Snapshot c50a8ad26a72432f26e39046d6a6f21fd7a190ee from idea/134.1160 of git://git.jetbrains.org/idea/community.git
c50a8ad: register missing tips & test
8a2b786: fix tests
0a8f4c2: WEB-10915 Limit on command for File Watchers?
60c1be3: IDEA-119721 License dialog to include JBA fields Async network activity, better layout, deferred success notification
0308187: NodeJS 132.1145 isn't compatible
d4f6c63: CR-IU-583 - accept ssh key as file always
376dbc6: CR-IU-583 - pass RemoteServer instead of ServerConfiguration to ServerType#createConnector
5b276d7: tipAndTrick EP
fe52778: continue js repl: left gutter — show prompt, align right gutter — right-aligned text, max 100 (trim middle) line separator — buggy and ugly yet
40b273b: cleanup
a10ab1e: Merge remote-tracking branch 'origin/master'
2cc672b: PY-12175 Extract superclass: import for existing super class is removed
5dbee39: introduced reformat directory dialog [CR-IC-4286]
52288f3: use new serializer for inspection
34d24bf: inspection moved (IDEA-120870)
005ff90: Merge branch 'diff'
7ebaa92: diff: add ToggleAutoScroll button to the merge window
721c137: diff: remember HighlightMode
786d70b: we restored broken API of ContainerUtil
d47bc1e: PY-12174 Extract superclass: untidy <br> tag in error message
621f555: PY-12171 Extract superclass: do not add objec base class with python 3 interpreters
7c1dd01: fake classes are not displayed as superclasses
f20e01f: PY-12170 Extract Superclass: breaks code when extracting fields not defined in __init__
d915b2e: Merge remote-tracking branch 'origin/master'
7f367e9: IDEA-80056 Column selection mode improvement
80fdfb2: Add build number to python plugin version.
f84a881: restore unstable API setAutoInitBreakpoints +review
262ff80: AbstractMethods copies docstrings
361f276: Merge remote-tracking branch 'origin/master'
da9c594: some more methods overridden to preserve List-Set contract
7a23b2c: disabling Pythonid 3.1, NodeJS 134.1081 / 1039 / 985, ruby 6.0.0.20140207
d9e54f2: IDEA-80056 Column selection mode improvement
408a5af: Merge remote-tracking branch 'origin/master'
4e39946: Fix dead-lock on components initialization (PY-12154).
feaed8b: IDEA-120823 Runnig TestNG test fails if using variable in POM in maven-surefire-plugin's configuration
66b1e0d: Allow to disable MavenJUnitPatcher via VM options (idea.maven.surefire.disable.*)
f89bc2a: restored backward binary compatibility
66a180f: avoid deadlock when somebody saturates the job thread pool with zillion locking tasks (especially for 2-cores cpus)
5e00ccf: IDEA-120518 Cannot create new Ruby on Rails application
d475a78: cleanup
80b93e2: capitalization
3734a6e: when a plugin depends on a module include classloader of the plugin containing the module to the parent classloaders
326ccf2: Merge remote-tracking branch 'origin/master'
4a5b8cb: Use unix path separators for helpers dir.
bc260c6: Merge remote-tracking branch 'origin/master'
895a305: do not add sdk in case it's already in interpreters table
daf6a18: test for http://crucible.labs.intellij.net/cru/CR-IC-4366
8d86965: Merge remote-tracking branch 'origin/master'
c2100be: fixed doubled sdks after apply for detected sdk
b3032ea: DEA-120811 compile-server process hung with 0 CPU
12dd76b: IDEA-120784 "Class is public should be declared in a file named <Classname>.java" for inner interface
ba7188d: Methods chains completion for arrays
68622f7: Merge remote-tracking branch 'origin/master'
6c53d3f: Merge remote-tracking branch 'origin/master'
71b92de: Methods chains completion merged with smart completion
60c9433: removed over logging, not informative messages from updater logger.
5681402: Merge remote-tracking branch 'origin/master'
d9c6cab: fixed import
24009db: IDEA-80056 Column selection mode improvement
080c3cc: Merge remote-tracking branch 'origin/master'
0be5b22: Merge branch 'pycharm-interpreters-rework'
6adb3a3: 'ruby' and 'python' modules included into Ruby/Python plugins to allow writing plugins for both RubyMine/PyCharm and IDEA with Ruby/Python plugin
8f808a1: IDEA-120609: Help pages available for 'library dialogs'
c7d283f: setup platform prefix for external system tests
bd1641c: fix PluginXmlFunctionalTest#testLanguageAttribute
0becd7e: EA-53969 - ISE: TextComponentEditor.getCaretModel
625185d: js console: annotated right gutter, show tooltips
27dea64: IDEA-120840 Bundled Maven 3.0.3 corrupts local maven repo on redirects Update embedded maven to 3.0.5
61b4874: IDEA-120840 Bundled Maven 3.0.3 corrupts local maven repo on redirects Update embedded maven to 3.0.5
f0320f8: unnecessary methods from HgVersion deleted; HgVcs used instead of project; IllegalArgumentException thrown instead if assertion
9ae90ef: make EnumeratorStringDescriptor thread-safe
d1bb7de: IDEA-80056 Column selection mode improvement
ea84716: IDEA-117734 Clipboard history no longer works by num hotkeys
d4757a7: IDEA-100755 Language injection: properties: prefix causes ISE at PropertyImplEscaper.decode()
4c300cd: EA-53558 - CCE: DatabaseVirtualFileSystem.dataSourceUpdated
9093d3f: Platform tests: do not change detected platform with initPlatformPrefix
f5c7ec3: Merge remote-tracking branch 'origin/master'
b32156d: PY-2858 Pull Up Abstract Method (finally!)
aa2a0c7: treat files with plain text file type that was detected from content as files with unknown file type
4ecac02: method to detect that file type was detected from content
c33e23a: use only 1 additional line for console editor (only JS REPL affected, platform will be discussed later)
51e0a7d: keep and deprecate old signature
e8f6414: not-null
32ceffc: keep and deprecate old signature
b8baeb5: move LanguageConsoleBuilder to appropriate package
e2bb599: remove unused import
ebe13e4: simplify BaseConsoleExecuteActionHandler — pass LanguageConsoleView (so, we don't need to hold it, and we don't need to fight — how to set LanguageConsoleView to handler (handler need to print))
9d12e62: cleanup
07cc8bd: use AsyncGenericProgramRunner +review
f7eb621: cleanup
a117497: deprecate MockCommandLineState +review
d9bfedf: lazy injector loading
2b4210a: avoid loading JavaPsiFacade for default project while decompiling class files
40f6fbe: PyArgumentList#addArgument fixed and test added
bb44a3d: put sdks to create new project interpreter combobox properly
c3defd1: Merge remote-tracking branch 'origin/master'
93d20bb: allow JavaFileManager in default project
5d767af: IDEA-120665 Custom file type identifiers should include underscores
279e8a1: remove unused PomJavaAspect
c67953e: don't add nulls to project sdks
c53564a: IDEA-80056 Column selection mode improvement
3bb055a: create nwe project with detected sdk, get rid of PythonSdkConfigurable, create fixed isDjangoInstalled in create new django project
6c0426f: diff: typo
c57dbf5: do call projectOpened callback in case of project exists but we want to create new on it's place
e3b3064: diff: pre-allocate memory for StringBuilders
c55ee26: diff: do not calc diff if there is nothing to compare
416e735: fix addAll implementation
4ba3dbb: better name
8ff3c33: JavaFileManager -> service
d93593a: allow compiler vfs changes to be watched in GroovyCompilerTest$IdeaMode
d861a3e: new project creation
5b60bc5: cleanup
73c644c: cleanup
9f1e375: IDEA-80056 Column selection mode improvement
e419749: fixed package list update + cleanup
b1f922e: Merge branch 'master' of git.labs.intellij.net:idea/community
27903b3: IDEA-120034 - Propose to upload SSH keys on connection problem - OpenShift
9cf2d8b: set min size for IDEA-114386 Width of Inject Language options
e2e52a0: JavaPsiFacade -> service
e45f74c: JavaFileManager: remove dead code, use volatile
3f43ec8: don't do smart highlighting stuff when live template settings editor is disposed together with the project (IDEA-120651)
687526b: removed debug field
f6ccd15: - indexing by unindexedfilefinder (root dependent cache updater) removes indexed file from filesToUpdate set - when removing outdated data reset file indexed attribute for later being able to index unindexedfilefinder (root dependent cache updater)
47c896c: avoid problem with concurrent clearing of timestamp cache between thread saving indexed attributes (e.g. indexer thread) and another one (e.g. flushing thread)
b011dc5: IDEA-80056 Column selection mode improvement
66379b1: write "singleton=<value>" if it was specified explicitly
4d50f3b: tests
b8a3e47: IDEA-120786 Log gets crowded with warnings while configuring JavaEE artifact
dc70440: Header and style added.
6a1809d: Absolute layout instead of GridBagLayout, area required for the message is taken into account, performance optimisations.
289b58c: filter duplicates
727c2da: initialize singleton to its default value
640165f: IDEA-100495 do not ignore invalid hg configuration
7dc4749: IDEA-118795 Gradle configuration with multiple artifacts not all reflected in IDEA module dependencies
e389e68: memory optimisation: spare ReentrantLock on each list allocation
4170df8: IDEA-110268 Lossy encoding: false positive for separated 0A/0D as UTF-8
9f6ada3: IDEA-119615 Find in path mixes "occurrences" and "usages" terminology
df15cf0: cleanup
3b8e3e1: do not exhaust limited job scheduling pool
2349f39: wrong level for class in wrong file
ac43ca6: EA-53926 - CCE: ScopeTreeViewPanel.getSelectedPsiElements
3c57658: EA-53874 - assert: PsiFileImpl.getStubTree
a2b51f6: IDEA-118795 Gradle configuration with multiple artifacts not all reflected in IDEA module dependencies
0c5ad97: wrong dependency removed
6c43236: diff: do not enumerate strings if we don't need it
d01ff56: diff: add comment
864bf0f: fixed bugs in implementation of "find k shortest paths" algorithm
bbe5c6c: Merge remote-tracking branch 'origin/master'
a1b2fb3: fixed updater tests.
bffd4de: cleanup
f0b2c3d: overrides
c804677: cleanup
b5aafd8: not-null
cec8a1e: cleanup
ed6b710: not-null
c90cd8e: IDEA-80056 Column selection mode improvement
c4b701b: Merge remote-tracking branch 'origin/master'
1678667: IDEA-120631 SOE fix
f7f2082: better insets and font for Win and Linux
2c11ffd: Revert https://github.com/JetBrains/intellij-community/pull/149 take 2.
b213dfd: com.intellij.index.IndexTest._testSkipUnknownFileTypes
4c87f76: fix GroovyDebuggerTest?
5cd8a05: IDEA-120738 Complete current statement creates broken code
4fb9534: don't apply single-line folding to methods exceeding the right margin (IDEA-120719)
2ba17e9: IDEA-120750 Fold single-statement methods into one line
b1d4696: IDEA-120694 collapsing one liners is overly eager
aef4cb8: IDEA-120726 Double "Press" word in hint when Find Usages
68b84ec: Merge remote-tracking branch 'origin/master'
6f1100e: Delete unused method.
65d6658: fixed build patches.
28903c8: Merge remote-tracking branch 'origin/master'
f4cf28b: Merge remote-tracking branch 'origin/master'
fd20dd8: improve stub-psi-mismatch diagnostic
f737684: IDEA-120094 New Project wizard: Maven project: use correct archetype +review
4274185: platform: default project name ping-ponging simplified
4a0c982: Fix failed tests
0e862f9: smart sync of pooled threads on start
0f1d210: fix two actions Pick Color
613e807: Merge branch 'master' of git.labs.intellij.net:idea/community
4b21ba6: IDEA-120034 - Propose to upload SSH keys on connection problems - runnable on existing server runtime task
b7025f7: IDEA-120480 (Invalid set of actions on enum's constants.)
7a16617: Partial fix for IDEA-117025 Eclipse code style import: Blank Lines: some categories are not applied
48c2261: Merge remote-tracking branch 'origin/master'
2a6f01c: dispose debugger thread dump consoles
8a99a3e: better control size management in fatal error dialog (IDEA-120304, IDEA-116542)
42bc794: junit 4.11 include hamcrest into redistribution
31aba54: new inference: choosing the most specific method inference
c8fb420: fix negative offset when injection is contained in parent
4820b2f: Code cleanup.
f9c35d6b: IDEA-120557 (Add an option to Inspection "Method can be variable arity method" to only apply to public methods.)
84a2242: MacMessages emulation using dialogs Initial load under ide.mac.message.sheets.java.emulation.dialogs registry key.
30a6ad1: Merge remote-tracking branch 'origin/master'
93e0abf: fixed NPE.
869ffee: Compilation fix
43f1fc2: Merge remote-tracking branch 'origin/master'
23a1f72: improved performance of logger operations.
937dbcf: CR-IA-225 use DefaultActionGroup
2c9bc0d: Merge remote-tracking branch 'origin/master'
57ed93c: Merge remote-tracking branch 'origin/master'
68bb982: Revert: https://github.com/JetBrains/intellij-community/pull/149 (a2301175e3628cae091eb4fd69cd5433c9dc730d)
a0aeafa: Merge remote-tracking branch 'origin/master'
40cb267: IDEA-119369 Indent statements after label treat label as a statement
e9d512c: check argument count
ff5872b: http://crucible.labs.intellij.net/cru/CR-IC-4264#c22278
165c965: IDEA-117794 in the message shown in "magnifier" view
0e53745: recursive FileIncludeManager.getIncludedFiles
193470c: add @TestDataFile
959eabb: [log] filters refactoring
4d6e648: clarify description
c76e367: IDEA-120623 (Add "org.mockito.InOrder" to the list of known classes for "JUnit test method without any assertions")
5674c5b: fixed growing list of listeners (forgotten remove)
677595a: optimization: avoid a call to contains()
8f1a176: IDEA-120661 prioritize bundles from project
14c6739: JavaPsiFacadeImpl: fix possible race condition
df03a06: project service seems a bit late a place to initialize stub element types
eeef876: IDEA-120661 spring: ResourceBundleMessageSource: support "/" as separator
bd3d065: IDEA-120717 The Gradle plugin ignores http.nonProxyHosts
ad3d62c: diff: add tests
f4f31e4: Merge remote-tracking branch 'origin/master'
a042b0a: updater changes: - removed dependency from util module - added new parameter - idea log dir - cleanup
048183c: removed unnecessary libs from cp for updater execution and added new parameter - idea log folder.
ff3f68f: removed updater dependency from util module.
6cab9a0: updater tests modified to support changes of initializing update logger.
b888b15: IDEA-120663 Log and History broken for mercurial 2.9
eb682eb: IDEA-120244 Native file dialog on "Install plugin from disk" disables ZIP files on OS X
59f8dbb: use proper configurable in configure interpreters link
8c3d81d: IDEA-80056 Column selection mode improvement
a91e90e: IDEA-80056 Column selection mode improvement
0a13f6c: console options always modified
80eaa69: isModified() fixed
9edcbfe: reverted SafeVarargs because of Oracle license restrictions
716977e: diff: fix patience algorithm
0383adf: fixed test data because of one less document loaded (see change 9464870 in SelfElementInfo)
87fd1d5: can't navigate to non-code usage sometimes
37fc695: Removed lock on cache evaluation - fixed dead-lock while reindex (PY-12034).
d6d0215: java: hanging file dropped
69b36ad: Cleanup (javadoc)
6e6e261: Cleanup (formatting)
b1558ae: potentional empty groovy psi elements bounded to left
5dab227: cleanup
3189a60: fix IEA
22e0438: don't suggest empty argument list as element to highlight
5bbc86a: Groovy: in-place introduce field from local variable without initializer
dfa7845: IDEA-120680: Breakpoints are not shown until indexing finished after IDE start
0e25de5: modificationCount++
eea4cf1: fire rootsChanged when adding a module using ModuleManager.loadModule
eb2683d: make MvcProjectWithoutLibraryNotificator read action cancellable
c7a7517: PostHighlightingPass: move service loading away from edt
6b0101c: less garbage in addDocumentListener
a51f225: diff: Patience diff algorithm
52ea261: diff: unify myMaxX/myMaxY values
c30c6c3: diff: prepare for recursive call of IntLCS
e38138c: diff: incapsulate LinkedDiffPaths logic
7478ad9: diff: allow to count LCS of subarray
ed6ff89: added detected sdks to create virtual env
aa98747: add detected sdk from details dialog
b3cae01: used proper sorting in details list
807a713: used setup sdk properly
700ee90: IDEA-119785 Inline local variable refactoring events
04ba3c7: MembersManagers now accepts PyMemberInfo (needed to get abstract and other info) (todo: doc)
1a437f5: selection fix
cb2cca7: CR-IC-4324 revert to NotNull, move new contract to PathUtil
3bce479: CR-IC-4324 not-null
1e174de: CR-IC-4324 not-null
114540b: CR-IC-4324 not-null
321eec0: overrides
48d6f4a: use both original and custom selectors to search for latest config to import #WEB-10964 fixed
fb03522: select in combobox interpreter selected in details
e5fe5df: LanguageConsoleImpl: use simple SingleAlarm Alarm - add flush method
9ab4e10: js repl: prepare: show clear error message on error
c16501b: PyMemberInfo is generic now
8c38db1: Merge remote-tracking branch 'origin/master'
5173b2f: Don't report exception about user-skeletons absence.
77ff70d: remove upused methods
aba8055: renamed PythonSdkDetailsDialog
dd5098d: reload python paths list
a65b69b: fixed create virtual environment
83a342e: trim whitespace more aggressively
712bff4: bring back download button when there's no patch
85e3e91: added simple implementation of PsiDocumentManager to 'core'
6942f6f: fixed uninstall action availability
5111f9d: proper reset in case sdk added
586a0e4: Overrides, ensure that start browser url is trimmed
0710931: don't perform costly root model comparison when it's loaded the first time
73c0a8e: decrease invocation counts a bit when doing path macro substitutions
60d1fa3: hide plugin searching task from user
945357a: IDEA-120600 Create Inner Class should create static inner class in qualifier class
06f7e3f: ensure nav bar adjustments take place (IDEA-120667)
2076c69: IDEA-120636 Wrong "enum cannot be instantiated"
aa96d2f: IDEA-120629 PluginManager doesn't handle dependencies for plugins specified with idea.load.plugins.id system property.
bee6616: No need in special extension for Dartium, configure Dartium in 'Dart' settings page, WEB-10460 Dartium browser startup options
a5bdd89: IDEA-120668 Gradle: Impossible to get Gradle classes resolved in guild.gradle file when project is not of Gradle type
7212836: Move to professional components that don't exist in community.
cc8318b: Better minimum size heuristic.
998d1fa: toSystemDependentName/toSystemIndependentName: "Contract" annotation improved
d78de12: don't overwrite workspace.xml file if it is corrupted (ZD-21210)
f9a8828: IDEA-120209 Resolve in jsp links to web resources from external .war file: tag dir support
c042f8e: Merge remote-tracking branch 'origin/master'
7ff5964: Merge remote-tracking branch 'origin/master'
738c43f: Merge remote-tracking branch 'origin/master'
4fdaa09: memory optimisation: do not leave stale data in cache
c1dac1b: isChromeRunning — detect Yandex and Opera (mac&win only!) BrowserLauncher — hide internal openOrBrowse browser configuration — respect FileUtilRt.toSystemDependentName/FileUtilRt.toSystemIndependentName policy
af067d7: Merge remote-tracking branch 'origin/master'
7e67fc9: IDEA-119606 Find in Path settings icon has issues
9b58556: annotated by SafeVarargs. The stub of SaveVarargs is put into util module for those old stumps clutching to their precious JDK1.6
b16df95: new inference: lift type parameters; stop inference after false appears in bounds
ea25e61: new inference: method ref constraint: take into account provided type arguments
a35cdbc: new inference: incorporation: allow self as parameterization
b203b5b: NPE
91a27d6: [log] Fix arrow ui.
445cf7f: IDEA-115442 Empty lines appear in the log when filtering by branch #IDEA-115442 Fixed
4a2d89c: [vcs] Pass service as extension parameter
baaaa88: Merge remote-tracking branch 'origin/master'
80a9635: fixed updater in according to the review recommendations.
96f6a67: update combobox on add local interpreter
9d89714: apply in case of detected sdk
ed7a6c3: Postfix completion: fix CCE
1805aa5: IDEA-120481 Ctrl+Alt+F7 cannot find usages in Selection
ca64418: IDEA-120542 "Find Usages" uses scope of last "Find in Path"
ebc8333: IDEA-114244 Find in path tooltip wrongly parses HTML entities
fec4fa9: jdk8 compilation
cb1eb74: made final
2067791: notnull
64ebe4f: notnull
9a85877: notnull
ccaada1: NPE fix
5df90d4: put detected vEnv in front of other detected vEnvs
d4e7730: PythonSdkDetailsStep renamed
08476e2: added focus to sdk list
0722673: NPE
47f9d56: added generate skeletons action
6776407: Merge remote-tracking branch 'origin/master'
82c40b6: fix compilation for java 8 (sic!)
a6926fe: Use ParametersList.addParametersString() instead of CommandLineTokenizer.
a34d392: IDEA-120642 Fix maven-surefire-plugin argList.
23c4184: + "portlet"
9356f0b: don't add already existed sdk
021c0c8: new inference: stop inference if false was inferred
b5e1b38: new inference: incorporation step: substitute equal bounds
84d7f65: initial version of show all/more actions
83d2858: do not suggest templates for ne module
950f9a5: Revert "no need in special extension for Dartium browser"
9c277e7: Gradle: add new module to community project
73f8bba: library editor: change tooltip for 'remove' button when an excluded entry is selected
a70d89c: prepositions list updated
4fab7c6: prepositions list sorted
a696706: library editor: updated icon for 'add to excluded' button and tooltips
8924e43: EA-53859 fixed
868e994: New decompiler API (crash proofness; stub logging verbosity level restored)
4692cb1: Diagnostic
7b4d26b: Merge remote-tracking branch 'origin/master'
1a10cd5: Merge remote-tracking branch 'origin/master'
18dea6c: Diagnostic
d262234: EA-46543 (cleanup)
4fb9316: PY-10963 Pushing methods down should add needed imports fixed
7b06ac4: WEB-10745 Dictionary returns confused type in TypeScript
2bf1fbc: don't use vfs in vfs events if old build isn't enabled at least for one project
42465b0: Merge remote-tracking branch 'origin/master'
9278320: schedule cache update in dumb mode when synchronizing roots or having large vfs change, to avoid stalls upon collecting files to update that can build vfs / update filetypr / filename indices (IDEA-109525)
c99aa93: method reference: ref qualified isExact fixed (IDEA-120370)
76846b7: debug logging for IDEA-120339 Type Hierarchy works only when the cursor is over a class name
bc2af62: faster getOriginalElement for source methods
dd3bdee: Merge remote-tracking branch 'origin/master'
25462fa: EA-46543 (stub reuse avoided)
374b215: New decompiler API (compatibility restored)
a230117: https://github.com/JetBrains/intellij-community/pull/149
1cea73f: IDEA-120626 UI / Colors & Fonts: "Lens mode" color not adjustable
9e83af7: IDEA-119859 Double Alt not working (Show tool window bars)
0a749fa: no need in special extension for Dartium browser
9a5f9fe: EA-53797 - CCE: ShiftUtils.getLogBaseTwo
bb66ffc: correct customizations (IDEA-120461)
211d532: IDEA-119903 IDEA should disable broken plugins automatically
581d2b7: IDEA-120586 @ParametersAreNonnullByDefault support broken
b189061: Problem With outdated HgRepository information when branch or bookmark created fixed.
76a3cc3: style
9bd5262: execute status widget update as soon as possible
14b3c35: Simplify HgStatusWidget
fe84874: IDEA-112737 Mercurial: hide closed branches
b1944c2: IDEA-119506 active Mercurial bookmark shown instead of a named branch in status bar
89cf188: Merge branch 'github'
df7da63: diff: codereview
19ee818: Replace TextRange with UnfairTextRange for relative coordinates
0dace45: Merge remote-tracking branch 'origin/master'
63c7b54: Initialize UI lazily in createComponent() to ensure that tree builder will be disposed, if it was created
77a4fd6: IDEA-120588 Gradle plugin broken with Gradle 1.12 dev builds
9466bd9: new inference: method refs: potentially compatible condition
dd66d26: new inference: generify
27ae864: new inference: method refs resolve: do not infer from void return type
1b17bec: new inference: method refs overload resolution compact
d38edf2: all sdks properly added to sdk combobox
1cf61ab: IDEA-120117 Rearrange entries is not idempotent (and misplaces static fields) [CR-IC-4226]
5d8f0b9: Move groovy importers to org.jetbrains.idea.maven.plugins.groovy package
bce543e: IDEA-119665 Memory leak in RemoteMavenServer when buildnumber plugin is used
34512ba: Gradle: data models implements Serializable added to retain out-of-process mode support
7ef6dd2: WEB-10929 Bower: Throwable on Uninstall package
d7f87c3: rollback. Selection is broken
8570ff1: listen to internal model for notifications
2ba5cc7: Gradle: fix gant scripts
fe6b753: PY-10963 Pushing methods down should add needed imports (test only added)
1485108: no space
b0e96de: IDEA-120588 Gradle plugin broken with Gradle 1.12 dev builds
d4b9fd4: WEB-10924 Bower: provide indication for loading description
ecc2479: Merge remote-tracking branch 'origin/master'
4e3b4a7: Fix "DummyHolder cannot be cast to com.jetbrains.python.psi.PyFile"
e78c7d7: fix problem when action is disabled in popup menu, but working from keyboard shortcut
a42e228: update runnerw configuration files to Visual Studio 13
d04ed7b: IDEA-120562 IntelliJ 13.0.2 does not respect Gradle IdeaModel Configuration
fc583db: IDEA-117674 please rebuild and commit runnerw.exe
038550f: get rid of make active for selected checkbox in create virtual env
fdf1dd4: IDEA-120591 Simplify new Flash module creation in 13.1
e59ab47: Cleanup (var names)
a582b91: New decompiler API (ability to call default decompiler from extensions)
c823858: do not log PCE
a6a8745: IDEA-120544 13.1 EAP (134.1007): impossible to add empty Web module to the project: update selection
9d349c8: cleanup
e7bd55b: show packages for detected sdk, fixed NPE if no interpreter selected
bd55771: 'Static Web' module type available in IntelliJ IDEA Community Edition (required for Dart support), see also IDEA-120593
0ccaddd: Add template text to live template quick doc
74fcddb: changes reverted
800eaba: IDEA-120544 13.1 EAP (134.1007): impossible to add empty Web module to the project
6d9052c: Gradle: add Gradle SDK sources before classes in a build classpath and retain the order
0072e05: testdata fixed
846cd83: second iteration for python project interpreters page
fd00ca6: new inference: method refs overload resolution: filter static problems for ReferenceType refs only
49a2d0a: new inference: do not infer based on wrong number type params
2b5764d: new inference: method references: process varargs
cb5a0b7: new inference: strict subtyping constraint: null processing
4889751: new inference: exclude return constraints/non pertinent to applicability argument constraints from overload resolution process
b9ef7b6: new inference: subtyping/equality constraints interoperability
a73a84f: Merge remote-tracking branch 'origin/master'
2daa625: fixed build of patches, and corrected updater dependency.
472e58b: Gradle: respect build classpath order and use both classes and sources jars if available
e4b9fea: 'com.intellij.modules.python' module included into Python plugin to allow writing plugins compatible with PyCharm and IDEA with Python plugin
e16e79f: 'com.intellij.modules.ruby' module included into Ruby plugin to allow writing plugins for both RubyMine and IDEA with Ruby plugin
344bf8b: IDEA-120265 Incorrect whitespaces (tab) painting when cursor change position
500f1b9: #WEB-10913 fixed
828b80f: Thread problems with updateTo action fixed
6c1effc: show "Loading ..." label on fetching installed package list
2a3f6b3: Refactoring to make PushDown use the same engine as other refactorings (documented)
dd6e05b: Merge remote-tracking branch 'origin/master'
735084d: Refactoring to make PushDown use the same engine as other refactorings (need to doc)
f6c6bec: New decompiler API
a281951: + "facelet"
5b8af7d: faster html tag selectioner using psi #IDEA-120533 fixed
750013c: parameter nullity annotation should have higher-priority than package-level ones
4757fc9: fixture-based NullableStuffInspectionTest
3104edd: respect default browser: jstd — use BrowserSelector
7c3e5b9: respect default browser
78b379e: StringUtil.splitByLinesKeepSeparators javadoc
132042f: Merge remote-tracking branch 'origin/master'
32aa1a8: Merge branch 'svn_18_3'
ea3cf29: IDEA-120535 SelectableChannel.register should have the same magic constants as SelectionKey.interestOps
ad661d9: correct level in highlighting: highlight element X only when visiting X or its ascendant
e0792ea: cleanup
9464870: optimisation: do not load document during smart pointer creation
78581c6: notnull
a0cc711: [git] amend: don't add \n to the commit message
340659b: svn: Refactored SvnUtil.getFileContents - reuse factory selection logic from SvnVcs
ec7edd3: Dispose tree builder in disposeUIResources() to prevent memory leak
f1ff831: Update message about unsupported JIRA version
840b6be: svn: Implemented command line support to logic that preserves changed svn properties during complex reverts - when package rename is reverted, but child files should not be reverted (child files are not not checked in dialog)
fbae010: spare some memory in vcs log
fdcdfce: WEB-1171 javascript live console
094e633: kill duplicates
7128707: IDEA-118234 Closure to SAM coercion: infer generic by SAM return type
ebffbc9: InheritanceUtil: some contracts
176b06d: mark setPassShellEnvironmentAsParent and isPassShellEnvironmentAsParent deprecated to wait for IDEA-118946
1c0199f: support actions history
7070677: mock groovy 2.3
b7569fa: IDEA-116775 Use idea home directory as working directory for "revert" operation (not to block current directory in case of reverting rename/move operations)
043c3e9: IDEA-120502 Support renamed gmaven-plugin plugin (groovy-maven-plugin)
b5d20bd: [git log] Fix multi-value filter by user
c823985: [log] can happen during log initialization while the table is empty
58c8791: Gradle: war artifact/facet creation fix.
5c74ffe: move js debugger platform up
353d557: IDEA-118646 Determine client factory for "revert" operation based on file being reverted (and not only based on project root and settings)
cb73b8d: IDEA-118222 Closure to SAM interface coercion doesn't handle contravariant types correctly
1c724d9: Merge remote-tracking branch 'origin/master'
d15b588: added openapi.jar as dependency for updater.
50eb71a: IDEA-95952 Debugger tooltip is shown in the incorrect place and overlaps annotation tooltip.
12c7874: Merge remote-tracking branch 'origin/master'
5767476: IDEA-120338 Create log for update to the same place where idea (idea based product) logs are located.
e53366b: Merge branch 'python-fixes'
dfa6f63: rename parameters
0b47cef: Disable StringLiteralQuotesAnnotator for multi-PSI files (PY-11658)
27d26d6: Apply visitor filters for all languages of the view provider (PY-11658)
711229d: Allow run indenting processor not only from the beginning of the file (PY-11658)
d7df2d4: svn: Implemented command line support for SingleCommittedListProvider
44e47f8: save RootIndex memory
d568223: IDEA-120528 Minimum size is not applied to VCS Log user filter popup
fbfc7d0: IDEA-120410 It's not possible to select old values of the variable via mouse
0caff04: IDEA-115128 Status bar: exception count font
8654ea3: select value in combobox on action
31f1665: ensure EDT
d8472bd: fix assertion — we must reset settings on family change
a5b9e92: Merge remote-tracking branch 'origin/master'
d68b3f5: fixed updater logger in accordance with the review's recomendations.
7f04cc2: svn: Refactored SingleCommittedListProvider - renames, removed duplication
27794a5: svn: Fixed SingleCommittedListProvider - use previous logic to check changes size and not just first item
5df8b8b: don't find local variable in extract method
d6c5296: Merge remote-tracking branch 'origin/master'
393fe4b: proper fix for PY-12052 Can't run django tests with nosetests because of `nose_utils` not found.
ec61769: less dependent on UnusedDeclarationInspection
42f69a2: notnull
261824e: moved to right package
1cf0b70: moved PostHighlightingPass to analysis
9d46ee9: cleanup
539ccf8: don't rely on SmartPOinterManager to load document
46fce02: IDEA-120265 Incorrect whitespaces (tab) painting when cursor change position
9c3260d: fix NPE
143c66b: EA-52671 - assert: AbstractMappingStrategy.processFoldRegion
37b45f0: Groovy: in-place introduce parameter: show parameters to remove in preview
ec8c847: Groovy: introduce parameter from local variable (both in-place and via dialog)
edfbd5e: Groovy: in-place introduce from variable always process all occurrences
f3a4b5f: Groovy: in-place introduce field from local var
48f76ae: EA-49782 - assert: TextRange.<init>
c2e137a: Groovy ControlFlowBuilder: additional logging
d9c547a: Groovy ControlFlowBuilder: make some fields final
a4a7cd5: cleanup default option searching
7318d5d: load installed packages in a background thread
3c4388c: Merge remote-tracking branch 'origin/master'
aac150d: Fix a typo (PY-12077).
05bb24e: WEB-10858 File Watchers plugin doesn't work http://youtrack.jetbrains.com/issue/WEB-10858#comment=27-672181
db734f3: this is mostly revert of my last year commit 101e4e4 from 27.03.13 because the change introduced deadlock (IDEA-118827) since clearing stub index needs write lock and we can have read lock already from processingStubs. The reverted change introduced better handling of index corruption: do clearIndex at checkRebuild directly. In current code we only advance index version from checkRebuild and proceed with clear index later on edt (with progress) as it was before.
83758fe: fix regress: invalidateIndices shouldn't schedule indexing for nonindexed files, many thanks for Peter.Gromov for help of finding the problem in review sessions
d516dd3: pull up: support static methods and interfaces for java 8
29b6eef: static methods in interfaces should not have abstract by default
f22cff3: presentation (IDEA-120353)
91b0fd7: invalid assertion for red code removed
a80cc8e: spi files: do not override std file types (IDEA-120291)
5358bd2: new inference: testdata for IDEA-120376
6cf7b4a: JavaFX Scene Builder integration
e54fc5b: JavaFX Scene Builder integration
a8237f5: hide embedded scene builder under "embed.scene.builder" property [https://javafx-jira.kenai.com/browse/RT-35745]
6efef68: new inference: method ref inference: postpone return type inference in case of constructor refs
5fb1dbb: new inference: check containing class type params if they are in bounds
3bda220: new inference: method ref inference cleanup
c0cbeb95: new inference: method constructor inference
8ab67db: new inference: method reference inference
5c8aa95: Cleanup (test)
94f05f9: gwt code server run on module A. A inherits module B. Our current file belongs to module B.
7084660: It is safe now to deprecate launchBrowser
613c3be: move impl to BrowserLauncher
ac8d9f5: move UrlOpener to platform-api
9823767: prepare to move UrlOpener to platform-api
aecf185: prepare to move UrlOpener to platform-api
1bce665: extract WebBrowserBase
ddd555f: extract WebBrowserBase
a689252: update since-build
ab3c292: remove deprecated BrowsersConfiguration
4389b66: move BrowserFamily to upper level
e7200d5: cleanup
3395850: continue: add "Fix" button — open web browser settings
4c2d519: continue: add "Fix" button — open web browser settings
a775355: extract button.fix resource
5054ae0: show message — pass project
08cf6b3: Merge remote-tracking branch 'origin/master'
f41d2be: Merge remote-tracking branch 'origin/master'
39bf620: remove redundant check on import (we'll check on creating suite)
b0f4997: IDEA-91883 Edit breakpoint dialog: cannot click on combo if it expands out of the popup border
503440c: IDEA-13489 background tasks window should have a minimum size
ad2647f: don't highlight the entire expression and add test
0859e0e: don't highlight the entire expression and add test
f761ceb: better warning message & more tests
bbfa3ce: don't highlight the entire expression
6820fe5: added options for the details button
651545e: Bomb maven tests
ab01855: Python plugin for IDEA 13.1 EAP.
e914322: Logo updated: 'Tools matter' moved.
89bffcd: PyCharm 3.1 artwork
03171ce: fix typo
306f284: Merge remote-tracking branch 'origin/master'
669cff7: Cython and Python parsers should never create functions with out of statements even if code is bad
49a4da3: test fixed
bbe8aaa: hotfix: IDEA-119851 Gradle: the "out-of-process" mode doesn't work (cherry picked from commit 83fe636)
366f1e9: IDEA-118917 Gradle: multiple war artifact configuration issue
4c31d6d: Move PlainTextParserDefinition to core-impl
6164b56: Bug fix: embedderJdk is not saved between restart of IDEA
cc5c729: WEB-10894: increase the width of surround with Emmet popup
188dbc7: WEB-10894: increase the width of surround with Emmet popup
d97ccc0: Support java 1.8
a1378e8: EA-49128 if project already disposed return default charset
89bdb11: Fix maven test add groups "org.codehaus.plexus" and "intellij.test"
7eb0d93: gson version added
4e65421: be ready for large keys: DataOutputStream.writeUTF schokes on strings larger than 0xFFFF
90acbc8: Scala 0.32.512 and Php 133.679 marked as incompatible
c003973: - forceUpdate also process limited number of files out of current scope (e.g. worspace.xml and source filter) in order to keep myFilesToUpdate empty.
b35e1d9: Merge remote-tracking branch 'origin/master'
9506a68: Merge remote-tracking branch 'origin/master'
60cd07e: NPE fix
a080b75: new inference: apply non-wildcard parameterization for method refs
8cfcf78: 'show serialized xml' action: fixed instantiation of bean class
a216d7d: paint about info text a bit lower
0d7e21c: update AppInfo for EAP
8aa0248: new community about screen for EAP
5839250: new community logo for EAP
23caa08: Merge remote-tracking branch 'origin/master'
af3f020: Don't change commandLine.exePath in RemoteSdkUtil.
cae527f: java: do not infer expression type and value for decompilation into text
346252d: fix groovy test
43f6124: Merge remote-tracking branch 'origin/master'
f6e061c: cosmetics
c0c4908: platform: file scope made tolerant to default project
205ae95: Logging
f5b2821: Merge remote-tracking branch 'origin/master'
a6cb307: IDEA-119372 Search results tree "looses" items while scrolling
a82d1cd: IDEA-119721 License dialog to include JBA fields
deb294e: workaround for log user filter if select ME value
80dedd3: svn: Refactored SvnCommittedChangesProvider - SingleCommittedListProvider extracted to separate class
a0363cb: svn: Refactored SvnCommittedChangesProvider.getOneList - logic extracted to separate inner class
9a7568e: IDEA-120385 'Generate Test method' doesn't work
18d0ee6: method refs: separate inference from conflict resolution (to be continued)
ff66c1b: new inference: well formed check
d24e983: new inference: non-wildcard parameterization
865a535: new inference: wildcard parameterization inference
dd1c5d9: new inference: incorporation of capture constraint: captured wildcard treatment
10d4a51: new inference: incorporation of capture constraint
0bb6aa5: new inference: different parameterizations condition/wildcards parameterization in return type covered
26d23a9: svn: Refactored SvnCommittedChangesProvider.getOneList - simplify parameters detection (use already existing objects instead of executing svn commands again)
88910bd: optimize class in package search
bf547fd: live templates should be at the bottom of the completion list
c8afa74: add PlainTextFileType registration
9636378: reverted "move FileTypeFactory to core-*": jps-model modules must not depend on core modules
0cdea4e: show error if we cannot launch browser add "Fix" button — open web browser settings
e80c761: cleanup
3787e1e: added proper tooltip for install/uninstall buttons
8b6e62b: Merge remote-tracking branch 'origin/master'
057c5f3: initial python project interpreters page
e34c407: Merge remote-tracking branch 'origin/master'
2f65c96: Python function parsing fixed: any function has statement list now
e8d0cbb: Merge branch 'check-physical-in-go-to-class' of https://github.com/niktrop/intellij-community into niktrop-check-physical-in-go-to-class
3fd5b8e: don't suggest lowercase non-imported classes in autopopup (IDEA-114348)
ab8284b: actually cache GrModifierListImpl.getAnnotations
7fd991d: fixed python community icon-robots.txt
6f783fe: fixed PY-12052 Can't run django tests with nosetests because of `nose_utils` not found.
be252b2: Merge remote-tracking branch 'origin/master'
24c879c: Code cleanup for "membersManager" package to make it type-safe
486a608: svn: Removed unnecessary LocationDetector and accompanying logic
53e055f: Looks like a typo.
df9c434: external build: save list of GWT modules to file before compilation to avoid scanning source roots in external build process (ZD-19763)
b467cbe: javadoc added
9d4fa47: avoid NPEs in breakpoint dialog
d57662b: support filters in breakpoint adapter
feced99: svn: Removed unnecessary SvnLoadingRepositoryLocation
c07a129: don't add duplicate patterns
0cf2990: IDEA-97800 Groovy: remove annotation quick fix
5383da8: Groovy: 'implement interface' intention should work with generic classes
927951a: Groovy: red code in plugin.xml
d9fb514: Add custom templates to completion list if corresponding Registry-key is enabled
f00e6c6: Zen coding: do not commit while checking availability
0c9d76e: svn: Refactored SvnCommittedChangesProvider.getOneList - simplify code flow
ead776d: move FileTypeFactory to core-*
f6ec6b8: formatting
7eb4cd3: Add empty panel shown when no certificate is selected like in TaskRepositoriesConfigurable. Tree builder is correctly reinitialized in reset(). Change grow policy of warning message in form.
3323ed4: [log] IDEA-117248 Fix multiline subject message rendering
0441a53: showInBestPositionFor editor
f26bec3: enable required dependencies
f826ab8: Slightly update logic of getCertificates in trust manager
3357209: cleanup, prepare to fix WEB-9756 Quick evaluate expression popup: long values are cut and cannot be copy correctly
cd527f0: cleanup, prepare to fix WEB-9756 Quick evaluate expression popup: long values are cut and cannot be copy correctly
882965b: inter-framework dependencies
8669a75: Arrangement tokens creation patch.
294cccf: webpack
fb04460: don't highlight the entire expression
d712dda: cleanup and test
a2dd182: move utility method to it's only usage and add test
38f7944: 'commonjs' and 'webpark' added
802a696: [log] IDEA-120178 Check if branch exists before querying Git or Hg
6919265: IDEA-117727 Gradle web project correctly apply 'WebGradle' web facet but detects another web facet - which is the same - as 'Web'
d5b9d47: Merge branch 'master' of git.labs.intellij.net:idea/community
ce3a156: IDEA-120391 - Support OpenShift debug
2c5e6cd: better way to determine if class is a concrete collection class
0654ba5: Cleanup (formatting)
ccfd1f8: IDEA-120226 ("Class explicitly extends a Collection" inspection should be suppressed when overriding removeEldestEntry() from class LinkedHashMap)
6200195: split DuplicatesProfile into index part and presentation part introduce duplicates-analysis-* modules independent on platform-* or lang-* modules, suitable for Upsource
4463280: cleanup duplicates
261aeb6: jdk8 compilation
c78401f: gson library version updated to 2.2.4
0d514da: style: unnecessary conditions and expressions simplified
c5f9c1f: cosmetic for VcsRoot tests
f1726af: Merge remote-tracking branch 'origin/master'
80b77c9: Missing tops images (PY-11794).
f3d0abb: refactoring: types refined
ee84db9: "create project from existing sources" fixed for mixed non-java projects (IDEA-91446)
44d1eb2: new inference: incorporation upper bounds case added
0d9ea1f: no frameworks for empty project type
7eea76a: [git-log] escape backslashes (otherwise git doesn't like it)
6b6f14b: [vcs] more correct commit successful notification: "changes" -> "files"
fc2b716: NotNull
76bfc1f: "create project from existing sources" fixed for mixed non-java projects (IDEA-91446)
8abb5a0: refactor GrAssignabilityCheckInspection
f0f09c7: NPE
4f3ad93: binary operators with number types are correct
9efb2cd: IDEA-120237 IAE at com.intellij.ide.plugins.PluginTable$2.setSortKeys
7b058f4: proper border for description panel
a38b53a: button colors for Darcula
4c780db: set shared flag when toByteArray is called and if it is set then copy byte buffer on write
0922b72: - forceUpdate also process limited number of files out of current project in order to keep myFilesToUpdate empty. The files in question can be from other project or excluded from current one or even from user home directory (as by product of building vfs / watching it and broadcasting vfs events to listeners) - indexFileContent skips processing contentless indices: they should be processed during building files to index or during vfs events processing
bf1cada: svn: Refactored SvnCommittedChangesProvider - inner classes moved to separate files and renamed
0a1c3bb: svn: Refactored SvnCommittedChangesProvider - method extractions, simplifications
29ec204: Merge remote-tracking branch 'origin/master'
47d2598: Accepted certificates are shown in tree, grouped by organization name, like in browsers. Not valid certificates look strikeout.
90e4f29: svn: Refactored SvnCommittedChangesProvider - simplified progress indicator updating
f89e476: Merge remote-tracking branch 'origin/master'
1132b19: Use correct option for saving files on switching to terminal (IDEA-118846).
7d228d5: warn when only difference is @Override annotation
86b18ce: IDEA-120272 New Project wizard: java templates (JavaFX application, Command Line Application) are missing
61e3b94: IDEA-120343 Gradle: custom title for gradle files in editors
bd2fcae: CR-IA-226 ImportFilter: make targetFile parameter not null
06fb88c: IDEA-120272 New Project wizard: java templates (JavaFX application, Command Line Application) are missing
58da780: Update auxiliary ShowCertificateAction to take first certificate from storage, change note at the bottom of dialog
dba7e9a: lock-free FileBasedIndexImpl.myTransactionMap
55ef9c2: don't show extra information in case of 3rd party repos
3695846: svn: Refactored SvnCommittedChangesProvider - removed duplication in repository root detection logic
9940cf1: IDEA-80056 Column selection mode improvement
ef010fe: IDEA-80056 Column selection mode improvement
76283b3: IDEA-80056 Column selection mode improvement
9f107c8: IDEA-80056 Column selection mode improvement
d1106d7: svn: Refactored SvnHistoryProvider - reuse repository root detection logic from SvnUtil
bdcc096: ensure selection exists after repo change
1ee1f54: better fix for 3rd party repos
e3bd2bb: svn: Refactored RepositoryBrowserDialog - code simplifications
4047f29: fixed adjust range for list children renderer
0092f5c: fix integration with private repos
ce976f3: fix NPE
8be18c0: new inference: accept parameter bounds on return step
b70b27c: new inference: do not fall down to raw types
d1e99e2: svn: Fixed revisions loading in tree conflict panel for tree conflicts with "incoming delete" to use common ClientFactory model
6f42f9c: svn: Explicitly specify "limit=1" when retrieving history for tree conflict panel (instead of throwing cancel exception)
b2eec46: Merge remote-tracking branch 'origin/master'
dd7661a: IDEA-117841 Make launcher reflect the true product
d10a98e: Remove ComparisonUtils duplication
37ea597: qualify with all containing classes not just the first one
cf46311: svn: Fixed revisions loading in tree conflict panel for tree conflicts with "incoming delete"
d72179f: svn: Refactored TreeConflictRefreshablePanel - commented code removed, simplifications
252e5f8: Gradle: log level for gradle execution error trace changed to debug
2c2b8f7: avoid costly PsiElement#findReferenceAt when element is null||PsiWhiteSpace
16d78e2: IDEA-116285 XDebugger API based java line breakpoints: implement class filters
64dd67f: create project from existing sources: refactored and tests added
cd2d984: use natural ordering for nodes in Project Structure dialog
ae32dbb: updater tests and test data moved to 'updater' module
bc90ef4: fixed paths to updater log files
1962ba6: cleanup
8a0eaa0: don't forget about closure args
823614d: complete extends, implements
ce14ee7: IDEA-120232 Groovy: Extracting string literal part: check for escape symbols
b74503d: Refactor reference expression parsing. Fix 'literal'\n{} case
9eb6611: IDEA-116997 Check binary operator applicability
8fb5deb: add new modules to community modules.xml also
6218043: don't warn on new expression's of non-static inner classes
f3192b0: move nested class to where it's used
b0c5cbe: WEB-10821 Weird character in Alt+F1 menu before "Open in browser..."
329845b: IDEA-99123 Fixed latest revision detection logic for "Update/Switch to specific revision" dialog to use "svn info" command (instead of SVNRepository api from SVNKit)
1ba9675: Merge branch 'python-fixes'
2543454: Fixed parsing of invalid Unicode code points in literals (PY-12012)
eee22a3: IDEA-99123 Fixed "Update/Switch to specific revision" dialog not to always use SVNKit implementation
20f8ef4: svn: Refactored SvnLogUtil - methods extracted, inlined
4e2db64: IDEA-99123 Fixed "switch" operation for svn 1.7 working copies not to always use SVNKit implementation (now common client factory selection logic is used for update and switch operations)
2a700e0: test for wrong version parsing added (IDEA-112316)
772d5f4: save history values (initial)
4513345: PHP WI-22023 Local History For Function is not available
5270ee9: fixed stackoverflow in breakpoints dialog
2ee8cc2: Merge remote-tracking branch 'origin/master'
e0b32c9: Install CollectionListModel by default, listener method act only in EDT
906efb7: cache classes and files in console exception filter
0898580: IDEA-120280 Exception in completion
9c67ca6: java completion: make recursion weigher less important than by-kind, because now it can lead to very unexpected sorting
528f460: Merge remote-tracking branch 'origin/master'
ba11e80: IDEA-120217 same lambda param names highlighting
b6cb00a: new inference: collect additional constraints by call arguments [todo]
487c78e: new inference: propagate inference variables from grand ~parents calls
2c85d0f: new inference: decide about NULL type later (JDK-8033407)
32502b5: IDEA-119704 Disable "Unlinked Gradle project?" dialog doesn't work on OSX
be43eec: IDEA-118581 diff: remove files duplication in ChangesTreeList
062dfe6: diff: codereview
01660d6: Fix maven test
6b3a0a4: don't paint table busy if there are no installed plugins
3d0b01a: Merge remote-tracking branch 'origin/master'
8a80544: IDEA-115711 When open tab limit is exceeded IDEA dosn't close the less frequently used tab but the most frequently used tab instead
11ae1b1: separate editor tab closing logic from actual closing
fb685aa: GroovyDebuggerClassFilterProvider: cleanup
6fb03c5: Restore factory with default with least priority; remember if user chooses factory by himself
f0ed128: Prefer custom code fragment factory on context change
abb3e62: Fix maven test.
62395fe: Gradle: tooling lib version updated in libLicenses.gant
c304982: gradle-reporting-1.9.jar removed from gradle module
30292ae: Gradle: introduce gradle-tooling-extensions modules with respective classpath; expose scala project configuration for ProjectDataService usage
214cf08: Gradle: introduce gradle-tooling-extensions modules with respective classpath; expose scala project configuration for ProjectDataService usage
734f659: Improvement for MacMessages rollback. MacMessages have been handled in Messages class but they are used directly from the MessageDialogBuilder.
01fdfd4: custom wizard step for gradle and maven
fc1469b: Fix test-data.
c2d5819: Fix Grails test: "Create variable" quick fix is not present in GSP. +review CR-IU
f0ffa4f: Don't wrap before dot (PY-5464).
f0e55e9: IDEA-119246 Flex: Jump to find result broken from CTRL-ALT-F7 dialog
078dbd9: IDEA-119180 Groovy .gdsl editing support is broken in Intellij IDEA 13
32b846b: optimisation
3529094: Get rid of grandparent for alignment.
75e5f3c: IDEA-120245: Mark directory as "Generated Sources" is not available in plugin project
62476fa: Fix alignment in list comprehension in dict (PY-10076).
e8fd0a0: add new module from project structure
6ed5541: Add broken plugins
0584de3: external build classpath: try decapitalize plugin name to find plugin dir (e.g. for Osmorc plugin) under case-sensitive OS
ee833f1: windows error code check fixed
6dd77e9: Merge remote-tracking branch 'origin/master'
8cca960: new inference: target type detection according to consequence inference (IDEA-120193)
6e7ba09: Merge remote-tracking branch 'origin/master'
834e582: Merge remote-tracking branch 'origin/master'
36aae7d: Merge remote-tracking branch 'origin/master'
955663a: PY-3450 Refactoring: pull up class variables/attributes (almost done: need to check dependencies, resolve conflicts and use same functionality for "extract superclass" and "pushdown")
05a631b: remove template placeholder from description
5294ae1: Merge remote-tracking branch 'origin/master'
5081222: remove unused PluginModuleType#ADD_PLUGIN_MODULE_ICON
1adfc8f: use PluginModuleType.isOfType
ee3168a: DevKit: (re-)use DOM in DescriptorUtil
e4f8eaf: Don't wrap at the start of string literal (PY-9436).
594f81b: PY-3450 Refactoring: pull up class variables/attributes: Refactoring and wrongly formatted code does not lead to exceptions in pull-up method anymore
ed67544: do not suggest @FunctionalInterface for interfaces with generics methods
17853f2: th should not close th in previous row
3ede82b: Fixed text range in pre-format processor.
9993883: Fix a typo.
12d1184: NotNull
34826b2: new inference: introduce "thrown" bound
ef15e60: new inference: lambda compatibility: ground type constraint added
11f8200: new inference: ignore self eq bounds
9cf6781: new inference: skip constraints which won't produce anything: proper return type for lambda
21fe45f: invalid @FunctionalInterface severity change warning -> error (IDEA-120162)
b268a7f: revert (IDEA-120153)
0e875b2: new inference: primitive types processing: ignore eq constraint by the spec
5b40000: updated path to log4j.jar for executing Updater.
5dfb607: Merge remote-tracking branch 'origin/master'
6d8e028: PY-3450 Refactoring: pull up class variables/attributes: Refactoring + compilation fix
b7837167: IDEA-117777 Change the way native splashscreen is shown in WinLauncher IDEA-117163 Parameter "nosplash" is broken on launcher
3e21a1f: Fix test data for PEP8.
4896ad4: Fix tests returning correct text range from pre-format processor.
b803597: Merge remote-tracking branch 'origin/master'
7ae9d1d: PY-3450 Refactoring: pull up class variables/attributes: Fixed, but refactoring is required.
5609596: Merge branch 'python-fixes'
17d36f3: Fixed potential NPE
c1e515e: [git] Don't read default commit message from .COMMIT_EDITMSG
79e3da5: Infer 'Iterable' as the type of tuples as default parameter values (PY-10967)
20a4f26: fix "Invalid file"
a6dcd8c: cleanup
94b3989: background of editorpane should be white
e67783c: 'properties' plugin layout should respect 'pluginFilter' (fixes failed WebStorm builds)
6981f2d: Merge remote-tracking branch 'origin/master'
6ee3e2b: Refactoring (membersManager package introduced) to make PY-3450 Refactoring: pull up class variables/attributes easier
f4433d4: Check that item is in list model before addition/removal by event
8a8aeaa: cleanup
bb497d3: added test for 'null' values in @Attribute
a1ce98f: diff: Add option to reduce diff granularity and to turn diff highlighting off.
d30c09e: IDEA-56098 diff: add ability to disable autoscroll
ec1afef: diff: add DumbAware to the inner action too
1384b9c: diff: Add separator after 'IgnoreWhitespaces' action on toolbar
193105e: IDEA-120145 New Project wizard: when for Java Enterprise or Spring type 'create by template' option is selected the chosen technologies are ignored, jars are downloaded to wrong place
7548b57: EA-53622 - IAE: ContextComputationProcessor.getTopLevelInjectionTarget
3ef4f28: cleanup: http://crucible.labs.intellij.net/cru/CR-IC-4132#c21654
e66493f: javadoc added
c49c45f: move agreement dialog to platform-api
c8dda3a: Remove previous generic version of Gitlab connector
3b73d78: IDEA-119508 pass context PsiFile to ImportFilter
c103300: IDEA-120224 Add possibility to customize ConsoleView popup actions
9eae975: JavaFX Scene Builder integration
a153738: Fix test data to satisfy PEP8
f0facb3: jdk8 compilation
6e01cbc: moved to analysis
42ee4dc: cleanup
ba80bec: memleak
5898e76: fixed PY-11916 PyCharm nose helper causes DeprecationWarning
e96a71e: Merge remote-tracking branch 'origin/master'
fdaa217: do not prefer simple python run configuration over tests
ee800d4: JavaFX Scene Builder integration
5e496d0: Merge remote-tracking branch 'origin/master'
1cb0753: do not prefer simple python run configuration over custom (django, etc.)
90a5c56: Merge branch 'python-fixes'
7bd76e8: Reverted percent formatting by default for MySQL parser compatibility with Python (PY-10771)
acdc335: root detection call optimized for empty root checkers
65bce6c: unnecessary 'else' removed
fa2e577: Capitalize property for dialog
9403845: style
321cebb: style
b9e6494: Setting for space before # (PY-8273).
1097ad6: IDEA-120134 align ? and : of ternary operator
6aaf437: Space after '#' according to PEP8 (PY-11571).
6ec28ac: duplicates
0e3104e: introduce parameter from expression with null type
d50f621: IDEA-118325 honor "maximum blank lines" setting
930f90e: use json representation of bower commands
d4ff7e2: IDEA-119415 (Inspection for Static field/method referenced via subclass should ignore fields/methods in non accessible base class.)
1c30543: Mark NodeJS:134.680 as broken.
b100ad6: Don't use JSON to store broken plugins list. Parsing of JSON take a lot of time on startup.
1261469: Mark NodeJS:134.680 as broken.
cca607e: Revert bad commit
689dd6b: Don't forget to close ZipFile.
ebf4294: Fill brokenPlugins.json
27047db: IDEA-120161 ("Interface may be annotated @FunctionalInterface" inspection)
20f6fd6: move to "Inheritance issues" category
aa93c1b: Update brokenPlugins.json
18790ff: Fix broken API. Add old method to repair PHP plugin.
7a2a46d: Github: do not show error while testing credentials on operation cancel
2a694d8: Github: add TwoFactor detection
1635c6f: Github: fix tests
50a0f3d: Github: fix inspection warnings
9f6e257: Github: allow to create access token from settings
61b03df: @NotNull
72a613a: Github: do not show error for untrusted certificates
d955158: Github: do not fail without access to account data
6d4c366: Github: add API function
6a7e1a6: Github: wrap testConnection to modal progress
597982b: Github: remove GithubSslSupport
3287d5d: revive NewElementSamePlace action
32b9577: JavaFX Scene Builder integration
86bb6f4: Merge remote-tracking branch 'origin/master'
89d2ebc: invocation type inference: when unchecked conversion was performed - treat its results in return value checks as they were in bounds
dc65257: JavaFX Scene Builder integration
125d832: fix thread access violations
be84252: type equality constraint: reject type/wildcard pairs; subtyping constraint: become eq constraint for types
948e76a: separate subtyping constraints
f26b803: type compatibility constrain: unchecked conversion: return type is inference variable case
5a9c00a: type compatibility constrain: unchecked conversion step
af8095f: type compatibility constrain: boxing is not completeness-preserving: move treatment to return constraint
4444fc1: type equality constraint: accept unbounded/extends wildcards pair; reject unbounded/super
2070864: test to choose overloaded method to detect target type
09437d8: new UI for plugins
7f5bcec: Code cleanup after CR-IC-4191
c6d5377: CE compilation fixed
7864194: Properties language psi api extracted for upsource
de32aab: IDEA-120028 Groovy: "Optimize imports": static keyword is removed from unresolved imports
5fcedc1: select a literal if its whole content is selected but quotes are skipped
222509a: Groovy: introduce refactorings: check range inside string literal
8f505bf: Merge remote-tracking branch 'origin/master'
13ce8bc: Add listeners support, update extraction of fields from principal's name
87187b1: Fix error related to disappearing certificates by changing alias construction
87b442b: Always ask about untrusted certificates, in particular when default trust store is missing on Mac
df23197: Fix locking in ConfirmingTrustManager, simplify error checks.
3ebc299: CR-IC-4179 (cleanup)
6287268: cleanup after review
41a6fe5: IDEA-117389 Groovy: Introduce refactorings from dollar-slashy strings/regexs
5331b63: Yep! Implement yet another stupid workaround https://code.google.com/p/v8/issues/detail?id=2825 It seems it is really works :) WEB-8174 Node.js debugging problem
13fd492: add support if only frameworks selected
d3f57de: fix loading from jar file
f325ac8: #WEB-5170 fixed
2a159c3: Groovy: in-place introduce constant from local var reference: don't suggest replace all/only one occurrences options
cee821f: Groovy: in-place introduce constant from local var reference
3d07be5: Groovy: in-place introduce constant from local var declaration
25d5d2e: Groovy: in-place introduce field from reference to local var
fa3a51c: Groovy: in-place introduce field from local var
c3b1957: Cleanup (formatting; typos)
3020665: platform: recover after interrupted extension loading
3676ab3: Delete disabled new-template
5456a95: Rollback showing MacMessage if we cannot find an appropriate native parent. MacMessages are enabled for multiple dialog hierarchy.
a18ac62: MacMessages should be disabled for jdk8 until resolution of jdk8 issues.
9747976: Merge branch 'python-fixes'
0c8e03f: Fixed add method quick fix after changing the element reported by the unresolved references inspection
a1e95ef: IDEA-70915 (inspection: implicit usage of platform default charset)
b3b145d: IDEA-116116 New Project Wizard: default folder for jars download is /lib
5a27ed3: fix table rows parsing in case row count is more than 2 #WEB-2414 fixed
10758ff: autoclose thead with tbody #WEB-2411 fixed
e136bf6: #WEB-2359 fixed
1ff8ae8: fill in empty tags from R# schema #WEB-6626 fixed
f485ada: TransferToEDTQueue.createRunnableMerger
6281d32: merge some java completion weighers into PreferByKindWeigher
c491893: support non-jetbrains notnull annotations in equals/hashCode generator (IDEA-120036)
7feba9e: Merge remote-tracking branch 'origin/master'
35603ff: Kill Python console with SIGKILL, because SIGINT generates KeyboardInterrupt and closes nothing.
6f94942: Add diagnostic attachments for commit document assertion
e0fbc63: resolve names conflicts inside lambda body (IDEA-120096)
876784b: wildcard bounds composition (IDEA-113297)
f0bfe36: forbid forward references from lambda again (IDEA-119936)
704285a: method refs constraint (IDEA-118437)
dab66b5: Add diagnostic attachments for commit document assertion
330f52b: Gradle: Module builder updated.
be3418b: Add indication that certificate expired or not yet valid in configurable and certificate info panel
b3be019: Rename CertificateInfo to CertificateInfoPanel. It no longer uses form editor
cbdda5d: Slightly refactor hostname verifier, add check of CertificatesManager 'checkHostname' option
ebd0cba: Merge remote-tracking branch 'origin/master'
dc46fec: Merge remote-tracking branch 'origin/master'
112e784: Merge remote-tracking branch 'origin/master'
8bf273f: NotNull annotation.
2afeaf5: Fixed EA-52685 - assert: MultiHostRegistrarImpl.doneInjecting
c7346ee: Annotations for Paths, Files and Channels
aab7556: Merge remote-tracking branch 'origin/master'
2db0f1e: custom steps are back
8204f64: NotNull annotation.
b5c312d: chronon class filters requires dot as delimiter
a6583ab: Merge remote-tracking branch 'origin/master'
154bc88: IDEA-119366 Reformatting only VCS changed code produces unwanted side-effect [CR-IC-4175]
f276863: skinny doesn't work in most of the cases
5f2c78e: NPE (EA-52843)
fe79cc4: project type sorting fixed
35afccf: Reordered methods
f27ab12: Gradle: code cleanup
789eb57: Merge remote-tracking branch 'origin/master'
2ca9e60: Formatter & Scanner annotations
58ba880: FileInputStream, FileReader, FileWriter, InputStreamReader, OutputStream, PrintStream & PrintWriter annotations
d258c37: String.format annotation
5a75778: VcsRootDetectorI renamed
77af356: VcsRootDetector refactoring
ec25543: ChooseTemplateStep
2e82518: EA-49160
da0b420: WEB-10797 nodejs: strange exit code
5b436cc: StringUtil.splitByLinesKeepSeparators
43fc3e2: IDEA-120051 Maven Project ignores profile-specific dependencies
b44000d: NPE(EA-52907).
1ac0a95: IOOBE (EA-53138).
8e887d7: SIOOBE(EA-53677).
39a3ef5: EA-47815
c1728ca: IDEA-56096 Allow to create file templates with extension contains dot [CR-IC-3923]
e507a6f: spase within spread operator
4248fd8: [git] Fix NPE if process is not started
52db790: [log] Don't join if there is only one repository
619f11c: new project wizard: frameworks on the first page
3bffb58: Build fix
f4c8a46: 'cast parameter' fix if spread operator used
8ed8c4c: remove duplicate
a7bab7d: cleanup
b55ff2d: EA-51997 - CCE: GroovyAnnotator.registerMakeAbstractMethodNotAbstractFix
926fbff: EA-52115 - IAE: ResolveUtil.processNonCodeMembers & some @NotNull
430fc9a: EA-52506 - NPE: TypeConversionUtil$WildcardDetector.visitClassType
884380a: EA-52532 - CCE: GroovyCreateFieldFromUsageHelper.setupTemplateImpl
36c07d3: EA-52789 - diagnistics
8555cde: duplicates
8fc0687: EA-53288 - cast fixes.
be3da4b: EA-53309 - CCE: GrInplaceFieldIntroducer.checkLocalScope
935bc3d: EA-53448 - CCE: JavaCompletionUtil.setShowFQN
6a30279: deeply eliminate wildcards as they may appear during inference in wildcard's bounds
6773fcc: testdata for IDEA-104429
c17274e: lambda: check functional type return type before accepting cached value
e2c708d: method refs: add constraint P1->ReferenceType for inexact method references despite of spec (IDEA-117311)
9ef2c46: new inference: propagate current substitutors during additional constrains processing (IDEA-118965)
7dc476d: Gradle: Module builder updated. * New Module now adds module to the respective gradle project using settings.gradle inclusion * Support for *.ipr (file based) project format added
d88e160: IDEA-119651 DomStubBuilder uses physical files for indexing but it should use supplied one
e6fe39c: make constant search not block the UI
4037871: IDEA-119983 Smart type completion mixes order for Color.RED
589208f: test that stats is remembered for global static method completion variants
c314c53: make Show All Tabs action name & description closer to the behavior
23c0651: inspection considered harmful (IDEA-119766)
e72c1a3: Merge remote-tracking branch 'origin/master'
5fd0a91: Fixed SQL 'select/insert/...' rule injection into indented string literals (PY-11970)
4ecd882: Fix NPE
5c4ef6b: JavaFX Scene Builder integration
2621f17: Assume that string without '%' operator or 'format()' contains no formatting (PY-11771)
0c35ee7: cleanup
6e66b22: Don't run code analysis for injections with interpolation in string formatting (PY-11962)
9f28f9d: AbstractCollectionComboBoxModel — specify list type
4428d76: MutableCollectionComboBoxModel — specify list type
e77b8c9: use gap instead of titled border move 'Clear ..." to new line (left-aligned), not right-aligned on the same line
8824507: breakpoint properties was not saved if breakpoints dialog was opened from line breakpoint popup
ba59486: Update appearance of certificates configurable. Buffer storage modifications in configurable, instead of applying them directly
5f4f22b: IDEA-79353 No completion in the Type field of Custom Renderer preference page
27d736e: don't allow edit action if not editable
4b5b6e8: assume custom stubs only if psifile's content element type isn't IStubElementType, this fixes performance problem of previous change (that added support for dom indices). The performance problem was manifested for flex stubs produced by decompiler.
cc66943: Fix typo.
447fa05: Make WorkspaceReader available to extensions.
217a6ba: Activate Maven extensions during project resolution.
f98b4ed: PY-11958 PullUp refactoring breaks class signature if class has more than 2 ancestors
6c989e6: high CPU and EditorTextField/LanguageConsole scrolling
c010442: Merge remote-tracking branch 'origin/master'
6040533: update browser icons add icons for custom browsers — yandex, chromium, canary
31f6857: [git] IDEA-120042 Protect against zero timestamp
fe3a49a: regress: don't hold strong reference to index content
470ad4d: GitRootFinder removed as unnecessary
003d00c: PY-11968 "Pull member up" refactoring should not allow user to move member up if parent already has one PY-11290 Target classes of "Pull Members Up" refactoring should be sorted in ancestry order PY-11289 "Pull Members Up" should not hoist code into python stubs/skeletons. PY-11288 Better default for target of "Pull Members Up" refactoring
e4bf6e4: Add injection place even if a string fragment consists of zero chunks
76e0d23: Fixed parsing of unbalanced new style string formatting (PY-11962)
3e71eee: IDEA-119738 Problem with Android Studio connecting to wrong VCS (Git vs. Mercurial)
1195dd4: style
4045914: fix incorrect fileChooser descriptor — use createSingleFileOrExecutableAppDescriptor
68771c2: IDEA-119965 Mac messages with one button should have focus on that button
4eb8664: IDEA-102508 error status of run configuration is not updated after fix Needless component revalidation fix
a6d541e: New Xib format
e706b96: CR-IC-3901 check isMacOSSnowLeopard
f04c8a6: CR-IC-3901 mac file chooser must respect FileChooserDescriptor.isFileSelectable
e9fdcd9: a few more words in the base dictionaries
5f70931: FoundationTest — junit 4
129898f: move createDict and fillArray to Foundation util
aa04a46: new inference: reduce additional constraints order fixed
4c7fec7: correct file name
38de625: IDEA-119976 Code | Completion | SmartType's Alt+Space shortcut does not work
09e3217: commit may change psiFile instance, completion should be prepared to that (EA-46770)
69b71e7: allow to use step into and smart step into shortcuts to select smart step into target
09846dc: proper size
fd6db9f7: [git] IDEA-119887 Support one more git version output format
bd9cc7f: [git] convert GitVersionTest to junit
89e5e54: UsefulTestCase.assertNotEmpty
299ca1f: inline protected method 'createAnnotation' http://crucible.labs.intellij.net/cru/CR-IC-4157#c21408
bfbcdc8: [^kb] on java 8/linux non-focusable popups get focus a bit later, workaround that (IDEA-94683)
55a4c7b: CR-IC-4150 use equals on vfiles
9200d31: add a description for Show All Tabs action (IDEA-119952)
86a57b2: IDEA-119961 List support for Expression Evaluation
b91fcf2: Merge branch 'python-fixes'
e37f9b1: Fixed spelling in names of variables
61f5888: Simplified always true expressions
fc7fabe: Fixed EA-49990: assert: TextRange.<init>
b132ae4: WEB-10741 Turning on Karma Plugin Autotest will highjack editor window upon retest.
40f3ae8: lambda: ground target type for implicit lambda
32094bf: temp solution (IDEA-118527)
486cac8: IDEA-119969 Root node has wrong offset
a05d051: IDEA-118817 Parameter annotations are not respected for @Delegate annotation
695bc50: corrected test data after fixing IDEA-119589
7d2fe18: IDEA-119910 Middle matching doesn't work if pattern starts with a digit
e0b2a8b: [vcs] IDEA-119891 Use correct line separators in commit message document
22463b1: CCE fixed
0f133cf: Gradle: buildscript configuration respect inheritance
e140b1e: IDEA-69253 completion in type elements of parameters after dot
d3a5dab: IDEA-117390 don't complete light elements containing IntelliJIdeaRulezzz
6a90cfb: IDEA-119658 Watches inplace editor does not resize
802f6de: category icons
d6f2453: IDEA-119894 "Customize data views" dialog is ugly
620b789: 'fixme' added to the dictionary (OC-9056) -> word moved to jetbrains.dic
b79e4f3: IDEA-119520 New Project / Module Wizard: last-selected template should be remembered
f5be91b: Cleanup (deprecated constant dropped)
b0116c0: EA-53411 (more reliable diagnostic and better recovery)
50c6083: extra fix after review
a5d9cdb: maven: webapp resource filtering supported (IDEA-25934)
b61e7f9: trying to fix blinking test
d6951b6: refactoring: class extracted
a6e1abc: IDEA-119864 indents
b7b65ba: IDEA-108964 caching field accessors
6e833dd: fix should not have psi refs
9e97414: allow to create an annotation with a custom severity
2106911: Fix CCE (PY-10999).
4fe2695: Merge remote-tracking branch 'origin/master'
2f3b719: Setup __loader__ for __main__ module (PY-10535).
a44092b: enable File|New action in Database view
b50f4bc: enable File|New action in Database view
bb558e8: better fix for IDEA-111684
3e8d5d8: fix regress IDEA-119720 : schedule for update if file isn't too large
5897d97: better code per review suggestion
445aa37: EJB method hierarchy shouldn't affect completion statistics (IDEA-117673)
be30e67: IDEA-116506 File Templates: can not delete duplicated template
8bafc21: NonTrivialActionGroup instead of NonEmptyActionGroup (the latter takes "registered" actions into account only).
b8f41b5: DEA-119860 Empty tab name if turn on option "hide file extension"
37e2a4c: IDEA-117852 NullPointerException when making project with mixed java/groovy sources
a4d5836: ignore groovyc stderr spam about JAVA_TOOL_OPTIONS (IDEA-118182)
e82c49a: IDEA-119794 IntelliJ inspection "may produce NullPointerException" doesn't understand Objects.requireNonNull(...)
7e06961: IDEA-30947 Invalid error message in debugger/type renders dialog: "Incovertible types..."
8c4dc0e: Merge remote-tracking branch 'origin/master'
a64db8a: EA-53583 - IAE: UsageViewPresentation.setNonCodeUsagesString
12a834f: case fixed
88c7770: graph inference: accept raw inference when return type was erased (IDEA-119844)
c8e5698: graph inference: recursive calls (IDEA-119834)
a1eef95: [log] IDEA-119898 Fix graph artifact in case of diagonal edges
9984c56: [log] dry
5960162: [log] @NotNull
7942f6c: restore "analyze stacktrace"
71d742a: Add possibility to add/remove certificates from application trust store
8122c69: keep java-docs in sync
41104b6: make sure 'startRunProfile' is invoked in EDT
4269a85: IDEA-103743 Settings > Code Style > Arrangement UI glitch (after-review improvement)
bd4e9ec: mac file chooser should not resolve symlinks +review
1413859: Revert "updated external tools. Added annoying *.whl for the needs of virtualenv."
798bcad: CR-IC-4108
eb65f3e: convenient "Done" ctor
59e3ab1: CR-IC-4046 use chooser description in mac native file chooser
4dba37a: IDEA-119855 Github: remove duplicates from "Share On Github" dialog
db9023c: Rethrow SSL exception in case "empty trust anchors" error, when Mac JRE has no default keystore
e2cdf40: CR-IC-4094 (confusing methods united)
e7106a4: return name of SettingStep#getModuleNameField()
388e840: fix installers: remove lint-cli module
34d1109: IDEA-118601 New Module: Maven: click on "Create from archetype" reverts typed coordinates.
0f28587: IDEA-116116 New Project Wizard: default folder for jars download is /lib
99ec69c: 'fixme' added to the dictionary (OC-9056)
9f73164: Refactor CertificatesManager components to standalone classes, add configurable for certificates management and truststore access.
5e029bf: Mercurial Repository info problem fixed
96ec395: style
9c77e2a: use explicit html4 to reduce variants
8129c49: IDEA-119680 Gradle: work offline
1d2d040: refactoring: file content filtering part extracted to separate class
4d12f56: standalone JPS build: added option to build all artifacts (IDEA-119784)
1eacef4: processFilesRecursively optimized by eliminating unnecessary 'isDirectory' calls (ZD-19763)
c9219f4: maven compiling tests: base class extracted
8d2a295: remove microdata, it is handled by custom directives provider for better code insight
59f3848: modifier fix should not contain psi refs
5877fa8: include only SVG-tiny
a0435ca: [diff] IDEA-119780 close dialogs with CANCEL exit code rather OK
2f8cda1: [diff] remove unused
a6b4095: [vcs] Don't allow returning duplicate VirtualFiles
6d904e2: [diff] Don't create inner class for customizing action's icon
64be498: [github] IDEA-119693 Don't share workspace.xml
0f1ccae: xhtml should be valid, only body/head/frameset are permitted under html node
f6a05c7: testdata corrected for new schema
4301bab: cleanup SVG and MathML hack
e7bc5492: new html5 schema with blackjack and extensions SVG, MathML and RDFa are now supported #WEB-462 fixed #WEB-417 fixed
d8e1c94: IDEA-119773 (slf4j placeholder inspection false warnings when passing in Object array)
173c6e8: Merge remote-tracking branch 'origin/master'
0147c24: Added test for PY-11337
7d84519: Text changes: "unused" -> "irrelevant"
d120238: IDEA-102508 error status of run configuration is not updated after fix
5c5e163: Merge remote-tracking branch 'origin/master'
25652d5: PY-3569 Inspection to warn if a loop variable is assigned inside the loop
8b70d81: remove stubs presuming to build jar locally before we move to java 7
3d8a6d0: IDEA-119826 Do not require confirmation each time I open an IPR file
9038ec4: IDEA-119589 Wrap when typing reaches right margin wraps one symbol before needed [CR-IC-4089]
5759064: IDEA-107538 java: "Go To..Next Method / Previous Method" should skip fields
c92cb87: Merge remote-tracking branch 'origin/master'
e628865: Merge remote-tracking branch 'origin/master'
2f3a48e: revert
aa68b40: IDEA-111122 remove attached jar artifact coming from "apklib" dependency from the dependencies of app module: users add it to deploy jar to Maven repository in addition to "apklib" file, but we don't need to add it to the classpath, because it leads to class duplication [rev=sergey.evdokimov] (cherry picked from commit 0663734)
03b007d: EA-53045 - NPE: PsiFileImpl.navigate (CR-IC-4127)
69ee7c8: IDEA-119509 do not show classes we're not going to import in "import" dialog [rev=peter]
e62c18d: advance bomb
315aa55: adapt android step to the new wizard
a7311eb: keep overridden group content option
66cf177: a less distracting thread dump filter (IDEA-99943)
6995ba8: remove AbstractMethodErrorWrapper
54879ea: Merge remote-tracking branch 'origin/master'
e4c8354: replace SBKit stubs with jar (it's under GPL license and we do not redistribute it)
643f3e1: revert of accidental previous commit revert
b79c1da: spring file based indexes/searchers
4fa374f: fixed EA-53497 - assert: TextRange.<init>
6e4c2d3: DevKit "language": restrict Language.getRegisteredLanguages() results to those available in project/SDK (CR-IC-4017#c21280)
7064f5c: Merge remote-tracking branch 'origin/master'
670d010: a way to detect bundled plugins when run Idea from Idea
6b8e5bb: Merge remote-tracking branch 'origin/master'
e0e690c: Merge remote-tracking branch 'origin/master'
2a9b3e2: updated external tools. Added annoying *.whl for the needs of virtualenv.
1d6519a: unavailable api inspection: support for java 8 api
f03ea37: Merge branch 'python-performance'
2fa8245: Cache presence or absence of a user skeleton for file in its user data
4aca40b: better project name for temp project + pass dummy status
10f6a0f: another stub update index fix: - stubs doesn't get buffered status update notifications because they aren't built out of unsaved documents - also index read also made affected to buffered status
455ca8f: WEB-10733 Mac OSX: disabling JSHint results in buggy presentation of version combo
e0d53aa: IDEA-119328 don't remove unresolved imports only if references in code could be resolved with them
eef5c14: IDEA-119328 parse code reference elements without name element
3c69c63: IDEA-119647 CCE on groovy file
ba0b939: cleanup
3dd03e8: cleanup
328c39f: FileUtil#loadLines moved to FileUtilRt
5404220: CR-IC-3879 (handle module component initialization errors)
3c288a8: Rewritten PyQualifiedReference.collectAssignedAttributes() for better performance
6bbdc88: Cache the result of asQualifiedName()
3306469: Forgot call to super
389fc76: EA-53504 - IOE: PsiJavaParserFacadeImpl.createExpressionFromText
3f409f1: EA-53575 - CCE: InlineMethodHandler.inlineElement
b00014b: method ref constrain (IDEA-119552)
bd80c20: cleanup
6404ec9: Merge remote-tracking branch 'origin/master'
6c7831a: tune decoration color for Darcula
5485ead: filtering frameworks by template
1d47fa0: IDEA-114381 (do not use foreign clipboard contents in internal events)
03ca39f: IDEA-114381 (missed use case; tests)
db15563: Resolve conflict with "&Replace with"
7a8ad62: Merge remote-tracking branch 'origin/master'
801f34d: fixed missing sys import
3e29ea2: Merge remote-tracking branch 'origin/master'
a185876: Disabled comment injector for Python for performance reasons
228266b: IDEA-117522 Some dialogs are not disposed with the escape key
1ae36ce: ProjectCategoryTemplate
2d44f96: Merge remote-tracking branch 'origin/master'
32d79c8: fixed missing sys import
115576d: Merge remote-tracking branch 'origin/master'
50c4cf3: Merge remote-tracking branch 'origin/master'
37645b4: fixed PY-11561 "Add super class call" incorrectly inserts parameter annotations
a9da411: Cleanup (typo)
714969c: build scripts: launch .jar reorder task in headless mode
8145dd4: IDEA-114381 (check clipboard data flavours before loading the whole content)
4fa6582: Cleanup (formatting)
acf1752: fixed PY-11495 Create function: do not propose quick-fix for unresolved parts of fqn
21e2c1d: fixed PY-11484 Implement abstract method: pushes docstring out of the way
43e98b8: fixed isAbstractmethod
1c85aca: Unnecessary parameter --ignore removed from appropriate status commands.
e0f86d5: do not check plugin name for non bundled plugins
00f955e: If Gradle task execution fails, now we throw an exception showing the message of the real cause.
774ae65: use system font on Windows (Segoe UI, 12)
8281f35: IDEA-119035 Select All shortcut for any table on mac with Darcula
abc190b: hide Show Implementation action just like Quick Doc when not appropriate
2ad99bc: IDEA-119630 Live template broke in IDEA 13
1216a4b: Merge remote-tracking branch 'origin/master'
4db9093: Fix align multiline elements in parenthesized expressions, parameters and arguments lists.
46a84e6: Merge branch 'python-performance'
50d1e9b: Cleanup of API for qualified names of expressions
74c850c: Method call in indenting statement should have continuation indent.
b69f7d4: fixed PY-11353 Creating Run Configuration from specific test gets the "target" wrong
8775d1b: DRY
e8ac1dc: #WEB-5067 fixed
2c804f6: cls reference ignores passed outer class type arguments (IDEA-118733)
e6350af: IDEA-119677 AWT thread blocking during start up
c49bd1b: fixed PY-11312 False positive CamelCase variable imported as lowercase
1d6966b: fixed PY-11281 Convert dict comprehension to dict call omits if expression
b811619: Deprecated PyResolveUtil.treeCrawlUp() as a slow way of traversing the PSI
5deb882: Made several internal methods of PyResolveUtil private
5a2fdc9: cancel outdated quick info calculation on ctrl+mouse (IDEA-119642)
36d507f: fixed PY-11277 Python: Wrong "argument equals default" inspection
a5fc7ef: Merge remote-tracking branch 'origin/master'
8cdcea8: fixed PY-11617 Nosetest runner: simple function tests cannot jump to source
7b704287: fixed PY-11696 Cancel after adding new interpreter removes configured project interpreter
a2f1da9: IDEA-118773 Change Assembla's issue IDs to be project local instead of unique global
9e9dde3: Disable possibility to create feature branch in "Open Task" dialog, before at least one branch already exists
ae83297: proper fix for PY-11879
585e827: Added PyQualifiedReference.isQualified() that potentially doesn't require AST access
99af1d0: Use ScopeUtil.getScopeOwner() for preventing unnecessary stubs to AST switch
3421829: Add plugins to check: Pythonid, org.intellij.clojure, NodeJS
4e91422: fixed PY-11340 Invalid case for can't assign to literal inspection
501d6a5: FileUtil#loadLines and ExecUtil#execAndReadLine allow to specify encoding
7731644: Merge remote-tracking branch 'origin/master'
80f6238: fixed PY-11341 Invalid case for identifier expected inspection after as in with statement
c7d5036: Fix continuation indentation in while statement (PY-11869).
5459b34: default test runner is unittest
3cb5420: IDEA-119467 Gradle: auto discovery of buildSrc project
3a98272: IDEA-119467 Gradle: auto discovery of buildSrc project
a33865b: Cache the results of asQualifiedName() for performance reasons
b275188: JavaFX Scene Builder integration
1a196a0: IDEA-73920 Auto-activate maven profile when in IDEA
24c45a2: Merge remote-tracking branch 'origin/master'
077da06: Indent comment in tuple (PY-11904).
dca7107: Gradle: respect the order of dependencies
4c154e6: Merge remote-tracking branch 'origin/master'
2142a55: Fixed test data to satisfy PEP8.
6889a43: IDEA-111432 Mac OS X: Shortcut Alt-W in search dialog not working (the mnemonic should be consistent with find in path dialog)
90a0a5c: IDEA-111432 Mac OS X: Shortcut Alt-W in search dialog not working
f97694c: Remove wrong depends from module
a87dd11: JavaFX Scene Builder integration
ccd0d4a: Maven, Android, and Groove moved under Java
2b72075: EA-53537
a880968: IDEA-66430 "Find In Path" doesn't show up in "Recent Find Usages"
3c9a856: assertion for EA-52184 - IAE: FileTypeManagerImpl.isFileIgnored
ce5e012: IDEA-119617
e27d306: notnull
41d0ae5: already disposed
823b697: dispose progress if application exits unexpectedly
f11fc22: notnull
7c26960: fixed PY-11879 Refactor: Rename: references in ivar directive are not updated
b016bf2: Merge remote-tracking branch 'origin/master'
874f0ef: Fix Jira test related to time tracking (zero hours case)
76956c0: IDEA-119740 Ctrl+Shift+Space does not complete exception type after "final"
100bad7: fixed PY-11884 Missing completion for finally keyword after else statement
b2dc0d2: #WEB-7422 fixed
5106f0d: #WEB-8715 fixed
a19ebc2: IDEA-118759: Run ant headless so no dock icon will appear (https://github.com/JetBrains/intellij-community/pull/131 manually merged and improved)
5ad360e: fix grails tests
404f4e3: IDEA-119663 false positive Constant conditions & exceptions: "Argument ... might be null"
32ff621: Merge remote-tracking branch 'origin/master'
f831c81: IDEA-110055 Code Style: Copy to Project: Arrangement settings are not copied (copy empty grouping rules)
7567649: IDEA-110055 Code Style: Copy to Project: Arrangement settings are not copied
b55ee30: PY-11882 Assignment to for loop inspection false positive PY-3569 Inspection to warn if a loop variable is assigned inside the loop
11a158b: Merge remote-tracking branch 'origin/master'
56c1793: Insert two spaces before line comment (PY-11901).
3087918: hide some File-menu actions when appropriate: File|Encoding, Line-separators, change R/O, HTML export
04af1dc: introduce NonTrivialActionGroup
e04ba66: Merge remote-tracking branch 'origin/master'
8984779: javadoc improved
97fee4e: Merge remote-tracking branch 'origin/master'
abfcab9: fix layout
6c0615a: Do not allow view to be larger than viewport with SCROLLBAR_NEVER policy
9f9aa28: javafx: scene builder: do not load javafx classes from multiple loaders
db4b9e9: restore "show hierarchy" when no element was selected
db9fa78: Fix indent in parenthesized expression in indenting statement (PY-11868).
85bcbe8: IDEA-119510 Update Pivotal connector to correctly set "Started" and "Finished" states for stories. Unify titles of error dialogs in "Close task" and "Open task" actions.
9623666: JavaFX Scene Builder integration
f9a833b: Merge remote-tracking branch 'origin/master'
7ca0e52: Inject SQL only into strings that have SELECT/UPDATE... at the beginning
1eb3644: NPE fix
da3e2e3: select word should honor string literals in custom file types
fbdee48: move long griffon/grails framework detection into background
673ed61: IDEA-115351 Idea UI hangs after performing Move Module to group
77234b7: Merge remote-tracking branch 'origin/master'
d6184d3: fixed PY-11428 "Variable in function should be lowercase" false positive for variables declared global
e4df7b8a: javafx: scene builder: eliminate dependency
36e15a7: IDEA-118605 Add missing attribute check in YouTrack response handling
66827e2: Merge remote-tracking branch 'origin/master'
bbdecb0: Try stub-based containers for Python PSI elements instead of getParent()
219d0fe: Use hasDefaultValue() instead of getDefaultValue() in order to prevent switching from stubs to AST
58065e5: Qualified targets are never local
54700b3: Use isQualified() instead of getQualifier() in order to prevent switching from stubs to AST
81794e4: Find owner via ScopeUtil in order to prevent switching from stubs to AST
5a5e085: Note about stubs to AST
1038077: javafx: scene builder: move stubs to separate module
a0f51bb: javafx: scene builder: embedder
41ac380: Merge remote-tracking branch 'origin/master'
7318d6d: IDEA-58838 Alt+Click on Exception breakpoint marker should switch this breakpoint off instead of creating new line breakpoint.
fa02045: External system: respect scopes for module level library dependencies
021501a: Add hostname verifier to SSL support (disabled for now)
1b3806b: Annotate for renamed/moved file fixed
4b8aad4: getFileNameInTargetRevision updated
64db488: Traverse class owners via ScopeUtil in order to prevent switching from stubs to AST
a21046b: Revert "added -Dfile.encoding=UTF-8 to tests.gant"
9b3d7f3: Merge remote-tracking branch 'origin/master'
256144b: test fixed: do not assert order of ClassInheritors
1600ff2: Merge remote-tracking branch 'origin/master'
72f7af1: Merge remote-tracking branch 'origin/master'
b3d735f: don't allow to change family of predefined browsers
9ea642c: set default editor for Enum
fdee8bc: IDEA-88390 Object variables could be casted to any class in Evaluation window
17002f6: javafx template is back
3234409: added -Dfile.encoding=UTF-8 to tests.gant
3168f61: IDEA-88390 Object variables could be casted to any class in Evaluation window
41a0c8e: pass idea.config.path and related properties to external build process to ensure that APPLICATION_PLUGINS_DIR path variable is substituted properly (IDEA-118928)
c864c4b: Gradle: test data fix
fc69870: extract superclass events posting (IDEA-119248)
93330f8: restore that ClassInheritorsSearch returns unique results (IDEA-119628)
fb06a91: Filter out non-physical classes in DefaultClassNavigationContributor
debd3f2: AsyncGenericProgramRunner added to let program runners make some calculation before actual console appearance
47b6662: getSelectedObjects — use the same approach as in TableUtil to collect selected items
9d412b0: don't allow to remove predefined browsers
7702e1d: ComboBoxTableCellEditor — cleanup, it should extends DefaultCellEditor
9e3ecd3: myUpdaters contains only one item in most cases
76e1f83: cleanup — use isSelectionEmpty
e266783: TableToolbarDecorator — remove action supports multiple selection
5036cb3: cleanup
6ac47d8: use ContainerUtil.reverse instead of LinkedList ContainerUtil.reverse returns empty list if source is empty
99fee5d: JavaFX Scene Builder integration
aeb1257: IDEA-55171 (prevent sync refresh from locking if application is disposed)
1697889: Merge remote-tracking branch 'origin/master'
9e120cc: Compare decorators by name preventing unnecessary switch from stubs to AST
726c608: Merge remote-tracking branch 'origin/master'
e82fca2: IDEA-88390 Object variables could be casted to any class in Evaluation window
6d2b1e8: Don't analyze target expressions not located in the current file
3e8cc71: Emmet add diagnostic info
e45ecbf: Fixed NPE
8b820b6: IDEA-117373 Spacing options for Java type arguments/parameters [CR-IC-4071]
869e503: [log] IDEA-116322 Fix structure filter for multiple roots
4d4d364: [log] refactor: group filters before passing them to providers
a3f1fcc: Merge remote-tracking branch 'origin/master'
d873fec: DOM: use null, not empty StringRef for non-set ElementStub#elementClass
3a314c4: tests corrected for new schema
30527da: CR-IC-4025 (more concise fix)
7a31cf5: IDEA-119498 (only suppress plugin updates for true command-line usage)
93f8684: debugger value popup refactored: less duplication in different implementations, reduced coupling between classes, recreate tree component after disposing
290de68: tests corrected for new schema
a98faf2: updated schema for html5
58fa267: Merge remote-tracking branch 'origin/master'
6320d5f: do not replace checked exception with unchecked (IDEA-119345)
aaa813a: resolve conflicting names (IDEA-119412)
9cc6ad8: duplicate string literals: do not add introduce constant fix for batch mode
baee0eb: distinct prover: do not distinguish raw type arguments from type arguments without params (IDEA-119546)
3f6a77a: IDEA-119566 "Delegate Methods" doesn't work with fields of a generic type
a22c53c: Merge remote-tracking branch 'origin/master'
72fc2ed: update path field on data changed
0f41580: add profiling parameters to the right part of the classpath (has been broken after Launcher was introduced)
ed3781b: Merge branch 'python3.4'
3234c0b: IDEA-119336 Gradle build files: build.gradle scripts are checkout from Perforce even if the file is not changed
40ab35c: removed dependency on non-community module
ac0fe97: wrong unneeded dependency removed
7f1152e: Calculate iteration type via types, not PyClass elements
3217cdf: requestFocus after on edit dialog close
e979477: fixed PY-11875 Pycharm code analysis stalls on specific code (caused by AIOOB in getArguments of decorator)
99d62b0: http://ea.jetbrains.com/browser/ea_problems/45670
8df5aab: use existing byte[] from stream to avoid producing large garbage objects
fcd155b: inflate zipped contents out of the lock
62fd790: don't consume VK_EVENT in case of in-place editing
ccb42ff: String cell editor undoable by default +review
e2798fd: move createUndoableTextField to GuiUtils (we cannot depend on platform-impl)
801a351: fix isModified
7334354: WEB-3421 resolve RequireJS aliases from main path
711c0cc: IDEA-119467 Gradle: auto discovery of buildSrc project IDEA-98930 IDEA does not resolve dependencies in Gradle buildSrc/ project
20ae03f: Merge remote-tracking branch 'origin/master'
22ba22a: update copyright in artworks
f32591a: Merge remote-tracking branch 'origin/master'
82ddf7d: fixed empty headers and import (dependant in language level) for qt, gtk... skeletons.
b8ddcd4: Gradle: EA-53148 - NPE: AbstractExternalSystemConfigurable.getProjectName
d2a8310: Removed redundant PyTypeProvider.getIterationType()
0982afc: IDEA-119467 Gradle: auto discovery of buildSrc project IDEA-98930 IDEA does not resolve dependencies in Gradle buildSrc/ project
2bbb843: Types of Enum members' fields and type of Enum.__members__
d7435e4: Merge remote-tracking branch 'origin/master'
8a38ae9: log problem if needed
47c08b7: Merge remote-tracking branch 'origin/master'
a677cc2: mark root node as terminated if some nodes aren't final
5feb54c: notnull
b8772f1: decapitalize
245a416: assertion removed in CR-IC-4018 is back
cfe53d3: notnull
a42cc19: allow to call remove() on iterator
99c78160: obey "new ArrayList(Collection)" contract about created list capacity
0d881cd: cleanup
1e7e11b: replaced with reparseFiles
aa16517: notnull
7ab28bb: notnull
31b1b18: duplicate code
ba9f665: IDEA-72304 Namespace auto import does not work for EL functions
3ab8bc7: Code Style: Lazy arrangement settings save
22d7399: IDEA-95410 Arrangement: Preserve fold regions on arrangement
6e02e4d: Merge remote-tracking branch 'origin/master'
09916b5: PY-6955 Unused import not greyed out if also failing
f293c4a: IDEA-119619 Settings / Language Injections: project level XML tag injection loses Sub-Tags value on IDE restart
d2af13a: PY-6955 Unused import not greyed out if also failing
89beff8: Fixed PyABCUtil.isSubtype() check for class definitions that have metaclasses
14c2396: Type provider for enum.Enum members
6238d92: Store metaclass qualified name in class stub for better performance
2e110fd: PY-6955 Unused import not greyed out if also failing (test refactored)
cb9e823: Added PyClass.getMetaClassExpression()
1ee1c25: Extracted getMetaClassExpression()
48b90c2: Evaluate metaclass type using TypeEvalContext
2cfa88c: IDEA-118977 Minor alignment issues with the new style for bottom (and right) aligned tool window tabs
92107d2: Check __metaclass__ attribute only for Python 2.x
bf9a384: Refactored PyUtil.getMetaClass() into PyClass.getMetaClassType()
90548c0: Don't hide 3 or less "unused" items in "+" popup. Action text has been updated.
8adfd34: don't leak dom navigation targets from gutter icons (IDEA-103010)
04425c9: support table decoration on IntelliJ laf
a3030e6: browser table — continue "default browser" usability improvements
1f430b7: avoid use getItems() — use model directly (our ListTableModel provides handy methods) remove duplicated code — getSelection equals to getSelectedObject
55ee980: IDEA-118211 - also avoid double dispose
8068651: Merge remote-tracking branch 'origin/master'
609c0db: Keywords already contains 'as' and 'with'
4d1ca37: Merge PyKeywords with PyNames
af674d6: IDEA-118374 Formatter chop down method arguments when long is not working correctly [CR-IC-4041]
e733d8c: IDEA-56062 Sticky custom data type renderers
2ff5892: EA-53317 - NPE: CompoundRendererConfigurable$.run
7f1c2d7: Add brokenPlugins.json
7813f62: ensure that editor listener removed
3ffe34f: fix java.lang.NullPointerException at com.intellij.ide.browsers.StartBrowserPanel$3.chosenFileToResultingText(StartBrowserPanel.java:143)
cfebc26: fix NPE on channel write
4ecf94b: Merge remote-tracking branch 'origin/master'
43105d2: fixed PY-11823 Test Runner detection in settings doesn't pick up just installed test runner
68bfa5e: Gradle: dependencies scope merge and sourceSets type handling updated related issues: IDEA-119365 Gradle import does not respect model customisations IDEA-118280 Gradle import: IDEA detect java folder as a resource folder IDEA-117668 IDEA v13 spontaneously changes additional test source root to source root
8e2ce03: IDEA-112303 Tool Windows Quick Access button: impossible to select item in list by mouse
63facd9: More fixes for IDEA-115200 Eclipse code style import: Line Wrapping: some categories are not applied
2cc69e5: AC/C++: OC-9003 Trailing whitespaces are stripped in PCH during typing +review CR-IC
47dee08: Trying to fix EA-51665 - assert: FTManager.createAndStoreBundledTemplate
a5e4cf4: Add additional diagnostic to investigate EA-51665 (assert: FTManager.createAndStoreBundledTemplate).
3c5ad21: fix test attempt 2
128b5ad: Merge remote-tracking branch 'origin/master'
7d3eeee: Fixed dedent in case of tabs ( PY-10120).
5753542: Correctly handle "chop down if long" option when importing from Eclipse
5e15a7d: Python keywords extracted. Cleanup.
9685932: Merge remote-tracking branch 'origin/master'
6ac50ed: Merge remote-tracking branch 'origin/master'
416c4da: Merge remote-tracking branch 'origin/master'
917a759: Fixed test data to satisfy PEP8.
79c766f: EA-52368 GeneralIdBasedToSMTRunnerEventsConvertor.findActiveNode: findActiveNode method simplification
9586436: IDEA-119444 Closure view shouldn't be flickering
ea36958: Extracted PyStdlibTypeProvider.getNamedTupleType()
fcea608: WEB-9743 Javascript file with compressed code at the top recognized as minified WEB-7143 Line(s) of minified CSS result(s) in CSS color previews disabled for entire file
c86df90: Move all certificate related classes in com.intellij.util.net.ssl package. Update appearance of certificate warning dialog.
b805e1e: [log] IDEA-119316 Fix "go to commit" if there are log filters
b22a9a7: Don't mark PairFunction return type as Nullable
9ff4ea4: [vcs] Remove read action from loading byte content from java.io.File
ba71108: [vcs] Don't wrap FilePath creation into read action
f5ade74: EA-42899 - CCE: XmlLanguageInjectionSupport.doEditInjection & cleanup
7db1bed: EA-53406 - IAE: ServiceManager.getService
33c31e6: Make right par indent=none in import statement (PY-9075).
0a33757: Merge remote-tracking branch 'origin/master'
9ee1b1e: Make continuation indent after continuation in indenting statement (PY-9573).
9d84c3f: fix UnscrambleDialogTest
14bdb82: PY-3569 Inspection to warn if a loop variable is assigned inside the loop
d912f2d: Merge remote-tracking branch 'origin/master'
ab7b959: Test for PY-9573
334ca32: IDEA-99943 Allow to filter thread dump by a word in stacktrace
9dc5a4f: Fix IDEA-119515 for the other IDE's
2203503: avoid some duplication in ExpectedTypesProvider
032c188: IDEA-119416 Smart type completion proposes nothing in String concatenation expressions
e323fe1: WI-13685 PhpStorm doesn't save project name CR-PS-181 (cherry picked from commit ed41c77)
c62cebb: Merge branch 'python3.4'
0a359f1: IDEA-118389 Forbid completion inside guard blocks; honor greediness
9102f56: Handle 'mode' as a keyword argument to open() as well
40dbf8e: Detect text or binary I/O in pathlib.Path.open()
b7a28d6: IDEA-119514 Tip of the day in IntellliJ IDEA mentions Webstorm
a8474e6: Return instance types for instance types of superclasses
9ffaba9: IDEA-65566 Allow 'NotNull' as the default element behavior for a given class or package
0b9321b: IDEA-99331 Complete Statement: incorrectly completes at statement within new array size brackets
3594766: IDEA-115138 Eclipse code style import: Line Wrapping / Annotations is ignored, IDEA-115200 Eclipse code style import: Line Wrapping: some categories are not applied
6351c3b: Method to process stubs without firing error when stub index is overflown (for Upsource)
2d7f331: fixed PY-11837 nose test runner errors while formatting a test error
2e395dd: Bug fix: IDEA incorrect handle escaping.
4113b3e: IDEA-105253 Missing icon for Thread dumps view
ccb7872: initial ssl support
c69719b: RecentProjectManager -> applicationService
2d6afbe: IDEA-119521 improvement
85e7348: unix signals added
4a5e793: IDEA-104735 Dracula: INVALID string have not dracula style red color
8e8019c: Nullity annotations
4a6c046: Add test for time tracking support in JIRA, simplify test of task's state update
6c0c76a: DSGN-979 DevKit SDK icons update
b197141: IDEA-119523 IOE at com.intellij.openapi.editor.impl.DocumentImpl.d
0cbfc8c: new project wizard preferred width fixed
78f09b8: IDEA-91376 Debugger links incorrectly to codeline in a class which name contains a dollar sign
13b4260: allow to disable "Testing started at <TIME>..." printing on test run
c2834c0: Merge remote-tracking branch 'origin/master'
24f4cf5: fixed test data
48eef72: fixed test data
64f9820: IDEA-119406 IDEA make corrupts files when performing Maven resource filtering (default value of escapeString is null)
952f6a1: IDEA-119515 (Tip of the day contains null character and unclear screen shot)
5b6b3f6: IDEA-119406 IDEA make corrupts files when performing Maven resource filtering
babf29a: print nothing for an ignored test if ignoredMsg is empty
7ddc070: Merge remote-tracking branch 'origin/master'
cbe858f: javaModule.png
4c64507: fixed updater's tests.
4ebbcfd: EA-52519 - IAE: TObjectHash.throwObjectContractViolation
fa5d7c4: EA-52654 - NPE: TemplateState.setCurrentVariableNumber
c803a10: EA-52644 - assert: PsiUtilBase.reallyEvaluateLanguageInRange
0705193: make program HighlightSeverity.toString()-independent
fd7a60e: cleanup
e1472a8: cleanup
68d24f5: visibility
cd45f8e: EA-52792 - assert: PsiSearchHelperImpl.getFilesWithText
040aeb2: IDEA-119521 Adding RSA keys dialog becomes unclickable if it is displayed when test connection is in progress
d0d85af: PY-3569 Inspection to warn if a loop variable is assigned inside the loop
4948059: [git] IDEA-119492 Don't add a newline to amended message
8a91462: filter non-project related keys
f935909: case-insensitive CharSequenceHashingStrategy
48b739f: Merge remote-tracking branch 'origin/master'
53660a9: Merge remote-tracking branch 'origin/master'
916fc5e: EA-53325 - NPE: GenerateXmlTagAction.generateRaw
0b6158a: External System - Maven: clear external system API module options during module Mavenization
1e7bbd2: External System - Maven: clear external system API module options during module Mavenization
c954c2b: try to find name element for rnc descriptor fixes documentation for some tags (e.g. dialog)
fe7db5c: generate html5 tag table descriptors #WEB-10489 fixed
5936b93: support 'nodeId' attribute in 'testStdErr' message
8072bd9: make nonDefaultProject="true" really work
ca3a6c2: cosmetics
2f4f868: use ExtensionException for AbstractMethodError handling
afdb280: Merge remote-tracking branch 'origin/master'
e01cd00: generator: do not drop the whole module in case there are broken __repr__ defined
7b058bd: PreferredProducerFind: remove duplication
f43d5aa: RunConfigurationProducer.EP_NAME should be final
cdb9746: implement alexander.doroshko suggestion: simplify&improve default browser UI (now you set first custom browser as default)
4e504cc: overrides
59ac759: must be in edt
c192b3a: fixed tests of updater.
bafdb6b: CR-IC-3918 a way to detect AbstractMethodError-causing plugin without introducing new Application method
f2dae4a: performance for generator: Split big generated modules (like _Gtk, PyQt) into smaller ones
7840ba3: IDEA-81893 "Do not step into the classes" feature does not work after calling of "Smart step" (Shift+F7)
32a579d: EA-53308 - CCE: DfaVariableValue.<init>
21cdea3: IDEA-119470 File and code templates: changes gone when switching tabs
298bb04: IDEA-119445 Remove first slash in "copy reference"
37521f0: IDEA-119153 file search too wide for users folder
a8c17de: EA-53176 - PIEAE: LazyParseablePsiElement.getContainingFile
2f368ec: EA-53286 - IAE: ObjectUtils._assertNotNull (tolerate null names in LookupElementBuilder.create)
54d19d8: Merge remote-tracking branch 'origin/master'
df0a55e: Refactoring for new Xib format
e8ffba6: better handling of EA-53318
b941c01: fix firefox debug use native file choosers — so, our JS Runners now must be async
3942b86: IDEA-118602 Input-method issues
b8514c9: IDEA-102508 error status of run configuration is not updated after fix
09c4961: Init project name by artifactId
f6af11f: hidpi support on Windows and Linux
ba8037d: IDEA-117555 Search everywhere dialog is being closed immediately
f678c44: Bug fix: IDEA can not guess parent maven project.
459eaa6: refactoring
e013fe3: quick evaluate popups: mysterious 2-pixel shifts removed
687755b: Simplified always true condition
dbd00ae: Extracted PyClassTypeImpl.findProperty()
b8a5d1e: Added 'inherited' parameter to PyClass.findProperty()
cb8f01e: IDEA-118211 Performance problem when closing project
1b24053: Merge remote-tracking branch 'origin/master'
132cb01: fixed IDEA-119347 ../jre64 JDK not being picked up by idea64.exe
3df1ffd: IDEA-119463 NPE at org.jetbrains.idea.maven.wizards.MavenModuleBuilder.findPotentialParentProject
38bf2a6: Python skeletons class members provider now can provide new overridden members
a54f6af: fix getDisplayName nullability assertion
e2db1ea: Fixed code insight for returning 'self' in base class methods (PY-10977, PY-11413)
786df13: IDEA-119347 ../jre64 JDK not being picked up by idea64.exe
abd5ff0: DevKit: cleanup icons
3a5e120: IDEA-88390 Object variables could be casted to any class in Evaluation window
e16c973: Merge remote-tracking branch 'origin/master'
2a31a79: Fix formatter to add two blank lines between declarations with comment (PY-9923).
4623114: IDEA-119462 CCE at com.intellij.ide.actions.OpenProjectAction.actionPerformed
5f1a87b: project types sorting
cba9bda: SearchEverywhere doesn't work on Linux
1aed056: IDEA-119444 Closure view shouldn't be flickering
e7a2066: IDEA-31340 Type Renderers tab has a wrong 'Renderer name' field behaviour
c2cc029: DevKit: "JDK" -> "SDK", use "IntelliJ Platform Plugin SDK" consistently
9a9c4bc: Gradle: respect module build classpath for build scripts resolving related issue - IDEA-118523 Gradle plugin is not resolving Apache Ant imports
35008d0: External System: clear maven module option on project import
6ade53e: IntelliJ Platform SDK: add Spring-API automatically
86f2bd7: EA-53082 - assert: ModuleManagerImpl.getSortedModules
79a7aa0: EA-46683 - assert: PsiDocumentManagerBase.doCommit
8c4583e: diagnostics for EA-53283 - assert: StringLiteralLexer.locateToken
3353fa8: EA-53287 - IAE: UpdateHighlightersUtil.a
43e0404: EA-49858 - assert: Divider.divideInsideAndOutside
ad757bf: faster getField(): do not traverse the whole hierarchy always
6d8156c: make extension dependencies explicit to fail fast when they are failed to load
16aea9d: cleanup
8277c63: Gradle: respect module build classpath for build scripts resolving related issue - IDEA-118523 Gradle plugin is not resolving Apache Ant imports
7f0c180: IDEA-79522 need ability to set display names for xml attribute and xml tag language injections
84ddafc: IDEA-117327 Add a setting to switch off autopopup completion item selection by Enter
8d1674e: don't use document.getText to detect encoding
83684a2: Merge remote-tracking branch 'origin/master'
540fd76: Use builder to create FileChooserDescriptor.
6676dee: there should be only one call to constructor and it should be done from static create method
1570b03: Merge remote-tracking branch 'origin/master'
41cb6dd: Roll-back FileChooserDescriptor API change.
422b1cf: IDEA-119163 "Language Injections" settings should use toolbar decorator in the same way as other
dc80a3d: IDEA-108994 Breakpoints dialog: after pressing F4 on some breakpoint, breakpoint's location should be opened in editor and dialog closed.
b9e76ef: external build for artifacts: added API to filter contents of directory extracted from jar file
91110ad: show warning instead of error if Google AppEngine inspection is failed to load white-list because IDEA is running under JDK 1.6
b788397: 1) IDEA-103743 Settings > Code Style > Arrangement UI glitch 2) checkbox unselection doesn't disable combobox
163bff2: [diff] IDEA-77540 Add "Edit Source" action to the toolbar.
07dd8e6: IDEA-107925 Failed to evaluate varargs method in debugger
b5dc0f2: fixed debugger tests correctness
00b4633: Merge remote-tracking branch 'origin/master'
ddda8c9: add field after super call
7c9140f: style
f38de23: Merge branch 'python-fixes'
234b375: Merge remote-tracking branch 'origin/master'
cfe29d7: Revert "Detect SQL fragments only in the beginning of string literals" (PY-11828)
7550df2: IDEA-114979 Patch update should leave a log of its application
1a84138: Merge remote-tracking branch 'origin/master'
baabbad: Use default charset as python console encoding.
55d379b: Merge remote-tracking branch 'origin/master'
0dc040c: DSGN-968 New Project Wizard icons for IDEA
ec099d3: IDEA-119353 (Required final modifier marked as unncessary for @SafeVarargs method)
83ff410: [log] simplify: if-else -> ?:
fee8b7b: IDEA-85627 amend commit supported in Mercurial
927440c: IDEA opens file from command line, same as e.g. WebStorm does
7181ca9: fix inspection description test
4e0dc9d4: EA-52862 - assert: DocumentImpl.doRemoveDocumentListener
050caa7: cleanup
46f846c: memory leak if application closed when ballons are still visible
0adc646: removed system.out
d62c7c5: notnull, cleanup
55469ef: notnull
fbe9a04: cleanup
7ff404b: notnull
148e9be: notnull
7c7f84f: EA-52945 - assert: ModuleManagerImpl.findModuleByName
8ec8ab9: cleanup, javadoc
cf011c3: Merge remote-tracking branch 'origin/master'
debf6f0: CR-IC-3901 revert
3807ba1: cleanup
75a6e39: remove ImmutableCharSequence from document API to avoid String wrapping and thus leave optimization possibilities
c7af9fe: groovy debugging agent that produces less garbage
2eb2739: CharTable: less garbage & more interning
d2262ca: some simple code for WI-1816 - open file creates temp directory for project instead of opening it
fca0242: dupes index / insection, controlled by idea.enable.duplicates.online.calculation property
54fcf2a: CR-IU-494 make "overrides" internal only
55143de: CR-IU-511 make abstract class abstract & leave getPresentableText mandatory
d2fef8b: rearrange code in commit message dialog (part of IDEA-96792) [CR-IC-3834]
e16bb5e: don't show browser if path is not specified
a60cfaa: cleanup
7a72712: DevKit: move "internal" inspections to "Plugin DevKit" group
c106233: external build for artifacts: method added
b56b6cc: Added Python 3.4 modules to the stdlib modules list
f000610: one random instance for daemon restarting
c5ce7ec: do not produce intermittent assertions & don't call sleep edt thread
d1c5ef3: Revert "Cleanup (code reuse)" Replace path selector in temporary file, otherwise it will stuck until next clean build
fb96650: Merge remote-tracking branch 'origin/master'
3e73aa2: IDEA-90352 plugin.xml: "language" support
0fe2cac: don't call robot on alt on Windows and when window is inactive
f14aab9: consume Alt events on WinXP in default handler to avoid WindowsRootPaneUI.AltProcessor
dde1494: add WinXP definition
149eb2e: IDEA-114979 Patch update should leave a log of its application
5d08937: AC/C++: Kryo lib is updated from 1.04 to 2.22 to prevent serialization buffer overflows +review CR-OC
bb9dfbf: IDEA-105350
dece38b: IDEA-119303 UI Designer: Create Form Snapshot failure
b8b48eb: fix reparse when a text was just appended to the document end
150a696: more tests on snakeCase() macro current behavior (IDEA-119192)
99c6435: validating web module
03c7955: fix dartium debug
cc24945: WEB-10422: make 'select whole CSS selector suffix' option affect SASS/LESS mixins, variables, functions and property values
91c362b: notnull
892c2b8: notnull
6010be5: IDEA-118273
23f9c97: EditorWindow: extracted interface and moved to platform
6a6cd63: assert thread usage even in tests
236d704: assertion for the curios case of disappearing extensions
24354b9: visibility
79b1073: cleanup, notnull
29e5efe: notnull
ff54cb4: EA-53080 - assert: LaterInvocator.isInModalContext
4d5b6a8: nonnls
052622f: com.intellij.xml.util.XmlStringUtil.wrapInHtml
585052b: don't change java identifiers when sanitizing
99b5a27: IDEA-107657 "Add to Watches" is always disabled in both "Expression Evaluation" and quick expression evaluation windows
0a9445d: don't hide completion popup in debugger on mouse wheel events (IDEA-76260)
c9239a7: DevKit: move and update inspection descriptions
32c9c09: IDEA-59252 "Customize Data Views" action should be available not only in Variables view, but in Watches view, too.
8540aec: revert GroovyOverrideImplementUtil hack
cb75c24: use existing psi for stub building to avoid issues when a fresh file from the same text has different structure
d5d5ff3: remove empty type parameter list from overriding groovy methods, as it doesn't appear on parsing the same text and causes stub index mismatch
5479f94: fix GroovyOverrideImplementTest test name typo
4aea702: fix groovy testdata case
ed030224: IDEA-119344 (Incorrect "Unnecessary call toString()" inspection when super is used)
15c56ec: hold local classes on a hard reference (EA-52225)
fb24d98: don't show parameter info for invisible editors (EA-53161 - NPE: ParameterInfoComponent.<init>)
a7320f0: EA-53223 - IOE: PsiUtil.checkIsIdentifier
2dc4ac2: IDEA-118551 Duplicated enum field in completion
b06366a: IDEA-119052 Java smart type code completion proposes incorrect variant if non-matching local variable hides a matching instance variable
df8967b: rethrow PCE from KeyedExtensionFactory reflection
9a116de: the users don't care if we're preparing editors to open (IDEA-115130)
5d81e8d: allow to turn off suggestion to create a file when creating a directory with file-like name (IDEA-118250)
a0be495: IDEA-119192 LiveTemplate function snakeCase() should convert the hyphens to underscores
db8902f: EA-52499 - NPE: BraceHighlightingHandler.highlightBraces
a34edd7: EA-53134 - IOE: DocumentImpl.doBeforeChangedUpdate
21bd013: unused code
a7cb0d4: avoid settings collisions (pre idea 14 vs idea 14) import old settings is not important in this case, but will be implemented later
c80c25d: save only custom path
b1fb92e: Merge branch 'python-fixes'
35a9cc0: Don't ignore unused attributes of empty constructors (PY-7527)
2c0ef61: tolerant findBrowser
968f634: continue — debug: select browser instead of debug engine
ae62fc5: finalize
8c630e9: debug: select browser instead of debug engine
925b976: Fixed NPE in PyUnusedLocalInspectionVisitor.visitPyCallExpression()
dd02782: [^maxim] build psi and index on the last committed document text (IDEA-117183, IDEA-116721)
f85e0e5: IDEA-118389 Forbid completion inside guard blocks
44f1ff0: IDEA-119222 Console folding does not fold single matching lines
c04b551: IDEA-30922 The "View As" options are shown for the undefined Watch items in the Watches tab.
4d2a597: IDEA-118989 Code Formatting broken in 13.0.2 EAP [CR-IC-3927]
a7d5dd0: IDEA-118521 Latest 13.0.1 keeps locking up. Editor becomes unresponsive. Various file types... using allScope()
ea99916: IDEA-21297 Debugger does not react to "F2" key which should open "Set Value" dialog
a377019: IDEA-21297 Debugger does not react to "F2" key which should open "Set Value" dialog
5963bc5: re-generate with icons.gant
3936e00: Add a couple of new methods in NewBaseRepositoryImpl, update Gitlab connector accordingly
133ac7e: Add notification about unsupported version of JIRA
23977ef: IDEA-117533 Return time tracking support in JIRA repository. Add missing nullability annotations.
ebd73df: [git] IDEA-119322 Use "unsorted" only since Git 1.7.12.1
b938477: IDEA-91148 Difficult to step over code due to tooltips
5f44d77: [diff] IDEA-77540 Go To Source from vcs diff
3eb7315: Remove unused stuff
56738b2: IDEA-118616 Lens mode with tool windows on the right side
7fb9772: fixed PY-11800 Parameter unfilled false positive for decorators with '*' arguments.
b1d9f99: IDEA-119272 Groovy: don't duplicate @Nullable in implemented methods
eefe03a: Add message about missing system cacerts keystore to log.
8aa8ca5: Postfix templates: fix template for anonymous classes
bf35035: fixed test data
84c7060: fixed add field declaration to the beginning of __init__
47997a4: fix NRE
2ba5691: Merge remote-tracking branch 'origin/master'
25e4279: Simplify check, that certificates chain is self-signed
2b21866: fixed EA-52897 - CCE: ImportToggleAliasIntention$.execute
81bcb9d: fixed EA-53046 - NPE: PyExtractMethodUtil.a
c584766: Update JIRA integration tests, set socket timeout of 10000ms. Some cleanups in logging and task status handling.
c026100: Remove legacy EASY_HTTPS protocol from Task Management
22fd4f3: Merge remote-tracking branch 'origin/master'
393df33: fixed quickdoc test
ea3b1ed: CR-IC-3884#c20360 "Setup" method should return VOID.
39237d0: WEB-10469 CSS Error Highlighting - Marking valid custom HTML tag as error
40274b7: fixed editing test
e4d168e: CR-IC-3246#c17895 hide LocalFileUrl
d079b49: IDEA-119085 Code style does not recognize Groovy spaceship operator <=>
b71b60b: tolerate removal of mouse and mouse motion listeners after disposal
973a88ca: use longs to access PagedFileStorage
9e5970a: fix "inner class may be static" inspection problems
29ecbf1: IDEA-117982 correct classpath for groovy scripts
bffaa0d: http://ea.jetbrains.com/browser/ea_problems/52822
721524a: IDEA-119172 Warning 'not all execution paths return a value' when using instanceof
45b9153: IDEA-119037 intention to alphabetically sort map entries
1df78c1: Groovy: align map entries in map literals by default
3743416: import exceptions from throws-list when implementing/overriding methods
db3de8c: Cleanup (code duplication; extra iterations)
aa23792: platform: specific method deprecated
1bbc497: devkit: another internal inspection; better applicability detection
79870fd: Cleanup (typo; code duplication)
e33f102: devkit: internal inspections moved from common code
7ae5b3f: EA-51122 - assert: TextRange.<init>
cd6bdd2: plugins advertiser: collect bundled plugins names to support ultimate choice
0977aaa: EA-53154 - NPE: CopyFilesOrDirectoriesHandler.checkFileExist
9a70c2a: EA-53127 - IAE: UnknownFeature.<init>
c1c99f3: IDEA-111535 Edit Language Fragment: Synchronization is broken after tab drag
9b30cda: true -> false!
ee5bc42: introduce variable in injected context: allow to check handler in context before starting execution (IDEA-118788)
aadac04: IllegalArgumentException fixed; cleanup
35886ad: extract method: fill elements to before refactoring data (IDEA-119223)
3d2c159: extract DummyCachingFileSystem: put all the weirdness in one place
8f85341: check psi syncability to document before the change and not after, to avoid text inconsistencies between the two
7c16b45: avoid side-effectful and range-marker-polluting JavaCompletionContributor.beforeCompletion when checking postfix template applicability
8f14bea: CR-IC-3920 (postpone class loading until extensions requested)
3de3063: extensions: collection-based sort API
dee2869: IDEA-82840 "test" button added to mercurial config panel
d456fd0: Merge remote-tracking branch 'origin/master'
814a86a: IDEA-112040 Customize Data Views control confused about data object's class
0ffe439: dead code
9a60903: IDEA-94950 Code Style | Arrangement: AIOOBE at ArrangementMatchingRulesModel.removeRow() on removing the last rule that is in edit mode
362fa2c: [git log] IDEA-119247 Use "--date-order" when requesting filtered results
fffa480: remove unused class
e9e968f: Merge remote-tracking branch 'origin/master'
2ed945f: IDEA-119178 Implemented file revisions collecting in batch (for revisions cache)
53a1f57: comments updated
060efdc: Remove debug info.
594dfe8: Merge remote-tracking branch 'origin/master'
62ff983: trivial if inspection merged with trivial if predicate; fix comments again (IDEA-114798)
c379b42: extract ReplacementUtil for igg and ipp to remove duplication
eafb98d: remove duplication
ea17b09: fixed testdata
fa2153d: more javadocs for CharArrayExternalizable and CharSequenceBackedByArray
8f2417b: Groovy: 'null' type in inplace variable introducing
8b6d80a: IDEA-118915 Smart completion for binary expressions
36834aa: Fix blink maven test.
0aafdee: EA-52969 (extension correctness checked on registering; better fix + tests)
4b44633: appendable storage extracted from enumerator
1466df4: Add retina version for executeMavenGoal.png icon.
dbc92b6: EA-52664 - IOE: DocumentImpl.doBeforeChangedUpdate
8d65b72: IDEA-116403 allow add external annotations for library even if its language level is less than 1.5
5bee53f: disable 'change type signature' for classes and other invalid constructs
657cf24: EA-52863 - assert: TypeConversionUtil.getSuperClassSubstitutor
ccad772: show different class pairs warnings
95d0f1c: EA-52980 - assert: CompositePsiElement.delete
b6378d2: EA-53048 - NPE: TestNGConfigurationEditor.applyEditorTo
d0c084d: testng: wrap in command document modification in ui
ac7eeca: Merge remote-tracking branch 'origin/master'
7566ddf: Merge remote-tracking branch 'origin/master'
4d6eee3: IDEA-96199 Debugger editor not disposed resulting in PSI leaks
34b48d1: IDEA-96199 Debugger editor not disposed resulting in PSI leaks
c4df089: DomApplicationComponent.getCumulativeVersion()
2007514: cleanup
c6c3721: test framework: hamcrest sources added
c730f89: Cleanup (test migrated to Junit 4 and generified)
1d944a1: introduce AbstractNavBarExtension with processChildren(..) API
bda26c0: some refactoring
baa4f977: add some words
1be3813: add/suppress <with> for EPs
6c0e58c: done WEB-2093: edit action JDOMUtil.isEmpty
cb8d43c: EA-52969 (extension correctness checked on registering)
e9c97c6: Add utility class for extraction information from X509 certificate
709a619: Use Commons Codecs DigestUtils for SHA-256/SHA-1 calculation
467de96: Certificate warning dialog shows SHA-1 and SHA-256 digests of certificate like in browsers.
e4df134: Add "Show certificate dialog" action to "Internal Actions" group
58f7dd5: Make CertificateManager application component for automatic initialization of default SSL context
8fb8ca23: do not spoil innocent classes
3ddac0b: IDEA-119151 Unable use 'Revert' in Editor Panel
4ec42a6: prevent cancellation upon removing data from indices, to avoid state data in e.g. stub index IDEA-117290
f9ef0bb: CR-IC-3880 (test added)
3b392a6: CR-IU-494 EmptyActionGroup extracted. Both EmptyXXX classes made final, javadoc improved.
70b8663: detect the plugin responsible for run configuration AbstractMethodError (IDEA-119173)
5411708: IDEA-96199 Debugger editor not disposed resulting in PSI leaks
a1ba9d0: CharArrayExternalizable: javadoc, @NotNull
2191ef5: Problem with several users in log filter fixed.
fbb0fd6: IDEA-119021 Wrong accessibility warnings when inlining a static class to anonymous
3ee557a: Gradle: pre-import check added
b20f87d: IDEA-110113 spellchecker always on in commit text field
07c3b8c: extract CheckBoxListModelEditor, consolidate copy action button placement (file watchers vs external tools)
221dc49: fixed PY-11765 @ivar and @type in class documentation cause PyUnresolvedReferences inspection to file
c77d473: refactoring listeners: missed after data (IDEA-119118)
2a1ccb4: refactoringIDs: IDEA-119121;IDEA-119122
466c409: Merge remote-tracking branch 'origin/master'
a3dee86: test fixed
f09134f: Merge remote-tracking branch 'origin/master'
2b27502: include hamcrest-library-1.3 into junit (IDEA-119067)
be1b190: junit version fixed for licenses (hamcrest has new BSD which is weaker than junit!)
2e89dfb: platform: PlatformUtils returned to the platform
93e1f40: platform: async refresh rate limited
fc95c37: ImmutableText implements CharArrayExternalizable
8457954: fix and deduplicate CharArrayUtil, introduce CharArrayExternalizable
b40eb53: revert "Platform: more accessible CaseInsensitiveStringHashingStrategy - available from StringUtil now"; get rid of trove deps from StringUtil
7ab2d0d: Merge remote-tracking branch 'origin/master'
44fd463: IDEA-57553 Optimize display of multiple similar editor gutter icons (e.g. Spring autowiring)
13fdd3e: tests fixed
bdfd016: IDEA-101710 Exception Breakpoints | Any Exception with Multiple Class Filters doesn't work
0230339: test assistance: @TestDataPath propagated to @Parameterized tests
cedfc01: typo
dc6fad7: toString
4945f56: remove unused com.intellij.psi.stubs.Stubbed
5940a39: CR-IC-3901 "mac file chooser must respect FileChooserDescriptor.isFileSelectable" real correct fix
3eb0d48: cleanup
511a608: CR-IC-3901 "mac file chooser must respect FileChooserDescriptor.isFileSelectable" revert stupid fix
0063990: cleanup (commented code)
517d80b: test assistance testdata -> test case navigation: ignore invalid identifiers when probe test names
cdd8c7f: test assistance: related files navigation from test data to test case
ca8fb58: test assistance: run test from test data
502f914: make IDEA-94683 fix controllable via registry (Completion popup loses focus when viewing documentation (sometimes, almost always))
3394c25: dfa: remove unused fields
ef55825: cesure is an english word
0c0e886: dfa: don't walk equals() method argument twice (IDEA-118971)
716fb90: use ContainerUtil
a455773: continue WEB-2093: fix reset, set empty text
57b7ed7: continue WEB-2093: copy action
5bda9aa: cleanup
be3fef5: continue WEB-2093: reset
297908b: init: consolidate control tool buttons orders
54ea61c: IDEA-118477 (optimization: root path is directory)
7eb1c2b: fix test!
4dda4fc: don't modify stdout lines (previously newline symbols handling was postponed)
8692f96: test assistance: navigate to test data from test view also for our parameterized tests
d417690: test assistance: navigate to test data from test view
276b989: test assistance: navigate to test data root
a777bdc: IDEA-118477 (new FS root creation moved out of write lock)
7b239df: allow external documentation over references with multiple resolve
1c993e8: Cleanup (typo)
7ddf6a8: continue WEB-2093: fix editing
9e02c06: cleanup, reuse getItem
5f46a76: mac file chooser must respect FileChooserDescriptor.isFileSelectable +review
fe523a9: overrides
871d53d: continue WEB-2093: up/down/add/remove actions
3969e28: getItem returns Item typed object +review
28b6591: [vcs-log] user-filter: treat empty user name as no filter.
cda9ec5: parameterized test: sample cases
a16d50b: IDEA-118970 (external URL formatting for Javadoc 8)
a1870c6: IDEA-118970 (preparation, cleanup, minor optimization)
fba5ecd: Cleanup (more common code extracted; dispose condition; wording)
ee40019: [log] IDEA-116242 Allow multiple users selection in the log filter
be0561a: 'writeln' added
2665a70: Java surrounders: if and not surrounder should be able to handle java.lang .Boolean expressions
d35b827: Java surrounders: check surrounder availability in tests
d8aa01e: remove unused IdSet
e3ec6fb: extract ReflectionUtil.getMethodDeclaringClass
60c6cdc: propagate multiple locations from tests view (IDEA-114248)
6d8c0f0: junit: restore MethodLocation after extracting parameter from ParametrizationLocation
2a4598d: junit: do not suggest to choose what to run when parametrization was selected
b6e117b: junit: search for children with initial runner
2344b22: junit: accept @RunWith on supers
67de9a4: remove unused suppression
64ae19c: deprecated doTestAll() outside of @Parameterized test
9564434: EA-52866 - NPE: DefaultChooseByNameItemProvider$.compare
76857c0: add read action (EA-51111)
31e5a94: use ensureValid (EA-51644)
01617e9: testall -> parameterized (I)
0a141f3: normalize tests
354936f: normalize tests
d9de437: Merge branch 'master' of git.labs.intellij.net:idea/community
8eae751: IDEA-119097 - cloud run-configs: deployment source change does not update error/warnings
0974ff1: StartBrowserSettings — avoid boilerplate code — use our handy XmlSerializer ability to specify string converter for bean (Attribute and OptionTag annotations) use member name as default name of attribute (Attribute annotation) ability to serialize/deserialize/use private classes (is not used in production code yet, but useful for tests/custom converters (web browser converter is public))
1944ad3: Merge branch 'master' of git.labs.intellij.net:idea/community
b073865: IDEA-119096 - Warning/QuickFix in cloud run-config when module name != app name
40847ee: Platform: more accessible CaseInsensitiveStringHashingStrategy - available from StringUtil now
e7154ee: simplification
9eef5fd: Cleanup (common method extracted)
0aac945: IDEA-119047 (MidnightBSD test)
277d2d4: platform: fake root dropped (test update)
dca3a8e: WEB-10517 warnings on startup
a512559: nullability
a24df11: #WEB-10492 fixed
b84ffb1: platform: fake root dropped
12617f2: junit: process Parameterized inheritors
779d2fd: fixed PY-11705 Nothing is selected by default in Docstring format field
d4a34fd: Merge remote-tracking branch 'origin/master'
28f5328: added special case workaround for IDEA-111701 according to CR-IC-3788
f1b481a: tests migrated to new wizard
a7f27f7: avoid exceptions in case of empty sourcemap avoid to create class only for configuring properties
1d52f11: JavaEETemplatesTest for new wizard
78f84c6: Empty Project icon
32269b8: IDEA-118436 Resource Bundle Editor converts UTF8 characters to ASCII even in UTF8 file
36cce0d: IDEA-116620 Some characters cause cursor to be misplaced
1b0b274: IDEA-118187 Change font size in run console only changes line height
1acb27b: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash
de74e3b: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash
2be15f5: IDEA-112730 PhpStorm goes crazy with collapsed comments and soft wraps until crash
e493f95: IDEA-112104 "Find Usages Settings Dialog" button re-emerged in "Find in Path" results
69cbd31: make show usages consistent with Find usages
de83cb0: do not show class icon for 'Find In Path' usages
ebd96b1: cleanup
13d7491: notnull
2c67d14: IDEA-117386 Introduce field/constant with it's class name
bcc9ac5: IDEA-117586 translation switch to if-else sequence
3a5fcae: fix flow searching
8301e91: rename file to class name intention now shows a new file name
ef9cc2e: IDEA-117586 invalid 'continue is unnecessary' inside case sections
412f350: WEB-825 Paths relative to the 'main' script aren't supported for RequireJS projects
2939027: fixed PY-11673 Error on project creation
43558ef: Prefer highlighting passes for the selected editor (IDEA-23831)
e61f6f2: Merge remote-tracking branch 'origin/master'
de36aec: updated test data for python3.4
b3ee771: IDEA-74428 Ability to turn on log debug categories from the GUI
899b70e: cleanup GroovyDocDialog
bac6ea3: EA-52747 logging
4f7d13c: EA-52865
d4bb110: Remove 'Help' action from maven toolbar.
09c14fa: IDEA-118747 Show IDE icon in the libnotify notification
79c397b: adding custom templates
0ad2452: no icons for subgroups
48c6f72: javadoc
6ef1f3d: test fix
6017ab7: IDEA-118708 libnotify is not avaliable in 32bit java 64bit OS configuration
1fc8800: show warning when generated source file is edited (IDEA-115757)
f6e9d9d: Fixed IDEA-116006 Eclipse code style import: import the same xml does not pick up changes until manual synchronization
419f61e: IDEA-115935 nulls and void in assignments
8d1e4ab: dispose injected documents on close
3575ed8: cleanup, made fields final
56354fd: performance: do not rewrite the whole file
f3bf9d0: notnull
938371b: optimisation: do not restore the element
1f869df: notnull
92d3e78: cleanup
7db9b0c: EA-27319 - assert: FoldingUpdate.getFoldingsFor
dc73830: IDEA-118394 "Delete to line end" missing
c323950: IDEA-118696 Replace with regex: IOOBE at SegmentArray.findSegmentIndex()
9dd6f07: SASS/SCSS: make functionBody lazy
1261c24: disable 'new' postfix template for a while again
6ac4b44: Add debug info to investigate blink test.
715a143: Merge remote-tracking branch 'origin/master'
cc39211: dispose caret
a9768ee: Fixed IDEA-117788 Eclipse code style import: continuation indent is imported not multiplied to tab size
f4038db: don't run batch inspections and search for duplicates in generated sources
d3a97cf: IDEA-114811 Mouse drag over left gutter below the last line: IOOBE at SegmentArray.getSegmentStart()
b4e61bb: Added missing license for ANTLR 4 Runtime library
17b4dfa: add http-cleint 4.3.1 to dist +review
97a168d: EA-52850
063e8df: sources for Groovy 2.2.1
5c66005: attach messages to root node if no running node found
fe19e6a: Move WhitespaceBinders to core-impl
c395dcf: [log] Flush the Hash->Int persistent map more often
76acb3e: [git log] Don't display "index" and "stash" pseudo-commits in the log
f1a1706: already disposed
e3a8369: IDEA-72835 yet another attempt
8c00119: show the containing file if ambiguous method ref occurred
d70cd08: notnull
8cbb8a3: notnull
43cca9b: notnull
ab77496: diagnostics: show the reason for document lock
8734302: notnull
0912313: IDEA-118701 Multimodule project imported into IDEA via opening project file gets incorrect project name
6351d04: IDEA-118613: catch all possible exceptions, that may be caused by corrupted storages
933abc6: used assertion to check fold region
64575f6: take words from other files if there is no variants from current file at all (IDEA-117511)
fb7a33b: default highlighting level for generated sources corrected
9d52b67: IDEA-117452: Generated folder should not be reformatted/imports-optimized on batch actions and on pre-commit action
92caef0: reformat code: exclusion project files from formatting simplified
20a3dce: IDEA-117724: source files under "generated source root" should not be inspected
6fe9437: groovy 2.2.1 once again
b4d35ba: WEB-8262 Comment with line/block comment STILL doesn't work on HTML in ASP file
6018640: WEB-10387 Mocha console log statements are not correctly aligned to their encasing tests
975cfe8: IDEA-96131 Java: Braces placements don't work as expected for `Next Line` [CR-IC-3694]
8fb92c4: more compact todo storage (since we advanced the version anyway)
caa3132: WEB-849 "Comment with line comment" on empty line in <script> block generates HTML instead of JS comment
9d00810: WEB-6700 TODOs not recognized on multiple level language template
4548db3: test fix: explicit encoding is required
5928448: Extract common used WhitespaceBinders
9e6c90a: Prepare css module for upsource: move indent parsers to core-impl
3dbc819: SASS: make declaration block lazy
9b111fe: reduce getNotNullHelper usage
15c7971: deprecate getNotNullHelper
ad17a0b: support keywords storage
a622b21: IDEA-118587 IDEA may not exit with black window
aa82d2a: WEB-9517 Npm: Error loading package list
892dab2: updated code compatibility inspection
7b0e37d: Merge remote-tracking branch 'origin/master'
4b92724: one more fix for IDEA-111701 Emacs: pressing Ctrl+k several times should add lines to muti-line buffer
c2e7ccb: App Engine: refresh library roots when new module created (IDEA-71691)
124408c: IDEA-71691: appengine facet doesnt bring in required libraries
b100613: IDEA-115761 MakeInnerClassOf refactoring should probably exclude target classes from GeneratedSources roots
d5de3de: cleanup
5623916: [vcs] IDEA-95729 Don't ask about adding new files from patch to VCS
76665be: custom options panel leak fixed
955220b: "Configurable Project Types"
b801015: [vcs] IDEA-118644 Fix apply patch for new file in new folder + test
8420f9e: [log] IDEA-115423 Limit number of commits requested when filtering
92eb361: IDEA-93034 SQL: MySQL: erasing the first backtick could erase the pair
20604f7: in case when some output and source roots intersect: do not stop rebuild if caches version is advanced (IDEA-118613)
91047f0: external build: throw BuildDataCorruptedException instead of generic RuntimeException if caches are corrupted
cd70918: Groovy: don't skip 'null' type in inference
c482422: IDEA-118333 Groovy: Extract Parameter Refactoring: "Replace all occurrences" replaces only current occurrence
1533ed8: IDEA-116621 Groovy: Extract Parameter Refactoring: 'Replace this occurrence only' replaces all occurrences in current method [^peter]
a541ab1: ability to copy status text
7960886: netty 5.0.0.Alpha1
b021743: Add extra test for new-expression template
4d61bc1: Postfix: enabled new-expression template
7af3bf2: separate checks if compiler is enabled and compiler api is supported by compiler implementation
3feff30: IDEA-118675 - Errors in app server run configs not shown in UI
41db6bf: less garbage
af79d47: notnull
b963343: cleanup
62b2dde: notnull
9930be0: cleanup
de7798b: gant in libLicences.gant
d0f541a: Merge remote-tracking branch 'origin/master'
17e6328: added test for IDEA-111701 (2 editors for 1 document)
b8e4600: Fix JavaAutoPopupTest: test live template without description
7c4b4a1: NewProjectWizardAction removed
4f93b7d: ProjectTemplateList
c3ca08b: description font
4130824: new project wizard in work
00dda2f: IDEA-118419 Keep caret on the screen while changing font size
e23693c: IDEA-118495 (Cyclic package dependency inspection is unusable.)
878641fc: move test to correct location
9edbf08: Fix live templates tests
6b54183: Bug fix: check not-null +review CR-IC-3798
68b7ce4: fix and clarify "Cyclic class dependency" inspection warning
6bd22b4: WEB-10360 Javascript debugger with non unique file names
d94c9a1: IDEA-118601 New Module: Maven: click on "Create from archetype" reverts typed coordinates +review CR-IC
d25214a: Add debug info to investigate blink test.
1a0c297: WEB-10367 JavaScript Debugging in Firefox hangs PhpStorm
558b4ba: overrides, prefer to use our utils methods
668b0c1: Merge remote-tracking branch 'origin/master'
7e3d1ab: static super methods: java 8 interfaces
1e147d8: Cleanup (formatting)
f45f27f: java: incorrect parsing of bounds in class files fixed
6d85c55: java: extra whitespace in class decompiler trimmed
e90c678: Groovy: reassigned vars without closures
89e472e: clean up literal type inference
3d634e4: fix performance problem on 'new Object() {}' test code
0a5485b: IDEA-118487 IDEA should suggest downloading missing plug-ins for unrecognised artifact configuration
59d1d4c: added copyright
43b7c90: use getElement instead of getParent
41ccbd2: EA-52292 fix (PHP template inside HTML comment case)
f6a4f20: IDEA-118419 Keep caret on the screen while changing font size, IDEA-117005 File can be scrolled automatically on setting a breakpoint
544d21f: ListTemplateAction should provide custom live templates
60a5c60: Extend block support API
107e9ae: IDEA-118569 Add quick doc for live template lookup items
5735d5c: Merge branch 'python-fixes'
9d07fd6: Introduced Bitness and JdkVersionInfo combining version and bitness
99aaa2c: lower the dfa inspection time limit in analyze mode (IDEA-118567)
461cd32e: plugin advertiser: do not suggest to update from ultimate to ultimate when 'bundled' plugin is not yet available for current version
6eaeefa: rename: do not show collisions for static methods rename in interfaces (IDEA-118577)
6565df2: untie static methods in interface hierarchy (IDEA-118577)
3d7a8fb: ensure public inner inside interface (IDEA-118564)
01753c7: IDEA-118588 (Concatenation with empty string fails to fix an expression)
9e8ef92: Added error message for missing python-skeletons diagnostics (PY-10411)
183e416: re-applied darcula changes correctly
8086000: IDEA-86907 Fold/unfold for the last node is incorrect
3a3bbff: Made builtins cache valid only if it has a valid reference to the builtins file (PY-11665)
5c0518e: roll back spy-js
b83d875: Merge remote-tracking branch 'origin/master'
93b3fcc: fixed IDEA-111701 Emacs: pressing Ctrl+k several times should add lines to muti-line buffer
c21cd02: EA-35422 - IOOBE: EditorImpl.offsetToLogicalLine (from debugger)
6d025c1: IDEA-97930
8ff12a4: cleanup
016ee36: cleanup
bb63a9b: EA-52137
5a86a94: EA-52726 (assert: ComponentManagerImpl.getComponent)
4cfd001: correct dependency type for gant
ec97f82: IDEA-118138 don't highlight closures using unassigned vars
5b8d6b2: IDEA-117966 introduce variable from unresolved reference
1dd4665: dfa: don't grow stack infinitely on &= (IDEA-118522)
a8861db: corrected gant
dfbbfe2: revert groovy 2.2.1
cf379f3: Merge remote-tracking branch 'origin/master'
77bf85b: update gant according to groovy version
87b06c1: disable 'new' postfix template for a while
62dec2d: get rid of GrBinaryExpressionImpl inheritors in code base
0ac89c0: don't run groovy shell if there is no full Groovy lib in a module
53ea375: groovy 2.2.1
12fd8d4: [log] simplify
4d55fdd: OutputSuppressed option added for HgCommandExecutor, style changed, unnecessary parameters removed
71f457f: Style: unnecessary array with indicator output command removed, myShowOutput field used instead
f1c78e1: cosmetics: revision hash template changed to long.
669ae41: + "trie"
2acfe62: drop cls navigation element cache on the navigation element change
2c458f1: avoid creating string garbage when searching for external annotations
ec01e46: free the memory used to build RootIndex
b83ecae: Do not throw on quick-fix creation, just return null
718d70f: use ctrl(meta) + shift + K shortcut for push
2c70839: use ctrl(meta) + shift + K shortcut for push
181d69e: % sign is useless while indexing
3aac7ab: don't show active file in recent files section
2f2154b: assertion added to check that 'registerOutputDirectory' isn't called for inappropriate targets (CR-IC-3742)
317be6e: IDEA-104706 Remove currently active file from "Recent Files" popup
054ec7e: cache cls navigation elements that are not so cheap to calculate each time
34ab25e: [log] Take END_COMMIT_NODE as well as COMMIT_NODE
cb5ee86: [log] Fix identifying root of Node
23583d3: [git] Wrap the VcsException not to loose the cause
2beff60: [log] Flush & Close persistent enumerator on dispose()
9a92cb9: [log] Supply correct commit object to getCommitData in DetailsPanel
7e9eaf9: fixed problem mentioned in CR-IC-3742
77792a3: Show unnamed branch heads without bookmarks and not current revision implemented.
32ab1db: Parents revision hash template changed to long.
4e16c417: Multiply revision node presentation in HgLog for only one revision fixed.
d4f5e53: VersionComparatorUtil.comparePriorities() simplified
fd3bc7f: Gradle: GrShiftExpressionImpl usage removed
0380bcf: constant-time ModuleManager.getModuleByFilePath
1feb27b: lazy sem contributor loading
628ff78: BackgroundTaskQueue doesn't postpone onSuccess/onCancel until next awt-event in test mode
be07183: BackgroundTaskQueue.waitForTasksToFinish API
d3be23f: check context for nullability
242a5e3: Switched back to char-based triple quotes detection for docstring element types (PY-11585)
fb53d06: can be final: ensure non final for base of anonymous class (IDEA-118493)
90d256c: allow autocompletion in dumb mode if provider is dumb aware
767d1ab: cosmetics
8d996fa: IDEA-118552 Generated ANT scripts do not honour cross-compile settings
f310fee: use folder icon for groups in Menus and Toolbars configurable
4e60af8: NotificationGroup constructor shouldn't require an initialized Application
0f2dda4: save RootIndex memory
93977b5: some cases to avoid Document.getText where CharSequence is enough
5c51405: uncomment DirectoryIndexTest assertions
b3a6dbb: free RootIndex memory on project dispose
aa52dce: don't fall into recursion while resolving annotation name
2ecd26f: Groovy: assignment type inference
7c2363d: Groovy: operator resolving & type inference
e48edcd6: save applicability in GroovyResolveResult
b9531f2: simplify type inference for unary expressions
dc77905: revert: IDEA-117864 optimize reference search scope
0f2e2a5: Copyright: commit document after comment updating
1684f09: Emmet: show 'Edit emmet settings' for emmet lookup item
a71af7f: Postfix: rename 'Edit postfix templates settings' action
e647f6f: Do not populate custom live template lookup with 'Edit live template settings'-action
e03fa18: Show "Split mode" action for sliding toolwindows.
32133c0: IDEA-118096 Documentation popup not usable because of Jetbrains annotations
c52f140: cleanup
c0a94d5: notnull
aa678f5: cleanup
11dad8c: optimisation: do not load document to check for isReadOnly
5202195: notnull
53fe9df: IDEA-118371 Partial find occurences disappear with 'group by ...' button
530c800: spy-js plugin initial commit
58e433a: IDEA-118496 disable boolean param inspection for library overriders
d35fc05: run manager: do not override shared status from default configuration when existing configuration is checked e.g. run from tests view
fa52498: junit: reject to start when no tests were found in package
7c4a448: add assert: respect initializer in ForStatement
ab1bebf: IDEA-118420 Better wording for quickfix to 'Declaration can have final modifier' analysis
fda7595: more precise quick fix name (IDEA-118416)
1da12c6: Cleanup (PTY runner decoupled from GeneralCommandLine)
f34a024: add missed src jar
d2e8aa1: Cleanup (duplicate)
2858767: platform: incompatible KTerm option stripped
4eb09a2: ui: correct icon for facet editor panel
c450665: IDEA-118429 (IDEA incorrectly suggests to remove unboxing)
bcebafd: polish "Difference using "Open in browser" vs browser icon" fix — we don't need to pass virtual file now
d4d4ad5: restore WebBrowserUrlProvider API
4777bfd: polish "Difference using "Open in browser" vs browser icon" fix
9348d2c: polish "Difference using "Open in browser" vs browser icon" fix — better name of context class
6b1ebcc: polish "Difference using "Open in browser" vs browser icon" fix — better name of context class
8e12a5e: use httpclient 4 in platform-impl
4c35a0c: don't use deprecated SimpleNodeRenderer
2f71cbc: GroovyDslScript: rethrow PCE
11f366b: more dfa predictability by using ordered data structures
0dc6c2b: more diagnostics and recovery on strange gdsl NPEs (IDEA-118457)
7cde1cb: VfsUtilTest.testPresentableUrlSurvivesDeletion
811cd43: New toolwindow animation
4ffacb9: commons-logging-1.1.3
52e167f: new project wizard: sorting groups
3206d79: Cleanup (non-public properties hidden)
9415eb8: platform: shell environment loading suppressed for tests and command-line apps
1b1bca4: IDEA-94565 (misleading "call to overridden method 'clone()' during object construction")
52794b6: Fix JavaAutoPopup test
509cbce: tests fixed
af49f19: WEB-9566 Debugger: optionally ignore certificate errors
70d4555: don't use deprecated class
402c994: cleanup
ee39199: better way to instantiate PersistentHashMap
1fa2163: IDEA-118029 Pressing TAB while having portion of a line selected causes indentation
ca4f7bc: IDEA-118063 Gradle: 'Add gradle plugin' action: 'Choose plugin' popup has lots of not clickable links
985ec94: IDEA-117792 Gradle Run/Debug Configuration: support adding Gradle specific parameters. Fix after review.
77c4739: IDEA-117380 Can't remove multiple Maven projects at the same time
60fba04: Postfix templates: rename all 'completion' to 'templates'
6b1a7b6: javawriter library
4cc2790: postfix templates cosmetics
09948c0: WEB-10158 Difference using "Open in browser" vs browser icon
9ef929f: Gradle: fix wrapper check
43d9b27: external build: added method to register output directory in source-to-output mapping instead of registering individual files to reduce occupied disk space (ZD-16651)
42ef854: added option to disable framework detection for all frameworks in whole project
ceee385: ! alias for not makes bulenkov happy
c138886: cleanup
d0eb168: made fields final to prevent some nasty bugs like EA-52519 - IAE: TObjectHash.throwObjectContractViolation
47267dc: extract delegate for IntroduceVariableBase.collectExpressions
8f82a73: get rid of JavaSurroundersProxy
6ee5fbc: IDEA-117792 Gradle Run/Debug Configuration: support adding Gradle specific parameters. Fix after review. + fix bug - http://youtrack.jetbrains.com/issue/IDEA-118470
3c774d6: Merge branch 'master' of git+ssh://git.labs.intellij.net/idea/community
dce2c17: move postfix templates to java-impl
d218b10: fix division by zero in IDEA-118443 UI hang on console hyperlink calculation
da559b8: fix some constant conditions concerning VirtualFile.getPresentableUrl
8286229: cleanup after merge
935cfc5: less compilation progress spam about groovy files
d244f07: more groovyc logging
347356c: IDEA-118443 UI hang on console hyperlink calculation
57cf9ce: control flow: visit assignment lValue only once (EA-51083 - ESE: Stack.pop)
746901e: IDEA-116947 Unqualified call NPE false positive with contracts
ea2b802: IDEA-118397 Resume build not working
23fc388: Merge postfix completion plugin
7865b3e: removed all data but folder to move
cac63bd: added rearrange checkbox on reformat code action for directories, modules and multiple files
b529f23: EA-52540 - AIOOBE: FunctionalInterfaceParameterizationUtil.getFunctionalType
db5abb5: open editor explicitly, do not rely on focus settlesDown
5d49870: restore classes in nav bar (IDEA-118168)
efb5693: IDEA-117792 Gradle Run/Debug Configuration: support adding Gradle specific parameters. Fix after review.
1208162: Merge remote-tracking branch 'origin/master'
9376c69: fixed PY-11654 Move Statement: IOE at com.intellij.openapi.editor.impl.DocumentImpl.d
2a33922: com.intellij.execution.ExecutableValidator.ourNotificationGroup
d255c5b: dfa: make state merging result predictable when removing a!=b and a!=c && b==c, don't restore a!=c
ea2df38: fixed PY-11610 Django johnny-cache breaks django_test_manage.py
e7d7b61: Code style, alignment
188b963: IDEA-118111 (OpenJDK 6 check made strict)
4a221d0: update stubs per file type reverted
835ed38: IDEA-102942 Wrap always Chained methods calls over-format simple operations
16670a6: Slowpoke plugin compatibility restored
2f10822: 2x more compact mapping storage for 7bit ascii paths [r=Eugene.Zhuravlev]
c808606: cosmetics: "other head" text duplication removed from hg merge dialog
df31d58: nn alias
5ade729: IDEA-118292 (process idea.properties in declaration order)
acc2554: avoid new CharSequence allocation inside document if possible
4bb3242: no smart icons and no parameter info in power save mode
adaceb9: IDEA-118281 Enable SystemNotifications.systemNotify() on Linux
5908944: platform: suppress update checker in headless mode
15de064: methods chains completion: fixed concurrency error and new indices creation refactored
ec8b243: IDEA-117297 @Contract doesn't play nice with @NotNull/@Nullable
8bca4a6: dfa: combine merge by equality and type into a generic relation-based merge
b75ba04: disable "increase language level fix" in libraries (IDEA-118378)
f3e093b: junit comparison: pass null implicitly (IDEA-118372)
a7df7ea: Cleanup (deprecation; dead code)
728f82a: platform: update check and notifications reworked
9efdbf5: Merge remote-tracking branch 'origin/master'
46fb4bb: NPE
4889341: @NotNull VirtualFile.getPresentableUrl (IDEA-117476)
6a771e7: preselect exact prefix match in autopopup completion (RUBY-14617)
c0860be: Find in Path notification group
da3be53: make com.intellij.execution.ExecutableValidator.myNotificationGroup static
7c9f008: IDEA-116806 Messages pane does not copy what is selected
b33d419: dump lookup weights in tests when the selected index doesn't match
d245447: Canonize .instanceof template line a bit
2c9fad1: IDEA-118116 (Intention to convert existing assertions/@NotNull to java.util.Objects#requireNonNull(T))
c61bbb8: Darcula: combobox as cell renderer/editor fixes
a64047e: fix default size of SourceMapInspector window
85700e4: lazy class loading for PtyProcess (r=Eugene.Zhuravlev), 2
e436b16: EA-52297 assert: CaretModelImpl.moveToLogicalPosition
60cf897: IDEA-106300 Sometimes PhpStorm doesn't exit rectangular selection mode on escape.
26a7d57: IDEA-118245 Retain the last used command line in the Execute Maven Goal dialog
77fcd32: [log] Correctly load details of commits around the selected commit
05b51ca: Merge branch 'no-unresolved-without-sdk'
9c3af9a: Use default Python interpreter from PATH on opening a directory for the first time (PY-4733)
a1a68a8: fixed PY-11581 RST: Header is not highlighted if there is a space after separator
ebc380b: CR-IC-3665#c19556
84cbbc9: fixed PY-11588 "Instance attribute %s defined outside __init__" in static method
ecafaa5: destructor rename fix
44f0697: fix ClassCastException: com.intellij.openapi.fileEditor.FileEditorState$1 cannot be cast to com.intellij.openapi.fileEditor.impl.text.TextEditorState
5753b4f: quick evaluate expression for sourcemap backed/dart debugging
a9f950d: cleanup
7e82f90: overrides
eeb5b4e: Merge remote-tracking branch 'origin/master'
f36a786: Delete unsupported features from description
a239ed4: fixed PY-11617 Nosetest runner: simple function tests cannot jump to source
451f0f5: Fix while example link
37dc827: Add changlog, change version, add missing template description in readme
6731e36: Add examples link in README
433a9d8: Fix notnull gif link
132cb0c: Add examples page
3688a79: skip invalid highlighters (EA-37197) - 8K reports!
67d004a: Switched to synchronized count of running Python skeleton generators
e84d8d8: Add gifs
362a60b: Allow to disable configuration of language level via "idea.maven.configure.language.level" system property.
5674820: Don't add python-skeletons to Python paths during skeletons generation
e234e09: Don't show python-skeletons path in the Python interpreter paths tab (PY-11218)
a78597b: Don't report unresolved references and unused imports during skeletons generation
1e4e54d: Fix maven tests.
33c1579: notnull
fedfba1: EA-52689 - IOE: DocumentImpl.doBeforeChangedUpdate
fd6e27f: select word works in console
37823aa: Fix nullable issue
dbcb907: update progress on test done (finished, failed, or ignored), not on test started
3e3fc75: inst alias works
fbbb855: files compiled on first round may require additional recompilation on the next round (second part for IDEA-116914) constant search on the IDE side rewritten: only direct dependencies are returned for each search round; all transitive dependencies will be additionally handled by make
eebad48: IDEA-118318 (Pointless Arithmetic Expression Inspection: false positives)
d85faec: remove braces
2218cb1: Merge remote-tracking branch 'origin/master'
0dc9c17: Make weaker declarations
30b933e: aliases initial
c5ffafa: drop empty line
cc3d204: @NotNull
6e55733: support space between class and caret in IDEA-118194 complete statement works strange for inner classes / enums
fbf6511: reuse empty ImmutableText instance
5a69aad: don't build dom on dtd files
1f13be4: preserve order in FindInProjectUtil.getLocalScopeFiles
772e035: propagate available intentions to find action/search everywhere (IDEA-117167)
bd4018c: NPE
4765a6d: ensure project not disposed
293de59: EA-52462 - assert: SelectionModelImpl.doSetSelection
2f164b2: IDEA-117756 File structure: editor window is not scrolled to the chosen element if latter is folded
efc25bf: Return var template to readme
e04907f: Update example image
3fb8600: Remove redundant dots and parenthesis from lookup elements Remove unsupported template from readme
730c1f3: Rename foreach template
857aa95: MEGA CLEAN UP!!!11
b958846: Delete unused tests
84c3770: Reformat tests
934a752: Reimplement indexed-for templates
9f7fb6c: IDEA-116383 cannot reconnect Some RuntimeException contains not serializable class 'org.apache.maven.model.building.DefaultModelProblem'. So IDEA throw java.rmi.UnmarshalException caused by java.io.NotSerializableException.
d159e53: Merge branch 'master' of git.labs.intellij.net:idea/community
e3a5672: Cloud integrations - search for git remote by url
75e0a96: Use argLine parameter of maven-surefire-plugin when start JUnit process. +review (IDEA-118176 Failsafe plugin argLine should be taken into account when running integration test)
3096c5b: Merge remote-tracking branch 'origin/master'
27a4b18: suggest to extend class from Throwable when it participates in throw statement (IDEA-118215)
05d3b27: IRV: ensure selected, add empty text (IDEA-117972)
a257dc4: IDEA-118256 Introduce Constant/Field should insert spaces between generic parameters
67edbe5: method may be static: process default methods (IDEA-118272)
9e9ad29: more compact code
a07a0f2: better method name
ed529d5: IDEA-118053 Editor "deprived of mind" when editing settings.xml
75ec80e: IDEA-118266 time measurements for all Mercurial commands added and log command debug output suppressed.
42b483f: remove unused properties
bbc19f5: IDEA-118181 (false positive "number of placeholders does not match number of arguments" for multi-catch)
0035160: IDEA-117921 JRadioButton icons don't display in plugin forms on Windows/Linux.
9833bb1: Merge branch 'skeletons-in-background' into no-unresolved-without-sdk
96c8bca: lazy class loading for PtyProcess (r=Eugene.Zhuravlev)
186cee5: disable identifier highlighting in class files
4af1c4b: notnull
4247710: IDEA-117864
c741bf4: diagnostics for EA-52496 - SOE: PsiUtilCore.getLanguageAtOffset
73fd43a: Return unknown return type for generator functions if the built-in generator type is not found
35cf414: Don't report unresolved references and unused imports if the project interpreter is not selected (PY-11589)
9a71943: [git] IDEA-118067 Correctly identify if Update Project should rebase
7536b4d: [log] IDEA-115407 Disable graph-only-actions if there is no graph
c6c69d4: [log] IDEA-115568 Don't crash if the log is empty
7ca0d0b: redundant cast: ensure that temp variable would have unique name (IDEA-118197)
a449241: distinct prover: distinguish types when type parameter has bounds (IDEA-118037)
0d7a908: introduce constant from literal: ignore null anchors for non-physical elements (IDEA-118166)
c53f3ca: IDEA-12202 Refactorings do not update unused symbol dependency injection annotations
2bf19b4: IDEA-116593 improve choosing of Android and Java SDKs when creating new android-gradle project/module: choose only Android SDK location (if we don't know it) on first step, not build target; choose Java SDK (if there is no any) separately, set it as project sdk and as internal jdk for newly created android sdk entities
58aabd6: correct check
e78399c: VcsRoot detector tests updated
a3946b7: Call a static method via its defining class, not its subclass
db8ec59: Removed unused PythonSdkType.switchPathToInterpreter()
0b2b95d: Nullity annotations for overridden methods
03035cb: Moved skeleton generation progress on adding a Python interpreter to background
3a22d6f: DOM index: @StubbedOccurrence
79a529e: use direct call to storage.resize() so that IOException is not masked with RuntimeException (IDEA-118107)
a1a37eb: fix find in path NPE
5e3e92e: GroovyCompilerTestCase: guard against executor errors resulting in a semaphore never released
cdfd0d8: make "Invalidate Caches / Restart" action discoverable by entering "restart" in Goto Action (IDEA-117839)
ea159c5: IDEA-117362 Find/Replace in Path does not work for current file if current file isn't part of the project
924e475: IDEA-118100 Annotation enum attribute auto-completion
3874a1e: RootIndex: allocate a bit less memory, clarify a condition
7554e69: BracePair.toString
581851e: IDEA-116695 Rename "Reopen" action to "Reopen project"
1e6cb22: IDEA-118194 complete statement works strange for inner classes / enums
cef372d: IDEA-116944 Constant Conditions & Exceptions doesn't report if statements with literal true/false condition
c50714a: consider parentheses
7e72b91: [log] IDEA-115901 Keep selection between refreshes and filtering
8163d04: [log] rename type parameter to a more descriptive name
e1145ae: simplify and test
b89c26e: simplify and test
6131aad: IDEA-78206 Constructing 'mailto' link -> cannot resolve file 'mailto'
29bb231: Cyclic Expand Word leaves word highlighted (IDEA-115727)
0d501e2: Platform: AppCode and CPP tests autodetection
259e062: avoid defensive text copying in LazyParseableElement if it's already immutable
b9a7bc3: avoid leaking too many components by tracking a limited number of focus requests
a900497: optimizing ImmutableText.delete for empty ranges
4677312: DocumentImpl: DRY, cache getCharSequence().toString()
e0c5940: fix presentation in inspection's Browser fixed (IDEA-118110)
fa5241a: add owner dependency when type parameter extends (IDEA-118093)
c6757f1: #loc removed
6f5e28c: show param info: highlight overload vararg method
8db186e: IDEA-24924 Background task "Indexing" could use % sign
2e3a0d8: IDEA-117127 Editor: Throwable on Select word at caret inside plain text
6b825df: IDEA-117476 "Project Files Changed" message includes null
1ef83d5: IDEA-117682 Annotation parameter completion: show defaults in variants popup
82953ab: IDEA-117857 Add exception type variable to "Catch Statement Body" template
5ae8f86: IDEA-117947 Method completion in import static adds parentheses
41f6f858: IDEA-117831 After deleting last live template in a group, I can't click OK.
3880c45: IDEA-118082 "Constant conditions & exceptions" warning expected inside local class
9729ea9: IDEA-118159 "Search Everywhere" inconsistent api on ItemPresentation
0e548a8: - detect proper encoding for html5's <meta charset="charsetname"> - [performance fix] avoid (light) parsing of html content if there is no charset\s*= pattern inside the string
5e016d6: Switched from showing balloons to logging errors for serious skeleton generation exceptions
08677f9: REGISTERED state added
423cd4c: rewrite for template
41c98e5: Added ellipses for skeleton processing progress messages
e104209: Merge branch 'pieae-in-python-builtins-cache'
580df9c: BuiltInWebBrowserUrlProvider should not return list of urls — prefer custom
b5d9c7a6: Fixed PIEAE in referencing obsolete cached PSI elements for built-in 'str | unicode' type
4dc9e51: Merge remote-tracking branch 'origin/master'
aa007bb: treat enum constructors as private (IDEA-118133)
140b91e: method references: smart completion to filter by return type
df47230: disable lambda completion after inserted qualifier
3c20d47: extract superclass from anonymous (IDEA-115663)
4268473: prefer keyboard shortcuts in Find Action (IDEA-115648)
1958e9a: introduced cvs.roots.refresh.uses.vfs property (true by default) and uses its value to refresh cvs roots after update using vfs to avoid performance problems (IDEA-112132)
1b7d320: rename
a948c54: test updated
831bab4: Merge remote-tracking branch 'origin/master'
0d2810b: Rearranged fields and constructors
eea6898: fix and improve intention description
7cbd227: Removed unused PyBuiltinCache.isValid()
43d1fe1: Removed stdlib type cache unused after the switch to python-skeletons
6f415a8: Call static methods via classes where they are actually defined
0008bb2: fixed PY-11594 New Project: selected interpreter is not set as project interpreter when attaching project to already opened one
2e0f889: Style
b13cb70: IDEA-35996 Ant integration: provide more informative message in case ant file execution is stopped due to unknown command line argument
5ea95e3: if IDEA sees text/plain and extension .java, perhaps it should infer that it's actually Java, because not everyone will set up their HTTP servers with language-specific mime types? (Particularly when following a URL to a source file in a sourcemap.) +review
d2bfd2d: regionMatches insteadof substring
a628d6f: better name
db99de4: remove unused import
646bc62: remove old tests
cca7354: IDEA-106716 Don't steal focus. Let IDE be active on startup.
c558b87: rewrite new template btw, I'm to lazy to rename the tests
64973e3: IDEA-118086 (Duplicate condition inspection is triggered on unresolved code)
ea200a4: ImmutableCharSequence cleanup
fb1b5fa: optimization for ImmutableText.concat(<empty seq>)
96c0ff9: chrome context menu action: Inspect in IDE
cf3e2c0: Remove inspection whose warnings are now covered by "Constant conditions & Exceptions" (IDEA-118025)
e610603: IDEA-118102 Maven: artifacts name not properly generated from pom in IDEA 13
237625e: IDEA-98419
cf82fe3: cleanup
447a3cb: notnull
92c2534: notnull
cbd2b73: IDEA-58977 Regression in Copy Line behavior
661b6b4: IDEA-58977 Regression in Copy Line behavior
dd41fbf: IDEA-117828 Groovy console: execute groovy code shortcut changed back
c1f377f: Groovy: review reference search scopes
da3cbf3: IDEA-84166 Support "CTRL+H" on class in .xml file
59b2c02: cleanup
7261323: IDEA-106300 Sometimes PhpStorm doesn't exit rectangular selection mode on escape.
fec1304: Gradle: null-check for project.getBaseDir added in a post startup activity
2143a06: use method instead of manual hack
e766068: better combobox rendering on aqua: no focus ring around combo button, fixed 1px size difference
cb1e878: Gradle: notification component, removed duplicate notification check and code cleanup
77ab090: cache Document.getText
9ddb619: compare char sequences using Comparing, not String.equals
0134ddd: do nothing if state didn't change
6ee0e48: IDEA-115859 Presentation mode is broken
d2014c1: add create method
a7ab87f: reuse parts of original document content in completion copy
b74c949: IDEA-117904 Ant integration: running: with an error (javac) the result is reported as "successful": perform all status calculations after all messages are processed
9e5ae50: [log] remove pointless code
1b63a25: [log] Don't use setFont(), instead supply value in getFont()
6d8ac44: [log] Fix showing dot in the root table header
69daed6: IDEA-105450 Attribute id in OSGI reference element not allowed: XmlHighlightingTest.testXhtmlSchemaHighlighting fixed
69e6a15: use equals for primitive types because of annotations for Java 8
3fda71a: get rid of some yellow code
ff86aab: public utility method for local disk detection (works on non-windows)
0fc9f5e: IDEA-117936 IDEA13 fails to stop at breakpoint inside advised method
258307f: Support Mac OS X 10.6+ keyboard setting "Full Keyboard Access" in sheets emulation. (after-review)
9e59f41: CapturingProcessHandler changed to OsProcessHandler for mercurial command execution, possibility to close some tasks added, text for process indicator added.
566ead9: Exception in log history fixed
89e66ae: Race condition fixed for configuration mercurial test.
65b6615: public utility method for local disk detection
1b964fd: Merge remote-tracking branch 'origin/master'
645e475: do not register fixes which need editor in batch mode (IDEA-116248)
a4e3782: IDEA-117613 Gradle: tool window is missing after the update
db25ba2: EA-52652 - NPE: ExceptionUtil.getUnhandledExceptions
cd7b2b2: rename inside injection: offset magic ( JSInplaceIntroduceVariableTest.testInitialOccurrenceSelected )
900a440: boolean method is always inverted: skip methods with one usage (IDEA-117984)
76d90f0: redundant type args: process nested calls (IDEA-117945)
711f709: IDEA-117989 JUnit: Run/Debug java test output "scroll to stacktrace" not working as expected
6d95991: fixed PY-11595 Unable to move lines within Python doc strings
91deb93: registry.properties file is not part of core, we must not rely on it
747815f: IDEA-117613 Gradle: tool window is missing after the update, fix after review
66867da: IDEA-117792 Gradle Run/Debug Configuration: support adding Gradle specific parameters
dfce2ba: IDEA-117864 optimize reference search scope
515619c: don't report silly assignment if lhs or rhs is unresolved
eaa86dc: IDEA-117977 Negative numbers as annotations arguments
3340beb: Fix for IDEA-116940 @formatter off still generating braces [CR-IC-3478]
ec44bbd: IDEA-105450 Attribute id in OSGI reference element not allowed: get schemaLocation from import tag
be385c1: toString()
908538b: RUBY-14672: better name for gracefulProcessTermination()
71e7853: annotation reference should skip processing declarations from class annotated with it
e8cafe5: Merge remote-tracking branch 'origin/master'
38f8048: add some technologies/framework names
03ec4af: Merge remote-tracking branch 'origin/master'
f22311a: IDEA-118027 Groovy: constructors with mixed privacy are flagged as errors
ab67bda: IDEA-116243 Class with same name as package prevents imports in Groovy
05c91bf: IDEA-117950 MacMessage Problem in mercurial clone dialog
912514c: IDEA-108447 Horizontal scrolling not possible or limited
e76fe51: refixing IDEA-57940 : the variants from other editors are suggested AFTER finishing variants from current file
95399a1: IDEA-118004 (Find's Regex Help Popup table header bad color with darcula)
cd5eb0c: Add configuration for expanding shortcut
670664d: Update configurable component on opening the settings
3b5880f: Clean up instanceof template
015306f: Clean up
da88bae: Do not expand templates if plugin is disabled
8cba0d8: Fix bottom border in templates lists
126eaf8: Show templates in completion according to postfix settings
288f972: New plugin options in configurable
77633e1: Rename panel
5913ae7: Delete unused testdata
5902c04: Merge remote-tracking branch 'origin/master'
13f0d48: Merge remote-tracking branch 'origin/master'
b3dcc96: Added logging.
524bfe4: cleanup
ba88950: cleanup
cf71d6b: avoid allocating sun.nio.cs.US_ASCII$Decoder when converting byte[] to String
5478fdf: don't create TIntArrayList(DEPTH_LIMIT) before we have clear indication that we might have a loop (parentId >= id)
a2fa6da: remove args template
7178198: rewrite throw template
2ad2cba: [log] Fix background of the details panel content
f796939: cleanup assert template
f5e6305: Merge branch 'master' of git.labs.intellij.net:idea/community
f370545: OpenShift integration - deploy EAR artifacts
4546732: RUBY-14672: we need to send SIGINT to Ruby debugger twice
f3eb6ff: IDEA-117613 Gradle: tool window is missing after the update
2e72fcc: avoid unconditional trace properly
8667b3e: improve description
2874e61: reset predefined loggers table when it is empty for IDEA-117939 ("Logger initialized with foreign class" inspection had no predefined cases)
a3408c5: wording; make it weak warning (IDEA-117943)
43a6e05: IDEA-117911 Delegate methods duplicate @Override
437658f: generate javadoc: search for modules under progress
c6bc8a6: improved user experience with run configuration producers
601c3d4: diag for EA-51660 - IAE: SuppressManagerImpl.createSuppressActions
f3da68d: diag for EA-51788 - assert: FileEditorManagerImpl.openFileImpl
bd0530a: javadoc
f0b5885: cleanup: dereference
1018090: more correct test
2a06a31: tests: jdk6.0 under mac is weird
5855743: avoid calling PsiFileImpl.toString, use charsequence from FileViewProvider
03f7413: avoid garbage creation in JDK7 due to calling StringBuilder.toString() that copies buffer now
3b6f9bf: new in 13, because these inspections were not actually integrated into 12.1
2f71eef: Fix test of inplace renaming inside injection
7b607b3: replace PsiPrimitiveType with PsiType
ed993d0: rewrite field template
5743c3c: fix assertion
4fd1af4: project: update script fixed to allow path with spaces
7ba76d5: avoid unconditional trace
476b30d: we must not use getKnownFileTypeOrAssociate on navigate
d30684d: IDEA-105450 Attribute id in OSGI reference element not allowed: namespaces from standard resources should be considered relevant
0230aac: Support new Xib format
e419af2: IDEA-117772 (start application loading in EDT)
3dd4fe8: CE modules list ordered
8c59784: Merge remote-tracking branch 'origin/master'
0bba0e0: Better multiline code handling in console.
c8bd8c1: Correct test data path.
521d39f: lazier groovy stub import reference creation
e6bf527: use cache for implicitly imported groovy classes
594785c: fix showValuePopup — incorrect scrolling
ceded58: cleanup
384f8f9: WEB-10231 first navigation to http file doesn't open desired location
e2129a7: Reimplement autocomplete tests with java
1257700: IDEA-117863 (Package with disjoint dependency graph ignores interfaces)
c44080f: CustomFileTypeWordSelectionTest.isCommunity==true
a240a44: gdsl: be prepared to multithreaded scripts
c7b5b3a: structural brace based folding for custom file types (IDEA-83026)
97a55ea: highlight usages in custom file type works as text highlighting (IDEA-117189)
84ad379: in custom file types, don't complete keywords in literals or comments (IDEA-117226)
a3ec15e: brace matcher-based select word in custom file types (IDEA-117225)
b7feb11: custom file type completion rewritten as completion contributor
8072d23: IDEA-117894 Incorrect warning of 'non-varags methods overrides varargs method'
f74cd44: IDEA-117896 Behavior of variable checked for null inspection is influenced by brackets
932153e: Add new gitlab integration based on httpclient4.3.1
67ebb35: Add missing colon after "Token" label in TrelloRepository
45a5f0f: Move http-client library to community. Upgrade it to version 4.3.1. Update licenses and restClient module dependencies appropriately.
f4fcf72: Add default method for installation date deserializer to GsonBuilder in TaskUtil. Remove JiraUtil class.
4b84c12: CSS: extract methods for skipping lazy parseble elements
4f29f40: "Run in background" option from now on means "show build messages immediately" rather than "execute with modal dialog"
510ff4d: fix compilation
cd4a6bc: javadoc for InjectionBackgroundSuppressor
d4507c9: IDEA-117548 Bad function parameters highlight
78aa878: IDEA-117883 make <--tooltip end--> logic work in Inspections View; provide additional tooltip bounds
27054e8: inspection description (IDEA-117881)
9ef64c3: Merge branch 'master' of git.labs.intellij.net:idea/community
02f5a16: use `==` instead of equals for PsiTypes
cae473d: Cloud integrations - refactor artifacts deploy
1a3e0a1: Merge pull request #9 from controlflow/var
3a4dfcd: rewrite var
699a6da: IDEA-117584 more stubs for annotations: tests
acd49e9: IDEA-117584 more stubs for annotations: use optimized operations
98be3a3: IDEA-117584 more stubs for annotations. Optimization for argument searching
9afba6b: IDEA-117317 Groovy SDK is not configured, if groovy-jar has name "groovy-all.jar"
30ea87e: Groovy: cache LiteralConstructorReferences
3e89815: IDEA-106716 Don't steal focus
a78f80d: condition replaced with assertion which checks contract expectation
a141b3e: http://crucible.labs.intellij.net/cru/CR-IC-3556
ca0853d: update netty
d9dbaf9: cleanup
f80d692: Gradle: fix dependencies scope merge IDEA-117556 Gradle custom provided configuration added with compile scope IDEA-117601 Gradle integration ignores scopes.TEST.plus in build.gradle
b636208: IDEA-117698 Auto closing of tags in jsp seems to incorrectly prioritize html tags
3bdaae0: new inference: propagate outer method to constraints, initial (IDEA-117803)
b055f12: IDEA-117827 Invalid "ambiguous method call" error
d47b6d1: IDEA-117455 Github: do not ask user for fork repository if we can guess choice
c2124bd: platform: fix (notification group creation postponed)
a085c19: delegate to ClsStubBuilder for inner class identification
c1e0536: [log] fix name of variable
805b67c: [log] IDEA-115675 IDEA-116040 Fix table columns sizing
6730fef: IDEA-116202 Set active changelist causes IDEA to hang: changelist name truncated to 100.
f074332: cleanup
e15a154: fix Alloy trees
e1a4f76: platform: write unsupported JRE notifications to the event log
d42dc05: Merge remote-tracking branch 'origin/master'
edc5e4e: fixed IDEA-111701 Emacs: pressing Ctrl+k several times should add lines to muti-line buffer (regression for IDEA-18764, broken in IDEA-111275)
4a1d393: Shouldn't try to move if myInfo.toMove2 is null
e2de67c: Merge remote-tracking branch 'origin/master'
515ef7a: IDEA-117584 more stubs for annotations
9207b87: avoid easy garbage java.util.ArrayList$Itr: 1,720,417,512 (1%) bytes in 71,684,063 (2%) objects (avg size 24 bytes) java.util.ArrayList.iterator: 1,720,392,864 (99%) bytes in 71,683,036 (99%) objects com.intellij.openapi.projectRoots.impl.ProjectJdkTableImpl.findJdk: 938,831,640 (54%) bytes in 39,117,985 (54%) objects com.intellij.openapi.editor.impl.ComplementaryFontsRegistry.getFontAbleToDisplay: 218,420,520 (12%) bytes in 9,100,855 (12%) objects
75c030c: don't call toString() without need to avoid garbage
d5a39325: rewrite var template, initial
d8ec59b: no need to create strings of PsiFile's Text when we can avoid it or use charsequence
b6ae811: look for xml properties in files with xml file type only
b46a384: do not claim inner / anonymous classes as indexable (we process them from top level class)
a1f95fa: IDEA-113922 incorrect statusbar text when hover Mercurial > Update to fixed
b64b76a: Add tests for boxed boolean variables
f525375: Boolean template should be able to handle boxed variables
20952d1: fix test data
1c3d516: fix test data
2c01929: Cleanup completion tests
5b1eb2a: Add tests of autopopup recalculation
59e3876: Uncomment test that requires Boolean class
d86bd2c: Add stub of Boolean class to environment
e3482a7: Add autopopup tests
07631d3: enable RootIndex
9c23c52: remove unnecessary dependencies from DomManager
d45e47d: replace condition with isAutoPopup method
b482595: Fix not template for boxed booleans
6a78db2: Rename test for better navigation
b6c7262: Completion should rerun on prefix changing
f72efa26: Delete help button from postfix completion configurable
6e26b1d: Fix psi pattern for 1.switch
99676d8: Add actions for completion items
e70714c: Postfix live template should return shortcut char from settings
0c61ab0: Implement live template completion
98332e8: Fix deadlock
4c947ab: [log] IDEA-117816 small optimization in graph cell drawing
bf9f135: create from usage: reuse 'completion inference' when create from argument list
778f002: [log] IDEA-117500 Don't repaint branches panel on every updateUI
1bb8fa1: [log] IDEA-117500 Optimize grouping of branch references
c3aabac: skip excluded nodes during prev/next occurrence navigation
44b1568: fix TextFieldWithHistory rendering on mac
1496a6b: IDEA-81565 Selection foreground is not applied in Column Mode
a0ba534: IDEA-117780 Bad code is green: non-static class T cannot be referenced from a static context
8970cc3: Cleanup (unused parameter; pointless array conversion)
ab9f14e: Merge remote-tracking branch 'origin/master'
913016a: rename & injections (fix for InjectedLanguageEditingTest.testRenameInPlaceDoesCorrectRangeMarking)
4af6570: fix PersistenceRenameTest blinking: inconsistent @NameValue placement and random methods order in DomGenericInfo
c3dd2bb: reassigned variables complicate back&forth debugging
6bafa09: IDEA-117784 ("type parameter hides visible type" inspection false positive)
781ba12: restore suppressions (IDEA-117763)
da48448: pull up: ignore conflicts coming from access object when it is also moved (IDEA-117671)
63044bd: skinny trees
7814a8f: EqualityPolicy.ByHashingStrategy
a7e4bdc: IDEA-117738 Incorrect warning about impossible ClassCastException
de5f46f: 13.1
639449e: platform: load Mac environment from interactive login shell
0c96a73: Test fixes (do not prematurely create config dir)
9492982: Branch information checks moved to appropriated separated methods.
6c3f3dd: suppress injection background for psql
a5dd92c: wait smart mode checks for isReadAccessAllowed too, so, we must not call it
44727c2: optimization — check isEmpty
88f7578: Gradle: fix to avoid simultaneous project refresh
0924c2b: Method name simplified
e12e09e: remember different working dirs for rerun (IDEA-116110)
96dd995: clean up imports
caed8cc: scope to check for cheap search (IDEA-117665)
03271e6: Contains in branches feature implemented for mercurial log.
8700581: consistent package directories ordering in two directory indices
e800ade: CR-IC-3511 CFR-63806
6dc50e6: move CertificatesManager to platform
0be09aa: Gradle: fix GradleSettingsListener project refresh
b34a551: rename
458c964: IDEA-113344 An easy way to exit from full screen mode using mouse
6148fe7d: cleanup
47adec8: IDEA-117669 gradle multi-module project executing subtask uses wrong gradle version
8618268: IDEA-117669 gradle multi-module project executing subtask uses wrong gradle version
007dc0d: [git] Don't modify the unmodifiable collection
ce13ca6: IDEA_APPLICATION constant
f6b2dfa: cleanup
f598d51: javadoc
02d5e68: convenience method
7280b67: cleanup
602dadd: cache resolved results of new expression
35424c3: don't infer GrClosureType parameters when it is not really needed
f488de2: AppUIUtil.createUndoableTextField
713f323: cleanup
5b7f60f: remove outdated and buggy (in case of library code) property java.debugger.xBreakpoint.onlyIfHasFacets
3cf968c: standalone JPS build: propagate 'forceBuild' option to dependencies implicitly included into compile scope
fb4c1af: Merge remote-tracking branch 'origin/master'
32eb3f3: IDEA-117704 (Add option to 'Non-static initializer'-inspection to ignore anonymous classes)
98baeca: Merge remote-tracking branch 'origin/master'
adfaa05: avoid offset calculation in case of LightVirtualFile or HttpVirtualFile
b35548d: cleanup
db4ca37: VmFileEditor — prepare to fix postponed navigation problem in our HTTP file editor. VmFileEditor supports postponed navigation.
9fffb51: simplify — use subResult
bb4de38: overrides
d4b7a60: cleanup, use SmartList
ba81717: cleanup
2f9ce36: javadoc
5e76246: javadoc
397c92d: cleanup
80f3ece: extract StatementPostfixTemplate
56c5cb7: rewrite synchronized
2a3e876: check parent
0f61ced: WEB-10191 Weird field in the Configure NodeJS Modules Sources
f856110: code style
cee8778: update vendors
ef31c24: refactoring high level listeners (IDEA-115905)
daba93f: inline parameter: do not warn about inaccessible propagated parameter
022615c: NPE
7cecc22: type migration: do not search for conversion when types are convertible (IDEA-117634)
2ace283: extend local scope a set of containing files as visitors expect file level (IDEA-117649)
5e9c2c3: fix quickfix breaking code when non-static inner class was used from an other file
65d7ab4: Merge remote-tracking branch 'origin/master'
2752d2f: IDEA-117378 Privilege escalation via JetBrains products by local attacker
5af5a62: safely skipping some invalid usages
7580ea3: Merge branch 'python-fixes'
35e38a8: modify code for single binary file stub builder
546c532: Detect SQL fragments only in the beginning of string literals
71fdf96: Fixed LiteralTextEscaper.getOffsetInHost() for partial ranges inside host that contain escapes
68b2eb1: proper synchronization
5224872: testdata for IDEA-114797
2e24dd4: testdata for IDEA-115210
aa63767: parse all generated classes no matter were errors detected or not. This is needed for later "differentiate" operation to work correctly
713f671: Added caching of decoded fragments of string literals
658b3cf: Fixed detecting file references in Python strings without delimiters
bc9e47f: Removed unused PyStringLiteralExpression.iterateCharacterRanges()
e1d4530: Switched to new string value iteration in Python file references inside string literals
55c1a59: RootIndex: only mark as project-excluded roots that are not under module content
30dc10c: [git] IDEA-117500 Don't copy, just wrap in unmodifiable
587fd52: [git] remove unused method
b5f2137: [log] Fix "details pane" layout
7c6bb19: [log] Separate loading indicator for "Contained in branches"
c791b46: [log] Fix "Containing branches" for filtered list & for Mercurial
f78700e: [git] Move & rename method to get branches to GitBranchUtil for reuse
f95b122: [git] Simplify method to get branches: use branch names.
4296b11: Merge remote-tracking branch 'origin/master'
8f789af: rename affected clone dialog
6ae1477: File name fixed
2d0dc7d: Use Pair instead of a custom class
42b515e: unused class removed
07367e6: style
5e00978: Merge remote-tracking branch 'origin/master'
6688a87: analyze this dependency: filter left tree so only files with dependencies are left (IDEA-115818)
8964502: tests notification: separate not started notification from ignored when no 'not started' tests were detected (IDEA-116825)
3b44e81: use Url instead of plain string +review
bb94f47: introduce newUrl
cf2220c: cleanup — use constant
8f424b5a: cleanup
ad27c69: IDEA-31095 (Add inspection for "instance initializer could be moved to constructor")
55eb306: package renamed
7c961a7: implementation of methods chain completion indexing on jps
f6f19e8: Switched to new string value iteration in Python spellchecker
67c5643: StringUtilTest for unquote* methods
5d8bfc1: Gradle: fix dependency scope merge to respect artifact classifier option related bug - IDEA-117627 Transitive dependencies missing from imported Gradle project
f7a965e: IDEA-96207, IDEA-97651, IDEA-116896 Git and Mercurial Clone dialog unified and improved
61969ae: - use all BinaryStubBuilders versions in stable order to calculate stub version - introduce version for ClassStubBuilderFactory and use all class stub builder factories in stable order to calculate version of ClassFileStubBuilder
ac06c39: EA-52572 - NPE: XmlResourceUtil.parseResources
562fb4d: IDEA-116547 optimization in reassigned vars check
64c1f8a: typo in diagnostics
7f02a4f: Merge remote-tracking branch 'origin/master'
e762f5d: ensure custom color schema is loaded for dif command line app (IDEA-116478)
44e5be9: suspicious names: highlight only variable name (IDEA-116475)
48ad86b: suppressions: accept variable suppressions for inspections which register problems on variable (IDEA-116475)
57a0cc6: IDEA-116640 Inspection suppression annotation: remove annotation fix
a22e845: CR-IC-3530 (fix refinement)
684fe1a: CR-IC-3530 (fix refinement)
dc79126: Gradle: hotfix disable extension point for executing tasks in external mode
fe3cabd: fix bad loop IDEA-117644 ("Move initializer to constructor" intention breaks code)
633834f: External system: build files modification triggers threads continuously if "auto-import" feature enabled
1540d12: differentiate between Sun and Oracle VMs
fd1b734: IDEA-117249 Optimize make's constant search algorithm, so that read action is not held for long time
3b31641: (unfinished)CSS module split into css-psi-impl which contains PSI and language implementation and css-analysis-impl which contains inspections and highlighting
f8f537e: notnull
cfac677: Merge remote-tracking branch 'origin/master'
2f0c878: Merge branch 'svn_18_2'
647571b: Merge remote-tracking branch 'origin/master'
ecc36c1: fixed silent installation mode.
f0eaa63: Cleanup (logging method moved to a better place)
1be5df4: Merge remote-tracking branch 'origin/master'
cd52e13: IDEA-117536 (No-op method in abstract class: Don't trigger when final)
a03bc48: Merge remote-tracking branch 'origin/master'
8ef8417: suggest using WriteCommandAction in document modification assertion
a5e3ec0: Local VCS tests quick fix (ignore temp. FS)
d1985af: disable introduce variable from part of literal expression which is not a string
3478706: testng: ignore default annotations attributes (IDEA-117575)
ae30b20: IDEA-117561 ("Magic Number": Allow use in final local variable?)
69847d4: preselect live templates in autopopup completion (IDEA-117153)
677ad2e: remove TextBlock
b979841: fix ftl test, demote StringBuffer/StringBuilder
7655390: IDEA-117378 Privilege escalation via JetBrains products by local attacker
82bdc89: RootIndex rewrite
bf5d349: make history almost unlimited
6bc6d61: no delay after tab or escape
7642400: Merge remote-tracking branch 'origin/master'
49111e8: re-create components on every call (laf change fix)
7253375: + "rearranger"
528ec37: more java.lang classes preferred
7368b35: prefer java.lang.String* and System classes in completion
a888bb5: PsiUtilsCore.findLanguageFromElement: result for empty and non-empty files should be the same +review CR-IC
84d8e52: DevKit: refine DOM stubs + test
b2f3b78: Stability
29fb1ff: rewrite switch
6c6b53d: Merge remote-tracking branch 'origin/master'
ce277a1: IDEA-117583 DevKit: highlight <idea-version> "min"|"max" as deprecated
59d8b84: Allow to navigate to goal definition.
3d8acf8: Merge remote-tracking branch 'origin/master'
baaaaa6: IDEA-117061 (Can not set location of proxy auto configuration (.pac) file at proxy setting auto-detect proxy settings)
3af91db: Merge remote-tracking branch 'origin/master'
fd41f02: DebugUtil psi modifications: add javadoc, log.info instead of log.error for invalidations outside transactiond
32f1969: revert read access condition reordering: currentThread should be very fast
f56ca26: cleanup, update "since-build"
d552ee4: IDEA-117573 DevKit: highlight <vendor> "logo" as obsolete
0a0aecf: IDEA-103199 Undo: UTF problem (after-review improvements)
fcfc7e1: Cleanup (test)
d371503: correct definition of "oracle vm" for java 6
a774fd7: deprecate StubIndex.get, replace its usages with safeGet made static and renamed to getElements
ae7ef35: check if we're holding read lock before invoking native currentThread
d24d279: EA-52563 - assert: ChooseModulesDialog$MyTableCellRenderer$.customizeCellRenderer
4b83e57: StringUtil.unquoteString with custom quotation character
f33b6f8: trace when psi becomes invalid
cf33faf: inplace rename inside injected elements (IDEA-117489)
1b25c50: be honest, prevent heisenbugs due to incorrect HashingStrategy
2b92540: diagnostics
61e36eb: cleanup
38f2f05: IDEA-117498 Caret locks up after using ctrl+tab to switch editors [r=Peter.Gromov]
bd8611a: test reworked to avoid double-copying of test data and double-comparison
588cd01: IDEA-117494 133.193: Importing grails modules not labeled as grails enabled +review CR-IU
e028bd7: IDEA-79276 Valid xml element substitution highlighted
3417027: test: assertions on I/O ops
95a276c: Merge remote-tracking branch 'origin/master'
9e07bda: rollback Denis's changes
3ddc0a4: IDEA-117227 load imports from stubs
7e72dbf: Added PyStringLiteralExpression.getDecodedFragments()
e1657e4: PsiExpressionStatement
7e401fb: remove obsolete EP "regExpPropertiesProvider"
ee55699: fix PyMultiFileResolveTest
fc4384d: use StubIndex.safeGet in GroovyDirectInheritorsSearcher
961e91c: groovy resolve: use internal package caches for faster class/subpackage retrieval by name
ffdb0d7: svn: Removed JavaHL from/to SVNKit types converters
4eaadc7: svn: Removed JavaHL logic - version checking, status client, acceleration type
1470364: svn: Refactored SvnStatusHandler - parse status value without using JavaHL classes
3ffe112: svn: Refactored SvnInfoStructure - parse conflict reason without using JavaHL classes
fa6cb4c: svn: Refactored SvnCommitRunner - use own constants instead of JavaHL Revision constants
5efbf3d: add missing licenses for Android libs
9a87f77: diagnostics
81ed6c6: jdk 8 compilation
9fb29f0: diagnostics
b28e2fd: method removed in JDK8
50c710a: tests fixed
3eaed12: cleanup
5c25635: add <with> to EP
70e1965: Minor optimization: use DomElementsInspection instead of BasicDomElementsInspection
0eb3de2: OC-8863 Add visual background to components groups in darkula
d6a9584: get rid of final classes
dfbbfd0: null
66af363: notnull
49fc4b7: Cleanup (test)
64ec592: PsiBuilder/GPUB: zero-length token parsing support (lexer-based macros)
f998a38: tolerate mysterious groovy class file corruption (IDEA-117454)
0edee1f: make "pointless arithmetic" inspection warn about i / i, i - i and i % i
29daad0: Merge remote-tracking branch 'origin/master'
ebdd22e: IDEA-115667 (Inspection: Abstract class naming convention)
9eb00cf: inject java
8b97583: add explicit arguments: eliminate wildcards (IDEA-106741)
c7fcf6b: IDEA-117458 Conditional breakpoints in Grails debugging don't work
49815e2: VcsRootError changed to be an interface, implementation moved to vcs-impl
efbcaf9: Merge remote-tracking branch 'origin/master'
3db176f: reverted module type from plugin_module to java_module for localization and rest
8896cc9: Merge branch 'master' of git.labs.intellij.net:idea/community
71cfc6d: IDEA-116519 - Heroku Deployment facet: make the public key field more user-friendly
2cf7ed8: GroovyHotSwapper: use FileTypeIndex
310e294: IDEA-79312 text cursor gets lost
8fdaba4: format code + style
ea49ecf: IDEA-103199 Undo: UTF problem
83b6571: check lambda return values during constant&conditions (IDEA-117420)
134c2e2: style
3934393: svn: Implemented parsing SVNConflictAction instances from their string codes without using JavaHL types
681278a: Add test for instanceof template
ce8dcc8: Replace instanceof template variable with variable segment
6450764: fix "Usage of obsolete 'junit.framework.Assert'" inspection's problem descriptor
b7ac73b: rewrite return
a70038a: merge junit and testng inspection and fix IDEA-117122 (Misordered assertEquals() arguments not reported for negative numbers)
771a647: mark as simple directory
6ccd631: get rid of throw clause
ba293ee: get rid of BooleanPostfixTemplate, hooray for BooleanPostfixTemplate2
3751c72c: rewrite not
0694e5d: IDEA-117432 Do not fail while resolving client factory for upgrade if "other factory" is configured incorrectly
6242d70: IDEA-117432 Do not fail while resolving client factory for checkout if "other factory" is configured incorrectly
0fdf921: OC-8840
4cc3742: IDEA-115906 Throwable ; IDEA-117401 IAE fixed
7793e6f: HEAD branch filter in new log fixed
b03f3a0: IDEA-117390 'IntelliJIdeaRulezzz' in Code Completion
72c0a83: fallback for expression selection
5dab608: IDEA-116059 After upgrade from 12, IDEA opens all new windows very small
e863612: par template
fd9047c: IDEA-101023 (There is no javax.sql.DriverManager class, the correct name is java.sql.DriverManager)
6919926: do not allow slash in the middle of the child name
02ee160: tests fixed
de1da66: make "Private member access between outer and inner classes" inspection not warn on uncompilable code
4076692: javafx: allow to configure custom manifest attributes (IDEA-115252)
e0222e9: FrequentEventDetector: log outside of synchronized (IDEA-117426)
b29d947: IDEA-117228 Import Gradle build script fails with NotSerializableException of DefaultModuleVersionSelector IDEA-117255 IDEA 133.124, does not recognize gradle project.
02f3e40: svn: Use decoded url string when loading branches (and displaying them in branches popup)
e9f8048: svn: Refactored BranchesLoader - removed unused code, code simplified
df3d4d4: svn: Implemented branches refreshing using command line for the "interactive auth" case (when dialog requesting credentials is shown if necessary)
5baddb3: svn: Implemented browse client - to list repository files and folders
3eb3eb4: svn: Removed unused ShowAllSubmittedFilesAction class
95c4383: svn: Removed unused Wrapper class
0ab2791: svn: Removed unused SVNChangelistClientI interface
3148494: svn: Removed unused imports from RelocateAction
fec66fe: svn: Removed unused SVNWCClient from SvnMergeInfoCache
44d74e4: svn: Removed unused SVNWCClient from BranchInfo constructor
e8d70bc: Move todos
bfdf190: Merge remote-tracking branch 'origin/master'
f573d2c: svn: Implemented "Show history" from repository browser for command line
9369ad1: Add todos
00e7ebf: typo
05b96b2: some words about future
0e08193: rewrite instanceof
4b02b95: svn: Added url targets support to history client
0c32386: another one
3b40534: cleanup
cef8f32: Introduce descriprtion and example for new templates
6375d5e: fix void cast test
be28300: Add extra test for cast template
bedab4d: cleanup?
07f185f: Make key-parameter optional
ab4a463: rewrite cast
2ecbb90: Fold tests + remove throws Exception
e4c55c2: Reimplement while template
dd594ce: In order to avoid deadlock disable prefix calculation by postfixLiveTemplate in LiveTemplateCompletionContributor
d359880: platform: Unix locale in DateFormatUtil
d96c9d0: Merge remote-tracking branch 'origin/livetemplate' into livetemplate
1231fc7: final modifier
871a547: rename
c5819e4: remove all indexed state upon invalidateIndicesForFile (r=Eugene.Zhuravlev)
5012a9b: can not clear JarFileHandler caches (e.g. on JDK 7) -> no logging
b838f19: Reimplement else template
5324fb4: don't lose attachments on stub-ast mismatch reporting
17c6b55: Move key and presentable name initialization to constructor
393d831: IDEA-117391 (annotation highlighting fixed)
9553e5a: Cleanup (pointless test dropped)
cc947b8: IDEA-117359 On unknown variables (say SomeClass.methodCall()) suggest import as the first fix
2545176: warn about non-configured jdk for project files only; check module sdk
d98f1fc: IDEA-117314 Can not compile Java project with Eclipse dependencies storage format
c9359cf: IDEA-116732 Field can be converted to a local variable
96f18ec: Merge branch 'master' of git.labs.intellij.net:idea/community
2694a1f: VisualizeScriptSourcemap action
30d4cdf: cleanup
10561f0: Merge branch 'master' of git.labs.intellij.net:idea/community
9bba592: IDEA-96825 Removed revisions filtering by changed path when building file history
d0a3b13: cache default method signature
9e1e105: tolerate null substitutions (EA-52502)
62c8325: cache GroovyHotSwapper.containsGroovyClasses (IDEA-116851)
c971784: CR-IU-410 - add to git with GitFileUtils#addFiles
da4c45a: Merge remote-tracking branch 'origin/master'
a7efa19: Reimplement AssertTemplate
ce7c8cd: fixed tests since we don't propose to make static decorated method
73392fb: Fix testData for if template
c889167: get max heap value for javac from the new location
657b8b5: * stop stdin scanning thread if stdin is ended * don't close process's output stream after sending control command
192a062: Check type in boolean templates
6fc6a21: + "redispatch"
caf3ece: fix actionSystem.fixLostTyping.description
ced044f: Check custom template availability in ChooseItem
10e95d0: @NotNull
5fcbea0: Merge remote-tracking branch 'origin/master'
a114ad8: [log] IDEA-117365 Expect "empty" git tag; protect against errors
acc583e: fixed PY-10998 Wrong highlight in rst (restructured texts) for headlines
d3a81f0: IDEA-116087 Warning when using new wrapper.gradleVersion construction
bc527b1: Merge branch 'master' of git.labs.intellij.net:idea/community
b875819: Merge remote-tracking branch 'origin/master'
9c2ae5e: CR-IU-410 - remove -a flag on commit
44b70b3: Groovy: introduce parameter: invoke in-place mode only when extracting from expression
3e946cc: IDEA-117389 Groovy: Introduce constant from string part
43b08e4: fix GenerateGetterSetterTest formatting expectations
b213f10: CR-IC-3471
73b245e: finalize consts
8086f92: gwt, ability to debug — one idea module to many gwt modules
0831af1: IDEA-78508 [Maven] Good Code Red with empty variables in classifiers
f3bf865: automatically starts rebuild if java builder caches are corrupted (IDEA-117024)
b5efe09: WaitForMultipleObjects always returns WAIT_OBJECT_0 (busy loop)
3b4eeac: Merge branch 'master' of git.labs.intellij.net:idea/community
d682a15: Merge branch 'master' of git.labs.intellij.net:idea/community
acb43b7: rename while we still can
95d9502: [log] Make fields volatile
4d5fb00: range fixed
afadf4d: IDEA-91899 Breakpoints: Edit breakpoint popup show point on the breakpoint icon
d55e730: Merge branch 'master' of git.labs.intellij.net:idea/community
034aaf4: don't call default Ctrl+C or Ctrl+Break handler function, because it terminates runnerw.exe process forcibly
336ba48: CR-IU-410 - git repository in idea.system.path
6763822: EA-51913 - assert: DomNamespaceKeyIndex.hasStubElementsWithNamespaceKey
15b5563: Merge remote-tracking branch 'origin/master'
092db72: Merge remote-tracking branch 'origin/master'
90c30da: EA-51912 - IAE: CachedValueProvider$Result.<init>
a776fa8: EA-52324 - assert: ClassMappingNameConverter.getVariants: diagnostics
7abab14: test classes combined
6bd1c83: cleanup
f3faf8b: test the actual FileDocumentManager instead of a mock implementation
dc6469b: more robust javac server shutdown
3da930f: range re-fixed
569f3d2: cleanup
3226823: spelling
561c8d1: NullFileEditorState +review
aaa236a: overrides
1251fb6: spelling
0dee8e9: Merge remote-tracking branch 'origin/master'
61eff6f: xml tag completion after prefix
5b13469: rollback
3262dcb: Merge remote-tracking branch 'origin/master'
afa779a: a little bit more diagnostics
524a857: Merge remote-tracking branch 'origin/master'
b491b34: fixing IDEA-117328 java.lang.NoSuchMethodError: com.sun.tools.javac.util.Paths.clearPathExistanceCache()
7d8691d: Rename "Java" -> "JVMOptions" so MacOS doesn't require java 1.6 download from Apple.
c7abbf3: Merge remote-tracking branch 'origin/master'
e5c53c6: Gradle: IDEA-116880 Intellij 13 doesn't auto-save files before Gradle task
4da70ec: Merge remote-tracking branch 'origin/master'
a1db704: Gradle: tooling model builders functional tests added
bf0cd69: Merge remote-tracking branch 'origin/master'
140b618: Gradle: fix check for gradle-related files
5d60265: Merge remote-tracking branch 'origin/master'
95fbdc9: Gradle: fix MultipleRepositoryUrlsInspection to operate on gradle-relevant files only
88a9b50: Merge remote-tracking branch 'origin/master'
3e6ebd9: IDEA-117347 Search Everywhere popup is too wide (cherry picked from commit f2aed4c)
df4e5d8: remove unnecessary tests
4d2d590: Merge remote-tracking branch 'origin/master'
723b5df: New API
5d2a90d: Groovy: injection in command expression
28dc97f: IDEA-117292 Groovy: checks for @Immutable class
fd433a7: IDEA-117227 stubs for Groovy imports
af3a9a5: merging ConcurrentMapFactory and ContainerUtil
92c9abb: recover from possible exceptions during rootsChanged
72f945c: add javolution_license.txt
227c05a: more DirectoryIndex tests
310a331: nicer-looking DirectoryIndex inconsistency report, suppress consistency check for isProjectExcludeRoot which fails too often
ab3238e: save a volatile read
5113ad7: Remove useless assertion comments Fix codestyle
df039b6: Wrapping nazi!
6377b26: osx encoding fix moved to platform-api
1e48680: [log] Register disposable right away, not after initialization
cad277c: remove dumps
b27df78: instanceof initial
70f2546: right desc
452d217: final modifiers
a171f52: type parameter rename
c48a500: cleanup
ce447db: [git] IDEA-116690 Fix "Select in Git Log" from File History
6b75dd5: check all applicable helpers when adding files to completion #WEB-10377 fixed
662747e: Postfix completion: fix autopopup after float-literals
3f83d10: use bitset for storing extra large indices
61abae1: WEB-10503 NPE on start
337260e: WI-7226 Rename: PSR-0 support for "new" and "refactor"
6cd0b95: Fixed tips of the day.
a848ce5: continue WEB-2093: reference by id
1b1bd74: Merge remote-tracking branch 'origin/master'
a2eb867: New PyCharm tips of the day.
d78db0f: set ancestor nodes running when a test starts running
c03e613: we should not use Boolean as source of search + review
79f23d6: overrides
412606d: continue WEB-2093: speed search
182a32d: set JTable.autoStartsEdit to false — edit on F2 & double click, do not interfere with quick search
3696408: deprecate old ComboBoxTableCellEditor
3d5743c: add IconTableCellRenderer, ComboBoxTableCellEditor continue WEB-2093: editable browser family
8484b66: overrides
2989162: Cut out escapes from vagrant output in message dialogs.
baef757: Make setters return this to encourage functional style.
71f2736: Merge remote-tracking branch 'origin/master'
548c6db: Fill providers combo depending on plugins list.
66045f4: IDEA-118330 (kill unresponsive environment reader after timeout)
401a323: revert breaking index change
139adb1: continue WEB-2093 adding user web browsers: path editor
c72dc25: use platform LocalPathCellEditor
47fdfa3: overrides
fd7fa21: continue WEB-2093 adding user web browsers
da7f771: TableUtil.setupCheckboxColumn
ef8f433: cleanup
4b3ea12: continue WEB-2093 adding user web browsers
ddec8b8: cleanup
fd6fe2a: cleanup
8179fb5: cleanup
ed794dd: finalize
28f07af: continue WEB-2093 adding user web browsers
e001efe: continue WEB-2093 adding user web browsers
413607f: init WEB-2093 adding user web browsers
cd5ead2: optimize memory usage for very frequent index occurrences
1898e3e: correct capitalization in some UI places (IDEA-118520, parts of PY-9806)
7b044cb: Merge remote-tracking branch 'origin/master'
717d210: testdata fixed
340bc7a: platform: fake root considered harmful
531ab9b: platform: temp FS excluded from local roots
80af195: Merge remote-tracking branch 'origin/master'
a3b2fc0: bundle junit-4.11.jar
aa53831: IDEA-118763 (handle project component initialization errors)
a6f80fc: [git] IDEA-116738 Don't eat newlines when amending
f4ea819: [git] IDEA-115594 Don't join equal commit messages from different roots
94e7166: Merge remote-tracking branch 'origin/master'
45844ac: bundle junit 4.11
e422a27: [git] DRY
35d0bc2: [git] remove unused
b79e759: [git] write less garbage to the log
2004462: [log] simplify loading details around selected commit
57c9e85: junit: allow to run single method for single param set from parameterized test
fbd90f6: refactorings: propagate usage info to the 'before refactoring event'
c57e44f: junit: allow to run one-param-set parameterized test from tests view (~IDEA-65966)
05074bb: junit: allow run with working directory $MODULE_DIR$ across multiple modules
ed0efd1: junit: allow passing param set name to junit @Parameterized through program parameters
213c1d6: Make the constant final
bf1b263: IDEA-95729 Make a registry option
c2300b6: SmartList — fix testSingleToArray case
98c596e: CR-IC-3851 Consider to use factory methods
e9c8368: CR-IC-3851 Consider to use factory methods
79314e5: SmartList.toArray — copy without iterator creation
e9290dc: fix SmartHashSet iterator (singleton) +review
f6c3de8: "I've had to include some path mapping to avoid the "read only popup"" http://devnet.jetbrains.com/message/5505049
e7b96cb: SmartList.toArray — copy without iterator creation + review
b495f44: don't convert CharSequence to String before converting it to ImmutableText
1f5057f: IDEA-118914 typo: subnet
c78d7e4: LOG.debug which file is currently checked when running inspections globally (IDEA-118567)
23dfd86: IDEA-115577 Commit Changes: keyboard shortcut for Commit Message History does not work
dd9fd24: IDEA-118772 Pattern oracle.bnf should also match oracle-11.2.bnf
2f26745: IDEA-118787 IAE: Argument 0 for @NotNull parameter of com/intellij/codeInspection/dataFlow/value/DfaPsiType.<init> must not be null (with testcase)
1eca4f5: CR-IC-3851 cleanup — Consider to use factory methods
f653174: Merge remote-tracking branch 'origin/master'
d00138c: avoid NPE for non-text editors
561a3bc: junit: @Parameterized inheritors supported
2103908: don't cache custom cls navigation elements, as they might be outdated not only on root change
b1a787f: extracted requestBalloonHiding, per review recommendation
5bd84de: better name for API method, according to review comments
02a8cf9: AppCode: test diagnostic
297193a: Action path fixed
fa67089: Cleanup (VFS test moved to others; fields extracted)
7e3ec6d: remove "Open in Dartium" action
041d958: get rid of ReflectionCache
9b69b3b: Merge remote-tracking branch 'origin/master'
b9c6939: do not loose all run configurations because of plugin error: ignore faulty configuration
f9b5884: inline deprecated methods of ReflectionCache
86bef20: Cleanup (formatting)
227e1aa: get rid of ReflectionCache
2aec3b6: do not loose all run configurations because of plugin error
1e17233: unable to remove qualifier from method reference even if the method is statically imported (IDEA-118979)
eb258ae: delete catch fix: introduce ARM
ef71e0b: unwrap: allow to unwrap catch for try-with-resources statement
63cf5b9: platform: minor VFS optimization and cleanup
eead8f1: nonempty check
ab602cb: project disposed check
22c7a4f: IDEA-118718 Occasionally seeing "Low disk space on a IntelliJ IDEA system directory partition"
598b328: IDEA-116803 UI frozen after project open
e1cfccf: Happy New Year
3294bc5: simplify Combobox ctor +review use idea Combobox
fe70b8a: suppress annotation: allow values from //noinspection comments to be included in the list (IDEA-118948)
a8329a3: safe delete: do not change semantic on delete loop/if body (IDEA-114406)
e07f3b2: fix message with coverage/debugger rejection when $MODULE_DIR$ is set as working directory for tests (IDEA-118572)
1e89f7a: extract ComputableActionGroup, introduce WebBrowserManager continue WEB-9047 "Open in browser" usability
2865587: Merge remote-tracking branch 'origin/master'
eb9ce37: Cleanup.
76a7612: Remove code duplication.
bd8c9c1: Merge remote-tracking branch 'origin/master'
dbb167a: Merge pull request #132 from lehnerj/tip13
17e82d2: IDEA-118756 Fix for stable changes in JUnit 4.12-SNAPSHOT
7071746: enable stripping policy per file (IDEA-118760)
ea66187: [git] Understand renames in the log
0830871: IDEA-101710 Exception Breakpoints | Any Exception with Multiple Class Filters doesn't work
fe16acc: fix arrow position for Retina
0063124: fix darcula colors
e87a766: slightly better fix for IDEA-118691
065fa6d: IDEA-111684 Quick Documentation should resolve values for aggregated / indirect constants
285751f: IDEA-118691 Quick Documentation (Ctrl+Q) often does not display correct javadoc after checking parameters with CTRL+P
6fe35d7: continue WEB-9047 "Open in browser" usability — remove "preview in" action from View menu
511e75c: continue WEB-9047 "Open in browser" usability — move class to appropriate package
a9e3f4a: init WEB-9047 "Open in browser" usability
313e968: strip @SuppressWarning on delegating (IDEA-118528)
a45470a: add inner border for IntelliJ LaF looks not disturbing
f4ed6fb: ensure i18n is available before dialog initialization (IDEA-118193)
3d9d563: quick documentation: fix formatting stripping html tags (IDEA-118673)
f7ce116: ActionManager: <action/> and <group/> "overrides" attribute
5d86370: IDEA-118916 "Install plugin from disk": do not show other files than accepted (JAR/ZIP) in browser
106a3b1: lambda -> anonym: stop at class level (IDEA-118641)
d53eabe: qualified name fixed (IDEA-118683)
a5bcb72: exclude suppressed problems from tree (IDEA-118697)
6591c25: refactored; accept lambda as run argument (IDEA-118775)
17f71f6: Merge branch 'svn_18_2'
6a073c9: xml serialization: Support null values in fields marked as @Attribute (do not add corresponding attribute to output if value is null)
b20439d: new look for combo box button
8c42cb3: icons for combo box button
d8b2c49: move code from auto-generated class AllIcons to AppUIUtil
58f0397: Merge remote-tracking branch 'origin/master'
8f76e73: IDEA-118743 (False positive "Number of placeholders does not match number of arguments in logging call")
2542ac1: run under read action to ensure dumb mode state
4b4ea54: EA-50513 - assert: ExpressionGenerator.visitExpression
8a387be: IDEA-97803 Add ignore options to Groovy empty catch block inspection
df5655c: IDEA-118908 svn: Fixed url validation for "Merge From" action to use SVNURL instances (instead of just strings)
7387dee: IDEA-54304 svn: Refactored BranchConfigurationDialog - use SVNURL instances for validation (and not just string values)
c6a9252: IDEA-54304 svn: Do not explicitly save/load port in branch configuration if default port value is specified
c08341d: svn: Refactored SvnInteractiveAuthenticationProvider - removed duplication (for setting dialog title logic)
536608d: IDEA-54304 svn: Take user name (if any) from repository url when first initializing auth data for SSH protocol
f0b3042: HtmlUtil.isScriptTag
ce43bbc: continue WEB-10360: Now we use script preprocessor to support source map backed breakpoints (we add debugger keyword) and... in this case we MUST use script tag offset instead of absolute.
09efbc2: IDEA-97775 Backing out of empty watch editor creates blank watch entry
c34b260: to get version sort copy of ClsStubBuilderFactory implementation array
c8bb6fd: continue WEB-10360 Javascript debugger with non unique file names
602db68: IDEA-118521 Latest 13.0.1 keeps locking up. Editor becomes unresponsive. Various file types. Using XmlPropertiesIndex to avoid getting xml file content
bb1a41b: Gradle: fix creation/sync of gradle wrapper files on project import (cherry picked from commit e8c50fa)
211d097: Merge remote-tracking branch 'origin/master'
0845f9e: faster xml properties indexing: don't process if no requered namespace string present
9987f8b: cleanup — Consider to use factory methods {@link #createLinked()}, {@link #createSet()}, {@link #createSmartList()}, {@link #create(gnu.trove.TObjectHashingStrategy)} instead of override.
27f0d06: cleanup — use MultiMap.createLinked
0bbfe5d: WEB-10382 Karma tests: allow "Test ignored" output to be suppressed
8fb96a5: Close session on logout option should be used (PY-11718).
bfeecb6: IDEA-118742 removed read action enclosing getting files with particular word (in case of not whole words search it was slow)
1f4910b: removed notnull
b245858: cleanup
f9efef5: Merge remote-tracking branch 'origin/master'
1020ee4: fix debugging watch tree
efd6190: EA-52867 (null check)
e9d6759: proper processing of dom indices, 2
c80901e: removed afterUpdate runnable because it was actually not used: all arguments passed were empty runnables
f18f1b5: [log] IDEA-117680 IDEA-116207 Fix showing Changes for multi-selection
a9b17a6: extract checkDisposed() with verbose reporting
f735058: Don't warn for method com.google.common.base.Throwables#propagate()
316d44c: cleanup code block generation
a8b7b63: Groovy: while's condition is expression
af0b7ba: tuple with parentheses are allowed only inside assignments
64aa586: fix switch testdata
227a659: Groovy control flow: do always process lhs of assignment
61ab9b1: Database navbar extension
e207b56: EA-49328 - diagnostics
4a85dff: IDEA-117377 more careful 'remove explicit type' intention for methods
559b6ef: whitespace checking
e5401d6: proper processing of dom indices
e560ee2: IDEA-118745 Show directory in editor tabs for non-unique filenames doesn't work for non-project files
90f2e9c: IDEA-118446 Installation and plugin update (patch) download ignores Settings / HTTP Proxy
cff5c6c: - fixed serialization for DOM indexes - DOM indices work without exception about stub mismatch
e826bed: typo fixed
db95c42: introduce InternalModuleType
0666a75: Added WinProcessManager for low level work with windows processes.
22c68ce: IDEA-118187 Change font size in run console only changes line height
52aafbb: EA-27319 - assert: FoldingUpdate.getFoldingsFor added more information to error report
a899539: cleanup
227468a: notnull
3a0ed45: EditorSplitters: update shortcuts on keymap change
c714b45: IDEA-99036 Changing breakpoint suspend policy from popup does not actually change the policy
8d3dd02: IDEA-81789 Expression Evaluation goes crazy when multiline expression is inserted
bc118c0: fix second <application/project-components/> error highlighting
8ebc84d: svn: Refactored SvnConfiguration - encapsulated "myUseAcceleration" (in tests)
00af757: svn: Refactored SvnConfiguration - removed old compatibility logic for "checkout urls" config parameter (which was moved from workspace file to app config)
c0c0136: svn: Removed unused "PASSWORD" configuration parameter
3658903: svn: Refactored SvnConfiguration - encapsulated configuration parameters fields - fields are still public not to break configuration persisting - simple renames
e57aca9: svn: Removed unused "LAST_MERGED_REVISION" configuration parameter (and related logic)
851d0f2: svn: Refactored SvnConfiguration - "create auth manager for command line" methods inlined to IdeaSvnkitBasedAuthenticationCallback
3fc6f6f: svn: Refactored SvnConfiguration - moved "clear auth cache" logic to SvnAuthenticationNotifier
e0538af: svn: Authentication tests refactored - methods extracted, removed duplication
035b208: svn: Refactored SvnConfigurable - moved "clear auth cache" logic to SvnAuthenticationNotifier
591ad78: svn: Refactored SvnConfiguration - moved config file utility methods to IdeaSVNConfigFile
20ac89b: svn: Refactored SvnConfiguration - fields encapsulated
249a78b: svn: Removed unused "addpath" configuration parameter
ec72d3c: svn: Removed unused "remoteStatus" and "upgradeMode" configuration parameters
f936508: svn: Refactored SvnConfiguration - removed unused methods, fixed simple warnings
bbae5a3: svn: Implemented usages collector of svn working copy formats used in project
644cc4e: svn: Refactored CompareWithBranchAction - inner classes with compare logic extracted to separate classes
a946a94: svn: Moved CompareWithBranchAction to "diff" package
47e7518: svn: Fixed CurrentContentRevision handling for properties diff
6e139b9: svn: Fixed CmdDiffClient to create correct ContentRevision and Change instances for retrieved changes - correctly handle directories, non-local files, deleted files
fb9a151: svn: Refactored SvnRepositoryContentRevision to use FilePath for remote path (instead of just String)
42c824a: svn: Refactored SvnRepositoryContentRevision not to use explicit repository root path (but just required item path)
11e0f08: svn: Refactored SvnRepositoryContentRevision - removed unnecessary catch blocks
62b3c16: svn: Implemented "Compare with Branch" action for svn 1.8 for command line
e160938: svn: Implemented diff client for command line - to compare local/remote directories content
b6ed9e4: svn: Refactored SvnStatusConvertor - removed unused code, inlined methods, not null
e9fde92: svn: Refactored CompareWithBranchAction - method extractions, object extractions, removed unused code
573e468: svn: Implemented "Compare with Branch" action for files for command line
95c04d1: svn: Use common path resolution logic while command output parsing for status, info, commit, update
ac3960b: svn: Implemented support to get info for several files in batch (for command line)
54ea88b: svn: Refactored ReceivedChangeList type checks - used ReceivedChangeList.unwrap()
606d680: svn: Remote revisions caches - added comments, removed unused methods
a5820de: svn: Fixed conflict reason and conflict action parsing (for info command)
19400c2: update tip of the day
c39a2fb: Merge remote-tracking branch 'origin/master'
d7b3afb: Get rid of 'Provider' thing as Alex suggested (naming, drop multiple lookup elements per template kind). Chop lines longer >140 symbols (IDEA default, I'm really hoping I'm following IDEA's guidelines)
3c82358: allow V8 map on IBM JDK 1.7
1f08bb4: do not disable "ext.dirs" location, because IBM jdk stores some of its essential jars there
332885d: better assertions
c6731e1: code style
2b49ac9: introduce variable inside lambda: do not step out of lambda block
2fdb93a: invalid range
abea706: Cleanup (formatting; arrangement)
eb9686b: Cleanup (single-use util class deprecated)
3f8057b: default concurrency level upper limit
dcfb1d8: encapsulation of factory's implementation details
75beb19: NPE protection for IDEA-117277, but actual NPE already fixed by Anna
10641fe: EA-52516 - IAE: HighlightUsagesHandlerBase.addOccurrence
8d22bd8: EA-52505 - NPE: MethodCandidateInfo.getPertinentApplicabilityLevel
17e9296: invalid range for xml attribute
19ac5df: IDEA-117252 Extract variable bug
4920da7: IDEA-113339 "replace with method reference" ignores side effect of expression: ignore any new expressions in qualifiers
5252a51: IDEA-117298 Darcula&IntelliJ on Windows: Inspection description is too small in Settings
7cf6caa: IDEA-117095 Goto File: checkbox 'include non-project files' is remembered between invocations [r=Anna.Kozlova]
f57d5ab: fix three state check box under intellij and darcula lafs
132a7c6: IDEA-117296 Fixed buttons look bad under Darcula and IntelliJ lafs
9a5b1b5: fix three state check box under intellij and darcula lafs
610c318: all code in "util" module to create CHM implementation via dedicated factory (see IDEA-116404 Java code compilation does not work with IBM JDK)
d7e8e2a: CodeInsightTestUtil#doIntentionTest(): remove Throwable declaration
40ae21d: CR-IU-366
e962648: close process's input stream after process termination
77e0f1a: support Windows soft kills using runnerw.exe in KillableColoredProcessHandler
b567581: IDEA-117258 IntelliJ theme: selected tabs in Debugger and in Run <application server> views get black color
b5afa13: IDEA-117113 Can't Start Mercurial
e42d12e: Problem — we use short gwt module name (Hello) instead of output name (hello, rename-to specified in Hello.gwt.xml). 1) if rename-to specified, url will be http://localhost:9876/sourcemaps/{rename-to} rename-to=“hello” => http://localhost:9876/sourcemaps/hello 2) if rename-to is not specified, url will be http://localhost:9876/sourcemaps/{qualified name} com.google.gwt.sample.hello.Hello => http://localhost:9876/sourcemaps/com.google.gwt.sample.hello.Hello
ecf090a: cleanup
cbc278d: enable the correct inspection by default
4613bad: fix NPEs
dfacab8: "read access" assertion and NPE fixes
77ed2ca: fix "read access" assertion
9c4f089: Merge remote-tracking branch 'origin/master'
c500616: Merge remote-tracking branch 'origin/master'
e668634: fix Url equality (scheme)
ec22c2e: fix NPE — url could be in any form, so, parsed can be null
fc8a662: Remove broken dependency on 'markdownj' from tasks-core module
2fdd102: IDEA-113543 Removed revisions filtering by changed paths for "Quick Manual Select" merge option
9d05ff2: IDEA-115786 Allow the number of Maven threads to be specified
d9d898d: EA-52459 (assert: JavaParserUtil.parseFragment)
03d2433: tests fixed
97b228f: interruptibility
0454a91: memory
a7c22bd: WI-21234 (NPE fixed, method argument annotated)
8813143: use uppercase first letter for options text
ffa841a: IDEA-117265 java.lang.ClassCastException: com.intellij.psi.impl.source.tree.java.PsiParenthesizedExpressionImpl cannot be cast to com.intellij.psi.PsiCallExpression
09fd3ba: IDEA-115953 Editor: Line Spacing < 1.0 no longer works
c613f66: IDEA-117191 (Inspection "Inner class may be static" not working if inner class is return type)
2ea48a5: Gradle: respect IdeaNameDeduper work from Tooling API
79cba99: Merge remote-tracking branch 'origin/master'
16baacc: NPE on invalid expressions
61d51d0: cleanup
689a977: move all stupid casts to the one place: extract ExpressionPostfixLookupElement
9007d7c: *Base classes
8b11913: drop "ignore in test code" checkbox and use "suppress for 'Tests' scope" quickfix
fca2783: remove obsolete test
3c9eb69: Merge remote-tracking branch 'origin/master'
52f0867: do not try to merge stubs if version changed: take three, NPE fix
c2b9a6e: do not try to merge stubs if version changed: take three
bb941b0: External system: add support for different naming of external entities within IDEA models. E.g. external lib name: 'somelib' -> IDEA lib name: 'Gradle: somelib'. external module name: 'some/module' -> IDEA module name: 'some_module'.
a6aa2bb: Fix NPE.
7a0f6ef: Don't break compatibility (PY-11499).
0ecc836: enable abbreviations
43378ec: more searchable options (cherry picked from commit 1dc77a9)
9a96a3f: fix history and symbols 'More' action (cherry picked from commit 31750db)
65eaf17: Merge remote-tracking branch 'origin/master'
79c9f36: add new actions (cherry picked from commit 84f584a)
6f3a339: change action place to Main Menu (cherry picked from commit 5a49390)
1d00a04: don't use smart search for files (don't use space as a separator) (cherry picked from commit 4a50f96)
8b01ecf: restore empty AST loading filter after highlighting
399eaf2: Docs & cosmetics. v0.7.6
6bcb2f9: Make use of 'JavaSurroundersProxy.ifStatement' in .notnull/.null templates
07d19f6: ImmutableText: include complete BSD license text
a9d3ef2: Make use of 'JavaSurroundersProxy.ifStatement' in .else template
6a6dcbb: One more unchecked cast, now compiles without warnings
4a7cbcd: Normalize formatting a bit, suppress unchecked warning
756937e: drop "ignore in test code" checkbox and use "suppress for 'Tests' scope" quickfix
7bff718: drop "ignore exceptions declared in tests" checkbox and use "suppress for 'Tests' scope" quickfix
3c78ab4: lambda -> method ref: do not convert if resulted ref would be ambiguous (IDEA-116964)
9859872: IDEA-117059 (error reporting in updater fixed)
d38a23d: IDEA-117059 (same temp. directory for updater)
9154ab0: NPE in mouse handler
9b13a43: IDEA-117071 (language level in decompiled .class files)
f99fa02: reuse stub reference text in qualified name calculation [^peter]
4b36fa1: introduce variable: forbid to replace write occurrences which occur after read; insert declaration after write usage (IDEA-117204)
d88f344: ready to nulls (EA-52470 - IAE: TypeCompatibilityConstraint.<init>)
bb9f2c7: drop "ignore in test code" checkbox and use "suppress for 'Tests' scope" quickfix
f0a13c2: cleanup and clarify
5840189: drop "ignore in test code" checkbox and use "suppress for 'Tests' scope" quickfix
13835cf: drop "ignore unused 'catch' parameters in tests" and use "suppress for 'Tests' scope" quickfix
f6ac8fe: drop "ignore feature envy in tests" checkbox and use "suppress for 'Tests' scope" quickfix
5aa9b8e: IDEA-116260 ISE: RPC handler object "AddOnlineUser" not found at com.intellij.ide.XmlRpcServerImpl.process
2eb0332: let test AST loading filters be more robust to test failures
50d1e11: fix null project
05a93b5: reconfigure navbar toolbar actions
76889ca: show separators in navbar toolbar
d14a620: update Source Code Pro to version 17
9006519: IDEA-117211 empty elements in Search Everywhere
7f304c1: IDEA-104734 Dracula: Cannot see well active tab in Modules Settings
a4e1707: IDEA-117192 NavBar popup shows in wrong place when navigating to the directory from popup
f1d09b5: tuned UI for got it button
e2cdb6d: introduced idea.register.bundled.fonts registry to be able to switch off bundled fonts registration in order to avoid garbled text in editor (IDEA-93404) [r=Konstantin.Bulenkov]
25cf3c5: use java surrounder for if template
f3e71c6: report missing optimizedFileManager only once
69cc0a4: correct place for optimizedFileManager.jar
bd134c2: tests for inside command modification
d7ce337: disable "document modification inside command only" for free-threaded documents
1cd19f7: command name
76880d9: build scripts: added dependencies to required jps plugins to fix starting build scripts from IDEA
99b0894: remove dependency on platform-impl — move data uri related util methods to util +review
356afaa: drop "ignore empty 'catch' blocks in tests" and use "suppress for 'Tests' scope" quickfix
6976e88: don't respect boolean any longer because there's no ui to disable it
ebeb994: make adapt_builder_() overridable (initState -> public)
869fa42: Merge remote-tracking branch 'origin/master'
342026e: Jediterm updated.
3c85c69: drop "ignore exceptions declared in test" and use "suppress for 'Tests' scope" quickfix
166d33a: enable by default
3b2bc9c: Merge remote-tracking branch 'origin/master'
bdd7043: Merge pull request #6 from ignatov/cast
d5d96de: deprecate useless ReflectionCache methods
184c578: fixed PY-11500 False positive in method may be static inspection for decorated methods
f060500: Mouse selection should always work in Terminal (IDEA-117210).
797ade1: EA-52484 - IOOBE: ConsoleHistoryModel.getHistoryPrev
dc4cc5a: notnull ImmutableText.valueOf parameters
1810858: avoid double DocumentImpl.assertWriteAccess
f22cec8: use ensureValid (EA-52448)
4479456: IDEA-115945 Provide support for Per Environment Bootstrapping
c2b27d2: use java cast surrounder
d0301c6: prefer URLUtil +review
a3081ca: [git] Quick-fix for IDEA-115581: don't fail, just skip such hashes
2e0c576: Merge remote-tracking branch 'origin/master'
7b6b8de: fixed problem of starting on mac 10.8.5+with no java installed
4617618: Merge remote-tracking branch 'origin/master'
852785e: testdata to check invalid method refs
282bfb6: EA-52426 - NPE: JavaDocInfoGenerator.generateSuperMethodsSection
34cbde3: EA-52436 - IAE: PsiElementFactoryImpl.createType
e305473: Remove dynamic dependencies on JavaVM.framework. Otherwise we will be asked to download java from Apple site
055d3bf: added rearranger test for anonymous classes
7bf1e6f: Use Source Code Pro as we don't have problems with unprintable pseudo-graphics as we iterate fonts to find suitable one for unprintable characters.
9e88e3b: [vcs] IDEA-109608 Apply patch: Fix path detection for new files + test
3afe8b5: Merge pull request #5 from ignatov/tests-cleanup
8e13a6a: missed test
be8da2f: Merge pull request #4 from ignatov/tests-cleanup
6a19297: Project parameter to runWriteCommandAction
c0f358c: cleanup
cdcb414: cleanup
04e17d1: overrides
01f1fa8: tests cleanup
b2307d0: IDEA-115412 Diff window is minimized after the appearance
9c31319: Merge pull request #3 from ignatov/shared-configs
7349d49: move tests to the appropriate package; run configurations added
32a21fb: Merge remote-tracking branch 'origin/master'
be905df: ActionTestCase extracted from CoffeeScript and Puppet
5847e27: suggest casting int to long when Long is expecting
f2c576c: method refs: do not choose more specific method between methods with different number of params (cherry picked from commit f986c7c3541f032da16736f43fd34c92337242c4)
41f4842: plugin advertiser: ensure that older plugins won't be ever suggested (cherry picked from commit 3bd2a55d4272f3154be73a93155cc6c512a7dcaa)
b9ee30c: plugins advertise: download plugin if it was not explicitly disabled (IDEA-117003) (cherry picked from commit f739564c0fb744ef8b819f2df4011a9eaeb00685)
ca248d8: plugins advertiser: provide loading plugin version for renderer (cherry picked from commit df398a91a558ef3c1a4f85c34b119fa4859bfd6f)
8818860: CCE (IDEA-117119) (cherry picked from commit 751d401cd177c5da5cd454ec9ebbcd6464a1b08f)
301efb1: lambda: do not distinguish between ellipsis and arrays for formal lambda params checks (IDEA-117124) (cherry picked from commit 03b253b084ddb93ce485b1997d47a4b00284eb74)
acdf70a: ~update mockJDK-1.7 used classes to be at least from jdk 1.5 (cherry picked from commit 7e1f100585719ad9c686d24d43a9c9e2a78109f1)
ad9486d: do not create raw outer types during diamond inference (cherry picked from commit c812622e14b3cb86ec18cedd406118789abb2e83)
834793e: mock 1.8 jdk (cherry picked from commit 86b3924bc3c6dca79f9d5f75bc5e93307a5da4f4)
0057f81: check that index for which indexUnsavedDocument is performed can be applied to given file type (EA-47740) [r=Eugene.Zhuravlev]
8eb6624: Merge remote-tracking branch 'origin/master'
6156989: Lowercase directory names on OS X... argh
15869e7: IDEA-96723 Java Rearranger deletes blank lines in field declarations
9d6c3a8: FileUtil.readLines(File) method
5b6dadb: use ImmutableText for document contents
39c059f: removed signing for CE launchers.
3c553d6: Minor typo fix (IDEA-116432 Incorrect Spelling of Eclipse)
13b5a46: IDEA-116558 Update state transition requests for JIRA REST API 2
3d0d149: a couple of tests fixed to avoid assertion of document modification outside command
ab71fcb: assertion for changing document inside command or undo-transparent action only and warning of PSI modifications inside document save listener
fa708d3: moved to psi
75151b1: IDEA-116866 (path overriding for plugins/log dirs fixed once again)
8e2ad06: IDEA-116756 Gradle multi-module project with deep-nested modules - idea places iml file in the wrong directory
9ecbdc6: special icon for generated test root
b076862: ver 0.7.5
0a139a6: Cleanup
8613b2c: Normalize 'import' style
731a05f: Fix naming of packages
af70c0e: faster dfa concatenation processing
117a25c: Rename SDK 2
00bd16a: Rename SDK
b34ebc4: Fix column widths in configurable
3721e70: Convert field to local variable Show column titles
790e23b: Rename templates panel
4077201: Merge pull request #2 from ignatov/cast
2520fb1: small cleanup for cast template
af0f00c: Revert (signer is not available within CE)
dc6be5b: IDEA-116866 (path overriding for plugins/log dirs fixed)
8fd2f55: Cleanup (punctuation)
cd9c425: EA-52322 (diagnostic)
80d5bcb: util: LinkedHashMap from pairs
4c4fc8c: Reimplement confugurable, first iteration
4d5bfb7: IDEA-92545 (Type maybe weakened does not always work)
641eabb: Extract method for retrieving PostfixTemplatesService
5558fef: Merge branch 'master' of git.labs.intellij.net:idea/community
6534861: CR-IU-410 - replace init method with constructor
f141c64: Merge remote-tracking branch 'origin/master'
329fe2b: Add out/ directory to .gitignore
c93fd52: Add idea codestyle
7fe0024a: Add idea inspection profile
56f1936: dfa: don't try to merge obviously incompatible states
b889d6e: cache intermediate dir infos in RootIndex
661b9da: Merge branch 'master' of git.labs.intellij.net:idea/community
554b244: CR-IU-410 - drop unused import
3de5bbe: Setup composite as it is done in EditorImpl.paintComponent.
a8e1e9a: don't let invalid fold regions and hyperlink highlights add up on console overflow (IDEA-117120)
25eb9fc: don't drop all caches on second completion invocation in the same place after the copy has already been reused
cbd50b3: Behave the same as EditorImpl.
c19e163: continue WEB-9968 Dart: ClassCastException when debugging web application in Dartium
62f5430: finalize constants
a708a6e: newHttpUrl — authority must be NotNull
95c5bb9: cosmetics
a13d7be: use the same background color
69ddb19: refactored AbstractLayoutCodeProcessor, ReformatCodeAction
b2bce83: set lower limit of 1 for max_worker_threads_count (for low-profile cpu)
6ccdae5: IDEA-111388 Built-in server not "available external" — it is unclear that port number must be also changed
e11330e: make IntelliJ laf by default on Linux
b412249: Merge remote-tracking branch 'origin/master'
eec2e4a: use backported V8 CHM only for Oracle or Apple JDK (IDEA-116404 Java code compilation does not work with IBM JDK)
abea23a: Merge remote-tracking branch 'origin/master'
ed3c105: added signing for community launchers in zip distr.
96e001e: avoid blocking runReadAction in debug logging
5b4f290: VfsUtilTest.testNotCanonicallyNamedChild under Linux
76896b9: moved to core
a63aaeb: isCaseSensitive method
e77ddeb: reaction to range highlighter' renderers change: repaint gutter non only when renderer appears but also when it is gone
50873ad: utility method
33fcb9e: Merge remote-tracking branch 'origin/master'
3052d82: fixed PY-2984 Surround with try/except reformats entire file
c847d67: save / load per project key hash codes
b929c67: use existing project
c102290: update artwork for version 13
6dafd1d: add history
8093829: CR-IC-3403#CFR-62470
d7a7a2f: IDEA-111161 Flat tool window design (hover shouldn't look like selected)
14c9ec9: CR-IC-3403 we must return empty state if empty, but not null
cd35a94: test for unzipping malformed zip archive
8e10c3a: target error message for a newly created project
fa39c70: NetUtils.tryToFindAvailableSocketPort
4ecac7f: introduce Urls.newUri, prepare to fix WEB-9968 Dart: ClassCastException when debugging web application in Dartium
391caac: Merge pull request #1 from zolotov/infrastructure-improvements
a128fa5: FinderRecursivePanel: do not perform getListItems() in EDT on update
02da50f: use ZipFile, because it throws exception for a malformed zip archive
eaf3233: mutating methods pushed down into SoftWrapModelImpl
d43e5d9: Fix maven tests.
691aebb: remove caching from ReflectionCache
c317710: Remove old TemplateProviders package
ec7f98e: Reimplement PostfixCompletionManager with Service
a6f9141: External System: support for multiple tasks execution added
b749bf1: better colors? fix balloon and popup borders
01e9748: utility class holding two colors for gradient painting
9750b3a: Simplify if-statements
dc07e66: Reimplement TemplateProviders with extensions
05c0e14: removed duplicate module definition
414a185: fixed clicking on stacktrace links in console when several classes are found: prefer modules over libraries, show popup if necessary (IDEA-52913)
691e7e2: Merge remote-tracking branch 'origin/master'
15cb709: File chooser for shell path (PY-11334).
99d62c8: Take shell path setting before every process creation.
189973d: Merge branch 'master' of git.labs.intellij.net:idea/community
036cc96: Cloud integrations - deploy artifacts to git clouds
01ef080: switching to java.util.ConcurrentHashMap in jps code; eliminate unneeded map queries
740725d: fix NPE [^Ann] (cherry picked from commit 403f9a5)
7f1b705: IDEA-114952 Eclipse code style import: would be nice to remember imported file location (URL fix for Windows)
896e23a: Merge remote-tracking branch 'origin/master'
b08500c: args can be immutable (PY-11465).
d08af6d: javadoc: keep whitespaces in {@code} tags (IDEA-109997)
02cabc4: IDEA-117082 Anonymous class assigned to final field
cbcc0e8: Merge remote-tracking branch 'origin/master'
aa90618: Merge remote-tracking branch 'origin/master'
3656e43: CR-IC-3403#CFR-62470 leads to changes between IDEA versions and we try to avoid this as much as possible
c5d4fdb: Take default shell from env variable.
95c72cb: don't drop all caches on second completion invocation in the same place
ab741be: Restore selection after undo delete operation
6646b18: some memory tune-ups
682c71d: Problem with username fixed
a4a8e3a: copyright: ensure that we update copyright in the correct project (IDEA-114186)
354fece: junit: do not reuse directory configuration from another test root (IDEA-116871)
effc865: junit: do not create directory configuration when selection is not under test root, e.g. module content root (IDEA-116871)
2b4dc10: product name -> full product name (IDEA-117070)
5d8f8fd: diagnose and recover from IOOBE when node ranges are inconsistent during commit
17cc299: Allow to pass parameters for MavenEmbedder via system properties.
fb583bf: IDEA-117077 Can't remove files from Recent Files
ee2e304: IDEA-117073 Recent files and Switcher are not centred in ide window
510da92: file watchers tips should be in WS only
dc69039: use ensureValid
9ef47ff: RootIndex: no package name for ignored directories
032b1f2: Copyright must not save empty settings +review
32453bd: cleanup
009ca28: IDEA-114418 (Grails SDK of an dependency) -Dgrails.disable.structure.update=true should work for JDK synchronization.
27557a3: index property optimization
5c1d10a: class searching optimization
fdb6916: typo
7c076b6: EA-52338 - assert: ComponentManagerImpl.getComponent
a7b76f5: shorter message
aadeb26: IDEA-117030 Groovy/Gradle frequent, severe hangs
99ffd83: plugins advertiser: ensure that all installed plugins would be enabled - check also unknown plugins (IDEA-117068)
e545297: plugins advertiser: do not suggest to update to ultimate on implicitly disabled plugins (IDEA-117040)
9af3c15: update complete statement tips
3e4c22c: removed LOG.error for null syntax highlighter
8d73687: remove image tag
423f210: missed images
53ae1ad: Enter in SE should close popup if selection is a setting
5b14b47: button placed on top, should be in the middle
e2953b9: fixed PY-11435 Can't run script by context menu action if it has method named test
283a1cf: Add missing module definition. (cherry picked from commit b975e7d)
1fe89e9: Fixed detection of the largest string literal for right parts of '%' operator
0df2a18: Add license for "aether-api-0.9.0.M2.jar"
79c4e6e: IDEA-116881 Please time stamp gradle tasks
e0712b9: IDEA-54405 Use decoded url for "Checkout"
9732da7: IDEA-116891 gradle import creates a lot of extra empty directories
ca7e083: IDEA-116891 gradle import creates a lot of extra empty directories
881fdc6: IDEA-117022 Use decoded url for "Show History"
58704c7: relative path - special url, encoding is not required
3868464: cleanup
065a7d1: CCE fixed (IDEA-116968)
36bacc0: IDEA-100294 Cannot edit a file - text jumps all over the screen
3b21d86: IDEA-116636 Android-Gradle facet is created when Gradle synchronization related bug IDEA-116887 Gradle web artifacts do not contain compiled classes and JSP files
64e7f51: IDEA-116636 Android-Gradle facet is created when Gradle synchronization related bug IDEA-116887 Gradle web artifacts do not contain compiled classes and JSP files
d3f9d06: IDEA-116974 Gradle Plugin doesn't handle 'providedCompile' dependencies in 'war' projects correctly
d274eb6: revert changes to fix problem with saving settings when WriteExternalException is thrown (cherry picked from commit a6fa4dd)
ef475ea: IDEA-97696 Custom tool windows layout is lost on exiting IDE with closed projects (cherry picked from commit 984cdfb)
20b26a1: Search fields: native border visual glitch (cherry picked from commit 922ecfc)
a4d51a6: Lens pixel hunting (reviewed by kb) (cherry picked from commit 17913b8)
7175093: IDEA-111161 Flat tool window design PATCH(reviewed by kb) (cherry picked from commit 4055528)
2a9a91b: IDEA-115546 Full Screen Mode: main menu persists on screen, when invoked by the keyboard shortcut(reviewed by kb) (cherry picked from commit 5be1c50)
3b1fe7f: compilation fixed
c30d973: don't write new settings to profile if they have the default value
cbe65f9: do not change parameter types in MethodSignature
243927e: copyright: common scope chooser before update
956e568: info -> debug in the old code
9062554: optimization: do not check scope if attributes are empty (^peter)
92adf45: inspection profile: no need to initialize on write when tool was not initialized (=had default settings on read)
fdb3b74: possible NPE, explanation for the used scope
094ac76: IDEA-116991 "IDE is up to date" message
bf64625: lambda: process lambda as parameter for anonymous class (IDEA-116987)
383ad37: export inspections: delegate severity of entry points to unused declaration (IDEA-116984)
d7dc6ca: IDEA-66494 Switching between search and replace
684ec2c: Merge remote-tracking branch 'origin/master'
5965955: Add idea.log to exception report attachment
0f9f94c: Merge remote-tracking branch 'origin/master'
c44098a: use exactly parent url
1088e3f: IDEA-115862 Find in Path should default to current files's path
d06f31a: IDEA-116921 Run configuration can't resolve test dependency when "Resolve workspace artifacts" ticked on.
1290923: handling cases when added class hides imported class with the same short name (IDEA-116914 Incremental compilation of Java project fails)
8c35e68: IDEA-116452 "Resolve workspace artifacts" option doesn't work with Maven 3.1.x +review CR-IC
89924a0: fixed PY-11452 tcunittest errors with single-character failure message
0520f19: Merge remote-tracking branch 'origin/master'
690f786: Merge remote-tracking branch 'origin/master'
afd0517: fixed test data
e6c7dba: do not update recent projects on closing in headless mode (cherry picked from commit 5b8fb93329ce88fd24e5b6dca913fb0b78fe880a)
9f23d62: plugin advertiser: filtering fixed (cherry picked from commit e2750ea61032f2a041cb012bb7b90cffa0deba73)
868f52a: new inference: cache functional type to check (cherry picked from commit 31bdea83bd3bcbffabdaed4f09d9b6ddfce04090)
220d3f6: respect search scope searching for constructor refs (cherry picked from commit a9669b2d78dad206f25ffc939199b20bd47ac7ad)
e493e0c: new inference: lift containing class type parameters for method references (cherry picked from commit a341be1196484b6e4c33a7d10059d2bec5bdf955)
912722b: new inference: raise a error when function type was not inferred (supposing well-formed type as free from wildcards) (cherry picked from commit a9173e822d2aab629265baf295248950e2319e31)
24cd3f0: wildcards inside: fix for intersection types [^roma] (cherry picked from commit 6e88ca6de6e921f45f069a34d1e48f5566d362a1)
b15fa5d: new inference: propagate calculated substitutor to use in B3 reduction process (cherry picked from commit 9e70662bfae9dd6419ded2928e30b28b31eeee68)
6bdc2b9: new inference: do not incorporate during B1 phase; TypeCompatibilityConstraint reduces to true for raw substitution and erase in this case method return type (cherry picked from commit bde1932a613b16a37843d93082763fc172626550)
75dbc07: plugins advertiser: ensure that installed plugin is not suggested (IDEA-116927) (cherry picked from commit 0f50ba85bb24c992749a5e61503e03cd635b3e26)
b1582ae: plugin advertiser: suggest ultimate edition for bound plugins (cherry picked from commit ddadbb201b8a127d4c27c692a340f020f99f58a0)
114485f: NPE (cherry picked from commit 4f8711f13c3a3ebb847d879c0347013397792e84)
3658742: quickfix name (IDEA-116639) (cherry picked from commit c56f91baa99d6946b3fc432c86072da44196b8a5)
4360e42: new inference: testdata to prevent regression (cherry picked from commit 48a86f05e7661d2a96cf6c6d95eaa4629446d0bb)
4001f9f: new inference: include containing class params for constructor refs (cherry picked from commit be696513a9ed7e418385a25a879b1e0373dd4cf2)
693eddf: new inference: testdata (cherry picked from commit 6f0f160f905ae275a2eeaca58343a176df1a42c8)
a6e99dd: new inference: incomplete methods ready (cherry picked from commit 59177525941b8cb78cb8f99d7402e9528c8894ad)
9ac34fc: new inference: highlight method refs with incompatible inferred bounds (cherry picked from commit e1af6d1b69f93db6915d3c4f86eaee95389607d2)
fc58e5e: new inference: include lifting constraint when parent call is being investigated (cherry picked from commit aaeafcdce1c8d49512cc1fece17afb3e1705492e)
45cf19c: new inference: skip null subtypes (cherry picked from commit 837fc3567e628ac753d3e3c19f5c1039465ecf7d)
5f1db87: new inference: avoid one type parameter inference (cherry picked from commit f764e69e3f7e98e0c94e701706121069f2775586)
f3950b7: method refs: take ref type arguments into account (cherry picked from commit 47474aaa3b68d2fa4c88276cb4e52cf17c6c55ac)
69191bf: new inference: accept Object/null type argument equivalence (cherry picked from commit e631676784df65aa2f68a4fcaddcae3802d3d7df)
3188589: new inference: do not instantiate vars with upper bounds mix when incomplete substitutor is supposed (cherry picked from commit ff73c519f10ec947b86832a0c4ce5d6ee9b9e4c3)
80e8321: intersection types for PsiTypeVisitor; do not convert intersection type to class type even when no actual substitution is needed (cherry picked from commit 4670ddf57981f596122082365e43587990c3a53e)
d338bc7: lambda: break/continue inside lambda body checks (cherry picked from commit a290c356e646bb8ad9c097664648ad9033adf2a8)
f8e74f0: new inference: temp solution for inexact method refs (cherry picked from commit e94cddb696cbcb3e3a8d8e4f62f8903b4bd71403)
19852e6: new inference: infer from thrown exceptions in lambda body (cherry picked from commit 04056c01aa1eef1239ac88d48baec7ff109ef0df)
709b616: lambda: void-compatibility check for expression's lambda void type conditional (cherry picked from commit 76bab4d85984e95279b0358b53ff85734c4589a5)
a1bf37f: new inference: lift type params from referenced method (cherry picked from commit 057bd4d4d576711b77141b64987079ef8d59a583)
12baf9a: new inference: accept all inexact refs during overload resolution (cherry picked from commit c21ac7ada213c2de28b3e8e5aa15d3fde4490458)
a6c8262: new inference: overload resolution: check return types when method refs are exact (cherry picked from commit ccacf897e97a121f795a079e485249842c95c273)
82fd892: new inference: overload resolution: check SAM specific withing common specific check (cherry picked from commit 2bbd45e57bc5df7ff2a5cae7acedc0d2428d9afe)
e3197b6: constructor refs: forbid raw constructor references with explicit new type args (cherry picked from commit a127d801aa080f2efe3784edd5cca419dccfda2e)
f66adc7: new inference: refinement on generics array creation/forbid wildcards in ClassType qualifier (cherry picked from commit 72a410e804b569893f0bad7739bdd9a7c1c270f1)
d42efc0: unchecked generics array creation for method references (cherry picked from commit 742ea955d1a88c4ac8cb7727a9221bdf65038c11)
e351956: lambda: void-compatibility check for expression's lambda refined (cherry picked from commit c59e6beb8c42c48a46550b39725587d3aa8f560a)
af2681e: new inference: forget old instantiations before reduction (need for incorporation) (cherry picked from commit aca9abc4139024765594cb7c683bed77ae8db74e)
10439a1: new inference: reject methrefs with inconsistent number of parameters (cherry picked from commit 9c41270192e140ed28067e2740333c6d3fa49bd2)
a9bc9bf: check bounds should ignore recursive substitution also when wildcard is captured (cherry picked from commit bb08b50baa9e80cf8f99a87e1d8d040bb099e12c)
b8c1c38: new inference: raise a conflict for 2 captured wildcards as equality constraints (cherry picked from commit 52bf5c35f05483ed957af17eb80b1b70cd3ed1c9)
73bf021: new inference: javac bug registration (JDK-8028503) (cherry picked from commit 76727c790a9fcac64dce762d8d6fc674680d1905)
b340126: new inference: cleanup (cherry picked from commit 7dc1d2239b2a40c8aa0a9905adf39b14d49d21fc)
d30bcb3: new inference: accept unbounded wildcards (cherry picked from commit ff37a13662a6d85d7890755130e6a696db00c4a6)
b3d9ff9: new inference: array creation notional method; testdata (cherry picked from commit dc1b25b74db12a5282332b5bae1d10da1aed99e8)
3c3f917: new inference: method constructor array reference processing (cherry picked from commit dbc986aab8519ee3c93f39f04c31cbae0bfd2657)
d7e914b: new inference: use policy to pass that params should be lifted without Object assignment (cherry picked from commit ba466100e201658701fa056c1a3641a42abb2d8d)
628e05b: new inference: isValueCompatible check during reduce (IDEA-116548) (cherry picked from commit 3d028a86a23efeba68187c5a43d822c7aeb388f3)
a6309f6: extend testdata for IDEA-93587 (cherry picked from commit d4939f7b93989a0e3387c225de335ef7bf19949f)
6086b17: testdata for IDEA-106670 (cherry picked from commit 78c98d762dd449ff86ea805179b51c2d2b4fc00f)
b612209: testdata for IDEA-116359 (cherry picked from commit bd1ca6826f3a5449c2a26a1ea3b471c21f4bc7d5)
bd64f40: testdata for IDEA-116252 (cherry picked from commit 263652d7e97e6caab5dce7fb95a37d14ff34de4b)
260977a: enable new inference for 1.8 (cherry picked from commit f8ab566aafbb1b639e935b34975440a7172a637c)
481bc25: switch tests on new inference (cherry picked from commit d2cbf3f2833104c3a0381059b0d6ef8ac0b3c94c)
23432e3: new inference: array constructor refs are always exact (IDEA-115725) (cherry picked from commit 0f6538fc54bbee0aaf6cbab9884c0407937d4568)
0c02d87: new inference: process type arguments withing bounds (cherry picked from commit 18c175ea17eb26b4baec7cc1f7b9579849783a5e)
f7fd852: lambda: catch exception by SAM method substitution (IDEA-116441) (cherry picked from commit 0bce39590bdcc6e6a74c0dcedbb02add3333e685)
79c9afb: testdata for IDEA-116493 (cherry picked from commit 9270256d3bb30a40be89fee9609f49f288a69040)
8d066a2: new inference: preserve the order (cherry picked from commit d83860b652f9510c2ed59109ccfdee2d02557241)
a9b10b9: new inference: unintended raw substitutor (cherry picked from commit 80cc211ac832022cebd429774cd4661b1b47877a)
d37bf95: disable tests for a while (cherry picked from commit ad536eda6f2b09b366dae6ab2322526e32558eb6)
7f5f6bf: new inference: reject wrong overloaded methods earlier (cherry picked from commit 1ae5a895d4ae466df6106913c268339d63dbbe64)
530d047: new inference: merge equals constraints before rejection (cherry picked from commit 3a660f4b84a23f42f1355bc7702c6d9904984ee2)
bbd2b72: new inference: skip wildcards in SAM return types (cherry picked from commit a2d6c53f181a000945b42777d21046ee7a05bff3)
ec99a45: new inference: include constraint without input variables first (cherry picked from commit f971c6fad15e7037cba08ba474bc8965ba7dc130)
492398b: new inference: simplify check for call expression (cherry picked from commit 3624126e79fd72af03425299300bbdd9cda75ef2)
72cf910: new inference: do not skip contradicted bounds (cherry picked from commit 8ce52d2dc87cfde0471a65c55df972711bffa1c4)
fa579af: new inference: input/output variables strictly after spec (cherry picked from commit 7a6936834b386b54df9e7901ee9c7452704ba084)
ba7784c: new inference: is poly expression strictly after spec (cherry picked from commit a66cfe3806da068d012952170e22000a47bbfda1)
adc1ea2: new inference: is pertinent to applicability strictly after spec (cherry picked from commit d1573452f675df60c3aa9155f29fb6c794ac964e)
0c5ad3e: new inference: equals/hashcode for final fields only (cherry picked from commit c1c6e161f6036938bb712c76e58c9270b4b86c38)
1f5e19e: inference testdata fixed (cherry picked from commit 684b8905b9b3be10200c855af7b54d543b128f2b)
c0c190f: CCE in scala (cherry picked from commit 88a43e939198ae9a966f457d27d381d283d4c112)
a1e0e12: new inference: check all overload methods during return type constraint detection (cherry picked from commit 7017ba9d1c7f0f911241331f03ef61198fc69d5c)
8e571b3: new inference: capture return type to emulate method call expression type (cherry picked from commit a14b996d8c3efe5b1dc4a6fc3d45aea5feff6197)
64c3ce5: plugins advertiser: ensure before open files (cherry picked from commit d8c3c254ae0f839b5dcc61ccc2bbfd42d274ff6b)
d881e4b: new inference: process mutual dependencies (cherry picked from commit 72dcb6d8ce54a6be5f236a9c3cae0350293375cd)
c8c35de: IDEA-116362 ignore extension does not work (cherry picked from commit 84fe96736fb2fbbbaf5f739b3aed4ea2072edb0e)
fbc9904: Guava and Pty4J libraries dependencies.
18db741: fixed PY-11476 No error given for mismatched accolade and squarebracket
70533cb: Pty lib updated - run in console mode.
8945d78: IDEA-116945 IDE unresponsive with too many console foldings
304a802: Allow to run processes with PTY.
abb93f2: IDEA-116917 check for jansi in classpath
9da2215: select correct shell runner in title
b6df353: IDEA-116837 Groovy: don't suggest to shorten references in comments
7e8b160: [log] IDEA-116399 Fix filter by branch
4696e18: grayed text is invisible on Linux
e5e7602: NPE fix: editor is not shown case
aa73c61: really enable by default
10eaf8a: Merge remote-tracking branch 'origin/master'
9609156: Merge remote-tracking branch 'origin/master'
b459118: Overriding language in VariableInplaceRenamer. (CoffeeScript)
6ebb2ee: Merge branch 'python-intellilang-injector'
ae9b9ba: IDEA-102449 Mac OS + JDK 1.7: dialog sheets go to background if focus is moved from IDEA and then back [Filechooser part added and refactoring]
f4303eb: Merge branch 'svn_18_2'
b98ce36: Merge remote-tracking branch 'origin/master'
b0fa5ca: Added comment-based language injector for Python
ae50061: fixed tests
efd5985: IDEA-113730 Implemented "cat" command to read content as binary data (not to read as text data and then convert to bytes using some encoding)
884c0ff: fix bounds violation when uncommenting EOF comment
1704b4a: DRY bug fixed
db52690: IDEA-55970 (Erroneous "type may be weakened to 'null'" in generic method)
16650f3: Merge branch 'python-intellilang-injector'
78fc601: Fixed un-inject language availability for temporary Python injections
61ee967: menu is not visible on Linux + IntelliJ theme
9de9e34: [vcs] IDEA-115571 Don't clean change lists's commit message until committed
ab2d17a: Method renamed.
11bc558: update tips
baafab9: Extracted PyInjectionBase.registerInjection
c132ce6: suppressed detection for all frameworks in our project
240a1ff: IDEA-116682 ("Collection declared by class, not interface" suggests abstract classes)
02b261e: Merge remote-tracking branch 'origin/master'
726ffc1: [log] Make "show details" & "show long edges" actions dumb aware
7021a46: style
0e1c820: IDEA-113684 Soft wraps insert additional spaces
372d6c1: javadoc
dfee10f: error reporting in 'Project Structure' dialog: merge UI updates (IDEA-116808, IDEA-110799)
495fddc: added quick-fix to delete all unused libraries (IDEA-99885)
7c80f38: IDEA-116910 (Invalid "unnecessary explicit numeric cast" warning)
f119c2e: IDEA-108838 Wrong code when introducing variable in injection
07385a6: get rid of invoke later
768f1de: IDEA-115275 (bundle compiler migrated from VFS to plain files)
2d366e6: Cleanup (formatting)
bcd648e: update CharArrayUtil.fromSequence doc, use it instead of fromSequenceStrict
85253bd: introduce multi-token nextTokenIs()
79ef033: do not auto-switch current suspend context if a new thread with suspenPolicy=thread hits a breakpoint (IDEA-116160)
49a033a: [log] IDEA-116950 Draw just "tag +" instead of "tag + 5 more"
9f24b72: [log] IDEA-116950 Don't display all tags if there are too many of them
3bb3524: [log] Refactor: move ref painter & drawRefs & calc refs padding to the common parent class
332b443: Do not initialize docks in test mode
030c5f3: IDEA-102449 Mac OS + JDK 1.7: dialog sheets go to background if focus is moved from IDEA and then back
307f301: [log] Fix possible race conditions in "Containing branches"
662f63c: [log] Don't display "Loading..." immediately, let a 300ms delay
cff1db6: enable by default
7ad802c: [log] Show details panel by default (as it were in the old log)
73ae4b2: [log] More clear name for "Go To Ref" action
4d1e0c0: [log] No need in "Copy Hash" action on the toolbar
538fcaf: [log] Don't hide "Go to ref" action when focus is not in the log
49939da: align RootIndex.isProjectExcludeRoot with DirectoryIndexImpl
bd9bfa8: fix testdata
51f20ec: IDEA-116628 No nulls in type parameters
1db5836: CharArrayUtil should not return array that's longer than CharSequence
2199afd: IDEA-116838 Make iteration order in com.intellij.util.containers.hash.LinkedHashMap consistent with java.util.LinkedHashMap's
5cde14b: platform: partial refresh fixed
702fee5: Cleanup (formatting)
264bf33: platform: more readable diagnostic message
c4e9893: Cleanup (bug reference updated)
a0c7d51: WEB-9933 What should happen when creating node.js Express App as New Module?
06d747d: Some html contains wrong width and height for images
c91c593: allow only string and int literals to have provided references in java
85af401: try to recover after finding stub in a non-stub file
c7a0408: get rid of psi/doc inconsistency before reparse by not relying on TextBlock information
badc25d: trying to make sense of p4 timeout in tests
8baba96: avoid double vfs name retrieval on initialization
68c0e46: UI HELL
f588bc4: Merge branch 'python-intellilang-injector'
f4a5f9a: Don't inject any language into percent-based Python formatting even without formatting operator (PY-10771)
67c086f: Fixed SQL select IntelliLang pattern (PY-10926)
3cf543e: notnull
59858a4: IDEA-76725 New option: "Find Usages: open in new tab" to be ON by default
c5bbe86: correct test
7a68cd1: IDEA-116929 [regression] Ant: after rewriting to DOM API create target quick fix is missing
fd11bd2: Support for temporary and configuration-based IntelliLang injections in Python (PY-10983, PY-10721)
c12b687: IDEA-116497 UI hang during index update [r=Eugene.Zhuravlev]
64636bb: fix one exception from IDEA-116497
58da86d: don't search classes if there is dot in pattern
8d4977a: introduce boolean empty_element_parsed_guard_()
a83276a: Connections & GestureRecognizers
d5248a1: introduce current_position_()
52412b3: rebomb
95940fa: EA-52260 (AIOOBE: SearchTextField$MyModel.addElement)
29278f8: enable softwraps for the text viewer
48a0044: IDEA-116862 Added Maven Dependency (via Quick Fix) added with incorrect scope add tests +review CR-IC-3321
8e82d1f: UpdateToRevision and CreateTag for revision implemented for mercurial (IDEA-116440)
e1eab58: IDEA-116071 (Field can be final inspection change)
425dcbb: disable rearranger grouper test: test utility and overriden methods
49639e8: IDEA-116508 ("Local variable or parameter can be final" inspection use generates uncompilable code not extracting a really finalizable variable)
fd8772d: [log] IDEA-116470 Show "Contained in branches:" information in details
fe846c1: [log] fix action's update()
55ad98c: [log] extract SequentialLimitedLifoExecutor from DataGetter for reuse
9acf2ac: IDEA-116816 Language Injection: Parameter Info: the popup is shown at the wrong place if 'Use tabs' is on
ce567b1: IDEA-116911 Speed search: wrong background in recent files
900039e: check for disposed editor or project
6f8c745: Retina for toolwindow icons
5f8bccf: Retina for general icons
0b4bf6c: update threads icons
8f15d7f: IDEA-116784 Error Parsing Regex /\s/ in Groovy. test
1a5a951: test fix (stupid type error fixed)
bcf55e0: inverse COLLAPSE handling & sync GPUB with GK version
eee493c: rearranger test fix
9059b86: IDEA-116784 Error Parsing Regex /\s/ in Groovy
981282e: IDEA-105131 fix inplace introduce of JSExpressionStatement
d006433: EA-50192 (IOOBE: CharArrayCharSequence.<init>)
0c6d5f0: EA-51155 (IOOBE: CharArrayCharSequence.<init>)
3fadd9a: avoid unexpected read action
eaea89e: correctly handle request for the not-canonically named child
1a0e321: IDEA-107909 Rearrange entries, permanent change arrangement of elements [CR-IC-3214]
7a0250a: better colors
ad7e85e: redesign and add checkbox
c550498: NPE fix
810199f: IDEA-116824 Gradle: Provide an inspection & quickfix for multiple custom maven repo links
5bd841b: IDEA-111702 Java Rearranger illegal forward reference on fields rearrangement [CR-IC-3034]
3b019b5: registry cleanup
8b7f449: IDEA-116318 Mercurial Log: on very first context menu invocation NewBranch etc actions are available
5ea19b4: IDEA-116862 Added Maven Dependency (via Quick Fix) added with incorrect scope
5f71e19: Merge remote-tracking branch 'origin/master'
57ac847: fix test
10ee1ac: Version 0.7-beta
5357494: New '.synchronized' template + tests
4cf7e59: New '.assert' template + tests
ab95a5d: Merge branch 'svn_18_2'
d86de0f: svn: Implemented "Integrate Directory" action for command line
2539615: svn: Added useAncestry option support to merge client
c784988: New '.throw' template + tests
f90fb46: New '.switch' template + tests
d58146c: cleanup
0486d44: Merge branch 'svn_18_2'
5fdcd75: svn: Implemented "Integrate to Branch" for command line for the case when only some changes of revision are integrated
6abd8f1: svn: Implemented support to copy files from repository to working copy
456ed31: svn: Updated merge command for command line - ensured working directory used in output parsing corresponds to process working directory
ba4ff98: svn: Added event handler support to delete client
aacc6af: svn: Added dryRun option support to delete client
7de409a: Rrrr
f8d0774: 0.6-beta
55c3c44: New '.return' template provider + tests
842b299: introduce rawTokenIndex
24bb6f8: check 'idea.java.redist' property set to 'bundled-jdk' to distinguish patch for installation package with jdk from installation package without
70460fa: 'final' all the things!
e5396f4: Tests for '.par' template
5f0fae5: svn: Implemented "Integrate to Branch" for command line for the case when all changes of revision are integrated
5d5903c: do not search usages of removed constant fields in injected PSI
810cc71: New '.par' template
17cffb7: WEB-9774 Suggest camel cased identifiers for jQuery expressions
3334c0b: support hippie completion at the file start (EA-52100)
6729189: SelectAll action
7d24aa5: update tips
7f01bcd: IDEA-111702 Java Rearranger illegal forward reference on fields rearrangement [CR-IC-3034]
6837234: EA-41668 (diagnostic)
0e3ad2c9: Cleanup (readability)
8f4c028: Excluding JumpList from unit testing.
424bea4: EA-52037 - PSE: MavenProjectsTree.matchesIgnoredFilesPatterns Use PatternUtil.convertToRegex(mask)
641f934: Add additional loggin.
4bae9af: NotNull
3ae7fd7: FinderRecursivePanel: missing super.dispose() call
be23034: [log] IDEA-116100 Fix Splitter leaks.
f04ec34: [log] IDEA-116267 files -> items in the structure filter
4acdb64: SelectAll action
8c3e8d4: MacMessages. Handling untitled and non-modal dialogs.
f61dc40: FinderRecursivePanel#hasChildren() -> abstract
a084cd4: Merge remote-tracking branch 'origin/master'
f1db274: added idea.java.redist to Info.plist.
8c117e9: new icon
2ccc5e9: turn jump lists on
703852d: revisions timestamp range updated for HgBrowseTest
c165c6e: Merge branch 'master' of git.labs.intellij.net:idea/community
ebf70ac: less memory
2165e8f: more diagnostics
3b4f846: Merge branch 'master' of git.labs.intellij.net:idea/community
df14eec: fix inspired by http://crucible.labs.intellij.net/cru/CR-WS-252#c18049
558f3e6: remove obsolete file
35806f22: special icon for 'generated source' roots
3c9a22c: icon class regenerated
dd55e70: IDEA-113977 Formatter: caret is moved on next line if closing brace has wrong indent [CR-IC-3034]
119488b: Merge remote-tracking branch 'origin/master'
2ddfd6a: If command executed but is incomplete and more lines are needed prompt shouldn't be changed to ordinary one in this case.
2e9d7fa: IDEA-116833 External System: clear orphan project libraries
3fd7878: better method naming, assertion conditions correction; reliably process events posted to debugger manager thread on its termination
f4edcef: add FinderRecursivePanel#isEditable()
56e0385: WEB-9986 CSS: fuzzy search shows turned off abbreviations
e879da5: Merge remote-tracking branch 'origin/master'
8e0156e: added tests for LayoutCodeProcessor [CR-IC-2957]
0bd5325: IDEA-116833 External System: clear orphan project libraries
c8a0a87: add @since
54cd711: add @since
2609798: IDEA-116792 Valid JSP/JSPX expression marked as invalid
d611594: cleanup
5d6a0c8: CR-IC-3246
2bcd0fb: IDEA-110654 Change Signature inserts unnecessary new line in comment block
e52b7db: [git] Update the widget content on click.
c031097: test added (cherry picked from commit 7058df1)
8b48bfb: Add missing files to AppCode build
9c664ac: do not try to merge stubs if version changed: take two
7974766: Obsolete test disabled
1c11805: java: .class stub builder fixed
d4e5553: fix outdated javadoc (completion is performed in a read action)
435817e: VcsRootDetector and NotifierError tests fixed (there were .git in T ot tmp dir above, so appropriate checker found its root,then error)
51864f4: CR-IC-3246
b3fff55: open in browser — choose url, show full url, not only path (decoded form with parameters)
86971b9: WeightBasedComparator — string natural compare +review
716766a: overrides
4676884: Merge branch 'master' of git.labs.intellij.net:idea/community
8b7b23a: SSH console - credentials validation
29d749c: display order entries in DirectoryInfo.toString
c76de8d: New '.field' template + tests
dca7bbf: Merge remote-tracking branch 'origin/master'
11398a8: internal action to show non retina icons
84f5d7c: Merge remote-tracking branch 'origin/master'
1b3e25e: fit value rectangle
73eb9ba: Merge remote-tracking branch 'origin/master'
21ce816: Fix modified console options modified after creation.
239c72d: add examples to description
f000351: Merge remote-tracking branch 'origin/master'
302d210: Pty4j updated - don't close streams in UnixPtyProcess.waitFor()
f916b25: problem with several hashes argument in mercurial log fixed
250a9f8: cleanup
a8ebab2: test for Cls parsing duplicates
a6f5b9e: test fix
dae8a3c: more diagnostics
faa180a: IDEA-116758 ('equals()' between objects of inconvertible types - not working for ...= equals("differentClass"));
9256d20: Version 0.5
843e41a: Test for '.forr' template
9e238fe: fixed http://youtrack.jetbrains.com/issue/PY-2953
d9f14ad: Extract 'ForIterationTemplateProviderBase'
f14b604: Merge remote-tracking branch 'origin/master'
eeba354: simplify visitors
d878e93: read access
b2f25d8: remove unnecessary setting
148ca98: EA-52004 (NPE: CyclicClassDependencyInspection.checkElement)
d9a30c6: platform: detect case-only name changes in case-insensitive FS only
7459a38: avoid using WolfTheProblemSolver.hasSyntaxErrors is possible, because it isn't designed to be a public API
0f79597: IDEA-116731 IntelliJ theme: Database Connections dialog: Scope combobox is too narrow IDEA-116768 IntelliJ theme: text end is too close to combobox button
c35c4f9: Merge remote-tracking branch 'origin/master'
4cfe198: fixed PY-11394 "no tests were found" with django 1.6 DiscoverRunner
278d4c8: IDEA-116727: Excluded library directories: removing a root does not removes its excludes
76312cd: IDEA-116713: Excluded library directories: it's possible to exclude the same directory twice
dfb4199: IDEA-116708: Excluded library directories in jar: a) show what is excluded; b) allow to include them back
17c219c: IDEA-115760: Spring: create class intentions should not create class in 'generated sources' roots
59ff22d: disable 'mark directory as resource root' action for Flex modules (IDEA-114866)
fb27e2c: EA-51314 - Throw process start exception right in CommandExecutor.start() (without catching it and rethrowing later)
0c2e0b2: read action
0bc2bc6: Double sets property value for one change
ceafea2: do not try to merge stubs if version changed: reverted
4ce8c5b: IDEA-115308 Find usages causes IDEA to hung forever
31ddc7e: removed js-analysis-impl module
a6a900e: javadoc
7acfa4a: cleanup
4e298bc: use indicator which is less dependencies demanding
f37078b: use ApplicationEx for mock application
eb73e5d: moved to core-impl
07e864d: moved to core-impl to prevent abuse
2e7e757: IDEA-116343 IntelliJ theme: selected radio button is misplaced
3538fec: filter out artificial 'documentChanged' events from FileDocumentManager#saveAllDocuments
267e10a: IDEA-116346 IntelliJ theme: comboboxes have darker background
2ba69f0: EA-45917 - IAE: RangeMarkerImpl.<init>
3629c77: do not try to merge stubs if version changed
dcbce74: RUBY-14570: fixing strings according to proofreading results.
127560f: WEB-10019 Don't show emmet preview after simply dot
8bdc013: WEB-10017 New "Surround with emmet" popup breaks usability
40a3f43: Gradle: basic detection of test resource folders added
874cc0e: IDEA-116097 Gradle: Code Completion for dependencies doesn't work inside brackets
2859d27: don't copy ui-designer runtime classes to output if only NetBeans *.form files are found (ZD-14954)
5ec83bb: BrokenLiteralPostfixTemplateContext FATTY BOOM BOOM
e91a047: Bunch of '.fori' tests, broken literal now have valid PsiType.INT type, prefix patching for broken literals + templates starting with 'e' and 'f' (such prefixes emits double/float literals and missing from reference expression name)
2c14348: Template for ".fori" postfix
f0a81ba: Refine ".fori" behavior
a0fa1a7: EA-52027 - assert: TextRange.<init>
f227ff4: Initial '.fori' template (iteration with index) bits
5bbf2d5: Cleanup
130da8b: 0.4-beta version, cosmetics
3d4922b: Fix undo for [Tab]-expansion
5d4caa2: [Tab]-expansion, refactor
0ff1fd5: [Tab]-expansion reparse with DUMMY_IDENTIFIER
01b02eb: [Tab]-expansion kind of works...
950a800: [Tab]-expansion bits...
6b02edd: Merge remote-tracking branch 'origin/master'
5083045: Cleanup (field visibility; deprecated API)
3ae8ca2: Classes moved
875ccbd: FinderRecursivePanel: cleanup, @Nullable
f7f4ae6: com.intellij.index.IndexTest._testSavedUncommittedDocument
f0f9f18: fix user completion popup dimensions + add empty border
356a1d3: turn logging on
ce8a057: fix color
c82cb23: remove border
26e7c1d: IDEA-116350 IntelliJ theme: file settings tree views colors are misplaced
44c2332: simplify by extending ActionsTopHitProvider
572e0eb: + private static final
e17ab9d: vcs top hits
66201bd: bae class for action hits
9f9efd1: Merge remote-tracking branch 'origin/master'
8551ccb: Jython doesn't support 'exec' symbol in interactive console.
8cf3335: Path escaping in PyCharm build script
de091aa: Merge remote-tracking branch 'origin/master'
87cbca6: One more test
794b4f4: make "Suppress for 'Tests' scope" fix undoable and only show in test roots
8d2e559: More '.new' test with statements after
c77f4b7: PyConsole: correctly indent after execution of incomplete multi-line string.
efae0fc: Relocate test data into separate folders
d7a0fe6: IDEA-116701 ISE at com.intellij.psi.impl.PsiToDocumentSynchronizer.a
2afc2a7: Merge remote-tracking branch 'origin/master'
e90eef2: test names
74dc868: avoid stub index inconsistency when psi was gc'd (IDEA-111448)
5a7f3a5: cleanup removed properties used for separate licensing of RefactorJS GuiceyIDEA
357f8a1: Lot of fixes when working with types, tests for .new, cleanup
fdfc865: Merge remote-tracking branch 'origin/master'
d2b7abe: failing tests on java structure updates without modification count change
62cbb8c: FinderRecursivePanel*Test: split
a54ff04: cleanup, assertions
1d4b59b: unbalanced markers fix and also some sqlite grammar cleanup
8975b3d: Gradle: update to Gradle 1.9
5b01566: External system: project import builder fix
d8c608d: Style
0fb37e9: Style
f84f608: Style
5b4cb26: svn: @NotNull for client factories in SvnVcs
c0de092: EA-52111 (diagnostic)
1685ef9: use Set for myEnabledDescriptors instead of List (as a side effect, not-thread-safe Set implementation is used, so there would be fewer locks)
cb7367d: External system: not serializable com.intellij.util.containers.ContainerUtilRt$EmptyList replaced with Collections.emptyList
890c7d0: External system: not serializable com.intellij.util.containers.ContainerUtilRt$EmptyList replaced with Collections.emptyList
2c56fc9: show indexed file names in progress for internal mode
744ea00: Merge branch 'master' of git.labs.intellij.net:idea/community
aad94bb: IDEA-115689 - IU-132.844. Heroku AS web app deployment link
80d1203: VcsRootDetector tests temporary fix
18e2e69: EA-52123 (IAE: InvertBooleanHandler.invoke)
7774de8: code simplification
1ac6cf0: don't get compiled file text to diagnose stub-psi mismatch
7bb1b86: (IDEA-116490) remove --debug argument if hg supports parents template variables
5eda813: Email info parsing fixed
2f3154a: [log] Improve javadoc
3afe644: fixed "enterprise view" providers (cherry picked from commit a2f8611)
7ac63f3: EA-51727 - RE: PostprocessReformattingAspect.beforeDocumentChanged
8947a38: EA-47998 - assert: GrIntroduceHandlerBase.processLiteral
03b64f6: IDEA-115702 DomAnchorImpl exception
d841051: comment about syntax errors checking added
630a1ee: moved to core
dd2be1e: consider variable prefixes from code style settings
463dbe3: Gradle: EA-46321 - assert: GradleScriptType$.configureCommandLine
9b1d84d: Merge remote-tracking branch 'origin/master'
8ad5e39: External system: EA-51698 - assert: ComponentManagerImpl.getPicoContainer
2f64e67: "Suppress for 'Tests' scope" quickfix
b6da22d: Gradle: EA-51873 - AIOOBE: ImportMavenRepositoriesTask.findMavenRemoteRepositories
9d36513: frameworks step removed for Groovy modules
e899eb0: improved layout of 'setup detected frameworks' dialog (IDEA-73513)
11e0307: Merge branch 'svn_18_2'
99705ad: Unused
9c46aac: IDEA-112787 Use peg revision when retrieving file content for given revision (as file url could not exist in repository anymore)
ec4d678: Huge cleanup
6d3c75a: OMFG refactor fixUp() for '1.postfix'-like expressions from PSI to document changes, much easier but still hard as hell :(
36e1e18: Fix 'smth == 0.else' case ("0.e" is valid double literal, still breaks prefix matching a bit...)
dfa1d3d: New '.new' template on types initial impl, constructor accessibility calculation
ca01868: IDEA-113732 Handled https 'certificate issued for a different hostname, issuer is not trusted' error for command line using SVNKit authentication lifecycle
1d4229a: Cleanup
7fef758: Specify dependencies, so now it works under AndroidStudio
72cf41e: API cleanup: deprecated methods dropped
e1f6bd5: 0.3 beta
e734a8e: Extract anonymous to named class
8db9c43: Fixes for no-variant completion mode
68a3555: Merge remote-tracking branch 'origin/master'
bf277bb: Merge branch 'svn_18_2'
19202bd: Merge remote-tracking branch 'origin/master'
c8938aa: Fixed execution of incomplete multiline code fragments.
c4af687: IDEA-114717 Combined supported formats for upgrade action from both svnkit and cmd client factories
5b09102: another fix for EA-49431 - PEBCE: PersistentEnumeratorBase.<init>
f679ad3: EA-51558 - assert: PersistentHashMap.updateValueId
74fd2bd: boo
d0ca2ab: RRRR
513a1ea: Mmmm?
d2bd82b: Basic no-variants mode tests
1ec26a7: IDEA-113533 Combined supported formats for "share directory" from both svnkit and cmd client factories
ccbb1fc: IDEA-114718 Combined supported formats for checkout from both svnkit and cmd client factories
a5c24ba: Dump all lookup elements in tests, not only pure postfix
7035aa0: wait for user input out of read action (IDEA-115944, consequence of IDEA-115258)
17c0f6c: First evaluate more then add to queue.
e6bc842: Cosmetics
ed83ac2: Fix prefix matching for chained items ('in.nn' now matches 'integers.notnull')
75f377b: Simplified.
cc63d32: Attribute renamed.
c79830a: NotNull annotation.
006e155: Fixed IPython and debug console broken by console execution model changes.
07f4120: eliminate SOE
aec0db5: fix SOE
364822c: Merge remote-tracking branch 'origin/master'
6ab00eb: Destruct some code
5bbdafe: Fixed write lock assertion.
7f76634: less AI in determining whether to process words in injected PSI
6f44a83: Merge remote-tracking branch 'origin/master'
6cf0e03: IDEA-116596 (New inspection: Exception printed using System.out.println())
7807a2e: Merge remote-tracking branch 'origin/master'
d124327: Merge branch 'master' of git.labs.intellij.net:idea/community
f47f98a: Urls.newFromIdea returns not-null
d4e4a40: move Url to platform - avoid raw string
65520cb: IDEA-116521 - Heroku deployment facet: application by sample creation doesn't work
cbabd0b: Execute multi-line code fragments by runsrouce with 'exec' option instead of one line by one (PY-10769).
7c9fdd3: Refactor
47a80e9: catch unexpected exception
eaafe8b: Refactor things
9fdd3d2: IDEA-116348 IDEA 13 starts with toolbar and Project structure toolbar hidden (cherry picked from commit e2be35a)
6112f27: remove stack trace (cherry picked from commit fc628f7)
48cbe1b: set timeout to 30 secs (cherry picked from commit 9cfb433)
10dc037: Gradle: IDEA-116166 Cannot re-import or refresh gradle project
473a17b: replace obsolete myFileType/lexer-highlighting with ConsoleViewUtil.printAsFileType
e061457: IDEA-111020 Status bar changes its height when progress is shown
496e519: LiveTemplates: Fix broken API
9b8aac5: UriUtil.trimLastSlash refine Url nullability (newFromIdea is not yet done)
3ab82b6: replace obsolete myFileType/lexer-highlighting with ConsoleViewUtil.printAsFileType
6880758: External system: prepare data in project import builder for import
d58edeb: not again.
30fedf3: Merge remote-tracking branch 'origin/master'
3611dc0: [log] Fix one more commit/author time mixture in commit details panel
026dae8: used consistent name prefix
0895ae0: EA-49679 - NSE: Thread.run
2bcf8e5: Use GrLightParameterListBuilder.copyParameters() to avoid copy-paste.
f299784: removed module js-analysis-api, fixed layout of JavascriptPlugin
f3828b0: Merge remote-tracking branch 'origin/master'
0ad875a: fixed PY-11415 GAE: Lazy Handler reference is not updated when moving to other module
34ef731: CR-IC-2986
e50df4c: cleanup
b4e7d2a: disposed check
76b3bee: fixed PY-9967 App Engine: do not resolve to installed to interpreter library
95e6103: Gradle: basic codeinsight for Gradle IdeaPlugin script block
2e427c8: wording
7951492: fix typo
f9b11f3: Merge remote-tracking branch 'origin/master'
b51fb7a: Merge remote-tracking branch 'origin/master'
a6d0ed6: report hidden type parameters (for IDEA-62748)
a6248e5: ignore internal exceptions when deleting (possibly invalid) requests
638d993: exception fix
8399e19: IDEA-115586 Support specifying default base branch and branch prefix for branches created through Task system: fixed
f2e274d: refactored for Upsource: - extracted js-analysis-* modules - moved ui-independent code to js-psi-*
57a72da: moved to indexing
6201961: moved to core-impl
0a27988: NPE in Upsource
1999b51: CR-IC-2986 MessageBuilder -> MessageDialogBuilder
07b62d0: Gradle: IDEA-115169 EAP Cardea Gradle Integration does not detect additional source folders
d8c651e: extract vars to find NPE
715d14c: EA-47212
036e287: cleanup
6f31031: EA-51728
0e495b1: avoided using JobLauncher for file downloading (CR-IC-3079)
55c498b: @NotNulls
d0b977b: IDEA-115702 DomAnchorImpl exception: element stubs indexed
f959ef1: Hides "Use auto-import" checkbox in the "Import Project" dialog.
bcfc005: Relocate copy&paste...
9128c91: Mmm
e1cd9ff: Cleanup
efb6b2b: Drop some typing :O
d5f0855: Generalize a bit
6806525: Support for 'UnfnshdTypNm.var', fixes
81e314d: AutoTestManager improvements
3d6cade: Refactor everything...
c44230b: switch off content cache (low hit rate) to save some memory
6ee757d: Decompose...
a673c02: [log] Use commit time instead of author time. Step 4. Update the filter
1a6e58d: [log] Use commit time instead of author time. Step 3. Actual change.
a5b0d90: [log] Use commit time instead of author time. Step 2. Renaming.
7388aa5: [log] Using commit time instead of author time. Step 1. Renaming.
04d706e: Cleanup.
f41449f: Broken indentetion in console fixed (PY-10776).
30e087a: Epic copy & paste :(
0f5abc4: Experimental no-variants mode support
8962e56: IDEA-116503 (some improvements to Unix shell scripts)
4403959: replacing infinite while loop with do-while doesn't need 'if'
a4236bf: replacing an infinite do-while loop with a while loop shouldn't use trickery
80450e7: ignore parentheses
ea1016c: don't let parentheses interfere with the "Redundant 'if' statement" inspection results
257df09: rename
5b1c002: Cleanup (misplaced test data)
4645f02: IDEA-113062 (using file naming convention to tell top-level classes from inner)
1483356: Cleanup (overspecified class)
dbbb643: IDEA-115580 (path selector for idea-CE.zip build as part of UE)
3023d26: Cleanup (code reuse)
88f123d: Use Condition instead of a BooleanFunction.
458145d: Fix undo issues with .arg/.cast/.for templates
52deb98: Cosmetics
318d854: Disable some templates inside code fragments (like 'evaluate expression' debugger window and so on)
0550fde: Merge remote-tracking branch 'origin/master'
c75587b: Fixed saving of env in console settings. Mappings format saving changed.
76b1549: EA-51231 (diagnostic)
ee627bb: EA-51924 (log corrupted .jar files)
cabce05: test: utility method extracted
3ede25d: IDEA-116503 (line separators in inspect.sh in Mac distributions fixed)
37056ef: Cleanup (javadoc)
f5898c5: Fixes and tests
9fbed52: New '.cast' template
28afe8b: Merge remote-tracking branch 'origin/master'
7a22316: AbstractBaseJavaLocalInspectionTool: make abstract
2aff3c0: IDEA-112242 (Improve Suspicious Array Cast)
d2b8150: clarify description
1b9ba24: clarify problem description
783d9ed: by default use breakpoint location filtering in java files with "java" language only: (IDEA-116518 AspectJ support. Add breakpoint handling)
fc91f19: tweak search match drawing on retina a little more room at the top for letters like 'l' and 'b' a little less room at the right side so the next letter is not overlapped
80d92ca: GitIntegrationEnablerTest changed to java test
752dc25: IDEA-116368 ("overly broad throws clause" "ignore exceptions declared in tests" doesn't work)
645e5c2: [git] IDEA-109511 Quick-fix of "Git Add" for tracked files.
b3ec037: more logging for NonUndoableAction
6fd000f: IDEA-108348 Add generic-based integration for Gitlab
fc3f452: IDEA-115708 Add workaround by setting global SSLContext
298a704: preload "New" action group (IDEA-116483)
3b6995e: no completion variants after class name and dot in javadoc (IDEA-116520)
b7fe304: IDEA-116446 Wrong label at report button
3e2513e: Improvment for "IDEA-106716 Don't steal focus". The effect is narrowed to progress dialogs and tip dialogs.
50501f2: cleanup
bebe0c1: update netty (investigate ref count exception)
d20effc: Fixed working directory setting in console settings.
4cad3d7: Merge remote-tracking branch 'origin/master'
6383733: Fixed saving path mappings in console settings (PY-9855).
5d851ae: Merge remote-tracking branch 'origin/master'
13f480a: IDEA-116393 ("java.lang.Error not rethrown" false negative for multi-catch)
d143f1c: Merge remote-tracking branch 'origin/master'
99ab501: improve description
925a7c5: Fix pycharm build.
2ecd8faa: IDEA-115586 Support specifying default base branch and branch prefix for branches created through Task system
07fab55: ok, but null literals shouldn't have references for sure
936a7e6: Improvement for "IDEA-106716 Don't steal focus" WelcomeScreen should not steal focus as well.
0529611: Gradle: fix issue with Gradle Tooling API classpath inferer
893ffaa: EA-50899 - ISE: GrRegexImpl.createLiteralTextEscaper
7959ed4: Groovy intentions: don't use selection model if block selection is enabled
0a0696a: IDEA-95170 closure parameter type
f38c1bc: Groovy Introduce constant: 'move to other class' in inplace mode should invoke dialog
1b7d8fc: Ups
aca0057: New .arg template
b8c4af2: standard java html browser doesn't support % in width and height
ff90a81: Merge remote-tracking branch 'origin/master'
567beaf: fix hardcoded completion popup bg (cherry picked from commit fa7a25b)
80bc6b9: Prettify code
f5125ce: Fix .var over expressions (caret placement, prevent from loosing comments/whitespace/semicolons)
8cb7aa7: IDEA-116415 Event log: all notifications before its opening get the timestamp of the opening
2d2caa6: Fix '2 + 2.var * 2' case
f121a2b: PsiSearchHelper.processElementsWithWord that doesn't walk injected PSI
673551a: Cosmetics
7e92b87: Set since-version to first IDEA 13 preview build version. Update readme.md
6c4e09e: Merge remote-tracking branch 'origin/master'
057b563: add debug logging to see who is guilty of "Cannot undo" messages
72f189d: let non-string literal expressions have no references
5e48524: remove external annotation root duplicates resulting by several modules using the same sdk
b4e89df: Merge branch 'python-fixes'
c6cc5c7: Extracted Python path walking and fixed broken symlink check (PY-10534)
9df86d3: Make .for work independently from standard "I" (Iterate shortcut) template existence
0dfae8b: revert platform fix for PY-6095, apply Python specifix fix instead
778380c: Fix broken Grails debug.
9741a1d: Merge remote-tracking branch 'origin/master'
6dd1423: IDEA-116324 IDEA 13 compiler uses some old xmx setting
eb5911c: Show branch name only once in case of multiple heads ( in status bar widget and log branch filter).
668c3f4: The functionality should be temporary disabled on Mac. The focus stays on dialog owner.
d65b254: Gradle: fixed IndexNotReadyException for MavenProjectIndicesManager usage in startup activity
fc03f41: IDEA-116422 Tweak "Drag'n'Drop" wording
b07b78d: faster simple accessor folding check
1d18499: [^jeka] ant create property cosmetics
368c36f: Made Run-configuration-related keys public.
f670e1d: IDEA-116458 Application menu is lost after rejecting exit from IDE
baff9f0: make 'No matches' bold
5d0e2d3: Merge remote-tracking branch 'origin/master'
323d9b1: installer fixes
f33c8aa: Improvement for IDEA-106716. We should not rely on the recent focused frame if we have only one empty frame.
36a5241: IDEA-114804 File types mapped to text are not remapped when corresponding plugin is installed
f39c910: ignore width and height in img tag
73b216c: determine tag end by doctype #WEB-2229 fixed
6a6560e: don't check script inside true html files #WEB-9833 fixed
5222ad0: fix installer
c88b649: return back custom maven index restoration upon corruption, only avoid logging exception when persistent enumerator version was upgraded
28e3c0d: throw VersionUpdatedException if existing enumerator wasn't dirty, there is no need to report it for example
e9ba764: InspectionDescriptionNotFoundInspection -> ERROR level
b3c0ae1: IDEA-116445 IntelliJ laf: Menu bar is hardly visible on Linux
84a4644: IDEA-116431 IntelliJ laf: menu shortcuts are invisible
502dff5: update tips resources
b0f008b: update camel case in goto tips
a6f250f: update camel completion tips
a8e4da3: update annotations tips
2e90122: support for retina and darcula images
88e9127: merge AntMissingPropertyInspection into more general AntResolveInspection
a200ab2: fix merge error
dfef0e3: CR-IC-2986 MessageBuilder
d4a628e: cleanup
d544bad: assertion for PersistentFS returning unique file names, a bit of optimisation
6516b9a: avoid using CharBuffer.subSequence() because its signature is different in jdk6/7
5e84485: compare Messages.showYesNoCancelDialog with correct values: Messages.YES/Messages.NO/Messages.CANCEL
b4e394f: compare Messages.showYesNoDialog with correct values: Messages.YES/Messages.NO
a51190d: compare Messages.showOkCancelDialog with correct values: Messages.OK/Messages.CANCEL
61be092: Don't ask to reconnect remote interpreter in case of fail as it never helps but causes problems (PY-10590).
28d673a: Cleanup (test)
c980dd8: platform: OS release info in usage statistics
1522798: IDEA-116328 (Method can be variable arity method inspection should not highlight for @Nullable parameters)
6039b2b: [by the patch from opticyclic] quick fix to create a property from unresolved property reference (IDEA-57875)
c161577: module util must not depends on Guava (incorrect usage was moved to platform-impl UriUtil) +review
e452798: continue "open actual script source" extract common code to XSourcePositionWrapper
fcddb47: cleanup
1baa4fa: IDEA-113730 Reverted CmdContentClient implementation back - as export could not be used to get contents of scheduled for deletion file
4fc7cd5: Merge branch 'svn_18_2'
28987dc: Jar updated.
042d6f3: Merge remote-tracking branch 'origin/master'
774b67c: pty4j updated to avoid multi-threading problem with ptsname()
2155e52: IDEA-116241 filtering by structure supported in Mercurial log
28f2ac3: correctly handle inner classes removal
9cbd59e: Merge remote-tracking branch 'origin/master'
812465c: Fixed libpty location for pycharm community build.
27308fa: Decompose
f371c40: [log] Remove unused methods & fields
f81d6b8: IDEA-113152 Groovy: In-Place Introduce Refactoring: PIEAE at GrCodeReferenceElementImpl.multiResolve()
f296f2c: unwanted reference overwriting fix, take 3
3323bec: IDEA-116371 (NPE in BrowserUtil fixed)
2bfb1f5: typo
fdba133: don't show dependencies in 'add module dependency' fix if they are forbidden by dependency validation rules
d9188ea: Exception fix
973fd26: IDEA-116271 groovy autocomplete tries to complete in /* */ comments
80755bd: IDEA-115699 Groovy: "Convert to Singleline Literal" intention shouldn't be shown for single-line slashy and dollar-slashy string literals
9249c20: Gradle: war artifact configuration IDEA-109369 External system: Correct WAR artifact setup on external system config change
30efd4e: IDEA-113730 Implemented content retrieval using export command (this eliminates encoding issues and correctly handle binary formats)
88ad884: Annotation for HgRepoInfo changed
22f4b6a: import new .iml file into community project
f736377: [log] Better approach to details filtering
01525be: Templates: add diagnostic info
35597e5: Parse username and user email if it is possible.
00cdb40: Problem with annotation user fixed
41d5f82: IDEA-116378 only expressions are available in loop conditions
a4e4ceb: fix typo that broke GeneralCodeFormatterTest
276f65a: svn: Unify credentials caching in memory logic for ssh and other protocols
ca13b82: platform: prematurely deprecated API returned
1fd0181: EA-51338 - CME: DocumentFoldingInfo.clear
d278cef: EA-51538 - assert: PsiDocumentManagerBase.cancelAndRunWhenAllCommitted
023aed1: EA-51560 - assert: TextRange.<init>
9efc4b2: trunk now 134
92c68fe: IDEA-106716 Don't steal focus [for jdk7]
3410f4d: about: scheme handling via web reference #WEB-7451 fixed
18c2e9a: IDEA-115798 New Project Wizard: templates panel changes its width on selecting some technologies
ec0ee95: edit contract for the compiled element, not its source
821bd24: remove frequently changing and likely useless file name from index progresses (IDEA-115130)
ab04a9d: simple testdata
f693902: New .while template, tests
7b2c051: Update plugin.xml
805e4f2: Less .for availability, test and other refinements
cd75f75: Assert final caret position in tests, fix caret, disable .null/.notnull on 'new T()' expressions, etc
f9904cc: IDEA-113860 Display dialog if credentials for certain repository are asked more than one time during single command execution (treat such situation as "previous credentials were wrong")
115f30b: svn: Refactored "svn process finished" logic in CommandRuntime (method extractions)
16d7f4a: Much better detection of nullable and boolean expression, disable all templates on types by default
2e3c561: Bring back useless code, lol
b7f56b4: More tests, remove some useless code
751597a: Simplifying things
2adbe3c: .gitignore rrrr
56e4c35: .gitignore
0dc3f74: .gitignore
c8d2a34: Notes
fa99902: Extract PostfixExecutionContext, get and store dummyIdentifier, all tests green.
9172e27: Decompose, fix issues with "xs.length > 0"
7ef1dd3: Support hard expression like "2 * 2.var + 2 * 2"
93733c5: Handle cases like '2 * 2.var + 2 * 2', moar .var tests, bits of standalone types support
47e970a: Delete alexander.xml
86507b1: Delete workspace.xml
ffdd40c: Initial .for template for iteration, disable some templates on types/packages
93e107a: New .not template for expressions + tests, .notnull/.null tests
12c66cb: Cosmetics
825c6e8: New .notnull/.null templates pair for nullability checks
87b080c: Refine force mode for .var, expression.var tests
972b6ee: Small fix
562ee90: Now .var works on expressions
ed16be7: So freakin tired :(
f9ab422: Basic .var on types, disable when expression type is unknown/on vars/locals, fixes
f72087e: fix 'fixUp' phase for expressions like `o != null.postfix`
7ea7425: Decompose StatementPostfixLookupElement.java
bc81fbb: new T() { }.var tests
57d1bc3: .var test, fix some issue
6e31aa7: .else test, readme
2eae01f: Meaningless project-wide code reformat (get rid of 'final' modifier for locals and parameters where possible)
d87c9b5: Decompose, new .else template
a6760ce: Downgrade project to java 1.6
66cb584: Support for "o is T.if" expressions
b91ee72: Tests all green
f8499a3: Remove workspace.xml from vcs
06a54ac: Optimize usings
7b3af96: Cleanup
ac7d68f: Cleanup
3780280: Basic .var functionality, solve undo stack issues
7abf5f8: Java shit bits, decompose
187498d: Moar workarounds, tests
a8431a9: First green test
a07c277: Trying to implement tests
27d95ba: Expression 'fixing' logic bits2
4ec9b7c: Expression 'fixing' logic bits
c8c91a6: Merge remote-tracking branch 'origin/master'
51552f0: Small fixes
a7b2ddb: Code monkey
f64564d: Code monkey
472d129: Even moar code
8050ba5: Moar code
ccc1053: 'final' all the things, lol. PrefixExpressionContext building
1c54ba9: Bits of 'x > 0.if'-like expressions support
2040031: Mmmm
eca0326: Fighting against component model
2456976: Exploring Java, lol
2686df7: Mmm
d6eb6dc: Initial
5b63b3e: Initial commit
725754d: Merge remote-tracking branch 'origin/master'
933ff6b: Merge remote-tracking branch 'origin/master'
d73a2d5: Merge remote-tracking branch 'origin/master'
5928f8a: IDEA-111701 Emacs: pressing Ctrl+k several times should add lines to muti-line buffer
Change-Id: Ib325575bfdf68fc4009119574543e2ef6217f113
diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml
index b84d8ef..19fba77 100644
--- a/.idea/copyright/profiles_settings.xml
+++ b/.idea/copyright/profiles_settings.xml
@@ -1,6 +1,5 @@
<component name="CopyrightManager">
<settings default="apache 2 license">
- <module2copyright />
<LanguageOptions name="__TEMPLATE__">
<option name="addBlankAfter" value="false" />
</LanguageOptions>
diff --git a/.idea/inspectionProfiles/idea_default.xml b/.idea/inspectionProfiles/idea_default.xml
index f4e8a0f..8924010 100644
--- a/.idea/inspectionProfiles/idea_default.xml
+++ b/.idea/inspectionProfiles/idea_default.xml
@@ -134,6 +134,7 @@
<inspection_tool class="InfiniteLoopJS" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="InfiniteRecursionJS" enabled="false" level="WARNING" enabled_by_default="false" />
<inspection_tool class="InnerClassMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true" />
+ <inspection_tool class="InspectionDescriptionNotFoundInspection" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="InstanceofCatchParameter" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InstanceofIncompatibleInterface" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="InterceptionAnnotationWithoutRuntimeRetention" enabled="false" level="WARNING" enabled_by_default="false" />
diff --git a/.idea/libraries/Groovy.xml b/.idea/libraries/Groovy.xml
index d8e0e9e..e396e49 100644
--- a/.idea/libraries/Groovy.xml
+++ b/.idea/libraries/Groovy.xml
@@ -1,45 +1,46 @@
<component name="libraryTable">
<library name="Groovy">
<CLASSES>
- <root url="jar://$PROJECT_DIR$/lib/groovy-all-2.0.6.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/groovy-all-2.2.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-json/src/main/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-json/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-test/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-xml/src/test/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-xml/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-servlet/src/test/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-servlet/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-console/src/main/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-bsf/src/test/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-bsf/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-groovysh/src/main/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-templates/src/test/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-templates/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-sql/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-swing/src/test/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-swing/src/main/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-swing/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-groovydoc/src/test/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-groovydoc/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-testng/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-jsr223/src/test/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-jsr223/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-jmx/src/test/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-jmx/src/test/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-jmx/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-ant/src/test/groovy" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-ant/src/test-resources" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/subprojects/groovy-ant/src/main/java" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/benchmark/bench" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/src/tck/src" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/src/test" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/src/test-resources/stubgenerator/propertyUsageFromJava" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/src/test-resources/stubgenerator/circularLanguageReference" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/src/examples" />
- <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.0.6.zip!/groovy-2.0.6/src/main" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/src/tck/src" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/src/main" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/src/test" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/src/examples" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/src/test-resources" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/buildSrc/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/benchmark/bench" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-ant/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-ant/src/test/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-ant/src/test-resources" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-bsf/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-bsf/src/test/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-jmx/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-jmx/src/test/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-jmx/src/test/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-sql/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-xml/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-xml/src/test/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-json/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-json/src/main/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-test/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-test/src/test/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-swing/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-swing/src/main/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-swing/src/test/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-jsr223/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-jsr223/src/test/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-testng/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-console/src/main/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-servlet/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-servlet/src/test/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-groovysh/src/main/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-groovydoc/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-groovydoc/src/test/groovy" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-templates/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/groovy-src-2.2.1.zip!/groovy-2.2.1/subprojects/groovy-templates/src/test/java" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/.idea/libraries/JUnit4.xml b/.idea/libraries/JUnit4.xml
index 3d61767..93d4c1c 100644
--- a/.idea/libraries/JUnit4.xml
+++ b/.idea/libraries/JUnit4.xml
@@ -1,11 +1,15 @@
<component name="libraryTable">
<library name="JUnit4">
<CLASSES>
- <root url="jar://$PROJECT_DIR$/lib/junit-4.10.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/hamcrest-core-1.3.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/junit-4.11.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/hamcrest-library-1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$PROJECT_DIR$/lib/src/junit-4.10-src.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/src/junit-4.11-src.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/src/hamcrest-1.3-src.zip!/hamcrest-core/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/hamcrest-1.3-src.zip!/hamcrest-library/src/main/java" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/.idea/libraries/Netty.xml b/.idea/libraries/Netty.xml
index 58682b2..8037545 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-4.1.0.Alpha1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/netty-all-5.0.0.Alpha1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$PROJECT_DIR$/lib/src/netty-all-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/src/netty-all-5.0.0.Alpha1-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/.idea/libraries/commons_logging.xml b/.idea/libraries/commons_logging.xml
index a9622f7..43ec77e 100644
--- a/.idea/libraries/commons_logging.xml
+++ b/.idea/libraries/commons_logging.xml
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="commons-logging">
<CLASSES>
- <root url="jar://$PROJECT_DIR$/lib/commons-logging-1.1.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-logging-1.1.3.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$PROJECT_DIR$/lib/src/commons-logging-1.1.1-src.zip!/commons-logging-1.1.1-src/src/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/commons-logging-1.1.3-src.zip!/commons-logging-1.1.3-src/src/main/java" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/.idea/libraries/gson.xml b/.idea/libraries/gson.xml
index beaa3d7..38af989 100644
--- a/.idea/libraries/gson.xml
+++ b/.idea/libraries/gson.xml
@@ -1,11 +1,11 @@
<component name="libraryTable">
<library name="gson">
<CLASSES>
- <root url="jar://$PROJECT_DIR$/lib/gson-2.2.3.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/gson-2.2.4.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$PROJECT_DIR$/lib/src/gson-2.2.3-sources.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/src/gson-2.2.4-sources.jar!/" />
</SOURCES>
</library>
</component>
\ No newline at end of file
diff --git a/.idea/libraries/http_client.xml b/.idea/libraries/http_client.xml
new file mode 100644
index 0000000..d4e6547
--- /dev/null
+++ b/.idea/libraries/http_client.xml
@@ -0,0 +1,20 @@
+<component name="libraryTable">
+ <library name="http-client">
+ <CLASSES>
+ <root url="jar://$PROJECT_DIR$/lib/httpcore-4.3.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/httpclient-4.3.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/httpmime-4.3.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/fluent-hc-4.3.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-client-4.3.1-src.zip!/httpcomponents-client-4.3.1/httpmime/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-client-4.3.1-src.zip!/httpcomponents-client-4.3.1/httpmime/src/main/java-deprecated" />
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-client-4.3.1-src.zip!/httpcomponents-client-4.3.1/httpclient/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-client-4.3.1-src.zip!/httpcomponents-client-4.3.1/httpclient/src/main/java-deprecated" />
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-core-4.3-src.zip!/httpcomponents-core-4.3/httpcore/src/main/java" />
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-core-4.3-src.zip!/httpcomponents-core-4.3/httpcore/src/main/java-deprecated" />
+ <root url="jar://$PROJECT_DIR$/lib/src/httpcomponents-client-4.3.1-src.zip!/httpcomponents-client-4.3.1/fluent-hc/src/main/java" />
+ </SOURCES>
+ </library>
+</component>
\ No newline at end of file
diff --git a/.idea/libraries/http_client_3_1.xml b/.idea/libraries/http_client_3_1.xml
index f3726b7..bff58b3 100644
--- a/.idea/libraries/http_client_3_1.xml
+++ b/.idea/libraries/http_client_3_1.xml
@@ -1,7 +1,7 @@
<component name="libraryTable">
<library name="http-client-3.1">
<CLASSES>
- <root url="jar://$PROJECT_DIR$/lib/commons-logging-1.1.1.jar!/" />
+ <root url="jar://$PROJECT_DIR$/lib/commons-logging-1.1.3.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/commons-httpclient-3.1-patched.jar!/" />
</CLASSES>
<JAVADOC>
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 804f4a7..941f718 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -4,10 +4,7 @@
<entry_points version="2.0" />
</component>
<component name="FrameworkDetectionExcludesConfiguration">
- <file type="android" url="file://$PROJECT_DIR$/plugins/android/testData/AndroidManifest.xml" />
- <file type="android" url="file://$PROJECT_DIR$/plugins/android/testData/lint/global/buttonsOrder/AndroidManifest.xml" />
- <file type="android" url="file://$PROJECT_DIR$/plugins/android/testData/lint/global/manifestOrder/AndroidManifest.xml" />
- <file type="android" url="file://$PROJECT_DIR$/plugins/android/testData/resNavigation/AndroidManifest.xml" />
+ <file url="file://$PROJECT_DIR$" />
</component>
<component name="IdProvider" IDEtalkID="88DB5D232B345F18EEFB2825E88EC093" />
<component name="JavadocGenerationManager">
@@ -31,7 +28,7 @@
<option name="projectName" value="idea-community" />
</component>
<component name="ProjectKey">
- <option name="state" value="$PROJECT_DIR$/.idea/misc.xml" />
+ <option name="state" value="git@git.labs.intellij.net:idea/community" />
</component>
<component name="ProjectResources">
<default-html-doctype>http://www.w3.org/1999/xhtml</default-html-doctype>
diff --git a/.idea/modules.xml b/.idea/modules.xml
index 5d00c5a..8a2dc3d 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -46,8 +46,8 @@
<module fileurl="file://$PROJECT_DIR$/platform/dvcs/dvcs.iml" filepath="$PROJECT_DIR$/platform/dvcs/dvcs.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/eclipse.iml" filepath="$PROJECT_DIR$/plugins/eclipse/eclipse.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/eclipse/jps-plugin/eclipse-jps-plugin.iml" group="plugins" />
- <module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" />
- <module fileurl="file://$PROJECT_DIR$/platform/editor-ui-ex/editor-ui-ex.iml" filepath="$PROJECT_DIR$/platform/editor-ui-ex/editor-ui-ex.iml" />
+ <module fileurl="file://$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" filepath="$PROJECT_DIR$/platform/editor-ui-api/editor-ui-api.iml" group="platform" />
+ <module fileurl="file://$PROJECT_DIR$/platform/editor-ui-ex/editor-ui-ex.iml" filepath="$PROJECT_DIR$/platform/editor-ui-ex/editor-ui-ex.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/java/execution/impl/execution-impl.iml" filepath="$PROJECT_DIR$/java/execution/impl/execution-impl.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/execution/openapi/execution-openapi.iml" filepath="$PROJECT_DIR$/java/execution/openapi/execution-openapi.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/platform/extensions/extensions.iml" filepath="$PROJECT_DIR$/platform/extensions/extensions.iml" group="platform" />
@@ -60,7 +60,11 @@
<module fileurl="file://$PROJECT_DIR$/plugins/github/github.iml" filepath="$PROJECT_DIR$/plugins/github/github.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/google-app-engine.iml" group="plugins/GAE" />
<module fileurl="file://$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/google-app-engine/jps-plugin/google-app-engine-jps-plugin.iml" group="plugins/GAE" />
- <module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/gradle/gradle.iml" filepath="$PROJECT_DIR$/plugins/gradle/gradle.iml" group="community/plugins/gradle" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension/gradle-tooling-extension.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension/gradle-tooling-extension.iml" group="community/plugins/gradle" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-v1.11/gradle-tooling-extension-v1.11.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-v1.11/gradle-tooling-extension-v1.11.iml" group="community/plugins/gradle" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-v1.12/gradle-tooling-extension-v1.12.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-v1.12/gradle-tooling-extension-v1.12.iml" group="community/plugins/gradle" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/gradle/tooling-extension-v1.9/gradle-tooling-extension-v1.9.iml" filepath="$PROJECT_DIR$/plugins/gradle/tooling-extension-v1.9/gradle-tooling-extension-v1.9.iml" group="community/plugins/gradle" />
<module fileurl="file://$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" filepath="$PROJECT_DIR$/plugins/groovy/jps-plugin/groovy-jps-plugin.iml" group="plugins/Groovy" />
<module fileurl="file://$PROJECT_DIR$/plugins/groovy/rt-constants/groovy-rt-constants.iml" filepath="$PROJECT_DIR$/plugins/groovy/rt-constants/groovy-rt-constants.iml" group="plugins/Groovy" />
<module fileurl="file://$PROJECT_DIR$/plugins/groovy/rt/groovy_rt.iml" filepath="$PROJECT_DIR$/plugins/groovy/rt/groovy_rt.iml" group="plugins/Groovy" />
@@ -124,6 +128,8 @@
<module fileurl="file://$PROJECT_DIR$/platform/projectModel-api/projectModel-api.iml" filepath="$PROJECT_DIR$/platform/projectModel-api/projectModel-api.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/projectModel-impl/projectModel-impl.iml" filepath="$PROJECT_DIR$/platform/projectModel-impl/projectModel-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/plugins/properties/properties.iml" filepath="$PROJECT_DIR$/plugins/properties/properties.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/properties/properties-psi-api/properties-psi-api.iml" filepath="$PROJECT_DIR$/plugins/properties/properties-psi-api/properties-psi-api.iml" group="plugins" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/properties/properties-psi-impl/properties-psi-impl.iml" filepath="$PROJECT_DIR$/plugins/properties/properties-psi-impl/properties-psi-impl.iml" group="plugins" />
<module fileurl="file://$PROJECT_DIR$/python/python-community.iml" filepath="$PROJECT_DIR$/python/python-community.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/build/python-community-build.iml" filepath="$PROJECT_DIR$/python/build/python-community-build.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/pluginSrc/python-community-plugin.iml" filepath="$PROJECT_DIR$/python/pluginSrc/python-community-plugin.iml" group="python" />
@@ -136,9 +142,9 @@
<module fileurl="file://$PROJECT_DIR$/python/python-pydev.iml" filepath="$PROJECT_DIR$/python/python-pydev.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/python/python-rest/python-rest.iml" filepath="$PROJECT_DIR$/python/python-rest/python-rest.iml" group="python" />
<module fileurl="file://$PROJECT_DIR$/xml/relaxng/relaxng.iml" filepath="$PROJECT_DIR$/xml/relaxng/relaxng.iml" group="plugins" />
- <module fileurl="file://$PROJECT_DIR$/platform/remote-servers/agent-rt/remote-servers-agent-rt.iml" filepath="$PROJECT_DIR$/platform/remote-servers/agent-rt/remote-servers-agent-rt.iml" />
+ <module fileurl="file://$PROJECT_DIR$/platform/remote-servers/agent-rt/remote-servers-agent-rt.iml" filepath="$PROJECT_DIR$/platform/remote-servers/agent-rt/remote-servers-agent-rt.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/remote-servers/api/remote-servers-api.iml" filepath="$PROJECT_DIR$/platform/remote-servers/api/remote-servers-api.iml" group="platform" />
- <module fileurl="file://$PROJECT_DIR$/plugins/git4idea/remote-servers-git/remote-servers-git.iml" filepath="$PROJECT_DIR$/plugins/git4idea/remote-servers-git/remote-servers-git.iml" />
+ <module fileurl="file://$PROJECT_DIR$/plugins/git4idea/remote-servers-git/remote-servers-git.iml" filepath="$PROJECT_DIR$/plugins/git4idea/remote-servers-git/remote-servers-git.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/platform/remote-servers/impl/remote-servers-impl.iml" filepath="$PROJECT_DIR$/platform/remote-servers/impl/remote-servers-impl.iml" group="platform" />
<module fileurl="file://$PROJECT_DIR$/java/remote-servers/api/remote-servers-java-api.iml" filepath="$PROJECT_DIR$/java/remote-servers/api/remote-servers-java-api.iml" group="java" />
<module fileurl="file://$PROJECT_DIR$/java/remote-servers/impl/remote-servers-java-impl.iml" filepath="$PROJECT_DIR$/java/remote-servers/impl/remote-servers-java-impl.iml" group="java" />
diff --git a/RegExpSupport/src/META-INF/RegExpPlugin.xml b/RegExpSupport/src/META-INF/RegExpPlugin.xml
index b84bc65..fab5139 100644
--- a/RegExpSupport/src/META-INF/RegExpPlugin.xml
+++ b/RegExpSupport/src/META-INF/RegExpPlugin.xml
@@ -1,7 +1,8 @@
<idea-plugin>
<extensionPoints>
- <extensionPoint name="regExpLanguageHost" beanClass="com.intellij.openapi.util.ClassExtensionPoint"/>
- <extensionPoint name="regExpPropertiesProvider" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
+ <extensionPoint name="regExpLanguageHost" beanClass="com.intellij.openapi.util.ClassExtensionPoint">
+ <with attribute="implementationClass" implements="org.intellij.lang.regexp.RegExpLanguageHost"/>
+ </extensionPoint>
<extensionPoint name="regExpModifierProvider" interface="org.intellij.lang.regexp.RegExpModifierProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
diff --git a/bin/linux/libnotifywrapper.so b/bin/linux/libnotifywrapper.so
new file mode 100755
index 0000000..7ed0beb
--- /dev/null
+++ b/bin/linux/libnotifywrapper.so
Binary files differ
diff --git a/bin/linux/libnotifywrapper64.so b/bin/linux/libnotifywrapper64.so
new file mode 100755
index 0000000..d78fba9
--- /dev/null
+++ b/bin/linux/libnotifywrapper64.so
Binary files differ
diff --git a/bin/win/runnerw.exe b/bin/win/runnerw.exe
index d9155d3..affd133 100644
--- a/bin/win/runnerw.exe
+++ b/bin/win/runnerw.exe
Binary files differ
diff --git a/build.txt b/build.txt
index 042f325..c0c3370 100644
--- a/build.txt
+++ b/build.txt
@@ -1 +1 @@
-133.SNAPSHOT
+134.SNAPSHOT
diff --git a/build.xml b/build.xml
index cf640ec..8e6bdbc 100644
--- a/build.xml
+++ b/build.xml
@@ -17,7 +17,7 @@
<sequential>
<java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
<jvmarg line="-Xmx612m -XX:MaxPermSize=152m"/>
-
+ <sysproperty key="java.awt.headless" value="true"/>
<arg line=""-Dgant.script=@{script}""/>
<arg line=""-Dteamcity.build.tempDir=${tmp.dir}""/>
<arg line=""-Didea.test.group=ALL_EXCLUDE_DEFINED""/>
diff --git a/build/build.iml b/build/build.iml
index 8c1854c..db115fb 100644
--- a/build/build.iml
+++ b/build/build.iml
@@ -31,6 +31,9 @@
</orderEntry>
<orderEntry type="module" module-name="antlayout" exported="" />
<orderEntry type="module" module-name="util" exported="" />
+ <orderEntry type="module" module-name="ui-designer-jps-plugin" scope="RUNTIME" />
+ <orderEntry type="module" module-name="groovy-jps-plugin" scope="RUNTIME" />
+ <orderEntry type="module" module-name="groovy_rt" scope="RUNTIME" />
</component>
</module>
diff --git a/build/lib/gant/bin/startGroovy b/build/lib/gant/bin/startGroovy
index f9e6251..9e9ccf3 100755
--- a/build/lib/gant/bin/startGroovy
+++ b/build/lib/gant/bin/startGroovy
@@ -127,7 +127,7 @@
if [ -z "$GROOVY_CONF" ] ; then
GROOVY_CONF="$GROOVY_HOME/conf/groovy-starter.conf"
fi
-STARTER_CLASSPATH="$GROOVY_HOME/lib/groovy-all-2.0.6.jar"
+STARTER_CLASSPATH="$GROOVY_HOME/lib/groovy-all-2.2.1.jar"
# Create the final classpath. Setting a classpath using the -cp or -classpath option means not to use the
# global classpath. Groovy behaves then the same as the java interpreter
diff --git a/build/lib/gant/bin/startGroovy.bat b/build/lib/gant/bin/startGroovy.bat
index e7c3476..d2b1436 100755
--- a/build/lib/gant/bin/startGroovy.bat
+++ b/build/lib/gant/bin/startGroovy.bat
@@ -203,7 +203,7 @@
:execute
@rem Setup the command line
-set STARTER_CLASSPATH=%GROOVY_HOME%\%JARSPATH%\groovy-all-2.0.6.jar;%STARTER_CLASSPATH%
+set STARTER_CLASSPATH=%GROOVY_HOME%\%JARSPATH%\groovy-all-2.2.1.jar;%STARTER_CLASSPATH%
if exist "%USERPROFILE%/.groovy/init.bat" call "%USERPROFILE%/.groovy/init.bat"
diff --git a/build/lib/gant/gant_groovy2.1-1.9.10-sources.jar b/build/lib/gant/gant_groovy2.1-1.9.10-sources.jar
new file mode 100644
index 0000000..776f888
--- /dev/null
+++ b/build/lib/gant/gant_groovy2.1-1.9.10-sources.jar
Binary files differ
diff --git a/build/lib/gant/lib/gant_groovy2.0-1.9.8.jar b/build/lib/gant/lib/gant_groovy2.0-1.9.8.jar
deleted file mode 100644
index 3d0d1ca..0000000
--- a/build/lib/gant/lib/gant_groovy2.0-1.9.8.jar
+++ /dev/null
Binary files differ
diff --git a/build/lib/gant/lib/gant_groovy2.1-1.9.10.jar b/build/lib/gant/lib/gant_groovy2.1-1.9.10.jar
new file mode 100644
index 0000000..8f8fc1e
--- /dev/null
+++ b/build/lib/gant/lib/gant_groovy2.1-1.9.10.jar
Binary files differ
diff --git a/build/lib/gant/src.zip b/build/lib/gant/src.zip
deleted file mode 100644
index 147e740..0000000
--- a/build/lib/gant/src.zip
+++ /dev/null
Binary files differ
diff --git a/build/lib/launcher-generator.jar b/build/lib/launcher-generator.jar
index b86185b..19951b9 100644
--- a/build/lib/launcher-generator.jar
+++ b/build/lib/launcher-generator.jar
Binary files differ
diff --git a/build/order.txt b/build/order.txt
index 94652b3..f93a7f2 100644
--- a/build/order.txt
+++ b/build/order.txt
@@ -9083,7 +9083,6 @@
inspectionDescriptions/IncompatibleMask.html:/plugins/InspectionGadgets/lib/resources_en.jar
inspectionDescriptions/PointlessBitwiseExpression.html:/plugins/InspectionGadgets/lib/resources_en.jar
inspectionDescriptions/ShiftOutOfRange.html:/plugins/InspectionGadgets/lib/resources_en.jar
-inspectionDescriptions/ArchaicSystemPropertyAccess.html:/plugins/InspectionGadgets/lib/resources_en.jar
inspectionDescriptions/ArrayEquals.html:/plugins/InspectionGadgets/lib/resources_en.jar
inspectionDescriptions/AssertWithSideEffects.html:/plugins/InspectionGadgets/lib/resources_en.jar
inspectionDescriptions/ConstantAssertCondition.html:/plugins/InspectionGadgets/lib/resources_en.jar
diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant
index 63b1027..8b0fbf8 100644
--- a/build/scripts/layouts.gant
+++ b/build/scripts/layouts.gant
@@ -47,7 +47,6 @@
def layoutFull(String home, String targetDirectory, String patchedDescriptorDir = null) {
projectBuilder.stage("layout to $targetDirectory")
- //noinspection GroovyAssignabilityCheck
List<String> openapiModules = [platformApiModules,
"compiler-openapi",
"debugger-openapi",
@@ -62,10 +61,8 @@
"remote-servers-api",
"remote-servers-java-api",
"testFramework-java",
- "xml-analysis-api",
].flatten()
- //noinspection GroovyAssignabilityCheck
List<String> implementationModules = [platformImplementationModules,
"compiler-impl",
"debugger-impl",
@@ -85,7 +82,6 @@
"remote-servers-java-impl",
"testFramework",
"tests_bootstrap",
- "xml-analysis-impl",
].flatten()
ant.patternset(id: "resources.included") {
@@ -114,12 +110,6 @@
fileset(dir: "${home}/lib/rt", includesfile: "${home}/lib/rt/required_for_dist.txt")
}
- dir("groovy") {
- dir("lib") {
- fileset(dir:"$home/lib/groovy/lib")
- }
- }
-
dir("libpty") {
fileset(dir: "$home/lib/libpty") {
exclude(name: "readme.txt")
@@ -226,6 +216,8 @@
module("common-javaFX-plugin")
}
}
+
+ fileset(dir: "${home}/plugins/javaFX/FxBuilderEmbedder/lib", includes: "embedder.jar");
}
}
@@ -257,7 +249,7 @@
}
dir("plugins") {
- def simplePlugins = ["commander", "copyright", "properties", "java-i18n", "hg4idea", "github", "ui-designer-core"] //, "tasks-time-tracking"]
+ def simplePlugins = ["commander", "copyright", "java-i18n", "hg4idea", "github", "ui-designer-core"] //, "tasks-time-tracking"]
simplePlugins.each {
layoutPlugin it
@@ -276,6 +268,16 @@
}
}
+ pluginDir("properties") {
+ dir("lib") {
+ jar("properties.jar") {
+ module("properties-psi-api")
+ module("properties-psi-impl")
+ module("properties")
+ }
+ }
+ }
+
layoutPlugin("maven") {
jar("maven-jps-plugin.jar") {
module("maven-jps-plugin")
@@ -327,6 +329,15 @@
jar("gradle.jar") {
module("gradle")
}
+ jar("gradle-tooling-extension.jar") {
+ module("gradle-tooling-extension")
+ }
+ def gradleToolingVersions = ["1.9", "1.11", "1.12"]
+ gradleToolingVersions.each { ver ->
+ jar("gradle-tooling-extension-v" + ver + ".jar") {
+ module("gradle-tooling-extension-v" + ver)
+ }
+ }
fileset(dir: "$home/plugins/gradle/lib") { include(name: "*.jar") }
}
@@ -640,7 +651,6 @@
module("ddmlib")
module("dvlib")
module("draw9patch")
- module("lint-cli")
module("lint-api")
module("lint-checks")
module("ninepatch")
diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant
index d857304..5b9240f 100644
--- a/build/scripts/libLicenses.gant
+++ b/build/scripts/libLicenses.gant
@@ -165,8 +165,7 @@
libraryLicense(name: "Apache Commons Compress", libraryName: "commons-compress", version: "1.0", license: "Apache 2.0", url: "http://commons.apache.org/proper/commons-compress/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "Apache Commons Discovery", libraryName: "commons-discovery-0.4.jar", version: "0.4", license: "Apache 2.0", url: "http://jakarta.apache.org/commons/discovery/", licenseUrl: "http://commons.apache.org/license.html")
libraryLicense(name: "Apache Commons HTTPClient", libraryName: "http-client-3.1", version: "3.1 (with patch by JetBrains)", license: "Apache 2.0", url: "http://hc.apache.org/httpclient-3.x")
-libraryLicense(name: "HttpComponents HttpClient", libraryName: "http-client", version: "4.1.1", license: "Apache 2.0", url: "http://hc.apache.org/httpcomponents-client-ga/index.html")
-libraryLicense(name: "HttpComponents HttpClient", libraryName: "httpclient-4.2.5", version: "4.2.5", license: "Apache 2.0", url: "http://hc.apache.org/httpcomponents-client-ga/index.html")
+libraryLicense(name: "HttpComponents HttpClient", libraryName: "http-client", version: "4.3.1", license: "Apache 2.0", url: "http://hc.apache.org/httpcomponents-client-ga/index.html")
libraryLicense(name: "Apache Commons Net", libraryName: "commons-net", version: "3.1", license: "Apache 2.0", url: "http://commons.apache.org/net/")
libraryLicense(name: "Apache Commons Logging", libraryName: "commons-logging", version: "1.1.1", license: "Apache 2.0", url: "http://commons.apache.org/logging/")
libraryLicense(name: "Apache Commons IO", libraryName: "commons-io-1.4.jar", version: "1.4", license: "Apache 2.0", url: "http://commons.apache.org/io/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt")
@@ -174,6 +173,7 @@
libraryLicense(name: "Apache Sanselan", libraryName: "Sanselan", version: "0.98", license: "Apache 2.0", url: "http://commons.apache.org/sanselan/")
libraryLicense(name: "Automaton", libraryName: "automaton.jar", version: "1.11", license: "BSD", url: "http://www.brics.dk/automaton/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php")
libraryLicense(name: "DTDParser", version: "1.13", license: "LGPL", url: "http://sourceforge.net/projects/dtdparser/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1")
+libraryLicense(name: "Gant", version: "1.9.8", libraryName: "gant_groovy2.0-1.9.8.jar", license: "Apache 2.0", url: "http://gant.codehaus.org/", licenseUrl: "http://gant.codehaus.org/Licence")
libraryLicense(name: "Ganymed", version: "bundled with SVNKit", libraryName: "svnkit.jar", license: "BSD", url: "http://www.ganymed.ethz.ch/ssh2/", licenseUrl: "http://www.ganymed.ethz.ch/ssh2/LICENSE.txt")
libraryLicense(name: "sqljet", version: "bundled with SVNKit", libraryName: "sqljet.jar", license: "link (commercial license)", url: "http://sqljet.com", licenseUrl: "http://svnkit.com/license.html")
libraryLicense(name: "svnkit-javahl", version: "bundled with SVNKit", libraryName: "svnkit-javahl.jar", license: "link (commercial license)", url: "http://www.svnkit.com/", licenseUrl: "http://svnkit.com/license.html")
@@ -186,8 +186,8 @@
licenseUrl: "http://www.antlr.org/license.html")
libraryLicense(name: "Guava", version: "14.0.1", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://ant.apache.org/license.html")
libraryLicense(name: "Guava", libraryName: "guava-tools", version: "14.0.1", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://ant.apache.org/license.html")
-libraryLicense(name: "Groovy", version: "1.7.3", license: "Apache 2.0", url: "http://groovy.codehaus.org/")
-libraryLicense(name: "Gson", libraryName: "gson", license: "Apache 2.0", url: "http://code.google.com/p/google-gson/")
+libraryLicense(name: "Groovy", version: "2.2.1", license: "Apache 2.0", url: "http://groovy.codehaus.org/")
+libraryLicense(name: "Gson", version: "2.2.4", libraryName: "gson", license: "Apache 2.0", url: "http://code.google.com/p/google-gson/")
libraryLicense(name: "ini4j", libraryName: "ini4j-0.5.2-patched", version: "0.5.2 (with a patch by JetBrains)", license: "Apache 2.0", url: "http://ini4j.sourceforge.net/", attachedTo: "git4idea")
libraryLicense(name: "ISO RELAX", libraryName: "isorelax.jar", license: "MIT License", url: "http://sourceforge.net/projects/iso-relax/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html")
libraryLicense(name: "JavaCVS", attachedTo: "javacvs-src", version: "no version number available (with patches by JetBrains)", license: "Sun Public License", url: "http://javacvs.netbeans.org/library/", licenseUrl: "http://www.netbeans.org/about/legal/spl.html")
@@ -204,19 +204,19 @@
libraryLicense(name: "JNA", libraryName: "jna", version: "3.4.0", license: "LGPL 2.1", url: "https://jna.dev.java.net/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
libraryLicense(name: "JSch", libraryName: "JSch", version: "0.1.50", license: "BSD", url: "http://www.jcraft.com/jsch/", licenseUrl: "http://www.jcraft.com/jsch/LICENSE.txt")
libraryLicense(name: "JUnit", libraryName: "JUnit3", version: "3.8.1", license: "CPL 1.0", url: "http://junit.org/")
-libraryLicense(name: "JUnit", libraryName: "JUnit4", version: "4.8", license: "CPL 1.0", url: "http://junit.org/")
+libraryLicense(name: "JUnit", libraryName: "JUnit4", version: "4.11", license: "CPL 1.0", url: "http://junit.org/")
libraryLicense(name: "Log4j", libraryName: "Log4J", version: "1.2.17", license: "Apache 2.0", url: "http://logging.apache.org/log4j/1.2/index.html", licenseUrl: "http://logging.apache.org/license.html")
libraryLicense(name: "markdownj", libraryName: "markdownj", version: "0.4.2", license: "New BSD", url: "https://code.google.com/p/markdownj/", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
libraryLicense(name: "Maven", version: "2.2.1", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
libraryLicense(name: "plexus-util", version: "2.0.6", license: "Apache 2.0", url: "http://maven.apache.org/", libraryNames:['plexus-utils-2.0.6.jar'], licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
-libraryLicense(name: "aether-api", version: "1.11", libraryNames: ["aether-api-1.11.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
+libraryLicense(name: "aether-api", version: "1.13.1", libraryNames: ["aether-api-1.13.1.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
libraryLicense(name: "aether-api-0.9.0.M2.jar", version: "0.9.0.M2", libraryNames: ["aether-api-0.9.0.M2.jar"], license: "Eclipse Public License v1.0", url: "http://nexus.sonatype.org/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html")
libraryLicense(name: "maven-2.2.1-uber", version: "2.2.1", libraryNames: ["maven-2.2.1-uber.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
-libraryLicense(name: "maven-artifact", version: "3.0.3", libraryNames: ["maven-artifact-3.0.3.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
-libraryLicense(name: "maven-core", version: "3.0.3", libraryNames: ["maven-core-3.0.3.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
+libraryLicense(name: "maven-artifact", version: "3.0.5", libraryNames: ["maven-artifact-3.0.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
+libraryLicense(name: "maven-core", version: "3.0.5", libraryNames: ["maven-core-3.0.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
libraryLicense(name: "plexus-component-annotations", version: "1.5.5", libraryNames: ["plexus-component-annotations-1.5.5.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
-libraryLicense(name: "Maven3", libraryNames: ["Maven3", "maven-dependency-tree-1.2.jar", "archetype-catalog-2.2.jar", "archetype-common-2.2.jar"], version: "3.0.3", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
-libraryLicense(name: "Gradle", version: "1.8", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license")
+libraryLicense(name: "Maven3", libraryNames: ["Maven3", "maven-dependency-tree-1.2.jar", "archetype-catalog-2.2.jar", "archetype-common-2.2.jar"], version: "3.0.5", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
+libraryLicense(name: "Gradle", version: "1.9", license: "Apache 2.0", url: "http://gradle.org/", licenseUrl: "http://gradle.org/license")
libraryLicense(name: "GradleJnaPosix", version: "1.0.3", license: "LGPL 2.1", url: "http://www.jruby.org/", licenseUrl: "http://www.gnu.org/licenses/lgpl-2.1.txt")
libraryLicense(name: "Slf4j", version: "1.7.2", license: "MIT License", url: "http://slf4j.org/", licenseUrl: "http://slf4j.org/license.html")
libraryLicense(name: "GradleGuava", version: "11.0.2", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
@@ -254,8 +254,8 @@
libraryLicense(name: "XStream", version: "1.4.3", license: "BSD", url: "http://xstream.codehaus.org/", licenseUrl: "http://xstream.codehaus.org/license.html")
libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-redist.jar", version: "8.0.x", license: "link (commercial license)", url: "http://yourkit.com/", licenseUrl: "http://www.yourkit.com/purchase/license.html")
libraryLicense(name: "protobuf", version: "2.5.0", license: "New BSD", url: "http://code.google.com/p/protobuf/", licenseUrl: "http://code.google.com/p/protobuf/source/browse/trunk/COPYING.txt?r=367")
-libraryLicense(name: "Netty", libraryName: "Netty", version: "4.1.0.Alpha1", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
-libraryLicense(name: "Kryo", libraryName: "Kryo", version: "1.04", license: "New BSD License", url: "http://code.google.com/p/kryo/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php")
+libraryLicense(name: "Netty", libraryName: "Netty", version: "5.0.0.Alpha1", license: "Apache 2.0", url: "http://netty.io", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
+libraryLicense(name: "Kryo", libraryName: "Kryo", version: "2.22", license: "New BSD License", url: "https://github.com/EsotericSoftware/kryo", licenseUrl: "https://github.com/EsotericSoftware/kryo/blob/master/license.txt")
libraryLicense(name: "Snappy-Java", libraryName: "Snappy-Java", version: "1.0.5", license: "Apache 2.0", url: "http://code.google.com/p/snappy-java/", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "Cucumber-Java", libraryName: "cucumber-java", version: "1.0.14", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html")
libraryLicense(name: "Cucumber-JVM", libraryName: "cucumber-jvm", version: "1.0.14", license: "MIT License", url: "https://github.com/cucumber/cucumber-jvm/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html")
@@ -276,6 +276,10 @@
libraryLicense(name: "fxg-utils", libraryName: "fxg-utils", version: "4.9.1", license: "Apache 2.0", url: "http://flex.apache.org", licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0")
libraryLicense(name: "jayatana", libraryName: "jayatana", version: "1.2.4", license: "MIT License", url: "https://code.google.com/p/java-swing-ayatana/", licenseUrl: "http://opensource.org/licenses/mit-license.php")
libraryLicense(name: "ForkJoin", version: "", license: "Creative Commons Public Domain Dedication", url: "http://gee.cs.oswego.edu/dl/concurrency-interest/index.html", licenseUrl: "http://creativecommons.org/publicdomain/zero/1.0/")
+libraryLicense(name: "ANTLR 4 Runtime", libraryName: "antlr-runtime-4.1.jar", version: "4.1", license: "BSD", url: "http://www.antlr.org", licenseUrl: "http://www.antlr.org/license.html")
+libraryLicense(name: "minlog", libraryName: "minlog-1.2.jar", version: "1.2", license: "BSD", url: "https://github.com/EsotericSoftware/minlog", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
+libraryLicense(name: "ReflectASM", libraryName: "reflectasm-1.0.7.jar", version: "1.0.7", license: "BSD", url: "https://github.com/EsotericSoftware/reflectasm", licenseUrl: "http://opensource.org/licenses/BSD-3-Clause")
+libraryLicense(name: "Objenesis", libraryName: "objenesis-1.2.jar", version: "1.2", license: "Apache 2.0", url: "http://objenesis.org/", licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
jetbrainsLibrary("JPS")
jetbrainsLibrary("Maven Embedder")
jetbrainsLibrary("tcServiceMessages")
diff --git a/build/scripts/utils.gant b/build/scripts/utils.gant
index 07dfd61..a48f2ce 100644
--- a/build/scripts/utils.gant
+++ b/build/scripts/utils.gant
@@ -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.
@@ -750,12 +750,14 @@
projectBuilder.stage("winLauncher")
if (pathsSelector != null) {
- ant.replace(file: launcherProperties) {
- replacefilter(token: "__PRODUCT_PATHS_SELECTOR__", value: pathsSelector)
- }
+ def paths = getProperty("paths")
+ def launcherPropertiesTemp = "${paths.sandbox}/launcher.properties"
+ copyAndPatchFile(launcherProperties, launcherPropertiesTemp, ["PRODUCT_PATHS_SELECTOR": pathsSelector])
+ launcherProperties = launcherPropertiesTemp
}
ant.java(classname: "com.pme.launcher.LauncherGeneratorMain", fork: "true") {
+ sysproperty(key: "java.awt.headless", value: "true")
arg(value: inputPath)
arg(value: appInfo)
arg(value: "$ch/native/WinLauncher/WinLauncher/resource.h")
diff --git a/build/update.sh b/build/update.sh
index 7fdd502..b58f117 100755
--- a/build/update.sh
+++ b/build/update.sh
@@ -24,7 +24,7 @@
ANT_HOME="$DEV_IDEA_HOME/lib/ant"
ANT_CLASSPATH="$DEV_IDEA_HOME/build/lib/gant/lib/jps.jar"
java -Xms64m -Xmx512m -Dant.home="$ANT_HOME" -classpath "$ANT_HOME/lib/ant-launcher.jar" org.apache.tools.ant.launch.Launcher \
- -lib "$ANT_CLASSPATH" -f $DEV_IDEA_HOME/build/update.xml $TARGET
+ -lib "$ANT_CLASSPATH" -f "$DEV_IDEA_HOME/build/update.xml" $TARGET
if [ "$?" != "0" ]; then
echo "Update failed; work IDEA build not modified."
@@ -32,17 +32,17 @@
exit 2
fi
-rm -rf $WORK_IDEA_HOME/lib
-rm -rf $WORK_IDEA_HOME/plugins
+rm -rf "$WORK_IDEA_HOME/lib"
+rm -rf "$WORK_IDEA_HOME/plugins"
-cp -R $DEV_IDEA_HOME/out/deploy/* $WORK_IDEA_HOME
+cp -R "$DEV_IDEA_HOME/out/deploy/"* "$WORK_IDEA_HOME"
OS_TYPE=`uname -s`
if [ "$OS_TYPE" = "Linux" ]; then
cp -a $DEV_IDEA_HOME/bin/linux/*.so $WORK_IDEA_HOME/bin
cp -a $DEV_IDEA_HOME/bin/linux/fsnotifier* $WORK_IDEA_HOME/bin
elif [ "$OS_TYPE" = "Darwin" ]; then
- cp -a $DEV_IDEA_HOME/bin/mac/*.jnilib $WORK_IDEA_HOME/bin
- cp -a $DEV_IDEA_HOME/bin/mac/fsnotifier $WORK_IDEA_HOME/bin
- cp -a $DEV_IDEA_HOME/bin/mac/restarter $WORK_IDEA_HOME/bin
+ cp -a "$DEV_IDEA_HOME/bin/mac/"*.jnilib "$WORK_IDEA_HOME/bin"
+ cp -a "$DEV_IDEA_HOME/bin/mac/fsnotifier" "$WORK_IDEA_HOME/bin"
+ cp -a "$DEV_IDEA_HOME/bin/mac/restarter" "$WORK_IDEA_HOME/bin"
fi
diff --git a/build/update.xml b/build/update.xml
index b3a49cc..e06cfce 100644
--- a/build/update.xml
+++ b/build/update.xml
@@ -43,6 +43,7 @@
</java>
<java classname="com.intellij.util.io.zip.ReorderJarsMain" fork="true">
+ <jvmarg line="-Djava.awt.headless=true"/>
<arg value="${build}/order.txt"/>
<arg value="@{deploy}"/>
<arg value="@{deploy}"/>
diff --git a/colorSchemes/src/colorSchemes/Darcula.xml b/colorSchemes/src/colorSchemes/Darcula.xml
index 2e96e56..ec6fcc3 100644
--- a/colorSchemes/src/colorSchemes/Darcula.xml
+++ b/colorSchemes/src/colorSchemes/Darcula.xml
@@ -1363,6 +1363,42 @@
<option name="ERROR_STRIPE_COLOR" value="246e00" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="9876aa" />
diff --git a/colorSchemes/src/colorSchemes/WarmNeon.xml b/colorSchemes/src/colorSchemes/WarmNeon.xml
index d38a587..8dc1d80 100644
--- a/colorSchemes/src/colorSchemes/WarmNeon.xml
+++ b/colorSchemes/src/colorSchemes/WarmNeon.xml
@@ -1122,6 +1122,42 @@
<option name="BACKGROUND" value="ffa600" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="SQL_COLUMN">
<value>
<option name="FOREGROUND" value="cc9900" />
diff --git a/colorSchemes/src/colorSchemes/all_hallows_eve.xml b/colorSchemes/src/colorSchemes/all_hallows_eve.xml
index 9483cad..a6f2dc9 100644
--- a/colorSchemes/src/colorSchemes/all_hallows_eve.xml
+++ b/colorSchemes/src/colorSchemes/all_hallows_eve.xml
@@ -1912,6 +1912,42 @@
<option name="FOREGROUND" value="66CC33" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="SQL_BAD_CHARACTER">
<value>
<option name="BACKGROUND" value="6e3b3b" />
diff --git a/colorSchemes/src/colorSchemes/blackboard.xml b/colorSchemes/src/colorSchemes/blackboard.xml
index eea6be0..5a5cace 100644
--- a/colorSchemes/src/colorSchemes/blackboard.xml
+++ b/colorSchemes/src/colorSchemes/blackboard.xml
@@ -1306,6 +1306,42 @@
<option name="FOREGROUND" value="FF6400" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="fda5ff" />
diff --git a/colorSchemes/src/colorSchemes/cobalt.xml b/colorSchemes/src/colorSchemes/cobalt.xml
index b008df8..0ecbaf1 100644
--- a/colorSchemes/src/colorSchemes/cobalt.xml
+++ b/colorSchemes/src/colorSchemes/cobalt.xml
@@ -1812,6 +1812,42 @@
<option name="FOREGROUND" value="E1EFFF" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="fda5ff" />
diff --git a/colorSchemes/src/colorSchemes/monokai.xml b/colorSchemes/src/colorSchemes/monokai.xml
index f2d6913..26df452 100644
--- a/colorSchemes/src/colorSchemes/monokai.xml
+++ b/colorSchemes/src/colorSchemes/monokai.xml
@@ -1395,6 +1395,42 @@
<option name="FOREGROUND" value="A6E22E" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="fda5ff" />
diff --git a/colorSchemes/src/colorSchemes/rails_casts.xml b/colorSchemes/src/colorSchemes/rails_casts.xml
index 1770d47..482692c 100644
--- a/colorSchemes/src/colorSchemes/rails_casts.xml
+++ b/colorSchemes/src/colorSchemes/rails_casts.xml
@@ -1492,6 +1492,42 @@
<option name="FOREGROUND" value="E8BF6A" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="fda5ff" />
diff --git a/colorSchemes/src/colorSchemes/twilight.xml b/colorSchemes/src/colorSchemes/twilight.xml
index b7f514e..41e5f1a 100644
--- a/colorSchemes/src/colorSchemes/twilight.xml
+++ b/colorSchemes/src/colorSchemes/twilight.xml
@@ -1543,6 +1543,42 @@
<option name="FOREGROUND" value="9B703F" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="STATIC_FIELD_ATTRIBUTES">
<value>
<option name="FOREGROUND" value="fda5ff" />
diff --git a/colorSchemes/src/colorSchemes/vibrant_ink.xml b/colorSchemes/src/colorSchemes/vibrant_ink.xml
index 1b0c677..9b33e87 100644
--- a/colorSchemes/src/colorSchemes/vibrant_ink.xml
+++ b/colorSchemes/src/colorSchemes/vibrant_ink.xml
@@ -1817,6 +1817,42 @@
<option name="FOREGROUND" value="66ff00" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="3A3A3A"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="532B2E"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="425F44"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9b7c6" />
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
<option name="SQL_BAD_CHARACTER">
<value>
<option name="BACKGROUND" value="6e3b3b" />
diff --git a/community-resources/src/idea/IdeaApplicationInfo.xml b/community-resources/src/idea/IdeaApplicationInfo.xml
index 9dbef92..b4e2724 100644
--- a/community-resources/src/idea/IdeaApplicationInfo.xml
+++ b/community-resources/src/idea/IdeaApplicationInfo.xml
@@ -1,10 +1,10 @@
<component>
- <version codename="Community Edition" major="13" minor="0.3" eap="true"/>
+ <version codename="Community Edition" major="13" minor="1" eap="true"/>
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
- <install-over minbuild="129.1" maxbuild="132.9999" version="12.1"/>
- <logo url="/idea_community_logo.png" textcolor="444444" progressColor="ffaa16" progressY="222" progressTailIcon="/community_progress_tail.png"/>
- <about url="/idea_community_about.png" foreground="444444" linkColor="000099" logoX="300" logoY="265" logoW="75" logoH="30"/>
+ <install-over minbuild="129.1" maxbuild="135.9999" version="13.1"/>
+ <logo url="/idea_community_logo.png" textcolor="dddddd" progressColor="ffaa16" progressY="235" progressTailIcon="/community_progress_tail.png"/>
+ <about url="/idea_community_about.png" foreground="dddddd" linkColor="8BBAF9" logoX="300" logoY="265" logoW="75" logoH="30"/>
<icon size32="/icon_CE.png" size16="/icon_CEsmall.png" size32opaque="/icon_CEwhite.png" size12="/toolwindows/toolWindowProject.png" size128="/icon_CE_128.png" ico="idea_CE.ico"/>
<package code="__PACKAGE_CODE__"/>
<names product="IDEA" fullname="IntelliJ IDEA" script="idea"/>
diff --git a/community-resources/src/idea_community_about.png b/community-resources/src/idea_community_about.png
index 2b5a763..871356c 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 f159fb0..caf2a35 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 91a8153..057bb16 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 1f2cfb1..451e5f2 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/META-INF/ImagesPlugin.xml b/images/src/META-INF/ImagesPlugin.xml
index 88aa896..120b85c 100644
--- a/images/src/META-INF/ImagesPlugin.xml
+++ b/images/src/META-INF/ImagesPlugin.xml
@@ -25,9 +25,6 @@
</application-components>
<actions>
- <action id="images.color.picker" class="org.intellij.images.actions.ColorPickerForImageAction" text="Show Color Picker">
- <add-to-group anchor="after" group-id="ProjectViewPopupMenu" relative-to-action="EditSource"/>
- </action>
<action class="org.intellij.images.actions.EditExternallyAction"
id="Images.EditExternally"
icon="ImagesIcons.EditExternally"
@@ -88,7 +85,7 @@
<separator/>
<reference id="VersionControlsGroup"/>
<separator/>
- <reference id="images.color.picker" />
+ <reference id="ShowColorPicker" />
<reference id="Images.EditExternally"/>
<reference id="ExternalToolsGroup"/>
</group>
diff --git a/images/src/org/intellij/images/ImagesBundle.java b/images/src/org/intellij/images/ImagesBundle.java
index b2a7092..3472ab9 100644
--- a/images/src/org/intellij/images/ImagesBundle.java
+++ b/images/src/org/intellij/images/ImagesBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author max
*/
public class ImagesBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "org.intellij.images.ImagesBundle";
private ImagesBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/images/src/org/intellij/images/vfs/IfsUtil.java b/images/src/org/intellij/images/vfs/IfsUtil.java
index bb2f154..12b8e59 100644
--- a/images/src/org/intellij/images/vfs/IfsUtil.java
+++ b/images/src/org/intellij/images/vfs/IfsUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -66,7 +66,7 @@
private static boolean refresh(@NotNull VirtualFile file) throws IOException {
Long loadedTimeStamp = file.getUserData(TIMESTAMP_KEY);
SoftReference<BufferedImage> imageRef = file.getUserData(BUFFERED_IMAGE_REF_KEY);
- if (loadedTimeStamp == null || loadedTimeStamp.longValue() != file.getTimeStamp() || imageRef == null || imageRef.get() == null) {
+ if (loadedTimeStamp == null || loadedTimeStamp.longValue() != file.getTimeStamp() || SoftReference.dereference(imageRef) == null) {
try {
final byte[] content = file.contentsToByteArray();
@@ -113,7 +113,7 @@
public static BufferedImage getImage(@NotNull VirtualFile file) throws IOException {
refresh(file);
SoftReference<BufferedImage> imageRef = file.getUserData(BUFFERED_IMAGE_REF_KEY);
- return imageRef != null ? imageRef.get() : null;
+ return SoftReference.dereference(imageRef);
}
@Nullable
diff --git a/java/compiler/impl/src/com/intellij/compiler/CompileTaskBean.java b/java/compiler/impl/src/com/intellij/compiler/CompileTaskBean.java
new file mode 100644
index 0000000..1b4a265
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/CompileTaskBean.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.compiler;
+
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.extensions.AbstractExtensionPointBean;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.AtomicNotNullLazyValue;
+import com.intellij.util.xmlb.annotations.Attribute;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public class CompileTaskBean extends AbstractExtensionPointBean {
+ public static final ExtensionPointName<CompileTaskBean> EP_NAME = ExtensionPointName.create("com.intellij.compiler.task");
+ public enum CompileTaskExecutionPhase { BEFORE, AFTER }
+
+ private final Project myProject;
+
+ public CompileTaskBean(Project project) {
+ myProject = project;
+ }
+
+ @Attribute("execute")
+ public CompileTaskExecutionPhase myExecutionPhase = CompileTaskExecutionPhase.BEFORE;
+
+ @Attribute("implementation")
+ public String myImplementation;
+
+ private final AtomicNotNullLazyValue<CompileTask> myInstanceHolder = new AtomicNotNullLazyValue<CompileTask>() {
+ @NotNull
+ @Override
+ protected CompileTask compute() {
+ try {
+ return instantiate(myImplementation, myProject.getPicoContainer());
+ }
+ catch (ClassNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+
+ public CompileTask getTaskInstance() {
+ return myInstanceHolder.getValue();
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java b/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java
index f505855..46a090d 100644
--- a/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java
+++ b/java/compiler/impl/src/com/intellij/compiler/CompilerManagerImpl.java
@@ -240,12 +240,22 @@
@NotNull
public CompileTask[] getBeforeTasks() {
- return myBeforeTasks.toArray(new CompileTask[myBeforeTasks.size()]);
+ return getCompileTasks(myBeforeTasks, CompileTaskBean.CompileTaskExecutionPhase.BEFORE);
+ }
+
+ private CompileTask[] getCompileTasks(List<CompileTask> taskList, CompileTaskBean.CompileTaskExecutionPhase phase) {
+ List<CompileTask> beforeTasks = new ArrayList<CompileTask>(taskList);
+ for (CompileTaskBean extension : CompileTaskBean.EP_NAME.getExtensions(myProject)) {
+ if (extension.myExecutionPhase == phase) {
+ beforeTasks.add(extension.getTaskInstance());
+ }
+ }
+ return beforeTasks.toArray(new CompileTask[beforeTasks.size()]);
}
@NotNull
public CompileTask[] getAfterTasks() {
- return myAfterTasks.toArray(new CompileTask[myAfterTasks.size()]);
+ return getCompileTasks(myAfterTasks, CompileTaskBean.CompileTaskExecutionPhase.AFTER);
}
public void compile(@NotNull VirtualFile[] files, CompileStatusNotification callback) {
diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java b/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java
index e823e88..ca18aca 100644
--- a/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java
+++ b/java/compiler/impl/src/com/intellij/compiler/actions/BuildArtifactAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -201,7 +201,7 @@
info + "Do you want to continue and clear these directories?";
}
final int answer = Messages.showYesNoDialog(myProject, message, "Clean Artifacts", null);
- if (answer != 0) {
+ if (answer != Messages.YES) {
return;
}
}
diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildAction.java b/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildAction.java
index f141aa0..62645c9 100644
--- a/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildAction.java
+++ b/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildAction.java
@@ -93,7 +93,7 @@
int rc = Messages
.showOkCancelDialog(project, CompilerBundle.message("generate.ant.build.custom.compiler.conflict.message", msg.toString()),
CompilerBundle.message("generate.ant.build.custom.compiler.conflict.title"), Messages.getErrorIcon());
- if (rc != 0) {
+ if (rc != Messages.OK) {
return false;
}
}
diff --git a/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildDialog.java b/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildDialog.java
index eb17b84..8d7f05c 100644
--- a/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildDialog.java
+++ b/java/compiler/impl/src/com/intellij/compiler/actions/GenerateAntBuildDialog.java
@@ -32,8 +32,8 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.Chunk;
import com.intellij.util.ListWithSelection;
-import com.intellij.util.ui.ComboBoxTableCellEditor;
import com.intellij.util.ui.Table;
+import com.intellij.util.ui.table.ComboBoxTableCellEditor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
diff --git a/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java b/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java
index d89cd15..15e568a 100644
--- a/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java
+++ b/java/compiler/impl/src/com/intellij/compiler/ant/BuildPropertiesImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.compiler.ant;
+import com.intellij.compiler.CompilerWorkspaceConfiguration;
import com.intellij.compiler.ant.taskdefs.*;
import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration;
import com.intellij.openapi.compiler.CompilerBundle;
@@ -57,7 +58,8 @@
add(new Property(PROPERTY_COMPILER_GENERATE_NO_WARNINGS, javacSettings.GENERATE_NO_WARNINGS ? "on" : "off"));
add(new Property(PROPERTY_COMPILER_ADDITIONAL_ARGS, javacSettings.ADDITIONAL_OPTIONS_STRING));
//noinspection HardCodedStringLiteral
- add(new Property(PROPERTY_COMPILER_MAX_MEMORY, Integer.toString(javacSettings.MAXIMUM_HEAP_SIZE) + "m"));
+ final int heapSize = CompilerWorkspaceConfiguration.getInstance(project).getProcessHeapSize(javacSettings.MAXIMUM_HEAP_SIZE);
+ add(new Property(PROPERTY_COMPILER_MAX_MEMORY, Integer.toString(heapSize) + "m"));
add(new IgnoredFiles());
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexConfigure.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexConfigure.java
new file mode 100644
index 0000000..fd15019
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexConfigure.java
@@ -0,0 +1,38 @@
+/*
+ * 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.compiler.classFilesIndex.api.index;
+
+import com.intellij.openapi.project.Project;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class ClassFilesIndexConfigure<K, V> {
+
+ public abstract String getIndexCanonicalName();
+
+ public abstract int getIndexVersion();
+
+ public abstract Class<? extends ClassFileIndexerFactory> getIndexerBuilderClass();
+
+ public abstract ClassFilesIndexReaderBase<K, V> createIndexReader(final Project project);
+
+ public void prepareToIndexing(final Project project) {
+ ClassFilesIndexReaderBase.checkIndexAndRecreateIfNeed(project, getIndexVersion(), getIndexCanonicalName());
+ }
+
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java
new file mode 100644
index 0000000..52f77b1
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeature.java
@@ -0,0 +1,76 @@
+/*
+ * 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.compiler.classFilesIndex.api.index;
+
+import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexConfigure;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.registry.RegistryValue;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * @author Dmitry Batkovich
+ */
+@SuppressWarnings("unchecked")
+public enum ClassFilesIndexFeature {
+ METHOD_CHAINS_COMPLETION("completion.enable.relevant.method.chain.suggestions", MethodsUsageIndexConfigure.INSTANCE);
+
+ @NotNull
+ private final String myKey;
+ @NotNull
+ private final Collection<? extends ClassFilesIndexConfigure> myRequiredIndicesConfigures;
+
+ ClassFilesIndexFeature(@NotNull final String key,
+ @NotNull final Collection<? extends ClassFilesIndexConfigure> requiredIndicesConfigures) {
+ myKey = key;
+ myRequiredIndicesConfigures = requiredIndicesConfigures;
+ }
+
+ ClassFilesIndexFeature(@NotNull final String key, @NotNull final ClassFilesIndexConfigure requiredConfigure) {
+ this(key, Collections.<ClassFilesIndexConfigure>singleton(requiredConfigure));
+ }
+
+ public RegistryValue getRegistryValue() {
+ return Registry.get(myKey);
+ }
+
+ @NotNull
+ public String getKey() {
+ return myKey;
+ }
+
+ /**
+ * is feature enabled by registry key
+ */
+ public boolean isEnabled() {
+ return Registry.is(myKey);
+ }
+
+ public void enable() {
+ getRegistryValue().setValue(true);
+ }
+
+ public void disable() {
+ getRegistryValue().setValue(false);
+ }
+
+ @NotNull
+ public Collection<? extends ClassFilesIndexConfigure> getRequiredIndicesConfigures() {
+ return myRequiredIndicesConfigures;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java
new file mode 100644
index 0000000..eee027c
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexFeaturesHolder.java
@@ -0,0 +1,179 @@
+/*
+ * 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.compiler.classFilesIndex.api.index;
+
+import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexConfigure;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileTask;
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.registry.RegistryValue;
+import com.intellij.openapi.util.registry.RegistryValueListener;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ClassFilesIndexFeaturesHolder extends AbstractProjectComponent {
+ private final Map<ClassFilesIndexConfigure, ClassFilesIndexReaderBase> myEnabledIndexReaders =
+ new HashMap<ClassFilesIndexConfigure, ClassFilesIndexReaderBase>();
+ private final Map<ClassFilesIndexFeature, FeatureState> myEnabledFeatures = new HashMap<ClassFilesIndexFeature, FeatureState>();
+
+ public static ClassFilesIndexFeaturesHolder getInstance(final Project project) {
+ return project.getComponent(ClassFilesIndexFeaturesHolder.class);
+ }
+
+ protected ClassFilesIndexFeaturesHolder(final Project project) {
+ super(project);
+ }
+
+ @Override
+ public final void projectOpened() {
+ for (final ClassFilesIndexFeature feature : ClassFilesIndexFeature.values()) {
+ final RegistryValue registryValue = feature.getRegistryValue();
+ registryValue.addListener(new RegistryValueListener.Adapter() {
+ @Override
+ public void afterValueChanged(final RegistryValue rawValue) {
+ if (!rawValue.asBoolean() && myEnabledFeatures.containsKey(feature)) {
+ disposeFeature(feature);
+ }
+ }
+ }, myProject);
+ }
+ final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
+ compilerManager.addBeforeTask(new CompileTask() {
+ @Override
+ public boolean execute(final CompileContext context) {
+ close();
+ return true;
+ }
+ });
+ }
+
+ public synchronized boolean enableFeatureIfNeed(final ClassFilesIndexFeature feature) {
+ if (!feature.isEnabled()) {
+ return false;
+ }
+ FeatureState state = myEnabledFeatures.get(feature);
+ if (state == null) {
+ state = initializeFeature(feature);
+ }
+ return state == FeatureState.AVAILABLE;
+ }
+
+ public synchronized void visitEnabledConfigures(final Processor<ClassFilesIndexConfigure> availableConfiguresVisitor,
+ final Processor<ClassFilesIndexConfigure> notAvailableConfiguresVisitor) {
+ for (final ClassFilesIndexConfigure configure : myEnabledIndexReaders.keySet()) {
+ availableConfiguresVisitor.process(configure);
+ }
+ for (final ClassFilesIndexFeature feature : ClassFilesIndexFeature.values()) {
+ if (feature.isEnabled() && !myEnabledFeatures.containsKey(feature)) {
+ for (final ClassFilesIndexConfigure configure : feature.getRequiredIndicesConfigures()) {
+ if (!myEnabledIndexReaders.containsKey(configure)) {
+ notAvailableConfiguresVisitor.process(configure);
+ }
+ }
+ }
+ }
+ }
+
+ private synchronized void disposeFeature(final ClassFilesIndexFeature featureToRemove) {
+ for (final ClassFilesIndexConfigure requiredConfigure : featureToRemove.getRequiredIndicesConfigures()) {
+ boolean needClose = true;
+ for (final ClassFilesIndexFeature enabledFeature : myEnabledFeatures.keySet()) {
+ if (!enabledFeature.equals(featureToRemove) && enabledFeature.getRequiredIndicesConfigures().contains(requiredConfigure)) {
+ needClose = false;
+ break;
+ }
+ }
+ if (needClose) {
+ final ClassFilesIndexReaderBase readerToClose = myEnabledIndexReaders.remove(requiredConfigure);
+ readerToClose.close();
+ }
+ }
+ myEnabledFeatures.remove(featureToRemove);
+ }
+
+ private synchronized FeatureState initializeFeature(final ClassFilesIndexFeature feature) {
+ if (myEnabledFeatures.containsKey(feature)) {
+ throw new IllegalStateException(String.format("feature %s already contains", feature.getKey()));
+ }
+ final Map<ClassFilesIndexConfigure, ClassFilesIndexReaderBase> newIndices =
+ new HashMap<ClassFilesIndexConfigure, ClassFilesIndexReaderBase>();
+ FeatureState newFeatureState = FeatureState.AVAILABLE;
+ for (final ClassFilesIndexConfigure requiredConfigure : feature.getRequiredIndicesConfigures()) {
+ boolean isIndexAlreadyLoaded = false;
+ for (final ClassFilesIndexFeature enabledFeature : myEnabledFeatures.keySet()) {
+ if (enabledFeature.getRequiredIndicesConfigures().contains(requiredConfigure)) {
+ isIndexAlreadyLoaded = true;
+ break;
+ }
+ }
+ if (!isIndexAlreadyLoaded) {
+ final ClassFilesIndexReaderBase reader = requiredConfigure.createIndexReader(myProject);
+ newIndices.put(requiredConfigure, reader);
+ if (reader.isEmpty()) {
+ newFeatureState = FeatureState.NOT_AVAILABLE;
+ }
+ }
+ }
+ myEnabledIndexReaders.putAll(newIndices);
+ myEnabledFeatures.put(feature, newFeatureState);
+ return newFeatureState;
+ }
+
+ private synchronized void close() {
+ for (final ClassFilesIndexReaderBase reader : myEnabledIndexReaders.values()) {
+ reader.close();
+ }
+ myEnabledIndexReaders.clear();
+ myEnabledFeatures.clear();
+ }
+
+ @Override
+ public void projectClosed() {
+ close();
+ }
+
+ /**
+ * try to find index with corresponding class only in currently enabled indexes
+ */
+ @Nullable
+ @SuppressWarnings("unchecked")
+ public <T extends ClassFilesIndexReaderBase> T getAvailableIndexReader(final Class<T> tClass) {
+ final String indexReaderClassName = tClass.getCanonicalName();
+ for (final ClassFilesIndexReaderBase reader : myEnabledIndexReaders.values()) {
+ if (reader.getClass().getCanonicalName().equals(indexReaderClassName)) {
+ return (T)reader;
+ }
+ }
+ throw new RuntimeException(String.format("index reader for class %s not found", indexReaderClassName));
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ private enum FeatureState {
+ AVAILABLE,
+ NOT_AVAILABLE
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java
new file mode 100644
index 0000000..8f6a7eb
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexReaderBase.java
@@ -0,0 +1,149 @@
+/*
+ * 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.compiler.classFilesIndex.api.index;
+
+import com.intellij.compiler.server.BuildManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndexStorage;
+import org.jetbrains.jps.classFilesIndex.indexer.api.IndexState;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class ClassFilesIndexReaderBase<K, V> {
+
+ private final static Logger LOG = Logger.getInstance(ClassFilesIndexReaderBase.class);
+ @Nullable
+ protected final ClassFilesIndexStorage<K, V> myIndex;
+
+
+ public static boolean checkIndexAndRecreateIfNeed(final Project project, final int currentVersion, final String canonicalIndexName) {
+ final File projectBuildSystemDirectory = BuildManager.getInstance().getProjectSystemDirectory(project);
+ assert projectBuildSystemDirectory != null;
+ final File versionFile = new File(ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory), "version");
+ final File indexDir = ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory);
+ if (versionFile.exists() &&
+ !versionDiffers(projectBuildSystemDirectory, canonicalIndexName, currentVersion) &&
+ IndexState.load(indexDir) == IndexState.EXIST) {
+ return true;
+ }
+ else {
+ recreateIndex(canonicalIndexName, currentVersion, projectBuildSystemDirectory, indexDir);
+ return false;
+ }
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ protected ClassFilesIndexReaderBase(final KeyDescriptor<K> keyDescriptor,
+ final DataExternalizer<V> valueExternalizer,
+ final String canonicalIndexName,
+ final int indexVersion,
+ final Project project) {
+ if (checkIndexAndRecreateIfNeed(project, indexVersion, canonicalIndexName)) {
+ ClassFilesIndexStorage<K, V> index = null;
+ IOException exception = null;
+ final File projectBuildSystemDirectory = BuildManager.getInstance().getProjectSystemDirectory(project);
+ final File indexDir = ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory);
+ try {
+ index = new ClassFilesIndexStorage<K, V>(indexDir, keyDescriptor, valueExternalizer);
+ }
+ catch (final IOException e) {
+ exception = e;
+ PersistentHashMap.deleteFilesStartingWith(ClassFilesIndexStorage.getIndexFile(indexDir));
+ }
+ if (exception != null) {
+ recreateIndex(canonicalIndexName, indexVersion, projectBuildSystemDirectory, indexDir);
+ myIndex = null;
+ }
+ else {
+ myIndex = index;
+ }
+ }
+ else {
+ myIndex = null;
+ }
+ }
+
+ private static void recreateIndex(final String canonicalIndexName,
+ final int indexVersion,
+ final File projectBuildSystemDirectory,
+ final File indexDir) {
+ if (indexDir.exists()) {
+ FileUtil.delete(indexDir);
+ }
+ try {
+ FileUtil.writeToFile(new File(ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory), "version"), String.valueOf(
+ indexVersion));
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ IndexState.NOT_EXIST.save(indexDir);
+ }
+
+ public boolean isEmpty() {
+ return myIndex == null;
+ }
+
+ public final void close() {
+ if (myIndex != null) {
+ try {
+ myIndex.close();
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ public final void delete() {
+ try {
+ if (myIndex != null) {
+ myIndex.delete();
+ }
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static File getVersionFile(final File projectBuildSystemDirectory, final String canonicalIndexName) {
+ return new File(ClassFilesIndexStorage.getIndexDir(canonicalIndexName, projectBuildSystemDirectory), "version");
+ }
+
+ private static boolean versionDiffers(final File projectBuildSystemDirectory, final String canonicalIndexName, final int currentVersion) {
+ final File versionFile = getVersionFile(projectBuildSystemDirectory, canonicalIndexName);
+ if (!versionFile.exists()) {
+ return true;
+ }
+ try {
+ return Integer.parseInt(FileUtil.loadFile(versionFile)) != currentVersion;
+ }
+ catch (final IOException e) {
+ LOG.error("error while reading version file " + versionFile.getAbsolutePath());
+ return true;
+ }
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java
new file mode 100644
index 0000000..eba69fd
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/api/index/ClassFilesIndexerBuilderParametersProvider.java
@@ -0,0 +1,69 @@
+/*
+ * 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.compiler.classFilesIndex.api.index;
+
+import com.intellij.compiler.server.BuildProcessParametersProvider;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndicesBuilder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ClassFilesIndexerBuilderParametersProvider extends BuildProcessParametersProvider {
+ private final ClassFilesIndexFeaturesHolder myIndicesHolder;
+
+ protected ClassFilesIndexerBuilderParametersProvider(final ClassFilesIndexFeaturesHolder indicesHolder) {
+ myIndicesHolder = indicesHolder;
+ }
+
+ @NotNull
+ @Override
+ public List<String> getVMArguments() {
+ final List<String> args = new ArrayList<String>();
+ myIndicesHolder.visitEnabledConfigures(
+ new Processor<ClassFilesIndexConfigure>() {
+ @Override
+ public boolean process(final ClassFilesIndexConfigure availableConfigure) {
+ final String className = availableConfigure.getIndexerBuilderClass().getCanonicalName();
+ args.add(className);
+ return true;
+ }
+ }, new Processor<ClassFilesIndexConfigure>() {
+ @Override
+ public boolean process(final ClassFilesIndexConfigure notAvailableConfigure) {
+ final String className = notAvailableConfigure.getIndexerBuilderClass().getCanonicalName();
+ args.add(className);
+ notAvailableConfigure.prepareToIndexing(myIndicesHolder.getProject());
+ return true;
+ }
+ }
+ );
+ if (args.size() != 0) {
+ final String serializedArgs = StringUtil.join(args, ";");
+ return Collections.singletonList("-D" + ClassFilesIndicesBuilder.PROPERTY_NAME + "=" + serializedArgs);
+ }
+ else {
+ return Collections.emptyList();
+ }
+ }
+
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java
new file mode 100644
index 0000000..da119b1
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/CachedRelevantStaticMethodSearcher.java
@@ -0,0 +1,136 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ContextRelevantStaticMethod;
+import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexReader;
+import com.intellij.compiler.classFilesIndex.impl.UsageIndexValue;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.SmartList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class CachedRelevantStaticMethodSearcher {
+ private final HashMap<MethodIncompleteSignature, PsiMethod> myCachedResolveResults = new HashMap<MethodIncompleteSignature, PsiMethod>();
+ private final MethodsUsageIndexReader myIndexReader;
+ private final JavaPsiFacade myJavaPsiFacade;
+ private final GlobalSearchScope myAllScope;
+ private final GlobalSearchScope myResolveScope;
+
+ public CachedRelevantStaticMethodSearcher(final Project project, final GlobalSearchScope resolveScope) {
+ myIndexReader = MethodsUsageIndexReader.getInstance(project);
+ myJavaPsiFacade = JavaPsiFacade.getInstance(project);
+ myAllScope = GlobalSearchScope.allScope(project);
+ myResolveScope = resolveScope;
+ }
+
+ @NotNull
+ public List<ContextRelevantStaticMethod> getRelevantStaticMethods(final String resultQualifiedClassName,
+ final int minOccurrence,
+ final ChainCompletionContext completionContext) {
+ if (resultQualifiedClassName == null ||
+ ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(resultQualifiedClassName) ||
+ completionContext.getTarget().equals(resultQualifiedClassName)) {
+ return Collections.emptyList();
+ }
+ final TreeSet<UsageIndexValue> indexValues = myIndexReader.getMethods(resultQualifiedClassName);
+ if (!indexValues.isEmpty()) {
+ int occurrences = 0;
+ final List<ContextRelevantStaticMethod> relevantMethods = new ArrayList<ContextRelevantStaticMethod>();
+ for (final UsageIndexValue indexValue : extractStaticMethods(indexValues)) {
+ final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+ final PsiMethod method;
+ if (myCachedResolveResults.containsKey(methodInvocation)) {
+ method = myCachedResolveResults.get(methodInvocation);
+ }
+ else {
+ final PsiMethod[] methods = completionContext.resolveNotDeprecated(methodInvocation);
+ method = MethodChainsSearchUtil
+ .getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTarget().getClassQName()));
+ myCachedResolveResults.put(methodInvocation, method);
+ if (method == null) {
+ return Collections.emptyList();
+ }
+ }
+ if (method == null) {
+ return Collections.emptyList();
+ }
+ if (method.hasModifierProperty(PsiModifier.PUBLIC)) {
+ if (isMethodValid(method, completionContext, resultQualifiedClassName)) {
+ occurrences += indexValue.getOccurrences();
+ if (myResolveScope.contains(method.getContainingFile().getVirtualFile())) {
+ relevantMethods.add(new ContextRelevantStaticMethod(method, null));
+ }
+ if (occurrences >= minOccurrence) {
+ return relevantMethods;
+ }
+ }
+ }
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ private static List<UsageIndexValue> extractStaticMethods(final TreeSet<UsageIndexValue> indexValues) {
+ final List<UsageIndexValue> relevantStaticMethods = new SmartList<UsageIndexValue>();
+ for (final UsageIndexValue indexValue : indexValues) {
+ if (indexValue.getMethodIncompleteSignature().isStatic()) {
+ relevantStaticMethods.add(indexValue);
+ }
+ }
+ return relevantStaticMethods;
+ }
+
+ private static boolean isMethodValid(final @Nullable PsiMethod method,
+ final ChainCompletionContext completionContext,
+ final String targetTypeShortName) {
+ if (method == null) return false;
+ for (final PsiParameter parameter : method.getParameterList().getParameters()) {
+ final PsiType type = parameter.getType();
+ final String shortClassName = typeAsString(type);
+ if (targetTypeShortName.equals(shortClassName)) return false;
+ if (!ChainCompletionStringUtil.isShortNamePrimitiveOrArrayOfPrimitives(shortClassName) &&
+ !completionContext.contains(type.getCanonicalText())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ @Nullable
+ public static String typeAsString(final PsiType type) {
+ if (type instanceof PsiClassType)
+ return ((PsiClassType) type).getClassName();
+ else if (type instanceof PsiPrimitiveType)
+ return type.getCanonicalText();
+ else if (type instanceof PsiArrayType) {
+ final String componentTypeAsString = typeAsString(((PsiArrayType) type).getComponentType());
+ if (componentTypeAsString == null) return null;
+ return String.format("%s[]", componentTypeAsString);
+ }
+ return null;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainCompletionStringUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainCompletionStringUtil.java
new file mode 100644
index 0000000..8a2c1d1
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainCompletionStringUtil.java
@@ -0,0 +1,109 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.openapi.util.text.StringUtilRt;
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainCompletionStringUtil {
+ private ChainCompletionStringUtil() {}
+
+ public static boolean isPrimitiveOrArray(final @Nullable String typeQName) {
+ return typeQName != null && (typeQName.endsWith("[]") || PRIMITIVES_NAMES.contains(typeQName));
+ }
+
+ /**
+ * CAUTION: isPrimitiveOrArrayOfPrimitives("java.lang.String") == true,
+ * isPrimitiveOrArrayOfPrimitives("java.lang.Object") == true
+ * isPrimitiveOrArrayOfPrimitives("java.lang.Class") == true
+ */
+ public static boolean isPrimitiveOrArrayOfPrimitives(final String typeQName) {
+ if (typeQName == null) {
+ return false;
+ }
+ return PRIMITIVES_NAMES.contains(deleteArraySigns(typeQName));
+ }
+
+ public static boolean isShortNamePrimitiveOrArrayOfPrimitives(final @Nullable String shortName) {
+ if (shortName == null) {
+ return false;
+ }
+ return PRIMITIVES_SHORT_NAMES.contains(deleteArraySigns(shortName));
+ }
+
+ private static String deleteArraySigns(final @NotNull String typeName) {
+ String nameWithoutArraySign = typeName;
+ while (nameWithoutArraySign.endsWith("[]")) {
+ nameWithoutArraySign = nameWithoutArraySign.substring(0, nameWithoutArraySign.length() - 2);
+ }
+ return nameWithoutArraySign;
+ }
+
+ private static final Set<String> PRIMITIVES_NAMES = new HashSet<String>();
+
+ static {
+ fillPrimitivesNames(PsiType.BOOLEAN);
+ fillPrimitivesNames(PsiType.INT);
+ fillPrimitivesNames(PsiType.LONG);
+ fillPrimitivesNames(PsiType.DOUBLE);
+ fillPrimitivesNames(PsiType.FLOAT);
+ fillPrimitivesNames(PsiType.SHORT);
+ fillPrimitivesNames(PsiType.CHAR);
+ fillPrimitivesNames(PsiType.BYTE);
+ fillPrimitivesNames(PsiType.VOID);
+ PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_STRING);
+ PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_OBJECT);
+ PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_CLASS);
+ }
+
+ private static void fillPrimitivesNames(final PsiPrimitiveType type) {
+ PRIMITIVES_NAMES.add(type.getBoxedTypeName());
+ PRIMITIVES_NAMES.add(type.getCanonicalText());
+ }
+
+ private static final Set<String> PRIMITIVES_SHORT_NAMES = new HashSet<String>();
+
+ static {
+ fillPrimitivesShortNames(PsiType.BOOLEAN);
+ fillPrimitivesShortNames(PsiType.INT);
+ fillPrimitivesShortNames(PsiType.LONG);
+ fillPrimitivesShortNames(PsiType.DOUBLE);
+ fillPrimitivesShortNames(PsiType.FLOAT);
+ fillPrimitivesShortNames(PsiType.SHORT);
+ fillPrimitivesShortNames(PsiType.CHAR);
+ fillPrimitivesShortNames(PsiType.BYTE);
+ fillPrimitivesShortNames(PsiType.VOID);
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_STRING));
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_OBJECT));
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_CLASS));
+ }
+
+ private static void fillPrimitivesShortNames(final PsiPrimitiveType type) {
+ PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(type.getBoxedTypeName()));
+ PRIMITIVES_SHORT_NAMES.add(type.getCanonicalText());
+ }
+
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainRelevance.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainRelevance.java
new file mode 100644
index 0000000..c3e9e0a
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainRelevance.java
@@ -0,0 +1,115 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ChainRelevance implements Comparable<ChainRelevance> {
+ public static final ChainRelevance LOWEST = new ChainRelevance(Integer.MAX_VALUE, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false, 0);
+
+ private final int myChainSize;
+ private final int myLastMethodOccurrences;
+ private final int myUnreachableParametersCount;
+ private final int myNotMatchedStringVars;
+ private final boolean myHasCallingVariableInContext;
+ private final boolean myFirstMethodStatic;
+ private final int myParametersInContext;
+
+ public ChainRelevance(final int chainSize,
+ final int lastMethodOccurrences,
+ final int unreachableParametersCount,
+ final int notMatchedStringVars,
+ final boolean hasCallingVariableInContext,
+ final boolean firstMethodStatic,
+ final int parametersInContext) {
+ myChainSize = chainSize;
+ myLastMethodOccurrences = lastMethodOccurrences;
+ myUnreachableParametersCount = unreachableParametersCount;
+ myNotMatchedStringVars = notMatchedStringVars;
+ myHasCallingVariableInContext = hasCallingVariableInContext;
+ myFirstMethodStatic = firstMethodStatic;
+ myParametersInContext = parametersInContext;
+ }
+
+ @TestOnly
+ public boolean hasCallingVariableInContext() {
+ return myHasCallingVariableInContext;
+ }
+
+ @TestOnly
+ public int getChainSize() {
+ return myChainSize;
+ }
+
+ @TestOnly
+ public int getLastMethodOccurrences() {
+ return myLastMethodOccurrences;
+ }
+
+ @TestOnly
+ public int getUnreachableParametersCount() {
+ return myUnreachableParametersCount;
+ }
+
+ @TestOnly
+ public int getNotMatchedStringVars() {
+ return myNotMatchedStringVars;
+ }
+
+ @TestOnly
+ public boolean isFirstMethodStatic() {
+ return myFirstMethodStatic;
+ }
+
+ @Override
+ public int compareTo(@NotNull final ChainRelevance that) {
+ if (myHasCallingVariableInContext && !that.myHasCallingVariableInContext) {
+ return 1;
+ }
+ if (that.myHasCallingVariableInContext && !myHasCallingVariableInContext) {
+ return -1;
+ }
+ if (myFirstMethodStatic && !that.myFirstMethodStatic) {
+ return -1;
+ }
+ if (that.myFirstMethodStatic && !myFirstMethodStatic) {
+ return 1;
+ }
+ if (myParametersInContext > that.myParametersInContext) {
+ return 1;
+ }
+ if (myParametersInContext <= that.myParametersInContext) {
+ return -1;
+ }
+ int sub = myLastMethodOccurrences - that.myLastMethodOccurrences;
+ if (sub != 0) return sub;
+ sub = myUnreachableParametersCount - that.myUnreachableParametersCount;
+ if (sub != 0) return -sub;
+ return 0;
+ }
+
+ @Override
+ public String toString() {
+ return (myFirstMethodStatic ? "1" : "0") +
+ (myHasCallingVariableInContext ? "1" : "0") + "_" +
+ myLastMethodOccurrences + "_" +
+ myUnreachableParametersCount;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java
new file mode 100644
index 0000000..c040e96
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ChainsSearcher.java
@@ -0,0 +1,321 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.TargetType;
+import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexReader;
+import com.intellij.compiler.classFilesIndex.impl.UsageIndexValue;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.*;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+import org.jetbrains.jps.incremental.storage.BuildDataManager;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainsSearcher {
+ private ChainsSearcher() {
+ }
+
+ private static final Logger LOG = Logger.getInstance(ChainsSearcher.class);
+ private static final double NEXT_METHOD_IN_CHAIN_RATIO = 1.5;
+
+ public static List<MethodsChain> search(final int pathMaximalLength,
+ final TargetType targetType,
+ final Set<String> contextQNames,
+ final int maxResultSize,
+ final ChainCompletionContext context,
+ final MethodsUsageIndexReader methodsUsageIndexReader) {
+ final SearchInitializer initializer =
+ createInitializer(targetType,
+ context.getExcludedQNames(),
+ methodsUsageIndexReader,
+ context);
+ if (initializer == null) {
+ return Collections.emptyList();
+ }
+ return search(methodsUsageIndexReader,
+ initializer,
+ contextQNames,
+ pathMaximalLength,
+ maxResultSize,
+ targetType.getClassQName(),
+ context);
+ }
+
+ @Nullable
+ private static SearchInitializer createInitializer(final TargetType target,
+ final Set<String> excludedParamsTypesQNames,
+ final MethodsUsageIndexReader methodsUsageIndexReader,
+ final ChainCompletionContext context) {
+ final TreeSet<UsageIndexValue> methods = methodsUsageIndexReader.getMethods(target.getClassQName());
+ return new SearchInitializer(methods, target.getClassQName(), excludedParamsTypesQNames, context);
+ }
+
+ @NotNull
+ private static List<MethodsChain> search(final MethodsUsageIndexReader indexReader,
+ final SearchInitializer initializer,
+ final Set<String> toSet,
+ final int pathMaximalLength,
+ final int maxResultSize,
+ final String targetQName,
+ final ChainCompletionContext context) {
+ final Set<String> allExcludedNames = MethodChainsSearchUtil.unionToHashSet(context.getExcludedQNames(), targetQName);
+ final SearchInitializer.InitResult initResult = initializer.init(Collections.<String>emptySet());
+
+ final Map<MethodIncompleteSignature, MethodsChain> knownDistance = initResult.getChains();
+
+ final List<WeightAware<MethodIncompleteSignature>> allInitialVertexes = initResult.getVertexes();
+
+ final LinkedList<WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>> q =
+ new LinkedList<WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>>(ContainerUtil.map(allInitialVertexes,
+ new Function<WeightAware<MethodIncompleteSignature>, WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>>() {
+ @Override
+ public WeightAware<Pair<MethodIncompleteSignature, MethodsChain>> fun(
+ final WeightAware<MethodIncompleteSignature> methodIncompleteSignatureWeightAware) {
+ final MethodIncompleteSignature underlying = methodIncompleteSignatureWeightAware.getUnderlying();
+ return new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
+ new Pair<MethodIncompleteSignature, MethodsChain>(
+ underlying,
+ new MethodsChain(context.resolveNotDeprecated(underlying),
+ methodIncompleteSignatureWeightAware.getWeight(),
+ underlying.getOwner()
+ )
+ ),
+ methodIncompleteSignatureWeightAware.getWeight()
+ );
+ }
+ }
+ ));
+
+ int maxWeight = 0;
+ for (final MethodsChain methodsChain : knownDistance.values()) {
+ if (methodsChain.getChainWeight() > maxWeight) {
+ maxWeight = methodsChain.getChainWeight();
+ }
+ }
+
+ final ResultHolder result = new ResultHolder(context.getPsiManager());
+ while (!q.isEmpty()) {
+ ProgressManager.checkCanceled();
+ final WeightAware<Pair<MethodIncompleteSignature, MethodsChain>> currentVertex = q.poll();
+ final int currentVertexDistance = currentVertex.getWeight();
+ final Pair<MethodIncompleteSignature, MethodsChain> currentVertexUnderlying = currentVertex.getUnderlying();
+ final MethodsChain currentVertexMethodsChain = knownDistance.get(currentVertexUnderlying.getFirst());
+ if (currentVertexDistance != currentVertexMethodsChain.getChainWeight()) {
+ continue;
+ }
+ if (currentVertex.getUnderlying().getFirst().isStatic() || toSet.contains(currentVertex.getUnderlying().getFirst().getOwner())) {
+ result.add(currentVertex.getUnderlying().getSecond());
+ continue;
+ }
+ final String currentReturnType = currentVertexUnderlying.getFirst().getOwner();
+ final SortedSet<UsageIndexValue> nextMethods = indexReader.getMethods(currentReturnType);
+ final MaxSizeTreeSet<WeightAware<MethodIncompleteSignature>> currentSignatures =
+ new MaxSizeTreeSet<WeightAware<MethodIncompleteSignature>>(maxResultSize);
+ for (final UsageIndexValue indexValue : nextMethods) {
+ final MethodIncompleteSignature vertex = indexValue.getMethodIncompleteSignature();
+ final int occurrences = indexValue.getOccurrences();
+ if (vertex.isStatic() || !vertex.getOwner().equals(targetQName)) {
+ final int vertexDistance = Math.min(currentVertexDistance, occurrences);
+ final MethodsChain knownVertexMethodsChain = knownDistance.get(vertex);
+ if ((knownVertexMethodsChain == null || knownVertexMethodsChain.getChainWeight() < vertexDistance)) {
+ if (currentSignatures.isEmpty() || currentSignatures.last().getWeight() < vertexDistance) {
+ if (currentVertexMethodsChain.size() < pathMaximalLength - 1) {
+ final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+ final PsiMethod[] psiMethods = context.resolveNotDeprecated(methodInvocation);
+ if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, allExcludedNames)) {
+ final MethodsChain newBestMethodsChain =
+ currentVertexMethodsChain.addEdge(psiMethods, indexValue.getMethodIncompleteSignature().getOwner(), vertexDistance);
+ currentSignatures
+ .add(new WeightAware<MethodIncompleteSignature>(indexValue.getMethodIncompleteSignature(), vertexDistance));
+ knownDistance.put(vertex, newBestMethodsChain);
+ }
+ }
+ }
+ }
+ else {
+ break;
+ }
+ }
+ }
+ boolean updated = false;
+ if (!currentSignatures.isEmpty()) {
+ boolean isBreak = false;
+ for (final WeightAware<MethodIncompleteSignature> sign : currentSignatures) {
+ final PsiMethod[] resolved = context.resolveNotDeprecated(sign.getUnderlying());
+ if (!isBreak) {
+ if (sign.getWeight() * NEXT_METHOD_IN_CHAIN_RATIO > currentVertex.getWeight()) {
+ final boolean stopChain = sign.getUnderlying().isStatic() || toSet.contains(sign.getUnderlying().getOwner());
+ if (stopChain) {
+ updated = true;
+ result.add(currentVertex.getUnderlying().getSecond().addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight()));
+ continue;
+ }
+ else {
+ updated = true;
+ final MethodsChain methodsChain =
+ currentVertexUnderlying.second.addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight());
+ q.add(new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
+ new Pair<MethodIncompleteSignature, MethodsChain>(sign.getUnderlying(), methodsChain), sign.getWeight()));
+ continue;
+ }
+ }
+ }
+ final MethodsChain methodsChain =
+ currentVertexUnderlying.second.addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight());
+ final ParametersMatcher.MatchResult parametersMatchResult = ParametersMatcher.matchParameters(methodsChain, context);
+ if (parametersMatchResult.noUnmatchedAndHasMatched() && parametersMatchResult.hasTarget()) {
+ updated = true;
+ q.addFirst(new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
+ new Pair<MethodIncompleteSignature, MethodsChain>(sign.getUnderlying(), methodsChain), sign.getWeight()));
+ }
+ isBreak = true;
+ }
+ }
+ if (!updated &&
+ (currentVertex.getUnderlying().getFirst().isStatic() ||
+ !targetQName.equals(currentVertex.getUnderlying().getFirst().getOwner()))) {
+ result.add(currentVertex.getUnderlying().getSecond());
+ }
+ if (result.size() > maxResultSize) {
+ return result.getResult();
+ }
+ }
+ return result.getResult();
+ }
+
+ private static MethodsChain createChainFromFirstElement(final MethodsChain chain, final PsiClass newQualifierClass) {
+ final String qualifiedClassName = newQualifierClass.getQualifiedName();
+ if (qualifiedClassName == null) {
+ throw new IllegalArgumentException();
+ }
+ return new MethodsChain(chain.getFirst(), chain.getChainWeight(), qualifiedClassName);
+ }
+
+ private static class ResultHolder {
+ private final List<MethodsChain> myResult;
+ private final PsiManager myContext;
+
+ private ResultHolder(final PsiManager psiManager) {
+ myContext = psiManager;
+ myResult = new ArrayList<MethodsChain>();
+ }
+
+ public void add(final MethodsChain newChain) {
+ if (myResult.isEmpty()) {
+ myResult.add(newChain);
+ return;
+ }
+ boolean doAdd = true;
+ final Stack<Integer> indexesToRemove = new Stack<Integer>();
+ for (int i = 0; i < myResult.size(); i++) {
+ final MethodsChain chain = myResult.get(i);
+ //
+ final MethodsChain.CompareResult r = MethodsChain.compare(chain, newChain, myContext);
+ switch (r) {
+ case LEFT_CONTAINS_RIGHT:
+ indexesToRemove.add(i);
+ break;
+ case RIGHT_CONTAINS_LEFT:
+ case EQUAL:
+ doAdd = false;
+ break;
+ case NOT_EQUAL:
+ break;
+ }
+ }
+ while (!indexesToRemove.empty()) {
+ myResult.remove((int)indexesToRemove.pop());
+ }
+ if (doAdd) {
+ myResult.add(newChain);
+ }
+ }
+
+ public List<MethodsChain> getRawResult() {
+ return myResult;
+ }
+
+ public List<MethodsChain> getResult() {
+ return findSimilar(reduceChainsSize(myResult, PsiManager.getInstance(myContext.getProject())), myContext);
+ }
+
+ public int size() {
+ return myResult.size();
+ }
+
+ private static List<MethodsChain> reduceChainsSize(final List<MethodsChain> chains, final PsiManager psiManager) {
+ return ContainerUtil.map(chains, new Function<MethodsChain, MethodsChain>() {
+ @Override
+ public MethodsChain fun(final MethodsChain chain) {
+ final Iterator<PsiMethod[]> chainIterator = chain.iterator();
+ if (!chainIterator.hasNext()) {
+ LOG.error("empty chain");
+ return chain;
+ }
+ final PsiMethod[] first = chainIterator.next();
+ while (chainIterator.hasNext()) {
+ final PsiMethod psiMethod = chainIterator.next()[0];
+ if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
+ continue;
+ }
+ final PsiClass current = psiMethod.getContainingClass();
+ if (current == null) {
+ LOG.error("containing class must be not null");
+ return chain;
+ }
+ final PsiMethod[] currentMethods = current.findMethodsByName(first[0].getName(), true);
+ if (currentMethods.length != 0) {
+ for (final PsiMethod f : first) {
+ final PsiMethod[] fSupers = f.findDeepestSuperMethods();
+ final PsiMethod fSuper = fSupers.length == 0 ? first[0] : fSupers[0];
+ for (final PsiMethod currentMethod : currentMethods) {
+ if (psiManager.areElementsEquivalent(currentMethod, fSuper)) {
+ return createChainFromFirstElement(chain, currentMethod.getContainingClass());
+ }
+ for (final PsiMethod method : currentMethod.findDeepestSuperMethods()) {
+ if (psiManager.areElementsEquivalent(method, fSuper)) {
+ return createChainFromFirstElement(chain, method.getContainingClass());
+ }
+ }
+ }
+ }
+ }
+ }
+ return chain;
+ }
+ });
+ }
+
+ private static List<MethodsChain> findSimilar(final List<MethodsChain> chains, final PsiManager psiManager) {
+ final ResultHolder resultHolder = new ResultHolder(psiManager);
+ for (final MethodsChain chain : chains) {
+ resultHolder.add(chain);
+ }
+ return resultHolder.getRawResult();
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MaxSizeTreeSet.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MaxSizeTreeSet.java
new file mode 100644
index 0000000..2266506
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MaxSizeTreeSet.java
@@ -0,0 +1,222 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MaxSizeTreeSet<E> implements NavigableSet<E> {
+ @NotNull
+ private final NavigableSet<E> myUnderlying;
+ private final int myMaxSize;
+
+ public MaxSizeTreeSet(final int maxSize) {
+ myMaxSize = maxSize;
+ if (myMaxSize < 1) {
+ throw new IllegalArgumentException();
+ }
+ myUnderlying = new TreeSet<E>();
+ }
+
+ public E lower(final E e) {
+ return myUnderlying.lower(e);
+ }
+
+ public E floor(final E e) {
+ return myUnderlying.floor(e);
+ }
+
+ public E ceiling(final E e) {
+ return myUnderlying.ceiling(e);
+ }
+
+ public E higher(final E e) {
+ return myUnderlying.higher(e);
+ }
+
+ @Override
+ public E pollFirst() {
+ return myUnderlying.pollFirst();
+ }
+
+ @Override
+ public E pollLast() {
+ return myUnderlying.pollLast();
+ }
+
+ @NotNull
+ @Override
+ public Iterator<E> iterator() {
+ return myUnderlying.iterator();
+ }
+
+ @NotNull
+ @Override
+ public NavigableSet<E> descendingSet() {
+ return myUnderlying.descendingSet();
+ }
+
+ @NotNull
+ @Override
+ public Iterator<E> descendingIterator() {
+ return myUnderlying.descendingIterator();
+ }
+
+ @NotNull
+ public NavigableSet<E> subSet(final E fromElement, final boolean fromInclusive, final E toElement, final boolean toInclusive) {
+ return myUnderlying.subSet(fromElement, fromInclusive, toElement, toInclusive);
+ }
+
+ @NotNull
+ public NavigableSet<E> headSet(final E toElement, final boolean inclusive) {
+ return myUnderlying.headSet(toElement, inclusive);
+ }
+
+ @NotNull
+ public NavigableSet<E> tailSet(final E fromElement, final boolean inclusive) {
+ return myUnderlying.tailSet(fromElement, inclusive);
+ }
+
+ @NotNull
+ public SortedSet<E> subSet(final E fromElement, final E toElement) {
+ return myUnderlying.subSet(fromElement, toElement);
+ }
+
+ @NotNull
+ public SortedSet<E> headSet(final E toElement) {
+ return myUnderlying.headSet(toElement);
+ }
+
+ @NotNull
+ public SortedSet<E> tailSet(final E fromElement) {
+ return myUnderlying.tailSet(fromElement);
+ }
+
+ @Nullable
+ @Override
+ public Comparator<? super E> comparator() {
+ return myUnderlying.comparator();
+ }
+
+ @Override
+ public E first() {
+ return myUnderlying.first();
+ }
+
+ @Override
+ public E last() {
+ return myUnderlying.last();
+ }
+
+ @Override
+ public int size() {
+ return myUnderlying.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return myUnderlying.isEmpty();
+ }
+
+ @Override
+ public boolean contains(final Object o) {
+ return myUnderlying.contains(o);
+ }
+
+ @NotNull
+ @Override
+ public Object[] toArray() {
+ return myUnderlying.toArray();
+ }
+
+ @NotNull
+ @Override
+ public <T> T[] toArray(final T[] a) {
+ return myUnderlying.toArray(a);
+ }
+
+ public boolean add(final E e) {
+ if (myUnderlying.size() == myMaxSize) {
+ //noinspection ConstantConditions
+ final Comparator<? super E> comparator = comparator();
+ if ((comparator == null ? ((Comparable)e).compareTo(last()) : comparator.compare(e, last())) < 0) {
+ final boolean isAdded = myUnderlying.add(e);
+ if (isAdded) {
+ pollLast();
+ return true;
+ }
+ }
+ return false;
+ }
+ return myUnderlying.add(e);
+ }
+
+ @Override
+ public boolean remove(final Object o) {
+ return myUnderlying.remove(o);
+ }
+
+ @Override
+ public boolean containsAll(final Collection<?> c) {
+ return myUnderlying.containsAll(c);
+ }
+
+ public boolean addAll(final Collection<? extends E> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(final Collection<?> c) {
+ return myUnderlying.retainAll(c);
+ }
+
+ @Override
+ public boolean removeAll(final Collection<?> c) {
+ return myUnderlying.removeAll(c);
+ }
+
+ @Override
+ public void clear() {
+ myUnderlying.clear();
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MaxSizeTreeSet)) return false;
+
+ final MaxSizeTreeSet that = (MaxSizeTreeSet)o;
+
+ if (!myUnderlying.equals(that.myUnderlying)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return myUnderlying.hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return myUnderlying.toString();
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodChainsSearchUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodChainsSearchUtil.java
new file mode 100644
index 0000000..08dbe04
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodChainsSearchUtil.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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.psi.*;
+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;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class MethodChainsSearchUtil {
+ private MethodChainsSearchUtil() {
+ }
+
+ @Nullable
+ public static PsiMethod getMethodWithMinNotPrimitiveParameters(final @NotNull PsiMethod[] methods,
+ final Set<String> excludedParamsQNames) {
+ PsiMethod minMethod = null;
+ int minParametersCount = Integer.MAX_VALUE;
+ for (final PsiMethod method : methods) {
+ final PsiParameterList parameterList = method.getParameterList();
+ boolean doContinue = false;
+ int parametersCount = parameterList.getParametersCount();
+ for (final PsiParameter p : parameterList.getParameters()) {
+ if (!(p.getType() instanceof PsiPrimitiveType)) {
+ if (excludedParamsQNames.contains(p.getType().getCanonicalText())) {
+ doContinue = true;
+ break;
+ }
+ parametersCount++;
+ }
+ }
+ if (doContinue) {
+ continue;
+ }
+ if (parametersCount < minParametersCount) {
+ if (parametersCount == 0) {
+ return method;
+ }
+ minParametersCount = parametersCount;
+ minMethod = method;
+ }
+ }
+ return minMethod;
+ }
+
+ public static boolean checkParametersForTypesQNames(final PsiMethod[] psiMethods, final Set<String> excludedTypesQNames) {
+ if (psiMethods.length == 0) {
+ return true;
+ }
+ for (final PsiMethod method : psiMethods) {
+ boolean hasTargetInParams = false;
+ for (final PsiParameter param : method.getParameterList().getParameters()) {
+ final String paramType = param.getType().getCanonicalText();
+ if (excludedTypesQNames.contains(paramType)) {
+ hasTargetInParams = true;
+ break;
+ }
+ }
+ if (!hasTargetInParams) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static <T> HashSet<T> unionToHashSet(final Collection<T> collection, final T... items) {
+ final HashSet<T> result = new HashSet<T>();
+ result.addAll(collection);
+ Collections.addAll(result, items);
+ return result;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChain.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChain.java
new file mode 100644
index 0000000..7d46c07
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChain.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+import static com.intellij.util.containers.ContainerUtil.findAll;
+import static com.intellij.util.containers.ContainerUtil.reverse;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChain {
+ private final List<PsiMethod[]> myRevertedPath;
+ private final int myWeight;
+ //
+ // chain qualifier class could be different with method.getContainingClass()
+ private final String myQualifierClassName;
+
+ private final Set<String> myExcludedQNames;
+
+ public MethodsChain(final PsiMethod[] methods, final int weight, final String qualifierClassName) {
+ this(Collections.singletonList(methods), weight, qualifierClassName, chooseParametersQNames(methods));
+ }
+
+ private MethodsChain(final List<PsiMethod[]> revertedPath,
+ final int weight,
+ final String qualifierClassName,
+ final Set<String> excludedQNames) {
+ myRevertedPath = revertedPath;
+ myWeight = weight;
+ myQualifierClassName = qualifierClassName;
+ myExcludedQNames = excludedQNames;
+ }
+
+ public int size() {
+ return myRevertedPath.size();
+ }
+
+ public Set<String> getExcludedQNames() {
+ return myExcludedQNames;
+ }
+
+ public String getQualifierClassName() {
+ return myQualifierClassName;
+ }
+
+ public Iterator<PsiMethod[]> iterator() {
+ return myRevertedPath.iterator();
+ }
+
+ @NotNull
+ public PsiMethod[] getFirst() {
+ return myRevertedPath.get(0);
+ }
+
+ public List<PsiMethod[]> getPath() {
+ return reverse(myRevertedPath);
+ }
+
+ public int getChainWeight() {
+ return myWeight;
+ }
+
+ @SuppressWarnings("unchecked")
+ public MethodsChain addEdge(final PsiMethod[] psiMethods, final String newQualifierClassName, final int newWeight) {
+ final List<PsiMethod[]> newRevertedPath = new ArrayList<PsiMethod[]>(myRevertedPath.size() + 1);
+ newRevertedPath.addAll(myRevertedPath);
+ newRevertedPath.add(psiMethods);
+ return new MethodsChain(newRevertedPath,
+ newWeight,
+ newQualifierClassName,
+ joinSets(myExcludedQNames, chooseParametersQNames(psiMethods)));
+ }
+
+
+ @Override
+ public String toString() {
+ return StringUtil.join(myRevertedPath, "<-");
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ public static CompareResult compare(final MethodsChain left, final MethodsChain right, final PsiManager psiManager) {
+ if (left.size() == 0) {
+ return CompareResult.RIGHT_CONTAINS_LEFT;
+ }
+ if (right.size() == 0) {
+ return CompareResult.LEFT_CONTAINS_RIGHT;
+ }
+ final Iterator<PsiMethod[]> leftIterator = left.myRevertedPath.iterator();
+ final Iterator<PsiMethod[]> rightIterator = right.myRevertedPath.iterator();
+
+ while (leftIterator.hasNext() && rightIterator.hasNext()) {
+ final PsiMethod thisNext = leftIterator.next()[0];
+ final PsiMethod thatNext = rightIterator.next()[0];
+ if (thisNext == null || thatNext == null) {
+ throw new NullPointerException();
+ }
+ if (((thisNext.isConstructor() != thatNext.isConstructor())) || !thisNext.getName().equals(thatNext.getName())) {
+ return CompareResult.NOT_EQUAL;
+ }
+ }
+ if (leftIterator.hasNext() && !rightIterator.hasNext()) {
+ return CompareResult.LEFT_CONTAINS_RIGHT;
+ }
+ if (!leftIterator.hasNext() && rightIterator.hasNext()) {
+ return CompareResult.RIGHT_CONTAINS_LEFT;
+ }
+
+
+ return hasBaseMethod(left.getPath().get(0), right.getPath().get(0), psiManager)
+ ? CompareResult.EQUAL
+ : CompareResult.NOT_EQUAL;
+ }
+
+ public enum CompareResult {
+ LEFT_CONTAINS_RIGHT,
+ RIGHT_CONTAINS_LEFT,
+ EQUAL,
+ NOT_EQUAL
+ }
+
+ private static boolean hasBaseMethod(final PsiMethod[] left, final PsiMethod[] right, final PsiManager psiManager) {
+ for (final PsiMethod rightMethod : right) {
+ final PsiMethod[] rightSupers = rightMethod.findDeepestSuperMethods();
+ if (rightSupers.length != 0) {
+ for (final PsiMethod leftMethod : left) {
+ final PsiMethod[] leftSupers = leftMethod.findDeepestSuperMethods();
+ if (leftSupers.length != 0) {
+ if (psiManager.areElementsEquivalent(leftSupers[0], rightSupers[0])) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static Set<String> joinSets(final Set<String>... sets) {
+ final Set<String> result = new HashSet<String>();
+ for (final Set<String> set : sets) {
+ for (final String s : set) {
+ result.add(s);
+ }
+ }
+ return result;
+ }
+
+ private static Set<String> chooseParametersQNames(final PsiMethod[] methods) {
+ final Set<String> qNames = new HashSet<String>();
+ for (final PsiParameter methodParameter : methods[0].getParameterList().getParameters()) {
+ qNames.add(methodParameter.getType().getCanonicalText());
+ }
+ return qNames;
+ }
+
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java
new file mode 100644
index 0000000..00a0dcd
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/MethodsChainLookupRangingHelper.java
@@ -0,0 +1,286 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.codeInsight.completion.JavaChainLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ContextRelevantStaticMethod;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ContextRelevantVariableGetter;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.ChainCompletionNewVariableLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.WeightableChainLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.GetterLookupSubLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.VariableSubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.VariableLookupItem;
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
+import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodsChainLookupRangingHelper {
+
+ public static List<LookupElement> chainsToWeightableLookupElements(final List<MethodsChain> chains,
+ final ChainCompletionContext context) {
+ final List<LookupElement> lookupElements = new ArrayList<LookupElement>(chains.size());
+ for (final MethodsChain chain : chains) {
+ final LookupElement lookupElement = chainToWeightableLookupElement(chain, context);
+ if (lookupElement != null) {
+ lookupElements.add(lookupElement);
+ }
+ }
+ return lookupElements;
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ @Nullable
+ private static LookupElement chainToWeightableLookupElement(final MethodsChain chain, final ChainCompletionContext context) {
+ final int chainSize = chain.size();
+ assert chainSize != 0;
+ final int lastMethodWeight = chain.getChainWeight();
+ int unreachableParametersCount = 0;
+ int notMatchedStringVars = 0;
+ int matchedParametersInContext = 0;
+ Boolean isFirstMethodStatic = null;
+ Boolean hasCallingVariableInContext = null;
+ LookupElement chainLookupElement = null;
+ PsiClass newVariableClass = null;
+ final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(context.getProject());
+
+ for (final PsiMethod[] psiMethods : chain.getPath()) {
+ final PsiMethod method =
+ MethodChainsSearchUtil.getMethodWithMinNotPrimitiveParameters(psiMethods, Collections.singleton(context.getTarget().getClassQName()));
+ if (method == null) {
+ return null;
+ }
+ if (isFirstMethodStatic == null) {
+ isFirstMethodStatic = psiMethods[0].hasModifierProperty(PsiModifier.STATIC);
+ }
+ final PsiClass qualifierClass;
+ final boolean isHead = chainLookupElement == null;
+ if (isHead) {
+ final String qualifierClassName = chain.getQualifierClassName();
+ qualifierClass = JavaPsiFacade.getInstance(context.getProject()).
+ findClass(qualifierClassName, context.getResolveScope());
+ }
+ else {
+ qualifierClass = null;
+ }
+
+ final MethodProcResult procResult = processMethod(method, qualifierClass, context, lastMethodWeight, isHead, nullableNotNullManager);
+ if (procResult == null) {
+ return null;
+ }
+ if (hasCallingVariableInContext == null) {
+ hasCallingVariableInContext = procResult.hasCallingVariableInContext();
+ }
+ if (isHead && procResult.isIntroduceNewVariable()) {
+ newVariableClass = qualifierClass;
+ }
+ matchedParametersInContext += procResult.getMatchedParametersInContext();
+ unreachableParametersCount += procResult.getUnreachableParametersCount();
+ notMatchedStringVars += procResult.getNotMatchedStringVars();
+ chainLookupElement =
+ isHead ? procResult.getLookupElement() : new JavaChainLookupElement(chainLookupElement, procResult.getLookupElement());
+ }
+
+ if (newVariableClass != null) {
+ chainLookupElement = ChainCompletionNewVariableLookupElement.create(newVariableClass, chainLookupElement);
+ }
+
+ final ChainRelevance relevance =
+ new ChainRelevance(chainSize, lastMethodWeight, unreachableParametersCount, notMatchedStringVars, hasCallingVariableInContext,
+ isFirstMethodStatic, matchedParametersInContext);
+
+ return new WeightableChainLookupElement(chainLookupElement, relevance);
+ }
+
+
+ @Nullable
+ private static MethodProcResult processMethod(@NotNull final PsiMethod method,
+ @Nullable final PsiClass qualifierClass,
+ final ChainCompletionContext context,
+ final int weight,
+ final boolean isHeadMethod,
+ final NullableNotNullManager nullableNotNullManager) {
+ int unreachableParametersCount = 0;
+ int notMatchedStringVars = 0;
+ int matchedParametersInContext = 0;
+ boolean hasCallingVariableInContext = false;
+ boolean introduceNewVariable = false;
+ final PsiParameterList parameterList = method.getParameterList();
+ final TIntObjectHashMap<SubLookupElement> parametersMap = new TIntObjectHashMap<SubLookupElement>(parameterList.getParametersCount());
+ final PsiParameter[] parameters = parameterList.getParameters();
+ for (int i = 0; i < parameters.length; i++) {
+ final PsiParameter parameter = parameters[i];
+ final String typeQName = parameter.getType().getCanonicalText();
+ if (JAVA_LANG_STRING.equals(typeQName)) {
+ final PsiVariable relevantStringVar = context.findRelevantStringInContext(parameter.getName());
+ if (relevantStringVar == null) {
+ notMatchedStringVars++;
+ }
+ else {
+ parametersMap.put(i, new VariableSubLookupElement(relevantStringVar));
+ }
+ }
+ else if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(typeQName)) {
+ final Collection<PsiVariable> contextVariables = context.getVariables(typeQName);
+ final PsiVariable contextVariable = ContainerUtil.getFirstItem(contextVariables, null);
+ if (contextVariable != null) {
+ if (contextVariables.size() == 1) parametersMap.put(i, new VariableSubLookupElement(contextVariable));
+ matchedParametersInContext++;
+ continue;
+ }
+ final Collection<ContextRelevantVariableGetter> relevantVariablesGetters = context.getRelevantVariablesGetters(typeQName);
+ final ContextRelevantVariableGetter contextVariableGetter = ContainerUtil.getFirstItem(relevantVariablesGetters, null);
+ if (contextVariableGetter != null) {
+ if (relevantVariablesGetters.size() == 1) parametersMap.put(i, contextVariableGetter.createSubLookupElement());
+ matchedParametersInContext++;
+ continue;
+ }
+ final Collection<PsiMethod> containingClassMethods = context.getContainingClassMethods(typeQName);
+ final PsiMethod contextRelevantGetter = ContainerUtil.getFirstItem(containingClassMethods, null);
+ if (contextRelevantGetter != null) {
+ if (containingClassMethods.size() == 1) parametersMap.put(i, new GetterLookupSubLookupElement(method.getName()));
+ matchedParametersInContext++;
+ continue;
+ }
+ final ContextRelevantStaticMethod contextRelevantStaticMethod =
+ ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null);
+ if (contextRelevantStaticMethod != null) {
+ //
+ // In most cases it is not really relevant
+ //
+ //parametersMap.put(i, contextRelevantStaticMethod.createLookupElement());
+ matchedParametersInContext++;
+ continue;
+ }
+ if (!nullableNotNullManager.isNullable(parameter, true)) {
+ unreachableParametersCount++;
+ }
+ }
+ }
+ final LookupElement lookupElement;
+ if (isHeadMethod) {
+ if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ hasCallingVariableInContext = true;
+ lookupElement = createLookupElement(method, parametersMap);
+ }
+ else if (method.isConstructor()) {
+ return null;
+ }
+ else {
+ @SuppressWarnings("ConstantConditions")
+ final String classQName = qualifierClass.getQualifiedName();
+ if (classQName == null) return null;
+ final Object e = ContainerUtil.getFirstItem(context.getContextRefElements(classQName), null);
+ if (e != null) {
+ final LookupElement firstChainElement;
+ if (e instanceof PsiVariable) {
+ firstChainElement = new VariableLookupItem((PsiVariable)e);
+ }
+ else if (e instanceof PsiMethod) {
+ firstChainElement = createLookupElement((PsiMethod)e, null);
+ }
+ else if (e instanceof LookupElement) {
+ firstChainElement = (LookupElement)e;
+ }
+ else {
+ throw new AssertionError();
+ }
+ hasCallingVariableInContext = true;
+ lookupElement = new JavaChainLookupElement(firstChainElement, createLookupElement(method, parametersMap));
+ }
+ else {
+ lookupElement = createLookupElement(method, parametersMap);
+ if (!context.getContainingClassQNames().contains(classQName)) {
+ introduceNewVariable = true;
+ }
+ }
+ }
+ }
+ else {
+ lookupElement = createLookupElement(method, parametersMap);
+ }
+ return new MethodProcResult(lookupElement,
+ unreachableParametersCount,
+ notMatchedStringVars,
+ hasCallingVariableInContext,
+ introduceNewVariable,
+ matchedParametersInContext);
+ }
+
+ private static class MethodProcResult {
+ private final LookupElement myMethodLookup;
+ private final int myUnreachableParametersCount;
+ private final int myNotMatchedStringVars;
+ private final boolean myHasCallingVariableInContext;
+ private final boolean myIntroduceNewVariable;
+ private final int myMatchedParametersInContext;
+
+ private MethodProcResult(final LookupElement methodLookup,
+ final int unreachableParametersCount,
+ final int notMatchedStringVars,
+ final boolean hasCallingVariableInContext,
+ final boolean introduceNewVariable,
+ final int matchedParametersInContext) {
+ myMethodLookup = methodLookup;
+ myUnreachableParametersCount = unreachableParametersCount;
+ myNotMatchedStringVars = notMatchedStringVars;
+ myHasCallingVariableInContext = hasCallingVariableInContext;
+ myIntroduceNewVariable = introduceNewVariable;
+ myMatchedParametersInContext = matchedParametersInContext;
+ }
+
+ private boolean isIntroduceNewVariable() {
+ return myIntroduceNewVariable;
+ }
+
+ private boolean hasCallingVariableInContext() {
+ return myHasCallingVariableInContext;
+ }
+
+ private LookupElement getLookupElement() {
+ return myMethodLookup;
+ }
+
+ private int getUnreachableParametersCount() {
+ return myUnreachableParametersCount;
+ }
+
+ private int getNotMatchedStringVars() {
+ return myNotMatchedStringVars;
+ }
+
+ public int getMatchedParametersInContext() {
+ return myMatchedParametersInContext;
+ }
+ }
+}
+
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java
new file mode 100644
index 0000000..68c2529
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/ParametersMatcher.java
@@ -0,0 +1,111 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiParameter;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.NavigableSet;
+import java.util.Set;
+import java.util.TreeSet;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ParametersMatcher {
+
+ private ParametersMatcher() {}
+
+ public static MatchResult matchParameters(final MethodsChain chain, final ChainCompletionContext context) {
+ MatchResult overallResult = EMPTY;
+ for (final PsiMethod[] methods : chain.getPath()) {
+ final NavigableSet<MatchResult> matchResults = new TreeSet<MatchResult>();
+ for (final PsiMethod method : methods) {
+ matchResults.add(matchParameters(method, context, chain.getExcludedQNames()));
+ }
+ final MatchResult best = matchResults.first();
+ overallResult = overallResult.add(best);
+ }
+ return overallResult;
+ }
+
+ private static MatchResult matchParameters(final PsiMethod method, final ChainCompletionContext context, final Set<String> additionalExcludedNames) {
+ int matched = 0;
+ int unMatched = 0;
+ boolean hasTarget = false;
+ for (final PsiParameter parameter : method.getParameterList().getParameters()) {
+ final PsiType type = parameter.getType();
+ final String canonicalText = type.getCanonicalText();
+ if (context.contains(canonicalText) || type instanceof PsiPrimitiveType) {
+ matched++;
+ }
+ else {
+ unMatched++;
+ }
+ if (context.getTarget().getClassQName().equals(canonicalText) || additionalExcludedNames.contains(canonicalText)) {
+ hasTarget = true;
+ }
+ }
+ return new MatchResult(matched, unMatched, hasTarget);
+ }
+
+ private static final MatchResult EMPTY = new MatchResult(0, 0, false);
+
+ public static class MatchResult implements Comparable<MatchResult> {
+ private final int myMatched;
+ private final int myUnMatched;
+ private final boolean myHasTarget;
+
+ private MatchResult(final int matched, final int unMatched, final boolean hasTarget) {
+ myMatched = matched;
+ myUnMatched = unMatched;
+ myHasTarget = hasTarget;
+ }
+
+ public int getMatched() {
+ return myMatched;
+ }
+
+ public int getUnMatched() {
+ return myUnMatched;
+ }
+
+ public boolean hasTarget() {
+ return myHasTarget;
+ }
+
+ public MatchResult add(final MatchResult other) {
+ return new MatchResult(getMatched() + other.getMatched(), getUnMatched() + other.getUnMatched(), other.myHasTarget || myHasTarget);
+ }
+
+ public boolean noUnmatchedAndHasMatched() {
+ return myUnMatched == 0 && myMatched != 0;
+ }
+
+ @Override
+ public int compareTo(@NotNull final MatchResult other) {
+ final int sub = getUnMatched() - other.getUnMatched();
+ if (sub != 0) {
+ return sub;
+ }
+ return getMatched() - other.getMatched();
+ }
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/SearchInitializer.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/SearchInitializer.java
new file mode 100644
index 0000000..89becb4
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/SearchInitializer.java
@@ -0,0 +1,106 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext;
+import com.intellij.compiler.classFilesIndex.impl.UsageIndexValue;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiMethod;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class SearchInitializer {
+ private final static int CHAIN_SEARCH_MAGIC_RATIO = 12;
+
+ private final LinkedHashMap<MethodIncompleteSignature, Pair<MethodsChain, Integer>> myChains;
+ private final ChainCompletionContext myContext;
+
+ public SearchInitializer(final SortedSet<UsageIndexValue> indexValues,
+ final String targetQName,
+ final Set<String> excludedParamsTypesQNames,
+ final ChainCompletionContext context) {
+ myContext = context;
+ final int size = indexValues.size();
+ myChains = new LinkedHashMap<MethodIncompleteSignature, Pair<MethodsChain, Integer>>(size);
+ add(indexValues, MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName));
+ }
+
+ private void add(final Collection<UsageIndexValue> indexValues, final Set<String> excludedParamsTypesQNames) {
+ int bestOccurrences = -1;
+ for (final UsageIndexValue indexValue : indexValues) {
+ if (add(indexValue, excludedParamsTypesQNames)) {
+ final int occurrences = indexValue.getOccurrences();
+ if (bestOccurrences == -1) {
+ bestOccurrences = occurrences;
+ }
+ else if (bestOccurrences > occurrences * CHAIN_SEARCH_MAGIC_RATIO) {
+ return;
+ }
+ }
+ }
+ }
+
+ private boolean add(final UsageIndexValue indexValue, final Set<String> excludedParamsTypesQNames) {
+ final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
+ final PsiMethod[] psiMethods = myContext.resolveNotDeprecated(methodInvocation);
+ if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, excludedParamsTypesQNames)) {
+ final int occurrences = indexValue.getOccurrences();
+ final MethodsChain methodsChain = new MethodsChain(psiMethods, occurrences, indexValue.getMethodIncompleteSignature().getOwner());
+ myChains.put(methodInvocation, Pair.create(methodsChain, occurrences));
+ return true;
+ }
+ return false;
+ }
+
+ public InitResult init(final Set<String> excludedEdgeNames) {
+ final int size = myChains.size();
+ final List<WeightAware<MethodIncompleteSignature>> initedVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
+ final LinkedHashMap<MethodIncompleteSignature, MethodsChain> initedChains =
+ new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
+ for (final Map.Entry<MethodIncompleteSignature, Pair<MethodsChain, Integer>> entry : myChains.entrySet()) {
+ final MethodIncompleteSignature signature = entry.getKey();
+ if (!excludedEdgeNames.contains(signature.getName())) {
+ initedVertexes.add(new WeightAware<MethodIncompleteSignature>(entry.getKey(), entry.getValue().getSecond()));
+ final MethodsChain methodsChain = entry.getValue().getFirst();
+ initedChains.put(signature, methodsChain);
+ }
+ }
+ return new InitResult(initedVertexes, initedChains);
+ }
+
+ public static class InitResult {
+ private final List<WeightAware<MethodIncompleteSignature>> myVertexes;
+ private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
+
+ private InitResult(final List<WeightAware<MethodIncompleteSignature>> vertexes,
+ final LinkedHashMap<MethodIncompleteSignature, MethodsChain> chains) {
+ myVertexes = vertexes;
+ myChains = chains;
+ }
+
+ public List<WeightAware<MethodIncompleteSignature>> getVertexes() {
+ return myVertexes;
+ }
+
+ public LinkedHashMap<MethodIncompleteSignature, MethodsChain> getChains() {
+ return myChains;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/WeightAware.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/WeightAware.java
new file mode 100644
index 0000000..9430a65
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/WeightAware.java
@@ -0,0 +1,48 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class WeightAware<V> implements Comparable<WeightAware<V>> {
+ private final V myUnderlying;
+ private final int myWeight;
+
+ public WeightAware(final V underlying, final int weight) {
+ myUnderlying = underlying;
+ myWeight = weight;
+ }
+
+ public V getUnderlying() {
+ return myUnderlying;
+ }
+
+ public int getWeight() {
+ return myWeight;
+ }
+
+ @Override
+ public int compareTo(@NotNull final WeightAware<V> that) {
+ final int sub = -getWeight() + that.getWeight();
+ if (sub != 0) {
+ return sub;
+ }
+ return myUnderlying.hashCode() - that.myUnderlying.hashCode();
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/CompletionContributorPatternUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/CompletionContributorPatternUtil.java
new file mode 100644
index 0000000..0ddade8
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/CompletionContributorPatternUtil.java
@@ -0,0 +1,48 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion;
+
+import com.intellij.codeInsight.completion.CompletionInitializationContext;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
+
+import static com.intellij.patterns.PsiJavaPatterns.psiElement;
+import static com.intellij.patterns.StandardPatterns.or;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public final class CompletionContributorPatternUtil {
+
+ private CompletionContributorPatternUtil() {}
+
+ @SuppressWarnings("unchecked")
+ public static ElementPattern<PsiElement> patternForVariableAssignment() {
+ final ElementPattern<PsiElement> patternForParent = or(psiElement().withText(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)
+ .afterSiblingSkipping(psiElement(PsiWhiteSpace.class),
+ psiElement(PsiJavaToken.class).withText("=")));
+
+ return psiElement().withParent(patternForParent).withSuperParent(2, or(psiElement(PsiAssignmentExpression.class),
+ psiElement(PsiLocalVariable.class)
+ .inside(PsiDeclarationStatement.class)))
+ .inside(PsiMethod.class);
+ }
+
+ public static ElementPattern<PsiElement> patternForMethodParameter() {
+ return psiElement().withSuperParent(3, PsiMethodCallExpressionImpl.class);
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java
new file mode 100644
index 0000000..85ee710
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsCompletionContributor.java
@@ -0,0 +1,223 @@
+package com.intellij.compiler.classFilesIndex.chainsSearch.completion;
+
+import com.intellij.codeInsight.completion.*;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeature;
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeaturesHolder;
+import com.intellij.compiler.classFilesIndex.chainsSearch.*;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ChainCompletionContext;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.ContextUtil;
+import com.intellij.compiler.classFilesIndex.chainsSearch.context.TargetType;
+import com.intellij.compiler.classFilesIndex.impl.MethodsUsageIndexReader;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.project.Project;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.PsiImmediateClassType;
+import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+import static com.intellij.patterns.PsiJavaPatterns.or;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChainsCompletionContributor extends CompletionContributor {
+ private final static boolean IS_UNIT_TEST_MODE = ApplicationManager.getApplication().isUnitTestMode();
+
+ public static final int INVOCATIONS_THRESHOLD = 2;
+ public static final CompletionType COMPLETION_TYPE = IS_UNIT_TEST_MODE ? CompletionType.BASIC : CompletionType.SMART;
+
+ private final static int MAX_SEARCH_RESULT_SIZE = 5;
+ private final static int MAX_CHAIN_SIZE = 4;
+ private final static int FILTER_RATIO = 10;
+
+ @Override
+ public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
+ if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD &&
+ ClassFilesIndexFeaturesHolder.getInstance(parameters.getPosition().getProject())
+ .enableFeatureIfNeed(ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION)) {
+ super.fillCompletionVariants(parameters, result);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public MethodsChainsCompletionContributor() {
+ final ElementPattern<PsiElement> pattern =
+ or(CompletionContributorPatternUtil.patternForMethodParameter(), CompletionContributorPatternUtil.patternForVariableAssignment());
+ extend(COMPLETION_TYPE, pattern, new CompletionProvider<CompletionParameters>() {
+ @Override
+ protected void addCompletions(final @NotNull CompletionParameters parameters,
+ final ProcessingContext context,
+ final @NotNull CompletionResultSet result) {
+ final ChainCompletionContext completionContext = extractContext(parameters);
+ if (completionContext == null) return;
+
+ final Set<String> contextTypesKeysSet = completionContext.getContextTypes();
+ final Set<String> contextRelevantTypes = new HashSet<String>(contextTypesKeysSet.size() + 1);
+ for (final String type : contextTypesKeysSet) {
+ if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(type)) {
+ contextRelevantTypes.add(type);
+ }
+ }
+ final TargetType target = completionContext.getTarget();
+ contextRelevantTypes.remove(target.getClassQName());
+ final List<LookupElement> elementsFoundByMethodsChainsSearch = searchForLookups(target, contextRelevantTypes, completionContext);
+ if (!IS_UNIT_TEST_MODE) {
+ result.runRemainingContributors(parameters, new Consumer<CompletionResult>() {
+ @Override
+ public void consume(final CompletionResult completionResult) {
+ final LookupElement lookupElement = completionResult.getLookupElement();
+ final PsiElement lookupElementPsi = lookupElement.getPsiElement();
+ if (lookupElementPsi != null) {
+ for (final LookupElement element : elementsFoundByMethodsChainsSearch) {
+ if (lookupElementPsi.isEquivalentTo(element.getPsiElement())) {
+ elementsFoundByMethodsChainsSearch.remove(element);
+ break;
+ }
+ }
+ }
+ result.passResult(completionResult);
+ }
+ });
+ } else {
+ result.stopHere();
+ }
+ result.addAllElements(elementsFoundByMethodsChainsSearch);
+ }
+ });
+ }
+
+ private static List<LookupElement> searchForLookups(final TargetType target,
+ final Set<String> contextRelevantTypes,
+ final ChainCompletionContext completionContext) {
+ final Project project = completionContext.getProject();
+ final MethodsUsageIndexReader methodsUsageIndexReader = MethodsUsageIndexReader.getInstance(project);
+ final List<MethodsChain> searchResult =
+ searchChains(target, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, methodsUsageIndexReader);
+ if (searchResult.size() < MAX_SEARCH_RESULT_SIZE) {
+ if (!target.isArray()) {
+ final List<MethodsChain> inheritorFilteredSearchResult = new SmartList<MethodsChain>();
+ final Processor<TargetType> consumer = new Processor<TargetType>() {
+ @Override
+ public boolean process(final TargetType targetType) {
+ for (final MethodsChain chain : searchChains(targetType, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE,
+ completionContext, methodsUsageIndexReader)) {
+ boolean insert = true;
+ for (final MethodsChain baseChain : searchResult) {
+ final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext.getPsiManager());
+ if (r != MethodsChain.CompareResult.NOT_EQUAL) {
+ insert = false;
+ break;
+ }
+ }
+ if (insert) {
+ inheritorFilteredSearchResult.add(chain);
+ }
+ }
+ searchResult.addAll(inheritorFilteredSearchResult);
+ return searchResult.size() < MAX_SEARCH_RESULT_SIZE;
+ }
+ };
+ DirectClassInheritorsSearch.search(((PsiClassType)target.getPsiType()).resolve()).forEach(new Processor<PsiClass>() {
+ @Override
+ public boolean process(final PsiClass psiClass) {
+ final String inheritorQName = psiClass.getQualifiedName();
+ if (inheritorQName == null) {
+ return true;
+ }
+ return consumer.process(new TargetType(inheritorQName, false, new PsiImmediateClassType(psiClass, PsiSubstitutor.EMPTY)));
+ }
+ });
+ }
+ }
+ final List<MethodsChain> chains = searchResult.size() > MAX_CHAIN_SIZE ? chooseHead(searchResult) : searchResult;
+ return MethodsChainLookupRangingHelper
+ .chainsToWeightableLookupElements(filterTailAndGetSumLastMethodOccurrence(chains), completionContext);
+ }
+
+ private static List<MethodsChain> chooseHead(final List<MethodsChain> elements) {
+ Collections.sort(elements, new Comparator<MethodsChain>() {
+ @Override
+ public int compare(final MethodsChain o1, final MethodsChain o2) {
+ return o2.getChainWeight() - o1.getChainWeight();
+ }
+ });
+ return elements.subList(0, MAX_CHAIN_SIZE);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Nullable
+ private static ChainCompletionContext extractContext(final CompletionParameters parameters) {
+ final PsiElement parent = PsiTreeUtil
+ .getParentOfType(parameters.getPosition(), PsiAssignmentExpression.class, PsiLocalVariable.class, PsiMethodCallExpression.class);
+ if (parent == null) {
+ return null;
+ }
+
+ if (parent instanceof PsiAssignmentExpression) {
+ return tryExtractContextFromAssignment((PsiAssignmentExpression)parent);
+ }
+ if (parent instanceof PsiLocalVariable) {
+ final PsiLocalVariable localVariable = (PsiLocalVariable)parent;
+ return ContextUtil.createContext(localVariable.getType(), localVariable.getName(),
+ PsiTreeUtil.getParentOfType(parent, PsiDeclarationStatement.class));
+ }
+ final PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
+ if (method == null) return null;
+ final PsiExpression expression = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpression.class);
+ final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpressionList.class);
+ if (expressionList == null) return null;
+ final int exprPosition = Arrays.asList(expressionList.getExpressions()).indexOf(expression);
+ final PsiParameter[] methodParameters = method.getParameterList().getParameters();
+ if (exprPosition < methodParameters.length) {
+ final PsiParameter methodParameter = methodParameters[exprPosition];
+ return ContextUtil
+ .createContext(methodParameter.getType(), null, PsiTreeUtil.getParentOfType(expression, PsiDeclarationStatement.class));
+ }
+ return null;
+ }
+
+ @Nullable
+ private static ChainCompletionContext tryExtractContextFromAssignment(final PsiAssignmentExpression assignmentExpression) {
+ final PsiType type = assignmentExpression.getLExpression().getType();
+ final PsiIdentifier identifier = PsiTreeUtil.getChildOfType(assignmentExpression.getLExpression(), PsiIdentifier.class);
+ if (identifier == null) return null;
+ final String identifierText = identifier.getText();
+ return ContextUtil.createContext(type, identifierText, assignmentExpression);
+ }
+
+ private static List<MethodsChain> filterTailAndGetSumLastMethodOccurrence(final List<MethodsChain> chains) {
+ int maxWeight = 0;
+ for (final MethodsChain chain : chains) {
+ final int chainWeight = chain.getChainWeight();
+ if (chainWeight > maxWeight) {
+ maxWeight = chainWeight;
+ }
+ }
+
+ final List<MethodsChain> filteredResult = new ArrayList<MethodsChain>();
+ for (final MethodsChain chain : chains) {
+ final int chainWeight = chain.getChainWeight();
+ if (chainWeight * FILTER_RATIO >= maxWeight) {
+ filteredResult.add(chain);
+ }
+ }
+ return filteredResult;
+ }
+
+ private static List<MethodsChain> searchChains(final TargetType target,
+ final Set<String> contextVarsQNames,
+ final int maxResultSize,
+ final int maxChainSize,
+ final ChainCompletionContext context,
+ final MethodsUsageIndexReader methodsUsageIndexReader) {
+ return ChainsSearcher.search(maxChainSize, target, contextVarsQNames, maxResultSize, context, methodsUsageIndexReader);
+ }
+}
\ No newline at end of file
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsWeigher.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsWeigher.java
new file mode 100644
index 0000000..9142c82
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/MethodsChainsWeigher.java
@@ -0,0 +1,36 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion;
+
+import com.intellij.codeInsight.completion.CompletionLocation;
+import com.intellij.codeInsight.completion.CompletionWeigher;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.WeightableChainLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.ChainRelevance;
+import com.intellij.codeInsight.lookup.LookupElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsChainsWeigher extends CompletionWeigher {
+ @Override
+ public Comparable weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) {
+ if (element instanceof WeightableChainLookupElement) {
+ return ((WeightableChainLookupElement)element).getChainRelevance();
+ }
+ return ChainRelevance.LOWEST;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionLookupElementUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionLookupElementUtil.java
new file mode 100644
index 0000000..3a6becb
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionLookupElementUtil.java
@@ -0,0 +1,68 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.psi.PsiKeyword;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.PsiParameter;
+import gnu.trove.TIntObjectHashMap;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ChainCompletionLookupElementUtil {
+ private ChainCompletionLookupElementUtil() {
+ }
+
+ public static LookupElement createLookupElement(final PsiMethod method,
+ final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
+ if (method.isConstructor()) {
+ //noinspection ConstantConditions
+ return LookupElementBuilder.create(String.format("%s %s", PsiKeyword.NEW, method.getContainingClass().getName()));
+ } else if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ return new ChainCompletionMethodCallLookupElement(method, replaceElements, false, true);
+ } else {
+ return new ChainCompletionMethodCallLookupElement(method, replaceElements);
+ }
+ }
+
+ public static String fillMethodParameters(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
+ final TIntObjectHashMap<SubLookupElement> notNullReplaceElements = replaceElements == null ?
+ new TIntObjectHashMap<SubLookupElement>(0) :
+ replaceElements;
+
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ final StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < parameters.length; i++) {
+ if (i != 0) {
+ sb.append(", ");
+ }
+ final PsiParameter parameter = parameters[i];
+ final SubLookupElement replaceElement = notNullReplaceElements.get(i);
+ if (replaceElement != null) {
+ sb.append(replaceElement.getInsertString());
+ } else {
+ sb.append(parameter.getName());
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionMethodCallLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionMethodCallLookupElement.java
new file mode 100644
index 0000000..d49ac3e
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionMethodCallLookupElement.java
@@ -0,0 +1,103 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.completion.JavaMethodCallElement;
+import com.intellij.codeInsight.completion.StaticallyImportable;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiMethod;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainCompletionMethodCallLookupElement extends JavaMethodCallElement implements StaticallyImportable {
+ public static final String PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION = "methods.chain.completion.autoCompletion";
+
+ private final PsiMethod myMethod;
+ @Nullable
+ private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
+ private final boolean myMergedOverloads;
+
+ public ChainCompletionMethodCallLookupElement(final PsiMethod method,
+ final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements,
+ final boolean shouldImportStatic,
+ final boolean mergedOverloads) {
+ super(method, shouldImportStatic, mergedOverloads);
+ myMethod = method;
+ myReplaceElements = replaceElements;
+ myMergedOverloads = mergedOverloads;
+ configureAutoCompletionPolicy();
+ }
+
+ public ChainCompletionMethodCallLookupElement(final PsiMethod method,
+ final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
+ super(method);
+ myMethod = method;
+ myReplaceElements = replaceElements;
+ myMergedOverloads = true;
+ configureAutoCompletionPolicy();
+ }
+
+ private void configureAutoCompletionPolicy() {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ if (PropertiesComponent.getInstance(myMethod.getProject()).getBoolean(PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, false)) {
+ setAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
+ }
+ }
+ }
+
+ @Override
+ public void handleInsert(final InsertionContext context) {
+ super.handleInsert(context);
+ if (!myMergedOverloads || isUniqueMethod(myMethod)) {
+ context.commitDocument();
+ context.getDocument()
+ .insertString(context.getTailOffset() - 1, ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
+ final PsiFile file = context.getFile();
+ assert file instanceof PsiJavaFile;
+ final PsiJavaFile javaFile = (PsiJavaFile)file;
+ if (myReplaceElements != null) {
+ myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
+ @Override
+ public boolean execute(final SubLookupElement subLookupElement) {
+ subLookupElement.doImport(javaFile);
+ return true;
+ }
+ });
+ }
+ context.commitDocument();
+ context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
+ context.commitDocument();
+ }
+ }
+
+
+ private static boolean isUniqueMethod(@NotNull final PsiMethod method) {
+ final PsiClass containingClass = method.getContainingClass();
+ return containingClass == null || containingClass.findMethodsByName(method.getName(), true).length == 1;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionNewVariableLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionNewVariableLookupElement.java
new file mode 100644
index 0000000..6e941d2
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/ChainCompletionNewVariableLookupElement.java
@@ -0,0 +1,131 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.RangeMarker;
+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.codeStyle.SuggestedNameInfo;
+import com.intellij.psi.codeStyle.VariableKind;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ChainCompletionNewVariableLookupElement extends LookupElementDecorator<LookupElement> {
+ private final static Logger log = Logger.getInstance(ChainCompletionNewVariableLookupElement.class);
+
+ private final PsiClass myPsiClass;
+ private final String myNewVarName;
+
+ public ChainCompletionNewVariableLookupElement(final PsiClass psiClass, final String newVarName, final LookupElement calledMethods) {
+ super(calledMethods);
+ myNewVarName = newVarName;
+ myPsiClass = psiClass;
+ }
+
+ public static ChainCompletionNewVariableLookupElement create(final PsiClass psiClass, final LookupElement calledMethods) {
+ final Project project = psiClass.getProject();
+ final String newVarName = chooseLongestName(JavaCodeStyleManager.getInstance(project).
+ suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, JavaPsiFacade.getElementFactory(project).createType(psiClass)));
+ return new ChainCompletionNewVariableLookupElement(psiClass, newVarName, calledMethods);
+ }
+
+ @Override
+ public void handleInsert(final InsertionContext context) {
+ final RangeMarker rangeMarker = context.getDocument().createRangeMarker(context.getStartOffset(), context.getStartOffset());
+ getDelegate().handleInsert(context);
+ final PsiFile file = context.getFile();
+ ((PsiJavaFile)file).importClass(myPsiClass);
+ final PsiElement caretElement = file.findElementAt(context.getEditor().getCaretModel().getOffset());
+ if (caretElement == null) {
+ log.error("element on caret position MUST BE not null");
+ return;
+ }
+ final PsiStatement statement = (PsiStatement) caretElement.getPrevSibling();
+ final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(statement, PsiCodeBlock.class);
+ if (codeBlock == null) {
+ log.error("code block MUST BE not null");
+ return;
+ }
+ final Project project = context.getProject();
+ final Ref<PsiElement> insertedStatementRef = Ref.create();
+ final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
+ context.commitDocument();
+ new WriteCommandAction.Simple(project, file) {
+ @Override
+ protected void run() throws Throwable {
+ final PsiStatement statementFromText = elementFactory.createStatementFromText(String.format("%s %s = null;", myPsiClass.getName(), myNewVarName), null);
+ insertedStatementRef.set(codeBlock.addBefore(statementFromText, statement));
+ }
+ }.execute();
+ final PsiLiteralExpression nullKeyword = findNull(insertedStatementRef.get());
+ PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(context.getDocument());
+ context.getDocument().insertString(rangeMarker.getStartOffset(), myNewVarName + ".");
+ context.commitDocument();
+ final int offset = nullKeyword.getTextOffset();
+ final int endOffset = offset + nullKeyword.getTextLength();
+ context.getEditor().getSelectionModel().setSelection(offset, endOffset);
+ context.getEditor().getCaretModel().moveToOffset(offset);
+ }
+
+ @NotNull
+ @Override
+ public String getLookupString() {
+ return getDelegate().getLookupString();
+ }
+
+ @Override
+ public void renderElement(final LookupElementPresentation presentation) {
+ super.renderElement(presentation);
+ presentation.setItemText(myNewVarName + "." + presentation.getItemText());
+ }
+
+ private static PsiLiteralExpression findNull(final PsiElement psiElement) {
+ final Collection<PsiLiteralExpression> literalExpressions = PsiTreeUtil.findChildrenOfType(psiElement, PsiLiteralExpression.class);
+ for (final PsiLiteralExpression literalExpression : literalExpressions) {
+ if (PsiKeyword.NULL.equals(literalExpression.getText())) {
+ return literalExpression;
+ }
+ }
+ throw new IllegalArgumentException();
+ }
+
+ private static String chooseLongestName(final SuggestedNameInfo suggestedNameInfo) {
+ final String[] names = suggestedNameInfo.names;
+ String longestWord = names[0];
+ int maxLength = longestWord.length();
+ for (int i = 1; i < names.length; i++) {
+ final int length = names[i].length();
+ if (length > maxLength) {
+ maxLength = length;
+ longestWord = names[i];
+ }
+ }
+ return longestWord;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java
new file mode 100644
index 0000000..ca30c13
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/WeightableChainLookupElement.java
@@ -0,0 +1,37 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.ChainRelevance;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementDecorator;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class WeightableChainLookupElement extends LookupElementDecorator<LookupElement> {
+ private final ChainRelevance myChainRelevance;
+
+ public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) {
+ super(delegate);
+ myChainRelevance = relevance;
+ }
+
+ public ChainRelevance getChainRelevance() {
+ return myChainRelevance;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/GetterLookupSubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/GetterLookupSubLookupElement.java
new file mode 100644
index 0000000..bb1cdf6
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/GetterLookupSubLookupElement.java
@@ -0,0 +1,50 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class GetterLookupSubLookupElement implements SubLookupElement {
+ private final String myVariableName;
+ private final String myMethodName;
+
+ public GetterLookupSubLookupElement(final String methodName) {
+ this(null, methodName);
+ }
+
+ public GetterLookupSubLookupElement(@Nullable final String variableName, final String methodName) {
+ myVariableName = variableName;
+ myMethodName = methodName;
+ }
+
+ @Override
+ public void doImport(final PsiJavaFile javaFile) {
+ }
+
+ @Override
+ public String getInsertString() {
+ final StringBuilder sb = new StringBuilder();
+ if (myVariableName != null) {
+ sb.append(myVariableName).append(".");
+ }
+ sb.append(myMethodName).append("()");
+ return sb.toString();
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/StaticMethodSubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/StaticMethodSubLookupElement.java
new file mode 100644
index 0000000..b96b8c2
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/StaticMethodSubLookupElement.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.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.ChainCompletionLookupElementUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiModifier;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class StaticMethodSubLookupElement implements SubLookupElement {
+
+ private final PsiMethod myMethod;
+ private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
+
+ public StaticMethodSubLookupElement(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
+ assert method.hasModifierProperty(PsiModifier.STATIC);
+ myReplaceElements = replaceElements;
+ myMethod = method;
+ }
+
+ @Override
+ public void doImport(final PsiJavaFile javaFile) {
+ final PsiClass containingClass = myMethod.getContainingClass();
+ if (containingClass != null) {
+ if (javaFile.findImportReferenceTo(containingClass) == null) {
+ javaFile.importClass(containingClass);
+ }
+ }
+ if (myReplaceElements != null) {
+ myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
+ @Override
+ public boolean execute(final SubLookupElement subLookupElement) {
+ subLookupElement.doImport(javaFile);
+ return false;
+ }
+ });
+ }
+ }
+
+ @Override
+ public String getInsertString() {
+ //noinspection ConstantConditions
+ return String.format("%s.%s(%s)", myMethod.getContainingClass().getName(), myMethod.getName(),
+ ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java
new file mode 100644
index 0000000..b13e7cd
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/SubLookupElement.java
@@ -0,0 +1,28 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public interface SubLookupElement {
+
+ void doImport(final PsiJavaFile javaFile);
+
+ String getInsertString();
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java
new file mode 100644
index 0000000..aa4cd03
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/completion/lookup/sub/VariableSubLookupElement.java
@@ -0,0 +1,40 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.completion.lookup.sub;
+
+import com.intellij.psi.PsiJavaFile;
+import com.intellij.psi.PsiVariable;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class VariableSubLookupElement implements SubLookupElement {
+
+ private final String myVarName;
+
+ public VariableSubLookupElement(final PsiVariable variable) {
+ myVarName = variable.getName();
+ }
+
+ @Override
+ public void doImport(final PsiJavaFile javaFile) {
+ }
+
+ @Override
+ public String getInsertString() {
+ return myVarName;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java
new file mode 100644
index 0000000..7d25398
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContext.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.CachedRelevantStaticMethodSearcher;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.FactoryMap;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ChainCompletionContext {
+ private final NotNullLazyValue<String> myContextMethodName = new NotNullLazyValue<String>() {
+ @NotNull
+ @Override
+ protected String compute() {
+ return myContextMethod.getName();
+ }
+ };
+ private final PsiMethod myContextMethod;
+ private final TargetType myTarget;
+ private final Set<String> myContainingClassQNames;
+ private final MultiMap<String, PsiVariable> myContextVars;
+ private final MultiMap<String, PsiMethod> myContainingClassGetters;
+ private final MultiMap<String, ContextRelevantVariableGetter> myContextVarsGetters;
+ private final Map<String, PsiVariable> myStringVars;
+ private final CachedRelevantStaticMethodSearcher myStaticMethodSearcher;
+ private final Set<String> myExcludedQNames;
+ private final GlobalSearchScope myResolveScope;
+ private final Project myProject;
+ private final PsiManager myPsiManager;
+ private final FactoryMap<MethodIncompleteSignature, PsiMethod[]> myNotDeprecatedMethodsResolver;
+
+ private final NotNullLazyValue<Set<String>> contextTypesQNames = new NotNullLazyValue<Set<String>>() {
+ @SuppressWarnings("unchecked")
+ @NotNull
+ @Override
+ protected Set<String> compute() {
+ return unionToHashSet(myContainingClassQNames, myContextVars.keySet(), myContainingClassGetters.keySet(),
+ myContextVarsGetters.keySet());
+ }
+ };
+
+ public Set<String> getExcludedQNames() {
+ return myExcludedQNames;
+ }
+
+ ChainCompletionContext(final PsiMethod contextMethod,
+ final TargetType target,
+ final Set<String> containingClassQNames,
+ final MultiMap<String, PsiVariable> contextVars,
+ final MultiMap<String, PsiMethod> containingClassGetters,
+ final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters,
+ final Map<String, PsiVariable> stringVars,
+ final Set<String> excludedQNames,
+ final Project project,
+ final GlobalSearchScope resolveScope) {
+ myContextMethod = contextMethod;
+ myTarget = target;
+ myContainingClassQNames = containingClassQNames;
+ myContextVars = contextVars;
+ myContainingClassGetters = containingClassGetters;
+ myContextVarsGetters = contextVarsGetters;
+ myStringVars = stringVars;
+ myExcludedQNames = excludedQNames;
+ myResolveScope = resolveScope;
+ myProject = project;
+ myPsiManager = PsiManager.getInstance(project);
+ myNotDeprecatedMethodsResolver = MethodIncompleteSignatureResolver.create(JavaPsiFacade.getInstance(project), resolveScope);
+ myStaticMethodSearcher = new CachedRelevantStaticMethodSearcher(project, resolveScope);
+ }
+
+ public PsiMethod getContextMethod() {
+ return myContextMethod;
+ }
+
+ public String getContextMethodName() {
+ return myContextMethodName.getValue();
+ }
+
+ public TargetType getTarget() {
+ return myTarget;
+ }
+
+ @Nullable
+ public PsiVariable findRelevantStringInContext(@Nullable final String stringParamName) {
+ if (stringParamName == null) {
+ return null;
+ }
+ for (final Map.Entry<String, PsiVariable> e : myStringVars.entrySet()) {
+ if (ChainCompletionContextStringUtil.isSimilar(e.getKey(), stringParamName)) {
+ return e.getValue();
+ }
+ }
+ return null;
+ }
+
+ public Set<String> getContainingClassQNames() {
+ return myContainingClassQNames;
+ }
+
+ public Collection<PsiVariable> getVariables(final String typeQName) {
+ return myContextVars.get(typeQName);
+ }
+
+ public Collection<PsiMethod> getContainingClassMethods(final String typeQName) {
+ return myContainingClassGetters.get(typeQName);
+ }
+
+ public Collection<ContextRelevantStaticMethod> getRelevantStaticMethods(final String typeQName, final int weight) {
+ return myStaticMethodSearcher.getRelevantStaticMethods(typeQName, weight, this);
+ }
+
+ public Collection<ContextRelevantVariableGetter> getRelevantVariablesGetters(final String typeQName) {
+ return myContextVarsGetters.get(typeQName);
+ }
+
+ public Collection<?> getContextRefElements(final String typeQName) {
+ final Collection<PsiVariable> variables = getVariables(typeQName);
+ final Collection<PsiMethod> containingClassMethods = getContainingClassMethods(typeQName);
+ final Collection<UserDataHolder> refElements = new ArrayList<UserDataHolder>(variables.size() + containingClassMethods.size());
+ refElements.addAll(variables);
+ refElements.addAll(containingClassMethods);
+ for (final ContextRelevantVariableGetter contextRelevantVariableGetter : getRelevantVariablesGetters(typeQName)) {
+ refElements.add(contextRelevantVariableGetter.createLookupElement());
+ }
+ return refElements;
+ }
+
+ public boolean contains(@Nullable final String typeQualifierName) {
+ return typeQualifierName != null && contextTypesQNames.getValue().contains(typeQualifierName);
+ }
+
+ public Set<String> getContextTypes() {
+ return contextTypesQNames.getValue();
+ }
+
+ public GlobalSearchScope getResolveScope() {
+ return myResolveScope;
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ public PsiManager getPsiManager() {
+ return myPsiManager;
+ }
+
+ @NotNull
+ public PsiMethod[] resolveNotDeprecated(final MethodIncompleteSignature methodIncompleteSignature) {
+ return myNotDeprecatedMethodsResolver.get(methodIncompleteSignature);
+ }
+
+ private static <T> HashSet<T> unionToHashSet(final Collection<T>... collections) {
+ final HashSet<T> res = new HashSet<T>();
+ for (final Collection<T> set : collections) {
+ res.addAll(set);
+ }
+ return res;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContextStringUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContextStringUtil.java
new file mode 100644
index 0000000..19466de
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ChainCompletionContextStringUtil.java
@@ -0,0 +1,51 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Batkovich
+ */
+class ChainCompletionContextStringUtil {
+
+ private ChainCompletionContextStringUtil(){}
+
+ private final static int COMMON_PART_MIN_LENGTH = 3;
+
+ public static boolean isSimilar(@NotNull final String varName,
+ @NotNull final String parameterName) {
+ final String sanitizedParamName = sanitizedToLowerCase(parameterName);
+ if (StringUtil.commonPrefix(varName, sanitizedParamName).length() >= COMMON_PART_MIN_LENGTH) {
+ return true;
+ }
+ final String suffix = StringUtil.commonSuffix(varName, sanitizedParamName);
+ return suffix.length() >= COMMON_PART_MIN_LENGTH;
+ }
+
+ @NotNull
+ public static String sanitizedToLowerCase(@NotNull final String name) {
+ final StringBuilder result = new StringBuilder();
+ for (int i = 0; i < name.length(); i++) {
+ final char ch = name.charAt(i);
+ if (Character.isLetter(ch)) {
+ result.append(Character.toLowerCase(ch));
+ }
+ }
+ return result.toString();
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextRelevantStaticMethod.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextRelevantStaticMethod.java
new file mode 100644
index 0000000..a10bf35
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextRelevantStaticMethod.java
@@ -0,0 +1,60 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.StaticMethodSubLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.VariableSubLookupElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+import gnu.trove.TIntObjectHashMap;
+import gnu.trove.TIntObjectProcedure;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ContextRelevantStaticMethod {
+ private final PsiMethod psiMethod;
+ @Nullable
+ private final TIntObjectHashMap<SubLookupElement> parameters;
+
+ public ContextRelevantStaticMethod(final PsiMethod psiMethod, @Nullable final TIntObjectHashMap<PsiVariable> parameters) {
+ this.psiMethod = psiMethod;
+ if (parameters == null) {
+ this.parameters = null;
+ } else {
+ this.parameters = new TIntObjectHashMap<SubLookupElement>(parameters.size());
+ parameters.forEachEntry(new TIntObjectProcedure<PsiVariable>() {
+ @SuppressWarnings("ConstantConditions")
+ @Override
+ public boolean execute(final int pos, final PsiVariable var) {
+ ContextRelevantStaticMethod.this.parameters.put(pos, new VariableSubLookupElement(var));
+ return false;
+ }
+ });
+ }
+ }
+
+ private SubLookupElement cachedLookupElement;
+
+ public SubLookupElement createLookupElement() {
+ if (cachedLookupElement == null) {
+ cachedLookupElement = new StaticMethodSubLookupElement(psiMethod, parameters);
+ }
+ return cachedLookupElement;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextRelevantVariableGetter.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextRelevantVariableGetter.java
new file mode 100644
index 0000000..601d263
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextRelevantVariableGetter.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 com.intellij.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.codeInsight.completion.JavaChainLookupElement;
+import com.intellij.codeInsight.completion.JavaMethodCallElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.GetterLookupSubLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.sub.SubLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.VariableLookupItem;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiVariable;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class ContextRelevantVariableGetter {
+ private final PsiVariable myVariable;
+ private final PsiMethod myMethod;
+
+ public ContextRelevantVariableGetter(final PsiVariable variable, final PsiMethod method) {
+ myVariable = variable;
+ myMethod = method;
+ }
+
+ public SubLookupElement createSubLookupElement() {
+ return new GetterLookupSubLookupElement(myVariable.getName(), myMethod.getName());
+ }
+
+ public LookupElement createLookupElement() {
+ return new JavaChainLookupElement(new VariableLookupItem(myVariable), new JavaMethodCallElement(myMethod));
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java
new file mode 100644
index 0000000..7b79ef7
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/ContextUtil.java
@@ -0,0 +1,258 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public final class ContextUtil {
+ @Nullable
+ public static ChainCompletionContext createContext(final @Nullable PsiType variableType,
+ final @Nullable String variableName,
+ final @Nullable PsiElement containingElement) {
+ if (variableType == null || containingElement == null) {
+ return null;
+ }
+
+ final TargetType target;
+ if (variableType instanceof PsiClassType) {
+ target = TargetType.create((PsiClassType)variableType);
+ }
+ else if (variableType instanceof PsiArrayType) {
+ target = TargetType.create((PsiArrayType)variableType);
+ }
+ else {
+ return null;
+ }
+ if (target == null) {
+ return null;
+ }
+
+ final PsiMethod method = PsiTreeUtil.getParentOfType(containingElement, PsiMethod.class);
+ if (method == null) {
+ return null;
+ }
+ final PsiClass aClass = method.getContainingClass();
+ if (aClass == null) {
+ return null;
+ }
+ final Set<String> containingClassQNames = resolveSupersNamesRecursively(aClass);
+
+ final List<PsiVariable> contextVars = new SmartList<PsiVariable>();
+ for (final PsiField field : aClass.getFields()) {
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass != null) {
+ if ((field.hasModifierProperty(PsiModifier.PUBLIC) ||
+ field.hasModifierProperty(PsiModifier.PROTECTED) ||
+ ((field.hasModifierProperty(PsiModifier.PRIVATE) || field.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) &&
+ aClass.isEquivalentTo(containingClass))) && !field.getName().equals(variableName)) {
+ contextVars.add(field);
+ }
+ }
+ }
+ Collections.addAll(contextVars, method.getParameterList().getParameters());
+
+ final PsiCodeBlock methodBody = method.getBody();
+ assert methodBody != null;
+ boolean processMethodTail = false;
+ final List<PsiElement> afterElements = new ArrayList<PsiElement>();
+ for (final PsiElement element : methodBody.getChildren()) {
+ if (element.isEquivalentTo(containingElement)) {
+ if (variableType instanceof PsiClassType) {
+ processMethodTail = true;
+ continue;
+ }
+ else {
+ break;
+ }
+ }
+ if (element instanceof PsiDeclarationStatement) {
+ if (processMethodTail) {
+ afterElements.add(element);
+ }
+ else {
+ for (final PsiElement declaredElement : ((PsiDeclarationStatement)element).getDeclaredElements()) {
+ if (declaredElement instanceof PsiLocalVariable &&
+ (variableName == null || !variableName.equals(((PsiLocalVariable)declaredElement).getName()))) {
+ contextVars.add((PsiVariable)declaredElement);
+ }
+ }
+ }
+ }
+ }
+
+ final Set<String> excludedQNames = processMethodTail
+ ? generateExcludedQNames(afterElements, ((PsiClassType)variableType).resolve(), variableName,
+ contextVars)
+ : Collections.<String>emptySet();
+
+ final List<PsiMethod> contextMethods = new ArrayList<PsiMethod>();
+ for (final PsiMethod psiMethod : aClass.getMethods()) {
+ if ((psiMethod.hasModifierProperty(PsiModifier.PROTECTED) || psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) &&
+ psiMethod.getParameterList().getParametersCount() == 0) {
+ contextMethods.add(psiMethod);
+ }
+ }
+
+ return create(method, target, contextVars, contextMethods, containingClassQNames, containingElement.getProject(),
+ containingElement.getResolveScope(), excludedQNames);
+ }
+
+ private static Set<String> generateExcludedQNames(final List<PsiElement> tailElements,
+ final @Nullable PsiClass psiClass,
+ final @Nullable String varName,
+ final List<PsiVariable> contextVars) {
+ if (psiClass == null) {
+ return Collections.emptySet();
+ }
+ final String classQName = psiClass.getQualifiedName();
+ if (classQName == null) {
+ return Collections.emptySet();
+ }
+
+ final Set<String> excludedQNames = new HashSet<String>();
+ if (!tailElements.isEmpty()) {
+ final Set<String> contextVarTypes = new HashSet<String>();
+ final Map<String, PsiVariable> contextVarNamesToVar = new HashMap<String, PsiVariable>();
+ for (final PsiVariable var : contextVars) {
+ contextVarTypes.add(var.getType().getCanonicalText());
+ contextVarNamesToVar.put(var.getName(), var);
+ }
+ for (final PsiElement element : tailElements) {
+ final Collection<PsiMethodCallExpression> methodCallExpressions =
+ PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression.class);
+ for (final PsiMethodCallExpression methodCallExpression : methodCallExpressions) {
+ final PsiExpressionList args = methodCallExpression.getArgumentList();
+ final PsiMethod resolvedMethod = methodCallExpression.resolveMethod();
+ if (resolvedMethod != null) {
+ final PsiType returnType = resolvedMethod.getReturnType();
+ if (returnType != null) {
+ final String returnTypeAsString = returnType.getCanonicalText();
+ for (final PsiExpression expression : args.getExpressions()) {
+ final String qVarName = expression.getText();
+ if (qVarName != null) {
+ if (contextVarNamesToVar.containsKey(qVarName) || qVarName.equals(varName)) {
+ excludedQNames.add(returnTypeAsString);
+ }
+ }
+ }
+ if (!contextVarTypes.contains(returnTypeAsString)) {
+ excludedQNames.add(returnTypeAsString);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return excludedQNames;
+ }
+
+ @Nullable
+ private static ChainCompletionContext create(final PsiMethod contextMethod,
+ final TargetType target,
+ final List<PsiVariable> contextVars,
+ final List<PsiMethod> contextMethods,
+ final Set<String> containingClassQNames,
+ final Project project,
+ final GlobalSearchScope resolveScope,
+ final Set<String> excludedQNames) {
+ final MultiMap<String, PsiVariable> classQNameToVariable = new MultiMap<String, PsiVariable>();
+ final MultiMap<String, PsiMethod> containingClassGetters = new MultiMap<String, PsiMethod>();
+ final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters = new MultiMap<String, ContextRelevantVariableGetter>();
+ final Map<String, PsiVariable> stringVars = new HashMap<String, PsiVariable>();
+
+ for (final PsiMethod method : contextMethods) {
+ final PsiType returnType = method.getReturnType();
+ if (returnType != null) {
+ final String returnTypeQName = returnType.getCanonicalText();
+ containingClassGetters.putValue(returnTypeQName, method);
+ }
+ }
+
+ for (final PsiVariable var : contextVars) {
+ final PsiType type = var.getType();
+ final Set<String> classQNames = new HashSet<String>();
+ if (type instanceof PsiClassType) {
+ if (JAVA_LANG_STRING_SHORT_NAME.equals(((PsiClassType)type).getClassName())) {
+ final String varName = var.getName();
+ if (varName != null) {
+ stringVars.put(ChainCompletionContextStringUtil.sanitizedToLowerCase(varName), var);
+ continue;
+ }
+ }
+
+ final PsiClass aClass = ((PsiClassType)type).resolve();
+ if (aClass != null) {
+ final String classQName = type.getCanonicalText();
+ if (!target.getClassQName().equals(classQName)) {
+ classQNames.add(classQName);
+ classQNames.addAll(resolveSupersNamesRecursively(aClass));
+ for (final PsiMethod method : aClass.getAllMethods()) {
+ if (method.getParameterList().getParametersCount() == 0 && method.getName().startsWith("get")) {
+ final PsiType returnType = method.getReturnType();
+ if (returnType != null) {
+ final String getterReturnTypeQName = returnType.getCanonicalText();
+ contextVarsGetters.putValue(getterReturnTypeQName, new ContextRelevantVariableGetter(var, method));
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ final String classQName = type.getCanonicalText();
+ classQNames.add(classQName);
+ }
+ for (final String qName : classQNames) {
+ classQNameToVariable.putValue(qName, var);
+ }
+ }
+ return new ChainCompletionContext(contextMethod, target, containingClassQNames, classQNameToVariable, containingClassGetters,
+ contextVarsGetters, stringVars, excludedQNames, project, resolveScope);
+ }
+
+ @NotNull
+ private static Set<String> resolveSupersNamesRecursively(@Nullable final PsiClass psiClass) {
+ final Set<String> result = new HashSet<String>();
+ if (psiClass != null) {
+ for (final PsiClass superClass : psiClass.getSupers()) {
+ final String qualifiedName = superClass.getQualifiedName();
+ if (!CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) {
+ if (qualifiedName != null) {
+ result.add(qualifiedName);
+ }
+ result.addAll(resolveSupersNamesRecursively(superClass));
+ }
+ }
+ }
+ return result;
+ }
+
+ private final static String JAVA_LANG_STRING_SHORT_NAME = StringUtil.getShortName(CommonClassNames.JAVA_LANG_STRING);
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java
new file mode 100644
index 0000000..5a9c257
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/MethodIncompleteSignatureResolver.java
@@ -0,0 +1,89 @@
+/*
+ * 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.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.FactoryMap;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Dmitry Batkovich
+ */
+final class MethodIncompleteSignatureResolver {
+ private MethodIncompleteSignatureResolver() {}
+
+ public static FactoryMap<MethodIncompleteSignature, PsiMethod[]> create(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
+ return new FactoryMap<MethodIncompleteSignature, PsiMethod[]>() {
+ @Nullable
+ @Override
+ protected PsiMethod[] create(final MethodIncompleteSignature signature) {
+ return resolveNotDeprecated(signature, javaPsiFacade, scope);
+ }
+ };
+ }
+
+ private static PsiMethod[] resolveNotDeprecated(final MethodIncompleteSignature signature,
+ final JavaPsiFacade javaPsiFacade,
+ final GlobalSearchScope scope) {
+ if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(signature.getName())) {
+ return PsiMethod.EMPTY_ARRAY;
+ }
+ final PsiClass aClass = javaPsiFacade.findClass(signature.getOwner(), scope);
+ if (aClass == null) {
+ return PsiMethod.EMPTY_ARRAY;
+ }
+ final PsiMethod[] methods = aClass.findMethodsByName(signature.getName(), true);
+ final List<PsiMethod> filtered = new ArrayList<PsiMethod>(methods.length);
+ for (final PsiMethod method : methods) {
+ if (method.hasModifierProperty(PsiModifier.STATIC) == signature.isStatic()) {
+ final PsiType returnType = method.getReturnType();
+ if (returnType != null) {
+ if (returnType instanceof PsiClassType) {
+ final PsiClass resolved = ((PsiClassType)returnType).resolve();
+ if (resolved == null) {
+ continue;
+ }
+ final String qualifiedName = resolved.getQualifiedName();
+ if (qualifiedName == null) {
+ continue;
+ }
+ if (qualifiedName.equals(signature.getReturnType())) {
+ filtered.add(method);
+ }
+ } else if (returnType.equalsToText(signature.getReturnType())) {
+ filtered.add(method);
+ }
+ }
+ }
+ }
+ if (filtered.size() > 1) {
+ Collections.sort(filtered, new Comparator<PsiMethod>() {
+ @Override
+ public int compare(final PsiMethod o1, final PsiMethod o2) {
+ return o1.getParameterList().getParametersCount() - o2.getParameterList().getParametersCount();
+ }
+ });
+ }
+ return filtered.toArray(new PsiMethod[filtered.size()]);
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/TargetType.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/TargetType.java
new file mode 100644
index 0000000..2d983f1
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/chainsSearch/context/TargetType.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 com.intellij.compiler.classFilesIndex.chainsSearch.context;
+
+import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class TargetType {
+
+ private final String myClassQName;
+ private final boolean myArray;
+ private final PsiType myPsiType;
+
+ public TargetType(final String classQName,
+ final boolean isArray,
+ final PsiType targetType) {
+ myClassQName = classQName;
+ myArray = isArray;
+ myPsiType = targetType;
+ }
+
+ public String getClassQName() {
+ return myClassQName;
+ }
+
+ public boolean isArray() {
+ return myArray;
+ }
+
+ public PsiType getPsiType() {
+ return myPsiType;
+ }
+
+ @Nullable
+ public static TargetType create(final PsiArrayType arrayType) {
+ PsiType currentComponentType = arrayType.getComponentType();
+ while (currentComponentType instanceof PsiArrayType) {
+ currentComponentType = ((PsiArrayType)currentComponentType).getComponentType();
+ }
+ if (!(currentComponentType instanceof PsiClassType)) {
+ return null;
+ }
+ final String targetQName = arrayType.getCanonicalText();
+ return new TargetType(targetQName, true, arrayType);
+ }
+
+ @Nullable
+ public static TargetType create(final PsiClassType classType) {
+ final PsiClassType.ClassResolveResult resolvedGenerics = classType.resolveGenerics();
+ final PsiClass resolvedClass = resolvedGenerics.getElement();
+ if (resolvedClass == null) {
+ return null;
+ }
+ final String classQName = resolvedClass.getQualifiedName();
+ if (classQName == null) {
+ return null;
+ }
+ if (resolvedClass.hasTypeParameters()) {
+ return null;
+ }
+ return new TargetType(classQName, false, classType);
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexConfigure.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexConfigure.java
new file mode 100644
index 0000000..e64dd1b
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexConfigure.java
@@ -0,0 +1,53 @@
+/*
+ * 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.compiler.classFilesIndex.impl;
+
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexConfigure;
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexReaderBase;
+import com.intellij.openapi.project.Project;
+import gnu.trove.TObjectIntHashMap;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexerFactory;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexer;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsUsageIndexConfigure extends ClassFilesIndexConfigure<String, TObjectIntHashMap<MethodIncompleteSignature>> {
+
+ public static final MethodsUsageIndexConfigure INSTANCE = new MethodsUsageIndexConfigure();
+
+ @Override
+ public String getIndexCanonicalName() {
+ return MethodsUsageIndexer.METHODS_USAGE_INDEX_CANONICAL_NAME;
+ }
+
+ @Override
+ public int getIndexVersion() {
+ return 0;
+ }
+
+ @Override
+ public Class<? extends ClassFileIndexerFactory> getIndexerBuilderClass() {
+ return MethodsUsageIndexerFactory.class;
+ }
+
+ @Override
+ public ClassFilesIndexReaderBase<String, TObjectIntHashMap<MethodIncompleteSignature>> createIndexReader(final Project project) {
+ return new MethodsUsageIndexReader(project, getIndexCanonicalName(), getIndexVersion());
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java
new file mode 100644
index 0000000..3b3adcd
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/MethodsUsageIndexReader.java
@@ -0,0 +1,81 @@
+/*
+ * 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.compiler.classFilesIndex.impl;
+
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeaturesHolder;
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexReaderBase;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import gnu.trove.TObjectIntHashMap;
+import gnu.trove.TObjectIntProcedure;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.classFilesIndex.TObjectIntHashMapExternalizer;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+
+import java.util.Collection;
+import java.util.TreeSet;
+
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class MethodsUsageIndexReader extends ClassFilesIndexReaderBase<String, TObjectIntHashMap<MethodIncompleteSignature>> {
+
+ public static MethodsUsageIndexReader getInstance(final Project project) {
+ final MethodsUsageIndexReader instance =
+ ClassFilesIndexFeaturesHolder.getInstance(project).getAvailableIndexReader(MethodsUsageIndexReader.class);
+ if (instance == null) {
+ throw new RuntimeException("couldn't get instance");
+ }
+ return instance;
+ }
+
+ public MethodsUsageIndexReader(final Project project, final String canonicalIndexName, final int version) {
+ //noinspection ConstantConditions
+ super(new EnumeratorStringDescriptor(),
+ new TObjectIntHashMapExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createDataExternalizer()),
+ canonicalIndexName, version, project);
+ }
+
+ @NotNull
+ public TreeSet<UsageIndexValue> getMethods(final String key) {
+ assert myIndex != null;
+ final Collection<TObjectIntHashMap<MethodIncompleteSignature>> unReducedValues = myIndex.getData(key);
+
+ final TObjectIntHashMap<MethodIncompleteSignature> rawValues = new TObjectIntHashMap<MethodIncompleteSignature>();
+ for (final TObjectIntHashMap<MethodIncompleteSignature> unReducedValue : unReducedValues) {
+ unReducedValue.forEachEntry(new TObjectIntProcedure<MethodIncompleteSignature>() {
+ @Override
+ public boolean execute(final MethodIncompleteSignature sign, final int occurrences) {
+ if (!rawValues.adjustValue(sign, occurrences)) {
+ rawValues.put(sign, occurrences);
+ }
+ return true;
+ }
+ });
+ }
+
+ final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
+ rawValues.forEachEntry(new TObjectIntProcedure<MethodIncompleteSignature>() {
+ @Override
+ public boolean execute(MethodIncompleteSignature sign, int occurrences) {
+ values.add(new UsageIndexValue(sign.toExternalRepresentation(), occurrences));
+ return true;
+ }
+ });
+ return values;
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/UsageIndexValue.java b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/UsageIndexValue.java
new file mode 100644
index 0000000..e04f64e
--- /dev/null
+++ b/java/compiler/impl/src/com/intellij/compiler/classFilesIndex/impl/UsageIndexValue.java
@@ -0,0 +1,64 @@
+/*
+ * 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.compiler.classFilesIndex.impl;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.classFilesIndex.indexer.impl.MethodIncompleteSignature;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class UsageIndexValue implements Comparable<UsageIndexValue> {
+ private final int myOccurrences;
+ private final MethodIncompleteSignature myMethodIncompleteSignature;
+
+ public UsageIndexValue(final MethodIncompleteSignature signature, final int occurrences) {
+ myOccurrences = occurrences;
+ myMethodIncompleteSignature = signature;
+ }
+
+ public int getOccurrences() {
+ return myOccurrences;
+ }
+
+ public MethodIncompleteSignature getMethodIncompleteSignature() {
+ return myMethodIncompleteSignature;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final UsageIndexValue that = (UsageIndexValue)o;
+
+ return myOccurrences == that.myOccurrences && myMethodIncompleteSignature.equals(that.myMethodIncompleteSignature);
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myOccurrences;
+ result = 31 * result + myMethodIncompleteSignature.hashCode();
+ return result;
+ }
+
+ @Override
+ public int compareTo(@NotNull final UsageIndexValue that) {
+ final int sub = -myOccurrences + that.myOccurrences;
+ if (sub != 0) return sub;
+ return MethodIncompleteSignature.COMPARATOR.compare(myMethodIncompleteSignature, that.myMethodIncompleteSignature);
+ }
+}
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
index 70b1d5b..a89c076 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/CompileDriver.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -784,7 +784,7 @@
myProject, "You are about to rebuild the whole project.\nRun 'Make Project' instead?", "Confirm Project Rebuild",
"Make", "Rebuild", Messages.getQuestionIcon()
);
- if (rv == 0 /*yes, please, do run make*/) {
+ if (rv == Messages.OK /*yes, please, do run make*/) {
startup(scope, false, false, callback, null, checkCachesVersion);
return;
}
diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/FileProcessingCompilerAdapterTask.java b/java/compiler/impl/src/com/intellij/compiler/impl/FileProcessingCompilerAdapterTask.java
index f3bb520..8ed8e88 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/FileProcessingCompilerAdapterTask.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/FileProcessingCompilerAdapterTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -21,6 +21,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -32,14 +33,14 @@
import java.util.List;
/**
- * This is an adapter for running any FileProcessingCompiler as a compiler task
- *
+ * This is an adapter for running any FileProcessingCompiler as a compiler task.
*
* @author Eugene Zhuravlev
* Date: 9/5/12
*/
-public class FileProcessingCompilerAdapterTask implements CompileTask{
+public class FileProcessingCompilerAdapterTask implements CompileTask {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.FileProcessingCompilerAdapterTask");
+
private final FileProcessingCompiler myCompiler;
public FileProcessingCompilerAdapterTask(FileProcessingCompiler compiler) {
@@ -56,15 +57,15 @@
if (!CompilerWorkspaceConfiguration.getInstance(project).useOutOfProcessBuild()) {
return true;
}
+
try {
final FileProcessingCompiler.ProcessingItem[] items = myCompiler.getProcessingItems(context);
if (items.length == 0) {
return true;
}
+
final List<FileProcessingCompiler.ProcessingItem> toProcess = new ArrayList<FileProcessingCompiler.ProcessingItem>();
final Ref<IOException> ex = new Ref<IOException>(null);
-
-
final FileProcessingCompilerStateCache cache = getCache(context);
final boolean isMake = context.isMake();
DumbService.getInstance(project).runReadActionInSmartMode(new Runnable() {
@@ -76,7 +77,7 @@
if (isMake && cache.getTimestamp(url) == file.getTimeStamp()) {
final ValidityState state = cache.getExtState(url);
final ValidityState itemState = item.getValidityState();
- if (state != null ? state.equalsTo(itemState) : itemState == null) {
+ if (Comparing.equal(state, itemState)) {
continue;
}
}
@@ -89,16 +90,17 @@
}
});
- if (ex.get() != null) {
- throw ex.get();
+ IOException exception = ex.get();
+ if (exception != null) {
+ throw exception;
}
if (toProcess.isEmpty()) {
return true;
}
- final FileProcessingCompiler.ProcessingItem[] processed = myCompiler.process(context, toProcess.toArray(new FileProcessingCompiler.ProcessingItem[toProcess.size()]));
-
+ final FileProcessingCompiler.ProcessingItem[] array = toProcess.toArray(new FileProcessingCompiler.ProcessingItem[toProcess.size()]);
+ final FileProcessingCompiler.ProcessingItem[] processed = myCompiler.process(context, array);
if (processed.length == 0) {
return true;
}
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 fdd1587..88f3521 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java
@@ -89,6 +89,7 @@
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)]
@@ -195,6 +196,7 @@
return;
}
FileUtil.createIfDoesntExist(CompilerPaths.getRebuildMarkerFile(project));
+ --myWatchedProjectsCount;
// cleanup internal structures to free memory
mySourcesToRecompile.remove(projectId);
myOutputsToDelete.remove(projectId);
@@ -216,6 +218,7 @@
public void watchProject(Project project) {
synchronized (myDataLock) {
mySuspendedProjects.remove(getProjectId(project));
+ ++myWatchedProjectsCount;
}
}
@@ -1473,6 +1476,7 @@
}
public void beforeFileDeletion(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();
@@ -1612,6 +1616,7 @@
}
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/javaCompiler/ModuleChunk.java b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java
index 864e4f8..513c5da 100644
--- a/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java
+++ b/java/compiler/impl/src/com/intellij/compiler/impl/javaCompiler/ModuleChunk.java
@@ -19,7 +19,7 @@
import com.intellij.compiler.CompilerConfigurationImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.ex.CompileContextEx;
-import com.intellij.openapi.module.LanguageLevelUtil;
+import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
@@ -304,7 +304,7 @@
//the check for equal language levels is done elsewhere
public LanguageLevel getLanguageLevel() {
- return LanguageLevelUtil.getEffectiveLanguageLevel(getNodes().iterator().next());
+ return EffectiveLanguageLevelUtil.getEffectiveLanguageLevel(getNodes().iterator().next());
}
public Project getProject() {
diff --git a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java
index f66e2a3..b772853 100644
--- a/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.java
+++ b/java/compiler/impl/src/com/intellij/compiler/options/CompilerUIConfigurable.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.
@@ -35,6 +35,7 @@
import com.intellij.ui.components.JBLabel;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtilRt;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -91,12 +92,12 @@
public CompilerUIConfigurable(@NotNull final Project project) {
myProject = project;
- myPatternLegendLabel.setText("<html><body>" +
+ myPatternLegendLabel.setText(XmlStringUtil.wrapInHtml(
"Use <b>;</b> to separate patterns and <b>!</b> to negate a pattern. " +
"Accepted wildcards: <b>?</b> — exactly one symbol; <b>*</b> — zero or more symbols; " +
"<b>/</b> — path separator; <b>/**/</b> — any number of directories; " +
- "<i><dir_name></i>:<i><pattern></i> — restrict to source roots with the specified name" +
- "</body></html>");
+ "<i><dir_name></i>:<i><pattern></i> — restrict to source roots with the specified name"
+ ));
myPatternLegendLabel.setForeground(new JBColor(Gray._50, Gray._130));
tweakControls(project);
}
diff --git a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java
index 8a8fcbb..d37e7c2 100644
--- a/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java
+++ b/java/compiler/impl/src/com/intellij/compiler/progress/CompilerTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -536,7 +536,7 @@
CompilerBundle.message("compiler.running.dialog.title"),
Messages.getQuestionIcon()
);
- if (result != 0) {
+ if (result != Messages.OK) {
return false; // veto closing
}
myUserAcceptedCancel = true;
@@ -589,7 +589,7 @@
CompilerBundle.message("compiler.running.dialog.title"),
Messages.getQuestionIcon()
);
- if (result != 0) {
+ if (result != Messages.OK) {
event.consume(); // veto closing
}
myUserAcceptedCancel = true;
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 49a0d9d..13d9be0 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java
@@ -902,7 +902,8 @@
cmdLine.addParameter("-D" + CharsetToolkit.FILE_ENCODING_PROPERTY + "=" + mySystemCharset.name());
}
cmdLine.addParameter("-D" + JpsGlobalLoader.FILE_TYPES_COMPONENT_NAME_KEY + "=" + FileTypeManagerImpl.getFileTypeComponentName());
- for (String name : new String[]{"user.language", "user.country", "user.region", PathManager.PROPERTY_HOME_PATH}) {
+ for (String name : new String[]{"user.language", "user.country", "user.region", PathManager.PROPERTY_HOME_PATH,
+ PathManager.PROPERTY_CONFIG_PATH, PathManager.PROPERTY_PLUGINS_PATH, PathManager.PROPERTY_PATHS_SELECTOR}) {
final String value = System.getProperty(name);
if (value != null) {
cmdLine.addParameter("-D" + name + "=" + value);
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java
index e0a7ffa..a6ba4a3 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildMessageDispatcher.java
@@ -39,7 +39,7 @@
class BuildMessageDispatcher extends SimpleChannelInboundHandler<CmdlineRemoteProto.Message> {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.server.BuildMessageDispatcher");
- private static final AttributeKey<SessionData> SESSION_DATA = new AttributeKey<SessionData>("BuildMessageDispatcher.sessionData");
+ private static final AttributeKey<SessionData> SESSION_DATA = AttributeKey.valueOf("BuildMessageDispatcher.sessionData");
private final Map<UUID, SessionData> myMessageHandlers = new ConcurrentHashMap<UUID, SessionData>(16, 0.75f, 1);
private final Set<UUID> myCanceledSessions = new ConcurrentHashSet<UUID>();
@@ -80,7 +80,7 @@
@Override
- protected void channelRead0(ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
+ protected void messageReceived(ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
SessionData sessionData = context.attr(SESSION_DATA).get();
UUID sessionId;
diff --git a/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java b/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java
index ef9d84b..80c2aaf 100644
--- a/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java
+++ b/java/compiler/impl/src/com/intellij/compiler/server/DefaultMessageHandler.java
@@ -19,6 +19,9 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
+import com.intellij.openapi.progress.util.ReadTask;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
@@ -37,6 +40,7 @@
import org.jetbrains.jps.api.CmdlineRemoteProto;
import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* @author Eugene Zhuravlev
@@ -81,12 +85,38 @@
protected abstract void handleBuildEvent(UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.BuildEvent event);
- private void handleConstantSearchTask(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
+ private void handleConstantSearchTask(final Channel channel, final UUID sessionId, final CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
+ while (true) {
+ final AtomicBoolean canceled = new AtomicBoolean(false);
+ DumbService.getInstance(myProject).waitForSmartMode();
+ ProgressIndicatorUtils.runWithWriteActionPriority(new ReadTask() {
+ @Override
+ public void computeInReadAction(@NotNull ProgressIndicator indicator) {
+ if (DumbService.isDumb(myProject)) {
+ canceled.set(true);
+ return;
+ }
+
+ doHandleConstantSearchTask(channel, sessionId, task);
+ }
+
+ @Override
+ public void onCanceled(@NotNull ProgressIndicator indicator) {
+ canceled.set(true);
+ }
+ });
+ if (!canceled.get()) {
+ break;
+ }
+ }
+ }
+ private void doHandleConstantSearchTask(Channel channel, UUID sessionId, CmdlineRemoteProto.Message.BuilderMessage.ConstantSearchTask task) {
final String ownerClassName = task.getOwnerClassName();
final String fieldName = task.getFieldName();
final int accessFlags = task.getAccessFlags();
final boolean accessChanged = task.getIsAccessChanged();
final boolean isRemoved = task.getIsFieldRemoved();
+ boolean canceled = false;
final Ref<Boolean> isSuccess = Ref.create(Boolean.TRUE);
final Set<String> affectedPaths = Collections.synchronizedSet(new HashSet<String>()); // PsiSearchHelper runs multiple threads
try {
@@ -167,23 +197,38 @@
}
}
}
- finally {
- final CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.Builder builder = CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.newBuilder();
- builder.setOwnerClassName(ownerClassName);
- builder.setFieldName(fieldName);
- if (isSuccess.get()) {
- builder.setIsSuccess(true);
- builder.addAllPath(affectedPaths);
- LOG.debug("Constant search task: " + affectedPaths.size() + " affected files found");
- }
- else {
- builder.setIsSuccess(false);
- LOG.debug("Constant search task: unsuccessful");
- }
- channel.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineRemoteProto.Message.ControllerMessage.newBuilder().setType(
- CmdlineRemoteProto.Message.ControllerMessage.Type.CONSTANT_SEARCH_RESULT).setConstantSearchResult(builder.build()).build()
- ));
+ catch (ProcessCanceledException e) {
+ canceled = true;
+ throw e;
}
+ finally {
+ if (!canceled) {
+ notifyConstantSearchFinished(channel, sessionId, ownerClassName, fieldName, isSuccess, affectedPaths);
+ }
+ }
+ }
+
+ private static void notifyConstantSearchFinished(Channel channel,
+ UUID sessionId,
+ String ownerClassName,
+ String fieldName,
+ Ref<Boolean> isSuccess, Set<String> affectedPaths) {
+ final CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.Builder builder =
+ CmdlineRemoteProto.Message.ControllerMessage.ConstantSearchResult.newBuilder();
+ builder.setOwnerClassName(ownerClassName);
+ builder.setFieldName(fieldName);
+ if (isSuccess.get()) {
+ builder.setIsSuccess(true);
+ builder.addAllPath(affectedPaths);
+ LOG.debug("Constant search task: " + affectedPaths.size() + " affected files found");
+ }
+ else {
+ builder.setIsSuccess(false);
+ LOG.debug("Constant search task: unsuccessful");
+ }
+ channel.writeAndFlush(CmdlineProtoUtil.toMessage(sessionId, CmdlineRemoteProto.Message.ControllerMessage.newBuilder().setType(
+ CmdlineRemoteProto.Message.ControllerMessage.Type.CONSTANT_SEARCH_RESULT).setConstantSearchResult(builder.build()).build()
+ ));
}
private boolean isDumbMode() {
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 076e7e0..2c06c2f 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
@@ -127,7 +127,11 @@
return extraDirFile;
}
}
- return PluginPathManager.getPluginHome(pluginDirName);
+ File pluginHome = PluginPathManager.getPluginHome(pluginDirName);
+ if (!pluginHome.isDirectory() && StringUtil.isCapitalized(pluginDirName)) {
+ pluginHome = PluginPathManager.getPluginHome(StringUtil.decapitalize(pluginDirName));
+ }
+ return pluginHome.isDirectory() ? pluginHome : null;
}
private static List<String> getDynamicClasspath(Project project) {
diff --git a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java
index a0ab466..0c2a151 100644
--- a/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java
+++ b/java/compiler/impl/src/com/intellij/packaging/impl/compiler/ArtifactCompilerUtil.java
@@ -40,7 +40,6 @@
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
-import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.api.CmdlineRemoteProto.Message.ControllerMessage.ParametersMessage.TargetTypeBuildScope;
@@ -49,7 +48,10 @@
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -147,12 +149,7 @@
}
public static MultiMap<String, Artifact> createOutputToArtifactMap(final Project project) {
- final MultiMap<String, Artifact> result = new MultiMap<String, Artifact>() {
- @Override
- protected Map<String, Collection<Artifact>> createMap() {
- return new THashMap<String, Collection<Artifact>>(FileUtil.PATH_HASHING_STRATEGY);
- }
- };
+ final MultiMap<String, Artifact> result = MultiMap.create(FileUtil.PATH_HASHING_STRATEGY);
new ReadAction() {
protected void run(final Result r) {
for (Artifact artifact : ArtifactManager.getInstance(project).getArtifacts()) {
diff --git a/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java b/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java
index cf81ca4..40170c9 100644
--- a/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java
+++ b/java/compiler/impl/testSrc/com/intellij/compiler/BaseCompilerTestCase.java
@@ -40,9 +40,7 @@
import javax.swing.*;
import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
/**
* @author nik
@@ -242,6 +240,13 @@
final Ref<CompilationLog> result = Ref.create(null);
final Semaphore semaphore = new Semaphore();
semaphore.down();
+ final List<String> generatedFilePaths = new ArrayList<String>();
+ getCompilerManager().addCompilationStatusListener(new CompilationStatusAdapter() {
+ @Override
+ public void fileGenerated(String outputRoot, String relativePath) {
+ generatedFilePaths.add(relativePath);
+ }
+ }, myTestRootDisposable);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
@@ -257,6 +262,7 @@
ExitStatus status = CompileDriver.getExternalBuildExitStatus(compileContext);
result.set(new CompilationLog(status == ExitStatus.UP_TO_DATE,
CompilerManagerImpl.getPathsToRecompile(), CompilerManagerImpl.getPathsToDelete(),
+ generatedFilePaths,
compileContext.getMessages(CompilerMessageCategory.ERROR),
compileContext.getMessages(CompilerMessageCategory.WARNING)));
}
@@ -421,16 +427,19 @@
protected class CompilationLog {
private final Set<String> myRecompiledPaths;
private final Set<String> myDeletedPaths;
+ private final Set<String> myGeneratedPaths;
private final boolean myExternalBuildUpToDate;
private final CompilerMessage[] myErrors;
private final CompilerMessage[] myWarnings;
- public CompilationLog(boolean externalBuildUpToDate, String[] recompiledPaths, String[] deletedPaths, CompilerMessage[] errors, CompilerMessage[] warnings) {
+ public CompilationLog(boolean externalBuildUpToDate, String[] recompiledPaths, String[] deletedPaths, List<String> generatedFilePaths,
+ CompilerMessage[] errors, CompilerMessage[] warnings) {
myExternalBuildUpToDate = externalBuildUpToDate;
myErrors = errors;
myWarnings = warnings;
myRecompiledPaths = getRelativePaths(recompiledPaths);
myDeletedPaths = getRelativePaths(deletedPaths);
+ myGeneratedPaths = new THashSet<String>(generatedFilePaths, FileUtil.PATH_HASHING_STRATEGY);
}
public void assertUpToDate() {
@@ -448,6 +457,10 @@
checkDeleted();
}
+ public void assertGenerated(String... expected) {
+ assertSet("generated", myGeneratedPaths, expected);
+ }
+
public void assertDeleted(String... expected) {
checkRecompiled();
checkDeleted(expected);
@@ -459,10 +472,12 @@
}
private void checkRecompiled(String... expected) {
+ if (useExternalCompiler()) return;
assertSet("recompiled", myRecompiledPaths, expected);
}
private void checkDeleted(String... expected) {
+ if (useExternalCompiler()) return;
assertSet("deleted", myDeletedPaths, expected);
}
@@ -475,7 +490,6 @@
}
private void assertSet(String name, Set<String> actual, String[] expected) {
- if (useExternalCompiler()) return;
for (String path : expected) {
if (!actual.remove(path)) {
Assert.fail("'" + path + "' is not " + name + ". " + name + ": " + new HashSet<String>(actual));
diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java
index eac8c80..ec70d82 100644
--- a/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java
+++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/CompilerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import com.intellij.openapi.projectRoots.Sdk;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -29,8 +30,12 @@
* Date: Sep 9, 2005
*/
public class CompilerBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.CompilerBundle";
private CompilerBundle() {
@@ -40,13 +45,8 @@
return message("javac.error.jdk.home.missing", jdk.getName(), jdk.getHomePath());
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/java/compiler/openapi/src/com/intellij/openapi/compiler/util/InspectionValidator.java b/java/compiler/openapi/src/com/intellij/openapi/compiler/util/InspectionValidator.java
index 64088c8..6fefedb 100644
--- a/java/compiler/openapi/src/com/intellij/openapi/compiler/util/InspectionValidator.java
+++ b/java/compiler/openapi/src/com/intellij/openapi/compiler/util/InspectionValidator.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.
diff --git a/java/debugger/impl/debugger-impl.iml b/java/debugger/impl/debugger-impl.iml
index 8b9d265..bb86d4e 100644
--- a/java/debugger/impl/debugger-impl.iml
+++ b/java/debugger/impl/debugger-impl.iml
@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="java-runtime" />
<orderEntry type="module" module-name="jsp-openapi" />
<orderEntry type="module" module-name="java-impl" />
+ <orderEntry type="module" module-name="platform-impl" />
</component>
<component name="copyright">
<Base>
diff --git a/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java b/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java
index df0ff53d..9ce095c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/InstanceFilter.java
@@ -33,6 +33,9 @@
public long ID = 0;
public boolean ENABLED = true;
+ public InstanceFilter() {
+ }
+
protected InstanceFilter(long ID, boolean ENABLED) {
this.ID = ID;
this.ENABLED = ENABLED;
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/AddToWatchActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/AddToWatchActionHandler.java
index 5e84000..a93bf81 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/AddToWatchActionHandler.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/AddToWatchActionHandler.java
@@ -28,14 +28,12 @@
import com.intellij.debugger.impl.DebuggerSession;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.ui.DebuggerPanelsManager;
-import com.intellij.debugger.ui.impl.MainWatchPanel;
-import com.intellij.debugger.ui.impl.VariablesPanel;
-import com.intellij.debugger.ui.impl.WatchDebuggerTree;
+import com.intellij.debugger.ui.impl.*;
import com.intellij.debugger.ui.impl.watch.*;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -46,10 +44,13 @@
public class AddToWatchActionHandler extends DebuggerActionHandler {
@Override
public boolean isEnabled(@NotNull Project project, AnActionEvent event) {
- DebuggerTreeNodeImpl[] selectedNodes = DebuggerAction.getSelectedNodes(event.getDataContext());
+ DataContext context = event.getDataContext();
+ DebuggerTreeNodeImpl[] selectedNodes = DebuggerAction.getSelectedNodes(context);
boolean enabled = false;
if (selectedNodes != null && selectedNodes.length > 0) {
- if (DebuggerAction.getPanel(event.getDataContext()) instanceof VariablesPanel) {
+ DebuggerTreePanel panel = DebuggerAction.getPanel(context);
+ if (panel instanceof VariablesPanel || panel instanceof WatchPanel
+ || (panel == null && DebuggerAction.getTree(context) instanceof InspectDebuggerTree)) {
enabled = true;
for (DebuggerTreeNodeImpl node : selectedNodes) {
NodeDescriptorImpl descriptor = node.getDescriptor();
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
index 854492e..4235b69 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/CustomizeContextViewAction.java
@@ -20,12 +20,12 @@
import com.intellij.debugger.settings.NodeRendererSettings;
import com.intellij.debugger.settings.UserRenderersConfigurable;
import com.intellij.debugger.ui.impl.FrameVariablesTree;
+import com.intellij.debugger.ui.impl.WatchDebuggerTree;
import com.intellij.debugger.ui.impl.watch.DebuggerTree;
import com.intellij.idea.ActionsBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.options.CompositeConfigurable;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
@@ -34,6 +34,8 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
import java.util.ArrayList;
import java.util.List;
@@ -67,6 +69,15 @@
public String getHelpTopic() {
return null;
}
+
+ @Override
+ protected void createConfigurableTabs() {
+ for (Configurable configurable : getConfigurables()) {
+ JComponent component = configurable.createComponent();
+ component.setBorder(new EmptyBorder(8,8,8,8));
+ myTabbedPane.addTab(configurable.getDisplayName(), component);
+ }
+ }
};
SingleConfigurableEditor editor = new SingleConfigurableEditor(project, configurable);
@@ -76,7 +87,7 @@
public void update(AnActionEvent e) {
DebuggerTree tree = getTree(e.getDataContext());
- e.getPresentation().setVisible(tree instanceof FrameVariablesTree);
+ e.getPresentation().setVisible(tree instanceof FrameVariablesTree || tree instanceof WatchDebuggerTree);
e.getPresentation().setText(ActionsBundle.actionText(DebuggerActions.CUSTOMIZE_VIEWS));
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/EditSourceAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/EditSourceAction.java
index da01b9f..778df90 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/EditSourceAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/EditSourceAction.java
@@ -31,19 +31,21 @@
public void actionPerformed(AnActionEvent e) {
final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
- if(project == null) return;
+ if(project == null) {
+ return;
+ }
final DebuggerContextImpl debuggerContext = getDebuggerContext(e.getDataContext());
final DebuggerTreeNodeImpl selectedNode = getSelectedNode(e.getDataContext());
if(debuggerContext != null && selectedNode != null) {
debuggerContext.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(debuggerContext) {
- public void threadAction() {
- final SourcePosition sourcePosition = getSourcePosition(selectedNode, debuggerContext);
- if (sourcePosition != null) {
- sourcePosition.navigate(true);
- }
+ public void threadAction() {
+ final SourcePosition sourcePosition = getSourcePosition(selectedNode, debuggerContext);
+ if (sourcePosition != null) {
+ sourcePosition.navigate(true);
}
- });
+ }
+ });
}
}
@@ -51,21 +53,24 @@
DebuggerTreeNodeImpl node = selectedNode;
final DebuggerContextImpl context = debuggerContext;
- if(node == null) return null;
- if(context == null) return null;
+ if(node == null || context == null) {
+ return null;
+ }
final Project project = context.getProject();
final DebuggerSession debuggerSession = context.getDebuggerSession();
- if(debuggerSession == null) return null;
+ if(debuggerSession == null) {
+ return null;
+ }
NodeDescriptorImpl nodeDescriptor = node.getDescriptor();
if(nodeDescriptor instanceof WatchItemDescriptor) {
Modifier modifier = ((WatchItemDescriptor)nodeDescriptor).getModifier();
-
- if(modifier == null) return null;
-
+ if(modifier == null) {
+ return null;
+ }
nodeDescriptor = (NodeDescriptorImpl)modifier.getInspectItem(project);
}
@@ -90,32 +95,24 @@
final DebuggerTreeNodeImpl node = getSelectedNode(e.getDataContext());
final Presentation presentation = e.getPresentation();
-
- presentation.setEnabled(true);
-
- //if user used shortcut actionPerformed is called immediately after update
- //we not disable presentation here to allow actionPerform work
- DebuggerInvocationUtil.invokeLater(project, new Runnable() {
- public void run() {
- presentation.setEnabled(false);
- }
- });
-
if(debuggerContext != null && debuggerContext.getDebugProcess() != null) {
+ presentation.setEnabled(true);
debuggerContext.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(debuggerContext) {
public void threadAction() {
final SourcePosition position = getSourcePosition(node, debuggerContext);
- if (position != null) {
+ if (position == null) {
DebuggerInvocationUtil.swingInvokeLater(project, new Runnable() {
public void run() {
- presentation.setEnabled(true);
+ presentation.setEnabled(false);
}
});
}
}
});
}
-
+ else {
+ presentation.setEnabled(false);
+ }
e.getPresentation().setText(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE).getTemplatePresentation().getText());
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java
index 0e33f84..9ed769a 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/JavaEditBreakpointActionHandler.java
@@ -29,7 +29,6 @@
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.EmptyRunnable;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.ui.UIUtil;
@@ -66,7 +65,8 @@
final JBPopupListener saveOnClose = new JBPopupListener.Adapter() {
@Override
public void onClosed(LightweightWindowEvent event) {
- propertiesPanel.saveTo(javaBreakpoint, EmptyRunnable.getInstance());
+ propertiesPanel.saveTo(javaBreakpoint);
+ propertiesPanel.dispose();
DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().fireBreakpointChanged(javaBreakpoint);
}
};
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java b/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java
index 8f5b109..5dde5d8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/JvmSmartStepIntoHandler.java
@@ -21,21 +21,28 @@
import com.intellij.debugger.engine.LambdaMethodFilter;
import com.intellij.debugger.engine.MethodFilter;
import com.intellij.debugger.impl.DebuggerSession;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.ShortcutSet;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.fileEditor.TextEditor;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.components.JBList;
+import com.intellij.ui.popup.list.ListPopupImpl;
+import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
+import java.awt.event.ActionEvent;
import java.util.Arrays;
import java.util.List;
@@ -72,7 +79,27 @@
session.stepInto(true, createMethodFilter(chosenTarget));
}
});
- final ListPopup popup = JBPopupFactory.getInstance().createListPopup(popupStep);
+ final ListPopup popup = new ListPopupImpl(popupStep) {
+ @Override
+ protected JComponent createContent() {
+ registerExtraHandleShortcuts(XDebuggerActions.STEP_INTO);
+ registerExtraHandleShortcuts(XDebuggerActions.SMART_STEP_INTO);
+ return super.createContent();
+ }
+
+ private void registerExtraHandleShortcuts(String actionName) {
+ AnAction action = ActionManager.getInstance().getAction(actionName);
+ KeyStroke stroke = KeymapUtil.getKeyStroke(action.getShortcutSet());
+ if (stroke != null) {
+ registerAction("handleSelection " + stroke, stroke, new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ handleSelect(true);
+ }
+ });
+ }
+ }
+ };
popup.addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
popupStep.getScopeHighlighter().dropHighlight();
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/SetValueAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/SetValueAction.java
index 8adff3f..b8de9e6 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/SetValueAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/SetValueAction.java
@@ -374,6 +374,10 @@
}
private void flushValue() {
+ if (comboBox.isPopupVisible()) {
+ comboBox.selectPopupValue();
+ }
+
Editor editor = getEditor();
if(editor == null) {
return;
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java b/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java
index aaa919b..d8e9572 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/ViewAsGroup.java
@@ -111,7 +111,7 @@
if (descriptor instanceof ValueDescriptorImpl) {
anyValueDescriptor = true;
ValueDescriptorImpl valueDescriptor = (ValueDescriptorImpl)descriptor;
- if (valueDescriptor.isValueValid() && !nodeRenderer.isApplicable(valueDescriptor.getType())) {
+ if (!valueDescriptor.isValueValid() || !nodeRenderer.isApplicable(valueDescriptor.getType())) {
allApp = false;
break;
}
@@ -141,7 +141,9 @@
}
}
- children.add(Separator.getInstance());
+ if (!children.isEmpty()) {
+ children.add(Separator.getInstance());
+ }
children.addAll(renderers);
return children.toArray(new AnAction[children.size()]);
diff --git a/java/debugger/impl/src/com/intellij/debugger/actions/ViewTextAction.java b/java/debugger/impl/src/com/intellij/debugger/actions/ViewTextAction.java
index d539de5..52cc1b1 100644
--- a/java/debugger/impl/src/com/intellij/debugger/actions/ViewTextAction.java
+++ b/java/debugger/impl/src/com/intellij/debugger/actions/ViewTextAction.java
@@ -32,6 +32,7 @@
* @author Jeka
*/
public class ViewTextAction extends BaseValueAction {
+ @Override
protected void processText(final Project project, final String text, DebuggerTreeNodeImpl node, DebuggerContextImpl debuggerContext) {
final NodeDescriptorImpl descriptor = node.getDescriptor();
final String labelText = descriptor instanceof ValueDescriptorImpl? ((ValueDescriptorImpl)descriptor).getValueLabel() : null;
@@ -42,8 +43,7 @@
}
private static class MyDialog extends DialogWrapper {
-
- private EditorTextField myTextViewer;
+ private final EditorTextField myTextViewer;
private MyDialog(Project project) {
super(project, false);
@@ -59,15 +59,18 @@
myTextViewer.setText(text);
}
+ @Override
@NotNull
protected Action[] createActions() {
return new Action[] {getCancelAction()};
}
+ @Override
protected String getDimensionServiceKey() {
return "#com.intellij.debugger.actions.ViewTextAction";
}
+ @Override
protected JComponent createCenterPanel() {
final JPanel panel = new JPanel(new BorderLayout());
panel.add(myTextViewer, BorderLayout.CENTER);
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
index f9c7b84..c54ab3b 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/DebugProcessEvents.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -443,7 +443,7 @@
DebuggerPanelsManager.getInstance(getProject()).toFront(mySession);
final String displayName = requestor instanceof Breakpoint? ((Breakpoint)requestor).getDisplayName() : requestor.getClass().getSimpleName();
final String message = DebuggerBundle.message("error.evaluating.breakpoint.condition.or.action", displayName, ex.getMessage());
- considerRequestHit[0] = Messages.showYesNoDialog(getProject(), message, ex.getTitle(), Messages.getQuestionIcon()) == 0;
+ considerRequestHit[0] = Messages.showYesNoDialog(getProject(), message, ex.getTitle(), Messages.getQuestionIcon()) == Messages.YES;
}
}, ModalityState.NON_MODAL);
requestHit = considerRequestHit[0];
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
index 570f6ba..cd6944c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/PositionManagerImpl.java
@@ -179,14 +179,16 @@
}
final String originalQName = refType.name();
- int dollar = originalQName.indexOf('$');
- final String qName = dollar >= 0 ? originalQName.substring(0, dollar) : originalQName;
final GlobalSearchScope searchScope = myDebugProcess.getSearchScope();
- PsiClass psiClass = DebuggerUtils.findClass(qName, project, searchScope);
- if (psiClass == null && dollar >= 0 /*originalName and qName really differ*/) {
- psiClass = DebuggerUtils.findClass(originalQName, project, searchScope); // try to lookup original name
+ PsiClass psiClass = DebuggerUtils.findClass(originalQName, project, searchScope); // try to lookup original name first
+ if (psiClass == null) {
+ int dollar = originalQName.indexOf('$');
+ if (dollar > 0) {
+ final String qName = originalQName.substring(0, dollar);
+ psiClass = DebuggerUtils.findClass(qName, project, searchScope);
+ }
}
-
+
if (psiClass != null) {
final PsiElement element = psiClass.getNavigationElement();
return element.getContainingFile();
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
index d72983a..ef444ea 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/EvaluatorBuilderImpl.java
@@ -47,10 +47,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
public class EvaluatorBuilderImpl implements EvaluatorBuilder {
private static final EvaluatorBuilderImpl ourInstance = new EvaluatorBuilderImpl();
@@ -866,7 +863,7 @@
}
final PsiExpressionList argumentList = expression.getArgumentList();
final PsiExpression[] argExpressions = argumentList.getExpressions();
- final Evaluator[] argumentEvaluators = new Evaluator[argExpressions.length];
+ Evaluator[] argumentEvaluators = new Evaluator[argExpressions.length];
// evaluate arguments
for (int idx = 0; idx < argExpressions.length; idx++) {
final PsiExpression psiExpression = argExpressions[idx];
@@ -957,6 +954,7 @@
if (psiMethod != null) {
processBoxingConversions(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators);
+ argumentEvaluators = wrapVarargs(psiMethod.getParameterList().getParameters(), argExpressions, resolveResult.getSubstitutor(), argumentEvaluators);
}
myResult = new MethodEvaluator(objectEvaluator, contextClass, methodExpr.getReferenceName(), psiMethod != null ? JVMNameUtil.getJVMSignature(psiMethod) : null, argumentEvaluators);
@@ -1162,6 +1160,7 @@
if (constructor != null) {
processBoxingConversions(constructor.getParameterList().getParameters(), argExpressions, constructorResolveResult.getSubstitutor(), argumentEvaluators);
+ argumentEvaluators = wrapVarargs(constructor.getParameterList().getParameters(), argExpressions, constructorResolveResult.getSubstitutor(), argumentEvaluators);
}
//noinspection HardCodedStringLiteral
@@ -1235,6 +1234,34 @@
}
}
+ private static Evaluator[] wrapVarargs(final PsiParameter[] declaredParams,
+ final PsiExpression[] actualArgumentExpressions,
+ final PsiSubstitutor methodResolveSubstitutor,
+ final Evaluator[] argumentEvaluators) {
+ int lastParam = declaredParams.length - 1;
+ if (lastParam >= 0 && declaredParams[lastParam].isVarArgs() && argumentEvaluators.length > lastParam) {
+ // only wrap if the first varargs parameter is null for now
+ if (!TypeConversionUtil.isNullType(actualArgumentExpressions[lastParam].getType())) {
+ return argumentEvaluators;
+ }
+ // do not wrap arrays twice
+ if (argumentEvaluators.length - lastParam == 1 && actualArgumentExpressions[lastParam].getType() instanceof PsiArrayType) {
+ return argumentEvaluators;
+ }
+ PsiEllipsisType declaredParamType = (PsiEllipsisType)methodResolveSubstitutor.substitute(declaredParams[lastParam].getType());
+ ArrayInitializerEvaluator varargArrayEvaluator =
+ new ArrayInitializerEvaluator(Arrays.copyOfRange(argumentEvaluators, lastParam, argumentEvaluators.length));
+ NewArrayInstanceEvaluator evaluator =
+ new NewArrayInstanceEvaluator(new TypeEvaluator(JVMNameUtil.getJVMQualifiedName(declaredParamType.toArrayType())), null,
+ varargArrayEvaluator);
+ Evaluator[] res = new Evaluator[declaredParams.length];
+ System.arraycopy(argumentEvaluators, 0, res, 0, lastParam);
+ res[lastParam] = new DisableGC(evaluator);
+ return res;
+ }
+ return argumentEvaluators;
+ }
+
private static void processBoxingConversions(final PsiParameter[] declaredParams,
final PsiExpression[] actualArgumentExpressions,
final PsiSubstitutor methodResolveSubstitutor,
diff --git a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TypeCastEvaluator.java b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TypeCastEvaluator.java
index 482373d..1942000 100644
--- a/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TypeCastEvaluator.java
+++ b/java/debugger/impl/src/com/intellij/debugger/engine/evaluation/expression/TypeCastEvaluator.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,15 +21,13 @@
package com.intellij.debugger.engine.evaluation.expression;
import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.engine.DebuggerUtils;
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.evaluation.EvaluateExceptionUtil;
import com.intellij.debugger.engine.evaluation.EvaluationContextImpl;
import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.jdi.VirtualMachineProxyImpl;
-import com.sun.jdi.BooleanValue;
-import com.sun.jdi.CharValue;
-import com.sun.jdi.PrimitiveValue;
-import com.sun.jdi.Value;
+import com.sun.jdi.*;
public class TypeCastEvaluator implements Evaluator {
private final Evaluator myOperandEvaluator;
@@ -55,13 +53,13 @@
return null;
}
VirtualMachineProxyImpl vm = context.getDebugProcess().getVirtualMachineProxy();
- if (DebuggerUtilsEx.isInteger(value)) {
+ if (DebuggerUtils.isInteger(value)) {
value = DebuggerUtilsEx.createValue(vm, myCastType, ((PrimitiveValue)value).longValue());
if (value == null) {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.cannot.cast.numeric", myCastType));
}
}
- else if (DebuggerUtilsEx.isNumeric(value)) {
+ else if (DebuggerUtils.isNumeric(value)) {
value = DebuggerUtilsEx.createValue(vm, myCastType, ((PrimitiveValue)value).doubleValue());
if (value == null) {
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.cannot.cast.numeric", myCastType));
@@ -79,6 +77,13 @@
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.cannot.cast.char", myCastType));
}
}
+ else if (value instanceof ObjectReference) {
+ Type type = value.type();
+ if (!DebuggerUtils.instanceOf(type, myCastType)) {
+ throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("evaluation.error.cannot.cast.object", type.name(), myCastType));
+ }
+ }
+
return value;
}
}
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 89db0d0..8329587 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
@@ -22,6 +22,7 @@
import com.intellij.debugger.engine.evaluation.EvaluateException;
import com.intellij.debugger.engine.events.DebuggerCommandImpl;
import com.intellij.debugger.impl.DebuggerSession;
+import com.intellij.debugger.impl.DebuggerUtilsEx;
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.debugger.requests.RequestManager;
import com.intellij.debugger.requests.Requestor;
@@ -163,29 +164,32 @@
if (requestor.CLASS_FILTERS_ENABLED && !(request instanceof BreakpointRequest) /*no built-in class filters support for breakpoint requests*/ ) {
ClassFilter[] classFilters = requestor.getClassFilters();
- for (final ClassFilter filter : classFilters) {
- if (!filter.isEnabled()) {
- continue;
- }
- final JVMName jvmClassName = ApplicationManager.getApplication().runReadAction(new Computable<JVMName>() {
- public JVMName compute() {
- PsiClass psiClass = DebuggerUtils.findClass(filter.getPattern(), myDebugProcess.getProject(), myDebugProcess.getSearchScope());
- if (psiClass == null) {
- return null;
+ if (DebuggerUtilsEx.getEnabledNumber(classFilters) == 1) {
+ for (final ClassFilter filter : classFilters) {
+ if (!filter.isEnabled()) {
+ continue;
+ }
+ final JVMName jvmClassName = ApplicationManager.getApplication().runReadAction(new Computable<JVMName>() {
+ public JVMName compute() {
+ PsiClass psiClass = DebuggerUtils.findClass(filter.getPattern(), myDebugProcess.getProject(), myDebugProcess.getSearchScope());
+ if (psiClass == null) {
+ return null;
+ }
+ return JVMNameUtil.getJVMQualifiedName(psiClass);
}
- return JVMNameUtil.getJVMQualifiedName(psiClass);
+ });
+ String pattern = filter.getPattern();
+ try {
+ if (jvmClassName != null) {
+ pattern = jvmClassName.getName(myDebugProcess);
+ }
}
- });
- String pattern = filter.getPattern();
- try {
- if (jvmClassName != null) {
- pattern = jvmClassName.getName(myDebugProcess);
+ catch (EvaluateException ignored) {
}
- }
- catch (EvaluateException ignored) {
- }
- addClassFilter(request, pattern);
+ addClassFilter(request, pattern);
+ break; // adding more than one inclusion filter does not work, only events that satisfy ALL filters are placed in the event queue.
+ }
}
for (ClassFilter filter : requestor.getClassExclusionFilters()) {
@@ -302,7 +306,7 @@
//there could be no requests after hotswap
}
else {
- LOG.error(e);
+ LOG.info(e);
}
}
}
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 19de95a..917dba2 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerSession.java
@@ -487,7 +487,7 @@
if (currentThread != null) {
try {
final int frameCount = currentThread.frameCount();
- if (frameCount == 0 || (frameCount < myIgnoreFiltersFrameCountThreshold)) {
+ if (frameCount == 0 || (frameCount <= myIgnoreFiltersFrameCountThreshold)) {
resetIgnoreStepFiltersFlag();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java
index c8b47e4..aa2b479 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/DebuggerUtilsEx.java
@@ -230,6 +230,16 @@
}
return false;
}
+
+ public static int getEnabledNumber(ClassFilter[] classFilters) {
+ int res = 0;
+ for (ClassFilter filter : classFilters) {
+ if (filter.isEnabled()) {
+ res++;
+ }
+ }
+ return res;
+ }
public static ClassFilter[] readFilters(List children) throws InvalidDataException {
if (children == null || children.size() == 0) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java
index 138da80..cb280fc 100644
--- a/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java
+++ b/java/debugger/impl/src/com/intellij/debugger/impl/GenericDebuggerRunner.java
@@ -46,10 +46,10 @@
}
@Override
- protected RunContentDescriptor doExecute(final Project project,
- final RunProfileState state,
+ protected RunContentDescriptor doExecute(@NotNull final Project project,
+ @NotNull final RunProfileState state,
final RunContentDescriptor contentToReuse,
- final ExecutionEnvironment env) throws ExecutionException {
+ @NotNull final ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
return createContentDescriptor(project, state, contentToReuse, env);
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/ArrayRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/ArrayRendererConfigurable.java
index eeb0986..eb74b08 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/ArrayRendererConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/ArrayRendererConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,7 +19,6 @@
import com.intellij.debugger.ui.tree.render.ArrayRenderer;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.options.UnnamedConfigurable;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import javax.swing.*;
@@ -77,7 +76,7 @@
DebuggerBundle.message("warning.range.too.big", ApplicationNamesInfo.getInstance().getProductName()),
DebuggerBundle.message("title.range.too.big"),
Messages.getWarningIcon());
- if(answer != DialogWrapper.OK_EXIT_CODE) {
+ if(answer != Messages.OK) {
return;
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
index 2f92bc5..ed9994c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/CompoundRendererConfigurable.java
@@ -26,18 +26,17 @@
import com.intellij.debugger.ui.JavaDebuggerSupport;
import com.intellij.debugger.ui.tree.render.*;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Pair;
-import com.intellij.psi.PsiClass;
+import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.ui.AnActionButton;
-import com.intellij.ui.AnActionButtonRunnable;
-import com.intellij.ui.TableUtil;
-import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
+import com.intellij.util.Function;
import com.intellij.util.ui.AbstractTableCellEditor;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -59,7 +58,7 @@
private CompoundReferenceRenderer myRenderer;
private CompoundReferenceRenderer myOriginalRenderer;
private Project myProject;
- private TextFieldWithBrowseButton myClassNameField;
+ private ClassNameEditorWithBrowseButton myClassNameField;
private JRadioButton myRbDefaultLabel;
private JRadioButton myRbExpressionLabel;
private JRadioButton myRbDefaultChildrenRenderer;
@@ -131,16 +130,18 @@
myRbListChildrenRenderer.addItemListener(updateListener);
myRbExpressionChildrenRenderer.addItemListener(updateListener);
- myClassNameField = new TextFieldWithBrowseButton(new ActionListener() {
+ myClassNameField = new ClassNameEditorWithBrowseButton(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PsiClass psiClass = DebuggerUtils.getInstance()
.chooseClassDialog(DebuggerBundle.message("title.compound.renderer.configurable.choose.renderer.reference.type"), myProject);
if (psiClass != null) {
- myClassNameField.setText(JVMNameUtil.getNonAnonymousClassName(psiClass));
+ String qName = JVMNameUtil.getNonAnonymousClassName(psiClass);
+ myClassNameField.setText(qName);
+ updateContext(qName);
}
}
- });
- myClassNameField.getTextField().addFocusListener(new FocusAdapter() {
+ }, myProject);
+ myClassNameField.getEditorTextField().addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
final String qName = myClassNameField.getText();
updateContext(qName);
@@ -203,8 +204,25 @@
myChildrenEditor.setContext(psiClass);
myChildrenExpandedEditor.setContext(psiClass);
myListChildrenEditor.setContext(psiClass);
+
+ PsiType type = DebuggerUtils.getType(qName, project);
+ myLabelEditor.setThisType(type);
+ myChildrenEditor.setThisType(type);
+ myChildrenExpandedEditor.setThisType(type);
+ myListChildrenEditor.setThisType(type);
}
});
+
+ // Need to recreate fields documents with the new context
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ myLabelEditor.setText(myLabelEditor.getText());
+ myChildrenEditor.setText(myChildrenEditor.getText());
+ myChildrenExpandedEditor.setText(myChildrenExpandedEditor.getText());
+ myListChildrenEditor.setText(myListChildrenEditor.getText());
+ }
+ }, ModalityState.any(), myProject.getDisposed());
}
private void updateEnabledState() {
@@ -494,4 +512,20 @@
}
}
}
+
+ private static class ClassNameEditorWithBrowseButton extends ReferenceEditorWithBrowseButton {
+ private ClassNameEditorWithBrowseButton(ActionListener browseActionListener, final Project project) {
+ super(browseActionListener, project,
+ new Function<String, Document>() {
+ @Override
+ public Document fun(String s) {
+ PsiPackage defaultPackage = JavaPsiFacade.getInstance(project).findPackage("");
+ final JavaCodeFragment fragment =
+ JavaCodeFragmentFactory.getInstance(project).createReferenceCodeFragment(s, defaultPackage, true, true);
+ fragment.setVisibilityChecker(JavaCodeFragment.VisibilityChecker.EVERYTHING_VISIBLE);
+ return PsiDocumentManager.getInstance(project).getDocument(fragment);
+ }
+ }, "");
+ }
+ }
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java
index c1207a5..4d188d8 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/DebuggerDataViewsConfigurable.java
@@ -185,6 +185,7 @@
panel.add(myCbEnableToString, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(4, 0, 0, 0), 0, 0));
panel.add(myRbAllThatOverride, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 12, 0, 0), 0, 0));
panel.add(myRbFromList, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 0.0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 12, 0, 0), 0, 0));
+ myToStringFilterEditor.setMinimumSize(new Dimension(50, 100));
panel.add(myToStringFilterEditor, new GridBagConstraints(0, GridBagConstraints.RELATIVE, 3, 1, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 12, 0, 0), 0, 0));
return panel;
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java b/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java
index 315e01f..a43ca7e 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/NodeRendererSettings.java
@@ -16,13 +16,16 @@
package com.intellij.debugger.settings;
import com.intellij.debugger.DebuggerBundle;
+import com.intellij.debugger.DebuggerContext;
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.engine.DebugProcess;
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.debugger.engine.evaluation.expression.ExpressionEvaluator;
import com.intellij.debugger.impl.DebuggerUtilsEx;
+import com.intellij.debugger.ui.impl.watch.ArrayElementDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.ValueDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor;
+import com.intellij.debugger.ui.tree.DebuggerTreeNode;
import com.intellij.debugger.ui.tree.ValueDescriptor;
import com.intellij.debugger.ui.tree.render.*;
import com.intellij.debugger.ui.tree.render.Renderer;
@@ -31,7 +34,11 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiElementFactory;
+import com.intellij.psi.PsiExpression;
import com.intellij.util.EventDispatcher;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.InternalIterator;
import com.intellij.util.ui.ColorIcon;
import com.sun.jdi.*;
@@ -87,6 +94,11 @@
createEnumerationChildrenRenderer(new String[][]{{"key", "getKey()"}, {"value", "getValue()"}})
),
createCompoundReferenceRenderer(
+ "List", CommonClassNames.JAVA_UTIL_LIST,
+ createLabelRenderer(" size = ", "size()", null),
+ new ListChildrenRenderer()
+ ),
+ createCompoundReferenceRenderer(
"Collection", "java.util.Collection",
createLabelRenderer(" size = ", "size()", null),
createExpressionChildrenRenderer("toArray()", "!isEmpty()")
@@ -477,6 +489,36 @@
}
}
+ private static class ListChildrenRenderer extends ExpressionChildrenRenderer {
+ private static final ArrayRenderer ourChildrenRenderer = new ArrayRenderer() {
+ @Override
+ public PsiExpression getChildValueExpression(DebuggerTreeNode node, DebuggerContext context) {
+ try {
+ ArrayElementDescriptorImpl descriptor = (ArrayElementDescriptorImpl)node.getDescriptor();
+ PsiElementFactory elementFactory = JavaPsiFacade.getInstance(node.getProject()).getElementFactory();
+ return elementFactory.createExpressionFromText("get(" + descriptor.getIndex() + ")", null);
+ }
+ catch (IncorrectOperationException e) {
+ // fallback to original
+ return super.getChildValueExpression(node, context);
+ }
+ }
+ };
+
+ public ListChildrenRenderer() {
+ setChildrenExpression(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "toArray()", "", StdFileTypes.JAVA));
+ setChildrenExpandable(new TextWithImportsImpl(CodeFragmentKind.EXPRESSION, "!isEmpty()", "", StdFileTypes.JAVA));
+ }
+
+ @Override
+ public void buildChildren(Value value, ChildrenBuilder builder, EvaluationContext evaluationContext) {
+ if (getLastChildrenRenderer(builder.getParentDescriptor()) == null) {
+ setPreferableChildrenRenderer(builder.getParentDescriptor(), ourChildrenRenderer);
+ }
+ super.buildChildren(value, builder, evaluationContext);
+ }
+ }
+
private static class DescriptorUpdater implements DescriptorLabelListener {
private final ValueDescriptor myTargetDescriptor;
@Nullable
diff --git a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
index 7e9ca74..3ab2028 100644
--- a/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
+++ b/java/debugger/impl/src/com/intellij/debugger/settings/UserRenderersConfigurable.java
@@ -52,6 +52,7 @@
private static final Icon UP_ICON = IconUtil.getMoveUpIcon();
private static final Icon DOWN_ICON = IconUtil.getMoveDownIcon();
+ private JPanel myNameFieldPanel;
private JTextField myNameField;
private ElementsChooser<NodeRenderer> myRendererChooser;
private NodeRenderer myCurrentRenderer = null;
@@ -91,14 +92,14 @@
left.add(renderersList, BorderLayout.CENTER);
myNameField = new JTextField();
- final JPanel nameFieldPanel = new JPanel(new BorderLayout());
- nameFieldPanel.add(new JLabel(DebuggerBundle.message("label.user.renderers.configurable.renderer.name")), BorderLayout.WEST);
- nameFieldPanel.add(myNameField, BorderLayout.CENTER);
-
+ myNameFieldPanel = new JPanel(new BorderLayout());
+ myNameFieldPanel.add(new JLabel(DebuggerBundle.message("label.user.renderers.configurable.renderer.name")), BorderLayout.WEST);
+ myNameFieldPanel.add(myNameField, BorderLayout.CENTER);
+ myNameFieldPanel.setVisible(false);
final JPanel center = new JPanel(new BorderLayout(0, 4));
- center.add(nameFieldPanel, BorderLayout.NORTH);
+ center.add(myNameFieldPanel, BorderLayout.NORTH);
center.add(rendererDataPanel, BorderLayout.CENTER);
myNameField.getDocument().addDocumentListener(new DocumentAdapter() {
@@ -159,11 +160,11 @@
}
myCurrentRenderer = renderer;
if (renderer != null) {
- myNameField.setEnabled(true);
+ myNameFieldPanel.setVisible(true);
myNameField.setText(renderer.getName());
}
else {
- myNameField.setEnabled(false);
+ myNameFieldPanel.setVisible(false);
myNameField.setText("");
}
myRendererDataConfigurable.setRenderer(renderer);
@@ -183,6 +184,8 @@
public void apply() throws ConfigurationException {
myRendererDataConfigurable.apply();
flushTo(NodeRendererSettings.getInstance().getCustomRenderers());
+
+ NodeRendererSettings.getInstance().fireRenderersChanged();
}
private void flushTo(final RendererConfiguration rendererConfiguration) {
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 6b514f3..5eb71c3 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerEditorImpl.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerEditorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -41,6 +41,7 @@
import com.intellij.psi.impl.PsiDocumentManagerBase;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.ClickListener;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -63,6 +64,7 @@
private final Project myProject;
private PsiElement myContext;
+ private PsiType myThisType;
private final String myRecentsId;
@@ -71,6 +73,8 @@
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();
@@ -111,8 +115,8 @@
myChooseFactory.setBorder(new EmptyBorder(0, 3, 0, 3));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
- ListPopup oldPopup = myPopup != null ? myPopup.get() : null;
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
+ ListPopup oldPopup = SoftReference.dereference(myPopup);
if (oldPopup != null && !oldPopup.isDisposed()) {
oldPopup.cancel();
myPopup = null;
@@ -138,6 +142,7 @@
@Override
public void actionPerformed(AnActionEvent e) {
setFactory(fragmentFactory);
+ myExplicitlyChosen = true;
setText(getText());
IdeFocusManager.getInstance(getProject()).requestFocus(DebuggerEditorImpl.this, true);
}
@@ -214,6 +219,10 @@
getPreferredFocusedComponent().requestFocus();
}
+ public void setThisType(PsiType thisType) {
+ myThisType = thisType;
+ }
+
@Nullable
protected Document createDocument(TextWithImports item) {
LOG.assertTrue(myContext == null || myContext.isValid());
@@ -223,7 +232,10 @@
}
JavaCodeFragment codeFragment = getCurrentFactory().createPresentationCodeFragment(item, myContext, getProject());
codeFragment.forceResolveScope(GlobalSearchScope.allScope(myProject));
- if (myContext != null) {
+ if (myThisType != null) {
+ codeFragment.setThisType(myThisType);
+ }
+ else if (myContext != null) {
final PsiClass contextClass = PsiTreeUtil.getNonStrictParentOfType(myContext, PsiClass.class);
if (contextClass != null) {
final PsiClassType contextType = JavaPsiFacade.getInstance(codeFragment.getProject()).getElementFactory().createType(contextClass);
@@ -288,12 +300,33 @@
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;
- setFactory(findAppropriateFactory(text, myContext));
+ CodeFragmentFactory newFactory = findFactoryForRestore(text, myContext);
+ if (!newFactory.equals(myFactory)) {
+ myExplicitlyChosen = false;
+ setFactory(newFactory);
+ }
}
private void setFactory(@NotNull final CodeFragmentFactory factory) {
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java
index a7b88f3..479c933 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerExpressionComboBox.java
@@ -18,6 +18,9 @@
import com.intellij.debugger.engine.evaluation.*;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.event.DocumentListener;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
@@ -66,6 +69,11 @@
final Document document = createDocument(twi);
getEditorComponent().setNewDocumentAndFileType(getCurrentFactory().getFileType(), document);
super.setItem(document);
+
+ // need to replace newlines with spaces, see IDEA-81789
+ if (document != null) {
+ document.addDocumentListener(REPLACE_NEWLINES_LISTENER);
+ }
/* Causes PSI being modified from PSI events. See IDEADEV-22102
final Editor editor = getEditor();
if (editor != null) {
@@ -76,6 +84,17 @@
}
+ private static DocumentListener REPLACE_NEWLINES_LISTENER = new DocumentAdapter() {
+ @Override
+ public void documentChanged(DocumentEvent e) {
+ final String text = e.getNewFragment().toString();
+ final String replaced = text.replace('\n', ' ');
+ if (replaced != text) {
+ e.getDocument().replaceString(e.getOffset(), e.getOffset() + e.getNewLength(), replaced);
+ }
+ }
+ };
+
public DebuggerExpressionComboBox(Project project, @NonNls String recentsId) {
this(project, null, recentsId, DefaultCodeFragmentFactory.getInstance());
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java
index 9ba6365..95024cd 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerSessionTab.java
@@ -485,6 +485,7 @@
}
}
});
+ Disposer.register(content, consoleView);
myUi.selectAndFocus(content, true, false);
if (threads.size() > 0) {
panel.selectStackFrame(0);
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerTreeCreatorImpl.java b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerTreeCreatorImpl.java
new file mode 100644
index 0000000..556c769
--- /dev/null
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/DebuggerTreeCreatorImpl.java
@@ -0,0 +1,76 @@
+/*
+ * 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;
+
+import com.intellij.concurrency.ResultConsumer;
+import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.engine.evaluation.EvaluateException;
+import com.intellij.debugger.engine.evaluation.TextWithImports;
+import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
+import com.intellij.debugger.impl.DebuggerContextImpl;
+import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeExpression;
+import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl;
+import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.xdebugger.impl.evaluate.quick.common.DebuggerTreeCreator;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+*/
+class DebuggerTreeCreatorImpl implements DebuggerTreeCreator<Pair<NodeDescriptorImpl, String>> {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.ValueHintTreeComponent");
+ private Project myProject;
+
+ public DebuggerTreeCreatorImpl(Project project) {
+ myProject = project;
+ }
+
+ @NotNull
+ @Override
+ public String getTitle(@NotNull Pair<NodeDescriptorImpl, String> descriptor) {
+ return descriptor.getSecond();
+ }
+
+ @Override
+ public void createDescriptorByNode(Object node, final ResultConsumer<Pair<NodeDescriptorImpl, String>> resultConsumer) {
+ if (node instanceof DebuggerTreeNodeImpl) {
+ final DebuggerTreeNodeImpl debuggerTreeNode = (DebuggerTreeNodeImpl)node;
+ final DebuggerContextImpl context = DebuggerManagerEx.getInstanceEx(myProject).getContext();
+ context.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(context) {
+ @Override
+ public void threadAction() {
+ try {
+ final TextWithImports evaluationText = DebuggerTreeNodeExpression.createEvaluationText(debuggerTreeNode, context);
+ resultConsumer.onSuccess(Pair.create(debuggerTreeNode.getDescriptor(), evaluationText.getText()));
+ }
+ catch (EvaluateException e) {
+ resultConsumer.onFailure(e);
+ }
+ }
+ });
+ }
+ }
+
+ @NotNull
+ @Override
+ public Tree createTree(@NotNull Pair<NodeDescriptorImpl, String> descriptor) {
+ return ValueHint.createInspectTree(descriptor.first, myProject);
+ }
+}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/ExportDialog.java b/java/debugger/impl/src/com/intellij/debugger/ui/ExportDialog.java
index 8e6b2cd..e970653 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/ExportDialog.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/ExportDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -124,7 +124,7 @@
DebuggerBundle.message("threads.export.dialog.title"),
Messages.getQuestionIcon()
);
- if (answer == 0) {
+ if (answer == Messages.YES) {
super.doOKAction();
}
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java b/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java
index 468dd1c..0070178 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/GetJPDADialog.java
@@ -60,7 +60,7 @@
new DoubleClickListener() {
@Override
protected boolean onDoubleClick(MouseEvent e) {
- BrowserUtil.launchBrowser(JPDA_URL);
+ BrowserUtil.browse(JPDA_URL);
return true;
}
}.installOn(label2);
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 6cfccee..e5bb8fa 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/PositionHighlighter.java
@@ -17,6 +17,7 @@
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerInvocationUtil;
+import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.SourcePosition;
import com.intellij.debugger.engine.DebugProcessEvents;
import com.intellij.debugger.engine.DebugProcessImpl;
@@ -28,6 +29,7 @@
import com.intellij.debugger.ui.breakpoints.*;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -429,6 +431,20 @@
}
@Override
+ public AnAction getMiddleButtonClickAction() {
+ return new AnAction() {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ if (myEventsOutOfLine.size() == 1) {
+ Breakpoint breakpoint = myEventsOutOfLine.get(0).getFirst();
+ breakpoint.ENABLED = !breakpoint.ENABLED;
+ DebuggerManagerEx.getInstanceEx(myProject).getBreakpointManager().fireBreakpointChanged(breakpoint);
+ }
+ }
+ };
+ }
+
+ @Override
public boolean equals(Object obj) {
return obj instanceof MyGutterIconRenderer &&
Comparing.equal(getTooltipText(), ((MyGutterIconRenderer)obj).getTooltipText()) &&
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/ValueHint.java b/java/debugger/impl/src/com/intellij/debugger/ui/ValueHint.java
index 2adcbb0..8a08772 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/ValueHint.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/ValueHint.java
@@ -19,6 +19,7 @@
import com.intellij.debugger.DebuggerBundle;
import com.intellij.debugger.DebuggerInvocationUtil;
import com.intellij.debugger.DebuggerManagerEx;
+import com.intellij.debugger.actions.DebuggerActions;
import com.intellij.debugger.engine.DebugProcessImpl;
import com.intellij.debugger.engine.JVMName;
import com.intellij.debugger.engine.JVMNameUtil;
@@ -32,8 +33,13 @@
import com.intellij.debugger.impl.EditorTextProvider;
import com.intellij.debugger.ui.impl.DebuggerTreeRenderer;
import com.intellij.debugger.ui.impl.InspectDebuggerTree;
+import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
import com.intellij.debugger.ui.impl.watch.WatchItemDescriptor;
import com.intellij.debugger.ui.tree.render.DescriptorLabelListener;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -45,7 +51,6 @@
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.IncorrectOperationException;
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
-import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHintTreeComponent;
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType;
import com.sun.jdi.Method;
import com.sun.jdi.PrimitiveValue;
@@ -54,6 +59,7 @@
import javax.swing.*;
import java.awt.*;
+import java.awt.event.KeyEvent;
/**
* @author lex
@@ -150,9 +156,9 @@
}
}
});
- } else {
- final InspectDebuggerTree tree = getInspectTree(descriptor);
- showTreePopup(tree, debuggerContext, expressionText, new ValueHintTreeComponent(ValueHint.this, tree, expressionText));
+ }
+ else {
+ createAndShowTree(expressionText, descriptor);
}
}
catch (EvaluateException e) {
@@ -167,23 +173,20 @@
}
}
- private static boolean isActiveTooltipApplicable(final Value value) {
- return value != null && !(value instanceof PrimitiveValue);
- }
-
- public void showTreePopup(final InspectDebuggerTree tree,
- final DebuggerContextImpl debuggerContext,
- final String title,
- final AbstractValueHintTreeComponent<?> component) {
+ private void createAndShowTree(final String expressionText, final NodeDescriptorImpl descriptor) {
+ final DebuggerTreeCreatorImpl creator = new DebuggerTreeCreatorImpl(getProject());
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
@Override
public void run() {
- tree.rebuild(debuggerContext);
- showTreePopup(component, tree, title);
+ showTreePopup(creator, Pair.create(descriptor, expressionText));
}
});
}
+ private static boolean isActiveTooltipApplicable(final Value value) {
+ return value != null && !(value instanceof PrimitiveValue);
+ }
+
private void showHint(final SimpleColoredText text, final WatchItemDescriptor descriptor) {
DebuggerInvocationUtil.invokeLater(getProject(), new Runnable() {
@Override
@@ -203,15 +206,14 @@
@Override
public void threadAction() {
descriptor.setRenderer(debugProcess.getAutoRenderer(descriptor));
- final InspectDebuggerTree tree = getInspectTree(descriptor);
final String expressionText = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
return myCurrentExpression.getText();
}
});
- showTreePopup(tree, debuggerContext, expressionText,
- new ValueHintTreeComponent(ValueHint.this, tree, expressionText));
+
+ createAndShowTree(expressionText, descriptor);
}
});
}
@@ -226,10 +228,19 @@
});
}
- private InspectDebuggerTree getInspectTree(final WatchItemDescriptor descriptor) {
- final InspectDebuggerTree tree = new InspectDebuggerTree(getProject());
- tree.getModel().addTreeModelListener(createTreeListener(tree));
+ public static InspectDebuggerTree createInspectTree(final NodeDescriptorImpl descriptor, Project project) {
+ final InspectDebuggerTree tree = new InspectDebuggerTree(project);
+ final AnAction setValueAction = ActionManager.getInstance().getAction(DebuggerActions.SET_VALUE);
+ setValueAction.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)), tree);
+ Disposer.register(tree, new Disposable() {
+ @Override
+ public void dispose() {
+ setValueAction.unregisterCustomShortcutSet(tree);
+ }
+ });
tree.setInspectDescriptor(descriptor);
+ DebuggerContextImpl context = DebuggerManagerEx.getInstanceEx(project).getContext();
+ tree.rebuild(context);
return tree;
}
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/ValueHintTreeComponent.java b/java/debugger/impl/src/com/intellij/debugger/ui/ValueHintTreeComponent.java
deleted file mode 100644
index 8c0caed..0000000
--- a/java/debugger/impl/src/com/intellij/debugger/ui/ValueHintTreeComponent.java
+++ /dev/null
@@ -1,86 +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;
-
-import com.intellij.debugger.DebuggerManagerEx;
-import com.intellij.debugger.engine.evaluation.EvaluateException;
-import com.intellij.debugger.engine.evaluation.TextWithImports;
-import com.intellij.debugger.engine.events.DebuggerContextCommandImpl;
-import com.intellij.debugger.impl.DebuggerContextImpl;
-import com.intellij.debugger.ui.impl.InspectDebuggerTree;
-import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeExpression;
-import com.intellij.debugger.ui.impl.watch.DebuggerTreeNodeImpl;
-import com.intellij.debugger.ui.impl.watch.NodeDescriptorImpl;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Pair;
-import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHintTreeComponent;
-
-/**
- * @author nik
-*/
-class ValueHintTreeComponent extends AbstractValueHintTreeComponent<Pair<NodeDescriptorImpl, String>> {
- private static final Logger LOG = Logger.getInstance("#com.intellij.debugger.ui.ValueHintTreeComponent");
- private final ValueHint myValueHint;
- private final InspectDebuggerTree myTree;
-
- public ValueHintTreeComponent(final ValueHint valueHint, InspectDebuggerTree tree, final String title) {
- super(valueHint, tree, Pair.create(tree.getInspectDescriptor(), title));
- myValueHint = valueHint;
- myTree = tree;
- }
-
-
- @Override
- protected void updateTree(Pair<NodeDescriptorImpl, String> descriptorWithTitle){
- final NodeDescriptorImpl descriptor = descriptorWithTitle.first;
- final String title = descriptorWithTitle.second;
- final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(myValueHint.getProject())).getContext();
- context.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(context) {
- @Override
- public void threadAction() {
- myTree.setInspectDescriptor(descriptor);
- myValueHint.showTreePopup(myTree, context, title, ValueHintTreeComponent.this);
- }
- });
- }
-
-
- @Override
- protected void setNodeAsRoot(final Object node) {
- if (node instanceof DebuggerTreeNodeImpl) {
- myValueHint.shiftLocation();
- final DebuggerTreeNodeImpl debuggerTreeNode = (DebuggerTreeNodeImpl)node;
- final DebuggerContextImpl context = (DebuggerManagerEx.getInstanceEx(myValueHint.getProject())).getContext();
- context.getDebugProcess().getManagerThread().schedule(new DebuggerContextCommandImpl(context) {
- @Override
- public void threadAction() {
- try {
- final NodeDescriptorImpl descriptor = debuggerTreeNode.getDescriptor();
- final TextWithImports evaluationText = DebuggerTreeNodeExpression.createEvaluationText(debuggerTreeNode, context);
- final String title = evaluationText.getText();
- addToHistory(Pair.create(descriptor, title));
- myTree.setInspectDescriptor(descriptor);
- myValueHint.showTreePopup(myTree, context, title, ValueHintTreeComponent.this);
- }
- catch (final EvaluateException e1) {
- LOG.debug(e1);
- }
- }
- });
- }
- }
-
-}
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 87ec469..1b370ca 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
@@ -32,7 +32,10 @@
import com.intellij.debugger.requests.ClassPrepareRequestor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.*;
+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.ui.AppUIUtil;
import com.intellij.util.StringBuilderSpinAllocator;
@@ -278,11 +281,7 @@
});
}
- public final void updateUI() {
- updateUI(EmptyRunnable.getInstance());
- }
-
- public void updateUI(@NotNull Runnable afterUpdate) {
+ public void updateUI() {
}
public void delete() {
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 95cdf09..d52044b 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
@@ -50,7 +50,6 @@
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointItem;
import com.intellij.xdebugger.impl.breakpoints.ui.BreakpointNoneItem;
import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -631,7 +630,7 @@
/**
* Save values in the UI components to the breakpoint object
*/
- public void saveTo(Breakpoint breakpoint, @NotNull Runnable afterUpdate) {
+ public void saveTo(Breakpoint breakpoint) {
saveMasterBreakpoint();
try {
@@ -667,7 +666,7 @@
myConditionCombo.addRecent(myConditionCombo.getText());
myLogExpressionCombo.addRecent(myLogExpressionCombo.getText());
- breakpoint.updateUI(afterUpdate);
+ breakpoint.updateUI();
}
private static String concatWithEx(List<String> s, String concator, int N, String NthConcator) {
@@ -878,6 +877,12 @@
}
@Override
+ protected void dispose() {
+ super.dispose();
+ myEditor.dispose();
+ }
+
+ @Override
protected void doOKAction() {
myTargetEditor.setText(myEditor.getText());
super.doOKAction();
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 984be03..16b7527 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
@@ -340,7 +340,7 @@
* updates the state of breakpoint and all the related UI widgets etc
*/
@Override
- public final void updateUI(@NotNull final Runnable afterUpdate) {
+ public final void updateUI() {
if (ApplicationManager.getApplication().isUnitTestMode()) {
return;
}
@@ -357,8 +357,6 @@
if (debugProcess == null || !debugProcess.isAttached()) {
updateCaches(null);
updateGutter();
-
- afterUpdate.run();
}
else {
debugProcess.getManagerThread().invoke(new DebuggerCommandImpl() {
@@ -374,7 +372,6 @@
@Override
public void run() {
updateGutter();
- afterUpdate.run();
}
});
}
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 73680f5..6d02499 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
@@ -25,7 +25,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ui.DialogUtil;
-import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -106,11 +105,11 @@
myNotifyUncaughtCheckBox.setSelected(exceptionBreakpoint.NOTIFY_UNCAUGHT);
}
- public void saveTo(Breakpoint breakpoint, @NotNull Runnable afterUpdate) {
+ public void saveTo(Breakpoint breakpoint) {
ExceptionBreakpoint exceptionBreakpoint = (ExceptionBreakpoint)breakpoint;
exceptionBreakpoint.NOTIFY_CAUGHT = myNotifyCaughtCheckBox.isSelected();
exceptionBreakpoint.NOTIFY_UNCAUGHT = myNotifyUncaughtCheckBox.isSelected();
- super.saveTo(breakpoint, afterUpdate);
+ super.saveTo(breakpoint);
}
}
\ No newline at end of file
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 77497f7..bec1264 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
@@ -24,7 +24,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ui.DialogUtil;
-import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -95,12 +94,12 @@
myWatchModificationCheckBox.setSelected(fieldBreakpoint.WATCH_MODIFICATION);
}
- public void saveTo(Breakpoint breakpoint, @NotNull Runnable afterUpdate) {
+ public void saveTo(Breakpoint breakpoint) {
FieldBreakpoint fieldBreakpoint = (FieldBreakpoint)breakpoint;
fieldBreakpoint.WATCH_ACCESS = myWatchAccessCheckBox.isSelected();
fieldBreakpoint.WATCH_MODIFICATION = myWatchModificationCheckBox.isSelected();
- super.saveTo(breakpoint, afterUpdate);
+ super.saveTo(breakpoint);
}
}
\ 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 e8fd23e..8aa57bd 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
@@ -41,6 +41,7 @@
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;
@@ -174,6 +175,11 @@
}
}
+ 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>() {
@@ -211,6 +217,35 @@
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() {
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
index 04a3f0b..ec3577c 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/breakpoints/JavaBreakpointItem.java
@@ -18,7 +18,6 @@
import com.intellij.debugger.DebuggerManagerEx;
import com.intellij.debugger.SourcePosition;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.SimpleColoredComponent;
@@ -72,7 +71,10 @@
@Override
protected void doUpdateDetailView(DetailView panel, boolean editorOnly) {
//saveState();
- myBreakpointPropertiesPanel = null;
+ if (myBreakpointPropertiesPanel != null) {
+ myBreakpointPropertiesPanel.dispose();
+ myBreakpointPropertiesPanel = null;
+ }
if (!editorOnly) {
myBreakpointPropertiesPanel = myBreakpointFactory != null ? myBreakpointFactory
@@ -126,13 +128,14 @@
@Override
public void removed(Project project) {
+ dispose();
DebuggerManagerEx.getInstanceEx(project).getBreakpointManager().removeBreakpoint(myBreakpoint);
}
@Override
public void saveState() {
if (myBreakpointPropertiesPanel != null) {
- myBreakpointPropertiesPanel.saveTo(myBreakpoint, EmptyRunnable.INSTANCE);
+ myBreakpointPropertiesPanel.saveTo(myBreakpoint);
}
}
@@ -159,6 +162,14 @@
}
@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) {
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 a78cb13..307b962 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
@@ -49,7 +49,6 @@
import com.intellij.psi.search.EverythingGlobalScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.StringBuilderSpinAllocator;
@@ -320,38 +319,19 @@
}
@Override
- public boolean evaluateCondition(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
- if(CLASS_FILTERS_ENABLED){
- String className = null;
- final ObjectReference thisObject = (ObjectReference)context.getThisObject();
- if(thisObject != null) {
- className = thisObject.referenceType().name();
- }
- else {
- final StackFrameProxyImpl frame = context.getFrameProxy();
- if (frame != null) {
- className = frame.location().declaringType().name();
- }
- }
- if (className != null) {
- boolean matches = false;
- for (ClassFilter classFilter : getClassFilters()) {
- if (classFilter.isEnabled() && classFilter.matches(className)) {
- matches = true;
- break;
- }
- }
- if(!matches) {
- return false;
- }
- for (ClassFilter classFilter : getClassExclusionFilters()) {
- if (classFilter.isEnabled() && classFilter.matches(className)) {
- return false;
- }
- }
+ protected String calculateEventClass(EvaluationContextImpl context, LocatableEvent event) throws EvaluateException {
+ String className = null;
+ final ObjectReference thisObject = (ObjectReference)context.getThisObject();
+ if (thisObject != null) {
+ className = thisObject.referenceType().name();
+ }
+ else {
+ final StackFrameProxyImpl frame = context.getFrameProxy();
+ if (frame != null) {
+ className = frame.location().declaringType().name();
}
}
- return super.evaluateCondition(context, event);
+ return className;
}
public String toString() {
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 5298474..c50b699 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
@@ -24,7 +24,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ui.DialogUtil;
-import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -101,7 +100,7 @@
}
}
- public void saveTo(Breakpoint breakpoint, @NotNull Runnable afterUpdate) {
+ public void saveTo(Breakpoint breakpoint) {
if (breakpoint instanceof MethodBreakpoint) {
MethodBreakpoint methodBreakpoint = (MethodBreakpoint)breakpoint;
methodBreakpoint.WATCH_ENTRY = myWatchEntryCheckBox.isSelected();
@@ -112,6 +111,6 @@
methodBreakpoint.WATCH_ENTRY = myWatchEntryCheckBox.isSelected();
methodBreakpoint.WATCH_EXIT = myWatchExitCheckBox.isSelected();
}
- super.saveTo(breakpoint, afterUpdate);
+ super.saveTo(breakpoint);
}
}
\ No newline at end of file
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/MainWatchPanel.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/MainWatchPanel.java
index 2034938..b58d9e6 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/MainWatchPanel.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/MainWatchPanel.java
@@ -184,8 +184,13 @@
}
TextWithImports text = comboBox.getText();
- WatchDebuggerTree.setWatchNodeText(node, text);
- comboBox.addRecent(text);
+ if (!text.isEmpty()) {
+ WatchDebuggerTree.setWatchNodeText(node, text);
+ comboBox.addRecent(text);
+ }
+ else {
+ getWatchTree().removeWatch(node);
+ }
try {
super.doOKAction();
}
@@ -196,6 +201,9 @@
public void cancelEditing() {
comboBox.setPopupVisible(false);
+ if (((WatchItemDescriptor)node.getDescriptor()).getEvaluationText().isEmpty()) {
+ getWatchTree().removeWatch(node);
+ }
try {
super.cancelEditing();
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java b/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java
index d9f7c18..e62dfbd 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/impl/TipManager.java
@@ -153,7 +153,7 @@
}
private boolean isInsideComponent(final MouseEvent e) {
- final Rectangle compBounds = myComponent.getBounds();
+ final Rectangle compBounds = myComponent.getVisibleRect();
final Point compPoint = SwingUtilities.convertPoint(e.getComponent(), e.getPoint(), myComponent);
return compBounds.contains(compPoint);
diff --git a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ExpressionChildrenRenderer.java b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ExpressionChildrenRenderer.java
index b902b5b..182fe27 100644
--- a/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ExpressionChildrenRenderer.java
+++ b/java/debugger/impl/src/com/intellij/debugger/ui/tree/render/ExpressionChildrenRenderer.java
@@ -81,11 +81,7 @@
evaluationContext.createEvaluationContext(value), parentDescriptor
);
- NodeRenderer renderer = getLastChildrenRenderer(parentDescriptor);
- if (renderer == null || childrenValue == null || !renderer.isApplicable(childrenValue.type())) {
- renderer = DebugProcessImpl.getDefaultRenderer(childrenValue != null ? childrenValue.type() : null);
- parentDescriptor.putUserData(LAST_CHILDREN_RENDERER, renderer);
- }
+ NodeRenderer renderer = getChildrenRenderer(childrenValue, parentDescriptor);
renderer.buildChildren(childrenValue, builder, evaluationContext);
}
catch (final EvaluateException e) {
@@ -141,12 +137,21 @@
throw EvaluateExceptionUtil.createEvaluateException(DebuggerBundle.message("error.unable.to.evaluate.expression"));
}
- ChildrenRenderer defaultChildrenRenderer = ((DebugProcessImpl)context.getDebugProcess()).getDefaultRenderer(expressionValue.type());
+ NodeRenderer childrenRenderer = getChildrenRenderer(expressionValue, descriptor);
return DebuggerUtils.getInstance().substituteThis(
- defaultChildrenRenderer.getChildValueExpression(node, context),
- (PsiExpression)myChildrenExpression.getPsiExpression(node.getProject()).copy(),
- expressionValue, context);
+ childrenRenderer.getChildValueExpression(node, context),
+ (PsiExpression)myChildrenExpression.getPsiExpression(node.getProject()).copy(),
+ expressionValue, context);
+ }
+
+ private NodeRenderer getChildrenRenderer(Value childrenValue, ValueDescriptor parentDescriptor) {
+ NodeRenderer renderer = getLastChildrenRenderer(parentDescriptor);
+ if (renderer == null || childrenValue == null || !renderer.isApplicable(childrenValue.type())) {
+ renderer = DebugProcessImpl.getDefaultRenderer(childrenValue != null ? childrenValue.type() : null);
+ setPreferableChildrenRenderer(parentDescriptor, renderer);
+ }
+ return renderer;
}
public boolean isExpandable(Value value, final EvaluationContext context, NodeDescriptor parentDescriptor) {
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
index c9f5735..a670584 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointAdapter.java
@@ -15,6 +15,8 @@
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");
@@ -26,6 +28,35 @@
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) {
@@ -60,6 +91,10 @@
changed = true;
}
+ if (applyFilters(jBreakpoint, breakpoint)) {
+ changed = true;
+ }
+
if (jBreakpoint.getSourcePosition().getLine() != breakpoint.getLine()) {
jBreakpoint.reload();
changed = true;
@@ -101,6 +136,7 @@
}
};
+ lineBreakpoint.setVisible(false);
lineBreakpoint.init();
return lineBreakpoint;
}
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointProperties.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointProperties.java
new file mode 100644
index 0000000..e2f3202
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointProperties.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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;
+
+import com.intellij.debugger.InstanceFilter;
+import com.intellij.ui.classFilter.ClassFilter;
+import com.intellij.xdebugger.breakpoints.XBreakpointProperties;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author egor
+ */
+public class JavaBreakpointProperties extends XBreakpointProperties<JavaBreakpointProperties> {
+ public boolean COUNT_FILTER_ENABLED = false;
+ public int COUNT_FILTER = 0;
+
+ public boolean CLASS_FILTERS_ENABLED = false;
+ private ClassFilter[] myClassFilters;
+ private ClassFilter[] myClassExclusionFilters;
+
+ public boolean INSTANCE_FILTERS_ENABLED = false;
+ private InstanceFilter[] myInstanceFilters;
+
+ public InstanceFilter[] getInstanceFilters() {
+ return myInstanceFilters != null ? myInstanceFilters : InstanceFilter.EMPTY_ARRAY;
+ }
+
+ public void setInstanceFilters(InstanceFilter[] instanceFilters) {
+ myInstanceFilters = instanceFilters;
+ }
+
+ 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 != null ? myClassFilters : ClassFilter.EMPTY_ARRAY;
+ }
+
+ public final void setClassFilters(ClassFilter[] classFilters) {
+ myClassFilters = classFilters;
+ }
+
+ public ClassFilter[] getClassExclusionFilters() {
+ return myClassExclusionFilters != null ? myClassExclusionFilters : ClassFilter.EMPTY_ARRAY;
+ }
+
+ public void setClassExclusionFilters(ClassFilter[] classExclusionFilters) {
+ myClassExclusionFilters = classExclusionFilters;
+ }
+
+ @Nullable
+ @Override
+ public JavaBreakpointProperties getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(JavaBreakpointProperties 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;
+
+ INSTANCE_FILTERS_ENABLED = state.INSTANCE_FILTERS_ENABLED;
+ myInstanceFilters = state.myInstanceFilters;
+ }
+}
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.form b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.form
new file mode 100644
index 0000000..db560b3
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.form
@@ -0,0 +1,168 @@
+<?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">
+ <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>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="5736" binding="myConditionsPanel" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="7">
+ <margin top="2" left="2" bottom="5" right="5"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <clientProperties>
+ <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
+ </clientProperties>
+ <border type="etched" title-resource-bundle="messages/DebuggerBundle" title-key="label.breakpoint.properties.panel.group.conditions"/>
+ <children>
+ <grid id="8e867" binding="myInstanceFiltersPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="17e11" class="javax.swing.JCheckBox" binding="myInstanceFiltersCheckBox">
+ <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>
+ <margin top="2" left="2" bottom="0" right="2"/>
+ <text resource-bundle="messages/DebuggerBundle" key="breakpoint.properties.panel.option.instance.filters"/>
+ </properties>
+ </component>
+ <grid id="5231f" layout-manager="GridLayoutManager" row-count="1" 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="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <hspacer id="eeee7">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="15" height="-1"/>
+ </grid>
+ </constraints>
+ </hspacer>
+ <xy id="28068" binding="myInstanceFiltersFieldPanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </xy>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <grid id="25884" binding="myClassFiltersPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
+ <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="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="729d5" class="javax.swing.JCheckBox" binding="myClassFiltersCheckBox">
+ <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>
+ <margin top="2" left="2" bottom="0" right="2"/>
+ <text resource-bundle="messages/DebuggerBundle" key="breakpoint.properties.panel.option.class.filters"/>
+ </properties>
+ </component>
+ <grid id="9bef6" layout-manager="GridLayoutManager" row-count="1" 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="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <xy id="e3d10" binding="myClassFiltersFieldPanel" layout-manager="XYLayout" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </xy>
+ <hspacer id="ec2a">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="15" height="-1"/>
+ </grid>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <grid id="275ca" binding="myPassCountPanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="0">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <grid row="2" 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>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="27bbc" class="javax.swing.JCheckBox" binding="myPassCountCheckbox">
+ <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>
+ <margin top="2" left="2" bottom="0" right="2"/>
+ <text resource-bundle="messages/DebuggerBundle" key="breakpoint.properties.panel.option.pass.count"/>
+ </properties>
+ </component>
+ <grid id="71095" layout-manager="GridLayoutManager" row-count="1" 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="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="33fef" class="javax.swing.JTextField" binding="myPassCountField">
+ <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="15" height="-1"/>
+ </grid>
+ </constraints>
+ <properties>
+ <enabled value="false"/>
+ <horizontalAlignment value="10"/>
+ </properties>
+ </component>
+ <hspacer id="28e6f">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="15" height="-1"/>
+ </grid>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <vspacer id="d1c29">
+ <constraints>
+ <grid row="3" 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>
+ </children>
+ </grid>
+ </children>
+ </grid>
+</form>
diff --git a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.java b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.java
new file mode 100644
index 0000000..e575973
--- /dev/null
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointPropertiesPanel.java
@@ -0,0 +1,402 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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;
+
+import com.intellij.debugger.InstanceFilter;
+import com.intellij.debugger.ui.breakpoints.EditClassFiltersDialog;
+import com.intellij.debugger.ui.breakpoints.EditInstanceFiltersDialog;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.ui.FieldPanel;
+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.ui.XBreakpointCustomPropertiesPanel;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * @author egor
+ */
+public class JavaBreakpointPropertiesPanel extends XBreakpointCustomPropertiesPanel<XLineBreakpoint<XBreakpointProperties>> {
+ private JPanel myConditionsPanel;
+ private JPanel myInstanceFiltersPanel;
+ private JCheckBox myInstanceFiltersCheckBox;
+ private JPanel myInstanceFiltersFieldPanel;
+ private JPanel myClassFiltersPanel;
+ private JCheckBox myClassFiltersCheckBox;
+ private JPanel myClassFiltersFieldPanel;
+ private JPanel myPassCountPanel;
+ private JCheckBox myPassCountCheckbox;
+ private JTextField myPassCountField;
+
+ private final FieldPanel myInstanceFiltersField;
+ private final FieldPanel myClassFiltersField;
+
+ private ClassFilter[] myClassFilters = ClassFilter.EMPTY_ARRAY;
+ private ClassFilter[] myClassExclusionFilters = ClassFilter.EMPTY_ARRAY;
+ private InstanceFilter[] myInstanceFilters = InstanceFilter.EMPTY_ARRAY;
+ protected final Project myProject;
+
+ private PsiClass myBreakpointPsiClass;
+
+ public JavaBreakpointPropertiesPanel(Project project) {
+ myProject = project;
+ myInstanceFiltersField = new FieldPanel(new MyTextField(), "", null,
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reloadInstanceFilters();
+ EditInstanceFiltersDialog _dialog = new EditInstanceFiltersDialog(myProject);
+ _dialog.setFilters(myInstanceFilters);
+ _dialog.show();
+ if (_dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
+ myInstanceFilters = _dialog.getFilters();
+ updateInstanceFilterEditor(true);
+ }
+ }
+ },
+ null
+ );
+
+ myClassFiltersField = new FieldPanel(new MyTextField(), "", null,
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ reloadClassFilters();
+
+ com.intellij.ide.util.ClassFilter classFilter = createClassConditionFilter();
+
+ EditClassFiltersDialog _dialog = new EditClassFiltersDialog(myProject, classFilter);
+ _dialog.setFilters(myClassFilters, myClassExclusionFilters);
+ _dialog.show();
+ if (_dialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
+ myClassFilters = _dialog.getFilters();
+ myClassExclusionFilters = _dialog.getExclusionFilters();
+ updateClassFilterEditor(true);
+ }
+ }
+ },
+ null
+ );
+
+ ActionListener updateListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ updateCheckboxes();
+ }
+ };
+
+ myPassCountCheckbox.addActionListener(updateListener);
+ myInstanceFiltersCheckBox.addActionListener(updateListener);
+ myClassFiltersCheckBox.addActionListener(updateListener);
+
+ ToolTipManager.sharedInstance().registerComponent(myClassFiltersField.getTextField());
+ ToolTipManager.sharedInstance().registerComponent(myInstanceFiltersField.getTextField());
+
+ insert(myInstanceFiltersFieldPanel, myInstanceFiltersField);
+ insert(myClassFiltersFieldPanel, myClassFiltersField);
+
+ DebuggerUIUtil.focusEditorOnCheck(myPassCountCheckbox, myPassCountField);
+ DebuggerUIUtil.focusEditorOnCheck(myInstanceFiltersCheckBox, myInstanceFiltersField.getTextField());
+ DebuggerUIUtil.focusEditorOnCheck(myClassFiltersCheckBox, myClassFiltersField.getTextField());
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myConditionsPanel;
+ }
+
+ @Override
+ public boolean isVisibleOnPopup(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
+ JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
+ if (properties != null) {
+ return properties.COUNT_FILTER_ENABLED || properties.CLASS_FILTERS_ENABLED || properties.INSTANCE_FILTERS_ENABLED;
+ }
+ return false;
+ }
+
+ @Override
+ public void saveTo(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
+ JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
+ if (properties == null) {
+ return;
+ }
+
+ try {
+ String text = myPassCountField.getText().trim();
+ properties.COUNT_FILTER = !text.isEmpty() ? Integer.parseInt(text) : 0;
+ if (properties.COUNT_FILTER < 0) {
+ properties.COUNT_FILTER = 0;
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ properties.COUNT_FILTER_ENABLED = properties.COUNT_FILTER > 0 && myPassCountCheckbox.isSelected();
+ reloadInstanceFilters();
+ reloadClassFilters();
+ updateInstanceFilterEditor(true);
+ updateClassFilterEditor(true);
+
+ properties.INSTANCE_FILTERS_ENABLED = myInstanceFiltersField.getText().length() > 0 && myInstanceFiltersCheckBox.isSelected();
+ properties.CLASS_FILTERS_ENABLED = myClassFiltersField.getText().length() > 0 && myClassFiltersCheckBox.isSelected();
+ properties.setClassFilters(myClassFilters);
+ properties.setClassExclusionFilters(myClassExclusionFilters);
+ properties.setInstanceFilters(myInstanceFilters);
+ }
+
+ private static void insert(JPanel panel, JComponent component) {
+ panel.setLayout(new BorderLayout());
+ panel.add(component, BorderLayout.CENTER);
+ }
+
+ @Override
+ public void loadFrom(@NotNull XLineBreakpoint<XBreakpointProperties> breakpoint) {
+ JavaBreakpointProperties properties = (JavaBreakpointProperties)breakpoint.getProperties();
+ if (properties != null) {
+ if (properties.COUNT_FILTER > 0) {
+ myPassCountField.setText(Integer.toString(properties.COUNT_FILTER));
+ }
+ else {
+ myPassCountField.setText("");
+ }
+
+ myPassCountCheckbox.setSelected(properties.COUNT_FILTER_ENABLED);
+
+ myInstanceFiltersCheckBox.setSelected(properties.INSTANCE_FILTERS_ENABLED);
+ myInstanceFiltersField.setEnabled(properties.INSTANCE_FILTERS_ENABLED);
+ myInstanceFiltersField.getTextField().setEditable(properties.INSTANCE_FILTERS_ENABLED);
+ myInstanceFilters = properties.getInstanceFilters();
+ updateInstanceFilterEditor(true);
+
+ myClassFiltersCheckBox.setSelected(properties.CLASS_FILTERS_ENABLED);
+ myClassFiltersField.setEnabled(properties.CLASS_FILTERS_ENABLED);
+ myClassFiltersField.getTextField().setEditable(properties.CLASS_FILTERS_ENABLED);
+ myClassFilters = properties.getClassFilters();
+ myClassExclusionFilters = properties.getClassExclusionFilters();
+ updateClassFilterEditor(true);
+
+ XSourcePosition position = breakpoint.getSourcePosition();
+ // TODO: need to calculate psi class
+ //myBreakpointPsiClass = breakpoint.getPsiClass();
+ }
+ updateCheckboxes();
+ }
+
+ private void updateInstanceFilterEditor(boolean updateText) {
+ List<String> filters = new ArrayList<String>();
+ for (InstanceFilter instanceFilter : myInstanceFilters) {
+ if (instanceFilter.isEnabled()) {
+ filters.add(Long.toString(instanceFilter.getId()));
+ }
+ }
+ if (updateText) {
+ myInstanceFiltersField.setText(StringUtil.join(filters, " "));
+ }
+
+ String tipText = concatWithEx(filters, " ", (int)Math.sqrt(myInstanceFilters.length) + 1, "\n");
+ myInstanceFiltersField.getTextField().setToolTipText(tipText);
+ }
+
+ private class MyTextField extends JTextField {
+ public MyTextField() {
+ }
+
+ @Override
+ public String getToolTipText(MouseEvent event) {
+ reloadClassFilters();
+ updateClassFilterEditor(false);
+ reloadInstanceFilters();
+ updateInstanceFilterEditor(false);
+ String toolTipText = super.getToolTipText(event);
+ return getToolTipText().length() == 0 ? null : toolTipText;
+ }
+
+ @Override
+ public JToolTip createToolTip() {
+ JToolTip toolTip = new JToolTip(){{
+ setUI(new MultiLineTooltipUI());
+ }};
+ toolTip.setComponent(this);
+ return toolTip;
+ }
+ }
+
+ private void reloadClassFilters() {
+ String filtersText = myClassFiltersField.getText();
+
+ ArrayList<ClassFilter> classFilters = new ArrayList<ClassFilter>();
+ ArrayList<ClassFilter> exclusionFilters = new ArrayList<ClassFilter>();
+ int startFilter = -1;
+ for(int i = 0; i <= filtersText.length(); i++) {
+ if(i < filtersText.length() && !Character.isWhitespace(filtersText.charAt(i))){
+ if(startFilter == -1) {
+ startFilter = i;
+ }
+ }
+ else {
+ if(startFilter >=0) {
+ if(filtersText.charAt(startFilter) == '-') {
+ exclusionFilters.add(new ClassFilter(filtersText.substring(startFilter + 1, i)));
+ }
+ else {
+ classFilters.add(new ClassFilter(filtersText.substring(startFilter, i)));
+ }
+ startFilter = -1;
+ }
+ }
+ }
+ for (ClassFilter classFilter : myClassFilters) {
+ if (!classFilter.isEnabled()) {
+ classFilters.add(classFilter);
+ }
+ }
+ for (ClassFilter classFilter : myClassExclusionFilters) {
+ if (!classFilter.isEnabled()) {
+ exclusionFilters.add(classFilter);
+ }
+ }
+ myClassFilters = classFilters .toArray(new ClassFilter[classFilters .size()]);
+ myClassExclusionFilters = exclusionFilters.toArray(new ClassFilter[exclusionFilters.size()]);
+ }
+
+ private void reloadInstanceFilters() {
+ String filtersText = myInstanceFiltersField.getText();
+
+ ArrayList<InstanceFilter> idxs = new ArrayList<InstanceFilter>();
+ int startNumber = -1;
+ for(int i = 0; i <= filtersText.length(); i++) {
+ if(i < filtersText.length() && Character.isDigit(filtersText.charAt(i))) {
+ if(startNumber == -1) {
+ startNumber = i;
+ }
+ }
+ else {
+ if(startNumber >=0) {
+ idxs.add(InstanceFilter.create(filtersText.substring(startNumber, i)));
+ startNumber = -1;
+ }
+ }
+ }
+ for (InstanceFilter instanceFilter : myInstanceFilters) {
+ if (!instanceFilter.isEnabled()) {
+ idxs.add(instanceFilter);
+ }
+ }
+ myInstanceFilters = idxs.toArray(new InstanceFilter[idxs.size()]);
+ }
+
+ private void updateClassFilterEditor(boolean updateText) {
+ List<String> filters = new ArrayList<String>();
+ for (ClassFilter classFilter : myClassFilters) {
+ if (classFilter.isEnabled()) {
+ filters.add(classFilter.getPattern());
+ }
+ }
+ List<String> excludeFilters = new ArrayList<String>();
+ for (ClassFilter classFilter : myClassExclusionFilters) {
+ if (classFilter.isEnabled()) {
+ excludeFilters.add("-" + classFilter.getPattern());
+ }
+ }
+ if (updateText) {
+ String editorText = StringUtil.join(filters, " ");
+ if(!filters.isEmpty()) {
+ editorText += " ";
+ }
+ editorText += StringUtil.join(excludeFilters, " ");
+ myClassFiltersField.setText(editorText);
+ }
+
+ int width = (int)Math.sqrt(myClassExclusionFilters.length + myClassFilters.length) + 1;
+ String tipText = concatWithEx(filters, " ", width, "\n");
+ if(!filters.isEmpty()) {
+ tipText += "\n";
+ }
+ tipText += concatWithEx(excludeFilters, " ", width, "\n");
+ myClassFiltersField.getTextField().setToolTipText(tipText);
+ }
+
+ private static String concatWithEx(List<String> s, String concator, int N, String NthConcator) {
+ String result = "";
+ int i = 1;
+ for (Iterator iterator = s.iterator(); iterator.hasNext(); i++) {
+ String str = (String) iterator.next();
+ result += str;
+ if(iterator.hasNext()){
+ if(i % N == 0){
+ result += NthConcator;
+ }
+ else {
+ result += concator;
+ }
+ }
+ }
+ return result;
+ }
+
+ protected com.intellij.ide.util.ClassFilter createClassConditionFilter() {
+ com.intellij.ide.util.ClassFilter classFilter;
+ if(myBreakpointPsiClass != null) {
+ classFilter = new com.intellij.ide.util.ClassFilter() {
+ @Override
+ public boolean isAccepted(PsiClass aClass) {
+ return myBreakpointPsiClass == aClass || aClass.isInheritor(myBreakpointPsiClass, true);
+ }
+ };
+ }
+ else {
+ classFilter = null;
+ }
+ return classFilter;
+ }
+
+ protected void updateCheckboxes() {
+ boolean passCountApplicable = true;
+ if (myInstanceFiltersCheckBox.isSelected() || myClassFiltersCheckBox.isSelected()) {
+ passCountApplicable = false;
+ }
+ myPassCountCheckbox.setEnabled(passCountApplicable);
+
+ final boolean passCountSelected = myPassCountCheckbox.isSelected();
+ myInstanceFiltersCheckBox.setEnabled(!passCountSelected);
+ myClassFiltersCheckBox.setEnabled(!passCountSelected);
+
+ myPassCountField.setEditable(myPassCountCheckbox.isSelected());
+ myPassCountField.setEnabled (myPassCountCheckbox.isSelected());
+
+ myInstanceFiltersField.setEnabled(myInstanceFiltersCheckBox.isSelected());
+ myInstanceFiltersField.getTextField().setEditable(myInstanceFiltersCheckBox.isSelected());
+
+ myClassFiltersField.setEnabled(myClassFiltersCheckBox.isSelected());
+ myClassFiltersField.getTextField().setEditable(myClassFiltersCheckBox.isSelected());
+ }
+}
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
index 00b7549..5e55a49 100644
--- a/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointType.java
+++ b/java/debugger/impl/src/org/jetbrains/java/debugger/breakpoints/JavaBreakpointType.java
@@ -13,6 +13,7 @@
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;
@@ -52,4 +53,24 @@
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/openapi/src/com/intellij/debugger/DebuggerBundle.java b/java/debugger/openapi/src/com/intellij/debugger/DebuggerBundle.java
index 179cf4a..17f7799 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/DebuggerBundle.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/DebuggerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import com.intellij.execution.configurations.RemoteConnection;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -25,8 +26,12 @@
import java.util.ResourceBundle;
public class DebuggerBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.DebuggerBundle";
private DebuggerBundle() {
@@ -40,13 +45,8 @@
return connection.isUseSockets() ? message("transport.name.socket") : message("transport.name.shared.memory");
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
index e2f93e7..64a7407 100644
--- a/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
+++ b/java/debugger/openapi/src/com/intellij/debugger/engine/DebuggerUtils.java
@@ -274,13 +274,17 @@
return getSuperTypeInt(subType, superType);
}
+ private static boolean typeEquals(Type type, String typeName) {
+ return type.name().replace('$', '.').equals(typeName.replace('$', '.'));
+ }
+
private static Type getSuperTypeInt(Type subType, String superType) {
Type result;
if (subType == null) {
return null;
}
- if (subType.name().equals(superType)) {
+ if (typeEquals(subType, superType)) {
return subType;
}
@@ -293,7 +297,7 @@
List ifaces = ((ClassType)subType).allInterfaces();
for (Object iface : ifaces) {
InterfaceType interfaceType = (InterfaceType)iface;
- if (interfaceType.name().equals(superType)) {
+ if (typeEquals(interfaceType, superType)) {
return interfaceType;
}
}
@@ -390,7 +394,9 @@
}
final PsiClass aClass =
JavaPsiFacade.getInstance(psiManager.getProject()).findClass(className.replace('$', '.'), GlobalSearchScope.allScope(project));
- return JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(aClass);
+ if (aClass != null) {
+ return JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createType(aClass);
+ }
}
catch (IncorrectOperationException e) {
LOG.error(e);
diff --git a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
index 76b093a..d472761 100644
--- a/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
+++ b/java/execution/impl/src/com/intellij/execution/impl/DefaultJavaProgramRunner.java
@@ -15,7 +15,10 @@
*/
package com.intellij.execution.impl;
-import com.intellij.execution.*;
+import com.intellij.execution.ExecutionBundle;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.RunnerRegistry;
import com.intellij.execution.configurations.*;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.CapturingProcessAdapter;
@@ -66,10 +69,10 @@
}
@Override
- protected RunContentDescriptor doExecute(final Project project,
- final RunProfileState state,
+ protected RunContentDescriptor doExecute(@NotNull final Project project,
+ @NotNull final RunProfileState state,
final RunContentDescriptor contentToReuse,
- final ExecutionEnvironment env) throws ExecutionException {
+ @NotNull final ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
ExecutionResult executionResult;
diff --git a/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java b/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java
index f56bbab..4463e3e 100644
--- a/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java
+++ b/java/execution/impl/src/com/intellij/execution/junit/InheritorChooser.java
@@ -17,6 +17,7 @@
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
+import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.ide.util.PsiClassListCellRenderer;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
@@ -63,7 +64,10 @@
if (aClass != null && !aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return false;
}
+ } else if (location instanceof PsiMemberParameterizedLocation) {
+ return false;
}
+
final List<PsiClass> classes = new ArrayList<PsiClass>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
@Override
diff --git a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java
index 74524ca..e4de6db 100644
--- a/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java
+++ b/java/execution/impl/src/com/intellij/execution/junit/JUnitUtil.java
@@ -49,10 +49,10 @@
@NonNls public static final String SUITE_METHOD_NAME = "suite";
public static final String BEFORE_ANNOTATION_NAME = "org.junit.Before";
public static final String AFTER_ANNOTATION_NAME = "org.junit.After";
- private static final String PARAMETRIZED_PARAMETERS_ANNOTATION_NAME = "org.junit.runners.Parameterized.Parameters";
+ public static final String PARAMETRIZED_PARAMETERS_ANNOTATION_NAME = "org.junit.runners.Parameterized.Parameters";
private static final String AFTER_CLASS_ANNOTATION_NAME = "org.junit.AfterClass";
private static final String BEFORE_CLASS_ANNOTATION_NAME = "org.junit.BeforeClass";
- private static final String PARAMETERIZED_CLASS_NAME = "org.junit.runners.Parameterized";
+ public static final String PARAMETERIZED_CLASS_NAME = "org.junit.runners.Parameterized";
public static boolean isSuiteMethod(@NotNull PsiMethod psiMethod) {
if (!psiMethod.hasModifierProperty(PsiModifier.PUBLIC)) return false;
diff --git a/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java b/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java
new file mode 100644
index 0000000..ea67cab
--- /dev/null
+++ b/java/execution/impl/src/com/intellij/execution/junit2/PsiMemberParameterizedLocation.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.execution.junit2;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.execution.Location;
+import com.intellij.execution.PsiLocation;
+import com.intellij.execution.junit.JUnitUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+
+public class PsiMemberParameterizedLocation extends PsiLocation<PsiElement> {
+ private final PsiClass myContainingClass;
+ private final String myParamSetName;
+
+ public PsiMemberParameterizedLocation(@NotNull Project project,
+ @NotNull PsiElement psiElement,
+ @Nullable PsiClass containingClass,
+ String paramSetName) {
+ super(project, psiElement);
+ myContainingClass = containingClass;
+ myParamSetName = paramSetName;
+ }
+
+ public static Location getParameterizedLocation(PsiClass psiClass, String paramSetName) {
+ return getParameterizedLocation(psiClass, paramSetName, JUnitUtil.PARAMETERIZED_CLASS_NAME);
+ }
+
+ public static Location getParameterizedLocation(PsiClass psiClass,
+ String paramSetName,
+ String parameterizedClassName) {
+ final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(psiClass, Collections.singleton(JUnitUtil.RUN_WITH));
+ if (annotation != null) {
+ final PsiAnnotationMemberValue attributeValue = annotation.findAttributeValue("value");
+ if (attributeValue instanceof PsiClassObjectAccessExpression) {
+ final PsiTypeElement operand = ((PsiClassObjectAccessExpression)attributeValue).getOperand();
+ if (InheritanceUtil.isInheritor(operand.getType(), parameterizedClassName)) {
+ return new PsiMemberParameterizedLocation(psiClass.getProject(),
+ psiClass,
+ null,
+ paramSetName);
+ }
+ }
+ }
+ return null;
+ }
+
+ public String getParamSetName() {
+ return myParamSetName;
+ }
+
+ public PsiClass getContainingClass() {
+ return myContainingClass;
+ }
+}
diff --git a/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java b/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java
index db2f5df..5259663 100644
--- a/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java
+++ b/java/execution/impl/src/com/intellij/execution/runners/ProcessProxyImpl.java
@@ -17,13 +17,13 @@
import com.intellij.execution.process.ProcessHandler;
import com.intellij.openapi.util.Key;
+import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NonNls;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
-import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
@@ -37,7 +37,6 @@
@NonNls public static final String PROPERTY_PORT_NUMBER = "idea.launcher.port";
@NonNls public static final String LAUNCH_MAIN_CLASS = "com.intellij.rt.execution.application.AppMain";
- @NonNls protected static final String LOCALHOST = "localhost";
@NonNls private static final String DONT_USE_LAUNCHER_PROPERTY = "idea.no.launcher";
private static final int SOCKET_NUMBER_START = 7532;
private static final int SOCKET_NUMBER = 100;
@@ -71,10 +70,12 @@
return -1;
}
+ @Override
public int getPortNumber() {
return myPortNumber;
}
+ @Override
@SuppressWarnings("FinalizeDeclaration")
protected synchronized void finalize() throws Throwable {
if (myWriter != null) {
@@ -84,6 +85,7 @@
super.finalize();
}
+ @Override
public void attach(final ProcessHandler processHandler) {
processHandler.putUserData(KEY, this);
}
@@ -93,7 +95,7 @@
if (myWriter == null) {
try {
if (mySocket == null) {
- mySocket = new Socket(InetAddress.getByName(LOCALHOST), myPortNumber);
+ mySocket = new Socket(NetUtils.getLoopbackAddress(), myPortNumber);
}
myWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(mySocket.getOutputStream())));
}
@@ -105,10 +107,12 @@
myWriter.flush();
}
+ @Override
public void sendBreak() {
writeLine("BREAK");
}
+ @Override
public void sendStop() {
writeLine("STOP");
}
diff --git a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
index 0e06157..53861de 100644
--- a/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
+++ b/java/execution/openapi/src/com/intellij/execution/JavaExecutionUtil.java
@@ -184,7 +184,7 @@
return name == null || name.startsWith(ExecutionBundle.message("run.configuration.unnamed.name.prefix"));
}
- public static Location stepIntoSingleClass(final Location location) {
+ public static Location stepIntoSingleClass(@NotNull final Location location) {
PsiElement element = location.getPsiElement();
if (!(element instanceof PsiClassOwner)) {
if (PsiTreeUtil.getParentOfType(element, PsiClass.class) != null) return location;
diff --git a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java
index 88fa616..9b42c38 100644
--- a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java
+++ b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionExFilterFactory.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.psi.*;
@@ -38,16 +39,17 @@
* @author gregsh
*/
public class ExceptionExFilterFactory implements ExceptionFilterFactory {
+ @NotNull
@Override
- public Filter create(GlobalSearchScope searchScope) {
+ public Filter create(@NotNull GlobalSearchScope searchScope) {
return new MyFilter(searchScope);
}
private static class MyFilter implements Filter, FilterMixin {
- private final GlobalSearchScope myScope;
+ private final ExceptionInfoCache myCache;
public MyFilter(@NotNull final GlobalSearchScope scope) {
- myScope = scope;
+ myCache = new ExceptionInfoCache(scope);
}
public Result applyFilter(final String line, final int textEndOffset) {
@@ -67,7 +69,7 @@
Map<String, Trinity<TextRange, TextRange, TextRange>> visited = new THashMap<String, Trinity<TextRange, TextRange, TextRange>>();
final Trinity<TextRange, TextRange, TextRange> emptyInfo = Trinity.create(null, null, null);
- final ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope);
+ final ExceptionWorker worker = new ExceptionWorker(myCache);
for (int i = 0; i < copiedFragment.getLineCount(); i++) {
final int lineStartOffset = copiedFragment.getLineStartOffset(i);
final int lineEndOffset = copiedFragment.getLineEndOffset(i);
@@ -84,10 +86,16 @@
worker.execute(text, lineEndOffset);
Result result = worker.getResult();
if (result == null) continue;
- OpenFileHyperlinkInfo hyperlinkInfo = ExceptionWorker.getOpenFileHyperlinkInfo(result);
- int offset = hyperlinkInfo == null? -1 : hyperlinkInfo.getDescriptor().getOffset();
+ HyperlinkInfo hyperlinkInfo = result.hyperlinkInfo;
+ if (!(hyperlinkInfo instanceof FileHyperlinkInfo)) continue;
+
+ OpenFileDescriptor descriptor = ((FileHyperlinkInfo)hyperlinkInfo).getDescriptor();
+ if (descriptor == null) continue;
+
+ int offset = descriptor.getOffset();
PsiFile psiFile = worker.getFile();
if (offset <= 0 || psiFile == null) continue;
+
PsiElement element = psiFile.findElementAt(offset);
PsiTryStatement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, true, PsiClass.class);
PsiCodeBlock tryBlock = parent != null? parent.getTryBlock() : null;
diff --git a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java
index 38a8a01..24b2bb2 100644
--- a/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java
+++ b/java/execution/openapi/src/com/intellij/execution/filters/ExceptionFilter.java
@@ -20,14 +20,14 @@
import org.jetbrains.annotations.NotNull;
public class ExceptionFilter implements Filter, DumbAware {
- private final GlobalSearchScope myScope;
+ private final ExceptionInfoCache myCache;
public ExceptionFilter(@NotNull final GlobalSearchScope scope) {
- myScope = scope;
+ myCache = new ExceptionInfoCache(scope);
}
public Result applyFilter(final String line, final int textEndOffset) {
- ExceptionWorker worker = new ExceptionWorker(myScope.getProject(), myScope);
+ ExceptionWorker worker = new ExceptionWorker(myCache);
worker.execute(line, textEndOffset);
return worker.getResult();
}
diff --git a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java
index 2683d21..178c855 100644
--- a/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java
+++ b/java/idea-ui/src/com/intellij/codeInsight/daemon/impl/SetupSDKNotificationProvider.java
@@ -25,10 +25,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.roots.ModuleRootAdapter;
-import com.intellij.openapi.roots.ModuleRootEvent;
-import com.intellij.openapi.roots.ModuleRootModificationUtil;
-import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
@@ -74,7 +71,13 @@
return null;
}
- if (ProjectRootManager.getInstance(myProject).getProjectSdk() != null) {
+ Module module = ModuleUtilCore.findModuleForPsiElement(psiFile);
+ if (module == null) {
+ return null;
+ }
+
+ Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
+ if (sdk != null) {
return null;
}
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java
index a205e45..dd9079e 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/EditLibraryDialog.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.ui.FormBuilder;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -74,4 +75,10 @@
}
super.doOKAction();
}
+
+ @Nullable
+ @Override
+ protected String getHelpId() {
+ return "Edit_Library_dialog";
+ }
}
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java
index 0bb6900..63ba7de 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FacetLibrariesValidatorImpl.java
@@ -117,7 +117,7 @@
private CustomLibraryDescription myDescription;
public LibrariesQuickFix(CustomLibraryDescription description) {
- super(IdeBundle.message("missing.libraries.fix.button"));
+ super(IdeBundle.message("button.fix"));
myDescription = description;
}
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java
index 95f012e..be22534 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/FrameworkLibraryValidatorImpl.java
@@ -73,7 +73,7 @@
private CustomLibraryDescription myDescription;
public LibrariesQuickFix(CustomLibraryDescription description) {
- super(IdeBundle.message("missing.libraries.fix.button"));
+ super(IdeBundle.message("button.fix"));
myDescription = description;
}
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java
index 52d5358..d71e184 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryCompositionSettings.java
@@ -29,6 +29,7 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.NotNullComputable;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,8 +44,8 @@
*/
public class LibraryCompositionSettings implements Disposable {
private final CustomLibraryDescription myLibraryDescription;
+ @NotNull private final NotNullComputable<String> myPathProvider;
private FrameworkLibraryVersionFilter myVersionFilter;
- private String myBaseDirectoryPath;
private final List<? extends FrameworkLibraryVersion> myAllVersions;
private LibrariesContainer.LibraryLevel myNewLibraryLevel;
private NewLibraryEditor myNewLibraryEditor;
@@ -56,13 +57,13 @@
private FrameworkLibraryProvider myLibraryProvider;
public LibraryCompositionSettings(final @NotNull CustomLibraryDescription libraryDescription,
- final @NotNull String baseDirectoryPath,
+ final @NotNull NotNullComputable<String> pathProvider,
@NotNull FrameworkLibraryVersionFilter versionFilter,
final List<? extends FrameworkLibraryVersion> allVersions) {
myLibraryDescription = libraryDescription;
+ myPathProvider = pathProvider;
myVersionFilter = versionFilter;
myNewLibraryLevel = libraryDescription.getDefaultLevel();
- myBaseDirectoryPath = baseDirectoryPath;
myAllVersions = allVersions;
final List<? extends FrameworkLibraryVersion> versions = getCompatibleVersions();
if (!versions.isEmpty()) {
@@ -72,7 +73,7 @@
private LibraryDownloadSettings createDownloadSettings(final FrameworkLibraryVersion version) {
return new LibraryDownloadSettings(version, myLibraryDescription.getDownloadableLibraryType(),
- myNewLibraryLevel, getDefaultDownloadPath(myBaseDirectoryPath));
+ myNewLibraryLevel, getDefaultDownloadPath(getBaseDirectoryPath()));
}
public void setVersionFilter(@NotNull FrameworkLibraryVersionFilter versionFilter) {
@@ -99,7 +100,7 @@
}
private static String getDefaultDownloadPath(@NotNull String baseDirectoryPath) {
- return baseDirectoryPath + "/lib";
+ return baseDirectoryPath.isEmpty() ? "lib" : baseDirectoryPath + "/lib";
}
public void setDownloadSettings(LibraryDownloadSettings downloadSettings) {
@@ -128,17 +129,7 @@
@NotNull
public String getBaseDirectoryPath() {
- return myBaseDirectoryPath;
- }
-
- public void changeBaseDirectoryPath(@NotNull String baseDirectoryPath) {
- if (!myBaseDirectoryPath.equals(baseDirectoryPath)) {
- if (myDownloadSettings != null &&
- myDownloadSettings.getDirectoryForDownloadedLibrariesPath().equals(getDefaultDownloadPath(myBaseDirectoryPath))) {
- myDownloadSettings.setDirectoryForDownloadedLibrariesPath(getDefaultDownloadPath(baseDirectoryPath));
- }
- myBaseDirectoryPath = baseDirectoryPath;
- }
+ return myPathProvider.compute();
}
public void setDownloadLibraries(final boolean downloadLibraries) {
@@ -155,7 +146,7 @@
public boolean downloadFiles(final @NotNull JComponent parent) {
if (myDownloadLibraries && myDownloadSettings != null) {
- final NewLibraryEditor libraryEditor = myDownloadSettings.download(parent);
+ final NewLibraryEditor libraryEditor = myDownloadSettings.download(parent, getBaseDirectoryPath());
if (libraryEditor != null) {
myNewLibraryEditor = libraryEditor;
}
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryDownloadSettings.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryDownloadSettings.java
index b94a582..f3c4f1e 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryDownloadSettings.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryDownloadSettings.java
@@ -25,6 +25,7 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.download.DownloadableFileDescription;
@@ -33,6 +34,7 @@
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -44,7 +46,7 @@
public class LibraryDownloadSettings {
private final FrameworkLibraryVersion myVersion;
private final DownloadableLibraryType myLibraryType;
- private String myDirectoryForDownloadedLibrariesPath;
+ private String myLibrariesPath;
private final String myLibraryName;
private final boolean myDownloadSources;
private final boolean myDownloadJavaDocs;
@@ -59,13 +61,13 @@
}
public LibraryDownloadSettings(@NotNull FrameworkLibraryVersion libraryVersion, @Nullable DownloadableLibraryType libraryType,
- @NotNull String directoryForDownloadedLibrariesPath, @NotNull String libraryName,
+ @NotNull String librariesPath, @NotNull String libraryName,
@NotNull LibrariesContainer.LibraryLevel libraryLevel,
@NotNull List<? extends DownloadableLibraryFileDescription> selectedDownloads,
boolean downloadSources, boolean downloadJavaDocs) {
myVersion = libraryVersion;
myLibraryType = libraryType;
- myDirectoryForDownloadedLibrariesPath = directoryForDownloadedLibrariesPath;
+ myLibrariesPath = librariesPath;
myLibraryName = libraryName;
myDownloadSources = downloadSources;
myDownloadJavaDocs = downloadJavaDocs;
@@ -100,7 +102,7 @@
}
public String getDirectoryForDownloadedLibrariesPath() {
- return myDirectoryForDownloadedLibrariesPath;
+ return myLibrariesPath;
}
public List<? extends DownloadableLibraryFileDescription> getSelectedDownloads() {
@@ -116,12 +118,8 @@
return myLibraryType;
}
- public void setDirectoryForDownloadedLibrariesPath(String directoryForDownloadedLibrariesPath) {
- myDirectoryForDownloadedLibrariesPath = directoryForDownloadedLibrariesPath;
- }
-
@Nullable
- public NewLibraryEditor download(JComponent parent) {
+ public NewLibraryEditor download(JComponent parent, @Nullable String rootPath) {
final List<DownloadableFileDescription> toDownload = new ArrayList<DownloadableFileDescription>(mySelectedDownloads);
Map<DownloadableFileDescription, OrderRootType> rootTypes = new HashMap<DownloadableFileDescription, OrderRootType>();
for (DownloadableLibraryFileDescription description : mySelectedDownloads) {
@@ -137,10 +135,11 @@
}
}
+ String path = rootPath != null && !FileUtil.isAbsolute(myLibrariesPath) ? new File(rootPath, myLibrariesPath).getPath() : myLibrariesPath;
List<Pair<VirtualFile,DownloadableFileDescription>> downloaded =
DownloadableFileService.getInstance()
.createDownloader(toDownload, myLibraryName + " Library")
- .downloadWithProgress(myDirectoryForDownloadedLibrariesPath, null, parent);
+ .downloadWithProgress(path, null, parent);
if (downloaded == null) {
return null;
}
diff --git a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java
index 0d06c9f..d44864e 100644
--- a/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java
+++ b/java/idea-ui/src/com/intellij/facet/impl/ui/libraries/LibraryOptionsPanel.java
@@ -41,6 +41,7 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.NotNullComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -107,7 +108,22 @@
private RadioButtonEnumModel<Choice> myButtonEnumModel;
public LibraryOptionsPanel(@NotNull final CustomLibraryDescription libraryDescription,
- @NotNull final String baseDirectoryPath,
+ @NotNull final String path,
+ @NotNull final FrameworkLibraryVersionFilter versionFilter,
+ @NotNull final LibrariesContainer librariesContainer,
+ final boolean showDoNotCreateOption) {
+
+ this(libraryDescription, new NotNullComputable<String>() {
+ @NotNull
+ @Override
+ public String compute() {
+ return path;
+ }
+ }, versionFilter, librariesContainer, showDoNotCreateOption);
+ }
+
+ public LibraryOptionsPanel(@NotNull final CustomLibraryDescription libraryDescription,
+ @NotNull final NotNullComputable<String> pathProvider,
@NotNull final FrameworkLibraryVersionFilter versionFilter,
@NotNull final LibrariesContainer librariesContainer,
final boolean showDoNotCreateOption) {
@@ -124,7 +140,7 @@
@Override
public void run() {
if (!myDisposed) {
- showSettingsPanel(libraryDescription, baseDirectoryPath, versionFilter, showDoNotCreateOption, versions);
+ showSettingsPanel(libraryDescription, pathProvider, versionFilter, showDoNotCreateOption, versions);
onVersionChanged(getPresentableVersion());
}
}
@@ -133,7 +149,7 @@
});
}
else {
- showSettingsPanel(libraryDescription, baseDirectoryPath, versionFilter, showDoNotCreateOption,
+ showSettingsPanel(libraryDescription, pathProvider, versionFilter, showDoNotCreateOption,
new ArrayList<FrameworkLibraryVersion>());
}
}
@@ -181,11 +197,11 @@
}
private void showSettingsPanel(CustomLibraryDescription libraryDescription,
- String baseDirectoryPath,
+ NotNullComputable<String> pathProvider,
FrameworkLibraryVersionFilter versionFilter,
boolean showDoNotCreateOption, final List<? extends FrameworkLibraryVersion> versions) {
//todo[nik] create mySettings only in apply() method
- mySettings = new LibraryCompositionSettings(libraryDescription, baseDirectoryPath, versionFilter, versions);
+ mySettings = new LibraryCompositionSettings(libraryDescription, pathProvider, versionFilter, versions);
Disposer.register(this, mySettings);
List<Library> libraries = calculateSuitableLibraries();
@@ -351,13 +367,6 @@
}
}
- public void changeBaseDirectoryPath(@NotNull String directoryForLibrariesPath) {
- if (mySettings != null) {
- mySettings.changeBaseDirectoryPath(directoryForLibrariesPath);
- updateState();
- }
- }
-
public void setVersionFilter(@NotNull FrameworkLibraryVersionFilter versionFilter) {
if (mySettings != null) {
mySettings.setVersionFilter(versionFilter);
diff --git a/java/idea-ui/src/com/intellij/framework/FrameworkTypeEx.java b/java/idea-ui/src/com/intellij/framework/FrameworkTypeEx.java
index 3bd2763..bbfa5a6 100644
--- a/java/idea-ui/src/com/intellij/framework/FrameworkTypeEx.java
+++ b/java/idea-ui/src/com/intellij/framework/FrameworkTypeEx.java
@@ -19,7 +19,6 @@
import com.intellij.ide.util.frameworkSupport.FrameworkRole;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportUtil;
import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -36,28 +35,31 @@
super(id);
}
+ /**
+ * Puts it under another framework.
+ * @see #getUnderlyingFrameworkTypeId()
+ */
@Nullable
public FrameworkGroup<?> getParentGroup() {
return null;
}
+ /**
+ * Puts it under framework group.
+ * @see #getParentGroup()
+ */
+ @Nullable
+ public String getUnderlyingFrameworkTypeId() {
+ return null;
+ }
+
@NotNull
public abstract FrameworkSupportInModuleProvider createProvider();
- @Nullable
- public String getUnderlyingFrameworkTypeId() {
- return null;
- }
-
public <V extends FrameworkVersion> List<V> getVersions() {
return Collections.emptyList();
}
- @NotNull
- public String[] getProjectCategories() {
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
-
public FrameworkRole[] getRoles() {
FrameworkGroup<?> parentGroup = getParentGroup();
if (parentGroup == null) {
diff --git a/java/idea-ui/src/com/intellij/framework/addSupport/FrameworkSupportInModuleProvider.java b/java/idea-ui/src/com/intellij/framework/addSupport/FrameworkSupportInModuleProvider.java
index 858aefd..f958964 100644
--- a/java/idea-ui/src/com/intellij/framework/addSupport/FrameworkSupportInModuleProvider.java
+++ b/java/idea-ui/src/com/intellij/framework/addSupport/FrameworkSupportInModuleProvider.java
@@ -16,8 +16,8 @@
package com.intellij.framework.addSupport;
import com.intellij.framework.FrameworkOrGroup;
-import com.intellij.ide.util.frameworkSupport.FrameworkRole;
import com.intellij.framework.FrameworkTypeEx;
+import com.intellij.ide.util.frameworkSupport.FrameworkRole;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportModel;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.openapi.module.Module;
@@ -58,11 +58,6 @@
return getFrameworkType().getPresentableName();
}
- @NotNull
- public String[] getProjectCategories() {
- return getFrameworkType().getProjectCategories();
- }
-
public FrameworkRole[] getRoles() {
return getFrameworkType().getRoles();
}
@@ -71,7 +66,7 @@
return "Version:";
}
- public List<String> getOptionalDependenciesFrameworkIds() {
+ public List<FrameworkDependency> getDependenciesFrameworkIds() {
return Collections.emptyList();
}
@@ -90,4 +85,33 @@
public String toString() {
return getPresentableName();
}
+
+ public static class FrameworkDependency {
+ private final String myFrameworkId;
+ private final boolean myOptional;
+
+ private FrameworkDependency(String frameworkId, boolean optional) {
+ myFrameworkId = frameworkId;
+ myOptional = optional;
+ }
+
+ public static FrameworkDependency optional(String frameworkId) {
+ return new FrameworkDependency(frameworkId, true);
+ }
+
+ public static FrameworkDependency required(String frameworkId) {
+ return new FrameworkDependency(frameworkId, false);
+ }
+
+ public String getFrameworkId() {
+ return myFrameworkId;
+ }
+
+ /**
+ * True if dependency is not required.
+ */
+ public boolean isOptional() {
+ return myOptional;
+ }
+ }
}
diff --git a/java/idea-ui/src/com/intellij/framework/addSupport/impl/AddSupportForSingleFrameworkDialog.java b/java/idea-ui/src/com/intellij/framework/addSupport/impl/AddSupportForSingleFrameworkDialog.java
index ea5bc70..84816f8 100644
--- a/java/idea-ui/src/com/intellij/framework/addSupport/impl/AddSupportForSingleFrameworkDialog.java
+++ b/java/idea-ui/src/com/intellij/framework/addSupport/impl/AddSupportForSingleFrameworkDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -109,7 +109,7 @@
int answer = Messages.showYesNoDialog(getRootPane(),
ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"),
CommonBundle.getWarningTitle(), Messages.getWarningIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
return;
}
}
@@ -166,12 +166,12 @@
}
final int result = Messages.showYesNoCancelDialog(rootModel.getProject(), message, "Library Already Exists",
"&Replace", "&Add", "&Cancel", null);
- if (result == 0) {
+ if (result == Messages.YES) {
for (OrderEntry entry : existingEntries) {
rootModel.removeOrderEntry(entry);
}
}
- else if (result != 1) {
+ else if (result != Messages.NO) {
return false;
}
}
diff --git a/java/idea-ui/src/com/intellij/framework/library/impl/DownloadableLibraryPropertiesEditor.java b/java/idea-ui/src/com/intellij/framework/library/impl/DownloadableLibraryPropertiesEditor.java
index 040cc7b..cf9ac42 100644
--- a/java/idea-ui/src/com/intellij/framework/library/impl/DownloadableLibraryPropertiesEditor.java
+++ b/java/idea-ui/src/com/intellij/framework/library/impl/DownloadableLibraryPropertiesEditor.java
@@ -75,7 +75,7 @@
pathForDownloaded);
final LibraryDownloadSettings settings = DownloadingOptionsDialog.showDialog(getMainPanel(), initialSettings, versions, false);
if (settings != null) {
- final NewLibraryEditor editor = settings.download(getMainPanel());
+ final NewLibraryEditor editor = settings.download(getMainPanel(), null);
if (editor != null) {
final LibraryEditorBase target = (LibraryEditorBase)myEditorComponent.getLibraryEditor();
target.removeAllRoots();
diff --git a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java b/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java
index 0e30795..6ac0734 100644
--- a/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java
+++ b/java/idea-ui/src/com/intellij/ide/RecentProjectsManager.java
@@ -21,7 +21,6 @@
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -34,8 +33,8 @@
)}
)
public class RecentProjectsManager extends RecentProjectsManagerBase {
- public RecentProjectsManager(final ProjectManager projectManager, final MessageBus messageBus) {
- super(projectManager, messageBus);
+ public RecentProjectsManager(MessageBus messageBus) {
+ super(messageBus);
}
protected String getProjectPath(@NotNull Project project) {
diff --git a/java/idea-ui/src/com/intellij/ide/actions/NewProjectAction.java b/java/idea-ui/src/com/intellij/ide/actions/NewProjectAction.java
index 048bda9..4c4601f 100644
--- a/java/idea-ui/src/com/intellij/ide/actions/NewProjectAction.java
+++ b/java/idea-ui/src/com/intellij/ide/actions/NewProjectAction.java
@@ -16,19 +16,15 @@
package com.intellij.ide.actions;
import com.intellij.ide.impl.NewProjectUtil;
-import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
-import com.intellij.ide.util.newProjectWizard.AddModuleWizardPro;
+import com.intellij.ide.projectWizard.NewProjectWizard;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
-import com.intellij.openapi.util.registry.Registry;
public class NewProjectAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
- NewProjectUtil.createNewProject(CommonDataKeys.PROJECT.getData(e.getDataContext()), Registry.is("new.project.wizard")
- ? new AddModuleWizardPro(null, ModulesProvider.EMPTY_MODULES_PROVIDER, null)
- : new AddModuleWizard(null, ModulesProvider.EMPTY_MODULES_PROVIDER, null));
+ NewProjectWizard wizard = new NewProjectWizard(null, ModulesProvider.EMPTY_MODULES_PROVIDER, null);
+ NewProjectUtil.createNewProject(getEventProject(e), wizard);
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/actions/OpenProjectAction.java b/java/idea-ui/src/com/intellij/ide/actions/OpenProjectAction.java
index e817b26..8cbb554 100644
--- a/java/idea-ui/src/com/intellij/ide/actions/OpenProjectAction.java
+++ b/java/idea-ui/src/com/intellij/ide/actions/OpenProjectAction.java
@@ -50,6 +50,7 @@
extensions.add(ProjectFileType.DOT_DEFAULT_EXTENSION);
final ProjectOpenProcessor[] openProcessors = Extensions.getExtensions(ProjectOpenProcessor.EXTENSION_POINT_NAME);
for (ProjectOpenProcessor openProcessor : openProcessors) {
+ if (!(openProcessor instanceof ProjectOpenProcessorBase)) continue;
final String[] supportedExtensions = ((ProjectOpenProcessorBase)openProcessor).getSupportedExtensions();
if (supportedExtensions != null) {
Collections.addAll(extensions, supportedExtensions);
diff --git a/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java b/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java
index 86b821d..1ad6a1c 100644
--- a/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.java
+++ b/java/idea-ui/src/com/intellij/ide/palette/impl/PaletteManager.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,9 +60,11 @@
myFileEditorManager = fileEditorManager;
}
+ @Override
public void projectOpened() {
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
StartupManager.getInstance(myProject).registerPostStartupActivity(new Runnable() {
+ @Override
public void run() {
myPaletteWindow = new PaletteWindow(myProject);
myPaletteToolWindow = ToolWindowManager.getInstance(myProject).
@@ -80,6 +82,7 @@
}
}
+ @Override
public void projectClosed() {
if (myPaletteWindow != null) {
myPaletteWindow.dispose();
@@ -88,14 +91,17 @@
}
}
+ @Override
@NotNull
public String getComponentName() {
return "PaletteManager";
}
+ @Override
public void initComponent() {
}
+ @Override
public void disposeComponent() {
if (myPaletteWindow != null) {
myPaletteWindow.dispose();
@@ -157,9 +163,9 @@
private final MergingUpdateQueue myQueue = new MergingUpdateQueue("palette", 200, true, null);
private void processFileEditorChange(@Nullable final VirtualFile selectedFile) {
-
myQueue.cancelAllUpdates();
myQueue.queue(new Update("update") {
+ @Override
public void run() {
if (myPaletteWindow == null) return;
myPaletteWindow.refreshPaletteIfChanged(selectedFile);
@@ -205,14 +211,17 @@
}
private class MyFileEditorManagerListener implements FileEditorManagerListener {
+ @Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
processFileEditorChange(file);
}
+ @Override
public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
processFileEditorChange(null);
}
+ @Override
public void selectionChanged(@NotNull FileEditorManagerEvent event) {
processFileEditorChange(event.getNewFile());
}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/BuilderBasedProjectType.java b/java/idea-ui/src/com/intellij/ide/projectWizard/BuilderBasedProjectType.java
deleted file mode 100644
index 6dd3d28..0000000
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/BuilderBasedProjectType.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.intellij.ide.projectWizard;
-
-import com.intellij.ide.util.projectWizard.ModuleBuilder;
-import com.intellij.openapi.module.JavaModuleType;
-import com.intellij.openapi.module.ModuleType;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author Dmitry Avdeev
- * Date: 20.09.13
- */
-public class BuilderBasedProjectType extends ProjectCategory {
-
- private final ModuleType myModuleType;
-
- public BuilderBasedProjectType(ModuleType moduleType) {
- myModuleType = moduleType;
- }
-
- @NotNull
- @Override
- public final ModuleBuilder createModuleBuilder() {
- return myModuleType.createModuleBuilder();
- }
-
- public static class Empty extends BuilderBasedProjectType {
-
- public Empty() {
- super(ModuleType.EMPTY);
- }
- }
-
- public static class Java extends BuilderBasedProjectType {
-
- public Java() {
- super(JavaModuleType.getModuleType());
- }
- }
-}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ChooseTemplateStep.form b/java/idea-ui/src/com/intellij/ide/projectWizard/ChooseTemplateStep.form
new file mode 100644
index 0000000..10c9cc5
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ChooseTemplateStep.form
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.projectWizard.ChooseTemplateStep">
+ <grid id="27dc6" binding="myPanel" 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>
+ <component id="13f52" class="com.intellij.ui.components.JBRadioButton" binding="myEmptyProjectButton">
+ <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="true"/>
+ <text value="Create &empty project"/>
+ </properties>
+ </component>
+ <hspacer id="35cc7">
+ <constraints>
+ <grid row="0" 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="2c81b" class="com.intellij.ui.components.JBRadioButton" binding="myFromTemplateButton">
+ <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 value="Create project from &template"/>
+ </properties>
+ </component>
+ <nested-form id="2fbda" form-file="com/intellij/ide/projectWizard/ProjectTemplateList.form" binding="myTemplateList">
+ <constraints>
+ <grid row="2" 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>
+ </nested-form>
+ </children>
+ </grid>
+ <buttonGroups>
+ <group name="myGroup">
+ <member id="2c81b"/>
+ <member id="13f52"/>
+ </group>
+ </buttonGroups>
+</form>
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ChooseTemplateStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ChooseTemplateStep.java
new file mode 100644
index 0000000..db2b79e
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ChooseTemplateStep.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.ide.projectWizard;
+
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.platform.ProjectTemplate;
+import com.intellij.ui.components.JBRadioButton;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class ChooseTemplateStep extends ModuleWizardStep {
+
+ private final WizardContext myWizardContext;
+ private final ProjectTypeStep myProjectTypeStep;
+
+ private JPanel myPanel;
+ private JBRadioButton myEmptyProjectButton;
+ private JBRadioButton myFromTemplateButton;
+ private ProjectTemplateList myTemplateList;
+
+ public ChooseTemplateStep(WizardContext wizardContext, ProjectTypeStep projectTypeStep) {
+ myWizardContext = wizardContext;
+ myProjectTypeStep = projectTypeStep;
+ ActionListener listener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ updateSelection();
+ }
+ };
+ myEmptyProjectButton.addActionListener(listener);
+ myFromTemplateButton.addActionListener(listener);
+ updateSelection();
+ }
+
+ private void updateSelection() {
+ myTemplateList.setEnabled(myFromTemplateButton.isSelected());
+ }
+
+ @Override
+ public boolean isStepVisible() {
+ return myWizardContext.isCreatingNewProject() && !myProjectTypeStep.getAvailableTemplates().isEmpty();
+ }
+
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Override
+ public void updateStep() {
+ myTemplateList.setTemplates(new ArrayList<ProjectTemplate>(myProjectTypeStep.getAvailableTemplates()), false);
+ }
+
+ @Override
+ public void updateDataModel() {
+ if (myFromTemplateButton.isSelected()) {
+ myWizardContext.setProjectTemplate(myTemplateList.getSelectedTemplate());
+ }
+ }
+}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/EmptyProjectBuilder.java b/java/idea-ui/src/com/intellij/ide/projectWizard/EmptyProjectBuilder.java
deleted file mode 100644
index c67bc25..0000000
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/EmptyProjectBuilder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.projectWizard;
-
-import com.intellij.ide.util.projectWizard.EmptyModuleBuilder;
-
-/**
-* @author Dmitry Avdeev
-* Date: 27.09.13
-*/
-public class EmptyProjectBuilder extends EmptyModuleBuilder {
- @Override
- public String getPresentableName() {
- return "Empty Project";
- }
-
- @Override
- public String getDescription() {
- return "Empty project without modules. Use it to create free-style module structure.";
- }
-}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleTypeCategory.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleTypeCategory.java
new file mode 100644
index 0000000..ed2665d
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ModuleTypeCategory.java
@@ -0,0 +1,32 @@
+package com.intellij.ide.projectWizard;
+
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
+import com.intellij.openapi.module.JavaModuleType;
+import com.intellij.openapi.module.ModuleType;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 20.09.13
+ */
+public class ModuleTypeCategory extends ProjectCategory {
+
+ private final ModuleType myModuleType;
+
+ public ModuleTypeCategory(ModuleType moduleType) {
+ myModuleType = moduleType;
+ }
+
+ @NotNull
+ @Override
+ public final ModuleBuilder createModuleBuilder() {
+ return myModuleType.createModuleBuilder();
+ }
+
+ public static class Java extends ModuleTypeCategory {
+
+ public Java() {
+ super(JavaModuleType.getModuleType());
+ }
+ }
+}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
index 77d6d91..12007df 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizard.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.projectWizard;
+import com.intellij.ide.IdeBundle;
import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard;
import com.intellij.ide.util.newProjectWizard.StepSequence;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
@@ -23,24 +24,35 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.awt.*;
+
/**
* @author Dmitry Avdeev
- * Date: 04.09.13
*/
public class NewProjectWizard extends AbstractProjectWizard {
- private final StepSequence mySequence;
+ private final StepSequence mySequence = new StepSequence();
public NewProjectWizard(@Nullable Project project, @NotNull ModulesProvider modulesProvider, @Nullable String defaultPath) {
- super("New Project", project, defaultPath);
+ super(project == null ? IdeBundle.message("title.new.project") : IdeBundle.message("title.add.module"), project, defaultPath);
+ init(modulesProvider);
+ }
+
+ public NewProjectWizard(Project project, Component dialogParent, ModulesProvider modulesProvider) {
+ super(IdeBundle.message("title.add.module"), project, dialogParent);
+ init(modulesProvider);
+ }
+
+ protected void init(@NotNull ModulesProvider modulesProvider) {
myWizardContext.setNewWizard(true);
- mySequence = new StepSequence();
- mySequence.addCommonStep(new ProjectTypeStep(myWizardContext, this, modulesProvider));
+ ProjectTypeStep projectTypeStep = new ProjectTypeStep(myWizardContext, this, modulesProvider);
+ mySequence.addCommonStep(projectTypeStep);
+ mySequence.addCommonStep(new ChooseTemplateStep(myWizardContext, projectTypeStep));
mySequence.addCommonFinishingStep(new ProjectSettingsStep(myWizardContext), null);
for (ModuleWizardStep step : mySequence.getAllSteps()) {
addStep(step);
}
- init();
+ super.init();
}
@Nullable
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizardAction.java b/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizardAction.java
deleted file mode 100644
index 29226b6..0000000
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/NewProjectWizardAction.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.projectWizard;
-
-import com.intellij.ide.impl.NewProjectUtil;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
-
-/**
- * @author Dmitry Avdeev
- * Date: 04.09.13
- */
-public class NewProjectWizardAction extends AnAction {
- @Override
- public void actionPerformed(AnActionEvent e) {
- NewProjectWizard wizard = new NewProjectWizard(null, ModulesProvider.EMPTY_MODULES_PROVIDER, null);
- NewProjectUtil.createNewProject(getEventProject(e), wizard);
- }
-}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectCategory.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectCategory.java
index 7ef2e82..67400bc 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectCategory.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectCategory.java
@@ -20,7 +20,6 @@
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -55,20 +54,21 @@
return createModuleBuilder().getGroupName();
}
- @Nullable
- public String getParentId() {
- return null;
- }
-
public FrameworkRole[] getAcceptableFrameworkRoles() {
return new FrameworkRole[] {createModuleBuilder().getDefaultAcceptableRole()};
}
+ /**
+ * Describes "main" frameworks to be shown on top of the tree
+ */
@NotNull
public String[] getAssociatedFrameworkIds() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
+ /**
+ * Preselects the frameworks in tree.
+ */
public String[] getPreselectedFrameworkIds() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectSettingsStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectSettingsStep.java
index 3db63ca..18c12d2 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectSettingsStep.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectSettingsStep.java
@@ -165,7 +165,7 @@
if (!validateModulePaths()) return false;
if (!myWizardContext.isCreatingNewProject()) {
- validateExistingModuleName();
+ validateExistingModuleName(myWizardContext.getProject());
}
if (mySettingsStep != null) {
@@ -359,15 +359,15 @@
}
}
- private void validateExistingModuleName() throws ConfigurationException {
+ private void validateExistingModuleName(Project project) throws ConfigurationException {
final String moduleName = getModuleName();
final Module module;
- final ProjectStructureConfigurable fromConfigurable = ProjectStructureConfigurable.getInstance(myWizardContext.getProject());
+ final ProjectStructureConfigurable fromConfigurable = ProjectStructureConfigurable.getInstance(project);
if (fromConfigurable != null) {
module = fromConfigurable.getModulesConfig().getModule(moduleName);
}
else {
- module = ModuleManager.getInstance(myWizardContext.getProject()).findModuleByName(moduleName);
+ module = ModuleManager.getInstance(project).findModuleByName(moduleName);
}
if (module != null) {
throw new ConfigurationException("Module \'" + moduleName + "\' already exist in project. Please, specify another name.");
@@ -398,7 +398,7 @@
int answer = Messages.showYesNoDialog(IdeBundle.message("prompt.overwrite.project.file", moduleFile.getAbsolutePath(),
IdeBundle.message("project.new.wizard.module.identification")),
IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
return false;
}
}
@@ -443,7 +443,7 @@
@NotNull
public JTextField getModuleNameField() {
- return myModuleName;
+ return getNameComponent();
}
protected String getModuleName() {
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form
new file mode 100644
index 0000000..7dbb92f
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.form
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.projectWizard.ProjectTemplateList">
+ <grid id="27dc6" binding="myPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <scrollpane id="99b52" class="com.intellij.ui.components.JBScrollPane">
+ <constraints border-constraint="Center"/>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="f677e" class="com.intellij.ui.components.JBList" binding="myList">
+ <constraints/>
+ <properties>
+ <selectionMode value="0"/>
+ </properties>
+ </component>
+ </children>
+ </scrollpane>
+ <grid id="2bdbb" 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 border-constraint="South"/>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <scrollpane id="1765e" class="com.intellij.ui.components.JBScrollPane">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="500" height="100"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="124ce" class="javax.swing.JTextPane" binding="myDescriptionPane">
+ <constraints/>
+ <properties/>
+ </component>
+ </children>
+ </scrollpane>
+ <vspacer id="c930f">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="1" anchor="1" fill="0" indent="0" use-parent-layout="false">
+ <preferred-size width="-1" height="3"/>
+ </grid>
+ </constraints>
+ </vspacer>
+ </children>
+ </grid>
+ </children>
+ </grid>
+</form>
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java
new file mode 100644
index 0000000..51e4294
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTemplateList.java
@@ -0,0 +1,199 @@
+/*
+ * 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.ide.projectWizard;
+
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.popup.ListItemDescriptor;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.platform.ProjectTemplate;
+import com.intellij.platform.templates.ArchivedProjectTemplate;
+import com.intellij.ui.*;
+import com.intellij.ui.SingleSelectionModel;
+import com.intellij.ui.components.JBList;
+import com.intellij.ui.popup.list.GroupedItemsListRenderer;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.awt.*;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 12/24/13
+ */
+public class ProjectTemplateList extends JPanel {
+
+ private static final String PROJECT_WIZARD_TEMPLATE = "project.wizard.template";
+
+ private JBList myList;
+ private JPanel myPanel;
+ private JTextPane myDescriptionPane;
+
+ public ProjectTemplateList() {
+ super(new BorderLayout());
+ add(myPanel, BorderLayout.CENTER);
+
+ GroupedItemsListRenderer renderer = new GroupedItemsListRenderer(new ListItemDescriptor<ProjectTemplate>() {
+ @Nullable
+ @Override
+ public String getTextFor(ProjectTemplate value) {
+ return value.getName();
+ }
+
+ @Nullable
+ @Override
+ public String getTooltipFor(ProjectTemplate value) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Icon getIconFor(ProjectTemplate value) {
+ return value.getIcon();
+ }
+
+ @Override
+ public boolean hasSeparatorAboveOf(ProjectTemplate value) {
+ return false;
+ }
+
+ @Nullable
+ @Override
+ public String getCaptionAboveOf(ProjectTemplate value) {
+ return null;
+ }
+ }) {
+
+ @Override
+ protected void customizeComponent(JList list, Object value, boolean isSelected) {
+ super.customizeComponent(list, value, isSelected);
+ Icon icon = myTextLabel.getIcon();
+ if (icon != null && myTextLabel.getDisabledIcon() == icon) {
+ myTextLabel.setDisabledIcon(IconLoader.getDisabledIcon(icon));
+ }
+ myTextLabel.setEnabled(myList.isEnabled());
+ myTextLabel.setBorder(IdeBorderFactory.createEmptyBorder(3, 3, 3, 3));
+ }
+ };
+ myList.setCellRenderer(renderer);
+ myList.setSelectionModel(new SingleSelectionModel());
+ myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ updateSelection();
+ }
+ });
+
+ Messages.installHyperlinkSupport(myDescriptionPane);
+ }
+
+ private void updateSelection() {
+ myDescriptionPane.setText("");
+ ProjectTemplate template = getSelectedTemplate();
+ if (template != null) {
+ String description = template.getDescription();
+ if (StringUtil.isNotEmpty(description)) {
+ description = "<html><body><font " +
+ (SystemInfo.isMac ? "" : "face=\"Verdana\" size=\"-1\"") + '>' + description +
+ "</font></body></html>";
+ myDescriptionPane.setText(description);
+ }
+ }
+ }
+
+ public void setTemplates(List<ProjectTemplate> list, boolean preserveSelection) {
+ Collections.sort(list, new Comparator<ProjectTemplate>() {
+ @Override
+ public int compare(ProjectTemplate o1, ProjectTemplate o2) {
+ return Comparing.compare(o1 instanceof ArchivedProjectTemplate, o2 instanceof ArchivedProjectTemplate);
+ }
+ });
+
+ int index = preserveSelection ? myList.getSelectedIndex() : -1;
+ //noinspection unchecked
+ myList.setModel(new CollectionListModel(list));
+ myList.setSelectedIndex(index == -1 ? 0 : index);
+ updateSelection();
+ }
+
+ @Nullable
+ public ProjectTemplate getSelectedTemplate() {
+ return (ProjectTemplate)myList.getSelectedValue();
+ }
+
+ @Override
+ public void setEnabled(boolean enabled) {
+ super.setEnabled(enabled);
+ myList.setEnabled(enabled);
+ myDescriptionPane.setEnabled(enabled);
+ }
+
+ void restoreSelection() {
+ final String templateName = PropertiesComponent.getInstance().getValue(PROJECT_WIZARD_TEMPLATE);
+ if (templateName != null && myList.getModel() instanceof CollectionListModel) {
+ @SuppressWarnings("unchecked")
+ List<ProjectTemplate> list = ((CollectionListModel<ProjectTemplate>)myList.getModel()).toList();
+ ProjectTemplate template = ContainerUtil.find(list, new Condition<ProjectTemplate>() {
+ @Override
+ public boolean value(ProjectTemplate template) {
+ return templateName.equals(template.getName());
+ }
+ });
+ if (template != null) {
+ myList.setSelectedValue(template, true);
+ }
+ }
+ myList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ ProjectTemplate template = getSelectedTemplate();
+ if (template != null) {
+ PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_TEMPLATE, template.getName());
+ }
+ }
+ });
+ }
+
+ public void addListSelectionListener(ListSelectionListener listener) {
+ myList.addListSelectionListener(listener);
+ }
+
+ public boolean setSelectedTemplate(String name) {
+ ListModel model1 = myList.getModel();
+ for (int j = 0; j < model1.getSize(); j++) {
+ if (name.equals(((ProjectTemplate)model1.getElementAt(j)).getName())) {
+ myList.setSelectedIndex(j);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public void setPaintBusy(boolean b) {
+ myList.setPaintBusy(b);
+ }
+}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form
index 1eaf128..24245d1 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.form
@@ -21,7 +21,7 @@
<children>
<scrollpane id="19f6a" class="com.intellij.ui.components.JBScrollPane">
<constraints>
- <grid row="0" 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="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="0" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="200" height="-1"/>
</grid>
</constraints>
@@ -30,7 +30,9 @@
<children>
<component id="5df9f" class="com.intellij.ui.components.JBList" binding="myProjectTypeList">
<constraints/>
- <properties/>
+ <properties>
+ <selectionMode value="0"/>
+ </properties>
</component>
</children>
</scrollpane>
@@ -45,7 +47,28 @@
<BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
</clientProperties>
<border type="none"/>
- <children/>
+ <children>
+ <grid id="27a92" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <card name="templates card"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <nested-form id="b063c" form-file="com/intellij/ide/projectWizard/ProjectTemplateList.form" binding="myTemplatesList">
+ <constraints border-constraint="Center"/>
+ </nested-form>
+ </children>
+ </grid>
+ <grid id="b50ee" binding="myFrameworksPanelPlaceholder" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <card name="frameworks card"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ </children>
</grid>
</children>
</grid>
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
index 4c66356..cde7955 100644
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypeStep.java
@@ -17,18 +17,22 @@
import com.intellij.CommonBundle;
import com.intellij.framework.addSupport.FrameworkSupportInModuleProvider;
+import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.frameworkSupport.FrameworkRole;
import com.intellij.ide.util.frameworkSupport.FrameworkSupportUtil;
import com.intellij.ide.util.newProjectWizard.AddSupportForFrameworksPanel;
import com.intellij.ide.util.newProjectWizard.TemplatesGroup;
import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase;
import com.intellij.ide.util.newProjectWizard.modes.CreateFromTemplateMode;
+import com.intellij.ide.util.projectWizard.EmptyModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.ide.wizard.CommitStepException;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
@@ -39,25 +43,24 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplateEP;
+import com.intellij.platform.ProjectTemplatesFactory;
import com.intellij.platform.templates.ArchivedProjectTemplate;
+import com.intellij.platform.templates.BuilderBasedTemplate;
import com.intellij.platform.templates.LocalArchivedTemplate;
import com.intellij.platform.templates.RemoteTemplatesFactory;
-import com.intellij.ui.*;
+import com.intellij.ui.CollectionListModel;
+import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.SingleSelectionModel;
import com.intellij.ui.components.JBList;
-import com.intellij.ui.tabs.TabInfo;
-import com.intellij.ui.tabs.TabsListener;
-import com.intellij.ui.tabs.impl.JBTabsImpl;
import com.intellij.util.Function;
-import com.intellij.util.containers.ConcurrentMultiMap;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.FactoryMap;
-import com.intellij.util.containers.MultiMap;
+import com.intellij.util.containers.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
@@ -68,47 +71,86 @@
import java.awt.*;
import java.net.URL;
import java.util.*;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
/**
* @author Dmitry Avdeev
* Date: 04.09.13
*/
+@SuppressWarnings("unchecked")
public class ProjectTypeStep extends ModuleWizardStep implements Disposable {
+ private static final String TEMPLATES_CARD = "templates card";
private static final String FRAMEWORKS_CARD = "frameworks card";
- private final WizardContext myContext;
- private final NewProjectWizard myWizard;
- private final ModulesProvider myModulesProvider;
- private final JTextPane myTemplateDescription;
+
+ private static final String PROJECT_WIZARD_GROUP = "project.wizard.group";
+ public static final Convertor<FrameworkSupportInModuleProvider,String> PROVIDER_STRING_CONVERTOR =
+ new Convertor<FrameworkSupportInModuleProvider, String>() {
+ @Override
+ public String convert(FrameworkSupportInModuleProvider o) {
+ return o.getId();
+ }
+ };
+
private JPanel myPanel;
private JPanel myOptionsPanel;
private JBList myProjectTypeList;
+ private ProjectTemplateList myTemplatesList;
+ private JPanel myFrameworksPanelPlaceholder;
- private final ProjectTypesList myProjectTypesList;
- private final JBList myTemplatesList;
- private final TabInfo myFrameworksTab;
- private final TabInfo myTemplatesTab;
-
- @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
- private final FactoryMap<ProjectCategory, ModuleBuilder> myBuilders = new FactoryMap<ProjectCategory, ModuleBuilder>() {
- @Nullable
- @Override
- protected ModuleBuilder create(ProjectCategory key) {
- return key.createModuleBuilder();
- }
- };
- private final Set<String> myCards = new HashSet<String>();
-
+ private final WizardContext myContext;
+ private final NewProjectWizard myWizard;
+ private final ModulesProvider myModulesProvider;
private final AddSupportForFrameworksPanel myFrameworksPanel;
private final ModuleBuilder.ModuleConfigurationUpdater myConfigurationUpdater;
- private boolean myCommitted;
- private final JBTabsImpl myTabs;
- private final MultiMap<String, ProjectTemplate> myTemplates = loadLocalTemplates();
+
+ @SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
+ private final FactoryMap<ProjectTemplate, ModuleBuilder> myBuilders = new FactoryMap<ProjectTemplate, ModuleBuilder>() {
+ @Nullable
+ @Override
+ protected ModuleBuilder create(ProjectTemplate key) {
+ return (ModuleBuilder)key.createModuleBuilder();
+ }
+ };
+ private final Map<String, ModuleWizardStep> myCustomSteps = new HashMap<String, ModuleWizardStep>();
+ private final MultiMap<TemplatesGroup,ProjectTemplate> myTemplatesMap;
+ private boolean myRemoteTemplatesLoaded;
+ private String myCurrentCard;
public ProjectTypeStep(WizardContext context, NewProjectWizard wizard, ModulesProvider modulesProvider) {
myContext = context;
myWizard = wizard;
+
+ myTemplatesMap = new ConcurrentMultiMap<TemplatesGroup, ProjectTemplate>();
+ List<TemplatesGroup> groups = fillTemplatesMap(context);
+
+ myProjectTypeList.setModel(new CollectionListModel<TemplatesGroup>(groups));
+ myProjectTypeList.setSelectionModel(new SingleSelectionModel());
+ myProjectTypeList.addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e) {
+ updateSelection();
+ }
+ });
+ myProjectTypeList.setCellRenderer(new ColoredListCellRenderer<TemplatesGroup>() {
+ @Override
+ protected void customizeCellRenderer(JList list, TemplatesGroup value, int index, boolean selected, boolean hasFocus) {
+ Font font = list.getFont();
+ if (value.getParentGroup() != null) {
+ setFont(font);
+ append(" ");
+ }
+ else {
+ setBorder(IdeBorderFactory.createEmptyBorder(2, 10, 2, 5));
+ setIcon(value.getIcon());
+ setFont(font.deriveFont(Font.BOLD));
+ }
+ append(value.getName());
+ }
+ });
+
myModulesProvider = modulesProvider;
Project project = context.getProject();
final LibrariesContainer container = LibrariesContainerFactory.createContainer(project);
@@ -117,182 +159,220 @@
@Override
public String getBaseDirectoryForLibrariesPath() {
ModuleBuilder builder = getSelectedBuilder();
- assert builder != null;
return StringUtil.notNullize(builder.getContentEntryPath());
}
};
+ myFrameworksPanel = new AddSupportForFrameworksPanel(Collections.<FrameworkSupportInModuleProvider>emptyList(), model, true);
+ Disposer.register(wizard.getDisposable(), myFrameworksPanel);
+ myFrameworksPanelPlaceholder.add(myFrameworksPanel.getMainPanel());
+
myConfigurationUpdater = new ModuleBuilder.ModuleConfigurationUpdater() {
@Override
public void update(@NotNull Module module, @NotNull ModifiableRootModel rootModel) {
- myFrameworksPanel.addSupport(module, rootModel);
+ if (isFrameworksMode()) {
+ myFrameworksPanel.addSupport(module, rootModel);
+ }
}
};
- final MultiMap<String, ProjectCategory> categories = new MultiMap<String, ProjectCategory>();
- for (ProjectCategory category : ProjectCategory.EXTENSION_POINT_NAME.getExtensions()) {
- categories.putValue(category.getGroupName(), category);
- }
-
- MultiMap<TemplatesGroup,ProjectTemplate> templatesMap = CreateFromTemplateMode.getTemplatesMap(context, false);
- List<TemplatesGroup> groups = new ArrayList<TemplatesGroup>(templatesMap.keySet());
- Collections.sort(groups);
- MultiMap<String, ProjectCategory> map = new MultiMap<String, ProjectCategory>();
- for (TemplatesGroup group : groups) {
- String name = group.getName();
- for (ProjectTemplate template : templatesMap.get(group)) {
- TemplateBasedProjectType projectType = new TemplateBasedProjectType(template);
- map.putValue(name, projectType);
- }
- for (ProjectCategory category : categories.get(name)) {
- map.putValue(name, category);
- }
- }
-
- myProjectTypesList = new ProjectTypesList(myProjectTypeList, map);
-
myProjectTypeList.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
- projectTypeChanged(true);
+ projectTypeChanged();
}
});
- for (ProjectCategory category : map.values()) {
- myWizard.getSequence().addStepsForBuilder(myBuilders.get(category), context, modulesProvider);
- }
- myFrameworksPanel = new AddSupportForFrameworksPanel(Collections.<FrameworkSupportInModuleProvider>emptyList(), model, true);
- Disposer.register(wizard.getDisposable(), myFrameworksPanel);
-
- myTemplatesList = new JBList();
- myTemplatesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myTemplatesList.setCellRenderer(new ColoredListCellRenderer<ProjectCategory>() {
- @Override
- protected void customizeCellRenderer(JList list, ProjectCategory value, int index, boolean selected, boolean hasFocus) {
- append(value.getDisplayName()).setIcon(value.getIcon());
- }
- });
myTemplatesList.addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
- projectTypeChanged(false);
- ProjectCategory type = (ProjectCategory)myTemplatesList.getSelectedValue();
- myTemplateDescription.setText(type == null ? "" : type.getDescription());
+ updateSelection();
}
});
- myTabs = new JBTabsImpl(null, IdeFocusManager.findInstance(), this);
- myFrameworksTab = new TabInfo(myFrameworksPanel.getMainPanel()).setText(" Frameworks ");
- myTabs.addTab(myFrameworksTab);
+ for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) {
+ ModuleBuilder builder = templatesGroup.getModuleBuilder();
+ if (builder != null) {
+ myWizard.getSequence().addStepsForBuilder(builder, context, modulesProvider);
+ }
+ for (ProjectTemplate template : myTemplatesMap.get(templatesGroup)) {
+ myWizard.getSequence().addStepsForBuilder(myBuilders.get(template), context, modulesProvider);
+ }
+ }
- JPanel templatesPanel = new JPanel(new BorderLayout());
- templatesPanel.add(ScrollPaneFactory.createScrollPane(myTemplatesList, SideBorder.BOTTOM));
- myTemplateDescription = new JTextPane();
- myTemplateDescription.setBorder(IdeBorderFactory.createEmptyBorder(5, 5, 5, 5));
- Messages.installHyperlinkSupport(myTemplateDescription);
- templatesPanel.add(myTemplateDescription, BorderLayout.SOUTH);
+ final String groupId = PropertiesComponent.getInstance().getValue(PROJECT_WIZARD_GROUP);
+ if (groupId != null) {
+ TemplatesGroup group = ContainerUtil.find(groups, new Condition<TemplatesGroup>() {
+ @Override
+ public boolean value(TemplatesGroup group) {
+ return groupId.equals(group.getId());
+ }
+ });
+ if (group != null) {
+ myProjectTypeList.setSelectedValue(group, true);
+ }
+ }
+ if (myProjectTypeList.getSelectedValue() == null) {
+ myProjectTypeList.setSelectedIndex(0);
+ }
+ myTemplatesList.restoreSelection();
+ }
- myTemplatesTab = new TabInfo(templatesPanel).setText(" Templates ");
- myTabs.addTab(myTemplatesTab);
- myOptionsPanel.add(myTabs.getComponent(), FRAMEWORKS_CARD);
+ private boolean isFrameworksMode() {
+ return FRAMEWORKS_CARD.equals(myCurrentCard) && getSelectedBuilder().equals(myContext.getProjectBuilder());
+ }
- myTabs.addListener(new TabsListener.Adapter() {
+ private List<TemplatesGroup> fillTemplatesMap(WizardContext context) {
+
+ List<ModuleBuilder> builders = ModuleBuilder.getAllBuilders();
+ if (context.isCreatingNewProject()) {
+ builders.add(new EmptyModuleBuilder());
+ }
+ Map<String, TemplatesGroup> groupMap = new HashMap<String, TemplatesGroup>();
+ for (ModuleBuilder builder : builders) {
+ BuilderBasedTemplate template = new BuilderBasedTemplate(builder);
+ if (builder.isTemplate()) {
+ TemplatesGroup group = groupMap.get(builder.getGroupName());
+ if (group == null) {
+ group = new TemplatesGroup(builder);
+ }
+ myTemplatesMap.putValue(group, template);
+ }
+ else {
+ TemplatesGroup group = new TemplatesGroup(builder);
+ groupMap.put(group.getName(), group);
+ myTemplatesMap.put(group, new ArrayList<ProjectTemplate>(Collections.singletonList(template)));
+ }
+ }
+
+ MultiMap<TemplatesGroup, ProjectTemplate> map = CreateFromTemplateMode.getTemplatesMap(context);
+ myTemplatesMap.putAllValues(map);
+
+ for (ProjectCategory category : ProjectCategory.EXTENSION_POINT_NAME.getExtensions()) {
+ myTemplatesMap.put(new TemplatesGroup(category), new ArrayList<ProjectTemplate>());
+ }
+
+ if (context.isCreatingNewProject()) {
+ MultiMap<String, ProjectTemplate> localTemplates = loadLocalTemplates();
+ for (TemplatesGroup group : myTemplatesMap.keySet()) {
+ myTemplatesMap.putValues(group, localTemplates.get(group.getId()));
+ }
+ }
+
+ // remove empty groups
+ //for (Iterator<Map.Entry<TemplatesGroup, Collection<ProjectTemplate>>> iterator = myTemplatesMap.entrySet().iterator();
+ // iterator.hasNext(); ) {
+ // Map.Entry<TemplatesGroup, Collection<ProjectTemplate>> entry = iterator.next();
+ // if (entry.getValue().isEmpty()) {
+ // iterator.remove();
+ // }
+ //}
+
+ List<TemplatesGroup> groups = new ArrayList<TemplatesGroup>(myTemplatesMap.keySet());
+
+ // sorting by module type popularity
+ final MultiMap<ModuleType, TemplatesGroup> moduleTypes = new MultiMap<ModuleType, TemplatesGroup>();
+ for (TemplatesGroup group : groups) {
+ ModuleType type = getModuleType(group);
+ moduleTypes.putValue(type, group);
+ }
+ Collections.sort(groups, new Comparator<TemplatesGroup>() {
@Override
- public void selectionChanged(TabInfo oldSelection, TabInfo newSelection) {
- projectTypeChanged(false);
+ public int compare(TemplatesGroup o1, TemplatesGroup o2) {
+ int u = Comparing.compare(ProjectTemplatesFactory.CUSTOM_GROUP.equals(o1.getName()), ProjectTemplatesFactory.CUSTOM_GROUP.equals(o2.getName()));
+ if (u != 0) return u;
+ int i1 = moduleTypes.get(getModuleType(o2)).size() - moduleTypes.get(getModuleType(o1)).size();
+ if (i1 != 0) return i1;
+ int i = myTemplatesMap.get(o2).size() - myTemplatesMap.get(o1).size();
+ return i != 0 ? i : o1.compareTo(o2);
}
});
- }
- // new category or template is selected
- public void projectTypeChanged(boolean updatePanel) {
- ModuleBuilder builder = getSelectedBuilder();
- if (builder != null) {
- myContext.setProjectBuilder(builder);
- myWizard.getSequence().setType(builder.getBuilderId());
- if (myFrameworksTab == myTabs.getSelectedInfo()) {
- builder.addModuleConfigurationUpdater(myConfigurationUpdater);
- }
- }
- if (updatePanel) {
- ProjectCategory type = getSelectedProjectType();
- if (type != null) {
- updateOptionsPanel(type);
- }
- }
- }
-
- @Nullable
- public ProjectCategory getSelectedProjectType() {
- if (myTabs.getSelectedInfo() == myFrameworksTab) {
- return myProjectTypesList.getSelectedType();
- }
- else {
- return (ProjectCategory)myTemplatesList.getSelectedValue();
- }
- }
-
- @Nullable
- private ModuleBuilder getSelectedBuilder() {
- ProjectCategory object = getSelectedProjectType();
- return object == null ? null : myBuilders.get(object);
- }
-
- private void updateOptionsPanel(final @NotNull ProjectCategory projectCategory) {
- ModuleBuilder builder = myBuilders.get(projectCategory);
- JComponent panel = builder.getCustomOptionsPanel(new Disposable() {
+ Set<String> groupNames = ContainerUtil.map2Set(groups, new Function<TemplatesGroup, String>() {
@Override
- public void dispose() {
- disposeUIResources();
+ public String fun(TemplatesGroup group) {
+ return group.getName();
}
});
- String card;
- if (panel != null) {
- card = builder.getBuilderId();
- if (myCards.add(card)) {
- myOptionsPanel.add(panel, card);
+
+ // move subgroups
+ MultiMap<String, TemplatesGroup> subGroups = new MultiMap<String, TemplatesGroup>();
+ for (ListIterator<TemplatesGroup> iterator = groups.listIterator(); iterator.hasNext(); ) {
+ TemplatesGroup group = iterator.next();
+ String parentGroup = group.getParentGroup();
+ if (parentGroup != null && groupNames.contains(parentGroup) && !group.getName().equals(parentGroup)) {
+ subGroups.putValue(parentGroup, group);
+ iterator.remove();
}
}
- else {
- card = FRAMEWORKS_CARD;
- List<FrameworkSupportInModuleProvider> allProviders = FrameworkSupportUtil.getProviders(builder);
- List<FrameworkSupportInModuleProvider> matched =
- ContainerUtil.filter(allProviders, new Condition<FrameworkSupportInModuleProvider>() {
- @Override
- public boolean value(FrameworkSupportInModuleProvider provider) {
- return matchFramework(projectCategory, provider);
+ for (ListIterator<TemplatesGroup> iterator = groups.listIterator(); iterator.hasNext(); ) {
+ TemplatesGroup group = iterator.next();
+ for (TemplatesGroup subGroup : subGroups.get(group.getName())) {
+ iterator.add(subGroup);
+ }
+ }
+ return groups;
+ }
+
+ private static ModuleType getModuleType(TemplatesGroup group) {
+ ModuleBuilder moduleBuilder = group.getModuleBuilder();
+ return moduleBuilder == null ? null : moduleBuilder.getModuleType();
+ }
+
+ // new TemplatesGroup selected
+ public void projectTypeChanged() {
+ TemplatesGroup group = getSelectedGroup();
+ if (group == null) return;
+ PropertiesComponent.getInstance().setValue(PROJECT_WIZARD_GROUP, group.getId() );
+ ModuleBuilder groupModuleBuilder = group.getModuleBuilder();
+ if (groupModuleBuilder == null || groupModuleBuilder.isTemplateBased()) {
+ showTemplates(group);
+ }
+ else if (!showCustomOptions(groupModuleBuilder)){
+ List<FrameworkSupportInModuleProvider> providers = FrameworkSupportUtil.getProviders(groupModuleBuilder);
+ final ProjectCategory category = group.getProjectCategory();
+ if (category != null) {
+ List<FrameworkSupportInModuleProvider> filtered = ContainerUtil.filter(providers, new Condition<FrameworkSupportInModuleProvider>() {
+ @Override
+ public boolean value(FrameworkSupportInModuleProvider provider) {
+ return matchFramework(category, provider);
+ }
+ });
+ // add associated
+ Map<String, FrameworkSupportInModuleProvider> map = ContainerUtil.newMapFromValues(providers.iterator(), PROVIDER_STRING_CONVERTOR);
+ Set<FrameworkSupportInModuleProvider> set = new HashSet<FrameworkSupportInModuleProvider>(filtered);
+ for (FrameworkSupportInModuleProvider provider : filtered) {
+ for (FrameworkSupportInModuleProvider.FrameworkDependency depId : provider.getDependenciesFrameworkIds()) {
+ FrameworkSupportInModuleProvider dependency = map.get(depId.getFrameworkId());
+ set.add(dependency);
}
- });
+ }
- myFrameworksPanel.setProviders(matched,
- new HashSet<String>(Arrays.asList(projectCategory.getAssociatedFrameworkIds())),
- new HashSet<String>(Arrays.asList(projectCategory.getPreselectedFrameworkIds())));
-
- boolean hasTemplates = updateTemplates(projectCategory, true);
- myFrameworksTab.setEnabled(!matched.isEmpty() || !hasTemplates);
- }
- ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, card);
- }
-
- private boolean updateTemplates(ProjectCategory projectCategory, boolean initial) {
- List<ProjectCategory> templates = ContainerUtil.map(myTemplates.get(projectCategory.getId()), new Function<ProjectTemplate, ProjectCategory>() {
- @Override
- public ProjectCategory fun(ProjectTemplate template) {
- return new TemplateBasedProjectType(template);
+ myFrameworksPanel.setProviders(new ArrayList<FrameworkSupportInModuleProvider>(set),
+ new HashSet<String>(Arrays.asList(category.getAssociatedFrameworkIds())),
+ new HashSet<String>(Arrays.asList(category.getPreselectedFrameworkIds())));
}
- });
+ else {
+ myFrameworksPanel.setProviders(providers);
+ }
+ getSelectedBuilder().addModuleConfigurationUpdater(myConfigurationUpdater);
- //noinspection unchecked
- myTemplatesList.setModel(new CollectionListModel<ProjectCategory>(templates));
- myTemplatesTab.setEnabled(!templates.isEmpty());
- if (initial && !templates.isEmpty()) {
- myTemplatesList.setSelectedIndex(0);
+ showCard(FRAMEWORKS_CARD);
}
- return !templates.isEmpty();
+ updateSelection();
}
- private boolean matchFramework(ProjectCategory projectCategory, FrameworkSupportInModuleProvider framework) {
+ private void showCard(String card) {
+ ((CardLayout)myOptionsPanel.getLayout()).show(myOptionsPanel, card);
+ myCurrentCard = card;
+ }
- if (!framework.isEnabledForModuleBuilder(myBuilders.get(projectCategory))) return false;
+ private void showTemplates(TemplatesGroup group) {
+ Collection<ProjectTemplate> templates = myTemplatesMap.get(group);
+ setTemplatesList(group, templates, false);
+ showCard(TEMPLATES_CARD);
+ }
+
+ private static boolean matchFramework(ProjectCategory projectCategory, FrameworkSupportInModuleProvider framework) {
FrameworkRole[] roles = framework.getRoles();
if (roles.length == 0) return true;
@@ -301,6 +381,72 @@
return ContainerUtil.intersects(Arrays.asList(roles), acceptable);
}
+
+ private void setTemplatesList(TemplatesGroup group, Collection<ProjectTemplate> templates, boolean preserveSelection) {
+ ArrayList<ProjectTemplate> list = new ArrayList<ProjectTemplate>(templates);
+ if (group.getParentGroup() == null) {
+ for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) {
+ if (group.getName().equals(templatesGroup.getParentGroup())) {
+ list.addAll(myTemplatesMap.get(templatesGroup));
+ }
+ }
+ }
+ myTemplatesList.setTemplates(list, preserveSelection);
+ }
+
+ private boolean showCustomOptions(@NotNull ModuleBuilder builder) {
+ String card = builder.getBuilderId();
+ if (!myCustomSteps.containsKey(card)) {
+ ModuleWizardStep step = builder.getCustomOptionsStep(myContext, this);
+ if (step == null) return false;
+ step.updateStep();
+ myCustomSteps.put(card, step);
+ myOptionsPanel.add(step.getComponent(), card);
+ }
+ showCard(card);
+ return true;
+ }
+
+ @Nullable
+ private ModuleWizardStep getCustomStep() {
+ return myCustomSteps.get(myCurrentCard);
+ }
+
+ private TemplatesGroup getSelectedGroup() {
+ return (TemplatesGroup)myProjectTypeList.getSelectedValue();
+ }
+
+ @Nullable
+ public ProjectTemplate getSelectedTemplate() {
+ return myCurrentCard == TEMPLATES_CARD ? myTemplatesList.getSelectedTemplate() : null;
+ }
+
+ private ModuleBuilder getSelectedBuilder() {
+ ProjectTemplate template = getSelectedTemplate();
+ if (template != null) {
+ return myBuilders.get(template);
+ }
+ return getSelectedGroup().getModuleBuilder();
+ }
+
+ public Collection<ProjectTemplate> getAvailableTemplates() {
+ return myCurrentCard != FRAMEWORKS_CARD ? Collections.<ProjectTemplate>emptyList() : myTemplatesMap.get(getSelectedGroup());
+ }
+
+ public void onWizardFinished() throws CommitStepException {
+ if (isFrameworksMode()) {
+ boolean ok = myFrameworksPanel.downloadLibraries();
+ if (!ok) {
+ int answer = Messages.showYesNoDialog(getComponent(),
+ ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"),
+ CommonBundle.getWarningTitle(), Messages.getWarningIcon());
+ if (answer != Messages.YES) {
+ throw new CommitStepException(null);
+ }
+ }
+ }
+ }
+
@Override
public JComponent getComponent() {
return myPanel;
@@ -309,50 +455,42 @@
@Override
public void updateDataModel() {
ModuleBuilder builder = getSelectedBuilder();
- assert builder != null;
myWizard.getSequence().addStepsForBuilder(builder, myContext, myModulesProvider);
+ ModuleWizardStep step = getCustomStep();
+ if (step != null) {
+ step.updateDataModel();
+ }
}
@Override
public void updateStep() {
- myProjectTypesList.resetSelection();
- loadRemoteTemplates();
- }
-
- @Override
- public void onStepLeaving() {
- myProjectTypesList.saveSelection();
- }
-
- @Override
- public void onWizardFinished() throws CommitStepException {
- if (!myCommitted && myTabs.getSelectedInfo() == myFrameworksTab) {
- boolean ok = myFrameworksPanel.downloadLibraries();
- if (!ok) {
- int answer = Messages.showYesNoDialog(getComponent(),
- ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"),
- CommonBundle.getWarningTitle(), Messages.getWarningIcon());
- if (answer != 0) {
- throw new CommitStepException(null);
- }
- }
- myCommitted = true;
+ if (myContext.isCreatingNewProject() && !myRemoteTemplatesLoaded) {
+ loadRemoteTemplates();
}
}
@Override
+ public boolean validate() throws ConfigurationException {
+ ModuleWizardStep step = getCustomStep();
+ return step != null ? step.validate() : super.validate();
+ }
+
+ @Override
public JComponent getPreferredFocusedComponent() {
return myProjectTypeList;
}
@TestOnly
- public AddSupportForFrameworksPanel getFrameworksPanel() {
- return myFrameworksPanel;
- }
-
- @TestOnly
- public boolean setSelectedProjectType(String group, String name) {
- return myProjectTypesList.setSelectedType(group, name);
+ public boolean setSelectedTemplate(String group, String name) {
+ ListModel model = myProjectTypeList.getModel();
+ for (int i = 0; i < model.getSize(); i++) {
+ if (group.equals(((TemplatesGroup)model.getElementAt(i)).getName())) {
+ myProjectTypeList.setSelectedIndex(i);
+ if (name == null) return getSelectedGroup().getName().equals(group);
+ return myTemplatesList.setSelectedTemplate(name);
+ }
+ }
+ return false;
}
@Override
@@ -364,14 +502,21 @@
Disposer.dispose(this);
}
- private static MultiMap<String, ProjectTemplate> loadLocalTemplates() {
+ private MultiMap<String, ProjectTemplate> loadLocalTemplates() {
ConcurrentMultiMap<String, ProjectTemplate> map = new ConcurrentMultiMap<String, ProjectTemplate>();
ProjectTemplateEP[] extensions = ProjectTemplateEP.EP_NAME.getExtensions();
for (ProjectTemplateEP ep : extensions) {
ClassLoader classLoader = ep.getLoaderForClass();
URL url = classLoader.getResource(ep.templatePath);
if (url != null) {
- map.putValue(ep.projectType, new LocalArchivedTemplate(url, classLoader));
+ LocalArchivedTemplate template = new LocalArchivedTemplate(url, classLoader);
+ if (ep.category) {
+ TemplateBasedCategory category = new TemplateBasedCategory(template);
+ myTemplatesMap.putValue(new TemplatesGroup(category), template);
+ }
+ else {
+ map.putValue(ep.projectType, template);
+ }
}
}
return map;
@@ -389,26 +534,41 @@
ProjectTemplate[] templates = factory.createTemplates(group, myContext);
for (ProjectTemplate template : templates) {
String id = ((ArchivedProjectTemplate)template).getCategory();
- myTemplates.putValue(id == null ? group : id, template);
+ for (TemplatesGroup templatesGroup : myTemplatesMap.keySet()) {
+ if (Comparing.equal(id, templatesGroup.getId()) || Comparing.equal(group, templatesGroup.getName())) {
+ myTemplatesMap.putValue(templatesGroup, template);
+ }
+ }
}
- }
+ }
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
public void run() {
- int index = myTemplatesList.getSelectedIndex();
- ProjectCategory type = myProjectTypesList.getSelectedType();
- if (type != null) {
- updateTemplates(type, false);
- }
- myTemplatesList.setSelectedIndex(index);
+ TemplatesGroup group = getSelectedGroup();
+ if (group == null) return;
+ Collection<ProjectTemplate> templates = myTemplatesMap.get(group);
+ setTemplatesList(group, templates, true);
}
});
}
finally {
myTemplatesList.setPaintBusy(false);
+ myRemoteTemplatesLoaded = true;
}
}
});
+ }
+ private void updateSelection() {
+ ProjectTemplate template = getSelectedTemplate();
+ if (template != null) {
+ myContext.setProjectTemplate(template);
+ }
+
+ ModuleBuilder builder = getSelectedBuilder();
+ myContext.setProjectBuilder(builder);
+ if (builder != null) {
+ myWizard.getSequence().setType(builder.getBuilderId());
+ }
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java b/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java
deleted file mode 100644
index b5d60bc..0000000
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/ProjectTypesList.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.projectWizard;
-
-import com.intellij.ide.util.newProjectWizard.SelectTemplateSettings;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.CustomShortcutSet;
-import com.intellij.openapi.ui.popup.ListItemDescriptor;
-import com.intellij.openapi.util.Pair;
-import com.intellij.ui.CollectionListModel;
-import com.intellij.ui.ListSpeedSearch;
-import com.intellij.ui.SpeedSearchComparator;
-import com.intellij.ui.components.JBList;
-import com.intellij.ui.popup.list.GroupedItemsListRenderer;
-import com.intellij.util.containers.MultiMap;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author Dmitry Avdeev
- * Date: 11/21/12
- */
-public class ProjectTypesList implements Disposable {
-
- private final JBList myList;
- private final CollectionListModel<TemplateItem> myModel;
- private Pair<TemplateItem, Integer> myBestMatch;
-
- public ProjectTypesList(JBList list, MultiMap<String, ProjectCategory> map) {
-
- myList = list;
- myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
- new ListSpeedSearch(myList) {
- @Override
- protected String getElementText(Object element) {
- return super.getElementText(element);
- }
- }.setComparator(new SpeedSearchComparator(false));
- List<TemplateItem> items = buildItems(map);
- myModel = new CollectionListModel<TemplateItem>(items);
-
- myList.setCellRenderer(new GroupedItemsListRenderer(new ListItemDescriptor() {
- @Nullable
- @Override
- public String getTextFor(Object value) {
- return ((TemplateItem)value).getName();
- }
-
- @Nullable
- @Override
- public String getTooltipFor(Object value) {
- return null;
- }
-
- @Nullable
- @Override
- public Icon getIconFor(Object value) {
- return ((TemplateItem)value).getIcon();
- }
-
- @Override
- public boolean hasSeparatorAboveOf(Object value) {
- TemplateItem item = (TemplateItem)value;
- int index = myModel.getElementIndex(item);
- return index == 0 || !myModel.getElementAt(index - 1).getGroupName().equals(item.getGroupName());
- }
-
- @Nullable
- @Override
- public String getCaptionAboveOf(Object value) {
- return ((TemplateItem)value).getGroupName();
- }
- }));
-
- myList.setModel(myModel);
- }
-
- void installKeyAction(JComponent component) {
- new AnAction() {
- @Override
- public void actionPerformed(AnActionEvent e) {
- InputEvent event = e.getInputEvent();
- if (event instanceof KeyEvent) {
- int row = myList.getSelectedIndex();
- int toSelect;
- switch (((KeyEvent)event).getKeyCode()) {
- case KeyEvent.VK_UP:
- toSelect = row == 0 ? myList.getItemsCount() - 1 : row - 1;
- myList.setSelectedIndex(toSelect);
- myList.ensureIndexIsVisible(toSelect);
- break;
- case KeyEvent.VK_DOWN:
- toSelect = row < myList.getItemsCount() - 1 ? row + 1 : 0;
- myList.setSelectedIndex(toSelect);
- myList.ensureIndexIsVisible(toSelect);
- break;
- }
- }
- }
- }.registerCustomShortcutSet(new CustomShortcutSet(KeyEvent.VK_UP, KeyEvent.VK_DOWN), component);
- }
-
- void resetSelection() {
- if (myList.getSelectedIndex() != -1) return;
- SelectTemplateSettings settings = SelectTemplateSettings.getInstance();
- if (settings.getLastGroup() == null || !setSelectedType(settings.getLastGroup(), settings.getLastTemplate())) {
- myList.setSelectedIndex(0);
- }
- }
-
- void saveSelection() {
- TemplateItem item = (TemplateItem)myList.getSelectedValue();
- if (item != null) {
- SelectTemplateSettings.getInstance().setLastTemplate(item.getGroupName(), item.getName());
- }
- }
-
- private List<TemplateItem> buildItems(MultiMap<String, ProjectCategory> map) {
- List<TemplateItem> items = new ArrayList<TemplateItem>();
- List<String> groups = new ArrayList<String>(map.keySet());
- Collections.sort(groups);
- for (String group : groups) {
- for (ProjectCategory template : map.get(group)) {
- TemplateItem templateItem = new TemplateItem(template, group);
- items.add(templateItem);
- }
- }
- return items;
- }
-
- @Nullable
- public ProjectCategory getSelectedType() {
- Object value = myList.getSelectedValue();
- return value instanceof TemplateItem ? ((TemplateItem)value).myTemplate : null;
- }
-
- public boolean setSelectedType(@Nullable String group, @Nullable String name) {
- for (int i = 0; i < myList.getModel().getSize(); i++) {
- Object o = myList.getModel().getElementAt(i);
- if (o instanceof TemplateItem && ((TemplateItem)o).myGroup.equals(group) && ((TemplateItem)o).getName().equals(name)) {
- myList.setSelectedIndex(i);
- myList.ensureIndexIsVisible(i);
- return true;
- }
- }
-
- return false;
- }
-
- @Override
- public void dispose() {
- }
-
- static class TemplateItem {
-
- private final ProjectCategory myTemplate;
- private final String myGroup;
-
- TemplateItem(ProjectCategory template, String group) {
- myTemplate = template;
- myGroup = group;
- }
-
- String getName() {
- return myTemplate.getDisplayName();
- }
-
- public String getGroupName() {
- return myGroup;
- }
-
- Icon getIcon() {
- return myTemplate.createModuleBuilder().getNodeIcon();
- }
-
- @Nullable
- String getDescription() {
- return myTemplate.getDescription();
- }
-
- @Override
- public String toString() {
- return getName() + " " + getGroupName();
- }
- }
-}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/TemplateBasedCategory.java b/java/idea-ui/src/com/intellij/ide/projectWizard/TemplateBasedCategory.java
new file mode 100644
index 0000000..6c00673
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/projectWizard/TemplateBasedCategory.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.projectWizard;
+
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
+import com.intellij.platform.templates.ArchivedProjectTemplate;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public class TemplateBasedCategory extends ProjectCategory {
+
+ private final ArchivedProjectTemplate myTemplate;
+
+ public TemplateBasedCategory(ArchivedProjectTemplate template) {
+ myTemplate = template;
+ }
+
+ @Override
+ public String getDisplayName() {
+ return myTemplate.getName();
+ }
+
+ @Override
+ public Icon getIcon() {
+ return myTemplate.getIcon();
+ }
+
+ @Override
+ public String getDescription() {
+ return myTemplate.getDescription();
+ }
+
+ @NotNull
+ @Override
+ public ModuleBuilder createModuleBuilder() {
+ return myTemplate.createModuleBuilder();
+ }
+}
diff --git a/java/idea-ui/src/com/intellij/ide/projectWizard/TemplateBasedProjectType.java b/java/idea-ui/src/com/intellij/ide/projectWizard/TemplateBasedProjectType.java
deleted file mode 100644
index e9eefe5..0000000
--- a/java/idea-ui/src/com/intellij/ide/projectWizard/TemplateBasedProjectType.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.projectWizard;
-
-import com.intellij.ide.util.projectWizard.ModuleBuilder;
-import com.intellij.platform.ProjectTemplate;
-import com.intellij.platform.templates.LocalArchivedTemplate;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.net.URL;
-
-/**
- * @author Dmitry Avdeev
- * Date: 20.09.13
- */
-public class TemplateBasedProjectType extends ProjectCategory {
-
- private final ProjectTemplate myTemplate;
-
- public TemplateBasedProjectType(String templatePath) {
- URL resource = getClass().getResource(templatePath);
- assert resource != null : templatePath;
- myTemplate = new LocalArchivedTemplate(resource, getClass().getClassLoader());
- }
-
- public TemplateBasedProjectType(ProjectTemplate template) {
- myTemplate = template;
- }
-
- @NotNull
- @Override
- public ModuleBuilder createModuleBuilder() {
- return (ModuleBuilder)myTemplate.createModuleBuilder();
- }
-
- @Override
- public String getId() {
- return getDisplayName();
- }
-
- @Override
- public String getDisplayName() {
- return myTemplate.getName();
- }
-
- @Override
- public String getDescription() {
- return myTemplate.getDescription();
- }
-
- @Override
- public Icon getIcon() {
- return myTemplate.getIcon();
- }
-}
diff --git a/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java b/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java
index be9fd1f..c2af447 100644
--- a/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java
+++ b/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/AddFrameworkSupportDialog.java
@@ -1,4 +1,19 @@
+/*
+ * 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.ide.util.frameworkSupport;
import com.intellij.CommonBundle;
@@ -76,7 +91,7 @@
int answer = Messages.showYesNoDialog(myAddSupportPanel.getMainPanel(),
ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"),
CommonBundle.getWarningTitle(), Messages.getWarningIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
return;
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/FrameworkSupportUtil.java b/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/FrameworkSupportUtil.java
index e5d225e..1c91104 100644
--- a/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/FrameworkSupportUtil.java
+++ b/java/idea-ui/src/com/intellij/ide/util/frameworkSupport/FrameworkSupportUtil.java
@@ -127,8 +127,8 @@
dependencies.add(underlyingProvider);
}
}
- for (String frameworkId : provider.getOptionalDependenciesFrameworkIds()) {
- FrameworkSupportInModuleProvider dep = findProvider(frameworkId, myFrameworkSupportProviders);
+ for (FrameworkSupportInModuleProvider.FrameworkDependency frameworkId : provider.getDependenciesFrameworkIds()) {
+ FrameworkSupportInModuleProvider dep = findProvider(frameworkId.getFrameworkId(), myFrameworkSupportProviders);
if (dep != null) {
dependencies.add(dep);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java b/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java
index c7279ac..ad7b5f8 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/DetectedRootData.java
@@ -26,14 +26,10 @@
/**
* @author nik
*/
-class DetectedRootData {
+public class DetectedRootData {
private final File myDirectory;
- private MultiMap<DetectedProjectRoot, ProjectStructureDetector> myRoots = new MultiMap<DetectedProjectRoot, ProjectStructureDetector>() {
- @Override
- protected Map<DetectedProjectRoot, Collection<ProjectStructureDetector>> createMap() {
- return new LinkedHashMap<DetectedProjectRoot, Collection<ProjectStructureDetector>>();
- }
- };
+ private MultiMap<DetectedProjectRoot, ProjectStructureDetector> myRoots = MultiMap.createLinked();
+
private boolean myIncluded = true;
private DetectedProjectRoot mySelectedRoot;
@@ -71,6 +67,10 @@
return roots.toArray(new DetectedProjectRoot[roots.size()]);
}
+ public boolean isEmpty() {
+ return myRoots.isEmpty();
+ }
+
public boolean isIncluded() {
return myIncluded;
}
@@ -93,7 +93,7 @@
mySelectedRoot = root;
}
- public void removeRoot(DetectedProjectRoot root) {
- myRoots.remove(root);
+ public Collection<ProjectStructureDetector> removeRoot(DetectedProjectRoot root) {
+ return myRoots.remove(root);
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java b/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java
index c596527..f707d49 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/JavaModuleInsight.java
@@ -16,6 +16,7 @@
package com.intellij.ide.util.importProject;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
+import com.intellij.ide.util.projectWizard.importSources.DetectedSourceRoot;
import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot;
import com.intellij.ide.util.projectWizard.importSources.JavaSourceRootDetectionUtil;
import com.intellij.lang.java.JavaParserDefinition;
@@ -166,7 +167,7 @@
}
}
- protected ModuleDescriptor createModuleDescriptor(final File moduleContentRoot, final Collection<DetectedProjectRoot> sourceRoots) {
+ protected ModuleDescriptor createModuleDescriptor(final File moduleContentRoot, final Collection<DetectedSourceRoot> sourceRoots) {
return new ModuleDescriptor(moduleContentRoot, StdModuleTypes.JAVA, sourceRoots);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java
index 2b2562d..d2441b7 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleDescriptor.java
@@ -18,6 +18,7 @@
import com.intellij.ide.highlighter.ModuleFileType;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
+import com.intellij.ide.util.projectWizard.importSources.DetectedSourceRoot;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.roots.ModifiableRootModel;
@@ -38,7 +39,7 @@
*/
public class ModuleDescriptor {
private String myName;
- private final MultiMap<File, DetectedProjectRoot> myContentToSourceRoots = new MultiMap<File, DetectedProjectRoot>();
+ private final MultiMap<File, DetectedSourceRoot> myContentToSourceRoots = new MultiMap<File, DetectedSourceRoot>();
private final Set<File> myLibraryFiles = new HashSet<File>();
private final Set<ModuleDescriptor> myDependencies = new HashSet<ModuleDescriptor>();
private static final Set<String> ourModuleNameStopList = new THashSet<String>(
@@ -50,14 +51,14 @@
private List<ModuleBuilder.ModuleConfigurationUpdater> myConfigurationUpdaters = new SmartList<ModuleBuilder.ModuleConfigurationUpdater>();
private ModuleType myModuleType;
- public ModuleDescriptor(final File contentRoot, final ModuleType moduleType, final Collection<DetectedProjectRoot> sourceRoots) {
+ public ModuleDescriptor(final File contentRoot, final ModuleType moduleType, final Collection<? extends DetectedSourceRoot> sourceRoots) {
myName = suggestModuleName(contentRoot);
myContentToSourceRoots.putValues(contentRoot, sourceRoots);
myModuleType = moduleType;
}
public ModuleDescriptor(final File contentRoot, final ModuleType moduleType,
- final DetectedProjectRoot sourceRoot) {
+ final DetectedSourceRoot sourceRoot) {
this(contentRoot, moduleType, Collections.singletonList(sourceRoot));
}
@@ -110,19 +111,19 @@
return myContentToSourceRoots.values();
}
- public Collection<DetectedProjectRoot> getSourceRoots(File contentRoot) {
+ public Collection<DetectedSourceRoot> getSourceRoots(File contentRoot) {
return myContentToSourceRoots.get(contentRoot);
}
public void addContentRoot(File contentRoot) {
- myContentToSourceRoots.put(contentRoot, new HashSet<DetectedProjectRoot>());
+ myContentToSourceRoots.put(contentRoot, new HashSet<DetectedSourceRoot>());
}
- public Collection<DetectedProjectRoot> removeContentRoot(File contentRoot) {
+ public Collection<DetectedSourceRoot> removeContentRoot(File contentRoot) {
return myContentToSourceRoots.remove(contentRoot);
}
- public void addSourceRoot(final File contentRoot, DetectedProjectRoot sourceRoot) {
+ public void addSourceRoot(final File contentRoot, DetectedSourceRoot sourceRoot) {
myContentToSourceRoots.putValue(contentRoot, sourceRoot);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java
index cc47ce3..4364f8e 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ModuleInsight.java
@@ -16,6 +16,7 @@
package com.intellij.ide.util.importProject;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
+import com.intellij.ide.util.projectWizard.importSources.DetectedSourceRoot;
import com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
@@ -42,7 +43,7 @@
@NotNull private final ProgressIndicatorWrapper myProgress;
private final Set<File> myEntryPointRoots = new HashSet<File>();
- private final List<DetectedProjectRoot> mySourceRoots = new ArrayList<DetectedProjectRoot>();
+ private final List<DetectedSourceRoot> mySourceRoots = new ArrayList<DetectedSourceRoot>();
private final Set<String> myIgnoredNames = new HashSet<String>();
private final Map<File, Set<String>> mySourceRootToReferencedPackagesMap = new HashMap<File, Set<String>>();
@@ -59,10 +60,10 @@
myExistingModuleNames = existingModuleNames;
myExistingProjectLibraryNames = existingProjectLibraryNames;
myProgress = new ProgressIndicatorWrapper(progress);
- setRoots(Collections.<File>emptyList(), Collections.<DetectedProjectRoot>emptyList(), Collections.<String>emptySet());
+ setRoots(Collections.<File>emptyList(), Collections.<DetectedSourceRoot>emptyList(), Collections.<String>emptySet());
}
- public final void setRoots(final List<File> contentRoots, final List<? extends DetectedProjectRoot> sourceRoots, final Set<String> ignoredNames) {
+ public final void setRoots(final List<File> contentRoots, final List<? extends DetectedSourceRoot> sourceRoots, final Set<String> ignoredNames) {
myModules = null;
myLibraries = null;
@@ -96,8 +97,8 @@
try {
myProgress.pushState();
- List<DetectedProjectRoot> processedRoots = new ArrayList<DetectedProjectRoot>();
- for (DetectedProjectRoot root : mySourceRoots) {
+ List<DetectedSourceRoot> processedRoots = new ArrayList<DetectedSourceRoot>();
+ for (DetectedSourceRoot root : mySourceRoots) {
final File sourceRoot = root.getDirectory();
if (myIgnoredNames.contains(sourceRoot.getName())) {
continue;
@@ -118,7 +119,7 @@
myProgress.pushState();
myProgress.setText("Building modules layout...");
- for (DetectedProjectRoot sourceRoot : processedRoots) {
+ for (DetectedSourceRoot sourceRoot : processedRoots) {
final File srcRoot = sourceRoot.getDirectory();
final File moduleContentRoot = myEntryPointRoots.contains(srcRoot)? srcRoot : srcRoot.getParentFile();
ModuleDescriptor moduleDescriptor = contentRootToModules.get(moduleContentRoot);
@@ -147,7 +148,7 @@
}
}
- protected abstract ModuleDescriptor createModuleDescriptor(final File moduleContentRoot, Collection<DetectedProjectRoot> sourceRoots);
+ protected abstract ModuleDescriptor createModuleDescriptor(final File moduleContentRoot, Collection<DetectedSourceRoot> sourceRoots);
private void buildModuleDependencies(final Map<File, ModuleDescriptor> contentRootToModules) {
final Set<File> moduleContentRoots = contentRootToModules.keySet();
@@ -233,8 +234,8 @@
public void merge(final ModuleDescriptor mainModule, final ModuleDescriptor module) {
for (File contentRoot : module.getContentRoots()) {
final File _contentRoot = appendContentRoot(mainModule, contentRoot);
- final Collection<DetectedProjectRoot> sources = module.getSourceRoots(contentRoot);
- for (DetectedProjectRoot source : sources) {
+ final Collection<DetectedSourceRoot> sources = module.getSourceRoots(contentRoot);
+ for (DetectedSourceRoot source : sources) {
mainModule.addSourceRoot(_contentRoot, source);
}
}
@@ -274,13 +275,13 @@
public ModuleDescriptor splitModule(final ModuleDescriptor descriptor, String newModuleName, final Collection<File> contentsToExtract) {
ModuleDescriptor newModule = null;
for (File root : contentsToExtract) {
- final Collection<DetectedProjectRoot> sources = descriptor.removeContentRoot(root);
+ final Collection<DetectedSourceRoot> sources = descriptor.removeContentRoot(root);
if (newModule == null) {
- newModule = createModuleDescriptor(root, sources != null ? sources : new HashSet<DetectedProjectRoot>());
+ newModule = createModuleDescriptor(root, sources != null ? sources : new HashSet<DetectedSourceRoot>());
}
else {
if (sources != null && sources.size() > 0) {
- for (DetectedProjectRoot source : sources) {
+ for (DetectedSourceRoot source : sources) {
newModule.addSourceRoot(root, source);
}
}
@@ -347,10 +348,10 @@
return moduleRoot; // no need to include a separate root
}
if (FileUtil.isAncestor(contentRoot, moduleRoot, true)) {
- final Collection<DetectedProjectRoot> currentSources = module.getSourceRoots(moduleRoot);
+ final Collection<DetectedSourceRoot> currentSources = module.getSourceRoots(moduleRoot);
module.removeContentRoot(moduleRoot);
module.addContentRoot(contentRoot);
- for (DetectedProjectRoot source : currentSources) {
+ for (DetectedSourceRoot source : currentSources) {
module.addSourceRoot(contentRoot, source);
}
return contentRoot; // no need to include a separate root
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesDetectionStep.java b/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesDetectionStep.java
index a3877c3..f9d734a 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesDetectionStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/ModulesDetectionStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -132,11 +132,11 @@
IdeBundle.message("warning.text.0.do.you.want.to.overwrite.these.files",
StringUtil.join(errors.keySet(), "\n"), errors.size()),
IdeBundle.message("title.file.already.exists"), "Overwrite", "Reuse", "Cancel", Messages.getQuestionIcon());
- if (answer == 2) {
+ if (answer == Messages.CANCEL) {
return false;
}
- if (answer != 0) {
+ if (answer != Messages.YES) {
for (ModuleDescriptor moduleDescriptor : errors.values()) {
moduleDescriptor.reuseExisting(true);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java b/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java
index 62f0f4a..735e5b6 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/RootDetectionProcessor.java
@@ -15,16 +15,22 @@
*/
package com.intellij.ide.util.importProject;
+import com.intellij.ide.util.projectWizard.importSources.DetectedContentRoot;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
+import com.intellij.ide.util.projectWizard.importSources.DetectedSourceRoot;
import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileTypeManager;
+import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
@@ -41,6 +47,11 @@
private final FileTypeManager myTypeManager;
private final ProgressIndicator myProgressIndicator;
+ @NotNull
+ public static List<DetectedRootData> detectRoots(@NotNull File baseProjectFile) {
+ return new RootDetectionProcessor(baseProjectFile, ProjectStructureDetector.EP_NAME.getExtensions()).detectRoots();
+ }
+
public RootDetectionProcessor(File baseDir, final ProjectStructureDetector[] detectors) {
myBaseDir = getCanonicalDir(baseDir);
myDetectors = detectors;
@@ -60,8 +71,18 @@
}
}
+ public static MultiMap<ProjectStructureDetector, DetectedProjectRoot> createRootsMap(List<DetectedRootData> list) {
+ MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots = new MultiMap<ProjectStructureDetector, DetectedProjectRoot>();
+ for (final DetectedRootData rootData : list) {
+ for (ProjectStructureDetector detector : rootData.getSelectedDetectors()) {
+ roots.putValue(detector, rootData.getSelectedRoot());
+ }
+ }
+ return roots;
+ }
- public Map<ProjectStructureDetector, List<DetectedProjectRoot>> findRoots() {
+
+ public Map<ProjectStructureDetector, List<DetectedProjectRoot>> runDetectors() {
if (!myBaseDir.isDirectory()) {
return Collections.emptyMap();
}
@@ -145,4 +166,123 @@
}
return parentsToSkip;
}
+
+ private static void removeIncompatibleRoots(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
+ DetectedRootData[] allRoots = rootData.values().toArray(new DetectedRootData[rootData.values().size()]);
+ for (DetectedRootData child : allRoots) {
+ final File childDirectory = child.getDirectory();
+ if (FileUtil.isAncestor(root.getDirectory(), childDirectory, true)) {
+ for (DetectedProjectRoot projectRoot : child.getAllRoots()) {
+ if (!root.canContainRoot(projectRoot)) {
+ child.removeRoot(projectRoot);
+ }
+ }
+ if (child.isEmpty()) {
+ rootData.remove(childDirectory);
+ }
+ }
+ }
+ }
+
+ private static boolean isUnderIncompatibleRoot(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
+ File directory = root.getDirectory().getParentFile();
+ while (directory != null) {
+ final DetectedRootData data = rootData.get(directory);
+ if (data != null) {
+ for (DetectedProjectRoot parentRoot : data.getAllRoots()) {
+ if (!parentRoot.canContainRoot(root)) {
+ return true;
+ }
+ }
+ }
+ directory = directory.getParentFile();
+ }
+ return false;
+ }
+
+ private List<DetectedRootData> detectRoots() {
+ Map<ProjectStructureDetector, List<DetectedProjectRoot>> roots = runDetectors();
+ if (myProgressIndicator != null) {
+ myProgressIndicator.setText2("Processing " + roots.values().size() + " project roots...");
+ }
+
+ Map<File, DetectedRootData> rootData = new LinkedHashMap<File, DetectedRootData>();
+ for (ProjectStructureDetector detector : roots.keySet()) {
+ for (DetectedProjectRoot detectedRoot : roots.get(detector)) {
+ if (isUnderIncompatibleRoot(detectedRoot, rootData)) {
+ continue;
+ }
+
+ final DetectedRootData data = rootData.get(detectedRoot.getDirectory());
+ if (data == null) {
+ rootData.put(detectedRoot.getDirectory(), new DetectedRootData(detector, detectedRoot));
+ }
+ else {
+ detectedRoot = data.addRoot(detector, detectedRoot);
+ }
+ removeIncompatibleRoots(detectedRoot, rootData);
+ }
+ }
+
+ List<DetectedRootData> dataCollection = mergeContentRoots(rootData);
+ if (myProgressIndicator != null) {
+ myProgressIndicator.setText2("");
+ }
+ return dataCollection;
+ }
+
+ private List<DetectedRootData> mergeContentRoots(Map<File, DetectedRootData> rootData) {
+ LOG.debug(rootData.size() + " roots found, merging content roots");
+ boolean hasSourceRoots = false;
+ Set<ModuleType> typesToReplace = new HashSet<ModuleType>();
+ Set<ModuleType> moduleTypes = new HashSet<ModuleType>();
+ for (DetectedRootData data : rootData.values()) {
+ for (DetectedProjectRoot root : data.getAllRoots()) {
+ if (root instanceof DetectedContentRoot) {
+ Collections.addAll(typesToReplace, ((DetectedContentRoot)root).getTypesToReplace());
+ moduleTypes.add(((DetectedContentRoot)root).getModuleType());
+ }
+ else if (root instanceof DetectedSourceRoot) {
+ LOG.debug("Source root found: " + root.getDirectory() + ", content roots will be ignored");
+ hasSourceRoots = true;
+ break;
+ }
+ }
+ }
+ moduleTypes.removeAll(typesToReplace);
+
+ if (hasSourceRoots || moduleTypes.size() <= 1) {
+ Iterator<DetectedRootData> iterator = rootData.values().iterator();
+ DetectedContentRoot firstRoot = null;
+ ProjectStructureDetector firstDetector = null;
+ while (iterator.hasNext()) {
+ DetectedRootData data = iterator.next();
+ for (DetectedProjectRoot root : data.getAllRoots()) {
+ if (root instanceof DetectedContentRoot) {
+ LOG.debug("Removed detected " + root.getRootTypeName() + " content root: " + root.getDirectory());
+ Collection<ProjectStructureDetector> detectors = data.removeRoot(root);
+ if ((firstRoot == null || firstDetector == null) && moduleTypes.contains(((DetectedContentRoot)root).getModuleType())) {
+ firstRoot = (DetectedContentRoot)root;
+ firstDetector = ContainerUtil.getFirstItem(detectors);
+ }
+ }
+ }
+ if (data.isEmpty()) {
+ iterator.remove();
+ }
+ }
+ if (!hasSourceRoots && firstRoot != null && firstDetector != null) {
+ DetectedContentRoot baseRoot = new DetectedContentRoot(myBaseDir, firstRoot.getRootTypeName(), firstRoot.getModuleType());
+ DetectedRootData data = rootData.get(myBaseDir);
+ if (data == null) {
+ rootData.put(myBaseDir, new DetectedRootData(firstDetector, baseRoot));
+ }
+ else {
+ data.addRoot(firstDetector, baseRoot);
+ }
+ LOG.debug("Added " + firstRoot.getRootTypeName() + " content root for " + myBaseDir);
+ }
+ }
+ return new ArrayList<DetectedRootData>(rootData.values());
+ }
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java b/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java
index 93d7c09..0717d0c 100644
--- a/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/importProject/RootsDetectionStep.java
@@ -16,20 +16,15 @@
package com.intellij.ide.util.importProject;
import com.intellij.ide.IdeBundle;
-import com.intellij.ide.util.newProjectWizard.*;
+import com.intellij.ide.util.newProjectWizard.StepSequence;
import com.intellij.ide.util.projectWizard.AbstractStepWithProgress;
import com.intellij.ide.util.projectWizard.WizardContext;
-import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
import com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl;
import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.MultiLineLabelUI;
import com.intellij.openapi.ui.ex.MultiLineLabel;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.ui.IdeBorderFactory;
-import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -122,17 +117,8 @@
}
public void updateDataModel() {
- MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots = new MultiMap<ProjectStructureDetector, DetectedProjectRoot>();
final List<DetectedRootData> selectedElements = myDetectedRootsChooser.getMarkedElements();
- for (final DetectedRootData rootData : selectedElements) {
- for (ProjectStructureDetector detector : rootData.getSelectedDetectors()) {
- roots.putValue(detector, rootData.getSelectedRoot());
- }
- }
- myBuilder.setProjectRoots(roots);
- for (ProjectStructureDetector detector : roots.keySet()) {
- detector.setupProjectStructure(roots.get(detector), myBuilder.getProjectDescriptor(detector), myBuilder);
- }
+ myBuilder.setupProjectStructure(RootDetectionProcessor.createRootsMap(selectedElements));
updateSelectedTypes();
}
@@ -177,71 +163,9 @@
return Collections.emptyList();
}
- final File baseProjectFile = new File(baseProjectPath);
- Map<ProjectStructureDetector, List<DetectedProjectRoot>> roots = new RootDetectionProcessor(baseProjectFile,
- ProjectStructureDetector.EP_NAME.getExtensions()).findRoots();
- final ProgressIndicator progressIndicator = ProgressManager.getInstance().getProgressIndicator();
- if (progressIndicator != null) {
- progressIndicator.setText2("Processing " + roots.values().size() + " project roots...");
- }
-
- Map<File, DetectedRootData> rootData = new LinkedHashMap<File, DetectedRootData>();
- for (ProjectStructureDetector detector : roots.keySet()) {
- for (DetectedProjectRoot detectedRoot : roots.get(detector)) {
- if (isUnderIncompatibleRoot(detectedRoot, rootData)) {
- continue;
- }
-
- final DetectedRootData data = rootData.get(detectedRoot.getDirectory());
- if (data == null) {
- rootData.put(detectedRoot.getDirectory(), new DetectedRootData(detector, detectedRoot));
- }
- else {
- detectedRoot = data.addRoot(detector, detectedRoot);
- }
- removeIncompatibleRoots(detectedRoot, rootData);
- }
- }
-
- if (progressIndicator != null) {
- progressIndicator.setText2("");
- }
- return new ArrayList<DetectedRootData>(rootData.values());
+ return RootDetectionProcessor.detectRoots(new File(baseProjectPath));
}
- private static void removeIncompatibleRoots(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
- DetectedRootData[] allRoots = rootData.values().toArray(new DetectedRootData[rootData.values().size()]);
- for (DetectedRootData child : allRoots) {
- final File childDirectory = child.getDirectory();
- if (FileUtil.isAncestor(root.getDirectory(), childDirectory, true)) {
- for (DetectedProjectRoot projectRoot : child.getAllRoots()) {
- if (!root.canContainRoot(projectRoot)) {
- child.removeRoot(projectRoot);
- }
- }
- if (child.getAllRoots().length == 0) {
- rootData.remove(childDirectory);
- }
- }
- }
- }
-
-
- private static boolean isUnderIncompatibleRoot(DetectedProjectRoot root, Map<File, DetectedRootData> rootData) {
- File directory = root.getDirectory().getParentFile();
- while (directory != null) {
- final DetectedRootData data = rootData.get(directory);
- if (data != null) {
- for (DetectedProjectRoot parentRoot : data.getAllRoots()) {
- if (!parentRoot.canContainRoot(root)) {
- return true;
- }
- }
- }
- directory = directory.getParentFile();
- }
- return false;
- }
@Nullable
private String getBaseProjectPath() {
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java
index 79cace7..f772f04 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/AddSupportForFrameworksPanel.java
@@ -108,7 +108,7 @@
((DefaultTreeModel)myFrameworksTree.getModel()).nodeChanged(getSelectedNode());
}
}, this);
- setProviders(providers, Collections.<String>emptySet(), Collections.<String>emptySet());
+ setProviders(providers);
myFrameworksTree.addTreeSelectionListener(new TreeSelectionListener() {
public void valueChanged(TreeSelectionEvent e) {
@@ -129,10 +129,14 @@
}
+ public void setProviders(List<FrameworkSupportInModuleProvider> providers) {
+ setProviders(providers, Collections.<String>emptySet(), Collections.<String>emptySet());
+ }
+
public void setProviders(List<FrameworkSupportInModuleProvider> providers, Set<String> associated, Set<String> preselected) {
myProviders = providers;
- myAssociatedFrameworks = createNodes(myProviders, associated);
+ myAssociatedFrameworks = createNodes(myProviders, associated, preselected);
for (FrameworkSupportNodeBase node : myRoots) {
if (preselected.contains(node.getId())) {
node.setChecked(true);
@@ -280,7 +284,9 @@
return true;
}
- private Collection<FrameworkSupportNodeBase> createNodes(List<FrameworkSupportInModuleProvider> providers, Set<String> associated) {
+ private Collection<FrameworkSupportNodeBase> createNodes(List<FrameworkSupportInModuleProvider> providers,
+ Set<String> associated,
+ final Set<String> preselected) {
Map<String, FrameworkSupportNode> nodes = new HashMap<String, FrameworkSupportNode>();
Map<FrameworkGroup<?>, FrameworkGroupNode> groups = new HashMap<FrameworkGroup<?>, FrameworkGroupNode>();
List<FrameworkSupportNodeBase> roots = new ArrayList<FrameworkSupportNodeBase>();
@@ -289,7 +295,12 @@
createNode(provider, nodes, groups, roots, providers, associated, associatedNodes);
}
- FrameworkSupportNodeBase.sortByName(roots);
+ FrameworkSupportNodeBase.sortByName(roots, new Comparator<FrameworkSupportNodeBase>() {
+ @Override
+ public int compare(FrameworkSupportNodeBase o1, FrameworkSupportNodeBase o2) {
+ return Comparing.compare(preselected.contains(o2.getId()), preselected.contains(o1.getId()));
+ }
+ });
myRoots = roots;
return associatedNodes.values();
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java
index 2536bc2..72e793e 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportNodeBase.java
@@ -30,11 +30,15 @@
return (T)super.getUserObject();
}
- public static void sortByName(@Nullable List<FrameworkSupportNodeBase> nodes) {
+ public static void sortByName(@Nullable List<FrameworkSupportNodeBase> nodes, @Nullable final Comparator<FrameworkSupportNodeBase> comparator) {
if (nodes == null) return;
Collections.sort(nodes, new Comparator<FrameworkSupportNodeBase>() {
public int compare(final FrameworkSupportNodeBase o1, final FrameworkSupportNodeBase o2) {
+ if (comparator != null) {
+ int compare = comparator.compare(o1, o2);
+ if (compare != 0) return compare;
+ }
if (o1 instanceof FrameworkGroupNode && !(o2 instanceof FrameworkGroupNode)) return -1;
if (o2 instanceof FrameworkGroupNode && !(o1 instanceof FrameworkGroupNode)) return 1;
if (o1.getChildCount() < o2.getChildCount()) return 1;
@@ -43,7 +47,7 @@
}
});
for (FrameworkSupportNodeBase node : nodes) {
- sortByName(node.children);
+ sortByName(node.children, null);
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportOptionsComponent.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportOptionsComponent.java
index 1b5c3b9..ec36a20 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportOptionsComponent.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworkSupportOptionsComponent.java
@@ -31,6 +31,7 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.NotNullComputable;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.SeparatorFactory;
import org.jetbrains.annotations.NotNull;
@@ -97,8 +98,13 @@
final CustomLibraryDescription description = myConfigurable.createLibraryDescription();
if (description != null) {
- myLibraryOptionsPanel = new LibraryOptionsPanel(description, myModel.getBaseDirectoryForLibrariesPath(), createLibraryVersionFilter(),
- container, !myConfigurable.isOnlyLibraryAdded()) {
+ myLibraryOptionsPanel = new LibraryOptionsPanel(description, new NotNullComputable<String>() {
+ @NotNull
+ @Override
+ public String compute() {
+ return myModel.getBaseDirectoryForLibrariesPath();
+ }
+ }, createLibraryVersionFilter(), container, !myConfigurable.isOnlyLibraryAdded()) {
@Override
protected void onVersionChanged(@Nullable String version) {
if (myFrameworkVersionComponent == null) {
@@ -120,7 +126,6 @@
public void updateLibrariesPanel() {
if (myLibraryOptionsPanel != null) {
- myLibraryOptionsPanel.changeBaseDirectoryPath(myModel.getBaseDirectoryForLibrariesPath());
myLibraryOptionsPanel.setVersionFilter(createLibraryVersionFilter());
myLibraryOptionsPanel.setLibraryProvider(myModel.getLibraryProvider());
myLibraryOptionsPanelWrapper.setVisible(myConfigurable.isVisible());
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworksTree.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworksTree.java
index dc2cecd..894bfcb 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworksTree.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/FrameworksTree.java
@@ -17,14 +17,12 @@
import com.intellij.framework.FrameworkOrGroup;
import com.intellij.ide.util.newProjectWizard.impl.FrameworkSupportModelBase;
-import com.intellij.ui.CheckboxTree;
-import com.intellij.ui.CheckedTreeNode;
-import com.intellij.ui.SimpleTextAttributes;
-import com.intellij.ui.TreeSpeedSearch;
+import com.intellij.ui.*;
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.tree.TreeUtil;
import javax.swing.*;
+import javax.swing.border.Border;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
@@ -103,6 +101,8 @@
private FrameworksTreeRenderer(FrameworkSupportModelBase model) {
super(true, false);
myModel = model;
+ Border border = IdeBorderFactory.createEmptyBorder(2, 2, 2, 2);
+ setBorder(border);
}
@Override
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/OldFrameworkSupportProviderWrapper.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/OldFrameworkSupportProviderWrapper.java
index 34aac0d..cbc91e8 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/OldFrameworkSupportProviderWrapper.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/OldFrameworkSupportProviderWrapper.java
@@ -81,11 +81,6 @@
return myProvider.isSupportAlreadyAdded(module, facetsProvider);
}
- @NotNull
- public String[] getProjectCategories() {
- return myProvider.getProjectCategories();
- }
-
@Override
public FrameworkRole[] getRoles() {
return myProvider.getRoles();
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameWithTypeStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameWithTypeStep.java
index e6fc2d9..baf7b4c 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameWithTypeStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectNameWithTypeStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -444,7 +444,7 @@
int answer = Messages.showYesNoDialog(IdeBundle.message("prompt.overwrite.project.file", moduleFile.getAbsolutePath(),
IdeBundle.message("project.new.wizard.module.identification")),
IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
return true;
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java
index 1af97c1..2872e0d 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/ProjectTypesList.java
@@ -68,7 +68,7 @@
}
}.setComparator(new SpeedSearchComparator(false));
List<TemplateItem> items = buildItems(map);
- final TemplatesGroup samplesGroup = new TemplatesGroup("Loading Templates...", "", null, 0);
+ final TemplatesGroup samplesGroup = new TemplatesGroup("Loading Templates...", "", null, 0, null, null, null);
myLoadingItem = new TemplateItem(new LoadingProjectTemplate(), samplesGroup) {
@Override
Icon getIcon() {
@@ -92,7 +92,7 @@
String[] groups = factory.getGroups();
final List<TemplateItem> items = new ArrayList<TemplateItem>();
for (String group : groups) {
- TemplatesGroup templatesGroup = new TemplatesGroup(group, "", factory.getGroupIcon(group), 0);
+ TemplatesGroup templatesGroup = new TemplatesGroup(group, "", factory.getGroupIcon(group), 0, null, null, null);
ProjectTemplate[] templates = factory.createTemplates(group, context);
for (ProjectTemplate template : templates) {
items.add(new TemplateItem(template, templatesGroup));
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
index d0a3536..c5e4a36 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SelectTemplateStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -476,7 +476,7 @@
int answer = Messages.showYesNoDialog(IdeBundle.message("prompt.overwrite.project.file", moduleFile.getAbsolutePath(),
IdeBundle.message("project.new.wizard.module.identification")),
IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
return false;
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java
index 13ad375..f39f042 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SourcePathsStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -257,10 +257,10 @@
final int answer = Messages.showYesNoCancelDialog(myTfSourceDirectoryName, text, IdeBundle.message("title.mark.source.directory"),
IdeBundle.message("action.mark"), IdeBundle.message("action.do.not.mark"),
CommonBundle.getCancelButtonText(), Messages.getQuestionIcon());
- if (answer == 2) {
+ if (answer == Messages.CANCEL) {
return false; // cancel
}
- if (answer == 1) { // don't mark
+ if (answer == Messages.NO) { // don't mark
myRbNoSource.doClick();
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SupportForFrameworksStep.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SupportForFrameworksStep.java
index 08f56ea..74badcc 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SupportForFrameworksStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/SupportForFrameworksStep.java
@@ -1,4 +1,19 @@
+/*
+ * 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.ide.util.newProjectWizard;
import com.intellij.CommonBundle;
@@ -76,7 +91,7 @@
int answer = Messages.showYesNoDialog(getComponent(),
ProjectBundle.message("warning.message.some.required.libraries.wasn.t.downloaded"),
CommonBundle.getWarningTitle(), Messages.getWarningIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
throw new CommitStepException(null);
}
}
@@ -84,6 +99,10 @@
}
}
+ public void onWizardFinished() throws CommitStepException {
+ _commit(true);
+ }
+
public JComponent getComponent() {
return mySupportForFrameworksPanel.getMainPanel();
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/TemplatesGroup.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/TemplatesGroup.java
index e830ef7..f91f378 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/TemplatesGroup.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/TemplatesGroup.java
@@ -15,13 +15,16 @@
*/
package com.intellij.ide.util.newProjectWizard;
+import com.intellij.ide.projectWizard.ProjectCategory;
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
+ * The groups are shown in "Project Type" selection list.
* @author Dmitry Avdeev
- * Date: 11/20/12
*/
public class TemplatesGroup implements Comparable<TemplatesGroup> {
@@ -29,14 +32,41 @@
private final String myDescription;
private final Icon myIcon;
private final int myWeight;
+ private final String myParentGroup;
+ private final String myId;
+ private final ModuleBuilder myModuleBuilder;
+ private ProjectCategory myProjectCategory;
- public TemplatesGroup(String name, String description, Icon icon, int weight) {
+ public TemplatesGroup(String name, String description, Icon icon, int weight, String parentGroup, String id, ModuleBuilder moduleBuilder) {
myName = name;
myDescription = description;
myIcon = icon;
myWeight = weight;
+ myParentGroup = parentGroup;
+ myId = id;
+ myModuleBuilder = moduleBuilder;
}
+ /**
+ * Category-based group
+ * @param category
+ */
+ public TemplatesGroup(ProjectCategory category) {
+ this(category.getDisplayName(), category.getDescription(), null, 0, category.getGroupName(), category.getId(), category.createModuleBuilder());
+ myProjectCategory = category;
+ }
+
+ public TemplatesGroup(ModuleBuilder builder) {
+ this(builder.getPresentableName(), builder.getDescription(), builder.getBigIcon(), 0, builder.getParentGroup(), builder.getBuilderId(), builder);
+ }
+
+ @Nullable
+ public ModuleBuilder getModuleBuilder() {
+ return myModuleBuilder;
+ }
+
+ public ProjectCategory getProjectCategory() { return myProjectCategory; }
+
public String getName() {
return myName;
}
@@ -76,4 +106,12 @@
int i = o.myWeight - myWeight;
return i == 0 ? o.getName().compareTo(getName()) : i;
}
+
+ public String getParentGroup() {
+ return myParentGroup;
+ }
+
+ public String getId() {
+ return myId;
+ }
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
index aa10976..b975ae4 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/impl/FrameworkSupportModelBase.java
@@ -180,17 +180,28 @@
}
public void onFrameworkSelectionChanged(FrameworkSupportNode node) {
- final FrameworkSupportModelListener multicaster = myDispatcher.getMulticaster();
final FrameworkSupportInModuleProvider provider = node.getUserObject();
//todo[nik]
+ boolean checked = node.isChecked();
if (provider instanceof OldFrameworkSupportProviderWrapper) {
final FrameworkSupportProvider oldProvider = ((OldFrameworkSupportProviderWrapper) provider).getProvider();
- if (node.isChecked()) {
- multicaster.frameworkSelected(oldProvider);
+ selectFramework(oldProvider, checked);
+ }
+ for (FrameworkSupportInModuleProvider.FrameworkDependency dependency : provider.getDependenciesFrameworkIds()) {
+ if (!dependency.isOptional()) {
+ String id = dependency.getFrameworkId();
+ setFrameworkComponentEnabled(id, true);
}
- else {
- multicaster.frameworkUnselected(oldProvider);
- }
+ }
+ }
+
+ public void selectFramework(FrameworkSupportProvider provider, boolean checked) {
+ final FrameworkSupportModelListener multicaster = myDispatcher.getMulticaster();
+ if (checked) {
+ multicaster.frameworkSelected(provider);
+ }
+ else {
+ multicaster.frameworkUnselected(provider);
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java
index 898e624..9652aa6 100644
--- a/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java
+++ b/java/idea-ui/src/com/intellij/ide/util/newProjectWizard/modes/CreateFromTemplateMode.java
@@ -24,17 +24,13 @@
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplatesFactory;
-import com.intellij.platform.templates.ArchivedTemplatesFactory;
-import com.intellij.platform.templates.LocalArchivedTemplate;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
-import java.util.Collection;
import java.util.List;
-import java.util.Map;
/**
* @author Dmitry Avdeev
@@ -44,45 +40,22 @@
private SelectTemplateStep mySelectTemplateStep;
- public static MultiMap<TemplatesGroup, ProjectTemplate> getTemplatesMap(WizardContext context, boolean includeArchived) {
+ public static MultiMap<TemplatesGroup, ProjectTemplate> getTemplatesMap(WizardContext context) {
ProjectTemplatesFactory[] factories = ProjectTemplatesFactory.EP_NAME.getExtensions();
final MultiMap<TemplatesGroup, ProjectTemplate> groups = new MultiMap<TemplatesGroup, ProjectTemplate>();
for (ProjectTemplatesFactory factory : factories) {
- if (!includeArchived && (factory instanceof ArchivedTemplatesFactory)) continue;
for (String group : factory.getGroups()) {
ProjectTemplate[] templates = factory.createTemplates(group, context);
List<ProjectTemplate> values = Arrays.asList(templates);
if (!values.isEmpty()) {
Icon icon = factory.getGroupIcon(group);
- TemplatesGroup templatesGroup = new TemplatesGroup(group, null, icon, factory.getGroupWeight(group));
- if (icon != null) {
- Collection<ProjectTemplate> collection = groups.remove(templatesGroup);
- groups.putValues(templatesGroup, values);
- if (collection != null) {
- groups.putValues(templatesGroup, collection);
- }
- }
- else {
- groups.putValues(templatesGroup, values);
- }
+ String parentGroup = factory.getParentGroup(group);
+ TemplatesGroup templatesGroup = new TemplatesGroup(group, null, icon, factory.getGroupWeight(group), parentGroup, group, null);
+ groups.putValues(templatesGroup, values);
}
}
}
- final MultiMap<TemplatesGroup, ProjectTemplate> sorted = new MultiMap<TemplatesGroup, ProjectTemplate>();
- // put single leafs under "Other"
- for (Map.Entry<TemplatesGroup, Collection<ProjectTemplate>> entry : groups.entrySet()) {
- Collection<ProjectTemplate> templates = entry.getValue();
- String name = entry.getKey().getName();
- if (templates.size() == 1 && !ProjectTemplatesFactory.CUSTOM_GROUP.equals(name) && !"Java".equals(name)) {
-
- if (!(templates.iterator().next() instanceof LocalArchivedTemplate)) {
- sorted.putValues(new TemplatesGroup(ProjectTemplatesFactory.OTHER_GROUP, null, null, -1), templates);
- continue;
- }
- }
- sorted.putValues(entry.getKey(), templates);
- }
- return sorted;
+ return groups;
}
@NotNull
@@ -105,7 +78,7 @@
@Nullable
@Override
protected StepSequence createSteps(@NotNull WizardContext context, @NotNull ModulesProvider modulesProvider) {
- MultiMap<TemplatesGroup, ProjectTemplate> map = getTemplatesMap(context, true);
+ MultiMap<TemplatesGroup, ProjectTemplate> map = getTemplatesMap(context);
StepSequence sequence = new StepSequence();
for (ProjectTemplate template : map.values()) {
sequence.addStepsForBuilder(template.createModuleBuilder(), context, modulesProvider);
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java
index 1068a14..50ecf4a 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/AbstractStepWithProgress.java
@@ -29,6 +29,7 @@
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.awt.*;
@@ -97,6 +98,14 @@
return progressPanel;
}
+ @TestOnly
+ public void performStep() {
+ Result result = calculate();
+ createResultsPanel();
+ onFinished(result, false);
+ updateDataModel();
+ }
+
private void cancelSearch() {
if (myProgressIndicator != null) {
myProgressIndicator.cancel();
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java
index 3ea1bcf..8a53180 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/JdkChooserPanel.java
@@ -70,7 +70,7 @@
});
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myProject == null) {
editJdkTable();
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
index 2a81296..6602053 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/NamePathComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -178,7 +178,7 @@
int answer = Messages.showYesNoDialog(
IdeBundle.message("prompt.overwrite.project.file", projectFile.getAbsolutePath(), context.getPresentationName()),
IdeBundle.message("title.file.already.exists"), Messages.getQuestionIcon());
- shouldContinue = (answer == 0);
+ shouldContinue = (answer == Messages.YES);
}
return shouldContinue;
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java
index 573c2bb..e36d3bb 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkForModuleStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -197,7 +197,7 @@
if (jdk == null) {
int result = Messages.showOkCancelDialog(IdeBundle.message("prompt.confirm.project.no.jdk"),
IdeBundle.message("title.no.jdk.specified"), Messages.getWarningIcon());
- if (result != 0) {
+ if (result != Messages.OK) {
return false;
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java
index 7c6462f..757c34f 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectJdkStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -92,7 +92,7 @@
if (jdk == null && !ApplicationManager.getApplication().isUnitTestMode()) {
int result = Messages.showOkCancelDialog(IdeBundle.message("prompt.confirm.project.no.jdk"),
IdeBundle.message("title.no.jdk.specified"), Messages.getWarningIcon());
- if (result != 0) {
+ if (result != Messages.OK) {
return false;
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java
index 35a606e..02e3d68 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectNameStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -130,7 +130,7 @@
: IdeBundle.message("prompt.overwrite.project.file",
projectFile.getAbsolutePath(), myWizardContext.getPresentationName());
int answer = Messages.showYesNoDialog(message, title, Messages.getQuestionIcon());
- shouldContinue = answer == 0;
+ shouldContinue = answer == Messages.YES;
}
return shouldContinue;
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardStepFactoryImpl.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardStepFactoryImpl.java
index 5397b3d..2e4fac1 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardStepFactoryImpl.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardStepFactoryImpl.java
@@ -15,7 +15,6 @@
*/
package com.intellij.ide.util.projectWizard;
-import com.intellij.ide.util.frameworkSupport.FrameworkSupportUtil;
import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard;
import com.intellij.ide.util.newProjectWizard.SourcePathsStep;
import com.intellij.ide.util.newProjectWizard.SupportForFrameworksStep;
@@ -33,7 +32,6 @@
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.Map;
/**
* @author Eugene Zhuravlev
@@ -137,10 +135,6 @@
@Override
public ModuleWizardStep createSupportForFrameworksStep(@NotNull WizardContext context, @NotNull ModuleBuilder builder, @NotNull ModulesProvider modulesProvider) {
- Map<String,Boolean> availableFrameworks = builder.getAvailableFrameworks();
- if (FrameworkSupportUtil.getProviders(builder).isEmpty() || availableFrameworks != null && availableFrameworks.isEmpty()) {
- return null;
- }
final LibrariesContainer container = LibrariesContainerFactory.createContainer(context, modulesProvider);
return new SupportForFrameworksStep(context, builder, container);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardUtil.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardUtil.java
index 0f8e3c3..f4defcf 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardUtil.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/ProjectWizardUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -48,7 +48,7 @@
final int answer = Messages.showOkCancelDialog(IdeBundle.message("promot.projectwizard.directory.does.not.exist", promptPrefix,
dir.getPath(), ApplicationNamesInfo.getInstance().getFullProductName()),
IdeBundle.message("title.directory.does.not.exist"), Messages.getQuestionIcon());
- if (answer != 0) {
+ if (answer != Messages.OK) {
return false;
}
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java
index 4db9315..4e42026 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/SdkSettingsStep.java
@@ -17,12 +17,8 @@
import com.intellij.CommonBundle;
import com.intellij.ide.IdeBundle;
-import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -35,8 +31,6 @@
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
/**
* @author Dmitry Avdeev
@@ -47,64 +41,29 @@
protected final WizardContext myWizardContext;
protected final ProjectSdksModel myModel;
private final ModuleBuilder myModuleBuilder;
+ private final JPanel myJdkPanel;
- public SdkSettingsStep(@NotNull SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder, @NotNull Condition<SdkTypeId> sdkFilter) {
+ public SdkSettingsStep(SettingsStep settingsStep, @NotNull ModuleBuilder moduleBuilder,
+ @NotNull Condition<SdkTypeId> sdkFilter) {
+
+ this(settingsStep.getContext(), moduleBuilder, sdkFilter);
+ settingsStep.addSettingsField(getSdkFieldLabel(settingsStep.getContext().getProject()), myJdkPanel);
+ }
+
+ public SdkSettingsStep(WizardContext context,
+ @NotNull ModuleBuilder moduleBuilder,
+ @NotNull Condition<SdkTypeId> sdkFilter) {
myModuleBuilder = moduleBuilder;
- myWizardContext = settingsStep.getContext();
+ myWizardContext = context;
myModel = new ProjectSdksModel();
Project project = myWizardContext.getProject();
myModel.reset(project);
- myJdkComboBox = new JdkComboBox(myModel, sdkFilter);
-
- final PropertiesComponent component = project == null ? PropertiesComponent.getInstance() : PropertiesComponent.getInstance(project);
- ModuleType moduleType = moduleBuilder.getModuleType();
- final String selectedJdkProperty = "jdk.selected." + (moduleType == null ? "" : moduleType.getId());
- myJdkComboBox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- Sdk jdk = myJdkComboBox.getSelectedJdk();
- if (jdk != null) {
- component.setValue(selectedJdkProperty, jdk.getName());
- }
- }
- });
-
- if (project != null) {
- Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
- if (sdk != null && moduleBuilder.isSuitableSdkType(sdk.getSdkType())) {
- // use project SDK
- return;
- }
- }
- else {
- // set default project SDK
- Project defaultProject = ProjectManager.getInstance().getDefaultProject();
- Sdk sdk = ProjectRootManager.getInstance(defaultProject).getProjectSdk();
- if (sdk != null && sdkFilter.value(sdk.getSdkType())) {
- myJdkComboBox.setSelectedJdk(sdk);
- }
- }
-
- String value = component.getValue(selectedJdkProperty);
- if (value != null) {
- Sdk jdk = ProjectJdkTable.getInstance().findJdk(value);
- if (jdk != null) {
- myJdkComboBox.setSelectedJdk(jdk);
- }
- }
-
- JButton button = new JButton("Ne\u001Bw...");
- myJdkComboBox.setSetupButton(button, project, myModel,
- project == null ? new JdkComboBox.NoneJdkComboBoxItem() : new JdkComboBox.ProjectJdkComboBoxItem(),
- null,
- false);
- JPanel jdkPanel = new JPanel(new BorderLayout(4, 0));
- jdkPanel.add(myJdkComboBox);
- jdkPanel.add(button, BorderLayout.EAST);
- settingsStep.addSettingsField(getSdkFieldLabel(project), jdkPanel);
-
+ myJdkComboBox = JdkComboBox.createSdkComboBox(moduleBuilder, sdkFilter, project, myModel);
+ myJdkPanel = new JPanel(new BorderLayout(4, 0));
+ myJdkPanel.add(myJdkComboBox);
+ myJdkPanel.add(myJdkComboBox.getSetUpButton(), BorderLayout.EAST);
}
@NotNull
@@ -112,9 +71,13 @@
return (project == null ? "Project" : "Module") + " \u001BSDK:";
}
+ public JdkComboBox getJdkComboBox() {
+ return myJdkComboBox;
+ }
+
@Override
public JComponent getComponent() {
- return null;
+ return myJdkPanel;
}
@Override
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/DetectedContentRoot.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/DetectedContentRoot.java
new file mode 100644
index 0000000..c56af7d
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/DetectedContentRoot.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.util.projectWizard.importSources;
+
+import com.intellij.openapi.module.ModuleType;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public final class DetectedContentRoot extends DetectedProjectRoot {
+ @NotNull private final String myRootTypeName;
+ @NotNull private final ModuleType myModuleType;
+ @NotNull private final ModuleType[] myTypesToReplace;
+
+ public DetectedContentRoot(@NotNull File directory, @NotNull String rootTypeName, @NotNull ModuleType moduleType, @NotNull ModuleType... typesToReplace) {
+ super(directory);
+ myRootTypeName = rootTypeName;
+ myModuleType = moduleType;
+ myTypesToReplace = typesToReplace;
+ }
+
+ @NotNull
+ @Override
+ public String getRootTypeName() {
+ return myRootTypeName;
+ }
+
+ @NotNull
+ public ModuleType getModuleType() {
+ return myModuleType;
+ }
+
+ @NotNull
+ public ModuleType[] getTypesToReplace() {
+ return myTypesToReplace;
+ }
+}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java
index f83a8ab..47665a6 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/JavaSourceRootDetectionUtil.java
@@ -48,7 +48,7 @@
public static Collection<JavaModuleSourceRoot> suggestRoots(@NotNull File dir) {
final List<JavaSourceRootDetector> detectors = ContainerUtil.findAll(ProjectStructureDetector.EP_NAME.getExtensions(), JavaSourceRootDetector.class);
final RootDetectionProcessor processor = new RootDetectionProcessor(dir, detectors.toArray(new JavaSourceRootDetector[detectors.size()]));
- final Map<ProjectStructureDetector,List<DetectedProjectRoot>> rootsMap = processor.findRoots();
+ final Map<ProjectStructureDetector,List<DetectedProjectRoot>> rootsMap = processor.runDetectors();
Map<File, JavaModuleSourceRoot> result = new HashMap<File, JavaModuleSourceRoot>();
for (List<DetectedProjectRoot> roots : rootsMap.values()) {
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java
index fc28f8f..2863fe6 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/ProjectFromSourcesBuilder.java
@@ -44,4 +44,6 @@
WizardContext getContext();
boolean hasRootsFromOtherDetectors(ProjectStructureDetector thisDetector);
+
+ void setupModulesByContentRoots(ProjectDescriptor projectDescriptor, Collection<DetectedProjectRoot> roots);
}
diff --git a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java
index 1c33c8e..669ea1f 100644
--- a/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java
+++ b/java/idea-ui/src/com/intellij/ide/util/projectWizard/importSources/impl/ProjectFromSourcesBuilderImpl.java
@@ -25,10 +25,7 @@
import com.intellij.ide.util.projectWizard.ExistingModuleLoader;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.WizardContext;
-import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
-import com.intellij.ide.util.projectWizard.importSources.JavaModuleSourceRoot;
-import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder;
-import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
+import com.intellij.ide.util.projectWizard.importSources.*;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.diagnostic.Logger;
@@ -128,8 +125,11 @@
return myBaseProjectPath;
}
- public void setProjectRoots(MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots) {
+ public void setupProjectStructure(MultiMap<ProjectStructureDetector, DetectedProjectRoot> roots) {
myRoots = roots;
+ for (ProjectStructureDetector detector : roots.keySet()) {
+ detector.setupProjectStructure(roots.get(detector), getProjectDescriptor(detector), this);
+ }
}
@NotNull
@@ -316,6 +316,19 @@
return false;
}
+ @Override
+ public void setupModulesByContentRoots(ProjectDescriptor projectDescriptor, Collection<DetectedProjectRoot> roots) {
+ if (projectDescriptor.getModules().isEmpty()) {
+ List<ModuleDescriptor> modules = new ArrayList<ModuleDescriptor>();
+ for (DetectedProjectRoot root : roots) {
+ if (root instanceof DetectedContentRoot) {
+ modules.add(new ModuleDescriptor(root.getDirectory(), ((DetectedContentRoot)root).getModuleType(), Collections.<DetectedSourceRoot>emptyList()));
+ }
+ }
+ projectDescriptor.setModules(modules);
+ }
+ }
+
@NotNull
private static Module createModule(ProjectDescriptor projectDescriptor, final ModuleDescriptor descriptor,
final Map<LibraryDescriptor, Library> projectLibs, final ModifiableModuleModel moduleModel)
@@ -344,8 +357,8 @@
VirtualFile moduleContentRoot = lfs.refreshAndFindFileByPath(FileUtil.toSystemIndependentName(contentRoot.getPath()));
if (moduleContentRoot != null) {
final ContentEntry contentEntry = rootModel.addContentEntry(moduleContentRoot);
- final Collection<DetectedProjectRoot> sourceRoots = descriptor.getSourceRoots(contentRoot);
- for (DetectedProjectRoot srcRoot : sourceRoots) {
+ final Collection<DetectedSourceRoot> sourceRoots = descriptor.getSourceRoots(contentRoot);
+ for (DetectedSourceRoot srcRoot : sourceRoots) {
final String srcpath = FileUtil.toSystemIndependentName(srcRoot.getDirectory().getPath());
final VirtualFile sourceRoot = lfs.refreshAndFindFileByPath(srcpath);
if (sourceRoot != null) {
@@ -372,12 +385,10 @@
}
}
}
-
}
- public static String getPackagePrefix(final DetectedProjectRoot srcRoot) {
- // TODO we can introduce DetectedProjectRootWithPackagePrefix interface
- return srcRoot instanceof JavaModuleSourceRoot ? ((JavaModuleSourceRoot)srcRoot).getPackagePrefix() : "";
+ public static String getPackagePrefix(final DetectedSourceRoot srcRoot) {
+ return srcRoot.getPackagePrefix();
}
@NotNull
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java
index f81f840..8a8a554 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/JdkComboBox.java
@@ -16,13 +16,19 @@
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.ide.DataManager;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ProjectJdkListRenderer;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
+import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.JdkListConfigurable;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.ui.ComboBoxWithWidePopup;
@@ -57,6 +63,7 @@
private final Condition<SdkTypeId> myFilter;
@Nullable
private final Condition<SdkTypeId> myCreationFilter;
+ private JButton mySetUpButton;
public JdkComboBox(@NotNull final ProjectSdksModel jdkModel) {
this(jdkModel, null);
@@ -103,6 +110,57 @@
});
}
+ public static JdkComboBox createSdkComboBox(ModuleBuilder moduleBuilder,
+ Condition<SdkTypeId> sdkFilter,
+ Project project,
+ ProjectSdksModel model) {
+ final JdkComboBox comboBox = new JdkComboBox(model, sdkFilter);
+
+ final PropertiesComponent component = project == null ? PropertiesComponent.getInstance() : PropertiesComponent.getInstance(project);
+ ModuleType moduleType = moduleBuilder.getModuleType();
+ final String selectedJdkProperty = "jdk.selected." + (moduleType == null ? "" : moduleType.getId());
+ comboBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Sdk jdk = comboBox.getSelectedJdk();
+ if (jdk != null) {
+ component.setValue(selectedJdkProperty, jdk.getName());
+ }
+ }
+ });
+
+ if (project != null) {
+ Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
+ if (sdk != null && moduleBuilder.isSuitableSdkType(sdk.getSdkType())) {
+ // use project SDK
+ return null;
+ }
+ }
+ else {
+ // set default project SDK
+ Project defaultProject = ProjectManager.getInstance().getDefaultProject();
+ Sdk sdk = ProjectRootManager.getInstance(defaultProject).getProjectSdk();
+ if (sdk != null && sdkFilter.value(sdk.getSdkType())) {
+ comboBox.setSelectedJdk(sdk);
+ }
+ }
+
+ String value = component.getValue(selectedJdkProperty);
+ if (value != null) {
+ Sdk jdk = ProjectJdkTable.getInstance().findJdk(value);
+ if (jdk != null) {
+ comboBox.setSelectedJdk(jdk);
+ }
+ }
+
+ JButton button = new JButton("Ne\u001Bw...");
+ comboBox.setSetupButton(button, project, model,
+ project == null ? new NoneJdkComboBoxItem() : new ProjectJdkComboBoxItem(),
+ null,
+ false);
+ return comboBox;
+ }
+
@Override
public Dimension getPreferredSize() {
final Rectangle rec = ScreenUtil.getScreenRectangle(0, 0);
@@ -140,7 +198,9 @@
final JdkComboBoxItem firstItem,
@Nullable final Condition<Sdk> additionalSetup,
final String actionGroupTitle) {
- setUpButton.addActionListener(new ActionListener() {
+
+ mySetUpButton = setUpButton;
+ mySetUpButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
DefaultActionGroup group = new DefaultActionGroup();
@@ -199,6 +259,10 @@
});
}
+ public JButton getSetUpButton() {
+ return mySetUpButton;
+ }
+
@Override
public JdkComboBoxItem getSelectedItem() {
return (JdkComboBoxItem)super.getSelectedItem();
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleJdkConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleJdkConfigurable.java
index 378931a..66931e4 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleJdkConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModuleJdkConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -28,7 +28,6 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.roots.ui.configuration.projectRoot.StructureConfigurableContext;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ModuleProjectStructureElement;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
@@ -137,7 +136,7 @@
ProjectBundle.message("project.roots.no.jdk.on.project.message"),
ProjectBundle.message("project.roots.no.jdk.on.project.title"),
Messages.getInformationIcon());
- if (res == DialogWrapper.OK_EXIT_CODE) {
+ if (res == Messages.YES) {
myJdksModel.setProjectSdk(jdk);
return true;
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java
index 89c6617..f553168 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/ModulesConfigurator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -21,7 +21,8 @@
import com.intellij.facet.impl.ProjectFacetsConfigurator;
import com.intellij.facet.impl.ui.FacetEditorImpl;
import com.intellij.ide.actions.ImportModuleAction;
-import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
+import com.intellij.ide.projectWizard.NewProjectWizard;
+import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ProjectBuilder;
import com.intellij.openapi.Disposable;
@@ -430,14 +431,14 @@
@Nullable
ProjectBuilder runModuleWizard(Component dialogParent, boolean anImport) {
- AddModuleWizard wizard;
+ AbstractProjectWizard wizard;
if (anImport) {
wizard = ImportModuleAction.selectFileAndCreateWizard(myProject, dialogParent);
if (wizard == null) return null;
if (wizard.getStepCount() == 0) return wizard.getProjectBuilder();
}
else {
- wizard = new AddModuleWizard(dialogParent, myProject, this);
+ wizard = new NewProjectWizard(myProject, dialogParent, this);
}
wizard.show();
if (wizard.isOK()) {
@@ -472,7 +473,7 @@
}
int result =
Messages.showYesNoDialog(myProject, question, ProjectBundle.message("module.remove.confirmation.title"), Messages.getQuestionIcon());
- if (result != 0) {
+ if (result != Messages.YES) {
return false;
}
// do remove
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleAction.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleAction.java
index c04f91d..1139775 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleAction.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/actions/NewModuleAction.java
@@ -15,22 +15,19 @@
*/
package com.intellij.openapi.roots.ui.configuration.actions;
+import com.intellij.ide.projectWizard.NewProjectWizard;
import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard;
-import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
-import com.intellij.ide.util.newProjectWizard.AddModuleWizardPro;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.ide.util.projectWizard.ProjectBuilder;
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.module.Module;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.roots.ui.configuration.DefaultModulesProvider;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
-import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
@@ -58,9 +55,7 @@
if (virtualFile != null && virtualFile.isDirectory()) {
defaultPath = virtualFile.getPath();
}
- final AddModuleWizard wizard = Registry.is("new.project.wizard")
- ? new AddModuleWizardPro(project, new DefaultModulesProvider(project), defaultPath)
- : new AddModuleWizard(project, new DefaultModulesProvider(project), defaultPath);
+ NewProjectWizard wizard = new NewProjectWizard(project, new DefaultModulesProvider(project), defaultPath);
wizard.show();
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java
index 4d0da3e..f559559 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/ArtifactErrorPanel.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.roots.ui.configuration.artifacts;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ConfigurationErrorQuickFix;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupStep;
@@ -96,7 +97,7 @@
myCurrentQuickFixes = quickFixes;
myFixButton.setVisible(!quickFixes.isEmpty());
if (!quickFixes.isEmpty()) {
- myFixButton.setText(quickFixes.size() == 1 ? ContainerUtil.getFirstItem(quickFixes, null).getActionName() : "Fix...");
+ myFixButton.setText(quickFixes.size() == 1 ? ContainerUtil.getFirstItem(quickFixes, null).getActionName() : IdeBundle.message("button.fix"));
}
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
index d778e88..ff1fdd3 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/artifacts/LayoutTreeComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -282,7 +282,7 @@
message = "The selected node belongs to " + nodes.size() + " elements. Do you want to remove all these elements from the artifact?";
}
final int answer = Messages.showYesNoDialog(myArtifactsEditor.getMainComponent(), message, "Remove Elements", null);
- if (answer != 0) return false;
+ if (answer != Messages.YES) return false;
}
return true;
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java
index be87d34..25108a7 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/classpath/ClasspathPanelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -47,7 +47,6 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.SdkProjectStructureElement;
import com.intellij.openapi.ui.ComboBoxTableRenderer;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
@@ -787,7 +786,7 @@
}
if (Messages.showOkCancelDialog(myEntryTable,
"No code dependencies were found. Would you like to remove the dependency?",
- CommonBundle.getWarningTitle(), Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ CommonBundle.getWarningTitle(), Messages.getWarningIcon()) == Messages.OK) {
removeSelectedItems(TableUtil.removeSelectedItems(myEntryTable));
}
return false;
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java
index c7d8570..33445bd 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/CreateNewLibraryDialog.java
@@ -27,6 +27,7 @@
import com.intellij.openapi.ui.ComboBox;
import com.intellij.util.ui.FormBuilder;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
@@ -92,4 +93,10 @@
protected boolean shouldCheckName(String newName) {
return true;
}
+
+ @Nullable
+ @Override
+ protected String getHelpId() {
+ return "Create_Library_dialog";
+ }
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java
index 5723938..040ad01 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/EditExistingLibraryDialog.java
@@ -98,6 +98,12 @@
return myTableModifiableModel;
}
+ @Nullable
+ @Override
+ protected String getHelpId() {
+ return "Configure_Library_Dialog";
+ }
+
@Override
protected boolean shouldCheckName(String newName) {
return !Comparing.equal(newName, getLibraryRootsComponent().getLibraryEditor().getName());
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
index b69163f..b6dd460 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/libraryEditor/LibraryRootsComponent.java
@@ -20,10 +20,7 @@
import com.intellij.ide.util.treeView.AbstractTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
@@ -53,8 +50,10 @@
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.IconUtil;
import com.intellij.util.PathUtil;
-import com.intellij.util.containers.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.FilteringIterator;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -156,48 +155,15 @@
myTreePanel.setLayout(new BorderLayout());
ToolbarDecorator toolbarDecorator = ToolbarDecorator.createDecorator(myTree).disableUpDownActions()
- .setRemoveActionName(ProjectBundle.message("library.detach.action"))
- .setRemoveAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- final Object[] selectedElements = getSelectedElements();
- if (selectedElements.length == 0) {
- return;
- }
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- for (Object selectedElement : selectedElements) {
- if (selectedElement instanceof ItemElement) {
- final ItemElement itemElement = (ItemElement)selectedElement;
- getLibraryEditor().removeRoot(itemElement.getUrl(), itemElement.getRootType());
- }
- else if (selectedElement instanceof OrderRootTypeElement) {
- final OrderRootType rootType = ((OrderRootTypeElement)selectedElement).getOrderRootType();
- final String[] urls = getLibraryEditor().getUrls(rootType);
- for (String url : urls) {
- getLibraryEditor().removeRoot(url, rootType);
- }
- }
- else if (selectedElement instanceof ExcludedRootElement) {
- getLibraryEditor().removeExcludedRoot(((ExcludedRootElement)selectedElement).getUrl());
- }
- }
- }
- });
- libraryChanged(true);
- }
- });
+ .setRemoveActionName(ProjectBundle.message("library.remove.action"))
+ .disableRemoveAction();
- List<String> actionsOrder = new ArrayList<String>();
- actionsOrder.add("Add");
final List<AttachRootButtonDescriptor> popupItems = new ArrayList<AttachRootButtonDescriptor>();
for (AttachRootButtonDescriptor descriptor : myDescriptor.createAttachButtons()) {
Icon icon = descriptor.getToolbarIcon();
if (icon != null) {
AttachItemAction action = new AttachItemAction(descriptor, descriptor.getButtonText(), icon);
toolbarDecorator.addExtraAction(AnActionButton.fromAction(action));
- actionsOrder.add(action.getTemplatePresentation().getText());
}
else {
popupItems.add(descriptor);
@@ -205,9 +171,55 @@
}
myAddExcludedRootActionButton = new AddExcludedRootActionButton();
toolbarDecorator.addExtraAction(myAddExcludedRootActionButton);
- actionsOrder.add(myAddExcludedRootActionButton.getTemplatePresentation().getText());
- actionsOrder.add("Remove");
+ toolbarDecorator.addExtraAction(new AnActionButton("Remove", IconUtil.getRemoveIcon()) {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final Object[] selectedElements = getSelectedElements();
+ if (selectedElements.length == 0) {
+ return;
+ }
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ for (Object selectedElement : selectedElements) {
+ if (selectedElement instanceof ItemElement) {
+ final ItemElement itemElement = (ItemElement)selectedElement;
+ getLibraryEditor().removeRoot(itemElement.getUrl(), itemElement.getRootType());
+ }
+ else if (selectedElement instanceof OrderRootTypeElement) {
+ final OrderRootType rootType = ((OrderRootTypeElement)selectedElement).getOrderRootType();
+ final String[] urls = getLibraryEditor().getUrls(rootType);
+ for (String url : urls) {
+ getLibraryEditor().removeRoot(url, rootType);
+ }
+ }
+ else if (selectedElement instanceof ExcludedRootElement) {
+ getLibraryEditor().removeExcludedRoot(((ExcludedRootElement)selectedElement).getUrl());
+ }
+ }
+ }
+ });
+ libraryChanged(true);
+ }
+ @Override
+ public void updateButton(AnActionEvent e) {
+ super.updateButton(e);
+ Object[] elements = getSelectedElements();
+ Presentation presentation = e.getPresentation();
+ if (ContainerUtil.and(elements, new FilteringIterator.InstanceOf<ExcludedRootElement>(ExcludedRootElement.class))) {
+ presentation.setText("Cancel Exclusion");
+ }
+ else {
+ presentation.setText(getTemplatePresentation().getText());
+ }
+ }
+
+ @Override
+ public ShortcutSet getShortcut() {
+ return CommonShortcuts.DELETE;
+ }
+ });
toolbarDecorator.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
@@ -228,7 +240,6 @@
.show(button.getPreferredPopupPoint());
}
});
- toolbarDecorator.setButtonComparator(ArrayUtil.toStringArray(actionsOrder));
myTreePanel.add(toolbarDecorator.createPanel(), BorderLayout.CENTER);
Disposer.register(this, myTreeBuilder);
@@ -511,13 +522,13 @@
private class AddExcludedRootActionButton extends AnActionButton {
public AddExcludedRootActionButton() {
- super("Add Excluded", null, AllIcons.Modules.ExcludeRoot);
+ super("Exclude", null, AllIcons.Modules.AddExcludedRoot);
}
@Override
public void actionPerformed(AnActionEvent e) {
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createMultipleJavaPathDescriptor();
- descriptor.setTitle("Add Excluded Roots");
+ descriptor.setTitle("Exclude from Library");
descriptor.setDescription("Select directories which should be excluded from the library content. Content of excluded directories won't be processed by IDE.");
Set<VirtualFile> roots = getNotExcludedRoots();
descriptor.setRoots(roots.toArray(new VirtualFile[roots.size()]));
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java
index 2552631..2f38609 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/BaseLibrariesConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -33,7 +33,6 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureDaemonAnalyzer;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElementUsage;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.NamedConfigurable;
import com.intellij.openapi.ui.NonEmptyInputValidator;
@@ -235,25 +234,25 @@
@Override
protected void updateSelection(@Nullable NamedConfigurable configurable) {
boolean selectionChanged = !Comparing.equal(myCurrentConfigurable, configurable);
- if (myCurrentConfigurable != null && selectionChanged) {
+ if (myCurrentConfigurable instanceof LibraryConfigurable && selectionChanged) {
((LibraryConfigurable)myCurrentConfigurable).onUnselected();
}
super.updateSelection(configurable);
- if (myCurrentConfigurable != null && selectionChanged) {
+ if (myCurrentConfigurable instanceof LibraryConfigurable && selectionChanged) {
((LibraryConfigurable)myCurrentConfigurable).onSelected();
}
}
@Override
public void onStructureUnselected() {
- if (myCurrentConfigurable != null) {
+ if (myCurrentConfigurable instanceof LibraryConfigurable) {
((LibraryConfigurable)myCurrentConfigurable).onUnselected();
}
}
@Override
public void onStructureSelected() {
- if (myCurrentConfigurable != null) {
+ if (myCurrentConfigurable instanceof LibraryConfigurable) {
((LibraryConfigurable)myCurrentConfigurable).onSelected();
}
}
@@ -313,7 +312,7 @@
sb.append(".\n\nAre you sure you want to delete this library?");
- if (DialogWrapper.OK_EXIT_CODE == Messages.showOkCancelDialog(myProject, sb.toString(),
+ if (Messages.OK == Messages.showOkCancelDialog(myProject, sb.toString(),
"Delete Library", Messages.getQuestionIcon())) {
for (final ProjectStructureElementUsage usage : usages) {
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
index 75899d3..e5a008d 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/FacetStructureConfigurable.java
@@ -35,6 +35,7 @@
import com.intellij.openapi.roots.ui.configuration.projectRoot.daemon.ProjectStructureElement;
import com.intellij.openapi.ui.DetailsComponent;
import com.intellij.openapi.ui.NamedConfigurable;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.util.ui.tree.TreeUtil;
import org.jetbrains.annotations.NonNls;
@@ -154,7 +155,7 @@
if (c1 instanceof FrameworkDetectionConfigurable && !(c2 instanceof FrameworkDetectionConfigurable)) return 1;
if (!(c1 instanceof FrameworkDetectionConfigurable) && c2 instanceof FrameworkDetectionConfigurable) return -1;
- return node1.getDisplayName().compareToIgnoreCase(node2.getDisplayName());
+ return StringUtil.naturalCompare(node1.getDisplayName(), node2.getDisplayName());
}
};
}
diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
index 0614771..44d7820 100644
--- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
+++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/projectRoot/ModuleStructureConfigurable.java
@@ -90,7 +90,7 @@
final NamedConfigurable configurable1 = o1.getConfigurable();
final NamedConfigurable configurable2 = o2.getConfigurable();
if (configurable1.getClass() == configurable2.getClass()) {
- return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
+ return StringUtil.naturalCompare(o1.getDisplayName(), o2.getDisplayName());
}
final Object editableObject1 = configurable1.getEditableObject();
final Object editableObject2 = configurable2.getEditableObject();
@@ -530,7 +530,7 @@
if (Messages.showYesNoDialog(parent,
ProjectBundle.message("project.roots.replace.library.entry.message", entry.getPresentableName()),
ProjectBundle.message("project.roots.replace.library.entry.title"),
- Messages.getInformationIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getInformationIcon()) == Messages.YES) {
modelProxy.removeOrderEntry(entry);
break;
}
diff --git a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/NewProjectCheckoutListener.java b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/NewProjectCheckoutListener.java
index 0abd54f..52f0f6b 100644
--- a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/NewProjectCheckoutListener.java
+++ b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/NewProjectCheckoutListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -44,7 +44,7 @@
ProjectCheckoutListener.getProductNameWithArticle(),
directory.getAbsolutePath()),
VcsBundle.message("checkout.title"), Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
final ProjectManager pm = ProjectManager.getInstance();
final Project[] projects = pm.getOpenProjects();
final Set<VirtualFile> files = projectsLocationSet(projects);
diff --git a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectCheckoutListener.java b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectCheckoutListener.java
index 5c91519..f7bc32e 100644
--- a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectCheckoutListener.java
+++ b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectCheckoutListener.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,7 +39,7 @@
int rc = Messages
.showYesNoDialog(project, VcsBundle.message("checkout.open.project.prompt", getProductNameWithArticle(), files[0].getPath()),
VcsBundle.message("checkout.title"), Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
ProjectUtil.openProject(files[0].getPath(), project, false);
}
return true;
@@ -55,7 +55,7 @@
final ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance();
// example: "to create an IntelliJ IDEA project" (full product name is ok);
// "to create a JetBrains Astella project" (better use not full product name: "to create an Astella project")
- final String productName = PlatformUtils.isIdea() ? namesInfo.getFullProductName() : namesInfo.getProductName();
+ final String productName = PlatformUtils.isIdeaUltimate() ? namesInfo.getFullProductName() : namesInfo.getProductName();
final String article = StringUtil.isVowel(Character.toLowerCase(productName.charAt(0))) ? "an " : "a ";
return article + productName;
}
diff --git a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectDirCheckoutListener.java b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectDirCheckoutListener.java
index 4909d76..a25ff87 100644
--- a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectDirCheckoutListener.java
+++ b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectDirCheckoutListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -33,7 +33,7 @@
String message = VcsBundle.message("checkout.open.project.dir.prompt",
ProjectCheckoutListener.getProductNameWithArticle(), directory.getPath());
int rc = Messages.showYesNoDialog(project, message, VcsBundle.message("checkout.title"), Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
ProjectUtil.openProject(directory.getPath(), project, false);
}
return true;
diff --git a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectImporterCheckoutListener.java b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectImporterCheckoutListener.java
index 2c42d3b..1846bcd 100644
--- a/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectImporterCheckoutListener.java
+++ b/java/idea-ui/src/com/intellij/openapi/vcs/checkout/ProjectImporterCheckoutListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -39,7 +39,7 @@
int rc = Messages
.showYesNoDialog(project, VcsBundle.message("checkout.open.project.prompt", ProjectCheckoutListener.getProductNameWithArticle(), file.getPath()),
VcsBundle.message("checkout.title"), Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
openProcessor.doOpenProject(virtualFile, project, false);
}
return true;
diff --git a/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java b/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java
index 3902389..5e37d69 100644
--- a/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java
+++ b/java/idea-ui/src/com/intellij/openapi/wm/impl/welcomeScreen/DevelopPluginsAction.java
@@ -35,10 +35,10 @@
public void actionPerformed(final AnActionEvent e) {
try {
if (new File(PLUGIN_URL).isFile()) {
- BrowserUtil.launchBrowser(PLUGIN_URL);
+ BrowserUtil.browse(PLUGIN_URL);
}
else {
- BrowserUtil.launchBrowser(PLUGIN_WEBSITE);
+ BrowserUtil.browse(PLUGIN_WEBSITE);
}
}
catch(IllegalStateException ex) {
diff --git a/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java
index b2ea502..23f4e7e 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/ArchivedTemplatesFactory.java
@@ -15,9 +15,8 @@
*/
package com.intellij.platform.templates;
+import com.intellij.icons.AllIcons;
import com.intellij.ide.fileTemplates.impl.UrlUtil;
-import com.intellij.ide.plugins.IdeaPluginDescriptor;
-import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -29,6 +28,7 @@
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
+import javax.swing.*;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
@@ -48,22 +48,21 @@
@Override
protected MultiMap<String, Pair<URL, ClassLoader>> compute() {
MultiMap<String, Pair<URL, ClassLoader>> map = new MultiMap<String, Pair<URL, ClassLoader>>();
- IdeaPluginDescriptor[] plugins = PluginManagerCore.getPlugins();
Map<URL, ClassLoader> urls = new HashMap<URL, ClassLoader>();
- for (IdeaPluginDescriptor plugin : plugins) {
- if (!plugin.isEnabled()) continue;
- try {
- ClassLoader loader = plugin.getPluginClassLoader();
- Enumeration<URL> resources = loader.getResources("resources/projectTemplates");
- ArrayList<URL> list = Collections.list(resources);
- for (URL url : list) {
- urls.put(url, loader);
- }
- }
- catch (IOException e) {
- LOG.error(e);
- }
- }
+ //for (IdeaPluginDescriptor plugin : plugins) {
+ // if (!plugin.isEnabled()) continue;
+ // try {
+ // ClassLoader loader = plugin.getPluginClassLoader();
+ // Enumeration<URL> resources = loader.getResources("resources/projectTemplates");
+ // ArrayList<URL> list = Collections.list(resources);
+ // for (URL url : list) {
+ // urls.put(url, loader);
+ // }
+ // }
+ // catch (IOException e) {
+ // LOG.error(e);
+ // }
+ //}
URL configURL = getCustomTemplatesURL();
if (configURL != null) {
@@ -149,5 +148,10 @@
return CUSTOM_GROUP.equals(group) ? -2 : 0;
}
+ @Override
+ public Icon getGroupIcon(String group) {
+ return CUSTOM_GROUP.equals(group) ? AllIcons.Modules.Types.UserDefined : super.getGroupIcon(group);
+ }
+
private final static Logger LOG = Logger.getInstance(ArchivedTemplatesFactory.class);
}
diff --git a/java/idea-ui/src/com/intellij/platform/templates/PlainModuleTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/PlainModuleTemplatesFactory.java
deleted file mode 100644
index 464bfb6..0000000
--- a/java/idea-ui/src/com/intellij/platform/templates/PlainModuleTemplatesFactory.java
+++ /dev/null
@@ -1,97 +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.platform.templates;
-
-import com.intellij.ide.projectWizard.EmptyProjectBuilder;
-import com.intellij.ide.util.projectWizard.ModuleBuilder;
-import com.intellij.ide.util.projectWizard.WizardContext;
-import com.intellij.platform.ProjectTemplate;
-import com.intellij.platform.ProjectTemplatesFactory;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.Function;
-import com.intellij.util.NullableFunction;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Dmitry Avdeev
- * Date: 10/9/12
- */
-public class PlainModuleTemplatesFactory extends ProjectTemplatesFactory {
-
- @NotNull
- @Override
- public String[] getGroups() {
- List<ModuleBuilder> builders = ModuleBuilder.getAllBuilders();
- Set<String> groups = ContainerUtil.map2Set(builders, new Function<ModuleBuilder, String>() {
- @Override
- public String fun(ModuleBuilder builder) {
- return builder.getGroupName();
- }
- });
- HashSet<String> set = new HashSet<String>(groups);
- set.add(OTHER_GROUP);
- return ArrayUtil.toStringArray(set);
- }
-
- @NotNull
- @Override
- public ProjectTemplate[] createTemplates(final String group, WizardContext context) {
- if (OTHER_GROUP.equals(group)) {
- if (!context.isCreatingNewProject()) {
- return ProjectTemplate.EMPTY_ARRAY;
- }
- return new ProjectTemplate[]{new BuilderBasedTemplate(new EmptyProjectBuilder())};
- }
- List<ModuleBuilder> builders = ModuleBuilder.getAllBuilders();
- List<ProjectTemplate> templates = ContainerUtil.mapNotNull(builders, new NullableFunction<ModuleBuilder, ProjectTemplate>() {
- @Nullable
- @Override
- public ProjectTemplate fun(ModuleBuilder builder) {
- return builder.getGroupName().equals(group) ? new BuilderBasedTemplate(builder) : null;
- }
- });
- return templates.toArray(new ProjectTemplate[templates.size()]);
- }
-
- @Override
- public Icon getGroupIcon(String group) {
- List<ModuleBuilder> builders = ModuleBuilder.getAllBuilders();
- for (ModuleBuilder builder : builders) {
- if (group.equals(builder.getGroupName())) {
- return builder.getNodeIcon();
- }
- }
- return null;
- }
-
- @Override
- public int getGroupWeight(String group) {
- List<ModuleBuilder> builders = ModuleBuilder.getAllBuilders();
- for (int i = 0; i < builders.size(); i++) {
- if (group.equals(builders.get(i).getGroupName())) {
- return builders.size() - i;
- }
- }
- return 0;
- }
-}
diff --git a/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java b/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java
index d5e839b..5ddafe0 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/TemplateModuleBuilder.java
@@ -53,7 +53,6 @@
import javax.swing.*;
import java.io.File;
import java.io.IOException;
-import java.util.Collections;
import java.util.List;
import java.util.Properties;
import java.util.zip.ZipInputStream;
@@ -85,7 +84,6 @@
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
ModuleBuilder builder = myType.createModuleBuilder();
- builder.setAvailableFrameworks(Collections.<String, Boolean>emptyMap());
return builder.createWizardSteps(wizardContext, modulesProvider);
}
@@ -156,6 +154,11 @@
return myTemplate.getIcon();
}
+ @Override
+ public boolean isTemplateBased() {
+ return true;
+ }
+
@NotNull
@Override
public Module createModule(@NotNull ModifiableModuleModel moduleModel)
diff --git a/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java b/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java
index 7ede6a8..a7bb76b 100644
--- a/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java
+++ b/java/idea-ui/src/com/intellij/projectImport/ProjectOpenProcessorBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -186,8 +186,8 @@
IdeBundle.message("project.import.open.existing.reimport"),
CommonBundle.message("button.cancel"),
Messages.getQuestionIcon());
- if (result == 2) return null;
- shouldOpenExisting = result == 0;
+ if (result == Messages.CANCEL) return null;
+ shouldOpenExisting = result == Messages.YES;
}
final Project projectToOpen;
diff --git a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java
index 45edd4a..db9b58b 100644
--- a/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java
+++ b/java/idea-ui/src/com/intellij/util/descriptors/impl/ConfigFileImpl.java
@@ -1,3 +1,18 @@
+/*
+ * 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.util.descriptors.impl;
import com.intellij.openapi.project.Project;
@@ -71,8 +86,7 @@
@Override
@Nullable
public PsiFile getPsiFile() {
- Reference<PsiFile> ref = myPsiFile;
- PsiFile psiFile = ref == null ? null : ref.get();
+ PsiFile psiFile = com.intellij.reference.SoftReference.dereference(myPsiFile);
if (psiFile != null && psiFile.isValid()) {
return psiFile;
diff --git a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java
index f14f9ec..edd7adb 100644
--- a/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.java
+++ b/java/java-analysis-api/src/com/intellij/codeInsight/intention/QuickFixFactory.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 @@
import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
@@ -222,6 +223,26 @@
public abstract void registerPullAsAbstractUpFixes(@NotNull PsiMethod method, @NotNull QuickFixActionRegistrar registrar);
- public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair);
+ @NotNull
+ public abstract IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair);
+ @NotNull
+ public abstract IntentionAction createOptimizeImportsFix();
+
+ public abstract void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo);
+
+ @NotNull
+ public abstract IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project, @NotNull String qualifiedName, @NotNull String element);
+
+ @NotNull
+ public abstract IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field);
+
+ @NotNull
+ public abstract IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement);
+
+ @NotNull
+ public abstract IntentionAction createEnableOptimizeImportsOnTheFlyFix();
+
+ @NotNull
+ public abstract IntentionAction createSafeDeleteFix(@NotNull PsiElement element);
}
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java b/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java
index 6a4d049..7a8065b 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/AbstractBaseJavaLocalInspectionTool.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class AbstractBaseJavaLocalInspectionTool extends LocalInspectionTool {
+public abstract class AbstractBaseJavaLocalInspectionTool extends LocalInspectionTool {
/**
* Override this to report problems at method level.
*
diff --git a/java/java-analysis-api/src/com/intellij/codeInspection/BaseJavaBatchLocalInspectionTool.java b/java/java-analysis-api/src/com/intellij/codeInspection/BaseJavaBatchLocalInspectionTool.java
index 36d4596..18f1c51 100644
--- a/java/java-analysis-api/src/com/intellij/codeInspection/BaseJavaBatchLocalInspectionTool.java
+++ b/java/java-analysis-api/src/com/intellij/codeInspection/BaseJavaBatchLocalInspectionTool.java
@@ -20,6 +20,12 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+/**
+ * Base java local inspection which provides batch suppress actions, i.e. actions which don't need UI components to run (e.g. Editor).
+ * Please use this class if your inspection and its fixes
+ * - work with PSI or document only and
+ * - don't provide {@link com.intellij.codeInsight.intention.IntentionAction} for quick fixes/suppression, making do with {@link LocalQuickFix} only.
+ */
public abstract class BaseJavaBatchLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool implements BatchSuppressableTool {
@NotNull
@Override
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java
new file mode 100644
index 0000000..469d03a
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.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.codeInsight.daemon.impl;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMember;
+import com.intellij.psi.PsiNamedElement;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author peter
+ */
+public abstract class GlobalUsageHelper {
+ final Map<PsiClass,Boolean> unusedClassCache = new HashMap<PsiClass, Boolean>();
+
+ public abstract boolean shouldCheckUsages(@NotNull PsiMember member);
+ public abstract boolean isLocallyUsed(@NotNull PsiNamedElement member);
+ public abstract boolean isCurrentFileAlreadyChecked();
+}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
new file mode 100644
index 0000000..83bec19
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
@@ -0,0 +1,809 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.impl;
+
+import com.intellij.codeHighlighting.Pass;
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
+import com.intellij.codeInsight.daemon.JavaErrorMessages;
+import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
+import com.intellij.codeInsight.daemon.impl.analysis.*;
+import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
+import com.intellij.codeInsight.intention.EmptyIntentionAction;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.intention.QuickFixFactory;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.InspectionsBundle;
+import com.intellij.codeInspection.SuppressionUtil;
+import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
+import com.intellij.codeInspection.ex.EntryPointsManagerBase;
+import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
+import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
+import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
+import com.intellij.lang.Language;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.PomNamedTarget;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.impl.PsiClassImplUtil;
+import com.intellij.psi.impl.source.PsiClassImpl;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiNonJavaFileReferenceProcessor;
+import com.intellij.psi.search.PsiSearchHelper;
+import com.intellij.psi.search.SearchScope;
+import com.intellij.psi.search.searches.OverridingMethodsSearch;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.search.searches.SuperMethodsSearch;
+import com.intellij.psi.util.PropertyUtil;
+import com.intellij.psi.util.PsiModificationTracker;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.Predicate;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
+ private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
+ private RefCountHolder myRefCountHolder;
+ private final PsiFile myFile;
+ @Nullable private final Editor myEditor;
+ private final boolean myUnusedImportEnabled;
+ @NotNull private final Predicate<PsiElement> myIsEntryPointPredicate;
+ private final int myStartOffset;
+ private final int myEndOffset;
+
+ private Collection<HighlightInfo> myHighlights;
+ private boolean myHasRedundantImports;
+ private int myCurrentEntryIndex;
+ private boolean myHasMissortedImports;
+ private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
+ private UnusedSymbolLocalInspectionBase myUnusedSymbolInspection;
+ private HighlightDisplayKey myUnusedSymbolKey;
+ private boolean myInLibrary;
+ private HighlightDisplayKey myDeadCodeKey;
+ private HighlightInfoType myDeadCodeInfoType;
+
+ public PostHighlightingPass(@NotNull Project project,
+ @NotNull PsiFile file,
+ @Nullable Editor editor,
+ @NotNull Document document,
+ @NotNull HighlightInfoProcessor highlightInfoProcessor,
+ boolean unusedImportEnabled,
+ @NotNull Predicate<PsiElement> isEntryPoint) {
+ super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor);
+ myFile = file;
+ myEditor = editor;
+ myUnusedImportEnabled = unusedImportEnabled;
+ myIsEntryPointPredicate = isEntryPoint;
+ myStartOffset = 0;
+ myEndOffset = file.getTextLength();
+
+ myCurrentEntryIndex = -1;
+ }
+
+ static boolean isUpToDate(@NotNull PsiFile file) {
+ Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
+ long currentStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
+ return lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file);
+ }
+
+ private static void markFileUpToDate(@NotNull PsiFile file) {
+ long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
+ file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
+ }
+
+ private static boolean isInjected(@NotNull Project project, @NotNull PsiModifierListOwner modifierListOwner) {
+ return EntryPointsManagerBase.getInstance(project).isEntryPoint(modifierListOwner);
+ }
+
+ @Override
+ protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
+ DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
+ final FileStatusMap fileStatusMap = daemonCodeAnalyzer.getFileStatusMap();
+ final List<HighlightInfo> highlights = new ArrayList<HighlightInfo>();
+ final FileViewProvider viewProvider = myFile.getViewProvider();
+ final Set<Language> relevantLanguages = viewProvider.getLanguages();
+ final Set<PsiElement> elementSet = new THashSet<PsiElement>();
+ for (Language language : relevantLanguages) {
+ PsiElement psiRoot = viewProvider.getPsi(language);
+ if (!HighlightingLevelManager.getInstance(myProject).shouldHighlight(psiRoot)) continue;
+ List<PsiElement> elements = CollectHighlightsUtil.getElementsInRange(psiRoot, myStartOffset, myEndOffset);
+ elementSet.addAll(elements);
+ }
+
+ ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
+ VirtualFile virtualFile = viewProvider.getVirtualFile();
+ myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);
+
+ myRefCountHolder = RefCountHolder.endUsing(myFile, progress);
+ if (myRefCountHolder == null || !myRefCountHolder.retrieveUnusedReferencesInfo(progress, new Runnable() {
+ @Override
+ public void run() {
+ boolean errorFound = collectHighlights(elementSet, highlights, progress);
+ myHighlights = highlights;
+ if (errorFound) {
+ fileStatusMap.setErrorFoundFlag(myDocument, true);
+ }
+ }
+ })) {
+ // we must be sure GHP will restart
+ fileStatusMap.markFileScopeDirty(getDocument(), Pass.UPDATE_ALL);
+ GeneralHighlightingPass.cancelAndRestartDaemonLater(progress, myProject, this);
+ }
+ }
+
+ @Override
+ public List<HighlightInfo> getInfos() {
+ return myHighlights == null ? null : new ArrayList<HighlightInfo>(myHighlights);
+ }
+
+ @Override
+ protected void applyInformationWithProgress() {
+ if (myHighlights == null) return;
+ UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL);
+ markFileUpToDate(myFile);
+
+ Editor editor = myEditor;
+ if (editor != null) {
+ optimizeImportsOnTheFly(editor);
+ }
+ }
+
+ private void optimizeImportsOnTheFly(@NotNull final Editor editor) {
+ if (myHasRedundantImports || myHasMissortedImports) {
+ IntentionAction optimizeImportsFix = QuickFixFactory.getInstance().createOptimizeImportsFix();
+ if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) {
+ optimizeImportsFix.invoke(myProject, editor, myFile);
+ }
+ }
+ }
+
+ // returns true if error highlight was created
+ private boolean collectHighlights(@NotNull Collection<PsiElement> elements,
+ @NotNull final List<HighlightInfo> result,
+ @NotNull ProgressIndicator progress) throws ProcessCanceledException {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+
+ InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
+ myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspectionBase.SHORT_NAME);
+ boolean unusedSymbolEnabled = profile.isToolEnabled(myUnusedSymbolKey, myFile);
+ myUnusedSymbolInspection = (UnusedSymbolLocalInspectionBase)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.SHORT_NAME, myFile);
+ LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null);
+
+ myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);
+
+ HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
+
+ myDeadCodeInfoType = myDeadCodeKey == null
+ ? HighlightInfoType.UNUSED_SYMBOL
+ : new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(),
+ HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());
+
+ GlobalUsageHelper helper = new GlobalUsageHelper() {
+ @Override
+ public boolean shouldCheckUsages(@NotNull PsiMember member) {
+ return !myInLibrary && !myIsEntryPointPredicate.apply(member);
+ }
+
+ @Override
+ public boolean isCurrentFileAlreadyChecked() {
+ return true;
+ }
+
+ @Override
+ public boolean isLocallyUsed(@NotNull PsiNamedElement member) {
+ return myRefCountHolder.isReferenced(member);
+ }
+ };
+
+ boolean errorFound = false;
+ if (unusedSymbolEnabled) {
+ for (PsiElement element : elements) {
+ progress.checkCanceled();
+ if (element instanceof PsiIdentifier) {
+ PsiIdentifier identifier = (PsiIdentifier)element;
+ HighlightInfo info = processIdentifier(identifier, progress, helper);
+ if (info != null) {
+ errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
+ result.add(info);
+ }
+ }
+ }
+ }
+ if (myUnusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) {
+ PsiImportList importList = ((PsiJavaFile)myFile).getImportList();
+ if (importList != null) {
+ final PsiImportStatementBase[] imports = importList.getAllImportStatements();
+ for (PsiImportStatementBase statement : imports) {
+ progress.checkCanceled();
+ final HighlightInfo info = processImport(statement, unusedImportKey);
+ if (info != null) {
+ errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
+ result.add(info);
+ }
+ }
+ }
+ }
+
+ return errorFound;
+ }
+
+ @Nullable
+ private HighlightInfo processIdentifier(@NotNull PsiIdentifier identifier, @NotNull ProgressIndicator progress, @NotNull GlobalUsageHelper helper) {
+ if (SuppressionUtil.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null;
+ PsiElement parent = identifier.getParent();
+ if (PsiUtilCore.hasErrorElementChild(parent)) return null;
+
+ if (parent instanceof PsiLocalVariable && myUnusedSymbolInspection.LOCAL_VARIABLE) {
+ return processLocalVariable((PsiLocalVariable)parent, identifier, progress);
+ }
+ if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) {
+ return processField(myProject, (PsiField)parent, identifier, progress, helper);
+ }
+ if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
+ if (SuppressionUtil.isSuppressed(identifier, UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME)) return null;
+ return processParameter(myProject, (PsiParameter)parent, identifier, progress);
+ }
+ if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
+ return processMethod(myProject, (PsiMethod)parent, identifier, progress, helper);
+ }
+ if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) {
+ return processClass(myProject, (PsiClass)parent, identifier, progress, helper);
+ }
+ return null;
+ }
+
+ @Nullable
+ private HighlightInfo processLocalVariable(@NotNull PsiLocalVariable variable,
+ @NotNull PsiIdentifier identifier,
+ @NotNull ProgressIndicator progress) {
+ if (variable instanceof PsiResourceVariable && PsiUtil.isIgnoredName(variable.getName())) return null;
+ if (isImplicitUsage(myProject, variable, progress)) return null;
+
+ if (!myRefCountHolder.isReferenced(variable)) {
+ String message = JavaErrorMessages.message("local.variable.is.never.used", identifier.getText());
+ HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
+ IntentionAction fix = variable instanceof PsiResourceVariable ? QuickFixFactory.getInstance().createRenameToIgnoredFix(variable) : QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable);
+ QuickFixAction.registerQuickFixAction(highlightInfo, fix, myUnusedSymbolKey);
+ return highlightInfo;
+ }
+
+ boolean referenced = myRefCountHolder.isReferencedForRead(variable);
+ if (!referenced && !isImplicitRead(myProject, variable, progress)) {
+ String message = JavaErrorMessages.message("local.variable.is.not.used.for.reading", identifier.getText());
+ HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(variable), myUnusedSymbolKey);
+ return highlightInfo;
+ }
+
+ if (!variable.hasInitializer()) {
+ referenced = myRefCountHolder.isReferencedForWrite(variable);
+ if (!referenced && !isImplicitWrite(myProject, variable, progress)) {
+ String message = JavaErrorMessages.message("local.variable.is.not.assigned", identifier.getText());
+ final HighlightInfo unusedSymbolInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
+ QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspectionBase.DISPLAY_NAME), myUnusedSymbolKey);
+ return unusedSymbolInfo;
+ }
+ }
+
+ return null;
+ }
+
+ public static boolean isImplicitUsage(@NotNull Project project,
+ @NotNull PsiModifierListOwner element,
+ @NotNull ProgressIndicator progress) {
+ if (isInjected(project, element)) return true;
+ for (ImplicitUsageProvider provider : ourImplicitUsageProviders) {
+ progress.checkCanceled();
+ if (provider.isImplicitUsage(element)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static boolean isImplicitRead(@NotNull Project project, @NotNull PsiVariable element, @NotNull ProgressIndicator progress) {
+ for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
+ progress.checkCanceled();
+ if (provider.isImplicitRead(element)) {
+ return true;
+ }
+ }
+ return isInjected(project, element);
+ }
+
+ private static boolean isImplicitWrite(@NotNull Project project,
+ @NotNull PsiVariable element,
+ @NotNull ProgressIndicator progress) {
+ for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
+ progress.checkCanceled();
+ if (provider.isImplicitWrite(element)) {
+ return true;
+ }
+ }
+ return isInjected(project, element);
+ }
+
+ @Nullable
+ public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element,
+ @NotNull String message,
+ @NotNull final HighlightInfoType highlightInfoType) {
+ HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create();
+ if (info == null) {
+ return null; //filtered out
+ }
+
+ UnusedDeclarationFixProvider[] fixProviders = Extensions.getExtensions(UnusedDeclarationFixProvider.EP_NAME);
+ for (UnusedDeclarationFixProvider provider : fixProviders) {
+ IntentionAction[] fixes = provider.getQuickFixes(element);
+ for (IntentionAction fix : fixes) {
+ QuickFixAction.registerQuickFixAction(info, fix);
+ }
+ }
+ return info;
+ }
+
+ @Nullable
+ private HighlightInfo processField(@NotNull final Project project,
+ @NotNull final PsiField field,
+ @NotNull PsiIdentifier identifier,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (HighlightUtil.isSerializationImplicitlyUsedField(field)) {
+ return null;
+ }
+ if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
+ if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(myProject, field, progress)) {
+ String message = JavaErrorMessages.message("private.field.is.not.used", identifier.getText());
+
+ HighlightInfo highlightInfo = suggestionsToMakeFieldUsed(field, identifier, message);
+ if (!field.hasInitializer()) {
+ QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(field));
+ }
+ return highlightInfo;
+ }
+
+ final boolean readReferenced = myRefCountHolder.isReferencedForRead(field);
+ if (!readReferenced && !isImplicitRead(project, field, progress)) {
+ String message = JavaErrorMessages.message("private.field.is.not.used.for.reading", identifier.getText());
+ return suggestionsToMakeFieldUsed(field, identifier, message);
+ }
+
+ if (field.hasInitializer()) {
+ return null;
+ }
+ final boolean writeReferenced = myRefCountHolder.isReferencedForWrite(field);
+ if (!writeReferenced && !isImplicitWrite(project, field, progress)) {
+ String message = JavaErrorMessages.message("private.field.is.not.assigned", identifier.getText());
+ final HighlightInfo info = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
+
+ QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
+ QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), QuickFixFactory.getInstance().createCreateConstructorParameterFromFieldFix(
+ field));
+ SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
+ @Override
+ public boolean process(final String annoName) {
+ QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance()
+ .createAddToDependencyInjectionAnnotationsFix(project, annoName, "fields"));
+ return true;
+ }
+ });
+ return info;
+ }
+ }
+ else if (isImplicitUsage(myProject, field, progress)) {
+ return null;
+ }
+ else if (isFieldUnused(myProject, myFile, field, progress, helper)) {
+ return formatUnusedSymbolHighlightInfo(project, "field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier);
+ }
+ return null;
+ }
+
+ public static boolean isFieldUnused(@NotNull Project project,
+ @NotNull PsiFile containingFile,
+ @NotNull PsiField field,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(project, containingFile, field, progress, helper)) {
+ return false;
+ }
+ return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(project, containingFile, field, progress, helper);
+ }
+
+ private HighlightInfo suggestionsToMakeFieldUsed(@NotNull PsiField field, @NotNull PsiIdentifier identifier, @NotNull String message) {
+ HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRemoveUnusedVariableFix(field), myUnusedSymbolKey);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createCreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
+ return highlightInfo;
+ }
+
+ private static boolean isOverriddenOrOverrides(PsiMethod method) {
+ boolean overrides = SuperMethodsSearch.search(method, null, true, false).findFirst() != null;
+ return overrides || OverridingMethodsSearch.search(method).findFirst() != null;
+ }
+
+ @Nullable
+ private HighlightInfo processParameter(@NotNull Project project,
+ @NotNull PsiParameter parameter,
+ @NotNull PsiIdentifier identifier,
+ @NotNull ProgressIndicator progress) {
+ PsiElement declarationScope = parameter.getDeclarationScope();
+ if (declarationScope instanceof PsiMethod) {
+ PsiMethod method = (PsiMethod)declarationScope;
+ if (PsiUtilCore.hasErrorElementChild(method)) return null;
+ if ((method.isConstructor() ||
+ method.hasModifierProperty(PsiModifier.PRIVATE) ||
+ method.hasModifierProperty(PsiModifier.STATIC) ||
+ !method.hasModifierProperty(PsiModifier.ABSTRACT) &&
+ myUnusedSymbolInspection.REPORT_PARAMETER_FOR_PUBLIC_METHODS &&
+ !isOverriddenOrOverrides(method)) &&
+ !method.hasModifierProperty(PsiModifier.NATIVE) &&
+ !JavaHighlightUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
+ !PsiClassImplUtil.isMainOrPremainMethod(method)) {
+ if (isInjected(project, method)) return null;
+ HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
+ if (highlightInfo != null) {
+ QuickFixFactory.getInstance().registerFixesForUnusedParameter(parameter, highlightInfo);
+ return highlightInfo;
+ }
+ }
+ }
+ else if (declarationScope instanceof PsiForeachStatement && !PsiUtil.isIgnoredName(parameter.getName())) {
+ HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
+ if (highlightInfo != null) {
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createRenameToIgnoredFix(parameter), myUnusedSymbolKey);
+ return highlightInfo;
+ }
+ }
+
+ return null;
+ }
+
+ @Nullable
+ private HighlightInfo checkUnusedParameter(@NotNull PsiParameter parameter,
+ @NotNull PsiIdentifier identifier,
+ @NotNull ProgressIndicator progress) {
+ if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(myProject, parameter, progress)) {
+ String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
+ return createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
+ }
+ return null;
+ }
+
+ @Nullable
+ private HighlightInfo processMethod(@NotNull final Project project,
+ @NotNull final PsiMethod method,
+ @NotNull PsiIdentifier identifier,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (isMethodReferenced(myProject, myFile, method, progress, helper)) return null;
+ HighlightInfoType highlightInfoType;
+ HighlightDisplayKey highlightDisplayKey;
+ String key;
+ if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
+ highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
+ highlightDisplayKey = myUnusedSymbolKey;
+ key = method.isConstructor() ? "private.constructor.is.not.used" : "private.method.is.not.used";
+ }
+ else {
+ highlightInfoType = myDeadCodeInfoType;
+ highlightDisplayKey = myDeadCodeKey;
+ key = method.isConstructor() ? "constructor.is.not.used" : "method.is.not.used";
+ }
+ String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY);
+ String message = JavaErrorMessages.message(key, symbolName);
+ final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(method), highlightDisplayKey);
+ SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(method, new Processor<String>() {
+ @Override
+ public boolean process(final String annoName) {
+ IntentionAction fix = QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, "methods");
+ QuickFixAction.registerQuickFixAction(highlightInfo, fix);
+ return true;
+ }
+ });
+ return highlightInfo;
+ }
+
+ public static boolean isMethodReferenced(@NotNull Project project,
+ @NotNull PsiFile containingFile,
+ @NotNull PsiMethod method,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (helper.isLocallyUsed(method)) return true;
+
+ boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
+ PsiClass containingClass = method.getContainingClass();
+ if (JavaHighlightUtil.isSerializationRelatedMethod(method, containingClass)) return true;
+ if (aPrivate) {
+ if (isIntentionalPrivateConstructor(method, containingClass)) {
+ return true;
+ }
+ if (isImplicitUsage(project, method, progress)) {
+ return true;
+ }
+ if (!helper.isCurrentFileAlreadyChecked()) {
+ return !weAreSureThereAreNoUsages(project, containingFile, method, progress, helper);
+ }
+ }
+ else {
+ //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too
+ if (containingClass != null && method.isConstructor()
+ && containingClass.getConstructors().length == 1
+ && isClassUsed(project, containingFile, containingClass, progress, helper)) {
+ return true;
+ }
+ if (isImplicitUsage(project, method, progress)) return true;
+
+ if (method.findSuperMethods().length != 0) {
+ return true;
+ }
+ if (!weAreSureThereAreNoUsages(project, containingFile, method, progress, helper)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean weAreSureThereAreNoUsages(@NotNull Project project,
+ @NotNull PsiFile containingFile,
+ @NotNull PsiMember member,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (!helper.shouldCheckUsages(member)) return false;
+
+ String name = member.getName();
+ if (name == null) return false;
+ SearchScope useScope = member.getUseScope();
+ PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
+ PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? containingFile : null;
+ if (useScope instanceof GlobalSearchScope) {
+ // some classes may have references from within XML outside dependent modules, e.g. our actions
+ if (member instanceof PsiClass) {
+ useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope);
+ }
+
+ PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
+ if (cheapEnough == PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) return false;
+
+ //search usages if it cheap
+ //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
+ if (cheapEnough == PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES && !canBeReferencedViaWeirdNames(member, containingFile)) {
+ return true;
+ }
+
+ if (member instanceof PsiMethod) {
+ String propertyName = PropertyUtil.getPropertyName(member);
+ if (propertyName != null) {
+ SearchScope fileScope = containingFile.getUseScope();
+ if (fileScope instanceof GlobalSearchScope &&
+ searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) ==
+ PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES) {
+ return false;
+ }
+ }
+ }
+ }
+ if (ReferencesSearch.search(member, useScope, true).findFirst() != null) return false;
+ return !(useScope instanceof GlobalSearchScope) || !foundUsageInText(member, (GlobalSearchScope)useScope, searchHelper, ignoreFile);
+ }
+
+ private static boolean foundUsageInText(@NotNull PsiMember member,
+ @NotNull GlobalSearchScope scope,
+ @NotNull PsiSearchHelper searchHelper,
+ final PsiFile ignoreFile) {
+ return !searchHelper.processUsagesInNonJavaFiles(member, member.getName(), new PsiNonJavaFileReferenceProcessor() {
+ @Override
+ public boolean process(final PsiFile psiFile, final int startOffset, final int endOffset) {
+ if (psiFile == ignoreFile) return true; // ignore usages in containingFile because isLocallyUsed() method would have caught that
+ PsiElement element = psiFile.findElementAt(startOffset);
+ return element instanceof PsiComment; // ignore comments
+ }
+ }, scope);
+ }
+
+ private static boolean isEnumValuesMethodUsed(@NotNull Project project,
+ @NotNull PsiFile containingFile,
+ @NotNull PsiMember member,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ final PsiClass containingClass = member.getContainingClass();
+ if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
+ final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
+ return valuesMethod == null || isMethodReferenced(project, containingFile, valuesMethod, progress, helper);
+ }
+
+ private static boolean canBeReferencedViaWeirdNames(@NotNull PsiMember member, @NotNull PsiFile containingFile) {
+ if (member instanceof PsiClass) return false;
+ if (!(containingFile instanceof PsiJavaFile)) return true; // Groovy field can be referenced from Java by getter
+ if (member instanceof PsiField) return false; //Java field cannot be referenced by anything but its name
+ if (member instanceof PsiMethod) {
+ return PropertyUtil.isSimplePropertyAccessor((PsiMethod)member); //Java accessors can be referenced by field name from Groovy
+ }
+ return false;
+ }
+
+ @Nullable
+ private HighlightInfo processClass(@NotNull Project project,
+ @NotNull PsiClass aClass,
+ @NotNull PsiIdentifier identifier,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (isClassUsed(project, myFile, aClass, progress, helper)) return null;
+
+ String pattern;
+ HighlightDisplayKey highlightDisplayKey;
+ HighlightInfoType highlightInfoType;
+ if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE)) {
+ pattern = aClass.isInterface()
+ ? "private.inner.interface.is.not.used"
+ : "private.inner.class.is.not.used";
+ highlightDisplayKey = myUnusedSymbolKey;
+ highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
+ }
+ else if (aClass.getParent() instanceof PsiDeclarationStatement) { // local class
+ pattern = "local.class.is.not.used";
+ highlightDisplayKey = myUnusedSymbolKey;
+ highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
+ }
+ else if (aClass instanceof PsiTypeParameter) {
+ pattern = "type.parameter.is.not.used";
+ highlightDisplayKey = myUnusedSymbolKey;
+ highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
+ }
+ else {
+ pattern = "class.is.not.used";
+ highlightDisplayKey = myDeadCodeKey;
+ highlightInfoType = myDeadCodeInfoType;
+ }
+ return formatUnusedSymbolHighlightInfo(myProject, pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier);
+ }
+
+ public static boolean isClassUsed(@NotNull Project project,
+ @NotNull PsiFile containingFile,
+ @NotNull PsiClass aClass,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ Boolean result = helper.unusedClassCache.get(aClass);
+ if (result == null) {
+ result = isReallyUsed(project, containingFile, aClass, progress, helper);
+ helper.unusedClassCache.put(aClass, result);
+ }
+ return result;
+ }
+
+ private static boolean isReallyUsed(@NotNull Project project,
+ @NotNull PsiFile containingFile,
+ @NotNull PsiClass aClass,
+ @NotNull ProgressIndicator progress,
+ @NotNull GlobalUsageHelper helper) {
+ if (isImplicitUsage(project, aClass, progress) || helper.isLocallyUsed(aClass)) return true;
+ if (helper.isCurrentFileAlreadyChecked()) {
+ if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) ||
+ aClass.getParent() instanceof PsiDeclarationStatement ||
+ aClass instanceof PsiTypeParameter) return false;
+ }
+ return !weAreSureThereAreNoUsages(project, containingFile, aClass, progress, helper);
+ }
+
+ private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull final Project project,
+ @NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
+ @NotNull final PsiNameIdentifierOwner aClass,
+ @NotNull final String element,
+ HighlightDisplayKey highlightDisplayKey,
+ @NotNull HighlightInfoType highlightInfoType,
+ @NotNull PsiElement identifier) {
+ String symbolName = aClass.getName();
+ String message = JavaErrorMessages.message(pattern, symbolName);
+ final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
+ QuickFixAction.registerQuickFixAction(highlightInfo, QuickFixFactory.getInstance().createSafeDeleteFix(aClass), highlightDisplayKey);
+ SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes((PsiModifierListOwner)aClass, new Processor<String>() {
+ @Override
+ public boolean process(final String annoName) {
+ QuickFixAction
+ .registerQuickFixAction(highlightInfo,
+ QuickFixFactory.getInstance().createAddToDependencyInjectionAnnotationsFix(project, annoName, element));
+ return true;
+ }
+ });
+ return highlightInfo;
+ }
+
+ @Nullable
+ private HighlightInfo processImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
+ // jsp include directive hack
+ if (importStatement.isForeignFileImport()) return null;
+
+ if (PsiUtilCore.hasErrorElementChild(importStatement)) return null;
+
+ boolean isRedundant = myRefCountHolder.isRedundant(importStatement);
+ if (!isRedundant && !(importStatement instanceof PsiImportStaticStatement)) {
+ //check import from same package
+ String packageName = ((PsiClassOwner)importStatement.getContainingFile()).getPackageName();
+ PsiJavaCodeReferenceElement reference = importStatement.getImportReference();
+ PsiElement resolved = reference == null ? null : reference.resolve();
+ if (resolved instanceof PsiPackage) {
+ isRedundant = packageName.equals(((PsiQualifiedNamedElement)resolved).getQualifiedName());
+ }
+ else if (resolved instanceof PsiClass && !importStatement.isOnDemand()) {
+ String qName = ((PsiClass)resolved).getQualifiedName();
+ if (qName != null) {
+ String name = ((PomNamedTarget)resolved).getName();
+ isRedundant = qName.equals(packageName + '.' + name);
+ }
+ }
+ }
+
+ if (isRedundant) {
+ return registerRedundantImport(importStatement, unusedImportKey);
+ }
+
+ int entryIndex = JavaCodeStyleManager.getInstance(myProject).findEntryIndex(importStatement);
+ if (entryIndex < myCurrentEntryIndex) {
+ myHasMissortedImports = true;
+ }
+ myCurrentEntryIndex = entryIndex;
+
+ return null;
+ }
+
+ private HighlightInfo registerRedundantImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
+ String description = InspectionsBundle.message("unused.import.statement");
+ HighlightInfo info =
+ HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description)
+ .create();
+
+ QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createOptimizeImportsFix(), unusedImportKey);
+ QuickFixAction.registerQuickFixAction(info, QuickFixFactory.getInstance().createEnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
+ myHasRedundantImports = true;
+ return info;
+ }
+
+
+ private static boolean isIntentionalPrivateConstructor(@NotNull PsiMethod method, PsiClass containingClass) {
+ return method.isConstructor() &&
+ method.getParameterList().getParametersCount() == 0 &&
+ containingClass != null &&
+ containingClass.getConstructors().length == 1;
+ }
+}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
index 175c133..66de82f 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/RefCountHolder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -77,7 +77,7 @@
private static RefCountHolder getInstance(@NotNull PsiFile file, @NotNull ProgressIndicator indicator, boolean acquire) {
HolderReference ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
- RefCountHolder holder = ref == null ? null : ref.get();
+ RefCountHolder holder = com.intellij.reference.SoftReference.dereference(ref);
if (holder == null && acquire) {
holder = new RefCountHolder(file);
HolderReference newRef = new HolderReference(holder);
@@ -88,7 +88,7 @@
break;
}
ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
- RefCountHolder newHolder = ref == null ? null : ref.get();
+ RefCountHolder newHolder = com.intellij.reference.SoftReference.dereference(ref);
if (newHolder != null) {
holder = newHolder;
break;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
index 8ee44f4..c445cec 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/AnnotationsHighlightUtil.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.
@@ -160,8 +160,7 @@
return null;
}
- @Nullable
- public static HighlightInfo checkDuplicateAnnotations(PsiAnnotation annotationToCheck) {
+ static HighlightInfo checkDuplicateAnnotations(@NotNull PsiAnnotation annotationToCheck) {
PsiAnnotationOwner owner = annotationToCheck.getOwner();
if (owner == null) return null;
@@ -170,20 +169,26 @@
PsiElement resolved = element.resolve();
if (!(resolved instanceof PsiClass)) return null;
- for (PsiAnnotation annotation : owner.getAnnotations()) {
- if (annotation == annotationToCheck) continue;
- PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
- if (nameRef == null) continue;
- PsiElement aClass = nameRef.resolve();
- if (!resolved.equals(aClass)) continue;
+ PsiClass annotationType = (PsiClass)resolved;
+ PsiClass contained = contained(annotationType);
+ String containedElementFQN = contained == null ? null : contained.getQualifiedName();
+
+ if (containedElementFQN != null) {
+ PsiClass container = annotationType;
+ String containerName = container.getQualifiedName();
+ if (isAnnotationRepeatedTwice(owner, containedElementFQN)) {
+ String description = JavaErrorMessages.message("annotation.container.wrong.place", containerName);
+ return annotationError(annotationToCheck, description);
+ }
+ }
+ else if (isAnnotationRepeatedTwice(owner, annotationType.getQualifiedName())) {
if (!PsiUtil.isLanguageLevel8OrHigher(annotationToCheck)) {
String description = JavaErrorMessages.message("annotation.duplicate.annotation");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(description).create();
}
-
- PsiClass annotationType = (PsiClass)resolved;
PsiAnnotation metaAnno = PsiImplUtil.findAnnotation(annotationType.getModifierList(), CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE);
+
if (metaAnno == null) {
String explanation = JavaErrorMessages.message("annotation.non.repeatable", annotationType.getQualifiedName());
String description = JavaErrorMessages.message("annotation.duplicate.explained", explanation);
@@ -198,28 +203,58 @@
PsiClass container = getRepeatableContainer(metaAnno);
if (container != null) {
- String containerName = container.getQualifiedName();
- if (containerName != null) {
- PsiAnnotation containerAnno = owner.findAnnotation(containerName);
- if (containerAnno != null) {
- String description = JavaErrorMessages.message("annotation.container.wrong.place", containerName);
- return annotationError(containerAnno, description);
- }
- }
-
PsiAnnotation.TargetType[] targets = PsiImplUtil.getTargetsForLocation(owner);
PsiAnnotation.TargetType applicable = PsiImplUtil.findApplicableTarget(container, targets);
if (applicable == null) {
String target = JavaErrorMessages.message("annotation.target." + targets[0]);
- String message = JavaErrorMessages.message("annotation.container.not.applicable", containerName, target);
- return annotationError(annotation, message);
+ String message = JavaErrorMessages.message("annotation.container.not.applicable", container.getName(), target);
+ return annotationError(annotationToCheck, message);
}
}
}
+ for (PsiAnnotation annotation : owner.getAnnotations()) {
+ if (annotation == annotationToCheck) continue;
+ PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
+ if (nameRef == null) continue;
+ PsiElement aClass = nameRef.resolve();
+ if (!resolved.equals(aClass)) continue;
+
+ }
+
return null;
}
+ // returns contained element
+ private static PsiClass contained(PsiClass annotationType) {
+ if (!annotationType.isAnnotationType()) return null;
+ PsiMethod[] values = annotationType.findMethodsByName("value", false);
+ if (values.length != 1) return null;
+ PsiMethod value = values[0];
+ PsiType returnType = value.getReturnType();
+ if (!(returnType instanceof PsiArrayType)) return null;
+ PsiType type = ((PsiArrayType)returnType).getComponentType();
+ if (!(type instanceof PsiClassType)) return null;
+ PsiClass contained = ((PsiClassType)type).resolve();
+ if (contained == null || !contained.isAnnotationType()) return null;
+ if (PsiImplUtil.findAnnotation(contained.getModifierList(), CommonClassNames.JAVA_LANG_ANNOTATION_REPEATABLE) == null) return null;
+
+ return contained;
+ }
+
+ private static boolean isAnnotationRepeatedTwice(@NotNull PsiAnnotationOwner owner, @NotNull String qualifiedName) {
+ int count = 0;
+ for (PsiAnnotation annotation : owner.getAnnotations()) {
+ PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
+ if (nameRef == null) continue;
+ PsiElement resolved = nameRef.resolve();
+ if (!(resolved instanceof PsiClass) || !qualifiedName.equals(((PsiClass)resolved).getQualifiedName())) continue;
+ count++;
+ if (count == 2) return true;
+ }
+ return false;
+ }
+
@Nullable
public static HighlightInfo checkMissingAttributes(PsiAnnotation annotation) {
PsiJavaCodeReferenceElement nameRef = annotation.getNameReferenceElement();
@@ -579,7 +614,7 @@
public static HighlightInfo checkFunctionalInterface(@NotNull PsiAnnotation annotation, @NotNull LanguageLevel languageLevel) {
final String errorMessage = LambdaUtil.checkFunctionalInterface(annotation, languageLevel);
if (errorMessage != null) {
- return HighlightInfo.newHighlightInfo(HighlightInfoType.WARNING).range(annotation).descriptionAndTooltip(errorMessage).create();
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(annotation).descriptionAndTooltip(errorMessage).create();
}
return null;
}
@@ -601,7 +636,7 @@
}
@Nullable
- private static String doCheckRepeatableAnnotation(PsiAnnotation annotation) {
+ private static String doCheckRepeatableAnnotation(@NotNull PsiAnnotation annotation) {
PsiAnnotationOwner owner = annotation.getOwner();
if (!(owner instanceof PsiModifierList)) return null;
PsiElement target = ((PsiModifierList)owner).getParent();
@@ -642,7 +677,7 @@
}
@Nullable
- private static PsiClass getRepeatableContainer(PsiAnnotation annotation) {
+ private static PsiClass getRepeatableContainer(@NotNull PsiAnnotation annotation) {
PsiAnnotationMemberValue containerRef = PsiImplUtil.findAttributeValue(annotation, null);
if (!(containerRef instanceof PsiClassObjectAccessExpression)) return null;
PsiType containerType = ((PsiClassObjectAccessExpression)containerRef).getOperand().getType();
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 98f3963..324a222 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
@@ -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.
@@ -62,8 +62,14 @@
public static HighlightInfo checkInferredTypeArguments(PsiTypeParameterListOwner listOwner,
PsiElement call,
PsiSubstitutor substitutor) {
- final Pair<PsiTypeParameter, PsiType> inferredTypeArgument =
- GenericsUtil.findTypeParameterWithBoundError(listOwner.getTypeParameters(), substitutor, call, false);
+ return checkInferredTypeArguments(listOwner.getTypeParameters(), call, substitutor);
+ }
+
+ @Nullable
+ public static HighlightInfo checkInferredTypeArguments(PsiTypeParameter[] typeParameters,
+ PsiElement call,
+ PsiSubstitutor substitutor) {
+ final Pair<PsiTypeParameter, PsiType> inferredTypeArgument = GenericsUtil.findTypeParameterWithBoundError(typeParameters, substitutor, call, false);
if (inferredTypeArgument != null) {
final PsiType extendsType = inferredTypeArgument.second;
final PsiTypeParameter typeParameter = inferredTypeArgument.first;
@@ -234,7 +240,7 @@
final PsiClass referenceClass = type instanceof PsiClassType ? ((PsiClassType)type).resolve() : null;
final PsiType psiType = substitutor.substitute(classParameter);
if (psiType instanceof PsiClassType && !(PsiUtil.resolveClassInType(psiType) instanceof PsiTypeParameter)) {
- if (checkNotInBounds(type, psiType, referenceParameterList)) {
+ if (GenericsUtil.checkNotInBounds(type, psiType, referenceParameterList)) {
final String description = "Actual type argument and inferred type contradict each other";
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(typeElement2Highlight).descriptionAndTooltip(description).create();
}
@@ -243,7 +249,7 @@
final PsiClassType[] bounds = classParameter.getSuperTypes();
for (PsiClassType type1 : bounds) {
PsiType bound = substitutor.substitute(type1);
- if (!bound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && checkNotInBounds(type, bound, referenceParameterList)) {
+ if (!bound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && GenericsUtil.checkNotInBounds(type, bound, referenceParameterList)) {
PsiClass boundClass = bound instanceof PsiClassType ? ((PsiClassType)bound).resolve() : null;
@NonNls final String messageKey = boundClass == null || referenceClass == null || referenceClass.isInterface() == boundClass.isInterface()
@@ -267,79 +273,6 @@
return null;
}
- private static boolean checkNotInBounds(PsiType type, PsiType bound, PsiReferenceParameterList referenceParameterList) {
- if (type instanceof PsiClassType) {
- return checkNotAssignable(bound, type, allowUncheckedConversions((PsiClassType)type, referenceParameterList));
- }
- if (type instanceof PsiWildcardType) {
- if (((PsiWildcardType)type).isExtends()) {
- return checkExtendsWildcardCaptureFailure((PsiWildcardType)type, bound);
- }
- else if (((PsiWildcardType)type).isSuper()) {
- final PsiType superBound = ((PsiWildcardType)type).getSuperBound();
- if (PsiUtil.resolveClassInType(superBound) instanceof PsiTypeParameter) return TypesDistinctProver.provablyDistinct(type, bound);
- return checkNotAssignable(bound, superBound, false);
- }
- }
- else if (type instanceof PsiArrayType) {
- return checkNotAssignable(bound, type, true);
- }
- return false;
- }
-
- //JLS 5.1.10
- private static boolean checkExtendsWildcardCaptureFailure(PsiWildcardType type, PsiType bound) {
- LOG.assertTrue(type.isExtends());
- final PsiType extendsBound = type.getExtendsBound();
- PsiType boundBound = bound;
- if (bound instanceof PsiWildcardType) {
- if (((PsiWildcardType)bound).isBounded()) {
- boundBound = ((PsiWildcardType)bound).isSuper()
- ? ((PsiWildcardType)bound).getSuperBound()
- : ((PsiWildcardType)bound).getExtendsBound();
- }
- else {
- return false;
- }
- }
- return !TypeConversionUtil.areTypesConvertible(boundBound, extendsBound) &&
- !TypeConversionUtil.areTypesConvertible(extendsBound, boundBound);
- }
-
- private static boolean checkNotAssignable(final PsiType bound,
- final PsiType type,
- final boolean allowUncheckedConversion) {
- if (bound instanceof PsiWildcardType) {
- if (((PsiWildcardType)bound).isBounded()) {
- final PsiType boundBound = ((PsiWildcardType)bound).isExtends()
- ? ((PsiWildcardType)bound).getExtendsBound()
- : ((PsiWildcardType)bound).getSuperBound();
- return !TypeConversionUtil.isAssignable(boundBound, type, allowUncheckedConversion);
- }
- else {
- return true;
- }
- }
- else {
- return !TypeConversionUtil.isAssignable(bound, type, allowUncheckedConversion);
- }
- }
-
- private static boolean allowUncheckedConversions(PsiClassType type, PsiReferenceParameterList referenceParameterList) {
- final PsiClass psiClass = type.resolve();
- if (psiClass != null) {
- for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(psiClass)) {
- if (parameter.getExtendsListTypes().length != 0) {
- return false;
- }
- }
- if (psiClass instanceof PsiTypeParameter && psiClass.getExtendsListTypes().length != 0) return false;
- }
- if (!type.isRaw()) return true;
- //allow unchecked conversions in method calls but not in type declaration
- return referenceParameterList.getParent() instanceof PsiReferenceExpression;
- }
-
private static String typeParameterListOwnerDescription(final PsiTypeParameterListOwner typeParameterListOwner) {
if (typeParameterListOwner instanceof PsiClass) {
return HighlightUtil.formatClass((PsiClass)typeParameterListOwner);
@@ -393,7 +326,7 @@
if (errorResult == null && languageLevel.isAtLeast(LanguageLevel.JDK_1_7) &&
referenceElements.length > 1) {
//todo suppress erased methods which come from the same class
- return checkOverrideEquivalentMethods(aClass);
+ return checkOverrideEquivalentMethods(languageLevel, aClass);
}
return errorResult;
}
@@ -447,7 +380,8 @@
return null;
}
- public static HighlightInfo checkOverrideEquivalentMethods(@NotNull PsiClass aClass) {
+ public static HighlightInfo checkOverrideEquivalentMethods(@NotNull LanguageLevel languageLevel,
+ @NotNull PsiClass aClass) {
final Collection<HierarchicalMethodSignature> signaturesWithSupers = aClass.getVisibleSignatures();
PsiManager manager = aClass.getManager();
Map<MethodSignature, MethodSignatureBackedByPsiMethod> sameErasureMethods =
@@ -462,43 +396,31 @@
}
}
- final PsiIdentifier classIdentifier = aClass.getNameIdentifier();
- if (PsiUtil.isLanguageLevel8OrHigher(aClass) && classIdentifier != null) {
- HighlightInfo info = checkUnrelatedDefaultMethods(aClass, signaturesWithSupers, classIdentifier);
- if (info != null) return info;
- info = checkDefaultMethodOverrideEquivalentToObjectNonPrivate(aClass, signaturesWithSupers);
- if (info != null) return info;
- }
-
return null;
}
- private static HighlightInfo checkDefaultMethodOverrideEquivalentToObjectNonPrivate(PsiClass aClass,
- Collection<HierarchicalMethodSignature> withSupers) {
- if (aClass.isInterface()) {
- for (HierarchicalMethodSignature sig : withSupers) {
- final PsiMethod method = sig.getMethod();
- if (method.hasModifierProperty(PsiModifier.DEFAULT)) {
- for (HierarchicalMethodSignature methodSignature : sig.getSuperSignatures()) {
- final PsiClass containingClass = methodSignature.getMethod().getContainingClass();
- if (containingClass != null && CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())) {
- final PsiIdentifier identifier = method.getNameIdentifier();
- LOG.assertTrue(identifier != null);
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
- .descriptionAndTooltip("Default method " + sig.getName() + " overrides a member of java.lang.Object")
- .range(identifier)
- .create();
- }
- }
+ static HighlightInfo checkDefaultMethodOverrideEquivalentToObjectNonPrivate(@NotNull LanguageLevel languageLevel,
+ @NotNull PsiClass aClass,
+ @NotNull PsiMethod method,
+ @NotNull PsiElement methodIdentifier) {
+ 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())) {
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
+ .descriptionAndTooltip("Default method '" + sig.getName() + "' overrides a member of 'java.lang.Object'")
+ .range(methodIdentifier)
+ .create();
}
}
}
return null;
}
- private static HighlightInfo checkUnrelatedDefaultMethods(PsiClass aClass,
- Collection<HierarchicalMethodSignature> signaturesWithSupers,
- PsiIdentifier classIdentifier) {
+ static HighlightInfo checkUnrelatedDefaultMethods(@NotNull PsiClass aClass,
+ @NotNull Collection<HierarchicalMethodSignature> signaturesWithSupers,
+ @NotNull PsiIdentifier classIdentifier) {
for (HierarchicalMethodSignature methodSignature : signaturesWithSupers) {
final PsiMethod method = methodSignature.getMethod();
if (method.hasModifierProperty(PsiModifier.DEFAULT)) {
@@ -792,14 +714,10 @@
}
@Nullable
- public static HighlightInfo checkEnumInstantiation(PsiNewExpression expression) {
- final PsiType type = expression.getType();
- if (type instanceof PsiClassType) {
- final PsiClass aClass = ((PsiClassType)type).resolve();
- if (aClass != null && aClass.isEnum()) {
- String description = JavaErrorMessages.message("enum.types.cannot.be.instantiated");
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create();
- }
+ public static HighlightInfo checkEnumInstantiation(PsiNewExpression expression, PsiClass aClass) {
+ if (aClass != null && aClass.isEnum() && expression.getArrayDimensions().length == 0 && expression.getArrayInitializer() == null) {
+ String description = JavaErrorMessages.message("enum.types.cannot.be.instantiated");
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expression).descriptionAndTooltip(description).create();
}
return null;
}
@@ -1046,8 +964,8 @@
}
}
- static void checkEnumConstantForConstructorProblems(PsiEnumConstant enumConstant,
- final HighlightInfoHolder holder,
+ static void checkEnumConstantForConstructorProblems(@NotNull PsiEnumConstant enumConstant,
+ @NotNull HighlightInfoHolder holder,
@NotNull JavaSdkVersion javaSdkVersion) {
PsiClass containingClass = enumConstant.getContainingClass();
if (enumConstant.getInitializingClass() == null) {
@@ -1275,23 +1193,17 @@
/**
* http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.8
*/
- @Nullable
- public static HighlightInfo checkRawOnParameterizedType(PsiReferenceParameterList list) {
- if (list.getTypeArguments().length > 0) return null;
- final PsiElement parent = list.getParent();
- if (parent instanceof PsiJavaCodeReferenceElement) {
- final PsiElement qualifier = ((PsiJavaCodeReferenceElement)parent).getQualifier();
- if (qualifier instanceof PsiJavaCodeReferenceElement) {
- if (((PsiJavaCodeReferenceElement)qualifier).getTypeParameters().length > 0) {
- final PsiElement resolve = ((PsiJavaCodeReferenceElement)parent).resolve();
- if (resolve instanceof PsiTypeParameterListOwner
- && ((PsiTypeParameterListOwner)resolve).hasTypeParameters()
- && !((PsiTypeParameterListOwner)resolve).hasModifierProperty(PsiModifier.STATIC)) {
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip(
- "Improper formed type; some type parameters are missing").create();
- }
- }
- }
+ static HighlightInfo checkRawOnParameterizedType(@NotNull PsiJavaCodeReferenceElement parent, PsiElement resolved) {
+ PsiReferenceParameterList list = parent.getParameterList();
+ if (list == null || list.getTypeArguments().length > 0) return null;
+ final PsiElement qualifier = parent.getQualifier();
+ if (qualifier instanceof PsiJavaCodeReferenceElement &&
+ ((PsiJavaCodeReferenceElement)qualifier).getTypeParameters().length > 0 &&
+ resolved instanceof PsiTypeParameterListOwner &&
+ ((PsiTypeParameterListOwner)resolved).hasTypeParameters() &&
+ !((PsiTypeParameterListOwner)resolved).hasModifierProperty(PsiModifier.STATIC)) {
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip(
+ "Improper formed type; some type parameters are missing").create();
}
return null;
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index 064888b..163ca42 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.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.
@@ -57,16 +57,10 @@
* new ref(...) or new ref(..) { ... } where ref is abstract class
*/
@Nullable
- static HighlightInfo checkAbstractInstantiation(PsiJavaCodeReferenceElement ref, PsiElement resolved) {
+ static HighlightInfo checkAbstractInstantiation(@NotNull PsiJavaCodeReferenceElement ref, PsiElement resolved) {
PsiElement parent = ref.getParent();
HighlightInfo highlightInfo = null;
- if (parent instanceof PsiNewExpression && !PsiUtilCore.hasErrorElementChild(parent)) {
- if (((PsiNewExpression)parent).getType() instanceof PsiArrayType) return null;
- if (resolved instanceof PsiClass) {
- highlightInfo = checkInstantiationOfAbstractClass((PsiClass)resolved, ref);
- }
- }
- else if (parent instanceof PsiAnonymousClass
+ if (parent instanceof PsiAnonymousClass
&& parent.getParent() instanceof PsiNewExpression
&& !PsiUtilCore.hasErrorElementChild(parent.getParent())) {
PsiAnonymousClass aClass = (PsiAnonymousClass)parent;
@@ -127,26 +121,21 @@
}
@Nullable
- public static HighlightInfo checkInstantiationOfAbstractClass(PsiClass aClass, PsiElement highlightElement) {
+ public static HighlightInfo checkInstantiationOfAbstractClass(PsiClass aClass, @NotNull PsiElement highlightElement) {
HighlightInfo errorResult = null;
- if (aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ if (aClass != null && aClass.hasModifierProperty(PsiModifier.ABSTRACT)
+ && (!(highlightElement instanceof PsiNewExpression) || !(((PsiNewExpression)highlightElement).getType() instanceof PsiArrayType))) {
String baseClassName = aClass.getName();
String message = JavaErrorMessages.message("abstract.cannot.be.instantiated", baseClassName);
- PsiElement parent = highlightElement.getParent();
- if (parent instanceof PsiNewExpression) {
- errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip(message).create();
- } else {
- errorResult =
- HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(highlightElement).descriptionAndTooltip(message).create();
- }
+ errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(highlightElement).descriptionAndTooltip(message).create();
final PsiMethod anyAbstractMethod = ClassUtil.getAnyAbstractMethod(aClass);
if (!aClass.isInterface() && anyAbstractMethod == null) {
// suggest to make not abstract only if possible
QuickFixAction.registerQuickFixAction(errorResult,
QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.ABSTRACT, false, false));
}
- if (anyAbstractMethod != null && parent instanceof PsiNewExpression && ((PsiNewExpression)parent).getClassReference() != null) {
- QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementAbstractClassMethodsFix(parent));
+ if (anyAbstractMethod != null && highlightElement instanceof PsiNewExpression && ((PsiNewExpression)highlightElement).getClassReference() != null) {
+ QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createImplementAbstractClassMethodsFix(highlightElement));
}
}
return errorResult;
@@ -239,21 +228,13 @@
}
@Nullable
- static HighlightInfo checkPublicClassInRightFile(PsiKeyword keyword, PsiModifierList psiModifierList) {
- // most test case classes are located in wrong files
+ static HighlightInfo checkPublicClassInRightFile(PsiClass aClass) {
+ // most test case classes are located in wrong files
if (ApplicationManager.getApplication().isUnitTestMode()) return null;
- if (new PsiMatcherImpl(keyword)
- .dot(PsiMatchers.hasText(PsiModifier.PUBLIC))
- .parent(PsiMatchers.hasClass(PsiModifierList.class))
- .parent(PsiMatchers.hasClass(PsiClass.class))
- .parent(PsiMatchers.hasClass(PsiJavaFile.class))
- .getElement() == null) {
- return null;
- }
-
- PsiClass aClass = (PsiClass)keyword.getParent().getParent();
- PsiJavaFile file = (PsiJavaFile)aClass.getContainingFile();
+ PsiFile containingFile = aClass.getContainingFile();
+ if (aClass.getParent() != containingFile || !aClass.hasModifierProperty(PsiModifier.PUBLIC) || !(containingFile instanceof PsiJavaFile)) return null;
+ PsiJavaFile file = (PsiJavaFile)containingFile;
VirtualFile virtualFile = file.getVirtualFile();
HighlightInfo errorResult = null;
if (virtualFile != null && !aClass.getName().equals(virtualFile.getNameWithoutExtension())) {
@@ -262,6 +243,7 @@
errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).
range(aClass, range.getStartOffset(), range.getEndOffset()).
descriptionAndTooltip(message).create();
+ PsiModifierList psiModifierList = aClass.getModifierList();
QuickFixAction.registerQuickFixAction(errorResult,
QUICK_FIX_FACTORY.createModifierListFix(psiModifierList, PsiModifier.PUBLIC, false, false));
PsiClass[] classes = file.getClasses();
@@ -595,7 +577,7 @@
}
@Nullable
- private static PsiClass getCircularClass(PsiClass aClass, Collection<PsiClass> usedClasses) {
+ public static PsiClass getCircularClass(PsiClass aClass, Collection<PsiClass> usedClasses) {
if (usedClasses.contains(aClass)) {
return aClass;
}
@@ -688,10 +670,9 @@
}
@Nullable
- public static HighlightInfo checkQualifiedNew(PsiNewExpression expression) {
+ public static HighlightInfo checkQualifiedNew(PsiNewExpression expression, PsiType type, PsiClass aClass) {
PsiExpression qualifier = expression.getQualifier();
if (qualifier == null) return null;
- PsiType type = expression.getType();
if (type instanceof PsiArrayType) {
String description = JavaErrorMessages.message("invalid.qualified.new");
HighlightInfo info =
@@ -699,7 +680,6 @@
QuickFixAction.registerQuickFixAction(info, QUICK_FIX_FACTORY.createRemoveNewQualifierFix(expression, null));
return info;
}
- PsiClass aClass = PsiUtil.resolveClassInType(type);
HighlightInfo info = null;
if (aClass != null) {
if (aClass.hasModifierProperty(PsiModifier.STATIC)) {
@@ -820,17 +800,15 @@
}
@Nullable
- public static HighlightInfo checkCreateInnerClassFromStaticContext(PsiNewExpression expression) {
- PsiType type = expression.getType();
- PsiExpression qualifier = expression.getQualifier();
+ public static HighlightInfo checkCreateInnerClassFromStaticContext(PsiNewExpression expression, PsiType type, PsiClass aClass) {
if (type == null || type instanceof PsiArrayType || type instanceof PsiPrimitiveType) return null;
- PsiClass aClass = PsiUtil.resolveClassInType(type);
if (aClass == null) return null;
if (aClass instanceof PsiAnonymousClass) {
aClass = ((PsiAnonymousClass)aClass).getBaseClassType().resolve();
if (aClass == null) return null;
}
+ PsiExpression qualifier = expression.getQualifier();
return checkCreateInnerClassFromStaticContext(expression, qualifier, aClass);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
index 357c934..35f9416 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightControlFlowUtil.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.
@@ -638,8 +638,8 @@
@Nullable
- static HighlightInfo checkVariableMustBeFinal(PsiVariable variable,
- PsiJavaCodeReferenceElement context,
+ static HighlightInfo checkVariableMustBeFinal(@NotNull PsiVariable variable,
+ @NotNull PsiJavaCodeReferenceElement context,
@NotNull LanguageLevel languageLevel) {
if (variable.hasModifierProperty(PsiModifier.FINAL)) return null;
final PsiClass innerClass = getInnerClassVariableReferencedFrom(variable, context);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
index 0485394..ac211ff 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.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,6 +30,7 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
@@ -120,8 +121,8 @@
}
- static HighlightInfo checkMethodIncompatibleReturnType(MethodSignatureBackedByPsiMethod methodSignature,
- List<HierarchicalMethodSignature> superMethodSignatures,
+ static HighlightInfo checkMethodIncompatibleReturnType(@NotNull MethodSignatureBackedByPsiMethod methodSignature,
+ @NotNull List<HierarchicalMethodSignature> superMethodSignatures,
boolean includeRealPositionInfo) {
return checkMethodIncompatibleReturnType(methodSignature, superMethodSignatures, includeRealPositionInfo, null);
}
@@ -142,10 +143,11 @@
if (returnType == null || superReturnType == null || method == superMethod) continue;
PsiClass superClass = superMethod.getContainingClass();
if (superClass == null) continue;
+ TextRange toHighlight = textRange != null ? textRange
+ : includeRealPositionInfo ? method.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE;
HighlightInfo highlightInfo = checkSuperMethodSignature(superMethod, superMethodSignature, superReturnType, method, methodSignature,
returnType, JavaErrorMessages.message("incompatible.return.type"),
- textRange != null ? textRange
- : includeRealPositionInfo ? method.getReturnTypeElement().getTextRange() : TextRange.EMPTY_RANGE);
+ toHighlight);
if (highlightInfo != null) return highlightInfo;
}
@@ -153,12 +155,13 @@
}
private static HighlightInfo checkSuperMethodSignature(@NotNull PsiMethod superMethod,
- MethodSignatureBackedByPsiMethod superMethodSignature,
+ @NotNull MethodSignatureBackedByPsiMethod superMethodSignature,
PsiType superReturnType,
- PsiMethod method,
- MethodSignatureBackedByPsiMethod methodSignature,
- PsiType returnType,
- String detailMessage, final TextRange range) {
+ @NotNull PsiMethod method,
+ @NotNull MethodSignatureBackedByPsiMethod methodSignature,
+ @NotNull PsiType returnType,
+ @NotNull String detailMessage,
+ @NotNull TextRange range) {
if (superReturnType == null) return null;
if ("clone".equals(method.getName())) {
final PsiClass containingClass = method.getContainingClass();
@@ -188,16 +191,15 @@
}
}
- return createIncompatibleReturnTypeMessage(method, superMethod,
- substitutedSuperReturnType, returnType, detailMessage,
- range);
+ return createIncompatibleReturnTypeMessage(method, superMethod, substitutedSuperReturnType, returnType, detailMessage, range);
}
- private static HighlightInfo createIncompatibleReturnTypeMessage(PsiMethod method,
+ private static HighlightInfo createIncompatibleReturnTypeMessage(@NotNull PsiMethod method,
@NotNull PsiMethod superMethod,
- PsiType substitutedSuperReturnType,
+ @NotNull PsiType substitutedSuperReturnType,
@NotNull PsiType returnType,
- String detailMessage, final TextRange textRange) {
+ @NotNull String detailMessage,
+ @NotNull TextRange textRange) {
String description = MessageFormat.format("{0}; {1}", createClashMethodMessage(method, superMethod, true), detailMessage);
HighlightInfo errorResult = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(textRange).descriptionAndTooltip(description).create();
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createMethodReturnFix(method, substitutedSuperReturnType, false));
@@ -352,7 +354,6 @@
}
if (!resolveResult.isAccessible() || !resolveResult.isStaticsScopeCorrect()) {
- //highlightInfo = checkAmbiguousMethodCall(referenceToMethod, results, list, element, resolveResult, methodCall, resolveHelper);
highlightInfo = null;
}
else if (candidateInfo != null && !candidateInfo.isApplicable()) {
@@ -421,12 +422,13 @@
}
@Nullable
- static HighlightInfo checkAmbiguousMethodCall(final PsiReferenceExpression referenceToMethod,
- JavaResolveResult[] resolveResults,
- @NotNull PsiExpressionList list,
- final PsiElement element,
- final JavaResolveResult resolveResult,
- final PsiMethodCallExpression methodCall, final PsiResolveHelper resolveHelper) {
+ static HighlightInfo checkAmbiguousMethodCallIdentifier(@NotNull PsiReferenceExpression referenceToMethod,
+ @NotNull JavaResolveResult[] resolveResults,
+ @NotNull PsiExpressionList list,
+ final PsiElement element,
+ @NotNull JavaResolveResult resolveResult,
+ @NotNull PsiMethodCallExpression methodCall,
+ @NotNull PsiResolveHelper resolveHelper) {
MethodCandidateInfo methodCandidate1 = null;
MethodCandidateInfo methodCandidate2 = null;
for (JavaResolveResult result : resolveResults) {
@@ -449,19 +451,7 @@
PsiElement elementToHighlight;
HighlightInfoType highlightInfoType = HighlightInfoType.ERROR;
if (methodCandidate2 != null) {
- String m1 = PsiFormatUtil.formatMethod(methodCandidate1.getElement(),
- methodCandidate1.getSubstitutor(),
- PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME |
- PsiFormatUtilBase.SHOW_PARAMETERS,
- PsiFormatUtilBase.SHOW_TYPE);
- String m2 = PsiFormatUtil.formatMethod(methodCandidate2.getElement(),
- methodCandidate2.getSubstitutor(),
- PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME |
- PsiFormatUtilBase.SHOW_PARAMETERS,
- PsiFormatUtilBase.SHOW_TYPE);
- description = JavaErrorMessages.message("ambiguous.method.call", m1, m2);
- toolTip = createAmbiguousMethodHtmlTooltip(new MethodCandidateInfo[]{methodCandidate1, methodCandidate2});
- elementToHighlight = list;
+ return null;
}
else {
if (element != null && !resolveResult.isAccessible()) {
@@ -480,6 +470,97 @@
highlightInfoType = HighlightInfoType.WRONG_REF;
}
else {
+ return null;
+ }
+ }
+ toolTip = XmlStringUtil.escapeString(description);
+ }
+ HighlightInfo info =
+ HighlightInfo.newHighlightInfo(highlightInfoType).range(elementToHighlight).description(description).escapedToolTip(toolTip).create();
+ if (methodCandidate2 == null) {
+ registerMethodCallIntentions(info, methodCall, list, resolveHelper);
+ }
+ if (!resolveResult.isAccessible() && resolveResult.isStaticsScopeCorrect() && methodCandidate2 != null) {
+ HighlightUtil.registerAccessQuickFixAction((PsiMember)element, referenceToMethod, info, resolveResult.getCurrentFileResolveScope());
+ }
+ if (element != null && !resolveResult.isStaticsScopeCorrect()) {
+ HighlightUtil.registerStaticProblemQuickFixAction(element, info, referenceToMethod);
+ }
+
+ TextRange fixRange = getFixRange(elementToHighlight);
+ CastMethodArgumentFix.REGISTRAR.registerCastActions(candidates, methodCall, info, fixRange);
+ PermuteArgumentsFix.registerFix(info, methodCall, candidates, fixRange);
+ WrapExpressionFix.registerWrapAction(candidates, list.getExpressions(), info);
+ registerChangeParameterClassFix(methodCall, list, info);
+ return info;
+ }
+
+ @Nullable
+ static HighlightInfo checkAmbiguousMethodCallArguments(@NotNull PsiReferenceExpression referenceToMethod,
+ @NotNull JavaResolveResult[] resolveResults,
+ @NotNull PsiExpressionList list,
+ final PsiElement element,
+ @NotNull JavaResolveResult resolveResult,
+ @NotNull PsiMethodCallExpression methodCall,
+ @NotNull PsiResolveHelper resolveHelper) {
+ MethodCandidateInfo methodCandidate1 = null;
+ MethodCandidateInfo methodCandidate2 = null;
+ for (JavaResolveResult result : resolveResults) {
+ if (!(result instanceof MethodCandidateInfo)) continue;
+ MethodCandidateInfo candidate = (MethodCandidateInfo)result;
+ if (candidate.isApplicable() && !candidate.getElement().isConstructor()) {
+ if (methodCandidate1 == null) {
+ methodCandidate1 = candidate;
+ }
+ else {
+ methodCandidate2 = candidate;
+ break;
+ }
+ }
+ }
+ MethodCandidateInfo[] candidates = toMethodCandidates(resolveResults);
+
+ String description;
+ String toolTip;
+ PsiElement elementToHighlight;
+ HighlightInfoType highlightInfoType = HighlightInfoType.ERROR;
+ if (methodCandidate2 != null) {
+ PsiMethod element1 = methodCandidate1.getElement();
+ String m1 = PsiFormatUtil.formatMethod(element1,
+ methodCandidate1.getSubstitutor(),
+ PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME |
+ PsiFormatUtilBase.SHOW_PARAMETERS,
+ PsiFormatUtilBase.SHOW_TYPE);
+ PsiMethod element2 = methodCandidate2.getElement();
+ String m2 = PsiFormatUtil.formatMethod(element2,
+ methodCandidate2.getSubstitutor(),
+ PsiFormatUtilBase.SHOW_CONTAINING_CLASS | PsiFormatUtilBase.SHOW_NAME |
+ PsiFormatUtilBase.SHOW_PARAMETERS,
+ PsiFormatUtilBase.SHOW_TYPE);
+ VirtualFile virtualFile1 = PsiUtilCore.getVirtualFile(element1);
+ VirtualFile virtualFile2 = PsiUtilCore.getVirtualFile(element2);
+ if (!Comparing.equal(virtualFile1, virtualFile2)) {
+ if (virtualFile1 != null) m1 += " (In " + virtualFile1.getPresentableUrl() + ")";
+ if (virtualFile2 != null) m2 += " (In " + virtualFile2.getPresentableUrl() + ")";
+ }
+ description = JavaErrorMessages.message("ambiguous.method.call", m1, m2);
+ toolTip = createAmbiguousMethodHtmlTooltip(new MethodCandidateInfo[]{methodCandidate1, methodCandidate2});
+ elementToHighlight = list;
+ }
+ else {
+ if (element != null && !resolveResult.isAccessible()) {
+ return null;
+ }
+ else if (element != null && !resolveResult.isStaticsScopeCorrect()) {
+ return null;
+ }
+ else {
+ String methodName = referenceToMethod.getReferenceName() + buildArgTypesList(list);
+ description = JavaErrorMessages.message("cannot.resolve.method", methodName);
+ if (candidates.length == 0) {
+ return null;
+ }
+ else {
elementToHighlight = list;
}
}
@@ -505,8 +586,9 @@
return info;
}
- private static MethodCandidateInfo[] toMethodCandidates(JavaResolveResult[] resolveResults) {
- List<MethodCandidateInfo> candidateList = new ArrayList<MethodCandidateInfo>();
+ @NotNull
+ private static MethodCandidateInfo[] toMethodCandidates(@NotNull JavaResolveResult[] resolveResults) {
+ List<MethodCandidateInfo> candidateList = new ArrayList<MethodCandidateInfo>(resolveResults.length);
for (JavaResolveResult result : resolveResults) {
if (!(result instanceof MethodCandidateInfo)) continue;
@@ -902,9 +984,6 @@
additionalFixes.add(QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.STATIC, true, false));
}
}
- else if (isExtension) {
- return HighlightUtil.checkExtensionMethodsFeature(method, languageLevel,containingFile);
- }
}
else if (isExtension) {
description = JavaErrorMessages.message("extension.method.in.class");
@@ -932,8 +1011,7 @@
}
@Nullable
- static HighlightInfo checkConstructorCallMustBeFirstStatement(PsiReferenceExpression expression) {
- PsiElement methodCall = expression.getParent();
+ static HighlightInfo checkConstructorCallMustBeFirstStatement(@NotNull PsiMethodCallExpression methodCall) {
if (!RefactoringChangeUtil.isSuperOrThisMethodCall(methodCall)) return null;
PsiElement codeBlock = methodCall.getParent().getParent();
if (codeBlock instanceof PsiCodeBlock
@@ -946,21 +1024,19 @@
prevSibling = prevSibling.getPrevSibling();
}
}
+ PsiReferenceExpression expression = methodCall.getMethodExpression();
String message = JavaErrorMessages.message("constructor.call.must.be.first.statement", expression.getText() + "()");
- PsiElement element = expression.getParent();
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(element).descriptionAndTooltip(message).create();
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCall).descriptionAndTooltip(message).create();
}
- static HighlightInfo checkAbstractMethodDirectCall(PsiSuperExpression expr) {
- if (expr.getParent() instanceof PsiReferenceExpression
- && expr.getParent().getParent() instanceof PsiMethodCallExpression) {
- PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expr.getParent().getParent();
- PsiMethod method = methodCallExpression.resolveMethod();
- if (method != null && method.hasModifierProperty(PsiModifier.ABSTRACT)) {
- String message = JavaErrorMessages.message("direct.abstract.method.access", JavaHighlightUtil.formatMethod(method));
- return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCallExpression).descriptionAndTooltip(message).create();
- }
+ static HighlightInfo checkSuperAbstractMethodDirectCall(@NotNull PsiMethodCallExpression methodCallExpression) {
+ PsiReferenceExpression expression = methodCallExpression.getMethodExpression();
+ if (!(expression.getQualifierExpression() instanceof PsiSuperExpression)) return null;
+ PsiMethod method = methodCallExpression.resolveMethod();
+ if (method != null && method.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ String message = JavaErrorMessages.message("direct.abstract.method.access", JavaHighlightUtil.formatMethod(method));
+ return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(methodCallExpression).descriptionAndTooltip(message).create();
}
return null;
}
@@ -1222,8 +1298,10 @@
}
- static void checkNewExpression(@NotNull PsiNewExpression expression, @NotNull HighlightInfoHolder holder, @NotNull JavaSdkVersion javaSdkVersion) {
- PsiType type = expression.getType();
+ static void checkNewExpression(@NotNull PsiNewExpression expression,
+ PsiType type,
+ @NotNull HighlightInfoHolder holder,
+ @NotNull JavaSdkVersion javaSdkVersion) {
if (!(type instanceof PsiClassType)) return;
PsiClassType.ClassResolveResult typeResult = ((PsiClassType)type).resolveGenerics();
PsiClass aClass = typeResult.getElement();
@@ -1417,7 +1495,9 @@
return builder.toString();
}
- private static void registerChangeParameterClassFix(PsiCall methodCall, PsiExpressionList list, HighlightInfo highlightInfo) {
+ private static void registerChangeParameterClassFix(@NotNull PsiCall methodCall,
+ @NotNull PsiExpressionList list,
+ HighlightInfo highlightInfo) {
final JavaResolveResult result = methodCall.resolveMethodGenerics();
PsiMethod method = (PsiMethod)result.getElement();
final PsiSubstitutor substitutor = result.getSubstitutor();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java
index e7b162f..b6b1365 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightNamesUtil.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.
@@ -234,21 +234,21 @@
DependencyValidationManagerImpl validationManager = (DependencyValidationManagerImpl)DependencyValidationManager.getInstance(file.getProject());
List<Pair<NamedScope,NamedScopesHolder>> scopes = validationManager.getScopeBasedHighlightingCachedScopes();
for (Pair<NamedScope, NamedScopesHolder> scope : scopes) {
- NamedScope namedScope = scope.getFirst();
- NamedScopesHolder scopesHolder = scope.getSecond();
- PackageSet packageSet = namedScope.getValue();
- if (packageSet != null && packageSet.contains(file, scopesHolder)) {
- TextAttributesKey scopeKey = ScopeAttributesUtil.getScopeTextAttributeKey(namedScope.getName());
- TextAttributes attributes = colorsScheme.getAttributes(scopeKey);
- if (attributes == null || attributes.isEmpty()) {
- continue;
- }
+ final NamedScope namedScope = scope.getFirst();
+ final TextAttributesKey scopeKey = ScopeAttributesUtil.getScopeTextAttributeKey(namedScope.getName());
+ final TextAttributes attributes = colorsScheme.getAttributes(scopeKey);
+ if (attributes == null || attributes.isEmpty()) {
+ continue;
+ }
+ final PackageSet packageSet = namedScope.getValue();
+ if (packageSet != null && packageSet.contains(file, scope.getSecond())) {
result = TextAttributes.merge(attributes, result);
}
}
return result;
}
+ @NotNull
public static TextRange getMethodDeclarationTextRange(@NotNull PsiMethod method) {
if (method instanceof SyntheticElement) return TextRange.EMPTY_RANGE;
int start = stripAnnotationsFromModifierList(method.getModifierList());
@@ -258,12 +258,14 @@
return new TextRange(start, end);
}
+ @NotNull
public static TextRange getFieldDeclarationTextRange(@NotNull PsiField field) {
int start = stripAnnotationsFromModifierList(field.getModifierList());
int end = field.getNameIdentifier().getTextRange().getEndOffset();
return new TextRange(start, end);
}
+ @NotNull
public static TextRange getClassDeclarationTextRange(@NotNull PsiClass aClass) {
if (aClass instanceof PsiEnumConstantInitializer) {
return ((PsiEnumConstantInitializer)aClass).getEnumConstant().getNameIdentifier().getTextRange();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
index cd01d32..7c4e8fa 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.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.
@@ -600,7 +600,7 @@
static HighlightInfo checkVariableAlreadyDefined(@NotNull PsiVariable variable) {
if (variable instanceof ExternallyDefinedPsiElement) return null;
boolean isIncorrect = false;
- PsiElement declarationScope;
+ PsiElement declarationScope = null;
if (variable instanceof PsiLocalVariable ||
variable instanceof PsiParameter &&
((declarationScope = ((PsiParameter)variable).getDeclarationScope()) instanceof PsiCatchSection ||
@@ -623,6 +623,8 @@
}
if (proc.size() > 0) {
isIncorrect = true;
+ } else if (declarationScope instanceof PsiLambdaExpression) {
+ isIncorrect = checkSameNames(variable);
}
}
else if (variable instanceof PsiField) {
@@ -635,17 +637,7 @@
}
}
else {
- PsiElement scope = variable.getParent();
- PsiElement[] children = scope.getChildren();
- for (PsiElement child : children) {
- if (child instanceof PsiVariable) {
- if (child.equals(variable)) continue;
- if (variable.getName().equals(((PsiVariable)child).getName())) {
- isIncorrect = true;
- break;
- }
- }
- }
+ isIncorrect = checkSameNames(variable);
}
if (isIncorrect) {
@@ -662,6 +654,20 @@
return null;
}
+ private static boolean checkSameNames(PsiVariable variable) {
+ PsiElement scope = variable.getParent();
+ PsiElement[] children = scope.getChildren();
+ for (PsiElement child : children) {
+ if (child instanceof PsiVariable) {
+ if (child.equals(variable)) continue;
+ if (variable.getName().equals(((PsiVariable)child).getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
@Nullable
public static HighlightInfo checkUnderscore(@NotNull PsiIdentifier identifier, @NotNull PsiVariable variable) {
if ("_".equals(variable.getName()) && PsiUtil.isLanguageLevel8OrHigher(variable)) {
@@ -1160,13 +1166,14 @@
}
@Nullable
- static Collection<HighlightInfo> checkExceptionThrownInTry(@NotNull final PsiParameter parameter, @NotNull final Set<PsiClassType> thrownTypes) {
+ static List<HighlightInfo> checkExceptionThrownInTry(@NotNull final PsiParameter parameter, @NotNull final Set<PsiClassType> thrownTypes) {
final PsiElement declarationScope = parameter.getDeclarationScope();
if (!(declarationScope instanceof PsiCatchSection)) return null;
final PsiType caughtType = parameter.getType();
if (caughtType instanceof PsiClassType) {
- return checkSimpleCatchParameter(parameter, thrownTypes, (PsiClassType)caughtType);
+ HighlightInfo info = checkSimpleCatchParameter(parameter, thrownTypes, (PsiClassType)caughtType);
+ return info == null ? null : Collections.<HighlightInfo>singletonList(info);
}
if (caughtType instanceof PsiDisjunctionType) {
return checkMultiCatchParameter(parameter, thrownTypes);
@@ -1176,7 +1183,7 @@
}
@Nullable
- private static Collection<HighlightInfo> checkSimpleCatchParameter(@NotNull final PsiParameter parameter,
+ private static HighlightInfo checkSimpleCatchParameter(@NotNull final PsiParameter parameter,
@NotNull final Collection<PsiClassType> thrownTypes,
@NotNull final PsiClassType caughtType) {
if (ExceptionUtil.isUncheckedExceptionOrSuperclass(caughtType)) return null;
@@ -1189,14 +1196,14 @@
final HighlightInfo errorResult =
HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parameter).descriptionAndTooltip(description).create();
QuickFixAction.registerQuickFixAction(errorResult, QUICK_FIX_FACTORY.createDeleteCatchFix(parameter));
- return Collections.singleton(errorResult);
+ return errorResult;
}
@Nullable
- private static Collection<HighlightInfo> checkMultiCatchParameter(@NotNull final PsiParameter parameter,
- @NotNull final Collection<PsiClassType> thrownTypes) {
+ private static List<HighlightInfo> checkMultiCatchParameter(@NotNull final PsiParameter parameter,
+ @NotNull final Collection<PsiClassType> thrownTypes) {
final List<PsiTypeElement> typeElements = PsiUtil.getParameterTypeElements(parameter);
- final Collection<HighlightInfo> highlights = ContainerUtil.newArrayListWithCapacity(typeElements.size());
+ final List<HighlightInfo> highlights = new ArrayList<HighlightInfo>(typeElements.size());
for (final PsiTypeElement typeElement : typeElements) {
final PsiType catchType = typeElement.getType();
@@ -1394,17 +1401,6 @@
String description = JavaErrorMessages.message("dot.expected.after.super.or.this");
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(o, o + 1).descriptionAndTooltip(description).create();
}
-
- if (PsiUtil.isLanguageLevel8OrHigher(expr)) {
- final PsiMethod method = PsiTreeUtil.getParentOfType(expr, PsiMethod.class);
- if (method != null && method.hasModifierProperty(PsiModifier.DEFAULT) && qualifier == null) {
- final String description = JavaErrorMessages.message("unqualified.super.disallowed");
- final HighlightInfo highlightInfo =
- HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(parent).descriptionAndTooltip(description).create();
- QualifySuperArgumentFix.registerQuickFixAction((PsiSuperExpression)expr, highlightInfo);
- return highlightInfo;
- }
- }
}
PsiClass aClass;
@@ -1444,6 +1440,21 @@
return null;
}
+ static HighlightInfo checkUnqualifiedSuperInDefaultMethod(@NotNull LanguageLevel languageLevel,
+ @NotNull PsiReferenceExpression expr,
+ PsiExpression qualifier) {
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && qualifier instanceof PsiSuperExpression) {
+ final PsiMethod method = PsiTreeUtil.getParentOfType(expr, PsiMethod.class);
+ if (method != null && method.hasModifierProperty(PsiModifier.DEFAULT) && ((PsiSuperExpression)qualifier).getQualifier() == null) {
+ String description = JavaErrorMessages.message("unqualified.super.disallowed");
+ HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(expr).descriptionAndTooltip(description).create();
+ QualifySuperArgumentFix.registerQuickFixAction((PsiSuperExpression)qualifier, info);
+ return info;
+ }
+ }
+ return null;
+ }
+
private static boolean isInsideDefaultMethod(PsiMethod method, PsiClass aClass) {
while (method != null && method.getContainingClass() != aClass) {
method = PsiTreeUtil.getParentOfType(method, PsiMethod.class, true);
@@ -1765,7 +1776,7 @@
if (expression.getTextRange().getStartOffset() >= referencedField.getTextRange().getEndOffset()) return null;
// only simple reference can be illegal
if (expression.getQualifierExpression() != null) return null;
- PsiField initField = findEnclosingFieldInitializer(expression, true);
+ PsiField initField = findEnclosingFieldInitializer(expression);
PsiClassInitializer classInitializer = findParentClassInitializer(expression);
if (initField == null && classInitializer == null) return null;
// instance initializers may access static fields
@@ -1786,11 +1797,6 @@
*/
@Nullable
public static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element) {
- return findEnclosingFieldInitializer(element, false);
- }
-
- @Nullable
- public static PsiField findEnclosingFieldInitializer(@Nullable PsiElement element, boolean stopAtLambda) {
while (element != null) {
PsiElement parent = element.getParent();
if (parent instanceof PsiField) {
@@ -1798,7 +1804,7 @@
if (element == field.getInitializer()) return field;
if (field instanceof PsiEnumConstant && element == ((PsiEnumConstant)field).getArgumentList()) return field;
}
- if (element instanceof PsiClass || element instanceof PsiMethod || (stopAtLambda && parent instanceof PsiLambdaExpression)) return null;
+ if (element instanceof PsiClass || element instanceof PsiMethod) return null;
element = parent;
}
return null;
@@ -2421,6 +2427,11 @@
QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createAddTypeCastFix(throwable, (PsiExpression)context));
}
}
+
+ final PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(type);
+ if (aClass != null) {
+ QuickFixAction.registerQuickFixAction(highlightInfo, QUICK_FIX_FACTORY.createExtendsListFix(aClass, throwable, true));
+ }
return highlightInfo;
}
return null;
@@ -2528,8 +2539,7 @@
}
}
if ((resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) && !(resolved instanceof ImplicitVariable)) {
- highlightInfo = HighlightControlFlowUtil.checkVariableMustBeFinal((PsiVariable)resolved, ref,
- languageLevel);
+ highlightInfo = HighlightControlFlowUtil.checkVariableMustBeFinal((PsiVariable)resolved, ref, languageLevel);
}
else if (resolved instanceof PsiClass) {
if (Comparing.strEqual(((PsiClass)resolved).getQualifiedName(), ((PsiClass)resolved).getName())) {
@@ -2807,9 +2817,14 @@
}
@Nullable
- public static HighlightInfo checkDiamondFeature(@NotNull PsiTypeElement typeElement, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
- return typeElement.getType() instanceof PsiDiamondType ? checkFeature(typeElement.getParent(), Feature.DIAMOND_TYPES,
- languageLevel, containingFile) : null;
+ public static HighlightInfo checkDiamondFeature(@NotNull PsiType type,
+ @NotNull PsiElement toHighlight,
+ @NotNull LanguageLevel languageLevel,
+ @NotNull PsiFile containingFile) {
+ if (type instanceof PsiDiamondType) {
+ return checkFeature(toHighlight, Feature.DIAMOND_TYPES, languageLevel, containingFile);
+ }
+ return null;
}
@Nullable
@@ -2819,8 +2834,8 @@
}
@Nullable
- public static HighlightInfo checkTryWithResourcesFeature(@NotNull PsiResourceVariable resourceVariable, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
- return checkFeature(resourceVariable.getParent(), Feature.TRY_WITH_RESOURCES, languageLevel, containingFile);
+ public static HighlightInfo checkTryWithResourcesFeature(@NotNull PsiElement toHighlight, @NotNull LanguageLevel languageLevel,@NotNull PsiFile containingFile) {
+ return checkFeature(toHighlight, Feature.TRY_WITH_RESOURCES, languageLevel, containingFile);
}
@Nullable
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 5946e8a..bf9f3e0 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
@@ -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,6 +21,7 @@
import com.intellij.codeInsight.daemon.impl.quickfix.QuickFixAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.colors.TextAttributesScheme;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -40,6 +41,7 @@
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTagValue;
import com.intellij.psi.util.*;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.MostlySingularMultiMap;
import gnu.trove.THashMap;
@@ -52,6 +54,7 @@
import java.util.Set;
public class HighlightVisitorImpl extends JavaElementVisitor implements HighlightVisitor {
+ @NotNull
private final PsiResolveHelper myResolveHelper;
private HighlightInfoHolder myHolder;
@@ -83,13 +86,14 @@
private final Map<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>> myDuplicateMethods = new THashMap<PsiClass, MostlySingularMultiMap<MethodSignature, PsiMethod>>();
private LanguageLevel myLanguageLevel;
private JavaSdkVersion myJavaSdkVersion;
+ private static final boolean CHECK_ELEMENT_LEVEL = ApplicationManager.getApplication().isUnitTestMode() || ApplicationManager.getApplication().isInternal();
public HighlightVisitorImpl(@NotNull PsiResolveHelper resolveHelper) {
myResolveHelper = resolveHelper;
}
@NotNull
- private MostlySingularMultiMap<MethodSignature, PsiMethod> getDuplicateMethods(PsiClass aClass) {
+ private MostlySingularMultiMap<MethodSignature, PsiMethod> getDuplicateMethods(@NotNull PsiClass aClass) {
MostlySingularMultiMap<MethodSignature, PsiMethod> signatures = myDuplicateMethods.get(aClass);
if (signatures == null) {
signatures = new MostlySingularMultiMap<MethodSignature, PsiMethod>();
@@ -122,7 +126,14 @@
@Override
public void visit(@NotNull PsiElement element) {
- element.accept(this);
+ if (CHECK_ELEMENT_LEVEL) {
+ ((CheckLevelHighlightInfoHolder)myHolder).enterLevel(element);
+ element.accept(this);
+ ((CheckLevelHighlightInfoHolder)myHolder).enterLevel(null);
+ }
+ else {
+ element.accept(this);
+ }
}
private void registerReferencesFromInjectedFragments(@NotNull PsiElement element) {
@@ -133,16 +144,17 @@
@NotNull final List<PsiLanguageInjectionHost.Shred> places) {
injectedPsi.accept(REGISTER_REFERENCES_VISITOR);
}
- });
+ }
+ );
}
@Override
public boolean analyze(@NotNull final PsiFile file,
final boolean updateWholeFile,
- @NotNull HighlightInfoHolder holder,
+ @NotNull final HighlightInfoHolder holder,
@NotNull final Runnable action) {
myFile = file;
- myHolder = holder;
+ myHolder = CHECK_ELEMENT_LEVEL ? new CheckLevelHighlightInfoHolder(file, holder) : holder;
boolean success = true;
try {
myLanguageLevel = PsiUtil.getLanguageLevel(file);
@@ -258,7 +270,7 @@
@Override
public void visitAssignmentExpression(PsiAssignmentExpression assignment) {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentCompatibleTypes(assignment));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment,myFile));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkAssignmentOperatorApplicable(assignment, myFile));
if (!myHolder.hasErrorResults()) visitExpression(assignment);
}
@@ -270,7 +282,7 @@
@Override
public void visitLambdaExpression(PsiLambdaExpression expression) {
- myHolder.add(HighlightUtil.checkLambdaFeature(expression, myLanguageLevel,myFile));
+ myHolder.add(HighlightUtil.checkLambdaFeature(expression, myLanguageLevel, myFile));
if (!myHolder.hasErrorResults()) {
if (LambdaUtil.isValidLambdaContext(expression.getParent())) {
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
@@ -370,6 +382,7 @@
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findExitedStatement()));
}
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBreakOutsideLoop(statement));
}
@Override
@@ -381,6 +394,7 @@
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumMustNotBeLocal(aClass));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkImplicitThisReferenceBeforeSuper(aClass, myJavaSdkVersion));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkClassAndPackageConflict(aClass));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkPublicClassInRightFile(aClass));
}
@Override
@@ -412,6 +426,7 @@
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightUtil.checkLabelDefined(statement.getLabelIdentifier(), statement.findContinuedStatement()));
}
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkContinueOutsideLoop(statement));
}
@Override
@@ -516,6 +531,37 @@
}
@Override
+ public void visitExpressionList(PsiExpressionList list) {
+ super.visitExpressionList(list);
+ PsiElement parent = list.getParent();
+ if (parent instanceof PsiMethodCallExpression) {
+ PsiMethodCallExpression expression = (PsiMethodCallExpression)parent;
+ if (expression.getArgumentList() == list) {
+ PsiReferenceExpression referenceExpression = expression.getMethodExpression();
+ JavaResolveResult result;
+ JavaResolveResult[] results;
+ try {
+ results = resolveOptimised(referenceExpression);
+ result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
+ }
+ catch (IndexNotReadyException e) {
+ return;
+ }
+ PsiElement resolved = result.getElement();
+
+ if ((!result.isAccessible() || !result.isStaticsScopeCorrect()) &&
+ !HighlightMethodUtil.isDummyConstructorCall(expression, myResolveHelper, list, referenceExpression)) {
+ try {
+ myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallArguments(referenceExpression, results, list, resolved, result, expression, myResolveHelper));
+ }
+ catch (IndexNotReadyException ignored) {
+ }
+ }
+ }
+ }
+ }
+
+ @Override
public void visitField(PsiField field) {
super.visitField(field);
if (!myHolder.hasErrorResults()) myHolder.add(HighlightControlFlowUtil.checkFinalFieldInitialized(field));
@@ -529,6 +575,7 @@
@Override
public void visitForeachStatement(final PsiForeachStatement statement) {
myHolder.add(HighlightUtil.checkForEachFeature(statement, myLanguageLevel, myFile));
+ if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkForeachLoopParameterType(statement));
}
@Override
@@ -551,7 +598,11 @@
}
boolean isMethodParameter = variable instanceof PsiParameter && ((PsiParameter)variable).getDeclarationScope() instanceof PsiMethod;
- if (!isMethodParameter) { // method params are highlighted in visitMethod since we should make sure the method body was visited before
+ if (isMethodParameter) {
+ myReassignedParameters.put((PsiParameter)variable, 1); // mark param as present in current file
+ }
+ else {
+ // method params are highlighted in visitMethod since we should make sure the method body was visited before
if (HighlightControlFlowUtil.isReassigned(variable, myFinalVarProblems)) {
myHolder.add(HighlightNamesUtil.highlightReassignedVariable(variable, identifier));
}
@@ -559,9 +610,6 @@
myHolder.add(HighlightNamesUtil.highlightVariableName(variable, identifier, colorsScheme));
}
}
- else {
- myReassignedParameters.put((PsiParameter)variable, 1); // mark param as present in current file
- }
myHolder.add(HighlightUtil.checkUnderscore(identifier, variable));
}
@@ -575,6 +623,9 @@
if (!(parent instanceof PsiAnonymousClass) && aClass.getNameIdentifier() == identifier) {
myHolder.add(HighlightNamesUtil.highlightClassName(aClass, identifier, colorsScheme));
}
+ if (!myHolder.hasErrorResults() && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
+ myHolder.add(GenericsHighlightUtil.checkUnrelatedDefaultMethods(aClass, aClass.getVisibleSignatures(), identifier));
+ }
}
else if (parent instanceof PsiMethod) {
PsiMethod method = (PsiMethod)parent;
@@ -582,32 +633,14 @@
myHolder.add(HighlightMethodUtil.checkConstructorName(method));
}
myHolder.add(HighlightNamesUtil.highlightMethodName(method, identifier, true, colorsScheme));
- }
- else {
- visitParentReference(parent);
+ myHolder.add(GenericsHighlightUtil.checkDefaultMethodOverrideEquivalentToObjectNonPrivate(myLanguageLevel,
+ method.getContainingClass(), method,
+ identifier));
}
super.visitIdentifier(identifier);
}
- private void visitParentReference(PsiElement parent) {
- if (parent instanceof PsiJavaCodeReferenceElement && !(parent.getParent() instanceof PsiJavaCodeReferenceElement) &&
- !((PsiJavaCodeReferenceElement)parent).isQualified()) {
- PsiJavaCodeReferenceElement ref = (PsiJavaCodeReferenceElement)parent;
- JavaResolveResult result;
- try {
- result = ref.advancedResolve(true);
- }
- catch (IndexNotReadyException e) {
- return;
- }
- myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
- if (myRefCountHolder != null) {
- myRefCountHolder.registerReference(ref, result);
- }
- }
- }
-
@Override
public void visitImportStatement(final PsiImportStatement statement) {
if (!myHolder.hasErrorResults()) {
@@ -681,27 +714,15 @@
PsiModifierList psiModifierList = (PsiModifierList)parent;
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkNotAllowedModifier(keyword, psiModifierList));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalModifierCombination(keyword, psiModifierList));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkPublicClassInRightFile(keyword, psiModifierList));
if (PsiModifier.ABSTRACT.equals(text) && psiModifierList.getParent() instanceof PsiMethod) {
if (!myHolder.hasErrorResults()) {
myHolder.add(HighlightMethodUtil.checkAbstractMethodInConcreteClass((PsiMethod)psiModifierList.getParent(), keyword));
}
}
}
- else if (PsiKeyword.CONTINUE.equals(text) && parent instanceof PsiContinueStatement) {
- PsiContinueStatement statement = (PsiContinueStatement)parent;
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkContinueOutsideLoop(statement));
- }
- else if (PsiKeyword.BREAK.equals(text) && parent instanceof PsiBreakStatement) {
- PsiBreakStatement statement = (PsiBreakStatement)parent;
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkBreakOutsideLoop(statement));
- }
else if (PsiKeyword.INTERFACE.equals(text) && parent instanceof PsiClass) {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkInterfaceCannotBeLocal((PsiClass)parent));
}
- else {
- visitParentReference(parent);
- }
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkStaticDeclarationInInnerClass(keyword));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalVoidType(keyword));
@@ -734,9 +755,15 @@
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkRecursiveConstructorInvocation(method));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideAnnotation(method, myLanguageLevel));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkSafeVarargsAnnotation(method));
+ PsiClass aClass = method.getContainingClass();
if (!myHolder.hasErrorResults() && method.isConstructor()) {
- myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, method.getContainingClass()));
+ myHolder.add(HighlightClassUtil.checkThingNotAllowedInInterface(method, aClass));
}
+ if (!myHolder.hasErrorResults() && method.hasModifierProperty(PsiModifier.DEFAULT)) {
+ myHolder.add(HighlightUtil.checkExtensionMethodsFeature(method, myLanguageLevel, myFile));
+ }
+
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
// method params are highlighted in visitMethod since we should make sure the method body was visited before
PsiParameter[] parameters = method.getParameterList().getParameters();
@@ -810,6 +837,9 @@
}
}
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkSuperAbstractMethodDirectCall(expression));
+
if (!myHolder.hasErrorResults()) visitExpression(expression);
}
@@ -838,7 +868,6 @@
}
PsiClass aClass = method.getContainingClass();
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkMethodMustHaveBody(method, aClass));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkDuplicateMethod(aClass, method, getDuplicateMethods(aClass)));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallsBaseClassConstructor(method, myRefCountHolder, myResolveHelper));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkStaticMethodOverride(method,myFile));
}
@@ -854,7 +883,8 @@
myHolder.add(HighlightClassUtil.checkClassDoesNotCallSuperConstructorOrHandleExceptions(aClass, myRefCountHolder, myResolveHelper));
}
if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkOverrideEquivalentInheritedMethods(aClass, myFile));
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(aClass));
+ if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass
+ ));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCyclicInheritance(aClass));
}
catch (IndexNotReadyException ignored) {
@@ -879,18 +909,21 @@
@Override
public void visitNewExpression(PsiNewExpression expression) {
+ final PsiType type = expression.getType();
+ final PsiClass aClass = PsiUtil.resolveClassInType(type);
myHolder.add(HighlightUtil.checkUnhandledExceptions(expression, null));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkAnonymousInheritFinal(expression));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNew(expression));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkQualifiedNew(expression, type, aClass));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkCreateInnerClassFromStaticContext(expression, type, aClass));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkTypeParameterInstantiation(expression));
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightClassUtil.checkInstantiationOfAbstractClass(aClass, expression));
try {
- if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, myHolder, myJavaSdkVersion);
+ if (!myHolder.hasErrorResults()) HighlightMethodUtil.checkNewExpression(expression, type, myHolder, myJavaSdkVersion);
}
catch (IndexNotReadyException ignored) {
}
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression));
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, expression.getType()));
+ if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkEnumInstantiation(expression, aClass));
+ if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkGenericArrayCreation(expression, type));
if (!myHolder.hasErrorResults()) registerConstructorCall(expression);
if (!myHolder.hasErrorResults()) visitExpression(expression);
@@ -911,9 +944,6 @@
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkVarArgParameterIsLast(parameter,
myLanguageLevel,myFile));
}
- else if (parent instanceof PsiForeachStatement) {
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkForeachLoopParameterType((PsiForeachStatement)parent));
- }
else if (parent instanceof PsiCatchSection) {
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkMultiCatchFeature(parameter, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkCatchParameterIsThrowable(parameter));
@@ -944,7 +974,7 @@
}
}
- private void registerConstructorCall(PsiConstructorCall constructorCall) {
+ private void registerConstructorCall(@NotNull PsiConstructorCall constructorCall) {
if (myRefCountHolder != null) {
JavaResolveResult resolveResult = constructorCall.resolveMethodGenerics();
final PsiElement resolved = resolveResult.getElement();
@@ -956,23 +986,14 @@
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement ref) {
- doVisitReferenceElement(ref);
+ JavaResolveResult resolveResult = doVisitReferenceElement(ref);
+ if (resolveResult != null && !myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkRawOnParameterizedType(ref, resolveResult.getElement()));
}
private JavaResolveResult doVisitReferenceElement(@NotNull PsiJavaCodeReferenceElement ref) {
JavaResolveResult result;
try {
- if (ref instanceof PsiReferenceExpressionImpl) {
- PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)ref;
- JavaResolveResult[] results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
- PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE,
- true, true,
- myFile);
- result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
- }
- else {
- result = ref.advancedResolve(true);
- }
+ result = resolveOptimised(ref);
}
catch (IndexNotReadyException e) {
return null;
@@ -980,11 +1001,11 @@
PsiElement resolved = result.getElement();
PsiElement parent = ref.getParent();
+ if (myRefCountHolder != null) {
+ myRefCountHolder.registerReference(ref, result);
+ }
+ myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
if (parent instanceof PsiJavaCodeReferenceElement || ref.isQualified()) {
- if (myRefCountHolder != null) {
- myRefCountHolder.registerReference(ref, result);
- }
- myHolder.add(HighlightUtil.checkReference(ref, result, myFile, myLanguageLevel));
if (!myHolder.hasErrorResults() && resolved instanceof PsiTypeParameter) {
boolean cannotSelectFromTypeParameter = !myJavaSdkVersion.isAtLeast(JavaSdkVersion.JDK_1_7);
if (!cannotSelectFromTypeParameter) {
@@ -1018,7 +1039,8 @@
}
if (parent instanceof PsiAnonymousClass && ref.equals(((PsiAnonymousClass)parent).getBaseClassReference())) {
- myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods((PsiClass)parent));
+ PsiClass aClass = (PsiClass)parent;
+ myHolder.add(GenericsHighlightUtil.checkOverrideEquivalentMethods(myLanguageLevel, aClass));
}
if (resolved instanceof PsiVariable) {
@@ -1091,6 +1113,38 @@
return result;
}
+ @NotNull
+ private JavaResolveResult resolveOptimised(@NotNull PsiJavaCodeReferenceElement ref) {
+ JavaResolveResult result;
+ if (ref instanceof PsiReferenceExpressionImpl) {
+ PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)ref;
+ JavaResolveResult[] results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
+ PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE,
+ true, true,
+ myFile);
+ result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
+ }
+ else {
+ result = ref.advancedResolve(true);
+ }
+ return result;
+ }
+
+ @NotNull
+ private JavaResolveResult[] resolveOptimised(@NotNull PsiReferenceExpression expression) {
+ JavaResolveResult[] results;
+ if (expression instanceof PsiReferenceExpressionImpl) {
+ PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)expression;
+ results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
+ PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, true,
+ myFile);
+ }
+ else {
+ results = expression.multiResolve(true);
+ }
+ return results;
+ }
+
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
JavaResolveResult resultForIncompleteCode = doVisitReferenceElement(expression);
@@ -1101,15 +1155,7 @@
JavaResolveResult result;
JavaResolveResult[] results;
try {
- if (expression instanceof PsiReferenceExpressionImpl) {
- PsiReferenceExpressionImpl referenceExpression = (PsiReferenceExpressionImpl)expression;
- results = JavaResolveUtil.resolveWithContainingFile(referenceExpression,
- PsiReferenceExpressionImpl.OurGenericsResolver.INSTANCE, true, true,
- myFile);
- }
- else {
- results = expression.multiResolve(true);
- }
+ results = resolveOptimised(expression);
result = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
}
catch (IndexNotReadyException e) {
@@ -1140,13 +1186,14 @@
PsiExpressionList list = methodCallExpression.getArgumentList();
if (!HighlightMethodUtil.isDummyConstructorCall(methodCallExpression, myResolveHelper, list, expression)) {
try {
- HighlightInfo info = HighlightMethodUtil.checkAmbiguousMethodCall(expression, results, list, resolved, result, methodCallExpression, myResolveHelper);
- myHolder.add(info);
+ myHolder.add(HighlightMethodUtil.checkAmbiguousMethodCallIdentifier(expression, results, list, resolved, result,
+ methodCallExpression, myResolveHelper));
}
catch (IndexNotReadyException ignored) {
}
}
}
+
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkExpressionRequired(expression, resultForIncompleteCode));
if (!myHolder.hasErrorResults() && resolved instanceof PsiField) {
try {
@@ -1155,9 +1202,9 @@
catch (IndexNotReadyException ignored) {
}
}
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkConstructorCallMustBeFirstStatement(expression));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkAccessStaticFieldFromEnumConstructor(expression, result));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkClassReferenceAfterQualifier(expression, resolved));
+ myHolder.add(HighlightUtil.checkUnqualifiedSuperInDefaultMethod(myLanguageLevel, expression, expression.getQualifierExpression()));
}
@Override
@@ -1249,7 +1296,13 @@
}
if (!myHolder.hasErrorResults() && method instanceof PsiTypeParameterListOwner) {
- myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments((PsiTypeParameterListOwner)method, expression, result.getSubstitutor()));
+ PsiTypeParameter[] typeParameters = ((PsiTypeParameterListOwner)method).getTypeParameters();
+ if (method instanceof PsiMethod) {
+ final PsiClass containingClass = ((PsiMethod)method).getContainingClass();
+ assert containingClass != null : method;
+ typeParameters = ArrayUtil.mergeArrays(typeParameters, containingClass.getTypeParameters());
+ }
+ myHolder.add(GenericsHighlightUtil.checkInferredTypeArguments(typeParameters, expression, result.getSubstitutor()));
}
}
@@ -1270,7 +1323,11 @@
public void visitReferenceParameterList(PsiReferenceParameterList list) {
myHolder.add(GenericsHighlightUtil.checkParametersAllowed(list, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkParametersOnRaw(list));
- if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkRawOnParameterizedType(list));
+ if (!myHolder.hasErrorResults()) {
+ for (PsiType type : list.getTypeArguments()) {
+ myHolder.add(HighlightUtil.checkDiamondFeature(type, list, myLanguageLevel,myFile));
+ }
+ }
}
@Override
@@ -1292,7 +1349,6 @@
@Override
public void visitSuperExpression(PsiSuperExpression expr) {
myHolder.add(HighlightUtil.checkThisOrSuperExpressionInIllegalContext(expr, expr.getQualifier()));
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightMethodUtil.checkAbstractMethodDirectCall(expr));
if (!myHolder.hasErrorResults()) visitExpression(expr);
}
@@ -1345,14 +1401,18 @@
@Override
public void visitResourceVariable(final PsiResourceVariable resourceVariable) {
visitVariable(resourceVariable);
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryWithResourcesFeature(resourceVariable, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryResourceIsAutoCloseable(resourceVariable));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkUnhandledCloserExceptions(resourceVariable));
}
@Override
+ public void visitResourceList(PsiResourceList resourceList) {
+ super.visitResourceList(resourceList);
+ if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkTryWithResourcesFeature(resourceList, myLanguageLevel, myFile));
+ }
+
+ @Override
public void visitTypeElement(final PsiTypeElement type) {
- if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkDiamondFeature(type, myLanguageLevel,myFile));
if (!myHolder.hasErrorResults()) myHolder.add(HighlightUtil.checkIllegalType(type));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkReferenceTypeUsedAsTypeArgument(type));
if (!myHolder.hasErrorResults()) myHolder.add(GenericsHighlightUtil.checkWildcardUsage(type));
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java
index be85a95..257f7c0 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/IncreaseLanguageLevelFix.java
@@ -70,6 +70,7 @@
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return false;
final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
+ if (module == null) return false;
return isLanguageLevelAcceptable(project, module, myLevel);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsFix.java
index 805a045..1a55195 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddTypeArgumentsFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -64,7 +64,7 @@
final PsiTypeParameter[] typeParameters = method.getTypeParameters();
if (typeParameters.length > 0) {
- PsiType[] mappings = new PsiType[typeParameters.length];
+ PsiType[] mappings = PsiType.createArray(typeParameters.length);
PsiResolveHelper helper = JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper();
LanguageLevel level = PsiUtil.getLanguageLevel(expression);
for (int i = 0; i < typeParameters.length; i++) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java
index 76bf6ae..760beff 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ArgumentFixerActionFactory.java
@@ -90,6 +90,10 @@
if (parameterType instanceof PsiWildcardType) continue;
if (!GenericsUtil.isFromExternalTypeLanguage(parameterType)) continue;
if (suggestedCasts.contains(parameterType.getCanonicalText())) continue;
+ if (exprType instanceof PsiPrimitiveType && parameterType instanceof PsiClassType) {
+ parameterType = PsiPrimitiveType.getUnboxedType(parameterType);
+ if (parameterType == null) continue;
+ }
// strict compare since even widening cast may help
if (Comparing.equal(exprType, parameterType)) continue;
PsiCall newCall = (PsiCall) call.copy();
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CastMethodArgumentFix.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CastMethodArgumentFix.java
index 04a7b58..f96118b 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CastMethodArgumentFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CastMethodArgumentFix.java
@@ -66,6 +66,10 @@
parameterType = ((PsiPrimitiveType)parameterType).getBoxedType(context); //unboxing from type of cast expression will take place at runtime
if (parameterType == null) return false;
}
+ if (exprType instanceof PsiPrimitiveType && parameterType instanceof PsiClassType) {
+ parameterType = PsiPrimitiveType.getUnboxedType(parameterType);
+ if (parameterType == null) return false;
+ }
return parameterType.isConvertibleFrom(exprType);
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
index d9bfebc..d6c4f03 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInsight/guess/impl/GuessManagerImpl.java
@@ -1,4 +1,3 @@
-
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
@@ -102,7 +101,7 @@
}
}
- return typesSet.toArray(new PsiType[typesSet.size()]);
+ return typesSet.toArray(PsiType.createArray(typesSet.size()));
}
@Nullable
@@ -125,7 +124,7 @@
addExprTypesWhenContainerElement(types, expr);
addExprTypesByDerivedClasses(types, expr);
- return types.toArray(new PsiType[types.size()]);
+ return types.toArray(PsiType.createArray(types.size()));
}
@NotNull
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AddAssertStatementFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AddAssertStatementFix.java
index 4bdf058..257b9a6 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AddAssertStatementFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AddAssertStatementFix.java
@@ -53,6 +53,10 @@
PsiElement element = descriptor.getPsiElement();
PsiElement anchorElement = PsiTreeUtil.getParentOfType(element, PsiStatement.class);
LOG.assertTrue(anchorElement != null);
+ final PsiElement tempParent = anchorElement.getParent();
+ if (tempParent instanceof PsiForStatement && !PsiTreeUtil.isAncestor(((PsiForStatement)tempParent).getBody(), anchorElement, false)) {
+ anchorElement = tempParent;
+ }
PsiElement prev = PsiTreeUtil.skipSiblingsBackward(anchorElement, PsiWhiteSpace.class);
if (prev instanceof PsiComment && JavaSuppressionUtil.getSuppressedInspectionIdsIn(prev) != null) {
anchorElement = prev;
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 1d8a128..93e4951 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java
@@ -17,10 +17,10 @@
import com.intellij.codeInsight.ChangeContextUtil;
import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -29,9 +29,12 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.HashSet;
+import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
+import java.util.HashMap;
+import java.util.Map;
import java.util.Set;
/**
@@ -129,7 +132,6 @@
if (field != null) {
final PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField &&
- ((PsiField)resolved).hasModifierProperty(PsiModifier.FINAL) &&
!((PsiField)resolved).hasInitializer() &&
((PsiField)resolved).getContainingClass() == field.getContainingClass()) {
bodyContainsForbiddenRefs[0] = true;
@@ -181,8 +183,8 @@
final PsiMethod method = anonymousClass.getMethods()[0];
LOG.assertTrue(method != null);
- final String lambdaWithTypesDeclared = composeLambdaText(method, lambdaContext, true);
- final String withoutTypesDeclared = composeLambdaText(method, lambdaContext, false);
+ final String lambdaWithTypesDeclared = composeLambdaText(method, true);
+ final String withoutTypesDeclared = composeLambdaText(method, false);
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
PsiLambdaExpression lambdaExpression =
(PsiLambdaExpression)elementFactory.createExpressionFromText(withoutTypesDeclared, anonymousClass);
@@ -202,6 +204,43 @@
LOG.assertTrue(lambdaBody != null);
lambdaBody.replace(copy);
+ final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
+ final Map<PsiParameter, String> names = new HashMap<PsiParameter, String>();
+ for (PsiParameter parameter : lambdaExpression.getParameterList().getParameters()) {
+ String parameterName = parameter.getName();
+ final String uniqueVariableName = codeStyleManager.suggestUniqueVariableName(parameterName, lambdaContext, false);
+ if (!Comparing.equal(parameterName, uniqueVariableName)) {
+ names.put(parameter, uniqueVariableName);
+ }
+ }
+
+ final LinkedHashMap<PsiElement, PsiElement> replacements = new LinkedHashMap<PsiElement, PsiElement>();
+ lambdaExpression.accept(new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitParameter(PsiParameter parameter) {
+ final String newName = names.get(parameter);
+ if (newName != null) {
+ replacements.put(parameter.getNameIdentifier(), elementFactory.createIdentifier(newName));
+ }
+ }
+
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
+ final PsiElement resolve = expression.resolve();
+ if (resolve instanceof PsiParameter) {
+ final String newName = names.get(resolve);
+ if (newName != null) {
+ replacements.put(expression, elementFactory.createExpressionFromText(newName, expression));
+ }
+ }
+ }
+ });
+
+ for (PsiElement psiElement : replacements.keySet()) {
+ psiElement.replace(replacements.get(psiElement));
+ }
+
final PsiNewExpression newExpression = (PsiNewExpression)anonymousClass.getParent();
lambdaExpression = (PsiLambdaExpression)newExpression.replace(lambdaExpression);
ChangeContextUtil.decodeContextInfo(lambdaExpression, null, null);
@@ -254,18 +293,17 @@
interfaceType) != null;
}
- private static String composeLambdaText(PsiMethod method, final PsiElement lambdaContext, final boolean appendType) {
+ private static String composeLambdaText(PsiMethod method, final boolean appendType) {
final StringBuilder buf = new StringBuilder();
final PsiParameter[] parameters = method.getParameterList().getParameters();
if (parameters.length != 1 || appendType) {
buf.append("(");
}
- final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(lambdaContext.getProject());
buf.append(StringUtil.join(parameters,
new Function<PsiParameter, String>() {
@Override
public String fun(PsiParameter parameter) {
- return composeParameter(parameter, appendType, codeStyleManager, lambdaContext);
+ return composeParameter(parameter, appendType);
}
}, ","));
if (parameters.length != 1 || appendType) {
@@ -276,9 +314,7 @@
}
private static String composeParameter(PsiParameter parameter,
- boolean appendType,
- JavaCodeStyleManager codeStyleManager,
- PsiElement lambdaContext) {
+ boolean appendType) {
final String parameterType;
if (appendType) {
final PsiTypeElement typeElement = parameter.getTypeElement();
@@ -291,7 +327,7 @@
if (parameterName == null) {
parameterName = "";
}
- return parameterType + codeStyleManager.suggestUniqueVariableName(parameterName, lambdaContext, true);
+ return parameterType + parameterName;
}
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java
index ca09e77..63dec13 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/JavaSuppressionUtil.java
@@ -166,7 +166,7 @@
return getInspectionIdsSuppressedInAnnotation(modifierList);
}
- static String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
+ public static String getSuppressedInspectionIdsIn(@NotNull PsiElement element) {
if (element instanceof PsiComment) {
String text = element.getText();
Matcher matcher = SuppressionUtil.SUPPRESS_IN_LINE_COMMENT_PATTERN.matcher(text);
@@ -205,7 +205,7 @@
return statement;
}
- PsiVariable local = PsiTreeUtil.getParentOfType(place, PsiVariable.class);
+ PsiVariable local = PsiTreeUtil.getParentOfType(place, PsiVariable.class, false);
if (local != null && getAnnotationMemberSuppressedIn(local, toolId) != null) {
PsiModifierList modifierList = local.getModifierList();
return modifierList != null ? modifierList.findAnnotation(SUPPRESS_INSPECTIONS_ANNOTATION_NAME) : null;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/RemoveAnnotationQuickFix.java b/java/java-analysis-impl/src/com/intellij/codeInspection/RemoveAnnotationQuickFix.java
index 2993b39..fd553e4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/RemoveAnnotationQuickFix.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/RemoveAnnotationQuickFix.java
@@ -54,7 +54,7 @@
catch (IncorrectOperationException e) {
LOG.error(e);
}
- } else {
+ } else if (myListOwner != null) {
ExternalAnnotationsManager.getInstance(project).deannotate(myListOwner, myAnnotation.getQualifiedName());
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java
index e628b92..8f8e35e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlow.java
@@ -27,7 +27,6 @@
import com.intellij.codeInspection.dataFlow.instructions.FlushVariableInstruction;
import com.intellij.codeInspection.dataFlow.instructions.Instruction;
import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
-import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiVariable;
import gnu.trove.TObjectIntHashMap;
@@ -40,7 +39,6 @@
private final List<Instruction> myInstructions = new ArrayList<Instruction>();
private final TObjectIntHashMap<PsiElement> myElementToStartOffsetMap = new TObjectIntHashMap<PsiElement>();
private final TObjectIntHashMap<PsiElement> myElementToEndOffsetMap = new TObjectIntHashMap<PsiElement>();
- private DfaVariableValue[] myFields;
private final DfaValueFactory myFactory;
public ControlFlow(final DfaValueFactory factory) {
@@ -101,15 +99,6 @@
};
}
- public DfaVariableValue[] getFields() {
- return myFields;
- }
-
- public void setFields(DfaVariableValue[] fields) {
- myFields = fields;
- }
-
-
public String toString() {
StringBuilder result = new StringBuilder();
final List<Instruction> instructions = myInstructions;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
index 22c919c..75f2419 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ControlFlowAnalyzer.java
@@ -52,7 +52,6 @@
private final DfaValueFactory myFactory;
private ControlFlow myCurrentFlow;
- private Set<DfaVariableValue> myFields;
private Stack<CatchDescriptor> myCatchStack;
private DfaValue myRuntimeException;
private DfaValue myError;
@@ -83,7 +82,6 @@
PsiParameter mockVar = JavaPsiFacade.getElementFactory(manager.getProject()).createParameterFromText("java.lang.Object $exception$", null);
myExceptionHolder = myFactory.getVarFactory().createVariableValue(mockVar, false);
- myFields = new HashSet<DfaVariableValue>();
myCatchStack = new Stack<CatchDescriptor>();
myCurrentFlow = new ControlFlow(myFactory);
@@ -98,7 +96,6 @@
if (parent instanceof PsiLambdaExpression && codeFragment instanceof PsiExpression) {
addInstruction(new CheckReturnValueInstruction(codeFragment));
}
- myCurrentFlow.setFields(myFields.toArray(new DfaVariableValue[myFields.size()]));
addInstruction(new ReturnInstruction(false));
@@ -153,54 +150,55 @@
return;
}
- lExpr.accept(this);
-
IElementType op = expression.getOperationTokenType();
PsiType type = expression.getType();
boolean isBoolean = PsiType.BOOLEAN.equals(type);
if (op == JavaTokenType.EQ) {
+ lExpr.accept(this);
rExpr.accept(this);
generateBoxingUnboxingInstructionFor(rExpr, type);
}
else if (op == JavaTokenType.ANDEQ) {
if (isBoolean) {
- generateNonLazyExpression(true, lExpr, rExpr, type);
+ generateBooleanAssignmentExpression(true, lExpr, rExpr, type);
}
else {
- generateDefaultBinOp(lExpr, rExpr, type);
+ generateDefaultAssignmentBinOp(lExpr, rExpr, type);
}
}
else if (op == JavaTokenType.OREQ) {
if (isBoolean) {
- generateNonLazyExpression(false, lExpr, rExpr, type);
+ generateBooleanAssignmentExpression(false, lExpr, rExpr, type);
}
else {
- generateDefaultBinOp(lExpr, rExpr, type);
+ generateDefaultAssignmentBinOp(lExpr, rExpr, type);
}
}
else if (op == JavaTokenType.XOREQ) {
if (isBoolean) {
- generateXorExpression(expression, new PsiExpression[]{lExpr, rExpr}, type);
+ generateXorExpression(expression, new PsiExpression[]{lExpr, rExpr}, type, true);
}
else {
- generateDefaultBinOp(lExpr, rExpr, type);
+ generateDefaultAssignmentBinOp(lExpr, rExpr, type);
}
}
else if (op == JavaTokenType.PLUSEQ && type != null && type.equalsToText(JAVA_LANG_STRING)) {
lExpr.accept(this);
+ addInstruction(new DupInstruction());
rExpr.accept(this);
addInstruction(new BinopInstruction(JavaTokenType.PLUS, null, lExpr.getProject()));
}
else {
- generateDefaultBinOp(lExpr, rExpr, type);
+ generateDefaultAssignmentBinOp(lExpr, rExpr, type);
}
addInstruction(new AssignInstruction(rExpr));
finishElement(expression);
}
- private void generateDefaultBinOp(PsiExpression lExpr, PsiExpression rExpr, final PsiType exprType) {
+ private void generateDefaultAssignmentBinOp(PsiExpression lExpr, PsiExpression rExpr, final PsiType exprType) {
lExpr.accept(this);
+ addInstruction(new DupInstruction());
generateBoxingUnboxingInstructionFor(lExpr,exprType);
rExpr.accept(this);
generateBoxingUnboxingInstructionFor(rExpr, exprType);
@@ -1062,7 +1060,7 @@
generateOrExpression(operands, type, true);
}
else if (op == JavaTokenType.XOR && PsiType.BOOLEAN.equals(type)) {
- generateXorExpression(expression, operands, type);
+ generateXorExpression(expression, operands, type, false);
}
else if (op == JavaTokenType.AND && PsiType.BOOLEAN.equals(type)) {
generateAndExpression(operands, type, false);
@@ -1153,9 +1151,12 @@
}
}
- private void generateXorExpression(PsiExpression expression, PsiExpression[] operands, final PsiType exprType) {
+ private void generateXorExpression(PsiExpression expression, PsiExpression[] operands, final PsiType exprType, boolean forAssignment) {
PsiExpression operand = operands[0];
operand.accept(this);
+ if (forAssignment) {
+ addInstruction(new DupInstruction());
+ }
generateBoxingUnboxingInstructionFor(operand, exprType);
for (int i = 1; i < operands.length; i++) {
operand = operands[i];
@@ -1187,12 +1188,14 @@
}
}
- private void generateNonLazyExpression(boolean and, PsiExpression lExpression, PsiExpression rExpression, PsiType exprType) {
- rExpression.accept(this);
- generateBoxingUnboxingInstructionFor(rExpression, exprType);
-
+ private void generateBooleanAssignmentExpression(boolean and, PsiExpression lExpression, PsiExpression rExpression, PsiType exprType) {
lExpression.accept(this);
generateBoxingUnboxingInstructionFor(lExpression, exprType);
+ addInstruction(new DupInstruction());
+
+ rExpression.accept(this);
+ generateBoxingUnboxingInstructionFor(rExpression, exprType);
+ addInstruction(new SwapInstruction());
combineStackBooleans(and, lExpression);
}
@@ -1359,12 +1362,26 @@
PsiExpression[] expressions = expression.getArgumentList().getExpressions();
PsiElement method = methodExpression.resolve();
PsiParameter[] parameters = method instanceof PsiMethod ? ((PsiMethod)method).getParameterList().getParameters() : null;
+ boolean isEqualsCall = expressions.length == 1 && method instanceof PsiMethod &&
+ "equals".equals(((PsiMethod)method).getName()) && parameters.length == 1 &&
+ parameters[0].getType().equalsToText(JAVA_LANG_OBJECT) &&
+ PsiType.BOOLEAN.equals(((PsiMethod)method).getReturnType());
+
for (int i = 0; i < expressions.length; i++) {
PsiExpression paramExpr = expressions[i];
paramExpr.accept(this);
if (parameters != null && i < parameters.length) {
generateBoxingUnboxingInstructionFor(paramExpr, parameters[i].getType());
}
+ if (i == 0 && isEqualsCall) {
+ // stack: .., qualifier, arg1
+ addInstruction(new SwapInstruction());
+ // stack: .., arg1, qualifier
+ addInstruction(new DupInstruction(2, 1));
+ // stack: .., arg1, qualifier, arg1, qualifier
+ addInstruction(new PopInstruction());
+ // stack: .., arg1, qualifier, arg1
+ }
}
addConditionalRuntimeThrow();
@@ -1374,19 +1391,20 @@
addMethodThrows(expression.resolveMethod());
}
- if (expressions.length == 1 && method instanceof PsiMethod &&
- "equals".equals(((PsiMethod)method).getName()) && parameters.length == 1 &&
- parameters[0].getType().equalsToText(JAVA_LANG_OBJECT) &&
- PsiType.BOOLEAN.equals(((PsiMethod)method).getReturnType())) {
- addInstruction(new PushInstruction(myFactory.getConstFactory().getFalse(), null));
- addInstruction(new SwapInstruction());
- addInstruction(new ConditionalGotoInstruction(getEndOffset(expression), true, null));
+ if (isEqualsCall) {
+ // assume equals argument must be not-null if the result is true
+ // don't assume the call result to be false if arg1==null
+
+ // stack: .., arg1, call-result
+ ConditionalGotoInstruction ifFalse = addInstruction(new ConditionalGotoInstruction(null, true, null));
- addInstruction(new PopInstruction());
- addInstruction(new PushInstruction(myFactory.getConstFactory().getTrue(), null));
-
- expressions[0].accept(this);
addInstruction(new ApplyNotNullInstruction(expression));
+ addInstruction(new PushInstruction(myFactory.getConstFactory().getTrue(), null));
+ addInstruction(new GotoInstruction(getEndOffset(expression)));
+
+ ifFalse.setOffset(myCurrentFlow.getInstructionCount());
+ addInstruction(new PopInstruction());
+ addInstruction(new PushInstruction(myFactory.getConstFactory().getFalse(), null));
}
finishElement(expression);
}
@@ -1414,14 +1432,14 @@
if (contracts.size() > 1) {
addInstruction(new DupInstruction(args.length, contracts.size() - 1));
}
- for (MethodContract contract : contracts) {
- handleContract(expression, contract);
+ for (int i = 0; i < contracts.size(); i++) {
+ handleContract(expression, contracts.get(i), contracts.size() - 1 - i);
}
- pushUnknown(); // goto here if all contracts are false
+ pushUnknownReturnValue(expression); // goto here if all contracts are false
return true;
}
- private void handleContract(PsiMethodCallExpression expression, MethodContract contract) {
+ private void handleContract(PsiMethodCallExpression expression, MethodContract contract, int remainingContracts) {
PsiExpression[] args = expression.getArgumentList().getExpressions();
final ControlFlow.ControlFlowOffset exitPoint = getEndOffset(expression);
@@ -1448,10 +1466,14 @@
continueCheckingContract.setOffset(myCurrentFlow.getInstructionCount());
}
+ for (int j = 0; j < remainingContracts * args.length; j++) {
+ addInstruction(new PopInstruction());
+ }
+
// if contract is true
switch (contract.returnValue) {
case ANY_VALUE:
- pushUnknown();
+ pushUnknownReturnValue(expression);
addInstruction(new GotoInstruction(exitPoint));
break;
case NULL_VALUE:
@@ -1482,6 +1504,17 @@
}
}
+ private void pushUnknownReturnValue(PsiMethodCallExpression expression) {
+ PsiMethod method = expression.resolveMethod();
+ if (method != null) {
+ PsiType type = expression.getType();
+ addInstruction(new PushInstruction(myFactory.createTypeValue(type, DfaPsiUtil.getElementNullability(type, method)), null));
+ }
+ else {
+ pushUnknown();
+ }
+ }
+
private static List<MethodContract> getCallContracts(PsiMethodCallExpression expression) {
PsiMethod resolved = expression.resolveMethod();
if (resolved != null) {
@@ -1516,8 +1549,8 @@
}
}
else if ("junit.framework.Assert".equals(className) || "org.junit.Assert".equals(className) ||
- "junit.framework.TestCase".equals(className) || "org.testng.Assert".equals(className)) {
- boolean testng = "org.testng.Assert".equals(className);
+ "junit.framework.TestCase".equals(className) || "org.testng.Assert".equals(className) || "org.testng.AssertJUnit".equals(className)) {
+ boolean testng = className.startsWith("org.testng.");
if ("fail".equals(methodName)) {
return Collections.singletonList(new MethodContract(getAnyArgConstraints(params), ValueConstraint.THROW_EXCEPTION));
}
@@ -1771,12 +1804,6 @@
@Nullable
private DfaValue getExpressionDfaValue(PsiReferenceExpression expression) {
DfaValue dfaValue = myFactory.createReferenceValue(expression);
- if (dfaValue instanceof DfaVariableValue) {
- DfaVariableValue dfaVariable = (DfaVariableValue)dfaValue;
- if (dfaVariable.getPsiVariable() instanceof PsiField) {
- myFields.add(dfaVariable);
- }
- }
if (dfaValue == null) {
PsiElement resolved = expression.resolve();
if (resolved instanceof PsiField) {
@@ -1822,17 +1849,12 @@
return null;
}
- PsiExpression qualifier = refExpr.getQualifierExpression();
- if (qualifier == null) {
- DfaVariableValue result = myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null);
- if (var instanceof PsiField) {
- myFields.add(result);
- }
- return result;
+ if (DfaValueFactory.isEffectivelyUnqualified(refExpr)) {
+ return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, null);
}
if (!(var instanceof PsiField) || !var.hasModifierProperty(PsiModifier.TRANSIENT) && !var.hasModifierProperty(PsiModifier.VOLATILE)) {
- DfaVariableValue qualifierValue = createChainedVariableValue(qualifier);
+ DfaVariableValue qualifierValue = createChainedVariableValue(refExpr.getQualifierExpression());
if (qualifierValue != null) {
return myFactory.getVarFactory().createVariableValue(var, refExpr.getType(), false, qualifierValue);
}
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 305085c..cc1b2ae 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
@@ -104,6 +104,16 @@
}
@Override
+ public void visitIfStatement(PsiIfStatement statement) {
+ PsiExpression condition = statement.getCondition();
+ if (BranchingInstruction.isBoolConst(condition)) {
+ assert condition != null;
+ LocalQuickFix fix = createSimplifyBooleanExpressionFix(condition, condition.textMatches(PsiKeyword.TRUE));
+ holder.registerProblem(condition, "Condition is always " + condition.getText(), fix);
+ }
+ }
+
+ @Override
public void visitAnnotation(PsiAnnotation annotation) {
if (!ControlFlowAnalyzer.ORG_JETBRAINS_ANNOTATIONS_CONTRACT.equals(annotation.getQualifiedName())) return;
@@ -490,12 +500,13 @@
holder.registerProblem(expr, text);
}
else if (AnnotationUtil.isAnnotatingApplicable(statement)) {
- final String defaultNullable = NullableNotNullManager.getInstance(holder.getProject()).getPresentableDefaultNullable();
- final String text = isNullLiteralExpression(expr)
- ? InspectionsBundle.message("dataflow.message.return.null.from.notnullable", defaultNullable)
- : InspectionsBundle.message("dataflow.message.return.nullable.from.notnullable", defaultNullable);
final NullableNotNullManager manager = NullableNotNullManager.getInstance(expr.getProject());
- holder.registerProblem(expr, text, new AnnotateMethodFix(manager.getDefaultNullable(), ArrayUtil.toStringArray(manager.getNotNulls())){
+ final String defaultNullable = manager.getDefaultNullable();
+ final String presentableNullable = StringUtil.getShortName(defaultNullable);
+ 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;
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
index 6c5c909..d3e2ed8 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowRunner.java
@@ -38,7 +38,6 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.MultiMapBasedOnSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,7 +50,6 @@
private Instruction[] myInstructions;
private final MultiMap<PsiElement, DfaMemoryState> myNestedClosures = new MultiMap<PsiElement, DfaMemoryState>();
- private DfaVariableValue[] myFields;
private final DfaValueFactory myValueFactory;
// Maximum allowed attempts to process instruction. Fail as too complex to process if certain instruction
@@ -113,7 +111,6 @@
int endOffset = flow.getInstructionCount();
myInstructions = flow.getInstructions();
- myFields = flow.getFields();
myNestedClosures.clear();
Set<Instruction> joinInstructions = ContainerUtil.newHashSet();
@@ -144,10 +141,10 @@
queue.offer(new DfaInstructionState(myInstructions[0], initialState));
}
- MultiMapBasedOnSet<BranchingInstruction, DfaMemoryState> processedStates = new MultiMapBasedOnSet<BranchingInstruction, DfaMemoryState>();
- MultiMapBasedOnSet<BranchingInstruction, DfaMemoryState> incomingStates = new MultiMapBasedOnSet<BranchingInstruction, DfaMemoryState>();
+ MultiMap<BranchingInstruction, DfaMemoryState> processedStates = MultiMap.createSet();
+ MultiMap<BranchingInstruction, DfaMemoryState> incomingStates = MultiMap.createSet();
- WorkingTimeMeasurer measurer = new WorkingTimeMeasurer(shouldCheckTimeLimit() ? ourTimeLimit : ourTimeLimit * 42);
+ WorkingTimeMeasurer measurer = new WorkingTimeMeasurer(shouldCheckTimeLimit() ? ourTimeLimit : ourTimeLimit * 5);
int count = 0;
while (!queue.isEmpty()) {
for (DfaInstructionState instructionState : queue.getNextInstructionStates(joinInstructions)) {
@@ -232,12 +229,8 @@
}
else if (instruction instanceof EmptyInstruction) {
PsiElement anchor = ((EmptyInstruction)instruction).getAnchor();
- if (anchor instanceof PsiDeclarationStatement) {
- for (PsiElement element : ((PsiDeclarationStatement)anchor).getDeclaredElements()) {
- if (element instanceof PsiClass) {
- registerNestedClosures(instructionState, (PsiClass)element);
- }
- }
+ if (anchor instanceof PsiClass) {
+ registerNestedClosures(instructionState, (PsiClass)anchor);
}
}
@@ -284,10 +277,6 @@
return myInstructions[index];
}
- public DfaVariableValue[] getFields() {
- return myFields;
- }
-
public MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
return new MultiMap<PsiElement, DfaMemoryState>(myNestedClosures);
}
@@ -326,9 +315,9 @@
return Pair.create(trueSet, falseSet);
}
- private DfaMemoryStateImpl createClosureState(DfaMemoryState memState) {
+ private static DfaMemoryStateImpl createClosureState(DfaMemoryState memState) {
DfaMemoryStateImpl copy = (DfaMemoryStateImpl)memState.createCopy();
- copy.flushFields(getFields());
+ copy.flushFields();
Set<DfaVariableValue> vars = new HashSet<DfaVariableValue>(copy.getVariableStates().keySet());
for (DfaVariableValue value : vars) {
copy.flushDependencies(value);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaInstructionState.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaInstructionState.java
index 22d2a09..ea31206 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaInstructionState.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaInstructionState.java
@@ -28,12 +28,10 @@
import com.intellij.openapi.util.Pair;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
-import java.util.Collections;
-import java.util.List;
-import java.util.PriorityQueue;
-import java.util.Set;
+import java.util.*;
public class DfaInstructionState implements Comparable<DfaInstructionState> {
public static final DfaInstructionState[] EMPTY_ARRAY = new DfaInstructionState[0];
@@ -96,15 +94,16 @@
}
if (memoryStates.size() > 1 && joinInstructions.contains(instruction)) {
- StateMerger merger = new StateMerger();
- while (true) {
- List<DfaMemoryStateImpl> nextStates = merger.mergeByEquality(memoryStates);
- if (nextStates == null) nextStates = merger.mergeByType(memoryStates);
- if (nextStates == null) nextStates = merger.mergeByNullability(memoryStates);
- if (nextStates == null) nextStates = merger.mergeByUnknowns(memoryStates);
- if (nextStates == null) break;
- memoryStates = nextStates;
+ MultiMap<Object, DfaMemoryStateImpl> groups = MultiMap.create();
+ for (DfaMemoryStateImpl memoryState : memoryStates) {
+ groups.putValue(memoryState.getSuperficialKey(), memoryState);
}
+
+ memoryStates = ContainerUtil.newArrayList();
+ for (Map.Entry<Object, Collection<DfaMemoryStateImpl>> entry : groups.entrySet()) {
+ memoryStates.addAll(mergeGroup((List<DfaMemoryStateImpl>)entry.getValue()));
+ }
+
}
return ContainerUtil.map(memoryStates, new Function<DfaMemoryStateImpl, DfaInstructionState>() {
@@ -113,7 +112,21 @@
return new DfaInstructionState(instruction, state);
}
});
+ }
+
+ private static List<DfaMemoryStateImpl> mergeGroup(List<DfaMemoryStateImpl> group) {
+ if (group.size() < 2) {
+ return group;
+ }
+
+ StateMerger merger = new StateMerger();
+ while (true) {
+ List<DfaMemoryStateImpl> nextStates = merger.mergeByFacts(group);
+ if (nextStates == null) nextStates = merger.mergeByNullability(group);
+ if (nextStates == null) nextStates = merger.mergeByUnknowns(group);
+ if (nextStates == null) break;
+ group = nextStates;
+ }
+ return group;
}
-
-
}
\ No newline at end of file
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
index 2676f99..2fb0de1 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryState.java
@@ -44,7 +44,7 @@
boolean applyCondition(DfaValue dfaCond);
- void flushFields(DfaVariableValue[] fields);
+ void flushFields();
void flushVariable(DfaVariableValue variable);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
index ccf45ae..c3f81ec 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaMemoryStateImpl.java
@@ -26,6 +26,7 @@
import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UnorderedPair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.JavaTokenType;
@@ -34,8 +35,6 @@
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
-import gnu.trove.THashMap;
-import gnu.trove.THashSet;
import gnu.trove.TLongArrayList;
import gnu.trove.TLongHashSet;
import org.jetbrains.annotations.NotNull;
@@ -50,17 +49,17 @@
private final List<EqClass> myEqClasses;
private final Stack<DfaValue> myStack;
private final TLongHashSet myDistinctClasses;
- private final Map<DfaVariableValue,DfaVariableState> myVariableStates;
+ private final LinkedHashMap<DfaVariableValue,DfaVariableState> myVariableStates;
private final Map<DfaVariableValue,DfaVariableState> myDefaultVariableStates;
- private final Set<DfaVariableValue> myUnknownVariables;
+ private final LinkedHashSet<DfaVariableValue> myUnknownVariables;
private boolean myEphemeral;
public DfaMemoryStateImpl(final DfaValueFactory factory) {
myFactory = factory;
myDefaultVariableStates = ContainerUtil.newTroveMap();
myEqClasses = ContainerUtil.newArrayList();
- myUnknownVariables = ContainerUtil.newTroveSet();
- myVariableStates = ContainerUtil.newTroveMap();
+ myUnknownVariables = ContainerUtil.newLinkedHashSet();
+ myVariableStates = ContainerUtil.newLinkedHashMap();
myDistinctClasses = new TLongHashSet();
myStack = new Stack<DfaValue>();
}
@@ -72,10 +71,10 @@
myStack = new Stack<DfaValue>(toCopy.myStack);
myDistinctClasses = new TLongHashSet(toCopy.myDistinctClasses.toArray());
- myUnknownVariables = new THashSet<DfaVariableValue>(toCopy.myUnknownVariables);
+ myUnknownVariables = ContainerUtil.newLinkedHashSet(toCopy.myUnknownVariables);
myEqClasses = ContainerUtil.newArrayList(toCopy.myEqClasses);
- myVariableStates = new THashMap<DfaVariableValue, DfaVariableState>(toCopy.myVariableStates);
+ myVariableStates = ContainerUtil.newLinkedHashMap(toCopy.myVariableStates);
myCachedDistinctClassPairs = toCopy.myCachedDistinctClassPairs;
myCachedNonTrivialEqClasses = toCopy.myCachedNonTrivialEqClasses;
@@ -101,7 +100,11 @@
return myUnknownVariables.equals(that.myUnknownVariables);
}
- boolean equalsSuperficially(DfaMemoryStateImpl other) {
+ Object getSuperficialKey() {
+ return Pair.create(myEphemeral, myStack);
+ }
+
+ private boolean equalsSuperficially(DfaMemoryStateImpl other) {
return myEphemeral == other.myEphemeral && myStack.equals(other.myStack);
}
@@ -113,22 +116,22 @@
return myVariableStates.equals(that.myVariableStates);
}
- private Set<UnorderedPair<EqClass>> myCachedDistinctClassPairs;
- Set<UnorderedPair<EqClass>> getDistinctClassPairs() {
+ private LinkedHashSet<UnorderedPair<EqClass>> myCachedDistinctClassPairs;
+ LinkedHashSet<UnorderedPair<EqClass>> getDistinctClassPairs() {
if (myCachedDistinctClassPairs != null) return myCachedDistinctClassPairs;
- Set<UnorderedPair<EqClass>> result = ContainerUtil.newHashSet();
+ LinkedHashSet<UnorderedPair<EqClass>> result = ContainerUtil.newLinkedHashSet();
for (long encodedPair : myDistinctClasses.toArray()) {
result.add(new UnorderedPair<EqClass>(myEqClasses.get(low(encodedPair)), myEqClasses.get(high(encodedPair))));
}
return myCachedDistinctClassPairs = result;
}
- private Set<EqClass> myCachedNonTrivialEqClasses;
- Set<EqClass> getNonTrivialEqClasses() {
+ private LinkedHashSet<EqClass> myCachedNonTrivialEqClasses;
+ LinkedHashSet<EqClass> getNonTrivialEqClasses() {
if (myCachedNonTrivialEqClasses != null) return myCachedNonTrivialEqClasses;
-
- Set<EqClass> result = ContainerUtil.newHashSet();
+
+ LinkedHashSet<EqClass> result = ContainerUtil.newLinkedHashSet();
for (EqClass eqClass : myEqClasses) {
if (eqClass != null && eqClass.size() > 1) {
result.add(eqClass);
@@ -265,6 +268,11 @@
return myEqClasses.size() - 1;
}
+ boolean areEquivalent(DfaValue val1, DfaValue val2) {
+ int index = getEqClassIndex(val1);
+ return index >= 0 && index == getEqClassIndex(val2);
+ }
+
@NotNull
private List<DfaValue> getEqClassesFor(@NotNull DfaValue dfaValue) {
int index = getEqClassIndex(dfaValue);
@@ -806,7 +814,7 @@
}
@Override
- public void flushFields(DfaVariableValue[] fields) {
+ public void flushFields() {
for (EqClass aClass : myEqClasses) {
if (aClass != null) {
for (DfaVariableValue value : aClass.getVariables()) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
index c99be10..6056f07 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaUtil.java
@@ -22,19 +22,21 @@
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.MultiValuesMap;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
+import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.FList;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* @author Gregory.Shrago
@@ -138,10 +140,28 @@
for (Map.Entry<DfaVariableValue, DfaVariableState> entry : map.entrySet()) {
ValuableDataFlowRunner.ValuableDfaVariableState state = (ValuableDataFlowRunner.ValuableDfaVariableState)entry.getValue();
DfaVariableValue variableValue = entry.getKey();
- final PsiExpression psiExpression = state.myExpression;
- if (psiExpression != null && variableValue.getQualifier() == null) {
+ final FList<PsiExpression> concatenation = state.myConcatenation;
+ if (!concatenation.isEmpty() && variableValue.getQualifier() == null) {
PsiModifierListOwner element = variableValue.getPsiVariable();
if (element instanceof PsiVariable) {
+ PsiExpression psiExpression;
+ if (concatenation.size() == 1) {
+ psiExpression = concatenation.getHead();
+ } else {
+ String text = StringUtil.join(ContainerUtil.reverse(new ArrayList<PsiExpression>(concatenation)), new Function<PsiExpression, String>() {
+ @Override
+ public String fun(PsiExpression expression) {
+ return expression.getText();
+ }
+ }, "+");
+ try {
+ psiExpression = JavaPsiFacade.getElementFactory(element.getProject()).createExpressionFromText(text, concatenation.getHead());
+ }
+ catch (IncorrectOperationException e) {
+ psiExpression = concatenation.getHead();
+ }
+ }
+
myValues.put((PsiVariable)element, psiExpression);
}
}
@@ -177,25 +197,17 @@
final IElementType type = parent instanceof PsiAssignmentExpression
? ((PsiAssignmentExpression)parent).getOperationTokenType() : JavaTokenType.EQ;
// store current value - to use in case of '+='
- final PsiExpression prevValue = ((ValuableDataFlowRunner.ValuableDfaVariableState)memState.getVariableState(var)).myExpression;
+ final FList<PsiExpression> prevValue = ((ValuableDataFlowRunner.ValuableDfaVariableState)memState.getVariableState(var)).myConcatenation;
memState.setVarValue(var, dfaSource);
// state may have been changed so re-retrieve it
final ValuableDataFlowRunner.ValuableDfaVariableState curState = (ValuableDataFlowRunner.ValuableDfaVariableState)memState.getVariableState(var);
- final PsiExpression curValue = curState.myExpression;
- final PsiExpression nextValue;
- if (type == JavaTokenType.PLUSEQ && prevValue != null) {
- PsiExpression tmpExpression;
- try {
- tmpExpression = JavaPsiFacade.getElementFactory(myContext.getProject())
- .createExpressionFromText(prevValue.getText() + "+" + rightValue.getText(), rightValue);
- }
- catch (Exception e) {
- tmpExpression = curValue == null ? rightValue : curValue;
- }
- nextValue = tmpExpression;
+ final FList<PsiExpression> curValue = curState.myConcatenation;
+ final FList<PsiExpression> nextValue;
+ if (type == JavaTokenType.PLUSEQ && !prevValue.isEmpty()) {
+ nextValue = prevValue.prepend(rightValue);
}
else {
- nextValue = curValue == null ? rightValue : curValue;
+ nextValue = curValue.isEmpty() ? curValue.prepend(rightValue) : curValue;
}
memState.setVariableState(var, curState.withExpression(nextValue));
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
index 4894eea..4f9c271 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaVariableState.java
@@ -172,4 +172,13 @@
public DfaValue getValue() {
return null;
}
+
+ public Set<DfaPsiType> getInstanceofValues() {
+ return myInstanceofValues;
+ }
+
+ public Set<DfaPsiType> getNotInstanceofValues() {
+ return myNotInstanceofValues;
+ }
+
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InstructionVisitor.java
index 0b9f0b0..a714f1e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InstructionVisitor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/InstructionVisitor.java
@@ -125,7 +125,7 @@
if (variable != null) {
memState.flushVariable(variable);
} else {
- memState.flushFields(runner.getFields());
+ memState.flushFields();
}
return nextInstruction(instruction, runner, memState);
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
index fa21da0..0217b81 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StandardInstructionVisitor.java
@@ -25,7 +25,6 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FactoryMap;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.MultiMapBasedOnSet;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -39,7 +38,7 @@
private static final Object ANY_VALUE = new Object();
private final Set<BinopInstruction> myReachable = new THashSet<BinopInstruction>();
private final Set<BinopInstruction> myCanBeNullInInstanceof = new THashSet<BinopInstruction>();
- private final MultiMap<PushInstruction, Object> myPossibleVariableValues = new MultiMapBasedOnSet<PushInstruction, Object>();
+ private final MultiMap<PushInstruction, Object> myPossibleVariableValues = MultiMap.createSet();
private final Set<PsiElement> myNotToReportReachability = new THashSet<PsiElement>();
private final Set<InstanceofInstruction> myUsefulInstanceofs = new THashSet<InstanceofInstruction>();
@SuppressWarnings("MismatchedQueryAndUpdateOfCollection")
@@ -237,7 +236,7 @@
finally {
memState.push(getMethodResultValue(instruction, qualifier, runner.getFactory()));
if (instruction.shouldFlushFields()) {
- memState.flushFields(runner.getFields());
+ memState.flushFields();
}
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
index aa69d05..65899e9 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/StateMerger.java
@@ -15,68 +15,119 @@
*/
package com.intellij.codeInspection.dataFlow;
-import com.intellij.codeInspection.dataFlow.value.DfaConstValue;
-import com.intellij.codeInspection.dataFlow.value.DfaPsiType;
-import com.intellij.codeInspection.dataFlow.value.DfaValue;
-import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
+import com.intellij.codeInspection.dataFlow.value.*;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.UnorderedPair;
+import com.intellij.psi.JavaTokenType;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nullable;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* @author peter
*/
class StateMerger {
- private final Map<DfaMemoryStateImpl, Map<DfaVariableValue, DfaConstValue>> myVarValues = ContainerUtil.newIdentityHashMap();
- private final Map<DfaMemoryStateImpl, List<UnorderedPair<DfaValue>>> myEqPairs = ContainerUtil.newIdentityHashMap();
+ private final Map<DfaMemoryStateImpl, LinkedHashSet<Fact>> myFacts = ContainerUtil.newIdentityHashMap();
private final Map<DfaMemoryState, Map<DfaVariableValue, DfaMemoryStateImpl>> myCopyCache = ContainerUtil.newIdentityHashMap();
@Nullable
- public List<DfaMemoryStateImpl> mergeByEquality(List<DfaMemoryStateImpl> states) {
- final MultiMap<UnorderedPair<DfaValue>,DfaMemoryStateImpl> statesByEq = new MultiMap<UnorderedPair<DfaValue>, DfaMemoryStateImpl>();
+ List<DfaMemoryStateImpl> mergeByFacts(List<DfaMemoryStateImpl> states) {
+ MultiMap<Fact, DfaMemoryStateImpl> statesByFact = MultiMap.createLinked();
for (DfaMemoryStateImpl state : states) {
ProgressManager.checkCanceled();
- for (UnorderedPair<DfaValue> pair : getEqPairs(state)) {
- statesByEq.putValue(pair, state);
+ for (Fact fact : getFacts(state)) {
+ statesByFact.putValue(fact, state);
}
}
- for (final DfaMemoryStateImpl state : states) {
+ for (final Fact fact : statesByFact.keySet()) {
+ if (statesByFact.get(fact).size() == states.size() || fact.myPositive) continue;
+
+ Collection<DfaMemoryStateImpl> statesWithNegations = statesByFact.get(fact.getPositiveCounterpart());
+ if (statesWithNegations.isEmpty()) continue;
+
ProgressManager.checkCanceled();
- MultiMap<DfaVariableValue, DfaValue> distincts = getDistinctsMap(state);
- for (DfaVariableValue var : distincts.keySet()) {
- Map<DfaValue, Collection<DfaMemoryStateImpl>> statesByValue = getCompatibleStatesByValue(state, var, distincts, statesByEq);
- if (statesByValue == null) {
- continue;
- }
-
- final THashSet<DfaMemoryStateImpl> complementaryStates = findComplementaryStates(var, statesByValue, state);
- if (complementaryStates == null) {
- continue;
- }
-
- DfaMemoryStateImpl copy = copyWithoutVar(state, var).createCopy();
-
- complementaryStates.add(state);
- mergeNullableState(var, copy, complementaryStates);
- mergeUnknowns(copy, complementaryStates);
- return getMergeResult(states, complementaryStates, copy);
+
+ MultiMap<Set<Fact>, DfaMemoryStateImpl> statesByUnrelatedFacts = MultiMap.createLinked();
+ for (DfaMemoryStateImpl state : ContainerUtil.concat(statesByFact.get(fact), statesWithNegations)) {
+ statesByUnrelatedFacts.putValue(getUnrelatedFacts(fact, state), state);
}
+ Set<DfaMemoryStateImpl> removedStates = ContainerUtil.newIdentityTroveSet();
+ List<DfaMemoryStateImpl> result = ContainerUtil.newArrayList();
+ for (Set<Fact> key : statesByUnrelatedFacts.keySet()) {
+ Collection<DfaMemoryStateImpl> group = statesByUnrelatedFacts.get(key);
+ if (group.size() > 1) {
+ DfaMemoryStateImpl copy = group.iterator().next().createCopy();
+ fact.removeFromState(copy);
+ if (fact.myType == FactType.equality) {
+ restoreOtherInequalities(fact, group, copy);
+ }
+ mergeUnknowns(copy, group);
+
+ removedStates.addAll(group);
+ result.add(copy);
+ }
+ }
+
+ if (!result.isEmpty()) {
+ for (DfaMemoryStateImpl state : states) {
+ if (!removedStates.contains(state)) {
+ result.add(state);
+ }
+ }
+ return result;
+ }
}
return null;
}
+ private LinkedHashSet<Fact> getUnrelatedFacts(final Fact fact, DfaMemoryStateImpl state) {
+ return new LinkedHashSet<Fact>(ContainerUtil.filter(getFacts(state), new Condition<Fact>() {
+ @Override
+ public boolean value(Fact another) {
+ return !fact.invalidatesFact(another);
+ }
+ }));
+ }
+
+ private void restoreOtherInequalities(Fact removedFact, Collection<DfaMemoryStateImpl> mergedGroup, DfaMemoryStateImpl state) {
+ Set<DfaConstValue> inequalitiesToRestore = null;
+ for (DfaMemoryStateImpl member : mergedGroup) {
+ LinkedHashSet<Fact> memberFacts = getFacts(member);
+ if (memberFacts.contains(removedFact)) {
+ Set<DfaConstValue> otherInequalities = getOtherInequalities(removedFact, memberFacts, member);
+ if (inequalitiesToRestore == null) {
+ inequalitiesToRestore = otherInequalities;
+ } else {
+ inequalitiesToRestore.retainAll(otherInequalities);
+ }
+ }
+ }
+ if (inequalitiesToRestore != null) {
+ DfaRelationValue.Factory relationFactory = state.getFactory().getRelationFactory();
+ for (DfaConstValue toRestore : inequalitiesToRestore) {
+ state.applyCondition(relationFactory.createRelation(removedFact.myVar, toRestore, JavaTokenType.EQEQ, true));
+ }
+ }
+ }
+
+ private static Set<DfaConstValue> getOtherInequalities(Fact removedFact, LinkedHashSet<Fact> memberFacts, DfaMemoryStateImpl state) {
+ Set<DfaConstValue> otherInequalities = ContainerUtil.newLinkedHashSet();
+ for (Fact candidate : memberFacts) {
+ if (candidate.myType == FactType.equality && !candidate.myPositive && candidate.myVar == removedFact.myVar &&
+ !state.areEquivalent((DfaValue)candidate.myArg, (DfaValue)removedFact.myArg) &&
+ candidate.myArg instanceof DfaConstValue) {
+ otherInequalities.add((DfaConstValue)candidate.myArg);
+ }
+ }
+ return otherInequalities;
+ }
+
private static void mergeUnknowns(DfaMemoryStateImpl mergedState, Collection<DfaMemoryStateImpl> complementaryStates) {
for (DfaMemoryStateImpl removedState : complementaryStates) {
for (DfaVariableValue unknownVar : removedState.getUnknownVariables()) {
@@ -84,15 +135,6 @@
}
}
}
- private static void mergeNullableState(DfaVariableValue var,
- DfaMemoryStateImpl mergedState,
- Collection<DfaMemoryStateImpl> complementaryStates) {
- for (DfaMemoryStateImpl removedState : complementaryStates) {
- if (removedState.getVariableState(var).isNullable()) {
- mergedState.setVariableState(var, mergedState.getVariableState(var).withNullability(Nullness.NULLABLE));
- }
- }
- }
private static List<DfaMemoryStateImpl> getMergeResult(List<DfaMemoryStateImpl> statesBeforeMerge,
final THashSet<DfaMemoryStateImpl> mergedStates,
@@ -125,7 +167,7 @@
List<DfaMemoryStateImpl> complementary = ContainerUtil.filter(similarStates, new Condition<DfaMemoryStateImpl>() {
@Override
public boolean value(DfaMemoryStateImpl state2) {
- return state1.equalsSuperficially(state2) && state1.equalsByRelations(state2) && state1.equalsByVariableStates(state2);
+ return state1.equalsByRelations(state2) && state1.equalsByVariableStates(state2);
}
});
if (complementary.size() > 1) {
@@ -162,8 +204,7 @@
List<DfaMemoryStateImpl> complementary = ContainerUtil.filter(similarStates, new Condition<DfaMemoryStateImpl>() {
@Override
public boolean value(DfaMemoryStateImpl state2) {
- return state1.equalsSuperficially(state2) &&
- state1.equalsByRelations(state2) &&
+ return state1.equalsByRelations(state2) &&
areEquivalentModuloVar(state1, state2, var) &&
areVarStatesEqualModuloNullability(state1, state2, var);
}
@@ -182,64 +223,12 @@
return null;
}
- @Nullable
- public List<DfaMemoryStateImpl> mergeByType(List<DfaMemoryStateImpl> states) {
- MultiMap<Pair<DfaVariableValue, DfaPsiType>,DfaMemoryStateImpl> byInstanceof = new MultiMap<Pair<DfaVariableValue, DfaPsiType>, DfaMemoryStateImpl>();
- for (final DfaMemoryStateImpl state : states) {
- ProgressManager.checkCanceled();
- for (DfaVariableValue value : state.getChangedVariables()) {
- for (DfaPsiType instanceofValue : state.getVariableState(value).myInstanceofValues) {
- byInstanceof.putValue(Pair.create(value, instanceofValue), state);
- }
- }
- }
-
- for (final DfaMemoryStateImpl state : states) {
- ProgressManager.checkCanceled();
-
- for (final DfaVariableValue var : state.getChangedVariables()) {
- for (final DfaPsiType notInstanceof : state.getVariableState(var).myNotInstanceofValues) {
- final DfaVariableState varStateWithoutType = getVarStateWithoutType(state, var, notInstanceof);
- List<DfaMemoryStateImpl> complementaryStates = ContainerUtil.filter(
- byInstanceof.get(Pair.create(var, notInstanceof)),
- new Condition<DfaMemoryStateImpl>() {
- @Override
- public boolean value(DfaMemoryStateImpl another) {
- return seemCompatible(state, another, var) &&
- another.getVariableState(var).myInstanceofValues.contains(notInstanceof) &&
- varStateWithoutType.equals(getVarStateWithoutType(another, var, notInstanceof)) &&
- areEquivalentModuloVar(another, state, var) &&
- !(state.isNull(var) && another.isNotNull(var));
- }
- });
- if (complementaryStates.isEmpty()) {
- continue;
- }
-
- DfaMemoryStateImpl copy = state.createCopy();
- copy.setVariableState(var, varStateWithoutType);
-
- complementaryStates.add(state);
- mergeNullableState(var, copy, complementaryStates);
- mergeUnknowns(copy, complementaryStates);
- return getMergeResult(states, ContainerUtil.newIdentityTroveSet(complementaryStates), copy);
- }
- }
-
- }
- return null;
- }
-
private boolean areEquivalentModuloVar(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
DfaMemoryStateImpl copy1 = copyWithoutVar(state1, var);
DfaMemoryStateImpl copy2 = copyWithoutVar(state2, var);
return copy2.equalsByRelations(copy1) && copy2.equalsByVariableStates(copy1);
}
- private static DfaVariableState getVarStateWithoutType(DfaMemoryStateImpl s, DfaVariableValue var, DfaPsiType type) {
- return s.getVariableState(var).withoutType(type).withNullability(Nullness.UNKNOWN);
- }
-
private DfaMemoryStateImpl copyWithoutVar(DfaMemoryStateImpl state, DfaVariableValue var) {
Map<DfaVariableValue, DfaMemoryStateImpl> map = myCopyCache.get(state);
if (map == null) {
@@ -254,132 +243,140 @@
return copy;
}
- @Nullable
- private THashSet<DfaMemoryStateImpl> findComplementaryStates(DfaVariableValue var,
- Map<DfaValue, Collection<DfaMemoryStateImpl>> statesByValue,
- DfaMemoryStateImpl state) {
- THashSet<DfaMemoryStateImpl> removedStates = ContainerUtil.newIdentityTroveSet();
-
- eachValue:
- for (DfaValue value : statesByValue.keySet()) {
- for (DfaMemoryStateImpl originalState : statesByValue.get(value)) {
- if (areEquivalentModuloVar(originalState, state, var)) {
- removedStates.add(originalState);
- continue eachValue;
- }
- }
- return null;
- }
- return removedStates;
- }
-
- @Nullable
- private Map<DfaValue, Collection<DfaMemoryStateImpl>> getCompatibleStatesByValue(final DfaMemoryStateImpl state,
- final DfaVariableValue var,
- MultiMap<DfaVariableValue, DfaValue> distincts,
- MultiMap<UnorderedPair<DfaValue>,DfaMemoryStateImpl> statesByEq) {
- Map<DfaValue, Collection<DfaMemoryStateImpl>> statesByValue = ContainerUtil.newHashMap();
- for (DfaValue value : distincts.get(var)) {
- List<DfaMemoryStateImpl> compatible = ContainerUtil.filter(statesByEq.get(createPair(var, value)), new Condition<DfaMemoryStateImpl>() {
- @Override
- public boolean value(DfaMemoryStateImpl state2) {
- return seemCompatible(state, state2, var) &&
- areVarStatesEqualModuloNullability(state, state2, var);
- }
- });
- if (compatible.isEmpty()) {
- return null;
- }
- statesByValue.put(value, compatible);
- }
- return statesByValue;
- }
-
private static boolean areVarStatesEqualModuloNullability(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
return state1.getVariableState(var).withNullability(Nullness.UNKNOWN).equals(state2.getVariableState(var).withNullability(Nullness.UNKNOWN));
}
- private boolean seemCompatible(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue differentVar) {
- if (!state1.equalsSuperficially(state2)) {
- return false;
+ private LinkedHashSet<Fact> getFacts(DfaMemoryStateImpl state) {
+ LinkedHashSet<Fact> result = myFacts.get(state);
+ if (result != null) {
+ return result;
}
- Map<DfaVariableValue, DfaConstValue> varValues1 = getVarValues(state1);
- Map<DfaVariableValue, DfaConstValue> varValues2 = getVarValues(state2);
- for (DfaVariableValue var : varValues1.keySet()) {
- if (var != differentVar && varValues1.get(var) != varValues2.get(var)) {
- return false;
- }
- }
- for (DfaVariableValue var : varValues2.keySet()) {
- if (var != differentVar && !varValues1.containsKey(var)) {
- return false;
- }
- }
- return true;
- }
-
- private Map<DfaVariableValue, DfaConstValue> getVarValues(DfaMemoryStateImpl state) {
- Map<DfaVariableValue, DfaConstValue> map = myVarValues.get(state);
- if (map == null) {
- map = ContainerUtil.newHashMap();
- for (UnorderedPair<DfaValue> pair : getEqPairs(state)) {
- if (pair.first instanceof DfaVariableValue && pair.second instanceof DfaConstValue) {
- map.put((DfaVariableValue)pair.first, (DfaConstValue)pair.second);
+ result = ContainerUtil.newLinkedHashSet();
+ for (EqClass eqClass : state.getNonTrivialEqClasses()) {
+ DfaConstValue constant = eqClass.findConstant(true);
+ List<DfaVariableValue> vars = eqClass.getVariables();
+ for (DfaVariableValue var : vars) {
+ if (constant != null) {
+ result.add(Fact.createEqualityFact(var, constant, true));
+ }
+ for (DfaVariableValue eqVar : vars) {
+ if (var != eqVar) {
+ result.add(Fact.createEqualityFact(var, eqVar, true));
+ }
}
}
- myVarValues.put(state, map);
-
}
- return map;
- }
-
- private static MultiMap<DfaVariableValue, DfaValue> getDistinctsMap(DfaMemoryStateImpl state) {
- MultiMap<DfaVariableValue, DfaValue> distincts = new MultiMap<DfaVariableValue, DfaValue>();
+
for (UnorderedPair<EqClass> classPair : state.getDistinctClassPairs()) {
- for (DfaValue value1 : classPair.first.getMemberValues()) {
- value1 = DfaMemoryStateImpl.unwrap(value1);
- for (DfaValue value2 : classPair.second.getMemberValues()) {
- value2 = DfaMemoryStateImpl.unwrap(value2);
- if (value1 instanceof DfaVariableValue) {
- if (value2 instanceof DfaVariableValue || value2 instanceof DfaConstValue) {
- distincts.putValue((DfaVariableValue)value1, value2);
- }
- }
- if (value2 instanceof DfaVariableValue) {
- if (value1 instanceof DfaVariableValue || value1 instanceof DfaConstValue) {
- distincts.putValue((DfaVariableValue)value2, value1);
- }
- }
- }
- }
- }
- return distincts;
- }
+ List<DfaVariableValue> vars1 = classPair.first.getVariables();
+ List<DfaVariableValue> vars2 = classPair.second.getVariables();
+
+ LinkedHashSet<DfaValue> firstSet = new LinkedHashSet<DfaValue>(vars1);
+ ContainerUtil.addIfNotNull(firstSet, classPair.first.findConstant(true));
- private List<UnorderedPair<DfaValue>> getEqPairs(DfaMemoryStateImpl state) {
- List<UnorderedPair<DfaValue>> result = myEqPairs.get(state);
- if (result == null) {
- Set<UnorderedPair<DfaValue>> eqPairs = ContainerUtil.newHashSet();
- for (EqClass eqClass : state.getNonTrivialEqClasses()) {
- DfaConstValue constant = eqClass.findConstant(true);
- List<DfaVariableValue> vars = eqClass.getVariables();
- for (int i = 0; i < vars.size(); i++) {
- DfaVariableValue var = vars.get(i);
- if (constant != null) {
- eqPairs.add(createPair(var, constant));
- }
- for (int j = i + 1; j < vars.size(); j++) {
- eqPairs.add(createPair(var, vars.get(j)));
- }
+ LinkedHashSet<DfaValue> secondSet = new LinkedHashSet<DfaValue>(vars2);
+ ContainerUtil.addIfNotNull(secondSet, classPair.second.findConstant(true));
+
+ for (DfaVariableValue var : vars1) {
+ for (DfaValue value : secondSet) {
+ result.add(new Fact(FactType.equality, var, false, value));
}
}
- myEqPairs.put(state, result = ContainerUtil.newArrayList(eqPairs));
+ for (DfaVariableValue var : vars2) {
+ for (DfaValue value : firstSet) {
+ result.add(new Fact(FactType.equality, var, false, value));
+ }
+ }
}
+
+ Map<DfaVariableValue, DfaVariableState> states = state.getVariableStates();
+ for (DfaVariableValue var : states.keySet()) {
+ DfaVariableState variableState = states.get(var);
+ for (DfaPsiType type : variableState.getInstanceofValues()) {
+ result.add(new Fact(FactType.instanceOf, var, true, type));
+ }
+ for (DfaPsiType type : variableState.getNotInstanceofValues()) {
+ result.add(new Fact(FactType.instanceOf, var, false, type));
+ }
+ }
+
+ myFacts.put(state, result);
return result;
}
- private static UnorderedPair<DfaValue> createPair(DfaVariableValue var, DfaValue val) {
- return new UnorderedPair<DfaValue>(var, val);
+ private enum FactType { equality, instanceOf }
+
+ private static class Fact {
+ final FactType myType;
+ final DfaVariableValue myVar;
+ final boolean myPositive;
+ final Object myArg; // DfaValue for equality fact, DfaPsiType for instanceOf fact
+
+ private Fact(FactType type, DfaVariableValue var, boolean positive, Object arg) {
+ myType = type;
+ myVar = var;
+ myPositive = positive;
+ myArg = arg;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof Fact)) return false;
+
+ Fact fact = (Fact)o;
+
+ if (myPositive != fact.myPositive) return false;
+ if (!myArg.equals(fact.myArg)) return false;
+ if (myType != fact.myType) return false;
+ if (!myVar.equals(fact.myVar)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myType.hashCode();
+ result = 31 * result + myVar.hashCode();
+ result = 31 * result + (myPositive ? 1 : 0);
+ result = 31 * result + myArg.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return myVar + " " + (myPositive ? "" : "!") + myType + " " + myArg;
+ }
+
+ static Fact createEqualityFact(DfaVariableValue var, DfaValue val, boolean equal) {
+ if (val instanceof DfaVariableValue && val.getID() < var.getID()) {
+ return new Fact(FactType.equality, (DfaVariableValue)val, equal, var);
+ }
+ return new Fact(FactType.equality, var, equal, val);
+ }
+
+ Fact getPositiveCounterpart() {
+ return new Fact(myType, myVar, true, myArg);
+ }
+
+ boolean invalidatesFact(Fact another) {
+ if (another.myType != myType) return false;
+ if (myType == FactType.equality) {
+ return myVar == another.myVar || myVar == another.myArg;
+ }
+ return myVar == another.myVar && myArg == another.myArg;
+ }
+
+ void removeFromState(DfaMemoryStateImpl state) {
+ DfaVariableState varState = state.getVariableState(myVar);
+ if (myType == FactType.equality) {
+ state.flushVariable(myVar);
+ state.setVariableState(myVar, varState);
+ } else {
+ state.setVariableState(myVar, varState.withoutType((DfaPsiType)myArg));
+ }
+ }
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
index efbbbc4..21a6160 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/ValuableDataFlowRunner.java
@@ -22,6 +22,8 @@
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
+import com.intellij.util.containers.FList;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Set;
@@ -63,36 +65,36 @@
static class ValuableDfaVariableState extends DfaVariableState {
final DfaValue myValue;
- final PsiExpression myExpression;
+ @NotNull final FList<PsiExpression> myConcatenation;
private ValuableDfaVariableState(final DfaVariableValue psiVariable) {
super(psiVariable);
myValue = null;
- myExpression = null;
+ myConcatenation = FList.emptyList();
}
private ValuableDfaVariableState(Set<DfaPsiType> instanceofValues,
Set<DfaPsiType> notInstanceofValues,
- Nullness nullability, DfaValue value, PsiExpression expression) {
+ Nullness nullability, DfaValue value, @NotNull FList<PsiExpression> concatenation) {
super(instanceofValues, notInstanceofValues, nullability);
myValue = value;
- myExpression = expression;
+ myConcatenation = concatenation;
}
@Override
protected DfaVariableState createCopy(Set<DfaPsiType> instanceofValues, Set<DfaPsiType> notInstanceofValues, Nullness nullability) {
- return new ValuableDfaVariableState(instanceofValues, notInstanceofValues, nullability, myValue, myExpression);
+ return new ValuableDfaVariableState(instanceofValues, notInstanceofValues, nullability, myValue, myConcatenation);
}
@Override
public DfaVariableState withValue(@Nullable final DfaValue value) {
if (value == myValue) return this;
- return new ValuableDfaVariableState(myInstanceofValues, myNotInstanceofValues, myNullability, value, myExpression);
+ return new ValuableDfaVariableState(myInstanceofValues, myNotInstanceofValues, myNullability, value, myConcatenation);
}
- public ValuableDfaVariableState withExpression(@Nullable final PsiExpression expression) {
- if (expression == myExpression) return this;
- return new ValuableDfaVariableState(myInstanceofValues, myNotInstanceofValues, myNullability, myValue, expression);
+ public ValuableDfaVariableState withExpression(@NotNull final FList<PsiExpression> concatenation) {
+ if (concatenation == myConcatenation) return this;
+ return new ValuableDfaVariableState(myInstanceofValues, myNotInstanceofValues, myNullability, myValue, concatenation);
}
@Override
@@ -108,7 +110,7 @@
ValuableDfaVariableState state = (ValuableDfaVariableState)o;
- if (myExpression != null ? !myExpression.equals(state.myExpression) : state.myExpression != null) return false;
+ if (!myConcatenation.equals(state.myConcatenation)) return false;
if (myValue != null ? !myValue.equals(state.myValue) : state.myValue != null) return false;
return true;
@@ -118,7 +120,7 @@
public int hashCode() {
int result = super.hashCode();
result = 31 * result + (myValue != null ? myValue.hashCode() : 0);
- result = 31 * result + (myExpression != null ? myExpression.hashCode() : 0);
+ result = 31 * result + myConcatenation.hashCode();
return result;
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/BranchingInstruction.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/BranchingInstruction.java
index 0f83d84..3e152e5 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/BranchingInstruction.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/instructions/BranchingInstruction.java
@@ -66,7 +66,7 @@
return !isConstTrue && myIsTrueReachable != myIsFalseReachable;
}
- private static boolean isBoolConst(PsiElement condition) {
+ public static boolean isBoolConst(PsiElement condition) {
if (!(condition instanceof PsiLiteralExpression)) return false;
@NonNls String text = condition.getText();
return "true".equals(text) || "false".equals(text);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
index 51a3111..bbeb09e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationInspection.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.
@@ -435,7 +435,7 @@
myPhase = 1;
}
- public boolean isEntryPoint(final RefElement owner) {
+ public boolean isEntryPoint(@NotNull RefElement owner) {
final PsiElement element = owner.getElement();
if (RefUtil.isImplicitUsage(element)) return true;
if (element instanceof PsiModifierListOwner) {
@@ -444,9 +444,11 @@
return true;
}
}
- for (EntryPoint extension : myExtensions) {
- if (extension.isEntryPoint(owner, element)) {
- return true;
+ if (element != null) {
+ for (EntryPoint extension : myExtensions) {
+ if (extension.isEntryPoint(owner, element)) {
+ return true;
+ }
}
}
return false;
@@ -482,7 +484,7 @@
}
if (element instanceof PsiModifierListOwner) {
final EntryPointsManager entryPointsManager = EntryPointsManager.getInstance(project);
- if (entryPointsManager.isEntryPoint((PsiModifierListOwner)element)) return true;
+ if (entryPointsManager.isEntryPoint(element)) return true;
//if (AnnotationUtil
// .checkAnnotatedUsingPatterns((PsiModifierListOwner)element, entryPointsManager.ADDITIONAL_ANNOTATIONS) ||
// AnnotationUtil
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java
index 90fe1c0..fbe379b 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/Java15APIUsageInspectionBase.java
@@ -69,6 +69,7 @@
ourPresentableShortMessage.put(LanguageLevel.JDK_1_4, "1.5");
ourPresentableShortMessage.put(LanguageLevel.JDK_1_5, "1.6");
ourPresentableShortMessage.put(LanguageLevel.JDK_1_6, "1.7");
+ ourPresentableShortMessage.put(LanguageLevel.JDK_1_7, "1.8");
loadForbiddenApi("ignore16List.txt", ourIgnored16ClassesAPI);
}
@@ -85,8 +86,8 @@
private static Set<String> getForbiddenApi(@NotNull LanguageLevel languageLevel) {
if (!ourPresentableShortMessage.containsKey(languageLevel)) return null;
Reference<Set<String>> ref = ourForbiddenAPI.get(languageLevel);
- Set<String> result;
- if (ref == null || (result = ref.get()) == null) {
+ Set<String> result = SoftReference.dereference(ref);
+ if (result == null) {
result = new THashSet<String>(1000);
loadForbiddenApi("api" + getShortName(languageLevel) + ".txt", result);
ourForbiddenAPI.put(languageLevel, new SoftReference<Set<String>>(result));
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/api1.8.txt b/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/api1.8.txt
new file mode 100644
index 0000000..c2fbfdf
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/java15api/api1.8.txt
@@ -0,0 +1,861 @@
+com.sun.source.tree.MethodTree#getReceiverParameter()
+com.sun.source.tree.AnnotatedTypeTree
+com.sun.source.tree.TypeParameterTree#getAnnotations()
+com.sun.source.tree.MemberReferenceTree
+com.sun.source.tree.IntersectionTypeTree
+com.sun.source.util.Plugin
+com.sun.source.util.DocTrees
+com.sun.source.util.JavacTask#instance(ProcessingEnvironment;)
+com.sun.source.util.JavacTask#addTaskListener(TaskListener;)
+com.sun.source.util.JavacTask#removeTaskListener(TaskListener;)
+com.sun.source.util.DocTreePath
+com.sun.source.util.DocTreeScanner
+com.sun.source.util.DocSourcePositions
+com.sun.source.util.DocTreePathScanner
+com.sun.source.util.SimpleDocTreeVisitor
+com.sun.source.doctree.DocTree
+com.sun.source.doctree.SeeTree
+com.sun.source.doctree.LinkTree
+com.sun.source.doctree.TextTree
+com.sun.source.doctree.ParamTree
+com.sun.source.doctree.SinceTree
+com.sun.source.doctree.ValueTree
+com.sun.source.doctree.AuthorTree
+com.sun.source.doctree.EntityTree
+com.sun.source.doctree.ReturnTree
+com.sun.source.doctree.SerialTree
+com.sun.source.doctree.ThrowsTree
+com.sun.source.doctree.CommentTree
+com.sun.source.doctree.DocRootTree
+com.sun.source.doctree.LiteralTree
+com.sun.source.doctree.VersionTree
+com.sun.source.doctree.BlockTagTree
+com.sun.source.doctree.AttributeTree
+com.sun.source.doctree.ErroneousTree
+com.sun.source.doctree.InlineTagTree
+com.sun.source.doctree.ReferenceTree
+com.sun.source.doctree.DeprecatedTree
+com.sun.source.doctree.DocCommentTree
+com.sun.source.doctree.DocTreeVisitor
+com.sun.source.doctree.EndElementTree
+com.sun.source.doctree.IdentifierTree
+com.sun.source.doctree.InheritDocTree
+com.sun.source.doctree.SerialDataTree
+com.sun.source.doctree.SerialFieldTree
+com.sun.source.doctree.StartElementTree
+com.sun.source.doctree.UnknownBlockTagTree
+com.sun.source.doctree.UnknownInlineTagTree
+com.sun.javadoc.Type#asAnnotatedType()
+com.sun.javadoc.Type#getElementType()
+com.sun.javadoc.AnnotatedType
+com.sun.javadoc.ExecutableMemberDoc#receiverType()
+com.sun.security.jgss.ExtendedGSSCredential
+java.io.BufferedReader#lines()
+java.io.DefaultFileSystem
+java.io.UncheckedIOException
+java.awt.event.InvocationEvent#listener
+java.awt.KeyboardFocusManager#clearFocusOwner()
+java.net.URLPermission
+java.net.HttpConnectSocketImpl
+java.nio.file.attribute.FileTime#from(Instant;)
+java.nio.file.attribute.FileTime#toInstant()
+java.nio.file.Files#newBufferedReader(Path;)
+java.nio.file.Files#newBufferedWriter(Path;OpenOption[];)
+java.nio.file.Files#readAllLines(Path;)
+java.nio.file.Files#write(Path;Iterable<? extends CharSequence>;OpenOption[];)
+java.nio.file.Files#list(Path;)
+java.nio.file.Files#walk(Path;int;FileVisitOption[];)
+java.nio.file.Files#walk(Path;FileVisitOption[];)
+java.nio.file.Files#find(Path;int;BiPredicate<Path,BasicFileAttributes>;FileVisitOption[];)
+java.nio.file.Files#lines(Path;Charset;)
+java.nio.file.Files#lines(Path;)
+java.sql.Date#valueOf(LocalDate;)
+java.sql.Date#toLocalDate()
+java.sql.Time#valueOf(LocalTime;)
+java.sql.Time#toLocalTime()
+java.sql.Types#REF_CURSOR
+java.sql.Types#TIME_WITH_TIMEZONE
+java.sql.Types#TIMESTAMP_WITH_TIMEZONE
+java.sql.SQLType
+java.sql.JDBCType
+java.sql.SQLInput#readObject(Class<T>;)
+java.sql.ResultSet#updateObject(int;Object;SQLType;int;)
+java.sql.ResultSet#updateObject(String;Object;SQLType;int;)
+java.sql.ResultSet#updateObject(int;Object;SQLType;)
+java.sql.ResultSet#updateObject(String;Object;SQLType;)
+java.sql.SQLOutput#writeObject(Object;SQLType;)
+java.sql.Statement#getLargeUpdateCount()
+java.sql.Statement#setLargeMaxRows(long;)
+java.sql.Statement#getLargeMaxRows()
+java.sql.Statement#executeLargeBatch()
+java.sql.Statement#executeLargeUpdate(String;)
+java.sql.Statement#executeLargeUpdate(String;int;)
+java.sql.Statement#executeLargeUpdate(String;int[];)
+java.sql.Statement#executeLargeUpdate(String;String[];)
+java.sql.Timestamp#valueOf(LocalDateTime;)
+java.sql.Timestamp#toLocalDateTime()
+java.sql.Timestamp#from(Instant;)
+java.sql.Timestamp#toInstant()
+java.sql.DriverAction#deregister()
+java.sql.DriverAction
+java.sql.DriverManager#DEREGISTER_DRIVER_PERMISSION
+java.sql.DriverManager#registerDriver(java.sql.Driver;DriverAction;)
+java.sql.DatabaseMetaData#getMaxLogicalLobSize()
+java.sql.DatabaseMetaData#supportsRefCursors()
+java.sql.CallableStatement#setObject(String;Object;SQLType;int;)
+java.sql.CallableStatement#setObject(String;Object;SQLType;)
+java.sql.CallableStatement#registerOutParameter(int;SQLType;)
+java.sql.CallableStatement#registerOutParameter(int;SQLType;int;)
+java.sql.CallableStatement#registerOutParameter(int;SQLType;String;)
+java.sql.CallableStatement#registerOutParameter(String;SQLType;)
+java.sql.CallableStatement#registerOutParameter(String;SQLType;int;)
+java.sql.CallableStatement#registerOutParameter(String;SQLType;String;)
+java.sql.PreparedStatement#setObject(int;Object;SQLType;int;)
+java.sql.PreparedStatement#setObject(int;Object;SQLType;)
+java.sql.PreparedStatement#executeLargeUpdate()
+java.sql.BatchUpdateException#BatchUpdateException(String;String;int;long[];Throwable;)
+java.sql.BatchUpdateException#getLargeUpdateCounts()
+java.sql.BatchUpdateException#longUpdateCounts
+java.lang.invoke.MethodHandles#reflectAs(Class<T>;MethodHandle;)
+java.lang.invoke.MethodHandles.Lookup#revealDirect(MethodHandle;)
+java.lang.invoke.MethodHandleInfo
+java.lang.reflect.Type#getTypeName()
+java.lang.reflect.Field#getAnnotationsByType(Class<T>;)
+java.lang.reflect.Field#getAnnotatedType()
+java.lang.reflect.Method#isDefault()
+java.lang.reflect.Method#getAnnotatedReturnType()
+java.lang.reflect.Modifier#parameterModifiers()
+java.lang.reflect.Parameter
+java.lang.reflect.Executable#getParameterCount()
+java.lang.reflect.Executable#getParameters()
+java.lang.reflect.Executable#getAnnotationsByType(Class<T>;)
+java.lang.reflect.Executable#getAnnotatedReturnType()
+java.lang.reflect.Executable#getAnnotatedReceiverType()
+java.lang.reflect.Executable#getAnnotatedParameterTypes()
+java.lang.reflect.Executable#getAnnotatedExceptionTypes()
+java.lang.reflect.Executable
+java.lang.reflect.Constructor#getAnnotatedReturnType()
+java.lang.reflect.Constructor#getAnnotatedReceiverType()
+java.lang.reflect.TypeVariable#getAnnotatedBounds()
+java.lang.reflect.AnnotatedType
+java.lang.reflect.AccessibleObject#getAnnotationsByType(Class<T>;)
+java.lang.reflect.AccessibleObject#getDeclaredAnnotation(Class<T>;)
+java.lang.reflect.AccessibleObject#getDeclaredAnnotationsByType(Class<T>;)
+java.lang.reflect.AnnotatedElement#getAnnotationsByType(Class<T>;)
+java.lang.reflect.AnnotatedElement#getDeclaredAnnotation(Class<T>;)
+java.lang.reflect.AnnotatedElement#getDeclaredAnnotationsByType(Class<T>;)
+java.lang.reflect.AnnotatedArrayType
+java.lang.reflect.AnnotatedTypeVariable
+java.lang.reflect.AnnotatedWildcardType
+java.lang.reflect.AnnotatedParameterizedType
+java.lang.reflect.MalformedParametersException
+java.lang.Byte#hashCode(byte;)
+java.lang.Byte#toUnsignedInt(byte;)
+java.lang.Byte#toUnsignedLong(byte;)
+java.lang.Byte#BYTES
+java.lang.Long#toUnsignedString(long;int;)
+java.lang.Long#toUnsignedString(long;)
+java.lang.Long#parseUnsignedLong(String;int;)
+java.lang.Long#parseUnsignedLong(String;)
+java.lang.Long#hashCode(long;)
+java.lang.Long#compareUnsigned(long;long;)
+java.lang.Long#divideUnsigned(long;long;)
+java.lang.Long#remainderUnsigned(long;long;)
+java.lang.Long#BYTES
+java.lang.Long#sum(long;long;)
+java.lang.Long#max(long;long;)
+java.lang.Long#min(long;long;)
+java.lang.Math#addExact(int;int;)
+java.lang.Math#addExact(long;long;)
+java.lang.Math#subtractExact(int;int;)
+java.lang.Math#subtractExact(long;long;)
+java.lang.Math#multiplyExact(int;int;)
+java.lang.Math#multiplyExact(long;long;)
+java.lang.Math#incrementExact(int;)
+java.lang.Math#incrementExact(long;)
+java.lang.Math#decrementExact(int;)
+java.lang.Math#decrementExact(long;)
+java.lang.Math#negateExact(int;)
+java.lang.Math#negateExact(long;)
+java.lang.Math#toIntExact(long;)
+java.lang.Math#floorDiv(int;int;)
+java.lang.Math#floorDiv(long;long;)
+java.lang.Math#floorMod(int;int;)
+java.lang.Math#floorMod(long;long;)
+java.lang.Math#nextDown(double;)
+java.lang.Math#nextDown(float;)
+java.lang.Class#toGenericString()
+java.lang.Class#getTypeName()
+java.lang.Class#getAnnotationsByType(java.lang.Class<A>;)
+java.lang.Class#getDeclaredAnnotation(java.lang.Class<A>;)
+java.lang.Class#getDeclaredAnnotationsByType(java.lang.Class<A>;)
+java.lang.Class#getAnnotatedSuperclass()
+java.lang.Class#getAnnotatedInterfaces()
+java.lang.Float#BYTES
+java.lang.Float#isFinite(float;)
+java.lang.Float#hashCode(float;)
+java.lang.Float#sum(float;float;)
+java.lang.Float#max(float;float;)
+java.lang.Float#min(float;float;)
+java.lang.Short#hashCode(short;)
+java.lang.Short#BYTES
+java.lang.Short#toUnsignedInt(short;)
+java.lang.Short#toUnsignedLong(short;)
+java.lang.annotation.Native
+java.lang.annotation.Repeatable
+java.lang.annotation.ElementType#TYPE_PARAMETER
+java.lang.annotation.ElementType#TYPE_USE
+java.lang.management.LockInfo#from(CompositeData;)
+java.lang.Double#BYTES
+java.lang.Double#isFinite(double;)
+java.lang.Double#hashCode(double;)
+java.lang.Double#sum(double;double;)
+java.lang.Double#max(double;double;)
+java.lang.Double#min(double;double;)
+java.lang.String#join(CharSequence;CharSequence[];)
+java.lang.String#join(CharSequence;Iterable<? extends CharSequence>;)
+java.lang.Boolean#hashCode(boolean;)
+java.lang.Boolean#logicalAnd(boolean;boolean;)
+java.lang.Boolean#logicalOr(boolean;boolean;)
+java.lang.Boolean#logicalXor(boolean;boolean;)
+java.lang.Integer#toUnsignedString(int;int;)
+java.lang.Integer#toUnsignedString(int;)
+java.lang.Integer#parseUnsignedInt(String;int;)
+java.lang.Integer#parseUnsignedInt(String;)
+java.lang.Integer#hashCode(int;)
+java.lang.Integer#compareUnsigned(int;int;)
+java.lang.Integer#toUnsignedLong(int;)
+java.lang.Integer#divideUnsigned(int;int;)
+java.lang.Integer#remainderUnsigned(int;int;)
+java.lang.Integer#BYTES
+java.lang.Integer#sum(int;int;)
+java.lang.Integer#max(int;int;)
+java.lang.Integer#min(int;int;)
+java.lang.Package#getAnnotationsByType(Class<A>;)
+java.lang.Package#getDeclaredAnnotation(Class<A>;)
+java.lang.Package#getDeclaredAnnotationsByType(Class<A>;)
+java.lang.Process#waitFor(long;TimeUnit;)
+java.lang.Process#destroyForcibly()
+java.lang.Process#isAlive()
+java.lang.Iterable#forEach(Consumer<? super T>;)
+java.lang.Iterable#spliterator()
+java.lang.Character.UnicodeBlock#ARABIC_EXTENDED_A
+java.lang.Character.UnicodeBlock#SUNDANESE_SUPPLEMENT
+java.lang.Character.UnicodeBlock#MEETEI_MAYEK_EXTENSIONS
+java.lang.Character.UnicodeBlock#MEROITIC_HIEROGLYPHS
+java.lang.Character.UnicodeBlock#MEROITIC_CURSIVE
+java.lang.Character.UnicodeBlock#SORA_SOMPENG
+java.lang.Character.UnicodeBlock#CHAKMA
+java.lang.Character.UnicodeBlock#SHARADA
+java.lang.Character.UnicodeBlock#TAKRI
+java.lang.Character.UnicodeBlock#MIAO
+java.lang.Character.UnicodeBlock#ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS
+java.lang.Character#hashCode(char;)
+java.lang.Character#BYTES
+java.lang.StrictMath#addExact(int;int;)
+java.lang.StrictMath#addExact(long;long;)
+java.lang.StrictMath#subtractExact(int;int;)
+java.lang.StrictMath#subtractExact(long;long;)
+java.lang.StrictMath#multiplyExact(int;int;)
+java.lang.StrictMath#multiplyExact(long;long;)
+java.lang.StrictMath#toIntExact(long;)
+java.lang.StrictMath#floorDiv(int;int;)
+java.lang.StrictMath#floorDiv(long;long;)
+java.lang.StrictMath#floorMod(int;int;)
+java.lang.StrictMath#floorMod(long;long;)
+java.lang.StrictMath#nextDown(double;)
+java.lang.StrictMath#nextDown(float;)
+java.lang.ThreadLocal#withInitial(Supplier<? extends S>;)
+java.lang.CharSequence#chars()
+java.lang.CharSequence#codePoints()
+java.lang.StringBuffer#append(AbstractStringBuilder;)
+java.lang.InternalError#InternalError(String;Throwable;)
+java.lang.InternalError#InternalError(Throwable;)
+java.lang.FunctionalInterface
+java.lang.VirtualMachineError#VirtualMachineError(String;Throwable;)
+java.lang.VirtualMachineError#VirtualMachineError(Throwable;)
+java.lang.AbstractStringBuilder#append(java.lang.AbstractStringBuilder;)
+java.math.BigInteger#longValueExact()
+java.math.BigInteger#intValueExact()
+java.math.BigInteger#shortValueExact()
+java.math.BigInteger#byteValueExact()
+java.time.zone.Ser
+java.time.zone.ZoneRules
+java.time.zone.ZoneRulesProvider
+java.time.zone.ZoneRulesException
+java.time.zone.ZoneOffsetTransition
+java.time.zone.TzdbZoneRulesProvider
+java.time.zone.ZoneOffsetTransitionRule
+java.time.chrono.Era
+java.time.chrono.Ser
+java.time.chrono.IsoEra
+java.time.chrono.HijrahEra
+java.time.chrono.MinguoEra
+java.time.chrono.Chronology
+java.time.chrono.HijrahDate
+java.time.chrono.MinguoDate
+java.time.chrono.JapaneseEra
+java.time.chrono.ChronoPeriod
+java.time.chrono.JapaneseDate
+java.time.chrono.IsoChronology
+java.time.chrono.ChronoLocalDate
+java.time.chrono.ThaiBuddhistEra
+java.time.chrono.ChronoPeriodImpl
+java.time.chrono.HijrahChronology
+java.time.chrono.MinguoChronology
+java.time.chrono.ThaiBuddhistDate
+java.time.chrono.AbstractChronology
+java.time.chrono.JapaneseChronology
+java.time.chrono.ChronoLocalDateImpl
+java.time.chrono.ChronoLocalDateTime
+java.time.chrono.ChronoZonedDateTime
+java.time.chrono.ThaiBuddhistChronology
+java.time.chrono.ChronoLocalDateTimeImpl
+java.time.chrono.ChronoZonedDateTimeImpl
+java.time.format.Parsed
+java.time.format.SignStyle
+java.time.format.FormatStyle
+java.time.format.DecimalStyle
+java.time.format.ResolverStyle
+java.time.format.DateTimeFormatter
+java.time.format.DateTimeParseContext
+java.time.format.DateTimePrintContext
+java.time.format.DateTimeTextProvider
+java.time.format.DateTimeParseException
+java.time.format.DateTimeFormatterBuilder
+java.time.Ser
+java.time.temporal.Temporal
+java.time.temporal.IsoFields
+java.time.temporal.ChronoUnit
+java.time.temporal.ValueRange
+java.time.temporal.WeekFields
+java.time.temporal.ChronoField
+java.time.temporal.JulianFields
+java.time.temporal.TemporalUnit
+java.time.temporal.TemporalField
+java.time.temporal.TemporalQuery
+java.time.temporal.TemporalAmount
+java.time.temporal.TemporalQueries
+java.time.temporal.TemporalAccessor
+java.time.temporal.TemporalAdjuster
+java.time.temporal.TemporalAdjusters
+java.time.temporal.UnsupportedTemporalTypeException
+java.time.Year
+java.time.Clock
+java.time.Month
+java.time.Period
+java.time.ZoneId
+java.time.Instant
+java.time.Duration
+java.time.MonthDay
+java.time.DayOfWeek
+java.time.LocalDate
+java.time.LocalTime
+java.time.YearMonth
+java.time.OffsetTime
+java.time.ZoneOffset
+java.time.ZoneRegion
+java.time.LocalDateTime
+java.time.ZonedDateTime
+java.time.OffsetDateTime
+java.time.DateTimeException
+java.util.spi.CalendarDataProvider
+java.util.spi.CalendarNameProvider
+java.util.spi.TimeZoneNameProvider#getGenericDisplayName(String;int;Locale;)
+java.util.spi.LocaleServiceProvider#isSupportedLocale(Locale;)
+java.util.spi.ResourceBundleControlProvider
+java.util.zip.CRC32#update(ByteBuffer;)
+java.util.zip.Adler32#update(ByteBuffer;)
+java.util.zip.ZipFile#stream()
+java.util.zip.ZipEntry#setLastModifiedTime(FileTime;)
+java.util.zip.ZipEntry#getLastModifiedTime()
+java.util.zip.ZipEntry#setLastAccessTime(FileTime;)
+java.util.zip.ZipEntry#getLastAccessTime()
+java.util.zip.ZipEntry#setCreationTime(FileTime;)
+java.util.zip.ZipEntry#getCreationTime()
+java.util.regex.Matcher#start(String;)
+java.util.regex.Matcher#end(String;)
+java.util.regex.Pattern#asPredicate()
+java.util.regex.Pattern#splitAsStream(CharSequence;)
+java.util.stream.Node
+java.util.stream.Sink
+java.util.stream.Nodes
+java.util.stream.Stream.Builder
+java.util.stream.Stream
+java.util.stream.FindOps
+java.util.stream.Streams
+java.util.stream.MatchOps
+java.util.stream.SliceOps
+java.util.stream.Tripwire
+java.util.stream.Collector
+java.util.stream.IntStream.Builder
+java.util.stream.IntStream
+java.util.stream.ReduceOps
+java.util.stream.SortedOps
+java.util.stream.BaseStream
+java.util.stream.Collectors
+java.util.stream.ForEachOps
+java.util.stream.LongStream.Builder
+java.util.stream.LongStream
+java.util.stream.TerminalOp
+java.util.stream.DistinctOps
+java.util.stream.IntPipeline.Head
+java.util.stream.IntPipeline.StatelessOp
+java.util.stream.IntPipeline.StatefulOp
+java.util.stream.IntPipeline
+java.util.stream.StreamShape
+java.util.stream.AbstractTask
+java.util.stream.DoubleStream.Builder
+java.util.stream.DoubleStream
+java.util.stream.LongPipeline.Head
+java.util.stream.LongPipeline.StatelessOp
+java.util.stream.LongPipeline.StatefulOp
+java.util.stream.LongPipeline
+java.util.stream.SpinedBuffer
+java.util.stream.StreamOpFlag
+java.util.stream.TerminalSink
+java.util.stream.StreamSupport
+java.util.stream.DoublePipeline.StatelessOp
+java.util.stream.DoublePipeline.StatefulOp
+java.util.stream.DoublePipeline
+java.util.stream.PipelineHelper
+java.util.stream.AbstractPipeline
+java.util.stream.ReferencePipeline.Head
+java.util.stream.ReferencePipeline.StatelessOp
+java.util.stream.ReferencePipeline.StatefulOp
+java.util.stream.ReferencePipeline
+java.util.stream.StreamSpliterators
+java.util.stream.AbstractSpinedBuffer
+java.util.stream.AbstractShortCircuitTask
+java.util.logging.Logger#log(Level;Throwable;Supplier<String>;)
+java.util.logging.Logger#logp(Level;String;String;Supplier<String>;)
+java.util.logging.Logger#logp(Level;String;String;Throwable;Supplier<String>;)
+java.util.logging.Logger#logrb(Level;String;String;ResourceBundle;String;Object[];)
+java.util.logging.Logger#logrb(Level;String;String;ResourceBundle;String;Throwable;)
+java.util.logging.Logger#severe(Supplier<String>;)
+java.util.logging.Logger#warning(Supplier<String>;)
+java.util.logging.Logger#info(Supplier<String>;)
+java.util.logging.Logger#config(Supplier<String>;)
+java.util.logging.Logger#fine(Supplier<String>;)
+java.util.logging.Logger#finer(Supplier<String>;)
+java.util.logging.Logger#finest(Supplier<String>;)
+java.util.logging.Logger#setResourceBundle(ResourceBundle;)
+java.util.Map.Entry#comparingByKey()
+java.util.Map.Entry#comparingByValue()
+java.util.Map.Entry#comparingByKey(Comparator<? super K>;)
+java.util.Map.Entry#comparingByValue(Comparator<? super V>;)
+java.util.Map#getOrDefault(Object;V;)
+java.util.Map#forEach(BiConsumer<? super K,? super V>;)
+java.util.Map#replaceAll(BiFunction<? super K,? super V,? extends V>;)
+java.util.Map#putIfAbsent(K;V;)
+java.util.Map#remove(Object;Object;)
+java.util.Map#replace(K;V;V;)
+java.util.Map#replace(K;V;)
+java.util.Map#computeIfAbsent(K;Function<? super K,? extends V>;)
+java.util.Map#computeIfPresent(K;BiFunction<? super K,? super V,? extends V>;)
+java.util.Map#compute(K;BiFunction<? super K,? super V,? extends V>;)
+java.util.Map#merge(K;V;BiFunction<? super V,? super V,? extends V>;)
+java.util.Set#spliterator()
+java.util.function.Consumer
+java.util.function.Function
+java.util.function.Supplier
+java.util.function.Predicate
+java.util.function.BiConsumer
+java.util.function.BiFunction
+java.util.function.BiPredicate
+java.util.function.IntConsumer
+java.util.function.IntFunction
+java.util.function.IntSupplier
+java.util.function.IntPredicate
+java.util.function.LongConsumer
+java.util.function.LongFunction
+java.util.function.LongSupplier
+java.util.function.LongPredicate
+java.util.function.ToIntFunction
+java.util.function.UnaryOperator
+java.util.function.BinaryOperator
+java.util.function.DoubleConsumer
+java.util.function.DoubleFunction
+java.util.function.DoubleSupplier
+java.util.function.ObjIntConsumer
+java.util.function.ToLongFunction
+java.util.function.BooleanSupplier
+java.util.function.DoublePredicate
+java.util.function.ObjLongConsumer
+java.util.function.ToIntBiFunction
+java.util.function.IntUnaryOperator
+java.util.function.ToDoubleFunction
+java.util.function.ToLongBiFunction
+java.util.function.IntBinaryOperator
+java.util.function.IntToLongFunction
+java.util.function.LongToIntFunction
+java.util.function.LongUnaryOperator
+java.util.function.ObjDoubleConsumer
+java.util.function.LongBinaryOperator
+java.util.function.ToDoubleBiFunction
+java.util.function.DoubleToIntFunction
+java.util.function.DoubleUnaryOperator
+java.util.function.IntToDoubleFunction
+java.util.function.DoubleBinaryOperator
+java.util.function.DoubleToLongFunction
+java.util.function.LongToDoubleFunction
+java.util.Date#from(Instant;)
+java.util.Date#toInstant()
+java.util.List#replaceAll(UnaryOperator<E>;)
+java.util.List#sort(Comparator<? super E>;)
+java.util.List#spliterator()
+java.util.concurrent.locks.StampedLock
+java.util.concurrent.atomic.LongAdder
+java.util.concurrent.atomic.AtomicLong#getAndUpdate(LongUnaryOperator;)
+java.util.concurrent.atomic.AtomicLong#updateAndGet(LongUnaryOperator;)
+java.util.concurrent.atomic.AtomicLong#getAndAccumulate(long;LongBinaryOperator;)
+java.util.concurrent.atomic.AtomicLong#accumulateAndGet(long;LongBinaryOperator;)
+java.util.concurrent.atomic.DoubleAdder
+java.util.concurrent.atomic.AtomicInteger#getAndUpdate(IntUnaryOperator;)
+java.util.concurrent.atomic.AtomicInteger#updateAndGet(IntUnaryOperator;)
+java.util.concurrent.atomic.AtomicInteger#getAndAccumulate(int;IntBinaryOperator;)
+java.util.concurrent.atomic.AtomicInteger#accumulateAndGet(int;IntBinaryOperator;)
+java.util.concurrent.atomic.AtomicLongArray#getAndUpdate(int;LongUnaryOperator;)
+java.util.concurrent.atomic.AtomicLongArray#updateAndGet(int;LongUnaryOperator;)
+java.util.concurrent.atomic.AtomicLongArray#getAndAccumulate(int;long;LongBinaryOperator;)
+java.util.concurrent.atomic.AtomicLongArray#accumulateAndGet(int;long;LongBinaryOperator;)
+java.util.concurrent.atomic.AtomicReference#getAndUpdate(UnaryOperator<V>;)
+java.util.concurrent.atomic.AtomicReference#updateAndGet(UnaryOperator<V>;)
+java.util.concurrent.atomic.AtomicReference#getAndAccumulate(V;BinaryOperator<V>;)
+java.util.concurrent.atomic.AtomicReference#accumulateAndGet(V;BinaryOperator<V>;)
+java.util.concurrent.atomic.LongAccumulator
+java.util.concurrent.atomic.DoubleAccumulator
+java.util.concurrent.atomic.AtomicIntegerArray#getAndUpdate(int;IntUnaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerArray#updateAndGet(int;IntUnaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerArray#getAndAccumulate(int;int;IntBinaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerArray#accumulateAndGet(int;int;IntBinaryOperator;)
+java.util.concurrent.atomic.AtomicReferenceArray#getAndUpdate(int;UnaryOperator<E>;)
+java.util.concurrent.atomic.AtomicReferenceArray#updateAndGet(int;UnaryOperator<E>;)
+java.util.concurrent.atomic.AtomicReferenceArray#getAndAccumulate(int;E;BinaryOperator<E>;)
+java.util.concurrent.atomic.AtomicReferenceArray#accumulateAndGet(int;E;BinaryOperator<E>;)
+java.util.concurrent.atomic.AtomicLongFieldUpdater#getAndUpdate(T;LongUnaryOperator;)
+java.util.concurrent.atomic.AtomicLongFieldUpdater#updateAndGet(T;LongUnaryOperator;)
+java.util.concurrent.atomic.AtomicLongFieldUpdater#getAndAccumulate(T;long;LongBinaryOperator;)
+java.util.concurrent.atomic.AtomicLongFieldUpdater#accumulateAndGet(T;long;LongBinaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater#getAndUpdate(T;IntUnaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater#updateAndGet(T;IntUnaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater#getAndAccumulate(T;int;IntBinaryOperator;)
+java.util.concurrent.atomic.AtomicIntegerFieldUpdater#accumulateAndGet(T;int;IntBinaryOperator;)
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater#getAndUpdate(T;UnaryOperator<V>;)
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater#updateAndGet(T;UnaryOperator<V>;)
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater#getAndAccumulate(T;V;BinaryOperator<V>;)
+java.util.concurrent.atomic.AtomicReferenceFieldUpdater#accumulateAndGet(T;V;BinaryOperator<V>;)
+java.util.concurrent.Executors#newWorkStealingPool(int;)
+java.util.concurrent.Executors#newWorkStealingPool()
+java.util.concurrent.ForkJoinPool#commonPool()
+java.util.concurrent.ForkJoinPool#getCommonPoolParallelism()
+java.util.concurrent.ForkJoinTask#quietlyComplete()
+java.util.concurrent.ForkJoinTask#getForkJoinTaskTag()
+java.util.concurrent.ForkJoinTask#setForkJoinTaskTag(short;)
+java.util.concurrent.ForkJoinTask#compareAndSetForkJoinTaskTag(short;short;)
+java.util.concurrent.ConcurrentMap#getOrDefault(Object;V;)
+java.util.concurrent.ConcurrentMap#forEach(BiConsumer<? super K,? super V>;)
+java.util.concurrent.ConcurrentMap#replaceAll(BiFunction<? super K,? super V,? extends V>;)
+java.util.concurrent.ConcurrentMap#computeIfAbsent(K;Function<? super K,? extends V>;)
+java.util.concurrent.ConcurrentMap#computeIfPresent(K;BiFunction<? super K,? super V,? extends V>;)
+java.util.concurrent.ConcurrentMap#compute(K;BiFunction<? super K,? super V,? extends V>;)
+java.util.concurrent.ConcurrentMap#merge(K;V;BiFunction<? super V,? super V,? extends V>;)
+java.util.concurrent.CompletionStage
+java.util.concurrent.CountedCompleter
+java.util.concurrent.SynchronousQueue#spliterator()
+java.util.concurrent.CompletableFuture.AsynchronousCompletionTask
+java.util.concurrent.CompletableFuture
+java.util.concurrent.ConcurrentHashMap#mappingCount()
+java.util.concurrent.ConcurrentHashMap#newKeySet()
+java.util.concurrent.ConcurrentHashMap#newKeySet(int;)
+java.util.concurrent.ConcurrentHashMap#forEach(long;BiConsumer<? super K,? super V>;)
+java.util.concurrent.ConcurrentHashMap#forEach(long;BiFunction<? super K,? super V,? extends U>;Consumer<? super U>;)
+java.util.concurrent.ConcurrentHashMap#search(long;BiFunction<? super K,? super V,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduce(long;BiFunction<? super K,? super V,? extends U>;BiFunction<? super U,? super U,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceToDouble(long;ToDoubleBiFunction<? super K,? super V>;double;DoubleBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceToLong(long;ToLongBiFunction<? super K,? super V>;long;LongBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceToInt(long;ToIntBiFunction<? super K,? super V>;int;IntBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#forEachKey(long;Consumer<? super K>;)
+java.util.concurrent.ConcurrentHashMap#forEachKey(long;Function<? super K,? extends U>;Consumer<? super U>;)
+java.util.concurrent.ConcurrentHashMap#searchKeys(long;Function<? super K,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceKeys(long;BiFunction<? super K,? super K,? extends K>;)
+java.util.concurrent.ConcurrentHashMap#reduceKeys(long;Function<? super K,? extends U>;BiFunction<? super U,? super U,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceKeysToDouble(long;ToDoubleFunction<? super K>;double;DoubleBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceKeysToLong(long;ToLongFunction<? super K>;long;LongBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceKeysToInt(long;ToIntFunction<? super K>;int;IntBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#forEachValue(long;Consumer<? super V>;)
+java.util.concurrent.ConcurrentHashMap#forEachValue(long;Function<? super V,? extends U>;Consumer<? super U>;)
+java.util.concurrent.ConcurrentHashMap#searchValues(long;Function<? super V,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceValues(long;BiFunction<? super V,? super V,? extends V>;)
+java.util.concurrent.ConcurrentHashMap#reduceValues(long;Function<? super V,? extends U>;BiFunction<? super U,? super U,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceValuesToDouble(long;ToDoubleFunction<? super V>;double;DoubleBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceValuesToLong(long;ToLongFunction<? super V>;long;LongBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceValuesToInt(long;ToIntFunction<? super V>;int;IntBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#forEachEntry(long;Consumer<? super Map.Entry<K,V>>;)
+java.util.concurrent.ConcurrentHashMap#forEachEntry(long;Function<Map.Entry<K,V>,? extends U>;Consumer<? super U>;)
+java.util.concurrent.ConcurrentHashMap#searchEntries(long;Function<Map.Entry<K,V>,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceEntries(long;BiFunction<Map.Entry<K,V>,Map.Entry<K,V>,? extends Map.Entry<K,V>>;)
+java.util.concurrent.ConcurrentHashMap#reduceEntries(long;Function<Map.Entry<K,V>,? extends U>;BiFunction<? super U,? super U,? extends U>;)
+java.util.concurrent.ConcurrentHashMap#reduceEntriesToDouble(long;ToDoubleFunction<Map.Entry<K,V>>;double;DoubleBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceEntriesToLong(long;ToLongFunction<Map.Entry<K,V>>;long;LongBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap#reduceEntriesToInt(long;ToIntFunction<Map.Entry<K,V>>;int;IntBinaryOperator;)
+java.util.concurrent.ConcurrentHashMap.KeySetView
+java.util.concurrent.ThreadLocalRandom#ints(long;)
+java.util.concurrent.ThreadLocalRandom#ints()
+java.util.concurrent.ThreadLocalRandom#ints(long;int;int;)
+java.util.concurrent.ThreadLocalRandom#ints(int;int;)
+java.util.concurrent.ThreadLocalRandom#longs(long;)
+java.util.concurrent.ThreadLocalRandom#longs()
+java.util.concurrent.ThreadLocalRandom#longs(long;long;long;)
+java.util.concurrent.ThreadLocalRandom#longs(long;long;)
+java.util.concurrent.ThreadLocalRandom#doubles(long;)
+java.util.concurrent.ThreadLocalRandom#doubles()
+java.util.concurrent.ThreadLocalRandom#doubles(long;double;double;)
+java.util.concurrent.ThreadLocalRandom#doubles(double;double;)
+java.util.concurrent.ArrayBlockingQueue#spliterator()
+java.util.concurrent.CompletionException
+java.util.concurrent.CopyOnWriteArraySet#spliterator()
+java.util.concurrent.LinkedBlockingDeque#spliterator()
+java.util.concurrent.LinkedBlockingQueue#spliterator()
+java.util.concurrent.LinkedTransferQueue#spliterator()
+java.util.concurrent.CopyOnWriteArrayList#spliterator()
+java.util.concurrent.ConcurrentLinkedDeque#spliterator()
+java.util.concurrent.ConcurrentLinkedQueue#spliterator()
+java.util.concurrent.ConcurrentSkipListMap#getOrDefault(Object;V;)
+java.util.concurrent.ConcurrentSkipListMap#computeIfAbsent(K;Function<? super K,? extends V>;)
+java.util.concurrent.ConcurrentSkipListMap#computeIfPresent(K;BiFunction<? super K,? super V,? extends V>;)
+java.util.concurrent.ConcurrentSkipListMap#compute(K;BiFunction<? super K,? super V,? extends V>;)
+java.util.concurrent.ConcurrentSkipListMap#merge(K;V;BiFunction<? super V,? super V,? extends V>;)
+java.util.concurrent.ConcurrentSkipListSet#spliterator()
+java.util.concurrent.PriorityBlockingQueue#spliterator()
+java.util.Arrays#parallelSort(byte[];)
+java.util.Arrays#parallelSort(byte[];int;int;)
+java.util.Arrays#parallelSort(char[];)
+java.util.Arrays#parallelSort(char[];int;int;)
+java.util.Arrays#parallelSort(short[];)
+java.util.Arrays#parallelSort(short[];int;int;)
+java.util.Arrays#parallelSort(int[];)
+java.util.Arrays#parallelSort(int[];int;int;)
+java.util.Arrays#parallelSort(long[];)
+java.util.Arrays#parallelSort(long[];int;int;)
+java.util.Arrays#parallelSort(float[];)
+java.util.Arrays#parallelSort(float[];int;int;)
+java.util.Arrays#parallelSort(double[];)
+java.util.Arrays#parallelSort(double[];int;int;)
+java.util.Arrays#parallelSort(T[];)
+java.util.Arrays#parallelSort(T[];int;int;)
+java.util.Arrays#parallelSort(T[];Comparator<? super T>;)
+java.util.Arrays#parallelSort(T[];int;int;Comparator<? super T>;)
+java.util.Arrays#parallelPrefix(T[];BinaryOperator<T>;)
+java.util.Arrays#parallelPrefix(T[];int;int;BinaryOperator<T>;)
+java.util.Arrays#parallelPrefix(long[];LongBinaryOperator;)
+java.util.Arrays#parallelPrefix(long[];int;int;LongBinaryOperator;)
+java.util.Arrays#parallelPrefix(double[];DoubleBinaryOperator;)
+java.util.Arrays#parallelPrefix(double[];int;int;DoubleBinaryOperator;)
+java.util.Arrays#parallelPrefix(int[];IntBinaryOperator;)
+java.util.Arrays#parallelPrefix(int[];int;int;IntBinaryOperator;)
+java.util.Arrays#setAll(T[];IntFunction<? extends T>;)
+java.util.Arrays#parallelSetAll(T[];IntFunction<? extends T>;)
+java.util.Arrays#setAll(int[];IntUnaryOperator;)
+java.util.Arrays#parallelSetAll(int[];IntUnaryOperator;)
+java.util.Arrays#setAll(long[];IntToLongFunction;)
+java.util.Arrays#parallelSetAll(long[];IntToLongFunction;)
+java.util.Arrays#setAll(double[];IntToDoubleFunction;)
+java.util.Arrays#parallelSetAll(double[];IntToDoubleFunction;)
+java.util.Arrays#spliterator(T[];)
+java.util.Arrays#spliterator(T[];int;int;)
+java.util.Arrays#spliterator(int[];)
+java.util.Arrays#spliterator(int[];int;int;)
+java.util.Arrays#spliterator(long[];)
+java.util.Arrays#spliterator(long[];int;int;)
+java.util.Arrays#spliterator(double[];)
+java.util.Arrays#spliterator(double[];int;int;)
+java.util.Arrays#stream(T[];)
+java.util.Arrays#stream(T[];int;int;)
+java.util.Arrays#stream(int[];)
+java.util.Arrays#stream(int[];int;int;)
+java.util.Arrays#stream(long[];)
+java.util.Arrays#stream(long[];int;int;)
+java.util.Arrays#stream(double[];)
+java.util.Arrays#stream(double[];int;int;)
+java.util.Base64.Encoder
+java.util.Base64.Decoder
+java.util.Base64
+java.util.BitSet#stream()
+java.util.Locale#hasExtensions()
+java.util.Locale#stripExtensions()
+java.util.Locale.FilteringMode
+java.util.Locale.LanguageRange
+java.util.Locale#filter(List<LanguageRange>;Collection<Locale>;java.util.Locale.FilteringMode;)
+java.util.Locale#filter(List<LanguageRange>;Collection<Locale>;)
+java.util.Locale#filterTags(List<LanguageRange>;Collection<String>;java.util.Locale.FilteringMode;)
+java.util.Locale#filterTags(List<LanguageRange>;Collection<String>;)
+java.util.Locale#lookup(List<LanguageRange>;Collection<Locale>;)
+java.util.Locale#lookupTag(List<LanguageRange>;Collection<String>;)
+java.util.Random#ints(long;)
+java.util.Random#ints()
+java.util.Random#ints(long;int;int;)
+java.util.Random#ints(int;int;)
+java.util.Random#longs(long;)
+java.util.Random#longs()
+java.util.Random#longs(long;long;long;)
+java.util.Random#longs(long;long;)
+java.util.Random#doubles(long;)
+java.util.Random#doubles()
+java.util.Random#doubles(long;double;double;)
+java.util.Random#doubles(double;double;)
+java.util.Vector#spliterator()
+java.util.HashSet#spliterator()
+java.util.Objects#isNull(Object;)
+java.util.Objects#nonNull(Object;)
+java.util.Objects#requireNonNull(T;Supplier<String>;)
+java.util.TimSort#sort(T[];int;int;Comparator<? super T>;T[];int;int;)
+java.util.TreeSet#spliterator()
+java.util.Calendar#NARROW_FORMAT
+java.util.Calendar#NARROW_STANDALONE
+java.util.Calendar#SHORT_FORMAT
+java.util.Calendar#LONG_FORMAT
+java.util.Calendar#SHORT_STANDALONE
+java.util.Calendar#LONG_STANDALONE
+java.util.Calendar.Builder
+java.util.Calendar#getAvailableCalendarTypes()
+java.util.Calendar#getCalendarType()
+java.util.Calendar#toInstant()
+java.util.Iterator#forEachRemaining(Consumer<? super E>;)
+java.util.Optional
+java.util.TimeZone#getTimeZone(ZoneId;)
+java.util.TimeZone#toZoneId()
+java.util.Tripwire
+java.util.ArrayList#spliterator()
+java.util.SortedSet#spliterator()
+java.util.ArrayDeque#spliterator()
+java.util.Collection#removeIf(Predicate<? super E>;)
+java.util.Collection#spliterator()
+java.util.Collection#stream()
+java.util.Collection#parallelStream()
+java.util.Comparator#reversed()
+java.util.Comparator#thenComparing(java.util.Comparator<? super T>;)
+java.util.Comparator#thenComparing(Function<? super T,? extends U>;java.util.Comparator<? super U>;)
+java.util.Comparator#thenComparing(Function<? super T,? extends U>;)
+java.util.Comparator#thenComparingInt(ToIntFunction<? super T>;)
+java.util.Comparator#thenComparingLong(ToLongFunction<? super T>;)
+java.util.Comparator#thenComparingDouble(ToDoubleFunction<? super T>;)
+java.util.Comparator#reverseOrder()
+java.util.Comparator#naturalOrder()
+java.util.Comparator#nullsFirst(java.util.Comparator<? super T>;)
+java.util.Comparator#nullsLast(java.util.Comparator<? super T>;)
+java.util.Comparator#comparing(Function<? super T,? extends U>;java.util.Comparator<? super U>;)
+java.util.Comparator#comparing(Function<? super T,? extends U>;)
+java.util.Comparator#comparingInt(ToIntFunction<? super T>;)
+java.util.Comparator#comparingLong(ToLongFunction<? super T>;)
+java.util.Comparator#comparingDouble(ToDoubleFunction<? super T>;)
+java.util.LinkedList#spliterator()
+java.util.Collections#unmodifiableNavigableSet(NavigableSet<T>;)
+java.util.Collections#unmodifiableNavigableMap(NavigableMap<K,? extends V>;)
+java.util.Collections#synchronizedNavigableSet(NavigableSet<T>;)
+java.util.Collections#synchronizedNavigableMap(NavigableMap<K,V>;)
+java.util.Collections#checkedQueue(Queue<E>;Class<E>;)
+java.util.Collections#checkedNavigableSet(NavigableSet<E>;Class<E>;)
+java.util.Collections#checkedNavigableMap(NavigableMap<K,V>;Class<K>;Class<V>;)
+java.util.Collections#emptySortedSet()
+java.util.Collections#emptyNavigableSet()
+java.util.Collections#emptySortedMap()
+java.util.Collections#emptyNavigableMap()
+java.util.OptionalInt
+java.util.Spliterator.OfPrimitive
+java.util.Spliterator.OfInt
+java.util.Spliterator.OfLong
+java.util.Spliterator.OfDouble
+java.util.Spliterator
+java.util.OptionalLong
+java.util.Spliterators.AbstractSpliterator
+java.util.Spliterators.AbstractIntSpliterator
+java.util.Spliterators.AbstractLongSpliterator
+java.util.Spliterators.AbstractDoubleSpliterator
+java.util.Spliterators
+java.util.StringJoiner
+java.util.LinkedHashSet#spliterator()
+java.util.PriorityQueue#PriorityQueue(Comparator<? super E>;)
+java.util.PriorityQueue#spliterator()
+java.util.OptionalDouble
+java.util.ResourceBundle#getBaseBundleName()
+java.util.SplittableRandom
+java.util.ComparableTimSort#sort(Object[];int;int;Object[];int;int;)
+java.util.GregorianCalendar#getCalendarType()
+java.util.GregorianCalendar#toZonedDateTime()
+java.util.GregorianCalendar#from(ZonedDateTime;)
+java.util.PrimitiveIterator.OfInt
+java.util.PrimitiveIterator.OfLong
+java.util.PrimitiveIterator.OfDouble
+java.util.PrimitiveIterator
+java.util.ArrayPrefixHelpers
+java.util.IntSummaryStatistics
+java.util.LongSummaryStatistics
+java.util.DoubleSummaryStatistics
+java.security.cert.X509CRL#verify(PublicKey;Provider;)
+java.security.cert.Certificate#verify(PublicKey;Provider;)
+java.security.cert.CertPathBuilder#getRevocationChecker()
+java.security.cert.CertPathChecker
+java.security.cert.X509Certificate#verify(PublicKey;Provider;)
+java.security.cert.CertPathValidator#getRevocationChecker()
+java.security.cert.CertPathBuilderSpi#engineGetRevocationChecker()
+java.security.cert.CertPathValidatorSpi#engineGetRevocationChecker()
+java.security.cert.PKIXRevocationChecker
+java.security.KeyStore.PasswordProtection#PasswordProtection(char[];String;AlgorithmParameterSpec;)
+java.security.KeyStore.PasswordProtection#getProtectionAlgorithm()
+java.security.KeyStore.PasswordProtection#getProtectionParameters()
+java.security.KeyStore.Entry#getAttributes()
+java.security.KeyStore.Entry.Attribute
+java.security.KeyStore.PrivateKeyEntry#PrivateKeyEntry(PrivateKey;Certificate[];Set<Attribute>;)
+java.security.KeyStore.PrivateKeyEntry#getAttributes()
+java.security.KeyStore.SecretKeyEntry#SecretKeyEntry(SecretKey;Set<Attribute>;)
+java.security.KeyStore.SecretKeyEntry#getAttributes()
+java.security.KeyStore.TrustedCertificateEntry#TrustedCertificateEntry(Certificate;Set<Attribute>;)
+java.security.KeyStore.TrustedCertificateEntry#getAttributes()
+java.security.Provider#putIfAbsent(Object;Object;)
+java.security.Provider#remove(Object;Object;)
+java.security.Provider#replace(Object;Object;Object;)
+java.security.Provider#replace(Object;Object;)
+java.security.Provider#replaceAll(BiFunction<? super Object,? super Object,? extends Object>;)
+java.security.Provider#compute(Object;BiFunction<? super Object,? super Object,? extends Object>;)
+java.security.Provider#computeIfAbsent(Object;Function<? super Object,? extends Object>;)
+java.security.Provider#computeIfPresent(Object;BiFunction<? super Object,? super Object,? extends Object>;)
+java.security.Provider#merge(Object;Object;BiFunction<? super Object,? super Object,? extends Object>;)
+java.security.Provider#getOrDefault(Object;Object;)
+java.security.Provider#forEach(BiConsumer<? super Object,? super Object>;)
+java.security.Principal#implies(Subject;)
+java.security.SecureRandom#getInstanceStrong()
+java.security.PKCS12Attribute
+java.security.AccessController#doPrivileged(PrivilegedAction<T>;AccessControlContext;Permission[];)
+java.security.AccessController#doPrivilegedWithCombiner(PrivilegedAction<T>;AccessControlContext;Permission[];)
+java.security.AccessController#doPrivileged(PrivilegedExceptionAction<T>;AccessControlContext;Permission[];)
+java.security.AccessController#doPrivilegedWithCombiner(PrivilegedExceptionAction<T>;AccessControlContext;Permission[];)
+java.security.DomainLoadStoreParameter
+javax.xml.validation.SchemaFactoryConfigurationError
+javax.lang.model.type.TypeKind#INTERSECTION
+javax.lang.model.type.TypeVisitor#visitIntersection(IntersectionType;P;)
+javax.lang.model.type.ExecutableType#getReceiverType()
+javax.lang.model.type.IntersectionType
+javax.lang.model.util.Elements#isFunctionalInterface(TypeElement;)
+javax.lang.model.util.ElementScanner8
+javax.lang.model.util.TypeKindVisitor8
+javax.lang.model.util.SimpleTypeVisitor8
+javax.lang.model.util.ElementKindVisitor8
+javax.lang.model.util.AbstractTypeVisitor6#visitIntersection(IntersectionType;P;)
+javax.lang.model.util.AbstractTypeVisitor8
+javax.lang.model.util.SimpleElementVisitor8
+javax.lang.model.util.AbstractElementVisitor8
+javax.lang.model.util.SimpleAnnotationValueVisitor8
+javax.lang.model.util.AbstractAnnotationValueVisitor8
+javax.lang.model.element.Modifier#DEFAULT
+javax.lang.model.element.ExecutableElement#getReceiverType()
+javax.lang.model.element.ExecutableElement#isDefault()
+javax.lang.model.SourceVersion#RELEASE_8
+javax.lang.model.AnnotatedConstruct
+javax.tools.StandardLocation#NATIVE_HEADER_OUTPUT
+javax.security.auth.kerberos.KeyTab#getUnboundInstance(File;)
+javax.security.auth.kerberos.KeyTab#getInstance(KerberosPrincipal;File;)
+javax.security.auth.kerberos.KeyTab#getUnboundInstance()
+javax.security.auth.kerberos.KeyTab#getInstance(KerberosPrincipal;)
+javax.security.auth.kerberos.KeyTab#getPrincipal()
+javax.security.auth.kerberos.KeyTab#isBound()
\ No newline at end of file
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java b/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java
index d4cff69..b693e5e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/localCanBeFinal/LocalCanBeFinal.java
@@ -21,21 +21,19 @@
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
+import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import javax.swing.event.ChangeEvent;
-import javax.swing.event.ChangeListener;
-import java.awt.*;
import java.util.*;
-import java.util.List;
/**
* @author max
@@ -56,6 +54,18 @@
}
@Override
+ public void writeSettings(@NotNull Element node) throws WriteExternalException {
+ node.addContent(new Element("option").setAttribute("name", "REPORT_VARIABLES").setAttribute("value", String.valueOf(REPORT_VARIABLES)));
+ node.addContent(new Element("option").setAttribute("name", "REPORT_PARAMETERS").setAttribute("value", String.valueOf(REPORT_PARAMETERS)));
+ if (!REPORT_CATCH_PARAMETERS) {
+ node.addContent(new Element("option").setAttribute("name", "REPORT_CATCH_PARAMETERS").setAttribute("value", "false"));
+ }
+ if (!REPORT_FOREACH_PARAMETERS) {
+ node.addContent(new Element("option").setAttribute("name", "REPORT_FOREACH_PARAMETERS").setAttribute("value", "false"));
+ }
+ }
+
+ @Override
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
List<ProblemDescriptor> list = checkCodeBlock(method.getBody(), manager, isOnTheFly);
return list == null ? null : list.toArray(new ProblemDescriptor[list.size()]);
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
index e05c4b1..0edaee4 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/nullable/NullableStuffInspectionBase.java
@@ -77,14 +77,20 @@
if (!AnnotationUtil.isAnnotatingApplicable(field, anno)) {
final PsiAnnotation notNull = AnnotationUtil.findAnnotation(field, manager.getNotNulls());
final PsiAnnotation nullable = AnnotationUtil.findAnnotation(field, manager.getNullables());
- String message = "";
+ final PsiAnnotation annotation;
+ String message = "Not \'";
if (annotated.isDeclaredNullable) {
message += nullable.getQualifiedName();
+ annotation = nullable;
} else {
message += notNull.getQualifiedName();
+ annotation = notNull;
}
- message += " contradicts to configured defaults";
- holder.registerProblem(field.getNameIdentifier(), message,
+ message += "\' but \'" + anno + "\' would be used for code generation.";
+ final PsiJavaCodeReferenceElement annotationNameReferenceElement = annotation.getNameReferenceElement();
+ holder.registerProblem(annotationNameReferenceElement != null ? annotationNameReferenceElement : field.getNameIdentifier(),
+ message,
+ ProblemHighlightType.WEAK_WARNING,
new ChangeNullableDefaultsFix(notNull, nullable, manager));
return;
}
@@ -92,8 +98,6 @@
String propName = JavaCodeStyleManager.getInstance(project).variableNameToPropertyName(field.getName(), VariableKind.FIELD);
final boolean isStatic = field.hasModifierProperty(PsiModifier.STATIC);
final PsiMethod getter = PropertyUtil.findPropertyGetter(field.getContainingClass(), propName, isStatic, false);
- final String nullableSimpleName = StringUtil.getShortName(manager.getDefaultNullable());
- final String notNullSimpleName = StringUtil.getShortName(manager.getDefaultNotNull());
final PsiIdentifier nameIdentifier = getter == null ? null : getter.getNameIdentifier();
if (nameIdentifier != null && nameIdentifier.isPhysical()) {
if (PropertyUtil.isSimpleGetter(getter)) {
@@ -104,20 +108,16 @@
}
};
if (REPORT_NOT_ANNOTATED_GETTER) {
- if (!AnnotationUtil.isAnnotated(getter, manager.getAllAnnotations(), false, false) &&
- !TypeConversionUtil.isPrimitiveAndNotNull(getter.getReturnType())) {
+ if (!manager.hasNullability(getter) && !TypeConversionUtil.isPrimitiveAndNotNull(getter.getReturnType())) {
holder.registerProblem(nameIdentifier, InspectionsBundle
- .message("inspection.nullable.problems.annotated.field.getter.not.annotated", StringUtil.getShortName(anno)),
+ .message("inspection.nullable.problems.annotated.field.getter.not.annotated", getPresentableAnnoName(field)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix);
}
}
- if (annotated.isDeclaredNotNull && manager.isNullable(getter, false)) {
+ if (annotated.isDeclaredNotNull && manager.isNullable(getter, false) ||
+ annotated.isDeclaredNullable && manager.isNotNull(getter, false)) {
holder.registerProblem(nameIdentifier, InspectionsBundle.message(
- "inspection.nullable.problems.annotated.field.getter.conflict", StringUtil.getShortName(anno), nullableSimpleName),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix);
- } else if (annotated.isDeclaredNullable && manager.isNotNull(getter, false)) {
- holder.registerProblem(nameIdentifier, InspectionsBundle.message(
- "inspection.nullable.problems.annotated.field.getter.conflict", StringUtil.getShortName(anno), notNullSimpleName),
+ "inspection.nullable.problems.annotated.field.getter.conflict", getPresentableAnnoName(field), getPresentableAnnoName(getter)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, getterAnnoFix);
}
}
@@ -131,30 +131,23 @@
final PsiParameter parameter = parameters[0];
LOG.assertTrue(parameter != null, setter.getText());
AddAnnotationPsiFix addAnnoFix = new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove));
- if (REPORT_NOT_ANNOTATED_GETTER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations(), false, false) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
+ if (REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier();
assertValidElement(setter, parameter, nameIdentifier1);
holder.registerProblem(nameIdentifier1,
InspectionsBundle.message("inspection.nullable.problems.annotated.field.setter.parameter.not.annotated",
- StringUtil.getShortName(anno)),
+ getPresentableAnnoName(field)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
addAnnoFix);
}
if (PropertyUtil.isSimpleSetter(setter)) {
- if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false)) {
+ if (annotated.isDeclaredNotNull && manager.isNullable(parameter, false) ||
+ annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) {
final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier();
assertValidElement(setter, parameter, nameIdentifier1);
holder.registerProblem(nameIdentifier1, InspectionsBundle.message(
"inspection.nullable.problems.annotated.field.setter.parameter.conflict",
- StringUtil.getShortName(anno), nullableSimpleName),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
- addAnnoFix);
- }
- else if (annotated.isDeclaredNullable && manager.isNotNull(parameter, false)) {
- final PsiIdentifier nameIdentifier1 = parameter.getNameIdentifier();
- assertValidElement(setter, parameter, nameIdentifier1);
- holder.registerProblem(nameIdentifier1, InspectionsBundle.message(
- "inspection.nullable.problems.annotated.field.setter.parameter.conflict", StringUtil.getShortName(anno), notNullSimpleName),
+ getPresentableAnnoName(field), getPresentableAnnoName(parameter)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
addAnnoFix);
}
@@ -167,12 +160,12 @@
if (target instanceof PsiParameter) {
PsiParameter parameter = (PsiParameter)target;
AddAnnotationPsiFix fix = new AddAnnotationPsiFix(anno, parameter, PsiNameValuePair.EMPTY_ARRAY, ArrayUtil.toStringArray(annoToRemove));
- if (REPORT_NOT_ANNOTATED_GETTER && !AnnotationUtil.isAnnotated(parameter, manager.getAllAnnotations(), false, false) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
+ if (REPORT_NOT_ANNOTATED_GETTER && !manager.hasNullability(parameter) && !TypeConversionUtil.isPrimitiveAndNotNull(parameter.getType())) {
final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier();
assert nameIdentifier2 != null : parameter;
holder.registerProblem(nameIdentifier2, InspectionsBundle
.message("inspection.nullable.problems.annotated.field.constructor.parameter.not.annotated",
- StringUtil.getShortName(anno)),
+ getPresentableAnnoName(field)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix);
continue;
}
@@ -188,8 +181,8 @@
final PsiIdentifier nameIdentifier2 = parameter.getNameIdentifier();
assert nameIdentifier2 != null : parameter;
holder.registerProblem(nameIdentifier2, InspectionsBundle.message(
- "inspection.nullable.problems.annotated.field.constructor.parameter.conflict", StringUtil.getShortName(anno),
- notNullSimpleName),
+ "inspection.nullable.problems.annotated.field.constructor.parameter.conflict", getPresentableAnnoName(field),
+ getPresentableAnnoName(parameter)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
fix);
}
@@ -213,6 +206,17 @@
};
}
+ @NotNull
+ private static String getPresentableAnnoName(@NotNull PsiModifierListOwner owner) {
+ NullableNotNullManager manager = NullableNotNullManager.getInstance(owner.getProject());
+ String anno = manager.getNotNull(owner);
+ return StringUtil.getShortName(anno != null ? anno : StringUtil.notNullize(manager.getNullable(owner), "???"));
+ }
+
+ private static String getPresentableAnnoName(@NotNull PsiAnnotation annotation) {
+ return StringUtil.getShortName(StringUtil.notNullize(annotation.getQualifiedName(), "???"));
+ }
+
private static class Annotated {
private final boolean isDeclaredNotNull;
private final boolean isDeclaredNullable;
@@ -282,7 +286,7 @@
reported_nullable_method_overrides_notnull = true;
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(method, nullableManager.getNullables(), true);
holder.registerProblem(annotation != null ? annotation : method.getNameIdentifier(),
- InspectionsBundle.message("inspection.nullable.problems.Nullable.method.overrides.NotNull", nullableManager.getPresentableDefaultNullable(), nullableManager.getPresentableDefaultNotNull()),
+ InspectionsBundle.message("inspection.nullable.problems.Nullable.method.overrides.NotNull", getPresentableAnnoName(method), getPresentableAnnoName(superMethod)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
if (!reported_not_annotated_method_overrides_notnull
@@ -297,7 +301,7 @@
? createAnnotateMethodFix(defaultNotNull, annotationsToRemove)
: createChangeDefaultNotNullFix(nullableManager, superMethod);
holder.registerProblem(method.getNameIdentifier(),
- InspectionsBundle.message("inspection.nullable.problems.method.overrides.NotNull", nullableManager.getPresentableDefaultNotNull()),
+ InspectionsBundle.message("inspection.nullable.problems.method.overrides.NotNull", getPresentableAnnoName(superMethod)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
wrapFix(fix));
}
@@ -316,19 +320,18 @@
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(parameter, nullableManager.getNotNulls(), true);
holder.registerProblem(annotation != null ? annotation : parameter.getNameIdentifier(),
InspectionsBundle.message("inspection.nullable.problems.NotNull.parameter.overrides.Nullable",
- nullableManager.getPresentableDefaultNotNull(),
- nullableManager.getPresentableDefaultNullable()),
+ getPresentableAnnoName(parameter),
+ getPresentableAnnoName(superParameter)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
if (!reported_not_annotated_parameter_overrides_notnull[i] && REPORT_NOT_ANNOTATED_METHOD_OVERRIDES_NOTNULL) {
- if (!AnnotationUtil.isAnnotated(parameter, nullableManager.getAllAnnotations(), false, false) &&
- nullableManager.isNotNull(superParameter, false)) {
+ if (!nullableManager.hasNullability(parameter) && nullableManager.isNotNull(superParameter, false)) {
reported_not_annotated_parameter_overrides_notnull[i] = true;
final LocalQuickFix fix = AnnotationUtil.isAnnotatingApplicable(parameter, nullableManager.getDefaultNotNull())
? new AddNotNullAnnotationFix(parameter)
: createChangeDefaultNotNullFix(nullableManager, superParameter);
holder.registerProblem(parameter.getNameIdentifier(),
- InspectionsBundle.message("inspection.nullable.problems.parameter.overrides.NotNull", nullableManager.getPresentableDefaultNotNull()),
+ InspectionsBundle.message("inspection.nullable.problems.parameter.overrides.NotNull", getPresentableAnnoName(superParameter)),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
wrapFix(fix));
}
@@ -435,10 +438,9 @@
private static void reportNullableNotNullConflict(final ProblemsHolder holder, final PsiModifierListOwner listOwner, final PsiAnnotation declaredNullable,
final PsiAnnotation declaredNotNull) {
- final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(holder.getProject());
final String bothNullableNotNullMessage = InspectionsBundle.message("inspection.nullable.problems.Nullable.NotNull.conflict",
- nullableNotNullManager.getPresentableDefaultNullable(),
- nullableNotNullManager.getPresentableDefaultNotNull());
+ getPresentableAnnoName(declaredNullable),
+ getPresentableAnnoName(declaredNotNull));
holder.registerProblem(declaredNotNull.isPhysical() ? declaredNotNull : listOwner.getNavigationElement(),
bothNullableNotNullMessage,
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new RemoveAnnotationQuickFix(declaredNotNull, listOwner));
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
index 06fb572..674311e 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaUtilImpl.java
@@ -281,6 +281,9 @@
if (ownerClass.isInterface()) {
result = PsiModifier.PUBLIC;
}
+ if (ownerClass.isEnum() && result.equals(PsiModifier.PACKAGE_LOCAL)) {
+ result = PsiModifier.PRIVATE;
+ }
}
}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
index daf7c79..cceb339 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unneededThrows/RedundantThrows.java
@@ -268,7 +268,9 @@
if (!FileModificationService.getInstance().preparePsiElementsForWrite(refsToDelete)) return;
for (final PsiJavaCodeReferenceElement aRefsToDelete : refsToDelete) {
- aRefsToDelete.delete();
+ if (aRefsToDelete.isValid()) {
+ aRefsToDelete.delete();
+ }
}
}
catch (IncorrectOperationException e) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.java
new file mode 100644
index 0000000..dc28a7b
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspectionBase.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.codeInspection.unusedSymbol;
+
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
+import com.intellij.codeInspection.*;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class UnusedSymbolLocalInspectionBase extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool {
+ @NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
+ @NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
+ @NonNls public static final String UNUSED_PARAMETERS_SHORT_NAME = "UnusedParameters";
+
+ public boolean LOCAL_VARIABLE = true;
+ public boolean FIELD = true;
+ public boolean METHOD = true;
+ public boolean CLASS = true;
+ public boolean PARAMETER = true;
+ public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true;
+
+ @Override
+ public boolean isSuppressedFor(@NotNull PsiElement element) {
+ return isSuppressedFor(element, this);
+ }
+ public static boolean isSuppressedFor(@NotNull PsiElement element, @NotNull LocalInspectionTool tool) {
+ return BaseJavaBatchLocalInspectionTool.isSuppressedFor(element, tool);
+ }
+ @Override
+ public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
+ String shortName = getShortName();
+ HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
+ if (key == null) {
+ throw new AssertionError("HighlightDisplayKey.find(" + shortName + ") is null. Inspection: "+getClass());
+ }
+ SuppressQuickFix[] batchSuppressActions = BatchSuppressManager.SERVICE.getInstance().createBatchSuppressActions(key);
+ return SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions);
+ }
+}
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
index 1424bce..fd66f28 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/visibility/VisibilityInspection.java
@@ -42,7 +42,9 @@
import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.usageView.UsageViewTypeLocation;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.VisibilityUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -192,13 +194,25 @@
final PsiElement element = refElement.getElement();
final PsiElement nameIdentifier = element != null ? IdentifierUtil.getNameIdentifier(element) : null;
if (nameIdentifier != null) {
+ final String message;
+ String quickFixName = "Make " + ElementDescriptionUtil.getElementDescription(element, UsageViewTypeLocation.INSTANCE) + " ";
+ if (access.equals(PsiModifier.PRIVATE)) {
+ message = CAN_BE_PRIVATE;
+ quickFixName += PsiModifier.PRIVATE;
+ }
+ else {
+ if (access.equals(PsiModifier.PACKAGE_LOCAL)) {
+ message = CAN_BE_PACKAGE_LOCAL;
+ quickFixName += "package local";
+ }
+ else {
+ message = CAN_BE_PROTECTED;
+ quickFixName += PsiModifier.PROTECTED;
+ }
+ }
return new ProblemDescriptor[]{manager.createProblemDescriptor(nameIdentifier,
- access.equals(PsiModifier.PRIVATE)
- ? CAN_BE_PRIVATE
- : access.equals(PsiModifier.PACKAGE_LOCAL)
- ? CAN_BE_PACKAGE_LOCAL
- : CAN_BE_PROTECTED,
- new AcceptSuggestedAccess(globalContext.getRefManager(), access),
+ message,
+ new AcceptSuggestedAccess(globalContext.getRefManager(), access, quickFixName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false)};
}
}
@@ -527,7 +541,7 @@
@Override
@Nullable
public QuickFix getQuickFix(final String hint) {
- return new AcceptSuggestedAccess(null, hint);
+ return new AcceptSuggestedAccess(null, hint, null);
}
@Override
@@ -539,22 +553,24 @@
private static class AcceptSuggestedAccess implements LocalQuickFix{
private final RefManager myManager;
@PsiModifier.ModifierConstant private final String myHint;
+ private String myName;
- private AcceptSuggestedAccess(final RefManager manager, @PsiModifier.ModifierConstant String hint) {
+ private AcceptSuggestedAccess(final RefManager manager, @PsiModifier.ModifierConstant String hint, String name) {
myManager = manager;
myHint = hint;
+ myName = name;
}
@Override
@NotNull
public String getName() {
- return InspectionsBundle.message("inspection.visibility.accept.quickfix");
+ return myName != null ? myName : getFamilyName();
}
@Override
@NotNull
public String getFamilyName() {
- return getName();
+ return InspectionsBundle.message("inspection.visibility.accept.quickfix");
}
@Override
diff --git a/java/java-impl/src/com/intellij/openapi/roots/JavaGeneratedSourcesFilter.java b/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaGeneratedSourcesFilter.java
similarity index 100%
rename from java/java-impl/src/com/intellij/openapi/roots/JavaGeneratedSourcesFilter.java
rename to java/java-analysis-impl/src/com/intellij/openapi/roots/JavaGeneratedSourcesFilter.java
diff --git a/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java b/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java
new file mode 100644
index 0000000..f7666eb
--- /dev/null
+++ b/java/java-analysis-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java
@@ -0,0 +1,92 @@
+package com.intellij.openapi.roots;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiCodeFragment;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.DelegatingGlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class JavaProjectRootsUtil {
+ public static boolean isOutsideJavaSourceRoot(@Nullable PsiFile psiFile) {
+ if (psiFile == null) return false;
+ if (psiFile instanceof PsiCodeFragment) return false;
+ final VirtualFile file = psiFile.getVirtualFile();
+ if (file == null) return false;
+ final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(psiFile.getProject()).getFileIndex();
+ return !projectFileIndex.isUnderSourceRootOfType(file, JavaModuleSourceRootTypes.SOURCES) && !projectFileIndex.isInLibrarySource(file)
+ && !projectFileIndex.isInLibraryClasses(file);
+ }
+
+ /**
+ * @return list of all java source roots in the project which can be suggested as a target directory for a class created by user
+ */
+ @NotNull
+ public static List<VirtualFile> getSuitableDestinationSourceRoots(@NotNull Project project) {
+ List<VirtualFile> roots = new ArrayList<VirtualFile>();
+ for (Module module : ModuleManager.getInstance(project).getModules()) {
+ for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
+ for (SourceFolder sourceFolder : entry.getSourceFolders(JavaModuleSourceRootTypes.SOURCES)) {
+ if (!isForGeneratedSources(sourceFolder)) {
+ ContainerUtil.addIfNotNull(roots, sourceFolder.getFile());
+ }
+ }
+ }
+ }
+ return roots;
+ }
+
+ private static boolean isForGeneratedSources(SourceFolder sourceFolder) {
+ JavaSourceRootProperties properties = sourceFolder.getJpsElement().getProperties(JavaModuleSourceRootTypes.SOURCES);
+ return properties != null && properties.isForGeneratedSources();
+ }
+
+ public static boolean isInGeneratedCode(@NotNull VirtualFile file, @NotNull Project project) {
+ ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+ Module module = fileIndex.getModuleForFile(file);
+ if (module == null) return false;
+
+ VirtualFile sourceRoot = fileIndex.getSourceRootForFile(file);
+ if (sourceRoot == null) return false;
+
+ for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
+ for (SourceFolder folder : entry.getSourceFolders()) {
+ if (sourceRoot.equals(folder.getFile())) {
+ return isForGeneratedSources(folder);
+ }
+ }
+ }
+ return false;
+ }
+
+ public static GlobalSearchScope getScopeWithoutGeneratedSources(@NotNull GlobalSearchScope baseScope, @NotNull Project project) {
+ return new NonGeneratedSourceScope(baseScope, project);
+ }
+
+ private static class NonGeneratedSourceScope extends DelegatingGlobalSearchScope {
+ @NotNull private final Project myProject;
+
+ private NonGeneratedSourceScope(@NotNull GlobalSearchScope baseScope, @NotNull Project project) {
+ super(baseScope);
+ myProject = project;
+ }
+
+ @Override
+ public boolean contains(@NotNull VirtualFile file) {
+ return super.contains(file) && !isInGeneratedCode(file, myProject);
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/analysis/BaseClassesAnalysisAction.java b/java/java-impl/src/com/intellij/analysis/BaseClassesAnalysisAction.java
index 9d13990..7d7692a 100644
--- a/java/java-impl/src/com/intellij/analysis/BaseClassesAnalysisAction.java
+++ b/java/java-impl/src/com/intellij/analysis/BaseClassesAnalysisAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -58,9 +58,9 @@
final int i = Messages.showYesNoCancelDialog(getProject(), AnalysisScopeBundle.message("recompile.confirmation.message"),
AnalysisScopeBundle.message("project.is.out.of.date"), Messages.getWarningIcon());
- if (i == 2) return;
+ if (i == Messages.CANCEL) return;
- if (i == 0) {
+ if (i == Messages.YES) {
compileAndAnalyze(project, scope);
}
else {
diff --git a/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java
index f40b5ba..eaf2dbc 100644
--- a/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.java
+++ b/java/java-impl/src/com/intellij/application/options/JavaCodeStyleSettingsProvider.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.
@@ -16,11 +16,10 @@
package com.intellij.application.options;
import com.intellij.openapi.options.Configurable;
-import com.intellij.psi.codeStyle.CodeStyleSettings;
-import com.intellij.psi.codeStyle.CodeStyleSettingsProvider;
-import com.intellij.psi.codeStyle.DisplayPriority;
+import com.intellij.psi.codeStyle.*;
import com.intellij.util.PlatformUtils;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author Rustam Vishnyakov
@@ -29,7 +28,7 @@
@NotNull
@Override
public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) {
- return new CodeStyleAbstractConfigurable(settings, originalSettings, "Java") {
+ return new CodeStyleAbstractConfigurable(settings, originalSettings, "Java") {
protected CodeStyleAbstractPanel createPanel(final CodeStyleSettings settings) {
return new JavaCodeStyleMainPanel(getCurrentSettings(), settings);
}
@@ -41,11 +40,17 @@
@Override
public DisplayPriority getPriority() {
- return PlatformUtils.isIdea() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS;
+ return PlatformUtils.isIdeaUltimate() ? DisplayPriority.KEY_LANGUAGE_SETTINGS : DisplayPriority.LANGUAGE_SETTINGS;
}
@Override
public String getConfigurableDisplayName() {
return "Java";
}
+
+ @Nullable
+ @Override
+ public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) {
+ return new JavaCodeStyleSettings(settings);
+ }
}
diff --git a/java/java-impl/src/com/intellij/application/options/editor/JavaCodeFoldingOptionsProvider.java b/java/java-impl/src/com/intellij/application/options/editor/JavaCodeFoldingOptionsProvider.java
index e33b90b..7657ea0 100644
--- a/java/java-impl/src/com/intellij/application/options/editor/JavaCodeFoldingOptionsProvider.java
+++ b/java/java-impl/src/com/intellij/application/options/editor/JavaCodeFoldingOptionsProvider.java
@@ -27,6 +27,7 @@
public class JavaCodeFoldingOptionsProvider extends BeanConfigurable<JavaCodeFoldingSettings> implements CodeFoldingOptionsProvider {
public JavaCodeFoldingOptionsProvider() {
super(JavaCodeFoldingSettings.getInstance());
+ checkBox("COLLAPSE_ONE_LINE_METHODS", ApplicationBundle.message("checkbox.collapse.one.line.methods"));
checkBox("COLLAPSE_ACCESSORS", ApplicationBundle.message("checkbox.collapse.simple.property.accessors"));
checkBox("COLLAPSE_INNER_CLASSES", ApplicationBundle.message("checkbox.collapse.inner.classes"));
checkBox("COLLAPSE_ANONYMOUS_CLASSES", ApplicationBundle.message("checkbox.collapse.anonymous.classes"));
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
index c9f75a0..f2445e1 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExpectedTypesProvider.java
@@ -35,6 +35,7 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.Stack;
import gnu.trove.THashSet;
@@ -85,6 +86,11 @@
}
@NotNull
+ private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, PsiType defaultType) {
+ return createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, defaultType, TailType.NONE);
+ }
+
+ @NotNull
private static ExpectedTypeInfoImpl createInfoImpl(@NotNull PsiType type, @ExpectedTypeInfo.Type int kind, PsiType defaultType, @NotNull TailType tailType) {
return new ExpectedTypeInfoImpl(type, kind, defaultType, tailType, null, ExpectedTypeInfoImpl.NULL);
}
@@ -163,7 +169,7 @@
}
}
- return set.toArray(new PsiType[set.size()]);
+ return set.toArray(PsiType.createArray(set.size()));
}
private static void processType(@NotNull PsiType type, @NotNull PsiTypeVisitor<PsiType> visitor, @NotNull Set<PsiType> typeSet) {
@@ -216,7 +222,7 @@
private final boolean myUsedAfter;
private final ExpectedClassProvider myClassProvider;
private final boolean myVoidable;
- private ExpectedTypeInfo[] myResult = ExpectedTypeInfo.EMPTY_ARRAY;
+ final List<ExpectedTypeInfo> myResult = ContainerUtil.newArrayList();
@NonNls private static final String LENGTH_SYNTHETIC_ARRAY_FIELD = "length";
private MyParentVisitor(PsiExpression expr,
@@ -233,7 +239,7 @@
@NotNull
public ExpectedTypeInfo[] getResult() {
- return myResult;
+ return myResult.toArray(new ExpectedTypeInfo[myResult.size()]);
}
@Override
@@ -241,7 +247,7 @@
if (myExpr == method.getDefaultValue()) {
final PsiType type = method.getReturnType();
if (type != null) {
- myResult = new ExpectedTypeInfo[]{createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.SEMICOLON)};
+ myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.SEMICOLON));
}
}
}
@@ -251,7 +257,7 @@
if (myForCompletion) {
final MyParentVisitor visitor = new MyParentVisitor(expression, myForCompletion, myClassProvider, myVoidable, myUsedAfter);
expression.getParent().accept(visitor);
- myResult = visitor.getResult();
+ myResult.addAll(visitor.myResult);
return;
}
@@ -259,15 +265,15 @@
if (referenceName != null) {
final PsiElement parent = expression.getParent();
if (parent instanceof PsiMethodCallExpression) {
- myResult = findClassesWithDeclaredMethod((PsiMethodCallExpression)parent, myForCompletion);
+ Collections.addAll(myResult, findClassesWithDeclaredMethod((PsiMethodCallExpression)parent, false));
}
else if (parent instanceof PsiReferenceExpression || parent instanceof PsiVariable ||
parent instanceof PsiExpression) {
if (LENGTH_SYNTHETIC_ARRAY_FIELD.equals(referenceName)) {
- myResult = anyArrayType();
+ myResult.addAll(anyArrayType());
}
else {
- myResult = findClassesWithDeclaredField(expression);
+ Collections.addAll(myResult, findClassesWithDeclaredField(expression));
}
}
}
@@ -276,7 +282,7 @@
@Override
public void visitExpressionStatement(PsiExpressionStatement statement) {
if (myVoidable) {
- myResult = new ExpectedTypeInfo[]{VOID_EXPECTED};
+ myResult.add(VOID_EXPECTED);
}
}
@@ -298,19 +304,17 @@
type = ((PsiAnnotationMethod)parent).getReturnType();
}
if (type instanceof PsiArrayType) {
- myResult = new ExpectedTypeInfo[]{createInfoImpl(((PsiArrayType)type).getComponentType(), ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.UNKNOWN)};
+ myResult.add(createInfoImpl(((PsiArrayType)type).getComponentType(), type));
}
}
@Override public void visitNameValuePair(@NotNull PsiNameValuePair pair) {
final PsiType type = getAnnotationMethodType(pair);
if (type == null) return;
- final ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.UNKNOWN);
+ myResult.add(createInfoImpl(type, type));
if (type instanceof PsiArrayType) {
- myResult = new ExpectedTypeInfo[]{info, createInfoImpl(((PsiArrayType)type).getComponentType(), ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.UNKNOWN)};
- }
- else {
- myResult = new ExpectedTypeInfo[] {info};
+ PsiType componentType = ((PsiArrayType)type).getComponentType();
+ myResult.add(createInfoImpl(componentType, componentType));
}
}
@@ -373,39 +377,27 @@
else {
expectedName = ExpectedTypeInfoImpl.NULL;
}
- ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type,
- tailTypeSemicolon ? TailType.SEMICOLON : TailType.NONE, null, expectedName);
- myResult = new ExpectedTypeInfo[]{info};
- }
- else {
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
+ myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type,
+ tailTypeSemicolon ? TailType.SEMICOLON : TailType.NONE, null, expectedName));
}
}
@Override public void visitIfStatement(PsiIfStatement statement) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailTypes.IF_RPARENTH);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.IF_RPARENTH));
}
@Override public void visitWhileStatement(PsiWhileStatement statement) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH));
}
@Override public void visitDoWhileStatement(PsiDoWhileStatement statement) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailTypes.WHILE_RPARENTH));
}
@Override public void visitForStatement(@NotNull PsiForStatement statement) {
if (myExpr.equals(statement.getCondition())) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailType.SEMICOLON);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.SEMICOLON));
}
}
@@ -413,14 +405,10 @@
public void visitAssertStatement(@NotNull PsiAssertStatement statement) {
if (statement.getAssertDescription() == myExpr) {
final PsiClassType stringType = PsiType.getJavaLangString(myExpr.getManager(), myExpr.getResolveScope());
- ExpectedTypeInfoImpl info = createInfoImpl(stringType, ExpectedTypeInfo.TYPE_STRICTLY,
- stringType, TailType.SEMICOLON);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(stringType, ExpectedTypeInfo.TYPE_STRICTLY, stringType, TailType.SEMICOLON));
}
else {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailType.SEMICOLON);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.SEMICOLON));
}
}
@@ -429,41 +417,30 @@
PsiType type = statement.getIterationParameter().getType();
PsiType arrayType = type.createArrayType();
- ExpectedTypeInfoImpl info1 = createInfoImpl(arrayType, ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- arrayType, TailType.NONE);
+ myResult.add(createInfoImpl(arrayType, arrayType));
PsiManager manager = statement.getManager();
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
PsiClass iterableClass =
JavaPsiFacade.getInstance(manager.getProject()).findClass("java.lang.Iterable", statement.getResolveScope());
- if (iterableClass == null || iterableClass.getTypeParameters().length != 1) {
- myResult = new ExpectedTypeInfo[]{info1};
- }
- else {
+ if (iterableClass != null && iterableClass.getTypeParameters().length == 1) {
Map<PsiTypeParameter, PsiType> map = new HashMap<PsiTypeParameter, PsiType>();
map.put(iterableClass.getTypeParameters()[0], PsiWildcardType.createExtends(manager, type));
- PsiSubstitutor substitutor = factory.createSubstitutor(map);
- PsiType iterableType = factory.createType(iterableClass, substitutor);
- ExpectedTypeInfoImpl info2 = createInfoImpl(iterableType, ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- iterableType, TailType.NONE);
-
- myResult = new ExpectedTypeInfo[]{info1, info2};
+ PsiType iterableType = factory.createType(iterableClass, factory.createSubstitutor(map));
+ myResult.add(createInfoImpl(iterableType, iterableType));
}
}
}
@Override public void visitSwitchStatement(@NotNull PsiSwitchStatement statement) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT,
- TailType.NONE);
+ myResult.add(createInfoImpl(PsiType.LONG, PsiType.INT));
if (!PsiUtil.isLanguageLevel5OrHigher(statement)) {
- myResult = new ExpectedTypeInfo[]{info};
return;
}
PsiManager manager = statement.getManager();
PsiClassType enumType = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory().createTypeByFQClassName("java.lang.Enum", statement.getResolveScope());
- ExpectedTypeInfoImpl enumInfo = createInfoImpl(enumType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, enumType, TailType.NONE);
- myResult = new ExpectedTypeInfo[] {info, enumInfo};
+ myResult.add(createInfoImpl(enumType, enumType));
}
@Override
@@ -474,7 +451,7 @@
if (expression != null) {
final PsiType type = expression.getType();
if (type != null) {
- myResult = new ExpectedTypeInfo[]{createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.CASE_COLON)};
+ myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.CASE_COLON));
}
}
}
@@ -483,14 +460,13 @@
@Override public void visitSynchronizedStatement(@NotNull PsiSynchronizedStatement statement) {
PsiElementFactory factory = JavaPsiFacade.getInstance(statement.getProject()).getElementFactory();
PsiType objectType = factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_OBJECT, myExpr.getResolveScope());
- myResult = new ExpectedTypeInfo[]{createInfoImpl(objectType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, objectType, TailType.NONE)};
+ myResult.add(createInfoImpl(objectType, objectType));
}
@Override public void visitVariable(@NotNull PsiVariable variable) {
PsiType type = variable.getType();
- ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type,
- variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON, null, getPropertyName(variable));
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type,
+ variable instanceof PsiResourceVariable ? TailType.NONE : TailType.SEMICOLON, null, getPropertyName(variable)));
}
@Override public void visitAssignmentExpression(@NotNull PsiAssignmentExpression assignment) {
@@ -506,11 +482,7 @@
expectedName = getPropertyName((PsiVariable)refElement);
}
}
- ExpectedTypeInfoImpl info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tailType, null, expectedName);
- myResult = new ExpectedTypeInfo[]{info};
- }
- else {
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
+ myResult.add(createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, tailType, null, expectedName));
}
}
else {
@@ -533,12 +505,9 @@
final int kind = assignment.getOperationTokenType() != JavaTokenType.EQ
? ExpectedTypeInfo.TYPE_STRICTLY
: ExpectedTypeInfo.TYPE_OR_SUPERTYPE;
- ExpectedTypeInfoImpl info = createInfoImpl(type, kind, type, TailType.NONE);
- myResult = new ExpectedTypeInfo[]{info};
- return;
+ myResult.add(createInfoImpl(type, kind, type, TailType.NONE));
}
}
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
}
}
@@ -561,7 +530,7 @@
if (list.getParent() instanceof PsiMethodCallExpression) {
PsiMethodCallExpression methodCall = (PsiMethodCallExpression)list.getParent();
CandidateInfo[] candidates = helper.getReferencedMethodCandidates(methodCall, false);
- myResult = getExpectedArgumentTypesForMethodCall(candidates, list, myExpr, myForCompletion);
+ Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(candidates, list, myExpr, myForCompletion));
}
else if (list.getParent() instanceof PsiEnumConstant) {
getExpectedArgumentsTypesForEnumConstant((PsiEnumConstant)list.getParent(), list);
@@ -614,7 +583,7 @@
array.add(new MethodCandidateInfo(constructor, substitutor, false, false, argumentList, null, argumentList.getExpressionTypes(), null));
}
CandidateInfo[] candidates = array.toArray(new CandidateInfo[array.size()]);
- myResult = getExpectedArgumentTypesForMethodCall(candidates, argumentList, myExpr, myForCompletion);
+ Collections.addAll(myResult, getExpectedArgumentTypesForMethodCall(candidates, argumentList, myExpr, myForCompletion));
}
@Override
@@ -627,18 +596,19 @@
final MyParentVisitor visitor = new MyParentVisitor(expr, myForCompletion, myClassProvider, myVoidable, myUsedAfter);
myExpr = (PsiExpression)myExpr.getParent();
expr.getParent().accept(visitor);
- myResult = visitor.getResult();
+ myResult.addAll(visitor.myResult);
if (!(expr.getParent() instanceof PsiExpressionList)) {
- for (int i = 0; i < myResult.length; i++) {
- final ExpectedTypeInfo info = myResult[i];
- myResult[i] = createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailType.NONE, info.getCalledMethod(),
- new NullableComputable<String>() {
- @Nullable
- @Override
- public String compute() {
- return ((ExpectedTypeInfoImpl)info).getExpectedName();
+ for (int i = 0; i < myResult.size(); i++) {
+ final ExpectedTypeInfo info = myResult.get(i);
+ myResult.set(i, createInfoImpl(info.getType(), info.getKind(), info.getDefaultType(), TailType.NONE, info.getCalledMethod(),
+ new NullableComputable<String>() {
+ @Nullable
+ @Override
+ public String compute() {
+ return ((ExpectedTypeInfoImpl)info).getExpectedName();
+ }
}
- });
+ ));
}
}
return;
@@ -654,53 +624,40 @@
i == JavaTokenType.GT ||
i == JavaTokenType.LE ||
i == JavaTokenType.GE) {
- if (anotherType == null) {
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
- }
- else {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- anotherType, TailType.NONE);
- myResult = new ExpectedTypeInfo[]{info};
+ if (anotherType != null) {
+ myResult.add(createInfoImpl(PsiType.DOUBLE, anotherType));
}
}
else if (i == JavaTokenType.PLUS) {
if (anotherType == null || anotherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
+ PsiClassType objectType = PsiType.getJavaLangObject(expr.getManager(), expr.getResolveScope());
+ myResult.add(createInfoImpl(objectType, anotherType != null ? anotherType : objectType));
}
else if (PsiType.DOUBLE.isAssignableFrom(anotherType)) {
- myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE)};
+ myResult.add(createInfoImpl(PsiType.DOUBLE, anotherType));
}
}
else if (i == JavaTokenType.EQEQ || i == JavaTokenType.NE) {
- ExpectedTypeInfo info = getEqualsType(anotherExpr);
- myResult = info == null ? ExpectedTypeInfo.EMPTY_ARRAY : new ExpectedTypeInfo[]{info};
+ ContainerUtil.addIfNotNull(myResult, getEqualsType(anotherExpr));
}
else if (i == JavaTokenType.LTLT || i == JavaTokenType.GTGT || i == JavaTokenType.GTGTGT) {
- if (anotherType == null) {
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
- }
- else {
- myResult = new ExpectedTypeInfo[]{createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_BETWEEN, PsiType.SHORT, TailType.NONE)};
+ if (anotherType != null) {
+ myResult.add(createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_BETWEEN, PsiType.SHORT, TailType.NONE));
}
}
else if (i == JavaTokenType.OROR || i == JavaTokenType.ANDAND) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailType.NONE);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.NONE));
}
else if (i == JavaTokenType.OR || i == JavaTokenType.XOR || i == JavaTokenType.AND) {
- if (anotherType == null) {
- myResult = ExpectedTypeInfo.EMPTY_ARRAY;
- }
- else {
+ if (anotherType != null) {
ExpectedTypeInfoImpl info;
if (PsiType.BOOLEAN.equals(anotherType)) {
info = createInfoImpl(anotherType, ExpectedTypeInfo.TYPE_STRICTLY, anotherType, TailType.NONE);
}
else {
- info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, anotherType, TailType.NONE);
+ info = createInfoImpl(PsiType.LONG, anotherType);
}
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(info);
}
}
}
@@ -759,17 +716,13 @@
info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, tailType);
}
}
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(info);
}
else if (i == JavaTokenType.PLUS || i == JavaTokenType.MINUS) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- PsiType.INT, tailType);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.DOUBLE, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, tailType));
}
else if (i == JavaTokenType.EXCL) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, tailType);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, tailType));
}
}
@@ -786,10 +739,10 @@
info = createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUPERTYPE, PsiType.INT, TailType.NONE);
}
else {
- info = createInfoImpl(PsiType.LONG, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, TailType.NONE);
+ info = createInfoImpl(PsiType.LONG, PsiType.INT);
}
}
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(info);
}
@Override
@@ -811,9 +764,7 @@
if (arrayType instanceof PsiArrayType) {
PsiType componentType = ((PsiArrayType)arrayType).getComponentType();
- ExpectedTypeInfoImpl info = createInfoImpl(componentType, ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- componentType, TailType.NONE);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(componentType, componentType));
}
}
@@ -821,9 +772,7 @@
PsiExpression[] arrayDimensions = expression.getArrayDimensions();
for (PsiExpression dimension : arrayDimensions) {
if (myExpr.equals(dimension)) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.INT, ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- PsiType.INT, TailType.NONE);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.INT, PsiType.INT));
return;
}
}
@@ -831,9 +780,7 @@
@Override public void visitArrayAccessExpression(@NotNull PsiArrayAccessExpression expr) {
if (myExpr.equals(expr.getIndexExpression())) {
- ExpectedTypeInfoImpl info = createInfoImpl(PsiType.INT, ExpectedTypeInfo.TYPE_OR_SUBTYPE, PsiType.INT, TailType.NONE)
- ; //todo: special tail type
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.INT, PsiType.INT));
}
else if (myExpr.equals(expr.getArrayExpression())) {
if (myForCompletion) {
@@ -848,14 +795,13 @@
parent.accept(visitor);
ExpectedTypeInfo[] componentTypeInfo = visitor.getResult();
if (componentTypeInfo.length == 0) {
- myResult = anyArrayType();
+ myResult.addAll(anyArrayType());
}
else {
- myResult = new ExpectedTypeInfoImpl[componentTypeInfo.length];
for (int i = 0; i < componentTypeInfo.length; i++) {
ExpectedTypeInfo compInfo = componentTypeInfo[i];
PsiType expectedArrayType = compInfo.getType().createArrayType();
- myResult[i] = createInfoImpl(expectedArrayType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, expectedArrayType, TailType.NONE);
+ myResult.add(createInfoImpl(expectedArrayType, expectedArrayType));
}
}
}
@@ -869,9 +815,7 @@
return;
}
- ExpectedTypeInfo info = createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY,
- PsiType.BOOLEAN, TailType.NONE);
- myResult = new ExpectedTypeInfo[]{info};
+ myResult.add(createInfoImpl(PsiType.BOOLEAN, ExpectedTypeInfo.TYPE_STRICTLY, PsiType.BOOLEAN, TailType.NONE));
}
else if (myExpr.equals(expr.getThenExpression())) {
ExpectedTypeInfo[] types = getExpectedTypes(expr, myForCompletion);
@@ -886,13 +830,13 @@
}
});
}
- myResult = types;
+ Collections.addAll(myResult, types);
}
else {
if (!myExpr.equals(expr.getElseExpression())) {
LOG.error(Arrays.asList(expr.getChildren()) + "; " + myExpr);
}
- myResult = getExpectedTypes(expr, myForCompletion);
+ Collections.addAll(myResult, getExpectedTypes(expr, myForCompletion));
}
}
@@ -911,18 +855,16 @@
throwsTypes = new PsiClassType[]{exceptionType};
}
- ExpectedTypeInfo[] infos = new ExpectedTypeInfo[throwsTypes.length];
- for (int i = 0; i < infos.length; i++) {
- infos[i] = createInfoImpl(
+ for (int i = 0; i < throwsTypes.length; i++) {
+ myResult.add(createInfoImpl(
myExpr instanceof PsiTypeCastExpression && myForCompletion ?
throwsTypes[i] :
throwableType,
ExpectedTypeInfo.TYPE_OR_SUBTYPE,
throwsTypes[i],
TailType.SEMICOLON
- );
+ ));
}
- myResult = infos;
}
}
@@ -930,7 +872,7 @@
if (codeFragment instanceof PsiExpressionCodeFragment) {
final PsiType type = ((PsiExpressionCodeFragment)codeFragment).getExpectedType();
if (type != null) {
- myResult = new ExpectedTypeInfo[] {createInfoImpl(type, ExpectedTypeInfo.TYPE_OR_SUBTYPE, type, TailType.NONE)};
+ myResult.add(createInfoImpl(type, type));
}
}
}
@@ -1224,16 +1166,13 @@
}
@NotNull
- private ExpectedTypeInfo[] anyArrayType() {
+ private List<ExpectedTypeInfo> anyArrayType() {
PsiType objType = PsiType.getJavaLangObject(myExpr.getManager(), myExpr.getResolveScope()).createArrayType();
- ExpectedTypeInfo info = createInfoImpl(objType, ExpectedTypeInfo.TYPE_OR_SUBTYPE, objType,
- TailType.NONE);
- ExpectedTypeInfo info1 = createInfoImpl(PsiType.DOUBLE.createArrayType(), ExpectedTypeInfo.TYPE_OR_SUBTYPE,
- PsiType.INT.createArrayType(), TailType.NONE);
+ ExpectedTypeInfo info = createInfoImpl(objType, objType);
+ ExpectedTypeInfo info1 = createInfoImpl(PsiType.DOUBLE.createArrayType(), PsiType.INT.createArrayType());
PsiType booleanType = PsiType.BOOLEAN.createArrayType();
- ExpectedTypeInfo info2 = createInfoImpl(booleanType, ExpectedTypeInfo.TYPE_STRICTLY, booleanType,
- TailType.NONE);
- return new ExpectedTypeInfo[]{info, info1, info2};
+ ExpectedTypeInfo info2 = createInfoImpl(booleanType, ExpectedTypeInfo.TYPE_STRICTLY, booleanType, TailType.NONE);
+ return Arrays.asList(info, info1, info2);
}
@NotNull
diff --git a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java
index fda11fd..394d42a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/ExternalAnnotationsManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -544,27 +544,35 @@
final XmlTag rootTag = document.getRootTag();
final String externalName = getExternalName(listOwner, false);
if (rootTag != null) {
+ XmlTag anchor = null;
for (XmlTag item : rootTag.getSubTags()) {
- if (Comparing.strEqual(StringUtil.unescapeXml(item.getAttributeValue("name")), externalName)) {
+ int compare = Comparing.compare(externalName, StringUtil.unescapeXml(item.getAttributeValue("name")));
+ if (compare == 0) {
+ anchor = null;
for (XmlTag annotation : item.getSubTags()) {
- if (Comparing.strEqual(annotation.getAttributeValue("name"), annotationFQName)) {
+ compare = Comparing.compare(annotationFQName, annotation.getAttributeValue("name"));
+ if (compare == 0) {
annotation.delete();
break;
}
+ if (compare < 0) break;
+ anchor = annotation;
}
XmlTag newTag = XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(
createAnnotationTag(annotationFQName, values));
- item.add(newTag);
+ item.addAfter(newTag, anchor);
commitChanges(xmlFile);
notifyAfterAnnotationChanging(listOwner, annotationFQName, true);
return;
}
+ if (compare < 0) break;
+ anchor = item;
}
@NonNls String text =
"<item name=\'" + StringUtil.escapeXml(externalName) + "\'>\n";
text += createAnnotationTag(annotationFQName, values);
text += "</item>";
- rootTag.add(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text));
+ rootTag.addAfter(XmlElementFactory.getInstance(myPsiManager.getProject()).createTagFromText(text), anchor);
}
}
commitChanges(xmlFile);
@@ -604,7 +612,8 @@
}
}
- Collections.sort(itemTags, new Comparator<XmlTag>() {
+ List<XmlTag> sorted = new ArrayList<XmlTag>(itemTags);
+ Collections.sort(sorted, new Comparator<XmlTag>() {
@Override
public int compare(XmlTag item1, XmlTag item2) {
String externalName1 = item1.getAttributeValue("name");
@@ -613,9 +622,11 @@
return externalName1.compareTo(externalName2);
}
});
- for (XmlTag item : itemTags) {
- rootTag.addAfter(item, null);
- item.delete();
+ if (!sorted.equals(itemTags)) {
+ for (XmlTag item : sorted) {
+ rootTag.addAfter(item, null);
+ item.delete();
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
index 81cb9b5..a5431b5 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/AllClassesGetter.java
@@ -23,6 +23,8 @@
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl;
@@ -156,8 +158,13 @@
@Override
public boolean process(PsiClass psiClass) {
- if (parameters.getInvocationCount() < 2 && PsiReferenceExpressionImpl.seemsScrambled(psiClass)) {
- return true;
+ if (parameters.getInvocationCount() < 2) {
+ if (PsiReferenceExpressionImpl.seemsScrambled(psiClass)) {
+ return true;
+ }
+ if (!StringUtil.isCapitalized(psiClass.getName()) && !Registry.is("ide.completion.show.lower.case.classes")) {
+ return true;
+ }
}
assert psiClass != null;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java
index 9411f76..68893c6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/CollectionsUtilityMethodsProvider.java
@@ -17,7 +17,6 @@
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NonNls;
@@ -29,7 +28,6 @@
* @author peter
*/
class CollectionsUtilityMethodsProvider {
- public static final Key<Boolean> COLLECTION_FACTORY = Key.create("CollectionFactory");
private final PsiElement myElement;
private final PsiType myExpectedType;
private final PsiType myDefaultType;
@@ -95,7 +93,6 @@
final JavaMethodCallElement item = new JavaMethodCallElement(method, false, false);
item.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
item.setInferenceSubstitutor(SmartCompletionDecorator.calculateMethodReturnTypeSubstitutor(method, expectedType), myElement);
- item.putUserData(COLLECTION_FACTORY, true);
myResult.consume(item);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/CompletionBundle.java b/java/java-impl/src/com/intellij/codeInsight/completion/CompletionBundle.java
index 0f5942a..0e5ff81 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/CompletionBundle.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/CompletionBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author max
*/
public class CompletionBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.CompletionBundle";
private CompletionBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
index 1cd0983..b17afb7 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionContributor.java
@@ -462,18 +462,30 @@
final PsiNameValuePair[] existingPairs = parameterList.getAttributes();
methods: for (PsiMethod method : annoClass.getMethods()) {
+ if (!(method instanceof PsiAnnotationMethod)) continue;
+
final String attrName = method.getName();
for (PsiNameValuePair apair : existingPairs) {
if (Comparing.equal(apair.getName(), attrName)) continue methods;
}
- result.addElement(new LookupItem<PsiMethod>(method, attrName).setInsertHandler(new InsertHandler<LookupElement>() {
+ LookupElementBuilder element = LookupElementBuilder.createWithIcon(method).withInsertHandler(new InsertHandler<LookupElement>() {
@Override
public void handleInsert(InsertionContext context, LookupElement item) {
final Editor editor = context.getEditor();
TailType.EQ.processTail(editor, editor.getCaretModel().getOffset());
context.setAddCompletionChar(false);
}
- }));
+ });
+
+ PsiAnnotationMemberValue defaultValue = ((PsiAnnotationMethod)method).getDefaultValue();
+ if (defaultValue != null) {
+ Object constant = JavaPsiFacade.getInstance(method.getProject()).getConstantEvaluationHelper().computeConstantExpression(defaultValue);
+ if (constant != null) {
+ element = element.withTailText(" default " + (constant instanceof String ? "\"" + constant + "\"" : constant), true);
+ }
+ }
+
+ result.addElement(element);
}
}
}
@@ -624,7 +636,7 @@
autoImport(file, context.getStartOffset() - 1, context.getEditor());
if (context.getCompletionType() == CompletionType.BASIC) {
- if (semicolonNeeded(context)) {
+ if (semicolonNeeded(context.getEditor(), file, context.getStartOffset())) {
context.setDummyIdentifier(CompletionInitializationContext.DUMMY_IDENTIFIER.trim() + ";");
return;
}
@@ -657,8 +669,15 @@
}
}
- private static boolean semicolonNeeded(CompletionInitializationContext context) {
- HighlighterIterator iterator = ((EditorEx) context.getEditor()).getHighlighter().createIterator(context.getStartOffset());
+ public static boolean semicolonNeeded(final Editor editor, PsiFile file, final int startOffset) {
+ final PsiJavaCodeReferenceElement ref = PsiTreeUtil.findElementOfClassAtOffset(file, startOffset, PsiJavaCodeReferenceElement.class, false);
+ if (ref != null && !(ref instanceof PsiReferenceExpression)) {
+ if (ref.getParent() instanceof PsiTypeElement) {
+ return true;
+ }
+ }
+
+ HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(startOffset);
if (iterator.atEnd()) return false;
if (iterator.getTokenType() == JavaTokenType.IDENTIFIER) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
index cabc5d9..b66073e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
@@ -30,7 +30,6 @@
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.javadoc.PsiDocComment;
-import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
@@ -60,9 +59,6 @@
List<LookupElementWeigher> afterProximity = new ArrayList<LookupElementWeigher>();
afterProximity.add(new PreferContainingSameWords(expectedTypes));
- if (smart) {
- afterProximity.add(new PreferFieldsAndGetters());
- }
afterProximity.add(new PreferShorter(expectedTypes));
CompletionSorter sorter = CompletionSorter.defaultSorter(parameters, result.getPrefixMatcher());
@@ -79,13 +75,13 @@
if (!smart) {
ContainerUtil.addIfNotNull(afterPrefix, preferStatics(position, expectedTypes));
}
- ContainerUtil.addIfNotNull(afterPrefix, recursion(parameters, expectedTypes));
if (!smart && !afterNew) {
afterPrefix.add(new PreferExpected(false, expectedTypes));
}
- Collections.addAll(afterPrefix, new PreferByKindWeigher(type, position), new PreferSimilarlyEnding(expectedTypes),
- new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(),
- new PreferEnumConstants(parameters));
+ afterPrefix.add(new PreferByKindWeigher(type, position));
+ ContainerUtil.addIfNotNull(afterPrefix, recursion(parameters, expectedTypes));
+ Collections.addAll(afterPrefix, new PreferSimilarlyEnding(expectedTypes),
+ new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple());
sorter = sorter.weighAfter("prefix", afterPrefix.toArray(new LookupElementWeigher[afterPrefix.size()]));
sorter = sorter.weighAfter("proximity", afterProximity.toArray(new LookupElementWeigher[afterProximity.size()]));
@@ -428,30 +424,6 @@
}
}
- private static class PreferEnumConstants extends LookupElementWeigher {
- private final CompletionParameters myParameters;
-
- public PreferEnumConstants(CompletionParameters parameters) {
- super("constants");
- myParameters = parameters;
- }
-
- @NotNull
- @Override
- public Comparable weigh(@NotNull LookupElement element) {
- if (element.getObject() instanceof PsiEnumConstant) return -2;
-
- if (!(myParameters.getOriginalFile() instanceof PsiJavaFile)) return -1;
-
- if (PsiKeyword.TRUE.equals(element.getLookupString()) || PsiKeyword.FALSE.equals(element.getLookupString())) {
- boolean inReturn = PsiTreeUtil.getParentOfType(myParameters.getPosition(), PsiReturnStatement.class, false, PsiMember.class) != null;
- return inReturn ? -2 : 0;
- }
-
- return -1;
- }
- }
-
private static class PreferExpected extends LookupElementWeigher {
private final boolean myAcceptClasses;
private final ExpectedTypeInfo[] myExpectedTypes;
@@ -517,21 +489,6 @@
}
}
- private static class PreferFieldsAndGetters extends LookupElementWeigher {
- public PreferFieldsAndGetters() {
- super("fieldsAndGetters");
- }
-
- @NotNull
- @Override
- public Comparable weigh(@NotNull LookupElement element) {
- final Object object = element.getObject();
- if (object instanceof PsiField) return -2;
- if (object instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)object)) return -1;
- return 0;
- }
- }
-
private static class PreferShorter extends LookupElementWeigher {
private final ExpectedTypeInfo[] myExpectedTypes;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
index 8a512dc..a5fd607 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java
@@ -30,10 +30,7 @@
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.NullableLazyKey;
-import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PsiJavaPatterns;
@@ -382,7 +379,7 @@
if (isInExcludedPackage((PsiMember)o, true)) {
continue;
}
- mentioned.add((PsiMember)o);
+ mentioned.add(CompletionUtil.getOriginalOrSelf((PsiMember)o));
}
set.add(highlightIfNeeded(qualifierType, castQualifier(item, castItem, plainQualifier, processor), o));
}
@@ -449,7 +446,7 @@
PsiSubstitutor plainSub = plainResult.getSubstitutor();
PsiSubstitutor castSub = TypeConversionUtil.getSuperClassSubstitutor(plainClass, (PsiClassType)castType);
if (method.getSignature(plainSub).equals(method.getSignature(castSub)) &&
- plainSub.substitute(method.getReturnType()).equals(castSub.substitute(method.getReturnType())) &&
+ Comparing.equal(plainSub.substitute(method.getReturnType()), castSub.substitute(method.getReturnType())) &&
processor.isAccessible(plainClass.findMethodBySignature(method, true))
) {
return item;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
index ad2989f..a174ef4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaNoVariantsDelegator.java
@@ -116,7 +116,7 @@
private static void suggestChainedCalls(CompletionParameters parameters, CompletionResultSet result, PsiElement position) {
PsiElement parent = position.getParent();
- if (!(parent instanceof PsiJavaCodeReferenceElement)) {
+ if (!(parent instanceof PsiJavaCodeReferenceElement) || parent.getParent() instanceof PsiImportStatementBase) {
return;
}
PsiElement qualifier = ((PsiJavaCodeReferenceElement)parent).getQualifier();
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java
index c1bfeda..43c19b0 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -27,6 +27,7 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.reference.SoftReference;
import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -48,8 +49,8 @@
public JavaPsiClassReferenceElement(PsiClass psiClass) {
super(psiClass.getName(), psiClass.getName());
- myClass = psiClass.getContainingFile().getVirtualFile() == null ? psiClass : PsiAnchor.create(psiClass);
myQualifiedName = psiClass.getQualifiedName();
+ myClass = psiClass.getContainingFile().getVirtualFile() == null || myQualifiedName == null ? psiClass : PsiAnchor.create(psiClass);
JavaCompletionUtil.setShowFQN(this);
setInsertHandler(AllClassesGetter.TRY_SHORTENING);
setTailType(TailType.NONE);
@@ -85,12 +86,9 @@
@Override
public PsiClass getObject() {
if (myClass instanceof PsiAnchor) {
- Reference<PsiClass> cache = myCache;
- if (cache != null) {
- PsiClass psiClass = cache.get();
- if (psiClass != null) {
- return psiClass;
- }
+ PsiClass psiClass = SoftReference.dereference(myCache);
+ if (psiClass != null) {
+ return psiClass;
}
final PsiClass retrieve = (PsiClass)((PsiAnchor)myClass).retrieve();
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
index bcfa4f0..1e0fa6c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaSmartCompletionContributor.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,7 +19,10 @@
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.util.Key;
-import com.intellij.patterns.*;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.patterns.PatternCondition;
+import com.intellij.patterns.PsiElementPattern;
+import com.intellij.patterns.PsiJavaPatterns;
import com.intellij.psi.*;
import com.intellij.psi.filters.ElementExtractorFilter;
import com.intellij.psi.filters.ElementFilter;
@@ -37,7 +40,7 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
@@ -299,10 +302,10 @@
});
final Key<PsiTryStatement> tryKey = Key.create("try");
- extend(CompletionType.SMART, psiElement().afterLeaf(
- psiElement().withText("("))
- .withSuperParent(3, psiElement(PsiCatchSection.class).withParent(
- psiElement(PsiTryStatement.class).save(tryKey))), new CompletionProvider<CompletionParameters>() {
+ extend(CompletionType.SMART, psiElement().insideStarting(
+ psiElement(PsiTypeElement.class).withParent(
+ psiElement(PsiCatchSection.class).withParent(
+ psiElement(PsiTryStatement.class).save(tryKey)))), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull final CompletionParameters parameters, final ProcessingContext context, @NotNull final CompletionResultSet result) {
final PsiCodeBlock tryBlock = context.get(tryKey).getTryBlock();
@@ -435,13 +438,13 @@
@Override
public boolean isClassAcceptable(Class hintClass) {
- if (ReflectionCache.isAssignable(PsiClass.class, hintClass)) {
+ if (ReflectionUtil.isAssignable(PsiClass.class, hintClass)) {
return acceptClasses;
}
- if (ReflectionCache.isAssignable(PsiVariable.class, hintClass) ||
- ReflectionCache.isAssignable(PsiMethod.class, hintClass) ||
- ReflectionCache.isAssignable(CandidateInfo.class, hintClass)) {
+ if (ReflectionUtil.isAssignable(PsiVariable.class, hintClass) ||
+ ReflectionUtil.isAssignable(PsiMethod.class, hintClass) ||
+ ReflectionUtil.isAssignable(CandidateInfo.class, hintClass)) {
return acceptMembers;
}
return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
index 6e2c627..e8c828a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
@@ -28,6 +28,7 @@
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.proximity.KnownElementWeigher;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
@@ -112,9 +113,12 @@
qualifiedWithField,
qualifiedWithGetter,
superMethodParameters,
+ expectedTypeConstant,
+ field,
+ getter,
normal,
collectionFactory,
- expectedTypeMember,
+ expectedTypeMethod,
suitableClass,
nonInitialized,
classLiteral,
@@ -134,6 +138,10 @@
if (PsiKeyword.ELSE.equals(keyword) || PsiKeyword.FINALLY.equals(keyword)) {
return MyResult.probableKeyword;
}
+ if (PsiKeyword.TRUE.equals(keyword) || PsiKeyword.FALSE.equals(keyword)) {
+ boolean inReturn = PsiTreeUtil.getParentOfType(myPosition, PsiReturnStatement.class, false, PsiMember.class) != null;
+ return inReturn ? MyResult.probableKeyword : MyResult.normal;
+ }
}
if (myCompletionType == CompletionType.SMART) {
@@ -147,11 +155,15 @@
}
if (myCompletionType == CompletionType.SMART) {
- if (item.getUserData(CollectionsUtilityMethodsProvider.COLLECTION_FACTORY) != null) {
- return MyResult.collectionFactory;
+ if (object instanceof PsiMethod) {
+ PsiClass containingClass = ((PsiMethod)object).getContainingClass();
+ if (containingClass != null && CommonClassNames.JAVA_UTIL_COLLECTIONS.equals(containingClass.getQualifiedName())) {
+ return MyResult.collectionFactory;
+ }
}
- if (Boolean.TRUE.equals(item.getUserData(MembersGetter.EXPECTED_TYPE_INHERITOR_MEMBER))) {
- return MyResult.expectedTypeMember;
+ Boolean expectedTypeMember = item.getUserData(MembersGetter.EXPECTED_TYPE_MEMBER);
+ if (expectedTypeMember != null) {
+ return expectedTypeMember ? (object instanceof PsiField ? MyResult.expectedTypeConstant : MyResult.expectedTypeMethod) : MyResult.classNameOrGlobalStatic;
}
final JavaChainLookupElement chain = item.as(JavaChainLookupElement.CLASS_CONDITION_KEY);
@@ -163,11 +175,14 @@
if (qualifier instanceof PsiField) {
return MyResult.qualifiedWithField;
}
- if (qualifier instanceof PsiMethod && PropertyUtil.isSimplePropertyGetter((PsiMethod)qualifier)) {
+ if (isGetter(qualifier)) {
return MyResult.qualifiedWithGetter;
}
}
+ if (object instanceof PsiField) return MyResult.field;
+ if (isGetter(object)) return MyResult.getter;
+
return MyResult.normal;
}
@@ -200,6 +215,15 @@
return MyResult.normal;
}
+ private static boolean isGetter(Object object) {
+ if (!(object instanceof PsiMethod)) return false;
+
+ PsiMethod method = (PsiMethod)object;
+ if (!PropertyUtil.hasGetterName(method)) return false;
+
+ return !KnownElementWeigher.isGetClass(method);
+ }
+
private static boolean isLastStatement(PsiStatement statement) {
if (statement == null || !(statement.getParent() instanceof PsiCodeBlock)) {
return true;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java
index 73a9e5e..b61c8a2 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/RecursionWeigher.java
@@ -28,10 +28,11 @@
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
import com.intellij.psi.filters.element.ExcludeSillyAssignment;
+import com.intellij.psi.impl.search.MethodDeepestSuperSearcher;
import com.intellij.psi.scope.ElementClassFilter;
-import com.intellij.psi.search.searches.DeepestSuperMethodsSearch;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.CommonProcessors;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -209,7 +210,9 @@
@NotNull
public static PsiMethod findDeepestSuper(@NotNull final PsiMethod method) {
- final PsiMethod first = DeepestSuperMethodsSearch.search(method).findFirst();
+ CommonProcessors.FindFirstProcessor<PsiMethod> processor = new CommonProcessors.FindFirstProcessor<PsiMethod>();
+ MethodDeepestSuperSearcher.processDeepestSuperMethods(method, processor);
+ final PsiMethod first = processor.getFoundValue();
return first == null ? method : first;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
index f4adccc..1f951f8 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/ReferenceExpressionCompletionContributor.java
@@ -491,8 +491,13 @@
}
private static boolean shouldChain(PsiElement element, PsiType qualifierType, PsiType expectedType, LookupElement item) {
- if (item.getObject() instanceof PsiMethod) {
- final PsiMethod method = (PsiMethod)item.getObject();
+ Object object = item.getObject();
+ if (object instanceof PsiModifierListOwner && ((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) {
+ return false;
+ }
+
+ if (object instanceof PsiMethod) {
+ final PsiMethod method = (PsiMethod)object;
if (psiMethod().withName("toArray").withParameterCount(1)
.definedInClass(CommonClassNames.JAVA_UTIL_COLLECTION).accepts(method)) {
return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java
index 9a91e8f..e79fe27 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/StaticMemberProcessor.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.
@@ -32,8 +32,6 @@
import java.util.*;
-import static com.intellij.util.containers.ContainerUtil.addIfNotNull;
-
/**
* @author peter
*/
@@ -53,7 +51,7 @@
}
public void importMembersOf(@Nullable PsiClass psiClass) {
- addIfNotNull(myStaticImportedClasses, psiClass);
+ ContainerUtil.addIfNotNull(myStaticImportedClasses, psiClass);
}
public void processStaticMethodsGlobally(final PrefixMatcher matcher, Consumer<LookupElement> consumer) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java
deleted file mode 100644
index 688fada..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/ChainCompletionStringUtil.java
+++ /dev/null
@@ -1,94 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains;
-
-import com.intellij.openapi.util.text.StringUtilRt;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiPrimitiveType;
-import com.intellij.psi.PsiType;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class ChainCompletionStringUtil {
- private ChainCompletionStringUtil() {}
-
- public static boolean isPrimitiveOrArray(final @Nullable String typeQName) {
- return typeQName != null && (typeQName.endsWith("[]") || PRIMITIVES_NAMES.contains(typeQName));
- }
-
- /**
- * CAUTION: isPrimitiveOrArrayOfPrimitives("java.lang.String") == true,
- * isPrimitiveOrArrayOfPrimitives("java.lang.Object") == true
- * isPrimitiveOrArrayOfPrimitives("java.lang.Class") == true
- */
- public static boolean isPrimitiveOrArrayOfPrimitives(final String typeQName) {
- if (typeQName == null) {
- return false;
- }
- return PRIMITIVES_NAMES.contains(deleteArraySigns(typeQName));
- }
-
- public static boolean isShortNamePrimitiveOrArrayOfPrimitives(final @Nullable String shortName) {
- if (shortName == null) {
- return false;
- }
- return PRIMITIVES_SHORT_NAMES.contains(deleteArraySigns(shortName));
- }
-
- private static String deleteArraySigns(final @NotNull String typeName) {
- String nameWithoutArraySign = typeName;
- while (nameWithoutArraySign.endsWith("[]")) {
- nameWithoutArraySign = nameWithoutArraySign.substring(0, nameWithoutArraySign.length() - 2);
- }
- return nameWithoutArraySign;
- }
-
- private static final Set<String> PRIMITIVES_NAMES = new HashSet<String>();
-
- static {
- fillPrimitivesNames(PsiType.BOOLEAN);
- fillPrimitivesNames(PsiType.INT);
- fillPrimitivesNames(PsiType.LONG);
- fillPrimitivesNames(PsiType.DOUBLE);
- fillPrimitivesNames(PsiType.FLOAT);
- fillPrimitivesNames(PsiType.SHORT);
- fillPrimitivesNames(PsiType.CHAR);
- fillPrimitivesNames(PsiType.BYTE);
- fillPrimitivesNames(PsiType.VOID);
- PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_STRING);
- PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_OBJECT);
- PRIMITIVES_NAMES.add(CommonClassNames.JAVA_LANG_CLASS);
- }
-
- private static void fillPrimitivesNames(final PsiPrimitiveType type) {
- PRIMITIVES_NAMES.add(type.getBoxedTypeName());
- PRIMITIVES_NAMES.add(type.getCanonicalText());
- }
-
- private static final Set<String> PRIMITIVES_SHORT_NAMES = new HashSet<String>();
-
- static {
- fillPrimitivesShortNames(PsiType.BOOLEAN);
- fillPrimitivesShortNames(PsiType.INT);
- fillPrimitivesShortNames(PsiType.LONG);
- fillPrimitivesShortNames(PsiType.DOUBLE);
- fillPrimitivesShortNames(PsiType.FLOAT);
- fillPrimitivesShortNames(PsiType.SHORT);
- fillPrimitivesShortNames(PsiType.CHAR);
- fillPrimitivesShortNames(PsiType.BYTE);
- fillPrimitivesShortNames(PsiType.VOID);
- PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_STRING));
- PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_OBJECT));
- PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(CommonClassNames.JAVA_LANG_CLASS));
- }
-
- private static void fillPrimitivesShortNames(final PsiPrimitiveType type) {
- PRIMITIVES_SHORT_NAMES.add(StringUtilRt.getShortName(type.getBoxedTypeName()));
- PRIMITIVES_SHORT_NAMES.add(type.getCanonicalText());
- }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java
deleted file mode 100644
index f020afa..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/CompletionContributorPatternUtil.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion;
-
-import com.intellij.codeInsight.completion.CompletionInitializationContext;
-import com.intellij.patterns.ElementPattern;
-import com.intellij.psi.*;
-import com.intellij.psi.impl.source.tree.java.PsiMethodCallExpressionImpl;
-
-import static com.intellij.patterns.PsiJavaPatterns.psiElement;
-import static com.intellij.patterns.StandardPatterns.or;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public final class CompletionContributorPatternUtil {
-
- private CompletionContributorPatternUtil() {}
-
- @SuppressWarnings("unchecked")
- public static ElementPattern<PsiElement> patternForVariableAssignment() {
- final ElementPattern<PsiElement> patternForParent = or(psiElement().withText(CompletionInitializationContext.DUMMY_IDENTIFIER_TRIMMED)
- .afterSiblingSkipping(psiElement(PsiWhiteSpace.class),
- psiElement(PsiJavaToken.class).withText("=")));
-
- return psiElement().withParent(patternForParent).withSuperParent(2, or(psiElement(PsiAssignmentExpression.class),
- psiElement(PsiLocalVariable.class)
- .inside(PsiDeclarationStatement.class)))
- .inside(PsiMethod.class);
- }
-
- public static ElementPattern<PsiElement> patternForMethodParameter() {
- return psiElement().withSuperParent(3, PsiMethodCallExpressionImpl.class);
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java
deleted file mode 100644
index 9b602dc..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsCompletionContributor.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion;
-
-import com.intellij.codeInsight.completion.*;
-import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ContextUtil;
-import com.intellij.codeInsight.completion.methodChains.search.ChainsSearcher;
-import com.intellij.codeInsight.completion.methodChains.search.MethodChainsSearchService;
-import com.intellij.codeInsight.completion.methodChains.search.MethodsChain;
-import com.intellij.codeInsight.completion.methodChains.search.MethodsChainLookupRangingHelper;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexFeature;
-import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.patterns.ElementPattern;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.searches.DirectClassInheritorsSearch;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.ProcessingContext;
-import com.intellij.util.Processor;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.FactoryMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-import static com.intellij.patterns.PsiJavaPatterns.or;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MethodsChainsCompletionContributor extends CompletionContributor {
- public static final int INVOCATIONS_THRESHOLD = 3;
-
- private final static int MAX_SEARCH_RESULT_SIZE = 5;
- private final static int MAX_CHAIN_SIZE = 4;
- private final static int FILTER_RATIO = 10;
-
- @Override
- public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
- if (parameters.getInvocationCount() >= INVOCATIONS_THRESHOLD && CompilerOutputIndexFeature.METHOD_CHAINS_COMPLETION.isEnabled()) {
- super.fillCompletionVariants(parameters, result);
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- result.stopHere();
- }
- }
- }
-
- @SuppressWarnings("unchecked")
- public MethodsChainsCompletionContributor() {
- final ElementPattern<PsiElement> pattern =
- or(CompletionContributorPatternUtil.patternForMethodParameter(), CompletionContributorPatternUtil.patternForVariableAssignment());
- extend(CompletionType.BASIC, pattern, new CompletionProvider<CompletionParameters>() {
- @Override
- protected void addCompletions(final @NotNull CompletionParameters parameters,
- final ProcessingContext context,
- final @NotNull CompletionResultSet result) {
- final ChainCompletionContext completionContext = extractContext(parameters);
- if (completionContext == null) return;
-
- final String targetClassQName = completionContext.getTargetQName();
- final Set<String> contextTypesKeysSet = completionContext.getContextTypes();
- final Set<String> contextRelevantTypes = new HashSet<String>(contextTypesKeysSet.size() + 1);
- for (final String type : contextTypesKeysSet) {
- if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(type)) {
- contextRelevantTypes.add(type);
- }
- }
- contextRelevantTypes.remove(targetClassQName);
-
- final List<LookupElement> foundElements = searchForLookups(targetClassQName, contextRelevantTypes, completionContext);
- result.addAllElements(foundElements);
- }
- });
- }
-
- private static List<LookupElement> searchForLookups(final String targetClassQName,
- final Set<String> contextRelevantTypes,
- final ChainCompletionContext completionContext) {
- final MethodChainsSearchService searchService = new MethodChainsSearchService(completionContext.getProject());
- final List<MethodsChain> searchResult =
- searchChains(targetClassQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE, completionContext, searchService);
- if (searchResult.size() < MAX_SEARCH_RESULT_SIZE) {
- final PsiClass aClass = JavaPsiFacade.getInstance(completionContext.getProject())
- .findClass(targetClassQName, GlobalSearchScope.allScope(completionContext.getProject()));
- if (aClass != null) {
- DirectClassInheritorsSearch.search(aClass).forEach(new Processor<PsiClass>() {
- @Override
- public boolean process(final PsiClass psiClass) {
- final String inheritorQName = psiClass.getQualifiedName();
- if (!StringUtil.isEmpty(inheritorQName)) {
- final List<MethodsChain> inheritorFilteredSearchResult = new SmartList<MethodsChain>();
- //noinspection ConstantConditions
- for (final MethodsChain chain : searchChains(inheritorQName, contextRelevantTypes, MAX_SEARCH_RESULT_SIZE, MAX_CHAIN_SIZE,
- completionContext, searchService)) {
- boolean insert = true;
- for (final MethodsChain baseChain : searchResult) {
- final MethodsChain.CompareResult r = MethodsChain.compare(baseChain, chain, completionContext);
- if (r != MethodsChain.CompareResult.NOT_EQUAL) {
- insert = false;
- break;
- }
- }
- if (insert) {
- inheritorFilteredSearchResult.add(chain);
- }
- }
- searchResult.addAll(inheritorFilteredSearchResult);
- }
- return true;
- }
- });
- }
- }
- final List<MethodsChain> chains = searchResult.size() > MAX_CHAIN_SIZE ? chooseHead(searchResult) : searchResult;
- return MethodsChainLookupRangingHelper
- .chainsToWeightableLookupElements(filterTailAndGetSumLastMethodOccurrence(chains), completionContext);
- }
-
- private static List<MethodsChain> chooseHead(final List<MethodsChain> elements) {
- Collections.sort(elements, new Comparator<MethodsChain>() {
- @Override
- public int compare(final MethodsChain o1, final MethodsChain o2) {
- return o2.getChainWeight() - o1.getChainWeight();
- }
- });
- return elements.subList(0, MAX_CHAIN_SIZE);
- }
-
- @SuppressWarnings("unchecked")
- @Nullable
- private static ChainCompletionContext extractContext(final CompletionParameters parameters) {
- final PsiElement parent = PsiTreeUtil
- .getParentOfType(parameters.getPosition(), PsiAssignmentExpression.class, PsiLocalVariable.class, PsiMethodCallExpression.class);
- if (parent == null) {
- return null;
- }
-
- if (parent instanceof PsiAssignmentExpression) {
- return tryExtractContextFromAssignment((PsiAssignmentExpression)parent);
- }
- if (parent instanceof PsiLocalVariable) {
- final PsiLocalVariable localVariable = (PsiLocalVariable)parent;
- return ContextUtil.createContext(localVariable.getType(), localVariable.getName(),
- PsiTreeUtil.getParentOfType(parent, PsiDeclarationStatement.class));
- }
- final PsiMethod method = ((PsiMethodCallExpression)parent).resolveMethod();
- if (method == null) return null;
- final PsiExpression expression = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpression.class);
- final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(parameters.getPosition(), PsiExpressionList.class);
- if (expressionList == null) return null;
- final int exprPosition = Arrays.asList(expressionList.getExpressions()).indexOf(expression);
- final PsiParameter[] methodParameters = method.getParameterList().getParameters();
- if (exprPosition < methodParameters.length) {
- final PsiParameter methodParameter = methodParameters[exprPosition];
- return ContextUtil
- .createContext(methodParameter.getType(), null, PsiTreeUtil.getParentOfType(expression, PsiDeclarationStatement.class));
- }
- return null;
- }
-
- @Nullable
- private static ChainCompletionContext tryExtractContextFromAssignment(final PsiAssignmentExpression assignmentExpression) {
- final PsiType type = assignmentExpression.getLExpression().getType();
- final PsiIdentifier identifier = PsiTreeUtil.getChildOfType(assignmentExpression.getLExpression(), PsiIdentifier.class);
- if (identifier == null) return null;
- final String identifierText = identifier.getText();
- return ContextUtil.createContext(type, identifierText, assignmentExpression);
- }
-
- private static List<MethodsChain> filterTailAndGetSumLastMethodOccurrence(final List<MethodsChain> chains) {
- int maxWeight = 0;
- for (final MethodsChain chain : chains) {
- final int chainWeight = chain.getChainWeight();
- if (chainWeight > maxWeight) {
- maxWeight = chainWeight;
- }
- }
-
- final List<MethodsChain> filteredResult = new ArrayList<MethodsChain>();
- for (final MethodsChain chain : chains) {
- final int chainWeight = chain.getChainWeight();
- if (chainWeight * FILTER_RATIO >= maxWeight) {
- filteredResult.add(chain);
- }
- }
- return filteredResult;
- }
-
- private static List<MethodsChain> searchChains(final String targetQName,
- final Set<String> contextVarsQNames,
- final int maxResultSize,
- final int maxChainSize,
- final ChainCompletionContext context,
- final MethodChainsSearchService searchService) {
- return ChainsSearcher.search(searchService, targetQName, contextVarsQNames, maxResultSize, maxChainSize,
- createNotDeprecatedMethodsResolver(JavaPsiFacade.getInstance(context.getProject()),
- context.getResolveScope()), context.getExcludedQNames(), context);
- }
-
- private static FactoryMap<MethodIncompleteSignature, PsiMethod[]> createNotDeprecatedMethodsResolver(final JavaPsiFacade javaPsiFacade,
- final GlobalSearchScope scope) {
- return new FactoryMap<MethodIncompleteSignature, PsiMethod[]>() {
- @Nullable
- @Override
- protected PsiMethod[] create(final MethodIncompleteSignature signature) {
- return signature.resolveNotDeprecated(javaPsiFacade, scope);
- }
- };
- }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java
deleted file mode 100644
index 57293ca..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/MethodsChainsWeigher.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.completion.methodChains.completion;
-
-import com.intellij.codeInsight.completion.CompletionLocation;
-import com.intellij.codeInsight.completion.CompletionWeigher;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
-import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
-import com.intellij.codeInsight.lookup.LookupElement;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MethodsChainsWeigher extends CompletionWeigher {
- @Override
- public Comparable weigh(@NotNull final LookupElement element, @NotNull final CompletionLocation location) {
- if (element instanceof WeightableChainLookupElement) {
- return ((WeightableChainLookupElement)element).getChainRelevance();
- }
- return ChainRelevance.LOWEST;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java
deleted file mode 100644
index bb8d92d..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContext.java
+++ /dev/null
@@ -1,156 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.context;
-
-import com.intellij.codeInsight.completion.methodChains.search.CachedRelevantStaticMethodSearcher;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.NotNullLazyValue;
-import com.intellij.openapi.util.UserDataHolder;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiVariable;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.util.containers.MultiMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * @author Dmitry Batkovich
- */
-public class ChainCompletionContext {
- private final NotNullLazyValue<String> myContextMethodName = new NotNullLazyValue<String>() {
- @NotNull
- @Override
- protected String compute() {
- return myContextMethod.getName();
- }
- };
- private final PsiMethod myContextMethod;
- private final String myTargetQName;
- private final Set<String> myContainingClassQNames;
- private final MultiMap<String, PsiVariable> myContextVars;
- private final MultiMap<String, PsiMethod> myContainingClassGetters;
- private final MultiMap<String, ContextRelevantVariableGetter> myContextVarsGetters;
- private final Map<String, PsiVariable> myStringVars;
- private final CachedRelevantStaticMethodSearcher myStaticMethodSearcher;
- private final Set<String> myExcludedQNames;
- private final GlobalSearchScope myResolveScope;
- private final Project myProject;
-
- private final NotNullLazyValue<Set<String>> contextTypesQNames = new NotNullLazyValue<Set<String>>() {
- @SuppressWarnings("unchecked")
- @NotNull
- @Override
- protected Set<String> compute() {
- return unionToHashSet(myContainingClassQNames, myContextVars.keySet(), myContainingClassGetters.keySet(),
- myContextVarsGetters.keySet());
- }
- };
-
- public Set<String> getExcludedQNames() {
- return myExcludedQNames;
- }
-
- ChainCompletionContext(final PsiMethod contextMethod,
- final String targetQName,
- final Set<String> containingClassQNames,
- final MultiMap<String, PsiVariable> contextVars,
- final MultiMap<String, PsiMethod> containingClassGetters,
- final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters,
- final Map<String, PsiVariable> stringVars,
- final Set<String> excludedQNames,
- final Project project,
- final GlobalSearchScope resolveScope) {
- myContextMethod = contextMethod;
- myTargetQName = targetQName;
- myContainingClassQNames = containingClassQNames;
- myContextVars = contextVars;
- myContainingClassGetters = containingClassGetters;
- myContextVarsGetters = contextVarsGetters;
- myStringVars = stringVars;
- myExcludedQNames = excludedQNames;
- myResolveScope = resolveScope;
- myProject = project;
- myStaticMethodSearcher = new CachedRelevantStaticMethodSearcher(project, resolveScope);
- }
-
- public PsiMethod getContextMethod() {
- return myContextMethod;
- }
-
- public String getContextMethodName() {
- return myContextMethodName.getValue();
- }
-
- public String getTargetQName() {
- return myTargetQName;
- }
-
- @Nullable
- public PsiVariable findRelevantStringInContext(@Nullable final String stringParamName) {
- if (stringParamName == null) {
- return null;
- }
- for (final Map.Entry<String, PsiVariable> e : myStringVars.entrySet()) {
- if (ChainCompletionContextStringUtil.isSimilar(e.getKey(), stringParamName)) {
- return e.getValue();
- }
- }
- return null;
- }
-
- public Set<String> getContainingClassQNames() {
- return myContainingClassQNames;
- }
-
- public Collection<PsiVariable> getVariables(final String typeQName) {
- return myContextVars.get(typeQName);
- }
-
- public Collection<PsiMethod> getContainingClassMethods(final String typeQName) {
- return myContainingClassGetters.get(typeQName);
- }
-
- public Collection<ContextRelevantStaticMethod> getRelevantStaticMethods(final String typeQName, final int weight) {
- return myStaticMethodSearcher.getRelevantStaticMethods(typeQName, weight, this);
- }
-
- public Collection<ContextRelevantVariableGetter> getRelevantVariablesGetters(final String typeQName) {
- return myContextVarsGetters.get(typeQName);
- }
-
- public Collection<?> getContextRefElements(final String typeQName) {
- final Collection<PsiVariable> variables = getVariables(typeQName);
- final Collection<PsiMethod> containingClassMethods = getContainingClassMethods(typeQName);
- final Collection<UserDataHolder> refElements = new ArrayList<UserDataHolder>(variables.size() + containingClassMethods.size());
- refElements.addAll(variables);
- refElements.addAll(containingClassMethods);
- for (final ContextRelevantVariableGetter contextRelevantVariableGetter : getRelevantVariablesGetters(typeQName)) {
- refElements.add(contextRelevantVariableGetter.createLookupElement());
- }
- return refElements;
- }
-
- public boolean contains(@Nullable final String typeQualifierName) {
- return typeQualifierName != null && contextTypesQNames.getValue().contains(typeQualifierName);
- }
-
- public Set<String> getContextTypes() {
- return contextTypesQNames.getValue();
- }
-
- public GlobalSearchScope getResolveScope() {
- return myResolveScope;
- }
-
- public Project getProject() {
- return myProject;
- }
-
- private static <T> HashSet<T> unionToHashSet(final Collection<T>... collections) {
- final HashSet<T> res = new HashSet<T>();
- for (final Collection<T> set : collections) {
- res.addAll(set);
- }
- return res;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java
deleted file mode 100644
index a9b1903..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ChainCompletionContextStringUtil.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.context;
-
-import com.intellij.openapi.util.text.StringUtil;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author Dmitry Batkovich
- */
-class ChainCompletionContextStringUtil {
-
- private ChainCompletionContextStringUtil(){}
-
- private final static int COMMON_PART_MIN_LENGTH = 3;
-
- public static boolean isSimilar(@NotNull final String varName,
- @NotNull final String parameterName) {
- final String sanitizedParamName = sanitizedToLowerCase(parameterName);
- if (StringUtil.commonPrefix(varName, sanitizedParamName).length() >= COMMON_PART_MIN_LENGTH) {
- return true;
- }
- final String suffix = StringUtil.commonSuffix(varName, sanitizedParamName);
- return suffix.length() >= COMMON_PART_MIN_LENGTH;
- }
-
- @NotNull
- public static String sanitizedToLowerCase(@NotNull final String name) {
- final StringBuilder result = new StringBuilder();
- for (int i = 0; i < name.length(); i++) {
- final char ch = name.charAt(i);
- if (Character.isLetter(ch)) {
- result.append(Character.toLowerCase(ch));
- }
- }
- return result.toString();
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java
deleted file mode 100644
index 23b1c26..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantStaticMethod.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.context;
-
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.StaticMethodSubLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiVariable;
-import gnu.trove.TIntObjectHashMap;
-import gnu.trove.TIntObjectProcedure;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author Dmitry Batkovich
- */
-public class ContextRelevantStaticMethod {
- private final PsiMethod psiMethod;
- @Nullable
- private final TIntObjectHashMap<SubLookupElement> parameters;
-
- public ContextRelevantStaticMethod(final PsiMethod psiMethod, @Nullable final TIntObjectHashMap<PsiVariable> parameters) {
- this.psiMethod = psiMethod;
- if (parameters == null) {
- this.parameters = null;
- } else {
- this.parameters = new TIntObjectHashMap<SubLookupElement>(parameters.size());
- parameters.forEachEntry(new TIntObjectProcedure<PsiVariable>() {
- @SuppressWarnings("ConstantConditions")
- @Override
- public boolean execute(final int pos, final PsiVariable var) {
- ContextRelevantStaticMethod.this.parameters.put(pos, new VariableSubLookupElement(var));
- return false;
- }
- });
- }
- }
-
- private SubLookupElement cachedLookupElement;
-
- public SubLookupElement createLookupElement() {
- if (cachedLookupElement == null) {
- cachedLookupElement = new StaticMethodSubLookupElement(psiMethod, parameters);
- }
- return cachedLookupElement;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java
deleted file mode 100644
index fec1cfd..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextRelevantVariableGetter.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.context;
-
-import com.intellij.codeInsight.completion.JavaChainLookupElement;
-import com.intellij.codeInsight.completion.JavaMethodCallElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.VariableLookupItem;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiVariable;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class ContextRelevantVariableGetter {
- private final PsiVariable myVariable;
- private final PsiMethod myMethod;
-
- public ContextRelevantVariableGetter(final PsiVariable variable, final PsiMethod method) {
- myVariable = variable;
- myMethod = method;
- }
-
- public SubLookupElement createSubLookupElement() {
- return new GetterLookupSubLookupElement(myVariable.getName(), myMethod.getName());
- }
-
- public LookupElement createLookupElement() {
- return new JavaChainLookupElement(new VariableLookupItem(myVariable), new JavaMethodCallElement(myMethod));
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java
deleted file mode 100644
index da17e4d..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/context/ContextUtil.java
+++ /dev/null
@@ -1,248 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.context;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.MultiMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * @author Dmitry Batkovich
- */
-public class ContextUtil {
- @Nullable
- public static ChainCompletionContext createContext(final @Nullable PsiType variableType,
- final @Nullable String variableName,
- final @Nullable PsiElement containingElement) {
- if (variableType == null || containingElement == null) {
- return null;
- }
- if (variableType instanceof PsiClassType) {
- final PsiClass aClass = ((PsiClassType)variableType).resolve();
- if (aClass != null) {
- if (aClass.hasTypeParameters()) {
- return null;
- }
- }
- else {
- return null;
- }
- }
-
- final String targetQName = variableType.getCanonicalText();
- if (targetQName == null || targetQName.endsWith("[]")) {
- return null;
- }
-
- final PsiMethod method = PsiTreeUtil.getParentOfType(containingElement, PsiMethod.class);
- if (method == null) {
- return null;
- }
- final PsiClass aClass = method.getContainingClass();
- if (aClass == null) {
- return null;
- }
- final Set<String> containingClassQNames = resolveSupersNamesRecursively(aClass);
-
- final List<PsiVariable> contextVars = new SmartList<PsiVariable>();
- for (final PsiField field : aClass.getFields()) {
- final PsiClass containingClass = field.getContainingClass();
- if (containingClass != null) {
- if ((field.hasModifierProperty(PsiModifier.PUBLIC) ||
- field.hasModifierProperty(PsiModifier.PROTECTED) ||
- ((field.hasModifierProperty(PsiModifier.PRIVATE) || field.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) &&
- aClass.isEquivalentTo(containingClass))) && !field.getName().equals(variableName)) {
- contextVars.add(field);
- }
- }
- }
- Collections.addAll(contextVars, method.getParameterList().getParameters());
-
- final PsiCodeBlock methodBody = method.getBody();
- assert methodBody != null;
- boolean processMethodTail = false;
- final List<PsiElement> afterElements = new ArrayList<PsiElement>();
- for (final PsiElement element : methodBody.getChildren()) {
- if (element.isEquivalentTo(containingElement)) {
- if (variableType instanceof PsiClassType) {
- processMethodTail = true;
- continue;
- }
- else {
- break;
- }
- }
- if (element instanceof PsiDeclarationStatement) {
- if (processMethodTail) {
- afterElements.add(element);
- }
- else {
- for (final PsiElement declaredElement : ((PsiDeclarationStatement)element).getDeclaredElements()) {
- if (declaredElement instanceof PsiLocalVariable &&
- (variableName == null || !variableName.equals(((PsiLocalVariable)declaredElement).getName()))) {
- contextVars.add((PsiVariable)declaredElement);
- }
- }
- }
- }
- }
-
- final Set<String> excludedQNames = processMethodTail
- ? generateExcludedQNames(afterElements, ((PsiClassType)variableType).resolve(), variableName,
- contextVars)
- : Collections.<String>emptySet();
-
- final List<PsiMethod> contextMethods = new ArrayList<PsiMethod>();
- for (final PsiMethod psiMethod : aClass.getMethods()) {
- if ((psiMethod.hasModifierProperty(PsiModifier.PROTECTED) || psiMethod.hasModifierProperty(PsiModifier.PRIVATE)) &&
- psiMethod.getParameterList().getParametersCount() == 0) {
- contextMethods.add(psiMethod);
- }
- }
-
- return create(method, targetQName, contextVars, contextMethods, containingClassQNames, containingElement.getProject(),
- containingElement.getResolveScope(), excludedQNames);
- }
-
- private static Set<String> generateExcludedQNames(final List<PsiElement> tailElements,
- final @Nullable PsiClass psiClass,
- final @Nullable String varName,
- final List<PsiVariable> contextVars) {
- if (psiClass == null) {
- return Collections.emptySet();
- }
- final String classQName = psiClass.getQualifiedName();
- if (classQName == null) {
- return Collections.emptySet();
- }
-
- final Set<String> excludedQNames = new HashSet<String>();
- if (!tailElements.isEmpty()) {
- final Set<String> contextVarTypes = new HashSet<String>();
- final Map<String, PsiVariable> contextVarNamesToVar = new HashMap<String, PsiVariable>();
- for (final PsiVariable var : contextVars) {
- contextVarTypes.add(var.getType().getCanonicalText());
- contextVarNamesToVar.put(var.getName(), var);
- }
- for (final PsiElement element : tailElements) {
- final Collection<PsiMethodCallExpression> methodCallExpressions =
- PsiTreeUtil.findChildrenOfType(element, PsiMethodCallExpression.class);
- for (final PsiMethodCallExpression methodCallExpression : methodCallExpressions) {
- final PsiExpressionList args = methodCallExpression.getArgumentList();
- final PsiMethod resolvedMethod = methodCallExpression.resolveMethod();
- if (resolvedMethod != null) {
- final PsiType returnType = resolvedMethod.getReturnType();
- if (returnType != null) {
- final String returnTypeAsString = returnType.getCanonicalText();
- for (final PsiExpression expression : args.getExpressions()) {
- final String qVarName = expression.getText();
- if (qVarName != null) {
- if (contextVarNamesToVar.containsKey(qVarName) || qVarName.equals(varName)) {
- excludedQNames.add(returnTypeAsString);
- }
- }
- }
- if (!contextVarTypes.contains(returnTypeAsString)) {
- excludedQNames.add(returnTypeAsString);
- }
- }
- }
- }
- }
- }
-
- return excludedQNames;
- }
-
- @Nullable
- private static ChainCompletionContext create(final PsiMethod contextMethod,
- final String targetQName,
- final List<PsiVariable> contextVars,
- final List<PsiMethod> contextMethods,
- final Set<String> containingClassQNames,
- final Project project,
- final GlobalSearchScope resolveScope,
- final Set<String> excludedQNames) {
- final MultiMap<String, PsiVariable> classQNameToVariable = new MultiMap<String, PsiVariable>();
- final MultiMap<String, PsiMethod> containingClassGetters = new MultiMap<String, PsiMethod>();
- final MultiMap<String, ContextRelevantVariableGetter> contextVarsGetters = new MultiMap<String, ContextRelevantVariableGetter>();
- final Map<String, PsiVariable> stringVars = new HashMap<String, PsiVariable>();
-
- for (final PsiMethod method : contextMethods) {
- PsiType returnType = method.getReturnType();
- if (returnType != null) {
- final String returnTypeQName = returnType.getCanonicalText();
- if (returnTypeQName != null) {
- containingClassGetters.putValue(returnTypeQName, method);
- }
- }
- }
-
- for (final PsiVariable var : contextVars) {
- final PsiType type = var.getType();
- final Set<String> classQNames = new HashSet<String>();
- if (type instanceof PsiClassType) {
- if (JAVA_LANG_STRING_SHORT_NAME.equals(((PsiClassType)type).getClassName())) {
- final String varName = var.getName();
- if (varName != null) {
- stringVars.put(ChainCompletionContextStringUtil.sanitizedToLowerCase(varName), var);
- continue;
- }
- }
-
- final PsiClass aClass = ((PsiClassType)type).resolve();
- if (aClass != null) {
- final String classQName = type.getCanonicalText();
- if (!targetQName.equals(classQName)) {
- classQNames.add(classQName);
- classQNames.addAll(resolveSupersNamesRecursively(aClass));
- for (final PsiMethod method : aClass.getAllMethods()) {
- if (method.getParameterList().getParametersCount() == 0 && method.getName().startsWith("get")) {
- final String getterReturnTypeQName = method.getReturnType().getCanonicalText();
- if (getterReturnTypeQName != null) {
- contextVarsGetters.putValue(getterReturnTypeQName, new ContextRelevantVariableGetter(var, method));
- }
- }
- }
- }
- }
- }
- else {
- final String classQName = type.getCanonicalText();
- if (classQName != null) {
- classQNames.add(classQName);
- }
- }
- for (final String qName : classQNames) {
- classQNameToVariable.putValue(qName, var);
- }
- }
- return new ChainCompletionContext(contextMethod, targetQName, containingClassQNames, classQNameToVariable, containingClassGetters,
- contextVarsGetters, stringVars, excludedQNames, project, resolveScope);
- }
-
- @NotNull
- private static Set<String> resolveSupersNamesRecursively(@Nullable final PsiClass psiClass) {
- final Set<String> result = new HashSet<String>();
- if (psiClass != null) {
- for (final PsiClass superClass : psiClass.getSupers()) {
- final String qualifiedName = superClass.getQualifiedName();
- if (!CommonClassNames.JAVA_LANG_OBJECT.equals(qualifiedName)) {
- if (qualifiedName != null) {
- result.add(qualifiedName);
- }
- result.addAll(resolveSupersNamesRecursively(superClass));
- }
- }
- }
- return result;
- }
-
- private final static String JAVA_LANG_STRING_SHORT_NAME = StringUtil.getShortName(CommonClassNames.JAVA_LANG_STRING);
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java
deleted file mode 100644
index 65be892..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionLookupElementUtil.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup;
-
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.LookupElementBuilder;
-import com.intellij.psi.PsiKeyword;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiModifier;
-import com.intellij.psi.PsiParameter;
-import gnu.trove.TIntObjectHashMap;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class ChainCompletionLookupElementUtil {
- private ChainCompletionLookupElementUtil() {
- }
-
- public static LookupElement createLookupElement(final PsiMethod method,
- final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
- if (method.isConstructor()) {
- //noinspection ConstantConditions
- return LookupElementBuilder.create(String.format("%s %s", PsiKeyword.NEW, method.getContainingClass().getName()));
- } else if (method.hasModifierProperty(PsiModifier.STATIC)) {
- return new ChainCompletionMethodCallLookupElement(method, replaceElements, false, true);
- } else {
- return new ChainCompletionMethodCallLookupElement(method, replaceElements);
- }
- }
-
- public static String fillMethodParameters(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
- final TIntObjectHashMap<SubLookupElement> notNullReplaceElements = replaceElements == null ?
- new TIntObjectHashMap<SubLookupElement>(0) :
- replaceElements;
-
- final PsiParameter[] parameters = method.getParameterList().getParameters();
- final StringBuilder sb = new StringBuilder();
- for (int i = 0; i < parameters.length; i++) {
- if (i != 0) {
- sb.append(", ");
- }
- final PsiParameter parameter = parameters[i];
- final SubLookupElement replaceElement = notNullReplaceElements.get(i);
- if (replaceElement != null) {
- sb.append(replaceElement.getInsertString());
- } else {
- sb.append(parameter.getName());
- }
- }
- return sb.toString();
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java
deleted file mode 100644
index f7a62d6..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionMethodCallLookupElement.java
+++ /dev/null
@@ -1,88 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup;
-
-import com.intellij.codeInsight.completion.InsertionContext;
-import com.intellij.codeInsight.completion.JavaMethodCallElement;
-import com.intellij.codeInsight.completion.StaticallyImportable;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
-import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
-import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiJavaFile;
-import com.intellij.psi.PsiMethod;
-import gnu.trove.TIntObjectHashMap;
-import gnu.trove.TObjectProcedure;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author Dmitry Batkovich
- */
-public class ChainCompletionMethodCallLookupElement extends JavaMethodCallElement implements StaticallyImportable {
- public static final String PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION = "methods.chain.completion.autoCompletion";
-
- private final PsiMethod myMethod;
- @Nullable
- private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
- private final boolean myMergedOverloads;
-
- public ChainCompletionMethodCallLookupElement(final PsiMethod method,
- final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements,
- final boolean shouldImportStatic,
- final boolean mergedOverloads) {
- super(method, shouldImportStatic, mergedOverloads);
- myMethod = method;
- myReplaceElements = replaceElements;
- myMergedOverloads = mergedOverloads;
- configureAutoCompletionPolicy();
- }
-
- public ChainCompletionMethodCallLookupElement(final PsiMethod method,
- final @Nullable TIntObjectHashMap<SubLookupElement> replaceElements) {
- super(method);
- myMethod = method;
- myReplaceElements = replaceElements;
- myMergedOverloads = true;
- configureAutoCompletionPolicy();
- }
-
- private void configureAutoCompletionPolicy() {
- if (ApplicationManager.getApplication().isUnitTestMode()) {
- if (PropertiesComponent.getInstance(myMethod.getProject()).getBoolean(PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, false)) {
- setAutoCompletionPolicy(AutoCompletionPolicy.GIVE_CHANCE_TO_OVERWRITE);
- }
- }
- }
-
- @Override
- public void handleInsert(final InsertionContext context) {
- super.handleInsert(context);
- if (!myMergedOverloads || isUniqueMethod(myMethod)) {
- context.commitDocument();
- context.getDocument()
- .insertString(context.getTailOffset() - 1, ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
- final PsiFile file = context.getFile();
- assert file instanceof PsiJavaFile;
- final PsiJavaFile javaFile = (PsiJavaFile)file;
- if (myReplaceElements != null) {
- myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
- @Override
- public boolean execute(final SubLookupElement subLookupElement) {
- subLookupElement.doImport(javaFile);
- return true;
- }
- });
- }
- context.commitDocument();
- context.getEditor().getCaretModel().moveToOffset(context.getTailOffset());
- context.commitDocument();
- }
- }
-
-
- private static boolean isUniqueMethod(@NotNull final PsiMethod method) {
- final PsiClass containingClass = method.getContainingClass();
- return containingClass == null || containingClass.findMethodsByName(method.getName(), true).length == 1;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java
deleted file mode 100644
index b775640..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/ChainCompletionNewVariableLookupElement.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup;
-
-import com.intellij.codeInsight.completion.CompletionInitializationContext;
-import com.intellij.codeInsight.completion.InsertionContext;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.LookupElementDecorator;
-import com.intellij.codeInsight.lookup.LookupElementPresentation;
-import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.RangeMarker;
-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.codeStyle.SuggestedNameInfo;
-import com.intellij.psi.codeStyle.VariableKind;
-import com.intellij.psi.util.PsiTreeUtil;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class ChainCompletionNewVariableLookupElement extends LookupElementDecorator<LookupElement> {
- private final static Logger log = Logger.getInstance(ChainCompletionNewVariableLookupElement.class);
-
- private final PsiClass myPsiClass;
- private final String myNewVarName;
-
- public ChainCompletionNewVariableLookupElement(final PsiClass psiClass, final String newVarName, final LookupElement calledMethods) {
- super(calledMethods);
- myNewVarName = newVarName;
- myPsiClass = psiClass;
- }
-
- public static ChainCompletionNewVariableLookupElement create(final PsiClass psiClass, final LookupElement calledMethods) {
- final Project project = psiClass.getProject();
- final String newVarName = chooseLongestName(JavaCodeStyleManager.getInstance(project).
- suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, JavaPsiFacade.getElementFactory(project).createType(psiClass)));
- return new ChainCompletionNewVariableLookupElement(psiClass, newVarName, calledMethods);
- }
-
- @Override
- public void handleInsert(final InsertionContext context) {
- final RangeMarker rangeMarker = context.getDocument().createRangeMarker(context.getStartOffset(), context.getStartOffset());
- getDelegate().handleInsert(context);
- final PsiFile file = context.getFile();
- ((PsiJavaFile)file).importClass(myPsiClass);
- final PsiElement caretElement = file.findElementAt(context.getEditor().getCaretModel().getOffset());
- if (caretElement == null) {
- log.error("element on caret position MUST BE not null");
- return;
- }
- final PsiStatement statement = (PsiStatement) caretElement.getPrevSibling();
- final PsiCodeBlock codeBlock = PsiTreeUtil.getParentOfType(statement, PsiCodeBlock.class);
- if (codeBlock == null) {
- log.error("code block MUST BE not null");
- return;
- }
- final Project project = context.getProject();
- final Ref<PsiElement> insertedStatementRef = Ref.create();
- final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
- context.commitDocument();
- new WriteCommandAction.Simple(project, file) {
- @Override
- protected void run() throws Throwable {
- final PsiStatement statementFromText = elementFactory.createStatementFromText(String.format("%s %s = null;", myPsiClass.getName(), myNewVarName), null);
- insertedStatementRef.set(codeBlock.addBefore(statementFromText, statement));
- }
- }.execute();
- final PsiLiteralExpression nullKeyword = findNull(insertedStatementRef.get());
- PsiDocumentManager.getInstance(context.getProject()).doPostponedOperationsAndUnblockDocument(context.getDocument());
- context.getDocument().insertString(rangeMarker.getStartOffset(), myNewVarName + ".");
- context.commitDocument();
- final int offset = nullKeyword.getTextOffset();
- final int endOffset = offset + nullKeyword.getTextLength();
- context.getEditor().getSelectionModel().setSelection(offset, endOffset);
- context.getEditor().getCaretModel().moveToOffset(offset);
- }
-
- @NotNull
- @Override
- public String getLookupString() {
- return getDelegate().getLookupString();
- }
-
- @Override
- public void renderElement(final LookupElementPresentation presentation) {
- super.renderElement(presentation);
- presentation.setItemText(myNewVarName + "." + presentation.getItemText());
- }
-
- private static PsiLiteralExpression findNull(final PsiElement psiElement) {
- final Collection<PsiLiteralExpression> literalExpressions = PsiTreeUtil.findChildrenOfType(psiElement, PsiLiteralExpression.class);
- for (final PsiLiteralExpression literalExpression : literalExpressions) {
- if (PsiKeyword.NULL.equals(literalExpression.getText())) {
- return literalExpression;
- }
- }
- throw new IllegalArgumentException();
- }
-
- private static String chooseLongestName(final SuggestedNameInfo suggestedNameInfo) {
- final String[] names = suggestedNameInfo.names;
- String longestWord = names[0];
- int maxLength = longestWord.length();
- for (int i = 1; i < names.length; i++) {
- final int length = names[i].length();
- if (length > maxLength) {
- maxLength = length;
- longestWord = names[i];
- }
- }
- return longestWord;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java
deleted file mode 100644
index 16ee646..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/WeightableChainLookupElement.java
+++ /dev/null
@@ -1,23 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup;
-
-import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.LookupElementDecorator;
-import com.intellij.codeInsight.lookup.LookupElementPresentation;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class WeightableChainLookupElement extends LookupElementDecorator<LookupElement> {
- private final ChainRelevance myChainRelevance;
-
- public WeightableChainLookupElement(final @NotNull LookupElement delegate, final ChainRelevance relevance) {
- super(delegate);
- myChainRelevance = relevance;
- }
-
- public ChainRelevance getChainRelevance() {
- return myChainRelevance;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java
deleted file mode 100644
index e6b8410..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/GetterLookupSubLookupElement.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
-
-import com.intellij.psi.PsiJavaFile;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author Dmitry Batkovich
- */
-public class GetterLookupSubLookupElement implements SubLookupElement {
- private final String myVariableName;
- private final String myMethodName;
-
- public GetterLookupSubLookupElement(final String methodName) {
- this(null, methodName);
- }
-
- public GetterLookupSubLookupElement(@Nullable final String variableName, final String methodName) {
- myVariableName = variableName;
- myMethodName = methodName;
- }
-
- @Override
- public void doImport(final PsiJavaFile javaFile) {
- }
-
- @Override
- public String getInsertString() {
- final StringBuilder sb = new StringBuilder();
- if (myVariableName != null) {
- sb.append(myVariableName).append(".");
- }
- sb.append(myMethodName).append("()");
- return sb.toString();
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java
deleted file mode 100644
index 88d8b01..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/StaticMethodSubLookupElement.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
-
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiJavaFile;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiModifier;
-import gnu.trove.TIntObjectHashMap;
-import gnu.trove.TObjectProcedure;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author Dmitry Batkovich
- */
-public class StaticMethodSubLookupElement implements SubLookupElement {
-
- private final PsiMethod myMethod;
- private final TIntObjectHashMap<SubLookupElement> myReplaceElements;
-
- public StaticMethodSubLookupElement(final PsiMethod method, @Nullable final TIntObjectHashMap<SubLookupElement> replaceElements) {
- assert method.hasModifierProperty(PsiModifier.STATIC);
- myReplaceElements = replaceElements;
- myMethod = method;
- }
-
- @Override
- public void doImport(final PsiJavaFile javaFile) {
- final PsiClass containingClass = myMethod.getContainingClass();
- if (containingClass != null) {
- if (javaFile.findImportReferenceTo(containingClass) == null) {
- javaFile.importClass(containingClass);
- }
- }
- if (myReplaceElements != null) {
- myReplaceElements.forEachValue(new TObjectProcedure<SubLookupElement>() {
- @Override
- public boolean execute(final SubLookupElement subLookupElement) {
- subLookupElement.doImport(javaFile);
- return false;
- }
- });
- }
- }
-
- @Override
- public String getInsertString() {
- //noinspection ConstantConditions
- return String.format("%s.%s(%s)", myMethod.getContainingClass().getName(), myMethod.getName(),
- ChainCompletionLookupElementUtil.fillMethodParameters(myMethod, myReplaceElements));
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java
deleted file mode 100644
index 7046012..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/SubLookupElement.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
-
-import com.intellij.psi.PsiJavaFile;
-
-/**
- * @author Dmitry Batkovich
- */
-public interface SubLookupElement {
-
- void doImport(final PsiJavaFile javaFile);
-
- String getInsertString();
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java
deleted file mode 100644
index 894f10b..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/completion/lookup/sub/VariableSubLookupElement.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.completion.lookup.sub;
-
-import com.intellij.psi.PsiJavaFile;
-import com.intellij.psi.PsiVariable;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class VariableSubLookupElement implements SubLookupElement {
-
- private final String myVarName;
-
- public VariableSubLookupElement(final PsiVariable variable) {
- myVarName = variable.getName();
- }
-
- @Override
- public void doImport(final PsiJavaFile javaFile) {
- }
-
- @Override
- public String getInsertString() {
- return myVarName;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java
deleted file mode 100644
index ef11e72..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/CachedRelevantStaticMethodSearcher.java
+++ /dev/null
@@ -1,122 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
-import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
-import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
-import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.util.SmartList;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * @author Dmitry Batkovich
- */
-public class CachedRelevantStaticMethodSearcher {
- private final HashMap<MethodIncompleteSignature, PsiMethod> myCachedResolveResults = new HashMap<MethodIncompleteSignature, PsiMethod>();
- private final MethodsUsageIndex myIndex;
- private final JavaPsiFacade myJavaPsiFacade;
- private final GlobalSearchScope myAllScope;
- private final GlobalSearchScope myResolveScope;
-
- public CachedRelevantStaticMethodSearcher(final Project project, final GlobalSearchScope resolveScope) {
- myIndex = MethodsUsageIndex.getInstance(project);
- myJavaPsiFacade = JavaPsiFacade.getInstance(project);
- myAllScope = GlobalSearchScope.allScope(project);
- myResolveScope = resolveScope;
- }
-
- @NotNull
- public List<ContextRelevantStaticMethod> getRelevantStaticMethods(final String resultQualifiedClassName,
- final int minOccurrence,
- final ChainCompletionContext completionContext) {
- if (resultQualifiedClassName == null ||
- ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(resultQualifiedClassName) ||
- completionContext.getTargetQName().equals(resultQualifiedClassName)) {
- return Collections.emptyList();
- }
- final TreeSet<UsageIndexValue> indexValues = myIndex.getValues(resultQualifiedClassName);
- if (indexValues != null) {
- int occurrences = 0;
- final List<ContextRelevantStaticMethod> relevantMethods = new ArrayList<ContextRelevantStaticMethod>();
- for (final UsageIndexValue indexValue : extractStaticMethods(indexValues)) {
- final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
- final PsiMethod method;
- if (myCachedResolveResults.containsKey(methodInvocation)) {
- method = myCachedResolveResults.get(methodInvocation);
- }
- else {
- final PsiMethod[] methods = methodInvocation.resolveNotDeprecated(myJavaPsiFacade, myAllScope);
- method = MethodChainsSearchUtil
- .getMethodWithMinNotPrimitiveParameters(methods, Collections.singleton(completionContext.getTargetQName()));
- myCachedResolveResults.put(methodInvocation, method);
- if (method == null) {
- return Collections.emptyList();
- }
- }
- if (method == null) {
- return Collections.emptyList();
- }
- if (method.hasModifierProperty(PsiModifier.PUBLIC)) {
- if (isMethodValid(method, completionContext, resultQualifiedClassName)) {
- occurrences += indexValue.getOccurrences();
- if (myResolveScope.contains(method.getContainingFile().getVirtualFile())) {
- relevantMethods.add(new ContextRelevantStaticMethod(method, null));
- }
- if (occurrences >= minOccurrence) {
- return relevantMethods;
- }
- }
- }
- }
- }
- return Collections.emptyList();
- }
-
- private static List<UsageIndexValue> extractStaticMethods(final TreeSet<UsageIndexValue> indexValues) {
- final List<UsageIndexValue> relevantStaticMethods = new SmartList<UsageIndexValue>();
- for (final UsageIndexValue indexValue : indexValues) {
- if (indexValue.getMethodIncompleteSignature().isStatic()) {
- relevantStaticMethods.add(indexValue);
- }
- }
- return relevantStaticMethods;
- }
-
- private static boolean isMethodValid(final @Nullable PsiMethod method,
- final ChainCompletionContext completionContext,
- final String targetTypeShortName) {
- if (method == null) return false;
- for (final PsiParameter parameter : method.getParameterList().getParameters()) {
- final PsiType type = parameter.getType();
- final String shortClassName = typeAsString(type);
- if (targetTypeShortName.equals(shortClassName)) return false;
- if (!ChainCompletionStringUtil.isShortNamePrimitiveOrArrayOfPrimitives(shortClassName) &&
- !completionContext.contains(type.getCanonicalText())) {
- return false;
- }
- }
- return true;
- }
-
-
- @Nullable
- public static String typeAsString(final PsiType type) {
- if (type instanceof PsiClassType)
- return ((PsiClassType) type).getClassName();
- else if (type instanceof PsiPrimitiveType)
- return type.getCanonicalText();
- else if (type instanceof PsiArrayType) {
- final String componentTypeAsString = typeAsString(((PsiArrayType) type).getComponentType());
- if (componentTypeAsString == null) return null;
- return String.format("%s[]", componentTypeAsString);
- }
- return null;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java
deleted file mode 100644
index 0aa7231..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainRelevance.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.TestOnly;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class ChainRelevance implements Comparable<ChainRelevance> {
- public static final ChainRelevance LOWEST = new ChainRelevance(Integer.MAX_VALUE, 0, Integer.MAX_VALUE, Integer.MAX_VALUE, false, false, 0);
-
- private final int myChainSize;
- private final int myLastMethodOccurrences;
- private final int myUnreachableParametersCount;
- private final int myNotMatchedStringVars;
- private final boolean myHasCallingVariableInContext;
- private final boolean myFirstMethodStatic;
- private final int myParametersInContext;
-
- public ChainRelevance(final int chainSize,
- final int lastMethodOccurrences,
- final int unreachableParametersCount,
- final int notMatchedStringVars,
- final boolean hasCallingVariableInContext,
- final boolean firstMethodStatic,
- final int parametersInContext) {
- myChainSize = chainSize;
- myLastMethodOccurrences = lastMethodOccurrences;
- myUnreachableParametersCount = unreachableParametersCount;
- myNotMatchedStringVars = notMatchedStringVars;
- myHasCallingVariableInContext = hasCallingVariableInContext;
- myFirstMethodStatic = firstMethodStatic;
- myParametersInContext = parametersInContext;
- }
-
- @TestOnly
- public boolean hasCallingVariableInContext() {
- return myHasCallingVariableInContext;
- }
-
- @TestOnly
- public int getChainSize() {
- return myChainSize;
- }
-
- @TestOnly
- public int getLastMethodOccurrences() {
- return myLastMethodOccurrences;
- }
-
- @TestOnly
- public int getUnreachableParametersCount() {
- return myUnreachableParametersCount;
- }
-
- @TestOnly
- public int getNotMatchedStringVars() {
- return myNotMatchedStringVars;
- }
-
- @TestOnly
- public boolean isFirstMethodStatic() {
- return myFirstMethodStatic;
- }
-
- @Override
- public int compareTo(@NotNull final ChainRelevance that) {
- if (myHasCallingVariableInContext && !that.myHasCallingVariableInContext) {
- return 1;
- }
- if (that.myHasCallingVariableInContext && !myHasCallingVariableInContext) {
- return -1;
- }
- if (myFirstMethodStatic && !that.myFirstMethodStatic) {
- return -1;
- }
- if (that.myFirstMethodStatic && !myFirstMethodStatic) {
- return 1;
- }
- if (myParametersInContext > that.myParametersInContext) {
- return 1;
- }
- if (myParametersInContext <= that.myParametersInContext) {
- return -1;
- }
- int sub = myLastMethodOccurrences - that.myLastMethodOccurrences;
- if (sub != 0) return sub;
- sub = myUnreachableParametersCount - that.myUnreachableParametersCount;
- if (sub != 0) return -sub;
- return 0;
- }
-
- @Override
- public String toString() {
- return (myFirstMethodStatic ? "1" : "0") +
- (myHasCallingVariableInContext ? "1" : "0") + "_" +
- myLastMethodOccurrences + "_" +
- myUnreachableParametersCount;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java
deleted file mode 100644
index 5ecba09..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ChainsSearcher.java
+++ /dev/null
@@ -1,297 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
-import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
-import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiModifier;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.FactoryMap;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.*;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class ChainsSearcher {
- private ChainsSearcher() {
- }
-
- private static final Logger LOG = Logger.getInstance(ChainsSearcher.class);
- private static final double NEXT_METHOD_IN_CHAIN_RATIO = 1.5;
-
- public static List<MethodsChain> search(final MethodChainsSearchService searchService,
- final String targetQName,
- final Set<String> contextQNames,
- final int maxResultSize,
- final int pathMaximalLength,
- final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
- final Set<String> excludedParamsTypesQNames,
- final ChainCompletionContext context) {
- final SearchInitializer initializer = createInitializer(targetQName, resolver, searchService, excludedParamsTypesQNames);
- return search(searchService, initializer, contextQNames, pathMaximalLength, maxResultSize, resolver, targetQName,
- excludedParamsTypesQNames, context);
- }
-
- private static SearchInitializer createInitializer(final String targetQName,
- final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
- final MethodChainsSearchService searchService,
- final Set<String> excludedParamsTypesQNames) {
- return new SearchInitializer(searchService.getMethods(targetQName), resolver, targetQName, excludedParamsTypesQNames);
- }
-
- @NotNull
- private static List<MethodsChain> search(final MethodChainsSearchService searchService,
- final SearchInitializer initializer,
- final Set<String> toSet,
- final int pathMaximalLength,
- final int maxResultSize,
- final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
- final String targetQName,
- final Set<String> excludedParamsTypesQNames,
- final ChainCompletionContext context) {
- final Set<String> allExcludedNames = MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName);
- final SearchInitializer.InitResult initResult = initializer.init(Collections.<String>emptySet());
-
- final Map<MethodIncompleteSignature, MethodsChain> knownDistance = initResult.getChains();
-
- final List<WeightAware<MethodIncompleteSignature>> allInitialVertexes = initResult.getVertexes();
-
- final LinkedList<WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>> q =
- new LinkedList<WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>>(ContainerUtil.map(allInitialVertexes,
- new Function<WeightAware<MethodIncompleteSignature>, WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>>() {
- @Override
- public WeightAware<Pair<MethodIncompleteSignature, MethodsChain>> fun(
- final WeightAware<MethodIncompleteSignature> methodIncompleteSignatureWeightAware) {
- return new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
- new Pair<MethodIncompleteSignature, MethodsChain>(
- methodIncompleteSignatureWeightAware
- .getUnderlying(),
- new MethodsChain(resolver.get(
- methodIncompleteSignatureWeightAware
- .getUnderlying()),
- methodIncompleteSignatureWeightAware
- .getWeight(),
- methodIncompleteSignatureWeightAware
- .getUnderlying()
- .getOwner())),
- methodIncompleteSignatureWeightAware
- .getWeight());
- }
- }));
-
- int maxWeight = 0;
- for (final MethodsChain methodsChain : knownDistance.values()) {
- if (methodsChain.getChainWeight() > maxWeight) {
- maxWeight = methodsChain.getChainWeight();
- }
- }
-
- final ResultHolder result = new ResultHolder(context);
- while (!q.isEmpty()) {
- ProgressManager.checkCanceled();
- final WeightAware<Pair<MethodIncompleteSignature, MethodsChain>> currentVertex = q.poll();
- final int currentVertexDistance = currentVertex.getWeight();
- final Pair<MethodIncompleteSignature, MethodsChain> currentVertexUnderlying = currentVertex.getUnderlying();
- final MethodsChain currentVertexMethodsChain = knownDistance.get(currentVertexUnderlying.getFirst());
- if (currentVertexDistance != currentVertexMethodsChain.getChainWeight()) {
- continue;
- }
- if (currentVertex.getUnderlying().getFirst().isStatic() || toSet.contains(currentVertex.getUnderlying().getFirst().getOwner())) {
- result.add(currentVertex.getUnderlying().getSecond());
- continue;
- }
- final SortedSet<UsageIndexValue> nextMethods = searchService.getMethods(currentVertexUnderlying.getFirst().getOwner());
- final MaxSizeTreeSet<WeightAware<MethodIncompleteSignature>> currentSignatures =
- new MaxSizeTreeSet<WeightAware<MethodIncompleteSignature>>(maxResultSize);
- for (final UsageIndexValue indexValue : nextMethods) {
- final MethodIncompleteSignature vertex = indexValue.getMethodIncompleteSignature();
- final int occurrences = indexValue.getOccurrences();
- if (vertex.isStatic() || !vertex.getOwner().equals(targetQName)) {
- final int vertexDistance = Math.min(currentVertexDistance, occurrences);
- final MethodsChain knownVertexMethodsChain = knownDistance.get(vertex);
- if ((knownVertexMethodsChain == null || knownVertexMethodsChain.getChainWeight() < vertexDistance)) {
- if (currentSignatures.isEmpty() || currentSignatures.last().getWeight() < vertexDistance) {
- final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
- final PsiMethod[] psiMethods = resolver.get(methodInvocation);
- if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, allExcludedNames)) {
- final MethodsChain newBestMethodsChain =
- currentVertexMethodsChain.addEdge(psiMethods, indexValue.getMethodIncompleteSignature().getOwner(), vertexDistance);
- if (newBestMethodsChain.size() <= pathMaximalLength - 1) {
- currentSignatures
- .add(new WeightAware<MethodIncompleteSignature>(indexValue.getMethodIncompleteSignature(), vertexDistance));
- }
- knownDistance.put(vertex, newBestMethodsChain);
- }
- }
- }
- else {
- break;
- }
- }
- }
- boolean updated = false;
- if (!currentSignatures.isEmpty()) {
- boolean isBreak = false;
- for (final WeightAware<MethodIncompleteSignature> sign : currentSignatures) {
- final PsiMethod[] resolved = resolver.get(sign.getUnderlying());
- if (!isBreak) {
- if (sign.getWeight() * NEXT_METHOD_IN_CHAIN_RATIO > currentVertex.getWeight()) {
- final boolean stopChain = sign.getUnderlying().isStatic() || toSet.contains(sign.getUnderlying().getOwner());
- if (stopChain) {
- updated = true;
- result.add(currentVertex.getUnderlying().getSecond().addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight()));
- continue;
- }
- else {
- updated = true;
- final MethodsChain methodsChain =
- currentVertexUnderlying.second.addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight());
- q.add(new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
- new Pair<MethodIncompleteSignature, MethodsChain>(sign.getUnderlying(), methodsChain), sign.getWeight()));
- continue;
- }
- }
- }
- final MethodsChain methodsChain =
- currentVertexUnderlying.second.addEdge(resolved, sign.getUnderlying().getOwner(), sign.getWeight());
- final ParametersMatcher.MatchResult parametersMatchResult = ParametersMatcher.matchParameters(methodsChain, context);
- if (parametersMatchResult.noUnmatchedAndHasMatched() && parametersMatchResult.hasTarget()) {
- updated = true;
- q.addFirst(new WeightAware<Pair<MethodIncompleteSignature, MethodsChain>>(
- new Pair<MethodIncompleteSignature, MethodsChain>(sign.getUnderlying(), methodsChain), sign.getWeight()));
- }
- isBreak = true;
- }
- }
- if (!updated &&
- (currentVertex.getUnderlying().getFirst().isStatic() ||
- !targetQName.equals(currentVertex.getUnderlying().getFirst().getOwner()))) {
- result.add(currentVertex.getUnderlying().getSecond());
- }
- if (result.size() > maxResultSize) {
- return result.getResult();
- }
- }
- return result.getResult();
- }
-
- private static MethodsChain createChainFromFirstElement(final MethodsChain chain, final PsiClass newQualifierClass) {
- final String qualifiedClassName = newQualifierClass.getQualifiedName();
- if (qualifiedClassName == null) {
- throw new IllegalArgumentException();
- }
- return new MethodsChain(chain.getFirst(), chain.getChainWeight(), qualifiedClassName);
- }
-
- private static class ResultHolder {
- private final List<MethodsChain> myResult;
- private final ChainCompletionContext myContext;
-
- private ResultHolder(final ChainCompletionContext context) {
- myContext = context;
- myResult = new ArrayList<MethodsChain>();
- }
-
- public void add(final MethodsChain newChain) {
- if (myResult.isEmpty()) {
- myResult.add(newChain);
- return;
- }
- boolean doAdd = true;
- final Stack<Integer> indexesToRemove = new Stack<Integer>();
- for (int i = 0; i < myResult.size(); i++) {
- final MethodsChain chain = myResult.get(i);
- //
- final MethodsChain.CompareResult r = MethodsChain.compare(chain, newChain, myContext);
- switch (r) {
- case LEFT_CONTAINS_RIGHT:
- indexesToRemove.add(i);
- break;
- case RIGHT_CONTAINS_LEFT:
- case EQUAL:
- doAdd = false;
- break;
- case NOT_EQUAL:
- break;
- }
- }
- while (!indexesToRemove.empty()) {
- myResult.remove((int)indexesToRemove.pop());
- }
- if (doAdd) {
- myResult.add(newChain);
- }
- }
-
- public List<MethodsChain> getRawResult() {
- return myResult;
- }
-
- public List<MethodsChain> getResult() {
- return findSimilar(reduceChainsSize(myResult, PsiManager.getInstance(myContext.getProject())), myContext);
- }
-
- public int size() {
- return myResult.size();
- }
-
- private static List<MethodsChain> reduceChainsSize(final List<MethodsChain> chains, final PsiManager psiManager) {
- return ContainerUtil.map(chains, new Function<MethodsChain, MethodsChain>() {
- @Override
- public MethodsChain fun(final MethodsChain chain) {
- final Iterator<PsiMethod[]> chainIterator = chain.iterator();
- if (!chainIterator.hasNext()) {
- LOG.error("empty chain");
- return chain;
- }
- final PsiMethod[] first = chainIterator.next();
- while (chainIterator.hasNext()) {
- final PsiMethod psiMethod = chainIterator.next()[0];
- if (psiMethod.hasModifierProperty(PsiModifier.STATIC)) {
- continue;
- }
- final PsiClass current = psiMethod.getContainingClass();
- if (current == null) {
- LOG.error("containing class must be not null");
- return chain;
- }
- final PsiMethod[] currentMethods = current.findMethodsByName(first[0].getName(), true);
- if (currentMethods.length != 0) {
- for (final PsiMethod f : first) {
- final PsiMethod[] fSupers = f.findDeepestSuperMethods();
- final PsiMethod fSuper = fSupers.length == 0 ? first[0] : fSupers[0];
- for (final PsiMethod currentMethod : currentMethods) {
- if (psiManager.areElementsEquivalent(currentMethod, fSuper)) {
- return createChainFromFirstElement(chain, currentMethod.getContainingClass());
- }
- for (final PsiMethod method : currentMethod.findDeepestSuperMethods()) {
- if (psiManager.areElementsEquivalent(method, fSuper)) {
- return createChainFromFirstElement(chain, method.getContainingClass());
- }
- }
- }
- }
- }
- }
- return chain;
- }
- });
- }
-
- private static List<MethodsChain> findSimilar(final List<MethodsChain> chains, final ChainCompletionContext context) {
- final ResultHolder resultHolder = new ResultHolder(context);
- for (final MethodsChain chain : chains) {
- resultHolder.add(chain);
- }
- return resultHolder.getRawResult();
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MaxSizeTreeSet.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MaxSizeTreeSet.java
deleted file mode 100644
index 535cf09..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MaxSizeTreeSet.java
+++ /dev/null
@@ -1,209 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.*;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MaxSizeTreeSet<E> implements NavigableSet<E> {
-
- @NotNull
- private final NavigableSet<E> myUnderlying;
- private final int myMaxSize;
-
- public MaxSizeTreeSet(final int maxSize) {
- myMaxSize = maxSize;
- if (myMaxSize < 1) {
- throw new IllegalArgumentException();
- }
- myUnderlying = new TreeSet<E>();
- }
-
- public E lower(final E e) {
- return myUnderlying.lower(e);
- }
-
- public E floor(final E e) {
- return myUnderlying.floor(e);
- }
-
- public E ceiling(final E e) {
- return myUnderlying.ceiling(e);
- }
-
- public E higher(final E e) {
- return myUnderlying.higher(e);
- }
-
- @Override
- public E pollFirst() {
- return myUnderlying.pollFirst();
- }
-
- @Override
- public E pollLast() {
- return myUnderlying.pollLast();
- }
-
- @NotNull
- @Override
- public Iterator<E> iterator() {
- return myUnderlying.iterator();
- }
-
- @NotNull
- @Override
- public NavigableSet<E> descendingSet() {
- return myUnderlying.descendingSet();
- }
-
- @NotNull
- @Override
- public Iterator<E> descendingIterator() {
- return myUnderlying.descendingIterator();
- }
-
- @NotNull
- public NavigableSet<E> subSet(final E fromElement, final boolean fromInclusive, final E toElement, final boolean toInclusive) {
- return myUnderlying.subSet(fromElement, fromInclusive, toElement, toInclusive);
- }
-
- @NotNull
- public NavigableSet<E> headSet(final E toElement, final boolean inclusive) {
- return myUnderlying.headSet(toElement, inclusive);
- }
-
- @NotNull
- public NavigableSet<E> tailSet(final E fromElement, final boolean inclusive) {
- return myUnderlying.tailSet(fromElement, inclusive);
- }
-
- @NotNull
- public SortedSet<E> subSet(final E fromElement, final E toElement) {
- return myUnderlying.subSet(fromElement, toElement);
- }
-
- @NotNull
- public SortedSet<E> headSet(final E toElement) {
- return myUnderlying.headSet(toElement);
- }
-
- @NotNull
- public SortedSet<E> tailSet(final E fromElement) {
- return myUnderlying.tailSet(fromElement);
- }
-
- @Nullable
- @Override
- public Comparator<? super E> comparator() {
- return myUnderlying.comparator();
- }
-
- @Override
- public E first() {
- return myUnderlying.first();
- }
-
- @Override
- public E last() {
- return myUnderlying.last();
- }
-
- @Override
- public int size() {
- return myUnderlying.size();
- }
-
- @Override
- public boolean isEmpty() {
- return myUnderlying.isEmpty();
- }
-
- @Override
- public boolean contains(final Object o) {
- return myUnderlying.contains(o);
- }
-
- @NotNull
- @Override
- public Object[] toArray() {
- return myUnderlying.toArray();
- }
-
- @NotNull
- @Override
- public <T> T[] toArray(final T[] a) {
- return myUnderlying.toArray(a);
- }
-
- public boolean add(final E e) {
- if (myUnderlying.size() == myMaxSize) {
- //noinspection ConstantConditions
- final Comparator<? super E> comparator = comparator();
- if ((comparator == null ? ((Comparable)e).compareTo(last()) : comparator.compare(e, last())) < 0) {
- final boolean isAdded = myUnderlying.add(e);
- if (isAdded) {
- pollLast();
- return true;
- }
- }
- return false;
- }
- return myUnderlying.add(e);
- }
-
- @Override
- public boolean remove(final Object o) {
- return myUnderlying.remove(o);
- }
-
- @Override
- public boolean containsAll(final Collection<?> c) {
- return myUnderlying.containsAll(c);
- }
-
- public boolean addAll(final Collection<? extends E> c) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean retainAll(final Collection<?> c) {
- return myUnderlying.retainAll(c);
- }
-
- @Override
- public boolean removeAll(final Collection<?> c) {
- return myUnderlying.removeAll(c);
- }
-
- @Override
- public void clear() {
- myUnderlying.clear();
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (!(o instanceof MaxSizeTreeSet)) return false;
-
- final MaxSizeTreeSet that = (MaxSizeTreeSet)o;
-
- if (!myUnderlying.equals(that.myUnderlying)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return myUnderlying.hashCode();
- }
-
- @Override
- public String toString() {
- return myUnderlying.toString();
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java
deleted file mode 100644
index 587945d..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchService.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
-import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiManager;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class MethodChainsSearchService {
- private final static SortedSet EMPTY_SORTED_SET = new TreeSet();
-
- private final MethodsUsageIndex myMethodsUsageIndex;
- private final Project myProject;
-
- public MethodChainsSearchService(final Project project) {
- myMethodsUsageIndex = MethodsUsageIndex.getInstance(project);
- myProject = project;
- }
-
- public Project getProject() {
- return myProject;
- }
-
- @NotNull
- @SuppressWarnings("unchecked")
- public SortedSet<UsageIndexValue> getMethods(final String targetQName) {
- final TreeSet<UsageIndexValue> value = myMethodsUsageIndex.getValues(targetQName);
- if (value != null) {
- return value;
- }
- return EMPTY_SORTED_SET;
- }
-
- public PsiManager getPsiManager() {
- return PsiManager.getInstance(getProject());
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java
deleted file mode 100644
index ae0df95..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodChainsSearchUtil.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiParameter;
-import com.intellij.psi.PsiParameterList;
-import com.intellij.psi.PsiPrimitiveType;
-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;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class MethodChainsSearchUtil {
- private MethodChainsSearchUtil() {
- }
-
- @Nullable
- public static PsiMethod getMethodWithMinNotPrimitiveParameters(final @NotNull PsiMethod[] methods,
- final Set<String> excludedParamsQNames) {
- PsiMethod minMethod = null;
- int minParametersCount = Integer.MAX_VALUE;
- for (final PsiMethod method : methods) {
- final PsiParameterList parameterList = method.getParameterList();
- boolean doContinue = false;
- int parametersCount = parameterList.getParametersCount();
- for (final PsiParameter p : parameterList.getParameters()) {
- if (!(p.getType() instanceof PsiPrimitiveType)) {
- if (excludedParamsQNames.contains(p.getType().getCanonicalText())) {
- doContinue = true;
- break;
- }
- parametersCount++;
- }
- }
- if (doContinue) {
- continue;
- }
- if (parametersCount < minParametersCount) {
- if (parametersCount == 0) {
- return method;
- }
- minParametersCount = parametersCount;
- minMethod = method;
- }
- }
- return minMethod;
- }
-
- public static boolean checkParametersForTypesQNames(final PsiMethod[] psiMethods, final Set<String> excludedTypesQNames) {
- if (psiMethods.length == 0) {
- return true;
- }
- for (final PsiMethod method : psiMethods) {
- boolean hasTargetInParams = false;
- for (final PsiParameter param : method.getParameterList().getParameters()) {
- final String paramType = param.getType().getCanonicalText();
- if (excludedTypesQNames.contains(paramType)) {
- hasTargetInParams = true;
- break;
- }
- }
- if (!hasTargetInParams) {
- return true;
- }
- }
- return false;
- }
-
- public static <T> HashSet<T> unionToHashSet(final Collection<T> collection, final T... items) {
- final HashSet<T> result = new HashSet<T>();
- result.addAll(collection);
- Collections.addAll(result, items);
- return result;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java
deleted file mode 100644
index a4b055b..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChain.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiManager;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiParameter;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.*;
-
-import static com.intellij.util.containers.ContainerUtil.findAll;
-import static com.intellij.util.containers.ContainerUtil.reverse;
-
-/**
- * @author Dmitry Batkovich
- */
-public class MethodsChain {
- private final List<PsiMethod[]> myRevertedPath;
- private final int myWeight;
- //
- // chain qualifier class could be different with method.getContainingClass()
- private final String myQualifierClassName;
-
- private final Set<String> myExcludedQNames;
-
- public MethodsChain(final PsiMethod[] methods, final int weight, final String qualifierClassName) {
- this(Collections.singletonList(methods), weight, qualifierClassName, chooseParametersQNames(methods));
- }
-
- private MethodsChain(final List<PsiMethod[]> revertedPath,
- final int weight,
- final String qualifierClassName,
- final Set<String> excludedQNames) {
- myRevertedPath = revertedPath;
- myWeight = weight;
- myQualifierClassName = qualifierClassName;
- myExcludedQNames = excludedQNames;
- }
-
- public int size() {
- return myRevertedPath.size();
- }
-
- public Set<String> getExcludedQNames() {
- return myExcludedQNames;
- }
-
- public String getQualifierClassName() {
- return myQualifierClassName;
- }
-
- public Iterator<PsiMethod[]> iterator() {
- return myRevertedPath.iterator();
- }
-
- @NotNull
- public PsiMethod[] getFirst() {
- return myRevertedPath.get(0);
- }
-
- public List<PsiMethod[]> getPath() {
- return reverse(myRevertedPath);
- }
-
- public int getChainWeight() {
- return myWeight;
- }
-
- @SuppressWarnings("unchecked")
- public MethodsChain addEdge(final PsiMethod[] psiMethods, final String newQualifierClassName, final int newWeight) {
- final List<PsiMethod[]> newRevertedPath = new ArrayList<PsiMethod[]>(myRevertedPath.size() + 1);
- newRevertedPath.addAll(myRevertedPath);
- newRevertedPath.add(psiMethods);
- return new MethodsChain(newRevertedPath,
- newWeight,
- newQualifierClassName,
- joinSets(myExcludedQNames, chooseParametersQNames(psiMethods)));
- }
-
-
- @Override
- public String toString() {
- return StringUtil.join(myRevertedPath, "<-");
- }
-
- @SuppressWarnings("ConstantConditions")
- public static CompareResult compare(final MethodsChain left, final MethodsChain right, final ChainCompletionContext context) {
- if (left.size() == 0) {
- return CompareResult.RIGHT_CONTAINS_LEFT;
- }
- if (right.size() == 0) {
- return CompareResult.LEFT_CONTAINS_RIGHT;
- }
- final Iterator<PsiMethod[]> leftIterator = left.myRevertedPath.iterator();
- final Iterator<PsiMethod[]> rightIterator = right.myRevertedPath.iterator();
-
- while (leftIterator.hasNext() && rightIterator.hasNext()) {
- final PsiMethod thisNext = leftIterator.next()[0];
- final PsiMethod thatNext = rightIterator.next()[0];
- if (thisNext == null || thatNext == null) {
- throw new NullPointerException();
- }
- if (((thisNext.isConstructor() != thatNext.isConstructor())) || !thisNext.getName().equals(thatNext.getName())) {
- return CompareResult.NOT_EQUAL;
- }
- }
- if (leftIterator.hasNext() && !rightIterator.hasNext()) {
- return CompareResult.LEFT_CONTAINS_RIGHT;
- }
- if (!leftIterator.hasNext() && rightIterator.hasNext()) {
- return CompareResult.RIGHT_CONTAINS_LEFT;
- }
-
-
- return hasBaseMethod(left.getPath().get(0), right.getPath().get(0), PsiManager.getInstance(context.getProject()))
- ? CompareResult.EQUAL
- : CompareResult.NOT_EQUAL;
- }
-
- public enum CompareResult {
- LEFT_CONTAINS_RIGHT,
- RIGHT_CONTAINS_LEFT,
- EQUAL,
- NOT_EQUAL
- }
-
- private static boolean hasBaseMethod(final PsiMethod[] left, final PsiMethod[] right, final PsiManager psiManager) {
- for (final PsiMethod rightMethod : right) {
- final PsiMethod[] rightSupers = rightMethod.findDeepestSuperMethods();
- if (rightSupers.length != 0) {
- for (final PsiMethod leftMethod : left) {
- final PsiMethod[] leftSupers = leftMethod.findDeepestSuperMethods();
- if (leftSupers.length != 0) {
- if (psiManager.areElementsEquivalent(leftSupers[0], rightSupers[0])) {
- return true;
- }
- }
- }
- }
- }
- return false;
- }
-
- private static Set<String> joinSets(final Set<String>... sets) {
- final Set<String> result = new HashSet<String>();
- for (final Set<String> set : sets) {
- for (final String s : set) {
- result.add(s);
- }
- }
- return result;
- }
-
- private static Set<String> chooseParametersQNames(final PsiMethod[] methods) {
- final Set<String> qNames = new HashSet<String>();
- for (final PsiParameter methodParameter : methods[0].getParameterList().getParameters()) {
- qNames.add(methodParameter.getType().getCanonicalText());
- }
- return qNames;
- }
-
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java
deleted file mode 100644
index 0389f76..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/MethodsChainLookupRangingHelper.java
+++ /dev/null
@@ -1,275 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.codeInsight.NullableNotNullManager;
-import com.intellij.codeInsight.completion.JavaChainLookupElement;
-import com.intellij.codeInsight.completion.methodChains.ChainCompletionStringUtil;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantStaticMethod;
-import com.intellij.codeInsight.completion.methodChains.completion.context.ContextRelevantVariableGetter;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionNewVariableLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.GetterLookupSubLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.SubLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.sub.VariableSubLookupElement;
-import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.codeInsight.lookup.VariableLookupItem;
-import com.intellij.psi.*;
-import com.intellij.util.containers.ContainerUtil;
-import gnu.trove.TIntObjectHashMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-
-import static com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionLookupElementUtil.createLookupElement;
-import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class MethodsChainLookupRangingHelper {
-
- public static List<LookupElement> chainsToWeightableLookupElements(final List<MethodsChain> chains,
- final ChainCompletionContext context) {
- final List<LookupElement> lookupElements = new ArrayList<LookupElement>(chains.size());
- for (final MethodsChain chain : chains) {
- final LookupElement lookupElement = chainToWeightableLookupElement(chain, context);
- if (lookupElement != null) {
- lookupElements.add(lookupElement);
- }
- }
- return lookupElements;
- }
-
- @SuppressWarnings("ConstantConditions")
- @Nullable
- private static WeightableChainLookupElement chainToWeightableLookupElement(final MethodsChain chain,
- final ChainCompletionContext context) {
- final int chainSize = chain.size();
- assert chainSize != 0;
- final int lastMethodWeight = chain.getChainWeight();
- int unreachableParametersCount = 0;
- int notMatchedStringVars = 0;
- int matchedParametersInContext = 0;
- Boolean isFirstMethodStatic = null;
- Boolean hasCallingVariableInContext = null;
- LookupElement chainLookupElement = null;
- PsiClass newVariableClass = null;
- final NullableNotNullManager nullableNotNullManager = NullableNotNullManager.getInstance(context.getProject());
-
- for (final PsiMethod[] psiMethods : chain.getPath()) {
- final PsiMethod method =
- MethodChainsSearchUtil.getMethodWithMinNotPrimitiveParameters(psiMethods, Collections.singleton(context.getTargetQName()));
- if (method == null) {
- return null;
- }
- if (isFirstMethodStatic == null) {
- isFirstMethodStatic = psiMethods[0].hasModifierProperty(PsiModifier.STATIC);
- }
- final PsiClass qualifierClass;
- final boolean isHead = chainLookupElement == null;
- if (isHead) {
- final String qualifierClassName = chain.getQualifierClassName();
- qualifierClass = JavaPsiFacade.getInstance(context.getProject()).
- findClass(qualifierClassName, context.getResolveScope());
- }
- else {
- qualifierClass = null;
- }
-
- final MethodProcResult procResult = processMethod(method, qualifierClass, context, lastMethodWeight, isHead, nullableNotNullManager);
- if (procResult == null) {
- return null;
- }
- if (hasCallingVariableInContext == null) {
- hasCallingVariableInContext = procResult.hasCallingVariableInContext();
- }
- if (isHead && procResult.isIntroduceNewVariable()) {
- newVariableClass = qualifierClass;
- }
- matchedParametersInContext += procResult.getMatchedParametersInContext();
- unreachableParametersCount += procResult.getUnreachableParametersCount();
- notMatchedStringVars += procResult.getNotMatchedStringVars();
- chainLookupElement =
- isHead ? procResult.getLookupElement() : new JavaChainLookupElement(chainLookupElement, procResult.getLookupElement());
- }
-
- if (newVariableClass != null) {
- chainLookupElement = ChainCompletionNewVariableLookupElement.create(newVariableClass, chainLookupElement);
- }
-
- final ChainRelevance relevance =
- new ChainRelevance(chainSize, lastMethodWeight, unreachableParametersCount, notMatchedStringVars, hasCallingVariableInContext,
- isFirstMethodStatic, matchedParametersInContext);
-
- return new WeightableChainLookupElement(chainLookupElement, relevance);
- }
-
-
- @Nullable
- private static MethodProcResult processMethod(@NotNull final PsiMethod method,
- @Nullable final PsiClass qualifierClass,
- final ChainCompletionContext context,
- final int weight,
- final boolean isHeadMethod,
- final NullableNotNullManager nullableNotNullManager) {
- int unreachableParametersCount = 0;
- int notMatchedStringVars = 0;
- int matchedParametersInContext = 0;
- boolean hasCallingVariableInContext = false;
- boolean introduceNewVariable = false;
- final PsiParameterList parameterList = method.getParameterList();
- final TIntObjectHashMap<SubLookupElement> parametersMap = new TIntObjectHashMap<SubLookupElement>(parameterList.getParametersCount());
- final PsiParameter[] parameters = parameterList.getParameters();
- for (int i = 0; i < parameters.length; i++) {
- final PsiParameter parameter = parameters[i];
- final String typeQName = parameter.getType().getCanonicalText();
- if (typeQName != null) {
- if (JAVA_LANG_STRING.equals(typeQName)) {
- final PsiVariable relevantStringVar = context.findRelevantStringInContext(parameter.getName());
- if (relevantStringVar == null) {
- notMatchedStringVars++;
- }
- else {
- parametersMap.put(i, new VariableSubLookupElement(relevantStringVar));
- }
- }
- else if (!ChainCompletionStringUtil.isPrimitiveOrArrayOfPrimitives(typeQName)) {
- final Collection<PsiVariable> contextVariables = context.getVariables(typeQName);
- final PsiVariable contextVariable = ContainerUtil.getFirstItem(contextVariables, null);
- if (contextVariable != null) {
- if (contextVariables.size() == 1) parametersMap.put(i, new VariableSubLookupElement(contextVariable));
- matchedParametersInContext++;
- continue;
- }
- final Collection<ContextRelevantVariableGetter> relevantVariablesGetters = context.getRelevantVariablesGetters(typeQName);
- final ContextRelevantVariableGetter contextVariableGetter = ContainerUtil.getFirstItem(relevantVariablesGetters, null);
- if (contextVariableGetter != null) {
- if (relevantVariablesGetters.size() == 1) parametersMap.put(i, contextVariableGetter.createSubLookupElement());
- matchedParametersInContext++;
- continue;
- }
- final Collection<PsiMethod> containingClassMethods = context.getContainingClassMethods(typeQName);
- final PsiMethod contextRelevantGetter = ContainerUtil.getFirstItem(containingClassMethods, null);
- if (contextRelevantGetter != null) {
- if (containingClassMethods.size() == 1) parametersMap.put(i, new GetterLookupSubLookupElement(method.getName()));
- matchedParametersInContext++;
- continue;
- }
- final ContextRelevantStaticMethod contextRelevantStaticMethod =
- ContainerUtil.getFirstItem(context.getRelevantStaticMethods(typeQName, weight), null);
- if (contextRelevantStaticMethod != null) {
- //
- // In most cases it is not really relevant
- //
- //parametersMap.put(i, contextRelevantStaticMethod.createLookupElement());
- matchedParametersInContext++;
- continue;
- }
- if (!nullableNotNullManager.isNullable(parameter, true)) {
- unreachableParametersCount++;
- }
- }
- }
- }
- final LookupElement lookupElement;
- if (isHeadMethod) {
- if (method.hasModifierProperty(PsiModifier.STATIC)) {
- hasCallingVariableInContext = true;
- lookupElement = createLookupElement(method, parametersMap);
- }
- else if (method.isConstructor()) {
- return null;
- }
- else {
- @SuppressWarnings("ConstantConditions")
- final String classQName = qualifierClass.getQualifiedName();
- if (classQName == null) return null;
- final Object e = ContainerUtil.getFirstItem(context.getContextRefElements(classQName), null);
- if (e != null) {
- final LookupElement firstChainElement;
- if (e instanceof PsiVariable) {
- firstChainElement = new VariableLookupItem((PsiVariable)e);
- }
- else if (e instanceof PsiMethod) {
- firstChainElement = createLookupElement((PsiMethod)e, null);
- }
- else if (e instanceof LookupElement) {
- firstChainElement = (LookupElement)e;
- }
- else {
- throw new AssertionError();
- }
- hasCallingVariableInContext = true;
- lookupElement = new JavaChainLookupElement(firstChainElement, createLookupElement(method, parametersMap));
- }
- else {
- lookupElement = createLookupElement(method, parametersMap);
- if (!context.getContainingClassQNames().contains(classQName)) {
- introduceNewVariable = true;
- }
- }
- }
- }
- else {
- lookupElement = createLookupElement(method, parametersMap);
- }
- return new MethodProcResult(lookupElement,
- unreachableParametersCount,
- notMatchedStringVars,
- hasCallingVariableInContext,
- introduceNewVariable,
- matchedParametersInContext);
- }
-
- private static class MethodProcResult {
- private final LookupElement myMethodLookup;
- private final int myUnreachableParametersCount;
- private final int myNotMatchedStringVars;
- private final boolean myHasCallingVariableInContext;
- private final boolean myIntroduceNewVariable;
- private final int myMatchedParametersInContext;
-
- private MethodProcResult(final LookupElement methodLookup,
- final int unreachableParametersCount,
- final int notMatchedStringVars,
- final boolean hasCallingVariableInContext,
- final boolean introduceNewVariable,
- final int matchedParametersInContext) {
- myMethodLookup = methodLookup;
- myUnreachableParametersCount = unreachableParametersCount;
- myNotMatchedStringVars = notMatchedStringVars;
- myHasCallingVariableInContext = hasCallingVariableInContext;
- myIntroduceNewVariable = introduceNewVariable;
- myMatchedParametersInContext = matchedParametersInContext;
- }
-
- private boolean isIntroduceNewVariable() {
- return myIntroduceNewVariable;
- }
-
- private boolean hasCallingVariableInContext() {
- return myHasCallingVariableInContext;
- }
-
- private LookupElement getLookupElement() {
- return myMethodLookup;
- }
-
- private int getUnreachableParametersCount() {
- return myUnreachableParametersCount;
- }
-
- private int getNotMatchedStringVars() {
- return myNotMatchedStringVars;
- }
-
- public int getMatchedParametersInContext() {
- return myMatchedParametersInContext;
- }
- }
-}
-
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java
deleted file mode 100644
index fd4d5d7..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/ParametersMatcher.java
+++ /dev/null
@@ -1,96 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.codeInsight.completion.methodChains.completion.context.ChainCompletionContext;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiParameter;
-import com.intellij.psi.PsiPrimitiveType;
-import com.intellij.psi.PsiType;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.NavigableSet;
-import java.util.Set;
-import java.util.TreeSet;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class ParametersMatcher {
-
- private ParametersMatcher() {}
-
- public static MatchResult matchParameters(final MethodsChain chain, final ChainCompletionContext context) {
- MatchResult overallResult = EMPTY;
- for (final PsiMethod[] methods : chain.getPath()) {
- final NavigableSet<MatchResult> matchResults = new TreeSet<MatchResult>();
- for (final PsiMethod method : methods) {
- matchResults.add(matchParameters(method, context, chain.getExcludedQNames()));
- }
- final MatchResult best = matchResults.first();
- overallResult = overallResult.add(best);
- }
- return overallResult;
- }
-
- private static MatchResult matchParameters(final PsiMethod method, final ChainCompletionContext context, final Set<String> additionalExcludedNames) {
- int matched = 0;
- int unMatched = 0;
- boolean hasTarget = false;
- for (final PsiParameter parameter : method.getParameterList().getParameters()) {
- final PsiType type = parameter.getType();
- final String canonicalText = type.getCanonicalText();
- if (context.contains(canonicalText) || type instanceof PsiPrimitiveType) {
- matched++;
- }
- else {
- unMatched++;
- }
- if (context.getTargetQName().equals(canonicalText) || additionalExcludedNames.contains(canonicalText)) {
- hasTarget = true;
- }
- }
- return new MatchResult(matched, unMatched, hasTarget);
- }
-
- private static final MatchResult EMPTY = new MatchResult(0, 0, false);
-
- public static class MatchResult implements Comparable<MatchResult> {
- private final int myMatched;
- private final int myUnMatched;
- private final boolean myHasTarget;
-
- private MatchResult(final int matched, final int unMatched, final boolean hasTarget) {
- myMatched = matched;
- myUnMatched = unMatched;
- myHasTarget = hasTarget;
- }
-
- public int getMatched() {
- return myMatched;
- }
-
- public int getUnMatched() {
- return myUnMatched;
- }
-
- public boolean hasTarget() {
- return myHasTarget;
- }
-
- public MatchResult add(final MatchResult other) {
- return new MatchResult(getMatched() + other.getMatched(), getUnMatched() + other.getUnMatched(), other.myHasTarget || myHasTarget);
- }
-
- public boolean noUnmatchedAndHasMatched() {
- return myUnMatched == 0 && myMatched != 0;
- }
-
- @Override
- public int compareTo(@NotNull final MatchResult other) {
- final int sub = getUnMatched() - other.getUnMatched();
- if (sub != 0) {
- return sub;
- }
- return getMatched() - other.getMatched();
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java
deleted file mode 100644
index 54e6d01..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/SearchInitializer.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
-import com.intellij.compilerOutputIndex.impl.UsageIndexValue;
-import com.intellij.psi.PsiMethod;
-import com.intellij.util.containers.FactoryMap;
-
-import java.util.*;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class SearchInitializer {
- private final static int CHAIN_SEARCH_MAGIC_RATIO = 12;
-
- private final List<WeightAware<MethodIncompleteSignature>> myVertices;
- private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
- private final FactoryMap<MethodIncompleteSignature, PsiMethod[]> myResolver;
-
- public SearchInitializer(final SortedSet<UsageIndexValue> indexValues,
- final FactoryMap<MethodIncompleteSignature, PsiMethod[]> resolver,
- final String targetQName,
- final Set<String> excludedParamsTypesQNames) {
- myResolver = resolver;
- final int size = indexValues.size();
- myVertices = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
- myChains = new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
- add(indexValues, MethodChainsSearchUtil.unionToHashSet(excludedParamsTypesQNames, targetQName));
- }
-
- private void add(final Collection<UsageIndexValue> indexValues, final Set<String> excludedParamsTypesQNames) {
- int bestOccurrences = -1;
- for (final UsageIndexValue indexValue : indexValues) {
- if (add(indexValue, excludedParamsTypesQNames)) {
- final int occurrences = indexValue.getOccurrences();
- if (bestOccurrences == -1) {
- bestOccurrences = occurrences;
- }
- else if (bestOccurrences > occurrences * CHAIN_SEARCH_MAGIC_RATIO) {
- return;
- }
- }
- }
- }
-
- private boolean add(final UsageIndexValue indexValue, final Set<String> excludedParamsTypesQNames) {
- final MethodIncompleteSignature methodInvocation = indexValue.getMethodIncompleteSignature();
- final PsiMethod[] psiMethods = myResolver.get(methodInvocation);
- if (psiMethods.length != 0 && MethodChainsSearchUtil.checkParametersForTypesQNames(psiMethods, excludedParamsTypesQNames)) {
- final int occurrences = indexValue.getOccurrences();
- final MethodsChain methodsChain = new MethodsChain(psiMethods, occurrences, indexValue.getMethodIncompleteSignature().getOwner());
- myChains.put(methodInvocation, methodsChain);
- myVertices.add(new WeightAware<MethodIncompleteSignature>(methodInvocation, occurrences));
- return true;
- }
- return false;
- }
-
- public InitResult init(final Set<String> excludedEdgeNames) {
- final int size = myVertices.size();
- final List<WeightAware<MethodIncompleteSignature>> initedVertexes = new ArrayList<WeightAware<MethodIncompleteSignature>>(size);
- final LinkedHashMap<MethodIncompleteSignature, MethodsChain> initedChains =
- new LinkedHashMap<MethodIncompleteSignature, MethodsChain>(size);
- final Iterator<Map.Entry<MethodIncompleteSignature, MethodsChain>> chainsIterator = myChains.entrySet().iterator();
- for (final WeightAware<MethodIncompleteSignature> vertex : myVertices) {
- final Map.Entry<MethodIncompleteSignature, MethodsChain> chainEntry = chainsIterator.next();
- final MethodIncompleteSignature method = vertex.getUnderlying();
- if (!excludedEdgeNames.contains(method.getName())) {
- initedVertexes.add(vertex);
- final MethodsChain methodsChain = chainEntry.getValue();
- initedChains.put(chainEntry.getKey(), methodsChain);
- }
- }
- return new InitResult(initedVertexes, initedChains);
- }
-
- public static class InitResult {
- private final List<WeightAware<MethodIncompleteSignature>> myVertexes;
- private final LinkedHashMap<MethodIncompleteSignature, MethodsChain> myChains;
-
- private InitResult(final List<WeightAware<MethodIncompleteSignature>> vertexes,
- final LinkedHashMap<MethodIncompleteSignature, MethodsChain> chains) {
- myVertexes = vertexes;
- myChains = chains;
- }
-
- public List<WeightAware<MethodIncompleteSignature>> getVertexes() {
- return myVertexes;
- }
-
- public LinkedHashMap<MethodIncompleteSignature, MethodsChain> getChains() {
- return myChains;
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java b/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java
deleted file mode 100644
index 7fd6824..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/completion/methodChains/search/WeightAware.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.intellij.codeInsight.completion.methodChains.search;
-
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author Dmitry Batkovich
- */
-public class WeightAware<V> implements Comparable<WeightAware<V>> {
- private final V myUnderlying;
- private final int myWeight;
-
- public WeightAware(final V underlying, final int weight) {
- myUnderlying = underlying;
- myWeight = weight;
- }
-
- public V getUnderlying() {
- return myUnderlying;
- }
-
- public int getWeight() {
- return myWeight;
- }
-
- @Override
- public int compareTo(@NotNull final WeightAware<V> that) {
- final int sub = -getWeight() + that.getWeight();
- if (sub != 0) {
- return sub;
- }
- return myUnderlying.hashCode() - that.myUnderlying.hashCode();
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java
index 5f95ae7..a6f3e94 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/CompletionElement.java
@@ -54,10 +54,13 @@
return ((PsiMethod)myElement).getSignature(mySubstitutor);
}
if (myElement instanceof PsiVariable) {
- return "#" + ((PsiVariable)myElement).getName();
+ return getVariableUniqueId((PsiVariable)myElement);
}
return null;
}
+ public static String getVariableUniqueId(final PsiVariable variable) {
+ return "#" + variable.getName();
+ }
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
index 0344cfd..041b7f6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java
@@ -227,7 +227,10 @@
(sp == StaticProblem.staticAfterInstance ? myFilteredResults : myResults).add(element1);
}
}
+ } else if (element instanceof PsiLocalVariable || element instanceof PsiParameter) {
+ myResultNames.add(CompletionElement.getVariableUniqueId((PsiVariable)element));
}
+
return true;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java
deleted file mode 100644
index cf2b86f..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/GlobalUsageHelper.java
+++ /dev/null
@@ -1,35 +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.codeInsight.daemon.impl;
-
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiMember;
-import com.intellij.psi.PsiNamedElement;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * @author peter
- */
-public abstract class GlobalUsageHelper {
- final Map<PsiClass,Boolean> unusedClassCache = new HashMap<PsiClass, Boolean>();
-
- public abstract boolean shouldCheckUsages(@NotNull PsiMember member);
- public abstract boolean isLocallyUsed(@NotNull PsiNamedElement member);
- public abstract boolean isCurrentFileAlreadyChecked();
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java
index 5f47055..0d48f25 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/IconLineMarkerProvider.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.
@@ -31,7 +31,6 @@
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ImageLoader;
-import com.intellij.util.PlatformUtils;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -189,7 +188,7 @@
Pair<Long, Icon> iconInfo = iconsCache.get(path);
if (iconInfo == null || iconInfo.getFirst() < stamp) {
try {
- final Icon icon = createOrFindBetterIcon(file, PlatformUtils.isIdeaProject(project));
+ final Icon icon = createOrFindBetterIcon(file, isIdeaProject(project));
iconInfo = new Pair<Long, Icon>(stamp, hasProperSize(icon) ? icon : null);
iconsCache.put(file.getPath(), iconInfo);
}
@@ -201,7 +200,13 @@
return iconInfo == null ? null : iconInfo.getSecond();
}
- private Icon createOrFindBetterIcon(VirtualFile file, boolean tryToFindBetter) throws IOException {
+ private static boolean isIdeaProject(Project project) {
+ if (project == null) return false;
+ VirtualFile baseDir = project.getBaseDir();
+ return baseDir != null && (baseDir.findChild("idea.iml") != null || baseDir.findChild("community-main.iml") != null);
+ }
+
+ private static Icon createOrFindBetterIcon(VirtualFile file, boolean tryToFindBetter) throws IOException {
if (tryToFindBetter) {
VirtualFile parent = file.getParent();
String name = file.getNameWithoutExtension();
@@ -233,7 +238,7 @@
return new ImageIcon(file.contentsToByteArray());
}
- private ImageIcon loadIcon(VirtualFile file, int scale) throws IOException {
+ private static ImageIcon loadIcon(VirtualFile file, int scale) throws IOException {
return new ImageIcon(ImageLoader.loadFromStream(file.getInputStream(), scale));
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
deleted file mode 100644
index 9252436..0000000
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPass.java
+++ /dev/null
@@ -1,846 +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.codeInsight.daemon.impl;
-
-import com.intellij.codeHighlighting.Pass;
-import com.intellij.codeInsight.CodeInsightSettings;
-import com.intellij.codeInsight.daemon.HighlightDisplayKey;
-import com.intellij.codeInsight.daemon.ImplicitUsageProvider;
-import com.intellij.codeInsight.daemon.JavaErrorMessages;
-import com.intellij.codeInsight.daemon.impl.analysis.*;
-import com.intellij.codeInsight.daemon.impl.quickfix.*;
-import com.intellij.codeInsight.intention.EmptyIntentionAction;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInsight.intention.IntentionManager;
-import com.intellij.codeInspection.*;
-import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
-import com.intellij.codeInspection.reference.UnusedDeclarationFixProvider;
-import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
-import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
-import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
-import com.intellij.codeInspection.util.SpecialAnnotationsUtilBase;
-import com.intellij.diagnostic.AttachmentFactory;
-import com.intellij.diagnostic.LogMessageEx;
-import com.intellij.find.FindManager;
-import com.intellij.find.findUsages.*;
-import com.intellij.find.impl.FindManagerImpl;
-import com.intellij.lang.Language;
-import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.command.undo.UndoManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.progress.ProcessCanceledException;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.pom.PomNamedTarget;
-import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
-import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.impl.PsiClassImplUtil;
-import com.intellij.psi.impl.source.PsiClassImpl;
-import com.intellij.psi.impl.source.jsp.jspJava.JspxImportStatement;
-import com.intellij.psi.jsp.JspFile;
-import com.intellij.psi.jsp.JspSpiUtil;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.search.PsiSearchHelper;
-import com.intellij.psi.search.SearchScope;
-import com.intellij.psi.search.searches.OverridingMethodsSearch;
-import com.intellij.psi.search.searches.SuperMethodsSearch;
-import com.intellij.psi.util.PropertyUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.util.PsiUtilCore;
-import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
-import com.intellij.util.Processor;
-import gnu.trove.THashSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.PropertyKey;
-
-import java.util.*;
-
-import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
-import static com.intellij.psi.search.PsiSearchHelper.SearchCostResult.ZERO_OCCURRENCES;
-
-public class PostHighlightingPass extends ProgressableTextEditorHighlightingPass {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPass");
- private RefCountHolder myRefCountHolder;
- private final PsiFile myFile;
- @Nullable private final Editor myEditor;
- private final int myStartOffset;
- private final int myEndOffset;
-
- private Collection<HighlightInfo> myHighlights;
- private boolean myHasRedundantImports;
- private final JavaCodeStyleManager myStyleManager;
- private int myCurrentEntryIndex;
- private boolean myHasMissortedImports;
- private static final ImplicitUsageProvider[] ourImplicitUsageProviders = Extensions.getExtensions(ImplicitUsageProvider.EP_NAME);
- private UnusedDeclarationInspection myDeadCodeInspection;
- private UnusedSymbolLocalInspection myUnusedSymbolInspection;
- private HighlightDisplayKey myUnusedSymbolKey;
- private boolean myDeadCodeEnabled;
- private boolean myInLibrary;
- private HighlightDisplayKey myDeadCodeKey;
- private HighlightInfoType myDeadCodeInfoType;
- private UnusedParametersInspection myUnusedParametersInspection;
-
- PostHighlightingPass(@NotNull Project project,
- @NotNull PsiFile file,
- @Nullable Editor editor,
- @NotNull Document document,
- @NotNull HighlightInfoProcessor highlightInfoProcessor) {
- super(project, document, "Unused symbols", file, editor, file.getTextRange(), true, highlightInfoProcessor);
- myFile = file;
- myEditor = editor;
- myStartOffset = 0;
- myEndOffset = file.getTextLength();
-
- myStyleManager = JavaCodeStyleManager.getInstance(myProject);
- myCurrentEntryIndex = -1;
- }
-
- @Override
- protected void collectInformationWithProgress(@NotNull final ProgressIndicator progress) {
- DaemonCodeAnalyzerEx daemonCodeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
- final FileStatusMap fileStatusMap = daemonCodeAnalyzer.getFileStatusMap();
- final List<HighlightInfo> highlights = new ArrayList<HighlightInfo>();
- final FileViewProvider viewProvider = myFile.getViewProvider();
- final Set<Language> relevantLanguages = viewProvider.getLanguages();
- final Set<PsiElement> elementSet = new THashSet<PsiElement>();
- for (Language language : relevantLanguages) {
- PsiElement psiRoot = viewProvider.getPsi(language);
- if (!HighlightingLevelManager.getInstance(myProject).shouldHighlight(psiRoot)) continue;
- List<PsiElement> elements = CollectHighlightsUtil.getElementsInRange(psiRoot, myStartOffset, myEndOffset);
- elementSet.addAll(elements);
- }
-
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(myProject).getFileIndex();
- VirtualFile virtualFile = viewProvider.getVirtualFile();
- myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);
-
- myRefCountHolder = RefCountHolder.endUsing(myFile, progress);
- if (myRefCountHolder == null || !myRefCountHolder.retrieveUnusedReferencesInfo(progress, new Runnable() {
- @Override
- public void run() {
- boolean errorFound = collectHighlights(elementSet, highlights, progress);
- myHighlights = highlights;
- if (errorFound) {
- fileStatusMap.setErrorFoundFlag(myDocument, true);
- }
- }
- })) {
- // we must be sure GHP will restart
- fileStatusMap.markFileScopeDirty(getDocument(), Pass.UPDATE_ALL);
- GeneralHighlightingPass.cancelAndRestartDaemonLater(progress, myProject, this);
- }
- }
-
- @Override
- public List<HighlightInfo> getInfos() {
- return myHighlights == null ? null : new ArrayList<HighlightInfo>(myHighlights);
- }
-
- @Override
- protected void applyInformationWithProgress() {
- if (myHighlights == null) return;
- UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myHighlights, getColorsScheme(), Pass.POST_UPDATE_ALL);
- PostHighlightingPassFactory.markFileUpToDate(myFile);
-
- Editor editor = myEditor;
- if (editor != null && timeToOptimizeImports()) {
- optimizeImportsOnTheFly(editor);
- }
- }
-
- private void optimizeImportsOnTheFly(@NotNull final Editor editor) {
- if (myHasRedundantImports || myHasMissortedImports) {
- final OptimizeImportsFix optimizeImportsFix = new OptimizeImportsFix();
- if (optimizeImportsFix.isAvailable(myProject, editor, myFile) && myFile.isWritable()) {
- invokeOnTheFlyImportOptimizer(new Runnable() {
- @Override
- public void run() {
- optimizeImportsFix.invoke(myProject, editor, myFile);
- }
- }, myFile, editor);
- }
- }
- }
-
- public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
- @NotNull final PsiFile file,
- @NotNull final Editor editor) {
- final long stamp = editor.getDocument().getModificationStamp();
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
- //no need to optimize imports on the fly during undo/redo
- final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
- if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
- PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
- String beforeText = file.getText();
- final long oldStamp = editor.getDocument().getModificationStamp();
- CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
- @Override
- public void run() {
- ApplicationManager.getApplication().runWriteAction(runnable);
- }
- });
- if (oldStamp != editor.getDocument().getModificationStamp()) {
- String afterText = file.getText();
- if (Comparing.strEqual(beforeText, afterText)) {
- LOG.error(LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
- AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
- }
- }
- }
- });
- }
-
- // returns true if error highlight was created
- private boolean collectHighlights(@NotNull Collection<PsiElement> elements,
- @NotNull final List<HighlightInfo> result,
- @NotNull ProgressIndicator progress) throws ProcessCanceledException {
- ApplicationManager.getApplication().assertReadAccessAllowed();
-
- InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
- myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME);
- boolean unusedSymbolEnabled = profile.isToolEnabled(myUnusedSymbolKey, myFile);
- HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
- boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, myFile);
- myUnusedSymbolInspection = (UnusedSymbolLocalInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspection.SHORT_NAME, myFile);
- LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedSymbolInspection != null);
-
- myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);
- myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, myFile);
- myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, myFile);
-
- myUnusedParametersInspection = (UnusedParametersInspection)profile.getUnwrappedTool(UnusedParametersInspection.SHORT_NAME, myFile);
- LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || myUnusedParametersInspection != null);
- if (unusedImportEnabled && JspPsiUtil.isInJspFile(myFile)) {
- final JspFile jspFile = JspPsiUtil.getJspFile(myFile);
- if (jspFile != null) {
- unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile);
- }
- }
-
- myDeadCodeInfoType = myDeadCodeKey == null
- ? null
- : new HighlightInfoType.HighlightInfoTypeImpl(profile.getErrorLevel(myDeadCodeKey, myFile).getSeverity(),
- HighlightInfoType.UNUSED_SYMBOL.getAttributesKey());
-
- GlobalUsageHelper helper = new GlobalUsageHelper() {
- @Override
- public boolean shouldCheckUsages(@NotNull PsiMember member) {
- return !myInLibrary && myDeadCodeEnabled && !myDeadCodeInspection.isEntryPoint(member);
- }
-
- @Override
- public boolean isCurrentFileAlreadyChecked() {
- return true;
- }
-
- @Override
- public boolean isLocallyUsed(@NotNull PsiNamedElement member) {
- return myRefCountHolder.isReferenced(member);
- }
- };
-
- boolean errorFound = false;
- if (unusedSymbolEnabled) {
- for (PsiElement element : elements) {
- progress.checkCanceled();
- if (element instanceof PsiIdentifier) {
- PsiIdentifier identifier = (PsiIdentifier)element;
- HighlightInfo info = processIdentifier(identifier, progress, helper);
- if (info != null) {
- errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
- result.add(info);
- }
- }
- }
- }
- if (unusedImportEnabled && myFile instanceof PsiJavaFile && HighlightingLevelManager.getInstance(myProject).shouldHighlight(myFile)) {
- PsiImportList importList = ((PsiJavaFile)myFile).getImportList();
- if (importList != null) {
- final PsiImportStatementBase[] imports = importList.getAllImportStatements();
- for (PsiImportStatementBase statement : imports) {
- progress.checkCanceled();
- final HighlightInfo info = processImport(statement, unusedImportKey);
- if (info != null) {
- errorFound |= info.getSeverity() == HighlightSeverity.ERROR;
- result.add(info);
- }
- }
- }
- }
-
- return errorFound;
- }
-
- @Nullable
- private HighlightInfo processIdentifier(PsiIdentifier identifier, ProgressIndicator progress, GlobalUsageHelper helper) {
- if (SuppressionUtil.inspectionResultSuppressed(identifier, myUnusedSymbolInspection)) return null;
- PsiElement parent = identifier.getParent();
- if (PsiUtilCore.hasErrorElementChild(parent)) return null;
-
- if (parent instanceof PsiLocalVariable && myUnusedSymbolInspection.LOCAL_VARIABLE) {
- return processLocalVariable((PsiLocalVariable)parent, identifier, progress);
- }
- if (parent instanceof PsiField && myUnusedSymbolInspection.FIELD) {
- return processField((PsiField)parent, identifier, progress, helper);
- }
- if (parent instanceof PsiParameter && myUnusedSymbolInspection.PARAMETER) {
- if (SuppressionUtil.isSuppressed(identifier, UnusedParametersInspection.SHORT_NAME)) return null;
- return processParameter((PsiParameter)parent, identifier, progress);
- }
- if (parent instanceof PsiMethod && myUnusedSymbolInspection.METHOD) {
- return processMethod((PsiMethod)parent, identifier, progress, helper);
- }
- if (parent instanceof PsiClass && myUnusedSymbolInspection.CLASS) {
- return processClass((PsiClass)parent, identifier, progress, helper);
- }
- return null;
- }
-
- @Nullable
- private HighlightInfo processLocalVariable(@NotNull PsiLocalVariable variable,
- @NotNull PsiIdentifier identifier,
- @NotNull ProgressIndicator progress) {
- if (variable instanceof PsiResourceVariable && PsiUtil.isIgnoredName(variable.getName())) return null;
- if (isImplicitUsage(variable, progress)) return null;
-
- if (!myRefCountHolder.isReferenced(variable)) {
- String message = JavaErrorMessages.message("local.variable.is.never.used", identifier.getText());
- HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
- IntentionAction fix = variable instanceof PsiResourceVariable ? new RenameToIgnoredFix(variable) : new RemoveUnusedVariableFix(variable);
- QuickFixAction.registerQuickFixAction(highlightInfo, fix, myUnusedSymbolKey);
- return highlightInfo;
- }
-
- boolean referenced = myRefCountHolder.isReferencedForRead(variable);
- if (!referenced && !isImplicitRead(variable, progress)) {
- String message = JavaErrorMessages.message("local.variable.is.not.used.for.reading", identifier.getText());
- HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(variable), myUnusedSymbolKey);
- return highlightInfo;
- }
-
- if (!variable.hasInitializer()) {
- referenced = myRefCountHolder.isReferencedForWrite(variable);
- if (!referenced && !isImplicitWrite(variable, progress)) {
- String message = JavaErrorMessages.message("local.variable.is.not.assigned", identifier.getText());
- final HighlightInfo unusedSymbolInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(unusedSymbolInfo, new EmptyIntentionAction(UnusedSymbolLocalInspection.DISPLAY_NAME), myUnusedSymbolKey);
- return unusedSymbolInfo;
- }
- }
-
- return null;
- }
-
- public static boolean isImplicitUsage(final PsiModifierListOwner element, ProgressIndicator progress) {
- if (UnusedSymbolLocalInspection.isInjected(element)) return true;
- for (ImplicitUsageProvider provider : ourImplicitUsageProviders) {
- progress.checkCanceled();
- if (provider.isImplicitUsage(element)) {
- return true;
- }
- }
-
- return false;
- }
-
- private static boolean isImplicitRead(final PsiVariable element, ProgressIndicator progress) {
- for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
- progress.checkCanceled();
- if (provider.isImplicitRead(element)) {
- return true;
- }
- }
- return UnusedSymbolLocalInspection.isInjected(element);
- }
-
- private static boolean isImplicitWrite(final PsiVariable element, ProgressIndicator progress) {
- for(ImplicitUsageProvider provider: ourImplicitUsageProviders) {
- progress.checkCanceled();
- if (provider.isImplicitWrite(element)) {
- return true;
- }
- }
- return UnusedSymbolLocalInspection.isInjected(element);
- }
-
- @Nullable
- public static HighlightInfo createUnusedSymbolInfo(@NotNull PsiElement element, @NotNull String message, @NotNull final HighlightInfoType highlightInfoType) {
- HighlightInfo info = HighlightInfo.newHighlightInfo(highlightInfoType).range(element).descriptionAndTooltip(message).create();
- if (info == null) {
- return null; //filtered out
- }
-
- UnusedDeclarationFixProvider[] fixProviders = Extensions.getExtensions(UnusedDeclarationFixProvider.EP_NAME);
- for (UnusedDeclarationFixProvider provider : fixProviders) {
- IntentionAction[] fixes = provider.getQuickFixes(element);
- for (IntentionAction fix : fixes) {
- QuickFixAction.registerQuickFixAction(info, fix);
- }
- }
- return info;
- }
-
- @Nullable
- private HighlightInfo processField(@NotNull final PsiField field,
- @NotNull PsiIdentifier identifier,
- @NotNull ProgressIndicator progress,
- @NotNull GlobalUsageHelper helper) {
- if (HighlightUtil.isSerializationImplicitlyUsedField(field)) {
- return null;
- }
- if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
- if (!myRefCountHolder.isReferenced(field) && !isImplicitUsage(field, progress)) {
- String message = JavaErrorMessages.message("private.field.is.not.used", identifier.getText());
-
- HighlightInfo highlightInfo = suggestionsToMakeFieldUsed(field, identifier, message);
- if (!field.hasInitializer()) {
- QuickFixAction.registerQuickFixAction(highlightInfo, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field));
- }
- return highlightInfo;
- }
-
- final boolean readReferenced = myRefCountHolder.isReferencedForRead(field);
- if (!readReferenced && !isImplicitRead(field, progress)) {
- String message = JavaErrorMessages.message("private.field.is.not.used.for.reading", identifier.getText());
- return suggestionsToMakeFieldUsed(field, identifier, message);
- }
-
- if (field.hasInitializer()) {
- return null;
- }
- final boolean writeReferenced = myRefCountHolder.isReferencedForWrite(field);
- if (!writeReferenced && !isImplicitWrite(field, progress)) {
- String message = JavaErrorMessages.message("private.field.is.not.assigned", identifier.getText());
- final HighlightInfo info = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
-
- QuickFixAction.registerQuickFixAction(info, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
- QuickFixAction.registerQuickFixAction(info, HighlightMethodUtil.getFixRange(field), new CreateConstructorParameterFromFieldFix(field));
- SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(field, new Processor<String>() {
- @Override
- public boolean process(final String annoName) {
- QuickFixAction.registerQuickFixAction(info, UnusedSymbolLocalInspection.createQuickFix(annoName, "fields", field.getProject()));
- return true;
- }
- });
- return info;
- }
- }
- else if (isImplicitUsage(field, progress)) {
- return null;
- }
- else if (isFieldUnused(field, progress, helper)) {
- return formatUnusedSymbolHighlightInfo("field.is.not.used", field, "fields", myDeadCodeKey, myDeadCodeInfoType, identifier);
- }
- return null;
- }
-
- public static boolean isFieldUnused(PsiField field, ProgressIndicator progress, GlobalUsageHelper helper) {
- if (helper.isLocallyUsed(field) || !weAreSureThereAreNoUsages(field, progress, helper)) {
- return false;
- }
- return !(field instanceof PsiEnumConstant) || !isEnumValuesMethodUsed(field, progress, helper);
- }
-
- private HighlightInfo suggestionsToMakeFieldUsed(final PsiField field, final PsiIdentifier identifier, final String message) {
- HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
- QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedVariableFix(field), myUnusedSymbolKey);
- QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, false, field), myUnusedSymbolKey);
- QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(false, true, field), myUnusedSymbolKey);
- QuickFixAction.registerQuickFixAction(highlightInfo, new CreateGetterOrSetterFix(true, true, field), myUnusedSymbolKey);
- return highlightInfo;
- }
-
- private static boolean isOverriddenOrOverrides(PsiMethod method) {
- boolean overrides = SuperMethodsSearch.search(method, null, true, false).findFirst() != null;
- return overrides || OverridingMethodsSearch.search(method).findFirst() != null;
- }
-
- @Nullable
- private HighlightInfo processParameter(@NotNull PsiParameter parameter,
- @NotNull PsiIdentifier identifier,
- @NotNull ProgressIndicator progress) {
- PsiElement declarationScope = parameter.getDeclarationScope();
- if (declarationScope instanceof PsiMethod) {
- PsiMethod method = (PsiMethod)declarationScope;
- if (PsiUtilCore.hasErrorElementChild(method)) return null;
- if ((method.isConstructor() ||
- method.hasModifierProperty(PsiModifier.PRIVATE) ||
- method.hasModifierProperty(PsiModifier.STATIC) ||
- !method.hasModifierProperty(PsiModifier.ABSTRACT) &&
- myUnusedSymbolInspection.REPORT_PARAMETER_FOR_PUBLIC_METHODS &&
- !isOverriddenOrOverrides(method)) &&
- !method.hasModifierProperty(PsiModifier.NATIVE) &&
- !JavaHighlightUtil.isSerializationRelatedMethod(method, method.getContainingClass()) &&
- !PsiClassImplUtil.isMainOrPremainMethod(method)) {
- if (UnusedSymbolLocalInspection.isInjected(method)) return null;
- HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
- if (highlightInfo != null) {
- List<IntentionAction> options = new ArrayList<IntentionAction>();
- options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, myFile));
- if (myUnusedParametersInspection != null) {
- SuppressQuickFix[] batchSuppressActions = myUnusedParametersInspection.getBatchSuppressActions(parameter);
- Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions));
- }
- //need suppress from Unused Parameters but settings from Unused Symbol
- QuickFixAction.registerQuickFixAction(highlightInfo, new RemoveUnusedParameterFix(parameter),
- options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey));
- return highlightInfo;
- }
- }
- }
- else if (declarationScope instanceof PsiForeachStatement && !PsiUtil.isIgnoredName(parameter.getName())) {
- HighlightInfo highlightInfo = checkUnusedParameter(parameter, identifier, progress);
- if (highlightInfo != null) {
- QuickFixAction.registerQuickFixAction(highlightInfo, new RenameToIgnoredFix(parameter), myUnusedSymbolKey);
- return highlightInfo;
- }
- }
-
- return null;
- }
-
- @Nullable
- private HighlightInfo checkUnusedParameter(@NotNull PsiParameter parameter,
- @NotNull PsiIdentifier identifier,
- @NotNull ProgressIndicator progress) {
- if (!myRefCountHolder.isReferenced(parameter) && !isImplicitUsage(parameter, progress)) {
- String message = JavaErrorMessages.message("parameter.is.not.used", identifier.getText());
- return createUnusedSymbolInfo(identifier, message, HighlightInfoType.UNUSED_SYMBOL);
- }
- return null;
- }
-
- @Nullable
- private HighlightInfo processMethod(@NotNull final PsiMethod method,
- @NotNull PsiIdentifier identifier,
- @NotNull ProgressIndicator progress,
- @NotNull GlobalUsageHelper helper) {
- if (isMethodReferenced(method, progress, helper)) return null;
- HighlightInfoType highlightInfoType;
- HighlightDisplayKey highlightDisplayKey;
- String key;
- if (method.hasModifierProperty(PsiModifier.PRIVATE)) {
- highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
- highlightDisplayKey = myUnusedSymbolKey;
- key = method.isConstructor() ? "private.constructor.is.not.used" : "private.method.is.not.used";
- }
- else {
- highlightInfoType = myDeadCodeInfoType;
- highlightDisplayKey = myDeadCodeKey;
- key = method.isConstructor() ? "constructor.is.not.used" : "method.is.not.used";
- }
- String symbolName = HighlightMessageUtil.getSymbolName(method, PsiSubstitutor.EMPTY);
- String message = JavaErrorMessages.message(key, symbolName);
- final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
- QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), highlightDisplayKey);
- SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes(method, new Processor<String>() {
- @Override
- public boolean process(final String annoName) {
- QuickFixAction
- .registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, "methods", method.getProject()));
- return true;
- }
- });
- PsiClass containingClass = method.getContainingClass();
- if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) {
- //ignore methods with deleted return types as they are always marked as unused without any reason
- ChangeSignatureGestureDetector.getInstance(myProject).dismissForElement(method);
- }
- return highlightInfo;
- }
-
- public static boolean isMethodReferenced(PsiMethod method,
- ProgressIndicator progress,
- GlobalUsageHelper helper) {
- if (helper.isLocallyUsed(method)) return true;
-
- boolean aPrivate = method.hasModifierProperty(PsiModifier.PRIVATE);
- PsiClass containingClass = method.getContainingClass();
- if (JavaHighlightUtil.isSerializationRelatedMethod(method, containingClass)) return true;
- if (aPrivate) {
- if (isIntentionalPrivateConstructor(method, containingClass)) {
- return true;
- }
- if (isImplicitUsage(method, progress)) {
- return true;
- }
- if (!helper.isCurrentFileAlreadyChecked()) {
- return !weAreSureThereAreNoUsages(method, progress, helper);
- }
- }
- else {
- //class maybe used in some weird way, e.g. from XML, therefore the only constructor is used too
- if (containingClass != null && method.isConstructor()
- && containingClass.getConstructors().length == 1
- && isClassUsed(containingClass, progress, helper)) {
- return true;
- }
- if (isImplicitUsage(method, progress)) return true;
-
- if (method.findSuperMethods().length != 0) {
- return true;
- }
- if (!weAreSureThereAreNoUsages(method, progress, helper)) {
- return true;
- }
- }
- return false;
- }
-
- private static boolean weAreSureThereAreNoUsages(@NotNull PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
- if (!helper.shouldCheckUsages(member)) return false;
-
- String name = member.getName();
- if (name == null) return false;
- SearchScope useScope = member.getUseScope();
- Project project = member.getProject();
- if (useScope instanceof GlobalSearchScope) {
- // some classes may have references from within XML outside dependent modules, e.g. our actions
- if (member instanceof PsiClass) {
- useScope = GlobalSearchScope.projectScope(project).uniteWith((GlobalSearchScope)useScope);
- }
-
- PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
- PsiFile file = member.getContainingFile();
- PsiFile ignoreFile = helper.isCurrentFileAlreadyChecked() ? file : null;
- PsiSearchHelper.SearchCostResult cheapEnough = searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, ignoreFile, progress);
- if (cheapEnough == TOO_MANY_OCCURRENCES) return false;
-
- //search usages if it cheap
- //if count is 0 there is no usages since we've called myRefCountHolder.isReferenced() before
- if (cheapEnough == ZERO_OCCURRENCES) {
- if (!canBeReferencedViaWeirdNames(member)) return true;
- }
-
- if (member instanceof PsiMethod) {
- String propertyName = PropertyUtil.getPropertyName(member);
- if (propertyName != null && file != null) {
- SearchScope fileScope = file.getUseScope();
- if (fileScope instanceof GlobalSearchScope &&
- searchHelper.isCheapEnoughToSearch(propertyName, (GlobalSearchScope)fileScope, ignoreFile, progress) == TOO_MANY_OCCURRENCES) {
- return false;
- }
- }
- }
- }
- FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
- FindUsagesHandler handler = new JavaFindUsagesHandler(member, new JavaFindUsagesHandlerFactory(project));
- FindUsagesOptions findUsagesOptions = handler.getFindUsagesOptions().clone();
- findUsagesOptions.searchScope = useScope;
- findUsagesOptions.isSearchForTextOccurrences = true;
- return !findUsagesManager.isUsed(member, findUsagesOptions);
- }
-
- private static boolean isEnumValuesMethodUsed(PsiMember member, ProgressIndicator progress, GlobalUsageHelper helper) {
- final PsiClass containingClass = member.getContainingClass();
- if (containingClass == null || !(containingClass instanceof PsiClassImpl)) return true;
- final PsiMethod valuesMethod = ((PsiClassImpl)containingClass).getValuesMethod();
- return valuesMethod == null || isMethodReferenced(valuesMethod, progress, helper);
- }
-
- private static boolean canBeReferencedViaWeirdNames(PsiMember member) {
- if (member instanceof PsiClass) return false;
- PsiFile containingFile = member.getContainingFile();
- if (!(containingFile instanceof PsiJavaFile)) return true; // Groovy field can be referenced from Java by getter
- if (member instanceof PsiField) return false; //Java field cannot be referenced by anything but its name
- if (member instanceof PsiMethod) {
- return PropertyUtil.isSimplePropertyAccessor((PsiMethod)member); //Java accessors can be referenced by field name from Groovy
- }
- return false;
- }
-
- @Nullable
- private HighlightInfo processClass(@NotNull PsiClass aClass,
- @NotNull PsiIdentifier identifier,
- @NotNull ProgressIndicator progress,
- @NotNull GlobalUsageHelper helper) {
- if (isClassUsed(aClass, progress, helper)) return null;
-
- String pattern;
- HighlightDisplayKey highlightDisplayKey;
- HighlightInfoType highlightInfoType;
- if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE)) {
- pattern = aClass.isInterface()
- ? "private.inner.interface.is.not.used"
- : "private.inner.class.is.not.used";
- highlightDisplayKey = myUnusedSymbolKey;
- highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
- }
- else if (aClass.getParent() instanceof PsiDeclarationStatement) { // local class
- pattern = "local.class.is.not.used";
- highlightDisplayKey = myUnusedSymbolKey;
- highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
- }
- else if (aClass instanceof PsiTypeParameter) {
- pattern = "type.parameter.is.not.used";
- highlightDisplayKey = myUnusedSymbolKey;
- highlightInfoType = HighlightInfoType.UNUSED_SYMBOL;
- }
- else {
- pattern = "class.is.not.used";
- highlightDisplayKey = myDeadCodeKey;
- highlightInfoType = myDeadCodeInfoType;
- }
- return formatUnusedSymbolHighlightInfo(pattern, aClass, "classes", highlightDisplayKey, highlightInfoType, identifier);
- }
-
- public static boolean isClassUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
- if (aClass == null) return true;
- Boolean result = helper.unusedClassCache.get(aClass);
- if (result == null) {
- result = isReallyUsed(aClass, progress, helper);
- helper.unusedClassCache.put(aClass, result);
- }
- return result;
- }
-
- private static boolean isReallyUsed(PsiClass aClass, ProgressIndicator progress, GlobalUsageHelper helper) {
- if (isImplicitUsage(aClass, progress) || helper.isLocallyUsed(aClass)) return true;
- if (helper.isCurrentFileAlreadyChecked()) {
- if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.PRIVATE) ||
- aClass.getParent() instanceof PsiDeclarationStatement ||
- aClass instanceof PsiTypeParameter) return false;
- }
- return !weAreSureThereAreNoUsages(aClass, progress, helper);
- }
-
- private static HighlightInfo formatUnusedSymbolHighlightInfo(@NotNull @PropertyKey(resourceBundle = JavaErrorMessages.BUNDLE) String pattern,
- @NotNull final PsiNameIdentifierOwner aClass,
- @NotNull final String element,
- @NotNull HighlightDisplayKey highlightDisplayKey,
- @NotNull HighlightInfoType highlightInfoType,
- @NotNull PsiElement identifier) {
- String symbolName = aClass.getName();
- String message = JavaErrorMessages.message(pattern, symbolName);
- final HighlightInfo highlightInfo = createUnusedSymbolInfo(identifier, message, highlightInfoType);
- QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(aClass), highlightDisplayKey);
- SpecialAnnotationsUtilBase.createAddToSpecialAnnotationFixes((PsiModifierListOwner)aClass, new Processor<String>() {
- @Override
- public boolean process(final String annoName) {
- QuickFixAction
- .registerQuickFixAction(highlightInfo, UnusedSymbolLocalInspection.createQuickFix(annoName, element, aClass.getProject()));
- return true;
- }
- });
- return highlightInfo;
- }
-
- @Nullable
- private HighlightInfo processImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
- // jsp include directive hack
- if (importStatement instanceof JspxImportStatement && ((JspxImportStatement)importStatement).isForeignFileImport()) return null;
-
- if (PsiUtilCore.hasErrorElementChild(importStatement)) return null;
-
- boolean isRedundant = myRefCountHolder.isRedundant(importStatement);
- if (!isRedundant && !(importStatement instanceof PsiImportStaticStatement)) {
- //check import from same package
- String packageName = ((PsiClassOwner)importStatement.getContainingFile()).getPackageName();
- PsiJavaCodeReferenceElement reference = importStatement.getImportReference();
- PsiElement resolved = reference == null ? null : reference.resolve();
- if (resolved instanceof PsiPackage) {
- isRedundant = packageName.equals(((PsiQualifiedNamedElement)resolved).getQualifiedName());
- }
- else if (resolved instanceof PsiClass && !importStatement.isOnDemand()) {
- String qName = ((PsiClass)resolved).getQualifiedName();
- if (qName != null) {
- String name = ((PomNamedTarget)resolved).getName();
- isRedundant = qName.equals(packageName + '.' + name);
- }
- }
- }
-
- if (isRedundant) {
- return registerRedundantImport(importStatement, unusedImportKey);
- }
-
- int entryIndex = myStyleManager.findEntryIndex(importStatement);
- if (entryIndex < myCurrentEntryIndex) {
- myHasMissortedImports = true;
- }
- myCurrentEntryIndex = entryIndex;
-
- return null;
- }
-
- private HighlightInfo registerRedundantImport(@NotNull PsiImportStatementBase importStatement, @NotNull HighlightDisplayKey unusedImportKey) {
- String description = InspectionsBundle.message("unused.import.statement");
- HighlightInfo info =
- HighlightInfo.newHighlightInfo(JavaHighlightInfoTypes.UNUSED_IMPORT).range(importStatement).descriptionAndTooltip(description)
- .create();
-
- QuickFixAction.registerQuickFixAction(info, new OptimizeImportsFix(), unusedImportKey);
- QuickFixAction.registerQuickFixAction(info, new EnableOptimizeImportsOnTheFlyFix(), unusedImportKey);
- myHasRedundantImports = true;
- return info;
- }
-
- private boolean timeToOptimizeImports() {
- if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
-
- DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(myProject);
- PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
- // dont optimize out imports in JSP since it can be included in other JSP
- if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
-
- if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
- boolean errors = containsErrorsPreventingOptimize(file);
-
- return !errors && DaemonListeners.canChangeFileSilently(myFile);
- }
-
- private boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) {
- // ignore unresolved imports errors
- PsiImportList importList = ((PsiJavaFile)file).getImportList();
- final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange();
- boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx
- .processHighlights(myDocument, myProject, HighlightSeverity.ERROR, 0, myDocument.getTextLength(), new Processor<HighlightInfo>() {
- @Override
- public boolean process(HighlightInfo error) {
- int infoStart = error.getActualStartOffset();
- int infoEnd = error.getActualEndOffset();
-
- return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF);
- }
- });
-
- return hasErrorsExceptUnresolvedImports;
- }
-
- private static boolean isIntentionalPrivateConstructor(@NotNull PsiMethod method, PsiClass containingClass) {
- return method.isConstructor() &&
- method.getParameterList().getParametersCount() == 0 &&
- containingClass != null &&
- containingClass.getConstructors().length == 1;
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java
index 0a3e6a7..54a9bc2 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/PostHighlightingPassFactory.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,27 +19,46 @@
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
import com.intellij.codeHighlighting.TextEditorHighlightingPassRegistrar;
-import com.intellij.codeInsight.daemon.ProblemHighlightFilter;
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
+import com.intellij.codeInspection.InspectionProfile;
+import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
+import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.JspPsiUtil;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.util.PsiModificationTracker;
+import com.intellij.psi.jsp.JspFile;
+import com.intellij.psi.jsp.JspSpiUtil;
+import com.intellij.util.containers.Predicate;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
+
/**
* @author cdr
*/
public class PostHighlightingPassFactory extends AbstractProjectComponent implements MainHighlightingPassFactory {
- private static final Key<Long> LAST_POST_PASS_TIMESTAMP = Key.create("LAST_POST_PASS_TIMESTAMP");
- public PostHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.PostHighlightingPassFactory");
+
+ public PostHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar, HighlightVisitorImpl hvi) {
super(project);
highlightingPassRegistrar.registerTextEditorHighlightingPass(this, new int[]{Pass.UPDATE_ALL,}, null, true, Pass.POST_UPDATE_ALL);
+
+ if (hvi == null) {
+ HighlightVisitor[] extensions = Extensions.getExtensions(HighlightVisitor.EP_HIGHLIGHT_VISITOR, myProject);
+ LOG.error("com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl is unregistered; all available highlight visitors are: "+
+ Arrays.asList(extensions));
+ }
}
@Override
@@ -53,26 +72,44 @@
@Nullable
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) {
TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.UPDATE_ALL);
- if (textRange == null) {
- Long lastStamp = file.getUserData(LAST_POST_PASS_TIMESTAMP);
- long currentStamp = PsiModificationTracker.SERVICE.getInstance(myProject).getModificationCount();
- if (lastStamp != null && lastStamp == currentStamp || !ProblemHighlightFilter.shouldHighlightFile(file)) {
- return null;
- }
- }
+ if (textRange == null && PostHighlightingPass.isUpToDate(file)) return null;
- return new PostHighlightingPass(myProject, file, editor, editor.getDocument(), new DefaultHighlightInfoProcessor());
+ return create(file, editor.getDocument(), editor, new DefaultHighlightInfoProcessor());
}
@Override
public TextEditorHighlightingPass createMainHighlightingPass(@NotNull PsiFile file,
@NotNull Document document,
@NotNull HighlightInfoProcessor highlightInfoProcessor) {
- return new PostHighlightingPass(myProject, file, null, document, highlightInfoProcessor);
+ return create(file, document, null, highlightInfoProcessor);
}
- public static void markFileUpToDate(@NotNull PsiFile file) {
- long lastStamp = PsiModificationTracker.SERVICE.getInstance(file.getProject()).getModificationCount();
- file.putUserData(LAST_POST_PASS_TIMESTAMP, lastStamp);
+ private PostHighlightingPass create(@NotNull PsiFile file,
+ @NotNull Document document, Editor editor,
+ @NotNull HighlightInfoProcessor highlightInfoProcessor) {
+ HighlightDisplayKey unusedImportKey = HighlightDisplayKey.find(UnusedImportLocalInspection.SHORT_NAME);
+ InspectionProfile profile = InspectionProjectProfileManager.getInstance(file.getProject()).getInspectionProfile();
+ boolean importEnabled = isUnusedImportEnabled(unusedImportKey, file, profile);
+ final UnusedDeclarationInspection myDeadCodeInspection = (UnusedDeclarationInspection)profile.getUnwrappedTool(UnusedDeclarationInspection.SHORT_NAME, file);
+ HighlightDisplayKey myDeadCodeKey = HighlightDisplayKey.find(UnusedDeclarationInspection.SHORT_NAME);
+ final boolean myDeadCodeEnabled = profile.isToolEnabled(myDeadCodeKey, file);
+
+ return new PostHighlightingPass(myProject, file, editor, document, highlightInfoProcessor, importEnabled, new Predicate<PsiElement>() {
+ @Override
+ public boolean apply(PsiElement member) {
+ return !myDeadCodeEnabled || myDeadCodeInspection.isEntryPoint(member);
+ }
+ });
+ }
+
+ private static boolean isUnusedImportEnabled(HighlightDisplayKey unusedImportKey, @NotNull PsiFile file, InspectionProfile profile) {
+ boolean unusedImportEnabled = profile.isToolEnabled(unusedImportKey, file);
+ if (unusedImportEnabled && JspPsiUtil.isInJspFile(file)) {
+ final JspFile jspFile = JspPsiUtil.getJspFile(file);
+ if (jspFile != null) {
+ unusedImportEnabled = !JspSpiUtil.isIncludedOrIncludesSomething(jspFile);
+ }
+ }
+ return unusedImportEnabled;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java
index 6009eb3..7e70dbe 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddExceptionToThrowsFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -77,10 +77,10 @@
QuickFixBundle.message("method.is.inherited.warning.title"),
Messages.getQuestionIcon());
- if (result == 0) {
+ if (result == Messages.YES) {
processSuperMethods = true;
}
- else if (result == 1) {
+ else if (result == Messages.NO) {
processSuperMethods = false;
}
else {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java
index 7891773..9a6ba5c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/AddModuleDependencyFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -179,7 +179,7 @@
int ret = Messages.showOkCancelDialog(project, message,
QuickFixBundle.message("orderEntry.fix.title.circular.dependency.warning"),
Messages.getWarningIcon());
- if (ret == 0) {
+ if (ret == Messages.OK) {
ApplicationManager.getApplication().runWriteAction(doit);
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
index 0814f8f..16eb888 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageBaseFix.java
@@ -287,7 +287,17 @@
PsiJavaCodeReferenceElement ref = newExpression.getClassOrAnonymousClassReference();
if (ref != null) {
PsiElement refElement = ref.resolve();
- if (refElement instanceof PsiClass) psiClass = (PsiClass)refElement;
+ if (refElement instanceof PsiClass) {
+ psiClass = (PsiClass)refElement;
+ } else {
+ final PsiElement refQualifier = ref.getQualifier();
+ if (refQualifier instanceof PsiJavaCodeReferenceElement) {
+ refElement = ((PsiJavaCodeReferenceElement)refQualifier).resolve();
+ if (refElement instanceof PsiClass) {
+ psiClass = (PsiClass)refElement;
+ }
+ }
+ }
}
}
else if (element instanceof PsiReferenceExpression) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
index 401833a..1df89f7 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateFromUsageUtils.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.
@@ -578,7 +578,7 @@
PsiElement parent = expr.getParent();
if (!(parent instanceof PsiReferenceExpression)) {
- ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, false);
+ ExpectedTypeInfo[] someExpectedTypes = ExpectedTypesProvider.getExpectedTypes(expr, PsiUtil.skipParenthesizedExprUp(parent) instanceof PsiExpressionList);
if (someExpectedTypes.length > 0) {
Arrays.sort(someExpectedTypes, new Comparator<ExpectedTypeInfo>() {
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
index dba7da8..209dde6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateGetterOrSetterFix.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,7 +40,7 @@
private final PsiField myField;
private final String myPropertyName;
- public CreateGetterOrSetterFix(boolean createGetter, boolean createSetter, PsiField field) {
+ public CreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) {
myCreateGetter = createGetter;
myCreateSetter = createSetter;
myField = field;
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java
index dfcb0ee..55fe766 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateInnerClassFromNewFix.java
@@ -54,12 +54,15 @@
PsiClass created = elementFactory.createClass(refName);
final PsiModifierList modifierList = created.getModifierList();
LOG.assertTrue(modifierList != null);
- if (targetClass.isInterface()) {
- modifierList.setModifierProperty(PsiModifier.PACKAGE_LOCAL, true);
- } else {
- modifierList.setModifierProperty(PsiModifier.PRIVATE, true);
+ if (PsiTreeUtil.isAncestor(targetClass, newExpression, true)) {
+ if (targetClass.isInterface()) {
+ modifierList.setModifierProperty(PsiModifier.PACKAGE_LOCAL, true);
+ } else {
+ modifierList.setModifierProperty(PsiModifier.PRIVATE, true);
+ }
}
- if (PsiUtil.getEnclosingStaticElement(newExpression, targetClass) != null || isInThisOrSuperCall(newExpression)) {
+
+ if (!PsiTreeUtil.isAncestor(targetClass, newExpression, true) || PsiUtil.getEnclosingStaticElement(newExpression, targetClass) != null || isInThisOrSuperCall(newExpression)) {
modifierList.setModifierProperty(PsiModifier.STATIC, true);
}
created = (PsiClass)targetClass.add(created);
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java
index f697144..b5dc43e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/DefaultQuickFixProvider.java
@@ -22,12 +22,14 @@
import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.EnumMap;
import java.util.Map;
@@ -100,7 +102,7 @@
}
}
- @NotNull
+ @Nullable
private static VariableKind getKind(@NotNull JavaCodeStyleManager styleManager, @NotNull PsiReferenceExpression refExpr) {
final String reference = refExpr.getText();
@@ -121,6 +123,10 @@
}
}
+ if (StringUtil.isCapitalized(reference)) {
+ return null;
+ }
+
return VariableKind.LOCAL_VARIABLE;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java
index b001e4d..e9cee8c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/GuessTypeParameters.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -81,13 +81,13 @@
if (infos.length == 1 && substitutor != null && substitutor != PsiSubstitutor.EMPTY) {
ExpectedTypeInfo info = infos[0];
Map<PsiTypeParameter, PsiType> map = substitutor.getSubstitutionMap();
- PsiType[] vals = map.values().toArray(new PsiType[map.size()]);
+ PsiType[] vals = map.values().toArray(PsiType.createArray(map.size()));
PsiTypeParameter[] params = map.keySet().toArray(new PsiTypeParameter[map.size()]);
List<PsiType> types = matchingTypeParameters(vals, params, info);
if (!types.isEmpty()) {
ContainerUtil.addAll(types, ExpectedTypesProvider.processExpectedTypes(infos, new MyTypeVisitor(manager, scope), project));
- builder.replaceElement(typeElement, new TypeExpression(project, types.toArray(new PsiType[types.size()])));
+ builder.replaceElement(typeElement, new TypeExpression(project, types.toArray(PsiType.createArray(types.size()))));
return;
}
else {
@@ -180,8 +180,8 @@
if (!CommonClassNames.JAVA_LANG_OBJECT.equals(substituted.getCanonicalText()) && (toplevel || substituted.equals(type))) {
types.add(substituted);
}
-
- builder.replaceElement(typeElement, new TypeExpression(project, types.toArray(new PsiType[types.size()])));
+
+ builder.replaceElement(typeElement, new TypeExpression(project, types.toArray(PsiType.createArray(types.size()))));
return toplevel ? SUBSTITUTED_IN_REF : SUBSTITUTED_IN_PARAMETERS;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
index eae38cc..715da62 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImplementMethodsFix.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.
@@ -50,7 +50,7 @@
@Override
@NotNull
public String getFamilyName() {
- return QuickFixBundle.message("implement.methods.fix");
+ return getText();
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
index ad23526..8047486 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ImportClassFixBase.java
@@ -18,6 +18,7 @@
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.FileModificationService;
+import com.intellij.codeInsight.ImportFilter;
import com.intellij.codeInsight.completion.JavaCompletionUtil;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzerSettings;
import com.intellij.codeInsight.daemon.QuickFixBundle;
@@ -112,6 +113,7 @@
if (classes.length == 0) return Collections.emptyList();
List<PsiClass> classList = new ArrayList<PsiClass>(classes.length);
boolean isAnnotationReference = myElement.getParent() instanceof PsiAnnotation;
+ final PsiFile file = myElement.getContainingFile();
for (PsiClass aClass : classes) {
if (isAnnotationReference && !aClass.isAnnotationType()) continue;
if (JavaCompletionUtil.isInExcludedPackage(aClass, false)) continue;
@@ -119,7 +121,7 @@
String qName = aClass.getQualifiedName();
if (qName != null) { //filter local classes
if (qName.indexOf('.') == -1) continue; //do not show classes from default package)
- if (qName.endsWith(name)) {
+ if (qName.endsWith(name) && (file == null || ImportFilter.shouldImport(file, qName))) {
if (isAccessible(aClass, myElement)) {
classList.add(aClass);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
index 0d71068..78d9a81 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/ModifierFix.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,7 +23,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.search.PsiElementProcessor;
@@ -185,7 +184,7 @@
if (Messages.showYesNoDialog(project,
QuickFixBundle.message("change.inheritors.visibility.warning.text"),
QuickFixBundle.message("change.inheritors.visibility.warning.title"),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getQuestionIcon()) == Messages.YES) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java
index 7a867df..d1c9989 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/OrderEntryFix.java
@@ -37,6 +37,7 @@
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.PsiShortNamesCache;
@@ -174,7 +175,12 @@
List<LocalQuickFix> result = new ArrayList<LocalQuickFix>();
Set<Object> librariesToAdd = new THashSet<Object>();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(psiElement.getProject());
- final PsiClass[] classes = PsiShortNamesCache.getInstance(project).getClassesByName(referenceName, GlobalSearchScope.allScope(project));
+ PsiClass[] classes = PsiShortNamesCache.getInstance(project).getClassesByName(referenceName, GlobalSearchScope.allScope(project));
+ List<PsiClass> allowedDependencies = filterAllowedDependencies(psiElement, classes);
+ if (allowedDependencies.isEmpty()) {
+ return result;
+ }
+ classes = allowedDependencies.toArray(new PsiClass[allowedDependencies.size()]);
final OrderEntryFix moduleDependencyFix = new AddModuleDependencyFix(currentModule, classVFile, classes, reference);
registrar.register(moduleDependencyFix);
result.add(moduleDependencyFix);
@@ -239,6 +245,18 @@
return result;
}
+ private static List<PsiClass> filterAllowedDependencies(PsiElement element, PsiClass[] classes) {
+ DependencyValidationManager dependencyValidationManager = DependencyValidationManager.getInstance(element.getProject());
+ PsiFile fromFile = element.getContainingFile();
+ List<PsiClass> result = new ArrayList<PsiClass>();
+ for (PsiClass psiClass : classes) {
+ if (dependencyValidationManager.getViolatorDependencyRule(fromFile, psiClass.getContainingFile()) == null) {
+ result.add(psiClass);
+ }
+ }
+ return result;
+ }
+
private static boolean isAnnotation(final PsiElement psiElement) {
return PsiTreeUtil.getParentOfType(psiElement, PsiAnnotation.class) != null && PsiUtil.isLanguageLevel5OrHigher(psiElement);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java
index 4d53c2c..4df807f 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/JavaSmartEnterProcessor.java
@@ -75,6 +75,7 @@
fixers.add(new ParenthesizedFixer());
fixers.add(new SemicolonFixer());
fixers.add(new MissingArrayInitializerBraceFixer());
+ fixers.add(new MissingArrayConstructorBracketFixer());
fixers.add(new EnumFieldFixer());
//ourFixers.add(new CompletionFixer());
ourFixers = fixers.toArray(new Fixer[fixers.size()]);
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java
new file mode 100644
index 0000000..5153062
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingArrayConstructorBracketFixer.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.editorActions.smartEnter;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.JavaTokenType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNewExpression;
+import com.intellij.util.IncorrectOperationException;
+
+public class MissingArrayConstructorBracketFixer implements Fixer {
+ @Override
+ public void apply(Editor editor, JavaSmartEnterProcessor processor, PsiElement psiElement) throws IncorrectOperationException {
+ if (!(psiElement instanceof PsiNewExpression)) return;
+ PsiNewExpression expr = (PsiNewExpression)psiElement;
+ int count = 0;
+ for (PsiElement element : expr.getChildren()) {
+ if (element.getNode().getElementType() == JavaTokenType.LBRACKET) {
+ count++;
+ } else if (element.getNode().getElementType() == JavaTokenType.RBRACKET) {
+ count--;
+ }
+ }
+ if (count > 0) {
+ editor.getDocument().insertString(psiElement.getTextRange().getEndOffset(), "]");
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingClassBodyFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingClassBodyFixer.java
index b99f988..355a0f4 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingClassBodyFixer.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingClassBodyFixer.java
@@ -16,7 +16,9 @@
PsiClass psiClass = (PsiClass) psiElement;
if (psiClass.getLBrace() == null) {
- editor.getDocument().insertString(psiClass.getTextRange().getEndOffset(), " {\n}");
+ int offset = psiClass.getTextRange().getEndOffset();
+ editor.getDocument().insertString(offset, " {\n}");
+ editor.getCaretModel().moveToOffset(offset);
}
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java
index b154594..f7f9459 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java
@@ -17,7 +17,6 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
@@ -57,10 +56,9 @@
}
return;
}
- int endOffset = method.getTextRange().getEndOffset();
- if (StringUtil.endsWithChar(method.getText(), ';')) {
- doc.deleteString(endOffset - 1, endOffset);
- endOffset--;
+ int endOffset = method.getThrowsList().getTextRange().getEndOffset();
+ if (endOffset < doc.getTextLength() && doc.getCharsSequence().charAt(endOffset) == ';') {
+ doc.deleteString(endOffset, endOffset + 1);
}
doc.insertString(endOffset, "{\n}");
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
index 4f77375..0fe5892 100644
--- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
+++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/PlainEnterProcessor.java
@@ -123,7 +123,7 @@
private static boolean processExistingBlankLine(@NotNull Editor editor, @Nullable PsiCodeBlock codeBlock, @Nullable PsiElement element) {
PsiWhiteSpace whiteSpace = null;
if (codeBlock == null) {
- if (element != null) {
+ if (element != null && !(element instanceof PsiMember)) {
final PsiElement next = PsiTreeUtil.nextLeaf(element);
if (next instanceof PsiWhiteSpace) {
whiteSpace = (PsiWhiteSpace)next;
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java
index 2151111..be7450b 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateDelegateHandler.java
@@ -32,17 +32,16 @@
import com.intellij.psi.scope.processor.VariablesProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.util.*;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* @author mike
@@ -239,7 +238,17 @@
List<PsiMethodMember> methodInstances = new ArrayList<PsiMethodMember>();
- final PsiMethod[] allMethods = targetClass.getAllMethods();
+ final PsiMethod[] allMethods;
+ if (targetClass instanceof PsiTypeParameter) {
+ LinkedHashSet<PsiMethod> meths = new LinkedHashSet<PsiMethod>();
+ for (PsiClass superClass : targetClass.getSupers()) {
+ meths.addAll(Arrays.asList(superClass.getAllMethods()));
+ }
+ allMethods = meths.toArray(new PsiMethod[meths.size()]);
+ }
+ else {
+ allMethods = targetClass.getAllMethods();
+ }
final Set<MethodSignature> signatures = new HashSet<MethodSignature>();
final Set<MethodSignature> existingSignatures = new HashSet<MethodSignature>(aClass.getVisibleSignatures());
final Set<PsiMethodMember> selection = new HashSet<PsiMethodMember>();
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHandler.java
index 2377b46..dbe45f7 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateEqualsHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,7 +23,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
@@ -67,7 +66,7 @@
if (Messages.showYesNoDialog(project, text,
CodeInsightBundle.message("generate.equals.and.hashcode.already.defined.title"),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getQuestionIcon()) == Messages.YES) {
if (!ApplicationManager.getApplication().runWriteAction(new Computable<Boolean>() {
@Override
public Boolean compute() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java
index f89d23b..a03fd18 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateMembersHandlerBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -69,7 +69,7 @@
final ClassMember[] members = chooseOriginalMembers(aClass, project, editor);
if (members == null) return;
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(project, new Runnable() {
@Override
public void run() {
doGenerate(project, editor, aClass, members);
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaBooleanExpressionSurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaBooleanExpressionSurrounder.java
new file mode 100644
index 0000000..9f0d1cc
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaBooleanExpressionSurrounder.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.generation.surroundWith;
+
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
+
+abstract public class JavaBooleanExpressionSurrounder extends JavaExpressionSurrounder {
+ @Override
+ public boolean isApplicable(PsiExpression expr) {
+ PsiType type = expr.getType();
+ return type != null && (PsiType.BOOLEAN.equals(type) || PsiType.BOOLEAN.equals(PsiPrimitiveType.getUnboxedType(type)));
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithCastSurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithCastSurrounder.java
index 7bd6e45..c2fe98a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithCastSurrounder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithCastSurrounder.java
@@ -33,7 +33,7 @@
import java.util.LinkedHashSet;
import java.util.Set;
-class JavaWithCastSurrounder extends JavaExpressionSurrounder {
+public class JavaWithCastSurrounder extends JavaExpressionSurrounder {
@NonNls private static final String TYPE_TEMPLATE_VARIABLE = "type";
@Override
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java
index bcfd4d0..aff61fa 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithIfExpressionSurrounder.java
@@ -1,6 +1,6 @@
/*
- * 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.
@@ -23,15 +23,14 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.util.FileTypeUtils;
+import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
-class JavaWithIfExpressionSurrounder extends JavaExpressionSurrounder{
+public class JavaWithIfExpressionSurrounder extends JavaBooleanExpressionSurrounder {
@Override
public boolean isApplicable(PsiExpression expr) {
- PsiType type = expr.getType();
- if (PsiType.BOOLEAN != type) return false;
+ if (!super.isApplicable(expr)) return false;
if (!expr.isPhysical()) return false;
PsiElement parent = expr.getParent();
if (!(parent instanceof PsiExpressionStatement)) return false;
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNotSurrounder.java b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNotSurrounder.java
index ebd9c59..0dd7a8d 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNotSurrounder.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/surroundWith/JavaWithNotSurrounder.java
@@ -1,6 +1,6 @@
/*
- * 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,12 +25,7 @@
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
import com.intellij.util.IncorrectOperationException;
-class JavaWithNotSurrounder extends JavaExpressionSurrounder{
- @Override
- public boolean isApplicable(PsiExpression expr) {
- return PsiType.BOOLEAN.equals(expr.getType());
- }
-
+class JavaWithNotSurrounder extends JavaBooleanExpressionSurrounder {
@Override
public TextRange surroundExpression(Project project, Editor editor, PsiExpression expr) throws IncorrectOperationException {
PsiManager manager = expr.getManager();
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java
index c051e3a..035a469 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/ui/GenerateEqualsWizard.java
@@ -17,6 +17,7 @@
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.CodeInsightSettings;
+import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.generation.GenerateEqualsHelper;
import com.intellij.ide.wizard.StepAdapter;
import com.intellij.openapi.diagnostic.Logger;
@@ -94,7 +95,7 @@
myNonNullPanel = new MemberSelectionPanel(CodeInsightBundle.message("generate.equals.hashcode.non.null.fields.chooser.title"), Collections.<MemberInfo>emptyList(), null);
myFieldsToNonNull = createFieldToMemberInfoMap(false);
for (final Map.Entry<PsiMember, MemberInfo> entry : myFieldsToNonNull.entrySet()) {
- entry.getValue().setChecked(entry.getKey().getModifierList().findAnnotation(NotNull.class.getName()) != null);
+ entry.getValue().setChecked(NullableNotNullManager.isNotNull(entry.getKey()));
}
}
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 9646ef9..e727568 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
@@ -30,8 +30,9 @@
* @author Maxim.Mossienko
*/
public class AnnotationParameterInfoHandler implements ParameterInfoHandler<PsiAnnotationParameterList,PsiAnnotationMethod>, DumbAware {
+ @Nullable
@Override
- public @Nullable Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
+ public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
return null;
}
@@ -46,7 +47,7 @@
}
@Override
- public PsiAnnotationParameterList findElementForParameterInfo(final CreateParameterInfoContext context) {
+ public PsiAnnotationParameterList findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
final PsiAnnotation annotation = ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), PsiAnnotation.class);
if (annotation != null) {
@@ -78,18 +79,18 @@
}
@Override
- public void showParameterInfo(@NotNull final PsiAnnotationParameterList element, final CreateParameterInfoContext context) {
+ public void showParameterInfo(@NotNull final PsiAnnotationParameterList element, @NotNull final CreateParameterInfoContext context) {
context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
}
@Override
- public PsiAnnotationParameterList findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) {
+ public PsiAnnotationParameterList findElementForUpdatingParameterInfo(@NotNull final UpdateParameterInfoContext context) {
final PsiAnnotation annotation = ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), PsiAnnotation.class);
return annotation != null ? annotation.getParameterList() : null;
}
@Override
- public void updateParameterInfo(@NotNull final PsiAnnotationParameterList o, final UpdateParameterInfoContext context) {
+ public void updateParameterInfo(@NotNull final PsiAnnotationParameterList parameterOwner, @NotNull final UpdateParameterInfoContext context) {
CharSequence chars = context.getEditor().getDocument().getCharsSequence();
int offset1 = CharArrayUtil.shiftForward(chars, context.getEditor().getCaretModel().getOffset(), " \t");
final char c = chars.charAt(offset1);
@@ -110,19 +111,17 @@
}
@Override
- public void updateUI(final PsiAnnotationMethod p, final ParameterInfoUIContext context) {
+ public void updateUI(final PsiAnnotationMethod p, @NotNull final ParameterInfoUIContext context) {
updateUIText(p, context);
}
public static String updateUIText(PsiAnnotationMethod p, ParameterInfoUIContext context) {
@NonNls StringBuilder buffer = new StringBuilder();
- int highlightStartOffset;
- int highlightEndOffset;
buffer.append(p.getReturnType().getPresentableText());
buffer.append(" ");
- highlightStartOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+ int highlightStartOffset = XmlStringUtil.escapeString(buffer.toString()).length();
buffer.append(p.getName());
- highlightEndOffset = XmlStringUtil.escapeString(buffer.toString()).length();
+ int highlightEndOffset = XmlStringUtil.escapeString(buffer.toString()).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 427383c..5da27d9 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -78,13 +78,13 @@
@Override
@Nullable
- public PsiExpressionList findElementForParameterInfo(final CreateParameterInfoContext context) {
+ public PsiExpressionList findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
PsiExpressionList argumentList = findArgumentList(context.getFile(), context.getOffset(), context.getParameterListStart());
if (argumentList != null) {
return findMethodsForArgumentList(context, argumentList);
}
- return argumentList;
+ return null;
}
private PsiExpressionList findArgumentList(final PsiFile file, int offset, int parameterStart) {
@@ -112,17 +112,17 @@
}
@Override
- public void showParameterInfo(@NotNull final PsiExpressionList element, final CreateParameterInfoContext context) {
+ public void showParameterInfo(@NotNull final PsiExpressionList element, @NotNull final CreateParameterInfoContext context) {
context.showHint(element, element.getTextRange().getStartOffset(), this);
}
@Override
- public PsiExpressionList findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) {
+ public PsiExpressionList findElementForUpdatingParameterInfo(@NotNull final UpdateParameterInfoContext context) {
return findArgumentList(context.getFile(), context.getOffset(), context.getParameterListStart());
}
@Override
- public void updateParameterInfo(@NotNull final PsiExpressionList o, final UpdateParameterInfoContext context) {
+ public void updateParameterInfo(@NotNull final PsiExpressionList o, @NotNull final UpdateParameterInfoContext context) {
PsiElement parameterOwner = context.getParameterOwner();
if (parameterOwner != o) {
context.removeHint();
@@ -357,7 +357,8 @@
}
}
- public static String updateMethodPresentation(PsiMethod method, @Nullable PsiSubstitutor substitutor, ParameterInfoUIContext context) {
+ @NotNull
+ public static String updateMethodPresentation(@NotNull PsiMethod method, @Nullable PsiSubstitutor substitutor, @NotNull ParameterInfoUIContext context) {
CodeInsightSettings settings = CodeInsightSettings.getInstance();
if (!method.isValid() || substitutor != null && !substitutor.isValid()) {
@@ -444,16 +445,20 @@
private static void appendModifierList(@NotNull StringBuilder buffer, @NotNull PsiModifierListOwner owner) {
int lastSize = buffer.length();
- for (PsiAnnotation a : AnnotationUtil.getAllAnnotations(owner, false, null)) {
- if (lastSize != buffer.length()) buffer.append(" ");
- final PsiJavaCodeReferenceElement element = a.getNameReferenceElement();
- if (element != null) buffer.append("@").append(element.getReferenceName());
+ for (PsiAnnotation annotation : AnnotationUtil.getAllAnnotations(owner, false, null)) {
+ final PsiJavaCodeReferenceElement element = annotation.getNameReferenceElement();
+ if (element != null) {
+ final PsiElement resolved = element.resolve();
+ if (resolved instanceof PsiClass && !AnnotationUtil.isAnnotated((PsiClass)resolved, "java.lang.annotation.Documented", false)) continue;
+ if (lastSize != buffer.length()) buffer.append(" ");
+ buffer.append("@").append(element.getReferenceName());
+ }
}
if (lastSize != buffer.length()) buffer.append(" ");
}
@Override
- public void updateUI(final Object p, final ParameterInfoUIContext context) {
+ public void updateUI(final Object p, @NotNull final ParameterInfoUIContext context) {
if (p instanceof CandidateInfo) {
CandidateInfo info = (CandidateInfo)p;
PsiMethod method = (PsiMethod)info.getElement();
diff --git a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/ReferenceParameterInfoHandler.java b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/ReferenceParameterInfoHandler.java
index 8992709..b1f882c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/ReferenceParameterInfoHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/hint/api/impls/ReferenceParameterInfoHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -45,7 +45,7 @@
}
@Override
- public PsiReferenceParameterList findElementForParameterInfo(final CreateParameterInfoContext context) {
+ public PsiReferenceParameterList findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
final PsiReferenceParameterList referenceParameterList =
ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), PsiReferenceParameterList.class);
@@ -66,18 +66,18 @@
}
@Override
- public void showParameterInfo(@NotNull final PsiReferenceParameterList element, final CreateParameterInfoContext context) {
+ public void showParameterInfo(@NotNull final PsiReferenceParameterList element, @NotNull final CreateParameterInfoContext context) {
context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
}
@Override
- public PsiReferenceParameterList findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) {
+ public PsiReferenceParameterList findElementForUpdatingParameterInfo(@NotNull final UpdateParameterInfoContext context) {
return ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), PsiReferenceParameterList.class);
}
@Override
- public void updateParameterInfo(@NotNull final PsiReferenceParameterList o, final UpdateParameterInfoContext context) {
- int index = ParameterInfoUtils.getCurrentParameterIndex(o.getNode(), context.getOffset(), JavaTokenType.COMMA);
+ public void updateParameterInfo(@NotNull final PsiReferenceParameterList parameterOwner, @NotNull final UpdateParameterInfoContext context) {
+ int index = ParameterInfoUtils.getCurrentParameterIndex(parameterOwner.getNode(), context.getOffset(), JavaTokenType.COMMA);
context.setCurrentParameter(index);
final Object[] objectsToView = context.getObjectsToView();
context.setHighlightedParameter(index < objectsToView.length && index >= 0 ? (PsiElement)objectsToView[index]:null);
@@ -95,7 +95,7 @@
}
@Override
- public void updateUI(PsiTypeParameter o, ParameterInfoUIContext context) {
+ public void updateUI(PsiTypeParameter o, @NotNull ParameterInfoUIContext context) {
updateTypeParameter(o, context);
}
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 2862189..2b839b5 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
@@ -57,7 +57,6 @@
public boolean isAvailable(@NotNull final Project project, @NotNull final PsiElement element) {
if (!element.isValid()) return false;
- if (!PsiUtil.isLanguageLevel5OrHigher(element)) return false;
final PsiModifierListOwner owner;
if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
owner = AddAnnotationPsiFix.getContainer(element);
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java
index dfede04..e359077 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/ConvertAbsolutePathToRelativeIntentionAction.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,8 +18,10 @@
import com.intellij.codeInsight.FileModificationService;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
+import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.util.IncorrectOperationException;
@@ -36,7 +38,14 @@
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- final PsiReference reference = file.findReferenceAt(editor.getCaretModel().getOffset());
+ final int offset = editor.getCaretModel().getOffset();
+ final PsiElement element = file.findElementAt(offset);
+ if (element == null ||
+ element instanceof PsiWhiteSpace) {
+ return false;
+ }
+
+ final PsiReference reference = file.findReferenceAt(offset);
final FileReference fileReference = reference == null ? null : FileReference.findFileReference(reference);
if (fileReference != null) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterDialog.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterDialog.java
index 9468452..73440ba 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterDialog.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/CreateFieldFromParameterDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -78,7 +78,7 @@
CodeInsightBundle.message("dialog.create.field.from.parameter.already.exists.text", getEnteredName()),
CodeInsightBundle.message("dialog.create.field.from.parameter.already.exists.title"),
Messages.getQuestionIcon());
- if (result == 0) {
+ if (result == Messages.OK) {
close(OK_EXIT_CODE);
}
else {
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
index 550da72..4d33908 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/MoveInitializerToConstructorAction.java
@@ -65,16 +65,12 @@
@NotNull
private static Collection<PsiMethod> removeChainedConstructors(@NotNull Collection<PsiMethod> constructors) {
final List<PsiMethod> result = new ArrayList<PsiMethod>(constructors);
-
- final Iterator<PsiMethod> iterator = result.iterator();
- //noinspection ForLoopThatDoesntUseLoopVariable
- for (PsiMethod constructor = iterator.next(); iterator.hasNext(); constructor = iterator.next()) {
- final List<PsiMethod> chained = JavaHighlightUtil.getChainedConstructors(constructor);
- if (chained != null) {
+ for (Iterator<PsiMethod> iterator = result.iterator(); iterator.hasNext(); ) {
+ final PsiMethod constructor = iterator.next();
+ if (JavaHighlightUtil.getChainedConstructors(constructor) != null) {
iterator.remove();
}
}
-
return result;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
index 7b69611..8c1da62 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/SplitDeclarationAction.java
@@ -119,15 +119,13 @@
statement = (PsiExpressionStatement)CodeStyleManager.getInstance(project).reformat(statement);
PsiAssignmentExpression assignment = (PsiAssignmentExpression)statement.getExpression();
PsiExpression initializer = var.getInitializer();
- PsiExpression rExpression;
- if (initializer instanceof PsiArrayInitializerExpression) {
+ PsiExpression rExpression = initializer;
+ if (initializer instanceof PsiArrayInitializerExpression && var.getType() instanceof PsiArrayType) {
rExpression = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory().createExpressionFromText(
"new " + var.getTypeElement().getText() + " " + initializer.getText(), null
);
}
- else {
- rExpression = initializer;
- }
+
assignment.getRExpression().replace(rExpression);
initializer.delete();
diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
index dcbf1a7..147cf33 100644
--- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.java
+++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/config/QuickFixFactoryImpl.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,30 +15,61 @@
*/
package com.intellij.codeInsight.intention.impl.config;
+import com.intellij.codeInsight.CodeInsightSettings;
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
+import com.intellij.codeInsight.daemon.QuickFixBundle;
+import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerEx;
+import com.intellij.codeInsight.daemon.impl.DaemonListeners;
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.analysis.IncreaseLanguageLevelFix;
-import com.intellij.codeInsight.daemon.impl.quickfix.ReplacePrimitiveWithBoxedTypeAction;
import com.intellij.codeInsight.daemon.impl.quickfix.*;
import com.intellij.codeInsight.daemon.quickFix.CreateClassOrPackageFix;
import com.intellij.codeInsight.daemon.quickFix.CreateFieldOrPropertyFix;
import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.intention.IntentionManager;
import com.intellij.codeInsight.intention.QuickFixFactory;
-import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
-import com.intellij.codeInspection.LocalQuickFixOnPsiElement;
+import com.intellij.codeInspection.*;
+import com.intellij.codeInspection.ex.EntryPointsManagerBase;
+import com.intellij.codeInspection.unusedParameters.UnusedParametersInspection;
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
+import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
+import com.intellij.diagnostic.AttachmentFactory;
+import com.intellij.diagnostic.LogMessageEx;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.util.PropertyMemberType;
import com.intellij.psi.util.ClassKind;
+import com.intellij.psi.util.PropertyMemberType;
+import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
* @author cdr
*/
public class QuickFixFactoryImpl extends QuickFixFactory {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.config.QuickFixFactoryImpl");
+
@NotNull
@Override
public LocalQuickFixAndIntentionActionOnPsiElement createModifierListFix(@NotNull PsiModifierList modifierList,
@@ -561,9 +592,177 @@
PullAsAbstractUpFix.registerQuickFix(method, registrar);
}
+ @NotNull
@Override
- public IntentionAction createCreateAnnotationMethodFromUsageFix(PsiNameValuePair pair) {
+ public IntentionAction createCreateAnnotationMethodFromUsageFix(@NotNull PsiNameValuePair pair) {
return new CreateAnnotationMethodFromUsageFix(pair);
}
+ @NotNull
+ @Override
+ public IntentionAction createOptimizeImportsFix() {
+ final OptimizeImportsFix fix = new OptimizeImportsFix();
+
+ return new IntentionAction() {
+ @NotNull
+ @Override
+ public String getText() {
+ return fix.getText();
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return fix.getFamilyName();
+ }
+
+ @Override
+ public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ return timeToOptimizeImports(file) && fix.isAvailable(project, editor, file);
+ }
+
+ @Override
+ public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
+ invokeOnTheFlyImportOptimizer(new Runnable() {
+ @Override
+ public void run() {
+ fix.invoke(project, editor, file);
+ }
+ }, file, editor);
+ }
+
+ @Override
+ public boolean startInWriteAction() {
+ return fix.startInWriteAction();
+ }
+ };
+ }
+
+ @Override
+ public void registerFixesForUnusedParameter(@NotNull PsiParameter parameter, @NotNull Object highlightInfo) {
+ Project myProject = parameter.getProject();
+ InspectionProfile profile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile();
+ UnusedParametersInspection unusedParametersInspection =
+ (UnusedParametersInspection)profile.getUnwrappedTool(UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME, parameter);
+ LOG.assertTrue(ApplicationManager.getApplication().isUnitTestMode() || unusedParametersInspection != null);
+ List<IntentionAction> options = new ArrayList<IntentionAction>();
+ HighlightDisplayKey myUnusedSymbolKey = HighlightDisplayKey.find(UnusedSymbolLocalInspection.SHORT_NAME);
+ options.addAll(IntentionManager.getInstance().getStandardIntentionOptions(myUnusedSymbolKey, parameter));
+ if (unusedParametersInspection != null) {
+ SuppressQuickFix[] batchSuppressActions = unusedParametersInspection.getBatchSuppressActions(parameter);
+ Collections.addAll(options, SuppressIntentionActionFromFix.convertBatchToSuppressIntentionActions(batchSuppressActions));
+ }
+ //need suppress from Unused Parameters but settings from Unused Symbol
+ QuickFixAction.registerQuickFixAction((HighlightInfo)highlightInfo, new RemoveUnusedParameterFix(parameter),
+ options, HighlightDisplayKey.getDisplayNameByKey(myUnusedSymbolKey));
+ }
+
+ @NotNull
+ @Override
+ public IntentionAction createAddToDependencyInjectionAnnotationsFix(@NotNull Project project,
+ @NotNull String qualifiedName,
+ @NotNull String element) {
+ final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
+ return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
+ QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
+ QuickFixBundle.message("fix.unused.symbol.injection.family"),
+ entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
+ }
+
+ @NotNull
+ @Override
+ public IntentionAction createCreateGetterOrSetterFix(boolean createGetter, boolean createSetter, @NotNull PsiField field) {
+ return new CreateGetterOrSetterFix(createGetter, createSetter, field);
+ }
+
+ @NotNull
+ @Override
+ public IntentionAction createRenameToIgnoredFix(@NotNull PsiNamedElement namedElement) {
+ return new RenameToIgnoredFix(namedElement);
+ }
+
+ @NotNull
+ @Override
+ public IntentionAction createEnableOptimizeImportsOnTheFlyFix() {
+ return new EnableOptimizeImportsOnTheFlyFix();
+ }
+
+ @NotNull
+ @Override
+ public IntentionAction createSafeDeleteFix(@NotNull PsiElement element) {
+ if (element instanceof PsiMethod) {
+ PsiMethod method = (PsiMethod)element;
+ PsiClass containingClass = method.getContainingClass();
+ if (method.getReturnType() != null || containingClass != null && Comparing.strEqual(containingClass.getName(), method.getName())) {
+ //ignore methods with deleted return types as they are always marked as unused without any reason
+ ChangeSignatureGestureDetector.getInstance(method.getProject()).dismissForElement(method);
+ }
+ }
+ return new SafeDeleteFix(element);
+ }
+
+ public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
+ @NotNull final PsiFile file,
+ @NotNull final Editor editor) {
+ final long stamp = editor.getDocument().getModificationStamp();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
+ //no need to optimize imports on the fly during undo/redo
+ final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
+ if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
+ PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
+ String beforeText = file.getText();
+ final long oldStamp = editor.getDocument().getModificationStamp();
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(runnable);
+ }
+ });
+ if (oldStamp != editor.getDocument().getModificationStamp()) {
+ String afterText = file.getText();
+ if (Comparing.strEqual(beforeText, afterText)) {
+ LOG.error(
+ LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
+ AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
+ }
+ }
+ }
+ });
+ }
+
+ private static boolean timeToOptimizeImports(@NotNull PsiFile file) {
+ if (!CodeInsightSettings.getInstance().OPTIMIZE_IMPORTS_ON_THE_FLY) return false;
+
+ DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(file.getProject());
+ // dont optimize out imports in JSP since it can be included in other JSP
+ if (file == null || !codeAnalyzer.isHighlightingAvailable(file) || !(file instanceof PsiJavaFile) || file instanceof ServerPageFile) return false;
+
+ if (!codeAnalyzer.isErrorAnalyzingFinished(file)) return false;
+ boolean errors = containsErrorsPreventingOptimize(file);
+
+ return !errors && DaemonListeners.canChangeFileSilently(file);
+ }
+
+ private static boolean containsErrorsPreventingOptimize(@NotNull PsiFile file) {
+ Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
+ if (document == null) return true;
+ // ignore unresolved imports errors
+ PsiImportList importList = ((PsiJavaFile)file).getImportList();
+ final TextRange importsRange = importList == null ? TextRange.EMPTY_RANGE : importList.getTextRange();
+ boolean hasErrorsExceptUnresolvedImports = !DaemonCodeAnalyzerEx
+ .processHighlights(document, file.getProject(), HighlightSeverity.ERROR, 0, document.getTextLength(), new Processor<HighlightInfo>() {
+ @Override
+ public boolean process(HighlightInfo error) {
+ int infoStart = error.getActualStartOffset();
+ int infoEnd = error.getActualEndOffset();
+
+ return importsRange.containsRange(infoStart, infoEnd) && error.type.equals(HighlightInfoType.WRONG_REF);
+ }
+ });
+
+ return hasErrorsExceptUnresolvedImports;
+ }
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java
index eb803e6..d1690cf 100644
--- a/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/navigation/JavaMethodNavigationOffsetProvider.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.navigation;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.*;
import org.jetbrains.annotations.Nullable;
@@ -37,8 +38,9 @@
private static void addNavigationElements(ArrayList<PsiElement> array, PsiElement element) {
PsiElement[] children = element.getChildren();
+ boolean stopOnFields = Registry.is("ide.structural.navigation.visit.fields");
for (PsiElement child : children) {
- if (child instanceof PsiMethod || child instanceof PsiClass || child instanceof PsiField) {
+ if (child instanceof PsiMethod || child instanceof PsiClass || stopOnFields && child instanceof PsiField) {
array.add(child);
addNavigationElements(array, child);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoBreakContinueHandler.java b/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoBreakContinueHandler.java
index 90e1720..b20c817 100644
--- a/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoBreakContinueHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoBreakContinueHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,11 +25,11 @@
* @author yole
*/
public class GotoBreakContinueHandler extends GotoDeclarationHandlerBase {
- private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.navigation.actions.GotoBreakContinueHandler");
+ private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.navigation.actions.GotoBreakContinueHandler");
@Override
@Nullable
- public PsiElement getGotoDeclarationTarget(final PsiElement elementAt, Editor editor) {
+ public PsiElement getGotoDeclarationTarget(@Nullable PsiElement elementAt, Editor editor) {
if (elementAt instanceof PsiKeyword) {
IElementType type = ((PsiKeyword)elementAt).getTokenType();
if (type == JavaTokenType.CONTINUE_KEYWORD) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoLambdaParameterHandler.java b/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoLambdaParameterHandler.java
index 183bcbe..7585b20 100644
--- a/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoLambdaParameterHandler.java
+++ b/java/java-impl/src/com/intellij/codeInsight/navigation/actions/GotoLambdaParameterHandler.java
@@ -20,10 +20,9 @@
import org.jetbrains.annotations.Nullable;
public class GotoLambdaParameterHandler extends GotoDeclarationHandlerBase {
-
@Override
@Nullable
- public PsiElement getGotoDeclarationTarget(final PsiElement elementAt, Editor editor) {
+ public PsiElement getGotoDeclarationTarget(@Nullable PsiElement elementAt, Editor editor) {
if (elementAt instanceof PsiIdentifier) {
PsiElement parent = elementAt.getParent();
if (parent instanceof PsiParameter && ((PsiParameter)parent).getTypeElement() == null) {
@@ -33,6 +32,7 @@
}
}
}
+
return null;
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/preview/JavaPreviewHintProvider.java b/java/java-impl/src/com/intellij/codeInsight/preview/JavaPreviewHintProvider.java
index a2c9af4..8578149 100644
--- a/java/java-impl/src/com/intellij/codeInsight/preview/JavaPreviewHintProvider.java
+++ b/java/java-impl/src/com/intellij/codeInsight/preview/JavaPreviewHintProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -21,7 +21,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
-import com.intellij.xml.util.ColorSampleLookupValue;
+import com.intellij.xml.util.ColorMap;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -137,7 +137,7 @@
if (psiElement instanceof PsiField) {
if ("java.awt.Color".equals(((PsiField)psiElement).getContainingClass().getQualifiedName())) {
final String colorName = ((PsiField)psiElement).getName().toLowerCase().replace("_", "");
- final String hex = ColorSampleLookupValue.getHexCodeForColorName(colorName);
+ final String hex = ColorMap.getHexCodeForColorName(colorName);
return new ColorPreviewComponent(Color.decode("0x" + hex.substring(1)));
}
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/macro/ClassNameMacro.java b/java/java-impl/src/com/intellij/codeInsight/template/macro/ClassNameMacro.java
index 2d0d69e..d32f56c 100644
--- a/java/java-impl/src/com/intellij/codeInsight/template/macro/ClassNameMacro.java
+++ b/java/java-impl/src/com/intellij/codeInsight/template/macro/ClassNameMacro.java
@@ -58,7 +58,7 @@
}
if (aClass == null) return null;
- String qname = aClass.getQualifiedName();
+ String qname = aClass.getName();
return qname == null ? null : new TextResult(qname);
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.java
new file mode 100644
index 0000000..b6a7b5f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateCompletionContributor.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.codeInsight.template.postfix.completion;
+
+import com.intellij.codeInsight.completion.CompletionContributor;
+import com.intellij.codeInsight.completion.CompletionType;
+import com.intellij.codeInsight.template.CustomLiveTemplate;
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
+import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.patterns.ElementPattern;
+import com.intellij.psi.JavaTokenType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.ElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static com.intellij.patterns.PsiJavaPatterns.psiElement;
+import static com.intellij.patterns.StandardPatterns.string;
+
+public class PostfixTemplateCompletionContributor extends CompletionContributor {
+ private static final TokenSet SUITABLE_ELEMENTS = TokenSet.orSet(ElementType.KEYWORD_BIT_SET,
+ ElementType.LITERAL_BIT_SET,
+ TokenSet.create(JavaTokenType.IDENTIFIER));
+
+ public PostfixTemplateCompletionContributor() {
+ extend(CompletionType.BASIC, identifierAfterDot(), new PostfixTemplatesCompletionProvider());
+ }
+
+ @Nullable
+ public static PostfixLiveTemplate getPostfixLiveTemplate(@NotNull PsiFile file, @NotNull Editor editor) {
+ PostfixLiveTemplate postfixLiveTemplate = CustomLiveTemplate.EP_NAME.findExtension(PostfixLiveTemplate.class);
+ return postfixLiveTemplate != null && TemplateManagerImpl.isApplicable(postfixLiveTemplate, editor, file) ? postfixLiveTemplate : null;
+ }
+
+ private static ElementPattern<? extends PsiElement> identifierAfterDot() {
+ return psiElement().withElementType(SUITABLE_ELEMENTS).afterLeaf(psiElement().withText(string().contains(".")));
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupActionProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupActionProvider.java
new file mode 100644
index 0000000..8781d31
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupActionProvider.java
@@ -0,0 +1,82 @@
+/*
+ * 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.codeInsight.template.postfix.completion;
+
+import com.intellij.codeInsight.lookup.Lookup;
+import com.intellij.codeInsight.lookup.LookupActionProvider;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementAction;
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesConfigurable;
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesListPanel;
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.Consumer;
+import com.intellij.util.PlatformIcons;
+
+public class PostfixTemplateLookupActionProvider implements LookupActionProvider {
+ @Override
+ public void fillActions(LookupElement element, final Lookup lookup, Consumer<LookupElementAction> consumer) {
+ if (element instanceof PostfixTemplateLookupElement) {
+ final PostfixTemplate template = ((PostfixTemplateLookupElement)element).getPostfixTemplate();
+
+ consumer.consume(new LookupElementAction(PlatformIcons.EDIT, "Edit postfix templates settings") {
+ @Override
+ public Result performLookupAction() {
+ final Project project = lookup.getEditor().getProject();
+ assert project != null;
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (project.isDisposed()) return;
+
+ final PostfixTemplatesConfigurable configurable = new PostfixTemplatesConfigurable();
+ ShowSettingsUtil.getInstance().editConfigurable(project, configurable, new Runnable() {
+ @Override
+ public void run() {
+ PostfixTemplatesListPanel templatesListPanel = configurable.getTemplatesListPanel();
+ if (templatesListPanel != null) {
+ templatesListPanel.selectTemplate(template);
+ }
+ }
+ });
+ }
+ });
+ return Result.HIDE_LOOKUP;
+ }
+ });
+
+ final PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ if (settings != null && settings.isTemplateEnabled(template)) {
+ consumer.consume(new LookupElementAction(AllIcons.Actions.Delete, String.format("Disable '%s' template", template.getKey())) {
+ @Override
+ public Result performLookupAction() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ settings.disableTemplate(template);
+ }
+ });
+ return Result.HIDE_LOOKUP;
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java
new file mode 100644
index 0000000..414d9a0
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplateLookupElement.java
@@ -0,0 +1,56 @@
+/*
+ * 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.codeInsight.template.postfix.completion;
+
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
+import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.openapi.util.SystemInfo;
+import org.jetbrains.annotations.NotNull;
+
+public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElement {
+ @NotNull
+ private final PostfixTemplate myTemplate;
+
+ public PostfixTemplateLookupElement(@NotNull PostfixLiveTemplate liveTemplate,
+ @NotNull PostfixTemplate postfixTemplate,
+ @NotNull String templateKey,
+ boolean sudden) {
+ super(liveTemplate, templateKey, postfixTemplate.getPresentableName(), postfixTemplate.getDescription(), sudden, true);
+ myTemplate = postfixTemplate;
+ }
+
+ @NotNull
+ public PostfixTemplate getPostfixTemplate() {
+ return myTemplate;
+ }
+
+ @Override
+ public void renderElement(LookupElementPresentation presentation) {
+ super.renderElement(presentation);
+ if (sudden) {
+ presentation.setTailText(" " + arrow() + " " + myTemplate.getExample());
+ }
+ else {
+ presentation.setTypeText(myTemplate.getExample());
+ }
+ }
+
+ private static String arrow() {
+ return SystemInfo.isMac ? "→" : "->";
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.java
new file mode 100644
index 0000000..386718e
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/completion/PostfixTemplatesCompletionProvider.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.codeInsight.template.postfix.completion;
+
+import com.intellij.codeInsight.completion.CompletionParameters;
+import com.intellij.codeInsight.completion.CompletionProvider;
+import com.intellij.codeInsight.completion.CompletionResultSet;
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
+import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.patterns.StandardPatterns;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+
+import static com.intellij.codeInsight.template.postfix.completion.PostfixTemplateCompletionContributor.getPostfixLiveTemplate;
+
+class PostfixTemplatesCompletionProvider extends CompletionProvider<CompletionParameters> {
+ @Override
+ protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
+ if (!isCompletionEnabled(parameters) || Registry.is("show.live.templates.in.completion")) {
+ /**
+ * disabled or covered with {@link com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor}
+ */
+ return;
+ }
+
+ PostfixLiveTemplate postfixLiveTemplate = getPostfixLiveTemplate(parameters.getOriginalFile(), parameters.getEditor());
+ if (postfixLiveTemplate != null) {
+ PsiFile file = parameters.getPosition().getContainingFile();
+ final CustomTemplateCallback callback = new CustomTemplateCallback(parameters.getEditor(), file, false);
+ String computedKey = postfixLiveTemplate.computeTemplateKey(callback);
+ if (computedKey != null) {
+ PostfixTemplate template = postfixLiveTemplate.getTemplateByKey(computedKey);
+ if (template != null) {
+ result = result.withPrefixMatcher(computedKey);
+ result.addElement(new PostfixTemplateLookupElement(postfixLiveTemplate, template, computedKey, true));
+ }
+ }
+
+ CharSequence documentContent = parameters.getEditor().getDocument().getCharsSequence();
+ String possibleKey = postfixLiveTemplate.computeTemplateKeyWithoutContextChecking(documentContent, parameters.getOffset());
+ if (possibleKey != null) {
+ result = result.withPrefixMatcher(possibleKey);
+ result.restartCompletionOnPrefixChange(StandardPatterns.string().oneOf(postfixLiveTemplate.getAllTemplateKeys()));
+ }
+ }
+ }
+
+ private static boolean isCompletionEnabled(@NotNull CompletionParameters parameters) {
+ if (!parameters.isAutoPopup()) {
+ return false;
+ }
+
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ if (settings == null || !settings.isPostfixTemplatesEnabled() || !settings.isTemplatesCompletionEnabled()) {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.form b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.form
new file mode 100644
index 0000000..a94559a
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.form
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesConfigurable">
+ <grid id="27dc6" binding="myPanel" 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"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="f9f95" class="com.intellij.ui.components.JBCheckBox" binding="myPostfixTemplatesEnabled">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="1" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="&Enable postfix templates"/>
+ </properties>
+ </component>
+ <grid id="a9fc9" binding="myTemplatesListPanelContainer" 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="3" 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"/>
+ <children/>
+ </grid>
+ <component id="9f784" class="com.intellij.ui.components.JBCheckBox" binding="myCompletionEnabledCheckbox">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="1" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="&Show postfix templates in completion autopopup"/>
+ </properties>
+ </component>
+ <component id="2231a" class="com.intellij.ui.components.JBLabel">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="1" anchor="8" fill="0" indent="1" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Expand templates with"/>
+ </properties>
+ </component>
+ <component id="63d6b" class="com.intellij.openapi.ui.ComboBox" binding="myShortcutComboBox">
+ <constraints>
+ <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="1" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <model/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java
new file mode 100644
index 0000000..78e0475
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesConfigurable.java
@@ -0,0 +1,184 @@
+/*
+ * 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.codeInsight.template.postfix.settings;
+
+import com.intellij.application.options.editor.EditorOptionsProvider;
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.template.impl.TemplateSettings;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.ui.components.JBCheckBox;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.ChangeEvent;
+import javax.swing.event.ChangeListener;
+import java.awt.*;
+import java.util.Arrays;
+import java.util.Map;
+
+public class PostfixTemplatesConfigurable implements SearchableConfigurable, EditorOptionsProvider, Configurable.NoScroll {
+ @Nullable
+ private PostfixTemplatesListPanel myTemplatesListPanel;
+ @NotNull
+ private final PostfixTemplatesSettings myTemplatesSettings;
+
+ private JComponent myPanel;
+ private JBCheckBox myCompletionEnabledCheckbox;
+ private JBCheckBox myPostfixTemplatesEnabled;
+ private JPanel myTemplatesListPanelContainer;
+ private ComboBox myShortcutComboBox;
+
+ private static final String SPACE = CodeInsightBundle.message("template.shortcut.space");
+ private static final String TAB = CodeInsightBundle.message("template.shortcut.tab");
+ private static final String ENTER = CodeInsightBundle.message("template.shortcut.enter");
+
+ @SuppressWarnings("unchecked")
+ public PostfixTemplatesConfigurable() {
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ if (settings == null) {
+ throw new RuntimeException("Can't retrieve postfix template settings");
+ }
+
+ myTemplatesSettings = settings;
+ myTemplatesListPanel = new PostfixTemplatesListPanel(Arrays.asList(PostfixTemplate.EP_NAME.getExtensions()));
+ myTemplatesListPanelContainer.setLayout(new BorderLayout());
+ myTemplatesListPanelContainer.add(myTemplatesListPanel.getComponent(), BorderLayout.CENTER);
+ myPostfixTemplatesEnabled.addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ updateComponents();
+ }
+ });
+ myShortcutComboBox.addItem(TAB);
+ myShortcutComboBox.addItem(SPACE);
+ myShortcutComboBox.addItem(ENTER);
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return "reference.settingsdialog.IDE.editor.postfix.templates";
+ }
+
+ @Nullable
+ @Override
+ public String getHelpTopic() {
+ return null;
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return "Postfix Templates";
+ }
+
+ @Nullable
+ public PostfixTemplatesListPanel getTemplatesListPanel() {
+ return myTemplatesListPanel;
+ }
+
+ @NotNull
+ @Override
+ public JComponent createComponent() {
+ return myPanel;
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ if (myTemplatesListPanel != null) {
+ Map<String, Boolean> newTemplatesState = ContainerUtil.newHashMap();
+ for (Map.Entry<String, Boolean> entry : myTemplatesListPanel.getState().entrySet()) {
+ Boolean value = entry.getValue();
+ if (value != null && !value) {
+ newTemplatesState.put(entry.getKey(), entry.getValue());
+ }
+ }
+ myTemplatesSettings.setTemplatesState(newTemplatesState);
+ myTemplatesSettings.setPostfixTemplatesEnabled(myPostfixTemplatesEnabled.isSelected());
+ myTemplatesSettings.setTemplatesCompletionEnabled(myCompletionEnabledCheckbox.isSelected());
+ myTemplatesSettings.setShortcut(stringToShortcut((String)myShortcutComboBox.getSelectedItem()));
+ }
+ }
+
+ @Override
+ public void reset() {
+ if (myTemplatesListPanel != null) {
+ myTemplatesListPanel.setState(myTemplatesSettings.getTemplatesState());
+ myPostfixTemplatesEnabled.setSelected(myTemplatesSettings.isPostfixTemplatesEnabled());
+ myCompletionEnabledCheckbox.setSelected(myTemplatesSettings.isTemplatesCompletionEnabled());
+ myShortcutComboBox.setSelectedItem(shortcutToString((char)myTemplatesSettings.getShortcut()));
+ updateComponents();
+ }
+ }
+
+ @Override
+ public boolean isModified() {
+ if (myTemplatesListPanel == null) {
+ return false;
+ }
+ return myPostfixTemplatesEnabled.isSelected() != myTemplatesSettings.isPostfixTemplatesEnabled() ||
+ myCompletionEnabledCheckbox.isSelected() != myTemplatesSettings.isTemplatesCompletionEnabled() ||
+ stringToShortcut((String)myShortcutComboBox.getSelectedItem()) != myTemplatesSettings.getShortcut() ||
+ !myTemplatesListPanel.getState().equals(myTemplatesSettings.getTemplatesState());
+ }
+
+ @Override
+ public void disposeUIResources() {
+ myTemplatesListPanel = null;
+ }
+
+ @Nullable
+ @Override
+ public Runnable enableSearch(String s) {
+ return null;
+ }
+
+ private void updateComponents() {
+ boolean pluginEnabled = myPostfixTemplatesEnabled.isSelected();
+ myCompletionEnabledCheckbox.setEnabled(pluginEnabled);
+ myShortcutComboBox.setEnabled(pluginEnabled);
+ if (myTemplatesListPanel != null) {
+ myTemplatesListPanel.setEnabled(pluginEnabled);
+ }
+ }
+
+ private static char stringToShortcut(@NotNull String string) {
+ if (SPACE.equals(string)) {
+ return TemplateSettings.SPACE_CHAR;
+ }
+ else if (ENTER.equals(string)) {
+ return TemplateSettings.ENTER_CHAR;
+ }
+ return TemplateSettings.TAB_CHAR;
+ }
+
+ private static String shortcutToString(char shortcut) {
+ if (shortcut == TemplateSettings.SPACE_CHAR) {
+ return SPACE;
+ }
+ if (shortcut == TemplateSettings.ENTER_CHAR) {
+ return ENTER;
+ }
+ return TAB;
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java
new file mode 100644
index 0000000..581b774
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesListPanel.java
@@ -0,0 +1,207 @@
+package com.intellij.codeInsight.template.postfix.settings;
+
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.ui.BooleanTableCellEditor;
+import com.intellij.ui.BooleanTableCellRenderer;
+import com.intellij.ui.TableViewSpeedSearch;
+import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.components.JBCheckBox;
+import com.intellij.ui.table.TableView;
+import com.intellij.util.Function;
+import com.intellij.util.NotNullFunction;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ColumnInfo;
+import com.intellij.util.ui.ListTableModel;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+public class PostfixTemplatesListPanel {
+ private static final NotNullFunction<PostfixTemplate, String> GET_SHORTCUT_FUNCTION =
+ new NotNullFunction<PostfixTemplate, String>() {
+ @NotNull
+ @Override
+ public String fun(@NotNull PostfixTemplate template) {
+ return template.getKey();
+ }
+ };
+
+ private static final NotNullFunction<PostfixTemplate, String> GET_DESCRIPTION_FUNCTION =
+ new NotNullFunction<PostfixTemplate, String>() {
+ @NotNull
+ @Override
+ public String fun(@NotNull PostfixTemplate template) {
+ return template.getDescription();
+ }
+ };
+
+ private static final NotNullFunction<PostfixTemplate, String> GET_EXAMPLE_FUNCTION =
+ new NotNullFunction<PostfixTemplate, String>() {
+ @NotNull
+ @Override
+ public String fun(@NotNull PostfixTemplate template) {
+ return template.getExample();
+ }
+ };
+
+ @NotNull private final Map<String, Boolean> myTemplatesState = ContainerUtil.newHashMap();
+ @NotNull private final JPanel myPanelWithTableView;
+ private final TableView<PostfixTemplate> myTemplatesTableView;
+
+ public PostfixTemplatesListPanel(@NotNull List<PostfixTemplate> templates) {
+ ColumnInfo[] columns = generateColumns(templates);
+ ListTableModel<PostfixTemplate> templatesTableModel = new ListTableModel<PostfixTemplate>(columns, templates, 0);
+ myTemplatesTableView = new TableView<PostfixTemplate>();
+ myTemplatesTableView.setModelAndUpdateColumns(templatesTableModel);
+ myTemplatesTableView.setShowGrid(false);
+ myTemplatesTableView.setStriped(true);
+ myTemplatesTableView.setBorder(null);
+
+ new TableViewSpeedSearch<PostfixTemplate>(myTemplatesTableView) {
+ @Override
+ protected String getItemText(@NotNull PostfixTemplate template) {
+ return template.getPresentableName();
+ }
+ };
+
+ myPanelWithTableView = ToolbarDecorator.createDecorator(myTemplatesTableView)
+ .setAsUsualTopToolbar()
+ .disableAddAction()
+ .disableRemoveAction()
+ .disableUpDownActions().createPanel();
+ }
+
+ @NotNull
+ private ColumnInfo[] generateColumns(@NotNull List<PostfixTemplate> templates) {
+ String longestTemplateName = "";
+ String longestDescription = "";
+ String longestExample = "";
+ for (PostfixTemplate template : templates) {
+ longestTemplateName = longestString(longestTemplateName, GET_SHORTCUT_FUNCTION.fun(template));
+ longestDescription = longestString(longestDescription, GET_DESCRIPTION_FUNCTION.fun(template));
+ longestExample = longestString(longestExample, GET_EXAMPLE_FUNCTION.fun(template));
+ }
+ return new ColumnInfo[]{
+ new BooleanColumnInfo(),
+ new StringColumnInfo("Shortcut", GET_SHORTCUT_FUNCTION, longestTemplateName),
+ new StringColumnInfo("Description", GET_DESCRIPTION_FUNCTION, longestDescription),
+ new StringColumnInfo("Example", GET_EXAMPLE_FUNCTION, longestExample),
+ };
+ }
+
+ public void selectTemplate(@NotNull PostfixTemplate template) {
+ myTemplatesTableView.setSelection(Arrays.asList(template));
+ }
+
+ @NotNull
+ private static String longestString(@NotNull String firstString, @NotNull String secondString) {
+ return secondString.length() > firstString.length() ? secondString : firstString;
+ }
+
+ @NotNull
+ public JPanel getComponent() {
+ return myPanelWithTableView;
+ }
+
+ public void setState(@NotNull Map<String, Boolean> templatesState) {
+ myTemplatesState.clear();
+ for (Map.Entry<String, Boolean> entry : templatesState.entrySet()) {
+ myTemplatesState.put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @NotNull
+ public Map<String, Boolean> getState() {
+ return myTemplatesState;
+ }
+
+ public void setEnabled(boolean enabled) {
+ myTemplatesTableView.setEnabled(enabled);
+ }
+
+ private class BooleanColumnInfo extends ColumnInfo<PostfixTemplate, Boolean> {
+ private final BooleanTableCellRenderer CELL_RENDERER = new BooleanTableCellRenderer();
+ private final BooleanTableCellEditor CELL_EDITOR = new BooleanTableCellEditor();
+ private final int WIDTH = new JBCheckBox().getPreferredSize().width + 4;
+
+ public BooleanColumnInfo() {
+ super("");
+ }
+
+ @Nullable
+ @Override
+ public TableCellRenderer getRenderer(PostfixTemplate template) {
+ return CELL_RENDERER;
+ }
+
+ @Nullable
+ @Override
+ public TableCellEditor getEditor(PostfixTemplate template) {
+ return CELL_EDITOR;
+ }
+
+ @Override
+ public int getWidth(JTable table) {
+ return WIDTH;
+ }
+
+ @NotNull
+ @Override
+ public Class getColumnClass() {
+ return Boolean.class;
+ }
+
+ @Override
+ public boolean isCellEditable(PostfixTemplate template) {
+ return myTemplatesTableView.isEnabled();
+ }
+
+ @Nullable
+ @Override
+ public Boolean valueOf(@NotNull PostfixTemplate template) {
+ return ContainerUtil.getOrElse(myTemplatesState, template.getKey(), true);
+ }
+
+ @Override
+ public void setValue(@NotNull PostfixTemplate template, Boolean value) {
+ myTemplatesState.put(template.getKey(), value);
+ }
+ }
+
+ private static class StringColumnInfo extends ColumnInfo<PostfixTemplate, String> {
+ @NotNull private final Function<PostfixTemplate, String> myValueOfFunction;
+ @Nullable private final String myPreferredStringValue;
+
+ public StringColumnInfo(@NotNull String name,
+ @NotNull Function<PostfixTemplate, String> valueOfFunction,
+ @Nullable String preferredStringValue) {
+ super(name);
+ myValueOfFunction = valueOfFunction;
+
+ boolean hasValue = preferredStringValue != null && !preferredStringValue.isEmpty();
+ myPreferredStringValue = hasValue ? preferredStringValue : null;
+ }
+
+ @Override
+ public int getAdditionalWidth() {
+ return UIUtil.DEFAULT_HGAP;
+ }
+
+ @Nullable
+ @Override
+ public String getPreferredStringValue() {
+ return myPreferredStringValue;
+ }
+
+ public String valueOf(final PostfixTemplate template) {
+ return myValueOfFunction.fun(template);
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesSettings.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesSettings.java
new file mode 100644
index 0000000..6e5f69c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/settings/PostfixTemplatesSettings.java
@@ -0,0 +1,111 @@
+/*
+ * 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.codeInsight.template.postfix.settings;
+
+import com.intellij.codeInsight.template.impl.TemplateSettings;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Map;
+
+@State(
+ name = "PostfixTemplatesSettings",
+ storages = {
+ @Storage(file = StoragePathMacros.APP_CONFIG + "/postfixTemplates.xml")
+ }
+)
+public class PostfixTemplatesSettings implements PersistentStateComponent<PostfixTemplatesSettings>, ExportableComponent {
+ @NotNull
+ private Map<String, Boolean> myTemplatesState = ContainerUtil.newHashMap();
+ private boolean postfixTemplatesEnabled = true;
+ private boolean templatesCompletionEnabled = true;
+ private int myShortcut = TemplateSettings.TAB_CHAR;
+
+ public boolean isTemplateEnabled(@NotNull PostfixTemplate template) {
+ return ContainerUtil.getOrElse(myTemplatesState, template.getKey(), true);
+ }
+
+ public void disableTemplate(@NotNull PostfixTemplate template) {
+ myTemplatesState.put(template.getKey(), Boolean.FALSE);
+ }
+
+ public boolean isPostfixTemplatesEnabled() {
+ return postfixTemplatesEnabled;
+ }
+
+ public void setPostfixTemplatesEnabled(boolean postfixTemplatesEnabled) {
+ this.postfixTemplatesEnabled = postfixTemplatesEnabled;
+ }
+
+ public boolean isTemplatesCompletionEnabled() {
+ return templatesCompletionEnabled;
+ }
+
+ public void setTemplatesCompletionEnabled(boolean templatesCompletionEnabled) {
+ this.templatesCompletionEnabled = templatesCompletionEnabled;
+ }
+
+ @NotNull
+ public Map<String, Boolean> getTemplatesState() {
+ return myTemplatesState;
+ }
+
+ public void setTemplatesState(@NotNull Map<String, Boolean> templatesState) {
+ myTemplatesState = templatesState;
+ }
+
+ public int getShortcut() {
+ return myShortcut;
+ }
+
+ public void setShortcut(int shortcut) {
+ myShortcut = shortcut;
+ }
+
+ @Nullable
+ public static PostfixTemplatesSettings getInstance() {
+ return ServiceManager.getService(PostfixTemplatesSettings.class);
+ }
+
+ @Nullable
+ @Override
+ public PostfixTemplatesSettings getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(PostfixTemplatesSettings settings) {
+ XmlSerializerUtil.copyBean(settings, this);
+ }
+
+ @NotNull
+ @Override
+ public File[] getExportFiles() {
+ return new File[]{PathManager.getOptionsFile("postfixCompletion.xml")};
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return "Postfix Completion";
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java
new file mode 100644
index 0000000..daa4da2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplate.java
@@ -0,0 +1,17 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+public class AssertStatementPostfixTemplate extends BooleanPostfixTemplate {
+ public AssertStatementPostfixTemplate() {
+ super("assert", "Creates assertion from boolean expression", "assert expr;");
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PostfixTemplatesUtils.createSimpleStatement(context, editor, "assert");
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java
new file mode 100644
index 0000000..ab6f90e
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/BooleanPostfixTemplate.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Document;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+abstract public class BooleanPostfixTemplate extends PostfixTemplate {
+ protected BooleanPostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
+ super(name, description, example);
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ PsiExpression topmostExpression = getTopmostExpression(context);
+ return topmostExpression != null && PostfixTemplatesUtils.isBoolean(topmostExpression.getType());
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
new file mode 100644
index 0000000..414b79c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/CastExpressionPostfixTemplate.java
@@ -0,0 +1,18 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.generation.surroundWith.JavaWithCastSurrounder;
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+public class CastExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+ public CastExpressionPostfixTemplate() {
+ super("cast", "Surrounds expression with cast", "((SomeType) expr)");
+ }
+
+ @Override
+ protected void doIt(@NotNull final Editor editor, @NotNull final PsiExpression expression) {
+ PostfixTemplatesUtils.apply(new JavaWithCastSurrounder(), expression.getProject(), editor, expression);
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java
new file mode 100644
index 0000000..3718745
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplate.java
@@ -0,0 +1,26 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.CodeInsightServicesUtil;
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+public class ElseStatementPostfixTemplate extends BooleanPostfixTemplate {
+ public ElseStatementPostfixTemplate() {
+ super("else", "Checks boolean expression to be 'false'", "if (!expr)");
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expression = getTopmostExpression(context);
+ assert expression != null;
+ PsiExpression invertedExpression = (PsiExpression)expression.replace(CodeInsightServicesUtil.invertCondition(expression));
+ TextRange range = PostfixTemplatesUtils.ifStatement(invertedExpression.getProject(), editor, invertedExpression);
+ if (range != null) {
+ editor.getCaretModel().moveToOffset(range.getStartOffset());
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java
new file mode 100644
index 0000000..6f09a79
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ExpressionPostfixTemplateWithChooser.java
@@ -0,0 +1,88 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.codeInsight.unwrap.ScopeHighlighter;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiType;
+import com.intellij.psi.util.PsiExpressionTrimRenderer;
+import com.intellij.refactoring.IntroduceTargetChooser;
+import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author ignatov
+ */
+public abstract class ExpressionPostfixTemplateWithChooser extends PostfixTemplate {
+ protected ExpressionPostfixTemplateWithChooser(@NotNull String name, @NotNull String description, @NotNull String example) {
+ super(name, description, example);
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ return !getExpressions(context, copyDocument, newOffset).isEmpty();
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
+ List<PsiExpression> expressions = getExpressions(context, editor.getDocument(), editor.getCaretModel().getOffset());
+
+ if (expressions.isEmpty()) {
+ PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
+ }
+ else if (expressions.size() == 1) {
+ doIt(editor, expressions.get(0));
+ }
+ else {
+ IntroduceTargetChooser.showChooser(
+ editor, expressions,
+ new Pass<PsiExpression>() {
+ public void pass(@NotNull final PsiExpression e) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().executeCommand(e.getProject(), new Runnable() {
+ public void run() {
+ doIt(editor, e);
+ }
+ }, "Expand postfix template", PostfixLiveTemplate.POSTFIX_TEMPLATE_ID);
+ }
+ });
+ }
+ },
+ new PsiExpressionTrimRenderer.RenderFunction(),
+ "Expressions", 0, ScopeHighlighter.NATURAL_RANGER);
+ }
+ }
+
+ @NotNull
+ protected List<PsiExpression> getExpressions(@NotNull PsiElement context, @NotNull Document document, int offset) {
+ List<PsiExpression> expressions = IntroduceVariableBase.collectExpressions(context.getContainingFile(), document, offset, false);
+ return ContainerUtil.filter(expressions.isEmpty() ? maybeTopmostExpression(context) : expressions, getTypeCondition());
+ }
+
+ @NotNull
+ @SuppressWarnings("unchecked")
+ protected Condition<PsiExpression> getTypeCondition() {
+ return Condition.TRUE;
+ }
+
+ @NotNull
+ private static List<PsiExpression> maybeTopmostExpression(@NotNull PsiElement context) {
+ PsiExpression expression = getTopmostExpression(context);
+ PsiType type = expression != null ? expression.getType() : null;
+ if (type == null || PsiType.VOID.equals(type)) return ContainerUtil.emptyList();
+ return ContainerUtil.createMaybeSingletonList(expression);
+ }
+
+ protected abstract void doIt(@NotNull Editor editor, @NotNull PsiExpression expression);
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForAscendingPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForAscendingPostfixTemplate.java
new file mode 100644
index 0000000..f2282eb
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForAscendingPostfixTemplate.java
@@ -0,0 +1,31 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class ForAscendingPostfixTemplate extends ForIndexedPostfixTemplate {
+ public ForAscendingPostfixTemplate() {
+ super("fori", "Iterates with index over collection", "for (int i = 0; i < expr.length; i++)");
+ }
+
+ @Override
+ @NotNull
+ protected String getOperator() {
+ return "++";
+ }
+
+ @NotNull
+ @Override
+ protected String getComparativeSign(@NotNull PsiExpression expr) {
+ return "<";
+ }
+
+ @Nullable
+ @Override
+ protected Pair<String, String> calculateBounds(@NotNull PsiExpression expression) {
+ String bound = getExpressionBound(expression);
+ return bound != null ? Pair.create("0", bound) : null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java
new file mode 100644
index 0000000..33888a5
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplate.java
@@ -0,0 +1,37 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class ForDescendingPostfixTemplate extends ForIndexedPostfixTemplate {
+ public ForDescendingPostfixTemplate() {
+ super("forr", "Iterates with index in reverse order", "for (int i = expr.length-1; i >= 0; i--)");
+ }
+
+ @Override
+ @NotNull
+ protected String getOperator() {
+ return "--";
+ }
+
+ @NotNull
+ @Override
+ protected String getComparativeSign(@NotNull PsiExpression expr) {
+ return PostfixTemplatesUtils.isNumber(expr.getType()) ? ">" : ">=";
+ }
+
+ @Nullable
+ @Override
+ protected Pair<String, String> calculateBounds(@NotNull PsiExpression expression) {
+ String bound = getExpressionBound(expression);
+ if (bound == null) {
+ return null;
+ }
+ return PostfixTemplatesUtils.isNumber(expression.getType())
+ ? Pair.create(bound, "0")
+ : Pair.create(bound + " - 1", "0");
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java
new file mode 100644
index 0000000..c353c8d
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForIndexedPostfixTemplate.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.templates;
+
+import com.intellij.codeInsight.template.Template;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.codeInsight.template.impl.MacroCallNode;
+import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class ForIndexedPostfixTemplate extends PostfixTemplate {
+ protected ForIndexedPostfixTemplate(@NotNull String key, @NotNull String description, @NotNull String example) {
+ super(key, description, example);
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ PsiExpression expr = getTopmostExpression(context);
+ return expr != null && (PostfixTemplatesUtils.isNumber(expr.getType()) ||
+ PostfixTemplatesUtils.isArray(expr.getType()) ||
+ PostfixTemplatesUtils.isIterable(expr.getType()));
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expr = getTopmostExpression(context);
+ if (expr == null) {
+ PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
+ return;
+ }
+
+ Pair<String, String> bounds = calculateBounds(expr);
+ if (bounds == null) {
+ PostfixTemplatesUtils.showErrorHint(context.getProject(), editor);
+ return;
+ }
+ Project project = context.getProject();
+
+ Document document = editor.getDocument();
+ document.deleteString(expr.getTextRange().getStartOffset(), expr.getTextRange().getEndOffset());
+ TemplateManager manager = TemplateManager.getInstance(project);
+
+ Template template = manager.createTemplate("", "");
+ template.setToReformat(true);
+ template.addTextSegment("for (" + suggestIndexType(expr) + " ");
+ MacroCallNode index = new MacroCallNode(new SuggestVariableNameMacro());
+ String indexVariable = "index";
+ template.addVariable(indexVariable, index, index, true);
+ template.addTextSegment(" = " + bounds.first + "; ");
+ template.addVariableSegment(indexVariable);
+ template.addTextSegment(getComparativeSign(expr));
+ template.addTextSegment(bounds.second);
+ template.addTextSegment("; ");
+ template.addVariableSegment(indexVariable);
+ template.addTextSegment(getOperator());
+ template.addTextSegment(") {\n");
+ template.addEndVariable();
+ template.addTextSegment("\n}");
+
+ manager.startTemplate(editor, template);
+ }
+
+ @NotNull
+ protected abstract String getComparativeSign(@NotNull PsiExpression expr);
+
+ @Nullable
+ protected abstract Pair<String, String> calculateBounds(@NotNull PsiExpression expression);
+
+ @NotNull
+ protected abstract String getOperator();
+
+ @Nullable
+ protected static String getExpressionBound(@NotNull PsiExpression expr) {
+ PsiType type = expr.getType();
+ if (PostfixTemplatesUtils.isNumber(type)) {
+ return expr.getText();
+ }
+ else if (PostfixTemplatesUtils.isArray(type)) {
+ return expr.getText() + ".length";
+ }
+ else if (PostfixTemplatesUtils.isIterable(type)) {
+ return expr.getText() + ".size()";
+ }
+ return null;
+ }
+
+ @NotNull
+ private static String suggestIndexType(@NotNull PsiExpression expr) {
+ PsiType type = expr.getType();
+ if (PostfixTemplatesUtils.isNumber(type)) {
+ return type.getCanonicalText();
+ }
+ return "int";
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.java
new file mode 100644
index 0000000..aabf47c
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ForeachPostfixTemplate.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.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.Template;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.codeInsight.template.impl.MacroCallNode;
+import com.intellij.codeInsight.template.impl.TextExpression;
+import com.intellij.codeInsight.template.impl.VariableNode;
+import com.intellij.codeInsight.template.macro.IterableComponentTypeMacro;
+import com.intellij.codeInsight.template.macro.SuggestVariableNameMacro;
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+public class ForeachPostfixTemplate extends PostfixTemplate {
+ public ForeachPostfixTemplate() {
+ super("for", "Iterates over enumerable collection", "for (T item : collection)");
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ PsiExpression expr = getTopmostExpression(context);
+ return expr != null && (PostfixTemplatesUtils.isArray(expr.getType()) || PostfixTemplatesUtils.isIterable(expr.getType()));
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expr = getTopmostExpression(context);
+ if (expr == null) return;
+ Project project = context.getProject();
+
+ Document document = editor.getDocument();
+ document.deleteString(expr.getTextRange().getStartOffset(), expr.getTextRange().getEndOffset());
+ TemplateManager manager = TemplateManager.getInstance(project);
+
+ Template template = manager.createTemplate("", "");
+ template.setToReformat(true);
+ template.addTextSegment("for (");
+ MacroCallNode type = new MacroCallNode(new IterableComponentTypeMacro());
+
+ String variable = "variable";
+ type.addParameter(new VariableNode(variable, null));
+ MacroCallNode name = new MacroCallNode(new SuggestVariableNameMacro());
+
+ template.addVariable("type", type, type, false);
+ template.addTextSegment(" ");
+ template.addVariable("name", name, name, true);
+
+ template.addTextSegment(" : ");
+ template.addVariable(variable, new TextExpression(expr.getText()), false);
+ template.addTextSegment(") {\n");
+ template.addEndVariable();
+ template.addTextSegment("\n}");
+
+ manager.startTemplate(editor, template);
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java
new file mode 100644
index 0000000..9610ec5
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplate.java
@@ -0,0 +1,25 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+public class IfStatementPostfixTemplate extends BooleanPostfixTemplate {
+ public IfStatementPostfixTemplate() {
+ super("if", "Checks boolean expression to be 'true'", "if (expr)");
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull final Editor editor) {
+ PsiExpression expression = getTopmostExpression(context);
+ assert expression != null;
+ TextRange range = PostfixTemplatesUtils.ifStatement(expression.getProject(), editor, expression);
+ if (range != null) {
+ editor.getCaretModel().moveToOffset(range.getStartOffset());
+ }
+ }
+}
+
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java
new file mode 100644
index 0000000..aac8bf9
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/InstanceofExpressionPostfixTemplate.java
@@ -0,0 +1,108 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.guess.GuessManager;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
+import com.intellij.codeInsight.template.*;
+import com.intellij.codeInsight.template.postfix.util.Aliases;
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
+import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.refactoring.introduceField.ElementToWorkOn;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+@Aliases(".inst")
+public class InstanceofExpressionPostfixTemplate extends PostfixTemplate {
+ public InstanceofExpressionPostfixTemplate() {
+ super("instanceof", "Surrounds expression with instanceof", "expr instanceof SomeType ? ((SomeType) expr). : null");
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ return getTopmostExpression(context) != null;
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expression = getTopmostExpression(context);
+ if (expression == null) return;
+ surroundExpression(context.getProject(), editor, expression);
+ }
+
+ private static void surroundExpression(Project project, Editor editor, PsiExpression expr) throws IncorrectOperationException {
+ assert expr.isValid();
+ PsiType[] types = GuessManager.getInstance(project).guessTypeToCast(expr);
+ final boolean parenthesesNeeded = expr instanceof PsiPolyadicExpression ||
+ expr instanceof PsiConditionalExpression ||
+ expr instanceof PsiAssignmentExpression;
+ String exprText = parenthesesNeeded ? "(" + expr.getText() + ")" : expr.getText();
+ Template template = generateTemplate(project, exprText, types);
+ TextRange range;
+ if (expr.isPhysical()) {
+ range = expr.getTextRange();
+ }
+ else {
+ RangeMarker rangeMarker = expr.getUserData(ElementToWorkOn.TEXT_RANGE);
+ if (rangeMarker == null) {
+ PostfixTemplatesUtils.showErrorHint(project, editor);
+ return;
+ }
+ range = new TextRange(rangeMarker.getStartOffset(), rangeMarker.getEndOffset());
+ }
+ editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
+ editor.getCaretModel().moveToOffset(range.getStartOffset());
+ editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ TemplateManager.getInstance(project).startTemplate(editor, template);
+ }
+
+ private static Template generateTemplate(Project project, String exprText, PsiType[] suggestedTypes) {
+ TemplateManager templateManager = TemplateManager.getInstance(project);
+ Template template = templateManager.createTemplate("", "");
+ template.setToReformat(true);
+
+ Set<LookupElement> itemSet = new LinkedHashSet<LookupElement>();
+ for (PsiType type : suggestedTypes) {
+ itemSet.add(PsiTypeLookupItem.createLookupItem(type, null));
+ }
+ final LookupElement[] lookupItems = itemSet.toArray(new LookupElement[itemSet.size()]);
+ final Result result = suggestedTypes.length > 0 ? new PsiTypeResult(suggestedTypes[0], project) : null;
+
+ Expression expr = new Expression() {
+ @Override
+ public LookupElement[] calculateLookupItems(ExpressionContext context) {
+ return lookupItems.length > 1 ? lookupItems : null;
+ }
+
+ @Override
+ public Result calculateResult(ExpressionContext context) {
+ return result;
+ }
+
+ @Override
+ public Result calculateQuickResult(ExpressionContext context) {
+ return null;
+ }
+ };
+
+ template.addTextSegment(exprText);
+ template.addTextSegment(" instanceof ");
+ String type = "type";
+ template.addVariable(type, expr, expr, true);
+ template.addTextSegment(" ? ((");
+ template.addVariableSegment(type);
+ template.addTextSegment(")" + exprText + ")");
+ template.addEndVariable();
+ template.addTextSegment(" : null;");
+
+ return template;
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
new file mode 100644
index 0000000..cb85db9
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceFieldPostfixTemplate.java
@@ -0,0 +1,40 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
+import org.jetbrains.annotations.NotNull;
+
+public class IntroduceFieldPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+ public IntroduceFieldPostfixTemplate() {
+ super("field", "Introduces field for expression", "myField = expr;");
+ }
+
+ @Override
+ protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) {
+ IntroduceFieldHandler handler = ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler(expression) : new IntroduceFieldHandler();
+ handler.invoke(expression.getProject(), new PsiElement[]{expression}, null);
+ }
+
+ @NotNull
+ private static IntroduceFieldHandler getMockHandler(@NotNull final PsiExpression expression) {
+ final PsiClass containingClass = PsiTreeUtil.getParentOfType(expression, PsiClass.class);
+ assert containingClass != null;
+
+ return new IntroduceFieldHandler() {
+ // mock default settings
+ @Override
+ protected Settings showRefactoringDialog(Project project, Editor editor, PsiClass parentClass,
+ PsiExpression expr, PsiType type, PsiExpression[] occurrences,
+ PsiElement anchorElement, PsiElement anchorElementIfAll) {
+ return new Settings(
+ "foo", expression, PsiExpression.EMPTY_ARRAY, false, false, false,
+ InitializationPlace.IN_CURRENT_METHOD, PsiModifier.PRIVATE, null,
+ null, false, containingClass, false, false);
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
new file mode 100644
index 0000000..019a4fe
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IntroduceVariablePostfixTemplate.java
@@ -0,0 +1,72 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiType;
+import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
+import com.intellij.refactoring.introduceVariable.InputValidator;
+import com.intellij.refactoring.introduceVariable.IntroduceVariableHandler;
+import com.intellij.refactoring.introduceVariable.IntroduceVariableSettings;
+import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
+import org.jetbrains.annotations.NotNull;
+
+// todo: support for int[].var (parses as .class access!)
+public class IntroduceVariablePostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+ public IntroduceVariablePostfixTemplate() {
+ super("var", "Introduces variable for expression", "T name = expr;");
+ }
+
+ @Override
+ protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) {
+ // for advanced stuff use ((PsiJavaCodeReferenceElement)expression).advancedResolve(true).getElement();
+ IntroduceVariableHandler handler = ApplicationManager.getApplication().isUnitTestMode() ? getMockHandler() : new IntroduceVariableHandler();
+ handler.invoke(expression.getProject(), editor, expression);
+ }
+
+ @NotNull
+ private static IntroduceVariableHandler getMockHandler() {
+ return new IntroduceVariableHandler() {
+ // mock default settings
+ @Override
+ public final IntroduceVariableSettings getSettings(Project project, Editor editor, final PsiExpression expr,
+ PsiExpression[] occurrences, TypeSelectorManagerImpl typeSelectorManager,
+ boolean declareFinalIfAll, boolean anyAssignmentLHS, InputValidator validator,
+ PsiElement anchor, OccurrencesChooser.ReplaceChoice replaceChoice) {
+ return new IntroduceVariableSettings() {
+ @Override
+ public String getEnteredName() {
+ return "foo";
+ }
+
+ @Override
+ public boolean isReplaceAllOccurrences() {
+ return false;
+ }
+
+ @Override
+ public boolean isDeclareFinal() {
+ return false;
+ }
+
+ @Override
+ public boolean isReplaceLValues() {
+ return false;
+ }
+
+ @Override
+ public PsiType getSelectedType() {
+ return expr.getType();
+ }
+
+ @Override
+ public boolean isOK() {
+ return true;
+ }
+ };
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java
new file mode 100644
index 0000000..0d6ce72
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/IsNullCheckPostfixTemplate.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class IsNullCheckPostfixTemplate extends NullCheckPostfixTemplate {
+ public IsNullCheckPostfixTemplate() {
+ super("null", "Checks expression to be null", "if (expr == null)");
+ }
+
+ @NotNull
+ @Override
+ protected String getTail() {
+ return "== null";
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
new file mode 100644
index 0000000..14c723f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplate.java
@@ -0,0 +1,32 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.CodeInsightServicesUtil;
+import com.intellij.codeInsight.template.postfix.util.Aliases;
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+@Aliases("!")
+public class NotExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+ public NotExpressionPostfixTemplate() {
+ super("not", "Negates boolean expression", "!expr");
+ }
+
+ @Override
+ protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) {
+ expression.replace(CodeInsightServicesUtil.invertCondition(expression));
+ }
+
+ @NotNull
+ @Override
+ protected Condition<PsiExpression> getTypeCondition() {
+ return new Condition<PsiExpression>() {
+ @Override
+ public boolean value(PsiExpression expression) {
+ return PostfixTemplatesUtils.isBoolean(expression.getType());
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java
new file mode 100644
index 0000000..e4bde32
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NotNullCheckPostfixTemplate.java
@@ -0,0 +1,17 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.Aliases;
+import org.jetbrains.annotations.NotNull;
+
+@Aliases(".nn")
+public class NotNullCheckPostfixTemplate extends NullCheckPostfixTemplate {
+ public NotNullCheckPostfixTemplate() {
+ super("notnull", "Checks expression to be not-null", "if (expr != null)");
+ }
+
+ @NotNull
+ @Override
+ protected String getTail() {
+ return "!= null";
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.java
new file mode 100644
index 0000000..77126b8
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/NullCheckPostfixTemplate.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.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementFactory;
+import com.intellij.psi.PsiExpression;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public abstract class NullCheckPostfixTemplate extends PostfixTemplate {
+ protected NullCheckPostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
+ super(name, description, example);
+ }
+
+ @NotNull
+ abstract String getTail();
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ return getTopmostExpression(context) != null;
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expr = getTopmostExpression(context);
+ if (expr == null) return;
+
+ Project project = expr.getProject();
+ PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
+ PsiExpression condition = factory.createExpressionFromText(expr.getText() + getTail(), context);
+
+ PsiElement replace = expr.replace(condition);
+ assert replace instanceof PsiExpression;
+
+ TextRange range = PostfixTemplatesUtils.ifStatement(project, editor, (PsiExpression)replace);
+ if (range != null) {
+ editor.getCaretModel().moveToOffset(range.getStartOffset());
+ }
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
new file mode 100644
index 0000000..52492fb
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ParenthesizedExpressionPostfixTemplate.java
@@ -0,0 +1,24 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiElementFactory;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiParenthesizedExpression;
+import org.jetbrains.annotations.NotNull;
+
+public class ParenthesizedExpressionPostfixTemplate extends ExpressionPostfixTemplateWithChooser {
+ public ParenthesizedExpressionPostfixTemplate() {
+ super("par", "Parenthesizes expression", "(expression)");
+ }
+
+ @Override
+ protected void doIt(@NotNull Editor editor, @NotNull PsiExpression expression) {
+ PsiElementFactory factory = JavaPsiFacade.getInstance(expression.getProject()).getElementFactory();
+ PsiParenthesizedExpression parenthesizedExpression = (PsiParenthesizedExpression)factory.createExpressionFromText("(expr)", expression.getParent());
+ PsiExpression operand = parenthesizedExpression.getExpression();
+ assert operand != null;
+ operand.replace(expression);
+ expression.replace(parenthesizedExpression);
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java
new file mode 100644
index 0000000..95b1ceb
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixLiveTemplate.java
@@ -0,0 +1,314 @@
+/*
+ * 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.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.completion.CompletionInitializationContext;
+import com.intellij.codeInsight.completion.JavaCompletionContributor;
+import com.intellij.codeInsight.template.CustomLiveTemplateBase;
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
+import com.intellij.codeInsight.template.impl.TemplateSettings;
+import com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupElement;
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
+import com.intellij.codeInsight.template.postfix.util.Aliases;
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.undo.UndoConstants;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileFactory;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+public class PostfixLiveTemplate extends CustomLiveTemplateBase {
+ public static final String POSTFIX_TEMPLATE_ID = "POSTFIX_TEMPLATE_ID";
+
+ private static final Logger LOG = Logger.getInstance(PostfixLiveTemplate.class);
+ private final HashMap<String, PostfixTemplate> myTemplates = ContainerUtil.newHashMap();
+
+ public PostfixLiveTemplate() {
+ for (PostfixTemplate template : PostfixTemplate.EP_NAME.getExtensions()) {
+ register(template.getKey(), template);
+ Aliases aliases = template.getClass().getAnnotation(Aliases.class);
+ if (aliases != null) {
+ for (String key : aliases.value()) {
+ register(key, template);
+ }
+ }
+ }
+ }
+
+ private void register(@NotNull String key, @NotNull PostfixTemplate template) {
+ PostfixTemplate registered = myTemplates.put(key, template);
+ if (registered != null) {
+ LOG.error("Can't register postfix template. Duplicated key: " + template.getKey());
+ }
+ }
+
+ @Nullable
+ @Override
+ public String computeTemplateKey(@NotNull CustomTemplateCallback callback) {
+ Editor editor = callback.getEditor();
+ String key = computeTemplateKeyWithoutContextChecking(editor.getDocument().getCharsSequence(), editor.getCaretModel().getOffset());
+ if (key == null) return null;
+ return isApplicableTemplate(getTemplateByKey(key), key, callback.getContext().getContainingFile(), editor) ? key : null;
+ }
+
+ @Nullable
+ @Override
+ public String computeTemplateKeyWithoutContextChecking(@NotNull CustomTemplateCallback callback) {
+ Editor editor = callback.getEditor();
+ return computeTemplateKeyWithoutContextChecking(editor.getDocument().getCharsSequence(), editor.getCaretModel().getOffset());
+ }
+
+ @Nullable
+ public String computeTemplateKeyWithoutContextChecking(@NotNull CharSequence documentContent, int currentOffset) {
+ int startOffset = currentOffset;
+ if (documentContent.length() < startOffset) {
+ return null;
+ }
+ while (startOffset > 0) {
+ char currentChar = documentContent.charAt(startOffset - 1);
+ if (!Character.isJavaIdentifierPart(currentChar)) {
+ if (currentChar != '.' && currentChar != '!') {
+ return null;
+ }
+ startOffset--;
+ break;
+ }
+ startOffset--;
+ }
+ return String.valueOf(documentContent.subSequence(startOffset, currentOffset));
+ }
+
+ @Override
+ public void expand(@NotNull final String key, @NotNull final CustomTemplateCallback callback) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+
+ final PostfixTemplate template = getTemplateByKey(key);
+ final Editor editor = callback.getEditor();
+ final PsiFile file = callback.getContext().getContainingFile();
+ if (isApplicableTemplate(template, key, file, editor)) {
+ int currentOffset = editor.getCaretModel().getOffset();
+ PsiElement newContext = deleteTemplateKey(file, editor.getDocument(), currentOffset, key);
+ newContext = addSemicolonIfNeeded(editor, editor.getDocument(), newContext, currentOffset - key.length());
+ expandTemplate(template, editor, newContext);
+ }
+ else {
+ LOG.error("Template not found by key: " + key);
+ }
+ }
+
+ @Override
+ public boolean isApplicable(PsiFile file, int offset, boolean wrapping) {
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ if (wrapping || file == null || settings == null || !settings.isPostfixTemplatesEnabled() ||
+ PsiUtilCore.getLanguageAtOffset(file, offset) != JavaLanguage.INSTANCE) {
+ return false;
+ }
+ return StringUtil.isNotEmpty(computeTemplateKeyWithoutContextChecking(file.getText(), offset + 1));
+ }
+
+ @Override
+ public boolean supportsWrapping() {
+ return false;
+ }
+
+ @Override
+ public void wrap(@NotNull String selection, @NotNull CustomTemplateCallback callback) {
+ throw new UnsupportedOperationException();
+ }
+
+ @NotNull
+ @Override
+ public String getTitle() {
+ return "Postfix";
+ }
+
+ @Override
+ public char getShortcut() {
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ return settings != null ? (char)settings.getShortcut() : TemplateSettings.TAB_CHAR;
+ }
+
+ @Override
+ public boolean hasCompletionItem(@NotNull PsiFile file, int offset) {
+ return true;
+ }
+
+ @NotNull
+ @Override
+ public Collection<? extends CustomLiveTemplateLookupElement> getLookupElements(@NotNull PsiFile file, @NotNull Editor editor, int offset) {
+ String key = computeTemplateKeyWithoutContextChecking(editor.getDocument().getCharsSequence(), offset);
+ if (key != null) {
+ Map<String, CustomLiveTemplateLookupElement> result = ContainerUtil.newHashMap();
+ Condition<PostfixTemplate> isApplicationTemplateFunction = createIsApplicationTemplateFunction(key, file, editor);
+ for (Map.Entry<String, PostfixTemplate> entry : myTemplates.entrySet()) {
+ PostfixTemplate postfixTemplate = entry.getValue();
+ if (entry.getKey().startsWith(key) && isApplicationTemplateFunction.value(postfixTemplate)) {
+ result.put(postfixTemplate.getKey(), new PostfixTemplateLookupElement(this, postfixTemplate, postfixTemplate.getKey(), false));
+ }
+ }
+ return result.values();
+ }
+ return super.getLookupElements(file, editor, offset);
+ }
+
+ @NotNull
+ public Set<String> getAllTemplateKeys() {
+ return myTemplates.keySet();
+ }
+
+ @Nullable
+ public PostfixTemplate getTemplateByKey(@NotNull String key) {
+ return myTemplates.get(key);
+ }
+
+ private static void expandTemplate(@NotNull final PostfixTemplate template,
+ @NotNull final Editor editor,
+ @NotNull final PsiElement context) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().executeCommand(context.getProject(), new Runnable() {
+ public void run() {
+ template.expand(context, editor);
+ }
+ }, "Expand postfix template", POSTFIX_TEMPLATE_ID);
+ }
+ });
+ }
+
+ @Contract("null, _, _, _ -> false")
+ private static boolean isApplicableTemplate(@Nullable PostfixTemplate template, @NotNull String key, @NotNull PsiFile file, @NotNull Editor editor) {
+ return createIsApplicationTemplateFunction(key, file, editor).value(template);
+ }
+
+ private static Condition<PostfixTemplate> createIsApplicationTemplateFunction(@NotNull String key, @NotNull PsiFile file, @NotNull Editor editor) {
+ int currentOffset = editor.getCaretModel().getOffset();
+ final int newOffset = currentOffset - key.length();
+ CharSequence fileContent = editor.getDocument().getCharsSequence();
+
+ StringBuilder fileContentWithoutKey = new StringBuilder();
+ fileContentWithoutKey.append(fileContent.subSequence(0, newOffset));
+ fileContentWithoutKey.append(fileContent.subSequence(currentOffset, fileContent.length()));
+ PsiFile copyFile = copyFile(file, fileContentWithoutKey);
+ Document copyDocument = copyFile.getViewProvider().getDocument();
+ if (copyDocument == null) {
+ //noinspection unchecked
+ return Condition.FALSE;
+ }
+
+ if (isSemicolonNeeded(copyFile, editor)) {
+ fileContentWithoutKey.insert(newOffset, ';');
+ copyFile = copyFile(file, fileContentWithoutKey);
+ copyDocument = copyFile.getViewProvider().getDocument();
+ if (copyDocument == null) {
+ //noinspection unchecked
+ return Condition.FALSE;
+ }
+ }
+
+ final PsiElement context = CustomTemplateCallback.getContext(copyFile, newOffset > 0 ? newOffset - 1 : newOffset);
+ final Document finalCopyDocument = copyDocument;
+ return new Condition<PostfixTemplate>() {
+ @Override
+ public boolean value(PostfixTemplate template) {
+ return template != null && template.isEnabled() && template.isApplicable(context, finalCopyDocument, newOffset);
+ }
+ };
+ }
+
+ @NotNull
+ private static PsiFile copyFile(@NotNull PsiFile file, @NotNull StringBuilder fileContentWithoutKey) {
+ final PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(file.getProject());
+ PsiFile copy = psiFileFactory.createFileFromText(file.getName(), file.getFileType(), fileContentWithoutKey);
+ VirtualFile vFile = copy.getVirtualFile();
+ if (vFile != null) {
+ vFile.putUserData(UndoConstants.DONT_RECORD_UNDO, Boolean.TRUE);
+ }
+ return copy;
+ }
+
+ @NotNull
+ private static PsiElement deleteTemplateKey(@NotNull final PsiFile file,
+ @NotNull final Document document,
+ final int currentOffset,
+ @NotNull final String key) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+
+ final int startOffset = currentOffset - key.length();
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ public void run() {
+ document.deleteString(startOffset, currentOffset);
+ PsiDocumentManager.getInstance(file.getProject()).commitDocument(document);
+ }
+ });
+ }
+ });
+ return CustomTemplateCallback.getContext(file, startOffset > 0 ? startOffset - 1 : startOffset);
+ }
+
+ @NotNull
+ private static PsiElement addSemicolonIfNeeded(@NotNull final Editor editor,
+ @NotNull final Document document,
+ @NotNull final PsiElement context,
+ final int offset) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+
+ final Ref<PsiElement> newContext = Ref.create(context);
+ final PsiFile file = context.getContainingFile();
+ if (isSemicolonNeeded(file, editor)) {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ public void run() {
+ document.insertString(offset, ";");
+ PsiDocumentManager.getInstance(context.getProject()).commitDocument(document);
+ newContext.set(CustomTemplateCallback.getContext(file, offset - 1));
+ }
+ });
+ }
+ });
+ }
+ return newContext.get();
+ }
+
+ private static boolean isSemicolonNeeded(@NotNull PsiFile file, @NotNull Editor editor) {
+ return JavaCompletionContributor.semicolonNeeded(editor, file, CompletionInitializationContext.calcStartOffset(editor));
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java
new file mode 100644
index 0000000..80a68ab
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/PostfixTemplate.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiExpressionStatement;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class PostfixTemplate {
+ @NotNull private final String myPresentableName;
+ @NotNull private final String myKey;
+ @NotNull private final String myDescription;
+ @NotNull private final String myExample;
+
+ @NotNull
+ public static final ExtensionPointName<PostfixTemplate> EP_NAME = ExtensionPointName.create("com.intellij.postfixTemplate");
+
+ protected PostfixTemplate(@NotNull String name, @NotNull String description, @NotNull String example) {
+ this(name, "." + name, description, example);
+ }
+
+ protected PostfixTemplate(@NotNull String name, @NotNull String key, @NotNull String description, @NotNull String example) {
+ myPresentableName = name;
+ myKey = key;
+ myDescription = description;
+ myExample = example;
+ }
+
+ @NotNull
+ public final String getKey() {
+ return myKey;
+ }
+
+ @NotNull
+ public String getPresentableName() {
+ return myPresentableName;
+ }
+
+ @NotNull
+ public String getDescription() {
+ return myDescription;
+ }
+
+ @NotNull
+ public String getExample() {
+ return myExample;
+ }
+
+ public boolean isEnabled() {
+ final PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ return settings != null && settings.isPostfixTemplatesEnabled() && settings.isTemplateEnabled(this);
+ }
+
+ @Nullable
+ public static PsiExpression getTopmostExpression(PsiElement context) {
+ PsiExpressionStatement statement = PsiTreeUtil.getNonStrictParentOfType(context, PsiExpressionStatement.class);
+ return statement != null ? PsiTreeUtil.getChildOfType(statement, PsiExpression.class) : null;
+ }
+
+ public abstract boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset);
+
+ public abstract void expand(@NotNull PsiElement context, @NotNull Editor editor);
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java
new file mode 100644
index 0000000..e15f6c4
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ReturnStatementPostfixTemplate.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+public class ReturnStatementPostfixTemplate extends PostfixTemplate {
+ public ReturnStatementPostfixTemplate() {
+ super("return", "Returns value from containing method", "return expr;");
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ PsiExpression expr = getTopmostExpression(context);
+ if (expr == null) return false;
+ PsiType type = expr.getType();
+ return type != null && !PsiType.VOID.equals(type);
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expr = getTopmostExpression(context);
+ PsiElement parent = expr != null ? expr.getParent() : null;
+ if (!(parent instanceof PsiExpressionStatement)) return;
+ PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory();
+ PsiReturnStatement returnStatement = (PsiReturnStatement)factory.createStatementFromText("return " + expr.getText() + ";", parent);
+ parent.replace(returnStatement);
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java
new file mode 100644
index 0000000..4449c55
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/StatementPostfixTemplateBase.java
@@ -0,0 +1,37 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.CodeInsightUtilCore;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.util.PsiTreeUtil;
+
+/**
+ * @author ignatov
+ */
+public abstract class StatementPostfixTemplateBase extends PostfixTemplate {
+ protected StatementPostfixTemplateBase(String name, String description, String example) {
+ super(name, description, example);
+ }
+
+ protected void surroundWith(PsiElement context, Editor editor, String text) {
+ PsiExpression expr = getTopmostExpression(context);
+ PsiElement parent = expr != null ? expr.getParent() : null;
+ if (!(parent instanceof PsiExpressionStatement)) return;
+
+ Project project = context.getProject();
+ PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
+ CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
+ PsiElement statement = codeStyleManager.reformat(factory.createStatementFromText(text + " (" + expr.getText() + ") {\nst;\n}", context));
+ statement = parent.replace(statement);
+
+ //noinspection ConstantConditions
+ PsiCodeBlock block = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(PsiTreeUtil.getChildOfType(statement, PsiCodeBlock.class));
+ TextRange range = block.getStatements()[0].getTextRange();
+ editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
+
+ editor.getCaretModel().moveToOffset(range.getStartOffset());
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.java
new file mode 100644
index 0000000..880c045
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SwitchStatementPostfixTemplate.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.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.pom.java.LanguageLevel;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class SwitchStatementPostfixTemplate extends StatementPostfixTemplateBase {
+ public SwitchStatementPostfixTemplate() {
+ super("switch", "Produces switch over integral/enum/string values", "switch (expr)");
+ }
+
+ private static boolean isSwitchCompatibleType(@Nullable PsiType type, @NotNull PsiElement context) {
+ if (type == null) return false;
+ if (PsiType.INT.isAssignableFrom(type)) return true;
+
+ if (type instanceof PsiClassType) {
+ PsiClass psiClass = ((PsiClassType)type).resolve();
+ if (psiClass != null && psiClass.isEnum()) return true;
+ }
+
+ if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) return true; // todo: mock jdk 6 and 7
+ PsiFile containingFile = context.getContainingFile();
+ if (containingFile instanceof PsiJavaFile) {
+ LanguageLevel level = ((PsiJavaFile)containingFile).getLanguageLevel();
+ if (level.isAtLeast(LanguageLevel.JDK_1_7)) return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ PsiExpression expr = getTopmostExpression(context);
+ return expr != null && isSwitchCompatibleType(expr.getType(), context);
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ surroundWith(context, editor, "switch");
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java
new file mode 100644
index 0000000..044dadc
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/SynchronizedStatementPostfixTemplate.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.templates;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+
+public class SynchronizedStatementPostfixTemplate extends StatementPostfixTemplateBase {
+ public SynchronizedStatementPostfixTemplate() {
+ super("synchronized", "Produces synchronization statement", "synchronized (expr)");
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ PsiExpression expression = getTopmostExpression(context);
+ PsiType type = expression != null ? expression.getType() : null;
+ return type != null && !(type instanceof PsiPrimitiveType);
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ surroundWith(context, editor, "synchronized");
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java
new file mode 100644
index 0000000..7c2017f
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/ThrowExceptionPostfixTemplate.java
@@ -0,0 +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.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.postfix.util.PostfixTemplatesUtils;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+public class ThrowExceptionPostfixTemplate extends PostfixTemplate {
+ public ThrowExceptionPostfixTemplate() {
+ super("throw", "Throws expression of 'Throwable' type", "throw expr;");
+ }
+
+ @Override
+ public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
+ return getTopmostExpression(context) != null;
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PostfixTemplatesUtils.createSimpleStatement(context, editor, "throw");
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java
new file mode 100644
index 0000000..03d91b2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplate.java
@@ -0,0 +1,31 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+public class WhileStatementPostfixTemplate extends BooleanPostfixTemplate {
+ public WhileStatementPostfixTemplate() {
+ super("while", "Iterating while boolean statement is 'true'", "while (expr)");
+ }
+
+ @Override
+ public void expand(@NotNull PsiElement context, @NotNull Editor editor) {
+ PsiExpression expression = getTopmostExpression(context);
+ assert expression != null;
+
+ PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject());
+ PsiWhileStatement whileStatement = (PsiWhileStatement)factory.createStatementFromText("while(expr)", context);
+ PsiExpression condition = whileStatement.getCondition();
+ assert condition != null;
+ condition.replace(expression);
+ PsiElement replacedWhileStatement = expression.replace(whileStatement);
+ if (replacedWhileStatement instanceof PsiWhileStatement) {
+ PsiJavaToken parenth = ((PsiWhileStatement)replacedWhileStatement).getRParenth();
+ if (parenth != null) {
+ editor.getCaretModel().moveToOffset(parenth.getTextRange().getEndOffset());
+ }
+ }
+ }
+}
+
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java
new file mode 100644
index 0000000..3de07c3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/Aliases.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.util;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * @author ignatov
+ */
+@Target(value = ElementType.TYPE)
+@Retention(value = RetentionPolicy.RUNTIME)
+public @interface Aliases {
+ String[] value();
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java
new file mode 100644
index 0000000..923dfdc
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/template/postfix/util/PostfixTemplatesUtils.java
@@ -0,0 +1,102 @@
+/*
+ * 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.codeInsight.template.postfix.util;
+
+import com.intellij.codeInsight.generation.surroundWith.JavaExpressionSurrounder;
+import com.intellij.codeInsight.generation.surroundWith.JavaWithIfExpressionSurrounder;
+import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.refactoring.util.CommonRefactoringUtil;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class PostfixTemplatesUtils {
+ private PostfixTemplatesUtils() {
+ }
+
+ public static void showErrorHint(Project project, Editor editor) {
+ CommonRefactoringUtil.showErrorHint(project, editor, "Can't expand postfix template", "Can't expand postfix template", "");
+ }
+
+ public static void createSimpleStatement(@NotNull PsiElement context, @NotNull Editor editor, @NotNull String text) {
+ PsiExpression expr = PostfixTemplate.getTopmostExpression(context);
+ PsiElement parent = expr != null ? expr.getParent() : null;
+ assert parent instanceof PsiStatement;
+ PsiElementFactory factory = JavaPsiFacade.getInstance(context.getProject()).getElementFactory();
+ PsiStatement assertStatement = factory.createStatementFromText(text + " " + expr.getText() + ";", parent);
+ PsiElement replace = parent.replace(assertStatement);
+ editor.getCaretModel().moveToOffset(replace.getTextRange().getEndOffset());
+ }
+
+ @Contract("null -> false")
+ public static boolean isIterable(@Nullable PsiType type) {
+ return type != null && InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_LANG_ITERABLE);
+ }
+
+ @Contract("null -> false")
+ public static boolean isArray(@Nullable PsiType type) {
+ return type != null && type instanceof PsiArrayType;
+ }
+
+ @Contract("null -> false")
+ public static boolean isBoolean(@Nullable PsiType type) {
+ return type != null && (PsiType.BOOLEAN.equals(type) || PsiType.BOOLEAN.equals(PsiPrimitiveType.getUnboxedType(type)));
+ }
+
+ @Contract("null -> false")
+ public static boolean isNumber(@Nullable PsiType type) {
+ if (type == null) {
+ return false;
+ }
+ if (PsiType.INT.equals(type) || PsiType.BYTE.equals(type) || PsiType.LONG.equals(type)) {
+ return true;
+ }
+
+ PsiPrimitiveType unboxedType = PsiPrimitiveType.getUnboxedType(type);
+ return PsiType.INT.equals(unboxedType) || PsiType.BYTE.equals(unboxedType) || PsiType.LONG.equals(unboxedType);
+ }
+
+ @Nullable
+ public static TextRange ifStatement(@NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) {
+ JavaExpressionSurrounder surrounder = new JavaWithIfExpressionSurrounder();
+ PsiElement[] elements = {expr};
+ if (surrounder.isApplicable(elements)) {
+ return surrounder.surroundElements(project, editor, elements);
+ }
+ else {
+ showErrorHint(project, editor);
+ }
+ return null;
+ }
+
+ @Nullable
+ public static TextRange apply(@NotNull JavaExpressionSurrounder surrounder, @NotNull Project project, @NotNull Editor editor, @NotNull PsiExpression expr) {
+ PsiElement[] elements = {expr};
+ if (surrounder.isApplicable(elements)) {
+ return surrounder.surroundElements(project, editor, elements);
+ }
+ else {
+ showErrorHint(project, editor);
+ }
+ return null;
+ }
+}
+
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 a3928ef..7040347 100644
--- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java
+++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/EditContractIntention.java
@@ -50,7 +50,6 @@
private static PsiMethod getTargetMethod(@NotNull Project project, Editor editor, PsiFile file) {
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element == null) return null;
- if (!PsiUtil.isLanguageLevel5OrHigher(element)) return null;
if (!element.getManager().isInProject(element) || CodeStyleSettingsManager.getSettings(project).USE_EXTERNAL_ANNOTATIONS) {
final PsiModifierListOwner owner = AddAnnotationPsiFix.getContainer(element);
if (owner instanceof PsiMethod) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
index 04fe0f2..20465b1 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/DummyEntryPointsPresentation.java
@@ -46,6 +46,11 @@
return myQuickFixActions;
}
+ @Override
+ protected String getSeverityDelegateName() {
+ return UnusedDeclarationInspection.SHORT_NAME;
+ }
+
private class MoveEntriesToSuspicious extends QuickFixAction {
private MoveEntriesToSuspicious(@NotNull InspectionToolWrapper toolWrapper) {
super(InspectionsBundle.message("inspection.dead.code.remove.from.entry.point.quickfix"), null, null, toolWrapper);
diff --git a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
index 8dd6a04..276bb97 100644
--- a/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
+++ b/java/java-impl/src/com/intellij/codeInspection/deadCode/UnusedDeclarationPresentation.java
@@ -117,7 +117,7 @@
@NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag"));
final RefElement refElement = (RefElement)refEntity;
- final HighlightSeverity severity = getSeverity(refElement, getContext(), getToolWrapper());
+ final HighlightSeverity severity = getSeverity(refElement);
final String attributeKey =
getTextAttributeKey(refElement.getRefManager().getProject(), severity, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
problemClassElement.setAttribute("severity", severity.myName);
diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java
index 8d7eeaa..9835c68 100644
--- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/DefaultFileTemplateUsageInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,7 +18,7 @@
import com.intellij.codeInspection.*;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.impl.FileTemplateConfigurable;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -127,7 +127,7 @@
boolean ok = ShowSettingsUtil.getInstance().editConfigurable(project, configurable);
if (ok) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(project, new Runnable() {
@Override
public void run() {
myReplaceTemplateFix.applyFix(project, descriptor);
diff --git a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java
index 85ccbf9..a3db2c3 100644
--- a/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.java
+++ b/java/java-impl/src/com/intellij/codeInspection/defaultFileTemplateUsage/FileHeaderChecker.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.
@@ -49,12 +49,10 @@
public class FileHeaderChecker {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.defaultFileTemplateUsage.FileHeaderChecker");
- static ProblemDescriptor checkFileHeader(@NotNull final PsiFile file, final InspectionManager manager, boolean onTheFly) {
+ static ProblemDescriptor checkFileHeader(@NotNull final PsiFile file, @NotNull InspectionManager manager, boolean onTheFly) {
TIntObjectHashMap<String> offsetToProperty = new TIntObjectHashMap<String>();
- Pattern pattern = getTemplatePattern(FileTemplateManager.getInstance()
- .getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME),
- file.getProject(), offsetToProperty
- );
+ FileTemplate defaultTemplate = FileTemplateManager.getInstance().getDefaultTemplate(FileTemplateManager.FILE_HEADER_TEMPLATE_NAME);
+ Pattern pattern = getTemplatePattern(defaultTemplate, file.getProject(), offsetToProperty);
Matcher matcher = pattern.matcher(file.getViewProvider().getContents());
if (matcher.matches()) {
final int startOffset = matcher.start(1);
@@ -80,7 +78,7 @@
return null;
}
- public static Pattern getTemplatePattern(FileTemplate template, Project project, TIntObjectHashMap<String> offsetToProperty) {
+ public static Pattern getTemplatePattern(@NotNull FileTemplate template, @NotNull Project project, @NotNull TIntObjectHashMap<String> offsetToProperty) {
String templateText = template.getText().trim();
String regex = templateToRegex(templateText, offsetToProperty, project);
regex = StringUtil.replace(regex, "with", "(?:with|by)");
@@ -150,7 +148,7 @@
return new LocalQuickFix[]{replaceTemplateFix,editFileTemplateFix};
}
- private static String templateToRegex(final String text, TIntObjectHashMap<String> offsetToProperty, Project project) {
+ private static String templateToRegex(@NotNull String text, @NotNull TIntObjectHashMap<String> offsetToProperty, @NotNull Project project) {
String regex = text;
@NonNls Collection<String> properties = new ArrayList<String>((Collection)FileTemplateManager.getInstance().getDefaultProperties(project).keySet());
properties.add("PACKAGE_NAME");
@@ -162,7 +160,7 @@
String escaped = escapeRegexChars("${"+name+"}");
boolean first = true;
for (int i = regex.indexOf(escaped); i!=-1 && i<regex.length(); i = regex.indexOf(escaped,i+1)) {
- String replacement = first ? "(.*)" : "\\" + groupNumber;
+ String replacement = first ? "([^\\n]*)" : "\\" + groupNumber;
final int delta = escaped.length() - replacement.length();
int[] offs = offsetToProperty.keys();
for (int off : offs) {
diff --git a/java/java-impl/src/com/intellij/codeInspection/ex/AdditionalAnnotationsRefactoringElementListener.java b/java/java-impl/src/com/intellij/codeInspection/ex/AdditionalAnnotationsRefactoringElementListener.java
new file mode 100644
index 0000000..d639b72
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInspection/ex/AdditionalAnnotationsRefactoringElementListener.java
@@ -0,0 +1,51 @@
+/*
+ * 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.codeInspection.ex;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiQualifiedNamedElement;
+import com.intellij.refactoring.listeners.RefactoringElementListener;
+import com.intellij.refactoring.listeners.RefactoringElementListenerProvider;
+import com.intellij.refactoring.listeners.UndoRefactoringElementAdapter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class AdditionalAnnotationsRefactoringElementListener implements RefactoringElementListenerProvider {
+ @Nullable
+ @Override
+ public RefactoringElementListener getListener(final PsiElement psiElement) {
+ if (!(psiElement instanceof PsiClass)) return null;
+ final String oldName = ((PsiClass)psiElement).getQualifiedName();
+ if (oldName == null) return null;
+ final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(psiElement.getProject());
+ return new UndoRefactoringElementAdapter() {
+ @Override
+ protected void refactored(@NotNull PsiElement element, @Nullable String oldQualifiedName) {
+ if (element instanceof PsiClass) {
+ final String newQualifiedName = ((PsiClass)element).getQualifiedName();
+ if (newQualifiedName != null) {
+ final int idx = entryPointsManager.ADDITIONAL_ANNOTATIONS.indexOf(oldQualifiedName != null ? newQualifiedName : oldName);
+ if (idx > -1) {
+ entryPointsManager.ADDITIONAL_ANNOTATIONS.remove(idx);
+ entryPointsManager.ADDITIONAL_ANNOTATIONS.add(idx, oldQualifiedName != null ? oldQualifiedName : newQualifiedName);
+ }
+ }
+ }
+ }
+ };
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java
index 1add924..ae45a6f 100644
--- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java
+++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/InferNullityAnnotationsAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -37,7 +37,6 @@
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryUtil;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.text.StringUtil;
@@ -130,7 +129,7 @@
"' library with IDEA nullity annotations. Would you like to add the dependenc";
message += (modulesWithoutAnnotations.size() == 1 ? "y" : "ies") + " now?";
if (Messages.showOkCancelDialog(project, message, INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) ==
- DialogWrapper.OK_EXIT_CODE) {
+ Messages.OK) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
@@ -146,7 +145,7 @@
" be available in all your project sources.\n\nYou will need to add annotations.jar as a library. " +
"It is possible to configure custom jar in e.g. Constant Conditions & Exceptions inspection or use JetBrains annotations available in installation. " +
" IntelliJ IDEA nullity annotations are freely usable and redistributable under the Apache 2.0 license. Would you like to do it now?",
- INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ INFER_NULLITY_ANNOTATIONS, Messages.getErrorIcon()) == Messages.OK) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
diff --git a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java
index 06076cf..6496349 100644
--- a/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java
+++ b/java/java-impl/src/com/intellij/codeInspection/inferNullity/NullityInferrer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.codeInsight.NullableNotNullManager;
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
@@ -30,6 +31,7 @@
import com.intellij.util.Query;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
import java.util.ArrayList;
@@ -139,6 +141,7 @@
while (prevNumAnnotationsAdded < numAnnotationsAdded && pass < MAX_PASSES);
}
+ @TestOnly
public void apply(final Project project) {
final NullableNotNullManager manager = NullableNotNullManager.getInstance(project);
for (SmartPsiElementPointer<? extends PsiModifierListOwner> pointer : myNullableSet) {
@@ -175,8 +178,7 @@
if (element != null) {
if (shouldIgnore(element)) return;
if (element instanceof PsiField && ((PsiField)element).hasInitializer() && element.hasModifierProperty(PsiModifier.FINAL)) return;
- new AddAnnotationFix(manager.getDefaultNotNull(), element, manager.getDefaultNullable()).invoke(project, null,
- element.getContainingFile());
+ invoke(project, element, manager.getDefaultNotNull(), manager.getDefaultNullable());
}
}
@@ -186,10 +188,21 @@
final PsiModifierListOwner element = pointer.getElement();
if (element != null) {
if (shouldIgnore(element)) return;
- new AddAnnotationFix(manager.getDefaultNullable(), element, manager.getDefaultNotNull()).invoke(project, null, element.getContainingFile());
+ invoke(project, element, manager.getDefaultNullable(), manager.getDefaultNotNull());
}
}
+ private static void invoke(final Project project,
+ final PsiModifierListOwner element,
+ final String fqn, final String toRemove) {
+ WriteCommandAction.runWriteCommandAction(project, new Runnable() {
+ @Override
+ public void run() {
+ new AddAnnotationFix(fqn, element, toRemove).invoke(project, null, element.getContainingFile());
+ }
+ });
+ }
+
public int getCount() {
return myNotNullSet.size() + myNullableSet.size();
}
diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/FileEqualsUsageInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/FileEqualsUsageInspection.java
deleted file mode 100644
index 7f09a27..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/internal/FileEqualsUsageInspection.java
+++ /dev/null
@@ -1,51 +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.codeInspection.internal;
-
-import com.intellij.codeInspection.ProblemHighlightType;
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.psi.*;
-import org.jetbrains.annotations.NotNull;
-
-public class FileEqualsUsageInspection extends InternalInspection {
- private static final String MESSAGE =
- "Do not use File.equals/hashCode/compareTo as they don't honor case-sensitivity on MacOS. " +
- "Please use FileUtil.filesEquals/fileHashCode/compareFiles instead";
-
- @Override
- @NotNull
- public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
- return new JavaElementVisitor() {
- @Override
- public void visitMethodCallExpression(PsiMethodCallExpression expression) {
- PsiReferenceExpression methodExpression = expression.getMethodExpression();
- PsiElement resolved = methodExpression.resolve();
- if (!(resolved instanceof PsiMethod)) return;
-
- PsiMethod method = (PsiMethod)resolved;
-
- PsiClass clazz = method.getContainingClass();
- if (clazz == null) return;
-
- String methodName = method.getName();
- if (CommonClassNames.JAVA_IO_FILE.equals(clazz.getQualifiedName()) &&
- ("equals".equals(methodName) || "compareTo".equals(methodName) || "hashCode".equals(methodName))) {
- holder.registerProblem(methodExpression, MESSAGE, ProblemHighlightType.LIKE_DEPRECATED);
- }
- }
- };
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java
deleted file mode 100644
index 8011f89..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/internal/GtkPreferredJComboBoxRendererInspection.java
+++ /dev/null
@@ -1,72 +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.codeInspection.internal;
-
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.ListCellRendererWrapper;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-public class GtkPreferredJComboBoxRendererInspection extends InternalInspection {
- private static final String COMBO_BOX_CLASS_NAME = JComboBox.class.getName();
- private static final String[] RIGHT_RENDERER_CLASS_NAMES =
- {ListCellRendererWrapper.class.getName(), ColoredListCellRenderer.class.getName()};
- private static final String SETTER_METHOD_NAME = "setRenderer";
-
- private static final String MESSAGE =
- "Default ListCellRenderer implementations are known to cause UI artifacts under GTK+ look&feel, " +
- "so please use ListCellRendererWrapper or ColoredListCellRenderer instead.";
-
- @Override
- @NotNull
- public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
- return new JavaElementVisitor() {
- @Override
- public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
- super.visitMethodCallExpression(expression);
-
- final Project project = expression.getProject();
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
-
- final PsiElement target = expression.getMethodExpression().resolve();
- if (!(target instanceof PsiMethod)) return;
- final PsiMethod method = (PsiMethod)target;
- if (!SETTER_METHOD_NAME.equals(method.getName())) return;
- final PsiClass aClass = ((PsiMethod)target).getContainingClass();
- final PsiClass comboClass = facade.findClass(COMBO_BOX_CLASS_NAME, GlobalSearchScope.allScope(project));
- if (!InheritanceUtil.isInheritorOrSelf(aClass, comboClass, true)) return;
-
- final PsiExpression[] arguments = expression.getArgumentList().getExpressions();
- if (arguments.length != 1) return;
- final PsiType type = arguments[0].getType();
- if (!(type instanceof PsiClassType)) return;
- final PsiClass rendererClass = ((PsiClassType)type).resolve();
- for (String rightClassName : RIGHT_RENDERER_CLASS_NAMES) {
- final PsiClass rightClass = facade.findClass(rightClassName, GlobalSearchScope.allScope(project));
- if (InheritanceUtil.isInheritorOrSelf(rendererClass, rightClass, true)) return;
- }
-
- holder.registerProblem(expression, MESSAGE);
- }
- };
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/InternalInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/InternalInspection.java
deleted file mode 100644
index 3a27ebd..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/internal/InternalInspection.java
+++ /dev/null
@@ -1,59 +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.codeInspection.internal;
-
-import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
-import com.intellij.codeInspection.LocalInspectionToolSession;
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.ui.components.JBList;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class InternalInspection extends BaseJavaLocalInspectionTool {
- private static final Key<Boolean> INTERNAL_INSPECTIONS = Key.create("idea.internal.inspections.enabled");
- private static final String MARKER_CLASS = JBList.class.getName();
- private static final PsiElementVisitor EMPTY_VISITOR = new PsiElementVisitor() { };
-
- @NotNull
- @Override
- public final PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
- return isAllowed(holder.getProject()) ? buildInternalVisitor(holder, isOnTheFly) : EMPTY_VISITOR;
- }
-
- @NotNull
- @Override
- public final PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
- boolean isOnTheFly,
- @NotNull LocalInspectionToolSession session) {
- return isAllowed(holder.getProject()) ? buildInternalVisitor(holder, isOnTheFly) : EMPTY_VISITOR;
- }
-
- private static boolean isAllowed(@NotNull Project project) {
- Boolean flag = project.getUserData(INTERNAL_INSPECTIONS);
- if (flag == null) {
- final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
- flag = JavaPsiFacade.getInstance(project).findClass(MARKER_CLASS, scope) != null;
- project.putUserData(INTERNAL_INSPECTIONS, flag);
- }
- return flag;
- }
-
- public abstract PsiElementVisitor buildInternalVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly);
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java
deleted file mode 100644
index bf463e2..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/internal/UndesirableClassUsageInspection.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInspection.internal;
-
-import com.intellij.codeInspection.ProblemHighlightType;
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.openapi.application.QueryExecutorBase;
-import com.intellij.openapi.ui.ComboBox;
-import com.intellij.psi.*;
-import com.intellij.ui.components.JBList;
-import com.intellij.ui.components.JBScrollPane;
-import com.intellij.ui.table.JBTable;
-import com.intellij.ui.treeStructure.Tree;
-import com.intellij.util.QueryExecutor;
-import gnu.trove.THashMap;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.image.BufferedImage;
-import java.util.Map;
-
-public class UndesirableClassUsageInspection extends InternalInspection {
- private static final Map<String, String> CLASSES = new THashMap<String, String>();
- static {
- CLASSES.put(JList.class.getName(), JBList.class.getName());
- CLASSES.put(JTable.class.getName(), JBTable.class.getName());
- CLASSES.put(JTree.class.getName(), Tree.class.getName());
- CLASSES.put(JScrollPane.class.getName(), JBScrollPane.class.getName());
- CLASSES.put(JComboBox.class.getName(), ComboBox.class.getName());
- CLASSES.put(QueryExecutor.class.getName(), QueryExecutorBase.class.getName());
- CLASSES.put(BufferedImage.class.getName(), "UIUtil.createImage()");
- }
-
- @Override
- @NotNull
- public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
- return new JavaElementVisitor() {
- @Override
- public void visitNewExpression(PsiNewExpression expression) {
- PsiJavaCodeReferenceElement ref = expression.getClassReference();
- if (ref == null) return;
-
- PsiElement res = ref.resolve();
- if (res == null) return;
-
- String name = ((PsiClass)res).getQualifiedName();
- if (name == null) return;
-
- String replacement = CLASSES.get(name);
- if (replacement == null) return;
-
- holder.registerProblem(expression, "Please use '" + replacement + "' instead", ProblemHighlightType.LIKE_DEPRECATED);
- }
- };
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/internal/UnsafeVfsRecursionInspection.java b/java/java-impl/src/com/intellij/codeInspection/internal/UnsafeVfsRecursionInspection.java
deleted file mode 100644
index 2747ce7..0000000
--- a/java/java-impl/src/com/intellij/codeInspection/internal/UnsafeVfsRecursionInspection.java
+++ /dev/null
@@ -1,76 +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.codeInspection.internal;
-
-import com.intellij.codeInspection.ProblemsHolder;
-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.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import org.jetbrains.annotations.NotNull;
-
-public class UnsafeVfsRecursionInspection extends InternalInspection {
- private static final String VIRTUAL_FILE_CLASS_NAME = VirtualFile.class.getName();
- private static final String GET_CHILDREN_METHOD_NAME = "getChildren";
-
- private static final String MESSAGE =
- "VirtualFile.getChildren() is called from a recursive method. " +
- "This may cause an endless loop on cyclic symlinks. " +
- "Please use VfsUtilCore.visitChildrenRecursively() instead.";
-
- @NotNull
- @Override
- public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
- return new JavaElementVisitor() {
- @Override
- public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
- final Project project = expression.getProject();
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
-
- final PsiReferenceExpression methodRef = expression.getMethodExpression();
- if (!GET_CHILDREN_METHOD_NAME.equals(methodRef.getReferenceName())) return;
- final PsiElement methodElement = methodRef.resolve();
- if (!(methodElement instanceof PsiMethod)) return;
- final PsiMethod method = (PsiMethod)methodElement;
- final PsiClass aClass = method.getContainingClass();
- final PsiClass virtualFileClass = facade.findClass(VIRTUAL_FILE_CLASS_NAME, GlobalSearchScope.allScope(project));
- if (!InheritanceUtil.isInheritorOrSelf(aClass, virtualFileClass, true)) return;
-
- final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expression, PsiMethod.class);
- if (containingMethod == null) return;
- final String containingMethodName = containingMethod.getName();
- final Ref<Boolean> result = Ref.create();
- containingMethod.accept(new JavaRecursiveElementVisitor() {
- @Override
- public void visitMethodCallExpression(final PsiMethodCallExpression expression2) {
- if (expression2 != expression &&
- containingMethodName.equals(expression2.getMethodExpression().getReferenceName()) &&
- expression2.resolveMethod() == containingMethod) {
- result.set(Boolean.TRUE);
- }
- }
- });
-
- if (!result.isNull()) {
- holder.registerProblem(expression, MESSAGE);
- }
- }
- };
- }
-}
diff --git a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
index f53e1fb..b65366b 100644
--- a/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
+++ b/java/java-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java
@@ -379,6 +379,16 @@
public void visitReferenceParameterList(final PsiReferenceParameterList list) {
super.visitReferenceParameterList(list);
final PsiMember member = PsiTreeUtil.getParentOfType(list, PsiMember.class);
+
+ if (member instanceof PsiTypeParameter) {
+ final PsiMember owner = ((PsiTypeParameter)member).getOwner();
+ if (owner != null) {
+ for (PsiClassType type : ((PsiTypeParameter)member).getExtendsListTypes()) {
+ myRefUtil.addTypeReference(owner, type, myRefManager);
+ }
+ }
+ }
+
final PsiType[] typeArguments = list.getTypeArguments();
for (PsiType type : typeArguments) {
myRefUtil.addTypeReference(member, type, myRefManager);
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
index 9750838..e1fa136 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedParameters/UnusedParametersInspection.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,6 +30,7 @@
import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ex.EntryPointsManager;
import com.intellij.codeInspection.reference.*;
+import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspectionBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.util.Comparing;
@@ -43,7 +44,6 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.changeSignature.ChangeSignatureProcessor;
import com.intellij.refactoring.changeSignature.ParameterInfoImpl;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,8 +54,6 @@
import java.util.List;
public class UnusedParametersInspection extends GlobalJavaBatchInspectionTool {
- @NonNls public static final String SHORT_NAME = "UnusedParameters";
-
@Override
@Nullable
public CommonProblemDescriptor[] checkElement(@NotNull final RefEntity refEntity,
@@ -229,7 +227,7 @@
@Override
@NotNull
public String getShortName() {
- return SHORT_NAME;
+ return UnusedSymbolLocalInspectionBase.UNUSED_PARAMETERS_SHORT_NAME;
}
@Override
diff --git a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
index f24fcd7..961427f 100644
--- a/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.java
+++ b/java/java-impl/src/com/intellij/codeInspection/unusedSymbol/UnusedSymbolLocalInspection.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,20 +17,13 @@
package com.intellij.codeInspection.unusedSymbol;
import com.intellij.codeInsight.daemon.GroupNames;
-import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
import com.intellij.codeInspection.ex.EntryPointsManager;
-import com.intellij.codeInspection.ex.EntryPointsManagerBase;
import com.intellij.codeInspection.ex.PairedUnfairLocalInspectionTool;
-import com.intellij.codeInspection.util.SpecialAnnotationsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
-import com.intellij.psi.PsiModifierListOwner;
import org.intellij.lang.annotations.Pattern;
-import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,18 +37,7 @@
* User: anna
* Date: 17-Feb-2006
*/
-public class UnusedSymbolLocalInspection extends BaseJavaLocalInspectionTool implements PairedUnfairLocalInspectionTool {
- @NonNls public static final String SHORT_NAME = HighlightInfoType.UNUSED_SYMBOL_SHORT_NAME;
- @NonNls public static final String DISPLAY_NAME = HighlightInfoType.UNUSED_SYMBOL_DISPLAY_NAME;
-
- public boolean LOCAL_VARIABLE = true;
- public boolean FIELD = true;
- public boolean METHOD = true;
- public boolean CLASS = true;
- public boolean PARAMETER = true;
- public boolean REPORT_PARAMETER_FOR_PUBLIC_METHODS = true;
-
-
+public class UnusedSymbolLocalInspection extends UnusedSymbolLocalInspectionBase implements PairedUnfairLocalInspectionTool {
@Override
@NotNull
public String getGroupDisplayName() {
@@ -154,16 +136,4 @@
public JComponent createOptionsPanel() {
return new OptionsPanel().getPanel();
}
-
- public static IntentionAction createQuickFix(@NonNls String qualifiedName, @Nls String element, Project project) {
- final EntryPointsManagerBase entryPointsManager = EntryPointsManagerBase.getInstance(project);
- return SpecialAnnotationsUtil.createAddToSpecialAnnotationsListIntentionAction(
- QuickFixBundle.message("fix.unused.symbol.injection.text", element, qualifiedName),
- QuickFixBundle.message("fix.unused.symbol.injection.family"),
- entryPointsManager.ADDITIONAL_ANNOTATIONS, qualifiedName);
- }
-
- public static boolean isInjected(final PsiModifierListOwner modifierListOwner) {
- return EntryPointsManagerBase.getInstance(modifierListOwner.getProject()).isEntryPoint(modifierListOwner);
- }
}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java
deleted file mode 100644
index ac45d25..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/ArrayListDataExternalizer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.intellij.compilerOutputIndex.api.descriptor;
-
-import com.intellij.util.io.DataExternalizer;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class ArrayListDataExternalizer<E> implements DataExternalizer<List<E>> {
- private final DataExternalizer<E> myDataExternalizer;
-
- public ArrayListDataExternalizer(final DataExternalizer<E> dataExternalizer) {
- myDataExternalizer = dataExternalizer;
- }
-
- @Override
- public void save(final DataOutput out, final List<E> list) throws IOException {
- out.writeInt(list.size());
- for (final E element : list) {
- myDataExternalizer.save(out, element);
- }
- }
-
- @Override
- public ArrayList<E> read(final DataInput in) throws IOException {
- final int size = in.readInt();
- final ArrayList<E> list = new ArrayList<E>(size);
- for (int i = 0; i < size; i++) {
- list.add(myDataExternalizer.read(in));
- }
- return list;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java
deleted file mode 100644
index fbc538e..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/descriptor/HashSetDataExternalizer.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package com.intellij.compilerOutputIndex.api.descriptor;
-
-import com.intellij.util.io.DataExternalizer;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author Dmitry Batkovich
- */
-public class HashSetDataExternalizer<K> implements DataExternalizer<Set<K>> {
- private final DataExternalizer<K> myDataExternalizer;
-
- public HashSetDataExternalizer(final DataExternalizer<K> myDataExternalizer) {
- this.myDataExternalizer = myDataExternalizer;
- }
-
- @Override
- public void save(final DataOutput out, final Set<K> set) throws IOException {
- out.writeInt(set.size());
- for (final K k : set) {
- myDataExternalizer.save(out, k);
- }
- }
-
- @Override
- public HashSet<K> read(final DataInput in) throws IOException {
- final int size = in.readInt();
- final HashSet<K> set = new HashSet<K>(size);
- for (int i = 0; i < size; i++) {
- set.add(myDataExternalizer.read(in));
- }
- return set;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java
deleted file mode 100644
index 0ed0948..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/AsmUtil.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.intellij.compilerOutputIndex.api.fs;
-
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.asm4.Opcodes;
-import org.jetbrains.asm4.Type;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public final class AsmUtil implements Opcodes {
-
- private AsmUtil() {}
-
- public static boolean isStaticMethodDeclaration(final int access) {
- return (access & Opcodes.ACC_STATIC) != 0;
- }
-
- public static String getQualifiedClassName(final String name) {
- return asJavaInnerClassQName(Type.getObjectType(name).getClassName());
- }
-
- public static String getReturnType(final String desc) {
- return asJavaInnerClassQName(Type.getReturnType(desc).getClassName());
- }
-
- public static String[] getQualifiedClassNames(final String[] classNames, final String... yetAnotherClassNames) {
- final List<String> qualifiedClassNames = new ArrayList<String>(classNames.length + yetAnotherClassNames.length);
- for (final String className : classNames) {
- qualifiedClassNames.add(getQualifiedClassName(className));
- }
- for (final String className : yetAnotherClassNames) {
- if (className != null) {
- qualifiedClassNames.add(getQualifiedClassName(className));
- }
- }
- return ArrayUtil.toStringArray(qualifiedClassNames);
- }
-
- public static String[] getParamsTypes(final String desc) {
- final Type[] types = Type.getArgumentTypes(desc);
- final String[] typesAsString = new String[types.length];
- for (int i = 0; i < types.length; i++) {
- typesAsString[i] = types[i].getClassName();
- }
- return typesAsString;
- }
-
- private static String asJavaInnerClassQName(final String byteCodeClassQName) {
- return StringUtil.replaceChar(byteCodeClassQName, '$', '.');
- }
-
- //char
- //double
- //float
- //int
- //long
- //short
- //boolean
- //byte
- //void
- //Object
- //String
- //Class
- private static final Set<String> ASM_PRIMITIVE_TYPES = ContainerUtil.newHashSet("C", "D", "F", "I", "J", "S", "Z", "B", "V",
- "Ljava/lang/Object;",
- "Ljava/lang/String;",
- "Ljava/lang/Class;");
-
- public static boolean isPrimitive(final String asmType) {
- return ASM_PRIMITIVE_TYPES.contains(asmType);
- }
-
- public static boolean isPrimitiveOrArray(final String asmType) {
- if (asmType.startsWith("[")) {
- return true;
- }
- return isPrimitive(asmType);
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java
deleted file mode 100644
index ef41370..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/CompilerOutputFilesUtil.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.intellij.compilerOutputIndex.api.fs;
-
-import com.intellij.openapi.compiler.CompilerPaths;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.Consumer;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.File;
-import java.util.HashSet;
-import java.util.Set;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public final class CompilerOutputFilesUtil {
-
- private CompilerOutputFilesUtil() {}
-
- public final static String CLASS_FILES_SUFFIX = ".class";
-
- public static void iterateProjectClassFiles(@NotNull final Project project, @NotNull final Consumer<File> fileConsumer) {
- for (final Module module : ModuleManager.getInstance(project).getModules()) {
- iterateModuleClassFiles(module, fileConsumer);
- }
- }
-
- public static void iterateModuleClassFiles(@NotNull final Module module, @NotNull final Consumer<File> fileConsumer) {
- final VirtualFile moduleOutputDirectory = CompilerPaths.getModuleOutputDirectory(module, false);
- if (moduleOutputDirectory == null) {
- return;
- }
- final String canonicalPath = moduleOutputDirectory.getCanonicalPath();
- if (canonicalPath == null) {
- return;
- }
- final File root = new File(canonicalPath);
- iterateClassFilesOverRoot(root, fileConsumer);
- }
-
- public static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer) {
- iterateClassFilesOverRoot(file, fileConsumer, new HashSet<File>());
- }
-
- private static void iterateClassFilesOverRoot(@NotNull final File file, final Consumer<File> fileConsumer, final Set<File> visited) {
- if (file.isDirectory()) {
- final File[] files = file.listFiles();
- if (files != null) {
- for (final File childFile : files) {
- if (visited.add(childFile)) {
- iterateClassFilesOverRoot(childFile.getAbsoluteFile(), fileConsumer, visited);
- }
- }
- }
- }
- else {
- if (file.getName().endsWith(CLASS_FILES_SUFFIX)) {
- fileConsumer.consume(file);
- }
- }
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java
deleted file mode 100644
index 9a7f00b..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/fs/FileVisitorService.java
+++ /dev/null
@@ -1,53 +0,0 @@
-package com.intellij.compilerOutputIndex.api.fs;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.util.Consumer;
-
-import java.io.File;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public interface FileVisitorService {
-
- interface Visitor {
- void visit(File file);
- }
-
- void visit(final Consumer<File> visitor);
-
- class ProjectClassFiles implements FileVisitorService {
- private final Project myProject;
-
- public ProjectClassFiles(final Project project) {
- myProject = project;
- }
-
- @Override
- public void visit(final Consumer<File> visitor) {
- CompilerOutputFilesUtil.iterateProjectClassFiles(myProject, visitor);
- }
- }
-
- class DirectoryClassFiles implements FileVisitorService {
- private final File myDir;
-
- public DirectoryClassFiles(final File dir) {
- if (!dir.isDirectory()) {
- throw new IllegalArgumentException();
- }
- myDir = dir;
- }
-
- @Override
- public void visit(final Consumer<File> visitor) {
- //noinspection ConstantConditions
- for (final File file : myDir.listFiles()) {
- if (file.getName().endsWith(CompilerOutputFilesUtil.CLASS_FILES_SUFFIX)) {
- visitor.consume(file);
- }
- }
- }
- }
-}
-
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java
deleted file mode 100644
index cf4de25..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputBaseIndex.java
+++ /dev/null
@@ -1,170 +0,0 @@
-package com.intellij.compilerOutputIndex.api.indexer;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Factory;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.ThrowableComputable;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.util.indexing.*;
-import com.intellij.util.io.DataExternalizer;
-import com.intellij.util.io.IOUtil;
-import com.intellij.util.io.KeyDescriptor;
-import com.intellij.util.io.PersistentHashMap;
-import org.jetbrains.asm4.tree.ClassNode;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import static com.intellij.util.indexing.IndexInfrastructure.*;
-
-/**
- * @author Dmitry Batkovich
- */
-public abstract class CompilerOutputBaseIndex<K, V> {
- public final static ExtensionPointName<CompilerOutputBaseIndex> EXTENSION_POINT_NAME =
- ExtensionPointName.create("com.intellij.java.compilerOutputIndex");
-
- private final static Logger LOG = Logger.getInstance(CompilerOutputBaseIndex.class);
- private final KeyDescriptor<K> myKeyDescriptor;
- private final DataExternalizer<V> myValueExternalizer;
- protected volatile MapReduceIndex<K, V, ClassNode> myIndex;
-
- protected final Project myProject;
-
- protected volatile AtomicBoolean myInitialized = new AtomicBoolean(false);
-
- public CompilerOutputBaseIndex(final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer, final Project project) {
- myProject = project;
- myKeyDescriptor = keyDescriptor;
- myValueExternalizer = valueExternalizer;
- }
-
- public final boolean initIfNeed() {
- if (myInitialized.compareAndSet(false, true)) {
- final MapReduceIndex<K, V, ClassNode> index;
- final Ref<Boolean> rewriteIndex = new Ref<Boolean>(false);
- try {
- final ID<K, V> indexId = getIndexId();
- if (!IndexInfrastructure.getIndexRootDir(indexId).exists()) {
- rewriteIndex.set(true);
- }
- final File storageFile = getStorageFile(indexId);
- final MapIndexStorage<K, V> indexStorage = IOUtil.openCleanOrResetBroken(
- new ThrowableComputable<MapIndexStorage<K, V>, IOException>() {
- @Override
- public MapIndexStorage<K, V> compute() throws IOException {
- return new MapIndexStorage<K, V>(storageFile, myKeyDescriptor, myValueExternalizer, 1024);
- }
- },
- new Runnable() {
- @Override
- public void run() {
- IOUtil.deleteAllFilesStartingWith(storageFile);
- rewriteIndex.set(true);
- }
- }
- );
- index = new MapReduceIndex<K, V, ClassNode>(indexId, getIndexer(), indexStorage);
- index.setInputIdToDataKeysIndex(new Factory<PersistentHashMap<Integer, Collection<K>>>() {
- @Override
- public PersistentHashMap<Integer, Collection<K>> create() {
- try {
- return IOUtil.openCleanOrResetBroken(
- new ThrowableComputable<PersistentHashMap<Integer, Collection<K>>, IOException>() {
- @Override
- public PersistentHashMap<Integer, Collection<K>> compute() throws IOException {
- return FileBasedIndexImpl.createIdToDataKeysIndex(indexId, myKeyDescriptor, new MemoryIndexStorage<K, V>(indexStorage));
- }
- },
- new Runnable() {
- @Override
- public void run() {
- FileUtil.delete(getInputIndexStorageFile(getIndexId()));
- rewriteIndex.set(true);
- }
- }
- );
- }
- catch (IOException e) {
- throw new RuntimeException("couldn't create index", e);
- }
- }
- });
- final File versionFile = getVersionFile(indexId);
- if (versionFile.exists()) {
- if (versionDiffers(versionFile, getVersion())) {
- rewriteVersion(versionFile, getVersion());
- rewriteIndex.set(true);
- try {
- LOG.info("clearing index for updating index version");
- index.clear();
- }
- catch (StorageException e) {
- LOG.error("couldn't clear index for reinitializing", e);
- throw new RuntimeException(e);
- }
- }
- }
- else if (versionFile.createNewFile()) {
- rewriteVersion(versionFile, getVersion());
- rewriteIndex.set(true);
- }
- else {
- LOG.error(String.format("problems while access to index version file to index %s ", indexId));
- }
- }
- catch (IOException e) {
- LOG.error("couldn't initialize index", e);
- throw new RuntimeException(e);
- }
- myIndex = index;
- return rewriteIndex.get();
- }
- else {
- return false;
- }
- }
-
- protected abstract ID<K, V> getIndexId();
-
- protected abstract int getVersion();
-
- protected abstract DataIndexer<K, V, ClassNode> getIndexer();
-
- public final void closeIfInitialized() {
- if (myInitialized.get()) {
- if (myIndex != null) {
- try {
- myIndex.flush();
- }
- catch (StorageException ignored) {
- }
- myIndex.dispose();
- }
- }
- }
-
- public final void update(final int id, final ClassNode inputData) {
- final Boolean result = myIndex.update(id, inputData).compute();
- if (result == Boolean.FALSE) throw new RuntimeException();
- }
-
- public final void clearIfInitialized() {
- if (myInitialized.get()) {
- try {
- myIndex.clear();
- }
- catch (StorageException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- protected final ID<K, V> generateIndexId(final String indexName) {
- return CompilerOutputIndexUtil.generateIndexId(indexName, myProject);
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java
deleted file mode 100644
index 7a8169f..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexFeature.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
-* Copyright 2000-2013 JetBrains s.r.o.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-package com.intellij.compilerOutputIndex.api.indexer;
-
-import com.intellij.compilerOutputIndex.impl.MethodsUsageIndex;
-import com.intellij.openapi.util.registry.Registry;
-import com.intellij.openapi.util.registry.RegistryValue;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Collection;
-import java.util.Collections;
-
-/**
- * @author Dmitry Batkovich
- */
-@SuppressWarnings("unchecked")
-public enum CompilerOutputIndexFeature {
- METHOD_CHAINS_COMPLETION("completion.enable.relevant.method.chain.suggestions", ContainerUtil
- .<Class<? extends CompilerOutputBaseIndex>>newArrayList(MethodsUsageIndex.class));
-
- @NotNull
- private final String myKey;
- @NotNull
- private final Collection<Class<? extends CompilerOutputBaseIndex>> myRequiredIndexes;
-
- CompilerOutputIndexFeature(@NotNull final String key,
- @NotNull final Collection<Class<? extends CompilerOutputBaseIndex>> requiredIndexes) {
- myKey = key;
- myRequiredIndexes = requiredIndexes;
- }
-
- CompilerOutputIndexFeature(@NotNull final String key, @NotNull final Class<? extends CompilerOutputBaseIndex> requiredIndex) {
- this(key, Collections.<Class<? extends CompilerOutputBaseIndex>>singleton(requiredIndex));
- }
-
- public RegistryValue getRegistryValue() {
- return Registry.get(myKey);
- }
-
- public boolean isEnabled() {
- return Registry.is(myKey);
- }
-
- public void enable() {
- getRegistryValue().setValue(true);
- }
-
- public void disable() {
- getRegistryValue().setValue(false);
- }
-
- @NotNull
- public Collection<Class<? extends CompilerOutputBaseIndex>> getRequiredIndexes() {
- return myRequiredIndexes;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java
deleted file mode 100644
index 3ca2551..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexUtil.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.intellij.compilerOutputIndex.api.indexer;
-
-import com.intellij.compilerOutputIndex.impl.MethodIncompleteSignature;
-import com.intellij.openapi.project.Project;
-import com.intellij.util.indexing.ID;
-
-/**
- * @author Dmitry Batkovich
- */
-public final class CompilerOutputIndexUtil {
- private CompilerOutputIndexUtil() {}
-
- public static <K, V> ID<K, V> generateIndexId(final String indexName, final Project project) {
- final String hash = Integer.toHexString(project.getBasePath().hashCode());
- return ID.create(String.format("compilerOutputIndex.%s.%s", indexName, hash));
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java
deleted file mode 100644
index fed4c02..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/api/indexer/CompilerOutputIndexer.java
+++ /dev/null
@@ -1,387 +0,0 @@
-package com.intellij.compilerOutputIndex.api.indexer;
-
-import com.intellij.compilerOutputIndex.api.fs.CompilerOutputFilesUtil;
-import com.intellij.compilerOutputIndex.api.fs.FileVisitorService;
-import com.intellij.openapi.compiler.CompilationStatusAdapter;
-import com.intellij.openapi.compiler.CompilerManager;
-import com.intellij.openapi.components.AbstractProjectComponent;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.progress.ProcessCanceledException;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.ThrowableComputable;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.registry.RegistryValue;
-import com.intellij.openapi.util.registry.RegistryValueListener;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.Consumer;
-import com.intellij.util.containers.ConcurrentHashSet;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.indexing.ID;
-import com.intellij.util.indexing.IndexInfrastructure;
-import com.intellij.util.io.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-import org.jetbrains.asm4.ClassReader;
-import org.jetbrains.asm4.Opcodes;
-import org.jetbrains.asm4.tree.ClassNode;
-
-import java.io.*;
-import java.util.*;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantLock;
-
-/**
- * @author Dmitry Batkovich
- */
-public class CompilerOutputIndexer extends AbstractProjectComponent {
- private final static Logger LOG = Logger.getInstance(CompilerOutputIndexer.class);
-
- public final static String TITLE = "Compiler output indexer in progress...";
-
- private final Map<String, CompilerOutputBaseIndex> myIndexTypeQNameToIndex = new HashMap<String, CompilerOutputBaseIndex>();
- private volatile PersistentHashMap<String, Long> myFileTimestampsIndex;
- private volatile PersistentEnumeratorDelegate<String> myFileEnumerator;
-
- private final Lock myLock = new ReentrantLock();
- private final AtomicBoolean myInProgress = new AtomicBoolean(false);
- @SuppressWarnings("SetReplaceableByEnumSet")
- private final Set<CompilerOutputIndexFeature> myCurrentEnabledFeatures = new ConcurrentHashSet<CompilerOutputIndexFeature>();
- private final AtomicBoolean myInitialized = new AtomicBoolean(false);
-
- public static CompilerOutputIndexer getInstance(final Project project) {
- return project.getComponent(CompilerOutputIndexer.class);
- }
-
- protected CompilerOutputIndexer(final Project project) {
- super(project);
- }
-
- private ID<String, Long> getFileTimestampsIndexId() {
- return CompilerOutputIndexUtil.generateIndexId("ProjectCompilerOutputClassFilesTimestamps", myProject);
- }
-
- @Override
- public final void projectOpened() {
- for (final CompilerOutputIndexFeature feature : CompilerOutputIndexFeature.values()) {
- final RegistryValue registryValue = feature.getRegistryValue();
- registryValue.addListener(new RegistryValueListener.Adapter() {
- @Override
- public void afterValueChanged(final RegistryValue rawValue) {
- final Collection<Class<? extends CompilerOutputBaseIndex>> requiredIndexes = feature.getRequiredIndexes();
- if (rawValue.asBoolean()) {
- if (myCurrentEnabledFeatures.add(feature)) {
- if (myCurrentEnabledFeatures.size() == 1) {
- doEnable();
- }
- addIndexes(requiredIndexes);
- }
- }
- else {
- removeIndexes(requiredIndexes);
- myCurrentEnabledFeatures.remove(feature);
- }
- }
- }, myProject);
- if (registryValue.asBoolean()) {
- if (myCurrentEnabledFeatures.add(feature)) {
- if (myCurrentEnabledFeatures.size() == 1) {
- doEnable();
- }
- addIndexes(feature.getRequiredIndexes());
- }
- }
- }
- }
-
- private CompilerOutputBaseIndex[] getAllIndexes() {
- return Extensions.getExtensions(CompilerOutputBaseIndex.EXTENSION_POINT_NAME, myProject);
- }
-
- private void addIndexes(final Collection<Class<? extends CompilerOutputBaseIndex>> indexes) {
- final Collection<CompilerOutputBaseIndex> indexesToReindex = new ArrayList<CompilerOutputBaseIndex>();
- for (final Class<? extends CompilerOutputBaseIndex> indexClass : indexes) {
- final String canonicalName = indexClass.getCanonicalName();
- if (!myIndexTypeQNameToIndex.containsKey(canonicalName)) {
- final CompilerOutputBaseIndex index = Extensions.findExtension(CompilerOutputBaseIndex.EXTENSION_POINT_NAME, myProject, indexClass);
- myIndexTypeQNameToIndex.put(canonicalName, index);
- if (index.initIfNeed()) {
- indexesToReindex.add(index);
- }
- }
- }
- if (!indexesToReindex.isEmpty()) {
- if (myInProgress.compareAndSet(false, true)) {
- ProgressManager.getInstance().run(new Task.Backgroundable(myProject, TITLE) {
- @Override
- public void onCancel() {
- myInProgress.set(false);
- }
-
- @Override
- public void onSuccess() {
- myInProgress.set(false);
- }
-
- @Override
- public void run(@NotNull final ProgressIndicator indicator) {
- reindex(new FileVisitorService.ProjectClassFiles(CompilerOutputIndexer.this.myProject), indexesToReindex, true, indicator);
- }
- });
- }
- }
- }
-
- private void removeIndexes(final Collection<Class<? extends CompilerOutputBaseIndex>> indexes) {
- final Set<Class<? extends CompilerOutputBaseIndex>> toRemove = ContainerUtil.newHashSet(indexes);
- for (final CompilerOutputIndexFeature feature : CompilerOutputIndexFeature.values()) {
- if (feature.getRegistryValue().asBoolean()) {
- for (final Class<? extends CompilerOutputBaseIndex> aClass : feature.getRequiredIndexes()) {
- toRemove.remove(aClass);
- }
- }
- }
- for (final Class aClass : toRemove) {
- myIndexTypeQNameToIndex.remove(aClass.getCanonicalName());
- }
- }
-
- private void doEnable() {
- if (myInitialized.compareAndSet(false, true)) {
- initTimestampIndex();
- final File storageFile =
- IndexInfrastructure.getStorageFile(CompilerOutputIndexUtil.generateIndexId("compilerOutputIndexFileId.enum", myProject));
-
- try {
- myFileEnumerator = IOUtil.openCleanOrResetBroken(new ThrowableComputable<PersistentEnumeratorDelegate<String>, IOException>() {
- @Override
- public PersistentEnumeratorDelegate<String> compute() throws IOException {
- return new PersistentEnumeratorDelegate<String>(storageFile, new EnumeratorStringDescriptor(), 2048);
- }
- }, storageFile);
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- CompilerManager.getInstance(myProject).addCompilationStatusListener(new CompilationStatusAdapter() {
- @Override
- public void fileGenerated(final String outputRoot, final String relativePath) {
- if (StringUtil.endsWith(relativePath, CompilerOutputFilesUtil.CLASS_FILES_SUFFIX) && !myCurrentEnabledFeatures.isEmpty()) {
- try {
- doIndexing(new File(outputRoot, relativePath), myIndexTypeQNameToIndex.values(), false, null);
- }
- catch (ProcessCanceledException e0) {
- throw e0;
- }
- catch (RuntimeException e) {
- LOG.error(e);
- }
- }
- }
- }, myProject);
- }
- }
-
- private void initTimestampIndex() {
- final File storageFile = IndexInfrastructure.getStorageFile(getFileTimestampsIndexId());
- try {
- myFileTimestampsIndex = IOUtil.openCleanOrResetBroken(
- new ThrowableComputable<PersistentHashMap<String, Long>, IOException>() {
- @Override
- public PersistentHashMap<String, Long> compute() throws IOException {
- return new PersistentHashMap<String, Long>(storageFile,
- new EnumeratorStringDescriptor(), new DataExternalizer<Long>() {
- @Override
- public void save(final DataOutput out, final Long value) throws IOException {
- out.writeLong(value);
- }
-
- @Override
- public Long read(final DataInput in) throws IOException {
- return in.readLong();
- }
- });
- }
- },
- new Runnable() {
- public void run() {
- FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
- }
- }
- );
- } catch (IOException ex) {
- throw new RuntimeException("Timestamps index not initialized", ex);
- }
- }
-
- public void reindex(final FileVisitorService visitorService, final @NotNull ProgressIndicator indicator) {
- reindex(visitorService, myIndexTypeQNameToIndex.values(), false, indicator);
- }
-
- private void reindex(final FileVisitorService visitorService,
- final @NotNull Collection<CompilerOutputBaseIndex> indexes,
- final boolean force,
- final @NotNull ProgressIndicator indicator) {
- myLock.lock();
- try {
- indicator.setText(TITLE);
- visitorService.visit(new Consumer<File>() {
- @Override
- public void consume(final File file) {
- try {
- doIndexing(file, indexes, force, indicator);
- }
- catch (ProcessCanceledException e0) {
- throw e0;
- }
- catch (RuntimeException e) {
- LOG.error(e);
- }
- }
- });
- }
- finally {
- myLock.unlock();
- }
- }
-
- @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
- private void doIndexing(@NotNull final File file,
- @NotNull final Collection<CompilerOutputBaseIndex> indexes,
- final boolean force,
- @Nullable final ProgressIndicator indicator) {
- final String filePath;
- try {
- filePath = file.getCanonicalPath();
- }
- catch (IOException e) {
- LOG.error(e);
- return;
- }
- final Long timestamp;
- ProgressManager.checkCanceled();
- final long currentTimeStamp = file.lastModified();
- if (force || (timestamp = getTimestamp(filePath)) == null || timestamp != currentTimeStamp) {
- putTimestamp(filePath, currentTimeStamp);
- final ClassNode inputData = new ClassNode(Opcodes.ASM4);
- InputStream is = null;
- try {
- is = new FileInputStream(file);
- final ClassReader reader = new ClassReader(is);
- reader.accept(inputData, ClassReader.EXPAND_FRAMES);
- }
- catch (IOException e) {
- removeTimestamp(filePath);
- return;
- }
- finally {
- if (is != null) {
- try {
- is.close();
- }
- catch (IOException ignored) {
- }
- }
- }
- try {
- if (indicator != null) {
- indicator.setText2(filePath);
- }
- final int id = myFileEnumerator.enumerate(filePath);
- for (final CompilerOutputBaseIndex index : indexes) {
- index.update(id, inputData);
- }
- }
- catch (RuntimeException e) {
- LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
- }
- catch (IOException e) {
- LOG.error(String.format("can't index file: %s", file.getAbsolutePath()), e);
- }
- }
- }
-
- public void clear() {
- try {
- myFileTimestampsIndex.close();
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- initTimestampIndex();
- for (final CompilerOutputBaseIndex index : getAllIndexes()) {
- index.clearIfInitialized();
- }
- }
-
- private void removeTimestamp(final String fileId) {
- try {
- myFileTimestampsIndex.remove(fileId);
- }
- catch (IOException e) {
- LOG.error(e);
- }
- }
-
- @Nullable
- private Long getTimestamp(final String fileName) {
- try {
- return myFileTimestampsIndex.get(fileName);
- }
- catch (IOException e) {
- LOG.error(e);
- return 0L;
- }
- }
-
- private void putTimestamp(final String fileName, final long timestamp) {
- try {
- myFileTimestampsIndex.put(fileName, timestamp);
- }
- catch (IOException e) {
- LOG.error(e);
- }
- }
-
-
- @Override
- public void projectClosed() {
- if (myInitialized.get()) {
- for (final CompilerOutputBaseIndex index : getAllIndexes()) {
- index.closeIfInitialized();
- }
- try {
- myFileTimestampsIndex.close();
- myFileEnumerator.close();
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
-
- @TestOnly
- public void removeIndexes() {
- for (final CompilerOutputBaseIndex index : getAllIndexes()) {
- FileUtil.delete(IndexInfrastructure.getIndexRootDir(index.getIndexId()));
- }
- FileUtil.delete(IndexInfrastructure.getIndexRootDir(getFileTimestampsIndexId()));
- }
-
- /**
- * try to find index with corresponding class only in currently enabled indexes
- */
- @SuppressWarnings("unchecked")
- public <T extends CompilerOutputBaseIndex> T getIndex(final Class<T> tClass) {
- final CompilerOutputBaseIndex index = myIndexTypeQNameToIndex.get(tClass.getCanonicalName());
- if (index == null) {
- throw new RuntimeException(String.format("index class with name %s not found", tClass.getName()));
- }
- return (T)index;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java
deleted file mode 100644
index fe36071..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/GuavaHashMultiSetExternalizer.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.compilerOutputIndex.impl;
-
-import com.google.common.collect.HashMultiset;
-import com.google.common.collect.Multiset;
-import com.intellij.util.io.DataExternalizer;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.Set;
-
-/**
- * @author Dmitry Batkovich
- */
-public class GuavaHashMultiSetExternalizer<K> implements DataExternalizer<Multiset<K>> {
- private final DataExternalizer<K> myKeyDataExternalizer;
-
- public GuavaHashMultiSetExternalizer(final DataExternalizer<K> keyDataExternalizer) {
- myKeyDataExternalizer = keyDataExternalizer;
- }
-
- @Override
- public void save(final DataOutput out, final Multiset<K> multiset) throws IOException {
- final Set<Multiset.Entry<K>> entries = multiset.entrySet();
- out.writeInt(entries.size());
- for (final Multiset.Entry<K> entry : entries) {
- myKeyDataExternalizer.save(out, entry.getElement());
- out.writeInt(entry.getCount());
- }
- }
-
- @Override
- public Multiset<K> read(final DataInput in) throws IOException {
- final int size = in.readInt();
- final Multiset<K> multiset = HashMultiset.create(size);
- for (int i = 0; i < size; i++) {
- multiset.add(myKeyDataExternalizer.read(in), in.readInt());
- }
- return multiset;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java
deleted file mode 100644
index c0904bc..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignature.java
+++ /dev/null
@@ -1,200 +0,0 @@
-package com.intellij.compilerOutputIndex.impl;
-
-import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.io.EnumeratorStringDescriptor;
-import com.intellij.util.io.KeyDescriptor;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class MethodIncompleteSignature {
-
- public static final String CONSTRUCTOR_METHOD_NAME = "<init>";
-
- @NotNull
- private final String myOwner;
- @NotNull
- private final String myReturnType;
- @NotNull
- private final String myName;
- private final boolean myStatic;
-
- public MethodIncompleteSignature(@NotNull final String owner,
- @NotNull final String returnType,
- @NotNull final String name,
- final boolean aStatic) {
- myOwner = owner;
- myReturnType = returnType;
- myName = name;
- myStatic = aStatic;
- }
-
- public static MethodIncompleteSignature constructor(@NotNull final String className) {
- return new MethodIncompleteSignature(className, className, CONSTRUCTOR_METHOD_NAME, true);
- }
-
- public MethodIncompleteSignature toExternalRepresentation() {
- return new MethodIncompleteSignature(AsmUtil.getQualifiedClassName(getOwner()),
- AsmUtil.getQualifiedClassName(getReturnType()),
- getName(),
- isStatic());
- }
-
- @NotNull
- public String getOwner() {
- return myOwner;
- }
-
- @NotNull
- public String getReturnType() {
- return myReturnType;
- }
-
- @NotNull
- public String getName() {
- return myName;
- }
-
- public boolean isStatic() {
- return myStatic;
- }
-
- @NotNull
- public PsiMethod[] resolveNotDeprecated(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
- return notDeprecated(resolve(javaPsiFacade, scope));
- }
-
- @NotNull
- public PsiMethod[] resolve(final JavaPsiFacade javaPsiFacade, final GlobalSearchScope scope) {
- if (CONSTRUCTOR_METHOD_NAME.equals(getName())) {
- return PsiMethod.EMPTY_ARRAY;
- }
- final PsiClass aClass = javaPsiFacade.findClass(getOwner(), scope);
- if (aClass == null) {
- return PsiMethod.EMPTY_ARRAY;
- }
- final PsiMethod[] methods = aClass.findMethodsByName(getName(), true);
- final List<PsiMethod> filtered = new ArrayList<PsiMethod>(methods.length);
- for (final PsiMethod method : methods) {
- if (method.hasModifierProperty(PsiModifier.STATIC) == isStatic()) {
- final PsiType returnType = method.getReturnType();
- if (returnType != null && returnType.equalsToText(getReturnType())) {
- filtered.add(method);
- }
- }
- }
- if (filtered.size() > 1) {
- Collections.sort(filtered, new Comparator<PsiMethod>() {
- @Override
- public int compare(final PsiMethod o1, final PsiMethod o2) {
- return o1.getParameterList().getParametersCount() - o2.getParameterList().getParametersCount();
- }
- });
- }
- return filtered.toArray(new PsiMethod[filtered.size()]);
- }
-
- public static KeyDescriptor<MethodIncompleteSignature> createKeyDescriptor() {
- final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
- return new KeyDescriptor<MethodIncompleteSignature>() {
- @Override
- public void save(final DataOutput out, final MethodIncompleteSignature value) throws IOException {
- stringDescriptor.save(out, value.getOwner());
- stringDescriptor.save(out, value.getReturnType());
- stringDescriptor.save(out, value.getName());
- out.writeBoolean(value.isStatic());
- }
-
- @Override
- public MethodIncompleteSignature read(final DataInput in) throws IOException {
- return new MethodIncompleteSignature(stringDescriptor.read(in), stringDescriptor.read(in), stringDescriptor.read(in),
- in.readBoolean());
- }
-
- @Override
- public int getHashCode(final MethodIncompleteSignature value) {
- return value.hashCode();
- }
-
- @Override
- public boolean isEqual(final MethodIncompleteSignature val1, final MethodIncompleteSignature val2) {
- return val1.equals(val2);
- }
- };
- }
-
- @NotNull
- private static PsiMethod[] notDeprecated(@NotNull final PsiMethod[] methods) {
- final List<PsiMethod> filtered = ContainerUtil.filter(methods, NOT_DEPRECATED_CONDITION);
- return filtered.toArray(new PsiMethod[filtered.size()]);
- }
-
- private final static Condition<PsiMethod> NOT_DEPRECATED_CONDITION = new Condition<PsiMethod>() {
- @Override
- public boolean value(final PsiMethod method) {
- return !method.isDeprecated();
- }
- };
-
- public final static Comparator<MethodIncompleteSignature> COMPARATOR = new Comparator<MethodIncompleteSignature>() {
- @Override
- public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) {
- int sub = o1.getOwner().compareTo(o2.getOwner());
- if (sub != 0) {
- return sub;
- }
- sub = o1.getName().compareTo(o2.getName());
- if (sub != 0) {
- return sub;
- }
- sub = o1.getReturnType().compareTo(o2.getReturnType());
- if (sub != 0) {
- return sub;
- }
- if (o1.isStatic() && !o2.isStatic()) {
- return 1;
- }
- if (o2.isStatic() && !o1.isStatic()) {
- return -1;
- }
- return 0;
- }
- };
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final MethodIncompleteSignature that = (MethodIncompleteSignature)o;
-
- if (myStatic != that.myStatic) return false;
- if (!myName.equals(that.myName)) return false;
- if (!myOwner.equals(that.myOwner)) return false;
- if (!myReturnType.equals(that.myReturnType)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = myOwner.hashCode();
- result = 31 * result + myReturnType.hashCode();
- result = 31 * result + myName.hashCode();
- result = 31 * result + (myStatic ? 1 : 0);
- return result;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java
deleted file mode 100644
index a11e731..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodIncompleteSignatureChain.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.intellij.compilerOutputIndex.impl;
-
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class MethodIncompleteSignatureChain {
- private final List<MethodIncompleteSignature> myMethodIncompleteSignatures;
-
- public MethodIncompleteSignatureChain(final List<MethodIncompleteSignature> methodIncompleteSignatures) {
- myMethodIncompleteSignatures = methodIncompleteSignatures;
- }
-
- public List<MethodIncompleteSignature> list() {
- return myMethodIncompleteSignatures;
- }
-
- public boolean isEmpty() {
- return myMethodIncompleteSignatures.isEmpty();
- }
-
- @Nullable
- public MethodIncompleteSignature getFirstInvocation() {
- final int size = myMethodIncompleteSignatures.size();
- return size == 0 ? null : myMethodIncompleteSignatures.get(0);
- }
-
- @Nullable
- public MethodIncompleteSignature getLastInvocation() {
- final int size = myMethodIncompleteSignatures.size();
- return size == 0 ? null : myMethodIncompleteSignatures.get(size -1);
- }
-
- public int size() {
- return myMethodIncompleteSignatures.size();
- }
-
- public MethodIncompleteSignature get(final int index) {
- return myMethodIncompleteSignatures.get(index);
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java
deleted file mode 100644
index 78a63bd..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/MethodsUsageIndex.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package com.intellij.compilerOutputIndex.impl;
-
-import com.google.common.collect.HashMultiset;
-import com.google.common.collect.Multiset;
-import com.intellij.compilerOutputIndex.api.fs.AsmUtil;
-import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex;
-import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ModifiableRootModel;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.ModuleRootModel;
-import com.intellij.psi.*;
-import com.intellij.util.indexing.DataIndexer;
-import com.intellij.util.indexing.ID;
-import com.intellij.util.indexing.StorageException;
-import com.intellij.util.indexing.ValueContainer;
-import com.intellij.util.io.DataExternalizer;
-import com.intellij.util.io.EnumeratorStringDescriptor;
-import com.intellij.util.io.KeyDescriptor;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.asm4.ClassVisitor;
-import org.jetbrains.asm4.MethodVisitor;
-import org.jetbrains.asm4.Opcodes;
-import org.jetbrains.asm4.Type;
-import org.jetbrains.asm4.tree.ClassNode;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.TreeSet;
-
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class MethodsUsageIndex extends CompilerOutputBaseIndex<String, Multiset<MethodIncompleteSignature>> {
-
- public static MethodsUsageIndex getInstance(final Project project) {
- return CompilerOutputIndexer.getInstance(project).getIndex(MethodsUsageIndex.class);
- }
-
- public MethodsUsageIndex(final Project project) {
- super(new EnumeratorStringDescriptor(),
- new GuavaHashMultiSetExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createKeyDescriptor()), project);
- }
-
- @Override
- protected DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassNode> getIndexer() {
- return new DataIndexer<String, Multiset<MethodIncompleteSignature>, ClassNode>() {
- @NotNull
- @Override
- public Map<String, Multiset<MethodIncompleteSignature>> map(final ClassNode inputData) {
- final Map<String, Multiset<MethodIncompleteSignature>> map = new HashMap<String, Multiset<MethodIncompleteSignature>>();
- final MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM4) {
- @Override
- public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
- final Type returnType = Type.getReturnType(desc);
- if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name) ||
- AsmUtil.isPrimitiveOrArray(returnType.getDescriptor())) {
- return;
- }
- final String returnClassName = returnType.getInternalName();
- final boolean isStatic = opcode == Opcodes.INVOKESTATIC;
- if (!owner.equals(returnClassName) || isStatic) {
- addToIndex(map, returnClassName, new MethodIncompleteSignature(owner, returnClassName, name, isStatic));
- }
- }
- };
- inputData.accept(new ClassVisitor(Opcodes.ASM4) {
- @Override
- public MethodVisitor visitMethod(final int access,
- final String name,
- final String desc,
- final String signature,
- final String[] exceptions) {
- return methodVisitor;
- }
- });
- return map;
- }
- };
- }
-
- @Override
- protected ID<String, Multiset<MethodIncompleteSignature>> getIndexId() {
- return generateIndexId("MethodsUsage");
- }
-
- @Override
- protected int getVersion() {
- return 1;
- }
-
- public TreeSet<UsageIndexValue> getValues(final String key) {
- try {
- final ValueContainer<Multiset<MethodIncompleteSignature>> valueContainer = myIndex.getData(key);
- final Multiset<MethodIncompleteSignature> rawValues = HashMultiset.create();
- valueContainer.forEach(new ValueContainer.ContainerAction<Multiset<MethodIncompleteSignature>>() {
- @Override
- public boolean perform(final int id, final Multiset<MethodIncompleteSignature> values) {
- for (final Multiset.Entry<MethodIncompleteSignature> entry : values.entrySet()) {
- rawValues.add(entry.getElement(), entry.getCount());
- }
- return true;
- }
- });
- return rawValuesToValues(rawValues);
- }
- catch (final StorageException e) {
- throw new RuntimeException();
- }
- }
-
- private static void addToIndex(final Map<String, Multiset<MethodIncompleteSignature>> map,
- final String internalClassName,
- final MethodIncompleteSignature mi) {
- final String className = AsmUtil.getQualifiedClassName(internalClassName);
- Multiset<MethodIncompleteSignature> occurrences = map.get(className);
- if (occurrences == null) {
- occurrences = HashMultiset.create();
- map.put(className, occurrences);
- }
- occurrences.add(mi);
- }
-
- private static TreeSet<UsageIndexValue> rawValuesToValues(final Multiset<MethodIncompleteSignature> rawValues) {
- final TreeSet<UsageIndexValue> values = new TreeSet<UsageIndexValue>();
- for (final Multiset.Entry<MethodIncompleteSignature> entry : rawValues.entrySet()) {
- values.add(new UsageIndexValue(entry.getElement().toExternalRepresentation(), entry.getCount()));
- }
- return values;
- }
-}
diff --git a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java b/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java
deleted file mode 100644
index f99a0de..0000000
--- a/java/java-impl/src/com/intellij/compilerOutputIndex/impl/UsageIndexValue.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.intellij.compilerOutputIndex.impl;
-
-import com.intellij.util.io.DataExternalizer;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.IOException;
-
-/**
- * @author Dmitry Batkovich
- */
-public class UsageIndexValue implements Comparable<UsageIndexValue> {
- private final int myOccurrences;
- private final MethodIncompleteSignature myMethodIncompleteSignature;
-
- public UsageIndexValue(final MethodIncompleteSignature signature, final int occurrences) {
- myOccurrences = occurrences;
- myMethodIncompleteSignature = signature;
- }
-
- public int getOccurrences() {
- return myOccurrences;
- }
-
- public MethodIncompleteSignature getMethodIncompleteSignature() {
- return myMethodIncompleteSignature;
- }
-
- public static DataExternalizer<UsageIndexValue> createDataExternalizer() {
- final DataExternalizer<MethodIncompleteSignature> methodInvocationDataExternalizer = MethodIncompleteSignature.createKeyDescriptor();
- return new DataExternalizer<UsageIndexValue>() {
- @Override
- public void save(final DataOutput out, final UsageIndexValue value) throws IOException {
- methodInvocationDataExternalizer.save(out, value.myMethodIncompleteSignature);
- out.writeInt(value.myOccurrences);
- }
-
- @Override
- public UsageIndexValue read(final DataInput in) throws IOException {
- return new UsageIndexValue(methodInvocationDataExternalizer.read(in), in.readInt());
- }
- };
- }
-
- @Override
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final UsageIndexValue that = (UsageIndexValue)o;
-
- return myOccurrences == that.myOccurrences && myMethodIncompleteSignature.equals(that.myMethodIncompleteSignature);
- }
-
- @Override
- public int hashCode() {
- int result = myOccurrences;
- result = 31 * result + myMethodIncompleteSignature.hashCode();
- return result;
- }
-
- @Override
- public int compareTo(@NotNull final UsageIndexValue that) {
- final int sub = -myOccurrences + that.myOccurrences;
- if (sub != 0) return sub;
- return MethodIncompleteSignature.COMPARATOR.compare(myMethodIncompleteSignature, that.myMethodIncompleteSignature);
- }
-}
diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaClassFindUsagesOptions.java b/java/java-impl/src/com/intellij/find/findUsages/JavaClassFindUsagesOptions.java
index 076f700..8a509ab 100644
--- a/java/java-impl/src/com/intellij/find/findUsages/JavaClassFindUsagesOptions.java
+++ b/java/java-impl/src/com/intellij/find/findUsages/JavaClassFindUsagesOptions.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.findUsages;
import com.intellij.find.FindBundle;
@@ -23,7 +38,7 @@
}
@Override
- protected void addUsageTypes(LinkedHashSet<String> strings) {
+ protected void addUsageTypes(@NotNull LinkedHashSet<String> strings) {
if (isUsages || isMethodsUsages || isFieldsUsages) {
strings.add(FindBundle.message("find.usages.panel.title.usages"));
}
diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java
index 577201a..ce04618 100644
--- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.java
+++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandler.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,7 +25,6 @@
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
@@ -106,7 +105,7 @@
FindBundle.message("find.parameter.usages.in.overriding.methods.prompt", parameter.getName()),
FindBundle.message("find.parameter.usages.in.overriding.methods.title"),
CommonBundle.getYesButtonText(), CommonBundle.getNoButtonText(),
- Messages.getQuestionIcon()) == 0;
+ Messages.getQuestionIcon()) == Messages.OK;
}
@NotNull
@@ -125,7 +124,7 @@
elementsToSearch.add(parameters[idx]);
}
}
- return elementsToSearch.toArray(new PsiElement[elementsToSearch.size()]);
+ return PsiUtilCore.toPsiElementArray(elementsToSearch);
}
@@ -184,7 +183,7 @@
FindBundle.message("find.field.accessors.title"),
CommonBundle.getYesButtonText(),
CommonBundle.getNoButtonText(), Messages.getQuestionIcon()) ==
- DialogWrapper.OK_EXIT_CODE;
+ Messages.OK;
if (doSearch) {
final Set<PsiElement> elements = new THashSet<PsiElement>();
for (PsiMethod accessor : accessors) {
diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandlerFactory.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandlerFactory.java
index 82cd4a8..2842b83 100644
--- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandlerFactory.java
+++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesHandlerFactory.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.
@@ -71,22 +71,27 @@
return new JavaFindUsagesHandler(element, this);
}
+ @NotNull
public JavaClassFindUsagesOptions getFindClassOptions() {
return myFindClassOptions;
}
+ @NotNull
public JavaMethodFindUsagesOptions getFindMethodOptions() {
return myFindMethodOptions;
}
+ @NotNull
public JavaPackageFindUsagesOptions getFindPackageOptions() {
return myFindPackageOptions;
}
+ @NotNull
public JavaThrowFindUsagesOptions getFindThrowOptions() {
return myFindThrowOptions;
}
+ @NotNull
public JavaVariableFindUsagesOptions getFindVariableOptions() {
return myFindVariableOptions;
}
diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesOptions.java b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesOptions.java
index 7aa9130..2d28a8d 100644
--- a/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesOptions.java
+++ b/java/java-impl/src/com/intellij/find/findUsages/JavaFindUsagesOptions.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.findUsages;
import com.intellij.find.FindBundle;
@@ -33,21 +48,22 @@
return result;
}
- protected void addUsageTypes(LinkedHashSet<String> to) {
- if (this.isUsages) {
+ protected void addUsageTypes(@NotNull LinkedHashSet<String> to) {
+ if (isUsages) {
to.add(FindBundle.message("find.usages.panel.title.usages"));
}
}
+ @NotNull
@Override
public final String generateUsagesString() {
- String suffix = " " + FindBundle.message("find.usages.panel.title.separator") + " ";
+ String separator = " " + FindBundle.message("find.usages.panel.title.separator") + " ";
LinkedHashSet<String> strings = new LinkedHashSet<String>();
addUsageTypes(strings);
if (strings.isEmpty()) {
strings.add(FindBundle.message("find.usages.panel.title.usages"));
}
- return StringUtil.join(strings, suffix);
+ return StringUtil.join(strings, separator);
}
diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaMethodFindUsagesOptions.java b/java/java-impl/src/com/intellij/find/findUsages/JavaMethodFindUsagesOptions.java
index 6efafe1..575ea88 100644
--- a/java/java-impl/src/com/intellij/find/findUsages/JavaMethodFindUsagesOptions.java
+++ b/java/java-impl/src/com/intellij/find/findUsages/JavaMethodFindUsagesOptions.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.findUsages;
import com.intellij.find.FindBundle;
@@ -48,15 +63,15 @@
}
@Override
- protected void addUsageTypes(LinkedHashSet<String> strings) {
+ protected void addUsageTypes(@NotNull LinkedHashSet<String> strings) {
super.addUsageTypes(strings);
- if (this.isIncludeOverloadUsages) {
+ if (isIncludeOverloadUsages) {
strings.add(FindBundle.message("find.usages.panel.title.overloaded.methods.usages"));
}
- if (this.isImplementingMethods) {
+ if (isImplementingMethods) {
strings.add(FindBundle.message("find.usages.panel.title.implementing.methods"));
}
- if (this.isOverridingMethods) {
+ if (isOverridingMethods) {
strings.add(FindBundle.message("find.usages.panel.title.overriding.methods"));
}
diff --git a/java/java-impl/src/com/intellij/find/findUsages/JavaPackageFindUsagesOptions.java b/java/java-impl/src/com/intellij/find/findUsages/JavaPackageFindUsagesOptions.java
index 9cd867d..415e06b 100644
--- a/java/java-impl/src/com/intellij/find/findUsages/JavaPackageFindUsagesOptions.java
+++ b/java/java-impl/src/com/intellij/find/findUsages/JavaPackageFindUsagesOptions.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.findUsages;
import com.intellij.find.FindBundle;
@@ -19,7 +34,7 @@
}
@Override
- protected void addUsageTypes(LinkedHashSet<String> to) {
+ protected void addUsageTypes(@NotNull LinkedHashSet<String> to) {
if (this.isUsages || this.isClassesUsages) {
to.add(FindBundle.message("find.usages.panel.title.usages"));
}
diff --git a/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java b/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java
index 06b1828..f56df64 100644
--- a/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.java
+++ b/java/java-impl/src/com/intellij/ide/JavaFilePasteProvider.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,9 +15,10 @@
*/
package com.intellij.ide;
-import com.intellij.lang.StdLanguages;
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.DataKeys;
+import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
@@ -33,15 +34,14 @@
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
/**
* @author yole
*/
public class JavaFilePasteProvider implements PasteProvider {
public void performPaste(@NotNull final DataContext dataContext) {
- final Project project = DataKeys.PROJECT.getData(dataContext);
- final IdeView ideView = DataKeys.IDE_VIEW.getData(dataContext);
+ final Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ final IdeView ideView = LangDataKeys.IDE_VIEW.getData(dataContext);
if (project == null || ideView == null) return;
final PsiJavaFile javaFile = createJavaFileFromClipboardContent(project);
if (javaFile == null) return;
@@ -59,7 +59,7 @@
final PsiClass mainClass = publicClass;
new WriteCommandAction(project, "Paste class '" + mainClass.getName() + "'") {
@Override
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
PsiFile file;
try {
file = targetDir.createFile(mainClass.getName() + ".java");
@@ -68,8 +68,10 @@
return;
}
final Document document = PsiDocumentManager.getInstance(project).getDocument(file);
- document.setText(javaFile.getText());
- PsiDocumentManager.getInstance(project).commitDocument(document);
+ if (document != null) {
+ document.setText(javaFile.getText());
+ PsiDocumentManager.getInstance(project).commitDocument(document);
+ }
if (file instanceof PsiJavaFile) {
updatePackageStatement((PsiJavaFile) file, targetDir);
}
@@ -113,8 +115,8 @@
}
public boolean isPasteEnabled(@NotNull final DataContext dataContext) {
- final Project project = DataKeys.PROJECT.getData(dataContext);
- final IdeView ideView = DataKeys.IDE_VIEW.getData(dataContext);
+ final Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ final IdeView ideView = LangDataKeys.IDE_VIEW.getData(dataContext);
if (project == null || ideView == null || ideView.getDirectories().length == 0) {
return false;
}
@@ -124,20 +126,7 @@
@Nullable
private static PsiJavaFile createJavaFileFromClipboardContent(final Project project) {
- PsiJavaFile file = null;
- Transferable content = CopyPasteManager.getInstance().getContents();
- if (content != null) {
- String text = null;
- try {
- text = (String)content.getTransferData(DataFlavor.stringFlavor);
- }
- catch (Exception e) {
- // ignore;
- }
- if (text != null) {
- file = (PsiJavaFile) PsiFileFactory.getInstance(project).createFileFromText("A.java", StdLanguages.JAVA, text);
- }
- }
- return file;
+ String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
+ return text != null ? (PsiJavaFile)PsiFileFactory.getInstance(project).createFileFromText("A.java", JavaLanguage.INSTANCE, text) : null;
}
}
diff --git a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java
index b9ef355..2f68430 100644
--- a/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.java
+++ b/java/java-impl/src/com/intellij/ide/JavaLanguageCodeStyleSettingsProvider.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,10 +24,7 @@
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
-import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable;
-import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
-import com.intellij.psi.codeStyle.DisplayPriority;
-import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider;
+import com.intellij.psi.codeStyle.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.PlatformUtils;
@@ -61,6 +58,17 @@
@Override
public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) {
consumer.showAllStandardOptions();
+ if (settingsType == SettingsType.SPACING_SETTINGS) {
+ consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACES_WITHIN_ANGLE_BRACKETS", "Angle brackets",CodeStyleSettingsCustomizable.SPACES_WITHIN);
+
+ String groupName = CodeStyleSettingsCustomizable.SPACES_IN_TYPE_ARGUMENTS;
+ consumer.moveStandardOption("SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS", groupName);
+ consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT", "After closing angle bracket", groupName);
+
+ groupName = CodeStyleSettingsCustomizable.SPACES_IN_TYPE_PARAMETERS;
+ consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER", "Before opening angle bracket", groupName);
+ consumer.showCustomOption(JavaCodeStyleSettings.class, "SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS", "Around type bounds", groupName);
+ }
}
@Override
@@ -74,7 +82,7 @@
@Override
public DisplayPriority getDisplayPriority() {
- if (PlatformUtils.isIdea()) return DisplayPriority.KEY_LANGUAGE_SETTINGS;
+ if (PlatformUtils.isIdeaUltimate()) return DisplayPriority.KEY_LANGUAGE_SETTINGS;
return DisplayPriority.LANGUAGE_SETTINGS;
}
@@ -180,12 +188,12 @@
private static final String SPACING_SAMPLE =
"@Annotation(param1 = \"value1\", param2 = \"value2\")\n" +
"@SuppressWarnings({\"ALL\"})\n" +
- "public class Foo<T, U> {\n" +
+ "public class Foo<T extends Bar & Abba, U> {\n" +
" int[] X = new int[]{1, 3, 5, 6, 7, 87, 1213, 2};\n" +
"\n" +
" public void foo(int x, int y) {" +
" Runnable r = () -> {};\n" +
- " Runnable r1 = this :: bar;\n" +
+ " Runnable r1 = this :: bar;\n" +
" for (int i = 0; i < x; i++) {\n" +
" y += (y ^ 0x123) << 2;\n" +
" }\n" +
@@ -209,13 +217,20 @@
" finally {\n" +
" int[] arr = (int[])g(y);\n" +
" x = y >= 0 ? arr[y] : -1;\n" +
+ " Map<String, String> sMap = new HashMap<String, String>();\n" +
+ " Bar.<String, Integer>mess(null);\n" +
" }\n" +
" }\n" +
" while (true);\n" +
" }\n" +
" void bar(){{return;}}\n" +
"}\n" +
- "class Bar {}";
+ "class Bar {\n" +
+ " static <U, T> U mess(T t) {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}\n" +
+ "interface Abba {}";
private static final String WRAPPING_CODE_SAMPLE =
"/*\n" +
diff --git a/java/java-impl/src/com/intellij/ide/hierarchy/type/JavaTypeHierarchyProvider.java b/java/java-impl/src/com/intellij/ide/hierarchy/type/JavaTypeHierarchyProvider.java
index 896edaf..ecde45d 100644
--- a/java/java-impl/src/com/intellij/ide/hierarchy/type/JavaTypeHierarchyProvider.java
+++ b/java/java-impl/src/com/intellij/ide/hierarchy/type/JavaTypeHierarchyProvider.java
@@ -21,8 +21,7 @@
import com.intellij.ide.hierarchy.TypeHierarchyBrowserBase;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
@@ -32,11 +31,15 @@
* @author yole
*/
public class JavaTypeHierarchyProvider implements HierarchyProvider {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.ide.hierarchy.type.JavaTypeHierarchyProvider");
public PsiElement getTarget(@NotNull final DataContext dataContext) {
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project == null) return null;
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("editor " + editor);
+ }
if (editor != null) {
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (file == null) return null;
@@ -44,6 +47,9 @@
final PsiElement targetElement = TargetElementUtilBase.findTargetElement(editor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED |
TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED |
TargetElementUtilBase.LOOKUP_ITEM_ACCEPTED);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("target element " + targetElement);
+ }
if (targetElement instanceof PsiClass) {
return targetElement;
}
@@ -51,6 +57,9 @@
final int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
while (element != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("context element " + element);
+ }
if (element instanceof PsiFile) {
if (!(element instanceof PsiClassOwner)) return null;
final PsiClass[] classes = ((PsiClassOwner)element).getClasses();
diff --git a/java/java-impl/src/com/intellij/ide/projectView/actions/MarkGeneratedSourceRootAction.java b/java/java-impl/src/com/intellij/ide/projectView/actions/MarkGeneratedSourceRootAction.java
index 2106f17..59d36b8 100644
--- a/java/java-impl/src/com/intellij/ide/projectView/actions/MarkGeneratedSourceRootAction.java
+++ b/java/java-impl/src/com/intellij/ide/projectView/actions/MarkGeneratedSourceRootAction.java
@@ -42,7 +42,7 @@
@Override
protected boolean isEnabled(@NotNull RootsSelection selection, @NotNull Module module) {
- if (!(ModuleType.get(module) instanceof JavaModuleType)) return false;
+ if (!isJavaModule(module)) return false;
if (selection.myHaveSelectedFilesUnderSourceRoots) {
return false;
@@ -61,6 +61,12 @@
return false;
}
+ private static boolean isJavaModule(Module module) {
+ ModuleType moduleType = ModuleType.get(module);
+ //this additional check can be removed when we get rid of PluginModuleType
+ return moduleType instanceof JavaModuleType || moduleType != null && "PLUGIN_MODULE".equals(moduleType.getId());
+ }
+
@Override
protected void modifyRoots(VirtualFile vFile, ContentEntry entry) {
JavaSourceRootProperties properties = JpsJavaExtensionService.getInstance().createSourceRootProperties("", true);
diff --git a/java/java-impl/src/com/intellij/ide/util/PackageUtil.java b/java/java-impl/src/com/intellij/ide/util/PackageUtil.java
index 59f09f5..239fbb6 100644
--- a/java/java-impl/src/com/intellij/ide/util/PackageUtil.java
+++ b/java/java-impl/src/com/intellij/ide/util/PackageUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -135,7 +135,7 @@
IdeBundle.message("prompt.create.non.existing.package", packageName),
IdeBundle.message("title.package.not.found"),
Messages.getQuestionIcon());
- if (toCreate != 0) {
+ if (toCreate != Messages.YES) {
return null;
}
askedToCreate = true;
@@ -238,7 +238,7 @@
IdeBundle.message("prompt.create.non.existing.package", packageName),
IdeBundle.message("title.package.not.found"),
Messages.getQuestionIcon());
- if (toCreate != 0) {
+ if (toCreate != Messages.YES) {
return null;
}
}
diff --git a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java
index efb05d7..5e3a2d1 100644
--- a/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java
+++ b/java/java-impl/src/com/intellij/ide/util/SuperMethodWarningUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -157,6 +157,7 @@
}).createPopup().showInBestPositionFor(editor);
}
+ @Messages.YesNoCancelResult
public static int askWhetherShouldAnnotateBaseMethod(@NotNull PsiMethod method, @NotNull PsiMethod superMethod) {
String implement = !method.hasModifierProperty(PsiModifier.ABSTRACT) && superMethod.hasModifierProperty(PsiModifier.ABSTRACT)
? InspectionsBundle.message("inspection.annotate.quickfix.implements")
diff --git a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
index 23aa77a..b0cbc06 100644
--- a/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
+++ b/java/java-impl/src/com/intellij/ide/util/gotoByName/DefaultClassNavigationContributor.java
@@ -90,7 +90,7 @@
final boolean isAnnotation = parameters.getLocalPatternName().startsWith("@");
@Override
public boolean process(PsiClass aClass) {
- if (aClass.getContainingFile().getVirtualFile() == null) return true;
+ if (aClass.getContainingFile().getVirtualFile() == null || !aClass.isPhysical()) return true;
if (isAnnotation && !aClass.isAnnotationType()) return true;
return processor.process(aClass);
}
diff --git a/java/java-impl/src/com/intellij/javadoc/JavadocBundle.java b/java/java-impl/src/com/intellij/javadoc/JavadocBundle.java
index b59c698..f231bd8 100644
--- a/java/java-impl/src/com/intellij/javadoc/JavadocBundle.java
+++ b/java/java-impl/src/com/intellij/javadoc/JavadocBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author yole
*/
public class JavadocBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.JavadocBundle";
private JavadocBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java
index 4190b85..6a267f6 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java
@@ -549,7 +549,7 @@
createElementLink(sb, element, StringUtil.escapeXml(str));
}
- return CodeInsightBundle.message("javadoc.candiates", text, sb);
+ return CodeInsightBundle.message("javadoc.candidates", text, sb);
}
return CodeInsightBundle.message("javadoc.candidates.not.found", text);
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java
index 2a69d6f..75acbeb 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaFindUsagesProvider.java
@@ -1,8 +1,5 @@
/*
-
-import com.intellij.lang.findUsages.FindUsagesProvider;
-
-* Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -70,7 +67,7 @@
if (ThrowSearchUtil.isSearchable(element)) {
return HelpID.FIND_THROW_USAGES;
}
- return HelpID.FIND_OTHER_USAGES;
+ return com.intellij.lang.HelpID.FIND_OTHER_USAGES;
}
@Override
diff --git a/java/java-impl/src/com/intellij/lang/java/JavaFormattingModelBuilder.java b/java/java-impl/src/com/intellij/lang/java/JavaFormattingModelBuilder.java
index 0dab38a..2f53bde 100644
--- a/java/java-impl/src/com/intellij/lang/java/JavaFormattingModelBuilder.java
+++ b/java/java-impl/src/com/intellij/lang/java/JavaFormattingModelBuilder.java
@@ -31,6 +31,7 @@
import com.intellij.psi.TokenType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.formatter.FormattingDocumentModelImpl;
import com.intellij.psi.formatter.java.AbstractJavaBlock;
@@ -51,8 +52,9 @@
public FormattingModel createModel(final PsiElement element, final CodeStyleSettings settings) {
final FileElement fileElement = TreeUtil.getFileElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(element));
LOG.assertTrue(fileElement != null, "File element should not be null for " + element);
- CommonCodeStyleSettings javaSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
- Block block = AbstractJavaBlock.createJavaBlock(fileElement, javaSettings);
+ CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JavaLanguage.INSTANCE);
+ JavaCodeStyleSettings customJavaSettings = settings.getCustomSettings(JavaCodeStyleSettings.class);
+ Block block = AbstractJavaBlock.createJavaBlock(fileElement, commonSettings, customJavaSettings);
FormattingDocumentModelImpl model = FormattingDocumentModelImpl.createOn(element.getContainingFile());
return new PsiBasedFormatterModelWithShiftIndentInside (element.getContainingFile(), block, model);
}
diff --git a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
index ade31f9..4de05e2 100644
--- a/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
+++ b/java/java-impl/src/com/intellij/openapi/module/JavaModuleType.java
@@ -21,19 +21,16 @@
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkTypeId;
import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.JavaPsiFacade;
-import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
import javax.swing.*;
-import java.util.ArrayList;
public class JavaModuleType extends ModuleType<JavaModuleBuilder> {
@@ -81,22 +78,6 @@
return getJavaModuleNodeIconClosed();
}
- @NotNull
- @Override
- public ModuleWizardStep[] createWizardSteps(@NotNull final WizardContext wizardContext, @NotNull final JavaModuleBuilder moduleBuilder,
- @NotNull final ModulesProvider modulesProvider) {
- final ProjectWizardStepFactory wizardFactory = ProjectWizardStepFactory.getInstance();
- ArrayList<ModuleWizardStep> steps = new ArrayList<ModuleWizardStep>();
- if (!wizardContext.isNewWizard()) {
- final ModuleWizardStep supportForFrameworksStep = wizardFactory.createSupportForFrameworksStep(wizardContext, moduleBuilder, modulesProvider);
- if (supportForFrameworksStep != null) {
- steps.add(supportForFrameworksStep);
- }
- }
- final ModuleWizardStep[] wizardSteps = steps.toArray(new ModuleWizardStep[steps.size()]);
- return ArrayUtil.mergeArrays(wizardSteps, super.createWizardSteps(wizardContext, moduleBuilder, modulesProvider));
- }
-
@Nullable
@Override
public ModuleWizardStep modifySettingsStep(@NotNull SettingsStep settingsStep, @NotNull final ModuleBuilder moduleBuilder) {
diff --git a/java/java-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java b/java/java-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java
deleted file mode 100644
index cecab4e..0000000
--- a/java/java-impl/src/com/intellij/openapi/roots/JavaProjectRootsUtil.java
+++ /dev/null
@@ -1,72 +0,0 @@
-package com.intellij.openapi.roots;
-
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiCodeFragment;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
-import org.jetbrains.jps.model.java.JavaSourceRootProperties;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class JavaProjectRootsUtil {
- public static boolean isOutsideJavaSourceRoot(@Nullable PsiFile psiFile) {
- if (psiFile == null) return false;
- if (psiFile instanceof PsiCodeFragment) return false;
- final VirtualFile file = psiFile.getVirtualFile();
- if (file == null) return false;
- final ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(psiFile.getProject()).getFileIndex();
- return !projectFileIndex.isUnderSourceRootOfType(file, JavaModuleSourceRootTypes.SOURCES) && !projectFileIndex.isInLibrarySource(file)
- && !projectFileIndex.isInLibraryClasses(file);
- }
-
- /**
- * @return list of all java source roots in the project which can be suggested as a target directory for a class created by user
- */
- @NotNull
- public static List<VirtualFile> getSuitableDestinationSourceRoots(@NotNull Project project) {
- List<VirtualFile> roots = new ArrayList<VirtualFile>();
- for (Module module : ModuleManager.getInstance(project).getModules()) {
- for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
- for (SourceFolder sourceFolder : entry.getSourceFolders(JavaModuleSourceRootTypes.SOURCES)) {
- if (!isForGeneratedSources(sourceFolder)) {
- ContainerUtil.addIfNotNull(roots, sourceFolder.getFile());
- }
- }
- }
- }
- return roots;
- }
-
- private static boolean isForGeneratedSources(SourceFolder sourceFolder) {
- JavaSourceRootProperties properties = sourceFolder.getJpsElement().getProperties(JavaModuleSourceRootTypes.SOURCES);
- return properties != null && properties.isForGeneratedSources();
- }
-
- public static boolean isInGeneratedCode(@NotNull VirtualFile file, @NotNull Project project) {
- ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
- Module module = fileIndex.getModuleForFile(file);
- if (module == null) return false;
-
- VirtualFile sourceRoot = fileIndex.getSourceRootForFile(file);
- if (sourceRoot == null) return false;
-
- for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
- for (SourceFolder folder : entry.getSourceFolders()) {
- if (sourceRoot.equals(folder.getFile())) {
- return isForGeneratedSources(folder);
- }
- }
- }
- return false;
- }
-}
diff --git a/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java b/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java
index dd5252b..2d57299 100644
--- a/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/roots/impl/LanguageLevelProjectExtensionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -122,7 +122,7 @@
return;
}
final String _message = ProjectBundle.message("project.language.level.reload.prompt", myProject.getName());
- if (Messages.showYesNoDialog(myProject, _message, ProjectBundle.message("project.language.level.reload.title"), Messages.getQuestionIcon()) == 0) {
+ if (Messages.showYesNoDialog(myProject, _message, ProjectBundle.message("project.language.level.reload.title"), Messages.getQuestionIcon()) == Messages.YES) {
ProjectManager.getInstance().reloadProject(myProject);
}
myReloadProjectRequest = null;
diff --git a/java/java-impl/src/com/intellij/openapi/roots/libraries/LibrariesHelperImpl.java b/java/java-impl/src/com/intellij/openapi/roots/libraries/LibrariesHelperImpl.java
index ca84c57..6fa0e1e 100644
--- a/java/java-impl/src/com/intellij/openapi/roots/libraries/LibrariesHelperImpl.java
+++ b/java/java-impl/src/com/intellij/openapi/roots/libraries/LibrariesHelperImpl.java
@@ -57,7 +57,7 @@
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
if (file == null) continue;
if (!(file.getFileSystem() instanceof JarFileSystem) && !file.isDirectory()) {
- file = JarFileSystem.getInstance().findFileByPath(file.getPath() + JarFileSystem.JAR_SEPARATOR);
+ file = JarFileSystem.getInstance().getJarRootForLocalFile(file);
}
if (file == null) continue;
if (findInFile(file, new StringTokenizer(fqn, "."))) return true;
diff --git a/java/java-impl/src/com/intellij/openapi/vcs/contentAnnotation/VcsContentAnnotationExceptionFilter.java b/java/java-impl/src/com/intellij/openapi/vcs/contentAnnotation/VcsContentAnnotationExceptionFilter.java
index b52273b..a26ca36 100644
--- a/java/java-impl/src/com/intellij/openapi/vcs/contentAnnotation/VcsContentAnnotationExceptionFilter.java
+++ b/java/java-impl/src/com/intellij/openapi/vcs/contentAnnotation/VcsContentAnnotationExceptionFilter.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.vcs.contentAnnotation;
+import com.intellij.execution.filters.ExceptionInfoCache;
import com.intellij.execution.filters.ExceptionWorker;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.FilterMixin;
@@ -54,15 +55,15 @@
public class VcsContentAnnotationExceptionFilter implements Filter, FilterMixin {
private final Project myProject;
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.contentAnnotation.VcsContentAnnotationExceptionFilter");
- private final GlobalSearchScope myScope;
private final VcsContentAnnotationSettings mySettings;
- private Map<VirtualFile,VcsRevisionNumber> myRevNumbersCache;
+ private final Map<VirtualFile,VcsRevisionNumber> myRevNumbersCache;
+ private final ExceptionInfoCache myCache;
public VcsContentAnnotationExceptionFilter(@NotNull GlobalSearchScope scope) {
- myScope = scope;
myProject = scope.getProject();
mySettings = VcsContentAnnotationSettings.getInstance(myProject);
myRevNumbersCache = new HashMap<VirtualFile, VcsRevisionNumber>();
+ myCache = new ExceptionInfoCache(scope);
}
private static class MyAdditionalHighlight extends AdditionalHighlight {
@@ -75,10 +76,10 @@
EditorColorsScheme globalScheme = EditorColorsManager.getInstance().getGlobalScheme();
final TextAttributes changedColor = globalScheme.getAttributes(DiffColors.DIFF_MODIFIED);
if (source == null) {
- TextAttributes atts =
+ TextAttributes attrs =
globalScheme.getAttributes(CodeInsightColors.CLASS_NAME_ATTRIBUTES).clone();
- atts.setBackgroundColor(changedColor.getBackgroundColor());
- return atts;
+ attrs.setBackgroundColor(changedColor.getBackgroundColor());
+ return attrs;
}
TextAttributes clone = source.clone();
clone.setBackgroundColor(changedColor.getBackgroundColor());
@@ -103,7 +104,7 @@
for (int i = 0; i < copiedFragment.getLineCount(); i++) {
final int lineStartOffset = copiedFragment.getLineStartOffset(i);
final int lineEndOffset = copiedFragment.getLineEndOffset(i);
- final ExceptionWorker worker = new ExceptionWorker(myProject, myScope);
+ final ExceptionWorker worker = new ExceptionWorker(myCache);
final String[] lineText = new String[1];
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
@@ -216,7 +217,7 @@
}
}
- private Document getDocumentForFile(final ExceptionWorker worker) {
+ private static Document getDocumentForFile(final ExceptionWorker worker) {
return ApplicationManager.getApplication().runReadAction(new Computable<Document>() {
@Override
public Document compute() {
@@ -231,7 +232,9 @@
}
// line numbers
- private List<TextRange> findMethodRange(final ExceptionWorker worker, final Document document, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
+ private static List<TextRange> findMethodRange(final ExceptionWorker worker,
+ final Document document,
+ final Trinity<PsiClass, PsiFile, String> previousLineResult) {
return ApplicationManager.getApplication().runReadAction(new Computable<List<TextRange>>() {
@Override
public List<TextRange> compute() {
@@ -249,7 +252,7 @@
// null - check all
@Nullable
- private List<PsiMethod> selectMethod(final PsiMethod[] methods, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
+ private static List<PsiMethod> selectMethod(final PsiMethod[] methods, final Trinity<PsiClass, PsiFile, String> previousLineResult) {
if (previousLineResult == null || previousLineResult.getThird() == null) return null;
final List<PsiMethod> result = new SmartList<PsiMethod>();
@@ -270,7 +273,7 @@
return result;
}
- private List<TextRange> getTextRangeForMethod(final ExceptionWorker worker, Trinity<PsiClass, PsiFile, String> previousLineResult) {
+ private static List<TextRange> getTextRangeForMethod(final ExceptionWorker worker, Trinity<PsiClass, PsiFile, String> previousLineResult) {
String method = worker.getMethod();
PsiClass psiClass = worker.getPsiClass();
PsiMethod[] methods;
diff --git a/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java b/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java
deleted file mode 100644
index 6d1c807..0000000
--- a/java/java-impl/src/com/intellij/pom/java/impl/PomJavaAspectImpl.java
+++ /dev/null
@@ -1,55 +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.pom.java.impl;
-
-import com.intellij.lang.java.JavaLanguage;
-import com.intellij.openapi.roots.LanguageLevelProjectExtension;
-import com.intellij.pom.PomModel;
-import com.intellij.pom.PomModelAspect;
-import com.intellij.pom.event.PomModelEvent;
-import com.intellij.pom.java.LanguageLevel;
-import com.intellij.pom.java.PomJavaAspect;
-import com.intellij.pom.java.events.PomJavaAspectChangeSet;
-import com.intellij.pom.tree.TreeAspect;
-import com.intellij.pom.tree.events.TreeChangeEvent;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-
-import java.util.Collections;
-
-public class PomJavaAspectImpl extends PomJavaAspect {
- private final PsiManager myPsiManager;
- private final PomModel myPomModel;
-
- public PomJavaAspectImpl(PsiManager psiManager, TreeAspect treeAspect, PomModel pomModel) {
- myPsiManager = psiManager;
- myPomModel = pomModel;
- pomModel.registerAspect(PomJavaAspect.class, this, Collections.singleton((PomModelAspect)treeAspect));
- }
-
- public LanguageLevel getLanguageLevel() {
- return LanguageLevelProjectExtension.getInstance(myPsiManager.getProject()).getLanguageLevel();
- }
-
- public void update(PomModelEvent event) {
- final TreeChangeEvent changeSet = (TreeChangeEvent)event.getChangeSet(myPomModel.getModelAspect(TreeAspect.class));
- if(changeSet == null) return;
- final PsiFile containingFile = changeSet.getRootElement().getPsi().getContainingFile();
- if(!(containingFile.getLanguage() instanceof JavaLanguage)) return;
- final PomJavaAspectChangeSet set = new PomJavaAspectChangeSet(myPomModel);
- event.registerChangeSet(this, set);
- }
-}
diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java
new file mode 100644
index 0000000..7e117e3
--- /dev/null
+++ b/java/java-impl/src/com/intellij/psi/codeStyle/JavaCodeStyleSettings.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeStyle;
+
+public class JavaCodeStyleSettings extends CustomCodeStyleSettings {
+
+ public JavaCodeStyleSettings(CodeStyleSettings container) {
+ super("JavaCodeStyleSettings", container);
+ }
+
+ public boolean SPACES_WITHIN_ANGLE_BRACKETS = false;
+
+ //Type arguments
+ public boolean SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT = false;
+
+ //Type parameters
+ public boolean SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER = false;
+ public boolean SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS = true;
+
+}
diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
index 826ad21..f46b4d6 100644
--- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
+++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaArrangementVisitor.java
@@ -23,6 +23,8 @@
import com.intellij.psi.search.searches.SuperMethodsSearch;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.psi.util.PropertyUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
@@ -61,6 +63,8 @@
@NotNull private final MethodBodyProcessor myMethodBodyProcessor;
@Nullable private final Document myDocument;
+ @Nullable private Set<PsiField> classFields;
+
public JavaArrangementVisitor(@NotNull JavaArrangementParseInfo infoHolder,
@Nullable Document document,
@NotNull Collection<TextRange> ranges,
@@ -164,26 +168,35 @@
if (entry == null)
return;
- PsiExpression fieldInitializer = field.getInitializer();
- processEntry(entry, field, fieldInitializer);
+ processEntry(entry, field, field.getInitializer());
myInfo.onFieldEntryCreated(field, entry);
- if (fieldInitializer != null) {
- List<PsiField> referencedFields = getReferencedFields(fieldInitializer);
- for (PsiField referencedField : referencedFields) {
- myInfo.registerFieldInitializationDependency(field, referencedField);
- }
+ List<PsiField> referencedFields = getReferencedFields(field);
+ for (PsiField referencedField : referencedFields) {
+ myInfo.registerFieldInitializationDependency(field, referencedField);
}
}
@NotNull
- private List<PsiField> getReferencedFields(@NotNull PsiExpression expression) {
+ private List<PsiField> getReferencedFields(@NotNull PsiField field) {
final List<PsiField> referencedElements = new ArrayList<PsiField>();
- expression.accept(new JavaRecursiveElementVisitor() {
+
+ PsiExpression fieldInitializer = field.getInitializer();
+ PsiClass containingClass = field.getContainingClass();
+
+ if (fieldInitializer == null || containingClass == null) {
+ return referencedElements;
+ }
+
+ if (classFields == null) {
+ classFields = ContainerUtil.map2Set(containingClass.getFields(), new Function.Self<PsiField, PsiField>());
+ }
+
+ fieldInitializer.accept(new JavaRecursiveElementVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
PsiElement ref = expression.resolve();
- if (ref instanceof PsiField) {
+ if (ref instanceof PsiField && classFields.contains(ref)) {
referencedElements.add((PsiField)ref);
}
}
diff --git a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java
index cc35e7d..7e3f95a 100644
--- a/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java
+++ b/java/java-impl/src/com/intellij/psi/codeStyle/arrangement/JavaRearranger.java
@@ -101,6 +101,38 @@
GROUPING_RULES.put(DEPENDENT_METHODS, ContainerUtilRt.newArrayList(BREADTH_FIRST, DEPTH_FIRST));
}
+ private static final StdArrangementSettings DEFAULT_SETTINGS;
+
+ static {
+ List<ArrangementGroupingRule> groupingRules = ContainerUtilRt.newArrayList(new ArrangementGroupingRule(GETTERS_AND_SETTERS));
+ List<StdArrangementMatchRule> matchRules = ContainerUtilRt.newArrayList();
+ ArrangementSettingsToken[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE};
+ for (ArrangementSettingsToken modifier : visibility) {
+ and(matchRules, FIELD, STATIC, FINAL, modifier);
+ }
+ for (ArrangementSettingsToken modifier : visibility) {
+ and(matchRules, FIELD, STATIC, modifier);
+ }
+ for (ArrangementSettingsToken modifier : visibility) {
+ and(matchRules, FIELD, FINAL, modifier);
+ }
+ for (ArrangementSettingsToken modifier : visibility) {
+ and(matchRules, FIELD, modifier);
+ }
+ and(matchRules, FIELD);
+ and(matchRules, CONSTRUCTOR);
+ and(matchRules, METHOD, STATIC);
+ and(matchRules, METHOD);
+ and(matchRules, ENUM);
+ and(matchRules, INTERFACE);
+ and(matchRules, CLASS, STATIC);
+ and(matchRules, CLASS);
+
+ DEFAULT_SETTINGS = new StdRulePriorityAwareSettings(groupingRules, matchRules);
+ }
+
+ private static final DefaultArrangementSettingsSerializer SETTINGS_SERIALIZER = new DefaultArrangementSettingsSerializer(DEFAULT_SETTINGS);
+
@NotNull
private static Set<ArrangementSettingsToken> concat(@NotNull Set<ArrangementSettingsToken> base, ArrangementSettingsToken... modifiers) {
Set<ArrangementSettingsToken> result = ContainerUtilRt.newHashSet(base);
@@ -279,32 +311,14 @@
@NotNull
@Override
- public StdArrangementSettings getDefaultSettings() {
- List<ArrangementGroupingRule> groupingRules = ContainerUtilRt.newArrayList(new ArrangementGroupingRule(GETTERS_AND_SETTERS));
- List<StdArrangementMatchRule> matchRules = ContainerUtilRt.newArrayList();
- ArrangementSettingsToken[] visibility = {PUBLIC, PROTECTED, PACKAGE_PRIVATE, PRIVATE};
- for (ArrangementSettingsToken modifier : visibility) {
- and(matchRules, FIELD, STATIC, FINAL, modifier);
- }
- for (ArrangementSettingsToken modifier : visibility) {
- and(matchRules, FIELD, STATIC, modifier);
- }
- for (ArrangementSettingsToken modifier : visibility) {
- and(matchRules, FIELD, FINAL, modifier);
- }
- for (ArrangementSettingsToken modifier : visibility) {
- and(matchRules, FIELD, modifier);
- }
- and(matchRules, FIELD);
- and(matchRules, CONSTRUCTOR);
- and(matchRules, METHOD, STATIC);
- and(matchRules, METHOD);
- and(matchRules, ENUM);
- and(matchRules, INTERFACE);
- and(matchRules, CLASS, STATIC);
- and(matchRules, CLASS);
+ public ArrangementSettingsSerializer getSerializer() {
+ return SETTINGS_SERIALIZER;
+ }
- return new StdRulePriorityAwareSettings(groupingRules, matchRules);
+ @NotNull
+ @Override
+ public StdArrangementSettings getDefaultSettings() {
+ return DEFAULT_SETTINGS;
}
@Nullable
diff --git a/java/java-impl/src/com/intellij/psi/filters/GeneratorFilter.java b/java/java-impl/src/com/intellij/psi/filters/GeneratorFilter.java
index 996c0bc..e481617 100644
--- a/java/java-impl/src/com/intellij/psi/filters/GeneratorFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/GeneratorFilter.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,7 +18,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiElement;
import com.intellij.reference.SoftReference;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -72,7 +72,7 @@
try{
final ElementFilter elementFilter = (ElementFilter) myFilterClass.newInstance();
final Object[] initArgument = myGetter.get(context, null);
- if(ReflectionCache.isAssignable(InitializableFilter.class, myFilterClass) && initArgument != null){
+ if(ReflectionUtil.isAssignable(InitializableFilter.class, myFilterClass) && initArgument != null){
((InitializableFilter)elementFilter).init(initArgument);
return elementFilter;
}
diff --git a/java/java-impl/src/com/intellij/psi/filters/classes/AssignableFromContextFilter.java b/java/java-impl/src/com/intellij/psi/filters/classes/AssignableFromContextFilter.java
index 35b5174..00287f4 100644
--- a/java/java-impl/src/com/intellij/psi/filters/classes/AssignableFromContextFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/classes/AssignableFromContextFilter.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,7 +19,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.reference.SoftReference;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -32,7 +32,7 @@
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiClass.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiClass.class, hintClass);
}
private SoftReference myCurrentContext = new SoftReference(null);
diff --git a/java/java-impl/src/com/intellij/psi/filters/classes/ClassAssignableFilter.java b/java/java-impl/src/com/intellij/psi/filters/classes/ClassAssignableFilter.java
index 0028e9a..5034c48 100644
--- a/java/java-impl/src/com/intellij/psi/filters/classes/ClassAssignableFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/classes/ClassAssignableFilter.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.
@@ -22,7 +22,7 @@
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.reference.SoftReference;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -42,7 +42,7 @@
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiClass.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiClass.class, hintClass);
}
protected PsiClass getPsiClass(PsiManager manager, GlobalSearchScope scope){
diff --git a/java/java-impl/src/com/intellij/psi/filters/classes/EnumOrAnnotationTypeFilter.java b/java/java-impl/src/com/intellij/psi/filters/classes/EnumOrAnnotationTypeFilter.java
index c7dcff2..de48dfa 100644
--- a/java/java-impl/src/com/intellij/psi/filters/classes/EnumOrAnnotationTypeFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/classes/EnumOrAnnotationTypeFilter.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,14 +18,14 @@
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.ElementFilter;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
public class EnumOrAnnotationTypeFilter implements ElementFilter{
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiClass.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiClass.class, hintClass);
}
@Override
diff --git a/java/java-impl/src/com/intellij/psi/filters/classes/InterfaceFilter.java b/java/java-impl/src/com/intellij/psi/filters/classes/InterfaceFilter.java
index 97c3552..702dced 100644
--- a/java/java-impl/src/com/intellij/psi/filters/classes/InterfaceFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/classes/InterfaceFilter.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,7 +18,7 @@
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.ElementFilter;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -30,7 +30,7 @@
public class InterfaceFilter implements ElementFilter{
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiClass.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiClass.class, hintClass);
}
@Override
diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/ExpectedTypesGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/ExpectedTypesGetter.java
index e7f7042..eb8a015 100644
--- a/java/java-impl/src/com/intellij/psi/filters/getters/ExpectedTypesGetter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/getters/ExpectedTypesGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -60,6 +60,6 @@
}
result.add(defaultType);
}
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(PsiType.createArray(result.size()));
}
}
diff --git a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java
index 9cb5a21..9e13bdc 100644
--- a/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/getters/MembersGetter.java
@@ -44,7 +44,7 @@
* @author peter
*/
public abstract class MembersGetter {
- public static final Key<Boolean> EXPECTED_TYPE_INHERITOR_MEMBER = Key.create("EXPECTED_TYPE_INHERITOR_MEMBER");
+ public static final Key<Boolean> EXPECTED_TYPE_MEMBER = Key.create("EXPECTED_TYPE_MEMBER");
private final Set<PsiMember> myImportedStatically = new HashSet<PsiMember>();
private final List<PsiClass> myPlaceClasses = new ArrayList<PsiClass>();
private final List<PsiMethod> myPlaceMethods = new ArrayList<PsiMethod>();
@@ -111,12 +111,12 @@
if (mayProcessMembers(psiClass)) {
final FilterScopeProcessor<PsiElement> declProcessor = new FilterScopeProcessor<PsiElement>(TrueFilter.INSTANCE);
psiClass.processDeclarations(declProcessor, ResolveState.initial(), null, myPlace);
- doProcessMembers(acceptMethods, results, psiType != baseType, declProcessor.getResults());
+ doProcessMembers(acceptMethods, results, psiType == baseType, declProcessor.getResults());
String name = psiClass.getName();
if (name != null && searchFactoryMethods) {
Collection<PsiMember> factoryMethods = JavaStaticMemberTypeIndex.getInstance().getStaticMembers(name, project, scope);
- doProcessMembers(acceptMethods, results, psiType != baseType, factoryMethods);
+ doProcessMembers(acceptMethods, results, false, factoryMethods);
}
}
}
@@ -129,7 +129,7 @@
private void doProcessMembers(boolean acceptMethods,
Consumer<LookupElement> results,
- boolean isInheritor, Collection<? extends PsiElement> declarations) {
+ boolean isExpectedTypeMember, Collection<? extends PsiElement> declarations) {
for (final PsiElement result : declarations) {
if (result instanceof PsiMember && !(result instanceof PsiClass)) {
final PsiMember member = (PsiMember)result;
@@ -144,7 +144,7 @@
final LookupElement item = result instanceof PsiMethod ? createMethodElement((PsiMethod)result) : createFieldElement((PsiField)result);
if (item != null) {
- item.putUserData(EXPECTED_TYPE_INHERITOR_MEMBER, isInheritor);
+ item.putUserData(EXPECTED_TYPE_MEMBER, isExpectedTypeMember);
results.consume(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(item));
}
}
diff --git a/java/java-impl/src/com/intellij/psi/filters/position/TokenTypeFilter.java b/java/java-impl/src/com/intellij/psi/filters/position/TokenTypeFilter.java
index 485cff0..58d8788 100644
--- a/java/java-impl/src/com/intellij/psi/filters/position/TokenTypeFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/position/TokenTypeFilter.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,7 +21,7 @@
import com.intellij.psi.javadoc.PsiDocToken;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.XmlToken;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -41,7 +41,7 @@
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiDocToken.class, hintClass) || ReflectionCache.isAssignable(XmlToken.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiDocToken.class, hintClass) || ReflectionUtil.isAssignable(XmlToken.class, hintClass);
}
@Override
diff --git a/java/java-impl/src/com/intellij/psi/filters/types/TypeFilter.java b/java/java-impl/src/com/intellij/psi/filters/types/TypeFilter.java
index 9e96ba2..fd5e91f 100644
--- a/java/java-impl/src/com/intellij/psi/filters/types/TypeFilter.java
+++ b/java/java-impl/src/com/intellij/psi/filters/types/TypeFilter.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,7 +18,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.filters.ElementFilter;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -41,6 +41,6 @@
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiType.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiType.class, hintClass);
}
}
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java
index d98165f..59dc77a 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/AbstractJavaBlock.java
@@ -26,12 +26,13 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.formatter.common.AbstractBlock;
import com.intellij.psi.formatter.java.wrap.JavaWrapManager;
import com.intellij.psi.formatter.java.wrap.ReservedWrapsProvider;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
-import com.intellij.psi.impl.source.codeStyle.ShiftIndentInsideHelper;
+import com.intellij.psi.impl.source.codeStyle.*;
import com.intellij.psi.impl.source.tree.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.impl.source.tree.java.ClassElement;
@@ -73,6 +74,7 @@
));
@NotNull protected final CommonCodeStyleSettings mySettings;
+ @NotNull protected final JavaCodeStyleSettings myJavaSettings;
protected final CommonCodeStyleSettings.IndentOptions myIndentSettings;
private final Indent myIndent;
protected Indent myChildIndent;
@@ -92,27 +94,33 @@
final Wrap wrap,
final Alignment alignment,
final Indent indent,
- @NotNull final CommonCodeStyleSettings settings) {
- this(node, wrap, indent, settings, JavaWrapManager.INSTANCE, AlignmentStrategy.wrap(alignment), AlignmentInColumnsHelper.INSTANCE);
+ @NotNull final CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings)
+ {
+ this(node, wrap, indent, settings, javaSettings, JavaWrapManager.INSTANCE, AlignmentStrategy.wrap(alignment), AlignmentInColumnsHelper.INSTANCE);
}
protected AbstractJavaBlock(@NotNull final ASTNode node,
final Wrap wrap,
@NotNull final AlignmentStrategy alignmentStrategy,
final Indent indent,
- @NotNull final CommonCodeStyleSettings settings) {
- this(node, wrap, indent, settings, JavaWrapManager.INSTANCE, alignmentStrategy, AlignmentInColumnsHelper.INSTANCE);
+ @NotNull final CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings)
+ {
+ this(node, wrap, indent, settings, javaSettings, JavaWrapManager.INSTANCE, alignmentStrategy, AlignmentInColumnsHelper.INSTANCE);
}
protected AbstractJavaBlock(@NotNull final ASTNode node,
final Wrap wrap,
final Indent indent,
@NotNull final CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings,
final JavaWrapManager wrapManager,
@NotNull final AlignmentStrategy alignmentStrategy,
AlignmentInColumnsHelper alignmentInColumnsHelper) {
super(node, wrap, createBlockAlignment(alignmentStrategy, node));
mySettings = settings;
+ myJavaSettings = javaSettings;
myIndentSettings = settings.getIndentOptions();
myIndent = indent;
myWrapManager = wrapManager;
@@ -131,30 +139,35 @@
}
@NotNull
- public static Block createJavaBlock(@NotNull final ASTNode child,
- @NotNull final CommonCodeStyleSettings settings,
- @Nullable final Indent indent,
+ public static Block createJavaBlock(@NotNull ASTNode child,
+ @NotNull CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings,
+ @Nullable Indent indent,
@Nullable Wrap wrap,
- Alignment alignment) {
- return createJavaBlock(child, settings, indent, wrap, AlignmentStrategy.wrap(alignment));
+ Alignment alignment)
+ {
+ return createJavaBlock(child, settings, javaSettings,indent, wrap, AlignmentStrategy.wrap(alignment));
}
@NotNull
- public static Block createJavaBlock(@NotNull final ASTNode child,
- @NotNull final CommonCodeStyleSettings settings,
+ public static Block createJavaBlock(@NotNull ASTNode child,
+ @NotNull CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings,
final Indent indent,
@Nullable Wrap wrap,
@NotNull AlignmentStrategy alignmentStrategy) {
- return createJavaBlock(child, settings, indent, wrap, alignmentStrategy, -1);
+ return createJavaBlock(child, settings, javaSettings, indent, wrap, alignmentStrategy, -1);
}
@NotNull
- public static Block createJavaBlock(@NotNull final ASTNode child,
- @NotNull final CommonCodeStyleSettings settings,
- @Nullable final Indent indent,
- Wrap wrap,
- @NotNull AlignmentStrategy alignmentStrategy,
- int startOffset) {
+ private static Block createJavaBlock(@NotNull ASTNode child,
+ @NotNull CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings,
+ @Nullable Indent indent,
+ Wrap wrap,
+ @NotNull AlignmentStrategy alignmentStrategy,
+ int startOffset)
+ {
Indent actualIndent = indent == null ? getDefaultSubtreeIndent(child, getJavaIndentOptions(settings)) : indent;
final IElementType elementType = child.getElementType();
Alignment alignment = alignmentStrategy.getAlignment(elementType);
@@ -165,20 +178,20 @@
int end = CharArrayUtil.shiftBackward(text, text.length() - 1, " \t\n") + 1;
LOG.assertTrue(start < end);
return new PartialWhitespaceBlock(child, new TextRange(start + child.getStartOffset(), end + child.getStartOffset()),
- wrap, alignment, actualIndent, settings);
+ wrap, alignment, actualIndent, settings, javaSettings);
}
if (child.getPsi() instanceof PsiClass) {
- return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings);
+ return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings, javaSettings);
}
if (isBlockType(elementType)) {
- return new BlockContainingJavaBlock(child, wrap, alignment, actualIndent, settings);
+ return new BlockContainingJavaBlock(child, wrap, alignment, actualIndent, settings, javaSettings);
}
if (isStatement(child, child.getTreeParent())) {
- return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings);
+ return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings, javaSettings);
}
if (child instanceof PsiComment && child instanceof PsiLanguageInjectionHost && InjectedLanguageUtil
.hasInjections((PsiLanguageInjectionHost)child)) {
- return new CommentWithInjectionBlock(child, wrap, alignment, indent, settings);
+ return new CommentWithInjectionBlock(child, wrap, alignment, indent, settings, javaSettings);
}
if (child instanceof LeafElement) {
final LeafBlock block = new LeafBlock(child, wrap, alignment, actualIndent);
@@ -186,28 +199,31 @@
return block;
}
else if (isLikeExtendsList(elementType)) {
- return new ExtendsListBlock(child, wrap, alignmentStrategy, settings);
+ return new ExtendsListBlock(child, wrap, alignmentStrategy, settings, javaSettings);
}
else if (elementType == JavaElementType.CODE_BLOCK) {
- return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings);
+ return new CodeBlockBlock(child, wrap, alignment, actualIndent, settings, javaSettings);
}
else if (elementType == JavaElementType.LABELED_STATEMENT) {
- return new LabeledJavaBlock(child, wrap, alignment, actualIndent, settings);
+ return new LabeledJavaBlock(child, wrap, alignment, actualIndent, settings, javaSettings);
}
else if (elementType == JavaDocElementType.DOC_COMMENT) {
- return new DocCommentBlock(child, wrap, alignment, actualIndent, settings);
+ return new DocCommentBlock(child, wrap, alignment, actualIndent, settings, javaSettings);
}
else {
- final SimpleJavaBlock simpleJavaBlock = new SimpleJavaBlock(child, wrap, alignmentStrategy, actualIndent, settings);
+ final SimpleJavaBlock simpleJavaBlock = new SimpleJavaBlock(child, wrap, alignmentStrategy, actualIndent, settings, javaSettings);
simpleJavaBlock.setStartOffset(startOffset);
return simpleJavaBlock;
}
}
@NotNull
- public static Block createJavaBlock(@NotNull ASTNode child, @NotNull CommonCodeStyleSettings settings) {
- return createJavaBlock(child, settings, getDefaultSubtreeIndent(child, getJavaIndentOptions(settings)),
- null, AlignmentStrategy.getNullStrategy());
+ public static Block createJavaBlock(@NotNull ASTNode child,
+ @NotNull CommonCodeStyleSettings settings,
+ @NotNull JavaCodeStyleSettings javaSettings) {
+ return createJavaBlock(
+ child, settings, javaSettings, getDefaultSubtreeIndent(child, getJavaIndentOptions(settings)), null, AlignmentStrategy.getNullStrategy()
+ );
}
@NotNull
@@ -307,7 +323,7 @@
@Nullable
@Override
public Spacing getSpacing(Block child1, @NotNull Block child2) {
- return JavaSpacePropertyProcessor.getSpacing(getTreeNode(child2), mySettings);
+ return JavaSpacePropertyProcessor.getSpacing(getTreeNode(child2), mySettings, myJavaSettings);
}
@Override
@@ -457,7 +473,7 @@
if (childType == JavaElementType.METHOD_CALL_EXPRESSION) {
result.add(createMethodCallExpressionBlock(child,
arrangeChildWrap(child, defaultWrap),
- arrangeChildAlignment(child, alignmentStrategy)));
+ arrangeChildAlignment(child, alignmentStrategy), childIndent));
}
else {
IElementType nodeType = myNode.getElementType();
@@ -535,7 +551,7 @@
else if (childType == JavaElementType.LOCAL_VARIABLE
|| childType == JavaElementType.DECLARATION_STATEMENT && myNode.getElementType() == JavaElementType.METHOD)
{
- result.add(new SimpleJavaBlock(child, defaultWrap, alignmentStrategy, childIndent, mySettings));
+ result.add(new SimpleJavaBlock(child, defaultWrap, alignmentStrategy, childIndent, mySettings, myJavaSettings));
}
else {
AlignmentStrategy alignmentStrategyToUse = AlignmentStrategy.wrap(arrangeChildAlignment(child, alignmentStrategy));
@@ -545,7 +561,7 @@
alignmentStrategyToUse = myAlignmentStrategy;
}
final Block block = createJavaBlock(
- child, mySettings, childIndent, arrangeChildWrap(child, defaultWrap), alignmentStrategyToUse, childOffset
+ child, mySettings, myJavaSettings, childIndent, arrangeChildWrap(child, defaultWrap), alignmentStrategyToUse, childOffset
);
if (childType == JavaElementType.MODIFIER_LIST && containsAnnotations(child)) {
@@ -599,18 +615,19 @@
final Indent childIndent) {
ASTNode lastFieldInGroup = findLastFieldInGroup(child);
if (lastFieldInGroup == child) {
- result.add(createJavaBlock(child, getSettings(), childIndent, arrangeChildWrap(child, defaultWrap), alignmentStrategy));
+ result.add(createJavaBlock(child, getSettings(), myJavaSettings, childIndent, arrangeChildWrap(child, defaultWrap), alignmentStrategy));
return child;
}
else {
final ArrayList<Block> localResult = new ArrayList<Block>();
while (child != null) {
if (!FormatterUtil.containsWhiteSpacesOnly(child)) {
- localResult.add(createJavaBlock(child,
- getSettings(),
- Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS),
- arrangeChildWrap(child, defaultWrap),
- alignmentStrategy)
+ localResult.add(createJavaBlock(
+ child, getSettings(), myJavaSettings,
+ Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS),
+ arrangeChildWrap(child, defaultWrap),
+ alignmentStrategy
+ )
);
}
if (child == lastFieldInGroup) break;
@@ -618,7 +635,7 @@
child = child.getTreeNext();
}
if (!localResult.isEmpty()) {
- result.add(new SyntheticCodeBlock(localResult, null, getSettings(), childIndent, null));
+ result.add(new SyntheticCodeBlock(localResult, null, getSettings(), myJavaSettings, childIndent, null));
}
return lastFieldInGroup;
}
@@ -695,7 +712,7 @@
}
}
- result.add(new SyntheticCodeBlock(localResult, chooseAlignment(alignment, alignment2, child), getSettings(), null, wrap));
+ result.add(new SyntheticCodeBlock(localResult, chooseAlignment(alignment, alignment2, child), getSettings(), myJavaSettings, null, wrap));
if (current == null) {
return null;
@@ -710,10 +727,10 @@
}
@NotNull
- private Block createMethodCallExpressionBlock(@NotNull final ASTNode node, final Wrap blockWrap, final Alignment alignment) {
+ private Block createMethodCallExpressionBlock(@NotNull ASTNode node, Wrap blockWrap, Alignment alignment, Indent indent) {
final ArrayList<ASTNode> nodes = new ArrayList<ASTNode>();
collectNodes(nodes, node);
- return new ChainMethodCallsBlockBuilder(alignment, blockWrap).build(nodes);
+ return new ChainMethodCallsBlockBuilder(alignment, blockWrap, indent).build(nodes);
}
@NotNull
@@ -721,23 +738,23 @@
final ArrayList<Block> subBlocks = new ArrayList<Block>();
final ASTNode firstNode = subNodes.get(0);
if (firstNode.getElementType() == JavaTokenType.DOT) {
- subBlocks.add(createJavaBlock(firstNode, getSettings(), Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
+ subBlocks.add(createJavaBlock(firstNode, getSettings(), myJavaSettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
subNodes.remove(0);
if (!subNodes.isEmpty()) {
subBlocks.add(createSyntheticBlock(subNodes, wrap, null));
}
return new SyntheticCodeBlock(subBlocks, alignment, mySettings,
- Indent.getContinuationIndent(myIndentSettings.USE_RELATIVE_INDENTS), wrap);
+ myJavaSettings, Indent.getContinuationIndent(myIndentSettings.USE_RELATIVE_INDENTS), wrap);
}
return new SyntheticCodeBlock(createJavaBlocks(subNodes), alignment, mySettings,
- Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), null);
+ myJavaSettings, Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), null);
}
@NotNull
private List<Block> createJavaBlocks(@NotNull final List<ASTNode> subNodes) {
final ArrayList<Block> result = new ArrayList<Block>();
for (ASTNode node : subNodes) {
- result.add(createJavaBlock(node, getSettings(), Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), null,
+ result.add(createJavaBlock(node, getSettings(), myJavaSettings, Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS), null,
AlignmentStrategy.getNullStrategy()));
}
return result;
@@ -1028,23 +1045,24 @@
ASTNode prev = child;
boolean afterAnonymousClass = false;
+ final boolean enforceIndent = shouldEnforceIndentToChildren();
while (child != null) {
isAfterIncomplete = isAfterIncomplete || child.getElementType() == TokenType.ERROR_ELEMENT ||
child.getElementType() == JavaElementType.EMPTY_EXPRESSION;
if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0) {
if (child.getElementType() == from) {
- result.add(createJavaBlock(child, mySettings, externalIndent, null, bracketAlignment));
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, externalIndent, null, bracketAlignment));
}
else if (child.getElementType() == to) {
- result.add(createJavaBlock(child, mySettings,
+ result.add(createJavaBlock(child, mySettings, myJavaSettings,
isAfterIncomplete && !afterAnonymousClass ? internalIndent : externalIndent,
null,
- isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment));
+ isAfterIncomplete ? alignmentStrategy.getAlignment(null) : bracketAlignment)
+ );
return child;
}
else {
final IElementType elementType = child.getElementType();
- final boolean enforceIndent = shouldEnforceIndentToChildren(child);
Indent indentToUse = enforceIndent ? internalIndentEnforcedToChildren : internalIndent;
AlignmentStrategy alignmentStrategyToUse = canUseAnonymousClassAlignment(child) ? anonymousClassStrategy : alignmentStrategy;
processChild(result, child, alignmentStrategyToUse.getAlignment(elementType), wrappingStrategy.getWrap(elementType), indentToUse);
@@ -1105,8 +1123,7 @@
return true;
}
- private boolean shouldEnforceIndentToChildren(@NotNull ASTNode node) {
- // Filter only anonymous class instances as method call arguments
+ private boolean shouldEnforceIndentToChildren() {
if (myNode.getElementType() != JavaElementType.EXPRESSION_LIST) {
return false;
}
@@ -1114,13 +1131,10 @@
if (parent == null || parent.getElementType() != JavaElementType.METHOD_CALL_EXPRESSION) {
return false;
}
- if (!isAnonymousClass(node) || !JavaFormatterUtil.hasAnonymousClassesArguments((PsiExpressionList)myNode.getPsi(), 2)) {
- return false;
- }
-
- // Enforce indent only if anonymous class instance expression doesn't start new line and have anonymous class expression sibling.
- ASTNode prev = node.getTreePrev();
- return prev != null && !(StringUtil.containsLineBreak(prev.getChars()) && prev.getElementType() != TokenType.WHITE_SPACE);
+
+ PsiExpression[] arguments = ((PsiExpressionList)myNode.getPsi()).getExpressions();
+ return (JavaFormatterUtil.hasMultilineArguments(arguments) || JavaFormatterUtil.canHaveMultilineArgumentsAfterWrap(arguments, mySettings))
+ && (JavaFormatterUtil.isMultilineExceptArguments(arguments) || JavaFormatterUtil.canBeMultilineExceptArgumentsAfterWrap(arguments, mySettings));
}
private static boolean isAnonymousClass(@Nullable ASTNode node) {
@@ -1140,7 +1154,7 @@
.createWrap(getWrapType(mySettings.ENUM_CONSTANTS_WRAP), true));
while (child != null) {
if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0) {
- result.add(createJavaBlock(child, mySettings, Indent.getNormalIndent(),
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, Indent.getNormalIndent(),
wrappingStrategy.getWrap(child.getElementType()), AlignmentStrategy.getNullStrategy()));
if (child == last) return child;
}
@@ -1428,7 +1442,7 @@
@NotNull
public SyntheticCodeBlock createCodeBlockBlock(final List<Block> localResult, final Indent indent, final int childrenIndent) {
- final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), indent, null);
+ final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, null, getSettings(), myJavaSettings, indent, null);
result.setChildAttributes(new ChildAttributes(getCodeBlockInternalIndent(childrenIndent), null));
return result;
}
@@ -1436,13 +1450,15 @@
private class ChainMethodCallsBlockBuilder {
private Wrap blockWrap;
private Alignment blockAlignment;
+ private Indent blockIndent;
private Wrap myWrap;
private Alignment myChainedCallsAlignment;
- public ChainMethodCallsBlockBuilder(Alignment alignment, Wrap wrap) {
+ public ChainMethodCallsBlockBuilder(Alignment alignment, Wrap wrap, Indent indent) {
blockWrap = wrap;
blockAlignment = alignment;
+ blockIndent = indent;
}
public Block build(List<ASTNode> nodes) {
@@ -1450,9 +1466,9 @@
myChainedCallsAlignment = getNewAlignment();
List<Block> blocks = buildBlocksFrom(nodes);
- Indent indent = Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS);
- return new SyntheticCodeBlock(blocks, blockAlignment, mySettings, indent, blockWrap);
+ Indent indent = blockIndent != null ? blockIndent : Indent.getContinuationWithoutFirstIndent(myIndentSettings.USE_RELATIVE_INDENTS);
+ return new SyntheticCodeBlock(blocks, blockAlignment, mySettings, myJavaSettings, indent, blockWrap);
}
private List<Block> buildBlocksFrom(List<ASTNode> nodes) {
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java
index cb5139c..a97d6d1 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/BlockContainingJavaBlock.java
@@ -20,6 +20,7 @@
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiStatement;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
@@ -44,8 +45,13 @@
private final List<Indent> myIndentsBefore = new ArrayList<Indent>();
- public BlockContainingJavaBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent, CommonCodeStyleSettings settings) {
- super(node, wrap, alignment, indent, settings);
+ public BlockContainingJavaBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings) {
+ super(node, wrap, alignment, indent, settings, javaSettings);
}
@Override
protected List<Block> buildChildren() {
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java
index 574c93f..d6fe92b 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/CodeBlockBlock.java
@@ -23,6 +23,7 @@
import com.intellij.psi.PsiSyntheticClass;
import com.intellij.psi.TokenType;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.formatter.common.AbstractBlock;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
@@ -42,12 +43,13 @@
private final int myChildrenIndent;
- public CodeBlockBlock(final ASTNode node,
- final Wrap wrap,
- final Alignment alignment,
- final Indent indent,
- final CommonCodeStyleSettings settings) {
- super(node, wrap, getAlignmentStrategy(alignment, node, settings), indent, settings);
+ public CodeBlockBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings) {
+ super(node, wrap, getAlignmentStrategy(alignment, node, settings), indent, settings, javaSettings);
if (isSwitchCodeBlock() && !settings.INDENT_CASE_FROM_SWITCH) {
myChildrenIndent = 0;
}
@@ -200,7 +202,7 @@
private SyntheticCodeBlock createCaseSectionBlock(final ArrayList<Block> localResult, final Alignment childAlignment, final Indent indent,
final Wrap childWrap) {
- final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, childAlignment, getSettings(), indent, childWrap) {
+ final SyntheticCodeBlock result = new SyntheticCodeBlock(localResult, childAlignment, getSettings(), myJavaSettings, indent, childWrap) {
@Override
@NotNull
public ChildAttributes getChildAttributes(final int newChildIndex) {
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/CommentWithInjectionBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/CommentWithInjectionBlock.java
index 7e31f44..f03d412 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/CommentWithInjectionBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/CommentWithInjectionBlock.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.common.InjectedLanguageBlockBuilder;
import org.jetbrains.annotations.NotNull;
@@ -32,8 +33,13 @@
public class CommentWithInjectionBlock extends AbstractJavaBlock {
private final InjectedLanguageBlockBuilder myInjectedBlockBuilder;
- public CommentWithInjectionBlock(ASTNode node, Wrap wrap, Alignment alignment, Indent indent, CommonCodeStyleSettings settings) {
- super(node, wrap, alignment, indent, settings);
+ public CommentWithInjectionBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings) {
+ super(node, wrap, alignment, indent, settings, javaSettings);
myInjectedBlockBuilder = new JavaCommentInjectedBlockBuilder();
}
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
index 4bc6f6d..eeb4b7b 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/DocCommentBlock.java
@@ -20,6 +20,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.psi.JavaDocTokenType;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import org.jetbrains.annotations.NotNull;
@@ -27,8 +28,14 @@
import java.util.List;
public class DocCommentBlock extends AbstractJavaBlock{
- public DocCommentBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent, CommonCodeStyleSettings settings) {
- super(node, wrap, alignment, indent, settings);
+ public DocCommentBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings)
+ {
+ super(node, wrap, alignment, indent, settings, javaSettings);
}
@Override
@@ -38,9 +45,9 @@
ASTNode child = myNode.getFirstChildNode();
while (child != null) {
if (child.getElementType() == JavaDocTokenType.DOC_COMMENT_START) {
- result.add(createJavaBlock(child, mySettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
} else if (!FormatterUtil.containsWhiteSpacesOnly(child) && !child.getText().trim().isEmpty()){
- result.add(createJavaBlock(child, mySettings, Indent.getSpaceIndent(1), null, AlignmentStrategy.getNullStrategy()));
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, Indent.getSpaceIndent(1), null, AlignmentStrategy.getNullStrategy()));
}
child = child.getTreeNext();
}
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java
index 37e49de..975bece 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/ExtendsListBlock.java
@@ -22,6 +22,7 @@
import com.intellij.formatting.alignment.AlignmentStrategy;
import com.intellij.lang.ASTNode;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -30,12 +31,22 @@
import java.util.List;
public class ExtendsListBlock extends AbstractJavaBlock{
- public ExtendsListBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, CommonCodeStyleSettings settings) {
- super(node, wrap, alignment, Indent.getNoneIndent(), settings);
+ public ExtendsListBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings)
+ {
+ super(node, wrap, alignment, Indent.getNoneIndent(), settings, javaSettings);
}
- public ExtendsListBlock(final ASTNode node, final Wrap wrap, final AlignmentStrategy alignmentStrategy, CommonCodeStyleSettings settings) {
- super(node, wrap, alignmentStrategy, Indent.getNoneIndent(), settings);
+ public ExtendsListBlock(ASTNode node,
+ Wrap wrap,
+ AlignmentStrategy alignmentStrategy,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings)
+ {
+ super(node, wrap, alignmentStrategy, Indent.getNoneIndent(), settings, javaSettings);
}
@Override
@@ -54,10 +65,10 @@
if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){
if (ElementType.KEYWORD_BIT_SET.contains(child.getElementType())) {
if (!elementsExceptKeyword.isEmpty()) {
- result.add(new SyntheticCodeBlock(elementsExceptKeyword, null, mySettings, Indent.getNoneIndent(), null));
+ result.add(new SyntheticCodeBlock(elementsExceptKeyword, null, mySettings, myJavaSettings, Indent.getNoneIndent(), null));
elementsExceptKeyword = new ArrayList<Block>();
}
- result.add(createJavaBlock(child, mySettings, myChildIndent, arrangeChildWrap(child, childWrap), alignment));
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, myChildIndent, arrangeChildWrap(child, childWrap), alignment));
} else {
if (myAlignmentStrategy != null) {
Alignment candidate = myAlignmentStrategy.getAlignment(child.getElementType());
@@ -71,7 +82,7 @@
child = child.getTreeNext();
}
if (!elementsExceptKeyword.isEmpty()) {
- result.add(new SyntheticCodeBlock(elementsExceptKeyword, alignment, mySettings, Indent.getNoneIndent(), null));
+ result.add(new SyntheticCodeBlock(elementsExceptKeyword, alignment, mySettings, myJavaSettings, Indent.getNoneIndent(), null));
}
return result;
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java
index 2f6c7f9..5c1b5b7 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaFormatterUtil.java
@@ -16,13 +16,11 @@
package com.intellij.psi.formatter.java;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.PsiExpression;
-import com.intellij.psi.PsiExpressionList;
-import com.intellij.psi.PsiPolyadicExpression;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
import java.util.Set;
@@ -75,35 +73,50 @@
return expression1.getOperationTokenType() == expression2.getOperationTokenType();
}
- /**
- * Allows to check if given expression list has given number of anonymous classes.
- *
- * @param count interested number of anonymous classes used at the given expression list
- * @return <code>true</code> if given expression list contains given number of anonymous classes;
- * <code>false</code> otherwise
- */
- public static boolean hasAnonymousClassesArguments(@NotNull PsiExpressionList expressionList, int count) {
- int found = 0;
- for (PsiExpression expression : expressionList.getExpressions()) {
- ASTNode node = expression.getNode();
- if (isAnonymousClass(node)) {
- found++;
- }
- if (found >= count) {
+ public static boolean hasMultilineArguments(@NotNull PsiExpression[] arguments) {
+ for (PsiExpression argument: arguments) {
+ ASTNode node = argument.getNode();
+ if (node.textContains('\n'))
return true;
- }
}
+
return false;
}
- private static boolean isAnonymousClass(@Nullable final ASTNode node) {
- if (node == null) {
- return false;
+ public static boolean canHaveMultilineArgumentsAfterWrap(@NotNull PsiExpression[] arguments, @NotNull CommonCodeStyleSettings settings) {
+ for (PsiExpression argument: arguments) {
+ ASTNode node = argument.getNode();
+
+ if (node instanceof PsiMethodCallExpression) {
+ if (settings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE || settings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE) {
+ if (((PsiMethodCallExpression)node).getArgumentList().getExpressions().length > 0) return true;
+ }
+ }
}
- ASTNode nodeToCheck = node;
- if (node.getElementType() == JavaElementType.NEW_EXPRESSION) {
- nodeToCheck = node.getLastChildNode();
- }
- return nodeToCheck != null && nodeToCheck.getElementType() == JavaElementType.ANONYMOUS_CLASS;
+
+ return false;
}
+
+ public static boolean isMultilineExceptArguments(@NotNull PsiExpression[] arguments) {
+ for (PsiExpression argument : arguments) {
+ ASTNode beforeArgument = argument.getNode().getTreePrev();
+ if (isWhiteSpaceWithLineFeed(beforeArgument))
+ return true;
+ }
+
+ PsiExpression lastArgument = arguments[arguments.length - 1];
+ ASTNode afterLastArgument = lastArgument.getNode().getTreeNext();
+ return isWhiteSpaceWithLineFeed(afterLastArgument);
+ }
+
+ public static boolean canBeMultilineExceptArgumentsAfterWrap(@NotNull PsiExpression[] arguments, @NotNull CommonCodeStyleSettings settings) {
+ return arguments.length > 0
+ && (settings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE || settings.CALL_PARAMETERS_RPAREN_ON_NEXT_LINE);
+ }
+
+ private static boolean isWhiteSpaceWithLineFeed(@NotNull ASTNode node) {
+ return node instanceof PsiWhiteSpace
+ && node.textContains('\n');
+ }
+
}
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
index 39a1a73..b904628 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/JavaSpacePropertyProcessor.java
@@ -29,6 +29,7 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.codeStyle.ImportHelper;
@@ -54,6 +55,7 @@
private int myRole1;
private int myRole2;
private CommonCodeStyleSettings mySettings;
+ private JavaCodeStyleSettings myJavaSettings;
private Spacing myResult;
private ASTNode myChild1;
@@ -66,9 +68,10 @@
private static final ThreadLocal<JavaSpacePropertyProcessor> mySharedProcessorAllocator = new ThreadLocal<JavaSpacePropertyProcessor>();
- private void doInit(final ASTNode child, final CommonCodeStyleSettings settings) {
+ private void doInit(ASTNode child, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
init(child);
mySettings = settings;
+ myJavaSettings = javaSettings;
if (myChild1 == null) {
// Given node corresponds to the first document block.
@@ -408,7 +411,7 @@
}
else if (myRole2 == ChildRole.TYPE_PARAMETER_LIST) {
- createSpaceInCode(mySettings.SPACE_BEFORE_TYPE_PARAMETER_LIST);
+ createSpaceInCode(myJavaSettings.SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER);
}
else if (myRole2 == ChildRole.ARGUMENT_LIST) {
@@ -1151,7 +1154,8 @@
createParenthSpace(mySettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE, mySettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES);
}
else if (myRole2 == ChildRole.RPARENTH) {
- if (JavaFormatterUtil.hasAnonymousClassesArguments(list, 2)) {
+ PsiExpression[] arguments = list.getExpressions();
+ if (JavaFormatterUtil.hasMultilineArguments(arguments) && JavaFormatterUtil.isMultilineExceptArguments(arguments)) {
myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, 0);
}
else {
@@ -1321,17 +1325,18 @@
}
@Override public void visitReferenceParameterList(PsiReferenceParameterList list) {
- if (myRole1 == ChildRole.LT_IN_TYPE_LIST && myRole2 == ChildRole.TYPE_IN_REFERENCE_PARAMETER_LIST
- || myRole1 == ChildRole.LT_IN_TYPE_LIST && myRole2 == ChildRole.GT_IN_TYPE_LIST
- || myRole1 == ChildRole.TYPE_IN_REFERENCE_PARAMETER_LIST && myRole2 == ChildRole.COMMA)
- {
+ if (myRole1 == ChildRole.LT_IN_TYPE_LIST && myRole2 == ChildRole.GT_IN_TYPE_LIST
+ || myRole1 == ChildRole.TYPE_IN_REFERENCE_PARAMETER_LIST && myRole2 == ChildRole.COMMA) {
createSpaceInCode(false);
}
+ else if (myRole1 == ChildRole.LT_IN_TYPE_LIST && myRole2 == ChildRole.TYPE_IN_REFERENCE_PARAMETER_LIST) {
+ createSpaceInCode(myJavaSettings.SPACES_WITHIN_ANGLE_BRACKETS);
+ }
else if (myRole1 == ChildRole.COMMA && myRole2 == ChildRole.TYPE_IN_REFERENCE_PARAMETER_LIST) {
createSpaceInCode(mySettings.SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS);
}
else if (myRole2 == ChildRole.GT_IN_TYPE_LIST) {
- createSpaceInCode(false);
+ createSpaceInCode(myJavaSettings.SPACES_WITHIN_ANGLE_BRACKETS);
}
}
@@ -1372,10 +1377,11 @@
else if (myRole2 == ChildRole.COMMA) {
createSpaceInCode(false);
}
+ else if (myRole1 == ChildRole.AMPERSAND_IN_BOUNDS_LIST || myRole2 == ChildRole.AMPERSAND_IN_BOUNDS_LIST) {
+ createSpaceInCode(myJavaSettings.SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS);
+ }
else if (myRole1 == ChildRole.EXTENDS_KEYWORD
|| myRole2 == ChildRole.EXTENDS_KEYWORD
- || myRole1 == ChildRole.AMPERSAND_IN_BOUNDS_LIST
- || myRole2 == ChildRole.AMPERSAND_IN_BOUNDS_LIST
|| myRole1 == ChildRole.IMPLEMENTS_KEYWORD
|| myRole2 == ChildRole.IMPLEMENTS_KEYWORD
|| myRole1 == ChildRole.THROWS_KEYWORD)
@@ -1459,16 +1465,19 @@
}
@Override public void visitTypeParameterList(PsiTypeParameterList list) {
- if (myRole2 == ChildRole.GT_IN_TYPE_LIST) {
- createSpaceInCode(false);
+ if (myRole1 == ChildRole.LT_IN_TYPE_LIST || myRole2 == ChildRole.GT_IN_TYPE_LIST) {
+ createSpaceInCode(myJavaSettings.SPACES_WITHIN_ANGLE_BRACKETS);
}
else if (myRole1 == ChildRole.COMMA) {
- createSpaceInCode(mySettings.SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS);
+ createSpaceInCode(mySettings.SPACE_AFTER_COMMA);
}
}
@Override public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
- if (myRole2 == ChildRole.REFERENCE_PARAMETER_LIST) {
+ if (myRole1 == ChildRole.REFERENCE_PARAMETER_LIST && myRole2 == ChildRole.REFERENCE_NAME) {
+ createSpaceInCode(myJavaSettings.SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT);
+ }
+ else if (myRole2 == ChildRole.REFERENCE_PARAMETER_LIST) {
createSpaceInCode(mySettings.SPACE_BEFORE_TYPE_PARAMETER_LIST);
}
else if (myRole2 == ChildRole.DOT){
@@ -1596,14 +1605,14 @@
}
@SuppressWarnings({"ConstantConditions"})
- public static Spacing getSpacing(ASTNode node, CommonCodeStyleSettings settings) {
+ public static Spacing getSpacing(ASTNode node, CommonCodeStyleSettings settings, JavaCodeStyleSettings javaSettings) {
JavaSpacePropertyProcessor spacePropertyProcessor = mySharedProcessorAllocator.get();
try {
if (spacePropertyProcessor == null) {
spacePropertyProcessor = new JavaSpacePropertyProcessor();
mySharedProcessorAllocator.set(spacePropertyProcessor);
}
- spacePropertyProcessor.doInit(node, settings);
+ spacePropertyProcessor.doInit(node, settings, javaSettings);
return spacePropertyProcessor.getResult();
}
finally {
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java
index c3f0af1..4e52dc9 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/LabeledJavaBlock.java
@@ -21,20 +21,21 @@
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
-import com.intellij.psi.impl.source.tree.ElementType;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class LabeledJavaBlock extends AbstractJavaBlock{
- public LabeledJavaBlock(final ASTNode node,
- final Wrap wrap,
- final Alignment alignment,
- final Indent indent,
- final CommonCodeStyleSettings settings) {
- super(node, wrap, alignment, indent, settings);
+ public LabeledJavaBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings) {
+ super(node, wrap, alignment, indent, settings, javaSettings);
}
@Override
@@ -45,7 +46,7 @@
Wrap currentWrap = null;
while (child != null) {
if (!FormatterUtil.containsWhiteSpacesOnly(child) && child.getTextLength() > 0){
- result.add(createJavaBlock(child, mySettings, currentIndent, currentWrap, AlignmentStrategy.getNullStrategy()));
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, currentIndent, currentWrap, AlignmentStrategy.getNullStrategy()));
if (child.getElementType() == JavaTokenType.COLON) {
currentIndent = Indent.getNoneIndent();
currentWrap =Wrap.createWrap(WrapType.ALWAYS, true);
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java
index bf5ca67..502a428 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/MethodCallExpressionBlock.java
@@ -21,12 +21,19 @@
import com.intellij.formatting.Indent;
import com.intellij.formatting.Block;
import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import java.util.List;
public class MethodCallExpressionBlock extends AbstractJavaBlock{
- public MethodCallExpressionBlock(final ASTNode node, final Wrap wrap, final Alignment alignment, final Indent indent, final CodeStyleSettings settings) {
- super(node, wrap, alignment, indent, settings);
+ public MethodCallExpressionBlock(ASTNode node,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings)
+ {
+ super(node, wrap, alignment, indent, settings, javaSettings);
}
@Override
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/PartialWhitespaceBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/PartialWhitespaceBlock.java
index 67b8e1a..652070ea 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/PartialWhitespaceBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/PartialWhitespaceBlock.java
@@ -15,14 +15,14 @@
*/
package com.intellij.psi.formatter.java;
-import com.intellij.formatting.alignment.AlignmentStrategy;
-import com.intellij.lang.ASTNode;
import com.intellij.formatting.Alignment;
import com.intellij.formatting.Indent;
import com.intellij.formatting.Wrap;
+import com.intellij.formatting.alignment.AlignmentStrategy;
+import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
/**
@@ -31,13 +31,14 @@
public class PartialWhitespaceBlock extends SimpleJavaBlock {
private final TextRange myRange;
- public PartialWhitespaceBlock(final ASTNode node,
- final TextRange range,
- final Wrap wrap,
- final Alignment alignment,
- final Indent indent,
- CommonCodeStyleSettings settings) {
- super(node, wrap, AlignmentStrategy.wrap(alignment), indent, settings);
+ public PartialWhitespaceBlock(ASTNode node,
+ TextRange range,
+ Wrap wrap,
+ Alignment alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings) {
+ super(node, wrap, AlignmentStrategy.wrap(alignment), indent, settings, javaSettings);
myRange = range;
}
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java
index 0a4c105..34d6772 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/SimpleJavaBlock.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.source.tree.JavaDocElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -38,8 +39,13 @@
private int myStartOffset = -1;
private final Map<IElementType, Wrap> myReservedWrap = new HashMap<IElementType, Wrap>();
- public SimpleJavaBlock(final ASTNode node, final Wrap wrap, final AlignmentStrategy alignment, final Indent indent, CommonCodeStyleSettings settings) {
- super(node, wrap, alignment, indent,settings);
+ public SimpleJavaBlock(ASTNode node,
+ Wrap wrap,
+ AlignmentStrategy alignment,
+ Indent indent,
+ CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings) {
+ super(node, wrap, alignment, indent, settings, javaSettings);
}
@Override
@@ -51,7 +57,7 @@
Indent indent = null;
while (child != null) {
if (StdTokenSets.COMMENT_BIT_SET.contains(child.getElementType()) || child.getElementType() == JavaDocElementType.DOC_COMMENT) {
- result.add(createJavaBlock(child, mySettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
+ result.add(createJavaBlock(child, mySettings, myJavaSettings, Indent.getNoneIndent(), null, AlignmentStrategy.getNullStrategy()));
indent = Indent.getNoneIndent();
}
else if (!FormatterUtil.containsWhiteSpacesOnly(child)) {
diff --git a/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java b/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java
index b094d4f..bdfb015 100644
--- a/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java
+++ b/java/java-impl/src/com/intellij/psi/formatter/java/SyntheticCodeBlock.java
@@ -21,8 +21,8 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.JavaCodeStyleSettings;
import com.intellij.psi.formatter.common.AbstractBlock;
import org.jetbrains.annotations.NotNull;
@@ -34,6 +34,7 @@
private final Alignment myAlignment;
private final Indent myIndentContent;
private final CommonCodeStyleSettings mySettings;
+ private final JavaCodeStyleSettings myJavaSettings;
private final Wrap myWrap;
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.formatter.newXmlFormatter.java.SyntheticCodeBlock");
@@ -43,11 +44,14 @@
private ChildAttributes myChildAttributes;
private boolean myIsIncomplete = false;
- public SyntheticCodeBlock(final List<Block> subBlocks,
- final Alignment alignment,
+ public SyntheticCodeBlock(List<Block> subBlocks,
+ Alignment alignment,
CommonCodeStyleSettings settings,
+ JavaCodeStyleSettings javaSettings,
Indent indent,
- Wrap wrap) {
+ Wrap wrap)
+ {
+ myJavaSettings = javaSettings;
myIndentContent = indent;
if (subBlocks.isEmpty()) {
LOG.assertTrue(false);
@@ -89,7 +93,7 @@
@Override
public Spacing getSpacing(Block child1, @NotNull Block child2) {
- return JavaSpacePropertyProcessor.getSpacing(AbstractJavaBlock.getTreeNode(child2), mySettings);
+ return JavaSpacePropertyProcessor.getSpacing(AbstractJavaBlock.getTreeNode(child2), mySettings, myJavaSettings);
}
public String toString() {
diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java
index ab62895..57884ac 100644
--- a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java
@@ -107,6 +107,7 @@
return original != null ? original : psiClass;
}
+ @NotNull
@Override
public PsiElement getClsFileNavigationElement(PsiJavaFile clsFile) {
String packageName = clsFile.getPackageName();
@@ -258,12 +259,13 @@
}
@Override
- public void setupCatchBlock(String exceptionName, PsiElement context, PsiCatchSection catchSection) {
+ public void setupCatchBlock(@NotNull String exceptionName, @NotNull PsiType exceptionType, PsiElement context, @NotNull PsiCatchSection catchSection) {
final FileTemplate catchBodyTemplate = FileTemplateManager.getInstance().getCodeTemplate(JavaTemplateUtil.TEMPLATE_CATCH_BODY);
LOG.assertTrue(catchBodyTemplate != null);
final Properties props = new Properties();
props.setProperty(FileTemplate.ATTRIBUTE_EXCEPTION, exceptionName);
+ props.setProperty(FileTemplate.ATTRIBUTE_EXCEPTION_TYPE, exceptionType.getCanonicalText());
if (context != null && context.isPhysical()) {
final PsiDirectory directory = context.getContainingFile().getContainingDirectory();
if (directory != null) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java b/java/java-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java
deleted file mode 100644
index 7c9fcb3..0000000
--- a/java/java-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java
+++ /dev/null
@@ -1,51 +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.
- */
-
-/*
- * @author max
- */
-package com.intellij.psi.impl.compiled;
-
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
-import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiManager;
-import org.jetbrains.annotations.NotNull;
-
-public class ClassFileDecompiler implements BinaryFileDecompiler {
- @Override
- @NotNull
- public CharSequence decompile(final VirtualFile file) {
- assert file.getFileType() == StdFileTypes.CLASS;
-
- final Project[] projects = ProjectManager.getInstance().getOpenProjects();
- if (projects.length == 0) return "";
- final Project project = projects[0];
-
- final ContentBasedFileSubstitutor[] processors = Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME);
- for (ContentBasedFileSubstitutor processor : processors) {
- if (processor.isApplicable(project, file)) {
- return processor.obtainFileText(project, file);
- }
- }
-
- return ClsFileImpl.decompile(PsiManager.getInstance(project), file);
- }
-}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/psi/impl/compiled/DeprecatedClassFileDecompiler.java b/java/java-impl/src/com/intellij/psi/impl/compiled/DeprecatedClassFileDecompiler.java
new file mode 100644
index 0000000..2e4c134
--- /dev/null
+++ b/java/java-impl/src/com/intellij/psi/impl/compiled/DeprecatedClassFileDecompiler.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.impl.compiled;
+
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+/** @deprecated temporary solution, to remove in IDEA 14 */
+@SuppressWarnings("deprecation")
+public class DeprecatedClassFileDecompiler implements ClassFileDecompiler.PlatformDecompiler {
+ @Override
+ public CharSequence decompile(@NotNull VirtualFile file) {
+ Project[] projects = ProjectManager.getInstance().getOpenProjects();
+ if (projects.length > 0) {
+ Project project = projects[0];
+ for (ContentBasedFileSubstitutor processor : Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME)) {
+ if (processor.isApplicable(project, file)) {
+ return processor.obtainFileText(project, file);
+ }
+ }
+ }
+
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java
index ef15196..ca9d77d 100644
--- a/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerImpl.java
@@ -16,42 +16,28 @@
package com.intellij.psi.impl.file.impl;
-import com.intellij.AppTopics;
-import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
-import com.intellij.openapi.roots.*;
+import com.intellij.ide.startup.StartupManagerEx;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.startup.StartupManager;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.util.messages.MessageBus;
-import org.jetbrains.annotations.NotNull;
/**
* @author max
*/
public class JavaFileManagerImpl extends JavaFileManagerBase {
-
public JavaFileManagerImpl(final PsiManagerEx manager, final ProjectRootManager projectRootManager, MessageBus bus,
final StartupManager startupManager) {
super(manager, projectRootManager, bus);
- myConnection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
- @Override
- public void fileWithNoDocumentChanged(@NotNull final VirtualFile file) {
- clearNonRepositoryMaps();
- }
- });
-
-
-
- startupManager.registerStartupActivity(
- new Runnable() {
- @Override
- public void run() {
- initialize();
- }
- }
- );
-
+ if (!((StartupManagerEx)startupManager).startupActivityPassed() &&
+ !ApplicationManager.getApplication().isUnitTestMode() &&
+ !manager.getProject().isDefault()) {
+ Logger.getInstance("#com.intellij.psi.impl.file.impl.JavaFileManagerImpl")
+ .error("Access to psi files should be performed only after startup activity");
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java b/java/java-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java
index fb45938..c7a3117 100644
--- a/java/java-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java
+++ b/java/java-impl/src/com/intellij/psi/impl/light/LightFieldBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -15,7 +15,7 @@
*/
package com.intellij.psi.impl.light;
-import com.intellij.lang.StdLanguages;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.util.IncorrectOperationException;
@@ -26,8 +26,8 @@
* @author Maxim.Medvedev
*/
public class LightFieldBuilder extends LightVariableBuilder<LightFieldBuilder> implements PsiField {
- PsiClass myContainingClass = null;
- PsiExpression myInitializer = null;
+ private PsiClass myContainingClass = null;
+ private PsiExpression myInitializer = null;
private PsiDocComment myDocComment = null;
private boolean myIsDeprecated = false;
@@ -41,7 +41,7 @@
}
public LightFieldBuilder(PsiManager manager, @NotNull String name, @NotNull PsiType type) {
- super(manager, name, type, StdLanguages.JAVA);
+ super(manager, name, type, JavaLanguage.INSTANCE);
}
public LightFieldBuilder setContainingClass(PsiClass psiClass) {
diff --git a/java/java-impl/src/com/intellij/psi/impl/light/LightVariableBuilder.java b/java/java-impl/src/com/intellij/psi/impl/light/LightVariableBuilder.java
index 6922a66..b07425c 100644
--- a/java/java-impl/src/com/intellij/psi/impl/light/LightVariableBuilder.java
+++ b/java/java-impl/src/com/intellij/psi/impl/light/LightVariableBuilder.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.
@@ -78,6 +78,11 @@
return (T)this;
}
+ public T setModifierList(LightModifierList modifierList) {
+ myModifierList = modifierList;
+ return (T)this;
+ }
+
@Override
public boolean hasModifierProperty(@NonNls @NotNull String name) {
return myModifierList.hasModifierProperty(name);
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java
index a281f27..c4b4401 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/PsiCodeFragmentImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -283,7 +283,7 @@
}
@Override
- public void setIntentionActionsFilter(final IntentionActionsFilter filter) {
+ public void setIntentionActionsFilter(@NotNull final IntentionActionsFilter filter) {
myIntentionActionsFilter = filter;
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
index 852c729..9ade1c2 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/ImportHelper.java
@@ -370,7 +370,7 @@
String className = refClass.getQualifiedName();
if (className == null) return true;
- if (!ImportFilter.shouldImport(className)) {
+ if (!ImportFilter.shouldImport(file, className)) {
return false;
}
String packageName = getPackageOrClassName(className);
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
index e5e7741..10d4584 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/codeStyle/JavaCodeStyleManagerImpl.java
@@ -1005,7 +1005,7 @@
}
private boolean isIdentifier(String name) {
- return JavaPsiFacade.getInstance(myProject).getNameHelper().isIdentifier(name, LanguageLevel.HIGHEST);
+ return PsiNameHelper.getInstance(myProject).isIdentifier(name, LanguageLevel.HIGHEST);
}
private CodeStyleSettings getSettings() {
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
index 5e4e42e..08d4405 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/JavaClassReference.java
@@ -452,11 +452,8 @@
Project project = getElement().getProject();
GlobalSearchScope scope = myJavaClassReferenceSet.getProvider().getScope(project);
if (scope == null) {
- final Module module = ModuleUtilCore.findModuleForPsiElement(getElement());
- if (module != null) {
- return module.getModuleWithDependenciesAndLibrariesScope(true);
- }
- return GlobalSearchScope.allScope(project);
+ Module module = ModuleUtilCore.findModuleForPsiElement(getElement());
+ return module != null ? module.getModuleWithDependenciesAndLibrariesScope(true) : GlobalSearchScope.allScope(project);
}
return scope;
}
diff --git a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java
index 5139b49..271eb0c 100644
--- a/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java
+++ b/java/java-impl/src/com/intellij/psi/impl/source/tree/injected/MyTestInjector.java
@@ -312,7 +312,7 @@
if (host instanceof PsiLiteralExpression && ((PsiLiteralExpression)host).getValue() instanceof String) {
PsiVariable variable = PsiTreeUtil.getParentOfType(host, PsiVariable.class);
if (variable == null) return;
- if (host.getParent() instanceof PsiBinaryExpression) return;
+ if (host.getParent() instanceof PsiPolyadicExpression) return;
if ("ql".equals(variable.getName())) {
placesToInject.addPlace(ql, textRangeToInject(host), null, null);
}
diff --git a/java/java-impl/src/com/intellij/psi/util/proximity/KnownElementWeigher.java b/java/java-impl/src/com/intellij/psi/util/proximity/KnownElementWeigher.java
index 4f492e8..ffb122b 100644
--- a/java/java-impl/src/com/intellij/psi/util/proximity/KnownElementWeigher.java
+++ b/java/java-impl/src/com/intellij/psi/util/proximity/KnownElementWeigher.java
@@ -49,12 +49,14 @@
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null) {
String methodName = method.getName();
- if ("finalize".equals(methodName) || "registerNatives".equals(methodName) || "getClass".equals(methodName) ||
- methodName.startsWith("wait") || methodName.startsWith("notify")) {
+ if ("finalize".equals(methodName) || "registerNatives".equals(methodName) || methodName.startsWith("wait") || methodName.startsWith("notify")) {
if (CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName())) {
return -1;
}
}
+ if (isGetClass(method)) {
+ return -1;
+ }
if ("subSequence".equals(methodName)) {
if (CommonClassNames.JAVA_LANG_STRING.equals(containingClass.getQualifiedName())) {
return -1;
@@ -72,6 +74,10 @@
return 0;
}
+ public static boolean isGetClass(PsiMethod method) {
+ return "getClass".equals(method.getName()) && method.getParameterList().getParametersCount() <= 0;
+ }
+
private static Comparable getJdkClassProximity(@Nullable PsiClass element) {
if (element == null || element.getContainingClass() != null) {
return 0;
@@ -81,13 +87,14 @@
if (qname != null) {
String pkg = StringUtil.getPackageName(qname);
if (qname.equals(CommonClassNames.JAVA_LANG_OBJECT)) return 5;
- if (pkg.equals("java.lang")) return 7;
- if (pkg.equals("java.util")) return 6;
+ if (isPopularJdkClass(qname)) return 8;
+ if (pkg.equals("java.lang")) return 6;
+ if (pkg.equals("java.util")) return 7;
if (qname.startsWith("java.lang")) return 5;
if (qname.startsWith("java.util")) return 4;
- if (pkg.equals("javax.swing")) return element instanceof PsiClass ? 3 : 2;
+ if (pkg.equals("javax.swing")) return 3;
if (qname.startsWith("java.")) return 2;
if (qname.startsWith("javax.")) return 1;
if (qname.startsWith("com.")) return -1;
@@ -95,4 +102,14 @@
}
return 0;
}
+
+ private static boolean isPopularJdkClass(String qname) {
+ return qname.equals(CommonClassNames.JAVA_LANG_STRING) ||
+ qname.equals(System.class.getName()) ||
+ qname.equals(CommonClassNames.JAVA_LANG_EXCEPTION) ||
+ qname.equals(CommonClassNames.JAVA_LANG_THROWABLE) ||
+ qname.equals(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION) ||
+ qname.equals(CommonClassNames.JAVA_LANG_RUNNABLE) ||
+ qname.equals(CommonClassNames.JAVA_LANG_CLASS);
+ }
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.java b/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.java
index 7759601..f2bd765 100644
--- a/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.java
+++ b/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,19 +16,21 @@
package com.intellij.refactoring;
import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.util.ResourceBundle;
-public class RefactorJBundle{
- private static final ResourceBundle ourBundle =
- ResourceBundle.getBundle("com.intellij.refactoring.RefactorJBundle");
+public class RefactorJBundle {
- private RefactorJBundle(){
- }
+ public static String message(@NotNull @PropertyKey(resourceBundle = "com.intellij.refactoring.RefactorJBundle") String key,
+ @NotNull Object... params) {
+ return CommonBundle.message(ourBundle, key, params);
+ }
- public static String message(@PropertyKey(resourceBundle = "com.intellij.refactoring.RefactorJBundle")String key,
- Object... params){
- return CommonBundle.message(ourBundle, key, params);
- }
+ private static final ResourceBundle ourBundle =
+ ResourceBundle.getBundle("com.intellij.refactoring.RefactorJBundle");
+
+ private RefactorJBundle() {
+ }
}
diff --git a/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.properties b/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.properties
index 5fe99f8..55482ac 100644
--- a/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.properties
+++ b/java/java-impl/src/com/intellij/refactoring/RefactorJBundle.properties
@@ -159,30 +159,6 @@
control.flow.category=Control Flow
other.category=Other
genericize.uses.in.border=Genericize uses of {0} in {1}
-to.purchase.a.commercial.license.please.visit=To purchase a commercial license, please visit
-enter.license.key.for.refactor.j=Enter license key for Refactor-J
-review.license.terms=Review License terms
-user.name=&User Name:
-license.key=&License Key:
-www.sixthandredriver.com=www.sixthandredriver.com
-i.have.read.the.terms.of.this.license.and.i.accept.them=&I have read the terms of this license, and I accept them.
-i.do.not.accept.the.terms.of.this.license=I &do not accept the terms of this license.
-enter.refactor.j.license.data.title=Enter Refactor-J License Data
-license.renewal.needed=License renewal needed
-license.entered=License Entered
-license.expired=License Expired
-to.purchase.a.license.for.the.latest.version.please.contact.sixth.and.red.river.software=To purchase a license for the latest version, please contact Sixth and Red River Software
-to.purchase.a.new.license.please.contact.sixth.and.red.river.software=To purchase a new license, please contact Sixth and Red River Software
-to.purchase.a.license.for.the.refactor.j.please.contact.sixth.and.red.river.software=To purchase a license for the Refactor-J, please contact Sixth and Red River Software
-invalid.license.data=Invalid License Data
-invalid.license.data.please.try.again=Invalid license data. Please, try again.
-your.refactor.j.license.has.expired=Your Refactor-J license has expired. \n
-your.refactor.j.license.is.for.an.older.version.and.does.not.support.the.currently.installed.version.of.refactor.j=Your Refactor-J license is for an older version, and does not support the currently installed version of Refactor-J. \n
-the.refactor.j.license.entered.is.for.another.product=The Refactor-J license entered is for another product. \n
-to.purchase.a.full.license.please.contact.sixth.and.red.river.software=To purchase a full license, please contact Sixth and Red River Software.
-your.evaluation.license.for.refactor.j.will.expire.in.less.than.a.day.n=Your evaluation license for Refactor-J will expire in less than a day.\n
-your.evaluation.license.for.refactor.j.will.expire.in.one.day=Your evaluation license for Refactor-J will expire in one day.\n
-thank.you.for.supporting.sixth.and.red.river.software=Thank you for supporting Sixth and Red River Software
extract.class=Extract Class
the.selected.class.is.an.interface=The selected class is an interface.
the.selected.class.is.an.annotation.type=The selected class is an annotation type.
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java
index 17cef58..5653701 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/ChangeSignatureProcessor.java
@@ -23,7 +23,6 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
@@ -215,7 +214,7 @@
protected boolean isProcessCovariantOverriders() {
return Messages
.showYesNoDialog(myProject, RefactoringBundle.message("do.you.want.to.process.overriding.methods.with.covariant.return.type"),
- JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE;
+ JavaChangeSignatureHandler.REFACTORING_NAME, Messages.getQuestionIcon()) == Messages.YES;
}
public static void makeEmptyBody(final PsiElementFactory factory, final PsiMethod delegate) throws IncorrectOperationException {
diff --git a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
index df0afa8..2548fbf 100644
--- a/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/changeSignature/JavaChangeSignatureDialog.java
@@ -609,7 +609,7 @@
if (!RefactoringUtil.isResolvableType(((PsiTypeCodeFragment)myReturnTypeCodeFragment).getType())) {
if (Messages.showOkCancelDialog(myProject, RefactoringBundle
.message("changeSignature.cannot.resolve.return.type", myReturnTypeCodeFragment.getText()),
- RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) != 0) {
+ RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) != Messages.OK) {
return EXIT_SILENTLY;
}
}
@@ -620,7 +620,7 @@
if (Messages.showOkCancelDialog(myProject, RefactoringBundle
.message("changeSignature.cannot.resolve.parameter.type", item.typeCodeFragment.getText(), item.parameter.getName()),
RefactoringBundle.message("changeSignature.refactoring.name"), Messages.getWarningIcon()) !=
- 0) {
+ Messages.OK) {
return EXIT_SILENTLY;
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
index 11c77dd..8905ce2 100644
--- a/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/encapsulateFields/EncapsulateFieldsDialog.java
@@ -368,7 +368,7 @@
columnModel.getColumn(FIELD_COLUMN).setCellRenderer(renderer);
columnModel.getColumn(GETTER_COLUMN).setCellRenderer(renderer);
columnModel.getColumn(SETTER_COLUMN).setCellRenderer(renderer);
- columnModel.getColumn(CHECKED_COLUMN).setMaxWidth(new JCheckBox().getPreferredSize().width);
+ TableUtil.setupCheckboxColumn(columnModel.getColumn(CHECKED_COLUMN));
myTable.setPreferredScrollableViewportSize(new Dimension(550, myTable.getRowHeight() * 12));
myTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
diff --git a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java b/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java
index 7dd6ac1..e141735 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractInterface/ExtractInterfaceHandler.java
@@ -31,6 +31,7 @@
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.extractSuperclass.ExtractSuperClassUtil;
import com.intellij.refactoring.lang.ElementsHandler;
+import com.intellij.refactoring.listeners.RefactoringEventListener;
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.DocCommentPolicy;
@@ -139,14 +140,22 @@
String interfaceName,
MemberInfo[] selectedMembers,
DocCommentPolicy javaDocPolicy) throws IncorrectOperationException {
- PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName);
- PsiJavaCodeReferenceElement ref = ExtractSuperClassUtil.createExtendingReference(anInterface, aClass, selectedMembers);
- final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList();
- assert referenceList != null;
- referenceList.add(ref);
- PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, anInterface, selectedMembers, javaDocPolicy);
- pullUpHelper.moveMembersToBase();
- return anInterface;
+ aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
+ .refactoringStarted(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createBeforeData(aClass, selectedMembers));
+ try {
+ PsiClass anInterface = JavaDirectoryService.getInstance().createInterface(targetDir, interfaceName);
+ PsiJavaCodeReferenceElement ref = ExtractSuperClassUtil.createExtendingReference(anInterface, aClass, selectedMembers);
+ final PsiReferenceList referenceList = aClass.isInterface() ? aClass.getExtendsList() : aClass.getImplementsList();
+ assert referenceList != null;
+ referenceList.add(ref);
+ PullUpProcessor pullUpHelper = new PullUpProcessor(aClass, anInterface, selectedMembers, javaDocPolicy);
+ pullUpHelper.moveMembersToBase();
+ return anInterface;
+ }
+ finally {
+ aClass.getProject().getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
+ .refactoringDone(ExtractSuperClassUtil.REFACTORING_EXTRACT_SUPER_ID, ExtractSuperClassUtil.createAfterData(aClass));
+ }
}
private String getCommandName() {
diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHandler.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHandler.java
index 659ebfb..c9a44d9 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHandler.java
@@ -153,8 +153,9 @@
PostprocessReformattingAspect.getInstance(project).postponeFormattingInside(new Runnable() {
public void run() {
try {
- project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
- .refactoringStarted("refactoring.extract.method", new RefactoringEventData());
+ final RefactoringEventData beforeData = new RefactoringEventData();
+ beforeData.addElements(processor.myElements);
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted("refactoring.extract.method", beforeData);
processor.doRefactoring();
diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseProcessor.java
index aae2d48..0d608e7 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperBaseProcessor.java
@@ -25,7 +25,6 @@
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.listeners.RefactoringEventData;
import com.intellij.refactoring.turnRefsToSuper.TurnRefsToSuperProcessorBase;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.RefactoringUIUtil;
@@ -34,14 +33,11 @@
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewDescriptor;
import com.intellij.usageView.UsageViewUtil;
-import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.List;
/**
* @author dsl
@@ -106,34 +102,6 @@
return false;
}
- @Nullable
- @Override
- protected String getRefactoringId() {
- return "refactoring.extractSuper";
- }
-
- @Nullable
- @Override
- protected RefactoringEventData getBeforeData() {
- RefactoringEventData data = new RefactoringEventData();
- data.addElement(myClass);
- data.addMembers(myMemberInfos, new Function<MemberInfo, PsiElement>() {
- @Override
- public PsiElement fun(MemberInfo info) {
- return info.getMember();
- }
- });
- return data;
- }
-
- @Nullable
- @Override
- protected RefactoringEventData getAfterData(UsageInfo[] usages) {
- RefactoringEventData data = new RefactoringEventData();
- data.addElement(myClass);
- return data;
- }
-
@NotNull
protected UsageInfo[] findUsages() {
PsiReference[] refs = ReferencesSearch.search(myClass, GlobalSearchScope.projectScope(myProject), false).toArray(new PsiReference[0]);
diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java
index b457443..bd2c7cb 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperClassUtil.java
@@ -15,7 +15,7 @@
*/
package com.intellij.refactoring.extractSuperclass;
-import com.intellij.codeInsight.generation.OverrideImplementUtil;
+import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
@@ -31,11 +31,14 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.refactoring.listeners.RefactoringEventData;
+import com.intellij.refactoring.listeners.RefactoringEventListener;
import com.intellij.refactoring.memberPullUp.PullUpProcessor;
import com.intellij.refactoring.ui.ConflictsDialog;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.refactoring.util.classMembers.MemberInfo;
+import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
@@ -52,6 +55,8 @@
*/
public class ExtractSuperClassUtil {
private static final Logger LOG = Logger.getInstance("com.intellij.refactoring.extractSuperclass.ExtractSuperClassUtil");
+ public static final String REFACTORING_EXTRACT_SUPER_ID = "refactoring.extractSuper";
+
private ExtractSuperClassUtil() {}
public static PsiClass extractSuperClass(final Project project,
@@ -61,39 +66,57 @@
final MemberInfo[] selectedMemberInfos,
final DocCommentPolicy javaDocPolicy)
throws IncorrectOperationException {
- PsiClass superclass = JavaDirectoryService.getInstance().createClass(targetDirectory, superclassName);
- final PsiModifierList superClassModifierList = superclass.getModifierList();
- assert superClassModifierList != null;
- superClassModifierList.setModifierProperty(PsiModifier.FINAL, false);
- final PsiReferenceList subClassExtends = subclass.getExtendsList();
- assert subClassExtends != null: subclass;
- copyPsiReferenceList(subClassExtends, superclass.getExtendsList());
- // create constructors if neccesary
- PsiMethod[] constructors = getCalledBaseConstructors(subclass);
- if (constructors.length > 0) {
- createConstructorsByPattern(project, superclass, constructors);
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
+ .refactoringStarted(REFACTORING_EXTRACT_SUPER_ID, createBeforeData(subclass, selectedMemberInfos));
+
+ try {
+ PsiClass superclass = JavaDirectoryService.getInstance().createClass(targetDirectory, superclassName);
+ final PsiModifierList superClassModifierList = superclass.getModifierList();
+ assert superClassModifierList != null;
+ superClassModifierList.setModifierProperty(PsiModifier.FINAL, false);
+ final PsiReferenceList subClassExtends = subclass.getExtendsList();
+ if (subClassExtends != null) {
+ copyPsiReferenceList(subClassExtends, superclass.getExtendsList());
+ } else if (subclass instanceof PsiAnonymousClass) {
+ superclass.getExtendsList().add(((PsiAnonymousClass)subclass).getBaseClassReference());
+ }
+
+ // create constructors if neccesary
+ PsiMethod[] constructors = getCalledBaseConstructors(subclass);
+ if (constructors.length > 0) {
+ createConstructorsByPattern(project, superclass, constructors);
+ }
+
+ // clear original class' "extends" list
+ if (subClassExtends != null) {
+ clearPsiReferenceList(subclass.getExtendsList());
+ }
+
+ // make original class extend extracted superclass
+ PsiJavaCodeReferenceElement ref = createExtendingReference(superclass, subclass, selectedMemberInfos);
+ if (subClassExtends != null) {
+ subclass.getExtendsList().add(ref);
+ } else if (subclass instanceof PsiAnonymousClass) {
+ ((PsiAnonymousClass)subclass).getBaseClassReference().replace(ref);
+ }
+
+ PullUpProcessor pullUpHelper = new PullUpProcessor(subclass, superclass, selectedMemberInfos,
+ javaDocPolicy
+ );
+
+ pullUpHelper.moveMembersToBase();
+ pullUpHelper.moveFieldInitializations();
+
+ Collection<MethodSignature> toImplement = OverrideImplementExploreUtil.getMethodSignaturesToImplement(superclass);
+ if (!toImplement.isEmpty()) {
+ superClassModifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
+ }
+ return superclass;
}
-
- // clear original class' "extends" list
- clearPsiReferenceList(subclass.getExtendsList());
-
- // make original class extend extracted superclass
- PsiJavaCodeReferenceElement ref = createExtendingReference(superclass, subclass, selectedMemberInfos);
- subclass.getExtendsList().add(ref);
-
- PullUpProcessor pullUpHelper = new PullUpProcessor(subclass, superclass, selectedMemberInfos,
- javaDocPolicy
- );
-
- pullUpHelper.moveMembersToBase();
- pullUpHelper.moveFieldInitializations();
-
- Collection<MethodSignature> toImplement = OverrideImplementUtil.getMethodSignaturesToImplement(superclass);
- if (!toImplement.isEmpty()) {
- superClassModifierList.setModifierProperty(PsiModifier.ABSTRACT, true);
+ finally {
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_EXTRACT_SUPER_ID, createAfterData(subclass));
}
- return superclass;
}
private static void createConstructorsByPattern(Project project, final PsiClass superclass, PsiMethod[] patternConstructors) throws IncorrectOperationException {
@@ -230,6 +253,7 @@
public static boolean showConflicts(DialogWrapper dialog, MultiMap<PsiElement, String> conflicts, final Project project) {
if (!conflicts.isEmpty()) {
+ fireConflictsEvent(conflicts, project);
ConflictsDialog conflictsDialog = new ConflictsDialog(project, conflicts);
conflictsDialog.show();
final boolean ok = conflictsDialog.isOK();
@@ -238,4 +262,30 @@
}
return true;
}
+
+ private static void fireConflictsEvent(MultiMap<PsiElement, String> conflicts, Project project) {
+ final RefactoringEventData conflictUsages = new RefactoringEventData();
+ conflictUsages.putUserData(RefactoringEventData.CONFLICTS_KEY, conflicts.values());
+ project.getMessageBus()
+ .syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC)
+ .conflictsDetected(REFACTORING_EXTRACT_SUPER_ID, conflictUsages);
+ }
+
+ public static RefactoringEventData createBeforeData(final PsiClass subclassClass, final MemberInfo[] members) {
+ RefactoringEventData data = new RefactoringEventData();
+ data.addElement(subclassClass);
+ data.addMembers(members, new Function<MemberInfo, PsiElement>() {
+ @Override
+ public PsiElement fun(MemberInfo info) {
+ return info.getMember();
+ }
+ });
+ return data;
+ }
+
+ public static RefactoringEventData createAfterData(final PsiClass subClass) {
+ RefactoringEventData data = new RefactoringEventData();
+ data.addElement(subClass);
+ return data;
+ }
}
diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java
index 2c93dec..b8f24bc 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/ExtractSuperclassHandler.java
@@ -25,7 +25,6 @@
import com.intellij.lang.findUsages.DescriptiveNameUtil;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
@@ -70,7 +69,7 @@
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, HelpID.EXTRACT_SUPERCLASS);
return;
}
- if (element instanceof PsiClass && !(element instanceof PsiAnonymousClass)) {
+ if (element instanceof PsiClass) {
invoke(project, new PsiElement[]{element}, dataContext);
return;
}
@@ -108,7 +107,7 @@
}, false);
final ExtractSuperclassDialog dialog =
- new ExtractSuperclassDialog(project, mySubclass, memberInfos, ExtractSuperclassHandler.this);
+ new ExtractSuperclassDialog(project, mySubclass, memberInfos, this);
dialog.show();
if (!dialog.isOK() || !dialog.isExtractSuperclass()) return;
@@ -138,7 +137,7 @@
final MultiMap<PsiElement,String> conflicts = new MultiMap<PsiElement, String>();
if (!ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
public void run() {
- final PsiClass superClass = mySubclass.getExtendsListTypes().length > 0 ? mySubclass.getSuperClass() : null;
+ final PsiClass superClass = mySubclass.getExtendsListTypes().length > 0 || mySubclass instanceof PsiAnonymousClass ? mySubclass.getSuperClass() : null;
conflicts.putAllValues(PullUpConflictsUtil.checkConflicts(infos, mySubclass, superClass, targetPackage, targetDirectory, dialog.getContainmentVerifier(), false));
}
}, RefactoringBundle.message("detecting.possible.conflicts"), true, myProject)) return false;
diff --git a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java
index 817b684..f80af85 100644
--- a/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/extractSuperclass/JavaExtractSuperBaseDialog.java
@@ -27,6 +27,8 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.impl.ElementPresentationUtil;
+import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import com.intellij.refactoring.MoveDestination;
import com.intellij.refactoring.PackageWrapper;
import com.intellij.refactoring.RefactoringBundle;
@@ -96,7 +98,8 @@
protected JTextField createSourceClassField() {
JTextField result = new JTextField();
result.setEditable(false);
- result.setText(mySourceClass.getQualifiedName());
+ final String qualifiedName = mySourceClass.getQualifiedName();
+ result.setText(qualifiedName != null ? qualifiedName : SymbolPresentationUtil.getSymbolPresentableText(mySourceClass));
return result;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java
index a21680e..6c74e8a 100644
--- a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.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.
@@ -851,7 +851,7 @@
UsageViewManager manager = UsageViewManager.getInstance(myProject);
manager.showUsages(
new UsageTarget[]{new PsiElement2UsageTargetAdapter(myClass)},
- UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(myClass), usages),
+ UsageInfoToUsageConverter.convert(new PsiElement[]{myClass}, usages),
presentation
);
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
index 41aa79b..622a9ab 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineLocalHandler.java
@@ -39,6 +39,8 @@
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.listeners.RefactoringEventData;
+import com.intellij.refactoring.listeners.RefactoringEventListener;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.refactoring.util.InlineUtil;
import com.intellij.refactoring.util.RefactoringMessageDialog;
@@ -231,8 +233,14 @@
final Runnable runnable = new Runnable() {
public void run() {
+ final String refactoringId = "refactoring.inline.local.variable";
try{
SmartPsiElementPointer<PsiExpression>[] exprs = new SmartPsiElementPointer[refsToInline.length];
+
+ RefactoringEventData beforeData = new RefactoringEventData();
+ beforeData.addElements(refsToInline);
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(refactoringId, beforeData);
+
final SmartPointerManager pointerManager = SmartPointerManager.getInstance(project);
for(int idx = 0; idx < refsToInline.length; idx++){
PsiJavaCodeReferenceElement refElement = (PsiJavaCodeReferenceElement)refsToInline[idx];
@@ -266,6 +274,11 @@
catch (IncorrectOperationException e){
LOG.error(e);
}
+ finally {
+ final RefactoringEventData afterData = new RefactoringEventData();
+ afterData.addElement(containingClass);
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(refactoringId, afterData);
+ }
}
};
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodHandler.java
index 166e6f2..b84e772 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodHandler.java
@@ -127,7 +127,14 @@
final VirtualFile vFile = method.getContainingFile().getVirtualFile();
ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(vFile);
}
- PsiJavaCodeReferenceElement refElement = reference != null ? (PsiJavaCodeReferenceElement)reference.getElement() : null;
+
+ PsiJavaCodeReferenceElement refElement = null;
+ if (reference != null) {
+ final PsiElement referenceElement = reference.getElement();
+ if (referenceElement instanceof PsiJavaCodeReferenceElement) {
+ refElement = (PsiJavaCodeReferenceElement)referenceElement;
+ }
+ }
InlineMethodDialog dialog = new InlineMethodDialog(project, method, refElement, editor, allowInlineThisOnly);
dialog.show();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java
index aaece25..c9649a0 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineMethodProcessor.java
@@ -357,6 +357,8 @@
result.put(memberContainer, inaccessibleReferenced);
for (PsiMember member : referencedElements) {
if (PsiTreeUtil.isAncestor(elementToInline, member, false)) continue;
+ if (elementToInline instanceof PsiClass &&
+ InheritanceUtil.isInheritorOrSelf((PsiClass)elementToInline, member.getContainingClass(), true)) continue;
if (!PsiUtil.isAccessible(usage.getProject(), member, usageElement, null)) {
inaccessibleReferenced.add(member);
}
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java
index 81c5b69..5046a30 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java
@@ -342,7 +342,15 @@
myConflicts.putValue(expression, "Parameter initializer depends on value which is not available inside method");
}
} else if (element instanceof PsiParameter) {
- myConflicts.putValue(expression, "Parameter initializer depends on callers parameter");
+ boolean bound = false;
+ for (PsiParameter parameter : myMethod.getParameterList().getParameters()) {
+ if (parameter.getType().equals(((PsiParameter)element).getType()) && parameter.getName().equals(((PsiParameter)element).getName())) {
+ bound = true;
+ }
+ }
+ if (!bound) {
+ myConflicts.putValue(expression, "Parameter initializer depends on callers parameter");
+ }
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
index e5c9490..2b28555 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterHandler.java
@@ -20,6 +20,7 @@
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -217,11 +218,15 @@
final RefactoringEventData data = new RefactoringEventData();
data.addElement(psiElement.copy());
- project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, data);
- SameParameterValueInspection.InlineParameterValueFix.inlineSameParameterValue(method, psiParameter, constantExpression);
-
- project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_ID, null);
+ CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+ @Override
+ public void run() {
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(REFACTORING_ID, data);
+ SameParameterValueInspection.InlineParameterValueFix.inlineSameParameterValue(method, psiParameter, constantExpression);
+ project.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringDone(REFACTORING_ID, null);
+ }
+ }, REFACTORING_NAME, null);
}
@Nullable
diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java
index b762395..97ce059 100644
--- a/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineToAnonymousConstructorProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -87,7 +87,7 @@
PsiType substType = classResolveSubstitutor.substitute(mySuperType);
PsiTypeParameter[] typeParams = myClass.getTypeParameters();
- PsiType[] substitutedParameters = new PsiType[typeParams.length];
+ PsiType[] substitutedParameters = PsiType.createArray(typeParams.length);
for(int i=0; i< typeParams.length; i++) {
substitutedParameters [i] = classResolveSubstitutor.substitute(typeParams [i]);
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
index be633c4..e543dd7 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java
@@ -408,8 +408,8 @@
PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
try {
PsiField field = factory.createFieldFromText(pattern.toString(), null);
- field = (PsiField)CodeStyleManager.getInstance(psiManager.getProject()).reformat(field);
field.getTypeElement().replace(factory.createTypeElement(type));
+ field = (PsiField)CodeStyleManager.getInstance(psiManager.getProject()).reformat(field);
if (includeInitializer) {
field.getInitializer().replace(initializerExpr);
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java
index 553610f..071e2cf 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceConstantDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -420,7 +420,7 @@
if (!"".equals (targetClassName) && !Comparing.strEqual(targetClassName, myParentClass.getQualifiedName())) {
newClass = JavaPsiFacade.getInstance(myProject).findClass(targetClassName, GlobalSearchScope.projectScope(myProject));
if (newClass == null) {
- if (Messages.showOkCancelDialog(myProject, RefactoringBundle.message("class.does.not.exist.in.the.project"), IntroduceConstantHandler.REFACTORING_NAME, Messages.getErrorIcon()) != OK_EXIT_CODE) {
+ if (Messages.showOkCancelDialog(myProject, RefactoringBundle.message("class.does.not.exist.in.the.project"), IntroduceConstantHandler.REFACTORING_NAME, Messages.getErrorIcon()) != Messages.OK) {
return;
}
myDestinationClass = new BaseExpressionToFieldHandler.TargetDestination(targetClassName, myParentClass);
@@ -457,7 +457,7 @@
IntroduceFieldHandler.REFACTORING_NAME,
Messages.getWarningIcon()
);
- if (answer != 0) {
+ if (answer != Messages.YES) {
return;
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java
index 27ad6be..09c8cbd 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceField/IntroduceFieldDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -263,7 +263,7 @@
IntroduceFieldHandler.REFACTORING_NAME,
Messages.getWarningIcon()
);
- if (answer != 0) {
+ if (answer != Messages.YES) {
return;
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
index 53162cd..5c6f5d3 100644
--- a/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/introduceVariable/IntroduceVariableBase.java
@@ -175,7 +175,13 @@
final Editor editor,
final int offset,
boolean acceptVoid) {
- Document document = editor.getDocument();
+ return collectExpressions(file, editor.getDocument(), offset, acceptVoid);
+ }
+
+ public static List<PsiExpression> collectExpressions(final PsiFile file,
+ final Document document,
+ final int offset,
+ boolean acceptVoid) {
CharSequence text = document.getCharsSequence();
int correctedOffset = offset;
int textLength = document.getTextLength();
@@ -278,7 +284,7 @@
elementAtStart = PsiTreeUtil.skipSiblingsForward(elementAtStart, PsiWhiteSpace.class, PsiComment.class);
if (elementAtStart == null) {
if (injectedLanguageManager.isInjectedFragment(file)) {
- return getSelectionFromInjectedHost(project, file, injectedLanguageManager);
+ return getSelectionFromInjectedHost(project, file, injectedLanguageManager, startOffset, endOffset);
} else {
return null;
}
@@ -297,7 +303,7 @@
PsiElement elementAt = PsiTreeUtil.findCommonParent(elementAtStart, elementAtEnd);
if (PsiTreeUtil.getParentOfType(elementAt, PsiExpression.class, false) == null) {
if (injectedLanguageManager.isInjectedFragment(file)) {
- return getSelectionFromInjectedHost(project, file, injectedLanguageManager);
+ return getSelectionFromInjectedHost(project, file, injectedLanguageManager, startOffset, endOffset);
}
elementAt = null;
}
@@ -441,10 +447,9 @@
private static PsiExpression getSelectionFromInjectedHost(Project project,
PsiFile file,
- InjectedLanguageManager injectedLanguageManager) {
+ InjectedLanguageManager injectedLanguageManager, int startOffset, int endOffset) {
final PsiLanguageInjectionHost injectionHost = injectedLanguageManager.getInjectionHost(file);
- final TextRange range = injectionHost.getTextRange();
- return getSelectedExpression(project, injectionHost.getContainingFile(), range.getStartOffset(), range.getEndOffset());
+ return getSelectedExpression(project, injectionHost.getContainingFile(), injectedLanguageManager.injectedToHost(file, startOffset), injectedLanguageManager.injectedToHost(file, endOffset));
}
@Nullable
@@ -591,15 +596,36 @@
}
}
- if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return false;
-
final ExpressionOccurrenceManager occurrenceManager = createOccurrenceManager(expr, tempContainer);
final PsiExpression[] occurrences = occurrenceManager.getOccurrences();
final PsiElement anchorStatementIfAll = occurrenceManager.getAnchorStatementForAll();
- final LinkedHashMap<OccurrencesChooser.ReplaceChoice, List<PsiExpression>> occurrencesMap = ContainerUtil.newLinkedHashMap();
- final boolean hasWriteAccess = fillChoices(expr, occurrences, occurrencesMap);
+ final List<PsiExpression> nonWrite = new ArrayList<PsiExpression>();
+ boolean cantReplaceAll = false;
+ boolean cantReplaceAllButWrite = false;
+ for (PsiExpression occurrence : occurrences) {
+ if (!RefactoringUtil.isAssignmentLHS(occurrence)) {
+ nonWrite.add(occurrence);
+ } else if (isFinalVariableOnLHS(occurrence)) {
+ cantReplaceAll = true;
+ } else if (!nonWrite.isEmpty()){
+ cantReplaceAllButWrite = true;
+ cantReplaceAll = true;
+ }
+ }
+ if (!CommonRefactoringUtil.checkReadOnlyStatus(project, file)) return false;
+
+ final LinkedHashMap<OccurrencesChooser.ReplaceChoice, List<PsiExpression>> occurrencesMap = ContainerUtil.newLinkedHashMap();
+ occurrencesMap.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(expr));
+ final boolean hasWriteAccess = occurrences.length > nonWrite.size() && occurrences.length > 1;
+ if (hasWriteAccess && !cantReplaceAllButWrite) {
+ occurrencesMap.put(OccurrencesChooser.ReplaceChoice.NO_WRITE, nonWrite);
+ }
+
+ if (occurrences.length > 1 && !cantReplaceAll) {
+ occurrencesMap.put(OccurrencesChooser.ReplaceChoice.ALL, Arrays.asList(occurrences));
+ }
final boolean inFinalContext = occurrenceManager.isInFinalContext();
final InputValidator validator = new InputValidator(this, project, anchorStatementIfAll, anchorStatement, occurrenceManager);
@@ -608,8 +634,7 @@
final Pass<OccurrencesChooser.ReplaceChoice> callback = new Pass<OccurrencesChooser.ReplaceChoice>() {
@Override
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
- final boolean allOccurences = choice != OccurrencesChooser.ReplaceChoice.NO;
- final PsiElement chosenAnchor = allOccurences ? anchorStatementIfAll : anchorStatement;
+ final boolean allOccurences = choice == OccurrencesChooser.ReplaceChoice.ALL || choice == OccurrencesChooser.ReplaceChoice.NO_WRITE;
final Ref<SmartPsiElementPointer<PsiVariable>> variable = new Ref<SmartPsiElementPointer<PsiVariable>>();
final Editor topLevelEditor;
@@ -619,8 +644,16 @@
topLevelEditor = editor;
}
- final IntroduceVariableSettings settings =
- getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, chosenAnchor, choice);
+ final IntroduceVariableSettings settings;
+ final PsiElement chosenAnchor;
+ if (choice != null) {
+ chosenAnchor = chooseAnchor(allOccurences, choice == OccurrencesChooser.ReplaceChoice.NO_WRITE, nonWrite, anchorStatementIfAll, anchorStatement);
+ settings = getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, chosenAnchor, choice);
+ }
+ else {
+ settings = getSettings(project, topLevelEditor, expr, occurrences, typeSelectorManager, inFinalContext, hasWriteAccess, validator, anchorStatement, choice);
+ chosenAnchor = chooseAnchor(settings.isReplaceAllOccurrences(), hasWriteAccess, nonWrite, anchorStatementIfAll, anchorStatement);
+ }
if (!settings.isOK()) {
wasSucceed[0] = false;
return;
@@ -637,8 +670,7 @@
}
}
final String expressionText = expr.getText();
- final Runnable runnable =
- introduce(project, expr, topLevelEditor, anchorStatement, tempContainer, occurrences, anchorStatementIfAll, settings, variable);
+ final Runnable runnable = introduce(project, expr, topLevelEditor, chosenAnchor, occurrences, settings, variable);
CommandProcessor.getInstance().executeCommand(
project,
new Runnable() {
@@ -652,7 +684,7 @@
final JavaVariableInplaceIntroducer renamer =
new JavaVariableInplaceIntroducer(project, expression, topLevelEditor, elementToRename, cantChangeFinalModifier,
typeSelectorManager.getTypesForAll().length > 1, exprMarker, occurrenceMarkers,
- IntroduceVariableBase.REFACTORING_NAME);
+ REFACTORING_NAME);
renamer.initInitialText(expressionText);
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(topLevelEditor.getDocument());
renamer.performInplaceRefactoring(new LinkedHashSet<String>(Arrays.asList(suggestedName.names)));
@@ -672,6 +704,24 @@
return wasSucceed[0];
}
+ protected PsiElement chooseAnchor(boolean allOccurences,
+ boolean hasWriteAccess,
+ List<PsiExpression> nonWrite,
+ PsiElement anchorStatementIfAll,
+ PsiElement anchorStatement) {
+ if (allOccurences) {
+ if (hasWriteAccess) {
+ return RefactoringUtil.getAnchorElementForMultipleExpressions(nonWrite.toArray(new PsiExpression[nonWrite.size()]), null);
+ }
+ else {
+ return anchorStatementIfAll;
+ }
+ }
+ else {
+ return anchorStatement;
+ }
+ }
+
protected boolean isInplaceAvailableInTestMode() {
return false;
}
@@ -717,50 +767,14 @@
return parent3 instanceof JspHolderMethod;
}
- /**
- * @return true if write usages found
- */
- private static boolean fillChoices(final PsiExpression expr,
- final PsiExpression[] occurrences,
- final LinkedHashMap<OccurrencesChooser.ReplaceChoice, List<PsiExpression>> occurrencesMap) {
- occurrencesMap.put(OccurrencesChooser.ReplaceChoice.NO, Collections.singletonList(expr));
-
- final List<PsiExpression> nonWrite = new ArrayList<PsiExpression>();
- boolean cantReplaceAll = false;
- for (PsiExpression occurrence : occurrences) {
- if (!RefactoringUtil.isAssignmentLHS(occurrence)) {
- nonWrite.add(occurrence);
- } else if (isFinalVariableOnLHS(occurrence)) {
- cantReplaceAll = true;
- }
- }
- final boolean hasWriteAccess = occurrences.length > nonWrite.size() && occurrences.length > 1;
- if (hasWriteAccess) {
- occurrencesMap.put(OccurrencesChooser.ReplaceChoice.NO_WRITE, nonWrite);
- }
-
- if (occurrences.length > 1 && !cantReplaceAll) {
- occurrencesMap.put(OccurrencesChooser.ReplaceChoice.ALL, Arrays.asList(occurrences));
- }
- return hasWriteAccess;
- }
-
private static Runnable introduce(final Project project,
final PsiExpression expr,
final Editor editor,
- PsiElement anchorStatement,
- PsiElement tempContainer,
+ final PsiElement anchorStatement,
final PsiExpression[] occurrences,
- PsiElement anchorStatementIfAll,
final IntroduceVariableSettings settings,
final Ref<SmartPsiElementPointer<PsiVariable>> variable) {
- if (settings.isReplaceAllOccurrences()) {
- anchorStatement = anchorStatementIfAll;
- tempContainer = anchorStatement.getParent();
- }
-
- final PsiElement container = tempContainer;
-
+ final PsiElement container = anchorStatement.getParent();
PsiElement child = anchorStatement;
if (!RefactoringUtil.isLoopOrIf(container)) {
child = locateAnchor(child);
@@ -798,7 +812,6 @@
final PsiCodeBlock newDeclarationScope = PsiTreeUtil.getParentOfType(container, PsiCodeBlock.class, false);
final FieldConflictsResolver fieldConflictsResolver = new FieldConflictsResolver(settings.getEnteredName(), newDeclarationScope);
- final PsiElement finalAnchorStatement = anchorStatement;
return new Runnable() {
public void run() {
try {
@@ -871,7 +884,7 @@
}
}
- declaration = (PsiDeclarationStatement) RefactoringUtil.putStatementInLoopBody(declaration, container, finalAnchorStatement);
+ declaration = (PsiDeclarationStatement) RefactoringUtil.putStatementInLoopBody(declaration, container, anchorStatement);
declaration = (PsiDeclarationStatement)JavaCodeStyleManager.getInstance(project).shortenClassReferences(declaration);
PsiVariable var = (PsiVariable) declaration.getDeclaredElements()[0];
PsiUtil.setModifierProperty(var, PsiModifier.FINAL, settings.isDeclareFinal());
diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java
index 40e1d5e..fa471df 100644
--- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeParameterizedStaticDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -219,7 +219,7 @@
}
protected boolean validateData() {
- int ret = 0;
+ int ret = Messages.YES;
if (isMakeClassParameter()) {
final PsiMethod methodWithParameter = checkParameterDoesNotExist();
if (methodWithParameter != null) {
@@ -230,7 +230,7 @@
myClassParameterNameInputField.requestFocusInWindow();
}
}
- return ret == 0;
+ return ret == Messages.YES;
}
private PsiMethod checkParameterDoesNotExist() {
@@ -272,7 +272,7 @@
}
private JComboBox createComboBoxForName() {
- final ComboBox combobox = new ComboBox(myNameSuggestions,-1);
+ final ComboBox combobox = new ComboBox(myNameSuggestions);
combobox.setEditable(true);
combobox.setSelectedIndex(0);
diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticHandler.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticHandler.java
index 91497a3..fde9098 100644
--- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeStaticHandler.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,8 +26,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -50,6 +48,7 @@
public static final String REFACTORING_NAME = RefactoringBundle.message("make.method.static.title");
private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.makeMethodStatic.MakeMethodStaticHandler");
+ @Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file, DataContext dataContext) {
PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
editor.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
@@ -71,6 +70,7 @@
invoke(project, new PsiElement[]{element}, dataContext);
}
+ @Override
public void invoke(@NotNull final Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
if(elements.length != 1 || !(elements[0] instanceof PsiTypeParameterListOwner)) return;
@@ -108,10 +108,7 @@
@Override
public boolean process(PsiReference reference) {
final PsiElement element = reference.getElement();
- if (element instanceof PsiMethodReferenceExpression) {
- return false;
- }
- return true;
+ return !(element instanceof PsiMethodReferenceExpression);
}
});
}
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java
index 0110c55..b92c5f5 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPullUp/PullUpDialog.java
@@ -180,11 +180,12 @@
@Override
public boolean isMemberEnabled(MemberInfo member) {
- PsiClass currentSuperClass = getSuperClass();
+ final PsiClass currentSuperClass = getSuperClass();
if(currentSuperClass == null) return true;
if (myMemberInfoStorage.getDuplicatedMemberInfos(currentSuperClass).contains(member)) return false;
if (myMemberInfoStorage.getExtending(currentSuperClass).contains(member.getMember())) return false;
- if (!currentSuperClass.isInterface()) return true;
+ final boolean isInterface = currentSuperClass.isInterface();
+ if (!isInterface) return true;
PsiElement element = member.getMember();
if (element instanceof PsiClass && ((PsiClass) element).isInterface()) return true;
@@ -192,13 +193,11 @@
return ((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC);
}
if (element instanceof PsiMethod) {
- if (currentSuperClass.isInterface()) {
- final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(currentSuperClass, myClass, PsiSubstitutor.EMPTY);
- final MethodSignature signature = ((PsiMethod) element).getSignature(superSubstitutor);
- final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(currentSuperClass, signature, false);
- if (superClassMethod != null) return false;
- }
- return !((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC);
+ final PsiSubstitutor superSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(currentSuperClass, myClass, PsiSubstitutor.EMPTY);
+ final MethodSignature signature = ((PsiMethod) element).getSignature(superSubstitutor);
+ final PsiMethod superClassMethod = MethodSignatureUtil.findMethodBySignature(currentSuperClass, signature, false);
+ if (superClassMethod != null) return false;
+ return !((PsiModifierListOwner) element).hasModifierProperty(PsiModifier.STATIC) || PsiUtil.isLanguageLevel8OrHigher(currentSuperClass);
}
return true;
}
@@ -218,8 +217,9 @@
PsiClass currentSuperClass = getSuperClass();
if(currentSuperClass == null) return false;
if (currentSuperClass.isInterface()) {
- if (member.getMember() instanceof PsiMethod) {
- return true;
+ final PsiMember psiMember = member.getMember();
+ if (psiMember instanceof PsiMethod) {
+ return !psiMember.hasModifierProperty(PsiModifier.STATIC);
}
}
return false;
diff --git a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
index 532e0b9..d6f7367 100644
--- a/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/memberPushDown/PushDownProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
@@ -134,7 +133,7 @@
if (myClass.isEnum() || myClass.hasModifierProperty(PsiModifier.FINAL)) {
if (Messages.showOkCancelDialog((myClass.isEnum() ? "Enum " + myClass.getQualifiedName() + " doesn't have constants to inline to. " : "Final class " + myClass.getQualifiedName() + "does not have inheritors. ") +
"Pushing members down will result in them being deleted. " +
- "Would you like to proceed?", JavaPushDownHandler.REFACTORING_NAME, Messages.getWarningIcon()) != DialogWrapper.OK_EXIT_CODE) {
+ "Would you like to proceed?", JavaPushDownHandler.REFACTORING_NAME, Messages.getWarningIcon()) != Messages.OK) {
return false;
}
} else {
@@ -143,7 +142,7 @@
RefactoringBundle.message("class.0.does.not.have.inheritors", myClass.getQualifiedName());
final String message = noInheritors + "\n" + RefactoringBundle.message("push.down.will.delete.members");
final int answer = Messages.showYesNoCancelDialog(message, JavaPushDownHandler.REFACTORING_NAME, Messages.getWarningIcon());
- if (answer == DialogWrapper.OK_EXIT_CODE) {
+ if (answer == Messages.YES) {
myCreateClassDlg = CreateSubclassAction.chooseSubclassToCreate(myClass);
if (myCreateClassDlg != null) {
pushDownConflicts.checkTargetClassConflicts(null, false, myCreateClassDlg.getTargetDirectory());
@@ -151,7 +150,7 @@
} else {
return false;
}
- } else if (answer != 1) return false;
+ } else if (answer != Messages.NO) return false;
}
}
Runnable runnable = new Runnable() {
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java
index 8719d9a..2bf5f27 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/JavaMoveClassesOrPackagesHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -168,15 +168,15 @@
RefactoringBundle.message("move.current.directory"),
RefactoringBundle.message("move.directories"),
CommonBundle.getCancelButtonText(), Messages.getWarningIcon());
- if (ret == 0) {
+ if (ret == Messages.YES) {
moveAsDirectory(project, targetContainer, callback, directories);
}
- else if (ret == 1) {
+ else if (ret == Messages.NO) {
moveAsDirectory(project, targetContainer, callback, projectDirectories);
}
}
else if (Messages.showOkCancelDialog(project, prompt + "?", RefactoringBundle.message("warning.title"),
- Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getWarningIcon()) == Messages.OK) {
moveAsDirectory(project, targetContainer, callback, directories);
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java
index 30cef8b..c5caa4c 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveClassesOrPackages/MoveClassesOrPackagesDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -32,6 +32,7 @@
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
@@ -175,7 +176,8 @@
myWithBrowseButtonReference = createPackageChooser();
myClassPackageChooser = createPackageChooser();
- myInnerClassChooser = new ClassNameReferenceEditor(myProject, null, ProjectScope.getProjectScope(myProject));
+ GlobalSearchScope scope = JavaProjectRootsUtil.getScopeWithoutGeneratedSources(ProjectScope.getProjectScope(myProject), myProject);
+ myInnerClassChooser = new ClassNameReferenceEditor(myProject, null, scope);
myInnerClassChooser.addDocumentListener(new DocumentAdapter() {
public void documentChanged(DocumentEvent e) {
validateButtons();
@@ -499,7 +501,7 @@
if (!targetPackage.exists()) {
final int ret = Messages.showYesNoDialog(myProject, RefactoringBundle.message("package.does.not.exist", packageName),
RefactoringBundle.message("move.title"), Messages.getQuestionIcon());
- if (ret != 0) return null;
+ if (ret != Messages.YES) return null;
}
return ((DestinationFolderComboBox)myDestinationFolderCB).selectDirectory(targetPackage, mySuggestToMoveToAnotherRoot);
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java
index 1196d73..b839f3b 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodDialogBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -121,7 +121,7 @@
final int result = Messages.showYesNoDialog(project, message, myRefactoringName,
Messages.getQuestionIcon());
- if (result != 0) return false;
+ if (result != Messages.YES) return false;
}
return true;
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java
index 921ce85..a6f6e78 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveInstanceMethod/MoveInstanceMethodHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,13 +18,10 @@
import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -121,7 +118,7 @@
final String suggestToMakeStaticMessage = "Would you like to make method \'" + method.getName() + "\' static and then move?";
if (Messages
.showYesNoCancelDialog(project, message + ". " + suggestToMakeStaticMessage,
- REFACTORING_NAME, Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ REFACTORING_NAME, Messages.getErrorIcon()) == Messages.YES) {
MakeStaticHandler.invoke(method);
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersDialog.java b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersDialog.java
index 0fd4474..ab1bc8a 100644
--- a/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/move/moveMembers/MoveMembersDialog.java
@@ -348,7 +348,7 @@
MoveMembersImpl.REFACTORING_NAME,
Messages.getQuestionIcon()
);
- if (answer != 0) return null;
+ if (answer != Messages.YES) return null;
final Ref<IncorrectOperationException> eRef = new Ref<IncorrectOperationException>();
final PsiClass newClass = ApplicationManager.getApplication().runWriteAction(new Computable<PsiClass>() {
public PsiClass compute() {
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java
index 4430538..85f26f1 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/RenameJavaVariableProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -239,7 +239,7 @@
private static boolean askToRenameAccesors(PsiMethod getter, PsiMethod setter, String newName, final Project project) {
if (ApplicationManager.getApplication().isUnitTestMode()) return false;
String text = RefactoringMessageUtil.getGetterSetterMessage(newName, RefactoringBundle.message("rename.title"), getter, setter);
- return Messages.showYesNoDialog(project, text, RefactoringBundle.message("rename.title"), Messages.getQuestionIcon()) != 0;
+ return Messages.showYesNoDialog(project, text, RefactoringBundle.message("rename.title"), Messages.getQuestionIcon()) != Messages.YES;
}
private static void addOverriddenAndImplemented(PsiMethod methodPrototype, final String newName, final Map<PsiElement, String> allRenames) {
diff --git a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticUsageRenamingDialog.java b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticUsageRenamingDialog.java
index e3060ed..152c037 100644
--- a/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticUsageRenamingDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/rename/naming/AutomaticUsageRenamingDialog.java
@@ -15,22 +15,21 @@
*/
package com.intellij.refactoring.rename.naming;
+import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.refactoring.RefactoringBundle;
import com.intellij.ui.*;
import com.intellij.ui.components.panels.ValidatingComponent;
-import com.intellij.util.ui.Table;
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.ide.IdeBundle;
+import com.intellij.ui.table.JBTable;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
@@ -49,7 +48,7 @@
private boolean[] myShouldRename;
private String[] myNewNames;
private MyTableModel myTableModel;
- private Table myTable;
+ private JBTable myTable;
private DocumentAdapter myCellEditorListener;
private ValidatingComponent myValidatingComponent;
@@ -80,6 +79,7 @@
return getElements().size();
}
+ @Override
protected JComponent createNorthPanel() {
final Box box = Box.createHorizontalBox();
box.add(new JLabel(myRenamer.getDialogDescription()));
@@ -87,6 +87,7 @@
return box;
}
+ @Override
public void show() {
if (ApplicationManager.getApplication().isUnitTestMode()) return;
super.show();
@@ -119,7 +120,7 @@
return isChecked(element) ? myRenamer.getErrorText(element) : null;
}
- private SimpleTextAttributes highlightIfNeeded(SimpleTextAttributes attributes, String errorText) {
+ private static SimpleTextAttributes highlightIfNeeded(SimpleTextAttributes attributes, String errorText) {
if (errorText != null) {
Color errorColor = SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor();
int style = attributes.getStyle() | SimpleTextAttributes.STYLE_ITALIC | SimpleTextAttributes.STYLE_WAVED;
@@ -128,25 +129,29 @@
return attributes;
}
+ @Override
public JComponent getPreferredFocusedComponent() {
return myTable;
}
+ @Override
protected JComponent createCenterPanel() {
final Box box = Box.createVerticalBox();
setupTable();
myTableModel.addTableModelListener(new TableModelListener() {
+ @Override
public void tableChanged(TableModelEvent e) {
handleChanges();
}
});
- setupCheckColumn();
+ TableUtil.setupCheckboxColumn(myTable, CHECK_COLUMN);
setupOldNameColumn();
setupNewNameColumn();
myValidatingComponent = new ValidatingComponent() {
+ @Override
protected JComponent createMainComponent() {
return ScrollPaneFactory.createScrollPane(myTable);
}
@@ -163,6 +168,7 @@
final JButton deselectAllButton = new JButton(RefactoringBundle.message("unselect.all.button"));
buttonBox.add(deselectAllButton);
selectAllButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < getElementCount(); i++) {
myShouldRename[i] = true;
@@ -173,6 +179,7 @@
selectAllButton.setMnemonic('S');
deselectAllButton.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
for (int i = 0; i < getElementCount(); i++) {
myShouldRename[i] = false;
@@ -189,11 +196,12 @@
}
private void setupTable() {
- myTable = new Table();
+ myTable = new JBTable();
myTableModel = new MyTableModel();
myTable.setModel(myTableModel);
myTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
public void valueChanged(ListSelectionEvent e) {
refreshValidatingComponent();
}
@@ -206,6 +214,7 @@
private void setupNewNameColumn() {
myTable.getColumnModel().getColumn(NEW_NAME_COLUMN).setCellRenderer(new ColoredTableCellRenderer() {
+ @Override
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
T element = getElements().get(row);
String errorText = getErrorText(element);
@@ -217,16 +226,19 @@
final JTextField textField = new JTextField("");
textField.setBorder(new EmptyBorder(0, 0, 0, 0));
myTable.getColumnModel().getColumn(NEW_NAME_COLUMN).setCellEditor(new DefaultCellEditor(textField) {
+ @Override
public boolean stopCellEditing() {
removeListener(textField);
return super.stopCellEditing();
}
+ @Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, final int row, final int column) {
super.getTableCellEditorComponent(table, value, isSelected, row, column);
removeListener(textField);
myCellEditorListener = new DocumentAdapter() {
+ @Override
protected void textChanged(DocumentEvent e) {
myTableModel.setValueAt(getCellEditorValue(), row, column);
setChecked(row, true);
@@ -257,7 +269,9 @@
private void setupOldNameColumn() {
myTable.getColumnModel().getColumn(OLD_NAME_COLUMN).setCellRenderer(new ColoredTableCellRenderer() {
+ @Override
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
+ //noinspection unchecked
T element = (T) value;
setToolTipText(getErrorText(element));
append(myRenamer.getName(element), SimpleTextAttributes.REGULAR_ATTRIBUTES);
@@ -269,13 +283,6 @@
});
}
- private void setupCheckColumn() {
- TableColumn column = myTable.getColumnModel().getColumn(CHECK_COLUMN);
- int checkBoxWidth = new JCheckBox().getPreferredSize().width;
- column.setMaxWidth(checkBoxWidth);
- column.setMinWidth(checkBoxWidth);
- }
-
private void removeListener(JTextField textField) {
if (myCellEditorListener != null) {
textField.getDocument().removeDocumentListener(myCellEditorListener);
@@ -286,6 +293,7 @@
return new SimpleTextAttributes(SimpleTextAttributes.STYLE_ITALIC | attributes.getStyle(), attributes.getFgColor(), attributes.getWaveColor());
}
+ @Override
protected void doOKAction() {
TableUtil.stopEditing(myTable);
handleChanges();
@@ -333,14 +341,17 @@
myTable.getActionMap().put("enter", new EnterAction());
}
+ @Override
public int getColumnCount() {
return 3;
}
+ @Override
public int getRowCount() {
return getElementCount();
}
+ @Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch(columnIndex) {
case CHECK_COLUMN:
@@ -355,6 +366,7 @@
}
}
+ @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
switch(columnIndex) {
case CHECK_COLUMN:
@@ -370,10 +382,12 @@
repaintTable();
}
+ @Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
return columnIndex != OLD_NAME_COLUMN;
}
+ @Override
@Nullable
public Class getColumnClass(int columnIndex) {
switch(columnIndex) {
@@ -384,6 +398,7 @@
}
}
+ @Override
public String getColumnName(int column) {
switch(column) {
case OLD_NAME_COLUMN:
@@ -396,6 +411,7 @@
}
private class MySpaceAction extends AbstractAction {
+ @Override
public void actionPerformed(ActionEvent e) {
if (myTable.isEditing()) return;
@@ -410,6 +426,7 @@
}
private class EnterAction extends AbstractAction {
+ @Override
public void actionPerformed(ActionEvent e) {
if (!myTable.isEditing()) {
doOKAction();
diff --git a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryHandler.java b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryHandler.java
index ffc2787..2c9424a 100644
--- a/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/replaceConstructorWithFactory/ReplaceConstructorWithFactoryHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,7 +17,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.project.Project;
@@ -121,7 +120,7 @@
RefactoringBundle.message("would.you.like.to.replace.default.constructor.of.0.with.factory.method", aClass.getQualifiedName()),
REFACTORING_NAME, Messages.getQuestionIcon()
);
- if (answer != 0) return;
+ if (answer != Messages.YES) return;
if (!CommonRefactoringUtil.checkReadOnlyStatus(myProject, aClass)) return;
new ReplaceConstructorWithFactoryDialog(myProject, null, aClass).show();
}
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
index 46b604e..09d752f 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/JavaSafeDeleteProcessor.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.
@@ -23,7 +23,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
@@ -140,7 +139,7 @@
if (parametersToDelete.size() > 1 && !ApplicationManager.getApplication().isUnitTestMode()) {
String message = RefactoringBundle.message("0.is.a.part.of.method.hierarchy.do.you.want.to.delete.multiple.parameters", UsageViewUtil.getLongName(method));
if (Messages.showYesNoDialog(project, message, SafeDeleteHandler.REFACTORING_NAME,
- Messages.getQuestionIcon()) != DialogWrapper.OK_EXIT_CODE) return null;
+ Messages.getQuestionIcon()) != Messages.YES) return null;
}
return parametersToDelete;
}
@@ -171,7 +170,7 @@
}
return manager.showUsages(targets,
- UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(elements),
+ UsageInfoToUsageConverter.convert(elements,
others.toArray(new UsageInfo[others.size()])),
presentation
);
@@ -204,7 +203,7 @@
if (askUser && (getters != null || setter != null)) {
final String message =
RefactoringMessageUtil.getGetterSetterMessage(field.getName(), RefactoringBundle.message("delete.title"), getters != null ? getters[0] : null, setter);
- if (!ApplicationManager.getApplication().isUnitTestMode() && Messages.showYesNoDialog(project, message, RefactoringBundle.message("safe.delete.title"), Messages.getQuestionIcon()) != 0) {
+ if (!ApplicationManager.getApplication().isUnitTestMode() && Messages.showYesNoDialog(project, message, RefactoringBundle.message("safe.delete.title"), Messages.getQuestionIcon()) != Messages.YES) {
getters = null;
setter = null;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java
index 4217ace..427e669 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/OverridingMethodsDialog.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.
@@ -23,12 +23,15 @@
import com.intellij.openapi.util.Disposer;
import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.safeDelete.usageInfo.SafeDeleteOverridingMethodUsageInfo;
import com.intellij.ui.BooleanTableCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.TableUtil;
import com.intellij.usageView.UsageInfo;
+import com.intellij.usages.UsageViewPresentation;
import com.intellij.usages.impl.UsagePreviewPanel;
import com.intellij.util.ui.Table;
import org.jetbrains.annotations.NonNls;
@@ -38,6 +41,7 @@
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionEvent;
@@ -70,12 +74,12 @@
for (int i = 0; i < myMethodText.length; i++) {
myMethodText[i] = PsiFormatUtil.formatMethod(
((SafeDeleteOverridingMethodUsageInfo) myOverridingMethods.get(i)).getOverridingMethod(),
- PsiSubstitutor.EMPTY, PsiFormatUtil.SHOW_CONTAINING_CLASS
- | PsiFormatUtil.SHOW_NAME | PsiFormatUtil.SHOW_PARAMETERS | PsiFormatUtil.SHOW_TYPE,
- PsiFormatUtil.SHOW_TYPE
+ PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_CONTAINING_CLASS
+ | PsiFormatUtilBase.SHOW_NAME | PsiFormatUtilBase.SHOW_PARAMETERS | PsiFormatUtilBase.SHOW_TYPE,
+ PsiFormatUtilBase.SHOW_TYPE
);
}
- myUsagePreviewPanel = new UsagePreviewPanel(project);
+ myUsagePreviewPanel = new UsagePreviewPanel(project, new UsageViewPresentation());
setTitle(RefactoringBundle.message("unused.overriding.methods.title"));
init();
}
@@ -130,11 +134,9 @@
TableColumnModel columnModel = myTable.getColumnModel();
// columnModel.getColumn(DISPLAY_NAME_COLUMN).setCellRenderer(new MemberSelectionTable.MyTableRenderer());
- final int checkBoxWidth = new JCheckBox().getPreferredSize().width;
- columnModel.getColumn(CHECK_COLUMN).setCellRenderer(new BooleanTableCellRenderer());
- columnModel.getColumn(CHECK_COLUMN).setMaxWidth(checkBoxWidth);
- columnModel.getColumn(CHECK_COLUMN).setMinWidth(checkBoxWidth);
-
+ TableColumn checkboxColumn = columnModel.getColumn(CHECK_COLUMN);
+ TableUtil.setupCheckboxColumn(checkboxColumn);
+ checkboxColumn.setCellRenderer(new BooleanTableCellRenderer());
// make SPACE check/uncheck selected rows
@NonNls InputMap inputMap = myTable.getInputMap();
diff --git a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteReferenceJavaDeleteUsageInfo.java b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteReferenceJavaDeleteUsageInfo.java
index dbac6e9..a248352 100644
--- a/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteReferenceJavaDeleteUsageInfo.java
+++ b/java/java-impl/src/com/intellij/refactoring/safeDelete/usageInfo/SafeDeleteReferenceJavaDeleteUsageInfo.java
@@ -15,9 +15,16 @@
*/
package com.intellij.refactoring.safeDelete.usageInfo;
+import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpressionStatement;
+import com.intellij.psi.PsiStatement;
+import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
+import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.refactoring.safeDelete.ImportSearcher;
+import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.IncorrectOperationException;
/**
@@ -48,7 +55,12 @@
importStatement.delete();
}
else {
- element.delete();
+ if (element instanceof PsiExpressionStatement && RefactoringUtil.isLoopOrIf(element.getParent())) {
+ final PsiStatement emptyTest = JavaPsiFacade.getInstance(getProject()).getElementFactory().createStatementFromText(";", null);
+ element.replace(emptyTest);
+ } else {
+ element.delete();
+ }
}
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/PsiTypeVariableFactory.java b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/PsiTypeVariableFactory.java
index 35c5d72..e9a53aa 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/PsiTypeVariableFactory.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/PsiTypeVariableFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -62,6 +62,7 @@
private final int myIndex = myCurrent++;
private final PsiElement myContext = context;
+ @Override
public boolean isValidInContext(final PsiType type) {
if (myContext == null) {
return true;
@@ -72,14 +73,17 @@
}
return type.accept(new PsiTypeVisitor<Boolean>() {
+ @Override
public Boolean visitType(final PsiType type) {
return Boolean.TRUE;
}
+ @Override
public Boolean visitArrayType(final PsiArrayType arrayType) {
return arrayType.getDeepComponentType().accept(this);
}
+ @Override
public Boolean visitWildcardType(final PsiWildcardType wildcardType) {
final PsiType bound = wildcardType.getBound();
@@ -90,6 +94,7 @@
return Boolean.TRUE;
}
+ @Override
public Boolean visitClassType(final PsiClassType classType) {
final PsiClassType.ClassResolveResult result = classType.resolveGenerics();
final PsiClass aClass = result.getElement();
@@ -143,33 +148,43 @@
}).booleanValue();
}
+ @Override
+ @NotNull
public String getPresentableText() {
return "$" + myIndex;
}
+ @Override
+ @NotNull
public String getCanonicalText() {
return getPresentableText();
}
+ @Override
+ @NotNull
public String getInternalCanonicalText() {
return getCanonicalText();
}
+ @Override
public boolean isValid() {
return true;
}
- public boolean equalsToText(String text) {
+ @Override
+ public boolean equalsToText(@NotNull String text) {
return text.equals(getPresentableText());
}
+ @Override
public GlobalSearchScope getResolveScope() {
return null;
}
+ @Override
@NotNull
public PsiType[] getSuperTypes() {
- return new PsiType[0];
+ return EMPTY_ARRAY;
}
public boolean equals(Object o) {
@@ -187,6 +202,7 @@
return myIndex;
}
+ @Override
public int getIndex() {
return myIndex;
}
diff --git a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/ResolverTree.java b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/ResolverTree.java
index d513ec1..7279b6d 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/ResolverTree.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeCook/deductive/resolver/ResolverTree.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -78,6 +78,7 @@
private static class PsiTypeVarCollector extends PsiExtendedTypeVisitor {
final HashSet<PsiTypeVariable> mySet = new HashSet<PsiTypeVariable>();
+ @Override
public Object visitTypeVariable(final PsiTypeVariable var) {
mySet.add(var);
@@ -209,10 +210,12 @@
}
final DFSTBuilder<PsiTypeVariable> dfstBuilder = new DFSTBuilder<PsiTypeVariable>(new Graph<PsiTypeVariable>() {
+ @Override
public Collection<PsiTypeVariable> getNodes() {
return nodes;
}
+ @Override
public Iterator<PsiTypeVariable> getIn(final PsiTypeVariable n) {
final HashSet<PsiTypeVariable> in = ins.get(n);
@@ -223,6 +226,7 @@
return in.iterator();
}
+ @Override
public Iterator<PsiTypeVariable> getOut(final PsiTypeVariable n) {
final HashSet<PsiTypeVariable> out = outs.get(n);
@@ -241,6 +245,7 @@
sccs.forEach(new TIntProcedure() {
int myTNumber = 0;
+ @Override
public boolean execute(int size) {
for (int j = 0; j < size; j++) {
index.put(dfstBuilder.getNodeByTNumber(myTNumber + j), myTNumber);
@@ -387,7 +392,7 @@
fillTypeRange(lowerBound, upperBound, range);
- return range.toArray(new PsiType[]{});
+ return range.toArray(PsiType.createArray(range.size()));
}
private void reduceInterval(final Constraint left, final Constraint right) {
@@ -451,7 +456,7 @@
}
private void reduce() {
- if (myConstraints.size() == 0) {
+ if (myConstraints.isEmpty()) {
return;
}
@@ -665,18 +670,22 @@
private void reduceTypeVar(final Constraint x, final Constraint y) {
reduceSideVar(x, y, new Reducer() {
+ @Override
public LinkedList<Pair<PsiType, Binding>> unify(final PsiType x, final PsiType y) {
return myBindingFactory.intersect(x, y);
}
+ @Override
public Constraint create(final PsiTypeVariable var, final PsiType type) {
return new Subtype(type, var);
}
+ @Override
public PsiType getType(final Constraint c) {
return c.getLeft();
}
+ @Override
public PsiTypeVariable getVar(final Constraint c) {
return (PsiTypeVariable)c.getRight();
}
@@ -685,18 +694,22 @@
private void reduceVarType(final Constraint x, final Constraint y) {
reduceSideVar(x, y, new Reducer() {
+ @Override
public LinkedList<Pair<PsiType, Binding>> unify(final PsiType x, final PsiType y) {
return myBindingFactory.union(x, y);
}
+ @Override
public Constraint create(final PsiTypeVariable var, final PsiType type) {
return new Subtype(var, type);
}
+ @Override
public PsiType getType(final Constraint c) {
return c.getRight();
}
+ @Override
public PsiTypeVariable getVar(final Constraint c) {
return (PsiTypeVariable)c.getLeft();
}
@@ -711,7 +724,7 @@
final LinkedList<Pair<PsiType, Binding>> union = reducer.unify(xType, yType);
- if (union.size() == 0) {
+ if (union.isEmpty()) {
return;
}
@@ -749,7 +762,7 @@
}
}
else {
- if (myConstraints.size() == 0) {
+ if (myConstraints.isEmpty()) {
logSolution();
mySolutions.putSolution(myCurrentBinding);
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java
index 318bc6a..e75b825 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java
@@ -41,7 +41,7 @@
PsiTypeElement typeElement = PsiTreeUtil.getParentOfType(element, PsiTypeElement.class);
while (typeElement != null) {
final PsiElement parent = typeElement.getParent();
- if (parent instanceof PsiVariable || parent instanceof PsiMember || (parent instanceof PsiReferenceParameterList && PsiTreeUtil.getParentOfType(parent, PsiMember.class) instanceof PsiClass)) {
+ if (parent instanceof PsiVariable || (parent instanceof PsiMember && !(parent instanceof PsiClass)) || isClassArgument(parent)) {
invoke(project, parent, null, editor);
return;
}
@@ -60,17 +60,30 @@
}
public static boolean invokeOnElement(final Project project, final PsiElement element) {
- if (element instanceof PsiVariable || element instanceof PsiMember || element instanceof PsiFile) {
+ if (element instanceof PsiVariable || (element instanceof PsiMember && !(element instanceof PsiClass)) || element instanceof PsiFile) {
invoke(project, element, null, null);
return true;
}
- if (element instanceof PsiReferenceParameterList && PsiTreeUtil.getParentOfType(element, PsiMember.class) instanceof PsiClass) {
+ if (isClassArgument(element)) {
invoke(project, element, null, null);
return true;
}
return false;
}
+ protected static boolean isClassArgument(PsiElement element) {
+ if (element instanceof PsiReferenceParameterList) {
+ final PsiMember member = PsiTreeUtil.getParentOfType(element, PsiMember.class);
+ if (member instanceof PsiClass) {
+ final PsiReferenceList implementsList = ((PsiClass)member).getImplementsList();
+ final PsiReferenceList extendsList = ((PsiClass)member).getExtendsList();
+ return PsiTreeUtil.isAncestor(implementsList, element, false) ||
+ PsiTreeUtil.isAncestor(extendsList, element, false);
+ }
+ }
+ return false;
+ }
+
public static void invoke(final Project project, final PsiElement root, final TypeMigrationRules rules, final Editor editor) {
if (Util.canBeMigrated(root)) {
TypeMigrationDialog dialog = new TypeMigrationDialog(project, root, rules);
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java
index 1060495..0542ff2 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -19,7 +19,6 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
@@ -459,17 +458,23 @@
else if (resolved instanceof PsiExpression){
return (((PsiExpression)resolved).getType());
} else if (resolved instanceof PsiReferenceParameterList) {
- final PsiElement parent = resolved.getParent();
- LOG.assertTrue(parent instanceof PsiJavaCodeReferenceElement);
- final PsiClass psiClass = (PsiClass)((PsiJavaCodeReferenceElement)parent).resolve();
- return JavaPsiFacade.getElementFactory(parent.getProject()).createType(psiClass, TypeConversionUtil.getSuperClassSubstitutor(psiClass, PsiTreeUtil.getParentOfType(parent,
- PsiClass.class),
- PsiSubstitutor.EMPTY));
+ PsiElement parent = resolved.getParent();
+ while (parent != null) {
+ LOG.assertTrue(parent instanceof PsiJavaCodeReferenceElement);
+ final PsiClass psiClass = (PsiClass)((PsiJavaCodeReferenceElement)parent).resolve();
+ final PsiClass containingClass = PsiTreeUtil.getParentOfType(parent, PsiClass.class);
+ if (psiClass != null && containingClass != null) {
+ final PsiSubstitutor classSubstitutor = TypeConversionUtil.getClassSubstitutor(psiClass, containingClass, PsiSubstitutor.EMPTY);
+ if (classSubstitutor != null) {
+ return JavaPsiFacade.getElementFactory(parent.getProject()).createType(psiClass, classSubstitutor);
+ }
+ }
+ parent = PsiTreeUtil.getParentOfType(parent, PsiJavaCodeReferenceElement.class, true);
+ }
} else if (resolved instanceof PsiClass) {
return JavaPsiFacade.getElementFactory(resolved.getProject()).createType((PsiClass)resolved, PsiSubstitutor.EMPTY);
}
}
- LOG.error("should not happen: " + resolved.getClass());
return null;
}
@@ -480,7 +485,7 @@
final Runnable checkTimeToStopRunnable = new Runnable() {
public void run() {
if (Messages.showYesNoCancelDialog("Found more than 10 roots to migrate. Do you want to preview?", "Type Migration",
- Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getWarningIcon()) == Messages.YES) {
myException = new MigrateException();
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java
index b9496f0..34abe92 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java
@@ -464,7 +464,9 @@
case TypeInfection.RIGHT_INFECTED:
PsiType psiType = migrationType != null ? migrationType : right.getType();
- if (psiType != null && declarationType != null && !myLabeler.addMigrationRoot(variable, psiType, myStatement, TypeConversionUtil.isAssignable(declarationType, psiType), true)) {
+ if (psiType != null && declarationType != null &&
+ !myLabeler.addMigrationRoot(variable, psiType, myStatement, TypeConversionUtil.isAssignable(declarationType, psiType), true) &&
+ !TypeConversionUtil.isAssignable(left.getType(), psiType)) {
myLabeler.convertExpression(value, psiType, left.getType(), isCovariantPosition);
}
break;
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java
index bfb07f1..ffe30a7 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationConflictsPanel.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,8 +17,8 @@
import com.intellij.openapi.project.Project;
import com.intellij.packageDependencies.ui.UsagesPanel;
+import com.intellij.psi.PsiElement;
import com.intellij.usageView.UsageInfo;
-import com.intellij.usages.UsageInfoToUsageConverter;
import org.jetbrains.annotations.NotNull;
/**
@@ -39,7 +39,7 @@
}
@Override
- public void showUsages(@NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, @NotNull final UsageInfo[] usageInfos) {
- super.showUsages(descriptor, usageInfos);
+ public void showUsages(@NotNull final PsiElement[] primaryElements, @NotNull final UsageInfo[] usageInfos) {
+ super.showUsages(primaryElements, usageInfos);
}
}
\ No newline at end of file
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java
index c571e76..29d7c37 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationPanel.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.
@@ -163,7 +163,7 @@
final MigrationNode migrationNode = (MigrationNode)userObject;
final UsageInfo[] failedUsages = myLabeler.getFailedUsages();
if (failedUsages.length > 0) {
- myConflictsPanel.showUsages(new UsageInfoToUsageConverter.TargetElementsDescriptor(new PsiElement[0]), failedUsages);
+ myConflictsPanel.showUsages(PsiElement.EMPTY_ARRAY, failedUsages);
}
final AbstractTreeNode rootNode = migrationNode.getParent();
if (rootNode instanceof MigrationNode) {
@@ -450,7 +450,7 @@
}
if (typeElement == null) typeElement = element;
PsiDocumentManager.getInstance(element.getProject()).commitAllDocuments();
- final UsagePresentation presentation = UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(typeElement), new UsageInfo(typeElement)).getPresentation();
+ final UsagePresentation presentation = UsageInfoToUsageConverter.convert(new PsiElement[]{typeElement}, new UsageInfo(typeElement)).getPresentation();
boolean isPrefix = true; //skip usage position
for (TextChunk chunk : presentation.getText()) {
if (!isPrefix) append(chunk.getText(), patchAttrs(usageInfo, chunk.getSimpleAttributesIgnoreBackground()));
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java
index 968de84..020dccf 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/MigrationUsagesPanel.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,7 +21,6 @@
import com.intellij.refactoring.typeMigration.TypeMigrationLabeler;
import com.intellij.refactoring.typeMigration.usageInfo.TypeMigrationUsageInfo;
import com.intellij.usageView.UsageInfo;
-import com.intellij.usages.UsageInfoToUsageConverter;
import java.awt.*;
import java.util.ArrayList;
@@ -48,8 +47,6 @@
public void showRootUsages(UsageInfo root, UsageInfo migration, final TypeMigrationLabeler labeler) {
final PsiElement rootElement = root.getElement();
if (rootElement == null) return;
- final UsageInfoToUsageConverter.TargetElementsDescriptor targetElementsDescriptor =
- new UsageInfoToUsageConverter.TargetElementsDescriptor(rootElement);
final Set<PsiElement> usages = labeler.getTypeUsages((TypeMigrationUsageInfo)migration, ((TypeMigrationUsageInfo)root));
if (usages != null) {
final List<UsageInfo> infos = new ArrayList<UsageInfo>(usages.size());
@@ -58,9 +55,10 @@
infos.add(new UsageInfo(usage));
}
}
- showUsages(targetElementsDescriptor, infos.toArray(new UsageInfo[infos.size()]));
- } else {
- showUsages(targetElementsDescriptor, new UsageInfo[] {migration});
+ showUsages(new PsiElement[]{rootElement}, infos.toArray(new UsageInfo[infos.size()]));
+ }
+ else {
+ showUsages(new PsiElement[]{rootElement}, new UsageInfo[] {migration});
}
}
diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java
index 6ffaf33..3ba66bb 100644
--- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java
+++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java
@@ -257,6 +257,10 @@
return "type of variable " + ((PsiLocalVariable)element).getName();
}
+ if (element instanceof PsiReferenceParameterList) {
+ return "class type arguments ";
+ }
+
if (element instanceof PsiParameter) {
final PsiParameter param = (PsiParameter)element;
String result = "type of parameter " + param.getName();
diff --git a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelector.java b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelector.java
index 6fe8213..2391fc6 100644
--- a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelector.java
+++ b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -75,7 +75,7 @@
}
public PsiType[] getTypes() {
- final PsiType[] types = new PsiType[myComboBoxModel.mySuggestions.length];
+ final PsiType[] types = PsiType.createArray(myComboBoxModel.mySuggestions.length);
for (int i = 0; i < types.length; i++) {
types[i] = myComboBoxModel.mySuggestions[i].getType();
}
@@ -147,11 +147,13 @@
}
// implements javax.swing.ListModel
+ @Override
public int getSize() {
return mySuggestions.length;
}
// implements javax.swing.ListModel
+ @Override
public Object getElementAt(int index) {
return mySuggestions[index];
}
diff --git a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java
index 0a81d89..b17e856 100644
--- a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java
@@ -192,7 +192,7 @@
});
ArrayList<PsiType> result = normalizeTypeList(allowedTypes);
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(PsiType.createArray(result.size()));
}
private PsiType[] getTypesForAll(final boolean areTypesDirected) {
@@ -232,7 +232,7 @@
if (!areTypesDirected) {
Collections.reverse(result);
}
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(PsiType.createArray(result.size()));
}
protected boolean isUsedAfter() {
diff --git a/java/java-impl/src/com/intellij/refactoring/util/ConflictsUtil.java b/java/java-impl/src/com/intellij/refactoring/util/ConflictsUtil.java
index 0dfd748..19d1eb9 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/ConflictsUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/ConflictsUtil.java
@@ -75,7 +75,7 @@
}
}
- if (method != null && method != refactoredMethod) {
+ if (method != null && method != refactoredMethod && !isStaticInterfaceMethods(aClass, refactoredMethod, method)) {
if (aClass.equals(method.getContainingClass())) {
final String classDescr = aClass instanceof PsiAnonymousClass ?
RefactoringBundle.message("current.class") :
@@ -116,6 +116,11 @@
}
}
+ private static boolean isStaticInterfaceMethods(PsiClass aClass, PsiMethod refactoredMethod, PsiMethod method) {
+ return aClass.isInterface() && method.hasModifierProperty(PsiModifier.STATIC) &&
+ refactoredMethod != null && refactoredMethod.hasModifierProperty(PsiModifier.STATIC);
+ }
+
private static String getMethodPrototypeString(final PsiMethod prototype) {
return PsiFormatUtil.formatMethod(
prototype,
diff --git a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java
index 2f80b2c..486258f 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/InlineUtil.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,6 +107,7 @@
builder.append(exprType.getCanonicalText());
builder.append("[]{");
builder.append(StringUtil.join(Arrays.asList(arguments), new Function<PsiExpression, String>() {
+ @Override
public String fun(final PsiExpression expr) {
return expr.getText();
}
@@ -294,8 +295,10 @@
public static boolean allUsagesAreTailCalls(final PsiMethod method) {
final List<PsiReference> nonTailCallUsages = Collections.synchronizedList(new ArrayList<PsiReference>());
boolean result = ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
+ @Override
public void run() {
ReferencesSearch.search(method).forEach(new Processor<PsiReference>() {
+ @Override
public boolean process(final PsiReference psiReference) {
ProgressManager.checkCanceled();
if (getTailCallType(psiReference) == TailCallType.None) {
diff --git a/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java b/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java
index 256c3a9..83fba88 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/ParameterTablePanel.java
@@ -15,13 +15,13 @@
*/
package com.intellij.refactoring.util;
-import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.refactoring.ui.TypeSelector;
import com.intellij.refactoring.ui.TypeSelectorManager;
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
import com.intellij.ui.BooleanTableCellRenderer;
+import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.TableUtil;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBComboBoxLabel;
@@ -82,8 +82,9 @@
myTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myTable.setCellSelectionEnabled(true);
- myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN).setCellRenderer(new CheckBoxTableCellRenderer());
- myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN).setMaxWidth(new JCheckBox().getPreferredSize().width);
+ TableColumn checkboxColumn = myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN);
+ TableUtil.setupCheckboxColumn(checkboxColumn);
+ checkboxColumn.setCellRenderer(new CheckBoxTableCellRenderer());
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_NAME_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
index 7f63723..3a9f796 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java
@@ -516,7 +516,11 @@
continue;
}
PsiElement anchor1 = getParentExpressionAnchorElement(occurrence);
- if (anchor1 == null) return null;
+
+ if (anchor1 == null) {
+ if (occurrence.isPhysical()) return null;
+ continue;
+ }
if (anchor == null) {
anchor = anchor1;
@@ -549,6 +553,7 @@
}
}
+ if (anchor == null) return null;
if (occurrences.length > 1 && anchor.getParent().getParent() instanceof PsiSwitchStatement) {
PsiSwitchStatement switchStatement = (PsiSwitchStatement)anchor.getParent().getParent();
if (switchStatement.getBody().equals(anchor.getParent())) {
@@ -762,7 +767,7 @@
}
public static void makeMethodDefault(@NotNull PsiMethod method) throws IncorrectOperationException {
- PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, true);
+ PsiUtil.setModifierProperty(method, PsiModifier.DEFAULT, !method.hasModifierProperty(PsiModifier.STATIC));
PsiUtil.setModifierProperty(method, PsiModifier.ABSTRACT, false);
prepareForInterface(method);
diff --git a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java
index 5c3b164..895334d 100644
--- a/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java
+++ b/java/java-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -35,7 +35,6 @@
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
@@ -124,7 +123,7 @@
showAll.set(allChosen);
if (allChosen && confirmDuplicatePrompt != null && prompt == null) {
if (Messages.showOkCancelDialog(project, "In order to replace all occurrences method signature will be changed. Proceed?", CommonBundle.getWarningTitle(), Messages.getWarningIcon()) !=
- DialogWrapper.OK_EXIT_CODE) return true;
+ Messages.OK) return true;
}
if (promptDialog.getExitCode() == FindManager.PromptResult.SKIP) return false;
if (promptDialog.getExitCode() == FindManager.PromptResult.CANCEL) return true;
@@ -193,11 +192,11 @@
if (duplicates.size() == 1) {
previewMatch(project, duplicates.get(0), editor);
}
- final int answer = ApplicationManager.getApplication().isUnitTestMode() ? 0 : Messages.showYesNoDialog(project,
+ final int answer = ApplicationManager.getApplication().isUnitTestMode() ? Messages.YES : Messages.showYesNoDialog(project,
RefactoringBundle.message("0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method",
ApplicationNamesInfo.getInstance().getProductName(), duplicates.size()),
"Process Duplicates", Messages.getQuestionIcon());
- if (answer == 0) {
+ if (answer == Messages.YES) {
invoke(project, editor, provider);
}
}
diff --git a/java/java-impl/src/com/intellij/slicer/SlicePanel.java b/java/java-impl/src/com/intellij/slicer/SlicePanel.java
index 09f90e4..4c7866e 100644
--- a/java/java-impl/src/com/intellij/slicer/SlicePanel.java
+++ b/java/java-impl/src/com/intellij/slicer/SlicePanel.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.
@@ -37,6 +37,7 @@
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usages.Usage;
+import com.intellij.usages.UsageViewPresentation;
import com.intellij.usages.UsageViewSettings;
import com.intellij.usages.impl.UsagePreviewPanel;
import com.intellij.util.EditSourceOnDoubleClickHandler;
@@ -156,7 +157,7 @@
boolean vertical = myToolWindow.getAnchor() == ToolWindowAnchor.LEFT || myToolWindow.getAnchor() == ToolWindowAnchor.RIGHT;
Splitter splitter = new Splitter(vertical, UsageViewSettings.getInstance().PREVIEW_USAGES_SPLITTER_PROPORTIONS);
splitter.setFirstComponent(pane);
- myUsagePreviewPanel = new UsagePreviewPanel(myProject);
+ myUsagePreviewPanel = new UsagePreviewPanel(myProject, new UsageViewPresentation());
myUsagePreviewPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT));
Disposer.register(this, myUsagePreviewPanel);
diff --git a/java/java-impl/src/com/intellij/spi/SPIFileType.java b/java/java-impl/src/com/intellij/spi/SPIFileType.java
index 0d4a3bd..5075404 100644
--- a/java/java-impl/src/com/intellij/spi/SPIFileType.java
+++ b/java/java-impl/src/com/intellij/spi/SPIFileType.java
@@ -18,12 +18,13 @@
import com.intellij.icons.AllIcons;
import com.intellij.lang.spi.SPILanguage;
import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -49,7 +50,7 @@
for (Object condition : Extensions.getExtensions("com.intellij.vetoSPICondition")) {
if (((Condition<String>)condition).value(fileName)) return false;
}
- return true;
+ return FileTypeRegistry.getInstance().getFileTypeByFileName(fileName) == FileTypes.UNKNOWN;
}
}
return false;
diff --git a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java
index bb70ddc..cf363e5 100644
--- a/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java
+++ b/java/java-impl/src/com/intellij/testIntegration/BaseGenerateTestSupportMethodAction.java
@@ -26,6 +26,7 @@
import com.intellij.ide.fileTemplates.impl.AllFileTemplatesConfigurable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -200,7 +201,7 @@
private void doGenerate(final Editor editor, final PsiFile file, final PsiClass targetClass, final TestFramework framework) {
if (!CommonRefactoringUtil.checkReadOnlyStatus(file)) return;
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(file.getProject(), new Runnable() {
@Override
public void run() {
try {
diff --git a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java
index 5d81ec7..a094aa1 100644
--- a/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java
+++ b/java/java-impl/src/com/intellij/testIntegration/createTest/CreateTestAction.java
@@ -26,7 +26,6 @@
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -104,7 +103,7 @@
final HashSet<VirtualFile> testFolders = new HashSet<VirtualFile>();
checkForTestRoots(srcModule, testFolders);
if (testFolders.isEmpty() && !propertiesComponent.getBoolean(CREATE_TEST_IN_THE_SAME_ROOT, false)) {
- if (Messages.showOkCancelDialog(project, "Create test in the same source root?", "No Test Roots Found", Messages.getQuestionIcon()) != DialogWrapper.OK_EXIT_CODE) {
+ if (Messages.showOkCancelDialog(project, "Create test in the same source root?", "No Test Roots Found", Messages.getQuestionIcon()) != Messages.OK) {
return;
}
diff --git a/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java b/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java
index 4fc26a0..006092c 100644
--- a/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java
+++ b/java/java-impl/src/com/intellij/unscramble/ThreadDumpPanel.java
@@ -15,18 +15,24 @@
*/
package com.intellij.unscramble;
+import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.DataManager;
import com.intellij.notification.NotificationGroup;
-import com.intellij.openapi.actionSystem.ActionManager;
-import com.intellij.openapi.actionSystem.ActionPlaces;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Splitter;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.ui.*;
import com.intellij.ui.components.JBList;
@@ -34,6 +40,7 @@
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
+import javax.swing.event.DocumentEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
@@ -58,15 +65,28 @@
private static final Icon EDT_BUSY_ICON_DAEMON = new LayeredIcon(EdtBusy, Daemon_sign);
private static final Icon IO_ICON_DAEMON = new LayeredIcon(IO, Daemon_sign);
private final JBList myThreadList;
+ private final List<ThreadState> myThreadDump;
+ private final JPanel myFilterPanel;
+ private final SearchTextField myFilterField;
- public ThreadDumpPanel(Project project, final ConsoleView consoleView, final DefaultActionGroup toolbarActions, final List<ThreadState> threadDump) {
+ public ThreadDumpPanel(final Project project, final ConsoleView consoleView, final DefaultActionGroup toolbarActions, final List<ThreadState> threadDump) {
super(new BorderLayout());
- final ThreadState[] data = threadDump.toArray(new ThreadState[threadDump.size()]);
- DefaultListModel model = new DefaultListModel();
- for (ThreadState threadState : data) {
- model.addElement(threadState);
- }
- myThreadList = new JBList(model);
+ myThreadDump = threadDump;
+
+ myFilterField = new SearchTextField();
+ myFilterField.addDocumentListener(new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ updateThreadList();
+ }
+ });
+
+ myFilterPanel = new JPanel(new BorderLayout());
+ myFilterPanel.add(new JLabel("Filter:"), BorderLayout.WEST);
+ myFilterPanel.add(myFilterField);
+ myFilterPanel.setVisible(false);
+
+ myThreadList = new JBList(new DefaultListModel());
myThreadList.setCellRenderer(new ThreadListCellRenderer());
myThreadList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
myThreadList.addListSelectionListener(new ListSelectionListener() {
@@ -82,18 +102,74 @@
myThreadList.repaint();
}
});
+
+ FilterAction filterAction = new FilterAction();
+ filterAction.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_FIND).getShortcutSet(), myThreadList);
+ toolbarActions.add(filterAction);
toolbarActions.add(new CopyToClipboardAction(threadDump, project));
toolbarActions.add(new SortThreadsAction());
//toolbarActions.add(new ShowRecentlyChanged());
add(ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, toolbarActions, false).getComponent(), BorderLayout.WEST);
- final Splitter splitter = new Splitter(false, 0.3f);
- splitter.setFirstComponent(ScrollPaneFactory.createScrollPane(myThreadList, SideBorder.LEFT | SideBorder.RIGHT));
- splitter.setSecondComponent(consoleView.getComponent());
+ JPanel leftPanel = new JPanel(new BorderLayout());
+ leftPanel.add(myFilterPanel, BorderLayout.NORTH);
+ leftPanel.add(ScrollPaneFactory.createScrollPane(myThreadList, SideBorder.LEFT | SideBorder.RIGHT), BorderLayout.CENTER);
+ final Splitter splitter = new Splitter(false, 0.3f);
+ splitter.setFirstComponent(leftPanel);
+ splitter.setSecondComponent(consoleView.getComponent());
add(splitter, BorderLayout.CENTER);
new ListSpeedSearch(myThreadList).setComparator(new SpeedSearchComparator(false, true));
+
+ updateThreadList();
+
+ final Editor editor = CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext(consoleView.getPreferredFocusableComponent()));
+ if (editor != null) {
+ editor.getDocument().addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
+ @Override
+ public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
+ String filter = myFilterField.getText();
+ if (StringUtil.isNotEmpty(filter)) {
+ highlightOccurrences(filter, project, editor);
+ }
+ }
+ }, consoleView);
+ }
+ }
+
+ private void updateThreadList() {
+ String text = myFilterPanel.isVisible() ? myFilterField.getText() : "";
+ DefaultListModel model = (DefaultListModel)myThreadList.getModel();
+ model.clear();
+ for (ThreadState state : myThreadDump) {
+ if (StringUtil.containsIgnoreCase(state.getStackTrace(), text) || StringUtil.containsIgnoreCase(state.getName(), text)) {
+ //noinspection unchecked
+ model.addElement(state);
+ }
+ }
+ if (!model.isEmpty()) {
+ myThreadList.setSelectedIndex(0);
+ }
+ myThreadList.revalidate();
+ myThreadList.repaint();
+ }
+
+ private static void highlightOccurrences(String filter, Project project, Editor editor) {
+ final HighlightManager highlightManager = HighlightManager.getInstance(project);
+ EditorColorsManager colorManager = EditorColorsManager.getInstance();
+ final TextAttributes attributes = colorManager.getGlobalScheme().getAttributes(EditorColors.TEXT_SEARCH_RESULT_ATTRIBUTES);
+ String documentText = editor.getDocument().getText();
+ int i = -1;
+ while (true) {
+ int nextOccurrence = StringUtil.indexOfIgnoreCase(documentText, filter, i + 1);
+ if (nextOccurrence < 0) {
+ break;
+ }
+ i = nextOccurrence;
+ highlightManager.addOccurrenceHighlight(editor, i, i + filter.length(), attributes,
+ HighlightManager.HIDE_BY_TEXT_CHANGE, null, null);
+ }
}
private static Icon getThreadStateIcon(final ThreadState threadState) {
@@ -119,7 +195,7 @@
return daemon ? RUNNING_ICON_DAEMON : Running;
}
- private static enum StateCode {RUN, RUN_IO, RUN_SOCKET, PAUSED, LOCKED, EDT, IDLE}
+ private enum StateCode {RUN, RUN_IO, RUN_SOCKET, PAUSED, LOCKED, EDT, IDLE}
private static StateCode getThreadStateCode(final ThreadState state) {
if (state.isSleeping()) return StateCode.PAUSED;
if (state.isWaiting()) return StateCode.LOCKED;
@@ -257,4 +333,26 @@
GROUP.createNotification("Full thread dump was successfully copied to clipboard", MessageType.INFO).notify(myProject);
}
}
+
+ private class FilterAction extends ToggleAction implements DumbAware {
+
+ FilterAction() {
+ super("Filter", "Show only threads containing a specific string", AllIcons.General.Filter);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return myFilterPanel.isVisible();
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ myFilterPanel.setVisible(state);
+ if (state) {
+ IdeFocusManager.getInstance(getEventProject(e)).requestFocus(myFilterField, true);
+ myFilterField.selectText();
+ }
+ updateThreadList();
+ }
+ }
}
diff --git a/java/java-impl/src/com/intellij/usageView/UsageContextDataflowFromPanel.java b/java/java-impl/src/com/intellij/usageView/UsageContextDataflowFromPanel.java
index 1896243..bce3bf4 100644
--- a/java/java-impl/src/com/intellij/usageView/UsageContextDataflowFromPanel.java
+++ b/java/java-impl/src/com/intellij/usageView/UsageContextDataflowFromPanel.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.openapi.project.Project;
import com.intellij.usages.UsageContextPanel;
import com.intellij.usages.UsageView;
+import com.intellij.usages.UsageViewPresentation;
import com.intellij.usages.impl.UsageViewImpl;
import org.jetbrains.annotations.NotNull;
@@ -27,7 +28,7 @@
@NotNull
@Override
public UsageContextPanel create(@NotNull UsageView usageView) {
- return new UsageContextDataflowFromPanel(((UsageViewImpl)usageView).getProject());
+ return new UsageContextDataflowFromPanel(((UsageViewImpl)usageView).getProject(), usageView.getPresentation());
}
@NotNull
@@ -37,8 +38,8 @@
}
}
- public UsageContextDataflowFromPanel(@NotNull Project project) {
- super(project);
+ public UsageContextDataflowFromPanel(@NotNull Project project, @NotNull UsageViewPresentation presentation) {
+ super(project, presentation);
}
diff --git a/java/java-impl/src/com/intellij/usageView/UsageContextDataflowToPanel.java b/java/java-impl/src/com/intellij/usageView/UsageContextDataflowToPanel.java
index de31282..38804dd 100644
--- a/java/java-impl/src/com/intellij/usageView/UsageContextDataflowToPanel.java
+++ b/java/java-impl/src/com/intellij/usageView/UsageContextDataflowToPanel.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,10 +28,7 @@
import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiVariable;
import com.intellij.slicer.*;
-import com.intellij.usages.PsiElementUsageTarget;
-import com.intellij.usages.UsageContextPanel;
-import com.intellij.usages.UsageTarget;
-import com.intellij.usages.UsageView;
+import com.intellij.usages.*;
import com.intellij.usages.impl.UsageContextPanelBase;
import com.intellij.usages.impl.UsageViewImpl;
import org.jetbrains.annotations.NotNull;
@@ -42,13 +39,14 @@
import java.util.List;
public class UsageContextDataflowToPanel extends UsageContextPanelBase {
+ @NotNull private final UsageViewPresentation myPresentation;
private JComponent myPanel;
public static class Provider implements UsageContextPanel.Provider {
@NotNull
@Override
public UsageContextPanel create(@NotNull UsageView usageView) {
- return new UsageContextDataflowToPanel(((UsageViewImpl)usageView).getProject());
+ return new UsageContextDataflowToPanel(((UsageViewImpl)usageView).getProject(), usageView.getPresentation());
}
@Override
@@ -70,8 +68,9 @@
}
}
- public UsageContextDataflowToPanel(@NotNull Project project) {
- super(project);
+ public UsageContextDataflowToPanel(@NotNull Project project, @NotNull UsageViewPresentation presentation) {
+ super(project, presentation);
+ myPresentation = presentation;
}
@Override
@@ -84,7 +83,7 @@
public void updateLayoutLater(@Nullable final List<UsageInfo> infos) {
if (infos == null) {
removeAll();
- JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview"), SwingConstants.CENTER);
+ JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview", myPresentation.getUsagesWord()), SwingConstants.CENTER);
add(titleComp, BorderLayout.CENTER);
revalidate();
}
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java
index 496703d..a7d98ad 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/MethodGroupingRule.java
@@ -131,7 +131,8 @@
@Override
public FileStatus getFileStatus() {
- return isValid() ? NavigationItemFileStatus.get(getMethod()) : null;
+ PsiFile file = myMethodPointer.getContainingFile();
+ return file == null ? null : NavigationItemFileStatus.get(file);
}
@Override
diff --git a/java/java-impl/src/com/intellij/usages/impl/rules/PackageGroupingRule.java b/java/java-impl/src/com/intellij/usages/impl/rules/PackageGroupingRule.java
index 86f57a4..b979394 100644
--- a/java/java-impl/src/com/intellij/usages/impl/rules/PackageGroupingRule.java
+++ b/java/java-impl/src/com/intellij/usages/impl/rules/PackageGroupingRule.java
@@ -43,7 +43,7 @@
}
@Override
- protected UsageGroup getGroupForFile(final VirtualFile dir) {
+ protected UsageGroup getGroupForFile(@NotNull final VirtualFile dir) {
PsiDirectory psiDirectory = PsiManager.getInstance(myProject).findDirectory(dir);
if (psiDirectory != null) {
PsiPackage aPackage = JavaDirectoryService.getInstance().getPackage(psiDirectory);
diff --git a/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java b/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java
index 0fd831c..9ee1521 100644
--- a/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.java
+++ b/java/java-impl/src/com/intellij/util/xml/impl/ExtendsClassChecker.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.
@@ -24,7 +24,7 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.xml.XmlElement;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.xml.*;
import com.intellij.util.xml.highlighting.DomCustomAnnotationChecker;
@@ -168,8 +168,8 @@
private static boolean isPsiClassType(GenericDomValue element) {
final Class genericValueParameter = DomUtil.getGenericValueParameter(element.getDomElementType());
- if (genericValueParameter != null && (ReflectionCache.isAssignable(genericValueParameter, PsiClass.class) ||
- ReflectionCache.isAssignable(genericValueParameter, PsiType.class))) {
+ if (genericValueParameter != null && (ReflectionUtil.isAssignable(genericValueParameter, PsiClass.class) ||
+ ReflectionUtil.isAssignable(genericValueParameter, PsiType.class))) {
return true;
}
return false;
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.java
index 7f68eaf..79445e6 100644
--- a/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.java
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/AnnotatedElementsSearch.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.
diff --git a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
index be4c4f8..e076920 100644
--- a/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
+++ b/java/java-indexing-api/src/com/intellij/psi/search/searches/ClassInheritorsSearch.java
@@ -156,7 +156,7 @@
}
public static Query<PsiClass> search(@NotNull SearchParameters parameters) {
- return INSTANCE.createQuery(parameters);
+ return INSTANCE.createUniqueResultsQuery(parameters);
}
public static Query<PsiClass> search(@NotNull final PsiClass aClass, @NotNull SearchScope scope, final boolean checkDeep, final boolean checkInheritance) {
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
index 4efdf20..e80e487 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/PsiShortNamesCacheImpl.java
@@ -134,7 +134,8 @@
@Override
@NotNull
public PsiMethod[] getMethodsByName(@NotNull String name, @NotNull final GlobalSearchScope scope) {
- Collection<PsiMethod> methods = StubIndex.getInstance().get(JavaStubIndexKeys.METHODS, name, myManager.getProject(), new JavaSourceFilterScope(scope));
+ Collection<PsiMethod> methods = StubIndex.getElements(JavaStubIndexKeys.METHODS, name, myManager.getProject(),
+ new JavaSourceFilterScope(scope), PsiMethod.class);
if (methods.isEmpty()) return PsiMethod.EMPTY_ARRAY;
List<PsiMethod> list = filterMembers(methods, scope);
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java
index 1637d2b..b41b363 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/file/impl/JavaFileManagerBase.java
@@ -21,12 +21,8 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileWithId;
-import com.intellij.openapi.vfs.newvfs.BulkFileListener;
-import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.file.PsiPackageImpl;
@@ -38,7 +34,6 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
@@ -50,16 +45,10 @@
*/
public abstract class JavaFileManagerBase implements JavaFileManager, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.file.impl.JavaFileManagerImpl");
- @NonNls private static final String JAVA_EXTENSION = ".java";
- @NonNls private static final String CLASS_EXTENSION = ".class";
private final ConcurrentHashMap<GlobalSearchScope, PsiClass> myCachedObjectClassMap = new ConcurrentHashMap<GlobalSearchScope, PsiClass>();
- private final Map<String,PsiClass> myNameToClassMap = new ConcurrentHashMap<String, PsiClass>(); // used only in mode without repository
private final PsiManagerEx myManager;
private final ProjectRootManager myProjectRootManager;
- private final FileManager myFileManager;
- private final boolean myUseRepository;
- private Set<String> myNontrivialPackagePrefixes = null;
- private boolean myInitialized = false;
+ private volatile Set<String> myNontrivialPackagePrefixes = null;
private boolean myDisposed = false;
private final PackageIndex myPackageIndex;
protected final MessageBusConnection myConnection;
@@ -68,28 +57,13 @@
final PsiManagerEx manager, final ProjectRootManager projectRootManager,
final MessageBus bus) {
myManager = manager;
- myFileManager = manager.getFileManager();
myProjectRootManager = projectRootManager;
- myUseRepository = true;
myPackageIndex = PackageIndex.getInstance(myManager.getProject());
myConnection = bus.connect();
myConnection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
@Override
public void rootsChanged(final ModuleRootEvent event) {
myNontrivialPackagePrefixes = null;
- clearNonRepositoryMaps();
- }
- });
-
- myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
- @Override
- public void before(@NotNull final List<? extends VFileEvent> events) {
- clearNonRepositoryMaps();
- }
-
- @Override
- public void after(@NotNull final List<? extends VFileEvent> events) {
- clearNonRepositoryMaps();
}
});
@@ -99,13 +73,6 @@
myCachedObjectClassMap.clear();
}
});
-
- Disposer.register(myManager.getProject(), this);
- }
-
- @Override
- public void initialize() {
- myInitialized = true;
}
@Override
@@ -114,12 +81,6 @@
myCachedObjectClassMap.clear();
}
- protected void clearNonRepositoryMaps() {
- if (!myUseRepository) {
- myNameToClassMap.clear();
- }
- }
-
@Override
@Nullable
public PsiPackage findPackage(@NotNull String packageName) {
@@ -169,14 +130,6 @@
@Override
@Nullable
public PsiClass findClass(@NotNull String qName, @NotNull GlobalSearchScope scope) {
- if (!myUseRepository) {
- return findClassWithoutRepository(qName);
- }
-
- if (!myInitialized) {
- LOG.error("Access to psi files should be performed only after startup activity");
- return null;
- }
LOG.assertTrue(!myDisposed);
if (CommonClassNames.JAVA_LANG_OBJECT.equals(qName)) { // optimization
@@ -195,89 +148,6 @@
}
@Nullable
- private PsiClass findClassWithoutRepository(String qName) {
- PsiClass aClass = myNameToClassMap.get(qName);
- if (aClass != null) {
- return aClass;
- }
-
- aClass = _findClassWithoutRepository(qName);
- myNameToClassMap.put(qName, aClass);
- return aClass;
- }
-
- @Nullable
- private PsiClass _findClassWithoutRepository(String qName) {
- VirtualFile[] sourcePath = myProjectRootManager.orderEntries().sources().usingCache().getRoots();
- VirtualFile[] classPath = myProjectRootManager.orderEntries().withoutModuleSourceEntries().classes().usingCache().getRoots();
-
- int index = 0;
- while (index < qName.length()) {
- int index1 = qName.indexOf('.', index);
- if (index1 < 0) {
- index1 = qName.length();
- }
- String name = qName.substring(index, index1);
-
- final int sourceType = 0;
- //final int compiledType = 1;
-
- for (int type = 0; type < 2; type++) {
- VirtualFile[] vDirs = type == sourceType ? sourcePath : classPath;
- for (VirtualFile vDir : vDirs) {
- if (vDir != null) {
- VirtualFile vChild = type == sourceType
- ? vDir.findChild(name + JAVA_EXTENSION)
- : vDir.findChild(name + CLASS_EXTENSION);
- if (vChild != null) {
- PsiFile file = myFileManager.findFile(vChild);
- if (file instanceof PsiJavaFile) {
- PsiClass aClass = findClassByName((PsiJavaFile)file, name);
- if (aClass != null) {
- index = index1 + 1;
- while (index < qName.length()) {
- index1 = qName.indexOf('.', index);
- if (index1 < 0) {
- index1 = qName.length();
- }
- name = qName.substring(index, index1);
- aClass = findClassByName(aClass, name);
- if (aClass == null) return null;
- index = index1 + 1;
- }
- return aClass;
- }
- }
- }
- }
- }
- }
-
- boolean existsDir = false;
- for (int type = 0; type < 2; type++) {
- VirtualFile[] vDirs = type == sourceType ? sourcePath : classPath;
- for (int i = 0; i < vDirs.length; i++) {
- if (vDirs[i] != null) {
- VirtualFile vDirChild = vDirs[i].findChild(name);
- if (vDirChild != null) {
- PsiDirectory dir = myFileManager.findDirectory(vDirChild);
- if (dir != null) {
- vDirs[i] = vDirChild;
- existsDir = true;
- continue;
- }
- }
- vDirs[i] = null;
- }
- }
- }
- if (!existsDir) return null;
- index = index1 + 1;
- }
- return null;
- }
-
- @Nullable
private PsiClass findClassInIndex(String qName, GlobalSearchScope scope) {
VirtualFile bestFile = null;
PsiClass bestClass = null;
@@ -347,25 +217,4 @@
return myNontrivialPackagePrefixes;
}
- @Nullable
- private static PsiClass findClassByName(PsiJavaFile scope, String name) {
- PsiClass[] classes = scope.getClasses();
- for (PsiClass aClass : classes) {
- if (name.equals(aClass.getName())) {
- return aClass;
- }
- }
- return null;
- }
-
- @Nullable
- private static PsiClass findClassByName(PsiClass scope, String name) {
- PsiClass[] classes = scope.getInnerClasses();
- for (PsiClass aClass : classes) {
- if (name.equals(aClass.getName())) {
- return aClass;
- }
- }
- return null;
- }
}
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java
index 03c8c3e..90edae7 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnnotationIndex.java
@@ -26,7 +26,6 @@
import com.intellij.psi.stubs.StringStubIndexExtension;
import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
-import com.intellij.psi.stubs.StubProcessingHelperBase;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -46,6 +45,6 @@
@Override
public Collection<PsiAnnotation> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiAnnotation.class);
+ return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiAnnotation.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
index b2d61c4..3c92cd4 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaAnonymousClassBaseRefOccurenceIndex.java
@@ -46,6 +46,6 @@
@Override
public Collection<PsiAnonymousClass> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiAnonymousClass.class);
+ return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiAnonymousClass.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
index e00f2bf..873ea3e 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFieldNameIndex.java
@@ -45,6 +45,6 @@
@Override
public Collection<PsiField> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiField.class);
+ return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiField.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java
index a4f4c15..045fdc0 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaFullClassNameIndex.java
@@ -45,6 +45,6 @@
@Override
public Collection<PsiClass> get(final Integer integer, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), integer, project, new JavaSourceFilterScope(scope), PsiClass.class);
+ return StubIndex.getElements(getKey(), integer, project, new JavaSourceFilterScope(scope), PsiClass.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
index 51d28ad..daf3f52 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaMethodNameIndex.java
@@ -45,6 +45,6 @@
@Override
public Collection<PsiMethod> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiMethod.class);
+ return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiMethod.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
index 95e27ea..35e1d1e 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaShortClassNameIndex.java
@@ -52,7 +52,7 @@
@Override
public Collection<PsiClass> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiClass.class);
+ return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiClass.class);
}
@Override
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java
index 3cb51d9..3b86d23 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberNameIndex.java
@@ -24,6 +24,7 @@
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +44,6 @@
}
public Collection<PsiMember> getStaticMembers(final String name, final Project project, @NotNull final GlobalSearchScope scope) {
- return super.get(name, project, new JavaSourceFilterScope(scope));
+ return StubIndex.getElements(getKey(), name, project, new JavaSourceFilterScope(scope), PsiMember.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java
index 3898c73..2bd119d 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaStaticMemberTypeIndex.java
@@ -24,6 +24,7 @@
import com.intellij.psi.impl.search.JavaSourceFilterScope;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StringStubIndexExtension;
+import com.intellij.psi.stubs.StubIndex;
import com.intellij.psi.stubs.StubIndexKey;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +44,7 @@
}
public Collection<PsiMember> getStaticMembers(@NotNull final String shortTypeText, final Project project, @NotNull final GlobalSearchScope scope) {
- return super.get(shortTypeText, project, new JavaSourceFilterScope(scope));
+ return StubIndex.getElements(JavaStubIndexKeys.JVM_STATIC_MEMBERS_TYPES, shortTypeText, project,
+ new JavaSourceFilterScope(scope), PsiMember.class);
}
}
\ No newline at end of file
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
index e1e8819..dcd7ae9 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/java/stubs/index/JavaSuperClassNameOccurenceIndex.java
@@ -46,7 +46,7 @@
@Override
public Collection<PsiReferenceList> get(final String s, final Project project, @NotNull final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), s, project, new JavaSourceFilterScope(scope), PsiReferenceList.class);
+ return StubIndex.getElements(getKey(), s, project, new JavaSourceFilterScope(scope), PsiReferenceList.class);
}
@Override
diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java
index 2c9117b..ece2108 100644
--- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java
+++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/MethodDeepestSuperSearcher.java
@@ -14,6 +14,10 @@
public class MethodDeepestSuperSearcher implements QueryExecutor<PsiMethod, PsiMethod> {
@Override
public boolean execute(@NotNull PsiMethod method, @NotNull Processor<PsiMethod> consumer) {
+ return processDeepestSuperMethods(method, consumer);
+ }
+
+ public static boolean processDeepestSuperMethods(PsiMethod method, Processor<PsiMethod> consumer) {
final Set<PsiMethod> methods = new THashSet<PsiMethod>();
methods.add(method);
return findDeepestSuperOrSelfSignature(method, methods, null, consumer);
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
index a333505..a5cf550 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/AnnotationUtil.java
@@ -78,12 +78,12 @@
}
@Nullable
- public static PsiAnnotation findAnnotation(PsiModifierListOwner listOwner, @NotNull String... annotationNames) {
+ public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, @NotNull String... annotationNames) {
return findAnnotation(listOwner, false, annotationNames);
}
@Nullable
- public static PsiAnnotation findAnnotation(PsiModifierListOwner listOwner, final boolean skipExternal, @NotNull String... annotationNames) {
+ public static PsiAnnotation findAnnotation(@Nullable PsiModifierListOwner listOwner, final boolean skipExternal, @NotNull String... annotationNames) {
if (annotationNames.length == 0) return null;
Set<String> set = annotationNames.length == 1 ? Collections.singleton(annotationNames[0]) : new HashSet<String>(Arrays.asList(annotationNames));
return findAnnotation(listOwner, set, skipExternal);
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java b/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java
index 4863b82..536aa5c 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/ImportFilter.java
@@ -1,6 +1,7 @@
package com.intellij.codeInsight;
import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
/**
@@ -9,11 +10,11 @@
public abstract class ImportFilter {
public static final ExtensionPointName<ImportFilter> EP_NAME = new ExtensionPointName<ImportFilter>("com.intellij.importFilter");
- public abstract boolean shouldUseFullyQualifiedName(@NotNull String classQualifiedName);
+ public abstract boolean shouldUseFullyQualifiedName(@NotNull PsiFile targetFile, @NotNull String classQualifiedName);
- public static boolean shouldImport(@NotNull String classQualifiedName) {
+ public static boolean shouldImport(@NotNull PsiFile targetFile, @NotNull String classQualifiedName) {
for (ImportFilter filter : EP_NAME.getExtensions()) {
- if (filter.shouldUseFullyQualifiedName(classQualifiedName)) {
+ if (filter.shouldUseFullyQualifiedName(targetFile, classQualifiedName)) {
return false;
}
}
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
index b1c12da..668390c 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java
@@ -15,23 +15,22 @@
*/
package com.intellij.codeInsight;
-import com.intellij.openapi.components.*;
+import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiModifierListOwner;
+import com.intellij.psi.*;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
/**
* User: anna
@@ -57,10 +56,11 @@
return ServiceManager.getService(project, NullableNotNullManager.class);
}
- public Collection<String> getAllAnnotations() {
- final List<String> all = new ArrayList<String>(getNullables());
- all.addAll(getNotNulls());
- return all;
+ /**
+ * @return if owner has a @NotNull or @Nullable annotation, or is in scope of @ParametersAreNullableByDefault or ParametersAreNonnullByDefault
+ */
+ public boolean hasNullability(@NotNull PsiModifierListOwner owner) {
+ return isNullable(owner, false) || isNotNull(owner, false);
}
private static void addAllIfNotPresent(Collection<String> collection, String... annotations) {
@@ -88,16 +88,10 @@
return myDefaultNullable;
}
- public String getPresentableDefaultNullable() {
- return StringUtil.getShortName(myDefaultNullable);
- }
-
@Nullable
public String getNullable(PsiModifierListOwner owner) {
- for (String nullable : getNullables()) {
- if (AnnotationUtil.isAnnotated(owner, nullable, false, false)) return nullable;
- }
- return null;
+ PsiAnnotation annotation = findNullabilityAnnotation(owner, false, true);
+ return annotation == null ? null : annotation.getQualifiedName();
}
public void setDefaultNullable(@NotNull String defaultNullable) {
@@ -108,16 +102,11 @@
public String getDefaultNotNull() {
return myDefaultNotNull;
}
- public String getPresentableDefaultNotNull() {
- return StringUtil.getShortName(myDefaultNotNull);
- }
@Nullable
public String getNotNull(PsiModifierListOwner owner) {
- for (String notNull : getNotNulls()) {
- if (AnnotationUtil.isAnnotated(owner, notNull, false, false)) return notNull;
- }
- return null;
+ PsiAnnotation annotation = findNullabilityAnnotation(owner, false, false);
+ return annotation == null ? null : annotation.getQualifiedName();
}
public void setDefaultNotNull(@NotNull String defaultNotNull) {
@@ -125,12 +114,56 @@
myDefaultNotNull = defaultNotNull;
}
- public boolean isNullable(PsiModifierListOwner owner, boolean checkBases) {
- return AnnotationUtil.isAnnotated(owner, getNullables(), checkBases, false);
+ @Nullable
+ private PsiAnnotation findNullabilityAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases, boolean nullable) {
+ Set<String> qNames = ContainerUtil.newHashSet(nullable ? getNullables() : getNotNulls());
+ PsiAnnotation annotation = checkBases && (owner instanceof PsiClass || owner instanceof PsiMethod)
+ ? AnnotationUtil.findAnnotationInHierarchy(owner, qNames)
+ : AnnotationUtil.findAnnotation(owner, qNames);
+ if (annotation != null) {
+ return annotation;
+ }
+
+ if (owner instanceof PsiParameter && !TypeConversionUtil.isPrimitiveAndNotNull(((PsiParameter)owner).getType())) {
+ // even if javax.annotation.Nullable is not configured, it should still take precedence over ByDefault annotations
+ if (AnnotationUtil.isAnnotated(owner, nullable ? Arrays.asList(DEFAULT_NOT_NULLS) : Arrays.asList(DEFAULT_NULLABLES), checkBases, false)) {
+ return null;
+ }
+ return findContainerAnnotation(owner, nullable
+ ? "javax.annotation.ParametersAreNullableByDefault"
+ : "javax.annotation.ParametersAreNonnullByDefault");
+ }
+ return null;
}
- public boolean isNotNull(PsiModifierListOwner owner, boolean checkBases) {
- return AnnotationUtil.isAnnotated(owner, getNotNulls(), checkBases, false);
+ public boolean isNullable(@NotNull PsiModifierListOwner owner, boolean checkBases) {
+ return findNullabilityAnnotation(owner, checkBases, true) != null;
+ }
+
+ public boolean isNotNull(@NotNull PsiModifierListOwner owner, boolean checkBases) {
+ return findNullabilityAnnotation(owner, checkBases, false) != null;
+ }
+
+ @Nullable
+ private static PsiAnnotation findContainerAnnotation(PsiModifierListOwner owner, String annotationFQN) {
+ PsiElement element = owner.getParent();
+ while (element != null) {
+ if (element instanceof PsiModifierListOwner) {
+ PsiAnnotation annotation = AnnotationUtil.findAnnotation((PsiModifierListOwner)element, annotationFQN);
+ if (annotation != null) {
+ return annotation;
+ }
+ }
+
+ if (element instanceof PsiClassOwner) {
+ String packageName = ((PsiClassOwner)element).getPackageName();
+ PsiPackage psiPackage = JavaPsiFacade.getInstance(element.getProject()).findPackage(packageName);
+ return AnnotationUtil.findAnnotation(psiPackage, annotationFQN);
+ }
+
+ element = element.getContext();
+ }
+ return null;
}
public List<String> getNullables() {
diff --git a/java/java-psi-api/src/com/intellij/codeInsight/folding/JavaCodeFoldingSettings.java b/java/java-psi-api/src/com/intellij/codeInsight/folding/JavaCodeFoldingSettings.java
index 585ce02..360b983 100644
--- a/java/java-psi-api/src/com/intellij/codeInsight/folding/JavaCodeFoldingSettings.java
+++ b/java/java-psi-api/src/com/intellij/codeInsight/folding/JavaCodeFoldingSettings.java
@@ -39,6 +39,8 @@
public abstract boolean isCollapseAccessors();
public abstract void setCollapseAccessors(boolean value);
+ public abstract boolean isCollapseOneLineMethods();
+
public abstract boolean isCollapseInnerClasses();
public abstract void setCollapseInnerClasses(boolean value);
diff --git a/java/java-psi-api/src/com/intellij/core/JavaCoreBundle.java b/java/java-psi-api/src/com/intellij/core/JavaCoreBundle.java
index ffac7af..f63801f 100644
--- a/java/java-psi-api/src/com/intellij/core/JavaCoreBundle.java
+++ b/java/java-psi-api/src/com/intellij/core/JavaCoreBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author max
*/
public class JavaCoreBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.JavaCoreBundle";
private JavaCoreBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java b/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java
index 3de211a..93676f3 100644
--- a/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.java
+++ b/java/java-psi-api/src/com/intellij/patterns/PsiJavaPatterns.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.
diff --git a/java/java-psi-api/src/com/intellij/patterns/PsiMethodCallPattern.java b/java/java-psi-api/src/com/intellij/patterns/PsiMethodCallPattern.java
index a649126..09bb9c7 100644
--- a/java/java-psi-api/src/com/intellij/patterns/PsiMethodCallPattern.java
+++ b/java/java-psi-api/src/com/intellij/patterns/PsiMethodCallPattern.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.
diff --git a/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.java b/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.java
index c5ca744..8b15e8f 100644
--- a/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.java
+++ b/java/java-psi-api/src/com/intellij/psi/ClsFileDecompiledPsiFileProvider.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,21 +17,11 @@
import com.intellij.openapi.extensions.ExtensionPointName;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-/**
- * @author Evgeny Gerashchenko
- * @since 3/20/12
- */
+/** @deprecated API no longer supported, use {@link com.intellij.psi.compiled.ClassFileDecompilers} instead (to remove in IDEA 14) */
+@SuppressWarnings({"UnusedDeclaration", "deprecation"})
public interface ClsFileDecompiledPsiFileProvider {
ExtensionPointName<ClsFileDecompiledPsiFileProvider> EP_NAME = ExtensionPointName.create("com.intellij.psi.clsDecompiledFileProvider");
- /**
- * Returns decompiled PSI associated with this classfile
- *
- * @param clsFile instance of ClsFile
- * @return decompiled PSI file
- */
- @Nullable
PsiFile getDecompiledPsiFile(@NotNull PsiJavaFile clsFile);
}
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 ef793fb..8c36cfa 100644
--- a/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/GenericsUtil.java
@@ -23,6 +23,7 @@
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.util.TypesDistinctProver;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
@@ -90,7 +91,7 @@
for (PsiType type : conjuncts) {
newConjuncts.add(getLeastUpperBound(type, type2, compared, manager));
}
- return PsiIntersectionType.createIntersection(newConjuncts.toArray(new PsiType[newConjuncts.size()]));
+ return PsiIntersectionType.createIntersection(newConjuncts.toArray(PsiType.createArray(newConjuncts.size())));
}
if (type2 instanceof PsiIntersectionType) {
return getLeastUpperBound(type2, type1, compared, manager);
@@ -454,7 +455,7 @@
result.add(substitutionMap.get(key));
}
}
- return PsiSubstitutor.EMPTY.putAll(psiClass, result.toArray(new PsiType[result.size()]));
+ return PsiSubstitutor.EMPTY.putAll(psiClass, result.toArray(PsiType.createArray(result.size())));
}
public static PsiType eliminateWildcards(PsiType type) {
@@ -463,7 +464,7 @@
public static PsiType eliminateWildcards(PsiType type, final boolean eliminateInTypeArguments) {
if (eliminateInTypeArguments && type instanceof PsiClassType) {
- PsiClassType classType = ((PsiClassType)type);
+ PsiClassType classType = (PsiClassType)type;
JavaResolveResult resolveResult = classType.resolveGenerics();
PsiClass aClass = (PsiClass)resolveResult.getElement();
if (aClass != null) {
@@ -489,11 +490,87 @@
}
else if (type instanceof PsiWildcardType) {
final PsiType bound = ((PsiWildcardType)type).getBound();
- return bound != null ? bound
- : ((PsiWildcardType)type).getExtendsBound();//object
+ return eliminateWildcards(bound != null ? bound : ((PsiWildcardType)type).getExtendsBound(), false);//object
} else if (type instanceof PsiCapturedWildcardType && !eliminateInTypeArguments) {
return eliminateWildcards(((PsiCapturedWildcardType)type).getWildcard(), eliminateInTypeArguments);
}
return type;
}
+
+ public static boolean checkNotInBounds(PsiType type, PsiType bound, PsiReferenceParameterList referenceParameterList) {
+ //allow unchecked conversions in method calls but not in type declaration
+ return checkNotInBounds(type, bound, referenceParameterList.getParent() instanceof PsiReferenceExpression);
+ }
+
+ public static boolean checkNotInBounds(PsiType type, PsiType bound, boolean uncheckedConversionByDefault) {
+ if (type instanceof PsiClassType) {
+ return checkNotAssignable(bound, type, allowUncheckedConversions((PsiClassType)type, uncheckedConversionByDefault));
+ }
+ if (type instanceof PsiWildcardType) {
+ if (((PsiWildcardType)type).isExtends()) {
+ return checkExtendsWildcardCaptureFailure((PsiWildcardType)type, bound);
+ }
+ else if (((PsiWildcardType)type).isSuper()) {
+ final PsiType superBound = ((PsiWildcardType)type).getSuperBound();
+ if (PsiUtil.resolveClassInType(superBound) instanceof PsiTypeParameter) return TypesDistinctProver.provablyDistinct(type, bound);
+ return checkNotAssignable(bound, superBound, false);
+ }
+ }
+ else if (type instanceof PsiArrayType) {
+ return checkNotAssignable(bound, type, true);
+ }
+ return false;
+ }
+
+ //JLS 5.1.10
+ private static boolean checkExtendsWildcardCaptureFailure(PsiWildcardType type, PsiType bound) {
+ LOG.assertTrue(type.isExtends());
+ final PsiType extendsBound = type.getExtendsBound();
+ PsiType boundBound = bound;
+ if (bound instanceof PsiWildcardType) {
+ if (((PsiWildcardType)bound).isBounded()) {
+ boundBound = ((PsiWildcardType)bound).isSuper()
+ ? ((PsiWildcardType)bound).getSuperBound()
+ : ((PsiWildcardType)bound).getExtendsBound();
+ }
+ else {
+ return false;
+ }
+ }
+ return !TypeConversionUtil.areTypesConvertible(boundBound, extendsBound) &&
+ !TypeConversionUtil.areTypesConvertible(extendsBound, boundBound);
+ }
+
+ private static boolean checkNotAssignable(final PsiType bound,
+ final PsiType type,
+ final boolean allowUncheckedConversion) {
+ if (bound instanceof PsiWildcardType) {
+ if (((PsiWildcardType)bound).isBounded()) {
+ final PsiType boundBound = ((PsiWildcardType)bound).isExtends()
+ ? ((PsiWildcardType)bound).getExtendsBound()
+ : ((PsiWildcardType)bound).getSuperBound();
+ return !TypeConversionUtil.isAssignable(boundBound, type, allowUncheckedConversion);
+ }
+ else {
+ return true;
+ }
+ }
+ else {
+ return !TypeConversionUtil.isAssignable(bound, type, allowUncheckedConversion);
+ }
+ }
+
+ private static boolean allowUncheckedConversions(PsiClassType type, boolean uncheckedConversionByDefault) {
+ final PsiClass psiClass = type.resolve();
+ if (psiClass != null) {
+ for (PsiTypeParameter parameter : PsiUtil.typeParametersIterable(psiClass)) {
+ if (parameter.getExtendsListTypes().length != 0) {
+ return false;
+ }
+ }
+ if (psiClass instanceof PsiTypeParameter && psiClass.getExtendsListTypes().length != 0) return false;
+ }
+ if (!type.isRaw()) return true;
+ return uncheckedConversionByDefault;
+ }
}
diff --git a/java/java-psi-api/src/com/intellij/psi/HierarchicalMethodSignature.java b/java/java-psi-api/src/com/intellij/psi/HierarchicalMethodSignature.java
index 8de679a..22619ab 100644
--- a/java/java-psi-api/src/com/intellij/psi/HierarchicalMethodSignature.java
+++ b/java/java-psi-api/src/com/intellij/psi/HierarchicalMethodSignature.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -34,7 +34,7 @@
private static PsiType[] getParameterTypes(PsiMethod method) {
final PsiParameter[] parameters = method.getParameterList().getParameters();
- final PsiType[] paramTypes = new PsiType[parameters.length];
+ final PsiType[] paramTypes = PsiType.createArray(parameters.length);
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = parameters[i].getType();
}
diff --git a/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java b/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java
index 3b4f9a2..72e37a2 100644
--- a/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java
+++ b/java/java-psi-api/src/com/intellij/psi/JavaPsiFacade.java
@@ -101,6 +101,7 @@
* Returns the name helper for the project, which can be used to validate
* and parse Java identifiers.
*
+ * @deprecated use {@link com.intellij.psi.PsiNameHelper#getInstance(com.intellij.openapi.project.Project)}
* @return the name helper instance.
*/
@NotNull
diff --git a/java/java-psi-api/src/com/intellij/psi/JavaResolveResult.java b/java/java-psi-api/src/com/intellij/psi/JavaResolveResult.java
index 320a69c..dc911ba 100644
--- a/java/java-psi-api/src/com/intellij/psi/JavaResolveResult.java
+++ b/java/java-psi-api/src/com/intellij/psi/JavaResolveResult.java
@@ -15,6 +15,8 @@
*/
package com.intellij.psi;
+import org.jetbrains.annotations.NotNull;
+
/**
* JavaResolveResult holds additional information that is obtained
* when Java references are being resolved.
@@ -28,6 +30,7 @@
/**
* Substitutor providing values of type parameters occurring in {@link #getElement()}.
*/
+ @NotNull
PsiSubstitutor getSubstitutor();
boolean isPackagePrefixPackageReference();
@@ -47,6 +50,7 @@
JavaResolveResult EMPTY = new JavaResolveResult() {
@Override public PsiElement getElement() { return null; }
+ @NotNull
@Override public PsiSubstitutor getSubstitutor() { return PsiSubstitutor.EMPTY; }
@Override public boolean isValidResult() { return false; }
@Override public boolean isAccessible() { return false; }
diff --git a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java
index cd67ed9..86137d0 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaHighlightingUtil.java
@@ -40,8 +40,6 @@
if (signatures == null) return interfaceNonFunctionalMessage;
if (signatures.isEmpty()) return "No target method found";
if (signatures.size() == 1) {
- final MethodSignature functionalMethod = signatures.get(0);
- if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic";
return null;
}
return "Multiple non-overriding abstract methods found";
@@ -106,6 +104,12 @@
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(functionalInterfaceType));
final PsiClass aClass = resolveResult.getElement();
if (aClass != null) {
+ if (aClass instanceof PsiTypeParameter) return null; //should be logged as cyclic inference
+ final List<MethodSignature> signatures = LambdaUtil.findFunctionCandidates(aClass);
+ if (signatures != null && signatures.size() == 1) {
+ final MethodSignature functionalMethod = signatures.get(0);
+ if (functionalMethod.getTypeParameters().length > 0) return "Target method is generic";
+ }
if (checkReturnTypeApplicable(resolveResult, aClass)) {
return "No instance of type " + functionalInterfaceType.getPresentableText() + " exists so that lambda expression can be type-checked";
}
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 4851504..11ba3f2 100644
--- a/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/LambdaUtil.java
@@ -16,14 +16,11 @@
package com.intellij.psi;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
-import com.intellij.psi.infos.CandidateInfo;
-import com.intellij.psi.infos.ClassCandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.util.*;
import org.jetbrains.annotations.NonNls;
@@ -94,6 +91,22 @@
return initialSubst;
}
+ public static boolean isFunctionalType(PsiType type) {
+ if (type instanceof PsiIntersectionType) {
+ for (PsiType type1 : ((PsiIntersectionType)type).getConjuncts()) {
+ if (isFunctionalType(type1)) return true;
+ }
+ }
+ final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(type));
+ final PsiClass aClass = resolveResult.getElement();
+ if (aClass != null) {
+ if (aClass instanceof PsiTypeParameter) return false;
+ final List<MethodSignature> signatures = findFunctionCandidates(aClass);
+ return signatures != null && signatures.size() == 1;
+ }
+ return false;
+ }
+
public static boolean isValidLambdaContext(@Nullable PsiElement context) {
return context instanceof PsiTypeCastExpression ||
context instanceof PsiAssignmentExpression ||
@@ -252,7 +265,7 @@
}
@Nullable
- static List<MethodSignature> findFunctionCandidates(PsiClass psiClass) {
+ public static List<MethodSignature> findFunctionCandidates(PsiClass psiClass) {
if (psiClass instanceof PsiAnonymousClass) {
psiClass = PsiUtil.resolveClassInType(((PsiAnonymousClass)psiClass).getBaseClassType());
}
@@ -470,13 +483,19 @@
final int finalLambdaIdx = adjustLambdaIdx(lambdaIdx, (PsiMethod)resolve, parameters);
if (finalLambdaIdx < parameters.length) {
if (!tryToSubstitute) return getNormalizedType(parameters[finalLambdaIdx]);
- if (cachedType != null && paramIdx > -1) {
+ if (cachedType != null) {
final PsiMethod interfaceMethod = getFunctionalInterfaceMethod(cachedType);
if (interfaceMethod != null) {
final PsiClassType.ClassResolveResult cachedResult = PsiUtil.resolveGenericsClassInType(cachedType);
- final PsiType interfaceMethodParameterType = interfaceMethod.getParameterList().getParameters()[paramIdx].getType();
- if (!dependsOnTypeParams(cachedResult.getSubstitutor().substitute(interfaceMethodParameterType), cachedType, expression)){
- return cachedType;
+ if (paramIdx == -1) {
+ if (!dependsOnTypeParams(cachedType, cachedType, expression) && !dependsOnTypeParams(getFunctionalInterfaceReturnType(cachedType), cachedType, expression)) {
+ return cachedType;
+ }
+ }
+ else {
+ if (!dependsOnTypeParams(cachedResult.getSubstitutor().substitute(interfaceMethod.getParameterList().getParameters()[paramIdx].getType()), cachedType, expression)) {
+ return cachedType;
+ }
}
}
}
@@ -579,25 +598,6 @@
return null;
}
- public static PsiSubstitutor inferFromReturnType(final PsiTypeParameter[] typeParameters,
- final PsiType returnType,
- @Nullable final PsiType interfaceMethodReturnType,
- PsiSubstitutor psiSubstitutor,
- final LanguageLevel languageLevel,
- final Project project) {
- if (interfaceMethodReturnType == null) return psiSubstitutor;
- final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(project).getResolveHelper();
- final PsiSubstitutor substitutor =
- resolveHelper.inferTypeArguments(typeParameters, new PsiType[]{interfaceMethodReturnType}, new PsiType[]{returnType}, languageLevel);
- for (PsiTypeParameter typeParameter : typeParameters) {
- final PsiType inferredType = substitutor.substitute(typeParameter);
- if (PsiUtil.resolveClassInType(inferredType) != typeParameter) {
- psiSubstitutor = psiSubstitutor.put(typeParameter, inferredType);
- }
- }
- return psiSubstitutor;
- }
-
public static boolean notInferredType(PsiType typeByExpression) {
return typeByExpression instanceof PsiMethodReferenceType || typeByExpression instanceof PsiLambdaExpressionType || typeByExpression instanceof PsiLambdaParameterType;
}
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 39d4dac..bc61565 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiArrayType.java
@@ -41,19 +41,22 @@
myComponentType = componentType;
}
+ @NotNull
@Override
public String getPresentableText() {
- return StringUtil.joinOrNull(myComponentType.getPresentableText(), getAnnotationsTextPrefix(false, true, true), "[]");
+ return StringUtil.join(myComponentType.getPresentableText(), getAnnotationsTextPrefix(false, true, true), "[]");
}
+ @NotNull
@Override
public String getCanonicalText() {
- return StringUtil.joinOrNull(myComponentType.getCanonicalText(), "[]");
+ return StringUtil.join(myComponentType.getCanonicalText(), "[]");
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
- return StringUtil.joinOrNull(myComponentType.getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "[]");
+ return StringUtil.join(myComponentType.getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "[]");
}
@Override
@@ -62,7 +65,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return text.endsWith("[]") && myComponentType.equalsToText(text.substring(0, text.length() - 2));
}
@@ -80,7 +83,7 @@
@NotNull
public PsiType[] getSuperTypes() {
final PsiType[] superTypes = myComponentType.getSuperTypes();
- final PsiType[] result = new PsiType[superTypes.length];
+ final PsiType[] result = createArray(superTypes.length);
for (int i = 0; i < superTypes.length; i++) {
result[i] = superTypes[i].createArrayType();
}
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 5f51304..9fe82b3 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiCapturedWildcardType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -47,16 +47,19 @@
return new PsiCapturedWildcardType(existential, context);
}
+ @NotNull
@Override
public String getPresentableText() {
return myExistential.getPresentableText();
}
+ @NotNull
@Override
public String getCanonicalText() {
return myExistential.getCanonicalText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
//noinspection HardCodedStringLiteral
@@ -69,7 +72,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return false;
}
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 ea3b693..30d9570 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiClassType.java
@@ -166,7 +166,7 @@
if (aClass == null) return EMPTY_ARRAY;
PsiClassType[] superTypes = aClass.getSuperTypes();
- PsiType[] substitutionResults = new PsiType[superTypes.length];
+ PsiType[] substitutionResults = createArray(superTypes.length);
for (int i = 0; i < superTypes.length; i++) {
substitutionResults[i] = resolveResult.getSubstitutor().substitute(superTypes[i]);
}
@@ -248,6 +248,7 @@
return null;
}
+ @NotNull
@Override
public PsiSubstitutor getSubstitutor() {
return PsiSubstitutor.EMPTY;
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiDiamondType.java b/java/java-psi-api/src/com/intellij/psi/PsiDiamondType.java
index a264aad..84e8162 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiDiamondType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiDiamondType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -91,7 +91,7 @@
if (myErrorMessage != null) {
return PsiType.EMPTY_ARRAY;
}
- return myInferredTypes.toArray(new PsiType[myInferredTypes.size()]);
+ return myInferredTypes.toArray(createArray(myInferredTypes.size()));
}
/**
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 4b25ff5..e9e0cf3 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiDisjunctionType.java
@@ -81,6 +81,7 @@
return new PsiDisjunctionType(types, myManager);
}
+ @NotNull
@Override
public String getPresentableText() {
return StringUtil.join(myTypes, new Function<PsiType, String>() {
@@ -88,6 +89,7 @@
}, " | ");
}
+ @NotNull
@Override
public String getCanonicalText() {
return StringUtil.join(myTypes, new Function<PsiType, String>() {
@@ -95,6 +97,7 @@
}, " | ");
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return StringUtil.join(myTypes, new Function<PsiType, String>() {
@@ -111,7 +114,7 @@
}
@Override
- public boolean equalsToText(@NonNls final String text) {
+ public boolean equalsToText(@NotNull @NonNls final String text) {
return Comparing.equal(text, getCanonicalText());
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java b/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java
index 3838dc1..9996048 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiElementFactory.java
@@ -81,6 +81,7 @@
* @return the created annotation type instance.
* @throws IncorrectOperationException if <code>name</code> is not a valid Java identifier.
*/
+ @Override
@NotNull
PsiClass createAnnotationType(@NotNull @NonNls String name) throws IncorrectOperationException;
@@ -123,6 +124,7 @@
* @param name the name of the constructor to create.
* @return the created constructor instance.
*/
+ @Override
@NotNull
PsiMethod createConstructor(@NotNull @NonNls String name);
@@ -162,6 +164,7 @@
* @param substitutor the substitutor to use.
* @return the class type instance.
*/
+ @Override
@NotNull PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor);
/**
@@ -173,8 +176,10 @@
* @param languageLevel to memorize language level for allowing/prohibiting boxing/unboxing.
* @return the class type instance.
*/
+ @Override
@NotNull PsiClassType createType(@NotNull PsiClass resolve, @NotNull PsiSubstitutor substitutor, @Nullable LanguageLevel languageLevel);
+ @Override
@NotNull PsiClassType createType(@NotNull PsiClass resolve,
@NotNull PsiSubstitutor substitutor,
@Nullable LanguageLevel languageLevel,
@@ -188,8 +193,10 @@
*/
@NotNull PsiClassType createType(@NotNull PsiJavaCodeReferenceElement classReference);
+ @Override
@NotNull PsiClassType createType(@NotNull PsiClass aClass, PsiType parameters);
+ @Override
@NotNull PsiClassType createType(@NotNull PsiClass aClass, PsiType... parameters);
/**
@@ -199,6 +206,7 @@
* @param owner the class or method for which the substitutor is created.
* @return the substitutor instance.
*/
+ @Override
@NotNull PsiSubstitutor createRawSubstitutor(@NotNull PsiTypeParameterListOwner owner);
/**
@@ -207,6 +215,7 @@
* @param map the type parameter to type map used by the substitutor.
* @return the substitutor instance.
*/
+ @Override
@NotNull PsiSubstitutor createSubstitutor(@NotNull Map<PsiTypeParameter, PsiType> map);
/**
@@ -216,6 +225,7 @@
* @return the primitive type instance, or null if <code>name</code> is not a valid
* primitive type name.
*/
+ @Override
@Nullable PsiPrimitiveType createPrimitiveType(@NotNull String text);
/**
@@ -225,6 +235,7 @@
* @param qName the full-qualified name of the class to create the reference to.
* @return the class type instance.
*/
+ @Override
@NotNull PsiClassType createTypeByFQClassName(@NotNull @NonNls String qName);
/**
@@ -235,6 +246,7 @@
* @param resolveScope the scope in which the class is searched.
* @return the class type instance.
*/
+ @Override
@NotNull PsiClassType createTypeByFQClassName(@NotNull @NonNls String qName, @NotNull GlobalSearchScope resolveScope);
/**
@@ -251,6 +263,7 @@
* @param type the class type to create the reference to.
* @return the reference element instance.
*/
+ @Override
@NotNull PsiJavaCodeReferenceElement createReferenceElementByType(@NotNull PsiClassType type);
/**
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 bfb2c4f..0d14479 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiEllipsisType.java
@@ -42,23 +42,26 @@
return new PsiEllipsisType(componentType, annotations);
}
+ @NotNull
@Override
public String getPresentableText() {
- return StringUtil.joinOrNull(getComponentType().getPresentableText(), getAnnotationsTextPrefix(false, true, true), "...");
+ return StringUtil.join(getComponentType().getPresentableText(), getAnnotationsTextPrefix(false, true, true), "...");
}
+ @NotNull
@Override
public String getCanonicalText() {
- return StringUtil.joinOrNull(getComponentType().getCanonicalText(), "...");
+ return StringUtil.join(getComponentType().getCanonicalText(), "...");
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
- return StringUtil.joinOrNull(getComponentType().getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "...");
+ return StringUtil.join(getComponentType().getInternalCanonicalText(), getAnnotationsTextPrefix(true, true, true), "...");
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return text.endsWith("...") && getComponentType().equalsToText(text.substring(0, text.length() - 3)) ||
super.equalsToText(text);
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java b/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java
index 582f51d..6b7354a 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiImportStatementBase.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.
@@ -61,4 +61,6 @@
*/
@Nullable
PsiElement resolve();
+
+ boolean isForeignFileImport();
}
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 b502b5c..215bb86 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiIntersectionType.java
@@ -39,7 +39,7 @@
@NotNull
public static PsiType createIntersection(@NotNull List<PsiType> conjuncts) {
- return createIntersection(conjuncts.toArray(new PsiType[conjuncts.size()]));
+ return createIntersection(conjuncts.toArray(createArray(conjuncts.size())));
}
@NotNull
@@ -53,7 +53,7 @@
private static PsiType[] flattenAndRemoveDuplicates(PsiType[] conjuncts) {
try {
Set<PsiType> flattened = flatten(conjuncts, new THashSet<PsiType>());
- return flattened.toArray(new PsiType[flattened.size()]);
+ return flattened.toArray(createArray(flattened.size()));
}
catch (NoSuchElementException e) {
throw new RuntimeException(Arrays.toString(conjuncts), e);
@@ -71,7 +71,7 @@
}
}
if (types.size() > 1) {
- PsiType[] array = types.toArray(new PsiType[types.size()]);
+ PsiType[] array = types.toArray(createArray(types.size()));
for (Iterator<PsiType> iterator = types.iterator(); iterator.hasNext(); ) {
PsiType type = iterator.next();
@@ -97,6 +97,7 @@
return myConjuncts;
}
+ @NotNull
@Override
public String getPresentableText() {
return StringUtil.join(myConjuncts, new Function<PsiType, String>() {
@@ -107,11 +108,13 @@
}, " & ");
}
+ @NotNull
@Override
public String getCanonicalText() {
return myConjuncts[0].getCanonicalText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
StringBuilder buffer = new StringBuilder();
@@ -131,7 +134,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return false;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java b/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java
index 0ae5c8a..db9db62 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiLambdaExpressionType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -30,16 +30,19 @@
myExpression = expression;
}
+ @NotNull
@Override
public String getPresentableText() {
return "<lambda expression>";
}
+ @NotNull
@Override
public String getCanonicalText() {
return getPresentableText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getCanonicalText();
@@ -51,7 +54,7 @@
}
@Override
- public boolean equalsToText(@NonNls final String text) {
+ public boolean equalsToText(@NotNull @NonNls final String text) {
return false;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiLambdaParameterType.java b/java/java-psi-api/src/com/intellij/psi/PsiLambdaParameterType.java
index de62f0e..6a1991c 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiLambdaParameterType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiLambdaParameterType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -30,16 +30,19 @@
myParameter = parameter;
}
+ @NotNull
@Override
public String getPresentableText() {
return "<lambda parameter>";
}
+ @NotNull
@Override
public String getCanonicalText() {
return getPresentableText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getCanonicalText();
@@ -51,7 +54,7 @@
}
@Override
- public boolean equalsToText(@NonNls final String text) {
+ public boolean equalsToText(@NotNull @NonNls final String text) {
return false;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceExpression.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceExpression.java
index f65ee0e..01a11a6 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceExpression.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceExpression.java
@@ -36,9 +36,31 @@
@Nullable
PsiType getFunctionalInterfaceType();
+ /**
+ * @return if there is only one possible compile-time declaration with only one possible invocation type,
+ * regardless of the targeted function type return true, false otherwise
+ */
boolean isExact();
/**
+ * 15.12.2.1 Identify Potentially Applicable Methods
+ * .................................................
+ * A method reference (15.13) is potentially compatible with a functional interface type if, where the type's function type arity is n,
+ * there exists at least one potentially-applicable method for the method reference at arity n (15.13.1), and one of the following is true:
+ * The method reference has the form ReferenceType::NonWildTypeArgumentsopt Identifier and at least one potentially-applicable method either
+ * i) is declared static and supports arity n, or
+ * ii) is not declared static and supports arity n-1.
+ * The method reference has some other form and at least one potentially-applicable method is not declared static.
+ */
+ boolean isPotentiallyCompatible(PsiType functionalInterfaceType);
+
+ /**
+ * @return potential applicable member for exact reference, otherwise null
+ */
+ @Nullable
+ PsiMember getPotentiallyApplicableMember();
+
+ /**
* @return true if reference is of form ClassType::new
*/
boolean isConstructor();
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java
index 7109554..437bdc9 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -30,16 +30,19 @@
myReference = reference;
}
+ @NotNull
@Override
public String getPresentableText() {
return "<method reference>";
}
+ @NotNull
@Override
public String getCanonicalText() {
return getPresentableText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getPresentableText();
@@ -51,7 +54,7 @@
}
@Override
- public boolean equalsToText(@NonNls final String text) {
+ public boolean equalsToText(@NotNull @NonNls final String text) {
return false;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
index 30b9a2b..28cf4de 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiMethodReferenceUtil.java
@@ -37,7 +37,7 @@
public static boolean hasReceiver(PsiType[] parameterTypes, QualifierResolveResult qualifierResolveResult, PsiMethodReferenceExpression methodRef) {
if (parameterTypes.length > 0 &&
- isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) &&
+ isReceiverType(parameterTypes[0], qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()) &&
isStaticallyReferenced(methodRef)) {
return true;
}
@@ -48,9 +48,7 @@
final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(expression);
final PsiElement resolve = result.getElement();
if (resolve instanceof PsiMethod) {
- PsiSubstitutor subst = PsiSubstitutor.EMPTY;
- subst = subst.putAll(qualifierResolveResult.getSubstitutor());
- subst = subst.putAll(result.getSubstitutor());
+ PsiSubstitutor subst = result.getSubstitutor();
final PsiType interfaceReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
@@ -165,7 +163,12 @@
if (methodReferenceExpression == null) return false;
final PsiElement argsList = PsiTreeUtil.getParentOfType(methodReferenceExpression, PsiExpressionList.class);
if (MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argsList)) {
- if (!methodReferenceExpression.isExact()) return true;
+ if (!methodReferenceExpression.isPotentiallyCompatible(left)) {
+ return false;
+ }
+ if (!methodReferenceExpression.isExact()) {
+ return true;
+ }
}
if (left instanceof PsiIntersectionType) {
for (PsiType conjunct : ((PsiIntersectionType)left).getConjuncts()) {
@@ -197,9 +200,7 @@
final PsiElement resolve = result.getElement();
if (resolve instanceof PsiMethod) {
final MethodSignature signature1 = method.getSignature(LambdaUtil.getSubstitutor(method, resolveResult));
- PsiSubstitutor subst = PsiSubstitutor.EMPTY;
- subst = subst.putAll(TypeConversionUtil.getSuperClassSubstitutor(((PsiMethod)resolve).getContainingClass(), qualifierResolveResult.getContainingClass(), qualifierResolveResult.getSubstitutor()));
- subst = subst.putAll(result.getSubstitutor());
+ PsiSubstitutor subst = result.getSubstitutor();
final MethodSignature signature2 = ((PsiMethod)resolve).getSignature(subst);
if (methodReferenceExpression.isExact()) {
@@ -257,7 +258,6 @@
}
public static boolean isReceiverType(PsiType receiverType, @Nullable PsiClass containingClass, PsiSubstitutor psiSubstitutor) {
- boolean arrayType = receiverType instanceof PsiArrayType;
if (containingClass != null) {
receiverType = getExpandedType(receiverType, containingClass);
}
@@ -265,17 +265,15 @@
final PsiClass receiverClass = resolveResult.getElement();
if (receiverClass != null && isReceiverType(receiverClass, containingClass)) {
LOG.assertTrue(containingClass != null);
- return arrayType ||
- resolveResult.getSubstitutor().equals(psiSubstitutor) ||
- emptyOrRaw(containingClass, psiSubstitutor) ||
- emptyOrRaw(receiverClass, resolveResult.getSubstitutor());
+ return emptyOrRaw(containingClass, psiSubstitutor) ||
+ TypeConversionUtil.isAssignable(JavaPsiFacade.getElementFactory(containingClass.getProject()).createType(containingClass, psiSubstitutor), GenericsUtil.eliminateWildcards(receiverType));
}
return false;
}
private static boolean emptyOrRaw(PsiClass containingClass, PsiSubstitutor psiSubstitutor) {
return PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor) ||
- (!containingClass.hasTypeParameters() && psiSubstitutor.getSubstitutionMap().isEmpty());
+ psiSubstitutor.getSubstitutionMap().isEmpty();
}
public static boolean isReceiverType(PsiType functionalInterfaceType, PsiClass containingClass, @Nullable PsiMethod referencedMethod) {
@@ -322,9 +320,13 @@
else if (!isVarargs) {
return false;
}
+ } else if (isVarargs) {
+ if (isReceiverType(signatureParameterTypes1[0], psiClass, psiSubstitutor)) {
+ offset++;
+ }
}
- final int min = Math.min(signatureParameterTypes2.length, signatureParameterTypes1.length);
+ final int min = Math.min(signatureParameterTypes2.length, signatureParameterTypes1.length - offset);
for (int i = 0; i < min; i++) {
final PsiType type1 = GenericsUtil.eliminateWildcards(psiSubstitutor.substitute(signatureParameterTypes1[offset + i]));
if (isVarargs && i == min - 1) {
@@ -442,7 +444,7 @@
LOG.assertTrue(signature != null);
final PsiType[] parameterTypes = signature.getParameterTypes();
final QualifierResolveResult qualifierResolveResult = getQualifierResolveResult(methodRef);
- return method.getParameterList().getParametersCount() + 1 == parameterTypes.length &&
+ return (method.getParameterList().getParametersCount() + 1 == parameterTypes.length || method.isVarArgs() && parameterTypes.length > 0)&&
hasReceiver(parameterTypes, qualifierResolveResult, methodRef);
}
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 4291ee7..6ae0fa6 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiNameHelper.java
@@ -15,6 +15,8 @@
*/
package com.intellij.psi;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
@@ -31,6 +33,11 @@
* @see com.intellij.psi.JavaPsiFacade#getNameHelper()
*/
public abstract class PsiNameHelper {
+
+ 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.
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 0a38c64..6797e84 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiPrimitiveType.java
@@ -51,16 +51,19 @@
}
}
+ @NotNull
@Override
public String getPresentableText() {
return getAnnotationsTextPrefix(false, false, true) + myName;
}
+ @NotNull
@Override
public String getCanonicalText() {
return myName;
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getAnnotationsTextPrefix(true, false, true) + myName;
@@ -75,7 +78,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return myName.equals(text);
}
@@ -92,7 +95,7 @@
@Override
@NotNull
public PsiType[] getSuperTypes() {
- return new PsiType[0];
+ return EMPTY_ARRAY;
}
/**
diff --git a/java/java-psi-api/src/com/intellij/psi/PsiSubstitutor.java b/java/java-psi-api/src/com/intellij/psi/PsiSubstitutor.java
index ddc301e..0fcc46e 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiSubstitutor.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiSubstitutor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -37,7 +37,9 @@
* <b>Example:</b> consider class <code>List<E></code>. <code>this</code>
* inside class <code>List</code> has type List with EMPTY substitutor.
*/
+ @NotNull
PsiSubstitutor EMPTY = EmptySubstitutor.getInstance();
+ @NotNull
PsiSubstitutor UNKNOWN = EMPTY;
/**
@@ -61,7 +63,7 @@
//Should be used with great care, be sure to prevent infinite recursion that could arise
// from the use of recursively bounded type parameters
- PsiType substituteWithBoundsPromotion(PsiTypeParameter typeParameter);
+ PsiType substituteWithBoundsPromotion(@NotNull PsiTypeParameter typeParameter);
/**
* Creates a substitutor instance which provides the specified parameter to type mapping in addition
@@ -71,7 +73,8 @@
* @param mapping the type to which the parameter is mapped.
* @return the new substitutor instance.
*/
- PsiSubstitutor put(PsiTypeParameter classParameter, PsiType mapping);
+ @NotNull
+ PsiSubstitutor put(@NotNull PsiTypeParameter classParameter, PsiType mapping);
/**
* Creates a substitutor instance which maps the type parameters of the specified class to the
@@ -81,7 +84,8 @@
* @param mappings the types to which the parameters are mapped.
* @return the new substitutor instance.
*/
- PsiSubstitutor putAll(PsiClass parentClass, PsiType[] mappings);
+ @NotNull
+ PsiSubstitutor putAll(@NotNull PsiClass parentClass, PsiType[] mappings);
/**
* Creates a substitutor instance containing all mappings from this substitutor and the
@@ -90,7 +94,8 @@
* @param another the substitutor to get the mappings from.
* @return the new substitutor instance.
*/
- PsiSubstitutor putAll(PsiSubstitutor another);
+ @NotNull
+ PsiSubstitutor putAll(@NotNull PsiSubstitutor another);
/**
* Returns the map from type parameters to types used for substitution by this substitutor.
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 8d415d5..3b95be0 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiType.java
@@ -17,6 +17,7 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.ArrayFactory;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,6 +38,17 @@
public static final PsiPrimitiveType NULL = new PsiPrimitiveType("null", (String)null);
public static final PsiType[] EMPTY_ARRAY = new PsiType[0];
+ public static final ArrayFactory<PsiType> ARRAY_FACTORY = new ArrayFactory<PsiType>() {
+ @NotNull
+ @Override
+ public PsiType[] create(int count) {
+ return count == 0 ? EMPTY_ARRAY : new PsiType[count];
+ }
+ };
+ @NotNull
+ public static PsiType[] createArray(int count) {
+ return ARRAY_FACTORY.create(count);
+ }
private final PsiAnnotation[] myAnnotations;
@@ -56,7 +68,7 @@
* Creates array type with this type as a component.
*/
@NotNull
- public PsiArrayType createArrayType(PsiAnnotation... annotations) {
+ public PsiArrayType createArrayType(@NotNull PsiAnnotation... annotations) {
return new PsiArrayType(this, annotations);
}
@@ -64,18 +76,21 @@
* @return text of the type that can be presented to a user (non-qualified references, with annotations).
*/
@NonNls
+ @NotNull
public abstract String getPresentableText();
/**
* @return text of the type (fully-qualified references, no annotations).
*/
@NonNls
+ @NotNull
public abstract String getCanonicalText();
/**
* @return text of the type (fully-qualified references, with annotations).
*/
@NonNls
+ @NotNull
public abstract String getInternalCanonicalText();
/**
@@ -106,7 +121,7 @@
* @param text the text to compare with.
* @return true if the string is equivalent to the type, false otherwise
*/
- public abstract boolean equalsToText(@NonNls String text);
+ public abstract boolean equalsToText(@NotNull @NonNls String text);
/**
* Returns the class type for the java.lang.Object class.
@@ -128,7 +143,8 @@
* @param resolveScope the scope in which the class is searched.
* @return the class instance.
*/
- public static PsiClassType getJavaLangClass(PsiManager manager, GlobalSearchScope resolveScope) {
+ @NotNull
+ public static PsiClassType getJavaLangClass(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_CLASS, resolveScope);
}
@@ -140,7 +156,8 @@
* @param resolveScope the scope in which the class is searched.
* @return the class instance.
*/
- public static PsiClassType getJavaLangThrowable(PsiManager manager, GlobalSearchScope resolveScope) {
+ @NotNull
+ public static PsiClassType getJavaLangThrowable(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_THROWABLE, resolveScope);
}
@@ -153,7 +170,7 @@
* @return the class instance.
*/
@NotNull
- public static PsiClassType getJavaLangString(PsiManager manager, GlobalSearchScope resolveScope) {
+ public static PsiClassType getJavaLangString(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, resolveScope);
}
@@ -165,7 +182,8 @@
* @param resolveScope the scope in which the class is searched.
* @return the class instance.
*/
- public static PsiClassType getJavaLangError(PsiManager manager, GlobalSearchScope resolveScope) {
+ @NotNull
+ public static PsiClassType getJavaLangError(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_ERROR, resolveScope);
}
@@ -177,7 +195,8 @@
* @param resolveScope the scope in which the class is searched.
* @return the class instance.
*/
- public static PsiClassType getJavaLangRuntimeException(PsiManager manager, GlobalSearchScope resolveScope) {
+ @NotNull
+ public static PsiClassType getJavaLangRuntimeException(@NotNull PsiManager manager, @NotNull GlobalSearchScope resolveScope) {
PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
return factory.createTypeByFQClassName(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, resolveScope);
}
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 6dcd00c..a3dd77a 100644
--- a/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java
+++ b/java/java-psi-api/src/com/intellij/psi/PsiWildcardType.java
@@ -35,6 +35,7 @@
@NonNls private static final String EXTENDS_PREFIX = "? extends ";
@NonNls private static final String SUPER_PREFIX = "? super ";
+ @NotNull
private final PsiManager myManager;
private final boolean myIsExtending;
private final PsiType myBound;
@@ -79,6 +80,7 @@
return annotations.length == 0 ? this : new PsiWildcardType(this, annotations);
}
+ @NotNull
@Override
public String getPresentableText() {
return getAnnotationsTextPrefix(false, false, true) +
@@ -86,10 +88,12 @@
}
@Override
+ @NotNull
public String getCanonicalText() {
- return (myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getCanonicalText());
+ return myBound == null ? "?" : (myIsExtending ? EXTENDS_PREFIX : SUPER_PREFIX) + myBound.getCanonicalText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getAnnotationsTextPrefix(true, false, true) +
@@ -115,7 +119,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
if (myBound == null) return "?".equals(text);
if (myIsExtending) {
return text.startsWith(EXTENDS_PREFIX) && myBound.equalsToText(text.substring(EXTENDS_PREFIX.length()));
@@ -124,7 +128,7 @@
return text.startsWith(SUPER_PREFIX) && myBound.equalsToText(text.substring(SUPER_PREFIX.length()));
}
}
-
+ @NotNull
public PsiManager getManager() {
return myManager;
}
@@ -204,6 +208,7 @@
*
* @return <code>PsiType</code> representing a lower bound. Never returns <code>null</code>.
*/
+ @NotNull
public PsiType getExtendsBound() {
if (myBound == null || !myIsExtending) {
return getJavaLangObject(myManager, getResolveScope());
@@ -222,6 +227,7 @@
*
* @return <code>PsiType</code> representing an upper bound. Never returns <code>null</code>.
*/
+ @NotNull
public PsiType getSuperBound() {
return myBound == null || myIsExtending ? NULL : myBound;
}
diff --git a/java/java-psi-api/src/com/intellij/psi/compiled/ClassFileDecompilers.java b/java/java-psi-api/src/com/intellij/psi/compiled/ClassFileDecompilers.java
new file mode 100644
index 0000000..e2d0483
--- /dev/null
+++ b/java/java-psi-api/src/com/intellij/psi/compiled/ClassFileDecompilers.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.compiled;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PsiManager;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * An API to extend default IDEA .class file decompiler and handle files compiled from sources other than Java.
+ *
+ * @since 134.1050
+ */
+public class ClassFileDecompilers {
+
+ /**
+ * Actual implementations should extend either {@link Light} or {@link Full} classes -
+ * those that don't are silently ignored.
+ */
+ public interface Decompiler {
+ boolean accepts(@NotNull VirtualFile file);
+ }
+
+
+ /**
+ * <p>"Light" decompilers are intended for augmenting file text constructed by standard IDEA decompiler
+ * without changing it's structure - i.e. providing additional information in comments,
+ * or replacing standard "compiled code" method body comment with something more meaningful.</p>
+ *
+ * <p>Plugins registering extension of this type normally should accept all files and use {@code order="last"}
+ * attribute to avoid interfering with other decompilers.</p>
+ */
+ public abstract static class Light implements Decompiler {
+ @NotNull
+ public abstract CharSequence getText(@NotNull VirtualFile file);
+ }
+
+
+ /**
+ * <p>"Full" decompilers are designed to provide extended support for languages significantly different from Java.
+ * Extensions of this type should take care of building file stubs and properly indexing them -
+ * in return they have an ability to represent decompiled file in a way natural for original language.</p>
+ */
+ public abstract static class Full implements Decompiler {
+ @NotNull
+ public abstract ClsStubBuilder getStubBuilder();
+
+ /**
+ * <h5>Notes for implementers</h5>
+ *
+ * <p>1. Return a correct language from {@link FileViewProvider#getBaseLanguage()}.</p>
+ *
+ * <p>2. This method is called for both PSI file construction and obtaining document text.
+ * In the latter case the PsiManager is based on default project, and the only method called
+ * on a resulting view provider is {@link FileViewProvider#getContents()}.</p>
+ *
+ * <p>3. A language compiler may produce auxiliary .class files which should be handled as part of their parent classes.
+ * A standard practice is to hide such files by returning {@code null} from
+ * {@link FileViewProvider#getPsi(com.intellij.lang.Language)}.</p>
+ */
+ @NotNull
+ public abstract FileViewProvider createFileViewProvider(@NotNull VirtualFile file, @NotNull PsiManager manager, boolean physical);
+ }
+
+
+ public static ExtensionPointName<Decompiler> EP_NAME = ExtensionPointName.create("com.intellij.psi.classFileDecompiler");
+
+ private ClassFileDecompilers() { }
+
+ @Nullable
+ public static Decompiler find(@NotNull VirtualFile file) {
+ for (Decompiler decompiler : EP_NAME.getExtensions()) {
+ if ((decompiler instanceof Light || decompiler instanceof Full) && decompiler.accepts(file)) {
+ return decompiler;
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/java/java-psi-api/src/com/intellij/psi/compiled/ClsStubBuilder.java b/java/java-psi-api/src/com/intellij/psi/compiled/ClsStubBuilder.java
new file mode 100644
index 0000000..ea4fd9f
--- /dev/null
+++ b/java/java-psi-api/src/com/intellij/psi/compiled/ClsStubBuilder.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.psi.compiled;
+
+import com.intellij.psi.stubs.PsiFileStub;
+import com.intellij.util.cls.ClsFormatException;
+import com.intellij.util.indexing.FileContent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class ClsStubBuilder {
+ /**
+ * Non-zero positive number expected.
+ */
+ public abstract int getStubVersion();
+
+ /**
+ * May return {@code null} for inner or synthetic classes - i.e. those indexed as a part of their parent .class file.
+ */
+ @Nullable
+ public abstract PsiFileStub<?> buildFileStub(@NotNull FileContent fileContent) throws ClsFormatException;
+}
diff --git a/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java
index e136ddc..aff69cd 100644
--- a/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java
+++ b/java/java-psi-api/src/com/intellij/psi/infos/CandidateInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,55 +29,57 @@
private final PsiElement myPlace;
private final PsiClass myAccessClass;
private final PsiElement myCandidate;
- private Boolean myAccessProblem = null;
private final boolean myStaticsProblem;
protected final PsiSubstitutor mySubstitutor;
private final PsiElement myCurrentFileResolveContext;
- private boolean myPackagePrefixPackageReference;
+ private final boolean myPackagePrefixPackageReference;
+ private Boolean myAccessible; // benign datarace
private CandidateInfo(PsiElement candidate,
- PsiSubstitutor substitutor,
- Boolean accessProblem,
+ @NotNull PsiSubstitutor substitutor,
+ Boolean accessible,
boolean staticsProblem,
PsiElement currFileContext,
PsiElement place,
- PsiClass accessClass) {
+ PsiClass accessClass,
+ boolean packagePrefixPackageReference) {
myCandidate = candidate;
- myAccessProblem = accessProblem;
+ myAccessible = accessible;
myStaticsProblem = staticsProblem;
mySubstitutor = substitutor;
myCurrentFileResolveContext = currFileContext;
myAccessClass = accessClass;
myPlace = place;
+ myPackagePrefixPackageReference = packagePrefixPackageReference;
}
- public CandidateInfo(PsiElement candidate, PsiSubstitutor substitutor, boolean accessProblem, boolean staticsProblem, PsiElement currFileContext) {
- this(candidate, substitutor, accessProblem ? Boolean.TRUE : Boolean.FALSE, staticsProblem, currFileContext, null, null);
+ public CandidateInfo(PsiElement candidate, @NotNull PsiSubstitutor substitutor, boolean accessProblem, boolean staticsProblem, PsiElement currFileContext) {
+ this(candidate, substitutor, !accessProblem, staticsProblem, currFileContext, null, null, false);
}
- public CandidateInfo(PsiElement candidate, PsiSubstitutor substitutor, boolean accessProblem, boolean staticsProblem){
+ public CandidateInfo(PsiElement candidate, @NotNull PsiSubstitutor substitutor, boolean accessProblem, boolean staticsProblem){
this(candidate, substitutor, accessProblem, staticsProblem, null);
}
- public CandidateInfo(PsiElement candidate, PsiSubstitutor substitutor, PsiElement place, boolean staticsProblem){
- this(candidate, substitutor, place, null, staticsProblem, null);
- }
-
public CandidateInfo(PsiElement candidate,
- PsiSubstitutor substitutor,
+ @NotNull PsiSubstitutor substitutor,
PsiElement place,
PsiClass accessClass,
boolean staticsProblem,
PsiElement currFileContext){
- this(candidate, substitutor, null, staticsProblem, currFileContext, place, accessClass);
+ this(candidate, substitutor, null, staticsProblem, currFileContext, place, accessClass, false);
}
- public CandidateInfo(PsiElement candidate, PsiSubstitutor substitutor){
+ public CandidateInfo(PsiElement candidate, @NotNull PsiSubstitutor substitutor, PsiElement place, boolean staticsProblem){
+ this(candidate, substitutor, place, null, staticsProblem, null);
+ }
+
+ public CandidateInfo(PsiElement candidate, @NotNull PsiSubstitutor substitutor){
this(candidate, substitutor, null, null, false, null);
}
- public CandidateInfo(@NotNull CandidateInfo candidate, PsiSubstitutor newSubstitutor){
- this(candidate.myCandidate, newSubstitutor, candidate.myPlace, null, candidate.myStaticsProblem, candidate.myCurrentFileResolveContext);
- myAccessProblem = candidate.myAccessProblem;
+ public CandidateInfo(CandidateInfo candidate, @NotNull PsiSubstitutor newSubstitutor){
+ this(candidate.myCandidate, newSubstitutor, candidate.myAccessible, candidate.myStaticsProblem, candidate.myCurrentFileResolveContext, candidate.myPlace,
+ null, false);
}
@Override
@@ -95,26 +97,31 @@
return myCandidate;
}
+ @NotNull
@Override
public PsiSubstitutor getSubstitutor(){
return mySubstitutor;
}
@Override
- public boolean isAccessible(){
- if(myAccessProblem == null){
- boolean accessProblem = false;
+ public boolean isAccessible() {
+ Boolean Accessible = myAccessible;
+ boolean accessible = true;
+ if(Accessible == null) {
if (myPlace != null && myCandidate instanceof PsiMember) {
final PsiMember member = (PsiMember)myCandidate;
- accessProblem = !JavaPsiFacade.getInstance(myPlace.getProject()).getResolveHelper()
+ accessible = JavaPsiFacade.getInstance(myPlace.getProject()).getResolveHelper()
.isAccessible(member, member.getModifierList(), myPlace, myAccessClass, myCurrentFileResolveContext);
- if (!accessProblem && member.hasModifierProperty(PsiModifier.PRIVATE) && myPlace instanceof PsiReferenceExpression && JavaVersionService.getInstance().isAtLeast(myPlace, JavaSdkVersion.JDK_1_7)) {
- accessProblem = isAccessedThroughTypeParameterBound();
+ if (accessible && member.hasModifierProperty(PsiModifier.PRIVATE) && myPlace instanceof PsiReferenceExpression && JavaVersionService.getInstance().isAtLeast(myPlace, JavaSdkVersion.JDK_1_7)) {
+ accessible = !isAccessedThroughTypeParameterBound();
}
}
- myAccessProblem = accessProblem ? Boolean.TRUE : Boolean.FALSE;
+ myAccessible = accessible;
}
- return !myAccessProblem.booleanValue();
+ else {
+ accessible = Accessible;
+ }
+ return accessible;
}
private boolean isAccessedThroughTypeParameterBound() {
@@ -143,16 +150,6 @@
return myCurrentFileResolveContext;
}
- private void setPackagePrefixPackageReference(boolean packagePrefixPackageReference) {
- myPackagePrefixPackageReference = packagePrefixPackageReference;
- }
-
- public static CandidateInfo createCandidateInfoForPackagePrefixPart() {
- final CandidateInfo candidateInfo = new CandidateInfo(null, PsiSubstitutor.EMPTY, false, false);
- candidateInfo.setPackagePrefixPackageReference(true);
- return candidateInfo;
- }
-
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -162,7 +159,7 @@
if (myPackagePrefixPackageReference != that.myPackagePrefixPackageReference) return false;
if (myStaticsProblem != that.myStaticsProblem) return false;
if (myAccessClass != null ? !myAccessClass.equals(that.myAccessClass) : that.myAccessClass != null) return false;
- if (myAccessProblem != null ? !myAccessProblem.equals(that.myAccessProblem) : that.myAccessProblem != null) return false;
+ if (isAccessible() != that.isAccessible()) return false;
if (myCandidate != null ? !myCandidate.equals(that.myCandidate) : that.myCandidate != null) return false;
if (myCurrentFileResolveContext != null
? !myCurrentFileResolveContext.equals(that.myCurrentFileResolveContext)
@@ -170,22 +167,23 @@
return false;
}
if (myPlace != null ? !myPlace.equals(that.myPlace) : that.myPlace != null) return false;
- if (mySubstitutor != null ? !mySubstitutor.equals(that.mySubstitutor) : that.mySubstitutor != null) return false;
-
- return true;
+ return mySubstitutor.equals(that.mySubstitutor);
}
+
public int hashCode() {
int result = myPlace != null ? myPlace.hashCode() : 0;
result = 31 * result + (myAccessClass != null ? myAccessClass.hashCode() : 0);
result = 31 * result + (myCandidate != null ? myCandidate.hashCode() : 0);
- result = 31 * result + (myAccessProblem != null ? myAccessProblem.hashCode() : 0);
+ result = 31 * result + (isAccessible() ? 1 : 0);
result = 31 * result + (myStaticsProblem ? 1 : 0);
- result = 31 * result + (mySubstitutor != null ? mySubstitutor.hashCode() : 0);
+ result = 31 * result + mySubstitutor.hashCode();
result = 31 * result + (myCurrentFileResolveContext != null ? myCurrentFileResolveContext.hashCode() : 0);
result = 31 * result + (myPackagePrefixPackageReference ? 1 : 0);
return result;
}
- public static final JavaResolveResult[] RESOLVE_RESULT_FOR_PACKAGE_PREFIX_PACKAGE = {createCandidateInfoForPackagePrefixPart()};
+ @NotNull
+ public static final JavaResolveResult[] RESOLVE_RESULT_FOR_PACKAGE_PREFIX_PACKAGE =
+ {new CandidateInfo(null, PsiSubstitutor.EMPTY, Boolean.TRUE, false, null, null, null, true)};
}
diff --git a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
index 0851f26..9b9174b 100644
--- a/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
+++ b/java/java-psi-api/src/com/intellij/psi/infos/MethodCandidateInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -40,11 +40,12 @@
public class MethodCandidateInfo extends CandidateInfo{
public static final RecursionGuard ourOverloadGuard = RecursionManager.createGuard("overload.guard");
public static final ThreadLocal<Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>>> CURRENT_CANDIDATE = new ThreadLocal<Map<PsiElement, Pair<PsiMethod, PsiSubstitutor>>>();
- @ApplicabilityLevelConstant private int myApplicabilityLevel = 0;
+ @ApplicabilityLevelConstant
+ private int myApplicabilityLevel; // benign race
private final PsiElement myArgumentList;
private final PsiType[] myArgumentTypes;
private final PsiType[] myTypeArguments;
- private PsiSubstitutor myCalcedSubstitutor = null;
+ private PsiSubstitutor myCalcedSubstitutor; // benign race
private final LanguageLevel myLanguageLevel;
public MethodCandidateInfo(PsiElement candidate,
@@ -103,45 +104,42 @@
return getApplicabilityLevel();
}
- final PsiMethod method = getElement();
- if (method != null && method.hasTypeParameters() || myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) {
- @ApplicabilityLevelConstant int level;
- if (myArgumentTypes == null) {
- return ApplicabilityLevel.NOT_APPLICABLE;
- }
- else {
- final PsiSubstitutor substitutor = getSubstitutor();
- Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable<Integer>() {
- @Override
- public Integer compute() {
- return PsiUtil.getApplicabilityLevel(getElement(), substitutor, myArgumentTypes, myLanguageLevel);
- }
- });
- level = boxedLevel != null ? boxedLevel : getApplicabilityLevel();
- }
- if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable()) level = ApplicabilityLevel.NOT_APPLICABLE;
- return level;
+ if (myArgumentTypes == null) {
+ return ApplicabilityLevel.NOT_APPLICABLE;
}
+
+ @ApplicabilityLevelConstant int level;
Integer boxedLevel = ourOverloadGuard.doPreventingRecursion(myArgumentList, false, new Computable<Integer>() {
@Override
public Integer compute() {
+
+ final PsiMethod method = getElement();
+ if (method != null && method.hasTypeParameters() || myArgumentList == null || !PsiUtil.isLanguageLevel8OrHigher(myArgumentList)) {
+ return PsiUtil.getApplicabilityLevel(getElement(), getSubstitutor(false), myArgumentTypes, myLanguageLevel);
+ }
return getApplicabilityLevelInner();
}
+
});
- return boxedLevel != null ? boxedLevel : getApplicabilityLevel();
+ level = boxedLevel != null ? boxedLevel : getApplicabilityLevel();
+ if (level > ApplicabilityLevel.NOT_APPLICABLE && !isTypeArgumentsApplicable(false)) level = ApplicabilityLevel.NOT_APPLICABLE;
+ return level;
}
public PsiSubstitutor getSiteSubstitutor() {
return super.getSubstitutor();
}
+ @NotNull
@Override
public PsiSubstitutor getSubstitutor() {
return getSubstitutor(true);
}
-
+
+ @NotNull
public PsiSubstitutor getSubstitutor(boolean includeReturnConstraint) {
- if (myCalcedSubstitutor == null || !includeReturnConstraint) {
+ PsiSubstitutor substitutor = myCalcedSubstitutor;
+ if (substitutor == null || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
PsiSubstitutor incompleteSubstitutor = super.getSubstitutor();
PsiMethod method = getElement();
if (myTypeArguments == null) {
@@ -149,32 +147,36 @@
final PsiSubstitutor inferredSubstitutor = inferTypeArguments(DefaultParameterTypeInferencePolicy.INSTANCE, includeReturnConstraint);
- if (!stackStamp.mayCacheNow() || !includeReturnConstraint) {
+ if (!stackStamp.mayCacheNow() || !includeReturnConstraint && myLanguageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
return inferredSubstitutor;
}
- myCalcedSubstitutor = inferredSubstitutor;
+ myCalcedSubstitutor = substitutor = inferredSubstitutor;
}
else {
PsiTypeParameter[] typeParams = method.getTypeParameters();
for (int i = 0; i < myTypeArguments.length && i < typeParams.length; i++) {
incompleteSubstitutor = incompleteSubstitutor.put(typeParams[i], myTypeArguments[i]);
}
- myCalcedSubstitutor = incompleteSubstitutor;
+ myCalcedSubstitutor = substitutor = incompleteSubstitutor;
}
}
- return myCalcedSubstitutor;
+ return substitutor;
}
public boolean isTypeArgumentsApplicable() {
+ return isTypeArgumentsApplicable(false);
+ }
+
+ public boolean isTypeArgumentsApplicable(boolean includeReturnConstraint) {
final PsiMethod psiMethod = getElement();
PsiTypeParameter[] typeParams = psiMethod.getTypeParameters();
if (myTypeArguments != null && typeParams.length != myTypeArguments.length && !PsiUtil.isLanguageLevel7OrHigher(psiMethod)){
return typeParams.length == 0 && JavaVersionService.getInstance().isAtLeast(psiMethod, JavaSdkVersion.JDK_1_7);
}
- PsiSubstitutor substitutor = getSubstitutor();
+ PsiSubstitutor substitutor = getSubstitutor(includeReturnConstraint);
return GenericsUtil.isTypeArgumentsApplicable(typeParams, substitutor, getParent());
}
@@ -192,6 +194,7 @@
return (PsiMethod)super.getElement();
}
+ @NotNull
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
return inferTypeArguments(policy, myArgumentList instanceof PsiExpressionList
? ((PsiExpressionList)myArgumentList).getExpressions()
@@ -215,6 +218,7 @@
}
}
+ @NotNull
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy,
@NotNull PsiExpression[] arguments,
boolean includeReturnConstraint) {
diff --git a/java/java-psi-api/src/com/intellij/psi/search/searches/DeepestSuperMethodsSearch.java b/java/java-psi-api/src/com/intellij/psi/search/searches/DeepestSuperMethodsSearch.java
index 543abd6..3be8a8d 100644
--- a/java/java-psi-api/src/com/intellij/psi/search/searches/DeepestSuperMethodsSearch.java
+++ b/java/java-psi-api/src/com/intellij/psi/search/searches/DeepestSuperMethodsSearch.java
@@ -24,7 +24,7 @@
* @author max
*/
public class DeepestSuperMethodsSearch extends ExtensibleQueryFactory<PsiMethod, PsiMethod> {
- public static ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.deepestSuperMethodsSearch");
+ public static final ExtensionPointName<QueryExecutor> EP_NAME = ExtensionPointName.create("com.intellij.deepestSuperMethodsSearch");
public static final DeepestSuperMethodsSearch DEEPEST_SUPER_METHODS_SEARCH_INSTANCE = new DeepestSuperMethodsSearch();
private DeepestSuperMethodsSearch() {
diff --git a/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java b/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java
index 5dc8bcb..304d6fa 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/InheritanceUtil.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.psi.*;
import com.intellij.util.Processor;
import gnu.trove.THashSet;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,6 +62,7 @@
return true;
}
+ @Contract("null, _ -> fail")
public static boolean isInheritor(@Nullable PsiType type, @NotNull @NonNls final String baseClassName) {
if (type instanceof PsiClassType) {
return isInheritor(((PsiClassType)type).resolve(), baseClassName);
@@ -69,10 +71,12 @@
return false;
}
+ @Contract("null, _ -> fail")
public static boolean isInheritor(@Nullable PsiClass psiClass, @NotNull final String baseClassName) {
return isInheritor(psiClass, false, baseClassName);
}
+ @Contract("null, _, _ -> fail")
public static boolean isInheritor(@Nullable PsiClass psiClass, final boolean strict, @NotNull final String baseClassName) {
if (psiClass == null) {
return false;
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
index 756543d..adc9306 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBackedByPsiMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -80,7 +80,7 @@
assert substitutor.isValid();
final PsiParameter[] parameters = method.getParameterList().getParameters();
- PsiType[] parameterTypes = new PsiType[parameters.length];
+ PsiType[] parameterTypes = PsiType.createArray(parameters.length);
for (int i = 0; i < parameterTypes.length; i++) {
PsiParameter parameter = parameters[i];
PsiType type = parameter.getType();
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java
index fe2bbae..150a39c 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -31,7 +31,7 @@
protected MethodSignatureBase(@NotNull PsiSubstitutor substitutor, @NotNull PsiType[] parameterTypes, @NotNull PsiTypeParameter[] typeParameters) {
mySubstitutor = substitutor;
assert substitutor.isValid();
- myParameterTypes = parameterTypes.length == 0 ? PsiType.EMPTY_ARRAY : new PsiType[parameterTypes.length];
+ myParameterTypes = PsiType.createArray(parameterTypes.length);
for (int i = 0; i < parameterTypes.length; i++) {
PsiType type = parameterTypes[i];
if (type != null) {
@@ -52,7 +52,7 @@
}
else {
final PsiParameter[] parameters = parameterList.getParameters();
- myParameterTypes = parameters.length == 0 ? PsiType.EMPTY_ARRAY : new PsiType[parameters.length];
+ myParameterTypes = PsiType.createArray(parameters.length);
for (int i = 0; i < parameters.length; i++) {
PsiType type = parameters[i].getType();
if (type instanceof PsiEllipsisType) type = ((PsiEllipsisType)type).toArrayType();
diff --git a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
index b514fa2..388da3b 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/MethodSignatureUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -72,7 +72,7 @@
if (parameterTypes.length == 0) return PsiType.EMPTY_ARRAY;
PsiSubstitutor substitutor = signature.getSubstitutor();
- PsiType[] erasedTypes = new PsiType[parameterTypes.length];
+ PsiType[] erasedTypes = PsiType.createArray(parameterTypes.length);
for (int i = 0; i < parameterTypes.length; i++) {
erasedTypes[i] = TypeConversionUtil.erasure(substitutor.substitute(parameterTypes[i]), substitutor);
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java
index d837685..2e126d1 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java
@@ -308,7 +308,8 @@
}
public static String suggestGetterName(@NotNull String propertyName, @Nullable PsiType propertyType, @NonNls String existingGetterName) {
- @NonNls StringBuilder name = new StringBuilder(StringUtil.capitalizeWithJavaBeanConvention(propertyName));
+ @NonNls StringBuilder name =
+ new StringBuilder(StringUtil.capitalizeWithJavaBeanConvention(StringUtil.sanitizeJavaIdentifier(propertyName)));
if (isBoolean(propertyType)) {
if (existingGetterName == null || !existingGetterName.startsWith("get")) {
name.insert(0, IS_PREFIX);
@@ -330,12 +331,13 @@
@NonNls
public static String[] suggestGetterNames(String propertyName) {
- final String str = StringUtil.capitalizeWithJavaBeanConvention(propertyName);
+ final String str = StringUtil.capitalizeWithJavaBeanConvention(StringUtil.sanitizeJavaIdentifier(propertyName));
return new String[] { IS_PREFIX + str, "get" + str };
}
public static String suggestSetterName(@NonNls String propertyName) {
- @NonNls StringBuilder name = new StringBuilder(StringUtil.capitalizeWithJavaBeanConvention(propertyName));
+ @NonNls StringBuilder name =
+ new StringBuilder(StringUtil.capitalizeWithJavaBeanConvention(StringUtil.sanitizeJavaIdentifier(propertyName)));
name.insert(0, "set");
return name.toString();
}
diff --git a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
index 926b88b..385e3a6 100644
--- a/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
+++ b/java/java-psi-api/src/com/intellij/psi/util/TypeConversionUtil.java
@@ -71,6 +71,7 @@
return true;
}
+ @NotNull
@Override
@NonNls
public String getPresentableText() {
@@ -1023,7 +1024,7 @@
* <code>InheritanceUtil.isInheritor(derivedClass, superClass, true)</code>
*
* @return substitutor (never returns <code>null</code>)
- * @see PsiClass#isInheritor(PsiClass, PsiClass, boolean)
+ * @see PsiClass#isInheritor(PsiClass, boolean)
*/
@NotNull
public static PsiSubstitutor getSuperClassSubstitutor(@NotNull PsiClass superClass,
@@ -1057,7 +1058,7 @@
substitutor = getSuperClassSubstitutorInner(superClass, derivedClass, derivedSubstitutor, visited, manager);
}
if (substitutor == null) {
- if (ourReportedSuperClassSubstitutorExceptions.add(derivedClass.getQualifiedName())) {
+ if (ourReportedSuperClassSubstitutorExceptions.add(derivedClass.getQualifiedName() + "/" + superClass.getQualifiedName())) {
final StringBuilder msg = new StringBuilder("Super: " + classInfo(superClass));
msg.append("visited:\n");
for (PsiClass aClass : visited) {
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
index 9c9b2fa..05b516e 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/BaseExternalAnnotationsManager.java
@@ -22,7 +22,6 @@
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -52,7 +51,7 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.BaseExternalAnnotationsManager");
@NotNull private static final List<PsiFile> NULL_LIST = new ArrayList<PsiFile>(0);
@NotNull
- private final ConcurrentMap<String, List<PsiFile>> myExternalAnnotations = new ConcurrentSoftValueHashMap<String, List<PsiFile>>(10, 0.75f, 2);
+ private final ConcurrentMap<VirtualFile, List<PsiFile>> myExternalAnnotations = new ConcurrentSoftValueHashMap<VirtualFile, List<PsiFile>>(10, 0.75f, 2);
protected final PsiManager myPsiManager;
@SuppressWarnings("UnusedDeclaration")
@@ -72,13 +71,6 @@
return PsiFormatUtil.getExternalName(listOwner, showParamName, Integer.MAX_VALUE);
}
- @Nullable
- private static String getFQN(@NotNull String packageName, @NotNull PsiFile psiFile) {
- VirtualFile virtualFile = psiFile.getVirtualFile();
- if (virtualFile == null) return null;
- return StringUtil.getQualifiedName(packageName, virtualFile.getNameWithoutExtension());
- }
-
protected abstract boolean hasAnyAnnotationsRoots();
@Override
@@ -230,9 +222,9 @@
final PsiJavaFile javaFile = (PsiJavaFile)containingFile;
final String packageName = javaFile.getPackageName();
final VirtualFile virtualFile = containingFile.getVirtualFile();
- String fqn = getFQN(packageName, containingFile);
- if (fqn == null) return null;
- final List<PsiFile> files = myExternalAnnotations.get(fqn);
+ if (virtualFile == null) return null;
+
+ final List<PsiFile> files = myExternalAnnotations.get(virtualFile);
if (files == NULL_LIST) return null;
if (files != null) {
boolean allValid = true;
@@ -258,7 +250,7 @@
}
List<PsiFile> result;
if (possibleAnnotationsXmls.isEmpty()) {
- myExternalAnnotations.put(fqn, NULL_LIST);
+ myExternalAnnotations.put(virtualFile, NULL_LIST);
result = null;
}
else {
@@ -276,7 +268,7 @@
}
});
- myExternalAnnotations.put(fqn, result);
+ myExternalAnnotations.put(virtualFile, result);
}
return result;
}
@@ -344,9 +336,9 @@
}
protected void cacheExternalAnnotations(@NotNull String packageName, @NotNull PsiFile fromFile, @NotNull List<PsiFile> annotationFiles) {
- String fqn = getFQN(packageName, fromFile);
- if (fqn != null) {
- myExternalAnnotations.put(fqn, annotationFiles);
+ VirtualFile virtualFile = fromFile.getVirtualFile();
+ if (virtualFile != null) {
+ myExternalAnnotations.put(virtualFile, annotationFiles);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java b/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java
index 530c87c..74d06d2 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/daemon/JavaErrorMessages.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -24,16 +24,15 @@
* @author max
*/
public class JavaErrorMessages extends AbstractBundle {
- public static final JavaErrorMessages INSTANCE = new JavaErrorMessages();
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return INSTANCE.getMessage(key, params);
+ }
+
+ public static final JavaErrorMessages INSTANCE = new JavaErrorMessages();
@NonNls public static final String BUNDLE = "messages.JavaErrorMessages";
private JavaErrorMessages() {
super(BUNDLE);
}
-
- @NotNull
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return INSTANCE.getMessage(key, params);
- }
}
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaCodeFoldingSettingsBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaCodeFoldingSettingsBase.java
index c092b53..ee3ff0c 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaCodeFoldingSettingsBase.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaCodeFoldingSettingsBase.java
@@ -4,7 +4,8 @@
import com.intellij.codeInsight.folding.JavaCodeFoldingSettings;
public class JavaCodeFoldingSettingsBase extends JavaCodeFoldingSettings {
- @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_ACCESSORS = true;
+ @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_ACCESSORS = false;
+ @SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_ONE_LINE_METHODS = true;
@SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_INNER_CLASSES = false;
@SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_ANONYMOUS_CLASSES = false;
@SuppressWarnings({"WeakerAccess"}) public boolean COLLAPSE_ANNOTATIONS = false;
@@ -63,6 +64,10 @@
public void setCollapseAccessors(boolean value) {
COLLAPSE_ACCESSORS = value;
}
+ @Override
+ public boolean isCollapseOneLineMethods() {
+ return COLLAPSE_ONE_LINE_METHODS;
+ }
@Override
public boolean isCollapseInnerClasses() {
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
index 712bbad..c1875bc 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/folding/impl/JavaFoldingBuilderBase.java
@@ -7,6 +7,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.CustomFoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
+import com.intellij.lang.folding.NamedFoldingDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldingGroup;
@@ -69,11 +70,16 @@
return "...";
}
+ private static boolean areOnAdjacentLines(PsiElement e1, PsiElement e2, Document document) {
+ return document.getLineNumber(e1.getTextRange().getEndOffset()) + 1 == document.getLineNumber(e2.getTextRange().getStartOffset());
+ }
+
private static boolean isSimplePropertyAccessor(PsiMethod method) {
PsiCodeBlock body = method.getBody();
if (body == null || body.getLBrace() == null || body.getRBrace() == null) return false;
PsiStatement[] statements = body.getStatements();
if (statements.length == 0) return false;
+
PsiStatement statement = statements[0];
if (PropertyUtil.isSimplePropertyGetter(method)) {
if (statement instanceof PsiReturnStatement) {
@@ -521,8 +527,8 @@
if (child instanceof PsiMethod) {
PsiMethod method = (PsiMethod)child;
- boolean accessor = isSimplePropertyAccessor(method) && addInlineAccessorFolding(list, method);
- if (!accessor) {
+ boolean oneLiner = addOneLineMethodFolding(list, method);
+ if (!oneLiner) {
addToFold(list, method, document, true);
}
addAnnotationsToFold(method.getModifierList(), list, document);
@@ -535,7 +541,7 @@
}
PsiCodeBlock body = method.getBody();
- if (body != null && !accessor) {
+ if (body != null && !oneLiner) {
addCodeBlockFolds(body, list, processedComments, document, quick);
}
}
@@ -569,23 +575,34 @@
}
}
- private static boolean addInlineAccessorFolding(List<FoldingDescriptor> descriptorList, PsiMethod accessor) {
- if (!JavaCodeFoldingSettings.getInstance().isCollapseAccessors()) {
+ private boolean addOneLineMethodFolding(List<FoldingDescriptor> descriptorList, PsiMethod method) {
+ if (!JavaCodeFoldingSettings.getInstance().isCollapseOneLineMethods()) {
return false;
}
- PsiCodeBlock body = accessor.getBody();
- assert body != null;
- if (body.getStatements().length > 1) {
+ Document document = method.getContainingFile().getViewProvider().getDocument();
+ PsiCodeBlock body = method.getBody();
+ if (body == null || document == null) {
+ return false;
+ }
+ PsiJavaToken lBrace = body.getLBrace();
+ PsiJavaToken rBrace = body.getRBrace();
+ PsiStatement[] statements = body.getStatements();
+ if (lBrace == null || rBrace == null || statements.length != 1) {
return false;
}
- PsiStatement statement = body.getStatements()[0];
+ PsiStatement statement = statements[0];
if (statement.textContains('\n')) {
return false;
}
- int leftStart = accessor.getParameterList().getTextRange().getEndOffset();
+ if (!areOnAdjacentLines(lBrace, statement, document) || !areOnAdjacentLines(statement, rBrace, document)) {
+ //the user might intend to type at an empty line
+ return false;
+ }
+
+ int leftStart = method.getParameterList().getTextRange().getEndOffset();
int leftEnd = statement.getTextRange().getStartOffset();
int rightStart = statement.getTextRange().getEndOffset();
int rightEnd = body.getTextRange().getEndOffset();
@@ -593,29 +610,18 @@
return false;
}
- FoldingGroup group = FoldingGroup.newGroup("simple property accessor");
- PsiJavaToken lBrace = body.getLBrace();
- assert lBrace != null;
- descriptorList.add(new FoldingDescriptor(lBrace.getNode(), new TextRange(leftStart, leftEnd), group) {
- @Nullable
- @Override
- public String getPlaceholderText() {
- return " { ";
- }
- });
+ String leftText = " { ";
+ String rightText = " }";
+ if (!fitsRightMargin(method, document, leftStart, rightEnd, rightStart - leftEnd + leftText.length() + rightText.length())) {
+ return false;
+ }
- PsiJavaToken rBrace = body.getRBrace();
- assert rBrace != null;
- descriptorList.add(new FoldingDescriptor(rBrace.getNode(), new TextRange(rightStart, rightEnd), group) {
- @Nullable
- @Override
- public String getPlaceholderText() {
- return " }";
- }
- });
+ FoldingGroup group = FoldingGroup.newGroup("one-liner");
+ descriptorList.add(new NamedFoldingDescriptor(lBrace, leftStart, leftEnd, group, leftText));
+ descriptorList.add(new NamedFoldingDescriptor(rBrace, rightStart, rightEnd, group, rightText));
return true;
}
-
+
@Override
protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) {
return getPlaceholderText(SourceTreeToPsiMap.treeElementToPsi(node));
@@ -632,7 +638,7 @@
if (element instanceof PsiJavaToken &&
element.getParent() instanceof PsiCodeBlock &&
element.getParent().getParent() instanceof PsiMethod) {
- return settings.isCollapseAccessors();
+ return settings.isCollapseOneLineMethods();
}
if (element instanceof PsiReferenceParameterList) {
return settings.isCollapseConstructorGenericParameters();
@@ -642,9 +648,6 @@
return settings.isCollapseImports();
}
else if (element instanceof PsiMethod || element instanceof PsiClassInitializer || element instanceof PsiCodeBlock) {
- if (!settings.isCollapseAccessors() && !settings.isCollapseMethods()) {
- return false;
- }
if (element instanceof PsiMethod && isSimplePropertyAccessor((PsiMethod)element)) {
return settings.isCollapseAccessors();
}
@@ -787,41 +790,22 @@
final int closureEnd = expression.getTextRange().getEndOffset();
boolean oneLine = false;
String contents = seq.subSequence(firstLineStart, lastLineEnd).toString();
- if (contents.indexOf('\n') < 0) {
- final int beforeLength = closureStart - document.getLineStartOffset(document.getLineNumber(closureStart));
- final int afterLength = document.getLineEndOffset(document.getLineNumber(closureEnd)) - closureEnd;
- final int resultLineLength = beforeLength + lambdas.length() + contents.length() + 5 + afterLength;
-
- if (isBelowRightMargin(aClass.getProject(), resultLineLength)) {
- rangeStart = CharArrayUtil.shiftForward(seq, rangeStart, " \n\t");
- rangeEnd = CharArrayUtil.shiftBackward(seq, rangeEnd - 1, " \n\t") + 1;
- oneLine = true;
- }
+ if (contents.indexOf('\n') < 0 &&
+ fitsRightMargin(aClass, document, closureStart, closureEnd, lambdas.length() + contents.length() + 5)) {
+ rangeStart = CharArrayUtil.shiftForward(seq, rangeStart, " \n\t");
+ rangeEnd = CharArrayUtil.shiftBackward(seq, rangeEnd - 1, " \n\t") + 1;
+ oneLine = true;
}
if (rangeStart >= rangeEnd) return false;
FoldingGroup group = FoldingGroup.newGroup("lambda");
-
final String prettySpace = oneLine ? " " : "";
-
- foldElements.add(
- new FoldingDescriptor(expression.getNode(), new TextRange(closureStart, rangeStart), group) {
- @Override
- public String getPlaceholderText() {
- return lambdas + prettySpace;
- }
- });
-
+ foldElements.add(new NamedFoldingDescriptor(expression, closureStart, rangeStart, group, lambdas + prettySpace));
if (rbrace != null && rangeEnd + 1 < closureEnd) {
- foldElements
- .add(new FoldingDescriptor(rbrace.getNode(), new TextRange(rangeEnd, closureEnd), group) {
- @Override
- public String getPlaceholderText() {
- return prettySpace + "}";
- }
- });
+ foldElements.add(new NamedFoldingDescriptor(rbrace, rangeEnd, closureEnd, group, prettySpace + "}"));
}
+
addCodeBlockFolds(body, foldElements, processedComments, document, quick);
}
}
@@ -831,6 +815,12 @@
return isClosure;
}
+ private boolean fitsRightMargin(PsiElement element, Document document, int foldingStart, int foldingEnd, int collapsedLength) {
+ final int beforeLength = foldingStart - document.getLineStartOffset(document.getLineNumber(foldingStart));
+ final int afterLength = document.getLineEndOffset(document.getLineNumber(foldingEnd)) - foldingEnd;
+ return isBelowRightMargin(element.getProject(), beforeLength + collapsedLength + afterLength);
+ }
+
protected abstract boolean isBelowRightMargin (Project project, final int lineLength);
@Override
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
index f8991e6..c64baf2 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/generation/OverrideImplementExploreUtil.java
@@ -9,10 +9,7 @@
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.infos.CandidateInfo;
-import com.intellij.psi.util.MethodSignature;
-import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
-import com.intellij.psi.util.MethodSignatureUtil;
-import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.*;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -47,12 +44,12 @@
Map<MethodSignature, PsiMethod> finals = new LinkedHashMap<MethodSignature,PsiMethod>();
Map<MethodSignature, PsiMethod> concretes = new LinkedHashMap<MethodSignature,PsiMethod>();
- LOG.assertTrue(aClass.isValid());
+ PsiUtilCore.ensureValid(aClass);
Collection<HierarchicalMethodSignature> allMethodSigs = aClass.getVisibleSignatures();
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper();
for (HierarchicalMethodSignature signature : allMethodSigs) {
PsiMethod method = signature.getMethod();
- LOG.assertTrue(method.isValid(), aClass);
+ PsiUtilCore.ensureValid(method);
if (method.hasModifierProperty(PsiModifier.STATIC) || !resolveHelper.isAccessible(method, aClass, aClass)) continue;
PsiClass hisClass = method.getContainingClass();
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
index 23b1d30..ab07fc2 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
@@ -27,6 +27,7 @@
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
@@ -58,19 +59,21 @@
public class JavaDocInfoGenerator {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocInfoGenerator");
- private static final @NonNls Pattern ourNotDot = Pattern.compile("[^.]");
- private static final @NonNls Pattern ourWhitespaces = Pattern.compile("[ \\n\\r\\t]+");
+ @NonNls private static final Pattern ourNotDot = Pattern.compile("[^.]");
+ @NonNls private static final Pattern ourWhitespaces = Pattern.compile("[ \\n\\r\\t]+");
- private static final @NonNls String THROWS_KEYWORD = "throws";
- private static final @NonNls String BR_TAG = "<br>";
- private static final @NonNls String LINK_TAG = "link";
- private static final @NonNls String LITERAL_TAG = "literal";
- private static final @NonNls String CODE_TAG = "code";
- private static final @NonNls String LINKPLAIN_TAG = "linkplain";
- private static final @NonNls String INHERITDOC_TAG = "inheritDoc";
- private static final @NonNls String DOCROOT_TAG = "docRoot";
- private static final @NonNls String VALUE_TAG = "value";
-
+ @NonNls private static final String THROWS_KEYWORD = "throws";
+ @NonNls private static final String BR_TAG = "<br>";
+ @NonNls private static final String LINK_TAG = "link";
+ @NonNls private static final String LITERAL_TAG = "literal";
+ @NonNls private static final String CODE_TAG = "code";
+ @NonNls private static final String LINKPLAIN_TAG = "linkplain";
+ @NonNls private static final String INHERITDOC_TAG = "inheritDoc";
+ @NonNls private static final String DOCROOT_TAG = "docRoot";
+ @NonNls private static final String VALUE_TAG = "value";
+ private static final String LT = "<";
+ private static final String GT = ">";
+
private final Project myProject;
private final PsiElement myElement;
@@ -204,7 +207,7 @@
@Nullable
private static String fixupDoc(@NotNull final StringBuilder buffer) {
String text = buffer.toString();
- if (text.length() == 0) {
+ if (text.isEmpty()) {
return null;
}
if (LOG.isDebugEnabled()) {
@@ -253,14 +256,14 @@
return null;
if (docURLs != null) {
- StringBuilder errorsSection = new StringBuilder("<p id=\"error\">Following external urls were checked:<br> <i>");
- errorsSection.append(StringUtil.join(docURLs, "</i><br> <i>"));
- errorsSection.append("</i><br>The documentation for this element is not found. Please add all the needed paths to API docs in ");
- errorsSection.append("<a href=\"open://Project Settings\">Project Settings.</a></p>");
if (buffer.length() == 0) {
buffer.append("<html><body></body></html>");
}
- buffer.insert(buffer.indexOf("<body>"), errorsSection.toString());
+ String errorSection = "<p id=\"error\">Following external urls were checked:<br> <i>" +
+ StringUtil.join(docURLs, "</i><br> <i>") +
+ "</i><br>The documentation for this element is not found. Please add all the needed paths to API docs in " +
+ "<a href=\"open://Project Settings\">Project Settings.</a></p>";
+ buffer.insert(buffer.indexOf("<body>"), errorSection);
}
return fixupDoc(buffer);
}
@@ -274,7 +277,7 @@
PsiFile file = aClass.getContainingFile();
if (file instanceof PsiJavaFile) {
String packageName = ((PsiJavaFile)file).getPackageName();
- if (packageName.length() > 0) {
+ if (!packageName.isEmpty()) {
buffer.append("<small><b>");
buffer.append(packageName);
buffer.append("</b></small>");
@@ -285,7 +288,7 @@
buffer.append("<PRE>");
generateAnnotations(buffer, aClass);
String modifiers = PsiFormatUtil.formatModifiers(aClass, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
- if (modifiers.length() > 0) {
+ if (!modifiers.isEmpty()) {
buffer.append(modifiers);
buffer.append(" ");
}
@@ -445,7 +448,7 @@
buffer.append("<PRE>");
generateAnnotations(buffer, field);
String modifiers = PsiFormatUtil.formatModifiers(field, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
- if (modifiers.length() > 0) {
+ if (!modifiers.isEmpty()) {
buffer.append(modifiers);
buffer.append(" ");
}
@@ -487,7 +490,7 @@
buffer.append("<PRE>");
String modifiers = PsiFormatUtil.formatModifiers(variable, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
- if (modifiers.length() > 0) {
+ if (!modifiers.isEmpty()) {
buffer.append(modifiers);
buffer.append(" ");
}
@@ -558,7 +561,7 @@
String htmlText = packageHtmlFile.getText();
try {
- final Document document = JDOMUtil.loadDocument(new ByteArrayInputStream(htmlText.getBytes()));
+ final Document document = JDOMUtil.loadDocument(new ByteArrayInputStream(htmlText.getBytes(CharsetToolkit.UTF8_CHARSET)));
final Element rootTag = document.getRootElement();
if (rootTag != null) {
final Element subTag = rootTag.getChild("body");
@@ -663,7 +666,7 @@
}
}
- private static void generateAnnotations(@NonNls StringBuilder buffer, PsiModifierListOwner owner) {
+ private static void generateAnnotations(@NonNls @NotNull StringBuilder buffer, @NotNull PsiModifierListOwner owner) {
final PsiModifierList ownerModifierList = owner.getModifierList();
if (ownerModifierList == null) return;
PsiAnnotation[] annotations = ownerModifierList.getAnnotations();
@@ -685,8 +688,8 @@
generateType(buffer, type, owner);
final PsiNameValuePair[] attributes = annotation.getParameterList().getAttributes();
if (attributes.length > 0) {
- boolean first = true;
buffer.append("(");
+ boolean first = true;
for (PsiNameValuePair pair : attributes) {
if (!first) buffer.append(" ");
first = false;
@@ -719,7 +722,7 @@
buffer.append("<PRE>");
String modifiers = PsiFormatUtil.formatModifiers(parameter, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
- if (modifiers.length() > 0) {
+ if (!modifiers.isEmpty()) {
buffer.append(modifiers);
buffer.append(" ");
}
@@ -768,18 +771,18 @@
}
buffer.append("<PRE>");
- int indent = 0;
generateAnnotations(buffer, method);
String modifiers = PsiFormatUtil.formatModifiers(method, PsiFormatUtilBase.JAVADOC_MODIFIERS_ONLY);
- if (modifiers.length() > 0) {
+ int indent = 0;
+ if (!modifiers.isEmpty()) {
buffer.append(modifiers);
buffer.append(" ");
indent += modifiers.length() + 1;
}
final String typeParamsString = generateTypeParameters(method);
- indent += typeParamsString.length();
- if (typeParamsString.length() > 0) {
+ indent += StringUtil.unescapeXml(StringUtil.stripHtml(typeParamsString, true)).length();
+ if (!typeParamsString.isEmpty()) {
buffer.append(typeParamsString);
buffer.append(" ");
indent++;
@@ -970,7 +973,7 @@
String text = description.getText();
if (text != null) {
- if (ourWhitespaces.matcher(text).replaceAll("").length() != 0) {
+ if (!ourWhitespaces.matcher(text).replaceAll("").isEmpty()) {
return false;
}
}
@@ -1040,7 +1043,7 @@
}
private String getDocRoot() {
- PsiClass aClass = null;
+ PsiClass aClass;
if (myElement instanceof PsiClass) {
aClass = (PsiClass)myElement;
@@ -1080,10 +1083,7 @@
if (element instanceof PsiInlineDocTag) {
PsiInlineDocTag tag = (PsiInlineDocTag)element;
final String tagName = tag.getName();
- if (tagName == null) {
- buffer.append(element.getText());
- }
- else if (tagName.equals(LINK_TAG)) {
+ if (tagName.equals(LINK_TAG)) {
generateLinkValue(tag, buffer, false);
}
else if (tagName.equals(LITERAL_TAG)) {
@@ -1132,20 +1132,20 @@
}
private static void appendPlainText(@NonNls String text, final StringBuilder buffer) {
- text = text.replaceAll("<", "<");
- text = text.replaceAll(">", ">");
+ text = text.replaceAll("<", LT);
+ text = text.replaceAll(">", GT);
buffer.append(text);
}
- private void generateLinkValue(PsiInlineDocTag tag, StringBuilder buffer, boolean plainLink) {
+ private static void generateLinkValue(PsiInlineDocTag tag, StringBuilder buffer, boolean plainLink) {
PsiElement[] tagElements = tag.getDataElements();
String text = createLinkText(tagElements);
- if (text.length() > 0) {
+ if (!text.isEmpty()) {
int index = JavaDocUtil.extractReference(text);
String refText = text.substring(0, index).trim();
String label = text.substring(index).trim();
- if (label.length() == 0) {
+ if (label.isEmpty()) {
label = null;
}
generateLink(buffer, refText, label, tagElements[0], plainLink);
@@ -1155,7 +1155,7 @@
private void generateValueValue(final PsiInlineDocTag tag, final StringBuilder buffer, final PsiElement element) {
String text = createLinkText(tag.getDataElements());
PsiField valueField = null;
- if (text.length() == 0) {
+ if (text.isEmpty()) {
if (myElement instanceof PsiField) valueField = (PsiField) myElement;
}
else {
@@ -1172,7 +1172,7 @@
}
if (value != null) {
- buffer.append(value.toString());
+ buffer.append(value);
}
else {
buffer.append(element.getText());
@@ -1225,7 +1225,7 @@
}
@SuppressWarnings({"HardCodedStringLiteral"})
- private void generateSeeAlsoSection(StringBuilder buffer, PsiDocComment comment) {
+ private static void generateSeeAlsoSection(StringBuilder buffer, PsiDocComment comment) {
PsiDocTag[] tags = comment.findTagsByName("see");
if (tags.length > 0) {
buffer.append("<DD><DL>");
@@ -1247,7 +1247,7 @@
int index = JavaDocUtil.extractReference(text);
String refText = text.substring(0, index).trim();
String label = text.substring(index).trim();
- if (label.length() == 0) {
+ if (label.isEmpty()) {
label = null;
}
generateLink(buffer, refText, label, comment, false);
@@ -1278,7 +1278,7 @@
}
}
- if (collectedTags.size() > 0) {
+ if (!collectedTags.isEmpty()) {
buffer.append("<DD><DL>");
buffer.append("<DT><b>").append(CodeInsightBundle.message("javadoc.parameters")).append("</b>");
for (Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag : collectedTags) {
@@ -1308,7 +1308,7 @@
}
private void generateTypeParametersSection(final StringBuilder buffer, final LinkedList<Pair<PsiDocTag, InheritDocProvider<PsiDocTag>>> collectedTags) {
- if (collectedTags.size() > 0) {
+ if (!collectedTags.isEmpty()) {
buffer.append("<DD><DL>");
buffer.append("<DT><b>").append(CodeInsightBundle.message("javadoc.type.parameters")).append("</b>");
for (Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag : collectedTags) {
@@ -1394,7 +1394,7 @@
});
if (pair == null && myElement instanceof PsiMethod) {
- pair = findInheritDocTag(((PsiMethod)myElement), new ReturnTagLocator());
+ pair = findInheritDocTag((PsiMethod)myElement, new ReturnTagLocator());
}
if (pair != null) {
@@ -1498,7 +1498,7 @@
}
}
- if (collectedTags.size() > 0) {
+ if (!collectedTags.isEmpty()) {
buffer.append("<DD><DL>");
buffer.append("<DT><b>").append(CodeInsightBundle.message("javadoc.throws")).append("</b>");
for (Pair<PsiDocTag, InheritDocProvider<PsiDocTag>> tag : collectedTags) {
@@ -1510,7 +1510,7 @@
String refText = text.substring(0, index).trim();
generateLink(buffer, refText, null, method, false);
String rest = text.substring(index);
- if (rest.length() > 0 || elements.length > 1) buffer.append(" - ");
+ if (!rest.isEmpty() || elements.length > 1) buffer.append(" - ");
buffer.append(rest);
generateValue(buffer, elements, 1, mapProvider(tag.second, true));
}
@@ -1519,7 +1519,7 @@
}
@SuppressWarnings({"HardCodedStringLiteral"})
- private void generateSuperMethodsSection(StringBuilder buffer, PsiMethod method, boolean overrides) {
+ private static void generateSuperMethodsSection(StringBuilder buffer, PsiMethod method, boolean overrides) {
PsiClass parentClass = method.getContainingClass();
if (parentClass == null) return;
if (parentClass.isInterface() && !overrides) return;
@@ -1589,12 +1589,12 @@
buffer.append("<font color=red>");
buffer.append(label);
buffer.append("</font>");
- return label.length();
+ return StringUtil.stripHtml(label, true).length();
}
generateLink(buffer, target, label, plainLink);
- return label.length();
+ return StringUtil.stripHtml(label, true).length();
}
/**
@@ -1618,7 +1618,7 @@
if (type instanceof PsiArrayType) {
int rest = generateType(buffer, ((PsiArrayType)type).getComponentType(), context, generateLink);
- if ((type instanceof PsiEllipsisType)) {
+ if (type instanceof PsiEllipsisType) {
buffer.append("...");
return rest + 3;
}
@@ -1633,7 +1633,7 @@
}
if (type instanceof PsiWildcardType){
- PsiWildcardType wt = ((PsiWildcardType)type);
+ PsiWildcardType wt = (PsiWildcardType)type;
buffer.append("?");
@@ -1654,9 +1654,10 @@
PsiSubstitutor psiSubst = result.getSubstitutor();
if (psiClass == null) {
- String text = "<font color=red>" + StringUtil.escapeXml(type.getCanonicalText()) + "</font>";
+ String canonicalText = type.getCanonicalText();
+ String text = "<font color=red>" + StringUtil.escapeXml(canonicalText) + "</font>";
buffer.append(text);
- return text.length();
+ return canonicalText.length();
}
String qName = psiClass.getQualifiedName();
@@ -1678,11 +1679,12 @@
if (psiClass.hasTypeParameters()) {
StringBuilder subst = new StringBuilder();
- boolean goodSubst = true;
PsiTypeParameter[] params = psiClass.getTypeParameters();
- subst.append("<");
+ subst.append(LT);
+ length += 1;
+ boolean goodSubst = true;
for (int i = 0; i < params.length; i++) {
PsiType t = psiSubst.substitute(params[i]);
@@ -1698,7 +1700,8 @@
}
}
- subst.append(">");
+ subst.append(GT);
+ length += 1;
if (goodSubst) {
String text = subst.toString();
@@ -1711,12 +1714,12 @@
if (type instanceof PsiDisjunctionType || type instanceof PsiIntersectionType) {
if (!generateLink) {
- final String text = StringUtil.escapeXml(type.getCanonicalText());
+ String canonicalText = type.getCanonicalText();
+ final String text = StringUtil.escapeXml(canonicalText);
buffer.append(text);
- return text.length();
+ return canonicalText.length();
}
else {
- int length = 0;
final String separator = type instanceof PsiDisjunctionType ? " | " : " & ";
final List<PsiType> componentTypes;
if (type instanceof PsiIntersectionType) {
@@ -1725,6 +1728,7 @@
else {
componentTypes = ((PsiDisjunctionType)type).getDisjunctions();
}
+ int length = 0;
for (PsiType psiType : componentTypes) {
if (length > 0) {
buffer.append(separator);
@@ -1740,13 +1744,13 @@
}
@SuppressWarnings({"HardCodedStringLiteral"})
- private String generateTypeParameters(PsiTypeParameterListOwner owner) {
+ private static String generateTypeParameters(PsiTypeParameterListOwner owner) {
if (owner.hasTypeParameters()) {
PsiTypeParameter[] parms = owner.getTypeParameters();
StringBuilder buffer = new StringBuilder();
- buffer.append("<");
+ buffer.append(LT);
for (int i = 0; i < parms.length; i++) {
PsiTypeParameter p = parms[i];
@@ -1772,7 +1776,7 @@
}
}
- buffer.append(">");
+ buffer.append(GT);
return buffer.toString();
}
@@ -1812,15 +1816,14 @@
}
@Nullable
- private <T> PsiMethod findMethodInSuperClass(PsiMethod method, PsiClass aSuper) {
- PsiMethod overriden = null;
+ private static PsiMethod findMethodInSuperClass(PsiMethod method, PsiClass aSuper) {
for (PsiMethod superMethod : method.findDeepestSuperMethods()) {
- overriden = aSuper.findMethodBySignature(superMethod, false);
+ PsiMethod overriden = aSuper.findMethodBySignature(superMethod, false);
if (overriden != null) {
return overriden;
}
}
- return overriden;
+ return null;
}
@Nullable private <T> Pair<T, InheritDocProvider<T>> searchDocTagInSupers(PsiClassType[] supers,
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java
index 2420717..8a686f8 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -32,7 +32,7 @@
public class JavaDocUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocUtil");
- private static final @NonNls Pattern ourTypePattern = Pattern.compile("[ ]+[^ ^\\[^\\]]");
+ @NonNls private static final Pattern ourTypePattern = Pattern.compile("[ ]+[^ ^\\[^\\]]");
private JavaDocUtil() {
}
@@ -81,7 +81,7 @@
}
else {
String classRef = refText.substring(0, poundIndex).trim();
- if (classRef.length() > 0) {
+ if (!classRef.isEmpty()) {
PsiClass aClass = facade.getResolveHelper().resolveReferencedClass(classRef, context);
if (aClass == null) aClass = facade.findClass(classRef, context.getResolveScope());
@@ -127,7 +127,7 @@
String parmsText = memberRefText.substring(parenthIndex + 1, rparenIndex).trim();
StringTokenizer tokenizer = new StringTokenizer(parmsText.replaceAll("[*]", ""), ",");
- PsiType[] types = new PsiType[tokenizer.countTokens()];
+ PsiType[] types = PsiType.createArray(tokenizer.countTokens());
int i = 0;
PsiElementFactory factory = JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory();
while (tokenizer.hasMoreTokens()) {
@@ -290,7 +290,7 @@
String classRef = refText.substring(0, poundIndex).trim();
String memberText = refText.substring(poundIndex + 1);
String memberLabel = getMemberLabelText(project, manager, memberText, context);
- if (classRef.length() > 0) {
+ if (!classRef.isEmpty()) {
PsiElement refClass = findReferenceTarget(manager, classRef, context);
if (refClass instanceof PsiClass) {
PsiElement scope = context;
diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java
index f769a60..a012988 100644
--- a/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java
+++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaFileManager.java
@@ -198,10 +198,6 @@
return Collections.emptyList();
}
- @Override
- public void initialize() {
- }
-
public void addToClasspath(VirtualFile root) {
myClasspath.add(root);
}
diff --git a/java/java-psi-impl/src/com/intellij/core/CoreJavaPsiImplementationHelper.java b/java/java-psi-impl/src/com/intellij/core/CoreJavaPsiImplementationHelper.java
index e785272..21b6151 100644
--- a/java/java-psi-impl/src/com/intellij/core/CoreJavaPsiImplementationHelper.java
+++ b/java/java-psi-impl/src/com/intellij/core/CoreJavaPsiImplementationHelper.java
@@ -31,6 +31,7 @@
return psiClass;
}
+ @NotNull
@Override
public PsiElement getClsFileNavigationElement(PsiJavaFile clsFile) {
return clsFile;
@@ -52,7 +53,7 @@
}
@Override
- public void setupCatchBlock(String exceptionName, PsiElement context, PsiCatchSection element) {
+ public void setupCatchBlock(@NotNull String exceptionName, @NotNull PsiType exceptionType, PsiElement context, @NotNull PsiCatchSection element) {
throw new UnsupportedOperationException("TODO");
}
}
diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java
index 51ae457..cfe57a3 100644
--- a/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.java
+++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreApplicationEnvironment.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.
@@ -26,6 +26,9 @@
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.openapi.fileTypes.PlainTextLanguage;
+import com.intellij.openapi.fileTypes.PlainTextParserDefinition;
import com.intellij.openapi.projectRoots.JavaVersionService;
import com.intellij.openapi.util.ClassExtension;
import com.intellij.openapi.util.Disposer;
@@ -36,9 +39,9 @@
import com.intellij.psi.impl.PsiExpressionEvaluator;
import com.intellij.psi.impl.compiled.ClassFileStubBuilder;
import com.intellij.psi.impl.compiled.ClsStubBuilderFactory;
-import com.intellij.psi.impl.compiled.DefaultClsStubBuilderFactory;
import com.intellij.psi.impl.file.PsiPackageImplementationHelper;
import com.intellij.psi.impl.source.tree.CoreJavaASTFactory;
+import com.intellij.psi.impl.source.tree.PlainTextASTFactory;
import com.intellij.psi.presentation.java.*;
import com.intellij.psi.stubs.BinaryFileStubBuilders;
@@ -52,10 +55,14 @@
registerFileType(JavaClassFileType.INSTANCE, "class");
registerFileType(JavaFileType.INSTANCE, "java");
registerFileType(ArchiveFileType.INSTANCE, "jar;zip");
+ registerFileType(PlainTextFileType.INSTANCE, "txt;sh;bat;cmd;policy;log;cgi;MF;jad;jam;htaccess;rb");
+
+ addExplicitExtension(LanguageASTFactory.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextASTFactory());
+ addExplicitExtension(LanguageParserDefinitions.INSTANCE, PlainTextLanguage.INSTANCE, new PlainTextParserDefinition());
addExplicitExtension(FileTypeFileViewProviders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileViewProviderFactory());
addExplicitExtension(BinaryFileStubBuilders.INSTANCE, JavaClassFileType.INSTANCE, new ClassFileStubBuilder());
-
+
addExplicitExtension(LanguageASTFactory.INSTANCE, JavaLanguage.INSTANCE, new CoreJavaASTFactory());
addExplicitExtension(LanguageParserDefinitions.INSTANCE, JavaLanguage.INSTANCE, new JavaParserDefinition());
addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, JavaLanguage.INSTANCE, new PsiExpressionEvaluator());
@@ -63,7 +70,6 @@
registerExtensionPoint(Extensions.getRootArea(), ClsStubBuilderFactory.EP_NAME, ClsStubBuilderFactory.class);
registerExtensionPoint(Extensions.getRootArea(), PsiAugmentProvider.EP_NAME, PsiAugmentProvider.class);
registerExtensionPoint(Extensions.getRootArea(), JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider.class);
- addExtension(ClsStubBuilderFactory.EP_NAME, new DefaultClsStubBuilderFactory());
myApplication.registerService(PsiPackageImplementationHelper.class, new CorePsiPackageImplementationHelper());
diff --git a/java/java-psi-impl/src/com/intellij/core/JavaCoreProjectEnvironment.java b/java/java-psi-impl/src/com/intellij/core/JavaCoreProjectEnvironment.java
index 6f83e69..bc55d33 100644
--- a/java/java-psi-impl/src/com/intellij/core/JavaCoreProjectEnvironment.java
+++ b/java/java-psi-impl/src/com/intellij/core/JavaCoreProjectEnvironment.java
@@ -59,7 +59,6 @@
myProject.registerService(JavaFileManager.class, myFileManager);
JavaPsiFacadeImpl javaPsiFacade = new JavaPsiFacadeImpl(myProject, myPsiManager, myFileManager, myMessageBus);
- registerProjectComponent(JavaPsiFacade.class, javaPsiFacade);
myProject.registerService(JavaPsiFacade.class, javaPsiFacade);
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java
index 939a0a5..0377048 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java
@@ -17,6 +17,7 @@
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.WhitespacesBinders;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.impl.source.tree.ElementType;
@@ -910,7 +911,7 @@
done(annoArray, JavaElementType.ANNOTATION_ARRAY_INITIALIZER);
if (unclosed) {
- annoArray.setCustomEdgeTokenBinders(null, GREEDY_RIGHT_EDGE_PROCESSOR);
+ annoArray.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
}
return annoArray;
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
index 25da019..a8a2ff5 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java
@@ -18,6 +18,7 @@
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilderUtil;
+import com.intellij.lang.WhitespacesBinders;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.TokenType;
import com.intellij.psi.impl.source.tree.ElementType;
@@ -964,7 +965,7 @@
list.done(JavaElementType.EXPRESSION_LIST);
if (!closed) {
- list.setCustomEdgeTokenBinders(null, GREEDY_RIGHT_EDGE_PROCESSOR);
+ list.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
}
return list;
}
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java
index 2b436e7..ec6b391 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/JavaParserUtil.java
@@ -51,13 +51,6 @@
void parse(PsiBuilder builder);
}
- public static final WhitespacesAndCommentsBinder GREEDY_RIGHT_EDGE_PROCESSOR = new WhitespacesAndCommentsBinder() {
- @Override
- public int getEdgePosition(final List<IElementType> tokens, final boolean atStreamEdge, final TokenTextGetter getter) {
- return tokens.size();
- }
- };
-
private static class PrecedingWhitespacesAndCommentsBinder implements WhitespacesAndCommentsBinder {
private final boolean myAfterEmptyImport;
diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java
index a2bce4d..9e0655e 100644
--- a/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java
+++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/StatementParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.codeInsight.daemon.JavaErrorMessages;
import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.WhitespacesBinders;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.impl.source.tree.ElementType;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -109,7 +110,7 @@
codeBlock.collapse(JavaElementType.CODE_BLOCK);
if (greedyBlock) {
- codeBlock.setCustomEdgeTokenBinders(null, GREEDY_RIGHT_EDGE_PROCESSOR);
+ codeBlock.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
}
return codeBlock;
}
@@ -128,7 +129,7 @@
done(codeBlock, JavaElementType.CODE_BLOCK);
if (greedyBlock) {
- codeBlock.setCustomEdgeTokenBinders(null, GREEDY_RIGHT_EDGE_PROCESSOR);
+ codeBlock.setCustomEdgeTokenBinders(null, WhitespacesBinders.GREEDY_RIGHT_BINDER);
}
return codeBlock;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/Bottom.java b/java/java-psi-impl/src/com/intellij/psi/Bottom.java
index 942d779..022c863 100644
--- a/java/java-psi-impl/src/com/intellij/psi/Bottom.java
+++ b/java/java-psi-impl/src/com/intellij/psi/Bottom.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -28,16 +28,19 @@
super(PsiAnnotation.EMPTY_ARRAY);
}
+ @NotNull
@Override
public String getPresentableText() {
return "_";
}
+ @NotNull
@Override
public String getCanonicalText() {
return "_";
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getCanonicalText();
@@ -49,7 +52,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return text.equals("_");
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java
index 87b664d..bdcc3f1 100644
--- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.java
+++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProvider.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,23 +37,27 @@
@Override
protected PsiFile createFile(@NotNull final Project project, @NotNull final VirtualFile vFile, @NotNull final FileType fileType) {
- final FileIndexFacade fileIndex = ServiceManager.getService(project, FileIndexFacade.class);
- if (fileIndex.isInLibraryClasses(vFile) || !fileIndex.isInSource(vFile)) {
- if (!isInnerOrAnonymousClass(vFile)) {
- return new ClsFileImpl(PsiManager.getInstance(project), this);
- }
+ FileIndexFacade fileIndex = ServiceManager.getService(project, FileIndexFacade.class);
+ if (!fileIndex.isInLibraryClasses(vFile) && fileIndex.isInSource(vFile)) {
+ return null;
}
- return null;
+ // skip inners & anonymous
+ if (isInnerClass(vFile)) return null;
+
+ return new ClsFileImpl(this);
}
- public static boolean isInnerOrAnonymousClass(VirtualFile file) {
- // todo: read actual class name from file
- String name = file.getName();
- int dotIndex = name.lastIndexOf('.');
- if (dotIndex < 0) dotIndex = name.length();
- int index = name.lastIndexOf('$', dotIndex);
- return index > 0 && index != dotIndex - 1;
+ public static boolean isInnerClass(VirtualFile vFile) {
+ String name = vFile.getNameWithoutExtension();
+ int index = name.lastIndexOf('$', name.length());
+ if (index > 0 && index < name.length() - 1) {
+ String supposedParentName = name.substring(0, index) + ".class";
+ if (vFile.getParent().findChild(supposedParentName) != null) {
+ return true;
+ }
+ }
+ return false;
}
@NotNull
diff --git a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProviderFactory.java b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProviderFactory.java
index 213468b..d9b7711 100644
--- a/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProviderFactory.java
+++ b/java/java-psi-impl/src/com/intellij/psi/ClassFileViewProviderFactory.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,24 +13,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * @author max
- */
package com.intellij.psi;
import com.intellij.lang.Language;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.ContentBasedFileSubstitutor;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.compiled.ClassFileDecompilers;
import org.jetbrains.annotations.NotNull;
-public class ClassFileViewProviderFactory implements FileViewProviderFactory{
+import static com.intellij.psi.compiled.ClassFileDecompilers.Full;
+
+/**
+ * @author max
+ */
+public class ClassFileViewProviderFactory implements FileViewProviderFactory {
@Override
- public FileViewProvider createFileViewProvider(@NotNull final VirtualFile file, final Language language, @NotNull final PsiManager manager, final boolean physical) {
- // Define language for compiled file
- final ContentBasedFileSubstitutor[] processors = Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME);
- for (ContentBasedFileSubstitutor processor : processors) {
+ public FileViewProvider createFileViewProvider(@NotNull VirtualFile file, Language language, @NotNull PsiManager manager, boolean physical) {
+ ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
+ if (decompiler instanceof Full) {
+ return ((Full)decompiler).createFileViewProvider(file, manager, physical);
+ }
+
+ for (ContentBasedFileSubstitutor processor : Extensions.getExtensions(ContentBasedFileSubstitutor.EP_NAME)) {
Language lang = processor.obtainLanguageForFile(file);
if (lang != null) {
FileViewProviderFactory factory = LanguageFileViewProviders.INSTANCE.forLanguage(language);
diff --git a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
index 129be2e..2da9534 100644
--- a/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/PsiDiamondTypeImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -52,16 +52,19 @@
myTypeElement = psiTypeElement;
}
+ @NotNull
@Override
public String getPresentableText() {
return "";
}
+ @NotNull
@Override
public String getCanonicalText() {
return "";
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return "Diamond Type";
@@ -73,7 +76,7 @@
}
@Override
- public boolean equalsToText(@NonNls String text) {
+ public boolean equalsToText(@NotNull @NonNls String text) {
return text != null && text.isEmpty();
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
index 915cdbe..a7b7e29 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowAnalyzer.java
@@ -1270,10 +1270,11 @@
PsiExpression lExpr = PsiUtil.skipParenthesizedExprDown(expression.getLExpression());
if (lExpr instanceof PsiReferenceExpression) {
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lExpr;
- if (!referenceExpression.isQualified()
- || referenceExpression.getQualifierExpression() instanceof PsiThisExpression) {
-
- PsiVariable variable = getUsedVariable(referenceExpression);
+ PsiExpression qualifierExpression = referenceExpression.getQualifierExpression();
+ PsiVariable variable = getUsedVariable(referenceExpression);
+ if (qualifierExpression == null ||
+ qualifierExpression instanceof PsiThisExpression ||
+ variable instanceof PsiField && variable.hasModifierProperty(PsiModifier.STATIC)) {
if (variable != null) {
if (myAssignmentTargetsAreElements)
startElement(lExpr);
@@ -1285,7 +1286,6 @@
if (myAssignmentTargetsAreElements) finishElement(lExpr);
}
-
}
else {
lExpr.accept(this); //?
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java
index a1b28c5..2ba1906 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowFactory.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.
@@ -29,6 +29,7 @@
import com.intellij.openapi.util.NotNullLazyKey;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.PsiManagerEx;
+import com.intellij.util.containers.ConcurrentList;
import com.intellij.util.containers.ConcurrentWeakHashMap;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,11 +37,10 @@
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArrayList;
public class ControlFlowFactory {
// psiElements hold weakly, controlFlows softly
- private final ConcurrentMap<PsiElement, Reference<CopyOnWriteArrayList<ControlFlowContext>>> cachedFlows = new ConcurrentWeakHashMap<PsiElement, Reference<CopyOnWriteArrayList<ControlFlowContext>>>();
+ private final ConcurrentMap<PsiElement, Reference<ConcurrentList<ControlFlowContext>>> cachedFlows = new ConcurrentWeakHashMap<PsiElement, Reference<ConcurrentList<ControlFlowContext>>>();
private static final NotNullLazyKey<ControlFlowFactory, Project> INSTANCE_KEY = ServiceManager.createLazyKey(ControlFlowFactory.class);
@@ -127,7 +127,7 @@
boolean enableShortCircuit,
boolean evaluateConstantIfCondition) throws AnalysisCanceledException {
final long modificationCount = element.getManager().getModificationTracker().getModificationCount();
- CopyOnWriteArrayList<ControlFlowContext> cached = getOrCreateCachedFlowsForElement(element);
+ ConcurrentList<ControlFlowContext> cached = getOrCreateCachedFlowsForElement(element);
for (ControlFlowContext context : cached) {
if (context.isFor(policy, evaluateConstantIfCondition,modificationCount)) return context.controlFlow;
}
@@ -152,17 +152,17 @@
final long modificationCount = element.getManager().getModificationTracker().getModificationCount();
ControlFlowContext controlFlowContext = createContext(evaluateConstantIfCondition, policy, flow, modificationCount);
- CopyOnWriteArrayList<ControlFlowContext> cached = getOrCreateCachedFlowsForElement(element);
+ ConcurrentList<ControlFlowContext> cached = getOrCreateCachedFlowsForElement(element);
cached.addIfAbsent(controlFlowContext);
}
@NotNull
- private CopyOnWriteArrayList<ControlFlowContext> getOrCreateCachedFlowsForElement(@NotNull PsiElement element) {
- Reference<CopyOnWriteArrayList<ControlFlowContext>> cachedRef = cachedFlows.get(element);
- CopyOnWriteArrayList<ControlFlowContext> cached = cachedRef == null ? null : cachedRef.get();
+ private ConcurrentList<ControlFlowContext> getOrCreateCachedFlowsForElement(@NotNull PsiElement element) {
+ Reference<ConcurrentList<ControlFlowContext>> cachedRef = cachedFlows.get(element);
+ ConcurrentList<ControlFlowContext> cached = com.intellij.reference.SoftReference.dereference(cachedRef);
if (cached == null) {
- cached = ContainerUtil.createEmptyCOWList();
- cachedFlows.put(element, new SoftReference<CopyOnWriteArrayList<ControlFlowContext>>(cached));
+ cached = ContainerUtil.createConcurrentList();
+ cachedFlows.put(element, new SoftReference<ConcurrentList<ControlFlowContext>>(cached));
}
return cached;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java
index c6f57a5..1966ae5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/controlFlow/ControlFlowUtil.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,7 +21,7 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.IntArrayList;
import gnu.trove.THashSet;
import gnu.trove.TIntHashSet;
@@ -351,7 +351,7 @@
private static boolean isElementOfClass(PsiElement element, Class[] classesFilter) {
if (classesFilter == null) return true;
for (Class aClassesFilter : classesFilter) {
- if (ReflectionCache.isAssignable(aClassesFilter, element.getClass())) {
+ if (ReflectionUtil.isAssignable(aClassesFilter, element.getClass())) {
return true;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/filters/classes/AnnotationTypeFilter.java b/java/java-psi-impl/src/com/intellij/psi/filters/classes/AnnotationTypeFilter.java
index 156773f..aacab9d 100644
--- a/java/java-psi-impl/src/com/intellij/psi/filters/classes/AnnotationTypeFilter.java
+++ b/java/java-psi-impl/src/com/intellij/psi/filters/classes/AnnotationTypeFilter.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,7 +18,7 @@
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.filters.ElementFilter;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -32,7 +32,7 @@
@Override
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(PsiClass.class, hintClass);
+ return ReflectionUtil.isAssignable(PsiClass.class, hintClass);
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/EmptySubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/EmptySubstitutorImpl.java
index 9a327a8..dc8a2e8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/EmptySubstitutorImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/EmptySubstitutorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -38,26 +38,29 @@
}
@Override
- public PsiType substituteWithBoundsPromotion(PsiTypeParameter typeParameter) {
+ public PsiType substituteWithBoundsPromotion(@NotNull PsiTypeParameter typeParameter) {
return JavaPsiFacade.getInstance(typeParameter.getProject()).getElementFactory().createType(typeParameter);
}
+ @NotNull
@Override
- public PsiSubstitutor put(PsiTypeParameter classParameter, PsiType mapping){
+ public PsiSubstitutor put(@NotNull PsiTypeParameter classParameter, PsiType mapping){
if (mapping != null && !mapping.isValid()) {
LOG.error("Invalid type in substitutor: " + mapping);
}
return new PsiSubstitutorImpl(classParameter, mapping);
}
+ @NotNull
@Override
- public PsiSubstitutor putAll(PsiClass parentClass, PsiType[] mappings){
+ public PsiSubstitutor putAll(@NotNull PsiClass parentClass, PsiType[] mappings){
if(!parentClass.hasTypeParameters()) return this;
return new PsiSubstitutorImpl(parentClass, mappings);
}
+ @NotNull
@Override
- public PsiSubstitutor putAll(PsiSubstitutor another) {
+ public PsiSubstitutor putAll(@NotNull PsiSubstitutor another) {
return another;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java
index 3655819..3501a5c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeEx.java
@@ -19,6 +19,7 @@
*/
package com.intellij.psi.impl;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.psi.JavaPsiFacade;
@@ -41,5 +42,5 @@
}
@TestOnly
- public abstract void setAssertOnFileLoadingFilter(@NotNull VirtualFileFilter filter);
+ public abstract void setAssertOnFileLoadingFilter(@NotNull VirtualFileFilter filter, Disposable parentDisposable);
}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java
index 07f2758..13ca628 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiFacadeImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.impl;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ReadActionProcessor;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
import com.intellij.openapi.project.DumbAware;
@@ -32,7 +33,6 @@
import com.intellij.psi.impl.source.JavaDummyHolder;
import com.intellij.psi.impl.source.JavaDummyHolderFactory;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
-import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.stubs.StubTreeLoader;
import com.intellij.psi.util.PsiModificationTracker;
@@ -57,8 +57,7 @@
* @author max
*/
public class JavaPsiFacadeImpl extends JavaPsiFacadeEx {
- private PsiElementFinder[] myElementFinders; //benign data race
- private final PsiNameHelper myNameHelper;
+ private volatile PsiElementFinder[] myElementFinders;
private final PsiConstantEvaluationHelper myConstantEvaluationHelper;
private volatile SoftReference<ConcurrentMap<String, PsiPackage>> myPackageCache;
private final Project myProject;
@@ -70,7 +69,6 @@
MessageBus bus) {
myProject = project;
myFileManager = javaFileManager;
- myNameHelper = new PsiNameHelperImpl(this);
myConstantEvaluationHelper = new PsiConstantEvaluationHelperImpl();
final PsiModificationTracker modificationTracker = psiManager.getModificationTracker();
@@ -91,7 +89,6 @@
}
DummyHolderFactory.setFactory(new JavaDummyHolderFactory());
- JavaElementType.ANNOTATION.getIndex(); // Initialize stubs.
}
@Override
@@ -178,8 +175,7 @@
@Override
public PsiPackage findPackage(@NotNull String qualifiedName) {
- SoftReference<ConcurrentMap<String, PsiPackage>> ref = myPackageCache;
- ConcurrentMap<String, PsiPackage> cache = ref == null ? null : ref.get();
+ ConcurrentMap<String, PsiPackage> cache = SoftReference.dereference(myPackageCache);
if (cache == null) {
myPackageCache = new SoftReference<ConcurrentMap<String, PsiPackage>>(cache = new ConcurrentHashMap<String, PsiPackage>());
}
@@ -225,7 +221,7 @@
@Override
@NotNull
public PsiNameHelper getNameHelper() {
- return myNameHelper;
+ return PsiNameHelper.getInstance(myProject);
}
@NotNull
@@ -467,7 +463,7 @@
@TestOnly
@Override
- public void setAssertOnFileLoadingFilter(@NotNull final VirtualFileFilter filter) {
- ((PsiManagerImpl)PsiManager.getInstance(myProject)).setAssertOnFileLoadingFilter(filter);
+ public void setAssertOnFileLoadingFilter(@NotNull final VirtualFileFilter filter, Disposable parentDisposable) {
+ ((PsiManagerImpl)PsiManager.getInstance(myProject)).setAssertOnFileLoadingFilter(filter, parentDisposable);
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelper.java
index 77b0675..6a677a9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelper.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelper.java
@@ -34,6 +34,7 @@
public abstract PsiClass getOriginalClass(PsiClass psiClass);
+ @NotNull
public abstract PsiElement getClsFileNavigationElement(PsiJavaFile clsFile);
/**
@@ -50,5 +51,6 @@
@Nullable
public abstract PsiElement getDefaultMemberAnchor(@NotNull PsiClass psiClass, @NotNull PsiMember firstPsi);
- public abstract void setupCatchBlock(String exceptionName, PsiElement context, PsiCatchSection element);
+ public abstract void setupCatchBlock(@NotNull String exceptionName, @NotNull PsiType exceptionType,
+ @Nullable PsiElement context, @NotNull PsiCatchSection element);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
index e87fbe3..8aedad8 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiElementFactoryImpl.java
@@ -748,7 +748,7 @@
final Project project = myManager.getProject();
final JavaPsiImplementationHelper helper = JavaPsiImplementationHelper.getInstance(project);
- helper.setupCatchBlock(exceptionName, context, (PsiCatchSection)element);
+ helper.setupCatchBlock(exceptionName, exceptionType, context, (PsiCatchSection)element);
final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
final PsiCatchSection catchSection = (PsiCatchSection)styleManager.reformat(element);
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 48c9d63..0de45be 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
@@ -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.
@@ -275,7 +275,7 @@
@NotNull
public static PsiType[] typesByTypeElements(@NotNull PsiTypeElement[] typeElements) {
- PsiType[] types = new PsiType[typeElements.length];
+ PsiType[] types = PsiType.createArray(typeElements.length);
for (int i = 0; i < types.length; i++) {
types[i] = typeElements[i].getType();
}
@@ -370,7 +370,7 @@
// todo[r.sh] cache?
@Nullable
- public static Set<TargetType> getAnnotationTargets(PsiClass annotationType) {
+ public static Set<TargetType> getAnnotationTargets(@NotNull PsiClass annotationType) {
if (!annotationType.isAnnotationType()) return null;
PsiModifierList modifierList = annotationType.getModifierList();
if (modifierList == null) return null;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java
index 717d123..05819c4 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiJavaParserFacadeImpl.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.
@@ -48,7 +48,6 @@
*/
public class PsiJavaParserFacadeImpl implements PsiJavaParserFacade {
protected final PsiManager myManager;
- private PsiJavaFile myDummyJavaFile;
private static final String DUMMY_FILE_NAME = "_Dummy_." + JavaFileType.INSTANCE.getDefaultExtension();
@@ -384,14 +383,6 @@
return annotations.length == 0 ? primitiveType : new PsiPrimitiveType(text, annotations);
}
- public PsiJavaFile getDummyJavaFile() {
- if (myDummyJavaFile == null) {
- myDummyJavaFile = createDummyJavaFile("");
- }
-
- return myDummyJavaFile;
- }
-
public static PsiPrimitiveType getPrimitiveType(final String text) {
return PRIMITIVE_TYPES.get(text);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java
index 5d931e6..702ed8e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiNameHelperImpl.java
@@ -16,10 +16,10 @@
package com.intellij.psi.impl;
import com.intellij.lang.java.lexer.JavaLexer;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiNameHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,8 +27,8 @@
public class PsiNameHelperImpl extends PsiNameHelper {
private final LanguageLevelProjectExtension myLanguageLevelExtension;
- public PsiNameHelperImpl(JavaPsiFacade manager) {
- myLanguageLevelExtension = LanguageLevelProjectExtension.getInstance(manager.getProject());
+ public PsiNameHelperImpl(Project project) {
+ myLanguageLevelExtension = LanguageLevelProjectExtension.getInstance(project);
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
index 94f6627..723f509 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSubstitutorImpl.java
@@ -86,7 +86,7 @@
return mySubstitutionMap.containsKey(typeParameter);
}
- private PsiType getFromMap(PsiTypeParameter typeParameter) {
+ private PsiType getFromMap(@NotNull PsiTypeParameter typeParameter) {
if (typeParameter instanceof LightTypeParameter) {
typeParameter = ((LightTypeParameter)typeParameter).getDelegate();
}
@@ -105,7 +105,7 @@
}
@Override
- public PsiType substituteWithBoundsPromotion(PsiTypeParameter typeParameter) {
+ public PsiType substituteWithBoundsPromotion(@NotNull PsiTypeParameter typeParameter) {
return addBounds(substitute(typeParameter), typeParameter);
}
@@ -176,12 +176,18 @@
}
private static PsiType handleBoundComposition(PsiWildcardType wildcardType, PsiWildcardType bound) {
+ final PsiType newBoundBound = bound.getBound();
if (bound.isExtends() == wildcardType.isExtends()) {
- final PsiType newBoundBound = bound.getBound();
if (newBoundBound != null) {
return rebound(wildcardType, newBoundBound);
}
}
+
+ if (newBoundBound != null) {
+ return wildcardType.isExtends() ? PsiWildcardType.createExtends(wildcardType.getManager(), newBoundBound)
+ : PsiWildcardType.createSuper(wildcardType.getManager(), newBoundBound);
+ }
+
return PsiWildcardType.createUnbounded(wildcardType.getManager());
}
@@ -306,7 +312,7 @@
return result;
}
- private PsiType substituteTypeParameter(final PsiTypeParameter typeParameter) {
+ private PsiType substituteTypeParameter(@NotNull PsiTypeParameter typeParameter) {
PsiType t = getFromMap(typeParameter);
if (myKind == SubstituteKind.SIMPLE) {
return t;
@@ -350,7 +356,7 @@
}
}
- private PsiType addBounds(PsiType substituted, final PsiTypeParameter typeParameter) {
+ private PsiType addBounds(PsiType substituted, @NotNull PsiTypeParameter typeParameter) {
PsiType oldSubstituted = substituted;
PsiElement captureContext = null;
if (substituted instanceof PsiCapturedWildcardType) {
@@ -432,6 +438,7 @@
return new PsiSubstitutorImpl(mySubstitutionMap);
}
+ @NotNull
@Override
public PsiSubstitutor put(@NotNull PsiTypeParameter typeParameter, PsiType mapping) {
PsiSubstitutorImpl ret = clone();
@@ -461,6 +468,7 @@
}
}
+ @NotNull
@Override
public PsiSubstitutor putAll(@NotNull PsiClass parentClass, PsiType[] mappings) {
PsiSubstitutorImpl substitutor = clone();
@@ -468,8 +476,9 @@
return substitutor;
}
+ @NotNull
@Override
- public PsiSubstitutor putAll(PsiSubstitutor another) {
+ public PsiSubstitutor putAll(@NotNull PsiSubstitutor another) {
if (another instanceof EmptySubstitutorImpl) return this;
final PsiSubstitutorImpl anotherImpl = (PsiSubstitutorImpl)another;
PsiSubstitutorImpl substitutor = clone();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
index 80fca22..a11a285 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/PsiSuperMethodImplUtil.java
@@ -273,7 +273,11 @@
if (superClass != null) {
if (superClass.isInterface() ||
CommonClassNames.JAVA_LANG_OBJECT.equals(superClass.getQualifiedName())) {
- if (superMethod.hasModifierProperty(PsiModifier.DEFAULT) || hierarchicalMethodSignature.getMethod().hasModifierProperty(PsiModifier.DEFAULT)) {
+ if (superMethod.hasModifierProperty(PsiModifier.STATIC)) {
+ return false;
+ }
+ if (superMethod.hasModifierProperty(PsiModifier.DEFAULT) ||
+ hierarchicalMethodSignature.getMethod().hasModifierProperty(PsiModifier.DEFAULT)) {
return !InheritanceUtil.isInheritorOrSelf(superClass, containingClass, true);
}
return true;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java
new file mode 100644
index 0000000..9626aa4
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.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 com.intellij.psi.impl.compiled;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
+import com.intellij.openapi.project.DefaultProjectFactory;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.compiled.ClassFileDecompilers;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author max
+ */
+public class ClassFileDecompiler implements BinaryFileDecompiler {
+ /** @deprecated temporary solution, to remove in IDEA 14 */
+ public interface PlatformDecompiler {
+ @Nullable
+ CharSequence decompile(@NotNull VirtualFile file);
+ }
+
+ @Override
+ @NotNull
+ public CharSequence decompile(@NotNull VirtualFile file) {
+ ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
+ if (decompiler instanceof ClassFileDecompilers.Full) {
+ PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject());
+ return ((ClassFileDecompilers.Full)decompiler).createFileViewProvider(file, manager, true).getContents();
+ }
+
+ @SuppressWarnings("deprecation") PlatformDecompiler platformDecompiler = ServiceManager.getService(PlatformDecompiler.class);
+ if (platformDecompiler != null) {
+ CharSequence result = platformDecompiler.decompile(file);
+ if (result != null) return result;
+ }
+
+ return decompileText(file);
+ }
+
+ @NotNull
+ public static CharSequence decompileText(@NotNull VirtualFile file) {
+ ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
+ if (decompiler instanceof ClassFileDecompilers.Light) {
+ return ((ClassFileDecompilers.Light)decompiler).getText(file);
+ }
+
+ return ClsFileImpl.decompile(file);
+ }
+}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java
index 96c48ec..f2a4b48 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileStubBuilder.java
@@ -19,14 +19,20 @@
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.impl.source.JavaFileElementType;
+import com.intellij.psi.compiled.ClassFileDecompilers;
import com.intellij.psi.stubs.BinaryFileStubBuilder;
import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.stubs.StubElement;
import com.intellij.util.cls.ClsFormatException;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileContent;
+import org.jetbrains.annotations.NotNull;
-import java.util.*;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static com.intellij.psi.compiled.ClassFileDecompilers.Full;
/**
* @author max
@@ -34,56 +40,82 @@
public class ClassFileStubBuilder implements BinaryFileStubBuilder {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClassFileStubBuilder");
- public static final int STUB_VERSION = 8 + JavaFileElementType.STUB_VERSION;
+ public static final int STUB_VERSION = 9;
@Override
- public boolean acceptsFile(final VirtualFile file) {
- final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME);
- for (ClsStubBuilderFactory factory : factories) {
- if (!factory.isInnerClass(file)) {
- return true;
- }
- }
- return false;
+ public boolean acceptsFile(@NotNull VirtualFile file) {
+ return true;
}
+ @SuppressWarnings("deprecation")
@Override
- public StubElement buildStubTree(FileContent fileContent) {
+ public StubElement buildStubTree(@NotNull FileContent fileContent) {
+ VirtualFile file = fileContent.getFile();
+ byte[] content = fileContent.getContent();
+
try {
- VirtualFile file = fileContent.getFile();
+ ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
+ if (decompiler instanceof Full) {
+ return ((Full)decompiler).getStubBuilder().buildFileStub(fileContent);
+ }
+ }
+ catch (ClsFormatException e) {
+ LOG.debug(e);
+ }
+
+ try {
Project project = fileContent.getProject();
- byte[] content = fileContent.getContent();
- final ClsStubBuilderFactory[] factories = Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME);
- for (ClsStubBuilderFactory factory : factories) {
+ for (ClsStubBuilderFactory factory : Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME)) {
if (!factory.isInnerClass(file) && factory.canBeProcessed(file, content)) {
PsiFileStub stub = factory.buildFileStub(file, content, project);
if (stub != null) return stub;
}
}
- if (!fileContent.getFileName().contains("$")) {
- LOG.info("No stub built for file " + fileContent);
- }
- return null;
}
catch (ClsFormatException e) {
- return null;
+ LOG.debug(e);
}
+
+ try {
+ PsiFileStub<?> stub = ClsFileImpl.buildFileStub(file, content);
+ if (stub == null && !fileContent.getFileName().contains("$")) {
+ LOG.info("No stub built for file " + fileContent);
+ }
+ return stub;
+ }
+ catch (ClsFormatException e) {
+ LOG.debug(e);
+ }
+
+ return null;
}
+ private static final Comparator<Object> CLASS_NAME_COMPARATOR = new Comparator<Object>() {
+ @Override
+ public int compare(Object o1, Object o2) {
+ return o1.getClass().getName().compareTo(o2.getClass().getName());
+ }
+ };
+
+ @SuppressWarnings("deprecation")
@Override
public int getStubVersion() {
int version = STUB_VERSION;
- List<ClsStubBuilderFactory> factories = new ArrayList<ClsStubBuilderFactory>(Arrays.asList(
- Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME)));
- Collections.sort(factories, new Comparator<ClsStubBuilderFactory>() { // stable order in copy
- @Override
- public int compare(ClsStubBuilderFactory o1, ClsStubBuilderFactory o2) {
- return o1.getClass().getName().compareTo(o2.getClass().getName());
+
+ List<ClassFileDecompilers.Decompiler> decompilers = ContainerUtil.newArrayList(ClassFileDecompilers.EP_NAME.getExtensions());
+ Collections.sort(decompilers, CLASS_NAME_COMPARATOR);
+ for (ClassFileDecompilers.Decompiler decompiler : decompilers) {
+ if (decompiler instanceof Full) {
+ version = version * 31 + ((Full)decompiler).getStubBuilder().getStubVersion() + decompiler.getClass().getName().hashCode();
}
- });
- for(ClsStubBuilderFactory factory:factories) {
+ }
+
+ List<ClsStubBuilderFactory> factories = ContainerUtil.newArrayList(Extensions.getExtensions(ClsStubBuilderFactory.EP_NAME));
+ Collections.sort(factories, CLASS_NAME_COMPARATOR);
+ for (ClsStubBuilderFactory factory : factories) {
version = version * 31 + factory.getStubVersion() + factory.getClass().getName().hashCode();
}
+
return version;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsCustomNavigationPolicy.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsCustomNavigationPolicy.java
index 6b61c54..68f4410 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsCustomNavigationPolicy.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsCustomNavigationPolicy.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,10 +20,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-/**
- * @author Evgeny Gerashchenko
- * @since 3/2/12
- */
+/** @deprecated API no longer supported, use {@link com.intellij.psi.compiled.ClassFileDecompilers} instead (to remove in IDEA 14) */
+@SuppressWarnings({"UnusedDeclaration", "deprecation"})
public interface ClsCustomNavigationPolicy {
ExtensionPointName<ClsCustomNavigationPolicy> EP_NAME = ExtensionPointName.create("com.intellij.psi.clsCustomNavigationPolicy");
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsElementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsElementImpl.java
index 3fbfc4b..8808cc7 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsElementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsElementImpl.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,7 +95,7 @@
return PsiElement.EMPTY_ARRAY;
}
- List<PsiElement> list = ContainerUtil.newArrayListWithExpectedSize(children.length);
+ List<PsiElement> list = ContainerUtil.newArrayListWithCapacity(children.length);
for (PsiElement child : children) {
if (child != null) {
list.add(child);
@@ -228,7 +228,7 @@
StringBuilder buffer = new StringBuilder();
appendMirrorText(0, buffer);
- LOG.error("Mirror wasn't set for " + this + ", expected text:\n" + buffer);
+ LOG.error("Mirror wasn't set for " + this + " in " + getContainingFile() + ", expected text '" + buffer + "'");
return buffer.toString();
}
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 b35a97e..36a725a 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
@@ -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.
@@ -27,14 +27,18 @@
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.NonCancelableSection;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.project.DefaultProjectFactory;
+import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.ui.Queryable;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.JavaPsiImplementationHelper;
import com.intellij.psi.impl.PsiFileEx;
-import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.impl.java.stubs.PsiClassStub;
+import com.intellij.psi.impl.java.stubs.PsiJavaFileStub;
import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.impl.source.PsiFileWithStubSupport;
@@ -44,13 +48,19 @@
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.psi.stubs.*;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiUtil;
import com.intellij.reference.SoftReference;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.cls.ClsFormatException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -66,30 +76,34 @@
private final Object myMirrorLock = new Object();
private final Object myStubLock = new Object();
- private final PsiManager myManager;
- private final boolean myIsForDecompiling;
private final FileViewProvider myViewProvider;
+ private final boolean myIsForDecompiling;
private volatile SoftReference<StubTree> myStub;
private volatile TreeElement myMirrorFileElement;
private volatile ClsPackageStatementImpl myPackageStatement = null;
private boolean myIsPhysical = true;
- private ClsFileImpl(@NotNull PsiManager manager, @NotNull FileViewProvider viewProvider, boolean forDecompiling) {
- //noinspection ConstantConditions
- super(null);
- myManager = manager;
- myIsForDecompiling = forDecompiling;
- myViewProvider = viewProvider;
- JavaElementType.CLASS.getIndex(); // initialize Java stubs
+ public ClsFileImpl(@NotNull FileViewProvider viewProvider) {
+ this(viewProvider, false);
}
- public ClsFileImpl(PsiManager manager, FileViewProvider viewProvider) {
- this(manager, viewProvider, false);
+ /** @deprecated use {@link #ClsFileImpl(FileViewProvider)} (to remove in IDEA 14) */
+ @SuppressWarnings("unused")
+ public ClsFileImpl(@NotNull PsiManager manager, @NotNull FileViewProvider viewProvider) {
+ this(viewProvider, false);
+ }
+
+ private ClsFileImpl(@NotNull FileViewProvider viewProvider, boolean forDecompiling) {
+ //noinspection ConstantConditions
+ super(null);
+ myViewProvider = viewProvider;
+ myIsForDecompiling = forDecompiling;
+ JavaElementType.CLASS.getIndex(); // initialize Java stubs
}
@Override
public PsiManager getManager() {
- return myManager;
+ return myViewProvider.getManager();
}
@Override
@@ -123,9 +137,11 @@
@Override
public boolean isValid() {
- if (myIsForDecompiling) return true;
- VirtualFile vFile = getVirtualFile();
- return vFile.isValid();
+ return myIsForDecompiling || getVirtualFile().isValid();
+ }
+
+ protected boolean isForDecompiling() {
+ return myIsForDecompiling;
}
@Override
@@ -260,6 +276,7 @@
setMirrors(getClasses(), mirrorFile.getClasses());
}
+ @SuppressWarnings("deprecation")
@Override
@NotNull
public PsiElement getNavigationElement() {
@@ -272,7 +289,15 @@
}
}
- return JavaPsiImplementationHelper.getInstance(getProject()).getClsFileNavigationElement(this);
+ return CachedValuesManager.getCachedValue(this, new CachedValueProvider<PsiElement>() {
+ @Nullable
+ @Override
+ public Result<PsiElement> compute() {
+ PsiElement target = JavaPsiImplementationHelper.getInstance(getProject()).getClsFileNavigationElement(ClsFileImpl.this);
+ ModificationTracker tracker = FileIndexFacade.getInstance(getProject()).getRootModificationTracker();
+ return Result.create(target, ClsFileImpl.this, target.getContainingFile(), tracker);
+ }
+ });
}
@Override
@@ -283,7 +308,7 @@
mirrorTreeElement = myMirrorFileElement;
if (mirrorTreeElement == null) {
VirtualFile file = getVirtualFile();
- String mirrorText = decompile(getManager(), file);
+ CharSequence mirrorText = ClassFileDecompiler.decompileText(file);
String ext = JavaFileType.INSTANCE.getDefaultExtension();
PsiClass[] classes = getClasses();
@@ -314,13 +339,7 @@
@Override
public PsiFile getDecompiledPsiFile() {
- for (ClsFileDecompiledPsiFileProvider provider : Extensions.getExtensions(ClsFileDecompiledPsiFileProvider.EP_NAME)) {
- PsiFile decompiledPsiFile = provider.getDecompiledPsiFile(this);
- if (decompiledPsiFile != null) {
- return decompiledPsiFile;
- }
- }
- return (PsiFile) getMirror();
+ return (PsiFile)getMirror();
}
@Override
@@ -370,26 +389,6 @@
public void subtreeChanged() {
}
- public static String decompile(PsiManager manager, VirtualFile file) {
- ClsFileImpl psiFile = null;
-
- final FileViewProvider provider = ((PsiManagerEx)manager).getFileManager().findViewProvider(file);
- if (provider != null) {
- final PsiFile psi = provider.getPsi(provider.getBaseLanguage());
- if (psi instanceof ClsFileImpl) {
- psiFile = (ClsFileImpl)psi;
- }
- }
-
- if (psiFile == null) {
- psiFile = new ClsFileImpl(manager, new ClassFileViewProvider(manager, file), true);
- }
-
- final StringBuilder buffer = new StringBuilder();
- psiFile.appendMirrorText(0, buffer);
- return buffer.toString();
- }
-
@Override
public PsiElement getContext() {
return FileContextUtil.getFileContext(this);
@@ -397,7 +396,7 @@
@Override
@NotNull
- public PsiClassHolderFileStub getStub() {
+ public PsiClassHolderFileStub<?> getStub() {
return (PsiClassHolderFileStub)getStubTree().getRoot();
}
@@ -422,8 +421,8 @@
stubTree = newStubTree;
- //noinspection unchecked
- ((PsiFileStubImpl)stubTree.getRoot()).setPsi(this);
+ @SuppressWarnings("unchecked") PsiFileStubImpl<PsiFile> fileStub = (PsiFileStubImpl)stubTree.getRoot();
+ fileStub.setPsi(this);
myStub = new SoftReference<StubTree>(stubTree);
}
@@ -485,4 +484,75 @@
public void setPhysical(boolean isPhysical) {
myIsPhysical = isPhysical;
}
+
+ // default decompiler implementation
+
+ /** @deprecated use {@link #decompile(VirtualFile)} (to remove in IDEA 14) */
+ @SuppressWarnings("unused")
+ public static String decompile(@NotNull PsiManager manager, @NotNull VirtualFile file) {
+ return decompile(file).toString();
+ }
+
+ @NotNull
+ public static CharSequence decompile(@NotNull VirtualFile file) {
+ PsiManager manager = PsiManager.getInstance(DefaultProjectFactory.getInstance().getDefaultProject());
+ StringBuilder buffer = new StringBuilder();
+ new ClsFileImpl(new ClassFileViewProvider(manager, file), true).appendMirrorText(0, buffer);
+ return buffer;
+ }
+
+ @Nullable
+ public static PsiJavaFileStub buildFileStub(@NotNull VirtualFile file, @NotNull byte[] bytes) throws ClsFormatException {
+ if (ClassFileViewProvider.isInnerClass(file)) {
+ return null;
+ }
+
+ try {
+ PsiJavaFileStubImpl stub = new PsiJavaFileStubImpl("do.not.know.yet", true);
+ StubBuildingVisitor<VirtualFile> visitor = new StubBuildingVisitor<VirtualFile>(file, STRATEGY, stub, 0, file.getNameWithoutExtension());
+ try {
+ new ClassReader(bytes).accept(visitor, ClassReader.SKIP_FRAMES);
+ }
+ catch (OutOfOrderInnerClassException e) {
+ return null;
+ }
+
+ PsiClassStub<?> result = visitor.getResult();
+ if (result == null) return null;
+
+ stub.setPackageName(getPackageName(result));
+ return stub;
+ }
+ catch (Exception e) {
+ throw new ClsFormatException(file.getPath() + ": " + e.getMessage(), e);
+ }
+ }
+
+ private static final InnerClassSourceStrategy<VirtualFile> STRATEGY = new InnerClassSourceStrategy<VirtualFile>() {
+ @Nullable
+ @Override
+ public VirtualFile findInnerClass(String innerName, VirtualFile outerClass) {
+ String baseName = outerClass.getNameWithoutExtension();
+ VirtualFile dir = outerClass.getParent();
+ assert dir != null : outerClass;
+ return dir.findChild(baseName + "$" + innerName + ".class");
+ }
+
+ @Nullable
+ @Override
+ public ClassReader readerForInnerClass(VirtualFile innerClass) {
+ try {
+ return new ClassReader(innerClass.contentsToByteArray());
+ }
+ catch (IOException e) {
+ return null;
+ }
+ }
+ };
+
+ private static String getPackageName(@NotNull PsiClassStub<?> result) {
+ String fqn = result.getQualifiedName();
+ String shortName = result.getName();
+ return fqn == null || Comparing.equal(shortName, fqn) ? "" : fqn.substring(0, fqn.lastIndexOf('.'));
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsMethodImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsMethodImpl.java
index d1e9ff6..64ff878 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsMethodImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsMethodImpl.java
@@ -18,6 +18,7 @@
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.text.StringUtil;
@@ -34,9 +35,7 @@
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.scope.util.PsiScopesUtil;
import com.intellij.psi.search.SearchScope;
-import com.intellij.psi.util.MethodSignature;
-import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
-import com.intellij.psi.util.MethodSignatureUtil;
+import com.intellij.psi.util.*;
import com.intellij.ui.RowIcon;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
@@ -280,6 +279,20 @@
@Nullable
public PsiMethod getSourceMirrorMethod() {
+ return CachedValuesManager.getCachedValue(this, new CachedValueProvider<PsiMethod>() {
+ @Nullable
+ @Override
+ public Result<PsiMethod> compute() {
+ return Result.create(calcSourceMirrorMethod(),
+ getContainingFile(),
+ getContainingFile().getNavigationElement(),
+ FileIndexFacade.getInstance(getProject()).getRootModificationTracker());
+ }
+ });
+ }
+
+ @Nullable
+ private PsiMethod calcSourceMirrorMethod() {
PsiClass sourceClassMirror = ((ClsClassImpl)getParent()).getSourceMirrorClass();
if (sourceClassMirror == null) return null;
for (PsiMethod sourceMethod : sourceClassMirror.findMethodsByName(getName(), false)) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java
index d4b1033..879f2a9 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsParsingUtil.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,7 +23,6 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
-import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.DummyHolderFactory;
import com.intellij.psi.impl.source.JavaDummyElement;
@@ -48,38 +47,34 @@
private ClsParsingUtil() { }
- public static PsiExpression createExpressionFromText(final String exprText, final PsiManager manager, final ClsElementImpl parent) {
- final PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(manager.getProject()).getParserFacade();
- final PsiJavaFile dummyJavaFile = ((PsiJavaParserFacadeImpl)parserFacade).getDummyJavaFile(); // to resolve classes from java.lang
- final PsiExpression expr;
+ public static PsiExpression createExpressionFromText(@NotNull String exprText,
+ @NotNull PsiManager manager,
+ @NotNull ClsElementImpl parent) {
+ PsiJavaParserFacade parserFacade = JavaPsiFacade.getInstance(manager.getProject()).getParserFacade();
try {
- expr = parserFacade.createExpressionFromText(exprText, dummyJavaFile);
+ PsiExpression expr = parserFacade.createExpressionFromText(exprText, null);
+ return psiToClsExpression(expr, parent);
}
catch (IncorrectOperationException e) {
LOG.error(e);
return null;
}
-
- return psiToClsExpression(expr, parent);
}
- @NotNull
- public static PsiAnnotationMemberValue createMemberValueFromText(final String text, final PsiManager manager, final ClsElementImpl parent) {
- final PsiElementFactory factory = JavaPsiFacade.getInstance(manager.getProject()).getElementFactory();
- final PsiJavaFile context = ((PsiJavaParserFacadeImpl)factory).getDummyJavaFile(); // to resolve classes from java.lang
- final LanguageLevel level = PsiUtil.getLanguageLevel(parent);
- final DummyHolder holder = DummyHolderFactory.createHolder(manager, new JavaDummyElement(text, ANNOTATION_VALUE, level), context);
- final PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
+ public static PsiAnnotationMemberValue createMemberValueFromText(@NotNull String text,
+ @NotNull PsiManager manager,
+ @NotNull ClsElementImpl parent) {
+ LanguageLevel level = PsiUtil.getLanguageLevel(parent);
+ DummyHolder holder = DummyHolderFactory.createHolder(manager, new JavaDummyElement(text, ANNOTATION_VALUE, level), null);
+ PsiElement element = SourceTreeToPsiMap.treeElementToPsi(holder.getTreeElement().getFirstChildNode());
if (!(element instanceof PsiAnnotationMemberValue)) {
LOG.error("Could not parse initializer:'" + text + "'");
return null;
}
-
return getMemberValue(element, parent);
}
- @NotNull
- public static PsiAnnotationMemberValue getMemberValue(final PsiElement element, final ClsElementImpl parent) {
+ public static PsiAnnotationMemberValue getMemberValue(@NotNull PsiElement element, @NotNull ClsElementImpl parent) {
if (element instanceof PsiExpression) {
return psiToClsExpression((PsiExpression)element, parent);
}
@@ -121,15 +116,19 @@
}
}
- @NotNull
- private static PsiExpression psiToClsExpression(final PsiExpression expr, @Nullable final ClsElementImpl parent) {
+ private static PsiExpression psiToClsExpression(PsiExpression expr, @Nullable ClsElementImpl parent) {
if (expr instanceof PsiLiteralExpression) {
- return new ClsLiteralExpressionImpl(parent, expr.getText(), expr.getType(), ((PsiLiteralExpression)expr).getValue());
+ if (parent != null && ((ClsFileImpl)parent.getContainingFile()).isForDecompiling()) {
+ return new ClsLiteralExpressionImpl(parent, expr.getText(), PsiType.NULL, null);
+ }
+ else {
+ return new ClsLiteralExpressionImpl(parent, expr.getText(), expr.getType(), ((PsiLiteralExpression)expr).getValue());
+ }
}
if (expr instanceof PsiPrefixExpression) {
- final PsiPrefixExpression prefixExpr = (PsiPrefixExpression)expr;
- final ClsJavaTokenImpl operation = new ClsJavaTokenImpl(null, prefixExpr.getOperationTokenType(), prefixExpr.getOperationSign().getText());
- final ClsLiteralExpressionImpl literal = (ClsLiteralExpressionImpl) psiToClsExpression(prefixExpr.getOperand(), null);
+ PsiPrefixExpression prefixExpr = (PsiPrefixExpression)expr;
+ ClsJavaTokenImpl operation = new ClsJavaTokenImpl(null, prefixExpr.getOperationTokenType(), prefixExpr.getOperationSign().getText());
+ ClsLiteralExpressionImpl literal = (ClsLiteralExpressionImpl)psiToClsExpression(prefixExpr.getOperand(), null);
return new ClsPrefixExpressionImpl(parent, operation, literal);
}
if (expr instanceof PsiClassObjectAccessExpression) {
@@ -143,10 +142,10 @@
return new ClsReferenceExpressionImpl(parent, (PsiReferenceExpression)expr);
}
if (expr instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpr = (PsiBinaryExpression)expr;
- final PsiExpression lOperand = psiToClsExpression(binaryExpr.getLOperand(), null);
- final ClsJavaTokenImpl operation = new ClsJavaTokenImpl(null, binaryExpr.getOperationTokenType(), binaryExpr.getOperationSign().getText());
- final PsiExpression rOperand = psiToClsExpression(binaryExpr.getROperand(), null);
+ PsiBinaryExpression binaryExpr = (PsiBinaryExpression)expr;
+ PsiExpression lOperand = psiToClsExpression(binaryExpr.getLOperand(), null);
+ ClsJavaTokenImpl operation = new ClsJavaTokenImpl(null, binaryExpr.getOperationTokenType(), binaryExpr.getOperationSign().getText());
+ PsiExpression rOperand = psiToClsExpression(binaryExpr.getROperand(), null);
if (lOperand instanceof ClsLiteralExpressionImpl) {
return new ClsBinaryExpressionImpl(parent, (ClsLiteralExpressionImpl)lOperand, operation, (ClsLiteralExpressionImpl)rOperand);
}
@@ -155,6 +154,9 @@
}
}
else {
+ if (parent != null && ((ClsFileImpl)parent.getContainingFile()).isForDecompiling()) {
+ return new ClsLiteralExpressionImpl(parent, expr.getText(), PsiType.NULL, null);
+ }
final PsiConstantEvaluationHelper evaluator = JavaPsiFacade.getInstance(expr.getProject()).getConstantEvaluationHelper();
final Object value = evaluator.computeConstantExpression(expr);
if (value != null) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsReferenceParameterListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsReferenceParameterListImpl.java
index 1606e76..aa2fae3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsReferenceParameterListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsReferenceParameterListImpl.java
@@ -72,7 +72,7 @@
public PsiType[] getTypeArguments() {
PsiType[] cachedTypes = myTypeParametersCachedTypes;
if (cachedTypes == null) {
- cachedTypes = myTypeParameters.length == 0 ? PsiType.EMPTY_ARRAY : new PsiType[myTypeParameters.length];
+ cachedTypes = PsiType.createArray(myTypeParameters.length);
for (int i = 0; i < cachedTypes.length; i++) {
cachedTypes[cachedTypes.length - i - 1] = myTypeParameters[i].getType();
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java
index b670938..5cfde3e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsStubBuilderFactory.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,32 +21,23 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.util.cls.ClsFormatException;
-import org.jetbrains.annotations.Nullable;
-/**
- * @author ilyas
- */
+/** @deprecated API no longer supported, use {@link com.intellij.psi.compiled.ClassFileDecompilers} instead (to remove in IDEA 14) */
+@SuppressWarnings({"deprecation", "unused"})
public abstract class ClsStubBuilderFactory<T extends PsiFile> {
-
public static final ExtensionPointName<ClsStubBuilderFactory> EP_NAME = ExtensionPointName.create("com.intellij.clsStubBuilderFactory");
- @Nullable
- public abstract PsiFileStub<T> buildFileStub(final VirtualFile file, byte[] bytes) throws ClsFormatException;
+ public abstract PsiFileStub<T> buildFileStub(final VirtualFile file, byte[] bytes) throws ClsFormatException;
- @Nullable
- public PsiFileStub<T> buildFileStub(final VirtualFile file, byte[] bytes, Project project) throws ClsFormatException {
+ public PsiFileStub<T> buildFileStub(final VirtualFile file, byte[] bytes, Project project) throws ClsFormatException {
return buildFileStub(file, bytes);
}
public abstract boolean canBeProcessed(final VirtualFile file, byte[] bytes);
- /**
- * Should be fast, because of processing file only according to the name.
- * It can be inconsistent with 'canBeProcessed' method.
- * @param file classFile
- * @return false in case if it's not inner class
- */
public abstract boolean isInnerClass(final VirtualFile file);
- public int getStubVersion() { return 1; }
+ public int getStubVersion() {
+ return 1;
+ }
}
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 7cab653..599f756 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
@@ -21,6 +21,7 @@
import com.intellij.openapi.util.VolatileNullableLazyValue;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
+import com.intellij.psi.impl.PsiJavaParserFacadeImpl;
import com.intellij.psi.impl.cache.TypeInfo;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -136,7 +137,7 @@
}
private ClsElementImpl calculateChild() {
- if (JavaPsiFacade.getInstance(getProject()).getElementFactory().createPrimitiveType(myTypeText) != null) {
+ if (PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText) != null) {
return null;
}
else if (isArray()) {
@@ -153,7 +154,7 @@
}
private PsiType calculateType() {
- PsiType result = JavaPsiFacade.getInstance(getProject()).getElementFactory().createPrimitiveType(myTypeText);
+ PsiType result = PsiJavaParserFacadeImpl.getPrimitiveType(myTypeText);
if (result != null) return result;
ClsElementImpl childElement = myChild.getValue();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeParametersListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeParametersListImpl.java
index ba4802b..b5d96af 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeParametersListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsTypeParametersListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -41,7 +41,7 @@
if (i > 0) buffer.append(", ");
appendText(params[i], indentLevel, buffer);
}
- buffer.append("> ");
+ buffer.append(">");
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java
deleted file mode 100644
index db75c58..0000000
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/DefaultClsStubBuilderFactory.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.psi.impl.compiled;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.ClassFileViewProvider;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.impl.java.stubs.PsiClassStub;
-import com.intellij.psi.impl.java.stubs.impl.PsiJavaFileStubImpl;
-import com.intellij.psi.stubs.PsiFileStub;
-import com.intellij.util.cls.ClsFormatException;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.asm4.ClassReader;
-
-import java.io.IOException;
-
-/**
- * @author max
- */
-@SuppressWarnings({"HardCodedStringLiteral"})
-public class DefaultClsStubBuilderFactory extends ClsStubBuilderFactory {
- private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.DefaultClsStubBuilderFactory");
-
- @Override
- public PsiFileStub buildFileStub(VirtualFile vFile, byte[] bytes) throws ClsFormatException {
- final PsiJavaFileStubImpl file = new PsiJavaFileStubImpl("do.not.know.yet", true);
- try {
- final ClassReader reader = new ClassReader(bytes);
- final StubBuildingVisitor<VirtualFile> classVisitor =
- new StubBuildingVisitor<VirtualFile>(vFile, VirtualFileInnerClassStrategy.INSTANCE, file, 0, null);
- try {
- reader.accept(classVisitor, ClassReader.SKIP_FRAMES);
- }
- catch (OutOfOrderInnerClassException e) {
- return null;
- }
-
- @SuppressWarnings("unchecked") final PsiClassStub<PsiClass> result = (PsiClassStub<PsiClass>)classVisitor.getResult();
- if (result == null) return null;
-
- file.setPackageName(getPackageName(result));
- return file;
- }
- catch (Exception e) {
- LOG.debug(vFile.getPath(), e);
- throw new ClsFormatException();
- }
- }
-
- @Override
- public boolean canBeProcessed(VirtualFile file, byte[] bytes) {
- return true;
- }
-
- @Override
- public boolean isInnerClass(VirtualFile file) {
- return ClassFileViewProvider.isInnerOrAnonymousClass(file);
- }
-
- private static class VirtualFileInnerClassStrategy implements InnerClassSourceStrategy<VirtualFile> {
- public static VirtualFileInnerClassStrategy INSTANCE = new VirtualFileInnerClassStrategy();
-
- @Nullable
- @Override
- public VirtualFile findInnerClass(String innerName, VirtualFile outerClass) {
- final String baseName = outerClass.getNameWithoutExtension();
- final VirtualFile dir = outerClass.getParent();
- assert dir != null;
-
- return dir.findChild(baseName + "$" + innerName + ".class");
- }
-
- @Nullable
- @Override
- public ClassReader readerForInnerClass(VirtualFile innerClass) {
- try {
- return new ClassReader(innerClass.contentsToByteArray());
- }
- catch (IOException e) {
- return null;
- }
- }
- }
-
- private static String getPackageName(final PsiClassStub<PsiClass> result) {
- final String fqn = result.getQualifiedName();
- final String shortName = result.getName();
- if (fqn == null || Comparing.equal(shortName, fqn)) {
- return "";
- }
-
- return fqn.substring(0, fqn.lastIndexOf('.'));
- }
-}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java
index 89ea3bc..6033e54 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/SignatureParsing.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * 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.
@@ -56,14 +56,13 @@
return list;
}
- private static PsiTypeParameterStub parseTypeParameter(CharacterIterator signatureIterator, PsiTypeParameterListStub parent)
- throws ClsFormatException {
+ private static PsiTypeParameterStub parseTypeParameter(CharacterIterator iterator, PsiTypeParameterListStub parent) throws ClsFormatException {
StringBuilder name = new StringBuilder();
- while (signatureIterator.current() != ':' && signatureIterator.current() != CharacterIterator.DONE) {
- name.append(signatureIterator.current());
- signatureIterator.next();
+ while (iterator.current() != ':' && iterator.current() != CharacterIterator.DONE) {
+ name.append(iterator.current());
+ iterator.next();
}
- if (signatureIterator.current() == CharacterIterator.DONE) {
+ if (iterator.current() == CharacterIterator.DONE) {
throw new ClsFormatException();
}
@@ -71,9 +70,9 @@
PsiTypeParameterStub parameterStub = new PsiTypeParameterStubImpl(parent, StringRef.fromString(name.toString()));
List<String> bounds = ContainerUtil.newSmartList();
- while (signatureIterator.current() == ':') {
- signatureIterator.next();
- String bound = parseTopLevelClassRefSignature(signatureIterator);
+ while (iterator.current() == ':') {
+ iterator.next();
+ String bound = parseTopLevelClassRefSignature(iterator);
if (bound != null) {
bounds.add(bound);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
index d65a00d..3878101 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/StubBuildingVisitor.java
@@ -17,7 +17,8 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiNameHelper;
+import com.intellij.psi.PsiReferenceList;
import com.intellij.psi.impl.cache.ModifierFlags;
import com.intellij.psi.impl.cache.TypeInfo;
import com.intellij.psi.impl.java.stubs.*;
@@ -82,8 +83,16 @@
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
- String fqn = getClassName(name);
- String shortName = myShortName != null ? myShortName : PsiNameHelper.getShortClassName(fqn);
+ String fqn, shortName;
+ if (myShortName != null && name.endsWith(myShortName)) {
+ shortName = myShortName;
+ fqn = name.length() == shortName.length()
+ ? shortName : getClassName(name.substring(0, name.length() - shortName.length() - 1)) + "." + shortName;
+ }
+ else {
+ fqn = getClassName(name);
+ shortName = PsiNameHelper.getShortClassName(fqn);
+ }
int flags = myAccess == 0 ? access : myAccess;
boolean isDeprecated = (flags & Opcodes.ACC_DEPRECATED) != 0;
@@ -306,8 +315,9 @@
throw new OutOfOrderInnerClassException();
}
}
-
- if (!getClassName(outerName).equals(myResult.getQualifiedName())) return;
+ if (!namesEqual(outerName, myResult.getQualifiedName())) {
+ return;
+ }
final T innerSource = myInnersStrategy.findInnerClass(innerName, mySource);
if (innerSource == null) return;
@@ -323,6 +333,24 @@
return name != null;
}
+ private static boolean namesEqual(String signature, String fqn) {
+ if (fqn == null) return true; // impossible case, just ignore
+ if (fqn.length() != signature.length()) return false;
+
+ int p = 0, dot;
+ while ((dot = fqn.indexOf('.', p)) >= 0) {
+ if (!signature.regionMatches(p, fqn, p, dot - p)) {
+ return false;
+ }
+ char ch = signature.charAt(dot);
+ if (ch != '/' && ch != '$') {
+ return false;
+ }
+ p = dot + 1;
+ }
+ return fqn.regionMatches(p, signature, p, fqn.length() - p);
+ }
+
@Override
@Nullable
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
index 12964bc..bab137c 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/PsiPackageImpl.java
@@ -20,6 +20,7 @@
import com.intellij.lang.java.JavaLanguage;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
+import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
@@ -29,27 +30,27 @@
import com.intellij.psi.scope.ElementClassHint;
import com.intellij.psi.scope.NameHint;
import com.intellij.psi.scope.PsiScopeProcessor;
-import com.intellij.psi.search.DelegatingGlobalSearchScope;
+import com.intellij.psi.search.EverythingGlobalScope;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiSearchScopeUtil;
import com.intellij.psi.util.*;
import com.intellij.reference.SoftReference;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.CommonProcessors;
+import com.intellij.util.containers.ConcurrentSoftValueHashMap;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
public class PsiPackageImpl extends PsiPackageBase implements PsiPackage, Queryable {
public static boolean DEBUG = false;
private volatile CachedValue<PsiModifierList> myAnnotationList;
private volatile CachedValue<Collection<PsiDirectory>> myDirectories;
private volatile CachedValue<Collection<PsiDirectory>> myDirectoriesWithLibSources;
- private volatile SoftReference<Set<String>> myPublicClassNamesCache;
+ private volatile SoftReference<Map<String, PsiClass[]>> myClassCache;
public PsiPackageImpl(PsiManager manager, String qualifiedName) {
super(manager, qualifiedName);
@@ -175,44 +176,66 @@
return (JavaPsiFacadeImpl)JavaPsiFacade.getInstance(myManager.getProject());
}
- private Set<String> getClassNamesCache() {
- SoftReference<Set<String>> ref = myPublicClassNamesCache;
- Set<String> cache = ref == null ? null : ref.get();
- if (cache == null) {
- GlobalSearchScope scope = allScope();
-
- if (!scope.isForceSearchingInLibrarySources()) {
- scope = new DelegatingGlobalSearchScope(scope) {
- @Override
- public boolean isForceSearchingInLibrarySources() {
- return true;
- }
- };
- }
- cache = getFacade().getClassNames(this, scope);
- myPublicClassNamesCache = new SoftReference<Set<String>>(cache);
- }
-
- return cache;
- }
-
@NotNull
- private PsiClass[] findClassesByName(String name, GlobalSearchScope scope) {
+ private PsiClass[] getCachedClassesByName(String name) {
+ SoftReference<Map<String, PsiClass[]>> ref = myClassCache;
+ Map<String, PsiClass[]> map = SoftReference.dereference(ref);
+ if (map == null) {
+ myClassCache = new SoftReference<Map<String, PsiClass[]>>(map = new ConcurrentSoftValueHashMap<String, PsiClass[]>());
+ }
+ PsiClass[] classes = map.get(name);
+ if (classes != null) {
+ return classes;
+ }
+
+ GlobalSearchScope scope = new EverythingGlobalScope(getProject());
+
+ if (DumbService.getInstance(getProject()).isDumb()) {
+ if (ref == null) {
+ for (PsiClass psiClass : getClasses(scope)) {
+ String psiClassName = psiClass.getName();
+ if (psiClassName != null) {
+ PsiClass[] existing = map.get(psiClassName);
+ map.put(psiClassName, existing == null ? new PsiClass[]{psiClass} : ArrayUtil.append(existing, psiClass));
+ }
+ }
+ }
+ classes = map.get(name);
+ return classes == null ? PsiClass.EMPTY_ARRAY : classes;
+ }
+
final String qName = getQualifiedName();
final String classQName = !qName.isEmpty() ? qName + "." + name : name;
- return getFacade().findClasses(classQName, scope);
+ map.put(name, classes = getFacade().findClasses(classQName, scope));
+ return classes;
}
-
+
@Override
public boolean containsClassNamed(String name) {
- return getClassNamesCache().contains(name);
+ return getCachedClassesByName(name).length > 0;
}
@NotNull
@Override
- public PsiClass[] findClassByShortName(@NotNull String name, @NotNull GlobalSearchScope scope) {
- if (!containsClassNamed(name)) return PsiClass.EMPTY_ARRAY;
- return getFacade().findClassByShortName(name, this, scope);
+ public PsiClass[] findClassByShortName(@NotNull String name, @NotNull final GlobalSearchScope scope) {
+ PsiClass[] allClasses = getCachedClassesByName(name);
+ if (allClasses.length == 0) return allClasses;
+ if (allClasses.length == 1) {
+ return PsiSearchScopeUtil.isInScope(scope, allClasses[0]) ? allClasses : PsiClass.EMPTY_ARRAY;
+ }
+ PsiClass[] array = ContainerUtil.findAllAsArray(allClasses, new Condition<PsiClass>() {
+ @Override
+ public boolean value(PsiClass aClass) {
+ return PsiSearchScopeUtil.isInScope(scope, aClass);
+ }
+ });
+ Arrays.sort(array, new Comparator<PsiClass>() {
+ @Override
+ public int compare(PsiClass o1, PsiClass o2) {
+ return scope.compare(o2.getContainingFile().getVirtualFile(), o1.getContainingFile().getVirtualFile());
+ }
+ });
+ return array;
}
@Nullable
@@ -233,24 +256,18 @@
ElementClassHint classHint = processor.getHint(ElementClassHint.KEY);
final JavaPsiFacade facade = getFacade();
- final Condition<String> prefixMatcher = processor.getHint(JavaCompletionHints.NAME_FILTER);
+ final Condition<String> nameCondition = processor.getHint(JavaCompletionHints.NAME_FILTER);
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
NameHint nameHint = processor.getHint(NameHint.KEY);
if (nameHint != null) {
final String shortName = nameHint.getName(state);
- if (containsClassNamed(shortName) && processClassesByName(processor, state, scope, shortName)) return false;
- }
- else if (prefixMatcher != null) {
- for (String className : getClassNamesCache()) {
- if (prefixMatcher.value(className)) {
- if (processClassesByName(processor, state, scope, className)) return false;
- }
- }
+ final PsiClass[] classes = findClassByShortName(shortName, scope);
+ if (!processClasses(processor, state, classes, Condition.TRUE)) return false;
}
else {
PsiClass[] classes = getClasses(scope);
- if (!processClasses(processor, state, classes)) return false;
+ if (!processClasses(processor, state, classes, nameCondition != null ? nameCondition : Condition.TRUE)) return false;
}
}
if (classHint == null || classHint.shouldProcess(ElementClassHint.DeclarationKind.PACKAGE)) {
@@ -278,17 +295,11 @@
return true;
}
- private boolean processClassesByName(PsiScopeProcessor processor,
- ResolveState state,
- GlobalSearchScope scope,
- String className) {
- final PsiClass[] classes = findClassesByName(className, scope);
- return !processClasses(processor, state, classes);
- }
-
- private static boolean processClasses(PsiScopeProcessor processor, ResolveState state, PsiClass[] classes) {
+ private static boolean processClasses(PsiScopeProcessor processor, ResolveState state, PsiClass[] classes,
+ @NotNull Condition<String> nameCondition) {
for (PsiClass aClass : classes) {
- if (!processor.execute(aClass, state)) return false;
+ String name = aClass.getName();
+ if (name != null && nameCondition.value(name) && !processor.execute(aClass, state)) return false;
}
return true;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/file/impl/JavaFileManager.java b/java/java-psi-impl/src/com/intellij/psi/impl/file/impl/JavaFileManager.java
index 059fa74..fc883fe 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/file/impl/JavaFileManager.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/file/impl/JavaFileManager.java
@@ -38,5 +38,4 @@
Collection<String> getNonTrivialPackagePrefixes();
- void initialize();
}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java
index 3262f35..f704bf0 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiAnnotationStubImpl.java
@@ -57,17 +57,15 @@
@Override
public PsiAnnotation getPsiElement() {
- if (myParsedFromRepository != null) {
- PsiAnnotation annotation = myParsedFromRepository.get();
- if (annotation != null) {
- return annotation;
- }
+ PsiAnnotation annotation = SoftReference.dereference(myParsedFromRepository);
+ if (annotation != null) {
+ return annotation;
}
final String text = getText();
try {
PsiJavaParserFacade facade = JavaPsiFacade.getInstance(getProject()).getParserFacade();
- PsiAnnotation annotation = facade.createAnnotationFromText(text, getPsi());
+ annotation = facade.createAnnotationFromText(text, getPsi());
myParsedFromRepository = new SoftReference<PsiAnnotation>(annotation);
return annotation;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java
index 1de00bf..65c6019 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/java/stubs/impl/PsiImportStatementStubImpl.java
@@ -77,7 +77,7 @@
@Override
@Nullable
public PsiJavaCodeReferenceElement getReference() {
- PsiJavaCodeReferenceElement ref = myReference != null ? myReference.get() : null;
+ PsiJavaCodeReferenceElement ref = SoftReference.dereference(myReference);
if (ref == null) {
ref = isStatic() ? getStaticReference() : getRegularReference();
myReference = new SoftReference<PsiJavaCodeReferenceElement>(ref);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/smartPointers/TypePointerBase.java b/java/java-psi-impl/src/com/intellij/psi/impl/smartPointers/TypePointerBase.java
index 895ea66..1f3baf5 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/smartPointers/TypePointerBase.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/smartPointers/TypePointerBase.java
@@ -35,8 +35,7 @@
@Override
public T getType() {
- Reference<T> typeRef = myTypeRef;
- T myType = typeRef == null ? null : typeRef.get();
+ T myType = SoftReference.dereference(myTypeRef);
if (myType != null && myType.isValid()) return myType;
myType = calcType();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java
index 70229d1..def3bb3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnnotationMethodImpl.java
@@ -57,17 +57,15 @@
final String text = stub.getDefaultValueText();
if (StringUtil.isEmpty(text)) return null;
- if (myCachedDefaultValue != null) {
- final PsiAnnotationMemberValue value = myCachedDefaultValue.get();
- if (value != null) {
- return value;
- }
+ PsiAnnotationMemberValue value = SoftReference.dereference(myCachedDefaultValue);
+ if (value != null) {
+ return value;
}
@NonNls final String annoText = "@interface _Dummy_ { Class foo() default " + text + "; }";
final PsiFileFactory factory = PsiFileFactory.getInstance(getProject());
final PsiJavaFile file = (PsiJavaFile)factory.createFileFromText("a.java", JavaFileType.INSTANCE, annoText);
- final PsiAnnotationMemberValue value = ((PsiAnnotationMethod)file.getClasses()[0].getMethods()[0]).getDefaultValue();
+ value = ((PsiAnnotationMethod)file.getClasses()[0].getMethods()[0]).getDefaultValue();
myCachedDefaultValue = new SoftReference<PsiAnnotationMemberValue>(value);
return value;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java
index 9d14b52..b25f033 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiAnonymousClassImpl.java
@@ -72,19 +72,17 @@
return getTypeByTree();
}
- PsiClassType type = null;
- if (myCachedBaseType != null) type = myCachedBaseType.get();
+ PsiClassType type = SoftReference.dereference(myCachedBaseType);
if (type != null) return type;
if (!isInQualifiedNew()) {
- final PsiJavaCodeReferenceElement ref;
final String refText = stub.getBaseClassReferenceText();
assert refText != null : stub;
final PsiElementFactory factory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
final PsiElement context = calcBasesResolveContext(PsiNameHelper.getShortClassName(refText), getExtendsList());
try {
- ref = factory.createReferenceFromText(refText, context);
+ final PsiJavaCodeReferenceElement ref = factory.createReferenceFromText(refText, context);
((PsiJavaCodeReferenceElementImpl)ref).setKindWhenDummy(PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND);
type = factory.createType(ref);
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java
index 6d6229c..5edd337 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiClassImpl.java
@@ -720,7 +720,7 @@
PsiMethod method = myValueOfMethod;
if (method == null && isEnum() && getName() != null) {
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(getProject()).getElementFactory();
- final PsiMethod valuesMethod = elementFactory.createMethodFromText("public static " + getName() + " valueOf(String name) throws IllegalArgumentException {}", this);
+ final PsiMethod valuesMethod = elementFactory.createMethodFromText("public static " + getName() + " valueOf(String name) throws java.lang.IllegalArgumentException {}", this);
myValueOfMethod = method = new LightMethod(getManager(), valuesMethod, this);
}
return method;
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 72cd0de..a43c02d 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
@@ -60,7 +60,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
return Comparing.equal(text, getCanonicalText());
}
@@ -92,10 +92,11 @@
private static class DelegatingClassResolveResult implements ClassResolveResult {
private final JavaResolveResult myDelegate;
- private DelegatingClassResolveResult(JavaResolveResult delegate) {
+ private DelegatingClassResolveResult(@NotNull JavaResolveResult delegate) {
myDelegate = delegate;
}
+ @NotNull
@Override
public PsiSubstitutor getSubstitutor() {
return myDelegate.getSubstitutor();
@@ -178,16 +179,19 @@
return element == null ? this : new PsiImmediateClassType(element, resolveResult.getSubstitutor());
}
+ @NotNull
@Override
public String getPresentableText() {
return getAnnotationsTextPrefix(false, false, true) + PsiNameHelper.getPresentableText(myReference);
}
+ @NotNull
@Override
public String getCanonicalText() {
return myReference.getCanonicalText();
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getAnnotationsTextPrefix(true, false, true) + getCanonicalText();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
index 3535bfe..367a8bb 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiFieldImpl.java
@@ -128,15 +128,12 @@
public PsiType getType() {
final PsiFieldStub stub = getStub();
if (stub != null) {
- SoftReference<PsiType> cachedType = myCachedType;
- if (cachedType != null) {
- PsiType type = cachedType.get();
- if (type != null) return type;
- }
+ PsiType type = SoftReference.dereference(myCachedType);
+ if (type != null) return type;
String typeText = TypeInfo.createTypeText(stub.getType(true));
try {
- final PsiType type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
+ type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
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 3850cea..9456c29 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
@@ -44,6 +44,7 @@
return myClass;
}
+ @NotNull
@Override
public PsiSubstitutor getSubstitutor() {
return mySubstitutor;
@@ -118,7 +119,7 @@
lst.add(substituted);
}
}
- return lst.toArray(new PsiType[lst.size()]);
+ return lst.toArray(createArray(lst.size()));
}
@Override
@@ -133,6 +134,7 @@
return JavaPsiFacade.getInstance(myClass.getProject()).getElementFactory().createType(myClass);
}
+ @NotNull
@Override
public String getPresentableText() {
if (myPresentableText == null) {
@@ -143,6 +145,7 @@
return myPresentableText;
}
+ @NotNull
@Override
public String getCanonicalText() {
if (myCanonicalText == null) {
@@ -154,6 +157,7 @@
return myCanonicalText;
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
if (myInternalCanonicalText == null) {
@@ -251,7 +255,7 @@
}
@Override
- public boolean equalsToText(String text) {
+ public boolean equalsToText(@NotNull String text) {
PsiElementFactory factory = JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory();
final PsiType patternType;
try {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java
index b252f1f..c5af2ad 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementBaseImpl.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.
@@ -63,4 +63,9 @@
final PsiJavaCodeReferenceElement reference = getImportReference();
return reference == null ? null : reference.resolve();
}
+
+ @Override
+ public boolean isForeignFileImport() {
+ return false;
+ }
}
\ No newline at end of file
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementImpl.java
index 7c955ca..80461d3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiImportStatementImpl.java
@@ -42,6 +42,10 @@
@Override
public String getQualifiedName() {
+ PsiImportStatementStub stub = getStub();
+ if (stub != null) {
+ return stub.getImportReferenceText();
+ }
final PsiJavaCodeReferenceElement reference = getImportReference();
return reference == null ? null : reference.getCanonicalText();
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java
index 59a0e3d..b8ef7d3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiMethodImpl.java
@@ -37,14 +37,13 @@
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.stubs.IStubElementType;
-import com.intellij.psi.util.MethodSignature;
-import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
-import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.*;
import com.intellij.reference.SoftReference;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
@@ -196,14 +195,11 @@
final String typeText = TypeInfo.createTypeText(stub.getReturnTypeText(true));
if (typeText == null) return null;
- SoftReference<PsiType> cachedType = myCachedType;
- if (cachedType != null) {
- PsiType type = cachedType.get();
- if (type != null) return type;
- }
+ PsiType type = SoftReference.dereference(myCachedType);
+ if (type != null) return type;
try {
- final PsiType type = JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeFromText(typeText, this);
+ type = JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeFromText(typeText, this);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
@@ -311,7 +307,17 @@
@Override
@NotNull
- public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor){
+ public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor) {
+ if (substitutor == PsiSubstitutor.EMPTY) {
+ return CachedValuesManager.getCachedValue(this, new CachedValueProvider<MethodSignature>() {
+ @Nullable
+ @Override
+ public Result<MethodSignature> compute() {
+ MethodSignature signature = MethodSignatureBackedByPsiMethod.create(PsiMethodImpl.this, PsiSubstitutor.EMPTY);
+ return Result.create(signature, PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
+ }
+ });
+ }
return MethodSignatureBackedByPsiMethod.create(this, substitutor);
}
@@ -319,9 +325,12 @@
public PsiElement getOriginalElement() {
final PsiClass containingClass = getContainingClass();
if (containingClass != null) {
- final PsiMethod originalMethod = ((PsiClass)containingClass.getOriginalElement()).findMethodBySignature(this, false);
- if (originalMethod != null) {
- return originalMethod;
+ PsiElement original = containingClass.getOriginalElement();
+ if (original != containingClass) {
+ final PsiMethod originalMethod = ((PsiClass)original).findMethodBySignature(this, false);
+ if (originalMethod != null) {
+ return originalMethod;
+ }
}
}
return this;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java
index 7378569..925c0ee 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java
@@ -130,7 +130,7 @@
return false;
}
if (type == JavaTokenType.ABSTRACT_KEYWORD) {
- return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null;
+ return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null && getNode().findChildByType(JavaTokenType.STATIC_KEYWORD) == null;
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
index 52827e2..287fba0 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiParameterImpl.java
@@ -39,12 +39,13 @@
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
+import java.lang.ref.Reference;
import java.util.Arrays;
public class PsiParameterImpl extends JavaStubPsiElement<PsiParameterStub> implements PsiParameter {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.PsiParameterImpl");
- private volatile SoftReference<PsiType> myCachedType = null;
+ private volatile Reference<PsiType> myCachedType = null;
public PsiParameterImpl(@NotNull PsiParameterStub stub) {
this(stub, JavaStubElementTypes.PARAMETER);
@@ -116,16 +117,13 @@
public PsiType getType() {
PsiParameterStub stub = getStub();
if (stub != null) {
- SoftReference<PsiType> cachedType = myCachedType;
- if (cachedType != null) {
- PsiType type = cachedType.get();
- if (type != null) return type;
- }
+ PsiType type = SoftReference.dereference(myCachedType);
+ if (type != null) return type;
String typeText = TypeInfo.createTypeText(stub.getType(true));
assert typeText != null : stub;
try {
- PsiType type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
+ type = JavaPsiFacade.getInstance(getProject()).getParserFacade().createTypeFromText(typeText, this);
myCachedType = new SoftReference<PsiType>(type);
return type;
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java
index 121ebdf..959df6e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocCommentImpl.java
@@ -192,19 +192,27 @@
}
needToAddNewline = true;
}
- if (anchor.getElementType() != DOC_TAG) {
- final CharTable charTable = SharedImplUtil.findCharTableByTree(this);
- final TreeElement newLine = Factory.createSingleLeafElement(DOC_COMMENT_DATA, "\n", 0, 1, charTable, getManager());
- final TreeElement leadingAsterisk = Factory.createSingleLeafElement(DOC_COMMENT_LEADING_ASTERISKS, "*", 0, 1, charTable, getManager());
- final TreeElement commentData = Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
- final TreeElement indentWS = Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
- newLine.getTreeParent().addChild(indentWS);
- newLine.getTreeParent().addChild(leadingAsterisk);
- newLine.getTreeParent().addChild(commentData);
- super.addInternal(newLine, commentData, anchor, Boolean.FALSE);
- anchor = commentData;
- before = Boolean.FALSE;
+ if (anchor.getElementType() != DOC_TAG) {
+ if (nodeOnSameLineWithCommentStartBlock(anchor)
+ || !nodeIsNextAfterAsterisks(anchor)
+ || !docTagEndsWithLineFeedAndAsterisks(first))
+ {
+ final CharTable charTable = SharedImplUtil.findCharTableByTree(this);
+ final TreeElement newLine = Factory.createSingleLeafElement(DOC_COMMENT_DATA, "\n", 0, 1, charTable, getManager());
+ final TreeElement leadingAsterisk = Factory.createSingleLeafElement(DOC_COMMENT_LEADING_ASTERISKS, "*", 0, 1, charTable, getManager());
+ final TreeElement commentData = Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
+ final TreeElement indentWS = Factory.createSingleLeafElement(DOC_COMMENT_DATA, " ", 0, 1, charTable, getManager());
+
+ newLine.getTreeParent().addChild(indentWS);
+ newLine.getTreeParent().addChild(leadingAsterisk);
+ newLine.getTreeParent().addChild(commentData);
+
+ super.addInternal(newLine, commentData, anchor, Boolean.FALSE);
+
+ anchor = commentData;
+ before = Boolean.FALSE;
+ }
}
else {
needToAddNewline = true;
@@ -243,6 +251,45 @@
}
}
+ private static boolean nodeIsNextAfterAsterisks(@NotNull ASTNode node) {
+ ASTNode current = TreeUtil.findSiblingBackward(node, DOC_COMMENT_LEADING_ASTERISKS);
+ if (current == null || current == node) return false;
+ while (current.getTreeNext() != node) {
+ current = current.getTreeNext();
+ CharSequence currentText = current.getChars();
+ if (CharArrayUtil.shiftForward(currentText, 0, " \t") != currentText.length()) return false;
+ }
+ return true;
+ }
+
+ private static boolean docTagEndsWithLineFeedAndAsterisks(@NotNull ASTNode node) {
+ assert (node.getElementType() == DOC_TAG);
+ ASTNode lastAsterisks = TreeUtil.findChildBackward(node, DOC_COMMENT_LEADING_ASTERISKS);
+ if (lastAsterisks == null || !lastAsterisks.getTreePrev().textContains('\n')) {
+ return false;
+ }
+ //So last asterisk is placed on new line, checking if after it there are no non-whitespace symbols
+ ASTNode last = node.getLastChildNode();
+ ASTNode current = lastAsterisks;
+ while (current != last) {
+ current = current.getTreeNext();
+ CharSequence currentText = current.getChars();
+ if (CharArrayUtil.shiftForward(currentText, 0, " \t") != currentText.length()) return false;
+ }
+ return true;
+ }
+
+ private static boolean nodeOnSameLineWithCommentStartBlock(@NotNull ASTNode node) {
+ ASTNode current = TreeUtil.findSiblingBackward(node, DOC_COMMENT_START);
+ if (current == null) return false;
+ if (current == node) return true;
+ while (current.getTreeNext() != node) {
+ current = current.getTreeNext();
+ if (current.textContains('\n')) return false;
+ }
+ return true;
+ }
+
@Override
public void deleteChildInternal(@NotNull ASTNode child) {
if (child.getElementType() == DOC_TAG) {
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java
index 4c3ad50..28d12cd 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/javadoc/PsiDocMethodOrFieldRef.java
@@ -105,7 +105,7 @@
types.add(PsiType.NULL);
}
}
- methodSignature = MethodSignatureUtil.createMethodSignature(name, types.toArray(new PsiType[types.size()]),
+ methodSignature = MethodSignatureUtil.createMethodSignature(name, types.toArray(PsiType.createArray(types.size())),
PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY,
name.equals(scope.getName()));
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/GraphInferencePolicy.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/GraphInferencePolicy.java
index 1b2ea84..b6a0baa 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/GraphInferencePolicy.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/GraphInferencePolicy.java
@@ -73,7 +73,7 @@
protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
if (argumentList != null) {
final PsiExpression[] expressions = argumentList.getExpressions();
- final PsiType[] types = new PsiType[expressions.length];
+ final PsiType[] types = PsiType.createArray(expressions.length);
for (int i = 0; i < expressions.length; i++) {
if (i != exprIdx) {
types[i] = expressions[i].getType();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
index 7389517..185d08e 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/JavaResolveCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -124,7 +124,7 @@
private <T extends PsiExpression> PsiType getCachedType(T expr) {
Reference<PsiType> reference = myCalculatedTypes.get(expr);
- return reference == null ? null : reference.get();
+ return SoftReference.dereference(reference);
}
@Nullable
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 6bb94b3..5b76439 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
@@ -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.
@@ -232,7 +232,8 @@
CandidateInfo resolveResult = (CandidateInfo)result[i];
PsiElement resultElement = resolveResult.getElement();
if (resultElement instanceof PsiClass && ((PsiClass)resultElement).hasTypeParameters()) {
- result[i] = new CandidateInfo(resolveResult, resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters));
+ PsiSubstitutor substitutor = resolveResult.getSubstitutor().putAll((PsiClass)resultElement, parameters);
+ result[i] = new CandidateInfo(resolveResult, substitutor);
}
}
}
@@ -240,10 +241,10 @@
@NotNull
public static <T extends PsiPolyVariantReference> JavaResolveResult[] resolveWithContainingFile(@NotNull T ref,
- @NotNull ResolveCache.PolyVariantResolver<T> resolver,
- boolean needToPreventRecursion,
- boolean incompleteCode,
- @NotNull PsiFile containingFile) {
+ @NotNull ResolveCache.PolyVariantResolver<T> resolver,
+ boolean needToPreventRecursion,
+ boolean incompleteCode,
+ @NotNull PsiFile containingFile) {
boolean valid = containingFile.isValid();
if (!valid) {
return JavaResolveResult.EMPTY_ARRAY;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java
index 8615d91..bb75e07 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/PsiOldInferenceHelper.java
@@ -27,7 +27,6 @@
import com.intellij.openapi.util.registry.Registry;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
-import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
@@ -57,36 +56,36 @@
@NotNull PsiSubstitutor partialSubstitutor,
final PsiElement parent,
@NotNull ParameterTypeInferencePolicy policy) {
- PsiType[] paramTypes = new PsiType[arguments.length];
- PsiType[] argTypes = new PsiType[arguments.length];
- if (parameters.length > 0) {
- for (int j = 0; j < argTypes.length; j++) {
- final PsiExpression argument = arguments[j];
- if (argument == null) continue;
- if (argument instanceof PsiMethodCallExpression && PsiResolveHelper.ourGuard.currentStack().contains(argument)) continue;
+ PsiType[] paramTypes = PsiType.createArray(arguments.length);
+ PsiType[] argTypes = PsiType.createArray(arguments.length);
+ if (parameters.length > 0) {
+ for (int j = 0; j < argTypes.length; j++) {
+ final PsiExpression argument = arguments[j];
+ if (argument == null) continue;
+ if (argument instanceof PsiMethodCallExpression && PsiResolveHelper.ourGuard.currentStack().contains(argument)) continue;
- final RecursionGuard.StackStamp stackStamp = PsiDiamondType.ourDiamondGuard.markStack();
- argTypes[j] = argument.getType();
- if (!stackStamp.mayCacheNow()) {
- argTypes[j] = null;
- continue;
- }
+ final RecursionGuard.StackStamp stackStamp = PsiDiamondType.ourDiamondGuard.markStack();
+ argTypes[j] = argument.getType();
+ if (!stackStamp.mayCacheNow()) {
+ argTypes[j] = null;
+ continue;
+ }
- final PsiParameter parameter = parameters[Math.min(j, parameters.length - 1)];
- if (j >= parameters.length && !parameter.isVarArgs()) break;
- paramTypes[j] = parameter.getType();
- if (paramTypes[j] instanceof PsiEllipsisType) {
- paramTypes[j] = ((PsiEllipsisType)paramTypes[j]).getComponentType();
- if (arguments.length == parameters.length &&
- argTypes[j] instanceof PsiArrayType &&
- !(((PsiArrayType)argTypes[j]).getComponentType() instanceof PsiPrimitiveType)) {
- argTypes[j] = ((PsiArrayType)argTypes[j]).getComponentType();
+ final PsiParameter parameter = parameters[Math.min(j, parameters.length - 1)];
+ if (j >= parameters.length && !parameter.isVarArgs()) break;
+ paramTypes[j] = parameter.getType();
+ if (paramTypes[j] instanceof PsiEllipsisType) {
+ paramTypes[j] = ((PsiEllipsisType)paramTypes[j]).getComponentType();
+ if (arguments.length == parameters.length &&
+ argTypes[j] instanceof PsiArrayType &&
+ !(((PsiArrayType)argTypes[j]).getComponentType() instanceof PsiPrimitiveType)) {
+ argTypes[j] = ((PsiArrayType)argTypes[j]).getComponentType();
+ }
}
}
}
+ return inferTypeForMethodTypeParameterInner(typeParameter, paramTypes, argTypes, partialSubstitutor, parent, policy);
}
- return inferTypeForMethodTypeParameterInner(typeParameter, paramTypes, argTypes, partialSubstitutor, parent, policy);
- }
private Pair<PsiType, ConstraintType> inferTypeForMethodTypeParameterInner(@NotNull PsiTypeParameter typeParameter,
@NotNull PsiType[] paramTypes,
@@ -255,7 +254,7 @@
@NotNull PsiElement parent,
@NotNull ParameterTypeInferencePolicy policy,
@NotNull LanguageLevel languageLevel) {
- PsiType[] substitutions = new PsiType[typeParameters.length];
+ PsiType[] substitutions = PsiType.createArray(typeParameters.length);
@SuppressWarnings("unchecked")
Pair<PsiType, ConstraintType>[] constraints = new Pair[typeParameters.length];
for (int i = 0; i < typeParameters.length; i++) {
@@ -307,7 +306,6 @@
}
}
}
-
}
}
@@ -334,7 +332,8 @@
constraint = inferMethodTypeParameterFromParent(typeParameter, partialSubstitutor, parent, policy);
}
else if (constraint.getSecond() == ConstraintType.SUBTYPE) {
- Pair<PsiType, ConstraintType> otherConstraint = inferMethodTypeParameterFromParent(typeParameter, partialSubstitutor, parent, policy);
+ Pair<PsiType, ConstraintType> otherConstraint =
+ inferMethodTypeParameterFromParent(typeParameter, partialSubstitutor, parent, policy);
if (otherConstraint != null) {
if (otherConstraint.getSecond() == ConstraintType.EQUALS || otherConstraint.getSecond() == ConstraintType.SUPERTYPE) {
constraint = otherConstraint;
@@ -586,7 +585,7 @@
if (functionalInterfaceMethod != null) {
final PsiSubstitutor subst = LambdaUtil.getSubstitutor(functionalInterfaceMethod, resolveResult);
final PsiParameter[] methodParameters = functionalInterfaceMethod.getParameterList().getParameters();
- PsiType[] methodParamTypes = new PsiType[methodParameters.length];
+ PsiType[] methodParamTypes = PsiType.createArray(methodParameters.length);
for (int i = 0; i < methodParameters.length; i++) {
methodParamTypes[i] = GenericsUtil.eliminateWildcards(subst.substitute(methodParameters[i].getType()));
}
@@ -595,7 +594,7 @@
return null;
}
- final PsiType[] args = new PsiType[methodParameters.length];
+ final PsiType[] args = PsiType.createArray(methodParameters.length);
Map<PsiMethodReferenceExpression,PsiType> map = PsiMethodReferenceUtil.ourRefs.get();
if (map == null) {
map = new HashMap<PsiMethodReferenceExpression, PsiType>();
@@ -744,7 +743,7 @@
PsiMethod method, PsiLambdaExpression lambdaExpression) {
final PsiParameter[] parameters = lambdaExpression.getParameterList().getParameters();
if (parameters.length == 0) return null;
- final PsiType[] lambdaArgs = new PsiType[parameters.length];
+ final PsiType[] lambdaArgs = PsiType.createArray(parameters.length);
for (int i = 0; i < parameters.length; i++) {
PsiParameter parameter = parameters[i];
if (parameter.getTypeElement() == null) {
@@ -754,7 +753,7 @@
}
final PsiParameter[] methodParameters = method.getParameterList().getParameters();
- PsiType[] methodParamTypes = new PsiType[methodParameters.length];
+ PsiType[] methodParamTypes = PsiType.createArray(methodParameters.length);
for (int i = 0; i < methodParameters.length; i++) {
methodParamTypes[i] = GenericsUtil.eliminateWildcards(subst.substitute(methodParameters[i].getType()));
}
@@ -764,7 +763,7 @@
private static PsiType intersectAllExtends(PsiTypeParameter typeParam, PsiType arg) {
if (arg == null) return null;
PsiClassType[] superTypes = typeParam.getSuperTypes();
- PsiType[] erasureTypes = new PsiType[superTypes.length];
+ PsiType[] erasureTypes = PsiType.createArray(superTypes.length);
for (int i = 0; i < superTypes.length; i++) {
erasureTypes[i] = TypeConversionUtil.erasure(superTypes[i]);
}
@@ -1084,7 +1083,7 @@
PsiType[] superTypes = typeParameter.getSuperTypes();
if (superTypes.length == 0) return null;
- final PsiType[] types = new PsiType[superTypes.length];
+ final PsiType[] types = PsiType.createArray(superTypes.length);
for (int i = 0; i < superTypes.length; i++) {
PsiType superType = substitutor.substitute(superTypes[i]);
if (superType instanceof PsiClassType && ((PsiClassType)superType).isRaw()) {
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 86c1f5f..1195b74 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,9 +18,13 @@
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;
+import java.util.HashSet;
+
public class FunctionalInterfaceParameterizationUtil {
private static final Logger LOG = Logger.getInstance("#" + FunctionalInterfaceParameterizationUtil.class.getName());
@@ -43,20 +47,26 @@
}
@Nullable
- public static PsiType getFunctionalType(@Nullable PsiType psiClassType, PsiLambdaExpression expr) {
- return getFunctionalType(psiClassType, expr, true);
+ public static PsiType getGroundTargetType(@Nullable PsiType psiClassType) {
+ return getGroundTargetType(psiClassType, null);
}
@Nullable
- public static PsiType getFunctionalType(@Nullable PsiType psiClassType, PsiLambdaExpression expr, boolean resolve) {
- if (!expr.hasFormalParameterTypes() || expr.getParameterList().getParametersCount() == 0) return psiClassType;
+ public static PsiType getGroundTargetType(@Nullable PsiType psiClassType, @Nullable PsiLambdaExpression expr) {
if (!isWildcardParameterized(psiClassType)) {
return psiClassType;
}
+
+ if (expr != null && expr.hasFormalParameterTypes()) return getFunctionalTypeExplicit(psiClassType, expr);
+
+ return psiClassType instanceof PsiClassType ? getNonWildcardParameterization((PsiClassType)psiClassType) : null;
+ }
+
+ private static PsiType getFunctionalTypeExplicit(PsiType psiClassType, PsiLambdaExpression expr) {
final PsiParameter[] lambdaParams = expr.getParameterList().getParameters();
if (psiClassType instanceof PsiIntersectionType) {
for (PsiType psiType : ((PsiIntersectionType)psiClassType).getConjuncts()) {
- final PsiType functionalType = getFunctionalType(psiType, expr, false);
+ final PsiType functionalType = getFunctionalTypeExplicit(psiType, expr);
if (functionalType != null) return functionalType;
}
return null;
@@ -72,26 +82,107 @@
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
if (interfaceMethod == null) return null;
- final InferenceSession session = new InferenceSession(PsiSubstitutor.EMPTY);
PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
if (typeParameters.length != parameters.length) {
return null;
}
-
- for (int i = 0; i < typeParameters.length; i++) {
- session.addVariable(typeParameters[i], parameters[i]);
- }
-
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(psiClass.getProject());
final PsiParameter[] targetMethodParams = interfaceMethod.getParameterList().getParameters();
+ if (targetMethodParams.length != lambdaParams.length) {
+ return null;
+ }
+
+ final InferenceSession session = new InferenceSession(typeParameters, PsiSubstitutor.EMPTY, expr.getManager(), expr);
+
for (int i = 0; i < targetMethodParams.length; i++) {
- if (resolve) {
- session.addConstraint(new TypeEqualityConstraint(lambdaParams[i].getType(), targetMethodParams[i].getType()));
+ session.addConstraint(new TypeEqualityConstraint(lambdaParams[i].getType(), targetMethodParams[i].getType()));
+ }
+
+ if (!session.repeatInferencePhases(false)) {
+ return null;
+ }
+
+ session.resolveBounds(false);
+ final PsiType[] newTypeParameters = new PsiType[parameters.length];
+ for (int i = 0; i < typeParameters.length; i++) {
+ PsiTypeParameter typeParameter = typeParameters[i];
+ final InferenceVariable variable = session.getInferenceVariable(typeParameter);
+ final PsiType instantiation = variable.getInstantiation();
+ if (instantiation != PsiType.NULL) {
+ newTypeParameters[i] = instantiation;
+ } else {
+ newTypeParameters[i] = parameters[i];
}
}
- final PsiClassType parameterization = elementFactory.createType(psiClass, session.infer());
- if (!TypeConversionUtil.containsWildcards(parameterization)) return parameterization;
+ final PsiClassType parameterization = elementFactory.createType(psiClass, newTypeParameters);
+
+ if (!isWellFormed(psiClass, typeParameters, newTypeParameters)) {
+ return null;
+ }
+
+ if (!TypeConversionUtil.containsWildcards(parameterization)) {
+ return parameterization;
+ }
+
+ return getNonWildcardParameterization(parameterization);
+ }
+ return null;
+ }
+
+ private static boolean isWellFormed(PsiClass psiClass, PsiTypeParameter[] typeParameters, PsiType[] newTypeParameters) {
+ final PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.putAll(psiClass, newTypeParameters);
+ for (int i = 0; i < typeParameters.length; i++) {
+ for (PsiClassType bound : typeParameters[i].getExtendsListTypes()) {
+ if (GenericsUtil.checkNotInBounds(newTypeParameters[i], substitutor.substitute(bound), false)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ The function type of a parameterized functional interface, F<A1...An>, where one or more of A1...An is a wildcard, is the function type of the non-wildcard parameterization of F, F<T1...Tn> determined as follows.
+ Let P1, ..., Pn be the type parameters of F and B1, ..., Bn be the corresponding bounds. For all i, 1 ≤ i ≤ n, Ti is derived according to the form of Ai:
+
+ If Ai is a type, then Ti = Ai.
+ If Ai is a wildcard, and the corresponding type parameter bound, Bi, mentions one of P1...Pn, then Ti is undefined and there is no function type.
+ Otherwise:
+ If Ai is an unbound wildcard ?, then Ti = Bi.
+ If Ai is a upper-bounded wildcard ? extends Ui, then Ti = glb(Ui, Bi).
+ If Ai is a lower-bounded wildcard ? super Li, then Ti = Li.
+ */
+ @Nullable
+ public static PsiType getNonWildcardParameterization(PsiClassType psiClassType) {
+ final PsiClass psiClass = psiClassType.resolve();
+ if (psiClass != null) {
+ final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
+ final PsiType[] parameters = psiClassType.getParameters();
+
+ if (parameters.length != typeParameters.length) return null;
+
+ final HashSet<PsiTypeParameter> typeParametersSet = ContainerUtil.newHashSet(typeParameters);
+ 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 = ((PsiWildcardType)paramType).getBound();
+ if (bound == null) {
+ parameters[i] = Bi;
+ } else if (((PsiWildcardType)paramType).isExtends()){
+ parameters[i] = GenericsUtil.getGreatestLowerBound(Bi, GenericsUtil.eliminateWildcards(bound, false));
+ } else {
+ parameters[i] = GenericsUtil.eliminateWildcards(bound, false);
+ }
+ }
+ }
+ return JavaPsiFacade.getElementFactory(psiClass.getProject()).createType(psiClass, parameters);
}
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 d57022d..0eaf3d8 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
@@ -15,54 +15,171 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.ConstraintFormula;
-import com.intellij.psi.impl.source.resolve.graphInference.constraints.SubtypingConstraint;
+import com.intellij.psi.impl.source.resolve.graphInference.constraints.StrictSubtypingConstraint;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeEqualityConstraint;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.util.Processor;
+import java.util.LinkedHashSet;
import java.util.List;
/**
* User: anna
*/
public class InferenceIncorporationPhase {
+ private static final Logger LOG = Logger.getInstance("#" + InferenceIncorporationPhase.class.getName());
private final InferenceSession mySession;
+ private PsiClassType myCapture;
public InferenceIncorporationPhase(InferenceSession session) {
mySession = session;
}
- public void incorporate() {
+ public void setCapture(PsiClassType capture) {
+ myCapture = capture;
+ }
+
+ public boolean incorporate() {
for (InferenceVariable inferenceVariable : mySession.getInferenceVariables()) {
if (inferenceVariable.getInstantiation() != PsiType.NULL) continue;
final List<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
final List<PsiType> upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER);
final List<PsiType> lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER);
- /*
- todo inference errors
- Infer infer = inferenceContext.infer();
- for (Type e : uv.getBounds(InferenceBound.EQ)) {
- if (e.containsAny(inferenceContext.inferenceVars())) continue;
- for (Type u : uv.getBounds(InferenceBound.UPPER)) {
- if (!isSubtype(e, inferenceContext.asFree(u), warn, infer)) {
- infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_UPPER);
- }
- }
- for (Type l : uv.getBounds(InferenceBound.LOWER)) {
- if (!isSubtype(inferenceContext.asFree(l), e, warn, infer)) {
- infer.reportBoundError(uv, BoundErrorKind.BAD_EQ_LOWER);
- }
- }
- }
- */
eqEq(eqBounds);
- upperLower(upperBounds, lowerBounds);
+ upDown(lowerBounds, upperBounds);
upDown(eqBounds, upperBounds);
upDown(lowerBounds, eqBounds);
+
+ upUp(upperBounds);
+
+ for (PsiType eqBound : eqBounds) {
+ if (mySession.isProperType(eqBound)) {
+ final PsiSubstitutor substitutor = PsiSubstitutor.EMPTY.put(inferenceVariable.getParameter(), eqBound);
+ for (PsiType upperBound : upperBounds) {
+ if (!mySession.isProperType(upperBound)) {
+ addConstraint(new StrictSubtypingConstraint(substitutor.substitute(upperBound), eqBound));
+ }
+ }
+
+ for (PsiType lowerBound : lowerBounds) {
+ if (!mySession.isProperType(lowerBound)) {
+ addConstraint(new StrictSubtypingConstraint(eqBound, substitutor.substitute(lowerBound)));
+ }
+ }
+
+ for (PsiType otherEqBound : eqBounds) {
+ if (eqBound != otherEqBound && !mySession.isProperType(otherEqBound)) {
+ addConstraint(new TypeEqualityConstraint(substitutor.substitute(otherEqBound), eqBound));
+ }
+ }
+ }
+ }
+
+ //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));
+ }
+ }
+ }
+ }
}
+
+ if (myCapture != null) {
+ final PsiClass gClass = myCapture.resolve();
+ LOG.assertTrue(gClass != null);
+ final PsiTypeParameter[] parameters = gClass.getTypeParameters();
+ PsiType[] typeArgs = myCapture.getParameters();
+ LOG.assertTrue(parameters.length == typeArgs.length);
+ for (int i = 0; i < typeArgs.length; i++) {
+ PsiType aType = typeArgs[i];
+ if (aType instanceof PsiCapturedWildcardType) {
+ aType = ((PsiCapturedWildcardType)aType).getWildcard();
+ }
+ final InferenceVariable inferenceVariable = mySession.getInferenceVariable(parameters[i]);
+ LOG.assertTrue(inferenceVariable != null);
+
+ final List<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
+ final List<PsiType> upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER);
+ final List<PsiType> lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER);
+
+ if (aType instanceof PsiWildcardType) {
+
+ for (PsiType eqBound : eqBounds) {
+ if (mySession.isProperType(eqBound)) return false;
+ }
+
+ final PsiClassType[] paramBounds = parameters[i].getExtendsListTypes();
+
+ if (!((PsiWildcardType)aType).isBounded()) {
+
+ for (PsiType upperBound : upperBounds) {
+ if (mySession.isProperType(upperBound)) {
+ for (PsiClassType paramBound : paramBounds) {
+ addConstraint(new StrictSubtypingConstraint(upperBound, paramBound));
+ }
+ }
+ }
+
+ for (PsiType lowerBound : lowerBounds) {
+ if (mySession.isProperType(lowerBound)) return false;
+ }
+
+ } else if (((PsiWildcardType)aType).isExtends()) {
+
+ final PsiType extendsBound = ((PsiWildcardType)aType).getExtendsBound();
+
+ for (PsiType upperBound : upperBounds) {
+ if (mySession.isProperType(upperBound)) {
+ if (paramBounds.length == 1 && paramBounds[0].equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || paramBounds.length == 0) {
+ addConstraint(new StrictSubtypingConstraint(upperBound, extendsBound));
+ } else if (extendsBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
+ for (PsiClassType paramBound : paramBounds) {
+ addConstraint(new StrictSubtypingConstraint(upperBound, paramBound));
+ }
+ }
+ }
+ }
+
+ for (PsiType lowerBound : lowerBounds) {
+ if (mySession.isProperType(lowerBound)) return false;
+ }
+
+ } else {
+ LOG.assertTrue(((PsiWildcardType)aType).isSuper());
+ final PsiType superBound = ((PsiWildcardType)aType).getSuperBound();
+
+ for (PsiType upperBound : upperBounds) {
+ if (mySession.isProperType(upperBound)) {
+ for (PsiClassType paramBound : paramBounds) {
+ addConstraint(new StrictSubtypingConstraint(paramBound, upperBound));
+ }
+ }
+ }
+
+ for (PsiType lowerBound : lowerBounds) {
+ if (mySession.isProperType(lowerBound)) {
+ addConstraint(new StrictSubtypingConstraint(lowerBound, superBound));
+ }
+ }
+ }
+ } else {
+ inferenceVariable.addBound(aType, InferenceBound.EQ);
+ }
+ }
+ }
+ return true;
}
boolean isFullyIncorporated() {
@@ -88,7 +205,6 @@
for (PsiType eqBound : eqBounds) {
final InferenceVariable inferenceVar = mySession.getInferenceVariable(eqBound);
if (inferenceVar != null) {
- //inferenceVar.addBound(inferenceVariable.qType, InferenceVariable.InferenceBound.EQ);
for (InferenceBound inferenceBound : InferenceBound.values()) {
for (PsiType bound : inferenceVariable.getBounds(inferenceBound)) {
if (mySession.getInferenceVariable(bound) != inferenceVar) {
@@ -121,12 +237,11 @@
for (PsiType upperBound : upperBounds) {
final InferenceVariable inferenceVar = mySession.getInferenceVariable(upperBound);
if (inferenceVar != null) {
- //todo inferenceVar.addBound(inferenceVariable.qType, inferenceBound);
+
for (PsiType lowerBound : lowerBounds) {
result |= inferenceVar.addBound(lowerBound, inferenceBound);
}
-
for (PsiType varUpperBound : inferenceVar.getBounds(oppositeBound)) {
result |= inferenceVariable.addBound(varUpperBound, oppositeBound);
}
@@ -139,28 +254,19 @@
* a = S & a <: T imply S <: T
* or
* a = S & T <: a imply T <: S
+ * or
+ * S <: a & a <: T imply S <: T
*/
private void upDown(List<PsiType> eqBounds, List<PsiType> upperBounds) {
for (PsiType upperBound : upperBounds) {
- if (upperBound == null) continue;
- for (PsiType eqBound : eqBounds) {
- if (!upperBound.equals(eqBound) && !upperBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
- addConstraint(new SubtypingConstraint(upperBound, eqBound, true));
- }
+ if (mySession.isProperType(upperBound)) {
+ continue;
}
- }
- }
-
- /**
- * S <: a & a <: T imply S <: T
- */
- private void upperLower(List<PsiType> upperBounds, List<PsiType> lowerBounds) {
- for (PsiType upperBound : upperBounds) {
- if (upperBound == null) continue;
- for (PsiType lowerBound : lowerBounds) {
- if (!upperBound.equals(lowerBound)) {
- addConstraint(new SubtypingConstraint(upperBound, lowerBound, true));
+ for (PsiType eqBound : eqBounds) {
+ if (mySession.isProperType(eqBound)) {
+ continue;
}
+ addConstraint(new StrictSubtypingConstraint(upperBound, eqBound));
}
}
}
@@ -171,15 +277,74 @@
private void eqEq(List<PsiType> eqBounds) {
for (int i = 0; i < eqBounds.size(); i++) {
PsiType sBound= eqBounds.get(i);
- if (sBound == null) continue;
+ if (mySession.isProperType(sBound)) {
+ continue;
+ }
for (int j = i + 1; j < eqBounds.size(); j++) {
final PsiType tBound = eqBounds.get(j);
- if (tBound == null) continue;
+ if (mySession.isProperType(tBound)) {
+ continue;
+ }
addConstraint(new TypeEqualityConstraint(tBound, sBound));
}
}
}
+
+ /**
+ * If two bounds have the form α <: S and α <: T, and if for some generic class or interface, G,
+ * there exists a supertype (4.10) of S of the form G<S1, ..., Sn> and a supertype of T of the form G<T1, ..., Tn>,
+ * then for all i, 1 ≤ i ≤ n, if Si and Ti are types (not wildcards), the constraint ⟨Si = Ti⟩ is implied.
+ */
+ private boolean upUp(List<PsiType> upperBounds) {
+ return findParameterizationOfTheSameGenericClass(upperBounds, new Processor<Pair<PsiType, PsiType>>() {
+ @Override
+ public boolean process(Pair<PsiType, PsiType> pair) {
+ final PsiType sType = pair.first;
+ final PsiType tType = pair.second;
+ if (!mySession.isProperType(sType) && !mySession.isProperType(tType)) {
+ if (!(sType instanceof PsiWildcardType) && !(tType instanceof PsiWildcardType) && sType != null && tType != null) {
+ addConstraint(new TypeEqualityConstraint(sType, tType));
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ public static boolean findParameterizationOfTheSameGenericClass(List<PsiType> upperBounds, Processor<Pair<PsiType, PsiType>> processor) {
+ for (int i = 0; i < upperBounds.size(); i++) {
+ final PsiType sBound = upperBounds.get(i);
+ final PsiClass sClass = PsiUtil.resolveClassInClassTypeOnly(sBound);
+ if (sClass == null) continue;
+ final LinkedHashSet<PsiClass> superClasses = InheritanceUtil.getSuperClasses(sClass);
+ superClasses.add(sClass);
+ for (int j = i + 1; j < upperBounds.size(); j++) {
+ final PsiType tBound = upperBounds.get(j);
+ final PsiClass tClass = PsiUtil.resolveClassInClassTypeOnly(tBound);
+ if (tClass != null) {
+
+ final LinkedHashSet<PsiClass> tSupers = InheritanceUtil.getSuperClasses(tClass);
+ tSupers.add(tClass);
+ tSupers.retainAll(superClasses);
+
+ for (PsiClass gClass : tSupers) {
+ final PsiSubstitutor sSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)sBound);
+ final PsiSubstitutor tSubstitutor = TypeConversionUtil.getSuperClassSubstitutor(gClass, (PsiClassType)tBound);
+ for (PsiTypeParameter typeParameter : gClass.getTypeParameters()) {
+ final PsiType sType = sSubstitutor.substitute(typeParameter);
+ final PsiType tType = tSubstitutor.substitute(typeParameter);
+ if (!processor.process(Pair.create(sType, tType))) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
private void addConstraint(ConstraintFormula constraint) {
mySession.addConstraint(constraint);
}
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 b404ab4..4b74ef2 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
@@ -27,12 +27,15 @@
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.MethodProcessorSetupFailedException;
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;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.ArrayUtilRt;
+import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,17 +58,17 @@
private final InferenceIncorporationPhase myIncorporationPhase = new InferenceIncorporationPhase(this);
- public InferenceSession(PsiSubstitutor siteSubstitutor) {
- mySiteSubstitutor = siteSubstitutor;
- }
+ private final PsiElement myContext;
public InferenceSession(PsiTypeParameter[] typeParams,
PsiType[] leftTypes,
PsiType[] rightTypes,
PsiSubstitutor siteSubstitutor,
- PsiManager manager) {
+ PsiManager manager,
+ PsiElement context) {
myManager = manager;
mySiteSubstitutor = siteSubstitutor;
+ myContext = context;
initBounds(typeParams);
@@ -80,9 +83,11 @@
public InferenceSession(PsiTypeParameter[] typeParams,
PsiSubstitutor siteSubstitutor,
- PsiManager manager) {
+ PsiManager manager,
+ PsiElement context) {
myManager = manager;
mySiteSubstitutor = siteSubstitutor;
+ myContext = context;
initBounds(typeParams);
}
@@ -194,9 +199,21 @@
@Nullable PsiExpression[] args,
@Nullable PsiElement parent,
ParameterTypeInferencePolicy policy) {
- boolean doesNotContainFalseBound = repeatInferencePhases(parameters == null);
+ return infer(parameters, args, parent, false, policy);
+ }
- resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, false);
+ @NotNull
+ public PsiSubstitutor infer(@Nullable PsiParameter[] parameters,
+ @Nullable PsiExpression[] args,
+ @Nullable PsiElement parent,
+ boolean acceptNonPertinentArgs,
+ ParameterTypeInferencePolicy policy) {
+
+ if (!repeatInferencePhases(parameters == null || !policy.allowPostponeInference())) {
+ return prepareSubstitution();
+ }
+
+ resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, !policy.allowPostponeInference());
final Pair<PsiMethod, PsiCallExpression> pair = getPair(parent);
if (pair != null) {
@@ -204,16 +221,18 @@
for (InferenceVariable inferenceVariable : myInferenceVariables.values()) {
inferenceVariable.ignoreInstantiation();
}
- doesNotContainFalseBound = repeatInferencePhases(true);
+ if (!repeatInferencePhases(true)) {
+ return prepareSubstitution();
+ }
- PsiSubstitutor substitutor = resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, false);
+ PsiSubstitutor substitutor = resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, !policy.allowPostponeInference());
LOG.assertTrue(parent != null);
PsiExpressionList argumentList = ((PsiCallExpression)parent).getArgumentList();
LOG.assertTrue(argumentList != null);
MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
}
- if (parameters != null && args != null) {
+ if (parameters != null && args != null && (acceptNonPertinentArgs || pair != null)) {
final Set<ConstraintFormula> additionalConstraints = new HashSet<ConstraintFormula>();
if (parameters.length > 0) {
for (int i = 0; i < args.length; i++) {
@@ -231,7 +250,9 @@
for (InferenceVariable inferenceVariable : myInferenceVariables.values()) {
inferenceVariable.ignoreInstantiation();
}
- doesNotContainFalseBound = proceedWithAdditionalConstraints(additionalConstraints);
+ if (!proceedWithAdditionalConstraints(additionalConstraints)) {
+ return prepareSubstitution();
+ }
}
}
@@ -240,6 +261,10 @@
}
mySiteSubstitutor = resolveBounds(myInferenceVariables.values(), mySiteSubstitutor, !policy.allowPostponeInference());
+ return prepareSubstitution();
+ }
+
+ private PsiSubstitutor prepareSubstitution() {
for (InferenceVariable inferenceVariable : myInferenceVariables.values()) {
final PsiTypeParameter typeParameter = inferenceVariable.getParameter();
PsiType instantiation = inferenceVariable.getInstantiation();
@@ -252,6 +277,17 @@
return mySiteSubstitutor;
}
+ private boolean isInsideRecursiveCall(PsiTypeParameter parameter) {
+ final PsiTypeParameterListOwner parameterOwner = parameter.getOwner();
+ if (myContext != null && PsiTreeUtil.isAncestor(parameterOwner, myContext, true)) {
+ final PsiModifierListOwner staticContainer = PsiUtil.getEnclosingStaticElement(myContext, null);
+ if (staticContainer == null || PsiTreeUtil.isAncestor(staticContainer, parameterOwner, false)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void initBounds(PsiTypeParameter... typeParameters) {
for (PsiTypeParameter parameter : typeParameters) {
if (myInferenceVariables.containsKey(parameter)) continue;
@@ -274,32 +310,124 @@
}
public void addCapturedVariable(PsiTypeParameter param) {
- if (myInferenceVariables.containsKey(param)) return; //same method call
initBounds(param);
}
private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method) ||
context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) {
- final PsiType returnType = method.getReturnType();
+ 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, true, new Computable<PsiType>() {
+ final PsiType finalReturnType = returnType;
+ targetType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(context, false, new Computable<PsiType>() {
@Override
public PsiType compute() {
- return getTargetType(context);
+ return getTargetType(context, finalReturnType);
}
});
}
if (targetType != null) {
- myConstraints.add(new TypeCompatibilityConstraint(myErased ? TypeConversionUtil.erasure(targetType) : GenericsUtil.eliminateWildcards(targetType, false), PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context)));
+ registerConstraints(returnType, targetType);
}
}
}
+
+ for (PsiClassType thrownType : method.getThrowsList().getReferencedTypes()) {
+ final InferenceVariable variable = getInferenceVariable(thrownType);
+ if (variable != null) {
+ variable.setThrownBound();
+ }
+ }
}
- private PsiType getTargetType(final PsiExpression context) {
+ public void registerConstraints(PsiType returnType, PsiType targetType) {
+ final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
+ if (inferenceVariable != null) {
+ resolveBounds(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true);
+ myConstraints.add(new TypeCompatibilityConstraint(inferenceVariable.getInstantiation(), returnType));
+ }
+ else {
+ if (targetType instanceof PsiClassType && ((PsiClassType)targetType).isRaw()) {
+ setErased();
+ }
+ myConstraints.add(new TypeCompatibilityConstraint(myErased ? TypeConversionUtil.erasure(targetType) : GenericsUtil.eliminateWildcards(
+ targetType, false), returnType));
+ }
+ }
+
+ private InferenceVariable shouldResolveAndInstantiate(PsiType returnType, PsiType targetType) {
+ final InferenceVariable inferenceVariable = getInferenceVariable(returnType);
+ if (inferenceVariable != null) {
+ if (targetType instanceof PsiPrimitiveType && hasPrimitiveWrapperBound(inferenceVariable)) {
+ return inferenceVariable;
+ }
+ if (targetType instanceof PsiClassType) {
+ if (myErased ||
+ hasUncheckedBounds(inferenceVariable, (PsiClassType)targetType) ||
+ hasWildcardParameterization(inferenceVariable, (PsiClassType)targetType)) {
+ return inferenceVariable;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean hasPrimitiveWrapperBound(InferenceVariable inferenceVariable) {
+ final InferenceBound[] boundTypes = {InferenceBound.UPPER, InferenceBound.LOWER};
+ for (InferenceBound inferenceBound : boundTypes) {
+ final List<PsiType> bounds = inferenceVariable.getBounds(inferenceBound);
+ for (PsiType bound : bounds) {
+ if (PsiPrimitiveType.getUnboxedType(bound) != null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasUncheckedBounds(InferenceVariable inferenceVariable, PsiClassType targetType) {
+ if (!targetType.isRaw()) {
+ final InferenceBound[] boundTypes = {InferenceBound.EQ, InferenceBound.LOWER};
+ for (InferenceBound inferenceBound : boundTypes) {
+ final List<PsiType> bounds = inferenceVariable.getBounds(inferenceBound);
+ for (PsiType bound : bounds) {
+ if (TypeCompatibilityConstraint.isUncheckedConversion(targetType, bound)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static boolean hasWildcardParameterization(InferenceVariable inferenceVariable, PsiClassType targetType) {
+ if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(targetType)) {
+ final List<PsiType> bounds = inferenceVariable.getBounds(InferenceBound.LOWER);
+ final Processor<Pair<PsiType, PsiType>> differentParameterizationProcessor = new Processor<Pair<PsiType, PsiType>>() {
+ @Override
+ public boolean process(Pair<PsiType, PsiType> pair) {
+ return pair.first == null || pair.second == null || pair.first.equals(pair.second);
+ }
+ };
+ if (InferenceIncorporationPhase.findParameterizationOfTheSameGenericClass(bounds, differentParameterizationProcessor)) return true;
+ final List<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
+ for (PsiType lowBound : bounds) {
+ if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(lowBound)) {
+ for (PsiType bound : eqBounds) {
+ if (lowBound.equals(bound)) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private PsiType getTargetType(final PsiExpression context, PsiType returnType) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
if (parent instanceof PsiExpressionList) {
final PsiElement gParent = parent.getParent();
@@ -309,13 +437,13 @@
final Pair<PsiMethod, PsiSubstitutor> pair = MethodCandidateInfo.getCurrentMethod(argumentList);
final JavaResolveResult resolveResult;
if (pair == null) {
- final MethodCandidatesProcessor processor = new MethodCandidatesProcessor(gParent, context.getContainingFile()) {
+ final MethodCandidatesProcessor processor = new MethodResolverProcessor((PsiCallExpression)gParent, argumentList, context.getContainingFile()) {
@Override
protected PsiType[] getExpressionTypes(PsiExpressionList argumentList) {
if (argumentList != null) {
final PsiExpression[] expressions = argumentList.getExpressions();
final int idx = LambdaUtil.getLambdaIdx(argumentList, context);
- final PsiType[] types = new PsiType[expressions.length];
+ final PsiType[] types = PsiType.createArray(expressions.length);
for (int i = 0; i < expressions.length; i++) {
if (i != idx) {
types[i] = expressions[i].getType();
@@ -338,13 +466,7 @@
return null;
}
final JavaResolveResult[] results = processor.getResult();
- for (JavaResolveResult result : results) {
- final PsiType type = getTypeByMethod(context, argumentList, null, result, result.getElement());
- if (type != null) {
- return type;
- }
- }
- return null;
+ return results.length == 1 ? getTypeByMethod(context, argumentList, null, results[0], results[0].getElement()) : null;
}
return getTypeByMethod(context, argumentList, pair, null, pair.first);
}
@@ -352,7 +474,7 @@
} else if (parent instanceof PsiConditionalExpression) {
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent((PsiExpression)parent);
if (targetType == null) {
- targetType = getTargetType((PsiExpression)parent);
+ targetType = getTargetType((PsiExpression)parent, returnType);
}
return targetType;
}
@@ -382,9 +504,9 @@
}
else {
args[i] = null;
- final PsiTypeParameter[] typeParameters = ((PsiMethod)parentMethod).getTypeParameters();
- initBounds(typeParameters);
final PsiSubstitutor substitutor = ((MethodCandidateInfo)result).inferSubstitutorFromArgs(LiftParameterTypeInferencePolicy.INSTANCE, args);
+ final Set<PsiTypeParameter> typeParameters = substitutor.getSubstitutionMap().keySet();
+ initBounds(typeParameters.toArray(new PsiTypeParameter[typeParameters.size()]));
return getParameterType(parameters, args, i, substitutor);
}
}
@@ -447,14 +569,23 @@
return dependencies != null ? !dependencies.isEmpty() : isProper;
}
- private boolean repeatInferencePhases(boolean incorporate) {
+ public boolean repeatInferencePhases(boolean incorporate) {
+ do {
+ if (!reduceConstraints()) {
+ //inference error occurred
+ return false;
+ }
+ } while (myConstraintIdx < myConstraints.size());
+
do {
if (!reduceConstraints()) {
//inference error occurred
return false;
}
if (incorporate) {
- myIncorporationPhase.incorporate();
+ if (!myIncorporationPhase.incorporate()) {
+ return false;
+ }
}
} while (incorporate && !myIncorporationPhase.isFullyIncorporated() || myConstraintIdx < myConstraints.size());
@@ -476,14 +607,20 @@
return true;
}
- private PsiSubstitutor resolveBounds(final Collection<InferenceVariable> inferenceVariables, PsiSubstitutor substitutor, boolean acceptInitialUpperBound) {
+ protected PsiSubstitutor resolveBounds(boolean acceptInitialUpperBound) {
+ return resolveBounds(getInferenceVariables(), mySiteSubstitutor, acceptInitialUpperBound);
+ }
+
+ private PsiSubstitutor resolveBounds(final Collection<InferenceVariable> inferenceVariables,
+ PsiSubstitutor substitutor,
+ boolean acceptInitialUpperBound) {
final List<List<InferenceVariable>> independentVars = InferenceVariablesOrder.resolveOrder(inferenceVariables, this);
for (List<InferenceVariable> variables : independentVars) {
for (InferenceVariable inferenceVariable : variables) {
- if (inferenceVariable.getInstantiation() != PsiType.NULL) continue;
final PsiTypeParameter typeParameter = inferenceVariable.getParameter();
try {
+ if (inferenceVariable.getInstantiation() != PsiType.NULL) continue;
final List<PsiType> eqBounds = inferenceVariable.getBounds(InferenceBound.EQ);
final List<PsiType> lowerBounds = inferenceVariable.getBounds(InferenceBound.LOWER);
final List<PsiType> upperBounds = inferenceVariable.getBounds(InferenceBound.UPPER);
@@ -494,8 +631,9 @@
PsiType bound = null;
if (eqBounds.size() > 1) {
for (Iterator<PsiType> iterator = eqBounds.iterator(); iterator.hasNext(); ) {
- PsiType eqBound = acceptBoundsWithRecursiveDependencies(inferenceVariable, iterator.next(), substitutor);
- if (PsiUtil.resolveClassInType(eqBound) == typeParameter || !(bound instanceof PsiCapturedWildcardType) && Comparing.equal(bound, eqBound)) {
+ final PsiType unsubstBound = iterator.next();
+ PsiType eqBound = substituteNonProperBound(unsubstBound, substitutor);
+ if (PsiUtil.resolveClassInType(eqBound) == typeParameter || !(bound instanceof PsiCapturedWildcardType && bound.equals(unsubstBound)) && Comparing.equal(bound, eqBound)) {
iterator.remove();
} else if (bound == null) {
bound = eqBound;
@@ -503,13 +641,13 @@
}
if (eqBounds.size() > 1) continue;
}
- bound = eqBounds.isEmpty() ? null : acceptBoundsWithRecursiveDependencies(inferenceVariable, eqBounds.get(0), substitutor);
+ bound = eqBounds.isEmpty() ? null : substituteNonProperBound(eqBounds.get(0), substitutor);
if (bound != null) {
inferenceVariable.setInstantiation(bound);
} else {
PsiType lub = null;
for (PsiType lowerBound : lowerBounds) {
- lowerBound = acceptBoundsWithRecursiveDependencies(inferenceVariable, lowerBound, substitutor);
+ lowerBound = substituteNonProperBound(lowerBound, substitutor);
if (isProperType(lowerBound)) {
if (lub == null) {
lub = lowerBound;
@@ -525,13 +663,13 @@
else {
boolean inferred = false;
PsiType glb = null;
- if (isThrowable(upperBounds)) {
+ if (inferenceVariable.isThrownBound() && isThrowable(upperBounds)) {
glb = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject()));
inferred = true;
} else {
int boundCandidatesNumber = 0;
for (PsiType upperBound : upperBounds) {
- PsiType substitutedBound = acceptBoundsWithRecursiveDependencies(inferenceVariable, upperBound, substitutor);
+ PsiType substitutedBound = substituteNonProperBound(upperBound, substitutor);
if (isProperType(substitutedBound)) {
boundCandidatesNumber++;
if (!upperBound.equals(substitutedBound)) {
@@ -549,7 +687,7 @@
inferred = boundCandidatesNumber > typeParameter.getExtendsListTypes().length && (typeParameter.getExtendsListTypes().length > 0 || boundCandidatesNumber > 1);
}
}
- if (glb != null && (acceptInitialUpperBound || inferred)) {
+ if (glb != null && (acceptInitialUpperBound && !isInsideRecursiveCall(typeParameter) || inferred)) {
inferenceVariable.setInstantiation(glb);
}
}
@@ -580,14 +718,8 @@
return commonThrowable;
}
- private PsiType acceptBoundsWithRecursiveDependencies(InferenceVariable inferenceVariable, PsiType bound, PsiSubstitutor substitutor) {
- final HashSet<InferenceVariable> dependencies = new HashSet<InferenceVariable>();
- final boolean collectDependencies = collectDependencies(bound, dependencies);
- if (collectDependencies) {
- final PsiSubstitutor subst = !dependencies.contains(inferenceVariable) ? substitutor.put(inferenceVariable.getParameter(), null) : substitutor;
- return subst.substitute(bound);
- }
- return bound;
+ private PsiType substituteNonProperBound(PsiType bound, PsiSubstitutor substitutor) {
+ return isProperType(bound) ? bound : substitutor.substitute(bound);
}
public PsiManager getManager() {
@@ -612,59 +744,67 @@
return myInferenceVariables.keySet();
}
- public void addVariable(PsiTypeParameter typeParameter, final PsiType parameter) {
- InferenceVariable variable = new InferenceVariable(typeParameter);
- if (parameter instanceof PsiWildcardType) {
- PsiType bound = ((PsiWildcardType)parameter).getBound();
- if (bound != null) {
- variable.addBound(bound, ((PsiWildcardType)parameter).isExtends() ? InferenceBound.UPPER : InferenceBound.LOWER);
- } else {
- variable.addBound(PsiType.getJavaLangObject(typeParameter.getManager(), typeParameter.getResolveScope()), InferenceBound.UPPER);
- }
- } else {
- variable.addBound(parameter, InferenceBound.EQ);
- }
- myInferenceVariables.put(typeParameter, variable);
- }
-
private boolean proceedWithAdditionalConstraints(Set<ConstraintFormula> additionalConstraints) {
while (!additionalConstraints.isEmpty()) {
- final Set<InferenceVariable> outputVariables = new HashSet<InferenceVariable>();
- for (ConstraintFormula constraint : additionalConstraints) {
- if (constraint instanceof InputOutputConstraintFormula) {
- final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
- final Set<InferenceVariable> outputVars = ((InputOutputConstraintFormula)constraint).getOutputVariables(inputVariables, this);
- if (outputVars != null) {
- outputVariables.addAll(outputVars);
- }
+ final Set<InferenceVariable> varsToResolve = new HashSet<InferenceVariable>();
+
+ final Set<ConstraintFormula> subset = buildSubset(additionalConstraints, varsToResolve);
+
+ PsiSubstitutor substitutor = resolveBounds(varsToResolve, mySiteSubstitutor, true);
+
+ if (myContext instanceof PsiCallExpression) {
+ PsiExpressionList argumentList = ((PsiCallExpression)myContext).getArgumentList();
+ LOG.assertTrue(argumentList != null);
+ MethodCandidateInfo.updateSubstitutor(argumentList, substitutor);
+ }
+
+ for (ConstraintFormula additionalConstraint : subset) {
+ additionalConstraint.apply(substitutor);
+ }
+
+ myConstraints.addAll(subset);
+ if (!repeatInferencePhases(true)) {
+ return false;
+ }
+
+ }
+ return true;
+ }
+
+ private Set<ConstraintFormula> buildSubset(final Set<ConstraintFormula> additionalConstraints,
+ final Set<InferenceVariable> varsToResolve) {
+
+ final Set<ConstraintFormula> subset = new HashSet<ConstraintFormula>();
+ final Set<InferenceVariable> outputVariables = new HashSet<InferenceVariable>();
+ for (ConstraintFormula constraint : additionalConstraints) {
+ if (constraint instanceof InputOutputConstraintFormula) {
+ final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
+ final Set<InferenceVariable> outputVars = ((InputOutputConstraintFormula)constraint).getOutputVariables(inputVariables, this);
+ if (outputVars != null) {
+ outputVariables.addAll(outputVars);
}
}
- Set<ConstraintFormula> subset = new HashSet<ConstraintFormula>();
- final Set<InferenceVariable> varsToResolve = new HashSet<InferenceVariable>();
- for (ConstraintFormula constraint : additionalConstraints) {
- if (constraint instanceof InputOutputConstraintFormula) {
- final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
- if (inputVariables != null) {
- boolean dependsOnOutput = false;
- for (InferenceVariable inputVariable : inputVariables) {
- final Set<InferenceVariable> dependencies = inputVariable.getDependencies(this);
- dependencies.add(inputVariable);
- dependencies.retainAll(outputVariables);
- if (!dependencies.isEmpty()) {
- dependsOnOutput = true;
- break;
- }
- }
- if (!dependsOnOutput) {
- subset.add(constraint);
- varsToResolve.addAll(inputVariables);
+ }
+
+ for (ConstraintFormula constraint : additionalConstraints) {
+ if (constraint instanceof InputOutputConstraintFormula) {
+ final Set<InferenceVariable> inputVariables = ((InputOutputConstraintFormula)constraint).getInputVariables(this);
+ if (inputVariables != null) {
+ boolean dependsOnOutput = false;
+ for (InferenceVariable inputVariable : inputVariables) {
+ final Set<InferenceVariable> dependencies = inputVariable.getDependencies(this);
+ dependencies.add(inputVariable);
+ dependencies.retainAll(outputVariables);
+ if (!dependencies.isEmpty()) {
+ dependsOnOutput = true;
+ break;
}
}
- else {
+ if (!dependsOnOutput) {
subset.add(constraint);
- Set<InferenceVariable> outputVars = ((InputOutputConstraintFormula)constraint).getOutputVariables(null, this);
- if (outputVars != null) {
- varsToResolve.addAll(outputVars);
+ for (InferenceVariable variable : inputVariables) {
+ varsToResolve.addAll(variable.getDependencies(this));
+ varsToResolve.add(variable);
}
}
}
@@ -672,26 +812,246 @@
subset.add(constraint);
}
}
- if (subset.isEmpty()) {
- subset = Collections.singleton(additionalConstraints.iterator().next()); //todo choose one constraint
+ else {
+ subset.add(constraint);
}
- additionalConstraints.removeAll(subset);
+ }
+ if (subset.isEmpty()) {
+ subset.add(additionalConstraints.iterator().next()); //todo choose one constraint
+ }
- myConstraints.addAll(subset);
- if (!repeatInferencePhases(true)) {
+ additionalConstraints.removeAll(subset);
+ return subset;
+ }
+
+ public void setErased() {
+ myErased = true;
+ }
+
+ public InferenceVariable getInferenceVariable(PsiTypeParameter parameter) {
+ return myInferenceVariables.get(parameter);
+ }
+
+ /**
+ * 18.5.4 More Specific Method Inference
+ */
+ public static boolean isMoreSpecific(PsiMethod m1,
+ PsiMethod m2,
+ PsiSubstitutor siteSubstitutor2,
+ PsiExpression[] args,
+ PsiElement context,
+ boolean varargs) {
+ final PsiTypeParameter[] typeParameters = m2.getTypeParameters();
+
+ final InferenceSession session = new InferenceSession(typeParameters, siteSubstitutor2, m2.getManager(), context);
+
+ final PsiParameter[] parameters1 = m1.getParameterList().getParameters();
+ final PsiParameter[] parameters2 = m2.getParameterList().getParameters();
+ LOG.assertTrue(parameters1.length == parameters2.length);
+
+ final int paramsLength = !varargs ? parameters1.length : parameters1.length - 1;
+ for (int i = 0; i < paramsLength; i++) {
+ PsiType sType = siteSubstitutor2.substitute(parameters1[i].getType());
+ PsiType tType = siteSubstitutor2.substitute(parameters2[i].getType());
+ if (session.isProperType(sType) && session.isProperType(tType)) {
+ if (!TypeConversionUtil.isAssignable(tType, sType)) {
+ return false;
+ }
+ continue;
+ }
+ if (LambdaUtil.isFunctionalType(sType) && LambdaUtil.isFunctionalType(tType) && !relates(sType, tType)) {
+ if (!isFunctionalTypeMoreSpecific(sType, tType, session, args)) {
+ return false;
+ }
+ } else {
+ session.addConstraint(new StrictSubtypingConstraint(tType, sType));
+ }
+ }
+
+ if (varargs) {
+ PsiType sType = siteSubstitutor2.substitute(parameters1[paramsLength].getType());
+ PsiType tType = siteSubstitutor2.substitute(parameters2[paramsLength].getType());
+ session.addConstraint(new StrictSubtypingConstraint(tType, sType));
+ }
+
+ return session.repeatInferencePhases(true);
+ }
+
+ /**
+ * 15.12.2.5 Choosing the Most Specific Method
+ * "a functional interface type S is more specific than a functional interface type T for an expression exp" part
+ */
+ public static boolean isFunctionalTypeMoreSpecificOnExpression(PsiType sType,
+ PsiType tType,
+ PsiExpression arg) {
+ return isFunctionalTypeMoreSpecific(sType, tType, null, arg);
+ }
+
+ private static boolean isFunctionalTypeMoreSpecific(PsiType sType,
+ PsiType tType,
+ @Nullable InferenceSession session,
+ PsiExpression... args) {
+ final PsiClassType.ClassResolveResult sResult = PsiUtil.resolveGenericsClassInType(sType);
+ final PsiMethod sInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(sResult); //todo capture of Si
+ LOG.assertTrue(sInterfaceMethod != null);
+ final PsiSubstitutor sSubstitutor = LambdaUtil.getSubstitutor(sInterfaceMethod, sResult);
+
+ final PsiClassType.ClassResolveResult tResult = PsiUtil.resolveGenericsClassInType(tType);
+ final PsiMethod tInterfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(tResult);
+ LOG.assertTrue(tInterfaceMethod != null);
+ final PsiSubstitutor tSubstitutor = LambdaUtil.getSubstitutor(tInterfaceMethod, tResult);
+
+ for (PsiExpression arg : args) {
+ if (!argConstraints(arg, session, sInterfaceMethod, sSubstitutor, tInterfaceMethod, tSubstitutor)) {
return false;
}
-
- PsiSubstitutor substitutor = resolveBounds(varsToResolve, mySiteSubstitutor, false);
-
- for (ConstraintFormula additionalConstraint : additionalConstraints) {
- additionalConstraint.apply(substitutor);
- }
}
return true;
}
- public void setErased() {
- myErased = true;
+ protected static boolean argConstraints(PsiExpression arg,
+ @Nullable InferenceSession session,
+ PsiMethod sInterfaceMethod,
+ PsiSubstitutor sSubstitutor,
+ PsiMethod tInterfaceMethod,
+ PsiSubstitutor tSubstitutor) {
+ if (arg instanceof PsiLambdaExpression && ((PsiLambdaExpression)arg).hasFormalParameterTypes()) {
+ final PsiType sReturnType = sSubstitutor.substitute(sInterfaceMethod.getReturnType());
+ final PsiType tReturnType = tSubstitutor.substitute(tInterfaceMethod.getReturnType());
+
+ if (tReturnType == PsiType.VOID) {
+ return true;
+ }
+
+ if (sReturnType == PsiType.VOID && session != null) {
+ return false;
+ }
+
+ if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) &&
+ !TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(sReturnType), TypeConversionUtil.erasure(tReturnType)) &&
+ !TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(tReturnType), TypeConversionUtil.erasure(sReturnType))) {
+
+ //Otherwise, if R1 and R2 are functional interface types, and neither interface is a subinterface of the other,
+ //then these rules are applied recursively to R1 and R2, for each result expression in expi.
+ final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)arg);
+ if (!isFunctionalTypeMoreSpecific(sReturnType, tReturnType, session, returnExpressions.toArray(new PsiExpression[returnExpressions.size()]))) {
+ return false;
+ }
+ } else {
+ final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType;
+ final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType;
+ if (sPrimitive ^ tPrimitive) {
+ for (PsiExpression returnExpression : LambdaUtil.getReturnExpressions((PsiLambdaExpression)arg)) {
+ if (!PsiPolyExpressionUtil.isPolyExpression(returnExpression)) {
+ final PsiType returnExpressionType = returnExpression.getType();
+ if (sPrimitive) {
+ if (!(returnExpressionType instanceof PsiPrimitiveType)) {
+ return false;
+ }
+ } else {
+ if (!(returnExpressionType instanceof PsiClassType)) {
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+ if (session != null) {
+ session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType));
+ return true;
+ } else {
+ return TypeConversionUtil.isAssignable(sReturnType, tReturnType);
+ }
+ }
+ }
+
+ if (arg instanceof PsiMethodReferenceExpression && ((PsiMethodReferenceExpression)arg).isExact()) {
+ final PsiParameter[] sParameters = sInterfaceMethod.getParameterList().getParameters();
+ final PsiParameter[] tParameters = tInterfaceMethod.getParameterList().getParameters();
+ LOG.assertTrue(sParameters.length == tParameters.length);
+ if (session != null) {
+ for (int i = 0; i < tParameters.length; i++) {
+ session.addConstraint(new TypeEqualityConstraint(tSubstitutor.substitute(tParameters[i].getType()),
+ sSubstitutor.substitute(sParameters[i].getType())));
+ }
+ }
+ final PsiType sReturnType = sSubstitutor.substitute(sInterfaceMethod.getReturnType());
+ final PsiType tReturnType = tSubstitutor.substitute(tInterfaceMethod.getReturnType());
+ if (tReturnType == PsiType.VOID) {
+ return true;
+ }
+
+ if (sReturnType == PsiType.VOID && session != null) {
+ return false;
+ }
+
+ final boolean sPrimitive = sReturnType instanceof PsiPrimitiveType;
+ final boolean tPrimitive = tReturnType instanceof PsiPrimitiveType;
+
+ if (sPrimitive ^ tPrimitive) {
+ final PsiMember member = ((PsiMethodReferenceExpression)arg).getPotentiallyApplicableMember();
+ LOG.assertTrue(member != null);
+ if (member instanceof PsiMethod) {
+ final PsiType methodReturnType = ((PsiMethod)member).getReturnType();
+ if (sPrimitive && methodReturnType instanceof PsiPrimitiveType ||
+ tPrimitive && methodReturnType instanceof PsiClassType) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (session != null) {
+ session.addConstraint(new StrictSubtypingConstraint(tReturnType, sReturnType));
+ return true;
+ } else {
+ return TypeConversionUtil.isAssignable(sReturnType, tReturnType);
+ }
+ }
+
+ if (arg instanceof PsiParenthesizedExpression) {
+ return argConstraints(((PsiParenthesizedExpression)arg).getExpression(), session, sInterfaceMethod, sSubstitutor, tInterfaceMethod, tSubstitutor);
+ }
+
+ if (arg instanceof PsiConditionalExpression) {
+ final PsiExpression thenExpression = ((PsiConditionalExpression)arg).getThenExpression();
+ final PsiExpression elseExpression = ((PsiConditionalExpression)arg).getElseExpression();
+ return argConstraints(thenExpression, session, sInterfaceMethod, sSubstitutor, tInterfaceMethod, tSubstitutor) &&
+ argConstraints(elseExpression, session, sInterfaceMethod, sSubstitutor, tInterfaceMethod, tSubstitutor);
+ }
+ return false;
+ }
+
+ /**
+ * if Si is a functional interface type and Ti is a parameterization of functional interface, I, and none of the following is true:
+
+ * Si is a superinterface of I, or a parameterization of a superinterface of I.
+ * Si is subinterface of I, or a parameterization of a subinterface of I.
+ * Si is an intersection type and each element of the intersection is a superinterface of I, or a parameterization of a superinterface of I.
+ * Si is an intersection type and some element of the intersection is a subinterface of I, or a parameterization of a subinterface of I.
+ */
+ private static boolean relates(PsiType sType, PsiType tType) {
+ final PsiType erasedType = TypeConversionUtil.erasure(tType);
+ LOG.assertTrue(erasedType != null);
+ if (sType instanceof PsiIntersectionType) {
+ boolean superRelation = true;
+ boolean subRelation = false;
+ for (PsiType sConjunct : ((PsiIntersectionType)sType).getConjuncts()) {
+ final PsiType sConjunctErasure = TypeConversionUtil.erasure(sConjunct);
+ if (sConjunctErasure != null) {
+ superRelation &= TypeConversionUtil.isAssignable(sConjunctErasure, erasedType);
+ subRelation |= TypeConversionUtil.isAssignable(erasedType, sConjunctErasure);
+ }
+ }
+ return superRelation || subRelation;
+ }
+ if (sType instanceof PsiClassType) {
+ final PsiType sTypeErasure = TypeConversionUtil.erasure(sType);
+ if (sTypeErasure != null) {
+ return TypeConversionUtil.isAssignable(sTypeErasure, erasedType) || TypeConversionUtil.isAssignable(erasedType, sTypeErasure);
+ }
+ }
+ return false;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
index 80db95a..c3ef4b6 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/InferenceVariable.java
@@ -27,6 +27,7 @@
return myParameter;
}
+ private boolean myThrownBound = false;
private final Map<InferenceBound, List<PsiType>> myBounds = new HashMap<InferenceBound, List<PsiType>>();
private final PsiTypeParameter myParameter;
@@ -47,6 +48,9 @@
}
public boolean addBound(PsiType classType, InferenceBound inferenceBound) {
+ if (inferenceBound == InferenceBound.EQ && classType instanceof PsiClassType && ((PsiClassType)classType).resolve() == myParameter) {
+ return false;
+ }
List<PsiType> list = myBounds.get(inferenceBound);
if (list == null) {
list = new ArrayList<PsiType>();
@@ -74,4 +78,25 @@
}
return dependencies;
}
+
+ public boolean isThrownBound() {
+ return myThrownBound;
+ }
+
+ public void setThrownBound() {
+ myThrownBound = true;
+ }
+
+ public InferenceVariable copy() {
+ final InferenceVariable variable = new InferenceVariable(myParameter);
+ for (InferenceBound bound : InferenceBound.values()) {
+ for (PsiType type : getBounds(bound)) {
+ variable.addBound(type, bound);
+ }
+ }
+ if (myThrownBound) {
+ variable.setThrownBound();
+ }
+ return variable;
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java
index 8b36b35..094ef28 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/PsiGraphInferenceHelper.java
@@ -38,7 +38,7 @@
@NotNull PsiSubstitutor partialSubstitutor,
@Nullable PsiElement parent,
@NotNull ParameterTypeInferencePolicy policy) {
- final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParameter}, partialSubstitutor, myManager);
+ final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParameter}, partialSubstitutor, myManager, parent);
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
return inferenceSession.infer(parameters, arguments, parent, policy).substitute(typeParameter);
}
@@ -53,7 +53,7 @@
@NotNull ParameterTypeInferencePolicy policy,
@NotNull LanguageLevel languageLevel) {
if (typeParameters.length == 0) return partialSubstitutor;
- final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, myManager);
+ final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, myManager, parent);
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
return inferenceSession.infer(parameters, arguments, parent, policy);
}
@@ -65,7 +65,7 @@
@NotNull PsiType[] rightTypes,
@NotNull LanguageLevel languageLevel) {
if (typeParameters.length == 0) return PsiSubstitutor.EMPTY;
- InferenceSession session = new InferenceSession(typeParameters, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager);
+ InferenceSession session = new InferenceSession(typeParameters, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager, null);
for (PsiType leftType : leftTypes) {
if (!session.isProperType(leftType)) {
return session.infer();
@@ -104,7 +104,7 @@
leftTypes = new PsiType[] {arg};
rightTypes = new PsiType[]{param};
}
- final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParam}, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager);
+ final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParam}, leftTypes, rightTypes, PsiSubstitutor.EMPTY, myManager, null);
if (inferenceSession.isProperType(param) && inferenceSession.isProperType(arg)) {
boolean proceed = false;
for (PsiClassType classType : typeParam.getExtendsListTypes()) {
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 4fe5dfb..a67b64e 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
@@ -21,7 +21,6 @@
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
-import com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.Function;
@@ -46,7 +45,18 @@
@Override
public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
- if (myExpression instanceof PsiCallExpression || !PsiPolyExpressionUtil.isPolyExpression(myExpression)) {
+ 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) {
@@ -65,7 +75,7 @@
return true;
}
if (myExpression instanceof PsiLambdaExpression || myExpression instanceof PsiMethodReferenceExpression) {
- if (LambdaHighlightingUtil.checkInterfaceFunctional(myT) != null) {
+ if (!LambdaUtil.isFunctionalType(myT)) {
return false;
}
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(myT);
@@ -74,11 +84,17 @@
}
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, PsiUtil.resolveGenericsClassInType(myT));
- for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) {
- if (!session.isProperType(substitutor.substitute(parameter.getType()))) return false;
+ if (myExpression instanceof PsiLambdaExpression && !((PsiLambdaExpression)myExpression).hasFormalParameterTypes() ||
+ myExpression instanceof PsiMethodReferenceExpression && !((PsiMethodReferenceExpression)myExpression).isExact()) {
+ for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) {
+ if (!session.isProperType(substitutor.substitute(parameter.getType()))) return false;
+ }
}
+
final PsiType returnType = interfaceMethod.getReturnType();
- if (!session.isProperType(substitutor.substitute(returnType))) return false;
+ if (myExpression instanceof PsiLambdaExpression || !((PsiMethodReferenceExpression)myExpression).isExact()) {
+ if (!session.isProperType(substitutor.substitute(returnType))) return false;
+ }
final List<PsiType>
expectedThrownTypes = ContainerUtil.map(interfaceMethod.getThrowsList().getReferencedTypes(), new Function<PsiType, PsiType>() {
@@ -101,20 +117,24 @@
thrownTypes.addAll(ExceptionUtil.getUnhandledExceptions(body));
}
} else {
+
+ final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult((PsiMethodReferenceExpression)myExpression);
+ final PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
+ final PsiMethod method;
if (((PsiMethodReferenceExpression)myExpression).isExact()) {
final PsiElement resolve = ((PsiMethodReferenceExpression)myExpression).resolve();
if (resolve instanceof PsiMethod) {
- for (PsiClassType type : ((PsiMethod)resolve).getThrowsList().getReferencedTypes()) {
- if (!ExceptionUtil.isUncheckedException(type)) {
- thrownTypes.add(type);
- }
- }
+ method = (PsiMethod)resolve;
+ } else {
+ method = null;
}
}
else {
- PsiSubstitutor psiSubstitutor =
- PsiMethodReferenceUtil.getQualifierResolveResult((PsiMethodReferenceExpression)myExpression).getSubstitutor();
- for (PsiType type : interfaceMethod.getThrowsList().getReferencedTypes()) {
+ method = interfaceMethod;
+ }
+
+ if (method != null) {
+ for (PsiType type : method.getThrowsList().getReferencedTypes()) {
type = psiSubstitutor.substitute(type);
if (type instanceof PsiClassType && !ExceptionUtil.isUncheckedException((PsiClassType)type)) {
thrownTypes.add(type);
@@ -133,10 +153,16 @@
for (PsiType thrownType : thrownTypes) {
if (!isAddressed(expectedProperTypes, thrownType)) {
for (PsiType expectedNonProperThrownType : expectedNonProperThrownTypes) {
- constraints.add(new TypeCompatibilityConstraint(expectedNonProperThrownType, thrownType));
+ constraints.add(new StrictSubtypingConstraint(expectedNonProperThrownType, thrownType));
}
}
}
+
+ for (PsiType expectedNonProperThrownType : expectedNonProperThrownTypes) {
+ final InferenceVariable variable = session.getInferenceVariable(expectedNonProperThrownType);
+ LOG.assertTrue(variable != null);
+ variable.setThrownBound();
+ }
}
}
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 b433c13..6caa6bf 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
@@ -50,7 +50,7 @@
}
final PsiType exprType = myExpression.getType();
- if (exprType != null && !exprType.equals(PsiType.NULL)) {
+ if (exprType != null) {
constraints.add(new TypeCompatibilityConstraint(myT, exprType));
}
return true;
@@ -108,11 +108,11 @@
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
if (pair == null) {
if (method != null) {
- InferenceSession callSession = new InferenceSession(typeParams, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(), myExpression.getManager());
+ InferenceSession callSession = new InferenceSession(typeParams, ((MethodCandidateInfo)resolveResult).getSiteSubstitutor(), myExpression.getManager(), myExpression);
final PsiExpression[] args = argumentList.getExpressions();
final PsiParameter[] parameters = method.getParameterList().getParameters();
callSession.initExpressionConstraints(parameters, args, myExpression, method);
- substitutor = callSession.infer(parameters, args, myExpression, LiftParameterTypeInferencePolicy.INSTANCE);
+ substitutor = callSession.infer(parameters, args, myExpression, true, LiftParameterTypeInferencePolicy.INSTANCE);
}
} else {
substitutor = pair.second;
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
index 40cd875..e409089 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/InputOutputConstraintFormula.java
@@ -19,7 +19,6 @@
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
-import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.Nullable;
@@ -53,7 +52,7 @@
if (LambdaHighlightingUtil.checkInterfaceFunctional(type) == null) {
final PsiType functionType =
psiExpression instanceof PsiLambdaExpression
- ? FunctionalInterfaceParameterizationUtil.getFunctionalType(type, (PsiLambdaExpression)psiExpression)
+ ? FunctionalInterfaceParameterizationUtil.getGroundTargetType(type, (PsiLambdaExpression)psiExpression)
: type;
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionType);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
index 0c3bdd9..3d923b7 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/LambdaExpressionCompatibilityConstraint.java
@@ -1,13 +1,10 @@
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
import com.intellij.psi.*;
-import com.intellij.psi.controlFlow.*;
import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.containers.IntArrayList;
-import java.util.Collection;
import java.util.List;
/**
@@ -24,14 +21,12 @@
@Override
public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
- if (LambdaHighlightingUtil.checkInterfaceFunctional(myT) != null) {
+ if (!LambdaUtil.isFunctionalType(myT)) {
return false;
}
- if (myExpression.hasFormalParameterTypes()) {
- }
- final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(
- FunctionalInterfaceParameterizationUtil.getFunctionalType(myT, myExpression, false));
+ final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT, myExpression);
+ final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(groundTargetType);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
if (interfaceMethod == null) {
return false;
@@ -47,6 +42,7 @@
for (int i = 0; i < lambdaParameters.length; i++) {
constraints.add(new TypeEqualityConstraint(lambdaParameters[i].getType(), substitutor.substitute(parameters[i].getType())));
}
+ constraints.add(new StrictSubtypingConstraint(myT, groundTargetType));
} else {
for (PsiParameter parameter : parameters) {
if (!session.isProperType(substitutor.substitute(parameter.getType()))) {
@@ -55,7 +51,7 @@
}
}
- final PsiType returnType = interfaceMethod.getReturnType();
+ PsiType returnType = interfaceMethod.getReturnType();
if (returnType != null) {
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(myExpression);
if (returnType.equals(PsiType.VOID)) {
@@ -66,8 +62,11 @@
if (returnExpressions.isEmpty() && !myExpression.isValueCompatible()) { //not value-compatible
return false;
}
- for (PsiExpression returnExpression : returnExpressions) {
- constraints.add(new ExpressionCompatibilityConstraint(returnExpression, GenericsUtil.eliminateWildcards(substitutor.substitute(returnType))));
+ returnType = substitutor.substitute(returnType);
+ if (!session.isProperType(returnType)) {
+ for (PsiExpression returnExpression : returnExpressions) {
+ constraints.add(new ExpressionCompatibilityConstraint(returnExpression, GenericsUtil.eliminateWildcards(returnType)));
+ }
}
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
index 555b53b..175f3d6 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/PsiMethodReferenceCompatibilityConstraint.java
@@ -17,16 +17,17 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
+import com.intellij.psi.impl.PsiImplUtil;
+import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.PsiPolyExpressionUtil;
import com.intellij.psi.impl.source.tree.java.PsiMethodReferenceExpressionImpl;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
/**
* User: anna
@@ -43,11 +44,12 @@
@Override
public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
- if (LambdaHighlightingUtil.checkInterfaceFunctional(myT) != null) {
+ if (!LambdaUtil.isFunctionalType(myT)) {
return false;
}
- final PsiClassType.ClassResolveResult classResolveResult = PsiUtil.resolveGenericsClassInType(myT);
+ final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT);
+ final PsiClassType.ClassResolveResult classResolveResult = PsiUtil.resolveGenericsClassInType(groundTargetType);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(classResolveResult);
if (interfaceMethod == null) {
return false;
@@ -55,7 +57,11 @@
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, classResolveResult);
final PsiParameter[] targetParameters = interfaceMethod.getParameterList().getParameters();
- final PsiType returnType = substitutor.substitute(interfaceMethod.getReturnType());
+ final PsiType interfaceMethodReturnType = interfaceMethod.getReturnType();
+ PsiType returnType = substitutor.substitute(interfaceMethodReturnType);
+ if (myExpression.getTypeParameters().length == 0 && returnType != null) {
+ returnType = PsiImplUtil.normalizeWildcardTypeByPosition(returnType, myExpression);
+ }
final PsiType[] typeParameters = myExpression.getTypeParameters();
if (!myExpression.isExact()) {
for (PsiParameter parameter : targetParameters) {
@@ -77,25 +83,7 @@
}
final PsiParameter[] parameters = applicableMember instanceof PsiMethod ? ((PsiMethod)applicableMember).getParameterList().getParameters() : PsiParameter.EMPTY_ARRAY;
if (targetParameters.length == parameters.length + 1) {
- final PsiTypeElement qualifierTypeElement = myExpression.getQualifierType();
- final PsiExpression qualifierExpression = myExpression.getQualifierExpression();
- PsiType qualifierType;
- if (qualifierTypeElement != null) {
- qualifierType = qualifierTypeElement.getType();
- }
- else {
- LOG.assertTrue(qualifierExpression != null);
- qualifierType = qualifierExpression.getType();
- if (qualifierType == null && qualifierExpression instanceof PsiReferenceExpression) {
- final JavaResolveResult resolveResult = ((PsiReferenceExpression)qualifierExpression).advancedResolve(false);
- final PsiElement resolve = resolveResult.getElement();
- if (resolve instanceof PsiClass) {
- qualifierType = JavaPsiFacade.getElementFactory(resolve.getProject()).createType((PsiClass)resolve, resolveResult.getSubstitutor());
- }
- }
- }
-
- constraints.add(new SubtypingConstraint(qualifierType, GenericsUtil.eliminateWildcards(substitutor.substitute(targetParameters[0].getType())), true));
+ specialCase(session, constraints, substitutor, targetParameters);
for (int i = 1; i < targetParameters.length; i++) {
constraints.add(new TypeCompatibilityConstraint(psiSubstitutor.substitute(parameters[i - 1].getType()), GenericsUtil.eliminateWildcards(substitutor.substitute(targetParameters[i].getType()))));
}
@@ -130,7 +118,7 @@
map = new HashMap<PsiMethodReferenceExpression, PsiType>();
PsiMethodReferenceUtil.ourRefs.set(map);
}
- final PsiType added = map.put(myExpression, myT);
+ final PsiType added = map.put(myExpression, groundTargetType);
final PsiElement resolve;
try {
resolve = myExpression.resolve();
@@ -161,25 +149,75 @@
}
LOG.assertTrue(referencedMethodReturnType != null, method);
- if (typeParameters.length == 0 &&
- ((PsiMethod)resolve).getTypeParameters().length > 0 &&
- PsiPolyExpressionUtil.mentionsTypeParameters(returnType, new HashSet<PsiTypeParameter>(Arrays.asList(interfaceMethod.getTypeParameters())))) {
- //todo target type constraint
- return true;
+ session.initBounds(method.getTypeParameters());
+ session.initBounds(containingClass.getTypeParameters());
+
+ if (typeParameters.length == 0 && ((PsiMethod)resolve).getTypeParameters().length > 0) {
+
+ final PsiClass interfaceClass = classResolveResult.getElement();
+ LOG.assertTrue(interfaceClass != null);
+ if (PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType,
+ ContainerUtil.newHashSet(method.getTypeParameters()))) {
+ constraints.add(new TypeCompatibilityConstraint(referencedMethodReturnType, returnType));
+ return true;
+ }
}
if (PsiType.VOID.equals(referencedMethodReturnType)) {
return false;
}
- session.initBounds(method.getTypeParameters());
- session.initBounds(containingClass.getTypeParameters());
- constraints.add(new TypeCompatibilityConstraint(returnType, referencedMethodReturnType));
+ int idx = 0;
+ PsiSubstitutor psiSubstitutor = PsiSubstitutor.EMPTY;
+ for (PsiTypeParameter param : method.getTypeParameters()) {
+ if (idx < typeParameters.length) {
+ psiSubstitutor = psiSubstitutor.put(param, typeParameters[idx++]);
+ }
+ }
+
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ if (targetParameters.length == parameters.length + 1 && !method.isVarArgs()) {
+ specialCase(session, constraints, substitutor, targetParameters);
+ }
+ constraints.add(new TypeCompatibilityConstraint(returnType, psiSubstitutor.substitute(referencedMethodReturnType)));
}
return true;
}
+ private void specialCase(InferenceSession session,
+ List<ConstraintFormula> constraints,
+ PsiSubstitutor substitutor,
+ PsiParameter[] targetParameters) {
+ final PsiTypeElement qualifierTypeElement = myExpression.getQualifierType();
+ final PsiExpression qualifierExpression = myExpression.getQualifierExpression();
+ PsiType qualifierType;
+ if (qualifierTypeElement != null) {
+ qualifierType = qualifierTypeElement.getType();
+ }
+ else {
+ LOG.assertTrue(qualifierExpression != null);
+ qualifierType = qualifierExpression.getType();
+ if (qualifierType == null && qualifierExpression instanceof PsiReferenceExpression) {
+ final JavaResolveResult resolveResult = ((PsiReferenceExpression)qualifierExpression).advancedResolve(false);
+ final PsiElement res = resolveResult.getElement();
+ if (res instanceof PsiClass) {
+ PsiClass containingClass = (PsiClass)res;
+ final boolean isRawSubst = !myExpression.isConstructor() &&
+ PsiTreeUtil.isAncestor(containingClass, myExpression, true) &&
+ PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
+ qualifierType = JavaPsiFacade.getElementFactory(res.getProject()).createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : resolveResult.getSubstitutor());
+ }
+ }
+ }
+
+ final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
+ if (qualifierClass != null) {
+ session.initBounds(qualifierClass.getTypeParameters());
+ constraints.add(new StrictSubtypingConstraint(qualifierType, GenericsUtil.eliminateWildcards(substitutor.substitute(targetParameters[0].getType()))));
+ }
+ }
+
@Override
public void apply(PsiSubstitutor substitutor) {
myT = substitutor.substitute(myT);
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java
new file mode 100644
index 0000000..88accf9
--- /dev/null
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/StrictSubtypingConstraint.java
@@ -0,0 +1,136 @@
+/*
+ * 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.psi.impl.source.resolve.graphInference.constraints;
+
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.graphInference.InferenceBound;
+import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
+import com.intellij.psi.util.TypeConversionUtil;
+
+import java.util.List;
+
+/**
+ * User: anna
+ */
+public class StrictSubtypingConstraint implements ConstraintFormula {
+ private PsiType myS;
+ private PsiType myT;
+
+ public StrictSubtypingConstraint(PsiType t, PsiType s) {
+ myT = t;
+ myS = s;
+ }
+
+ @Override
+ public void apply(PsiSubstitutor substitutor) {
+ myT = substitutor.substitute(myT);
+ myS = substitutor.substitute(myS);
+ }
+
+
+ @Override
+ public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
+ if (session.isProperType(myS) && session.isProperType(myT)) {
+ if (myT == null) return myS == null || myS.equalsToText(CommonClassNames.JAVA_LANG_OBJECT);
+ if (myS == null) return true;
+ return TypeConversionUtil.isAssignable(myT, myS);
+ }
+
+ if (PsiType.NULL.equals(myS) || myS == null) return true;
+ if (PsiType.NULL.equals(myT) || myT == null) return false;
+
+ InferenceVariable inferenceVariable = session.getInferenceVariable(myS);
+ if (inferenceVariable != null) {
+ inferenceVariable.addBound(myT, InferenceBound.UPPER);
+ return true;
+ }
+ inferenceVariable = session.getInferenceVariable(myT);
+ if (inferenceVariable != null) {
+ inferenceVariable.addBound(myS, InferenceBound.LOWER);
+ return true;
+ }
+ if (myT instanceof PsiArrayType) {
+ if (!(myS instanceof PsiArrayType)) return false; //todo most specific array supertype
+ final PsiType tComponentType = ((PsiArrayType)myT).getComponentType();
+ final PsiType sComponentType = ((PsiArrayType)myS).getComponentType();
+ if (!(tComponentType instanceof PsiPrimitiveType) && !(sComponentType instanceof PsiPrimitiveType)) {
+ constraints.add(new StrictSubtypingConstraint(tComponentType, sComponentType));
+ return true;
+ }
+ return sComponentType instanceof PsiPrimitiveType && sComponentType.equals(tComponentType);
+ }
+ if (myT instanceof PsiClassType) {
+ final PsiClassType.ClassResolveResult TResult = ((PsiClassType)myT).resolveGenerics();
+ final PsiClass CClass = TResult.getElement();
+ if (CClass != null) {
+ if (CClass instanceof PsiTypeParameter) {
+ if (myS instanceof PsiIntersectionType) {
+ for (PsiType conjunct : ((PsiIntersectionType)myS).getConjuncts()) {
+ if (myT.equals(conjunct)) return true;
+ }
+ }
+ //todo ((PsiTypeParameter)C).getLowerBound()
+ return false;
+ }
+
+ if (!(myS instanceof PsiClassType)) return false;
+ PsiClassType.ClassResolveResult SResult = ((PsiClassType)myS).resolveGenerics();
+ PsiClass SClass = SResult.getElement();
+ final PsiSubstitutor tSubstitutor = TResult.getSubstitutor();
+ final PsiSubstitutor sSubstitutor = SClass != null ? TypeConversionUtil.getClassSubstitutor(CClass, SClass, SResult.getSubstitutor()) : null;
+ if (sSubstitutor != null) {
+ for (PsiTypeParameter parameter : CClass.getTypeParameters()) {
+ final PsiType tSubstituted = tSubstitutor.substitute(parameter);
+ final PsiType sSubstituted = sSubstitutor.substituteWithBoundsPromotion(parameter);
+ constraints.add(new SubtypingConstraint(tSubstituted, sSubstituted));
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ if (myT instanceof PsiIntersectionType) {
+ for (PsiType conjunct : ((PsiIntersectionType)myT).getConjuncts()) {
+ constraints.add(new StrictSubtypingConstraint(conjunct, myS));
+ }
+ return true;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ StrictSubtypingConstraint that = (StrictSubtypingConstraint)o;
+
+ if (myS != null ? !myS.equals(that.myS) : that.myS != null) return false;
+ if (myT != null ? !myT.equals(that.myT) : that.myT != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myS != null ? myS.hashCode() : 0;
+ result = 31 * result + (myT != null ? myT.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java
index dd75a07..f226228 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/SubtypingConstraint.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,168 +15,26 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
-import com.intellij.psi.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiCapturedWildcardType;
+import com.intellij.psi.PsiSubstitutor;
+import com.intellij.psi.PsiType;
+import com.intellij.psi.PsiWildcardType;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceBound;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.psi.util.TypeConversionUtil;
import java.util.List;
-/**
- * User: anna
- */
public class SubtypingConstraint implements ConstraintFormula {
+ private static final Logger LOG = Logger.getInstance("#" + SubtypingConstraint.class.getName());
+
private PsiType myS;
private PsiType myT;
- private final boolean myIsRefTypes;
- public SubtypingConstraint(PsiType t, PsiType s, boolean isRefTypes) {
+ public SubtypingConstraint(PsiType t, PsiType s) {
myT = t;
myS = s;
- myIsRefTypes = isRefTypes;
- }
-
- @Override
- public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
- if (myIsRefTypes) {
- if (session.isProperType(myS) && session.isProperType(myT)) {
- if (myT == null) return myS == null || myS.equalsToText(CommonClassNames.JAVA_LANG_OBJECT);
- if (myS == null) return myT.equalsToText(CommonClassNames.JAVA_LANG_OBJECT);
- return TypeConversionUtil.isAssignable(myT, myS);
- }
- InferenceVariable inferenceVariable = session.getInferenceVariable(myS);
- if (inferenceVariable != null) {
- inferenceVariable.addBound(myT, InferenceBound.UPPER);
- return true;
- }
- if (PsiType.NULL.equals(myS) || myS == null) return true;
- inferenceVariable = session.getInferenceVariable(myT);
- if (inferenceVariable != null) {
- inferenceVariable.addBound(myS, InferenceBound.LOWER);
- return true;
- }
- if (myT instanceof PsiArrayType) {
- if (!(myS instanceof PsiArrayType)) return false; //todo most specific array supertype
- final PsiType tComponentType = ((PsiArrayType)myT).getComponentType();
- final PsiType sComponentType = ((PsiArrayType)myS).getComponentType();
- if (!(tComponentType instanceof PsiPrimitiveType) && !(sComponentType instanceof PsiPrimitiveType)) {
- constraints.add(new SubtypingConstraint(tComponentType, sComponentType, true));
- return true;
- }
- return sComponentType instanceof PsiPrimitiveType && sComponentType.equals(tComponentType);
- }
- if (myT instanceof PsiClassType) {
- final PsiClassType.ClassResolveResult TResult = ((PsiClassType)myT).resolveGenerics();
- final PsiClass CClass = TResult.getElement();
- if (CClass != null) {
- if (CClass instanceof PsiTypeParameter) {
- if (myS instanceof PsiIntersectionType) {
- for (PsiType conjunct : ((PsiIntersectionType)myS).getConjuncts()) {
- if (myT.equals(conjunct)) return true;
- }
- }
- //todo ((PsiTypeParameter)C).getLowerBound()
- return false;
- }
-
- if (!(myS instanceof PsiClassType)) return false;
- PsiClassType.ClassResolveResult SResult = ((PsiClassType)myS).resolveGenerics();
- PsiClass SClass = SResult.getElement();
- final PsiSubstitutor tSubstitutor = TResult.getSubstitutor();
- final PsiSubstitutor sSubstitutor = SClass != null ? TypeConversionUtil.getClassSubstitutor(CClass, SClass, SResult.getSubstitutor()) : null;
- if (sSubstitutor != null) {
- //18.2.2 Type Compatibility Constraints
- if (PsiUtil.isRawSubstitutor(CClass, sSubstitutor)) {
- session.setErased();
- return true;
- }
- for (PsiTypeParameter parameter : CClass.getTypeParameters()) {
- final PsiType tSubstituted = tSubstitutor.substitute(parameter);
- final PsiType sSubstituted = sSubstitutor.substituteWithBoundsPromotion(parameter);
- constraints.add(new SubtypingConstraint(tSubstituted, sSubstituted, false));
- }
- return true;
- }
- }
- return false;
- }
-
- if (myT instanceof PsiIntersectionType) {
- for (PsiType conjunct : ((PsiIntersectionType)myT).getConjuncts()) {
- constraints.add(new SubtypingConstraint(conjunct, myS, true));
- }
- return true;
- }
-
- if (PsiType.NULL.equals(myT)) return false;
- } else {
- if (myT instanceof PsiWildcardType) {
- final PsiType tBound = ((PsiWildcardType)myT).getBound();
- if (tBound == null) {
- return true;
- }
-
- if (myS instanceof PsiCapturedWildcardType) {
- myS = ((PsiCapturedWildcardType)myS).getWildcard();
- }
-
- if (((PsiWildcardType)myT).isExtends()) {
- if (tBound.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
- return true;
- }
-
- if (myS instanceof PsiWildcardType) {
- final PsiType sBound = ((PsiWildcardType)myS).getBound();
- if (sBound == null) {
- return true;
- }
-
- if (((PsiWildcardType)myS).isExtends()) {
- constraints.add(new SubtypingConstraint(tBound, sBound, true));
- return true;
- }
- } else {
- constraints.add(new SubtypingConstraint(tBound, myS, true));
- return true;
- }
- return false;
- } else {
-
- if (myS instanceof PsiWildcardType) {
- final PsiType sBound = ((PsiWildcardType)myS).getBound();
- if (sBound != null && ((PsiWildcardType)myS).isSuper()) {
- constraints.add(new SubtypingConstraint(sBound, tBound, true));
- return true;
- }
- } else {
- constraints.add(new SubtypingConstraint(myS, tBound, true));
- return true;
- }
- }
- return false;
- } else {
- InferenceVariable inferenceVariable = session.getInferenceVariable(myT);
- if (myS instanceof PsiWildcardType) {
- return inferenceVariable != null;
- } else {
- final InferenceVariable inferenceVariableS = session.getInferenceVariable(myS);
- if (inferenceVariableS != null) {
- inferenceVariableS.addBound(myT, InferenceBound.EQ);
- return true;
- }
-
- if (inferenceVariable != null) {
- inferenceVariable.addBound(myS, InferenceBound.EQ);
- return true;
- }
- constraints.add(new SubtypingConstraint(myT, myS, true));
- return true;
- }
- }
- }
- return true;
}
@Override
@@ -192,9 +50,7 @@
SubtypingConstraint that = (SubtypingConstraint)o;
- if (myIsRefTypes != that.myIsRefTypes) return false;
-
- if (!myIsRefTypes && myS instanceof PsiCapturedWildcardType && myS != that.myS) return false;
+ if ( myS instanceof PsiCapturedWildcardType && myS != that.myS) return false;
if (myS != null ? !myS.equals(that.myS) : that.myS != null) return false;
if (myT != null ? !myT.equals(that.myT) : that.myT != null) return false;
@@ -206,7 +62,68 @@
public int hashCode() {
int result = myS != null ? myS.hashCode() : 0;
result = 31 * result + (myT != null ? myT.hashCode() : 0);
- result = 31 * result + (myIsRefTypes ? 1 : 0);
return result;
}
+
+ @Override
+ public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
+ if (myT instanceof PsiWildcardType) {
+ final PsiType tBound = ((PsiWildcardType)myT).getBound();
+ if (tBound == null) {
+ return true;
+ }
+
+ if (myS instanceof PsiCapturedWildcardType) {
+ myS = ((PsiCapturedWildcardType)myS).getWildcard();
+ }
+
+ if (((PsiWildcardType)myT).isExtends()) {
+ if (myS instanceof PsiWildcardType) {
+ final PsiType sBound = ((PsiWildcardType)myS).getBound();
+ if (sBound == null) {
+ constraints.add(new StrictSubtypingConstraint(tBound, ((PsiWildcardType)myS).getExtendsBound()));
+ return true;
+ }
+
+ if (((PsiWildcardType)myS).isExtends()) {
+ constraints.add(new StrictSubtypingConstraint(tBound, sBound));
+ return true;
+ }
+
+ if (((PsiWildcardType)myS).isSuper()) {
+ constraints.add(new TypeEqualityConstraint(tBound, PsiType.getJavaLangObject(((PsiWildcardType)myT).getManager(), myT.getResolveScope())));
+ return true;
+ }
+
+ assert false;
+ }
+ else {
+ constraints.add(new StrictSubtypingConstraint(tBound, myS));
+ return true;
+ }
+ }
+ else {
+ LOG.assertTrue(((PsiWildcardType)myT).isSuper());
+
+ if (myS instanceof PsiWildcardType) {
+ final PsiType sBound = ((PsiWildcardType)myS).getBound();
+ if (sBound != null && ((PsiWildcardType)myS).isSuper()) {
+ constraints.add(new StrictSubtypingConstraint(sBound, tBound));
+ return true;
+ }
+ } else {
+ constraints.add(new StrictSubtypingConstraint(myS, tBound));
+ return true;
+ }
+ }
+ return false;
+ } else {
+ if (myS instanceof PsiWildcardType) {
+ return false;
+ } else {
+ constraints.add(new TypeEqualityConstraint(myT, myS));
+ return true;
+ }
+ }
+ }
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeCompatibilityConstraint.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeCompatibilityConstraint.java
index bf5987f..d94aa94 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeCompatibilityConstraint.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/resolve/graphInference/constraints/TypeCompatibilityConstraint.java
@@ -15,11 +15,9 @@
*/
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
-import com.intellij.psi.PsiClassType;
-import com.intellij.psi.PsiPrimitiveType;
-import com.intellij.psi.PsiSubstitutor;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NotNull;
@@ -52,14 +50,39 @@
if (myT instanceof PsiPrimitiveType) {
final PsiClassType boxedType = ((PsiPrimitiveType)myT).getBoxedType(session.getManager(), session.getScope());
if (boxedType != null) {
- constraints.add(new TypeCompatibilityConstraint(boxedType, myS));
+ constraints.add(new TypeEqualityConstraint(boxedType, myS));
return true;
}
}
- constraints.add(new SubtypingConstraint(myT, myS, true));
+
+ if (isUncheckedConversion(myT, myS)) {
+ session.setErased();
+ return true;
+ }
+
+ constraints.add(new StrictSubtypingConstraint(myT, myS));
return true;
}
+ public static boolean isUncheckedConversion(final PsiType t, final PsiType s) {
+ if (t instanceof PsiClassType && !((PsiClassType)t).isRaw() && s instanceof PsiClassType) {
+ final PsiClassType.ClassResolveResult tResult = ((PsiClassType)t).resolveGenerics();
+ final PsiClassType.ClassResolveResult sResult = ((PsiClassType)s).resolveGenerics();
+ final PsiClass tClass = tResult.getElement();
+ final PsiClass sClass = sResult.getElement();
+ if (tClass != null && sClass != null) {
+ final PsiSubstitutor sSubstitutor = TypeConversionUtil.getClassSubstitutor(tClass, sClass, sResult.getSubstitutor());
+ if (sSubstitutor != null && PsiUtil.isRawSubstitutor(tClass, sSubstitutor)) {
+ return true;
+ }
+ }
+ }
+ else if (t instanceof PsiArrayType && t.getArrayDimensions() == s.getArrayDimensions()) {
+ return isUncheckedConversion(t.getDeepComponentType(), s.getDeepComponentType());
+ }
+ return false;
+ }
+
@Override
public void apply(PsiSubstitutor substitutor) {
myT = substitutor.substitute(myT);
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 e215a80..1b5ebfb 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
@@ -16,11 +16,11 @@
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceBound;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
-import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -32,15 +32,47 @@
private PsiType myT;
private PsiType myS;
- public TypeEqualityConstraint(@NotNull PsiType t, @NotNull PsiType s) {
+ public TypeEqualityConstraint(PsiType t, PsiType s) {
myT = t;
myS = s;
}
@Override
public boolean reduce(InferenceSession session, List<ConstraintFormula> constraints) {
+ if (myT instanceof PsiWildcardType && myS instanceof PsiWildcardType) {
+ final PsiType tBound = ((PsiWildcardType)myT).getBound();
+ final PsiType sBound = ((PsiWildcardType)myS).getBound();
+
+ if (tBound == null && sBound == null) return true;
+
+ if (sBound == null && ((PsiWildcardType)myT).isExtends()) {
+ //extends bound of "?" (Object)
+ constraints.add(new TypeEqualityConstraint(((PsiWildcardType)myS).getExtendsBound(), tBound));
+ return true;
+ }
+
+ if (tBound == null && ((PsiWildcardType)myS).isExtends()) {
+ //extends bound of "?" (Object)
+ constraints.add(new TypeEqualityConstraint(((PsiWildcardType)myT).getExtendsBound(), sBound));
+ return true;
+ }
+
+ if (((PsiWildcardType)myT).isExtends() && ((PsiWildcardType)myS).isExtends() ||
+ ((PsiWildcardType)myT).isSuper() && ((PsiWildcardType)myS).isSuper()) {
+
+ LOG.assertTrue(tBound != null);
+ LOG.assertTrue(sBound != null);
+ constraints.add(new TypeEqualityConstraint(tBound, sBound));
+ return true;
+ }
+ }
+
+ if (myT instanceof PsiWildcardType || myS instanceof PsiWildcardType) {
+ return false;
+ }
+
if (session.isProperType(myT) && session.isProperType(myS)) {
- return myT.equals(myS);
+ return Comparing.equal(myT, myS);
}
InferenceVariable inferenceVariable = session.getInferenceVariable(myS);
if (inferenceVariable != null) {
@@ -55,11 +87,12 @@
if (myT instanceof PsiClassType && myS instanceof PsiClassType) {
final PsiClassType.ClassResolveResult tResult = ((PsiClassType)myT).resolveGenerics();
final PsiClassType.ClassResolveResult sResult = ((PsiClassType)myS).resolveGenerics();
- final PsiClass C = tResult.getElement();
- if (C == sResult.getElement() && C != null) {
+ final PsiClass tClass = tResult.getElement();
+ //equal erasure
+ if (tClass != null && tClass.equals(sResult.getElement())) {
final PsiSubstitutor tSubstitutor = tResult.getSubstitutor();
final PsiSubstitutor sSubstitutor = sResult.getSubstitutor();
- for (PsiTypeParameter typeParameter : C.getTypeParameters()) {
+ for (PsiTypeParameter typeParameter : tClass.getTypeParameters()) {
final PsiType tSubstituted = tSubstitutor.substitute(typeParameter);
final PsiType sSubstituted = sSubstitutor.substitute(typeParameter);
if (tSubstituted != null && sSubstituted != null) {
@@ -73,32 +106,7 @@
constraints.add(new TypeEqualityConstraint(((PsiArrayType)myT).getComponentType(), ((PsiArrayType)myS).getComponentType()));
return true;
}
- if (myT instanceof PsiIntersectionType && myS instanceof PsiIntersectionType) {
- final PsiType[] tConjuncts = ((PsiIntersectionType)myT).getConjuncts();
- final PsiType[] sConjuncts = ((PsiIntersectionType)myS).getConjuncts();
- if (sConjuncts.length == tConjuncts.length) {
- for (int i = 0; i < sConjuncts.length; i++) {
- constraints.add(new TypeEqualityConstraint(tConjuncts[i], sConjuncts[i]));
- }
- return true;
- }
- }
- if (myT instanceof PsiWildcardType && myS instanceof PsiWildcardType) {
- final PsiType tBound = ((PsiWildcardType)myT).getBound();
- final PsiType sBound = ((PsiWildcardType)myS).getBound();
-
- if (tBound == null && sBound == null) return true;
-
- if (((PsiWildcardType)myT).isExtends() && ((PsiWildcardType)myS).isExtends() ||
- ((PsiWildcardType)myT).isSuper() && ((PsiWildcardType)myS).isSuper()) {
-
- LOG.assertTrue(tBound != null);
- LOG.assertTrue(sBound != null);
- constraints.add(new TypeEqualityConstraint(tBound, sBound));
- return true;
- }
- }
return false;
}
@@ -115,16 +123,19 @@
TypeEqualityConstraint that = (TypeEqualityConstraint)o;
- if (!myS.equals(that.myS)) return false;
- if (!myT.equals(that.myT)) return false;
+ if (myS instanceof PsiCapturedWildcardType && myS != that.myS) return false;
+ if (myT instanceof PsiCapturedWildcardType && myT != that.myT) return false;
+
+ if (myS != null ? !myS.equals(that.myS) : that.myS != null) return false;
+ if (myT != null ? !myT.equals(that.myT) : that.myT != null) return false;
return true;
}
@Override
public int hashCode() {
- int result = myT.hashCode();
- result = 31 * result + myS.hashCode();
+ int result = myT != null ? myT.hashCode() : 0;
+ result = 31 * result + (myS != null ? myS.hashCode() : 0);
return result;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java
index 2433885..93e9f60 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/SourceUtil.java
@@ -99,11 +99,10 @@
}
newChild.putUserData(CharTable.CHAR_TABLE_KEY, SharedImplUtil.findCharTableByTree(newChild));
- dummyExpr.rawReplaceWithList(newChild);
+ dummyExpr.getTreeParent().replaceChild(dummyExpr, newChild);
- newChild = parenthExpr;
// TODO remove explicit caches drop since this should be ok if we will use ChangeUtil for the modification
- TreeUtil.clearCaches(TreeUtil.getFileElement(newChild));
- return newChild;
+ TreeUtil.clearCaches(TreeUtil.getFileElement(parenthExpr));
+ return parenthExpr;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
index 9f0f4a5..ae45273 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiExpressionListImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -42,7 +42,7 @@
@NotNull
public PsiType[] getExpressionTypes() {
PsiExpression[] expressions = getExpressions();
- PsiType[] types = new PsiType[expressions.length];
+ PsiType[] types = PsiType.createArray(expressions.length);
for (int i = 0; i < types.length; i++) {
types[i] = expressions[i].getType();
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
index b49cafd..90ca869 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLambdaExpressionImpl.java
@@ -65,7 +65,7 @@
@Nullable
@Override
public PsiType getFunctionalInterfaceType() {
- return FunctionalInterfaceParameterizationUtil.getFunctionalType(LambdaUtil.getFunctionalInterfaceType(this, true), this);
+ return FunctionalInterfaceParameterizationUtil.getGroundTargetType(LambdaUtil.getFunctionalInterfaceType(this, true), this);
}
@Override
diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java
index f6c790a..cf099fb 100644
--- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java
+++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiLiteralExpressionImpl.java
@@ -382,8 +382,11 @@
@Override
@NotNull
public PsiReference[] getReferences() {
- PsiReference[] references = PsiReferenceService.getService().getContributedReferences(this);
- return references;
+ IElementType type = getLiteralElementType();
+ if (type != JavaTokenType.STRING_LITERAL && type != JavaTokenType.INTEGER_LITERAL) {
+ return PsiReference.EMPTY_ARRAY; // there are references in int literals in SQL API parameters
+ }
+ return PsiReferenceService.getService().getContributedReferences(this);
}
@Override
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 a52efdf..89ef1e0 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
@@ -17,15 +17,16 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
-import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
-import com.intellij.psi.impl.light.LightMethod;
import com.intellij.psi.impl.source.resolve.ParameterTypeInferencePolicy;
import com.intellij.psi.impl.source.resolve.ResolveCache;
+import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil;
+import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
+import com.intellij.psi.impl.source.resolve.graphInference.constraints.TypeCompatibilityConstraint;
import com.intellij.psi.impl.source.tree.ChildRole;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -37,6 +38,7 @@
import com.intellij.psi.scope.JavaScopeProcessorEvent;
import com.intellij.psi.scope.PsiConflictResolver;
import com.intellij.psi.scope.PsiScopeProcessor;
+import com.intellij.psi.scope.conflictResolvers.DuplicateConflictResolver;
import com.intellij.psi.scope.conflictResolvers.JavaMethodsConflictResolver;
import com.intellij.psi.scope.processor.FilterScopeProcessor;
import com.intellij.psi.scope.processor.MethodCandidatesProcessor;
@@ -66,7 +68,7 @@
@Nullable
@Override
public PsiType getFunctionalInterfaceType() {
- return LambdaUtil.getFunctionalInterfaceType(this, true);
+ return FunctionalInterfaceParameterizationUtil.getGroundTargetType(LambdaUtil.getFunctionalInterfaceType(this, true));
}
@Override
@@ -74,6 +76,49 @@
return getPotentiallyApplicableMember() != null;
}
+ @Override
+ public boolean isPotentiallyCompatible(final PsiType functionalInterfaceType) {
+ final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(functionalInterfaceType);
+ if (interfaceMethod == null) return false;
+
+ final MethodReferenceResolver resolver = new MethodReferenceResolver() {
+ @Override
+ protected PsiConflictResolver createResolver(PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult,
+ PsiMethod interfaceMethod,
+ MethodSignature signature) {
+ return DuplicateConflictResolver.INSTANCE;
+ }
+
+ @Override
+ protected PsiType getInterfaceType(PsiMethodReferenceExpression reference) {
+ return functionalInterfaceType;
+ }
+ };
+
+ final ResolveResult[] result = resolver.resolve(this, false);
+ final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(this);
+ final int interfaceArity = interfaceMethod.getParameterList().getParametersCount();
+ for (ResolveResult resolveResult : result) {
+ final PsiElement element = resolveResult.getElement();
+ if (element instanceof PsiMethod) {
+ final boolean isStatic = ((PsiMethod)element).hasModifierProperty(PsiModifier.STATIC);
+ if (qualifierResolveResult.isReferenceTypeQualified() && getReferenceNameElement() instanceof PsiIdentifier) {
+ final int parametersCount = ((PsiMethod)element).getParameterList().getParametersCount();
+ if (parametersCount == interfaceArity && isStatic) {
+ return true;
+ }
+ if (parametersCount == interfaceArity - 1 && !isStatic) {
+ return true;
+ }
+ } else if (!isStatic) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
public PsiMember getPotentiallyApplicableMember() {
return CachedValuesManager.getCachedValue(this, new CachedValueProvider<PsiMember>() {
@Nullable
@@ -132,9 +177,12 @@
}
}
} else if (qualifier instanceof PsiReferenceExpression) {
- final PsiReferenceParameterList parameterList = ((PsiReferenceExpression)qualifier).getParameterList();
- if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
- return null;
+ final PsiReferenceExpression expression = (PsiReferenceExpression)qualifier;
+ if (qualifierResolveResult.isReferenceTypeQualified()) {
+ final PsiReferenceParameterList parameterList = expression.getParameterList();
+ if (parameterList == null || parameterList.getTypeParameterElements().length == 0) {
+ return null;
+ }
}
}
}
@@ -306,6 +354,12 @@
}
@Override
+ public boolean isConstructor() {
+ final PsiElement element = getReferenceNameElement();
+ return element instanceof PsiKeyword && PsiKeyword.NEW.equals(element.getText());
+ }
+
+ @Override
public String toString() {
return "PsiMethodReferenceExpression:" + getText();
}
@@ -324,11 +378,11 @@
return false;
}
- private class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiJavaReference> {
+ private class MethodReferenceResolver implements ResolveCache.PolyVariantResolver<PsiMethodReferenceExpression> {
@NotNull
@Override
- public ResolveResult[] resolve(@NotNull PsiJavaReference reference, boolean incompleteCode) {
- final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(PsiMethodReferenceExpressionImpl.this);
+ public ResolveResult[] resolve(@NotNull final PsiMethodReferenceExpression reference, boolean incompleteCode) {
+ final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(reference);
final PsiClass containingClass = qualifierResolveResult.getContainingClass();
PsiSubstitutor substitutor = qualifierResolveResult.getSubstitutor();
@@ -340,65 +394,127 @@
if (isConstructor && (containingClass.isEnum() || containingClass.hasModifierProperty(PsiModifier.ABSTRACT))) {
return JavaResolveResult.EMPTY_ARRAY;
}
- PsiType functionalInterfaceType = null;
- final Map<PsiMethodReferenceExpression,PsiType> map = PsiMethodReferenceUtil.ourRefs.get();
- if (map != null) {
- functionalInterfaceType = map.get(PsiMethodReferenceExpressionImpl.this);
- }
- if (functionalInterfaceType == null) {
- functionalInterfaceType = getFunctionalInterfaceType();
- }
+ final PsiType functionalInterfaceType = getInterfaceType(reference);
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionalInterfaceType);
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
- final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(LambdaUtil.getSubstitutor(interfaceMethod, resolveResult)) : null;
+ final PsiSubstitutor functionalInterfaceSubstitutor = interfaceMethod != null ? LambdaUtil.getSubstitutor(interfaceMethod, resolveResult) : null;
+ final MethodSignature signature = interfaceMethod != null ? interfaceMethod.getSignature(functionalInterfaceSubstitutor) : null;
final PsiType interfaceMethodReturnType = LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
- PsiFile containingFile = getContainingFile();
- final LanguageLevel languageLevel = PsiUtil.getLanguageLevel(containingFile);
- if (isConstructor && interfaceMethod != null) {
- final PsiTypeParameter[] typeParameters = containingClass.getTypeParameters();
- final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor);
- Project project = containingClass.getProject();
- final PsiClassType returnType = JavaPsiFacade.getElementFactory(project).createType(containingClass,
- isRawSubst ? PsiSubstitutor.EMPTY : substitutor);
-
- substitutor = LambdaUtil.inferFromReturnType(typeParameters, returnType, GenericsUtil.eliminateWildcards(interfaceMethodReturnType), substitutor, languageLevel,
- project);
-
- if (containingClass.getConstructors().length == 0) {
- ClassCandidateInfo candidateInfo = null;
- if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) && signature.getParameterTypes().length == 0 ||
- PsiMethodReferenceUtil.onArrayType(containingClass, signature)) {
- candidateInfo = new ClassCandidateInfo(containingClass, substitutor);
- }
- return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo};
+ if (isConstructor && interfaceMethod != null && containingClass.getConstructors().length == 0) {
+ final PsiClassType returnType = composeReturnType(containingClass, substitutor);
+ final InferenceSession session = new InferenceSession(containingClass.getTypeParameters(), substitutor, getManager(), null);
+ if (!(session.isProperType(returnType) && session.isProperType(interfaceMethodReturnType))) {
+ session.registerConstraints(returnType, interfaceMethodReturnType);
+ substitutor = session.infer();
}
+ ClassCandidateInfo candidateInfo = null;
+ if ((containingClass.getContainingClass() == null || !isLocatedInStaticContext(containingClass)) &&
+ signature.getParameterTypes().length == 0 ||
+ PsiMethodReferenceUtil.onArrayType(containingClass, signature)) {
+ candidateInfo = new ClassCandidateInfo(containingClass, substitutor);
+ }
+ return candidateInfo == null ? JavaResolveResult.EMPTY_ARRAY : new JavaResolveResult[]{candidateInfo};
}
- final MethodReferenceConflictResolver conflictResolver =
- new MethodReferenceConflictResolver(qualifierResolveResult, signature, interfaceMethod != null && interfaceMethod.isVarArgs());
- final PsiConflictResolver[] resolvers;
- if (signature != null) {
- final PsiType[] parameterTypes = signature.getParameterTypes();
- resolvers = new PsiConflictResolver[]{conflictResolver, new MethodRefsSpecificResolver(parameterTypes, languageLevel)};
- }
- else {
- resolvers = new PsiConflictResolver[]{conflictResolver};
- }
+ final PsiConflictResolver conflictResolver = createResolver(qualifierResolveResult, interfaceMethod, signature);
final MethodCandidatesProcessor processor =
- new MethodCandidatesProcessor(PsiMethodReferenceExpressionImpl.this, containingFile, resolvers, new SmartList<CandidateInfo>()) {
+ new MethodCandidatesProcessor(reference, getContainingFile(), new PsiConflictResolver[] {conflictResolver}, new SmartList<CandidateInfo>()) {
@Override
protected MethodCandidateInfo createCandidateInfo(final PsiMethod method,
final PsiSubstitutor substitutor,
final boolean staticProblem,
final boolean accessible) {
final PsiExpressionList argumentList = getArgumentList();
- final PsiType[] typeParameters = PsiMethodReferenceExpressionImpl.this.getTypeParameters();
+ final PsiType[] typeParameters = reference.getTypeParameters();
return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext,
argumentList != null ? argumentList.getExpressionTypes() : null, typeParameters.length > 0 ? typeParameters : null,
getLanguageLevel()) {
+ @NotNull
@Override
public PsiSubstitutor inferTypeArguments(@NotNull ParameterTypeInferencePolicy policy, boolean includeReturnConstraint) {
- return inferTypeArgumentsFromInterfaceMethod(signature, interfaceMethodReturnType, method, substitutor, languageLevel);
+ return inferTypeArguments(false);
+ }
+
+ public PsiSubstitutor inferTypeArguments(boolean varargs) {
+ if (interfaceMethod == null) return substitutor;
+ final PsiSubstitutor qualifierResultSubstitutor = qualifierResolveResult.getSubstitutor();
+ final InferenceSession session = new InferenceSession(method.getTypeParameters(), substitutor, getManager(), reference);
+
+ //lift parameters from outer call
+ final Pair<PsiMethod,PsiSubstitutor> methodSubstitutorPair = MethodCandidateInfo.getCurrentMethod(reference.getParent());
+ if (methodSubstitutorPair != null) {
+ session.initBounds(methodSubstitutorPair.first.getTypeParameters());
+ }
+
+ final PsiParameter[] functionalMethodParameters = interfaceMethod.getParameterList().getParameters();
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ final boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC);
+ if (parameters.length == functionalMethodParameters.length && !varargs || isStatic && varargs) {//static methods
+
+ if (method.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, qualifierResultSubstitutor)) {
+ session.initBounds(containingClass.getTypeParameters());
+ }
+
+ for (int i = 0; i < functionalMethodParameters.length; i++) {
+ final PsiType pType = signature.getParameterTypes()[i];
+ session.addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, varargs), pType));
+ }
+ }
+ else if (parameters.length + 1 == functionalMethodParameters.length && !varargs || !isStatic && varargs && functionalMethodParameters.length > 0) { //instance methods
+ final PsiClass aClass = qualifierResolveResult.getContainingClass();
+ session.initBounds(aClass.getTypeParameters());
+
+ final PsiType pType = signature.getParameterTypes()[0];
+
+ PsiSubstitutor psiSubstitutor = qualifierResultSubstitutor;
+ // 15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1,
+ // the type to search is the result of capture conversion (5.1.10) applied to T;
+ // otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference.
+ if (PsiUtil.isRawSubstitutor(containingClass, qualifierResultSubstitutor)) {
+ final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(pType);
+ final PsiClass pClass = pResult.getElement();
+ final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
+ if (receiverSubstitutor != null) {
+ psiSubstitutor = receiverSubstitutor;
+ }
+ }
+
+ final PsiType qType = JavaPsiFacade.getElementFactory(getProject()).createType(containingClass, psiSubstitutor);
+
+ session.addConstraint(new TypeCompatibilityConstraint(qType, pType));
+
+ for (int i = 0; i < signature.getParameterTypes().length - 1; i++) {
+ final PsiType interfaceParamType = signature.getParameterTypes()[i + 1];
+ session.addConstraint(new TypeCompatibilityConstraint(getParameterType(parameters, i, varargs), interfaceParamType));
+ }
+ }
+ else {
+ return substitutor;
+ }
+
+ if (!session.repeatInferencePhases(false)) {
+ if (method.isVarArgs() && !varargs) {
+ return inferTypeArguments(true);
+ }
+ return substitutor;
+ }
+
+ if (interfaceMethodReturnType != PsiType.VOID) {
+ final PsiType returnType = method.isConstructor() ? composeReturnType(containingClass, substitutor) : method.getReturnType();
+ if (returnType != null) {
+ session.registerConstraints(returnType, interfaceMethodReturnType);
+ }
+ }
+ return session.infer(parameters, null, null);
+ }
+
+ private PsiType getParameterType(PsiParameter[] parameters, int i, boolean varargs) {
+ if (varargs && i >= parameters.length - 1) {
+ final PsiType type = parameters[parameters.length - 1].getType();
+ LOG.assertTrue(type instanceof PsiEllipsisType);
+ return ((PsiEllipsisType)type).getComponentType();
+ }
+ return parameters[i].getType();
}
};
}
@@ -414,195 +530,120 @@
processor.handleEvent(JavaScopeProcessorEvent.START_STATIC, null);
}
ResolveState state = ResolveState.initial().put(PsiSubstitutor.KEY, substitutor);
- containingClass.processDeclarations(processor, state,
- PsiMethodReferenceExpressionImpl.this,
- PsiMethodReferenceExpressionImpl.this);
+ containingClass.processDeclarations(processor, state, reference, reference);
return processor.getResult();
}
}
return JavaResolveResult.EMPTY_ARRAY;
}
- private PsiSubstitutor inferTypeArgumentsFromInterfaceMethod(@Nullable MethodSignature signature,
- @Nullable PsiType interfaceMethodReturnType,
- PsiMethod method,
- PsiSubstitutor substitutor,
- LanguageLevel languageLevel) {
- if (signature == null) return PsiSubstitutor.EMPTY;
- PsiType[] types = method.getSignature(PsiUtil.isRawSubstitutor(method, substitutor) ? PsiSubstitutor.EMPTY : substitutor).getParameterTypes();
- PsiType[] rightTypes = signature.getParameterTypes();
- if (!method.isVarArgs() || types.length == 0) {
- if (types.length < rightTypes.length) {
- return getSubstitutor(rightTypes[0]);
- } else if (types.length > rightTypes.length) {
- return getSubstitutor(types[0]);
- }
- } else {
- if (rightTypes.length != types.length || rightTypes[rightTypes.length - 1].getArrayDimensions() != types[types.length-1].getArrayDimensions()) {
- types[types.length - 1] = ((PsiArrayType)types[types.length - 1]).getComponentType();
- int min = Math.min(types.length, rightTypes.length);
- types = Arrays.copyOf(types, min);
- rightTypes = Arrays.copyOf(rightTypes, min);
- }
+ protected PsiType getInterfaceType(PsiMethodReferenceExpression reference) {
+ PsiType functionalInterfaceType = null;
+ final Map<PsiMethodReferenceExpression,PsiType> map = PsiMethodReferenceUtil.ourRefs.get();
+ if (map != null) {
+ functionalInterfaceType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(map.get(reference));
}
- for (int i = 0; i < rightTypes.length; i++) {
- rightTypes[i] = GenericsUtil.eliminateWildcards(rightTypes[i]);
+ if (functionalInterfaceType == null) {
+ functionalInterfaceType = reference.getFunctionalInterfaceType();
}
- final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(getProject()).getResolveHelper();
- PsiSubstitutor psiSubstitutor = resolveHelper.inferTypeArguments(method.getTypeParameters(), types, rightTypes, languageLevel);
- if (method.isConstructor()) {
- psiSubstitutor = psiSubstitutor.putAll(resolveHelper.inferTypeArguments(method.getContainingClass().getTypeParameters(), types, rightTypes, languageLevel));
- }
- if (!PsiUtil.isRawSubstitutor(method, substitutor)) {
- psiSubstitutor = psiSubstitutor.putAll(substitutor);
- }
- return LambdaUtil.inferFromReturnType(method.getTypeParameters(),
- method.getReturnType(),
- GenericsUtil.eliminateWildcards(interfaceMethodReturnType),
- psiSubstitutor,
- languageLevel, getProject());
+
+ return functionalInterfaceType;
}
- private PsiSubstitutor getSubstitutor(PsiType type) {
- final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(GenericsUtil.eliminateWildcards(type));
- PsiSubstitutor psiSubstitutor = resolveResult.getSubstitutor();
- if (type instanceof PsiClassType) {
- final PsiClass psiClass = resolveResult.getElement();
- if (psiClass instanceof PsiTypeParameter) {
- for (PsiClass aClass : psiClass.getSupers()) {
- psiSubstitutor = psiSubstitutor.putAll(TypeConversionUtil.getSuperClassSubstitutor(aClass, (PsiClassType)type));
- }
- }
- }
- return psiSubstitutor;
+ protected PsiConflictResolver createResolver(PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult,
+ PsiMethod interfaceMethod,
+ MethodSignature signature) {
+ return new MethodReferenceConflictResolver(qualifierResolveResult, signature, interfaceMethod != null && interfaceMethod.isVarArgs());
}
- private class MethodReferenceConflictResolver implements PsiConflictResolver {
- private final PsiSubstitutor mySubstitutor;
+ private PsiClassType composeReturnType(PsiClass containingClass, PsiSubstitutor substitutor) {
+ final boolean isRawSubst = PsiUtil.isRawSubstitutor(containingClass, substitutor);
+ return JavaPsiFacade.getElementFactory(containingClass.getProject())
+ .createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : substitutor);
+ }
+
+ private class MethodReferenceConflictResolver extends JavaMethodsConflictResolver {
private final MethodSignature mySignature;
private final PsiMethodReferenceUtil.QualifierResolveResult myQualifierResolveResult;
private final boolean myFunctionalMethodVarArgs;
private MethodReferenceConflictResolver(PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult,
@Nullable MethodSignature signature, boolean varArgs) {
+ super(PsiMethodReferenceExpressionImpl.this, signature != null ? signature.getParameterTypes() : PsiType.EMPTY_ARRAY, PsiUtil.getLanguageLevel(PsiMethodReferenceExpressionImpl.this));
myQualifierResolveResult = qualifierResolveResult;
myFunctionalMethodVarArgs = varArgs;
- mySubstitutor = qualifierResolveResult.getSubstitutor();
mySignature = signature;
}
@Nullable
@Override
public CandidateInfo resolveConflict(@NotNull List<CandidateInfo> conflicts) {
+ return resolveConflict(conflicts, false);
+ }
+
+ public CandidateInfo resolveConflict(@NotNull List<CandidateInfo> conflicts, boolean varargs) {
if (mySignature == null) return null;
+ checkSameSignatures(conflicts);
+ checkAccessStaticLevels(conflicts, true);
+
final PsiType[] parameterTypes = mySignature.getParameterTypes();
boolean hasReceiver = PsiMethodReferenceUtil.hasReceiver(parameterTypes, myQualifierResolveResult,
PsiMethodReferenceExpressionImpl.this);
final List<CandidateInfo> firstCandidates = new ArrayList<CandidateInfo>();
final List<CandidateInfo> secondCandidates = new ArrayList<CandidateInfo>();
+
for (CandidateInfo conflict : conflicts) {
if (!(conflict instanceof MethodCandidateInfo)) continue;
final PsiMethod psiMethod = ((MethodCandidateInfo)conflict).getElement();
if (psiMethod == null) continue;
- PsiSubstitutor subst = PsiSubstitutor.EMPTY;
- subst = subst.putAll(TypeConversionUtil.getSuperClassSubstitutor(psiMethod.getContainingClass(), myQualifierResolveResult.getContainingClass(), mySubstitutor));
- subst = subst.putAll(conflict.getSubstitutor());
- final PsiType[] signatureParameterTypes2 = psiMethod.getSignature(subst).getParameterTypes();
- final boolean varArgs = psiMethod.isVarArgs();
+ final PsiSubstitutor substitutor = conflict.getSubstitutor();
+ final PsiType[] signatureParameterTypes2 = psiMethod.getSignature(substitutor).getParameterTypes();
- if (parameterTypes.length == signatureParameterTypes2.length || (varArgs && !myFunctionalMethodVarArgs && Math.abs(parameterTypes.length - signatureParameterTypes2.length) <= 1)) {
- boolean correct = true;
- for (int i = 0; i < parameterTypes.length; i++) {
- final PsiType type1 = subst.substitute(GenericsUtil.eliminateWildcards(parameterTypes[i]));
- if (varArgs && i >= signatureParameterTypes2.length - 1) {
- final PsiType type2 = signatureParameterTypes2[signatureParameterTypes2.length - 1];
- correct &= TypeConversionUtil.isAssignable(type2, type1) || TypeConversionUtil.isAssignable(((PsiArrayType)type2).getComponentType(), type1);
- }
- else {
- correct &= TypeConversionUtil.isAssignable(signatureParameterTypes2[i], type1);
- }
- }
- if (correct) {
- firstCandidates.add(conflict);
- }
+ if (varargs && (!psiMethod.isVarArgs() || myFunctionalMethodVarArgs)) continue;
+
+ if ((varargs || parameterTypes.length == signatureParameterTypes2.length) &&
+ isCorrectAssignment(signatureParameterTypes2, parameterTypes, substitutor, varargs, 0)) {
+ firstCandidates.add(conflict);
}
- if (hasReceiver && parameterTypes.length == signatureParameterTypes2.length + 1) {
- boolean correct = true;
- for (int i = 0; i < signatureParameterTypes2.length; i++) {
- final PsiType type1 = subst.substitute(GenericsUtil.eliminateWildcards(parameterTypes[i + 1]));
- final PsiType type2 = signatureParameterTypes2[i];
- final boolean assignable = TypeConversionUtil.isAssignable(type2, type1);
- if (varArgs && i == signatureParameterTypes2.length - 1) {
- correct &= assignable || TypeConversionUtil.isAssignable(((PsiArrayType)type2).getComponentType(), type1);
- }
- else {
- correct &= assignable;
- }
- }
- if (correct) {
- secondCandidates.add(conflict);
- }
+ if (hasReceiver &&
+ (varargs || parameterTypes.length == signatureParameterTypes2.length + 1) &&
+ isCorrectAssignment(signatureParameterTypes2, parameterTypes, substitutor, varargs, 1)) {
+ secondCandidates.add(conflict);
}
}
- final int acceptedCount = secondCandidates.size() + firstCandidates.size();
- if (acceptedCount != 1) {
- if (acceptedCount == 0) {
- conflicts.clear();
- }
- firstCandidates.addAll(secondCandidates);
- conflicts.clear();
- conflicts.addAll(firstCandidates);
- return null;
- }
- return !firstCandidates.isEmpty() ? firstCandidates.get(0) : secondCandidates.get(0);
- }
- }
+ checkSpecifics(firstCandidates,
+ varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
- private class MethodRefsSpecificResolver extends JavaMethodsConflictResolver {
- public MethodRefsSpecificResolver(@NotNull PsiType[] parameterTypes, @NotNull LanguageLevel languageLevel) {
- super(PsiMethodReferenceExpressionImpl.this, parameterTypes, languageLevel);
- }
+ checkSpecifics(secondCandidates,
+ varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY, myLanguageLevel);
- @Override
- public CandidateInfo resolveConflict(@NotNull List<CandidateInfo> conflicts) {
- checkSameSignatures(conflicts);
- if (conflicts.size() == 1) return conflicts.get(0);
+ 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);
- checkAccessStaticLevels(conflicts, true);
- if (conflicts.size() == 1) return conflicts.get(0);
-
- boolean varargs = false;
- boolean fixedArity = false;
- for (CandidateInfo conflict : conflicts) {
- final PsiElement psiElement = conflict.getElement();
- if (psiElement instanceof PsiMethod) {
- final boolean isVarargs = ((PsiMethod)psiElement).isVarArgs();
- if (isVarargs) {
- varargs = true;
- } else {
- fixedArity = true;
- }
- if (varargs && fixedArity) break;
- }
- }
- if (varargs && fixedArity) {
- for (Iterator<CandidateInfo> iterator = conflicts.iterator(); iterator.hasNext(); ) {
- CandidateInfo conflict = iterator.next();
- final PsiElement element = conflict.getElement();
- if (element instanceof PsiMethod && ((PsiMethod)element).isVarArgs()) iterator.remove();
- }
+ //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);
}
- checkSpecifics(conflicts,
- varargs ? MethodCandidateInfo.ApplicabilityLevel.VARARGS : MethodCandidateInfo.ApplicabilityLevel.FIXED_ARITY,
- myLanguageLevel);
- return conflicts.size() == 1 ? conflicts.get(0) : null;
+ final int acceptedCount = firstCandidates.size() + secondCandidates.size();
+ if (acceptedCount == 1) {
+ return !firstCandidates.isEmpty() ? firstCandidates.get(0) : secondCandidates.get(0);
+ }
+
+ if (!varargs) {
+ return resolveConflict(conflicts, true);
+ }
+
+ conflicts.clear();
+ firstCandidates.addAll(secondCandidates);
+ conflicts.addAll(firstCandidates);
+ return null;
}
@Override
@@ -618,12 +659,43 @@
}
return false;
}
- }
- }
- @Override
- public boolean isConstructor() {
- final PsiElement element = getReferenceNameElement();
- return element instanceof PsiKeyword && PsiKeyword.NEW.equals(element.getText());
+ /**
+ * 15.13.1
+ */
+ private void filterStaticCorrectCandidates(List<CandidateInfo> firstCandidates,
+ boolean shouldBeStatic) {
+ for (Iterator<CandidateInfo> iterator = firstCandidates.iterator(); iterator.hasNext(); ) {
+ final PsiElement element = iterator.next().getElement();
+ if (element instanceof PsiMethod) {
+ final boolean isStatic = ((PsiMethod)element).hasModifierProperty(PsiModifier.STATIC);
+ if (shouldBeStatic && !isStatic || !shouldBeStatic && isStatic) {
+ iterator.remove();
+ }
+ }
+ }
+ }
+
+ private boolean isCorrectAssignment(PsiType[] signatureParameterTypes2,
+ PsiType[] parameterTypes,
+ PsiSubstitutor substitutor,
+ boolean varargs,
+ int offset) {
+ final int min = Math.min(signatureParameterTypes2.length, parameterTypes.length - offset);
+ for (int i = 0; i < min; i++) {
+ final PsiType type1 = substitutor.substitute(parameterTypes[i + offset]);
+ final PsiType type2 = signatureParameterTypes2[i];
+ if (varargs && i == signatureParameterTypes2.length - 1) {
+ if (!TypeConversionUtil.isAssignable(type2, type1) && !TypeConversionUtil.isAssignable(((PsiArrayType)type2).getComponentType(), type1)) {
+ return false;
+ }
+ }
+ else if (!TypeConversionUtil.isAssignable(type2, type1)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
index 79c50b3..70dfd67 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaMethodsConflictResolver.java
@@ -23,6 +23,7 @@
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
+import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.infos.CandidateInfo;
import com.intellij.psi.infos.MethodCandidateInfo;
import com.intellij.psi.scope.PsiConflictResolver;
@@ -120,7 +121,8 @@
if (methodParameters.length == 0) continue;
final PsiParameter param = i < methodParameters.length ? methodParameters[i] : methodParameters[methodParameters.length - 1];
final PsiType paramType = param.getType();
- if (!LambdaUtil.isAcceptable(lambdaExpression, conflict.getSubstitutor().substitute(paramType), lambdaExpression.hasFormalParameterTypes())) {
+ if (!LambdaUtil.isAcceptable(lambdaExpression, ((MethodCandidateInfo)conflict).getSubstitutor(false).substitute(paramType),
+ lambdaExpression.hasFormalParameterTypes())) {
iterator.remove();
}
}
@@ -144,7 +146,7 @@
ProgressManager.checkCanceled();
final CandidateInfo conflict = newConflictsArray[j];
if (nonComparable(method, conflict)) continue;
- switch (isMoreSpecific(method, conflict, applicabilityLevel, languageLevel)) {
+ switch (isMoreSpecific((MethodCandidateInfo)method, (MethodCandidateInfo)conflict, applicabilityLevel, languageLevel)) {
case FIRST:
conflicts.remove(conflict);
break;
@@ -214,7 +216,7 @@
}
PsiClass class1 = method.getContainingClass();
- PsiSubstitutor infoSubstitutor = info.getSubstitutor();
+ PsiSubstitutor infoSubstitutor = ((MethodCandidateInfo)info).getSubstitutor(false);
MethodSignature signature = method.getSignature(infoSubstitutor);
CandidateInfo existing = signatures.get(signature);
@@ -273,7 +275,7 @@
PsiType returnType2 = existingMethod.getReturnType();
if (returnType1 != null && returnType2 != null) {
returnType1 = infoSubstitutor.substitute(returnType1);
- returnType2 = existing.getSubstitutor().substitute(returnType2);
+ returnType2 = ((MethodCandidateInfo)existing).getSubstitutor(false).substitute(returnType2);
if (!returnType1.equals(returnType2) && returnType1.isAssignableFrom(returnType2)) {
conflicts.remove(i);
i--;
@@ -434,12 +436,12 @@
return TypeConversionUtil.boxingConversionApplicable(parameterType, argType);
}
- private Specifics isMoreSpecific(final CandidateInfo info1,
- final CandidateInfo info2,
+ private Specifics isMoreSpecific(final MethodCandidateInfo info1,
+ final MethodCandidateInfo info2,
@MethodCandidateInfo.ApplicabilityLevelConstant int applicabilityLevel,
@NotNull LanguageLevel languageLevel) {
- PsiMethod method1 = (PsiMethod)info1.getElement();
- PsiMethod method2 = (PsiMethod)info2.getElement();
+ PsiMethod method1 = info1.getElement();
+ PsiMethod method2 = info2.getElement();
final PsiClass class1 = method1.getContainingClass();
final PsiClass class2 = method2.getContainingClass();
@@ -448,12 +450,12 @@
final PsiTypeParameter[] typeParameters1 = method1.getTypeParameters();
final PsiTypeParameter[] typeParameters2 = method2.getTypeParameters();
- final PsiSubstitutor classSubstitutor1 = info1.getSubstitutor(); //substitutions for method type parameters will be ignored
- final PsiSubstitutor classSubstitutor2 = info2.getSubstitutor();
+ final PsiSubstitutor classSubstitutor1 = info1.getSubstitutor(false); //substitutions for method type parameters will be ignored
+ final PsiSubstitutor classSubstitutor2 = info2.getSubstitutor(false);
final int max = Math.max(params1.length, params2.length);
- PsiType[] types1 = new PsiType[max];
- PsiType[] types2 = new PsiType[max];
+ PsiType[] types1 = PsiType.createArray(max);
+ PsiType[] types2 = PsiType.createArray(max);
final boolean varargsPosition = applicabilityLevel == MethodCandidateInfo.ApplicabilityLevel.VARARGS;
for (int i = 0; i < max; i++) {
ProgressManager.checkCanceled();
@@ -501,18 +503,18 @@
if (boxingHappened[0] > 0 && boxingHappened[1] == 0) return Specifics.SECOND;
if (sameBoxing) {
- final PsiSubstitutor siteSubstitutor1 = ((MethodCandidateInfo)info1).getSiteSubstitutor();
- final PsiSubstitutor siteSubstitutor2 = ((MethodCandidateInfo)info2).getSiteSubstitutor();
+ final PsiSubstitutor siteSubstitutor1 = info1.getSiteSubstitutor();
+ final PsiSubstitutor siteSubstitutor2 = info2.getSiteSubstitutor();
final PsiType[] types2AtSite = typesAtSite(types2, siteSubstitutor2, typeParameters2);
final PsiType[] types1AtSite = typesAtSite(types1, siteSubstitutor1, typeParameters1);
final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite,
languageLevel);
- boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1);
+ boolean applicable12 = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition, methodSubstitutor1, method2, siteSubstitutor1);
final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel);
- boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2);
+ boolean applicable21 = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition, methodSubstitutor2, method1, siteSubstitutor2);
final boolean typeArgsApplicable12 = GenericsUtil.isTypeArgumentsApplicable(typeParameters1, methodSubstitutor1, myArgumentsList, !applicable21);
final boolean typeArgsApplicable21 = GenericsUtil.isTypeArgumentsApplicable(typeParameters2, methodSubstitutor2, myArgumentsList, !applicable12);
@@ -539,11 +541,11 @@
return Specifics.FIRST;
}
}
- if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && myArgumentsList instanceof PsiExpressionList) {
boolean toCompareFunctional = false;
for (int i = 0; i < myActualParameterTypes.length; i++) {
- if (types1.length > 0 && LambdaHighlightingUtil.checkInterfaceFunctional(types1[Math.min(i, types1.length - 1)]) == null &&
- types2.length > 0 && LambdaHighlightingUtil.checkInterfaceFunctional(types2[Math.min(i, types2.length - 1)]) == null) {
+ if (types1.length > 0 && LambdaUtil.isFunctionalType(types1[Math.min(i, types1.length - 1)]) &&
+ types2.length > 0 && LambdaUtil.isFunctionalType(types2[Math.min(i, types2.length - 1)])) {
types1AtSite[Math.min(i, types1.length - 1)] = PsiType.NULL;
types2AtSite[Math.min(i, types2.length - 1)] = PsiType.NULL;
toCompareFunctional = true;
@@ -552,16 +554,16 @@
if (toCompareFunctional) {
final boolean applicable12ignoreFunctionalType = isApplicableTo(types2AtSite, method1, languageLevel, varargsPosition,
- calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel));
+ calculateMethodSubstitutor(typeParameters1, method1, siteSubstitutor1, types1, types2AtSite, languageLevel), null, null);
final boolean applicable21ignoreFunctionalType = isApplicableTo(types1AtSite, method2, languageLevel, varargsPosition,
- calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel));
+ calculateMethodSubstitutor(typeParameters2, method2, siteSubstitutor2, types2, types1AtSite, languageLevel), null, null);
if (applicable12ignoreFunctionalType || applicable21ignoreFunctionalType) {
Specifics specifics = null;
for (int i = 0; i < myActualParameterTypes.length; i++) {
if (types1.length > 0 && types1AtSite[Math.min(i, types1.length - 1)] == PsiType.NULL &&
types2.length > 0 && types2AtSite[Math.min(i, types2.length - 1)] == PsiType.NULL) {
- Specifics specific = compareFunctionalTypes(info1, info2, myActualParameterTypes[i], i, languageLevel);
+ Specifics specific = isFunctionalTypeMoreSpecific(info1, info2, ((PsiExpressionList)myArgumentsList).getExpressions()[i], i);
if (specific == Specifics.NEITHER) {
specifics = Specifics.NEITHER;
break;
@@ -576,11 +578,11 @@
}
}
- if (applicable12ignoreFunctionalType && !applicable21ignoreFunctionalType) {
+ if (!applicable12ignoreFunctionalType && applicable21ignoreFunctionalType) {
return specifics == Specifics.SECOND ? Specifics.SECOND : Specifics.NEITHER;
}
- if (applicable21ignoreFunctionalType && !applicable12ignoreFunctionalType) {
+ if (!applicable21ignoreFunctionalType && applicable12ignoreFunctionalType) {
return specifics == Specifics.FIRST ? Specifics.FIRST : Specifics.NEITHER;
}
@@ -604,7 +606,7 @@
if (class1 != class2) {
if (class2.isInheritor(class1, true) || class1.isInterface() && !class2.isInterface()) {
- if (MethodSignatureUtil.isSubsignature(method1.getSignature(info1.getSubstitutor()), method2.getSignature(info2.getSubstitutor()))) {
+ if (MethodSignatureUtil.isSubsignature(method1.getSignature(info1.getSubstitutor(false)), method2.getSignature(info2.getSubstitutor(false)))) {
return Specifics.SECOND;
}
else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) {
@@ -613,7 +615,7 @@
}
else if (class1.isInheritor(class2, true) || class2.isInterface()) {
if (MethodSignatureUtil.areErasedParametersEqual(method1.getSignature(PsiSubstitutor.EMPTY), method2.getSignature(PsiSubstitutor.EMPTY)) &&
- MethodSignatureUtil.isSubsignature(method2.getSignature(info2.getSubstitutor()), method1.getSignature(info1.getSubstitutor()))) {
+ MethodSignatureUtil.isSubsignature(method2.getSignature(info2.getSubstitutor(false)), method1.getSignature(info1.getSubstitutor(false)))) {
return Specifics.FIRST;
}
else if (method1.hasModifierProperty(PsiModifier.STATIC) && method2.hasModifierProperty(PsiModifier.STATIC) && boxingHappened[0] == 0) {
@@ -631,17 +633,22 @@
return Specifics.NEITHER;
}
- private static boolean isApplicableTo(PsiType[] types2AtSite,
- PsiMethod method1,
- LanguageLevel languageLevel,
- boolean varargsPosition,
- final PsiSubstitutor methodSubstitutor1) {
+ private boolean isApplicableTo(PsiType[] types2AtSite,
+ PsiMethod method1,
+ LanguageLevel languageLevel,
+ boolean varargsPosition,
+ final PsiSubstitutor methodSubstitutor1,
+ PsiMethod method2,
+ PsiSubstitutor siteSubstitutor1) {
+ if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8) && method2 != null && method1.getTypeParameters().length > 0 && myArgumentsList instanceof PsiExpressionList) {
+ return InferenceSession.isMoreSpecific(method2, method1, siteSubstitutor1, ((PsiExpressionList)myArgumentsList).getExpressions(), null, varargsPosition);
+ }
final int applicabilityLevel = PsiUtil.getApplicabilityLevel(method1, methodSubstitutor1, types2AtSite, languageLevel, false, varargsPosition);
return applicabilityLevel > MethodCandidateInfo.ApplicabilityLevel.NOT_APPLICABLE;
}
- private static PsiType[] typesAtSite(PsiType[] types1, PsiSubstitutor siteSubstitutor1, PsiTypeParameter[] typeParameters1 ) {
- final PsiType[] types = new PsiType[types1.length];
+ private static PsiType[] typesAtSite(PsiType[] types1, PsiSubstitutor siteSubstitutor1, PsiTypeParameter[] typeParameters1) {
+ final PsiType[] types = PsiType.createArray(types1.length);
for (int i = 0; i < types1.length; i++) {
types[i] = siteSubstitutor1.substitute(types1[i]);
if (types[i] instanceof PsiClassType) {
@@ -755,143 +762,49 @@
}
}
- enum TypeKind {
- PRIMITIVE, REFERENCE, NONE_DETERMINED
- }
-
- private static Specifics compareFunctionalTypes(CandidateInfo method,
- CandidateInfo conflict,
- PsiType paramType,
- int functionalInterfaceIdx,
- LanguageLevel languageLevel) {
- final PsiMethod methodElement = (PsiMethod)method.getElement();
- final PsiMethod conflictElement = (PsiMethod)conflict.getElement();
- final PsiType interfaceReturnType = getReturnType(functionalInterfaceIdx, method);
- final PsiType interfaceReturnType1 = getReturnType(functionalInterfaceIdx, conflict);
- if (paramType instanceof PsiLambdaExpressionType) {
- final PsiLambdaExpression lambdaExpression = ((PsiLambdaExpressionType)paramType).getExpression();
- if (!lambdaExpression.hasFormalParameterTypes()) {
- return Specifics.NEITHER;
- }
- }
- if (paramType instanceof PsiMethodReferenceType) {
- final PsiMethodReferenceExpression
- methodReferenceExpression = ((PsiMethodReferenceType)paramType).getExpression();
- if (!methodReferenceExpression.isExact()) {
- return Specifics.NEITHER;
- }
- }
- if (paramType instanceof PsiLambdaExpressionType || paramType instanceof PsiMethodReferenceType) {
- if (interfaceReturnType != null && interfaceReturnType1 != null && !Comparing.equal(interfaceReturnType, interfaceReturnType1)) {
- Specifics moreSpecific1 = comparePrimitives(paramType, interfaceReturnType, interfaceReturnType1);
- if (moreSpecific1 == Specifics.NEITHER && (interfaceReturnType != PsiType.VOID && interfaceReturnType1 != PsiType.VOID)) {
- return compareConflicts((MethodCandidateInfo)method, (MethodCandidateInfo)conflict,
- methodElement, conflictElement,
- interfaceReturnType, interfaceReturnType1, languageLevel);
- }
- return moreSpecific1;
- }
- }
- return Specifics.NEITHER;
- }
-
- private static Specifics compareConflicts(MethodCandidateInfo method,
- MethodCandidateInfo conflict,
- PsiMethod methodElement,
- PsiMethod conflictElement,
- PsiType interfaceReturnType,
- PsiType interfaceReturnType1,
- LanguageLevel languageLevel) {
- final PsiSubstitutor siteSubstitutor1 = method.getSiteSubstitutor();
- final PsiSubstitutor siteSubstitutor2 = conflict.getSiteSubstitutor();
-
- final PsiTypeParameter[] typeParameters1 = methodElement.getTypeParameters();
- final PsiTypeParameter[] typeParameters2 = conflictElement.getTypeParameters();
-
- final PsiType[] types1AtSite = {interfaceReturnType1};
- final PsiType[] types2AtSite = {interfaceReturnType};
-
- final PsiSubstitutor methodSubstitutor1 = calculateMethodSubstitutor(typeParameters1, methodElement, siteSubstitutor1, types2AtSite, types1AtSite, languageLevel);
- final PsiSubstitutor methodSubstitutor2 = calculateMethodSubstitutor(typeParameters2, conflictElement, siteSubstitutor2, types1AtSite, types2AtSite,languageLevel);
-
- final boolean applicable12 = TypeConversionUtil.isAssignable(interfaceReturnType1, methodSubstitutor1.substitute(interfaceReturnType));
- final boolean applicable21 = TypeConversionUtil.isAssignable(interfaceReturnType, methodSubstitutor2.substitute(interfaceReturnType1));
-
-
- if (applicable12 || applicable21) {
- if (!applicable21) {
- return Specifics.FIRST;
- }
-
- if (!applicable12) {
- return Specifics.SECOND;
- }
- }
- return Specifics.NEITHER;
- }
-
- private static Specifics comparePrimitives(PsiType type,
- PsiType interfaceReturnType,
- PsiType interfaceReturnType1) {
- final TypeKind typeKind = getKind(type);
- Specifics moreSpecific1 = Specifics.NEITHER;
- if (typeKind != TypeKind.NONE_DETERMINED) {
- final boolean isPrimitive = typeKind == TypeKind.PRIMITIVE;
- if (interfaceReturnType instanceof PsiPrimitiveType) {
- if (interfaceReturnType1 instanceof PsiPrimitiveType &&
- TypeConversionUtil.isAssignable(interfaceReturnType, interfaceReturnType1)) {
- moreSpecific1 = isPrimitive ? Specifics.SECOND : Specifics.FIRST;
- } else {
- moreSpecific1 = isPrimitive ? Specifics.FIRST : Specifics.SECOND;
- }
- } else if (interfaceReturnType1 instanceof PsiPrimitiveType) {
- moreSpecific1 = isPrimitive ? Specifics.SECOND : Specifics.FIRST;
- }
- }
- return moreSpecific1;
- }
-
@Nullable
- private static PsiType getReturnType(int functionalTypeIdx, CandidateInfo method) {
- final PsiParameter[] methodParameters = ((PsiMethod)method.getElement()).getParameterList().getParameters();
+ private static PsiType getFunctionalType(int functionalTypeIdx, CandidateInfo candidateInfo) {
+ final PsiMethod psiMethod = (PsiMethod)candidateInfo.getElement();
+ LOG.assertTrue(psiMethod != null);
+ final PsiParameter[] methodParameters = psiMethod.getParameterList().getParameters();
if (methodParameters.length == 0) return null;
final PsiParameter param = functionalTypeIdx < methodParameters.length ? methodParameters[functionalTypeIdx] : methodParameters[methodParameters.length - 1];
- final PsiType functionalInterfaceType = ((MethodCandidateInfo)method).getSiteSubstitutor().substitute(param.getType());
- return LambdaUtil.getFunctionalInterfaceReturnType(functionalInterfaceType);
+ return ((MethodCandidateInfo)candidateInfo).getSiteSubstitutor().substitute(param.getType());
}
- private static TypeKind getKind(PsiType lambdaType) {
- TypeKind typeKind = TypeKind.PRIMITIVE;
- if (lambdaType instanceof PsiLambdaExpressionType) {
- typeKind = areLambdaReturnExpressionsPrimitive((PsiLambdaExpressionType)lambdaType);
- } else if (lambdaType instanceof PsiMethodReferenceType) {
- final PsiElement referencedElement = ((PsiMethodReferenceType)lambdaType).getExpression().resolve();
- if (referencedElement instanceof PsiMethod && !(((PsiMethod)referencedElement).getReturnType() instanceof PsiPrimitiveType)) {
- typeKind = TypeKind.REFERENCE;
- }
+ private static Specifics isFunctionalTypeMoreSpecific(CandidateInfo method,
+ CandidateInfo conflict,
+ PsiExpression expr,
+ int functionalInterfaceIdx) {
+ if (expr instanceof PsiParenthesizedExpression) {
+ return isFunctionalTypeMoreSpecific(method, conflict, ((PsiParenthesizedExpression)expr).getExpression(), functionalInterfaceIdx);
}
- return typeKind;
- }
+ if (expr instanceof PsiConditionalExpression) {
+ final Specifics thenSpecifics =
+ isFunctionalTypeMoreSpecific(method, conflict, ((PsiConditionalExpression)expr).getThenExpression(), functionalInterfaceIdx);
+ final Specifics elseSpecifics =
+ isFunctionalTypeMoreSpecific(method, conflict, ((PsiConditionalExpression)expr).getElseExpression(), functionalInterfaceIdx);
+ return thenSpecifics == elseSpecifics ? thenSpecifics : Specifics.NEITHER;
+ }
- private static TypeKind areLambdaReturnExpressionsPrimitive(PsiLambdaExpressionType lambdaType) {
- final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(lambdaType.getExpression());
- TypeKind typeKind = TypeKind.NONE_DETERMINED;
- for (PsiExpression expression : returnExpressions) {
- final PsiType returnExprType = expression.getType();
- if (returnExprType instanceof PsiPrimitiveType) {
- if (typeKind == TypeKind.REFERENCE) {
- typeKind = TypeKind.NONE_DETERMINED;
- break;
- }
- typeKind = TypeKind.PRIMITIVE;
- } else {
- if (typeKind == TypeKind.PRIMITIVE) {
- typeKind = TypeKind.NONE_DETERMINED;
- break;
- }
- typeKind = TypeKind.REFERENCE;
+ if (expr instanceof PsiLambdaExpression || expr instanceof PsiMethodReferenceExpression) {
+
+ if (expr instanceof PsiLambdaExpression && !((PsiLambdaExpression)expr).hasFormalParameterTypes()) {
+ return Specifics.NEITHER;
+ }
+ if (expr instanceof PsiMethodReferenceExpression && !((PsiMethodReferenceExpression)expr).isExact()) {
+ return Specifics.NEITHER;
+ }
+
+ final PsiType sType = getFunctionalType(functionalInterfaceIdx, method);
+ final PsiType tType = getFunctionalType(functionalInterfaceIdx, conflict);
+ if (LambdaUtil.isFunctionalType(sType) && LambdaUtil.isFunctionalType(tType)) {
+ final boolean specific12 = InferenceSession.isFunctionalTypeMoreSpecificOnExpression(sType, tType, expr);
+ final boolean specific21 = InferenceSession.isFunctionalTypeMoreSpecificOnExpression(tType, sType, expr);
+ if (specific12 && !specific21) return Specifics.FIRST;
+ if (!specific12 && specific21) return Specifics.SECOND;
}
}
- return typeKind;
+ return Specifics.NEITHER;
}
}
diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodResolverProcessor.java b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodResolverProcessor.java
index 736433a..396d9b3 100644
--- a/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodResolverProcessor.java
+++ b/java/java-psi-impl/src/com/intellij/psi/scope/processor/MethodResolverProcessor.java
@@ -27,10 +27,15 @@
public class MethodResolverProcessor extends MethodCandidatesProcessor {
private boolean myStopAcceptingCandidates = false;
- public MethodResolverProcessor(@NotNull PsiMethodCallExpression place, @NotNull PsiFile placeFile){
- this(place, placeFile, new PsiConflictResolver[]{new JavaMethodsConflictResolver(place.getArgumentList(),
- PsiUtil.getLanguageLevel(placeFile))});
- setArgumentList(place.getArgumentList());
+ public MethodResolverProcessor(@NotNull PsiMethodCallExpression place, @NotNull PsiFile placeFile) {
+ this(place, place.getArgumentList(), placeFile);
+ }
+
+ public MethodResolverProcessor(@NotNull PsiCallExpression place,
+ @NotNull PsiExpressionList argumentList,
+ @NotNull PsiFile placeFile){
+ this(place, placeFile, new PsiConflictResolver[]{new JavaMethodsConflictResolver(argumentList, PsiUtil.getLanguageLevel(placeFile))});
+ setArgumentList(argumentList);
obtainTypeArguments(place);
}
diff --git a/java/java-psi-impl/src/messages/JavaErrorMessages.properties b/java/java-psi-impl/src/messages/JavaErrorMessages.properties
index 08aa578..d9feb5c 100644
--- a/java/java-psi-impl/src/messages/JavaErrorMessages.properties
+++ b/java/java-psi-impl/src/messages/JavaErrorMessages.properties
@@ -78,7 +78,7 @@
generics.unchecked.call.to.member.of.raw.type=Unchecked call to ''{0}'' as a member of raw type ''{1}''
generics.diamond.not.applicable=Diamond operator is not applicable for non-parameterized types
generics.reference.parameters.not.allowed=Reference parameters are not allowed here
-foreach.not.applicable=foreach not applicable to type ''{0}''.
+foreach.not.applicable=foreach not applicable to type ''{0}''
illegal.to.access.static.member.from.enum.constructor.or.instance.initializer=It is illegal to access static member ''{0}'' from enum constructor or instance initializer
enum.types.cannot.be.instantiated=Enum types cannot be instantiated
generic.array.creation=Generic array creation
@@ -133,7 +133,7 @@
variable.already.assigned=Variable ''{0}'' might already have been assigned to
variable.assigned.in.loop=Variable ''{0}'' might be assigned in loop
assignment.to.final.variable=Cannot assign a value to final variable ''{0}''
-variable.must.be.final=Variable ''{0}'' is accessed from within inner class. Needs to be declared final.
+variable.must.be.final=Variable ''{0}'' is accessed from within inner class, needs to be declared final
initializer.must.be.able.to.complete.normally=Initializer must be able to complete normally
weaker.privileges={0}; attempting to assign weaker access privileges (''{1}''); was ''{2}''
incompatible.return.type=attempting to use incompatible return type
@@ -170,7 +170,7 @@
<html><body><table border=0>\
<tr><td colspan={0}>Ambiguous method call. Both</td></tr>\
<tr>{1}<td>in <b>{2}</b>\\ and</td></tr>\
- <tr>{3}<td>in <b>{4}</b>\\ match.</td></tr>\
+ <tr>{3}<td>in <b>{4}</b>\\ match</td></tr>\
</table></body></html>
@@ -339,7 +339,7 @@
expected.lparen.or.lbracket='(' or '[' expected
expected.array.initializer=Array initializer expected
unexpected.tokens=Unexpected tokens
-expected.gt.or.comma='>' or ',' expected.
+expected.gt.or.comma='>' or ',' expected
string.expected=String literal expected
else.without.if='else' without 'if'
catch.without.try='catch' without 'try'
diff --git a/java/java-runtime/src/com/intellij/rt/execution/junit/ComparisonDetailsExtractor.java b/java/java-runtime/src/com/intellij/rt/execution/junit/ComparisonDetailsExtractor.java
index 78ce51b..56bb397 100644
--- a/java/java-runtime/src/com/intellij/rt/execution/junit/ComparisonDetailsExtractor.java
+++ b/java/java-runtime/src/com/intellij/rt/execution/junit/ComparisonDetailsExtractor.java
@@ -96,8 +96,12 @@
public Packet createPacket(OutputObjectRegistry registry, Object test) {
Packet packet = super.createPacket(registry, test);
packet.
- addLimitedString(myExpected).
- addLimitedString(myActual);
+ addLimitedString(wrap(myExpected)).
+ addLimitedString(wrap(myActual));
return packet;
}
+
+ private static String wrap(final String message) {
+ return message != null ? message : "null";
+ }
}
diff --git a/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java
new file mode 100644
index 0000000..be3a03c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket.java
@@ -0,0 +1,5 @@
+public class Foo {
+ public void fails() {
+ boolean[] a = new boolean[f(<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java
new file mode 100644
index 0000000..2a09299
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/ArrayInitializerRBracket_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ public void fails() {
+ boolean[] a = new boolean[f()];<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethod.java b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethod.java
new file mode 100644
index 0000000..1551d00
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethod.java
@@ -0,0 +1,6 @@
+public class Foo {
+ public static enum MyEnum<caret>
+
+ public void foo() {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethodWithSpace.java b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethodWithSpace.java
new file mode 100644
index 0000000..bd6118e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethodWithSpace.java
@@ -0,0 +1,6 @@
+public class Foo {
+ public static enum MyEnum <caret>
+
+ public void foo() {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethodWithSpace_after.java b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethodWithSpace_after.java
new file mode 100644
index 0000000..6213c47
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethodWithSpace_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ public static enum MyEnum {
+ <caret>
+ }
+
+ public void foo() {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethod_after.java b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethod_after.java
new file mode 100644
index 0000000..6213c47
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/InnerEnumBeforeMethod_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ public static enum MyEnum {
+ <caret>
+ }
+
+ public void foo() {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentField.java b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentField.java
new file mode 100644
index 0000000..52185be
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentField.java
@@ -0,0 +1,6 @@
+public class Test {
+
+ private String s()<caret>
+
+ /* a comment */ String foo;
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentField_after.java b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentField_after.java
new file mode 100644
index 0000000..99e3571
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentField_after.java
@@ -0,0 +1,8 @@
+public class Test {
+
+ private String s() {
+ <caret>
+ }
+
+ /* a comment */ String foo;
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentMethod.java b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentMethod.java
new file mode 100644
index 0000000..914725e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentMethod.java
@@ -0,0 +1,6 @@
+public class Test {
+
+ private String s()<caret>
+
+ /* a comment */ String foo() {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentMethod_after.java b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentMethod_after.java
new file mode 100644
index 0000000..973fac3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completeStatement/MethodBeforeCommentMethod_after.java
@@ -0,0 +1,8 @@
+public class Test {
+
+ private String s() {
+ <caret>
+ }
+
+ /* a comment */ String foo() {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-result.java b/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-result.java
index 7f346c9..bb90de1 100644
--- a/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-result.java
+++ b/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-result.java
@@ -3,6 +3,6 @@
class Main {
public static void main(String[] args) {
- equals(FileInputStrea<caret>aaa);
+ equals(FileInputStreaaaa);
}
}
diff --git a/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-source.java b/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-source.java
index 495354a..370be35 100644
--- a/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-source.java
+++ b/java/java-tests/testData/codeInsight/completion/className/nameCompletion/java/InStaticImport-source.java
@@ -3,6 +3,6 @@
class Main {
public static void main(String[] args) {
- equals(FileInputStrea<caret>aaa);
+ equals(FileInputStreaaaa);
}
}
diff --git a/java/java-tests/testData/codeInsight/completion/customFileType/foo.cs b/java/java-tests/testData/codeInsight/completion/customFileType/foo.cs
new file mode 100644
index 0000000..1fcab38
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/customFileType/foo.cs
@@ -0,0 +1 @@
+// ca<caret>
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestCompletion.java
new file mode 100644
index 0000000..40aae5d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestCompletion.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+import java.jang.String;
+
+class PsiMethod {
+}
+
+interface PsiClass {
+ PsiMethod[] getMethods();
+}
+
+public class TestCompletion {
+
+ PsiClass c;
+
+ public void method() {
+ PsiMethod[] m = <caret>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestIndex.java
new file mode 100644
index 0000000..9f9ce1a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/methodChains/testArrayReturnType/TestIndex.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.
+ */
+public class TestIndex {
+
+ public void statMethod(PsiClass c) {
+ c.getMethods();
+ c.getMethods();
+ c.getMethods();
+ c.getMethods();
+ c.getMethods();
+ c.getMethods();
+ c.getMethods();
+ c.getMethods();
+ }
+}
+
+class PsiMethod {
+}
+
+interface PsiClass {
+ PsiMethod[] getMethods();
+}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java
deleted file mode 100644
index 2b9ce15..0000000
--- a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestCompletion.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-
-
-class PsiMethod implements PsiElement {
-}
-
-interface PsiElement {
-}
-
-class PsiClass {
- public PsiMethod findMethodByName(String methodName) {
- return null;
- }
-}
-
-public class TestCompletion {
-
- PsiClass c;
-
- public void method() {
- PsiElement element = <caret>
- }
-}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java
deleted file mode 100644
index 95e4761..0000000
--- a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassNotShowed2/TestIndex.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class TestIndex {
-
- public void statMethod(PsiClass c) {
- c.findMethodByName("asd");
- c.findMethodByName("asd");
- c.findMethodByName("asd");
- c.findMethodByName("asd");
- }
-}
-
-class PsiMethod implements PsiElement {
-}
-
-interface PsiElement {
-}
-
-class PsiClass {
- public PsiMethod findMethodByName(String methodName) {
- return null;
- }
-}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java
new file mode 100644
index 0000000..491d379
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestCompletion.java
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+
+
+class PsiMethod implements PsiElement {
+}
+
+interface PsiElement {
+}
+
+class PsiClass {
+ public PsiMethod findMethodByName(String methodName) {
+ return null;
+ }
+}
+
+public class TestCompletion {
+
+ PsiClass c;
+
+ public void method() {
+ PsiElement element = <caret>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java
new file mode 100644
index 0000000..4e2c417
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/methodChains/testMethodReturnsSubclassOfTargetClassShowed2/TestIndex.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class TestIndex {
+
+ public void statMethod(PsiClass c) {
+ c.findMethodByName("asd");
+ c.findMethodByName("asd");
+ c.findMethodByName("asd");
+ c.findMethodByName("asd");
+ }
+}
+
+class PsiMethod implements PsiElement {
+}
+
+interface PsiElement {
+}
+
+class PsiClass {
+ public PsiMethod findMethodByName(String methodName) {
+ return null;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java
deleted file mode 100644
index 8fdad22..0000000
--- a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestCompletion.java
+++ /dev/null
@@ -1,24 +0,0 @@
-import java.jang.String;
-
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-
-class PsiElement {
-}
-
-class PsiClass extends PsiElement {
-}
-
-class PsiElementFactory {
- public PsiClass createClass() {
- return null;
- }
-}
-
-public class TestCompletion {
-
- public void method(PsiElementFactory f) {
- PsiElement e = <caret>
- }
-}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java
deleted file mode 100644
index 85376be..0000000
--- a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesNotShowed/TestIndex.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/**
- * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
- */
-public class TestIndex {
-
- public void statMethod(PsiElementFactory f) {
- f.createClass();
- f.createClass();
- f.createClass();
- f.createClass();
- f.createClass();
- f.createClass();
- }
-}
-
-class PsiElement {
-}
-
-class PsiClass extends PsiElement {
-}
-
-class PsiElementFactory {
- public PsiClass createClass() {
- return null;
- }
-}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java
new file mode 100644
index 0000000..885d234
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestCompletion.java
@@ -0,0 +1,39 @@
+/*
+ * 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.
+ */
+import java.jang.String;
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+
+class PsiElement {
+}
+
+class PsiClass extends PsiElement {
+}
+
+class PsiElementFactory {
+ public PsiClass createClass() {
+ return null;
+ }
+}
+
+public class TestCompletion {
+
+ public void method(PsiElementFactory f) {
+ PsiElement e = <caret>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java
new file mode 100644
index 0000000..0dd1f15
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/methodChains/testResultsForSuperClassesShowed/TestIndex.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * @author Dmitry Batkovich <dmitry.batkovich@jetbrains.com>
+ */
+public class TestIndex {
+
+ public void statMethod(PsiElementFactory f) {
+ f.createClass();
+ f.createClass();
+ f.createClass();
+ f.createClass();
+ f.createClass();
+ f.createClass();
+ }
+}
+
+class PsiElement {
+}
+
+class PsiClass extends PsiElement {
+}
+
+class PsiElementFactory {
+ public PsiClass createClass() {
+ return null;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/DisplayDefaultValueInAnnotationMethods.java b/java/java-tests/testData/codeInsight/completion/normal/DisplayDefaultValueInAnnotationMethods.java
new file mode 100644
index 0000000..2995c01
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/DisplayDefaultValueInAnnotationMethods.java
@@ -0,0 +1,9 @@
+@interface Anno {
+ String myString() default "unknown";
+ boolean myBool() default false;
+}
+
+@Anno(<caret>)
+public class State {
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normal/NoLowercaseClasses.java b/java/java-tests/testData/codeInsight/completion/normal/NoLowercaseClasses.java
new file mode 100644
index 0000000..fba3e38
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/NoLowercaseClasses.java
@@ -0,0 +1,6 @@
+public class Zoo {
+ void foo() {
+ abcdefg<caret>x
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedFieldsTwiceSwitch.java b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedFieldsTwiceSwitch.java
new file mode 100644
index 0000000..e1744f9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedFieldsTwiceSwitch.java
@@ -0,0 +1,11 @@
+import static C.A.*;
+class C {
+ enum A {Abc}
+
+ public static void main(A a) {
+ switch (a) {
+ case A<caret>
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedFieldsTwiceSwitch_after.java b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedFieldsTwiceSwitch_after.java
new file mode 100644
index 0000000..e93b856
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/StaticallyImportedFieldsTwiceSwitch_after.java
@@ -0,0 +1,11 @@
+import static C.A.*;
+class C {
+ enum A {Abc}
+
+ public static void main(A a) {
+ switch (a) {
+ case Abc:<caret>
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/AnnotationEnum.java b/java/java-tests/testData/codeInsight/completion/normalSorting/AnnotationEnum.java
new file mode 100644
index 0000000..e0c3ae2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normalSorting/AnnotationEnum.java
@@ -0,0 +1,9 @@
+public class Foo {
+ @MyAnno(value = <caret>)
+}
+
+@interface MyAnno {
+ MyEnum[] value();
+}
+
+enum MyEnum { FOO, BAR }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java b/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java
deleted file mode 100644
index 4acc0b1..0000000
--- a/java/java-tests/testData/codeInsight/completion/normalSorting/DispreferDeclaredOfExpectedType.java
+++ /dev/null
@@ -1,9 +0,0 @@
-public class Aaaaaaa {
- private final String aaa;
-
- Aaaaaaa(Object aabbb) {
- aaa = "";
- aaa = true ? null : aa<caret>
- }
-
-}
diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/GlobalStaticMemberStats.java b/java/java-tests/testData/codeInsight/completion/normalSorting/GlobalStaticMemberStats.java
new file mode 100644
index 0000000..06d45b6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normalSorting/GlobalStaticMemberStats.java
@@ -0,0 +1,12 @@
+public class Foo {
+
+ void foo() {
+ newLi<caret>
+ }
+}
+
+class Bar {
+ static void newLinkedSet0() {}
+ static void newLinkedSet1(int a) {}
+ static void newLinkedSet2(int a, int b) {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferString.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferString.java
new file mode 100644
index 0000000..6ebf1ed
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferString.java
@@ -0,0 +1,6 @@
+public class Foo {
+
+ void foo() {
+ S<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/ShorterPrefixesGoFirst.html b/java/java-tests/testData/codeInsight/completion/normalSorting/ShorterPrefixesGoFirst.html
index fe6254d..65707a2 100644
--- a/java/java-tests/testData/codeInsight/completion/normalSorting/ShorterPrefixesGoFirst.html
+++ b/java/java-tests/testData/codeInsight/completion/normalSorting/ShorterPrefixesGoFirst.html
@@ -1 +1,2 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<p<caret>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java
new file mode 100644
index 0000000..036e7c5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation-out.java
@@ -0,0 +1,8 @@
+public class Test {
+
+ {
+ int abcdef = 2;
+ System.out.println("" + abcdef<caret>);
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java
new file mode 100644
index 0000000..f34d7ba
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/EverythingInStringConcatenation.java
@@ -0,0 +1,8 @@
+public class Test {
+
+ {
+ int abcdef = 2;
+ System.out.println("" + abc<caret>);
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InsideCatchFinal-out.java b/java/java-tests/testData/codeInsight/completion/smartType/InsideCatchFinal-out.java
new file mode 100644
index 0000000..4bbdf25
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/InsideCatchFinal-out.java
@@ -0,0 +1,9 @@
+class A{
+
+{
+ try{
+ throw new Exception();
+ }
+ catch(final Exception <caret>)
+}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/InsideCatchFinal.java b/java/java-tests/testData/codeInsight/completion/smartType/InsideCatchFinal.java
new file mode 100644
index 0000000..86328e3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/InsideCatchFinal.java
@@ -0,0 +1,9 @@
+class A{
+
+{
+ try{
+ throw new Exception();
+ }
+ catch(final <caret>)
+}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoHiddenParameter-out.java b/java/java-tests/testData/codeInsight/completion/smartType/NoHiddenParameter-out.java
new file mode 100644
index 0000000..31d2231
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/NoHiddenParameter-out.java
@@ -0,0 +1,18 @@
+import java.util.Collection;
+
+class A {
+ String join(Collection<String> strings) {
+ return StringUtil.join(strings, ",");
+ }
+
+ void method(Collection<String> param) {
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String[] param = {""}; // hides the parameter
+ Collection<String> params = Arrays.asList(param);
+ join(params)<caret>
+ }
+ };
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/NoHiddenParameter.java b/java/java-tests/testData/codeInsight/completion/smartType/NoHiddenParameter.java
new file mode 100644
index 0000000..1b697dd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartType/NoHiddenParameter.java
@@ -0,0 +1,18 @@
+import java.util.Collection;
+
+class A {
+ String join(Collection<String> strings) {
+ return StringUtil.join(strings, ",");
+ }
+
+ void method(Collection<String> param) {
+ new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String[] param = {""}; // hides the parameter
+ Collection<String> params = Arrays.asList(param);
+ join(<caret>)
+ }
+ };
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/GlobalStaticMemberStats.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/GlobalStaticMemberStats.java
new file mode 100644
index 0000000..48f2fe9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/GlobalStaticMemberStats.java
@@ -0,0 +1,14 @@
+import java.util.Set;
+
+public class Foo {
+
+ void foo() {
+ Set s = newLi<caret>
+ }
+}
+
+class Bar {
+ static Set newLinkedSet0() {}
+ static Set newLinkedSet1(int a) {}
+ static Set newLinkedSet2(int a, int b) {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferExpectedTypeMembers.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferExpectedTypeMembers.java
new file mode 100644
index 0000000..bf4b84f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferExpectedTypeMembers.java
@@ -0,0 +1,14 @@
+class MyColor {
+ static final MyColor RED = null;
+}
+class Another {
+ static final MyColor RED = null;
+}
+
+class Foo {
+ public static final MyColor MARKED_BACKGROUND = new MyColor();
+
+ {
+ MyColor color = RED<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java
new file mode 100644
index 0000000..5601688
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/smartTypeSorting/PreferStringsInStringConcatenation.java
@@ -0,0 +1,6 @@
+class Foo {
+
+ {
+ System.out.println("" + <caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AnnotatorWorksWithFileLevel.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AnnotatorWorksWithFileLevel.java
new file mode 100644
index 0000000..516f266
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/AnnotatorWorksWithFileLevel.java
@@ -0,0 +1,3 @@
+class X {
+ <caret>
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/DuplicateClassMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/DuplicateClassMethod.java
index a5d74eb..15b61df 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/DuplicateClassMethod.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/DuplicateClassMethod.java
@@ -1,6 +1,6 @@
public class a {
<error descr="'f(int)' is already defined in 'a'">void f(int i)</error> { }
- <error descr="'f(int)' is already defined in 'a'">void f(int i)</error> {
+ void f(int i) {
new c1() {
<error descr="'f1()' is already defined in 'Anonymous class derived from c1'">public void f1()</error> {}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/InstantiateAbstract.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/InstantiateAbstract.java
index 9bf1beb..455f86b 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/InstantiateAbstract.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/InstantiateAbstract.java
@@ -28,6 +28,7 @@
}
abstract class c1 {
abstract public void f1(int i);
+ Object o = new c1[0];
}
interface ii {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MustBeFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MustBeFinal.java
index f2a914b..f05342d 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MustBeFinal.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/MustBeFinal.java
@@ -4,7 +4,7 @@
int r = 0;
new Runnable() {
public void run() {
- int k = <error descr="Variable 'r' is accessed from within inner class. Needs to be declared final.">r</error>;
+ int k = <error descr="Variable 'r' is accessed from within inner class, needs to be declared final">r</error>;
int ii = i;
}
};
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/UnsupportedFeatures.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/UnsupportedFeatures.java
index b3bdd17..326c24b 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/UnsupportedFeatures.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/UnsupportedFeatures.java
@@ -27,9 +27,9 @@
<error descr="For-each loops are not supported at this language level">for (String s : args) { System.out.println(s); }</error>
List<error descr="Generics are not supported at this language level"><String></error> list =
- new ArrayList<error descr="Diamond types are not supported at this language level"><></error>();
+ new ArrayList<error descr="Generics are not supported at this language level"><></error>();
- for (<error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.String'">String s : list</error>) {}
+ <error descr="For-each loops are not supported at this language level">for (String s : list) {}</error>
Arrays.asList<error descr="'asList(java.lang.String...)' in 'java.util.Arrays' cannot be applied to '(java.lang.String)'">("")</error>;
<error descr="Incompatible types. Found: 'boolean', required: 'java.lang.Boolean'">Boolean b = true;</error>
<error descr="Incompatible types. Found: 'java.lang.Boolean', required: 'boolean'">boolean b1 = Boolean.TRUE;</error>
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/EnumInitializers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/EnumInitializers.java
new file mode 100644
index 0000000..b04096e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/EnumInitializers.java
@@ -0,0 +1,16 @@
+import java.util.*;
+public class MyEnum {
+
+ enum Test {A,B}
+
+ public static Test[] accepted1() {
+ List<Test> list = new ArrayList<Test>();
+ return list.toArray(new Test[list.size()]);
+ }
+
+ public static Test[] accepted2() {
+ return new Test[]{};
+ }
+
+ Test t = <error descr="Enum types cannot be instantiated">new Test()</error>;
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptionsValueOf.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptionsValueOf.java
new file mode 100644
index 0000000..b1a6060
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnhandledExceptionsValueOf.java
@@ -0,0 +1,10 @@
+enum SomeEnumeration {
+ A;
+
+ public static SomeEnumeration fromValue(String v) {
+ return valueOf(v);
+ }
+}
+
+
+public class IllegalArgumentException extends Exception {}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java
new file mode 100644
index 0000000..506accd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting6/UnsupportedFeatures7.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+import java.io.*;
+import java.util.*;
+
+import static java.lang.Math.*;
+
+@interface Anno { }
+
+@Anno
+class UnsupportedFeatures {
+ void m(String... args) throws Exception {
+ for (String s : args) { System.out.println(s); }
+
+ List<String> list =
+ new ArrayList<>();
+
+ for (String s : list) {}
+ Arrays.asList("");
+ Boolean b = true;
+ boolean b1 = Boolean.TRUE;
+
+ try { Reader r = new FileReader("/dev/null"); }
+ catch (<error descr="Multi-catches are not supported at this language level">FileNotFoundException | IOException e</error>) { e.printStackTrace(); }
+
+ try <error descr="Try-with-resources are not supported at this language level">(Reader r = new FileReader("/dev/null"))</error> { }
+
+ I i1 = <error descr="Method references are not supported at this language level">UnsupportedFeatures::m</error>;
+ I i2 = <error descr="Lambda expressions are not supported at this language level">() -> { }</error>;
+ }
+
+ interface I {
+ <error descr="Extension methods are not supported at this language level">default void m() { }</error>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/staticImportConflict/Usage.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/staticImportConflict/Usage.java
index dcbc8cc..eccbc76 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/staticImportConflict/Usage.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting7/staticImportConflict/Usage.java
@@ -24,6 +24,6 @@
m(Base1.F); //Base1.m(int)
m(F); //Base2.m(float), float Base2.F
F.class.getName(); // class Base2.F
- m<error descr="Cannot resolve method 'm(?)'">(<error descr="Reference to 'IF' is ambiguous, both 'I1.IF' and 'I2.IF' match">IF</error>)</error>;
+ m(<error descr="Reference to 'IF' is ambiguous, both 'I1.IF' and 'I2.IF' match">IF</error>);
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java
index 581948e..ffb0435 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/annotations/wrongPlace.java
@@ -22,7 +22,10 @@
}
interface I {
- @<error descr="Duplicate annotation">Anno</error> public @<error descr="Duplicate annotation">Anno</error> Collection<<error descr="Type annotations are not supported at this language level">@Anno</error> String> method(@<error descr="Duplicate annotation">Anno</error> @<error descr="Duplicate annotation">Anno</error> Object o);
+ @<error descr="Duplicate annotation">Anno</error>
+ public @<error descr="Duplicate annotation">Anno</error>
+ Collection<<error descr="Type annotations are not supported at this language level">@Anno</error> String>
+ method(@<error descr="Duplicate annotation">Anno</error> @<error descr="Duplicate annotation">Anno</error> Object o);
}
@interface Caller {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ForeachTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ForeachTypes.java
index c9fc821..2f3f516 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ForeachTypes.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/ForeachTypes.java
@@ -22,8 +22,12 @@
for (Object oi: (Iterable)o) {}
- for (<error descr="Incompatible types. Found: 'double', required: 'int'">int i:db</error>) {
+ // error descr="Incompatible types. Found: 'double', required: 'int'" was not shown because there is an error in nested for
+ for (int i : db) {
for (<error descr="Incompatible types. Found: 'java.lang.Object', required: 'int'">int p: list</error>) {}
}
+
+ for (int gjkh : <error descr="foreach not applicable to type 'int'">222</error>) {
+ }
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ForeachTypes.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ForeachTypes.java
index bd06d92..47c44fe 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ForeachTypes.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/ForeachTypes.java
@@ -22,7 +22,7 @@
for (Object oi: (Iterable)o) {}
- for (<error descr="Incompatible types. Found: 'double', required: 'int'">int i:db</error>) {
+ for (int i:db) {
for (<error descr="Incompatible types. Found: 'java.lang.Object', required: 'int'">int p: list</error>) {}
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57311.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57311.java
index a566b5b..1ff6401 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57311.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57311.java
@@ -4,7 +4,7 @@
}
void bar(A<?> x){
- baz<error descr="'baz(A<A<?>>)' in 'A' cannot be applied to '(A<A<capture<?>>>)'">(x.foo())</error>;
+ baz<error descr="'baz(A<A<? extends S>>)' in 'A' cannot be applied to '(A<A<capture<?>>>)'">(x.foo())</error>;
}
<S> void baz(A<A<? extends S>> x){}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57413.java
index de27a24..699a60d 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 'capture<?>' for type parameter 'T' is not within its bound; should extend 'A<capture<? extends A<capture<?>>>>'">foo(x)</error>;
+ foo<error descr="'foo(T)' in 'A' cannot be applied to '(A<capture<?>>)'">(x)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java
index 686e181..d264fbb 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57439.java
@@ -17,15 +17,15 @@
foo2(sb);
foo2(s);
- foo3<error descr="'foo3(A<A<?>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
- foo3<error descr="'foo3(A<A<? extends java.lang.String>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
- foo3<error descr="'foo3(A<A<?>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
- foo3<error descr="'foo3(A<A<? extends java.lang.String>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
+ foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
+ foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
+ foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
+ foo3<error descr="'foo3(A<A<? extends T>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
- foo4<error descr="'foo4(A<A<? super java.lang.Object>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
- foo4<error descr="'foo4(A<A<? super java.lang.Object>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
- foo4<error descr="'foo4(A<A<? super java.lang.String>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
- foo4<error descr="'foo4(A<A<? super java.lang.String>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
+ foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<capture<?>>)'">(b)</error>;
+ foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<capture<? extends java.lang.String>>)'">(eb)</error>;
+ foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<capture<? super java.lang.String>>)'">(sb)</error>;
+ foo4<error descr="'foo4(A<A<? super T>>)' in 'B' cannot be applied to '(B<java.lang.String>)'">(s)</error>;
foo5(b);
foo5(eb);
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57494.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57494.java
index c5248da..38bafca 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57494.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57494.java
@@ -11,6 +11,6 @@
abstract <T> T baz(List<? super T> a);
void bar(List<?> x){
- String o = baz<error descr="'baz(java.util.List<? super java.lang.Object>)' in 'A1' cannot be applied to '(java.util.List<capture<?>>)'">(x)</error>;
+ String o = baz<error descr="'baz(java.util.List<? super T>)' in 'A1' cannot be applied to '(java.util.List<capture<?>>)'">(x)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57495.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57495.java
index 7598ea9..63f8c91 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57495.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57495.java
@@ -4,6 +4,6 @@
abstract <T> T baz(List<? super List<? super T>> a);
void bar(C<?> x){
- baz<error descr="'baz(java.util.List<? super java.util.List<? super java.lang.Object>>)' in 'A' cannot be applied to '(C<capture<?>>)'">(x)</error>;
+ baz<error descr="'baz(java.util.List<? super java.util.List<? super T>>)' in 'A' cannot be applied to '(C<capture<?>>)'">(x)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57533.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57533.java
index d7ffd7e..5d1507f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57533.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA57533.java
@@ -1,6 +1,6 @@
class C<T extends C<? extends C<? extends T>>>{
void foo(C<?> x){
- <error descr="Inferred type 'capture<? extends C<? extends C<capture<?>>>>' for type parameter 'T' is not within its bound; should extend 'C<capture<? extends C<? extends C<capture<?>>>>>'">bar(x)</error>;
+ bar<error descr="'bar(C<T>)' in 'C' cannot be applied to '(C<capture<?>>)'">(x)</error>;
}
<T extends C<? extends T>> void bar(C<T> x){}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA67744.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA67744.java
index e71ede8..8514e43 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA67744.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA67744.java
@@ -8,8 +8,8 @@
void bar(List<List<?>> x, List<List<List<?>>> y){
foo(x) [0] = "";
- foo1<error descr="'foo1(java.util.List<? extends java.util.List<java.lang.Object>>)' in 'B' cannot be applied to '(java.util.List<java.util.List<?>>)'">(x)</error> [0] = "";
- foo2<error descr="'foo2(java.util.List<java.util.List<? super java.util.List<java.lang.Object>>>)' in 'B' cannot be applied to '(java.util.List<java.util.List<java.util.List<?>>>)'">(y)</error> [0] = "";
+ foo1<error descr="'foo1(java.util.List<? extends java.util.List<T>>)' in 'B' cannot be applied to '(java.util.List<java.util.List<?>>)'">(x)</error> [0] = "";
+ foo2<error descr="'foo2(java.util.List<java.util.List<? super java.util.List<T>>>)' in 'B' cannot be applied to '(java.util.List<java.util.List<java.util.List<?>>>)'">(y)</error> [0] = "";
String s = foo0(x);
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA94011.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA94011.java
index cf11bfd..6d5cdfa 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA94011.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEA94011.java
@@ -10,7 +10,7 @@
public void test(Set<MyConsumer> set) {
@SuppressWarnings("unchecked")
- Map<Parent, MyConsumer<Parent>> map = <error descr="Inferred type 'T' for type parameter 'T' is not within its bound; should implement 'Test.Consumer<Test.Parent>'">create(set)</error>;
+ Map<Parent, MyConsumer<Parent>> map = create<error descr="'create(java.util.Set<T>)' in 'Test' cannot be applied to '(java.util.Set<Test.MyConsumer>)'">(set)</error>;
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV10459.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV10459.java
index bf85591..f3185c8 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV10459.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV10459.java
@@ -8,7 +8,7 @@
List<Movable<? extends Serializable>> list = new ArrayList<Movable<? extends Serializable>> ();
Factory factory = Factory.newInstance();
// Doesn't compile, but Idea doesn't complain
- Mover<? extends Serializable> mover = factory.getNew<error descr="'getNew(java.util.List<? extends Movable<java.io.Serializable>>)' in 'Factory' cannot be applied to '(java.util.List<Movable<? extends java.io.Serializable>>)'">(list)</error>;
+ Mover<? extends Serializable> mover = factory.getNew<error descr="'getNew(java.util.List<? extends Movable<T>>)' in 'Factory' cannot be applied to '(java.util.List<Movable<? extends java.io.Serializable>>)'">(list)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV57343.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV57343.java
index 2c4a7fe..fb7e477 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV57343.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/IDEADEV57343.java
@@ -1,6 +1,6 @@
class D<T> {
void foo(D<?> x){
- bar<error descr="'bar(D<?>, D<? super java.lang.Object>)' in 'D' cannot be applied to '(D<capture<?>>, D<capture<?>>)'">(x,x)</error>;
+ bar<error descr="'bar(D<? extends T>, D<? super T>)' in 'D' cannot be applied to '(D<capture<?>>, D<capture<?>>)'">(x,x)</error>;
}
<T> void bar(D<? extends T> x, D<? super T> y){}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
index a969700..67f89f9 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/Variance.java
@@ -87,7 +87,7 @@
}
void foo (Class<? extends Emum<CaptureTest>> clazz) {
- <error descr="Inferred type 'capture<? extends CaptureTest.Emum<CaptureTest>>' for type parameter 'T' is not within its bound; should extend 'CaptureTest.Emum<capture<? extends CaptureTest.Emum<CaptureTest>>>'">Emum.valueOf(clazz, "CCC")</error>;
+ Emum.valueOf<error descr="'valueOf(java.lang.Class<T>, java.lang.String)' in 'CaptureTest.Emum' cannot be applied to '(java.lang.Class<capture<? extends CaptureTest.Emum<CaptureTest>>>, java.lang.String)'">(clazz, "CCC")</error>;
}
}
@@ -182,7 +182,7 @@
multiList.add(intHolder);
multiList.add(doubleHolder);
- swapFirstTwoValues<error descr="'swapFirstTwoValues(java.util.List<TypeBug.ValueHolder<java.lang.Object>>)' in 'TypeBug' cannot be applied to '(java.util.List<TypeBug.ValueHolder<?>>)'">(multiList)</error>; //need to be highlighted
+ swapFirstTwoValues<error descr="'swapFirstTwoValues(java.util.List<TypeBug.ValueHolder<T>>)' in 'TypeBug' cannot be applied to '(java.util.List<TypeBug.ValueHolder<?>>)'">(multiList)</error>; //need to be highlighted
// this line causes a ClassCastException when checked.
Integer value = intHolder.value;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/WildcardsBoundsIntersection.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/WildcardsBoundsIntersection.java
index 6385fe5..3fc74e5 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/WildcardsBoundsIntersection.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting8/WildcardsBoundsIntersection.java
@@ -10,6 +10,6 @@
class Main {
public static void main(NodeProperty<NumberExpression, Integer> nval, Node<? extends NodeType> expr) {
- int val = expr.get<error descr="'get(NodeProperty<? super capture<? extends NodeType>,java.lang.Integer>)' in 'Node' cannot be applied to '(NodeProperty<NumberExpression,java.lang.Integer>)'">(nval)</error>;
+ int val = expr.get<error descr="'get(NodeProperty<? super capture<? extends NodeType>,ValueT>)' in 'Node' cannot be applied to '(NodeProperty<NumberExpression,java.lang.Integer>)'">(nval)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/EqualityUnboundWildcard.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/EqualityUnboundWildcard.java
new file mode 100644
index 0000000..650725f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/EqualityUnboundWildcard.java
@@ -0,0 +1,37 @@
+public class SampleExtendsWildcard {
+ public void highlightsTheBug(Stream<String> stream) {
+ stream.flatMap((Block<?> sink, String element) -> {});
+ }
+
+ public interface Block<B> {
+ void apply(B t);
+ }
+
+ public interface Stream<S> {
+ <R> Stream<R> flatMap(FlatMapper<? super S, R> mapper);
+
+ }
+
+ public interface FlatMapper<F, R> {
+ void flatMapInto(Block<? extends R> sink, F element);
+ }
+}
+
+class SampleSuperWildcard {
+ public void highlightsTheBug(Stream<String> stream) {
+ stream.flatMap(<error descr="Cannot infer functional interface type">(Block<?> sink, String element) -> {}</error>);
+ }
+
+ public interface Block<B> {
+ void apply(B t);
+ }
+
+ public interface Stream<S> {
+ <R> Stream<R> flatMap(FlatMapper<? super S, R> mapper);
+
+ }
+
+ public interface FlatMapper<F, R> {
+ void flatMapInto(Block<? super R> sink, F element);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/LambdaGroundTest.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/LambdaGroundTest.java
new file mode 100644
index 0000000..d5b0dad
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/LambdaGroundTest.java
@@ -0,0 +1,13 @@
+import java.util.List;
+
+public class Sample {
+ interface Fun<A extends List <String>, B> {
+ B f(A a);
+ }
+
+ <T, R> void foo(Fun<? super T , R> f) {}
+
+ {
+ foo((List<String> ls) -> ls.size());
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/PrimitiveTypesCompatibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/PrimitiveTypesCompatibility.java
new file mode 100644
index 0000000..25d3482
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/PrimitiveTypesCompatibility.java
@@ -0,0 +1,7 @@
+public class Sample {
+ static <T> T foo(T t) { return null; }
+
+ static {
+ long l11 = foo(1 );
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/SubtypingExtendsSuper.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/SubtypingExtendsSuper.java
new file mode 100644
index 0000000..1ced38b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/SubtypingExtendsSuper.java
@@ -0,0 +1,22 @@
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class Sample {
+
+ static List<String> getList(Function<Object, String> function, ArrayList<? super String> objects) {
+ return transform(objects, new ArrayList<String>(), function);
+ }
+
+ static <R, S, T extends Collection<S>> T transform(Iterable<? extends R> oldCollection,
+ T newCollection,
+ Function<R, S> function) {
+
+ return newCollection;
+ }
+
+ interface Function<X, Y> {
+ Y apply(X input);
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/TypeCompatibilityUncheckedConversion.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/TypeCompatibilityUncheckedConversion.java
new file mode 100644
index 0000000..e4fa851
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/TypeCompatibilityUncheckedConversion.java
@@ -0,0 +1,14 @@
+public class Sample {
+ interface G<A> {}
+ interface G1 extends G {}
+
+ void foo(G1 g1) {
+ bar(g1);
+ }
+ <B>void bar(G<B> gb) {}
+
+ void foo(G1[] g1) {
+ bar(g1);
+ }
+ <B>void bar(G<B>[] gb) {}
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/TypeCompatibilityUncheckedConversionReturnConstraints.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/TypeCompatibilityUncheckedConversionReturnConstraints.java
new file mode 100644
index 0000000..acbc592
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/TypeCompatibilityUncheckedConversionReturnConstraints.java
@@ -0,0 +1,10 @@
+public class Sample {
+ interface G<A> {}
+ interface G1 extends G {}
+
+ <B> B bar(B b) {return null;}
+
+ void f(G1 g1) {
+ G<String> l11 = bar(g1);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/UncheckedBoundsWithErasure.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/UncheckedBoundsWithErasure.java
new file mode 100644
index 0000000..49753a7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/constraints/UncheckedBoundsWithErasure.java
@@ -0,0 +1,14 @@
+public class Sample {
+ interface G<A> {}
+ interface G1 extends G {}
+ void foo(G1 g1) {
+ bar(g1);
+ }
+ <B> B bar(G<B> gb) {return null;}
+
+ void f(G1 g1) {
+ <error descr="Incompatible types. Found: 'java.lang.Object', required: 'Sample.G<java.lang.String>'">G<String> l11 = bar(g1);</error>
+ <error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.String'">String l1 = bar(g1);</error>
+ Object o = bar(g1);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ErasedByReturnConstraint.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ErasedByReturnConstraint.java
new file mode 100644
index 0000000..47940ac
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/ErasedByReturnConstraint.java
@@ -0,0 +1,16 @@
+import java.util.List;
+
+public class Bug
+{
+
+ void foo(List<I> futures, I1<Object> callable){
+ futures.add(submit(callable));
+ }
+
+ <T> I<T> submit(I1<T> task){
+ return null;
+ }
+
+ interface I<TI>{}
+ interface I1<TI2>{}
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/GrandParentTypeParams.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/GrandParentTypeParams.java
new file mode 100644
index 0000000..49c3e6b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/GrandParentTypeParams.java
@@ -0,0 +1,22 @@
+
+import java.util.function.Function;
+import java.util.function.Supplier;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
+import java.util.*;
+
+public class X1 {
+ void test(Stream<Integer> stream) {
+ Function<List<Integer>, List<Integer>> unmodifiableList = Collections::unmodifiableList;
+ stream.collect(collectingAndThen(toList(), unmodifiableList)).remove(0);
+ }
+
+ public static<T,A1,R,RR> Collector<T,A1,RR> collectingAndThen(Collector<T,A1,R> downstream,
+ Function<R,RR> finisher) {
+ return null;
+ }
+
+ static <T> Collector<T, ?, List<T>> toList() {
+ return null;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA104429.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA104429.java
new file mode 100644
index 0000000..bf73abc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/IDEA104429.java
@@ -0,0 +1,26 @@
+class B {}
+
+class E extends B {}
+
+class P<T> {}
+
+class S<T> {}
+
+class SS {
+
+ static <T> S<T> stream(P<? extends T> spliterator) {
+ return null;
+ }
+
+}
+
+public class Issue1 {
+
+ public static void main(String[] args) {
+
+ P<E> splb = null;
+
+ S<B> sb2 = SS.stream(splb);
+
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferenceFromNotEqualTypeParamsBounds.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferenceFromNotEqualTypeParamsBounds.java
index 764acd2..1841e01 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferenceFromNotEqualTypeParamsBounds.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/InferenceFromNotEqualTypeParamsBounds.java
@@ -29,7 +29,7 @@
static <T, K, D, M1 extends Map<K, D>> C<T, M1> groupingBy(F<M1> f,
C<T, D> c,
BiConsumer<M1, T> consumer) {
- return new CImpl<>(f, consumer, <error descr="Inferred type 'M1' for type parameter 'M2' is not within its bound; should implement 'ConcurrentCollectors.ConcurrentMap<java.lang.Object,D>'">arg(c.getOp())</error>);
+ return new CImpl<>(f, consumer, arg<error descr="'arg(ConcurrentCollectors.BiOp<V>)' in 'ConcurrentCollectors.Test3' cannot be applied to '(ConcurrentCollectors.BiOp<D>)'">(c.getOp())</error>);
}
static <K, V, M2 extends ConcurrentMap<K, V>> BiOp<M2> arg(BiOp<V> op) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/TargetTypeByOverloadedMethod.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/TargetTypeByOverloadedMethod.java
new file mode 100644
index 0000000..17d279a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/TargetTypeByOverloadedMethod.java
@@ -0,0 +1,23 @@
+import java.util.List;
+import java.util.Set;
+
+public class Sample {
+ interface L<T> {
+ List<T> foo();
+ }
+
+ interface S<T> {
+ Set<T> foo();
+ }
+
+ {
+ bar(collect(foo())) ;
+ }
+
+ void bar(List<String> l){}
+
+ <T> Set<T> collect(L<T> l, int i){return null;}
+ <T1> List<T1> collect(S<T1> l){return null;}
+
+ <K> S<K> foo(){return null;}
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/TargetTypeByOverloadedMethod2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/TargetTypeByOverloadedMethod2.java
new file mode 100644
index 0000000..139fcb4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/graphInference/TargetTypeByOverloadedMethod2.java
@@ -0,0 +1,72 @@
+import java.util.Arrays;
+
+import static java.lang.System.out;
+
+public final class LambdaMain {
+ public static void main(final String... args) {
+ for (final A<String, X> a : Arrays.<A<String, X>>asList(new A<String, X>() {
+ @Override
+ public String foo(final String ignored)
+ throws X {
+ throw new X();
+ }
+ }, ignored -> { throw new X(); }))
+ try {
+ test(a, "Bob");
+ } catch (final X x) {
+ x.printStackTrace();
+ }
+
+ try {
+ out.println(test(new A<String, X>() {
+ @Override
+ public String foo(final String ignored)
+ throws X {
+ throw new X();
+ }
+ }, "Bob"));
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+
+ try {
+ out.println(test(ignored -> { throw new X(); }, "Bob"));
+ } catch (final Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ static class X
+ extends Exception {}
+
+ interface A<T, E extends Exception> {
+ T foo(T ignored)
+ throws E;
+ }
+
+ static <T, E extends Exception> T test(final A<T, E> a, final T ignored)
+ throws E {
+ return a.foo(ignored);
+ }
+}
+
+final class LambdaMainTest {
+ public void main(A<String> a) {
+ println(test(a));
+ }
+
+
+ public void println(boolean x) {}
+
+ public void println(String x) {}
+
+
+
+ interface A<T> {
+ T foo(T ignored) ;
+ }
+
+ static <T> T test (final A<T> a) {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java
index 2e4416c..6c664dd 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityRawGenerics.java
@@ -22,6 +22,6 @@
<Z> void foo(I3<Z> s) { }
void bar() {
- foo<error descr="Ambiguous method call: both 'AmbiguityRawGenerics.foo(I)' and 'AmbiguityRawGenerics.foo(I3<Object>)' match">(()-> { throw new RuntimeException(); })</error>;
+ foo<error descr="Ambiguous method call: both 'AmbiguityRawGenerics.foo(I1)' and 'AmbiguityRawGenerics.foo(I2)' match">(()-> { throw new RuntimeException(); })</error>;
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution.java
index 57f194d..1512dd0 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution.java
@@ -1,6 +1,6 @@
public interface IDEA99969 {
default IntStream distinct(Stream s) {
- return s.map<error descr="Ambiguous method call: both 'Stream.map(Function)' and 'Stream.map(IntFunction)' match">(i -> <error descr="Inconvertible types; cannot cast '<lambda parameter>' to 'int'">(int) i</error>)</error>;
+ return s.map(i -> <error descr="Inconvertible types; cannot cast '<lambda parameter>' to 'int'">(int) i</error>);
}
}
interface Stream<T> {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution3.java
index 6f7e6d0..ca4938f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution3.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguityReturnValueResolution3.java
@@ -8,8 +8,8 @@
IntStream mi = sp.map(Inner::foo);
Stream<Integer> mI = sp.map(Inner::fooBoxed);
- IntStream li = sp.map<error descr="Ambiguous method call: both 'Stream.map(Function<? super Inner,?>)' and 'Stream.map(IntFunction<? super Inner>)' match">(inner->inner.<error descr="Cannot resolve method 'foo()'">foo</error>())</error>;
- Stream<Integer> lI = sp.map<error descr="Ambiguous method call: both 'Stream.map(Function<? super Inner,? extends Integer>)' and 'Stream.map(IntFunction<? super Inner>)' match">(inner -> inner.<error descr="Cannot resolve method 'fooBoxed()'">fooBoxed</error>())</error>;
+ IntStream li = sp.map(inner->inner.<error descr="Cannot resolve method 'foo()'">foo</error>());
+ Stream<Integer> lI = sp.map(inner -> inner.<error descr="Cannot resolve method 'fooBoxed()'">fooBoxed</error>());
}
interface Stream<T> {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguitySpecificReturn.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguitySpecificReturn.java
index 738dd66..5b9d5d7 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguitySpecificReturn.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/AmbiguitySpecificReturn.java
@@ -1,6 +1,6 @@
class IntStream {
private void foo(IntStream s) {
- s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> <error descr="Operator '<<' cannot be applied to 'int', '<lambda parameter>'">1 << i</error>)</error>;
+ s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> 1 << i)</error>;
s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> 1)</error>;
s.map<error descr="Ambiguous method call: both 'IntStream.map(IntUnaryOperator)' and 'IntStream.map(ObjIntFunction<Integer>)' match">(i -> i)</error>;
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
index 1d3bab8..254ec71 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/EffectiveFinal.java
@@ -108,7 +108,7 @@
new Runnable() {
@Override
public void run() {
- System.out.println(<error descr="Variable 'o' is accessed from within inner class. Needs to be declared final.">o</error>);
+ System.out.println(<error descr="Variable 'o' is accessed from within inner class, needs to be declared final">o</error>);
}
}.run();
return 0;
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java
index 379e586..05b2585 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/FunctionalInterfaceAnnotation.java
@@ -1,4 +1,4 @@
-<warning descr="Multiple non-overriding abstract methods found">@FunctionalInterface</warning>
+<error descr="Multiple non-overriding abstract methods found">@FunctionalInterface</error>
interface Test {
void foo();
void bar();
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java
index 774c555..81537ef 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/LambdaRawOrNot.java
@@ -12,7 +12,7 @@
class Test2 {
protected <T, U> U exerciseOps(TestData<T> data, TerminalOp<T, U> terminal, IntermediateOp... ops) {
- <error descr="Incompatible types. Found: 'java.lang.Object', required: 'U'">return exerciseOps(data, (u, v) -> u.equals(v), terminal);</error>
+ return exerciseOps(data, (u, v) -> u.equals(v), terminal);
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java
index 1a65e84..53e96c3 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/NoInferenceResult.java
@@ -21,7 +21,7 @@
m((String s1) -> s1.length());
m((String s1) -> s1);
- m1(<error descr="Target type of a lambda conversion must be an interface">() -> { }</error>);
+ m1<error descr="'m1(T)' in 'NoInferenceResult' cannot be applied to '(<lambda expression>)'">(() -> { })</error>;
Foo<String> foo = new Foo<String>();
foo.map(v -> null);
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/RecursiveAccess.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/RecursiveAccess.java
index b430ebd..cf95ac4 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/RecursiveAccess.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/RecursiveAccess.java
@@ -1,5 +1,5 @@
public class LambdaTest {
- Op lambda_fib = (n) -> (n < 2) ? 1 : lambda_fib.op(n - 1) + lambda_fib.op(n - 2);
+ Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Illegal forward reference">lambda_fib</error>.op(n - 1) + <error descr="Illegal forward reference">lambda_fib</error>.op(n - 2);
{
Op lambda_fib = (n) -> (n < 2) ? 1 : <error descr="Variable 'lambda_fib' might not have been initialized">lambda_fib</error>.op(n - 1) + lambda_fib.op(n - 2);
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java
index 22e1767..ab62ca4 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/ReturnTypeCompatibility.java
@@ -25,7 +25,7 @@
}
public static void main(String[] args) {
- call<error descr="Ambiguous method call: both 'ReturnTypeIncompatibility.call(I1<Integer>)' and 'ReturnTypeIncompatibility.call(I3<Object>)' match">(i-> {return i;})</error>;
+ call<error descr="Ambiguous method call: both 'ReturnTypeIncompatibility.call(I1<Integer>)' and 'ReturnTypeIncompatibility.call(I2<Integer>)' match">(i-> {return i;})</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 8daa44f..84e9296 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<error descr="Ambiguous method call: both 'Foo.forAll(I<String,Boolean>)' and 'Foo.forAll(II<String,String>)' match">(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> false)</error>)</error>;
- String s1 = as.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<String,Boolean>)' and 'Foo.forAll(II<String,String>)' match">(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> "")</error>)</error>;
- boolean b2 = as.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<String,Boolean>)' and 'Foo.forAll(II<String,String>)' match">(s -> ac.forAll<error descr="Ambiguous method call: both 'Foo.forAll(I<Character,Boolean>)' and 'Foo.forAll(II<Character,String>)' match">(c -> "")</error>)</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/highlighting/SameLambdaParamNames.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/SameLambdaParamNames.java
new file mode 100644
index 0000000..d049aa5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/highlighting/SameLambdaParamNames.java
@@ -0,0 +1,4 @@
+import java.util.function.BiFunction;
+class X {
+ BiFunction<Object, Object, Object> b = (<error descr="Variable 'o1' is already defined in the scope">o1</error>, <error descr="Variable 'o1' is already defined in the scope">o1</error>) -> null;
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/inference/SimpleCyclicInference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/inference/SimpleCyclicInference.java
index b7c966e..400c469 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/inference/SimpleCyclicInference.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/inference/SimpleCyclicInference.java
@@ -14,7 +14,7 @@
static <T> T id(T i2) {return i2;}
{
- id(<error descr="Target type of a lambda conversion must be an interface">() -> {System.out.println("hi");}</error>);
+ id<error descr="'id(T)' in 'NoLambda' cannot be applied to '(<lambda expression>)'">(() -> {System.out.println("hi");})</error>;
NoLambda.<Runnable>id(() -> {System.out.println("hi");});
}
}
\ No newline at end of file
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 ea14af2..cb671b7 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/DefaultMethodOverrideEquivalentObject.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/DefaultMethodOverrideEquivalentObject.java
@@ -1,5 +1,5 @@
interface A {
- default String <error descr="Default method toString overrides a member of java.lang.Object">toString</error>() {
+ default String <error descr="Default method 'toString' overrides a member of 'java.lang.Object'">toString</error>() {
return "";
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ExtensionMethods.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ExtensionMethods.java
index 8c6bc7e..cc358d6 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ExtensionMethods.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/ExtensionMethods.java
@@ -23,10 +23,10 @@
interface II extends I {
default void m() {
I.super.m();
- <error descr="Unqualified super reference is not allowed in extension method">super.m</error>();
+ <error descr="Unqualified super reference is not allowed in extension method">super.<error descr="Cannot resolve method 'm()'">m</error></error>();
System.out.println(I.super.i);
- System.out.println<error descr="Cannot resolve method 'println(?)'">(<error descr="Unqualified super reference is not allowed in extension method">super.i</error>)</error>;
+ System.out.println(<error descr="Unqualified super reference is not allowed in extension method">super.<error descr="Cannot resolve symbol 'i'">i</error></error>);
}
void ma();
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethods.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethods.java
new file mode 100644
index 0000000..3514c04
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/interfaceMethods/StaticMethods.java
@@ -0,0 +1,8 @@
+interface A
+{
+ static void foo(){}
+}
+interface B extends A
+{
+ static int foo(){ return 1; }
+}
\ 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 bc235b2..40811fd 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>
- IInt i5 = <error descr="Non-static method cannot be referenced from a static context">MyTest::baz</error>;
+ <error descr="Incompatible types. Found: '<method reference>', required: 'AlienTest.IInt'">IInt i5 = 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/ConstructorAssignability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorAssignability.java
index 70c7840..cad262f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorAssignability.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ConstructorAssignability.java
@@ -13,7 +13,7 @@
public void foo() {
reduce(Moo::new);
- <error descr="Inferred type 'Foo<R>.AMoo' for type parameter 'S' is not within its bound; should implement 'Foo.ASink<java.lang.Object,Foo<R>.AMoo>'">reduce(AMoo::new)</error>;
+ reduce(<error descr="Cyclic inference">AMoo::new</error>);
reduce(AAMoo::new);
reduce(AAAMoo::new);
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromMethodReference.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromMethodReference.java
index f8978cd..393a3ae 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromMethodReference.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/InferenceFromMethodReference.java
@@ -5,14 +5,14 @@
static void test() {
Integer next = map(String::length).iterator().next();
- <error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.Integer'">Integer next1 = map(Test::length).iterator().next();</error>
+ Integer next1 = map(Test::length).iterator().next();//error with int!!!
}
public static <T> T length(T s) {
return null;
}
- public static <T> int length(String s) {
+ public static <T> /*int*/Integer length(String s) {
return 0;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java
index 67bbac2..69fd198 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/RawQualifier.java
@@ -39,6 +39,6 @@
static void foo(I3 i) {}
static {
- foo<error descr="Cannot resolve method 'foo(<method reference>)'">(Foo::new)</error>;
+ foo<error descr="Ambiguous method call: both 'MyTest1.foo(I1)' and 'MyTest1.foo(I2)' match">(Foo::new)</error>;
}
}
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 93ca789..848c423 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/ReturnTypeSpecific.java
@@ -67,7 +67,7 @@
}
public static void main(String[] args) {
- m<error descr="Ambiguous method call: both 'MyTest1.m(I2)' and 'MyTest1.m(I3)' match">(Foo::new)</error>;
+ m<error descr="Ambiguous method call: both 'MyTest1.m(I1)' and 'MyTest1.m(I2)' match">(Foo::new)</error>;
}
}
class MyTest2 {
@@ -104,6 +104,6 @@
}
public static void main(String[] args) {
- m<error descr="Ambiguous method call: both 'MyTest2.m(I2)' and 'MyTest2.m(I3)' match">(Foo::new)</error>;
+ m<error descr="Ambiguous method call: both 'MyTest2.m(I1)' and 'MyTest2.m(I2)' match">(Foo::new)</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 194eaac..3375ceb 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/StaticProblems.java
@@ -41,21 +41,21 @@
static void call2(I2 s) { }
static void test1() {
- 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>);
+ <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 s2 = MyTest1 :: m2;
call1(MyTest1::m2);
I1 s3 = MyTest1::m3;
call1(MyTest1::m3);
- 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>);
+ <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>;
}
static void test2() {
- <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest1.I2'">I2 s1 = MyTest1 :: m1;</error>
- call2<error descr="'call2(MyTest1.I2)' in 'MyTest1' cannot be applied to '(<method reference>)'">(MyTest1::m1)</error>;
- <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest1.I2'">I2 s2 = MyTest1 :: m2;</error>
- call2<error descr="'call2(MyTest1.I2)' in 'MyTest1' cannot be applied to '(<method reference>)'">(MyTest1::m2)</error>;
+ I2 s1 = MyTest1 :: m1;
+ call2(MyTest1::m1);
+ I2 s2 = MyTest1 :: m2;
+ call2(MyTest1::m2);
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest1.I2'">I2 s3 = MyTest1 :: m3;</error>
call2<error descr="'call2(MyTest1.I2)' in 'MyTest1' cannot be applied to '(<method reference>)'">(MyTest1::m3)</error>;
@@ -90,21 +90,21 @@
static void call2(I2 s) { }
static void test1() {
- 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>);
+ <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 s2 = MyTest2 :: m2;
call1(MyTest2::m2);
I1 s3 = MyTest2::m3;
call1(MyTest2::m3);
- 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>);
+ <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>;
}
static void test2() {
- <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest2.I2'">I2 s1 = MyTest2 :: m1;</error>
- call2<error descr="'call2(MyTest2.I2)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m1)</error>;
- <error descr="Incompatible types. Found: '<method reference>', required: 'MyTest2.I2'">I2 s2 = MyTest2 :: m2;</error>
- call2<error descr="'call2(MyTest2.I2)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m2)</error>;
+ I2 s1 = MyTest2 :: m1;
+ call2(MyTest2::m1);
+ I2 s2 = MyTest2 :: m2;
+ call2(MyTest2::m2);
<error descr="Incompatible types. Found: '<method reference>', required: 'MyTest2.I2'">I2 s3 = MyTest2 :: m3;</error>
call2<error descr="'call2(MyTest2.I2)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m3)</error>;
@@ -115,10 +115,10 @@
static void call3(I1 s) {}
static void call3(I2 s) {}
static {
- call3<error descr="Cannot resolve method 'call3(<method reference>)'">(MyTest2::m1)</error>;
- call3<error descr="Cannot resolve method 'call3(<method reference>)'">(MyTest2::m2)</error>;
- call3<error descr="Cannot resolve method 'call3(<method reference>)'">(MyTest2::m3)</error>;
- call3<error descr="Cannot resolve method 'call3(<method reference>)'">(MyTest2::m4)</error>;
+ call3(MyTest2::m1);
+ call3<error descr="Ambiguous method call: both 'MyTest2.call3(I1)' and 'MyTest2.call3(I2)' match">(MyTest2::m2)</error>;
+ call3(MyTest2::m3);
+ call3<error descr="'call3(MyTest2.I2)' in 'MyTest2' cannot be applied to '(<method reference>)'">(MyTest2::m4)</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/UnknownQualifierClass.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/UnknownQualifierClass.java
new file mode 100644
index 0000000..c74179e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/UnknownQualifierClass.java
@@ -0,0 +1,9 @@
+public class Test {
+ interface I {
+ void foo();
+ }
+
+ public static void main(String[] args){
+ I i = <error descr="Cannot resolve symbol 'UnknownClass'">UnknownClass</error>::wait;
+ }
+}
\ No newline at end of file
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 e521df2..66f4e07 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 @@
{
- 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_1 = 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/Varargs2.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Varargs2.java
new file mode 100644
index 0000000..2778e71
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/Varargs2.java
@@ -0,0 +1,55 @@
+class Main {
+
+ <T, R, P> Collector<T, R> m(Supplier<? extends R> supplier, BiConsumer<R, T, P> accumulator) {
+ return null;
+ }
+
+ Collector<String, Main> test2(Supplier<Main> sb) {
+ return m(sb, Main::append);
+ }
+
+ public Main append(String... str) {
+ return this;
+ }
+
+
+ interface Supplier<T> {
+ public T get();
+ }
+
+ interface Collector<T, R> {
+ }
+
+ interface BiConsumer<T, U, P> {
+ void accept(T t);
+ }
+
+}
+
+class Main1 {
+
+ <T, R, P> Collector<T, R> m(Supplier<? extends R> supplier, BiConsumer<R, T, P> accumulator) {
+ return null;
+ }
+
+ Collector<String, Main1> test2(Supplier<Main1> sb) {
+ return m(sb, Main1::append);
+ }
+
+ public Main1 append(Main1... str) {
+ return this;
+ }
+
+
+ interface Supplier<T> {
+ public T get();
+ }
+
+ interface Collector<T, R> {
+ }
+
+ interface BiConsumer<T, U, P> {
+ void accept(T t);
+ }
+
+}
\ No newline at end of file
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 c8e4d48..f6c1e3f 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/VarargsInReceiverPosition.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/methodRef/VarargsInReceiverPosition.java
@@ -2,8 +2,8 @@
class Test {
void test() {
- <error descr="Incompatible types. Found: '<method reference>', required: 'java.util.Comparator<Test>'">Comparator<Test> r2 = Test::yyy;</error>
- Comparator1<Test> c1 = <error descr="Non-static method cannot be referenced from a static context">Test::yyy</error>;
+ Comparator<Test> r2 = Test::yyy;
+ <error descr="Incompatible types. Found: '<method reference>', required: 'Comparator1<Test>'">Comparator1<Test> c1 = 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/AdditionalConstraintSubstitution.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AdditionalConstraintSubstitution.java
new file mode 100644
index 0000000..74240f1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AdditionalConstraintSubstitution.java
@@ -0,0 +1,19 @@
+import java.util.Map;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.stream.Collector;
+import java.util.stream.Stream;
+
+public class Bug
+{
+
+ void foo(Stream<Bug> words){
+ words.collect(toMap(w -> 1, (a, b) -> a + b));
+ }
+
+ public static <T, K, U>
+ Collector<T, ?, Map<K,U>> toMap(Function<Bug, U> valueMapper,
+ BinaryOperator<U> mergeFunction) {
+ return null;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AdditionalConstraintsReduceOrder.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AdditionalConstraintsReduceOrder.java
new file mode 100644
index 0000000..7c76e64
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/AdditionalConstraintsReduceOrder.java
@@ -0,0 +1,14 @@
+import java.util.List;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+
+public class FooBar<K> {
+ void foo(List<K > s) {}
+ <T, U> List<T> bar(BinaryOperator<U> kk, Function<T, U> f){
+ return null;
+ }
+
+ void f(FooBar<Integer> integerFooBar){
+ integerFooBar.foo(bar((a, b) -> a + b, x -> 1));
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/GroundTargetTypeForImplicitLambdas.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/GroundTargetTypeForImplicitLambdas.java
new file mode 100644
index 0000000..8622832
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/GroundTargetTypeForImplicitLambdas.java
@@ -0,0 +1,38 @@
+import java.util.List;
+
+interface TT<T extends List<T>> {
+ boolean p(T t);
+}
+
+class TU {
+ void foo(TT<? extends List<?>> k){}
+
+ {
+ foo(<error descr="Cannot infer functional interface type">x -> false</error>);
+ }
+}
+
+interface TT1<T extends List<?>> {
+ boolean p(T t);
+}
+
+class TU1 {
+ void foo(TT1<? extends List<?>> k){}
+
+ {
+ foo(x -> false);
+ }
+}
+
+
+interface TT2<T> {
+ boolean p(T t);
+}
+
+class TU2 {
+ void foo(TT2<? extends List<?>> k){}
+
+ {
+ foo(x -> false);
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA106670.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA106670.java
index 0742a19..e899b42 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA106670.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/IDEA106670.java
@@ -34,7 +34,7 @@
}
public void test(I<?> i) {
- bar<error descr="'bar(Test1111.I<? super java.lang.Object>)' in 'Test1111' cannot be applied to '(Test1111.I<capture<?>>)'">(i)</error>;
+ bar<error descr="'bar(Test1111.I<? super A>)' in 'Test1111' cannot be applied to '(Test1111.I<capture<?>>)'">(i)</error>;
}
public static <A> void bar(I<? super A> i) {}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/RecursiveCalls.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/RecursiveCalls.java
new file mode 100644
index 0000000..cd946b5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/RecursiveCalls.java
@@ -0,0 +1,19 @@
+public class Bug
+{
+
+ interface I<K>{}
+ public static <CRN>I<CRN> create(final I<CRN> it)
+ {
+ final I<CRN> f = null;
+
+ Bug.<String>create(fn<error descr="'fn(Bug.I<java.lang.String>)' in 'Bug' cannot be applied to '(Bug.I<CRN>)'">(f)</error>);
+
+ return create(fn(f));
+
+ }
+
+ private static <FN>I<FN> fn(final I<FN> f)
+ {
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/UseCalculatedSubstitutor.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/UseCalculatedSubstitutor.java
index 6ac3a34..72b47c3 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/UseCalculatedSubstitutor.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newLambda/UseCalculatedSubstitutor.java
@@ -8,7 +8,7 @@
void foo(I<? extends String, ? extends List<? extends String>> fip) { }
void test() {
- foo(<error descr="Cannot infer functional interface type">(ArrayList<? extends String> p) -> p.get(0)</error>);
+ foo<error descr="'foo(Test.I<? extends java.lang.String,? extends java.util.List<? extends java.lang.String>>)' in 'Test' cannot be applied to '(<lambda expression>)'">((ArrayList<? extends String> p) -> p.get(0))</error>;
}
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CapturingReturnValue.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CapturingReturnValue.java
new file mode 100644
index 0000000..8e182be
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/CapturingReturnValue.java
@@ -0,0 +1,18 @@
+import java.util.*;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+
+class Test {
+ final List<String> wordList = new ArrayList<>();
+
+ public void upperCaseWords() {
+ wordList.stream().map(String::toUpperCase);
+
+ List<String> output =
+ wordList.stream()
+ .map(String::toUpperCase)
+ .collect(toList());
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/DeepWildcardEliminating.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/DeepWildcardEliminating.java
new file mode 100644
index 0000000..385a644
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/DeepWildcardEliminating.java
@@ -0,0 +1,14 @@
+import java.util.Arrays;
+import java.util.List;
+
+class FunctionReferenceTest {
+ public static void main(String[] args) {
+ List<String> strings = Arrays.asList();
+
+ int sum = strings.stream().mapToInt(CharSequence::length).sum();
+
+ List<? extends CharSequence> sequences = strings;
+
+ sum = sequences.stream().mapToInt(CharSequence::length).sum();
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java
index bc3b75c..0d1e798 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/HighlightReferenceWhenContradictBoundsAreInferred.java
@@ -29,10 +29,10 @@
static void meth4(I3 s) { }
static {
- meth1<error descr="'meth1(Test.I1)' in 'Test' cannot be applied to '(<method reference>)'">(Foo::new)</error>;
+ meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
meth2(Foo::new);
- meth3<error descr="'meth3(Test.I3)' in 'Test' cannot be applied to '(<method reference>)'">(Foo::new)</error>;
- meth4<error descr="Cannot resolve method 'meth4(<method reference>)'">(Foo::new)</error>;
+ meth3(<error descr="Inferred type 'java.lang.Object' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Foo::new</error>);
+ meth4<error descr="Ambiguous method call: both 'Test.meth4(I1)' and 'Test.meth4(I2)' match">(Foo::new)</error>;
meth1(<error descr="Inferred type 'java.lang.String' for type parameter 'X' is not within its bound; should extend 'java.lang.Number'">Test::foo</error>);
meth2(Test::foo);
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA113297.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA113297.java
new file mode 100644
index 0000000..c20ca59
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA113297.java
@@ -0,0 +1,18 @@
+public class Test {
+
+ {
+ addListener(this::editPropertyChanged);
+ }
+
+ void addListener(ChangeListener<? super Boolean> changeListener){}
+
+ public void editPropertyChanged(Value<? extends Boolean> property) {}
+
+
+ interface ChangeListener <T> {
+ void changed(Value<? extends T> value);
+ }
+
+ class Value<K> {}
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA117311.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA117311.java
new file mode 100644
index 0000000..0c8cf6c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA117311.java
@@ -0,0 +1,18 @@
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class Box<TBox>
+{
+
+ public TBox getValue()
+ {
+ return null;
+ }
+
+ void foo(Stream<Box<String>> stream){
+ List<String> l1 = stream.map(Box<String>::getValue).collect(Collectors.toList());
+ List<String> l2 = stream.map(Box::getValue).collect(Collectors.toList());
+ }
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA118437.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA118437.java
new file mode 100644
index 0000000..0a0e307
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA118437.java
@@ -0,0 +1,21 @@
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+class Test {
+ public <T2> void validate(Stream<ConstraintViolation<T2>> stream) {
+ // ...
+ Set<Violation> violations = stream.map(this::convertToResult).collect(Collectors.toSet());
+ // ...
+ }
+
+ private <T1> Violation convertToResult(ConstraintViolation<T1> violation) {
+ // ...
+ return new Violation();
+ }
+
+ class Violation {}
+
+ class ConstraintViolation<T> {
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120370.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120370.java
new file mode 100644
index 0000000..652c87e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120370.java
@@ -0,0 +1,23 @@
+import java.util.List;
+import java.util.concurrent.Callable;
+
+public class Tmp {
+ static void doo(Runnable action){}
+ static void doo(Callable<?> action){}
+
+ interface X<T> {
+ void bar();
+ }
+
+ interface Y {
+ void bar();
+ }
+
+ void test(X<String> x1, X x2, Y y) {
+ doo(x1::bar);
+
+ doo(x2::bar);
+
+ doo(y::bar);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java
new file mode 100644
index 0000000..822402f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/IDEA120376.java
@@ -0,0 +1,9 @@
+import java.util.Comparator;
+
+public class Test<T extends Test<T>> {
+ Comparator<Test<?>> bySize = Comparator.comparingInt(Test::size);
+
+ public int size() {
+ return 0;
+ }
+}
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 379e69e..ab7614c 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/newMethodRef/PotentialApplicability.java
@@ -51,9 +51,9 @@
static {
Test s1 = staticCall(Test::n0);
- Test s2 = staticCall<error descr="Ambiguous method call: both 'Test.staticCall(I1<String & Test>)' and 'Test.staticCall(I2<Test,String>)' match">(Test::n1)</error>;
- Test s3 = staticCall(<error descr="Non-static method cannot be referenced from a static context">Test::n2</error>);
+ 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="Cannot resolve method 'staticCall(<method reference>)'">(Test::n012)</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/params/MethodApplicability.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/params/MethodApplicability.java
index cd82c71..81c52a8 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/params/MethodApplicability.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lambda/params/MethodApplicability.java
@@ -14,9 +14,9 @@
void foo(K k){}
void bar() {
- foo<error descr="Ambiguous method call: both 'Foo.foo(I)' and 'Foo.foo(K)' match">((p) -> {
+ foo((p) -> {
System.out.println<error descr="Cannot resolve method 'println(<lambda parameter>)'">(p)</error>;
- })</error>;
+ });
foo((p, k) -> {
System.out.println(p);
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lossyEncoding/InconsistentLineSeparators.txt b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lossyEncoding/InconsistentLineSeparators.txt
new file mode 100644
index 0000000..1da43ef
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lossyEncoding/InconsistentLineSeparators.txt
@@ -0,0 +1,7 @@
+package temp.04
+
+class Book {
+
+ static constraints = {
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lossyEncoding/Win1251.txt b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lossyEncoding/Win1251.txt
new file mode 100644
index 0000000..95c0901
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/lossyEncoding/Win1251.txt
@@ -0,0 +1 @@
+ÆÎÏ
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/afterForInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/afterForInitializer.java
new file mode 100644
index 0000000..7e66580
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/afterForInitializer.java
@@ -0,0 +1,8 @@
+// "Assert 'container != null'" "true"
+class A{
+ void test(){
+ Integer container = null;
+ assert container != null;
+ for (int i = 0, limit = container.intValue(); i < limit; i++){}
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/beforeForInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/beforeForInitializer.java
new file mode 100644
index 0000000..d2514ec
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/beforeForInitializer.java
@@ -0,0 +1,7 @@
+// "Assert 'container != null'" "true"
+class A{
+ void test(){
+ Integer container = null;
+ for (int i = 0, limit = con<caret>tainer.intValue(); i < limit; i++){}
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflicts.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflicts.java
index 0dac8f4..84d80a1 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflicts.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflicts.java
@@ -2,6 +2,6 @@
class Test {
{
String o = "";
- Comparable<String> c = o1 -> 0;
+ Comparable<String> c = o1 -> o1.length();
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflictsEnums.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflictsEnums.java
new file mode 100644
index 0000000..22b2e3d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterComparableConflictsEnums.java
@@ -0,0 +1,21 @@
+// "Replace with lambda" "true"
+public class MyNameConflict {
+
+ {
+
+ int x = 0;
+
+ Comparable<E> c = x1 -> {
+ switch (x1) {
+ case EE:
+ break;
+ }
+ return x1.hashCode();
+ };
+ }
+
+ static enum E {
+ EE;
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflicts.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflicts.java
index f8ba6ce..ad1dc58 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflicts.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflicts.java
@@ -5,7 +5,7 @@
Comparable<String> c = new Compa<caret>rable<String>() {
@Override
public int compareTo(String o) {
- return 0;
+ return o.length();
}
};
}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflictsEnums.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflictsEnums.java
new file mode 100644
index 0000000..ce6921f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeComparableConflictsEnums.java
@@ -0,0 +1,24 @@
+// "Replace with lambda" "true"
+public class MyNameConflict {
+
+ {
+
+ int x = 0;
+
+ Comparable<E> c = new Compara<caret>ble<E>() {
+ @Override
+ public int compareTo(E x) {
+ switch (x) {
+ case EE:
+ break;
+ }
+ return x.hashCode();
+ }
+ };
+ }
+
+ static enum E {
+ EE;
+ }
+
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeLinkToNextField.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeLinkToNextField.java
new file mode 100644
index 0000000..ad1b518
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeLinkToNextField.java
@@ -0,0 +1,11 @@
+// "Replace with lambda" "false"
+class MyTest {
+ final Runnable anonymRunnable = new Run<caret>nable() {
+ @Override
+ public void run() {
+ System.out.println(o);
+ }
+ };
+
+ Object o;
+ }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15/afterPrimitiveWrappers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15/afterPrimitiveWrappers.java
new file mode 100644
index 0000000..6963121
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15/afterPrimitiveWrappers.java
@@ -0,0 +1,8 @@
+// "Cast parameter to 'long'" "true"
+class a {
+ void f(Long l) {}
+ void g() {
+ f((long) 0);
+ }
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15/beforePrimitiveWrappers.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15/beforePrimitiveWrappers.java
new file mode 100644
index 0000000..69c1bf0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15/beforePrimitiveWrappers.java
@@ -0,0 +1,8 @@
+// "Cast parameter to 'long'" "true"
+class a {
+ void f(Long l) {}
+ void g() {
+ f(<caret>0);
+ }
+}
+
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java
index 92a5cf4..d412555 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass/beforeAnonymousClassArgument.java
@@ -9,6 +9,6 @@
};
protected Foo() {
- IBar bar = anonymou<caret>s;
+ IBar bar = anonymous;
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterQualifiedNew3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterQualifiedNew3.java
new file mode 100644
index 0000000..2d90dfd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/afterQualifiedNew3.java
@@ -0,0 +1,11 @@
+// "Create Inner Class 'ArrayList'" "true"
+public class Test {
+ public static void main() {
+ new B.ArrayList();
+ }
+}
+
+class B {
+ public static class ArrayList {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeQualifiedNew3.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeQualifiedNew3.java
new file mode 100644
index 0000000..58e9a9c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createInnerClassFromNew/beforeQualifiedNew3.java
@@ -0,0 +1,8 @@
+// "Create Inner Class 'ArrayList'" "true"
+public class Test {
+ public static void main() {
+ new B.<caret>ArrayList();
+ }
+}
+
+class B {}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterMorePreciseType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterMorePreciseType.java
new file mode 100644
index 0000000..e253f05
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/afterMorePreciseType.java
@@ -0,0 +1,13 @@
+// "Create Local Variable 'foo'" "true"
+import java.util.*;
+class Test {
+ {
+ String foo<caret>;
+ new Bar(Collections.singletonList(foo));
+ }
+
+ class Bar {
+ Bar(List<String> l) {
+ }
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeMorePreciseType.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeMorePreciseType.java
new file mode 100644
index 0000000..a9387c7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/createLocalFromUsage/beforeMorePreciseType.java
@@ -0,0 +1,12 @@
+// "Create Local Variable 'foo'" "true"
+import java.util.*;
+class Test {
+ {
+ new Bar(Collections.singletonList(fo<caret>o));
+ }
+
+ class Bar {
+ Bar(List<String> l) {
+ }
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementAbstractFromNew/beforeImplementInterfaceIncomplete.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementAbstractFromNew/beforeImplementInterfaceIncomplete.java
deleted file mode 100644
index 6279236..0000000
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/implementAbstractFromNew/beforeImplementInterfaceIncomplete.java
+++ /dev/null
@@ -1,9 +0,0 @@
-// "Implement Methods" "true"
-class c {
- void foo() {
- new I<String>(<caret>
- }
-}
-interface I<T> {
- foo(T t);
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable/afterThrowsNew.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable/afterThrowsNew.java
new file mode 100644
index 0000000..2a65087
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable/afterThrowsNew.java
@@ -0,0 +1,8 @@
+// "Make 'C' extend 'java.lang.Throwable'" "true"
+
+class C extends Throwable {}
+class Main {
+ public static void main(String[] args) {
+ throw new <caret>C();
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable/beforeThrowsNew.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable/beforeThrowsNew.java
new file mode 100644
index 0000000..2dc46ca
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable/beforeThrowsNew.java
@@ -0,0 +1,8 @@
+// "Make 'C' extend 'java.lang.Throwable'" "true"
+
+class C {}
+class Main {
+ public static void main(String[] args) {
+ throw new <caret>C();
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/after5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/after5.java
index 93bc313..6bf0da8 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/after5.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/after5.java
@@ -1,4 +1,6 @@
// "Make 'victim' return 'boolean'" "true"
+import java.util.*;
+
public class External {
void m1() {
if (new Out().victim(null)) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/before5.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/before5.java
index 3c7bc2f..fb2bb3b 100644
--- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/before5.java
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/methodReturnBooleanFix/before5.java
@@ -1,4 +1,6 @@
// "Make 'victim' return 'boolean'" "true"
+import java.util.*;
+
public class External {
void m1() {
if (new Out().<caret>victim(null)) {
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterChained.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterChained.java
new file mode 100644
index 0000000..504df1b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/afterChained.java
@@ -0,0 +1,13 @@
+// "Move initializer to constructor" "true"
+class X {
+ final String s;
+ final String t;
+
+ X(String s) {
+ this.s = s;
+ t = "t";
+ }
+ X() {
+ this("s");
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeChained.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeChained.java
new file mode 100644
index 0000000..bc3ee6a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/moveInitializerToConstructor/beforeChained.java
@@ -0,0 +1,12 @@
+// "Move initializer to constructor" "true"
+class X {
+ final String s;
+ final String t = <caret>"t";
+
+ X(String s) {
+ this.s = s;
+ }
+ X() {
+ this("s");
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterNotArray.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterNotArray.java
new file mode 100644
index 0000000..1f96859
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/afterNotArray.java
@@ -0,0 +1,7 @@
+// "Split into declaration and assignment" "true"
+class Test {
+ {
+ String l;
+ l = {"foo"};
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeNotArray.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeNotArray.java
new file mode 100644
index 0000000..ad28e1c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration/beforeNotArray.java
@@ -0,0 +1,6 @@
+// "Split into declaration and assignment" "true"
+class Test {
+ {
+ String l <caret>= {"foo"};
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotations.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotations.xml
index 4d905a4..5daf0fa 100644
--- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotations.xml
+++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/p/annotations.xml
@@ -1,8 +1,8 @@
<root>
- <item name='p.TestDeannotation java.lang.String get()'>
- <annotation name='org.jetbrains.annotations.NotNull'/>
- </item>
- <item name='p.TestDeannotation1 java.lang.String get(java.lang.String) 0'>
- <annotation name='org.jetbrains.annotations.NotNull'/>
- </item>
+ <item name='p.TestDeannotation java.lang.String get()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='p.TestDeannotation1 java.lang.String get(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
</root>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotations.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotations.xml
index 0144363..d25dd2f 100644
--- a/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotations.xml
+++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/anno/suppressed/annotations.xml
@@ -1,10 +1,10 @@
<root>
- <item name='suppressed.ExistingExternalName java.lang.String foo()'>
- <annotation name='org.jetbrains.annotations.NotNull'/>
- </item>
- <item name='suppressed.SecondSuppression void second()'>
- <annotation name='java.lang.SuppressWarnings'>
- <val val="{DoesntMatterWhat}"/>
- </annotation>
- </item>
+ <item name='suppressed.ExistingExternalName java.lang.String foo()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='suppressed.SecondSuppression void second()'>
+ <annotation name='java.lang.SuppressWarnings'>
+ <val val="{DoesntMatterWhat}"/>
+ </annotation>
+ </item>
</root>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations.xml
index 36aa8d8..baa0a3a 100644
--- a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations.xml
+++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root1/multiRoot/annotations.xml
@@ -1,7 +1,7 @@
<root>
- <item name='multiRoot.Test java.lang.String get(java.lang.String) 0'>
- <annotation name='org.jetbrains.annotations.NotNull'>
- <val name="value" val=""foo""/>
- </annotation>
- </item>
+ <item name='multiRoot.Test java.lang.String get(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'>
+ <val name="value" val=""foo""/>
+ </annotation>
+ </item>
</root>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations.xml b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations.xml
index e497a6e..6061625 100644
--- a/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations.xml
+++ b/java/java-tests/testData/codeInsight/externalAnnotations/content/annoMultiRoot/root2/multiRoot/annotations.xml
@@ -1,7 +1,7 @@
<root>
- <item name='multiRoot.Test java.lang.String get(java.lang.String)'>
- <annotation name='org.jetbrains.annotations.Nullable'>
- <val name="value" val=""foo""/>
- </annotation>
- </item>
+ <item name='multiRoot.Test java.lang.String get(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.Nullable'>
+ <val name="value" val=""foo""/>
+ </annotation>
+ </item>
</root>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java b/java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java
new file mode 100644
index 0000000..5d02f2a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/folding/FoldingExceptionTest.java
@@ -0,0 +1,9 @@
+class Test {
+ int b;
+ java.util.List<String> values = new java.util.ArrayList<String>();
+
+ int getB() {
+<caret> java.util.List<String> values = new java.util.ArrayList<String>();
+ return b;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIf.java b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIf.java
new file mode 100644
index 0000000..4ab6685
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIf.java
@@ -0,0 +1,9 @@
+class Test {
+ boolean foo() {
+ return null;
+ }
+
+ void bar() {
+ <selection>foo()</selection>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIfForBoxedBooleans.java b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIfForBoxedBooleans.java
new file mode 100644
index 0000000..9516787
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIfForBoxedBooleans.java
@@ -0,0 +1,11 @@
+import java.lang.Boolean;
+
+class Test {
+ Boolean foo() {
+ return null;
+ }
+
+ void bar() {
+ <selection>foo()</selection>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIfForBoxedBooleans_after.java b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIfForBoxedBooleans_after.java
new file mode 100644
index 0000000..9c71d52
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIfForBoxedBooleans_after.java
@@ -0,0 +1,13 @@
+import java.lang.Boolean;
+
+class Test {
+ Boolean foo() {
+ return null;
+ }
+
+ void bar() {
+ if (foo()) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIf_after.java b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIf_after.java
new file mode 100644
index 0000000..f17f075
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithIf_after.java
@@ -0,0 +1,11 @@
+class Test {
+ boolean foo() {
+ return null;
+ }
+
+ void bar() {
+ if (foo()) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithNotForBoxedBooleans.java b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithNotForBoxedBooleans.java
new file mode 100644
index 0000000..9516787
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithNotForBoxedBooleans.java
@@ -0,0 +1,11 @@
+import java.lang.Boolean;
+
+class Test {
+ Boolean foo() {
+ return null;
+ }
+
+ void bar() {
+ <selection>foo()</selection>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithNotForBoxedBooleans_after.java b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithNotForBoxedBooleans_after.java
new file mode 100644
index 0000000..d2c0339
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/generation/surroundWith/java/SurroundExpressionWithNotForBoxedBooleans_after.java
@@ -0,0 +1,11 @@
+import java.lang.Boolean;
+
+class Test {
+ Boolean foo() {
+ return null;
+ }
+
+ void bar() {
+ !(foo())
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/methodFormatting.html b/java/java-tests/testData/codeInsight/javadocIG/methodFormatting.html
new file mode 100644
index 0000000..9cb6179
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/javadocIG/methodFormatting.html
@@ -0,0 +1,3 @@
+<html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b><a href="psi_element://Producer"><code>Producer</code></a></b></small><PRE><E extends <a href="psi_element://java.lang.Exception"><code>Exception</code></a>> void <b>drainTo</b>(<a href="psi_element://Consumer"><code>Consumer</code></a><? super T, E> consumer,
+ <a href="psi_element://java.lang.Object"><code>Object</code></a> someParameter)
+ throws <a href="psi_element://E"><code>E</code></a></PRE><DD><DL><DT><b>Throws:</b><DD><a href="psi_element://E"><code>E</code></a></DD></DL></DD></body></html>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/methodFormatting.java b/java/java-tests/testData/codeInsight/javadocIG/methodFormatting.java
new file mode 100644
index 0000000..a6b8124
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/javadocIG/methodFormatting.java
@@ -0,0 +1,12 @@
+interface Producer<T> {
+
+ <E extends Exception> void drainTo( Consumer<? super T, E> consumer, Object someParameter ) throws E;
+
+}
+
+interface Consumer<T, E extends Exception> {
+
+ void consume( T message ) throws E;
+
+}
+
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var03-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var03-out.java
new file mode 100644
index 0000000..7bd5541
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var03-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Object o) {
+ Foo foo = new Foo() {
+ };<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var03.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var03.java
new file mode 100644
index 0000000..8eb3580
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var03.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ new Foo() { }.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var04-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var04-out.java
new file mode 100644
index 0000000..8f1a8f3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var04-out.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ int foo = 2 + 2;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var04.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var04.java
new file mode 100644
index 0000000..45eff86
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var04.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ 2 + 2.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var05-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var05-out.java
new file mode 100644
index 0000000..d2e6b0f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var05-out.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ Foo foo = new Foo();<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var05.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var05.java
new file mode 100644
index 0000000..62d6eca
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var05.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ Foo.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var06-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var06-out.java
new file mode 100644
index 0000000..95b99fc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var06-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ unresolved.var
+ <caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var06.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var06.java
new file mode 100644
index 0000000..a3fcd98
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var06.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ unresolved.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var07-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var07-out.java
new file mode 100644
index 0000000..a38c529
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var07-out.java
@@ -0,0 +1,7 @@
+public class Foo {
+ Foo m() {
+ Foo foo = m().m();
+ foo<caret>.m();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var07.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var07.java
new file mode 100644
index 0000000..b56ec1a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var07.java
@@ -0,0 +1,6 @@
+public class Foo {
+ Foo m() {
+ m().m().<caret>.m();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var08-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var08-out.java
new file mode 100644
index 0000000..3cface4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var08-out.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ boolean foo = true && false;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var08.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var08.java
new file mode 100644
index 0000000..71127de
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var08.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ true && false.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var09-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var09-out.java
new file mode 100644
index 0000000..1a4afb6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var09-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(boolean b) {
+ boolean foo = b && false;
+ m(foo<caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var09.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var09.java
new file mode 100644
index 0000000..1f5a880
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var09.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(boolean b) {
+ m(b && false.<caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var10-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var10-out.java
new file mode 100644
index 0000000..ce3f0e3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var10-out.java
@@ -0,0 +1,5 @@
+public class Foo<T> {
+ void m() {
+ Foo<Foo> foo = new Foo<Foo>();<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var10.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var10.java
new file mode 100644
index 0000000..9553064
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var10.java
@@ -0,0 +1,5 @@
+public class Foo<T> {
+ void m() {
+ Foo<Foo>.<caret>;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var11-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var11-out.java
new file mode 100644
index 0000000..3e4614c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var11-out.java
@@ -0,0 +1,8 @@
+public class Foo {
+ Foo f;
+ Foo m() {
+ Foo foo = m().m().f;<caret>
+ m();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var11.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var11.java
new file mode 100644
index 0000000..6d7ad15
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var11.java
@@ -0,0 +1,7 @@
+public class Foo {
+ Foo f;
+ Foo m() {
+ m().m().f.<caret>m();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var12-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var12-out.java
new file mode 100644
index 0000000..9c9f813
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var12-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int foo = 1;
+ foo<caret> + 2 /* comment */; // comment2
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var12.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var12.java
new file mode 100644
index 0000000..546614b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var12.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ 1.<caret> + 2 /* comment */; // comment2
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var13-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var13-out.java
new file mode 100644
index 0000000..9fc4195
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var13-out.java
@@ -0,0 +1,8 @@
+public class Foo {
+ Foo f;
+ Foo m() {
+ Foo foo = m().m().f;<caret>
+ blah();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var13.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var13.java
new file mode 100644
index 0000000..8954cf3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var13.java
@@ -0,0 +1,7 @@
+public class Foo {
+ Foo f;
+ Foo m() {
+ m().m().f.v<caret>blah();
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var14-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var14-out.java
new file mode 100644
index 0000000..7386b39
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var14-out.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ int foo = 1;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var14.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var14.java
new file mode 100644
index 0000000..ac94b79
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var14.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ 1.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var15-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var15-out.java
new file mode 100644
index 0000000..8b3d7ad
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var15-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int foo = 2 * 2;
+ foo<caret> + 2 * 2; /* boo */
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var15.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var15.java
new file mode 100644
index 0000000..6f545ae
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var15.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ 2 * 2.<caret> + 2 * 2; /* boo */
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var16-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var16-out.java
new file mode 100644
index 0000000..0be9747
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var16-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int foo = 2;
+ int i = foo<caret> + 2 /**/ ;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var16.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var16.java
new file mode 100644
index 0000000..7139f9c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var16.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ int i = 2.<caret> + 2 /**/ ;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var17-out.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var17-out.java
new file mode 100644
index 0000000..ba80328
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var17-out.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int foo = 2 + 3;
+ int i = foo<caret> * 4; // blah
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var17.java b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var17.java
new file mode 100644
index 0000000..71fa61e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/backlog/var/var17.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ int i = 2 + 3.<caret> * 4; // blah
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/autopopupWithEnabledLiveTemplatesInCompletion.java b/java/java-tests/testData/codeInsight/template/postfix/completion/autopopupWithEnabledLiveTemplatesInCompletion.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/autopopupWithEnabledLiveTemplatesInCompletion.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowDisabledTemplate.java b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowDisabledTemplate.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowDisabledTemplate.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateIfPluginIsDisabled.java b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateIfPluginIsDisabled.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateIfPluginIsDisabled.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateIfTemplateCompletionIsDisabled.java b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateIfTemplateCompletionIsDisabled.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateIfTemplateCompletionIsDisabled.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateInInappropriateContext.java b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateInInappropriateContext.java
new file mode 100644
index 0000000..fc346a6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateInInappropriateContext.java
@@ -0,0 +1 @@
+package com.<caret>
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateOnCompletion.java b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateOnCompletion.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/doNotShowTemplateOnCompletion.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithEnter.java b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithEnter.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithEnter.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithEnter_after.java b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithEnter_after.java
new file mode 100644
index 0000000..eef0e3a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithEnter_after.java
@@ -0,0 +1,8 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().par
+
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithTab.java b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithTab.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithTab.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithTab_after.java b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithTab_after.java
new file mode 100644
index 0000000..8214c33
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/quickTypingWithTab_after.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ (new Object())
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/recalculatePrefix.java b/java/java-tests/testData/codeInsight/template/postfix/completion/recalculatePrefix.java
new file mode 100644
index 0000000..3748a11
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/recalculatePrefix.java
@@ -0,0 +1,9 @@
+public class Foo {
+ void m() {
+ new MyClass().<caret>
+ }
+
+ private class MyClass {
+ public void parents() {}
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/restartCompletionForExactMatchOnly.java b/java/java-tests/testData/codeInsight/template/postfix/completion/restartCompletionForExactMatchOnly.java
new file mode 100644
index 0000000..902e20e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/restartCompletionForExactMatchOnly.java
@@ -0,0 +1,11 @@
+public class Test {
+ public static void main(String[] args) {
+ Gray<caret>
+ }
+
+ private static class Gray {
+ public static void _2() {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/restartCompletionForExactMatchOnly_after.java b/java/java-tests/testData/codeInsight/template/postfix/completion/restartCompletionForExactMatchOnly_after.java
new file mode 100644
index 0000000..ff7a720
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/restartCompletionForExactMatchOnly_after.java
@@ -0,0 +1,11 @@
+public class Test {
+ public static void main(String[] args) {
+ Gray._2();<caret>
+ }
+
+ private static class Gray {
+ public static void _2() {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByEnter.java b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByEnter.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByEnter.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByEnter_after.java b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByEnter_after.java
new file mode 100644
index 0000000..8214c33
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByEnter_after.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ (new Object())
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByTab.java b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByTab.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByTab.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByTab_after.java b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByTab_after.java
new file mode 100644
index 0000000..8214c33
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/selectTemplateByTab_after.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ (new Object())
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/showAutoPopupForAliases.java b/java/java-tests/testData/codeInsight/template/postfix/completion/showAutoPopupForAliases.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/showAutoPopupForAliases.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/showAutoPopupForFloatLiterals.java b/java/java-tests/testData/codeInsight/template/postfix/completion/showAutoPopupForFloatLiterals.java
new file mode 100644
index 0000000..0c6a426
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/showAutoPopupForFloatLiterals.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ 10.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/showTemplateInAutoPopup.java b/java/java-tests/testData/codeInsight/template/postfix/completion/showTemplateInAutoPopup.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/showTemplateInAutoPopup.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/showTemplateOnDoubleLiteral.java b/java/java-tests/testData/codeInsight/template/postfix/completion/showTemplateOnDoubleLiteral.java
new file mode 100644
index 0000000..7528615
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/showTemplateOnDoubleLiteral.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ 1.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/completion/simpleCompletionList.java b/java/java-tests/testData/codeInsight/template/postfix/completion/simpleCompletionList.java
new file mode 100644
index 0000000..c238b76
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/completion/simpleCompletionList.java
@@ -0,0 +1,7 @@
+import java.lang.Object;
+
+public class Foo {
+ void m() {
+ new Object().<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplates.java b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplates.java
new file mode 100644
index 0000000..4f3240a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplates.java
@@ -0,0 +1,5 @@
+class A {
+ void test() {
+ true.<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplatesWithPrefix.java b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplatesWithPrefix.java
new file mode 100644
index 0000000..b98c280
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplatesWithPrefix.java
@@ -0,0 +1,5 @@
+class A {
+ void test() {
+ true.no<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplatesWithPrefix_after.java b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplatesWithPrefix_after.java
new file mode 100644
index 0000000..ebdbccd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplatesWithPrefix_after.java
@@ -0,0 +1,5 @@
+class A {
+ void test() {
+ false<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplates_after.java b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplates_after.java
new file mode 100644
index 0000000..ebdbccd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/listTemplates/listTemplates_after.java
@@ -0,0 +1,5 @@
+class A {
+ void test() {
+ false<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/booleanVariableBeforeAssignment.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/booleanVariableBeforeAssignment.java
new file mode 100644
index 0000000..8bb04c3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/booleanVariableBeforeAssignment.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(boolean b, int value) {
+ b.assert<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/booleanVariableBeforeAssignment_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/booleanVariableBeforeAssignment_after.java
new file mode 100644
index 0000000..5902129
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/booleanVariableBeforeAssignment_after.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(boolean b, int value) {
+ assert b;<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/boxedBooleanVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/boxedBooleanVariable.java
new file mode 100644
index 0000000..e1ff34e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/boxedBooleanVariable.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Boolean x) {
+ x.assert<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/boxedBooleanVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/boxedBooleanVariable_after.java
new file mode 100644
index 0000000..e79a288
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/boxedBooleanVariable_after.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Boolean x) {
+ assert x;<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceof.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceof.java
new file mode 100644
index 0000000..c77bf98
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceof.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(Object o) {
+ o instanceof String.assert<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceofBeforeReturnStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceofBeforeReturnStatement.java
new file mode 100644
index 0000000..fc6fc9f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceofBeforeReturnStatement.java
@@ -0,0 +1,10 @@
+package templates;
+
+public class Foo {
+ boolean m(Object o) {
+ if (o instanceof T1) return true;
+ o instanceof T2.assert<caret>
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceofBeforeReturnStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceofBeforeReturnStatement_after.java
new file mode 100644
index 0000000..3f774e4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceofBeforeReturnStatement_after.java
@@ -0,0 +1,10 @@
+package templates;
+
+public class Foo {
+ boolean m(Object o) {
+ if (o instanceof T1) return true;
+ assert o instanceof T2;<caret>
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceof_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceof_after.java
new file mode 100644
index 0000000..ddc4530
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/instanceof_after.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(Object o) {
+ assert o instanceof String;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/integerComparison.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/integerComparison.java
new file mode 100644
index 0000000..1076f05
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/integerComparison.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(boolean[] xs) {
+ xs.length > 0.assert<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/integerComparison_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/integerComparison_after.java
new file mode 100644
index 0000000..bd9c38a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/integerComparison_after.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(boolean[] xs) {
+ assert xs.length > 0;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/methodInvocation.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/methodInvocation.java
new file mode 100644
index 0000000..6ff5cff
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/methodInvocation.java
@@ -0,0 +1,11 @@
+package templates;
+
+public class Foo {
+ void m() {
+ bar().assert<caret>
+ }
+
+ boolean bar() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/methodInvocation_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/methodInvocation_after.java
new file mode 100644
index 0000000..b23fa93
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/methodInvocation_after.java
@@ -0,0 +1,11 @@
+package templates;
+
+public class Foo {
+ void m() {
+ assert bar();<caret>
+ }
+
+ boolean bar() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notBooleanExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notBooleanExpression.java
new file mode 100644
index 0000000..4a9880c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notBooleanExpression.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(String b, int value) {
+ b.assert<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notBooleanExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notBooleanExpression_after.java
new file mode 100644
index 0000000..4c7902d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notBooleanExpression_after.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(String b, int value) {
+ b.assert <caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notNull.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notNull.java
new file mode 100644
index 0000000..66e79c1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notNull.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(Object arg) {
+ arg != null.assert<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notNull_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notNull_after.java
new file mode 100644
index 0000000..046c217
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/notNull_after.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(Object arg) {
+ assert arg != null;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/severalConditions.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/severalConditions.java
new file mode 100644
index 0000000..628a35e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/severalConditions.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(String s) {
+ s.isEmpty() || s.contains("asas").assert<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/severalConditions_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/severalConditions_after.java
new file mode 100644
index 0000000..0a417ac
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/severalConditions_after.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(String s) {
+ assert s.isEmpty() || s.contains("asas");<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/unresolvedVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/unresolvedVariable.java
new file mode 100644
index 0000000..4e9a972
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/unresolvedVariable.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(int value) {
+ b.assert<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/assert/unresolvedVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/unresolvedVariable_after.java
new file mode 100644
index 0000000..01d7478
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/assert/unresolvedVariable_after.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(int value) {
+ b.assert <caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/cast/singleExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/singleExpression.java
new file mode 100644
index 0000000..716038e
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/singleExpression.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.cast<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/cast/singleExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/singleExpression_after.java
new file mode 100644
index 0000000..3b12c84
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/singleExpression_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ (() o)<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/cast/voidExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/voidExpression.java
new file mode 100644
index 0000000..dba8575
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/voidExpression.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ bar().cast<caret>
+ }
+
+ void bar() {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/cast/voidExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/voidExpression_after.java
new file mode 100644
index 0000000..a7dc817
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/cast/voidExpression_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ bar().cast <caret>
+ }
+
+ void bar() {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperations.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperations.java
new file mode 100644
index 0000000..87e7234
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperations.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(boolean x, boolean y, boolean z) {
+ x & y && z || x ^ y.else<caret>
+ foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperationsWithMethod.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperationsWithMethod.java
new file mode 100644
index 0000000..176dcc8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperationsWithMethod.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(boolean x, boolean y, boolean z) {
+ foo() & y & z.else<caret>
+ Type t = new Type();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperationsWithMethod_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperationsWithMethod_after.java
new file mode 100644
index 0000000..eee82ec
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperationsWithMethod_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(boolean x, boolean y, boolean z) {
+ if (!(foo() & y & z)) {
+ <caret>
+ }
+ Type t = new Type();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperations_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperations_after.java
new file mode 100644
index 0000000..050ff13
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/bitOperations_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(boolean x, boolean y, boolean z) {
+ if ((!(x & y) || !z) && !(x ^ y)) {
+ <caret>
+ }
+ foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/booleanVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/booleanVariable.java
new file mode 100644
index 0000000..21053e6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/booleanVariable.java
@@ -0,0 +1,8 @@
+package templates.
+
+public class Foo {
+ void m(boolean x) {
+ x.else<caret>
+ value = dummyAssignment;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/booleanVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/booleanVariable_after.java
new file mode 100644
index 0000000..370b905
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/booleanVariable_after.java
@@ -0,0 +1,10 @@
+package templates.
+
+public class Foo {
+ void m(boolean x) {
+ if (!x) {
+ <caret>
+ }
+ value = dummyAssignment;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/boxedBooleanVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/boxedBooleanVariable.java
new file mode 100644
index 0000000..08d1150
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/boxedBooleanVariable.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Boolean x) {
+ x.else<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/boxedBooleanVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/boxedBooleanVariable_after.java
new file mode 100644
index 0000000..11c74ed
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/boxedBooleanVariable_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(Boolean x) {
+ if (!x) {
+ <caret>
+ }
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/instanceof.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/instanceof.java
new file mode 100644
index 0000000..94c43ed
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/instanceof.java
@@ -0,0 +1,7 @@
+package completion;
+
+public class Foo {
+ void m(Object o) {
+ o instanceof String.else<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/instanceof_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/instanceof_after.java
new file mode 100644
index 0000000..b72d0d0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/instanceof_after.java
@@ -0,0 +1,9 @@
+package completion;
+
+public class Foo {
+ void m(Object o) {
+ if (!(o instanceof String)) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/integerComparison.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/integerComparison.java
new file mode 100644
index 0000000..7434a86
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/integerComparison.java
@@ -0,0 +1,6 @@
+public class Foo {
+ Foo[] xs;
+ void m() {
+ xs.length == 0.else<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/integerComparison_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/integerComparison_after.java
new file mode 100644
index 0000000..7c3c5ef
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/integerComparison_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ Foo[] xs;
+ void m() {
+ if (xs.length != 0) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/logicalOperations.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/logicalOperations.java
new file mode 100644
index 0000000..d7cc4fc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/logicalOperations.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(boolean x, boolean y, boolean z) {
+ x && y && z.else<caret>
+ value = dummyAssignment;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/logicalOperations_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/logicalOperations_after.java
new file mode 100644
index 0000000..3ea543f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/logicalOperations_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(boolean x, boolean y, boolean z) {
+ if (!x || !y || !z) {
+ <caret>
+ }
+ value = dummyAssignment;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/notNull.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/notNull.java
new file mode 100644
index 0000000..2d4f9b7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/notNull.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o != null.else<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/notNull_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/notNull_after.java
new file mode 100644
index 0000000..68bc4d6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/notNull_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ if (o == null) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/unresolvedVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/unresolvedVariable.java
new file mode 100644
index 0000000..e86f073
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/unresolvedVariable.java
@@ -0,0 +1,8 @@
+package templates.
+
+public class Foo {
+ void m() {
+ x.else<caret>
+ value = dummyAssignment;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/else/unresolvedVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/else/unresolvedVariable_after.java
new file mode 100644
index 0000000..90af0e2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/else/unresolvedVariable_after.java
@@ -0,0 +1,8 @@
+package templates.
+
+public class Foo {
+ void m() {
+ x.else <caret>
+ value = dummyAssignment;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/field/foo.java b/java/java-tests/testData/codeInsight/template/postfix/templates/field/foo.java
new file mode 100644
index 0000000..16e74b8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/field/foo.java
@@ -0,0 +1,5 @@
+public class Foo {
+ public void bar(Foo arg) {
+ arg.field<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/field/foo_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/field/foo_after.java
new file mode 100644
index 0000000..ca78b61
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/field/foo_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ private Foo foo;
+
+ public void bar(Foo arg) {
+ foo = arg;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/field/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/field/simple.java
new file mode 100644
index 0000000..9dd7ace
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/field/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ public Foo(int arg) {
+ arg.field<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/field/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/field/simple_after.java
new file mode 100644
index 0000000..5a99373
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/field/simple_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ private int foo;
+
+ public Foo(int arg) {
+ foo = arg;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/for/ints.java b/java/java-tests/testData/codeInsight/template/postfix/templates/for/ints.java
new file mode 100644
index 0000000..4516e79
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/for/ints.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int[] xs = {1, 2, 3};
+ xs.for<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/for/ints_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/for/ints_after.java
new file mode 100644
index 0000000..de1f9ba
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/for/ints_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ int[] xs = {1, 2, 3};
+ for (int x : xs) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedByteNumber.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedByteNumber.java
new file mode 100644
index 0000000..4e19541
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedByteNumber.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ Byte foo = 100;
+ foo.fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedByteNumber_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedByteNumber_after.java
new file mode 100644
index 0000000..7957666
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedByteNumber_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ Byte foo = 100;
+ for (Byte i = 0; i < foo; i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedIntegerArray.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedIntegerArray.java
new file mode 100644
index 0000000..de054bb
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedIntegerArray.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ Integer[] xs = {1, 2, 3};
+ xs.fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedIntegerArray_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedIntegerArray_after.java
new file mode 100644
index 0000000..ef1bb97
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedIntegerArray_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ Integer[] xs = {1, 2, 3};
+ for (int i = 0; i < xs.length; i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedLongArray.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedLongArray.java
new file mode 100644
index 0000000..78789d3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedLongArray.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ Long[] xs = {1, 2, 3};
+ xs.fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedLongArray_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedLongArray_after.java
new file mode 100644
index 0000000..fb7da6a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/boxedLongArray_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ Long[] xs = {1, 2, 3};
+ for (int i = 0; i < xs.length; i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/byteNumber.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/byteNumber.java
new file mode 100644
index 0000000..8245757
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/byteNumber.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ byte foo = 100;
+ foo.fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/byteNumber_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/byteNumber_after.java
new file mode 100644
index 0000000..db5a610
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/byteNumber_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ byte foo = 100;
+ for (byte i = 0; i < foo; i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/collection.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/collection.java
new file mode 100644
index 0000000..8a7dcef
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/collection.java
@@ -0,0 +1,7 @@
+import java.util.ArrayList;
+
+public class Foo {
+ void m() {
+ new ArrayList().fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/collection_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/collection_after.java
new file mode 100644
index 0000000..a25108f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/collection_after.java
@@ -0,0 +1,9 @@
+import java.util.ArrayList;
+
+public class Foo {
+ void m() {
+ for (int i = 0; i < new ArrayList().size(); i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intArray.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intArray.java
new file mode 100644
index 0000000..9811f72
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intArray.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int[] xs = {1, 2, 3};
+ xs.fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intArray_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intArray_after.java
new file mode 100644
index 0000000..e565a5a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intArray_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ int[] xs = {1, 2, 3};
+ for (int i = 0; i < xs.length; i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intNumber.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intNumber.java
new file mode 100644
index 0000000..c29d12c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intNumber.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int foo = 100;
+ foo.fori<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intNumber_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intNumber_after.java
new file mode 100644
index 0000000..8dc1bf5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/fori/intNumber_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ int foo = 100;
+ for (int i = 0; i < foo; i++) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedIntegerArray.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedIntegerArray.java
new file mode 100644
index 0000000..0b06bdf
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedIntegerArray.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ Integer[] xs = {1, 2, 3};
+ xs.forr<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedIntegerArray_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedIntegerArray_after.java
new file mode 100644
index 0000000..8a24f7c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedIntegerArray_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ Integer[] xs = {1, 2, 3};
+ for (int i = xs.length - 1; i >= 0; i--) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedLongArray.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedLongArray.java
new file mode 100644
index 0000000..2255d95
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedLongArray.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ Long[] xs = {1, 2, 3};
+ xs.forr<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedLongArray_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedLongArray_after.java
new file mode 100644
index 0000000..551f440
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/boxedLongArray_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ Long[] xs = {1, 2, 3};
+ for (int i = xs.length - 1; i >= 0; i--) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/byteNumber.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/byteNumber.java
new file mode 100644
index 0000000..9ca9fbc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/byteNumber.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ byte foo = 100;
+ foo.forr<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/byteNumber_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/byteNumber_after.java
new file mode 100644
index 0000000..702ba10
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/byteNumber_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ byte foo = 100;
+ for (byte b = foo; b > 0; b--) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/intArray.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/intArray.java
new file mode 100644
index 0000000..1aac1ce
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/intArray.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m() {
+ int[] xs = {1, 2, 3};
+ xs.forr<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/forr/intArray_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/intArray_after.java
new file mode 100644
index 0000000..d04a438
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/forr/intArray_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m() {
+ int[] xs = {1, 2, 3};
+ for (int i = xs.length - 1; i >= 0; i--) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/booleanVariableBeforeAssignment.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/booleanVariableBeforeAssignment.java
new file mode 100644
index 0000000..2f56d81
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/booleanVariableBeforeAssignment.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(boolean b, int value) {
+ b.if<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/booleanVariableBeforeAssignment_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/booleanVariableBeforeAssignment_after.java
new file mode 100644
index 0000000..6a098d6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/booleanVariableBeforeAssignment_after.java
@@ -0,0 +1,10 @@
+package templates;
+
+public class Foo {
+ void m(boolean b, int value) {
+ if (b) {
+ <caret>
+ }
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/boxedBooleanVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/boxedBooleanVariable.java
new file mode 100644
index 0000000..f68683b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/boxedBooleanVariable.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Boolean x) {
+ x.if<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/boxedBooleanVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/boxedBooleanVariable_after.java
new file mode 100644
index 0000000..9a77299
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/boxedBooleanVariable_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(Boolean x) {
+ if (x) {
+ <caret>
+ }
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceof.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceof.java
new file mode 100644
index 0000000..f66dda3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceof.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(Object o) {
+ o instanceof String.if<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceofBeforeReturnStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceofBeforeReturnStatement.java
new file mode 100644
index 0000000..c96a8bd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceofBeforeReturnStatement.java
@@ -0,0 +1,10 @@
+package templates;
+
+public class Foo {
+ boolean m(Object o) {
+ if (o instanceof T1) return true;
+ o instanceof T2.if<caret>
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceofBeforeReturnStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceofBeforeReturnStatement_after.java
new file mode 100644
index 0000000..2cdba65
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceofBeforeReturnStatement_after.java
@@ -0,0 +1,12 @@
+package templates;
+
+public class Foo {
+ boolean m(Object o) {
+ if (o instanceof T1) return true;
+ if (o instanceof T2) {
+ <caret>
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceof_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceof_after.java
new file mode 100644
index 0000000..ed7bc9d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/instanceof_after.java
@@ -0,0 +1,9 @@
+package templates;
+
+public class Foo {
+ void m(Object o) {
+ if (o instanceof String) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/integerComparison.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/integerComparison.java
new file mode 100644
index 0000000..22bf79a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/integerComparison.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(boolean[] xs) {
+ xs.length > 0.if<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/integerComparison_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/integerComparison_after.java
new file mode 100644
index 0000000..563f56f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/integerComparison_after.java
@@ -0,0 +1,9 @@
+package templates;
+
+public class Foo {
+ void m(boolean[] xs) {
+ if (xs.length > 0) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/methodInvocation.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/methodInvocation.java
new file mode 100644
index 0000000..6331814
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/methodInvocation.java
@@ -0,0 +1,11 @@
+package templates;
+
+public class Foo {
+ void m() {
+ bar().if<caret>
+ }
+
+ boolean bar() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/methodInvocation_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/methodInvocation_after.java
new file mode 100644
index 0000000..6597208
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/methodInvocation_after.java
@@ -0,0 +1,13 @@
+package templates;
+
+public class Foo {
+ void m() {
+ if (bar()) {
+ <caret>
+ }
+ }
+
+ boolean bar() {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/notBooleanExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/notBooleanExpression.java
new file mode 100644
index 0000000..3b58506
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/notBooleanExpression.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(String b, int value) {
+ b.if<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/notBooleanExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/notBooleanExpression_after.java
new file mode 100644
index 0000000..c5af1f0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/notBooleanExpression_after.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(String b, int value) {
+ b.if <caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/severalConditions.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/severalConditions.java
new file mode 100644
index 0000000..755375a
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/severalConditions.java
@@ -0,0 +1,7 @@
+package templates;
+
+public class Foo {
+ void m(String s) {
+ s.isEmpty() || s.contains("asas").if<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/severalConditions_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/severalConditions_after.java
new file mode 100644
index 0000000..a661c98
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/severalConditions_after.java
@@ -0,0 +1,9 @@
+package templates;
+
+public class Foo {
+ void m(String s) {
+ if (s.isEmpty() || s.contains("asas")) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/unresolvedVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/unresolvedVariable.java
new file mode 100644
index 0000000..27af644
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/unresolvedVariable.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(int value) {
+ b.if<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/if/unresolvedVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/if/unresolvedVariable_after.java
new file mode 100644
index 0000000..ca1b32d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/if/unresolvedVariable_after.java
@@ -0,0 +1,8 @@
+package templates;
+
+public class Foo {
+ void m(int value) {
+ b.if <caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/alias.java b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/alias.java
new file mode 100644
index 0000000..c91403b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/alias.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.inst<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/alias_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/alias_after.java
new file mode 100644
index 0000000..c3798e0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/alias_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o instanceof ? (() o)<caret> : null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpression.java
new file mode 100644
index 0000000..0558a62
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpression.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.instanceof<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpressionTemplate.java b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpressionTemplate.java
new file mode 100644
index 0000000..0558a62
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpressionTemplate.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.instanceof<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpressionTemplate_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpressionTemplate_after.java
new file mode 100644
index 0000000..b7979dd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpressionTemplate_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o instanceof Integer ? ((Integer) o)<caret> : null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpression_after.java
new file mode 100644
index 0000000..c3798e0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/instanceof/singleExpression_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o instanceof ? (() o)<caret> : null;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01.java
new file mode 100644
index 0000000..220f385
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ Foo.new<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java
new file mode 100644
index 0000000..6e5cbcd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new01_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ new Foo();<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java
new file mode 100644
index 0000000..3a79f1b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02.java
@@ -0,0 +1,5 @@
+public class Foo<T> {
+ void m() {
+ Foo<Integer>.new<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java
new file mode 100644
index 0000000..ea6b652
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new02_after.java
@@ -0,0 +1,5 @@
+public class Foo<T> {
+ void m() {
+ new Foo<Integer>();<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java
new file mode 100644
index 0000000..1d13ef1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03.java
@@ -0,0 +1,5 @@
+public abstract class Foo<T, U> {
+ void m() {
+ Foo<Integer, U>.new<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java
new file mode 100644
index 0000000..b6f938b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new03_after.java
@@ -0,0 +1,6 @@
+public abstract class Foo<T, U> {
+ void m() {
+ new Foo<Integer, U>() {<caret>
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04.java
new file mode 100644
index 0000000..21c2336
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04.java
@@ -0,0 +1,10 @@
+public abstract class Foo {
+ void m() {
+ Foo.new<caret>
+ }
+}
+
+class FooBar1 { private FooBar1() { } }
+class FooBar2 { private FooBar2(int x) { } }
+class FooBar3 { public FooBar3(int x) { } private FooBar3() { } }
+class FooBar4 { private FooBar4(int x) { } public FooBar4() { } }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java
new file mode 100644
index 0000000..838fa7b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new04_after.java
@@ -0,0 +1,11 @@
+public abstract class Foo {
+ void m() {
+ new Foo() {<caret>
+ };
+ }
+}
+
+class FooBar1 { private FooBar1() { } }
+class FooBar2 { private FooBar2(int x) { } }
+class FooBar3 { public FooBar3(int x) { } private FooBar3() { } }
+class FooBar4 { private FooBar4(int x) { } public FooBar4() { } }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05.java
new file mode 100644
index 0000000..113e7be
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05.java
@@ -0,0 +1,7 @@
+public class Foo {
+ public Foo(int x) { }
+ void m() {
+ Foo.new<caret>
+ Bar a = new Bar();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java
new file mode 100644
index 0000000..5a46dc4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new05_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ public Foo(int x) { }
+ void m() {
+ new Foo(<caret>);
+ Bar a = new Bar();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new06.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new06.java
new file mode 100644
index 0000000..5c0ec30
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new06.java
@@ -0,0 +1,7 @@
+public class Foo {
+ public Foo() { }
+ void m() {
+ Foo.new<caret>
+ _a = new Bar();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new06_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new06_after.java
new file mode 100644
index 0000000..43b01e4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new06_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ public Foo() { }
+ void m() {
+ new Foo()<caret>;
+ _a = new Bar();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07.java
new file mode 100644
index 0000000..f70629d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07.java
@@ -0,0 +1,10 @@
+public class Foo {
+ void m() {
+ IFoo.new<caret>
+ f();
+ }
+}
+
+interface IFoo {
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java
new file mode 100644
index 0000000..1d97581
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new07_after.java
@@ -0,0 +1,11 @@
+public class Foo {
+ void m() {
+ new IFoo() {<caret>
+ };
+ f();
+ }
+}
+
+interface IFoo {
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08.java
new file mode 100644
index 0000000..217342b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08.java
@@ -0,0 +1,6 @@
+public abstract class Foo {
+ void m() {
+ FooBar.new<caret>
+ }
+ class FooBar { private FooBar(int x) { } }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java
new file mode 100644
index 0000000..9982ebf
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/new08_after.java
@@ -0,0 +1,6 @@
+public abstract class Foo {
+ void m() {
+ new FooBar(<caret>);
+ }
+ class FooBar { private FooBar(int x) { } }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression.java
new file mode 100644
index 0000000..b8dcc5f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ Foo variable = Foo.new<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java
new file mode 100644
index 0000000..e0f83fc
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/new/newOnAssignExpression_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ Foo variable = new Foo();<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/boxedBoolean.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/boxedBoolean.java
new file mode 100644
index 0000000..802c112
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/boxedBoolean.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Boolean a) {
+ a.not<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/boxedBoolean_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/boxedBoolean_after.java
new file mode 100644
index 0000000..887d958
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/boxedBoolean_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Boolean a) {
+ !a<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/complexCondition.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/complexCondition.java
new file mode 100644
index 0000000..4f4d174
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/complexCondition.java
@@ -0,0 +1,8 @@
+public class Foo {
+ Foo[] xs;
+ void m() {
+ if (xs.length == 0.not<caret>) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/complexCondition_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/complexCondition_after.java
new file mode 100644
index 0000000..bd9f97b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/complexCondition_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ Foo[] xs;
+ void m() {
+ if (xs.length != 0<caret>) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/exclamation.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/exclamation.java
new file mode 100644
index 0000000..1706898
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/exclamation.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(boolean b) {
+ m(b!<caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/exclamation_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/exclamation_after.java
new file mode 100644
index 0000000..107fdd2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/exclamation_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(boolean b) {
+ m(!b<caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/negation.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/negation.java
new file mode 100644
index 0000000..00232ca
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/negation.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(boolean b) {
+ if (!b.<caret>) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/negation_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/negation_after.java
new file mode 100644
index 0000000..3b12cae
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/negation_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(boolean b) {
+ if (b<caret>) {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/simple.java
new file mode 100644
index 0000000..aeecd67
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(boolean b) {
+ m(b.not<caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/not/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/not/simple_after.java
new file mode 100644
index 0000000..107fdd2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/not/simple_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(boolean b) {
+ m(!b<caret>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/nn.java b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/nn.java
new file mode 100644
index 0000000..1a28397
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/nn.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.nn<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/nn_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/nn_after.java
new file mode 100644
index 0000000..462dc48
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/nn_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ if (o != null) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/secondStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/secondStatement.java
new file mode 100644
index 0000000..b560ff7
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/secondStatement.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Object o) {
+ o.notnull<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/secondStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/secondStatement_after.java
new file mode 100644
index 0000000..5469cef
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/secondStatement_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(Object o) {
+ if (o != null) {
+ <caret>
+ }
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/simple.java
new file mode 100644
index 0000000..b5d7fd8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.notnull<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/simple_after.java
new file mode 100644
index 0000000..462dc48
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/notnull/simple_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ if (o != null) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/secondStatement.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/secondStatement.java
new file mode 100644
index 0000000..94eba24
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/secondStatement.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Object o) {
+ o.null<caret>
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/secondStatement_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/secondStatement_after.java
new file mode 100644
index 0000000..f1ea3b5
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/secondStatement_after.java
@@ -0,0 +1,8 @@
+public class Foo {
+ void m(Object o) {
+ if (o == null) {
+ <caret>
+ }
+ value = 123;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/simple.java
new file mode 100644
index 0000000..2b78407
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.null<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/null/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/null/simple_after.java
new file mode 100644
index 0000000..68bc4d6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/null/simple_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ if (o == null) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/par/extra.java b/java/java-tests/testData/codeInsight/template/postfix/templates/par/extra.java
new file mode 100644
index 0000000..822b4ae
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/par/extra.java
@@ -0,0 +1,7 @@
+package templates.par;
+
+public class Foo {
+ void m(Object o) {
+ (10).par<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/par/extra_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/par/extra_after.java
new file mode 100644
index 0000000..ebf8b2d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/par/extra_after.java
@@ -0,0 +1,7 @@
+package templates.par;
+
+public class Foo {
+ void m(Object o) {
+ ((10))<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/par/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/par/simple.java
new file mode 100644
index 0000000..eabb698
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/par/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ 10.par<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/par/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/par/simple_after.java
new file mode 100644
index 0000000..72fd3d9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/par/simple_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ (10)<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite.java b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite.java
new file mode 100644
index 0000000..319c5a9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(int x) {
+ x + 1.return<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite2.java b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite2.java
new file mode 100644
index 0000000..e368d75
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite2.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f() {
+ 42 + 1 + 2.return<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite2_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite2_after.java
new file mode 100644
index 0000000..fb1236d
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite2_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f() {
+ return 42 + 1 + 2;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite_after.java
new file mode 100644
index 0000000..51dce73
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/return/composite_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(int x) {
+ return x + 1;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/return/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/return/simple.java
new file mode 100644
index 0000000..de438ea
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/return/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(int x) {
+ x.return<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/return/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/return/simple_after.java
new file mode 100644
index 0000000..92d209c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/return/simple_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(int x) {
+ return x;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/byte.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/byte.java
new file mode 100644
index 0000000..aacf7f9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/byte.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(byte x) {
+ x.switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/byte_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/byte_after.java
new file mode 100644
index 0000000..b493158
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/byte_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ int f(byte x) {
+ switch (x) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/char.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/char.java
new file mode 100644
index 0000000..1134571
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/char.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(char x) {
+ x.switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/char_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/char_after.java
new file mode 100644
index 0000000..a2331c3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/char_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ int f(char x) {
+ switch (x) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/composite.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/composite.java
new file mode 100644
index 0000000..630a5f6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/composite.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m() {
+ 42 + 42.switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/composite_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/composite_after.java
new file mode 100644
index 0000000..338ec75
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/composite_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m() {
+ switch (42 + 42) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/enum.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/enum.java
new file mode 100644
index 0000000..886a0ad
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/enum.java
@@ -0,0 +1,7 @@
+public enum Foo {
+ A, B, C;
+
+ void f(Foo foo) {
+ foo.switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/enum_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/enum_after.java
new file mode 100644
index 0000000..d699088
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/enum_after.java
@@ -0,0 +1,9 @@
+public enum Foo {
+ A, B, C;
+
+ void f(Foo foo) {
+ switch (foo) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/int.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/int.java
new file mode 100644
index 0000000..15d7e1b
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/int.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(int x) {
+ x.switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/int_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/int_after.java
new file mode 100644
index 0000000..02de617
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/int_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ int f(int x) {
+ switch (x) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/short.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/short.java
new file mode 100644
index 0000000..147f3fd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/short.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f(short x) {
+ x.switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/short_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/short_after.java
new file mode 100644
index 0000000..116d170
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/short_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ int f(short x) {
+ switch (x) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/string.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/string.java
new file mode 100644
index 0000000..75ea1a2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/string.java
@@ -0,0 +1,5 @@
+public class Foo {
+ int f() {
+ "abc".switch<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/switch/string_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/string_after.java
new file mode 100644
index 0000000..1b6571f
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/switch/string_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ int f() {
+ switch ("abc") {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/synchronized/object.java b/java/java-tests/testData/codeInsight/template/postfix/templates/synchronized/object.java
new file mode 100644
index 0000000..9a202bf
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/synchronized/object.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.synchronized<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/synchronized/object_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/synchronized/object_after.java
new file mode 100644
index 0000000..5e8563c
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/synchronized/object_after.java
@@ -0,0 +1,7 @@
+public class Foo {
+ void m(Object o) {
+ synchronized (o) {
+ <caret>
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/throw/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/throw/simple.java
new file mode 100644
index 0000000..edfbaab
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/throw/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o.throw<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/throw/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/throw/simple_after.java
new file mode 100644
index 0000000..900e720
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/throw/simple_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ throw o;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/var/add.java b/java/java-tests/testData/codeInsight/template/postfix/templates/var/add.java
new file mode 100644
index 0000000..39f4af9
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/var/add.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ 1.var<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/var/add_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/var/add_after.java
new file mode 100644
index 0000000..05f95bd
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/var/add_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ int foo = 1;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/var/simple.java b/java/java-tests/testData/codeInsight/template/postfix/templates/var/simple.java
new file mode 100644
index 0000000..837de82
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/var/simple.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ o instanceof String.var<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/var/simple_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/var/simple_after.java
new file mode 100644
index 0000000..3922fc4
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/var/simple_after.java
@@ -0,0 +1,5 @@
+public class Foo {
+ void m(Object o) {
+ boolean foo = o instanceof String;<caret>
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/booleanVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/booleanVariable.java
new file mode 100644
index 0000000..211ab99
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/booleanVariable.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(boolean x) {
+ x.while<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/booleanVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/booleanVariable_after.java
new file mode 100644
index 0000000..21c8695
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/booleanVariable_after.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(boolean x) {
+ while (x)<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/boxedBooleanVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/boxedBooleanVariable.java
new file mode 100644
index 0000000..beb2807
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/boxedBooleanVariable.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Boolean x) {
+ x.while<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/boxedBooleanVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/boxedBooleanVariable_after.java
new file mode 100644
index 0000000..e0c4194
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/boxedBooleanVariable_after.java
@@ -0,0 +1,6 @@
+public class Foo {
+ void m(Boolean x) {
+ while (x)<caret>
+ return;
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/stringVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/stringVariable.java
new file mode 100644
index 0000000..8b93251
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/stringVariable.java
@@ -0,0 +1,7 @@
+package templates.
+
+public class Foo {
+ void m(String x) {
+ x.while<caret>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/stringVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/stringVariable_after.java
new file mode 100644
index 0000000..2d6a7a0
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/stringVariable_after.java
@@ -0,0 +1,7 @@
+package templates.
+
+public class Foo {
+ void m(String x) {
+ x.while <caret>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/unresolvedVariable.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/unresolvedVariable.java
new file mode 100644
index 0000000..5e9cd77
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/unresolvedVariable.java
@@ -0,0 +1,7 @@
+package templates.
+
+public class Foo {
+ void m() {
+ x.while<caret>
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/template/postfix/templates/while/unresolvedVariable_after.java b/java/java-tests/testData/codeInsight/template/postfix/templates/while/unresolvedVariable_after.java
new file mode 100644
index 0000000..6e469c2
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/template/postfix/templates/while/unresolvedVariable_after.java
@@ -0,0 +1,7 @@
+package templates.
+
+public class Foo {
+ void m() {
+ x.while <caret>
+ }
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/caseAndNpe/expected.xml b/java/java-tests/testData/inspection/dataFlow/caseAndNpe/expected.xml
index a83ef7b..184e6c5 100644
--- a/java/java-tests/testData/inspection/dataFlow/caseAndNpe/expected.xml
+++ b/java/java-tests/testData/inspection/dataFlow/caseAndNpe/expected.xml
@@ -20,5 +20,10 @@
<line>49</line>
<description>Switch label 'case 2:' is unreachable</description>
</problem>
+ <problem>
+ <file>CaseAndNpe.java</file>
+ <line>80</line>
+ <description>Condition is always true</description>
+ </problem>
</problems>
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/AndEquals.java b/java/java-tests/testData/inspection/dataFlow/fixture/AndEquals.java
new file mode 100644
index 0000000..068c494
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/AndEquals.java
@@ -0,0 +1,11 @@
+import java.util.List;
+
+class Some {
+ public static void appendTokenTypes(StringBuilder sb, List<String> tokenTypes) {
+ for (int count = 0, line = 0, size = tokenTypes.size(); count < size; count++) {
+ boolean newLine = count == 2 || <warning descr="Condition 'line > 0' is always 'false' when reached">line > 0</warning> && (count - 2) % 6 == 0;
+ newLine &= (size - count) > 2;
+ }
+ }
+
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ContractSeveralClauses.java b/java/java-tests/testData/inspection/dataFlow/fixture/ContractSeveralClauses.java
index 554e979..f201cf4 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/ContractSeveralClauses.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ContractSeveralClauses.java
@@ -1,4 +1,5 @@
import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nullable;
public class Foo {
@@ -6,8 +7,21 @@
return escapeStr(s, escaper);
}
+ String foo2(Object escaper, @Nullable String s) {
+ return <warning descr="Expression 'escapeStr(s, escaper)' might evaluate to null but is returned by the method which is not declared as @Nullable">escapeStr(s, escaper)</warning>;
+ }
+
+ void foo3(@Nullable String s) {
+ foo2(this, escapeStr(s));
+ }
+
@Contract("null,_->null;!null,_->!null")
String escapeStr(String s, Object o) {
return s;
}
+
+ @Contract("null->null;!null->!null")
+ String escapeStr(String s) {
+ return s;
+ }
}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNullable.java b/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNullable.java
index 99cee25..47ce7fc 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNullable.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ContractWithNullable.java
@@ -12,5 +12,32 @@
@Nullable
Object foo(Object a) { return a; }
+ @NotNull
+ Object notNull() {
+ return <warning descr="Expression 'nullable(false)' might evaluate to null but is returned by the method declared as @NotNull">nullable(false)</warning>;
+ }
+
+ @NotNull
+ Object notNull2() {
+ return <warning descr="Expression 'nullable2(false)' might evaluate to null but is returned by the method declared as @NotNull">nullable2(false)</warning>;
+ }
+
+ @Nullable
+ @Contract("true -> !null")
+ Object nullable(boolean notNull) {
+ return notNull ? "" : anotherNullable();
+ }
+
+ @Nullable
+ @Contract("true -> !null; _->_")
+ Object nullable2(boolean notNull) {
+ return notNull ? "" : anotherNullable();
+ }
+
+ @Nullable
+ Object anotherNullable() {
+ return null;
+ }
+
}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/DontLoseInequalityInformation.java b/java/java-tests/testData/inspection/dataFlow/fixture/DontLoseInequalityInformation.java
new file mode 100644
index 0000000..14fcdff
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/DontLoseInequalityInformation.java
@@ -0,0 +1,13 @@
+class Some {
+ public static void main(int i) {
+ if (i != 0) {
+ if (i == 1 || i == 2 || i == 3) {
+ System.out.println("hello");
+ }
+ if (<warning descr="Condition 'i == 0' is always 'false'">i == 0</warning>) {
+ System.out.println("wat?");
+ }
+ }
+ }
+
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/DontMakeUnrelatedVariableFalseWhenMerging.java b/java/java-tests/testData/inspection/dataFlow/fixture/DontMakeUnrelatedVariableFalseWhenMerging.java
new file mode 100644
index 0000000..858cd00
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/DontMakeUnrelatedVariableFalseWhenMerging.java
@@ -0,0 +1,26 @@
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+
+class Some {
+ void foo(String[] args) {
+ boolean b = false;
+
+ if (hashCode() == 2) {
+ b = new File("a").exists();
+ }
+
+ boolean b2 = hashCode() == 4;
+ if (!b2) {
+ return;
+ }
+
+ if (b) {
+
+ }
+
+ if (b) {
+
+ }
+ }
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/DontMakeUnrelatedVariableNotNullWhenMerging.java b/java/java-tests/testData/inspection/dataFlow/fixture/DontMakeUnrelatedVariableNotNullWhenMerging.java
new file mode 100644
index 0000000..8e995dc
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/DontMakeUnrelatedVariableNotNullWhenMerging.java
@@ -0,0 +1,14 @@
+import org.jetbrains.annotations.Nullable;
+
+class Some {
+ public static void main(String arg, @Nullable StringBuilder sb) {
+ if (arg != null) {
+ return;
+ }
+
+ if (sb != null) { }
+
+ if (sb != null) { }
+ }
+
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/EqualsImpliesNotNull.java b/java/java-tests/testData/inspection/dataFlow/fixture/EqualsImpliesNotNull.java
index 4327644..b2d6bf6 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/EqualsImpliesNotNull.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/EqualsImpliesNotNull.java
@@ -21,4 +21,15 @@
System.out.println(<warning descr="Method invocation 'parentNode.toString()' may produce 'java.lang.NullPointerException'">parentNode.toString()</warning>);
}
+ public static int foo(String a, String b) {
+ if (a.equals(b.startsWith("a") ? b : "")) {
+ return 0;
+ }
+ return a.length();
+ }
+
+ static boolean isEmpty(String s) {
+ return s.length() == 0;
+ }
+
}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/LocalClass.java b/java/java-tests/testData/inspection/dataFlow/fixture/LocalClass.java
index 76196ec..b991cbf 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/LocalClass.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/LocalClass.java
@@ -13,5 +13,10 @@
}
}
}
+ class Local {
+ void s(@Nullable String s) {
+ final int i = <warning descr="Method invocation 's.hashCode()' may produce 'java.lang.NullPointerException'">s.hashCode()</warning>;
+ }
+ }
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/LongDisjunctionsNotComplex.java b/java/java-tests/testData/inspection/dataFlow/fixture/LongDisjunctionsNotComplex.java
index affd67c..c816a50 100644
--- a/java/java-tests/testData/inspection/dataFlow/fixture/LongDisjunctionsNotComplex.java
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/LongDisjunctionsNotComplex.java
@@ -1,5 +1,8 @@
class Some {
void getName(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10) {
+ if (i1 == 0 || i2 == 0 || i3 == 0 || i4 == 0 || i5 == 0 || i6 == 0 || i7 == 0 || i8 == 0 || i9 == 0 || i10 == 0) {
+ return;
+ }
if (i1 == 1 ||
i1 == 2 ||
i1 == 3 ||
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/NotEqualsTypo.java b/java/java-tests/testData/inspection/dataFlow/fixture/NotEqualsTypo.java
new file mode 100644
index 0000000..17413dd
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/NotEqualsTypo.java
@@ -0,0 +1,12 @@
+class Some {
+ boolean foo(Object first, Object second) {
+ boolean isEqual = true;
+
+ if (<error descr="Operator '||' cannot be applied to 'boolean', 'java.lang.Object'">first != null || second</error> -= null) {
+ return isEqual;
+ }
+
+ return isEqual;
+ }
+
+}
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/OptionalThis.java b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalThis.java
new file mode 100644
index 0000000..4e8547d
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/OptionalThis.java
@@ -0,0 +1,46 @@
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class TestInspection {
+
+ private static class StringWrapper {
+ private String inner = null;
+
+ @Nullable
+ public String getString() {
+ return inner;
+ }
+ }
+
+ @NotNull
+ private final StringWrapper wrapper;
+
+ @Nullable
+ private String string = null;
+
+ public TestInspection() {
+ wrapper = new StringWrapper();
+ }
+
+ public void doTest() {
+ if (this.wrapper.getString() != null) {
+ doSomething(this.wrapper.getString());
+ }
+ if (this.wrapper.getString() != null) {
+ doSomething(wrapper.getString());
+ }
+ if (wrapper.getString() != null) {
+ doSomething(this.wrapper.getString());
+ }
+ if (wrapper.getString() != null) {
+ doSomething(wrapper.getString());
+ }
+ if (this.string != null) {
+ doSomething(this.string);
+ }
+ }
+
+ private void doSomething(@NotNull String s) {
+ //...
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java b/java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java
new file mode 100644
index 0000000..7dc2e51
--- /dev/null
+++ b/java/java-tests/testData/inspection/dataFlow/fixture/ParametersAreNonnullByDefault.java
@@ -0,0 +1,25 @@
+import foo.*;
+
+class Some {
+ void foo() {
+ NotNullClass.foo(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
+ NotNullClass.foo("a");
+
+ NullableClass.foo(null);
+ NullableClass.foo("a");
+
+ AnotherPackageNotNull.foo(<warning descr="Passing 'null' argument to parameter annotated as @NotNull">null</warning>);
+ AnotherPackageNotNull.foo("a");
+ }
+
+}
+
+@javax.annotation.ParametersAreNonnullByDefault
+class NotNullClass {
+ static void foo(String s) {}
+
+}
+@javax.annotation.ParametersAreNullableByDefault
+class NullableClass {
+ static void foo(String s) {}
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/defaultFileTemplateUsage/defaultFile/src/x/X3.java b/java/java-tests/testData/inspection/defaultFileTemplateUsage/defaultFile/src/x/X3.java
new file mode 100644
index 0000000..c50dafa
--- /dev/null
+++ b/java/java-tests/testData/inspection/defaultFileTemplateUsage/defaultFile/src/x/X3.java
@@ -0,0 +1,9 @@
+package x;
+import java.io.*;
+
+/**
+ * Created by Alexey on 02.12.2005.
+ * This class represents something important.
+ */
+public class X2 {
+}
diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/staticQualifiedFieldAccessForWriting/expected.xml b/java/java-tests/testData/inspection/fieldCanBeLocal/staticQualifiedFieldAccessForWriting/expected.xml
new file mode 100644
index 0000000..580a889
--- /dev/null
+++ b/java/java-tests/testData/inspection/fieldCanBeLocal/staticQualifiedFieldAccessForWriting/expected.xml
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+</problems>
diff --git a/java/java-tests/testData/inspection/fieldCanBeLocal/staticQualifiedFieldAccessForWriting/src/Test.java b/java/java-tests/testData/inspection/fieldCanBeLocal/staticQualifiedFieldAccessForWriting/src/Test.java
new file mode 100644
index 0000000..09fa156
--- /dev/null
+++ b/java/java-tests/testData/inspection/fieldCanBeLocal/staticQualifiedFieldAccessForWriting/src/Test.java
@@ -0,0 +1,7 @@
+class G{
+ private static boolean foo = true;
+ static void bar(){
+ if(foo)
+ G.foo = false;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/javaDocInspection/enumConstructor/expected.xml b/java/java-tests/testData/inspection/javaDocInspection/enumConstructor/expected.xml
new file mode 100644
index 0000000..79e1a0f
--- /dev/null
+++ b/java/java-tests/testData/inspection/javaDocInspection/enumConstructor/expected.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+</problems>
+
diff --git a/java/java-tests/testData/inspection/javaDocInspection/enumConstructor/src/Foo.java b/java/java-tests/testData/inspection/javaDocInspection/enumConstructor/src/Foo.java
new file mode 100644
index 0000000..28caa85
--- /dev/null
+++ b/java/java-tests/testData/inspection/javaDocInspection/enumConstructor/src/Foo.java
@@ -0,0 +1,6 @@
+public enum Foo {
+ ;
+
+ Foo() {
+ }
+}
diff --git a/java/java-tests/testData/inspection/nullableProblems/GetterSetterProblems.java b/java/java-tests/testData/inspection/nullableProblems/GetterSetterProblems.java
new file mode 100644
index 0000000..d49cd9c
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/GetterSetterProblems.java
@@ -0,0 +1,67 @@
+import org.jetbrains.annotations.NotNull;
+
+class B {
+ @NotNull
+ B b;
+
+ public B <warning descr="Getter for @NotNull field might be annotated @NotNull itself">getB</warning>() {
+ return b;
+ }
+
+ public void setB(B <warning descr="Setter parameter for @NotNull field might be annotated @NotNull itself">b</warning>) {
+ this.b = b;
+ }
+
+ @NotNull
+ private String bug = "true";
+
+ public boolean getBug() {
+ return Boolean.valueOf(bug);
+ }
+}
+class C {
+ @NotNull C c;
+
+ C(C <warning descr="Constructor parameter for @NotNull field might be annotated @NotNull itself">c</warning>) {
+ this.c = c;
+ }
+
+ C(@<error descr="Cannot resolve symbol 'Nullable'">Nullable</error> C <warning descr="Constructor parameter for @NotNull field might be annotated @NotNull itself">c</warning>, int i) {
+ this.c = c;
+ }
+
+ @<error descr="Cannot resolve symbol 'Nullable'">Nullable</error>
+ public C <warning descr="Getter for @NotNull field might be annotated @NotNull itself">getC</warning>() {
+ return c;
+ }
+
+ public void setC(@<error descr="Cannot resolve symbol 'Nullable'">Nullable</error> C <warning descr="Setter parameter for @NotNull field might be annotated @NotNull itself">c</warning>) {
+ this.c = c;
+ }
+
+ @NotNull C c1;
+ @org.jetbrains.annotations.Nullable
+ public C getC1() {
+ if (c1 != null) {
+ return null;
+ }
+ return c1;
+ }
+}
+
+class D {
+ @<error descr="Cannot resolve symbol 'Nullable'">Nullable</error> Long myL;
+
+ D(long l) {
+ myL = l;
+ }
+}
+
+class E {
+ final @NotNull C c;
+
+ E(C <warning descr="Constructor parameter for @NotNull field might be annotated @NotNull itself">c</warning>) {
+ this.c = c;
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/HonorParameterDefaultInSetters.java b/java/java-tests/testData/inspection/nullableProblems/HonorParameterDefaultInSetters.java
new file mode 100644
index 0000000..a6b9b17
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/HonorParameterDefaultInSetters.java
@@ -0,0 +1,17 @@
+package foo;
+
+import javax.annotation.Nullable;
+
+class C {
+ @Nullable
+ private String a;
+ private String b;
+
+ public void setA(String <warning descr="Setter parameter for @Nullable field is annotated @ParametersAreNonnullByDefault">a</warning>) {
+ this.a = a;
+ }
+
+ public void setB(@Nullable String b) { // doesn't lead to a warning because b field is not a parameter
+ this.b = b;
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/HonorSuperParameterDefault.java b/java/java-tests/testData/inspection/nullableProblems/HonorSuperParameterDefault.java
new file mode 100644
index 0000000..174f7b7
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/HonorSuperParameterDefault.java
@@ -0,0 +1,12 @@
+import foo.*;
+
+class B {
+ {
+ new NullableFunction() {
+ public void fun(Object o) {}
+ };
+ new AnyFunction() {
+ public void fun(Object <warning descr="Not annotated parameter overrides @ParametersAreNonnullByDefault parameter">o</warning>) {}
+ };
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/HonorThisParameterDefault.java b/java/java-tests/testData/inspection/nullableProblems/HonorThisParameterDefault.java
new file mode 100644
index 0000000..626734e
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/HonorThisParameterDefault.java
@@ -0,0 +1,13 @@
+package foo;
+
+interface A {
+ void f(double a);
+ void f2(Object a);
+}
+
+class B implements A {
+ public void f(double a) {
+ }
+ public void f2(Object a) {
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/notNullFieldNullableParam/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/NotNullFieldNullableParam.java
similarity index 100%
rename from java/java-tests/testData/inspection/nullableProblems/notNullFieldNullableParam/src/Test.java
rename to java/java-tests/testData/inspection/nullableProblems/NotNullFieldNullableParam.java
diff --git a/java/java-tests/testData/inspection/nullableProblems/NullableFieldNotnullParam.java b/java/java-tests/testData/inspection/nullableProblems/NullableFieldNotnullParam.java
new file mode 100644
index 0000000..71eb422
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/NullableFieldNotnullParam.java
@@ -0,0 +1,21 @@
+import org.jetbrains.annotations.*;
+
+class Test {
+ @Nullable private final String baseFile;
+ @Nullable private final String baseFile1;
+
+
+ public Test(@NotNull String <warning descr="Constructor parameter for @Nullable field is annotated @NotNull">baseFile</warning>) {
+ this.baseFile = baseFile;
+ this.baseFile1 = null;
+ }
+
+ public Test(@NotNull String baseFile1, boolean a) {
+ this.baseFile1 = baseFile1;
+ if (baseFile1.contains("foo")) {
+ this.baseFile = null;
+ } else {
+ this.baseFile = null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/OverriddenMethods.java b/java/java-tests/testData/inspection/nullableProblems/OverriddenMethods.java
new file mode 100644
index 0000000..81ac5b0
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/OverriddenMethods.java
@@ -0,0 +1,53 @@
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+abstract class P2 {
+ <warning descr="Overridden methods are not annotated">@NotNull</warning>
+ String foo(<warning descr="Overridden method parameters are not annotated">@NotNull</warning> <error descr="Cannot resolve symbol 'P'">P</error> p) {
+ return "";
+ }
+}
+
+class PPP extends P2 {
+ String <warning descr="Not annotated method overrides method annotated with @NotNull">foo</warning>(<error descr="Cannot resolve symbol 'P'">P</error> <warning descr="Not annotated parameter overrides @NotNull parameter">p</warning>) {
+ return super.foo(p);
+ }
+}
+class PPP2 extends P2 {
+
+ String <warning descr="Not annotated method overrides method annotated with @NotNull">foo</warning>(<error descr="Cannot resolve symbol 'P'">P</error> <warning descr="Not annotated parameter overrides @NotNull parameter">p</warning>) {
+ return super.foo(p);
+ }
+}
+
+/////// in library
+interface Foo {
+ @NotNull
+ String getTitle();
+}
+<error descr="Unhandled exception: java.awt.HeadlessException">class FooImpl extends java.awt.Frame implements Foo</error> {
+// public String getTitle() {
+// return super.getTitle(); //To change body of overridden methods use File | Settings | File Templates.
+// }
+}
+
+
+interface I1 {
+ @Nullable
+ Object foo();
+}
+
+interface I2 extends I1 {
+ @NotNull
+ Object foo();
+}
+
+class A implements I1 {
+ @Override
+ public Object foo() {
+ // returns something
+ <error descr="Missing return statement">}</error>
+}
+
+class B extends A implements I2 {
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/Problems.java b/java/java-tests/testData/inspection/nullableProblems/Problems.java
new file mode 100644
index 0000000..a34f091
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/Problems.java
@@ -0,0 +1,26 @@
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class B {
+ public void f(@NotNull String p){}
+ @NotNull
+ public String nn(@Nullable String param) {
+ return "";
+ }
+}
+
+public class Y extends B {
+ <warning descr="Cannot annotate with both @Nullable and @NotNull">@NotNull</warning> <warning descr="Cannot annotate with both @Nullable and @NotNull">@Nullable</warning> String s;
+ public void f(String <warning descr="Not annotated parameter overrides @NotNull parameter">p</warning>){}
+
+
+ public String <warning descr="Not annotated method overrides method annotated with @NotNull">nn</warning>(<warning descr="Parameter annotated @NotNull must not override @Nullable parameter">@NotNull</warning> String param) {
+ return "";
+ }
+ void p(<warning descr="Cannot annotate with both @Nullable and @NotNull">@NotNull</warning> <warning descr="Cannot annotate with both @Nullable and @NotNull">@Nullable</warning> String p2){}
+
+
+ <warning descr="Primitive type members cannot be annotated">@Nullable</warning> int f;
+ <warning descr="Primitive type members cannot be annotated">@NotNull</warning> void vf(){}
+ void t(<warning descr="Primitive type members cannot be annotated">@NotNull</warning> double d){}
+}
diff --git a/java/java-tests/testData/inspection/nullableProblems/Problems2.java b/java/java-tests/testData/inspection/nullableProblems/Problems2.java
new file mode 100644
index 0000000..18ee51f
--- /dev/null
+++ b/java/java-tests/testData/inspection/nullableProblems/Problems2.java
@@ -0,0 +1,24 @@
+import org.jetbrains.annotations.*;
+
+class C {
+ public static C C = null;
+ @NotNull public C getC() {return C;}
+ @NotNull public C getC2() {return C;}
+
+ public void f1(@Nullable C p) {}
+ public void f2(@NotNull C p) {}
+ public void f3(@Nullable C p) {}
+ public void f4(@NotNull C p) {}
+}
+
+class CC extends C {
+ <warning descr="Method annotated with @Nullable must not override @NotNull method">@Nullable</warning> public C getC() {return C;}
+ public C <warning descr="Not annotated method overrides method annotated with @NotNull">getC2</warning>() {return C;}
+
+ public void f1(<warning descr="Parameter annotated @NotNull must not override @Nullable parameter">@NotNull</warning> C p) {}
+ public void f2(@NotNull C p) {}
+ public void f3(@Nullable C p) {}
+ public void f4(@Nullable C p) {}
+
+ <warning descr="Cannot annotate with both @Nullable and @NotNull">@Nullable</warning> <warning descr="Cannot annotate with both @Nullable and @NotNull">@NotNull</warning> String f() { return null;}
+}
diff --git a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml b/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml
deleted file mode 100644
index e83b29b..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/expected.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
- <problem>
- <file>Test.java</file>
- <line>11</line>
- <method>
- <name>void setB(B b)</name>
- <display_name>setB(B)</display_name>
- <package><default></package>
- <class>
- <name>B</name>
- <display_name>B</display_name>
- </class>
- </method>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Setter parameter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
- <problem>
- <file>Test.java</file>
- <line>7</line>
- <method>
- <name>B getB()</name>
- <display_name>getB()</display_name>
- <package><default></package>
- <class>
- <name>B</name>
- <display_name>B</display_name>
- </class>
- </method>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Getter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
-
- <problem>
- <file>Test.java</file>
- <line>25</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Constructor parameter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>38</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Setter parameter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>34</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Getter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>29</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Constructor parameter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
-
- <problem>
- <file>Test.java</file>
- <line>63</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Constructor parameter for @NotNull field might be annotated @NotNull itself</description>
- </problem>
-
-
-</problems>
diff --git a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java
deleted file mode 100644
index 6fc47b4..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/getterSetterProblems/src/Test.java
+++ /dev/null
@@ -1,67 +0,0 @@
-import org.jetbrains.annotations.NotNull;
-
-class B {
- @NotNull
- B b;
-
- public B getB() {
- return b;
- }
-
- public void setB(B b) {
- this.b = b;
- }
-
- @NotNull
- private String bug = "true";
-
- public boolean getBug() {
- return Boolean.valueOf(bug);
- }
-}
-class C {
- @NotNull C c;
-
- C(C c) {
- this.c = c;
- }
-
- C(@Nullable C c, int i) {
- this.c = c;
- }
-
- @Nullable
- public C getC() {
- return c;
- }
-
- public void setC(@Nullable C c) {
- this.c = c;
- }
-
- @NotNull C c1;
- @org.jetbrains.annotations.Nullable
- public C getC1() {
- if (c1 != null) {
- return null;
- }
- return c1;
- }
-}
-
-class D {
- @Nullable Long myL;
-
- D(long l) {
- myL = l;
- }
-}
-
-class E {
- final @NotNull C c;
-
- E(C c) {
- this.c = c;
- }
-
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/nullableFieldNotnullParam/expected.xml b/java/java-tests/testData/inspection/nullableProblems/nullableFieldNotnullParam/expected.xml
deleted file mode 100644
index 407582e..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/nullableFieldNotnullParam/expected.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
- <problem>
- <file>Test.java</file>
- <line>8</line>
- <description>Constructor parameter for @Nullable field is annotated @NotNull</description>
- </problem>
-</problems>
-
diff --git a/java/java-tests/testData/inspection/nullableProblems/nullableFieldNotnullParam/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/nullableFieldNotnullParam/src/Test.java
deleted file mode 100644
index 5cebab7..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/nullableFieldNotnullParam/src/Test.java
+++ /dev/null
@@ -1,21 +0,0 @@
-import org.jetbrains.annotations.*;
-
-class Test {
- @Nullable private final String baseFile;
- @Nullable private final String baseFile1;
-
-
- public Test(@NotNull String baseFile) {
- this.baseFile = baseFile;
- this.baseFile1 = null;
- }
-
- public Test(@NotNull String baseFile1, boolean a) {
- this.baseFile1 = baseFile1;
- if (baseFile1.contains("foo")) {
- this.baseFile = null;
- } else {
- this.baseFile = null;
- }
- }
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/overriddenMethods/expected.xml b/java/java-tests/testData/inspection/nullableProblems/overriddenMethods/expected.xml
deleted file mode 100644
index 1c1f7ce..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/overriddenMethods/expected.xml
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
-<problem>
- <file>Test.java</file>
- <line>18</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Not annotated method overrides method annotated with @NotNull</description>
-</problem>
-
-<problem>
- <file>Test.java</file>
- <line>18</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Not annotated parameter overrides @NotNull parameter</description>
-</problem>
-
-<problem>
- <file>Test.java</file>
- <line>5</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Overridden methods are not annotated</description>
-</problem>
-
-<problem>
- <file>Test.java</file>
- <line>6</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Overridden method parameters are not annotated</description>
-</problem>
-
-<problem>
- <file>Test.java</file>
- <line>12</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Not annotated method overrides method annotated with @NotNull</description>
-</problem>
-
-<problem>
- <file>Test.java</file>
- <line>12</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Not annotated parameter overrides @NotNull parameter</description>
-</problem></problems>
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/overriddenMethods/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/overriddenMethods/src/Test.java
deleted file mode 100644
index e44eb8c..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/overriddenMethods/src/Test.java
+++ /dev/null
@@ -1,53 +0,0 @@
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-abstract class P2 {
- @NotNull
- String foo(@NotNull P p) {
- return "";
- }
-}
-
-class PPP extends P2 {
- String foo(P p) {
- return super.foo(p);
- }
-}
-class PPP2 extends P2 {
-
- String foo(P p) {
- return super.foo(p);
- }
-}
-
-/////// in library
-interface Foo {
- @NotNull
- String getTitle();
-}
-class FooImpl extends java.awt.Frame implements Foo {
-// public String getTitle() {
-// return super.getTitle(); //To change body of overridden methods use File | Settings | File Templates.
-// }
-}
-
-
-interface I1 {
- @Nullable
- Object foo();
-}
-
-interface I2 extends I1 {
- @NotNull
- Object foo();
-}
-
-class A implements I1 {
- @Override
- public Object foo() {
- // returns something
- }
-}
-
-class B extends A implements I2 {
-}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/problems/expected.xml b/java/java-tests/testData/inspection/nullableProblems/problems/expected.xml
deleted file mode 100644
index 0c33e4d..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/problems/expected.xml
+++ /dev/null
@@ -1,169 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
-<problem>
- <file>Test.java</file>
- <line>14</line>
- <method>
- <name>void f(String p)</name>
- <display_name>f(String)</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <description>Not annotated parameter overrides @NotNull parameter</description>
-</problem>
-
-
-<problem>
- <file>Test.java</file>
- <line>17</line>
- <text_range start="361" end="363" />
- <method>
- <name>String nn(String param)</name>
- <display_name>nn(String)</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <description>Not annotated method overrides method annotated with @NotNull</description>
-</problem>
-
-
-<problem>
- <file>Test.java</file>
- <line>17</line>
- <text_range start="380" end="385" />
- <method>
- <name>String nn(String param)</name>
- <display_name>nn(String)</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <description>Parameter annotated @NotNull must not override @Nullable parameter</description>
-</problem>
-
-
-<problem>
- <file>Test.java</file>
- <line>13</line>
- <text_range start="291" end="292" />
- <field>
- <name>String s</name>
- <display_name>s</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </field>
- <description>Cannot annotate with both @Nullable and @NotNull</description>
-
-</problem>
- <problem>
- <file>Test.java</file>
- <line>13</line>
- <field>
- <name>String s</name>
- <display_name>s</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </field>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Cannot annotate with both @Nullable and @NotNull</description>
- </problem>
-
-
-<problem>
- <file>Test.java</file>
- <line>20</line>
- <text_range start="452" end="454" />
- <method>
- <name>void p(String p2)</name>
- <display_name>p(String)</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <description>Cannot annotate with both @Nullable and @NotNull</description>
-</problem>
-
- <problem>
- <file>Test.java</file>
- <line>23</line>
- <text_range start="476" end="477" />
- <field>
- <name>int f</name>
- <display_name>f</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </field>
- <description>Primitive type members cannot be annotated</description>
- </problem>
-
- <problem>
- <file>Test.java</file>
- <line>24</line>
- <text_range start="492" end="496" />
- <method>
- <name>void vf()</name>
- <display_name>vf()</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <description>Primitive type members cannot be annotated</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>25</line>
- <text_range start="531" end="532" />
- <method>
- <name>void t(double d)</name>
- <display_name>t(double)</display_name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <description>Primitive type members cannot be annotated</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>20</line>
- <method>
- <name>void p(String p2)</name>
- <name>p(String)</name>
- <package><default></package>
- <class>
- <name>Y</name>
- <display_name>Y</display_name>
- </class>
- </method>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Cannot annotate with both @Nullable and @NotNull</description>
- </problem>
-
-</problems>
-
diff --git a/java/java-tests/testData/inspection/nullableProblems/problems/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/problems/src/Test.java
deleted file mode 100644
index a1403cc..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/problems/src/Test.java
+++ /dev/null
@@ -1,26 +0,0 @@
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-class B {
- public void f(@NotNull String p){}
- @NotNull
- public String nn(@Nullable String param) {
- return "";
- }
-}
-
-public class Y extends B {
- @NotNull @Nullable String s;
- public void f(String p){}
-
-
- public String nn(@NotNull String param) {
- return "";
- }
- void p(@NotNull @Nullable String p2){}
-
-
- @Nullable int f;
- @NotNull void vf(){}
- void t(@NotNull double d){}
-}
diff --git a/java/java-tests/testData/inspection/nullableProblems/problems2/expected.xml b/java/java-tests/testData/inspection/nullableProblems/problems2/expected.xml
deleted file mode 100644
index 8f12a75..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/problems2/expected.xml
+++ /dev/null
@@ -1,85 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
- <problem>
- <file>Test.java</file>
- <line>23</line>
- <text_range start="556" end="557" />
- <method>
- <name>String f()</name>
- <display_name>f()</display_name>
- <package><default></package>
- <class>
- <name>CC</name>
- <display_name>CC</display_name>
- </class>
- </method>
- <description>Cannot annotate with both @Nullable and @NotNull</description>
- </problem>
- <problem>
- <file>Test.java</file>
- <line>23</line>
- <method>
- <name>String f()</name>
- <name>f()</name>
- <package><default></package>
- <class>
- <name>CC</name>
- <display_name>CC</display_name>
- </class>
- </method>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">@NotNull/@Nullable problems</problem_class>
- <description>Cannot annotate with both @Nullable and @NotNull</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>16</line>
- <text_range start="368" end="373" />
- <method>
- <name>C getC2()</name>
- <display_name>getC2()</display_name>
- <package><default></package>
- <class>
- <name>CC</name>
- <display_name>CC</display_name>
- </class>
- </method>
- <description>Not annotated method overrides method annotated with @NotNull</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>18</line>
- <text_range start="417" end="418" />
- <method>
- <name>void f1(C p)</name>
- <display_name>f1(C)</display_name>
- <package><default></package>
- <class>
- <name>CC</name>
- <display_name>CC</display_name>
- </class>
- </method>
- <description>Parameter annotated @NotNull must not override @Nullable parameter</description>
- </problem>
-
-
- <problem>
- <file>Test.java</file>
- <line>15</line>
- <text_range start="338" end="342" />
- <method>
- <name>C getC()</name>
- <display_name>getC()</display_name>
- <package><default></package>
- <class>
- <name>CC</name>
- <display_name>CC</display_name>
- </class>
- </method>
- <description>Method annotated with @Nullable must not override @NotNull method</description>
- </problem>
-</problems>
-
diff --git a/java/java-tests/testData/inspection/nullableProblems/problems2/src/Test.java b/java/java-tests/testData/inspection/nullableProblems/problems2/src/Test.java
deleted file mode 100644
index 16a05db..0000000
--- a/java/java-tests/testData/inspection/nullableProblems/problems2/src/Test.java
+++ /dev/null
@@ -1,24 +0,0 @@
-import org.jetbrains.annotations.*;
-
-class C {
- public static C C = null;
- @NotNull public C getC() {return C;}
- @NotNull public C getC2() {return C;}
-
- public void f1(@Nullable C p) {}
- public void f2(@NotNull C p) {}
- public void f3(@Nullable C p) {}
- public void f4(@NotNull C p) {}
-}
-
-class CC extends C {
- @Nullable public C getC() {return C;}
- public C getC2() {return C;}
-
- public void f1(@NotNull C p) {}
- public void f2(@NotNull C p) {}
- public void f3(@Nullable C p) {}
- public void f4(@Nullable C p) {}
-
- @Nullable @NotNull String f() { return null;}
-}
diff --git a/java/java-tests/testData/psi/cls/mirror/Bounds.txt b/java/java-tests/testData/psi/cls/mirror/Bounds.txt
index ab190fd..2350274 100644
--- a/java/java-tests/testData/psi/cls/mirror/Bounds.txt
+++ b/java/java-tests/testData/psi/cls/mirror/Bounds.txt
@@ -7,7 +7,7 @@
class Bounds {
Bounds() { /* compiled code */ }
- public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T> collection) { /* compiled code */ }
+ public static <T extends java.lang.Object & java.lang.Comparable<? super T>> T max(java.util.Collection<? extends T> collection) { /* compiled code */ }
- public static <T> T max(java.util.Collection<? extends T> collection, java.util.Comparator<? super T> comparator) { /* compiled code */ }
+ public static <T> T max(java.util.Collection<? extends T> collection, java.util.Comparator<? super T> comparator) { /* compiled code */ }
}
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/cls/mirror/DefaultPackage.txt b/java/java-tests/testData/psi/cls/mirror/DefaultPackage.txt
new file mode 100644
index 0000000..453e866
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/DefaultPackage.txt
@@ -0,0 +1,7 @@
+
+ // IntelliJ API Decompiler stub source generated from a class file
+ // Implementation of methods is not available
+
+public class DefaultPackage {
+ public DefaultPackage() { /* compiled code */ }
+}
diff --git a/java/java-tests/testData/psi/cls/mirror/KotlinFunList.txt b/java/java-tests/testData/psi/cls/mirror/KotlinFunList.txt
index a08328b..b6c31e2 100644
--- a/java/java-tests/testData/psi/cls/mirror/KotlinFunList.txt
+++ b/java/java-tests/testData/psi/cls/mirror/KotlinFunList.txt
@@ -4,7 +4,7 @@
package pkg;
-public abstract class KotlinFunList <T> {
+public abstract class KotlinFunList <T> {
public static pkg.KotlinFunList.ClassObject$ $classobj;
public KotlinFunList() { /* compiled code */ }
@@ -12,13 +12,13 @@
public static final class ClassObject$ {
public ClassObject$() { /* compiled code */ }
- public final class Standard <T> {
+ public final class Standard <T> {
final pkg.KotlinFunList.ClassObject$ this$0;
public Standard() { /* compiled code */ }
}
- public final class Empty <T> {
+ public final class Empty <T> {
final pkg.KotlinFunList.ClassObject$ this$0;
public Empty() { /* compiled code */ }
diff --git a/java/java-tests/testData/psi/cls/mirror/LocalClass.txt b/java/java-tests/testData/psi/cls/mirror/LocalClass.txt
new file mode 100644
index 0000000..a53c42c
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/LocalClass.txt
@@ -0,0 +1,11 @@
+
+ // IntelliJ API Decompiler stub source generated from a class file
+ // Implementation of methods is not available
+
+package pkg;
+
+public class LocalClass {
+ public LocalClass() { /* compiled code */ }
+
+ public java.lang.Runnable runnable() { /* compiled code */ }
+}
diff --git a/java/java-tests/testData/psi/cls/mirror/Middle$Buck.txt b/java/java-tests/testData/psi/cls/mirror/Middle$Buck.txt
new file mode 100644
index 0000000..3d9b279
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/Middle$Buck.txt
@@ -0,0 +1,13 @@
+
+ // IntelliJ API Decompiler stub source generated from a class file
+ // Implementation of methods is not available
+
+package pkg;
+
+public class Middle$Buck {
+ public Middle$Buck() { /* compiled code */ }
+
+ private static class Inner$Buck {
+ private Inner$Buck() { /* compiled code */ }
+ }
+}
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/DefaultPackage.class b/java/java-tests/testData/psi/cls/mirror/pkg/DefaultPackage.class
new file mode 100644
index 0000000..08aec68
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/DefaultPackage.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/LocalClass$1MyRunnable.class b/java/java-tests/testData/psi/cls/mirror/pkg/LocalClass$1MyRunnable.class
new file mode 100644
index 0000000..ae380d4
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/LocalClass$1MyRunnable.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/LocalClass.class b/java/java-tests/testData/psi/cls/mirror/pkg/LocalClass.class
new file mode 100644
index 0000000..b654b6f
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/LocalClass.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Middle$Buck$Inner$Buck.class b/java/java-tests/testData/psi/cls/mirror/pkg/Middle$Buck$Inner$Buck.class
new file mode 100644
index 0000000..3e13130
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Middle$Buck$Inner$Buck.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/Middle$Buck.class b/java/java-tests/testData/psi/cls/mirror/pkg/Middle$Buck.class
new file mode 100644
index 0000000..d470c41
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/pkg/Middle$Buck.class
Binary files differ
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java
index 81bd3a0..bacda1c 100644
--- a/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/Bounds.java
@@ -1,18 +1,3 @@
-/*
- * Copyright 2000-2014 JetBrains s.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 pkg;
import java.util.Collection;
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/DefaultPackage.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/DefaultPackage.java
new file mode 100644
index 0000000..afc7849
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/DefaultPackage.java
@@ -0,0 +1,2 @@
+public class DefaultPackage {
+}
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/LocalClass.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/LocalClass.java
new file mode 100644
index 0000000..fa8e230
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/LocalClass.java
@@ -0,0 +1,13 @@
+package pkg;
+
+public class LocalClass {
+ public Runnable runnable() {
+ class MyRunnable implements Runnable {
+ public void run() {
+ System.out.println(this);
+ }
+ }
+
+ return new MyRunnable();
+ }
+}
diff --git a/java/java-tests/testData/psi/cls/mirror/src/pkg/Middle$Buck.java b/java/java-tests/testData/psi/cls/mirror/src/pkg/Middle$Buck.java
new file mode 100644
index 0000000..d9c6bb8
--- /dev/null
+++ b/java/java-tests/testData/psi/cls/mirror/src/pkg/Middle$Buck.java
@@ -0,0 +1,6 @@
+package pkg;
+
+public class Middle$Buck {
+ private static class Inner$Buck {
+ }
+}
diff --git a/java/java-tests/testData/psi/formatter/java/ParametersAlignment_after.java b/java/java-tests/testData/psi/formatter/java/ParametersAlignment_after.java
index 0e0dee8..cf135bf 100644
--- a/java/java-tests/testData/psi/formatter/java/ParametersAlignment_after.java
+++ b/java/java-tests/testData/psi/formatter/java/ParametersAlignment_after.java
@@ -7,6 +7,7 @@
settings,
indentOptions,
child2.getTextRange(),
- false);
+ false
+ );
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt b/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt
index fd394aa..38e287e 100644
--- a/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt
+++ b/java/java-tests/testData/psi/parser-full/commonParsing/RefParamsAfterError.txt
@@ -63,7 +63,7 @@
PsiJavaToken:LT('<')
PsiErrorElement:Identifier expected
<empty list>
- PsiErrorElement:'>' or ',' expected.
+ PsiErrorElement:'>' or ',' expected
<empty list>
PsiErrorElement:Identifier expected
<empty list>
diff --git a/java/java-tests/testData/psi/search/inheritors/multipleInheritance/Test.java b/java/java-tests/testData/psi/search/inheritors/multipleInheritance/Test.java
new file mode 100644
index 0000000..4b76063
--- /dev/null
+++ b/java/java-tests/testData/psi/search/inheritors/multipleInheritance/Test.java
@@ -0,0 +1,3 @@
+interface I {}
+class A implements I {}
+class B extends A implements I{}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/changeSignature/JavadocNoNewLineInserted.java b/java/java-tests/testData/refactoring/changeSignature/JavadocNoNewLineInserted.java
new file mode 100644
index 0000000..aaf93b8
--- /dev/null
+++ b/java/java-tests/testData/refactoring/changeSignature/JavadocNoNewLineInserted.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+class Test {
+
+ /**
+ * Blah blah
+ *
+ * @param arg too many
+ * @return zero
+ */
+ public static int <caret>get(int arg) {
+ return 0;
+ }
+
+}
diff --git a/java/java-tests/testData/refactoring/changeSignature/JavadocNoNewLineInserted_after.java b/java/java-tests/testData/refactoring/changeSignature/JavadocNoNewLineInserted_after.java
new file mode 100644
index 0000000..5ab0d31
--- /dev/null
+++ b/java/java-tests/testData/refactoring/changeSignature/JavadocNoNewLineInserted_after.java
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+class Test {
+
+ /**
+ * Blah blah
+ *
+ * @param newArgs too many
+ * @return zero
+ */
+ public static int get(double newArgs) {
+ return 0;
+ }
+
+}
diff --git a/java/java-tests/testData/refactoring/inlineParameter/PropagatedParams.java b/java/java-tests/testData/refactoring/inlineParameter/PropagatedParams.java
new file mode 100644
index 0000000..e554bf2
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineParameter/PropagatedParams.java
@@ -0,0 +1,10 @@
+class X {
+ void bar(String str){
+ foo(str, str.substring(0));
+ }
+
+ void foo(String str, String st<caret>r1) {
+ System.out.println(str);
+ System.out.println(str1);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineParameter/PropagatedParams.java.after b/java/java-tests/testData/refactoring/inlineParameter/PropagatedParams.java.after
new file mode 100644
index 0000000..354e537
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineParameter/PropagatedParams.java.after
@@ -0,0 +1,10 @@
+class X {
+ void bar(String str){
+ foo(str);
+ }
+
+ void foo(String str) {
+ System.out.println(str);
+ System.out.println(str.substring(0));
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineToAnonymousClass/AvailableInSupers.java b/java/java-tests/testData/refactoring/inlineToAnonymousClass/AvailableInSupers.java
new file mode 100644
index 0000000..f6ff94e
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineToAnonymousClass/AvailableInSupers.java
@@ -0,0 +1,17 @@
+class A {
+ protected int i;
+}
+
+class B extends A {}
+
+class C {
+ C() {
+ B d = new D();
+ }
+
+ static class <caret>D extends B {
+ D() {
+ System.out.println(i);
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inlineToAnonymousClass/AvailableInSupers.java.after b/java/java-tests/testData/refactoring/inlineToAnonymousClass/AvailableInSupers.java.after
new file mode 100644
index 0000000..545b104
--- /dev/null
+++ b/java/java-tests/testData/refactoring/inlineToAnonymousClass/AvailableInSupers.java.after
@@ -0,0 +1,16 @@
+class A {
+ protected int i;
+}
+
+class B extends A {}
+
+class C {
+ C() {
+ B d = new B() {
+ {
+ System.out.println(i);
+ }
+ };
+ }
+
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/correctConstantPosition_after.java b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/correctConstantPosition_after.java
index 1e994b8..663aa29 100644
--- a/java/java-tests/testData/refactoring/inplaceIntroduceConstant/correctConstantPosition_after.java
+++ b/java/java-tests/testData/refactoring/inplaceIntroduceConstant/correctConstantPosition_after.java
@@ -1,6 +1,6 @@
public class Res {
- public static final Res.R<String,Object> R = new Res.R<String, Object>() {
+ public static final Res.R<String, Object> R = new Res.R<String, Object>() {
final String param = "";
@Override
diff --git a/java/java-tests/testData/refactoring/introduceConstant/PartialStringLiteralAnchorFromAnnotation.java b/java/java-tests/testData/refactoring/introduceConstant/PartialStringLiteralAnchorFromAnnotation.java
new file mode 100644
index 0000000..76b402c
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceConstant/PartialStringLiteralAnchorFromAnnotation.java
@@ -0,0 +1,14 @@
+@Model(usages = @Usage("${<selection>__REQUEST_PARAMETERS</selection>}"))
+public class SomeClass {
+
+ public String getModelName() {
+ return "__REQUEST_PARAMETERS";
+ }
+}
+
+@interface Model {
+ Usage usages();
+}
+@interface Usage {
+ String value();
+}
diff --git a/java/java-tests/testData/refactoring/introduceConstant/PartialStringLiteralAnchorFromAnnotation_after.java b/java/java-tests/testData/refactoring/introduceConstant/PartialStringLiteralAnchorFromAnnotation_after.java
new file mode 100644
index 0000000..983e0c3
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceConstant/PartialStringLiteralAnchorFromAnnotation_after.java
@@ -0,0 +1,16 @@
+@Model(usages = @Usage("${" + SomeClass.xxx + "}"))
+public class SomeClass {
+
+ public static final String xxx = "__REQUEST_PARAMETERS";
+
+ public String getModelName() {
+ return xxx;
+ }
+}
+
+@interface Model {
+ Usage usages();
+}
+@interface Usage {
+ String value();
+}
diff --git a/java/java-tests/testData/refactoring/introduceVariable/ExpectedType8Inference.after.java b/java/java-tests/testData/refactoring/introduceVariable/ExpectedType8Inference.after.java
new file mode 100644
index 0000000..be3606b
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/ExpectedType8Inference.after.java
@@ -0,0 +1,25 @@
+import java.util.*;
+class A {
+ private void foo(Stream<String> a) {
+ Map<String, List<String>> temp = a.collect(groupingBy(Function.<String>identity()));
+ }
+
+ interface Collector<T, A, R> {
+ }
+
+ public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) {
+ return null;
+ }
+
+ interface Stream<T> {
+ <R, A> R collect(Collector<? super T, A, R> collector);
+ }
+
+ interface Function<A, B> {
+ B fn(A a);
+
+ static <T> Function<T, T> identity() {
+ return t -> t;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/introduceVariable/ExpectedType8Inference.java b/java/java-tests/testData/refactoring/introduceVariable/ExpectedType8Inference.java
new file mode 100644
index 0000000..e793aa2
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/ExpectedType8Inference.java
@@ -0,0 +1,25 @@
+import java.util.*;
+class A {
+ private void foo(Stream<String> a) {
+ <selection>a.collect(groupingBy(Function.<String>identity()))</selection>;
+ }
+
+ interface Collector<T, A, R> {
+ }
+
+ public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier) {
+ return null;
+ }
+
+ interface Stream<T> {
+ <R, A> R collect(Collector<? super T, A, R> collector);
+ }
+
+ interface Function<A, B> {
+ B fn(A a);
+
+ static <T> Function<T, T> identity() {
+ return t -> t;
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/introduceVariable/WriteUsages.after.java b/java/java-tests/testData/refactoring/introduceVariable/WriteUsages.after.java
new file mode 100644
index 0000000..d14c695
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/WriteUsages.after.java
@@ -0,0 +1,9 @@
+class A {
+ {
+ String[] result = new String[1];
+ result[0] = "";
+ String c = result[0];
+ System.out.println(c);
+ System.out.println(c);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/introduceVariable/WriteUsages.java b/java/java-tests/testData/refactoring/introduceVariable/WriteUsages.java
new file mode 100644
index 0000000..0dab38c
--- /dev/null
+++ b/java/java-tests/testData/refactoring/introduceVariable/WriteUsages.java
@@ -0,0 +1,8 @@
+class A {
+ {
+ String[] result = new String[1];
+ result[0] = "";
+ System.out.println(result[0]);
+ System.out.println(<selection>result[0]</selection>);
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/invertBoolean/methodRefs.conflicts.txt b/java/java-tests/testData/refactoring/invertBoolean/methodRefs.conflicts.txt
new file mode 100644
index 0000000..9ba9a29
--- /dev/null
+++ b/java/java-tests/testData/refactoring/invertBoolean/methodRefs.conflicts.txt
@@ -0,0 +1 @@
+Method is used in method reference expression
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameNoStaticOverridingInInterfaces.java b/java/java-tests/testData/refactoring/renameCollisions/RenameNoStaticOverridingInInterfaces.java
new file mode 100644
index 0000000..1ed4b3d
--- /dev/null
+++ b/java/java-tests/testData/refactoring/renameCollisions/RenameNoStaticOverridingInInterfaces.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+interface A
+{
+ static void foo(){}
+}
+interface B extends A
+{
+ static int ba<caret>r(){ return 1; }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/renameCollisions/RenameNoStaticOverridingInInterfaces.java.after b/java/java-tests/testData/refactoring/renameCollisions/RenameNoStaticOverridingInInterfaces.java.after
new file mode 100644
index 0000000..2398a2e
--- /dev/null
+++ b/java/java-tests/testData/refactoring/renameCollisions/RenameNoStaticOverridingInInterfaces.java.after
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+interface A
+{
+ static void foo(){}
+}
+interface B extends A
+{
+ static int foo(){ return 1; }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/safeDelete/EmptyIf.java b/java/java-tests/testData/refactoring/safeDelete/EmptyIf.java
new file mode 100644
index 0000000..ea06c0f
--- /dev/null
+++ b/java/java-tests/testData/refactoring/safeDelete/EmptyIf.java
@@ -0,0 +1,8 @@
+class A {
+ void f(String p){
+ String <caret>t;
+ if (p == null)
+ t = "1";
+ System.out.println("");
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/refactoring/safeDelete/EmptyIf_after.java b/java/java-tests/testData/refactoring/safeDelete/EmptyIf_after.java
new file mode 100644
index 0000000..de39700
--- /dev/null
+++ b/java/java-tests/testData/refactoring/safeDelete/EmptyIf_after.java
@@ -0,0 +1,7 @@
+class A {
+ void f(String p){
+ if (p == null)
+ ;
+ System.out.println("");
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/JavaTestUtil.java b/java/java-tests/testSrc/com/intellij/JavaTestUtil.java
index 43e38e0..4dfce7c 100644
--- a/java/java-tests/testSrc/com/intellij/JavaTestUtil.java
+++ b/java/java-tests/testSrc/com/intellij/JavaTestUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -53,7 +53,7 @@
});
}
- private static Sdk getTestJdk() {
+ public static Sdk getTestJdk() {
try {
ProjectJdkImpl jdk = (ProjectJdkImpl)JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk().clone();
jdk.setName("JDK");
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
index d33075a..d8a89cb 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java
@@ -107,6 +107,10 @@
public void testMethod() throws Exception { doTest(); }
public void testClass() throws Exception { doTest(); }
+
+ public void testInnerEnumBeforeMethod() { doTest(); }
+
+ public void testInnerEnumBeforeMethodWithSpace() { doTest(); }
public void testCompleteElseIf() throws Exception { doTest(); }
@@ -143,6 +147,8 @@
public void testFieldBeforeAnnotation() throws Exception { doTest(); }
public void testMethodBeforeAnnotation() throws Exception { doTest(); }
+ public void testMethodBeforeCommentField() throws Exception { doTest(); }
+ public void testMethodBeforeCommentMethod() throws Exception { doTest(); }
public void testParenthesized() throws Exception { doTest(); }
@@ -254,6 +260,8 @@
public void testGenericMethodBody() throws Exception { doTest(); }
+ public void testArrayInitializerRBracket() throws Exception { doTest(); }
+
private void doTestBracesNextLineStyle() throws Exception {
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
settings.BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
@@ -269,11 +277,11 @@
}
}
- private void doTest() throws Exception {
+ private void doTest() {
doTest("java");
}
- private void doTest(String ext) throws Exception {
+ private void doTest(String ext) {
String path = "/codeInsight/completeStatement/";
doFileTest(path + getTestName(false) + "." + ext, path + getTestName(false) + "_after." + ext, true);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy
index e845ae3..07fee95 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/GenerateGetterSetterTest.groovy
@@ -16,6 +16,7 @@
package com.intellij.codeInsight
import com.intellij.codeInsight.generation.ClassMember
import com.intellij.codeInsight.generation.GenerateGetterHandler
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
@@ -41,7 +42,8 @@
public YesNoRAMField getIsStateForceMailField() {
return isStateForceMailField;
- }}
+ }
+}
'''
}
@@ -60,11 +62,13 @@
public boolean isStateForceMailField() {
return isStateForceMailField;
- }}
+ }
+}
'''
}
private void generateGetter() {
+ WriteCommandAction.runWriteCommandAction(getProject(), {
new GenerateGetterHandler() {
@Override
protected ClassMember[] chooseMembers(
@@ -76,5 +80,6 @@
return members
}
}.invoke(project, myFixture.editor, myFixture.file)
+ })
}
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java
index 2c757c1..83c54f9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/ParameterInfoTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.codeInsight;
import com.intellij.codeInsight.hint.ParameterInfoComponent;
@@ -8,21 +23,29 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.infos.MethodCandidateInfo;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.testFramework.utils.parameterInfo.MockCreateParameterInfoContext;
+import com.intellij.testFramework.utils.parameterInfo.MockParameterInfoUIContext;
import com.intellij.testFramework.utils.parameterInfo.MockUpdateParameterInfoContext;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import junit.framework.Assert;
+import java.io.IOException;
+
public class ParameterInfoTest extends LightCodeInsightTestCase {
private static final String BASE_PATH = "/codeInsight/parameterInfo/";
- private Object[] doTest(String paramsList) throws Exception {
+ private void doTest(String paramsList) throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
+ String joined = invokeParameterInfo();
+ assertEquals(paramsList, joined);
+ }
+
+ private static String invokeParameterInfo() {
final MethodParameterInfoHandler handler = new MethodParameterInfoHandler();
final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile);
final PsiExpressionList list = handler.findElementForParameterInfo(context);
@@ -31,14 +54,12 @@
assertTrue(context.getItemsToShow().length > 0);
Object[] params = handler.getParametersForDocumentation(context.getItemsToShow()[0], context);
assertNotNull(params);
- String joined = StringUtil.join(params, new Function<Object, String>() {
+ return StringUtil.join(params, new Function<Object, String>() {
@Override
public String fun(Object o) {
return ((PsiParameter)o).getName();
}
}, ",");
- assertEquals(paramsList, joined);
- return params;
}
public void testPrivateMethodOfEnclosingClass() throws Exception {
@@ -49,6 +70,20 @@
doTest("param");
}
+ public void testParameterInfoDoesNotShowInternalJetbrainsAnnotations() throws IOException {
+ configureFromFileText("x.java", "class X { void f(@org.intellij.lang.annotations.Flow int i) { f(<caret>0); }}");
+
+ final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile);
+
+ PsiMethod method = PsiTreeUtil.getParentOfType(myFile.findElementAt(context.getOffset()), PsiMethod.class);
+ final String list = MethodParameterInfoHandler.updateMethodPresentation(method, PsiSubstitutor.EMPTY, new MockParameterInfoUIContext<PsiMethod>(method));
+
+ assertEquals("int i", list);
+
+ PsiAnnotation[] annotations = AnnotationUtil.getAllAnnotations(method.getParameterList().getParameters()[0], false, null);
+ assertEquals(1, annotations.length);
+ }
+
public void testNoParams() throws Exception {
doTestPresentation("<html><no parameters></html>");
}
@@ -66,7 +101,7 @@
assertNotNull(list);
final Object[] itemsToShow = context.getItemsToShow();
assertNotNull(itemsToShow);
- assertTrue(itemsToShow.length == 2);
+ assertEquals(2, itemsToShow.length);
assertTrue(itemsToShow[0] instanceof MethodCandidateInfo);
final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, -1);
final Boolean [] enabled = new Boolean[itemsToShow.length];
@@ -95,7 +130,7 @@
assertNotNull(list);
final Object[] itemsToShow = context.getItemsToShow();
assertNotNull(itemsToShow);
- assertTrue(itemsToShow.length == 2);
+ assertEquals(2, itemsToShow.length);
assertTrue(itemsToShow[0] instanceof MethodCandidateInfo);
final PsiMethod method = ((MethodCandidateInfo)itemsToShow[0]).getElement();
final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, 1);
@@ -118,7 +153,7 @@
assertNotNull(list);
final Object[] itemsToShow = context.getItemsToShow();
assertNotNull(itemsToShow);
- assertTrue(itemsToShow.length == 1);
+ assertEquals(1, itemsToShow.length);
assertTrue(itemsToShow[0] instanceof MethodCandidateInfo);
final PsiMethod method = ((MethodCandidateInfo)itemsToShow[0]).getElement();
final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, -1);
@@ -134,17 +169,21 @@
private void doTestAnnotationPresentation(String expectedString) {
configureByFile(BASE_PATH + getTestName(false) + ".java");
+ String text = invokeParameterInfoForAnnotations();
+ Assert.assertEquals(expectedString, text);
+ }
+
+ private static String invokeParameterInfoForAnnotations() {
final AnnotationParameterInfoHandler handler = new AnnotationParameterInfoHandler();
final CreateParameterInfoContext context = new MockCreateParameterInfoContext(myEditor, myFile);
final PsiAnnotationParameterList list = handler.findElementForParameterInfo(context);
assertNotNull(list);
final Object[] itemsToShow = context.getItemsToShow();
assertNotNull(itemsToShow);
- assertTrue(itemsToShow.length == 1);
+ assertEquals(1, itemsToShow.length);
assertTrue(itemsToShow[0] instanceof PsiAnnotationMethod);
final PsiAnnotationMethod method = (PsiAnnotationMethod)itemsToShow[0];
final ParameterInfoUIContextEx parameterContext = ParameterInfoComponent.createContext(itemsToShow, myEditor, handler, -1);
- Assert.assertEquals(expectedString,
- AnnotationParameterInfoHandler.updateUIText(method, parameterContext));
+ return AnnotationParameterInfoHandler.updateUIText(method, parameterContext);
}
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java
new file mode 100644
index 0000000..f6327b7
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessorTest.java
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.actions;
+
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.module.StdModuleTypes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDirectory;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.file.PsiDirectoryFactory;
+import com.intellij.testFramework.PsiTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase {
+
+ private static final String[] IMPORTS_LIST = new String[]{"import java.util.List;", "import java.util.Set;", "import java.util.Map"};
+
+ private static final String TEST_SOURCE = "%s" +
+ "public class %s {\n" +
+ "\n" +
+ "public void start(String str) {\n" +
+ "}\n" +
+ "\n" +
+ "public static void staticComesSecond(String[] args) {\n" +
+ "}\n" +
+ "\n" +
+ "int firstInt;\n" +
+ "static int notFirstStatic;\n" +
+ "final static String t = \"T\";\n" +
+ "\n" +
+ "}\n";
+
+ private static final String FORMATED_SOURCE = "%s" +
+ "public class %s {\n" +
+ "\n" +
+ " public void start(String str) {\n" +
+ " }\n" +
+ "\n" +
+ " public static void staticComesSecond(String[] args) {\n" +
+ " }\n" +
+ "\n" +
+ " int firstInt;\n" +
+ " static int notFirstStatic;\n" +
+ " final static String t = \"T\";\n" +
+ "\n" +
+ "}\n";
+
+ private static final String ARRANGED_AND_FORMATTED = "public class %s {\n" +
+ "\n" +
+ " final static String t = \"T\";\n" +
+ " static int notFirstStatic;\n" +
+ " int firstInt;\n" +
+ "\n" +
+ " public static void staticComesSecond(String[] args) {\n" +
+ " }\n" +
+ "\n" +
+ " public void start(String str) {\n" +
+ " }\n" +
+ "}";
+ private static final String TEMP_DIR_NAME = "dir";
+ private PsiDirectory myWorkingDirectory;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myWorkingDirectory = createDirectory(getProject().getBaseDir(), TEMP_DIR_NAME);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ super.tearDown();
+ delete(myWorkingDirectory.getVirtualFile());
+ }
+
+ @NotNull
+ protected PsiDirectory getTempRootDirectory() {
+ return myWorkingDirectory;
+ }
+
+ protected void injectMockDialogFlags(ReformatFilesOptions options) {
+ ReformatCodeAction.setTestOptions(options);
+ }
+
+ protected PsiDirectory createDirectory(VirtualFile parent, String name) {
+ VirtualFile dir = createChildDirectory(parent, name);
+ return PsiDirectoryFactory.getInstance(getProject()).createDirectory(dir);
+ }
+
+ @NotNull
+ protected List<PsiFile> createTestFiles(@NotNull VirtualFile parentDirectory, @NotNull String[] fileNames) throws IOException {
+ String[] fileText = createTestJavaClassesWithAdditionalImports(fileNames);
+ List<PsiFile> files = new ArrayList<PsiFile>();
+ for (int i = 0; i < fileNames.length; i++) {
+ String fileName = fileNames[i] + ".java";
+ files.add(createFile(getModule(), parentDirectory, fileName, fileText[i]));
+ }
+ return files;
+ }
+
+ @NotNull
+ protected List<PsiFile> createTestFiles(@NotNull PsiDirectory parentDirectory, @NotNull String[] fileNames) throws IOException {
+ return createTestFiles(parentDirectory.getVirtualFile(), fileNames);
+ }
+
+ protected void performReformatActionOnSelectedFiles(List<PsiFile> files) {
+ final AnAction action = getReformatCodeAction();
+ action.actionPerformed(createEventFor(action, getVirtualFileArrayFrom(files), getProject()));
+ }
+
+ protected void performReformatActionOnSelectedFile(PsiFile file) {
+ final AnAction action = getReformatCodeAction();
+ action.actionPerformed(createEventFor(action, ContainerUtil.newArrayList(file), getProject(), new AdditionalEventInfo().setPsiElement(file)));
+ }
+
+ protected void performReformatActionOnModule(Module module, List<PsiFile> files) {
+ final AnAction action = getReformatCodeAction();
+ action.actionPerformed(createEventFor(action, files, getProject(), new AdditionalEventInfo().setModule(module)));
+ }
+
+ private static AnAction getReformatCodeAction() {
+ final String actionId = IdeActions.ACTION_EDITOR_REFORMAT;
+ return ActionManager.getInstance().getAction(actionId);
+ }
+
+ protected void performReformatActionOnFileInEditor(PsiFile file) {
+ final AnAction action = getReformatCodeAction();
+ Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file);
+ Editor editor = EditorFactory.getInstance().createEditor(document);
+ action.actionPerformed(createEventFor(action, ContainerUtil.newArrayList(file), getProject(), new AdditionalEventInfo().setEditor(editor)));
+ EditorFactory.getInstance().releaseEditor(editor);
+ }
+
+ protected void checkFormationAndImportsOptimizationFor(@NotNull List<PsiFile>... fileCollection) {
+ for (List<PsiFile> files : fileCollection) {
+ for (PsiFile file : files) {
+ String className = getClassNameFromJavaFile(file);
+ assertEquals(getFormattedAndImportOptimizedJavaSourceFor(className), file.getText());
+ }
+ }
+ }
+
+ protected void checkNoProcessingWasPerformedOn(@NotNull List<PsiFile>... fileCollections) {
+ for (List<PsiFile> files : fileCollections) {
+ for (PsiFile file : files) {
+ String className = getClassNameFromJavaFile(file);
+ assertEquals(getUntouchedJavaSourceForTotalProcessing(className), file.getText());
+ }
+ }
+ }
+
+ protected void checkRearrangeReformatAndOptimizeImportsHappend(@NotNull List<PsiFile>... fileCollections) {
+ for (List<PsiFile> files : fileCollections) {
+ for (PsiFile file : files) {
+ String className = getClassNameFromJavaFile(file);
+ assertEquals(getFormattedAndImportOptimizedAndRearrangedJavaSourceFor(className), file.getText());
+ }
+ }
+ }
+
+ protected AnActionEvent createEventFor(AnAction action, final VirtualFile[] files, final Project project) {
+ return new AnActionEvent(null, new DataContext() {
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return files;
+ if (CommonDataKeys.PROJECT.is(dataId)) return project;
+ return null;
+ }
+ }, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0);
+ }
+
+ protected AnActionEvent createEventFor(AnAction action, List<PsiFile> files, final Project project, @NotNull final AdditionalEventInfo eventInfo) {
+ final VirtualFile[] vFilesArray = getVirtualFileArrayFrom(files);
+ return new AnActionEvent(null, new DataContext() {
+ @Nullable
+ @Override
+ public Object getData(@NonNls String dataId) {
+ if (CommonDataKeys.VIRTUAL_FILE_ARRAY.is(dataId)) return vFilesArray;
+ if (CommonDataKeys.PROJECT.is(dataId)) return project;
+ if (CommonDataKeys.EDITOR.is(dataId)) return eventInfo.getEditor();
+ if (LangDataKeys.MODULE_CONTEXT.is(dataId)) return eventInfo.getModule();
+ if (CommonDataKeys.PSI_ELEMENT.is(dataId)) return eventInfo.getElement();
+ return null;
+ }
+ }, "", action.getTemplatePresentation(), ActionManager.getInstance(), 0);
+ }
+
+
+ @NotNull
+ protected String getUntouchedJavaSourceForTotalProcessing(String className) {
+ return createTestJavaClassTextFor(getImportListFrom(IMPORTS_LIST), className);
+ }
+
+ @NotNull
+ protected String getFormattedAndImportOptimizedJavaSourceFor(String className) {
+ return String.format(FORMATED_SOURCE, "", className);
+ }
+
+ @NotNull
+ protected String getFormattedAndImportOptimizedAndRearrangedJavaSourceFor(String className) {
+ return String.format(ARRANGED_AND_FORMATTED, className);
+ }
+
+ @NotNull
+ private String createTestJavaClassTextFor(String imports, String className) {
+ return String.format(TEST_SOURCE, imports, className);
+ }
+
+ @NotNull
+ private String getImportListFrom(String[] imports) {
+ StringBuilder sb = new StringBuilder();
+ for (String anImport : imports) {
+ sb.append(anImport).append('\n');
+ }
+ return String.valueOf(sb);
+ }
+
+ @NotNull
+ protected String getClassNameFromJavaFile(@NotNull PsiFile file) {
+ return file.getName().split("\\.")[0];
+ }
+
+ @NotNull
+ protected String[] createTestJavaClassesWithAdditionalImports(String[] classNames) {
+ String[] classes = new String[classNames.length];
+ for (int i = 0; i < classNames.length; i++) {
+ classes[i] = getUntouchedJavaSourceForTotalProcessing(classNames[i]);
+ }
+ return classes;
+ }
+
+ private VirtualFile[] getVirtualFileArrayFrom(List<PsiFile> files) {
+ VirtualFile[] array = new VirtualFile[files.size()];
+ int i = 0;
+ for (PsiFile f : files) {
+ array[i++] = f.getVirtualFile();
+ }
+ return array;
+ }
+
+ protected Module createModuleWithSourceRoot(String newModuleName) {
+ PsiDirectory dir = createDirectory(getTempRootDirectory().getVirtualFile(), newModuleName);
+ String path = dir.getVirtualFile().getPath() + "/" + newModuleName + ".iml";
+
+ Module module = ModuleManager.getInstance(getProject()).newModule(path, StdModuleTypes.JAVA.getId());
+ PsiDirectory src = createDirectory(dir.getVirtualFile(), "src");
+
+ PsiTestUtil.addSourceRoot(module, src.getVirtualFile());
+ return module;
+ }
+
+ class TestFileStructure {
+ private int myLevel;
+ @NotNull private PsiDirectory myRoot;
+ @NotNull private PsiDirectory myCurrentLevelDirectory;
+ private List<List<PsiFile>> myFilesForLevel = new ArrayList<List<PsiFile>>();
+
+ TestFileStructure(@NotNull PsiDirectory root) {
+ myRoot = root;
+ myCurrentLevelDirectory = root;
+ myFilesForLevel.add(new ArrayList<PsiFile>());
+ myLevel = 0;
+ }
+
+ TestFileStructure addTestFilesToCurrentDirectory(String[] names) throws IOException {
+ getFilesAtLevel(myLevel).addAll(createTestFiles(myCurrentLevelDirectory, names));
+ return this;
+ }
+
+ TestFileStructure createDirectoryAndMakeItCurrent(String name) {
+ myLevel++;
+ myFilesForLevel.add(new ArrayList<PsiFile>());
+ myCurrentLevelDirectory = createDirectory(myCurrentLevelDirectory.getVirtualFile(), name);
+ return this;
+ }
+
+ List<PsiFile> getFilesAtLevel(int level) {
+ assert (myLevel >= level);
+ return myFilesForLevel.get(level);
+ }
+
+ List<PsiFile> getAllFiles() {
+ List<PsiFile> all = new ArrayList<PsiFile>();
+ for (List<PsiFile> files: myFilesForLevel) {
+ all.addAll(files);
+ }
+ return all;
+ }
+ }
+}
+
+
+class AdditionalEventInfo {
+ @Nullable private Editor myEditor;
+ @Nullable private Module myModule;
+ @Nullable private PsiElement myElement;
+
+ @Nullable
+ Module getModule() {
+ return myModule;
+ }
+
+ AdditionalEventInfo setModule(@Nullable Module module) {
+ myModule = module;
+ return this;
+ }
+
+ @Nullable
+ Editor getEditor() {
+ return myEditor;
+ }
+
+ @Nullable
+ PsiElement getElement() {
+ return myElement;
+ }
+
+ AdditionalEventInfo setPsiElement(@Nullable PsiElement element) {
+ myElement = element;
+ return this;
+ }
+
+ AdditionalEventInfo setEditor(@Nullable Editor editor) {
+ myEditor = editor;
+ return this;
+ }
+}
+
+class MockReformatFileSettings implements LayoutCodeOptions {
+ private boolean myProcessWholeFile;
+ private boolean myProcessDirectories;
+ private boolean myRearrange;
+ private boolean myIncludeSubdirs;
+ private boolean myOptimizeImports;
+ private boolean myProcessOnlyChangedText;
+ private boolean myIsOK = true;
+
+ @Override
+ public boolean isProcessWholeFile() {
+ return myProcessWholeFile;
+ }
+
+ MockReformatFileSettings setProcessWholeFile(boolean processWholeFile) {
+ myProcessWholeFile = processWholeFile;
+ return this;
+ }
+
+ @Override
+ public boolean isProcessDirectory() {
+ return myProcessDirectories;
+ }
+
+ MockReformatFileSettings setProcessDirectory(boolean processDirectories) {
+ myProcessDirectories = processDirectories;
+ return this;
+ }
+
+ @Override
+ public boolean isRearrangeEntries() {
+ return myRearrange;
+ }
+
+ @Override
+ public boolean isIncludeSubdirectories() {
+ return myIncludeSubdirs;
+ }
+
+ @Override
+ public boolean isOptimizeImports() {
+ return myOptimizeImports;
+ }
+
+ @NotNull
+ MockReformatFileSettings setOptimizeImports(boolean optimizeImports) {
+ myOptimizeImports = optimizeImports;
+ return this;
+ }
+
+ @Override
+ public boolean isProcessOnlyChangedText() {
+ return myProcessOnlyChangedText;
+ }
+
+ @NotNull
+ MockReformatFileSettings setProcessOnlyChangedText(boolean processOnlyChangedText) {
+ myProcessOnlyChangedText = processOnlyChangedText;
+ return this;
+ }
+
+ @NotNull
+ MockReformatFileSettings setRearrange(boolean rearrange) {
+ myRearrange = rearrange;
+ return this;
+ }
+
+ @NotNull
+ MockReformatFileSettings setIncludeSubdirs(boolean includeSubdirs) {
+ myIncludeSubdirs = includeSubdirs;
+ return this;
+ }
+}
+
+
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java
new file mode 100644
index 0000000..fa0a4c1
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.codeInsight.actions;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author Lepenkin Y.A.
+ */
+public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest {
+
+ private static String[] classNames = {"Vasya", "Main", "Oiie", "Ololo"};
+
+ private TestFileStructure getThreeLevelDirectoryStructure() throws IOException {
+ TestFileStructure fileStructure = new TestFileStructure(getTempRootDirectory());
+ fileStructure.createDirectoryAndMakeItCurrent("dir").addTestFilesToCurrentDirectory(classNames)
+ .createDirectoryAndMakeItCurrent("innerDir").addTestFilesToCurrentDirectory(classNames)
+ .createDirectoryAndMakeItCurrent("innerInnerDir").addTestFilesToCurrentDirectory(classNames);
+ return fileStructure;
+ }
+
+ public void testReformatAndOptimizeMultipleFiles() throws IOException {
+ List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
+
+ performReformatActionOnSelectedFiles(files);
+ checkFormationAndImportsOptimizationFor(files);
+ }
+
+ public void testReformatSingleSelectedFile() throws IOException {
+ List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
+ PsiFile fileToReformat = files.get(0);
+ List<PsiFile> shouldNotBeFormatted = files.subList(1, files.size());
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
+
+ performReformatActionOnSelectedFile(fileToReformat);
+
+ checkFormationAndImportsOptimizationFor(Arrays.asList(fileToReformat));
+ checkNoProcessingWasPerformedOn(shouldNotBeFormatted);
+ }
+
+ public void testReformatAndOptimizeFileFromEditor() throws IOException {
+ List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
+
+ PsiFile fileToFormat = files.get(0);
+ List<PsiFile> shouldNotBeFormatted = files.subList(1, files.size());
+
+ performReformatActionOnFileInEditor(fileToFormat);
+ checkFormationAndImportsOptimizationFor(Arrays.asList(fileToFormat));
+ checkNoProcessingWasPerformedOn(shouldNotBeFormatted);
+ }
+
+ public void testOptimizeAndReformatOnlySelectedFiles() throws IOException {
+ List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
+ List<PsiFile> forProcessing = ContainerUtil.newArrayList(files.get(0), files.get(1));
+ List<PsiFile> noProcessing = ContainerUtil.newArrayList(files.get(2), files.get(3));
+
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
+
+ performReformatActionOnSelectedFiles(forProcessing);
+
+ checkFormationAndImportsOptimizationFor(forProcessing);
+ checkNoProcessingWasPerformedOn(noProcessing);
+ }
+
+ public void testOptimizeAndReformatAllFilesInDirectoryIncludeSubdirs() throws IOException {
+ TestFileStructure fileStructure = getThreeLevelDirectoryStructure();
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setProcessDirectory(true).setIncludeSubdirs(true));
+ PsiFile fileInEditor = fileStructure.getFilesAtLevel(2).get(0);
+ List<PsiFile> shouldNotBeFormatted = fileStructure.getFilesAtLevel(1);
+
+ performReformatActionOnFileInEditor(fileInEditor);
+
+ checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2), fileStructure.getFilesAtLevel(3));
+ checkNoProcessingWasPerformedOn(shouldNotBeFormatted);
+ }
+
+ public void testOptimizeAndReformatAllFilesInDirectoryExcludeSubdirs() throws IOException {
+ TestFileStructure fileStructure = getThreeLevelDirectoryStructure();
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true).setIncludeSubdirs(false));
+
+ performReformatActionOnSelectedFiles(fileStructure.getFilesAtLevel(2));
+
+ checkFormationAndImportsOptimizationFor(fileStructure.getFilesAtLevel(2));
+ checkNoProcessingWasPerformedOn(fileStructure.getFilesAtLevel(1), fileStructure.getFilesAtLevel(3));
+ }
+
+ public void testOptimizeAndReformatInModule() throws IOException {
+ Module module = createModuleWithSourceRoot("newModule");
+ VirtualFile srcDir = ModuleRootManager.getInstance(module).getSourceRoots()[0];
+ List<PsiFile> files = createTestFiles(srcDir, classNames);
+ injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
+
+ performReformatActionOnModule(module, files.subList(0, 1));
+
+ checkFormationAndImportsOptimizationFor(files);
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java
index ec1fa51..2a925bf 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/AbstractCompilerAwareTest.java
@@ -1,9 +1,31 @@
+/*
+ * 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.codeInsight.completion;
+import com.intellij.openapi.compiler.CompilerMessage;
+import com.intellij.openapi.compiler.CompilerMessageCategory;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.psi.PsiType;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.testFramework.CompilerTester;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
-import com.sun.tools.javac.Main;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
import java.io.File;
import java.io.IOException;
@@ -12,19 +34,31 @@
* @author Dmitry Batkovich
*/
public abstract class AbstractCompilerAwareTest extends JavaCodeInsightFixtureTestCase {
- protected final File compileData(final String testCaseName, final String fileToCompile) {
- final File compilerOutput = getCompilerOutputPath(testCaseName);
- assertEquals(Main.compile(
- new String[]{"-g:vars", "-d", compilerOutput.getAbsolutePath(), String.format("%s/%s/%s", getTestDataPath(), testCaseName, fileToCompile)}), 0);
- return compilerOutput;
+ private CompilerTester myCompilerTester;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myCompilerTester = new CompilerTester(true, myModule);
}
- private static File getCompilerOutputPath(final String testCaseName) {
+ @Override
+ protected void tearDown() throws Exception {
+ myCompilerTester.tearDown();
+ super.tearDown();
+ }
+
+ protected final void compileAndIndexData(final String... fileNames) {
try {
- return FileUtil.createTempDirectory(testCaseName, "_compiled");
+ for (String fileName : fileNames) {
+ myFixture.addFileToProject(fileName, FileUtil.loadFile(new File(getTestDataPath() + getName() + "/" + fileName))).getVirtualFile();
+ }
}
catch (IOException e) {
throw new RuntimeException(e);
}
+ for (final CompilerMessage compilerMessage : myCompilerTester.rebuild()) {
+ assertNotSame(compilerMessage.getMessage(), CompilerMessageCategory.ERROR, compilerMessage.getCategory());
+ }
}
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java
index 03f11aa..4e7cc1f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/ClassNameCompletionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,7 +17,7 @@
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.lookup.LookupManager;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.vfs.VirtualFile;
@@ -204,7 +204,7 @@
}
private void cleanupVfs() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
FileDocumentManager.getInstance().saveAllDocuments();
for (VirtualFile file : myFixture.getTempDirFixture().getFile("").getChildren()) {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CustomFileTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CustomFileTypeCompletionTest.java
index 97ba3b3..dd0dc3a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/CustomFileTypeCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/CustomFileTypeCompletionTest.java
@@ -37,6 +37,11 @@
testByCount(2, "case", "catch");
}
+ public void testComment() throws Throwable {
+ configureByFile(BASE_PATH + "foo.cs");
+ testByCount(0, new String[] { null });
+ }
+
public void testPlainTextSubstitution() throws IOException {
FileTypeManagerEx.getInstanceEx().registerFileType(MockLanguageFileType.INSTANCE, "xxx");
try {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy
index c70c166..76041d2 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/GlobalMemberNameCompletionTest.groovy
@@ -246,4 +246,20 @@
myFixture.checkResult output
}
+ public void "test no results in incomplete static import"() {
+ def text = """
+package p;
+
+import static Foo.ba<caret>
+
+class Foo {
+ static void bar() {}
+}
+"""
+ def file = myFixture.addFileToProject("p/Foo.java", text)
+ myFixture.configureFromExistingVirtualFile(file.virtualFile)
+ myFixture.completeBasic()
+ myFixture.checkResult text
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.groovy
index 45f79b2..45a3f81 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/HeavyNormalCompletionTest.groovy
@@ -20,6 +20,8 @@
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiDocumentManager
+import com.intellij.psi.PsiManager
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.testFramework.PsiTestUtil
@@ -141,5 +143,30 @@
myFixture.assertPreferredCompletionItems 0, 'getBuilder'
}
+ public void testNoJavaStructureModificationOnSecondInvocation() {
+ myFixture.configureByText 'a.java', 'class Foo { Xxxxx<caret> }'
+ def oldCount = PsiManager.getInstance(project).modificationTracker.javaStructureModificationCount
+ assert !myFixture.completeBasic()
+ assert !myFixture.completeBasic()
+ assert oldCount == PsiManager.getInstance(project).modificationTracker.javaStructureModificationCount
+ }
+
+ public void testNoJavaStructureModificationOnSecondInvocationAfterTyping() {
+ myFixture.configureByText 'a.java', 'class Foo { Xxxxx<caret> }'
+
+ def tracker = PsiManager.getInstance(project).modificationTracker
+ def oldCount = tracker.javaStructureModificationCount
+ assert !myFixture.completeBasic()
+ assert oldCount == tracker.javaStructureModificationCount
+
+ myFixture.type 'x'
+ PsiDocumentManager.getInstance(project).commitAllDocuments()
+ assert oldCount != tracker.javaStructureModificationCount
+ oldCount = tracker.javaStructureModificationCount
+
+ assert !myFixture.completeBasic()
+ assert !myFixture.completeBasic()
+ assert oldCount == tracker.javaStructureModificationCount
+ }
}
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 04a7324..308d1fb 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/JavaAutoPopupTest.groovy
@@ -24,6 +24,7 @@
import com.intellij.codeInsight.lookup.PsiTypeLookupItem
import com.intellij.codeInsight.lookup.impl.LookupImpl
import com.intellij.codeInsight.template.*
+import com.intellij.codeInsight.template.impl.LiveTemplateDocumentationProvider
import com.intellij.codeInsight.template.impl.TemplateImpl
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.impl.TemplateSettings
@@ -81,7 +82,7 @@
les = myFixture.lookupElementStrings
assert 'iterable' in les
assert 'iter' in les
- assertEquals 'iterable', lookup.currentItem.lookupString
+ assertEquals 'iter', lookup.currentItem.lookupString
assert lookup.focused
type 'a'
@@ -116,7 +117,7 @@
}
""")
type "r"
- myFixture.assertPreferredCompletionItems 1, "iter", "iterable"
+ myFixture.assertPreferredCompletionItems 0, "iter", "iterable"
type '\b'
assertContains "iterable"
@@ -131,7 +132,7 @@
assertContains "iterable"
type "r"
- myFixture.assertPreferredCompletionItems 1, "iter", "iterable"
+ myFixture.assertPreferredCompletionItems 0, "iter", "iterable"
}
public void testExplicitSelectionShouldSurvive() {
@@ -1305,7 +1306,7 @@
type 'e'
myFixture.assertPreferredCompletionItems 0, 'itera', 'itex'
type 'r'
- myFixture.assertPreferredCompletionItems 1, 'iter', 'itera'
+ myFixture.assertPreferredCompletionItems 0, 'iter', 'itera'
type '\b'
myFixture.assertPreferredCompletionItems 0, 'itera', 'itex'
}
@@ -1518,6 +1519,25 @@
assert myFixture.lookupElementStrings == ['public int getField']
}
+ public void "test live template quick doc"() {
+ myFixture.configureByText "a.java", """
+class Cls {
+ void foo() {
+ <caret>
+ }
+ void mySout() {}
+}
+"""
+ type('sout')
+ assert lookup
+ assert 'sout' in myFixture.lookupElementStrings
+
+ def docProvider = new LiveTemplateDocumentationProvider()
+ def docElement = docProvider.getDocumentationElementForLookupItem(myFixture.psiManager, lookup.currentItem, null)
+ assert docElement.presentation.presentableText == 'sout'
+ assert docProvider.generateDoc(docElement, docElement).contains('System.out')
+ }
+
public void "test finishing class reference property value completion with dot opens autopopup"() {
myFixture.configureByText "a.properties", "myprop=ja<caret>"
type 'v'
@@ -1544,7 +1564,7 @@
}
'''
type 'tpl'
- myFixture.assertPreferredCompletionItems 1, 'tpl', 'tplMn'
+ myFixture.assertPreferredCompletionItems 0, 'tpl', 'tplMn'
LookupElementPresentation p = LookupElementPresentation.renderElement(myFixture.lookupElements[0])
assert p.itemText == 'tpl'
@@ -1552,5 +1572,4 @@
def tabKeyPresentation = KeyEvent.getKeyText(TemplateSettings.TAB_CHAR as int)
assert p.typeText == " [$tabKeyPresentation] "
}
-
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java
index f52ec11..74e46e0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/MethodChainsCompletionTest.java
@@ -1,19 +1,16 @@
package com.intellij.codeInsight.completion;
import com.intellij.JavaTestUtil;
-import com.intellij.codeInsight.completion.methodChains.completion.MethodsChainsCompletionContributor;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.ChainCompletionMethodCallLookupElement;
-import com.intellij.codeInsight.completion.methodChains.completion.lookup.WeightableChainLookupElement;
-import com.intellij.codeInsight.completion.methodChains.search.ChainRelevance;
import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.compilerOutputIndex.api.fs.FileVisitorService;
-import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexFeature;
-import com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer;
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeature;
+import com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeaturesHolder;
+import com.intellij.compiler.classFilesIndex.chainsSearch.ChainRelevance;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.MethodsChainsCompletionContributor;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.ChainCompletionMethodCallLookupElement;
+import com.intellij.compiler.classFilesIndex.chainsSearch.completion.lookup.WeightableChainLookupElement;
import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.mock.MockProgressIndicator;
import com.intellij.util.SmartList;
-import java.io.File;
import java.util.List;
/**
@@ -22,19 +19,18 @@
public class MethodChainsCompletionTest extends AbstractCompilerAwareTest {
private final static String TEST_INDEX_FILE_NAME = "TestIndex.java";
private final static String TEST_COMPLETION_FILE_NAME = "TestCompletion.java";
-
private final static String BEFORE_COMPLETION_FILE = "BeforeCompletion.java";
private final static String AFTER_COMPLETION_FILE = "AfterCompletion.java";
@Override
protected void setUp() throws Exception {
super.setUp();
- CompilerOutputIndexFeature.METHOD_CHAINS_COMPLETION.enable();
+ ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION.enable();
}
@Override
protected void tearDown() throws Exception {
- CompilerOutputIndexFeature.METHOD_CHAINS_COMPLETION.disable();
+ ClassFilesIndexFeature.METHOD_CHAINS_COMPLETION.disable();
super.tearDown();
}
@@ -52,7 +48,8 @@
public void testStaticMethod() {
final List<WeightableChainLookupElement> elements = doCompletion();
- assertAdvisorLookupElementEquals("getInstance", 0, 2, 1, 0, assertOneElement(elements));
+ assertSize(2, elements);
+ assertAdvisorLookupElementEquals("getInstance", 0, 2, 1, 0, elements.get(0));
}
public void testStaticMethodAndMethod() {
@@ -86,12 +83,13 @@
assertOneElement(doCompletion());
}
- public void testMethodReturnsSubclassOfTargetClassNotShowed2() {
- assertEmpty(doCompletion());
+ public void testMethodReturnsSubclassOfTargetClassShowed2() {
+ assertOneElement(doCompletion());
}
- public void testResultsForSuperClassesNotShowed() {
- assertEmpty(doCompletion());
+ public void testResultsForSuperClassesShowed() {
+ // if no other elements found we search by super classes
+ assertOneElement(doCompletion());
}
public void testInnerClasses() {
@@ -108,8 +106,9 @@
}
public void testBigrams3() {
- final List<WeightableChainLookupElement> collection = doCompletion();
- assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 2, 8, 3, 0, assertOneElement(collection));
+ final List<WeightableChainLookupElement> elements = doCompletion();
+ assertSize(2, elements);
+ assertAdvisorLookupElementEquals("getInstance().findFile().findElementAt", 2, 8, 3, 0, elements.get(0));
}
public void testMethodWithNoQualifiedVariableInContext() {
@@ -217,18 +216,24 @@
}
private void doTestRendering() {
- PropertiesComponent.getInstance(getProject()).setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(true));
- indexCompiledData(compileData(getName(), TEST_INDEX_FILE_NAME));
+ final ClassFilesIndexFeaturesHolder indicesHolder = ClassFilesIndexFeaturesHolder.getInstance(getProject());
+ PropertiesComponent.getInstance(getProject())
+ .setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(true));
+ indicesHolder.projectOpened();
+ compileAndIndexData(TEST_INDEX_FILE_NAME);
myFixture.configureByFiles(getBeforeCompletionFilePath());
myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD);
- PropertiesComponent.getInstance(getProject()).setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(false));
+ PropertiesComponent.getInstance(getProject())
+ .setValue(ChainCompletionMethodCallLookupElement.PROP_METHODS_CHAIN_COMPLETION_AUTO_COMPLETION, String.valueOf(false));
myFixture.checkResultByFile(getAfterCompletionFilePath());
+ indicesHolder.projectClosed();
}
private List<WeightableChainLookupElement> doCompletion() {
+ final ClassFilesIndexFeaturesHolder indicesHolder = ClassFilesIndexFeaturesHolder.getInstance(getProject());
try {
- indexCompiledData(compileData(getName(), TEST_INDEX_FILE_NAME));
-
+ indicesHolder.projectOpened();
+ compileAndIndexData(TEST_INDEX_FILE_NAME);
final LookupElement[] allLookupElements = runCompletion();
final List<WeightableChainLookupElement> targetLookupElements = new SmartList<WeightableChainLookupElement>();
for (final LookupElement lookupElement : allLookupElements) {
@@ -236,30 +241,20 @@
targetLookupElements.add((WeightableChainLookupElement)lookupElement);
}
}
-
return targetLookupElements;
}
finally {
- final CompilerOutputIndexer indexer = CompilerOutputIndexer.getInstance(getProject());
- indexer.projectClosed();
- indexer.removeIndexes();
+ indicesHolder.projectClosed();
}
}
private LookupElement[] runCompletion() {
myFixture.configureByFiles(getTestCompletionFilePath());
- final LookupElement[] lookupElements = myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD);
+ final LookupElement[] lookupElements =
+ myFixture.complete(CompletionType.BASIC, MethodsChainsCompletionContributor.INVOCATIONS_THRESHOLD);
return lookupElements == null ? LookupElement.EMPTY_ARRAY : lookupElements;
}
- private void indexCompiledData(final File compilerOutput) {
- final FileVisitorService.DirectoryClassFiles visitorService = new FileVisitorService.DirectoryClassFiles(compilerOutput);
- final CompilerOutputIndexer indexer = CompilerOutputIndexer.getInstance(getProject());
- indexer.projectOpened();
- indexer.clear();
- indexer.reindex(visitorService, new MockProgressIndicator());
- }
-
private String getTestCompletionFilePath() {
return getName() + "/" + TEST_COMPLETION_FILE_NAME;
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
index 2f69074..64dba68 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy
@@ -117,10 +117,6 @@
checkPreferredItems(0, "aabbb", "aaa");
}
- public void testDispreferDeclaredOfExpectedType() throws Throwable {
- checkPreferredItems(0, "aabbb", "aaa");
- }
-
public void testDispreferImpls() throws Throwable {
myFixture.addClass("package foo; public class Xxx {}");
configureSecondCompletion();
@@ -456,7 +452,7 @@
myFixture.addClass('public class fooAClass {}')
configureNoCompletion(getTestName(false) + ".java");
myFixture.complete(CompletionType.BASIC, 2);
- assertPreferredItems(0, 'fooy', 'fooAClass', 'fooBar', 'foox');
+ assertPreferredItems(0, 'fooy', 'foox', 'fooAClass', 'fooBar');
}
public void testChangePreselectionOnSecondInvocation() {
@@ -616,4 +612,20 @@
assertPreferredItems 0, 'setText', 'setOurText'
}
+ public void testPreferString() {
+ checkPreferredItems 0, 'String', 'System', 'Set'
+ }
+
+ public void testAnnotationEnum() {
+ checkPreferredItems 0, 'MyEnum.BAR', 'MyEnum', 'MyEnum.FOO'
+ }
+
+ public void testGlobalStaticMemberStats() {
+ configureNoCompletion(getTestName(false) + ".java")
+ myFixture.complete(CompletionType.BASIC, 2)
+ assertPreferredItems 0, 'newLinkedSet0', 'newLinkedSet1', 'newLinkedSet2'
+ incUseCount lookup, 1
+ assertPreferredItems 0, 'newLinkedSet1', 'newLinkedSet0', 'newLinkedSet2'
+ }
+
}
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 48febc3..a511209 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
@@ -100,6 +100,20 @@
assert "Param2" == presentation.itemText
assert presentation.tailText == " (type parameter of goo)"
}
+
+ public void testDisplayDefaultValueInAnnotationMethods() {
+ configure()
+ LookupElementPresentation presentation = renderElement(myItems[0])
+ assert "myBool" == presentation.itemText
+ assert presentation.tailText == " default false"
+ assert presentation.tailFragments[0].grayed
+ assert !presentation.typeText
+ assert !presentation.itemTextBold
+
+ presentation = renderElement(myItems[1])
+ assert "myString" == presentation.itemText
+ assert presentation.tailText == ' default "unknown"'
+ }
public void testMethodItemPresentation() {
configure()
@@ -1129,6 +1143,7 @@
""")
assertOneElement myFixture.completeBasic()
}
+ public void testStaticallyImportedFieldsTwiceSwitch() { doTest() }
public void testStatementKeywords() {
myFixture.configureByText("a.java", """
@@ -1355,8 +1370,7 @@
myFixture.configureByText "a.java", """
class Foo extends my<caret>
"""
- myFixture.completeBasic()
- myFixture.type('\n')
+ myFixture.complete(CompletionType.BASIC, 2)
myFixture.checkResult '''import foo.myClass;
class Foo extends myClass
@@ -1390,4 +1404,11 @@
public void testNoMathTargetMethods() { doAntiTest() }
+ public void testNoLowercaseClasses() {
+ myFixture.addClass("package foo; public class abcdefgXxx {}")
+ doAntiTest()
+ myFixture.complete(CompletionType.BASIC, 2)
+ assertStringItems('abcdefgXxx')
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java
index a25827a..22ed4e8 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SecondSmartTypeCompletionTest.java
@@ -203,7 +203,7 @@
public void testGlobalFactoryMethods() {
configure();
- assertStringItems("createExpected", "Constants.SUBSTRING", "createSubGeneric", "createSubRaw", "createSubString");
+ assertStringItems("Constants.SUBSTRING", "createExpected", "createSubGeneric", "createSubRaw", "createSubString");
}
public void testEmptyMapPresentation() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
index 195a1a8..b19da5a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionOrderingTest.groovy
@@ -149,7 +149,7 @@
}
public void testBooleanValueOf() throws Throwable {
- checkPreferredItems(0, "b", "valueOf", "valueOf", "Boolean.FALSE", "Boolean.TRUE");
+ checkPreferredItems(0, "b", "Boolean.FALSE", "Boolean.TRUE", "equals", "false", "true", "valueOf", "valueOf");
}
public void testXmlTagGetAttribute() throws Throwable {
@@ -161,7 +161,7 @@
}
public void testPreferParametersToGetters() throws Throwable {
- checkPreferredItems(0, "a", "I._1", "valueOf", "getLastI");
+ checkPreferredItems(0, "a", "I._1", "getLastI", "valueOf");
}
public void testExpectedInterfaceShouldGoFirst() throws Throwable {
@@ -178,7 +178,7 @@
}
public void testPreferNonRecursiveMethodParams() throws Throwable {
- checkPreferredItems(0, "b", "hashCode", "s", "a");
+ checkPreferredItems(0, "b", "s", "a", "hashCode");
}
public void testPreferDelegatingMethodParams() throws Throwable {
@@ -302,7 +302,7 @@
}
public void testDispreferGetterInSetterCall() {
- checkPreferredItems 0, 'getZooColor', 'hashCode', 'color', 'getColor'
+ checkPreferredItems 0, 'color', 'getZooColor', 'getColor', 'hashCode'
}
public void testPreferOtherGetterInSetterCall() {
checkPreferredItems 0, 'color', 'getColor', 'getZooColor', 'hashCode'
@@ -321,6 +321,25 @@
checkPreferredItems 0, 'type', 'Object.class'
}
+ public void testPreferStringsInStringConcatenation() {
+ checkPreferredItems 0, 'toString'
+ }
+
+ public void testGlobalStaticMemberStats() {
+ configureNoCompletion(getTestName(false) + ".java")
+ myFixture.complete(CompletionType.SMART, 2)
+ assertPreferredItems 0, 'newLinkedSet0', 'newLinkedSet1', 'newLinkedSet2'
+ incUseCount lookup, 1
+ assertPreferredItems 0, 'newLinkedSet1', 'newLinkedSet0', 'newLinkedSet2'
+ }
+
+ public void testPreferExpectedTypeMembers() {
+ configureNoCompletion(getTestName(false) + ".java")
+ myFixture.complete(CompletionType.SMART, 2)
+ assertPreferredItems 0, 'MyColor.RED', 'Another.RED'
+ assert lookup.items.size() == 2
+ }
+
@Override
protected String getBasePath() {
return JavaTestUtil.getRelativeJavaTestDataPath() + BASE_PATH;
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
index bea6707..6779aac 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
@@ -317,7 +317,8 @@
checkResultByFile(path + "/after2.java");
}
- public void testInsideCatch() throws Exception { doTest(); }
+ public void testInsideCatch() { doTest(); }
+ public void testInsideCatchFinal() { doTest(); }
public void testGenerics6() throws Exception {
String path = "/generics";
@@ -773,7 +774,7 @@
}
public void testNoClassLiteral() throws Exception {
doActionTest();
- assertStringItems("Object.class", "forName", "forName", "getClass");
+ assertStringItems("Object.class", "getClass", "forName", "forName");
}
public void testClassLiteralInAnno2() throws Throwable {
@@ -994,6 +995,8 @@
public void testCaseMissingEnumValue() throws Throwable { doTest(); }
public void testCaseMissingEnumValue2() throws Throwable { doTest(); }
+
+ public void testNoHiddenParameter() { doTest(); }
public void testTypeVariableInstanceOf() throws Throwable {
configureByTestName();
@@ -1018,6 +1021,7 @@
public void testArrayInitializerBeforeVarargs() throws Throwable { doTest(); }
public void testDuplicateMembersFromSuperClass() throws Throwable { doTest(); }
public void testInnerAfterNew() throws Throwable { doTest(); }
+ public void testEverythingInStringConcatenation() throws Throwable { doTest(); }
public void testMemberImportStatically() {
configureByTestName();
@@ -1106,7 +1110,7 @@
complete();
}
- private void doTest() throws Exception {
+ private void doTest() {
doTest(Lookup.NORMAL_SELECT_CHAR);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
index 968d078..89d3792 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.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,7 @@
import java.util.Collection;
/**
- * This class intended for "heavily-loaded" tests only, e.g. those need to setup separate project directory structure to run.
+ * This class intended for "heavy-loaded" tests only, e.g. those need to setup separate project directory structure to run.
* For "lightweight" tests use LightAdvHighlightingTest.
*/
public class AdvHighlightingTest extends DaemonAnalyzerTestCase {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/HighlightStressTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/HighlightStressTest.java
index 2e5b388..101fe0d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/HighlightStressTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/HighlightStressTest.java
@@ -30,7 +30,7 @@
import com.intellij.codeInspection.unusedImport.UnusedImportLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
@@ -225,7 +225,7 @@
if (v>100) break;
}
final String text = imports + "\n class X {{\n" + usages + "}}";
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
getEditor().getDocument().setText(text);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImplementationsViewTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImplementationsViewTest.java
index 6963712..6e3b0cc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImplementationsViewTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImplementationsViewTest.java
@@ -116,7 +116,7 @@
try {
final String[] visibleFiles = component.getVisibleFiles();
Assert.assertArrayEquals(Arrays.toString(visibleFiles),
- new String[]{"a.java (AFoo)", "a.java (AFoo1 in AFoo)", "a.java (AFoo3 in AFoo)", "a.java (AFoo2 in AFoo)"}, visibleFiles);
+ new String[]{"a.java (AFoo)", "a.java (AFoo1 in AFoo)", "a.java (AFoo2 in AFoo)", "a.java (AFoo3 in AFoo)"}, visibleFiles);
}
finally {
component.removeNotify();
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 1ff6b6a..b50052b 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImportHelperTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/ImportHelperTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.codeInsight.daemon;
import com.intellij.codeInsight.CodeInsightSettings;
@@ -59,7 +74,7 @@
getProject(), new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
try {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java
index 4af4e6b..7ebb887 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk6Test.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.
@@ -59,4 +59,7 @@
public void testRedundantCastInConditionalExpression() throws Exception { setLanguageLevel(LanguageLevel.JDK_1_6); doTest(true, false); }
public void testJava5CastConventions() { setLanguageLevel(LanguageLevel.JDK_1_5); doTest(true, false); }
public void testUnhandledExceptions() { doTest(true, false); }
+ public void testUnhandledExceptionsValueOf() { doTest(true, false); }
+ public void testUnsupportedFeatures7() { doTest(false, false); }
+ public void testEnumInitializers() { doTest(false, false); }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
index 03e81dd..ec16061 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk7Test.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.
@@ -109,8 +109,8 @@
ExtensionPoint<EntryPoint> point = Extensions.getRootArea().getExtensionPoint(ToolExtensionPoints.DEAD_CODE_TOOL);
EntryPoint extension = new EntryPoint() {
@NotNull @Override public String getDisplayName() { return "duh"; }
- @Override public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) { return false; }
- @Override public boolean isEntryPoint(PsiElement psiElement) { return false; }
+ @Override public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) { return false; }
+ @Override public boolean isEntryPoint(@NotNull PsiElement psiElement) { return false; }
@Override public boolean isSelected() { return false; }
@Override public void setSelected(boolean selected) { }
@Override public void readExternal(Element element) { }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
index 79c45a9..974a322 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingTest.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,6 +16,7 @@
package com.intellij.codeInsight.daemon;
import com.intellij.ToolExtensionPoints;
+import com.intellij.codeInsight.daemon.impl.DaemonCodeAnalyzerImpl;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstance;
@@ -31,10 +32,13 @@
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageAnnotators;
+import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.StdFileTypes;
@@ -53,6 +57,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import java.awt.*;
import java.io.IOException;
import java.util.List;
@@ -229,12 +234,12 @@
}
@Override
- public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
return false;
}
@Override
- public boolean isEntryPoint(PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull PsiElement psiElement) {
return psiElement instanceof PsiMethod && ((PsiMethod)psiElement).getName().equals("myTestMethod");
}
@@ -270,7 +275,7 @@
enableInspectionTool(deadCodeInspection);
doTest(true, false);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
PsiDirectory directory = myFile.getParent();
@@ -392,4 +397,44 @@
List<HighlightInfo> infos = highlightErrors();
assertTrue(!infos.isEmpty());
}
+
+ public static class MyTopFileAnnotator implements Annotator {
+ @Override
+ public void annotate(@NotNull PsiElement psiElement, @NotNull final AnnotationHolder holder) {
+ if (psiElement instanceof PsiFile && !psiElement.getText().contains("xxx")) {
+ Annotation annotation = holder.createWarningAnnotation(psiElement, "top level");
+ annotation.setFileLevelAnnotation(true);
+ }
+ }
+ }
+
+ public void testAnnotatorWorksWithFileLevel() {
+ Annotator annotator = new MyTopFileAnnotator();
+ Language java = StdFileTypes.JAVA.getLanguage();
+ LanguageAnnotators.INSTANCE.addExplicitExtension(java, annotator);
+ try {
+ List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(java);
+ assertTrue(list.toString(), list.contains(annotator));
+ configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
+ ((EditorEx)getEditor()).getScrollPane().getViewport().setSize(new Dimension(1000,1000)); // whole file fit onscreen
+ doHighlighting();
+ List<HighlightInfo> fileLevel =
+ ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(ourProject)).getFileLevelHighlights(getProject(), getFile());
+ HighlightInfo info = assertOneElement(fileLevel);
+ assertEquals("top level", info.getDescription());
+
+ type("//xxx"); //disable top level annotation
+ List<HighlightInfo> warnings = doHighlighting(HighlightSeverity.WARNING);
+ assertEmpty(warnings);
+ fileLevel = ((DaemonCodeAnalyzerImpl)DaemonCodeAnalyzer.getInstance(ourProject)).getFileLevelHighlights(getProject(), getFile());
+ assertEmpty(fileLevel);
+ }
+ finally {
+ LanguageAnnotators.INSTANCE.removeExplicitExtension(java, annotator);
+ }
+
+ List<Annotator> list = LanguageAnnotators.INSTANCE.allForLanguage(java);
+ assertFalse(list.toString(), list.contains(annotator));
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LossyEncodingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LossyEncodingTest.java
index ad65d8b..903905e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LossyEncodingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LossyEncodingTest.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,11 @@
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.LossyEncodingInspection;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.FileTypes;
+import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
@@ -41,7 +45,7 @@
import java.util.Collection;
import java.util.List;
-public class LossyEncodingTest extends LightDaemonAnalyzerTestCase {
+public class LossyEncodingTest extends DaemonAnalyzerTestCase {
@NonNls private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lossyEncoding";
@NotNull
@@ -53,6 +57,7 @@
public void testText() throws Exception {
doTest("Text.txt");
Charset ascii = CharsetToolkit.forName("US-ASCII");
+ VirtualFile myVFile = myFile.getVirtualFile();
EncodingManager.getInstance().setEncoding(myVFile, ascii);
assertEquals(ascii, myVFile.getCharset());
int start = myEditor.getCaretModel().getOffset();
@@ -68,11 +73,12 @@
backspace();
backspace();
- doTestConfiguredFile(true, false, null);
+
+ doDoTest(true, false);
}
public void testNativeConversion() throws Exception {
- configureFromFileText("x.properties","a=<caret>v");
+ configureByText(StdFileTypes.PROPERTIES, "a=<caret>v");
EncodingProjectManager.getInstance(getProject()).setNative2AsciiForPropertiesFiles(null, true);
UIUtil.dispatchAllInvocationEvents(); //reload files
@@ -104,7 +110,7 @@
configureByFile(BASE_PATH + "/" + "MultipleRanges.xml");
type("US-ASCII");
- doTestConfiguredFile(true, false, null);
+ doDoTest(true, false);
}
private void doTest(@NonNls String filePath) throws Exception {
@@ -115,17 +121,28 @@
EncodingManager.getInstance().setNative2AsciiForPropertiesFiles(null, true);
configureByFile(BASE_PATH + "/" + "NativeEncoding.properties");
- doTestConfiguredFile(true, false, null);
+ doDoTest(true, false);
}
- public void testDetectWrongEncoding() throws Exception {
+ public void testDetectWrongEncoding0() throws Exception {
String threeNotoriousRussianLetters = "\u0416\u041e\u041f";
- configureFromFileText("Win1251.txt", threeNotoriousRussianLetters);
+ configureByText(FileTypes.PLAIN_TEXT, threeNotoriousRussianLetters);
VirtualFile virtualFile = getFile().getVirtualFile();
+ final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, " ");
+ document.deleteString(0, 1);
+ }
+ });
+
+
+ assertTrue(FileDocumentManager.getInstance().isDocumentUnsaved(document));
assertEquals(CharsetToolkit.UTF8_CHARSET, virtualFile.getCharset());
Charset WINDOWS_1251 = Charset.forName("windows-1251");
virtualFile.setCharset(WINDOWS_1251);
- FileDocumentManager.getInstance().saveAllDocuments();
+ FileDocumentManager.getInstance().saveAllDocuments(); // save in wrong encoding
assertEquals(WINDOWS_1251, virtualFile.getCharset());
assertEquals(threeNotoriousRussianLetters, new String(virtualFile.contentsToByteArray(), WINDOWS_1251));
virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
@@ -135,4 +152,30 @@
HighlightInfo info = assertOneElement(infos);
assertEquals("File was loaded in the wrong encoding: 'UTF-8'", info.getDescription());
}
+
+ public void testDetectWrongEncoding() throws Exception {
+ VirtualFile virtualFile = getVirtualFile(BASE_PATH + "/" + "Win1251.txt");
+ virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET);
+ configureByExistingFile(virtualFile);
+ final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+
+ assertFalse(FileDocumentManager.getInstance().isDocumentUnsaved(document));
+ assertEquals(CharsetToolkit.UTF8_CHARSET, virtualFile.getCharset());
+
+ doHighlighting();
+ List<HighlightInfo> infos = DaemonCodeAnalyzerEx.getInstanceEx(getProject()).getFileLevelHighlights(getProject(), getFile());
+ HighlightInfo info = assertOneElement(infos);
+ assertEquals("File was loaded in the wrong encoding: 'UTF-8'", info.getDescription());
+ }
+
+ public void testInconsistentLineSeparators() throws Exception {
+ VirtualFile virtualFile = getVirtualFile(BASE_PATH + "/" + getTestName(false) + ".txt");
+ configureByExistingFile(virtualFile);
+ FileDocumentManager.getInstance().saveAllDocuments();
+ final Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+ assertFalse(FileDocumentManager.getInstance().isDocumentUnsaved(document));
+ doHighlighting();
+ List<HighlightInfo> infos = DaemonCodeAnalyzerEx.getInstanceEx(getProject()).getFileLevelHighlights(getProject(), getFile());
+ assertEmpty(infos);
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/RehighlightingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/RehighlightingTest.groovy
index 860be8b..b97c0d6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/RehighlightingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/RehighlightingTest.groovy
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon
-import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase
/**
* @author peter
@@ -54,7 +54,7 @@
myFixture.type(' ')
assert myFixture.doHighlighting().size() > 0
- ApplicationManager.application.runWriteAction {
+ WriteCommandAction.runWriteCommandAction project, {
myFixture.editor.document.insertString(myFixture.editor.caretModel.offset, caption)
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/UnusedSymbolLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/UnusedSymbolLocalTest.java
index ca2c03b..2652f73 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/UnusedSymbolLocalTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/UnusedSymbolLocalTest.java
@@ -1,10 +1,25 @@
+/*
+ * 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.codeInsight.daemon;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.psi.PsiDocumentManager;
@@ -31,7 +46,7 @@
assertEquals(0, collection.size());
final int offset = myEditor.getCaretModel().getOffset();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.insertString(offset, "//");
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java
new file mode 100644
index 0000000..42433d3
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/ConstraintsInferenceMiscTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.Sdk;
+import com.intellij.testFramework.IdeaTestUtil;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * Created by anna on 1/31/14.
+ */
+public class ConstraintsInferenceMiscTest extends LightDaemonAnalyzerTestCase {
+ @NonNls static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/lambda/constraints";
+
+ public void testEqualityUnboundWildcard() throws Exception {
+ doTest(false);
+ }
+
+ public void testPrimitiveTypesCompatibility() throws Exception {
+ doTest(false);
+ }
+
+ public void testTypeCompatibilityUncheckedConversion() throws Exception {
+ doTest(false);
+ }
+
+ public void testTypeCompatibilityUncheckedConversionReturnConstraints() throws Exception {
+ doTest(false);
+ }
+
+ public void testSubtypingExtendsSuper() throws Exception {
+ doTest(false);
+ }
+
+ public void testUncheckedBoundsWithErasure() throws Exception {
+ doTest(false);
+ }
+
+ public void testLambdaGroundTest() throws Exception {
+ doTest(false);
+ }
+
+ private void doTest(final boolean checkWarnings) {
+ doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false);
+ }
+
+ @Override
+ protected Sdk getProjectJDK() {
+ return IdeaTestUtil.getMockJdk18();
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java
index 8841277..8eaf7c3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/FunctionalInterfaceTest.java
@@ -31,7 +31,7 @@
final PsiClass psiClass = getJavaFacade().findClass("Foo", GlobalSearchScope.projectScope(getProject()));
assertNotNull("Class Foo not found", psiClass);
- final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional(psiClass);
+ final String errorMessage = LambdaHighlightingUtil.checkInterfaceFunctional(getJavaFacade().getElementFactory().createType(psiClass));
assertEquals(expectedErrorMessage, errorMessage);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
index 34ae397..e873a0a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/GenericsHighlighting8Test.java
@@ -71,13 +71,13 @@
public void testInferenceWithBounds() {
doTest();
}
- public void testInferenceWithSuperBounds() {
+ public void _testInferenceWithSuperBounds() { //todo waiting for capture bound
doTest();
}
public void testInferenceWithUpperBoundPromotion() {
doTest();
}
- public void testVariance() {
+ public void _testVariance() { //todo waiting for capture bound
doTest();
}
public void testForeachTypes() {
@@ -737,6 +737,10 @@
doTest();
}
+ public void testIDEA114797() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
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 d0048b7..8ca146b 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
@@ -88,7 +88,7 @@
doTest();
}
- public void testCapturedReturnTypes() throws Exception {
+ public void _testCapturedReturnTypes() throws Exception {//todo waiting for capture incorporation
doTest();
}
@@ -108,6 +108,26 @@
doTest();
}
+ public void testErasedByReturnConstraint() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA104429() throws Exception {
+ doTest();
+ }
+
+ public void testTargetTypeByOverloadedMethod() throws Exception {
+ doTest();
+ }
+
+ public void testTargetTypeByOverloadedMethod2() throws Exception {
+ doTest();
+ }
+
+ public void testGrandParentTypeParams() throws Exception {
+ doTest();
+ }
+
private void doTest() throws Exception {
doTest(false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java
index 57a4d72..7e1832a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/Interface8MethodsHighlightingTest.java
@@ -32,6 +32,7 @@
public void testThisAccessibility() { doTest(false, false); }
public void testStaticMethodCalls() { doTest(false, false); }
public void testDefaultMethodOverrideEquivalentObject() { doTest(false, false); }
+ public void testStaticMethods() { doTest(false, false); }
public void testDefaultSupersInStaticContext() {
doTest(false, false);
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java
index 8e43934..93c629a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/LambdaHighlightingTest.java
@@ -97,6 +97,7 @@
public void testWildcardsAndFormalLambdaParams() {doTest();}
public void testFinalInitializer() {doTest();}
public void testBreakContinueInside() {doTest();}
+ public void testSameLambdaParamNames() {doTest();}
private void doTest() {
doTest(false);
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
index 7c25d3b..1d09f51 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/lambda/MethodRefHighlightingTest.java
@@ -48,6 +48,7 @@
public void testConstructorRefsInnerClasses() { doTest(); }
public void testVarargs() { doTest(); }
public void testVarargs1() { doTest(); }
+ public void testVarargs2() { doTest(); }
public void testConstructorRefInnerFromSuper() { doTest(); }
public void testReferenceParameters() { doTest(); }
public void testRawQualifier() { doTest(); }
@@ -94,6 +95,10 @@
doTest();
}
+ public void testUnknownQualifierClass() throws Exception {
+ doTest();
+ }
+
private void doTest() {
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 35b91ef..bfac8d3 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
@@ -95,6 +95,22 @@
doTest();
}
+ public void testRecursiveCalls() throws Exception {
+ doTest();
+ }
+
+ public void testGroundTargetTypeForImplicitLambdas() throws Exception {
+ doTest();
+ }
+
+ public void testAdditionalConstraintsReduceOrder() throws Exception {
+ doTest();
+ }
+
+ public void testAdditionalConstraintSubstitution() 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 ae6ae3b..31b2ec7 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
@@ -20,6 +20,7 @@
import com.intellij.codeInspection.uncheckedWarnings.UncheckedWarningLocalInspection;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import com.intellij.openapi.projectRoots.JavaSdkVersion;
+import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.testFramework.IdeaTestUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -124,6 +125,38 @@
doTest();
}
+ public void testCapturingReturnValue() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA117311() throws Exception {
+ doTest();
+ }
+
+ public void testDeepWildcardEliminating() throws Exception {
+ doTest();
+ }
+
+ public void _testLambdaExercise() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA118437() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA113297() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA120376() throws Exception {
+ doTest();
+ }
+
+ public void testIDEA120370() throws Exception {
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
@@ -132,4 +165,9 @@
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", warnings, false);
}
+
+ @Override
+ protected Sdk getProjectJDK() {
+ return IdeaTestUtil.getMockJdk18();
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AccessStaticViaInstanceTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AccessStaticViaInstanceTest.java
index 4e82b32..82aa508 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AccessStaticViaInstanceTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AccessStaticViaInstanceTest.java
@@ -15,13 +15,21 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.accessStaticViaInstance.AccessStaticViaInstance;
+import org.jetbrains.annotations.NotNull;
-public class AccessStaticViaInstanceTest extends LightQuickFixTestCase {
+public class AccessStaticViaInstanceTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[] {new AccessStaticViaInstance()};
+ }
+
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/accessStaticViaInstance";
}
- public void test() throws Exception { enableInspectionTool(new AccessStaticViaInstance()); doAllTests(); }
+ public void test() throws Exception { doAllTests(); }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddAssertStatementFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddAssertStatementFixTest.java
new file mode 100644
index 0000000..994bcfa
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddAssertStatementFixTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/*
+ * User: anna
+ * Date: 21-Mar-2008
+ */
+package com.intellij.codeInsight.daemon.quickFix;
+
+import com.intellij.codeInspection.LocalInspectionTool;
+import com.intellij.codeInspection.dataFlow.DataFlowInspection;
+import org.jetbrains.annotations.NotNull;
+
+public class AddAssertStatementFixTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[]{new DataFlowInspection()};
+ }
+
+ public void test() throws Exception {
+ doAllTests();
+ }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/addAssert";
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java
index 2fdf1ba..4ef4c49 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToCatchTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class AddExceptionToCatchTest extends LightQuickFixTestCase {
+public class AddExceptionToCatchTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToThrowsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToThrowsTest.java
index 70e61db..f25775f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToThrowsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddExceptionToThrowsTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class AddExceptionToThrowsTest extends LightQuickFixTestCase {
+public class AddExceptionToThrowsTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddMethodBodyTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddMethodBodyTest.java
index 1862adb..86be608 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddMethodBodyTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddMethodBodyTest.java
@@ -1,9 +1,8 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class AddMethodBodyTest extends LightQuickFixTestCase {
+public class AddMethodBodyTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddNewArrayExpressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddNewArrayExpressionTest.java
index f89ddd0..9db9894 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddNewArrayExpressionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddNewArrayExpressionTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class AddNewArrayExpressionTest extends LightQuickFixTestCase {
+public class AddNewArrayExpressionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddReturnTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddReturnTest.java
index 96beeed..456591f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddReturnTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddReturnTest.java
@@ -1,7 +1,6 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class AddReturnTest extends LightQuickFixTestCase {
+public class AddReturnTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsConditionalTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsConditionalTest.java
index 0f13cf3..f21dde3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsConditionalTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsConditionalTest.java
@@ -15,7 +15,9 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class AddTypeArgumentsConditionalTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class AddTypeArgumentsConditionalTest extends LightQuickFixTestCase {
public void test() throws Exception { doAllTests(); }
@@ -23,4 +25,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/addTypeArgumentsConditional";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsTest.java
index f5de535..a902252 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeArgumentsTest.java
@@ -1,6 +1,8 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class AddTypeArgumentsTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class AddTypeArgumentsTest extends LightQuickFixTestCase {
public void test() throws Exception { doAllTests(); }
@@ -9,4 +11,8 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/addTypeArguments";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeCastTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeCastTest.java
index d48013e..c093f06 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeCastTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddTypeCastTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class AddTypeCastTest extends LightQuickFixTestCase {
+public class AddTypeCastTest extends LightQuickFixParameterizedTestCase {
public void test() { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddVariableInitializerTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddVariableInitializerTest.java
index 01eb51a..b4444e0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddVariableInitializerTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AddVariableInitializerTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class AddVariableInitializerTest extends LightQuickFixTestCase {
+public class AddVariableInitializerTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AnnotateMethodTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AnnotateMethodTest.java
index 1b92a0c..39b577f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AnnotateMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/AnnotateMethodTest.java
@@ -4,11 +4,12 @@
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.nullable.NullableStuffInspection;
import com.intellij.openapi.project.Project;
+import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiMethod;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-public class AnnotateMethodTest extends LightQuickFix15TestCase {
+public class AnnotateMethodTest extends LightQuickFixTestCase {
private boolean myMustBeAvailableAfterInvoke;
@Override
@@ -44,4 +45,9 @@
}
public void test() throws Exception { doAllTests(); }
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java
index c21eac6..4689fe1 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2LambdaInspectionTest.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
-public class Anonymous2LambdaInspectionTest extends LightQuickFixTestCase {
+public class Anonymous2LambdaInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java
index 402409c..c41b990 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Anonymous2MethodReferenceInspectionTest.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
-public class Anonymous2MethodReferenceInspectionTest extends LightQuickFixTestCase {
+public class Anonymous2MethodReferenceInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java
index 9468172..b69a4e8 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BreakStringOnLineBreaksTest.java
@@ -18,7 +18,7 @@
/**
* @author Danila Ponomarenko
*/
-public class BreakStringOnLineBreaksTest extends LightQuickFixTestCase {
+public class BreakStringOnLineBreaksTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BringVariableIntoScopeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BringVariableIntoScopeTest.java
index 7663401..b7db420 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BringVariableIntoScopeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/BringVariableIntoScopeTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class BringVariableIntoScopeTest extends LightQuickFixTestCase {
+public class BringVariableIntoScopeTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastConstructorParametersTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastConstructorParametersTest.java
index 95398ec..4ffcda2 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastConstructorParametersTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastConstructorParametersTest.java
@@ -1,9 +1,8 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class CastConstructorParametersTest extends LightQuickFixTestCase {
+public class CastConstructorParametersTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParameters15Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParameters15Test.java
new file mode 100644
index 0000000..a69da29
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParameters15Test.java
@@ -0,0 +1,34 @@
+/*
+ * 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.codeInsight.daemon.quickFix;
+
+public class CastMethodParameters15Test extends LightQuickFixParameterizedTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testPrimitiveWrappers() throws Exception {
+ doSingleTest(getTestName(false) + ".java");
+ }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/castMethodParameters15";
+ }
+}
+
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParametersTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParametersTest.java
index 5acb1fe..93f3ba2 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParametersTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CastMethodParametersTest.java
@@ -1,15 +1,13 @@
-
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
-public class CastMethodParametersTest extends LightQuickFixTestCase {
+public class CastMethodParametersTest extends LightQuickFixParameterizedTestCase {
@Override
- protected void setUp() throws Exception {
- super.setUp();
- LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_3);
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_3;
}
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeExtendsToImplementsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeExtendsToImplementsTest.java
index ef87689..05e4360 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeExtendsToImplementsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeExtendsToImplementsTest.java
@@ -1,11 +1,18 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class ChangeExtendsToImplementsTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class ChangeExtendsToImplementsTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeExtendsToImplements";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeMethodSignatureFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeMethodSignatureFromUsageTest.java
index ee03a40..c48ccb4 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeMethodSignatureFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeMethodSignatureFromUsageTest.java
@@ -1,9 +1,11 @@
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
+
/**
* @author cdr
*/
-public class ChangeMethodSignatureFromUsageTest extends LightQuickFix15TestCase {
+public class ChangeMethodSignatureFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -11,4 +13,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeMethodSignatureFromUsage";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeNewOperatorTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeNewOperatorTypeTest.java
index db262aa..5ff85de 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeNewOperatorTypeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeNewOperatorTypeTest.java
@@ -2,10 +2,14 @@
import com.intellij.pom.java.LanguageLevel;
-public class ChangeNewOperatorTypeTest extends LightQuickFixTestCase {
+public class ChangeNewOperatorTypeTest extends LightQuickFixParameterizedTestCase {
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_7;
+ }
public void test() throws Exception {
- setLanguageLevel(LanguageLevel.JDK_1_7);
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeParameterClassTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeParameterClassTest.java
index f6de85e..8e57f7e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeParameterClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeParameterClassTest.java
@@ -1,14 +1,9 @@
-
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.pom.java.LanguageLevel;
-
-
-public class ChangeParameterClassTest extends LightQuickFix15TestCase {
-
+public class ChangeParameterClassTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
- setLanguageLevel(LanguageLevel.JDK_1_5);
doAllTests();
}
@@ -17,5 +12,9 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeParameterClass";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeStringLiteralToCharInMethodCallTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeStringLiteralToCharInMethodCallTest.java
index be2891a..df95214 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeStringLiteralToCharInMethodCallTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeStringLiteralToCharInMethodCallTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class ChangeStringLiteralToCharInMethodCallTest extends LightQuickFixTestCase {
+public class ChangeStringLiteralToCharInMethodCallTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeToAppendTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeToAppendTest.java
index c7d1a7b..53fa978 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeToAppendTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeToAppendTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class ChangeToAppendTest extends LightQuickFixTestCase {
+public class ChangeToAppendTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeTypeArgumentsFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeTypeArgumentsFixTest.java
index 7aa289c..5a06470 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeTypeArgumentsFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ChangeTypeArgumentsFixTest.java
@@ -15,7 +15,9 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class ChangeTypeArgumentsFixTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class ChangeTypeArgumentsFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -23,4 +25,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/changeTypeArgs";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java
index a13f078..1107d11 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertColorRepresentationTest.java
@@ -15,10 +15,12 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
+
/**
* @author Danila Ponomarenko
*/
-public class ConvertColorRepresentationTest extends LightQuickFix15TestCase {
+public class ConvertColorRepresentationTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -26,4 +28,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/convertColorRepresentation";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertDoubleToFloatFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertDoubleToFloatFixTest.java
index 1f57ad9..00e5d83 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertDoubleToFloatFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertDoubleToFloatFixTest.java
@@ -15,10 +15,12 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
+
/**
* @author cdr
*/
-public class ConvertDoubleToFloatFixTest extends LightQuickFix15TestCase {
+public class ConvertDoubleToFloatFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -26,4 +28,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/convertDoubleToFloat";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java
index d74b67f..5e8879a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertFieldToLocalTest.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
-public class ConvertFieldToLocalTest extends LightQuickFixTestCase {
+public class ConvertFieldToLocalTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertSwitchToIfTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertSwitchToIfTest.java
index 1d7123e..7a962cc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertSwitchToIfTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ConvertSwitchToIfTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class ConvertSwitchToIfTest extends LightQuickFixTestCase {
+public class ConvertSwitchToIfTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationMethodFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationMethodFromUsageTest.java
index 684c27d..5e01d3c 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationMethodFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationMethodFromUsageTest.java
@@ -15,7 +15,9 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class CreateAnnotationMethodFromUsageTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class CreateAnnotationMethodFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
@@ -23,4 +25,8 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/createAnnotationMethodFromUsage";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationTypeFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationTypeFromUsageTest.java
index 969e27e..5a85f95 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationTypeFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateAnnotationTypeFromUsageTest.java
@@ -18,7 +18,7 @@
/**
* @author ven
*/
-public class CreateAnnotationTypeFromUsageTest extends LightQuickFixTestCase{
+public class CreateAnnotationTypeFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromNewTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromNewTest.java
index 82fcd0e..bf3e9a5 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromNewTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromNewTest.java
@@ -20,9 +20,14 @@
/**
* @author ven
*/
-public class CreateClassFromNewTest extends LightQuickFixTestCase {
- public void test() throws Exception {
+public class CreateClassFromNewTest extends LightQuickFixParameterizedTestCase {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
CodeStyleSettingsManager.getSettings(getProject()).SPACE_BEFORE_CLASS_LBRACE = true;
+ }
+
+ public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromUsageTest.java
index 0732ca3..2855c45 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateClassFromUsageTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateClassFromUsageTest extends LightQuickFixTestCase{
+public class CreateClassFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromCallTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromCallTest.java
index 96b7e6b..a4619ad 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromCallTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromCallTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateConstructorFromCallTest extends LightQuickFixTestCase {
+public class CreateConstructorFromCallTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromSuperTest.java
index 7020d4a..023f4b4 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromSuperTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorFromSuperTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateConstructorFromSuperTest extends LightQuickFixTestCase {
+public class CreateConstructorFromSuperTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorMatchingSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorMatchingSuperTest.java
index 13d5b7b..2fca61c 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorMatchingSuperTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorMatchingSuperTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateConstructorMatchingSuperTest extends LightQuickFixTestCase {
+public class CreateConstructorMatchingSuperTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorParameterFromFieldTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorParameterFromFieldTest.java
index 94f8a9c..63fc95e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorParameterFromFieldTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateConstructorParameterFromFieldTest.java
@@ -7,7 +7,7 @@
/**
* @author cdr
*/
-public class CreateConstructorParameterFromFieldTest extends LightQuickFixTestCase {
+public class CreateConstructorParameterFromFieldTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateEnumConstantFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateEnumConstantFromUsageTest.java
index 01dff28..ca5ccc9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateEnumConstantFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateEnumConstantFromUsageTest.java
@@ -1,9 +1,11 @@
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
+
/**
* @author ven
*/
-public class CreateEnumConstantFromUsageTest extends LightQuickFix15TestCase{
+public class CreateEnumConstantFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -12,4 +14,8 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/createEnumConstantFromUsage";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java
index 09b9ebf..fba0c77 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateFieldFromUsageTest.java
@@ -11,7 +11,7 @@
/**
* @author ven
*/
-public class CreateFieldFromUsageTest extends LightQuickFixTestCase{
+public class CreateFieldFromUsageTest extends LightQuickFixTestCase {
public void testAnonymousClass() throws Exception { doSingleTest(); }
public void testExpectedTypes() throws Exception { doSingleTest(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateGetterOrSetterTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateGetterOrSetterTest.java
index a73f222b..0f67365 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateGetterOrSetterTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateGetterOrSetterTest.java
@@ -15,14 +15,21 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
+import org.jetbrains.annotations.NotNull;
/**
* @author Danila Ponomarenko
*/
-public class CreateGetterOrSetterTest extends LightQuickFixTestCase {
+public class CreateGetterOrSetterTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[] {new UnusedSymbolLocalInspection()};
+ }
+
public void test() throws Exception {
- enableInspectionTool(new UnusedSymbolLocalInspection());
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromNewTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromNewTest.java
index 7b53bd1..2fc498c 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromNewTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromNewTest.java
@@ -18,7 +18,7 @@
/**
* @author yole
*/
-public class CreateInnerClassFromNewTest extends LightQuickFixTestCase {
+public class CreateInnerClassFromNewTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromUsageTest.java
index e088ea5..7f420dc 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateInnerClassFromUsageTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateInnerClassFromUsageTest extends LightQuickFixTestCase{
+public class CreateInnerClassFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateLocalFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateLocalFromUsageTest.java
index b529288..bbfb138 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateLocalFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateLocalFromUsageTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateLocalFromUsageTest extends LightQuickFixTestCase {
+public class CreateLocalFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateParameterFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateParameterFromUsageTest.java
index 73c5cd2..4f50040 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateParameterFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreateParameterFromUsageTest.java
@@ -3,7 +3,7 @@
/**
* @author ven
*/
-public class CreateParameterFromUsageTest extends LightQuickFixTestCase{
+public class CreateParameterFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreatePropertyFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreatePropertyFromUsageTest.java
index 0ad7252..1aede55 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreatePropertyFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/CreatePropertyFromUsageTest.java
@@ -15,7 +15,9 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class CreatePropertyFromUsageTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class CreatePropertyFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
@@ -23,4 +25,8 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/createPropertyFromUsage";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeferFinalAssignmentTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeferFinalAssignmentTest.java
index 2b5aead..5064fec 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeferFinalAssignmentTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeferFinalAssignmentTest.java
@@ -1,9 +1,8 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class DeferFinalAssignmentTest extends LightQuickFixTestCase {
+public class DeferFinalAssignmentTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java
index fa38ee7..c53bb00 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DelegateWithDefaultParamValueTest.java
@@ -21,7 +21,7 @@
/**
* @author anna
*/
-public class DelegateWithDefaultParamValueTest extends LightQuickFixTestCase {
+public class DelegateWithDefaultParamValueTest extends LightQuickFixParameterizedTestCase {
@Override
protected void doAction(String text, boolean actionShouldBeAvailable, String testFullPath, String testName)
throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteCatchTest.java
index 7fd7a71..ec78fc3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteCatchTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteCatchTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class DeleteCatchTest extends LightQuickFixTestCase {
+public class DeleteCatchTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteMultiCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteMultiCatchTest.java
index b8d0c02..3f4f78d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteMultiCatchTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/DeleteMultiCatchTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class DeleteMultiCatchTest extends LightQuickFixTestCase {
+public class DeleteMultiCatchTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java
index 0895fd9..579081a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EmptyIntentionInspectionQuickFixTest.java
@@ -17,7 +17,7 @@
/**
* @author cdr
*/
-public class EmptyIntentionInspectionQuickFixTest extends LightQuickFixTestCase{
+public class EmptyIntentionInspectionQuickFixTest extends LightQuickFixTestCase {
@Override
@NonNls
protected String getBasePath() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EnableOptimizeImportsOnTheFlyTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EnableOptimizeImportsOnTheFlyTest.java
index 3da506a..8ebc9aa 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EnableOptimizeImportsOnTheFlyTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/EnableOptimizeImportsOnTheFlyTest.java
@@ -7,7 +7,7 @@
import org.jetbrains.annotations.NotNull;
-public class EnableOptimizeImportsOnTheFlyTest extends LightQuickFixTestCase {
+public class EnableOptimizeImportsOnTheFlyTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllQuickfixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllQuickfixTest.java
index 3cfb844..74563a0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllQuickfixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FixAllQuickfixTest.java
@@ -9,7 +9,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-public class FixAllQuickfixTest extends LightQuickFixTestCase {
+public class FixAllQuickfixTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java
index ddd8ce4..a3501db 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/FlipIntersectionTypesTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class FlipIntersectionTypesTest extends LightQuickFixTestCase {
+public class FlipIntersectionTypesTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java
index 08678c9..ac0c5b4 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GeneralizeCatchTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class GeneralizeCatchTest extends LightQuickFixTestCase {
+public class GeneralizeCatchTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GenericCreateFromUsageTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GenericCreateFromUsageTest.java
index 124ea58..72e724e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GenericCreateFromUsageTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/GenericCreateFromUsageTest.java
@@ -1,9 +1,11 @@
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
+
/**
* @author ven
*/
-public class GenericCreateFromUsageTest extends LightQuickFix15TestCase {
+public class GenericCreateFromUsageTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -11,4 +13,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/genericCreateFromUsage";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nQuickFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nQuickFixTest.java
index 9a9a3c6..f5994cd 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nQuickFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/I18nQuickFixTest.java
@@ -18,12 +18,13 @@
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.i18n.I18nInspection;
import com.intellij.openapi.util.Comparing;
+import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
-public class I18nQuickFixTest extends LightQuickFix15TestCase {
+public class I18nQuickFixTest extends LightQuickFixParameterizedTestCase {
private boolean myMustBeAvailableAfterInvoke;
@NotNull
@@ -50,4 +51,9 @@
protected boolean shouldBeAvailableAfterExecution() {
return myMustBeAvailableAfterInvoke;
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InitializeFinalFieldInConstructorFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InitializeFinalFieldInConstructorFixTest.java
index 4b3c868..ac7bba9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InitializeFinalFieldInConstructorFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InitializeFinalFieldInConstructorFixTest.java
@@ -4,7 +4,7 @@
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import org.jetbrains.annotations.NotNull;
-public class InitializeFinalFieldInConstructorFixTest extends LightQuickFixTestCase {
+public class InitializeFinalFieldInConstructorFixTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertNewTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertNewTest.java
index c23e7cb..9eaa00d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertNewTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertNewTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class InsertNewTest extends LightQuickFixTestCase {
+public class InsertNewTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertSuperTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertSuperTest.java
index 373c039..8c9ef4a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertSuperTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/InsertSuperTest.java
@@ -1,9 +1,8 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class InsertSuperTest extends LightQuickFixTestCase {
+public class InsertSuperTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/IterateOverTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/IterateOverTest.java
index 17cf0dd..3fa2204 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/IterateOverTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/IterateOverTest.java
@@ -1,4 +1,3 @@
-
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
@@ -17,8 +16,9 @@
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
-public class IterateOverTest extends LightQuickFix15TestCase {
+public class IterateOverTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -27,5 +27,9 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/iterateOver";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java
index 17e729e..0dd109f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/JavadocInspectionQuickFixTest.java
@@ -12,9 +12,10 @@
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
+import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
-public class JavadocInspectionQuickFixTest extends LightQuickFix15TestCase {
+public class JavadocInspectionQuickFixTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
@@ -38,4 +39,8 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/javadocTags";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Lambda2MethodReferenceInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Lambda2MethodReferenceInspectionTest.java
index 50de135..2bbe041 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Lambda2MethodReferenceInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Lambda2MethodReferenceInspectionTest.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
-public class Lambda2MethodReferenceInspectionTest extends LightQuickFixTestCase {
+public class Lambda2MethodReferenceInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFix15TestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFix15TestCase.java
deleted file mode 100644
index 63e01f3..0000000
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFix15TestCase.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.daemon.quickFix;
-
-import com.intellij.pom.java.LanguageLevel;
-
-/**
- * @author ven
- */
-public abstract class LightQuickFix15TestCase extends LightQuickFixTestCase {
- @Override
- protected void doAllTests() {
- setLanguageLevel(LanguageLevel.JDK_1_5);
- super.doAllTests();
- }
-}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFixAvailabilityTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFixAvailabilityTestCase.java
index 58a3dac..d000a80 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFixAvailabilityTestCase.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/LightQuickFixAvailabilityTestCase.java
@@ -6,7 +6,7 @@
* tests corresponding intention for availability only, does not invoke action
* @author cdr
*/
-public abstract class LightQuickFixAvailabilityTestCase extends LightQuickFixTestCase {
+public abstract class LightQuickFixAvailabilityTestCase extends LightQuickFixParameterizedTestCase {
@Override
protected void doAction(final String text, final boolean actionShouldBeAvailable, final String testFullPath, final String testName)
throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MakeExtendsThrowableTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MakeExtendsThrowableTest.java
new file mode 100644
index 0000000..7522d18
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MakeExtendsThrowableTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.codeInsight.daemon.quickFix;
+
+import com.intellij.pom.java.LanguageLevel;
+
+public class MakeExtendsThrowableTest extends LightQuickFixParameterizedTestCase {
+ public void test() throws Exception { doAllTests(); }
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/makeExtendsThrowable";
+ }
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
+}
+
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnBooleanTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnBooleanTest.java
index 84e9c33..eba4646 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnBooleanTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnBooleanTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class MethodReturnBooleanTest extends LightQuickFixTestCase {
+public class MethodReturnBooleanTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnTest.java
index 0d76f37..b125ee6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodReturnTest.java
@@ -1,9 +1,9 @@
-
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.pom.java.LanguageLevel;
-public class MethodReturnTest extends LightQuickFix15TestCase {
+public class MethodReturnTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -12,5 +12,9 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/methodReturn";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodThrowsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodThrowsTest.java
index e79fbae..4009bde 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodThrowsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MethodThrowsTest.java
@@ -1,12 +1,18 @@
-
package com.intellij.codeInsight.daemon.quickFix;
+import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.unneededThrows.RedundantThrowsDeclaration;
+import org.jetbrains.annotations.NotNull;
-public class MethodThrowsTest extends LightQuickFixTestCase {
+public class MethodThrowsTest extends LightQuickFixParameterizedTestCase {
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return new LocalInspectionTool[] {new RedundantThrowsDeclaration()};
+ }
- public void test() throws Exception { enableInspectionTool(new RedundantThrowsDeclaration()); doAllTests(); }
+ public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier18Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier18Test.java
index 7e614b7..535bedf 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier18Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Modifier18Test.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class Modifier18Test extends LightQuickFixTestCase {
+public class Modifier18Test extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java
index 6c57880..7f66f3f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ModifierTest.java
@@ -2,7 +2,7 @@
import com.intellij.pom.java.LanguageLevel;
-public class ModifierTest extends LightQuickFixTestCase {
+public class ModifierTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveBoundClassToFrontTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveBoundClassToFrontTest.java
index 215d24a..0b5ac1f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveBoundClassToFrontTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveBoundClassToFrontTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class MoveBoundClassToFrontTest extends LightQuickFixTestCase {
+public class MoveBoundClassToFrontTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveCatchUpTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveCatchUpTest.java
index 3c15ab1..9b84e44 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveCatchUpTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/MoveCatchUpTest.java
@@ -1,7 +1,6 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class MoveCatchUpTest extends LightQuickFixTestCase {
+public class MoveCatchUpTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/NegationBroadScopeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/NegationBroadScopeTest.java
index bbe7511..acb8a0a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/NegationBroadScopeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/NegationBroadScopeTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class NegationBroadScopeTest extends LightQuickFixTestCase {
+public class NegationBroadScopeTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java
index 6bd671b..d2e17d8 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OrderEntryTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.DaemonAnalyzerTestCase;
@@ -5,6 +20,7 @@
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -77,7 +93,7 @@
if (!actionShouldBeAvailable) {
fail("Action '" + text + "' is available in test " + testFullPath);
}
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
action.invoke(getProject(), getEditor(), getFile());
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OverrideMethodTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OverrideMethodTest.java
index cb27ee0..b36f62f 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OverrideMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/OverrideMethodTest.java
@@ -1,4 +1,3 @@
-
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
@@ -16,7 +15,9 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class OverrideMethodTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class OverrideMethodTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
@@ -27,5 +28,9 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/overrideMethod";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PermuteArgumentsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PermuteArgumentsTest.java
index 8093aa9..ca4e77d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PermuteArgumentsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PermuteArgumentsTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class PermuteArgumentsTest extends LightQuickFixTestCase {
+public class PermuteArgumentsTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PushConditionInCallTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PushConditionInCallTest.java
index b80d4a9..0231d30 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PushConditionInCallTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/PushConditionInCallTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class PushConditionInCallTest extends LightQuickFixTestCase{
+public class PushConditionInCallTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyThisArgumentFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyThisArgumentFixTest.java
index c92cb1f..4a02b66 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyThisArgumentFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyThisArgumentFixTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class QualifyThisArgumentFixTest extends LightQuickFixTestCase {
+public class QualifyThisArgumentFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyWithThisFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyWithThisFixTest.java
index 1e8d2ed..5ea6571 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyWithThisFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/QualifyWithThisFixTest.java
@@ -18,7 +18,7 @@
/**
* @author anna
*/
-public class QualifyWithThisFixTest extends LightQuickFixTestCase {
+public class QualifyWithThisFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaCodeBlockInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaCodeBlockInspectionTest.java
index b5ed938..4c298ca 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaCodeBlockInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaCodeBlockInspectionTest.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
-public class RedundantLambdaCodeBlockInspectionTest extends LightQuickFixTestCase {
+public class RedundantLambdaCodeBlockInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java
index 84bdbc6..e9b9645 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RedundantLambdaParameterTypeIntentionTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class RedundantLambdaParameterTypeIntentionTest extends LightQuickFixTestCase {
+public class RedundantLambdaParameterTypeIntentionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveNewQualifierTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveNewQualifierTest.java
index 327fc71..5da1d3d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveNewQualifierTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveNewQualifierTest.java
@@ -1,9 +1,8 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class RemoveNewQualifierTest extends LightQuickFixTestCase {
+public class RemoveNewQualifierTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveQualifierTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveQualifierTest.java
index 5d0bb62..9b13809 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveQualifierTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveQualifierTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class RemoveQualifierTest extends LightQuickFixTestCase {
+public class RemoveQualifierTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java
index 2930d5d..e9b75ea 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantArgumentTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class RemoveRedundantArgumentTest extends LightQuickFixTestCase {
+public class RemoveRedundantArgumentTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java
index ac465b1..0a33ada 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantElseActionTest.java
@@ -19,7 +19,7 @@
* User: anna
* Date: Aug 30, 2010
*/
-public class RemoveRedundantElseActionTest extends LightQuickFixTestCase {
+public class RemoveRedundantElseActionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
index 4afe459..80b5f62 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveRedundantUncheckedSuppressionTest.java
@@ -24,7 +24,7 @@
import org.jetbrains.annotations.NotNull;
-public class RemoveRedundantUncheckedSuppressionTest extends LightQuickFixTestCase {
+public class RemoveRedundantUncheckedSuppressionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveTypeArgumentsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveTypeArgumentsTest.java
index cd1a096..f608409 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveTypeArgumentsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveTypeArgumentsTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class RemoveTypeArgumentsTest extends LightQuickFixTestCase {
+public class RemoveTypeArgumentsTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedParameterTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedParameterTest.java
index fd6afa2..6ca1ef6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedParameterTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedParameterTest.java
@@ -1,4 +1,3 @@
-
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -6,7 +5,7 @@
import org.jetbrains.annotations.NotNull;
-public class RemoveUnusedParameterTest extends LightQuickFixTestCase {
+public class RemoveUnusedParameterTest extends LightQuickFixParameterizedTestCase {
@NotNull
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedVariableTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedVariableTest.java
index 41b0863..e9c74a0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedVariableTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/RemoveUnusedVariableTest.java
@@ -1,11 +1,10 @@
-
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection;
import org.jetbrains.annotations.NotNull;
-public class RemoveUnusedVariableTest extends LightQuickFixTestCase {
+public class RemoveUnusedVariableTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceAddAllArrayToCollectionsFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceAddAllArrayToCollectionsFixTest.java
index 47d7f35..79e6e0e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceAddAllArrayToCollectionsFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceAddAllArrayToCollectionsFixTest.java
@@ -20,7 +20,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class ReplaceAddAllArrayToCollectionsFixTest extends LightQuickFixTestCase {
+public class ReplaceAddAllArrayToCollectionsFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceImplementsWithStaticImportTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceImplementsWithStaticImportTest.java
index cf37964..cfbc836 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceImplementsWithStaticImportTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceImplementsWithStaticImportTest.java
@@ -23,7 +23,7 @@
import com.intellij.JavaTestUtil;
import org.jetbrains.annotations.NotNull;
-public class ReplaceImplementsWithStaticImportTest extends LightQuickFixTestCase {
+public class ReplaceImplementsWithStaticImportTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected String getTestDataPath() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceInaccessibleFieldWithGetterSetterFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceInaccessibleFieldWithGetterSetterFixTest.java
index 426a771..fc520a3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceInaccessibleFieldWithGetterSetterFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceInaccessibleFieldWithGetterSetterFixTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class ReplaceInaccessibleFieldWithGetterSetterFixTest extends LightQuickFixTestCase {
+public class ReplaceInaccessibleFieldWithGetterSetterFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplacePrimitiveWithBoxedTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplacePrimitiveWithBoxedTypeTest.java
index 2784185..75988ef 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplacePrimitiveWithBoxedTypeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplacePrimitiveWithBoxedTypeTest.java
@@ -15,12 +15,19 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class ReplacePrimitiveWithBoxedTypeTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class ReplacePrimitiveWithBoxedTypeTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/replacePrimitiveWithBoxed";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithListAccessTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithListAccessTest.java
index e577764..7e604b7 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithListAccessTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithListAccessTest.java
@@ -18,7 +18,7 @@
/**
* @author Danila Ponomarenko
*/
-public class ReplaceWithListAccessTest extends LightQuickFixTestCase {
+public class ReplaceWithListAccessTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithTernaryOperatorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithTernaryOperatorTest.java
index 3692eec..1cc9ded 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithTernaryOperatorTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReplaceWithTernaryOperatorTest.java
@@ -25,7 +25,7 @@
import com.intellij.codeInspection.nullable.NullableStuffInspection;
import org.jetbrains.annotations.NotNull;
-public class ReplaceWithTernaryOperatorTest extends LightQuickFixTestCase {
+public class ReplaceWithTernaryOperatorTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java
index 043e678..8f79c13 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/ReuseVariableDeclarationTest.java
@@ -1,7 +1,7 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class ReuseVariableDeclarationTest extends LightQuickFixTestCase {
+public class ReuseVariableDeclarationTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SafeVarargsCanBeUsedTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SafeVarargsCanBeUsedTest.java
index 6b4605b..4c5598e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SafeVarargsCanBeUsedTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SafeVarargsCanBeUsedTest.java
@@ -20,7 +20,7 @@
import org.jetbrains.annotations.NotNull;
-public class SafeVarargsCanBeUsedTest extends LightQuickFixTestCase {
+public class SafeVarargsCanBeUsedTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java
index bd3f7a0..eb3b795 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java
@@ -21,7 +21,7 @@
//todo test3 should be checked if it compiles - as now javac infers Object instead of String?!
-public class Simplify2DiamondInspectionsTest extends LightQuickFixTestCase {
+public class Simplify2DiamondInspectionsTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportMethodTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportMethodTest.java
index aa0f827..2414ae9 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/StaticImportMethodTest.java
@@ -1,6 +1,8 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class StaticImportMethodTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class StaticImportMethodTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -8,4 +10,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/staticImportMethod";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuperMethodReturnTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuperMethodReturnTest.java
index 83083c4..243fce3 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuperMethodReturnTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuperMethodReturnTest.java
@@ -1,9 +1,8 @@
-
package com.intellij.codeInsight.daemon.quickFix;
-public class SuperMethodReturnTest extends LightQuickFixTestCase {
+public class SuperMethodReturnTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {doAllTests();}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java
index 2ab3462..c9baaed 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Suppress15InspectionsTest.java
@@ -27,7 +27,7 @@
import org.jetbrains.annotations.NotNull;
-public class Suppress15InspectionsTest extends LightQuickFixTestCase {
+public class Suppress15InspectionsTest extends LightQuickFixParameterizedTestCase {
@Override
protected void setUp() throws Exception {
super.setUp();
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressLocalInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressLocalInspectionTest.java
index a69ef8c..8a992b1 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressLocalInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressLocalInspectionTest.java
@@ -1,4 +1,3 @@
-
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -7,11 +6,10 @@
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
-public class SuppressLocalInspectionTest extends LightQuickFixTestCase {
+public class SuppressLocalInspectionTest extends LightQuickFixParameterizedTestCase {
@Override
- protected void setUp() throws Exception {
- super.setUp();
- LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_3);
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_3;
}
@NotNull
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressNonInspectionsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressNonInspectionsTest.java
index 78ecf4f..2b69de6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressNonInspectionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SuppressNonInspectionsTest.java
@@ -1,4 +1,3 @@
-
package com.intellij.codeInsight.daemon.quickFix;
import com.intellij.codeInspection.LocalInspectionTool;
@@ -14,12 +13,10 @@
import org.jetbrains.annotations.NotNull;
-public class SuppressNonInspectionsTest extends LightQuickFixTestCase {
-
+public class SuppressNonInspectionsTest extends LightQuickFixParameterizedTestCase {
@Override
- protected void setUp() throws Exception {
- super.setUp();
- LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_3);
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_3;
}
@NotNull
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithArrayFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithArrayFixTest.java
index 287edea..00df904 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithArrayFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithArrayFixTest.java
@@ -20,7 +20,9 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class SurroundWithArrayFixTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class SurroundWithArrayFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
@@ -29,4 +31,9 @@
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/surroundWithArray";
}
+
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithIfFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithIfFixTest.java
index 19ed7fc..6283e82 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithIfFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithIfFixTest.java
@@ -24,7 +24,7 @@
import com.intellij.codeInspection.dataFlow.DataFlowInspection;
import org.jetbrains.annotations.NotNull;
-public class SurroundWithIfFixTest extends LightQuickFixTestCase {
+public class SurroundWithIfFixTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithTryCatchTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithTryCatchTest.java
index 207dcf3..c75c6dd 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithTryCatchTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/SurroundWithTryCatchTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class SurroundWithTryCatchTest extends LightQuickFixTestCase {
+public class SurroundWithTryCatchTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/UnimplementIntentionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/UnimplementIntentionTest.java
index accd592..5637c08 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/UnimplementIntentionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/UnimplementIntentionTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-public class UnimplementIntentionTest extends LightQuickFixTestCase {
+public class UnimplementIntentionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java
index d7c4e76..84201d7 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableAccessFromInnerClass18Test.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -15,12 +15,12 @@
*/
package com.intellij.codeInsight.daemon.quickFix;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
/**
* User: anna
*/
-public class VariableAccessFromInnerClass18Test extends LightQuickFixTestCase {
+public class VariableAccessFromInnerClass18Test extends LightQuickFixParameterizedTestCase {
public void test() throws Exception {
doAllTests();
}
@@ -33,7 +33,7 @@
@Override
protected void beforeActionStarted(String testName, String contents) {
for (int i=0;i<10;i++) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
myEditor.getDocument().insertString(myEditor.getCaretModel().getOffset(), "//");
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableArrayTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableArrayTypeTest.java
index fd9765a..99f318e 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableArrayTypeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableArrayTypeTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class VariableArrayTypeTest extends LightQuickFixTestCase {
+public class VariableArrayTypeTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableParameterizedTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableParameterizedTypeTest.java
index 9a7fa9b..0df311d 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableParameterizedTypeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableParameterizedTypeTest.java
@@ -1,6 +1,8 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class VariableParameterizedTypeTest extends LightQuickFix15TestCase {
+import com.intellij.pom.java.LanguageLevel;
+
+public class VariableParameterizedTypeTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@@ -9,5 +11,9 @@
return "/codeInsight/daemonCodeAnalyzer/quickFix/variableParameterizedType";
}
+ @Override
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_5;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeFromCallTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeFromCallTest.java
index 6ee5908..d4f8706 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeFromCallTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeFromCallTest.java
@@ -16,7 +16,7 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class VariableTypeFromCallTest extends LightQuickFixTestCase {
+public class VariableTypeFromCallTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeTest.java
index 0a61f1c..6ce721a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/VariableTypeTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon.quickFix;
-public class VariableTypeTest extends LightQuickFixTestCase {
+public class VariableTypeTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/WrapExpressionFixTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/WrapExpressionFixTest.java
index 92b441a..58d0ea5 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/WrapExpressionFixTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/WrapExpressionFixTest.java
@@ -18,11 +18,10 @@
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.pom.java.LanguageLevel;
-public class WrapExpressionFixTest extends LightQuickFixTestCase {
+public class WrapExpressionFixTest extends LightQuickFixParameterizedTestCase {
@Override
- protected void setUp() throws Exception {
- super.setUp();
- LanguageLevelProjectExtension.getInstance(getProject()).setLanguageLevel(LanguageLevel.JDK_1_6);
+ protected LanguageLevel getLanguageLevel() {
+ return LanguageLevel.JDK_1_6;
}
public void test() throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy
index 2b537de..d6b1e99 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/editorActions/BlockIndentOnPasteTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -14,14 +14,11 @@
* limitations under the License.
*/
package com.intellij.codeInsight.editorActions
-
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.openapi.fileTypes.FileType
import com.intellij.openapi.fileTypes.StdFileTypes
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
-import com.intellij.openapi.application.ApplicationManager
-
-/**
+/**
* @author Denis Zhdanov
* @since 7/6/11 6:52 PM
*/
@@ -760,7 +757,7 @@
try {
def offset = myFixture.editor.caretModel.offset
def column = myFixture.editor.caretModel.logicalPosition.column
- ApplicationManager.application.runWriteAction {
+ com.intellij.openapi.command.WriteCommandAction.runWriteCommandAction project, {
myFixture.editor.document.insertString(offset, toPaste)
PasteHandler.indentBlock(project, myFixture.editor, offset, offset + toPaste.length(), column)
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
index 566d535..686fc6b 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/folding/JavaFoldingTest.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.
@@ -279,6 +279,28 @@
assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("MyAction2(")).placeholderText == '(MyAction2) () -> { '
}
+ public void "test closure folding after paste"() {
+ def text = """\
+class Test {
+<caret>// comment
+ void test() {
+ Runnable r = new Runnable() {
+ public void run() {
+ System.out.println();
+ }
+ };
+ }
+}
+"""
+ configure text
+ myFixture.performEditorAction("EditorCut")
+ myFixture.performEditorAction("EditorPaste")
+
+ def foldingModel = myFixture.editor.foldingModel as FoldingModelImpl
+
+ assert foldingModel.getCollapsedRegionAtOffset(text.indexOf("Runnable(")).placeholderText == '() -> { '
+ }
+
public void "test closure folding when overriding one method of many"() {
myFixture.addClass('abstract class Runnable { void run() {}; void run2() {} }')
myFixture.addClass('abstract class Runnable2 { void run() {}; void run2() {} }')
@@ -435,6 +457,7 @@
configure """class Foo {
int field;
int field2;
+ int field3;
int getField()
{
@@ -445,28 +468,62 @@
field = f;
}
- void setField2(int f){field2=f;}
+ void setField2(int f){field2=f;} // normal method folding here
+
+ // normal method folding here
+ void setField3(int f){
+
+ field2=f;
+ }
}"""
PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
- assert regions.size() == 5
-
- Closure checkAccessorFolding = { FoldRegion region1, FoldRegion region2, PsiMethod method ->
- assert region1.startOffset == method.parameterList.textRange.endOffset
- assert region1.endOffset == method.body.statements[0].textRange.startOffset
- assert region1.placeholderText == ' { '
-
- assert region2.startOffset == method.body.statements[0].textRange.endOffset
- assert region2.endOffset == method.textRange.endOffset
- assert region2.placeholderText == ' }'
- assert region1.group == region2.group
- }
+ assert regions.size() == 6
checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
checkAccessorFolding(regions[2], regions[3], fooClass.methods[1])
assert regions[4].placeholderText == '{...}'
+ assert regions[5].placeholderText == '{...}'
+ }
+
+ static checkAccessorFolding(FoldRegion region1, FoldRegion region2, PsiMethod method) {
+ assert region1.startOffset == method.parameterList.textRange.endOffset
+ assert region1.endOffset == method.body.statements[0].textRange.startOffset
+ assert region1.placeholderText == ' { '
+
+ assert region2.startOffset == method.body.statements[0].textRange.endOffset
+ assert region2.endOffset == method.textRange.endOffset
+ assert region2.placeholderText == ' }'
+ assert region1.group == region2.group
+ }
+
+ public void "test fold one-line methods"() {
+ configure """class Foo {
+ int someMethod() {
+ return 0;
+ }
+
+}"""
+ PsiClass fooClass = JavaPsiFacade.getInstance(project).findClass('Foo', GlobalSearchScope.allScope(project))
+ def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
+ assert regions.size() == 2
+ checkAccessorFolding(regions[0], regions[1], fooClass.methods[0])
+ }
+
+ public void "test don't inline very long one-line methods"() {
+ configure """class Foo {
+ int someVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable;
+
+ // don't create folding that would exceed the right margin
+ int getSomeVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable() {
+ return someVeryVeryLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongLongVariable;
+ }
+}"""
+ def regions = myFixture.editor.foldingModel.allFoldRegions.sort { it.startOffset }
+ assert regions.size() == 1
+ assert regions[0].placeholderText == '{...}'
}
private def changeFoldRegions(Closure op) {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/generation/surroundWith/JavaSurroundWithTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/generation/surroundWith/JavaSurroundWithTest.java
index a7aa174..6f31786 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/generation/surroundWith/JavaSurroundWithTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/generation/surroundWith/JavaSurroundWithTest.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,9 +17,15 @@
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
+import com.intellij.lang.LanguageSurrounders;
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.lang.surroundWith.SurroundDescriptor;
import com.intellij.lang.surroundWith.Surrounder;
+import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
import com.intellij.testFramework.LightCodeInsightTestCase;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -124,9 +130,31 @@
TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
doTest(getTestName(false), new JavaWithNullCheckSurrounder());
}
+
+ public void testSurroundExpressionWithIf() {
+ TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
+ doTest(getTestName(false), new JavaWithIfExpressionSurrounder());
+ }
+
+ public void testSurroundExpressionWithIfForBoxedBooleans() {
+ TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
+ doTest(getTestName(false), new JavaWithIfExpressionSurrounder());
+ }
+
+ public void testSurroundExpressionWithNotForBoxedBooleans() {
+ TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
+ doTest(getTestName(false), new JavaWithNotSurrounder());
+ }
private void doTest(@NotNull String fileName, final Surrounder surrounder) {
configureByFile(BASE_PATH + fileName + ".java");
+
+ SurroundDescriptor item = ContainerUtil.getFirstItem(LanguageSurrounders.INSTANCE.allForLanguage(JavaLanguage.INSTANCE));
+ assertNotNull(item);
+ SelectionModel selectionModel = getEditor().getSelectionModel();
+ PsiElement[] elements = item.getElementsToSurround(getFile(), selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+ assertTrue(surrounder.isApplicable(elements));
+
SurroundWithHandler.invoke(getProject(), getEditor(), getFile(), surrounder);
checkResultByFile(BASE_PATH + fileName + "_after.java");
}
@@ -144,5 +172,4 @@
templateState.nextTab();
checkResultByFile(BASE_PATH + fileName + "_after.java");
}
-
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy
index b2a4447..662762b 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/intention/AddImportActionTest.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.
@@ -25,7 +25,7 @@
myFixture.configureByText 'a.java', '''\
public class Foo {
void foo() {
- Ma<caret>p<> l;
+ Ma<caret>p l;
}
}
'''
@@ -34,7 +34,7 @@
public class Foo {
void foo() {
- Ma<caret>p<> l;
+ Ma<caret>p l;
}
}
'''
@@ -45,7 +45,7 @@
myFixture.configureByText 'a.java', '''\
public class Foo {
void foo() {
- Ma<caret>p<> l;
+ Ma<caret>p l;
}
}
'''
@@ -54,7 +54,7 @@
public class Foo {
void foo() {
- Ma<caret>p<> l;
+ Ma<caret>p l;
}
}
'''
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/intention/CreateSubclassTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/intention/CreateSubclassTest.java
index b76e7ce..b7be442 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/intention/CreateSubclassTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/intention/CreateSubclassTest.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.codeInsight.intention;
import com.intellij.codeInsight.intention.impl.CreateSubclassAction;
@@ -6,6 +21,7 @@
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.search.ProjectScope;
import com.intellij.refactoring.MultiFileTestCase;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
@@ -47,6 +63,7 @@
});
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/codeInsight/createSubclass/";
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitDeclarationTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitDeclarationTest.java
new file mode 100644
index 0000000..50e46ab
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/intention/SplitDeclarationTest.java
@@ -0,0 +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.codeInsight.intention;
+
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
+import com.intellij.codeInsight.intention.impl.SplitIfAction;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.testFramework.LightCodeInsightTestCase;
+
+public class SplitDeclarationTest extends LightQuickFixParameterizedTestCase {
+
+ @Override
+ protected String getBasePath() {
+ return "/codeInsight/daemonCodeAnalyzer/quickFix/splitDeclaration";
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java
index 757b74e..6df51f0 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java
@@ -55,7 +55,11 @@
public void testEnumValueOf() throws Exception {
doTestMethod();
}
-
+
+ public void testMethodFormatting() throws Exception {
+ doTestMethod();
+ }
+
public void testConstantFieldInitializer() throws Exception {
doTestField();
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/CapitalizeAndUnderscoreTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/template/CapitalizeAndUnderscoreTest.groovy
new file mode 100644
index 0000000..2d8d957
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/CapitalizeAndUnderscoreTest.groovy
@@ -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.codeInsight.template
+
+import com.intellij.codeInsight.template.macro.CapitalizeAndUnderscoreMacro
+import com.intellij.codeInsight.template.macro.SnakeCaseMacro
+import junit.framework.TestCase
+
+/**
+ * @author peter
+ */
+class CapitalizeAndUnderscoreTest extends TestCase {
+
+ public void "test capitalize and underscore"() {
+ assert "FOO_BAR" == cau("fooBar")
+ assert "FOO_BAR" == cau("fooBar")
+ assert "FOO_BAR" == cau("foo-Bar")
+ assert "FOO_BAR" == cau("foo-bar")
+ }
+
+ public void "test snake case"() {
+ assert "foo" == snakeCase("foo")
+ assert "foo_bar" == snakeCase("foo-bar")
+ assert "foo_bar" == snakeCase("fooBar")
+ assert "foo_bar" == snakeCase("FOO_BAR")
+ assert "_foo_bar_" == snakeCase("-FOO-BAR-")
+ assert "a_b_c_d_e_f_g" == snakeCase("a-b.c/d|e*f+g")
+ assert "a_b" == snakeCase("a--b")
+ }
+
+ private static def snakeCase(String s) {
+ return new SnakeCaseMacro().convertString(s)
+ }
+ private static def cau(String s) {
+ return new CapitalizeAndUnderscoreMacro().convertString(s)
+ }
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
index 8bdfbf8..939e752 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/LiveTemplateTest.groovy
@@ -14,7 +14,6 @@
* limitations under the License.
*/
package com.intellij.codeInsight.template
-
import com.intellij.JavaTestUtil
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.lookup.LookupManager
@@ -24,10 +23,9 @@
import com.intellij.codeInsight.template.macro.ClassNameCompleteMacro
import com.intellij.codeInsight.template.macro.CompleteMacro
import com.intellij.codeInsight.template.macro.MethodReturnTypeMacro
+import com.intellij.codeInsight.template.macro.SnakeCaseMacro
import com.intellij.openapi.Disposable
-import com.intellij.openapi.application.AccessToken
-import com.intellij.openapi.application.WriteAction
-import com.intellij.openapi.command.CommandProcessor
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.impl.DocumentImpl
import com.intellij.openapi.util.Disposer
@@ -39,7 +37,6 @@
import org.jetbrains.annotations.NotNull
import static com.intellij.codeInsight.template.Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE
-
/**
* @author spleaner
*/
@@ -61,7 +58,9 @@
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
CodeInsightSettings.instance.SELECT_AUTOPOPUP_SUGGESTIONS_BY_CHARS = false
if (state != null) {
- state.gotoEnd();
+ WriteCommandAction.runWriteCommandAction project, {
+ state.gotoEnd()
+ };
}
super.tearDown();
}
@@ -426,15 +425,7 @@
}
private writeCommand(Runnable runnable) {
- CommandProcessor.instance.executeCommand(project, {
- AccessToken token = WriteAction.start()
- try {
- runnable.run()
- }
- finally {
- token.finish()
- }
- }, null, null)
+ WriteCommandAction.runWriteCommandAction(null, runnable)
}
public void testSearchByDescriptionWhenTemplatesListed() {
@@ -611,7 +602,7 @@
}
}'''
myFixture.type('\t')
- assert myFixture.editor.document.text.contains("Outer.Inner.foo")
+ assert myFixture.editor.document.text.contains("\"Inner.foo")
}
public void "test do not strip type argument containing class"() {
@@ -714,4 +705,21 @@
}
+ public void "test snakeCase should convert hyphens to underscores"() {
+ final TemplateManager manager = TemplateManager.getInstance(getProject());
+ final Template template = manager.createTemplate("result", "user", '$A$ $B$ c');
+ template.addVariable('A', new EmptyNode(), true)
+
+ def macroCallNode = new MacroCallNode(new SnakeCaseMacro())
+ macroCallNode.addParameter(new VariableNode('A', null))
+ template.addVariable('B', macroCallNode, false)
+
+ myFixture.configureByText "a.txt", "<caret>"
+ manager.startTemplate(editor, template);
+ myFixture.type('-foo-bar_goo-')
+ state.nextTab()
+ assert !state
+ myFixture.checkResult('-foo-bar_goo- _foo_bar_goo_ c<caret>')
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/completion/ListTemplatesActionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/completion/ListTemplatesActionTest.java
new file mode 100644
index 0000000..e9ef659
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/completion/ListTemplatesActionTest.java
@@ -0,0 +1,55 @@
+/*
+ * 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.codeInsight.template.postfix.completion;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.codeInsight.lookup.Lookup;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.template.impl.ListTemplatesHandler;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+
+public class ListTemplatesActionTest extends LightCodeInsightFixtureTestCase {
+ public void testListTemplates() {
+ doTest();
+ }
+
+ public void testListTemplatesWithPrefix() {
+ doTest();
+ }
+
+ private void doTest() {
+ myFixture.configureByFile(getTestName(true) + ".java");
+ new ListTemplatesHandler().invoke(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile());
+ LookupElement[] elements = myFixture.getLookupElements();
+ assertNotNull(elements);
+
+ LookupElement targetElement = null;
+ for (LookupElement element : elements) {
+ if (element.getLookupString().equals(".not")) {
+ targetElement = element;
+ }
+ }
+ assertNotNull(targetElement);
+ myFixture.getLookup().setCurrentItem(targetElement);
+ myFixture.finishLookup(Lookup.NORMAL_SELECT_CHAR);
+ myFixture.checkResultByFile(getTestName(true) + "_after.java");
+ }
+
+ @Override
+ protected String getBasePath() {
+ return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/template/postfix/listTemplates";
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/completion/TemplatesCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/completion/TemplatesCompletionTest.java
new file mode 100644
index 0000000..26de5c1
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/completion/TemplatesCompletionTest.java
@@ -0,0 +1,206 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.completion;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.codeInsight.completion.CompletionAutoPopupTestCase;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.impl.LookupImpl;
+import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
+import com.intellij.codeInsight.template.postfix.templates.*;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.registry.RegistryValue;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
+
+ private boolean oldRegistryValue;
+
+ @Override
+ public void setUp() {
+ super.setUp();
+ RegistryValue registryValue = Registry.get("show.live.templates.in.completion");
+ oldRegistryValue = registryValue.asBoolean();
+ registryValue.setValue(false);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ RegistryValue registryValue = Registry.get("show.live.templates.in.completion");
+ registryValue.setValue(oldRegistryValue);
+
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ assertNotNull(settings);
+ settings.setTemplatesState(ContainerUtil.<String, Boolean>newHashMap());
+ settings.setPostfixTemplatesEnabled(true);
+ settings.setTemplatesCompletionEnabled(true);
+ super.tearDown();
+ }
+
+ public void testSimpleCompletionList() {
+ Registry.get("show.live.templates.in.completion").setValue(true);
+
+ doAutoPopupTest("ins", InstanceofExpressionPostfixTemplate.class);
+ }
+
+ public void testAutopopupWithEnabledLiveTemplatesInCompletion() {
+ Registry.get("show.live.templates.in.completion").setValue(true);
+
+ configureByFile();
+ type("instanceof");
+ LookupImpl lookup = getLookup();
+ assertNotNull(lookup);
+ assertEquals(1, lookup.getItems().size());
+ LookupElement item = lookup.getCurrentItem();
+ assertNotNull(item);
+ assertInstanceOf(item, PostfixTemplateLookupElement.class);
+ assertInstanceOf(((PostfixTemplateLookupElement)item).getPostfixTemplate(), InstanceofExpressionPostfixTemplate.class);
+ }
+
+ public void testDoNotShowTemplateInInappropriateContext() {
+ doAutoPopupTest("instanceof", null);
+ }
+
+ // IDEA-119910 Middle matching doesn't work if pattern starts with a digit
+ public void testRestartCompletionForExactMatchOnly() {
+ doCompleteTest(".2", '\n');
+ }
+
+ public void testShowTemplateInAutoPopup() {
+ doAutoPopupTest("instanceof", InstanceofExpressionPostfixTemplate.class);
+ }
+
+ public void testShowAutoPopupForAliases() {
+ doAutoPopupTest("nn", NotNullCheckPostfixTemplate.class);
+ }
+
+ public void testShowAutoPopupForFloatLiterals() {
+ doAutoPopupTest("fori", ForAscendingPostfixTemplate.class);
+ }
+
+ public void testDoNotShowTemplateIfPluginIsDisabled() {
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ assertNotNull(settings);
+ settings.setPostfixTemplatesEnabled(false);
+ doAutoPopupTest("instanceof", null);
+ }
+
+ public void testDoNotShowTemplateIfTemplateCompletionIsDisabled() {
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ assertNotNull(settings);
+ settings.setTemplatesCompletionEnabled(false);
+ doAutoPopupTest("instanceof", null);
+ }
+
+ public void testShowTemplateOnDoubleLiteral() {
+ doAutoPopupTest("switch", SwitchStatementPostfixTemplate.class);
+ }
+
+ public void testSelectTemplateByTab() {
+ doCompleteTest("par", '\t');
+ }
+
+ public void testSelectTemplateByEnter() {
+ doCompleteTest("par", '\n');
+ }
+
+ public void testQuickTypingWithTab() {
+ doQuickTypingTest("par", '\t');
+ }
+
+ public void testQuickTypingWithEnter() {
+ doQuickTypingTest("par", '\n');
+ }
+
+ public void testDoNotShowDisabledTemplate() {
+ PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
+ assertNotNull(settings);
+ settings.disableTemplate(new InstanceofExpressionPostfixTemplate());
+ doAutoPopupTest("instanceof", null);
+ }
+
+ public void testDoNotShowTemplateOnCompletion() {
+ configureByFile();
+ myFixture.completeBasic();
+ LookupElement[] elements = myFixture.getLookupElements();
+ assertNotNull(elements);
+ assertNull(ContainerUtil.findInstance(elements, PostfixTemplateLookupElement.class));
+ }
+
+ public void testRecalculatePrefix() {
+ configureByFile();
+ type("par");
+ int selectedIndex = 0;
+ myFixture.assertPreferredCompletionItems(selectedIndex, ".par", "parents");
+
+ type("\b");
+ assertNotNull(getLookup());
+ myFixture.assertPreferredCompletionItems(selectedIndex, "parents");
+
+ type("r");
+ myFixture.assertPreferredCompletionItems(selectedIndex, ".par", "parents");
+ }
+
+ @Override
+ protected String getBasePath() {
+ return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/template/postfix/completion";
+ }
+
+ private void doQuickTypingTest(String textToType, char c) {
+ configureByFile();
+ myFixture.type(textToType + c);
+ checkResultByFile();
+ }
+
+ private void doCompleteTest(String textToType, char c) {
+ configureByFile();
+ type(textToType);
+ assertNotNull(getLookup());
+ myFixture.type(c);
+ checkResultByFile();
+ }
+
+ private void doAutoPopupTest(@NotNull String textToType, @Nullable Class<? extends PostfixTemplate> expectedClass) {
+ configureByFile();
+ type(textToType);
+ LookupImpl lookup = getLookup();
+ if (expectedClass != null) {
+ assertNotNull(lookup);
+ LookupElement item = lookup.getCurrentItem();
+ assertNotNull(item);
+ assertInstanceOf(item, PostfixTemplateLookupElement.class);
+ assertInstanceOf(((PostfixTemplateLookupElement)item).getPostfixTemplate(), expectedClass);
+ }
+ else {
+ assertNull(lookup);
+ }
+ }
+
+ private void configureByFile() {
+ edt(new Runnable() {
+ @Override
+ public void run() {
+ myFixture.configureByFile(getTestName(true) + ".java");
+ }
+ });
+ }
+
+ private void checkResultByFile() {
+ myFixture.checkResultByFile(getTestName(true) + "_after.java");
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplateTest.java
new file mode 100644
index 0000000..bab9ef8
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/AssertStatementPostfixTemplateTest.java
@@ -0,0 +1,21 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class AssertStatementPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "assert"; }
+
+ public void testBooleanVariableBeforeAssignment() { doTest(); }
+ public void testBoxedBooleanVariable() { doTest(); }
+ public void testNotBooleanExpression() { doTest(); }
+ public void testUnresolvedVariable() { doTest(); }
+ public void testSeveralConditions() { doTest(); }
+ public void testIntegerComparison() { doTest(); }
+ public void testMethodInvocation() { doTest(); }
+ public void testInstanceof() { doTest(); }
+ public void testInstanceofBeforeReturnStatement() { doTest(); }
+ public void testNotNull() { doTest(); }
+}
+
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/CastPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/CastPostfixTemplateTest.java
new file mode 100644
index 0000000..dbd4c1d
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/CastPostfixTemplateTest.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class CastPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "cast"; }
+
+ public void testSingleExpression() { doTest(); } // jdk mock needed
+ public void testVoidExpression() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplateTest.java
new file mode 100644
index 0000000..f58016a
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ElseStatementPostfixTemplateTest.java
@@ -0,0 +1,20 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ElseStatementPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "else"; }
+
+ public void testBooleanVariable() { doTest(); }
+ public void testBoxedBooleanVariable() { doTest(); }
+ public void testBitOperations() { doTest(); }
+ public void testBitOperationsWithMethod() { doTest(); }
+ public void testUnresolvedVariable() { doTest(); }
+ public void testInstanceof() { doTest(); }
+ public void testIntegerComparison() { doTest(); }
+ public void testLogicalOperations() { doTest(); }
+
+ public void testNotNull() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/FieldPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/FieldPostfixTemplateTest.java
new file mode 100644
index 0000000..b68477d
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/FieldPostfixTemplateTest.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class FieldPostfixTemplateTest extends PostfixTemplateTestCase {
+ public void testSimple() { doTest(); }
+ public void testFoo() { doTest(); }
+
+ @NotNull
+ @Override
+ protected String getSuffix() { return "field"; }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForAscendingPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForAscendingPostfixTemplateTest.java
new file mode 100644
index 0000000..6c777a0
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForAscendingPostfixTemplateTest.java
@@ -0,0 +1,17 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ForAscendingPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "fori"; }
+
+ public void testIntArray() { doTest(); }
+ public void testIntNumber() { doTest(); }
+ public void testByteNumber() { doTest(); }
+ public void testBoxedByteNumber() { doTest(); }
+ public void testCollection() { doTest(); }
+ public void testBoxedIntegerArray() { doTest(); }
+ public void testBoxedLongArray() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplateTest.java
new file mode 100644
index 0000000..1069df9
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForDescendingPostfixTemplateTest.java
@@ -0,0 +1,14 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ForDescendingPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "forr"; }
+
+ public void testIntArray() { doTest(); }
+ public void testByteNumber() { doTest(); }
+ public void testBoxedIntegerArray() { doTest(); }
+ public void testBoxedLongArray() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForeachTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForeachTemplateTest.java
new file mode 100644
index 0000000..46b274f
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ForeachTemplateTest.java
@@ -0,0 +1,11 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ForeachTemplateTest extends PostfixTemplateTestCase {
+ public void testInts() { doTest(); }
+
+ @NotNull
+ @Override
+ protected String getSuffix() { return "for"; }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplateTest.java
new file mode 100644
index 0000000..41f4fa0
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/IfStatementPostfixTemplateTest.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class IfStatementPostfixTemplateTest extends PostfixTemplateTestCase {
+ public void testBooleanVariableBeforeAssignment() { doTest(); }
+ public void testBoxedBooleanVariable() { doTest(); }
+ public void testNotBooleanExpression() { doTest(); }
+ public void testUnresolvedVariable() { doTest(); }
+ public void testSeveralConditions() { doTest(); }
+ public void testIntegerComparison() { doTest(); }
+ public void testMethodInvocation() { doTest(); }
+ public void testInstanceof() { doTest(); }
+ public void testInstanceofBeforeReturnStatement() { doTest(); }
+
+ @NotNull
+ @Override
+ protected String getSuffix() { return "if"; }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/InstanceofPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/InstanceofPostfixTemplateTest.java
new file mode 100644
index 0000000..f5e363c
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/InstanceofPostfixTemplateTest.java
@@ -0,0 +1,31 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
+import com.intellij.codeInsight.template.impl.TemplateState;
+import org.jetbrains.annotations.NotNull;
+
+public class InstanceofPostfixTemplateTest extends PostfixTemplateTestCase {
+ public void testSingleExpression() { doTest(); }
+ public void testAlias() { doTest(); }
+
+ public void testSingleExpressionTemplate() {
+ TemplateManagerImpl.setTemplateTesting(getProject(), getTestRootDisposable());
+
+ myFixture.configureByFile(getTestName(true) + ".java");
+ myFixture.type('\t');
+
+ TemplateState templateState = TemplateManagerImpl.getTemplateState(myFixture.getEditor());
+ assertNotNull(templateState);
+ assertFalse(templateState.isFinished());
+
+ myFixture.type("Integer");
+ templateState.nextTab();
+ assertTrue(templateState.isFinished());
+
+ myFixture.checkResultByFile(getTestName(true) + "_after.java", true);
+ }
+
+ @NotNull
+ @Override
+ protected String getSuffix() { return "instanceof"; }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplateTest.java
new file mode 100644
index 0000000..f5397f3
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NotExpressionPostfixTemplateTest.java
@@ -0,0 +1,18 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class NotExpressionPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "not"; }
+
+ public void testSimple() { doTest(); }
+ public void testComplexCondition() { doTest(); }
+ public void testBoxedBoolean() { doTest(); }
+ public void testExclamation() { doTest(); }
+// public void testNegation() { doTest(); } // todo: test for chooser
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NotNullPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NotNullPostfixTemplateTest.java
new file mode 100644
index 0000000..ab3b93c
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NotNullPostfixTemplateTest.java
@@ -0,0 +1,16 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class NotNullPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "notnull"; }
+
+ public void testSimple() { doTest(); }
+ public void testNn() { doTest(); }
+ public void testSecondStatement() { doTest(); }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
new file mode 100644
index 0000000..7f501b6
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/NullPostfixTemplateTest.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class NullPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "null"; }
+
+ public void testSimple() { doTest(); }
+ public void testSecondStatement() { doTest(); }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ParPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ParPostfixTemplateTest.java
new file mode 100644
index 0000000..eee136d
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ParPostfixTemplateTest.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class ParPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "par"; }
+
+ public void testSimple() { doTest(); }
+ public void testExtra() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateTestCase.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateTestCase.java
new file mode 100644
index 0000000..8960088
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/PostfixTemplateTestCase.java
@@ -0,0 +1,41 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+
+abstract public class PostfixTemplateTestCase extends LightCodeInsightFixtureTestCase {
+ @Override
+ protected String getBasePath() {
+ return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/template/postfix/templates/" + getSuffix();
+ }
+
+ @Override
+ final protected String getTestDataPath() {
+ return super.getTestDataPath();
+ }
+
+ @NotNull
+ protected abstract String getSuffix();
+
+ protected void doTest() {
+ myFixture.configureByFile(getTestName(true) + ".java");
+ myFixture.type('\t');
+ myFixture.checkResultByFile(getTestName(true) + "_after.java", true);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ myFixture.addClass("package java.lang;\n" +
+ "public final class Boolean implements java.io.Serializable, Comparable<Boolean> {}");
+ myFixture.addClass("package java.lang;\n" +
+ "public final class Byte implements java.io.Serializable, Comparable<Byte> {}");
+ myFixture.addClass("package java.lang;\n" +
+ "public interface Iterable<T> {}");
+ myFixture.addClass("package java.util;\n" +
+ "public class ArrayList<E> extends AbstractList<E>\n" +
+ " implements List<E>, Iterable<E>, RandomAccess, Cloneable, java.io.Serializable {}");
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ReturnPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ReturnPostfixTemplateTest.java
new file mode 100644
index 0000000..a6668e0
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ReturnPostfixTemplateTest.java
@@ -0,0 +1,16 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class ReturnPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "return"; }
+
+ public void testSimple() { doTest(); }
+ public void testComposite() { doTest(); }
+ public void testComposite2() { doTest(); }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/SwitchPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/SwitchPostfixTemplateTest.java
new file mode 100644
index 0000000..7dd70e9
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/SwitchPostfixTemplateTest.java
@@ -0,0 +1,20 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class SwitchPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "switch"; }
+
+ public void testInt() { doTest(); }
+ public void testByte() { doTest(); }
+ public void testChar() { doTest(); }
+ public void testShort() { doTest(); }
+ public void testEnum() { doTest(); }
+ public void testString() { doTest(); }
+ public void testComposite() { doTest(); }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/SynchronizedPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/SynchronizedPostfixTemplateTest.java
new file mode 100644
index 0000000..65f81a8
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/SynchronizedPostfixTemplateTest.java
@@ -0,0 +1,14 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class SynchronizedPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "synchronized"; }
+
+ public void testObject() { doTest(); }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ThrowStatementPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ThrowStatementPostfixTemplateTest.java
new file mode 100644
index 0000000..a163b50
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/ThrowStatementPostfixTemplateTest.java
@@ -0,0 +1,11 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class ThrowStatementPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "throw"; }
+
+ public void testSimple() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/VarPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/VarPostfixTemplateTest.java
new file mode 100644
index 0000000..3567654
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/VarPostfixTemplateTest.java
@@ -0,0 +1,15 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author ignatov
+ */
+public class VarPostfixTemplateTest extends PostfixTemplateTestCase {
+ @NotNull
+ @Override
+ protected String getSuffix() { return "var"; }
+
+ public void testSimple() { doTest(); }
+ public void testAdd() { doTest(); }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplateTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplateTest.java
new file mode 100644
index 0000000..7d975ee
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/template/postfix/templates/WhileStatementPostfixTemplateTest.java
@@ -0,0 +1,14 @@
+package com.intellij.codeInsight.template.postfix.templates;
+
+import org.jetbrains.annotations.NotNull;
+
+public class WhileStatementPostfixTemplateTest extends PostfixTemplateTestCase {
+ public void testBooleanVariable() { doTest(); }
+ public void testBoxedBooleanVariable() { doTest(); }
+ public void testStringVariable() { doTest(); }
+ public void testUnresolvedVariable() { doTest(); }
+
+ @NotNull
+ @Override
+ protected String getSuffix() { return "while"; }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/AnalysisScopeTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/AnalysisScopeTest.java
new file mode 100644
index 0000000..af68ab5
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/AnalysisScopeTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.codeInspection;
+
+import com.intellij.analysis.AnalysisScope;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.ModuleTestCase;
+import com.intellij.testFramework.PsiTestUtil;
+import com.intellij.testFramework.VfsTestUtil;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+
+/**
+ * @author nik
+ */
+public class AnalysisScopeTest extends ModuleTestCase {
+ public void testGeneratedSourceRoot() throws Exception {
+ VirtualFile genRoot = getVirtualFile(createTempDir("genSrcRoot"));
+ VirtualFile srcRoot = getVirtualFile(createTempDir("srcRoot"));
+ JavaSourceRootProperties properties = JpsJavaExtensionService.getInstance().createSourceRootProperties("", true);
+ PsiTestUtil.addSourceRoot(myModule, genRoot, JavaSourceRootType.SOURCE, properties);
+ PsiTestUtil.addSourceRoot(myModule, srcRoot);
+ VirtualFile genClass = VfsTestUtil.createFile(genRoot, "Gen.java", "class Gen{}");
+ VirtualFile srcClass = VfsTestUtil.createFile(srcRoot, "Src.java", "class Src{}");
+ AnalysisScope scope = new AnalysisScope(myModule);
+ assertTrue(scope.contains(srcClass));
+ assertFalse(scope.contains(genClass));
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/ConvertParameterToLocalVariableTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/ConvertParameterToLocalVariableTest.java
index 8a7cf8e..f008400 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/ConvertParameterToLocalVariableTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/ConvertParameterToLocalVariableTest.java
@@ -21,13 +21,13 @@
package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
-import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.varScopeCanBeNarrowed.ParameterCanBeLocalInspection;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-public class ConvertParameterToLocalVariableTest extends LightQuickFixTestCase {
+public class ConvertParameterToLocalVariableTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected String getTestDataPath() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
index 30993c0..e4cf4c7 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java
@@ -104,6 +104,7 @@
public void testChainedFinalFieldAccessorsDfa() throws Throwable { doTest(); }
public void testAccessorPlusMutator() throws Throwable { doTest(); }
public void testClosureVariableField() throws Throwable { doTest(); }
+ public void testOptionalThis() { doTest(); }
public void testAssigningNullableToNotNull() throws Throwable { doTest(); }
public void testAssigningUnknownToNullable() throws Throwable { doTest(); }
@@ -125,7 +126,7 @@
public void testPrimitiveCastMayChangeValue() throws Throwable { doTest(); }
public void testPassingNullableIntoVararg() throws Throwable { doTest(); }
- public void testEqualsImpliesNotNull() throws Throwable { doTest(); }
+ public void testEqualsImpliesNotNull() throws Throwable { doTestReportConstantReferences(); }
public void testEffectivelyUnqualified() throws Throwable { doTest(); }
public void testSkipAssertions() {
@@ -297,6 +298,22 @@
public void testDontForgetInstanceofInfoWhenMerging() { doTest(); }
public void testDontForgetEqInfoWhenMergingByType() { doTest(); }
public void testDontMakeNullableAfterInstanceof() { doTest(); }
+ public void testDontMakeUnrelatedVariableNotNullWhenMerging() { doTest(); }
+ public void testDontMakeUnrelatedVariableFalseWhenMerging() { doTest(); }
+ public void testDontLoseInequalityInformation() { doTest(); }
+
+ public void testNotEqualsTypo() { doTest(); }
+ public void testAndEquals() { doTest(); }
+
+ public void testParametersAreNonnullByDefault() {
+ myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
+ myFixture.addClass("package javax.annotation; public @interface ParametersAreNullableByDefault {}");
+
+ myFixture.addClass("package foo; public class AnotherPackageNotNull { public static void foo(String s) {}}");
+ myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
+
+ doTest();
+ }
public void _testNullCheckBeforeInstanceof() { doTest(); } // http://youtrack.jetbrains.com/issue/IDEA-113220
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java
index e6c17b9..db303c6 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/FieldCanBeLocalTest.java
@@ -38,6 +38,7 @@
public void testFieldUsedInConstantInitialization() throws Exception {doTest();}
public void testFieldWithImmutableType() throws Exception {doTest();}
public void testFieldUsedForWritingInLambda() throws Exception {doTest();}
+ public void testStaticQualifiedFieldAccessForWriting() throws Exception {doTest();}
public void testIgnoreAnnotated() throws Exception {
final FieldCanBeLocalInspection inspection = new FieldCanBeLocalInspection();
doTestConfigured(inspection);
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InlineSameParameterValueTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InlineSameParameterValueTest.java
index 2ca4b72..c1e400c 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/InlineSameParameterValueTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/InlineSameParameterValueTest.java
@@ -5,13 +5,13 @@
package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
-import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.sameParameterValue.SameParameterValueInspection;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-public class InlineSameParameterValueTest extends LightQuickFixTestCase {
+public class InlineSameParameterValueTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected String getTestDataPath() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java
index ed2db87..a84b070 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/InspectionProfileTest.java
@@ -313,7 +313,7 @@
assertEquals(0, countInitializedTools(profile));
profile.writeExternal(new Element("profile"));
List<InspectionToolWrapper> initializedTools = getInitializedTools(profile);
- if (initializedTools.size() != 1) {
+ if (initializedTools.size() > 0) {
for (InspectionToolWrapper initializedTool : initializedTools) {
System.out.println(initializedTool.getShortName());
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java
index a833088..0f4644a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/JavaDocInspectionTest.java
@@ -59,6 +59,12 @@
doTest();
}
+ public void testEnumConstructor() throws Exception {
+ final JavaDocLocalInspection localInspection = new JavaDocLocalInspection();
+ localInspection.METHOD_OPTIONS.ACCESS_JAVADOC_REQUIRED_FOR = "package";
+ doTest("javaDocInspection/" + getTestName(true), localInspection);
+ }
+
public void testIgnoreDuplicateThrows() throws Exception {
final JavaDocLocalInspection inspection = new JavaDocLocalInspection();
inspection.IGNORE_DUPLICATED_THROWS = true;
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspection14Test.java b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspection14Test.java
new file mode 100644
index 0000000..7e57a07
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspection14Test.java
@@ -0,0 +1,67 @@
+/*
+ * Created by IntelliJ IDEA.
+ * User: Alexey
+ * Date: 08.07.2006
+ * Time: 0:07:45
+ */
+package com.intellij.codeInspection;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
+import com.intellij.codeInspection.nullable.NullableStuffInspection;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.SdkModificator;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.InspectionTestCase;
+
+public class NullableStuffInspection14Test extends InspectionTestCase {
+ private final NullableStuffInspection myInspection = new NullableStuffInspection();
+ {
+ myInspection.REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = false;
+ }
+
+ @Override
+ protected String getTestDataPath() {
+ return JavaTestUtil.getJavaTestDataPath() + "/inspection";
+ }
+
+ private void doTest14() throws Exception {
+ myExcludeAnnotations = true;
+ try {
+ doTest("nullableProblems/" + getTestName(true), new LocalInspectionToolWrapper(myInspection),"java 1.4");
+ }
+ finally {
+ myExcludeAnnotations = false;
+ }
+ }
+
+ public void testJdk14() throws Exception{ doTest14(); }
+
+ private boolean myExcludeAnnotations = false;
+
+ @Override
+ protected void setupRootModel(String testDir, VirtualFile[] sourceDir, String sdkName) {
+ super.setupRootModel(testDir, sourceDir, sdkName);
+
+ if (myExcludeAnnotations) {
+ final Sdk sdk = ModuleRootManager.getInstance(myModule).getSdk();
+ assert sdk != null;
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ final SdkModificator sdkMod = sdk.getSdkModificator();
+ for (VirtualFile file : sdkMod.getRoots(OrderRootType.CLASSES)) {
+ if ("annotations.jar".equals(file.getName())) {
+ sdkMod.removeRoot(file, OrderRootType.CLASSES);
+ break;
+ }
+ }
+ sdkMod.commitChanges();
+ }
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
index a36ffac..843dcbb 100644
--- a/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInspection/NullableStuffInspectionTest.java
@@ -7,17 +7,10 @@
package com.intellij.codeInspection;
import com.intellij.JavaTestUtil;
-import com.intellij.codeInspection.ex.LocalInspectionToolWrapper;
import com.intellij.codeInspection.nullable.NullableStuffInspection;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.projectRoots.SdkModificator;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.OrderRootType;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.testFramework.InspectionTestCase;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
-public class NullableStuffInspectionTest extends InspectionTestCase {
+public class NullableStuffInspectionTest extends LightCodeInsightFixtureTestCase {
private final NullableStuffInspection myInspection = new NullableStuffInspection();
{
myInspection.REPORT_ANNOTATION_NOT_PROPAGATED_TO_OVERRIDERS = false;
@@ -25,27 +18,18 @@
@Override
protected String getTestDataPath() {
- return JavaTestUtil.getJavaTestDataPath() + "/inspection";
+ return JavaTestUtil.getJavaTestDataPath() + "/inspection/nullableProblems/";
}
- private void doTest() throws Exception {
- doTest("nullableProblems/" + getTestName(true), new LocalInspectionToolWrapper(myInspection),"java 1.5");
- }
- private void doTest14() throws Exception {
- myExcludeAnnotations = true;
- try {
- doTest("nullableProblems/" + getTestName(true), new LocalInspectionToolWrapper(myInspection),"java 1.4");
- }
- finally {
- myExcludeAnnotations = false;
- }
+ private void doTest() {
+ myFixture.enableInspections(myInspection);
+ myFixture.testHighlighting(true, false, true, getTestName(false) + ".java");
}
public void testProblems() throws Exception{ doTest(); }
public void testProblems2() throws Exception{ doTest(); }
public void testNullableFieldNotnullParam() throws Exception{ doTest(); }
public void testNotNullFieldNullableParam() throws Exception{ doTest(); }
- public void testJdk14() throws Exception{ doTest14(); }
public void testGetterSetterProblems() throws Exception{ doTest(); }
public void testOverriddenMethods() throws Exception{
@@ -53,28 +37,34 @@
doTest();
}
- private boolean myExcludeAnnotations = false;
+ public void testHonorSuperParameterDefault() {
+ myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
+ myFixture.addClass("package javax.annotation; public @interface Nullable {}");
+ myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
- @Override
- protected void setupRootModel(String testDir, VirtualFile[] sourceDir, String sdkName) {
- super.setupRootModel(testDir, sourceDir, sdkName);
+ myFixture.addClass("import javax.annotation.*; package foo; public interface NullableFunction { void fun(@Nullable Object o); }");
+ myFixture.addClass("package foo; public interface AnyFunction { void fun(Object o); }");
- if (myExcludeAnnotations) {
- final Sdk sdk = ModuleRootManager.getInstance(myModule).getSdk();
- assert sdk != null;
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- final SdkModificator sdkMod = sdk.getSdkModificator();
- for (VirtualFile file : sdkMod.getRoots(OrderRootType.CLASSES)) {
- if ("annotations.jar".equals(file.getName())) {
- sdkMod.removeRoot(file, OrderRootType.CLASSES);
- break;
- }
- }
- sdkMod.commitChanges();
- }
- });
- }
+ doTest();
}
+
+ public void testHonorThisParameterDefault() {
+ myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
+ myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
+
+ myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
+ myFixture.enableInspections(myInspection);
+ myFixture.checkHighlighting(true, false, true);
+ }
+
+ public void testHonorParameterDefaultInSetters() {
+ myFixture.addClass("package javax.annotation; public @interface ParametersAreNonnullByDefault {}");
+ myFixture.addClass("package javax.annotation; public @interface Nullable {}");
+ myFixture.addFileToProject("foo/package-info.java", "@javax.annotation.ParametersAreNonnullByDefault package foo;");
+
+ myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".java", "foo/Classes.java"));
+ myFixture.enableInspections(myInspection);
+ myFixture.checkHighlighting(true, false, true);
+ }
+
}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/concurrency/JobUtilTest.java b/java/java-tests/testSrc/com/intellij/concurrency/JobUtilTest.java
index 5df9119..d0ab59b 100644
--- a/java/java-tests/testSrc/com/intellij/concurrency/JobUtilTest.java
+++ b/java/java-tests/testSrc/com/intellij/concurrency/JobUtilTest.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 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.util.Processor;
@@ -29,6 +30,8 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
@@ -72,7 +75,7 @@
return COUNT.incrementAndGet();
}
- public void testJobUtilFinishes() throws Exception {
+ public void testJobUtilCorrectlySplitsUpHugeWorkAndFinishes() throws Exception {
COUNT.set(0);
int N = 100000;
List<String> list = Collections.nCopies(N, null);
@@ -177,7 +180,7 @@
ProgressIndicator actualIndicator = ProgressManager.getInstance().getProgressIndicator();
if (progress == null) {
assertNotNull(actualIndicator);
- assertTrue(actualIndicator instanceof ProgressIndicatorBase);
+ assertTrue(actualIndicator instanceof AbstractProgressIndicatorBase);
}
else {
assertTrue(actualIndicator instanceof SensitiveProgressWrapper);
@@ -258,7 +261,7 @@
public void testJobUtilRecursiveCancel() throws Exception {
final List<String> list = Collections.nCopies(100, "");
final List<Integer> ilist = Collections.nCopies(100, 0);
- for (int i=0; i<1/*0*/; i++) {
+ for (int i=0; i<10; i++) {
COUNT.set(0);
long start = System.currentTimeMillis();
boolean success = false;
@@ -276,7 +279,7 @@
return true;
}
});
- System.out.println("nestedSuccess = " + nestedSuccess);
+ //System.out.println("nestedSuccess = " + nestedSuccess);
return true;
}
});
@@ -293,4 +296,35 @@
assertFalse(success);
}
}
+
+ public void testSaturation() throws InterruptedException {
+ final CountDownLatch latch = new CountDownLatch(1);
+ for (int i=0; i<100; i++) {
+ JobLauncher.getInstance().submitToJobThread(0, new Runnable() {
+ @Override
+ public void run() {
+ try {
+ latch.await();
+ }
+ catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
+ }
+ JobLauncher.getInstance().submitToJobThread(0, new Runnable() {
+ @Override
+ public void run() {
+ latch.countDown();
+ }
+ });
+
+ try {
+ boolean scheduled = latch.await(3, TimeUnit.SECONDS);
+ assertFalse(scheduled); // pool saturated, no thread can be scheduled
+ }
+ finally {
+ latch.countDown();
+ }
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
index 0110fdc..1b11603 100644
--- a/java/java-tests/testSrc/com/intellij/find/FindManagerTest.java
+++ b/java/java-tests/testSrc/com/intellij/find/FindManagerTest.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.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.util.ProperTextRange;
@@ -39,6 +40,7 @@
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.fixtures.TempDirTestFixture;
import com.intellij.testFramework.fixtures.impl.LightTempDirTestFixtureImpl;
+import com.intellij.testFramework.fixtures.impl.TempDirTestFixtureImpl;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.FindUsagesProcessPresentation;
import com.intellij.usages.Usage;
@@ -46,6 +48,7 @@
import com.intellij.util.CommonProcessors;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.WaitFor;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.ArrayList;
@@ -182,11 +185,11 @@
assertEquals(expectedResults, usages.size());
}
- private List<UsageInfo> findUsages(final FindModel findModel) {
+ private List<UsageInfo> findUsages(@NotNull FindModel findModel) {
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.findUsages(findModel, psiDirectory, myProject, true, collector, new FindUsagesProcessPresentation(FindInProjectUtil.setupViewPresentation(true, findModel)));
return result;
}
@@ -370,7 +373,7 @@
}
public void testReplaceAll() throws FindManager.MalformedReplacementStringException {
- FindModel findModel = new FindModel();
+ final FindModel findModel = new FindModel();
String toFind = "xxx";
@SuppressWarnings("SpellCheckingInspection") String toReplace = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
findModel.setStringToFind(toFind);
@@ -389,11 +392,21 @@
String text = StringUtil.repeat(toFind + "\n",6);
configureByText(FileTypes.PLAIN_TEXT, text);
- List<Usage> usages = FindUtil.findAll(getProject(), myEditor, findModel);
+ final List<Usage> usages = FindUtil.findAll(getProject(), myEditor, findModel);
assertNotNull(usages);
- for (Usage usage : usages) {
- ReplaceInProjectManager.getInstance(getProject()).replaceUsage(usage, findModel, Collections.<Usage>emptySet(), false);
- }
+ CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ for (Usage usage : usages) {
+ try {
+ ReplaceInProjectManager.getInstance(getProject()).replaceUsage(usage, findModel, Collections.<Usage>emptySet(), false);
+ }
+ catch (FindManager.MalformedReplacementStringException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ }, "", null);
String newText = StringUtil.repeat(toReplace + "\n",6);
assertEquals(newText, getEditor().getDocument().getText());
}
@@ -467,6 +480,21 @@
FindManagerTestUtils.runFindInCommentsAndLiterals(myFindManager, findModel, text);
}
+ public void testFindInCurrentFileOutsideProject() throws Exception {
+ final TempDirTestFixture tempDirFixture = new TempDirTestFixtureImpl();
+ tempDirFixture.setUp();
+ try {
+ VirtualFile file = tempDirFixture.createFile("a.txt", "foo bar foo");
+ FindModel findModel = FindManagerTestUtils.configureFindModel("foo");
+ findModel.setWholeWordsOnly(true);
+ findModel.setCustomScope(new LocalSearchScope(PsiManager.getInstance(myProject).findFile(file)));
+ assertSize(2, findUsages(findModel));
+ }
+ finally {
+ tempDirFixture.tearDown();
+ }
+ }
+
public void testFindInJavaDocs() {
FindModel findModel = FindManagerTestUtils.configureFindModel("done");
String text = "/** done done done */";
diff --git a/java/java-tests/testSrc/com/intellij/index/IndexTest.java b/java/java-tests/testSrc/com/intellij/index/IndexTest.java
index 6b84a76..7cbe2f6 100644
--- a/java/java-tests/testSrc/com/intellij/index/IndexTest.java
+++ b/java/java-tests/testSrc/com/intellij/index/IndexTest.java
@@ -1,17 +1,32 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
+import com.intellij.psi.*;
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.PsiSearchHelper;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
@@ -182,7 +197,7 @@
assertTrue(new HashSet<T>(Arrays.asList(expected)).equals(new HashSet<T>(actual)));
}
- public void _testCollectedPsiWithChangedDocument() throws IOException {
+ public void testCollectedPsiWithChangedDocument() throws IOException {
VirtualFile dir = getVirtualFile(createTempDirectory());
PsiTestUtil.addSourceContentToRoots(myModule, dir);
@@ -192,23 +207,100 @@
final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
assertNotNull(facade.findClass("Foo", scope));
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
assertNotNull(psiFile);
-
+
Document document = FileDocumentManager.getInstance().getDocument(vFile);
document.deleteString(0, document.getTextLength());
assertNotNull(facade.findClass("Foo", scope));
-
+
psiFile = null;
PlatformTestUtil.tryGcSoftlyReachableObjects();
assertNull(((PsiManagerEx)PsiManager.getInstance(getProject())).getFileManager().getCachedPsiFile(vFile));
- // should be assertNull(facade.findClass("Foo", scope));
- // or the file should not be allowed to be gc'ed
- facade.findClass("Foo", scope).getText();
+ PsiClass foo = facade.findClass("Foo", scope);
+ assertNotNull(foo);
+ assertTrue(foo.isValid());
+ assertEquals("class Foo {}", foo.getText());
+ assertTrue(foo.isValid());
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ assertNull(facade.findClass("Foo", scope));
+ }
+ });
+ }
+
+ public void testSavedUncommittedDocument() throws IOException {
+ VirtualFile dir = getVirtualFile(createTempDirectory());
+ PsiTestUtil.addSourceContentToRoots(myModule, dir);
+
+ final VirtualFile vFile = createChildData(dir, "Foo.java");
+ VfsUtil.saveText(vFile, "");
+
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
+ assertNull(facade.findClass("Foo", scope));
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ @Override
+ public void run() {
+ PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
+ assertNotNull(psiFile);
+
+ long count = PsiManager.getInstance(myProject).getModificationTracker().getModificationCount();
+
+ Document document = FileDocumentManager.getInstance().getDocument(vFile);
+ document.insertString(0, "class Foo {}");
+ FileDocumentManager.getInstance().saveDocument(document);
+
+ assertTrue(count == PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
+ assertNull(facade.findClass("Foo", scope));
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ assertNotNull(facade.findClass("Foo", scope));
+ assertNotNull(facade.findClass("Foo", scope).getText());
+ // if Foo exists now, mod count should be different
+ assertTrue(count != PsiManager.getInstance(myProject).getModificationTracker().getModificationCount());
+ }
+ });
+ }
+
+ public void testSkipUnknownFileTypes() throws IOException {
+ VirtualFile dir = getVirtualFile(createTempDirectory());
+ PsiTestUtil.addSourceContentToRoots(myModule, dir);
+
+ final VirtualFile vFile = createChildData(dir, "Foo.test");
+ VfsUtil.saveText(vFile, "Foo");
+ assertEquals(UnknownFileType.INSTANCE, vFile.getFileType());
+ assertEmpty(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
+
+ final Document document = FileDocumentManager.getInstance().getDocument(vFile);
+ //todo should file type be changed silently without events?
+ //assertEquals(UnknownFileType.INSTANCE, vFile.getFileType());
+
+ final PsiFile file = getPsiFile(document);
+ assertInstanceOf(file, PsiPlainTextFile.class);
+ assertEquals("Foo", file.getText());
+
+ assertEmpty(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
+
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, " ");
+ assertEquals("Foo", file.getText());
+ assertEmpty(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
+
+ FileDocumentManager.getInstance().saveDocument(document);
+ assertEquals("Foo", file.getText());
+ assertEmpty(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
+
+ PsiDocumentManager.getInstance(myProject).commitAllDocuments();
+ assertEquals(" Foo", file.getText());
+ assertEmpty(PsiSearchHelper.SERVICE.getInstance(myProject).findFilesWithPlainTextWords("Foo"));
+
}
});
}
diff --git a/java/java-tests/testSrc/com/intellij/lang/psi/PsiBuilderTest.java b/java/java-tests/testSrc/com/intellij/lang/psi/PsiBuilderTest.java
index a0823ca..833590c 100644
--- a/java/java-tests/testSrc/com/intellij/lang/psi/PsiBuilderTest.java
+++ b/java/java-tests/testSrc/com/intellij/lang/psi/PsiBuilderTest.java
@@ -22,6 +22,7 @@
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaTokenType;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.tree.JavaElementType;
@@ -212,6 +213,7 @@
myBuilder = createBuilder(" bar", tree);
parseWhenEmptyElementAfterWhitespaceIsLastChild();
+ DebugUtil.startPsiModification(null);
try {
myBuilder.getTreeBuilt();
fail();
@@ -219,6 +221,9 @@
catch (BlockSupport.ReparsedSuccessfullyException e) {
e.getDiffLog().performActualPsiChange(tree.getPsi().getContainingFile());
}
+ finally {
+ DebugUtil.finishPsiModification();
+ }
assertEquals(" bar", tree.getText());
}
diff --git a/java/java-tests/testSrc/com/intellij/lang/spi/SPIRenameTest.java b/java/java-tests/testSrc/com/intellij/lang/spi/SPIRenameTest.java
index bb4bd50..9ed424b 100644
--- a/java/java-tests/testSrc/com/intellij/lang/spi/SPIRenameTest.java
+++ b/java/java-tests/testSrc/com/intellij/lang/spi/SPIRenameTest.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.refactoring.MultiFileTestCase;
import com.intellij.refactoring.rename.RenameProcessor;
import com.intellij.refactoring.rename.RenamePsiElementProcessor;
+import org.jetbrains.annotations.NotNull;
/**
* User: anna
@@ -53,6 +54,7 @@
});
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/spi/";
diff --git a/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.java b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.java
new file mode 100644
index 0000000..329288c
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/openapi/editor/impl/FoldingExceptionTest.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.openapi.editor.impl;
+
+import com.intellij.codeHighlighting.TextEditorHighlightingPass;
+import com.intellij.codeInsight.daemon.impl.CodeFoldingPassFactory;
+import com.intellij.mock.MockProgressIndicator;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.LightCodeInsightTestCase;
+
+public class FoldingExceptionTest extends LightCodeInsightTestCase {
+
+ public void test() {
+ configureByFile("/codeInsight/folding/FoldingExceptionTest.java");
+ EditorTestUtil.configureSoftWraps(myEditor, 120);
+ runFoldingPass();
+ deleteLine();
+ runFoldingPass();
+ // we just verify here that the operation completes normally - it was known to fail previously
+ }
+
+ private static void runFoldingPass() {
+ PsiDocumentManager psiDocumentManager = PsiDocumentManager.getInstance(getProject());
+ psiDocumentManager.commitAllDocuments();
+ PsiFile psiFile = psiDocumentManager.getPsiFile(myEditor.getDocument());
+ assertNotNull(psiFile);
+
+ CodeFoldingPassFactory factory = getProject().getComponent(CodeFoldingPassFactory.class);
+ TextEditorHighlightingPass highlightingPass = factory.createHighlightingPass(psiFile, myEditor);
+ highlightingPass.collectInformation(new MockProgressIndicator());
+ highlightingPass.doApplyInformationToEditor();
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
index dbdbb5a..51fdd8c 100644
--- a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
+++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/DirectoryIndexTest.java
@@ -40,6 +40,7 @@
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
import static java.util.Collections.singletonList;
@@ -186,7 +187,7 @@
return instance;
}
- public void testDirInfos() {
+ public void testDirInfos() throws IOException {
checkInfoNull(myRootVFile);
// beware: files in directory index
@@ -204,6 +205,8 @@
checkInfo(myLibDir, myModule, false, false, null, null);
checkInfo(myLibSrcDir, myModule, false, true, "", null, myModule2, myModule3);
checkInfo(myLibClsDir, myModule, true, false, "", null, myModule2, myModule3);
+
+ assertEquals(myLibSrcDir, checkInfoNotNull(myLibSrcDir).getSourceRoot());
checkInfo(myModule2Dir, myModule2, false, false, null, null);
checkInfo(mySrcDir2, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
@@ -215,11 +218,15 @@
assertEquals(myModule1Dir, checkInfoNotNull(myLibClsDir).getContentRoot());
checkInfo(myModule3Dir, myModule3, false, false, null, null);
+
+ VirtualFile cvs = myPack1Dir.createChildDirectory(this, "CVS");
+ checkInfoNull(cvs);
+ assertNull(ProjectRootManager.getInstance(myProject).getFileIndex().getPackageNameByDirectory(cvs));
}
- public void testDirsByPackageName() {
- checkPackage("", true, myFileLibSrc, myFileLibCls, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myLibSrcDir, myLibClsDir, mySrcDir2);
- checkPackage("", false, myFileLibCls, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myLibClsDir, mySrcDir2);
+ public void testDirsByPackageName() throws IOException {
+ checkPackage("", true, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myFileLibSrc, myFileLibCls, mySrcDir2, myLibSrcDir, myLibClsDir);
+ checkPackage("", false, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myFileLibCls, mySrcDir2, myLibClsDir);
checkPackage("pack1", true, myPack1Dir);
checkPackage("pack1", false, myPack1Dir);
@@ -229,6 +236,25 @@
checkPackage(".pack2", false);
checkPackage(".pack2", true);
+
+ VirtualFile libClsPack = myLibClsDir.createChildDirectory(this, "pack1");
+ VirtualFile libSrcPack = myLibSrcDir.createChildDirectory(this, "pack1");
+ fireRootsChanged();
+ checkPackage("pack1", true, myPack1Dir, libSrcPack, libClsPack);
+ checkPackage("pack1", false, myPack1Dir, libClsPack);
+ }
+
+ public void testDirectoriesWithPackagePrefix() {
+ PsiTestUtil.addSourceRoot(myModule3, myModule3Dir);
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ final ModifiableRootModel model = ModuleRootManager.getInstance(myModule3).getModifiableModel();
+ model.getContentEntries()[0].getSourceFolders()[0].setPackagePrefix("pack1");
+ model.commit();
+ }
+ });
+ checkPackage("pack1", true, myPack1Dir, myModule3Dir);
}
public void testCreateDir() throws Exception {
@@ -389,6 +415,56 @@
ProjectRootManagerEx.getInstanceEx(getProject()).makeRootsChange(EmptyRunnable.getInstance(), false, true);
}
+ public void testModuleSourceAsLibrarySource() throws Exception {
+ ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Collections.<String>emptyList(), Arrays.asList(mySrcDir1.getUrl()));
+
+ checkInfo(mySrcDir1, myModule, false, true, "", JavaSourceRootType.SOURCE, myModule, myModule);
+ OrderEntry[] entries = myIndex.getInfoForDirectory(mySrcDir1).getOrderEntries();
+ assertInstanceOf(entries[0], LibraryOrderEntry.class);
+ assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
+
+ checkInfo(myTestSrc1, myModule, false, true, "testSrc", JavaSourceRootType.TEST_SOURCE, myModule, myModule);
+ entries = myIndex.getInfoForDirectory(myTestSrc1).getOrderEntries();
+ assertInstanceOf(entries[0], LibraryOrderEntry.class);
+ assertInstanceOf(entries[1], ModuleSourceOrderEntry.class);
+ }
+
+ public void testModuleSourceAsLibraryClasses() throws Exception {
+ ModuleRootModificationUtil.addModuleLibrary(myModule, "someLib", Arrays.asList(mySrcDir1.getUrl()), Collections.<String>emptyList());
+ checkInfo(mySrcDir1, myModule, true, false, "", JavaSourceRootType.SOURCE, myModule);
+ assertInstanceOf(assertOneElement(checkInfoNotNull(mySrcDir1).getOrderEntries()), ModuleSourceOrderEntry.class);
+ }
+
+ public void testModulesWithSameSourceContentRoot() {
+ // now our API allows this (ReformatCodeActionTest), although UI doesn't. Maybe API shouldn't allow it as well?
+ PsiTestUtil.addContentRoot(myModule2, myModule1Dir);
+ PsiTestUtil.addSourceRoot(myModule2, mySrcDir1);
+
+ checkInfo(myModule1Dir, myModule, false, false, null, null);
+ checkInfo(mySrcDir1, myModule, false, false, "", JavaSourceRootType.SOURCE, myModule3, myModule);
+ checkInfo(myTestSrc1, myModule, false, false, "", JavaSourceRootType.TEST_SOURCE, myModule3, myModule);
+ checkInfo(myResDir, myModule, false, false, "", JavaResourceRootType.RESOURCE, myModule);
+
+ checkInfo(mySrcDir2, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
+ assertEquals(myModule2Dir, myIndex.getInfoForDirectory(mySrcDir2).getContentRoot());
+ }
+
+ public void testModuleWithSameSourceRoot() {
+ PsiTestUtil.addSourceRoot(myModule2, mySrcDir1);
+ checkInfo(mySrcDir1, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
+ checkInfo(myTestSrc1, myModule2, false, false, "testSrc", JavaSourceRootType.SOURCE, myModule2, myModule3);
+ }
+
+ public void testModuleContentUnderSourceRoot() {
+ PsiTestUtil.addContentRoot(myModule2, myPack1Dir);
+ checkInfo(myPack1Dir, myModule2, false, false, null, null);
+ }
+
+ public void testSameSourceAndOutput() {
+ PsiTestUtil.setCompilerOutputPath(myModule, mySrcDir1.getUrl(), false);
+ checkInfoNull(mySrcDir1);
+ }
+
public void testExcludedDirShouldBeExcludedRightAfterItsCreation() throws Exception {
VirtualFile excluded = myModule1Dir.createChildDirectory(this, "excluded");
VirtualFile projectOutput = myModule1Dir.createChildDirectory(this, "projectOutput");
@@ -413,6 +489,9 @@
checkInfoNull(module2TestOutput);
assertFalse(myIndex.isProjectExcludeRoot(excluded));
+ assertFalse(myIndex.isProjectExcludeRoot(projectOutput));
+ assertFalse(myIndex.isProjectExcludeRoot(module2Output));
+ assertFalse(myIndex.isProjectExcludeRoot(module2TestOutput));
excluded.delete(this);
projectOutput.delete(this);
@@ -426,14 +505,32 @@
VirtualFile file = e.getFile();
checkInfoNull(file);
created.add(file);
+
+ String fileName = e.getFileName();
+ if (fileName.equals("projectOutput")) {
+ assertFalse(myIndex.isProjectExcludeRoot(file));
+ }
+ if (fileName.equals("module2Output")) {
+ assertFalse(myIndex.isProjectExcludeRoot(file));
+ }
+ if (fileName.equals("module2TestOutput")) {
+ assertFalse(myIndex.isProjectExcludeRoot(file));
+ }
}
};
VirtualFileManager.getInstance().addVirtualFileListener(l, getTestRootDisposable());
+
excluded = myModule1Dir.createChildDirectory(this, excluded.getName());
assertFalse(myIndex.isProjectExcludeRoot(excluded));
+
projectOutput = myModule1Dir.createChildDirectory(this, projectOutput.getName());
+ assertFalse(myIndex.isProjectExcludeRoot(projectOutput));
+
module2Output = myModule1Dir.createChildDirectory(this, module2Output.getName());
+ assertFalse(myIndex.isProjectExcludeRoot(module2Output));
+
module2TestOutput = myModule2Dir.createChildDirectory(this, module2TestOutput.getName());
+ assertFalse(myIndex.isProjectExcludeRoot(module2TestOutput));
checkInfoNull(excluded);
checkInfoNull(projectOutput);
@@ -443,6 +540,9 @@
assertEquals(created.toString(), 4, created.size());
assertFalse(myIndex.isProjectExcludeRoot(excluded));
+ assertFalse(myIndex.isProjectExcludeRoot(projectOutput));
+ assertFalse(myIndex.isProjectExcludeRoot(module2Output));
+ assertFalse(myIndex.isProjectExcludeRoot(module2TestOutput));
}
public void testExcludesShouldBeRecognizedRightOnRefresh() throws Exception {
@@ -509,6 +609,10 @@
checkInfo(myModule1Dir, myModule, true, false, "", null, myModule);
checkInfo(mySrcDir1, myModule, true, false, "", JavaSourceRootType.SOURCE, myModule);
+ checkInfo(myModule2Dir, myModule2, true, false, "module2", null, myModule);
+ checkInfo(mySrcDir2, myModule2, true, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
+ checkInfo(myExcludeDir, null, true, false, "module2.src2.excluded", null, myModule3);
+
checkInfo(myLibDir, myModule, true, false, "lib", null, myModule);
checkInfo(myLibClsDir, myModule, true, false, "", null, myModule2, myModule3);
@@ -516,9 +620,19 @@
checkInfo(myLibSrcDir, myModule, true, true, "", null, myModule, myModule3);
checkInfo(myResDir, myModule, true, false, "", JavaResourceRootType.RESOURCE, myModule);
+ assertInstanceOf(assertOneElement(checkInfoNotNull(myResDir).getOrderEntries()), ModuleSourceOrderEntry.class);
checkInfo(myExcludedLibSrcDir, null, true, false, "lib.src.exc", null, myModule3, myModule);
checkInfo(myExcludedLibClsDir, null, true, false, "lib.cls.exc", null, myModule3);
+
+ checkPackage("lib.src.exc", true, myExcludedLibSrcDir);
+ checkPackage("lib.cls.exc", true, myExcludedLibClsDir);
+
+ checkPackage("lib.src", true);
+ checkPackage("lib.cls", true);
+
+ checkPackage("exc", false);
+ checkPackage("exc", true);
}
public void testExcludeCompilerOutputOutsideOfContentRoot() throws Exception {
@@ -539,6 +653,28 @@
assertTrue(myIndex.isProjectExcludeRoot(myOutputDir));
assertTrue(myIndex.isProjectExcludeRoot(myModule1OutputDir));
assertTrue(fileIndex.isIgnored(myModule1OutputDir));
+
+ PsiTestUtil.setCompilerOutputPath(myModule, moduleOutputUrl, true);
+ PsiTestUtil.setCompilerOutputPath(myModule2, moduleOutputUrl, false);
+ PsiTestUtil.setCompilerOutputPath(myModule2, moduleOutputUrl, true);
+ PsiTestUtil.setCompilerOutputPath(myModule3, moduleOutputUrl, false);
+ PsiTestUtil.setCompilerOutputPath(myModule3, moduleOutputUrl, true);
+
+ // now no module inherits project output dir, but it still should be project-excluded
+ assertTrue(myIndex.isProjectExcludeRoot(myOutputDir));
+
+ // project output inside module content shouldn't be projectExcludeRoot
+ VirtualFile projectOutputUnderContent = myModule1Dir.createChildDirectory(this, "projectOutputUnderContent");
+ getCompilerProjectExtension().setCompilerOutputUrl(projectOutputUnderContent.getUrl());
+ fireRootsChanged();
+
+ assertFalse(myIndex.isProjectExcludeRoot(myOutputDir));
+ assertFalse(myIndex.isProjectExcludeRoot(projectOutputUnderContent));
+
+ projectOutputUnderContent.delete(this);
+ projectOutputUnderContent = myModule1Dir.createChildDirectory(this, "projectOutputUnderContent");
+ assertFalse(myIndex.isProjectExcludeRoot(myOutputDir));
+ assertFalse(myIndex.isProjectExcludeRoot(projectOutputUnderContent));
}
private void checkInfo(VirtualFile dir,
@@ -568,7 +704,7 @@
assertEquals(Arrays.toString(info.getOrderEntries()), modulesOfOrderEntries.length, info.getOrderEntries().length);
for (Module aModule : modulesOfOrderEntries) {
OrderEntry found = info.findOrderEntryWithOwnerModule(aModule);
- assertNotNull("not found: " + aModule, found);
+ assertNotNull("not found: " + aModule + " in " + Arrays.toString(info.getOrderEntries()), found);
}
}
@@ -585,6 +721,15 @@
private void checkPackage(String packageName, boolean includeLibrarySources, VirtualFile... expectedDirs) {
VirtualFile[] actualDirs = myIndex.getDirectoriesByPackageName(packageName, includeLibrarySources).toArray(VirtualFile.EMPTY_ARRAY);
assertNotNull(actualDirs);
- assertSameElements(actualDirs, expectedDirs);
+ assertOrderedEquals(actualDirs, expectedDirs);
+ }
+
+ public void testFileLibraryInsideFolderLibrary() throws IOException {
+ VirtualFile file = myLibSrcDir.createChildData(this, "empty.txt");
+ ModuleRootModificationUtil.addModuleLibrary(myModule2, "lib2",
+ Collections.<String>emptyList(), singletonList(file.getUrl()),
+ Collections.<String>emptyList(), DependencyScope.COMPILE, true);
+ checkInfo(file, null, false, true, "", null, myModule2, myModule3);
+
}
}
diff --git a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java
index 469c5be..bd41a9c 100644
--- a/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java
+++ b/java/java-tests/testSrc/com/intellij/openapi/roots/impl/ProjectLibrariesTest.java
@@ -1,7 +1,23 @@
+/*
+ * 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.openapi.roots.impl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
@@ -26,7 +42,7 @@
public class ProjectLibrariesTest extends IdeaTestCase {
public void test() {
final LibraryTable libraryTable = ProjectLibraryTable.getInstance(myProject);
- Library lib = ApplicationManager.getApplication().runWriteAction(new Computable<Library>() {
+ Library lib = WriteCommandAction.runWriteCommandAction(null, new Computable<Library>() {
@Override
public Library compute() {
return libraryTable.createLibrary("LIB");
@@ -36,7 +52,7 @@
final JavaPsiFacade manager = getJavaFacade();
assertNull(manager.findClass("pack.MyClass", GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(myModule)));
final File file = new File(PathManagerEx.getTestDataPath() + "/psi/repositoryUse/cls");
- final VirtualFile root = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ final VirtualFile root = WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
@@ -57,7 +73,7 @@
public void test1() {
final LibraryTable libraryTable = ProjectLibraryTable.getInstance(myProject);
- Library lib = ApplicationManager.getApplication().runWriteAction(new Computable<Library>() {
+ Library lib = WriteCommandAction.runWriteCommandAction(null, new Computable<Library>() {
@Override
public Library compute() {
return libraryTable.createLibrary("LIB");
@@ -70,7 +86,7 @@
final ModifiableRootModel rootModel2 = ModuleRootManager.getInstance(myModule).getModifiableModel();
assertNotNull(rootModel2.findLibraryOrderEntry(lib));
final File file = new File(PathManagerEx.getTestDataPath() + "/psi/repositoryUse/cls");
- final VirtualFile root = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ final VirtualFile root = WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
diff --git a/java/java-tests/testSrc/com/intellij/project/convertors/Convertor34Test.java b/java/java-tests/testSrc/com/intellij/project/convertors/Convertor34Test.java
index 92170d1..93858db 100644
--- a/java/java-tests/testSrc/com/intellij/project/convertors/Convertor34Test.java
+++ b/java/java-tests/testSrc/com/intellij/project/convertors/Convertor34Test.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.
@@ -29,6 +29,7 @@
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.List;
@@ -43,6 +44,7 @@
super.setUp();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/moduleRootManager/convertor34/";
diff --git a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java
index 827c44f..8b6c7a3 100644
--- a/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java
+++ b/java/java-tests/testSrc/com/intellij/projectView/NavigateFromSourceTest.java
@@ -1,33 +1,17 @@
/*
- * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved.
+ * Copyright 2000-2014 JetBrains s.r.o.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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
*
- * -Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * -Redistribution in binary form must reproduct the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the distribution.
- *
- * Neither the name of JetBrains or IntelliJ IDEA
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
- * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT
- * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
- * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
- * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST
- * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
- * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
- * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
- * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ * 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.projectView;
@@ -39,8 +23,8 @@
import com.intellij.ide.projectView.impl.ProjectViewToolWindowFactory;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowId;
@@ -92,8 +76,7 @@
" -PsiDirectory: src\n" +
" -PsiDirectory: com\n" +
" -PsiDirectory: package1\n" +
- " -Class1.java\n" +
- " [Class1]\n" +
+ " [Class1]\n" +
" Class2\n" +
getRootFiles() +
" +External Libraries\n");
@@ -132,7 +115,7 @@
pane.select(psiClass, psiClass.getContainingFile().getVirtualFile(), true);
- assertEquals(10, tree.getSelectionCount());
+ assertEquals(9, tree.getSelectionCount());
}
private static void changeClassTextAndTryToNavigate(final String newClassString,
@@ -142,7 +125,7 @@
PsiClass psiClass = psiFile.getClasses()[0];
final VirtualFile virtualFile = psiClass.getContainingFile().getVirtualFile();
final JTree tree = pane.getTree();
- writeToFile(virtualFile, newClassString.getBytes());
+ virtualFile.setBinaryContent(newClassString.getBytes(CharsetToolkit.UTF8_CHARSET));
PlatformTestUtil.waitForAlarm(600);
@@ -150,10 +133,4 @@
pane.select(psiClass, virtualFile, true);
PlatformTestUtil.assertTreeEqual(tree, expected, true);
}
-
- private static void writeToFile(final VirtualFile virtualFile, final byte[] b) throws IOException {
- virtualFile.setBinaryContent(b);
- }
-
-
}
diff --git a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java
index c23078e..dc7ab08 100644
--- a/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java
+++ b/java/java-tests/testSrc/com/intellij/projectView/ProjectViewUpdatingTest.java
@@ -1,33 +1,17 @@
/*
- * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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
*
- * -Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * -Redistribution in binary form must reproduct the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the distribution.
- *
- * Neither the name of JetBrains or IntelliJ IDEA
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
- * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT
- * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
- * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
- * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST
- * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
- * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
- * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
- * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ * 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.projectView;
@@ -40,6 +24,7 @@
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
@@ -83,7 +68,7 @@
final PsiClass[] classes = JavaDirectoryService.getInstance()
.getPackage(getContentDirectory().findSubdirectory("src").findSubdirectory("com").findSubdirectory("package1")).getClasses();
sortClassesByName(classes);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
classes[0].delete();
}
diff --git a/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java b/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java
index 84b607c..e9cd4ec 100644
--- a/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java
+++ b/java/java-tests/testSrc/com/intellij/projectView/StructureViewUpdatingTest.java
@@ -1,40 +1,23 @@
/*
- * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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
*
- * -Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * -Redistribution in binary form must reproduct the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the distribution.
- *
- * Neither the name of JetBrains or IntelliJ IDEA
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
- * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT
- * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
- * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
- * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST
- * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
- * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
- * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
- * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ * 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.projectView;
import com.intellij.JavaTestUtil;
import com.intellij.ide.structureView.newStructureView.StructureViewComponent;
import com.intellij.ide.util.InheritedMembersNodeProvider;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
@@ -166,7 +149,7 @@
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
try {
diff --git a/java/java-tests/testSrc/com/intellij/psi/AddRemoveInTypeParameterListTest.java b/java/java-tests/testSrc/com/intellij/psi/AddRemoveInTypeParameterListTest.java
index 1f829aa..0c08c28 100644
--- a/java/java-tests/testSrc/com/intellij/psi/AddRemoveInTypeParameterListTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/AddRemoveInTypeParameterListTest.java
@@ -1,6 +1,21 @@
+/*
+ * 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.psi;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.testFramework.LightIdeaTestCase;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.IncorrectOperationException;
@@ -40,7 +55,7 @@
PsiReferenceParameterList list = ref.getParameterList();
final PsiTypeElement[] parms = list.getTypeParameterElements();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
parms[0].delete();
diff --git a/java/java-tests/testSrc/com/intellij/psi/ArrayIndexOutOfBoundsTest.java b/java/java-tests/testSrc/com/intellij/psi/ArrayIndexOutOfBoundsTest.java
index f82d430..4c8ada5 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ArrayIndexOutOfBoundsTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ArrayIndexOutOfBoundsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,13 +17,14 @@
import com.intellij.JavaTestUtil;
import com.intellij.lang.ASTNode;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.rename.RenameProcessor;
@@ -98,7 +99,7 @@
public void run() {
final PsiPackage aPackage = JavaPsiFacade.getInstance(myPsiManager.getProject()).findPackage("anotherBla");
assertNotNull("Package anotherBla not found", aPackage);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
aPackage.getDirectories()[0].delete();
diff --git a/java/java-tests/testSrc/com/intellij/psi/AstLeaksTest.groovy b/java/java-tests/testSrc/com/intellij/psi/AstLeaksTest.groovy
index a028baf..ed0ac4d 100644
--- a/java/java-tests/testSrc/com/intellij/psi/AstLeaksTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/AstLeaksTest.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,14 +15,14 @@
*/
package com.intellij.psi
-import com.intellij.openapi.application.ApplicationManager
+import com.intellij.codeInspection.defaultFileTemplateUsage.DefaultFileTemplateUsageInspection
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.psi.impl.source.PsiFileImpl
import com.intellij.psi.impl.source.tree.java.JavaFileElement
import com.intellij.psi.impl.source.tree.java.MethodElement
import com.intellij.testFramework.LeakHunter
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import com.intellij.util.Processor
-import com.intellij.codeInspection.defaultFileTemplateUsage.DefaultFileTemplateUsageInspection
/**
* @author peter
@@ -34,12 +34,11 @@
assert file.findElementAt(0) instanceof PsiKeyword
LeakHunter.checkLeak(file, JavaFileElement)
- ApplicationManager.application.runWriteAction {
+ WriteCommandAction.runWriteCommandAction project, {
file.viewProvider.document.insertString(0, ' ')
PsiDocumentManager.getInstance(project).commitAllDocuments()
- assert file.findElementAt(0) instanceof PsiWhiteSpace
}
-
+ assert file.findElementAt(0) instanceof PsiWhiteSpace
LeakHunter.checkLeak(file, JavaFileElement)
}
@@ -51,8 +50,7 @@
myFixture.configureFromExistingVirtualFile(file.virtualFile)
myFixture.doHighlighting()
- def mainClass = ((PsiJavaFile) file).classes[0]
-
+ def mainClass = ((PsiJavaFile)file).classes[0]
LeakHunter.checkLeak(mainClass, MethodElement, { MethodElement node ->
superClass == node.psi.parent
} as Processor<MethodElement>)
@@ -77,12 +75,15 @@
public void "test no hard refs to Default File Template inspection internal AST"() {
myFixture.addFileToProject('sup.java', 'class Super { void bar() {} }')
- PsiJavaFile foo = myFixture.addFileToProject('a.java', 'class Foo { void bar() { bar(); } }')
- myFixture.configureFromExistingVirtualFile(foo.virtualFile)
+ def file = myFixture.addFileToProject('a.java', 'class Foo { void bar() { bar(); } }')
+ myFixture.configureFromExistingVirtualFile(file.virtualFile)
myFixture.enableInspections(new DefaultFileTemplateUsageInspection())
myFixture.doHighlighting()
- LeakHunter.checkLeak(foo.classes[0], MethodElement, { MethodElement node -> !node.psi.physical } as Processor<MethodElement>)
+ def mainClass = ((PsiJavaFile)file).classes[0]
+ LeakHunter.checkLeak(mainClass, MethodElement, { MethodElement node ->
+ !node.psi.physical
+ } as Processor<MethodElement>)
}
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.java
index 51c816e..4676c00 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ClsBuilderTest.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;
import com.intellij.JavaTestUtil;
@@ -6,7 +21,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.impl.compiled.DefaultClsStubBuilderFactory;
+import com.intellij.psi.impl.compiled.ClsFileImpl;
import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.psi.stubs.StubBase;
import com.intellij.testFramework.LightIdeaTestCase;
@@ -81,7 +96,7 @@
}
private static void doTest(VirtualFile vFile, String goldFile) throws ClsFormatException, IOException {
- final PsiFileStub stub = (new DefaultClsStubBuilderFactory()).buildFileStub(vFile, vFile.contentsToByteArray());
+ final PsiFileStub stub = ClsFileImpl.buildFileStub(vFile, vFile.contentsToByteArray());
assert stub != null : vFile;
final String butWas = ((StubBase)stub).printTree();
diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsDuplicatesTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsDuplicatesTest.java
new file mode 100644
index 0000000..81dcb5c
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/psi/ClsDuplicatesTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.psi;
+
+import com.intellij.JavaTestUtil;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.testFramework.PsiTestCase;
+import com.intellij.usageView.UsageViewLongNameLocation;
+import gnu.trove.THashSet;
+import gnu.trove.TObjectHashingStrategy;
+
+import java.util.Set;
+
+public class ClsDuplicatesTest extends PsiTestCase {
+ private Set<PsiNamedElement> myUnique = new THashSet<PsiNamedElement>(new TObjectHashingStrategy<PsiNamedElement>() {
+ @Override
+ public int computeHashCode(PsiNamedElement object) {
+ String name = object.getName();
+ return name == null ? 0 : name.hashCode();
+ }
+
+ @Override
+ public boolean equals(PsiNamedElement o1, PsiNamedElement o2) {
+ return o1.getParent() == o2.getParent() &&
+ o1.getClass() == o2.getClass() &&
+ StringUtil.equals(o1.getName(), o2.getName()) &&
+ StringUtil.equals(o1.getText(), o2.getText());
+ }
+ });
+
+ @Override
+ protected void tearDown() throws Exception {
+ myUnique = null;
+ super.tearDown();
+ }
+
+ @Override
+ protected Sdk getTestProjectJdk() {
+ return JavaTestUtil.getTestJdk();
+ }
+
+ public void testDuplicates() throws Exception {
+ final PsiPackage rootPackage = JavaPsiFacade.getInstance(getProject()).findPackage("");
+ assert rootPackage != null;
+
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(getProject());
+ JavaRecursiveElementVisitor visitor = new JavaRecursiveElementVisitor() {
+ @Override
+ public void visitPackage(PsiPackage aPackage) {
+ visit(aPackage);
+ for (PsiPackage subPackage : aPackage.getSubPackages(scope)) {
+ visitPackage(subPackage);
+ }
+ for (PsiClass aClass : aPackage.getClasses(scope)) {
+ visitClass(aClass);
+ }
+ }
+
+ @Override
+ public void visitElement(PsiElement element) {
+ if (element instanceof PsiNamedElement) {
+ visit((PsiNamedElement)element);
+ }
+ super.visitElement(element);
+ }
+
+ @Override
+ public void visitClass(PsiClass aClass) {
+ super.visitClass(aClass);
+ PsiElement parent = aClass.getParent();
+ if (parent instanceof PsiFile) {
+ myUnique.clear();
+ }
+ }
+ };
+
+ rootPackage.accept(visitor);
+ }
+
+ private void visit(PsiNamedElement element) {
+ if (!myUnique.add(element)) {
+ String description = ElementDescriptionUtil.getElementDescription(element, UsageViewLongNameLocation.INSTANCE);
+ fail("Duplicate Element: " + description + ": " + element.getText());
+ }
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
index 728fd72..7523e5b 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java
@@ -16,9 +16,12 @@
package com.intellij.psi;
import com.intellij.JavaTestUtil;
+import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.impl.compiled.ClsFileImpl;
import com.intellij.testFramework.LightIdeaTestCase;
import com.intellij.testFramework.PlatformTestUtil;
@@ -44,8 +47,24 @@
public void testClassRefs() { doTest(); }
public void testEA46236() { doTest("ValuedEnum"); }
public void testKotlinFunList() { doTest(); }
+ public void testMiddle$Buck() { doTest(); }
+ public void testDefaultPackage() { doTest(); }
+ public void testLocalClass() { doTest(); }
public void testBounds() { doTest(); }
+ public void testTextPsiMismatch() throws Exception {
+ CommonCodeStyleSettings.IndentOptions options =
+ CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings().getIndentOptions(JavaFileType.INSTANCE);
+ int indent = options.INDENT_SIZE;
+ options.INDENT_SIZE *= 2;
+ try {
+ doTest("Bounds");
+ }
+ finally {
+ options.INDENT_SIZE = indent;
+ }
+ }
+
private void doTest() {
doTest(getTestName(false));
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java
index ea6614e..504838c 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ClsRepositoryUseTest.java
@@ -232,13 +232,11 @@
}
public void testFindClass() {
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL, myTestRootDisposable);
PsiClass aClass = myJavaFacade.findClass("pack.MyClass", GlobalSearchScope.allScope(myProject));
assertNotNull(aClass);
checkValid(aClass);
-
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
}
public void testIsInterface() {
diff --git a/java/java-tests/testSrc/com/intellij/psi/ConstantValuesTest.java b/java/java-tests/testSrc/com/intellij/psi/ConstantValuesTest.java
index 9e8523d..5c3b631 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ConstantValuesTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ConstantValuesTest.java
@@ -1,7 +1,23 @@
+/*
+ * 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.psi;
import com.intellij.JavaTestUtil;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -45,8 +61,8 @@
super.invokeTestRunnable(runnable);
final PsiJavaFile file = (PsiJavaFile)myClass.getContainingFile();
- ApplicationManager.getApplication().runWriteAction(
- new Runnable() {
+ WriteCommandAction.runWriteCommandAction(
+ null, new Runnable() {
@Override
public void run() {
try {
diff --git a/java/java-tests/testSrc/com/intellij/psi/JavaSOEOnReparsePerformanceTest.java b/java/java-tests/testSrc/com/intellij/psi/JavaSOEOnReparsePerformanceTest.java
index f1d9c07..4de8d98 100644
--- a/java/java-tests/testSrc/com/intellij/psi/JavaSOEOnReparsePerformanceTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/JavaSOEOnReparsePerformanceTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.codeInsight.daemon.LightDaemonAnalyzerTestCase;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
public class JavaSOEOnReparsePerformanceTest extends LightDaemonAnalyzerTestCase {
private StringBuilder myHugeExpr;
@@ -51,11 +52,13 @@
final int pos = getEditor().getDocument().getText().indexOf("\"\"");
// replace small expression with huge binary one
- ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override
- public void run() {
- getEditor().getDocument().replaceString(pos, pos + 2, myHugeExpr);
- PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
- }});
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ @Override
+ public void run() {
+ getEditor().getDocument().replaceString(pos, pos + 2, myHugeExpr);
+ PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+ }
+ });
doTestConfiguredFile(false, false, null);
// modify huge binary expression (1)
diff --git a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
index 6e58fee..301a993 100644
--- a/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/MiscPsiTest.java
@@ -116,7 +116,7 @@
final PsiClass aClass = getJavaFacade().getElementFactory().createClassFromText("public int i, j;", null);
final PsiField aField = aClass.getFields()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
aField.delete();
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/ModifyAnnotationsTest.java b/java/java-tests/testSrc/com/intellij/psi/ModifyAnnotationsTest.java
index 1895c67..e4f8b59 100644
--- a/java/java-tests/testSrc/com/intellij/psi/ModifyAnnotationsTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/ModifyAnnotationsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -16,9 +16,8 @@
package com.intellij.psi;
import com.intellij.JavaTestUtil;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.vfs.VirtualFileFilter;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.IdeaTestUtil;
@@ -41,7 +40,7 @@
public void testReplaceAnnotation() throws Exception {
//be sure not to load tree
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL, myTestRootDisposable);
PsiClass aClass = myJavaFacade.findClass("Test", GlobalSearchScope.allScope(myProject));
assertNotNull(aClass);
final PsiAnnotation[] annotations = aClass.getModifierList().getAnnotations();
@@ -49,11 +48,11 @@
assertEquals("A", annotations[0].getNameReferenceElement().getReferenceName());
final PsiAnnotation newAnnotation = myJavaFacade.getElementFactory().createAnnotationFromText("@B", null);
//here the tree is going to be loaded
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
try {
diff --git a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java
index aa2efdb..5d1c505 100644
--- a/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/OptimizeImportsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -15,9 +15,9 @@
*/
package com.intellij.psi;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.testFramework.PsiTestCase;
@@ -53,7 +53,7 @@
getProject(), new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
String fileName = getTestName(false) + extension;
diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
index ee23c2d..95d54bb 100644
--- a/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/PsiConcurrencyStressTest.java
@@ -20,7 +20,6 @@
package com.intellij.psi;
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
-import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl;
import com.intellij.openapi.application.ApplicationManager;
@@ -148,7 +147,7 @@
mark("-");
final PsiMethod[] psiMethods = getPsiClass().getMethods();
if (psiMethods.length > 0) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
psiMethods[random.nextInt(psiMethods.length)].delete();
diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java
index aaad3fd..db2a5f1 100644
--- a/java/java-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/PsiDocumentManagerImplTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -18,7 +18,7 @@
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.mock.MockDocument;
import com.intellij.mock.MockPsiFile;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
@@ -30,7 +30,6 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.PsiDocumentManagerImpl;
-import com.intellij.psi.impl.TextBlock;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.testFramework.LeakHunter;
import com.intellij.testFramework.LightVirtualFile;
@@ -113,15 +112,14 @@
}
public void testGetUncommittedDocuments_documentChanged_DontProcessEvents() throws Exception {
- PsiFile file = getPsiManager().findFile(createFile());
+ final PsiFile file = getPsiManager().findFile(createFile());
final Document document = getPsiDocumentManager().getDocument(file);
- final TextBlock block = TextBlock.get(file);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
- block.performAtomically(new Runnable() {
+ getPsiDocumentManager().getSynchronizer().performAtomically(file, new Runnable() {
@Override
public void run() {
getPsiDocumentManager().documentChanged(new DocumentEventImpl(document, 0, "", "", document.getModificationStamp(), false));
@@ -137,7 +135,7 @@
public void testGetUncommittedDocuments_documentNotRegistered() throws Exception {
final Document document = new MockDocument();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
getPsiDocumentManager().documentChanged(new DocumentEventImpl(document, 0, "", "", document.getModificationStamp(), false));
@@ -153,7 +151,7 @@
final Document document = getPsiDocumentManager().getDocument(file);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
getPsiDocumentManager().documentChanged(new DocumentEventImpl(document, 0, "", "", document.getModificationStamp(), false));
@@ -170,7 +168,7 @@
final Document document = getPsiDocumentManager().getDocument(file);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
getPsiDocumentManager().documentChanged(new DocumentEventImpl(document, 0, "", "", document.getModificationStamp(), false));
@@ -205,7 +203,7 @@
assertEquals(0, alienDocManager.getUncommittedDocuments().length);
assertEquals(0, getPsiDocumentManager().getUncommittedDocuments().length);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
getPsiDocumentManager()
@@ -251,7 +249,7 @@
waitAndPump(semaphore, 30000);
assertTrue(getPsiDocumentManager().isCommitted(document));
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.insertString(0, "class X {}");
@@ -277,7 +275,7 @@
}
};
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.insertString(0, "/**/");
@@ -296,7 +294,7 @@
assertEquals(1, count.get());
count.set(0);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.insertString(0, "/**/");
@@ -347,7 +345,7 @@
assertEquals(0, alienDocManager.getUncommittedDocuments().length);
assertEquals(0, getPsiDocumentManager().getUncommittedDocuments().length);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
document.setText("xxx");
diff --git a/java/java-tests/testSrc/com/intellij/psi/PsiModificationTrackerTest.java b/java/java-tests/testSrc/com/intellij/psi/PsiModificationTrackerTest.java
index 7cba4a8..bd9641f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/PsiModificationTrackerTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/PsiModificationTrackerTest.java
@@ -2,13 +2,19 @@
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.impl.PsiManagerEx;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.testFramework.IdeaTestCase;
+import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import com.intellij.util.Processor;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import java.io.IOException;
@@ -143,4 +149,110 @@
assertEquals(count + 1, modificationTracker.getJavaStructureModificationCount());
}
+
+ public void testClassShouldNotAppearWithoutEvents_WithPsi() throws IOException {
+ final VirtualFile file = myFixture.getTempDirFixture().createFile("Foo.java", "");
+ final Document document = FileDocumentManager.getInstance().getDocument(file);
+ assertNotNull(document);
+ new WriteCommandAction.Simple(getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ assertNull(JavaPsiFacade.getInstance(getProject()).findClass("Foo", GlobalSearchScope.allScope(getProject())));
+ PsiManager psiManager = PsiManager.getInstance(getProject());
+ PsiModificationTracker tracker = psiManager.getModificationTracker();
+ long count1 = tracker.getJavaStructureModificationCount();
+ PsiJavaFile psiFile = (PsiJavaFile)psiManager.findFile(file);
+
+ document.insertString(0, "class Foo {}");
+
+ assertEquals(count1, tracker.getJavaStructureModificationCount()); // no PSI changes yet
+ //so the class should not exist
+ assertNull(JavaPsiFacade.getInstance(getProject()).findClass("Foo", GlobalSearchScope.allScope(getProject())));
+ assertSize(0, psiFile.getClasses());
+ assertEquals("", psiManager.findFile(file).getText());
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+
+ PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+
+ assertFalse(count1 == tracker.getJavaStructureModificationCount());
+ assertNotNull(JavaPsiFacade.getInstance(getProject()).findClass("Foo", GlobalSearchScope.allScope(getProject())));
+ assertEquals("class Foo {}", psiManager.findFile(file).getText());
+ assertEquals("class Foo {}", psiManager.findFile(file).getNode().getText());
+ assertSize(1, psiFile.getClasses());
+ }
+ }.execute();
+ }
+
+ public void testClassShouldNotAppearWithoutEvents_WithoutPsi() throws IOException {
+ final GlobalSearchScope allScope = GlobalSearchScope.allScope(getProject());
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(getProject());
+ final PsiManager psiManager = PsiManager.getInstance(getProject());
+ final PsiModificationTracker tracker = psiManager.getModificationTracker();
+
+ final VirtualFile file = myFixture.getTempDirFixture().createFile("Foo.java", "");
+ final Document document = FileDocumentManager.getInstance().getDocument(file);
+ assertNotNull(document);
+ new WriteCommandAction.Simple(getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ assertNull(facade.findClass("Foo", allScope));
+ long count1 = tracker.getJavaStructureModificationCount();
+
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+ assertNull(PsiDocumentManager.getInstance(getProject()).getCachedPsiFile(document));
+
+ document.insertString(0, "class Foo {}");
+
+ assertFalse(count1 == tracker.getJavaStructureModificationCount());
+ assertTrue(PsiDocumentManager.getInstance(getProject()).isCommitted(document));
+ assertNotNull(facade.findClass("Foo", allScope));
+
+ PsiJavaFile psiFile = (PsiJavaFile)psiManager.findFile(file);
+ assertSize(1, psiFile.getClasses());
+ assertEquals("class Foo {}", psiFile.getText());
+ assertEquals("class Foo {}", psiFile.getNode().getText());
+ }
+ }.execute();
+ }
+
+ public void testClassShouldNotDisappearWithoutEvents() throws IOException {
+ new WriteCommandAction.Simple(getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ PsiModificationTracker tracker = PsiManager.getInstance(getProject()).getModificationTracker();
+ long count0 = tracker.getJavaStructureModificationCount();
+
+ final VirtualFile file = myFixture.addFileToProject("Foo.java", "class Foo {}").getVirtualFile();
+ final Document document = FileDocumentManager.getInstance().getDocument(file);
+ assertNotNull(document);
+
+ assertNotNull(JavaPsiFacade.getInstance(getProject()).findClass("Foo", GlobalSearchScope.allScope(getProject())));
+ long count1 = tracker.getJavaStructureModificationCount();
+ assertFalse(count1 == count0);
+
+ document.deleteString(0, document.getTextLength());
+
+ // some plugins (e.g. Copyright) hold file reference in an invokeLater runnable, let them pass
+ UIUtil.dispatchAllInvocationEvents();
+
+ // gc softly-referenced file and AST
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+ final PsiManagerEx psiManager = (PsiManagerEx)PsiManager.getInstance(getProject());
+ assertNull(psiManager.getFileManager().getCachedPsiFile(file));
+
+ assertEquals(count1, tracker.getJavaStructureModificationCount()); // no PSI changes yet
+ //so the class should still be there
+ assertNotNull(JavaPsiFacade.getInstance(getProject()).findClass("Foo", GlobalSearchScope.allScope(getProject())));
+ assertSize(1, ((PsiJavaFile)psiManager.findFile(file)).getClasses());
+ assertEquals("class Foo {}", psiManager.findFile(file).getText());
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+
+ PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
+
+ assertFalse(count1 == tracker.getJavaStructureModificationCount());
+ assertNull(JavaPsiFacade.getInstance(getProject()).findClass("Foo", GlobalSearchScope.allScope(getProject())));
+ }
+ }.execute();
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java b/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java
index 42cc146..501914b 100644
--- a/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java
+++ b/java/java-tests/testSrc/com/intellij/psi/SCR17094Test.java
@@ -1,7 +1,22 @@
+/*
+ * 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.psi;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -17,7 +32,7 @@
public class SCR17094Test extends PsiTestCase {
protected void setUpClasses(final String s) throws Exception {
final String testRoot = PathManagerEx.getTestDataPath() + "/psi/repositoryUse/scr17094";
- VirtualFile classesRoot = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ VirtualFile classesRoot = WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
String path = testRoot + "/" + s;
diff --git a/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java
index 7424659..be60006 100644
--- a/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/Src15RepositoryUseTest.java
@@ -299,7 +299,7 @@
public boolean accept(final VirtualFile file) {
return !"package-info.java".equals(file.getName());
}
- });
+ }, myTestRootDisposable);
final PsiClass annotationTypeClass = findClass("annotations.AnnotationType");
assertTrue(annotationTypeClass.isAnnotationType());
@@ -321,11 +321,11 @@
}
private void setupLoadingFilter() {
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL, myTestRootDisposable);
}
private void tearDownLoadingFilter() {
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
}
@NotNull
diff --git a/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java b/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java
index 8400116..5ef9f24 100644
--- a/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/SrcRepositoryUseTest.java
@@ -584,11 +584,11 @@
}
private void teardownLoadingFilter() {
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
}
private void setupLoadingFilter() {
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.ALL, myTestRootDisposable);
}
public void testAnonymousClass2() throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy
index 936bb1c..c915398 100644
--- a/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/StubAstSwitchTest.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.
@@ -89,7 +89,7 @@
def oldClass = JavaPsiFacade.getInstance(project).findClass("A", GlobalSearchScope.allScope(project))
def pointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(oldClass)
- def document = FileDocumentManager.instance.getCachedDocument(file.virtualFile)
+ def document = FileDocumentManager.instance.getDocument(file.virtualFile)
assert document
assert file == PsiDocumentManager.getInstance(project).getCachedPsiFile(document)
assert document == PsiDocumentManager.getInstance(project).getCachedDocument(file)
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractJavaRearrangerTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractJavaRearrangerTest.groovy
index 7f6c641..7ce8d40 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractJavaRearrangerTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/AbstractJavaRearrangerTest.groovy
@@ -18,12 +18,31 @@
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.java.JavaLanguage
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.CLASS
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.FIELD
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.FIELD
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.FIELD
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.INTERFACE
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.METHOD
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.METHOD
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PUBLIC
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PUBLIC
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.STATIC
+
/**
* @author Denis Zhdanov
* @since 8/30/12 12:15 PM
*/
abstract class AbstractJavaRearrangerTest extends AbstractRearrangerTest {
+ def classic = [rule(INTERFACE),
+ rule(CLASS),
+ rule(FIELD, STATIC),
+ rule(FIELD, PUBLIC),
+ rule(FIELD),
+ rule(METHOD, PUBLIC),
+ rule(METHOD)]
+
AbstractJavaRearrangerTest() {
fileType = JavaFileType.INSTANCE
language = JavaLanguage.INSTANCE
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerAnonymousClassesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerAnonymousClassesTest.groovy
new file mode 100644
index 0000000..3d79cd5
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerAnonymousClassesTest.groovy
@@ -0,0 +1,51 @@
+/*
+ * 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.psi.codeStyle.arrangement
+
+class JavaRearrangerAnonymousClassesTest extends AbstractJavaRearrangerTest {
+
+ public void "test rearrangement doesn't brake anon classes alignment"() {
+
+ def text = '''\
+public class Test {
+ public static void main(String[] args) {
+ Action action1 = new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ }
+ };
+ Action action2 = new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ }
+ };
+ }
+}
+'''
+ doTest(
+ initial: text,
+ expected: text,
+ rules: classic
+ )
+ }
+
+
+
+
+
+
+
+}
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerBlankLinesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerBlankLinesTest.groovy
index 8f64026..2ceb83f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerBlankLinesTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerBlankLinesTest.groovy
@@ -24,14 +24,6 @@
*/
public class JavaRearrangerBlankLinesTest extends AbstractJavaRearrangerTest {
- def classic = [rule(INTERFACE),
- rule(CLASS),
- rule(FIELD, STATIC),
- rule(FIELD, PUBLIC),
- rule(FIELD),
- rule(METHOD, PUBLIC),
- rule(METHOD)]
-
void testPreserveRelativeBlankLines() {
commonSettings.BLANK_LINES_AROUND_CLASS = 2
commonSettings.BLANK_LINES_AROUND_FIELD = 1
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
index a2a996a..bd1b18b 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFieldReferenceTest.groovy
@@ -24,6 +24,7 @@
private List<StdArrangementMatchRule> defaultFieldsArrangement = [
rule(CLASS),
+ rule(FIELD, STATIC, FINAL),
rule(FIELD, PUBLIC),
rule(FIELD, PROTECTED),
rule(FIELD, PACKAGE_PRIVATE),
@@ -84,8 +85,8 @@
public static String TEST = "OK!";
public static String BOOK = "ATLAS";
private static String PREFIX = "prefix.";
- private static String PRIVATE_NAME = PREFIX + "private name";
public static String NAME = PREFIX + "name";
+ private static String PRIVATE_NAME = PREFIX + "private name";
}
''',
rules: defaultFieldsArrangement
@@ -253,4 +254,50 @@
);
}
+ void "test field references work ok with enums"() {
+ doTest(
+ initial: '''\
+public class Q {
+ private static final Q A = new Q(Q.E.EC);
+ private static final Q B = new Q(Q.E.EB);
+ private static final Q C = new Q(Q.E.EA);
+ private static final Q D = new Q(Q.E.EA);
+ private final E e;
+ private static final int seven = 7;
+
+ private Q(final Q.E e) {
+ this.e = e;
+ }
+
+ public static enum E {
+ EA,
+ EB,
+ EC,
+ }
+}
+''',
+ expected: '''\
+public class Q {
+ private static final Q A = new Q(Q.E.EC);
+ private static final Q B = new Q(Q.E.EB);
+ private static final Q C = new Q(Q.E.EA);
+ private static final Q D = new Q(Q.E.EA);
+ private static final int seven = 7;
+ private final E e;
+
+ private Q(final Q.E e) {
+ this.e = e;
+ }
+
+ public static enum E {
+ EA,
+ EB,
+ EC,
+ }
+}
+''',
+ rules: defaultFieldsArrangement
+ )
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFoldingTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFoldingTest.groovy
index 9166eaf..dfee35b 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFoldingTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerFoldingTest.groovy
@@ -15,6 +15,9 @@
*/
package com.intellij.psi.codeStyle.arrangement
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PRIVATE
+import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Modifier.PUBLIC
+
/**
* @author Denis Zhdanov
* @since 11/20/12 3:34 PM
@@ -24,51 +27,152 @@
void "test dummy"() {
}
- // This should be uncommented as soon as cdr pushed fixes for range markers processing.
-// void "test that doc comment folding is preserved"() {
-// commonSettings.BLANK_LINES_AROUND_METHOD = 1
-// doTest(
-// initial: '''\
-//import <fold>java.util.List;
-//import java.util.Set;</fold>
-//
-//<fold text="/**...*/">/**
-// * Class comment
-// */</fold>
-//class Test {
-//
-// <fold text="/**...*/>/**
-// * Method comment
-// */</fold>
-// private void test(List<String> l) {}
-//
-// <fold text="/**...*/>/**
-// * Another method comment
-// */</fold>
-// public void test(Set<String> s) {}
-//}''',
-//
-// rules: [rule(PUBLIC), rule(PRIVATE)],
-//
-// expected: '''\
-//import <fold>java.util.List;
-//import java.util.Set;</fold>
-//
-//<fold text="/**...*/">/**
-// * Class comment
-// */</fold>
-//class Test {
-//
-// <fold text="/**...*/>/**
-// * Another method comment
-// */</fold>
-// public void test(Set<String> s) {}
-//
-// <fold text="/**...*/>/**
-// * Method comment
-// */</fold>
-// private void test(List<String> l) {}
-//}'''
-// )
-// }
+ void "test that doc comment folding is preserved"() {
+ commonSettings.BLANK_LINES_AROUND_METHOD = 1
+ doTest(
+ initial: '''\
+import <fold>java.util.List;
+import java.util.Set;</fold>
+
+<fold text="/**...*/">/**
+* Class comment
+*/</fold>
+class Test {
+
+ <fold text="/**...*/>/**
+ * Method comment
+ */</fold>
+ private void test(List<String> l) {}
+
+ <fold text="/**...*/>/**
+ * Another method comment
+ */</fold>
+ public void test(Set<String> s) {}
+}''',
+
+ rules: [rule(PUBLIC), rule(PRIVATE)],
+
+ expected: '''\
+import <fold>java.util.List;
+import java.util.Set;</fold>
+
+<fold text="/**...*/">/**
+* Class comment
+*/</fold>
+class Test {
+
+ <fold text="/**...*/>/**
+ * Another method comment
+ */</fold>
+ public void test(Set<String> s) {}
+
+ <fold text="/**...*/>/**
+ * Method comment
+ */</fold>
+ private void test(List<String> l) {}
+}'''
+ )
+ }
+
+ void "test that doc comment and method folding is preserved"() {
+ commonSettings.BLANK_LINES_AROUND_METHOD = 1
+ doTest(
+ initial: '''\
+import java.util.List;
+import java.util.Set;
+
+class MyTest {
+ <fold text="/**...*/">/**
+ * comment 1
+ *
+ * @param s
+ */</fold>
+ private void test(String s) {
+ }
+
+ /**
+ * comment 2
+ *
+ * @param i
+ */
+ public void test(int i) {
+ }
+}''',
+
+ rules: [rule(PUBLIC), rule(PRIVATE)],
+
+ expected: '''\
+import java.util.List;
+import java.util.Set;
+
+class MyTest {
+ /**
+ * comment 2
+ *
+ * @param i
+ */
+ public void test(int i) {
+ }
+
+ <fold text="/**...*/">/**
+ * comment 1
+ *
+ * @param s
+ */</fold>
+ private void test(String s) {
+ }
+}'''
+ )
+ }
+
+ void "test that single doc comment folding is preserved"() {
+ commonSettings.BLANK_LINES_AROUND_METHOD = 1
+ doTest(
+ initial: '''\
+package a.b;
+
+class MyTest {
+ /**
+ * private comment
+ *
+ * @param s
+ */
+ private void test(String s) {
+ }
+
+ /**
+ * comment 2
+ *
+ * @param i
+ */
+ public void test(int i) <fold text="{...}">{
+ System.out.println(1);
+ }</fold>
+}''',
+
+ rules: [rule(PUBLIC), rule(PRIVATE)],
+
+ expected: '''\
+package a.b;
+
+class MyTest {
+ /**
+ * comment 2
+ *
+ * @param i
+ */
+ public void test(int i) <fold text="{...}">{
+ System.out.println(1);
+ }</fold>
+
+ /**
+ * private comment
+ *
+ * @param s
+ */
+ private void test(String s) {
+ }
+}'''
+ )
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy
index e730a41..e094e86 100644
--- a/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/codeStyle/arrangement/JavaRearrangerGrouperTest.groovy
@@ -126,7 +126,8 @@
void test2() {}
}''')
}
- void "test overriden and utility methods"() {
+
+ void "do not test overriden and utility methods"() {
doTest(
initial: '''\
class Base {
@@ -188,4 +189,51 @@
}'''
)
}
+
+
+ void "test keep dependent methods together multiple times produce same result"() {
+ def groups = [group(DEPENDENT_METHODS, BREADTH_FIRST)]
+ def before = "public class SuperClass {\n" +
+ "\n" +
+ " public void doSmth1() {\n" +
+ " }\n" +
+ "\n" +
+ " public void doSmth2() {\n" +
+ " }\n" +
+ "\n" +
+ " public void doSmth3() {\n" +
+ " }\n" +
+ "\n" +
+ " public void doSmth4() {\n" +
+ " }\n" +
+ "\n" +
+ " public void doSmth() {\n" +
+ " this.doSmth1();\n" +
+ " this.doSmth2();\n" +
+ " this.doSmth3();\n" +
+ " this.doSmth4();\n" +
+ " }\n" +
+ "}"
+ def after = "public class SuperClass {\n" +
+ "\n" +
+ " public void doSmth() {\n" +
+ " this.doSmth1();\n" +
+ " this.doSmth2();\n" +
+ " this.doSmth3();\n" +
+ " this.doSmth4();\n" +
+ " }\n" +
+ " public void doSmth1() {\n" +
+ " }\n" +
+ " public void doSmth2() {\n" +
+ " }\n" +
+ " public void doSmth3() {\n" +
+ " }\n" +
+ " public void doSmth4() {\n" +
+ " }\n" +
+ "}"
+ doTest(initial: before, expected: after, groups: groups)
+ doTest(initial: after, expected: after, groups: groups)
+ }
+
+
}
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 df73270..58c02ef 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
@@ -30,10 +30,7 @@
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.codeStyle.CodeStyleSettings;
-import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.codeStyle.*;
import com.intellij.testFramework.LightIdeaTestCase;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.text.LineReader;
@@ -78,6 +75,11 @@
protected enum Action {REFORMAT, INDENT}
+
+ public static JavaCodeStyleSettings getJavaSettings() {
+ return getSettings().getRootSettings().getCustomSettings(JavaCodeStyleSettings.class);
+ }
+
private interface TestFormatAction {
void run(PsiFile psiFile, int startOffset, int endOffset);
}
@@ -114,6 +116,11 @@
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);
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java
index b347207..ec41ee6 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterIndentationTest.java
@@ -340,10 +340,11 @@
"});",
"foo(1,\n" +
" 2, new Runnable() {\n" +
- " @Override\n" +
- " public void run() {\n" +
- " }\n" +
- "});"
+ " @Override\n" +
+ " public void run() {\n" +
+ " }\n" +
+ " }\n" +
+ ");"
);
doMethodTest(
@@ -446,16 +447,95 @@
" }\n" +
" });",
"foo(new Runnable() {\n" +
- " public void run() {\n" +
- " }\n" +
- " }, new Runnable() {\n" +
- " public void run() {\n" +
- " }\n" +
+ " public void run() {\n" +
" }\n" +
- ");"
+ "}, new Runnable() {\n" +
+ " public void run() {\n" +
+ " }\n" +
+ "});"
);
}
-
+
+ public void testAlignMultipleAnonymousClasses_PassedAsMethodParameters() throws Exception {
+ String text = "test(new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"AAA!\");\n" +
+ " }\n" +
+ "}, new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"BBB!\");\n" +
+ " }\n" +
+ "});\n";
+ doMethodTest(text, text);
+ }
+
+ public void testAlignmentAdditionalParamsWithMultipleAnonymousClasses_PassedAsMethodParameters() throws Exception {
+ String text = "foo(1221, new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"A\");\n" +
+ " }\n" +
+ "}, new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"BB\");\n" +
+ " }\n" +
+ "});";
+ doMethodTest(text, text);
+ }
+
+ public void testAlignmentMultipleParamsWithAnonymousClass_PassedAsMethodParams() throws Exception {
+ getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+ String text = "test(1000,\n" +
+ " new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"BBB\");\n" +
+ " }\n" +
+ " }\n" +
+ ");";
+ doMethodTest(text, text);
+ }
+
+ public void testAlignmentMultipleAnonymousClassesOnNewLines() throws Exception {
+ getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+ String text = "test(1000,\n" +
+ " new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"BBB\");\n" +
+ " }\n" +
+ " },\n" +
+ " new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ " System.out.println(\"BBB\");\n" +
+ " }\n" +
+ " }\n" +
+ ");";
+ doMethodTest(text, text);
+ }
+
+ public void testEnforceChildrenIndent_OfAnonymousClasses_IfAnyOfParamsIsLocatedOnNewLine() throws Exception {
+ getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+ String text = "test(\"Suuuuuuuuuuuuuuuuuper loooooooooooong string\",\n" +
+ " \"Next loooooooooooooooooooooong striiiiiiiiiiing\", new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ "\n" +
+ " }\n" +
+ " }, new Runnable() {\n" +
+ " @Override\n" +
+ " public void run() {\n" +
+ "\n" +
+ " }\n" +
+ " }\n" +
+ ");\n";
+ doMethodTest(text, text);
+ }
+
public void testPackagePrivateAnnotation() {
// Inspired by IDEA-67294
@@ -480,13 +560,12 @@
" }\n" +
" }, )",
"test(new Runnable() {\n" +
- " public void run() {\n" +
- " }\n" +
- " }, new Runnable() {\n" +
- " public void run() {\n" +
- " }\n" +
- " },\n" +
- ")"
+ " public void run() {\n" +
+ " }\n" +
+ "}, new Runnable() {\n" +
+ " public void run() {\n" +
+ " }\n" +
+ "}, )"
);
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java
index e78f718..ec5081c 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterSpaceTest.java
@@ -76,17 +76,18 @@
public void testCommaInTypeArguments() {
// Inspired by IDEA-31681
- getSettings().SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS = false;
+ getSettings().SPACE_AFTER_COMMA = false;
+ getSettings().SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS = false;
String initial =
"interface TestInterface<A,B> {\n" +
"\n" +
- " <X,Y> void foo(X x, Y y);\n" +
+ " <X,Y> void foo(X x,Y y);\n" +
"}\n" +
"\n" +
"public class FormattingTest implements TestInterface<String,Integer> {\n" +
"\n" +
- " public <X,Y> void foo(X x, Y y) {\n" +
+ " public <X,Y> void foo(X x,Y y) {\n" +
" Map<String,Integer> map = new HashMap<String,Integer>();\n" +
" }\n" +
"}";
@@ -95,14 +96,14 @@
getSettings().SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS = true;
String formatted =
- "interface TestInterface<A, B> {\n" +
+ "interface TestInterface<A,B> {\n" +
"\n" +
- " <X, Y> void foo(X x, Y y);\n" +
+ " <X,Y> void foo(X x,Y y);\n" +
"}\n" +
"\n" +
"public class FormattingTest implements TestInterface<String, Integer> {\n" +
"\n" +
- " public <X, Y> void foo(X x, Y y) {\n" +
+ " public <X,Y> void foo(X x,Y y) {\n" +
" Map<String, Integer> map = new HashMap<String, Integer>();\n" +
" }\n" +
"}";
@@ -490,4 +491,52 @@
"}";
doClassTest(text, text);
}
+
+ public void testSpacesWithinAngleBrackets() throws Exception {
+ getJavaSettings().SPACES_WITHIN_ANGLE_BRACKETS = true;
+
+ String beforeMethod = "static < T > void fromArray( T [ ] a , Collection< T > c) {\n}";
+ doClassTest(beforeMethod, "static < T > void fromArray(T[] a, Collection< T > c) {\n}");
+
+ String beforeLocal = "Map< String, String > map = new HashMap< String, String >();";
+ doMethodTest(beforeLocal, "Map< String, String > map = new HashMap< String, String >();");
+
+ String beforeClass = "class A < U > {\n}";
+ doTextTest(beforeClass, "class A< U > {\n}");
+
+ getJavaSettings().SPACES_WITHIN_ANGLE_BRACKETS = false;
+ doMethodTest(beforeLocal, "Map<String, String> map = new HashMap<String, String>();");
+ doClassTest(beforeMethod, "static <T> void fromArray(T[] a, Collection<T> c) {\n}");
+ doTextTest(beforeClass, "class A<U> {\n}");
+ }
+
+ public void testSpaceAfterClosingAngleBracket_InTypeArgument() throws Exception {
+ String before = "Bar.<String, Integer> mess(null);";
+
+ getJavaSettings().SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT = false;
+ doMethodTest(before, "Bar.<String, Integer>mess(null);");
+
+ getJavaSettings().SPACE_AFTER_CLOSING_ANGLE_BRACKET_IN_TYPE_ARGUMENT = true;
+ doMethodTest(before, "Bar.<String, Integer> mess(null);");
+ }
+
+ public void testSpaceBeforeOpeningAngleBracket_InTypeParameter() throws Exception {
+ String before = "class A<T> {\n}";
+
+ getJavaSettings().SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER = false;
+ doTextTest(before, "class A<T> {\n}");
+
+ getJavaSettings().SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER = true;
+ doTextTest(before, "class A <T> {\n}");
+ }
+
+ public void testSpaceAroundTypeBounds() throws Exception {
+ String before = "public class Foo<T extends Bar & Abba, U> {\n}";
+
+ getJavaSettings().SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS = true;
+ doTextTest(before, "public class Foo<T extends Bar & Abba, U> {\n}");
+
+ getJavaSettings().SPACE_AROUND_TYPE_BOUNDS_IN_TYPE_PARAMETERS = false;
+ doTextTest(before, "public class Foo<T extends Bar&Abba, U> {\n}");
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
index 8adb06b..c00db0f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -15,17 +15,17 @@
*/
package com.intellij.psi.formatter.java;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
-import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.codeStyle.CodeStyleSettings;
-import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.JavaCodeFragmentFactory;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiCodeFragment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.codeStyle.*;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
@@ -1150,7 +1150,7 @@
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
try {
@@ -3016,4 +3016,36 @@
settings.FORMATTER_ON_TAG = "end.*fragment";
doTest();
}
+
+ public void testDoNotIndentNotSelectedStatement_AfterSelectedOne() {
+ myTextRange = new TextRange(0, 73);
+ doTextTest(
+ "class Test {\n" +
+ " public static void main(String[] args) {\n" +
+ " int a = 3;\n" +
+ " System.out.println(\"AAA\");\n" +
+ " }\n" +
+ "}",
+ "class Test {\n" +
+ " public static void main(String[] args) {\n" +
+ " int a = 3;\n" +
+ " System.out.println(\"AAA\");\n" +
+ " }\n" +
+ "}"
+ );
+
+ myTextRange = new TextRange(0, 67);
+ doTextTest(
+ " import java.lang.Override;\n" +
+ " import java.lang.Exception;\n" +
+ " \n" +
+ " class Foo {\n" +
+ "}",
+ "import java.lang.Override;\n" +
+ "import java.lang.Exception;\n" +
+ " \n" +
+ " class Foo {\n" +
+ "}"
+ );
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
index c867bf1..5e545ec 100644
--- a/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/formatter/java/JavaFormatterWrapTest.java
@@ -325,9 +325,72 @@
"test(1,\n" +
" 2,\n" +
" Test.\n" +
- " loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongMethod());\n" +
+ " loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooongMethod()\n" +
+ ");\n" +
"int i = 1;\n" +
"int j = 2;";
doMethodTest(text, text);
}
+
+ public void testEnforceIndent_MethodCallParamWrap() throws Exception {
+ getSettings().WRAP_LONG_LINES = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 140;
+ getSettings().PREFER_PARAMETERS_WRAP = true;
+ getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
+
+ String before = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, String.format(\"Could not process annotations: %s%n%s\", e.toString(), writer.toString()));";
+
+ String afterFirstReformat = "processingEnv.getMessenger().printMessage(\n" +
+ " Diagnostic.Kind.ERROR, String.format(\n" +
+ " \"Could not process annotations: %s%n%s\",\n" +
+ " e.toString(),\n" +
+ " writer.toString()\n" +
+ ")\n" +
+ ");";
+
+ String after = "processingEnv.getMessenger().printMessage(\n" +
+ " Diagnostic.Kind.ERROR, String.format(\n" +
+ " \"Could not process annotations: %s%n%s\",\n" +
+ " e.toString(),\n" +
+ " writer.toString()\n" +
+ " )\n" +
+ ");";
+
+ doMethodTest(afterFirstReformat, after);
+
+ getSettings().CALL_PARAMETERS_RPAREN_ON_NEXT_LINE = true;
+ getSettings().CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = true;
+ doMethodTest(before, after);
+
+ before = "processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, call(\"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"));\n";
+ after = "processingEnv.getMessager().printMessage(\n" +
+ " Diagnostic.Kind.ERROR, call(\n" +
+ " \"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n" +
+ " )\n" +
+ ");\n";
+
+ doMethodTest(before, after);
+ }
+
+ public void testDoNotWrap_MethodsWithMethodCallAsParameters() throws Exception {
+ getSettings().WRAP_LONG_LINES = true;
+ getSettings().getRootSettings().RIGHT_MARGIN = 140;
+ getSettings().PREFER_PARAMETERS_WRAP = true;
+ getSettings().CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
+ getSettings().CALL_PARAMETERS_RPAREN_ON_NEXT_LINE = true;
+ getSettings().CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = true;
+
+ String before = " processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage());";
+ String after = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage());";
+
+ doMethodTest(before, after);
+
+ before = " processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage(loooooooooooooooooongParamName));";
+ after = "processingEnv.getMessenger().printMessage(Diagnostic.Kind.ERROR, getMessage(loooooooooooooooooongParamName));";
+
+ doMethodTest(before, after);
+ }
+
+
+
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR14423Test.java b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR14423Test.java
index b1692ba..2870108 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR14423Test.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/cache/impl/SCR14423Test.java
@@ -1,6 +1,22 @@
+/*
+ * 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.psi.impl.cache.impl;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
@@ -35,7 +51,7 @@
root.mkdir();
myFilesToDelete.add(root);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
try {
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java
index 7d0aaa6..12c94d2 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/smartPointers/SmartPsiElementPointersTest.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.
@@ -416,4 +416,22 @@
Assert.assertNotNull(pointer1.getRange());
}
}
+
+ public void testSmartPointerCreationDoesNotLoadDocument() {
+ PsiPackage aPackage = myJavaFacade.findPackage("java.io");
+ SmartPointerManagerImpl smartPointerManager = (SmartPointerManagerImpl)SmartPointerManager.getInstance(myProject);
+ for (PsiClass aClass : aPackage.getClasses()) {
+ PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
+ PsiFile file = aClass.getContainingFile();
+ Document document = documentManager.getCachedDocument(file);
+ if (document == null) { //ignore already loaded documents
+ SmartPsiElementPointer pointer = smartPointerManager.createSmartPsiElementPointer(aClass);
+ assertNull(documentManager.getCachedDocument(file));
+ //System.out.println("file = " + file);
+ }
+ else {
+ System.out.println("already loaded file = " + file);
+ }
+ }
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java
index cf33765..c926afd 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/BindToElementTest.java
@@ -1,14 +1,30 @@
+/*
+ * 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.psi.impl.source.tree.java;
import com.intellij.codeInsight.CodeInsightTestCase;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.IncorrectOperationException;
@@ -17,13 +33,14 @@
/**
* @author dsl
*/
+@PlatformTestCase.WrapInCommand
public class BindToElementTest extends CodeInsightTestCase {
public static final String TEST_ROOT = PathManagerEx.getTestDataPath() + "/psi/impl/bindToElementTest/".replace('/', File.separatorChar);
@Override
protected void setUp() throws Exception {
super.setUp();
- VirtualFile root = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ VirtualFile root = WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java
index f8fdc17..85aa78f 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ExtendsBoundListTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package com.intellij.psi.impl.source.tree.java;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.testFramework.LightCodeInsightTestCase;
@@ -25,7 +26,7 @@
public class ExtendsBoundListTest extends LightCodeInsightTestCase {
public void testRemoveBoundFromFront() throws Exception {
final PsiTypeParameter typeParameter = getTypeParameter();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
typeParameter.getExtendsList().getReferenceElements()[0].delete();
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java
index 5fa7fa8..3c637f8 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/JavadocParamTagsTest.java
@@ -1,8 +1,24 @@
+/*
+ * 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.psi.impl.source.tree.java;
import com.intellij.codeInsight.CodeInsightUtilCore;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.javadoc.PsiDocTag;
@@ -25,7 +41,7 @@
final PsiDocComment docComment = method.getDocComment();
assertNotNull(docComment);
final PsiDocTag[] tags = docComment.getTags();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
tags[0].delete();
diff --git a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java
index 5683089..964474a 100644
--- a/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/impl/source/tree/java/ReferenceParameterListTest.java
@@ -1,6 +1,21 @@
+/*
+ * 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.psi.impl.source.tree.java;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
@@ -41,12 +56,13 @@
null);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
try {
classFromText.setName("Q");
- } catch (IncorrectOperationException e) {
+ }
+ catch (IncorrectOperationException e) {
LOG.error(e);
}
}
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 1ac6c36..e21c180 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
@@ -15,9 +15,9 @@
*/
package com.intellij.psi.impl.source.tree.java;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.impl.JavaPsiFacadeEx;
@@ -77,7 +77,7 @@
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
JavaCodeStyleManager.getInstance(getProject()).shortenClassReferences(myFixture.getFile());
diff --git a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy
index 8e3a64a..5e6adfd 100644
--- a/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/psi/resolve/ResolveInLibrariesTest.groovy
@@ -125,8 +125,8 @@
assert other0.isInheritor(i0, true)
assert !other0.isInheritor(i0, false)
- assert ClassInheritorsSearch.search(i0).findAll() == [m0, b1, other0]
- assert ClassInheritorsSearch.search(m0).findAll() == [b1, other0]
+ assert ClassInheritorsSearch.search(i0).findAll() == [m0, b1, other0] as Set
+ assert ClassInheritorsSearch.search(m0).findAll() == [b1, other0] as Set
assert fooInheritors(i0) == [fooMethod(m0), fooMethod(other0)] as Set
assert fooInheritors(m0) == [fooMethod(other0), fooMethod(b1)] as Set
diff --git a/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java b/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java
index 11aa9b6..4d6291e 100644
--- a/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java
+++ b/java/java-tests/testSrc/com/intellij/psi/search/InheritorsTest.java
@@ -53,6 +53,10 @@
doTest("x.Test", "", true, "x.Goo", "x.Zoo");
}
+ public void testMultipleInheritance() throws Exception {
+ doTest("I", "", true, "A", "B");
+ }
+
private void doTest(String className, String packageScopeName, final boolean deep, String... inheritorNames) throws Exception {
final PsiClass aClass = myJavaFacade.findClass(className);
assertNotNull(aClass);
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/AnonymousToInnerTest.java b/java/java-tests/testSrc/com/intellij/refactoring/AnonymousToInnerTest.java
index f37c769..0cb6685 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/AnonymousToInnerTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/AnonymousToInnerTest.java
@@ -18,11 +18,13 @@
import com.intellij.JavaTestUtil;
import com.intellij.refactoring.anonymousToInner.AnonymousToInnerHandler;
import com.intellij.testFramework.LightCodeInsightTestCase;
+import com.intellij.testFramework.TestDataPath;
import org.jetbrains.annotations.NotNull;
/**
* @author yole
*/
+@TestDataPath("$CONTENT_ROOT/testData")
public class AnonymousToInnerTest extends LightCodeInsightTestCase {
private static final String TEST_ROOT = "/refactoring/anonymousToInner/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java
index 61f3b18..36d7d39 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureGestureTest.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.
@@ -30,7 +30,6 @@
import com.intellij.refactoring.changeSignature.ChangeSignatureDetectorAction;
import com.intellij.refactoring.changeSignature.ChangeSignatureGestureDetector;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
-import junit.framework.Assert;
import java.util.List;
@@ -62,9 +61,10 @@
final IntentionAction intention = myFixture.findSingleIntention(hint);
myFixture.launchAction(intention);
myFixture.checkResultByFile("/refactoring/changeSignatureGesture/" + getTestName(false) + "_after.java");
- } else {
+ }
+ else {
final List<IntentionAction> intentionActions = myFixture.filterAvailableIntentions(hint);
- Assert.assertEquals(true, intentionActions.isEmpty());
+ assertEmpty(intentionActions);
}
}
finally {
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java
index b7a5662..e769c7a 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ChangeSignatureTest.java
@@ -182,6 +182,12 @@
}, false);
}
+ public void testJavadocNoNewLineInserted() throws Exception {
+ doTest(null, new ParameterInfoImpl[]{
+ new ParameterInfoImpl(0, "newArgs", PsiType.DOUBLE),
+ }, false);
+ }
+
public void testSuperCallFromOtherMethod() throws Exception {
doTest(null, new ParameterInfoImpl[] {
new ParameterInfoImpl(-1, "nnn", PsiType.INT, "-222"),
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java
index 3c6d9fd..5189caf 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/CopyClassTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,7 +17,9 @@
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightTestCase;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
@@ -25,6 +27,7 @@
import com.intellij.psi.search.ProjectScope;
import com.intellij.refactoring.copy.CopyClassesHandler;
import com.intellij.testFramework.IdeaTestUtil;
+import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.util.IncorrectOperationException;
@@ -36,6 +39,7 @@
/**
* @author yole
*/
+@PlatformTestCase.WrapInCommand
public class CopyClassTest extends CodeInsightTestCase {
private VirtualFile myRootDir;
@@ -65,9 +69,18 @@
}
private PsiElement performAction(final String oldName, final String copyName) throws IncorrectOperationException {
- PsiClass oldClass = JavaPsiFacade.getInstance(myProject).findClass(oldName, ProjectScope.getAllScope(myProject));
- return CopyClassesHandler.doCopyClasses(Collections.singletonMap(oldClass.getNavigationElement().getContainingFile(), new PsiClass[]{oldClass}), copyName, myPsiManager.findDirectory(myRootDir),
- myProject);
+ final PsiClass oldClass = JavaPsiFacade.getInstance(myProject).findClass(oldName, ProjectScope.getAllScope(myProject));
+
+ return WriteCommandAction.runWriteCommandAction(null, new Computable<PsiElement>(){
+ @Override
+ public PsiElement compute() {
+ return CopyClassesHandler.doCopyClasses(
+ Collections.singletonMap(oldClass.getNavigationElement().getContainingFile(), new PsiClass[]{oldClass}), copyName,
+ myPsiManager.findDirectory(myRootDir),
+ myProject);
+
+ }
+ });
}
public void testPackageLocalClasses() throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.java b/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.java
index 51a5acf..ee971c4 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/DndMoveTest.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.
@@ -21,6 +21,7 @@
import com.intellij.psi.*;
import com.intellij.refactoring.move.MoveHandler;
import com.intellij.testFramework.PsiTestUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -28,6 +29,7 @@
* @since Aug 31, 2010
*/
public class DndMoveTest extends CodeInsightTestCase {
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/dndMove/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java
index 666168b..a24ffb0 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/EncapsulateFieldsTest.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.
@@ -36,6 +36,7 @@
import com.intellij.refactoring.encapsulateFields.FieldDescriptorImpl;
import com.intellij.refactoring.util.DocCommentPolicy;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
public class EncapsulateFieldsTest extends MultiFileTestCase{
public void testAlreadyExist() throws Exception {
@@ -76,6 +77,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/encapsulateFields/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java
index 1e287b2..812b2ab 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractClassTest.java
@@ -1,4 +1,20 @@
/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
* User: anna
* Date: 20-Aug-2008
*/
@@ -17,6 +33,7 @@
import com.intellij.refactoring.extractclass.ExtractClassProcessor;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
@@ -24,6 +41,7 @@
import java.util.TreeSet;
public class ExtractClassTest extends MultiFileTestCase{
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/extractClass/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java
index 48d711b..c6b811c 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ExtractEnumTest.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.refactoring.extractclass.ExtractClassProcessor;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
@@ -36,6 +37,7 @@
public class ExtractEnumTest extends MultiFileTestCase {
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/extractEnum/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/InheritanceToDelegationTest.java b/java/java-tests/testSrc/com/intellij/refactoring/InheritanceToDelegationTest.java
index 5b72898..0106832 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/InheritanceToDelegationTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/InheritanceToDelegationTest.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.refactoring;
import com.intellij.JavaTestUtil;
@@ -8,6 +23,7 @@
import com.intellij.refactoring.inheritanceToDelegation.InheritanceToDelegationProcessor;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -21,6 +37,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/inheritanceToDelegation/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/InlineSuperClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/InlineSuperClassTest.java
index 2aecb28..690f7ac 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/InlineSuperClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/InlineSuperClassTest.java
@@ -1,4 +1,20 @@
/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
* User: anna
* Date: 20-Aug-2008
*/
@@ -10,8 +26,10 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.inlineSuperClass.InlineSuperClassRefactoringProcessor;
import com.intellij.refactoring.util.DocCommentPolicy;
+import org.jetbrains.annotations.NotNull;
public class InlineSuperClassTest extends MultiFileTestCase {
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/inlineSuperClass/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceParameterTest.java b/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceParameterTest.java
index 5be5dad..697b423 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceParameterTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/InplaceIntroduceParameterTest.java
@@ -122,7 +122,7 @@
});
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
- assertEquals("There is already a parameter <b><code>p</code></b>. It will conflict with an introduced parameter", e.getMessage());
+ assertEquals("There is already a parameter <b><code>p</code></b>. It will conflict with the introduced parameter", e.getMessage());
return;
}
fail("Conflict expected");
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java
index 3704351..3308baa 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceConstantTest.java
@@ -91,6 +91,12 @@
checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
}
+ public void testPartialStringLiteralAnchorFromAnnotation() throws Exception {
+ configureByFile(BASE_PATH + getTestName(false) + ".java");
+ new MockIntroduceConstantHandler(null).invoke(getProject(), getEditor(), getFile(), null);
+ checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
+ }
+
public void testIntroduceConstantFromThisCall() throws Exception {
configureByFile(BASE_PATH + getTestName(false) + ".java");
new MockIntroduceConstantHandler(null).invoke(getProject(), getEditor(), getFile(), null);
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java
index 905f87e..387424a 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceParameterObjectTest.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.
@@ -30,8 +30,10 @@
import com.intellij.refactoring.util.VariableData;
import com.intellij.util.Function;
import com.intellij.util.VisibilityUtil;
+import org.jetbrains.annotations.NotNull;
public class IntroduceParameterObjectTest extends MultiFileTestCase{
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/introduceParameterObject/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableMultifileTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableMultifileTest.java
index e967250..b200906 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableMultifileTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableMultifileTest.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.refactoring;
import com.intellij.JavaTestUtil;
@@ -11,10 +26,13 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
+import com.intellij.testFramework.PlatformTestCase;
+import org.jetbrains.annotations.NotNull;
/**
* @author dsl
*/
+@PlatformTestCase.WrapInCommand
public class IntroduceVariableMultifileTest extends MultiFileTestCase {
@Override
protected void setUp() throws Exception {
@@ -22,6 +40,7 @@
LanguageLevelProjectExtension.getInstance(myJavaFacade.getProject()).setLanguageLevel(LanguageLevel.JDK_1_5);
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/introduceVariable/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java
index 35560bf..16c7d33 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java
@@ -18,10 +18,9 @@
import com.intellij.JavaTestUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiExpression;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.PsiResolveHelperImpl;
+import com.intellij.psi.impl.source.resolve.graphInference.PsiGraphInferenceHelper;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.introduceVariable.InputValidator;
import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
@@ -98,6 +97,18 @@
doTest(new MockIntroduceVariableHandler("temp", true, false, false, "int"));
}
+ public void testExpectedType8Inference() throws Exception {
+ final PsiResolveHelperImpl helper = (PsiResolveHelperImpl)JavaPsiFacade.getInstance(getProject()).getResolveHelper();
+ helper.setTestHelper(new PsiGraphInferenceHelper(getPsiManager()));
+ try {
+ doTest(new MockIntroduceVariableHandler("temp", true, false, false,
+ "java.util.Map<java.lang.String,java.util.List<java.lang.String>>"));
+ }
+ finally {
+ helper.setTestHelper(null);
+ }
+ }
+
public void testMethodCall() throws Exception {
doTest(new MockIntroduceVariableHandler("temp", true, true, true, CommonClassNames.JAVA_LANG_OBJECT));
}
@@ -412,6 +423,10 @@
doTest(new MockIntroduceVariableHandler("c", false, false, false, CommonClassNames.JAVA_LANG_OBJECT));
}
+ public void testWriteUsages() throws Exception {
+ doTest(new MockIntroduceVariableHandler("c", true, false, false, CommonClassNames.JAVA_LANG_STRING));
+ }
+
public void testLambdaExpr() throws Exception {
doTest(new MockIntroduceVariableHandler("c", false, false, false, "SAM<java.lang.Integer>"));
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java b/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java
index 1755770..82b5a2d 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/InvertBooleanTest.java
@@ -1,54 +1,39 @@
package com.intellij.refactoring;
-import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
+import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.refactoring.invertBoolean.InvertBooleanProcessor;
-import org.jetbrains.annotations.NotNull;
+import com.intellij.testFramework.TestDataPath;
/**
* @author ven
*/
-public class InvertBooleanTest extends LightRefactoringTestCase {
- @NotNull
+@TestDataPath("$CONTENT_ROOT/testData/refactoring/invertBoolean/")
+public class InvertBooleanTest extends LightRefactoringParameterizedTestCase {
@Override
- protected String getTestDataPath() {
- return JavaTestUtil.getJavaTestDataPath();
- }
-
- private static final String TEST_ROOT = "/refactoring/invertBoolean/";
-
- public void test1() throws Exception { doTest(); }
-
- public void test2() throws Exception { doTest(); } //inverting breaks overriding
-
- public void testParameter() throws Exception { doTest(); } //inverting boolean parameter
-
- public void testParameter1() throws Exception { doTest(); } //inverting boolean parameter more advanced stuff
- public void testUnusedReturnValue() throws Exception { doTest(); }
-
- public void testInnerClasses() throws Exception {doTest();}
- public void testAnonymousClasses() throws Exception {doTest();}
- public void testMethodRefs() throws Exception {
- try {
- doTest();
- fail("Conflict expected.");
- }
- catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
- assertEquals("Method is used in method reference expression", e.getMessage());
- }
- }
-
- private void doTest() throws Exception {
- configureByFile(TEST_ROOT + getTestName(true) + ".java");
+ protected void perform() {
PsiElement element = TargetElementUtilBase.findTargetElement(myEditor, TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
assertTrue(element instanceof PsiNamedElement);
final PsiNamedElement namedElement = (PsiNamedElement)element;
final String name = namedElement.getName();
new InvertBooleanProcessor(namedElement, name + "Inverted").run();
- checkResultByFile(TEST_ROOT + getTestName(true) + "_after.java");
}
+ @Override
+ protected String getAfterFile(String fileName) {
+ return FileUtilRt.getNameWithoutExtension(fileName) + "_" + AFTER_PREFIX + "." + FileUtilRt.getExtension(fileName);
+ }
+
+ @Override
+ protected String getBeforeFile(String fileName) {
+ return fileName;
+ }
+
+ @Override
+ public String getFileSuffix(String beforeFile) {
+ return !beforeFile.contains(AFTER_PREFIX) && !beforeFile.endsWith(CONFLICTS_SUFFIX) ? beforeFile : null;
+ }
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/LightRefactoringParameterizedTestCase.java b/java/java-tests/testSrc/com/intellij/refactoring/LightRefactoringParameterizedTestCase.java
new file mode 100644
index 0000000..b822a66
--- /dev/null
+++ b/java/java-tests/testSrc/com/intellij/refactoring/LightRefactoringParameterizedTestCase.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
+ * Created by IntelliJ IDEA.
+ * User: dsl
+ * Date: 04.06.2002
+ * Time: 20:01:43
+ * To change template for new class use
+ * Code Style | Class Templates options (Tools | IDE Options).
+ */
+package com.intellij.refactoring;
+
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.testFramework.FileBasedTestCaseHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+
+@RunWith(com.intellij.testFramework.Parameterized.class)
+public abstract class LightRefactoringParameterizedTestCase extends LightRefactoringTestCase implements FileBasedTestCaseHelper {
+
+ protected static final String BEFORE_PREFIX = "before";
+ protected static final String AFTER_PREFIX = "after";
+ protected static final String CONFLICTS_SUFFIX = ".conflicts.txt";
+
+ protected abstract void perform();
+
+ protected abstract String getAfterFile(String fileNameCore);
+ protected abstract String getBeforeFile(String fileNameCore);
+
+ @Test
+ public void runSingle() throws Throwable {
+ final Throwable[] throwables = new Throwable[1];
+
+ final Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final String filePath = getBeforeFile(myFileSuffix);
+ configureByFile(filePath);
+
+ final File testDir = new File(getTestDataPath(), filePath).getParentFile();
+ final String afterName = getAfterFile(myFileSuffix);
+ final boolean conflictShouldBeFound = !new File(testDir, afterName).exists();
+ try {
+ perform();
+ if (conflictShouldBeFound) {
+ fail("Conflict expected.");
+ }
+ }
+ catch (BaseRefactoringProcessor.ConflictsInTestsException exception) {
+ if (!conflictShouldBeFound) {
+ fail("Conflict not expected");
+ } else {
+ final File conflicts = new File(testDir, FileUtilRt.getNameWithoutExtension(myFileSuffix) + CONFLICTS_SUFFIX);
+ if (!conflicts.exists()) {
+ fail("Conflict file " + conflicts.getPath() + " not found");
+ }
+ final VirtualFile conflictsFile = VfsUtil.findFileByIoFile(conflicts, false);
+ assertNotNull(conflictsFile);
+ assertEquals(LoadTextUtil.loadText(conflictsFile).toString(), exception.getMessage());
+ }
+ }
+
+ if (!conflictShouldBeFound) {
+ checkResultByFile(getAfterFile(myFileSuffix));
+ }
+ }
+ catch (Throwable e) {
+ throwables[0] = e;
+ }
+ }
+ };
+
+ invokeTestRunnable(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ runnable.run();
+ }
+ }, "", null);
+ }
+ });
+
+ if (throwables[0] != null) {
+ throw throwables[0];
+ }
+
+ }
+}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MoveInnerTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MoveInnerTest.java
index bbc7576..2e6865b 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/MoveInnerTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/MoveInnerTest.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,6 +25,7 @@
import com.intellij.refactoring.move.moveInner.MoveInnerImpl;
import com.intellij.refactoring.move.moveInner.MoveInnerProcessor;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -36,6 +37,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/moveInner/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java
index 2f384c9..83e8fa1 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/MoveMembersTest.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.refactoring;
import com.intellij.JavaTestUtil;
@@ -13,6 +28,7 @@
import com.intellij.refactoring.move.moveMembers.MockMoveMembersOptions;
import com.intellij.refactoring.move.moveMembers.MoveMembersProcessor;
import com.intellij.util.VisibilityUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.LinkedHashSet;
@@ -171,6 +187,7 @@
doTest("Outer.Inner", "Outer", true, VisibilityUtil.ESCALATE_VISIBILITY, 0);
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/moveMembers/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MovePackageAsDirectoryTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MovePackageAsDirectoryTest.java
index 01b8604..d4fb335 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/MovePackageAsDirectoryTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/MovePackageAsDirectoryTest.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,6 +17,7 @@
import com.intellij.JavaTestUtil;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileAdapter;
@@ -27,6 +28,7 @@
import com.intellij.refactoring.move.moveClassesOrPackages.MoveDirectoryWithClassesProcessor;
import com.intellij.testFramework.PsiTestUtil;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Comparator;
@@ -38,6 +40,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/movePackageAsDir/";
@@ -86,7 +89,7 @@
protected void preprocessSrcDir(PsiDirectory srcDirectory) {
final PsiFile empty = srcDirectory.findFile(EMPTY_TXT);
assert empty != null;
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
empty.delete();
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MovePackageMultirootTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MovePackageMultirootTest.java
index 4dd2381..1ae0af9 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/MovePackageMultirootTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/MovePackageMultirootTest.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.
@@ -28,6 +28,7 @@
import com.intellij.refactoring.move.moveClassesOrPackages.MultipleRootsMoveDestination;
import com.intellij.JavaTestUtil;
import com.intellij.testFramework.PsiTestUtil;
+import org.jetbrains.annotations.NotNull;
/**
* @author dsl
@@ -39,6 +40,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/movePackageMultiroot/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MovePackageTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MovePackageTest.java
index 1c35bd2..19296b0 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/MovePackageTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/MovePackageTest.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.refactoring;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -8,6 +23,7 @@
import com.intellij.refactoring.move.moveClassesOrPackages.MoveClassesOrPackagesProcessor;
import com.intellij.refactoring.move.moveClassesOrPackages.SingleSourceRootMoveDestination;
import com.intellij.JavaTestUtil;
+import org.jetbrains.annotations.NotNull;
public class MovePackageTest extends MultiFileTestCase {
@@ -33,6 +49,7 @@
doTest(new String[]{"a"}, "a.b");
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/movePackage/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java
index 2d3864b..a1df6db 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/PullUpMultifileTest.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,12 +30,14 @@
import com.intellij.refactoring.util.classMembers.InterfaceContainmentVerifier;
import com.intellij.refactoring.util.classMembers.MemberInfo;
import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.HashSet;
//pull first method from class a.A to class b.B
public class PullUpMultifileTest extends MultiFileTestCase {
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/pullUp/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/PushDownMultifileTest.java b/java/java-tests/testSrc/com/intellij/refactoring/PushDownMultifileTest.java
index c10a6cd..1119144 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/PushDownMultifileTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/PushDownMultifileTest.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.
@@ -29,9 +29,11 @@
import com.intellij.refactoring.memberPushDown.PushDownProcessor;
import com.intellij.refactoring.util.DocCommentPolicy;
import com.intellij.refactoring.util.classMembers.MemberInfo;
+import org.jetbrains.annotations.NotNull;
//push first method from class a.A to class b.B
public class PushDownMultifileTest extends MultiFileTestCase {
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/pushDown/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RemoveMiddleManTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RemoveMiddleManTest.java
index fa025c8..8966302 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/RemoveMiddleManTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/RemoveMiddleManTest.java
@@ -1,4 +1,20 @@
/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
* User: anna
* Date: 20-Aug-2008
*/
@@ -15,6 +31,7 @@
import com.intellij.refactoring.removemiddleman.DelegationUtils;
import com.intellij.refactoring.removemiddleman.RemoveMiddlemanProcessor;
import com.intellij.refactoring.util.classMembers.MemberInfo;
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
@@ -26,6 +43,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/removemiddleman/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameClassTest.java
index c3c4de3..6bf0f40 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/RenameClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameClassTest.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.refactoring;
import com.intellij.JavaTestUtil;
@@ -10,6 +25,7 @@
import com.intellij.refactoring.rename.RenameProcessor;
import com.intellij.refactoring.rename.naming.AutomaticRenamerFactory;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
public class RenameClassTest extends MultiFileTestCase {
@Override
@@ -101,6 +117,7 @@
FileDocumentManager.getInstance().saveAllDocuments();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/renameClass/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
index e09c448..4fc4240 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameCollisionsTest.java
@@ -197,6 +197,10 @@
doTest("foo2");
}
+ public void testRenameNoStaticOverridingInInterfaces() throws Exception {
+ doTest("foo");
+ }
+
public void testRenameTypeParameterToExistingClassName() throws Exception {
doTest("P");
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/RenameMethodMultiTest.java b/java/java-tests/testSrc/com/intellij/refactoring/RenameMethodMultiTest.java
index 6da0cdf..cb354a6 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/RenameMethodMultiTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/RenameMethodMultiTest.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.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.rename.RenameProcessor;
+import org.jetbrains.annotations.NotNull;
import org.junit.Assert;
/**
@@ -34,6 +35,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/renameMethod/multi/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java
index 7d18135..a727714 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/ReplaceConstructorWithBuilderTest.java
@@ -1,4 +1,20 @@
/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
* User: anna
* Date: 06-May-2008
*/
@@ -14,6 +30,7 @@
import com.intellij.refactoring.replaceConstructorWithBuilder.ParameterData;
import com.intellij.refactoring.replaceConstructorWithBuilder.ReplaceConstructorWithBuilderProcessor;
import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
import java.util.LinkedHashMap;
import java.util.Map;
@@ -122,6 +139,7 @@
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/replaceConstructorWithBuilder/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
index 0c534a9..a6768c9 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/SafeDeleteTest.java
@@ -1,41 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
-import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.safeDelete.SafeDeleteHandler;
-import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
-import java.io.File;
-
public class SafeDeleteTest extends MultiFileTestCase {
- private VirtualFile myRootBefore;
-
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/safeDelete/";
}
- @Override
- protected boolean clearModelBeforeConfiguring() {
- return true;
- }
-
public void testImplicitCtrCall() throws Exception {
try {
doTest("Super");
@@ -59,12 +65,10 @@
}
public void testMultipleInterfacesImplementation() throws Exception {
- myDoCompare = false;
doTest("IFoo");
}
public void testMultipleInterfacesImplementationThroughCommonInterface() throws Exception {
- myDoCompare = false;
doTest("IFoo");
}
@@ -73,43 +77,35 @@
}
public void testParameterInHierarchy() throws Exception {
- myDoCompare = false;
doTest("C2");
}
public void testTopLevelDocComment() throws Exception {
- myDoCompare = false;
doTest("foo.C1");
}
public void testTopParameterInHierarchy() throws Exception {
- myDoCompare = false;
doTest("I");
}
public void testExtendsList() throws Exception {
- myDoCompare = false;
doTest("B");
}
public void testJavadocParamRef() throws Exception {
- myDoCompare = false;
doTest("Super");
}
public void testEnumConstructorParameter() throws Exception {
- myDoCompare = false;
doTest("UserFlags");
}
public void testSafeDeleteStaticImports() throws Exception {
- myDoCompare = false;
doTest("A");
}
public void testRemoveOverridersInspiteOfUnsafeUsages() throws Exception {
- myDoCompare = false;
try {
BaseRefactoringProcessor.ConflictsInTestsException.setTestIgnore(true);
doTest("A");
@@ -120,17 +116,14 @@
}
public void testLocalVariable() throws Exception {
- myDoCompare = false;
doTest("Super");
}
public void testOverrideAnnotation() throws Exception {
- myDoCompare = false;
doTest("Super");
}
public void testSuperCall() throws Exception {
- myDoCompare = false;
try {
doTest("Super");
fail("Conflict was not detected");
@@ -142,7 +135,6 @@
}
public void testMethodDeepHierarchy() throws Exception {
- myDoCompare = false;
doTest("Super");
}
@@ -151,7 +143,6 @@
}
public void testLocalVariableSideEffect() throws Exception {
- myDoCompare = false;
try {
doTest("Super");
fail("Side effect was ignored");
@@ -163,7 +154,6 @@
}
public void testUsageInGenerated() throws Exception {
- myDoCompare = false;
doTest("A");
}
@@ -190,13 +180,16 @@
public void testStripOverride() throws Exception {
doSingleFileTest();
}
+
+ public void testEmptyIf() throws Exception {
+ doSingleFileTest();
+ }
private void doTest(@NonNls final String qClassName) throws Exception {
doTest(new PerformAction() {
@Override
public void performAction(VirtualFile rootDir, VirtualFile rootAfter) throws Exception {
SafeDeleteTest.this.performAction(qClassName);
- PlatformTestUtil.assertDirectoriesEqual(rootAfter, myRootBefore);
}
});
}
@@ -226,9 +219,7 @@
private void performAction(final String qClassName) throws Exception {
final PsiClass aClass = myJavaFacade.findClass(qClassName, GlobalSearchScope.allScope(getProject()));
assertNotNull("Class " + qClassName + " not found", aClass);
-
- final String root = ProjectRootManager.getInstance(getProject()).getContentRoots()[0].getPath();
- myRootBefore = configureByFiles(new File(root), aClass.getContainingFile().getVirtualFile());
+ configureByExistingFile(aClass.getContainingFile().getVirtualFile());
performAction();
}
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java b/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java
index 44defbe..a2ab684 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/TurnRefsToSuperTest.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.search.GlobalSearchScope;
import com.intellij.refactoring.turnRefsToSuper.TurnRefsToSuperProcessor;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
public class TurnRefsToSuperTest extends MultiFileTestCase {
public void testSuperClass() throws Exception { doTest("AClass", "ASuper", true); }
@@ -73,6 +74,7 @@
}, true);
}
+ @NotNull
@Override
public String getTestRoot() {
return "/refactoring/turnRefsToSuper/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java b/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java
index 076280d..5cfefaa 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/TypeCookTest.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.refactoring.typeCook.deductive.builder.SystemBuilder;
import com.intellij.refactoring.typeCook.deductive.resolver.Binding;
import com.intellij.refactoring.typeCook.deductive.resolver.ResolverTree;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.FileNotFoundException;
@@ -47,6 +48,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
public String getTestRoot() {
return "/refactoring/typeCook/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java b/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java
index ddd3803..1b0d7f1 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/WrapReturnValueTest.java
@@ -1,4 +1,20 @@
/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
* User: anna
* Date: 20-Aug-2008
*/
@@ -12,6 +28,7 @@
import com.intellij.refactoring.wrapreturnvalue.WrapReturnValueProcessor;
import com.intellij.JavaTestUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
public class WrapReturnValueTest extends MultiFileTestCase{
@Override
@@ -19,6 +36,7 @@
return JavaTestUtil.getJavaTestDataPath();
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/wrapReturnValue/";
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java
index 2bbee1a..541d75d 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineLibraryMethodTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,9 +17,12 @@
import com.intellij.JavaTestUtil;
import com.intellij.ide.highlighter.JavaFileType;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiMethod;
import com.intellij.refactoring.RefactoringTestCase;
import com.intellij.refactoring.util.InlineUtil;
import org.jetbrains.annotations.NonNls;
@@ -48,7 +51,7 @@
PsiClass fileClass = getJavaFacade().findClass("mycompany.File");
assertNotNull(fileClass);
final PsiFile file = fileClass.getContainingFile();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
try {
((VirtualFileSystemEntry)file.getVirtualFile()).setWritable(false);
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java
index b49a306..6432763 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineParameterTest.java
@@ -138,6 +138,10 @@
doTest(false);
}
+ public void testPropagatedParams() throws Exception {
+ doTest(false);
+ }
+
public void testParameterWithWriteAccess() throws Exception {
try {
doTest(false);
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineToAnonymousClassTest.java b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineToAnonymousClassTest.java
index 0da3db2..8325a33 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineToAnonymousClassTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/inline/InlineToAnonymousClassTest.java
@@ -231,6 +231,10 @@
public void testBraces() throws Exception {
doTest(false, false);
}
+
+ public void testAvailableInSupers() throws Exception {
+ doTest(false, false);
+ }
public void testNoInlineAbstract() throws Exception {
doTestNoInline("Abstract classes cannot be inlined");
diff --git a/java/java-tests/testSrc/com/intellij/refactoring/migration/MigrationTest.java b/java/java-tests/testSrc/com/intellij/refactoring/migration/MigrationTest.java
index f66f695..91349d6 100644
--- a/java/java-tests/testSrc/com/intellij/refactoring/migration/MigrationTest.java
+++ b/java/java-tests/testSrc/com/intellij/refactoring/migration/MigrationTest.java
@@ -1,9 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.migration;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.refactoring.MultiFileTestCase;
import com.intellij.JavaTestUtil;
+import org.jetbrains.annotations.NotNull;
/**
* @author dsl
@@ -50,6 +66,7 @@
};
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/refactoring/migration/";
diff --git a/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java b/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java
index e604800..ef3800d 100644
--- a/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java
+++ b/java/java-tests/testSrc/com/intellij/roots/MultiModuleEditingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.ProjectTopics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -191,10 +192,11 @@
}
private VirtualFile getVirtualFileInTestData(final String relativeVfsPath) {
- return ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ return WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
- final String path = TEST_PATH + File.separatorChar + getTestName(true) + File.separatorChar + relativeVfsPath.replace('/', File.separatorChar);
+ final String path =
+ TEST_PATH + File.separatorChar + getTestName(true) + File.separatorChar + relativeVfsPath.replace('/', File.separatorChar);
final VirtualFile result = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path));
assertNotNull("File " + path + " doen\'t exist", result);
return result;
diff --git a/java/java-tests/testSrc/com/intellij/slicer/SliceBackwardTest.java b/java/java-tests/testSrc/com/intellij/slicer/SliceBackwardTest.java
index 30e2cce..513fcec 100644
--- a/java/java-tests/testSrc/com/intellij/slicer/SliceBackwardTest.java
+++ b/java/java-tests/testSrc/com/intellij/slicer/SliceBackwardTest.java
@@ -17,7 +17,7 @@
import com.intellij.analysis.AnalysisScope;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
@@ -133,7 +133,7 @@
}
private static void extract(final Document document, final Map<String, RangeMarker> sliceUsageName2Offset, final String name) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
for (int i = 1; i < 9; i++) {
diff --git a/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java b/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
index 3a5053f..6e34ebf 100644
--- a/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
+++ b/java/java-tests/testSrc/com/intellij/slicer/SliceTreeTest.java
@@ -146,10 +146,17 @@
public void testLeafExpressionsMoreComplex() throws Exception {
SliceTreeStructure treeStructure = configureTree("Duplicate");
SliceNode root = (SliceNode)treeStructure.getRootElement();
- Collection<PsiElement> leaves = SliceLeafAnalyzer.calcLeafExpressions(root, treeStructure, SliceLeafAnalyzer.createMap());
+ Map<SliceNode, Collection<PsiElement>> map = SliceLeafAnalyzer.createMap();
+ Collection<PsiElement> leaves = SliceLeafAnalyzer.calcLeafExpressions(root, treeStructure, map);
assertNotNull(leaves);
- assertEquals(2, leaves.size());
List<PsiElement> list = new ArrayList<PsiElement>(leaves);
+ String message = ContainerUtil.map(list, new Function<PsiElement, String>() {
+ @Override
+ public String fun(PsiElement element) {
+ return element.getClass() +": '"+element.getText()+"' ("+ SliceLeafAnalyzer.LEAF_ELEMENT_EQUALITY.computeHashCode(element)+") ";
+ }
+ }).toString();
+ assertEquals(map.entrySet()+"\n"+message, 2, leaves.size());
Collections.sort(list, new Comparator<PsiElement>() {
@Override
public int compare(PsiElement o1, PsiElement o2) {
diff --git a/java/jdkAnnotations/java/awt/annotations.xml b/java/jdkAnnotations/java/awt/annotations.xml
index b7d7584..9fbbeba 100644
--- a/java/jdkAnnotations/java/awt/annotations.xml
+++ b/java/jdkAnnotations/java/awt/annotations.xml
@@ -150,6 +150,9 @@
<val name="intValues" val="{java.awt.Label.LEFT, java.awt.Label.CENTER, java.awt.Label.RIGHT}" />
</annotation>
</item>
+ <item name='java.awt.Point Point(java.awt.Point) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.awt.Rectangle Rectangle(java.awt.Dimension) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
diff --git a/java/jdkAnnotations/java/awt/event/annotations.xml b/java/jdkAnnotations/java/awt/event/annotations.xml
index ce47d03..8808ee8 100644
--- a/java/jdkAnnotations/java/awt/event/annotations.xml
+++ b/java/jdkAnnotations/java/awt/event/annotations.xml
@@ -100,6 +100,9 @@
<val name="flagsFromClass" val="java.awt.event.InputEvent.class" />
</annotation>
</item>
+ <item name='java.awt.event.MouseEvent java.awt.Point getPoint()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.awt.event.MouseEvent java.lang.String getMouseModifiersText(int) 0">
<annotation name="org.intellij.lang.annotations.MagicConstant">
<val name="flagsFromClass" val="java.awt.event.InputEvent.class" />
diff --git a/java/jdkAnnotations/java/io/annotations.xml b/java/jdkAnnotations/java/io/annotations.xml
index df2f353..45f54e4 100644
--- a/java/jdkAnnotations/java/io/annotations.xml
+++ b/java/jdkAnnotations/java/io/annotations.xml
@@ -122,6 +122,21 @@
<item name="java.io.File java.nio.file.Path toPath()">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.io.FileInputStream FileInputStream(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileInputStream FileInputStream(java.io.FileDescriptor) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileInputStream FileInputStream(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileInputStream int read(byte[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileInputStream int read(byte[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.io.FileOutputStream FileOutputStream(java.io.File) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
@@ -149,6 +164,30 @@
<item name="java.io.FileOutputStream void write(byte[], int, int) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.io.FileReader FileReader(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileReader FileReader(java.io.FileDescriptor) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileReader FileReader(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileWriter FileWriter(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileWriter FileWriter(java.io.File, boolean) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileWriter FileWriter(java.io.FileDescriptor) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileWriter FileWriter(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.FileWriter FileWriter(java.lang.String, boolean) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.io.FilterInputStream FilterInputStream(java.io.InputStream) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
@@ -176,6 +215,36 @@
<item name="java.io.InputStream int read(byte[], int, int) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream, java.nio.charset.Charset) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream, java.nio.charset.Charset) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream, java.nio.charset.CharsetDecoder) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader InputStreamReader(java.io.InputStream, java.nio.charset.CharsetDecoder) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.InputStreamReader int read(char[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.OutputStream void write(byte[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.OutputStream void write(byte[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.io.OutputStreamWriter OutputStreamWriter(java.io.OutputStream) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
@@ -203,6 +272,117 @@
<item name="java.io.OutputStreamWriter void write(java.lang.String, int, int) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.io.PrintStream PrintStream(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.io.File, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.io.File, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.io.OutputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.io.OutputStream, boolean) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.io.OutputStream, boolean, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.io.OutputStream, boolean, java.lang.String) 2'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.lang.String, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream PrintStream(java.lang.String, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream java.io.PrintStream format(java.lang.String, java.lang.Object...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream java.io.PrintStream format(java.util.Locale, java.lang.String, java.lang.Object...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream java.io.PrintStream printf(java.lang.String, java.lang.Object...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream java.io.PrintStream printf(java.util.Locale, java.lang.String, java.lang.Object...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream void print(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream void println(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintStream void write(byte[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.File, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.File, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.OutputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.OutputStream, boolean) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.Writer) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.io.Writer, boolean) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.lang.String, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter PrintWriter(java.lang.String, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter java.io.PrintWriter format(java.lang.String, java.lang.Object...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter java.io.PrintWriter format(java.util.Locale, java.lang.String, java.lang.Object...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter java.io.PrintWriter printf(java.lang.String, java.lang.Object...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter java.io.PrintWriter printf(java.util.Locale, java.lang.String, java.lang.Object...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter void print(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter void println(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter void write(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter void write(char[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter void write(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.io.PrintWriter void write(java.lang.String, int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.io.RandomAccessFile RandomAccessFile(java.io.File, java.lang.String) 1">
<annotation name="org.jetbrains.annotations.NonNls" />
</item>
diff --git a/java/jdkAnnotations/java/lang/annotations.xml b/java/jdkAnnotations/java/lang/annotations.xml
index 50e716a..cf2eac3 100644
--- a/java/jdkAnnotations/java/lang/annotations.xml
+++ b/java/jdkAnnotations/java/lang/annotations.xml
@@ -231,6 +231,9 @@
<item name="java.lang.String java.lang.String format(java.lang.String, java.lang.Object...) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.lang.String java.lang.String format(java.util.Locale, java.lang.String, java.lang.Object...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.lang.String java.lang.String intern()">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
diff --git a/java/jdkAnnotations/java/nio/annotations.xml b/java/jdkAnnotations/java/nio/annotations.xml
index 59c7057..9076683 100644
--- a/java/jdkAnnotations/java/nio/annotations.xml
+++ b/java/jdkAnnotations/java/nio/annotations.xml
@@ -1,5 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
+ <item name='java.nio.Buffer java.lang.Object array()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer clear()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer flip()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer limit(int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer mark()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer position(int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer reset()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.Buffer java.nio.Buffer rewind()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.nio.ByteBuffer byte[] array()">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
@@ -69,8 +93,101 @@
<item name="java.nio.ByteBuffer java.nio.ShortBuffer asShortBuffer()">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.nio.CharBuffer char[] array()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.nio.CharBuffer int read(java.nio.CharBuffer) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer allocate(int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer asReadOnlyBuffer()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer compact()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer duplicate()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer get(char[])'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer get(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer get(char[], int, int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer get(char[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(char)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(char[])'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(char[], int, int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(char[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(int, char)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(java.lang.String, int, int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(java.lang.String, int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(java.nio.CharBuffer)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer put(java.nio.CharBuffer) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer slice()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(char[])'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(char[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(char[], int, int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(char[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(java.lang.CharSequence)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(java.lang.CharSequence) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(java.lang.CharSequence, int, int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.CharBuffer java.nio.CharBuffer wrap(java.lang.CharSequence, int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.HeapCharBuffer HeapCharBuffer(char[], int, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
</root>
diff --git a/java/jdkAnnotations/java/nio/channels/annotations.xml b/java/jdkAnnotations/java/nio/channels/annotations.xml
new file mode 100644
index 0000000..d0ecca8
--- /dev/null
+++ b/java/jdkAnnotations/java/nio/channels/annotations.xml
@@ -0,0 +1,75 @@
+<root>
+ <item name='java.nio.channels.Channels java.io.InputStream newInputStream(java.nio.channels.AsynchronousByteChannel) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.InputStream newInputStream(java.nio.channels.ReadableByteChannel) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.OutputStream newOutputStream(java.nio.channels.AsynchronousByteChannel) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.OutputStream newOutputStream(java.nio.channels.WritableByteChannel) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Reader newReader(java.nio.channels.ReadableByteChannel, java.nio.charset.CharsetDecoder, int) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.io.Writer newWriter(java.nio.channels.WritableByteChannel, java.nio.charset.CharsetEncoder, int) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.nio.channels.ReadableByteChannel newChannel(java.io.InputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.Channels java.nio.channels.WritableByteChannel newChannel(java.io.OutputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.channels.SelectableChannel int validOps()'>
+ <annotation name="org.intellij.lang.annotations.MagicConstant">
+ <val name="flagsFromClass" val="java.nio.channels.SelectionKey.class" />
+ </annotation>
+ </item>
+ <item name='java.nio.channels.SelectableChannel java.nio.channels.SelectionKey register(java.nio.channels.Selector, int) 1'>
+ <annotation name="org.intellij.lang.annotations.MagicConstant">
+ <val name="flagsFromClass" val="java.nio.channels.SelectionKey.class" />
+ </annotation>
+ </item>
+ <item
+ name='java.nio.channels.SelectableChannel java.nio.channels.SelectionKey register(java.nio.channels.Selector, int, java.lang.Object) 1'>
+ <annotation name="org.intellij.lang.annotations.MagicConstant">
+ <val name="flagsFromClass" val="java.nio.channels.SelectionKey.class" />
+ </annotation>
+ </item>
+ <item name='java.nio.channels.SelectionKey int interestOps()'>
+ <annotation name="org.intellij.lang.annotations.MagicConstant">
+ <val name="flagsFromClass" val="java.nio.channels.SelectionKey.class" />
+ </annotation>
+ </item>
+ <item name='java.nio.channels.SelectionKey java.nio.channels.SelectionKey interestOps(int) 0'>
+ <annotation name="org.intellij.lang.annotations.MagicConstant">
+ <val name="flagsFromClass" val="java.nio.channels.SelectionKey.class" />
+ </annotation>
+ </item>
+ <item name='java.nio.channels.SelectionKey int readyOps()'>
+ <annotation name="org.intellij.lang.annotations.MagicConstant">
+ <val name="flagsFromClass" val="java.nio.channels.SelectionKey.class" />
+ </annotation>
+ </item>
+</root>
\ No newline at end of file
diff --git a/java/jdkAnnotations/java/nio/charset/annotations.xml b/java/jdkAnnotations/java/nio/charset/annotations.xml
index e111541..b5664f8 100644
--- a/java/jdkAnnotations/java/nio/charset/annotations.xml
+++ b/java/jdkAnnotations/java/nio/charset/annotations.xml
@@ -1,5 +1,53 @@
<root>
+ <item name='java.nio.charset.Charset Charset(java.lang.String, java.lang.String[]) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset int compareTo(java.nio.charset.Charset) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.lang.String name()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.ByteBuffer encode(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.ByteBuffer encode(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.ByteBuffer encode(java.nio.CharBuffer)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.ByteBuffer encode(java.nio.CharBuffer) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.CharBuffer decode(java.nio.ByteBuffer)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.CharBuffer decode(java.nio.ByteBuffer) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.charset.Charset defaultCharset()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.Charset java.nio.charset.Charset forName(java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.nio.charset.Charset java.nio.charset.Charset forName(java.lang.String) 0'>
<annotation name='org.jetbrains.annotations.NonNls'/>
</item>
+ <item name='java.nio.charset.Charset java.util.SortedMap<java.lang.String,java.nio.charset.Charset> availableCharsets()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.CharsetDecoder java.nio.CharBuffer decode(java.nio.ByteBuffer)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.CharsetDecoder java.nio.CharBuffer decode(java.nio.ByteBuffer) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.CharsetEncoder java.nio.ByteBuffer encode(java.nio.CharBuffer)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.charset.CharsetEncoder java.nio.ByteBuffer encode(java.nio.CharBuffer) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
</root>
diff --git a/java/jdkAnnotations/java/nio/file/annotations.xml b/java/jdkAnnotations/java/nio/file/annotations.xml
new file mode 100644
index 0000000..d677cc6
--- /dev/null
+++ b/java/jdkAnnotations/java/nio/file/annotations.xml
@@ -0,0 +1,251 @@
+<root>
+ <item name='java.nio.file.Files A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files A readAttributes(java.nio.file.Path, java.lang.Class<A>, java.nio.file.LinkOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files V getFileAttributeView(java.nio.file.Path, java.lang.Class<V>, java.nio.file.LinkOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean deleteIfExists(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean exists(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isDirectory(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isExecutable(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isHidden(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isReadable(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isRegularFile(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isSameFile(java.nio.file.Path, java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isSameFile(java.nio.file.Path, java.nio.file.Path) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isSymbolicLink(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean isWritable(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files boolean notExists(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files byte[] read(java.io.InputStream, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files byte[] readAllBytes(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.io.BufferedReader newBufferedReader(java.nio.file.Path, java.nio.charset.Charset) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.io.BufferedReader newBufferedReader(java.nio.file.Path, java.nio.charset.Charset) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.io.BufferedWriter newBufferedWriter(java.nio.file.Path, java.nio.charset.Charset, java.nio.file.OpenOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.io.BufferedWriter newBufferedWriter(java.nio.file.Path, java.nio.charset.Charset, java.nio.file.OpenOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.io.InputStream newInputStream(java.nio.file.Path, java.nio.file.OpenOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.io.OutputStream newOutputStream(java.nio.file.Path, java.nio.file.OpenOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.lang.Object getAttribute(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.lang.String probeContentType(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.nio.file.OpenOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.channels.SeekableByteChannel newByteChannel(java.nio.file.Path, java.util.Set<? extends java.nio.file.OpenOption>, java.nio.file.attribute.FileAttribute<?>...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.DirectoryStream<java.nio.file.Path> newDirectoryStream(java.nio.file.Path, java.nio.file.DirectoryStream.Filter<? super java.nio.file.Path>) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.FileStore getFileStore(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path copy(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createDirectories(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createDirectory(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createFile(java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createLink(java.nio.file.Path, java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createLink(java.nio.file.Path, java.nio.file.Path) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createSymbolicLink(java.nio.file.Path, java.nio.file.Path, java.nio.file.attribute.FileAttribute<?>...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createTempDirectory(java.nio.file.Path, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path createTempFile(java.nio.file.Path, java.lang.String, java.lang.String, java.nio.file.attribute.FileAttribute<?>...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path move(java.nio.file.Path, java.nio.file.Path, java.nio.file.CopyOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path readSymbolicLink(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setAttribute(java.nio.file.Path, java.lang.String, java.lang.Object, java.nio.file.LinkOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setLastModifiedTime(java.nio.file.Path, java.nio.file.attribute.FileTime) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setOwner(java.nio.file.Path, java.nio.file.attribute.UserPrincipal) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setOwner(java.nio.file.Path, java.nio.file.attribute.UserPrincipal) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setPosixFilePermissions(java.nio.file.Path, java.util.Set<java.nio.file.attribute.PosixFilePermission>) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path setPosixFilePermissions(java.nio.file.Path, java.util.Set<java.nio.file.attribute.PosixFilePermission>) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor<? super java.nio.file.Path>) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path walkFileTree(java.nio.file.Path, java.nio.file.FileVisitor<? super java.nio.file.Path>) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path walkFileTree(java.nio.file.Path, java.util.Set<java.nio.file.FileVisitOption>, int, java.nio.file.FileVisitor<? super java.nio.file.Path>) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path walkFileTree(java.nio.file.Path, java.util.Set<java.nio.file.FileVisitOption>, int, java.nio.file.FileVisitor<? super java.nio.file.Path>) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path walkFileTree(java.nio.file.Path, java.util.Set<java.nio.file.FileVisitOption>, int, java.nio.file.FileVisitor<? super java.nio.file.Path>) 3'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path write(java.nio.file.Path, byte[], java.nio.file.OpenOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path write(java.nio.file.Path, byte[], java.nio.file.OpenOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path write(java.nio.file.Path, java.lang.Iterable<? extends java.lang.CharSequence>, java.nio.charset.Charset, java.nio.file.OpenOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.Path write(java.nio.file.Path, java.lang.Iterable<? extends java.lang.CharSequence>, java.nio.charset.Charset, java.nio.file.OpenOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.attribute.FileTime getLastModifiedTime(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.nio.file.attribute.UserPrincipal getOwner(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.util.List<java.lang.String> readAllLines(java.nio.file.Path, java.nio.charset.Charset) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.util.Map<java.lang.String,java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.util.Map<java.lang.String,java.lang.Object> readAttributes(java.nio.file.Path, java.lang.String, java.nio.file.LinkOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files java.util.Set<java.nio.file.attribute.PosixFilePermission> getPosixFilePermissions(java.nio.file.Path, java.nio.file.LinkOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long copy(java.io.InputStream, java.io.OutputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long copy(java.io.InputStream, java.io.OutputStream) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long copy(java.io.InputStream, java.nio.file.Path, java.nio.file.CopyOption...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long copy(java.io.InputStream, java.nio.file.Path, java.nio.file.CopyOption...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long copy(java.nio.file.Path, java.io.OutputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long copy(java.nio.file.Path, java.io.OutputStream) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files long size(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Files void delete(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Paths java.nio.file.Path get(java.lang.String, java.lang.String...) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.nio.file.Paths java.nio.file.Path get(java.net.URI) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+</root>
\ No newline at end of file
diff --git a/java/jdkAnnotations/java/util/annotations.xml b/java/jdkAnnotations/java/util/annotations.xml
index 88ec995..330f7a4 100644
--- a/java/jdkAnnotations/java/util/annotations.xml
+++ b/java/jdkAnnotations/java/util/annotations.xml
@@ -10,6 +10,15 @@
<val name="targetIsContainer" val="true"/>
</annotation>
</item>
+ <item name='java.util.ArrayList java.util.Iterator<E> iterator()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ArrayList java.util.ListIterator<E> listIterator()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ArrayList java.util.ListIterator<E> listIterator(int)'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.util.Arrays T[] copyOf(T[], int)">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
@@ -872,9 +881,60 @@
<item name="java.util.Deque java.util.Iterator<E> descendingIterator()">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.util.Formatter Formatter(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.File, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.File, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.File, java.lang.String, java.util.Locale) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.File, java.lang.String, java.util.Locale) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.OutputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.OutputStream, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.OutputStream, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.OutputStream, java.lang.String, java.util.Locale) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.OutputStream, java.lang.String, java.util.Locale) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.io.PrintStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.lang.String, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.lang.String, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.lang.String, java.lang.String, java.util.Locale) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Formatter Formatter(java.lang.String, java.lang.String, java.util.Locale) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="java.util.Formatter java.util.Formatter format(java.lang.String, java.lang.Object...) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.util.Formatter java.util.Formatter format(java.util.Locale, java.lang.String, java.lang.Object...) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.util.HashSet HashSet(java.util.Collection<? extends E>) 0'>
<annotation name='org.jetbrains.annotations.NotNull'/>
<annotation name='org.intellij.lang.annotations.Flow'>
@@ -1047,6 +1107,176 @@
<item name="java.util.NavigableSet java.util.NavigableSet<E> tailSet(E, boolean)">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='java.util.Objects T requireNonNull(T)'>
+ <annotation name='org.jetbrains.annotations.Contract'>
+ <val val=""null->fail""/>
+ </annotation>
+ </item>
+ <item name='java.util.Objects T requireNonNull(T, java.lang.String)'>
+ <annotation name='org.jetbrains.annotations.Contract'>
+ <val val=""null,_->fail""/>
+ </annotation>
+ </item>
+ <item name='java.util.ResourceBundle boolean containsKey(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.lang.Object getObject(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.lang.Object handleGetObject(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.lang.String getString(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.lang.String[] getStringArray(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.Enumeration<java.lang.String> getKeys()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader) 2'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader, java.util.ResourceBundle.Control) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader, java.util.ResourceBundle.Control) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader, java.util.ResourceBundle.Control) 2'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader, java.util.ResourceBundle.Control) 3'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.util.ResourceBundle.Control) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.util.ResourceBundle.Control) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item
+ name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.Locale, java.util.ResourceBundle.Control) 2'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.ResourceBundle.Control) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.ResourceBundle getBundle(java.lang.String, java.util.ResourceBundle.Control) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.Set<java.lang.String> handleKeySet()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle java.util.Set<java.lang.String> keySet()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.ResourceBundle void clearCache(java.lang.ClassLoader) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.io.File) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.io.File, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.io.File, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.io.InputStream) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.io.InputStream, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.io.InputStream, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.lang.Readable) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.nio.channels.ReadableByteChannel) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.nio.channels.ReadableByteChannel, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.nio.channels.ReadableByteChannel, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.nio.file.Path) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.nio.file.Path, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner Scanner(java.nio.file.Path, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner boolean hasNext(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner boolean hasNext(java.util.regex.Pattern) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.lang.String findInLine(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.lang.String findInLine(java.util.regex.Pattern) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.lang.String findWithinHorizon(java.lang.String, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.lang.String findWithinHorizon(java.util.regex.Pattern, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.lang.String next(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.lang.String next(java.util.regex.Pattern) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.util.Scanner skip(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.util.Scanner skip(java.util.regex.Pattern) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.util.Scanner useDelimiter(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.util.Scanner useDelimiter(java.util.regex.Pattern) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='java.util.Scanner java.util.Scanner useLocale(java.util.Locale) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name='java.util.Set T[] toArray(T[])'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
diff --git a/java/jdkAnnotations/javax/swing/tree/annotations.xml b/java/jdkAnnotations/javax/swing/tree/annotations.xml
index 055cc92..2728e61 100644
--- a/java/jdkAnnotations/javax/swing/tree/annotations.xml
+++ b/java/jdkAnnotations/javax/swing/tree/annotations.xml
@@ -12,6 +12,9 @@
<item name="javax.swing.tree.TreePath TreePath(javax.swing.tree.TreePath, java.lang.Object) 1">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='javax.swing.tree.TreePath java.lang.Object[] getPath()'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="javax.swing.tree.TreePath javax.swing.tree.TreePath pathByAddingChild(java.lang.Object) 0">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
diff --git a/java/jdkAnnotations/org/jdom/annotations.xml b/java/jdkAnnotations/org/jdom/annotations.xml
index 2354f1f..7cd091a 100644
--- a/java/jdkAnnotations/org/jdom/annotations.xml
+++ b/java/jdkAnnotations/org/jdom/annotations.xml
@@ -1,5 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<root>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String, int) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String, int) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String, int, org.jdom.Namespace) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String, int, org.jdom.Namespace) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String, org.jdom.Namespace) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute Attribute(java.lang.String, java.lang.String, org.jdom.Namespace) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute org.jdom.Attribute setName(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Attribute org.jdom.Attribute setValue(java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
<item name="org.jdom.Element Element(java.lang.String) 0">
<annotation name="org.jetbrains.annotations.NonNls" />
</item>
@@ -12,5 +42,20 @@
<item name="org.jdom.Element java.util.List getChildren(java.lang.String, org.jdom.Namespace)">
<annotation name="org.jetbrains.annotations.NotNull" />
</item>
+ <item name='org.jdom.Element org.jdom.Element setAttribute(java.lang.String, java.lang.String) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Element org.jdom.Element setAttribute(java.lang.String, java.lang.String) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Element org.jdom.Element setAttribute(java.lang.String, java.lang.String, org.jdom.Namespace) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Element org.jdom.Element setAttribute(java.lang.String, java.lang.String, org.jdom.Namespace) 1'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
+ <item name='org.jdom.Element org.jdom.Element setAttribute(org.jdom.Attribute) 0'>
+ <annotation name='org.jetbrains.annotations.NotNull'/>
+ </item>
</root>
diff --git a/java/jsp-openapi/src/com/intellij/psi/impl/source/jsp/jspJava/JspxImportStatement.java b/java/jsp-openapi/src/com/intellij/psi/impl/source/jsp/jspJava/JspxImportStatement.java
index a5f4c6f..dba00d1 100644
--- a/java/jsp-openapi/src/com/intellij/psi/impl/source/jsp/jspJava/JspxImportStatement.java
+++ b/java/jsp-openapi/src/com/intellij/psi/impl/source/jsp/jspJava/JspxImportStatement.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.
@@ -22,6 +22,5 @@
* @author peter
*/
public interface JspxImportStatement extends PsiImportStatement {
- boolean isForeignFileImport();
PsiFile getDeclarationFile();
}
diff --git a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java
index 4d5fe2c..7b9ba1d 100644
--- a/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java
+++ b/java/manifest/src/org/jetbrains/lang/manifest/ManifestBundle.java
@@ -16,18 +16,19 @@
package org.jetbrains.lang.manifest;
import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class ManifestBundle extends AbstractBundle {
- public static final String PATH_TO_BUNDLE = "org.jetbrains.lang.manifest.ManifestBundle";
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return BUNDLE.getMessage(key, params);
+ }
+
+ public static final String PATH_TO_BUNDLE = "org.jetbrains.lang.manifest.ManifestBundle";
private static final ManifestBundle BUNDLE = new ManifestBundle();
private ManifestBundle() {
super(PATH_TO_BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
- return BUNDLE.getMessage(key, params);
- }
}
diff --git a/java/mockJDK-1.7/jre/lib/annotations.jar b/java/mockJDK-1.7/jre/lib/annotations.jar
index 72aa54c..22b47ab 100644
--- a/java/mockJDK-1.7/jre/lib/annotations.jar
+++ b/java/mockJDK-1.7/jre/lib/annotations.jar
Binary files differ
diff --git a/java/openapi/src/com/intellij/codeInspection/BaseJavaLocalInspectionTool.java b/java/openapi/src/com/intellij/codeInspection/BaseJavaLocalInspectionTool.java
index 129dc58..201084a 100644
--- a/java/openapi/src/com/intellij/codeInspection/BaseJavaLocalInspectionTool.java
+++ b/java/openapi/src/com/intellij/codeInspection/BaseJavaLocalInspectionTool.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -27,11 +27,19 @@
* lie under corresponding first parameter of one method.
*
* @see GlobalInspectionTool
+ *
+ * Please note that if your inspection/fixes/suppressions don't need UI components (e.g. Editor) to run, consider using
+ * {@link BaseJavaBatchLocalInspectionTool} instead.
*/
public abstract class BaseJavaLocalInspectionTool extends AbstractBaseJavaLocalInspectionTool implements CustomSuppressableInspectionTool {
@Override
public SuppressIntentionAction[] getSuppressActions(final PsiElement element) {
- return SuppressManager.getInstance().createSuppressActions(HighlightDisplayKey.find(getShortName()));
+ String shortName = getShortName();
+ HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
+ if (key == null) {
+ throw new AssertionError("HighlightDisplayKey.find(" + shortName + ") is null. Inspection: "+getClass());
+ }
+ return SuppressManager.getInstance().createSuppressActions(key);
}
@Override
diff --git a/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java b/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java
new file mode 100644
index 0000000..e0ffc7f
--- /dev/null
+++ b/java/openapi/src/com/intellij/execution/filters/ExceptionInfoCache.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.execution.filters;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.reference.SoftReference;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author peter
+ */
+public class ExceptionInfoCache {
+ private final ConcurrentMap<String, SoftReference<Pair<PsiClass[], PsiFile[]>>> myCache = ContainerUtil.newConcurrentMap();
+ private final Project myProject;
+ private final GlobalSearchScope mySearchScope;
+
+ public ExceptionInfoCache(GlobalSearchScope searchScope) {
+ myProject = ObjectUtils.assertNotNull(searchScope.getProject());
+ mySearchScope = searchScope;
+ }
+
+ @NotNull public Project getProject() {
+ return myProject;
+ }
+
+ @NotNull
+ private PsiClass[] findClassesPreferringMyScope(String className) {
+ JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
+ PsiClass[] result = psiFacade.findClasses(className, mySearchScope);
+ return result.length != 0 ? result : psiFacade.findClasses(className, GlobalSearchScope.allScope(myProject));
+ }
+
+ Pair<PsiClass[], PsiFile[]> resolveClass(String className) {
+ Pair<PsiClass[], PsiFile[]> cached = SoftReference.dereference(myCache.get(className));
+ if (cached != null) {
+ return cached;
+ }
+
+ PsiClass[] classes = findClassesPreferringMyScope(className);
+ if (classes.length == 0) {
+ final int dollarIndex = className.indexOf('$');
+ if (dollarIndex >= 0) {
+ classes = findClassesPreferringMyScope(className.substring(0, dollarIndex));
+ }
+ }
+
+ PsiFile[] files = new PsiFile[classes.length];
+ for (int i = 0; i < classes.length; i++) {
+ files[i] = (PsiFile)classes[i].getContainingFile().getNavigationElement();
+ }
+
+ Pair<PsiClass[], PsiFile[]> result = Pair.create(classes, files);
+ myCache.put(className, new SoftReference<Pair<PsiClass[], PsiFile[]>>(result));
+ return result;
+ }
+
+}
diff --git a/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java b/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java
index 3fcd9c9..c89be37 100644
--- a/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java
+++ b/java/openapi/src/com/intellij/execution/filters/ExceptionWorker.java
@@ -15,26 +15,28 @@
*/
package com.intellij.execution.filters;
-import com.intellij.openapi.application.AccessToken;
-import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.Trinity;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.search.PsiShortNamesCache;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
+import java.util.ArrayList;
+import java.util.List;
/**
* User: Irina.Chernushina
@@ -59,16 +61,16 @@
}
private final Project myProject;
- private final GlobalSearchScope mySearchScope;
private Filter.Result myResult;
- private PsiClass myClass;
- private PsiFile myFile;
+ private PsiClass[] myClasses = PsiClass.EMPTY_ARRAY;
+ private PsiFile[] myFiles = PsiFile.EMPTY_ARRAY;
private String myMethod;
private Trinity<TextRange, TextRange, TextRange> myInfo;
+ private final ExceptionInfoCache myCache;
- public ExceptionWorker(@NotNull Project project, @NotNull GlobalSearchScope searchScope) {
- myProject = project;
- mySearchScope = searchScope;
+ public ExceptionWorker(@NotNull ExceptionInfoCache cache) {
+ myProject = cache.getProject();
+ myCache = cache;
}
public void execute(final String line, final int textEndOffset) {
@@ -90,16 +92,15 @@
final String lineString = fileAndLine.substring(colonIndex + 1);
try {
final int lineNumber = Integer.parseInt(lineString);
- myClass = findPositionClass(line);
- myFile = myClass == null ? null : (PsiFile)myClass.getContainingFile().getNavigationElement();
- if (myFile == null) {
+ Pair<PsiClass[], PsiFile[]> pair = myCache.resolveClass(myInfo.first.substring(line).trim());
+ myClasses = pair.first;
+ myFiles = pair.second;
+ if (myFiles.length == 0) {
// try find the file with the required name
- PsiFile[] files = PsiShortNamesCache.getInstance(myProject).getFilesByName(fileAndLine.substring(0, colonIndex).trim());
- if (files.length > 0) {
- myFile = files[0];
- }
+ //todo[nik] it would be better to use FilenameIndex here to honor the scope by it isn't accessible in Open API
+ myFiles = PsiShortNamesCache.getInstance(myProject).getFilesByName(fileAndLine.substring(0, colonIndex).trim());
}
- if (myFile == null) return;
+ if (myFiles.length == 0) return;
/*
IDEADEV-4976: Some scramblers put something like SourceFile mock instead of real class name.
@@ -113,12 +114,31 @@
final int highlightStartOffset = textStartOffset + lparenthIndex + 1;
final int highlightEndOffset = textStartOffset + rparenthIndex;
- final VirtualFile virtualFile = myFile.getVirtualFile();
- HyperlinkInfo linkInfo = new MyHyperlinkInfo(myProject, virtualFile, lineNumber);
+ ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
+ List<VirtualFile> virtualFilesInLibraries = new ArrayList<VirtualFile>();
+ List<VirtualFile> virtualFilesInContent = new ArrayList<VirtualFile>();
+ for (PsiFile file : myFiles) {
+ VirtualFile virtualFile = file.getVirtualFile();
+ if (index.isInContent(virtualFile)) {
+ virtualFilesInContent.add(virtualFile);
+ }
+ else {
+ virtualFilesInLibraries.add(virtualFile);
+ }
+ }
- boolean inContent = ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(virtualFile);
- TextAttributes attributes = inContent ? HYPERLINK_ATTRIBUTES : LIBRARY_HYPERLINK_ATTRIBUTES;
+ List<VirtualFile> virtualFiles;
+ TextAttributes attributes;
+ if (virtualFilesInContent.isEmpty()) {
+ attributes = LIBRARY_HYPERLINK_ATTRIBUTES;
+ virtualFiles = virtualFilesInLibraries;
+ }
+ else {
+ attributes = HYPERLINK_ATTRIBUTES;
+ virtualFiles = virtualFilesInContent;
+ }
+ HyperlinkInfo linkInfo = HyperlinkInfoFactory.getInstance().createMultipleFilesHyperlinkInfo(virtualFiles, lineNumber - 1, myProject);
myResult = new Filter.Result(highlightStartOffset, highlightEndOffset, linkInfo, attributes);
}
catch (NumberFormatException e) {
@@ -126,30 +146,12 @@
}
}
- private PsiClass findPositionClass(String line) {
- String className = myInfo.first.substring(line).trim();
- PsiClass result = findClassPreferringMyScope(className);
- if (result == null) {
- final int dollarIndex = className.indexOf('$');
- if (dollarIndex >= 0) {
- result = findClassPreferringMyScope(className.substring(0, dollarIndex));
- }
- }
- return result;
- }
-
- private PsiClass findClassPreferringMyScope(String className) {
- JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
- PsiClass result = psiFacade.findClass(className, mySearchScope);
- return result != null ? result : psiFacade.findClass(className, GlobalSearchScope.allScope(myProject));
- }
-
public Filter.Result getResult() {
return myResult;
}
public PsiClass getPsiClass() {
- return myClass;
+ return ArrayUtil.getFirstElement(myClasses);
}
public String getMethod() {
@@ -157,7 +159,7 @@
}
public PsiFile getFile() {
- return myFile;
+ return ArrayUtil.getFirstElement(myFiles);
}
public Trinity<TextRange, TextRange, TextRange> getInfo() {
@@ -182,18 +184,18 @@
}
}
- final int lparenIdx = line.indexOf('(', startIdx);
- if (lparenIdx < 0) return null;
- final int dotIdx = line.lastIndexOf('.', lparenIdx);
+ final int lParenIdx = line.indexOf('(', startIdx);
+ if (lParenIdx < 0) return null;
+ final int dotIdx = line.lastIndexOf('.', lParenIdx);
if (dotIdx < 0 || dotIdx < startIdx) return null;
- final int rparenIdx = line.indexOf(')', lparenIdx);
- if (rparenIdx < 0) return null;
+ final int rParenIdx = line.indexOf(')', lParenIdx);
+ if (rParenIdx < 0) return null;
// class, method, link
return Trinity.create(new TextRange(startIdx + 1 + (startIdx >= 0 ? AT.length() : 0), handleSpaces(line, dotIdx, -1, true)),
- new TextRange(handleSpaces(line, dotIdx + 1, 1, true), handleSpaces(line, lparenIdx + 1, -1, true)),
- new TextRange(lparenIdx, rparenIdx));
+ new TextRange(handleSpaces(line, dotIdx + 1, 1, true), handleSpaces(line, lParenIdx + 1, -1, true)),
+ new TextRange(lParenIdx, rParenIdx));
}
private static int handleSpaces(String line, int pos, int delta, boolean skip) {
@@ -205,59 +207,4 @@
}
return pos;
}
-
- @Nullable
- static OpenFileHyperlinkInfo getOpenFileHyperlinkInfo(Filter.Result result) {
- if (result.hyperlinkInfo instanceof MyHyperlinkInfo) {
- MyHyperlinkInfo info = (MyHyperlinkInfo)result.hyperlinkInfo;
- return new OpenFileHyperlinkInfo(info.myProject, info.myVirtualFile, info.myLineNumber);
- }
- return null;
- }
-
- private static class MyHyperlinkInfo implements FileHyperlinkInfo {
- private final VirtualFile myVirtualFile;
- private final int myLineNumber;
- private final Project myProject;
-
- public MyHyperlinkInfo(@NotNull Project project, @NotNull VirtualFile virtualFile, int lineNumber) {
- myProject = project;
- myVirtualFile = virtualFile;
- myLineNumber = lineNumber;
- }
-
- @Override
- public void navigate(Project project) {
- VirtualFile currentVirtualFile = null;
-
- AccessToken accessToken = ReadAction.start();
-
- try {
- if (!myVirtualFile.isValid()) return;
-
- PsiFile psiFile = PsiManager.getInstance(project).findFile(myVirtualFile);
- if (psiFile != null) {
- PsiElement navigationElement = psiFile.getNavigationElement(); // Sources may be downloaded.
- if (navigationElement instanceof PsiFile) {
- currentVirtualFile = ((PsiFile)navigationElement).getVirtualFile();
- }
- }
-
- if (currentVirtualFile == null) {
- currentVirtualFile = myVirtualFile;
- }
- }
- finally {
- accessToken.finish();
- }
-
- new OpenFileHyperlinkInfo(myProject, currentVirtualFile, myLineNumber - 1).navigate(project);
- }
-
- @Nullable
- @Override
- public OpenFileDescriptor getDescriptor() {
- return new OpenFileDescriptor(myProject, myVirtualFile, myLineNumber - 1, 0);
- }
- }
}
diff --git a/java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java b/java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java
index 3184488..655dc95 100644
--- a/java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java
+++ b/java/openapi/src/com/intellij/ide/util/projectWizard/JavaModuleBuilder.java
@@ -27,7 +27,6 @@
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
-import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -90,11 +89,6 @@
return StdModuleTypes.JAVA.modifySettingsStep(settingsStep, this);
}
- @Override
- public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
- return getModuleType().createWizardSteps(wizardContext, this, modulesProvider);
- }
-
public void setupRootModel(ModifiableRootModel rootModel) throws ConfigurationException {
final CompilerModuleExtension compilerModuleExtension = rootModel.getModuleExtension(CompilerModuleExtension.class);
compilerModuleExtension.setExcludeOutput(true);
diff --git a/java/openapi/src/com/intellij/pom/java/PomJavaAspect.java b/java/openapi/src/com/intellij/pom/java/PomJavaAspect.java
deleted file mode 100644
index 36e5eaf..0000000
--- a/java/openapi/src/com/intellij/pom/java/PomJavaAspect.java
+++ /dev/null
@@ -1,32 +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.pom.java;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.pom.PomModel;
-import com.intellij.pom.PomModelAspect;
-
-public abstract class PomJavaAspect implements PomModelAspect {
- public static PomJavaAspect getInstance(Project project) {
- return project.getComponent(PomJavaAspect.class);
- }
-
- public static PomJavaAspect getInstance(PomModel model) {
- return model.getModelAspect(PomJavaAspect.class);
- }
-
- public abstract LanguageLevel getLanguageLevel();
-}
\ No newline at end of file
diff --git a/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java b/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java
deleted file mode 100644
index 3ae8f6e..0000000
--- a/java/openapi/src/com/intellij/pom/java/events/PomJavaAspectChangeSet.java
+++ /dev/null
@@ -1,39 +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.pom.java.events;
-
-import com.intellij.pom.PomModel;
-import com.intellij.pom.PomModelAspect;
-import com.intellij.pom.event.PomChangeSet;
-import com.intellij.pom.java.PomJavaAspect;
-import org.jetbrains.annotations.NotNull;
-
-public class PomJavaAspectChangeSet implements PomChangeSet{
- private final PomModel myModel;
-
- public PomJavaAspectChangeSet(PomModel model) {
- myModel = model;
- }
-
- @NotNull
- public PomModelAspect getAspect() {
- return myModel.getModelAspect(PomJavaAspect.class);
- }
-
- public void merge(@NotNull PomChangeSet blocked) {
- }
-}
diff --git a/java/openapi/src/com/intellij/ui/classFilter/ClassFilterEditor.java b/java/openapi/src/com/intellij/ui/classFilter/ClassFilterEditor.java
index 85d92f5..2867bb1 100644
--- a/java/openapi/src/com/intellij/ui/classFilter/ClassFilterEditor.java
+++ b/java/openapi/src/com/intellij/ui/classFilter/ClassFilterEditor.java
@@ -53,6 +53,7 @@
private final ClassFilter myChooserFilter;
@Nullable
private final String myPatternsHelpId;
+ private String classDelimiter = "$";
public ClassFilterEditor(Project project) {
this(project, null);
@@ -116,9 +117,7 @@
TableColumnModel columnModel = myTable.getColumnModel();
TableColumn column = columnModel.getColumn(FilterTableModel.CHECK_MARK);
- int width = new JCheckBox().getPreferredSize().width;
- column.setPreferredWidth(width);
- column.setMaxWidth(width);
+ TableUtil.setupCheckboxColumn(column);
column.setCellRenderer(new EnabledCellRenderer(myTable.getDefaultRenderer(Boolean.class)));
columnModel.getColumn(FilterTableModel.FILTER).setCellRenderer(new FilterCellRenderer());
@@ -330,18 +329,22 @@
}
@Nullable
- private static String getJvmClassName(PsiClass aClass) {
+ private String getJvmClassName(PsiClass aClass) {
PsiClass parentClass = PsiTreeUtil.getParentOfType(aClass, PsiClass.class, true);
if (parentClass != null) {
final String parentName = getJvmClassName(parentClass);
if (parentName == null) {
return null;
}
- return parentName + "$" + aClass.getName();
+ return parentName + classDelimiter + aClass.getName();
}
return aClass.getQualifiedName();
}
+ public void setClassDelimiter(String classDelimiter) {
+ this.classDelimiter = classDelimiter;
+ }
+
public void addPattern(String pattern) {
com.intellij.ui.classFilter.ClassFilter filter = createFilter(pattern);
myTableModel.addRow(filter);
diff --git a/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java b/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java
index 3c81020..c6e03c9 100644
--- a/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java
+++ b/java/openapi/src/com/intellij/util/xml/ClassMappingNameConverter.java
@@ -52,7 +52,7 @@
if (classElement == null) return Collections.emptyList();
Object value = ((GenericDomValue)classElement).getValue();
if (value == null) return Collections.emptyList();
- assert value instanceof PsiClass : classElement + " should have PsiClass type";
+ assert value instanceof PsiClass : classElement + " should have PsiClass type, but was " + value;
PsiClass psiClass = (PsiClass)value;
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(context.getProject());
diff --git a/java/remote-servers/api/src/com/intellij/remoteServer/configuration/deployment/JavaDeploymentSourceUtil.java b/java/remote-servers/api/src/com/intellij/remoteServer/configuration/deployment/JavaDeploymentSourceUtil.java
index d096d8e..77ad3c7 100644
--- a/java/remote-servers/api/src/com/intellij/remoteServer/configuration/deployment/JavaDeploymentSourceUtil.java
+++ b/java/remote-servers/api/src/com/intellij/remoteServer/configuration/deployment/JavaDeploymentSourceUtil.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactPointer;
+import com.intellij.packaging.artifacts.ArtifactType;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@@ -38,4 +39,7 @@
@NotNull
public abstract List<DeploymentSource> createArtifactDeploymentSources(@NotNull Project project,
@NotNull Collection<? extends Artifact> artifacts);
+
+ @NotNull
+ public abstract List<DeploymentSource> createArtifactDeploymentSources(Project project, ArtifactType... artifactTypes);
}
diff --git a/java/remote-servers/impl/remote-servers-java-impl.iml b/java/remote-servers/impl/remote-servers-java-impl.iml
index c98f909..b0228d7 100644
--- a/java/remote-servers/impl/remote-servers-java-impl.iml
+++ b/java/remote-servers/impl/remote-servers-java-impl.iml
@@ -12,7 +12,7 @@
<orderEntry type="module" module-name="debugger-impl" />
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="lang-impl" />
- <orderEntry type="module" module-name="remote-servers-impl" scope="RUNTIME" />
+ <orderEntry type="module" module-name="remote-servers-impl" />
</component>
</module>
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/JavaDeploymentSourceUtilImpl.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/JavaDeploymentSourceUtilImpl.java
index 25f2229..6801248 100644
--- a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/JavaDeploymentSourceUtilImpl.java
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/JavaDeploymentSourceUtilImpl.java
@@ -16,17 +16,14 @@
package com.intellij.remoteServer.impl.configuration.deployment;
import com.intellij.openapi.project.Project;
-import com.intellij.packaging.artifacts.Artifact;
-import com.intellij.packaging.artifacts.ArtifactPointer;
-import com.intellij.packaging.artifacts.ArtifactPointerManager;
+import com.intellij.packaging.artifacts.*;
import com.intellij.remoteServer.configuration.deployment.ArtifactDeploymentSource;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
import com.intellij.remoteServer.configuration.deployment.JavaDeploymentSourceUtil;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
/**
* @author nik
@@ -49,4 +46,19 @@
}
return sources;
}
+
+ @NotNull
+ @Override
+ public List<DeploymentSource> createArtifactDeploymentSources(Project project, ArtifactType... artifactTypes) {
+ if (project.isDefault()) return Collections.emptyList();
+ Artifact[] artifacts = ArtifactManager.getInstance(project).getArtifacts();
+ List<Artifact> supportedArtifacts = new ArrayList<Artifact>();
+ Set<ArtifactType> typeSet = ContainerUtil.set(artifactTypes);
+ for (Artifact artifact : artifacts) {
+ if (typeSet.contains(artifact.getArtifactType())) {
+ supportedArtifacts.add(artifact);
+ }
+ }
+ return createArtifactDeploymentSources(project, supportedArtifacts);
+ }
}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/ArtifactDeploymentRuntimeProviderBase.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/ArtifactDeploymentRuntimeProviderBase.java
new file mode 100644
index 0000000..2773672
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/ArtifactDeploymentRuntimeProviderBase.java
@@ -0,0 +1,61 @@
+/*
+ * 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.remoteServer.impl.util;
+
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.remoteServer.configuration.deployment.ArtifactDeploymentSource;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+import com.intellij.remoteServer.util.*;
+
+import java.io.File;
+
+/**
+ * @author michael.golubev
+ */
+public abstract class ArtifactDeploymentRuntimeProviderBase implements CloudDeploymentRuntimeProvider {
+
+ @Override
+ public CloudDeploymentRuntime createDeploymentRuntime(DeploymentSource source,
+ CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager)
+ throws ServerRuntimeException {
+ if (!(source instanceof ArtifactDeploymentSource)) {
+ return null;
+ }
+
+ ArtifactDeploymentSource artifactSource = (ArtifactDeploymentSource)source;
+ Artifact artifact = artifactSource.getArtifact();
+ if (artifact == null) {
+ throw new ServerRuntimeException("Artifact not found " + artifactSource.getArtifactPointer().getArtifactName());
+ }
+
+ String artifactPath = artifact.getOutputFilePath();
+ if (artifactPath == null) {
+ throw new ServerRuntimeException("Artifact output not found");
+ }
+
+ return doCreateDeploymentRuntime(artifactSource, new File(artifactPath), serverRuntime, deploymentTask, logManager);
+ }
+
+ protected abstract CloudDeploymentRuntime doCreateDeploymentRuntime(ArtifactDeploymentSource artifactSource,
+ File artifactFile,
+ CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager) throws ServerRuntimeException;
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/RepositoryArtifactDeploymentRuntimeProviderBase.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/RepositoryArtifactDeploymentRuntimeProviderBase.java
new file mode 100644
index 0000000..2a276d6
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/RepositoryArtifactDeploymentRuntimeProviderBase.java
@@ -0,0 +1,67 @@
+/*
+ * 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.remoteServer.impl.util;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.remoteServer.configuration.deployment.ArtifactDeploymentSource;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+import com.intellij.remoteServer.util.CloudMultiSourceServerRuntimeInstance;
+import com.intellij.remoteServer.util.CloudDeploymentNameConfiguration;
+import com.intellij.remoteServer.util.CloudDeploymentRuntime;
+import com.intellij.remoteServer.util.ServerRuntimeException;
+
+import java.io.File;
+
+/**
+ * @author michael.golubev
+ */
+public abstract class RepositoryArtifactDeploymentRuntimeProviderBase extends ArtifactDeploymentRuntimeProviderBase {
+
+ @Override
+ protected CloudDeploymentRuntime doCreateDeploymentRuntime(ArtifactDeploymentSource artifactSource,
+ File artifactFile,
+ CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager) throws ServerRuntimeException {
+ RepositoryDeploymentConfiguration config = (RepositoryDeploymentConfiguration)deploymentTask.getConfiguration();
+
+ String repositoryPath = config.getRepositoryPath();
+ File repositoryRootFile;
+ if (StringUtil.isEmpty(repositoryPath)) {
+ File repositoryParentFolder = new File(PathManager.getSystemPath(), "cloud-git-artifact-deploy");
+ repositoryRootFile = FileUtil.findSequentNonexistentFile(repositoryParentFolder, artifactFile.getName(), "");
+ }
+ else {
+ repositoryRootFile = new File(repositoryPath);
+ }
+
+ if (!FileUtil.createDirectory(repositoryRootFile)) {
+ throw new ServerRuntimeException("Unable to create deploy folder: " + repositoryRootFile);
+ }
+ config.setRepositoryPath(repositoryRootFile.getAbsolutePath());
+ return doCreateDeploymentRuntime(artifactSource, artifactFile, serverRuntime, deploymentTask, logManager, repositoryRootFile);
+ }
+
+ protected abstract CloudDeploymentRuntime doCreateDeploymentRuntime(ArtifactDeploymentSource artifactSource,
+ File artifactFile,
+ CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager,
+ File repositoryRootFile) throws ServerRuntimeException;
+}
diff --git a/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/RepositoryDeploymentConfiguration.java b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/RepositoryDeploymentConfiguration.java
new file mode 100644
index 0000000..c164a0c
--- /dev/null
+++ b/java/remote-servers/impl/src/com/intellij/remoteServer/impl/util/RepositoryDeploymentConfiguration.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.remoteServer.impl.util;
+
+/**
+ * @author michael.golubev
+ */
+public interface RepositoryDeploymentConfiguration {
+
+ String getRepositoryPath();
+
+ void setRepositoryPath(String repositoryPath);
+}
diff --git a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
index add2b67..aecd3d6 100644
--- a/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/CodeInsightTestCase.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,7 +21,6 @@
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
-import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.undo.UndoManager;
@@ -40,21 +39,17 @@
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.util.Segment;
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.VfsUtil;
-import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.*;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPackage;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.search.ProjectScope;
-import com.intellij.testFramework.PsiTestCase;
-import com.intellij.testFramework.PsiTestData;
-import com.intellij.testFramework.PsiTestUtil;
-import com.intellij.testFramework.VfsTestUtil;
+import com.intellij.testFramework.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -68,6 +63,7 @@
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
/**
* @author Mike
@@ -75,7 +71,7 @@
public abstract class CodeInsightTestCase extends PsiTestCase {
protected Editor myEditor;
- protected Editor createEditor(VirtualFile file) {
+ protected Editor createEditor(@NotNull VirtualFile file) {
final FileEditorManager instance = FileEditorManager.getInstance(myProject);
if (file.getFileType().isBinary()) return null;
@@ -101,10 +97,6 @@
return new CodeInsightTestData();
}
- public static final String CARET_MARKER = "<caret>";
- @NonNls public static final String SELECTION_START_MARKER = "<selection>";
- @NonNls public static final String SELECTION_END_MARKER = "</selection>";
-
protected void configureByFile(@NonNls String filePath) throws Exception {
configureByFile(filePath, null);
}
@@ -112,7 +104,7 @@
/**
* @param files the first file will be loaded in editor
*/
- protected VirtualFile configureByFiles(@Nullable String projectRoot,String... files) throws Exception {
+ protected VirtualFile configureByFiles(@Nullable String projectRoot, @NotNull String... files) throws Exception {
if (files.length == 0) return null;
final VirtualFile[] vFiles = new VirtualFile[files.length];
for (int i = 0; i < files.length; i++) {
@@ -128,7 +120,7 @@
return configureByFiles(projectFile, vFiles);
}
- protected VirtualFile configureByFile(@NonNls String filePath, String projectRoot) throws Exception {
+ protected VirtualFile configureByFile(@NonNls String filePath, @Nullable String projectRoot) throws Exception {
String fullPath = getTestDataPath() + filePath;
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/'));
@@ -139,11 +131,11 @@
return configureByFile(vFile, projectFile);
}
- protected PsiFile configureByText(@NotNull FileType fileType, @NonNls final String text) {
+ protected PsiFile configureByText(@NotNull FileType fileType, @NonNls @NotNull final String text) {
return configureByText(fileType, text, null);
}
- protected PsiFile configureByText(@NotNull final FileType fileType, @NonNls final String text, @Nullable String _extension) {
+ protected PsiFile configureByText(@NotNull final FileType fileType, @NonNls @NotNull String text, @Nullable String _extension) {
try {
final String extension = _extension == null ? fileType.getDefaultExtension():_extension;
@@ -160,6 +152,7 @@
}
final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(tempFile);
assert vFile != null;
+ vFile.setCharset(CharsetToolkit.UTF8_CHARSET);
VfsUtil.saveText(vFile, text);
final VirtualFile vdir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(dir);
@@ -177,16 +170,11 @@
}
- @Override
- protected String getTestDataPath() {
- return PathManagerEx.getTestDataPath();
- }
-
- protected void configureByFile(final VirtualFile vFile) throws IOException {
+ protected void configureByFile(@NotNull VirtualFile vFile) throws IOException {
configureByFile(vFile, null);
}
- protected void configureByExistingFile(final VirtualFile virtualFile) {
+ protected void configureByExistingFile(@NotNull final VirtualFile virtualFile) {
myFile = null;
myEditor = null;
@@ -216,7 +204,7 @@
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
}
- protected VirtualFile configureByFiles(@Nullable final File rawProjectRoot, final VirtualFile... vFiles) throws IOException {
+ protected VirtualFile configureByFiles(@Nullable final File rawProjectRoot, @NotNull final VirtualFile... vFiles) throws IOException {
myFile = null;
myEditor = null;
@@ -235,7 +223,7 @@
// auxiliary files should be copied first
VirtualFile[] reversed = ArrayUtil.reverseArray(vFiles);
- final LinkedHashMap<VirtualFile, EditorInfo> editorInfos;
+ Map<VirtualFile, EditorInfo> editorInfos;
if (rawProjectRoot != null) {
final File projectRoot = rawProjectRoot.getCanonicalFile();
FileUtil.copyDir(projectRoot, toDirIO);
@@ -288,22 +276,26 @@
return false;
}
- protected void doCommitModel(final ModifiableRootModel rootModel) {
+ protected void doCommitModel(@NotNull ModifiableRootModel rootModel) {
rootModel.commit();
}
protected void sourceRootAdded(final VirtualFile dir) {
}
- protected LinkedHashMap<VirtualFile, EditorInfo> copyFilesFillingEditorInfos(String testDataFromDir,
- final VirtualFile toDir,
- final String... relativePaths) throws IOException {
+ @NotNull
+ protected Map<VirtualFile, EditorInfo> copyFilesFillingEditorInfos(@NotNull String testDataFromDir,
+ @NotNull VirtualFile toDir,
+ @NotNull String... relativePaths) throws IOException {
if (!testDataFromDir.startsWith("/")) testDataFromDir = "/" + testDataFromDir;
return copyFilesFillingEditorInfos(LocalFileSystem.getInstance().refreshAndFindFileByPath(getTestDataPath() + testDataFromDir), toDir, relativePaths);
}
- protected LinkedHashMap<VirtualFile, EditorInfo> copyFilesFillingEditorInfos(final VirtualFile fromDir, final VirtualFile toDir, final String... relativePaths) throws IOException {
- LinkedHashMap<VirtualFile, EditorInfo> editorInfos = new LinkedHashMap<VirtualFile, EditorInfo>();
+ @NotNull
+ protected Map<VirtualFile, EditorInfo> copyFilesFillingEditorInfos(@NotNull VirtualFile fromDir,
+ @NotNull VirtualFile toDir,
+ @NotNull String... relativePaths) throws IOException {
+ Map<VirtualFile, EditorInfo> editorInfos = new LinkedHashMap<VirtualFile, EditorInfo>();
List<OutputStream> streamsToClose = new ArrayList<OutputStream>();
@@ -356,28 +348,30 @@
}
}*/
- private EditorInfo copyContent(final VirtualFile from, final VirtualFile to, final List<OutputStream> streamsToClose) throws IOException {
+ private EditorInfo copyContent(@NotNull VirtualFile from, @NotNull VirtualFile to, @NotNull List<OutputStream> streamsToClose) throws IOException {
byte[] content = from.getFileType().isBinary() ? from.contentsToByteArray(): null;
- final String fileText = from.getFileType().isBinary() ? null : StringUtil.convertLineSeparators(VfsUtil.loadText(from));
+ final String fileText = from.getFileType().isBinary() ? null : StringUtil.convertLineSeparators(VfsUtilCore.loadText(from));
- EditorInfo editorInfo = fileText != null ? new EditorInfo(fileText) : null;
- String newFileText = fileText != null ? editorInfo.getNewFileText() : null;
+ EditorInfo editorInfo = fileText == null ? null : new EditorInfo(fileText);
+ String newFileText = fileText == null ? null : editorInfo.getNewFileText();
doWrite(newFileText, to, content, streamsToClose);
return editorInfo;
}
- protected final void setActiveEditor(Editor editor) {
+ protected final void setActiveEditor(@NotNull Editor editor) {
myEditor = editor;
myFile = getPsiFile(editor.getDocument());
}
- protected List<Editor> openEditorsAndActivateLast(final LinkedHashMap<VirtualFile, EditorInfo> editorInfos) {
+ @NotNull
+ protected List<Editor> openEditorsAndActivateLast(@NotNull Map<VirtualFile, EditorInfo> editorInfos) {
final List<Editor> list = openEditors(editorInfos);
setActiveEditor(list.get(list.size() - 1));
return list;
}
- protected final List<Editor> openEditors(final LinkedHashMap<VirtualFile, EditorInfo> editorInfos) {
+ @NotNull
+ protected final List<Editor> openEditors(@NotNull final Map<VirtualFile, EditorInfo> editorInfos) {
return ContainerUtil.map(editorInfos.keySet(), new Function<VirtualFile, Editor>() {
@Override
public Editor fun(final VirtualFile newVFile) {
@@ -396,14 +390,18 @@
});
}
- private void doWrite(final String newFileText, final VirtualFile newVFile, final byte[] content, final List<OutputStream> streamsToClose) throws IOException {
- if (newFileText != null) {
- VfsUtil.saveText(newVFile, newFileText);
- } else {
+ private void doWrite(final String newFileText,
+ @NotNull VirtualFile newVFile,
+ byte[] content,
+ @NotNull List<OutputStream> streamsToClose) throws IOException {
+ if (newFileText == null) {
final OutputStream outputStream = newVFile.getOutputStream(this, -1, -1);
outputStream.write(content);
streamsToClose.add(outputStream);
}
+ else {
+ VfsUtil.saveText(newVFile, newFileText);
+ }
}
protected boolean isAddDirToContentRoot() {
@@ -414,7 +412,7 @@
return true;
}
- protected VirtualFile configureByFile(final VirtualFile vFile, final File projectRoot) throws IOException {
+ protected VirtualFile configureByFile(@NotNull VirtualFile vFile, File projectRoot) throws IOException {
return configureByFiles(projectRoot, vFile);
}
@@ -422,42 +420,42 @@
return false;
}
- protected void setupCursorAndSelection(final Editor editor) {
+ protected void setupCursorAndSelection(@NotNull final Editor editor) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
Document document = editor.getDocument();
- final String text = document.getText();
-
- int caretIndex = text.indexOf(CARET_MARKER);
- int selStartIndex = text.indexOf(SELECTION_START_MARKER);
- int selEndIndex = text.indexOf(SELECTION_END_MARKER);
-
- final RangeMarker caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex) : null;
- final RangeMarker selStartMarker = selStartIndex >= 0 ? document.createRangeMarker(selStartIndex, selStartIndex) : null;
- final RangeMarker selEndMarker = selEndIndex >= 0 ? document.createRangeMarker(selEndIndex, selEndIndex) : null;
-
- if (caretMarker != null) {
- document.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_MARKER.length());
- }
- if (selStartMarker != null) {
- document.deleteString(selStartMarker.getStartOffset(), selStartMarker.getStartOffset() + SELECTION_START_MARKER.length());
- }
- if (selEndMarker != null) {
- document.deleteString(selEndMarker.getStartOffset(), selEndMarker.getStartOffset() + SELECTION_END_MARKER.length());
- }
+ EditorTestUtil.CaretsState caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document);
final String newText = document.getText();
- if (caretMarker != null) {
- int caretLine = StringUtil.offsetToLineNumber(newText, caretMarker.getStartOffset());
- int caretCol = caretMarker.getStartOffset() - StringUtil.lineColToOffset(newText, caretLine, 0);
- LogicalPosition pos = new LogicalPosition(caretLine, caretCol);
- editor.getCaretModel().moveToLogicalPosition(pos);
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ List<LogicalPosition> caretPositions = new ArrayList<LogicalPosition>();
+ List<Segment> selections = new ArrayList<Segment>();
+ for (EditorTestUtil.Caret caret : caretState.carets) {
+ LogicalPosition pos = null;
+ if (caret.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(newText, caret.offset);
+ int caretCol = caret.offset - StringUtil.lineColToOffset(newText, caretLine, 0);
+ pos = new LogicalPosition(caretLine, caretCol);
+ }
+ caretPositions.add(pos);
+ selections.add(caret.selection == null ? null : caret.selection);
+ }
+ editor.getCaretModel().setCarets(caretPositions, selections);
}
-
- if (selStartMarker != null) {
- editor.getSelectionModel().setSelection(selStartMarker.getStartOffset(), selEndMarker.getStartOffset());
+ else {
+ assert caretState.carets.size() == 1 : "Multiple carets are not supported by the model";
+ EditorTestUtil.Caret caret = caretState.carets.get(0);
+ if (caret.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(newText, caret.offset);
+ int caretCol = caret.offset - StringUtil.lineColToOffset(newText, caretLine, 0);
+ LogicalPosition pos = new LogicalPosition(caretLine, caretCol);
+ editor.getCaretModel().moveToLogicalPosition(pos);
+ }
+ if (caret.selection != null) {
+ editor.getSelectionModel().setSelection(caret.selection.getStartOffset(), caret.selection.getEndOffset());
+ }
}
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
@@ -466,7 +464,7 @@
}
@Override
- protected void configure(String path, String dataName) throws Exception {
+ protected void configure(@NotNull String path, String dataName) throws Exception {
super.configure(path, dataName);
myEditor = createEditor(myFile.getVirtualFile());
@@ -487,14 +485,15 @@
myEditor.getSelectionModel().setSelection(selectionStart, selectionEnd);
}
- protected void checkResultByFile(@NonNls String filePath) throws Exception {
+ protected void checkResultByFile(@NonNls @NotNull String filePath) throws Exception {
checkResultByFile(filePath, false);
}
- protected void checkResultByFile(@NonNls final String filePath, final boolean stripTrailingSpaces) throws Exception {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ protected void checkResultByFile(@NonNls @NotNull final String filePath, final boolean stripTrailingSpaces) throws Exception {
+ new WriteCommandAction<Document>(getProject()) {
+ @SuppressWarnings("ConstantConditions")
@Override
- public void run() {
+ protected void run(@NotNull Result<Document> result) throws Throwable {
getProject().getComponent(PostprocessReformattingAspect.class).doPostponedFormatting();
if (stripTrailingSpaces) {
((DocumentImpl)myEditor.getDocument()).stripTrailingSpaces(getProject());
@@ -506,9 +505,9 @@
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/'));
assertNotNull("Cannot find file " + fullPath, vFile);
- String ft = null;
+ String ft;
try {
- ft = VfsUtil.loadText(vFile);
+ ft = VfsUtilCore.loadText(vFile);
}
catch (IOException e) {
throw new RuntimeException(e);
@@ -517,23 +516,7 @@
String fileText = StringUtil.convertLineSeparators(ft);
Document document = EditorFactory.getInstance().createDocument(fileText);
- int caretIndex = fileText.indexOf(CARET_MARKER);
- int selStartIndex = fileText.indexOf(SELECTION_START_MARKER);
- int selEndIndex = fileText.indexOf(SELECTION_END_MARKER);
-
- final RangeMarker caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex) : null;
- final RangeMarker selStartMarker = selStartIndex >= 0 ? document.createRangeMarker(selStartIndex, selStartIndex) : null;
- final RangeMarker selEndMarker = selEndIndex >= 0 ? document.createRangeMarker(selEndIndex, selEndIndex) : null;
-
- if (caretMarker != null) {
- document.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_MARKER.length());
- }
- if (selStartMarker != null) {
- document.deleteString(selStartMarker.getStartOffset(), selStartMarker.getStartOffset() + SELECTION_START_MARKER.length());
- }
- if (selEndMarker != null) {
- document.deleteString(selEndMarker.getStartOffset(), selEndMarker.getStartOffset() + SELECTION_END_MARKER.length());
- }
+ EditorTestUtil.CaretsState caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document);
String newFileText = document.getText();
String newFileText1 = newFileText;
@@ -553,39 +536,49 @@
assertEquals("Text mismatch in file " + filePath, newFileText1, text);
- if (caretMarker != null) {
- int caretLine = StringUtil.offsetToLineNumber(newFileText, caretMarker.getStartOffset());
- int caretCol = caretMarker.getStartOffset() - StringUtil.lineColToOffset(newFileText, caretLine, 0);
+ CaretModel caretModel = myEditor.getCaretModel();
+ List<Caret> allCarets = new ArrayList<Caret>(caretModel.getAllCarets());
+ assertEquals("Unexpected number of carets", caretState.carets.size(), allCarets.size());
+ for (int i = 0; i < caretState.carets.size(); i++) {
+ String caretDescription = caretState.carets.size() == 1 ? "" : "caret " + (i + 1) + "/" + caretState.carets.size() + " ";
+ Caret currentCaret = allCarets.get(i);
+ LogicalPosition actualCaretPosition = currentCaret.getLogicalPosition();
+ EditorTestUtil.Caret expected = caretState.carets.get(i);
+ if (expected.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(newFileText, expected.offset);
+ int caretCol = expected.offset - StringUtil.lineColToOffset(newFileText, caretLine, 0);
- assertEquals("caretLine", caretLine + 1, myEditor.getCaretModel().getLogicalPosition().line + 1);
- assertEquals("caretColumn", caretCol + 1, myEditor.getCaretModel().getLogicalPosition().column + 1);
- }
+ assertEquals(caretDescription + "caretLine", caretLine + 1, actualCaretPosition.line + 1);
+ assertEquals(caretDescription + "caretColumn", caretCol + 1, actualCaretPosition.column + 1);
+ }
+ int actualSelectionStart = currentCaret.getSelectionStart();
+ int actualSelectionEnd = currentCaret.getSelectionEnd();
+ if (expected.selection != null) {
+ int selStartLine = StringUtil.offsetToLineNumber(newFileText, expected.selection.getStartOffset());
+ int selStartCol = expected.selection.getStartOffset() - StringUtil.lineColToOffset(newFileText, selStartLine, 0);
- if (selStartMarker != null && selEndMarker != null) {
- int selStartLine = StringUtil.offsetToLineNumber(newFileText, selStartMarker.getStartOffset());
- int selStartCol = selStartMarker.getStartOffset() - StringUtil.lineColToOffset(newFileText, selStartLine, 0);
+ int selEndLine = StringUtil.offsetToLineNumber(newFileText, expected.selection.getEndOffset());
+ int selEndCol = expected.selection.getEndOffset() - StringUtil.lineColToOffset(newFileText, selEndLine, 0);
- int selEndLine = StringUtil.offsetToLineNumber(newFileText, selEndMarker.getEndOffset());
- int selEndCol = selEndMarker.getEndOffset() - StringUtil.lineColToOffset(newFileText, selEndLine, 0);
+ assertEquals(caretDescription + "selectionStartLine", selStartLine + 1,
+ StringUtil.offsetToLineNumber(newFileText, actualSelectionStart) + 1);
- assertEquals("selectionStartLine", selStartLine + 1,
- StringUtil.offsetToLineNumber(newFileText, myEditor.getSelectionModel().getSelectionStart()) + 1);
+ assertEquals(caretDescription + "selectionStartCol", selStartCol + 1,
+ actualSelectionStart - StringUtil.lineColToOffset(newFileText, selStartLine, 0) + 1);
- assertEquals("selectionStartCol", selStartCol + 1,
- myEditor.getSelectionModel().getSelectionStart() - StringUtil.lineColToOffset(newFileText, selStartLine, 0) + 1);
+ assertEquals(caretDescription + "selectionEndLine", selEndLine + 1,
+ StringUtil.offsetToLineNumber(newFileText, actualSelectionEnd) + 1);
- assertEquals("selectionEndLine", selEndLine + 1,
- StringUtil.offsetToLineNumber(newFileText, myEditor.getSelectionModel().getSelectionEnd()) + 1);
-
- assertEquals("selectionEndCol", selEndCol + 1,
- myEditor.getSelectionModel().getSelectionEnd() - StringUtil.lineColToOffset(newFileText, selEndLine, 0) + 1);
- }
- else {
- assertTrue("should has no selection, but was: ("+myEditor.getSelectionModel().getSelectionStart()+", "+myEditor.getSelectionModel().getSelectionEnd()+")",
- !myEditor.getSelectionModel().hasSelection());
+ assertEquals(caretDescription + "selectionEndCol", selEndCol + 1,
+ actualSelectionEnd - StringUtil.lineColToOffset(newFileText, selEndLine, 0) + 1);
+ }
+ else {
+ assertFalse(caretDescription + "should has no selection, but was: (" + actualSelectionStart + ", " + actualSelectionEnd + ")",
+ currentCaret.hasSelection());
+ }
}
}
- });
+ }.execute();
}
@Override
@@ -626,7 +619,7 @@
return CommonDataKeys.EDITOR.is(dataId) ? myEditor : super.getData(dataId);
}
- protected VirtualFile getVirtualFile(@NonNls String filePath) {
+ protected VirtualFile getVirtualFile(@NonNls @NotNull String filePath) {
String fullPath = getTestDataPath() + filePath;
final VirtualFile vFile = LocalFileSystem.getInstance().findFileByPath(fullPath.replace(File.separatorChar, '/'));
@@ -634,6 +627,7 @@
return vFile;
}
+ @NotNull
protected String getTestRoot(){
return FileUtil.toSystemIndependentName(getTestDataPath());
}
@@ -673,7 +667,7 @@
action.execute(getEditor(), DataManager.getInstance().getDataContext());
}
- protected void type(@NonNls String s) {
+ protected void type(@NonNls @NotNull String s) {
for (char c : s.toCharArray()) {
type(c);
}
@@ -688,7 +682,7 @@
protected void backspace() {
backspace(getEditor());
}
- protected void backspace(final Editor editor) {
+ protected void backspace(@NotNull final Editor editor) {
CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
@Override
public void run() {
diff --git a/java/testFramework/src/com/intellij/codeInsight/EditorInfo.java b/java/testFramework/src/com/intellij/codeInsight/EditorInfo.java
index d770d7e..78d75d6 100644
--- a/java/testFramework/src/com/intellij/codeInsight/EditorInfo.java
+++ b/java/testFramework/src/com/intellij/codeInsight/EditorInfo.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,56 +15,36 @@
*/
package com.intellij.codeInsight;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.*;
+import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.text.StringUtil;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.testFramework.EditorTestUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
/**
* @author cdr
*/
public class EditorInfo {
- @NonNls public static final String CARET_MARKER = "<caret>";
- @NonNls public static final String SELECTION_START_MARKER = "<selection>";
- @NonNls public static final String SELECTION_END_MARKER = "</selection>";
-
String newFileText = null;
- public RangeMarker caretMarker = null;
- RangeMarker selStartMarker = null;
- RangeMarker selEndMarker = null;
+ public EditorTestUtil.CaretsState caretState;
public EditorInfo(final String fileText) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ new WriteCommandAction(null){
@Override
- public void run() {
+ protected void run(@NotNull Result result) throws Throwable {
updateCaretAndSelection(EditorFactory.getInstance().createDocument(fileText));
}
- });
+ }.execute();
}
- private boolean updateCaretAndSelection(final Document document) {
+ private void updateCaretAndSelection(final Document document) {
+ caretState = EditorTestUtil.extractCaretAndSelectionMarkers(document, false);
newFileText = document.getText();
-
- int caretIndex = newFileText.indexOf(CARET_MARKER);
- int selStartIndex = newFileText.indexOf(SELECTION_START_MARKER);
- int selEndIndex = newFileText.indexOf(SELECTION_END_MARKER);
-
- caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex) : null;
- selStartMarker = selStartIndex >= 0 ? document.createRangeMarker(selStartIndex, selStartIndex) : null;
- selEndMarker = selEndIndex >= 0 ? document.createRangeMarker(selEndIndex, selEndIndex) : null;
-
- if (caretMarker != null) {
- document.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_MARKER.length());
- }
- if (selStartMarker != null) {
- document.deleteString(selStartMarker.getStartOffset(), selStartMarker.getStartOffset() + SELECTION_START_MARKER.length());
- }
- if (selEndMarker != null) {
- document.deleteString(selEndMarker.getStartOffset(), selEndMarker.getStartOffset() + SELECTION_END_MARKER.length());
- }
-
- newFileText = document.getText();
- return caretMarker != null || selStartMarker != null || selEndMarker != null;
}
public String getNewFileText() {
@@ -72,15 +52,33 @@
}
public void applyToEditor(Editor editor) {
- if (caretMarker != null) {
- int caretLine = StringUtil.offsetToLineNumber(newFileText, caretMarker.getStartOffset());
- int caretCol = caretMarker.getStartOffset() - StringUtil.lineColToOffset(newFileText, caretLine, 0);
- LogicalPosition pos = new LogicalPosition(caretLine, caretCol);
- editor.getCaretModel().moveToLogicalPosition(pos);
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ List<LogicalPosition> caretPositions = new ArrayList<LogicalPosition>();
+ List<Segment> selections = new ArrayList<Segment>();
+ for (EditorTestUtil.Caret caret : caretState.carets) {
+ LogicalPosition pos = null;
+ if (caret.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(newFileText, caret.offset);
+ int caretCol = caret.offset - StringUtil.lineColToOffset(newFileText, caretLine, 0);
+ pos = new LogicalPosition(caretLine, caretCol);
+ }
+ caretPositions.add(pos);
+ selections.add(caret.selection == null ? null : caret.selection);
+ }
+ editor.getCaretModel().setCarets(caretPositions, selections);
}
-
- if (selStartMarker != null) {
- editor.getSelectionModel().setSelection(selStartMarker.getStartOffset(), selEndMarker.getStartOffset());
+ else {
+ assert caretState.carets.size() == 1 : "Multiple carets are not supported by the model";
+ EditorTestUtil.Caret caret = caretState.carets.get(0);
+ if (caret.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(newFileText, caret.offset);
+ int caretCol = caret.offset - StringUtil.lineColToOffset(newFileText, caretLine, 0);
+ LogicalPosition pos = new LogicalPosition(caretLine, caretCol);
+ editor.getCaretModel().moveToLogicalPosition(pos);
+ }
+ if (caret.selection != null) {
+ editor.getSelectionModel().setSelection(caret.selection.getStartOffset(), caret.selection.getEndOffset());
+ }
}
}
}
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
index f4d4c14..b9e5ba9 100644
--- a/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/DaemonAnalyzerTestCase.java
@@ -320,19 +320,22 @@
}
final JavaPsiFacadeEx facade = getJavaFacade();
if (facade != null) {
- facade.setAssertOnFileLoadingFilter(myFileTreeAccessFilter); // check repository work
+ facade.setAssertOnFileLoadingFilter(myFileTreeAccessFilter, myTestRootDisposable); // check repository work
}
- Collection<HighlightInfo> infos = doHighlighting();
+ try {
+ Collection<HighlightInfo> infos = doHighlighting();
- if (facade != null) {
- facade.setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
+ String text = myEditor.getDocument().getText();
+ data.checkLineMarkers(DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(getFile()), getProject()), text);
+ data.checkResult(infos, text);
+ return infos;
}
-
- String text = myEditor.getDocument().getText();
- data.checkLineMarkers(DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(getFile()), getProject()), text);
- data.checkResult(infos, text);
- return infos;
+ finally {
+ if (facade != null) {
+ facade.setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
+ }
+ }
}
public void allowTreeAccessForFile(@NotNull VirtualFile file) {
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java
index 46702b8..ff98bd2 100644
--- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightDaemonAnalyzerTestCase.java
@@ -105,7 +105,7 @@
}
protected void doTestConfiguredFile(boolean checkWarnings, boolean checkWeakWarnings, boolean checkInfos, @Nullable String filePath) {
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
ExpectedHighlightingData data = new ExpectedHighlightingData(getEditor().getDocument(), checkWarnings, checkWeakWarnings, checkInfos);
checkHighlighting(data, composeLocalPath(filePath));
@@ -122,13 +122,16 @@
PsiDocumentManager.getInstance(getProject()).commitAllDocuments();
getFile().getText(); //to load text
myJavaFilesFilter.allowTreeAccessForFile(getVFile());
- getJavaFacade().setAssertOnFileLoadingFilter(myJavaFilesFilter); // check repository work
+ getJavaFacade().setAssertOnFileLoadingFilter(myJavaFilesFilter, myTestRootDisposable); // check repository work
- Collection<HighlightInfo> infos = doHighlighting();
+ try {
+ Collection<HighlightInfo> infos = doHighlighting();
- getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
-
- data.checkResult(infos, getEditor().getDocument().getText(), filePath);
+ data.checkResult(infos, getEditor().getDocument().getText(), filePath);
+ }
+ finally {
+ getJavaFacade().setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
+ }
}
protected HighlightTestInfo doTestFile(@NonNls @NotNull String filePath) {
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/LightIntentionActionTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/LightIntentionActionTestCase.java
index 9268189..4a86713 100644
--- a/java/testFramework/src/com/intellij/codeInsight/daemon/LightIntentionActionTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/LightIntentionActionTestCase.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight.daemon;
-import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
-public abstract class LightIntentionActionTestCase extends LightQuickFixTestCase {
+public abstract class LightIntentionActionTestCase extends LightQuickFixParameterizedTestCase {
}
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixParameterizedTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixParameterizedTestCase.java
new file mode 100644
index 0000000..73e94a9
--- /dev/null
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixParameterizedTestCase.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.quickFix;
+
+import com.intellij.testFramework.FileBasedTestCaseHelperEx;
+import org.jetbrains.annotations.Nullable;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(com.intellij.testFramework.Parameterized.class)
+public abstract class LightQuickFixParameterizedTestCase extends LightQuickFixTestCase implements FileBasedTestCaseHelperEx {
+ @Override
+ public String getRelativeBasePath() {
+ return getBasePath();
+ }
+
+ @Nullable
+ @Override
+ public String getFileSuffix(String fileName) {
+ if (!fileName.startsWith(BEFORE_PREFIX)) return null;
+ return fileName.substring(BEFORE_PREFIX.length());
+ }
+
+ @Override
+ protected void doAllTests() {
+ super.doAllTests();
+ }
+
+ @Test
+ public void runSingle() throws Throwable {
+ final Throwable[] throwables = new Throwable[1];
+
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ doSingleTest(myFileSuffix, myTestDataPath);
+ }
+ catch (Throwable e) {
+ throwables[0] = e;
+ }
+ }
+ };
+
+ invokeTestRunnable(runnable);
+
+ if (throwables[0] != null) {
+ throw throwables[0];
+ }
+
+ }
+}
diff --git a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java
index 0925baf..eafc24d 100644
--- a/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.java
+++ b/java/testFramework/src/com/intellij/codeInsight/daemon/quickFix/LightQuickFixTestCase.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,8 +52,8 @@
import static com.intellij.util.ObjectUtils.notNull;
public abstract class LightQuickFixTestCase extends LightDaemonAnalyzerTestCase {
- @NonNls private static final String BEFORE_PREFIX = "before";
- @NonNls private static final String AFTER_PREFIX = "after";
+ @NonNls protected static final String BEFORE_PREFIX = "before";
+ @NonNls protected static final String AFTER_PREFIX = "after";
private static QuickFixTestCase myWrapper;
@@ -189,7 +189,7 @@
return findActionWithText(getAvailableActions(), text);
}
- public static IntentionAction findActionWithText(final List<IntentionAction> actions, final String text) {
+ public static IntentionAction findActionWithText(@NotNull List<IntentionAction> actions, final String text) {
for (IntentionAction action : actions) {
if (text.equals(action.getText())) {
return action;
@@ -225,12 +225,25 @@
doTestFor(fileSuffix, createWrapper());
}
+ /**
+ * @deprecated use com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase to get separate tests for all data files in
+ * testData directory
+ */
protected void doAllTests() {
doAllTests(createWrapper());
}
+ protected void doSingleTest(String fileSuffix, String testDataPath) {
+ doTestFor(fileSuffix, createWrapper(testDataPath));
+ }
- private QuickFixTestCase createWrapper() {
+ protected QuickFixTestCase createWrapper() {
+ return createWrapper(null);
+ }
+
+ protected QuickFixTestCase createWrapper(final String testDataPath) {
return new QuickFixTestCase() {
+ public String myTestDataPath = testDataPath;
+
@Override
public String getBasePath() {
return LightQuickFixTestCase.this.getBasePath();
@@ -238,7 +251,10 @@
@Override
public String getTestDataPath() {
- return LightQuickFixTestCase.this.getTestDataPath();
+ if (myTestDataPath == null) {
+ myTestDataPath = LightQuickFixTestCase.this.getTestDataPath();
+ }
+ return myTestDataPath;
}
@Override
diff --git a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java
index 348a1af..15b858f 100644
--- a/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java
+++ b/java/testFramework/src/com/intellij/compiler/CompilerTestUtil.java
@@ -2,6 +2,7 @@
import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor;
import com.intellij.compiler.impl.javaCompiler.javac.JavacConfiguration;
+import com.intellij.compiler.options.ExternalBuildOptionListener;
import com.intellij.compiler.server.BuildManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.Result;
@@ -81,6 +82,7 @@
new WriteAction() {
protected void run(final Result result) {
CompilerWorkspaceConfiguration.getInstance(project).USE_OUT_OF_PROCESS_BUILD = true;
+ project.getMessageBus().syncPublisher(ExternalBuildOptionListener.TOPIC).externalBuildOptionChanged(true);
ApplicationManagerEx.getApplicationEx().doNotSave(false);
JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
table.addJdk(table.getInternalJdk());
@@ -92,6 +94,7 @@
new WriteAction() {
protected void run(final Result result) {
CompilerWorkspaceConfiguration.getInstance(project).USE_OUT_OF_PROCESS_BUILD = false;
+ project.getMessageBus().syncPublisher(ExternalBuildOptionListener.TOPIC).externalBuildOptionChanged(false);
ApplicationManagerEx.getApplicationEx().doNotSave(true);
JavaAwareProjectJdkTableImpl table = JavaAwareProjectJdkTableImpl.getInstanceEx();
table.removeJdk(table.getInternalJdk());
diff --git a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
index bccbfe5..26e0eb5 100644
--- a/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
+++ b/java/testFramework/src/com/intellij/debugger/ExecutionWithDebuggerToolsTestCase.java
@@ -44,6 +44,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.CompositeException;
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.ui.UIUtil;
@@ -61,7 +62,7 @@
private final SynchronizationBasedSemaphore myScriptRunnablesSema = new SynchronizationBasedSemaphore();
protected static final int RATHER_LATER_INVOKES_N = 10;
public DebugProcessImpl myDebugProcess = null;
-
+ private final CompositeException exception = new CompositeException();
private class InvokeRatherLaterRequest {
private final DebuggerCommandImpl myDebuggerCommand;
@@ -103,6 +104,12 @@
});
}
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ if (!exception.isEmpty()) throw exception;
+ }
+
protected void onBreakpoint(SuspendContextRunnable runnable) {
if (myPauseScriptListener == null) {
final DebugProcessImpl debugProcess = getDebugProcess();
@@ -124,8 +131,12 @@
suspendContextRunnable.run(suspendContext);
}
catch (Exception e) {
+ exception.add(e);
error(e);
}
+ catch (AssertionError e) {
+ exception.add(e);
+ }
if (myScriptRunnables.isEmpty()) {
myScriptRunnablesSema.up();
diff --git a/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
index 075c681..bb8c0d0 100644
--- a/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
+++ b/java/testFramework/src/com/intellij/execution/ExecutionTestCase.java
@@ -230,11 +230,15 @@
// assertTrue(null, condition);
// }
- private static final int CURRENT_VERSION = 6;
- private static final String VERSION_FILE_NAME = "version-" + CURRENT_VERSION;
+ //private static final int CURRENT_VERSION = 6;
+ protected int getTestAppVersion() {
+ return 6;
+ }
+
protected void ensureCompiledAppExists() throws Exception {
final String appPath = getTestAppPath();
final File classesDir = new File(appPath, CLASSES);
+ String VERSION_FILE_NAME = "version-" + getTestAppVersion();
final File versionFile = new File(classesDir, VERSION_FILE_NAME);
if (!classesDir.exists() || !versionFile.exists() || !hasCompiledClasses(classesDir)) {
FileUtil.delete(classesDir);
diff --git a/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java b/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java
new file mode 100644
index 0000000..175a9fd
--- /dev/null
+++ b/java/testFramework/src/com/intellij/ide/projectWizard/ImportFromSourcesTestCase.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.projectWizard;
+
+import com.intellij.ide.util.importProject.DetectedRootData;
+import com.intellij.ide.util.importProject.RootDetectionProcessor;
+import com.intellij.ide.util.projectWizard.AbstractStepWithProgress;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
+import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
+import com.intellij.ide.util.projectWizard.importSources.impl.ProjectFromSourcesBuilderImpl;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.module.ModuleType;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.ui.EmptyIcon;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class ImportFromSourcesTestCase extends PlatformTestCase {
+ private ProjectFromSourcesBuilderImpl myBuilder;
+ private File myRootDir;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myBuilder = new ProjectFromSourcesBuilderImpl(new WizardContext(null), ModulesProvider.EMPTY_MODULES_PROVIDER);
+ }
+
+ @Override
+ protected void setUpProject() throws Exception {
+ }
+
+ protected Module assertOneModule(@NotNull ModuleType moduleType) {
+ Module module = assertOneElement(ModuleManager.getInstance(myProject).getModules());
+ assertEquals(moduleType, ModuleType.get(module));
+ return module;
+ }
+
+ protected void assertOneContentRoot(@NotNull Module module, String relativePath) {
+ File expected = new File(myRootDir, relativePath);
+ String url = assertOneElement(ModuleRootManager.getInstance(module).getContentRootUrls());
+ File actual = new File(VfsUtilCore.urlToPath(url));
+ assertEquals(expected.getAbsolutePath(), actual.getAbsolutePath());
+ }
+
+ protected void importFromSources(File dir) {
+ myRootDir = dir;
+ try {
+ myProject = doCreateProject(getIprFile());
+ myBuilder.setBaseProjectPath(dir.getAbsolutePath());
+ List<DetectedRootData> list = RootDetectionProcessor.detectRoots(dir);
+ MultiMap<ProjectStructureDetector,DetectedProjectRoot> map = RootDetectionProcessor.createRootsMap(list);
+ myBuilder.setupProjectStructure(map);
+ for (ProjectStructureDetector detector : map.keySet()) {
+ List<ModuleWizardStep> steps = detector.createWizardSteps(myBuilder, myBuilder.getProjectDescriptor(detector), EmptyIcon.ICON_16);
+ for (ModuleWizardStep step : steps) {
+ if (step instanceof AbstractStepWithProgress<?>) {
+ performStep((AbstractStepWithProgress<?>)step);
+ }
+ }
+ }
+ myBuilder.commit(myProject, null, ModulesProvider.EMPTY_MODULES_PROVIDER);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static <Result> void performStep(AbstractStepWithProgress<Result> step) {
+ step.performStep();
+ }
+}
diff --git a/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java b/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java
index e386eb0..d328f5a 100644
--- a/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java
+++ b/java/testFramework/src/com/intellij/ide/projectWizard/ProjectWizardTestCase.java
@@ -5,7 +5,7 @@
import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard;
import com.intellij.ide.util.newProjectWizard.AddModuleWizard;
import com.intellij.ide.util.newProjectWizard.SelectTemplateSettings;
-import com.intellij.ide.util.newProjectWizard.SelectTemplateStep;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.wizard.Step;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
@@ -23,7 +23,6 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.platform.ProjectTemplate;
import com.intellij.projectImport.ProjectImportProvider;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.util.Consumer;
@@ -86,13 +85,11 @@
protected void runWizard(String group, String name, Project project, @Nullable Consumer<Step> adjuster) throws IOException {
createWizard(project);
- SelectTemplateStep step = (SelectTemplateStep)myWizard.getCurrentStepObject();
+ ProjectTypeStep step = (ProjectTypeStep)myWizard.getCurrentStepObject();
boolean condition = step.setSelectedTemplate(group, name);
if (!condition) {
throw new IllegalArgumentException(group + "/" + name + " template not found");
}
- ProjectTemplate template = step.getSelectedTemplate();
- assertNotNull(template);
if (adjuster != null) {
adjuster.consume(step);
@@ -109,7 +106,7 @@
}
protected Project createProject(Consumer<Step> adjuster) throws IOException {
- createWizard(getProject());
+ createWizard(null);
runWizard(adjuster);
myCreatedProject = NewProjectUtil.createFromWizard(myWizard, null);
return myCreatedProject;
@@ -121,13 +118,17 @@
protected void runWizard(Consumer<Step> adjuster) {
while(true) {
+ ModuleWizardStep currentStep = myWizard.getCurrentStepObject();
if (adjuster != null) {
- adjuster.consume(myWizard.getCurrentStepObject());
+ adjuster.consume(currentStep);
}
if (myWizard.isLast()) {
break;
}
myWizard.doNextAction();
+ if (currentStep == myWizard.getCurrentStepObject()) {
+ throw new RuntimeException(currentStep + " is not validated");
+ }
}
myWizard.doOk();
}
diff --git a/java/testFramework/src/com/intellij/refactoring/MultiFileTestCase.java b/java/testFramework/src/com/intellij/refactoring/MultiFileTestCase.java
index dc18d32..cadc61a 100644
--- a/java/testFramework/src/com/intellij/refactoring/MultiFileTestCase.java
+++ b/java/testFramework/src/com/intellij/refactoring/MultiFileTestCase.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.
@@ -16,7 +16,7 @@
package com.intellij.refactoring;
import com.intellij.codeInsight.CodeInsightTestCase;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -25,6 +25,7 @@
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -54,7 +55,7 @@
final VirtualFile rootAfter = LocalFileSystem.getInstance().findFileByPath(pathAfter.replace(File.separatorChar, '/'));
performAction.performAction(rootDir, rootAfter);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
public void run() {
myProject.getComponent(PostprocessReformattingAspect.class).doPostponedFormatting();
}
@@ -71,6 +72,7 @@
PsiTestUtil.addSourceContentToRoots(myModule, rootDir);
}
+ @NotNull
@Override
@NonNls
protected abstract String getTestRoot();
diff --git a/java/testFramework/src/com/intellij/testFramework/EditorActionTestCase.java b/java/testFramework/src/com/intellij/testFramework/EditorActionTestCase.java
index a50e044..c6e01aa 100644
--- a/java/testFramework/src/com/intellij/testFramework/EditorActionTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/EditorActionTestCase.java
@@ -79,7 +79,7 @@
* @param ignoreTrailingSpaces true if trailing spaces should be ignored.
* @throws Exception
*/
- protected void doFileTest(String filePathBefore, String filePathAfter, boolean ignoreTrailingSpaces) throws Exception {
+ protected void doFileTest(String filePathBefore, String filePathAfter, boolean ignoreTrailingSpaces) {
configureByFile(filePathBefore);
invokeAction();
checkResultByFile(null, filePathAfter, ignoreTrailingSpaces);
diff --git a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
index c9d5c67..5962675 100644
--- a/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/InspectionTestCase.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.
@@ -188,12 +188,12 @@
}
@Override
- public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
return isEntryPoint(psiElement);
}
@Override
- public boolean isEntryPoint(PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull PsiElement psiElement) {
return ext_src != null && VfsUtilCore.isAncestor(ext_src, PsiUtilCore.getVirtualFile(psiElement), false);
}
diff --git a/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java b/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java
index 63bbdb2..c2c5b41 100644
--- a/java/testFramework/src/com/intellij/testFramework/PsiTestCase.java
+++ b/java/testFramework/src/com/intellij/testFramework/PsiTestCase.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 @@
import org.jdom.Document;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
@@ -122,7 +123,7 @@
return myFile.findElementAt(offset);
}
- protected void configure(String path, String dataName) throws Exception {
+ protected void configure(@NotNull String path, String dataName) throws Exception {
myDataRoot = getTestDataPath() + path;
myTestDataBefore = loadData(dataName);
diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory
new file mode 100644
index 0000000..0376d9e
--- /dev/null
+++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory
@@ -0,0 +1 @@
+org.jetbrains.jps.classFilesIndex.indexer.impl.MethodsUsageIndexerFactory
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java
index e94bee3..2b84d96 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/storage/BuildTargetStorages.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.builders.storage.StorageProvider;
@@ -55,7 +56,7 @@
return provider.createStorage(myPaths.getTargetDataRoot(myTarget));
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
};
@@ -68,12 +69,8 @@
try {
return (S)lazyValue.getValue();
}
- catch (RuntimeException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- throw (IOException)cause;
- }
- throw e;
+ catch (BuildDataCorruptedException e) {
+ throw e.getCause();
}
}
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 24ef26e..35de668 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
@@ -27,6 +27,7 @@
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.builders.java.dependencyView.Mappings;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
@@ -177,12 +178,8 @@
return additionalPassRequired;
}
- catch (RuntimeException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- throw ((IOException)cause);
- }
- throw e;
+ catch (BuildDataCorruptedException e) {
+ throw e.getCause();
}
finally {
context.processMessage(new ProgressMessage("")); // clean progress messages
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 154d5da..e104ffd 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
@@ -21,6 +21,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.*;
import java.lang.annotation.RetentionPolicy;
@@ -270,7 +271,7 @@
myUsages =(Set<UsageRepr.Usage>)RW.read(UsageRepr.externalizer(context), new THashSet<UsageRepr.Usage>(), in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -294,7 +295,7 @@
RW.save(myUsages, UsageRepr.externalizer(myContext), out);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -507,8 +508,8 @@
try {
bas.close();
}
- catch (final Exception e) {
- throw new RuntimeException(e);
+ catch (final IOException e) {
+ throw new BuildDataCorruptedException(e);
}
usages.add(bas.toString());
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java
index 922ec23..9e6311e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/DependencyContext.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.PersistentStringEnumerator;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.File;
import java.io.IOException;
@@ -83,7 +84,7 @@
return myEnumerator.valueOf(s);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -92,7 +93,7 @@
return StringUtil.isEmpty(s) ? myEmptyName : myEnumerator.enumerate(s);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -101,7 +102,7 @@
myEnumerator.close();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
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 f37ce8f..eb94639 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
@@ -26,6 +26,7 @@
import gnu.trove.TIntObjectProcedure;
import gnu.trove.TIntProcedure;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.*;
@@ -50,7 +51,7 @@
return collection == null? NULL_COLLECTION : collection;
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
};
@@ -62,7 +63,7 @@
return myMap.containsMapping(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -84,7 +85,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -116,7 +117,7 @@
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -131,7 +132,7 @@
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -153,7 +154,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -174,7 +175,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -185,7 +186,7 @@
myMap.remove(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -218,7 +219,7 @@
myMap.close();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -243,13 +244,13 @@
return procedure.execute(key, myMap.get(key));
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java
index 1f4387c..53c3fd3 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/IntObjectPersistentMaplet.java
@@ -22,6 +22,7 @@
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.TIntObjectProcedure;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.File;
import java.io.IOException;
@@ -49,13 +50,13 @@
return v1 == null? NULL_OBJ : v1;
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
};
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -65,7 +66,7 @@
return myMap.containsMapping(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -82,7 +83,7 @@
myMap.put(key, value);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -104,7 +105,7 @@
myMap.remove(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -115,7 +116,7 @@
myMap.close();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -141,13 +142,13 @@
return value == null? proc.execute(key, null) : proc.execute(key, value);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
}
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 23cee40..d195cbc 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
@@ -22,6 +22,7 @@
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.TIntObjectProcedure;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.*;
import java.util.Collection;
@@ -53,7 +54,7 @@
return collection == null? NULL_COLLECTION : collection;
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
};
@@ -66,7 +67,7 @@
return myMap.containsMapping(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -88,7 +89,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -105,7 +106,7 @@
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -132,7 +133,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -154,7 +155,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -165,7 +166,7 @@
myMap.remove(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -198,7 +199,7 @@
myMap.close();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -223,13 +224,13 @@
return procedure.execute(key, myMap.get(key));
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
index 553c60f..c4121fc 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
@@ -25,6 +25,7 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.ClassReader;
import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.incremental.storage.FileKeyDescriptor;
import java.io.File;
@@ -165,7 +166,7 @@
return new Mappings(this);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
}
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 b358e11..7b55ea7 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
@@ -19,12 +19,16 @@
import com.intellij.util.io.DataInputOutputUtil;
import gnu.trove.THashSet;
import org.jetbrains.asm4.Type;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.PrintStream;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Set;
/**
* @author: db
@@ -141,7 +145,7 @@
myExceptions = (Set<TypeRepr.AbstractType>)RW.read(externalizer, new THashSet<TypeRepr.AbstractType>(0), in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
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 ed6bc90..d94d092 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
@@ -22,6 +22,7 @@
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.TObjectObjectProcedure;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.*;
import java.util.Collection;
@@ -53,7 +54,7 @@
return collection == null? NULL_COLLECTION : collection;
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
};
@@ -66,7 +67,7 @@
return myMap.containsMapping(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -88,7 +89,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -105,7 +106,7 @@
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -132,7 +133,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -154,7 +155,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -165,7 +166,7 @@
myMap.remove(key);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -198,7 +199,7 @@
myMap.close();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -223,13 +224,13 @@
return procedure.execute(key, myMap.get(key));
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
});
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
index 62e0ebf..a7e70f6 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
@@ -17,6 +17,7 @@
import com.intellij.util.io.DataInputOutputUtil;
import org.jetbrains.asm4.Opcodes;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.DataInput;
import java.io.DataOutput;
@@ -45,7 +46,7 @@
name = DataInputOutputUtil.readINT(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -57,7 +58,7 @@
DataInputOutputUtil.writeINT(out, name);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
index fb3cb47..18582a8 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ProtoMember.java
@@ -17,6 +17,7 @@
import com.intellij.util.io.DataInputOutputUtil;
import org.jetbrains.asm4.Type;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.DataInput;
import java.io.DataOutput;
@@ -69,7 +70,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
assert (false);
@@ -84,7 +85,7 @@
myValue = loadTyped(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -123,7 +124,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
index f9d32b0..1f1704f 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/RW.java
@@ -20,6 +20,7 @@
import com.intellij.util.io.IOUtil;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntProcedure;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.*;
import java.util.Collection;
@@ -59,7 +60,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -74,13 +75,13 @@
return true;
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
});
}
catch (IOException c) {
- throw new RuntimeException(c);
+ throw new BuildDataCorruptedException(c);
}
}
@@ -93,7 +94,7 @@
}
}
catch (IOException c) {
- throw new RuntimeException(c);
+ throw new BuildDataCorruptedException(c);
}
}
@@ -108,7 +109,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -121,7 +122,7 @@
return result;
}
catch (IOException x) {
- throw new RuntimeException(x);
+ throw new BuildDataCorruptedException(x);
}
}
@@ -136,7 +137,7 @@
return acc;
}
catch (IOException x) {
- throw new RuntimeException(x);
+ throw new BuildDataCorruptedException(x);
}
}
@@ -151,7 +152,7 @@
return acc;
}
catch (IOException x) {
- throw new RuntimeException(x);
+ throw new BuildDataCorruptedException(x);
}
}
@@ -174,7 +175,7 @@
w.newLine();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -197,7 +198,7 @@
return r.readLine();
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
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 b341eae..dbdb7a9 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
@@ -19,6 +19,7 @@
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.DataInputOutputUtil;
import org.jetbrains.asm4.Type;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.DataInput;
import java.io.DataOutput;
@@ -68,7 +69,7 @@
DataInputOutputUtil.writeINT(out, type);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -81,7 +82,7 @@
type = DataInputOutputUtil.readINT(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -150,7 +151,7 @@
elementType.save(out);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
}
@@ -190,7 +191,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -225,7 +226,7 @@
}
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
}
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 f5201a7..8db8bbc 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
@@ -20,6 +20,7 @@
import gnu.trove.TIntHashSet;
import gnu.trove.TIntProcedure;
import org.jetbrains.asm4.Type;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import java.io.DataInput;
import java.io.DataOutput;
@@ -82,7 +83,7 @@
myOwner = DataInputOutputUtil.readINT(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -93,7 +94,7 @@
DataInputOutputUtil.writeINT(out, myOwner);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -130,7 +131,7 @@
myType = TypeRepr.externalizer(context).read(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -221,7 +222,7 @@
myReturnType = externalizer.read(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -289,7 +290,7 @@
myArity = DataInputOutputUtil.readINT(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -300,7 +301,7 @@
DataInputOutputUtil.writeINT(out, myArity);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -353,7 +354,7 @@
myClassName = DataInputOutputUtil.readINT(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -364,7 +365,7 @@
DataInputOutputUtil.writeINT(out, myClassName);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -410,7 +411,7 @@
DataInputOutputUtil.writeINT(out, myClassName);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
}
@@ -432,7 +433,7 @@
myClassName = DataInputOutputUtil.readINT(in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -443,7 +444,7 @@
DataInputOutputUtil.writeINT(out, myClassName);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -486,7 +487,7 @@
DataInputOutputUtil.writeINT(out, myClassName);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -573,7 +574,7 @@
myUsedTargets = (EnumSet<ElemType>)RW.read(elementTypeExternalizer, EnumSet.noneOf(ElemType.class), in);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
@@ -586,7 +587,7 @@
RW.save(myUsedTargets, elementTypeExternalizer, out);
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataCorruptedException.java b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataCorruptedException.java
new file mode 100644
index 0000000..ee81d7f
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/storage/BuildDataCorruptedException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.jps.builders.storage;
+
+import java.io.IOException;
+
+/**
+ * This exception indicates that some internal build storage cannot be loaded or saved properly. Rebuild will be requested to recover from
+ * the corruption.
+ *
+ * @author nik
+ */
+public class BuildDataCorruptedException extends RuntimeException {
+ public BuildDataCorruptedException(IOException cause) {
+ super(cause);
+ }
+
+ @Override
+ public synchronized IOException getCause() {
+ return (IOException)super.getCause();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java
new file mode 100644
index 0000000..4082d95
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/AsmUtil.java
@@ -0,0 +1,57 @@
+/*
+ * 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.jps.classFilesIndex;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.asm4.Type;
+
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class AsmUtil {
+ private AsmUtil() {}
+
+ public static String getQualifiedClassName(final String name) {
+ return StringUtil.replaceChar(Type.getObjectType(name).getClassName(), '$', '.');
+ }
+
+ //char
+ //double
+ //float
+ //int
+ //long
+ //short
+ //boolean
+ //byte
+ //void
+ //Object
+ //String
+ //Class
+ private static final Set<String> ASM_PRIMITIVE_TYPES = ContainerUtil
+ .newHashSet("C", "D", "F", "I", "J", "S", "Z", "B", "V", "Ljava/lang/Object;", "Ljava/lang/String;", "Ljava/lang/Class;");
+
+ public static boolean isPrimitiveOrArrayOfPrimitives(final String asmType) {
+ for (int i = 0; i < asmType.length(); i++) {
+ if (asmType.charAt(i) != '[') {
+ return ASM_PRIMITIVE_TYPES.contains(asmType.substring(i));
+ }
+ }
+ throw new AssertionError("Illegal string: " + asmType);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java
new file mode 100644
index 0000000..c754140
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/TObjectIntHashMapExternalizer.java
@@ -0,0 +1,80 @@
+/*
+ * 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.jps.classFilesIndex;
+
+import com.intellij.util.io.DataExternalizer;
+import gnu.trove.TObjectIntHashMap;
+import gnu.trove.TObjectIntProcedure;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class TObjectIntHashMapExternalizer<K> implements DataExternalizer<TObjectIntHashMap<K>> {
+ private final DataExternalizer<K> myKeyDataExternalizer;
+
+ public TObjectIntHashMapExternalizer(final DataExternalizer<K> keyDataExternalizer) {
+ myKeyDataExternalizer = keyDataExternalizer;
+ }
+
+ @Override
+ public void save(final DataOutput out, final TObjectIntHashMap<K> map) throws IOException {
+ out.writeInt(map.size());
+ try {
+ map.forEachEntry(new TObjectIntProcedure<K>() {
+ @Override
+ public boolean execute(final K key, final int value) {
+ try {
+ myKeyDataExternalizer.save(out, key);
+ out.writeInt(value);
+ }
+ catch (final IOException e) {
+ throw new IoExceptionRuntimeWrapperException(e);
+ }
+ return true;
+ }
+ });
+ }
+ catch (final IoExceptionRuntimeWrapperException e) {
+ throw e.getIoException();
+ }
+ }
+
+ @Override
+ public TObjectIntHashMap<K> read(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++) {
+ map.put(myKeyDataExternalizer.read(in), in.readInt());
+ }
+ return map;
+ }
+
+ private static class IoExceptionRuntimeWrapperException extends RuntimeException {
+ private final IOException myIoException;
+
+ private IoExceptionRuntimeWrapperException(final IOException ioException) {
+ myIoException = ioException;
+ }
+
+ public IOException getIoException() {
+ return myIoException;
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.java
new file mode 100644
index 0000000..b35bbca
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexer.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 org.jetbrains.jps.classFilesIndex.indexer.api;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.ClassReader;
+
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public abstract class ClassFileIndexer<K, V> {
+ private final String myIndexCanonicalName;
+
+ public ClassFileIndexer(final String indexCanonicalName) {
+ myIndexCanonicalName = indexCanonicalName;
+ }
+
+ @NotNull
+ public abstract Map<K, V> map(ClassReader inputData);
+
+ public abstract KeyDescriptor<K> getKeyDescriptor();
+
+ public abstract DataExternalizer<V> getDataExternalizer();
+
+ public String getIndexCanonicalName() {
+ return myIndexCanonicalName;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java
new file mode 100644
index 0000000..cc06cbe
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFileIndexerFactory.java
@@ -0,0 +1,25 @@
+/*
+ * 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.jps.classFilesIndex.indexer.api;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public interface ClassFileIndexerFactory<K, V> {
+
+ ClassFileIndexer<K, V> create();
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java
new file mode 100644
index 0000000..3ded5f2
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexStorage.java
@@ -0,0 +1,205 @@
+/*
+ * 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.jps.classFilesIndex.indexer.api;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.SLRUCache;
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import com.intellij.util.io.PersistentHashMap;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+
+/**
+ * @author Dmitry Batkovich
+ * <p/>
+ * synchronization only on write actions
+ */
+public class ClassFilesIndexStorage<K, V> {
+ private static final String INDEX_FILE_NAME = "index";
+ private static final int INITIAL_INDEX_SIZE = 16 * 1024;
+ private static final int CACHE_QUEUES_SIZE = 16 * 1024;
+
+ private final File myIndexFile;
+ private final KeyDescriptor<K> myKeyDescriptor;
+ private final DataExternalizer<V> myValueExternalizer;
+ private final Lock myWriteLock = new ReentrantLock();
+ private PersistentHashMap<K, CompiledDataValueContainer<V>> myMap;
+ @SuppressWarnings("FieldAccessedSynchronizedAndUnsynchronized") private SLRUCache<K, CompiledDataValueContainer<V>> myCache;
+
+ public ClassFilesIndexStorage(final File indexDir, final KeyDescriptor<K> keyDescriptor, final DataExternalizer<V> valueExternalizer)
+ throws IOException {
+ myIndexFile = getIndexFile(indexDir);
+ myKeyDescriptor = keyDescriptor;
+ myValueExternalizer = valueExternalizer;
+ initialize();
+ }
+
+ private void initialize() throws IOException {
+ myMap = new PersistentHashMap<K, CompiledDataValueContainer<V>>(myIndexFile, myKeyDescriptor,
+ createValueContainerExternalizer(myValueExternalizer),
+ INITIAL_INDEX_SIZE);
+ myCache = new SLRUCache<K, CompiledDataValueContainer<V>>(CACHE_QUEUES_SIZE, CACHE_QUEUES_SIZE) {
+ @NotNull
+ @Override
+ public CompiledDataValueContainer<V> createValue(final K key) {
+ try {
+ final CompiledDataValueContainer<V> valueContainer = myMap.get(key);
+ if (valueContainer != null) {
+ return valueContainer;
+ }
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ return new CompiledDataValueContainer<V>();
+ }
+
+ @Override
+ protected void onDropFromCache(final K key, final CompiledDataValueContainer<V> value) {
+ try {
+ myMap.put(key, value);
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ public Collection<V> getData(final K key) {
+ return myCache.get(key).getValues();
+ }
+
+ public void putData(final K key, final V value, final String inputId) {
+ try {
+ myWriteLock.lock();
+ final CompiledDataValueContainer<V> container = myCache.get(key);
+ container.putValue(inputId, value);
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ }
+
+ public void delete() throws IOException {
+ try {
+ myWriteLock.lock();
+ doDelete();
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ }
+
+ private void doDelete() throws IOException {
+ close();
+ PersistentHashMap.deleteFilesStartingWith(myIndexFile);
+ }
+
+ public void clear() throws IOException {
+ try {
+ myWriteLock.lock();
+ doDelete();
+ initialize();
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ }
+
+ public void flush() {
+ try {
+ myWriteLock.lock();
+ myCache.clear();
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ myMap.force();
+ }
+
+ public void close() throws IOException {
+ flush();
+ myMap.close();
+ }
+
+ public static class CompiledDataValueContainer<V> {
+ private final THashMap<String, V> myUnderlying;
+
+ private CompiledDataValueContainer(final THashMap<String, V> map) {
+ myUnderlying = map;
+ }
+
+ private CompiledDataValueContainer() {
+ this(new THashMap<String, V>());
+ }
+
+ private void putValue(final String inputId, final V value) {
+ myUnderlying.put(inputId, value);
+ }
+
+ public Collection<V> getValues() {
+ return myUnderlying.values();
+ }
+
+ }
+
+ public static File getIndexFile(final File indexDir) {
+ return new File(indexDir, INDEX_FILE_NAME);
+ }
+
+ public static File getIndexDir(final String indexName, final File projectSystemBuildDirectory) {
+ return new File(projectSystemBuildDirectory, "compiler.output.data.indices/" + indexName);
+ }
+
+ private static <V> DataExternalizer<CompiledDataValueContainer<V>> createValueContainerExternalizer(final DataExternalizer<V> valueExternalizer) {
+ final DataExternalizer<String> stringDataExternalizer = new EnumeratorStringDescriptor();
+ return new DataExternalizer<CompiledDataValueContainer<V>>() {
+ @Override
+ public void save(final DataOutput out, final CompiledDataValueContainer<V> value) throws IOException {
+ final THashMap<String, V> underlying = value.myUnderlying;
+ out.writeInt(underlying.size());
+ for (final Map.Entry<String, V> entry : underlying.entrySet()) {
+ stringDataExternalizer.save(out, entry.getKey());
+ valueExternalizer.save(out, entry.getValue());
+ }
+ }
+
+ @Override
+ public CompiledDataValueContainer<V> read(final DataInput in) throws IOException {
+ final THashMap<String, V> map = new THashMap<String, V>();
+ final int size = in.readInt();
+ for (int i = 0; i < size; i++) {
+ map.put(stringDataExternalizer.read(in), valueExternalizer.read(in));
+ }
+ return new CompiledDataValueContainer<V>(map);
+ }
+ };
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java
new file mode 100644
index 0000000..7609fee
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndexWriter.java
@@ -0,0 +1,99 @@
+/*
+ * 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.jps.classFilesIndex.indexer.api;
+
+import com.intellij.openapi.diagnostic.Log;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.io.PersistentHashMap;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ClassFilesIndexWriter<K, V> {
+ private static final Logger LOG = Logger.getInstance(ClassFilesIndexWriter.class);
+
+ private final ClassFileIndexer<K, V> myIndexer;
+ private final boolean myEmpty;
+ protected final ClassFilesIndexStorage<K, V> myIndex;
+
+ protected ClassFilesIndexWriter(final ClassFileIndexer<K, V> indexer, final CompileContext compileContext) {
+ myIndexer = indexer;
+ final File storageDir = getIndexRoot(compileContext);
+ final Set<String> containingFileNames = listFiles(storageDir);
+ if (!containingFileNames.contains("version") || !containingFileNames.contains("state")) {
+ throw new IllegalStateException("version or state file for index " + indexer.getIndexCanonicalName() + " not found in " + storageDir.getAbsolutePath());
+ }
+ ClassFilesIndexStorage<K, V> index = null;
+ IOException exception = null;
+ LOG.debug("start open... " + indexer.getIndexCanonicalName());
+ for (int attempt = 0; attempt < 2; attempt++) {
+ try {
+ index = new ClassFilesIndexStorage<K, V>(storageDir, myIndexer.getKeyDescriptor(), myIndexer.getDataExternalizer());
+ break;
+ }
+ catch (final IOException e) {
+ exception = e;
+ PersistentHashMap.deleteFilesStartingWith(ClassFilesIndexStorage.getIndexFile(storageDir));
+ }
+ }
+ LOG.debug("opened " + indexer.getIndexCanonicalName());
+ if (index == null) {
+ throw new RuntimeException(exception);
+ }
+ myIndex = index;
+ myEmpty = IndexState.EXIST != IndexState.load(storageDir) || exception != null;
+ IndexState.CORRUPTED.save(storageDir);
+ }
+
+ private static Set<String> listFiles(final File dir) {
+ final String[] containingFileNames = dir.list();
+ return containingFileNames == null ? Collections.<String>emptySet() : ContainerUtil.newHashSet(containingFileNames);
+ }
+
+ private File getIndexRoot(final CompileContext compileContext) {
+ final File rootFile = compileContext.getProjectDescriptor().dataManager.getDataPaths().getDataStorageRoot();
+ return ClassFilesIndexStorage.getIndexDir(myIndexer.getIndexCanonicalName(), rootFile);
+ }
+
+ public final boolean isEmpty() {
+ return myEmpty;
+ }
+
+ public final void close(final CompileContext compileContext) {
+ try {
+ myIndex.close();
+ IndexState.EXIST.save(getIndexRoot(compileContext));
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public final void update(final String id, final ClassReader inputData) {
+ for (final Map.Entry<K, V> e : myIndexer.map(inputData).entrySet()) {
+ myIndex.putData(e.getKey(), e.getValue(), id);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java
new file mode 100644
index 0000000..e3a95e9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/ClassFilesIndicesBuilder.java
@@ -0,0 +1,146 @@
+/*
+ * 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.jps.classFilesIndex.indexer.api;
+
+import com.intellij.compiler.instrumentation.InstrumentationClassFinder;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.asm4.ClassReader;
+import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.jps.ModuleChunk;
+import org.jetbrains.jps.builders.java.JavaBuilderUtil;
+import org.jetbrains.jps.incremental.BinaryContent;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.CompiledClass;
+import org.jetbrains.jps.incremental.instrumentation.BaseInstrumentingBuilder;
+import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+import java.io.File;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class ClassFilesIndicesBuilder extends BaseInstrumentingBuilder {
+ public static final Logger LOG = Logger.getInstance(ClassFilesIndicesBuilder.class);
+ private static final String PRESENTABLE_NAME = "Class-files indexer";
+ private static final String PROGRESS_MESSAGE = "Indexing class-files...";
+ public static final String PROPERTY_NAME = "intellij.compiler.output.index";
+
+ private final AtomicLong myMs = new AtomicLong(0);
+ private final AtomicInteger myFilesCount = new AtomicInteger(0);
+ private final Collection<ClassFilesIndexWriter> myIndexWriters = new ArrayList<ClassFilesIndexWriter>();
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public void buildStarted(final CompileContext context) {
+ super.buildStarted(context);
+ final boolean isEnabled = isEnabled();
+ LOG.info("class files data index " + (isEnabled ? "enabled" : "disabled"));
+ if (!isEnabled) {
+ return;
+ }
+ final Set<String> enabledIndicesBuilders = ContainerUtil.newHashSet(System.getProperty(PROPERTY_NAME).split(";"));
+ final boolean forcedRecompilation = JavaBuilderUtil.isForcedRecompilationAllJavaModules(context);
+ final Iterable<ClassFileIndexerFactory> extensions = JpsServiceManager.getInstance().getExtensions(ClassFileIndexerFactory.class);
+ int newIndicesCount = 0;
+ for (final ClassFileIndexerFactory builder : extensions) {
+ if (enabledIndicesBuilders.contains(builder.getClass().getName())) {
+ final ClassFilesIndexWriter indexWriter = new ClassFilesIndexWriter(builder.create(), context);
+ if (!indexWriter.isEmpty()) {
+ myIndexWriters.add(indexWriter);
+ }
+ else if (forcedRecompilation) {
+ newIndicesCount++;
+ myIndexWriters.add(indexWriter);
+ } else {
+ indexWriter.close(context);
+ }
+ }
+ }
+ if (forcedRecompilation) {
+ LOG.info(String.format("class files indexing: %d indices, %d new", myIndexWriters.size(), newIndicesCount));
+ }
+ else {
+ LOG.info(String.format("class files indexing: %d indices", myIndexWriters.size()));
+ }
+ }
+
+ @Override
+ public void buildFinished(final CompileContext context) {
+ super.buildFinished(context);
+ if (!isEnabled()) {
+ return;
+ }
+ final long ms = System.currentTimeMillis();
+ for (final ClassFilesIndexWriter index : myIndexWriters) {
+ index.close(context);
+ }
+ myIndexWriters.clear();
+ myMs.addAndGet(System.currentTimeMillis() - ms);
+ LOG.info("class files indexing finished for " + myFilesCount.get() + " files in " + myMs.get() + "ms");
+ }
+
+ @Nullable
+ @Override
+ protected BinaryContent instrument(final CompileContext context,
+ final CompiledClass compiled,
+ final ClassReader reader,
+ final ClassWriter writer,
+ final InstrumentationClassFinder finder) {
+ final long ms = System.currentTimeMillis();
+ for (final ClassFilesIndexWriter index : myIndexWriters) {
+ index.update(compiled.getOutputFile().getPath(), reader);
+ }
+ myMs.addAndGet(System.currentTimeMillis() - ms);
+ myFilesCount.incrementAndGet();
+ return null;
+ }
+
+ @Override
+ protected boolean canInstrument(final CompiledClass compiledClass, final int classFileVersion) {
+ return true;
+ }
+
+ @Override
+ protected boolean isEnabled(final CompileContext context, final ModuleChunk chunk) {
+ return isEnabled();
+ }
+
+ private static boolean isEnabled() {
+ return System.getProperty(PROPERTY_NAME) != null;
+ }
+
+ @Override
+ protected String getProgressMessage() {
+ return PROGRESS_MESSAGE;
+ }
+
+ @NotNull
+ @Override
+ public String getPresentableName() {
+ return PRESENTABLE_NAME;
+ }
+
+}
\ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java
new file mode 100644
index 0000000..ba371f9
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/api/IndexState.java
@@ -0,0 +1,62 @@
+/*
+ * 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.jps.classFilesIndex.indexer.api;
+
+import com.intellij.openapi.util.io.FileUtil;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public enum IndexState {
+ CORRUPTED,
+ NOT_EXIST,
+ EXIST;
+
+ private static final String STATE_FILE_NAME = "state";
+
+ public void save(final File indexDir) {
+ final File indexStateFile = new File(indexDir, STATE_FILE_NAME);
+ try {
+ FileUtil.writeToFile(indexStateFile, String.valueOf(this));
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public static IndexState load(final File indexDir) {
+ try {
+ final File indexStateFile = new File(indexDir, STATE_FILE_NAME);
+ if (!indexStateFile.exists()) {
+ NOT_EXIST.save(indexDir);
+ return NOT_EXIST;
+ }
+ final String fileString = FileUtil.loadFile(indexStateFile);
+ for (final IndexState indexState : values()) {
+ if (String.valueOf(indexState).equals(fileString)) {
+ return indexState;
+ }
+ }
+ throw new RuntimeException("Invalid state: " + fileString);
+ }
+ catch (final IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java
new file mode 100644
index 0000000..98844bf
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodIncompleteSignature.java
@@ -0,0 +1,160 @@
+/*
+ * 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.jps.classFilesIndex.indexer.impl;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.classFilesIndex.AsmUtil;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.Comparator;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodIncompleteSignature {
+ public static final String CONSTRUCTOR_METHOD_NAME = "<init>";
+
+ @NotNull
+ private final String myOwner;
+ @NotNull
+ private final String myReturnType;
+ @NotNull
+ private final String myName;
+ private final boolean myStatic;
+
+ public MethodIncompleteSignature(@NotNull final String owner,
+ @NotNull final String returnType,
+ @NotNull final String name,
+ final boolean aStatic) {
+ myOwner = owner;
+ myReturnType = returnType;
+ myName = name;
+ myStatic = aStatic;
+ }
+
+ public static MethodIncompleteSignature constructor(@NotNull final String className) {
+ return new MethodIncompleteSignature(className, className, CONSTRUCTOR_METHOD_NAME, true);
+ }
+
+ public MethodIncompleteSignature toExternalRepresentation() {
+ return new MethodIncompleteSignature(AsmUtil.getQualifiedClassName(getOwner()),
+ AsmUtil.getQualifiedClassName(getReturnType()),
+ getName(),
+ isStatic());
+ }
+
+ @NotNull
+ public String getOwner() {
+ return myOwner;
+ }
+
+ @NotNull
+ public String getReturnType() {
+ return myReturnType;
+ }
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
+
+ public boolean isStatic() {
+ return myStatic;
+ }
+
+ @Override
+ public String toString() {
+ return "MethodIncompleteSignature{" +
+ "myOwner='" + myOwner + '\'' +
+ ", myReturnType='" + myReturnType + '\'' +
+ ", myName='" + myName + '\'' +
+ ", myStatic=" + myStatic +
+ '}';
+ }
+
+ public final static Comparator<MethodIncompleteSignature> COMPARATOR = new Comparator<MethodIncompleteSignature>() {
+ @Override
+ public int compare(final MethodIncompleteSignature o1, final MethodIncompleteSignature o2) {
+ int sub = o1.getOwner().compareTo(o2.getOwner());
+ if (sub != 0) {
+ return sub;
+ }
+ sub = o1.getName().compareTo(o2.getName());
+ if (sub != 0) {
+ return sub;
+ }
+ sub = o1.getReturnType().compareTo(o2.getReturnType());
+ if (sub != 0) {
+ return sub;
+ }
+ if (o1.isStatic() && !o2.isStatic()) {
+ return 1;
+ }
+ if (o2.isStatic() && !o1.isStatic()) {
+ return -1;
+ }
+ return 0;
+ }
+ };
+
+ public static DataExternalizer<MethodIncompleteSignature> createDataExternalizer() {
+ final EnumeratorStringDescriptor stringDescriptor = new EnumeratorStringDescriptor();
+ return new DataExternalizer<MethodIncompleteSignature>() {
+ @Override
+ public void save(final DataOutput out, final MethodIncompleteSignature value) throws IOException {
+ stringDescriptor.save(out, value.getOwner());
+ stringDescriptor.save(out, value.getReturnType());
+ stringDescriptor.save(out, value.getName());
+ out.writeBoolean(value.isStatic());
+ }
+
+ @Override
+ public MethodIncompleteSignature read(final DataInput in) throws IOException {
+ return new MethodIncompleteSignature(stringDescriptor.read(in), stringDescriptor.read(in), stringDescriptor.read(in),
+ in.readBoolean());
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final MethodIncompleteSignature that = (MethodIncompleteSignature)o;
+
+ if (myStatic != that.myStatic) return false;
+ if (!myName.equals(that.myName)) return false;
+ if (!myOwner.equals(that.myOwner)) return false;
+ if (!myReturnType.equals(that.myReturnType)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myOwner.hashCode();
+ result = 31 * result + myReturnType.hashCode();
+ result = 31 * result + myName.hashCode();
+ result = 31 * result + (myStatic ? 1 : 0);
+ return result;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java
new file mode 100644
index 0000000..65eb0e4
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodUsageIndexKey.java
@@ -0,0 +1,105 @@
+/*
+ * 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.jps.classFilesIndex.indexer.impl;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumDataDescriptor;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodUsageIndexKey {
+ @NotNull
+ private final String myQualifiedClassName;
+ @NotNull
+ private final KeyRole myRole;
+
+ public MethodUsageIndexKey(@NotNull final String qualifiedClassName, @NotNull final KeyRole role) {
+ myQualifiedClassName = qualifiedClassName;
+ myRole = role;
+ }
+
+ @NotNull
+ public String getQualifiedClassName() {
+ return myQualifiedClassName;
+ }
+
+ @NotNull
+ public KeyRole getRole() {
+ return myRole;
+ }
+
+ public enum KeyRole {
+ RETURN_TYPE,
+ QUALIFIER;
+
+ private static final DataExternalizer<KeyRole> DATA_EXTERNALIZER = new EnumDataDescriptor<KeyRole>(KeyRole.class);
+ }
+
+
+ public static KeyDescriptor<MethodUsageIndexKey> createKeyDescriptor() {
+ final DataExternalizer<String> stringDataExternalizer = new EnumeratorStringDescriptor();
+ return new KeyDescriptor<MethodUsageIndexKey>() {
+ @Override
+ public void save(final DataOutput out, final MethodUsageIndexKey value) throws IOException {
+ stringDataExternalizer.save(out, value.getQualifiedClassName());
+ KeyRole.DATA_EXTERNALIZER.save(out, value.getRole());
+ }
+
+ @Override
+ public MethodUsageIndexKey read(final DataInput in) throws IOException {
+ return new MethodUsageIndexKey(stringDataExternalizer.read(in), KeyRole.DATA_EXTERNALIZER.read(in));
+ }
+
+ @Override
+ public int getHashCode(final MethodUsageIndexKey value) {
+ return value.hashCode();
+ }
+
+ @Override
+ public boolean isEqual(final MethodUsageIndexKey val1, final MethodUsageIndexKey val2) {
+ return val1.equals(val2);
+ }
+ };
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (!(o instanceof MethodUsageIndexKey)) return false;
+
+ final MethodUsageIndexKey that = (MethodUsageIndexKey)o;
+
+ if (!myQualifiedClassName.equals(that.myQualifiedClassName)) return false;
+ if (myRole != that.myRole) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myQualifiedClassName.hashCode();
+ result = 31 * result + myRole.hashCode();
+ return result;
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java
new file mode 100644
index 0000000..e4eac05
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexer.java
@@ -0,0 +1,97 @@
+/*
+ * 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.jps.classFilesIndex.indexer.impl;
+
+import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.EnumeratorStringDescriptor;
+import com.intellij.util.io.KeyDescriptor;
+import gnu.trove.TObjectIntHashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.asm4.*;
+import org.jetbrains.jps.classFilesIndex.AsmUtil;
+import org.jetbrains.jps.classFilesIndex.TObjectIntHashMapExternalizer;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Dmitry Batkovich
+ */
+public class MethodsUsageIndexer extends ClassFileIndexer<String, TObjectIntHashMap<MethodIncompleteSignature>> {
+ public static final String METHODS_USAGE_INDEX_CANONICAL_NAME = "MethodsUsageIndex";
+
+ public MethodsUsageIndexer() {
+ super(METHODS_USAGE_INDEX_CANONICAL_NAME);
+ }
+
+ @NotNull
+ @Override
+ public Map<String, TObjectIntHashMap<MethodIncompleteSignature>> map(final ClassReader inputData) {
+ final Map<String, TObjectIntHashMap<MethodIncompleteSignature>> map =
+ new HashMap<String, TObjectIntHashMap<MethodIncompleteSignature>>();
+ final MethodVisitor methodVisitor = new MethodVisitor(Opcodes.ASM4) {
+ @Override
+ public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc) {
+ final Type returnType = Type.getReturnType(desc);
+ if (MethodIncompleteSignature.CONSTRUCTOR_METHOD_NAME.equals(name) ||
+ AsmUtil.isPrimitiveOrArrayOfPrimitives(returnType.getDescriptor())) {
+ return;
+ }
+ final boolean isStatic = opcode == Opcodes.INVOKESTATIC;
+ final String returnClassName = returnType.getInternalName();
+ if (!owner.equals(returnClassName) || isStatic) {
+ addToIndex(map, returnClassName, new MethodIncompleteSignature(owner, returnClassName, name, isStatic));
+ }
+ }
+ };
+ inputData.accept(new ClassVisitor(Opcodes.ASM4) {
+ @Override
+ public MethodVisitor visitMethod(final int access,
+ final String name,
+ final String desc,
+ final String signature,
+ final String[] exceptions) {
+ return methodVisitor;
+ }
+ }, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
+ return map;
+ }
+
+ @Override
+ public KeyDescriptor<String> getKeyDescriptor() {
+ return new EnumeratorStringDescriptor();
+ }
+
+ @Override
+ public DataExternalizer<TObjectIntHashMap<MethodIncompleteSignature>> getDataExternalizer() {
+ return new TObjectIntHashMapExternalizer<MethodIncompleteSignature>(MethodIncompleteSignature.createDataExternalizer());
+ }
+
+ private static void addToIndex(final Map<String, TObjectIntHashMap<MethodIncompleteSignature>> map,
+ final String internalClassName,
+ final MethodIncompleteSignature mi) {
+ final String className = AsmUtil.getQualifiedClassName(internalClassName);
+ TObjectIntHashMap<MethodIncompleteSignature> occurrences = map.get(className);
+ if (occurrences == null) {
+ occurrences = new TObjectIntHashMap<MethodIncompleteSignature>();
+ map.put(className, occurrences);
+ }
+ if (!occurrences.increment(mi)) {
+ occurrences.put(mi, 1);
+ }
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java
new file mode 100644
index 0000000..670ddae
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/classFilesIndex/indexer/impl/MethodsUsageIndexerFactory.java
@@ -0,0 +1,30 @@
+/*
+ * 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.jps.classFilesIndex.indexer.impl;
+
+import gnu.trove.TObjectIntHashMap;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexer;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFileIndexerFactory;
+
+/**
+* @author Dmitry Batkovich
+*/
+public class MethodsUsageIndexerFactory implements ClassFileIndexerFactory<String, TObjectIntHashMap<MethodIncompleteSignature>> {
+ @Override
+ public ClassFileIndexer<String, TObjectIntHashMap<MethodIncompleteSignature>> create() {
+ return new MethodsUsageIndexer();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
index 0d5f03f..821a2ff 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/client/ProtobufClientMessageHandler.java
@@ -47,7 +47,7 @@
}
@Override
- public final void channelRead0(ChannelHandlerContext context, MessageLite message) throws Exception {
+ public final void messageReceived(ChannelHandlerContext context, MessageLite message) throws Exception {
final UUID messageUUID = myUuidGetter.getSessionUUID((JavacRemoteProto.Message)message);
final RequestFuture<T> future = myHandlers.get(messageUUID);
final T handler = future != null ? future.getMessageHandler() : null;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
index c6b34ab..8dc21b1 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildMain.java
@@ -112,7 +112,7 @@
}
@Override
- public void channelRead0(final ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
+ public void messageReceived(final ChannelHandlerContext context, CmdlineRemoteProto.Message message) throws Exception {
final CmdlineRemoteProto.Message.Type type = message.getType();
final Channel channel = context.channel();
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
index 7ac1a37..d7f46af 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
@@ -25,7 +25,6 @@
import com.intellij.util.concurrency.BoundedTaskExecutor;
import com.intellij.util.containers.ConcurrentHashSet;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.MultiMapBasedOnSet;
import com.intellij.util.io.MappingFailedException;
import com.intellij.util.io.PersistentEnumerator;
import gnu.trove.THashMap;
@@ -44,6 +43,7 @@
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
import org.jetbrains.jps.cmdline.BuildRunner;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
@@ -194,30 +194,31 @@
myMessageDispatcher.processMessage(new ProgressMessage(msg));
}
}
+ catch (BuildDataCorruptedException e) {
+ LOG.info(e);
+ requestRebuild(e, e);
+ }
catch (ProjectBuildException e) {
LOG.info(e);
final Throwable cause = e.getCause();
if (cause instanceof PersistentEnumerator.CorruptedException ||
cause instanceof MappingFailedException ||
- cause instanceof IOException) {
-
- myMessageDispatcher.processMessage(new CompilerMessage(
- "", BuildMessage.Kind.INFO,
- "Internal caches are corrupted or have outdated format, forcing project rebuild: " +
- e.getMessage())
- );
- throw new RebuildRequestedException(cause);
+ cause instanceof IOException ||
+ cause instanceof BuildDataCorruptedException) {
+ requestRebuild(e, cause);
}
else {
// should stop the build with error
final String errMessage = e.getMessage();
final CompilerMessage msg;
if (StringUtil.isEmptyOrSpaces(errMessage)) {
- msg = new CompilerMessage("", cause != null? cause : e);
+ msg = new CompilerMessage("", cause != null ? cause : e);
}
else {
- final String causeMessage = cause != null? cause.getMessage() : "";
- msg = new CompilerMessage("", BuildMessage.Kind.ERROR, StringUtil.isEmptyOrSpaces(causeMessage) || errMessage.equals(causeMessage)? errMessage : errMessage + ": " + causeMessage);
+ final String causeMessage = cause != null ? cause.getMessage() : "";
+ msg = new CompilerMessage("", BuildMessage.Kind.ERROR, StringUtil.isEmptyOrSpaces(causeMessage) || errMessage.equals(causeMessage)
+ ? errMessage
+ : errMessage + ": " + causeMessage);
}
myMessageDispatcher.processMessage(msg);
}
@@ -226,7 +227,7 @@
memWatcher.stop();
flushContext(context);
// wait for async tasks
- final CanceledStatus status = context == null? CanceledStatus.NULL : context.getCancelStatus();
+ final CanceledStatus status = context == null ? CanceledStatus.NULL : context.getCancelStatus();
synchronized (myAsyncTasks) {
for (Future task : myAsyncTasks) {
if (status.isCanceled()) {
@@ -238,6 +239,13 @@
}
}
+ private void requestRebuild(Exception e, Throwable cause) throws RebuildRequestedException {
+ myMessageDispatcher.processMessage(new CompilerMessage("", BuildMessage.Kind.INFO,
+ "Internal caches are corrupted or have outdated format, forcing project rebuild: " +
+ e.getMessage()));
+ throw new RebuildRequestedException(cause);
+ }
+
private static void waitForTask(@NotNull CanceledStatus status, Future task) {
try {
while (true) {
@@ -470,7 +478,7 @@
}
private void clearOutputs(CompileContext context) throws ProjectBuildException {
- final MultiMap<File, BuildTarget<?>> rootsToDelete = new MultiMapBasedOnSet<File, BuildTarget<?>>();
+ final MultiMap<File, BuildTarget<?>> rootsToDelete = MultiMap.createSet();
final Set<File> allSourceRoots = new HashSet<File>();
ProjectDescriptor projectDescriptor = context.getProjectDescriptor();
@@ -859,6 +867,9 @@
// }));
//}
}
+ catch (BuildDataCorruptedException e) {
+ throw e;
+ }
catch (ProjectBuildException e) {
throw e;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java
index 66ba66c..7d2cc28 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/JavaBuilderService.java
@@ -19,6 +19,7 @@
import org.jetbrains.jps.builders.BuildTargetType;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.classFilesIndex.indexer.api.ClassFilesIndicesBuilder;
import org.jetbrains.jps.incremental.instrumentation.NotNullInstrumentingBuilder;
import org.jetbrains.jps.incremental.instrumentation.RmiStubsGenerator;
import org.jetbrains.jps.incremental.java.JavaBuilder;
@@ -45,7 +46,10 @@
@NotNull
@Override
public List<? extends ModuleLevelBuilder> createModuleLevelBuilders() {
- return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()), new NotNullInstrumentingBuilder(), new RmiStubsGenerator());
+ return Arrays.asList(new JavaBuilder(SharedThreadPool.getInstance()),
+ new NotNullInstrumentingBuilder(),
+ new RmiStubsGenerator(),
+ new ClassFilesIndicesBuilder());
}
@NotNull
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java
index 8370c75..036f8e9 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactBuildTarget.java
@@ -121,7 +121,7 @@
ModuleExcludeIndex index,
IgnoredFileIndex ignoredFileIndex,
BuildDataPaths dataPaths) {
- ArtifactInstructionsBuilderImpl builder = new ArtifactInstructionsBuilderImpl(index, ignoredFileIndex, this);
+ ArtifactInstructionsBuilderImpl builder = new ArtifactInstructionsBuilderImpl(index, ignoredFileIndex, this, model, dataPaths);
ArtifactInstructionsBuilderContext context = new ArtifactInstructionsBuilderContextImpl(model, dataPaths);
String outputPath = StringUtil.notNullize(myArtifact.getOutputPath());
final CopyToDirectoryInstructionCreator instructionCreator = new CopyToDirectoryInstructionCreator(builder, outputPath);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
index 0352417..c6b15a7 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
@@ -17,9 +17,12 @@
import com.intellij.openapi.util.Condition;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.service.JpsServiceManager;
import java.io.File;
import java.util.ArrayList;
@@ -34,16 +37,25 @@
private final Map<String, JarInfo> myJarByPath;
private final List<ArtifactRootDescriptor> myDescriptors;
private final ModuleExcludeIndex myRootsIndex;
+ private final Iterable<ArtifactRootCopyingHandlerProvider> myCopyingHandlerProviders;
private int myRootIndex;
private final IgnoredFileIndex myIgnoredFileIndex;
private ArtifactBuildTarget myBuildTarget;
+ private final JpsModel myModel;
+ private final BuildDataPaths myBuildDataPaths;
- public ArtifactInstructionsBuilderImpl(ModuleExcludeIndex rootsIndex, IgnoredFileIndex ignoredFileIndex, ArtifactBuildTarget target) {
+ public ArtifactInstructionsBuilderImpl(@NotNull ModuleExcludeIndex rootsIndex,
+ @NotNull IgnoredFileIndex ignoredFileIndex,
+ @NotNull ArtifactBuildTarget target,
+ @NotNull JpsModel model, @NotNull BuildDataPaths dataPaths) {
myRootsIndex = rootsIndex;
myIgnoredFileIndex = ignoredFileIndex;
myBuildTarget = target;
+ myModel = model;
+ myBuildDataPaths = dataPaths;
myJarByPath = new HashMap<String, JarInfo>();
myDescriptors = new ArrayList<ArtifactRootDescriptor>();
+ myCopyingHandlerProviders = JpsServiceManager.getInstance().getExtensions(ArtifactRootCopyingHandlerProvider.class);
}
public IgnoredFileIndex getIgnoredFileIndex() {
@@ -74,8 +86,19 @@
public FileBasedArtifactRootDescriptor createFileBasedRoot(@NotNull File file,
@NotNull SourceFileFilter filter,
- final DestinationInfo destinationInfo) {
- return new FileBasedArtifactRootDescriptor(file, filter, myRootIndex++, myBuildTarget, destinationInfo);
+ final @NotNull DestinationInfo destinationInfo) {
+ FileCopyingHandler handler = createCopyingHandler(file);
+ return new FileBasedArtifactRootDescriptor(file, filter, myRootIndex++, myBuildTarget, destinationInfo, handler);
+ }
+
+ private FileCopyingHandler createCopyingHandler(File file) {
+ for (ArtifactRootCopyingHandlerProvider provider : myCopyingHandlerProviders) {
+ FileCopyingHandler handler = provider.createCustomHandler(myBuildTarget.getArtifact(), file, myModel, myBuildDataPaths);
+ if (handler != null) {
+ return handler;
+ }
+ }
+ return FileCopyingHandler.DEFAULT;
}
public JarBasedArtifactRootDescriptor createJarBasedRoot(@NotNull File jarFile,
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootCopyingHandlerProvider.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootCopyingHandlerProvider.java
new file mode 100644
index 0000000..fecaa16
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootCopyingHandlerProvider.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.incremental.artifacts.instructions;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.io.File;
+
+/**
+ * @author nik
+ */
+public abstract class ArtifactRootCopyingHandlerProvider {
+ @Nullable
+ public abstract FileCopyingHandler createCustomHandler(@NotNull JpsArtifact artifact, @NotNull File root, @NotNull JpsModel model,
+ @NotNull BuildDataPaths buildDataPaths);
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
index 71eb66d..09a46cc 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
@@ -17,9 +17,11 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ProjectBuildException;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
@@ -28,7 +30,9 @@
import org.jetbrains.jps.incremental.artifacts.impl.JpsArtifactPathUtil;
import java.io.File;
+import java.io.FileFilter;
import java.io.IOException;
+import java.io.PrintWriter;
import java.util.Collections;
/**
@@ -36,12 +40,21 @@
*/
public class FileBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
private static final Logger LOG = Logger.getInstance(FileBasedArtifactRootDescriptor.class);
+ private FileCopyingHandler myCopyingHandler;
+
public FileBasedArtifactRootDescriptor(@NotNull File file,
@NotNull SourceFileFilter filter,
int index,
ArtifactBuildTarget target,
- @NotNull DestinationInfo destinationInfo) {
- super(file, filter, index, target, destinationInfo);
+ @NotNull DestinationInfo destinationInfo, FileCopyingHandler copyingHandler) {
+ super(file, createCompositeFilter(filter, copyingHandler.createFileFilter()), index, target, destinationInfo);
+ myCopyingHandler = copyingHandler;
+ }
+
+ @NotNull
+ private static SourceFileFilter createCompositeFilter(@NotNull final SourceFileFilter baseFilter, @NotNull final FileFilter filter) {
+ if (filter.equals(FileUtilRt.ALL_FILES)) return baseFilter;
+ return new CompositeSourceFileFilter(baseFilter, filter);
}
@Override
@@ -49,6 +62,12 @@
return myRoot.getPath();
}
+ @Override
+ public void writeConfiguration(PrintWriter out) {
+ super.writeConfiguration(out);
+ myCopyingHandler.writeConfiguration(out);
+ }
+
public void copyFromRoot(String filePath,
int rootIndex, String outputPath,
CompileContext context, BuildOutputConsumer outputConsumer,
@@ -78,7 +97,7 @@
if (logger.isEnabled()) {
logger.logCompiledFiles(Collections.singletonList(file), IncArtifactBuilder.BUILDER_NAME, "Copying file:");
}
- FileUtil.copyContent(file, targetFile);
+ myCopyingHandler.copyFile(file, targetFile, context);
outputConsumer.registerOutputFile(targetFile, Collections.singletonList(filePath));
}
else if (LOG.isDebugEnabled()) {
@@ -86,4 +105,24 @@
}
outSrcMapping.appendData(targetPath, rootIndex, filePath);
}
+
+ private static class CompositeSourceFileFilter extends SourceFileFilter {
+ private final SourceFileFilter myBaseFilter;
+ private final FileFilter myFilter;
+
+ public CompositeSourceFileFilter(SourceFileFilter baseFilter, FileFilter filter) {
+ myBaseFilter = baseFilter;
+ myFilter = filter;
+ }
+
+ @Override
+ public boolean accept(@NotNull String fullFilePath) {
+ return myFilter.accept(new File(fullFilePath)) && myBaseFilter.accept(fullFilePath);
+ }
+
+ @Override
+ public boolean shouldBeCopied(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException {
+ return myBaseFilter.shouldBeCopied(fullFilePath, projectDescriptor);
+ }
+ }
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileCopyingHandler.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileCopyingHandler.java
new file mode 100644
index 0000000..da3d7e8
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileCopyingHandler.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 org.jetbrains.jps.incremental.artifacts.instructions;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.incremental.CompileContext;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author nik
+ */
+public abstract class FileCopyingHandler {
+ public static final FileCopyingHandler DEFAULT = new FileCopyingHandler() {
+ @Override
+ public void copyFile(@NotNull File from, @NotNull File to, @NotNull CompileContext context) throws IOException {
+ FileUtil.copyContent(from, to);
+ }
+
+ @Override
+ public void writeConfiguration(@NotNull PrintWriter out) {
+ }
+ };
+
+ public abstract void copyFile(@NotNull File from, @NotNull File to, @NotNull CompileContext context) throws IOException;
+
+ public abstract void writeConfiguration(@NotNull PrintWriter out);
+
+ @NotNull
+ public FileFilter createFileFilter() {
+ return FileUtilRt.ALL_FILES;
+ }
+}
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 dcc97f4..645cdd6 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
@@ -43,6 +43,7 @@
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
import org.jetbrains.jps.builders.java.dependencyView.Mappings;
import org.jetbrains.jps.builders.logging.ProjectBuilderLogger;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.*;
import org.jetbrains.jps.incremental.messages.BuildMessage;
@@ -191,6 +192,9 @@
return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer);
}
+ catch (BuildDataCorruptedException e) {
+ throw e;
+ }
catch (ProjectBuildException e) {
throw e;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
index 187d7d1..e481a02 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
@@ -22,7 +22,10 @@
import org.jetbrains.asm4.ClassReader;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
-import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.BinaryContent;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.CompiledClass;
+import org.jetbrains.jps.incremental.ModuleLevelBuilder;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
@@ -84,7 +87,7 @@
}
}
- if (!isTemp && outKind == JavaFileObject.Kind.CLASS && !Utils.errorsDetected(myContext)) {
+ if (!isTemp && outKind == JavaFileObject.Kind.CLASS) {
// register in mappings any non-temp class file
try {
final ClassReader reader = new ClassReader(content.getBuffer(), content.getOffset(), content.getLength());
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
index 809eafd..57524ac 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
@@ -23,6 +23,7 @@
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
import org.jetbrains.jps.builders.java.ResourcesTargetType;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ProjectBuildException;
import org.jetbrains.jps.incremental.ResourcesTarget;
@@ -96,6 +97,9 @@
context.processMessage(new ProgressMessage(""));
}
+ catch(BuildDataCorruptedException e) {
+ throw e;
+ }
catch(ProjectBuildException e) {
throw e;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
index c8fb9b9..d66144d 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildDataManager.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataCorruptedException;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.impl.BuildTargetChunk;
import org.jetbrains.jps.builders.impl.storage.BuildTargetStorages;
@@ -101,7 +102,7 @@
return new SourceToOutputMappingImpl(new File(getSourceToOutputMapRoot(key), "data"));
}
catch (IOException e) {
- throw new RuntimeException(e);
+ throw new BuildDataCorruptedException(e);
}
}
};
@@ -236,12 +237,8 @@
try {
mappings.close();
}
- catch (RuntimeException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- throw ((IOException)cause);
- }
- throw e;
+ catch (BuildDataCorruptedException e) {
+ throw e.getCause();
}
}
}
@@ -294,12 +291,8 @@
try {
return lazy.getValue();
}
- catch (RuntimeException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof IOException) {
- throw (IOException)cause;
- }
- throw e;
+ catch (BuildDataCorruptedException e) {
+ throw e.getCause();
}
}
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 b901f95..b5dc9ba 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacServer.java
@@ -72,6 +72,7 @@
}
public static void main(String[] args) {
+ JavacServer server = null;
try {
int port = DEFAULT_SERVER_PORT;
if (args.length > 0) {
@@ -84,12 +85,13 @@
}
}
- final JavacServer server = new JavacServer();
+ server = new JavacServer();
server.start(port);
+ final JavacServer finalServer = server;
Runtime.getRuntime().addShutdownHook(new Thread("Shutdown hook thread") {
@Override
public void run() {
- server.stop();
+ finalServer.stop();
}
});
@@ -99,7 +101,14 @@
catch (Throwable e) {
System.err.println(SERVER_ERROR_START_MESSAGE + e.getMessage());
e.printStackTrace(System.err);
- System.exit(-1);
+ try {
+ if (server != null) {
+ server.stop();
+ }
+ }
+ finally {
+ System.exit(-1);
+ }
}
}
@@ -175,7 +184,7 @@
@ChannelHandler.Sharable
private class CompilationRequestsHandler extends SimpleChannelInboundHandler<JavacRemoteProto.Message> {
@Override
- public void channelRead0(final ChannelHandlerContext context, JavacRemoteProto.Message message) throws Exception {
+ public void messageReceived(final ChannelHandlerContext context, JavacRemoteProto.Message message) throws Exception {
final UUID sessionId = JavacProtoUtil.fromProtoUUID(message.getSessionId());
final JavacRemoteProto.Message.Type messageType = message.getMessageType();
@@ -252,7 +261,7 @@
}
@ChannelHandler.Sharable
- private static final class ChannelRegistrar extends ChannelInboundHandlerAdapter {
+ private static final class ChannelRegistrar extends ChannelHandlerAdapter {
private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
public boolean isEmpty() {
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
index 5af8263..7c10239 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/rebuild/JpsRebuildTestCase.groovy
@@ -17,6 +17,7 @@
import com.intellij.openapi.application.ex.PathManagerEx
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.io.TestFileSystemBuilder
+import org.jetbrains.annotations.NotNull
import org.jetbrains.jps.util.JpsPathUtil
import org.jetbrains.jps.builders.JpsBuildTestCase
import org.jetbrains.jps.model.java.JpsJavaExtensionService
@@ -41,7 +42,7 @@
assertOutput(getOrCreateOutputDirectory().getAbsolutePath(), expectedOutput);
}
- def protected assertOutput(String targetFolder, Closure expectedOutput) {
+ def protected assertOutput(@NotNull String targetFolder, Closure expectedOutput) {
def root = TestFileSystemBuilder.fs()
initFileSystemItem(root, expectedOutput)
root.build().assertDirectoryEqual(new File(FileUtil.toSystemDependentName(targetFolder)))
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java b/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java
index 2f5aaa6..9cca7dc 100644
--- a/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/JdkVersionDetector.java
@@ -15,6 +15,8 @@
*/
package org.jetbrains.jps.model.java;
+import com.intellij.openapi.util.Bitness;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.service.JpsServiceManager;
@@ -35,6 +37,13 @@
public abstract String detectJdkVersion(String homePath, ActionRunner actionRunner);
@Nullable
+ public abstract JdkVersionInfo detectJdkVersionInfo(String homePath);
+
+ @Nullable
+ public abstract JdkVersionInfo detectJdkVersionInfo(String homePath, ActionRunner actionRunner);
+
+ @Deprecated
+ @Nullable
public abstract String readVersionFromProcessOutput(String homePath, String[] command, String versionLineMarker,
ActionRunner actionRunner);
@@ -42,4 +51,24 @@
public interface ActionRunner {
Future<?> run(Runnable runnable);
}
+
+ public static final class JdkVersionInfo {
+ private final String myVersion;
+ private final Bitness myBitness;
+
+ public JdkVersionInfo(@NotNull String version, @NotNull Bitness bitness) {
+ myVersion = version;
+ myBitness = bitness;
+ }
+
+ @NotNull
+ public String getVersion() {
+ return myVersion;
+ }
+
+ @NotNull
+ public Bitness getBitness() {
+ return myBitness;
+ }
+ }
}
diff --git a/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java b/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java
index 8758bfc..bd57584 100644
--- a/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java
+++ b/jps/model-api/src/org/jetbrains/jps/util/JpsPathUtil.java
@@ -17,7 +17,9 @@
import com.intellij.openapi.util.SystemInfoRt;
import com.intellij.openapi.util.io.FileUtilRt;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.util.Set;
@@ -45,12 +47,16 @@
return new File(urlToOsPath(url));
}
- public static String urlToOsPath(String url) {
+ @NotNull
+ public static String urlToOsPath(@NotNull String url) {
return FileUtilRt.toSystemDependentName(urlToPath(url));
}
- public static String urlToPath(String url) {
- if (url == null) return null;
+ @Contract("null -> null; !null -> !null")
+ public static String urlToPath(@Nullable String url) {
+ if (url == null) {
+ return null;
+ }
if (url.startsWith("file://")) {
return url.substring("file://".length());
}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java
index fecb068..ef4ae25 100644
--- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/JdkVersionDetectorImpl.java
@@ -16,12 +16,14 @@
package org.jetbrains.jps.model.java.impl;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Bitness;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.JdkVersionDetector;
import org.jetbrains.jps.service.SharedThreadPool;
import java.io.*;
import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicReference;
/**
* @author nik
@@ -43,20 +45,41 @@
@Nullable
public String detectJdkVersion(String homePath, final ActionRunner actionRunner) {
+ JdkVersionInfo info = detectJdkVersionInfo(homePath, actionRunner);
+ if (info != null) {
+ return info.getVersion();
+ }
+ return null;
+ }
+
+ @Override
+ public JdkVersionInfo detectJdkVersionInfo(String homePath) {
+ return detectJdkVersionInfo(homePath, ACTION_RUNNER);
+ }
+
+ @Override
+ public JdkVersionInfo detectJdkVersionInfo(String homePath, ActionRunner actionRunner) {
String[] command = {homePath + File.separator + "bin" + File.separator + "java", "-version"};
- return readVersionFromProcessOutput(homePath, command, "version", actionRunner);
+ return readVersionInfoFromProcessOutput(homePath, command, null, actionRunner);
}
public String readVersionFromProcessOutput(String homePath, String[] command, String versionLineMarker,
- ActionRunner actionRunner) {
+ ActionRunner actionRunner) {
+ JdkVersionInfo info = readVersionInfoFromProcessOutput(homePath, command, versionLineMarker, actionRunner);
+ if (info != null) {
+ return info.getVersion();
+ }
+ return null;
+ }
+
+ private static JdkVersionInfo readVersionInfoFromProcessOutput(String homePath, String[] command, String versionLineMarker, ActionRunner actionRunner) {
if (homePath == null || !new File(homePath).exists()) {
return null;
}
- final String[] versionString = new String[1];
try {
//noinspection HardCodedStringLiteral
Process process = Runtime.getRuntime().exec(command);
- VersionParsingThread parsingThread = new VersionParsingThread(process.getErrorStream(), versionString, versionLineMarker);
+ VersionParsingThread parsingThread = new VersionParsingThread(process.getErrorStream(), versionLineMarker);
final Future<?> parsingThreadFuture = actionRunner.run(parsingThread);
ReadStreamThread readThread = new ReadStreamThread(process.getInputStream());
actionRunner.run(readThread);
@@ -78,11 +101,15 @@
LOG.info(e);
}
}
+ String version = parsingThread.getVersion();
+ if (version != null) {
+ return new JdkVersionInfo(version, parsingThread.getBitness());
+ }
}
catch (IOException ex) {
LOG.info(ex);
}
- return versionString[0];
+ return null;
}
public static class ReadStreamThread implements Runnable {
@@ -109,13 +136,24 @@
private Reader myReader;
private final InputStream myStream;
private boolean mySkipLF = false;
- private final String[] myVersionString;
private final String myVersionLineMarker;
- protected VersionParsingThread(InputStream input, String[] versionString, String versionLineMarker) {
+ private final AtomicReference<String> myVersionString = new AtomicReference<String>();
+ private final AtomicReference<Bitness> myBitness = new AtomicReference<Bitness>(Bitness.x32);
+ private static final String VERSION_LINE_MARKER = "version";
+ private static final String BITNESS_64_MARKER = "64-Bit";
+
+ protected VersionParsingThread(InputStream input, String versionLineMarker) {
myStream = input;
- myVersionString = versionString;
- myVersionLineMarker = versionLineMarker;
+ myVersionLineMarker = versionLineMarker != null ? versionLineMarker : VERSION_LINE_MARKER;
+ }
+
+ Bitness getBitness() {
+ return myBitness.get();
+ }
+
+ String getVersion() {
+ return myVersionString.get();
}
public void run() {
@@ -125,7 +163,10 @@
String line = readLine();
if (line == null) return;
if (line.contains(myVersionLineMarker)) {
- myVersionString[0] = line;
+ myVersionString.set(line);
+ }
+ if (line.contains(BITNESS_64_MARKER)) {
+ myBitness.set(Bitness.x64);
}
}
}
diff --git a/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java b/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java
index ac01871..5f66757 100644
--- a/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java
+++ b/jps/model-serialization/src/com/intellij/openapi/components/ExpandMacroToPathMap.java
@@ -48,6 +48,10 @@
//noinspection ConstantConditions
return null;
}
+
+ if (text.indexOf('$') < 0) {
+ return text;
+ }
for (Map.Entry<String, String> entry : myPlainMap.entrySet()) {
// when replacing macros with actual paths the replace utility may be used as always 'case-sensitive'
diff --git a/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java b/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java
index 22500b2..8960523 100644
--- a/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java
+++ b/jps/model-serialization/src/com/intellij/openapi/components/PathMacroMap.java
@@ -43,9 +43,13 @@
else if (child instanceof Text) {
Text t = (Text)child;
if (filter == null || !filter.skipPathMacros(t)) {
- t.setText((recursively || (filter != null && filter.recursePathMacros(t)))
- ? substituteRecursively(t.getText(), caseSensitive)
- : substitute(t.getText(), caseSensitive));
+ String oldText = t.getText();
+ String newText = (recursively || (filter != null && filter.recursePathMacros(t)))
+ ? substituteRecursively(oldText, caseSensitive)
+ : substitute(oldText, caseSensitive);
+ if (oldText != newText) {
+ t.setText(newText);
+ }
}
}
else if (!(child instanceof Comment)) {
@@ -55,9 +59,13 @@
for (Attribute attribute : e.getAttributes()) {
if (filter == null || !filter.skipPathMacros(attribute)) {
- attribute.setValue((recursively || (filter != null && filter.recursePathMacros(attribute)))
- ? substituteRecursively(attribute.getValue(), caseSensitive)
- : substitute(attribute.getValue(), caseSensitive));
+ String oldValue = attribute.getValue();
+ String newValue = (recursively || (filter != null && filter.recursePathMacros(attribute)))
+ ? substituteRecursively(oldValue, caseSensitive)
+ : substitute(oldValue, caseSensitive);
+ if (oldValue != newValue) {
+ attribute.setValue(newValue);
+ }
}
}
}
diff --git a/jps/standalone-builder/jps-standalone-builder.iml b/jps/standalone-builder/jps-standalone-builder.iml
index 56631f2..11b0323 100644
--- a/jps/standalone-builder/jps-standalone-builder.iml
+++ b/jps/standalone-builder/jps-standalone-builder.iml
@@ -16,7 +16,7 @@
<orderEntry type="module-library" scope="PROVIDED">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/../../build/lib/gant/lib/gant_groovy2.0-1.9.8.jar!/" />
+ <root url="jar://$MODULE_DIR$/../../build/lib/gant/lib/gant_groovy2.1-1.9.10.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
diff --git a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java
index a4b7357..979fd78 100644
--- a/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java
+++ b/jps/standalone-builder/src/org/jetbrains/jps/build/Standalone.java
@@ -61,6 +61,9 @@
@Argument(value = "artifacts", prefix = "--", delimiter = ",", description = "Comma-separated list of artifacts to build")
public String[] artifacts = ArrayUtil.EMPTY_STRING_ARRAY;
+ @Argument(value = "all-artifacts", prefix = "--", description = "Build all artifacts")
+ public boolean allArtifacts;
+
@Argument(value = "i", description = "Build incrementally")
public boolean incremental;
@@ -115,8 +118,8 @@
initializer = new GroovyModelInitializer(scriptFile);
}
- if (modules.length == 0 && artifacts.length == 0 && !allModules) {
- System.err.println("Nothing to compile: at least one of --modules, --artifacts or --all-modules parameters must be specified");
+ if (modules.length == 0 && artifacts.length == 0 && !allModules && !allArtifacts) {
+ System.err.println("Nothing to compile: at least one of --modules, --artifacts, --all-modules or --all-artifacts parameters must be specified");
return;
}
@@ -137,7 +140,7 @@
long start = System.currentTimeMillis();
try {
- runBuild(loader, dataStorageRoot, !incremental, modulesSet, allModules, artifactsList, true, new ConsoleMessageHandler());
+ runBuild(loader, dataStorageRoot, !incremental, modulesSet, allModules, artifactsList, allArtifacts, true, new ConsoleMessageHandler());
}
catch (Throwable t) {
System.err.println("Internal error: " + t.getMessage());
@@ -155,6 +158,12 @@
public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet,
final boolean allModules, List<String> artifactsList, final boolean includeTests,
final MessageHandler messageHandler) throws Exception {
+ runBuild(loader, dataStorageRoot, forceBuild, modulesSet, allModules, artifactsList, false, includeTests, messageHandler);
+ }
+
+ public static void runBuild(JpsModelLoader loader, final File dataStorageRoot, boolean forceBuild, Set<String> modulesSet,
+ final boolean allModules, List<String> artifactsList, boolean allArtifacts, final boolean includeTests,
+ final MessageHandler messageHandler) throws Exception {
List<TargetTypeBuildScope> scopes = new ArrayList<TargetTypeBuildScope>();
for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
if (includeTests || !type.isTests()) {
@@ -167,9 +176,16 @@
}
}
}
- if (!artifactsList.isEmpty()) {
- scopes.add(TargetTypeBuildScope.newBuilder().setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId())
- .setForceBuild(forceBuild).addAllTargetId(artifactsList).build());
+
+ TargetTypeBuildScope.Builder builder = TargetTypeBuildScope.newBuilder()
+ .setTypeId(ArtifactBuildTargetType.INSTANCE.getTypeId())
+ .setForceBuild(forceBuild);
+
+ if (allArtifacts) {
+ scopes.add(builder.setAllTargets(true).build());
+ }
+ else if (!artifactsList.isEmpty()) {
+ scopes.add(builder.addAllTargetId(artifactsList).build());
}
runBuild(loader, dataStorageRoot, messageHandler, scopes, true);
diff --git a/lib/commons-logging-1.1.1.jar b/lib/commons-logging-1.1.1.jar
deleted file mode 100644
index 1deef14..0000000
--- a/lib/commons-logging-1.1.1.jar
+++ /dev/null
Binary files differ
diff --git a/lib/commons-logging-1.1.3.jar b/lib/commons-logging-1.1.3.jar
new file mode 100644
index 0000000..ab51254
--- /dev/null
+++ b/lib/commons-logging-1.1.3.jar
Binary files differ
diff --git a/lib/fluent-hc-4.3.1.jar b/lib/fluent-hc-4.3.1.jar
new file mode 100644
index 0000000..d0e9e86
--- /dev/null
+++ b/lib/fluent-hc-4.3.1.jar
Binary files differ
diff --git a/lib/groovy-all-2.0.6.jar b/lib/groovy-all-2.0.6.jar
deleted file mode 100644
index ed8e33a..0000000
--- a/lib/groovy-all-2.0.6.jar
+++ /dev/null
Binary files differ
diff --git a/lib/groovy-all-2.2.1.jar b/lib/groovy-all-2.2.1.jar
new file mode 100644
index 0000000..8d15127
--- /dev/null
+++ b/lib/groovy-all-2.2.1.jar
Binary files differ
diff --git a/lib/gson-2.2.3.jar b/lib/gson-2.2.3.jar
deleted file mode 100644
index a4e18be..0000000
--- a/lib/gson-2.2.3.jar
+++ /dev/null
Binary files differ
diff --git a/lib/gson-2.2.4.jar b/lib/gson-2.2.4.jar
new file mode 100644
index 0000000..9478253
--- /dev/null
+++ b/lib/gson-2.2.4.jar
Binary files differ
diff --git a/lib/hamcrest-core-1.3.jar b/lib/hamcrest-core-1.3.jar
new file mode 100644
index 0000000..9d5fe16
--- /dev/null
+++ b/lib/hamcrest-core-1.3.jar
Binary files differ
diff --git a/lib/hamcrest-library-1.3.jar b/lib/hamcrest-library-1.3.jar
new file mode 100644
index 0000000..9eac80d
--- /dev/null
+++ b/lib/hamcrest-library-1.3.jar
Binary files differ
diff --git a/lib/httpclient-4.3.1.jar b/lib/httpclient-4.3.1.jar
new file mode 100644
index 0000000..9b47364
--- /dev/null
+++ b/lib/httpclient-4.3.1.jar
Binary files differ
diff --git a/lib/httpcore-4.3.jar b/lib/httpcore-4.3.jar
new file mode 100644
index 0000000..e5da457
--- /dev/null
+++ b/lib/httpcore-4.3.jar
Binary files differ
diff --git a/lib/httpmime-4.3.1.jar b/lib/httpmime-4.3.1.jar
new file mode 100644
index 0000000..f6ee60e
--- /dev/null
+++ b/lib/httpmime-4.3.1.jar
Binary files differ
diff --git a/lib/jayatana-1.2.4.jar b/lib/jayatana-1.2.4.jar
index 8f73939..e7ac9f3 100644
--- a/lib/jayatana-1.2.4.jar
+++ b/lib/jayatana-1.2.4.jar
Binary files differ
diff --git a/lib/junit-4.10.jar b/lib/junit-4.10.jar
deleted file mode 100644
index bf5c0b9..0000000
--- a/lib/junit-4.10.jar
+++ /dev/null
Binary files differ
diff --git a/lib/junit-4.11.jar b/lib/junit-4.11.jar
new file mode 100644
index 0000000..aaf7444
--- /dev/null
+++ b/lib/junit-4.11.jar
Binary files differ
diff --git a/lib/kryo-1.04.jar b/lib/kryo-1.04.jar
deleted file mode 100755
index faa2cc2..0000000
--- a/lib/kryo-1.04.jar
+++ /dev/null
Binary files differ
diff --git a/lib/kryo-2.22.jar b/lib/kryo-2.22.jar
new file mode 100755
index 0000000..26d0d10
--- /dev/null
+++ b/lib/kryo-2.22.jar
Binary files differ
diff --git a/lib/netty-all-4.1.0.Alpha1.jar b/lib/netty-all-4.1.0.Alpha1.jar
deleted file mode 100644
index 35863fd..0000000
--- a/lib/netty-all-4.1.0.Alpha1.jar
+++ /dev/null
Binary files differ
diff --git a/lib/netty-all-5.0.0.Alpha1.jar b/lib/netty-all-5.0.0.Alpha1.jar
new file mode 100644
index 0000000..ff0afa0
--- /dev/null
+++ b/lib/netty-all-5.0.0.Alpha1.jar
Binary files differ
diff --git a/lib/objenesis-1.2.jar b/lib/objenesis-1.2.jar
new file mode 100755
index 0000000..45cb641
--- /dev/null
+++ b/lib/objenesis-1.2.jar
Binary files differ
diff --git a/lib/reflectasm-1.01.jar b/lib/reflectasm-1.01.jar
deleted file mode 100755
index 71b5550..0000000
--- a/lib/reflectasm-1.01.jar
+++ /dev/null
Binary files differ
diff --git a/lib/reflectasm-1.07.jar b/lib/reflectasm-1.07.jar
new file mode 100755
index 0000000..d5c31a4
--- /dev/null
+++ b/lib/reflectasm-1.07.jar
Binary files differ
diff --git a/lib/required_for_dist.txt b/lib/required_for_dist.txt
index 5f749bc..4085f88 100644
--- a/lib/required_for_dist.txt
+++ b/lib/required_for_dist.txt
@@ -6,12 +6,18 @@
cli-parser-1.1.jar
commons-codec-1.8.jar
commons-httpclient-3.1-patched.jar
-commons-logging-1.1.1.jar
+commons-logging-1.1.3.jar
commons-net-3.1.jar
+httpcore-4.3.jar
+httpclient-4.3.1.jar
+fluent-hc-4.3.1.jar
+httpmime-4.3.1.jar
ecj-4.2.1.jar
-groovy-all-2.0.6.jar
-gson-2.2.3.jar
+groovy-all-2.2.1.jar
+gson-2.2.4.jar
guava-14.0.1.jar
+hamcrest-core-1.3.jar
+hamcrest-library-1.3.jar
jaxen-1.1.3.jar
jayatana-1.2.4.jar
jcip-annotations.jar
@@ -25,7 +31,7 @@
jsch-0.1.50.jar
jsr166e.jar
jsr173_1.0_api.jar
-junit-4.10.jar
+junit-4.11.jar
junit.jar
jzlib-1.1.1.jar
log4j.jar
@@ -34,7 +40,7 @@
miglayout-swing.jar
nanoxml-2.2.3.jar
nekohtml-1.9.14.jar
-netty-all-4.1.0.Alpha1.jar
+netty-all-5.0.0.Alpha1.jar
oromatcher.jar
picocontainer.jar
protobuf-2.5.0.jar
diff --git a/lib/src/commons-logging-1.1.1-src.zip b/lib/src/commons-logging-1.1.1-src.zip
deleted file mode 100644
index 885f130..0000000
--- a/lib/src/commons-logging-1.1.1-src.zip
+++ /dev/null
Binary files differ
diff --git a/lib/src/commons-logging-1.1.3-src.zip b/lib/src/commons-logging-1.1.3-src.zip
new file mode 100644
index 0000000..9fa84bf
--- /dev/null
+++ b/lib/src/commons-logging-1.1.3-src.zip
Binary files differ
diff --git a/lib/src/groovy-src-2.0.6.zip b/lib/src/groovy-src-2.0.6.zip
deleted file mode 100644
index acdd4bd..0000000
--- a/lib/src/groovy-src-2.0.6.zip
+++ /dev/null
Binary files differ
diff --git a/lib/src/groovy-src-2.2.1.zip b/lib/src/groovy-src-2.2.1.zip
new file mode 100644
index 0000000..c11ab96
--- /dev/null
+++ b/lib/src/groovy-src-2.2.1.zip
Binary files differ
diff --git a/lib/src/gson-2.2.3-sources.jar b/lib/src/gson-2.2.3-sources.jar
deleted file mode 100644
index c7a0148..0000000
--- a/lib/src/gson-2.2.3-sources.jar
+++ /dev/null
Binary files differ
diff --git a/lib/src/gson-2.2.4-sources.jar b/lib/src/gson-2.2.4-sources.jar
new file mode 100644
index 0000000..30b13f6
--- /dev/null
+++ b/lib/src/gson-2.2.4-sources.jar
Binary files differ
diff --git a/lib/src/hamcrest-1.3-src.zip b/lib/src/hamcrest-1.3-src.zip
new file mode 100644
index 0000000..1176fa5
--- /dev/null
+++ b/lib/src/hamcrest-1.3-src.zip
Binary files differ
diff --git a/lib/src/httpcomponents-client-4.3.1-src.zip b/lib/src/httpcomponents-client-4.3.1-src.zip
new file mode 100644
index 0000000..6511fb6
--- /dev/null
+++ b/lib/src/httpcomponents-client-4.3.1-src.zip
Binary files differ
diff --git a/lib/src/httpcomponents-core-4.3-src.zip b/lib/src/httpcomponents-core-4.3-src.zip
new file mode 100644
index 0000000..6e1fb24
--- /dev/null
+++ b/lib/src/httpcomponents-core-4.3-src.zip
Binary files differ
diff --git a/lib/src/jayatana-1.2.4-src.zip b/lib/src/jayatana-1.2.4-src.zip
index a60cda1..bd8fde8 100644
--- a/lib/src/jayatana-1.2.4-src.zip
+++ b/lib/src/jayatana-1.2.4-src.zip
Binary files differ
diff --git a/lib/src/junit-4.10-src.jar b/lib/src/junit-4.10-src.jar
deleted file mode 100644
index 1449d28..0000000
--- a/lib/src/junit-4.10-src.jar
+++ /dev/null
Binary files differ
diff --git a/lib/src/junit-4.11-src.jar b/lib/src/junit-4.11-src.jar
new file mode 100644
index 0000000..8080156
--- /dev/null
+++ b/lib/src/junit-4.11-src.jar
Binary files differ
diff --git a/lib/src/kryo-src.zip b/lib/src/kryo-src.zip
index d16fe3a..ea6485a 100644
--- a/lib/src/kryo-src.zip
+++ b/lib/src/kryo-src.zip
Binary files differ
diff --git a/lib/src/netty-all-5.0.0.Alpha1-sources.jar b/lib/src/netty-all-5.0.0.Alpha1-sources.jar
new file mode 100644
index 0000000..767b4fb
--- /dev/null
+++ b/lib/src/netty-all-5.0.0.Alpha1-sources.jar
Binary files differ
diff --git a/lib/src/netty-all-sources.jar b/lib/src/netty-all-sources.jar
deleted file mode 100644
index 587f0d9..0000000
--- a/lib/src/netty-all-sources.jar
+++ /dev/null
Binary files differ
diff --git a/license/javolution_license.txt b/license/javolution_license.txt
new file mode 100644
index 0000000..900c442
--- /dev/null
+++ b/license/javolution_license.txt
@@ -0,0 +1,27 @@
+/*
+ * Javolution - Java(tm) Solution for Real-Time and Embedded Systems
+ * Copyright (c) 2012, Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
diff --git a/native/libnotifywrapper/LibNotifyWrapper.c b/native/libnotifywrapper/LibNotifyWrapper.c
new file mode 100644
index 0000000..e612f8b
--- /dev/null
+++ b/native/libnotifywrapper/LibNotifyWrapper.c
@@ -0,0 +1,52 @@
+#include "com_intellij_ui_LibNotifyWrapper.h"
+#include <dlfcn.h>
+
+/*
+ * Class: com_intellij_ui_LibNotifyWrapper
+ * Method: showNotification
+ * Signature: (Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_intellij_ui_LibNotifyWrapper_showNotification
+ (JNIEnv * jEnv, jclass c, jstring jTitle, jstring jDescription, jstring jLogoPath) {
+
+ void *handle;
+ gboolean (*notify_init_func)(const char *app_name);
+ void (*notify_uninit_func)();
+ NotifyNotification* (*notify_notification_new_func) (const char *summary,
+ const char *body,
+ const char *icon);
+ gboolean (*notify_notification_show_func) (NotifyNotification *notification,
+ GError **error);
+ char *error;
+
+ dlerror();
+
+ handle = dlopen("libnotify.so", RTLD_LAZY);
+
+ if ((error = dlerror()) != NULL)
+ {
+ (*jEnv)->ThrowNew(jEnv, (*jEnv)->FindClass(jEnv, "java/lang/UnsatisfiedLinkError"), error);
+ return;
+ }
+
+ dlerror();
+
+ *(void **) (¬ify_init_func) = dlsym(handle, "notify_init");
+ *(void **) (¬ify_uninit_func) = dlsym(handle, "notify_init");
+ *(void **) (¬ify_notification_new_func) = dlsym(handle, "notify_notification_new");
+ *(void **) (¬ify_notification_show_func) = dlsym(handle, "notify_notification_show");
+
+ (*notify_init_func) ("JetBrains");
+
+ const char *title = (*jEnv)->GetStringUTFChars(jEnv, jTitle, 0);
+ const char *description = (*jEnv)->GetStringUTFChars(jEnv, jDescription, 0);
+ const char *logoPath = (*jEnv)->GetStringUTFChars(jEnv, jLogoPath, 0);
+ NotifyNotification * notification = (*notify_notification_new_func) (title, description, logoPath);
+ (*notify_notification_show_func) (notification, NULL);
+ (*notify_uninit_func)();
+ (*jEnv)->ReleaseStringUTFChars(jEnv, jTitle, title);
+ (*jEnv)->ReleaseStringUTFChars(jEnv, jDescription, description);
+ (*jEnv)->ReleaseStringUTFChars(jEnv, jLogoPath, logoPath);
+
+ dlclose(handle);
+}
diff --git a/native/libnotifywrapper/com_intellij_ui_LibNotifyWrapper.h b/native/libnotifywrapper/com_intellij_ui_LibNotifyWrapper.h
new file mode 100644
index 0000000..cb55eca
--- /dev/null
+++ b/native/libnotifywrapper/com_intellij_ui_LibNotifyWrapper.h
@@ -0,0 +1,22 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include <jni.h>
+#include <libnotify/notify.h>
+/* Header for class com_intellij_ui_LibNotifyWrapper */
+
+#ifndef _Included_com_intellij_ui_LibNotifyWrapper
+#define _Included_com_intellij_ui_LibNotifyWrapper
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_intellij_ui_LibNotifyWrapper
+ * Method: showNotification
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_com_intellij_ui_LibNotifyWrapper_showNotification
+ (JNIEnv *, jclass, jstring, jstring, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/native/runner/runnerw/runnerw.cpp b/native/runner/runnerw/runnerw.cpp
index b0b18ac..8936b28 100644
--- a/native/runner/runnerw/runnerw.cpp
+++ b/native/runner/runnerw/runnerw.cpp
@@ -74,44 +74,44 @@
BOOL CtrlHandler(DWORD fdwCtrlType) {
switch (fdwCtrlType) {
case CTRL_C_EVENT:
- return FALSE;
+ return TRUE;
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
CtrlBreak();
return (TRUE);
case CTRL_BREAK_EVENT:
- return FALSE;
+ return TRUE;
default:
return FALSE;
}
}
-struct StdInThreadParams {
- HANDLE hEvent;
- HANDLE write_stdin;
-};
-
-DWORD WINAPI StdInThread(void *param) {
- StdInThreadParams *threadParams = (StdInThreadParams *) param;
+DWORD WINAPI scanStdinThread(void *param) {
+ HANDLE *write_stdin = (HANDLE *) param;
char buf[1];
memset(buf, 0, sizeof(buf));
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
- while (true) {
- DWORD cbRead = 0;
- DWORD cbWrite = 0;
+ BOOL endOfInput = false;
+ while (!endOfInput) {
+ DWORD nBytesRead = 0;
+ DWORD nBytesWritten = 0;
char c;
- ReadFile(hStdin, &c, 1, &cbRead, NULL);
- if (cbRead > 0) {
+ BOOL bResult = ReadFile(hStdin, &c, 1, &nBytesRead, NULL);
+ if (nBytesRead > 0) {
buf[0] = c;
BOOL ctrlBroken = Scan(buf, 1);
- WriteFile(threadParams->write_stdin, buf, 1, &cbWrite, NULL);
- if (ctrlBroken == TRUE) {
- SetEvent(threadParams->hEvent);
- break;
- }
+ WriteFile(*write_stdin, buf, 1, &nBytesWritten, NULL);
+ }
+ else {
+ /*
+ When a synchronous read operation reaches the end of a file,
+ ReadFile returns TRUE and sets *lpNumberOfBytesRead to zero.
+ See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365467(v=vs.85).aspx
+ */
+ endOfInput = bResult;
}
}
return 0;
@@ -195,7 +195,9 @@
char* c_args = new char[args.size() + 1];
strcpy(c_args, args.c_str());
- SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE);
+ if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE) CtrlHandler, TRUE)) {
+ ErrorMessage("SetConsoleCtrlHandler");
+ }
if (!CreateProcess(c_app, // Application name
c_args, // Application arguments
@@ -206,32 +208,22 @@
exit(0);
}
- unsigned long exit = 0;
+ CreateThread(NULL, 0, &scanStdinThread, &write_stdin, 0, NULL);
- HANDLE threadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- StdInThreadParams params;
- params.hEvent = threadEvent;
- params.write_stdin = write_stdin;
-
- CreateThread(NULL, 0, &StdInThread, ¶ms, 0, NULL);
-
- HANDLE objects_to_wait[2];
- objects_to_wait[0] = threadEvent;
- objects_to_wait[1] = pi.hProcess;
+ unsigned long exitCode = 0;
while (true) {
- int rc = WaitForMultipleObjects(2, objects_to_wait, FALSE, INFINITE);
- if (rc == WAIT_OBJECT_0 + 1) {
+ int rc = WaitForSingleObject(pi.hProcess, INFINITE);
+ if (rc == WAIT_OBJECT_0) {
break;
}
}
- GetExitCodeProcess(pi.hProcess, &exit);
+ GetExitCodeProcess(pi.hProcess, &exitCode);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
CloseHandle(newstdin);
CloseHandle(write_stdin);
- return exit;
+ return exitCode;
}
diff --git a/native/runner/runnerw/runnerw.vcxproj b/native/runner/runnerw/runnerw.vcxproj
index abc0927..c346390 100644
--- a/native/runner/runnerw/runnerw.vcxproj
+++ b/native/runner/runnerw/runnerw.vcxproj
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
@@ -12,15 +12,18 @@
</ItemGroup>
<PropertyGroup Label="Globals">
<Keyword>Win32Proj</Keyword>
+ <ProjectGuid>{52ADCA3D-82E9-86CF-9DEC-FF1A4A1B4E15}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
+ <PlatformToolset>v120</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java
index e976b4e..adabfa0 100644
--- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java
+++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScope.java
@@ -345,12 +345,22 @@
final boolean needReadAction) {
if (fileOrDir.isDirectory()) return true;
if (ProjectCoreUtil.isProjectOrWorkspaceFile(fileOrDir)) return true;
- if (projectFileIndex.isInContent(fileOrDir) && (myIncludeTestSource || !projectFileIndex.isInTestSourceContent(fileOrDir))) {
+ if (projectFileIndex.isInContent(fileOrDir) && (myIncludeTestSource || !projectFileIndex.isInTestSourceContent(fileOrDir))
+ && !isInGeneratedSources(fileOrDir, psiManager.getProject())) {
return processFile(fileOrDir, visitor, psiManager, needReadAction);
}
return true;
}
+ private static boolean isInGeneratedSources(@NotNull VirtualFile file, @NotNull Project project) {
+ for (GeneratedSourcesFilter filter : GeneratedSourcesFilter.EP_NAME.getExtensions()) {
+ if (filter.isGeneratedSource(file, project)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private static boolean processFile(@NotNull final VirtualFile fileOrDir,
@NotNull final PsiElementVisitor visitor,
@NotNull final PsiManager psiManager,
diff --git a/platform/analysis-api/src/com/intellij/analysis/AnalysisScopeBundle.java b/platform/analysis-api/src/com/intellij/analysis/AnalysisScopeBundle.java
index cdb72e2..5d3e987 100644
--- a/platform/analysis-api/src/com/intellij/analysis/AnalysisScopeBundle.java
+++ b/platform/analysis-api/src/com/intellij/analysis/AnalysisScopeBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -34,13 +35,12 @@
private AnalysisScopeBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE)String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java
index f8cd9d7..492aa78 100644
--- a/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.java
+++ b/platform/analysis-api/src/com/intellij/codeHighlighting/HighlightDisplayLevel.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.
@@ -56,7 +56,7 @@
for (Map.Entry<HighlightSeverity, HighlightDisplayLevel> entry : ourMap.entrySet()) {
HighlightSeverity severity = entry.getKey();
HighlightDisplayLevel displayLevel = entry.getValue();
- if (Comparing.strEqual(severity.toString(), name)) {
+ if (Comparing.strEqual(severity.getName(), name)) {
return displayLevel;
}
}
@@ -82,6 +82,11 @@
return mySeverity.toString();
}
+ @NotNull
+ public String getName() {
+ return mySeverity.getName();
+ }
+
public Icon getIcon() {
return myIcon;
}
diff --git a/platform/analysis-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java b/platform/analysis-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
new file mode 100644
index 0000000..18d541a
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.codeInsight.daemon;
+
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public interface ChangeLocalityDetector {
+ /**
+ * @return the psi element (ancestor of the changedElement) which should be re-highlighted, or null if unsure.
+ * Examples:
+ * - in Java, when the statement has changed, re-highlight the enclosing code block only.
+ * - in (hypothetical) framework which stores its annotations in comments, e.g. "// @someAnnotation",
+ * when that special comment has changed, re-highlight the whole file.
+ *
+ * Note: for the performance sake, do not traverse PSI tree upwards here, since this method will be called for the
+ * changed element and all its parents anyway.
+ * So the parent check is enough, e.g: {@code changedElement.getParent() instanceof PsiCodeBlock}
+ */
+ @Nullable
+ PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement);
+}
\ No newline at end of file
diff --git a/platform/analysis-api/src/com/intellij/codeInsight/daemon/DaemonBundle.java b/platform/analysis-api/src/com/intellij/codeInsight/daemon/DaemonBundle.java
index a7b4d79..b843dad 100644
--- a/platform/analysis-api/src/com/intellij/codeInsight/daemon/DaemonBundle.java
+++ b/platform/analysis-api/src/com/intellij/codeInsight/daemon/DaemonBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -34,13 +35,12 @@
private DaemonBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE)String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/InspectionsBundle.java b/platform/analysis-api/src/com/intellij/codeInspection/InspectionsBundle.java
index 95b2482..7283687 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/InspectionsBundle.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/InspectionsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -34,13 +35,12 @@
private InspectionsBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, @NonNls Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE)String key, @NotNull @NonNls Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/ModifiableModel.java b/platform/analysis-api/src/com/intellij/codeInspection/ModifiableModel.java
index bdaf567..c46b1a2 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/ModifiableModel.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/ModifiableModel.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,9 +41,9 @@
void setBaseProfile(InspectionProfile profile);
- void enableTool(String inspectionTool, NamedScope namedScope, Project project);
+ void enableTool(@NotNull String inspectionTool, NamedScope namedScope, Project project);
- void disableTool(String inspectionTool, NamedScope namedScope, @NotNull Project project);
+ void disableTool(@NotNull String inspectionTool, NamedScope namedScope, @NotNull Project project);
void setErrorLevel(HighlightDisplayKey key, @NotNull HighlightDisplayLevel level, Project project);
@@ -87,5 +87,5 @@
void disableTool(@NotNull String toolId, @NotNull PsiElement element);
- void disableTool(String inspectionTool, Project project);
+ void disableTool(@NotNull String inspectionTool, Project project);
}
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java
index 464ab9a..e241674 100644
--- a/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.java
+++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/EntryPoint.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.
@@ -28,8 +28,8 @@
@NotNull
public abstract String getDisplayName();
- public abstract boolean isEntryPoint(RefElement refElement, PsiElement psiElement);
- public abstract boolean isEntryPoint(PsiElement psiElement);
+ public abstract boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement);
+ public abstract boolean isEntryPoint(@NotNull PsiElement psiElement);
public abstract boolean isSelected();
public abstract void setSelected(boolean selected);
diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java
new file mode 100644
index 0000000..2b19e8f
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.reference;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Provides quick fixes for "Unused declaration" inspection
+ *
+ * @author Dmitry Avdeev
+ * Date: 1/19/12
+ */
+public interface UnusedDeclarationFixProvider {
+ ExtensionPointName<UnusedDeclarationFixProvider> EP_NAME = ExtensionPointName.create("com.intellij.unusedDeclarationFixProvider");
+
+ @NotNull
+ IntentionAction[] getQuickFixes(@NotNull PsiElement unusedElement);
+}
diff --git a/platform/analysis-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java b/platform/analysis-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java
new file mode 100644
index 0000000..1ca4a36
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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;
+
+import com.intellij.lang.annotation.ExternalAnnotator;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.psi.PsiFile;
+
+/**
+ * @author Dmitry Avdeev
+ */
+public interface ExternalAnnotatorsFilter {
+
+ ExtensionPointName<ExternalAnnotatorsFilter> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.daemon.externalAnnotatorsFilter");
+
+ boolean isProhibited(ExternalAnnotator annotator, PsiFile file);
+}
diff --git a/platform/analysis-api/src/com/intellij/lang/ExternalLanguageAnnotators.java b/platform/analysis-api/src/com/intellij/lang/ExternalLanguageAnnotators.java
new file mode 100644
index 0000000..90bd7a1
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/lang/ExternalLanguageAnnotators.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.lang;
+
+import com.intellij.lang.annotation.ExternalAnnotator;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.util.List;
+
+public class ExternalLanguageAnnotators extends LanguageExtension<ExternalAnnotator>{
+
+ private static final ExternalLanguageAnnotators INSTANCE = new ExternalLanguageAnnotators();
+
+ private ExternalLanguageAnnotators() {
+ super("com.intellij.externalAnnotator");
+ }
+
+ public static List<ExternalAnnotator> allForFile(Language language, final PsiFile file) {
+ List<ExternalAnnotator> annotators = INSTANCE.allForLanguage(language);
+ final ExternalAnnotatorsFilter[] filters = Extensions.getExtensions(ExternalAnnotatorsFilter.EXTENSION_POINT_NAME);
+ return ContainerUtil.findAll(annotators, new Condition<ExternalAnnotator>() {
+ @Override
+ public boolean value(ExternalAnnotator annotator) {
+ for (ExternalAnnotatorsFilter filter : filters) {
+ if (filter.isProhibited(annotator, file)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ });
+ }
+}
\ No newline at end of file
diff --git a/platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java b/platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java
index ea076d2..a315392 100644
--- a/platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java
+++ b/platform/analysis-api/src/com/intellij/lang/annotation/AnnotationHolder.java
@@ -142,6 +142,17 @@
*/
Annotation createInfoAnnotation(@NotNull TextRange range, @Nullable String message);
+ /**
+ * Creates an annotation with the given severity (colored highlighting only, with no gutter mark and not participating in
+ * "Next Error/Warning" navigation) with the specified message over the specified text range.
+ *
+ * @param severity the severity.
+ * @param range the text range over which the annotation is created.
+ * @param message the information message.
+ * @return the annotation (which can be modified to set additional annotation parameters)
+ */
+ Annotation createAnnotation(@NotNull HighlightSeverity severity, @NotNull TextRange range, @Nullable String message);
+
@NotNull
AnnotationSession getCurrentAnnotationSession();
diff --git a/platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java b/platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.java
new file mode 100644
index 0000000..9381a2a
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/lang/annotation/ExternalAnnotator.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.lang.annotation;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Implemented by a custom language plugin to process the files in a language by an
+ * external annotation tool. The external annotator is expected to be slow and is started
+ * after the regular annotator has completed its work.
+ *
+ * @author ven
+ * @see com.intellij.lang.ExternalLanguageAnnotators
+ */
+public abstract class ExternalAnnotator<InitialInfoType, AnnotationResultType> {
+ /**
+ * Collects initial information required for annotation. Expected to run within read action.
+ * See {@link ExternalAnnotator#collectInformation(PsiFile, Editor, boolean)} for details.
+ *
+ * @param file file to annotate
+ * @return see {@link ExternalAnnotator#collectInformation(PsiFile, Editor, boolean)}
+ */
+ @Nullable
+ public InitialInfoType collectInformation(@NotNull PsiFile file) {
+ return null;
+ }
+
+ /**
+ * Collects initial information required for annotation. This method is called within read action during annotation pass.
+ * Default implementation returns the result of {@link ExternalAnnotator#collectInformation(PsiFile)}
+ * if file has no errors or {@code null} otherwise.
+ * @param file file to annotate
+ * @param editor editor in which file's document reside
+ * @param hasErrors indicates if file has errors detected by preceding analyses
+ * @return information to pass to {@link ExternalAnnotator#doAnnotate(InitialInfoType)} or {@code null} if annotation should be skipped
+ */
+ @Nullable
+ public InitialInfoType collectInformation(@NotNull PsiFile file, @NotNull Editor editor, boolean hasErrors) {
+ return hasErrors ? null : collectInformation(file);
+ }
+
+ /**
+ * Collects full information required for annotation. This method is intended for long-running activities
+ * and will be called outside read/write actions during annotation pass.
+ * @param collectedInfo initial information gathered by {@link ExternalAnnotator#collectInformation(PsiFile, Editor, boolean)}
+ * @return annotation result to pass to {@link ExternalAnnotator#apply(PsiFile, AnnotationResultType, AnnotationHolder)}
+ */
+ @Nullable
+ public AnnotationResultType doAnnotate(InitialInfoType collectedInfo) {
+ return null;
+ }
+
+ /**
+ * Applies results of annotation. This method is called within read action during annotation pass.
+ * @param file file to annotate
+ * @param annotationResult annotation result acquired through {@link ExternalAnnotator#doAnnotate(InitialInfoType)}
+ * @param holder container which receives annotations
+ */
+ public void apply(@NotNull PsiFile file, AnnotationResultType annotationResult, @NotNull AnnotationHolder holder) {
+ }
+}
diff --git a/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java b/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java
index 7e6ea0f..eb375d2 100644
--- a/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.java
+++ b/platform/analysis-api/src/com/intellij/lang/annotation/HighlightSeverity.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,10 +15,7 @@
*/
package com.intellij.lang.annotation;
-import com.intellij.openapi.util.DefaultJDOMExternalizer;
-import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.JDOMExternalizable;
-import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.util.*;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -30,9 +27,9 @@
* @see com.intellij.lang.annotation.Annotation
*/
-public class HighlightSeverity implements Comparable<HighlightSeverity>, JDOMExternalizable {
- public String myName;
- public int myVal;
+public class HighlightSeverity implements Comparable<HighlightSeverity> {
+ public final String myName;
+ public final int myVal;
/**
* The standard severity level for information annotations.
@@ -79,14 +76,15 @@
* if two annotations with different severity levels cover the same text range, only
* the annotation with a higher severity level is displayed.
*/
- public HighlightSeverity(@NonNls String name, int val) {
+ public HighlightSeverity(@NonNls @NotNull String name, int val) {
myName = name;
myVal = val;
}
//read external only
- public HighlightSeverity() {
+ public HighlightSeverity(@NotNull Element element) {
+ this(JDOMExternalizerUtil.readField(element, "myName"), Integer.valueOf(JDOMExternalizerUtil.readField(element, "myVal")));
}
public String toString() {
@@ -98,17 +96,10 @@
return myVal - highlightSeverity.myVal;
}
- @Override
- public void readExternal(Element element) throws InvalidDataException {
- DefaultJDOMExternalizer.readExternal(this, element);
- }
-
- @Override
public void writeExternal(final Element element) throws WriteExternalException {
DefaultJDOMExternalizer.writeExternal(this, element);
}
-
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -121,4 +112,9 @@
public int hashCode() {
return myName.hashCode();
}
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
}
diff --git a/platform/lang-api/src/com/intellij/openapi/roots/GeneratedSourcesFilter.java b/platform/analysis-api/src/com/intellij/openapi/roots/GeneratedSourcesFilter.java
similarity index 100%
rename from platform/lang-api/src/com/intellij/openapi/roots/GeneratedSourcesFilter.java
rename to platform/analysis-api/src/com/intellij/openapi/roots/GeneratedSourcesFilter.java
diff --git a/platform/analysis-api/src/com/intellij/psi/IntentionFilterOwner.java b/platform/analysis-api/src/com/intellij/psi/IntentionFilterOwner.java
new file mode 100644
index 0000000..beceae7
--- /dev/null
+++ b/platform/analysis-api/src/com/intellij/psi/IntentionFilterOwner.java
@@ -0,0 +1,59 @@
+/*
+ * 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.psi;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import org.jetbrains.annotations.NotNull;
+
+public interface IntentionFilterOwner {
+ /**
+ * Sets the intention actions filter which is used to determine which intention actions should be available in an editor.
+ *
+ * @param filter the intention actions filter instance.
+ */
+ void setIntentionActionsFilter(@NotNull IntentionActionsFilter filter);
+
+ /**
+ * Sets the intention actions filter which is used to determine which intention actions should be available in an editor.
+ *
+ * @return the intention actions filter instance.
+ */
+ IntentionActionsFilter getIntentionActionsFilter();
+
+ /**
+ * Interface to control the available intention actions.
+ */
+ interface IntentionActionsFilter {
+
+ /**
+ * Checks if the intention action should be available in an editor.
+ * @param intentionAction the intention action to analyze
+ * @return Returns true if the intention action should be available, false otherwise
+ */
+ boolean isAvailable(@NotNull IntentionAction intentionAction);
+
+ /**
+ * This filter reports all intentions are available.
+ */
+ IntentionActionsFilter EVERYTHING_AVAILABLE = new IntentionActionsFilter() {
+ @Override
+ public boolean isAvailable(@NotNull final IntentionAction intentionAction) {
+ return true;
+ }
+ };
+ }
+}
diff --git a/platform/analysis-impl/analysis-impl.iml b/platform/analysis-impl/analysis-impl.iml
index 5e1e23c..b4ca0c1 100644
--- a/platform/analysis-impl/analysis-impl.iml
+++ b/platform/analysis-impl/analysis-impl.iml
@@ -9,7 +9,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="analysis-api" exported="" />
<orderEntry type="module" module-name="core-api" />
- <orderEntry type="module" module-name="core-impl" />
+ <orderEntry type="module" module-name="core-impl" exported="" />
<orderEntry type="module" module-name="util" />
<orderEntry type="module" module-name="extensions" />
<orderEntry type="module" module-name="resources-en" />
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/QuickFixBundle.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/QuickFixBundle.java
index 508aa95..fbcef3c 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/QuickFixBundle.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/QuickFixBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -34,13 +35,12 @@
private QuickFixBundle() {
}
- public static String message(@NonNls @PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @NonNls @PropertyKey(resourceBundle = BUNDLE)String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/AnnotationHolderImpl.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/AnnotationHolderImpl.java
index 533f62a..94ccd48 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/AnnotationHolderImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/AnnotationHolderImpl.java
@@ -59,64 +59,64 @@
@Override
public Annotation createErrorAnnotation(@NotNull PsiElement elt, String message) {
assertMyFile(elt);
- return createAnnotation(elt.getTextRange(), HighlightSeverity.ERROR, message);
+ return createAnnotation(HighlightSeverity.ERROR, elt.getTextRange(), message);
}
@Override
public Annotation createErrorAnnotation(@NotNull ASTNode node, String message) {
assertMyFile(node.getPsi());
- return createAnnotation(node.getTextRange(), HighlightSeverity.ERROR, message);
+ return createAnnotation(HighlightSeverity.ERROR, node.getTextRange(), message);
}
@Override
public Annotation createErrorAnnotation(@NotNull TextRange range, String message) {
- return createAnnotation(range, HighlightSeverity.ERROR, message);
+ return createAnnotation(HighlightSeverity.ERROR, range, message);
}
@Override
public Annotation createWarningAnnotation(@NotNull PsiElement elt, String message) {
assertMyFile(elt);
- return createAnnotation(elt.getTextRange(), HighlightSeverity.WARNING, message);
+ return createAnnotation(HighlightSeverity.WARNING, elt.getTextRange(), message);
}
@Override
public Annotation createWarningAnnotation(@NotNull ASTNode node, String message) {
assertMyFile(node.getPsi());
- return createAnnotation(node.getTextRange(), HighlightSeverity.WARNING, message);
+ return createAnnotation(HighlightSeverity.WARNING, node.getTextRange(), message);
}
@Override
public Annotation createWarningAnnotation(@NotNull TextRange range, String message) {
- return createAnnotation(range, HighlightSeverity.WARNING, message);
+ return createAnnotation(HighlightSeverity.WARNING, range, message);
}
@Override
public Annotation createWeakWarningAnnotation(@NotNull PsiElement elt, @Nullable String message) {
assertMyFile(elt);
- return createAnnotation(elt.getTextRange(), HighlightSeverity.WEAK_WARNING, message);
+ return createAnnotation(HighlightSeverity.WEAK_WARNING, elt.getTextRange(), message);
}
@Override
public Annotation createWeakWarningAnnotation(@NotNull ASTNode node, @Nullable String message) {
assertMyFile(node.getPsi());
- return createAnnotation(node.getTextRange(), HighlightSeverity.WEAK_WARNING, message);
+ return createAnnotation(HighlightSeverity.WEAK_WARNING, node.getTextRange(), message);
}
@Override
public Annotation createWeakWarningAnnotation(@NotNull TextRange range, String message) {
- return createAnnotation(range, HighlightSeverity.WEAK_WARNING, message);
+ return createAnnotation(HighlightSeverity.WEAK_WARNING, range, message);
}
@Override
public Annotation createInfoAnnotation(@NotNull PsiElement elt, String message) {
assertMyFile(elt);
- return createAnnotation(elt.getTextRange(), HighlightSeverity.INFORMATION, message);
+ return createAnnotation(HighlightSeverity.INFORMATION, elt.getTextRange(), message);
}
@Override
public Annotation createInfoAnnotation(@NotNull ASTNode node, String message) {
assertMyFile(node.getPsi());
- return createAnnotation(node.getTextRange(), HighlightSeverity.INFORMATION, message);
+ return createAnnotation(HighlightSeverity.INFORMATION, node.getTextRange(), message);
}
private void assertMyFile(PsiElement node) {
@@ -135,10 +135,11 @@
@Override
public Annotation createInfoAnnotation(@NotNull TextRange range, String message) {
- return createAnnotation(range, HighlightSeverity.INFORMATION, message);
+ return createAnnotation(HighlightSeverity.INFORMATION, range, message);
}
- protected Annotation createAnnotation(TextRange range, HighlightSeverity severity, @Nullable String message) {
+ @Override
+ public Annotation createAnnotation(@NotNull HighlightSeverity severity, @NotNull TextRange range, @Nullable String message) {
//noinspection HardCodedStringLiteral
//TODO: FIXME
@NonNls
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/CheckLevelHighlightInfoHolder.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/CheckLevelHighlightInfoHolder.java
new file mode 100644
index 0000000..67e54ab
--- /dev/null
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/CheckLevelHighlightInfoHolder.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.codeInsight.daemon.impl;
+
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
+import com.intellij.lang.annotation.AnnotationSession;
+import com.intellij.openapi.editor.colors.TextAttributesScheme;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+public class CheckLevelHighlightInfoHolder extends HighlightInfoHolder {
+ private final HighlightInfoHolder myHolder;
+ private PsiElement myLevel;
+
+ public CheckLevelHighlightInfoHolder(PsiFile file, HighlightInfoHolder holder) {
+ super(file);
+ myHolder = holder;
+ }
+
+ @NotNull
+ @Override
+ public TextAttributesScheme getColorsScheme() {
+ return myHolder.getColorsScheme();
+ }
+
+ @Override
+ public PsiFile getContextFile() {
+ return myHolder.getContextFile();
+ }
+
+ @NotNull
+ @Override
+ public Project getProject() {
+ return myHolder.getProject();
+ }
+
+ @Override
+ public boolean hasErrorResults() {
+ return myHolder.hasErrorResults();
+ }
+
+ @Override
+ public boolean add(@Nullable HighlightInfo info) {
+ if (info == null) return false;
+ PsiElement psiElement = info.psiElement;
+ if (psiElement != null && !PsiTreeUtil.isAncestor(myLevel, psiElement,false)) {
+ throw new RuntimeException("Info: '" + info + "' reported for the element '" + psiElement + "'; but it was at the level " + myLevel);
+ }
+ return myHolder.add(info);
+ }
+
+ @Override
+ public void clear() {
+ myHolder.clear();
+ }
+
+ @Override
+ public boolean addAll(Collection<? extends HighlightInfo> highlightInfos) {
+ return myHolder.addAll(highlightInfos);
+ }
+
+ @Override
+ public int size() {
+ return myHolder.size();
+ }
+
+ @Override
+ public HighlightInfo get(int i) {
+ return myHolder.get(i);
+ }
+
+ @NotNull
+ @Override
+ public AnnotationSession getAnnotationSession() {
+ return myHolder.getAnnotationSession();
+ }
+
+ public void enterLevel(PsiElement element) {
+ myLevel = element;
+ }
+}
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java
index a221c11..7c4a5ea 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/Divider.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.
@@ -134,7 +134,7 @@
PsiElement parent = !outside.isEmpty() ? outside.get(outside.size() - 1) :
!inside.isEmpty() ? inside.get(inside.size() - 1) :
CollectHighlightsUtil.findCommonParent(root, startOffset, endOffset);
- while (parent != null && parent != root) {
+ while (parent != null && !(parent instanceof PsiFile)) {
parent = parent.getParent();
if (parent != null) {
outside.add(parent);
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
index a29c339..eb082a1 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPass.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,7 +23,9 @@
import com.intellij.codeInsight.daemon.impl.analysis.HighlightInfoHolder;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
import com.intellij.codeInsight.problems.ProblemImpl;
+import com.intellij.concurrency.JobScheduler;
import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -56,6 +58,7 @@
import org.jetbrains.annotations.Nullable;
import java.util.*;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingPass implements DumbAware {
@@ -68,6 +71,7 @@
return HighlightingLevelManager.getInstance(file.getProject()).shouldHighlight(file);
}
};
+ private static final Random RESTART_DAEMON_RANDOM = new Random();
protected final int myStartOffset;
protected final int myEndOffset;
@@ -86,7 +90,7 @@
}
};
protected final EditorColorsScheme myGlobalScheme;
- private NotNullProducer<HighlightVisitor[]> myHighlightVisitorProducer = new NotNullProducer<HighlightVisitor[]>() {
+ private volatile NotNullProducer<HighlightVisitor[]> myHighlightVisitorProducer = new NotNullProducer<HighlightVisitor[]>() {
@NotNull
@Override
public HighlightVisitor[] produce() {
@@ -149,7 +153,12 @@
visitors.add(visitor);
}
}
- LOG.assertTrue(!visitors.isEmpty(), list);
+ if (visitors.isEmpty()) {
+ LOG.error("No visitors registered. list=" +
+ list +
+ "; all visitors are:" +
+ Arrays.asList(Extensions.getExtensions(HighlightVisitor.EP_HIGHLIGHT_VISITOR, myProject)));
+ }
HighlightVisitor[] visitorArray = visitors.toArray(new HighlightVisitor[visitors.size()]);
Arrays.sort(visitorArray, VISITOR_ORDER_COMPARATOR);
@@ -190,6 +199,13 @@
List<ProperTextRange> outsideRanges = new ArrayList<ProperTextRange>();
Divider.divideInsideAndOutside(myFile, myStartOffset, myEndOffset, myPriorityRange, insideElements, insideRanges, outsideElements,
outsideRanges, false, FILE_FILTER);
+ // put file element always in outsideElements
+ if (!insideElements.isEmpty() && insideElements.get(insideElements.size()-1) instanceof PsiFile) {
+ PsiElement file = insideElements.remove(insideElements.size() - 1);
+ outsideElements.add(file);
+ ProperTextRange range = insideRanges.remove(insideRanges.size() - 1);
+ outsideRanges.add(range);
+ }
setProgressLimit((long)(insideElements.size()+outsideElements.size()));
@@ -321,7 +337,7 @@
assert info != null;
if (!myRestrictRange.containsRange(info.getStartOffset(), info.getEndOffset())) continue;
- List<HighlightInfo> result = myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset()) ? insideResult : outsideResult;
+ List<HighlightInfo> result = myPriorityRange.containsRange(info.getStartOffset(), info.getEndOffset()) && !(element instanceof PsiFile) ? insideResult : outsideResult;
// have to filter out already obtained highlights
if (!result.add(info)) continue;
boolean isError = info.getSeverity() == HighlightSeverity.ERROR;
@@ -336,7 +352,6 @@
info.setBijective(elementRange.equalsToRange(info.startOffset, info.endOffset));
myHighlightInfoProcessor.infoIsAvailable(myHighlightingSession, info);
- //myTransferToEDTQueue.offer(info);
infosForThisRange.add(info);
}
// include infos which we got while visiting nested elements with the same range
@@ -359,7 +374,6 @@
nested.push(Pair.create(elementRange, infosForThisRange));
if (parent == null || !Comparing.equal(elementRange, parent.getTextRange())) {
myHighlightInfoProcessor.allHighlightsForRangeAreProduced(myHighlightingSession, elementRange, infosForThisRange);
- //killAbandonedHighlightsUnder(elementRange, infosForThisRange, progress);
}
}
advanceProgress(elements.size() - (nextLimit-chunkSize));
@@ -398,18 +412,21 @@
@NotNull final Project project,
@NotNull TextEditorHighlightingPass passCalledFrom) throws ProcessCanceledException {
progress.cancel();
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ JobScheduler.getScheduler().schedule(new Runnable() {
+
@Override
public void run() {
- try {
- Thread.sleep(new Random().nextInt(100));
+ Application application = ApplicationManager.getApplication();
+ if (!project.isDisposed() && !application.isDisposed()) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ DaemonCodeAnalyzer.getInstance(project).restart();
+ }
+ }, project.getDisposed());
}
- catch (InterruptedException e) {
- LOG.error(e);
- }
- DaemonCodeAnalyzer.getInstance(project).restart();
}
- }, project.getDisposed());
+ }, RESTART_DAEMON_RANDOM.nextInt(100), TimeUnit.MILLISECONDS);
throw new ProcessCanceledException();
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
index f8b7169..4cff679 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfo.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.
@@ -98,6 +98,7 @@
private static final int AFTER_END_OF_LINE_FLAG = 3;
private static final int FILE_LEVEL_ANNOTATION_FLAG = 4;
private static final int NEEDS_UPDATE_ON_TYPING_FLAG = 5;
+ PsiElement psiElement;
@NotNull
ProperTextRange getFixTextRange() {
@@ -432,6 +433,7 @@
return false;
}
}
+ info.psiElement = psiElement;
return true;
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java
index d5d4561..d4b0b2e 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightInfoType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -26,7 +26,6 @@
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
@@ -101,14 +100,14 @@
TextAttributesKey getAttributesKey();
- class HighlightInfoTypeImpl implements HighlightInfoType, JDOMExternalizable {
+ class HighlightInfoTypeImpl implements HighlightInfoType {
private final HighlightSeverity mySeverity;
private final TextAttributesKey myAttributesKey;
//read external only
- public HighlightInfoTypeImpl() {
- mySeverity = new HighlightSeverity();
- myAttributesKey = new TextAttributesKey();
+ HighlightInfoTypeImpl(@NotNull Element element) throws InvalidDataException {
+ mySeverity = new HighlightSeverity(element);
+ myAttributesKey = new TextAttributesKey(element);
}
public HighlightInfoTypeImpl(@NotNull HighlightSeverity severity, TextAttributesKey attributesKey) {
@@ -132,19 +131,11 @@
return "HighlightInfoTypeImpl[severity=" + mySeverity + ", key=" + myAttributesKey + "]";
}
- @Override
- public void readExternal(Element element) throws InvalidDataException {
- mySeverity.readExternal(element);
- myAttributesKey.readExternal(element);
- }
-
- @Override
public void writeExternal(Element element) throws WriteExternalException {
mySeverity.writeExternal(element);
myAttributesKey.writeExternal(element);
}
-
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightersRecycler.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightersRecycler.java
index 1b6f1df..bca7c45 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightersRecycler.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightersRecycler.java
@@ -18,26 +18,13 @@
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.TextRange;
-import com.intellij.util.SmartList;
import com.intellij.util.containers.MultiMap;
-import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
-import java.util.Map;
class HighlightersRecycler {
- private final MultiMap<TextRange, RangeHighlighter> incinerator = new MultiMap<TextRange, RangeHighlighter>(){
- @Override
- protected Map<TextRange, Collection<RangeHighlighter>> createMap() {
- return new THashMap<TextRange, Collection<RangeHighlighter>>();
- }
-
- @Override
- protected Collection<RangeHighlighter> createCollection() {
- return new SmartList<RangeHighlighter>();
- }
- };
+ private final MultiMap<TextRange, RangeHighlighter> incinerator = MultiMap.createSmartList();
void recycleHighlighter(@NotNull RangeHighlighter highlighter) {
if (highlighter.isValid()) {
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSession.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSession.java
index 0075db2..7bb43fa 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSession.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSession.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,13 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
public interface HighlightingSession {
- Project getProject();
- PsiFile getPsiFile();
+ @NotNull Project getProject();
+ @NotNull PsiFile getPsiFile();
Editor getEditor();
- Document getDocument();
+ @NotNull Document getDocument();
ProgressIndicator getProgressIndicator();
EditorColorsScheme getColorsScheme();
int getPassId();
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSessionImpl.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSessionImpl.java
index fe0c3f8..9294424 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSessionImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/HighlightingSessionImpl.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,7 +42,7 @@
private final EditorColorsScheme myEditorColorsScheme;
private final int myPassId;
@NotNull private final TextRange myRestrictRange;
- private final Project myProject;
+ @NotNull private final Project myProject;
private final Document myDocument;
private final Map<TextRange,RangeMarker> myRanges2markersCache = new THashMap<TextRange, RangeMarker>();
@@ -74,6 +74,7 @@
return myEditor;
}
+ @NotNull
@Override
public Document getDocument() {
return myDocument;
@@ -85,6 +86,7 @@
return myProgressIndicator;
}
+ @NotNull
@Override
public Project getProject() {
return myProject;
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java
index f932072..3e0213c 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/SeverityRegistrar.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,8 +27,9 @@
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.util.concurrency.AtomicFieldUpdater;
+import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.ContainerUtil;
-import gnu.trove.THashMap;
import gnu.trove.TObjectIntHashMap;
import gnu.trove.TObjectIntProcedure;
import org.jdom.Element;
@@ -46,15 +47,15 @@
* Date: 24-Feb-2006
*/
public class SeverityRegistrar implements JDOMExternalizable, Comparator<HighlightSeverity> {
- @NonNls private static final String INFO = "info";
- private final Map<String, SeverityBasedTextAttributes> myMap = new THashMap<String, SeverityBasedTextAttributes>();
- private final Map<String, Color> myRendererColors = new THashMap<String, Color>();
- @NonNls private static final String COLOR = "color";
+ @NonNls private static final String INFO_TAG = "info";
+ @NonNls private static final String COLOR_ATTRIBUTE = "color";
+ private final Map<String, SeverityBasedTextAttributes> myMap = new ConcurrentHashMap<String, SeverityBasedTextAttributes>();
+ private final Map<String, Color> myRendererColors = new ConcurrentHashMap<String, Color>();
- private final OrderMap myOrder = new OrderMap();
+ private volatile OrderMap myOrderMap;
private JDOMExternalizableStringList myReadOrder;
- private static final Map<String, HighlightInfoType> STANDARD_SEVERITIES = new THashMap<String, HighlightInfoType>();
+ private static final Map<String, HighlightInfoType> STANDARD_SEVERITIES = new ConcurrentHashMap<String, HighlightInfoType>();
public SeverityRegistrar() {
}
@@ -68,7 +69,7 @@
}
public static void registerStandard(@NotNull HighlightInfoType highlightInfoType, @NotNull HighlightSeverity highlightSeverity) {
- STANDARD_SEVERITIES.put(highlightSeverity.toString(), highlightInfoType);
+ STANDARD_SEVERITIES.put(highlightSeverity.getName(), highlightInfoType);
}
@NotNull
@@ -78,22 +79,21 @@
: InspectionProjectProfileManager.getInstance(project).getSeverityRegistrar();
}
- public void registerSeverity(@NotNull SeverityBasedTextAttributes info, Color renderColor){
+ public void registerSeverity(@NotNull SeverityBasedTextAttributes info, Color renderColor) {
final HighlightSeverity severity = info.getType().getSeverity(null);
- myMap.put(severity.toString(), info);
- myRendererColors.put(severity.toString(), renderColor);
- myOrder.clear();
+ myMap.put(severity.getName(), info);
+ myRendererColors.put(severity.getName(), renderColor);
+ myOrderMap = null;
HighlightDisplayLevel.registerSeverity(severity, renderColor);
}
-
public SeverityBasedTextAttributes unregisterSeverity(@NotNull HighlightSeverity severity){
- return myMap.remove(severity.toString());
+ return myMap.remove(severity.getName());
}
@NotNull
public HighlightInfoType.HighlightInfoTypeImpl getHighlightInfoTypeBySeverity(@NotNull HighlightSeverity severity) {
- HighlightInfoType infoType = STANDARD_SEVERITIES.get(severity.toString());
+ HighlightInfoType infoType = STANDARD_SEVERITIES.get(severity.getName());
if (infoType != null) {
return (HighlightInfoType.HighlightInfoTypeImpl)infoType;
}
@@ -102,13 +102,17 @@
return (HighlightInfoType.HighlightInfoTypeImpl)HighlightInfoType.INFORMATION;
}
- final SeverityBasedTextAttributes type = myMap.get(severity.toString());
- return (HighlightInfoType.HighlightInfoTypeImpl)(type != null ? type.getType() : HighlightInfoType.WARNING);
+ final SeverityBasedTextAttributes type = getAttributesBySeverity(severity);
+ return (HighlightInfoType.HighlightInfoTypeImpl)(type == null ? HighlightInfoType.WARNING : type.getType());
+ }
+
+ private SeverityBasedTextAttributes getAttributesBySeverity(@NotNull HighlightSeverity severity) {
+ return myMap.get(severity.getName());
}
@Nullable
public TextAttributes getTextAttributesBySeverity(@NotNull HighlightSeverity severity) {
- final SeverityBasedTextAttributes infoType = myMap.get(severity.toString());
+ final SeverityBasedTextAttributes infoType = getAttributesBySeverity(severity);
if (infoType != null) {
return infoType.getAttributes();
}
@@ -120,72 +124,74 @@
public void readExternal(Element element) throws InvalidDataException {
myMap.clear();
myRendererColors.clear();
- final List children = element.getChildren(INFO);
+ final List children = element.getChildren(INFO_TAG);
for (Object child : children) {
final Element infoElement = (Element)child;
- final SeverityBasedTextAttributes highlightInfo = new SeverityBasedTextAttributes();
- highlightInfo.readExternal(infoElement);
+ final SeverityBasedTextAttributes highlightInfo = new SeverityBasedTextAttributes(infoElement);
Color color = null;
- final String colorStr = infoElement.getAttributeValue(COLOR);
+ final String colorStr = infoElement.getAttributeValue(COLOR_ATTRIBUTE);
if (colorStr != null){
color = new Color(Integer.parseInt(colorStr, 16));
}
registerSeverity(highlightInfo, color);
}
- myOrder.clear();
-
myReadOrder = new JDOMExternalizableStringList();
myReadOrder.readExternal(element);
+
+ OrderMap orderMap = new OrderMap(myReadOrder.size());
for (int i = 0; i < myReadOrder.size(); i++) {
String name = myReadOrder.get(i);
HighlightSeverity severity = getSeverity(name);
if (severity == null) continue;
- myOrder.put(severity, i);
+ orderMap.put(severity, i);
}
final List<HighlightSeverity> knownSeverities = getDefaultOrder();
- myOrder.retainEntries(new TObjectIntProcedure<HighlightSeverity>() {
+ orderMap.retainEntries(new TObjectIntProcedure<HighlightSeverity>() {
@Override
public boolean execute(HighlightSeverity severity, int order) {
return knownSeverities.contains(severity);
}
});
- if (myOrder.isEmpty()) {
- setFromList(knownSeverities);
+ if (orderMap.isEmpty()) {
+ orderMap = fromList(knownSeverities);
}
- //enforce include all known
- List<HighlightSeverity> list = getOrderAsList();
- for (int i = 0; i < knownSeverities.size(); i++) {
- HighlightSeverity stdSeverity = knownSeverities.get(i);
- if (!list.contains(stdSeverity)) {
- for (int oIdx = 0; oIdx < list.size(); oIdx++) {
- HighlightSeverity orderSeverity = list.get(oIdx);
- HighlightInfoType type = STANDARD_SEVERITIES.get(orderSeverity.toString());
- if (type != null && knownSeverities.indexOf(type.getSeverity(null)) > i) {
- list.add(oIdx, stdSeverity);
- myReadOrder = null;
- break;
+ else {
+ //enforce include all known
+ List<HighlightSeverity> list = getOrderAsList(orderMap);
+ for (int i = 0; i < knownSeverities.size(); i++) {
+ HighlightSeverity stdSeverity = knownSeverities.get(i);
+ if (!list.contains(stdSeverity)) {
+ for (int oIdx = 0; oIdx < list.size(); oIdx++) {
+ HighlightSeverity orderSeverity = list.get(oIdx);
+ HighlightInfoType type = STANDARD_SEVERITIES.get(orderSeverity.getName());
+ if (type != null && knownSeverities.indexOf(type.getSeverity(null)) > i) {
+ list.add(oIdx, stdSeverity);
+ myReadOrder = null;
+ break;
+ }
}
}
}
+ orderMap = fromList(list);
}
- setFromList(list);
+ myOrderMap = orderMap;
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
- List<HighlightSeverity> list = getOrderAsList();
- for (HighlightSeverity s : list) {
- Element info = new Element(INFO);
- String severity = s.toString();
- final SeverityBasedTextAttributes infoType = myMap.get(severity);
+ List<HighlightSeverity> list = getOrderAsList(getOrderMap());
+ for (HighlightSeverity severity : list) {
+ Element info = new Element(INFO_TAG);
+ String severityName = severity.getName();
+ final SeverityBasedTextAttributes infoType = getAttributesBySeverity(severity);
if (infoType != null) {
infoType.writeExternal(info);
- final Color color = myRendererColors.get(severity);
+ final Color color = myRendererColors.get(severityName);
if (color != null) {
- info.setAttribute(COLOR, Integer.toString(color.getRGB() & 0xFFFFFF, 16));
+ info.setAttribute(COLOR_ATTRIBUTE, Integer.toString(color.getRGB() & 0xFFFFFF, 16));
}
element.addContent(info);
}
@@ -195,11 +201,11 @@
myReadOrder.writeExternal(element);
}
else if (!getDefaultOrder().equals(list)) {
- final JDOMExternalizableStringList ext = new JDOMExternalizableStringList(Collections.nCopies(myOrder.size(), ""));
- myOrder.forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
+ final JDOMExternalizableStringList ext = new JDOMExternalizableStringList(Collections.nCopies(getOrderMap().size(), ""));
+ getOrderMap().forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
@Override
public boolean execute(HighlightSeverity orderSeverity, int oIdx) {
- ext.set(oIdx, orderSeverity.toString());
+ ext.set(oIdx, orderSeverity.getName());
return true;
}
});
@@ -208,9 +214,9 @@
}
@NotNull
- private List<HighlightSeverity> getOrderAsList() {
+ private List<HighlightSeverity> getOrderAsList(@NotNull OrderMap orderMap) {
List<HighlightSeverity> list = new ArrayList<HighlightSeverity>();
- for (Object o : getOrder().keys()) {
+ for (Object o : orderMap.keys()) {
list.add((HighlightSeverity)o);
}
Collections.sort(list, this);
@@ -218,12 +224,12 @@
}
public int getSeveritiesCount() {
- return createCurrentSeverities().size();
+ return createCurrentSeverityNames().size();
}
public HighlightSeverity getSeverityByIndex(final int i) {
final HighlightSeverity[] found = new HighlightSeverity[1];
- getOrder().forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
+ getOrderMap().forEachEntry(new TObjectIntProcedure<HighlightSeverity>() {
@Override
public boolean execute(HighlightSeverity severity, int order) {
if (order == i) {
@@ -237,7 +243,7 @@
}
public int getSeverityMaxIndex() {
- int[] values = getOrder().getValues();
+ int[] values = getOrderMap().getValues();
int max = values[0];
for(int i = 1; i < values.length; ++i) if (values[i] > max) max = values[i];
@@ -254,7 +260,7 @@
}
@NotNull
- private List<String> createCurrentSeverities() {
+ private List<String> createCurrentSeverityNames() {
List<String> list = new ArrayList<String>();
list.addAll(STANDARD_SEVERITIES.keySet());
list.addAll(myMap.keySet());
@@ -269,37 +275,50 @@
return level.getIcon();
}
- return HighlightDisplayLevel.createIconByMask(myRendererColors.get(severity.toString()));
+ return HighlightDisplayLevel.createIconByMask(myRendererColors.get(severity.getName()));
}
- public boolean isSeverityValid(@NotNull String severity) {
- return createCurrentSeverities().contains(severity);
+ public boolean isSeverityValid(@NotNull String severityName) {
+ return createCurrentSeverityNames().contains(severityName);
}
@Override
public int compare(final HighlightSeverity s1, final HighlightSeverity s2) {
- OrderMap order = getOrder();
- int o1 = order.getOrder(s1, -1);
- int o2 = order.getOrder(s2, -1);
+ OrderMap orderMap = getOrderMap();
+ int o1 = orderMap.getOrder(s1, -1);
+ int o2 = orderMap.getOrder(s2, -1);
return o1 - o2;
}
@NotNull
- private OrderMap getOrder() {
- if (myOrder.isEmpty()) {
- List<HighlightSeverity> order = getDefaultOrder();
- setFromList(order);
+ private OrderMap getOrderMap() {
+ OrderMap orderMap;
+ OrderMap defaultOrder = null;
+ while ((orderMap = myOrderMap) == null) {
+ if (defaultOrder == null) {
+ defaultOrder = fromList(getDefaultOrder());
+ }
+ boolean replaced = ORDER_MAP_UPDATER.compareAndSet(this, null, defaultOrder);
+ if (replaced) {
+ orderMap = defaultOrder;
+ break;
+ }
}
- return myOrder;
+ return orderMap;
}
- private void setFromList(@NotNull List<HighlightSeverity> order) {
- myOrder.clear();
- for (int i = 0; i < order.size(); i++) {
- HighlightSeverity severity = order.get(i);
- myOrder.put(severity, i);
+ private static final AtomicFieldUpdater<SeverityRegistrar, OrderMap> ORDER_MAP_UPDATER = AtomicFieldUpdater.forFieldOfType(SeverityRegistrar.class, OrderMap.class);
+
+ @NotNull
+ private static OrderMap fromList(@NotNull List<HighlightSeverity> orderList) {
+ OrderMap orderMap = new OrderMap(orderList.size());
+ for (int i = 0; i < orderList.size(); i++) {
+ HighlightSeverity severity = orderList.get(i);
+ orderMap.put(severity, i);
}
+ orderMap.trimToSize();
+ return orderMap;
}
@NotNull
@@ -316,13 +335,13 @@
return order;
}
- public void setOrder(@NotNull List<HighlightSeverity> order) {
- setFromList(order);
+ public void setOrder(@NotNull List<HighlightSeverity> orderList) {
+ myOrderMap = fromList(orderList);
myReadOrder = null;
}
public int getSeverityIdx(@NotNull HighlightSeverity severity) {
- return getOrder().getOrder(severity, -1);
+ return getOrderMap().getOrder(severity, -1);
}
public boolean isDefaultSeverity(@NotNull HighlightSeverity severity) {
@@ -337,43 +356,41 @@
}
private static class OrderMap extends TObjectIntHashMap<HighlightSeverity> {
+ private OrderMap(int initialCapacity) {
+ super(initialCapacity);
+ }
+
private int getOrder(@NotNull HighlightSeverity severity, int defaultOrder) {
int index = index(severity);
return index < 0 ? defaultOrder : _values[index];
}
}
- public static class SeverityBasedTextAttributes implements JDOMExternalizable {
+ public static class SeverityBasedTextAttributes {
private final TextAttributes myAttributes;
private final HighlightInfoType.HighlightInfoTypeImpl myType;
//read external
- public SeverityBasedTextAttributes() {
- myAttributes = new TextAttributes();
- myType = new HighlightInfoType.HighlightInfoTypeImpl();
+ public SeverityBasedTextAttributes(@NotNull Element element) throws InvalidDataException {
+ this(new TextAttributes(element), new HighlightInfoType.HighlightInfoTypeImpl(element));
}
- public SeverityBasedTextAttributes(final TextAttributes attributes, final HighlightInfoType.HighlightInfoTypeImpl type) {
+ public SeverityBasedTextAttributes(@NotNull TextAttributes attributes, @NotNull HighlightInfoType.HighlightInfoTypeImpl type) {
myAttributes = attributes;
myType = type;
}
+ @NotNull
public TextAttributes getAttributes() {
return myAttributes;
}
+ @NotNull
public HighlightInfoType.HighlightInfoTypeImpl getType() {
return myType;
}
- @Override
- public void readExternal(Element element) throws InvalidDataException {
- myAttributes.readExternal(element);
- myType.readExternal(element);
- }
-
- @Override
- public void writeExternal(Element element) throws WriteExternalException {
+ private void writeExternal(@NotNull Element element) throws WriteExternalException {
myAttributes.writeExternal(element);
myType.writeExternal(element);
}
@@ -389,15 +406,15 @@
final SeverityBasedTextAttributes that = (SeverityBasedTextAttributes)o;
- if (myAttributes != null ? !myAttributes.equals(that.myAttributes) : that.myAttributes != null) return false;
- if (myType != null ? !myType.equals(that.myType) : that.myType != null) return false;
+ if (!myAttributes.equals(that.myAttributes)) return false;
+ if (!myType.equals(that.myType)) return false;
return true;
}
public int hashCode() {
- int result = myAttributes != null ? myAttributes.hashCode() : 0;
- result = 31 * result + (myType != null ? myType.hashCode() : 0);
+ int result = myAttributes.hashCode();
+ result = 31 * result + myType.hashCode();
return result;
}
}
@@ -410,5 +427,4 @@
Collection<HighlightInfoType> standardSeverities() {
return STANDARD_SEVERITIES.values();
}
-
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java
index fcb7075..f21a04a 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/daemon/impl/UpdateHighlightersUtil.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.
@@ -156,6 +156,7 @@
// set highlights inside startOffset,endOffset but outside priorityRange
static void setHighlightersOutsideRange(@NotNull final Project project,
@NotNull final Document document,
+ @NotNull final PsiFile psiFile,
@NotNull final List<HighlightInfo> infos,
@Nullable final EditorColorsScheme colorsScheme,
// if null global scheme will be used
@@ -165,7 +166,6 @@
final int group) {
ApplicationManager.getApplication().assertIsDispatchThread();
- final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(document);
final DaemonCodeAnalyzerEx codeAnalyzer = DaemonCodeAnalyzerEx.getInstanceEx(project);
codeAnalyzer.cleanFileLevelHighlights(project, group, psiFile);
@@ -176,29 +176,28 @@
final HighlightersRecycler infosToRemove = new HighlightersRecycler();
ContainerUtil.quickSort(infos, BY_START_OFFSET_NODUPS);
- DaemonCodeAnalyzerEx.processHighlightsOverlappingOutside(document, project, null, priorityRange.getStartOffset(), priorityRange.getEndOffset(),
- new Processor<HighlightInfo>() {
- @Override
- public boolean process(HighlightInfo info) {
- if (info.getGroup() == group) {
- RangeHighlighter highlighter = info.highlighter;
- int hiStart = highlighter.getStartOffset();
- int hiEnd = highlighter.getEndOffset();
- if (!info.isFromInjection() &&
- hiEnd < document.getTextLength() &&
- (hiEnd <= startOffset || hiStart >= endOffset))
- return true; // injections are oblivious to restricting range
- boolean toRemove = !(hiEnd == document.getTextLength() &&
- priorityRange.getEndOffset() == document.getTextLength()) &&
- !priorityRange.containsRange(hiStart, hiEnd);
- if (toRemove) {
- infosToRemove.recycleHighlighter(highlighter);
- info.highlighter = null;
- }
- }
- return true;
- }
- });
+ Processor<HighlightInfo> processor = new Processor<HighlightInfo>() {
+ @Override
+ public boolean process(HighlightInfo info) {
+ if (info.getGroup() == group) {
+ RangeHighlighter highlighter = info.highlighter;
+ int hiStart = highlighter.getStartOffset();
+ int hiEnd = highlighter.getEndOffset();
+ if (!info.isFromInjection() && hiEnd < document.getTextLength() && (hiEnd <= startOffset || hiStart >= endOffset)) {
+ return true; // injections are oblivious to restricting range
+ }
+ boolean toRemove = !(hiEnd == document.getTextLength() &&
+ priorityRange.getEndOffset() == document.getTextLength()) &&
+ !priorityRange.containsRange(hiStart, hiEnd);
+ if (toRemove) {
+ infosToRemove.recycleHighlighter(highlighter);
+ info.highlighter = null;
+ }
+ }
+ return true;
+ }
+ };
+ DaemonCodeAnalyzerEx.processHighlightsOverlappingOutside(document, project, null, priorityRange.getStartOffset(), priorityRange.getEndOffset(), processor);
final Map<TextRange, RangeMarker> ranges2markersCache = new THashMap<TextRange, RangeMarker>(10);
final boolean[] changed = {false};
@@ -213,7 +212,7 @@
if (!atStart) return true;
if (!info.isFromInjection() && info.getEndOffset() < document.getTextLength() && (info.getEndOffset() <= startOffset || info.getStartOffset()>=endOffset)) return true; // injections are oblivious to restricting range
- if (info.isFileLevelAnnotation() && psiFile != null && psiFile.getViewProvider().isPhysical()) {
+ if (info.isFileLevelAnnotation() && psiFile.getViewProvider().isPhysical()) {
codeAnalyzer.addFileLevelHighlight(project, group, info, psiFile);
changed[0] = true;
return true;
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java b/platform/analysis-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java
index a1ef1ed..ed53245 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/quickfix/UnresolvedReferenceQuickFixProvider.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,7 +20,7 @@
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.DumbService;
import com.intellij.psi.PsiReference;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
public abstract class UnresolvedReferenceQuickFixProvider<T extends PsiReference> {
@@ -32,7 +32,7 @@
if (dumb && !DumbService.isDumbAware(each)) {
continue;
}
- if (ReflectionCache.isAssignable(each.getReferenceClass(), referenceClass)) {
+ if (ReflectionUtil.isAssignable(each.getReferenceClass(), referenceClass)) {
each.registerFixes(ref, registrar);
}
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java b/platform/analysis-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java
new file mode 100644
index 0000000..f2a7c67
--- /dev/null
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection;
+
+import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
+import com.intellij.lang.annotation.Annotation;
+import com.intellij.lang.annotation.AnnotationSession;
+import com.intellij.lang.annotation.ExternalAnnotator;
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiElementVisitor;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor {
+ private static final Logger LOG = Logger.getInstance(ExternalAnnotatorInspectionVisitor.class);
+
+ private final ProblemsHolder myHolder;
+ private final ExternalAnnotator myAnnotator;
+ private final boolean myOnTheFly;
+
+ public ExternalAnnotatorInspectionVisitor(ProblemsHolder holder, ExternalAnnotator annotator, boolean onTheFly) {
+ myHolder = holder;
+ myAnnotator = annotator;
+ myOnTheFly = onTheFly;
+ }
+
+ @NotNull
+ public static <Init,Result> ProblemDescriptor[] checkFileWithExternalAnnotator(@NotNull PsiFile file,
+ @NotNull InspectionManager manager,
+ boolean isOnTheFly,
+ @NotNull ExternalAnnotator<Init,Result> annotator) {
+ if (isOnTheFly) {
+ // concrete JSLinterExternalAnnotator implementation does this work
+ return ProblemDescriptor.EMPTY_ARRAY;
+ }
+
+ Init info = annotator.collectInformation(file);
+ if (info != null) {
+ Result annotationResult = annotator.doAnnotate(info);
+ if (annotationResult == null) {
+ return ProblemDescriptor.EMPTY_ARRAY;
+ }
+ AnnotationHolderImpl annotationHolder = new AnnotationHolderImpl(new AnnotationSession(file));
+ annotator.apply(file, annotationResult, annotationHolder);
+ return convertToProblemDescriptors(annotationHolder, manager, file);
+ }
+ return ProblemDescriptor.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ private static ProblemDescriptor[] convertToProblemDescriptors(@NotNull final List<Annotation> annotations,
+ @NotNull final InspectionManager manager,
+ @NotNull final PsiFile file) {
+ if (annotations.isEmpty()) {
+ return ProblemDescriptor.EMPTY_ARRAY;
+ }
+
+ final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
+ for (final Annotation annotation : annotations) {
+ if (annotation.getSeverity() == HighlightSeverity.INFORMATION ||
+ annotation.getStartOffset() == annotation.getEndOffset()) {
+ continue;
+ }
+
+ final PsiElement startElement = file.findElementAt(annotation.getStartOffset());
+ final PsiElement endElement = file.findElementAt(annotation.getEndOffset() - 1);
+ if (startElement == null || endElement == null) {
+ continue;
+ }
+
+ problems.add(manager.createProblemDescriptor(startElement, endElement, annotation.getMessage(),
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false));
+ }
+ return problems.toArray(new ProblemDescriptor[problems.size()]);
+ }
+
+ @Override
+ public void visitFile(PsiFile file) {
+ if (!myOnTheFly) {
+ ProblemDescriptor[] descriptors = checkFileWithExternalAnnotator(file, myHolder.getManager(),
+ false, myAnnotator);
+ addDescriptors(descriptors);
+ }
+ }
+
+ private void addDescriptors(@NotNull ProblemDescriptor[] descriptors) {
+ for (ProblemDescriptor descriptor : descriptors) {
+ LOG.assertTrue(descriptor != null, getClass().getName());
+ myHolder.registerProblem(descriptor);
+ }
+ }
+}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java
index 45997b0..3ac277c 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ProblemDescriptorBase.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.
@@ -102,6 +102,7 @@
return PsiTreeUtil.findCommonParent(startElement, endElement);
}
+ @Override
@Nullable
public TextRange getTextRangeInElement() {
return myTextRangeInElement;
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java b/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
index 0da83b4..3fc800e 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/SuppressIntentionActionFromFix.java
@@ -48,8 +48,7 @@
@Override
public void invoke(@NotNull Project project, Editor editor, @NotNull PsiElement element) throws IncorrectOperationException {
- PsiElement container = myFix instanceof AbstractBatchSuppressByNoInspectionCommentFix
- ? ((AbstractBatchSuppressByNoInspectionCommentFix )myFix).getContainer(element) : null;
+ PsiElement container = getContainer(element);
boolean caretWasBeforeStatement = editor != null && container != null && editor.getCaretModel().getOffset() == container.getTextRange().getStartOffset();
InspectionManager inspectionManager = InspectionManager.getInstance(project);
ProblemDescriptor descriptor = inspectionManager.createProblemDescriptor(element, element, "", ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
@@ -60,6 +59,11 @@
}
}
+ public PsiElement getContainer(PsiElement element) {
+ return myFix instanceof AbstractBatchSuppressByNoInspectionCommentFix
+ ? ((AbstractBatchSuppressByNoInspectionCommentFix )myFix).getContainer(element) : null;
+ }
+
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, @NotNull PsiElement element) {
return myFix.isAvailable(project, element);
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java
index fbef51f..978aab6 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/HTMLComposerImpl.java
@@ -151,7 +151,7 @@
while (!(refEntity instanceof RefProject)) {
if (qName.length() > 0) qName = "." + qName;
- String name = refEntity.getName();
+ String name = null;
if (refEntity instanceof RefElement) {
final HTMLComposerExtension extension = getLanguageExtension((RefElement)refEntity);
if (extension != null) {
@@ -159,6 +159,10 @@
}
}
+ if (name == null) {
+ name = refEntity.getName();
+ }
+
qName = name + qName;
refEntity = refEntity.getOwner();
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
index f0a036b..e37a348 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileImpl.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.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import java.io.IOException;
import java.util.*;
@@ -63,7 +64,8 @@
private Map<String, ToolsImpl> myTools = new THashMap<String, ToolsImpl>();
private Map<String, Boolean> myDisplayLevelMap;
- @NotNull private final Map<String, Element> myDeinstalledInspectionsSettings;
+ @NotNull
+ private final Map<String, Element> myDeinstalledInspectionsSettings;
private boolean myLockedProfile = false;
protected InspectionProfileImpl mySource;
@@ -81,6 +83,7 @@
final InspectionToolRegistrar myRegistrar;
@NonNls private static final String IS_LOCKED = "is_locked";
private final ExternalInfo myExternalInfo = new ExternalInfo();
+ @TestOnly
public static boolean INIT_INSPECTIONS = false;
@Override
@@ -95,7 +98,6 @@
super(inspectionProfile.getName());
myRegistrar = inspectionProfile.myRegistrar;
- myTools = new HashMap<String, ToolsImpl>();
myDeinstalledInspectionsSettings = new LinkedHashMap<String, Element>(inspectionProfile.myDeinstalledInspectionsSettings);
myBaseProfile = inspectionProfile.myBaseProfile;
@@ -172,7 +174,7 @@
return myModified;
}
- private static boolean toolSettingsAreEqual(String toolName, @NotNull InspectionProfileImpl profile1, @NotNull InspectionProfileImpl profile2) {
+ private static boolean toolSettingsAreEqual(@NotNull String toolName, @NotNull InspectionProfileImpl profile1, @NotNull InspectionProfileImpl profile2) {
final Tools toolList1 = profile1.myTools.get(toolName);
final Tools toolList2 = profile2.myTools.get(toolName);
@@ -211,7 +213,7 @@
Project project = element == null ? null : element.getProject();
final ToolsImpl tools = getTools(inspectionToolKey.toString(), project);
HighlightDisplayLevel level = tools != null ? tools.getLevel(element) : HighlightDisplayLevel.WARNING;
- if (!((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().isSeverityValid(level.getSeverity().toString())) {
+ if (!((SeverityProvider)getProfileManager()).getOwnSeverityRegistrar().isSeverityValid(level.getSeverity().getName())) {
level = HighlightDisplayLevel.WARNING;
setErrorLevel(inspectionToolKey, level, project);
}
@@ -464,16 +466,16 @@
getTools(toolId, element.getProject()).disableTool(element);
}
- public void disableToolByDefault(String toolId, Project project) {
+ public void disableToolByDefault(@NotNull String toolId, Project project) {
getToolDefaultState(toolId, project).setEnabled(false);
}
@NotNull
- public ScopeToolState getToolDefaultState(String toolId, Project project) {
+ public ScopeToolState getToolDefaultState(@NotNull String toolId, Project project) {
return getTools(toolId, project).getDefaultState();
}
- public void enableToolByDefault(String toolId, Project project) {
+ public void enableToolByDefault(@NotNull String toolId, Project project) {
getToolDefaultState(toolId, project).setEnabled(true);
}
@@ -634,8 +636,8 @@
}
}
- public void enableTool(@NotNull String inspectionTool, Project project) {
- final ToolsImpl tools = getTools(inspectionTool, project);
+ public void enableTool(@NotNull String toolId, Project project) {
+ final ToolsImpl tools = getTools(toolId, project);
tools.setEnabled(true);
if (tools.getNonDefaultTools() == null) {
tools.getDefaultState().setEnabled(true);
@@ -643,18 +645,18 @@
}
@Override
- public void enableTool(String inspectionTool, NamedScope namedScope, Project project) {
+ public void enableTool(@NotNull String inspectionTool, NamedScope namedScope, Project project) {
getTools(inspectionTool, project).enableTool(namedScope, project);
}
@Override
- public void disableTool(String inspectionTool, NamedScope namedScope, @NotNull Project project) {
+ public void disableTool(@NotNull String inspectionTool, NamedScope namedScope, @NotNull Project project) {
getTools(inspectionTool, project).disableTool(namedScope, project);
}
@Override
- public void disableTool(String inspectionTool, Project project) {
+ public void disableTool(@NotNull String inspectionTool, Project project) {
final ToolsImpl tools = getTools(inspectionTool, project);
tools.setEnabled(false);
if (tools.getNonDefaultTools() == null) {
@@ -818,7 +820,7 @@
}
@NotNull
- public List<ScopeToolState> getNonDefaultTools(String shortName, Project project) {
+ public List<ScopeToolState> getNonDefaultTools(@NotNull String shortName, Project project) {
final List<ScopeToolState> result = new ArrayList<ScopeToolState>();
final List<ScopeToolState> nonDefaultTools = getTools(shortName, project).getNonDefaultTools();
if (nonDefaultTools != null) {
@@ -831,15 +833,15 @@
return getTools(key.toString(), project).isEnabled(namedScope,project);
}
- public void removeScope(String toolId, int scopeIdx, Project project) {
+ public void removeScope(@NotNull String toolId, int scopeIdx, Project project) {
getTools(toolId, project).removeScope(scopeIdx);
}
- public void removeAllScopes(String toolId, Project project) {
+ public void removeAllScopes(@NotNull String toolId, Project project) {
getTools(toolId, project).removeAllScopes();
}
- public void moveScope(String toolId, int idx, int dir, Project project) {
+ public void moveScope(@NotNull String toolId, int idx, int dir, Project project) {
getTools(toolId, project).moveScope(idx, dir);
}
@@ -882,7 +884,7 @@
getTools(key.toString(), project).setLevel(level, scopeIdx, project);
}
- private ToolsImpl getTools(String toolId, Project project) {
+ private ToolsImpl getTools(@NotNull String toolId, Project project) {
initInspectionTools(project);
return myTools.get(toolId);
}
@@ -906,9 +908,6 @@
@Override
public boolean equals(Object o) {
- if (super.equals(o)) {
- return ((InspectionProfileImpl) o).getProfileManager() == InspectionProfileImpl.this.getProfileManager();
- }
- return false;
+ return super.equals(o) && ((InspectionProfileImpl)o).getProfileManager() == getProfileManager();
}
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java
index 136ea58..4554cbe 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/InspectionProfileWrapper.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,10 +79,6 @@
return myProfile.isToolEnabled(key, element);
}
- public boolean isToolEnabled(final HighlightDisplayKey key) {
- return myProfile.isToolEnabled(key);
- }
-
public InspectionToolWrapper getInspectionTool(final String shortName, PsiElement element) {
return myProfile.getInspectionTool(shortName, element);
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
index a017575..b86ff68 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/ex/ToolsImpl.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.
@@ -142,18 +142,22 @@
for (ScopeToolState state : myTools) {
final Element scopeElement = new Element("scope");
scopeElement.setAttribute("name", state.getScopeName());
- scopeElement.setAttribute(LEVEL_ATTRIBUTE, state.getLevel().toString());
+ scopeElement.setAttribute(LEVEL_ATTRIBUTE, state.getLevel().getName());
scopeElement.setAttribute(ENABLED_ATTRIBUTE, Boolean.toString(state.isEnabled()));
InspectionToolWrapper toolWrapper = state.getTool();
- toolWrapper.getTool().writeSettings(scopeElement);
+ if (toolWrapper.isInitialized()) {
+ toolWrapper.getTool().writeSettings(scopeElement);
+ }
inspectionElement.addContent(scopeElement);
}
}
inspectionElement.setAttribute(ENABLED_ATTRIBUTE, Boolean.toString(isEnabled()));
- inspectionElement.setAttribute(LEVEL_ATTRIBUTE, getLevel().toString());
+ inspectionElement.setAttribute(LEVEL_ATTRIBUTE, getLevel().getName());
inspectionElement.setAttribute(ENABLED_BY_DEFAULT_ATTRIBUTE, Boolean.toString(myDefaultState.isEnabled()));
InspectionToolWrapper toolWrapper = myDefaultState.getTool();
- toolWrapper.getTool().writeSettings(inspectionElement);
+ if (toolWrapper.isInitialized()) {
+ toolWrapper.getTool().writeSettings(inspectionElement);
+ }
}
void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile) throws InvalidDataException {
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt b/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt
index c78817d..18ea3dd 100644
--- a/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt
+++ b/platform/analysis-impl/src/com/intellij/codeInspection/inspection-black-list.txt
@@ -76,7 +76,7 @@
com.siyeh.ig.classlayout.EmptyClassInspection
com.siyeh.ig.classlayout.InnerClassOnInterfaceInspection
com.siyeh.ig.classlayout.ListenerMayUseAdapterInspection
-com.siyeh.ig.classlayout.MissingOverrideAnnotationInspection
+com.siyeh.ig.inheritance.MissingOverrideAnnotationInspection
com.siyeh.ig.classlayout.UtilityClassInspection
com.siyeh.ig.classlayout.UtilityClassWithoutPrivateConstructorInspection
com.siyeh.ig.classmetrics.AnonymousClassComplexityInspection
@@ -163,7 +163,6 @@
com.siyeh.ig.methodmetrics.ThrownExceptionsPerMethodInspection
com.siyeh.ig.migration.ForCanBeForeachInspection
com.siyeh.ig.migration.IfCanBeSwitchInspection
-com.siyeh.ig.migration.MethodCanBeVariableArityMethodInspection
com.siyeh.ig.modularization.ModuleWithTooFewClassesInspection
com.siyeh.ig.modularization.ModuleWithTooManyClassesInspection
com.siyeh.ig.naming.AnnotationNamingConventionInspection
diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java
index 3c7b035..b15ecb7 100644
--- a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.java
+++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReference.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.
@@ -24,6 +24,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -140,9 +141,7 @@
final Collection<PsiFileSystemItem> contexts = getContexts();
final Collection<ResolveResult> result = new THashSet<ResolveResult>();
for (final PsiFileSystemItem context : contexts) {
- if (context != null) {
- innerResolveInContext(referenceText, context, result, caseSensitive);
- }
+ innerResolveInContext(referenceText, context, result, caseSensitive);
}
if (contexts.isEmpty() && isAllowedEmptyPath(referenceText)) {
result.add(new PsiElementResolveResult(getElement().getContainingFile()));
@@ -189,7 +188,11 @@
context = ((PackagePrefixFileSystemItem)context).getDirectory();
}
- if (context instanceof PsiDirectory && caseSensitivityApplies((PsiDirectory)context, caseSensitive)) {
+ if (context.getParent() == null && FileUtil.namesEqual(decoded, context.getName())) {
+ // match filesystem roots
+ result.add(new PsiElementResolveResult(getOriginalFile(context)));
+ }
+ else if (context instanceof PsiDirectory && caseSensitivityApplies((PsiDirectory)context, caseSensitive)) {
// optimization: do not load all children into VFS
PsiDirectory directory = (PsiDirectory)context;
PsiFileSystemItem child = directory.findFile(decoded);
diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelper.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelper.java
index f5a992e..9e6e7a1 100644
--- a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelper.java
+++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelper.java
@@ -49,6 +49,10 @@
@Nullable
public PsiFileSystemItem getPsiFileSystemItem(final Project project, @NotNull final VirtualFile file) {
final PsiManager psiManager = PsiManager.getInstance(project);
+ return getPsiFileSystemItem(psiManager, file);
+ }
+
+ public static PsiFileSystemItem getPsiFileSystemItem(PsiManager psiManager, VirtualFile file) {
return file.isDirectory() ? psiManager.findDirectory(file) : psiManager.findFile(file);
}
diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelperRegistrar.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelperRegistrar.java
index 55811f7..599cca5 100644
--- a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelperRegistrar.java
+++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceHelperRegistrar.java
@@ -23,6 +23,8 @@
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import java.util.List;
+
/**
* @author peter
*/
@@ -35,6 +37,10 @@
return Extensions.getExtensions(FileReferenceHelper.EP_NAME);
}
+ /**
+ * @deprecated this method is broken, please avoid using it, use getHelpers() instead
+ */
+ @Deprecated
@NotNull
public static <T extends PsiFileSystemItem> FileReferenceHelper getNotNullHelper(@NotNull T psiFileSystemItem) {
FileReferenceHelper helper = getHelper(psiFileSystemItem);
@@ -45,6 +51,10 @@
return helpers[helpers.length-1];
}
+ /**
+ * @deprecated this method is broken, please avoid using it, use getHelpers() instead
+ */
+ @Deprecated
public static <T extends PsiFileSystemItem> FileReferenceHelper getHelper(@NotNull final T psiFileSystemItem) {
final VirtualFile file = psiFileSystemItem.getVirtualFile();
if (file == null) return null;
@@ -57,6 +67,18 @@
});
}
+ public static <T extends PsiFileSystemItem> List<FileReferenceHelper> getHelpers(@NotNull final T psiFileSystemItem) {
+ final VirtualFile file = psiFileSystemItem.getVirtualFile();
+ if (file == null) return null;
+ final Project project = psiFileSystemItem.getProject();
+ return ContainerUtil.findAll(getHelpers(), new Condition<FileReferenceHelper>() {
+ @Override
+ public boolean value(final FileReferenceHelper fileReferenceHelper) {
+ return fileReferenceHelper.isMine(project, file);
+ }
+ });
+ }
+
public static boolean areElementsEquivalent(@NotNull final PsiFileSystemItem element1, @NotNull final PsiFileSystemItem element2) {
return element2.getManager().areElementsEquivalent(element1, element2);
}
diff --git a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java
index 33ea139..c0a3120 100644
--- a/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.java
+++ b/platform/analysis-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/FileReferenceSet.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,6 +28,8 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.Function;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -121,6 +123,10 @@
return "/";
}
+ /**
+ * This should be removed. Please use {@link FileReference#getContexts()} instead.
+ */
+ @Deprecated
protected Collection<PsiFileSystemItem> getExtraContexts() {
return Collections.emptyList();
}
@@ -223,7 +229,6 @@
protected List<FileReference> reparse(String str, int startInElement) {
final List<FileReference> referencesList = new ArrayList<FileReference>();
-
String separatorString = getSeparatorString(); // separator's length can be more then 1 char
int sepLen = separatorString.length();
int currentSlash = -sepLen;
@@ -246,17 +251,16 @@
}
while (true) {
- final int nextSlash = str.indexOf(separatorString, currentSlash + sepLen);
- final String subreferenceText = nextSlash > 0 ? str.substring(currentSlash + sepLen, nextSlash) : str.substring(currentSlash + sepLen);
- final FileReference ref = createFileReference(
- new TextRange(startInElement + currentSlash + sepLen, startInElement + (nextSlash > 0 ? nextSlash : str.length())),
- index++,
- subreferenceText);
+ int nextSlash = str.indexOf(separatorString, currentSlash + sepLen);
+ String subReferenceText = nextSlash > 0 ? str.substring(currentSlash + sepLen, nextSlash) : str.substring(currentSlash + sepLen);
+ TextRange range = new TextRange(startInElement + currentSlash + sepLen, startInElement + (nextSlash > 0 ? nextSlash : str.length()));
+ FileReference ref = createFileReference(range, index++, subReferenceText);
referencesList.add(ref);
if ((currentSlash = nextSlash) < 0) {
break;
}
}
+
return referencesList;
}
@@ -292,19 +296,17 @@
if (myOptions != null) {
final Function<PsiFile, Collection<PsiFileSystemItem>> value = DEFAULT_PATH_EVALUATOR_OPTION.getValue(myOptions);
-
if (value != null) {
final Collection<PsiFileSystemItem> roots = value.fun(file);
if (roots != null) {
for (PsiFileSystemItem root : roots) {
- if (root == null) {
- LOG.error("Default path evaluator " + value + " produced a null root for " + file);
- }
+ LOG.assertTrue(root != null, "Default path evaluator " + value + " produced a null root for " + file);
}
return roots;
}
}
}
+
if (isAbsolutePathReference()) {
return getAbsoluteTopLevelDirLocations(file);
}
@@ -315,12 +317,10 @@
@Nullable
protected PsiFile getContainingFile() {
PsiFile cf = myElement.getContainingFile();
- final PsiFile file = InjectedLanguageManager.getInstance(cf.getProject()).getTopLevelFile(cf);
- if (file == null) {
- LOG.error("Invalid element: " + myElement);
- }
-
- return file.getOriginalFile();
+ PsiFile file = InjectedLanguageManager.getInstance(cf.getProject()).getTopLevelFile(cf);
+ if (file != null) return file.getOriginalFile();
+ LOG.error("Invalid element: " + myElement);
+ return null;
}
@NotNull
@@ -395,20 +395,16 @@
@NotNull
public static Collection<PsiFileSystemItem> getAbsoluteTopLevelDirLocations(@NotNull final PsiFile file) {
-
final VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile == null) {
- return Collections.emptyList();
- }
- final Project project = file.getProject();
- PsiDirectory parent = file.getParent();
+ if (virtualFile == null) return Collections.emptyList();
+
+ final PsiDirectory parent = file.getParent();
final Module module = ModuleUtilCore.findModuleForPsiElement(parent == null ? file : parent);
- if (module == null) {
- return Collections.emptyList();
- }
- final FileReferenceHelper[] helpers = FileReferenceHelperRegistrar.getHelpers();
- final ArrayList<PsiFileSystemItem> list = new ArrayList<PsiFileSystemItem>();
- for (FileReferenceHelper helper : helpers) {
+ if (module == null) return Collections.emptyList();
+
+ final List<PsiFileSystemItem> list = new ArrayList<PsiFileSystemItem>();
+ final Project project = file.getProject();
+ for (FileReferenceHelper helper : FileReferenceHelperRegistrar.getHelpers()) {
if (helper.isMine(project, virtualFile)) {
if (helper.isFallback() && !list.isEmpty()) {
continue;
@@ -420,10 +416,25 @@
list.addAll(roots);
}
}
-
return list;
}
+ @NotNull
+ protected Collection<PsiFileSystemItem> toFileSystemItems(VirtualFile... files) {
+ return toFileSystemItems(Arrays.asList(files));
+ }
+
+ @NotNull
+ protected Collection<PsiFileSystemItem> toFileSystemItems(@NotNull Collection<VirtualFile> files) {
+ final PsiManager manager = getElement().getManager();
+ return ContainerUtil.mapNotNull(files, new NullableFunction<VirtualFile, PsiFileSystemItem>() {
+ @Override
+ public PsiFileSystemItem fun(VirtualFile file) {
+ return file != null ? manager.findDirectory(file) : null;
+ }
+ });
+ }
+
protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
return Conditions.alwaysTrue();
}
diff --git a/platform/annotations/src/org/intellij/lang/annotations/Flow.java b/platform/annotations/src/org/intellij/lang/annotations/Flow.java
index b52ae79..a6ea578 100644
--- a/platform/annotations/src/org/intellij/lang/annotations/Flow.java
+++ b/platform/annotations/src/org/intellij/lang/annotations/Flow.java
@@ -19,7 +19,6 @@
import java.lang.annotation.*;
-@Documented
@Retention(RetentionPolicy.CLASS)
@Target({ElementType.PARAMETER, ElementType.METHOD})
/**
diff --git a/platform/annotations/src/org/jetbrains/annotations/TestOnly.java b/platform/annotations/src/org/jetbrains/annotations/TestOnly.java
index f3ca739..81769fd 100644
--- a/platform/annotations/src/org/jetbrains/annotations/TestOnly.java
+++ b/platform/annotations/src/org/jetbrains/annotations/TestOnly.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.
@@ -26,6 +26,6 @@
*/
@Documented
@Retention(RetentionPolicy.SOURCE)
-@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
public @interface TestOnly {
}
diff --git a/platform/bootstrap/src/com/intellij/ide/Bootstrap.java b/platform/bootstrap/src/com/intellij/ide/Bootstrap.java
index 00fab13..95cdeea 100644
--- a/platform/bootstrap/src/com/intellij/ide/Bootstrap.java
+++ b/platform/bootstrap/src/com/intellij/ide/Bootstrap.java
@@ -26,10 +26,6 @@
public class Bootstrap {
private static final String PLUGIN_MANAGER = "com.intellij.ide.plugins.PluginManager";
- /** @deprecated use StartupUtil.NO_SPLASH if needed (to remove in 134.x) */
- @SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
- public static final String NO_SPLASH = "nosplash";
-
private Bootstrap() { }
public static void main(String[] args, String mainClass, String methodName) throws Exception {
diff --git a/platform/bootstrap/src/com/intellij/idea/Main.java b/platform/bootstrap/src/com/intellij/idea/Main.java
index 835fa4d..33a95c5 100644
--- a/platform/bootstrap/src/com/intellij/idea/Main.java
+++ b/platform/bootstrap/src/com/intellij/idea/Main.java
@@ -153,11 +153,12 @@
System.getProperty("java.home") + "/bin/java",
"-Xmx500m",
"-classpath",
- copyPatchFile.getPath(),
+ copyPatchFile.getPath() + File.pathSeparator + PathManager.getLibPath() + "/log4j.jar",
"-Djava.io.tmpdir=" + tempDir,
"com.intellij.updater.Runner",
"install",
- PathManager.getHomePath());
+ PathManager.getHomePath(),
+ PathManager.getLogPath());
status = Restarter.scheduleRestart(ArrayUtilRt.toStringArray(args));
}
diff --git a/platform/core-api/src/com/intellij/codeInsight/CodeInsightBundle.java b/platform/core-api/src/com/intellij/codeInsight/CodeInsightBundle.java
index 94d27d7..1b5a133 100644
--- a/platform/core-api/src/com/intellij/codeInsight/CodeInsightBundle.java
+++ b/platform/core-api/src/com/intellij/codeInsight/CodeInsightBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author max
*/
public class CodeInsightBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.CodeInsightBundle";
private CodeInsightBundle() {
}
- public static String message(@NonNls @PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-api/src/com/intellij/concurrency/JobLauncher.java b/platform/core-api/src/com/intellij/concurrency/JobLauncher.java
deleted file mode 100644
index 2822832..0000000
--- a/platform/core-api/src/com/intellij/concurrency/JobLauncher.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.concurrency;
-
-import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.progress.ProcessCanceledException;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.util.Consumer;
-import com.intellij.util.Processor;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
-import java.util.concurrent.Future;
-
-public abstract class JobLauncher {
- public static JobLauncher getInstance() {
- return ServiceManager.getService(JobLauncher.class);
- }
-
- /**
- * Schedules concurrent execution of #thingProcessor over each element of #things and waits for completion
- * With checkCanceled in each thread delegated to our current progress
- *
- * @param things data to process concurrently
- * @param progress progress indicator
- * @param failFastOnAcquireReadAction if true, returns false when failed to acquire read action
- * @param thingProcessor to be invoked concurrently on each element from the collection
- * @return false if tasks have been canceled,
- * or at least one processor returned false,
- * or threw an exception,
- * or we were unable to start read action in at least one thread
- * @throws ProcessCanceledException if at least one task has thrown ProcessCanceledException
- */
- public abstract <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
- ProgressIndicator progress,
- boolean failFastOnAcquireReadAction,
- @NotNull Processor<T> thingProcessor) throws ProcessCanceledException;
-
- public abstract <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
- ProgressIndicator progress,
- boolean runInReadAction,
- boolean failFastOnAcquireReadAction,
- @NotNull Processor<T> thingProcessor) throws ProcessCanceledException;
-
- @NotNull
- public abstract <T> AsyncFuture<Boolean> invokeConcurrentlyUnderProgressAsync(@NotNull List<? extends T> things,
- ProgressIndicator progress,
- boolean failFastOnAcquireReadAction,
- @NotNull Processor<T> thingProcessor);
-
-
- @NotNull
- public abstract Job<Void> submitToJobThread(int priority, @NotNull final Runnable action, @Nullable Consumer<Future> onDoneCallback);
-
- @NotNull
- public Job<Void> submitToJobThread(int priority, @NotNull final Runnable action) {
- return submitToJobThread(priority, action, null);
- }
-}
diff --git a/platform/core-api/src/com/intellij/core/CoreBundle.java b/platform/core-api/src/com/intellij/core/CoreBundle.java
index 36f4ccd..4423cda 100644
--- a/platform/core-api/src/com/intellij/core/CoreBundle.java
+++ b/platform/core-api/src/com/intellij/core/CoreBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author max
*/
public class CoreBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.CoreBundle";
private CoreBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-api/src/com/intellij/ide/IdeBundle.java b/platform/core-api/src/com/intellij/ide/IdeBundle.java
index d604862..51e4c1b 100644
--- a/platform/core-api/src/com/intellij/ide/IdeBundle.java
+++ b/platform/core-api/src/com/intellij/ide/IdeBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* @author yole
*/
public class IdeBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.IdeBundle";
private IdeBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-api/src/com/intellij/ide/presentation/VirtualFilePresentation.java b/platform/core-api/src/com/intellij/ide/presentation/VirtualFilePresentation.java
index 50fe043..d2d5ebf 100644
--- a/platform/core-api/src/com/intellij/ide/presentation/VirtualFilePresentation.java
+++ b/platform/core-api/src/com/intellij/ide/presentation/VirtualFilePresentation.java
@@ -1,8 +1,24 @@
+/*
+ * 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.ide.presentation;
import com.intellij.ide.TypePresentationService;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PlatformIcons;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -10,7 +26,7 @@
* @author yole
*/
public class VirtualFilePresentation {
- public static Icon getIcon(VirtualFile vFile) {
+ public static Icon getIcon(@NotNull VirtualFile vFile) {
Icon icon = TypePresentationService.getService().getIcon(vFile);
if (icon != null) {
return icon;
diff --git a/platform/platform-api/src/com/intellij/ide/util/PropertiesComponent.java b/platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
similarity index 100%
rename from platform/platform-api/src/com/intellij/ide/util/PropertiesComponent.java
rename to platform/core-api/src/com/intellij/ide/util/PropertiesComponent.java
diff --git a/platform/core-api/src/com/intellij/ide/util/PropertyName.java b/platform/core-api/src/com/intellij/ide/util/PropertyName.java
new file mode 100644
index 0000000..8e7164f
--- /dev/null
+++ b/platform/core-api/src/com/intellij/ide/util/PropertyName.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.ide.util;
+
+import java.lang.annotation.*;
+
+/**
+ * Allows to pass property name of field
+ *
+ * @author Konstantin Bulenkov
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface PropertyName {
+ String NOT_SET = "";
+ String value();
+ String defaultValue() default NOT_SET;
+}
diff --git a/platform/core-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java b/platform/core-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java
index f942013..067badf 100644
--- a/platform/core-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java
+++ b/platform/core-api/src/com/intellij/lang/folding/CompositeFoldingBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -80,4 +80,9 @@
final FoldingBuilder builder = node.getUserData(FOLDING_BUILDER);
return builder != null && builder.isCollapsedByDefault(node);
}
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName() + myBuilders;
+ }
}
diff --git a/platform/lang-api/src/com/intellij/lexer/FilterLexer.java b/platform/core-api/src/com/intellij/lexer/FilterLexer.java
similarity index 100%
rename from platform/lang-api/src/com/intellij/lexer/FilterLexer.java
rename to platform/core-api/src/com/intellij/lexer/FilterLexer.java
diff --git a/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java b/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java
index a163e5b..882e11a 100644
--- a/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.java
+++ b/platform/core-api/src/com/intellij/lexer/StringLiteralLexer.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.
@@ -38,13 +38,13 @@
private int myState;
private int myLastState;
private int myBufferEnd;
- private char myQuoteChar;
- private IElementType myOriginalLiteralToken;
+ private final char myQuoteChar;
+ private final IElementType myOriginalLiteralToken;
private final boolean myCanEscapeEolOrFramingSpaces;
private final String myAdditionalValidEscapes;
private boolean mySeenEscapedSpacesOnly;
- private boolean myAllowOctal;
- private boolean myAllowHex;
+ private final boolean myAllowOctal;
+ private final boolean myAllowHex;
public StringLiteralLexer(char quoteChar, final IElementType originalLiteralToken) {
this(quoteChar, originalLiteralToken, false, null);
@@ -55,17 +55,23 @@
* '\' in the end of the buffer (meaning escaped end of line) or
* '\ ' (escaped space) in the beginning and in the end of the buffer (meaning escaped space, to avoid auto trimming on load)
*/
- public StringLiteralLexer(char quoteChar, final IElementType originalLiteralToken, boolean canEscapeEolOrFramingSpaces, String additionalValidEscapes) {
+ public StringLiteralLexer(char quoteChar,
+ final IElementType originalLiteralToken,
+ boolean canEscapeEolOrFramingSpaces,
+ String additionalValidEscapes) {
this(quoteChar, originalLiteralToken, canEscapeEolOrFramingSpaces, additionalValidEscapes, true, false);
}
/**
* @param canEscapeEolOrFramingSpaces true if following sequences are acceptable
* '\' in the end of the buffer (meaning escaped end of line) or
- * @param allowOctal
*/
- public StringLiteralLexer(char quoteChar, final IElementType originalLiteralToken, boolean canEscapeEolOrFramingSpaces, String additionalValidEscapes,
- boolean allowOctal, boolean allowHex) {
+ public StringLiteralLexer(char quoteChar,
+ final IElementType originalLiteralToken,
+ boolean canEscapeEolOrFramingSpaces,
+ String additionalValidEscapes,
+ boolean allowOctal,
+ boolean allowHex) {
myQuoteChar = quoteChar;
myOriginalLiteralToken = originalLiteralToken;
myCanEscapeEolOrFramingSpaces = canEscapeEolOrFramingSpaces;
@@ -78,12 +84,7 @@
public void start(@NotNull CharSequence buffer, int startOffset, int endOffset, int initialState) {
myBuffer = buffer;
myStart = startOffset;
- if (myQuoteChar == NO_QUOTE_CHAR) {
- myState = AFTER_FIRST_QUOTE;
- }
- else {
- myState = initialState;
- }
+ myState = myQuoteChar == NO_QUOTE_CHAR ? AFTER_FIRST_QUOTE : initialState;
myLastState = initialState;
myBufferEnd = endOffset;
myEnd = locateToken(myStart);
@@ -136,6 +137,7 @@
case '6':
case '7':
if (!myAllowOctal) return StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN;
+ //noinspection fallthrough
case 'n':
case 'r':
case 'b':
@@ -223,15 +225,11 @@
return i + 1;
}
}
- LOG.assertTrue(myState == AFTER_FIRST_QUOTE || myBuffer.charAt(i) == myQuoteChar, myState);
+ LOG.assertTrue(myState == AFTER_FIRST_QUOTE || myBuffer.charAt(i) == myQuoteChar, this);
while (i < myBufferEnd) {
if (myBuffer.charAt(i) == '\\') {
return i;
}
- //if (myBuffer[i] == '\n') {
- // myState = AFTER_LAST_QUOTE;
- // return i;
- //}
if (myState == AFTER_FIRST_QUOTE && myBuffer.charAt(i) == myQuoteChar) {
if (i + 1 == myBufferEnd) myState = AFTER_LAST_QUOTE;
return i + 1;
@@ -261,4 +259,23 @@
return myBufferEnd;
}
+ @SuppressWarnings("HardCodedStringLiteral")
+ @Override
+ public String toString() {
+ return "StringLiteralLexer {" +
+ "myAllowHex=" + myAllowHex +
+ ", myAllowOctal=" + myAllowOctal +
+ ", mySeenEscapedSpacesOnly=" + mySeenEscapedSpacesOnly +
+ ", myAdditionalValidEscapes='" + myAdditionalValidEscapes + '\'' +
+ ", myCanEscapeEolOrFramingSpaces=" + myCanEscapeEolOrFramingSpaces +
+ ", myOriginalLiteralToken=" + myOriginalLiteralToken +
+ ", myQuoteChar=" + myQuoteChar +
+ ", myBufferEnd=" + myBufferEnd +
+ ", myLastState=" + myLastState +
+ ", myState=" + myState +
+ ", myEnd=" + myEnd +
+ ", myStart=" + myStart +
+ ", myToken=" + (myBuffer == null ? null : myBuffer.subSequence(myStart, myEnd)) +
+ '}';
+ }
}
diff --git a/platform/core-api/src/com/intellij/openapi/application/Application.java b/platform/core-api/src/com/intellij/openapi/application/Application.java
index e8789fb..2db5ca6 100644
--- a/platform/core-api/src/com/intellij/openapi/application/Application.java
+++ b/platform/core-api/src/com/intellij/openapi/application/Application.java
@@ -17,7 +17,6 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ComponentManager;
-import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.ThrowableComputable;
@@ -385,10 +384,4 @@
boolean isInternal();
boolean isEAP();
-
- /**
- * Find a plugin that loaded a class with the given name
- */
- @Nullable
- PluginId getPluginByClassName(@NotNull String className);
}
diff --git a/platform/core-api/src/com/intellij/openapi/application/BaseActionRunnable.java b/platform/core-api/src/com/intellij/openapi/application/BaseActionRunnable.java
index 212ac02..6bd8f05 100644
--- a/platform/core-api/src/com/intellij/openapi/application/BaseActionRunnable.java
+++ b/platform/core-api/src/com/intellij/openapi/application/BaseActionRunnable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -25,7 +25,7 @@
return mySilentExecution;
}
- protected abstract void run(Result<T> result) throws Throwable;
+ protected abstract void run(@NotNull Result<T> result) throws Throwable;
@NotNull
public abstract RunResult<T> execute();
diff --git a/platform/core-api/src/com/intellij/openapi/application/ModalityState.java b/platform/core-api/src/com/intellij/openapi/application/ModalityState.java
index fde7562..7ade35e 100644
--- a/platform/core-api/src/com/intellij/openapi/application/ModalityState.java
+++ b/platform/core-api/src/com/intellij/openapi/application/ModalityState.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.
@@ -63,4 +63,7 @@
}
public abstract boolean dominates(@NotNull ModalityState anotherState);
+
+ @Override
+ public abstract String toString();
}
diff --git a/platform/core-api/src/com/intellij/openapi/application/RunResult.java b/platform/core-api/src/com/intellij/openapi/application/RunResult.java
index 8ff9327..85c8448 100644
--- a/platform/core-api/src/com/intellij/openapi/application/RunResult.java
+++ b/platform/core-api/src/com/intellij/openapi/application/RunResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
+import org.jetbrains.annotations.NotNull;
public class RunResult<T> extends Result<T> {
@@ -28,7 +29,7 @@
protected RunResult() {
}
- public RunResult(BaseActionRunnable<T> action) {
+ public RunResult(@NotNull BaseActionRunnable<T> action) {
myActionRunnable = action;
}
diff --git a/platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java b/platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java
index 4be6c35..f2e891d 100644
--- a/platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java
+++ b/platform/core-api/src/com/intellij/openapi/command/WriteCommandAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
import com.intellij.openapi.application.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -150,11 +151,10 @@
/**
* WriteCommandAction without result
*/
- public abstract static class Simple extends WriteCommandAction {
+ public abstract static class Simple<T> extends WriteCommandAction<T> {
protected Simple(final Project project, PsiFile... files) {
super(project, files);
}
-
protected Simple(final Project project, final String commandName, final PsiFile... files) {
super(project, commandName, files);
}
@@ -164,11 +164,29 @@
}
@Override
- protected void run(final Result result) throws Throwable {
+ protected void run(@NotNull final Result<T> result) throws Throwable {
run();
}
protected abstract void run() throws Throwable;
}
+
+ public static void runWriteCommandAction(Project project, @NotNull final Runnable runnable) {
+ new Simple(project) {
+ @Override
+ protected void run() throws Throwable {
+ runnable.run();
+ }
+ }.execute();
+ }
+
+ public static <T> T runWriteCommandAction(Project project, @NotNull final Computable<T> computable) {
+ return new WriteCommandAction<T>(project) {
+ @Override
+ protected void run(@NotNull Result<T> result) throws Throwable {
+ result.setResult(computable.compute());
+ }
+ }.execute().getResultObject();
+ }
}
diff --git a/platform/core-api/src/com/intellij/openapi/editor/Document.java b/platform/core-api/src/com/intellij/openapi/editor/Document.java
index be5331b..de70048 100644
--- a/platform/core-api/src/com/intellij/openapi/editor/Document.java
+++ b/platform/core-api/src/com/intellij/openapi/editor/Document.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.
@@ -49,6 +49,7 @@
*
* @return document content.
*/
+ @NotNull
String getText();
@NotNull String getText(@NotNull TextRange range);
@@ -65,6 +66,13 @@
@NotNull CharSequence getCharsSequence();
/**
+ * @return a char sequence representing document content that's guaranteed to be immutable. No read- or write-action is necessary.
+ * @see com.intellij.util.text.ImmutableCharSequence
+ */
+ @NotNull
+ CharSequence getImmutableCharSequence();
+
+ /**
* @deprecated Use {@link #getCharsSequence()} or {@link #getText()} instead.
*/
@NotNull char[] getChars();
diff --git a/platform/core-api/src/com/intellij/openapi/editor/EditorBundle.java b/platform/core-api/src/com/intellij/openapi/editor/EditorBundle.java
index 933ddf2..5a407e7 100644
--- a/platform/core-api/src/com/intellij/openapi/editor/EditorBundle.java
+++ b/platform/core-api/src/com/intellij/openapi/editor/EditorBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author lesya
*/
public class EditorBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "messages.EditorBundle";
private EditorBundle() {
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java b/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java
index 53f0565..5425806 100644
--- a/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java
+++ b/platform/core-api/src/com/intellij/openapi/editor/colors/TextAttributesKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -28,7 +28,7 @@
/**
* A type of item with a distinct highlighting in an editor or in other views.
*/
-public final class TextAttributesKey implements Comparable<TextAttributesKey>, JDOMExternalizable {
+public final class TextAttributesKey implements Comparable<TextAttributesKey> {
private static final TextAttributes NULL_ATTRIBUTES = new TextAttributes();
private static final ConcurrentHashMap<String, TextAttributesKey> ourRegistry = new ConcurrentHashMap<String, TextAttributesKey>();
private static final NullableLazyValue<TextAttributeKeyDefaultsProvider> ourDefaultsProvider = new VolatileNullableLazyValue<TextAttributeKeyDefaultsProvider>() {
@@ -39,9 +39,8 @@
}
};
- public String myExternalName;
- public TextAttributes myDefaultAttributes = NULL_ATTRIBUTES;
-
+ private final String myExternalName;
+ private TextAttributes myDefaultAttributes = NULL_ATTRIBUTES;
private TextAttributesKey myFallbackAttributeKey;
private TextAttributesKey(String externalName) {
@@ -49,10 +48,16 @@
}
//read external only
- public TextAttributesKey() {
+ public TextAttributesKey(@NotNull Element element) throws InvalidDataException {
+ this(JDOMExternalizerUtil.readField(element, "myExternalName"));
+ Element myDefaultAttributesElement = JDOMExternalizerUtil.getOption(element, "myDefaultAttributes");
+ if (myDefaultAttributesElement != null) {
+ myDefaultAttributes = new TextAttributes(myDefaultAttributesElement);
+ }
}
- @NotNull public static TextAttributesKey find(@NotNull @NonNls String externalName) {
+ @NotNull
+ public static TextAttributesKey find(@NotNull @NonNls String externalName) {
return ourRegistry.cacheOrGet(externalName, new TextAttributesKey(externalName));
}
@@ -80,14 +85,13 @@
return find(externalName);
}
- @Override
- public void readExternal(Element element) throws InvalidDataException {
- DefaultJDOMExternalizer.readExternal(this, element);
- }
-
- @Override
public void writeExternal(Element element) throws WriteExternalException {
- DefaultJDOMExternalizer.writeExternal(this, element);
+ JDOMExternalizerUtil.writeField(element, "myExternalName", myExternalName);
+
+ if (myDefaultAttributes != NULL_ATTRIBUTES) {
+ Element option = JDOMExternalizerUtil.writeOption(element, "myDefaultAttributes");
+ myDefaultAttributes.writeExternal(option);
+ }
}
@@ -115,8 +119,9 @@
if (myDefaultAttributes == NULL_ATTRIBUTES) {
myDefaultAttributes = null;
final TextAttributeKeyDefaultsProvider provider = ourDefaultsProvider.getValue();
- if (provider != null)
+ if (provider != null) {
myDefaultAttributes = provider.getDefaultAttributes(this);
+ }
}
else if (myDefaultAttributes == null) {
myDefaultAttributes = NULL_ATTRIBUTES;
diff --git a/platform/core-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java b/platform/core-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java
index 411fc5e..8ef82d5 100644
--- a/platform/core-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.java
+++ b/platform/core-api/src/com/intellij/openapi/editor/markup/AttributesFlyweight.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,26 +20,31 @@
package com.intellij.openapi.editor.markup;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.DefaultJDOMExternalizer;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.JDOMExternalizerUtil;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.containers.StripedLockConcurrentHashMap;
import org.intellij.lang.annotations.JdkConstants;
+import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
+import java.util.concurrent.ConcurrentMap;
public class AttributesFlyweight {
- private static final StripedLockConcurrentHashMap<FlyweightKey, AttributesFlyweight> entries = new StripedLockConcurrentHashMap<FlyweightKey, AttributesFlyweight>();
+ private static final ConcurrentMap<FlyweightKey, AttributesFlyweight> entries = new StripedLockConcurrentHashMap<FlyweightKey, AttributesFlyweight>();
private static final ThreadLocal<FlyweightKey> ourKey = new ThreadLocal<FlyweightKey>();
private final int myHashCode;
- private final Color myForeground;
- private final Color myBackground;
+ private final Color myForeground;
+ private final Color myBackground;
@JdkConstants.FontStyle
- private final int myFontType;
- private final Color myEffectColor;
+ private final int myFontType;
+ private final Color myEffectColor;
private final EffectType myEffectType;
- private final Color myErrorStripeColor;
+ private final Color myErrorStripeColor;
private static class FlyweightKey implements Cloneable {
private Color foreground;
@@ -128,6 +133,86 @@
myHashCode = calcHashCode(foreground, background, fontType, effectColor, effectType, errorStripeColor);
}
+ @NotNull
+ public static AttributesFlyweight create(@NotNull Element element) throws InvalidDataException {
+ Color FOREGROUND = DefaultJDOMExternalizer.toColor(JDOMExternalizerUtil.readField(element, "FOREGROUND"));
+ Color BACKGROUND = DefaultJDOMExternalizer.toColor(JDOMExternalizerUtil.readField(element, "BACKGROUND"));
+ Color EFFECT_COLOR = DefaultJDOMExternalizer.toColor(JDOMExternalizerUtil.readField(element, "EFFECT_COLOR"));
+ Color ERROR_STRIPE_COLOR = DefaultJDOMExternalizer.toColor(JDOMExternalizerUtil.readField(element, "ERROR_STRIPE_COLOR"));
+ int fontType = DefaultJDOMExternalizer.toInt(JDOMExternalizerUtil.readField(element, "FONT_TYPE", "0"));
+ if (fontType < 0 || fontType > 3) {
+ fontType = 0;
+ }
+ int FONT_TYPE = fontType;
+ int EFFECT_TYPE = DefaultJDOMExternalizer.toInt(JDOMExternalizerUtil.readField(element, "EFFECT_TYPE", "0"));
+
+ return create(FOREGROUND, BACKGROUND, FONT_TYPE, EFFECT_COLOR, toEffectType(EFFECT_TYPE), ERROR_STRIPE_COLOR);
+ }
+
+ private static void writeColor(Element element, String fieldName, Color color) {
+ if (color != null) {
+ String string = Integer.toString(color.getRGB() & 0xFFFFFF, 16);
+ JDOMExternalizerUtil.writeField(element, fieldName, string);
+ }
+ }
+
+ void writeExternal(@NotNull Element element) {
+ writeColor(element, "FOREGROUND", getForeground());
+ writeColor(element, "BACKGROUND", getBackground());
+ int fontType = getFontType();
+ if (fontType != 0) {
+ JDOMExternalizerUtil.writeField(element, "FONT_TYPE", String.valueOf(fontType));
+ }
+ writeColor(element, "EFFECT_COLOR", getEffectColor());
+ writeColor(element, "ERROR_STRIPE_COLOR", getErrorStripeColor());
+ JDOMExternalizerUtil.writeField(element, "EFFECT_TYPE", String.valueOf(fromEffectType(getEffectType())));
+ }
+
+ private static final int EFFECT_BORDER = 0;
+ private static final int EFFECT_LINE = 1;
+ private static final int EFFECT_WAVE = 2;
+ private static final int EFFECT_STRIKEOUT = 3;
+ private static final int EFFECT_BOLD_LINE = 4;
+ private static final int EFFECT_BOLD_DOTTED_LINE = 5;
+
+ private static int fromEffectType(EffectType effectType) {
+ int EFFECT_TYPE;
+ if (effectType == EffectType.BOXED) {
+ EFFECT_TYPE = EFFECT_BORDER;
+ }
+ else if (effectType == EffectType.LINE_UNDERSCORE) {
+ EFFECT_TYPE = EFFECT_LINE;
+ }
+ else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
+ EFFECT_TYPE = EFFECT_BOLD_LINE;
+ }
+ else if (effectType == EffectType.STRIKEOUT) {
+ EFFECT_TYPE = EFFECT_STRIKEOUT;
+ }
+ else if (effectType == EffectType.WAVE_UNDERSCORE) {
+ EFFECT_TYPE = EFFECT_WAVE;
+ }
+ else if (effectType == EffectType.BOLD_DOTTED_LINE) {
+ EFFECT_TYPE = EFFECT_BOLD_DOTTED_LINE;
+ }
+ else {
+ EFFECT_TYPE = -1;
+ }
+ return EFFECT_TYPE;
+ }
+
+ private static EffectType toEffectType(int effectType) {
+ switch (effectType) {
+ case EFFECT_BORDER: return EffectType.BOXED;
+ case EFFECT_BOLD_LINE: return EffectType.BOLD_LINE_UNDERSCORE;
+ case EFFECT_LINE: return EffectType.LINE_UNDERSCORE;
+ case EFFECT_STRIKEOUT: return EffectType.STRIKEOUT;
+ case EFFECT_WAVE: return EffectType.WAVE_UNDERSCORE;
+ case EFFECT_BOLD_DOTTED_LINE: return EffectType.BOLD_DOTTED_LINE;
+ default: return null;
+ }
+ }
+
private static int calcHashCode(Color foreground,
Color background,
int fontType,
diff --git a/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java b/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java
index 008e7a5..c9d4bd5 100644
--- a/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java
+++ b/platform/core-api/src/com/intellij/openapi/editor/markup/TextAttributes.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.editor.markup;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
@@ -27,7 +26,6 @@
import org.jetbrains.annotations.Nullable;
import java.awt.*;
-import java.lang.reflect.Field;
/**
* Defines the visual representation (colors and effects) of text.
@@ -37,7 +35,7 @@
public static final TextAttributes ERASE_MARKER = new TextAttributes();
- private boolean myEnforcedDefaults = false;
+ private boolean myEnforcedDefaults;
@NotNull
private AttributesFlyweight myAttrs;
@@ -70,103 +68,19 @@
return attrs;
}
- private static class Externalizable implements Cloneable, JDOMExternalizable {
- public Color FOREGROUND = null;
- public Color BACKGROUND = null;
-
- @JdkConstants.FontStyle
- public int FONT_TYPE = Font.PLAIN;
-
- public Color EFFECT_COLOR = null;
- public int EFFECT_TYPE = EFFECT_BORDER;
- public Color ERROR_STRIPE_COLOR = null;
-
- private static final int EFFECT_BORDER = 0;
- private static final int EFFECT_LINE = 1;
- private static final int EFFECT_WAVE = 2;
- private static final int EFFECT_STRIKEOUT = 3;
- private static final int EFFECT_BOLD_LINE = 4;
- private static final int EFFECT_BOLD_DOTTED_LINE = 5;
-
- @Override
- public Object clone() throws CloneNotSupportedException {
- return super.clone();
- }
-
- @Override
- public void readExternal(Element element) throws InvalidDataException {
- DefaultJDOMExternalizer.readExternal(this, element);
- if (FONT_TYPE < 0 || FONT_TYPE > 3) {
- LOG.info("Wrong font type: " + FONT_TYPE);
- FONT_TYPE = 0;
- }
- }
-
- @Override
- public void writeExternal(Element element) throws WriteExternalException {
- DefaultJDOMExternalizer.writeExternal(this, element, new DefaultJDOMExternalizer.JDOMFilter() {
- @Override
- public boolean isAccept(@NotNull Field field) {
- try {
- if (field.getType().equals(Color.class) && field.get(Externalizable.this) == null) return false;
- if (field.getType().equals(int.class) && field.getInt(Externalizable.this) == 0) return false;
- }
- catch (IllegalAccessException e) {
- LOG.error("Can not access: " + field.getName());
- }
- return true;
- }
- });
- }
-
- private EffectType getEffectType() {
- switch (EFFECT_TYPE) {
- case EFFECT_BORDER:
- return EffectType.BOXED;
- case EFFECT_BOLD_LINE:
- return EffectType.BOLD_LINE_UNDERSCORE;
- case EFFECT_LINE:
- return EffectType.LINE_UNDERSCORE;
- case EFFECT_STRIKEOUT:
- return EffectType.STRIKEOUT;
- case EFFECT_WAVE:
- return EffectType.WAVE_UNDERSCORE;
- case EFFECT_BOLD_DOTTED_LINE:
- return EffectType.BOLD_DOTTED_LINE;
- default:
- return null;
- }
- }
-
- private void setEffectType(EffectType effectType) {
- if (effectType == EffectType.BOXED) {
- EFFECT_TYPE = EFFECT_BORDER;
- }
- else if (effectType == EffectType.LINE_UNDERSCORE) {
- EFFECT_TYPE = EFFECT_LINE;
- }
- else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) {
- EFFECT_TYPE = EFFECT_BOLD_LINE;
- }
- else if (effectType == EffectType.STRIKEOUT) {
- EFFECT_TYPE = EFFECT_STRIKEOUT;
- }
- else if (effectType == EffectType.WAVE_UNDERSCORE) {
- EFFECT_TYPE = EFFECT_WAVE;
- }
- else if (effectType == EffectType.BOLD_DOTTED_LINE) {
- EFFECT_TYPE = EFFECT_BOLD_DOTTED_LINE;
- }
- else {
- EFFECT_TYPE = -1;
- }
- }
- }
-
public TextAttributes() {
this(null, null, null, EffectType.BOXED, Font.PLAIN);
}
+ private TextAttributes(@NotNull AttributesFlyweight attributesFlyweight, boolean enforced) {
+ myAttrs = attributesFlyweight;
+ myEnforcedDefaults = enforced;
+ }
+
+ public TextAttributes(@NotNull Element element) throws InvalidDataException {
+ readExternal(element);
+ }
+
public TextAttributes(@Nullable Color foregroundColor, @Nullable Color backgroundColor, @Nullable Color effectColor, EffectType effectType, @JdkConstants.FontStyle int fontType) {
setAttributes(foregroundColor, backgroundColor, effectColor, null, effectType, fontType);
}
@@ -262,10 +176,7 @@
@Override
public TextAttributes clone() {
- TextAttributes cloned = new TextAttributes();
- cloned.myAttrs = myAttrs;
- cloned.myEnforcedDefaults = myEnforcedDefaults;
- return cloned;
+ return new TextAttributes(myAttrs, myEnforcedDefaults);
}
public boolean equals(Object obj) {
@@ -282,24 +193,13 @@
@Override
public void readExternal(Element element) throws InvalidDataException {
- Externalizable ext = new Externalizable();
- ext.readExternal(element);
- myAttrs = AttributesFlyweight.create(ext.FOREGROUND, ext.BACKGROUND, ext.FONT_TYPE, ext.EFFECT_COLOR, ext.getEffectType(), ext.ERROR_STRIPE_COLOR);
+ myAttrs = AttributesFlyweight.create(element);
if (isEmpty()) myEnforcedDefaults = true;
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
- Externalizable ext = new Externalizable();
-
- ext.FOREGROUND = myAttrs.getForeground();
- ext.BACKGROUND = myAttrs.getBackground();
- ext.FONT_TYPE = myAttrs.getFontType();
- ext.EFFECT_COLOR = myAttrs.getEffectColor();
- ext.ERROR_STRIPE_COLOR = myAttrs.getErrorStripeColor();
- ext.setEffectType(myAttrs.getEffectType());
-
- ext.writeExternal(element);
+ myAttrs.writeExternal(element);
}
@Override
diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java b/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java
new file mode 100644
index 0000000..bd69a0d
--- /dev/null
+++ b/platform/core-api/src/com/intellij/openapi/fileTypes/CharsetUtil.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ReflectionUtil;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.charset.Charset;
+import java.util.Map;
+
+/**
+ * @author peter
+ */
+public class CharsetUtil {
+ @SuppressWarnings("MismatchedQueryAndUpdenateOfCollection")
+ private static final Map<LanguageFileType, Boolean> ourSupportsCharsetDetection = new ConcurrentFactoryMap<LanguageFileType, Boolean>() {
+ @Nullable
+ @Override
+ protected Boolean create(LanguageFileType fileType) {
+ Class<?> ftClass = fileType.getClass();
+ String methodName = "extractCharsetFromFileContent";
+ Class declaring1 = ReflectionUtil.getMethodDeclaringClass(ftClass, methodName, Project.class, VirtualFile.class, String.class);
+ Class declaring2 = ReflectionUtil.getMethodDeclaringClass(ftClass, methodName, Project.class, VirtualFile.class, CharSequence.class);
+ return !LanguageFileType.class.equals(declaring1) || !LanguageFileType.class.equals(declaring2);
+ }
+ };
+
+ public static Charset extractCharsetFromFileContent(@Nullable Project project,
+ @Nullable VirtualFile virtualFile,
+ @Nullable FileType fileType,
+ @NotNull CharSequence text) {
+ if (fileType instanceof LanguageFileType &&
+ // otherwise the default implementations will always convert CharSequence to String unnecessarily, producing garbage
+ ourSupportsCharsetDetection.get(fileType)) {
+ return ((LanguageFileType)fileType).extractCharsetFromFileContent(project, virtualFile, text);
+ }
+ return null;
+ }
+}
diff --git a/platform/core-api/src/com/intellij/openapi/fileTypes/ContentBasedFileSubstitutor.java b/platform/core-api/src/com/intellij/openapi/fileTypes/ContentBasedFileSubstitutor.java
index 6ba20e8..890136b 100644
--- a/platform/core-api/src/com/intellij/openapi/fileTypes/ContentBasedFileSubstitutor.java
+++ b/platform/core-api/src/com/intellij/openapi/fileTypes/ContentBasedFileSubstitutor.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.
@@ -22,23 +22,16 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+/** @deprecated use com.intellij.psi.compiled.ClassFileDecompilers or com.intellij.psi.LanguageSubstitutors API (to remove in IDEA 14) */
+@SuppressWarnings("deprecation")
public interface ContentBasedFileSubstitutor {
ExtensionPointName<ContentBasedFileSubstitutor> EP_NAME = ExtensionPointName.create("com.intellij.contentBasedClassFileProcessor");
- /**
- * Checks whether appropriate specific activity is available on given file
- */
boolean isApplicable(Project project, VirtualFile vFile);
- /**
- * @return specific text representation of compiled classfile
- */
@NotNull
String obtainFileText(Project project, VirtualFile file);
- /**
- * @return language for compiled classfile
- */
@Nullable
Language obtainLanguageForFile(VirtualFile file);
}
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 214341c..fa04c3c 100644
--- a/platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java
+++ b/platform/core-api/src/com/intellij/openapi/fileTypes/LanguageFileType.java
@@ -66,7 +66,17 @@
return false;
}
+ /**
+ * Callers: use {@link com.intellij.openapi.fileTypes.CharsetUtil#extractCharsetFromFileContent(com.intellij.openapi.project.Project, com.intellij.openapi.vfs.VirtualFile, FileType, CharSequence)}
+ * Overriders: override {@link #extractCharsetFromFileContent(com.intellij.openapi.project.Project, com.intellij.openapi.vfs.VirtualFile, CharSequence)} instead
+ * @deprecated
+ */
public Charset extractCharsetFromFileContent(@Nullable Project project, @Nullable VirtualFile file, @NotNull String content) {
return null;
}
+
+ public Charset extractCharsetFromFileContent(@Nullable Project project, @Nullable VirtualFile file, @NotNull CharSequence content) {
+ //noinspection deprecation
+ return extractCharsetFromFileContent(project, file, content.toString());
+ }
}
diff --git a/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java b/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java
index 8ceef03..aa6d924 100644
--- a/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java
+++ b/platform/core-api/src/com/intellij/openapi/options/BaseSchemeProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -15,17 +15,19 @@
*/
package com.intellij.openapi.options;
+import org.jetbrains.annotations.NotNull;
+
/**
* @author yole
*/
public abstract class BaseSchemeProcessor<T extends ExternalizableScheme> implements SchemeProcessor<T> {
- public void initScheme(T scheme) {
+ public void initScheme(@NotNull T scheme) {
}
- public void onSchemeAdded(final T scheme) {
+ public void onSchemeAdded(@NotNull final T scheme) {
}
- public void onSchemeDeleted(final T scheme) {
+ public void onSchemeDeleted(@NotNull final T scheme) {
}
public void onCurrentSchemeChanged(final Scheme newCurrentScheme) {
diff --git a/platform/core-api/src/com/intellij/openapi/options/SchemeProcessor.java b/platform/core-api/src/com/intellij/openapi/options/SchemeProcessor.java
index 264d782..94ec194 100644
--- a/platform/core-api/src/com/intellij/openapi/options/SchemeProcessor.java
+++ b/platform/core-api/src/com/intellij/openapi/options/SchemeProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,18 +19,19 @@
import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Document;
import org.jdom.JDOMException;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public interface SchemeProcessor<T extends ExternalizableScheme> {
- T readScheme(Document schemeContent) throws InvalidDataException, IOException, JDOMException;
- Document writeScheme(T scheme) throws WriteExternalException;
+ T readScheme(@NotNull Document schemeContent) throws InvalidDataException, IOException, JDOMException;
+ Document writeScheme(@NotNull T scheme) throws WriteExternalException;
- boolean shouldBeSaved(T scheme);
- void initScheme(T scheme);
+ boolean shouldBeSaved(@NotNull T scheme);
+ void initScheme(@NotNull T scheme);
- void onSchemeAdded(T scheme);
- void onSchemeDeleted(T scheme);
+ void onSchemeAdded(@NotNull T scheme);
+ void onSchemeDeleted(@NotNull T scheme);
void onCurrentSchemeChanged(final Scheme oldCurrentScheme);
}
diff --git a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java
index 450f5c8..40559a1 100644
--- a/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java
+++ b/platform/core-api/src/com/intellij/openapi/options/SchemesManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -27,72 +27,89 @@
public interface SchemesManager <T extends Scheme, E extends ExternalizableScheme>{
SchemesManager EMPTY = new SchemesManager(){
+ @Override
@NotNull
public Collection loadSchemes() {
return Collections.emptySet();
}
+ @Override
@NotNull
public Collection loadSharedSchemes() {
return Collections.emptySet();
}
- public void exportScheme(final ExternalizableScheme scheme, final String name, final String description) {
+ @Override
+ public void exportScheme(@NotNull final ExternalizableScheme scheme, final String name, final String description) {
}
+ @Override
public boolean isImportAvailable() {
return false;
}
+ @Override
public boolean isExportAvailable() {
return false;
}
+ @Override
public boolean isShared(final Scheme scheme) {
return false;
}
+ @Override
public void addNewScheme(@NotNull final Scheme scheme, final boolean replaceExisting) {
}
+ @Override
public void clearAllSchemes() {
}
+ @Override
@NotNull
public List getAllSchemes() {
return Collections.emptyList();
}
+ @Override
public Scheme findSchemeByName(final String schemeName) {
return null;
}
+ @Override
public void save() {
}
+ @Override
public void setCurrentSchemeName(final String schemeName) {
}
+ @Override
public Scheme getCurrentScheme() {
return null;
}
+ @Override
public void removeScheme(final Scheme scheme) {
}
+ @Override
@NotNull
public Collection getAllSchemeNames() {
return Collections.emptySet();
}
+ @Override
@NotNull
public Collection loadSharedSchemes(final Collection currentSchemeList) {
return loadSharedSchemes();
}
+ @Override
public File getRootDirectory() {
return null;
}
@@ -103,7 +120,7 @@
@NotNull Collection<SharedScheme<E>> loadSharedSchemes();
@NotNull Collection<SharedScheme<E>> loadSharedSchemes(Collection<T> currentSchemeList);
- void exportScheme(final E scheme, final String name, final String description) throws WriteExternalException, IOException;
+ void exportScheme(@NotNull E scheme, final String name, final String description) throws WriteExternalException, IOException;
boolean isImportAvailable();
diff --git a/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java b/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java
index 55b9062..ef35993 100644
--- a/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java
+++ b/platform/core-api/src/com/intellij/openapi/options/SharedScheme.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,17 +15,20 @@
*/
package com.intellij.openapi.options;
+import org.jetbrains.annotations.NotNull;
+
public class SharedScheme<E extends ExternalizableScheme> {
private final String myUserName;
private final String myDescription;
private final E myScheme;
- public SharedScheme(final String userName, final String description, final E scheme) {
+ public SharedScheme(@NotNull String userName, final String description, @NotNull E scheme) {
myUserName = userName;
myDescription = description;
myScheme = scheme;
}
+ @NotNull
public String getUserName() {
return myUserName;
}
@@ -34,6 +37,7 @@
return myDescription;
}
+ @NotNull
public E getScheme() {
return myScheme;
}
diff --git a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
index 0fef333..cc7dddd 100644
--- a/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
+++ b/platform/core-api/src/com/intellij/openapi/roots/FileIndexFacade.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
@@ -61,4 +62,6 @@
public boolean shouldBeFound(GlobalSearchScope scope, VirtualFile virtualFile) {
return (scope.isSearchOutsideRootModel() || isInContent(virtualFile) || isInLibrarySource(virtualFile)) && !virtualFile.getFileType().isBinary();
}
+
+ @NotNull public abstract ModificationTracker getRootModificationTracker();
}
diff --git a/platform/core-api/src/com/intellij/openapi/util/ActionCallback.java b/platform/core-api/src/com/intellij/openapi/util/ActionCallback.java
index 1824c0c..7472e3d 100644
--- a/platform/core-api/src/com/intellij/openapi/util/ActionCallback.java
+++ b/platform/core-api/src/com/intellij/openapi/util/ActionCallback.java
@@ -26,6 +26,9 @@
import java.util.Set;
public class ActionCallback implements Disposable {
+ public static final ActionCallback DONE = new Done();
+ public static final ActionCallback REJECTED = new Rejected();
+
private final ExecutionCallback myDone;
private final ExecutionCallback myRejected;
diff --git a/platform/core-api/src/com/intellij/openapi/util/AsyncResult.java b/platform/core-api/src/com/intellij/openapi/util/AsyncResult.java
index 613fadc..1f4fe98 100644
--- a/platform/core-api/src/com/intellij/openapi/util/AsyncResult.java
+++ b/platform/core-api/src/com/intellij/openapi/util/AsyncResult.java
@@ -65,9 +65,9 @@
@NotNull
@Deprecated
/**
- * @deprecated Please use {@link #doWhenDone(com.intellij.util.Consumer)}
+ * @deprecated Use {@link #doWhenDone(com.intellij.util.Consumer)} (to remove in IDEA 16)
*/
- public AsyncResult<T> doWhenDone(@NotNull final Handler<T> handler) {
+ public AsyncResult<T> doWhenDone(@SuppressWarnings("deprecation") @NotNull final Handler<T> handler) {
doWhenDone(new Runnable() {
@Override
public void run() {
@@ -91,9 +91,9 @@
@NotNull
@Deprecated
/**
- * @deprecated use {@link #doWhenRejected(com.intellij.util.Consumer)}
+ * @deprecated Use {@link #doWhenRejected(com.intellij.util.Consumer)} (to remove in IDEA 16)
*/
- public AsyncResult<T> doWhenRejected(@NotNull final Handler<T> handler) {
+ public AsyncResult<T> doWhenRejected(@SuppressWarnings("deprecation") @NotNull final Handler<T> handler) {
doWhenRejected(new Runnable() {
@Override
public void run() {
@@ -135,6 +135,22 @@
return myResult;
}
+ @NotNull
+ public final ActionCallback doWhenProcessed(@NotNull final Consumer<T> consumer) {
+ doWhenDone(consumer);
+ doWhenRejected(new PairConsumer<T, String>() {
+ @Override
+ public void consume(T result, String error) {
+ consumer.consume(result);
+ }
+ });
+ return this;
+ }
+
+ @Deprecated
+ /**
+ * @deprecated Use {@link com.intellij.util.Consumer} (to remove in IDEA 16)
+ */
public interface Handler<T> {
void run(T t);
}
@@ -160,6 +176,10 @@
return REJECTED;
}
+ public static <R> AsyncResult<R> done(@NotNull R result) {
+ return new AsyncResult<R>().setDone(result);
+ }
+
// we don't use inner class, avoid memory leak, we don't want to hold this result while dependent is computing
private static class SubResultDoneCallback<Result, SubResult, AsyncSubResult extends AsyncResult<SubResult>> implements Consumer<Result> {
private final AsyncSubResult subResult;
diff --git a/platform/core-api/src/com/intellij/openapi/util/AsyncValueLoader.java b/platform/core-api/src/com/intellij/openapi/util/AsyncValueLoader.java
new file mode 100644
index 0000000..c699df1
--- /dev/null
+++ b/platform/core-api/src/com/intellij/openapi/util/AsyncValueLoader.java
@@ -0,0 +1,115 @@
+package com.intellij.openapi.util;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicReference;
+
+public abstract class AsyncValueLoader<T> {
+ private final AtomicReference<AsyncResult<T>> ref = new AtomicReference<AsyncResult<T>>();
+
+ @NotNull
+ public final AsyncResult<T> get() {
+ return get(true);
+ }
+
+ public final void reset() {
+ AsyncResult<T> oldValue = ref.getAndSet(null);
+ if (oldValue != null) {
+ rejectAndDispose(oldValue);
+ }
+ }
+
+ private void rejectAndDispose(@NotNull AsyncResult<T> asyncResult) {
+ try {
+ if (!asyncResult.isProcessed()) {
+ asyncResult.setRejected();
+ }
+ }
+ finally {
+ T result = asyncResult.getResult();
+ if (result != null) {
+ disposeResult(result);
+ }
+ }
+ }
+
+ protected void disposeResult(@NotNull T result) {
+ }
+
+ public final boolean has() {
+ AsyncResult<T> result = ref.get();
+ return result != null && result.isDone() && result.getResult() != null;
+ }
+
+ @NotNull
+ public final AsyncResult<T> get(boolean checkFreshness) {
+ AsyncResult<T> asyncResult = ref.get();
+ if (asyncResult == null) {
+ if (!ref.compareAndSet(null, asyncResult = new AsyncResult<T>())) {
+ return ref.get();
+ }
+ }
+ else if (!asyncResult.isProcessed()) {
+ // if current asyncResult is not processed, so, we don't need to check cache state
+ return asyncResult;
+ }
+ else if (asyncResult.isDone()) {
+ if (!checkFreshness || checkFreshness(asyncResult.getResult())) {
+ return asyncResult;
+ }
+
+ if (!ref.compareAndSet(asyncResult, asyncResult = new AsyncResult<T>())) {
+ AsyncResult<T> valueFromAnotherThread = ref.get();
+ while (valueFromAnotherThread == null) {
+ if (ref.compareAndSet(null, asyncResult)) {
+ callLoad(asyncResult);
+ return asyncResult;
+ }
+ else {
+ valueFromAnotherThread = ref.get();
+ }
+ }
+ return valueFromAnotherThread;
+ }
+ }
+
+ callLoad(asyncResult);
+ return asyncResult;
+ }
+
+ /**
+ * if result was rejected, by default this result will not be canceled - call get() will return rejected result instead of attempt to load again,
+ * but you can change this behavior - return true if you want to cancel result on reject
+ */
+ protected boolean isCancelOnReject() {
+ return false;
+ }
+
+ private void callLoad(final AsyncResult<T> asyncResult) {
+ if (isCancelOnReject()) {
+ asyncResult.doWhenRejected(new Runnable() {
+ @Override
+ public void run() {
+ ref.compareAndSet(asyncResult, null);
+ }
+ });
+ }
+
+ try {
+ load(asyncResult);
+ }
+ catch (Throwable e) {
+ ref.compareAndSet(asyncResult, null);
+ rejectAndDispose(asyncResult);
+ //noinspection InstanceofCatchParameter
+ throw e instanceof RuntimeException ? ((RuntimeException)e) : new RuntimeException(e);
+ }
+ }
+
+ protected abstract void load(AsyncResult<T> asyncResult) throws IOException;
+
+ protected boolean checkFreshness(T asyncResult) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/platform/core-api/src/com/intellij/openapi/util/AsyncValueLoaderManager.java b/platform/core-api/src/com/intellij/openapi/util/AsyncValueLoaderManager.java
new file mode 100644
index 0000000..6a658a7
--- /dev/null
+++ b/platform/core-api/src/com/intellij/openapi/util/AsyncValueLoaderManager.java
@@ -0,0 +1,85 @@
+package com.intellij.openapi.util;
+
+import com.intellij.openapi.util.AsyncResult;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
+
+@SuppressWarnings("unchecked")
+public abstract class AsyncValueLoaderManager<HOST, VALUE> {
+ private final AtomicReferenceFieldUpdater<HOST, AsyncResult> fieldUpdater;
+
+ public AsyncValueLoaderManager(AtomicReferenceFieldUpdater<HOST, AsyncResult> fieldUpdater) {
+ this.fieldUpdater = fieldUpdater;
+ }
+
+ public boolean checkFreshness(HOST host, VALUE value) {
+ return true;
+ }
+
+ public abstract void load(HOST host, AsyncResult<VALUE> result);
+
+ public final void reset(HOST host) {
+ fieldUpdater.set(host, null);
+ }
+
+ public final void set(HOST host, @Nullable VALUE value) {
+ if (value == null) {
+ reset(host);
+ }
+ else {
+ getOrCreateAsyncResult(host, false, false).setDone(value);
+ }
+ }
+
+ public final boolean has(HOST host) {
+ AsyncResult<VALUE> result = fieldUpdater.get(host);
+ return result != null && result.isDone() && result.getResult() != null;
+ }
+
+ public final AsyncResult<VALUE> get(HOST host) {
+ return get(host, true);
+ }
+
+ public final AsyncResult<VALUE> get(HOST host, boolean checkFreshness) {
+ return getOrCreateAsyncResult(host, checkFreshness, true);
+ }
+
+ private AsyncResult<VALUE> getOrCreateAsyncResult(HOST host, boolean checkFreshness, boolean load) {
+ AsyncResult<VALUE> asyncResult = fieldUpdater.get(host);
+ if (asyncResult == null) {
+ if (!fieldUpdater.compareAndSet(host, null, asyncResult = new AsyncResult<VALUE>())) {
+ return fieldUpdater.get(host);
+ }
+ }
+ else if (!asyncResult.isProcessed()) {
+ // if current asyncResult is not processed, so, we don't need to check cache state
+ return asyncResult;
+ }
+ else if (asyncResult.isDone()) {
+ if (!checkFreshness || checkFreshness(host, asyncResult.getResult())) {
+ return asyncResult;
+ }
+
+ if (!fieldUpdater.compareAndSet(host, asyncResult, asyncResult = new AsyncResult<VALUE>())) {
+ AsyncResult<VALUE> valueFromAnotherThread = fieldUpdater.get(host);
+ while (valueFromAnotherThread == null) {
+ if (fieldUpdater.compareAndSet(host, null, asyncResult)) {
+ if (load) {
+ load(host, asyncResult);
+ }
+ return asyncResult;
+ }
+ else {
+ valueFromAnotherThread = fieldUpdater.get(host);
+ }
+ }
+ return valueFromAnotherThread;
+ }
+ }
+ if (load) {
+ load(host, asyncResult);
+ }
+ return asyncResult;
+ }
+}
\ No newline at end of file
diff --git a/platform/core-api/src/com/intellij/openapi/util/ClassExtension.java b/platform/core-api/src/com/intellij/openapi/util/ClassExtension.java
index e763075..68720c3 100644
--- a/platform/core-api/src/com/intellij/openapi/util/ClassExtension.java
+++ b/platform/core-api/src/com/intellij/openapi/util/ClassExtension.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,7 +19,6 @@
*/
package com.intellij.openapi.util;
-import com.intellij.util.ReflectionCache;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -46,12 +45,12 @@
private static void collectSupers(Class classKey, Set<String> allSupers) {
allSupers.add(classKey.getName());
- final Class[] interfaces = ReflectionCache.getInterfaces(classKey);
+ final Class[] interfaces = classKey.getInterfaces();
for (final Class anInterface : interfaces) {
collectSupers(anInterface, allSupers);
}
- final Class superClass = ReflectionCache.getSuperClass(classKey);
+ final Class superClass = classKey.getSuperclass();
if (superClass != null) {
collectSupers(superClass, allSupers);
}
diff --git a/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java b/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java
index 3ecebe5..6e4549e 100644
--- a/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java
+++ b/platform/core-api/src/com/intellij/openapi/util/KeyedExtensionCollector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,6 +25,7 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.KeyedLazyInstance;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
@@ -129,9 +130,13 @@
for (Map.Entry<String, List<T>> entry : myExplicitExtensions.entrySet()) {
String key = entry.getKey();
if (keys.contains(key)) {
- if (result == null) result = new ArrayList<T>();
List<T> list = entry.getValue();
- result.addAll(list);
+ if (result == null) {
+ result = new ArrayList<T>(list);
+ }
+ else {
+ result.addAll(list);
+ }
}
}
@@ -159,7 +164,7 @@
LOG.error(e);
continue;
}
- if (result == null) result = new ArrayList<T>();
+ if (result == null) result = new SmartList<T>();
result.add(instance);
}
}
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/StandardFileSystems.java b/platform/core-api/src/com/intellij/openapi/vfs/StandardFileSystems.java
index ba55329..8362034 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/StandardFileSystems.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/StandardFileSystems.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,25 +17,35 @@
import com.intellij.ide.highlighter.ArchiveFileType;
import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-/**
- * @author yole
- */
public class StandardFileSystems {
- public static String FILE_PROTOCOL = "file";
- public static String FILE_PROTOCOL_PREFIX = "file://";
- public static String JAR_PROTOCOL = "jar";
- public static String JAR_PROTOCOL_PREFIX = "jar://";
- public static String JAR_SEPARATOR = "!/";
- public static String HTTP_PROTOCOL = "http";
+ public static final String FILE_PROTOCOL = URLUtil.FILE_PROTOCOL;
+ public static final String FILE_PROTOCOL_PREFIX = FILE_PROTOCOL + URLUtil.SCHEME_SEPARATOR;
+ public static final String JAR_PROTOCOL = URLUtil.JAR_PROTOCOL;
+ public static final String JAR_PROTOCOL_PREFIX = JAR_PROTOCOL + URLUtil.SCHEME_SEPARATOR;
+
+ @Deprecated
+ @SuppressWarnings("UnusedDeclaration")
+ /**
+ * @deprecated use {@link com.intellij.util.io.URLUtil#JAR_SEPARATOR}
+ */
+ public static final String JAR_SEPARATOR = URLUtil.JAR_SEPARATOR;
+
+ @Deprecated
+ @SuppressWarnings("UnusedDeclaration")
+ /**
+ * @deprecated use {@link com.intellij.util.io.URLUtil#HTTP_PROTOCOL}
+ */
+ public static final String HTTP_PROTOCOL = URLUtil.HTTP_PROTOCOL;
private static final NotNullLazyValue<VirtualFileSystem> ourLocal = new NotNullLazyValue<VirtualFileSystem>() {
@NotNull
@Override
protected VirtualFileSystem compute() {
- return VirtualFileManager.getInstance().getFileSystem(FILE_PROTOCOL);
+ return VirtualFileManager.getInstance().getFileSystem(URLUtil.FILE_PROTOCOL);
}
};
@@ -59,15 +69,14 @@
public static VirtualFile getJarRootForLocalFile(@NotNull VirtualFile virtualFile) {
if (virtualFile.getFileType() != ArchiveFileType.INSTANCE) return null;
- final String path = virtualFile.getPath() + JAR_SEPARATOR;
- return jar().findFileByPath(path);
+ return jar().findFileByPath(virtualFile.getPath() + URLUtil.JAR_SEPARATOR);
}
@Nullable
public static VirtualFile getVirtualFileForJar(@Nullable VirtualFile entryVFile) {
if (entryVFile == null) return null;
final String path = entryVFile.getPath();
- final int separatorIndex = path.indexOf(JAR_SEPARATOR);
+ final int separatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR);
if (separatorIndex < 0) return null;
String localPath = path.substring(0, separatorIndex);
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java
index 25f98af..d7e4ab8 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,21 +18,22 @@
import com.intellij.AbstractBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author yole
*/
public class VfsBundle extends AbstractBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return ourInstance.getMessage(key, params);
+ }
+
@NonNls private static final String BUNDLE = "messages.VfsBundle";
private static final VfsBundle ourInstance = new VfsBundle();
private VfsBundle() {
super(BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return ourInstance.getMessage(key, params);
- }
-
}
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
index 539e1f2..36333be 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VfsUtilCore.java
@@ -38,10 +38,7 @@
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import static com.intellij.openapi.vfs.VirtualFileVisitor.VisitorException;
@@ -358,7 +355,7 @@
@NotNull
public static String pathToUrl(@NonNls @NotNull String path) {
- return VirtualFileManager.constructUrl(StandardFileSystems.FILE_PROTOCOL, path);
+ return VirtualFileManager.constructUrl(URLUtil.FILE_PROTOCOL, path);
}
public static List<File> virtualToIoFiles(@NotNull Collection<VirtualFile> scope) {
@@ -389,7 +386,7 @@
if (SystemInfoRt.isWindows) {
return prefix + URLUtil.SCHEME_SEPARATOR + suffix;
}
- else if (removeLocalhostPrefix && prefix.equals(StandardFileSystems.FILE_PROTOCOL) && suffix.startsWith(LOCALHOST_URI_PATH_PREFIX)) {
+ else if (removeLocalhostPrefix && prefix.equals(URLUtil.FILE_PROTOCOL) && suffix.startsWith(LOCALHOST_URI_PATH_PREFIX)) {
// sometimes (e.g. in Google Chrome for Mac) local file url is prefixed with 'localhost' so we need to remove it
return prefix + ":///" + suffix.substring(LOCALHOST_URI_PATH_PREFIX.length());
}
@@ -423,8 +420,8 @@
public static String convertFromUrl(@NotNull URL url) {
String protocol = url.getProtocol();
String path = url.getPath();
- if (protocol.equals(StandardFileSystems.JAR_PROTOCOL)) {
- if (StringUtil.startsWithConcatenation(path, StandardFileSystems.FILE_PROTOCOL, PROTOCOL_DELIMITER)) {
+ if (protocol.equals(URLUtil.JAR_PROTOCOL)) {
+ if (StringUtil.startsWithConcatenation(path, URLUtil.FILE_PROTOCOL, PROTOCOL_DELIMITER)) {
try {
URL subURL = new URL(path);
path = subURL.getPath();
@@ -501,7 +498,7 @@
}
}
- if (file == null && uri.contains(StandardFileSystems.JAR_SEPARATOR)) {
+ if (file == null && uri.contains(URLUtil.JAR_SEPARATOR)) {
file = StandardFileSystems.jar().findFileByPath(uri);
if (file == null && base == null) {
file = VirtualFileManager.getInstance().findFileByUrl(uri);
@@ -543,6 +540,56 @@
}
/**
+ * Gets the common ancestor for passed files, or null if the files do not have common ancestors.
+ *
+ * @param file1 fist file
+ * @param file2 second file
+ * @return common ancestor for the passed files. Returns <code>null</code> if
+ * the files do not have common ancestor
+ */
+ @Nullable
+ public static VirtualFile getCommonAncestor(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
+ if (!file1.getFileSystem().equals(file2.getFileSystem())) {
+ return null;
+ }
+
+ VirtualFile[] path1 = getPathComponents(file1);
+ VirtualFile[] path2 = getPathComponents(file2);
+
+ int lastEqualIdx = -1;
+ for (int i = 0; i < path1.length && i < path2.length; i++) {
+ if (path1[i].equals(path2[i])) {
+ lastEqualIdx = i;
+ }
+ else {
+ break;
+ }
+ }
+ return lastEqualIdx == -1 ? null : path1[lastEqualIdx];
+ }
+
+ /**
+ * Gets an array of files representing paths from root to the passed file.
+ *
+ * @param file the file
+ * @return virtual files which represents paths from root to the passed file
+ */
+ @NotNull
+ static VirtualFile[] getPathComponents(@NotNull VirtualFile file) {
+ ArrayList<VirtualFile> componentsList = new ArrayList<VirtualFile>();
+ while (file != null) {
+ componentsList.add(file);
+ file = file.getParent();
+ }
+ int size = componentsList.size();
+ VirtualFile[] components = new VirtualFile[size];
+ for (int i = 0; i < size; i++) {
+ components[i] = componentsList.get(size - i - 1);
+ }
+ return components;
+ }
+
+ /**
* this collection will keep only distinct files/folders, e.g. C:\foo\bar will be removed when C:\foo is added
*/
public static class DistinctVFilesRootsCollection extends DistinctRootsCollection<VirtualFile> {
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 e1deb9b..8b67321 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFile.java
@@ -150,8 +150,8 @@
* @return the presentable URL.
* @see VirtualFileSystem#extractPresentableUrl
*/
+ @NotNull
public final String getPresentableUrl() {
- if (!isValid()) return null;
return getFileSystem().extractPresentableUrl(getPath());
}
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManager.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManager.java
index 3256567..b751bda 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManager.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFileManager.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 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
+import com.intellij.util.io.URLUtil;
import com.intellij.util.messages.Topic;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -130,7 +131,7 @@
*/
@NotNull
public static String constructUrl(@NotNull String protocol, @NotNull String path) {
- return protocol + "://" + path;
+ return protocol + URLUtil.SCHEME_SEPARATOR + path;
}
/**
@@ -142,7 +143,7 @@
*/
@Nullable
public static String extractProtocol(@NotNull String url) {
- int index = url.indexOf("://");
+ int index = url.indexOf(URLUtil.SCHEME_SEPARATOR);
if (index < 0) return null;
return url.substring(0, index);
}
@@ -156,9 +157,9 @@
*/
@NotNull
public static String extractPath(@NotNull String url) {
- int index = url.indexOf("://");
+ int index = url.indexOf(URLUtil.SCHEME_SEPARATOR);
if (index < 0) return url;
- return url.substring(index + "://".length());
+ return url.substring(index + URLUtil.SCHEME_SEPARATOR.length());
}
public abstract void addVirtualFileManagerListener(@NotNull VirtualFileManagerListener listener);
@@ -167,5 +168,5 @@
public abstract void removeVirtualFileManagerListener(@NotNull VirtualFileManagerListener listener);
- public abstract void notifyPropertyChanged(VirtualFile virtualFile, String property, Object oldValue, Object newValue);
+ public abstract void notifyPropertyChanged(@NotNull VirtualFile virtualFile, @NotNull String property, Object oldValue, Object newValue);
}
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFilePropertyEvent.java b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFilePropertyEvent.java
index f4433aa..91af87f 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/VirtualFilePropertyEvent.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/VirtualFilePropertyEvent.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,7 @@
*/
package com.intellij.openapi.vfs;
+import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
import org.jetbrains.annotations.NotNull;
/**
@@ -33,6 +34,7 @@
myPropertyName = propertyName;
myOldValue = oldValue;
myNewValue = newValue;
+ VFilePropertyChangeEvent.checkPropertyValuesCorrect(requestor, propertyName, oldValue, newValue);
}
/**
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java b/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java
index 7f68e08..9f8982f 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/ex/http/HttpFileSystem.java
@@ -18,17 +18,21 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem;
-import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
public abstract class HttpFileSystem extends DeprecatedVirtualFileSystem implements ApplicationComponent {
- @NonNls public static final String PROTOCOL = StandardFileSystems.HTTP_PROTOCOL;
+ @Deprecated
+ @SuppressWarnings("UnusedDeclaration")
+ /**
+ * @deprecated use {@link com.intellij.util.io.URLUtil#HTTP_PROTOCOL}
+ */
+ public static final String PROTOCOL = URLUtil.HTTP_PROTOCOL;
public static HttpFileSystem getInstance() {
- return (HttpFileSystem)VirtualFileManager.getInstance().getFileSystem(PROTOCOL);
+ return (HttpFileSystem)VirtualFileManager.getInstance().getFileSystem(URLUtil.HTTP_PROTOCOL);
}
public abstract boolean isFileDownloaded(@NotNull VirtualFile file);
diff --git a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java
index ac7803c..360ce83 100644
--- a/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.java
+++ b/platform/core-api/src/com/intellij/openapi/vfs/newvfs/events/VFilePropertyChangeEvent.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,8 +19,10 @@
*/
package com.intellij.openapi.vfs.newvfs.events;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
+import com.intellij.util.FileContentUtilCore;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,6 +44,32 @@
myPropertyName = propertyName;
myOldValue = oldValue;
myNewValue = newValue;
+ checkPropertyValuesCorrect(requestor, propertyName, oldValue, newValue);
+ }
+
+ public static void checkPropertyValuesCorrect(Object requestor, @NotNull String propertyName, Object oldValue, Object newValue) {
+ if (Comparing.equal(oldValue, newValue) && FileContentUtilCore.FORCE_RELOAD_REQUESTOR != requestor) {
+ throw new IllegalArgumentException("Values must be different, got the same: " + oldValue);
+ }
+ if (VirtualFile.PROP_NAME.equals(propertyName)) {
+ if (oldValue == null) throw new IllegalArgumentException("oldName must not be null");
+ if (newValue == null) throw new IllegalArgumentException("newName must not be null");
+ }
+ else if (VirtualFile.PROP_ENCODING.equals(propertyName)) {
+ if (oldValue == null) throw new IllegalArgumentException("oldCharset must not be null");
+ }
+ else if (VirtualFile.PROP_WRITABLE.equals(propertyName)) {
+ if (!(oldValue instanceof Boolean)) throw new IllegalArgumentException("oldWriteable must be boolean, got "+oldValue);
+ if (!(newValue instanceof Boolean)) throw new IllegalArgumentException("newWriteable must be boolean, got "+newValue);
+ }
+ else if (VirtualFile.PROP_HIDDEN.equals(propertyName)) {
+ if (!(oldValue instanceof Boolean)) throw new IllegalArgumentException("oldHidden must be boolean, got "+oldValue);
+ if (!(newValue instanceof Boolean)) throw new IllegalArgumentException("newHidden must be boolean, got "+newValue);
+ }
+ else if (VirtualFile.PROP_SYMLINK_TARGET.equals(propertyName)) {
+ if (oldValue != null && !(oldValue instanceof String)) throw new IllegalArgumentException("oldSymTarget must be String, got "+oldValue);
+ if (newValue != null && !(newValue instanceof String)) throw new IllegalArgumentException("newSymTarget must be String, got "+newValue);
+ }
}
@NotNull
diff --git a/platform/core-api/src/com/intellij/patterns/ObjectPattern.java b/platform/core-api/src/com/intellij/patterns/ObjectPattern.java
index a76ee94..cf9f751 100644
--- a/platform/core-api/src/com/intellij/patterns/ObjectPattern.java
+++ b/platform/core-api/src/com/intellij/patterns/ObjectPattern.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.
@@ -58,11 +58,13 @@
}
public Self andNot(final ElementPattern pattern) {
- return and(StandardPatterns.not(pattern));
+ ElementPattern<T> not = StandardPatterns.not(pattern);
+ return and(not);
}
- public Self andOr(final ElementPattern... patterns) {
- return and(StandardPatterns.or(patterns));
+ public Self andOr(@NotNull ElementPattern... patterns) {
+ ElementPattern or = StandardPatterns.or(patterns);
+ return and(or);
}
public Self and(final ElementPattern pattern) {
diff --git a/platform/core-api/src/com/intellij/patterns/PatternCondition.java b/platform/core-api/src/com/intellij/patterns/PatternCondition.java
index 043bf5c..07c3a8a 100644
--- a/platform/core-api/src/com/intellij/patterns/PatternCondition.java
+++ b/platform/core-api/src/com/intellij/patterns/PatternCondition.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,7 +18,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.PairProcessor;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -110,7 +109,7 @@
// this code eats CPU, for debug purposes ONLY
public boolean processParameters(final PairProcessor<String, Object> processor) {
- for (Class aClass = getClass(); aClass != null; aClass = ReflectionCache.getSuperClass(aClass)) {
+ for (Class aClass = getClass(); aClass != null; aClass = aClass.getSuperclass()) {
for (final Field field : aClass.getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers()) &&
(((field.getModifiers() & 0x1000 /*Modifer.SYNTHETIC*/) == 0 && !aClass.equals(PatternCondition.class))
diff --git a/platform/core-api/src/com/intellij/patterns/PsiElementPattern.java b/platform/core-api/src/com/intellij/patterns/PsiElementPattern.java
index 9a59c5b..d939516 100644
--- a/platform/core-api/src/com/intellij/patterns/PsiElementPattern.java
+++ b/platform/core-api/src/com/intellij/patterns/PsiElementPattern.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,6 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.PairProcessor;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -98,7 +97,7 @@
@Override
public boolean accepts(@NotNull final T t, final ProcessingContext context) {
for (final PsiReference reference : t.getReferences()) {
- if (ReflectionCache.isInstance(reference, referenceClass)) {
+ if (referenceClass.isInstance(reference)) {
return true;
}
}
diff --git a/platform/core-api/src/com/intellij/patterns/PsiFilePattern.java b/platform/core-api/src/com/intellij/patterns/PsiFilePattern.java
index 1a57436..6b944e2 100644
--- a/platform/core-api/src/com/intellij/patterns/PsiFilePattern.java
+++ b/platform/core-api/src/com/intellij/patterns/PsiFilePattern.java
@@ -16,6 +16,7 @@
package com.intellij.patterns;
+import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
@@ -63,6 +64,15 @@
});
}
+ public Self withFileType(final ElementPattern<? extends FileType> fileTypePattern) {
+ return with(new PatternCondition<T>("withFileType") {
+ @Override
+ public boolean accepts(@NotNull T file, ProcessingContext context) {
+ return fileTypePattern.accepts(file.getFileType(), context);
+ }
+ });
+ }
+
public static class Capture<T extends PsiFile> extends PsiFilePattern<T,Capture<T>> {
protected Capture(final Class<T> aClass) {
diff --git a/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java b/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java
index f955f35..e80dadf 100644
--- a/platform/core-api/src/com/intellij/patterns/TreeElementPattern.java
+++ b/platform/core-api/src/com/intellij/patterns/TreeElementPattern.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.
diff --git a/platform/core-api/src/com/intellij/psi/FileViewProviderFactory.java b/platform/core-api/src/com/intellij/psi/FileViewProviderFactory.java
index 66e25e3..4fe3ecd 100644
--- a/platform/core-api/src/com/intellij/psi/FileViewProviderFactory.java
+++ b/platform/core-api/src/com/intellij/psi/FileViewProviderFactory.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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.psi;
import com.intellij.lang.Language;
@@ -27,5 +26,5 @@
* @author yole
*/
public interface FileViewProviderFactory {
- FileViewProvider createFileViewProvider(@NotNull VirtualFile file, Language language, @NotNull PsiManager manager, final boolean physical);
+ FileViewProvider createFileViewProvider(@NotNull VirtualFile file, Language language, @NotNull PsiManager manager, boolean physical);
}
\ No newline at end of file
diff --git a/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java b/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java
index f0a2e95..4be3352 100644
--- a/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java
+++ b/platform/core-api/src/com/intellij/psi/LanguageSubstitutor.java
@@ -23,6 +23,7 @@
/**
* @author peter
+ * @see com.intellij.psi.LanguageSubstitutors
*/
public abstract class LanguageSubstitutor {
diff --git a/platform/core-api/src/com/intellij/psi/PsiBundle.java b/platform/core-api/src/com/intellij/psi/PsiBundle.java
index b196597..900fa03 100644
--- a/platform/core-api/src/com/intellij/psi/PsiBundle.java
+++ b/platform/core-api/src/com/intellij/psi/PsiBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -28,20 +28,19 @@
* @author max
*/
public class PsiBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.PsiBundle";
private PsiBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java b/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java
index 7ab0445..d2a7a9a 100644
--- a/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java
+++ b/platform/core-api/src/com/intellij/psi/PsiDocumentManager.java
@@ -101,6 +101,15 @@
public abstract void commitDocument(@NotNull Document document);
/**
+ * @param document
+ * @return the document text that PSI should be based upon. For changed documents, it's their old text until the document is committed.
+ * This sequence is immutable.
+ * @see com.intellij.util.text.ImmutableCharSequence
+ */
+ @NotNull
+ public abstract CharSequence getLastCommittedText(@NotNull Document document);
+
+ /**
* Returns the list of documents which have been modified but not committed.
*
* @return the list of uncommitted documents.
diff --git a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
index 8c6e4b7..8a71cf3 100644
--- a/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
+++ b/platform/core-api/src/com/intellij/psi/PsiInvalidElementAccessException.java
@@ -16,9 +16,13 @@
package com.intellij.psi;
+import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.ExceptionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,6 +33,7 @@
* @author mike
*/
public class PsiInvalidElementAccessException extends RuntimeException {
+ private static final Key<Object> INVALIDATION_TRACE = Key.create("TRACK_INVALIDATION_KEY");
private final SoftReference<PsiElement> myElementReference; // to prevent leaks, since exceptions are stored in IdeaLogger
public PsiInvalidElementAccessException(PsiElement element) {
@@ -49,10 +54,33 @@
}
private static String getMessageWithReason(@Nullable PsiElement element, @Nullable String message) {
- return (element == null ? "Unknown psi element" : "Element: " + element.getClass() + " because: " + reason(element)) +
+ return (element == null
+ ? "Unknown psi element"
+ : "Element: " + element.getClass() + " because: " + reason(element) + invalidationTraceText(element)) +
(message == null ? "" : "; " + message);
}
+ public static Object findInvalidationTrace(ASTNode element) {
+ while (element != null) {
+ Object trace = element.getUserData(INVALIDATION_TRACE);
+ if (trace != null) {
+ return trace;
+ }
+ element = element.getTreeParent();
+ }
+ return null;
+ }
+
+ @SuppressWarnings("ThrowableResultOfMethodCallIgnored")
+ private static String invalidationTraceText(PsiElement element) {
+ Object trace = findInvalidationTrace(element.getNode());
+ return "\ninvalidated at: " +
+ (!isTrackingInvalidation() ? "disabled" :
+ trace instanceof Throwable ? ExceptionUtil.getThrowableText((Throwable)trace) :
+ trace != null ? trace :
+ "no info");
+ }
+
@NonNls
@NotNull
private static String reason(@NotNull PsiElement root){
@@ -84,6 +112,14 @@
return "psi is outdated";
}
+ public static void setInvalidationTrace(ASTNode element, Object trace) {
+ element.putUserData(INVALIDATION_TRACE, trace);
+ }
+
+ public static boolean isTrackingInvalidation() {
+ return Registry.is("psi.track.invalidation", true);
+ }
+
@Nullable
public PsiElement getPsiElement() {
return myElementReference.get();
diff --git a/platform/core-api/src/com/intellij/psi/search/EverythingGlobalScope.java b/platform/core-api/src/com/intellij/psi/search/EverythingGlobalScope.java
index 18a0a91..191a5a2 100644
--- a/platform/core-api/src/com/intellij/psi/search/EverythingGlobalScope.java
+++ b/platform/core-api/src/com/intellij/psi/search/EverythingGlobalScope.java
@@ -48,6 +48,11 @@
}
@Override
+ public boolean isForceSearchingInLibrarySources() {
+ return true;
+ }
+
+ @Override
public boolean isSearchInModuleContent(@NotNull final Module aModule) {
return true;
}
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 cca7636..a94a146 100644
--- a/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.java
+++ b/platform/core-api/src/com/intellij/psi/search/GlobalSearchScope.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.search;
-import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.module.Module;
@@ -347,7 +346,7 @@
public boolean isSearchInLibraries() {
return myScope1.isSearchInLibraries() && myScope2.isSearchInLibraries();
}
-
+
@Override
public boolean isSearchOutsideRootModel() {
return myScope1.isSearchOutsideRootModel() && myScope2.isSearchOutsideRootModel();
@@ -574,8 +573,8 @@
private FileScope(@NotNull Project project, final VirtualFile virtualFile) {
super(project);
myVirtualFile = virtualFile;
- FileIndexFacade fileIndex = ServiceManager.getService(project, FileIndexFacade.class);
- myModule = myVirtualFile != null ? fileIndex.getModuleForFile(myVirtualFile) : null;
+ myModule = virtualFile != null && !project.isDefault() ?
+ FileIndexFacade.getInstance(project).getModuleForFile(virtualFile) : null;
}
@Override
diff --git a/platform/core-api/src/com/intellij/psi/stubs/BinaryFileStubBuilder.java b/platform/core-api/src/com/intellij/psi/stubs/BinaryFileStubBuilder.java
index ea1f00b..3914313 100644
--- a/platform/core-api/src/com/intellij/psi/stubs/BinaryFileStubBuilder.java
+++ b/platform/core-api/src/com/intellij/psi/stubs/BinaryFileStubBuilder.java
@@ -23,6 +23,9 @@
import com.intellij.util.indexing.FileContent;
import org.jetbrains.annotations.Nullable;
+/**
+ * @see com.intellij.psi.stubs.BinaryFileStubBuilders#EXTENSION_POINT_NAME
+ */
public interface BinaryFileStubBuilder {
boolean acceptsFile(VirtualFile file);
diff --git a/platform/core-api/src/com/intellij/psi/tree/IReparseableElementType.java b/platform/core-api/src/com/intellij/psi/tree/IReparseableElementType.java
index 5a1636d..c577297 100644
--- a/platform/core-api/src/com/intellij/psi/tree/IReparseableElementType.java
+++ b/platform/core-api/src/com/intellij/psi/tree/IReparseableElementType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,9 +19,11 @@
*/
package com.intellij.psi.tree;
+import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
public class IReparseableElementType extends ILazyParseableElementType {
public IReparseableElementType(@NonNls String debugName) {
@@ -43,10 +45,33 @@
*
* @param buffer the content to parse.
* @param fileLanguage language of the file
- * @param project the project containing the content. @return true if the content is valid, false if not
+ * @param project the project containing the content.
+ * @return true if the content is valid, false if not
*/
public boolean isParsable(CharSequence buffer, Language fileLanguage, final Project project) {
return false;
}
+
+ /**
+ * The same as {@link this#isParsable(CharSequence, com.intellij.lang.Language, com.intellij.openapi.project.Project)}
+ * but with parent ASTNode of the old node.
+ *
+ * Override this method only if you really understand what are doing.
+ * In other cases override {@link this#isParsable(CharSequence, com.intellij.lang.Language, com.intellij.openapi.project.Project)}
+ *
+ * Known valid use-case:
+ * Indent-based languages. You should know about parent indent in order to decide if block is reparsable with given text.
+ * Because if indent of some line became equals to parent indent then the block should have another parent or block is not block anymore.
+ * So it cannot be reparsed and whole file or parent block should be reparsed.
+ *
+ * @param parent parent node of old (or collapsed) reparsable node.
+ * @param buffer the content to parse.
+ * @param fileLanguage language of the file
+ * @param project the project containing the content.
+ * @return true if the content is valid, false if not
+ */
+ public boolean isParsable(@Nullable ASTNode parent, CharSequence buffer, Language fileLanguage, final Project project) {
+ return isParsable(buffer, fileLanguage, project);
+ }
}
diff --git a/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java b/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java
index 1e21c80..1f31645 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiCacheKey.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -51,7 +51,7 @@
@Nullable
public final T getCachedValueOrNull(@NotNull H h) {
SoftReference<Pair<Long, T>> ref = h.getUserData(this);
- Pair<Long, T> data = ref == null ? null : ref.get();
+ Pair<Long, T> data = SoftReference.dereference(ref);
if (data == null || data.getFirst() != h.getManager().getModificationTracker().getJavaStructureModificationCount()) {
return null;
}
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 4fe378c..d33ee46 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiTreeUtil.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.
diff --git a/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java b/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java
index eaf72d5..0328899 100644
--- a/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.java
+++ b/platform/core-api/src/com/intellij/psi/util/PsiUtilCore.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.
@@ -349,16 +349,14 @@
@Nullable
public static VirtualFile getVirtualFile(@Nullable PsiElement element) {
- if (element == null || !element.isValid()) {
+ if (element == null) {
return null;
}
-
if (element instanceof PsiFileSystemItem) {
- return ((PsiFileSystemItem)element).getVirtualFile();
+ return element.isValid() ? ((PsiFileSystemItem)element).getVirtualFile() : null;
}
-
final PsiFile containingFile = element.getContainingFile();
- if (containingFile == null) {
+ if (containingFile == null || !containingFile.isValid()) {
return null;
}
@@ -486,7 +484,7 @@
@NotNull
public static Language findLanguageFromElement(final PsiElement elt) {
- if (elt.getFirstChild() == null) { //is leaf
+ if (!(elt instanceof PsiFile) && elt.getFirstChild() == null) { //is leaf
final PsiElement parent = elt.getParent();
if (parent != null) {
return parent.getLanguage();
@@ -501,7 +499,11 @@
final PsiElement elt = file.findElementAt(offset);
if (elt == null) return file.getLanguage();
if (elt instanceof PsiWhiteSpace) {
- final int decremented = elt.getTextRange().getStartOffset() - 1;
+ TextRange textRange = elt.getTextRange();
+ if (!textRange.contains(offset)) {
+ LOG.error("PSI corrupted: in file "+file+" ("+file.getViewProvider().getVirtualFile()+") offset="+offset+" returned element "+elt+" with text range "+textRange);
+ }
+ final int decremented = textRange.getStartOffset() - 1;
if (decremented >= 0) {
return getLanguageAtOffset(file, decremented);
}
diff --git a/platform/core-api/src/com/intellij/psi/util/QualifiedName.java b/platform/core-api/src/com/intellij/psi/util/QualifiedName.java
index 9cdd11b..cd96e54 100644
--- a/platform/core-api/src/com/intellij/psi/util/QualifiedName.java
+++ b/platform/core-api/src/com/intellij/psi/util/QualifiedName.java
@@ -44,6 +44,7 @@
return qName;
}
+ @NotNull
public static QualifiedName fromComponents(String... components) {
QualifiedName result = new QualifiedName(components.length);
Collections.addAll(result.myComponents, components);
@@ -183,6 +184,7 @@
return StringUtil.join(myComponents, separator);
}
+ @NotNull
public static QualifiedName fromDottedString(@NotNull String refName) {
return fromComponents(refName.split("\\."));
}
diff --git a/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java b/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
index ceab1ec..158144a 100644
--- a/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
+++ b/platform/core-api/src/com/intellij/testFramework/LightVirtualFile.java
@@ -16,9 +16,9 @@
package com.intellij.testFramework;
import com.intellij.lang.Language;
+import com.intellij.openapi.fileTypes.CharsetUtil;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
-import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.vfs.DeprecatedVirtualFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -66,14 +66,7 @@
}
public LightVirtualFile(final String name, final FileType fileType, final CharSequence text, final long modificationStamp) {
- this(name, fileType, text, charsetFromContent(fileType, text), modificationStamp);
- }
-
- private static Charset charsetFromContent(FileType fileType, CharSequence text) {
- if (fileType instanceof LanguageFileType) {
- return ((LanguageFileType)fileType).extractCharsetFromFileContent(null, null, text.toString());
- }
- return null;
+ this(name, fileType, text, CharsetUtil.extractCharsetFromFileContent(null, null, fileType, text), modificationStamp);
}
public LightVirtualFile(final String name, final FileType fileType, final CharSequence text, Charset charset, final long modificationStamp) {
@@ -271,7 +264,7 @@
@Override
public long getTimeStamp() {
- return 0; // todo[max] : Add UnsupporedOperationException at better times.
+ return 0; // todo[max] : Add UnsupportedOperationException at better times.
}
@Override
@@ -280,6 +273,7 @@
return contentsToByteArray().length;
}
catch (IOException e) {
+ //noinspection CallToPrintStackTrace
e.printStackTrace();
assert false;
return 0;
@@ -295,6 +289,7 @@
myModStamp = LocalTimeCounter.currentTime();
}
+ @Override
public void setWritable(boolean b) {
myIsWritable = b;
}
diff --git a/platform/core-api/src/com/intellij/ui/IconDeferrer.java b/platform/core-api/src/com/intellij/ui/IconDeferrer.java
index 120f5aa..b5b5c46 100644
--- a/platform/core-api/src/com/intellij/ui/IconDeferrer.java
+++ b/platform/core-api/src/com/intellij/ui/IconDeferrer.java
@@ -31,4 +31,5 @@
}
public abstract <T> Icon defer(Icon base, T param, @NotNull Function<T, Icon> f);
+ public abstract <T> Icon deferAutoUpdatable(Icon base, T param, @NotNull Function<T, Icon> f);
}
\ No newline at end of file
diff --git a/platform/core-api/src/com/intellij/usageView/UsageInfo.java b/platform/core-api/src/com/intellij/usageView/UsageInfo.java
new file mode 100644
index 0000000..2d3cecc
--- /dev/null
+++ b/platform/core-api/src/com/intellij/usageView/UsageInfo.java
@@ -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 com.intellij.usageView;
+
+import com.intellij.lang.injection.InjectedLanguageManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.ProperTextRange;
+import com.intellij.openapi.util.Segment;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class UsageInfo {
+ public static final UsageInfo[] EMPTY_ARRAY = new UsageInfo[0];
+ private static final Logger LOG = Logger.getInstance("#com.intellij.usageView.UsageInfo");
+ private final SmartPsiElementPointer<?> mySmartPointer;
+ private final SmartPsiFileRange myPsiFileRange;
+
+ public final boolean isNonCodeUsage;
+ protected boolean myDynamicUsage = false;
+
+ public UsageInfo(@NotNull PsiElement element, int startOffset, int endOffset, boolean isNonCodeUsage) {
+ element = element.getNavigationElement();
+ PsiFile file = element.getContainingFile();
+ PsiElement topElement = file == null ? element : file;
+ LOG.assertTrue(topElement.isValid(), element);
+
+ TextRange elementRange = element.getTextRange();
+ if (elementRange == null) {
+ throw new IllegalArgumentException("text range null for " + element + "; " + element.getClass());
+ }
+ if (startOffset == -1 && endOffset == -1) {
+ // calculate natural element range
+ startOffset = element.getTextOffset() - elementRange.getStartOffset();
+ endOffset = elementRange.getEndOffset() - elementRange.getStartOffset();
+ }
+
+ if (startOffset < 0) {
+ throw new IllegalArgumentException("element " + element + "; startOffset " +startOffset);
+ }
+ if (startOffset > endOffset) {
+ throw new IllegalArgumentException("element " + element + "; diff " + (endOffset-startOffset));
+ }
+
+ Project project = topElement.getProject();
+ SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project);
+ mySmartPointer = smartPointerManager.createSmartPsiElementPointer(element, file);
+ if (startOffset != element.getTextOffset() - elementRange.getStartOffset() || endOffset != elementRange.getLength()) {
+ TextRange rangeToStore;
+ if (file != null && InjectedLanguageManager.getInstance(project).isInjectedFragment(file)) {
+ rangeToStore = elementRange;
+ }
+ else {
+ rangeToStore = TextRange.create(startOffset, endOffset).shiftRight(elementRange.getStartOffset());
+ }
+ myPsiFileRange = smartPointerManager.createSmartPsiFileRangePointer(file, rangeToStore);
+ }
+ else {
+ myPsiFileRange = null;
+ }
+ this.isNonCodeUsage = isNonCodeUsage;
+ }
+
+ public UsageInfo(@NotNull SmartPsiElementPointer<?> smartPointer,
+ SmartPsiFileRange psiFileRange,
+ boolean dynamicUsage,
+ boolean nonCodeUsage) {
+ myDynamicUsage = dynamicUsage;
+ isNonCodeUsage = nonCodeUsage;
+ myPsiFileRange = psiFileRange;
+ mySmartPointer = smartPointer;
+ }
+
+ @NotNull
+ public SmartPsiElementPointer<?> getSmartPointer() {
+ return mySmartPointer;
+ }
+
+ public SmartPsiFileRange getPsiFileRange() {
+ return myPsiFileRange;
+ }
+
+ public boolean isNonCodeUsage() {
+ return isNonCodeUsage;
+ }
+
+ public void setDynamicUsage(boolean dynamicUsage) {
+ myDynamicUsage = dynamicUsage;
+ }
+
+ public UsageInfo(@NotNull PsiElement element, boolean isNonCodeUsage) {
+ this(element, -1, -1, isNonCodeUsage);
+ }
+
+ public UsageInfo(@NotNull PsiElement element, int startOffset, int endOffset) {
+ this(element, startOffset, endOffset, false);
+ }
+
+ public UsageInfo(@NotNull PsiReference reference) {
+ this(reference.getElement(), reference.getRangeInElement().getStartOffset(), reference.getRangeInElement().getEndOffset());
+ myDynamicUsage = reference.resolve() == null;
+ }
+
+ public UsageInfo(@NotNull PsiQualifiedReferenceElement reference) {
+ this((PsiElement)reference);
+ }
+
+ public UsageInfo(@NotNull PsiElement element) {
+ this(element, false);
+ }
+
+ @Nullable
+ public PsiElement getElement() { // SmartPointer is used to fix SCR #4572, hotya eto krivo i nado vse perepisat'
+ return mySmartPointer.getElement();
+ }
+
+ @Nullable
+ public PsiReference getReference() {
+ PsiElement element = getElement();
+ return element == null ? null : element.getReference();
+ }
+
+ /**
+ * @deprecated for the range in element use {@link #getRangeInElement} instead,
+ * for the whole text range in the file covered by this usage info, use {@link #getSegment()}
+ */
+ public TextRange getRange() {
+ return getRangeInElement();
+ }
+
+ /**
+ * @return range in element
+ */
+ @Nullable("null means range is invalid")
+ public ProperTextRange getRangeInElement() {
+ PsiElement element = getElement();
+ if (element == null) return null;
+ TextRange elementRange = element.getTextRange();
+ ProperTextRange result;
+ if (myPsiFileRange == null) {
+ int startOffset = element.getTextOffset();
+ result = ProperTextRange.create(startOffset, elementRange.getEndOffset());
+ }
+ else {
+ Segment rangeInFile = myPsiFileRange.getRange();
+ if (rangeInFile == null) return null;
+ result = ProperTextRange.create(rangeInFile);
+ }
+ int delta = elementRange.getStartOffset();
+ return result.getStartOffset() < delta ? null : result.shiftRight(-delta);
+ }
+
+ /**
+ * Override this method if you want a tooltip to be displayed for this usage
+ */
+ public String getTooltipText() {
+ return null;
+ }
+
+ public int getNavigationOffset() {
+ if (myPsiFileRange != null) {
+ final Segment range = myPsiFileRange.getRange();
+ if (range != null) {
+ return range.getStartOffset();
+ }
+ }
+
+ PsiElement element = getElement();
+ if (element == null) return -1;
+ TextRange range = element.getTextRange();
+
+ TextRange rangeInElement = getRangeInElement();
+ if (rangeInElement == null) return -1;
+ return range.getStartOffset() + rangeInElement.getStartOffset();
+ }
+
+ public boolean isValid() {
+ return getSegment() != null;
+ }
+
+ @Nullable
+ public Segment getSegment() {
+ PsiElement element = getElement();
+ if (element == null) return null;
+ TextRange range = element.getTextRange();
+ TextRange.assertProperRange(range, element);
+ if (element instanceof PsiFile) {
+ // hack: it's actually a range inside file, use document for range checking since during the "find|replace all" operation, file range might have been changed
+ Document document = PsiDocumentManager.getInstance(getProject()).getDocument((PsiFile)element);
+ if (document != null) {
+ range = new ProperTextRange(0, document.getTextLength());
+ }
+ }
+ ProperTextRange rangeInElement = getRangeInElement();
+ if (rangeInElement == null) return null;
+ return new ProperTextRange(Math.min(range.getEndOffset(), range.getStartOffset() + rangeInElement.getStartOffset()),
+ Math.min(range.getEndOffset(), range.getStartOffset() + rangeInElement.getEndOffset()));
+ }
+
+ @NotNull
+ public Project getProject() {
+ return mySmartPointer.getProject();
+ }
+
+ public final boolean isWritable() {
+ PsiElement element = getElement();
+ return element == null || element.isWritable();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!getClass().equals(o.getClass())) return false;
+
+ final UsageInfo usageInfo = (UsageInfo)o;
+
+ if (isNonCodeUsage != usageInfo.isNonCodeUsage) return false;
+
+ SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(getProject());
+ return smartPointerManager.pointToTheSameElement(mySmartPointer, usageInfo.mySmartPointer)
+ && (myPsiFileRange == null || usageInfo.myPsiFileRange != null && smartPointerManager.pointToTheSameElement(myPsiFileRange, usageInfo.myPsiFileRange));
+ }
+
+ @Override
+ public int hashCode() {
+ int result = mySmartPointer != null ? mySmartPointer.hashCode() : 0;
+ result = 29 * result + (myPsiFileRange == null ? 0 : myPsiFileRange.hashCode());
+ result = 29 * result + (isNonCodeUsage ? 1 : 0);
+ return result;
+ }
+
+ @Nullable
+ public PsiFile getFile() {
+ return mySmartPointer.getContainingFile();
+ }
+
+ @Nullable
+ public VirtualFile getVirtualFile() {
+ return mySmartPointer.getVirtualFile();
+ }
+
+ public boolean isDynamicUsage() {
+ return myDynamicUsage;
+ }
+
+ // creates new smart pointers
+ @Nullable("null means could not copy because info is no longer valid")
+ public UsageInfo copy() {
+ PsiElement element = mySmartPointer.getElement();
+ SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(getProject());
+ PsiFile containingFile = myPsiFileRange == null ? null : myPsiFileRange.getContainingFile();
+ Segment segment = containingFile == null ? null : myPsiFileRange.getRange();
+ TextRange range = segment == null ? null : TextRange.create(segment);
+ SmartPsiFileRange psiFileRange = range == null ? null : smartPointerManager.createSmartPsiFileRangePointer(containingFile, range);
+ SmartPsiElementPointer<PsiElement> pointer = element == null || !isValid() ? null : smartPointerManager.createSmartPsiElementPointer(element);
+ return pointer == null ? null : new UsageInfo(pointer, psiFileRange, isDynamicUsage(), isNonCodeUsage());
+ }
+}
diff --git a/platform/core-api/src/com/intellij/util/ArrayQuery.java b/platform/core-api/src/com/intellij/util/ArrayQuery.java
index 3e04365..abe2f10 100644
--- a/platform/core-api/src/com/intellij/util/ArrayQuery.java
+++ b/platform/core-api/src/com/intellij/util/ArrayQuery.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.
diff --git a/platform/core-api/src/com/intellij/util/FileContentUtilCore.java b/platform/core-api/src/com/intellij/util/FileContentUtilCore.java
index 93833db..54a26f6 100644
--- a/platform/core-api/src/com/intellij/util/FileContentUtilCore.java
+++ b/platform/core-api/src/com/intellij/util/FileContentUtilCore.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.
@@ -27,10 +27,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
/**
* @author peter
@@ -38,12 +35,14 @@
public class FileContentUtilCore {
@NonNls public static final String FORCE_RELOAD_REQUESTOR = "FileContentUtilCore.saveOrReload";
+ public static void reparseFiles(@NotNull VirtualFile... files) {
+ reparseFiles(Arrays.asList(files));
+ }
public static void reparseFiles(@NotNull final Collection<VirtualFile> files) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
// files must be processed under one write action to prevent firing event for invalid files.
-
final Set<VFilePropertyChangeEvent> events = new THashSet<VFilePropertyChangeEvent>();
for (VirtualFile file : files) {
saveOrReload(file, events);
@@ -57,7 +56,7 @@
});
}
- private static void saveOrReload(VirtualFile file, Collection<VFilePropertyChangeEvent> events) {
+ private static void saveOrReload(VirtualFile file, @NotNull Collection<VFilePropertyChangeEvent> events) {
if (file == null || file.isDirectory() || !file.isValid()) {
return;
}
diff --git a/platform/core-api/src/com/intellij/util/IconUtil.java b/platform/core-api/src/com/intellij/util/IconUtil.java
index 3109717..2b314ca 100644
--- a/platform/core-api/src/com/intellij/util/IconUtil.java
+++ b/platform/core-api/src/com/intellij/util/IconUtil.java
@@ -121,44 +121,46 @@
return new ImageIcon(second);
}
+ private static final NullableFunction<FileIconKey, Icon> ICON_NULLABLE_FUNCTION = new NullableFunction<FileIconKey, Icon>() {
+ @Override
+ public Icon fun(final FileIconKey key) {
+ final VirtualFile file = key.getFile();
+ final int flags = key.getFlags();
+ final Project project = key.getProject();
+
+ if (!file.isValid() || project != null && (project.isDisposed() || !wasEverInitialized(project))) return null;
+
+ final Icon providersIcon = getProvidersIcon(file, flags, project);
+ Icon icon = providersIcon == null ? VirtualFilePresentation.getIcon(file) : providersIcon;
+
+ final boolean dumb = project != null && DumbService.getInstance(project).isDumb();
+ for (FileIconPatcher patcher : getPatchers()) {
+ if (dumb && !DumbService.isDumbAware(patcher)) {
+ continue;
+ }
+
+ icon = patcher.patchIcon(icon, file, flags, project);
+ }
+
+ if ((flags & Iconable.ICON_FLAG_READ_STATUS) != 0 &&
+ (!file.isWritable() || !WritingAccessProvider.isPotentiallyWritable(file, project))) {
+ icon = new LayeredIcon(icon, PlatformIcons.LOCKED_ICON);
+ }
+ if (file.is(VFileProperty.SYMLINK)) {
+ icon = new LayeredIcon(icon, PlatformIcons.SYMLINK_ICON);
+ }
+
+ Iconable.LastComputedIcon.put(file, icon, flags);
+
+ return icon;
+ }
+ };
+
public static Icon getIcon(@NotNull final VirtualFile file, @Iconable.IconFlags final int flags, @Nullable final Project project) {
Icon lastIcon = Iconable.LastComputedIcon.get(file, flags);
final Icon base = lastIcon != null ? lastIcon : VirtualFilePresentation.getIcon(file);
- return IconDeferrer.getInstance().defer(base, new FileIconKey(file, project, flags), new NullableFunction<FileIconKey, Icon>() {
- @Override
- public Icon fun(final FileIconKey key) {
- final VirtualFile file = key.getFile();
- final int flags = key.getFlags();
- final Project project = key.getProject();
-
- if (!file.isValid() || project != null && (project.isDisposed() || !wasEverInitialized(project))) return null;
-
- final Icon providersIcon = getProvidersIcon(file, flags, project);
- Icon icon = providersIcon == null ? VirtualFilePresentation.getIcon(file) : providersIcon;
-
- final boolean dumb = project != null && DumbService.getInstance(project).isDumb();
- for (FileIconPatcher patcher : getPatchers()) {
- if (dumb && !DumbService.isDumbAware(patcher)) {
- continue;
- }
-
- icon = patcher.patchIcon(icon, file, flags, project);
- }
-
- if ((flags & Iconable.ICON_FLAG_READ_STATUS) != 0 &&
- (!file.isWritable() || !WritingAccessProvider.isPotentiallyWritable(file, project))) {
- icon = new LayeredIcon(icon, PlatformIcons.LOCKED_ICON);
- }
- if (file.is(VFileProperty.SYMLINK)) {
- icon = new LayeredIcon(icon, PlatformIcons.SYMLINK_ICON);
- }
-
- Iconable.LastComputedIcon.put(file, icon, flags);
-
- return icon;
- }
- });
+ return IconDeferrer.getInstance().defer(base, new FileIconKey(file, project, flags), ICON_NULLABLE_FUNCTION);
}
@Nullable
diff --git a/platform/core-api/src/com/intellij/util/InstanceofQuery.java b/platform/core-api/src/com/intellij/util/InstanceofQuery.java
index a7d7ddb..bf18d26 100644
--- a/platform/core-api/src/com/intellij/util/InstanceofQuery.java
+++ b/platform/core-api/src/com/intellij/util/InstanceofQuery.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.
diff --git a/platform/core-api/src/com/intellij/util/PathUtil.java b/platform/core-api/src/com/intellij/util/PathUtil.java
index 95d4caf..a368e8f 100644
--- a/platform/core-api/src/com/intellij/util/PathUtil.java
+++ b/platform/core-api/src/com/intellij/util/PathUtil.java
@@ -17,11 +17,13 @@
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileProvider;
-import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.util.io.URLUtil;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,7 +37,7 @@
if (file == null || !file.isValid()) {
return null;
}
- if (file.getFileSystem().getProtocol().equals(StandardFileSystems.JAR_PROTOCOL) && file.getParent() != null) {
+ if (file.getFileSystem().getProtocol().equals(URLUtil.JAR_PROTOCOL) && file.getParent() != null) {
return null;
}
return getLocalPath(file.getPath());
@@ -43,7 +45,7 @@
@NotNull
public static String getLocalPath(@NotNull String path) {
- return FileUtil.toSystemDependentName(StringUtil.trimEnd(path, StandardFileSystems.JAR_SEPARATOR));
+ return FileUtil.toSystemDependentName(StringUtil.trimEnd(path, URLUtil.JAR_SEPARATOR));
}
@NotNull
@@ -100,4 +102,14 @@
return PathUtilRt.isValidFileName(fileName);
}
+ @Contract("null -> null; !null -> !null")
+ public static String toSystemIndependentName(@Nullable String path) {
+ return path == null ? null : FileUtilRt.toSystemIndependentName(path);
+ }
+
+
+ @Contract("null -> null; !null -> !null")
+ public static String toSystemDependentName(@Nullable String path) {
+ return path == null ? null : FileUtilRt.toSystemDependentName(path);
+ }
}
diff --git a/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java b/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java
index 6cda4f5..19854cc 100644
--- a/platform/core-api/src/com/intellij/util/PlatformUtilsCore.java
+++ b/platform/core-api/src/com/intellij/util/PlatformUtilsCore.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,8 +15,10 @@
*/
package com.intellij.util;
+/** @deprecated use PlatformUtils (to remove in IDEA 14) */
public class PlatformUtilsCore {
public static final String PLATFORM_PREFIX_KEY = "idea.platform.prefix";
+
public static final String IDEA_PREFIX = "idea";
public static final String COMMUNITY_PREFIX = "Idea";
public static final String APPCODE_PREFIX = "AppCode";
@@ -36,6 +38,10 @@
return System.getProperty(PLATFORM_PREFIX_KEY, defaultPrefix);
}
+ public static boolean isIntelliJ() {
+ return isIdea() || isCommunity();
+ }
+
public static boolean isIdea() {
return IDEA_PREFIX.equals(getPlatformPrefix());
}
@@ -57,8 +63,15 @@
}
public static boolean isPyCharm() {
- String prefix = getPlatformPrefix();
- return PYCHARM_PREFIX.equals(prefix) || (prefix != null && prefix.startsWith(PYCHARM_PREFIX2));
+ return isPyCharmPro() || isPyCharmCommunity();
+ }
+
+ static boolean isPyCharmPro() {
+ return PYCHARM_PREFIX.equals(getPlatformPrefix());
+ }
+
+ static boolean isPyCharmCommunity() {
+ return PYCHARM_PREFIX2.equals(getPlatformPrefix());
}
public static boolean isPhpStorm() {
@@ -68,8 +81,4 @@
public static boolean isWebStorm() {
return WEB_PREFIX.equals(getPlatformPrefix());
}
-
- public static boolean isIntelliJ() {
- return isIdea() || isCommunity();
- }
}
diff --git a/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java b/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java
index 96257ab..b8bf91a 100644
--- a/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.java
+++ b/platform/core-impl/src/com/intellij/codeInsight/CodeInsightUtilCore.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.
@@ -24,7 +24,7 @@
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
public abstract class CodeInsightUtilCore extends FileModificationService {
@@ -46,7 +46,7 @@
if (element2 == null || element1 == null) return null;
final PsiElement commonParent = PsiTreeUtil.findCommonParent(element1, element2);
final T element =
- ReflectionCache.isAssignable(klass, commonParent.getClass())
+ ReflectionUtil.isAssignable(klass, commonParent.getClass())
? (T)commonParent : PsiTreeUtil.getParentOfType(commonParent, klass);
if (element == null || element.getTextRange().getStartOffset() != startOffset || element.getTextRange().getEndOffset() != endOffset) {
return null;
diff --git a/platform/core-impl/src/com/intellij/concurrency/JobLauncher.java b/platform/core-impl/src/com/intellij/concurrency/JobLauncher.java
new file mode 100644
index 0000000..47cea3c
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/concurrency/JobLauncher.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.concurrency;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.util.Consumer;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+import java.util.concurrent.Future;
+
+/**
+ * Invitation-only service for running short-lived computing-intensive IO-free tasks on all available CPU cores.
+ * DO NOT USE for your tasks, IO-bound or long tasks, there is Application#executeOnPooledThread() for that.
+ */
+public abstract class JobLauncher {
+ public static JobLauncher getInstance() {
+ return ServiceManager.getService(JobLauncher.class);
+ }
+
+ /**
+ * Schedules concurrent execution of #thingProcessor over each element of #things and waits for completion
+ * With checkCanceled in each thread delegated to our current progress
+ *
+ * @param things data to process concurrently
+ * @param progress progress indicator
+ * @param failFastOnAcquireReadAction if true, returns false when failed to acquire read action
+ * @param thingProcessor to be invoked concurrently on each element from the collection
+ * @return false if tasks have been canceled,
+ * or at least one processor returned false,
+ * or threw an exception,
+ * or we were unable to start read action in at least one thread
+ * @throws ProcessCanceledException if at least one task has thrown ProcessCanceledException
+ */
+ public abstract <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
+ ProgressIndicator progress,
+ boolean failFastOnAcquireReadAction,
+ @NotNull Processor<T> thingProcessor) throws ProcessCanceledException;
+
+ public abstract <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<? extends T> things,
+ ProgressIndicator progress,
+ boolean runInReadAction,
+ boolean failFastOnAcquireReadAction,
+ @NotNull Processor<T> thingProcessor) throws ProcessCanceledException;
+
+ @NotNull
+ public abstract <T> AsyncFuture<Boolean> invokeConcurrentlyUnderProgressAsync(@NotNull List<? extends T> things,
+ ProgressIndicator progress,
+ boolean failFastOnAcquireReadAction,
+ @NotNull Processor<T> thingProcessor);
+
+
+ /**
+ * NEVER EVER submit runnable which can lock itself for indeterminate amount of time.
+ * This will cause deadlock since this thread pool is an easily exhaustible resource.
+ * Use {@link com.intellij.openapi.application.Application#executeOnPooledThread(java.lang.Runnable)} instead
+ */
+ @NotNull
+ public abstract Job<Void> submitToJobThread(int priority, @NotNull final Runnable action, @Nullable Consumer<Future> onDoneCallback);
+
+ /**
+ * NEVER EVER submit runnable which can lock itself for indeterminate amount of time.
+ * This will cause deadlock since this thread pool is an easily exhaustible resource.
+ * Use {@link com.intellij.openapi.application.Application#executeOnPooledThread(java.lang.Runnable)} instead
+ */
+ @NotNull
+ public Job<Void> submitToJobThread(int priority, @NotNull final Runnable action) {
+ return submitToJobThread(priority, action, null);
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
index fed68c5..60560a3 100644
--- a/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
+++ b/platform/core-impl/src/com/intellij/core/CoreApplicationEnvironment.java
@@ -19,6 +19,7 @@
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderFactoryImpl;
import com.intellij.mock.MockApplication;
+import com.intellij.mock.MockApplicationEx;
import com.intellij.mock.MockFileDocumentManagerImpl;
import com.intellij.mock.MockReferenceProvidersRegistry;
import com.intellij.openapi.Disposable;
@@ -135,7 +136,7 @@
}
protected MockApplication createApplication(Disposable parentDisposable) {
- return new MockApplication(parentDisposable);
+ return new MockApplicationEx(parentDisposable);
}
protected JobLauncher createJobLauncher() {
diff --git a/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java b/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java
index e905ec1..e28de38 100644
--- a/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java
+++ b/platform/core-impl/src/com/intellij/core/CoreProjectEnvironment.java
@@ -26,12 +26,15 @@
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Disposer;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.PsiManager;
+import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.impl.*;
import com.intellij.psi.impl.file.PsiDirectoryFactory;
import com.intellij.psi.impl.file.PsiDirectoryFactoryImpl;
import com.intellij.psi.impl.file.impl.FileManagerImpl;
+import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.search.ProjectScopeBuilder;
import com.intellij.psi.util.CachedValuesManager;
@@ -67,6 +70,10 @@
myPsiManager = new PsiManagerImpl(myProject, null, null, myFileIndexFacade, myMessageBus, modificationTracker);
((FileManagerImpl) myPsiManager.getFileManager()).markInitialized();
registerProjectComponent(PsiManager.class, myPsiManager);
+ myProject.registerService(SmartPointerManager.class, SmartPointerManagerImpl.class);
+ registerProjectComponent(PsiDocumentManager.class, new CorePsiDocumentManager(myProject, myPsiManager,
+ SmartPointerManager.getInstance(myProject), myMessageBus,
+ new MockDocumentCommitProcessor()));
myProject.registerService(ResolveScopeManager.class, createResolveScopeManager(myPsiManager));
diff --git a/platform/core-impl/src/com/intellij/core/CorePsiDocumentManager.java b/platform/core-impl/src/com/intellij/core/CorePsiDocumentManager.java
new file mode 100644
index 0000000..d94aecf
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/core/CorePsiDocumentManager.java
@@ -0,0 +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.core;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.SmartPointerManager;
+import com.intellij.psi.impl.DocumentCommitProcessor;
+import com.intellij.psi.impl.PsiDocumentManagerBase;
+import com.intellij.util.messages.MessageBus;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+class CorePsiDocumentManager extends PsiDocumentManagerBase {
+ public CorePsiDocumentManager(@NotNull Project project,
+ @NotNull PsiManager psiManager,
+ @NotNull SmartPointerManager smartPointerManager,
+ @NotNull MessageBus bus,
+ @NonNls @NotNull DocumentCommitProcessor documentCommitProcessor) {
+ super(project, psiManager, smartPointerManager, bus, documentCommitProcessor);
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/core/MockDocumentCommitProcessor.java b/platform/core-impl/src/com/intellij/core/MockDocumentCommitProcessor.java
new file mode 100644
index 0000000..9a7ac2c
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/core/MockDocumentCommitProcessor.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.core;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.impl.DocumentCommitProcessor;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author nik
+*/
+class MockDocumentCommitProcessor extends DocumentCommitProcessor {
+ @Override
+ public void commitSynchronously(@NotNull Document document, @NotNull Project project) {
+ }
+
+ @Override
+ public void commitAsynchronously(@NotNull Project project, @NotNull Document document, @NonNls @NotNull Object reason) {
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java
index b6535e5..1c9ad33 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/IdeaPluginDescriptorImpl.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.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.diagnostic.PluginException;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ComponentConfig;
import com.intellij.openapi.diagnostic.Logger;
@@ -637,7 +638,20 @@
@Override
public boolean isBundled() {
- return getPath().getAbsolutePath().startsWith(PathManager.getPreInstalledPluginsPath());
+ String path;
+ try {
+ //to avoid paths like this /home/kb/IDEA/bin/../config/plugins/APlugin
+ path = getPath().getCanonicalPath();
+ } catch (IOException e) {
+ path = getPath().getAbsolutePath();
+ }
+ if (ApplicationManager.getApplication().isInternal()) {
+ if (path.startsWith(PathManager.getHomePath() + File.separator + "out" + File.separator + "classes")) {
+ return true;
+ }
+ }
+
+ return path.startsWith(PathManager.getPreInstalledPluginsPath());
}
@Nullable
diff --git a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
index 80f5b54..db813c8 100644
--- a/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
+++ b/platform/core-impl/src/com/intellij/ide/plugins/PluginManagerCore.java
@@ -27,12 +27,15 @@
import com.intellij.openapi.extensions.*;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.PlatformUtilsCore;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.execution.ParametersListUtil;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.Graph;
@@ -61,7 +64,7 @@
public static final float PLUGINS_PROGRESS_MAX_VALUE = 0.3f;
static final Map<PluginId,Integer> ourId2Index = new THashMap<PluginId, Integer>();
@NonNls static final String MODULE_DEPENDENCY_PREFIX = "com.intellij.module";
- static final List<String> ourAvailableModules = new ArrayList<String>();
+ static final Map<String, IdeaPluginDescriptorImpl> ourModulesToContainingPlugins = new HashMap<String, IdeaPluginDescriptorImpl>();
static final PluginClassCache ourPluginClasses = new PluginClassCache();
@NonNls static final String SPECIAL_IDEA_PLUGIN = "IDEA CORE";
static final String DISABLE = "disable";
@@ -69,6 +72,7 @@
static final String EDIT = "edit";
@NonNls private static final String PROPERTY_PLUGIN_PATH = "plugin.path";
static List<String> ourDisabledPlugins = null;
+ static MultiMap<String, String> ourDisabledPluginVersions = null;
static IdeaPluginDescriptor[] ourPlugins;
static String myPluginError = null;
static List<String> myPlugins2Disable = null;
@@ -116,6 +120,42 @@
return ourDisabledPlugins;
}
+ public static MultiMap<String, String> getDisabledPluginVersions() {
+ if (ourDisabledPluginVersions == null) {
+ ourDisabledPluginVersions = MultiMap.createSet();
+
+ if (System.getProperty("idea.ignore.disabled.plugins") == null && !isUnitTestMode()) {
+ BufferedReader br = new BufferedReader(new InputStreamReader(PluginManagerCore.class.getResourceAsStream("/brokenPlugins.txt")));
+ try {
+ String s;
+ while ((s = br.readLine()) != null) {
+ s = s.trim();
+ if (s.startsWith("//")) continue;
+
+ List<String> tokens = ParametersListUtil.parse(s);
+ if (tokens.isEmpty()) continue;
+
+ if (tokens.size() == 1) {
+ throw new RuntimeException("brokenPlugins.txt is broken. The line contains plugin name, but does not contains version: " + s);
+ }
+
+ String pluginId = tokens.get(0);
+ List<String> versions = tokens.subList(1, tokens.size());
+
+ ourDisabledPluginVersions.putValues(pluginId, versions);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException("Failed to read /brokenPlugins.txt", e);
+ }
+ finally {
+ StreamUtil.closeStream(br);
+ }
+ }
+ }
+ return ourDisabledPluginVersions;
+ }
+
static boolean isUnitTestMode() {
final Application app = ApplicationManager.getApplication();
return app != null && app.isUnitTestMode();
@@ -196,7 +236,8 @@
if (processed.contains(dependentPluginId)) continue;
// TODO[yole] should this condition be a parameter?
- if (isModuleDependency(dependentPluginId) && (ourAvailableModules.isEmpty() || ourAvailableModules.contains(dependentPluginId.getIdString()))) {
+ if (isModuleDependency(dependentPluginId) && (ourModulesToContainingPlugins.isEmpty() || ourModulesToContainingPlugins.containsKey(
+ dependentPluginId.getIdString()))) {
continue;
}
if (!optionalDependencies.contains(dependentPluginId)) {
@@ -443,9 +484,8 @@
}
private static void addModulesAsDependents(Map<PluginId, ? super IdeaPluginDescriptorImpl> map) {
- for (String module : ourAvailableModules) {
- // fake plugin descriptors to satisfy dependencies
- map.put(PluginId.getId(module), new IdeaPluginDescriptorImpl());
+ for (Map.Entry<String, IdeaPluginDescriptorImpl> entry : ourModulesToContainingPlugins.entrySet()) {
+ map.put(PluginId.getId(entry.getKey()), entry.getValue());
}
}
@@ -927,7 +967,7 @@
}
final List<String> pluginIds = pluginId == null ? null : StringUtil.split(pluginId, ",");
- final boolean checkModuleDependencies = !ourAvailableModules.isEmpty() && !ourAvailableModules.contains("com.intellij.modules.all");
+ final boolean checkModuleDependencies = !ourModulesToContainingPlugins.isEmpty() && !ourModulesToContainingPlugins.containsKey("com.intellij.modules.all");
if (checkModuleDependencies && !hasModuleDependencies(descriptor)) {
return true;
}
@@ -947,12 +987,17 @@
map.put(pluginDescriptor.getPluginId(), pluginDescriptor);
}
addModulesAsDependents(map);
- final IdeaPluginDescriptor descriptorFromProperty = map.get(PluginId.getId(pluginId));
- shouldLoad = descriptorFromProperty != null && isDependent(descriptorFromProperty, descriptor.getPluginId(), map,
- checkModuleDependencies);
+ for (String id : pluginIds) {
+ final IdeaPluginDescriptor descriptorFromProperty = map.get(PluginId.getId(id));
+ if (descriptorFromProperty != null && isDependent(descriptorFromProperty, descriptor.getPluginId(), map, checkModuleDependencies)) {
+ shouldLoad = true;
+ break;
+ }
+ }
}
} else {
- shouldLoad = !getDisabledPlugins().contains(idString);
+ shouldLoad = !getDisabledPlugins().contains(idString) &&
+ !getDisabledPluginVersions().get(idString).contains(descriptor.getVersion());
}
if (shouldLoad && descriptor instanceof IdeaPluginDescriptorImpl) {
if (isIncompatible(descriptor)) return true;
@@ -1011,10 +1056,12 @@
final List<IdeaPluginDescriptorImpl> result = new ArrayList<IdeaPluginDescriptorImpl>();
final HashMap<String, String> disabledPluginNames = new HashMap<String, String>();
for (IdeaPluginDescriptorImpl descriptor : pluginDescriptors) {
- if (descriptor.getPluginId().getIdString().equals(CORE_PLUGIN_ID)) {
- final List<String> modules = descriptor.getModules();
- if (modules != null) {
- ourAvailableModules.addAll(modules);
+ final List<String> modules = descriptor.getModules();
+ if (modules != null) {
+ for (String module : modules) {
+ if (!ourModulesToContainingPlugins.containsKey(module)) {
+ ourModulesToContainingPlugins.put(module, descriptor);
+ }
}
}
@@ -1044,6 +1091,7 @@
}
mergeOptionalConfigs(idToDescriptorMap);
+ addModulesAsDependents(idToDescriptorMap);
// sort descriptors according to plugin dependencies
Collections.sort(result, getPluginDescriptorComparator(idToDescriptorMap));
diff --git a/platform/core-impl/src/com/intellij/indentation/AbstractIndentParser.java b/platform/core-impl/src/com/intellij/indentation/AbstractIndentParser.java
new file mode 100644
index 0000000..4905883
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/indentation/AbstractIndentParser.java
@@ -0,0 +1,243 @@
+/*
+ * 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.indentation;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiParser;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.util.containers.HashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: Andrey.Vokin
+ * Date: 3/20/12
+ */
+public abstract class AbstractIndentParser implements PsiParser {
+ protected PsiBuilder myBuilder;
+
+ protected int myCurrentIndent;
+
+ protected HashMap<PsiBuilder.Marker, Integer> myIndents;
+ protected HashMap<PsiBuilder.Marker, Boolean> myNewLines;
+
+ protected boolean myNewLine = true;
+
+ @NotNull
+ public ASTNode parse(IElementType root, PsiBuilder builder) {
+ myNewLines = new HashMap<PsiBuilder.Marker, Boolean>();
+ myIndents = new HashMap<PsiBuilder.Marker, Integer>();
+ myBuilder = builder;
+ parseRoot(root);
+ return myBuilder.getTreeBuilt();
+ }
+
+ protected abstract void parseRoot(IElementType root);
+
+ public PsiBuilder.Marker mark(boolean couldBeRolledBack) {
+ final PsiBuilder.Marker marker = myBuilder.mark();
+ if (couldBeRolledBack) {
+ myIndents.put(marker, myCurrentIndent);
+ myNewLines.put(marker, myNewLine);
+ }
+ return marker;
+ }
+
+ public PsiBuilder.Marker mark() {
+ return mark(false);
+ }
+
+ public void done(@NotNull final PsiBuilder.Marker marker, @NotNull final IElementType elementType) {
+ myIndents.remove(marker);
+ myNewLines.remove(marker);
+
+ marker.done(elementType);
+ }
+
+ public static void collapse(@NotNull final PsiBuilder.Marker marker, @NotNull final IElementType elementType) {
+ marker.collapse(elementType);
+ }
+
+ protected static void drop(@NotNull final PsiBuilder.Marker marker) {
+ marker.drop();
+ }
+
+ protected void rollbackTo(@NotNull final PsiBuilder.Marker marker) {
+ if (myIndents.get(marker) == null) {
+ throw new RuntimeException("Parser can't rollback marker that was created by mark() method, use mark(true) instead");
+ }
+ myCurrentIndent = myIndents.get(marker);
+ myNewLine = myNewLines.get(marker);
+
+ myIndents.remove(marker);
+ myNewLines.remove(marker);
+ marker.rollbackTo();
+ }
+
+ protected boolean eof() {
+ return myBuilder.eof();
+ }
+
+ protected int getCurrentOffset() {
+ return myBuilder.getCurrentOffset();
+ }
+
+ public int getCurrentIndent() {
+ return myCurrentIndent;
+ }
+
+ protected void error(String message) {
+ myBuilder.error(message);
+ }
+
+ @Nullable
+ public IElementType getTokenType() {
+ return myBuilder.getTokenType();
+ }
+
+ protected static boolean tokenIn(@Nullable final IElementType elementType, IElementType... tokens) {
+ for (IElementType token : tokens) {
+ if (elementType == token) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected boolean currentTokenIn(IElementType... tokens) {
+ return tokenIn(getTokenType(), tokens);
+ }
+
+ protected boolean currentTokenIn(@NotNull final TokenSet tokenSet) {
+ return tokenSet.contains(getTokenType());
+ }
+
+ protected static boolean tokenIn(@Nullable final IElementType elementType, @NotNull final TokenSet tokenSet) {
+ return tokenSet.contains(elementType);
+ }
+
+ @NotNull
+ protected String getTokenText() {
+ String result = myBuilder.getTokenText();
+ if (result == null) {
+ result = "";
+ }
+ return result;
+ }
+
+ protected boolean expect(@NotNull final IElementType elementType) {
+ return expect(elementType, "Expected: " + elementType);
+ }
+
+ protected boolean expect(@NotNull final IElementType elementType, String expectedMessage) {
+ if (getTokenType() == elementType) {
+ advance();
+ return true;
+ }
+ error(expectedMessage);
+ return false;
+ }
+
+ @Nullable
+ public IElementType lookAhead(int step) {
+ return myBuilder.lookAhead(step);
+ }
+
+ @Nullable
+ public IElementType rawLookup(int step) {
+ return myBuilder.rawLookup(step);
+ }
+
+ public boolean isNewLine() {
+ return myNewLine;
+ }
+
+ public void advance() {
+ final String tokenText = myBuilder.getTokenText();
+ final int tokenLength = tokenText == null ? 0 : tokenText.length();
+
+ final int whiteSpaceStart = getCurrentOffset() + tokenLength;
+ myBuilder.advanceLexer();
+ final int whiteSpaceEnd = getCurrentOffset();
+ final String whiteSpaceText = myBuilder.getOriginalText().subSequence(whiteSpaceStart, whiteSpaceEnd).toString();
+
+ int i = whiteSpaceText.lastIndexOf('\n');
+ if (i >= 0) {
+ myCurrentIndent = whiteSpaceText.length() - i - 1;
+ myNewLine = true;
+ }
+ else {
+ myNewLine = false;
+ }
+ }
+
+ public void recalculateCurrentIndent() {
+ int i = 0;
+ int firstIndentOffset = myBuilder.getCurrentOffset();
+ while (myBuilder.rawLookup(i) != null && myBuilder.rawLookup(i) != getEolElementType()) {
+ firstIndentOffset = myBuilder.rawTokenTypeStart(i);
+ i--;
+ }
+ int lastIndentOffset = firstIndentOffset;
+ i++;
+ while (myBuilder.rawLookup(i) == getIndentElementType()) {
+ i++;
+ lastIndentOffset = myBuilder.rawTokenTypeStart(i);
+ }
+ myCurrentIndent = lastIndentOffset - firstIndentOffset;
+ }
+
+ protected void advanceUntil(TokenSet tokenSet) {
+ while (getTokenType() != null && !isNewLine() && !tokenSet.contains(getTokenType())) {
+ advance();
+ }
+ }
+
+ protected void advanceUntilEol() {
+ advanceUntil(TokenSet.EMPTY);
+ }
+
+ protected void errorUntil(TokenSet tokenSet, String message) {
+ PsiBuilder.Marker errorMarker = mark();
+ advanceUntil(tokenSet);
+ errorMarker.error(message);
+ }
+
+ protected void errorUntilEol(@NotNull String message) {
+ PsiBuilder.Marker errorMarker = mark();
+ advanceUntilEol();
+ errorMarker.error(message);
+ }
+
+ protected void errorUntilEof(@NotNull String message) {
+ PsiBuilder.Marker errorMarker = mark();
+ while (!eof()) {
+ advance();
+ }
+ errorMarker.error(message);
+ }
+
+ protected void expectEolOrEof() {
+ if (!isNewLine() && !eof()) {
+ errorUntilEol("End of line expected");
+ }
+ }
+
+ protected abstract IElementType getIndentElementType();
+ protected abstract IElementType getEolElementType();
+}
diff --git a/platform/core-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java b/platform/core-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java
new file mode 100644
index 0000000..bf448cc
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java
@@ -0,0 +1,110 @@
+/*
+ * 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.indentation;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.folding.FoldingBuilder;
+import com.intellij.lang.folding.FoldingDescriptor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+
+/**
+ * @author oleg
+ */
+public abstract class IndentationFoldingBuilder implements FoldingBuilder, DumbAware {
+ private final TokenSet myTokenSet;
+
+ public IndentationFoldingBuilder(final TokenSet tokenSet) {
+ myTokenSet = tokenSet;
+ }
+
+ @Override
+ @NotNull
+ public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode astNode, @NotNull Document document) {
+ List<FoldingDescriptor> descriptors = new LinkedList<FoldingDescriptor>();
+ collectDescriptors(astNode, descriptors);
+ return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
+ }
+
+ private void collectDescriptors(@NotNull final ASTNode node, @NotNull final List<FoldingDescriptor> descriptors) {
+ final Queue<ASTNode> toProcess = new LinkedList<ASTNode>();
+ toProcess.add(node);
+ while (!toProcess.isEmpty()) {
+ final ASTNode current = toProcess.remove();
+ if (current.getTreeParent() != null
+ && current.getTextLength() > 1
+ && myTokenSet.contains(current.getElementType()))
+ {
+ descriptors.add(new FoldingDescriptor(current, current.getTextRange()));
+ }
+ for (ASTNode child = current.getFirstChildNode(); child != null; child = child.getTreeNext()) {
+ toProcess.add(child);
+ }
+ }
+ }
+
+ @Override
+ @Nullable
+ public String getPlaceholderText(@NotNull final ASTNode node) {
+ final StringBuilder builder = new StringBuilder();
+ ASTNode child = node.getFirstChildNode();
+ while (child != null) {
+ String text = child.getText();
+ if (text == null) {
+ if (builder.length() > 0) {
+ break;
+ }
+ }
+ else if (!text.contains("\n")) {
+ builder.append(text);
+ }
+ else if (builder.length() > 0) {
+ builder.append(text.substring(0, text.indexOf('\n')));
+ break;
+ }
+ else {
+ builder.append(getFirstNonEmptyLine(text));
+ if (builder.length() > 0) {
+ break;
+ }
+ }
+ child = child.getTreeNext();
+ }
+ return builder.toString();
+ }
+
+ @NotNull
+ private static String getFirstNonEmptyLine(@NotNull final String text) {
+ int start = 0;
+ int end;
+ while ((end = text.indexOf('\n', start)) != -1 && start >= end) {
+ start = end + 1;
+ }
+ return end == -1 ? text.substring(start) : text.substring(start, end);
+ }
+
+ @Override
+ public boolean isCollapsedByDefault(@NotNull ASTNode node) {
+ return false;
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/indentation/IndentationParser.java b/platform/core-impl/src/com/intellij/indentation/IndentationParser.java
new file mode 100644
index 0000000..6778768
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/indentation/IndentationParser.java
@@ -0,0 +1,174 @@
+/*
+ * 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.indentation;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.PsiParser;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.util.containers.Stack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author oleg
+ */
+public abstract class IndentationParser implements PsiParser {
+ @NotNull
+ private final IElementType myEolTokenType;
+ @NotNull
+ private final IElementType myIndentTokenType;
+ @NotNull
+ private final IElementType myBlockElementType;
+ @NotNull
+ private final IElementType myDocumentType;
+
+ public IndentationParser(
+ @NotNull IElementType documentType,
+ @NotNull final IElementType blockElementType,
+ @NotNull final IElementType eolTokenType,
+ @NotNull final IElementType indentTokenType)
+ {
+ myDocumentType = documentType;
+ myBlockElementType = blockElementType;
+ myEolTokenType = eolTokenType;
+ myIndentTokenType = indentTokenType;
+ }
+
+ @Override
+ @NotNull
+ public final ASTNode parse(final IElementType root, final PsiBuilder builder) {
+ final PsiBuilder.Marker fileMarker = builder.mark();
+ final PsiBuilder.Marker documentMarker = builder.mark();
+
+ final Stack<BlockInfo> stack = new Stack<BlockInfo>();
+ stack.push(new BlockInfo(0, builder.mark(), builder.getTokenType()));
+
+ PsiBuilder.Marker startLineMarker = null;
+ int currentIndent = 0;
+ boolean eolSeen = false;
+
+ while (!builder.eof()) {
+ final IElementType type = builder.getTokenType();
+ // EOL
+ if (type == myEolTokenType) {
+ // Handle variant with several EOLs
+ if (startLineMarker == null) {
+ startLineMarker = builder.mark();
+ }
+ eolSeen = true;
+ }
+ else {
+ if (type == myIndentTokenType) {
+ //noinspection ConstantConditions
+ currentIndent = builder.getTokenText().length();
+ }
+ else {
+ if (!eolSeen && !stack.isEmpty() && currentIndent > 0 && currentIndent < stack.peek().getIndent()) {
+ // sometimes we do not have EOL between indents
+ eolSeen = true;
+ }
+ if (eolSeen) {
+ if (startLineMarker != null) {
+ startLineMarker.rollbackTo();
+ startLineMarker = null;
+ }
+ // Close indentation blocks
+ while (!stack.isEmpty() && currentIndent < stack.peek().getIndent()) {
+ final BlockInfo blockInfo = stack.pop();
+ closeBlock(builder, blockInfo.getMarker(), blockInfo.getStartTokenType());
+ }
+
+ if (!stack.isEmpty()) {
+ final BlockInfo blockInfo = stack.peek();
+ if (currentIndent >= blockInfo.getIndent()) {
+ if (currentIndent == blockInfo.getIndent()) {
+ final BlockInfo info = stack.pop();
+ closeBlock(builder, info.getMarker(), info.getStartTokenType());
+ }
+ passEOLsAndIndents(builder);
+ stack.push(new BlockInfo(currentIndent, builder.mark(), type));
+ }
+ }
+ eolSeen = false;
+ currentIndent = 0;
+ }
+ }
+ }
+ advanceLexer(builder);
+ }
+
+ // Close all left opened markers
+ if (startLineMarker != null){
+ startLineMarker.drop();
+ }
+ while (!stack.isEmpty()){
+ final BlockInfo blockInfo = stack.pop();
+ closeBlock(builder, blockInfo.getMarker(), blockInfo.getStartTokenType());
+ }
+
+ documentMarker.done(myDocumentType);
+ fileMarker.done(root);
+ return builder.getTreeBuilt();
+ }
+
+ protected void closeBlock(final @NotNull PsiBuilder builder,
+ final @NotNull PsiBuilder.Marker marker,
+ final @Nullable IElementType startTokenType)
+ {
+ marker.done(myBlockElementType);
+ }
+
+ protected void advanceLexer(@NotNull PsiBuilder builder) {
+ builder.advanceLexer();
+ }
+
+ private void passEOLsAndIndents(@NotNull final PsiBuilder builder) {
+ IElementType tokenType = builder.getTokenType();
+ while (tokenType == myEolTokenType || tokenType == myIndentTokenType) {
+ builder.advanceLexer();
+ tokenType = builder.getTokenType();
+ }
+ }
+
+ private static final class BlockInfo {
+ private final int myIndent;
+ @NotNull
+ private final PsiBuilder.Marker myMarker;
+ @Nullable
+ private final IElementType myStartTokenType;
+
+ private BlockInfo(final int indent, final @NotNull PsiBuilder.Marker marker, final @Nullable IElementType type) {
+ myIndent = indent;
+ myMarker = marker;
+ myStartTokenType = type;
+ }
+
+ public int getIndent() {
+ return myIndent;
+ }
+
+ @NotNull
+ public PsiBuilder.Marker getMarker() {
+ return myMarker;
+ }
+
+ @Nullable
+ public IElementType getStartTokenType() {
+ return myStartTokenType;
+ }
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/indentation/OperationParserHelper.java b/platform/core-impl/src/com/intellij/indentation/OperationParserHelper.java
new file mode 100644
index 0000000..a85468a
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/indentation/OperationParserHelper.java
@@ -0,0 +1,222 @@
+/*
+ * 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.indentation;
+
+import com.intellij.lang.PsiBuilder;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * User: Andrey.Vokin
+ * Date: 3/23/12
+ */
+public class OperationParserHelper {
+ private static boolean parsePostfixOperation(@NotNull final BinaryOperationParser parser) {
+ final PsiBuilder.Marker tempMarker = parser.mark();
+ PsiBuilder.Marker lastMarker = tempMarker;
+ boolean result = parsePrefixOperation(parser);
+ boolean tempMarkerDeleted = false;
+ while (parser.getPostfixOperators().contains(parser.getTokenType()) &&
+ !parser.getWhitespaceTokenSet().contains(parser.rawLookup(-1)) && !parser.isNewLine()) {
+ final PsiBuilder.Marker operationMarker = lastMarker.precede();
+ if (!tempMarkerDeleted) {
+ tempMarker.drop();
+ tempMarkerDeleted = true;
+ }
+ lastMarker = operationMarker;
+ parser.advance();
+ parser.done(operationMarker, parser.getPostfixExpressionElementType());
+ result = true;
+ }
+ if (!tempMarkerDeleted) {
+ tempMarker.drop();
+ }
+ return result;
+ }
+
+ private static boolean parsePrefixOperation(@NotNull final BinaryOperationParser parser) {
+ int prefixCount = 0;
+ while (parser.getPrefixOperators().contains(parser.lookAhead(prefixCount))) {
+ prefixCount++;
+ }
+ final PsiBuilder.Marker[] prefixMarkers = new PsiBuilder.Marker[prefixCount];
+ final IElementType[] elementTypes = new IElementType[prefixCount];
+ for (int i = 0; i < prefixCount; i++) {
+ prefixMarkers[i] = parser.mark();
+ elementTypes[i] = parser.getPrefixExpressionElementType();
+ parser.advance();
+ }
+ final boolean result = parser.parseSimpleExpression() || prefixCount > 0;
+ for (int i = prefixCount - 1; i >= 0; i--) {
+ parser.done(prefixMarkers[i], elementTypes[i]);
+ }
+ return result;
+ }
+
+ public static boolean callParsingBinaryOperation(@NotNull final BinaryOperationParser parser, int level) {
+ if (level < 0) {
+ return parsePostfixOperation(parser);
+ }
+ return parseBinaryOperation(parser, level);
+ }
+
+ private static boolean isBinaryOperator(@NotNull final BinaryOperationParser parser, int level) {
+ if (parser instanceof CustomBinaryOperationParser) {
+ return ((CustomBinaryOperationParser)parser).isBinaryOperator(level);
+ }
+ final IElementType tokenType = parser.getTokenType();
+ return parser.getOperatorsByPriority()[level].contains(tokenType);
+ }
+
+ private static void parseBinaryOperator(@NotNull final BinaryOperationParser parser) {
+ if (parser instanceof CustomBinaryOperationParser) {
+ ((CustomBinaryOperationParser)parser).parseBinaryOperator();
+ } else {
+ parser.advance();
+ }
+ }
+
+ /**
+ * Parses arithmetic mult, arithmetic sum, bit operation, relation operation
+ * @param level 0 for mult, 1, for sum, 2 for bit, 3 for relations
+ */
+ private static boolean parseBinaryOperation(@NotNull final BinaryOperationParser parser, int level) {
+ final PsiBuilder.Marker tempMarker = parser.mark();
+ PsiBuilder.Marker lastMarker = tempMarker;
+ boolean result = callParsingBinaryOperation(parser, level - 1);
+ boolean tempMarkerDeleted = false;
+ while (isBinaryOperator(parser, level) && !parser.isNewLine()) {
+ final PsiBuilder.Marker operationMarker = lastMarker.precede();
+ if (!tempMarkerDeleted) {
+ tempMarker.drop();
+ tempMarkerDeleted = true;
+ }
+ lastMarker = operationMarker;
+ parseBinaryOperator(parser);
+ callParsingBinaryOperation(parser, level - 1);
+ parser.done(operationMarker, parser.getOperationElementTypes()[level]);
+ result = true;
+ }
+ if (!tempMarkerDeleted) {
+ tempMarker.drop();
+ }
+ return result;
+ }
+
+ public interface BinaryOperationParser {
+ /**
+ * Gets the TokenType from PsiBuilder
+ * @return IElementType of current element
+ */
+ IElementType getTokenType();
+
+ /**
+ * Checks current token starts the line
+ * @return true if new line
+ */
+ boolean isNewLine();
+
+ /**
+ * Advance current position of PsiBuilder
+ */
+ void advance();
+
+ /**
+ * See what token type is in <code>step</code> ahead / benind (including whitespaces)
+ * @param step 0 is current token, -1 is previous, 1 is next and so on
+ * @return IElementType of the required element
+ */
+ IElementType rawLookup(int step);
+
+ /**
+ * See what token type is in <code>step</code> ahead (not including whitespaces)
+ * @param step 0 is current token, 1 is next and so on
+ * @return IElementType of the required element
+ */
+ IElementType lookAhead(int step);
+
+ /**
+ * Create new marker
+ * @return PsiBuilder.Marker of created marker
+ */
+ PsiBuilder.Marker mark();
+
+ /**
+ * Close marker with element type
+ * @param marker to close
+ * @param elementType to close marker as
+ */
+ void done(PsiBuilder.Marker marker, IElementType elementType);
+
+ /**
+ * Parses operand
+ * @return boolean if success
+ */
+ boolean parseSimpleExpression();
+
+ /**
+ * Provides all whitespace tokens
+ * @return TokenSet of whitespaces
+ */
+ TokenSet getWhitespaceTokenSet();
+
+ /**
+ * Provides prefix operators
+ * @return TokenSet of prefix operators
+ */
+ TokenSet getPrefixOperators();
+
+ /**
+ * Provides postfix operators
+ * @return TokenSet of prefix operators
+ */
+ TokenSet getPostfixOperators();
+
+ /**
+ * Provides operation priority and operands
+ * @return array of TokenSets
+ */
+ TokenSet[] getOperatorsByPriority();
+
+ /**
+ * Provides element types to finish postfix element marker
+ * @return IElementType
+ */
+ @Nullable
+ IElementType getPostfixExpressionElementType();
+
+ /**
+ * Provides element types to finish prefix element marker
+ * @return IElementType
+ */
+ @Nullable
+ IElementType getPrefixExpressionElementType();
+
+ /**
+ * Provides element types to finish binary operation element
+ * @return array of Element Types
+ */
+ IElementType[] getOperationElementTypes();
+ }
+
+ public interface CustomBinaryOperationParser {
+ boolean isBinaryOperator(int level);
+
+ void parseBinaryOperator();
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/lang/HelpID.java b/platform/core-impl/src/com/intellij/lang/HelpID.java
new file mode 100644
index 0000000..acf5b38
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/lang/HelpID.java
@@ -0,0 +1,22 @@
+/*
+ * 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.lang;
+
+import org.jetbrains.annotations.NonNls;
+
+public class HelpID {
+ @NonNls public static final String FIND_OTHER_USAGES = "reference.dialogs.findUsages.other";
+}
diff --git a/platform/core-impl/src/com/intellij/lang/LangBundle.java b/platform/core-impl/src/com/intellij/lang/LangBundle.java
index ceab515..46ea66f 100644
--- a/platform/core-impl/src/com/intellij/lang/LangBundle.java
+++ b/platform/core-impl/src/com/intellij/lang/LangBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* @author yole
*/
public class LangBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.LangBundle";
private LangBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-impl/src/com/intellij/lang/WhitespacesBinders.java b/platform/core-impl/src/com/intellij/lang/WhitespacesBinders.java
new file mode 100644
index 0000000..4756be6
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/lang/WhitespacesBinders.java
@@ -0,0 +1,76 @@
+/*
+ * 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.lang;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class WhitespacesBinders {
+ public static final WhitespacesAndCommentsBinder DEFAULT_RIGHT_BINDER = new WhitespacesAndCommentsBinder() {
+ public int getEdgePosition(List<IElementType> tokens, boolean atStreamEdge, TokenTextGetter getter) {
+ return 0;
+ }
+ };
+ public static final WhitespacesAndCommentsBinder DEFAULT_LEFT_BINDER = new WhitespacesAndCommentsBinder() {
+ public int getEdgePosition(List<IElementType> tokens, boolean atStreamEdge, TokenTextGetter getter) {
+ return tokens.size();
+ }
+ };
+
+ public static final WhitespacesAndCommentsBinder GREEDY_LEFT_BINDER = DEFAULT_RIGHT_BINDER;
+ public static final WhitespacesAndCommentsBinder GREEDY_RIGHT_BINDER = DEFAULT_LEFT_BINDER;
+
+ public static WhitespacesAndCommentsBinder leadingCommentsBinder(@NotNull Condition<IElementType> isCommentCondition) {
+ return new LeadingCommentsBinder(isCommentCondition);
+ }
+
+ public static WhitespacesAndCommentsBinder leadingCommentsBinder(IElementType... commentTypes) {
+ return leadingCommentsBinder(TokenSet.create(commentTypes));
+ }
+
+ public static WhitespacesAndCommentsBinder leadingCommentsBinder(@NotNull final TokenSet commentTypes) {
+ return leadingCommentsBinder(new Condition<IElementType>() {
+ @Override
+ public boolean value(IElementType type) {
+ return commentTypes.contains(type);
+ }
+ });
+ }
+
+ private static class LeadingCommentsBinder implements WhitespacesAndCommentsBinder {
+ @NotNull private final Condition<IElementType> myIsCommentCondition;
+
+ LeadingCommentsBinder(@NotNull Condition<IElementType> isCommentCondition) {
+ myIsCommentCondition = isCommentCondition;
+ }
+
+ @Override
+ public int getEdgePosition(List<IElementType> tokens, boolean atStreamEdge, TokenTextGetter getter) {
+ int i = 0;
+ while (i < tokens.size() && !myIsCommentCondition.value(tokens.get(i))) {
+ i++;
+ }
+ return i;
+ }
+ }
+
+ private WhitespacesBinders() {
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/lang/folding/NamedFoldingDescriptor.java b/platform/core-impl/src/com/intellij/lang/folding/NamedFoldingDescriptor.java
new file mode 100644
index 0000000..abf78e5
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/lang/folding/NamedFoldingDescriptor.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.folding;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.editor.FoldingGroup;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class NamedFoldingDescriptor extends FoldingDescriptor {
+ private final String myPlaceholderText;
+
+ public NamedFoldingDescriptor(@NotNull PsiElement e, int start, int end, @Nullable FoldingGroup group, @NotNull String placeholderText) {
+ this(e.getNode(), new TextRange(start, end), group, placeholderText);
+ }
+
+ public NamedFoldingDescriptor(@NotNull ASTNode node, int start, int end, @Nullable FoldingGroup group, @NotNull String placeholderText) {
+ this(node, new TextRange(start, end), group, placeholderText);
+ }
+
+ public NamedFoldingDescriptor(@NotNull ASTNode node,
+ @NotNull final TextRange range,
+ @Nullable FoldingGroup group,
+ @NotNull String placeholderText) {
+ super(node, range, group);
+ myPlaceholderText = placeholderText;
+ }
+
+ @Override
+ @NotNull
+ public String getPlaceholderText() {
+ return myPlaceholderText;
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
index 48d7c43..dabe29e 100644
--- a/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
+++ b/platform/core-impl/src/com/intellij/lang/impl/PsiBuilderImpl.java
@@ -122,20 +122,6 @@
}
});
- private static final WhitespacesAndCommentsBinder DEFAULT_LEFT_EDGE_TOKEN_BINDER = new WhitespacesAndCommentsBinder() {
- @Override
- public int getEdgePosition(final List<IElementType> tokens, final boolean atStreamEdge, final TokenTextGetter getter) {
- return tokens.size();
- }
- };
-
- private static final WhitespacesAndCommentsBinder DEFAULT_RIGHT_EDGE_TOKEN_BINDER = new WhitespacesAndCommentsBinder() {
- @Override
- public int getEdgePosition(final List<IElementType> tokens, final boolean atStreamEdge, final TokenTextGetter getter) {
- return 0;
- }
- };
-
public static void registerWhitespaceToken(IElementType type) {
ourAnyLanguageWhitespaceTokens = TokenSet.orSet(ourAnyLanguageWhitespaceTokens, TokenSet.create(type));
}
@@ -302,7 +288,7 @@
private int myHC = -1;
private StartMarker() {
- myEdgeTokenBinder = DEFAULT_LEFT_EDGE_TOKEN_BINDER;
+ myEdgeTokenBinder = WhitespacesBinders.DEFAULT_LEFT_BINDER;
}
@Override
@@ -314,7 +300,7 @@
myDebugAllocationPosition = null;
myFirstChild = myLastChild = null;
myHC = -1;
- myEdgeTokenBinder = DEFAULT_LEFT_EDGE_TOKEN_BINDER;
+ myEdgeTokenBinder = WhitespacesBinders.DEFAULT_LEFT_BINDER;
}
@Override
@@ -577,7 +563,7 @@
private boolean myCollapse = false;
public DoneMarker() {
- myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
}
public DoneMarker(final StartMarker marker, final int currentLexeme) {
@@ -590,7 +576,7 @@
public void clean() {
super.clean();
myStart = null;
- myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
}
@Override
@@ -637,7 +623,7 @@
myBuilder = builder;
myMessage = message;
myLexemeIndex = idx;
- myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
}
@Override
@@ -883,7 +869,7 @@
DoneWithErrorMarker doneMarker = new DoneWithErrorMarker((StartMarker)marker, myCurrentLexeme, message);
boolean tieToTheLeft = isEmpty(((StartMarker)marker).myLexemeIndex, myCurrentLexeme);
- if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
((StartMarker)marker).myDoneMarker = doneMarker;
myProduction.add(doneMarker);
@@ -897,7 +883,7 @@
DoneWithErrorMarker doneMarker = new DoneWithErrorMarker((StartMarker)marker, ((StartMarker)before).myLexemeIndex, message);
boolean tieToTheLeft = isEmpty(((StartMarker)marker).myLexemeIndex, ((StartMarker)before).myLexemeIndex);
- if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
((StartMarker)marker).myDoneMarker = doneMarker;
myProduction.add(beforeIndex, doneMarker);
@@ -911,7 +897,7 @@
doneMarker.myLexemeIndex = myCurrentLexeme;
boolean tieToTheLeft = doneMarker.myStart.myType.isLeftBound() &&
isEmpty(((StartMarker)marker).myLexemeIndex, myCurrentLexeme);
- if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
((StartMarker)marker).myDoneMarker = doneMarker;
myProduction.add(doneMarker);
@@ -928,7 +914,7 @@
doneMarker.myStart = (StartMarker)marker;
boolean tieToTheLeft = doneMarker.myStart.myType.isLeftBound() &&
isEmpty(((StartMarker)marker).myLexemeIndex, ((StartMarker)before).myLexemeIndex);
- if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = DEFAULT_RIGHT_EDGE_TOKEN_BINDER;
+ if (tieToTheLeft) ((StartMarker)marker).myEdgeTokenBinder = WhitespacesBinders.DEFAULT_RIGHT_BINDER;
((StartMarker)marker).myDoneMarker = doneMarker;
myProduction.add(beforeIndex, doneMarker);
diff --git a/platform/core-impl/src/com/intellij/mock/MockApplication.java b/platform/core-impl/src/com/intellij/mock/MockApplication.java
index d881f7a..f331a7d 100644
--- a/platform/core-impl/src/com/intellij/mock/MockApplication.java
+++ b/platform/core-impl/src/com/intellij/mock/MockApplication.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.
@@ -15,10 +15,8 @@
*/
package com.intellij.mock;
-import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.*;
-import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.ThrowableComputable;
@@ -197,6 +195,11 @@
public boolean dominates(@NotNull ModalityState anotherState) {
return false;
}
+
+ @Override
+ public String toString() {
+ return "NONE";
+ }
};
}
return MODALITY_STATE_NONE;
@@ -270,10 +273,4 @@
return new ThreadPoolExecutor(10, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), ConcurrencyUtil.newNamedThreadFactory("MockApplication pooled thread"));
}
}
-
- @Nullable
- @Override
- public PluginId getPluginByClassName(@NotNull String className) {
- return PluginManagerCore.getPluginByClassName(className);
- }
}
diff --git a/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java b/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java
new file mode 100644
index 0000000..2636fae
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/mock/MockApplicationEx.java
@@ -0,0 +1,124 @@
+/*
+ * 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.mock;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ex.ApplicationEx;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.InvalidDataException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.IOException;
+
+public class MockApplicationEx extends MockApplication implements ApplicationEx {
+ public MockApplicationEx(@NotNull Disposable parentDisposable) {
+ super(parentDisposable);
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return "mock";
+ }
+
+ @Override
+ public boolean holdsReadLock() {
+ return false;
+ }
+
+ @Override
+ public void load(String path) throws IOException, InvalidDataException {
+ }
+
+ @Override
+ public boolean isLoaded() {
+ return true;
+ }
+
+ @Override
+ public void exit(boolean force) {
+ }
+
+ @Override
+ public void restart(boolean force) {
+ }
+
+ @Override
+ public void doNotSave() {
+ }
+
+ @Override
+ public void doNotSave(boolean value) {
+ }
+
+ @Override
+ public boolean isDoNotSave() {
+ return false;
+ }
+
+ @Override
+ public boolean runProcessWithProgressSynchronously(@NotNull final Runnable process, @NotNull final String progressTitle, final boolean canBeCanceled, @Nullable final Project project,
+ final JComponent parentComponent) {
+ return false;
+ }
+
+ @Override
+ public boolean runProcessWithProgressSynchronously(@NotNull Runnable process,
+ @NotNull String progressTitle,
+ boolean canBeCanceled,
+ @Nullable Project project,
+ JComponent parentComponent,
+ String cancelText) {
+ return false;
+ }
+
+ @Override
+ public boolean runProcessWithProgressSynchronously(@NotNull Runnable process,
+ @NotNull String progressTitle,
+ boolean canBeCanceled,
+ Project project) {
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public <T> T[] getExtensions(@NotNull final ExtensionPointName<T> extensionPointName) {
+ return Extensions.getRootArea().getExtensionPoint(extensionPointName).getExtensions();
+ }
+
+ @Override
+ public void assertIsDispatchThread(@Nullable final JComponent component) {
+ }
+
+ @Override
+ public void assertTimeConsuming() {
+ }
+
+ @Override
+ public void runEdtSafeAction(@NotNull Runnable runnable) {
+ runnable.run();
+ }
+
+ @Override
+ public boolean tryRunReadAction(@NotNull Runnable runnable) {
+ runReadAction(runnable);
+ return true;
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/mock/MockFileDocumentManagerImpl.java b/platform/core-impl/src/com/intellij/mock/MockFileDocumentManagerImpl.java
index 798078b..c655b8d 100644
--- a/platform/core-impl/src/com/intellij/mock/MockFileDocumentManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/mock/MockFileDocumentManagerImpl.java
@@ -1,3 +1,18 @@
+/*
+ * 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.mock;
import com.intellij.openapi.editor.Document;
@@ -8,6 +23,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.reference.SoftReference;
import com.intellij.util.Function;
import com.intellij.util.containers.WeakFactoryMap;
import org.jetbrains.annotations.NotNull;
@@ -51,7 +67,7 @@
public Document getCachedDocument(@NotNull VirtualFile file) {
if (myCachedDocumentKey != null) {
Reference<Document> reference = file.getUserData(myCachedDocumentKey);
- return reference != null ? reference.get() : null;
+ return SoftReference.dereference(reference);
}
return null;
}
diff --git a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
index ee0f2bb..dd6d73f 100644
--- a/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
+++ b/platform/core-impl/src/com/intellij/mock/MockFileIndexFacade.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.FileIndexFacade;
+import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
@@ -82,6 +83,12 @@
return VfsUtilCore.isAncestor(baseDir, child, false);
}
+ @NotNull
+ @Override
+ public ModificationTracker getRootModificationTracker() {
+ return ModificationTracker.NEVER_CHANGED;
+ }
+
public void addLibraryRoot(VirtualFile file) {
myLibraryRoots.add(file);
}
diff --git a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java
index 23b42f9..84b7ae5 100644
--- a/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/components/impl/ComponentManagerImpl.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,7 +30,7 @@
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusFactory;
@@ -488,7 +488,7 @@
for (int i = 0; i < myComponentInterfaces.size(); i++) {
Class interfaceClass = myComponentInterfaces.get(i);
final Class implClass = myInterfaceToClassMap.get(interfaceClass);
- if (ReflectionCache.isAssignable(baseClass, implClass)) {
+ if (ReflectionUtil.isAssignable(baseClass, implClass)) {
array.add((T)getComponent(interfaceClass));
}
}
diff --git a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java
index be82de1..5fba46a 100644
--- a/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java
+++ b/platform/core-impl/src/com/intellij/openapi/editor/impl/CharArray.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -19,7 +19,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
@@ -189,7 +188,7 @@
}
CharSequence originalSequence = myOriginalSequence;
int origLen = originalSequence == null ? -1 : originalSequence.length();
- String string = myStringRef == null ? null : myStringRef.get();
+ String string = com.intellij.reference.SoftReference.dereference(myStringRef);
int stringLen = string == null ? -1 : string.length();
assert origLen == stringLen || origLen==-1 || stringLen==-1;
@@ -220,7 +219,7 @@
myDebugArray.assertConsistency();
- CharSequence str = myStringRef == null ? null : myStringRef.get();
+ CharSequence str = com.intellij.reference.SoftReference.dereference(myStringRef);
if (str == null) {
if (myHasDeferredChanges) {
str = doSubString(0, myCount + myDeferredShift).toString();
@@ -389,7 +388,7 @@
@NotNull
public String toString() {
assertConsistency();
- String str = myStringRef == null ? null : myStringRef.get();
+ String str = com.intellij.reference.SoftReference.dereference(myStringRef);
if (str == null) {
if (myHasDeferredChanges) {
str = substring(0, length()).toString();
@@ -468,7 +467,7 @@
try {
flushDeferredChanged();
if (myOriginalSequence != null && myArray == null) {
- myArray = array = ArrayUtil.realloc(CharArrayUtil.fromSequence(myOriginalSequence), myOriginalSequence.length());
+ myArray = array = CharArrayUtil.fromSequence(myOriginalSequence);
myStringRef = null;
}
}
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 1ceaba4..df9ed9c 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
@@ -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,12 +32,13 @@
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.util.ArrayUtil;
+import com.intellij.reference.SoftReference;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CharArrayUtil;
+import com.intellij.util.text.ImmutableText;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,20 +54,21 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.DocumentImpl");
public static boolean CHECK_DOCUMENT_CONSISTENCY = ApplicationManager.getApplication() != null && ApplicationManager.getApplication().isUnitTestMode();
+ private final Ref<DocumentListener[]> myCachedDocumentListeners = Ref.create(null);
private final List<DocumentListener> myDocumentListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final RangeMarkerTree<RangeMarkerEx> myRangeMarkers = new RangeMarkerTree<RangeMarkerEx>(this);
private final List<RangeMarker> myGuardedBlocks = new ArrayList<RangeMarker>();
private ReadonlyFragmentModificationHandler myReadonlyFragmentModificationHandler;
private final LineSet myLineSet = new LineSet();
- private final CharArray myText;
+ private volatile ImmutableText myText;
+ private volatile SoftReference<String> myTextString;
private boolean myIsReadOnly = false;
- private boolean isStripTrailingSpacesEnabled = true;
+ private volatile boolean isStripTrailingSpacesEnabled = true;
private volatile long myModificationStamp;
private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);
- private final Ref<DocumentListener[]> myCachedDocumentListeners = Ref.create(null);
private final List<EditReadOnlyListener> myReadOnlyListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private int myCheckGuardedBlocks = 0;
@@ -76,6 +78,29 @@
private volatile boolean myDoingBulkUpdate = false;
private volatile boolean myAcceptSlashR = false;
private boolean myChangeInProgress;
+ private volatile int myBufferSize;
+ private final CharSequence myMutableCharSequence = new CharSequence() {
+ @Override
+ public int length() {
+ return myText.length();
+ }
+
+ @Override
+ public char charAt(int index) {
+ return myText.charAt(index);
+ }
+
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return myText.subSequence(start, end);
+ }
+
+ @NotNull
+ @Override
+ public String toString() {
+ return doGetText();
+ }
+ };
public DocumentImpl(@NotNull String text) {
this(text, false);
@@ -87,7 +112,7 @@
public DocumentImpl(@NotNull CharSequence chars, boolean forUseInNonAWTThread) {
assertValidSeparators(chars);
- myText = new MyCharArray(CharArrayUtil.fromSequence(chars), chars.length());
+ myText = ImmutableText.valueOf(chars);
myLineSet.documentCreated(this);
setCyclicBufferSize(0);
setModificationStamp(LocalTimeCounter.currentTime());
@@ -103,14 +128,10 @@
}
}
- public char[] getRawChars() {
- return myText.getChars();
- }
-
@Override
@NotNull
public char[] getChars() {
- return ArrayUtil.realloc(CharArrayUtil.fromSequence(getCharsSequence()), myText.length());
+ return CharArrayUtil.fromSequence(myText);
}
@Override
@@ -136,7 +157,7 @@
}
boolean markAsNeedsStrippingLater = false;
- CharSequence text = myText.getCharArray();
+ CharSequence text = myText;
RangeMarker caretMarker = caretOffset < 0 || caretOffset > getTextLength() ? null : createRangeMarker(caretOffset, caretOffset);
try {
for (int line = 0; line < myLineSet.getLineCount(); line++) {
@@ -160,13 +181,12 @@
}
else {
final int finalStart = whiteSpaceStart;
- if (project != null) {
- PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(this);
- }
- ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(this, project) {
+ // document must be unblocked by now. If not, some Save handler attempted to modify PSI
+ // which should have been caught by assertion in com.intellij.pom.core.impl.PomModelImpl.runTransaction
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
@Override
public void run() {
- CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(DocumentImpl.this, project) {
@Override
public void run() {
deleteString(finalStart, lineEnd);
@@ -174,7 +194,7 @@
});
}
});
- text = myText.getCharArray();
+ text = myText;
}
}
}
@@ -210,6 +230,7 @@
return myRangeMarkers.removeInterval(rangeMarker);
}
+ @Override
public void registerRangeMarker(@NotNull RangeMarkerEx rangeMarker,
int start,
int end,
@@ -346,7 +367,6 @@
}
assertWriteAccess();
assertValidSeparators(s);
- assertNotNestedModification();
if (!isWritable()) throw new ReadOnlyModificationException(this);
if (s.length() == 0) return;
@@ -356,7 +376,14 @@
throwGuardedFragment(marker, offset, null, s.toString());
}
- myText.insert(s, offset);
+ updateText(myText.insert(offset, ImmutableText.valueOf(s)), offset, null, s, false, LocalTimeCounter.currentTime());
+ trimToSize();
+ }
+
+ private void trimToSize() {
+ if (myBufferSize != 0 && getTextLength() > myBufferSize) {
+ deleteString(0, getTextLength() - myBufferSize);
+ }
}
@Override
@@ -366,16 +393,15 @@
assertWriteAccess();
if (!isWritable()) throw new ReadOnlyModificationException(this);
if (startOffset == endOffset) return;
- assertNotNestedModification();
- CharSequence sToDelete = myText.substring(startOffset, endOffset);
+ CharSequence sToDelete = myText.subSequence(startOffset, endOffset);
RangeMarker marker = getRangeGuard(startOffset, endOffset);
if (marker != null) {
throwGuardedFragment(marker, startOffset, sToDelete.toString(), null);
}
- myText.remove(startOffset, endOffset, sToDelete);
+ updateText(myText.delete(startOffset, endOffset), startOffset, sToDelete, null, false, LocalTimeCounter.currentTime());
}
@Override
@@ -383,8 +409,7 @@
assertBounds(srcStart, srcEnd);
if (dstOffset == srcEnd) return;
ProperTextRange srcRange = new ProperTextRange(srcStart, srcEnd);
- assert !srcRange.containsOffset(dstOffset) :
- String.format("Can't perform text move from range [%d; %d) to offset %d", srcStart, srcEnd, dstOffset);
+ assert !srcRange.containsOffset(dstOffset) : "Can't perform text move from range [" +srcStart+ "; " + srcEnd+ ") to offset "+dstOffset;
String replacement = getCharsSequence().subSequence(srcStart, srcEnd).toString();
@@ -411,7 +436,7 @@
replaceString(startOffset, endOffset, s, LocalTimeCounter.currentTime(), startOffset == 0 && endOffset == getTextLength());
}
- private void replaceString(int startOffset, int endOffset, CharSequence s, final long newModificationStamp, boolean wholeTextReplaced) {
+ private void replaceString(int startOffset, int endOffset, @NotNull CharSequence s, final long newModificationStamp, boolean wholeTextReplaced) {
assertBounds(startOffset, endOffset);
assertWriteAccess();
@@ -420,7 +445,6 @@
if (!isWritable()) {
throw new ReadOnlyModificationException(this);
}
- assertNotNestedModification();
final int newStringLength = s.length();
final CharSequence chars = getCharsSequence();
@@ -440,14 +464,22 @@
endOffset--;
}
- s = s.subSequence(newStartInString, newEndInString);
- CharSequence sToDelete = myText.substring(startOffset, endOffset);
+ CharSequence changedPart = s.subSequence(newStartInString, newEndInString);
+ CharSequence sToDelete = myText.subSequence(startOffset, endOffset);
RangeMarker guard = getRangeGuard(startOffset, endOffset);
if (guard != null) {
- throwGuardedFragment(guard, startOffset, sToDelete.toString(), s.toString());
+ throwGuardedFragment(guard, startOffset, sToDelete.toString(), changedPart.toString());
}
- myText.replace(startOffset, endOffset, sToDelete, s, newModificationStamp, wholeTextReplaced);
+ ImmutableText newText;
+ if (wholeTextReplaced && s instanceof ImmutableText) {
+ newText = (ImmutableText)s;
+ }
+ else {
+ newText = myText.delete(startOffset, endOffset).insert(startOffset, changedPart);
+ }
+ updateText(newText, startOffset, sToDelete, changedPart, wholeTextReplaced, newModificationStamp);
+ trimToSize();
}
private void assertBounds(final int startOffset, final int endOffset) {
@@ -508,7 +540,7 @@
}
}
- private void throwGuardedFragment(RangeMarker guard, int offset, String oldString, String newString) {
+ private void throwGuardedFragment(@NotNull RangeMarker guard, int offset, String oldString, String newString) {
if (myCheckGuardedBlocks > 0 && !myGuardsSuppressed) {
DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, false);
throw new ReadOnlyFragmentModificationException(event, guard);
@@ -543,15 +575,24 @@
}
}
- @NotNull
- private DocumentEvent beforeChangedUpdate(int offset, CharSequence oldString, CharSequence newString, boolean wholeTextReplaced) {
+ private void updateText(@NotNull ImmutableText newText,
+ int offset,
+ @Nullable CharSequence oldString,
+ @Nullable CharSequence newString,
+ boolean wholeTextReplaced,
+ long newModificationStamp) {
+ assertNotNestedModification();
myChangeInProgress = true;
+ final DocumentEvent event;
try {
- return doBeforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
+ event = doBeforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
}
finally {
myChangeInProgress = false;
}
+ myTextString = null;
+ myText = newText;
+ changedUpdate(event, newModificationStamp);
}
@NotNull
@@ -566,6 +607,7 @@
}
}
}
+ assertInsideCommand();
DocumentEvent event = new DocumentEventImpl(this, offset, oldString, newString, myModificationStamp, wholeTextReplaced);
@@ -585,7 +627,16 @@
return event;
}
- private void changedUpdate(DocumentEvent event, long newModificationStamp) {
+ private void assertInsideCommand() {
+ CommandProcessor commandProcessor = CommandProcessor.getInstance();
+ if (!commandProcessor.isUndoTransparentActionInProgress() &&
+ commandProcessor.getCurrentCommand() == null &&
+ myAssertThreading) {
+ throw new IncorrectOperationException("Must not change document outside command or undo-transparent action. See com.intellij.openapi.command.WriteCommandAction or com.intellij.openapi.command.CommandProcessor");
+ }
+ }
+
+ private void changedUpdate(@NotNull DocumentEvent event, long newModificationStamp) {
try {
if (LOG.isDebugEnabled()) LOG.debug(event.toString());
@@ -609,23 +660,33 @@
}
}
+ @NotNull
@Override
public String getText() {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
- return myText.toString();
+ return doGetText();
}
});
}
@NotNull
+ private String doGetText() {
+ String s = SoftReference.dereference(myTextString);
+ if (s == null) {
+ myTextString = new SoftReference<String>(s = myText.toString());
+ }
+ return s;
+ }
+
+ @NotNull
@Override
public String getText(@NotNull final TextRange range) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
- return myText.substring(range.getStartOffset(), range.getEndOffset()).toString();
+ return myText.subSequence(range.getStartOffset(), range.getEndOffset()).toString();
}
});
}
@@ -635,30 +696,26 @@
return myText.length();
}
- /**
- * This method should be used very carefully - only to read the array, and to be sure, that nobody changes
- * text, while this array is processed.
- * Really it is used only to optimize paint in Editor.
- * [Valentin] 25.04.2001: More really, it is used in 61 places in 29 files across the project :-)))
- */
- CharSequence getCharsNoThreadCheck() {
- return getCharsSequence();
- }
-
@Override
@NotNull
public CharSequence getCharsSequence() {
- return myText.getCharArray();
+ return myMutableCharSequence;
+ }
+
+ @NotNull
+ @Override
+ public CharSequence getImmutableCharSequence() {
+ return myText;
}
@Override
public void addDocumentListener(@NotNull DocumentListener listener) {
- if (myCachedDocumentListeners != null) {
- myCachedDocumentListeners.set(null);
- }
+ myCachedDocumentListeners.set(null);
- LOG.assertTrue(!myDocumentListeners.contains(listener), "Already registered: " + listener);
+ if (myDocumentListeners.contains(listener)) {
+ LOG.error("Already registered: " + listener);
+ }
boolean added = myDocumentListeners.add(listener);
LOG.assertTrue(added, listener);
}
@@ -670,12 +727,13 @@
}
private static class DocumentListenerDisposable implements Disposable {
+ private final DocumentListener myListener;
+ private final Ref<DocumentListener[]> myCachedDocumentListenersRef;
+ private final List<DocumentListener> myDocumentListeners;
- private DocumentListener myListener;
- private Ref<DocumentListener[]> myCachedDocumentListenersRef;
- private List<DocumentListener> myDocumentListeners;
-
- public DocumentListenerDisposable(DocumentListener listener, Ref<DocumentListener[]> cachedDocumentListenersRef, List<DocumentListener> documentListeners) {
+ public DocumentListenerDisposable(@NotNull DocumentListener listener,
+ @NotNull Ref<DocumentListener[]> cachedDocumentListenersRef,
+ @NotNull List<DocumentListener> documentListeners) {
myListener = listener;
myCachedDocumentListenersRef = cachedDocumentListenersRef;
myDocumentListeners = documentListeners;
@@ -692,15 +750,13 @@
doRemoveDocumentListener(listener, myCachedDocumentListeners, myDocumentListeners);
}
- private static void doRemoveDocumentListener(DocumentListener listener,
- Ref<DocumentListener[]> cachedDocumentListenersRef,
- List<DocumentListener> documentListeners) {
- if (cachedDocumentListenersRef != null) {
- cachedDocumentListenersRef.set(null);
- }
+ private static void doRemoveDocumentListener(@NotNull DocumentListener listener,
+ @NotNull Ref<DocumentListener[]> cachedDocumentListenersRef,
+ @NotNull List<DocumentListener> documentListeners) {
+ cachedDocumentListenersRef.set(null);
boolean success = documentListeners.remove(listener);
if (!success) {
- LOG.error("Can't remove document listener (" + listener + "). Registered cachedDocumentListenersRef: " + documentListeners);
+ LOG.error("Can't remove document listener (" + listener + "). Registered listeners: " + documentListeners);
}
}
@@ -786,7 +842,8 @@
@Override
public void setCyclicBufferSize(int bufferSize) {
- myText.setBufferSize(bufferSize);
+ assert bufferSize >= 0 : bufferSize;
+ myBufferSize = bufferSize;
}
@Override
@@ -826,7 +883,6 @@
return;
}
myDoingBulkUpdate = value;
- myText.setDeferredChangeMode(value);
if (value) {
getPublisher().updateStarted(this);
}
@@ -840,6 +896,7 @@
ApplicationManager.getApplication().getMessageBus().syncPublisher(DocumentBulkUpdateListener.TOPIC);
}
+ @NotNull
private static DocumentBulkUpdateListener getPublisher() {
return DocumentBulkUpdateListenerHolder.ourBulkChangePublisher;
}
@@ -857,7 +914,6 @@
@NotNull
public String dumpState() {
@NonNls StringBuilder result = new StringBuilder();
- result.append("deferred mode: ").append(myText.isDeferredChangeMode() ? "on" : "off");
result.append(", intervals:\n");
for (int line = 0; line < getLineCount(); line++) {
result.append(line).append(": ").append(getLineStartOffset(line)).append("-")
@@ -869,39 +925,8 @@
return result.toString();
}
- private class MyCharArray extends CharArray {
- private MyCharArray(@NotNull char[] chars, int length) {
- super(0, chars, length);
- }
-
- @Override
- @NotNull
- protected DocumentEvent beforeChangedUpdate(int offset,
- CharSequence oldString,
- CharSequence newString,
- boolean wholeTextReplaced) {
- return DocumentImpl.this.beforeChangedUpdate(offset, oldString, newString, wholeTextReplaced);
- }
-
- @Override
- protected void afterChangedUpdate(@NotNull DocumentEvent event, long newModificationStamp) {
- ((DocumentImpl)event.getDocument()).changedUpdate(event, newModificationStamp);
- }
-
- @Override
- protected void assertWriteAccess() {
- DocumentImpl.this.assertWriteAccess();
- }
-
- @Override
- protected void assertReadAccess() {
- if (myAssertThreading) {
- final Application application = ApplicationManager.getApplication();
- if (application != null) {
- application.assertReadAccessAllowed();
- }
- }
- }
+ @Override
+ public String toString() {
+ return "DocumentImpl[" + FileDocumentManager.getInstance().getFile(this) + "]";
}
}
-
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 43592db..d621140 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
@@ -330,13 +330,17 @@
return charset;
}
+ /**
+ * @deprecated use {@link #charsetFromContentOrNull(com.intellij.openapi.project.Project, com.intellij.openapi.vfs.VirtualFile, CharSequence)}
+ */
@Nullable("returns null if cannot determine from content")
public static Charset charsetFromContentOrNull(@Nullable Project project, @NotNull VirtualFile virtualFile, @NotNull String text) {
- FileType fileType = virtualFile.getFileType();
- if (fileType instanceof LanguageFileType) {
- return ((LanguageFileType)fileType).extractCharsetFromFileContent(project, virtualFile, text);
- }
- return null;
+ return CharsetUtil.extractCharsetFromFileContent(project, virtualFile, virtualFile.getFileType(), text);
+ }
+
+ @Nullable("returns null if cannot determine from content")
+ public static Charset charsetFromContentOrNull(@Nullable Project project, @NotNull VirtualFile virtualFile, @NotNull CharSequence text) {
+ return CharsetUtil.extractCharsetFromFileContent(project, virtualFile, virtualFile.getFileType(), text);
}
@NotNull
diff --git a/platform/core-impl/src/com/intellij/openapi/fileTypes/FileTypesBundle.java b/platform/core-impl/src/com/intellij/openapi/fileTypes/FileTypesBundle.java
index acae629..ac9fd71 100644
--- a/platform/core-impl/src/com/intellij/openapi/fileTypes/FileTypesBundle.java
+++ b/platform/core-impl/src/com/intellij/openapi/fileTypes/FileTypesBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author yole
*/
public class FileTypesBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.FileTypesBundle";
private FileTypesBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/core-impl/src/com/intellij/openapi/fileTypes/PlainTextParserDefinition.java b/platform/core-impl/src/com/intellij/openapi/fileTypes/PlainTextParserDefinition.java
new file mode 100644
index 0000000..5be5390
--- /dev/null
+++ b/platform/core-impl/src/com/intellij/openapi/fileTypes/PlainTextParserDefinition.java
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.openapi.fileTypes;
+
+import com.intellij.lang.ASTFactory;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.ParserDefinition;
+import com.intellij.lang.PsiParser;
+import com.intellij.lexer.EmptyLexer;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.FileViewProvider;
+import com.intellij.psi.PlainTextTokenTypes;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.PsiPlainTextFileImpl;
+import com.intellij.psi.tree.IFileElementType;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiUtilCore;
+import org.jetbrains.annotations.NotNull;
+
+public class PlainTextParserDefinition implements ParserDefinition {
+ private static final IFileElementType PLAIN_FILE_ELEMENT_TYPE = new IFileElementType(PlainTextFileType.INSTANCE.getLanguage()) {
+ @Override
+ public ASTNode parseContents(ASTNode chameleon) {
+ final CharSequence chars = chameleon.getChars();
+ return ASTFactory.leaf(PlainTextTokenTypes.PLAIN_TEXT, chars);
+ }
+ };
+
+ @Override
+ @NotNull
+ public Lexer createLexer(Project project) {
+ return new EmptyLexer();
+ }
+
+ @Override
+ @NotNull
+ public PsiParser createParser(Project project) {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ @Override
+ public IFileElementType getFileNodeType() {
+ return PLAIN_FILE_ELEMENT_TYPE;
+ }
+
+ @Override
+ @NotNull
+ public TokenSet getWhitespaceTokens() {
+ return TokenSet.EMPTY;
+ }
+
+ @Override
+ @NotNull
+ public TokenSet getCommentTokens() {
+ return TokenSet.EMPTY;
+ }
+
+ @Override
+ @NotNull
+ public TokenSet getStringLiteralElements() {
+ return TokenSet.EMPTY;
+ }
+
+ @Override
+ @NotNull
+ public PsiElement createElement(ASTNode node) {
+ return PsiUtilCore.NULL_PSI_ELEMENT;
+ }
+
+ @Override
+ public PsiFile createFile(FileViewProvider viewProvider) {
+ return new PsiPlainTextFileImpl(viewProvider);
+ }
+
+ @Override
+ public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
+ return SpaceRequirements.MAY;
+ }
+}
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java
index 4b3d65a..59f56bd 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFileManagerImpl.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.
@@ -185,7 +185,7 @@
}
@Override
- public void notifyPropertyChanged(final VirtualFile virtualFile, final String property, final Object oldValue, final Object newValue) {
+ public void notifyPropertyChanged(@NotNull final VirtualFile virtualFile, @NotNull final String property, final Object oldValue, final Object newValue) {
final Application application = ApplicationManager.getApplication();
final Runnable runnable = new Runnable() {
@Override
diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java
index 107f3f5..65dc79b 100644
--- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.java
+++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/VirtualFilePointerContainerImpl.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.
@@ -52,7 +52,6 @@
@NonNls public static final String URL_ATTR = "url";
private boolean myDisposed;
private static final boolean TRACE_CREATION = LOG.isDebugEnabled() || ApplicationManager.getApplication().isUnitTestMode();
-
public VirtualFilePointerContainerImpl(@NotNull VirtualFilePointerManager manager,
@NotNull Disposable parentDisposable,
@Nullable VirtualFilePointerListener listener) {
@@ -162,6 +161,7 @@
private void dropCaches() {
myTimeStampOfCachedThings = -1; // make it never equal to myVirtualFilePointerManager.getModificationCount()
+ myCachedThings = EMPTY;
}
@Override
diff --git a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
index 5644097..024062d 100644
--- a/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
+++ b/platform/core-impl/src/com/intellij/pom/core/impl/PomModelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -49,6 +49,7 @@
import com.intellij.psi.text.BlockSupport;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import com.intellij.util.lang.CompoundRuntimeException;
@@ -134,11 +135,15 @@
@Override
public void runTransaction(@NotNull PomTransaction transaction) throws IncorrectOperationException{
+ if (!allowPsiModification) {
+ throw new IncorrectOperationException("Must not modify PSI inside save listener");
+ }
List<Throwable> throwables = new ArrayList<Throwable>(0);
synchronized(PsiLock.LOCK){
final PomModelAspect aspect = transaction.getTransactionAspect();
startTransaction(transaction);
try{
+ DebugUtil.startPsiModification(null);
myBlockedAspects.push(new Pair<PomModelAspect, PomTransaction>(aspect, transaction));
final PomModelEvent event;
@@ -192,6 +197,9 @@
catch (Throwable t) {
throwables.add(t);
}
+ finally {
+ DebugUtil.finishPsiModification();
+ }
}
}
@@ -253,12 +261,7 @@
FileElement fileElement = ((PsiFileImpl)file).getTreeElement();
if (fileElement != null) {
String oldText = fileElement.getText();
- try {
- reparseFile(file, newText, oldText);
- }
- finally {
- TextBlock.get(file).clear();
- }
+ reparseFile(file, newText, oldText);
}
}
}
@@ -327,4 +330,17 @@
}
return psiFile.getNode() != null ? psiFile : null;
}
+
+ private static volatile boolean allowPsiModification = true;
+ public static <T extends Throwable> void guardPsiModificationsIn(@NotNull ThrowableRunnable<T> runnable) throws T {
+ ApplicationManager.getApplication().assertWriteAccessAllowed();
+ boolean old = allowPsiModification;
+ try {
+ allowPsiModification = false;
+ runnable.run();
+ }
+ finally {
+ allowPsiModification = old;
+ }
+ }
}
diff --git a/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java b/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java
index 195c4af..cd3997d 100644
--- a/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java
+++ b/platform/core-impl/src/com/intellij/pom/tree/events/impl/TreeChangeImpl.java
@@ -36,7 +36,7 @@
private final List<Pair<ASTNode,Integer>> mySortedChanges = new ArrayList<Pair<ASTNode, Integer>>(); // change, oldoffset
private final ASTNode myParent;
- private static boolean ourDoChecks = false;
+ private static boolean ourDoChecks = ApplicationManager.getApplication().isEAP();
public TreeChangeImpl(ASTNode parent) {
myParent = parent;
diff --git a/platform/core-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java
index 064239a..0d0e16c 100644
--- a/platform/core-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.java
+++ b/platform/core-impl/src/com/intellij/psi/MultiplePsiFilesPerDocumentFileViewProvider.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.
@@ -29,7 +29,7 @@
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.util.ConcurrencyUtil;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -142,7 +142,7 @@
final PsiFile mainRoot = getPsi(getBaseLanguage());
PsiElement ret = null;
for (final Language language : getLanguages()) {
- if (!ReflectionCache.isAssignable(lang, language.getClass())) continue;
+ if (!ReflectionUtil.isAssignable(lang, language.getClass())) continue;
if (lang.equals(Language.class) && !getLanguages().contains(language)) continue;
final PsiFile psiRoot = getPsi(language);
diff --git a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java
index 5449fe9..742483a 100644
--- a/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.java
+++ b/platform/core-impl/src/com/intellij/psi/SingleRootFileViewProvider.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.
@@ -47,7 +47,7 @@
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.LocalTimeCounter;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
@@ -355,14 +355,14 @@
@Nullable
private Document getCachedDocument() {
- final Document document = myDocument != null ? myDocument.get() : null;
+ final Document document = com.intellij.reference.SoftReference.dereference(myDocument);
if (document != null) return document;
return FileDocumentManager.getInstance().getCachedDocument(getVirtualFile());
}
@Override
public Document getDocument() {
- Document document = myDocument != null ? myDocument.get() : null;
+ Document document = com.intellij.reference.SoftReference.dereference(myDocument);
if (document == null/* TODO[ik] make this change && isEventSystemEnabled()*/) {
document = FileDocumentManager.getInstance().getDocument(getVirtualFile());
myDocument = new SoftReference<Document>(document);
@@ -433,12 +433,12 @@
@Override
public PsiElement findElementAt(int offset, @NotNull Class<? extends Language> lang) {
- if (!ReflectionCache.isAssignable(lang, getBaseLanguage().getClass())) return null;
+ if (!ReflectionUtil.isAssignable(lang, getBaseLanguage().getClass())) return null;
return findElementAt(offset);
}
@Nullable
- protected static PsiElement findElementAt(@Nullable final PsiElement psiFile, final int offset) {
+ public static PsiElement findElementAt(@Nullable final PsiElement psiFile, final int offset) {
if (psiFile == null) return null;
int offsetInElement = offset;
PsiElement child = psiFile.getFirstChild();
@@ -492,7 +492,7 @@
final VirtualFile virtualFile = getVirtualFile();
if (virtualFile instanceof LightVirtualFile) {
Document doc = getCachedDocument();
- if (doc != null) return doc.getCharsSequence();
+ if (doc != null) return getLastCommittedText(doc);
return ((LightVirtualFile)virtualFile).getContent();
}
@@ -501,7 +501,7 @@
return LoadTextUtil.loadText(virtualFile);
}
else {
- return document.getCharsSequence();
+ return getLastCommittedText(document);
}
}
@@ -517,6 +517,10 @@
}
}
+ private CharSequence getLastCommittedText(Document document) {
+ return PsiDocumentManager.getInstance(myManager.getProject()).getLastCommittedText(document);
+ }
+
private class DocumentContent implements Content {
@NonNls
@Override
@@ -530,12 +534,12 @@
public CharSequence getText() {
final Document document = getDocument();
assert document != null;
- return document.getCharsSequence();
+ return getLastCommittedText(document);
}
@Override
public long getModificationStamp() {
- Document document = myDocument == null ? null : myDocument.get();
+ Document document = com.intellij.reference.SoftReference.dereference(myDocument);
if (document != null) return document.getModificationStamp();
return myVirtualFile.getModificationStamp();
}
diff --git a/platform/core-impl/src/com/intellij/psi/css/MinifiedFilesUtil.java b/platform/core-impl/src/com/intellij/psi/css/MinifiedFilesUtil.java
index b1a8491..c641a91 100644
--- a/platform/core-impl/src/com/intellij/psi/css/MinifiedFilesUtil.java
+++ b/platform/core-impl/src/com/intellij/psi/css/MinifiedFilesUtil.java
@@ -1,16 +1,28 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.css;
import com.intellij.lang.ParserDefinition;
import com.intellij.lexer.Lexer;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
-
-/**
- * User: zolotov
- * Date: 2/19/13
- */
+import org.jetbrains.annotations.NotNull;
public class MinifiedFilesUtil {
+
private MinifiedFilesUtil() {
}
@@ -21,18 +33,39 @@
private static final int MIN_LINE_LENGTH = 100; // if there's compact line that is long enough, file is considered to be minified
private static final double MAX_UNNEEDED_OFFSET_PERCENTAGE = 0.01;
+
+ private static final int COUNT_OF_CONSIDERING_CHARACTERS_FROM_END_OF_FILE = 400;
/**
* Finds out whether the file minified by using common (not language-specific) heuristics.
* Can be used for checking of css/less/scss/sass and js files.
*
- * @param lexer Lexer started on content of target file
+ * @param fileContent target file content
* @param parserDefinition Parser definition of target language
* @param noWSRequireAfterTokenSet TokenSet of types that doesn't require whitespaces after them.
*/
- public static boolean isMinified(Lexer lexer,
- ParserDefinition parserDefinition,
- TokenSet noWSRequireAfterTokenSet) {
+ public static boolean isMinified(@NotNull CharSequence fileContent,
+ @NotNull ParserDefinition parserDefinition,
+ @NotNull TokenSet noWSRequireAfterTokenSet) {
+ Lexer lexer = parserDefinition.createLexer(null);
+ lexer.start(fileContent);
+ if (!isMinified(lexer, parserDefinition, noWSRequireAfterTokenSet)) {
+ return false;
+ }
+ else if (lexer.getTokenType() == null) {
+ // whole file had been considered
+ return true;
+ }
+
+ int startOffset = fileContent.length() - COUNT_OF_CONSIDERING_CHARACTERS_FROM_END_OF_FILE;
+ if (startOffset <= 0) {
+ return true;
+ }
+ lexer.start(fileContent, startOffset, fileContent.length());
+ return isMinified(lexer, parserDefinition, noWSRequireAfterTokenSet);
+ }
+
+ protected static boolean isMinified(Lexer lexer, ParserDefinition parserDefinition, TokenSet noWSRequireAfterTokenSet) {
int offsetIgnoringComments = 0;
int offsetIgnoringCommentsAndStrings = 0;
int lineLength = 0;
@@ -58,7 +91,13 @@
if (whitespaceTokens.contains(tokenType)) {
if (!commentTokens.contains(lastTokenType) && tokenLength > 1) {
- return false;
+ lexer.advance();
+ if (lexer.getTokenType() == null) {
+ // it was last token
+ break;
+ } else {
+ return false;
+ }
}
if (lexer.getTokenText().contains("\n")) {
@@ -82,10 +121,11 @@
lastTokenType = tokenType;
}
- return offsetIgnoringComments >= MIN_SIZE && (unneededWhitespaceCount + 0.0d) / offsetIgnoringCommentsAndStrings < MAX_UNNEEDED_OFFSET_PERCENTAGE;
+ return offsetIgnoringComments >= MIN_SIZE &&
+ (unneededWhitespaceCount + 0.0d) / offsetIgnoringCommentsAndStrings < MAX_UNNEEDED_OFFSET_PERCENTAGE;
}
- public static boolean isMinified(Lexer lexer, ParserDefinition parserDefinition) {
- return isMinified(lexer, parserDefinition, TokenSet.EMPTY);
+ public static boolean isMinified(@NotNull CharSequence fileContent, @NotNull ParserDefinition parserDefinition) {
+ return isMinified(fileContent, parserDefinition, TokenSet.EMPTY);
}
}
diff --git a/platform/core-impl/src/com/intellij/psi/filters/ClassFilter.java b/platform/core-impl/src/com/intellij/psi/filters/ClassFilter.java
index 413020b..67134b4 100644
--- a/platform/core-impl/src/com/intellij/psi/filters/ClassFilter.java
+++ b/platform/core-impl/src/com/intellij/psi/filters/ClassFilter.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,7 +17,7 @@
package com.intellij.psi.filters;
import com.intellij.psi.PsiElement;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
/**
@@ -46,7 +46,7 @@
}
private boolean filterMatches(final Class hintClass) {
- return ReflectionCache.isAssignable(myFilter, hintClass);
+ return ReflectionUtil.isAssignable(myFilter, hintClass);
}
@Override
diff --git a/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java b/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java
index 6e3745b..2a65863 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/DebugUtil.java
@@ -22,17 +22,15 @@
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-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.util.text.StringUtil;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiInvalidElementAccessException;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.TokenType;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.CompositeElement;
-import com.intellij.psi.impl.source.tree.RecursiveTreeElementWalkingVisitor;
import com.intellij.psi.impl.source.tree.SharedImplUtil;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.stubs.ObjectStubSerializer;
@@ -515,50 +513,69 @@
}
}
- private static final Key<List<Pair<Object, Processor<PsiElement>>>> TRACK_INVALIDATION_KEY = Key.create("TRACK_INVALIDATION_KEY");
- private static volatile boolean ourTrackInvalidationCalled = false;
+ private static final ThreadLocal<Object> ourPsiModificationTrace = new ThreadLocal<Object>();
+ private static final ThreadLocal<Integer> ourPsiModificationDepth = new ThreadLocal<Integer>();
- public static void trackInvalidation(@NotNull PsiElement element, @NotNull Object requestor, @NotNull Processor<PsiElement> callback) {
- ourTrackInvalidationCalled = true;
- synchronized (element) {
- final ASTNode node = element.getNode();
- if (node == null) return;
- List<Pair<Object, Processor<PsiElement>>> callbacks = node.getUserData(TRACK_INVALIDATION_KEY);
- if (callbacks == null) {
- callbacks = new SmartList<Pair<Object, Processor<PsiElement>>>();
- node.putUserData(TRACK_INVALIDATION_KEY, callbacks);
- }
- for (int i = 0; i < callbacks.size(); i++) {
- Pair<Object, Processor<PsiElement>> pair = callbacks.get(i);
- Object callbackRequestor = pair.first;
- if (callbackRequestor.equals(requestor)) {
- callbacks.set(i, Pair.create(requestor, callback));
- return;
- }
- }
- callbacks.add(Pair.create(requestor, callback));
- }
- }
-
- public static void onInvalidated(@NotNull TreeElement treeElement) {
- if (!ourTrackInvalidationCalled) {
+ /**
+ * Marks a start of PSI modification action. Any PSI/AST elements invalidated inside such an action will contain a debug trace
+ * identifying this transaction, and so will {@link com.intellij.psi.PsiInvalidElementAccessException} thrown when accessing such invalid
+ * elements. This should help finding out why a specific PSI element has become invalid.
+ *
+ * @param trace The debug trace that the invalidated elements should be identified by. May be null, then current stack trace is used.
+ */
+ public static void startPsiModification(@Nullable String trace) {
+ if (!PsiInvalidElementAccessException.isTrackingInvalidation()) {
return;
}
- treeElement.acceptTree(new RecursiveTreeElementWalkingVisitor(false) {
- @Override
- protected void visitNode(TreeElement element) {
- List<Pair<Object, Processor<PsiElement>>> callbacks = element.getUserData(TRACK_INVALIDATION_KEY);
- if (callbacks != null) {
- for (Pair<Object, Processor<PsiElement>> pair : callbacks) {
- Processor<PsiElement> callback = pair.second;
- PsiElement psi = element.getPsi();
- if (psi != null) callback.process(psi);
- }
- }
- super.visitNode(element);
- }
- });
+ //noinspection ThrowableResultOfMethodCallIgnored
+ if (ourPsiModificationTrace.get() == null) {
+ ourPsiModificationTrace.set(trace != null ? trace : new Throwable());
+ }
+ Integer depth = ourPsiModificationDepth.get();
+ if (depth == null) depth = 0;
+ ourPsiModificationDepth.set(depth + 1);
+ }
+
+ /**
+ * Finished PSI modification action.
+ * @see #startPsiModification(String)
+ */
+ public static void finishPsiModification() {
+ if (!PsiInvalidElementAccessException.isTrackingInvalidation()) {
+ return;
+ }
+ Integer depth = ourPsiModificationDepth.get();
+ if (depth == null) {
+ LOG.warn("Unmatched PSI modification end", new Throwable());
+ depth = 0;
+ } else {
+ depth--;
+ ourPsiModificationDepth.set(depth);
+ }
+ if (depth == 0) {
+ ourPsiModificationTrace.set(null);
+ }
+ }
+
+ public static void onInvalidated(@NotNull ASTNode treeElement) {
+ if (!PsiInvalidElementAccessException.isTrackingInvalidation()) {
+ return;
+ }
+ if (PsiInvalidElementAccessException.findInvalidationTrace(treeElement) != null) {
+ return;
+ }
+
+ Object trace = ourPsiModificationTrace.get();
+ if (trace == null) {
+ trace = new Throwable();
+ LOG.info("PSI invalidated outside transaction", (Throwable)trace);
+ }
+ PsiInvalidElementAccessException.setInvalidationTrace(treeElement, trace);
+ }
+
+ public static void revalidateNode(@NotNull ASTNode element) {
+ PsiInvalidElementAccessException.setInvalidationTrace(element, null);
}
public static void sleep(long millis) {
diff --git a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java
index 809f27b..8e54370 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/DocumentCommitProcessor.java
@@ -16,6 +16,7 @@
package com.intellij.psi.impl;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.EmptyProgressIndicator;
@@ -76,7 +77,7 @@
@Override
public String toString() {
return "Project: " + project.getName()
- + ", Doc: "+ document +" ("+ StringUtil.first(document.getText(), 12, true).replaceAll("\n"," ")+")"
+ + ", Doc: "+ document +" ("+ StringUtil.first(document.getImmutableCharSequence(), 12, true).toString().replaceAll("\n", " ")+")"
+(indicator.isCanceled() ? " (Canceled)" : "") + (removed ? "Removed" : "");
}
@@ -103,11 +104,9 @@
@NotNull final PsiFile file,
final boolean synchronously) {
Document document = task.document;
- if (PsiDocumentManager.getInstance(task.project).isCommitted(document)) return null;
- final TextBlock textBlock = TextBlock.get(file);
final long startDocModificationTimeStamp = document.getModificationStamp();
final FileElement myTreeElementBeingReparsedSoItWontBeCollected = ((PsiFileImpl)file).calcTreeElement();
- final CharSequence chars = document.getCharsSequence();
+ final CharSequence chars = document.getImmutableCharSequence();
final Boolean data = document.getUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY);
if (data != null) {
document.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, null);
@@ -131,25 +130,21 @@
public boolean process(Document document) {
ApplicationManager.getApplication().assertWriteAccessAllowed();
log("Finishing", task, synchronously, document.getModificationStamp(), startDocModificationTimeStamp);
- if (document.getModificationStamp() != startDocModificationTimeStamp) {
+ if (document.getModificationStamp() != startDocModificationTimeStamp ||
+ ((PsiDocumentManagerBase)PsiDocumentManager.getInstance(file.getProject())).getCachedViewProvider(document) != file.getViewProvider()) {
return false; // optimistic locking failed
}
- try {
- CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(new Runnable() {
- @Override
- public void run() {
- synchronized (PsiLock.LOCK) {
- doActualPsiChange(file, diffLog);
- }
+ CodeStyleManager.getInstance(file.getProject()).performActionWithFormatterDisabled(new Runnable() {
+ @Override
+ public void run() {
+ synchronized (PsiLock.LOCK) {
+ doActualPsiChange(file, diffLog);
}
- });
+ }
+ });
- assertAfterCommit(document, file, oldPsiText, myTreeElementBeingReparsedSoItWontBeCollected);
- }
- finally {
- textBlock.clear();
- }
+ assertAfterCommit(document, file, oldPsiText, myTreeElementBeingReparsedSoItWontBeCollected);
return true;
}
@@ -198,18 +193,14 @@
FileElement myTreeElementBeingReparsedSoItWontBeCollected) {
if (myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() != document.getTextLength()) {
final String documentText = document.getText();
- if (ApplicationManager.getApplication().isInternal()) {
- String fileText = file.getText();
- LOG.error("commitDocument left PSI inconsistent; file len=" + myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() +
- "; doc len=" + document.getTextLength() +
- "; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText) +
- ";\n file psi text=" + fileText +
- ";\n doc text=" + documentText +
- ";\n old psi file text=" + oldPsiText);
- }
- else {
- LOG.error("commitDocument left PSI inconsistent: " + file);
- }
+ String fileText = file.getText();
+ LOG.error("commitDocument left PSI inconsistent: " + file +
+ "; file len=" + myTreeElementBeingReparsedSoItWontBeCollected.getTextLength() +
+ "; doc len=" + document.getTextLength() +
+ "; doc.getText() == file.getText(): " + Comparing.equal(fileText, documentText),
+ new Attachment("file psi text", fileText),
+ new Attachment("old text", documentText),
+ new Attachment("old psi file text", oldPsiText));
file.putUserData(BlockSupport.DO_NOT_REPARSE_INCREMENTALLY, Boolean.TRUE);
try {
@@ -234,7 +225,7 @@
}
}
- public void log(@NonNls String msg, CommitTask task, boolean synchronously, @NonNls Object... args) {
+ public void log(@NonNls String msg, @Nullable CommitTask task, boolean synchronously, @NonNls Object... args) {
}
@NotNull
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
index 8d7d9bb..7f7f9a9 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java
@@ -30,6 +30,7 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
@@ -37,15 +38,16 @@
import com.intellij.psi.*;
import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
+import com.intellij.psi.impl.source.text.BlockSupportImpl;
import com.intellij.psi.text.BlockSupport;
import com.intellij.util.FileContentUtilCore;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
import com.intellij.util.SystemProperties;
import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.containers.ConcurrentHashSet;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
-import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,19 +58,20 @@
public abstract class PsiDocumentManagerBase extends PsiDocumentManager implements ProjectComponent, DocumentListener {
protected static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiDocumentManagerImpl");
- protected static final Key<PsiFile> HARD_REF_TO_PSI = new Key<PsiFile>("HARD_REFERENCE_TO_PSI");
- protected static final Key<List<Runnable>> ACTION_AFTER_COMMIT = Key.create("ACTION_AFTER_COMMIT");
+ private static final Key<PsiFile> HARD_REF_TO_PSI = new Key<PsiFile>("HARD_REFERENCE_TO_PSI");
+ private static final Key<List<Runnable>> ACTION_AFTER_COMMIT = Key.create("ACTION_AFTER_COMMIT");
protected final Project myProject;
- protected final PsiManager myPsiManager;
- protected final DocumentCommitProcessor myDocumentCommitProcessor;
- protected final Set<Document> myUncommittedDocuments = Collections.synchronizedSet(new THashSet<Document>());
+ private final PsiManager myPsiManager;
+ private final DocumentCommitProcessor myDocumentCommitProcessor;
+ protected final Set<Document> myUncommittedDocuments = new ConcurrentHashSet<Document>();
+ private final Map<Document, CharSequence> myLastCommittedTexts = ContainerUtil.newConcurrentMap();
- protected volatile boolean myIsCommitInProgress;
- protected final PsiToDocumentSynchronizer mySynchronizer;
+ private volatile boolean myIsCommitInProgress;
+ private final PsiToDocumentSynchronizer mySynchronizer;
- protected final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- protected final SmartPointerManagerImpl mySmartPointerManager;
+ private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final SmartPointerManagerImpl mySmartPointerManager;
public PsiDocumentManagerBase(@NotNull final Project project,
@NotNull PsiManager psiManager,
@@ -152,7 +155,7 @@
}
@Nullable
- protected PsiFile getPsiFile(VirtualFile virtualFile) {
+ private PsiFile getPsiFile(VirtualFile virtualFile) {
return ((PsiManagerEx)myPsiManager).getFileManager().findFile(virtualFile);
}
@@ -243,7 +246,9 @@
}
if (myUncommittedDocuments.isEmpty()) {
action.run();
- assert actionsWhenAllDocumentsAreCommitted.isEmpty() : actionsWhenAllDocumentsAreCommitted;
+ if (!hasUncommitedDocuments()) {
+ assert actionsWhenAllDocumentsAreCommitted.isEmpty() : actionsWhenAllDocumentsAreCommitted;
+ }
return true;
}
actionsWhenAllDocumentsAreCommitted.put(key, action);
@@ -317,7 +322,10 @@
break;
}
}
+ myLastCommittedTexts.remove(document);
viewProvider.contentsSynchronized();
+ } else {
+ handleCommitWithoutPsi(document);
}
}
finally {
@@ -496,9 +504,14 @@
if (!hasUncommitedDocuments() && !actionsWhenAllDocumentsAreCommitted.isEmpty()) {
List<Object> keys = new ArrayList<Object>(actionsWhenAllDocumentsAreCommitted.keySet());
for (Object key : keys) {
- Runnable action = actionsWhenAllDocumentsAreCommitted.remove(key);
- myDocumentCommitProcessor.log("Running after commit runnable: ", null, false, key, action);
- action.run();
+ try {
+ Runnable action = actionsWhenAllDocumentsAreCommitted.remove(key);
+ myDocumentCommitProcessor.log("Running after commit runnable: ", null, false, key, action);
+ action.run();
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
}
}
}
@@ -536,6 +549,13 @@
@Override
@NotNull
+ public CharSequence getLastCommittedText(@NotNull Document document) {
+ CharSequence text = myLastCommittedTexts.get(document);
+ return text != null ? text : document.getImmutableCharSequence();
+ }
+
+ @Override
+ @NotNull
public Document[] getUncommittedDocuments() {
ApplicationManager.getApplication().assertIsDispatchThread();
return myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]);
@@ -566,6 +586,9 @@
@Override
public void beforeDocumentChange(DocumentEvent event) {
final Document document = event.getDocument();
+ if (!(document instanceof DocumentWindow) && !myLastCommittedTexts.containsKey(document)) {
+ myLastCommittedTexts.put(document, document.getImmutableCharSequence());
+ }
final FileViewProvider viewProvider = getCachedViewProvider(document);
if (viewProvider == null) return;
@@ -582,7 +605,7 @@
}
mySmartPointerManager.fastenBelts(file, event.getOffset(), null);
- if (TextBlock.get(file).isLocked()) {
+ if (mySynchronizer.isInsideAtomicChange(file)) {
psiCause = file;
}
}
@@ -601,8 +624,14 @@
public void documentChanged(DocumentEvent event) {
final Document document = event.getDocument();
final FileViewProvider viewProvider = getCachedViewProvider(document);
- if (viewProvider == null) return;
- if (!isRelevant(viewProvider)) return;
+ if (viewProvider == null) {
+ handleCommitWithoutPsi(document);
+ return;
+ }
+ if (!isRelevant(viewProvider)) {
+ myLastCommittedTexts.remove(document);
+ return;
+ }
ApplicationManager.getApplication().assertWriteAccessAllowed();
final List<PsiFile> files = viewProvider.getAllFiles();
@@ -610,13 +639,11 @@
for (PsiFile file : files) {
mySmartPointerManager.unfastenBelts(file, event.getOffset());
- final TextBlock textBlock = TextBlock.get(file);
- if (textBlock.isLocked()) {
+ if (mySynchronizer.isInsideAtomicChange(file)) {
commitNecessary = false;
continue;
}
- textBlock.documentChanged(event);
assert file instanceof PsiFileImpl || "mock.file".equals(file.getName()) && ApplicationManager.getApplication().isUnitTestMode() :
event +
"; file=" +
@@ -642,15 +669,56 @@
if (commitNecessary) {
assert !(document instanceof DocumentWindow);
myUncommittedDocuments.add(document);
+ myDocumentCommitProcessor.log("added uncommitted doc", null, false, myProject, document, ((DocumentEx)document).isInBulkUpdate());
if (forceCommit) {
commitDocument(document);
}
else if (!((DocumentEx)document).isInBulkUpdate()) {
myDocumentCommitProcessor.commitAsynchronously(myProject, document, event);
}
+ } else {
+ myLastCommittedTexts.remove(document);
}
}
+ public void handleCommitWithoutPsi(final Document document) {
+ final CharSequence prevText = myLastCommittedTexts.remove(document);
+ if (prevText == null) {
+ return;
+ }
+
+ if (!myProject.isInitialized() || myProject.isDisposed()) {
+ return;
+ }
+
+ VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
+ if (virtualFile == null || !FileIndexFacade.getInstance(myProject).isInContent(virtualFile)) {
+ return;
+ }
+
+ final PsiFileImpl psiFile = (PsiFileImpl)getPsiFile(document);
+ if (psiFile == null) {
+ return;
+ }
+
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ psiFile.getViewProvider().beforeContentsSynchronized();
+ synchronized (PsiLock.LOCK) {
+ final int oldLength = prevText.length();
+ PsiManagerImpl manager = (PsiManagerImpl)psiFile.getManager();
+ BlockSupportImpl.sendBeforeChildrenChangeEvent(manager, psiFile, true);
+ BlockSupportImpl.sendBeforeChildrenChangeEvent(manager, psiFile, false);
+ psiFile.onContentReload();
+ BlockSupportImpl.sendAfterChildrenChangedEvent(manager, psiFile, oldLength, false);
+ BlockSupportImpl.sendAfterChildrenChangedEvent(manager, psiFile, oldLength, true);
+ }
+ psiFile.getViewProvider().contentsSynchronized();
+ }
+ });
+
+ }
+
private boolean isRelevant(@NotNull FileViewProvider viewProvider) {
VirtualFile virtualFile = viewProvider.getVirtualFile();
return !virtualFile.getFileType().isBinary() &&
@@ -724,6 +792,7 @@
@TestOnly
public void clearUncommittedDocuments() {
+ myLastCommittedTexts.clear();
myUncommittedDocuments.clear();
mySynchronizer.cleanupForNextTest();
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiElementBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiElementBase.java
index 79e6e76..f77adc5 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiElementBase.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiElementBase.java
@@ -1,6 +1,6 @@
/*
- * 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.
@@ -28,7 +28,6 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -289,7 +288,7 @@
protected <T> T[] findChildrenByClass(Class<T> aClass) {
List<T> result = new ArrayList<T>();
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, aClass)) result.add((T)cur);
+ if (aClass.isInstance(cur)) result.add((T)cur);
}
return result.toArray((T[]) Array.newInstance(aClass, result.size()));
}
@@ -297,7 +296,7 @@
@Nullable
protected <T> T findChildByClass(Class<T> aClass) {
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, aClass)) return (T)cur;
+ if (aClass.isInstance(cur)) return (T)cur;
}
return null;
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java
index 107f052..09a046c 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiManagerImpl.java
@@ -143,9 +143,15 @@
}
@TestOnly
- public void setAssertOnFileLoadingFilter(@NotNull VirtualFileFilter filter) {
+ public void setAssertOnFileLoadingFilter(@NotNull VirtualFileFilter filter, Disposable parentDisposable) {
// Find something to ensure there's no changed files waiting to be processed in repository indices.
myAssertOnFileLoadingFilter = filter;
+ Disposer.register(parentDisposable, new Disposable() {
+ @Override
+ public void dispose() {
+ myAssertOnFileLoadingFilter = VirtualFileFilter.NONE;
+ }
+ });
}
@Override
diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
index 05dc16f..c6c1d97 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/PsiToDocumentSynchronizer.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -35,6 +36,7 @@
public class PsiToDocumentSynchronizer extends PsiTreeChangeAdapter {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiToDocumentSynchronizer");
+ private static final Key<Boolean> PSI_DOCUMENT_ATOMIC_ACTION = Key.create("PSI_DOCUMENT_ATOMIC_ACTION");
private final PsiDocumentManagerBase myPsiDocumentManager;
private final MessageBus myBus;
@@ -67,24 +69,36 @@
void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event);
}
+ private void checkPsiModificationAllowed(@NotNull final PsiTreeChangeEvent event, boolean force) {
+ if (!toProcessPsiEvent()) return;
+ final PsiFile psiFile = event.getFile();
+ if (psiFile == null || psiFile.getNode() == null) return;
+
+ final Document document = getCachedDocument(psiFile, force);
+ if (document == null) return;
+
+ if (myPsiDocumentManager.isUncommited(document)) {
+ throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
+ }
+ }
+
+ private DocumentEx getCachedDocument(PsiFile psiFile, boolean force) {
+ final DocumentEx document = (DocumentEx)myPsiDocumentManager.getCachedDocument(psiFile);
+ if (document == null || document instanceof DocumentWindow || !force && getTransaction(document) == null) {
+ return null;
+ }
+ return document;
+ }
+
private void doSync(@NotNull final PsiTreeChangeEvent event, boolean force, @NotNull final DocSyncAction syncAction) {
if (!toProcessPsiEvent()) return;
final PsiFile psiFile = event.getFile();
if (psiFile == null || psiFile.getNode() == null) return;
- final DocumentEx document = (DocumentEx)myPsiDocumentManager.getCachedDocument(psiFile);
- if (document == null || document instanceof DocumentWindow) return;
- if (!force && getTransaction(document) == null) {
- return;
- }
+ final DocumentEx document = getCachedDocument(psiFile, force);
+ if (document == null) return;
- TextBlock textBlock = TextBlock.get(psiFile);
-
- if (!textBlock.isEmpty()) {
- throw new IllegalStateException("Attempt to modify PSI for non-committed Document!");
- }
-
- textBlock.performAtomically(new Runnable() {
+ performAtomically(psiFile, new Runnable() {
@Override
public void run() {
syncAction.syncDocument(document, (PsiTreeChangeEventImpl)event);
@@ -102,6 +116,42 @@
psiFile.getViewProvider().contentsSynchronized();
}
+ boolean isInsideAtomicChange(@NotNull PsiFile file) {
+ return file.getUserData(PSI_DOCUMENT_ATOMIC_ACTION) == Boolean.TRUE;
+ }
+
+ public void performAtomically(@NotNull PsiFile file, @NotNull Runnable runnable) {
+ assert !isInsideAtomicChange(file);
+ file.putUserData(PSI_DOCUMENT_ATOMIC_ACTION, Boolean.TRUE);
+
+ try {
+ runnable.run();
+ }
+ finally {
+ file.putUserData(PSI_DOCUMENT_ATOMIC_ACTION, null);
+ }
+ }
+
+ @Override
+ public void beforeChildAddition(@NotNull PsiTreeChangeEvent event) {
+ checkPsiModificationAllowed(event, false);
+ }
+
+ @Override
+ public void beforeChildRemoval(@NotNull PsiTreeChangeEvent event) {
+ checkPsiModificationAllowed(event, false);
+ }
+
+ @Override
+ public void beforeChildReplacement(@NotNull PsiTreeChangeEvent event) {
+ checkPsiModificationAllowed(event, false);
+ }
+
+ @Override
+ public void beforeChildrenChange(@NotNull PsiTreeChangeEvent event) {
+ checkPsiModificationAllowed(event, false);
+ }
+
@Override
public void childAdded(@NotNull final PsiTreeChangeEvent event) {
if (!(event.getChild() instanceof ForeignLeafPsiElement)) {
@@ -207,6 +257,7 @@
final PsiTreeChangeEventImpl fakeEvent = new PsiTreeChangeEventImpl(changeScope.getManager());
fakeEvent.setParent(changeScope);
fakeEvent.setFile(changeScope.getContainingFile());
+ checkPsiModificationAllowed(fakeEvent, true);
doSync(fakeEvent, true, new DocSyncAction() {
@Override
public void syncDocument(@NotNull Document document, @NotNull PsiTreeChangeEventImpl event) {
diff --git a/platform/core-impl/src/com/intellij/psi/impl/TextBlock.java b/platform/core-impl/src/com/intellij/psi/impl/TextBlock.java
deleted file mode 100644
index 65cf98f..0000000
--- a/platform/core-impl/src/com/intellij/psi/impl/TextBlock.java
+++ /dev/null
@@ -1,124 +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.psi.impl;
-
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.UserDataHolderEx;
-import com.intellij.psi.PsiFile;
-import org.jetbrains.annotations.NotNull;
-
-public class TextBlock {
- private static final Key<TextBlock> KEY_TEXT_BLOCK = Key.create("KEY_TEXT_BLOCK");
- @SuppressWarnings({"UnusedDeclaration"})
- private Document myDocument; // Will hold a document on a hard reference until there's uncommitted PSI for this document.
-
- private int myStartOffset = -1;
- private int myTextEndOffset = -1;
- private int myPsiEndOffset = -1;
- private boolean myIsLocked = false;
-
- public boolean isEmpty() {
- return myStartOffset == -1;
- }
-
- public void clear() {
- myStartOffset = -1;
- myDocument = null;
- }
-
- public int getStartOffset() {
- return myStartOffset;
- }
-
- public int getTextEndOffset() {
- return myTextEndOffset;
- }
-
- private void lock() {
- myIsLocked = true;
- }
-
- private void unlock() {
- myIsLocked = false;
- }
-
- public boolean isLocked() {
- return myIsLocked;
- }
-
- public int getPsiEndOffset() {
- return myPsiEndOffset;
- }
-
- public void documentChanged(DocumentEvent e) {
- myDocument = e.getDocument();
-
- assert !myIsLocked;
-
- final int offset = e.getOffset();
- if (isEmpty()) {
- myStartOffset = offset;
- myTextEndOffset = offset + e.getNewLength();
- myPsiEndOffset = offset + e.getOldLength();
- }
- else {
- int shift = offset + e.getOldLength() - myTextEndOffset;
- if (shift > 0) {
- myPsiEndOffset += shift;
- myTextEndOffset = offset + e.getNewLength();
- }
- else {
- myTextEndOffset += e.getNewLength() - e.getOldLength();
- }
-
- myStartOffset = Math.min(myStartOffset, offset);
- }
- }
-
- public void performAtomically(@NotNull Runnable runnable) {
- assert !isLocked();
- lock();
- try {
- runnable.run();
- }
- finally {
- unlock();
- }
- }
-
- @NotNull
- public static TextBlock get(@NotNull PsiFile file) {
- TextBlock textBlock = file.getUserData(KEY_TEXT_BLOCK);
- if (textBlock == null){
- textBlock = ((UserDataHolderEx)file).putUserDataIfAbsent(KEY_TEXT_BLOCK, new TextBlock());
- }
-
- return textBlock;
- }
-
- @Override
- public String toString() {
- return "TextBlock{" +
- "myStartOffset=" + myStartOffset +
- ", myTextEndOffset=" + myTextEndOffset +
- ", myPsiEndOffset=" + myPsiEndOffset +
- ", myIsLocked=" + myIsLocked +
- '}';
- }
-}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/cache/CacheUtil.java b/platform/core-impl/src/com/intellij/psi/impl/cache/CacheUtil.java
index d4c0e91..ed7ba4d 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/cache/CacheUtil.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/cache/CacheUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,6 +29,7 @@
import com.intellij.psi.impl.PsiFileEx;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -38,7 +39,7 @@
private CacheUtil() {
}
- public static boolean isCopy(PsiFile psiFile) {
+ public static boolean isCopy(@NotNull PsiFile psiFile) {
return psiFile.getUserData(CACHE_COPY_KEY) != null;
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java
index f61cab6..5ea2cdb 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SelfElementInfo.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.
@@ -62,14 +62,14 @@
myProject = project;
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
- Document document = documentManager.getDocument(containingFile);
- if (document == null || documentManager.isUncommited(document)) {
+ Document document = documentManager.getCachedDocument(containingFile);
+ if (document != null && documentManager.isUncommited(document)) {
mySyncMarkerIsValid = false;
- return;
}
-
- mySyncMarkerIsValid = true;
- setRange(range);
+ else {
+ mySyncMarkerIsValid = true;
+ setRange(range);
+ }
}
protected void setRange(@NotNull Segment range) {
@@ -193,8 +193,7 @@
}
private RangeMarker getMarker() {
- Reference<RangeMarker> ref = myMarkerRef;
- return ref == null ? null : ref.get();
+ return com.intellij.reference.SoftReference.dereference(myMarkerRef);
}
@Override
diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java
index d1cb392..8476372 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPointerManagerImpl.java
@@ -139,7 +139,7 @@
private static <E extends PsiElement> SmartPointerEx<E> getCachedPointer(@NotNull E element) {
Reference<SmartPointerEx> data = element.getUserData(CACHED_SMART_POINTER_KEY);
- SmartPointerEx cachedPointer = data == null ? null : data.get();
+ SmartPointerEx cachedPointer = SoftReference.dereference(data);
if (cachedPointer != null) {
PsiElement cachedElement = cachedPointer.getCachedElement();
if (cachedElement != null && cachedElement != element) {
@@ -208,7 +208,7 @@
public int getPointersNumber(@NotNull PsiFile containingFile) {
synchronized (lock) {
List<SmartPointerEx> pointers = getPointers(containingFile);
- return pointers == null ? 0 : pointers.size();
+ return pointers == null ? 0 : ((UnsafeWeakList)pointers).toStrongList().size();
}
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java
index bf6d1a5..7c66ef4 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/smartPointers/SmartPsiElementPointerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -93,8 +93,7 @@
@Override
public E getCachedElement() {
- Reference<E> ref = myElement;
- return ref == null ? null : ref.get();
+ return com.intellij.reference.SoftReference.dereference(myElement);
}
@Override
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java
index 6b10354..179d344 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/CharTableImpl.java
@@ -34,7 +34,7 @@
*/
public class CharTableImpl implements CharTable {
private static final int INTERN_THRESHOLD = 40; // 40 or more characters long tokens won't be interned.
- private static final CharSequenceHashingStrategy HASHER = new CharSequenceHashingStrategy();
+ private static final CharSequenceHashingStrategy HASHER = CharSequenceHashingStrategy.CASE_SENSITIVE;
private static final OpenTHashSet<CharSequence> STATIC_ENTRIES = newStaticSet();
private final OpenTHashSet<CharSequence> entries = new OpenTHashSet<CharSequence>(10, 0.9f, HASHER);
@@ -72,15 +72,17 @@
@NotNull
@Override
public CharSequence intern(@NotNull final CharSequence baseText, final int startOffset, final int endOffset) {
- if (endOffset - startOffset == baseText.length()) return baseText;
+ if (endOffset - startOffset == baseText.length()) return intern(baseText);
return intern(new CharSequenceSubSequence(baseText, startOffset, endOffset));
}
@NotNull
private static String createSequence(@NotNull CharSequence text) {
+ if (text instanceof String) {
+ return (String)text;
+ }
char[] buf = new char[text.length()];
CharArrayUtil.getChars(text, buf, 0);
-
return StringFactory.createShared(buf); // this way the .toString() doesn't create another instance (as opposed to new CharArrayCharSequence())
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java
index 621ba27..5d73c0d 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/PsiFileImpl.java
@@ -393,8 +393,7 @@
}
private void clearStub(@NotNull String reason) {
- SoftReference<StubTree> stubRef = myStub;
- StubTree stubHolder = stubRef == null ? null : stubRef.get();
+ StubTree stubHolder = SoftReference.dereference(myStub);
if (stubHolder != null) {
((PsiFileStubImpl<?>)stubHolder.getRoot()).clearPsi(reason);
}
@@ -617,7 +616,7 @@
@Override
@NotNull
public char[] textToCharArray() {
- return CharArrayUtil.fromSequenceStrict(getViewProvider().getContents());
+ return CharArrayUtil.fromSequence(getViewProvider().getContents());
}
@NotNull
@@ -730,7 +729,7 @@
if (myStub == null) return null;
synchronized (PsiLock.LOCK) {
- return myStub != null ? myStub.get() : null;
+ return SoftReference.dereference(myStub);
}
}
@@ -954,6 +953,8 @@
@Override
public void navigate(boolean requestFocus) {
+ assert canNavigate() : this;
+ //noinspection ConstantConditions
PsiNavigationSupport.getInstance().getDescriptor(this).navigate(requestFocus);
}
@@ -993,18 +994,20 @@
FileElement fileElement = calcTreeElement();
synchronized (myStubFromTreeLock) {
SoftReference<StubTree> ref = fileElement.getUserData(STUB_TREE_IN_PARSED_TREE);
- StubTree tree = ref == null ? null : ref.get();
+ StubTree tree = SoftReference.dereference(ref);
if (tree == null) {
ApplicationManager.getApplication().assertReadAccessAllowed();
IElementType contentElementType = getContentElementType();
if (!(contentElementType instanceof IStubFileElementType)) {
VirtualFile vFile = getVirtualFile();
- throw new AssertionError("ContentElementType: " + contentElementType + "; file: " + this +
- "\n\t" + "Boolean.TRUE.equals(getUserData(BUILDING_STUB)) = " + Boolean.TRUE.equals(getUserData(BUILDING_STUB)) +
- "\n\t" + "getTreeElement() = " + getTreeElement() +
- "\n\t" + "vFile instanceof VirtualFileWithId = " + (vFile instanceof VirtualFileWithId) +
- "\n\t" + "StubUpdatingIndex.canHaveStub(vFile) = " + StubTreeLoader.getInstance().canHaveStub(vFile));
+ String message = "ContentElementType: " + contentElementType + "; file: " + this +
+ "\n\t" + "Boolean.TRUE.equals(getUserData(BUILDING_STUB)) = " + Boolean.TRUE.equals(getUserData(BUILDING_STUB)) +
+ "\n\t" + "getTreeElement() = " + getTreeElement() +
+ "\n\t" + "vFile instanceof VirtualFileWithId = " + (vFile instanceof VirtualFileWithId) +
+ "\n\t" + "StubUpdatingIndex.canHaveStub(vFile) = " + StubTreeLoader.getInstance().canHaveStub(vFile);
+ rebuildStub();
+ throw new AssertionError(message);
}
StubElement currentStubTree = ((IStubFileElementType)contentElementType).getBuilder().buildStubTree(this);
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java
index 1452ed0..b507041 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/text/BlockSupportImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -106,11 +106,13 @@
if (baseLanguage.isKindOf(reparseable.getLanguage())) {
final int start = textRange.getStartOffset();
final int end = start + textRange.getLength() + lengthShift;
- assertFileLength(file, newFileText, node, elementType, start, end);
+ if (!assertFileLength(file, newFileText, node, elementType, start, end)) {
+ break;
+ }
CharSequence newTextStr = newFileText.subSequence(start, end);
- if (reparseable.isParsable(newTextStr, baseLanguage, project)) {
+ if (reparseable.isParsable(node.getTreeParent(), newTextStr, baseLanguage, project)) {
ASTNode chameleon = reparseable.createNode(newTextStr);
if (chameleon != null) {
DummyHolder holder = DummyHolderFactory.createHolder(fileImpl.getManager(), null, node.getPsi(), charTable);
@@ -134,11 +136,13 @@
return makeFullParse(node, newFileText, textLength, fileImpl, indicator);
}
- private static void assertFileLength(PsiFile file, CharSequence newFileText, ASTNode node, IElementType elementType, int start, int end) {
- if (end > newFileText.length() && ApplicationManager.getApplication().isInternal()) {
+ private static boolean assertFileLength(PsiFile file, CharSequence newFileText, ASTNode node, IElementType elementType, int start, int end) {
+ if ((end > newFileText.length() || start > end) && ApplicationManager.getApplication().isInternal()) {
String newTextBefore = newFileText.subSequence(0, start).toString();
String oldTextBefore = file.getText().subSequence(0, start).toString();
String message = "IOOBE: type=" + elementType +
+ "; start=" + start +
+ "; end=" + end +
"; oldText=" + node.getText() +
"; newText=" + newFileText.subSequence(start, newFileText.length()) +
"; length=" + node.getTextLength();
@@ -148,8 +152,10 @@
message += "; oldTextBefore=" + oldTextBefore +
"; newTextBefore=" + newTextBefore;
}
- throw new AssertionError(message);
+ LOG.error(message);
+ return false;
}
+ return true;
}
@NotNull
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/ChangeUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/ChangeUtil.java
index de5a817..5ecc9a9 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/ChangeUtil.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/ChangeUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,12 +29,13 @@
import com.intellij.pom.tree.events.impl.TreeChangeEventImpl;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.impl.source.DummyHolderFactory;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.codeStyle.CodeEditUtil;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.CharTable;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,7 +52,13 @@
}
private static void encodeInformation(TreeElement element, ASTNode original) {
- encodeInformation(element, original, new HashMap<Object, Object>());
+ DebugUtil.startPsiModification("encodeInformation");
+ try {
+ encodeInformation(element, original, new HashMap<Object, Object>());
+ }
+ finally {
+ DebugUtil.finishPsiModification();
+ }
}
private static void encodeInformation(TreeElement element, ASTNode original, Map<Object, Object> state) {
@@ -71,7 +78,13 @@
}
public static TreeElement decodeInformation(TreeElement element) {
- return decodeInformation(element, new HashMap<Object, Object>());
+ DebugUtil.startPsiModification("decodeInformation");
+ try {
+ return decodeInformation(element, new HashMap<Object, Object>());
+ }
+ finally {
+ DebugUtil.finishPsiModification();
+ }
}
private static TreeElement decodeInformation(TreeElement element, Map<Object, Object> state) {
@@ -135,7 +148,7 @@
@Nullable
public static TreeElement generateTreeElement(PsiElement original, CharTable table, final PsiManager manager) {
- LOG.assertTrue(original.isValid());
+ PsiUtilCore.ensureValid(original);
if (SourceTreeToPsiMap.hasTreeElement(original)) {
return copyElement((TreeElement)SourceTreeToPsiMap.psiElementToTree(original), table);
}
@@ -152,27 +165,22 @@
final FileElement changedFile = TreeUtil.getFileElement(changedElement);
final PsiManager manager = changedFile.getManager();
final PomModel model = PomManager.getModel(manager.getProject());
- try{
- final TreeAspect treeAspect = model.getModelAspect(TreeAspect.class);
- model.runTransaction(new PomTransactionBase(changedElement.getPsi(), treeAspect) {
- @Override
- public PomModelEvent runInner() {
- final PomModelEvent event = new PomModelEvent(model);
- final TreeChangeEvent destinationTreeChange = new TreeChangeEventImpl(treeAspect, changedFile);
- event.registerChangeSet(treeAspect, destinationTreeChange);
- action.makeChange(destinationTreeChange);
+ final TreeAspect treeAspect = model.getModelAspect(TreeAspect.class);
+ model.runTransaction(new PomTransactionBase(changedElement.getPsi(), treeAspect) {
+ @Override
+ public PomModelEvent runInner() {
+ final PomModelEvent event = new PomModelEvent(model);
+ final TreeChangeEvent destinationTreeChange = new TreeChangeEventImpl(treeAspect, changedFile);
+ event.registerChangeSet(treeAspect, destinationTreeChange);
+ action.makeChange(destinationTreeChange);
- TreeUtil.clearCaches(changedElement);
- if (changedElement instanceof CompositeElement) {
- ((CompositeElement) changedElement).subtreeChanged();
- }
- return event;
+ TreeUtil.clearCaches(changedElement);
+ if (changedElement instanceof CompositeElement) {
+ ((CompositeElement) changedElement).subtreeChanged();
}
- });
- }
- catch(IncorrectOperationException ioe){
- LOG.error(ioe);
- }
+ return event;
+ }
+ });
}
public interface ChangeAction{
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java
index aed99e5..f00c152 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/CompositeElement.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.
@@ -577,7 +577,8 @@
return myCachedLength;
}
- private static TreeElement drillDown(TreeElement start) {
+ @NotNull
+ private static TreeElement drillDown(@NotNull TreeElement start) {
TreeElement cur = start;
while (cur.getCachedLength() < 0) {
TreeElement child = cur.getFirstChildNode();
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java
index a09ab19..ebc699a 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseableElement.java
@@ -23,9 +23,11 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.ILazyParseableElementType;
import com.intellij.util.text.CharArrayUtil;
+import com.intellij.util.text.ImmutableCharSequence;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,16 +49,18 @@
// Lock which protects expanding chameleon for this node.
// Under no circumstances should you grab the PSI_LOCK while holding this lock.
private final ChameleonLock lock = new ChameleonLock();
- private CharSequence myText; /** guarded by {@link #lock} */
+ /** guarded by {@link #lock} */
+ private CharSequence myText;
+
private static final ThreadLocal<Boolean> ourSuppressEagerPsiCreation = new ThreadLocal<Boolean>();
- public LazyParseableElement(@NotNull IElementType type, CharSequence text) {
+ public LazyParseableElement(@NotNull IElementType type, @Nullable CharSequence text) {
super(type);
- synchronized (lock) {
- myText = text == null ? null : text.toString();
- if (text != null) {
- setCachedLength(text.length());
+ if (text != null) {
+ synchronized (lock) {
+ myText = ImmutableCharSequence.asImmutable(text);
}
+ setCachedLength(text.length());
}
}
@@ -162,24 +166,30 @@
ApplicationManager.getApplication().assertReadAccessAllowed();
- ILazyParseableElementType type = (ILazyParseableElementType)getElementType();
- ASTNode parsedNode = type.parseContents(this);
+ DebugUtil.startPsiModification("lazy-parsing");
+ try {
+ ILazyParseableElementType type = (ILazyParseableElementType)getElementType();
+ ASTNode parsedNode = type.parseContents(this);
- if (parsedNode == null && text.length() > 0) {
- CharSequence diagText = ApplicationManager.getApplication().isInternal() ? text : "";
- LOG.error("No parse for a non-empty string: " + diagText + "; type=" + LogUtil.objectAndClass(type));
- }
-
- synchronized (lock) {
- if (myText == null) return;
- if (rawFirstChild() != null) {
- LOG.error("Reentrant parsing?");
+ if (parsedNode == null && text.length() > 0) {
+ CharSequence diagText = ApplicationManager.getApplication().isInternal() ? text : "";
+ LOG.error("No parse for a non-empty string: " + diagText + "; type=" + LogUtil.objectAndClass(type));
}
- myText = null;
-
- if (parsedNode == null) return;
- super.rawAddChildrenWithoutNotifications((TreeElement)parsedNode);
+ synchronized (lock) {
+ if (myText == null) return;
+ if (rawFirstChild() != null) {
+ LOG.error("Reentrant parsing?");
+ }
+
+ myText = null;
+
+ if (parsedNode == null) return;
+ super.rawAddChildrenWithoutNotifications((TreeElement)parsedNode);
+ }
+ }
+ finally {
+ DebugUtil.finishPsiModification();
}
if (!Boolean.TRUE.equals(ourSuppressEagerPsiCreation.get())) {
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java
index 3678d8a..befc231 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LazyParseablePsiElement.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,7 +38,6 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -70,7 +69,7 @@
@Nullable
protected <T> T findChildByClass(Class<T> aClass) {
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, aClass)) return (T)cur;
+ if (aClass.isInstance(cur)) return (T)cur;
}
return null;
}
@@ -79,7 +78,7 @@
protected <T> T[] findChildrenByClass(Class<T> aClass) {
List<T> result = new ArrayList<T>();
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, aClass)) result.add((T)cur);
+ if (aClass.isInstance(cur)) result.add((T)cur);
}
return result.toArray((T[])Array.newInstance(aClass, result.size()));
}
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LeafElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LeafElement.java
index cfc1860..e33bcb4 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/LeafElement.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/LeafElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -234,42 +234,42 @@
@Override
public void addChild(@NotNull ASTNode child, ASTNode anchorBefore) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void addLeaf(@NotNull final IElementType leafType, final CharSequence leafText, final ASTNode anchorBefore) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void addChild(@NotNull ASTNode child) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void removeChild(@NotNull ASTNode child) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void replaceChild(@NotNull ASTNode oldChild, @NotNull ASTNode newChild) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void replaceAllChildrenToChildrenOf(ASTNode anotherParent) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void removeRange(@NotNull ASTNode first, ASTNode firstWhichStayInTree) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
public void addChildren(ASTNode firstChild, ASTNode lastChild, ASTNode anchorBefore) {
- throw new RuntimeException(new IncorrectOperationException("Leaf elements cannot have children."));
+ throw new IncorrectOperationException("Leaf elements cannot have children.");
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/OwnBufferLeafPsiElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/OwnBufferLeafPsiElement.java
similarity index 100%
rename from platform/lang-impl/src/com/intellij/psi/impl/source/tree/OwnBufferLeafPsiElement.java
rename to platform/core-impl/src/com/intellij/psi/impl/source/tree/OwnBufferLeafPsiElement.java
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PlainTextASTFactory.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/PlainTextASTFactory.java
similarity index 100%
rename from platform/lang-impl/src/com/intellij/psi/impl/source/tree/PlainTextASTFactory.java
rename to platform/core-impl/src/com/intellij/psi/impl/source/tree/PlainTextASTFactory.java
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiPlainTextImpl.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/PsiPlainTextImpl.java
similarity index 100%
rename from platform/lang-impl/src/com/intellij/psi/impl/source/tree/PsiPlainTextImpl.java
rename to platform/core-impl/src/com/intellij/psi/impl/source/tree/PsiPlainTextImpl.java
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java
index 298a711..fde4f52 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeElement.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLock;
+import com.intellij.psi.TokenType;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.ElementBase;
import com.intellij.psi.impl.PsiManagerEx;
@@ -176,6 +177,9 @@
final void setTreeParent(CompositeElement parent) {
myParent = parent;
+ if (parent != null && parent.getElementType() != TokenType.DUMMY_HOLDER) {
+ DebugUtil.revalidateNode(this);
+ }
}
final void setTreePrev(TreeElement prev) {
@@ -316,11 +320,10 @@
parent.subtreeChanged();
}
- // invalidate replaced element
+ onInvalidated();
setTreeNext(null);
setTreePrev(null);
setTreeParent(null);
- onInvalidated();
}
public void rawRemoveUpToLast() {
diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java
index b247f87..7e11599 100644
--- a/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java
+++ b/platform/core-impl/src/com/intellij/psi/impl/source/tree/TreeUtil.java
@@ -26,7 +26,10 @@
import com.intellij.psi.StubBuilder;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.PsiFileImpl;
-import com.intellij.psi.stubs.*;
+import com.intellij.psi.stubs.IStubElementType;
+import com.intellij.psi.stubs.StubBase;
+import com.intellij.psi.stubs.StubElement;
+import com.intellij.psi.stubs.StubTree;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.IStrongWhitespaceHolderElementType;
import com.intellij.psi.tree.IStubFileElementType;
@@ -180,6 +183,16 @@
}
@Nullable
+ public static ASTNode findSibling(ASTNode start, TokenSet types) {
+ ASTNode child = start;
+ while (true) {
+ if (child == null) return null;
+ if (types.contains(child.getElementType())) return child;
+ child = child.getTreeNext();
+ }
+ }
+
+ @Nullable
public static ASTNode findSiblingBackward(ASTNode start, IElementType elementType) {
ASTNode child = start;
while (true) {
@@ -189,6 +202,17 @@
}
}
+
+ @Nullable
+ public static ASTNode findSiblingBackward(ASTNode start, TokenSet types) {
+ ASTNode child = start;
+ while (true) {
+ if (child == null) return null;
+ if (types.contains(child.getElementType())) return child;
+ child = child.getTreePrev();
+ }
+ }
+
@Nullable
public static ASTNode findCommonParent(ASTNode one, ASTNode two) {
// optimization
diff --git a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java
index 2af2eff..871b7ee 100644
--- a/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.java
+++ b/platform/core-impl/src/com/intellij/psi/stubs/StubTreeBuilder.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,9 +17,12 @@
import com.intellij.lang.Language;
import com.intellij.lang.LanguageParserDefinitions;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.util.Key;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IFileElementType;
import com.intellij.psi.tree.IStubFileElementType;
@@ -31,8 +34,7 @@
public class StubTreeBuilder {
private static final Key<Stub> stubElementKey = Key.create("stub.tree.for.file.content");
- private StubTreeBuilder() {
- }
+ private StubTreeBuilder() { }
@Nullable
public static Stub buildStubTree(final FileContent inputData) {
@@ -50,16 +52,31 @@
if (builder != null) {
data = builder.buildStubTree(inputData);
}
- if (data == null && !fileType.isBinary()) {
+ else {
final LanguageFileType languageFileType = (LanguageFileType)fileType;
Language l = languageFileType.getLanguage();
final IFileElementType type = LanguageParserDefinitions.INSTANCE.forLanguage(l).getFileNodeType();
- PsiFile psi = inputData.getPsiFile();
+ PsiFile psi = null;
+ CharSequence contentAsText = null;
+ Document document = FileDocumentManager.getInstance().getCachedDocument(inputData.getFile());
+ if (document != null) {
+ PsiFile existingPsi = PsiDocumentManager.getInstance(inputData.getProject()).getPsiFile(document);
+ if (existingPsi != null) {
+ contentAsText = existingPsi.getText();
+ psi = existingPsi;
+ }
+ }
+ if (contentAsText == null) {
+ contentAsText = inputData.getContentAsText();
+ psi = inputData.getPsiFile();
+ }
psi = psi.getViewProvider().getStubBindingRoot();
- CharSequence contentAsText = inputData.getContentAsText();
psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, contentAsText);
+ // if we load AST, it should be easily gc-able. See PsiFileImpl.createTreeElementPointer()
+ psi.getManager().startBatchFilesProcessingMode();
+
try {
IStubFileElementType stubFileElementType;
if (type instanceof IStubFileElementType) {
@@ -80,6 +97,7 @@
}
finally {
psi.putUserData(IndexingDataKeys.FILE_TEXT_CONTENT_KEY, null);
+ psi.getManager().finishBatchFilesProcessingMode();
}
}
diff --git a/platform/core-impl/src/com/intellij/util/CachedValueBase.java b/platform/core-impl/src/com/intellij/util/CachedValueBase.java
index d6befd8..5be82af 100644
--- a/platform/core-impl/src/com/intellij/util/CachedValueBase.java
+++ b/platform/core-impl/src/com/intellij/util/CachedValueBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -96,8 +96,7 @@
@Nullable
private Data<T> getData() {
- final SoftReference<Data<T>> ref = myData;
- return ref == null ? null : ref.get();
+ return SoftReference.dereference(myData);
}
protected boolean isUpToDate(@NotNull Data data) {
diff --git a/platform/core-impl/src/com/intellij/util/CompressionUtil.java b/platform/core-impl/src/com/intellij/util/CompressionUtil.java
index 6785695..e5e7d0b 100644
--- a/platform/core-impl/src/com/intellij/util/CompressionUtil.java
+++ b/platform/core-impl/src/com/intellij/util/CompressionUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -52,7 +52,7 @@
public static int writeCompressed(DataOutput out, byte[] bytes, int length) throws IOException {
if (length > COMPRESSION_THRESHOLD && ourCanUseSnappy) {
SoftReference<byte[]> reference = spareBufferLocal.get();
- byte[] compressedOutputBuffer = reference != null ? reference.get():null;
+ byte[] compressedOutputBuffer = com.intellij.reference.SoftReference.dereference(reference);
int maxCompressedSize = 32 + length + length / 6; // snappy.cc#MaxCompressedLength
if (compressedOutputBuffer == null || compressedOutputBuffer.length < maxCompressedSize) {
compressedOutputBuffer = new byte[maxCompressedSize];
diff --git a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java
index a29935a..f320f85 100644
--- a/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java
+++ b/platform/core-impl/src/com/intellij/util/indexing/FileContentImpl.java
@@ -66,20 +66,23 @@
}
if (psi == null) {
- Project project = getProject();
- if (project == null) {
- project = DefaultProjectFactory.getInstance().getDefaultProject();
- }
- final Language language = ((LanguageFileType)getFileTypeWithoutSubstitution()).getLanguage();
- final Language substitutedLanguage = LanguageSubstitutors.INSTANCE.substituteLanguage(language, getFile(), project);
- psi = PsiFileFactory.getInstance(project).createFileFromText(getFileName(), substitutedLanguage, getContentAsText(), false, false, true);
-
+ psi = createFileFromText(getContentAsText());
psi.putUserData(IndexingDataKeys.VIRTUAL_FILE, getFile());
putUserData(CACHED_PSI, psi);
}
return psi;
}
+ public PsiFile createFileFromText(CharSequence text) {
+ Project project = getProject();
+ if (project == null) {
+ project = DefaultProjectFactory.getInstance().getDefaultProject();
+ }
+ final Language language = ((LanguageFileType)getFileTypeWithoutSubstitution()).getLanguage();
+ final Language substitutedLanguage = LanguageSubstitutors.INSTANCE.substituteLanguage(language, getFile(), project);
+ return PsiFileFactory.getInstance(project).createFileFromText(getFileName(), substitutedLanguage, text, false, false, true);
+ }
+
public static class IllegalDataException extends RuntimeException {
public IllegalDataException(final String message) {
super(message);
diff --git a/platform/dvcs/dvcs.iml b/platform/dvcs/dvcs.iml
index cca5f77..145ad63 100644
--- a/platform/dvcs/dvcs.iml
+++ b/platform/dvcs/dvcs.iml
@@ -16,6 +16,7 @@
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="vcs-log-api" />
<orderEntry type="module" module-name="vcs-log-impl" />
+ <orderEntry type="module" module-name="images" />
</component>
</module>
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java b/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
new file mode 100644
index 0000000..5690078
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/DvcsCommitAdditionalComponent.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.dvcs;
+
+import com.intellij.dvcs.ui.DvcsBundle;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.ThrowableComputable;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.CheckinProjectPanel;
+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.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public abstract class DvcsCommitAdditionalComponent implements RefreshableOnComponent {
+
+ private static final Logger log = Logger.getInstance(DvcsCommitAdditionalComponent.class);
+
+ protected final JPanel myPanel;
+ protected final JCheckBox myAmend;
+ @Nullable private String myPreviousMessage;
+ @Nullable private String myAmendedMessage;
+ @NotNull protected final CheckinProjectPanel myCheckinPanel;
+
+ public DvcsCommitAdditionalComponent(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
+ myCheckinPanel = panel;
+ myPanel = new JPanel(new GridBagLayout());
+ final Insets insets = new Insets(2, 2, 2, 2);
+ // add amend checkbox
+ GridBagConstraints c = new GridBagConstraints();
+ //todo change to MigLayout
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridwidth = 2;
+ c.anchor = GridBagConstraints.CENTER;
+ c.insets = insets;
+ c.weightx = 1;
+ c.fill = GridBagConstraints.HORIZONTAL;
+
+ myAmend = new NonFocusableCheckBox(DvcsBundle.message("commit.amend"));
+ myAmend.setMnemonic('m');
+ myAmend.setToolTipText(DvcsBundle.message("commit.amend.tooltip"));
+ myPreviousMessage = myCheckinPanel.getCommitMessage();
+
+ myAmend.addActionListener(new ActionListener() {
+ @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);
+ }
+ else { // checkbox is selected not the first time
+ substituteCommitMessage(myAmendedMessage);
+ }
+ }
+ }
+ else {
+ // there was the amended message, but user has changed it => not reverting
+ if (myCheckinPanel.getCommitMessage().equals(myAmendedMessage)) {
+ myCheckinPanel.setCommitMessage(myPreviousMessage);
+ }
+ }
+ }
+ });
+ myPanel.add(myAmend, c);
+ }
+
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ public void refresh() {
+ myAmend.setSelected(false);
+ }
+
+ private void loadMessageInModalTask(@NotNull Project project) {
+ try {
+ String messageFromVcs =
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable<String, VcsException>() {
+ @Override
+ public String compute() throws VcsException {
+ return getLastCommitMessage();
+ }
+ }, "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(),
+ "Commit Message not Loaded");
+ log.info(e);
+ }
+ }
+
+ private void substituteCommitMessage(@NotNull String newMessage) {
+ myPreviousMessage = myCheckinPanel.getCommitMessage();
+ if (!myPreviousMessage.trim().equals(newMessage.trim())) {
+ myCheckinPanel.setCommitMessage(newMessage);
+ }
+ }
+
+ @Nullable
+ private String getLastCommitMessage() throws VcsException {
+ Collection<VirtualFile> roots = getRoots();
+ 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);
+ }
+ }
+ if (!exception.isNull()) {
+ throw exception.get();
+ }
+ return DvcsUtil.joinMessagesOrNull(messages);
+ }
+
+ @NotNull
+ protected abstract Collection<VirtualFile> getRoots();
+
+ @Nullable
+ protected abstract String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException;
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsRememberedInputs.java b/platform/dvcs/src/com/intellij/dvcs/DvcsRememberedInputs.java
new file mode 100644
index 0000000..58292aa
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/DvcsRememberedInputs.java
@@ -0,0 +1,96 @@
+/*
+ * 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.dvcs;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Kirill Likhodedov
+ */
+public class DvcsRememberedInputs {
+
+ private State myState = new State();
+
+ public static class State {
+ public List<UrlAndUserName> visitedUrls = new ArrayList<UrlAndUserName>();
+ public String cloneParentDir = "";
+ }
+
+ public static class UrlAndUserName {
+ public String url;
+ public String userName;
+ }
+
+ @NotNull
+ public State getState() {
+ return myState;
+ }
+
+ public void loadState(State state) {
+ myState = state;
+ }
+
+ public void addUrl(@NotNull String url) {
+ addUrl(url, "");
+ }
+
+ public void addUrl(@NotNull String url, @NotNull String userName) {
+ for (UrlAndUserName visitedUrl : myState.visitedUrls) {
+ if (visitedUrl.url.equalsIgnoreCase(url)) { // don't add multiple entries for a single url
+ if (!userName.isEmpty()) { // rewrite username, unless no username is specified
+ visitedUrl.userName = userName;
+ }
+ return;
+ }
+ }
+
+ UrlAndUserName urlAndUserName = new UrlAndUserName();
+ urlAndUserName.url = url;
+ urlAndUserName.userName = userName;
+ myState.visitedUrls.add(urlAndUserName);
+ }
+
+ @Nullable
+ public String getUserNameForUrl(@NotNull String url) {
+ for (UrlAndUserName urlAndUserName : myState.visitedUrls) {
+ if (urlAndUserName.url.equalsIgnoreCase(url)) {
+ return urlAndUserName.userName;
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ public List<String> getVisitedUrls() {
+ List<String> urls = new ArrayList<String>(myState.visitedUrls.size());
+ for (UrlAndUserName urlAndUserName : myState.visitedUrls) {
+ urls.add(urlAndUserName.url);
+ }
+ return urls;
+ }
+
+ public String getCloneParentDir() {
+ return myState.cloneParentDir;
+ }
+
+ public void setCloneParentDir(String cloneParentDir) {
+ myState.cloneParentDir = cloneParentDir;
+ }
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java b/platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java
index 27a353c..c2aef05 100644
--- a/platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java
+++ b/platform/dvcs/src/com/intellij/dvcs/DvcsUtil.java
@@ -16,19 +16,39 @@
package com.intellij.dvcs;
import com.intellij.dvcs.repo.Repository;
+import com.intellij.dvcs.repo.RepositoryManager;
+import com.intellij.openapi.diagnostic.Logger;
+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.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
+import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.StatusBarWidget;
import com.intellij.openapi.wm.WindowManager;
+import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.vcs.log.VcsLog;
+import com.intellij.vcs.log.VcsLogProvider;
+import org.intellij.images.editor.ImageFileEditor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
/**
* @author Kirill Likhodedov
@@ -97,4 +117,70 @@
}
return false;
}
+
+ /**
+ * Report a warning that the given root has no associated Repositories.
+ */
+ public static void noVcsRepositoryForRoot(@NotNull Logger log,
+ @NotNull VirtualFile root,
+ @NotNull Project project,
+ @NotNull RepositoryManager repositoryManager,
+ @Nullable AbstractVcs vcs) {
+ if (vcs == null) {
+ return;
+ }
+ ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
+ List<VirtualFile> roots = Arrays.asList(vcsManager.getRootsUnderVcs(vcs));
+ log.warn(String.format("Repository not found for root: %s. All roots: %s, all repositories: %s", root, roots,
+ repositoryManager.getRepositories()));
+ }
+
+ /**
+ * Checks if there are hg roots in the VCS log.
+ */
+ public static boolean logHasRootForVcs(@NotNull VcsLog log, @Nullable final VcsKey vcsKey) {
+ return ContainerUtil.find(log.getLogProviders(), new Condition<VcsLogProvider>() {
+ @Override
+ public boolean value(VcsLogProvider logProvider) {
+ return logProvider.getSupportedVcs().equals(vcsKey);
+ }
+ }) != null;
+ }
+
+ @Nullable
+ public static String joinMessagesOrNull(@NotNull Collection<String> messages) {
+ String joined = StringUtil.join(messages, "\n");
+ return StringUtil.isEmptyOrSpaces(joined) ? null : joined;
+ }
+
+ /**
+ * Returns the currently selected file, based on which VcsBranch or StatusBar components will identify the current repository root.
+ */
+ @Nullable
+ public static VirtualFile getSelectedFile(@NotNull Project project) {
+ StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
+ final FileEditor fileEditor = StatusBarUtil.getCurrentFileEditor(project, statusBar);
+ VirtualFile result = null;
+ if (fileEditor != null) {
+ if (fileEditor instanceof TextEditor) {
+ Document document = ((TextEditor)fileEditor).getEditor().getDocument();
+ result = FileDocumentManager.getInstance().getFile(document);
+ }
+ else if (fileEditor instanceof ImageFileEditor) {
+ result = ((ImageFileEditor)fileEditor).getImageEditor().getFile();
+ }
+ }
+
+ if (result == null) {
+ final FileEditorManager manager = FileEditorManager.getInstance(project);
+ if (manager != null) {
+ Editor editor = manager.getSelectedTextEditor();
+ if (editor != null) {
+ result = FileDocumentManager.getInstance().getFile(editor.getDocument());
+ }
+ }
+ }
+ return result;
+ }
+
}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.form b/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.form
new file mode 100644
index 0000000..a0b6798
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.form
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.dvcs.ui.CloneDvcsDialog">
+ <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="4" 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="785" height="119"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="7e816" class="javax.swing.JLabel">
+ <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="b8c8e"/>
+ <text resource-bundle="com/intellij/dvcs/ui/DvcsBundle" key="clone.repository.url"/>
+ </properties>
+ </component>
+ <vspacer id="86a0f">
+ <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"/>
+ </constraints>
+ </vspacer>
+ <hspacer id="a0290">
+ <constraints>
+ <grid row="3" column="1" row-span="1" col-span="3" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ <component id="b8c8e" class="com.intellij.ui.EditorComboBox" binding="myRepositoryURL" custom-create="true">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="2" 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="1422b" class="javax.swing.JLabel">
+ <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 resource-bundle="com/intellij/dvcs/ui/DvcsBundle" key="clone.parent.dir"/>
+ </properties>
+ </component>
+ <component id="876a6" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myParentDirectory">
+ <constraints>
+ <grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="2002c" 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>
+ <labelFor value="4e988"/>
+ <text resource-bundle="com/intellij/dvcs/ui/DvcsBundle" key="clone.dir.name"/>
+ </properties>
+ </component>
+ <component id="fbda8" class="javax.swing.JButton" binding="myTestButton">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="com/intellij/dvcs/ui/DvcsBundle" key="clone.test"/>
+ </properties>
+ </component>
+ <component id="4e988" class="javax.swing.JTextField" binding="myDirectoryName">
+ <constraints>
+ <grid row="2" 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>
+ <hspacer id="e781a">
+ <constraints>
+ <grid row="2" column="2" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+</form>
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.java b/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
new file mode 100644
index 0000000..0b5cd43
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/CloneDvcsDialog.java
@@ -0,0 +1,330 @@
+/*
+ * 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.dvcs.ui;
+
+import com.intellij.dvcs.DvcsRememberedInputs;
+import com.intellij.ide.impl.ProjectUtil;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.*;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.EditorComboBox;
+import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import javax.swing.event.DocumentListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.regex.Pattern;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public abstract class CloneDvcsDialog extends DialogWrapper {
+ /**
+ * The pattern for SSH URL-s in form [user@]host:path
+ */
+ private static final Pattern SSH_URL_PATTERN;
+
+ static {
+ // TODO make real URL pattern
+ @NonNls final String ch = "[\\p{ASCII}&&[\\p{Graph}]&&[^@:/]]";
+ @NonNls final String host = ch + "+(?:\\." + ch + "+)*";
+ @NonNls final String path = "/?" + ch + "+(?:/" + ch + "+)*/?";
+ @NonNls final String all = "(?:" + ch + "+@)?" + host + ":" + path;
+ SSH_URL_PATTERN = Pattern.compile(all);
+ }
+
+ private JPanel myRootPanel;
+ private EditorComboBox myRepositoryURL;
+ private TextFieldWithBrowseButton myParentDirectory;
+ private JButton myTestButton; // test repository
+ private JTextField myDirectoryName;
+
+ @NotNull private String myTestURL; // the repository URL at the time of the last test
+ @Nullable private Boolean myTestResult; // the test result of the last test or null if not tested
+ @NotNull private String myDefaultDirectoryName = "";
+ @NotNull protected final Project myProject;
+ @NotNull protected final String myVcsDirectoryName;
+
+ public CloneDvcsDialog(@NotNull Project project, @NotNull String vcsDirectoryName) {
+ super(project, true);
+ myProject = project;
+ myVcsDirectoryName = vcsDirectoryName;
+ init();
+ initListeners();
+ setTitle(DvcsBundle.getString("clone.title"));
+ setOKButtonText(DvcsBundle.getString("clone.button"));
+ }
+
+ @NotNull
+ public String getSourceRepositoryURL() {
+ return getCurrentUrlText();
+ }
+
+ public String getParentDirectory() {
+ return myParentDirectory.getText();
+ }
+
+ public String getDirectoryName() {
+ return myDirectoryName.getText();
+ }
+
+ /**
+ * Init components
+ */
+ private void initListeners() {
+ FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor();
+ fcd.setShowFileSystemRoots(true);
+ fcd.setTitle(DvcsBundle.getString("clone.destination.directory.title"));
+ fcd.setDescription(DvcsBundle.getString("clone.destination.directory.description"));
+ fcd.setHideIgnored(false);
+ myParentDirectory.addActionListener(
+ new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>(fcd.getTitle(), fcd.getDescription(), myParentDirectory,
+ myProject, fcd, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
+ @Override
+ protected VirtualFile getInitialFile() {
+ // suggest project base directory only if nothing is typed in the component.
+ String text = getComponentText();
+ if (text.length() == 0) {
+ VirtualFile file = myProject.getBaseDir();
+ if (file != null) {
+ return file;
+ }
+ }
+ return super.getInitialFile();
+ }
+ }
+ );
+
+ final DocumentListener updateOkButtonListener = new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ updateButtons();
+ }
+ };
+ myParentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener);
+ String parentDir = getRememberedInputs().getCloneParentDir();
+ if (StringUtil.isEmptyOrSpaces(parentDir)) {
+ parentDir = ProjectUtil.getBaseDir();
+ }
+ myParentDirectory.setText(parentDir);
+
+ myDirectoryName.getDocument().addDocumentListener(updateOkButtonListener);
+
+ myTestButton.addActionListener(new ActionListener() {
+ public void actionPerformed(final ActionEvent e) {
+ test();
+ }
+ });
+
+ setOKActionEnabled(false);
+ myTestButton.setEnabled(false);
+ }
+
+ private void test() {
+ myTestURL = getCurrentUrlText();
+ boolean testResult = test(myTestURL);
+
+ if (testResult) {
+ Messages.showInfoMessage(myTestButton, DvcsBundle.message("clone.test.success.message", myTestURL),
+ DvcsBundle.getString("clone.test.connection.title"));
+ myTestResult = Boolean.TRUE;
+ }
+ else {
+ myTestResult = Boolean.FALSE;
+ }
+ updateButtons();
+ }
+
+ protected abstract boolean test(@NotNull String url);
+
+ @NotNull
+ protected abstract DvcsRememberedInputs getRememberedInputs();
+
+ /**
+ * Check fields and display error in the wrapper if there is a problem
+ */
+ private void updateButtons() {
+ if (!checkRepositoryURL()) {
+ return;
+ }
+ if (!checkDestination()) {
+ return;
+ }
+ setErrorText(null);
+ setOKActionEnabled(true);
+ }
+
+ /**
+ * Check destination directory and set appropriate error text if there are problems
+ *
+ * @return true if destination components are OK.
+ */
+ private boolean checkDestination() {
+ if (myParentDirectory.getText().length() == 0 || myDirectoryName.getText().length() == 0) {
+ setErrorText(null);
+ setOKActionEnabled(false);
+ return false;
+ }
+ File file = new File(myParentDirectory.getText(), myDirectoryName.getText());
+ if (file.exists()) {
+ setErrorText(DvcsBundle.message("clone.destination.exists.error", file));
+ setOKActionEnabled(false);
+ return false;
+ }
+ else if (!file.getParentFile().exists()) {
+ setErrorText(DvcsBundle.message("clone.parent.missing.error", file.getParent()));
+ setOKActionEnabled(false);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Check repository URL and set appropriate error text if there are problems
+ *
+ * @return true if repository URL is OK.
+ */
+ private boolean checkRepositoryURL() {
+ String repository = getCurrentUrlText();
+ if (repository.length() == 0) {
+ setErrorText(null);
+ setOKActionEnabled(false);
+ return false;
+ }
+ if (myTestResult != null && repository.equals(myTestURL)) {
+ if (!myTestResult.booleanValue()) {
+ setErrorText(DvcsBundle.getString("clone.test.failed.error"));
+ setOKActionEnabled(false);
+ return false;
+ }
+ else {
+ return true;
+ }
+ }
+ try {
+ if (new URI(repository).isAbsolute()) {
+ return true;
+ }
+ }
+ catch (URISyntaxException urlExp) {
+ // do nothing
+ }
+ // check if ssh url pattern
+ if (SSH_URL_PATTERN.matcher(repository).matches()) {
+ return true;
+ }
+ try {
+ File file = new File(repository);
+ if (file.exists()) {
+ if (!file.isDirectory()) {
+ setErrorText(DvcsBundle.getString("clone.url.is.not.directory.error"));
+ setOKActionEnabled(false);
+ }
+ return true;
+ }
+ }
+ catch (Exception fileExp) {
+ // do nothing
+ }
+ setErrorText(DvcsBundle.getString("clone.invalid.url"));
+ setOKActionEnabled(false);
+ return false;
+ }
+
+ @NotNull
+ private String getCurrentUrlText() {
+ return myRepositoryURL.getText().trim();
+ }
+
+ private void createUIComponents() {
+ myRepositoryURL = new EditorComboBox("");
+ final DvcsRememberedInputs rememberedInputs = getRememberedInputs();
+ myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getVisitedUrls(), String.class));
+ myRepositoryURL.addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
+ @Override
+ public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
+ // enable test button only if something is entered in repository URL
+ final String url = getCurrentUrlText();
+ myTestButton.setEnabled(url.length() != 0);
+ if (myDefaultDirectoryName.equals(myDirectoryName.getText()) || myDirectoryName.getText().length() == 0) {
+ // modify field if it was unmodified or blank
+ myDefaultDirectoryName = defaultDirectoryName(url, myVcsDirectoryName);
+ myDirectoryName.setText(myDefaultDirectoryName);
+ }
+ updateButtons();
+ }
+ });
+ }
+
+ public void prependToHistory(@NotNull final String item) {
+ myRepositoryURL.prependItem(item);
+ }
+
+ public void rememberSettings() {
+ final DvcsRememberedInputs rememberedInputs = getRememberedInputs();
+ rememberedInputs.addUrl(getSourceRepositoryURL());
+ rememberedInputs.setCloneParentDir(getParentDirectory());
+ }
+
+ /**
+ * Get default name for checked out directory
+ *
+ * @param url an URL to checkout
+ * @return a default repository name
+ */
+ @NotNull
+ private static String defaultDirectoryName(@NotNull final String url, @NotNull final String vcsDirName) {
+ String nonSystemName;
+ if (url.endsWith("/" + vcsDirName) || url.endsWith(File.separator + vcsDirName)) {
+ nonSystemName = url.substring(0, url.length() - vcsDirName.length() - 1);
+ }
+ else {
+ if (url.endsWith(vcsDirName)) {
+ nonSystemName = url.substring(0, url.length() - vcsDirName.length());
+ }
+ else {
+ nonSystemName = url;
+ }
+ }
+ int i = nonSystemName.lastIndexOf('/');
+ if (i == -1 && File.separatorChar != '/') {
+ i = nonSystemName.lastIndexOf(File.separatorChar);
+ }
+ return i >= 0 ? nonSystemName.substring(i + 1) : "";
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myRepositoryURL;
+ }
+
+ protected JComponent createCenterPanel() {
+ return myRootPanel;
+ }
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.java b/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.java
new file mode 100644
index 0000000..879def5
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.java
@@ -0,0 +1,55 @@
+/*
+ * 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.dvcs.ui;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ResourceBundle;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public class DvcsBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "com.intellij.dvcs.ui.DvcsBundle";
+
+ private DvcsBundle() {
+ }
+
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
+ if (bundle == null) {
+ bundle = ResourceBundle.getBundle(BUNDLE);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
+ }
+ return bundle;
+ }
+
+ public static String getString(@PropertyKey(resourceBundle = BUNDLE) final String key) {
+ return getBundle().getString(key);
+ }
+}
diff --git a/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.properties b/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.properties
new file mode 100644
index 0000000..7b8dbc4
--- /dev/null
+++ b/platform/dvcs/src/com/intellij/dvcs/ui/DvcsBundle.properties
@@ -0,0 +1,19 @@
+clone.button=Clone
+clone.destination.directory.description=Select a parent directory destination directory for clone
+clone.destination.directory.title=Parent Directory
+clone.destination.exists.error=The path {0} exists. Repository cannot be cloned to an existing directory.
+clone.dir.name=Directory &Name:
+clone.invalid.url=Repository URL is a malformed URL or non-existent directory.
+clone.parent.dir=&Parent Directory:
+clone.parent.missing.error=The parent path {0} must exist.
+clone.repository.url=Vcs &Repository URL:
+clone.test.failed.error=Repository test has failed.
+clone.test.success.message=<html>Connection to repository {0} has been successful.</html>
+clone.test.connection.title=Test Connection
+clone.test=&Test
+clone.testing=Testing repository {0}
+clone.title=Clone Repository
+clone.url.is.not.directory.error=Repository URL is not a directory.
+cloning.repository=Cloning source repository {0}
+commit.amend=Amend commit
+commit.amend.tooltip=<html>Merge this commit with the previous one</html>
diff --git a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
index 69934b6..881f68d 100644
--- a/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.java
+++ b/platform/editor-ui-api/src/com/intellij/ide/ui/UISettings.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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.ide.ui;
import com.intellij.ide.IdeBundle;
@@ -51,14 +50,24 @@
)}
)
public class UISettings implements PersistentStateComponent<UISettings>, ExportableApplicationComponent {
- private final EventListenerList myListenerList;
+ /** Not tabbed pane. */
+ public static final int TABS_NONE = 0;
- @Property(filter = FontFilter.class)
- @NonNls
- public String FONT_FACE;
- @Property(filter = FontFilter.class)
- public int FONT_SIZE;
+ public static UISettings getInstance() {
+ return ApplicationManager.getApplication().getComponent(UISettings.class);
+ }
+ /**
+ * Use this method if you are not sure whether the application is initialized.
+ * @return persisted UISettings instance or default values.
+ */
+ public static UISettings getShadowInstance() {
+ Application application = ApplicationManager.getApplication();
+ return application != null ? getInstance() : new UISettings();
+ }
+
+ @Property(filter = FontFilter.class) public String FONT_FACE;
+ @Property(filter = FontFilter.class) public int FONT_SIZE;
public int RECENT_FILES_LIMIT = 50;
public int CONSOLE_COMMAND_HISTORY_LIMIT = 300;
public int EDITOR_TAB_LIMIT = 10;
@@ -77,14 +86,14 @@
public boolean SHOW_NAVIGATION_BAR = true;
public boolean ALWAYS_SHOW_WINDOW_BUTTONS = false;
public boolean CYCLE_SCROLLING = true;
- public boolean SCROLL_TAB_LAYOUT_IN_EDITOR = PlatformUtilsCore.isAppCode();
+ public boolean SCROLL_TAB_LAYOUT_IN_EDITOR = false;
public boolean SHOW_CLOSE_BUTTON = true;
public int EDITOR_TAB_PLACEMENT = 1;
public boolean HIDE_KNOWN_EXTENSION_IN_TABS = false;
public boolean SHOW_ICONS_IN_QUICK_NAVIGATION = true;
public boolean CLOSE_NON_MODIFIED_FILES_FIRST = false;
public boolean ACTIVATE_MRU_EDITOR_ON_CLOSE = false;
- public boolean ACTIVATE_RIGHT_EDITOR_ON_CLOSE = PlatformUtilsCore.isAppCode();
+ public boolean ACTIVATE_RIGHT_EDITOR_ON_CLOSE = false;
public boolean ANTIALIASING_IN_EDITOR = true;
public boolean MOVE_MOUSE_ON_DEFAULT_BUTTON = false;
public boolean ENABLE_ALPHA_MODE = false;
@@ -104,18 +113,10 @@
public boolean DEFAULT_AUTOSCROLL_TO_SOURCE = false;
public boolean PRESENTATION_MODE = false;
public int PRESENTATION_MODE_FONT_SIZE = 24;
-
- /**
- * Defines whether asterisk is shown on modified editor tab or not
- */
public boolean MARK_MODIFIED_TABS_WITH_ASTERISK = false;
-
public boolean SHOW_DIRECTORY_FOR_NON_UNIQUE_FILENAMES = false;
- /**
- * Not tabbed pane
- */
- public static final int TABS_NONE = 0;
+ private final EventListenerList myListenerList;
public UISettings() {
myListenerList = new EventListenerList();
@@ -124,11 +125,11 @@
}
private void tweakPlatformDefaults() {
- // TODO: Make it pluggable
+ // TODO[anton] consider making all IDEs use the same settings
if (PlatformUtilsCore.isAppCode()) {
- SHOW_MAIN_TOOLBAR = false;
+ SCROLL_TAB_LAYOUT_IN_EDITOR = true;
+ ACTIVATE_RIGHT_EDITOR_ON_CLOSE = true;
SHOW_ICONS_IN_MENUS = false;
- SHOW_MEMORY_INDICATOR = false;
}
}
@@ -140,7 +141,7 @@
}
public void addUISettingsListener(@NotNull final UISettingsListener listener, @NotNull Disposable parentDisposable) {
- myListenerList.add(UISettingsListener.class,listener);
+ myListenerList.add(UISettingsListener.class, listener);
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
@@ -153,27 +154,14 @@
* Notifies all registered listeners that UI settings has been changed.
*/
public void fireUISettingsChanged() {
- UISettingsListener[] listeners= myListenerList.getListeners(UISettingsListener.class);
+ UISettingsListener[] listeners = myListenerList.getListeners(UISettingsListener.class);
for (UISettingsListener listener : listeners) {
listener.uiSettingsChanged(this);
}
}
- public static UISettings getInstance() {
- return ApplicationManager.getApplication().getComponent(UISettings.class);
- }
-
- /**
- * Use this method if you are not sure is application initialized or not
- * @return UISettings instance or default values
- */
- public static UISettings getShadowInstance() {
- Application application = ApplicationManager.getApplication();
- return application != null ? getInstance() : new UISettings();
- }
-
public void removeUISettingsListener(UISettingsListener listener) {
- myListenerList.remove(UISettingsListener.class,listener);
+ myListenerList.remove(UISettingsListener.class, listener);
}
private void setSystemFontFaceAndSize() {
@@ -185,11 +173,6 @@
}
private static Pair<String, Integer> getSystemFontFaceAndSize() {
- final Pair<String,Integer> fontData = UIUtil.getSystemFontData();
- if (fontData != null) {
- return fontData;
- }
-
if (SystemInfo.isWindows) {
//noinspection HardCodedStringLiteral
final Font font = (Font)Toolkit.getDefaultToolkit().getDesktopProperty("win.messagebox.font");
@@ -198,6 +181,11 @@
}
}
+ final Pair<String,Integer> fontData = UIUtil.getSystemFontData();
+ if (fontData != null) {
+ return fontData;
+ }
+
return Pair.create("Dialog", 12);
}
@@ -322,24 +310,27 @@
}
@NotNull
+ @Override
public File[] getExportFiles() {
return new File[]{PathManager.getOptionsFile("ui.lnf")};
}
@NotNull
+ @Override
public String getPresentableName() {
return IdeBundle.message("ui.settings");
}
@NonNls
@NotNull
+ @Override
public String getComponentName() {
return "UISettings";
}
- public void initComponent() {
- }
+ @Override
+ public void initComponent() { }
- public void disposeComponent() {
- }
+ @Override
+ public void disposeComponent() { }
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionGroup.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionGroup.java
index a0b40ad..3d2780a 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionGroup.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionGroup.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.actionSystem;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -22,12 +23,14 @@
import javax.swing.*;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
-import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;
/**
* Represents a group of actions.
+ *
+ * @see com.intellij.openapi.actionSystem.DefaultActionGroup
+ * @see com.intellij.openapi.actionSystem.ComputableActionGroup
*/
public abstract class ActionGroup extends AnAction {
private boolean myPopup;
@@ -169,17 +172,11 @@
boolean dumbAware = super.isDumbAware();
if (dumbAware) {
- myDumbAware = Boolean.valueOf(dumbAware);
+ myDumbAware = Boolean.TRUE;
} else {
if (myDumbAware == null) {
- try {
- Method updateMethod = getClass().getMethod("update", AnActionEvent.class);
- Class<?> declaringClass = updateMethod.getDeclaringClass();
- myDumbAware = AnAction.class.equals(declaringClass) || ActionGroup.class.equals(declaringClass);
- }
- catch (NoSuchMethodException e) {
- myDumbAware = Boolean.FALSE;
- }
+ Class<?> declaringClass = ReflectionUtil.getMethodDeclaringClass(getClass(), "update", AnActionEvent.class);
+ myDumbAware = AnAction.class.equals(declaringClass) || ActionGroup.class.equals(declaringClass);
}
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.java b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.java
index db95e99..5577664 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/actionSystem/ActionManager.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.
@@ -72,7 +72,7 @@
*
* @return An instance of <code>ActionToolbar</code>
*/
- public abstract ActionToolbar createActionToolbar(@NonNls String place, ActionGroup group, boolean horizontal);
+ public abstract ActionToolbar createActionToolbar(@NonNls String place, @NotNull ActionGroup group, boolean horizontal);
/**
* Returns action associated with the specified actionId.
@@ -151,7 +151,7 @@
* @return the created panel.
* @since 5.1
*/
- public abstract JComponent createButtonToolbar(final String actionPlace, final ActionGroup messageActionGroup);
+ public abstract JComponent createButtonToolbar(final String actionPlace, @NotNull ActionGroup messageActionGroup);
public abstract AnAction getActionOrStub(@NonNls String id);
@@ -172,5 +172,5 @@
public abstract void removeAnActionListener(AnActionListener listener);
@Nullable
- public abstract KeyboardShortcut getKeyboardShortcut(@NotNull String actionId);
+ public abstract KeyboardShortcut getKeyboardShortcut(@NonNls @NotNull String actionId);
}
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
new file mode 100644
index 0000000..3648e47
--- /dev/null
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/Caret.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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 com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.UserDataHolderEx;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Represents a specific caret instance in the editor when it support multiple carets (see {@link CaretModel#supportsMultipleCarets()}.
+ * Provides methods to query and modify caret position and caret's associated selection.
+ */
+public interface Caret extends UserDataHolderEx, Disposable {
+ /**
+ * Returns an instance of CaretModel, current caret is associated with.
+ */
+ @NotNull
+ CaretModel getCaretModel();
+
+ /**
+ * Tells whether this caret is valid, i.e. recognized by the caret model currently. Caret is valid since its creation till its
+ * removal from caret model.
+ *
+ * @see com.intellij.openapi.editor.CaretModel#addCaret(VisualPosition)
+ * @see com.intellij.openapi.editor.CaretModel#removeCaret(Caret)
+ */
+ boolean isValid();
+
+ /**
+ * Moves the caret by the specified number of lines and/or columns.
+ *
+ * @param columnShift the number of columns to move the caret by.
+ * @param lineShift the number of lines to move the caret by.
+ * @param withSelection if true, the caret move should extend the selection in the document.
+ * @param scrollToCaret if true, the document should be scrolled so that the caret is visible after the move.
+ */
+ void moveCaretRelatively(int columnShift,
+ int lineShift,
+ boolean withSelection,
+ boolean scrollToCaret);
+
+ /**
+ * Moves the caret to the specified logical position.
+ * If corresponding position is in the folded region currently, the region will be expanded.
+ *
+ * @param pos the position to move to.
+ */
+ void moveToLogicalPosition(@NotNull LogicalPosition pos);
+
+ /**
+ * Moves the caret to the specified visual position.
+ *
+ * @param pos the position to move to.
+ */
+ void moveToVisualPosition(@NotNull VisualPosition pos);
+
+ /**
+ * Short hand for calling {@link #moveToOffset(int, boolean)} with <code>'false'</code> as a second argument.
+ *
+ * @param offset the offset to move to
+ */
+ void moveToOffset(int offset);
+
+ /**
+ * Moves the caret to the specified offset in the document.
+ * If corresponding position is in the folded region currently, the region will be expanded.
+ *
+ * @param offset the offset to move to.
+ * @param locateBeforeSoftWrap there is a possible case that there is a soft wrap at the given offset, hence, the same offset
+ * corresponds to two different visual positions - just before soft wrap and just after soft wrap.
+ * We may want to clearly indicate where to put the caret then. Given parameter allows to do that.
+ * <b>Note:</b> it's ignored if there is no soft wrap at the given offset
+ */
+ void moveToOffset(int offset, boolean locateBeforeSoftWrap);
+
+ /**
+ * Caret position may be updated on document change (e.g. consider that user updates from VCS that causes addition of text
+ * before caret. Caret offset, visual and logical positions should be updated then). So, there is a possible case
+ * that caret model in in the process of caret position update now.
+ * <p/>
+ * Current method allows to check that.
+ *
+ * @return <code>true</code> if caret position is up-to-date for now; <code>false</code> otherwise
+ */
+ boolean isUpToDate();
+
+ /**
+ * Returns the logical position of the caret.
+ *
+ * @return the caret position.
+ */
+ @NotNull
+ LogicalPosition getLogicalPosition();
+
+ /**
+ * Returns the visual position of the caret.
+ *
+ * @return the caret position.
+ */
+ @NotNull
+ VisualPosition getVisualPosition();
+
+ /**
+ * Returns the offset of the caret in the document.
+ *
+ * @return the caret offset.
+ */
+ int getOffset();
+
+ /**
+ * @return document offset for the start of the logical line where caret is located
+ */
+ int getVisualLineStart();
+
+ /**
+ * @return document offset that points to the first symbol shown at the next visual line after the one with caret on it
+ */
+ int getVisualLineEnd();
+
+ /**
+ * Returns the start offset in the document of the selected text range, or the caret
+ * position if there is currently no selection.
+ *
+ * @return the selection start offset.
+ */
+ int getSelectionStart();
+
+ /**
+ * @return object that encapsulates information about visual position of selected text start if any
+ */
+ @NotNull
+ VisualPosition getSelectionStartPosition();
+
+ /**
+ * Returns the end offset in the document of the selected text range, or the caret
+ * position if there is currently no selection.
+ *
+ * @return the selection end offset.
+ */
+ int getSelectionEnd();
+
+ /**
+ * @return object that encapsulates information about visual position of selected text end if any;
+ */
+ @NotNull
+ VisualPosition getSelectionEndPosition();
+
+ /**
+ * Returns the text selected in the editor.
+ *
+ * @return the selected text, or null if there is currently no selection.
+ */
+ @Nullable
+ String getSelectedText();
+
+ /**
+ * Returns the offset from which the user started to extend the selection (the selection start
+ * if the selection was extended in forward direction, or the selection end if it was
+ * extended backward).
+ *
+ * @return the offset from which the selection was started, or the caret offset if there is
+ * currently no selection.
+ */
+ int getLeadSelectionOffset();
+
+ /**
+ * @return object that encapsulates information about visual position from which the user started to extend the selection if any
+ */
+ @NotNull
+ VisualPosition getLeadSelectionPosition();
+
+ /**
+ * Checks if a range of text is currently selected.
+ *
+ * @return true if a range of text is selected, false otherwise.
+ */
+ boolean hasSelection();
+
+ /**
+ * Selects the specified range of text.
+ *
+ * @param startOffset the start offset of the text range to select.
+ * @param endOffset the end offset of the text range to select.
+ */
+ void setSelection(int startOffset, int endOffset);
+
+ /**
+ * 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.
+ *
+ * @param startOffset start selection offset
+ * @param endPosition end visual position of the text range to select (<code>null</code> argument means that
+ * no specific visual position should be used)
+ * @param endOffset end selection offset
+ */
+ void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset);
+
+ /**
+ * 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.
+ *
+ * @param startPosition start visual position of the text range to select (<code>null</code> argument means that
+ * no specific visual position should be used)
+ * @param endPosition end visual position of the text range to select (<code>null</code> argument means that
+ * no specific visual position should be used)
+ * @param startOffset start selection offset
+ * @param endOffset end selection offset
+ */
+ void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset);
+
+ /**
+ * Removes the selection in the editor.
+ */
+ void removeSelection();
+
+ /**
+ * Selects the entire line of text at the caret position.
+ */
+ void selectLineAtCaret();
+
+ /**
+ * Selects the entire word at the caret position, optionally using camel-case rules to
+ * determine word boundaries.
+ *
+ * @param honorCamelWordsSettings if true and "Use CamelHumps words" is enabled,
+ * upper-case letters within the word are considered as
+ * boundaries for the range of text to select.
+ */
+ void selectWordAtCaret(boolean honorCamelWordsSettings);
+
+ /**
+ * Clones the current caret and positions the new one right above or below the current one. If current caret has selection, corresponding
+ * 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.
+ */
+ @Nullable
+ Caret clone(boolean above);
+}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretAction.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretAction.java
new file mode 100644
index 0000000..9c0b659
--- /dev/null
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/CaretAction.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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;
+
+/**
+ * Action to be performed on a specific editor caret
+ *
+ * @see com.intellij.openapi.editor.CaretModel#runForEachCaret(com.intellij.openapi.editor.CaretAction)
+ */
+public interface CaretAction {
+ void perform(Caret caret);
+}
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 a83020b..776566f 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
@@ -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,11 +17,32 @@
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;
+
+import java.util.Collection;
+import java.util.List;
/**
* Provides services for moving the caret and retrieving information about caret position.
*
+ * May support several carets existing simultaneously in a document. {@link #supportsMultipleCarets()} method can be used to find out
+ * whether particular instance of CaretModel does it. If it does, query and update methods for caret position operate on a certain 'primary'
+ * caret. There exists a way to perform the same operation(s) on each caret - see
+ * {@link #runForEachCaret(com.intellij.openapi.editor.CaretAction)} method. Within its context, query and update methods operate on the
+ * current caret in that iteration. This behaviour can change in future though, so using caret and selection query and update methods in
+ * actions that need to operate on multiple carets is discouraged - methods on {@link com.intellij.openapi.editor.Caret} instances obtained
+ * via {@link #getAllCarets()} or {@link #runForEachCaret(CaretAction)} should be used instead.
+ * <p>
+ * How 'primary' caret is determined by the model is not defined (currently it's the most recently added caret, but that can change).
+ * <p>
+ * At all times at least one caret will exist in a document.
+ * <p>
+ * Update methods, {@link #runBatchCaretOperation(Runnable)} and {@link #runForEachCaret(com.intellij.openapi.editor.CaretAction)} methods
+ * should only be run from EDT. Query methods can be run from any thread, when called not from EDT, those methods are 'not aware' of
+ * 'runForEachCaret' scope - they will always return information about primary caret.
+ *
* @see Editor#getCaretModel()
*/
public interface CaretModel {
@@ -32,7 +53,7 @@
* @param lineShift the number of lines to move the caret by.
* @param withSelection if true, the caret move should extend the range or block selection in the document.
* @param blockSelection if true and <code>withSelection</code> is true, the caret move should extend
- * the block selection in the document.
+ * the block selection in the document. This parameter is ignored when multiple carets are supported by the model.
* @param scrollToCaret if true, the document should be scrolled so that the caret is visible after the move.
*/
void moveCaretRelatively(int columnShift,
@@ -43,6 +64,7 @@
/**
* Moves the caret to the specified logical position.
+ * If corresponding position is in the folded region currently, the region will be expanded.
*
* @param pos the position to move to.
*/
@@ -64,6 +86,7 @@
/**
* Moves the caret to the specified offset in the document.
+ * If corresponding position is in the folded region currently, the region will be expanded.
*
* @param offset the offset to move to.
* @param locateBeforeSoftWrap there is a possible case that there is a soft wrap at the given offset, hence, the same offset
@@ -137,4 +160,80 @@
* @return Caret attributes.
*/
TextAttributes getTextAttributes();
+
+ /**
+ * Tells whether multiple coexisting carets are supported by this CaretModel instance.
+ */
+ boolean supportsMultipleCarets();
+
+ /**
+ * Returns current caret - the one, query and update methods in the model operate at the moment. In the current implementation this is
+ * either an iteration-current caret within the context of {@link #runForEachCaret(Runnable)} method, or the 'primary' caret without that
+ * context. Users {@link #runForEachCaret(Runnable)} method should use caret parameter passed to
+ * {@link com.intellij.openapi.editor.CaretAction#perform(Caret)} method instead of this method, as the definition of current caret (as
+ * well as caret instance operated on by model methods) can potentially change.
+ */
+ @NotNull
+ Caret getCurrentCaret();
+
+ /**
+ * Returns the 'primary' caret.
+ */
+ @NotNull
+ Caret getPrimaryCaret();
+
+ /**
+ * Returns all carets currently existing in the document, ordered by their position in the document.
+ */
+ @NotNull
+ Collection<Caret> getAllCarets();
+
+ /**
+ * Returns a caret at the given position in the document, or <code>null</code>, if there's no caret there.
+ */
+ @Nullable
+ Caret getCaretAt(@NotNull VisualPosition pos);
+
+ /**
+ * Adds a new caret at the given position, and returns corresponding Caret instance. Locations outside of possible values for the given
+ * document are trimmed automatically.
+ * Does nothing if multiple carets are not supporeted, a caret already exists at specified location or selection of existing caret
+ * includes the specified location, <code>null</code> is returned in this case.
+ */
+ @Nullable
+ Caret addCaret(@NotNull VisualPosition pos);
+
+ /**
+ * Removes a given caret if it's recognized by the model and is not the only existing caret in the document, returning <code>true</code>.
+ * <code>false</code> is returned if any of the above condition doesn't hold, and the removal cannot happen.
+ */
+ boolean removeCaret(@NotNull Caret caret);
+
+ /**
+ * Removes all carets except the 'primary' one from the document.
+ */
+ void removeSecondaryCarets();
+
+ /**
+ * Sets the number of carets, their positions and selection ranges according to the provided parameters. Null values in any of the lists
+ * 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 setCarets(@NotNull List<LogicalPosition> caretPositions, @NotNull List<? extends Segment> selections);
+
+ /**
+ * Executes the given task for each existing caret. Carets are iterated in their position order. Set of carets to iterate over is
+ * determined in the beginning and is not affected by the potential carets addition or removal by the task being executed.
+ * At the end, merging of carets and selections is performed, so that no two carets will occur at the same logical position and
+ * no two selection will overlap after this method is finished.
+ */
+ void runForEachCaret(@NotNull CaretAction action);
+
+ /**
+ * Executes the given task, performing caret merging afterwards. Caret merging will not happen until the operation is finished.
+ */
+ void runBatchCaretOperation(@NotNull Runnable runnable);
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java
index 3a5d9d4..bd63b43 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/Editor.java
@@ -22,7 +22,6 @@
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.UserDataHolder;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorSettings.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorSettings.java
index 59f568b..69efb46 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorSettings.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/EditorSettings.java
@@ -37,7 +37,7 @@
void setAdditionalLinesCount(int additionalLinesCount);
int getAdditionalColumnsCount();
- void setAdditionalColumnsCount(int additinalColumnsCount);
+ void setAdditionalColumnsCount(int additionalColumnsCount);
boolean isLineMarkerAreaShown();
void setLineMarkerAreaShown(boolean lineMarkerAreaShown);
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java
index fe76764..0b43e17 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java
@@ -137,6 +137,14 @@
);
}
+ /**
+ * Returns a new instance of class corresponding to the same logical position in the document, but without any cached
+ * reference to its visual position.
+ */
+ public LogicalPosition withoutVisualPositionInfo() {
+ return new LogicalPosition(line, column);
+ }
+
public boolean equals(Object o) {
if (!(o instanceof LogicalPosition)) return false;
final LogicalPosition logicalPosition = (LogicalPosition) o;
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/ScrollingModel.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/ScrollingModel.java
index 2c40c1f..460633c 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/ScrollingModel.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/ScrollingModel.java
@@ -28,12 +28,13 @@
public interface ScrollingModel {
@NotNull
Rectangle getVisibleArea();
+ @NotNull
Rectangle getVisibleAreaOnScrollingFinished();
- void scrollToCaret(ScrollType scrollType);
- void scrollTo(LogicalPosition pos, ScrollType scrollType);
+ void scrollToCaret(@NotNull ScrollType scrollType);
+ void scrollTo(@NotNull LogicalPosition pos, @NotNull ScrollType scrollType);
- void runActionOnScrollingFinished(Runnable action);
+ void runActionOnScrollingFinished(@NotNull Runnable action);
void disableAnimation();
void enableAnimation();
@@ -43,6 +44,6 @@
void scrollVertically(int scrollOffset);
void scrollHorizontally(int scrollOffset);
- void addVisibleAreaListener(VisibleAreaListener listener);
- void removeVisibleAreaListener(VisibleAreaListener listener);
+ void addVisibleAreaListener(@NotNull VisibleAreaListener listener);
+ void removeVisibleAreaListener(@NotNull VisibleAreaListener listener);
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java
index 077ddd5..9d66612 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/SelectionModel.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,14 @@
* these two types of selection, but only one type of selection can exist in a document at
* any given time.
*
+ * When caret model supports multiple carets, block selection mode is not supported.
+ * Instead, each caret can have its own selected region. Most of the methods querying or
+ * updating selection operate on the current caret (see {@link com.intellij.openapi.editor.CaretModel#runForEachCaret(Runnable)},
+ * or 'primary' caret if current caret is not defined. The exception is {@link #copySelectionToClipboard()},
+ * which copies contents of all selected regions to clipboard as one piece of text.
+ *
* @see Editor#getSelectionModel()
+ * @see com.intellij.openapi.editor.CaretModel
*/
public interface SelectionModel {
/**
@@ -69,6 +76,13 @@
String getSelectedText();
/**
+ * If <code>allCarets</code> is <code>true</code>, returns the concatenation of selections for all carets, or <code>null</code> if there
+ * are no selections. If <code>allCarets</code> is <code>false</code>, works just like {@link #getSelectedText}.
+ */
+ @Nullable
+ String getSelectedText(boolean allCarets);
+
+ /**
* Returns the offset from which the user started to extend the selection (the selection start
* if the selection was extended in forward direction, or the selection end if it was
* extended backward).
@@ -93,6 +107,15 @@
boolean hasSelection();
/**
+ * Checks if a range of text is currently selected. If <code>anyCaret</code> is <code>true</code>, check all existing carets in
+ * the document, and returns <code>true</code> if any of them has selection, otherwise checks only the current caret.
+ *
+ * @return true if a range of text is selected, false otherwise.
+ * @see #hasBlockSelection()
+ */
+ boolean hasSelection(boolean anyCaret);
+
+ /**
* Selects the specified range of text in regular (non-block) selection mode.
*
* @param startOffset the start offset of the text range to select.
@@ -133,6 +156,12 @@
void removeSelection();
/**
+ * Removes the selection in the editor. If <code>allCarets</code> is <code>true</code>, removes selections from all carets in the
+ * document, otherwise, does this just for the current caret.
+ */
+ void removeSelection(boolean allCarets);
+
+ /**
* Adds a listener for receiving information about selection changes.
*
* @param listener the listener instance.
@@ -163,27 +192,32 @@
/**
* Copies the currently selected text to the clipboard.
+ *
+ * When multiple selections exist in the document, all of them are copied, as a single piece of text.
*/
void copySelectionToClipboard();
/**
- * Selects the specified rectangle of text in block selection mode.
+ * Selects the specified rectangle of text in block selection mode. When multiple carets are supported by editor, this creates an
+ * equivalent multi-caret selection (note, that in this case {@link #hasBlockSelection()} will still return <code>false</code>
+ * afterwards!).
*
* @param blockStart the start of the rectangle to select.
* @param blockEnd the end of the rectangle to select.
* @see #setSelection(int, int)
*/
- void setBlockSelection(LogicalPosition blockStart, LogicalPosition blockEnd);
+ void setBlockSelection(@NotNull LogicalPosition blockStart, @NotNull LogicalPosition blockEnd);
/**
- * Removes the block selection from the document.
+ * Removes the block selection from the document. Does nothing if multiple carets are supported by editor.
*
* @see #removeSelection()
+ * @see #removeSelection(boolean)
*/
void removeBlockSelection();
/**
- * Checks if a rectangular block of text is currently selected in the document.
+ * Checks if a rectangular block of text is currently selected in the document. Does not apply to multiple-caret selections.
*
* @return true if a block selection currently exists, false otherwise.
* @see #hasSelection()
@@ -191,9 +225,8 @@
boolean hasBlockSelection();
/**
- * Returns an array of start offsets in the document for line parts selected
- * in block selection mode. The size of the returned array is equal to the height
- * of the selected text block.
+ * Returns an array of start offsets in the document for line parts selected in the document currently. Works both in single-caret state,
+ * multiple-caret selection and block-mode selection (for carets not having a selection, caret position is returned).
*
* @return the array of start offsets, or an array of 1 element if a range selection
* currently exists, or an empty array if no selection exists.
@@ -202,9 +235,8 @@
int[] getBlockSelectionStarts();
/**
- * Returns an array of end offsets in the document for line parts selected
- * in block selection mode. The size of the returned array is equal to the height
- * of the selected text block.
+ * Returns an array of end offsets in the document for line parts selected in the document currently. Works both in single-caret state,
+ * multiple-caret selection and block-mode selection (for carets not having a selection, caret position is returned).
*
* @return the array of end offsets, or an array of 1 element if a range selection
* currently exists, or an empty array if no selection exists.
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretEvent.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretEvent.java
index 5d37f95..8fcc3e0 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretEvent.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/CaretEvent.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,18 +15,26 @@
*/
package com.intellij.openapi.editor.event;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.EventObject;
public class CaretEvent extends EventObject {
+ private final Caret myCaret;
private final LogicalPosition myOldPosition;
private final LogicalPosition myNewPosition;
public CaretEvent(@NotNull Editor editor, @NotNull LogicalPosition oldPosition, @NotNull LogicalPosition newPosition) {
+ this(editor, null, oldPosition, newPosition);
+ }
+
+ public CaretEvent(@NotNull Editor editor, @Nullable Caret caret, @NotNull LogicalPosition oldPosition, @NotNull LogicalPosition newPosition) {
super(editor);
+ myCaret = caret;
myOldPosition = oldPosition;
myNewPosition = newPosition;
}
@@ -36,6 +44,11 @@
return (Editor) getSource();
}
+ @Nullable
+ public Caret getCaret() {
+ return myCaret;
+ }
+
@NotNull
public LogicalPosition getOldPosition() {
return myOldPosition;
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
new file mode 100644
index 0000000..0c225cf
--- /dev/null
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/event/MultipleCaretListener.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.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-api/src/com/intellij/openapi/editor/highlighter/EditorHighlighter.java b/platform/editor-ui-api/src/com/intellij/openapi/editor/highlighter/EditorHighlighter.java
index 14d1edd..a9737e5 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/editor/highlighter/EditorHighlighter.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/editor/highlighter/EditorHighlighter.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,10 +18,12 @@
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.event.DocumentListener;
+import org.jetbrains.annotations.NotNull;
public interface EditorHighlighter extends DocumentListener {
+ @NotNull
HighlighterIterator createIterator(int startOffset);
- void setText(CharSequence text);
- void setEditor(HighlighterClient editor);
- void setColorScheme(EditorColorsScheme scheme);
+ void setText(@NotNull CharSequence text);
+ void setEditor(@NotNull HighlighterClient editor);
+ void setColorScheme(@NotNull EditorColorsScheme scheme);
}
diff --git a/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java b/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java
index 2ae5243..0ca530b 100644
--- a/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.java
+++ b/platform/editor-ui-api/src/com/intellij/openapi/fileTypes/ContentBasedClassFileProcessor.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,17 +19,8 @@
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
-/**
- * Perfroms additional analyses on file with {@link com.intellij.openapi.fileTypes.StdFileTypes#CLASS} filetype (e. g. classfile,
- * compiled from other than Java source language).
- *
- * @author ilyas
- */
+/** @deprecated use com.intellij.psi.compiled.ClassFileDecompilers or com.intellij.psi.LanguageSubstitutors API (to remove in IDEA 14) */
public interface ContentBasedClassFileProcessor extends ContentBasedFileSubstitutor {
-
- /**
- * @return syntax highlighter for recognized classfile
- */
@NotNull
SyntaxHighlighter createHighlighter(Project project, VirtualFile vFile);
}
diff --git a/platform/editor-ui-ex/src/com/intellij/injected/editor/EditorWindow.java b/platform/editor-ui-ex/src/com/intellij/injected/editor/EditorWindow.java
new file mode 100644
index 0000000..e2d9712
--- /dev/null
+++ b/platform/editor-ui-ex/src/com/intellij/injected/editor/EditorWindow.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.injected.editor;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.util.UserDataHolderEx;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+
+public interface EditorWindow extends UserDataHolderEx, Editor {
+ boolean isValid();
+
+ @NotNull
+ PsiFile getInjectedFile();
+
+ @NotNull
+ LogicalPosition hostToInjected(@NotNull LogicalPosition hPos);
+
+ @NotNull
+ LogicalPosition injectedToHost(@NotNull LogicalPosition pos);
+
+ @NotNull
+ Editor getDelegate();
+
+ @NotNull
+ @Override
+ DocumentWindow getDocument();
+}
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 abe3790..b11ff74 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -157,7 +157,7 @@
}
@Override
- public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter) {
+ public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged) {
}
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
index f841300..e805d4c 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/colors/impl/AbstractColorsScheme.java
@@ -151,14 +151,15 @@
@Override
public void setEditorFontName(String fontName) {
+ int editorFontSize = getEditorFontSize();
myFontPreferences.clear();
- myFontPreferences.register(fontName, getEditorFontSize());
+ myFontPreferences.register(fontName, editorFontSize);
initFonts();
}
@Override
public void setEditorFontSize(int fontSize) {
- myFontPreferences.setSize(getEditorFontName(), fontSize);
+ myFontPreferences.register(getEditorFontName(), fontSize);
initFonts();
}
@@ -331,9 +332,8 @@
Element e = (Element)o;
String key = e.getAttributeValue(NAME_ATTR);
TextAttributesKey name = TextAttributesKey.find(key);
- TextAttributes attr = new TextAttributes();
Element value = e.getChild(VALUE_ELEMENT);
- attr.readExternal(value);
+ TextAttributes attr = new TextAttributes(value);
myAttributesMap.put(name, attr);
migrateErrorStripeColorFrom45(name, attr);
}
@@ -618,24 +618,24 @@
@Override
public void setConsoleFontName(String fontName) {
+ int consoleFontSize = getConsoleFontSize();
myConsoleFontPreferences.clear();
- myConsoleFontPreferences.register(fontName, getConsoleFontSize());
+ myConsoleFontPreferences.register(fontName, consoleFontSize);
}
@Override
public int getConsoleFontSize() {
String font = getConsoleFontName();
- if (!UISettings.getInstance().PRESENTATION_MODE && myConsoleFontPreferences.hasSize(font)) {
+ UISettings uiSettings = UISettings.getInstance();
+ if ((uiSettings == null || !uiSettings.PRESENTATION_MODE) && myConsoleFontPreferences.hasSize(font)) {
return myConsoleFontPreferences.getSize(font);
}
- else {
- return getEditorFontSize();
- }
+ return getEditorFontSize();
}
@Override
public void setConsoleFontSize(int fontSize) {
- myConsoleFontPreferences.setSize(getConsoleFontName(), fontSize);
+ myConsoleFontPreferences.register(getConsoleFontName(), fontSize);
initFonts();
}
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 e5cb4d3..284ef90 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -35,7 +35,7 @@
@Nullable
RangeHighlighter addPersistentLineHighlighter(int lineNumber, int layer, TextAttributes textAttributes);
- void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter);
+ void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged);
void fireAfterAdded(@NotNull RangeHighlighterEx segmentHighlighter);
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java
index 01612da..443e4fb 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/ex/util/LexerEditorHighlighter.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.
@@ -90,17 +90,18 @@
}
@Override
- public void setEditor(HighlighterClient editor) {
+ public void setEditor(@NotNull HighlighterClient editor) {
LOG.assertTrue(myEditor == null, "Highlighters cannot be reused with different editors");
myEditor = editor;
}
@Override
- public void setColorScheme(EditorColorsScheme scheme) {
+ public void setColorScheme(@NotNull EditorColorsScheme scheme) {
myScheme = scheme;
myAttributesMap.clear();
}
+ @NotNull
@Override
public HighlighterIterator createIterator(int startOffset) {
synchronized (this) {
@@ -287,7 +288,7 @@
}
@Override
- public void setText(CharSequence text) {
+ public void setText(@NotNull CharSequence text) {
synchronized (this) {
doSetText(text);
}
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 7c384f0..d9e5c4b 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
@@ -1,3 +1,18 @@
+/*
+ * 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.openapi.editor.impl;
import com.intellij.openapi.Disposable;
@@ -134,7 +149,7 @@
}
@Override
- public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter) {
+ public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged) {
}
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 311a7c8..36aa425 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
@@ -143,9 +143,9 @@
public void changeAttributesInBatch(@NotNull RangeHighlighterEx highlighter,
@NotNull Consumer<RangeHighlighterEx> changeAttributesAction) {
ApplicationManager.getApplication().assertIsDispatchThread();
- boolean changed = ((RangeHighlighterImpl)highlighter).changeAttributesNoEvents(changeAttributesAction);
- if (changed) {
- fireAttributesChanged(highlighter);
+ RangeHighlighterData.ChangeResult changed = ((RangeHighlighterImpl)highlighter).changeAttributesNoEvents(changeAttributesAction);
+ if (changed != RangeHighlighterData.ChangeResult.NOT_CHANGED) {
+ fireAttributesChanged(highlighter, changed == RangeHighlighterData.ChangeResult.RENDERERS_CHANGED);
}
}
@@ -216,9 +216,9 @@
}
@Override
- public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter) {
+ public void fireAttributesChanged(@NotNull RangeHighlighterEx segmentHighlighter, boolean renderersChanged) {
for (MarkupModelListener listener : myListeners) {
- listener.attributesChanged(segmentHighlighter);
+ listener.attributesChanged(segmentHighlighter, renderersChanged);
}
}
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java
index 4e3a0f6..b787c33 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterData.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -64,7 +64,8 @@
private static final int TARGET_AREA_IS_EXACT_FLAG = 2;
private static final int IN_BATCH_CHANGE_FLAG = 3;
private static final int CHANGED_FLAG = 4;
- @MagicConstant(intValues = {AFTER_END_OF_LINE_FLAG, ERROR_STRIPE_IS_THIN_FLAG, TARGET_AREA_IS_EXACT_FLAG, IN_BATCH_CHANGE_FLAG, CHANGED_FLAG})
+ private static final int RENDERERS_CHANGED_FLAG = 5;
+ @MagicConstant(intValues = {AFTER_END_OF_LINE_FLAG, ERROR_STRIPE_IS_THIN_FLAG, TARGET_AREA_IS_EXACT_FLAG, IN_BATCH_CHANGE_FLAG, CHANGED_FLAG, RENDERERS_CHANGED_FLAG})
@interface FlagConstant {}
private boolean isFlagSet(@FlagConstant int flag) {
@@ -90,7 +91,7 @@
TextAttributes old = myTextAttributes;
myTextAttributes = textAttributes;
if (!Comparing.equal(old, textAttributes)) {
- fireChanged();
+ fireChanged(false);
}
}
@@ -104,8 +105,11 @@
}
public void setLineMarkerRenderer(LineMarkerRenderer renderer) {
+ LineMarkerRenderer old = myLineMarkerRenderer;
myLineMarkerRenderer = renderer;
- fireChanged();
+ if (!Comparing.equal(old, renderer)) {
+ fireChanged(true);
+ }
}
public CustomHighlighterRenderer getCustomRenderer() {
@@ -113,7 +117,11 @@
}
public void setCustomRenderer(CustomHighlighterRenderer renderer) {
+ CustomHighlighterRenderer old = myCustomRenderer;
myCustomRenderer = renderer;
+ if (!Comparing.equal(old, renderer)) {
+ fireChanged(true);
+ }
}
public GutterIconRenderer getGutterIconRenderer() {
@@ -124,7 +132,7 @@
GutterMark old = myGutterIconRenderer;
myGutterIconRenderer = renderer;
if (!Comparing.equal(old, renderer)) {
- fireChanged();
+ fireChanged(true);
}
}
@@ -136,7 +144,7 @@
Color old = myErrorStripeColor;
myErrorStripeColor = color;
if (!Comparing.equal(old, color)) {
- fireChanged();
+ fireChanged(false);
}
}
@@ -149,7 +157,7 @@
Object old = myErrorStripeTooltip;
myErrorStripeTooltip = tooltipObject;
if (!Comparing.equal(old, tooltipObject)) {
- fireChanged();
+ fireChanged(false);
}
}
@@ -162,7 +170,7 @@
boolean old = isThinErrorStripeMark();
setFlag(ERROR_STRIPE_IS_THIN_FLAG, value);
if (old != value) {
- fireChanged();
+ fireChanged(false);
}
}
@@ -174,7 +182,7 @@
Color old = myLineSeparatorColor;
myLineSeparatorColor = color;
if (!Comparing.equal(old, color)) {
- fireChanged();
+ fireChanged(false);
}
}
@@ -186,13 +194,13 @@
SeparatorPlacement old = mySeparatorPlacement;
mySeparatorPlacement = placement;
if (!Comparing.equal(old, placement)) {
- fireChanged();
+ fireChanged(false);
}
}
public void setEditorFilter(@NotNull MarkupEditorFilter filter) {
myFilter = filter;
- fireChanged();
+ fireChanged(false);
}
@NotNull
@@ -208,17 +216,20 @@
boolean old = isAfterEndOfLine();
setFlag(AFTER_END_OF_LINE_FLAG, afterEndOfLine);
if (old != afterEndOfLine) {
- fireChanged();
+ fireChanged(false);
}
}
- private void fireChanged() {
+ private void fireChanged(boolean renderersChanged) {
if (myModel instanceof MarkupModelEx) {
if (isFlagSet(IN_BATCH_CHANGE_FLAG)) {
setFlag(CHANGED_FLAG, true);
+ if (renderersChanged) {
+ setFlag(RENDERERS_CHANGED_FLAG, true);
+ }
}
else {
- ((MarkupModelEx)myModel).fireAttributesChanged(getRangeHighlighter());
+ ((MarkupModelEx)myModel).fireAttributesChanged(getRangeHighlighter(), renderersChanged);
}
}
}
@@ -241,19 +252,24 @@
return Math.min(textLength, document.getLineEndOffset(document.getLineNumber(endOffset)) + 1);
}
- // returns true if change was detected
- boolean changeAttributesInBatch(@NotNull Consumer<RangeHighlighterEx> change) {
+ enum ChangeResult { NOT_CHANGED, MINOR_CHANGE, RENDERERS_CHANGED }
+ @NotNull
+ ChangeResult changeAttributesInBatch(@NotNull Consumer<RangeHighlighterEx> change) {
assert !isFlagSet(IN_BATCH_CHANGE_FLAG);
assert !isFlagSet(CHANGED_FLAG);
setFlag(IN_BATCH_CHANGE_FLAG, true);
- boolean result;
+ setFlag(RENDERERS_CHANGED_FLAG, false);
+ ChangeResult result;
try {
change.consume(getRangeHighlighter());
}
finally {
setFlag(IN_BATCH_CHANGE_FLAG, false);
- result = isFlagSet(CHANGED_FLAG);
+ boolean changed = isFlagSet(CHANGED_FLAG);
+ boolean renderersChanged = isFlagSet(RENDERERS_CHANGED_FLAG);
+ result = changed ? renderersChanged ? ChangeResult.RENDERERS_CHANGED : ChangeResult.MINOR_CHANGE : ChangeResult.NOT_CHANGED;
setFlag(CHANGED_FLAG, false);
+ setFlag(RENDERERS_CHANGED_FLAG, false);
}
return result;
}
@@ -263,7 +279,11 @@
}
public void setLineSeparatorRenderer(LineSeparatorRenderer renderer) {
+ LineSeparatorRenderer old = myLineSeparatorRenderer;
myLineSeparatorRenderer = renderer;
+ if (!Comparing.equal(old, renderer)) {
+ fireChanged(true);
+ }
}
public LineSeparatorRenderer getLineSeparatorRenderer() {
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java
index 0ad4c73..fe114fe 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/RangeHighlighterImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -86,7 +86,8 @@
getData().setTextAttributes(textAttributes);
}
- boolean changeAttributesNoEvents(@NotNull Consumer<RangeHighlighterEx> change) {
+ @NotNull
+ RangeHighlighterData.ChangeResult changeAttributesNoEvents(@NotNull Consumer<RangeHighlighterEx> change) {
return getData().changeAttributesInBatch(change);
}
diff --git a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/event/MarkupModelListener.java b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/event/MarkupModelListener.java
index b91757c..4e6074e 100644
--- a/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/event/MarkupModelListener.java
+++ b/platform/editor-ui-ex/src/com/intellij/openapi/editor/impl/event/MarkupModelListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,5 +25,5 @@
void afterAdded(@NotNull RangeHighlighterEx highlighter);
void beforeRemoved(@NotNull RangeHighlighterEx highlighter);
- void attributesChanged(@NotNull RangeHighlighterEx highlighter);
+ void attributesChanged(@NotNull RangeHighlighterEx highlighter, boolean renderersChanged);
}
diff --git a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java
index 2661e6a..febee0d 100644
--- a/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.java
+++ b/platform/editor-ui-ex/src/com/intellij/psi/impl/cache/impl/id/PlatformIdTableBuilding.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.
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointListener.java b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointListener.java
index 3dbebcf..ce7f01a 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointListener.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/ExtensionPointListener.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,15 @@
import org.jetbrains.annotations.Nullable;
public interface ExtensionPointListener<T> {
- void extensionAdded(@NotNull T extension, @Nullable final PluginDescriptor pluginDescriptor);
- void extensionRemoved(@NotNull T extension, @Nullable final PluginDescriptor pluginDescriptor);
+ void extensionAdded(@NotNull T extension, @Nullable PluginDescriptor pluginDescriptor);
+
+ void extensionRemoved(@NotNull T extension, @Nullable PluginDescriptor pluginDescriptor);
+
+ class Adapter<T> implements ExtensionPointListener<T> {
+ @Override
+ public void extensionAdded(@NotNull T extension, @Nullable PluginDescriptor pluginDescriptor) { }
+
+ @Override
+ public void extensionRemoved(@NotNull T extension, @Nullable PluginDescriptor pluginDescriptor) { }
+ }
}
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/LoadingOrder.java b/platform/extensions/src/com/intellij/openapi/extensions/LoadingOrder.java
index d9fd69d..0501568 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/LoadingOrder.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/LoadingOrder.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 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.GraphGenerator;
@@ -116,15 +117,19 @@
return new LoadingOrder(AFTER_STR + id);
}
- public static void sort(final Orderable[] orderables) {
- // our graph is pretty sparse so do benefit from the fact
- final Map<String,Orderable> map = new HashMap<String, Orderable>();
- final HashMap<Orderable, LoadingOrder> cachedMap = new HashMap<Orderable, LoadingOrder>(orderables.length);
- final HashSet<Orderable> first = new HashSet<Orderable>(1);
- final HashSet<Orderable> hasBefore = new HashSet<Orderable>(orderables.length);
+ public static void sort(@NotNull Orderable... orderable) {
+ sort(Arrays.asList(orderable));
+ }
- for(Orderable o:orderables) {
- final String id = o.getOrderId();
+ public static void sort(@NotNull final List<? extends Orderable> orderable) {
+ // our graph is pretty sparse so do benefit from the fact
+ final Map<String, Orderable> map = ContainerUtil.newHashMap();
+ final Map<Orderable, LoadingOrder> cachedMap = ContainerUtil.newHashMap();
+ final Set<Orderable> first = ContainerUtil.newHashSet(1);
+ final Set<Orderable> hasBefore = ContainerUtil.newHashSet(orderable.size());
+
+ for (Orderable o : orderable) {
+ String id = o.getOrderId();
if (StringUtil.isNotEmpty(id)) map.put(id, o);
LoadingOrder order = o.getOrder();
cachedMap.put(o, order);
@@ -132,61 +137,61 @@
if (order.myBefore.size() != 0) hasBefore.add(o);
}
- DFSTBuilder<Orderable> builder = new DFSTBuilder<Orderable>(new GraphGenerator<Orderable>(new CachingSemiGraph<Orderable>(new GraphGenerator.SemiGraph<Orderable>() {
+ GraphGenerator.SemiGraph<Orderable> graph = new GraphGenerator.SemiGraph<Orderable>() {
@Override
public Collection<Orderable> getNodes() {
- final ArrayList<Orderable> list = new ArrayList<Orderable>(Arrays.asList(orderables));
+ List<Orderable> list = ContainerUtil.newArrayList(orderable);
Collections.reverse(list);
return list;
}
@Override
- public Iterator<Orderable> getIn(final Orderable n) {
- final LoadingOrder order = cachedMap.get(n);
+ public Iterator<Orderable> getIn(Orderable n) {
+ LoadingOrder order = cachedMap.get(n);
Set<Orderable> predecessors = new LinkedHashSet<Orderable>();
- for (final String id : order.myAfter) {
- final Orderable orderable = map.get(id);
- if (orderable != null) {
- predecessors.add(orderable);
+ for (String id : order.myAfter) {
+ Orderable o = map.get(id);
+ if (o != null) {
+ predecessors.add(o);
}
}
String id = n.getOrderId();
if (StringUtil.isNotEmpty(id)) {
- for (final Orderable orderable : hasBefore) {
- final LoadingOrder hisOrder = cachedMap.get(orderable);
+ for (Orderable o : hasBefore) {
+ LoadingOrder hisOrder = cachedMap.get(o);
if (hisOrder.myBefore.contains(id)) {
- predecessors.add(orderable);
+ predecessors.add(o);
}
}
}
if (order.myLast) {
- for (final Orderable orderable : orderables) {
- final LoadingOrder hisOrder = cachedMap.get(orderable);
+ for (Orderable o : orderable) {
+ LoadingOrder hisOrder = cachedMap.get(o);
if (!hisOrder.myLast) {
- predecessors.add(orderable);
+ predecessors.add(o);
}
}
}
if (!order.myFirst) {
- for(Orderable orderable:first) {
- predecessors.add(orderable);
- }
+ predecessors.addAll(first);
}
return predecessors.iterator();
}
- })));
+ };
+
+ DFSTBuilder<Orderable> builder = new DFSTBuilder<Orderable>(new GraphGenerator<Orderable>(new CachingSemiGraph<Orderable>(graph)));
if (!builder.isAcyclic()) {
- final Pair<Orderable,Orderable> dependency = builder.getCircularDependency();
- throw new SortingException("Could not satisfy sorting requirements", new Element[]{dependency.first.getDescribingElement(), dependency.second.getDescribingElement()});
+ Pair<Orderable, Orderable> p = builder.getCircularDependency();
+ throw new SortingException("Could not satisfy sorting requirements", p.first.getDescribingElement(), p.second.getDescribingElement());
}
- Arrays.sort(orderables, builder.comparator());
+ Collections.sort(orderable, builder.comparator());
}
public static LoadingOrder readOrder(@NonNls String orderAttr) {
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/PluginId.java b/platform/extensions/src/com/intellij/openapi/extensions/PluginId.java
index 15beeb6..84fba8f 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/PluginId.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/PluginId.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.
@@ -36,7 +36,7 @@
}
@Override
- public int compareTo(PluginId o) {
+ public int compareTo(@NotNull PluginId o) {
return myIdString.compareTo(o.myIdString);
}
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/SortingException.java b/platform/extensions/src/com/intellij/openapi/extensions/SortingException.java
index b7e2c01..92ea1f2 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/SortingException.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/SortingException.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,7 +25,7 @@
public class SortingException extends RuntimeException {
private final Element[] myConflictingElements;
- public SortingException(String message, Element[] conflictingElements) {
+ public SortingException(String message, Element... conflictingElements) {
super(message + ": " + StringUtil.join(conflictingElements, new Function<Element, String>() {
@Override
public String fun(Element element) {
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java
index 51fb0d6..ed32ff4 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionComponentAdapter.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,6 +40,7 @@
private final boolean myDeserializeInstance;
private ComponentAdapter myDelegate;
private Class myImplementationClass;
+ private boolean myNotificationSent = false;
public ExtensionComponentAdapter(@NotNull String implementationClass,
Element extensionElement,
@@ -155,7 +156,7 @@
if (classLoader == null) {
classLoader = getClass().getClassLoader();
}
- myImplementationClass = Class.forName(className, true, classLoader);
+ myImplementationClass = Class.forName(className, false, classLoader);
}
catch (ClassNotFoundException e) {
throw new RuntimeException(e);
@@ -182,4 +183,12 @@
public String getAssignableToClassName() {
return myImplementationClassName;
}
+
+ public boolean isNotificationSent() {
+ return myNotificationSent;
+ }
+
+ public void setNotificationSent(boolean notificationSent) {
+ myNotificationSent = notificationSent;
+ }
}
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
index 7cf52a4..2ae5822 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionPointImpl.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,8 +19,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.*;
import com.intellij.openapi.util.Disposer;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.ArrayUtilRt;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.StringInterner;
import org.jdom.Element;
@@ -36,6 +34,7 @@
/**
* @author AKireyev
*/
+@SuppressWarnings("SynchronizeOnThis")
public class ExtensionPointImpl<T> implements ExtensionPoint<T> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.extensions.impl.ExtensionPointImpl");
@@ -121,8 +120,7 @@
public synchronized void registerExtension(@NotNull T extension, @NotNull LoadingOrder order) {
assert myExtensions.size() == myLoadedAdapters.size();
- ObjectComponentAdapter adapter = new ObjectComponentAdapter(extension, order);
- assertClass(extension.getClass());
+ ExtensionComponentAdapter adapter = new ObjectComponentAdapter(extension, order);
if (LoadingOrder.ANY == order) {
int index = myLoadedAdapters.size();
@@ -132,34 +130,45 @@
index--;
}
}
- internalRegisterExtension(extension, adapter, index, true);
+ registerExtension(extension, adapter, index, true);
}
else {
- myExtensionAdapters.add(adapter);
+ registerExtensionAdapter(adapter);
processAdapters();
}
- clearCache();
}
- private void internalRegisterExtension(@NotNull T extension, @NotNull ExtensionComponentAdapter adapter, int index, boolean runNotifications) {
+ private void registerExtension(@NotNull T extension, @NotNull ExtensionComponentAdapter adapter, int index, boolean runNotifications) {
if (myExtensions.contains(extension)) {
myLogger.error("Extension was already added: " + extension);
return;
}
+
+ Class<T> extensionClass = getExtensionClass();
+ if (!extensionClass.isInstance(extension)) {
+ myLogger.error("Extension " + extension.getClass() + " does not implement " + extensionClass);
+ return;
+ }
+
myExtensions.add(index, extension);
myLoadedAdapters.add(index, adapter);
- if (runNotifications) {
- if (extension instanceof Extension) {
- try {
- ((Extension)extension).extensionAdded(this);
- }
- catch (Throwable e) {
- myLogger.error(e);
- }
- }
+ if (runNotifications) {
clearCache();
- notifyListenersOnAdd(extension, adapter.getPluginDescriptor());
+
+ if (!adapter.isNotificationSent()) {
+ if (extension instanceof Extension) {
+ try {
+ ((Extension)extension).extensionAdded(this);
+ }
+ catch (Throwable e) {
+ myLogger.error(e);
+ }
+ }
+
+ notifyListenersOnAdd(extension, adapter.getPluginDescriptor());
+ adapter.setNotificationSent(true);
+ }
}
}
@@ -183,6 +192,7 @@
result = myExtensionsCache;
if (result == null) {
processAdapters();
+
Class<T> extensionClass = getExtensionClass();
@SuppressWarnings("unchecked") T[] a = (T[])Array.newInstance(extensionClass, myExtensions.size());
result = myExtensions.toArray(a);
@@ -196,12 +206,6 @@
" getExtensionClass(): " + extensionClass + ";\n" +
" size:" + myExtensions.size() + ";" + result.length);
}
-
- if (!extensionClass.isAssignableFrom(t.getClass())) {
- LOG.error("Extension '" + t.getClass() + "' must be an instance of '" + extensionClass + "'",
- new ExtensionException(t.getClass()));
- result = ArrayUtil.remove(result, i); // we assume that usually all extensions are OK
- }
}
myExtensionsCache = result;
@@ -225,29 +229,22 @@
private void processAdapters() {
int totalSize = myExtensionAdapters.size() + myLoadedAdapters.size();
if (totalSize != 0) {
- List<ExtensionComponentAdapter> allAdapters = new ArrayList<ExtensionComponentAdapter>(totalSize);
- allAdapters.addAll(myExtensionAdapters);
- allAdapters.addAll(myLoadedAdapters);
-
- myExtensions.clear();
- ExtensionComponentAdapter[] loadedAdapters = myLoadedAdapters.isEmpty()
- ? ExtensionComponentAdapter.EMPTY_ARRAY
- : myLoadedAdapters.toArray(new ExtensionComponentAdapter[myLoadedAdapters.size()]);
- myLoadedAdapters.clear();
- ExtensionComponentAdapter[] adapters = allAdapters.toArray(new ExtensionComponentAdapter[myExtensionAdapters.size()]);
+ List<ExtensionComponentAdapter> adapters = ContainerUtil.newArrayListWithCapacity(totalSize);
+ adapters.addAll(myExtensionAdapters);
+ adapters.addAll(myLoadedAdapters);
LoadingOrder.sort(adapters);
- final List<T> extensions = new ArrayList<T>(adapters.length);
+ myExtensionAdapters.clear();
+ myExtensionAdapters.addAll(adapters);
+
+ Set<ExtensionComponentAdapter> loaded = ContainerUtil.newHashOrEmptySet(myLoadedAdapters);
+ myExtensions.clear();
+ myLoadedAdapters.clear();
+
for (ExtensionComponentAdapter adapter : adapters) {
@SuppressWarnings("unchecked") T extension = (T)adapter.getExtension();
- assertClass(extension.getClass());
- extensions.add(extension);
+ registerExtension(extension, adapter, myExtensions.size(), !loaded.contains(adapter));
+ myExtensionAdapters.remove(adapter);
}
-
- for (int i = 0; i < extensions.size(); i++) {
- T extension = extensions.get(i);
- internalRegisterExtension(extension, adapters[i], myExtensions.size(), ArrayUtilRt.find(loadedAdapters, adapters[i]) == -1);
- }
- myExtensionAdapters.clear();
}
}
@@ -255,9 +252,7 @@
@Nullable
public T getExtension() {
T[] extensions = getExtensions();
- if (extensions.length == 0) return null;
-
- return extensions[0];
+ return extensions.length == 0 ? null : extensions[0];
}
@Override
@@ -271,13 +266,14 @@
final int index = getExtensionIndex(extension);
final ExtensionComponentAdapter adapter = myLoadedAdapters.get(index);
- myOwner.getMutablePicoContainer().unregisterComponent(adapter.getComponentKey());
- final MutablePicoContainer[] pluginContainers = myOwner.getPluginContainers();
- for (MutablePicoContainer pluginContainer : pluginContainers) {
- pluginContainer.unregisterComponent(adapter.getComponentKey());
+ Object key = adapter.getComponentKey();
+ myOwner.getMutablePicoContainer().unregisterComponent(key);
+ for (MutablePicoContainer pluginContainer : myOwner.getPluginContainers()) {
+ pluginContainer.unregisterComponent(key);
}
+
processAdapters();
- internalUnregisterExtension(extension, null);
+ unregisterExtension(extension, null);
}
private int getExtensionIndex(@NotNull T extension) {
@@ -288,20 +284,18 @@
return i;
}
- private void internalUnregisterExtension(@NotNull T extension, PluginDescriptor pluginDescriptor) {
+ private void unregisterExtension(@NotNull T extension, PluginDescriptor pluginDescriptor) {
int index = getExtensionIndex(extension);
+
myExtensions.remove(index);
-
myLoadedAdapters.remove(index);
-
clearCache();
notifyListenersOnRemove(extension, pluginDescriptor);
if (extension instanceof Extension) {
- Extension o = (Extension)extension;
try {
- o.extensionRemoved(this);
+ ((Extension)extension).extensionRemoved(this);
}
catch (Throwable e) {
myLogger.error(e);
@@ -321,13 +315,22 @@
}
@Override
+ public void addExtensionPointListener(@NotNull final ExtensionPointListener<T> listener, @NotNull Disposable parentDisposable) {
+ addExtensionPointListener(listener, true, parentDisposable);
+ }
+
public synchronized void addExtensionPointListener(@NotNull final ExtensionPointListener<T> listener,
- @NotNull Disposable parentDisposable) {
- addExtensionPointListener(listener);
+ final boolean invokeForLoadedExtensions,
+ @NotNull Disposable parentDisposable) {
+ if (invokeForLoadedExtensions) {
+ addExtensionPointListener(listener);
+ } else {
+ myEPListeners.add(listener);
+ }
Disposer.register(parentDisposable, new Disposable() {
@Override
public void dispose() {
- removeExtensionPointListener(listener);
+ removeExtensionPointListener(listener, invokeForLoadedExtensions);
}
});
}
@@ -349,19 +352,22 @@
}
@Override
- public synchronized void removeExtensionPointListener(@NotNull ExtensionPointListener<T> listener) {
- for (ExtensionComponentAdapter componentAdapter : myLoadedAdapters.toArray(new ExtensionComponentAdapter[myLoadedAdapters.size()])) {
- try {
- @SuppressWarnings("unchecked") T extension = (T)componentAdapter.getExtension();
- listener.extensionRemoved(extension, componentAdapter.getPluginDescriptor());
- }
- catch (Throwable e) {
- myLogger.error(e);
+ public void removeExtensionPointListener(@NotNull ExtensionPointListener<T> listener) {
+ removeExtensionPointListener(listener, true);
+ }
+
+ private synchronized void removeExtensionPointListener(@NotNull ExtensionPointListener<T> listener, boolean invokeForLoadedExtensions) {
+ if (myEPListeners.remove(listener) && invokeForLoadedExtensions) {
+ for (ExtensionComponentAdapter componentAdapter : myLoadedAdapters.toArray(new ExtensionComponentAdapter[myLoadedAdapters.size()])) {
+ try {
+ @SuppressWarnings("unchecked") T extension = (T)componentAdapter.getExtension();
+ listener.extensionRemoved(extension, componentAdapter.getPluginDescriptor());
+ }
+ catch (Throwable e) {
+ myLogger.error(e);
+ }
}
}
-
- boolean success = myEPListeners.remove(listener);
- assert success;
}
@Override
@@ -403,30 +409,24 @@
clearCache();
}
- private void assertClass(@NotNull Class<?> extensionClass) {
- Class<T> expectedClass = getExtensionClass();
- assert expectedClass.isAssignableFrom(extensionClass) : "Expected: " + expectedClass + "; Actual: " + extensionClass;
- }
-
private void clearCache() {
myExtensionsCache = null;
}
- synchronized boolean unregisterComponentAdapter(@NotNull ExtensionComponentAdapter componentAdapter) {
+ synchronized boolean unregisterExtensionAdapter(@NotNull ExtensionComponentAdapter adapter) {
try {
- if (myExtensionAdapters.remove(componentAdapter)) {
+ if (myExtensionAdapters.remove(adapter)) {
return true;
}
- if (myLoadedAdapters.contains(componentAdapter)) {
- final Object componentKey = componentAdapter.getComponentKey();
- myOwner.getMutablePicoContainer().unregisterComponent(componentKey);
- final MutablePicoContainer[] pluginContainers = myOwner.getPluginContainers();
- for (MutablePicoContainer pluginContainer : pluginContainers) {
- pluginContainer.unregisterComponent(componentKey);
+ if (myLoadedAdapters.contains(adapter)) {
+ Object key = adapter.getComponentKey();
+ myOwner.getMutablePicoContainer().unregisterComponent(key);
+ for (MutablePicoContainer pluginContainer : myOwner.getPluginContainers()) {
+ pluginContainer.unregisterComponent(key);
}
- @SuppressWarnings("unchecked") T extension = (T)componentAdapter.getExtension();
- internalUnregisterExtension(extension, componentAdapter.getPluginDescriptor());
+ @SuppressWarnings("unchecked") T extension = (T)adapter.getExtension();
+ unregisterExtension(extension, adapter.getPluginDescriptor());
return true;
}
return false;
@@ -450,7 +450,7 @@
private final LoadingOrder myLoadingOrder;
private ObjectComponentAdapter(@NotNull Object extension, @NotNull LoadingOrder loadingOrder) {
- super(Object.class.getName(), null, null, null, false);
+ super(extension.getClass().getName(), null, null, null, false);
myExtension = extension;
myLoadingOrder = loadingOrder;
}
diff --git a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
index 9579c61..0b88912 100644
--- a/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.java
+++ b/platform/extensions/src/com/intellij/openapi/extensions/impl/ExtensionsAreaImpl.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.
@@ -229,7 +229,7 @@
}
ExtensionComponentAdapter adapter = myExtensionElement2extension.remove(extensionElement);
if (adapter == null) return;
- if (getExtensionPoint(epName).unregisterComponentAdapter(adapter)) {
+ if (getExtensionPoint(epName).unregisterExtensionAdapter(adapter)) {
MutablePicoContainer pluginContainer = internalGetPluginContainer();
pluginContainer.unregisterComponent(adapter.getComponentKey());
}
diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java
index d39b9a3..e7a7e29 100644
--- a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.java
+++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/ExtensionPointImplTest.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,30 +16,41 @@
package com.intellij.openapi.extensions.impl;
import com.intellij.openapi.extensions.*;
-import junit.framework.TestCase;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.After;
+import org.junit.Test;
import org.picocontainer.defaults.DefaultPicoContainer;
+import java.util.List;
+
+import static com.intellij.openapi.extensions.impl.ExtensionComponentAdapterTest.readElement;
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
/**
* @author AKireyev
*/
-public class ExtensionPointImplTest extends TestCase {
+public class ExtensionPointImplTest {
+ private static final TestLogProvider ourTestLog = new TestLogProvider();
+
+ @After
+ public void tearDown() throws Exception {
+ ourTestLog.errors();
+ }
+
+ @Test
public void testCreate() {
- ExtensionPointImpl extensionPoint = buildExtensionPoint();
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
assertEquals(ExtensionsImplTest.EXTENSION_POINT_NAME_1, extensionPoint.getName());
assertEquals(Integer.class.getName(), extensionPoint.getClassName());
}
- private ExtensionPointImpl buildExtensionPoint() {
- return new ExtensionPointImpl(ExtensionsImplTest.EXTENSION_POINT_NAME_1, Integer.class.getName(), ExtensionPoint.Kind.INTERFACE, buildExtensionArea(), null, new Extensions.SimpleLogProvider(), new UndefinedPluginDescriptor());
- }
-
- private ExtensionsAreaImpl buildExtensionArea() {
- return new ExtensionsAreaImpl(new DefaultPicoContainer(), new Extensions.SimpleLogProvider());
- }
-
+ @Test
public void testUnregisterObject() {
- ExtensionPointImpl extensionPoint = buildExtensionPoint();
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
extensionPoint.registerExtension(new Integer(123));
Object[] extensions = extensionPoint.getExtensions();
assertEquals(1, extensions.length);
@@ -48,10 +59,12 @@
assertEquals(0, extensions.length);
}
- public void testRegisterUnregister_Extension() {
-
+ @Test
+ public void testRegisterUnregisterExtension() {
final AreaInstance area = new AreaInstance() {};
- final ExtensionPointImpl extensionPoint = new ExtensionPointImpl("an.extension.point", Object.class.getName(), ExtensionPoint.Kind.INTERFACE, buildExtensionArea(), area, new Extensions.SimpleLogProvider(), new UndefinedPluginDescriptor());
+ final ExtensionPoint<Object> extensionPoint = new ExtensionPointImpl<Object>(
+ "an.extension.point", Object.class.getName(), ExtensionPoint.Kind.INTERFACE, buildExtensionArea(), area,
+ ourTestLog, new UndefinedPluginDescriptor());
final boolean[] flags = new boolean[2];
Extension extension = new Extension() {
@@ -71,24 +84,26 @@
};
extensionPoint.registerExtension(extension);
- assertTrue("Registratioon call is missed", flags[0]);
+ assertTrue("Register call is missed", flags[0]);
assertFalse(flags[1]);
extensionPoint.unregisterExtension(extension);
- assertTrue("UnRegistratioon call is missed", flags[1]);
+ assertTrue("Unregister call is missed", flags[1]);
}
+ @Test
public void testRegisterObject() {
- ExtensionPointImpl extensionPoint = buildExtensionPoint();
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
extensionPoint.registerExtension(new Integer(123));
Object[] extensions = extensionPoint.getExtensions();
assertEquals("One extension", 1, extensions.length);
- assertEquals("Correct type", Integer[].class, extensions.getClass());
+ assertSame("Correct type", Integer[].class, extensions.getClass());
assertEquals("Correct object", new Integer(123), extensions[0]);
}
+ @Test
public void testRegistrationOrder() {
- ExtensionPointImpl extensionPoint = buildExtensionPoint();
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
extensionPoint.registerExtension(new Integer(123));
extensionPoint.registerExtension(new Integer(321), LoadingOrder.FIRST);
Object[] extensions = extensionPoint.getExtensions();
@@ -96,18 +111,19 @@
assertEquals("Correct object", new Integer(321), extensions[0]);
}
+ @Test
public void testListener() {
- ExtensionPointImpl extensionPoint = buildExtensionPoint();
- final boolean added[] = new boolean[1];
- final boolean removed[] = new boolean[1];
- extensionPoint.addExtensionPointListener(new ExtensionPointListener() {
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
+ final boolean[] added = new boolean[1];
+ final boolean[] removed = new boolean[1];
+ extensionPoint.addExtensionPointListener(new ExtensionPointListener<Integer>() {
@Override
- public void extensionAdded(@NotNull Object extension, final PluginDescriptor pluginDescriptor) {
+ public void extensionAdded(@NotNull Integer extension, final PluginDescriptor pluginDescriptor) {
added[0] = true;
}
@Override
- public void extensionRemoved(@NotNull Object extension, final PluginDescriptor pluginDescriptor) {
+ public void extensionRemoved(@NotNull Integer extension, final PluginDescriptor pluginDescriptor) {
removed[0] = true;
}
});
@@ -122,21 +138,146 @@
assertTrue(removed[0]);
}
+ @Test
public void testLateListener() {
- ExtensionPointImpl extensionPoint = buildExtensionPoint();
- final boolean added[] = new boolean[1];
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
+ final boolean[] added = new boolean[1];
extensionPoint.registerExtension(new Integer(123));
assertFalse(added[0]);
- extensionPoint.addExtensionPointListener(new ExtensionPointListener() {
+ extensionPoint.addExtensionPointListener(new ExtensionPointListener<Integer>() {
@Override
- public void extensionAdded(@NotNull Object extension, final PluginDescriptor pluginDescriptor) {
+ public void extensionAdded(@NotNull Integer extension, final PluginDescriptor pluginDescriptor) {
added[0] = true;
}
@Override
- public void extensionRemoved(@NotNull Object extension, final PluginDescriptor pluginDescriptor) {
+ public void extensionRemoved(@NotNull Integer extension, final PluginDescriptor pluginDescriptor) {
}
});
assertTrue(added[0]);
}
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testIncompatibleExtension() {
+ ExtensionPoint extensionPoint = buildExtensionPoint(Integer.class);
+
+ extensionPoint.registerExtension(new Double(0));
+ assertThat(ourTestLog.errors(), hasSize(1));
+
+ assertThat(extensionPoint.getExtensions(), emptyArray());
+ assertThat(ourTestLog.errors(), empty());
+
+ extensionPoint.registerExtension(new Integer(0));
+ assertThat(extensionPoint.getExtensions(), arrayWithSize(1));
+ assertThat(ourTestLog.errors(), empty());
+ }
+
+ @Test
+ public void testIncompatibleAdapter() {
+ ExtensionPoint<Integer> extensionPoint = buildExtensionPoint(Integer.class);
+
+ ((ExtensionPointImpl)extensionPoint).registerExtensionAdapter(buildAdapter());
+ assertThat(ourTestLog.errors(), empty());
+
+ assertThat(extensionPoint.getExtensions(), emptyArray());
+ assertThat(ourTestLog.errors(), hasSize(1));
+
+ extensionPoint.registerExtension(new Integer(0));
+ assertThat(extensionPoint.getExtensions(), arrayWithSize(1));
+ assertThat(ourTestLog.errors(), empty());
+ }
+
+ @Test
+ public void testCancelledRegistration() {
+ ExtensionPoint<String> extensionPoint = buildExtensionPoint(String.class);
+ MyShootingComponentAdapter adapter = buildAdapter();
+
+ extensionPoint.registerExtension("first");
+ assertThat(extensionPoint.getExtensions(), arrayWithSize(1));
+ assertThat(ourTestLog.errors(), empty());
+
+ extensionPoint.registerExtension("second", LoadingOrder.FIRST); // registers a wrapping adapter
+ ((ExtensionPointImpl)extensionPoint).registerExtensionAdapter(adapter);
+ adapter.setFire(true);
+ try {
+ extensionPoint.getExtensions();
+ fail("PCE expected");
+ }
+ catch (ProcessCanceledException ignored) { }
+ assertThat(ourTestLog.errors(), empty());
+
+ adapter.setFire(false);
+ assertThat(extensionPoint.getExtensions(), arrayContaining("second", "", "first"));
+ assertThat(ourTestLog.errors(), empty());
+ }
+
+ @Test
+ public void testListenerNotifications() {
+ ExtensionPoint<String> extensionPoint = buildExtensionPoint(String.class);
+ final List<String> extensions = ContainerUtil.newArrayList();
+ extensionPoint.addExtensionPointListener(new ExtensionPointListener.Adapter<String>() {
+ @Override
+ public void extensionAdded(@NotNull String extension, @Nullable PluginDescriptor pluginDescriptor) {
+ extensions.add(extension);
+ }
+ });
+ MyShootingComponentAdapter adapter = buildAdapter();
+
+ extensionPoint.registerExtension("first");
+ assertThat(extensions, contains("first"));
+ assertThat(ourTestLog.errors(), empty());
+
+ extensionPoint.registerExtension("second", LoadingOrder.FIRST);
+ ((ExtensionPointImpl)extensionPoint).registerExtensionAdapter(adapter);
+ adapter.setFire(true);
+ try {
+ extensionPoint.getExtensions();
+ fail("PCE expected");
+ }
+ catch (ProcessCanceledException ignored) { }
+ assertThat(extensions, contains("first", "second"));
+ assertThat(ourTestLog.errors(), empty());
+
+ adapter.setFire(false);
+ extensionPoint.getExtensions();
+ assertThat(extensions, contains("first", "second", ""));
+ assertThat(ourTestLog.errors(), empty());
+ }
+
+ private static <T> ExtensionPoint<T> buildExtensionPoint(Class<T> aClass) {
+ return new ExtensionPointImpl<T>(
+ ExtensionsImplTest.EXTENSION_POINT_NAME_1, aClass.getName(), ExtensionPoint.Kind.INTERFACE,
+ buildExtensionArea(), null, ourTestLog, new UndefinedPluginDescriptor());
+ }
+
+ private static ExtensionsAreaImpl buildExtensionArea() {
+ return new ExtensionsAreaImpl(new DefaultPicoContainer(), ourTestLog);
+ }
+
+ private static MyShootingComponentAdapter buildAdapter() {
+ return new MyShootingComponentAdapter(String.class.getName());
+ }
+
+ private static class MyShootingComponentAdapter extends ExtensionComponentAdapter {
+ private boolean myFire = false;
+
+ public MyShootingComponentAdapter(@NotNull String implementationClass) {
+ super(implementationClass, readElement("<bean/>"), new DefaultPicoContainer(), new DefaultPluginDescriptor("test"), false);
+ }
+
+ public void setFire(boolean fire) {
+ myFire = fire;
+ }
+
+ @Override
+ public Object getExtension() {
+ if (myFire) {
+ throw new ProcessCanceledException();
+ }
+ else {
+ return super.getExtension();
+ }
+ }
+ }
}
diff --git a/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/TestLogProvider.java b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/TestLogProvider.java
new file mode 100644
index 0000000..ec8febd
--- /dev/null
+++ b/platform/extensions/testSrc/com/intellij/openapi/extensions/impl/TestLogProvider.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.extensions.impl;
+
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.util.ExceptionUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public class TestLogProvider extends Extensions.SimpleLogProvider {
+ private final List<String> errors = ContainerUtil.newSmartList();
+
+ @Override
+ public void error(String message) {
+ errors.add(message);
+ }
+
+ @Override
+ public void error(String message, @NotNull Throwable t) {
+ errors.add(message + "\n" + ExceptionUtil.getThrowableText(t));
+ }
+
+ @Override
+ public void error(@NotNull Throwable t) {
+ errors.add(ExceptionUtil.getThrowableText(t));
+ }
+
+ @NotNull
+ public List<String> errors() {
+ List<String> copy = ContainerUtil.newArrayList(errors);
+ errors.clear();
+ return copy;
+ }
+}
diff --git a/platform/external-system-api/external-system-api.iml b/platform/external-system-api/external-system-api.iml
index 8df6aab..ac3b9ed 100644
--- a/platform/external-system-api/external-system-api.iml
+++ b/platform/external-system-api/external-system-api.iml
@@ -9,10 +9,10 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="annotations" exported="" />
- <orderEntry type="module" module-name="util" exported="" />
- <orderEntry type="module" module-name="projectModel-api" exported="" />
- <orderEntry type="module" module-name="platform-api" exported="" />
- <orderEntry type="module" module-name="lang-api" exported="" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="module" module-name="projectModel-api" />
+ <orderEntry type="module" module-name="platform-api" />
+ <orderEntry type="module" module-name="lang-api" />
</component>
</module>
diff --git a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties
index 9872721..e195238 100644
--- a/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties
+++ b/platform/external-system-api/resources/i18n/ExternalSystemBundle.properties
@@ -10,6 +10,7 @@
setting.type.location.explicit.correct={0} location is defined
setting.type.location.explicit.incorrect={0} location is incorrect
settings.label.select.project={0} project:
+settings.label.project.format=Project format:
settings.label.use.auto.import=Use auto-import
settings.label.create.empty.content.root.directories=Create directories for empty content roots automatically
settings.title.linked.projects=Linked {0} projects
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java
index 9fb2ea6..61586e1 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/model/project/ExternalProjectBuildClasspathPojo.java
@@ -99,4 +99,4 @@
public String toString() {
return myName;
}
-}
+}
\ No newline at end of file
diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java
index 0142b82..89cc9d8 100644
--- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java
+++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/util/ExternalSystemBundle.java
@@ -1,6 +1,22 @@
+/*
+ * 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.openapi.externalSystem.util;
import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
@@ -9,15 +25,14 @@
*/
public class ExternalSystemBundle extends AbstractBundle {
- public static final String PATH_TO_BUNDLE = "i18n.ExternalSystemBundle";
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return BUNDLE.getMessage(key, params);
+ }
+ public static final String PATH_TO_BUNDLE = "i18n.ExternalSystemBundle";
private static final ExternalSystemBundle BUNDLE = new ExternalSystemBundle();
public ExternalSystemBundle() {
super(PATH_TO_BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
- return BUNDLE.getMessage(key, params);
- }
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java
index edf4fee..83a010b 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/ExternalSystemFacadeManager.java
@@ -145,6 +145,11 @@
}
}
+ public ExternalSystemCommunicationManager getCommunicationManager(@NotNull ProjectSystemId externalSystemId) {
+ final boolean currentInProcess = ExternalSystemApiUtil.isInProcessMode(externalSystemId);
+ return currentInProcess ? myInProcessCommunicationManager : myRemoteCommunicationManager;
+ }
+
@SuppressWarnings("ConstantConditions")
@NotNull
private RemoteExternalSystemFacade doGetFacade(@NotNull IntegrationKey key, @NotNull Project project) throws Exception {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java
index 18e84d2..90ca62f 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/execution/ExternalSystemTaskRunner.java
@@ -48,10 +48,10 @@
@Nullable
@Override
- protected RunContentDescriptor doExecute(Project project,
- RunProfileState state,
+ protected RunContentDescriptor doExecute(@NotNull Project project,
+ @NotNull RunProfileState state,
RunContentDescriptor contentToReuse,
- ExecutionEnvironment env) throws ExecutionException
+ @NotNull ExecutionEnvironment env) throws ExecutionException
{
ExecutionResult executionResult = state.execute(env.getExecutor(), this);
if (executionResult == null) return null;
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemProcessingManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemProcessingManager.java
index 7e103cf..dc9f6ef 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemProcessingManager.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/internal/ExternalSystemProcessingManager.java
@@ -7,9 +7,12 @@
import com.intellij.openapi.externalSystem.service.ExternalSystemFacadeManager;
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
import com.intellij.util.Alarm;
+import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
+import com.intellij.util.containers.Convertor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java
index 05c1d72..f8fc059 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/LibraryDependencyDataService.java
@@ -125,7 +125,7 @@
if (!libraryData.isUnresolved()) {
Set<String> paths = ContainerUtilRt.newHashSet();
for (String path : libraryData.getPaths(LibraryPathType.BINARY)) {
- paths.add(ExternalSystemApiUtil.toCanonicalPath(path));
+ paths.add(ExternalSystemApiUtil.toCanonicalPath(path) + dependencyData.getScope().name());
}
moduleLibrariesToImport.put(paths, dependencyData);
toImport.add(dependencyData);
@@ -162,16 +162,19 @@
@NotNull LibraryTable libraryTable,
@NotNull Module module)
{
- for (LibraryDependencyData dependencyData : toImport) {
- LibraryData libraryData = dependencyData.getTarget();
- String libraryName = libraryData.getInternalName();
+ for (final LibraryDependencyData dependencyData : toImport) {
+ final LibraryData libraryData = dependencyData.getTarget();
+ final String libraryName = libraryData.getInternalName();
switch (dependencyData.getLevel()) {
case MODULE:
- @SuppressWarnings("ConstantConditions") Library moduleLib = moduleLibraryTable.createLibrary(libraryName);
- Library.ModifiableModel libModel = moduleLib.getModifiableModel();
+ final Library moduleLib = moduleLibraryTable.createLibrary(libraryName);
+ final Library.ModifiableModel libModel = moduleLib.getModifiableModel();
try {
Map<OrderRootType, Collection<File>> files = myLibraryManager.prepareLibraryFiles(libraryData);
myLibraryManager.registerPaths(files, libModel, libraryName);
+ LibraryOrderEntry orderEntry = moduleRootModel.findLibraryOrderEntry(moduleLib);
+ assert orderEntry != null;
+ setLibraryScope(orderEntry, moduleLib, module, dependencyData);
}
finally {
libModel.commit();
@@ -184,17 +187,24 @@
continue;
}
LibraryOrderEntry orderEntry = moduleRootModel.addLibraryEntry(projectLib);
- LOG.info(String.format("Adding library dependency '%s' to module '%s'", projectLib.getName(), module.getName()));
- orderEntry.setExported(dependencyData.isExported());
- orderEntry.setScope(dependencyData.getScope());
- LOG.info(String.format(
- "Configuring library dependency '%s' of module '%s' to be%s exported and have scope %s",
- projectLib.getName(), module.getName(), dependencyData.isExported() ? " not" : "", dependencyData.getScope()
- ));
+ setLibraryScope(orderEntry, projectLib, module, dependencyData);
}
}
}
+ private static void setLibraryScope(@NotNull LibraryOrderEntry orderEntry,
+ @NotNull Library lib,
+ @NotNull Module module,
+ @NotNull LibraryDependencyData dependencyData) {
+ LOG.info(String.format("Adding library dependency '%s' to module '%s'", lib.getName(), module.getName()));
+ orderEntry.setExported(dependencyData.isExported());
+ orderEntry.setScope(dependencyData.getScope());
+ LOG.info(String.format(
+ "Configuring library dependency '%s' of module '%s' to be%s exported and have scope %s",
+ lib.getName(), module.getName(), dependencyData.isExported() ? " not" : "", dependencyData.getScope()
+ ));
+ }
+
private static void filterUpToDateAndRemoveObsolete(@NotNull Map<Set<String>, LibraryDependencyData> moduleLibrariesToImport,
@NotNull Map<String, LibraryDependencyData> projectLibrariesToImport,
@NotNull Set<LibraryDependencyData> toImport,
@@ -204,20 +214,22 @@
Set<String> moduleLibraryKey = ContainerUtilRt.newHashSet();
for (OrderEntry entry : moduleRootModel.getOrderEntries()) {
if (entry instanceof ModuleLibraryOrderEntryImpl) {
- Library library = ((ModuleLibraryOrderEntryImpl)entry).getLibrary();
+ ModuleLibraryOrderEntryImpl moduleLibraryOrderEntry = (ModuleLibraryOrderEntryImpl)entry;
+ Library library = moduleLibraryOrderEntry.getLibrary();
if (library == null) {
LOG.warn("Skipping module-level library entry because it doesn't have backing Library object. Entry: " + entry);
continue;
}
moduleLibraryKey.clear();
for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
- moduleLibraryKey.add(ExternalSystemApiUtil.getLocalFileSystemPath(file));
+ moduleLibraryKey.add(ExternalSystemApiUtil.getLocalFileSystemPath(file) + moduleLibraryOrderEntry.getScope().name());
}
LibraryDependencyData existing = moduleLibrariesToImport.remove(moduleLibraryKey);
if (existing == null) {
moduleRootModel.removeOrderEntry(entry);
}
else {
+
toImport.remove(existing);
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
index a983624..4b1e3b1 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/ModuleDataService.java
@@ -219,6 +219,8 @@
@Override
public void execute() {
for (Module module : modules) {
+ if(module.isDisposed()) continue;
+
ModuleManager moduleManager = ModuleManager.getInstance(module.getProject());
String path = module.getModuleFilePath();
moduleManager.disposeModule(module);
@@ -282,5 +284,8 @@
if (moduleData.getVersion() != null) {
module.setOption(ExternalSystemConstants.EXTERNAL_SYSTEM_MODULE_VERSION_KEY, moduleData.getVersion());
}
+
+ // clear maven option
+ module.clearOption("org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule");
}
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalModuleBuilder.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalModuleBuilder.java
index 052041c..d3084e0 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalModuleBuilder.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/AbstractExternalModuleBuilder.java
@@ -15,29 +15,15 @@
*/
package com.intellij.openapi.externalSystem.service.project.wizard;
-import com.intellij.ide.fileTemplates.FileTemplate;
-import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.util.projectWizard.ModuleBuilder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
-import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
-import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
import com.intellij.openapi.externalSystem.util.ExternalSystemUiUtil;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.roots.ModifiableRootModel;
-import com.intellij.openapi.util.io.FileUtilRt;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
-import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.io.File;
-import java.io.IOException;
/**
* @author Denis Zhdanov
@@ -47,13 +33,12 @@
private static final Logger LOG = Logger.getInstance("#" + AbstractExternalModuleBuilder.class.getName());
- @NotNull private final Icon myIcon;
- @NotNull private final ProjectSystemId myExternalSystemId;
- @NotNull private final S myExternalProjectSettings;
+ @NotNull private final Icon myIcon;
+ @NotNull private final ProjectSystemId myExternalSystemId;
+ @NotNull private final S myExternalProjectSettings;
protected AbstractExternalModuleBuilder(@NotNull final ProjectSystemId externalSystemId,
- @NotNull final S externalProjectSettings)
- {
+ @NotNull final S externalProjectSettings) {
myExternalSystemId = externalSystemId;
myExternalProjectSettings = externalProjectSettings;
Icon icon = ExternalSystemUiUtil.getUiAware(externalSystemId).getProjectIcon();
@@ -80,61 +65,8 @@
return myIcon;
}
- @Override
- public void setupRootModel(ModifiableRootModel model) throws ConfigurationException {
- String contentPath = getContentEntryPath();
- if (StringUtil.isEmpty(contentPath)) {
- return;
- }
- File contentRootDir = new File(contentPath);
- FileUtilRt.createDirectory(contentRootDir);
- LocalFileSystem fileSystem = LocalFileSystem.getInstance();
- VirtualFile vContentRootDir = fileSystem.refreshAndFindFileByIoFile(contentRootDir);
- if (vContentRootDir == null) {
- return;
- }
-
- model.addContentEntry(vContentRootDir);
- model.inheritSdk();
-
- VirtualFile configFile = getExternalProjectConfigFile(vContentRootDir);
- final String templateConfigName = getTemplateConfigName(myExternalProjectSettings);
- if (configFile != null && templateConfigName != null) {
- FileTemplateManager manager = FileTemplateManager.getInstance();
- FileTemplate template = manager.getInternalTemplate(templateConfigName);
- try {
- VfsUtil.saveText(configFile, template.getText());
- }
- catch (IOException e) {
- LOG.warn(String.format("Unexpected exception on applying template %s config", myExternalSystemId.getReadableName()), e);
- throw new ConfigurationException(
- e.getMessage(),
- String.format("Can't apply %s template config text", myExternalSystemId.getReadableName())
- );
- }
- }
-
- AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(model.getProject(), myExternalSystemId);
- //noinspection unchecked
- myExternalProjectSettings.setExternalProjectPath(getContentEntryPath());
- settings.linkProject(myExternalProjectSettings);
- }
-
@NotNull
public S getExternalProjectSettings() {
return myExternalProjectSettings;
}
-
- /**
- * Asks external system-specific module builder to prepare external system config file if necessary.
- *
- * @param contentRootDir new module's content root dir
- * @return external system config file created by the external system-specific implementation (if any);
- * <code>null</code> as an indication that no external system config file has been created
- */
- @Nullable
- protected abstract VirtualFile getExternalProjectConfigFile(@NotNull VirtualFile contentRootDir);
-
- @Nullable
- protected abstract String getTemplateConfigName(@NotNull S settings);
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/SelectExternalProjectStep.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/SelectExternalProjectStep.java
index 1a1cbf3..218f743 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/SelectExternalProjectStep.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/wizard/SelectExternalProjectStep.java
@@ -57,6 +57,9 @@
@Override
public boolean validate() throws ConfigurationException {
myControl.apply();
+ if (myControl.getProjectFormatPanel() != null) {
+ myControl.getProjectFormatPanel().updateData(getWizardContext());
+ }
AbstractExternalProjectImportBuilder builder = getBuilder();
if (builder == null) {
return false;
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java
index b996f4d..59b1e5f 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractExternalSystemConfigurable.java
@@ -190,7 +190,7 @@
@NotNull
protected String getProjectName(@NotNull String path) {
File file = new File(path);
- return file.isDirectory() ? file.getName() : file.getParentFile().getName();
+ return file.isDirectory() || file.getParentFile() == null ? file.getName() : file.getParentFile().getName();
}
private void prepareSystemSettings(@NotNull SystemSettings s) {
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
index 2644b55..5dcb5ef 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/AbstractImportFromExternalSystemControl.java
@@ -27,6 +27,8 @@
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.projectImport.ProjectFormatPanel;
+import com.intellij.ui.HideableTitledPanel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,6 +53,8 @@
@NotNull private final PaintAwarePanel myComponent = new PaintAwarePanel(new GridBagLayout());
@NotNull private final TextFieldWithBrowseButton myLinkedProjectPathField = new TextFieldWithBrowseButton();
+ @Nullable private final HideableTitledPanel hideableSystemSettingsPanel;
+ @Nullable private final ProjectFormatPanel myProjectFormatPanel;
@NotNull private final ExternalSystemSettingsControl<ProjectSettings> myProjectSettingsControl;
@NotNull private final ProjectSystemId myExternalSystemId;
@@ -58,11 +62,19 @@
@Nullable Project myCurrentProject;
- @SuppressWarnings("AbstractMethodCallInConstructor")
protected AbstractImportFromExternalSystemControl(@NotNull ProjectSystemId externalSystemId,
@NotNull SystemSettings systemSettings,
@NotNull ProjectSettings projectSettings)
{
+ this(externalSystemId, systemSettings, projectSettings, false);
+ }
+
+ @SuppressWarnings("AbstractMethodCallInConstructor")
+ protected AbstractImportFromExternalSystemControl(@NotNull ProjectSystemId externalSystemId,
+ @NotNull SystemSettings systemSettings,
+ @NotNull ProjectSettings projectSettings,
+ boolean showProjectFormatPanel)
+ {
myExternalSystemId = externalSystemId;
mySystemSettings = systemSettings;
myProjectSettings = projectSettings;
@@ -102,8 +114,29 @@
myComponent.add(linkedProjectPathLabel, ExternalSystemUiUtil.getLabelConstraints(0));
myComponent.add(myLinkedProjectPathField, ExternalSystemUiUtil.getFillLineConstraints(0));
myProjectSettingsControl.fillUi(myComponent, 0);
+
+ if(showProjectFormatPanel) {
+ myProjectFormatPanel = new ProjectFormatPanel();
+ JLabel myProjectFormatLabel = new JLabel(ExternalSystemBundle.message("settings.label.project.format"));
+ myComponent.add(myProjectFormatLabel, ExternalSystemUiUtil.getLabelConstraints(0));
+ myComponent.add(myProjectFormatPanel.getStorageFormatComboBox(), ExternalSystemUiUtil.getFillLineConstraints(0));
+ } else {
+ myProjectFormatPanel = null;
+ }
+
if (mySystemSettingsControl != null) {
- mySystemSettingsControl.fillUi(myComponent, 0);
+ final PaintAwarePanel mySystemSettingsControlPanel = new PaintAwarePanel();
+ mySystemSettingsControl.fillUi(mySystemSettingsControlPanel, 0);
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(mySystemSettingsControlPanel, BorderLayout.CENTER);
+ hideableSystemSettingsPanel = new HideableTitledPanel(
+ ExternalSystemBundle.message("settings.title.system.settings", myExternalSystemId.getReadableName()), false);
+ hideableSystemSettingsPanel.setContentComponent(panel);
+ hideableSystemSettingsPanel.setOn(false);
+ myComponent.add(hideableSystemSettingsPanel, ExternalSystemUiUtil.getFillLineConstraints(0));
+ } else {
+ hideableSystemSettingsPanel = null;
}
ExternalSystemUiUtil.fillBottom(myComponent);
}
@@ -181,6 +214,9 @@
if (mySystemSettingsControl != null) {
mySystemSettingsControl.reset();
}
+ if (hideableSystemSettingsPanel != null) {
+ hideableSystemSettingsPanel.setOn(false);
+ }
}
public void apply() throws ConfigurationException {
@@ -208,4 +244,9 @@
mySystemSettingsControl.apply(mySystemSettings);
}
}
+
+ @Nullable
+ public ProjectFormatPanel getProjectFormatPanel() {
+ return myProjectFormatPanel;
+ }
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/ExternalSystemConfigLocator.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/ExternalSystemConfigLocator.java
index 34b08b4..2413473 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/ExternalSystemConfigLocator.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/settings/ExternalSystemConfigLocator.java
@@ -2,10 +2,13 @@
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
+import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.List;
+
/**
* @author Denis Zhdanov
* @since 7/16/13 3:36 PM
@@ -27,4 +30,13 @@
*/
@Nullable
VirtualFile adjust(@NotNull VirtualFile configPath);
+
+ /**
+ * Returns all configuration files used by external system to build the project.
+ *
+ * @param externalProjectSettings external system project settings
+ * @return external system project config files
+ */
+ @NotNull
+ List<VirtualFile> findAll(@NotNull ExternalProjectSettings externalProjectSettings);
}
diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java
index e828a42..2453723 100644
--- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java
+++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/util/ExternalSystemUtil.java
@@ -290,8 +290,8 @@
Set<String> toRefresh = ContainerUtilRt.newHashSet();
for (ExternalProjectSettings setting : projectsSettings) {
Long oldModificationStamp = modificationStamps.get(setting.getExternalProjectPath());
- long currentModificationStamp = getTimeStamp(setting.getExternalProjectPath(), externalSystemId);
- if (force || currentModificationStamp < 0 || oldModificationStamp == null || oldModificationStamp < currentModificationStamp) {
+ long currentModificationStamp = getTimeStamp(setting, externalSystemId);
+ if (force || oldModificationStamp == null || oldModificationStamp < currentModificationStamp) {
toRefresh.add(setting.getExternalProjectPath());
}
}
@@ -304,21 +304,17 @@
}
}
- private static long getTimeStamp(@NotNull String path, @NotNull ProjectSystemId externalSystemId) {
- VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path));
- if (vFile == null) {
- return -1;
- }
+ private static long getTimeStamp(@NotNull ExternalProjectSettings externalProjectSettings, @NotNull ProjectSystemId externalSystemId) {
+ long timeStamp = 0;
for (ExternalSystemConfigLocator locator : ExternalSystemConfigLocator.EP_NAME.getExtensions()) {
if (!externalSystemId.equals(locator.getTargetExternalSystemId())) {
continue;
}
- VirtualFile adjusted = locator.adjust(vFile);
- if (adjusted != null) {
- vFile = adjusted;
+ for (VirtualFile virtualFile : locator.findAll(externalProjectSettings)) {
+ timeStamp += virtualFile.getTimeStamp();
}
}
- return vFile.getTimeStamp();
+ return timeStamp;
}
/**
@@ -469,15 +465,12 @@
= new ExternalSystemResolveProjectTask(externalSystemId, project, externalProjectPath, isPreviewMode);
task.execute(indicator, ExternalSystemTaskNotificationListener.EP_NAME.getExtensions());
+ if(project.isDisposed()) return;
+
final Throwable error = task.getError();
if (error == null) {
ExternalSystemManager<?, ?, ?, ?, ?> manager = ExternalSystemApiUtil.getManager(externalSystemId);
assert manager != null;
- long stamp = getTimeStamp(externalProjectPath, externalSystemId);
- if (stamp > 0) {
- if(project.isDisposed()) return;
- manager.getLocalSettingsProvider().fun(project).getExternalConfigModificationStamps().put(externalProjectPath, stamp);
- }
DataNode<ProjectData> externalProject = task.getExternalProject();
if(externalProject != null) {
@@ -491,6 +484,11 @@
ExternalProjectSettings linkedProjectSettings = manager.getSettingsProvider().fun(project).getLinkedProjectSettings(projectPath);
if (linkedProjectSettings != null) {
linkedProjectSettings.setModules(externalModulePaths);
+
+ long stamp = getTimeStamp(linkedProjectSettings, externalSystemId);
+ if (stamp > 0) {
+ manager.getLocalSettingsProvider().fun(project).getExternalConfigModificationStamps().put(externalProjectPath, stamp);
+ }
}
}
@@ -504,8 +502,7 @@
String message = ExternalSystemApiUtil.buildErrorMessage(error);
if (StringUtil.isEmpty(message)) {
message = String.format(
- "Can't resolve %s project at '%s'. Reason: %s",
- externalSystemId.getReadableName(), externalProjectPath, message
+ "Can't resolve %s project at '%s'. Reason: %s", externalSystemId.getReadableName(), externalProjectPath, message
);
}
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/service/project/ExternalProjectServiceTest.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/service/project/ExternalProjectServiceTest.groovy
index cdbd811..60e4c1d 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/service/project/ExternalProjectServiceTest.groovy
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/service/project/ExternalProjectServiceTest.groovy
@@ -24,6 +24,7 @@
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleSourceOrderEntry
import com.intellij.openapi.roots.OrderEntry
+import com.intellij.openapi.roots.OrderRootType
import static com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType.*
/**
@@ -99,4 +100,43 @@
}
ExternalSystemTestUtil.assertMapsEqual(['source': 4, 'excluded': 2], folders)
}
+
+ void 'test library dependency with sources path added on subsequent refresh'() {
+ applyProjectState([
+ buildExternalProjectInfo {
+ project {
+ module('module') {
+ lib('lib1', level: 'module', bin: ["bin_path"]) } } },
+ buildExternalProjectInfo {
+ project {
+ module('module') {
+ lib('lib1', level: 'module', bin: ["bin_path"], src: ["source_path"]) } } }
+ ])
+
+ def helper = ServiceManager.getService(ProjectStructureHelper.class)
+ def module = helper.findIdeModule('module', project)
+ assertNotNull(module)
+
+ def facade = ServiceManager.getService(PlatformFacade.class)
+ def entries = facade.getOrderEntries(module)
+ def dependencies = [:].withDefault { 0 }
+ entries.each { OrderEntry entry ->
+ if (entry instanceof LibraryOrderEntry) {
+ def name = (entry as LibraryOrderEntry).libraryName
+ dependencies[name]++
+ if ("Test_external_system_id: lib1".equals(name)) {
+ def classesUrls = entry.getUrls(OrderRootType.CLASSES)
+ assertEquals(1, classesUrls.length)
+ assertTrue(classesUrls[0].endsWith("bin_path"))
+ def sourceUrls = entry.getUrls(OrderRootType.SOURCES)
+ assertEquals(1, sourceUrls.length)
+ assertTrue(sourceUrls[0].endsWith("source_path"))
+ }
+ else {
+ fail()
+ }
+ }
+ }
+ ExternalSystemTestUtil.assertMapsEqual(['Test_external_system_id: lib1': 1], dependencies)
+ }
}
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy
index 95d1089..37e35f1 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/AbstractExternalSystemTest.groovy
@@ -14,13 +14,11 @@
* limitations under the License.
*/
package com.intellij.openapi.externalSystem.test
-
import com.intellij.openapi.components.ServiceManager
import com.intellij.openapi.extensions.ExtensionPoint
import com.intellij.openapi.extensions.Extensions
import com.intellij.openapi.externalSystem.ExternalSystemManager
import com.intellij.openapi.externalSystem.model.DataNode
-import com.intellij.openapi.externalSystem.model.ProjectSystemId
import com.intellij.openapi.externalSystem.model.project.ProjectData
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange
@@ -28,6 +26,7 @@
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ex.ProjectRootManagerEx
import com.intellij.openapi.util.io.FileUtil
+import com.intellij.testFramework.PlatformTestCase
import com.intellij.testFramework.SkipInHeadlessEnvironment
import com.intellij.testFramework.UsefulTestCase
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture
@@ -38,7 +37,6 @@
import java.lang.reflect.Field
import java.lang.reflect.Modifier
-
/**
* @author Denis Zhdanov
* @since 8/7/13 2:04 PM
@@ -54,7 +52,11 @@
TestExternalSystemManager externalSystemManager
ExtensionPoint externalSystemManagerEP
-
+
+ AbstractExternalSystemTest() {
+ PlatformTestCase.autodetectPlatformPrefix()
+ }
+
@Override
protected void setUp() throws Exception {
super.setUp()
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemManager.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemManager.groovy
index a37e019..659da91 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemManager.groovy
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemManager.groovy
@@ -86,10 +86,10 @@
}
@Override
- void enhanceRemoteProcessing(@NotNull @NotNull SimpleJavaParameters parameters) throws ExecutionException {
+ void enhanceRemoteProcessing(@NotNull SimpleJavaParameters parameters) throws ExecutionException {
}
@Override
- void enhanceLocalProcessing(@NotNull @NotNull List<URL> urls) {
+ void enhanceLocalProcessing(@NotNull List<URL> urls) {
}
}
diff --git a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemSettings.groovy b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemSettings.groovy
index 52bdfe5..3e43b79 100644
--- a/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemSettings.groovy
+++ b/platform/external-system-impl/testSrc/com/intellij/openapi/externalSystem/test/TestExternalSystemSettings.groovy
@@ -34,17 +34,17 @@
}
@Override
- void subscribe(@NotNull @NotNull ExternalSystemSettingsListener<TestExternalProjectSettings> listener) {
+ void subscribe(@NotNull ExternalSystemSettingsListener<TestExternalProjectSettings> listener) {
throw new UnsupportedOperationException()
}
@Override
- protected void copyExtraSettingsFrom(@NotNull @NotNull TestExternalSystemSettings settings) {
+ protected void copyExtraSettingsFrom(@NotNull TestExternalSystemSettings settings) {
throw new UnsupportedOperationException()
}
@Override
- protected void checkSettings(@NotNull @NotNull TestExternalProjectSettings old, @NotNull @NotNull TestExternalProjectSettings current) {
+ protected void checkSettings(@NotNull TestExternalProjectSettings old, @NotNull TestExternalProjectSettings current) {
throw new UnsupportedOperationException()
}
}
diff --git a/platform/icons/src/general/comboBoxButtonArrow.png b/platform/icons/src/general/comboBoxButtonArrow.png
new file mode 100644
index 0000000..aa7de5d
--- /dev/null
+++ b/platform/icons/src/general/comboBoxButtonArrow.png
Binary files differ
diff --git a/platform/icons/src/general/comboBoxButtonArrow@2x.png b/platform/icons/src/general/comboBoxButtonArrow@2x.png
new file mode 100644
index 0000000..970d6b4
--- /dev/null
+++ b/platform/icons/src/general/comboBoxButtonArrow@2x.png
Binary files differ
diff --git a/platform/icons/src/general/downloadPlugin.png b/platform/icons/src/general/downloadPlugin.png
new file mode 100644
index 0000000..7dde20a
--- /dev/null
+++ b/platform/icons/src/general/downloadPlugin.png
Binary files differ
diff --git a/platform/icons/src/general/downloadPlugin@2x.png b/platform/icons/src/general/downloadPlugin@2x.png
new file mode 100644
index 0000000..6aa080e
--- /dev/null
+++ b/platform/icons/src/general/downloadPlugin@2x.png
Binary files differ
diff --git a/platform/icons/src/general/uninstallPlugin.png b/platform/icons/src/general/uninstallPlugin.png
new file mode 100644
index 0000000..019973d
--- /dev/null
+++ b/platform/icons/src/general/uninstallPlugin.png
Binary files differ
diff --git a/platform/icons/src/general/uninstallPlugin@2x.png b/platform/icons/src/general/uninstallPlugin@2x.png
new file mode 100644
index 0000000..c29c763
--- /dev/null
+++ b/platform/icons/src/general/uninstallPlugin@2x.png
Binary files differ
diff --git a/platform/icons/src/modules/addExcludedRoot.png b/platform/icons/src/modules/addExcludedRoot.png
new file mode 100644
index 0000000..bdb4715
--- /dev/null
+++ b/platform/icons/src/modules/addExcludedRoot.png
Binary files differ
diff --git a/platform/icons/src/modules/addExcludedRoot@2x.png b/platform/icons/src/modules/addExcludedRoot@2x.png
new file mode 100644
index 0000000..bfb2186
--- /dev/null
+++ b/platform/icons/src/modules/addExcludedRoot@2x.png
Binary files differ
diff --git a/platform/icons/src/modules/addExcludedRoot@2x_dark.png b/platform/icons/src/modules/addExcludedRoot@2x_dark.png
new file mode 100644
index 0000000..114c101
--- /dev/null
+++ b/platform/icons/src/modules/addExcludedRoot@2x_dark.png
Binary files differ
diff --git a/platform/icons/src/modules/addExcludedRoot_dark.png b/platform/icons/src/modules/addExcludedRoot_dark.png
new file mode 100644
index 0000000..bfaafac
--- /dev/null
+++ b/platform/icons/src/modules/addExcludedRoot_dark.png
Binary files differ
diff --git a/platform/icons/src/modules/types/emptyProjectType.png b/platform/icons/src/modules/types/emptyProjectType.png
index 25791ec..36ed04d 100644
--- a/platform/icons/src/modules/types/emptyProjectType.png
+++ b/platform/icons/src/modules/types/emptyProjectType.png
Binary files differ
diff --git a/platform/icons/src/modules/types/emptyProjectType@2x.png b/platform/icons/src/modules/types/emptyProjectType@2x.png
new file mode 100644
index 0000000..601c9d0
--- /dev/null
+++ b/platform/icons/src/modules/types/emptyProjectType@2x.png
Binary files differ
diff --git a/platform/icons/src/modules/types/javaModule.png b/platform/icons/src/modules/types/javaModule.png
index def27cf..5a040c8 100644
--- a/platform/icons/src/modules/types/javaModule.png
+++ b/platform/icons/src/modules/types/javaModule.png
Binary files differ
diff --git a/platform/icons/src/modules/types/javaModule@2x.png b/platform/icons/src/modules/types/javaModule@2x.png
new file mode 100644
index 0000000..3cdbe09
--- /dev/null
+++ b/platform/icons/src/modules/types/javaModule@2x.png
Binary files differ
diff --git a/platform/icons/src/modules/types/userDefined.png b/platform/icons/src/modules/types/userDefined.png
new file mode 100644
index 0000000..aaf940a
--- /dev/null
+++ b/platform/icons/src/modules/types/userDefined.png
Binary files differ
diff --git a/platform/icons/src/modules/types/userDefined@2x.png b/platform/icons/src/modules/types/userDefined@2x.png
new file mode 100644
index 0000000..fdc09e8
--- /dev/null
+++ b/platform/icons/src/modules/types/userDefined@2x.png
Binary files differ
diff --git a/platform/icons/src/modules/types/webModule.png b/platform/icons/src/modules/types/webModule.png
index 4a561d9..affdb0f 100644
--- a/platform/icons/src/modules/types/webModule.png
+++ b/platform/icons/src/modules/types/webModule.png
Binary files differ
diff --git a/platform/icons/src/modules/types/webModule@2x.png b/platform/icons/src/modules/types/webModule@2x.png
new file mode 100644
index 0000000..9b20aa6
--- /dev/null
+++ b/platform/icons/src/modules/types/webModule@2x.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/canary16.png b/platform/icons/src/xml/browsers/canary16.png
new file mode 100644
index 0000000..1630faf
--- /dev/null
+++ b/platform/icons/src/xml/browsers/canary16.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/canary16@2x.png b/platform/icons/src/xml/browsers/canary16@2x.png
new file mode 100644
index 0000000..893ad08
--- /dev/null
+++ b/platform/icons/src/xml/browsers/canary16@2x.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/chrome16.png b/platform/icons/src/xml/browsers/chrome16.png
index 2adb345..72c34ed 100644
--- a/platform/icons/src/xml/browsers/chrome16.png
+++ b/platform/icons/src/xml/browsers/chrome16.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/chrome16@2x.png b/platform/icons/src/xml/browsers/chrome16@2x.png
index 103297f..cda7eb3 100644
--- a/platform/icons/src/xml/browsers/chrome16@2x.png
+++ b/platform/icons/src/xml/browsers/chrome16@2x.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/chromium16.png b/platform/icons/src/xml/browsers/chromium16.png
new file mode 100644
index 0000000..904c707
--- /dev/null
+++ b/platform/icons/src/xml/browsers/chromium16.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/chromium16@2x.png b/platform/icons/src/xml/browsers/chromium16@2x.png
new file mode 100644
index 0000000..555d837
--- /dev/null
+++ b/platform/icons/src/xml/browsers/chromium16@2x.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/firefox16.png b/platform/icons/src/xml/browsers/firefox16.png
index da1a46d..cc57722 100644
--- a/platform/icons/src/xml/browsers/firefox16.png
+++ b/platform/icons/src/xml/browsers/firefox16.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/firefox16@2x.png b/platform/icons/src/xml/browsers/firefox16@2x.png
index a115983..c2797e8 100644
--- a/platform/icons/src/xml/browsers/firefox16@2x.png
+++ b/platform/icons/src/xml/browsers/firefox16@2x.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/opera16.png b/platform/icons/src/xml/browsers/opera16.png
index 696d2a8..0b4f83e 100644
--- a/platform/icons/src/xml/browsers/opera16.png
+++ b/platform/icons/src/xml/browsers/opera16.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/opera16@2x.png b/platform/icons/src/xml/browsers/opera16@2x.png
index ded79b8..791111a 100644
--- a/platform/icons/src/xml/browsers/opera16@2x.png
+++ b/platform/icons/src/xml/browsers/opera16@2x.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/yandex16.png b/platform/icons/src/xml/browsers/yandex16.png
new file mode 100644
index 0000000..70b974a
--- /dev/null
+++ b/platform/icons/src/xml/browsers/yandex16.png
Binary files differ
diff --git a/platform/icons/src/xml/browsers/yandex16@2x.png b/platform/icons/src/xml/browsers/yandex16@2x.png
new file mode 100644
index 0000000..436e30f
--- /dev/null
+++ b/platform/icons/src/xml/browsers/yandex16@2x.png
Binary files differ
diff --git a/platform/indexing-api/src/com/intellij/psi/search/TodoAttributes.java b/platform/indexing-api/src/com/intellij/psi/search/TodoAttributes.java
index d92e956..c5651b6 100644
--- a/platform/indexing-api/src/com/intellij/psi/search/TodoAttributes.java
+++ b/platform/indexing-api/src/com/intellij/psi/search/TodoAttributes.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -31,7 +31,7 @@
public class TodoAttributes implements Cloneable {
private Icon myIcon;
- private TextAttributes myTextAttributes = new TextAttributes();
+ private TextAttributes myTextAttributes;
private boolean myShouldUseCustomColors;
@NonNls private static final String ATTRIBUTE_ICON = "icon";
@@ -56,10 +56,12 @@
else{
throw new InvalidDataException(icon);
}
- myTextAttributes.readExternal(element);
if (element.getChild(ELEMENT_OPTION) == null) {
myTextAttributes = defaultTodoAttributes;
}
+ else {
+ myTextAttributes = new TextAttributes(element);
+ }
// default color setting
final String useCustomColors = element.getAttributeValue(USE_CUSTOM_COLORS_ATT);
diff --git a/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java b/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
index 448765f..f253346 100644
--- a/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
+++ b/platform/indexing-api/src/com/intellij/psi/stubs/StubIndex.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -45,11 +45,17 @@
return StubIndexHolder.ourInstance;
}
+ /**
+ * @deprecated use {@link #getElements(StubIndexKey, Object, com.intellij.openapi.project.Project, com.intellij.psi.search.GlobalSearchScope, Class)}
+ */
public abstract <Key, Psi extends PsiElement> Collection<Psi> get(@NotNull StubIndexKey<Key, Psi> indexKey,
@NotNull Key key,
@NotNull Project project,
final GlobalSearchScope scope);
+ /**
+ * @deprecated use {@link #getElements(StubIndexKey, Object, com.intellij.openapi.project.Project, com.intellij.psi.search.GlobalSearchScope, Class)}
+ */
public <Key, Psi extends PsiElement> Collection<Psi> get(@NotNull StubIndexKey<Key, Psi> indexKey,
@NotNull Key key,
@NotNull Project project,
@@ -82,12 +88,33 @@
return processAllKeys(indexKey, scope.getProject(), processor);
}
+ /**
+ * @deprecated use {@link #getElements(StubIndexKey, Object, com.intellij.openapi.project.Project, com.intellij.psi.search.GlobalSearchScope, Class)}
+ */
public <Key, Psi extends PsiElement> Collection<Psi> safeGet(@NotNull StubIndexKey<Key, Psi> indexKey,
@NotNull Key key,
@NotNull final Project project,
final GlobalSearchScope scope,
@NotNull Class<Psi> requiredClass) {
- Collection<Psi> collection = getInstance().get(indexKey, key, project, scope);
+ return getElements(indexKey, key, project, scope, requiredClass);
+ }
+
+ public static <Key, Psi extends PsiElement> Collection<Psi> getElements(@NotNull StubIndexKey<Key, Psi> indexKey,
+ @NotNull Key key,
+ @NotNull final Project project,
+ final GlobalSearchScope scope,
+ @NotNull Class<Psi> requiredClass) {
+ return getElements(indexKey, key, project, scope, null, requiredClass);
+ }
+
+ public static <Key, Psi extends PsiElement> Collection<Psi> getElements(@NotNull StubIndexKey<Key, Psi> indexKey,
+ @NotNull Key key,
+ @NotNull final Project project,
+ final GlobalSearchScope scope,
+ @Nullable IdFilter idFilter,
+ @NotNull Class<Psi> requiredClass) {
+ //noinspection deprecation
+ Collection<Psi> collection = getInstance().get(indexKey, key, project, scope, idFilter);
for (Iterator<Psi> iterator = collection.iterator(); iterator.hasNext(); ) {
Psi psi = iterator.next();
if (!requiredClass.isInstance(psi)) {
@@ -98,15 +125,15 @@
FileBasedIndex.getInstance().requestReindex(faultyContainer);
}
- reportStubPsiMismatch(psi, faultyContainer);
+ getInstance().reportStubPsiMismatch(psi, faultyContainer, requiredClass);
}
}
return collection;
}
- protected <Psi extends PsiElement> void reportStubPsiMismatch(Psi psi, VirtualFile file) {
- LOG.error("Invalid stub element type in index: " + file + ". found: " + psi);
+ protected <Psi extends PsiElement> void reportStubPsiMismatch(Psi psi, VirtualFile file, Class<Psi> requiredClass) {
+ LOG.error("Invalid stub element type in index: " + file + ". found: " + psi + ". expected: " + requiredClass);
}
}
diff --git a/platform/indexing-api/src/com/intellij/util/xml/NanoXmlUtil.java b/platform/indexing-api/src/com/intellij/util/xml/NanoXmlUtil.java
index e28ab91..d2c4343 100644
--- a/platform/indexing-api/src/com/intellij/util/xml/NanoXmlUtil.java
+++ b/platform/indexing-api/src/com/intellij/util/xml/NanoXmlUtil.java
@@ -140,7 +140,13 @@
@NotNull
public static XmlFileHeader parseHeaderWithException(final VirtualFile file) throws IOException {
- return parseHeader(new MyXMLReader(file.getInputStream()));
+ final InputStream stream = file.getInputStream();
+ try {
+ return parseHeader(new MyXMLReader(stream));
+ }
+ finally {
+ stream.close();
+ }
}
@Deprecated // TODO: remove
diff --git a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java
index d78dffb..f45032c 100644
--- a/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java
+++ b/platform/indexing-impl/src/com/intellij/ide/highlighter/custom/tokens/KeywordParser.java
@@ -96,7 +96,7 @@
}
char ch = myBuffer.charAt(offset);
- return ch != '-' && !Character.isLetterOrDigit(ch);
+ return ch != '-' && ch != '_' && !Character.isLetterOrDigit(ch);
}
private static IElementType getToken(int keywordSetIndex) {
diff --git a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java
index f039357..b91ac03 100644
--- a/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.java
+++ b/platform/indexing-impl/src/com/intellij/psi/impl/search/PsiSearchHelperImpl.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.
@@ -27,6 +27,7 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
+import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.TooManyUsagesStatus;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.FileIndexFacade;
@@ -368,6 +369,7 @@
});
if (!failedFiles.isEmpty()) {
for (final VirtualFile vfile : failedFiles) {
+ checkCanceled(progress);
TooManyUsagesStatus.getFrom(progress).pauseProcessingIfTooManyUsages();
// we failed to run read action in job launcher thread
// run read action in our thread instead
@@ -437,7 +439,12 @@
}
private static void checkCanceled(ProgressIndicator progress) {
- if (progress != null) progress.checkCanceled();
+ if (progress != null) {
+ progress.checkCanceled();
+ }
+ else {
+ ProgressManager.checkCanceled();
+ }
}
private void getFilesWithText(@NotNull GlobalSearchScope scope,
@@ -456,7 +463,7 @@
}
};
boolean success = processFilesWithText(scope, searchContext, caseSensitively, text, processor);
- LOG.assertTrue(success);
+ // success == false means exception in index
}
finally {
myManager.finishBatchFilesProcessingMode();
diff --git a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java
index 9355f44..6b24933 100644
--- a/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java
+++ b/platform/indexing-impl/src/com/intellij/psi/stubs/StubProcessingHelperBase.java
@@ -33,6 +33,10 @@
}
public <Psi extends PsiElement> boolean processStubsInFile(final Project project, final VirtualFile file, StubIdList value, final Processor<? super Psi> processor) {
+ return processStubsInFile(project, file, value, processor, false);
+ }
+
+ public <Psi extends PsiElement> boolean processStubsInFile(final Project project, final VirtualFile file, StubIdList value, final Processor<? super Psi> processor, final boolean skipOnErrors) {
StubTree stubTree = null;
PsiFile _psifile = PsiManager.getInstance(project).findFile(file);
@@ -71,7 +75,15 @@
stubTree = (StubTree)objectStubTree;
final List<StubElement<?>> plained = stubTree.getPlainList();
for (int i = 0, size = value.size(); i < size; i++) {
- final StubElement<?> stub = plained.get(value.get(i));
+ final int stubTreeIndex = value.get(i);
+ if (stubTreeIndex >= plained.size()) {
+ if (!skipOnErrors)
+ onInternalError(file);
+
+ break;
+ }
+
+ final StubElement<?> stub = plained.get(stubTreeIndex);
PsiUtilCore.ensureValid(psiFile);
final ASTNode tree = psiFile.findTreeForStub(stubTree, stub);
@@ -81,7 +93,7 @@
PsiUtilCore.ensureValid(psi);
if (!processor.process(psi)) return false;
}
- else {
+ else if (!skipOnErrors) {
String persistedStubTree = ((PsiFileStubImpl)stubTree.getRoot()).printTree();
String stubTreeJustBuilt =
@@ -108,11 +120,13 @@
for (int i = 0, size = value.size(); i < size; i++) {
final int stubTreeIndex = value.get(i);
if (stubTreeIndex >= plained.size()) {
- final VirtualFile virtualFile = psiFile.getVirtualFile();
- StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(project, file);
- LOG.error(stubTreeAndIndexDoNotMatch(stubTree, psiFile, plained, virtualFile, stubTreeFromIndex));
+ if (!skipOnErrors) {
+ final VirtualFile virtualFile = psiFile.getVirtualFile();
+ StubTree stubTreeFromIndex = (StubTree)StubTreeLoader.getInstance().readFromVFile(project, file);
+ LOG.error(stubTreeAndIndexDoNotMatch(stubTree, psiFile, plained, virtualFile, stubTreeFromIndex));
- onInternalError(file);
+ onInternalError(file);
+ }
break;
}
@@ -127,7 +141,7 @@
/***
* Returns a message to log when stub tree and index do not match
*/
- protected abstract String stubTreeAndIndexDoNotMatch(StubTree stubTree,
+ protected abstract Object stubTreeAndIndexDoNotMatch(StubTree stubTree,
PsiFileWithStubSupport psiFile,
List<StubElement<?>> plained,
VirtualFile virtualFile,
diff --git a/platform/indexing-impl/src/com/intellij/usageView/UsageViewTypeLocation.java b/platform/indexing-impl/src/com/intellij/usageView/UsageViewTypeLocation.java
new file mode 100644
index 0000000..8ded650
--- /dev/null
+++ b/platform/indexing-impl/src/com/intellij/usageView/UsageViewTypeLocation.java
@@ -0,0 +1,74 @@
+/*
+ * 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.usageView;
+
+import com.intellij.ide.TypePresentationService;
+import com.intellij.psi.*;
+import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.meta.PsiMetaOwner;
+import com.intellij.psi.meta.PsiPresentableMetaData;
+import com.intellij.lang.LangBundle;
+import com.intellij.lang.Language;
+import com.intellij.lang.findUsages.FindUsagesProvider;
+import com.intellij.lang.findUsages.LanguageFindUsages;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author peter
+ */
+public class UsageViewTypeLocation extends ElementDescriptionLocation {
+ private UsageViewTypeLocation() {
+ }
+
+ public static final UsageViewTypeLocation INSTANCE = new UsageViewTypeLocation();
+
+ @Override
+ public ElementDescriptionProvider getDefaultProvider() {
+ return DEFAULT_PROVIDER;
+ }
+
+ private static final ElementDescriptionProvider DEFAULT_PROVIDER = new ElementDescriptionProvider() {
+ @Override
+ public String getElementDescription(@NotNull final PsiElement psiElement, @NotNull final ElementDescriptionLocation location) {
+ if (!(location instanceof UsageViewTypeLocation)) return null;
+
+ if (psiElement instanceof PsiMetaOwner) {
+ final PsiMetaData metaData = ((PsiMetaOwner)psiElement).getMetaData();
+ if (metaData instanceof PsiPresentableMetaData) {
+ return ((PsiPresentableMetaData)metaData).getTypeName();
+ }
+ }
+
+ if (psiElement instanceof PsiFile) {
+ return LangBundle.message("terms.file");
+ }
+ if (psiElement instanceof PsiDirectory) {
+ return LangBundle.message("terms.directory");
+ }
+
+ final Language lang = psiElement.getLanguage();
+ FindUsagesProvider provider = LanguageFindUsages.INSTANCE.forLanguage(lang);
+ final String type = provider.getType(psiElement);
+ if (StringUtil.isNotEmpty(type)) {
+ return type;
+ }
+
+ return TypePresentationService.getService().getTypePresentableName(psiElement.getClass());
+ }
+ };
+}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
index c8dec2c..7cf2c7d 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionInitializationContext.java
@@ -49,14 +49,19 @@
myCompletionType = completionType;
myOffsetMap = new OffsetMap(editor.getDocument());
- final int caretOffset = editor.getCaretModel().getOffset();
+ myOffsetMap.addOffset(START_OFFSET, calcStartOffset(editor));
+ myOffsetMap.addOffset(SELECTION_END_OFFSET, calcSelectionEnd(editor));
+ myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, calcDefaultIdentifierEnd(editor, calcSelectionEnd(editor)));
+ }
+
+ private static int calcSelectionEnd(Editor editor) {
final SelectionModel selectionModel = editor.getSelectionModel();
- myOffsetMap.addOffset(START_OFFSET, selectionModel.hasSelection() ? selectionModel.getSelectionStart() : caretOffset);
+ return selectionModel.hasSelection() ? selectionModel.getSelectionEnd() : editor.getCaretModel().getOffset();
+ }
- final int selectionEndOffset = selectionModel.hasSelection() ? selectionModel.getSelectionEnd() : caretOffset;
- myOffsetMap.addOffset(SELECTION_END_OFFSET, selectionEndOffset);
-
- myOffsetMap.addOffset(IDENTIFIER_END_OFFSET, calcDefaultIdentifierEnd(editor, selectionEndOffset));
+ public static int calcStartOffset(Editor editor) {
+ final SelectionModel selectionModel = editor.getSelectionModel();
+ return selectionModel.hasSelection() ? selectionModel.getSelectionStart() : editor.getCaretModel().getOffset();
}
static int calcDefaultIdentifierEnd(Editor editor, int startFrom) {
diff --git a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
index 5d616e2..8a7feb2 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/completion/CompletionResultSet.java
@@ -1,8 +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.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.patterns.ElementPattern;
-import com.intellij.patterns.PlatformPatterns;
+import com.intellij.patterns.StandardPatterns;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
@@ -54,7 +69,7 @@
myConsumer.consume(result);
}
- public void addAllElements(@NotNull final Iterable<LookupElement> elements) {
+ public void addAllElements(@NotNull final Iterable<? extends LookupElement> elements) {
for (LookupElement element : elements) {
addElement(element);
}
@@ -118,7 +133,7 @@
}
public void restartCompletionOnPrefixChange(String prefix) {
- restartCompletionOnPrefixChange(PlatformPatterns.string().equalTo(prefix));
+ restartCompletionOnPrefixChange(StandardPatterns.string().equalTo(prefix));
}
public abstract void restartCompletionOnPrefixChange(ElementPattern<String> prefixCondition);
diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
deleted file mode 100644
index c89666e..0000000
--- a/platform/lang-api/src/com/intellij/codeInsight/daemon/ChangeLocalityDetector.java
+++ /dev/null
@@ -1,41 +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.
- */
-
-/*
- * @author max
- */
-package com.intellij.codeInsight.daemon;
-
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public interface ChangeLocalityDetector {
- /**
- * @param changedElement
- * @return the psi element (ancestor of the changedElement) which should be re-highlighted, or null if unsure.
- * Examples:
- * - in Java, when the statement has changed, re-highlight the enclosing code block only.
- * - in (hypothetical) framework which stores its annotations in comments, e.g. "// @someAnnotation",
- * when that special comment has changed, re-highlight the whole file.
- *
- * Note: for the performance sake, do not traverse PSI tree upwards here, since this method will be called for the
- * changed element and all its parents anyway.
- * So the parent check is enough, e.g: {@code changedElement.getParent() instanceof PsiCodeBlock}
- */
- @Nullable
- PsiElement getChangeHighlightingDirtyScopeFor(@NotNull PsiElement changedElement);
-}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java
index 55ce601..0c8236c 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/daemon/RelatedItemLineMarkerInfo.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,16 +21,21 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collection;
+import java.util.List;
+import java.util.Set;
/**
* @author nik
*/
-public class RelatedItemLineMarkerInfo<T extends PsiElement> extends LineMarkerInfo<T> {
+public class RelatedItemLineMarkerInfo<T extends PsiElement> extends MergeableLineMarkerInfo<T> {
private final NotNullLazyValue<Collection<? extends GotoRelatedItem>> myTargets;
public RelatedItemLineMarkerInfo(@NotNull T element, @NotNull TextRange range, Icon icon, int updatePass,
@@ -67,6 +72,39 @@
return new RelatedItemLineMarkerGutterIconRenderer<T>(this);
}
+ @Override
+ public boolean canMergeWith(@NotNull MergeableLineMarkerInfo<?> info) {
+ return myIcon == info.myIcon;
+ }
+
+ @Override
+ public Icon getCommonIcon(@NotNull List<MergeableLineMarkerInfo> infos) {
+ return myIcon;
+ }
+
+ @Override
+ public Function<? super PsiElement, String> getCommonTooltip(@NotNull final List<MergeableLineMarkerInfo> infos) {
+ return new Function<PsiElement, String>() {
+ @Override
+ public String fun(PsiElement element) {
+ Set<String> tooltips = ContainerUtil.map2Set(infos, new Function<MergeableLineMarkerInfo, String>() {
+ @Override
+ public String fun(MergeableLineMarkerInfo info) {
+ return info.getLineMarkerTooltip();
+ }
+ });
+ StringBuilder tooltip = new StringBuilder();
+ for (String info : tooltips) {
+ if (tooltip.length() > 0) {
+ tooltip.append(UIUtil.BORDER_LINE);
+ }
+ tooltip.append(UIUtil.getHtmlBody(info));
+ }
+ return XmlStringUtil.wrapInHtml(tooltip);
+ }
+ };
+ }
+
private static class RelatedItemLineMarkerGutterIconRenderer<T extends PsiElement> extends LineMarkerGutterIconRenderer<T> {
public RelatedItemLineMarkerGutterIconRenderer(final RelatedItemLineMarkerInfo<T> markerInfo) {
super(markerInfo);
diff --git a/platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java b/platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java
index e289234..825e94b 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/editorActions/TypedHandlerDelegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.codeInsight.editorActions;
import com.intellij.openapi.editor.Editor;
@@ -32,11 +31,6 @@
/**
* If the specified character triggers auto-popup, schedules the auto-popup appearance. This method is called even
* in overwrite mode, when the rest of typed handler delegate methods are not called.
- *
- * @param charTyped
- * @param project
- * @param editor
- * @param file
*/
public Result checkAutoPopup(char charTyped, final Project project, final Editor editor, final PsiFile file) {
return Result.CONTINUE;
@@ -45,12 +39,7 @@
/**
* Called before the specified character typed by the user is inserted in the editor.
*
- * @param c
- * @param project
- * @param editor
- * @param file
- * @param fileType
- * @return true if the typing has been processed - in this case, no further delegates are called and the character is not inserted.
+ * @return true if the typing has been processed (in this case, no further delegates are called and the character is not inserted),
* false otherwise.
*/
public Result beforeCharTyped(char c, final Project project, final Editor editor, final PsiFile file, final FileType fileType) {
@@ -59,11 +48,6 @@
/**
* Called after the specified character typed by the user has been inserted in the editor.
- *
- * @param c
- * @param project
- * @param editor
- * @param file
*/
public Result charTyped(char c, final Project project, final @NotNull Editor editor, @NotNull final PsiFile file) {
return Result.CONTINUE;
diff --git a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
index 2ebe5cf..9b980c5 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/lookup/LookupElementBuilder.java
@@ -18,10 +18,10 @@
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.util.PsiUtilCore;
-import com.intellij.util.ObjectUtils;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,7 +67,7 @@
public static LookupElementBuilder create(@NotNull PsiNamedElement element) {
PsiUtilCore.ensureValid(element);
- return new LookupElementBuilder(ObjectUtils.assertNotNull(element.getName()), element);
+ return new LookupElementBuilder(StringUtil.notNullize(element.getName()), element);
}
public static LookupElementBuilder createWithIcon(@NotNull PsiNamedElement element) {
diff --git a/platform/lang-api/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java b/platform/lang-api/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java
deleted file mode 100644
index 3de7c33..0000000
--- a/platform/lang-api/src/com/intellij/codeInspection/reference/UnusedDeclarationFixProvider.java
+++ /dev/null
@@ -1,34 +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.codeInspection.reference;
-
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.psi.PsiElement;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Provides quick fixes for "Unused declaration" inspection
- *
- * @author Dmitry Avdeev
- * Date: 1/19/12
- */
-public interface UnusedDeclarationFixProvider {
- ExtensionPointName<UnusedDeclarationFixProvider> EP_NAME = ExtensionPointName.create("com.intellij.unusedDeclarationFixProvider");
-
- @NotNull
- IntentionAction[] getQuickFixes(@NotNull PsiElement unusedElement);
-}
diff --git a/platform/lang-api/src/com/intellij/codeInspection/ui/ListTable.java b/platform/lang-api/src/com/intellij/codeInspection/ui/ListTable.java
index 676bbac..b921a62 100644
--- a/platform/lang-api/src/com/intellij/codeInspection/ui/ListTable.java
+++ b/platform/lang-api/src/com/intellij/codeInspection/ui/ListTable.java
@@ -16,6 +16,7 @@
package com.intellij.codeInspection.ui;
import com.intellij.ui.table.JBTable;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.JTableHeader;
@@ -53,7 +54,7 @@
}
@Override
- public void setModel(TableModel dataModel) {
+ public void setModel(@NotNull TableModel dataModel) {
if (!(dataModel instanceof ListWrappingTableModel)) {
throw new IllegalArgumentException(
"dataModel should be of type ListWrappingTableModel");
diff --git a/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java b/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java
index 5c6e47d..8a1ad25 100644
--- a/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java
+++ b/platform/lang-api/src/com/intellij/execution/ExecutionBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,20 +16,22 @@
package com.intellij.execution;
import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
* @author lesya
*/
public class ExecutionBundle extends AbstractBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return ourInstance.getMessage(key, params);
+ }
+
public static final String PATH_TO_BUNDLE = "messages.ExecutionBundle";
private static final AbstractBundle ourInstance = new ExecutionBundle();
private ExecutionBundle() {
super(PATH_TO_BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return ourInstance.getMessage(key, params);
- }
}
diff --git a/platform/lang-api/src/com/intellij/execution/Location.java b/platform/lang-api/src/com/intellij/execution/Location.java
index cb70e49..a1d3b5f 100644
--- a/platform/lang-api/src/com/intellij/execution/Location.java
+++ b/platform/lang-api/src/com/intellij/execution/Location.java
@@ -30,6 +30,7 @@
public abstract class Location<E extends PsiElement> {
public static final DataKey<Location<?>> DATA_KEY = DataKey.create("Location");
+ public static final DataKey<Location<?>[]> DATA_KEYS = DataKey.create("LocationArray");
@Deprecated @NonNls public static final String LOCATION = DATA_KEY.getName();
@NotNull public abstract E getPsiElement();
diff --git a/platform/lang-api/src/com/intellij/execution/RunProfileStarter.java b/platform/lang-api/src/com/intellij/execution/RunProfileStarter.java
index c2e3cca..163031f 100644
--- a/platform/lang-api/src/com/intellij/execution/RunProfileStarter.java
+++ b/platform/lang-api/src/com/intellij/execution/RunProfileStarter.java
@@ -30,6 +30,6 @@
public abstract class RunProfileStarter {
@Nullable
public abstract RunContentDescriptor execute(@NotNull Project project, @NotNull Executor executor, @NotNull RunProfileState state,
- @Nullable RunContentDescriptor contentToReuse, @NotNull ExecutionEnvironment env) throws ExecutionException;
+ @Nullable RunContentDescriptor contentToReuse, @NotNull ExecutionEnvironment environment) throws ExecutionException;
}
diff --git a/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java b/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java
index 859cd81..7922088 100644
--- a/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java
+++ b/platform/lang-api/src/com/intellij/execution/actions/ConsoleActionsPostProcessor.java
@@ -26,9 +26,9 @@
* @author Denis Zhdanov
* @since 4/25/11 1:16 PM
*/
-public interface ConsoleActionsPostProcessor {
+public abstract class ConsoleActionsPostProcessor {
- ExtensionPointName<ConsoleActionsPostProcessor> EP_NAME = ExtensionPointName.create("com.intellij.consoleActionsPostProcessor");
+ public static final ExtensionPointName<ConsoleActionsPostProcessor> EP_NAME = ExtensionPointName.create("com.intellij.consoleActionsPostProcessor");
/**
* Allows to adjust actions to use within the given console instance.
@@ -40,5 +40,12 @@
* @return actions to use within the given console instance (given actions may be returned by default)
*/
@NotNull
- AnAction[] postProcess(@NotNull ConsoleView console, @NotNull AnAction[] actions);
+ public AnAction[] postProcess(@NotNull ConsoleView console, @NotNull AnAction[] actions) {
+ return actions;
+ }
+
+ @NotNull
+ public AnAction[] postProcessPopupActions(@NotNull ConsoleView console, @NotNull AnAction[] actions) {
+ return actions;
+ }
}
diff --git a/platform/lang-api/src/com/intellij/execution/actions/PreferredProducerFind.java b/platform/lang-api/src/com/intellij/execution/actions/PreferredProducerFind.java
index 3f97f69..c96574d 100644
--- a/platform/lang-api/src/com/intellij/execution/actions/PreferredProducerFind.java
+++ b/platform/lang-api/src/com/intellij/execution/actions/PreferredProducerFind.java
@@ -16,7 +16,6 @@
package com.intellij.execution.actions;
-import com.intellij.diagnostic.PluginException;
import com.intellij.execution.Location;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.ConfigurationType;
@@ -24,8 +23,8 @@
import com.intellij.execution.junit.RuntimeConfigurationProducer;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionException;
import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.extensions.PluginId;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -51,27 +50,7 @@
if (location == null) {
return null;
}
-
- //todo load configuration types if not already loaded
- Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP);
- final RuntimeConfigurationProducer[] configurationProducers =
- ApplicationManager.getApplication().getExtensions(RuntimeConfigurationProducer.RUNTIME_CONFIGURATION_PRODUCER);
- final ArrayList<RuntimeConfigurationProducer> producers = new ArrayList<RuntimeConfigurationProducer>();
- for (final RuntimeConfigurationProducer prototype : configurationProducers) {
- final RuntimeConfigurationProducer producer;
- try {
- producer = prototype.createProducer(location, context);
- }
- catch (AbstractMethodError e) {
- PluginId pluginId = ApplicationManager.getApplication().getPluginByClassName(prototype.getClass().getName());
- LOG.error(prototype.toString(), pluginId != null ? new PluginException("Incompatible plugin", e, pluginId) : e);
- continue;
- }
- if (producer.getConfiguration() != null) {
- LOG.assertTrue(producer.getSourceElement() != null, producer);
- producers.add(producer);
- }
- }
+ final List<RuntimeConfigurationProducer> producers = findAllProducers(location, context);
if (producers.isEmpty()) return null;
Collections.sort(producers, RuntimeConfigurationProducer.COMPARATOR);
@@ -88,6 +67,29 @@
return producers;
}
+ private static List<RuntimeConfigurationProducer> findAllProducers(Location location, ConfigurationContext context) {
+ //todo load configuration types if not already loaded
+ Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP);
+ final RuntimeConfigurationProducer[] configurationProducers =
+ ApplicationManager.getApplication().getExtensions(RuntimeConfigurationProducer.RUNTIME_CONFIGURATION_PRODUCER);
+ final ArrayList<RuntimeConfigurationProducer> producers = new ArrayList<RuntimeConfigurationProducer>();
+ for (final RuntimeConfigurationProducer prototype : configurationProducers) {
+ final RuntimeConfigurationProducer producer;
+ try {
+ producer = prototype.createProducer(location, context);
+ }
+ catch (AbstractMethodError e) {
+ LOG.error(new ExtensionException(prototype.getClass()));
+ continue;
+ }
+ if (producer.getConfiguration() != null) {
+ LOG.assertTrue(producer.getSourceElement() != null, producer);
+ producers.add(producer);
+ }
+ }
+ return producers;
+ }
+
public static List<ConfigurationFromContext> getConfigurationsFromContext(final Location location,
final ConfigurationContext context,
final boolean strict) {
@@ -95,24 +97,9 @@
return null;
}
- //todo load configuration types if not already loaded
- Extensions.getExtensions(ConfigurationType.CONFIGURATION_TYPE_EP);
- final RuntimeConfigurationProducer[] configurationProducers =
- ApplicationManager.getApplication().getExtensions(RuntimeConfigurationProducer.RUNTIME_CONFIGURATION_PRODUCER);
final ArrayList<ConfigurationFromContext> configurationsFromContext = new ArrayList<ConfigurationFromContext>();
- for (final RuntimeConfigurationProducer prototype : configurationProducers) {
- final RuntimeConfigurationProducer producer;
- try {
- producer = prototype.createProducer(location, context);
- }
- catch (AbstractMethodError e) {
- LOG.error(prototype.toString(), e);
- continue;
- }
- if (producer.getConfiguration() != null) {
- LOG.assertTrue(producer.getSourceElement() != null, producer);
- configurationsFromContext.add(new ConfigurationFromContextWrapper(producer));
- }
+ for (RuntimeConfigurationProducer producer : findAllProducers(location, context)) {
+ configurationsFromContext.add(new ConfigurationFromContextWrapper(producer));
}
for (RunConfigurationProducer producer : Extensions.getExtensions(RunConfigurationProducer.EP_NAME)) {
diff --git a/platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java b/platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java
index 8ab9dcd..fc590c4 100644
--- a/platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java
+++ b/platform/lang-api/src/com/intellij/execution/actions/RunConfigurationProducer.java
@@ -40,7 +40,7 @@
* @author yole
*/
public abstract class RunConfigurationProducer<T extends RunConfiguration> {
- public static ExtensionPointName<RunConfigurationProducer> EP_NAME = ExtensionPointName.create("com.intellij.runConfigurationProducer");
+ public static final ExtensionPointName<RunConfigurationProducer> EP_NAME = ExtensionPointName.create("com.intellij.runConfigurationProducer");
private final ConfigurationFactory myConfigurationFactory;
protected RunConfigurationProducer(final ConfigurationFactory configurationFactory) {
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java b/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java
index cbe0535..bf52dde 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/CommandLineState.java
@@ -30,7 +30,6 @@
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.DumbAware;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,7 +42,6 @@
* @see GeneralCommandLine
*/
public abstract class CommandLineState implements RunProfileState {
- private static final Logger LOG = Logger.getInstance("#com.intellij.execution.configurations.CommandLineState");
private TextConsoleBuilder myConsoleBuilder;
private final ExecutionEnvironment myEnvironment;
@@ -83,10 +81,8 @@
@Nullable
protected ConsoleView createConsole(@NotNull final Executor executor) throws ExecutionException {
- final TextConsoleBuilder builder = getConsoleBuilder();
-
- return builder != null ? builder.getConsole()
- : null;
+ TextConsoleBuilder builder = getConsoleBuilder();
+ return builder != null ? builder.getConsole() : null;
}
/**
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/MockCommandLineState.java b/platform/lang-api/src/com/intellij/execution/configurations/MockCommandLineState.java
index 87c07b2..fc0b108 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/MockCommandLineState.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/MockCommandLineState.java
@@ -21,15 +21,16 @@
import com.intellij.execution.runners.ExecutionEnvironment;
import org.jetbrains.annotations.NotNull;
+@Deprecated
/**
- * @author oleg
+ * @deprecated Use {@link com.intellij.execution.configuration.EmptyRunProfileState} (to remove in IDEA 15)
*/
-
public class MockCommandLineState extends CommandLineState {
public MockCommandLineState(@NotNull final ExecutionEnvironment env) {
super(env);
}
+ @NotNull
@Override
protected OSProcessHandler startProcess() throws ExecutionException {
return null;
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java b/platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java
index b8d96e4..b61d4d1 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/RunConfiguration.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.
@@ -115,11 +115,12 @@
/**
* Checks whether the run configuration settings are valid.
+ * Note that this check may be invoked on every change (i.e. after each character typed in an input field).
*
* @throws RuntimeConfigurationException if the configuration settings contain a non-fatal problem which the user should be warned about
- * but the execution should still be allowed
- * @throws RuntimeConfigurationError if the configuration settings contain a fatal problem which makes it impossible to execute the run
- * configuration.
+ * but the execution should still be allowed.
+ * @throws RuntimeConfigurationError if the configuration settings contain a fatal problem which makes it impossible
+ * to execute the run configuration.
*/
void checkConfiguration() throws RuntimeConfigurationException;
}
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java b/platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java
index 5abaa75..ecf740e 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/RunProfileState.java
@@ -28,7 +28,9 @@
*
* @see CommandLineState
* @see RunConfiguration#getState(com.intellij.execution.Executor, com.intellij.execution.runners.ExecutionEnvironment)
+ * @see com.intellij.execution.configuration.EmptyRunProfileState
*/
+@SuppressWarnings("JavadocReference")
public interface RunProfileState {
/**
* Starts the process.
diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RuntimeConfigurationWarning.java b/platform/lang-api/src/com/intellij/execution/configurations/RuntimeConfigurationWarning.java
index f86f6f5..65e8710 100644
--- a/platform/lang-api/src/com/intellij/execution/configurations/RuntimeConfigurationWarning.java
+++ b/platform/lang-api/src/com/intellij/execution/configurations/RuntimeConfigurationWarning.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,8 +17,8 @@
import com.intellij.execution.ExecutionBundle;
-
-public class RuntimeConfigurationWarning extends RuntimeConfigurationException{
+@SuppressWarnings("ExceptionClassNameDoesntEndWithException")
+public class RuntimeConfigurationWarning extends RuntimeConfigurationException {
public RuntimeConfigurationWarning(final String message) {
this(message, null);
}
diff --git a/platform/lang-api/src/com/intellij/execution/filters/HyperlinkInfoFactory.java b/platform/lang-api/src/com/intellij/execution/filters/HyperlinkInfoFactory.java
new file mode 100644
index 0000000..42beb03
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/execution/filters/HyperlinkInfoFactory.java
@@ -0,0 +1,37 @@
+/*
+ * 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.execution.filters;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class HyperlinkInfoFactory {
+ @NotNull
+ public static HyperlinkInfoFactory getInstance() {
+ return ServiceManager.getService(HyperlinkInfoFactory.class);
+ }
+
+ @NotNull
+ public abstract HyperlinkInfo createMultipleFilesHyperlinkInfo(@NotNull List<VirtualFile> files,
+ int line, @NotNull Project project);
+}
diff --git a/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java
new file mode 100644
index 0000000..9ea188f
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/execution/runners/AsyncGenericProgramRunner.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.execution.runners;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionManager;
+import com.intellij.execution.Executor;
+import com.intellij.execution.RunProfileStarter;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RunnerSettings;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.AsyncResult;
+import com.intellij.util.Consumer;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Allows to postpone actual {@link RunProfileState} execution until all the needed preparations are done.
+ */
+public abstract class AsyncGenericProgramRunner<Settings extends RunnerSettings> extends BaseProgramRunner<Settings> {
+ @Override
+ protected final void startRunProfile(@NotNull final ExecutionEnvironment environment,
+ @Nullable final Callback callback,
+ @NotNull final Project project,
+ @NotNull final RunProfileState state) throws ExecutionException {
+ prepare(project, environment, state).doWhenProcessed(new Consumer<RunProfileStarter>() {
+ @Override
+ public void consume(@Nullable final RunProfileStarter result) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (!project.isDisposed()) {
+ startRunProfile(project, environment, state, callback, result);
+ }
+ }
+ });
+ }
+ });
+ }
+
+ /**
+ * Makes all the needed preparations for the further execution. Although this method is called in EDT,
+ * these preparations can be performed in a background thread.
+ *
+ * @param project Project instance
+ * @param environment ExecutionEnvironment instance
+ * @param state RunProfileState instance
+ * @return RunProfileStarter async result
+ */
+ @NotNull
+ protected abstract AsyncResult<RunProfileStarter> prepare(@NotNull Project project,
+ @NotNull ExecutionEnvironment environment,
+ @NotNull RunProfileState state) throws ExecutionException;
+
+ private static void startRunProfile(@NotNull Project project,
+ @NotNull ExecutionEnvironment environment,
+ @NotNull RunProfileState state,
+ @Nullable final Callback callback,
+ @Nullable final RunProfileStarter starter) {
+ ExecutionManager.getInstance(project).startRunProfile(new RunProfileStarter() {
+ @Override
+ public RunContentDescriptor execute(@NotNull Project project,
+ @NotNull Executor executor,
+ @NotNull RunProfileState state,
+ @Nullable RunContentDescriptor contentToReuse,
+ @NotNull ExecutionEnvironment environment) throws ExecutionException {
+ RunContentDescriptor descriptor = starter == null ? null : starter.execute(project, executor, state, contentToReuse, environment);
+ if (descriptor != null) {
+ descriptor.setExecutionId(environment.getExecutionId());
+ }
+ if (callback != null) {
+ callback.processStarted(descriptor);
+ }
+ return descriptor;
+ }
+ }, state, environment);
+ }
+}
diff --git a/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.java
new file mode 100644
index 0000000..340155c
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/execution/runners/BaseProgramRunner.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 com.intellij.execution.runners;
+
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionResult;
+import com.intellij.execution.Executor;
+import com.intellij.execution.RunManager;
+import com.intellij.execution.configurations.*;
+import com.intellij.execution.ui.RunContentDescriptor;
+import com.intellij.openapi.options.SettingsEditor;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class BaseProgramRunner<Settings extends RunnerSettings> implements ProgramRunner<Settings> {
+ @Override
+ @Nullable
+ public Settings createConfigurationData(ConfigurationInfoProvider settingsProvider) {
+ return null;
+ }
+
+ @Override
+ public void checkConfiguration(RunnerSettings settings, ConfigurationPerRunnerSettings configurationPerRunnerSettings)
+ throws RuntimeConfigurationException {
+ }
+
+ @Override
+ public void onProcessStarted(RunnerSettings settings, ExecutionResult executionResult) {
+ }
+
+ @Override
+ @Nullable
+ public SettingsEditor<Settings> getSettingsEditor(Executor executor, RunConfiguration configuration) {
+ return null;
+ }
+
+ @Override
+ public void execute(@NotNull ExecutionEnvironment environment) throws ExecutionException {
+ execute(environment, null);
+ }
+
+ @Override
+ public void execute(@NotNull ExecutionEnvironment environment, @Nullable Callback callback) throws ExecutionException {
+ RunProfileState state = environment.getState();
+ if (state == null) {
+ return;
+ }
+
+ Project project = environment.getProject();
+ RunManager.getInstance(project).refreshUsagesList(environment.getRunProfile());
+ startRunProfile(environment, callback, project, state);
+ }
+
+ protected abstract void startRunProfile(@NotNull ExecutionEnvironment environment,
+ @Nullable Callback callback,
+ @NotNull Project project,
+ @NotNull RunProfileState state) throws ExecutionException;
+
+ @Nullable
+ protected static RunContentDescriptor postProcess(@NotNull ExecutionEnvironment environment, @Nullable RunContentDescriptor descriptor, @Nullable Callback callback) {
+ if (descriptor != null) {
+ descriptor.setExecutionId(environment.getExecutionId());
+ }
+ if (callback != null) {
+ callback.processStarted(descriptor);
+ }
+ return descriptor;
+ }
+}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java
index d3e5097..86909ea 100644
--- a/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java
+++ b/platform/lang-api/src/com/intellij/execution/runners/ExecutionEnvironment.java
@@ -204,9 +204,11 @@
public String toString() {
if (myRunnerAndConfigurationSettings != null) {
return myRunnerAndConfigurationSettings.getName();
- } else if (myRunProfile != null) {
- return myRunProfile.getName();
- } else if (myContentToReuse != null) {
+ }
+ else if (myRunProfile != null) {
+ return myRunProfile.getName();
+ }
+ else if (myContentToReuse != null) {
return myContentToReuse.getDisplayName();
}
return super.toString();
diff --git a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java
index 04b64db..ae783ca 100644
--- a/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.java
+++ b/platform/lang-api/src/com/intellij/execution/runners/GenericProgramRunner.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,84 +16,50 @@
package com.intellij.execution.runners;
-import com.intellij.execution.*;
-import com.intellij.execution.configurations.*;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.ExecutionManager;
+import com.intellij.execution.Executor;
+import com.intellij.execution.RunProfileStarter;
+import com.intellij.execution.configurations.RunProfileState;
+import com.intellij.execution.configurations.RunnerSettings;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.actionSystem.DataKey;
-import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-/**
- * @author spleaner
- */
-public abstract class GenericProgramRunner<Settings extends RunnerSettings> implements ProgramRunner<Settings> {
-
+public abstract class GenericProgramRunner<Settings extends RunnerSettings> extends BaseProgramRunner<Settings> {
@Deprecated
public static final DataKey<RunContentDescriptor> CONTENT_TO_REUSE_DATA_KEY = DataKey.create("contentToReuse");
- @Deprecated @NonNls public static final String CONTENT_TO_REUSE = CONTENT_TO_REUSE_DATA_KEY.getName();
+ @SuppressWarnings({"UnusedDeclaration", "deprecation"}) @Deprecated @NonNls
+ public static final String CONTENT_TO_REUSE = CONTENT_TO_REUSE_DATA_KEY.getName();
@Override
- @Nullable
- public Settings createConfigurationData(final ConfigurationInfoProvider settingsProvider) {
- return null;
- }
-
- @Override
- public void checkConfiguration(final RunnerSettings settings, final ConfigurationPerRunnerSettings configurationPerRunnerSettings)
- throws RuntimeConfigurationException {
- }
-
- @Override
- public void onProcessStarted(final RunnerSettings settings, final ExecutionResult executionResult) {
- }
-
- @Override
- @Nullable
- public SettingsEditor<Settings> getSettingsEditor(final Executor executor, final RunConfiguration configuration) {
- return null;
- }
-
- @Override
- public void execute(@NotNull final ExecutionEnvironment environment) throws ExecutionException {
- execute(environment, null);
- }
-
- @Override
- public void execute(@NotNull final ExecutionEnvironment env, @Nullable final Callback callback)
- throws ExecutionException {
-
- final Project project = env.getProject();
-
- final RunProfileState state = env.getState();
- if (state == null) {
- return;
- }
-
- RunManager.getInstance(project).refreshUsagesList(env.getRunProfile());
-
+ protected void startRunProfile(@NotNull ExecutionEnvironment environment, @Nullable final Callback callback, @NotNull Project project, @NotNull RunProfileState state)
+ throws ExecutionException {
ExecutionManager.getInstance(project).startRunProfile(new RunProfileStarter() {
@Override
public RunContentDescriptor execute(@NotNull Project project,
@NotNull Executor executor,
@NotNull RunProfileState state,
@Nullable RunContentDescriptor contentToReuse,
- @NotNull ExecutionEnvironment env) throws ExecutionException {
- final RunContentDescriptor descriptor = doExecute(project, state, contentToReuse, env);
+ @NotNull ExecutionEnvironment environment) throws ExecutionException {
+ RunContentDescriptor descriptor = doExecute(project, state, contentToReuse, environment);
if (descriptor != null) {
- descriptor.setExecutionId(env.getExecutionId());
+ descriptor.setExecutionId(environment.getExecutionId());
}
- if (callback != null) callback.processStarted(descriptor);
+ if (callback != null) {
+ callback.processStarted(descriptor);
+ }
return descriptor;
}
- }, state, env);
+ }, state, environment);
}
@Nullable
- protected abstract RunContentDescriptor doExecute(final Project project, final RunProfileState state,
- final RunContentDescriptor contentToReuse,
- final ExecutionEnvironment env) throws ExecutionException;
+ protected abstract RunContentDescriptor doExecute(@NotNull Project project, @NotNull RunProfileState state,
+ @Nullable RunContentDescriptor contentToReuse,
+ @NotNull ExecutionEnvironment environment) throws ExecutionException;
}
diff --git a/platform/lang-api/src/com/intellij/execution/ui/ConsoleView.java b/platform/lang-api/src/com/intellij/execution/ui/ConsoleView.java
index 6ec35cd..3f2568d 100644
--- a/platform/lang-api/src/com/intellij/execution/ui/ConsoleView.java
+++ b/platform/lang-api/src/com/intellij/execution/ui/ConsoleView.java
@@ -22,7 +22,7 @@
import org.jetbrains.annotations.NotNull;
public interface ConsoleView extends ExecutionConsole {
- void print(String s, ConsoleViewContentType contentType);
+ void print(@NotNull String s, @NotNull ConsoleViewContentType contentType);
void clear();
diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/actions/AbstractAction.java b/platform/lang-api/src/com/intellij/facet/frameworks/actions/AbstractAction.java
index cac0f9c..b4ceea6 100644
--- a/platform/lang-api/src/com/intellij/facet/frameworks/actions/AbstractAction.java
+++ b/platform/lang-api/src/com/intellij/facet/frameworks/actions/AbstractAction.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.
diff --git a/platform/lang-api/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java b/platform/lang-api/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java
index d1aaf71..49bfd38 100644
--- a/platform/lang-api/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java
+++ b/platform/lang-api/src/com/intellij/framework/detection/DetectionExcludesConfiguration.java
@@ -30,8 +30,19 @@
return ServiceManager.getService(project, DetectionExcludesConfiguration.class);
}
+ /**
+ * Suppress detection of framework {@code type} everywhere in the project
+ */
public abstract void addExcludedFramework(@NotNull FrameworkType type);
- public abstract void addExcludedFile(@NotNull VirtualFile file, @Nullable FrameworkType type);
+
+ /**
+ * Suppress detection of framework {@code type} in the specified file or directory
+ */
+ public abstract void addExcludedFile(@NotNull VirtualFile fileOrDirectory, @Nullable FrameworkType type);
+
+ /**
+ * Suppress detection of framework {@code type} in the file or directory specified by {@code url}
+ */
public abstract void addExcludedUrl(@NotNull String url, @Nullable FrameworkType type);
public abstract boolean isExcludedFromDetection(@NotNull VirtualFile file, @NotNull FrameworkType frameworkType);
diff --git a/platform/lang-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java b/platform/lang-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java
index a6a17be..02d63de 100644
--- a/platform/lang-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.java
+++ b/platform/lang-api/src/com/intellij/ide/structureView/TextEditorBasedStructureViewModel.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,7 +26,7 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -130,7 +130,7 @@
if (element == null) return false;
final Class[] suitableClasses = getSuitableClasses();
for (Class suitableClass : suitableClasses) {
- if (ReflectionCache.isAssignable(suitableClass, element.getClass())) return true;
+ if (ReflectionUtil.isAssignable(suitableClass, element.getClass())) return true;
}
return false;
}
diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java
index 665b593..aa9bdaa 100644
--- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java
+++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/AbstractModuleBuilder.java
@@ -15,6 +15,7 @@
*/
package com.intellij.ide.util.projectWizard;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -38,9 +39,22 @@
return null;
}
+ /**
+ * Custom UI to be shown on the first wizard page
+ */
+ @Nullable
+ public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
+ return null;
+ }
+
public abstract void setName(String name);
public abstract void setModuleFilePath(@NonNls String path);
public abstract void setContentEntryPath(String moduleRootPath);
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj instanceof AbstractModuleBuilder && getBuilderId() != null && getBuilderId().equals(((AbstractModuleBuilder)obj).getBuilderId());
+ }
}
diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/EmptyModuleBuilder.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/EmptyModuleBuilder.java
index 38bb964..9d15fa9 100644
--- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/EmptyModuleBuilder.java
+++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/EmptyModuleBuilder.java
@@ -24,7 +24,7 @@
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.roots.ModifiableRootModel;
-public class EmptyModuleBuilder extends ModuleBuilder{
+public class EmptyModuleBuilder extends ModuleBuilder {
@Override
public boolean isOpenProjectSettingsAfter() {
return true;
@@ -44,4 +44,24 @@
public ModuleType getModuleType() {
return ModuleType.EMPTY;
}
+
+ @Override
+ public String getPresentableName() {
+ return "Empty Project";
+ }
+
+ @Override
+ public String getGroupName() {
+ return getPresentableName();
+ }
+
+ @Override
+ public boolean isTemplateBased() {
+ return true;
+ }
+
+ @Override
+ public String getDescription() {
+ return "Empty project without modules. Use it to create free-style module structure.";
+ }
}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java
index 349d358..82e108a 100644
--- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java
+++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/ModuleBuilder.java
@@ -18,7 +18,6 @@
import com.intellij.ide.IdeBundle;
import com.intellij.ide.highlighter.ModuleFileType;
import com.intellij.ide.util.frameworkSupport.FrameworkRole;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
@@ -51,6 +50,7 @@
import java.util.*;
public abstract class ModuleBuilder extends AbstractModuleBuilder {
+
public static final ExtensionPointName<ModuleBuilderFactory> EP_NAME = ExtensionPointName.create("com.intellij.moduleBuilder");
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.util.projectWizard.ModuleBuilder");
@@ -142,11 +142,6 @@
}
}
- @Nullable
- public JComponent getCustomOptionsPanel(Disposable parentDisposable) {
- return null;
- }
-
protected List<WizardInputField> getAdditionalFields() {
return Collections.emptyList();
}
@@ -348,6 +343,10 @@
}
public String getPresentableName() {
+ return getModuleTypeName();
+ }
+
+ protected String getModuleTypeName() {
String name = getModuleType().getName();
return StringUtil.trimEnd(name, " Module");
}
@@ -356,6 +355,18 @@
return getPresentableName().split(" ")[0];
}
+ public String getParentGroup() {
+ return null;
+ }
+
+ public boolean isTemplate() {
+ return false;
+ }
+
+ public boolean isTemplateBased() {
+ return false;
+ }
+
public void updateFrom(ModuleBuilder from) {
myName = from.getName();
myContentEntryPath = from.getContentEntryPath();
@@ -370,18 +381,6 @@
return myJdk;
}
- private Map<String, Boolean> myAvailableFrameworks;
-
- /** @deprecated will be removed */
- public Map<String, Boolean> getAvailableFrameworks() {
- return myAvailableFrameworks;
- }
-
- /** @deprecated will be removed */
- public void setAvailableFrameworks(Map<String, Boolean> availableFrameworks) {
- myAvailableFrameworks = availableFrameworks;
- }
-
@NotNull
public FrameworkRole getDefaultAcceptableRole() {
return getModuleType().getDefaultAcceptableRole();
diff --git a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
index fde32d0..0415487 100644
--- a/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
+++ b/platform/lang-api/src/com/intellij/ide/util/projectWizard/WizardContext.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.platform.ProjectTemplate;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -46,6 +47,7 @@
private String myCompilerOutputDirectory;
private Sdk myProjectJdk;
private ProjectBuilder myProjectBuilder;
+ private ProjectTemplate myProjectTemplate;
private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private StorageScheme myProjectStorageFormat = StorageScheme.DIRECTORY_BASED;
private boolean myNewWizard;
@@ -163,6 +165,16 @@
myProjectBuilder = projectBuilder;
}
+ @Nullable
+ public ProjectTemplate getProjectTemplate() {
+ return myProjectTemplate;
+ }
+
+ public void setProjectTemplate(ProjectTemplate projectTemplate) {
+ myProjectTemplate = projectTemplate;
+ setProjectBuilder(projectTemplate.createModuleBuilder());
+ }
+
public String getPresentationName() {
return myProject == null ? IdeBundle.message("project.new.wizard.project.identification") : IdeBundle.message("project.new.wizard.module.identification");
}
diff --git a/platform/lang-api/src/com/intellij/lang/BracePair.java b/platform/lang-api/src/com/intellij/lang/BracePair.java
index 5c762a7..7fc14ed 100644
--- a/platform/lang-api/src/com/intellij/lang/BracePair.java
+++ b/platform/lang-api/src/com/intellij/lang/BracePair.java
@@ -71,4 +71,13 @@
public boolean isStructural() {
return myStructural;
}
+
+ @Override
+ public String toString() {
+ return "BracePair{" +
+ "myLeftBrace=" + myLeftBrace +
+ ", myRightBrace=" + myRightBrace +
+ ", myStructural=" + myStructural +
+ '}';
+ }
}
diff --git a/platform/lang-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java b/platform/lang-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java
deleted file mode 100644
index e4050f0..0000000
--- a/platform/lang-api/src/com/intellij/lang/ExternalAnnotatorsFilter.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * 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.lang;
-
-import com.intellij.lang.annotation.ExternalAnnotator;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.psi.PsiFile;
-
-/**
- * @author Dmitry Avdeev
- */
-public interface ExternalAnnotatorsFilter {
-
- ExtensionPointName<ExternalAnnotatorsFilter> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.daemon.externalAnnotatorsFilter");
-
- boolean isProhibited(ExternalAnnotator annotator, PsiFile file);
-}
diff --git a/platform/lang-api/src/com/intellij/lang/ExternalLanguageAnnotators.java b/platform/lang-api/src/com/intellij/lang/ExternalLanguageAnnotators.java
deleted file mode 100644
index 4a46297..0000000
--- a/platform/lang-api/src/com/intellij/lang/ExternalLanguageAnnotators.java
+++ /dev/null
@@ -1,53 +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.
- */
-
-/*
- * @author max
- */
-package com.intellij.lang;
-
-import com.intellij.lang.annotation.ExternalAnnotator;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.util.Condition;
-import com.intellij.psi.PsiFile;
-import com.intellij.util.containers.ContainerUtil;
-
-import java.util.List;
-
-public class ExternalLanguageAnnotators extends LanguageExtension<ExternalAnnotator>{
-
- private static final ExternalLanguageAnnotators INSTANCE = new ExternalLanguageAnnotators();
-
- private ExternalLanguageAnnotators() {
- super("com.intellij.externalAnnotator");
- }
-
- public static List<ExternalAnnotator> allForFile(Language language, final PsiFile file) {
- List<ExternalAnnotator> annotators = INSTANCE.allForLanguage(language);
- final ExternalAnnotatorsFilter[] filters = Extensions.getExtensions(ExternalAnnotatorsFilter.EXTENSION_POINT_NAME);
- return ContainerUtil.findAll(annotators, new Condition<ExternalAnnotator>() {
- @Override
- public boolean value(ExternalAnnotator annotator) {
- for (ExternalAnnotatorsFilter filter : filters) {
- if (filter.isProhibited(annotator, file)) {
- return false;
- }
- }
- return true;
- }
- });
- }
-}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/lang/annotation/ExternalAnnotator.java b/platform/lang-api/src/com/intellij/lang/annotation/ExternalAnnotator.java
deleted file mode 100644
index 9f8644c..0000000
--- a/platform/lang-api/src/com/intellij/lang/annotation/ExternalAnnotator.java
+++ /dev/null
@@ -1,77 +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.lang.annotation;
-
-import com.intellij.openapi.editor.Editor;
-import com.intellij.psi.PsiFile;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * Implemented by a custom language plugin to process the files in a language by an
- * external annotation tool. The external annotator is expected to be slow and is started
- * after the regular annotator has completed its work.
- *
- * @author ven
- * @see com.intellij.lang.ExternalLanguageAnnotators
- */
-public abstract class ExternalAnnotator<InitialInfoType, AnnotationResultType> {
- /**
- * Collects initial information required for annotation. Expected to run within read action.
- * See {@link ExternalAnnotator#collectInformation(PsiFile, Editor, boolean)} for details.
- *
- * @param file file to annotate
- * @return see {@link ExternalAnnotator#collectInformation(PsiFile, Editor, boolean)}
- */
- @Nullable
- public InitialInfoType collectInformation(@NotNull PsiFile file) {
- return null;
- }
-
- /**
- * Collects initial information required for annotation. This method is called within read action during annotation pass.
- * Default implementation returns the result of {@link ExternalAnnotator#collectInformation(PsiFile)}
- * if file has no errors or {@code null} otherwise.
- * @param file file to annotate
- * @param editor editor in which file's document reside
- * @param hasErrors indicates if file has errors detected by preceding analyses
- * @return information to pass to {@link ExternalAnnotator#doAnnotate(InitialInfoType)} or {@code null} if annotation should be skipped
- */
- @Nullable
- public InitialInfoType collectInformation(@NotNull PsiFile file, @NotNull Editor editor, boolean hasErrors) {
- return hasErrors ? null : collectInformation(file);
- }
-
- /**
- * Collects full information required for annotation. This method is intended for long-running activities
- * and will be called outside read/write actions during annotation pass.
- * @param collectedInfo initial information gathered by {@link ExternalAnnotator#collectInformation(PsiFile, Editor, boolean)}
- * @return annotation result to pass to {@link ExternalAnnotator#apply(PsiFile, AnnotationResultType, AnnotationHolder)}
- */
- @Nullable
- public AnnotationResultType doAnnotate(InitialInfoType collectedInfo) {
- return null;
- }
-
- /**
- * Applies results of annotation. This method is called within read action during annotation pass.
- * @param file file to annotate
- * @param annotationResult annotation result acquired through {@link ExternalAnnotator#doAnnotate(InitialInfoType)}
- * @param holder container which receives annotations
- */
- public void apply(@NotNull PsiFile file, AnnotationResultType annotationResult, @NotNull AnnotationHolder holder) {
- }
-}
diff --git a/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoHandler.java b/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoHandler.java
index e492c77..2910a93 100644
--- a/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoHandler.java
+++ b/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -27,19 +27,20 @@
// Find element for parameter info should also set ItemsToShow in context and may set highlighted element
@Nullable
- ParameterOwner findElementForParameterInfo(final CreateParameterInfoContext context);
+ ParameterOwner findElementForParameterInfo(@NotNull CreateParameterInfoContext context);
// Usually context.showHint
- void showParameterInfo(@NotNull final ParameterOwner element, final CreateParameterInfoContext context);
+ void showParameterInfo(@NotNull final ParameterOwner element, @NotNull CreateParameterInfoContext context);
// Null returns leads to removing hint
@Nullable
- ParameterOwner findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context);
- void updateParameterInfo(@NotNull final ParameterOwner o, final UpdateParameterInfoContext context);
+ ParameterOwner findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context);
+ void updateParameterInfo(@NotNull final ParameterOwner parameterOwner, @NotNull UpdateParameterInfoContext context);
// Can be null if parameter info does not track parameter index
- @Nullable String getParameterCloseChars();
+ @Nullable
+ String getParameterCloseChars();
boolean tracksParameterIndex();
// context.setEnabled / context.setupUIComponentPresentation
- void updateUI(ParameterType p, ParameterInfoUIContext context);
+ void updateUI(ParameterType p, @NotNull ParameterInfoUIContext context);
}
diff --git a/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUtils.java b/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUtils.java
index ba054a2..92b6e2f 100644
--- a/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUtils.java
+++ b/platform/lang-api/src/com/intellij/lang/parameterInfo/ParameterInfoUtils.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.
diff --git a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java
index ccc4fed..14aea4c 100644
--- a/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java
+++ b/platform/lang-api/src/com/intellij/lang/refactoring/RefactoringSupportProvider.java
@@ -47,11 +47,20 @@
public boolean isSafeDeleteAvailable(@NotNull PsiElement element) { return false; }
/**
+ * @see #getIntroduceVariableHandler(com.intellij.psi.PsiElement)
+ */
+ @Nullable
+ public RefactoringActionHandler getIntroduceVariableHandler() { return null; }
+
+ /**
* @return handler for introducing local variables in this language
* @see com.intellij.refactoring.RefactoringActionHandler
*/
@Nullable
- public RefactoringActionHandler getIntroduceVariableHandler() { return null; }
+ public RefactoringActionHandler getIntroduceVariableHandler(PsiElement element) {
+ return getIntroduceVariableHandler();
+ }
+
/**
* @return handler for extracting methods in this language
diff --git a/platform/lang-api/src/com/intellij/navigation/NavigationItemFileStatus.java b/platform/lang-api/src/com/intellij/navigation/NavigationItemFileStatus.java
index 0661f61..c9f33fb 100644
--- a/platform/lang-api/src/com/intellij/navigation/NavigationItemFileStatus.java
+++ b/platform/lang-api/src/com/intellij/navigation/NavigationItemFileStatus.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -21,6 +21,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
@@ -43,11 +44,11 @@
return FileStatus.NOT_CHANGED;
}
- private static FileStatus getPsiElementFileStatus(PsiElement psiElement) {
+ private static FileStatus getPsiElementFileStatus(@NotNull PsiElement psiElement) {
if (!psiElement.isPhysical()) return FileStatus.NOT_CHANGED;
PsiFile contFile = psiElement.getContainingFile();
if (contFile == null) return FileStatus.NOT_CHANGED;
VirtualFile vFile = contFile.getVirtualFile();
- return vFile != null ? FileStatusManager.getInstance(psiElement.getProject()).getStatus(vFile) : FileStatus.NOT_CHANGED;
+ return vFile == null ? FileStatus.NOT_CHANGED : FileStatusManager.getInstance(psiElement.getProject()).getStatus(vFile);
}
}
diff --git a/platform/lang-api/src/com/intellij/openapi/module/InternalModuleType.java b/platform/lang-api/src/com/intellij/openapi/module/InternalModuleType.java
new file mode 100644
index 0000000..eb00c42
--- /dev/null
+++ b/platform/lang-api/src/com/intellij/openapi/module/InternalModuleType.java
@@ -0,0 +1,29 @@
+/*
+ * 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.openapi.module;
+
+import com.intellij.ide.util.projectWizard.ModuleBuilder;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author gregsh
+ */
+public abstract class InternalModuleType<T extends ModuleBuilder> extends ModuleType<T> {
+ protected InternalModuleType(@NotNull @NonNls String id) {
+ super(id);
+ }
+}
diff --git a/platform/lang-api/src/com/intellij/openapi/module/ModuleUtil.java b/platform/lang-api/src/com/intellij/openapi/module/ModuleUtil.java
index 3aeae29..a7f7f32 100644
--- a/platform/lang-api/src/com/intellij/openapi/module/ModuleUtil.java
+++ b/platform/lang-api/src/com/intellij/openapi/module/ModuleUtil.java
@@ -97,4 +97,10 @@
}
return modules.length == 0;
}
+
+ @Nullable
+ public static ModuleType getModuleType(@NotNull Module module) {
+ String type = module.getOptionValue(Module.ELEMENT_TYPE);
+ return ModuleTypeManager.getInstance().findByID(type);
+ }
}
diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/SdkVersionUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/SdkVersionUtil.java
index 8e61cd4..570d366 100644
--- a/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/SdkVersionUtil.java
+++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/impl/SdkVersionUtil.java
@@ -40,6 +40,7 @@
private SdkVersionUtil() {
}
+ @Deprecated
@Nullable
public static String readVersionFromProcessOutput(String homePath, @NonNls String[] command, @NonNls String versionLineMarker) {
return JdkVersionDetector.getInstance().readVersionFromProcessOutput(homePath, command, versionLineMarker, ACTION_RUNNER);
@@ -49,4 +50,9 @@
public static String detectJdkVersion(String homePath) {
return JdkVersionDetector.getInstance().detectJdkVersion(homePath, ACTION_RUNNER);
}
+
+ @Nullable
+ public static JdkVersionDetector.JdkVersionInfo getJdkVersionInfo(String homePath) {
+ return JdkVersionDetector.getInstance().detectJdkVersionInfo(homePath, ACTION_RUNNER);
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectTemplate.java b/platform/lang-api/src/com/intellij/platform/ProjectTemplate.java
similarity index 100%
rename from platform/platform-impl/src/com/intellij/platform/ProjectTemplate.java
rename to platform/lang-api/src/com/intellij/platform/ProjectTemplate.java
diff --git a/platform/lang-api/src/com/intellij/psi/IntentionFilterOwner.java b/platform/lang-api/src/com/intellij/psi/IntentionFilterOwner.java
deleted file mode 100644
index 2970952..0000000
--- a/platform/lang-api/src/com/intellij/psi/IntentionFilterOwner.java
+++ /dev/null
@@ -1,58 +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.psi;
-
-import com.intellij.codeInsight.intention.IntentionAction;
-
-public interface IntentionFilterOwner {
- /**
- * Sets the intention actions filter which is used to determine which intention actions should be available in an editor.
- *
- * @param filter the intention actions filter instance.
- */
- void setIntentionActionsFilter(IntentionActionsFilter filter);
-
- /**
- * Sets the intention actions filter which is used to determine which intention actions should be available in an editor.
- *
- * @return the intention actions filter instance.
- */
- IntentionActionsFilter getIntentionActionsFilter();
-
- /**
- * Interface to control the available intention actions.
- */
- interface IntentionActionsFilter {
-
- /**
- * Checks if the intention action should be available in an editor.
- * @param intentionAction the intention action to analyze
- * @return Returns true if the intention action should be available, false otherwise
- */
- boolean isAvailable(final IntentionAction intentionAction);
-
- /**
- * This filter reports all intentions are available.
- */
- IntentionActionsFilter EVERYTHING_AVAILABLE = new IntentionActionsFilter() {
- @Override
- public boolean isAvailable(final IntentionAction intentionAction) {
- return true;
- }
- };
- }
-}
diff --git a/platform/lang-api/src/com/intellij/psi/LanguageInjector.java b/platform/lang-api/src/com/intellij/psi/LanguageInjector.java
index d45e2b5..b92f092 100644
--- a/platform/lang-api/src/com/intellij/psi/LanguageInjector.java
+++ b/platform/lang-api/src/com/intellij/psi/LanguageInjector.java
@@ -23,6 +23,7 @@
* Describes logic for injecting language inside hosting PSI element.
* E.g. "inject XPath language into all XML attributes named 'select' that sit inside XML tag prefixed with 'xsl:'".
* @see com.intellij.psi.PsiLanguageInjectionHost
+ * @see com.intellij.lang.injection.MultiHostInjector
*/
public interface LanguageInjector {
ExtensionPointName<LanguageInjector> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.languageInjector");
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java
index 9fdfc49..5c63059 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CodeStyleSettingsCustomizable.java
@@ -202,6 +202,8 @@
String SPACES_WITHIN = ApplicationBundle.message("group.spaces.within");
String SPACES_IN_TERNARY_OPERATOR = ApplicationBundle.message("group.spaces.in.ternary.operator");
String SPACES_WITHIN_TYPE_ARGUMENTS = ApplicationBundle.message("group.spaces.in.type.arguments");
+ String SPACES_IN_TYPE_ARGUMENTS = ApplicationBundle.message("group.spaces.in.type.arguments.block");
+ String SPACES_IN_TYPE_PARAMETERS = ApplicationBundle.message("group.spaces.in.type.parameters.block");
String SPACES_OTHER = ApplicationBundle.message("group.spaces.other");
String BLANK_LINES_KEEP = ApplicationBundle.message("title.keep.blank.lines");
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
index 2ba2f35..310c005 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/CommonCodeStyleSettings.java
@@ -148,7 +148,7 @@
targetIndentOptions.copyFrom(myIndentOptions);
}
if (myArrangementSettings != null) {
- rootSettings.setArrangementSettings(myArrangementSettings);
+ commonSettings.setArrangementSettings(myArrangementSettings.clone());
}
return commonSettings;
}
@@ -956,7 +956,7 @@
public void serialize(Element indentOptionsElement, final IndentOptions defaultOptions) {
XmlSerializer.serializeInto(this, indentOptionsElement, new SkipDefaultValuesSerializationFilters() {
@Override
- protected void configure(Object o) {
+ protected void configure(@NotNull Object o) {
if (o instanceof IndentOptions && defaultOptions != null) {
((IndentOptions)o).copyFrom(defaultOptions);
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementSettings.java
index 2727bf1..3e9fc20 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementSettings.java
@@ -29,11 +29,14 @@
* @author Denis Zhdanov
* @since 9/17/12 11:51 AM
*/
-public interface ArrangementSettings {
+public interface ArrangementSettings extends Cloneable {
@NotNull
List<ArrangementGroupingRule> getGroupings();
@NotNull
List<? extends ArrangementMatchRule> getRules();
+
+ @NotNull
+ ArrangementSettings clone();
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java
index 2330c73..5d0b97c 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/ArrangementUtil.java
@@ -17,6 +17,7 @@
import com.intellij.application.options.codeStyle.arrangement.color.ArrangementColorsProvider;
import com.intellij.lang.Language;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Ref;
@@ -40,7 +41,8 @@
* @since 7/17/12 11:24 AM
*/
public class ArrangementUtil {
-
+ private static final Logger LOG = Logger.getInstance(ArrangementUtil.class);
+
private ArrangementUtil() {
}
@@ -49,20 +51,28 @@
@Nullable
public static ArrangementSettings readExternal(@NotNull Element element, @NotNull Language language) {
ArrangementSettingsSerializer serializer = getSerializer(language);
+ if (serializer == null) {
+ LOG.error("Can't find serializer for language: " + language.getDisplayName() + "(" + language.getID() + ")");
+ return null;
+ }
+
return serializer.deserialize(element);
}
public static void writeExternal(@NotNull Element element, @NotNull ArrangementSettings settings, @NotNull Language language) {
ArrangementSettingsSerializer serializer = getSerializer(language);
+ if (serializer == null) {
+ LOG.error("Can't find serializer for language: " + language.getDisplayName() + "(" + language.getID() + ")");
+ return;
+ }
+
serializer.serialize(settings, element);
}
+ @Nullable
private static ArrangementSettingsSerializer getSerializer(@NotNull Language language) {
Rearranger<?> rearranger = Rearranger.EXTENSION.forLanguage(language);
- if (rearranger instanceof ArrangementSettingsSerializer) {
- return (ArrangementSettingsSerializer)rearranger;
- }
- return DefaultArrangementSettingsSerializer.INSTANCE;
+ return rearranger == null ? null : rearranger.getSerializer();
}
//endregion
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementSettingsSerializer.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementSettingsSerializer.java
index 147064c..a3be98f 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementSettingsSerializer.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/DefaultArrangementSettingsSerializer.java
@@ -21,15 +21,14 @@
import com.intellij.psi.codeStyle.arrangement.match.DefaultArrangementEntryMatcherSerializer;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementMatchRule;
-import com.intellij.psi.codeStyle.arrangement.std.ArrangementSettingsToken;
-import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
-import com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens;
-import com.intellij.psi.codeStyle.arrangement.std.StdRulePriorityAwareSettings;
+import com.intellij.psi.codeStyle.arrangement.std.*;
+import com.intellij.util.containers.ContainerUtil;
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;
/**
@@ -40,9 +39,6 @@
* @since 7/18/12 10:37 AM
*/
public class DefaultArrangementSettingsSerializer implements ArrangementSettingsSerializer {
-
- public static final ArrangementSettingsSerializer INSTANCE = new DefaultArrangementSettingsSerializer(Mixin.NULL);
-
private static final Logger LOG = Logger.getInstance("#" + DefaultArrangementSettingsSerializer.class.getName());
@NotNull @NonNls private static final String GROUPS_ELEMENT_NAME = "groups";
@@ -55,10 +51,16 @@
@NotNull private final DefaultArrangementEntryMatcherSerializer myMatcherSerializer;
@NotNull private final Mixin myMixin;
+ @NotNull private final ArrangementSettings myDefaultSettings;
- public DefaultArrangementSettingsSerializer(@NotNull Mixin mixin) {
+ public DefaultArrangementSettingsSerializer(@NotNull StdArrangementSettings defaultSettings) {
+ this(Mixin.NULL, defaultSettings);
+ }
+
+ public DefaultArrangementSettingsSerializer(@NotNull Mixin mixin, @NotNull StdArrangementSettings defaultSettings) {
myMixin = mixin;
myMatcherSerializer = new DefaultArrangementEntryMatcherSerializer(mixin);
+ myDefaultSettings = defaultSettings;
}
@Override
@@ -68,9 +70,9 @@
}
StdArrangementSettings settings = (StdArrangementSettings)s;
-
List<ArrangementGroupingRule> groupings = settings.getGroupings();
- if (!groupings.isEmpty()) {
+ final boolean isDefaultGroupings = groupings.equals(myDefaultSettings.getGroupings());
+ if (!isDefaultGroupings) {
Element groupingsElement = new Element(GROUPS_ELEMENT_NAME);
holder.addContent(groupingsElement);
for (ArrangementGroupingRule group : groupings) {
@@ -82,7 +84,8 @@
}
List<StdArrangementMatchRule> rules = settings.getRules();
- if (!rules.isEmpty()) {
+ final boolean isDefaultRules = rules.equals(myDefaultSettings.getRules());
+ if (!isDefaultRules) {
Element rulesElement = new Element(RULES_ELEMENT_NAME);
holder.addContent(rulesElement);
for (StdArrangementMatchRule rule : rules) {
@@ -94,79 +97,95 @@
@Nullable
@Override
public ArrangementSettings deserialize(@NotNull Element element) {
- StdArrangementSettings result = new StdRulePriorityAwareSettings();
- Element groups = element.getChild(GROUPS_ELEMENT_NAME);
- if (groups != null) {
- for (Object group : groups.getChildren(GROUP_ELEMENT_NAME)) {
- Element groupElement = (Element)group;
+ final List<ArrangementGroupingRule> groupingRules = deserializeGropings(element, myDefaultSettings);
+ final List<StdArrangementMatchRule> rules = deserializeRules(element, myDefaultSettings);
+ return new StdRulePriorityAwareSettings(groupingRules, rules);
+ }
- // Grouping type.
- String groupingTypeId = groupElement.getChildText(TYPE_ELEMENT_NAME);
- ArrangementSettingsToken groupingType = StdArrangementTokens.byId(groupingTypeId);
- if (groupingType == null) {
- groupingType = myMixin.deserializeToken(groupingTypeId);
+ @NotNull
+ private List<ArrangementGroupingRule> deserializeGropings(@NotNull Element element, @Nullable ArrangementSettings defaultSettings) {
+ Element groups = element.getChild(GROUPS_ELEMENT_NAME);
+ if (groups == null) {
+ return defaultSettings == null ? ContainerUtil.<ArrangementGroupingRule>newSmartList() : defaultSettings.getGroupings();
+ }
+
+ final List<ArrangementGroupingRule> groupings = new ArrayList<ArrangementGroupingRule>();
+ for (Object group : groups.getChildren(GROUP_ELEMENT_NAME)) {
+ Element groupElement = (Element)group;
+
+ // Grouping type.
+ String groupingTypeId = groupElement.getChildText(TYPE_ELEMENT_NAME);
+ ArrangementSettingsToken groupingType = StdArrangementTokens.byId(groupingTypeId);
+ if (groupingType == null) {
+ groupingType = myMixin.deserializeToken(groupingTypeId);
+ }
+ if (groupingType == null) {
+ LOG.warn(String.format("Can't deserialize grouping type token by id '%s'", groupingTypeId));
+ continue;
+ }
+
+ // Order type.
+ String orderTypeId = groupElement.getChildText(ORDER_TYPE_ELEMENT_NAME);
+ ArrangementSettingsToken orderType = StdArrangementTokens.byId(orderTypeId);
+ if (orderType == null) {
+ orderType = myMixin.deserializeToken(orderTypeId);
+ }
+ if (orderType == null) {
+ LOG.warn(String.format("Can't deserialize grouping order type token by id '%s'", orderTypeId));
+ continue;
+ }
+ groupings.add(new ArrangementGroupingRule(groupingType, orderType));
+ }
+ return groupings;
+ }
+
+ @NotNull
+ private List<StdArrangementMatchRule> deserializeRules(@NotNull Element element, @Nullable ArrangementSettings defaultSettings) {
+ Element rulesElement = element.getChild(RULES_ELEMENT_NAME);
+ if (rulesElement == null) {
+ return defaultSettings instanceof StdArrangementSettings ? ((StdArrangementSettings)defaultSettings).getRules() :
+ ContainerUtil.<StdArrangementMatchRule>newSmartList();
+ }
+
+ final List<StdArrangementMatchRule> rules = new ArrayList<StdArrangementMatchRule>();
+ for (Object o : rulesElement.getChildren(RULE_ELEMENT_NAME)) {
+ Element ruleElement = (Element)o;
+ Element matcherElement = ruleElement.getChild(MATCHER_ELEMENT_NAME);
+ if (matcherElement == null) {
+ continue;
+ }
+
+ StdArrangementEntryMatcher matcher = null;
+ for (Object c : matcherElement.getChildren()) {
+ matcher = myMatcherSerializer.deserialize((Element)c);
+ if (matcher != null) {
+ break;
}
- if (groupingType == null) {
- LOG.warn(String.format("Can't deserialize grouping type token by id '%s'", groupingTypeId));
- continue;
- }
-
- // Order type.
- String orderTypeId = groupElement.getChildText(ORDER_TYPE_ELEMENT_NAME);
- ArrangementSettingsToken orderType = StdArrangementTokens.byId(orderTypeId);
+ }
+
+ if (matcher == null) {
+ return ContainerUtil.newSmartList();
+ }
+
+ Element orderTypeElement = ruleElement.getChild(ORDER_TYPE_ELEMENT_NAME);
+ ArrangementSettingsToken orderType = null;
+ if (orderTypeElement != null) {
+ String orderTypeId = orderTypeElement.getText();
+ orderType = StdArrangementTokens.byId(orderTypeId);
if (orderType == null) {
orderType = myMixin.deserializeToken(orderTypeId);
}
if (orderType == null) {
- LOG.warn(String.format("Can't deserialize grouping order type token by id '%s'", orderTypeId));
- continue;
+ LOG.warn(String.format("Can't deserialize matching rule order type for id '%s'. Falling back to default (%s)",
+ orderTypeId, ArrangementMatchRule.DEFAULT_ORDER_TYPE.getId()));
}
- result.addGrouping(new ArrangementGroupingRule(groupingType, orderType));
}
- }
-
- Element rulesElement = element.getChild(RULES_ELEMENT_NAME);
- if (rulesElement != null) {
- for (Object o : rulesElement.getChildren(RULE_ELEMENT_NAME)) {
- Element ruleElement = (Element)o;
- Element matcherElement = ruleElement.getChild(MATCHER_ELEMENT_NAME);
- if (matcherElement == null) {
- continue;
- }
-
- StdArrangementEntryMatcher matcher = null;
- for (Object c : matcherElement.getChildren()) {
- matcher = myMatcherSerializer.deserialize((Element)c);
- if (matcher != null) {
- break;
- }
- }
-
- if (matcher == null) {
- return null;
- }
-
- Element orderTypeElement = ruleElement.getChild(ORDER_TYPE_ELEMENT_NAME);
- ArrangementSettingsToken orderType = null;
- if (orderTypeElement != null) {
- String orderTypeId = orderTypeElement.getText();
- orderType = StdArrangementTokens.byId(orderTypeId);
- if (orderType == null) {
- orderType = myMixin.deserializeToken(orderTypeId);
- }
- if (orderType == null) {
- LOG.warn(String.format("Can't deserialize matching rule order type for id '%s'. Falling back to default (%s)",
- orderTypeId, ArrangementMatchRule.DEFAULT_ORDER_TYPE.getId()));
- }
- }
- if (orderType == null) {
- orderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE;
- }
- result.addRule(new StdArrangementMatchRule(matcher, orderType));
+ if (orderType == null) {
+ orderType = ArrangementMatchRule.DEFAULT_ORDER_TYPE;
}
+ rules.add(new StdArrangementMatchRule(matcher, orderType));
}
-
- return result;
+ return rules;
}
@Nullable
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java
index d15dcd8..57914fb 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/Rearranger.java
@@ -90,4 +90,15 @@
* negative as an indication that no blank lines adjustment is necessary
*/
int getBlankLines(@NotNull CodeStyleSettings settings, @Nullable E parent, @Nullable E previous, @NotNull E target);
+
+
+ /**
+ * @return serializer to save {@link com.intellij.psi.codeStyle.arrangement.ArrangementSettings arrangement settings}.
+ * Serializer is expected to be lazy and don't save
+ * {@link com.intellij.psi.codeStyle.arrangement.std.ArrangementStandardSettingsAware.getDefaultSettings() default settings}.
+ * <p/>
+ * @see com.intellij.psi.codeStyle.arrangement.DefaultArrangementSettingsSerializer
+ */
+ @NotNull
+ ArrangementSettingsSerializer getSerializer();
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingRule.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingRule.java
index e0e2d9f..0570bec 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingRule.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/group/ArrangementGroupingRule.java
@@ -52,6 +52,11 @@
}
@Override
+ public ArrangementGroupingRule clone() {
+ return new ArrangementGroupingRule(myGroupingType, myOrderType);
+ }
+
+ @Override
public int hashCode() {
int result = myGroupingType.hashCode();
result = 31 * result + myOrderType.hashCode();
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettings.java
index 11bff7f..449023a 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettings.java
@@ -52,6 +52,30 @@
return myRules;
}
+ @NotNull
+ protected List<ArrangementGroupingRule> cloneGroupings() {
+ final ArrayList<ArrangementGroupingRule> groupings = new ArrayList<ArrangementGroupingRule>();
+ for (ArrangementGroupingRule grouping : myGroupings) {
+ groupings.add(grouping.clone());
+ }
+ return groupings;
+ }
+
+ @NotNull
+ protected List<StdArrangementMatchRule> cloneMatchRules() {
+ final ArrayList<StdArrangementMatchRule> rules = new ArrayList<StdArrangementMatchRule>();
+ for (StdArrangementMatchRule rule : myRules) {
+ rules.add(rule.clone());
+ }
+ return rules;
+ }
+
+ @NotNull
+ @Override
+ public ArrangementSettings clone() {
+ return new StdArrangementSettings(cloneGroupings(), cloneMatchRules());
+ }
+
@Override
@NotNull
public List<ArrangementGroupingRule> getGroupings() {
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java
index 06e2c78..d6503f5 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementSettingsToken.java
@@ -28,18 +28,34 @@
@NotNull private final StdArrangementTokenType myTokenType;
- public StdArrangementSettingsToken(@NotNull String id, @NotNull StdArrangementTokenType tokenType) {
- super(id, id.toLowerCase().replace("_", " "));
- myTokenType = tokenType;
+ @NotNull
+ public static StdArrangementSettingsToken tokenById(@NotNull String id,
+ @NotNull StdArrangementTokenType tokenType) {
+ return new StdArrangementSettingsToken(id, id.toLowerCase().replace("_", " "), tokenType);
}
- public StdArrangementSettingsToken (@NotNull String id, @NotNull @PropertyKey(resourceBundle = ApplicationBundle.BUNDLE) String key,
- @NotNull StdArrangementTokenType tokenType) {
- super(id, ApplicationBundle.message(key));
- myTokenType = tokenType;
+ @NotNull
+ public static StdArrangementSettingsToken token(@NotNull String id,
+ @NotNull String name,
+ @NotNull StdArrangementTokenType tokenType) {
+ return new StdArrangementSettingsToken(id, name, tokenType);
+ }
+
+ @NotNull
+ public static StdArrangementSettingsToken tokenByBundle(@NotNull String id,
+ @NotNull @PropertyKey(resourceBundle = ApplicationBundle.BUNDLE) String key,
+ @NotNull StdArrangementTokenType tokenType) {
+ return new StdArrangementSettingsToken(id, ApplicationBundle.message(key), tokenType);
}
@NotNull public StdArrangementTokenType getTokenType() {
return myTokenType;
}
+
+ private StdArrangementSettingsToken(@NotNull String id,
+ @NotNull String uiName,
+ @NotNull StdArrangementTokenType tokenType) {
+ super(id, uiName);
+ myTokenType = tokenType;
+ }
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java
index 6977aa8..3dfff48 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdArrangementTokens.java
@@ -88,14 +88,14 @@
}
private static StdArrangementSettingsToken token(@NotNull String id, @NotNull StdArrangementTokenType type) {
- StdArrangementSettingsToken result = new StdArrangementSettingsToken(id, type);
+ StdArrangementSettingsToken result = StdArrangementSettingsToken.tokenById(id, type);
TOKENS_BY_ID.put(id, result);
return result;
}
private static StdArrangementSettingsToken token(@NotNull String id, @NotNull @PropertyKey(resourceBundle = ApplicationBundle.BUNDLE) String key,
@NotNull StdArrangementTokenType type) {
- StdArrangementSettingsToken result = new StdArrangementSettingsToken(id, key, type);
+ StdArrangementSettingsToken result = StdArrangementSettingsToken.tokenByBundle(id, key, type);
TOKENS_BY_ID.put(id, result);
return result;
}
diff --git a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdRulePriorityAwareSettings.java b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdRulePriorityAwareSettings.java
index eb14752..de466e0 100644
--- a/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdRulePriorityAwareSettings.java
+++ b/platform/lang-api/src/com/intellij/psi/codeStyle/arrangement/std/StdRulePriorityAwareSettings.java
@@ -15,6 +15,7 @@
*/
package com.intellij.psi.codeStyle.arrangement.std;
+import com.intellij.psi.codeStyle.arrangement.ArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.RulePriorityAwareSettings;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementMatchRule;
@@ -59,4 +60,10 @@
}
return myRulesByPriority;
}
+
+ @NotNull
+ @Override
+ public ArrangementSettings clone() {
+ return new StdRulePriorityAwareSettings(cloneGroupings(), cloneMatchRules());
+ }
}
diff --git a/platform/lang-api/src/com/intellij/psi/impl/include/FileIncludeManager.java b/platform/lang-api/src/com/intellij/psi/impl/include/FileIncludeManager.java
index 3d3e7a0..086d6ce 100644
--- a/platform/lang-api/src/com/intellij/psi/impl/include/FileIncludeManager.java
+++ b/platform/lang-api/src/com/intellij/psi/impl/include/FileIncludeManager.java
@@ -37,6 +37,8 @@
public abstract VirtualFile[] getIncludedFiles(@NotNull VirtualFile file, boolean compileTimeOnly);
+ public abstract VirtualFile[] getIncludedFiles(@NotNull VirtualFile file, boolean compileTimeOnly, boolean recursively);
+
public abstract VirtualFile[] getIncludingFiles(@NotNull VirtualFile file, boolean compileTimeOnly);
public abstract void processIncludingFiles(PsiFile context, Processor<Pair<VirtualFile, FileIncludeInfo>> processor);
diff --git a/platform/lang-api/src/com/intellij/psi/stubs/SerializerClass.java b/platform/lang-api/src/com/intellij/psi/stubs/SerializerClass.java
deleted file mode 100644
index 88113f2..0000000
--- a/platform/lang-api/src/com/intellij/psi/stubs/SerializerClass.java
+++ /dev/null
@@ -1,29 +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.
- */
-
-/*
- * @author max
- */
-package com.intellij.psi.stubs;
-
-import java.lang.annotation.*;
-
-@Inherited
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface SerializerClass {
- Class<? extends StubSerializer> value();
-}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/psi/stubs/Stubbed.java b/platform/lang-api/src/com/intellij/psi/stubs/Stubbed.java
deleted file mode 100644
index 7dc359a..0000000
--- a/platform/lang-api/src/com/intellij/psi/stubs/Stubbed.java
+++ /dev/null
@@ -1,30 +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.
- */
-
-/*
- * @author max
- */
-package com.intellij.psi.stubs;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-@Retention(value = RetentionPolicy.RUNTIME)
-@Target(value = {ElementType.METHOD, ElementType.TYPE})
-public @interface Stubbed {
-}
\ No newline at end of file
diff --git a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
index 04c4b63..1cb4441 100644
--- a/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.java
+++ b/platform/lang-api/src/com/intellij/psi/util/PsiUtilBase.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.
@@ -142,7 +142,10 @@
}
@Nullable
- public static Language reallyEvaluateLanguageInRange(final int start, final int end, final PsiFile file) {
+ public static Language reallyEvaluateLanguageInRange(final int start, final int end, @NotNull PsiFile file) {
+ if (file instanceof PsiBinaryFile) {
+ return file.getLanguage();
+ }
Language lang = null;
int curOffset = start;
do {
@@ -170,7 +173,7 @@
}
@Nullable
- public static Language evaluateLanguageInRange(final int start, final int end, final PsiFile file) {
+ public static Language evaluateLanguageInRange(final int start, final int end, @NotNull PsiFile file) {
PsiElement elt = getElementAtOffset(file, start);
TextRange selectionRange = new TextRange(start, end);
diff --git a/platform/lang-api/src/com/intellij/refactoring/RefactoringBundle.java b/platform/lang-api/src/com/intellij/refactoring/RefactoringBundle.java
index e1604d6..692f889 100644
--- a/platform/lang-api/src/com/intellij/refactoring/RefactoringBundle.java
+++ b/platform/lang-api/src/com/intellij/refactoring/RefactoringBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;
@@ -29,8 +30,12 @@
* @author ven
*/
public class RefactoringBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.RefactoringBundle";
private RefactoringBundle() {
@@ -72,17 +77,12 @@
return message("cannot.perform.refactoring") + (message == null ? "" : "\n" + message);
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key) {
+ public static String message(@PropertyKey(resourceBundle = BUNDLE) String key) {
return CommonBundle.message(getBundle(), key);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/lang-api/src/com/intellij/refactoring/classMembers/MemberInfoBase.java b/platform/lang-api/src/com/intellij/refactoring/classMembers/MemberInfoBase.java
index 924764c..1ddbf5a 100644
--- a/platform/lang-api/src/com/intellij/refactoring/classMembers/MemberInfoBase.java
+++ b/platform/lang-api/src/com/intellij/refactoring/classMembers/MemberInfoBase.java
@@ -66,7 +66,7 @@
}
public T getMember() {
- LOG.assertTrue(myMember.isValid());
+ LOG.assertTrue(myMember.isValid(), myMember.getText() + " is invalid");
return myMember;
}
diff --git a/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringEventData.java b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringEventData.java
index 3907b5a..6435024 100644
--- a/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringEventData.java
+++ b/platform/lang-api/src/com/intellij/refactoring/listeners/RefactoringEventData.java
@@ -17,7 +17,9 @@
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.UserDataHolder;
+import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.PsiElement;
+import com.intellij.usageView.UsageInfo;
import com.intellij.util.Function;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
@@ -28,16 +30,11 @@
import java.util.List;
import java.util.Map;
-public class RefactoringEventData implements UserDataHolder {
- private Map<Key, Object> data;
-
+public class RefactoringEventData extends UserDataHolderBase {
public static final Key<Collection<? extends String>> CONFLICTS_KEY = Key.create("conflicts");
public static final Key<PsiElement> PSI_ELEMENT_KEY = Key.create("element");
public static final Key<PsiElement[]> PSI_ELEMENT_ARRAY_KEY = Key.create("elementArray");
-
- public RefactoringEventData() {
- data = new HashMap<Key, Object>();
- }
+ public static final Key<Collection<UsageInfo>> USAGE_INFOS_KEY = Key.create("usageInfos");
public void addElement(PsiElement element) {
putUserData(PSI_ELEMENT_KEY, element);
@@ -58,16 +55,8 @@
public void addElements(PsiElement[] elements) {
putUserData(PSI_ELEMENT_ARRAY_KEY, elements);
}
-
-
- @Nullable
- @Override
- public <T> T getUserData(@NotNull Key<T> key) {
- return (T)data.get(key);
- }
- @Override
- public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
- data.put(key, value);
+ public void addUsages(Collection<UsageInfo> usageInfos) {
+ putUserData(USAGE_INFOS_KEY, usageInfos);
}
}
diff --git a/platform/lang-api/src/com/intellij/refactoring/util/CommonRefactoringUtil.java b/platform/lang-api/src/com/intellij/refactoring/util/CommonRefactoringUtil.java
index 44db009..7ae5549 100644
--- a/platform/lang-api/src/com/intellij/refactoring/util/CommonRefactoringUtil.java
+++ b/platform/lang-api/src/com/intellij/refactoring/util/CommonRefactoringUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -84,7 +84,7 @@
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- if (editor == null) {
+ if (editor == null || editor.getComponent().getRootPane() == null) {
showErrorMessage(title, message, helpId, project);
}
else {
@@ -96,7 +96,7 @@
@NonNls
public static String htmlEmphasize(String text) {
- return "<b><code>" + StringUtil.escapeXml(text) + "</code></b>";
+ return StringUtil.htmlEmphasize(text);
}
public static boolean checkReadOnlyStatus(@NotNull PsiElement element) {
diff --git a/platform/lang-api/src/com/intellij/semantic/SemKey.java b/platform/lang-api/src/com/intellij/semantic/SemKey.java
index 6379dee..9eadf0b 100644
--- a/platform/lang-api/src/com/intellij/semantic/SemKey.java
+++ b/platform/lang-api/src/com/intellij/semantic/SemKey.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.
diff --git a/platform/lang-api/src/com/intellij/usageView/UsageInfo.java b/platform/lang-api/src/com/intellij/usageView/UsageInfo.java
deleted file mode 100644
index fa1ab06..0000000
--- a/platform/lang-api/src/com/intellij/usageView/UsageInfo.java
+++ /dev/null
@@ -1,269 +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.usageView;
-
-import com.intellij.lang.injection.InjectedLanguageManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.OpenFileDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.ProperTextRange;
-import com.intellij.openapi.util.Segment;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class UsageInfo {
- public static final UsageInfo[] EMPTY_ARRAY = new UsageInfo[0];
- private static final Logger LOG = Logger.getInstance("#com.intellij.usageView.UsageInfo");
- private final SmartPsiElementPointer<?> mySmartPointer;
- private final SmartPsiFileRange myPsiFileRange;
-
- public final boolean isNonCodeUsage;
- protected boolean myDynamicUsage = false;
-
- public UsageInfo(@NotNull PsiElement element, int startOffset, int endOffset, boolean isNonCodeUsage) {
- element = element.getNavigationElement();
- PsiFile file = element.getContainingFile();
- PsiElement topElement = file == null ? element : file;
- LOG.assertTrue(topElement.isValid(), element);
- Project project = topElement.getProject();
- SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project);
-
- TextRange elementRange = element.getTextRange();
- if (elementRange == null) {
- throw new IllegalArgumentException("text range null for " + element + "; " + element.getClass());
- }
- if (startOffset == -1 && endOffset == -1) {
- // calculate natural element range
- startOffset = element.getTextOffset() - elementRange.getStartOffset();
- endOffset = elementRange.getEndOffset() - elementRange.getStartOffset();
- }
-
- if (startOffset < 0) {
- throw new IllegalArgumentException("element " + element + "; startOffset " +startOffset);
- }
- if (startOffset > endOffset) {
- throw new IllegalArgumentException("element " + element + "; diff " + (endOffset-startOffset));
- }
-
- if (startOffset != element.getTextOffset() - elementRange.getStartOffset() || endOffset != elementRange.getLength()) {
- mySmartPointer = smartPointerManager.createSmartPsiElementPointer(element, file);
- TextRange rangeToStore;
- if (file != null && InjectedLanguageManager.getInstance(project).isInjectedFragment(file)) {
- rangeToStore = elementRange;
- }
- else {
- rangeToStore = TextRange.create(startOffset, endOffset).shiftRight(elementRange.getStartOffset());
- }
- myPsiFileRange = smartPointerManager.createSmartPsiFileRangePointer(file, rangeToStore);
- }
- else {
- mySmartPointer = smartPointerManager.createSmartPsiElementPointer(element);
- myPsiFileRange = null;
- }
- this.isNonCodeUsage = isNonCodeUsage;
- }
-
- public UsageInfo(@NotNull SmartPsiElementPointer<?> smartPointer,
- SmartPsiFileRange psiFileRange,
- boolean dynamicUsage,
- boolean nonCodeUsage) {
- myDynamicUsage = dynamicUsage;
- isNonCodeUsage = nonCodeUsage;
- myPsiFileRange = psiFileRange;
- mySmartPointer = smartPointer;
- }
-
- public SmartPsiElementPointer<?> getSmartPointer() {
- return mySmartPointer;
- }
-
- public SmartPsiFileRange getPsiFileRange() {
- return myPsiFileRange;
- }
-
- public boolean isNonCodeUsage() {
- return isNonCodeUsage;
- }
-
- public void setDynamicUsage(boolean dynamicUsage) {
- myDynamicUsage = dynamicUsage;
- }
-
- public UsageInfo(@NotNull PsiElement element, boolean isNonCodeUsage) {
- this(element, -1, -1, isNonCodeUsage);
- }
-
- public UsageInfo(@NotNull PsiElement element, int startOffset, int endOffset) {
- this(element, startOffset, endOffset, false);
- }
-
- public UsageInfo(@NotNull PsiReference reference) {
- this(reference.getElement(), reference.getRangeInElement().getStartOffset(), reference.getRangeInElement().getEndOffset());
- myDynamicUsage = reference.resolve() == null;
- }
-
- public UsageInfo(@NotNull PsiQualifiedReferenceElement reference) {
- this((PsiElement)reference);
- }
-
- public UsageInfo(@NotNull PsiElement element) {
- this(element, false);
- }
-
- @Nullable
- public PsiElement getElement() { // SmartPointer is used to fix SCR #4572, hotya eto krivo i nado vse perepisat'
- return mySmartPointer.getElement();
- }
-
- @Nullable
- public PsiReference getReference() {
- PsiElement element = getElement();
- return element == null ? null : element.getReference();
- }
-
- /**
- * @deprecated for the range in element use {@link #getRangeInElement} instead,
- * for the whole text range in the file covered by this usage info, use {@link #getSegment()}
- */
- public TextRange getRange() {
- return getRangeInElement();
- }
-
- /**
- * @return range in element
- */
- @Nullable("null means range is invalid")
- public ProperTextRange getRangeInElement() {
- PsiElement element = getElement();
- if (element == null) return null;
- TextRange elementRange = element.getTextRange();
- ProperTextRange result;
- if (myPsiFileRange == null) {
- int startOffset = element.getTextOffset();
- result = ProperTextRange.create(startOffset, elementRange.getEndOffset());
- }
- else {
- Segment rangeInFile = myPsiFileRange.getRange();
- if (rangeInFile == null) return null;
- result = ProperTextRange.create(rangeInFile);
- }
- int delta = elementRange.getStartOffset();
- return result.getStartOffset() < delta ? null : result.shiftRight(-delta);
- }
-
- /**
- * Override this method if you want a tooltip to be displayed for this usage
- */
- public String getTooltipText () {
- return null;
- }
-
- public final void navigateTo(boolean requestFocus) {
- int offset = getNavigationOffset();
- VirtualFile file = getVirtualFile();
- Project project = getProject();
- FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file, offset), requestFocus);
- }
-
- public int getNavigationOffset() {
- if (myPsiFileRange != null) {
- final Segment range = myPsiFileRange.getRange();
- if (range != null) {
- return range.getStartOffset();
- }
- }
-
- PsiElement element = getElement();
- if (element == null) return -1;
- TextRange range = element.getTextRange();
-
- TextRange rangeInElement = getRangeInElement();
- if (rangeInElement == null) return -1;
- return range.getStartOffset() + rangeInElement.getStartOffset();
- }
-
- public boolean isValid() {
- return getSegment() != null;
- }
-
- @Nullable
- public Segment getSegment() {
- PsiElement element = getElement();
- if (element == null) return null;
- TextRange range = element.getTextRange();
- ProperTextRange.assertProperRange(range, element);
- if (element instanceof PsiFile) {
- // hack: it's actually a range inside file, use document for range checking since during the "find|replace all" operation, file range might have been changed
- Document document = PsiDocumentManager.getInstance(getProject()).getDocument((PsiFile)element);
- if (document != null) {
- range = new ProperTextRange(0, document.getTextLength());
- }
- }
- ProperTextRange rangeInElement = getRangeInElement();
- if (rangeInElement == null) return null;
- return new ProperTextRange(Math.min(range.getEndOffset(), range.getStartOffset() + rangeInElement.getStartOffset()),
- Math.min(range.getEndOffset(), range.getStartOffset() + rangeInElement.getEndOffset()));
- }
-
- @NotNull
- public Project getProject() {
- return mySmartPointer.getProject();
- }
-
- public final boolean isWritable() {
- PsiElement element = getElement();
- return element == null || element.isWritable();
- }
-
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!getClass().equals(o.getClass())) return false;
-
- final UsageInfo usageInfo = (UsageInfo)o;
-
- if (isNonCodeUsage != usageInfo.isNonCodeUsage) return false;
-
- SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(getProject());
- return smartPointerManager.pointToTheSameElement(mySmartPointer, usageInfo.mySmartPointer)
- && (myPsiFileRange == null || usageInfo.myPsiFileRange != null && smartPointerManager.pointToTheSameElement(myPsiFileRange, usageInfo.myPsiFileRange));
- }
-
- public int hashCode() {
- int result = mySmartPointer != null ? mySmartPointer.hashCode() : 0;
- result = 29 * result + (myPsiFileRange == null ? 0 : myPsiFileRange.hashCode());
- result = 29 * result + (isNonCodeUsage ? 1 : 0);
- return result;
- }
-
- @Nullable
- public PsiFile getFile() {
- return mySmartPointer.getContainingFile();
- }
-
- @Nullable
- public VirtualFile getVirtualFile() {
- return mySmartPointer.getVirtualFile();
- }
-
- public boolean isDynamicUsage() {
- return myDynamicUsage;
- }
-}
diff --git a/platform/lang-api/src/com/intellij/usageView/UsageViewBundle.java b/platform/lang-api/src/com/intellij/usageView/UsageViewBundle.java
index ebbff10..9e4d1f1 100644
--- a/platform/lang-api/src/com/intellij/usageView/UsageViewBundle.java
+++ b/platform/lang-api/src/com/intellij/usageView/UsageViewBundle.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,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,8 +29,12 @@
* @author yole
*/
public class UsageViewBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.UsageView";
private UsageViewBundle() {
@@ -50,13 +55,8 @@
return " (" + message("occurence.info.reference", usagesCount, filesCount) + ")";
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ public static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/lang-api/src/com/intellij/usageView/UsageViewDescriptor.java b/platform/lang-api/src/com/intellij/usageView/UsageViewDescriptor.java
index 6800e0e..0db0d6c 100644
--- a/platform/lang-api/src/com/intellij/usageView/UsageViewDescriptor.java
+++ b/platform/lang-api/src/com/intellij/usageView/UsageViewDescriptor.java
@@ -19,6 +19,9 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+/**
+ * TODO: Document
+ */
public interface UsageViewDescriptor {
/**
* @return an array of elements whose usages were searched or {@link com.intellij.psi.PsiElement#EMPTY_ARRAY} if not available
diff --git a/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/ArrangementSettingsSerializationTest.java b/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/ArrangementSettingsSerializationTest.java
index be2631f..57c578d 100644
--- a/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/ArrangementSettingsSerializationTest.java
+++ b/platform/lang-api/testSources/com/intellij/psi/codeStyle/arrangement/ArrangementSettingsSerializationTest.java
@@ -22,12 +22,13 @@
import com.intellij.psi.codeStyle.arrangement.std.StdArrangementSettings;
import com.intellij.psi.codeStyle.arrangement.std.StdRulePriorityAwareSettings;
import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
import org.junit.Test;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.EntryType.FIELD;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Grouping.OVERRIDDEN_METHODS;
import static com.intellij.psi.codeStyle.arrangement.std.StdArrangementTokens.Order.BY_NAME;
-import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.*;
/**
* @author Denis Zhdanov
@@ -35,17 +36,108 @@
*/
public class ArrangementSettingsSerializationTest {
- @Test
- public void all() {
- StdArrangementSettings settings = new StdRulePriorityAwareSettings();
- settings.addGrouping(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
- ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
- settings.addRule(new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME));
-
+ private static Element doSerializationTest(@NotNull StdArrangementSettings settings, @NotNull StdArrangementSettings defaultSettings) {
Element holder = new Element("holder");
- ArrangementSettingsSerializer instance = DefaultArrangementSettingsSerializer.INSTANCE;
+ ArrangementSettingsSerializer instance = new TestArrangementSettingsSerializer(defaultSettings);
instance.serialize(settings, holder);
ArrangementSettings restored = instance.deserialize(holder);
assertEquals(settings, restored);
+ return holder;
+ }
+
+ @Test
+ public void all() {
+ final StdArrangementSettings settings = new StdRulePriorityAwareSettings();
+ settings.addGrouping(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
+ final ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
+ settings.addRule(new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME));
+ doSerializationTest(settings, new StdArrangementSettings());
+ }
+
+ @Test
+ public void testDefaultFilter() {
+ final StdArrangementSettings settings = new StdRulePriorityAwareSettings();
+ settings.addGrouping(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
+ final ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
+ settings.addRule(new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME));
+
+ final Element holder = doSerializationTest(settings, settings);
+ assertTrue(holder.getChildren().isEmpty());
+ }
+
+ @Test
+ public void testDefaultGroupingFilter() {
+ final ArrangementGroupingRule groupingRule = new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME);
+ final ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
+ final StdArrangementMatchRule rule = new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME);
+
+ final StdArrangementSettings settings = new StdRulePriorityAwareSettings();
+ settings.addGrouping(groupingRule);
+ settings.addRule(rule);
+ final StdArrangementSettings defaultSettings = new StdRulePriorityAwareSettings();
+ defaultSettings.addGrouping(groupingRule);
+
+ final Element holder = doSerializationTest(settings, defaultSettings);
+ assertTrue(holder.getChildren().size() == 1);
+ assertNull(holder.getChild("groups"));
+ assertNotNull(holder.getChild("rules"));
+ }
+
+ @Test
+ public void testDefaultRulesFilter() {
+ final ArrangementGroupingRule groupingRule = new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME);
+ final ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
+ final StdArrangementMatchRule rule = new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME);
+
+ final StdArrangementSettings settings = new StdRulePriorityAwareSettings();
+ settings.addGrouping(groupingRule);
+ settings.addRule(rule);
+ final StdArrangementSettings defaultSettings = new StdRulePriorityAwareSettings();
+ defaultSettings.addRule(rule);
+
+ final Element holder = doSerializationTest(settings, defaultSettings);
+ assertTrue(holder.getChildren().size() == 1);
+ assertNotNull(holder.getChild("groups"));
+ assertNull(holder.getChild("rules"));
+ }
+
+ @Test
+ public void testEmptyGroupings() throws Exception {
+ final StdArrangementSettings settings = new StdRulePriorityAwareSettings();
+ final ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
+ settings.addRule(new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME));
+
+ final StdArrangementSettings defaultSettings = new StdRulePriorityAwareSettings();
+ defaultSettings.addGrouping(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
+
+ final Element holder = doSerializationTest(settings, defaultSettings);
+ assertTrue(holder.getChildren().size() == 2);
+ final Element groups = holder.getChild("groups");
+ assertNotNull(groups);
+ assertTrue(groups.getChildren().isEmpty());
+ }
+
+ @Test
+ public void testEmptyRules() throws Exception {
+ final StdArrangementSettings settings = new StdRulePriorityAwareSettings();
+ settings.addGrouping(new ArrangementGroupingRule(OVERRIDDEN_METHODS, BY_NAME));
+
+ final StdArrangementSettings defaultSettings = new StdRulePriorityAwareSettings();
+ final ArrangementAtomMatchCondition condition = new ArrangementAtomMatchCondition(FIELD);
+ final StdArrangementMatchRule rule = new StdArrangementMatchRule(new StdArrangementEntryMatcher(condition), BY_NAME);
+ defaultSettings.addRule(rule);
+
+ final Element holder = doSerializationTest(settings, defaultSettings);
+ assertTrue(holder.getChildren().size() == 2);
+ final Element rules = holder.getChild("rules");
+ assertNotNull(rules);
+ assertTrue(rules.getChildren().isEmpty());
+ }
+
+ private static class TestArrangementSettingsSerializer extends DefaultArrangementSettingsSerializer {
+
+ public TestArrangementSettingsSerializer(@NotNull StdArrangementSettings defaultSettings) {
+ super(defaultSettings);
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSpacesPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSpacesPanel.java
index 82af4ea..51c946b 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSpacesPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/CodeStyleSpacesPanel.java
@@ -115,6 +115,9 @@
initBooleanField("SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS", ApplicationBundle.message("checkbox.spaces.after.comma"), SPACES_WITHIN_TYPE_ARGUMENTS);
initCustomOptions(SPACES_WITHIN_TYPE_ARGUMENTS);
+ initCustomOptions(SPACES_IN_TYPE_ARGUMENTS);
+ initCustomOptions(SPACES_IN_TYPE_PARAMETERS);
+
initBooleanField("SPACE_BEFORE_COMMA", ApplicationBundle.message("checkbox.spaces.before.comma"), SPACES_OTHER);
initBooleanField("SPACE_AFTER_COMMA", ApplicationBundle.message("checkbox.spaces.after.comma"), SPACES_OTHER);
initBooleanField("SPACE_BEFORE_SEMICOLON", ApplicationBundle.message("checkbox.spaces.before.semicolon"), SPACES_OTHER);
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java
index 071330c..67b99f1 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/ManageCodeStyleSchemesDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -257,7 +257,7 @@
ApplicationBundle.message("message.code.style.scheme.already.exists", targetName),
ApplicationBundle.message("title.code.style.settings.import"),
Messages.getQuestionIcon());
- if (result != Messages.OK) {
+ if (result != Messages.YES) {
return null;
}
}
@@ -424,7 +424,7 @@
.showYesNoDialog("Scheme '" + scheme.getName() + "' was copied to be used as the project scheme.\n" +
"Switch to this created scheme?",
"Copy Scheme to Project", Messages.getQuestionIcon());
- if (switchToProject == 0) {
+ if (switchToProject == Messages.YES) {
mySchemesModel.setUsePerProjectSettings(true, true);
}
}
@@ -438,7 +438,7 @@
.showYesNoDialog("Project scheme was copied to global scheme list as '" + newScheme.getName() + "'.\n" +
"Switch to this created scheme?",
"Copy Project Scheme to Global List", Messages.getQuestionIcon());
- if (switchToGlobal == 0) {
+ if (switchToGlobal == Messages.YES) {
mySchemesModel.setUsePerProjectSettings(false);
mySchemesModel.selectScheme(newScheme, null);
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java
index 99defdf..673178a 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/OptionTreeWithPreviewPanel.java
@@ -219,7 +219,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (!optionsTree.isEnabled()) return false;
TreePath treePath = optionsTree.getPathForLocation(e.getX(), e.getY());
selectCheckbox(treePath);
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java
index 0f325f5..7fe6efd 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/ArrangementSettingsPanel.java
@@ -162,9 +162,7 @@
}
else {
List<ArrangementGroupingRule> groupings = s.getGroupings();
- if (!groupings.isEmpty()) {
- myGroupingRulesPanel.setRules(ContainerUtilRt.newArrayList(groupings));
- }
+ myGroupingRulesPanel.setRules(ContainerUtilRt.newArrayList(groupings));
myMatchingRulesPanel.setRules(copy(s.getRules()));
if (myForceArrangementPanel != null) {
myForceArrangementPanel.setSelectedMode(settings.getCommonSettings(myLanguage).FORCE_REARRANGE_MODE);
diff --git a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
index 455d35a..f863088 100644
--- a/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
+++ b/platform/lang-impl/src/com/intellij/application/options/codeStyle/arrangement/component/ArrangementAtomMatchConditionComponent.java
@@ -55,6 +55,7 @@
@NotNull
private final SimpleColoredComponent myTextControl = new SimpleColoredComponent() {
+ @NotNull
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
@@ -65,6 +66,7 @@
return getPreferredSize();
}
+ @NotNull
@Override
public Dimension getPreferredSize() {
return myTextControlSize == null ? super.getPreferredSize() : myTextControlSize;
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
index ef9856e..5159dfc 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/ColorAndFontOptions.java
@@ -253,7 +253,7 @@
"Darcula color scheme has been set for editors. Would you like to set Darcula as default Look and Feel?",
"Darcula Look and Feel",
Messages.getQuestionIcon());
- if (ok == Messages.OK) {
+ if (ok == Messages.YES) {
LafManager.getInstance().setCurrentLookAndFeel(new DarculaLookAndFeelInfo());
DarculaInstaller.install();
}
diff --git a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
index 72c8f5c..cf2172e 100644
--- a/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
+++ b/platform/lang-impl/src/com/intellij/application/options/colors/FontOptions.java
@@ -39,14 +39,9 @@
import javax.swing.event.DocumentEvent;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.awt.event.*;
+import java.util.*;
import java.util.List;
-import java.util.Set;
public class FontOptions extends JPanel implements OptionsPanel{
@@ -148,6 +143,21 @@
updateDescription(true);
}
});
+ myEditorFontSizeField.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() != KeyEvent.VK_UP && e.getKeyCode() != KeyEvent.VK_DOWN) return;
+ boolean up = e.getKeyCode() == KeyEvent.VK_UP;
+ try {
+ int value = Integer.parseInt(myEditorFontSizeField.getText());
+ value += (up ? 1 : -1);
+ value = Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, Math.max(OptionsConstants.MIN_EDITOR_FONT_SIZE, value));
+ myEditorFontSizeField.setText(String.valueOf(value));
+ }
+ catch (NumberFormatException ignored) {
+ }
+ }
+ });
myLineSpacingField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
@@ -160,11 +170,26 @@
updateDescription(true);
}
});
+ myLineSpacingField.addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyPressed(KeyEvent e) {
+ if (e.getKeyCode() != KeyEvent.VK_UP && e.getKeyCode() != KeyEvent.VK_DOWN) return;
+ boolean up = e.getKeyCode() == KeyEvent.VK_UP;
+ try {
+ float value = Float.parseFloat(myLineSpacingField.getText());
+ value += (up ? 1 : -1) * .1F;
+ value = Math.min(OptionsConstants.MAX_EDITOR_LINE_SPACING, Math.max(OptionsConstants.MIN_EDITOR_LINE_SPACING, value));
+ myLineSpacingField.setText(String.format(Locale.ENGLISH, "%.1f", value));
+ }
+ catch (NumberFormatException ignored) {
+ }
+ }
+ });
}
private int getFontSizeFromField() {
try {
- return Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, Math.max(1, Integer.parseInt(myEditorFontSizeField.getText())));
+ return Math.min(OptionsConstants.MAX_EDITOR_FONT_SIZE, Math.max(OptionsConstants.MIN_EDITOR_FONT_SIZE, Integer.parseInt(myEditorFontSizeField.getText())));
}
catch (NumberFormatException e) {
return OptionsConstants.DEFAULT_EDITOR_FONT_SIZE;
@@ -173,9 +198,9 @@
private float getLineSpacingFromField() {
try {
- return Math.min(30, Math.max(.6F, Float.parseFloat(myLineSpacingField.getText())));
+ return Math.min(OptionsConstants.MAX_EDITOR_LINE_SPACING, Math.max(OptionsConstants.MIN_EDITOR_LINE_SPACING, Float.parseFloat(myLineSpacingField.getText())));
} catch (NumberFormatException e){
- return 1;
+ return OptionsConstants.DEFAULT_EDITOR_LINE_SPACING;
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/CodeEditorBundle.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/CodeEditorBundle.java
index ab636b1..5968d57 100644
--- a/platform/lang-impl/src/com/intellij/codeEditor/printing/CodeEditorBundle.java
+++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/CodeEditorBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* @author yole
*/
public class CodeEditorBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.CodeEditorBundle";
private CodeEditorBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLAction.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLAction.java
index 12d5fce..28a664c 100644
--- a/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLAction.java
+++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLAction.java
@@ -55,6 +55,7 @@
}
PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(dataContext);
presentation.setEnabled(psiFile != null && psiFile.getContainingDirectory() != null);
+ presentation.setVisible(psiFile != null);
}
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java b/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java
index d293a79..bc8830c 100644
--- a/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java
+++ b/platform/lang-impl/src/com/intellij/codeEditor/printing/ExportToHTMLManager.java
@@ -20,8 +20,6 @@
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
@@ -117,7 +115,7 @@
}
textPainter.paint(null, psiFile.getFileType());
if (exportToHTMLSettings.OPEN_IN_BROWSER) {
- BrowserUtil.launchBrowser(textPainter.getHTMLFileName());
+ BrowserUtil.browse(textPainter.getHTMLFileName());
}
}
else {
@@ -269,7 +267,7 @@
dirToShow += File.separatorChar;
}
dirToShow += PsiDirectoryFactory.getInstance(myProject).getQualifiedName(myPsiDirectory, false).replace('.', File.separatorChar);
- BrowserUtil.launchBrowser(dirToShow);
+ BrowserUtil.browse(dirToShow);
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
index 9f14e00..36bae6b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/AutoPopupController.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.
@@ -42,6 +42,7 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.util.Alarm;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class AutoPopupController implements Disposable {
@@ -150,7 +151,7 @@
myAlarm.cancelAllRequests();
}
- public void autoPopupParameterInfo(final Editor editor, @Nullable final PsiElement highlightedMethod){
+ public void autoPopupParameterInfo(@NotNull final Editor editor, @Nullable final PsiElement highlightedMethod){
if (ApplicationManager.getApplication().isUnitTestMode()) return;
if (DumbService.isDumb(myProject)) return;
if (PowerSaveMode.isEnabled()) return;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java
index 7e9b614..63dfe57 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/CodeInsightUtilBase.java
@@ -107,10 +107,16 @@
// returns true on success
public static boolean prepareEditorForWrite(@NotNull Editor editor) {
if (!editor.isViewer()) return true;
+ showReadOnlyViewWarning(editor);
+ return false;
+ }
+
+ public static void showReadOnlyViewWarning(Editor editor) {
+ if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
+
JComponent component = HintUtil.createInformationLabel("This view is read-only");
final LightweightHint hint = new LightweightHint(component);
HintManagerImpl.getInstanceImpl().showEditorHint(hint, editor, HintManager.UNDER,
HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING, 0, false);
- return false;
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java b/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java
index 59f2c99..62ff7b0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/TargetElementUtilBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -118,9 +118,6 @@
/**
* @deprecated adjust offset with PsiElement should be used instead to provide correct checking for identifier part
- * @param document
- * @param offset
- * @return
*/
public static int adjustOffset(Document document, final int offset) {
return adjustOffset(null, document, offset);
@@ -223,9 +220,11 @@
Lookup activeLookup = LookupManager.getInstance(project).getActiveLookup();
if (activeLookup != null) {
LookupElement item = activeLookup.getCurrentItem();
- final PsiElement psi = item == null ? null : CompletionUtil.getTargetElement(item);
- if (psi != null && psi.isValid()) {
- return psi;
+ if (item != null && item.isValid()) {
+ final PsiElement psi = CompletionUtil.getTargetElement(item);
+ if (psi != null && psi.isValid()) {
+ return psi;
+ }
}
}
return null;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java
index 19f2336..1a2d483 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/AbstractLayoutCodeProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -33,20 +33,22 @@
import com.intellij.openapi.progress.util.ProgressWindow;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectCoreUtil;
+import com.intellij.openapi.roots.GeneratedSourcesFilter;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ex.MessagesEx;
-import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.SequentialModalProgressTask;
import com.intellij.util.SequentialTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -58,7 +60,7 @@
private PsiDirectory myDirectory;
private PsiFile myFile;
- private PsiFile[] myFiles;
+ private List<PsiFile> myFiles;
private boolean myIncludeSubdirs;
private final String myProgressText;
@@ -66,10 +68,30 @@
private final Runnable myPostRunnable;
private final boolean myProcessChangedTextOnly;
+ protected AbstractLayoutCodeProcessor myPreviousCodeProcessor;
+
protected AbstractLayoutCodeProcessor(Project project, String commandName, String progressText, boolean processChangedTextOnly) {
this(project, (Module)null, commandName, progressText, processChangedTextOnly);
}
+ protected AbstractLayoutCodeProcessor(@NotNull AbstractLayoutCodeProcessor previous,
+ @NotNull String commandName,
+ @NotNull String progressText)
+ {
+ myProject = previous.myProject;
+ myModule = previous.myModule;
+ myDirectory = previous.myDirectory;
+ myFile = previous.myFile;
+ myFiles = previous.myFiles;
+ myIncludeSubdirs = previous.myIncludeSubdirs;
+ myProcessChangedTextOnly = previous.myProcessChangedTextOnly;
+
+ myPostRunnable = null;
+ myProgressText = progressText;
+ myCommandName = commandName;
+ myPreviousCodeProcessor = previous;
+ }
+
protected AbstractLayoutCodeProcessor(Project project,
@Nullable Module module,
String commandName,
@@ -127,21 +149,27 @@
{
myProject = project;
myModule = null;
- myFiles = filterFiles(files);
+ myFiles = filterFilesTo(files, new ArrayList<PsiFile>());
myProgressText = progressText;
myCommandName = commandName;
myPostRunnable = postRunnable;
myProcessChangedTextOnly = processChangedTextOnly;
}
- private static PsiFile[] filterFiles(PsiFile[] files){
- ArrayList<PsiFile> list = new ArrayList<PsiFile>();
+ private static List<PsiFile> filterFilesTo(PsiFile[] files, List<PsiFile> list) {
+ GeneratedSourcesFilter[] filters = GeneratedSourcesFilter.EP_NAME.getExtensions();
for (PsiFile file : files) {
- if (isFormatable(file)) {
+ if (canBeFormatted(file, filters)) {
list.add(file);
}
}
- return PsiUtilCore.toPsiFileArray(list);
+ return list;
+ }
+
+ @Nullable
+ private FutureTask<Boolean> getPreviousProcessorTask(@NotNull PsiFile file, boolean processChangedTextOnly) {
+ return myPreviousCodeProcessor != null ? myPreviousCodeProcessor.preprocessFile(file, processChangedTextOnly)
+ : null;
}
/**
@@ -154,8 +182,25 @@
* @throws IncorrectOperationException if unexpected exception occurred during formatting
*/
@NotNull
- protected abstract FutureTask<Boolean> preprocessFile(@NotNull PsiFile file, boolean processChangedTextOnly)
- throws IncorrectOperationException;
+ protected abstract FutureTask<Boolean> prepareTask(@NotNull PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException;
+
+ public FutureTask<Boolean> preprocessFile(@NotNull PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException {
+ final FutureTask<Boolean> previousTask = getPreviousProcessorTask(file, processChangedTextOnly);
+ final FutureTask<Boolean> currentTask = prepareTask(file, processChangedTextOnly);
+
+ return new FutureTask<Boolean>(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ if (previousTask != null) {
+ previousTask.run();
+ if (!previousTask.get() || previousTask.isCancelled()) return false;
+ }
+
+ currentTask.run();
+ return currentTask.get() && !currentTask.isCancelled();
+ }
+ });
+ }
public void run() {
if (myDirectory != null){
@@ -272,7 +317,7 @@
};
}
- private void runProcessFiles(final PsiFile[] files) {
+ private void runProcessFiles(final List<PsiFile> files) {
// let's just ignore read-only files here
final Runnable[] resultRunnable = new Runnable[1];
@@ -280,7 +325,7 @@
new Runnable() {
@Override
public void run() {
- resultRunnable[0] = preprocessFiles(new ArrayList<PsiFile>(Arrays.asList(files)));
+ resultRunnable[0] = preprocessFiles(new ArrayList<PsiFile>(files));
}
},
new Runnable() {
@@ -290,13 +335,13 @@
resultRunnable[0].run();
}
}
- }, files.length > 1
+ }, files.size() > 1
);
}
private void runProcessDirectory(final PsiDirectory directory, final boolean recursive) {
final ArrayList<PsiFile> array = new ArrayList<PsiFile>();
- collectFilesToProcess(array, directory, getIgnoreRoots(directory.getProject()), recursive);
+ collectFilesToProcess(array, directory, recursive);
final String where = CodeInsightBundle.message("process.scope.directory", directory.getVirtualFile().getPresentableUrl());
runProcessOnFiles(where, array);
}
@@ -327,7 +372,7 @@
for (VirtualFile root : contentRoots) {
PsiDirectory dir = PsiManager.getInstance(myProject).findDirectory(root);
if (dir != null) {
- collectFilesToProcess(array, dir, getIgnoreRoots(module.getProject()), true);
+ collectFilesToProcess(array, dir, true);
}
}
}
@@ -345,7 +390,7 @@
if (writeables.isEmpty()) return;
int res = Messages.showOkCancelDialog(myProject, CodeInsightBundle.message("error.dialog.readonly.files.message", where),
CodeInsightBundle.message("error.dialog.readonly.files.title"), Messages.getQuestionIcon());
- if (res != 0) {
+ if (res != Messages.OK) {
return;
}
@@ -369,80 +414,30 @@
}, array.size() > 1);
}
- private static boolean isFormatable(PsiFile file) {
- return LanguageFormatting.INSTANCE.forContext(file) != null;
- }
-
- /**
- * There is a possible case that 'reformat' is invoked against particular directory via 'Project View'. We don't want
- * to modify project/module files then (these are internal files and their change due to reformatting will trigger dialog
- * that asks user if he or she wants to reload a project because of config file contents change).
- * <p/>
- * This method allows to collect set of file system entries (either files or directories) which contents should be ignored
- * during bulk reformatting.
- *
- * @param project target project
- * @return collection of file system entries that shouldn't be touched during bulk reformatting
- */
- private static Set<VirtualFile> getIgnoreRoots(@NotNull Project project) {
- Set<VirtualFile> result = new HashSet<VirtualFile>();
-
- VirtualFile projectBaseDir = project.getBaseDir();
- if (projectBaseDir != null && projectBaseDir.isDirectory()) {
- VirtualFile projectVirtualDirectory = projectBaseDir.findChild(Project.DIRECTORY_STORE_FOLDER);
- if (projectVirtualDirectory != null) {
- result.add(projectVirtualDirectory);
- }
- }
-
- VirtualFile projectFile = project.getProjectFile();
- if (projectFile != null) {
- result.add(projectFile);
- }
-
- VirtualFile workspaceFile = project.getWorkspaceFile();
- if (workspaceFile != null) {
- result.add(workspaceFile);
- }
-
- for (Module m : ModuleManager.getInstance(project).getModules()) {
- VirtualFile moduleFile = m.getModuleFile();
- if (moduleFile != null) {
- result.add(moduleFile);
- }
- }
-
- return result;
- }
-
- private static void collectFilesToProcess(ArrayList<PsiFile> array, PsiDirectory dir, @NotNull Set<VirtualFile> ignoreRoots,
- boolean recursive)
- {
- PsiFile[] files = dir.getFiles();
- for (PsiFile file : files) {
- if (isFormatable(file) && !shouldIgnore(file, ignoreRoots)) {
- array.add(file);
- }
- }
- if (recursive){
- PsiDirectory[] subdirs = dir.getSubdirectories();
- for (PsiDirectory subdir : subdirs) {
- collectFilesToProcess(array, subdir, ignoreRoots, recursive);
- }
- }
- }
-
- private static boolean shouldIgnore(@NotNull PsiFile file, Set<VirtualFile> ignoreRoots) {
- VirtualFile virtualFile = file.getVirtualFile();
- if (virtualFile == null) {
+ private static boolean canBeFormatted(PsiFile file, GeneratedSourcesFilter[] generatedSourcesFilters) {
+ if (LanguageFormatting.INSTANCE.forContext(file) == null) {
return false;
}
- for (VirtualFile root : ignoreRoots) {
- if (VfsUtilCore.isAncestor(root, virtualFile, false)) {
- return true;
+ VirtualFile virtualFile = file.getVirtualFile();
+ if (virtualFile == null) return true;
+
+ if (ProjectCoreUtil.isProjectOrWorkspaceFile(virtualFile)) return false;
+
+ for (GeneratedSourcesFilter filter : generatedSourcesFilters) {
+ if (filter.isGeneratedSource(virtualFile, file.getProject())) {
+ return false;
}
}
- return false;
+ return true;
+ }
+
+ private static void collectFilesToProcess(List<PsiFile> result, PsiDirectory dir, boolean recursive) {
+ filterFilesTo(dir.getFiles(), result);
+ if (recursive) {
+ for (PsiDirectory subdir : dir.getSubdirectories()) {
+ collectFilesToProcess(result, subdir, recursive);
+ }
+ }
}
private void runLayoutCodeProcess(final Runnable readAction, final Runnable writeAction, final boolean globalAction) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/DirectoryFormattingOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/DirectoryFormattingOptions.java
new file mode 100644
index 0000000..9a4c08e
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/DirectoryFormattingOptions.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.actions;
+
+public interface DirectoryFormattingOptions extends ReformatFilesOptions {
+
+ boolean isIncludeSubdirectories();
+
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java
index 950e4c9..d387559 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeDialog.java
@@ -39,7 +39,7 @@
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
-public class LayoutCodeDialog extends DialogWrapper {
+public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions {
@NotNull private final Project myProject;
@Nullable private final PsiFile myFile;
@Nullable private final PsiDirectory myDirectory;
@@ -56,10 +56,10 @@
private final String myHelpId;
@Nullable private CommonCodeStyleSettings myCommonSettings;
- private boolean myForceArrangeModeEnabled;
+ private boolean myRearrangeAlwaysEnabled;
- public LayoutCodeDialog(@NotNull Project project,
+ public LayoutCodeDialog(@NotNull Project project,
@NotNull String title,
@Nullable PsiFile file,
@Nullable PsiDirectory directory,
@@ -72,9 +72,9 @@
myTextSelected = isTextSelected;
if (myFile != null) myCommonSettings = CodeStyleSettingsManager.getSettings(myProject).getCommonSettings(myFile.getLanguage());
- myForceArrangeModeEnabled = myCommonSettings != null
- && myCommonSettings.isForceArrangeMenuAvailable()
- && myCommonSettings.FORCE_REARRANGE_MODE != CommonCodeStyleSettings.REARRANGE_ACCORDIND_TO_DIALOG;
+ myRearrangeAlwaysEnabled = myCommonSettings != null
+ && myCommonSettings.isForceArrangeMenuAvailable()
+ && myCommonSettings.FORCE_REARRANGE_MODE == CommonCodeStyleSettings.REARRANGE_ALWAYS;
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
setTitle(title);
@@ -101,9 +101,7 @@
myCbIncludeSubdirs.setSelected(true);
//Loading previous state
myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
- myCbArrangeEntries.setSelected(myForceArrangeModeEnabled ? myCommonSettings.FORCE_REARRANGE_MODE == CommonCodeStyleSettings.REARRANGE_ALWAYS
- : ReformatCodeAction.getLastSavedRearrangeCbState(myProject, myFile));
-
+ myCbArrangeEntries.setSelected(myRearrangeAlwaysEnabled || ReformatCodeAction.getLastSavedRearrangeCbState(myProject, myFile));
myCbOnlyVcsChangedRegions.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false));
ItemListener listener = new ItemListener() {
@@ -126,11 +124,14 @@
!myRbSelectedText.isSelected()
&& !(myFile != null && LanguageImportStatements.INSTANCE.forFile(myFile).isEmpty() && myRbFile.isSelected())
);
- myCbArrangeEntries.setEnabled(myFile != null
- && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null
- && !myForceArrangeModeEnabled
+ myCbArrangeEntries.setEnabled(isProcessDirectory()
+ || myFile != null
+ && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null
+ && !myRearrangeAlwaysEnabled
);
-
+ if (myRearrangeAlwaysEnabled && !myCbArrangeEntries.isEnabled()) {
+ myCbArrangeEntries.setSelected(true);
+ }
myCbOnlyVcsChangedRegions.setEnabled(canTargetVcsRegions());
myDoNotAskMeCheckBox.setEnabled(!myRbDirectory.isSelected());
myRbDirectory.setEnabled(!myDoNotAskMeCheckBox.isSelected());
@@ -185,7 +186,8 @@
}
myCbArrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries"));
- if (myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null) {
+ if (myDirectory != null || myFile != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null)
+ {
gbConstraints.gridy++;
gbConstraints.insets = new Insets(0, 0, 0, 0);
panel.add(myCbArrangeEntries, gbConstraints);
@@ -230,30 +232,37 @@
HelpManager.getInstance().invokeHelp(myHelpId);
}
+
public boolean isProcessSelectedText() {
return myRbSelectedText.isSelected();
}
+ @Override
public boolean isProcessWholeFile() {
return myRbFile.isSelected();
}
+ @Override
public boolean isProcessDirectory() {
return myRbDirectory.isSelected();
}
+ @Override
public boolean isIncludeSubdirectories() {
return myCbIncludeSubdirs.isSelected();
}
+ @Override
public boolean isOptimizeImports() {
return myCbOptimizeImports.isSelected();
}
+ @Override
public boolean isRearrangeEntries() {
return myCbArrangeEntries.isSelected();
}
-
+
+ @Override
public boolean isProcessOnlyChangedText() {
return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
}
@@ -270,7 +279,6 @@
@Override
protected void doOKAction() {
super.doOKAction();
- //Saving checkboxes state
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myCbOptimizeImports.isSelected()));
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected()));
saveRearrangeCbState(myCbArrangeEntries.isSelected());
@@ -289,7 +297,7 @@
}
if (isProcessWholeFile()) {
- return FormatChangedTextUtil.hasChanges(myFile);
+ return myFile != null && FormatChangedTextUtil.hasChanges(myFile);
}
if (isProcessDirectory()) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java
new file mode 100644
index 0000000..5a05a9a
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutCodeOptions.java
@@ -0,0 +1,24 @@
+/*
+ * 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.codeInsight.actions;
+
+public interface LayoutCodeOptions extends DirectoryFormattingOptions {
+
+ boolean isProcessWholeFile();
+
+ boolean isProcessDirectory();
+
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutDirectoryDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutDirectoryDialog.java
new file mode 100644
index 0000000..e8be41b
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutDirectoryDialog.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.codeInsight.actions;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class LayoutDirectoryDialog extends LayoutProjectCodeDialog implements DirectoryFormattingOptions {
+ private JCheckBox myIncludeSubdirs;
+
+ public LayoutDirectoryDialog(@NotNull Project project,
+ String title,
+ String text,
+ boolean enableOnlyVCSChangedTextCb)
+ {
+ super(project, title, text, true, enableOnlyVCSChangedTextCb);
+ }
+
+ public void setEnabledIncludeSubdirsCb(boolean isEnabled) {
+ myIncludeSubdirs.setEnabled(isEnabled);
+ }
+
+ public void setSelectedIncludeSubdirsCb(boolean isSelected) {
+ myIncludeSubdirs.setSelected(isSelected);
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel panel = new JPanel(new BorderLayout(0, 7));
+ JComponent layoutProjectDialog = super.createCenterPanel();
+
+ myIncludeSubdirs = new JCheckBox(CodeInsightBundle.message("reformat.option.include.subdirectories"));
+
+ panel.add(layoutProjectDialog, BorderLayout.CENTER);
+ panel.add(myIncludeSubdirs, BorderLayout.SOUTH);
+
+ return panel;
+ }
+
+ @Override
+ public boolean isIncludeSubdirectories() {
+ return myIncludeSubdirs.isSelected();
+ }
+
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java
index 638a225..aa4aadc 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/LayoutProjectCodeDialog.java
@@ -19,12 +19,10 @@
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.help.HelpManager;
-import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -32,29 +30,31 @@
/**
* @author max
*/
-public class LayoutProjectCodeDialog extends DialogWrapper {
+public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFilesOptions {
private static @NonNls final String HELP_ID = "editing.codeReformatting";
private final String myText;
+ private final boolean myEnableOnlyVCSChangedTextCb;
private final boolean mySuggestOptimizeImports;
private final Project myProject;
- private final Module myModule;
+
private JCheckBox myCbOptimizeImports;
private JCheckBox myCbOnlyVcsChangedRegions;
+ private JCheckBox myCbRearrangeEntries;
public LayoutProjectCodeDialog(@NotNull Project project,
- @Nullable Module module,
String title,
String text,
- boolean suggestOptimizeImports)
+ boolean suggestOptimizeImports,
+ boolean enableOnlyVCSChangedTextCb)
{
super(project, false);
myText = text;
mySuggestOptimizeImports = suggestOptimizeImports;
myProject = project;
- myModule = module;
-
+ myEnableOnlyVCSChangedTextCb = enableOnlyVCSChangedTextCb;
+
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
setTitle(title);
init();
@@ -62,20 +62,27 @@
@Override
protected JComponent createCenterPanel() {
- if (!mySuggestOptimizeImports) return new JLabel(myText);
- JPanel panel = new JPanel(new GridLayout(3, 1));
- panel.add(new JLabel(myText));
- myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports"));
- panel.add(myCbOptimizeImports);
- myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
+ if (!mySuggestOptimizeImports) {
+ return new JLabel(myText);
+ }
+ JPanel panel = new JPanel(new GridLayout(4, 1));
+ myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports"));
+ myCbRearrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries"));
myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region"));
+
+ panel.add(new JLabel(myText));
+ panel.add(myCbOptimizeImports);
+ panel.add(myCbRearrangeEntries);
panel.add(myCbOnlyVcsChangedRegions);
- final boolean canTargetVcsRegions = canTargetVcsRegions();
- myCbOnlyVcsChangedRegions.setEnabled(canTargetVcsRegions);
+
+ myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
+ myCbRearrangeEntries.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject));
+ myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb);
myCbOnlyVcsChangedRegions.setSelected(
- canTargetVcsRegions && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
+ myEnableOnlyVCSChangedTextCb && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
);
+
return panel;
}
@@ -86,6 +93,11 @@
}
@Override
+ public boolean isRearrangeEntries() {
+ return myCbRearrangeEntries.isSelected();
+ }
+
+ @Override
protected void doHelpAction() {
HelpManager.getInstance().invokeHelp(HELP_ID);
}
@@ -95,6 +107,10 @@
super.doOKAction();
if (mySuggestOptimizeImports) {
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports()));
+ LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries());
+ if (myEnableOnlyVCSChangedTextCb) {
+ PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected()));
+ }
}
}
@@ -105,12 +121,5 @@
public boolean isProcessOnlyChangedText() {
return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
}
-
- private boolean canTargetVcsRegions() {
- if (myModule != null) {
- return FormatChangedTextUtil.hasChanges(myModule);
- }
- return FormatChangedTextUtil.hasChanges(myProject);
- }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java
index 97555a3..bdcb777 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsAction.java
@@ -75,7 +75,7 @@
text = CodeInsightBundle.message("process.scope.project", projectContext.getPresentableUrl());
}
LayoutProjectCodeDialog dialog
- = new LayoutProjectCodeDialog(project, null, CodeInsightBundle.message("process.optimize.imports"), text, false);
+ = new LayoutProjectCodeDialog(project, CodeInsightBundle.message("process.optimize.imports"), text, false, FormatChangedTextUtil.hasChanges(project));
dialog.show();
if (!dialog.isOK()) return;
if (moduleContext != null) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java
index 86fa763..ed254ae 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/OptimizeImportsProcessor.java
@@ -24,7 +24,7 @@
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -34,7 +34,7 @@
public class OptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
private static final String PROGRESS_TEXT = CodeInsightBundle.message("progress.text.optimizing.imports");
- private static final String COMMAND_NAME = CodeInsightBundle.message("process.optimize.imports");
+ public static final String COMMAND_NAME = CodeInsightBundle.message("process.optimize.imports");
public OptimizeImportsProcessor(Project project) {
super(project, COMMAND_NAME, PROGRESS_TEXT, false);
@@ -60,9 +60,13 @@
super(project, files, PROGRESS_TEXT, commandName, postRunnable, false);
}
+ public OptimizeImportsProcessor(AbstractLayoutCodeProcessor processor) {
+ super(processor, COMMAND_NAME, PROGRESS_TEXT);
+ }
+
@Override
@NotNull
- protected FutureTask<Boolean> preprocessFile(@NotNull final PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException {
+ protected FutureTask<Boolean> prepareTask(@NotNull PsiFile file, boolean processChangedTextOnly) {
final Set<ImportOptimizer> optimizers = LanguageImportStatements.INSTANCE.forFile(file);
final List<Runnable> runnables = new ArrayList<Runnable>();
List<PsiFile> files = file.getViewProvider().getAllFiles();
@@ -76,8 +80,13 @@
Runnable runnable = runnables.isEmpty() ? EmptyRunnable.getInstance() : new Runnable() {
@Override
public void run() {
- for (Runnable runnable : runnables) {
- runnable.run();
+ CodeStyleManagerImpl.setSequentialProcessingAllowed(false);
+ try {
+ for (Runnable runnable : runnables)
+ runnable.run();
+ }
+ finally {
+ CodeStyleManagerImpl.setSequentialProcessingAllowed(true);
}
}
};
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java
new file mode 100644
index 0000000..53b2473
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/RearrangeCodeProcessor.java
@@ -0,0 +1,119 @@
+/*
+ * 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.codeInsight.actions;
+
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.arrangement.Rearranger;
+import com.intellij.psi.codeStyle.arrangement.engine.ArrangementEngine;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.concurrent.Callable;
+import java.util.concurrent.FutureTask;
+
+public class RearrangeCodeProcessor extends AbstractLayoutCodeProcessor {
+
+ public static final String COMMAND_NAME = "Rearrange code";
+ public static final String PROGRESS_TEXT = "Rearranging code...";
+
+ @Nullable private Condition<PsiFile> myAcceptCondition;
+
+ public RearrangeCodeProcessor(@NotNull AbstractLayoutCodeProcessor previousProcessor,
+ @Nullable Condition<PsiFile> acceptCondition) {
+ super(previousProcessor, COMMAND_NAME, PROGRESS_TEXT);
+ myAcceptCondition = acceptCondition;
+ }
+
+ public RearrangeCodeProcessor(@NotNull Project project,
+ @NotNull PsiFile[] files,
+ @NotNull String commandName,
+ @Nullable Runnable postRunnable)
+ {
+ super(project, files, PROGRESS_TEXT, commandName, postRunnable, false);
+ }
+
+ public boolean shouldRearrangeFile(@NotNull PsiFile file) {
+ return myAcceptCondition == null || myAcceptCondition.value(file);
+ }
+
+ @NotNull
+ @Override
+ protected FutureTask<Boolean> prepareTask(@NotNull final PsiFile file, boolean processChangedTextOnly) {
+ return new FutureTask<Boolean>(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ if (!shouldRearrangeFile(file)) return true;
+
+ RearrangeCommand rearranger = new RearrangeCommand(myProject, file, COMMAND_NAME);
+ if (rearranger.couldRearrange()) {
+ rearranger.run();
+ return true;
+ }
+ return false;
+ }
+ });
+ }
+
+}
+
+
+class RearrangeCommand {
+ @NotNull private PsiFile myFile;
+ @NotNull private String myCommandName;
+ @NotNull private Project myProject;
+ private Document myDocument;
+ private Runnable myCommand;
+
+ RearrangeCommand(@NotNull Project project, @NotNull PsiFile file, @NotNull String commandName) {
+ myProject = project;
+ myFile = file;
+ myCommandName = commandName;
+ myDocument = PsiDocumentManager.getInstance(project).getDocument(file);
+ }
+
+ boolean couldRearrange() {
+ return myDocument != null && Rearranger.EXTENSION.forLanguage(myFile.getLanguage()) != null;
+ }
+
+ void run() {
+ assert myDocument != null;
+ prepare();
+ try {
+ CommandProcessor.getInstance().executeCommand(myProject, myCommand, myCommandName, null);
+ }
+ finally {
+ PsiDocumentManager.getInstance(myProject).commitDocument(myDocument);
+ }
+ }
+
+ private void prepare() {
+ final ArrangementEngine engine = ServiceManager.getService(myProject, ArrangementEngine.class);
+ myCommand = new Runnable() {
+ @Override
+ public void run() {
+ engine.arrange(myFile, Collections.singleton(myFile.getTextRange()));
+ }
+ };
+ PsiDocumentManager.getInstance(myProject).doPostponedOperationsAndUnblockDocument(myDocument);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java
deleted file mode 100644
index 606d794..0000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatAndOptimizeImportsProcessor.java
+++ /dev/null
@@ -1,99 +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 com.intellij.codeInsight.actions;
-
-import com.intellij.codeInsight.CodeInsightBundle;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.codeStyle.CodeStyleManagerImpl;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.FutureTask;
-
-/**
- * @author max
- */
-public class ReformatAndOptimizeImportsProcessor extends AbstractLayoutCodeProcessor {
- public static final String COMMAND_NAME = CodeInsightBundle.message("progress.reformat.and.optimize.common.command.text");
- private static final String PROGRESS_TEXT = CodeInsightBundle.message("reformat.and.optimize.progress.common.text");
-
- private final OptimizeImportsProcessor myOptimizeImportsProcessor;
- private final ReformatCodeProcessor myReformatCodeProcessor;
-
- public ReformatAndOptimizeImportsProcessor(Project project, boolean processChangedTextOnly) {
- super(project, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
- myOptimizeImportsProcessor = new OptimizeImportsProcessor(project);
- myReformatCodeProcessor = new ReformatCodeProcessor(project, processChangedTextOnly);
- }
-
- public ReformatAndOptimizeImportsProcessor(Project project, Module module, boolean processChangedTextOnly) {
- super(project, module, COMMAND_NAME, PROGRESS_TEXT, processChangedTextOnly);
- myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, module);
- myReformatCodeProcessor = new ReformatCodeProcessor(project, module, processChangedTextOnly);
- }
-
- public ReformatAndOptimizeImportsProcessor(Project project, PsiFile[] files, boolean processChangedTextOnly) {
- super(project, files, PROGRESS_TEXT, COMMAND_NAME, null, processChangedTextOnly);
- myOptimizeImportsProcessor = new OptimizeImportsProcessor(project);
- myReformatCodeProcessor = new ReformatCodeProcessor(project, processChangedTextOnly);
- }
-
- public ReformatAndOptimizeImportsProcessor(Project project,
- PsiDirectory directory,
- boolean includeSubdirs,
- boolean processChangedTextOnly)
- {
- super(project, directory, includeSubdirs, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
- myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, directory, includeSubdirs);
- myReformatCodeProcessor = new ReformatCodeProcessor(project, directory, includeSubdirs, processChangedTextOnly);
- }
-
- public ReformatAndOptimizeImportsProcessor(Project project, PsiFile file, boolean processChangedTextOnly) {
- super(project, file, PROGRESS_TEXT, COMMAND_NAME, processChangedTextOnly);
- myOptimizeImportsProcessor = new OptimizeImportsProcessor(project, file);
- myReformatCodeProcessor = new ReformatCodeProcessor(project, file, null, processChangedTextOnly);
- }
-
- @Override
- @NotNull
- protected FutureTask<Boolean> preprocessFile(@NotNull PsiFile file, boolean processChangedTextOnly) throws IncorrectOperationException {
- final FutureTask<Boolean> reformatTask = myReformatCodeProcessor.preprocessFile(file, processChangedTextOnly);
- final FutureTask<Boolean> optimizeImportsTask = myOptimizeImportsProcessor.preprocessFile(file, false);
- return new FutureTask<Boolean>(new Callable<Boolean>() {
- @Override
- public Boolean call() throws Exception {
- reformatTask.run();
- if (!reformatTask.get() || reformatTask.isCancelled()) {
- return false;
- }
-
- CodeStyleManagerImpl.setSequentialProcessingAllowed(false);
- try {
- optimizeImportsTask.run();
- return optimizeImportsTask.get() && !optimizeImportsTask.isCancelled();
- }
- finally {
- CodeStyleManagerImpl.setSequentialProcessingAllowed(true);
- }
- }
- });
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
index c0c2332..42bfdb3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeAction.java
@@ -26,6 +26,7 @@
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Editor;
@@ -55,6 +56,8 @@
public class ReformatCodeAction extends AnAction implements DumbAware {
private static final @NonNls String HELP_ID = "editing.codeReformatting";
+ protected static ReformatFilesOptions myTestOptions;
+
@Override
public void actionPerformed(AnActionEvent event) {
@@ -83,19 +86,23 @@
else if (areFiles(files)) {
final ReadonlyStatusHandler.OperationStatus operationStatus = ReadonlyStatusHandler.getInstance(project).ensureFilesWritable(files);
if (!operationStatus.hasReadonlyFiles()) {
- final ReformatFilesDialog reformatFilesDialog = new ReformatFilesDialog(project, files);
- reformatFilesDialog.show();
- if (!reformatFilesDialog.isOK()) return;
- if (reformatFilesDialog.optimizeImports() && !DumbService.getInstance(project).isDumb()) {
- new ReformatAndOptimizeImportsProcessor(
- project, convertToPsiFiles(files, project), reformatFilesDialog.isProcessOnlyChangedText()
- ).run();
- }
- else {
- new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null, reformatFilesDialog.isProcessOnlyChangedText()).run();
- }
- }
+ ReformatFilesOptions selectedFlags = getReformatFilesOptions(project, files);
+ if (selectedFlags == null)
+ return;
+ final boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText();
+ final boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb();
+
+ AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor(project, convertToPsiFiles(files, project), null, processOnlyChangedText);
+ if (shouldOptimizeImports) {
+ processor = new OptimizeImportsProcessor(processor);
+ }
+ if (selectedFlags.isRearrangeEntries()) {
+ processor = new RearrangeCodeProcessor(processor, null);
+ }
+
+ processor.run();
+ }
return;
}
else {
@@ -103,33 +110,9 @@
Module moduleContext = LangDataKeys.MODULE_CONTEXT.getData(dataContext);
if (projectContext != null || moduleContext != null) {
- final String text;
- if (moduleContext != null) {
- text = CodeInsightBundle.message("process.scope.module", moduleContext.getModuleFilePath());
- }
- else {
- text = CodeInsightBundle.message("process.scope.project", project.getPresentableUrl());
- }
-
- LayoutProjectCodeDialog dialog
- = new LayoutProjectCodeDialog(project, moduleContext, CodeInsightBundle.message("process.reformat.code"), text, true);
- dialog.show();
- if (!dialog.isOK()) return;
- if (dialog.isOptimizeImports() && !DumbService.getInstance(project).isDumb()) {
- if (moduleContext != null) {
- new ReformatAndOptimizeImportsProcessor(project, moduleContext, dialog.isProcessOnlyChangedText()).run();
- }
- else {
- new ReformatAndOptimizeImportsProcessor(project, dialog.isProcessOnlyChangedText()).run();
- }
- }
- else {
- if (moduleContext != null) {
- new ReformatCodeProcessor(project, moduleContext, dialog.isProcessOnlyChangedText()).run();
- }
- else {
- new ReformatCodeProcessor(project, dialog.isProcessOnlyChangedText()).run();
- }
+ ReformatFilesOptions selectedFlags = getLayoutProjectOptions(project, moduleContext); // module menu - only 2 options available
+ if (selectedFlags != null) {
+ reformatModule(project, moduleContext, selectedFlags);
}
return;
}
@@ -155,30 +138,31 @@
boolean rearrangeEntries = getLastSavedRearrangeCbState(project, file);
final boolean showDialog = EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG;
- if (showDialog || (file == null && dir != null)) {
- final LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), file, dir,
- hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID);
- dialog.show();
- if (!dialog.isOK()) return;
- final boolean showDialogAtFuture = !dialog.isDoNotAskMe();
- EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = showDialogAtFuture;
- updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled");
- optimizeImports = dialog.isOptimizeImports();
- rearrangeEntries = dialog.isRearrangeEntries();
- processWholeFile = dialog.isProcessWholeFile();
- processChangedTextOnly = dialog.isProcessOnlyChangedText();
-
- if (dialog.isProcessDirectory()){
- if (optimizeImports) {
- new ReformatAndOptimizeImportsProcessor(project, dir, dialog.isIncludeSubdirectories(), processChangedTextOnly).run();
- }
- else {
- new ReformatCodeProcessor(project, dir, dialog.isIncludeSubdirectories(), processChangedTextOnly).run();
- }
+
+ if (file == null && dir != null) {
+ DirectoryFormattingOptions options = getDirectoryFormattingOptions(project, dir);
+ if (options != null) {
+ reformatDirectory(project, dir, options);
+ }
+ return;
+ }
+ else if (showDialog) {
+ LayoutCodeOptions selectedFlags = getLayoutCodeOptions(project, file, dir, hasSelection);
+ if (selectedFlags == null)
+ return;
+
+ optimizeImports = selectedFlags.isOptimizeImports();
+ rearrangeEntries = selectedFlags.isRearrangeEntries();
+ processWholeFile = selectedFlags.isProcessWholeFile();
+ processChangedTextOnly = selectedFlags.isProcessOnlyChangedText();
+
+ if (selectedFlags.isProcessDirectory()) {
+ assert dir != null : "File = " + file + ", Element = " + CommonDataKeys.PSI_ELEMENT.getData(dataContext);
+ reformatDirectory(project, dir, selectedFlags);
return;
}
}
-
+
final TextRange range;
if (!processWholeFile && editor != null && editor.getSelectionModel().hasSelection()){
range = TextRange.create(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd());
@@ -188,12 +172,7 @@
}
if (optimizeImports && range == null) {
- if (file != null || dir == null) {
- new ReformatAndOptimizeImportsProcessor(project, file, processChangedTextOnly).run();
- }
- else {
- new ReformatAndOptimizeImportsProcessor(project, dir, true, processChangedTextOnly).run();
- }
+ new OptimizeImportsProcessor(new ReformatCodeProcessor(project, file, null, processChangedTextOnly)).run();
}
else {
new ReformatCodeProcessor(project, file, range, processChangedTextOnly).run();
@@ -210,7 +189,7 @@
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
- engine.arrange(finalFile, Collections.singleton(rangeToUse));
+ engine.arrange(editor, finalFile, Collections.singleton(rangeToUse));
}
}, getTemplatePresentation().getText(), null);
}
@@ -220,11 +199,70 @@
}
}
- public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) {
- if (file != null) {
- return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage());
+ @Nullable
+ private static DirectoryFormattingOptions getDirectoryFormattingOptions(@NotNull Project project, @NotNull PsiDirectory dir) {
+ LayoutDirectoryDialog dialog = new LayoutDirectoryDialog(
+ project,
+ CodeInsightBundle.message("process.reformat.code"),
+ CodeInsightBundle.message("process.scope.directory", dir.getVirtualFile().getPath()),
+ FormatChangedTextUtil.hasChanges(dir)
+ );
+
+ boolean enableIncludeDirectoriesCb = dir.getSubdirectories().length > 0;
+ dialog.setEnabledIncludeSubdirsCb(enableIncludeDirectoriesCb);
+ dialog.setSelectedIncludeSubdirsCb(enableIncludeDirectoriesCb);
+
+ dialog.show();
+ if (dialog.isOK()) {
+ return dialog;
}
- return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project);
+ return null;
+ }
+
+ private static void reformatDirectory(@NotNull Project project,
+ @NotNull PsiDirectory dir,
+ @NotNull DirectoryFormattingOptions options)
+ {
+ AbstractLayoutCodeProcessor processor = new ReformatCodeProcessor(
+ project,
+ dir,
+ options.isIncludeSubdirectories(),
+ options.isProcessOnlyChangedText()
+ );
+
+ if (options.isOptimizeImports()) {
+ processor = new OptimizeImportsProcessor(processor);
+ }
+ if (options.isRearrangeEntries()) {
+ processor = new RearrangeCodeProcessor(processor, null);
+ }
+
+ processor.run();
+ }
+
+ private static void reformatModule(@NotNull Project project,
+ @Nullable Module moduleContext,
+ @NotNull ReformatFilesOptions selectedFlags)
+ {
+ boolean shouldOptimizeImports = selectedFlags.isOptimizeImports() && !DumbService.getInstance(project).isDumb();
+ boolean processOnlyChangedText = selectedFlags.isProcessOnlyChangedText();
+
+ AbstractLayoutCodeProcessor processor;
+ if (moduleContext != null)
+ processor = new ReformatCodeProcessor(project, moduleContext, processOnlyChangedText);
+ else
+ processor = new ReformatCodeProcessor(project, processOnlyChangedText);
+
+
+ if (shouldOptimizeImports) {
+ processor = new OptimizeImportsProcessor(processor);
+ }
+
+ if (selectedFlags.isRearrangeEntries()) {
+ processor = new RearrangeCodeProcessor(processor, null);
+ }
+
+ processor.run();
}
public static void updateShowDialogSetting(LayoutCodeDialog dialog, String title) {
@@ -323,6 +361,64 @@
presentation.setEnabled(true);
}
+ @Nullable
+ private static ReformatFilesOptions getReformatFilesOptions(@NotNull Project project, @NotNull VirtualFile[] files) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return myTestOptions;
+ }
+ ReformatFilesDialog dialog = new ReformatFilesDialog(project, files);
+ dialog.show();
+ if (!dialog.isOK()) return null;
+ return dialog;
+ }
+
+ @Nullable
+ private static ReformatFilesOptions getLayoutProjectOptions(@NotNull Project project, @Nullable Module module) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return myTestOptions;
+ }
+
+ final String text = module != null ? CodeInsightBundle.message("process.scope.module", module.getModuleFilePath())
+ : CodeInsightBundle.message("process.scope.project", project.getPresentableUrl());
+
+ final boolean enableOnlyVCSChangedRegions = module != null ? FormatChangedTextUtil.hasChanges(module)
+ : FormatChangedTextUtil.hasChanges(project);
+
+ LayoutProjectCodeDialog dialog = new LayoutProjectCodeDialog(project, CodeInsightBundle.message("process.reformat.code"), text, true, enableOnlyVCSChangedRegions);
+ dialog.show();
+ if (!dialog.isOK()) return null;
+ return dialog;
+ }
+
+ @Nullable
+ private static LayoutCodeOptions getLayoutCodeOptions(@NotNull Project project,
+ @Nullable PsiFile file,
+ @Nullable PsiDirectory dir,
+ boolean hasSelection)
+ {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ return (LayoutCodeOptions)myTestOptions;
+ }
+ LayoutCodeDialog dialog = new LayoutCodeDialog(project, CodeInsightBundle.message("process.reformat.code"),
+ file, dir, hasSelection ? Boolean.TRUE : Boolean.FALSE, HELP_ID);
+ dialog.show();
+ if (!dialog.isOK()) return null;
+ EditorSettingsExternalizable.getInstance().getOptions().SHOW_REFORMAT_DIALOG = !dialog.isDoNotAskMe();
+ updateShowDialogSetting(dialog, "\"Reformat Code\" dialog disabled");
+ return dialog;
+ }
+
+ public static boolean getLastSavedRearrangeCbState(@NotNull Project project, @Nullable PsiFile file) {
+ if (file != null) {
+ return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project, file.getLanguage());
+ }
+ return LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(project);
+ }
+
+ protected static void setTestOptions(ReformatFilesOptions options) {
+ myTestOptions = options;
+ }
+
public static boolean areFiles(final VirtualFile[] files) {
if (files == null) return false;
if (files.length < 2) return false;
@@ -332,3 +428,5 @@
return true;
}
}
+
+
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java
index e52d757..9bd23c3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java
@@ -77,7 +77,7 @@
@Override
@NotNull
- protected FutureTask<Boolean> preprocessFile(@NotNull final PsiFile file, final boolean processChangedTextOnly)
+ protected FutureTask<Boolean> prepareTask(@NotNull final PsiFile file, final boolean processChangedTextOnly)
throws IncorrectOperationException
{
return new FutureTask<Boolean>(new Callable<Boolean>() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form
index d5f043e..f27be63 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.form
@@ -3,12 +3,12 @@
<grid id="59847" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="4" bottom="0" right="0"/>
<constraints>
- <xy x="30" y="17" width="196" height="104"/>
+ <xy x="30" y="17" width="218" height="135"/>
</constraints>
<properties/>
<border type="none"/>
<children>
- <grid id="e83d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="e83d0" layout-manager="GridLayoutManager" row-count="5" 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="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -32,11 +32,6 @@
<text resource-bundle="messages/CodeInsightBundle" key="dialog.reformat.files.optimize.imports.checkbox"/>
</properties>
</component>
- <vspacer id="8d758">
- <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"/>
- </constraints>
- </vspacer>
<component id="a0a79" class="javax.swing.JCheckBox" binding="myOnlyChangedText">
<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"/>
@@ -45,6 +40,19 @@
<text resource-bundle="messages/CodeInsightBundle" key="reformat.option.vcs.changed.region"/>
</properties>
</component>
+ <vspacer id="8d758">
+ <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"/>
+ </constraints>
+ </vspacer>
+ <component id="cf942" class="javax.swing.JCheckBox" binding="myRearrangeEntriesCb">
+ <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="&Rearrange entries"/>
+ </properties>
+ </component>
</children>
</grid>
<hspacer id="c7098">
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java
index 1699ced..e02f1fc 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesDialog.java
@@ -25,15 +25,16 @@
import javax.swing.*;
-public class ReformatFilesDialog extends DialogWrapper {
+public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesOptions {
+ @NotNull private Project myProject;
private JPanel myPanel;
private JCheckBox myOptimizeImports;
private JCheckBox myOnlyChangedText;
- private final VirtualFile[] myFiles;
+ private JCheckBox myRearrangeEntriesCb;
public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) {
super(project, true);
- myFiles = files;
+ myProject = project;
setTitle(CodeInsightBundle.message("dialog.reformat.files.title"));
myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
boolean canTargetVcsChanges = false;
@@ -48,6 +49,7 @@
canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
);
myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
+ myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject));
init();
}
@@ -56,20 +58,27 @@
return myPanel;
}
- public boolean optimizeImports(){
+ @Override
+ public boolean isOptimizeImports(){
return myOptimizeImports.isSelected();
}
+ @Override
public boolean isProcessOnlyChangedText() {
return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected();
}
@Override
+ public boolean isRearrangeEntries() {
+ return myRearrangeEntriesCb.isSelected();
+ }
+
+ @Override
protected void doOKAction() {
super.doOKAction();
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected()));
- PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY,
- Boolean.toString(myOnlyChangedText.isSelected()));
+ PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected()));
+ LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries());
}
static boolean isOptmizeImportsOptionOn() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.java
new file mode 100644
index 0000000..37bf43c
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatFilesOptions.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.codeInsight.actions;
+
+public interface ReformatFilesOptions {
+
+ boolean isOptimizeImports();
+
+ boolean isProcessOnlyChangedText();
+
+ boolean isRearrangeEntries();
+
+}
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 853ea8f..3c816b0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CodeCompletionHandlerBase.java
@@ -45,8 +45,8 @@
import com.intellij.openapi.project.Project;
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.Trinity;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDocumentManager;
@@ -109,29 +109,25 @@
}
public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted) {
- final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
- assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
+ if (invokedExplicitly) {
+ CompletionLookupArranger.applyLastCompletionStatisticsUpdate();
+ }
checkNoWriteAccess();
CompletionAssertions.checkEditorValid(editor);
- if (editor.isViewer()) {
+ int offset = editor.getCaretModel().getOffset();
+ if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) {
editor.getDocument().fireReadOnlyModificationAttempt();
+ CodeInsightUtilBase.showReadOnlyViewWarning(editor);
return;
}
- if (invokedExplicitly) {
- CompletionLookupArranger.applyLastCompletionStatisticsUpdate();
- }
-
- if (!CodeInsightUtilBase.prepareEditorForWrite(editor) ||
- !FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
+ if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), project)) {
return;
}
- psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
-
CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
boolean repeated = phase.indicator != null && phase.indicator.isRepeatedInvocation(myCompletionType, editor);
/*
@@ -166,10 +162,13 @@
public void run() {
EditorUtil.fillVirtualSpaceUntilCaret(editor);
PsiDocumentManager.getInstance(project).commitAllDocuments();
-
- CompletionAssertions.assertCommitSuccessful(editor, psiFile);
CompletionAssertions.checkEditorValid(editor);
+ final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
+ assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
+ psiFile.putUserData(PsiFileEx.BATCH_REFERENCE_PROCESSING, Boolean.TRUE);
+ CompletionAssertions.assertCommitSuccessful(editor, psiFile);
+
initializationContext[0] = runContributorsBeforeCompletion(editor, psiFile);
}
};
@@ -178,7 +177,7 @@
};
if (autopopup) {
CommandProcessor.getInstance().runUndoTransparentAction(initCmd);
- if (!restarted && shouldSkipAutoPopup(editor, psiFile)) {
+ if (!restarted && shouldSkipAutoPopup(editor, initializationContext[0].getFile())) {
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
return;
}
@@ -457,7 +456,7 @@
public void run() {
AccessToken token = WriteAction.start();
try {
- hostCopy[0] = createFileCopy(hostFile);
+ hostCopy[0] = createFileCopy(hostFile, initContext.getStartOffset(), initContext.getSelectionEndOffset());
}
finally {
token.finish();
@@ -748,7 +747,7 @@
}
}
- public static final Key<SoftReference<Pair<PsiFile, Document>>> FILE_COPY_KEY = Key.create("CompletionFileCopy");
+ private static final Key<SoftReference<Trinity<PsiFile, Document, Long>>> FILE_COPY_KEY = Key.create("CompletionFileCopy");
private static boolean isCopyUpToDate(Document document, @NotNull PsiFile file) {
if (!file.isValid()) {
@@ -760,31 +759,42 @@
return current != null && current.getViewProvider().getPsi(file.getLanguage()) == file;
}
- private static PsiFile createFileCopy(PsiFile file) {
+ private static PsiFile createFileCopy(PsiFile file, long caret, long selEnd) {
final VirtualFile virtualFile = file.getVirtualFile();
- if (file.isPhysical() && virtualFile != null && virtualFile.isInLocalFileSystem()
- // must not cache injected file copy, since it does not reflect changes in host document
- && !InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) {
- final SoftReference<Pair<PsiFile, Document>> reference = file.getUserData(FILE_COPY_KEY);
- if (reference != null) {
- final Pair<PsiFile, Document> pair = reference.get();
- if (pair != null && pair.first.getClass().equals(file.getClass()) && isCopyUpToDate(pair.second, pair.first)) {
- final PsiFile copy = pair.first;
- if (copy.getViewProvider().getModificationStamp() > file.getViewProvider().getModificationStamp()) {
- ((PsiModificationTrackerImpl) file.getManager().getModificationTracker()).incCounter();
- }
- final Document document = pair.second;
- assert document != null;
- document.setText(file.getViewProvider().getContents());
- return copy;
- }
+ boolean mayCacheCopy = file.isPhysical() &&
+ // we don't want to cache code fragment copies even if they appear to be physical
+ virtualFile != null && virtualFile.isInLocalFileSystem();
+ long combinedOffsets = caret + (selEnd << 32);
+ if (mayCacheCopy) {
+ final Trinity<PsiFile, Document, Long> cached = SoftReference.dereference(file.getUserData(FILE_COPY_KEY));
+ if (cached != null && cached.first.getClass().equals(file.getClass()) && isCopyUpToDate(cached.second, cached.first)) {
+ final PsiFile copy = cached.first;
+ if (copy.getViewProvider().getModificationStamp() > file.getViewProvider().getModificationStamp() &&
+ cached.third.longValue() != combinedOffsets) {
+ // the copy PSI might have some caches that are not cleared on its modification because there are no events in the copy
+ // so, clear all the caches
+ // hopefully it's a rare situation that the user invokes completion in different parts of the file
+ // without modifying anything physical in between
+ ((PsiModificationTrackerImpl) file.getManager().getModificationTracker()).incCounter();
+ }
+ final Document document = cached.second;
+ assert document != null;
+ file.putUserData(FILE_COPY_KEY, new SoftReference<Trinity<PsiFile,Document, Long>>(Trinity.create(copy, document, combinedOffsets)));
+
+ Document originalDocument = file.getViewProvider().getDocument();
+ assert originalDocument != null;
+ assert originalDocument.getTextLength() == file.getTextLength() : originalDocument;
+ document.setText(originalDocument.getImmutableCharSequence());
+ return copy;
}
}
final PsiFile copy = (PsiFile)file.copy();
- final Document document = copy.getViewProvider().getDocument();
- assert document != null;
- file.putUserData(FILE_COPY_KEY, new SoftReference<Pair<PsiFile,Document>>(Pair.create(copy, document)));
+ if (mayCacheCopy) {
+ final Document document = copy.getViewProvider().getDocument();
+ assert document != null;
+ file.putUserData(FILE_COPY_KEY, new SoftReference<Trinity<PsiFile,Document, Long>>(Trinity.create(copy, document, combinedOffsets)));
+ }
return copy;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java
index 76ca0b5..6b46779 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionAssertions.java
@@ -34,6 +34,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.DebugUtil;
+import com.intellij.psi.util.PsiUtilCore;
import java.util.List;
@@ -120,7 +121,7 @@
}
static void assertHostInfo(PsiFile hostCopy, OffsetMap hostMap) {
- assert hostCopy.isValid() : "file became invalid: " + hostCopy.getClass();
+ PsiUtilCore.ensureValid(hostCopy);
if (hostMap.getOffset(CompletionInitializationContext.START_OFFSET) >= hostCopy.getTextLength()) {
throw new AssertionError("startOffset outside the host file: " + hostMap.getOffset(CompletionInitializationContext.START_OFFSET) + "; " + hostCopy);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionData.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionData.java
index 791f954..aee920b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionData.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionData.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,7 +34,7 @@
import com.intellij.psi.impl.source.resolve.reference.impl.PsiMultiReference;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.util.PsiUtilCore;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -64,7 +64,7 @@
return true;
for (final Class myFinalScope : myFinalScopes) {
- if (ReflectionCache.isAssignable(myFinalScope, scopeClass)) {
+ if (ReflectionUtil.isAssignable(myFinalScope, scopeClass)) {
return true;
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java
index 20dcb58..e5058a0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionLookupArranger.java
@@ -89,12 +89,7 @@
}
private MultiMap<CompletionSorterImpl, LookupElement> groupItemsBySorter(List<LookupElement> source) {
- MultiMap<CompletionSorterImpl, LookupElement> inputBySorter = new MultiMap<CompletionSorterImpl, LookupElement>() {
- @Override
- protected Map<CompletionSorterImpl, Collection<LookupElement>> createMap() {
- return ContainerUtil.newLinkedHashMap();
- }
- };
+ MultiMap<CompletionSorterImpl, LookupElement> inputBySorter = MultiMap.createLinked();
for (LookupElement element : source) {
inputBySorter.putValue(obtainSorter(element), element);
}
@@ -494,7 +489,7 @@
public void addSparedChars(CompletionProgressIndicator indicator, LookupElement item, InsertionContext context, char completionChar) {
String textInserted;
if (context.getStartOffset() >= 0 && context.getTailOffset() >= context.getStartOffset()) {
- textInserted = context.getDocument().getText().substring(context.getStartOffset(), context.getTailOffset());
+ textInserted = context.getDocument().getImmutableCharSequence().subSequence(context.getStartOffset(), context.getTailOffset()).toString();
} else {
textInserted = item.getLookupString();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
index 39e0b5d..d07b0b4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionProgressIndicator.java
@@ -188,8 +188,8 @@
else if (FeatureUsageTracker.getInstance()
.isToBeAdvertisedInLookup(CodeCompletionFeatures.EDITING_COMPLETION_CONTROL_ENTER, getProject())) {
myLookup.addAdvertisement("Press " +
- CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_ALWAYS) +
- " to choose the selected (or first) suggestion", null);
+ CompletionContributor.getActionShortcut(IdeActions.ACTION_CHOOSE_LOOKUP_ITEM_ALWAYS) +
+ " to choose the selected (or first) suggestion", null);
}
if (!myEditor.isOneLineMode() &&
FeatureUsageTracker.getInstance()
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionVariant.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionVariant.java
index 6f54511..13e213f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionVariant.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CompletionVariant.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,7 +26,7 @@
import com.intellij.psi.filters.ContextGetter;
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.filters.position.PatternFilter;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NonNls;
@@ -90,7 +90,7 @@
public boolean isScopeClassFinal(Class scopeClass){
for (final Object myScopeClass : myScopeClasses) {
Scope scope = (Scope)myScopeClass;
- if (ReflectionCache.isAssignable(scope.myClass, scopeClass) && scope.myIsFinalScope) {
+ if (ReflectionUtil.isAssignable(scope.myClass, scopeClass) && scope.myIsFinalScope) {
return true;
}
}
@@ -102,7 +102,7 @@
for (final Object myScopeClass : myScopeClasses) {
final Class aClass = ((Scope)myScopeClass).myClass;
- if (ReflectionCache.isAssignable(aClass, scopeClass)) {
+ if (ReflectionUtil.isAssignable(aClass, scopeClass)) {
ret = true;
break;
}
@@ -110,7 +110,7 @@
if(ret){
for (final Class aClass: myScopeClassExceptions) {
- if (ReflectionCache.isAssignable(aClass, scopeClass)) {
+ if (ReflectionUtil.isAssignable(aClass, scopeClass)) {
ret = false;
break;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/CustomFileTypeCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/CustomFileTypeCompletionContributor.java
new file mode 100644
index 0000000..aabd9a2
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/CustomFileTypeCompletionContributor.java
@@ -0,0 +1,93 @@
+/*
+ * 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.codeInsight.completion;
+
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.ide.highlighter.custom.SyntaxTable;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
+import com.intellij.psi.CustomHighlighterTokenType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+import static com.intellij.patterns.PlatformPatterns.psiFile;
+import static com.intellij.patterns.StandardPatterns.instanceOf;
+
+/**
+ * @author yole
+ */
+public class CustomFileTypeCompletionContributor extends CompletionContributor {
+ public CustomFileTypeCompletionContributor() {
+ extend(CompletionType.BASIC, psiElement().inFile(psiFile().withFileType(instanceOf(CustomSyntaxTableFileType.class))),
+ new CompletionProvider<CompletionParameters>() {
+ @Override
+ protected void addCompletions(@NotNull CompletionParameters parameters,
+ ProcessingContext context,
+ @NotNull CompletionResultSet result) {
+ if (inCommentOrLiteral(parameters)) {
+ return;
+ }
+
+ CustomSyntaxTableFileType fileType = (CustomSyntaxTableFileType)parameters.getOriginalFile().getFileType();
+ SyntaxTable syntaxTable = fileType.getSyntaxTable();
+ String prefix = findPrefix(parameters.getPosition(), parameters.getOffset());
+ CompletionResultSet resultSetWithPrefix = result.withPrefixMatcher(prefix);
+
+ addVariants(resultSetWithPrefix, syntaxTable.getKeywords1());
+ addVariants(resultSetWithPrefix, syntaxTable.getKeywords2());
+ addVariants(resultSetWithPrefix, syntaxTable.getKeywords3());
+ addVariants(resultSetWithPrefix, syntaxTable.getKeywords4());
+ }
+ });
+ }
+
+ private static boolean inCommentOrLiteral(CompletionParameters parameters) {
+ HighlighterIterator iterator = ((EditorEx)parameters.getEditor()).getHighlighter().createIterator(parameters.getOffset());
+ IElementType elementType = iterator.getTokenType();
+ if (elementType == CustomHighlighterTokenType.WHITESPACE) {
+ iterator.retreat();
+ elementType = iterator.getTokenType();
+ }
+ return elementType == CustomHighlighterTokenType.LINE_COMMENT ||
+ elementType == CustomHighlighterTokenType.MULTI_LINE_COMMENT ||
+ elementType == CustomHighlighterTokenType.STRING ||
+ elementType == CustomHighlighterTokenType.SINGLE_QUOTED_STRING;
+ }
+
+ private static void addVariants(CompletionResultSet resultSet, Set<String> keywords) {
+ for (String keyword : keywords) {
+ resultSet.addElement(LookupElementBuilder.create(keyword));
+ }
+ }
+
+ private static String findPrefix(PsiElement insertedElement, int offset) {
+ String text = insertedElement.getText();
+ int offsetInElement = offset - insertedElement.getTextOffset();
+ int start = offsetInElement - 1;
+ while(start >=0 ) {
+ if(!Character.isJavaIdentifierStart(text.charAt(start))) break;
+ --start;
+ }
+ return text.substring(start+1, offsetInElement).trim();
+ }
+
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java
index 65c2a74..f15a719 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/FilePathCompletionContributor.java
@@ -125,7 +125,7 @@
final Module contextModule = index.getModuleForFile(contextFile);
if (contextModule != null) {
- final FileReferenceHelper contextHelper = FileReferenceHelperRegistrar.getNotNullHelper(originalFile);
+ final List<FileReferenceHelper> helpers = FileReferenceHelperRegistrar.getHelpers(originalFile);
final GlobalSearchScope scope = ProjectScope.getProjectScope(project);
for (final String name : resultNames) {
@@ -139,10 +139,14 @@
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile != null && virtualFile.isValid() && !Comparing.equal(virtualFile, contextFile)) {
- if (contextHelper.isMine(project, virtualFile)) {
- if (pathPrefixParts == null ||
- fileMatchesPathPrefix(contextHelper.getPsiFileSystemItem(project, virtualFile), pathPrefixParts)) {
- __result.addElement(new FilePathLookupItem(file, contextHelper));
+ for (FileReferenceHelper contextHelper : helpers) {
+ ProgressManager.checkCanceled();
+
+ if (contextHelper.isMine(project, virtualFile)) {
+ if (pathPrefixParts == null ||
+ fileMatchesPathPrefix(contextHelper.getPsiFileSystemItem(project, virtualFile), pathPrefixParts)) {
+ __result.addElement(new FilePathLookupItem(file, contextHelper));
+ }
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/SyntaxTableCompletionData.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/SyntaxTableCompletionData.java
deleted file mode 100644
index 49cbdcc..0000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/SyntaxTableCompletionData.java
+++ /dev/null
@@ -1,58 +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.codeInsight.completion;
-
-import com.intellij.codeInsight.TailType;
-import com.intellij.ide.highlighter.custom.SyntaxTable;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.filters.TrueFilter;
-
-/**
- * @author Maxim.Mossienko
- */
-public class SyntaxTableCompletionData extends CompletionData{
- private final SyntaxTable mySyntaxTable;
-
- public SyntaxTableCompletionData(SyntaxTable _syntaxTable) {
- mySyntaxTable = _syntaxTable;
- mySyntaxTable.getKeywords1();
-
- final CompletionVariant variant = new CompletionVariant(TrueFilter.INSTANCE);
- variant.includeScopeClass(PsiElement.class, true);
- variant.addCompletionFilter(TrueFilter.INSTANCE);
- final String[] empty = {};
-
- variant.addCompletion(mySyntaxTable.getKeywords1().toArray(empty), TailType.NONE);
- variant.addCompletion(mySyntaxTable.getKeywords2().toArray(empty), TailType.NONE);
- variant.addCompletion(mySyntaxTable.getKeywords3().toArray(empty), TailType.NONE);
- variant.addCompletion(mySyntaxTable.getKeywords4().toArray(empty), TailType.NONE);
-
- registerVariant(variant);
- }
-
- @Override
- public String findPrefix(PsiElement insertedElement, int offset) {
- String text = insertedElement.getText();
- int offsetInElement = offset - insertedElement.getTextOffset();
- int start = offsetInElement - 1;
- while(start >=0 ) {
- if(!Character.isJavaIdentifierStart(text.charAt(start))) break;
- --start;
- }
- return text.substring(start+1, offsetInElement).trim();
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/WordCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/WordCompletionContributor.java
index f56553a..5d1ef95 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/WordCompletionContributor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/WordCompletionContributor.java
@@ -138,7 +138,7 @@
final PsiFile file = insertedElement.getContainingFile();
final CompletionData data = CompletionUtil.getCompletionDataByElement(insertedElement, file);
- if (data != null && !(data instanceof SyntaxTableCompletionData)) {
+ if (data != null) {
Set<CompletionVariant> toAdd = new HashSet<CompletionVariant>();
data.addKeywordVariants(toAdd, insertedElement, file);
for (CompletionVariant completionVariant : toAdd) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java
index d6ca655..645e791 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/actions/HippieWordCompletionHandler.java
@@ -17,6 +17,7 @@
package com.intellij.codeInsight.completion.actions;
import com.intellij.codeInsight.CodeInsightActionHandler;
+import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.completion.impl.CamelHumpMatcher;
import com.intellij.codeInsight.highlighting.HighlightManager;
@@ -54,6 +55,13 @@
public void invoke(@NotNull Project project, @NotNull final Editor editor, @NotNull PsiFile file) {
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
+ int offset = editor.getCaretModel().getOffset();
+ if (editor.isViewer() || editor.getDocument().getRangeGuard(offset, offset) != null) {
+ editor.getDocument().fireReadOnlyModificationAttempt();
+ CodeInsightUtilBase.showReadOnlyViewWarning(editor);
+ return;
+ }
+
LookupManager.getInstance(project).hideActiveLookup();
final CharSequence charsSequence = editor.getDocument().getCharsSequence();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java
index 1565d9e..7f3384b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.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.
@@ -246,6 +246,7 @@
final CompletionLocation location = new CompletionLocation(parameters);
CompletionSorterImpl sorter = emptySorter();
+ sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(new DispreferLiveTemplates()));
sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(new PreferStartMatching(location)));
for (final Weigher weigher : WeighingService.getWeighers(CompletionService.RELEVANCE_KEY)) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/DispreferLiveTemplates.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/DispreferLiveTemplates.java
new file mode 100644
index 0000000..f5cd343
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/DispreferLiveTemplates.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.codeInsight.completion.impl;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementWeigher;
+import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author peter
+*/
+public class DispreferLiveTemplates extends LookupElementWeigher {
+ public DispreferLiveTemplates() {
+ super("templates");
+ }
+
+ @Nullable
+ @Override
+ public Comparable weigh(@NotNull LookupElement element) {
+ return element instanceof LiveTemplateLookupElement;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java
index 1d4e3f0..271397d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/LiftShorterItemsClassifier.java
@@ -20,7 +20,6 @@
import com.intellij.openapi.util.Condition;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.*;
-import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.Nullable;
@@ -35,17 +34,7 @@
*/
public class LiftShorterItemsClassifier extends Classifier<LookupElement> {
private final TreeSet<String> mySortedStrings = new TreeSet<String>();
- private final MultiMap<String, LookupElement> myElements = new MultiMap<String, LookupElement>() {
- @Override
- protected Map<String, Collection<LookupElement>> createMap() {
- return new THashMap<String, Collection<LookupElement>>();
- }
-
- @Override
- protected Collection<LookupElement> createCollection() {
- return new ArrayList<LookupElement>(1);
- }
- };
+ private final MultiMap<String, LookupElement> myElements = MultiMap.createSmartList();
private final Map<LookupElement, FList<LookupElement>> myToLift = newIdentityHashMap();
private final IdentityHashMap<FList<LookupElement>, IdentityHashMap<LookupElement, FList<LookupElement>>> myPrepends = newIdentityHashMap();
private final String myName;
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 3f7b962..3304407 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
@@ -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.
@@ -211,7 +211,7 @@
}
myActiveEditors = activeEditors;
stopDaemon(true, "Active editor change"); // do not stop daemon if idea loses/gains focus
- if (LaterInvocator.isInModalContext()) {
+ if (ApplicationManager.getApplication().isDispatchThread() && LaterInvocator.isInModalContext()) {
// editor appear in modal context, re-enable the daemon
myDaemonCodeAnalyzer.setUpdateByTimerEnabled(true);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java
index d536fa7..7b3a3ce 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonTooltipRendererProvider.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.
@@ -34,6 +34,7 @@
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -135,7 +136,7 @@
@Override
protected boolean dressDescription(@NotNull final Editor editor) {
- final List<String> problems = StringUtil.split(UIUtil.getHtmlBody(myText), BORDER_LINE);
+ final List<String> problems = StringUtil.split(UIUtil.getHtmlBody(myText), UIUtil.BORDER_LINE);
String text = "";
for (String problem : problems) {
final String ref = getLinkRef(problem);
@@ -145,15 +146,15 @@
description = DefaultInspectionToolPresentation.stripUIRefsFromInspectionDescription(UIUtil.getHtmlBody(description));
text += UIUtil.getHtmlBody(problem).replace(DaemonBundle.message("inspection.extended.description"),
DaemonBundle.message("inspection.collapse.description")) +
- END_MARKER + "<p>" + description + BORDER_LINE;
+ END_MARKER + "<p>" + description + UIUtil.BORDER_LINE;
}
}
else {
- text += UIUtil.getHtmlBody(problem) + BORDER_LINE;
+ text += UIUtil.getHtmlBody(problem) + UIUtil.BORDER_LINE;
}
}
if (!text.isEmpty()) { //otherwise do not change anything
- myText = "<html><body>" + StringUtil.trimEnd(text, BORDER_LINE) + "</body></html>";
+ myText = XmlStringUtil.wrapInHtml(StringUtil.trimEnd(text, UIUtil.BORDER_LINE));
return true;
}
return false;
@@ -175,14 +176,14 @@
@Override
protected void stripDescription() {
- final List<String> problems = StringUtil.split(UIUtil.getHtmlBody(myText), BORDER_LINE);
- myText = "<html><body>";
- for (int i = 0, size = problems.size(); i < size; i++) {
- final String problem = StringUtil.split(problems.get(i), END_MARKER).get(0);
+ final List<String> problems = StringUtil.split(UIUtil.getHtmlBody(myText), UIUtil.BORDER_LINE);
+ myText = "";
+ for (String problem1 : problems) {
+ final String problem = StringUtil.split(problem1, END_MARKER).get(0);
myText += UIUtil.getHtmlBody(problem).replace(DaemonBundle.message("inspection.collapse.description"),
- DaemonBundle.message("inspection.extended.description")) + BORDER_LINE;
+ DaemonBundle.message("inspection.extended.description")) + UIUtil.BORDER_LINE;
}
- myText = StringUtil.trimEnd(myText, BORDER_LINE) + "</body></html>";
+ myText = XmlStringUtil.wrapInHtml(StringUtil.trimEnd(myText, UIUtil.BORDER_LINE));
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightInfoProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightInfoProcessor.java
index 04d5f22..076ffd9 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightInfoProcessor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DefaultHighlightInfoProcessor.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,7 +86,7 @@
@NotNull final List<HighlightInfo> infos,
@NotNull final TextRange priorityRange,
@NotNull final TextRange restrictedRange) {
- PsiFile psiFile = highlightingSession.getPsiFile();
+ final PsiFile psiFile = highlightingSession.getPsiFile();
final Project project = psiFile.getProject();
final Document document = PsiDocumentManager.getInstance(project).getDocument(psiFile);
if (document == null) return;
@@ -99,7 +99,7 @@
Editor editor = highlightingSession.getEditor();
EditorColorsScheme scheme = editor == null ? null : editor.getColorsScheme();
- UpdateHighlightersUtil.setHighlightersOutsideRange(project, document, infos, scheme,
+ UpdateHighlightersUtil.setHighlightersOutsideRange(project, document, psiFile, infos, scheme,
restrictedRange.getStartOffset(), restrictedRange.getEndOffset(),
ProperTextRange.create(priorityRange),
highlightingSession.getPassId());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPassFactory.java
index 5662d67..a1089ef 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPassFactory.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GeneralHighlightingPassFactory.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,11 +32,12 @@
* @author cdr
*/
public class GeneralHighlightingPassFactory extends AbstractProjectComponent implements MainHighlightingPassFactory {
- public GeneralHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar) {
+ public GeneralHighlightingPassFactory(Project project, TextEditorHighlightingPassRegistrar highlightingPassRegistrar, DefaultHighlightVisitor dhi) {
super(project);
highlightingPassRegistrar.registerTextEditorHighlightingPass(this,
null,
new int[]{Pass.UPDATE_FOLDING}, false, Pass.UPDATE_ALL);
+ assert dhi != null;
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java
index c8d9e8f..8da21f6 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/GotoNextErrorHandler.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.
@@ -126,6 +126,7 @@
if (offset != oldOffset) {
ScrollType scrollType = offset > oldOffset ? ScrollType.CENTER_DOWN : ScrollType.CENTER_UP;
editor.getSelectionModel().removeSelection();
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToOffset(offset);
scrollingModel.scrollToCaret(scrollType);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java
index 355098a..2308ba4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPass.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,7 +17,6 @@
package com.intellij.codeInsight.daemon.impl;
import com.intellij.codeHighlighting.TextEditorHighlightingPass;
-import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.TargetElementUtilBase;
import com.intellij.codeInsight.highlighting.HighlightHandlerBase;
import com.intellij.codeInsight.highlighting.HighlightUsagesHandler;
@@ -72,10 +71,6 @@
@Override
public void doCollectInformation(@NotNull final ProgressIndicator progress) {
- if (!CodeInsightSettings.getInstance().HIGHLIGHT_IDENTIFIER_UNDER_CARET) {
- return;
- }
-
final HighlightUsagesHandlerBase<PsiElement> handler = HighlightUsagesHandler.createCustomHandler(myEditor, myFile);
if (handler != null) {
List<PsiElement> targets = handler.getTargets();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPassFactory.java
index 87ce15f..35324c6 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPassFactory.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/IdentifierHighlighterPassFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -44,7 +44,8 @@
if (editor.isOneLineMode()) return null;
if (CodeInsightSettings.getInstance().HIGHLIGHT_IDENTIFIER_UNDER_CARET &&
- (!ApplicationManager.getApplication().isHeadlessEnvironment() || ourTestingIdentifierHighlighting)) {
+ (!ApplicationManager.getApplication().isHeadlessEnvironment() || ourTestingIdentifierHighlighting)
+ && file.isPhysical()) {
return new IdentifierHighlighterPass(file.getProject(), file, editor);
}
return null;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
index f41ce7d..0d1f359 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/InjectedGeneralHighlightingPass.java
@@ -216,11 +216,12 @@
if (documentWindow == null) return true;
Place places = InjectedLanguageUtil.getShreds(injectedPsi);
for (PsiLanguageInjectionHost.Shred place : places) {
- TextRange textRange = place.getRangeInsideHost().shiftRight(place.getHost().getTextRange().getStartOffset());
+ PsiLanguageInjectionHost host = place.getHost();
+ TextRange textRange = place.getRangeInsideHost().shiftRight(host.getTextRange().getStartOffset());
if (textRange.isEmpty()) continue;
String desc = injectedPsi.getLanguage().getDisplayName() + ": " + injectedPsi.getText();
HighlightInfo.Builder builder = HighlightInfo.newHighlightInfo(HighlightInfoType.INJECTED_LANGUAGE_BACKGROUND).range(textRange);
- if (injectedAttributes != null) {
+ if (injectedAttributes != null && InjectedLanguageUtil.isHighlightInjectionBackground(host)) {
builder.textAttributes(injectedAttributes);
}
builder.unescapedToolTip(desc);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java
index 9f1489c..19a247f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LineMarkersPass.java
@@ -122,10 +122,10 @@
collectLineMarkersForInjected(lineMarkers, elements, this, myFile, progress);
}
- myMarkers = mergeLineMarkers(lineMarkers);
+ myMarkers = mergeLineMarkers(lineMarkers, myEditor);
}
- private List<LineMarkerInfo> mergeLineMarkers(@NotNull List<LineMarkerInfo> markers) {
+ static List<LineMarkerInfo> mergeLineMarkers(@NotNull List<LineMarkerInfo> markers, Editor editor) {
List<MergeableLineMarkerInfo> forMerge = new ArrayList<MergeableLineMarkerInfo>();
final Iterator<LineMarkerInfo> iterator = markers.iterator();
while (iterator.hasNext()) {
@@ -137,12 +137,12 @@
}
}
- if (forMerge.isEmpty() || myEditor == null) return markers;
+ if (forMerge.isEmpty() || editor == null) return markers;
final List<LineMarkerInfo> result = new ArrayList<LineMarkerInfo>(markers);
TIntObjectHashMap<List<MergeableLineMarkerInfo>> sameLineMarkers = new TIntObjectHashMap<List<MergeableLineMarkerInfo>>();
for (MergeableLineMarkerInfo info : forMerge) {
- final LogicalPosition position = myEditor.offsetToLogicalPosition(info.startOffset);
+ final LogicalPosition position = editor.offsetToLogicalPosition(info.startOffset);
List<MergeableLineMarkerInfo> infos = sameLineMarkers.get(position.line);
if (infos == null) {
infos = new ArrayList<MergeableLineMarkerInfo>();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
index 5d86733..b0265af 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.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.
@@ -55,9 +55,7 @@
import com.intellij.util.ConcurrencyUtil;
import com.intellij.util.Function;
import com.intellij.util.Processor;
-import com.intellij.util.containers.ConcurrentHashMap;
-import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.TransferToEDTQueue;
+import com.intellij.util.containers.*;
import com.intellij.util.ui.UIUtil;
import com.intellij.xml.util.XmlStringUtil;
import gnu.trove.THashMap;
@@ -67,6 +65,7 @@
import org.jetbrains.annotations.Nullable;
import java.util.*;
+import java.util.LinkedHashSet;
import java.util.concurrent.ConcurrentMap;
/**
@@ -248,24 +247,8 @@
Set<Language> languages = new SmartHashSet<Language>();
Map<String, Language> langIds = new SmartHashMap<String, Language>();
Set<String> dialects = new SmartHashSet<String>();
- for (PsiElement element : inside) {
- Language language = element.getLanguage();
- if (languages.add(language)) {
- langIds.put(language.getID(), language);
- for (Language dialect : language.getDialects()) {
- dialects.add(dialect.getID());
- }
- }
- }
- for (PsiElement element : outside) {
- Language language = element.getLanguage();
- if (languages.add(language)) {
- langIds.put(language.getID(), language);
- for (Language dialect : language.getDialects()) {
- dialects.add(dialect.getID());
- }
- }
- }
+ calculateDialects(inside, languages, langIds, dialects);
+ calculateDialects(outside, languages, langIds, dialects);
MultiMap<LocalInspectionToolWrapper, String> toolToLanguages = new MultiMap<LocalInspectionToolWrapper, String>() {
@Override
protected Collection<String> createCollection() {
@@ -309,6 +292,21 @@
return toolToLanguages;
}
+ private static void calculateDialects(@NotNull List<PsiElement> inside,
+ @NotNull Set<Language> languages,
+ @NotNull Map<String, Language> langIds,
+ @NotNull Set<String> dialects) {
+ for (PsiElement element : inside) {
+ Language language = element.getLanguage();
+ if (languages.add(language)) {
+ langIds.put(language.getID(), language);
+ for (Language dialect : language.getDialects()) {
+ dialects.add(dialect.getID());
+ }
+ }
+ }
+ }
+
@NotNull
private List<InspectionContext> visitPriorityElementsAndInit(@NotNull MultiMap<LocalInspectionToolWrapper, String> toolToLanguages,
@NotNull final InspectionManagerEx iManager,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
index f07d318..f4563f4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/PsiChangeHandler.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,9 +107,11 @@
application.invokeLater(new Runnable() {
@Override
public void run() {
- EditorMarkupModel markupModel = (EditorMarkupModel)editor.getMarkupModel();
- PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
- TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markupModel, myProject, editor.getDocument(), file);
+ if (!editor.isDisposed()) {
+ EditorMarkupModel markupModel = (EditorMarkupModel)editor.getMarkupModel();
+ PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
+ TrafficLightRenderer.setOrRefreshErrorStripeRenderer(markupModel, myProject, editor.getDocument(), file);
+ }
}
}, ModalityState.stateForComponent(editor.getComponent()), myProject.getDisposed());
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityUtil.java
index de2e353..e4181e1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SeverityUtil.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.
@@ -38,6 +38,7 @@
if (textAttributes != null) {
return new SeverityRegistrar.SeverityBasedTextAttributes(textAttributes, (HighlightInfoType.HighlightInfoTypeImpl)type);
}
- return new SeverityRegistrar.SeverityBasedTextAttributes(registrar.getTextAttributesBySeverity(type.getSeverity(null)), (HighlightInfoType.HighlightInfoTypeImpl)type);
+ TextAttributes severity = registrar.getTextAttributesBySeverity(type.getSeverity(null));
+ return new SeverityRegistrar.SeverityBasedTextAttributes(severity, (HighlightInfoType.HighlightInfoTypeImpl)type);
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java
index 24ceab1..ebc7089 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPass.java
@@ -21,7 +21,7 @@
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightingLevelManager;
import com.intellij.lang.Language;
-import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.DumbAware;
@@ -39,14 +39,16 @@
public class SlowLineMarkersPass extends TextEditorHighlightingPass implements LineMarkersProcessor, DumbAware {
private final PsiFile myFile;
+ @NotNull private final Editor myEditor;
private final int myStartOffset;
private final int myEndOffset;
private volatile Collection<LineMarkerInfo> myMarkers = Collections.emptyList();
- public SlowLineMarkersPass(@NotNull Project project, @NotNull PsiFile file, @NotNull Document document, int startOffset, int endOffset) {
- super(project, document, false);
+ public SlowLineMarkersPass(@NotNull Project project, @NotNull PsiFile file, @NotNull Editor editor, int startOffset, int endOffset) {
+ super(project, editor.getDocument(), false);
myFile = file;
+ myEditor = editor;
myStartOffset = startOffset;
myEndOffset = endOffset;
}
@@ -65,7 +67,7 @@
LineMarkersPass.collectLineMarkersForInjected(markers, elements, this, myFile, progress);
}
- myMarkers = markers;
+ myMarkers = LineMarkersPass.mergeLineMarkers(markers, myEditor);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPassFactory.java
index c3b415b..416d24b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPassFactory.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SlowLineMarkersPassFactory.java
@@ -47,7 +47,7 @@
public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull final Editor editor) {
TextRange textRange = calculateRangeToProcess(editor);
if (textRange == null) return null;
- return new SlowLineMarkersPass(myProject, file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset());
+ return new SlowLineMarkersPass(myProject, file, editor, textRange.getStartOffset(), textRange.getEndOffset());
}
private static TextRange calculateRangeToProcess(Editor editor) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SmartHashSet.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SmartHashSet.java
deleted file mode 100644
index 5b87655..0000000
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/SmartHashSet.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.codeInsight.daemon.impl;
-
-import com.intellij.util.containers.SingletonIterator;
-import gnu.trove.THashSet;
-import gnu.trove.TObjectHashingStrategy;
-import gnu.trove.TObjectProcedure;
-import org.jetbrains.annotations.NotNull;
-
-import java.lang.reflect.Array;
-import java.util.Collection;
-import java.util.Iterator;
-import java.util.Set;
-
-/**
- * Hash set (based on THashSet) which is fast when contains one or zero elements (avoids to calculate hash codes and call equals whenever possible).
- * For other sizes it delegates to THashSet.
- * Null keys are NOT PERMITTED.
- */
-public class SmartHashSet<T> extends THashSet<T> {
- private T theElement; // contains the only element if size() == 1
-
- public SmartHashSet() {
- }
-
- public SmartHashSet(@NotNull TObjectHashingStrategy<T> strategy) {
- super(strategy);
- }
-
- public SmartHashSet(int initialCapacity) {
- super(initialCapacity);
- }
-
- public SmartHashSet(int initialCapacity, TObjectHashingStrategy<T> strategy) {
- super(initialCapacity, strategy);
- }
-
- public SmartHashSet(int initialCapacity, float loadFactor) {
- super(initialCapacity, loadFactor);
- }
-
- public SmartHashSet(int initialCapacity, float loadFactor, TObjectHashingStrategy<T> strategy) {
- super(initialCapacity, loadFactor, strategy);
- }
-
- public SmartHashSet(Collection<? extends T> collection) {
- super(collection);
- }
-
- public SmartHashSet(Collection<? extends T> collection, TObjectHashingStrategy<T> strategy) {
- super(collection, strategy);
- }
-
- @Override
- public boolean contains(@NotNull Object obj) {
- T theElement = this.theElement;
- if (theElement != null) {
- return eq(theElement, (T)obj);
- }
- return !super.isEmpty() && super.contains(obj);
- }
-
- @Override
- public boolean add(@NotNull T obj) {
- T theElement = this.theElement;
- if (theElement != null) {
- if (eq(theElement, obj)) return false;
- super.add(theElement);
- this.theElement = null;
- // fallthrough
- }
- else if (super.isEmpty()) {
- this.theElement = obj;
- return true;
- }
- return super.add(obj);
- }
-
- private boolean eq(T obj, T theElement) {
- return theElement == obj || _hashingStrategy.equals(theElement, obj);
- }
-
- @Override
- public boolean equals(@NotNull Object other) {
- T theElement = this.theElement;
- if (theElement != null) {
- return other instanceof Set && ((Set)other).size() == 1 && eq(theElement, (T)((Set)other).iterator().next());
- }
-
- return super.equals(other);
- }
-
- @Override
- public int hashCode() {
- T theElement = this.theElement;
- if (theElement != null) {
- return _hashingStrategy.computeHashCode(theElement);
- }
- return super.hashCode();
- }
-
- @Override
- public void clear() {
- theElement = null;
- super.clear();
- }
-
- @Override
- public int size() {
- T theElement = this.theElement;
- if (theElement != null) {
- return 1;
- }
- return super.size();
- }
-
- @Override
- public boolean isEmpty() {
- T theElement = this.theElement;
- return theElement == null && super.isEmpty();
- }
-
- @Override
- public boolean remove(@NotNull Object obj) {
- T theElement = this.theElement;
- if (theElement != null) {
- if (eq(theElement, (T)obj)) {
- this.theElement = null;
- return true;
- }
- return false;
- }
- return super.remove(obj);
- }
-
- @NotNull
- @Override
- public Iterator<T> iterator() {
- T theElement = this.theElement;
- if (theElement != null) {
- return new SingletonIterator<T>(theElement);
- }
- return super.iterator();
- }
-
- @Override
- public boolean forEach(@NotNull TObjectProcedure<T> procedure) {
- T theElement = this.theElement;
- if (theElement != null) {
- return procedure.execute(theElement);
- }
- return super.forEach(procedure);
- }
-
- @NotNull
- @Override
- public Object[] toArray() {
- T theElement = this.theElement;
- if (theElement != null) {
- return new Object[]{theElement};
- }
- return super.toArray();
- }
-
- @NotNull
- @Override
- public <T> T[] toArray(@NotNull T[] a) {
- T theElement = (T)this.theElement;
- if (theElement != null) {
- if (a.length == 0) {
- a = (T[]) Array.newInstance(a.getClass().getComponentType(), 1);
- }
- a[0] = theElement;
- if (a.length > 1) {
- a[1] = null;
- }
- return a;
- }
- return super.toArray(a);
- }
-
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/StatusBarUpdater.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/StatusBarUpdater.java
index 0437c18..cc92a65 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/StatusBarUpdater.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/StatusBarUpdater.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -32,7 +32,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.wm.StatusBar;
import com.intellij.openapi.wm.WindowManager;
-import com.intellij.openapi.wm.ex.StatusBarEx;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
@@ -96,11 +95,8 @@
String text = info != null && info.getDescription() != null ? info.getDescription() : "";
StatusBar statusBar = WindowManager.getInstance().getStatusBar(editor.getContentComponent(), myProject);
- if (statusBar instanceof StatusBarEx) {
- StatusBarEx barEx = (StatusBarEx)statusBar;
- if (!text.equals(barEx.getInfo())){
- statusBar.setInfo(text, "updater");
- }
+ if (statusBar != null && !text.equals(statusBar.getInfo())) {
+ statusBar.setInfo(text, "updater");
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java
index d68504c..f0db8a3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficLightRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -97,7 +97,7 @@
}
@Override
- public void attributesChanged(@NotNull RangeHighlighterEx highlighter) {
+ public void attributesChanged(@NotNull RangeHighlighterEx highlighter, boolean renderersChanged) {
}
});
UIUtil.invokeLaterIfNeeded(new Runnable() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java
index 4ed274f..19a958a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/TrafficProgressPanel.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.
@@ -34,6 +34,7 @@
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.hash.LinkedHashMap;
import com.intellij.util.ui.AwtVisitor;
+import com.intellij.xml.util.XmlStringUtil;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -223,12 +224,12 @@
int currentSeverityErrors = 0;
@Language("HTML")
- String text = "<html><body>";
+ String text = "";
for (int i = status.errorCount.length - 1; i >= 0; i--) {
if (status.errorCount[i] > 0) {
final HighlightSeverity severity = SeverityRegistrar.getSeverityRegistrar(myTrafficLightRenderer.getProject()).getSeverityByIndex(i);
String name =
- status.errorCount[i] > 1 ? StringUtil.pluralize(severity.toString().toLowerCase()) : severity.toString().toLowerCase();
+ status.errorCount[i] > 1 ? StringUtil.pluralize(severity.getName().toLowerCase()) : severity.getName().toLowerCase();
text += status.errorAnalyzingFinished
? DaemonBundle.message("errors.found", status.errorCount[i], name)
: DaemonBundle.message("errors.found.so.far", status.errorCount[i], name);
@@ -241,7 +242,7 @@
? DaemonBundle.message("no.errors.or.warnings.found")
: DaemonBundle.message("no.errors.or.warnings.found.so.far") + "<br>";
}
- statistics.setText(text);
+ statistics.setText(XmlStringUtil.wrapInHtml(text));
}
finally {
if (isFake) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GeneratedSourcesHighlightingSettingProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GeneratedSourcesHighlightingSettingProvider.java
new file mode 100644
index 0000000..78823d5
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/analysis/GeneratedSourcesHighlightingSettingProvider.java
@@ -0,0 +1,38 @@
+/*
+ * 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.codeInsight.daemon.impl.analysis;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.GeneratedSourcesFilter;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class GeneratedSourcesHighlightingSettingProvider extends DefaultHighlightingSettingProvider {
+ @Nullable
+ @Override
+ public FileHighlightingSetting getDefaultSetting(@NotNull Project project, @NotNull VirtualFile file) {
+ for (GeneratedSourcesFilter filter : GeneratedSourcesFilter.EP_NAME.getExtensions()) {
+ if (filter.isGeneratedSource(file, project)) {
+ return FileHighlightingSetting.SKIP_INSPECTION;
+ }
+ }
+ return null;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java
index 24780d7..5ccc3fe 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/quickFix/FileReferenceQuickFixProvider.java
@@ -25,7 +25,6 @@
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
@@ -103,7 +102,7 @@
if (context == null) return Collections.emptyList();
final VirtualFile virtualFile = context.getVirtualFile();
- if (virtualFile == null) return Collections.emptyList();
+ if (virtualFile == null || !virtualFile.isValid()) return Collections.emptyList();
final PsiDirectory directory = context.getManager().findDirectory(virtualFile);
if (directory == null) return Collections.emptyList();
@@ -111,7 +110,7 @@
if (fileReferenceSet.isCaseSensitive()) {
final PsiElement psiElement = reference.innerSingleResolve(false);
- if (psiElement instanceof PsiNamedElement) {
+ if (psiElement != null) {
final String existingElementName = ((PsiNamedElement)psiElement).getName();
final RenameFileReferenceIntentionAction renameRefAction = new RenameFileReferenceIntentionAction(existingElementName, reference);
@@ -151,7 +150,7 @@
@Nullable
private static Module getModuleForContext(@NotNull PsiFileSystemItem context) {
VirtualFile file = context.getVirtualFile();
- return file != null ? ModuleUtil.findModuleForFile(file, context.getProject()) : null;
+ return file != null ? ModuleUtilCore.findModuleForFile(file, context.getProject()) : null;
}
private static class MyCreateFileFix extends CreateFileFix {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java
index 12ea57d..42f34f0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/AbstractExternalFilter.java
@@ -31,6 +31,7 @@
import com.intellij.openapi.vfs.*;
import com.intellij.psi.PsiElement;
import com.intellij.util.SystemProperties;
+import com.intellij.util.io.URLUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NonNls;
@@ -157,7 +158,7 @@
referenceUnpackedImage = false;
JarFileSystem jarFileSystem = JarFileSystem.getInstance();
try {
- JarFile jarFile = jarFileSystem.getJarFile(jarFileSystem.findFileByPath(jarPath + StandardFileSystems.JAR_SEPARATOR));
+ JarFile jarFile = jarFileSystem.getJarFile(jarFileSystem.findFileByPath(jarPath + URLUtil.JAR_SEPARATOR));
if (jarFile != null) {
JarFile.JarEntry entry = jarFile.getEntry(imgPath);
if (entry != null) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
index 58aee51..c9d6fb5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -64,11 +64,12 @@
import java.awt.*;
import java.awt.event.*;
import java.util.List;
+import java.util.Map;
import java.util.Stack;
public class DocumentationComponent extends JPanel implements Disposable, DataProvider {
- private static final String DOCUMENTATION_TOPIC_ID = "reference.toolWindows.Documentation";
+ @NonNls private static final String DOCUMENTATION_TOPIC_ID = "reference.toolWindows.Documentation";
private static final DataContext EMPTY_DATA_CONTEXT = new DataContext() {
@Override
@@ -77,29 +78,29 @@
}
};
- private static final int MAX_WIDTH = 500;
+ private static final int MAX_WIDTH = 500;
private static final int MAX_HEIGHT = 300;
private static final int MIN_HEIGHT = 45;
- private DocumentationManager myManager;
+ private DocumentationManager myManager;
private SmartPsiElementPointer myElement;
- private final Stack<Context> myBackStack = new Stack<Context>();
+ private final Stack<Context> myBackStack = new Stack<Context>();
private final Stack<Context> myForwardStack = new Stack<Context>();
- private final ActionToolbar myToolBar;
- private boolean myIsEmpty;
- private boolean myIsShown;
- private final JLabel myElementLabel;
- private Style myFontSizeStyle;
- private JSlider myFontSizeSlider;
- private final JComponent mySettingsPanel;
+ private final ActionToolbar myToolBar;
+ private boolean myIsEmpty;
+ private boolean myIsShown;
+ private final JLabel myElementLabel;
+ private Style myFontSizeStyle;
+ private JSlider myFontSizeSlider;
+ private final JComponent mySettingsPanel;
private final MyShowSettingsButton myShowSettingsButton;
- private boolean myIgnoreFontSizeSliderChange;
+ private boolean myIgnoreFontSizeSliderChange;
private static class Context {
final SmartPsiElementPointer element;
- final String text;
- final Rectangle viewRect;
+ final String text;
+ final Rectangle viewRect;
public Context(SmartPsiElementPointer element, String text, Rectangle viewRect) {
this.element = element;
@@ -108,18 +109,17 @@
}
}
- private final JScrollPane myScrollPane;
- private final JEditorPane myEditorPane;
- private String myText; // myEditorPane.getText() surprisingly crashes.., let's cache the text
- private final JPanel myControlPanel;
- private boolean myControlPanelVisible;
- private final ExternalDocAction myExternalDocAction;
- private Consumer<PsiElement> myNavigateCallback;
+ private final JScrollPane myScrollPane;
+ private final JEditorPane myEditorPane;
+ private String myText; // myEditorPane.getText() surprisingly crashes.., let's cache the text
+ private final JPanel myControlPanel;
+ private boolean myControlPanelVisible;
+ private final ExternalDocAction myExternalDocAction;
+ private Consumer<PsiElement> myNavigateCallback;
private JBPopup myHint;
- private final HashMap<KeyStroke, ActionListener> myKeyboardActions = new HashMap<KeyStroke, ActionListener>();
- // KeyStroke --> ActionListener
+ private final Map<KeyStroke, ActionListener> myKeyboardActions = new HashMap<KeyStroke, ActionListener>();
@Override
public boolean requestFocusInWindow() {
@@ -362,7 +362,7 @@
private JComponent createSettingsPanel() {
JPanel result = new JPanel(new FlowLayout(FlowLayout.RIGHT, 3, 0));
result.add(new JLabel(ApplicationBundle.message("label.font.size")));
- myFontSizeSlider = new JSlider(JSlider.HORIZONTAL, 0, FontSize.values().length - 1, 3);
+ myFontSizeSlider = new JSlider(SwingConstants.HORIZONTAL, 0, FontSize.values().length - 1, 3);
myFontSizeSlider.setMinorTickSpacing(1);
myFontSizeSlider.setPaintTicks(true);
myFontSizeSlider.setPaintTrack(true);
@@ -500,10 +500,10 @@
}
private void setDataInternal(SmartPsiElementPointer element, String text, final Rectangle viewRect, boolean skip) {
- boolean justShown = false;
myElement = element;
+ boolean justShown = false;
if (!myIsShown && myHint != null) {
myEditorPane.setText(text);
applyFontSize();
@@ -749,7 +749,7 @@
}
});
- myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, KeyEvent.CTRL_MASK), new ActionListener() {
+ myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, InputEvent.CTRL_MASK), new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JScrollBar scrollBar = myScrollPane.getVerticalScrollBar();
@@ -757,7 +757,7 @@
}
});
- myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, KeyEvent.CTRL_MASK), new ActionListener() {
+ myKeyboardActions.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, InputEvent.CTRL_MASK), new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JScrollBar scrollBar = myScrollPane.getVerticalScrollBar();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
index 5fe02bb..273777e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java
@@ -266,9 +266,12 @@
final PsiElement list =
ParameterInfoController.findArgumentList(file, editor.getCaretModel().getOffset(), -1);
if (list != null) {
- myParameterInfoController = ParameterInfoController.findControllerAtOffset(editor, list.getTextRange().getStartOffset());
LookupEx lookup = LookupManager.getInstance(myProject).getActiveLookup();
- if (lookup != null) myParameterInfoController = null; // take completion variants for documentation then
+ if (lookup != null) {
+ myParameterInfoController = null; // take completion variants for documentation then
+ } else {
+ myParameterInfoController = ParameterInfoController.findControllerAtOffset(editor, list.getTextRange().getStartOffset());
+ }
}
final PsiElement originalElement = getContextElement(editor, file);
@@ -967,10 +970,11 @@
}
}
);
- BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : url);
+ String url1 = urls != null && !urls.isEmpty() ? urls.get(0) : url;
+ BrowserUtil.browse(url1);
}
else {
- BrowserUtil.launchBrowser(url);
+ BrowserUtil.browse(url);
}
return "";
}
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 7c23791..89e8b55 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/QuickDocOnMouseOverManager.java
@@ -32,6 +32,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiWhiteSpace;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.popup.PopupFactoryImpl;
import com.intellij.util.Alarm;
import com.intellij.util.containers.WeakHashMap;
@@ -169,11 +170,7 @@
if (hint != null) {
// Skip the event if the control is shown because of explicit 'show quick doc' action call.
- WeakReference<DocumentationManager> ref = myDocumentationManager;
- if (ref == null) {
- return;
- }
- DocumentationManager manager = ref.get();
+ DocumentationManager manager = SoftReference.dereference(myDocumentationManager);
if (manager == null || !manager.isCloseOnSneeze()) {
return;
}
@@ -257,16 +254,7 @@
@Nullable
private DocumentationManager getDocManager() {
- WeakReference<DocumentationManager> ref = myDocumentationManager;
- if (ref == null) {
- return null;
- }
-
- DocumentationManager docManager = ref.get();
- if (docManager == null) {
- return null;
- }
- return docManager;
+ return SoftReference.dereference(myDocumentationManager);
}
private static class DelayedQuickDocInfo {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java
index 4c24ff5..6184c67 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/AutoHardWrapHandler.java
@@ -118,7 +118,7 @@
}
VisualPosition visEndLinePosition = editor.offsetToVisualPosition(endOffset);
- if (margin > visEndLinePosition.column) {
+ if (margin >= visEndLinePosition.column) {
if (change != null) {
change.modificationStamp = document.getModificationStamp();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java
index 6017a40..c130b8a 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BackspaceHandler.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.
@@ -22,7 +22,6 @@
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -45,6 +44,7 @@
protected final EditorActionHandler myOriginalHandler;
public BackspaceHandler(EditorActionHandler originalHandler) {
+ super(true);
myOriginalHandler = originalHandler;
}
@@ -71,6 +71,7 @@
char c = chars.charAt(offset);
final Editor injectedEditor = TypedHandler.injectedEditorIfCharTypedIsSignificant(c, editor, file);
+ final Editor originalEditor = editor;
if (injectedEditor != editor) {
int injectedOffset = injectedEditor.getCaretModel().getOffset();
if (isOffsetInsideInjected(injectedEditor, injectedOffset)) {
@@ -93,7 +94,7 @@
HighlighterIterator hiterator = ((EditorEx)editor).getHighlighter().createIterator(offset);
boolean wasClosingQuote = quoteHandler != null && quoteHandler.isClosingQuote(hiterator, offset);
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.execute(originalEditor, dataContext);
if (!toWordStart) {
for(BackspaceHandlerDelegate delegate: delegates) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BaseEnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BaseEnterHandler.java
index 91a5118..2cd7c33 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BaseEnterHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/BaseEnterHandler.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.
@@ -23,6 +23,10 @@
public abstract class BaseEnterHandler extends EditorWriteActionHandler {
private static final String GROUP_ID = "EnterHandler.GROUP_ID";
+ protected BaseEnterHandler() {
+ super(true);
+ }
+
@Override
public DocCommandGroupId getCommandGroupId(Editor editor) {
return DocCommandGroupId.withGroupId(editor.getDocument(), GROUP_ID);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java
index 8ebd653..e7c723c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndAction.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,7 +26,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -39,6 +38,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java
index 085e465..9431da1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockEndWithSelectionAction.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.
@@ -38,6 +38,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java
index 3ab23ae..690efff 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartAction.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,7 +26,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -39,6 +38,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java
index 352297b..9819efc 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CodeBlockStartWithSelectionAction.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,7 +26,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -39,6 +38,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
index 2e70f9e..618e771 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyHandler.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,12 +20,10 @@
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.RawText;
-import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actions.CopyAction;
+import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
@@ -66,12 +64,23 @@
}
final SelectionModel selectionModel = editor.getSelectionModel();
- if(!selectionModel.hasSelection() && !selectionModel.hasBlockSelection()) {
+ if(!selectionModel.hasSelection(true) && !selectionModel.hasBlockSelection()) {
if (Registry.is(CopyAction.SKIP_COPY_AND_CUT_FOR_EMPTY_SELECTION_KEY)) {
return;
}
- selectionModel.selectLineAtCaret();
- if (!selectionModel.hasSelection()) return;
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ selectionModel.selectLineAtCaret();
+ }
+ });
+ if (!selectionModel.hasSelection(true)) return;
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ EditorActionUtil.moveCaretToLineStartIgnoringSoftWraps(editor);
+ }
+ });
}
PsiDocumentManager.getInstance(project).commitAllDocuments();
@@ -87,7 +96,7 @@
}
}
- String rawText = TextBlockTransferable.convertLineSeparators(selectionModel.getSelectedText(), "\n", transferableDatas);
+ String rawText = TextBlockTransferable.convertLineSeparators(selectionModel.getSelectedText(true), "\n", transferableDatas);
String escapedText = null;
for(CopyPastePreProcessor processor: Extensions.getExtensions(CopyPastePreProcessor.EP_NAME)) {
escapedText = processor.preprocessOnCopy(file, startOffsets, endOffsets, rawText);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java
index 01f2649..100cec5 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CopyPasteFoldingProcessor.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.
@@ -89,6 +89,8 @@
int caretOffset,
Ref<Boolean> indented,
final FoldingTransferableData value) {
+ if (value.getData().length == 0) return;
+
final CodeFoldingManagerImpl foldingManager = (CodeFoldingManagerImpl)CodeFoldingManager.getInstance(project);
foldingManager.updateFoldRegions(editor, true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CutHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CutHandler.java
index 426d95d..b35fa16 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CutHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/CutHandler.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,19 +20,22 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorModificationUtil;
-import com.intellij.openapi.editor.SelectionModel;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.actions.CopyAction;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
public class CutHandler extends EditorWriteActionHandler {
private final EditorActionHandler myOriginalHandler;
@@ -41,7 +44,7 @@
}
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(final Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getContentComponent()));
if (project == null) {
if (myOriginalHandler != null) {
@@ -59,27 +62,58 @@
return;
}
- SelectionModel selectionModel = editor.getSelectionModel();
- if (!selectionModel.hasSelection() && !selectionModel.hasBlockSelection()) {
+ final SelectionModel selectionModel = editor.getSelectionModel();
+ if (!selectionModel.hasSelection(true) && !selectionModel.hasBlockSelection()) {
if (Registry.is(CopyAction.SKIP_COPY_AND_CUT_FOR_EMPTY_SELECTION_KEY)) {
return;
}
- selectionModel.selectLineAtCaret();
- if (!selectionModel.hasSelection()) return;
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ selectionModel.selectLineAtCaret();
+ }
+ });
+ if (!selectionModel.hasSelection(true)) return;
}
int start = selectionModel.getSelectionStart();
int end = selectionModel.getSelectionEnd();
+ final List<TextRange> selections = new ArrayList<TextRange>();
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ selections.add(new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()));
+ }
+ });
+ }
EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_COPY).execute(editor, dataContext);
- if (start != end) {
- // There is a possible case that 'sticky selection' is active. It's automatically removed on copying then, so, we explicitly
- // remove the text.
- editor.getDocument().deleteString(start, end);
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+
+ Collections.reverse(selections);
+ final Iterator<TextRange> it = selections.iterator();
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ TextRange range = it.next();
+ editor.getCaretModel().moveToOffset(range.getStartOffset());
+ selectionModel.removeSelection();
+ editor.getDocument().deleteString(range.getStartOffset(), range.getEndOffset());
+ }
+ });
+ editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
else {
- EditorModificationUtil.deleteSelectedText(editor);
+ if (start != end) {
+ // There is a possible case that 'sticky selection' is active. It's automatically removed on copying then, so, we explicitly
+ // remove the text.
+ editor.getDocument().deleteString(start, end);
+ }
+ else {
+ EditorModificationUtil.deleteSelectedText(editor);
+ }
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EndHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EndHandler.java
index 7315311..dd00e26 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EndHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EndHandler.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,6 @@
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -37,6 +36,7 @@
private final EditorActionHandler myOriginalHandler;
public EndHandler(EditorActionHandler originalHandler) {
+ super(true);
myOriginalHandler = originalHandler;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java
index 1d83307..eebdb50 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/JoinLinesHandler.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,6 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
@@ -58,6 +57,7 @@
private final EditorActionHandler myOriginalHandler;
public JoinLinesHandler(EditorActionHandler originalHandler) {
+ super(true);
myOriginalHandler = originalHandler;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MatchBraceAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MatchBraceAction.java
index 11b70bb..0f19120 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MatchBraceAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/MatchBraceAction.java
@@ -1,8 +1,22 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.editorActions;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
@@ -24,6 +38,10 @@
}
private static class MyHandler extends EditorActionHandler {
+ public MyHandler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
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 65655c4..9c15f4f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/PasteHandler.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,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
@@ -22,13 +21,13 @@
import com.intellij.lang.LanguageFormatting;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorTextInsertHandler;
+import com.intellij.openapi.editor.actions.PasteAction;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
@@ -49,6 +48,7 @@
import com.intellij.util.containers.HashMap;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
@@ -56,48 +56,48 @@
public class PasteHandler extends EditorActionHandler implements EditorTextInsertHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.PasteHandler");
-
- public static final String TRANSFERABLE_PROVIDER = "PasteTransferableProvider";
-
- private final EditorActionHandler myOriginalHandler;
-
private static final ExtensionPointName<PasteProvider> EP_NAME = ExtensionPointName.create("com.intellij.customPasteProvider");
+ private final EditorActionHandler myOriginalHandler;
+
public PasteHandler(EditorActionHandler originalAction) {
myOriginalHandler = originalAction;
}
@Override
- public void execute(final Editor editor, final DataContext dataContext, final Producer<Transferable> transferableProvider) {
- if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return;
- final Document document = editor.getDocument();
+ public void execute(final Editor editor, final DataContext dataContext) {
+ execute(editor, dataContext, null);
+ }
+ @Override
+ public void execute(final Editor editor, final DataContext dataContext, @Nullable final Producer<Transferable> producer) {
+ if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return;
+
+ final Document document = editor.getDocument();
if (!FileDocumentManager.getInstance().requestWriting(document, CommonDataKeys.PROJECT.getData(dataContext))) {
return;
}
- DataContext context = new DataContext() {
- @Override
- public Object getData(@NonNls String dataId) {
- if (TRANSFERABLE_PROVIDER.equals(dataId)) {
- return transferableProvider;
+ DataContext context = dataContext;
+ if (producer != null) {
+ context = new DataContext() {
+ @Override
+ public Object getData(@NonNls String dataId) {
+ return PasteAction.TRANSFERABLE_PROVIDER.is(dataId) ? producer : dataContext.getData(dataId);
}
-
- return dataContext.getData(dataId);
- }
- };
-
+ };
+ }
final Project project = editor.getProject();
- if (project == null || editor.isColumnMode() || editor.getSelectionModel().hasBlockSelection()) {
+ if (project == null || editor.isColumnMode() || editor.getSelectionModel().hasBlockSelection()
+ || editor.getCaretModel().getAllCarets().size() > 1) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, context);
}
return;
}
-
- final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
+ final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (file == null) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, context);
@@ -107,13 +107,13 @@
document.startGuardedBlockChecking();
try {
- for(PasteProvider provider: Extensions.getExtensions(EP_NAME)) {
+ for (PasteProvider provider : Extensions.getExtensions(EP_NAME)) {
if (provider.isPasteEnabled(context)) {
provider.performPaste(context);
return;
}
}
- doPaste(editor, project, file, document, transferableProvider);
+ doPaste(editor, project, file, document, producer);
}
catch (ReadOnlyFragmentModificationException e) {
EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(document).handle(e);
@@ -123,28 +123,26 @@
}
}
- @Override
- public void execute(final Editor editor, final DataContext dataContext) {
- execute(editor, dataContext, new Producer<Transferable>() {
- @Override
- public Transferable produce() {
- CopyPasteManager copyPasteManager = CopyPasteManager.getInstance();
- Transferable contents = copyPasteManager.getContents();
- if (contents != null) {
- copyPasteManager.stopKillRings();
- }
-
- return contents;
- }
- });
- }
-
private static void doPaste(final Editor editor,
final Project project,
final PsiFile file,
final Document document,
- final Producer<Transferable> transferableFunction) {
- Transferable content = transferableFunction.produce();
+ final Producer<Transferable> producer) {
+ Transferable content = null;
+
+ if (producer != null) {
+ content = producer.produce();
+ }
+ else {
+ CopyPasteManager manager = CopyPasteManager.getInstance();
+ if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+ content = manager.getContents();
+ if (content != null) {
+ manager.stopKillRings();
+ }
+ }
+ }
+
if (content != null) {
String text = null;
try {
@@ -158,7 +156,7 @@
final CodeInsightSettings settings = CodeInsightSettings.getInstance();
final Map<CopyPastePostProcessor, TextBlockTransferableData> extraData = new HashMap<CopyPastePostProcessor, TextBlockTransferableData>();
- for(CopyPastePostProcessor processor: Extensions.getExtensions(CopyPastePostProcessor.EP_NAME)) {
+ for (CopyPastePostProcessor processor : Extensions.getExtensions(CopyPastePostProcessor.EP_NAME)) {
TextBlockTransferableData data = processor.extractTransferableData(content);
if (data != null) {
extraData.put(processor, data);
@@ -170,7 +168,7 @@
final CaretModel caretModel = editor.getCaretModel();
final SelectionModel selectionModel = editor.getSelectionModel();
final int col = caretModel.getLogicalPosition().column;
-
+
// There is a possible case that we want to perform paste while there is an active selection at the editor and caret is located
// inside it (e.g. Ctrl+A is pressed while caret is not at the zero column). We want to insert the text at selection start column
// then, hence, inserted block of text should be indented according to the selection start as well.
@@ -182,24 +180,12 @@
else {
blockIndentAnchorColumn = col;
}
-
- // We assume that EditorModificationUtil.insertStringAtCaret() is smart enough to understand that text that is currently
- // selected at editor (if any) should be removed.
- //
- //if (selectionModel.hasSelection()) {
- // ApplicationManager.getApplication().runWriteAction(
- // new Runnable() {
- // public void run() {
- // EditorModificationUtil.deleteSelectedText(editor);
- // }
- // }
- // );
- //}
+
+ // We assume that EditorModificationUtil.insertStringAtCaret() is smart enough to remove currently selected text (if any).
RawText rawText = RawText.fromTransferable(content);
-
String newText = text;
- for(CopyPastePreProcessor preProcessor: Extensions.getExtensions(CopyPastePreProcessor.EP_NAME)) {
+ for (CopyPastePreProcessor preProcessor : Extensions.getExtensions(CopyPastePreProcessor.EP_NAME)) {
newText = preProcessor.preprocessOnPaste(project, file, editor, newText, rawText);
}
int indentOptions = text.equals(newText) ? settings.REFORMAT_ON_PASTE : CodeInsightSettings.REFORMAT_BLOCK;
@@ -209,18 +195,17 @@
indentOptions = CodeInsightSettings.INDENT_BLOCK;
}
- int length = text.length();
- final String text1 = text;
-
+ final String _text = text;
ApplicationManager.getApplication().runWriteAction(
new Runnable() {
@Override
public void run() {
- EditorModificationUtil.insertStringAtCaret(editor, text1, false, true);
+ EditorModificationUtil.insertStringAtCaret(editor, _text, false, true);
}
}
);
+ int length = text.length();
int offset = caretModel.getOffset() - length;
if (offset < 0) {
length += offset;
@@ -233,12 +218,12 @@
selectionModel.removeSelection();
final Ref<Boolean> indented = new Ref<Boolean>(Boolean.FALSE);
- for(Map.Entry<CopyPastePostProcessor, TextBlockTransferableData> e: extraData.entrySet()) {
+ for (Map.Entry<CopyPastePostProcessor, TextBlockTransferableData> e : extraData.entrySet()) {
//noinspection unchecked
e.getKey().processTransferableData(project, editor, bounds, caretOffset, indented, e.getValue());
}
- boolean pastedTextContainsWhiteSpacesOnly =
+ boolean pastedTextContainsWhiteSpacesOnly =
CharArrayUtil.shiftForward(document.getCharsSequence(), bounds.getStartOffset(), " \n\t") >= bounds.getEndOffset();
VirtualFile virtualFile = file.getVirtualFile();
@@ -254,13 +239,13 @@
indentBlock(project, editor, bounds.getStartOffset(), bounds.getEndOffset(), blockIndentAnchorColumn);
}
break;
-
+
case CodeInsightSettings.INDENT_EACH_LINE:
if (!indented.get()) {
indentEachLine(project, editor, bounds.getStartOffset(), bounds.getEndOffset());
}
break;
-
+
case CodeInsightSettings.REFORMAT_BLOCK:
indentEachLine(project, editor, bounds.getStartOffset(), bounds.getEndOffset()); // this is needed for example when inserting a comment before method
reformatBlock(project, editor, bounds.getStartOffset(), bounds.getEndOffset());
@@ -294,42 +279,7 @@
}
else {
indentPlainTextBlock(document, startOffset, endOffset, originalCaretCol);
- }
-
-
- //boolean hasNewLine = false;
- //for (int i = endOffset - 1; i >= startOffset; i--) {
- // char c = chars.charAt(i);
- // if (c == '\n' || c == '\r') {
- // hasNewLine = true;
- // break;
- // }
- // if (c != ' ' && c != '\t') return; // do not indent if does not end with line separator
- //}
- //
- //if (!hasNewLine) return;
- //int lineStart = CharArrayUtil.shiftBackwardUntil(chars, startOffset - 1, "\n\r") + 1;
- //int spaceEnd = CharArrayUtil.shiftForward(chars, lineStart, " \t");
- //if (startOffset <= spaceEnd) { // we are in starting spaces
- // if (lineStart != startOffset) {
- // String deletedS = chars.subSequence(lineStart, startOffset).toString();
- // document.deleteString(lineStart, startOffset);
- // startOffset = lineStart;
- // endOffset -= deletedS.length();
- // document.insertString(endOffset, deletedS);
- // LogicalPosition pos = new LogicalPosition(editor.getCaretModel().getLogicalPosition().line, originalCaretCol);
- // editor.getCaretModel().moveToLogicalPosition(pos);
- // }
- //
- // PsiDocumentManager.getInstance(project).commitAllDocuments();
- // PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
- // if (LanguageFormatting.INSTANCE.forContext(file) != null) {
- // indentBlockWithFormatter(project, document, startOffset, endOffset, file);
- // }
- // else {
- // indentPlainTextBlock(document, startOffset, endOffset, originalCaretCol);
- // }
- //}
+ }
}
private static void indentEachLine(Project project, Editor editor, int startOffset, int endOffset) {
@@ -350,7 +300,7 @@
// int i = 1;
// int j = 1;
// }
- //
+ //
//
// We get the following on paste then:
// if (true) {
@@ -409,17 +359,17 @@
}
linesToAdjustIndent++;
}
-
+
String indentString = StringUtil.repeatSymbol(' ', indentLevel);
for (; linesToAdjustIndent > 0; linesToAdjustIndent--) {
int lineStartOffset = document.getLineStartOffset(++line);
document.insertString(lineStartOffset, indentString);
- }
+ }
}
private static void indentBlockWithFormatter(Project project, Document document, int startOffset, int endOffset, PsiFile file) {
-
+
// Algorithm: the main idea is to process the first line of the pasted block, adjust its indent if necessary, calculate indent
// adjustment string and apply to each line of the pasted block starting from the second one.
//
@@ -449,12 +399,12 @@
// Example:
// [pasted line 1
// pasted line 2]
- // We adjust the first line via formatter then and apply first line's indent to all subsequent pasted lines.
-
+ // We adjust the first line via formatter then and apply first line's indent to all subsequent pasted lines.
+
CharSequence chars = document.getCharsSequence();
final int firstLine = document.getLineNumber(startOffset);
final int firstLineStart = document.getLineStartOffset(firstLine);
-
+
// There is a possible case that we paste block that ends with new line that is empty or contains only white space symbols.
// We want to preserve indent for the original document line where paste was performed.
// Example:
@@ -478,7 +428,7 @@
break;
}
}
-
+
final int lastLine;
if (saveLastLineIndent) {
lastLine = document.getLineNumber(endOffset) - 1;
@@ -491,7 +441,7 @@
document.deleteString(start, i);
}
}
-
+
// Insert white space from the start line of the pasted block.
int indentToKeepEndOffset = Math.min(startOffset, CharArrayUtil.shiftForward(chars, firstLineStart, " \t"));
if (indentToKeepEndOffset > firstLineStart) {
@@ -500,10 +450,10 @@
}
else {
lastLine = document.getLineNumber(endOffset);
- }
-
+ }
+
final int i = CharArrayUtil.shiftBackward(chars, startOffset - 1, " \t");
-
+
// Handle a situation when pasted block doesn't start a new line.
if (chars.charAt(startOffset) != '\n' && i > 0 && chars.charAt(i) != '\n') {
int firstNonWsOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t");
@@ -511,7 +461,7 @@
CharSequence toInsert = chars.subSequence(firstLineStart, firstNonWsOffset);
for (int line = firstLine + 1; line <= lastLine; line++) {
document.insertString(document.getLineStartOffset(line), toInsert);
- }
+ }
}
return;
}
@@ -522,7 +472,7 @@
return;
}
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
-
+
final int j = CharArrayUtil.shiftForward(chars, startOffset, " \t\n");
if (j >= endOffset) {
// Pasted text contains white space/line feed symbols only, do nothing.
@@ -532,7 +482,7 @@
final int anchorLine = document.getLineNumber(j);
final int anchorLineStart = document.getLineStartOffset(anchorLine);
codeStyleManager.adjustLineIndent(file, j);
-
+
// Handle situation when pasted block starts with non-white space symbols.
if (anchorLine == firstLine && j == startOffset) {
int indentOffset = CharArrayUtil.shiftForward(chars, firstLineStart, " \t");
@@ -544,7 +494,7 @@
}
return;
}
-
+
// Handle situation when pasted block starts from white space symbols. Assume that the pasted text started at the line start,
// i.e. correct indentation level is stored at the blocks structure.
final int firstNonWsOffset = CharArrayUtil.shiftForward(chars, anchorLineStart, " \t");
@@ -559,7 +509,7 @@
}
return;
}
-
+
// We've pasted text to the non-first column and exact white space between the line start and caret position on the moment of paste
// has been removed by formatter during 'adjust line indent'
// Example:
@@ -582,8 +532,8 @@
}
else {
desiredSymbolsToRemove = -diff;
- }
-
+ }
+
for (int line = anchorLine + 1; line <= lastLine; line++) {
int currentLineStart = document.getLineStartOffset(line);
int currentLineIndentOffset = CharArrayUtil.shiftForward(chars, currentLineStart, " \t");
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java
index 338dbed..7d0fa65 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectWordHandler.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,9 +21,9 @@
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.CompositeLanguage;
import com.intellij.lang.Language;
+import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -33,18 +33,20 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.List;
+
public class SelectWordHandler extends EditorActionHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.SelectWordHandler");
private final EditorActionHandler myOriginalHandler;
public SelectWordHandler(EditorActionHandler originalHandler) {
+ super(true);
myOriginalHandler = originalHandler;
}
@@ -53,11 +55,6 @@
if (LOG.isDebugEnabled()) {
LOG.debug("enter: execute(editor='" + editor + "')");
}
- if (editor instanceof EditorWindow && editor.getSelectionModel().hasSelection()
- && InjectedLanguageUtil.isSelectionIsAboutToOverflowInjectedFragment((EditorWindow)editor)) {
- // selection about to spread beyond injected fragment
- editor = ((EditorWindow)editor).getDelegate();
- }
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(editor.getComponent()));
if (project == null) {
if (myOriginalHandler != null) {
@@ -65,26 +62,42 @@
}
return;
}
+ PsiDocumentManager.getInstance(project).commitAllDocuments();
- Document document = editor.getDocument();
- final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
-
- if (file == null) {
+ TextRange range = selectWord(editor, project);
+ if (editor instanceof EditorWindow) {
+ if (range == null || !isInsideEditableInjection((EditorWindow)editor, range, project) || TextRange.from(0, editor.getDocument().getTextLength()).equals(
+ new TextRange(editor.getSelectionModel().getSelectionStart(), editor.getSelectionModel().getSelectionEnd()))) {
+ editor = ((EditorWindow)editor).getDelegate();
+ range = selectWord(editor, project);
+ }
+ }
+ if (range == null) {
if (myOriginalHandler != null) {
myOriginalHandler.execute(editor, dataContext);
}
- return;
}
-
- PsiDocumentManager.getInstance(project).commitAllDocuments();
- doAction(editor, file);
+ else {
+ editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
+ }
}
- private static void doAction(@NotNull Editor editor, @NotNull PsiFile file) {
+ private static boolean isInsideEditableInjection(EditorWindow editor, TextRange range, Project project) {
+ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ if (file == null) return true;
+ List<TextRange> editables = InjectedLanguageManager.getInstance(project).intersectWithAllEditableFragments(file, range);
+
+ return editables.size() == 1 && range.equals(editables.get(0));
+ }
+
+ @Nullable("null means unable to select")
+ private static TextRange selectWord(@NotNull Editor editor, @NotNull Project project) {
+ Document document = editor.getDocument();
+ PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(document);
if (file instanceof PsiCompiledFile) {
file = ((PsiCompiledFile)file).getDecompiledPsiFile();
- if (file == null) return;
}
+ if (file == null) return null;
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.select.word");
@@ -102,7 +115,7 @@
while (element instanceof PsiWhiteSpace || element != null && StringUtil.isEmptyOrSpaces(element.getText())) {
while (element.getNextSibling() == null) {
- if (element instanceof PsiFile) return;
+ if (element instanceof PsiFile) return null;
final PsiElement parent = element.getParent();
final PsiElement[] children = parent.getChildren();
@@ -116,9 +129,9 @@
}
element = element.getNextSibling();
- if (element == null) return;
+ if (element == null) return null;
TextRange range = element.getTextRange();
- if (range == null) return; // Fix NPE (EA-29110)
+ if (range == null) return null; // Fix NPE (EA-29110)
caretOffset = range.getStartOffset();
}
@@ -153,8 +166,7 @@
}
});
- TextRange range = minimumRange.get();
- editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
+ return minimumRange.get();
}
private static int adjustCaretOffset(@NotNull Editor editor) {
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 4177ee7..d825a62 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/TypedHandler.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.
@@ -31,7 +31,6 @@
import com.intellij.lang.ParserDefinition;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
@@ -79,7 +78,7 @@
}
@Nullable
- public static QuoteHandler getQuoteHandler(@NotNull PsiFile file, Editor editor) {
+ public static QuoteHandler getQuoteHandler(@NotNull PsiFile file, @NotNull Editor editor) {
FileType fileType = getFileType(file, editor);
QuoteHandler quoteHandler = getQuoteHandlerForType(fileType);
if (quoteHandler == null) {
@@ -99,7 +98,7 @@
return quoteHandler;
}
- private static FileType getFileType(PsiFile file, Editor editor) {
+ private static FileType getFileType(@NotNull PsiFile file, @NotNull Editor editor) {
FileType fileType = file.getFileType();
Language language = PsiUtilBase.getLanguageInEditor(editor, file.getProject());
if (language != null && language != PlainTextLanguage.INSTANCE) {
@@ -109,11 +108,11 @@
return fileType;
}
- public static void registerBaseLanguageQuoteHandler(Class<? extends Language> languageClass, QuoteHandler quoteHandler) {
+ public static void registerBaseLanguageQuoteHandler(@NotNull Class<? extends Language> languageClass, @NotNull QuoteHandler quoteHandler) {
ourBaseLanguageQuoteHandlers.put(languageClass, quoteHandler);
}
- public static QuoteHandler getQuoteHandlerForType(final FileType fileType) {
+ public static QuoteHandler getQuoteHandlerForType(@NotNull FileType fileType) {
if (!quoteHandlers.containsKey(fileType)) {
QuoteHandler handler = null;
final QuoteHandlerEP[] handlerEPs = Extensions.getExtensions(QuoteHandlerEP.EP_NAME);
@@ -130,23 +129,16 @@
/** @see QuoteHandlerEP */
@Deprecated
- public static void registerQuoteHandler(FileType fileType, QuoteHandler quoteHandler) {
+ public static void registerQuoteHandler(@NotNull FileType fileType, @NotNull QuoteHandler quoteHandler) {
quoteHandlers.put(fileType, quoteHandler);
}
@Override
public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
- if (project == null || editor.isColumnMode()){
- if (myOriginalHandler != null){
- myOriginalHandler.execute(editor, charTyped, dataContext);
- }
- return;
- }
+ PsiFile file;
- PsiFile file = PsiUtilBase.getPsiFileInEditor(editor, project);
-
- if (file == null){
+ if (project == null || editor.isColumnMode() || (file = PsiUtilBase.getPsiFileInEditor(editor, project)) == null) {
if (myOriginalHandler != null){
myOriginalHandler.execute(editor, charTyped, dataContext);
}
@@ -158,6 +150,7 @@
return;
}
+ Editor originalEditor = editor;
Editor injectedEditor = injectedEditorIfCharTypedIsSignificant(charTyped, editor, file);
if (injectedEditor != editor) {
file = PsiDocumentManager.getInstance(project).getPsiFile(injectedEditor.getDocument());
@@ -181,7 +174,7 @@
}
if (!editor.isInsertMode()){
- myOriginalHandler.execute(editor, charTyped, dataContext);
+ myOriginalHandler.execute(originalEditor, charTyped, dataContext);
return;
}
@@ -213,7 +206,7 @@
}
long modificationStampBeforeTyping = editor.getDocument().getModificationStamp();
- myOriginalHandler.execute(editor, charTyped, dataContext);
+ myOriginalHandler.execute(originalEditor, charTyped, dataContext);
AutoHardWrapHandler.getInstance().wrapLineIfNecessary(editor, dataContext, modificationStampBeforeTyping);
if (('(' == charTyped || '[' == charTyped || '{' == charTyped) &&
@@ -245,19 +238,19 @@
}
}
- private static void autoPopupParameterInfo(Editor editor, char charTyped, Project project, PsiFile file) {
+ private static void autoPopupParameterInfo(@NotNull Editor editor, char charTyped, @NotNull Project project, @NotNull PsiFile file) {
if ((charTyped == '(' || charTyped == ',') && !isInsideStringLiteral(editor, file)) {
AutoPopupController.getInstance(project).autoPopupParameterInfo(editor, null);
}
}
- public static void autoPopupCompletion(Editor editor, char charTyped, Project project, PsiFile file) {
+ public static void autoPopupCompletion(@NotNull Editor editor, char charTyped, @NotNull Project project, @NotNull PsiFile file) {
if (charTyped == '.' || isAutoPopup(editor, file, charTyped)) {
AutoPopupController.getInstance(project).autoPopupMemberLookup(editor, null);
}
}
- private static boolean isAutoPopup(Editor editor, PsiFile file, char charTyped) {
+ private static boolean isAutoPopup(@NotNull Editor editor, @NotNull PsiFile file, char charTyped) {
final int offset = editor.getCaretModel().getOffset() - 1;
if (offset >= 0) {
final PsiElement element = file.findElementAt(offset);
@@ -271,7 +264,7 @@
return false;
}
- private static boolean isInsideStringLiteral(final Editor editor, final PsiFile file) {
+ private static boolean isInsideStringLiteral(@NotNull Editor editor, @NotNull PsiFile file) {
int offset = editor.getCaretModel().getOffset();
PsiElement element = file.findElementAt(offset);
if (element == null) return false;
@@ -296,7 +289,7 @@
}
@NotNull
- static Editor injectedEditorIfCharTypedIsSignificant(final char charTyped, Editor editor, PsiFile oldFile) {
+ static Editor injectedEditorIfCharTypedIsSignificant(final char charTyped, @NotNull Editor editor, @NotNull PsiFile oldFile) {
int offset = editor.getCaretModel().getOffset();
// even for uncommitted document try to retrieve injected fragment that has been there recently
// we are assuming here that when user is (even furiously) typing, injected language would not change
@@ -318,7 +311,7 @@
return editor;
}
- private static void handleAfterLParen(Editor editor, FileType fileType, char lparenChar){
+ private static void handleAfterLParen(@NotNull Editor editor, @NotNull FileType fileType, char lparenChar){
int offset = editor.getCaretModel().getOffset();
HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset);
boolean atEndOfDocument = offset == editor.getDocument().getTextLength();
@@ -373,7 +366,7 @@
}
}
- public static boolean handleRParen(Editor editor, FileType fileType, char charTyped) {
+ public static boolean handleRParen(@NotNull Editor editor, @NotNull FileType fileType, char charTyped) {
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET) return false;
int offset = editor.getCaretModel().getOffset();
@@ -430,7 +423,7 @@
return true;
}
- private boolean handleQuote(Editor editor, char quote, DataContext dataContext, PsiFile file) {
+ private boolean handleQuote(@NotNull Editor editor, char quote, @NotNull DataContext dataContext, @NotNull PsiFile file) {
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_QUOTE) return false;
final QuoteHandler quoteHandler = getQuoteHandler(file, editor);
if (quoteHandler == null) return false;
@@ -488,7 +481,7 @@
return true;
}
- private static boolean isClosingQuote(Editor editor, QuoteHandler quoteHandler, int offset) {
+ private static boolean isClosingQuote(@NotNull Editor editor, @NotNull QuoteHandler quoteHandler, int offset) {
HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(offset);
if (iterator.atEnd()){
LOG.assertTrue(false);
@@ -499,7 +492,7 @@
}
@Nullable
- private static CharSequence getClosingQuote(Editor editor, MultiCharQuoteHandler quoteHandler, int offset) {
+ private static CharSequence getClosingQuote(@NotNull Editor editor, @NotNull MultiCharQuoteHandler quoteHandler, int offset) {
HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(offset);
if (iterator.atEnd()){
LOG.assertTrue(false);
@@ -509,7 +502,7 @@
return quoteHandler.getClosingQuote(iterator, offset);
}
- private static boolean isOpeningQuote(Editor editor, QuoteHandler quoteHandler, int offset) {
+ private static boolean isOpeningQuote(@NotNull Editor editor, @NotNull QuoteHandler quoteHandler, int offset) {
HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(offset);
if (iterator.atEnd()){
LOG.assertTrue(false);
@@ -519,7 +512,7 @@
return quoteHandler.isOpeningQuote(iterator, offset);
}
- private static boolean hasNonClosedLiterals(Editor editor, QuoteHandler quoteHandler, int offset) {
+ private static boolean hasNonClosedLiterals(@NotNull Editor editor, @NotNull QuoteHandler quoteHandler, int offset) {
HighlighterIterator iterator = ((EditorEx) editor).getHighlighter().createIterator(offset);
if (iterator.atEnd()) {
LOG.assertTrue(false);
@@ -529,7 +522,7 @@
return quoteHandler.hasNonClosedLiteral(editor, iterator, offset);
}
- private static boolean isTypingEscapeQuote(Editor editor, QuoteHandler quoteHandler, int offset){
+ private static boolean isTypingEscapeQuote(@NotNull Editor editor, @NotNull QuoteHandler quoteHandler, int offset){
if (offset == 0) return false;
CharSequence chars = editor.getDocument().getCharsSequence();
int offset1 = CharArrayUtil.shiftBackward(chars, offset - 1, "\\");
@@ -537,7 +530,7 @@
return slashCount % 2 != 0 && isInsideLiteral(editor, quoteHandler, offset);
}
- private static boolean isInsideLiteral(Editor editor, QuoteHandler quoteHandler, int offset){
+ private static boolean isInsideLiteral(@NotNull Editor editor, @NotNull QuoteHandler quoteHandler, int offset){
if (offset == 0) return false;
HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(offset - 1);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java
index ab63582..ca3f22f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/UnSelectWordHandler.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.
@@ -19,7 +19,6 @@
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -33,6 +32,7 @@
private final EditorActionHandler myOriginalHandler;
public UnSelectWordHandler(EditorActionHandler originalHandler) {
+ super(true);
myOriginalHandler = originalHandler;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java
index 29b49e5..a5c2a59 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/BaseMoveHandler.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.
@@ -36,6 +36,7 @@
protected final boolean isDown;
public BaseMoveHandler(boolean down) {
+ super(true);
isDown = down;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java
index 34e3ddd..add65b4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/moveUpDown/MoverWrapper.java
@@ -45,6 +45,7 @@
}
public final void move(Editor editor, final PsiFile file) {
+ assert myInfo.toMove2 != null;
myMover.beforeMove(editor, myInfo, myIsDown);
final Document document = editor.getDocument();
final int start = StatementUpDownMover.getLineStartSafeOffset(document, myInfo.toMove.startLine);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java
index 4968512..bbb1e16 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/smartEnter/SmartEnterAction.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,7 +23,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -32,6 +31,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilBase;
+import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -44,7 +44,7 @@
}
@Override
- protected Editor getEditor(final DataContext dataContext) {
+ protected Editor getEditor(@NotNull final DataContext dataContext) {
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
if (editor == null) return null;
Project project = editor.getProject();
@@ -53,6 +53,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, dataContext);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java
index dc5d9f3..d6f17ad 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/wordSelection/NaturalLanguageTextSelectioner.java
@@ -18,6 +18,7 @@
import com.intellij.codeInsight.editorActions.ExtendWordSelectionHandlerBase;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
@@ -38,7 +39,8 @@
@Override
public boolean canSelect(PsiElement e) {
- return e instanceof PsiPlainText || e instanceof PsiComment;
+ return (e instanceof PsiPlainText || e instanceof PsiComment) &&
+ !(e.getContainingFile().getFileType() instanceof CustomSyntaxTableFileType);
}
private static TextRange findParagraphRange(String text, int start, int end) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/AbstractElementSignatureProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/AbstractElementSignatureProvider.java
index f7369df..3aa1d51 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/AbstractElementSignatureProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/AbstractElementSignatureProvider.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,7 +19,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -81,7 +81,7 @@
int index = 0;
for (PsiElement child : children) {
- if (ReflectionCache.isAssignable(hisClass, child.getClass())) {
+ if (ReflectionUtil.isAssignable(hisClass, child.getClass())) {
T namedChild = hisClass.cast(child);
final String childName = namedChild.getName();
@@ -106,7 +106,7 @@
PsiElement[] children = parent.getChildren();
for (PsiElement child : children) {
- if (ReflectionCache.isAssignable(hisClass, child.getClass())) {
+ if (ReflectionUtil.isAssignable(hisClass, child.getClass())) {
T namedChild = hisClass.cast(child);
final String childName = namedChild.getName();
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 0a81531..0e420b0 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
@@ -32,6 +32,7 @@
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.StringTokenizer;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -47,8 +48,8 @@
@NotNull private final Project myProject;
private final VirtualFile myFile;
- @NotNull private final List<SmartPsiElementPointer<PsiElement>> myPsiElements = new ArrayList<SmartPsiElementPointer<PsiElement>>();
- @NotNull private final List<RangeMarker> myRangeMarkers = new ArrayList<RangeMarker>();
+ @NotNull private final List<SmartPsiElementPointer<PsiElement>> myPsiElements = ContainerUtil.createLockFreeCopyOnWriteList();
+ @NotNull private final List<RangeMarker> myRangeMarkers = ContainerUtil.createLockFreeCopyOnWriteList();
private static final String DEFAULT_PLACEHOLDER = "...";
@NonNls private static final String ELEMENT_TAG = "element";
@NonNls private static final String SIGNATURE_ATT = "signature";
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java
index 67ba1af..c27d5ee 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/folding/impl/FoldingUpdate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package com.intellij.codeInsight.folding.impl;
+import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.Language;
@@ -23,6 +24,7 @@
import com.intellij.lang.folding.FoldingDescriptor;
import com.intellij.lang.folding.LanguageFolding;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -34,6 +36,7 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
@@ -206,7 +209,10 @@
" made by " + foldingBuilder +
" for " +language +
" and called on file " + psi +
- " is outside document range: " + docRange);
+ " is outside document range: " + docRange,
+ ApplicationManager.getApplication().isInternal()
+ ? new Attachment[] {AttachmentFactory.createAttachment(document), new Attachment("psiTree.txt", DebugUtil.psiToString(psi, false, true))}
+ : new Attachment[0]);
}
elementsToFoldMap.putValue(descriptor.getElement().getPsi(), descriptor);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java
index 75ae804..ee07d19 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/CommentByLineCommentHandler.java
@@ -483,6 +483,7 @@
}
if (endOffset >= suffix.length() && CharArrayUtil.regionMatches(myDocument.getCharsSequence(), endOffset - suffix.length(), suffix)) {
myDocument.deleteString(endOffset - suffix.length(), endOffset);
+ endOffset = myDocument.getTextLength();
}
if (commentedPrefix != null && commentedSuffix != null) {
CommentByBlockCommentHandler.commentNestedComments(myDocument, new TextRange(startOffset, endOffset), commenter);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternAction.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternAction.java
index 69e0a1e..b82cc2b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternAction.java
@@ -44,7 +44,7 @@
patterns = ArrayUtil.mergeArrays(patterns, extension.getDescriptors());
}
}
- GenerateByPatternDialog dialog = new GenerateByPatternDialog(e.getProject(), patterns, e.getDataContext());
+ GenerateByPatternDialog dialog = new GenerateByPatternDialog(e.getProject(), patterns);
dialog.show();
if (dialog.isOK()) {
dialog.getSelectedDescriptor().actionPerformed(e.getDataContext());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java
index 88ee7d9..abdcf6c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/GenerateByPatternDialog.java
@@ -3,8 +3,7 @@
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.impl.TemplateEditorUtil;
import com.intellij.codeInsight.template.impl.TemplateImpl;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.project.Project;
@@ -31,6 +30,7 @@
*/
public class GenerateByPatternDialog extends DialogWrapper {
+ private final Project myProject;
private JPanel myPanel;
private Splitter mySplitter;
private Tree myTree = new Tree();
@@ -38,8 +38,9 @@
private final MultiMap<String,PatternDescriptor> myMap;
- public GenerateByPatternDialog(Project project, PatternDescriptor[] descriptors, DataContext context) {
+ public GenerateByPatternDialog(Project project, PatternDescriptor[] descriptors) {
super(project);
+ myProject = project;
setTitle("Generate by Pattern");
setOKButtonText("Generate");
@@ -122,19 +123,20 @@
}
private void updateDetails(final PatternDescriptor descriptor) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ new WriteCommandAction.Simple(myProject) {
@Override
- public void run() {
+ protected void run() throws Throwable {
final Template template = descriptor.getTemplate();
if (template instanceof TemplateImpl) {
String text = ((TemplateImpl)template).getString();
myEditor.getDocument().replaceString(0, myEditor.getDocument().getTextLength(), text);
TemplateEditorUtil.setHighlighter(myEditor, ((TemplateImpl)template).getTemplateContext());
- } else {
+ }
+ else {
myEditor.getDocument().replaceString(0, myEditor.getDocument().getTextLength(), "");
}
}
- });
+ }.execute();
}
private DefaultMutableTreeNode createNode(@Nullable PatternDescriptor descriptor) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java
index f4bca9e..be65138 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/generation/surroundWith/SurroundWithHandler.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.
@@ -192,8 +192,10 @@
PsiDocumentManager.getInstance(project).commitAllDocuments();
int col = editor.getCaretModel().getLogicalPosition().column;
int line = editor.getCaretModel().getLogicalPosition().line;
- LogicalPosition pos = new LogicalPosition(0, 0);
- editor.getCaretModel().moveToLogicalPosition(pos);
+ if (!editor.getCaretModel().supportsMultipleCarets()) {
+ LogicalPosition pos = new LogicalPosition(0, 0);
+ editor.getCaretModel().moveToLogicalPosition(pos);
+ }
TextRange range = surrounder.surroundElements(project, editor, elements);
if (TemplateManager.getInstance(project).getActiveTemplate(editor) == null) {
LogicalPosition pos1 = new LogicalPosition(line, col);
@@ -201,6 +203,7 @@
}
if (range != null) {
int offset = range.getStartOffset();
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToOffset(offset);
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java
index b5bbc17..92d74cf 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/BraceHighlightingHandler.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.
@@ -26,8 +26,6 @@
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
-import com.intellij.concurrency.Job;
-import com.intellij.concurrency.JobLauncher;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -115,7 +113,7 @@
}
final int offset = editor.getCaretModel().getOffset();
final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
- JobLauncher.getInstance().submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() {
@@ -123,8 +121,11 @@
public void run() {
final PsiFile injected;
try {
- injected = psiFile == null || psiFile instanceof PsiCompiledElement || isReallyDisposed(editor, project)
- ? null : getInjectedFileIfAny(editor, project, offset, psiFile, alarm);
+ injected = psiFile == null ||
+ psiFile instanceof PsiCompiledElement ||
+ psiFile instanceof PsiBinaryFile ||
+ isReallyDisposed(editor, project)
+ ? null : getInjectedFileIfAny(editor, project, offset, psiFile, alarm);
}
catch (RuntimeException e) {
// Reset processing flag in case of unexpected exception.
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/ChooseOneOrAllRunnable.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/ChooseOneOrAllRunnable.java
index e710a0d..304d147 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/ChooseOneOrAllRunnable.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/ChooseOneOrAllRunnable.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.
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightHandlerBase.java
index 5a8a2ad..62025ce 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightHandlerBase.java
@@ -42,7 +42,7 @@
int lineStartOffset = document.getLineStartOffset(lineNumber);
int lineEndOffset = document.getLineEndOffset(lineNumber);
int lineFragmentEndOffset = Math.min(lineStartOffset + 140, lineEndOffset);
- String lineText = document.getText().substring(lineStartOffset, lineFragmentEndOffset);
+ String lineText = document.getImmutableCharSequence().subSequence(lineStartOffset, lineFragmentEndOffset).toString();
if (lineFragmentEndOffset != lineEndOffset) {
lineText = lineText.trim() + "...";
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java
index 6b94a3f..0576f1d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/highlighting/HighlightUsagesHandler.java
@@ -82,7 +82,7 @@
if (usageTargets == null) {
PsiElement targetElement = getTargetElement(editor, file);
- if (targetElement != null) {
+ if (targetElement != null && targetElement != file) {
if (!(targetElement instanceof NavigationItem)) {
targetElement = targetElement.getNavigationElement();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java
index 74c899e..36395b3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ImplementationViewComponent.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.
@@ -60,10 +60,8 @@
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.*;
import java.util.List;
-import java.util.Set;
public class ImplementationViewComponent extends JPanel {
@NonNls private static final String TEXT_PAGE_KEY = "Text";
@@ -87,7 +85,7 @@
private final ActionToolbar myToolbar;
private JLabel myLabel;
- public void setHint(final JBPopup hint, final String title) {
+ public void setHint(final JBPopup hint, @NotNull String title) {
myHint = hint;
myTitle = title;
}
@@ -173,7 +171,7 @@
toolbarPanel.add(myToolbar.getComponent(), gc);
setPreferredSize(new Dimension(600, 400));
-
+
update(elements, new PairFunction<PsiElement[], List<FileDescriptor>, Boolean>() {
@Override
public Boolean fun(final PsiElement[] psiElements, final List<FileDescriptor> fileDescriptors) {
@@ -273,7 +271,7 @@
@Override
public Boolean fun(PsiElement[] psiElements, List<FileDescriptor> fileDescriptors) {
if (psiElements.length == 0) return false;
-
+
final Project project = psiElements[0].getProject();
myElements = psiElements;
@@ -302,7 +300,7 @@
else {
myFileChooser.setVisible(false);
myCountLabel.setVisible(false);
-
+
VirtualFile file = psiFile.getVirtualFile();
if (file != null) {
myLabel.setIcon(getIconForFile(psiFile));
@@ -321,9 +319,9 @@
return true;
}
});
-
+
}
-
+
private static void update(@NotNull PsiElement[] elements, @NotNull PairFunction<PsiElement[], List<FileDescriptor>, Boolean> fun) {
List<PsiElement> candidates = new ArrayList<PsiElement>(elements.length);
List<FileDescriptor> files = new ArrayList<FileDescriptor>(elements.length);
@@ -333,6 +331,15 @@
names.add(((PsiNamedElement)element).getName());
}
}
+ Arrays.sort(elements, new Comparator<PsiElement>() {
+ @Override
+ public int compare(PsiElement e1, PsiElement e2) {
+ if (e1 instanceof PsiNamedElement && e2 instanceof PsiNamedElement) {
+ return Comparing.compare(((PsiNamedElement)e1).getName(), ((PsiNamedElement)e2).getName());
+ }
+ return e1.hashCode() - e2.hashCode();
+ }
+ });
for (PsiElement element : elements) {
PsiFile file = getContainingFile(element);
if (file == null) continue;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowContainerInfoHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowContainerInfoHandler.java
index b0e1e6c..5ccd71b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowContainerInfoHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowContainerInfoHandler.java
@@ -29,6 +29,7 @@
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.LightweightHint;
import org.jetbrains.annotations.NotNull;
@@ -45,14 +46,12 @@
PsiElement container = null;
WeakReference<LightweightHint> ref = editor.getUserData(MY_LAST_HINT_KEY);
- if (ref != null){
- LightweightHint hint = ref.get();
- if (hint != null && hint.isVisible()){
- hint.hide();
- container = hint.getUserData(CONTAINER_KEY);
- if (container != null && !container.isValid()){
- container = null;
- }
+ LightweightHint hint = SoftReference.dereference(ref);
+ if (hint != null && hint.isVisible()){
+ hint.hide();
+ container = hint.getUserData(CONTAINER_KEY);
+ if (container != null && !container.isValid()){
+ container = null;
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java
index 5f61a84..14e7487 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/ShowParameterInfoContext.java
@@ -110,11 +110,13 @@
showMethodInfo(getProject(), getEditor(), element, getHighlightedElement(), itemsToShow, offset, handler);
}
- private static void showParameterHint(final PsiElement element, final Editor editor, final Object[] descriptors,
- final Project project, final ShowParameterInfoHandler.BestLocationPointProvider provider,
+ private static void showParameterHint(final PsiElement element,
+ final Editor editor,
+ final Object[] descriptors,
+ final Project project,
@Nullable PsiElement highlighted,
- final int elementStart, final ParameterInfoHandler handler
- ) {
+ final int elementStart,
+ final ParameterInfoHandler handler) {
if (ParameterInfoController.isAlreadyShown(editor, elementStart)) return;
if (editor.isDisposed() || !editor.getComponent().isVisible()) return;
@@ -129,6 +131,7 @@
final LightweightHint hint = new LightweightHint(component);
hint.setSelectingHint(true);
final HintManagerImpl hintManager = HintManagerImpl.getInstanceImpl();
+ final ShowParameterInfoHandler.BestLocationPointProvider provider = new MyBestLocationPointProvider(editor);
final Pair<Point, Short> pos = provider.getBestPointPosition(hint, element, elementStart, true, HintManager.UNDER);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -143,6 +146,8 @@
hintHint.setExplicitClose(true);
Editor editorToShow = editor instanceof EditorWindow ? ((EditorWindow)editor).getDelegate() : editor;
+ // is case of injection we need to calculate position for EditorWindow
+ // also we need to show the hint in the main editor because of intention bulb
hintManager.showEditorHint(hint, editorToShow, pos.getFirst(), HintManager.HIDE_BY_ESCAPE | HintManager.UPDATE_BY_SCROLLING, 0, false, hintHint);
new ParameterInfoController(project, editor, elementStart, hint, handler, provider);
}
@@ -156,8 +161,7 @@
int offset,
ParameterInfoHandler handler
) {
- showParameterHint(list, editor, candidates, project, new MyBestLocationPointProvider(editor),
- candidates.length > 1 ? highlighted: null,offset, handler);
+ showParameterHint(list, editor, candidates, project, candidates.length > 1 ? highlighted : null, offset, handler);
}
/**
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java
index f9f3771..77995ac 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java
@@ -44,6 +44,7 @@
import com.intellij.psi.presentation.java.SymbolPresentationUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.popup.AbstractPopup;
import com.intellij.ui.popup.NotLookupOrSearchCondition;
import com.intellij.ui.popup.PopupPositionManager;
@@ -53,6 +54,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import java.lang.ref.WeakReference;
import java.util.*;
@@ -76,10 +78,32 @@
performForContext(e.getDataContext(), true);
}
+ @TestOnly
public void performForContext(DataContext dataContext) {
performForContext(dataContext, true);
}
+ @Override
+ public void update(final AnActionEvent e) {
+ Project project = e.getData(CommonDataKeys.PROJECT);
+ if (project == null) {
+ e.getPresentation().setEnabled(false);
+ return;
+ }
+
+ DataContext dataContext = e.getDataContext();
+ Editor editor = getEditor(dataContext);
+
+ PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
+ PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
+ element = getElement(project, file, editor, element);
+
+ PsiFile containingFile = element != null ? element.getContainingFile() : file;
+ boolean enabled = !(containingFile == null || !containingFile.getViewProvider().isPhysical());
+ e.getPresentation().setEnabled(enabled);
+ }
+
+
protected Editor getEditor(DataContext dataContext) {
Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
@@ -97,13 +121,11 @@
public void performForContext(DataContext dataContext, boolean invokedByShortcut) {
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
- PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
-
if (project == null) return;
-
PsiDocumentManager.getInstance(project).commitAllDocuments();
- final Editor editor = getEditor(dataContext);
+ PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
+ Editor editor = getEditor(dataContext);
PsiElement element = CommonDataKeys.PSI_ELEMENT.getData(dataContext);
boolean isInvokedFromEditor = CommonDataKeys.EDITOR.getData(dataContext) != null;
@@ -161,7 +183,8 @@
TargetElementUtilBase.getInstance().adjustElement(editor, TargetElementUtilBase.getInstance().getAllAccepted(), element, null);
if (adjustedElement != null) {
element = adjustedElement;
- } else if (file != null) {
+ }
+ else if (file != null) {
element = DocumentationManager.getInstance(project).getElementFromLookup(editor, file);
}
}
@@ -226,18 +249,16 @@
final Ref<UsageView> usageView = new Ref<UsageView>();
final String title = CodeInsightBundle.message("implementation.view.title", text);
- if (myPopupRef != null) {
- final JBPopup popup = myPopupRef.get();
- if (popup != null && popup.isVisible() && popup instanceof AbstractPopup) {
- final ImplementationViewComponent component = (ImplementationViewComponent) ((AbstractPopup)popup).getComponent();
- ((AbstractPopup)popup).setCaption(title);
- component.update(impls, index);
- updateInBackground(editor, element, component, title, (AbstractPopup)popup, usageView);
- if (invokedByShortcut) {
- ((AbstractPopup)popup).focusPreferredComponent();
- }
- return;
+ JBPopup popup = SoftReference.dereference(myPopupRef);
+ if (popup != null && popup.isVisible() && popup instanceof AbstractPopup) {
+ final ImplementationViewComponent component = (ImplementationViewComponent) ((AbstractPopup)popup).getComponent();
+ ((AbstractPopup)popup).setCaption(title);
+ component.update(impls, index);
+ updateInBackground(editor, element, component, title, (AbstractPopup)popup, usageView);
+ if (invokedByShortcut) {
+ ((AbstractPopup)popup).focusPreferredComponent();
}
+ return;
}
final ImplementationViewComponent component = new ImplementationViewComponent(impls, index);
@@ -250,7 +271,7 @@
}
};
- final JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component.getPreferredFocusableComponent())
+ popup = JBPopupFactory.getInstance().createComponentPopupBuilder(component, component.getPreferredFocusableComponent())
.setRequestFocusCondition(project, NotLookupOrSearchCondition.INSTANCE)
.setProject(project)
.addListener(updateProcessor)
@@ -284,11 +305,9 @@
ImplementationViewComponent component,
String title,
AbstractPopup popup, Ref<UsageView> usageView) {
- if (myTaskRef != null) {
- final BackgroundUpdaterTask updaterTask = myTaskRef.get();
- if (updaterTask != null) {
- updaterTask.setCanceled();
- }
+ final BackgroundUpdaterTask updaterTask = SoftReference.dereference(myTaskRef);
+ if (updaterTask != null) {
+ updaterTask.setCanceled();
}
if (element == null) return; //already found
@@ -357,12 +376,6 @@
return PsiUtilCore.toPsiElementArray(unique);
}
- @Override
- public void update(final AnActionEvent e) {
- final Project project = e.getData(CommonDataKeys.PROJECT);
- e.getPresentation().setEnabled(project != null);
- }
-
private static class ImplementationsUpdaterTask extends BackgroundUpdaterTask<ImplementationViewComponent> {
private String myCaption;
private Editor myEditor;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/FileLevelIntentionComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/FileLevelIntentionComponent.java
index 03f3ee3..6af5890 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/FileLevelIntentionComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/FileLevelIntentionComponent.java
@@ -32,6 +32,7 @@
import com.intellij.ui.ClickListener;
import com.intellij.ui.EditorNotificationPanel;
import com.intellij.ui.LightColors;
+import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.MouseEvent;
@@ -76,7 +77,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
IntentionListStep step = new IntentionListStep(null, info, editor, psiFile, project);
if (intentions != null && !intentions.isEmpty()) {
HighlightInfo.IntentionActionDescriptor descriptor = intentions.get(0).getFirst();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionActionWithTextCaching.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionActionWithTextCaching.java
index 8a6a19d..2c5b5b3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionActionWithTextCaching.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionActionWithTextCaching.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -31,12 +31,12 @@
*/
class IntentionActionWithTextCaching implements Comparable<IntentionActionWithTextCaching> {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.IntentionActionWithTextCaching");
- private final List<IntentionAction> myOptionIntentions;
- private final List<IntentionAction> myOptionErrorFixes;
+ private final List<IntentionAction> myOptionIntentions = new ArrayList<IntentionAction>();
+ private final List<IntentionAction> myOptionErrorFixes = new ArrayList<IntentionAction>();
+ private final List<IntentionAction> myOptionInspectionFixes = new ArrayList<IntentionAction>();
private final String myText;
private final IntentionAction myAction;
private final String myDisplayName;
- private final List<IntentionAction> myOptionInspectionFixes;
private final Icon myIcon;
IntentionActionWithTextCaching(IntentionAction action){
@@ -49,9 +49,6 @@
private IntentionActionWithTextCaching(IntentionAction action, String displayName, Icon icon) {
myIcon = icon;
- myOptionIntentions = new ArrayList<IntentionAction>();
- myOptionErrorFixes = new ArrayList<IntentionAction>();
- myOptionInspectionFixes = new ArrayList<IntentionAction>();
myText = action.getText();
// needed for checking errors in user written actions
//noinspection ConstantConditions
@@ -65,7 +62,7 @@
}
public void addIntention(final IntentionAction action) {
- myOptionIntentions.add(action);
+ myOptionIntentions.add(action);
}
public void addErrorFix(final IntentionAction action) {
myOptionErrorFixes.add(action);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java
index 57099c8..9db2c7d 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/IntentionListStep.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -92,11 +92,11 @@
//true if something changed
boolean updateActions(@NotNull ShowIntentionsPass.IntentionsInfo intentions) {
- boolean result = wrapActionsTo(intentions.errorFixesToShow, myCachedErrorFixes);
- result &= wrapActionsTo(intentions.inspectionFixesToShow, myCachedInspectionFixes);
- result &= wrapActionsTo(intentions.intentionsToShow, myCachedIntentions);
- result &= wrapActionsTo(intentions.guttersToShow, myCachedGutters);
- return !result;
+ boolean changed = wrapActionsTo(intentions.errorFixesToShow, myCachedErrorFixes);
+ changed |= wrapActionsTo(intentions.inspectionFixesToShow, myCachedInspectionFixes);
+ changed |= wrapActionsTo(intentions.intentionsToShow, myCachedIntentions);
+ changed |= wrapActionsTo(intentions.guttersToShow, myCachedGutters);
+ return changed;
}
private boolean wrapActionsTo(@NotNull List<HighlightInfo.IntentionActionDescriptor> newDescriptors,
@@ -129,14 +129,14 @@
injectedEditor = InjectedLanguageUtil.getInjectedEditorForInjectedFile(myEditor, injectedFile);
}
- boolean result = true;
+ boolean changed = false;
for (Iterator<IntentionActionWithTextCaching> iterator = cachedActions.iterator(); iterator.hasNext();) {
IntentionActionWithTextCaching cachedAction = iterator.next();
IntentionAction action = cachedAction.getAction();
if (!ShowIntentionActionsHandler.availableFor(myFile, myEditor, action)
&& (hostElement == element || element != null && !ShowIntentionActionsHandler.availableFor(injectedFile, injectedEditor, action))) {
iterator.remove();
- result = false;
+ changed = true;
}
}
@@ -146,12 +146,12 @@
if (element != null && element != hostElement && ShowIntentionActionsHandler.availableFor(injectedFile, injectedEditor, action)) {
IntentionActionWithTextCaching cachedAction = wrapAction(descriptor, element, injectedFile, injectedEditor);
wrappedNew.add(cachedAction);
- result &= !cachedActions.add(cachedAction);
+ changed |= cachedActions.add(cachedAction);
}
else if (hostElement != null && ShowIntentionActionsHandler.availableFor(myFile, myEditor, action)) {
IntentionActionWithTextCaching cachedAction = wrapAction(descriptor, hostElement, myFile, myEditor);
wrappedNew.add(cachedAction);
- result &= !cachedActions.add(cachedAction);
+ changed |= cachedActions.add(cachedAction);
}
}
for (Iterator<IntentionActionWithTextCaching> iterator = cachedActions.iterator(); iterator.hasNext();) {
@@ -159,12 +159,13 @@
if (!wrappedNew.contains(cachedAction)) {
// action disappeared
iterator.remove();
- result = false;
+ changed = true;
}
}
- return result;
+ return changed;
}
+ @NotNull
IntentionActionWithTextCaching wrapAction(@NotNull HighlightInfo.IntentionActionDescriptor descriptor,
@NotNull PsiElement element,
@NotNull PsiFile containingFile,
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionDescriptionPanel.java b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionDescriptionPanel.java
index 07408d1..ff829c8 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionDescriptionPanel.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/intention/impl/config/IntentionDescriptionPanel.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.
@@ -35,6 +35,7 @@
import com.intellij.openapi.project.ProjectManager;
import com.intellij.ui.HyperlinkLabel;
import com.intellij.ui.TitledSeparator;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -91,7 +92,7 @@
PluginId pluginId = actionMetaData == null ? null : actionMetaData.getPluginId();
JComponent owner;
if (pluginId == null) {
- @NonNls String label = "<html><body><b>" + ApplicationNamesInfo.getInstance().getFullProductName() + "</b></body></html>";
+ @NonNls String label = XmlStringUtil.wrapInHtml("<b>" + ApplicationNamesInfo.getInstance().getFullProductName() + "</b>");
owner = new JLabel(label);
}
else {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java
index fc79842..456b4d0 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/Advertiser.java
@@ -78,7 +78,7 @@
myNextLabel.setForeground(JBColor.blue);
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
myCurrentItem++;
updateAdvertisements();
return true;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java
index 77ad6a2..dffe186 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/BackspaceHandler.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.codeInsight.completion.impl.CompletionServiceImpl;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -31,10 +32,10 @@
}
@Override
- public void execute(final Editor editor, final DataContext dataContext){
+ public void execute(final Editor editor, Caret caret, final DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup == null){
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
return;
}
@@ -44,15 +45,19 @@
hideOffset = originalStart - 1;
}
- truncatePrefix(dataContext, lookup, myOriginalHandler, hideOffset);
+ truncatePrefix(dataContext, lookup, myOriginalHandler, hideOffset, caret);
}
- static void truncatePrefix(final DataContext dataContext, LookupImpl lookup, final EditorActionHandler handler, final int hideOffset) {
+ static void truncatePrefix(final DataContext dataContext,
+ LookupImpl lookup,
+ final EditorActionHandler handler,
+ final int hideOffset,
+ final Caret caret) {
final Editor editor = lookup.getEditor();
if (!lookup.performGuardedChange(new Runnable() {
@Override
public void run() {
- handler.execute(editor, dataContext);
+ handler.executeInCaretContext(editor, caret, dataContext);
}
})) {
return;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java
index 7c947ee..37c8970 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/EndHandler.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,7 @@
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.ui.ListScrollingUtil;
@@ -30,10 +31,10 @@
}
@Override
- public void execute(Editor editor, DataContext dataContext){
+ public void execute(Editor editor, Caret caret, DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup == null || !lookup.isFocused()) {
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
return;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java
index 781d17d..33c67db 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/HomeHandler.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,7 @@
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.ui.ListScrollingUtil;
@@ -30,10 +31,10 @@
}
@Override
- public void execute(Editor editor, DataContext dataContext){
+ public void execute(Editor editor, Caret caret, DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup == null || !lookup.isFocused()) {
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
return;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java
index 79838c5..4048b18 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupActionHandler.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,11 +25,13 @@
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.ui.ListScrollingUtil;
+import org.jetbrains.annotations.Nullable;
/**
* @author yole
@@ -49,22 +51,22 @@
}
@Override
- public void execute(Editor editor, DataContext dataContext){
+ public void execute(Editor editor, Caret caret, DataContext dataContext){
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(editor);
if (lookup == null || !lookup.isAvailableToUser() || myRequireFocusedLookup && !lookup.isFocused()) {
Project project = editor.getProject();
if (project != null) {
LookupManager.getInstance(project).hideActiveLookup();
}
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
return;
}
lookup.markSelectionTouched();
- executeInLookup(lookup, dataContext);
+ executeInLookup(lookup, dataContext, caret);
}
- protected abstract void executeInLookup(LookupImpl lookup, DataContext context);
+ protected abstract void executeInLookup(LookupImpl lookup, DataContext context, @Nullable Caret caret);
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
@@ -97,7 +99,7 @@
}
@Override
- protected void executeInLookup(final LookupImpl lookup, DataContext context) {
+ protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) {
executeUpOrDown(lookup, false);
}
@@ -145,9 +147,9 @@
}
@Override
- protected void executeInLookup(final LookupImpl lookup, DataContext context) {
+ protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) {
if (!UISettings.getInstance().CYCLE_SCROLLING && !lookup.isFocused() && lookup.getList().getSelectedIndex() == 0) {
- myOriginalHandler.execute(lookup.getEditor(), context);
+ myOriginalHandler.executeInCaretContext(lookup.getEditor(), caret, context);
return;
}
executeUpOrDown(lookup, true);
@@ -161,7 +163,7 @@
}
@Override
- protected void executeInLookup(final LookupImpl lookup, DataContext context) {
+ protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) {
lookup.setFocusDegree(LookupImpl.FocusDegree.FOCUSED);
ListScrollingUtil.movePageDown(lookup.getList());
}
@@ -173,7 +175,7 @@
}
@Override
- protected void executeInLookup(final LookupImpl lookup, DataContext context) {
+ protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) {
lookup.setFocusDegree(LookupImpl.FocusDegree.FOCUSED);
ListScrollingUtil.movePageUp(lookup.getList());
}
@@ -185,9 +187,9 @@
}
@Override
- protected void executeInLookup(final LookupImpl lookup, DataContext context) {
+ protected void executeInLookup(final LookupImpl lookup, DataContext context, Caret caret) {
if (!lookup.isCompletion()) {
- myOriginalHandler.execute(lookup.getEditor(), context);
+ myOriginalHandler.executeInCaretContext(lookup.getEditor(), caret, context);
return;
}
@@ -200,7 +202,7 @@
return;
}
- BackspaceHandler.truncatePrefix(context, lookup, myOriginalHandler, lookup.getLookupStart() - 1);
+ BackspaceHandler.truncatePrefix(context, lookup, myOriginalHandler, lookup.getLookupStart() - 1, caret);
}
}
public static class RightHandler extends LookupActionHandler {
@@ -209,12 +211,12 @@
}
@Override
- protected void executeInLookup(LookupImpl lookup, DataContext context) {
+ protected void executeInLookup(LookupImpl lookup, DataContext context, Caret caret) {
final Editor editor = lookup.getEditor();
final int offset = editor.getCaretModel().getOffset();
CharSequence seq = editor.getDocument().getCharsSequence();
if (seq.length() <= offset || !lookup.isCompletion()) {
- myOriginalHandler.execute(editor, context);
+ myOriginalHandler.executeInCaretContext(editor, caret, context);
return;
}
@@ -222,7 +224,7 @@
CharFilter.Result lookupAction = LookupTypedHandler.getLookupAction(c, lookup);
if (lookupAction != CharFilter.Result.ADD_TO_PREFIX || Character.isWhitespace(c)) {
- myOriginalHandler.execute(editor, context);
+ myOriginalHandler.executeInCaretContext(editor, caret, context);
return;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
index 3585709..87975c2 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/LookupCellRenderer.java
@@ -460,7 +460,7 @@
}
@Override
- protected void applyAdditionalHints(Graphics g) {
+ protected void applyAdditionalHints(@NotNull Graphics g) {
GraphicsUtil.setupAntialiasing(g);
}
}
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 99b47b7..b921550 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
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -34,10 +34,8 @@
import com.intellij.lang.LangBundle;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
@@ -654,13 +652,17 @@
}
myFinishing = true;
- AccessToken token = WriteAction.start();
- try {
- insertLookupString(item, getPrefixLength(item));
- }
- finally {
- token.finish();
- }
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ public void run() {
+ myEditor.getDocument().startGuardedBlockChecking();
+ try {
+ insertLookupString(item, getPrefixLength(item));
+ }
+ finally {
+ myEditor.getDocument().stopGuardedBlockChecking();
+ }
+ }
+ });
if (myDisposed) { // any document listeners could close us
return;
@@ -772,12 +774,14 @@
checkValid();
assert !myChangeGuard : "already in change";
+ myEditor.getDocument().startGuardedBlockChecking();
myChangeGuard = true;
boolean result;
try {
result = myOffsets.performGuardedChange(change, debug);
}
finally {
+ myEditor.getDocument().stopGuardedBlockChecking();
myChangeGuard = false;
}
if (!result || myDisposed) {
@@ -932,7 +936,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
setFocusDegree(FocusDegree.FOCUSED);
markSelectionTouched();
@@ -1520,7 +1524,7 @@
private class ChangeLookupSorting extends ClickListener {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
DataContext context = DataManager.getInstance().getDataContext(mySortingLabel);
DefaultActionGroup group = new DefaultActionGroup();
group.add(createSortingAction(true));
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemAction.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemAction.java
index 9656cfe..cbcdb40 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/actions/ChooseItemAction.java
@@ -124,6 +124,7 @@
if (customLiveTemplate instanceof CustomLiveTemplateBase) {
final int offset = editor.getCaretModel().getOffset();
if (customLiveTemplate.getShortcut() == shortcutChar
+ && TemplateManagerImpl.isApplicable(customLiveTemplate, editor, file)
&& ((CustomLiveTemplateBase)customLiveTemplate).hasCompletionItem(file, offset)) {
return customLiveTemplate.computeTemplateKey(callback) != null;
}
@@ -149,7 +150,7 @@
return false;
}
- return TemplateSettings.getInstance().getShortcutChar(liveTemplateLookup.getTemplate()) == shortcutChar;
+ return liveTemplateLookup.getTemplateShortcut() == shortcutChar;
}
public static class Always extends ChooseItemAction {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/AbstractDocumentationTooltipAction.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/AbstractDocumentationTooltipAction.java
index 713b434..c0a4780 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/AbstractDocumentationTooltipAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/AbstractDocumentationTooltipAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
+import com.intellij.reference.SoftReference;
import com.intellij.util.PatchedWeakReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -64,19 +65,11 @@
@Nullable
private Pair<PsiElement/* doc anchor */, PsiElement /* original element */> getDocInfo() {
- WeakReference<PsiElement> docAnchorRef = myDocAnchor;
- if (docAnchorRef == null) {
- return null;
- }
- PsiElement docAnchor = docAnchorRef.get();
+ PsiElement docAnchor = SoftReference.dereference(myDocAnchor);
if (docAnchor == null) {
return null;
}
- WeakReference<PsiElement> originalElementRef = myOriginalElement;
- if (originalElementRef == null) {
- return null;
- }
- PsiElement originalElement = originalElementRef.get();
+ PsiElement originalElement = SoftReference.dereference(myOriginalElement);
if (originalElement == null) {
return null;
}
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 b16cfe8..fd433b9 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/CtrlMouseHandler.java
@@ -56,7 +56,10 @@
import com.intellij.openapi.fileEditor.FileEditorManagerListener;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
+import com.intellij.openapi.progress.util.ReadTask;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.IndexNotReadyException;
@@ -728,21 +731,23 @@
private final LogicalPosition myPosition;
private BrowseMode myBrowseMode;
private boolean myDisposed;
+ private final ProgressIndicator myProgress = new ProgressIndicatorBase();
- public TooltipProvider(Editor editor, LogicalPosition pos) {
+ TooltipProvider(Editor editor, LogicalPosition pos) {
myEditor = editor;
myPosition = pos;
}
- public void dispose() {
+ void dispose() {
myDisposed = true;
+ myProgress.cancel();
}
public BrowseMode getBrowseMode() {
return myBrowseMode;
}
- public void execute(BrowseMode browseMode) {
+ void execute(BrowseMode browseMode) {
myBrowseMode = browseMode;
Document document = myEditor.getDocument();
@@ -760,15 +765,15 @@
int selEnd = myEditor.getSelectionModel().getSelectionEnd();
if (offset >= selStart && offset < selEnd) return;
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+
+ ProgressIndicatorUtils.scheduleWithWriteActionPriority(myProgress, new ReadTask() {
@Override
- public void run() {
- ProgressIndicatorUtils.runWithWriteActionPriority(new Runnable() {
- @Override
- public void run() {
- doExecute(file, offset);
- }
- });
+ public void computeInReadAction(@NotNull ProgressIndicator indicator) {
+ doExecute(file, offset);
+ }
+
+ @Override
+ public void onCanceled(@NotNull ProgressIndicator indicator) {
}
});
}
@@ -784,7 +789,7 @@
}
if (info == null) return;
- SwingUtilities.invokeLater(new Runnable() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
if (myDisposed || myEditor.isDisposed() || !myEditor.getComponent().isShowing()) return;
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 ef185d8..36e5d29 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/IncrementalSearchHandler.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.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
@@ -387,10 +388,10 @@
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void execute(Editor editor, Caret caret, DataContext dataContext) {
PerEditorSearchData data = editor.getUserData(SEARCH_DATA_IN_EDITOR_VIEW_KEY);
if (data == null || data.hint == null){
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
}
else{
LightweightHint hint = data.hint;
@@ -413,10 +414,10 @@
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void execute(Editor editor, Caret caret, DataContext dataContext) {
PerEditorSearchData data = editor.getUserData(SEARCH_DATA_IN_EDITOR_VIEW_KEY);
if (data == null || data.hint == null){
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
}
else{
LightweightHint hint = data.hint;
@@ -446,10 +447,10 @@
}
@Override
- public void execute(Editor editor, DataContext dataContext) {
+ public void execute(Editor editor, Caret caret, DataContext dataContext) {
PerEditorSearchData data = editor.getUserData(SEARCH_DATA_IN_EDITOR_VIEW_KEY);
if (data == null || data.hint == null){
- myOriginalHandler.execute(editor, dataContext);
+ myOriginalHandler.executeInCaretContext(editor, caret, dataContext);
}
else{
LightweightHint hint = data.hint;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodDownHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodDownHandler.java
index 2083cdf..80d329f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodDownHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodDownHandler.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,6 +40,7 @@
if (offset > caretOffset) {
int line = editor.offsetToLogicalPosition(offset).line;
if (line > caretLine) {
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToOffset(offset);
editor.getSelectionModel().removeSelection();
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER_DOWN);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpHandler.java
index eb4d85b..cabc87c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/MethodUpHandler.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,6 +41,7 @@
if (offset < caretOffset){
int line = editor.offsetToLogicalPosition(offset).line;
if (line < caretLine){
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToOffset(offset);
editor.getSelectionModel().removeSelection();
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER_UP);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
index 0025cdf..ea6f810 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/NavigationUtil.java
@@ -142,7 +142,9 @@
}
if (openAsNative || !activatePsiElementIfOpen(element, searchForOpen, requestFocus)) {
- ((NavigationItem)element).navigate(requestFocus);
+ final NavigationItem navigationItem = (NavigationItem)element;
+ if (!navigationItem.canNavigate()) return false;
+ navigationItem.navigate(requestFocus);
return true;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java
index 0a25d16..a6d4589 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationAction.java
@@ -32,6 +32,7 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
+import com.intellij.openapi.extensions.ExtensionException;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.DumbService;
@@ -199,8 +200,8 @@
if (file == null) {
return null;
}
- PsiElement elementAt = file.findElementAt(TargetElementUtilBase.adjustOffset(file, document, offset));
+ PsiElement elementAt = file.findElementAt(TargetElementUtilBase.adjustOffset(file, document, offset));
for (GotoDeclarationHandler handler : Extensions.getExtensions(GotoDeclarationHandler.EP_NAME)) {
try {
PsiElement[] result = handler.getGotoDeclarationTargets(elementAt, offset, editor);
@@ -215,7 +216,7 @@
}
}
catch (AbstractMethodError e) {
- LOG.error(handler.toString(), e);
+ LOG.error(new ExtensionException(handler.getClass()));
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandler.java
index aaadb90..9a616bd 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.codeInsight.navigation.actions;
import com.intellij.openapi.actionSystem.DataContext;
@@ -31,18 +30,18 @@
/**
* Provides an array of target declarations for given {@code sourceElement}.
*
- *
- * @param sourceElement input psiElement
- * @param offset offset in the file
- *@param editor @return all target declarations as an array of {@code PsiElement} or null if none was found
+ * @param sourceElement input PSI element
+ * @param offset offset in the file
+ * @param editor @return all target declarations as an array of {@code PsiElement} or null if none was found
*/
@Nullable
- PsiElement[] getGotoDeclarationTargets(PsiElement sourceElement, int offset, Editor editor);
+ PsiElement[] getGotoDeclarationTargets(@Nullable PsiElement sourceElement, int offset, Editor editor);
/**
- * Provides the custom action text
- * @return the custom text or null to use the default text
+ * Provides the custom action text.
+ *
* @param context the action data context
+ * @return the custom text or null to use the default text
*/
@Nullable
String getActionText(DataContext context);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandlerBase.java b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandlerBase.java
index 0fdff17..038bd71 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/navigation/actions/GotoDeclarationHandlerBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -26,13 +26,13 @@
public abstract class GotoDeclarationHandlerBase implements GotoDeclarationHandler {
@Nullable
@Override
- public PsiElement[] getGotoDeclarationTargets(PsiElement sourceElement, int offset, Editor editor) {
+ public PsiElement[] getGotoDeclarationTargets(@Nullable PsiElement sourceElement, int offset, Editor editor) {
final PsiElement target = getGotoDeclarationTarget(sourceElement, editor);
- return target != null ? new PsiElement[] {target} : null;
+ return target != null ? new PsiElement[]{target} : null;
}
@Nullable
- public abstract PsiElement getGotoDeclarationTarget(PsiElement sourceElement, Editor editor);
+ public abstract PsiElement getGotoDeclarationTarget(@Nullable PsiElement sourceElement, Editor editor);
@Override
public String getActionText(DataContext context) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/preview/ImageOrColorPreviewManager.java b/platform/lang-impl/src/com/intellij/codeInsight/preview/ImageOrColorPreviewManager.java
index 2336a9c..5c023da 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/preview/ImageOrColorPreviewManager.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/preview/ImageOrColorPreviewManager.java
@@ -33,6 +33,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.reference.SoftReference;
import com.intellij.util.Alarm;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -69,8 +70,9 @@
return;
}
- KeyListener keyListener = editor.getUserData(EDITOR_LISTENER_ADDED);
+ KeyListener keyListener = EDITOR_LISTENER_ADDED.get(editor);
if (keyListener != null) {
+ EDITOR_LISTENER_ADDED.set(editor, null);
editor.getContentComponent().removeKeyListener(keyListener);
editor.removeEditorMouseMotionListener(ImageOrColorPreviewManager.this);
}
@@ -111,7 +113,7 @@
};
editor.getContentComponent().addKeyListener(keyListener);
- editor.putUserData(EDITOR_LISTENER_ADDED, keyListener);
+ EDITOR_LISTENER_ADDED.set(editor, keyListener);
}
private static boolean isSupportedFile(PsiFile psiFile) {
@@ -160,15 +162,17 @@
if (elementRef == null && event.getMouseEvent().isShiftDown()) {
alarm.addRequest(new PreviewRequest(point, editor, false), 100);
}
- else if (elementRef != null && elementRef.get() != getPsiElementAt(point, editor)) {
- PsiElement element = elementRef.get();
- elementRef = null;
- for (ElementPreviewProvider provider : Extensions.getExtensions(ElementPreviewProvider.EP_NAME)) {
- try {
- provider.hide(element, editor);
- }
- catch (Exception e) {
- LOG.error(e);
+ else {
+ PsiElement element = SoftReference.dereference(elementRef);
+ if (element != getPsiElementAt(point, editor)) {
+ elementRef = null;
+ for (ElementPreviewProvider provider : Extensions.getExtensions(ElementPreviewProvider.EP_NAME)) {
+ try {
+ provider.hide(element, editor);
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
}
}
}
@@ -193,7 +197,7 @@
@Override
public void run() {
PsiElement element = getPsiElementAt(point, editor);
- if (element == null || !element.isValid() || (elementRef != null && elementRef.get() == element)) {
+ if (element == null || !element.isValid() || SoftReference.dereference(elementRef) == element) {
return;
}
if (PsiDocumentManager.getInstance(element.getProject()).isUncommited(editor.getDocument()) || DumbService.getInstance(element.getProject()).isDumb()) {
@@ -201,7 +205,7 @@
}
elementRef = new WeakReference<PsiElement>(element);
- for (ElementPreviewProvider provider : Extensions.getExtensions(ElementPreviewProvider.EP_NAME)) {
+ for (ElementPreviewProvider provider : ElementPreviewProvider.EP_NAME.getExtensions()) {
try {
provider.show(element, editor, point, keyTriggered);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/preview/ImagePreviewComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/preview/ImagePreviewComponent.java
index 3baa777..ca3e581 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/preview/ImagePreviewComponent.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/preview/ImagePreviewComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -103,7 +103,7 @@
private static boolean refresh(@NotNull VirtualFile file) throws IOException {
Long loadedTimeStamp = file.getUserData(TIMESTAMP_KEY);
SoftReference<BufferedImage> imageRef = file.getUserData(BUFFERED_IMAGE_REF_KEY);
- if (loadedTimeStamp == null || loadedTimeStamp < file.getTimeStamp() || imageRef == null || imageRef.get() == null) {
+ if (loadedTimeStamp == null || loadedTimeStamp < file.getTimeStamp() || SoftReference.dereference(imageRef) == null) {
try {
final byte[] content = file.contentsToByteArray();
InputStream inputStream = new ByteArrayInputStream(content, 0, content.length);
@@ -153,11 +153,9 @@
try {
refresh(file);
SoftReference<BufferedImage> imageRef = file.getUserData(BUFFERED_IMAGE_REF_KEY);
- if (imageRef != null) {
- final BufferedImage image = imageRef.get();
- if (image != null) {
- return new ImagePreviewComponent(image, file.getLength());
- }
+ final BufferedImage image = SoftReference.dereference(imageRef);
+ if (image != null) {
+ return new ImagePreviewComponent(image, file.getLength());
}
}
catch (IOException ignored) {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplate.java b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplate.java
index 77a3370..354c999 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplate.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplate.java
@@ -33,9 +33,9 @@
boolean supportsWrapping();
- void expand(String key, @NotNull CustomTemplateCallback callback);
+ void expand(@NotNull String key, @NotNull CustomTemplateCallback callback);
- void wrap(String selection, @NotNull CustomTemplateCallback callback);
+ void wrap(@NotNull String selection, @NotNull CustomTemplateCallback callback);
@NotNull
String getTitle();
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplateBase.java b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplateBase.java
index e542ebf..b9c3f2f 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplateBase.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomLiveTemplateBase.java
@@ -15,8 +15,14 @@
*/
package com.intellij.codeInsight.template;
+import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
+import com.intellij.openapi.editor.Editor;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.Collections;
abstract public class CustomLiveTemplateBase implements CustomLiveTemplate {
/**
@@ -26,4 +32,17 @@
public boolean hasCompletionItem(@NotNull PsiFile file, int offset) {
return false;
}
+
+ /**
+ * Return lookup elements for popup that appears on ListTemplateAction (Ctrl + J)
+ */
+ @NotNull
+ public Collection<? extends CustomLiveTemplateLookupElement> getLookupElements(@NotNull PsiFile file, @NotNull Editor editor, int offset) {
+ return Collections.emptyList();
+ }
+
+ @Nullable
+ public String computeTemplateKeyWithoutContextChecking(@NotNull CustomTemplateCallback callback) {
+ return computeTemplateKey(callback);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java
index 8c583ca..f962585 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/CustomTemplateCallback.java
@@ -47,7 +47,7 @@
private FileType myFileType;
- public CustomTemplateCallback(Editor editor, PsiFile file, boolean wrapping) {
+ public CustomTemplateCallback(@NotNull Editor editor, @NotNull PsiFile file, boolean wrapping) {
myProject = file.getProject();
myTemplateManager = TemplateManager.getInstance(myProject);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java
index 26d4652..5b29b04 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/TemplateBuilderImpl.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.
@@ -279,7 +279,7 @@
public void run() {
final Project project = myFile.getProject();
VirtualFile file = myFile.getVirtualFile();
- assert file != null;
+ assert file != null: "Virtual file is null for " + myFile;
OpenFileDescriptor descriptor = new OpenFileDescriptor(project, file);
final Editor editor = FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/CustomLiveTemplateLookupElement.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/CustomLiveTemplateLookupElement.java
new file mode 100644
index 0000000..c6065c2
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/CustomLiveTemplateLookupElement.java
@@ -0,0 +1,69 @@
+/*
+ * 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.codeInsight.template.impl;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.template.CustomLiveTemplateBase;
+import com.intellij.codeInsight.template.CustomTemplateCallback;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class CustomLiveTemplateLookupElement extends LiveTemplateLookupElement {
+ @NotNull private final CustomLiveTemplateBase myCustomLiveTemplate;
+
+ @NotNull private final String myTemplateKey;
+ @NotNull private final String myItemText;
+
+ public CustomLiveTemplateLookupElement(@NotNull CustomLiveTemplateBase customLiveTemplate,
+ @NotNull String templateKey,
+ @NotNull String itemText,
+ @Nullable String description,
+ boolean sudden,
+ boolean worthShowingInAutoPopup) {
+ super(templateKey, description, sudden, worthShowingInAutoPopup);
+ myCustomLiveTemplate = customLiveTemplate;
+ myTemplateKey = templateKey;
+ myItemText = itemText;
+ }
+
+ @NotNull
+ @Override
+ protected String getItemText() {
+ return myItemText;
+ }
+
+ @NotNull
+ public CustomLiveTemplateBase getCustomLiveTemplate() {
+ return myCustomLiveTemplate;
+ }
+
+ @Override
+ public char getTemplateShortcut() {
+ return myCustomLiveTemplate.getShortcut();
+ }
+
+ @Override
+ public void handleInsert(InsertionContext context) {
+ context.setAddCompletionChar(false);
+ expandTemplate(context.getEditor(), context.getFile());
+ }
+
+ public void expandTemplate(@NotNull Editor editor, @NotNull PsiFile file) {
+ myCustomLiveTemplate.expand(myTemplateKey, new CustomTemplateCallback(editor, file, false));
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java
index 50b14c4..887dca4 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/ListTemplatesHandler.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,9 @@
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
+import com.intellij.codeInsight.template.CustomLiveTemplate;
+import com.intellij.codeInsight.template.CustomLiveTemplateBase;
+import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.application.Result;
@@ -36,6 +39,7 @@
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -61,18 +65,20 @@
final Pattern prefixSearchPattern = Pattern.compile(".*\\b" + prefixWithoutDots + ".*");
for (TemplateImpl template : applicableTemplates) {
final String templateDescription = template.getDescription();
- if (template.getKey().startsWith(prefix) ||
+ if (template.getKey().startsWith(prefix) ||
!prefixWithoutDots.isEmpty() && templateDescription != null && prefixSearchPattern.matcher(templateDescription).matches()) {
matchingTemplates.add(template);
}
}
+ MultiMap<String,CustomLiveTemplateLookupElement> customTemplatesLookupElements = listApplicableCustomTemplates(editor, file, offset);
+
if (matchingTemplates.isEmpty()) {
matchingTemplates.addAll(applicableTemplates);
prefixWithoutDots = "";
}
- if (matchingTemplates.size() == 0) {
+ if (matchingTemplates.isEmpty() && customTemplatesLookupElements.isEmpty()) {
String text = prefixWithoutDots.length() == 0
? CodeInsightBundle.message("templates.no.defined")
: CodeInsightBundle.message("templates.no.defined.with.prefix", prefix);
@@ -81,23 +87,47 @@
}
Collections.sort(matchingTemplates, TemplateListPanel.TEMPLATE_COMPARATOR);
- showTemplatesLookup(project, editor, prefixWithoutDots, matchingTemplates);
+ showTemplatesLookup(project, editor, file, prefixWithoutDots, matchingTemplates, customTemplatesLookupElements);
}
- public static void showTemplatesLookup(final Project project, final Editor editor,
- @NotNull String prefix, List<TemplateImpl> matchingTemplates) {
+ private static void showTemplatesLookup(final Project project,
+ final Editor editor,
+ final PsiFile file,
+ @NotNull String prefix,
+ @NotNull List<TemplateImpl> matchingTemplates,
+ @NotNull MultiMap<String, CustomLiveTemplateLookupElement> customTemplatesLookupElements) {
final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, LookupElement.EMPTY_ARRAY, prefix,
new TemplatesArranger());
for (TemplateImpl template : matchingTemplates) {
lookup.addItem(createTemplateElement(template), new PlainPrefixMatcher(prefix));
}
-
- showLookup(lookup, null);
+
+ for (Map.Entry<String, Collection<CustomLiveTemplateLookupElement>> entry : customTemplatesLookupElements.entrySet()) {
+ for (CustomLiveTemplateLookupElement lookupElement : entry.getValue()) {
+ lookup.addItem(lookupElement, new PlainPrefixMatcher(entry.getKey()));
+ }
+ }
+
+ showLookup(lookup, file);
+ }
+
+ public static MultiMap<String, CustomLiveTemplateLookupElement> listApplicableCustomTemplates(@NotNull Editor editor, @NotNull PsiFile file, int offset) {
+ final MultiMap<String, CustomLiveTemplateLookupElement> result = MultiMap.create();
+ CustomTemplateCallback customTemplateCallback = new CustomTemplateCallback(editor, file, false);
+ for (CustomLiveTemplate customLiveTemplate : CustomLiveTemplate.EP_NAME.getExtensions()) {
+ if (customLiveTemplate instanceof CustomLiveTemplateBase && TemplateManagerImpl.isApplicable(customLiveTemplate, editor, file)) {
+ String customTemplatePrefix = ((CustomLiveTemplateBase)customLiveTemplate).computeTemplateKeyWithoutContextChecking(customTemplateCallback);
+ if (customTemplatePrefix != null) {
+ result.putValues(customTemplatePrefix, ((CustomLiveTemplateBase)customLiveTemplate).getLookupElements(file, editor, offset));
+ }
+ }
+ }
+ return result;
}
private static LiveTemplateLookupElement createTemplateElement(final TemplateImpl template) {
- return new LiveTemplateLookupElement(template, false) {
+ return new LiveTemplateLookupElementImpl(template, false) {
@Override
public Set<String> getAllLookupStrings() {
String description = template.getDescription();
@@ -139,6 +169,14 @@
lookup.showLookup();
}
+ private static void showLookup(LookupImpl lookup, @NotNull PsiFile file) {
+ Editor editor = lookup.getEditor();
+ Project project = editor.getProject();
+ lookup.addLookupListener(new MyLookupAdapter(project, editor, file));
+ lookup.refreshUi(false, true);
+ lookup.showLookup();
+ }
+
@Override
public boolean startInWriteAction() {
return true;
@@ -160,27 +198,46 @@
private final Project myProject;
private final Editor myEditor;
private final Map<TemplateImpl, String> myTemplate2Argument;
+ private final PsiFile myFile;
- public MyLookupAdapter(Project project, Editor editor, Map<TemplateImpl, String> template2Argument) {
+ public MyLookupAdapter(Project project, Editor editor, @Nullable Map<TemplateImpl, String> template2Argument) {
myProject = project;
myEditor = editor;
myTemplate2Argument = template2Argument;
+ myFile = null;
+ }
+
+ public MyLookupAdapter(Project project, Editor editor, @Nullable PsiFile file) {
+ myProject = project;
+ myEditor = editor;
+ myTemplate2Argument = null;
+ myFile = file;
}
@Override
- public void itemSelected(LookupEvent event) {
+ public void itemSelected(final LookupEvent event) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.liveTemplates");
- LookupElement item = event.getItem();
- if (item instanceof LiveTemplateLookupElement) {
- final TemplateImpl template = ((LiveTemplateLookupElement)item).getTemplate();
+ final LookupElement item = event.getItem();
+ if (item instanceof LiveTemplateLookupElementImpl) {
+ final TemplateImpl template = ((LiveTemplateLookupElementImpl)item).getTemplate();
final String argument = myTemplate2Argument != null ? myTemplate2Argument.get(template) : null;
new WriteCommandAction(myProject) {
@Override
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
((TemplateManagerImpl)TemplateManager.getInstance(myProject)).startTemplateWithPrefix(myEditor, template, null, argument);
}
}.execute();
}
+ else if (item instanceof CustomLiveTemplateLookupElement) {
+ if (myFile != null) {
+ new WriteCommandAction(myProject) {
+ @Override
+ protected void run(@NotNull Result result) throws Throwable {
+ ((CustomLiveTemplateLookupElement)item).expandTemplate(myEditor, myFile);
+ }
+ }.execute();
+ }
+ }
}
}
@@ -205,6 +262,5 @@
public LookupArranger createEmptyCopy() {
return new TemplatesArranger();
}
-
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java
index 005de1d..0a2fa55 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCharFilter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -30,7 +30,7 @@
if (item instanceof LiveTemplateLookupElement && lookup.isCompletion()) {
if (Character.isJavaIdentifierPart(c)) return Result.ADD_TO_PREFIX;
- if (c == ((LiveTemplateLookupElement)item).getTemplate().getShortcutChar()) {
+ if (c == ((LiveTemplateLookupElement)item).getTemplateShortcut()) {
return Result.SELECT_ITEM_AND_FINISH_LOOKUP;
}
return Result.HIDE_LOOKUP;
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java
index a6b0eba..295e6e1 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateCompletionContributor.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.
@@ -29,12 +29,13 @@
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
+
+import static com.intellij.codeInsight.template.impl.ListTemplatesHandler.listApplicableCustomTemplates;
/**
* @author peter
@@ -43,40 +44,40 @@
public LiveTemplateCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new CompletionProvider<CompletionParameters>() {
@Override
- protected void addCompletions(@NotNull CompletionParameters parameters,
+ protected void addCompletions(@NotNull final CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
final PsiFile file = parameters.getPosition().getContainingFile();
final int offset = parameters.getOffset();
final List<TemplateImpl> templates = listApplicableTemplates(file, offset);
+ Editor editor = parameters.getEditor();
if (showAllTemplates()) {
+ final MultiMap<String, CustomLiveTemplateLookupElement> customTemplates = listApplicableCustomTemplates(editor, file, offset);
final Ref<Boolean> templatesShown = Ref.create(false);
-
final CompletionResultSet finalResult = result;
result.runRemainingContributors(parameters, new Consumer<CompletionResult>() {
@Override
public void consume(CompletionResult completionResult) {
finalResult.passResult(completionResult);
- ensureTemplatesShown(templatesShown, templates, finalResult);
+ ensureTemplatesShown(templatesShown, templates, customTemplates, finalResult);
}
});
- ensureTemplatesShown(templatesShown, templates, result);
+ ensureTemplatesShown(templatesShown, templates, customTemplates, result);
return;
}
if (parameters.getInvocationCount() > 0) return; //only in autopopups for now
- String templatePrefix = findLiveTemplatePrefix(file, parameters.getEditor(), result.getPrefixMatcher().getPrefix());
+ String templatePrefix = findLiveTemplatePrefix(file, editor, result.getPrefixMatcher().getPrefix());
final TemplateImpl template = findApplicableTemplate(file, offset, templatePrefix);
if (template != null) {
result = result.withPrefixMatcher(template.getKey());
- result.addElement(new LiveTemplateLookupElement(template, true));
+ result.addElement(new LiveTemplateLookupElementImpl(template, true));
}
for (final TemplateImpl possible : templates) {
result.restartCompletionOnPrefixChange(possible.getKey());
}
-
}
});
}
@@ -86,11 +87,21 @@
return Registry.is("show.live.templates.in.completion");
}
- private static void ensureTemplatesShown(Ref<Boolean> templatesShown, List<TemplateImpl> templates, CompletionResultSet result) {
+ private static void ensureTemplatesShown(Ref<Boolean> templatesShown,
+ List<TemplateImpl> templates,
+ MultiMap<String, CustomLiveTemplateLookupElement> customTemplates,
+ CompletionResultSet result) {
if (!templatesShown.get()) {
templatesShown.set(true);
for (final TemplateImpl possible : templates) {
- result.addElement(new LiveTemplateLookupElement(possible, false));
+ result.addElement(new LiveTemplateLookupElementImpl(possible, false));
+ }
+
+ for (Map.Entry<String, Collection<CustomLiveTemplateLookupElement>> entry : customTemplates.entrySet()) {
+ Collection<CustomLiveTemplateLookupElement> value = entry.getValue();
+ if (!value.isEmpty()) {
+ result.withPrefixMatcher(entry.getKey()).addAllElements(value);
+ }
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateDocumentationProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateDocumentationProvider.java
new file mode 100644
index 0000000..6469d51
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateDocumentationProvider.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.template.impl;
+
+import com.intellij.lang.documentation.AbstractDocumentationProvider;
+import com.intellij.navigation.ItemPresentation;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.impl.FakePsiElement;
+import com.intellij.psi.impl.source.DummyHolder;
+import com.intellij.psi.impl.source.DummyHolderFactory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class LiveTemplateDocumentationProvider extends AbstractDocumentationProvider {
+ @Override
+ public PsiElement getDocumentationElementForLookupItem(PsiManager psiManager, Object object, PsiElement element) {
+ if (object instanceof LiveTemplateLookupElementImpl) {
+ TemplateImpl template = ((LiveTemplateLookupElementImpl)object).getTemplate();
+ final TemplateImpl templateFromSettings = TemplateSettings.getInstance().getTemplate(template.getKey(), template.getGroupName());
+ if (templateFromSettings != null) {
+ return new LiveTemplateElement(templateFromSettings, psiManager);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public String generateDoc(PsiElement element, @Nullable PsiElement originalElement) {
+ if (!(element instanceof LiveTemplateElement)) {
+ return null;
+ }
+
+ TemplateImpl template = ((LiveTemplateElement)element).getTemplate();
+ StringBuilder doc = new StringBuilder("<h2>").append(template.getKey()).append("</h2>");
+ String description = template.getDescription();
+ if (StringUtil.isNotEmpty(description)) {
+ doc.append("<pre>").append(StringUtil.escapeXml(description)).append("</pre><h2>template text</h2>");
+ }
+ return doc.append("<pre>").append(StringUtil.escapeXml(template.getString())).append("</pre>").toString();
+ }
+
+ private static class LiveTemplateElement extends FakePsiElement {
+ @NotNull private final TemplateImpl myTemplate;
+ @NotNull private final PsiManager myPsiManager;
+ @NotNull private DummyHolder myDummyHolder;
+
+ public LiveTemplateElement(@NotNull TemplateImpl template, @NotNull PsiManager psiManager) {
+ myTemplate = template;
+ myPsiManager = psiManager;
+ myDummyHolder = DummyHolderFactory.createHolder(myPsiManager, null);
+ }
+
+ @NotNull
+ public TemplateImpl getTemplate() {
+ return myTemplate;
+ }
+
+ @Override
+ public PsiElement getParent() {
+ return myDummyHolder;
+ }
+
+ @Override
+ public ItemPresentation getPresentation() {
+ return new ItemPresentation() {
+ @Nullable
+ @Override
+ public String getPresentableText() {
+ return myTemplate.getKey();
+ }
+
+ @Nullable
+ @Override
+ public String getLocationString() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public Icon getIcon(boolean unused) {
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public PsiManager getManager() {
+ return myPsiManager;
+ }
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupActionProvider.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupActionProvider.java
index 05fcba4..060494e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupActionProvider.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupActionProvider.java
@@ -1,3 +1,18 @@
+/*
+ * 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.codeInsight.template.impl;
import com.intellij.codeInsight.lookup.Lookup;
@@ -17,34 +32,35 @@
public class LiveTemplateLookupActionProvider implements LookupActionProvider {
@Override
public void fillActions(LookupElement element, final Lookup lookup, Consumer<LookupElementAction> consumer) {
- if (element instanceof LiveTemplateLookupElement) {
- final TemplateImpl template = ((LiveTemplateLookupElement)element).getTemplate();
-
- consumer.consume(new LookupElementAction(PlatformIcons.EDIT, "Edit live template settings") {
- @Override
- public Result performLookupAction() {
- final Project project = lookup.getEditor().getProject();
- assert project != null;
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- if (project.isDisposed()) return;
-
- final LiveTemplatesConfigurable configurable = new LiveTemplatesConfigurable();
- ShowSettingsUtil.getInstance().editConfigurable(project, configurable, new Runnable() {
- @Override
- public void run() {
- configurable.getTemplateListPanel().editTemplate(template);
- }
- });
- }
- });
- return Result.HIDE_LOOKUP;
- }
- });
-
+ if (element instanceof LiveTemplateLookupElementImpl) {
+ final TemplateImpl template = ((LiveTemplateLookupElementImpl)element).getTemplate();
final TemplateImpl templateFromSettings = TemplateSettings.getInstance().getTemplate(template.getKey(), template.getGroupName());
+
if (templateFromSettings != null) {
+ consumer.consume(new LookupElementAction(PlatformIcons.EDIT, "Edit live template settings") {
+ @Override
+ public Result performLookupAction() {
+ final Project project = lookup.getEditor().getProject();
+ assert project != null;
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (project.isDisposed()) return;
+
+ final LiveTemplatesConfigurable configurable = new LiveTemplatesConfigurable();
+ ShowSettingsUtil.getInstance().editConfigurable(project, configurable, new Runnable() {
+ @Override
+ public void run() {
+ configurable.getTemplateListPanel().editTemplate(template);
+ }
+ });
+ }
+ });
+ return Result.HIDE_LOOKUP;
+ }
+ });
+
+
consumer.consume(new LookupElementAction(AllIcons.Actions.Delete, String.format("Disable '%s' template", template.getKey())) {
@Override
public Result performLookupAction() {
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java
index 79a98aa..d01de9e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElement.java
@@ -15,11 +15,9 @@
*/
package com.intellij.codeInsight.template.impl;
-import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.lookup.RealLookupElementPresentation;
-import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,66 +27,56 @@
/**
* @author peter
*/
-public class LiveTemplateLookupElement extends LookupElement {
- private final String myPrefix;
- @NotNull private final TemplateImpl myTemplate;
+abstract public class LiveTemplateLookupElement extends LookupElement {
private final String myLookupString;
public final boolean sudden;
private final boolean myWorthShowingInAutoPopup;
+ private final String myDescription;
- public LiveTemplateLookupElement(@NotNull TemplateImpl template, boolean sudden) {
- this(template, null, sudden, false);
- }
-
- public LiveTemplateLookupElement(@NotNull TemplateImpl template, @Nullable String lookupString, boolean sudden, boolean worthShowingInAutoPopup) {
+ public LiveTemplateLookupElement(@NotNull String lookupString, @Nullable String description, boolean sudden, boolean worthShowingInAutoPopup) {
+ myDescription = description;
this.sudden = sudden;
myLookupString = lookupString;
- myPrefix = template.getKey();
- myTemplate = template;
myWorthShowingInAutoPopup = worthShowingInAutoPopup;
}
+
@NotNull
@Override
public String getLookupString() {
- return myPrefix;
+ return myLookupString;
}
@NotNull
- public TemplateImpl getTemplate() {
- return myTemplate;
+ protected String getItemText() {
+ return myLookupString;
}
@Override
public void renderElement(LookupElementPresentation presentation) {
super.renderElement(presentation);
- presentation.setItemText(StringUtil.notNullize(myLookupString, myPrefix));
+ char shortcut = getTemplateShortcut();
+ presentation.setItemText(getItemText());
if (sudden) {
presentation.setItemTextBold(true);
if (!presentation.isReal() || !((RealLookupElementPresentation)presentation).isLookupSelectionTouched()) {
- char shortcutChar = myTemplate.getShortcutChar();
- if (shortcutChar == TemplateSettings.DEFAULT_CHAR) {
- shortcutChar = TemplateSettings.getInstance().getDefaultShortcutChar();
+ if (shortcut == TemplateSettings.DEFAULT_CHAR) {
+ shortcut = TemplateSettings.getInstance().getDefaultShortcutChar();
}
- presentation.setTypeText(" [" + KeyEvent.getKeyText(shortcutChar) + "] ");
+ presentation.setTypeText(" [" + KeyEvent.getKeyText(shortcut) + "] ");
}
- String description = myTemplate.getDescription();
- if (description != null) {
- presentation.setTailText(" (" + description + ")", true);
+ if (StringUtil.isNotEmpty(myDescription)) {
+ presentation.setTailText(" (" + myDescription + ")", true);
}
- } else {
- presentation.setTypeText(myTemplate.getDescription());
}
- }
-
- @Override
- public void handleInsert(InsertionContext context) {
- context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
- context.setAddCompletionChar(false);
- TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), myTemplate);
+ else {
+ presentation.setTypeText(myDescription);
+ }
}
@Override
public boolean isWorthShowingInAutoPopup() {
return myWorthShowingInAutoPopup;
}
+
+ public abstract char getTemplateShortcut();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java
new file mode 100644
index 0000000..9ce0237
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateLookupElementImpl.java
@@ -0,0 +1,53 @@
+/*
+ * 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.codeInsight.template.impl;
+
+import com.intellij.codeInsight.completion.InsertionContext;
+import com.intellij.codeInsight.template.TemplateManager;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+
+public class LiveTemplateLookupElementImpl extends LiveTemplateLookupElement {
+ private final TemplateImpl myTemplate;
+
+ public LiveTemplateLookupElementImpl(@NotNull TemplateImpl template, boolean sudden) {
+ super(template.getKey(), StringUtil.notNullize(template.getDescription()), sudden, false);
+ myTemplate = template;
+ }
+
+ @NotNull
+ @Override
+ public String getLookupString() {
+ return myTemplate.getKey();
+ }
+
+ @NotNull
+ public TemplateImpl getTemplate() {
+ return myTemplate;
+ }
+
+ @Override
+ public char getTemplateShortcut() {
+ return TemplateSettings.getInstance().getShortcutChar(myTemplate);
+ }
+
+ @Override
+ public void handleInsert(InsertionContext context) {
+ context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
+ context.setAddCompletionChar(false);
+ TemplateManager.getInstance(context.getProject()).startTemplate(context.getEditor(), myTemplate);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java
index 868cf2f..fe0506e 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/LiveTemplateSettingsEditor.java
@@ -51,6 +51,7 @@
import com.intellij.util.ui.tree.TreeUtil;
import com.intellij.util.ui.update.Activatable;
import com.intellij.util.ui.update.UiNotifyConnector;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -129,9 +130,9 @@
return myTemplate;
}
- public void dispose() {
+ void dispose() {
final Project project = myTemplateEditor.getProject();
- if (project != null) {
+ if (project != null && !project.isDisposed()) {
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(myTemplateEditor.getDocument());
if (psiFile != null) {
DaemonCodeAnalyzer.getInstance(project).setHighlightingEnabled(psiFile, true);
@@ -233,7 +234,7 @@
gbConstraints.gridx = 1;
gbConstraints.insets = new Insets(0, 4, 0, 0);
- myExpandByCombo = new ComboBox(new Object[]{myDefaultShortcutItem, SPACE, TAB, ENTER}, -1);
+ myExpandByCombo = new ComboBox(new String[]{myDefaultShortcutItem, SPACE, TAB, ENTER});
myExpandByCombo.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
@@ -344,7 +345,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (disposeContextPopup()) return false;
final JPanel content = createPopupContextPanel(updateLabel, myContext);
@@ -381,12 +382,7 @@
static JPanel createPopupContextPanel(final Runnable onChange, final Map<TemplateContextType, Boolean> context) {
JPanel panel = new JPanel(new BorderLayout());
- MultiMap<TemplateContextType, TemplateContextType> hierarchy = new MultiMap<TemplateContextType, TemplateContextType>() {
- @Override
- protected Map<TemplateContextType, Collection<TemplateContextType>> createMap() {
- return new LinkedHashMap<TemplateContextType, Collection<TemplateContextType>>();
- }
- };
+ MultiMap<TemplateContextType, TemplateContextType> hierarchy = MultiMap.createLinked();
for (TemplateContextType type : context.keySet()) {
hierarchy.putValue(type.getBaseContextType(), type);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TableSorter.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TableSorter.java
index e197ad6..4418fa9 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TableSorter.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TableSorter.java
@@ -37,6 +37,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.ClickListener;
import com.intellij.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.TableModelEvent;
@@ -337,7 +338,7 @@
tableView.setColumnSelectionAllowed(false);
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
TableColumnModel columnModel = tableView.getColumnModel();
int viewColumn = columnModel.getColumnIndexAtX(e.getX());
int column = tableView.convertColumnIndexToModel(viewColumn);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java
index 0c1e604..05ecfad 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateManagerImpl.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.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.components.ProjectComponent;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.EditorFactoryAdapter;
@@ -79,11 +80,11 @@
Editor editor = event.getEditor();
if (editor.getProject() != null && editor.getProject() != myProject) return;
if (myProject.isDisposed() || !myProject.isOpen()) return;
- TemplateState tState = getTemplateState(editor);
- if (tState != null) {
- tState.gotoEnd();
+ TemplateState state = getTemplateState(editor);
+ if (state != null) {
+ state.gotoEnd();
}
- editor.putUserData(TEMPLATE_STATE_KEY, null);
+ clearTemplateState(editor);
}
};
EditorFactory.getInstance().addEditorFactoryListener(myEditorFactoryListener, myProject);
@@ -107,8 +108,8 @@
});
}
- private static void disposeState(final TemplateState tState) {
- Disposer.dispose(tState);
+ private static void disposeState(@NotNull TemplateState state) {
+ Disposer.dispose(state);
}
@Override
@@ -122,11 +123,11 @@
}
@Nullable
- public static TemplateState getTemplateState(Editor editor) {
+ public static TemplateState getTemplateState(@NotNull Editor editor) {
return editor.getUserData(TEMPLATE_STATE_KEY);
}
- void clearTemplateState(final Editor editor) {
+ static void clearTemplateState(@NotNull Editor editor) {
TemplateState prevState = getTemplateState(editor);
if (prevState != null) {
disposeState(prevState);
@@ -134,7 +135,7 @@
editor.putUserData(TEMPLATE_STATE_KEY, null);
}
- private TemplateState initTemplateState(final Editor editor) {
+ private TemplateState initTemplateState(@NotNull Editor editor) {
clearTemplateState(editor);
TemplateState state = new TemplateState(myProject, editor);
Disposer.register(this, state);
@@ -378,7 +379,7 @@
final Document document = editor.getDocument();
final CharSequence text = document.getCharsSequence();
- if (template2argument == null || template2argument.size() == 0) {
+ if (template2argument == null || template2argument.isEmpty()) {
return null;
}
if (!FileDocumentManager.getInstance().requestWriting(editor.getDocument(), myProject)) {
@@ -406,14 +407,13 @@
@Nullable Character shortcutChar,
TemplateSettings settings,
boolean hasArgument) {
- String key;
List<TemplateImpl> candidates = Collections.emptyList();
for (int i = settings.getMaxKeyLength(); i >= 1; i--) {
int wordStart = caretOffset - i;
if (wordStart < 0) {
continue;
}
- key = text.subSequence(wordStart, caretOffset).toString();
+ String key = text.subSequence(wordStart, caretOffset).toString();
if (Character.isJavaIdentifierStart(key.charAt(0))) {
if (wordStart > 0 && Character.isJavaIdentifierPart(text.charAt(wordStart - 1))) {
continue;
@@ -518,7 +518,7 @@
final TemplateContextType[] typeCollection = getAllContextTypes();
LinkedList<TemplateContextType> userDefinedExtensionsFirst = new LinkedList<TemplateContextType>();
for (TemplateContextType contextType : typeCollection) {
- if (contextType.getClass().getName().startsWith("com.intellij.codeInsight.template")) {
+ if (contextType.getClass().getName().startsWith(Template.class.getPackage().getName())) {
userDefinedExtensionsFirst.addLast(contextType);
}
else {
@@ -586,7 +586,7 @@
file = (PsiFile)file.copy();
final Document document = file.getViewProvider().getDocument();
assert document != null;
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(file.getProject(), new Runnable() {
@Override
public void run() {
document.replaceString(startOffset, endOffset, CompletionUtil.DUMMY_IDENTIFIER_TRIMMED);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java
index 520f15f..846320c 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/TemplateSettings.java
@@ -97,12 +97,7 @@
@NonNls private static final String TEMPLATES_CONFIG_FOLDER = "templates";
- private final MultiMap<String,TemplateImpl> myTemplates = new MultiMap<String,TemplateImpl>() {
- @Override
- protected Map<String, Collection<TemplateImpl>> createMap() {
- return new LinkedHashMap<String, Collection<TemplateImpl>>();
- }
- };
+ private final MultiMap<String,TemplateImpl> myTemplates = MultiMap.createLinked();
private final Map<String,Template> myTemplatesById = new LinkedHashMap<String,Template>();
private final Map<TemplateKey,TemplateImpl> myDefaultTemplates = new LinkedHashMap<TemplateKey, TemplateImpl>();
@@ -172,7 +167,7 @@
SchemeProcessor<TemplateGroup> processor = new BaseSchemeProcessor<TemplateGroup>() {
@Override
@Nullable
- public TemplateGroup readScheme(final Document schemeContent)
+ public TemplateGroup readScheme(@NotNull final Document schemeContent)
throws InvalidDataException, IOException, JDOMException {
return readTemplateFile(schemeContent, schemeContent.getRootElement().getAttributeValue("group"), false, false,
getClass().getClassLoader());
@@ -180,7 +175,7 @@
@Override
- public boolean shouldBeSaved(final TemplateGroup template) {
+ public boolean shouldBeSaved(@NotNull final TemplateGroup template) {
for (TemplateImpl t : template.getElements()) {
if (differsFromDefault(t)) {
return true;
@@ -190,7 +185,7 @@
}
@Override
- public Document writeScheme(final TemplateGroup template) throws WriteExternalException {
+ public Document writeScheme(@NotNull final TemplateGroup template) throws WriteExternalException {
Element templateSetElement = new Element(TEMPLATE_SET);
templateSetElement.setAttribute(GROUP, template.getName());
@@ -204,7 +199,7 @@
}
@Override
- public void initScheme(final TemplateGroup scheme) {
+ public void initScheme(@NotNull final TemplateGroup scheme) {
Collection<TemplateImpl> templates = scheme.getElements();
for (TemplateImpl template : templates) {
@@ -213,14 +208,14 @@
}
@Override
- public void onSchemeAdded(final TemplateGroup scheme) {
+ public void onSchemeAdded(@NotNull final TemplateGroup scheme) {
for (TemplateImpl template : scheme.getElements()) {
addTemplateImpl(template);
}
}
@Override
- public void onSchemeDeleted(final TemplateGroup scheme) {
+ public void onSchemeDeleted(@NotNull final TemplateGroup scheme) {
for (TemplateImpl template : scheme.getElements()) {
removeTemplate(template);
}
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 2bcf02b..1ce2e35 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
@@ -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.
@@ -93,6 +93,7 @@
private boolean myFinished;
@Nullable private PairProcessor<String, String> myProcessor;
private boolean mySelectionCalculated = false;
+ private boolean myStarted;
public TemplateState(@NotNull Project project, final Editor editor) {
myProject = project;
@@ -134,32 +135,27 @@
final LookupImpl lookup = myEditor != null ? (LookupImpl)LookupManager.getActiveLookup(myEditor) : null;
if (lookup != null) {
lookup.performGuardedChange(runnable);
- } else {
+ }
+ else {
runnable.run();
}
}
}
};
- myDocument.addDocumentListener(myEditorDocumentListener);
- CommandProcessor.getInstance().addCommandListener(myCommandListener);
+ myDocument.addDocumentListener(myEditorDocumentListener, this);
+ CommandProcessor.getInstance().addCommandListener(myCommandListener, this);
}
@Override
public synchronized void dispose() {
- if (myEditorDocumentListener != null) {
- myDocument.removeDocumentListener(myEditorDocumentListener);
- myEditorDocumentListener = null;
- }
- if (myCommandListener != null) {
- CommandProcessor.getInstance().removeCommandListener(myCommandListener);
- myCommandListener = null;
- }
+ myEditorDocumentListener = null;
+ myCommandListener = null;
myProcessor = null;
//Avoid the leak of the editor
- releaseEditor();
+ releaseAll();
myDocument = null;
}
@@ -176,7 +172,7 @@
private void setCurrentVariableNumber(int variableNumber) {
myCurrentVariableNumber = variableNumber;
- final boolean isFinished = variableNumber < 0;
+ final boolean isFinished = isFinished();
((DocumentEx)myDocument).setStripTrailingSpacesEnabled(isFinished);
myCurrentSegmentNumber = isFinished ? -1 : getCurrentSegmentNumber();
}
@@ -262,9 +258,11 @@
}
}
- public void start(TemplateImpl template,
+ public void start(@NotNull TemplateImpl template,
@Nullable final PairProcessor<String, String> processor,
@Nullable Map<String, String> predefinedVarValues) {
+ LOG.assertTrue(!myStarted, "Already started");
+ myStarted = true;
myTemplate = template;
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
@@ -328,7 +326,7 @@
}
}
- private void processAllExpressions(final TemplateImpl template) {
+ private void processAllExpressions(@NotNull final TemplateImpl template) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
@@ -365,7 +363,7 @@
});
}
- public void doReformat(final TextRange range) {
+ private void doReformat(final TextRange range) {
RangeMarker rangeMarker = null;
if (range != null) {
rangeMarker = myDocument.createRangeMarker(range);
@@ -876,14 +874,20 @@
}
}
+ boolean isDisposed() {
+ return myDocument == null;
+ }
+
private void cleanupTemplateState(boolean brokenOff) {
final Editor editor = myEditor;
fireBeforeTemplateFinished();
int oldVar = myCurrentVariableNumber;
- setCurrentVariableNumber(-1);
currentVariableChanged(oldVar);
- ((TemplateManagerImpl)TemplateManager.getInstance(myProject)).clearTemplateState(editor);
- fireTemplateFinished(brokenOff);
+ if (!isDisposed()) {
+ setCurrentVariableNumber(-1);
+ TemplateManagerImpl.clearTemplateState(editor);
+ fireTemplateFinished(brokenOff);
+ }
myListeners.clear();
myProject = null;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java
index 22774e8..8dc75cc 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/VariableNode.java
@@ -20,38 +20,31 @@
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.ExpressionContext;
import com.intellij.codeInsight.template.Result;
+import org.jetbrains.annotations.Nullable;
public class VariableNode extends Expression {
private final String myName;
private final Expression myInitialValue;
- public VariableNode(String name, Expression initialValue) {
+ public VariableNode(String name, @Nullable Expression initialValue) {
myName = name;
myInitialValue = initialValue;
}
@Override
public Result calculateResult(ExpressionContext context) {
- Result ret = null;
if (myInitialValue != null){
- ret = myInitialValue.calculateResult(context);
+ return myInitialValue.calculateResult(context);
}
- else{
- ret = TemplateManagerImpl.getTemplateState(context.getEditor()).getVariableValue(getName());
- }
- return ret;
+ return TemplateManagerImpl.getTemplateState(context.getEditor()).getVariableValue(getName());
}
@Override
public Result calculateQuickResult(ExpressionContext context) {
- Result ret = null;
if (myInitialValue != null){
- ret = myInitialValue.calculateQuickResult(context);
+ return myInitialValue.calculateQuickResult(context);
}
- else{
- ret = TemplateManagerImpl.getTemplateState(context.getEditor()).getVariableValue(getName());
- }
- return ret;
+ return TemplateManagerImpl.getTemplateState(context.getEditor()).getVariableValue(getName());
}
@Override
@@ -66,7 +59,7 @@
return myName;
}
- public Expression getInitialValue() {
+ @Nullable public Expression getInitialValue() {
return myInitialValue;
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/HomeEndHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/HomeEndHandler.java
index c5e1909..c200367 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/HomeEndHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/HomeEndHandler.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.
@@ -28,6 +28,7 @@
boolean myIsHomeHandler;
public HomeEndHandler(final EditorActionHandler originalHandler, boolean isHomeHandler) {
+ super(true);
myOriginalHandler = originalHandler;
myIsHomeHandler = isHomeHandler;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java
index 01a1d53..1e8dc18 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/impl/editorActions/LineStartEndWithSelectionHandler.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.
@@ -28,6 +28,7 @@
boolean myIsHomeHandler;
public LineStartEndWithSelectionHandler(final EditorActionHandler originalHandler, boolean isHomeHandler) {
+ super(true);
myOriginalHandler = originalHandler;
myIsHomeHandler = isHomeHandler;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java
index f7e134f..29fb920 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/CapitalizeAndUnderscoreMacro.java
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.template.macro;
+import com.google.common.annotations.VisibleForTesting;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.template.Expression;
import com.intellij.codeInsight.template.ExpressionContext;
@@ -39,23 +40,33 @@
@Override
protected Result calculateResult(@NotNull Expression[] params, ExpressionContext context, boolean quick) {
String text = getTextResult(params, context, true);
- if (text != null && text.length() > 0) {
- final String[] words = NameUtil.nameToWords(text);
- boolean insertUnderscore = false;
- final StringBuilder buf = new StringBuilder();
- for (String word : words) {
- if (insertUnderscore) {
- buf.append("_");
- } else {
- insertUnderscore = true;
- }
- buf.append(convertCase(word));
- }
- return new TextResult(buf.toString());
+ if (StringUtil.isNotEmpty(text)) {
+ return new TextResult(convertString(text));
}
return null;
}
+ @VisibleForTesting
+ public String convertString(String text) {
+ final String[] words = NameUtil.nameToWords(text);
+ boolean insertUnderscore = false;
+ final StringBuilder buf = new StringBuilder();
+ for (String word : words) {
+ if (!Character.isLetterOrDigit(word.charAt(0))) {
+ buf.append("_");
+ insertUnderscore = false;
+ continue;
+ }
+ if (insertUnderscore) {
+ buf.append("_");
+ } else {
+ insertUnderscore = true;
+ }
+ buf.append(convertCase(word));
+ }
+ return buf.toString();
+ }
+
protected String convertCase(String word) {
return StringUtil.toUpperCase(word);
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/ClipboardMacro.java b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/ClipboardMacro.java
index 01f0800..f1c3906 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/template/macro/ClipboardMacro.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/template/macro/ClipboardMacro.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,9 +20,6 @@
import com.intellij.openapi.ide.CopyPasteManager;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
-import java.io.IOException;
/**
* @author yole
@@ -34,20 +31,7 @@
@Override
protected String evaluateSimpleMacro(Expression[] params, ExpressionContext context) {
- Transferable contents = CopyPasteManager.getInstance().getContents();
- if (contents != null) {
- String result = "";
- try {
- result = (String) contents.getTransferData(DataFlavor.stringFlavor);
- }
- catch (UnsupportedFlavorException ignored) {
- }
- catch (IOException ignored) {
- }
- if (result != null) {
- return result;
- }
- }
- return "";
+ String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
+ return text != null ? text : "";
}
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java b/platform/lang-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java
deleted file mode 100644
index 54caec4..0000000
--- a/platform/lang-impl/src/com/intellij/codeInspection/ExternalAnnotatorInspectionVisitor.java
+++ /dev/null
@@ -1,92 +0,0 @@
-package com.intellij.codeInspection;
-
-import com.intellij.codeInsight.daemon.impl.AnnotationHolderImpl;
-import com.intellij.lang.annotation.Annotation;
-import com.intellij.lang.annotation.AnnotationSession;
-import com.intellij.lang.annotation.ExternalAnnotator;
-import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiElementVisitor;
-import com.intellij.psi.PsiFile;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class ExternalAnnotatorInspectionVisitor extends PsiElementVisitor {
- private static final Logger LOG = Logger.getInstance(ExternalAnnotatorInspectionVisitor.class);
-
- private final ProblemsHolder myHolder;
- private final ExternalAnnotator myAnnotator;
- private boolean myOnTheFly;
-
- public ExternalAnnotatorInspectionVisitor(ProblemsHolder holder, ExternalAnnotator annotator, boolean onTheFly) {
- myHolder = holder;
- myAnnotator = annotator;
- myOnTheFly = onTheFly;
- }
-
- public static ProblemDescriptor[] checkFileWithExternalAnnotator(PsiFile file,
- InspectionManager manager,
- boolean isOnTheFly, ExternalAnnotator annotator) {
- if (isOnTheFly) {
- // concrete JSLinterExternalAnnotator implementation does this work
- return ProblemDescriptor.EMPTY_ARRAY;
- }
-
- Object info = annotator.collectInformation(file);
- if (info != null) {
- Object annotationResult = annotator.doAnnotate(info);
- if (annotationResult == null) {
- return ProblemDescriptor.EMPTY_ARRAY;
- }
- AnnotationHolderImpl annotationHolder = new AnnotationHolderImpl(new AnnotationSession(file));
- annotator.apply(file, annotationResult, annotationHolder);
- return convertToProblemDescriptors(annotationHolder, manager, file);
- }
- return ProblemDescriptor.EMPTY_ARRAY;
- }
-
- private static ProblemDescriptor[] convertToProblemDescriptors(@NotNull final List<Annotation> annotations,
- @NotNull final InspectionManager manager,
- @NotNull final PsiFile file) {
- if (annotations.size() == 0) {
- return ProblemDescriptor.EMPTY_ARRAY;
- }
-
- final List<ProblemDescriptor> problems = new ArrayList<ProblemDescriptor>();
- for (final Annotation annotation : annotations) {
- if (annotation.getSeverity() == HighlightSeverity.INFORMATION ||
- annotation.getStartOffset() == annotation.getEndOffset()) {
- continue;
- }
-
- final PsiElement startElement = file.findElementAt(annotation.getStartOffset());
- final PsiElement endElement = file.findElementAt(annotation.getEndOffset() - 1);
- if (startElement == null || endElement == null) {
- continue;
- }
-
- problems.add(manager.createProblemDescriptor(startElement, endElement, annotation.getMessage(),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false));
- }
- return problems.toArray(new ProblemDescriptor[problems.size()]);
- }
-
- @Override
- public void visitFile(PsiFile file) {
- if (!myOnTheFly) {
- ProblemDescriptor[] descriptors = checkFileWithExternalAnnotator(file, myHolder.getManager(),
- false, myAnnotator);
- addDescriptors(descriptors);
- }
- }
-
- private void addDescriptors(@NotNull ProblemDescriptor[] descriptors) {
- for (ProblemDescriptor descriptor : descriptors) {
- LOG.assertTrue(descriptor != null, getClass().getName());
- myHolder.registerProblem(descriptor);
- }
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/LossyEncodingInspection.java b/platform/lang-impl/src/com/intellij/codeInspection/LossyEncodingInspection.java
index 7ec8be7..dcd8359 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/LossyEncodingInspection.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/LossyEncodingInspection.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,13 +33,11 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.ChangeFileEncodingAction;
import com.intellij.openapi.vfs.encoding.EncodingUtil;
@@ -104,7 +102,7 @@
if (charset instanceof Native2AsciiCharset) return null;
List<ProblemDescriptor> descriptors = new SmartList<ProblemDescriptor>();
- boolean ok = checkFileLoadedInWrongEncoding(file, manager, isOnTheFly, text, virtualFile, charset, descriptors);
+ boolean ok = checkFileLoadedInWrongEncoding(file, manager, isOnTheFly, virtualFile, charset, descriptors);
if (ok) {
checkIfCharactersWillBeLostAfterSave(file, manager, isOnTheFly, text, charset, descriptors);
}
@@ -115,7 +113,6 @@
private static boolean checkFileLoadedInWrongEncoding(@NotNull PsiFile file,
@NotNull InspectionManager manager,
boolean isOnTheFly,
- @NotNull String text,
@NotNull VirtualFile virtualFile,
@NotNull Charset charset,
@NotNull List<ProblemDescriptor> descriptors) {
@@ -124,7 +121,7 @@
) {
return true;
}
- if (!isGoodCharset(virtualFile, text, charset, file.getProject())) {
+ if (!isGoodCharset(virtualFile, charset)) {
descriptors.add(manager.createProblemDescriptor(file, "File was loaded in the wrong encoding: '"+charset+"'",
RELOAD_ENCODING_FIX, ProblemHighlightType.GENERIC_ERROR, isOnTheFly));
return false;
@@ -134,38 +131,29 @@
// check if file was loaded in correct encoding
// returns true if text converted with charset is equals to the bytes currently on disk
- private static boolean isGoodCharset(@NotNull VirtualFile virtualFile,
- @NotNull String text,
- @NotNull Charset charset,
- @NotNull Project project) {
+ private static boolean isGoodCharset(@NotNull VirtualFile virtualFile, @NotNull Charset charset) {
FileDocumentManager documentManager = FileDocumentManager.getInstance();
Document document = documentManager.getDocument(virtualFile);
if (document == null) return true;
- byte[] bytes;
+ byte[] loadedBytes;
+ byte[] bytesToSave;
try {
- bytes = virtualFile.contentsToByteArray();
+ loadedBytes = virtualFile.contentsToByteArray();
+ bytesToSave = new String(loadedBytes, charset).getBytes(charset);
}
- catch (IOException e) {
+ catch (Exception e) {
return true;
}
- String separator = LoadTextUtil.detectLineSeparator(virtualFile, false);
- if (separator == null) {
- separator = documentManager.isDocumentUnsaved(document) ?
- FileDocumentManagerImpl.getLineSeparator(document, virtualFile) :
- FileDocumentManager.getInstance().getLineSeparator(null, project);
- }
- String toSave = StringUtil.convertLineSeparators(text, separator);
byte[] bom = virtualFile.getBOM();
- byte[] bytesToSave = toSave.getBytes(charset);
if (bom != null && !ArrayUtil.startsWith(bytesToSave, bom)) {
bytesToSave = ArrayUtil.mergeArrays(bom, bytesToSave); // for 2-byte encodings String.getBytes(Charset) adds BOM automatically
}
- boolean equals = Arrays.equals(bytesToSave, bytes);
+ boolean equals = Arrays.equals(bytesToSave, loadedBytes);
if (!equals && LOG.isDebugEnabled()) {
try {
FileUtil.writeToFile(new File("C:\\temp\\bytesToSave"), bytesToSave);
- FileUtil.writeToFile(new File("C:\\temp\\bytes"), bytes);
+ FileUtil.writeToFile(new File("C:\\temp\\loadedBytes"), loadedBytes);
}
catch (IOException e) {
throw new RuntimeException(e);
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java
index 4a3a402..9069f4c 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/DescriptorComposer.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.util.text.CharArrayUtil;
@@ -81,13 +82,17 @@
}
List<String> texts = new ArrayList<String>();
for (QuickFixAction quickFix : quickFixes) {
- final String text = quickFix.getText(where);
+ String text = quickFix.getText(where);
if (text == null) continue;
- texts.add(text);
+ texts.add(escapeQuickFixText(text));
}
return texts.toArray(new String[texts.size()]);
}
+ private static String escapeQuickFixText(String text) {
+ return XmlStringUtil.isWrappedInHtml(text) ? XmlStringUtil.stripHtml(text) : StringUtil.escapeXml(text);
+ }
+
protected void composeAdditionalDescription(@NotNull StringBuffer buf, @NotNull RefEntity refEntity) {}
@Override
@@ -132,7 +137,7 @@
//noinspection HardCodedStringLiteral
buf.append("<a HREF=\"file://bred.txt#invokelocal:" + (idx++));
buf.append("\">");
- buf.append(fix.getName());
+ buf.append(escapeQuickFixText(fix.getName()));
//noinspection HardCodedStringLiteral
buf.append("</a>");
//noinspection HardCodedStringLiteral
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java
index ec29740..b5333e8 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/SeverityEditorDialog.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.
@@ -29,7 +29,6 @@
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.diagnostic.Logger;
import com.intellij.openapi.editor.colors.CodeInsightColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
@@ -86,7 +85,7 @@
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
final Component rendererComponent = super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof SeverityBasedTextAttributes) {
- setText(((SeverityBasedTextAttributes)value).getSeverity().toString());
+ setText(((SeverityBasedTextAttributes)value).getSeverity().getName());
}
return rendererComponent;
}
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java
index 5a0b5a4..ce8378d 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/Browser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2013 JetBrains s.r.o.
+ * 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.
@@ -417,7 +417,7 @@
public void showEmpty() {
myCurrentEntity = null;
try {
- myHTMLViewer.read(new StringReader("<html><body></body></html>"), null);
+ myHTMLViewer.read(new StringReader(InspectionsBundle.message("inspection.offline.view.empty.browser.text")), null);
}
catch (IOException e) {
//can't be
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
index 40f2b22..fe7c3ab 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java
@@ -110,17 +110,16 @@
return description;
}
- protected static HighlightSeverity getSeverity(@NotNull RefElement element,
- @NotNull GlobalInspectionContextImpl context,
- @NotNull InspectionToolWrapper thisToolWrapper) {
+ protected HighlightSeverity getSeverity(@NotNull RefElement element) {
final PsiElement psiElement = element.getPointer().getContainingFile();
if (psiElement != null) {
- String shortName = thisToolWrapper.getShortName();
+ final GlobalInspectionContextImpl context = getContext();
+ final String shortName = getSeverityDelegateName();
final Tools tools = context.getTools().get(shortName);
if (tools != null) {
for (ScopeToolState state : tools.getTools()) {
InspectionToolWrapper toolWrapper = state.getTool();
- if (toolWrapper == thisToolWrapper) {
+ if (toolWrapper == getToolWrapper()) {
return context.getCurrentProfile().getErrorLevel(HighlightDisplayKey.find(shortName), psiElement).getSeverity();
}
}
@@ -133,6 +132,10 @@
return null;
}
+ protected String getSeverityDelegateName() {
+ return getToolWrapper().getShortName();
+ }
+
protected static String getTextAttributeKey(@NotNull Project project,
@NotNull HighlightSeverity severity,
@NotNull ProblemHighlightType highlightType) {
@@ -222,7 +225,7 @@
}
InspectionNode toolNode = myToolNode;
if (toolNode == null) {
- final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement, context, myToolWrapper);
+ final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement);
view.addTool(myToolWrapper, HighlightDisplayLevel.find(currentSeverity), context.getUIOptions().GROUP_BY_SEVERITY);
}
else if (toolNode.isTooBigForOnlineRefresh()) {
@@ -456,7 +459,7 @@
problemClassElement.addContent(myToolWrapper.getDisplayName());
if (refEntity instanceof RefElement){
final RefElement refElement = (RefElement)refEntity;
- final HighlightSeverity severity = getSeverity(refElement, getContext(), getToolWrapper());
+ final HighlightSeverity severity = getSeverity(refElement);
ProblemHighlightType problemHighlightType = descriptor instanceof ProblemDescriptor
? ((ProblemDescriptor)descriptor).getHighlightType()
: ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java
index 0bc7fec..5dffdf7 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.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.
@@ -97,7 +97,7 @@
public int compare(HighlightDisplayLevel o1, HighlightDisplayLevel o2) {
final int severityDiff = o1.getSeverity().compareTo(o2.getSeverity());
if (severityDiff == 0) {
- return o1.toString().compareTo(o2.toString());
+ return o1.getName().compareTo(o2.getName());
}
return severityDiff;
}
@@ -173,6 +173,7 @@
});
createActionsToolbar();
+ TreeUtil.selectFirstNode(myTree);
}
private void initTreeListeners() {
@@ -218,6 +219,9 @@
@Override
@Nullable
protected Navigatable createDescriptorForNode(DefaultMutableTreeNode node) {
+ if (node instanceof InspectionTreeNode && ((InspectionTreeNode)node).isResolved()) {
+ return null;
+ }
if (node instanceof RefElementNode) {
final RefElementNode refNode = (RefElementNode)node;
if (refNode.hasDescriptorsUnder()) return null;
diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/actions/SuppressActionWrapper.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/actions/SuppressActionWrapper.java
index ac801b7..6b48fdf 100644
--- a/platform/lang-impl/src/com/intellij/codeInspection/ui/actions/SuppressActionWrapper.java
+++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/actions/SuppressActionWrapper.java
@@ -10,6 +10,7 @@
import com.intellij.codeInspection.ex.InspectionToolWrapper;
import com.intellij.codeInspection.reference.RefElement;
import com.intellij.codeInspection.reference.RefEntity;
+import com.intellij.codeInspection.ui.InspectionToolPresentation;
import com.intellij.codeInspection.ui.InspectionTreeNode;
import com.intellij.codeInspection.ui.ProblemDescriptionNode;
import com.intellij.codeInspection.ui.RefElementNode;
@@ -78,7 +79,10 @@
return actions;
}
- private boolean suppress(final PsiElement element, final SuppressIntentionAction action) {
+ private boolean suppress(final PsiElement element,
+ final CommonProblemDescriptor descriptor,
+ final SuppressIntentionAction action,
+ final RefEntity refEntity) {
final PsiModificationTracker tracker = PsiManager.getInstance(myProject).getModificationTracker();
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -86,13 +90,25 @@
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
try {
final long startModificationCount = tracker.getModificationCount();
+
+ PsiElement container = null;
+ if (action instanceof SuppressIntentionActionFromFix) {
+ container = ((SuppressIntentionActionFromFix)action).getContainer(element);
+ }
+ if (container == null) {
+ container = element;
+ }
+
if (action.isAvailable(myProject, null, element)) {
action.invoke(myProject, null, element);
}
if (startModificationCount != tracker.getModificationCount()) {
final Set<GlobalInspectionContextImpl> globalInspectionContexts = myManager.getRunningContexts();
for (GlobalInspectionContextImpl context : globalInspectionContexts) {
- context.ignoreElement(myToolWrapper.getTool(), element);
+ context.ignoreElement(myToolWrapper.getTool(), container);
+ if (descriptor != null) {
+ context.getPresentation(myToolWrapper).ignoreCurrentElementProblem(refEntity, descriptor);
+ }
}
}
}
@@ -149,7 +165,13 @@
final Pair<PsiElement, CommonProblemDescriptor> content = getContentToSuppress(node);
if (content.first == null) break;
final PsiElement element = content.first;
- if (!suppress(element, mySuppressAction)) break;
+ RefEntity refEntity = null;
+ if (node instanceof RefElementNode) {
+ refEntity = ((RefElementNode)node).getElement();
+ } else if (node instanceof ProblemDescriptionNode) {
+ refEntity = ((ProblemDescriptionNode)node).getElement();
+ }
+ if (!suppress(element, content.second, mySuppressAction, refEntity)) break;
}
final Set<GlobalInspectionContextImpl> globalInspectionContexts = myManager.getRunningContexts();
for (GlobalInspectionContextImpl context : globalInspectionContexts) {
diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java
index 09ad57a..99db026 100644
--- a/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java
+++ b/platform/lang-impl/src/com/intellij/conversion/impl/ConversionServiceImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -318,7 +318,7 @@
final int res = Messages.showYesNoDialog(project, IdeBundle.message("message.module.file.has.an.older.format.do.you.want.to.convert.it"),
IdeBundle.message("dialog.title.convert.module"), Messages.getQuestionIcon());
- if (res != 0) {
+ if (res != Messages.YES) {
return ConversionResultImpl.CONVERSION_CANCELED;
}
if (!moduleFile.canWrite()) {
diff --git a/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java b/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java
index e6eaf0c..e59d2d5 100644
--- a/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java
+++ b/platform/lang-impl/src/com/intellij/conversion/impl/ui/ConvertProjectDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -110,7 +110,7 @@
filesString),
IdeBundle.message("dialog.title.convert.project"),
Messages.getQuestionIcon());
- if (res != 0) {
+ if (res != Messages.YES) {
super.doOKAction();
return;
}
@@ -162,7 +162,7 @@
ApplicationNamesInfo.getInstance().getFullProductName(),
getFilesString(files));
final String[] options = {CommonBundle.getContinueButtonText(), CommonBundle.getCancelButtonText()};
- if (Messages.showOkCancelDialog(myMainPanel, message, IdeBundle.message("dialog.title.convert.project"), options[0], options[1], null) != 0) {
+ if (Messages.showOkCancelDialog(myMainPanel, message, IdeBundle.message("dialog.title.convert.project"), options[0], options[1], null) != Messages.OK) {
return false;
}
unlockFiles(files);
diff --git a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
index 72e9d56..f19d92f 100644
--- a/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
+++ b/platform/lang-impl/src/com/intellij/execution/ProgramRunnerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -101,7 +101,7 @@
}
while (!RunManagerImpl.canRunConfiguration(configuration, executor)) {
- if (0 == Messages
+ if (Messages.YES == Messages
.showYesNoDialog(project, "Configuration is still incorrect. Do you want to edit it again?", "Change Configuration Settings",
"Edit", "Continue Anyway", Messages.getErrorIcon())) {
if (!RunDialog.editConfiguration(project, configuration, "Edit configuration", executor)) {
diff --git a/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java b/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java
index 5f93561..fa530cc 100644
--- a/platform/lang-impl/src/com/intellij/execution/RunManagerEx.java
+++ b/platform/lang-impl/src/com/intellij/execution/RunManagerEx.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.
@@ -74,7 +74,6 @@
public abstract RunnerAndConfigurationSettings findConfigurationByName(@Nullable final String name);
public abstract Icon getConfigurationIcon(@NotNull RunnerAndConfigurationSettings settings);
- public abstract void invalidateConfigurationIcon(@NotNull RunnerAndConfigurationSettings settings);
@NotNull
public abstract Collection<RunnerAndConfigurationSettings> getSortedConfigurations();
diff --git a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java
index c323e8e..7cb6089 100644
--- a/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java
+++ b/platform/lang-impl/src/com/intellij/execution/actions/RunConfigurationsComboBoxAction.java
@@ -127,6 +127,7 @@
final RunnerAndConfigurationSettings settings,
final Project project) {
try {
+ presentation.setIcon(EmptyIcon.ICON_16);//Hack for same DeferredIcon with new "recalculated" delegate icon inside (events won't pass)
presentation.setIcon(RunManagerEx.getInstanceEx(project).getConfigurationIcon(settings));
}
catch (IndexNotReadyException ignored) {
diff --git a/platform/lang-impl/src/com/intellij/execution/configuration/EmptyRunProfileState.java b/platform/lang-impl/src/com/intellij/execution/configuration/EmptyRunProfileState.java
index b260a33..5622adc 100644
--- a/platform/lang-impl/src/com/intellij/execution/configuration/EmptyRunProfileState.java
+++ b/platform/lang-impl/src/com/intellij/execution/configuration/EmptyRunProfileState.java
@@ -1,6 +1,5 @@
package com.intellij.execution.configuration;
-import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RunProfileState;
@@ -9,14 +8,14 @@
import org.jetbrains.annotations.Nullable;
public final class EmptyRunProfileState implements RunProfileState {
- public static RunProfileState INSTANCE = new EmptyRunProfileState();
+ public static final RunProfileState INSTANCE = new EmptyRunProfileState();
private EmptyRunProfileState() {
}
@Nullable
@Override
- public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) throws ExecutionException {
+ public ExecutionResult execute(Executor executor, @NotNull ProgramRunner runner) {
return null;
}
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/BaseConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/console/BaseConsoleExecuteActionHandler.java
new file mode 100644
index 0000000..6df77d4
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/console/BaseConsoleExecuteActionHandler.java
@@ -0,0 +1,102 @@
+/*
+ * 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.execution.console;
+
+import com.intellij.execution.process.ConsoleHistoryModel;
+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.Document;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class BaseConsoleExecuteActionHandler {
+ private boolean myAddCurrentToHistory = true;
+ private final ConsoleHistoryModel myConsoleHistoryModel;
+ private final boolean myPreserveMarkup;
+
+ public BaseConsoleExecuteActionHandler(boolean preserveMarkup) {
+ myConsoleHistoryModel = new ConsoleHistoryModel();
+ myPreserveMarkup = preserveMarkup;
+ }
+
+ public ConsoleHistoryModel getConsoleHistoryModel() {
+ return myConsoleHistoryModel;
+ }
+
+ public void setAddCurrentToHistory(boolean addCurrentToHistory) {
+ myAddCurrentToHistory = addCurrentToHistory;
+ }
+
+ public void runExecuteAction(@NotNull LanguageConsoleView consoleView) {
+ runExecuteAction(consoleView, consoleView.getConsole());
+ }
+
+ private void runExecuteAction(@Nullable LanguageConsoleView consoleView, @NotNull LanguageConsoleImpl console) {
+ // process input and add to history
+ Document document = console.getCurrentEditor().getDocument();
+ String text = document.getText();
+ TextRange range = new TextRange(0, document.getTextLength());
+
+ console.getCurrentEditor().getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
+
+ if (myAddCurrentToHistory) {
+ console.addCurrentToHistory(range, false, myPreserveMarkup);
+ }
+
+ console.setInputText("");
+
+ ((UndoManagerImpl)UndoManager.getInstance(console.getProject())).invalidateActionsFor(DocumentReferenceManager.getInstance().create(document));
+
+ myConsoleHistoryModel.addToHistory(text);
+ if (consoleView == null) {
+ //noinspection deprecation
+ execute(text);
+ }
+ else {
+ execute(text, consoleView);
+ }
+ }
+
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 15
+ */
+ public void runExecuteAction(@NotNull LanguageConsoleImpl languageConsole) {
+ runExecuteAction(null, languageConsole);
+ }
+
+ protected void execute(@NotNull String text, @NotNull LanguageConsoleView console) {
+ //noinspection deprecation
+ execute(text);
+ }
+
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 15
+ */
+ protected void execute(@NotNull String text) {
+ throw new AbstractMethodError();
+ }
+
+ public void finishExecution() {
+ }
+
+ public String getEmptyExecuteAction() {
+ return ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID;
+ }
+}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java
new file mode 100644
index 0000000..f912178
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleExecuteAction.java
@@ -0,0 +1,67 @@
+/*
+ * 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.execution.console;
+
+import com.intellij.codeInsight.lookup.Lookup;
+import com.intellij.codeInsight.lookup.LookupManager;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.EmptyAction;
+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 org.jetbrains.annotations.NotNull;
+
+public class ConsoleExecuteAction extends DumbAwareAction {
+ static final String CONSOLE_EXECUTE_ACTION_ID = "Console.Execute";
+
+ private final LanguageConsoleView myConsole;
+ private final BaseConsoleExecuteActionHandler myExecuteActionHandler;
+ private final Condition<LanguageConsoleImpl> myEnabledCondition;
+
+ public ConsoleExecuteAction(@NotNull LanguageConsoleView console, @NotNull BaseConsoleExecuteActionHandler executeActionHandler) {
+ this(console, executeActionHandler, CONSOLE_EXECUTE_ACTION_ID, Conditions.<LanguageConsoleImpl>alwaysTrue());
+ }
+
+ public ConsoleExecuteAction(@NotNull LanguageConsoleView console, @NotNull BaseConsoleExecuteActionHandler executeActionHandler,
+ @NotNull String emptyExecuteActionId, @NotNull Condition<LanguageConsoleImpl> enabledCondition) {
+ super(null, null, AllIcons.Actions.Execute);
+
+ myConsole = console;
+ myExecuteActionHandler = executeActionHandler;
+ myEnabledCondition = enabledCondition;
+
+ EmptyAction.setupAction(this, emptyExecuteActionId, null);
+ }
+
+ @Override
+ public final void update(AnActionEvent e) {
+ EditorEx editor = myConsole.getConsole().getConsoleEditor();
+ Lookup lookup = LookupManager.getActiveLookup(editor);
+ e.getPresentation().setEnabled(!editor.isRendererMode() && isEnabled() &&
+ (lookup == null || !lookup.isCompletion()));
+ }
+
+ @Override
+ public final void actionPerformed(AnActionEvent e) {
+ myExecuteActionHandler.runExecuteAction(myConsole);
+ }
+
+ protected boolean isEnabled() {
+ return myEnabledCondition.value(myConsole.getConsole());
+ }
+}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java
new file mode 100644
index 0000000..c6cb073
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleGutterComponent.java
@@ -0,0 +1,189 @@
+package com.intellij.execution.console;
+
+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;
+import com.intellij.openapi.editor.ex.EditorMarkupModel;
+import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.ui.HintHint;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionListener;
+
+class ConsoleGutterComponent extends JComponent implements MouseMotionListener {
+ private static final TooltipGroup TOOLTIP_GROUP = new TooltipGroup("CONSOLE_GUTTER_TOOLTIP_GROUP", 0);
+ private static final int RIGHT_INSET = 6;
+
+ private int maxAnnotationWidth = 0;
+ private int myLastPreferredHeight = -1;
+ private final EditorImpl editor;
+
+ private final GutterContentProvider gutterContentProvider;
+
+ private int lastGutterToolTipLine = -1;
+
+ public ConsoleGutterComponent(@NotNull Editor editor, @NotNull GutterContentProvider provider) {
+ this.editor = (EditorImpl)editor;
+ gutterContentProvider = provider;
+ addListeners();
+
+ addMouseMotionListener(this);
+ }
+
+ private void addListeners() {
+ addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ if (!e.isPopupTrigger()) {
+ gutterContentProvider.doAction(getLineAtPoint(e.getPoint()), editor);
+ }
+ }
+ });
+ }
+
+ public void updateSize() {
+ int oldAnnotationsWidth = maxAnnotationWidth;
+ computeMaxAnnotationWidth();
+ if (oldAnnotationsWidth != maxAnnotationWidth || myLastPreferredHeight != editor.getPreferredHeight()) {
+ fireResized();
+ }
+ repaint();
+ }
+
+ private void fireResized() {
+ processComponentEvent(new ComponentEvent(this, ComponentEvent.COMPONENT_RESIZED));
+ }
+
+ private void computeMaxAnnotationWidth() {
+ if (!gutterContentProvider.hasText()) {
+ maxAnnotationWidth = 0;
+ return;
+ }
+
+ FontMetrics fontMetrics = editor.getFontMetrics(Font.PLAIN);
+ int lineCount = editor.getDocument().getLineCount();
+ gutterContentProvider.beforeUiComponentUpdate(editor);
+ int gutterSize = 0;
+ for (int i = 0; i < lineCount; i++) {
+ String text = gutterContentProvider.getText(i, editor);
+ if (text != null) {
+ gutterSize = Math.max(gutterSize, fontMetrics.stringWidth(text));
+ }
+ }
+ maxAnnotationWidth = gutterSize + RIGHT_INSET;
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ myLastPreferredHeight = editor.getPreferredHeight();
+ return new Dimension(maxAnnotationWidth, myLastPreferredHeight);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ ((ApplicationImpl)ApplicationManager.getApplication()).editorPaintStart();
+ try {
+ Rectangle clip = g.getClipBounds();
+ if (clip.height < 0 || maxAnnotationWidth == 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;
+ }
+
+ gutterContentProvider.beforeUiComponentUpdate(editor);
+
+ 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 - RIGHT_INSET - fontMetrics.stringWidth(text), y);
+ }
+ y += lineHeight;
+ }
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ TooltipController.getInstance().cancelTooltips();
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ int line = getLineAtPoint(e.getPoint());
+ if (line == lastGutterToolTipLine) {
+ return;
+ }
+
+ TooltipController controller = TooltipController.getInstance();
+ if (lastGutterToolTipLine != -1) {
+ controller.cancelTooltip(TOOLTIP_GROUP, e, true);
+ }
+
+ String toolTip = gutterContentProvider.getToolTip(line, editor);
+ setCursor(toolTip == null ? Cursor.getDefaultCursor() : Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ if (toolTip == null) {
+ lastGutterToolTipLine = -1;
+ controller.cancelTooltip(TOOLTIP_GROUP, e, false);
+ }
+ else {
+ lastGutterToolTipLine = line;
+ RelativePoint showPoint = new RelativePoint(this, e.getPoint());
+ controller.showTooltipByMouseMove(editor,
+ showPoint,
+ ((EditorMarkupModel)editor.getMarkupModel()).getErrorStripTooltipRendererProvider().calcTooltipRenderer(toolTip),
+ false,
+ TOOLTIP_GROUP,
+ new HintHint(this, e.getPoint()).setAwtTooltip(true));
+ }
+ }
+
+ private int getLineAtPoint(@NotNull Point clickPoint) {
+ return editor.yPositionToLogicalLine(clickPoint.y);
+ }
+}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
index ac25e69..6c0bfff 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleHistoryController.java
@@ -77,8 +77,7 @@
public ConsoleHistoryController(@NotNull String type, @Nullable String persistenceId,
@NotNull LanguageConsoleImpl console, @NotNull ConsoleHistoryModel model) {
- String id = persistenceId == null || StringUtil.isEmpty(persistenceId) ? console.getProject().getPresentableUrl() : persistenceId;
- myHelper = new ModelHelper(type, id, model);
+ myHelper = new ModelHelper(type, StringUtil.isEmpty(persistenceId) ? console.getProject().getPresentableUrl() : persistenceId, model);
myConsole = console;
}
@@ -419,7 +418,7 @@
try {
serializer.setProperty("http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " ");
}
- catch (Exception e) {
+ catch (Exception ignored) {
// not recognized
}
serializer.setOutput(os = new SafeFileOutputStream(file), CharsetToolkit.UTF8);
@@ -432,7 +431,7 @@
try {
os.close();
}
- catch (Exception e) {
+ catch (Exception ignored) {
// nothing
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/console/ConsoleIconGutterComponent.java b/platform/lang-impl/src/com/intellij/execution/console/ConsoleIconGutterComponent.java
new file mode 100644
index 0000000..144ae3f
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/console/ConsoleIconGutterComponent.java
@@ -0,0 +1,96 @@
+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.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 {
+ static final int ICON_AREA_WIDTH = 15;
+
+ 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;
+ }
+
+ 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(ICON_AREA_WIDTH, 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;
+ }
+
+ gutterContentProvider.beforeUiComponentUpdate(editor);
+
+ 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/FoldLinesLikeThis.java b/platform/lang-impl/src/com/intellij/execution/console/FoldLinesLikeThis.java
index ce90aa7..0f0ddb8 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/FoldLinesLikeThis.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/FoldLinesLikeThis.java
@@ -5,7 +5,6 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.editor.Document;
diff --git a/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java b/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java
new file mode 100644
index 0000000..af7d34c
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/console/GutterContentProvider.java
@@ -0,0 +1,30 @@
+package com.intellij.execution.console;
+
+import com.intellij.openapi.editor.Editor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+
+public abstract class GutterContentProvider {
+ public void beforeUiComponentUpdate(@NotNull Editor editor) {
+ }
+
+ public void documentCleared(@NotNull Editor editor) {
+ }
+
+ public void beforeEvaluate(@NotNull Editor editor) {
+ }
+
+ public abstract boolean hasText();
+
+ @Nullable
+ public abstract String getText(int line, @NotNull Editor editor);
+
+ @Nullable
+ public abstract String getToolTip(int line, @NotNull Editor editor);
+
+ public abstract void doAction(int line, @NotNull Editor editor);
+
+ public abstract void drawIcon(int line, @NotNull Graphics g, int y, @NotNull Editor editor);
+}
\ 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
new file mode 100644
index 0000000..75e4520
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleBuilder.java
@@ -0,0 +1,199 @@
+package com.intellij.execution.console;
+
+import com.intellij.execution.process.ProcessHandler;
+import com.intellij.lang.Language;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.colors.EditorColors;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.ex.DocumentBulkUpdateListener;
+import com.intellij.openapi.editor.ex.DocumentEx;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class LanguageConsoleBuilder {
+ private final LanguageConsoleImpl myConsole;
+ private LanguageConsoleView myConsoleView;
+ private Condition<LanguageConsoleImpl> myExecutionEnabled = Conditions.alwaysTrue();
+
+ public LanguageConsoleBuilder(@NotNull LanguageConsoleView consoleView) {
+ myConsole = consoleView.getConsole();
+ myConsoleView = consoleView;
+ }
+
+ public LanguageConsoleBuilder(@NotNull Project project, @NotNull Language language) {
+ myConsole = new MyLanguageConsole(project, language);
+ }
+
+ public LanguageConsoleBuilder processHandler(@NotNull ProcessHandler processHandler) {
+ myExecutionEnabled = new ProcessBackedExecutionEnabledCondition(processHandler);
+ return this;
+ }
+
+ public LanguageConsoleBuilder executionEnabled(@NotNull Condition<LanguageConsoleImpl> condition) {
+ myExecutionEnabled = condition;
+ return this;
+ }
+
+ public LanguageConsoleBuilder initActions(@NotNull BaseConsoleExecuteActionHandler executeActionHandler, @NotNull String historyType) {
+ ensureConsoleViewCreated();
+
+ ConsoleExecuteAction action = new ConsoleExecuteAction(myConsoleView, executeActionHandler, ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID, myExecutionEnabled);
+ action.registerCustomShortcutSet(action.getShortcutSet(), myConsole.getConsoleEditor().getComponent());
+
+ new ConsoleHistoryController(historyType, null, myConsole, executeActionHandler.getConsoleHistoryModel()).install();
+ return this;
+ }
+
+ public LanguageConsoleBuilder historyAnnotation(@Nullable GutterContentProvider provider) {
+ ((MyLanguageConsole)myConsole).gutterContentProvider = provider;
+ return this;
+ }
+
+ private void ensureConsoleViewCreated() {
+ if (myConsoleView == null) {
+ myConsoleView = new LanguageConsoleViewImpl(myConsole, true);
+ }
+ }
+
+ public LanguageConsoleView build() {
+ myConsole.setShowSeparatorLine(false);
+ myConsole.initComponents();
+
+ ensureConsoleViewCreated();
+ return myConsoleView;
+ }
+
+ public static class ProcessBackedExecutionEnabledCondition implements Condition<LanguageConsoleImpl> {
+ private final ProcessHandler myProcessHandler;
+
+ public ProcessBackedExecutionEnabledCondition(ProcessHandler myProcessHandler) {
+ this.myProcessHandler = myProcessHandler;
+ }
+
+ @Override
+ public boolean value(LanguageConsoleImpl console) {
+ return !myProcessHandler.isProcessTerminated();
+ }
+ }
+
+ private static class GutteredEditorPanel extends JPanel {
+ private final EditorEx editor;
+
+ public GutteredEditorPanel(EditorEx editor) {
+ super(new BorderLayout());
+
+ this.editor = editor;
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ super.paint(g);
+
+ Rectangle clip = g.getClipBounds();
+ if (clip.height < 0) {
+ return;
+ }
+
+ int lineHeight = editor.getLineHeight();
+ int startLine = clip.y / lineHeight;
+ int endLine = Math.min(((clip.y + clip.height) / lineHeight) + 1, ((EditorImpl)editor).getVisibleLineCount());
+ if (startLine >= endLine) {
+ return;
+ }
+
+ int y = ((startLine + 1) * lineHeight);
+ g.setColor(editor.getColorsScheme().getColor(EditorColors.INDENT_GUIDE_COLOR));
+ for (int i = startLine; i < endLine; i++) {
+ g.drawLine(ConsoleIconGutterComponent.ICON_AREA_WIDTH, y, clip.width, y);
+ y += lineHeight;
+ }
+ }
+ }
+
+ private static class MyLanguageConsole extends LanguageConsoleImpl {
+ @Nullable
+ private GutterContentProvider gutterContentProvider;
+
+ public MyLanguageConsole(@NotNull Project project, @NotNull Language language) {
+ super(project, language.getDisplayName() + " Console", language, false);
+ }
+
+ @Override
+ protected void setupEditorDefault(@NotNull EditorEx editor) {
+ super.setupEditorDefault(editor);
+
+ if (editor == getConsoleEditor()) {
+ // todo consider to fix platform
+ editor.getSettings().setAdditionalLinesCount(1);
+ }
+ else if (gutterContentProvider != null) {
+ JScrollPane scrollPane = editor.getScrollPane();
+ JPanel panel = new GutteredEditorPanel(editor);
+
+ final ConsoleIconGutterComponent lineStartGutter = new ConsoleIconGutterComponent(editor, gutterContentProvider);
+ panel.add(lineStartGutter, BorderLayout.LINE_START);
+
+ panel.add(scrollPane.getViewport().getView(), BorderLayout.CENTER);
+
+ final ConsoleGutterComponent lineEndGutter = new ConsoleGutterComponent(editor, gutterContentProvider);
+ panel.add(lineEndGutter, BorderLayout.LINE_END);
+
+ scrollPane.setViewportView(panel);
+
+ getProject().getMessageBus().connect(this).subscribe(DocumentBulkUpdateListener.TOPIC, new DocumentBulkUpdateListener.Adapter() {
+ @Override
+ public void updateFinished(@NotNull Document document) {
+ if (document.getTextLength() == 0) {
+ gutterContentProvider.documentCleared(getHistoryViewer());
+ }
+ lineStartGutter.updateSize();
+ lineEndGutter.updateSize();
+ }
+ });
+
+ editor.getDocument().addDocumentListener(new DocumentAdapter() {
+ @Override
+ public void documentChanged(DocumentEvent event) {
+ EditorEx editor = getHistoryViewer();
+ DocumentEx document = editor.getDocument();
+ if (document.isInBulkUpdate()) {
+ return;
+ }
+
+ if (document.getTextLength() > 0) {
+ int startDocLine = document.getLineNumber(event.getOffset());
+ int endDocLine = document.getLineNumber(event.getOffset() + event.getNewLength());
+ if (event.getOldLength() > event.getNewLength() || startDocLine != endDocLine || StringUtil.indexOf(event.getOldFragment(), '\n') != -1) {
+ lineStartGutter.updateSize();
+ lineEndGutter.updateSize();
+ }
+ }
+ else if (event.getOldLength() > 0) {
+ gutterContentProvider.documentCleared(editor);
+ }
+ }
+ });
+ }
+ }
+
+ @Override
+ protected void doAddPromptToHistory() {
+ if (gutterContentProvider == null) {
+ super.doAddPromptToHistory();
+ }
+ else {
+ gutterContentProvider.beforeEvaluate(getHistoryViewer());
+ }
+ }
+ }
+}
\ No newline at end of file
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 5be3b60..fed2716 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
@@ -46,13 +46,11 @@
import com.intellij.openapi.editor.impl.EditorFactoryImpl;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.fileEditor.*;
-import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.util.text.StringUtilRt;
@@ -65,10 +63,9 @@
import com.intellij.ui.SideBorder;
import com.intellij.util.FileContentUtil;
import com.intellij.util.ObjectUtils;
+import com.intellij.util.SingleAlarm;
import com.intellij.util.ui.AbstractLayoutManager;
import com.intellij.util.ui.UIUtil;
-import com.intellij.util.ui.update.MergingUpdateQueue;
-import com.intellij.util.ui.update.Update;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -83,7 +80,7 @@
/**
* @author Gregory.Shrago
- * In case of REPL consider to use {@link com.intellij.execution.runners.LanguageConsoleBuilder}
+ * In case of REPL consider to use {@link LanguageConsoleBuilder}
*/
public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
private static final int SEPARATOR_THICKNESS = 1;
@@ -104,7 +101,7 @@
private Editor myCurrentEditor;
private final AtomicBoolean myForceScrollToEnd = new AtomicBoolean(false);
- private final MergingUpdateQueue myUpdateQueue;
+ private final SingleAlarm myUpdateQueue;
private Runnable myUiUpdateRunnable;
private boolean myShowSeparatorLine = true;
@@ -141,8 +138,18 @@
myConsoleEditor.addFocusListener(myFocusListener);
myCurrentEditor = myConsoleEditor;
myHistoryViewer = (EditorEx)editorFactory.createViewer(((EditorFactoryImpl)editorFactory).createDocument(true), myProject);
- myUpdateQueue = new MergingUpdateQueue("ConsoleUpdateQueue", 300, true, null);
- Disposer.register(this, myUpdateQueue);
+ myUpdateQueue = new SingleAlarm(new Runnable() {
+ @Override
+ public void run() {
+ if (isConsoleEditorEnabled()) {
+ myPanel.revalidate();
+ myPanel.repaint();
+ }
+ if (myUiUpdateRunnable != null) {
+ myUiUpdateRunnable.run();
+ }
+ }
+ }, 300, this);
// action shortcuts are not yet registered
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -178,8 +185,7 @@
@Override
public void componentResized(ComponentEvent e) {
if (myForceScrollToEnd.getAndSet(false)) {
- final JScrollBar scrollBar = myHistoryViewer.getScrollPane().getVerticalScrollBar();
- scrollBar.setValue(scrollBar.getMaximum());
+ scrollHistoryToEnd();
}
}
@@ -192,10 +198,12 @@
}
public void setConsoleEditorEnabled(boolean consoleEditorEnabled) {
- if (isConsoleEditorEnabled() == consoleEditorEnabled) return;
- final FileEditorManagerEx fileManager = FileEditorManagerEx.getInstanceEx(getProject());
+ if (isConsoleEditorEnabled() == consoleEditorEnabled) {
+ return;
+ }
+
if (consoleEditorEnabled) {
- fileManager.closeFile(myVirtualFile);
+ FileEditorManager.getInstance(getProject()).closeFile(myVirtualFile);
myPanel.removeAll();
myPanel.add(myHistoryViewer.getComponent());
myPanel.add(myConsoleEditor.getComponent());
@@ -217,17 +225,18 @@
private void setupComponents() {
setupEditorDefault(myConsoleEditor);
setupEditorDefault(myHistoryViewer);
- myConsoleEditor.addEditorMouseListener(EditorActionUtil.createEditorPopupHandler(IdeActions.GROUP_CONSOLE_EDITOR_POPUP));
+
//noinspection PointlessBooleanExpression,ConstantConditions
if (SEPARATOR_THICKNESS > 0 && myShowSeparatorLine) {
myHistoryViewer.getComponent().setBorder(new SideBorder(JBColor.LIGHT_GRAY, SideBorder.BOTTOM));
}
myHistoryViewer.getComponent().setMinimumSize(new Dimension(0, 0));
myHistoryViewer.getComponent().setPreferredSize(new Dimension(0, 0));
- myConsoleEditor.getSettings().setAdditionalLinesCount(2);
- myConsoleEditor.setHighlighter(EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, myVirtualFile));
myHistoryViewer.setCaretEnabled(false);
- myConsoleEditor.setHorizontalScrollbarVisible(true);
+
+ myConsoleEditor.addEditorMouseListener(EditorActionUtil.createEditorPopupHandler(IdeActions.GROUP_CONSOLE_EDITOR_POPUP));
+ myConsoleEditor.setHighlighter(EditorHighlighterFactory.getInstance().createEditorHighlighter(myProject, myVirtualFile));
+
final VisibleAreaListener areaListener = new VisibleAreaListener() {
@Override
public void visibleAreaChanged(VisibleAreaEvent e) {
@@ -289,7 +298,7 @@
queueUiUpdate(true);
}
- private static void setupEditorDefault(@NotNull EditorEx editor) {
+ protected void setupEditorDefault(@NotNull EditorEx editor) {
ConsoleViewUtil.setupConsoleEditor(editor, false, false);
editor.getContentComponent().setFocusCycleRoot(false);
editor.setHorizontalScrollbarVisible(false);
@@ -297,7 +306,7 @@
editor.setBorder(null);
final EditorSettings editorSettings = editor.getSettings();
- editorSettings.setAdditionalLinesCount(0);
+ editorSettings.setAdditionalLinesCount(myHistoryViewer == editor ? 0 : 2);
editorSettings.setAdditionalColumnsCount(1);
editorSettings.setRightMarginShown(false);
}
@@ -311,6 +320,7 @@
myUpdateQueue.flush();
}
+ @SuppressWarnings("UnusedDeclaration")
@NotNull
public LightVirtualFile getHistoryFile() {
return myHistoryFile;
@@ -384,7 +394,7 @@
}
public void setTitle(@NotNull String title) {
- this.myTitle = title;
+ myTitle = title;
}
public void printToHistory(@NotNull CharSequence text, @NotNull TextAttributes attributes) {
@@ -399,30 +409,26 @@
}
protected void addTextToHistory(@Nullable CharSequence text, @Nullable TextAttributes attributes) {
- if (StringUtil.isEmpty(text)) {
+ if (StringUtil.isEmpty(text) || attributes == null) {
return;
}
Document history = myHistoryViewer.getDocument();
MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true);
int offset = appendToHistoryDocument(history, text);
- if (attributes == null) return;
markupModel.addRangeHighlighter(offset, offset + text.length(), HighlighterLayer.SYNTAX, attributes, HighlighterTargetArea.EXACT_RANGE);
}
- public String addCurrentToHistory(final TextRange textRange, final boolean erase, final boolean preserveMarkup) {
+ public String addCurrentToHistory(@NotNull TextRange textRange, boolean erase, boolean preserveMarkup) {
return addToHistoryInner(textRange, myConsoleEditor, erase, preserveMarkup);
}
- public String addToHistory(final TextRange textRange, final EditorEx editor, final boolean preserveMarkup) {
+ public String addToHistory(@NotNull TextRange textRange, @NotNull EditorEx editor, boolean preserveMarkup) {
return addToHistoryInner(textRange, editor, false, preserveMarkup);
}
@NotNull
- protected String addToHistoryInner(@NotNull final TextRange textRange,
- @NotNull final EditorEx editor,
- final boolean erase,
- final boolean preserveMarkup) {
+ protected String addToHistoryInner(@NotNull final TextRange textRange, @NotNull final EditorEx editor, boolean erase, final boolean preserveMarkup) {
String result = ApplicationManager.getApplication().runReadAction(new Computable<String>() {
@Override
public String compute() {
@@ -451,13 +457,15 @@
private void scrollHistoryToEnd() {
final int lineCount = myHistoryViewer.getDocument().getLineCount();
- if (lineCount == 0) return;
+ if (lineCount == 0) {
+ return;
+ }
myHistoryViewer.getCaretModel().moveToOffset(myHistoryViewer.getDocument().getLineStartOffset(lineCount - 1), false);
myHistoryViewer.getScrollingModel().scrollToCaret(ScrollType.MAKE_VISIBLE);
}
@NotNull
- protected String addTextRangeToHistory(@NotNull TextRange textRange, @NotNull final EditorEx consoleEditor, boolean preserveMarkup) {
+ protected String addTextRangeToHistory(@NotNull TextRange textRange, @NotNull EditorEx consoleEditor, boolean preserveMarkup) {
final Document history = myHistoryViewer.getDocument();
final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true);
doAddPromptToHistory();
@@ -542,21 +550,9 @@
return myPanel;
}
- public void queueUiUpdate(final boolean forceScrollToEnd) {
+ public void queueUiUpdate(boolean forceScrollToEnd) {
myForceScrollToEnd.compareAndSet(false, forceScrollToEnd);
- myUpdateQueue.queue(new Update("UpdateUi") {
- @Override
- public void run() {
- if (Disposer.isDisposed(LanguageConsoleImpl.this)) return;
- if (isConsoleEditorEnabled()) {
- myPanel.revalidate();
- myPanel.repaint();
- }
- if (myUiUpdateRunnable != null) {
- ApplicationManager.getApplication().runReadAction(myUiUpdateRunnable);
- }
- }
- });
+ myUpdateQueue.request();
}
@Override
@@ -588,10 +584,16 @@
final FileEditorManagerAdapter fileEditorListener = new FileEditorManagerAdapter() {
@Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
- if (!Comparing.equal(file, myVirtualFile) || myConsoleEditor == null) return;
+ if (myConsoleEditor == null || !Comparing.equal(file, myVirtualFile)) {
+ return;
+ }
+
Editor selectedTextEditor = source.getSelectedTextEditor();
for (FileEditor fileEditor : source.getAllEditors(file)) {
- if (!(fileEditor instanceof TextEditor)) continue;
+ if (!(fileEditor instanceof TextEditor)) {
+ continue;
+ }
+
final EditorEx editor = (EditorEx)((TextEditor)fileEditor).getEditor();
editor.addFocusListener(myFocusListener);
if (selectedTextEditor == editor) { // already focused
@@ -662,17 +664,21 @@
@Override
public void layoutContainer(@NotNull final Container parent) {
final int componentCount = parent.getComponentCount();
- if (componentCount == 0) return;
+ if (componentCount == 0) {
+ return;
+ }
+
final EditorEx history = myHistoryViewer;
final EditorEx editor = componentCount == 2 ? myConsoleEditor : null;
-
if (editor == null) {
parent.getComponent(0).setBounds(parent.getBounds());
return;
}
final Dimension panelSize = parent.getSize();
- if (panelSize.getHeight() <= 0) return;
+ if (panelSize.getHeight() <= 0) {
+ return;
+ }
final Dimension historySize = history.getContentSize();
final Dimension editorSize = editor.getContentSize();
final Dimension newEditorSize = new Dimension();
@@ -685,7 +691,9 @@
history.getSettings().setAdditionalColumnsCount(2 + (width - historySize.width) / EditorUtil.getSpaceWidth(Font.PLAIN, history));
// deal with height
- if (historySize.width == 0) historySize.height = 0;
+ if (historySize.width == 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);
diff --git a/platform/lang-impl/src/com/intellij/execution/filters/impl/HyperlinkInfoFactoryImpl.java b/platform/lang-impl/src/com/intellij/execution/filters/impl/HyperlinkInfoFactoryImpl.java
new file mode 100644
index 0000000..f8a8000
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/filters/impl/HyperlinkInfoFactoryImpl.java
@@ -0,0 +1,36 @@
+/*
+ * 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.execution.filters.impl;
+
+import com.intellij.execution.filters.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class HyperlinkInfoFactoryImpl extends HyperlinkInfoFactory {
+
+ @NotNull
+ @Override
+ public HyperlinkInfo createMultipleFilesHyperlinkInfo(@NotNull List<VirtualFile> files,
+ int line, @NotNull Project project) {
+ return new MultipleFilesHyperlinkInfo(files, line, project);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/execution/filters/impl/MultipleFilesHyperlinkInfo.java b/platform/lang-impl/src/com/intellij/execution/filters/impl/MultipleFilesHyperlinkInfo.java
new file mode 100644
index 0000000..36dc51e
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/execution/filters/impl/MultipleFilesHyperlinkInfo.java
@@ -0,0 +1,119 @@
+/*
+ * 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.execution.filters.impl;
+
+import com.intellij.execution.filters.FileHyperlinkInfo;
+import com.intellij.execution.filters.HyperlinkInfoBase;
+import com.intellij.execution.filters.OpenFileHyperlinkInfo;
+import com.intellij.ide.util.gotoByName.GotoFileCellRenderer;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author nik
+*/
+class MultipleFilesHyperlinkInfo extends HyperlinkInfoBase implements FileHyperlinkInfo {
+ private final List<VirtualFile> myVirtualFiles;
+ private final int myLineNumber;
+ private final Project myProject;
+
+ public MultipleFilesHyperlinkInfo(@NotNull List<VirtualFile> virtualFiles, int lineNumber, @NotNull Project project) {
+ myVirtualFiles = virtualFiles;
+ myLineNumber = lineNumber;
+ myProject = project;
+ }
+
+ @Override
+ public void navigate(@NotNull final Project project, @Nullable RelativePoint hyperlinkLocationPoint) {
+ List<PsiFile> currentFiles = new ArrayList<PsiFile>();
+
+ AccessToken accessToken = ReadAction.start();
+ try {
+ for (VirtualFile file : myVirtualFiles) {
+ if (!file.isValid()) continue;
+
+ PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
+ if (psiFile != null) {
+ PsiElement navigationElement = psiFile.getNavigationElement(); // Sources may be downloaded.
+ if (navigationElement instanceof PsiFile) {
+ currentFiles.add((PsiFile)navigationElement);
+ continue;
+ }
+ currentFiles.add(psiFile);
+ }
+ }
+ }
+ finally {
+ accessToken.finish();
+ }
+
+ if (currentFiles.isEmpty()) return;
+
+ if (currentFiles.size() == 1) {
+ new OpenFileHyperlinkInfo(myProject, currentFiles.get(0).getVirtualFile(), myLineNumber).navigate(project);
+ }
+ else {
+ final JBList list = new JBList(currentFiles);
+ int width = WindowManager.getInstance().getFrame(project).getSize().width;
+ list.setCellRenderer(new GotoFileCellRenderer(width));
+ JBPopup popup = JBPopupFactory.getInstance().createListPopupBuilder(list)
+ .setTitle("Choose Target File")
+ .setItemChoosenCallback(new Runnable() {
+ @Override
+ public void run() {
+ VirtualFile file = ((PsiFile)list.getSelectedValue()).getVirtualFile();
+ new OpenFileHyperlinkInfo(myProject, file, myLineNumber).navigate(project);
+ }
+ })
+ .createPopup();
+ if (hyperlinkLocationPoint != null) {
+ popup.show(hyperlinkLocationPoint);
+ }
+ else {
+ popup.showInFocusCenter();
+ }
+ }
+ }
+
+ @Nullable
+ @Override
+ public OpenFileDescriptor getDescriptor() {
+ VirtualFile file = getPreferredFile();
+ return file != null ? new OpenFileDescriptor(myProject, file, myLineNumber, 0) : null;
+ }
+
+ @Nullable
+ private VirtualFile getPreferredFile() {
+ return ContainerUtil.getFirstItem(myVirtualFiles);
+ }
+}
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 154d1e8..9eed96f 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.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.
@@ -65,6 +65,7 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.ui.EditorNotificationPanel;
+import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Alarm;
import com.intellij.util.Consumer;
import com.intellij.util.EditorPopupHandler;
@@ -78,7 +79,6 @@
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.*;
@@ -528,7 +528,7 @@
}
@Override
- public void print(String s, final ConsoleViewContentType contentType) {
+ public void print(@NotNull String s, @NotNull ConsoleViewContentType contentType) {
if (myInputMessageFilter == null) {
printHyperlink(s, contentType, null);
return;
@@ -657,6 +657,10 @@
final int oldLineCount = document.getLineCount();
final boolean isAtEndOfDocument = myEditor.getCaretModel().getOffset() == document.getTextLength();
boolean cycleUsed = myBuffer.isUseCyclicBuffer() && document.getTextLength() + text.length() > myBuffer.getCyclicBufferSize();
+ if (cycleUsed) {
+ clearHyperlinkAndFoldings();
+ }
+
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
@@ -706,21 +710,14 @@
myPsiDisposedCheck.performCheck();
final int newLineCount = document.getLineCount();
if (cycleUsed) {
- clearHyperlinkAndFoldings();
if (!myInSpareTimeUpdate) {
myInSpareTimeUpdate = true;
- final EditorNotificationPanel comp = new EditorNotificationPanel() {
- {
- myLabel.setIcon(AllIcons.General.ExclMark);
- myLabel.setText("Too much output to process");
- }
- };
+ final EditorNotificationPanel comp = new EditorNotificationPanel().text("Too much output to process").icon(AllIcons.General.ExclMark);
add(comp, BorderLayout.NORTH);
performWhenNoDeferredOutput(new Runnable() {
@Override
public void run() {
try {
- myHyperlinks.clearHyperlinks();
clearHyperlinkAndFoldings();
highlightHyperlinksAndFoldings(0, document.getLineCount() - 1);
}
@@ -742,15 +739,18 @@
}
private void clearHyperlinkAndFoldings() {
- for (Iterator<RangeHighlighter> it = myHyperlinks.getHyperlinks().keySet().iterator(); it.hasNext();) {
- if (!it.next().isValid()) {
- it.remove();
- }
- }
+ myHyperlinks.clearHyperlinks();
+ myEditor.getMarkupModel().removeAllHighlighters();
myPendingFoldRegions.clear();
myFolding.clear();
myFoldingAlarm.cancelAllRequests();
+ myEditor.getFoldingModel().runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ myEditor.getFoldingModel().clearFoldRegions();
+ }
+ });
cancelHeavyAlarm();
}
@@ -922,7 +922,14 @@
if (group == null) {
group = (ActionGroup)actionManager.getAction(CONSOLE_VIEW_POPUP_MENU);
}
- final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_POPUP, group);
+ final ConsoleActionsPostProcessor[] postProcessors = Extensions.getExtensions(ConsoleActionsPostProcessor.EP_NAME);
+ AnAction[] result = group.getChildren(null);
+
+ for (ConsoleActionsPostProcessor postProcessor : postProcessors) {
+ result = postProcessor.postProcessPopupActions(this, result);
+ }
+ final DefaultActionGroup processedGroup = new DefaultActionGroup(result);
+ final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.EDITOR_POPUP, processedGroup);
menu.getComponent().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
}
@@ -1064,9 +1071,6 @@
final int lEnd = line - 1;
int lStart = lEnd;
while (prevFolding.equals(myFolding.get(lStart - 1))) lStart--;
- if (lStart == lEnd) {
- return;
- }
for (int i = lStart; i <= lEnd; i++) {
myFolding.remove(i);
@@ -1127,6 +1131,7 @@
private class MyHighlighter extends DocumentAdapter implements EditorHighlighter {
private HighlighterClient myEditor;
+ @NotNull
@Override
public HighlighterIterator createIterator(final int startOffset) {
final int startIndex = ConsoleUtil.findTokenInfoIndexByOffset(myTokens, startOffset);
@@ -1181,17 +1186,17 @@
}
@Override
- public void setText(final CharSequence text) {
+ public void setText(@NotNull final CharSequence text) {
}
@Override
- public void setEditor(final HighlighterClient editor) {
+ public void setEditor(@NotNull final HighlighterClient editor) {
LOG.assertTrue(myEditor == null, "Highlighters cannot be reused with different editors");
myEditor = editor;
}
@Override
- public void setColorScheme(EditorColorsScheme scheme) {
+ public void setColorScheme(@NotNull EditorColorsScheme scheme) {
}
}
@@ -1263,15 +1268,7 @@
private static class PasteHandler extends ConsoleAction {
@Override
public void execute(final ConsoleViewImpl consoleView, final DataContext context) {
- final Transferable content = CopyPasteManager.getInstance().getContents();
- if (content == null) return;
- String s = null;
- try {
- s = (String)content.getTransferData(DataFlavor.stringFlavor);
- }
- catch (Exception e) {
- consoleView.getToolkit().beep();
- }
+ String s = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
if (s == null) return;
ApplicationManager.getApplication().assertIsDispatchThread();
Editor editor = consoleView.myEditor;
@@ -1384,10 +1381,18 @@
return EditorHyperlinkSupport.getNextOccurrence(myEditor, hyperlinks.getHyperlinks().keySet(), delta, new Consumer<RangeHighlighter>() {
@Override
public void consume(RangeHighlighter next) {
- scrollTo(next.getStartOffset());
+ int offset = next.getStartOffset();
+ scrollTo(offset);
final HyperlinkInfo hyperlinkInfo = hyperlinks.getHyperlinks().get(next);
if (hyperlinkInfo != null) {
- hyperlinkInfo.navigate(myProject);
+ if (hyperlinkInfo instanceof HyperlinkInfoBase) {
+ VisualPosition position = myEditor.offsetToVisualPosition(offset);
+ Point point = myEditor.visualPositionToXY(new VisualPosition(position.getLine() + 1, position.getColumn()));
+ ((HyperlinkInfoBase)hyperlinkInfo).navigate(myProject, new RelativePoint(myEditor.getContentComponent(), point));
+ }
+ else {
+ hyperlinkInfo.navigate(myProject);
+ }
}
}
});
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
index 0eae2ad..d984ad2 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/ExecutionManagerImpl.java
@@ -299,16 +299,21 @@
private void restartRunProfile(@NotNull final Project project,
- @Nullable final DataContext context,
- @Nullable ProgramRunner r,
- @Nullable final RunProfile runProfile,
- @Nullable final RunnerSettings runnerSettings,
- @Nullable final ConfigurationPerRunnerSettings configurationPerRunnerSettings,
- @NotNull final Executor executor,
- @NotNull final ExecutionTarget target,
- @Nullable final RunnerAndConfigurationSettings configuration,
- @Nullable final RunContentDescriptor currentDescriptor) {
- final ProgramRunner runner = r != null ? r : ProgramRunnerUtil.getRunner(executor.getId(), configuration);
+ @Nullable final DataContext context,
+ @Nullable ProgramRunner r,
+ @Nullable final RunProfile runProfile,
+ @Nullable final RunnerSettings runnerSettings,
+ @Nullable final ConfigurationPerRunnerSettings configurationPerRunnerSettings,
+ @NotNull final Executor executor,
+ @NotNull final ExecutionTarget target,
+ @Nullable final RunnerAndConfigurationSettings configuration,
+ @Nullable final RunContentDescriptor currentDescriptor) {
+ final ProgramRunner runner = r != null ?
+ r :
+ RunnerRegistry.getInstance().getRunner(executor.getId(),
+ configuration != null && configuration.getConfiguration() != null
+ ? configuration.getConfiguration()
+ : runProfile);
if (configuration != null && runner == null) {
LOG.error("Cannot find runner for " + configuration.getName());
return;
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java
index f8b5143..59546f1 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunConfigurable.java
@@ -27,10 +27,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.Splitter;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.ui.popup.ListPopup;
-import com.intellij.openapi.ui.popup.ListPopupStep;
-import com.intellij.openapi.ui.popup.PopupStep;
+import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
@@ -399,11 +396,6 @@
myRightPanel.add(((SingleConfigurationConfigurable)configurable).getValidationComponent(), BorderLayout.SOUTH);
}
- if (configurable instanceof SingleConfigurationConfigurable) {
- RunManagerEx.getInstanceEx(myProject)
- .invalidateConfigurationIcon((RunnerAndConfigurationSettings)((SingleConfigurationConfigurable)configurable).getSettings());
- }
-
setupDialogBounds();
}
@@ -1107,7 +1099,7 @@
@Override
@NotNull
public String getTextFor(final ConfigurationType type) {
- return type != null ? type.getDisplayName() : "(" + hiddenCount + " more items)";
+ return type != null ? type.getDisplayName() : hiddenCount + " items more (irrelevant)...";
}
@Override
@@ -1199,7 +1191,7 @@
applicableTypes.add(type);
}
}
- if (applicableTypes.size() < allTypes.length - 1) {
+ if (applicableTypes.size() < allTypes.length - 3) {
return applicableTypes;
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java b/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java
index bcf2f61..71e205c 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunDialog.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.
@@ -38,7 +38,7 @@
private final Project myProject;
private final RunConfigurable myConfigurable;
private JComponent myCenterPanel;
- @NonNls public static String HELP_ID = "reference.dialogs.rundebug";
+ @NonNls public static final String HELP_ID = "reference.dialogs.rundebug";
private final Executor myExecutor;
public RunDialog(final Project project, final Executor executor) {
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
index 14b8333..d09a236 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunManagerImpl.java
@@ -16,6 +16,7 @@
package com.intellij.execution.impl;
+import com.intellij.ProjectTopics;
import com.intellij.execution.*;
import com.intellij.execution.configurations.*;
import com.intellij.ide.util.PropertiesComponent;
@@ -23,6 +24,8 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootAdapter;
+import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.UnknownFeaturesCollector;
import com.intellij.openapi.util.*;
import com.intellij.ui.IconDeferrer;
@@ -59,6 +62,8 @@
@Nullable private String mySelectedConfigurationId = null;
private Map<String, Icon> myIdToIcon = new HashMap<String, Icon>();
+ private Map<String, Long> myIconCheckTimes = new HashMap<String, Long>();
+ private Map<String, Long> myIconCalcTime = new HashMap<String, Long>();
@NonNls
protected static final String CONFIGURATION = "configuration";
@@ -85,6 +90,15 @@
myProject = project;
initConfigurationTypes();
+ myProject.getMessageBus().connect(myProject).subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+ @Override
+ public void rootsChanged(ModuleRootEvent event) {
+ RunnerAndConfigurationSettings configuration = getSelectedConfiguration();
+ if (configuration != null) {
+ myIconCheckTimes.remove(configuration.getUniqueID());//cache will be expired
+ }
+ }
+ });
}
// separate method needed for tests
@@ -411,7 +425,6 @@
mySharedConfigurations.remove(settings.getUniqueID());
myConfigurationToBeforeTasksMap.remove(settings.getConfiguration());
myRecentlyUsedTemporaries.remove(settings.getConfiguration());
- invalidateConfigurationIcon(configuration);
myDispatcher.getMulticaster().runConfigurationRemoved(configuration);
break;
}
@@ -430,9 +443,6 @@
@Override
public void setSelectedConfiguration(@Nullable RunnerAndConfigurationSettings settings) {
setSelectedConfigurationId(settings == null ? null : settings.getUniqueID());
- if (settings != null) {
- invalidateConfigurationIcon(settings);
- }
fireRunConfigurationSelected();
}
@@ -667,7 +677,15 @@
Collections.sort(sortedElements, comparator); // ensure templates are loaded first!
for (final Element element : sortedElements) {
- if (loadConfiguration(element, false) == null) {
+ RunnerAndConfigurationSettings configurationSettings = null;
+ try {
+ configurationSettings = loadConfiguration(element, false);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ continue;
+ }
+ if (configurationSettings == null) {
if (myUnknownElements == null) myUnknownElements = new ArrayList<Element>(2);
myUnknownElements.add(element);
}
@@ -765,6 +783,8 @@
mySelectedConfigurationId = null;
myLoadedSelectedConfigurationUniqueName = null;
myIdToIcon.clear();
+ myIconCheckTimes.clear();
+ myIconCalcTime.clear();
myRecentlyUsedTemporaries.clear();
fireRunConfigurationsRemoved(configurations);
}
@@ -873,7 +893,6 @@
if (tempConfiguration == null) return;
tempConfiguration.setTemporary(true);
- invalidateConfigurationIcon(tempConfiguration);
addConfiguration(tempConfiguration, isConfigurationShared(tempConfiguration),
getBeforeRunTasks(tempConfiguration.getConfiguration()), false);
@@ -926,7 +945,6 @@
}
public void makeStable(@NotNull RunnerAndConfigurationSettings settings) {
- invalidateConfigurationIcon(settings);
settings.setTemporary(false);
myRecentlyUsedTemporaries.remove(settings.getConfiguration());
if (!myOrder.isEmpty()) {
@@ -989,21 +1007,29 @@
}
@Override
- public void invalidateConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) {
- myIdToIcon.remove(settings.getUniqueID());
- }
-
- @Override
public Icon getConfigurationIcon(@NotNull final RunnerAndConfigurationSettings settings) {
final String uniqueID = settings.getUniqueID();
+ RunnerAndConfigurationSettings selectedConfiguration = getSelectedConfiguration();
+ String selectedId = selectedConfiguration != null ? selectedConfiguration.getUniqueID() : "";
+ if (selectedId.equals(uniqueID)) {
+ Long lastCheckTime = myIconCheckTimes.get(uniqueID);
+ Long calcTime = myIconCalcTime.get(uniqueID);
+ if (calcTime == null || calcTime<150) calcTime = 150L;
+ if (lastCheckTime == null || System.currentTimeMillis() - lastCheckTime > calcTime*10) {
+ myIdToIcon.remove(uniqueID);//cache has expired
+ }
+ }
Icon icon = myIdToIcon.get(uniqueID);
if (icon == null) {
- icon = IconDeferrer.getInstance().defer(settings.getConfiguration().getIcon(), Pair.create(myProject, settings),
- new Function<Pair<Project, RunnerAndConfigurationSettings>, Icon>() {
+ icon = IconDeferrer.getInstance().deferAutoUpdatable(settings.getConfiguration().getIcon(), myProject.hashCode() ^ settings.hashCode(),
+ new Function<Integer, Icon>() {
@Override
- public Icon fun(Pair<Project, RunnerAndConfigurationSettings> projectRunnerAndConfigurationSettingsPair) {
+ public Icon fun(Integer param) {
if (myProject.isDisposed()) return null;
+ myIconCalcTime.remove(uniqueID);
+ long startTime = System.currentTimeMillis();
+
Icon icon;
try {
settings.checkSettings();
@@ -1012,12 +1038,13 @@
catch (RuntimeConfigurationException e) {
icon = ProgramRunnerUtil.getConfigurationIcon(settings, true);
}
-
+ myIconCalcTime.put(uniqueID, System.currentTimeMillis() - startTime);
return icon;
}
});
myIdToIcon.put(uniqueID, icon);
+ myIconCheckTimes.put(uniqueID, System.currentTimeMillis());
}
return icon;
@@ -1151,7 +1178,6 @@
final RunnerAndConfigurationSettings settings = entry.getValue();
if (!settings.isTemplate() && isConfigurationShared(settings) && !existing.contains(settings.getUniqueID())) {
removed.add(settings);
- invalidateConfigurationIcon(settings);
it.remove();
}
}
@@ -1159,7 +1185,6 @@
}
public void fireRunConfigurationChanged(@NotNull RunnerAndConfigurationSettings settings) {
- invalidateConfigurationIcon(settings);
myDispatcher.getMulticaster().runConfigurationChanged(settings);
}
diff --git a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java
index 55bdd85..626f184 100644
--- a/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/impl/RunnerAndConfigurationSettingsImpl.java
@@ -21,10 +21,12 @@
import com.intellij.execution.runners.ProgramRunner;
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionException;
import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
+import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -63,7 +65,7 @@
@NonNls
private static final String EDIT_BEFORE_RUN = "editBeforeRun";
@NonNls
- private static final String SINGLETON = "singleton";
+ public static final String SINGLETON = "singleton";
/** for compatibility */
@@ -83,6 +85,7 @@
private boolean myTemporary;
private boolean myEditBeforeRun;
private boolean mySingleton;
+ private boolean myWasSingletonSpecifiedExplicitly;
private String myFolderName;
//private String myID = null;
@@ -199,16 +202,25 @@
myFolderName = element.getAttributeValue(FOLDER_NAME);
//assert myID == null: "myId must be null at readExternal() stage";
//myID = element.getAttributeValue(UNIQUE_ID, UUID.randomUUID().toString());
- // singleton is not configurable by user for template
- if (!myIsTemplate) {
- mySingleton = Boolean.valueOf(element.getAttributeValue(SINGLETON)).booleanValue();
- }
-
final ConfigurationFactory factory = getFactory(element);
if (factory == null) return;
+ myWasSingletonSpecifiedExplicitly = false;
if (myIsTemplate) {
mySingleton = factory.isConfigurationSingletonByDefault();
+ }
+ else {
+ String singletonStr = element.getAttributeValue(SINGLETON);
+ if (StringUtil.isEmpty(singletonStr)) {
+ mySingleton = factory.isConfigurationSingletonByDefault();
+ }
+ else {
+ myWasSingletonSpecifiedExplicitly = true;
+ mySingleton = Boolean.parseBoolean(singletonStr);
+ }
+ }
+
+ if (myIsTemplate) {
myConfiguration = myManager.getConfigurationTemplate(factory).getConfiguration();
} else {
final String name = element.getAttributeValue(NAME_ATTR);
@@ -274,7 +286,9 @@
//element.setAttribute(UNIQUE_ID, getUniqueID());
if (isEditBeforeRun()) element.setAttribute(EDIT_BEFORE_RUN, String.valueOf(true));
- if (isSingleton()) element.setAttribute(SINGLETON, String.valueOf(true));
+ if (myWasSingletonSpecifiedExplicitly || mySingleton != factory.isConfigurationSingletonByDefault()) {
+ element.setAttribute(SINGLETON, String.valueOf(mySingleton));
+ }
if (myTemporary) {
element.setAttribute(TEMPORARY_ATTRIBUTE, Boolean.toString(myTemporary));
}
@@ -393,7 +407,7 @@
return runnerSettings;
}
catch (AbstractMethodError e) {
- LOG.error("Update failed for: " + myConfiguration.getType().getDisplayName() + ", runner: " + runner.getRunnerId(), e);
+ LOG.error("Update failed for: " + myConfiguration.getType().getDisplayName() + ", runner: " + runner.getRunnerId(), new ExtensionException(runner.getClass()));
}
}
return myRunnerSettings.get(runner);
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
index 818ab3c..0a62ed8 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/AbstractConsoleRunnerWithHistory.java
@@ -19,9 +19,7 @@
import com.intellij.execution.ExecutionHelper;
import com.intellij.execution.ExecutionManager;
import com.intellij.execution.Executor;
-import com.intellij.execution.console.LanguageConsoleImpl;
-import com.intellij.execution.console.LanguageConsoleView;
-import com.intellij.execution.console.LanguageConsoleViewImpl;
+import com.intellij.execution.console.*;
import com.intellij.execution.executors.DefaultRunExecutor;
import com.intellij.execution.process.*;
import com.intellij.execution.ui.RunContentDescriptor;
@@ -122,7 +120,7 @@
@Override
public JComponent compute() {
final EditorEx editor = getLanguageConsole().getConsoleEditor();
- return editor != null ? editor.getContentComponent() : null;
+ return editor.getContentComponent();
}
});
contentDescriptor.setAutoFocusContent(isAutoFocusContent());
@@ -161,7 +159,7 @@
max = num;
}
}
- catch (Exception e) {
+ catch (Exception ignored) {
//skip
}
}
@@ -221,7 +219,7 @@
actionList.add(closeAction);
// run action
- actionList.add(createConsoleExecAction(getLanguageConsole(), myProcessHandler, myConsoleExecuteActionHandler));
+ actionList.add(createConsoleExecAction(myConsoleView, myProcessHandler, myConsoleExecuteActionHandler));
// Help
actionList.add(CommonActionsManager.getInstance().createHelpAction("interactive_console"));
@@ -243,10 +241,10 @@
return myConsoleView.getConsole();
}
- public static AnAction createConsoleExecAction(final LanguageConsoleImpl languageConsole,
+ public static AnAction createConsoleExecAction(final LanguageConsoleView console,
final ProcessHandler processHandler,
final ConsoleExecuteActionHandler consoleExecuteActionHandler) {
- return new ConsoleExecuteAction(languageConsole, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
+ return new ConsoleExecuteAction(console, consoleExecuteActionHandler, consoleExecuteActionHandler.getEmptyExecuteAction(),
new LanguageConsoleBuilder.ProcessBackedExecutionEnabledCondition(processHandler));
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/BaseConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/BaseConsoleExecuteActionHandler.java
index 396c663..3b979bb 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/BaseConsoleExecuteActionHandler.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/BaseConsoleExecuteActionHandler.java
@@ -1,74 +1,11 @@
-/*
- * 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.execution.runners;
-import com.intellij.execution.console.LanguageConsoleImpl;
-import com.intellij.execution.process.ConsoleHistoryModel;
-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.Document;
-import com.intellij.openapi.util.TextRange;
-import org.jetbrains.annotations.NotNull;
-
-public abstract class BaseConsoleExecuteActionHandler {
- private boolean myAddCurrentToHistory = true;
- private final ConsoleHistoryModel myConsoleHistoryModel;
- private final boolean myPreserveMarkup;
-
+@Deprecated
+/**
+ * @deprecated to remove in IDEA 15
+ */
+public abstract class BaseConsoleExecuteActionHandler extends com.intellij.execution.console.BaseConsoleExecuteActionHandler {
public BaseConsoleExecuteActionHandler(boolean preserveMarkup) {
- myConsoleHistoryModel = new ConsoleHistoryModel();
- myPreserveMarkup = preserveMarkup;
- }
-
- public ConsoleHistoryModel getConsoleHistoryModel() {
- return myConsoleHistoryModel;
- }
-
- public void setAddCurrentToHistory(boolean addCurrentToHistory) {
- myAddCurrentToHistory = addCurrentToHistory;
- }
-
- public void runExecuteAction(@NotNull LanguageConsoleImpl languageConsole) {
- // process input and add to history
- Document document = languageConsole.getCurrentEditor().getDocument();
- String text = document.getText();
- TextRange range = new TextRange(0, document.getTextLength());
-
- languageConsole.getCurrentEditor().getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
-
- if (myAddCurrentToHistory) {
- languageConsole.addCurrentToHistory(range, false, myPreserveMarkup);
- }
-
- languageConsole.setInputText("");
-
- UndoManager manager = UndoManager.getInstance(languageConsole.getProject());
- ((UndoManagerImpl)manager).invalidateActionsFor(DocumentReferenceManager.getInstance().create(document));
-
- myConsoleHistoryModel.addToHistory(text);
- execute(text);
- }
-
- protected abstract void execute(@NotNull String text);
-
- public void finishExecution() {
- }
-
- public String getEmptyExecuteAction() {
- return ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID;
+ super(preserveMarkup);
}
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteAction.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteAction.java
deleted file mode 100644
index eb4cf4d..0000000
--- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteAction.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.execution.runners;
-
-import com.intellij.codeInsight.lookup.Lookup;
-import com.intellij.codeInsight.lookup.LookupManager;
-import com.intellij.execution.console.LanguageConsoleImpl;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.EmptyAction;
-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 org.jetbrains.annotations.NotNull;
-
-public class ConsoleExecuteAction extends DumbAwareAction {
- static final String CONSOLE_EXECUTE_ACTION_ID = "Console.Execute";
-
- private final LanguageConsoleImpl myConsole;
- private final BaseConsoleExecuteActionHandler myExecuteActionHandler;
- private final Condition<LanguageConsoleImpl> myEnabledCondition;
-
- public ConsoleExecuteAction(@NotNull LanguageConsoleImpl console, @NotNull BaseConsoleExecuteActionHandler executeActionHandler) {
- this(console, executeActionHandler, CONSOLE_EXECUTE_ACTION_ID, Conditions.<LanguageConsoleImpl>alwaysTrue());
- }
-
- public ConsoleExecuteAction(@NotNull LanguageConsoleImpl console, @NotNull BaseConsoleExecuteActionHandler executeActionHandler,
- @NotNull String emptyExecuteActionId, @NotNull Condition<LanguageConsoleImpl> enabledCondition) {
- super(null, null, AllIcons.Actions.Execute);
-
- myConsole = console;
- myExecuteActionHandler = executeActionHandler;
- myEnabledCondition = enabledCondition;
-
- EmptyAction.setupAction(this, emptyExecuteActionId, null);
- }
-
- @Override
- public final void update(AnActionEvent e) {
- EditorEx editor = myConsole.getConsoleEditor();
- Lookup lookup = LookupManager.getActiveLookup(editor);
- e.getPresentation().setEnabled(!editor.isRendererMode() && isEnabled() &&
- (lookup == null || !lookup.isCompletion()));
- }
-
- @Override
- public final void actionPerformed(AnActionEvent e) {
- myExecuteActionHandler.runExecuteAction(myConsole);
- }
-
- protected boolean isEnabled() {
- return myEnabledCondition.value(myConsole);
- }
-}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java
index 98d849a..d362e82 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/ConsoleExecuteActionHandler.java
@@ -15,6 +15,8 @@
*/
package com.intellij.execution.runners;
+import com.intellij.execution.console.BaseConsoleExecuteActionHandler;
+import com.intellij.execution.console.LanguageConsoleView;
import com.intellij.execution.process.BaseOSProcessHandler;
import com.intellij.execution.process.ProcessHandler;
import org.jetbrains.annotations.NotNull;
@@ -46,11 +48,20 @@
}
@Override
+ protected void execute(@NotNull String text, @NotNull LanguageConsoleView console) {
+ //noinspection deprecation
+ execute(text);
+ }
+
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 15
+ */
protected void execute(@NotNull String text) {
processLine(text);
}
- public void processLine(String line) {
+ public void processLine(@NotNull String line) {
sendText(line + "\n");
}
@@ -66,8 +77,7 @@
outputStream.write(bytes);
outputStream.flush();
}
- catch (IOException e) {
- // ignore
+ catch (IOException ignored) {
}
}
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java
index 6be1ad4..e2f8a5a 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/DefaultProgramRunner.java
@@ -22,6 +22,7 @@
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
/**
* @author spleaner
@@ -29,10 +30,10 @@
public abstract class DefaultProgramRunner extends GenericProgramRunner {
@Override
- protected RunContentDescriptor doExecute(final Project project,
- final RunProfileState state,
+ protected RunContentDescriptor doExecute(@NotNull final Project project,
+ @NotNull final RunProfileState state,
final RunContentDescriptor contentToReuse,
- final ExecutionEnvironment env) throws ExecutionException {
+ @NotNull final ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
ExecutionResult executionResult = state.execute(env.getExecutor(), this);
if (executionResult == null) return null;
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/LanguageConsoleBuilder.java b/platform/lang-impl/src/com/intellij/execution/runners/LanguageConsoleBuilder.java
deleted file mode 100644
index e893386..0000000
--- a/platform/lang-impl/src/com/intellij/execution/runners/LanguageConsoleBuilder.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.intellij.execution.runners;
-
-import com.intellij.execution.console.ConsoleHistoryController;
-import com.intellij.execution.console.LanguageConsoleImpl;
-import com.intellij.execution.console.LanguageConsoleView;
-import com.intellij.execution.process.ProcessHandler;
-import com.intellij.openapi.util.Condition;
-import com.intellij.openapi.util.Conditions;
-import org.jetbrains.annotations.NotNull;
-
-public class LanguageConsoleBuilder {
- private LanguageConsoleImpl myConsole;
- private Condition<LanguageConsoleImpl> myExecutionEnabled = Conditions.alwaysTrue();
-
- public LanguageConsoleBuilder console(@NotNull LanguageConsoleView console) {
- myConsole = console.getConsole();
- return this;
- }
-
- public LanguageConsoleBuilder processHandler(@NotNull ProcessHandler processHandler) {
- myExecutionEnabled = new ProcessBackedExecutionEnabledCondition(processHandler);
- return this;
- }
-
- public LanguageConsoleBuilder executionEnabled(@NotNull Condition<LanguageConsoleImpl> condition) {
- myExecutionEnabled = condition;
- return this;
- }
-
- public LanguageConsoleBuilder initActions(@NotNull BaseConsoleExecuteActionHandler executeActionHandler, @NotNull String historyType) {
- ConsoleExecuteAction action = new ConsoleExecuteAction(myConsole, executeActionHandler, ConsoleExecuteAction.CONSOLE_EXECUTE_ACTION_ID, myExecutionEnabled);
- action.registerCustomShortcutSet(action.getShortcutSet(), myConsole.getConsoleEditor().getComponent());
-
- new ConsoleHistoryController(historyType, "", myConsole, executeActionHandler.getConsoleHistoryModel()).install();
- return this;
- }
-
- static class ProcessBackedExecutionEnabledCondition implements Condition<LanguageConsoleImpl> {
- private ProcessHandler myProcessHandler;
-
- public ProcessBackedExecutionEnabledCondition(ProcessHandler myProcessHandler) {
- this.myProcessHandler = myProcessHandler;
- }
-
- @Override
- public boolean value(LanguageConsoleImpl console) {
- return !myProcessHandler.isProcessTerminated();
- }
- }
-}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java
index 04f5bdc..abb2b3b 100644
--- a/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java
+++ b/platform/lang-impl/src/com/intellij/execution/runners/RerunTestsNotification.java
@@ -53,7 +53,7 @@
return;
}
- GotItMessage message = GotItMessage.createMessage("Press " + shortcutText + " to rerun tests", "");
+ GotItMessage message = GotItMessage.createMessage("Rerun tests with " + shortcutText, "");
message.setDisposable(executionConsole);
message.setCallback(new Runnable() {
@Override
diff --git a/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java b/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java
index da0731c..48ca786 100644
--- a/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.java
+++ b/platform/lang-impl/src/com/intellij/extapi/psi/PsiElementBase.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,7 +30,6 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -253,7 +252,7 @@
protected <T> T[] findChildrenByClass(Class<T> aClass) {
List<T> result = new ArrayList<T>();
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, aClass)) result.add((T)cur);
+ if (aClass.isInstance(cur)) result.add((T)cur);
}
return result.toArray((T[]) Array.newInstance(aClass, result.size()));
}
@@ -261,7 +260,7 @@
@Nullable
protected <T> T findChildByClass(Class<T> aClass) {
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, aClass)) return (T)cur;
+ if (aClass.isInstance(cur)) return (T)cur;
}
return null;
}
diff --git a/platform/lang-impl/src/com/intellij/facet/FacetManagerImpl.java b/platform/lang-impl/src/com/intellij/facet/FacetManagerImpl.java
index c72f9fe..42d0583 100644
--- a/platform/lang-impl/src/com/intellij/facet/FacetManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/facet/FacetManagerImpl.java
@@ -237,7 +237,9 @@
if (!invalidFacetManager.isIgnored(facet)) {
FacetLoadingErrorDescription description = new FacetLoadingErrorDescription(facet);
ProjectLoadingErrorsNotifier.getInstance(myModule.getProject()).registerError(description);
- UnknownFeaturesCollector.getInstance(myModule.getProject()).registerUnknownFeature("com.intellij.facetType", typeId);
+ if (typeId != null) {
+ UnknownFeaturesCollector.getInstance(myModule.getProject()).registerUnknownFeature("com.intellij.facetType", typeId);
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java b/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java
index 5c66162..2de03c4 100644
--- a/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.java
+++ b/platform/lang-impl/src/com/intellij/facet/impl/ui/FacetErrorPanel.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,7 +25,7 @@
import com.intellij.ui.UserActivityListener;
import com.intellij.ui.UserActivityWatcher;
import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.NonNls;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -39,8 +39,6 @@
* @author nik
*/
public class FacetErrorPanel {
- @NonNls private static final String HTML_PREFIX = "<html><body>";
- @NonNls private static final String HTML_SUFFIX = "</body></html>";
private final JPanel myMainPanel;
private JPanel myButtonPanel;
private JButton myQuickFixButton;
@@ -128,7 +126,7 @@
ValidationResult validationResult = validator.check();
if (!validationResult.isOk()) {
myMainPanel.setVisible(true);
- myWarningLabel.setText(HTML_PREFIX + validationResult.getErrorMessage() + HTML_SUFFIX);
+ myWarningLabel.setText(XmlStringUtil.wrapInHtml(validationResult.getErrorMessage()));
myWarningLabel.setVisible(true);
myCurrentQuickFix = validationResult.getQuickFix();
myQuickFixButton.setVisible(myCurrentQuickFix != null);
diff --git a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
index da4024e..eda7b19 100644
--- a/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
+++ b/platform/lang-impl/src/com/intellij/find/EditorSearchComponent.java
@@ -357,7 +357,7 @@
}
private void setupHistoryToSearchField(SearchTextField field, String[] strings) {
- field.setHistorySize(strings.length);
+ field.setHistorySize(20);
field.setHistory(ContainerUtil.reverse(Arrays.asList(strings)));
}
diff --git a/platform/lang-impl/src/com/intellij/find/FindBundle.java b/platform/lang-impl/src/com/intellij/find/FindBundle.java
index 129858a..6f18c8c 100644
--- a/platform/lang-impl/src/com/intellij/find/FindBundle.java
+++ b/platform/lang-impl/src/com/intellij/find/FindBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* @author yole
*/
public class FindBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.FindBundle";
private FindBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/lang-impl/src/com/intellij/find/FindUtil.java b/platform/lang-impl/src/com/intellij/find/FindUtil.java
index fbef4f7..e54074d 100644
--- a/platform/lang-impl/src/com/intellij/find/FindUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/FindUtil.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.
@@ -307,7 +307,7 @@
public static void findAllAndShow(@NotNull Project project, @NotNull Editor editor, @NotNull FindModel findModel) {
List<Usage> usages = findAll(project, editor, findModel);
if (usages == null) return;
- final UsageTarget[] usageTargets = {new FindInProjectUtil.StringUsageTarget(project, findModel.getStringToFind())};
+ final UsageTarget[] usageTargets = {new FindInProjectUtil.StringUsageTarget(project, findModel)};
final UsageViewPresentation usageViewPresentation = FindInProjectUtil.setupViewPresentation(false, findModel);
UsageViewManager.getInstance(project).showUsages(usageTargets, usages.toArray(new Usage[usages.size()]), usageViewPresentation);
}
@@ -931,23 +931,20 @@
final UsageTarget[] usageTargets =
sourceElement == null ? UsageTarget.EMPTY_ARRAY : new UsageTarget[]{new PsiElement2UsageTargetAdapter(sourceElement)};
- final UsageInfoToUsageConverter.TargetElementsDescriptor targetElementsDescriptor =
- sourceElement != null ? new UsageInfoToUsageConverter.TargetElementsDescriptor(sourceElement)
- : new UsageInfoToUsageConverter.TargetElementsDescriptor(PsiElement.EMPTY_ARRAY);
- final Usage[] usages = {UsageInfoToUsageConverter.convert(targetElementsDescriptor, new UsageInfo(targets[0]))};
+ final PsiElement[] primary = sourceElement == null ? PsiElement.EMPTY_ARRAY : new PsiElement[]{sourceElement};
+ final Usage[] usages = {UsageInfoToUsageConverter.convert(primary, new UsageInfo(targets[0]))};
final UsageView view =
UsageViewManager.getInstance(project).showUsages(usageTargets, usages, presentation);
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Updating Usage View ...") {
@Override
public void run(@NotNull ProgressIndicator indicator) {
-
for (int i = 1; i < targets.length; i++) {
if (((UsageViewImpl)view).isDisposed()) break;
final PsiElement target = targets[i];
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
- final Usage usage = UsageInfoToUsageConverter.convert(targetElementsDescriptor, new UsageInfo(target));
+ final Usage usage = UsageInfoToUsageConverter.convert(primary, new UsageInfo(target));
view.appendUsage(usage);
}
});
diff --git a/platform/lang-impl/src/com/intellij/find/actions/FindInPathAction.java b/platform/lang-impl/src/com/intellij/find/actions/FindInPathAction.java
index 4ced6fb..abdf67d 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/FindInPathAction.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/FindInPathAction.java
@@ -29,7 +29,7 @@
import com.intellij.psi.PsiElement;
public class FindInPathAction extends AnAction implements DumbAware {
- static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("FindInPath", ToolWindowId.FIND, false);
+ public static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("Find in Path", ToolWindowId.FIND, false);
{ // enabled in modal content for find in path <-> replace in path modal dialog transition
setEnabledInModalContext(true);
diff --git a/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java
index d2536ee..3da2b2e 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/FindUsagesAction.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,7 +21,6 @@
import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
import com.intellij.find.FindBundle;
import com.intellij.find.FindManager;
-import com.intellij.find.findUsages.PsiElement2UsageTargetAdapter;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
@@ -73,7 +72,7 @@
}
protected void startFindUsages(@NotNull PsiElement element) {
- new PsiElement2UsageTargetAdapter(element).findUsages();
+ FindManager.getInstance(element.getProject()).findUsages(element);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
index cb93e1d..f720fe9 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesAction.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 @@
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.find.FindManager;
+import com.intellij.find.FindSettings;
import com.intellij.find.findUsages.*;
import com.intellij.find.impl.FindManagerImpl;
import com.intellij.icons.AllIcons;
@@ -47,7 +48,6 @@
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.SmartPsiElementPointer;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.PsiElementProcessor;
@@ -55,7 +55,9 @@
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.popup.AbstractPopup;
+import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewBundle;
+import com.intellij.usageView.UsageViewUtil;
import com.intellij.usages.*;
import com.intellij.usages.impl.*;
import com.intellij.usages.rules.UsageFilteringRuleProvider;
@@ -66,17 +68,22 @@
import com.intellij.util.ui.AsyncProcessIcon;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicReference;
public class ShowUsagesAction extends AnAction implements PopupAction {
private final boolean showSettingsDialogBefore;
@@ -198,7 +205,7 @@
private static FindUsagesOptions getDefaultOptions(@NotNull FindUsagesHandler handler) {
FindUsagesOptions options = handler.getFindUsagesOptions(DataManager.getInstance().getDataContext());
// by default, scope in FindUsagesOptions is copied from the FindSettings, but we need a default one
- //options.searchScope = FindUsagesManager.getMaximalScope(handler);
+ options.searchScope = GlobalSearchScope.projectScope(handler.getProject());
return options;
}
@@ -231,8 +238,6 @@
final List<Usage> usages = new ArrayList<Usage>();
final Set<UsageNode> visibleNodes = new LinkedHashSet<UsageNode>();
- UsageInfoToUsageConverter.TargetElementsDescriptor descriptor =
- new UsageInfoToUsageConverter.TargetElementsDescriptor(handler.getPrimaryElements(), handler.getSecondaryElements());
final MyTable table = new MyTable();
final AsyncProcessIcon processIcon = new AsyncProcessIcon("xxx");
@@ -252,7 +257,7 @@
SpeedSearchBase<JTable> speedSearch = new MySpeedSearch(table);
speedSearch.setComparator(new SpeedSearchComparator(false));
- final JBPopup popup = createUsagePopup(usages, descriptor, visibleNodes, handler, editor, popupPosition,
+ final JBPopup popup = createUsagePopup(usages, visibleNodes, handler, editor, popupPosition,
maxUsages, usageView, options, table, presentation, processIcon, hadMoreSeparator);
Disposer.register(popup, usageView);
@@ -332,7 +337,7 @@
}
};
- final ProgressIndicator indicator = FindUsagesManager.startProcessUsages(handler, descriptor, collect, options, new Runnable() {
+ final ProgressIndicator indicator = FindUsagesManager.startProcessUsages(handler, handler.getPrimaryElements(), handler.getSecondaryElements(), collect, options, new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -551,7 +556,6 @@
@NotNull
private JBPopup createUsagePopup(@NotNull final List<Usage> usages,
- @NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
@NotNull Set<UsageNode> visibleNodes,
@NotNull final FindUsagesHandler handler,
final Editor editor,
@@ -580,23 +584,44 @@
}
builder.setMovable(true).setResizable(true);
- builder.setItemChoosenCallback(new Runnable() {
+ final AtomicReference<UsageInfo> selectedUsage = new AtomicReference<UsageInfo>();
+ final AtomicBoolean moreUsages = new AtomicBoolean();
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
- public void run() {
+ public void valueChanged(ListSelectionEvent e) {
+ selectedUsage.set(null);
int[] selected = table.getSelectedRows();
for (int i : selected) {
Object value = table.getValueAt(i, 0);
if (value instanceof UsageNode) {
Usage usage = ((UsageNode)value).getUsage();
if (usage == MORE_USAGES_SEPARATOR) {
- appendMoreUsages(editor, popupPosition, handler, maxUsages, options);
- return;
+ moreUsages.set(true);
+ selectedUsage.set(null);
}
- navigateAndHint(usage, null, handler, popupPosition, maxUsages, options);
+ else {
+ moreUsages.set(false);
+ selectedUsage.set(usage instanceof UsageInfo2UsageAdapter ? ((UsageInfo2UsageAdapter)usage).getUsageInfo().copy() : null);
+ }
+ break;
}
}
}
});
+ builder.setMovable(true).setResizable(true);
+ builder.setItemChoosenCallback(new Runnable() {
+ @Override
+ public void run() {
+ if (moreUsages.get()) {
+ appendMoreUsages(editor, popupPosition, handler, maxUsages, options);
+ return;
+ }
+ UsageInfo usage = selectedUsage.get();
+ if (usage != null) {
+ UsageViewUtil.navigateTo(usage, true);
+ }
+ }
+ });
final JBPopup[] popup = new JBPopup[1];
KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut();
@@ -638,7 +663,7 @@
}
};
final DefaultActionGroup pinGroup = new DefaultActionGroup();
- final ActiveComponent pin = createPinButton(descriptor, usageView, options, popup, pinGroup);
+ final ActiveComponent pin = createPinButton(handler, usageView, options, popup, pinGroup);
builder.setCommandButton(new CompositeActiveComponent(spinningProgress, settingsButton, pin));
DefaultActionGroup toolbar = new DefaultActionGroup();
@@ -671,9 +696,11 @@
return popup[0];
}
- private ActiveComponent createPinButton(final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
- final UsageViewImpl usageView,
- final FindUsagesOptions options, final JBPopup[] popup, DefaultActionGroup pinGroup) {
+ private ActiveComponent createPinButton(@NotNull final FindUsagesHandler handler,
+ @NotNull final UsageViewImpl usageView,
+ @NotNull final FindUsagesOptions options,
+ @NotNull final JBPopup[] popup,
+ @NotNull DefaultActionGroup pinGroup) {
final AnAction pinAction =
new AnAction("Open Find Usages Toolwindow", "Show all usages in a separate toolwindow", AllIcons.General.AutohideOff) {
{
@@ -686,12 +713,8 @@
hideHints();
popup[0].cancel();
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(usageView.getProject())).getFindUsagesManager();
- FindUsagesManager.SearchData data = new FindUsagesManager.SearchData();
- data.myOptions = options;
- List<SmartPsiElementPointer<PsiElement>> plist = descriptor.getAllElementPointers();
-
- data.myElements = plist.toArray(new SmartPsiElementPointer[plist.size()]);
- findUsagesManager.rerunAndRecallFromHistory(data);
+ findUsagesManager.findUsages(handler.getPrimaryElements(), handler.getSecondaryElements(), handler, options,
+ FindSettings.getInstance().isSkipResultsWithOneUsage());
}
};
pinGroup.add(pinAction);
@@ -734,9 +757,9 @@
final String title = getSecondInvocationTitle(options, handler);
if (title != null) {
- text += "<br><small>Press " + title + "</small>";
+ text += "<br><small> " + title + "</small>";
}
- return "<html><body>" + text + "</body></html>";
+ return XmlStringUtil.wrapInHtml(text);
}
@Nullable
diff --git a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java
index 9aa4999..7603bab 100644
--- a/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.java
+++ b/platform/lang-impl/src/com/intellij/find/actions/ShowUsagesTableCellRenderer.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,6 +33,7 @@
import com.intellij.usages.rules.UsageInFile;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -65,7 +66,7 @@
if (usage == null || usageNode instanceof ShowUsagesAction.StringNode) {
panel.setLayout(new BorderLayout());
if (column == 0) {
- panel.add(new JLabel("<html><body><b>" + value + "</b></body></html>", SwingConstants.CENTER));
+ panel.add(new JLabel(XmlStringUtil.wrapInHtml("<b>" + value + "</b>"), SwingConstants.CENTER));
}
return panel;
}
diff --git a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleWholeWordsOnlyAction.java b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleWholeWordsOnlyAction.java
index 5465dfe..0c3a26a 100644
--- a/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleWholeWordsOnlyAction.java
+++ b/platform/lang-impl/src/com/intellij/find/editorHeaderActions/ToggleWholeWordsOnlyAction.java
@@ -5,7 +5,7 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
public class ToggleWholeWordsOnlyAction extends EditorHeaderToggleAction {
- private static final String WHOLE_WORDS_ONLY = "&Words";
+ private static final String WHOLE_WORDS_ONLY = "Wo&rds";
public ToggleWholeWordsOnlyAction(EditorSearchComponent editorSearchComponent) {
super(editorSearchComponent, WHOLE_WORDS_ONLY);
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 eff1325..4c11fe2 100644
--- a/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findInProject/FindInProjectManager.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,30 +21,21 @@
import com.intellij.find.FindSettings;
import com.intellij.find.FindUtil;
import com.intellij.find.impl.FindInProjectUtil;
+import com.intellij.find.impl.FindManagerImpl;
import com.intellij.find.replaceInProject.ReplaceInProjectManager;
-import com.intellij.ide.DataManager;
-import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Factory;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
-import com.intellij.psi.PsiFile;
import com.intellij.ui.content.Content;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewManager;
import com.intellij.usages.*;
-import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
public class FindInProjectManager {
private final Project myProject;
@@ -87,151 +78,68 @@
@Override
public void run() {
findModel.setOpenInNewTabVisible(false);
- final PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject);
- if (findModel.getDirectoryName() != null && psiDirectory == null){
- return;
- }
if (isOpenInNewTabEnabled) {
myToOpenInNewTab = toOpenInNewTab[0] = findModel.isOpenInNewTab();
}
- com.intellij.usages.UsageViewManager manager = com.intellij.usages.UsageViewManager.getInstance(myProject);
-
- if (manager == null) return;
- findManager.getFindInProjectModel().copyFrom(findModel);
- final FindModel findModelCopy = (FindModel)findModel.clone();
- final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(myToOpenInNewTab, findModelCopy);
- final boolean showPanelIfOnlyOneUsage = !FindSettings.getInstance().isSkipResultsWithOneUsage();
-
- final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, showPanelIfOnlyOneUsage, presentation);
- UsageTarget usageTarget = StringUtil.isEmpty(findModel.getStringToFind()) ? createFileByTypeTarget(findModel)
- : new FindInProjectUtil.StringUsageTarget(myProject, findModel.getStringToFind());
- manager.searchAndShowUsages(new UsageTarget[] {usageTarget},
- new Factory<UsageSearcher>() {
- @Override
- public UsageSearcher create() {
- return new UsageSearcher() {
- @Override
- public void generate(@NotNull final Processor<Usage> processor) {
- myIsFindInProgress = true;
-
- try {
- Processor<UsageInfo> consumer = new Processor<UsageInfo>() {
- @Override
- public boolean process(UsageInfo info) {
- Usage usage = UsageInfo2UsageAdapter.CONVERTER.fun(info);
- usage.getPresentation().getIcon(); // cache icon
- return processor.process(usage);
- }
- };
- FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, true, consumer, processPresentation);
- }
- finally {
- myIsFindInProgress = false;
- }
- }
- };
- }
- },
- processPresentation,
- presentation,
- null
- );
+ startFindInProject(findModel);
}
+
});
findModel.setOpenInNewTabVisible(false);
}
- @NotNull
- private ConfigurableUsageTarget createFileByTypeTarget(@NotNull FindModel model) {
- final String filter = model.getFileFilter();
- return new ConfigurableUsageTarget() {
- @Override
- public void showSettings() {
- Content selectedContent = UsageViewManager.getInstance(myProject).getSelectedContent(true);
- JComponent component = selectedContent == null ? null : selectedContent.getComponent();
- findInProject(DataManager.getInstance().getDataContext(component));
- }
+ public void startFindInProject(@NotNull FindModel findModel) {
+ final PsiDirectory psiDirectory = FindInProjectUtil.getPsiDirectory(findModel, myProject);
+ if (findModel.getDirectoryName() != null && psiDirectory == null){
+ return;
+ }
- @Override
- public void findUsages() {
- throw new IncorrectOperationException();
- }
+ com.intellij.usages.UsageViewManager manager = com.intellij.usages.UsageViewManager.getInstance(myProject);
- @Override
- public void findUsagesInEditor(@NotNull FileEditor editor) {
- throw new IncorrectOperationException();
- }
+ if (manager == null) return;
+ final FindManager findManager = FindManager.getInstance(myProject);
+ findManager.getFindInProjectModel().copyFrom(findModel);
+ final FindModel findModelCopy = (FindModel)findModel.clone();
+ final UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(myToOpenInNewTab, findModelCopy);
+ final boolean showPanelIfOnlyOneUsage = !FindSettings.getInstance().isSkipResultsWithOneUsage();
- @Override
- public void highlightUsages(@NotNull PsiFile file, @NotNull Editor editor, boolean clearHighlights) {
- throw new IncorrectOperationException();
- }
+ final FindUsagesProcessPresentation processPresentation = FindInProjectUtil.setupProcessPresentation(myProject, showPanelIfOnlyOneUsage, presentation);
+ ConfigurableUsageTarget usageTarget = new FindInProjectUtil.StringUsageTarget(myProject, findModel);
- @Override
- public boolean isValid() {
- return true;
- }
+ ((FindManagerImpl)FindManager.getInstance(myProject)).getFindUsagesManager().addToHistory(usageTarget);
- @Override
- public boolean isReadOnly() {
- return false;
- }
+ manager.searchAndShowUsages(new UsageTarget[] {usageTarget},
+ new Factory<UsageSearcher>() {
+ @Override
+ public UsageSearcher create() {
+ return new UsageSearcher() {
+ @Override
+ public void generate(@NotNull final Processor<Usage> processor) {
+ myIsFindInProgress = true;
- @Nullable
- @Override
- public VirtualFile[] getFiles() {
- return VirtualFile.EMPTY_ARRAY;
- }
-
- @Override
- public void update() {
- }
-
- @Nullable
- @Override
- public String getName() {
- return "Files with mask \""+filter+"\"";
- }
-
- @Nullable
- @Override
- public ItemPresentation getPresentation() {
- return new ItemPresentation() {
- @Nullable
- @Override
- public String getPresentableText() {
- return getName();
- }
-
- @Nullable
- @Override
- public String getLocationString() {
- return null;
- }
-
- @Nullable
- @Override
- public Icon getIcon(boolean unused) {
- return null;
- }
- };
- }
-
- @Override
- public void navigate(boolean requestFocus) {
- }
-
- @Override
- public boolean canNavigate() {
- return false;
- }
-
- @Override
- public boolean canNavigateToSource() {
- return false;
- }
- };
+ try {
+ Processor<UsageInfo> consumer = new Processor<UsageInfo>() {
+ @Override
+ public boolean process(UsageInfo info) {
+ Usage usage = UsageInfo2UsageAdapter.CONVERTER.fun(info);
+ usage.getPresentation().getIcon(); // cache icon
+ return processor.process(usage);
+ }
+ };
+ FindInProjectUtil.findUsages(findModelCopy, psiDirectory, myProject, true, consumer, processPresentation);
+ }
+ finally {
+ myIsFindInProgress = false;
+ }
+ }
+ };
+ }
+ },
+ processPresentation,
+ presentation,
+ null
+ );
}
public boolean isWorkInProgress() {
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java
index 6b718a4..2089d3d 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesManager.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.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.find.FindBundle;
+import com.intellij.find.FindSettings;
import com.intellij.lang.findUsages.LanguageFindUsages;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.ActionManager;
@@ -49,7 +50,6 @@
import com.intellij.openapi.wm.ex.ProgressIndicatorEx;
import com.intellij.psi.*;
import com.intellij.psi.search.*;
-import com.intellij.psi.util.PsiUtilCore;
import com.intellij.ui.LightweightHint;
import com.intellij.ui.content.Content;
import com.intellij.usageView.UsageInfo;
@@ -57,6 +57,7 @@
import com.intellij.usageView.UsageViewUtil;
import com.intellij.usages.*;
import com.intellij.util.CommonProcessors;
+import com.intellij.util.Function;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
@@ -66,13 +67,14 @@
import org.picocontainer.defaults.ConstructorInjectionComponentAdapter;
import javax.swing.*;
-import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
+/**
+ * see {@link com.intellij.find.impl.FindManagerImpl#getFindUsagesManager()}
+ */
public class FindUsagesManager implements JDOMExternalizable {
private static final Logger LOG = Logger.getInstance("#com.intellij.find.findParameterUsages.FindUsagesManager");
@@ -87,29 +89,11 @@
@NonNls private static final String VALUE_START_USAGE_AGAIN = "START_AGAIN";
private final Project myProject;
private final com.intellij.usages.UsageViewManager myAnotherManager;
- private boolean myToOpenInNewTab = false;
+ private boolean myToOpenInNewTab = true;
- public static class SearchData {
- public SmartPsiElementPointer[] myElements = null;
- public FindUsagesOptions myOptions = null;
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final SearchData that = (SearchData)o;
-
- return Arrays.equals(myElements, that.myElements)
- && (myOptions != null ? myOptions.equals(that.myOptions) : that.myOptions == null);
- }
-
- public int hashCode() {
- return myElements != null ? Arrays.hashCode(myElements) : 0;
- }
- }
-
- private SearchData myLastSearchInFileData = new SearchData();
- private final List<SearchData> myFindUsagesHistory = ContainerUtil.createLockFreeCopyOnWriteList();
+ private PsiElement2UsageTargetComposite myLastSearchInFileData;
+ private final UsageHistory myHistory = new UsageHistory();
public FindUsagesManager(@NotNull Project project, @NotNull com.intellij.usages.UsageViewManager anotherManager) {
myProject = project;
@@ -134,15 +118,14 @@
}
public void clearFindingNextUsageInFile() {
- myLastSearchInFileData.myOptions = null;
- myLastSearchInFileData.myElements = null;
+ myLastSearchInFileData = null;
}
- public boolean findNextUsageInFile(FileEditor editor) {
+ public boolean findNextUsageInFile(@NotNull FileEditor editor) {
return findUsageInFile(editor, FileSearchScope.AFTER_CARET);
}
- public boolean findPreviousUsageInFile(FileEditor editor) {
+ public boolean findPreviousUsageInFile(@NotNull FileEditor editor) {
return findUsageInFile(editor, FileSearchScope.BEFORE_CARET);
}
@@ -157,11 +140,16 @@
}
private boolean findUsageInFile(@NotNull FileEditor editor, @NotNull FileSearchScope direction) {
- PsiElement[] elements = restorePsiElements(myLastSearchInFileData, true);
- if (elements == null) return false;
- if (elements.length == 0) return true;//all elements have invalidated
-
- UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(elements);
+ if (myLastSearchInFileData == null) return false;
+ PsiElement[] primaryElements = myLastSearchInFileData.getPrimaryElements();
+ PsiElement[] secondaryElements = myLastSearchInFileData.getSecondaryElements();
+ if (primaryElements.length == 0) {//all elements have been invalidated
+ Messages.showMessageDialog(myProject, FindBundle.message("find.searched.elements.have.been.changed.error"),
+ FindBundle.message("cannot.search.for.usages.title"), Messages.getInformationIcon());
+ // SCR #10022
+ //clearFindingNextUsageInFile();
+ return false;
+ }
//todo
TextEditor textEditor = (TextEditor)editor;
@@ -169,49 +157,15 @@
PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(document);
if (psiFile == null) return false;
- final FindUsagesHandler handler = getFindUsagesHandler(elements[0], false);
+ final FindUsagesHandler handler = getFindUsagesHandler(primaryElements[0], false);
if (handler == null) return false;
- findUsagesInEditor(descriptor, handler, psiFile, direction, myLastSearchInFileData.myOptions, textEditor);
+ findUsagesInEditor(primaryElements, secondaryElements, handler, psiFile, direction, myLastSearchInFileData.myOptions, textEditor);
return true;
}
- // returns null if cannot find, empty Pair if all elements have been changed
- @Nullable
- private PsiElement[] restorePsiElements(SearchData searchData, final boolean showErrorMessage) {
- if (searchData == null) return null;
- SmartPsiElementPointer[] lastSearchElements = searchData.myElements;
- if (lastSearchElements == null) return null;
- List<PsiElement> elements = new ArrayList<PsiElement>();
- for (SmartPsiElementPointer pointer : lastSearchElements) {
- PsiElement element = pointer.getElement();
- if (element != null) elements.add(element);
- }
- if (elements.isEmpty() && showErrorMessage) {
- Messages.showMessageDialog(myProject, FindBundle.message("find.searched.elements.have.been.changed.error"),
- FindBundle.message("cannot.search.for.usages.title"), Messages.getInformationIcon());
- // SCR #10022
- //clearFindingNextUsageInFile();
- return PsiElement.EMPTY_ARRAY;
- }
- return PsiUtilCore.toPsiElementArray(elements);
- }
-
- private void initLastSearchElement(final FindUsagesOptions findUsagesOptions,
- UsageInfoToUsageConverter.TargetElementsDescriptor descriptor) {
- myLastSearchInFileData = createSearchData(descriptor.getAllElements(), findUsagesOptions);
- }
-
- private SearchData createSearchData(@NotNull List<? extends PsiElement> psiElements, final FindUsagesOptions findUsagesOptions) {
- SearchData data = new SearchData();
-
- data.myElements = new SmartPsiElementPointer[psiElements.size()];
- int idx = 0;
- for (PsiElement psiElement : psiElements) {
- data.myElements[idx++] = SmartPointerManager.getInstance(myProject).createSmartPsiElementPointer(psiElement);
- }
- data.myOptions = findUsagesOptions;
- return data;
+ private void initLastSearchElement(@NotNull FindUsagesOptions findUsagesOptions, @NotNull PsiElement[] primaryElements,@NotNull PsiElement[] secondaryElements) {
+ myLastSearchInFileData = new PsiElement2UsageTargetComposite(primaryElements, secondaryElements, findUsagesOptions);
}
@Nullable
@@ -246,14 +200,6 @@
}
public void findUsages(@NotNull PsiElement psiElement, final PsiFile scopeFile, final FileEditor editor, boolean showDialog) {
- doShowDialogAndStartFind(psiElement, scopeFile, editor, showDialog, false);
- }
-
- private void doShowDialogAndStartFind(@NotNull PsiElement psiElement,
- PsiFile scopeFile,
- FileEditor editor,
- boolean showDialog,
- boolean useMaximalScope) {
FindUsagesHandler handler = getNewFindUsagesHandler(psiElement, false);
if (handler == null) return;
@@ -270,25 +216,44 @@
setOpenInNewTab(dialog.isShowInSeparateWindow());
FindUsagesOptions findUsagesOptions = dialog.calcFindUsagesOptions();
- if (!showDialog && useMaximalScope) {
- findUsagesOptions.searchScope = getMaximalScope(handler);
+ if (!showDialog) {
+ findUsagesOptions.searchScope = GlobalSearchScope.projectScope(myProject);
}
clearFindingNextUsageInFile();
+
+ startFindUsages(findUsagesOptions, handler, scopeFile, editor);
+ }
+
+ void startFindUsages(@NotNull PsiElement psiElement,
+ @NotNull FindUsagesOptions findUsagesOptions,
+ PsiFile scopeFile,
+ FileEditor editor) {
+ FindUsagesHandler handler = getNewFindUsagesHandler(psiElement, false);
+ if (handler == null) return;
+ startFindUsages(findUsagesOptions, handler, scopeFile, editor);
+ }
+
+ void startFindUsages(@NotNull FindUsagesOptions findUsagesOptions,
+ @NotNull FindUsagesHandler handler,
+ PsiFile scopeFile,
+ FileEditor editor) {
+ boolean singleFile = scopeFile != null;
+
+ clearFindingNextUsageInFile();
LOG.assertTrue(handler.getPsiElement().isValid());
PsiElement[] primaryElements = handler.getPrimaryElements();
checkNotNull(primaryElements, handler, "getPrimaryElements()");
PsiElement[] secondaryElements = handler.getSecondaryElements();
checkNotNull(secondaryElements, handler, "getSecondaryElements()");
- UsageInfoToUsageConverter.TargetElementsDescriptor descriptor =
- new UsageInfoToUsageConverter.TargetElementsDescriptor(primaryElements, secondaryElements);
if (singleFile) {
findUsagesOptions = findUsagesOptions.clone();
editor.putUserData(KEY_START_USAGE_AGAIN, null);
- findUsagesInEditor(descriptor, handler, scopeFile, FileSearchScope.FROM_START, findUsagesOptions, editor);
+ findUsagesInEditor(primaryElements, secondaryElements, handler, scopeFile, FileSearchScope.FROM_START, findUsagesOptions, editor);
}
else {
- findUsages(descriptor, handler, dialog.isSkipResultsWhenOneUsage(), dialog.isShowInSeparateWindow(), findUsagesOptions);
+ boolean skipResultsWithOneUsage = FindSettings.getInstance().isSkipResultsWithOneUsage();
+ findUsages(primaryElements, secondaryElements, handler, findUsagesOptions, skipResultsWithOneUsage);
}
}
@@ -299,53 +264,25 @@
((ConfigurableUsageTarget)target).showSettings();
}
- private static void checkNotNull(@NotNull PsiElement[] primaryElements,
+ private static void checkNotNull(@NotNull PsiElement[] elements,
@NotNull FindUsagesHandler handler,
@NonNls @NotNull String methodName) {
- for (PsiElement element : primaryElements) {
+ for (PsiElement element : elements) {
if (element == null) {
- LOG.error(handler + "." + methodName + " has returned array with null elements: " + Arrays.asList(primaryElements));
+ LOG.error(handler + "." + methodName + " has returned array with null elements: " + Arrays.asList(elements));
}
}
}
- public boolean isUsed(@NotNull PsiElement element, @NotNull FindUsagesOptions findUsagesOptions) {
- FindUsagesHandler handler = getFindUsagesHandler(element, true);
- if (handler == null) return false;
- UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(element);
- UsageSearcher usageSearcher = createUsageSearcher(descriptor, handler, findUsagesOptions, null);
- final AtomicBoolean used = new AtomicBoolean();
- usageSearcher.generate(new Processor<Usage>() {
- @Override
- public boolean process(final Usage usage) {
- if (isInComment(usage)) return true;
- used.set(true);
- return false;
- }
- });
- return used.get();
- }
-
- private static boolean isInComment(Usage usage) {
- if (!(usage instanceof UsageInfo2UsageAdapter)) return false;
- UsageInfo usageInfo = ((UsageInfo2UsageAdapter)usage).getUsageInfo();
- if (!usageInfo.isNonCodeUsage()) return false;
- SmartPsiFileRange psiRangePointer = usageInfo.getPsiFileRange();
- if (psiRangePointer == null) return false;
- Segment range = psiRangePointer.getRange();
- PsiFile file = psiRangePointer.getContainingFile();
- if (file == null || range == null) return false;
- PsiElement element = file.findElementAt(range.getStartOffset());
- return element instanceof PsiComment;
- }
@NotNull
public static ProgressIndicator startProcessUsages(@NotNull FindUsagesHandler handler,
- @NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
+ @NotNull final PsiElement[] primaryElements,
+ @NotNull final PsiElement[] secondaryElements,
@NotNull final Processor<Usage> processor,
@NotNull FindUsagesOptions findUsagesOptions,
@NotNull final Runnable onComplete) {
- final UsageSearcher usageSearcher = createUsageSearcher(descriptor, handler, findUsagesOptions, null);
+ final UsageSearcher usageSearcher = createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, null);
final ProgressIndicatorBase indicator = new ProgressIndicatorBase();
dropResolveCacheRegularly(indicator, handler.getProject());
@@ -392,16 +329,18 @@
}
- private static UsageSearcher createUsageSearcher(@NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
+ @NotNull
+ private static UsageSearcher createUsageSearcher(@NotNull final PsiElement[] primaryElements,
+ @NotNull final PsiElement[] secondaryElements,
@NotNull final FindUsagesHandler handler,
- @NotNull FindUsagesOptions _options,
+ @NotNull FindUsagesOptions options,
final PsiFile scopeFile) {
- final FindUsagesOptions options = _options.clone();
+ final FindUsagesOptions optionsClone = options.clone();
return new UsageSearcher() {
@Override
public void generate(@NotNull final Processor<Usage> processor) {
if (scopeFile != null) {
- options.searchScope = new LocalSearchScope(scopeFile);
+ optionsClone.searchScope = new LocalSearchScope(scopeFile);
}
final Processor<UsageInfo> usageInfoProcessor = new CommonProcessors.UniqueProcessor<UsageInfo>(new Processor<UsageInfo>() {
@Override
@@ -409,21 +348,15 @@
Usage usage = ApplicationManager.getApplication().runReadAction(new Computable<Usage>() {
@Override
public Usage compute() {
- return UsageInfoToUsageConverter.convert(descriptor, usageInfo);
+ return UsageInfoToUsageConverter.convert(primaryElements, usageInfo);
}
});
return processor.process(usage);
}
});
- final List<? extends PsiElement> elements =
- ApplicationManager.getApplication().runReadAction(new Computable<List<? extends PsiElement>>() {
- @Override
- public List<? extends PsiElement> compute() {
- return descriptor.getAllElements();
- }
- });
+ final Iterable<PsiElement> elements = ContainerUtil.concat(primaryElements, secondaryElements);
- options.fastTrack = new SearchRequestCollector(new SearchSession());
+ optionsClone.fastTrack = new SearchRequestCollector(new SearchSession());
try {
for (final PsiElement element : elements) {
@@ -433,10 +366,10 @@
LOG.assertTrue(element.isValid());
}
});
- handler.processElementUsages(element, usageInfoProcessor, options);
+ handler.processElementUsages(element, usageInfoProcessor, optionsClone);
for (CustomUsageSearcher searcher : Extensions.getExtensions(CustomUsageSearcher.EP_NAME)) {
try {
- searcher.processElementUsages(element, processor, options);
+ searcher.processElementUsages(element, processor, optionsClone);
}
catch (IndexNotReadyException e) {
DumbService.getInstance(element.getProject()).showDumbModeNotification("Find usages is not available during indexing");
@@ -450,11 +383,11 @@
Project project = ApplicationManager.getApplication().runReadAction(new Computable<Project>() {
@Override
public Project compute() {
- return scopeFile != null ? scopeFile.getProject() : !elements.isEmpty() ? elements.get(0).getProject() : handler.getProject();
+ return scopeFile != null ? scopeFile.getProject() : primaryElements[0].getProject();
}
});
PsiSearchHelper.SERVICE.getInstance(project)
- .processRequests(options.fastTrack, new Processor<PsiReference>() {
+ .processRequests(optionsClone.fastTrack, new Processor<PsiReference>() {
@Override
public boolean process(final PsiReference ref) {
UsageInfo info = ApplicationManager.getApplication().runReadAction(new Computable<UsageInfo>() {
@@ -469,39 +402,45 @@
});
}
finally {
- options.fastTrack = null;
+ optionsClone.fastTrack = null;
}
}
};
}
-
- private static PsiElement2UsageTargetAdapter[] convertToUsageTargets(final List<? extends PsiElement> elementsToSearch) {
- final ArrayList<PsiElement2UsageTargetAdapter> targets = new ArrayList<PsiElement2UsageTargetAdapter>(elementsToSearch.size());
- for (PsiElement element : elementsToSearch) {
- convertToUsageTarget(targets, element);
- }
+ @NotNull
+ private static PsiElement2UsageTargetAdapter[] convertToUsageTargets(@NotNull Iterable<PsiElement> elementsToSearch,
+ @NotNull final FindUsagesOptions findUsagesOptions) {
+ final List<PsiElement2UsageTargetAdapter> targets = ContainerUtil.map(elementsToSearch,
+ new Function<PsiElement, PsiElement2UsageTargetAdapter>() {
+ @Override
+ public PsiElement2UsageTargetAdapter fun(PsiElement element) {
+ return convertToUsageTarget(element, findUsagesOptions);
+ }
+ });
return targets.toArray(new PsiElement2UsageTargetAdapter[targets.size()]);
}
- private void findUsages(@NotNull final UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
- @NotNull final FindUsagesHandler handler,
- final boolean toSkipUsagePanelWhenOneUsage,
- final boolean toOpenInNewTab,
- @NotNull final FindUsagesOptions findUsagesOptions) {
- List<? extends PsiElement> elements = descriptor.getAllElements();
- if (elements.isEmpty()) {
+ public void findUsages(@NotNull final PsiElement[] primaryElements,
+ @NotNull final PsiElement[] secondaryElements,
+ @NotNull final FindUsagesHandler handler,
+ @NotNull final FindUsagesOptions findUsagesOptions,
+ final boolean toSkipUsagePanelWhenOneUsage) {
+
+ if (primaryElements.length == 0) {
throw new AssertionError(handler + " " + findUsagesOptions);
}
- final UsageTarget[] targets = convertToUsageTargets(elements);
+ Iterable<PsiElement> allElements = ContainerUtil.concat(primaryElements, secondaryElements);
+ final UsageTarget[] targets = convertToUsageTargets(allElements, findUsagesOptions);
myAnotherManager.searchAndShowUsages(targets, new Factory<UsageSearcher>() {
@Override
public UsageSearcher create() {
dropResolveCacheRegularly(ProgressManager.getInstance().getProgressIndicator(), myProject);
- return createUsageSearcher(descriptor, handler, findUsagesOptions, null);
+ return createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, null);
}
- }, !toSkipUsagePanelWhenOneUsage, true, createPresentation(elements.get(0), findUsagesOptions, toOpenInNewTab), null);
- addToHistory(elements, findUsagesOptions);
+ }, !toSkipUsagePanelWhenOneUsage, true, createPresentation(primaryElements[0], findUsagesOptions, shouldOpenInNewTab()), null);
+ myHistory.add((ConfigurableUsageTarget)targets[0]);
+ //addToHistory(allElements, findUsagesOptions);
}
private static void dropResolveCacheRegularly(ProgressIndicator indicator, final Project project) {
@@ -526,12 +465,12 @@
@NotNull
private static UsageViewPresentation createPresentation(@NotNull PsiElement psiElement,
- @NotNull FindUsagesOptions findUsagesOptions,
+ @NotNull FindUsagesOptions options,
boolean toOpenInNewTab) {
UsageViewPresentation presentation = new UsageViewPresentation();
- String scopeString = findUsagesOptions.searchScope == null ? null : findUsagesOptions.searchScope.getDisplayName();
+ String scopeString = options.searchScope == null ? null : options.searchScope.getDisplayName();
presentation.setScopeText(scopeString);
- String usagesString = generateUsagesString(findUsagesOptions);
+ String usagesString = generateUsagesString(options);
presentation.setUsagesString(usagesString);
String title = scopeString == null
? FindBundle.message("find.usages.of.element.panel.title", usagesString, UsageViewUtil.getLongName(psiElement))
@@ -544,19 +483,20 @@
return presentation;
}
- private void findUsagesInEditor(@NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor,
+ private void findUsagesInEditor(@NotNull final PsiElement[] primaryElements,
+ @NotNull final PsiElement[] secondaryElements,
@NotNull FindUsagesHandler handler,
@NotNull PsiFile scopeFile,
@NotNull FileSearchScope direction,
@NotNull final FindUsagesOptions findUsagesOptions,
@NotNull FileEditor fileEditor) {
- initLastSearchElement(findUsagesOptions, descriptor);
+ initLastSearchElement(findUsagesOptions, primaryElements, secondaryElements);
clearStatusBar();
final FileEditorLocation currentLocation = fileEditor.getCurrentLocation();
- final UsageSearcher usageSearcher = createUsageSearcher(descriptor, handler, findUsagesOptions, scopeFile);
+ final UsageSearcher usageSearcher = createUsageSearcher(primaryElements, secondaryElements, handler, findUsagesOptions, scopeFile);
AtomicBoolean usagesWereFound = new AtomicBoolean();
Usage fUsage = findSiblingUsage(usageSearcher, direction, currentLocation, usagesWereFound, fileEditor);
@@ -566,12 +506,12 @@
fUsage.selectInEditor();
}
else if (!usagesWereFound.get()) {
- String message = getNoUsagesFoundMessage(descriptor.getPrimaryElements()[0]) + " in " + scopeFile.getName();
+ String message = getNoUsagesFoundMessage(primaryElements[0]) + " in " + scopeFile.getName();
showHintOrStatusBarMessage(message, fileEditor);
}
else {
fileEditor.putUserData(KEY_START_USAGE_AGAIN, VALUE_START_USAGE_AGAIN);
- showHintOrStatusBarMessage(getSearchAgainMessage(descriptor.getPrimaryElements()[0], direction), fileEditor);
+ showHintOrStatusBarMessage(getSearchAgainMessage(primaryElements[0], direction), fileEditor);
}
}
@@ -673,16 +613,16 @@
return foundUsage.get();
}
- private static void convertToUsageTarget(@NotNull List<PsiElement2UsageTargetAdapter> targets, @NotNull PsiElement elementToSearch) {
+ private static PsiElement2UsageTargetAdapter convertToUsageTarget(@NotNull PsiElement elementToSearch,
+ @NotNull FindUsagesOptions findUsagesOptions) {
if (elementToSearch instanceof NavigationItem) {
- targets.add(new PsiElement2UsageTargetAdapter(elementToSearch));
+ return new PsiElement2UsageTargetAdapter(elementToSearch,findUsagesOptions);
}
- else {
- throw new IllegalArgumentException("Wrong usage target:" + elementToSearch + "; " + elementToSearch.getClass());
- }
+ throw new IllegalArgumentException("Wrong usage target:" + elementToSearch + "; " + elementToSearch.getClass());
}
- private static String generateUsagesString(final FindUsagesOptions selectedOptions) {
+ @NotNull
+ private static String generateUsagesString(@NotNull FindUsagesOptions selectedOptions) {
return selectedOptions.generateUsagesString();
}
@@ -699,55 +639,21 @@
return LanguageFindUsages.INSTANCE.forLanguage(element.getLanguage()).getHelpId(element);
}
- private void addToHistory(final List<? extends PsiElement> elements, final FindUsagesOptions findUsagesOptions) {
- SearchData data = createSearchData(elements, findUsagesOptions);
- myFindUsagesHistory.remove(data);
- myFindUsagesHistory.add(data);
-
- // todo configure history depth limit
- if (myFindUsagesHistory.size() > 15) {
- myFindUsagesHistory.remove(0);
- }
+ public void rerunAndRecallFromHistory(@NotNull ConfigurableUsageTarget usageTarget) {
+ usageTarget.findUsages();
+ addToHistory(usageTarget);
}
- public void rerunAndRecallFromHistory(@NotNull SearchData searchData) {
- myFindUsagesHistory.remove(searchData);
- PsiElement[] elements = restorePsiElements(searchData, true);
- if (elements == null || elements.length == 0) return;
- UsageInfoToUsageConverter.TargetElementsDescriptor descriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(elements);
- final FindUsagesHandler handler = getFindUsagesHandler(elements[0], false);
- if (handler == null) return;
- findUsages(descriptor, handler, false, false, searchData.myOptions);
+ public void addToHistory(@NotNull ConfigurableUsageTarget usageTarget) {
+ myHistory.add(usageTarget);
}
- // most recent entry is at the end of the list
- public List<SearchData> getFindUsageHistory() {
- removeInvalidElementsFromHistory();
- return Collections.unmodifiableList(myFindUsagesHistory);
- }
-
- private void removeInvalidElementsFromHistory() {
- for (SearchData data : myFindUsagesHistory) {
- PsiElement[] elements = restorePsiElements(data, false);
- if (elements == null || elements.length == 0) myFindUsagesHistory.remove(data);
- }
- }
-
-
@NotNull
- private static PsiElement[] getPsiElements(@NotNull UsageTarget[] targets) {
- List<PsiElement> result = new ArrayList<PsiElement>();
- for (UsageTarget target : targets) {
- if (target instanceof PsiElementUsageTarget) {
- PsiElement element = ((PsiElementUsageTarget)target).getElement();
- if (element != null) {
- result.add(element);
- }
- }
- }
- return PsiUtilCore.toPsiElementArray(result);
+ public UsageHistory getHistory() {
+ return myHistory;
}
+
@NotNull
public static GlobalSearchScope getMaximalScope(@NotNull FindUsagesHandler handler) {
PsiElement element = handler.getPsiElement();
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java
index beddaba..39727af 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/FindUsagesOptions.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.
@@ -96,6 +96,7 @@
'}';
}
+ @NotNull
public String generateUsagesString() {
return FindBundle.message("find.usages.panel.title.usages");
}
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java
index 30fa592..e5119f2 100644
--- a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.java
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetAdapter.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,31 +17,40 @@
package com.intellij.find.findUsages;
import com.intellij.codeInsight.highlighting.HighlightUsagesHandler;
+import com.intellij.find.FindBundle;
import com.intellij.find.FindManager;
import com.intellij.find.impl.FindManagerImpl;
+import com.intellij.lang.findUsages.DescriptiveNameUtil;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.NavigationItem;
import com.intellij.navigation.PsiElementNavigationItem;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataSink;
+import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.pom.Navigatable;
import com.intellij.psi.*;
import com.intellij.psi.meta.PsiMetaData;
import com.intellij.psi.meta.PsiMetaOwner;
import com.intellij.psi.meta.PsiPresentableMetaData;
import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.ui.ComputableIcon;
import com.intellij.usageView.UsageInfo;
+import com.intellij.usageView.UsageViewBundle;
import com.intellij.usageView.UsageViewUtil;
+import com.intellij.usages.ConfigurableUsageTarget;
import com.intellij.usages.PsiElementUsageTarget;
import com.intellij.usages.UsageView;
+import com.intellij.usages.impl.UsageViewImpl;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -51,49 +60,55 @@
/**
* @author max
*/
-public class PsiElement2UsageTargetAdapter implements PsiElementUsageTarget, TypeSafeDataProvider, PsiElementNavigationItem {
+public class PsiElement2UsageTargetAdapter
+ implements PsiElementUsageTarget, TypeSafeDataProvider, PsiElementNavigationItem, ItemPresentation, ConfigurableUsageTarget {
private final SmartPsiElementPointer myPointer;
- private final MyItemPresentation myPresentation;
+ @NotNull protected final FindUsagesOptions myOptions;
- public PsiElement2UsageTargetAdapter(@NotNull PsiElement element) {
+ public PsiElement2UsageTargetAdapter(@NotNull PsiElement element, @NotNull FindUsagesOptions options) {
+ myOptions = options;
myPointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(element);
if (!(element instanceof NavigationItem)) {
throw new IllegalArgumentException("Element is not a navigation item: " + element);
}
+ update(element);
+ }
- myPresentation = new MyItemPresentation();
+ public PsiElement2UsageTargetAdapter(@NotNull PsiElement element) {
+ this(element, new FindUsagesOptions(element.getProject()));
}
@Override
public String getName() {
- return getNavigationItem().getName();
+ PsiElement element = getElement();
+ return element instanceof NavigationItem ? ((NavigationItem)element).getName() : null;
}
@Override
@NotNull
public ItemPresentation getPresentation() {
- return myPresentation;
+ return this;
}
@Override
public void navigate(boolean requestFocus) {
- if (!canNavigate()) return;
- getNavigationItem().navigate(requestFocus);
+ PsiElement element = getElement();
+ if (element instanceof Navigatable && ((Navigatable)element).canNavigate()) {
+ ((Navigatable)element).navigate(requestFocus);
+ }
}
@Override
public boolean canNavigate() {
- return isValid() && getNavigationItem().canNavigate();
+ PsiElement element = getElement();
+ return element instanceof Navigatable && ((Navigatable)element).canNavigate();
}
@Override
public boolean canNavigateToSource() {
- return isValid() && getNavigationItem().canNavigateToSource();
- }
-
- private NavigationItem getNavigationItem() {
- return (NavigationItem)getElement();
+ PsiElement element = getElement();
+ return element instanceof Navigatable && ((Navigatable)element).canNavigateToSource();
}
@Override
@@ -102,13 +117,14 @@
}
public String toString() {
- return myPresentation.getPresentableText();
+ return getPresentableText();
}
@Override
public void findUsages() {
PsiElement element = getElement();
- FindManager.getInstance(element.getProject()).findUsages(element);
+ if (element == null) return;
+ ((FindManagerImpl)FindManager.getInstance(element.getProject())).getFindUsagesManager().startFindUsages(element, myOptions, null, null);
}
@Override
@@ -164,12 +180,8 @@
return virtualFile == null ? null : new VirtualFile[]{virtualFile};
}
- @Override
- public void update() {
- myPresentation.update();
- }
-
- public static PsiElement2UsageTargetAdapter[] convert(PsiElement[] psiElements) {
+ @NotNull
+ public static PsiElement2UsageTargetAdapter[] convert(@NotNull PsiElement[] psiElements) {
PsiElement2UsageTargetAdapter[] targets = new PsiElement2UsageTargetAdapter[psiElements.length];
for (int i = 0; i < targets.length; i++) {
targets[i] = new PsiElement2UsageTargetAdapter(psiElements[i]);
@@ -189,6 +201,27 @@
}
@Override
+ public KeyboardShortcut getShortcut() {
+ return UsageViewImpl.getShowUsagesWithSettingsShortcut();
+ }
+
+ @NotNull
+ @Override
+ public String getLongDescriptiveName() {
+ SearchScope searchScope = myOptions.searchScope;
+ String scopeString = searchScope == null ? null : searchScope.getDisplayName();
+ PsiElement psiElement = getElement();
+
+ return psiElement == null ? UsageViewBundle.message("node.invalid") :
+ FindBundle.message("recent.find.usages.action.popup", StringUtil.capitalize(UsageViewUtil.getType(psiElement)),
+ DescriptiveNameUtil.getDescriptiveName(psiElement),
+ scopeString == null
+ ? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName()
+ : scopeString
+ );
+ }
+
+ @Override
public void showSettings() {
FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(myPointer.getProject())).getFindUsagesManager();
PsiElement element = getElement();
@@ -197,58 +230,56 @@
}
}
- private class MyItemPresentation implements ItemPresentation {
- private String myPresentableText;
- private ComputableIcon myIconOpen;
- private ComputableIcon myIconClosed;
+ private String myPresentableText;
+ private ComputableIcon myIconOpen;
+ private ComputableIcon myIconClosed;
- public MyItemPresentation() {
- update();
- }
+ @Override
+ public void update() {
+ update(getElement());
+ }
- public void update() {
- final PsiElement element = getElement();
- if (element != null && element.isValid()) {
- final ItemPresentation presentation = ((NavigationItem)element).getPresentation();
- myIconOpen = presentation != null ? ComputableIcon.create(presentation, true) : null;
- myIconClosed = presentation != null ? ComputableIcon.create(presentation, false) : null;
- myPresentableText = presentation != null ? presentation.getPresentableText() : UsageViewUtil.createNodeText(element);
- if (myIconOpen == null || myIconClosed == null) {
- if (element instanceof PsiMetaOwner) {
- final PsiMetaOwner psiMetaOwner = (PsiMetaOwner)element;
- final PsiMetaData metaData = psiMetaOwner.getMetaData();
- if (metaData instanceof PsiPresentableMetaData) {
- final PsiPresentableMetaData psiPresentableMetaData = (PsiPresentableMetaData)metaData;
- if (myIconOpen == null) myIconOpen = ComputableIcon.create(psiPresentableMetaData);
- if (myIconClosed == null) myIconClosed = ComputableIcon.create(psiPresentableMetaData);
- }
+ private void update(PsiElement element) {
+ if (element != null && element.isValid()) {
+ final ItemPresentation presentation = ((NavigationItem)element).getPresentation();
+ myIconOpen = presentation == null ? null : ComputableIcon.create(presentation, true);
+ myIconClosed = presentation == null ? null : ComputableIcon.create(presentation, false);
+ myPresentableText = presentation == null ? UsageViewUtil.createNodeText(element) : presentation.getPresentableText();
+ if (myIconOpen == null || myIconClosed == null) {
+ if (element instanceof PsiMetaOwner) {
+ final PsiMetaOwner psiMetaOwner = (PsiMetaOwner)element;
+ final PsiMetaData metaData = psiMetaOwner.getMetaData();
+ if (metaData instanceof PsiPresentableMetaData) {
+ final PsiPresentableMetaData psiPresentableMetaData = (PsiPresentableMetaData)metaData;
+ if (myIconOpen == null) myIconOpen = ComputableIcon.create(psiPresentableMetaData);
+ if (myIconClosed == null) myIconClosed = ComputableIcon.create(psiPresentableMetaData);
}
- else if (element instanceof PsiFile) {
- final PsiFile psiFile = (PsiFile)element;
- final VirtualFile virtualFile = psiFile.getVirtualFile();
- if (virtualFile != null) {
- myIconOpen = ComputableIcon.create(virtualFile);
- myIconClosed = ComputableIcon.create(virtualFile);
- }
+ }
+ else if (element instanceof PsiFile) {
+ final PsiFile psiFile = (PsiFile)element;
+ final VirtualFile virtualFile = psiFile.getVirtualFile();
+ if (virtualFile != null) {
+ myIconOpen = ComputableIcon.create(virtualFile);
+ myIconClosed = ComputableIcon.create(virtualFile);
}
}
}
}
+ }
- @Override
- public String getPresentableText() {
- return myPresentableText;
- }
+ @Override
+ public String getPresentableText() {
+ return myPresentableText;
+ }
- @Override
- public String getLocationString() {
- return null;
- }
+ @Override
+ public String getLocationString() {
+ return null;
+ }
- @Override
- public Icon getIcon(boolean open) {
- final ComputableIcon computableIcon = open ? myIconOpen : myIconClosed;
- return computableIcon == null? null : computableIcon.getIcon();
- }
+ @Override
+ public Icon getIcon(boolean open) {
+ final ComputableIcon computableIcon = open ? myIconOpen : myIconClosed;
+ return computableIcon == null ? null : computableIcon.getIcon();
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java
new file mode 100644
index 0000000..a16050a
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/PsiElement2UsageTargetComposite.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.findUsages;
+
+import com.intellij.find.FindManager;
+import com.intellij.find.FindSettings;
+import com.intellij.find.impl.FindManagerImpl;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.usages.UsageInfoToUsageConverter;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+public class PsiElement2UsageTargetComposite extends PsiElement2UsageTargetAdapter {
+ private final UsageInfoToUsageConverter.TargetElementsDescriptor myDescriptor;
+ public PsiElement2UsageTargetComposite(@NotNull PsiElement[] primaryElements,
+ @NotNull PsiElement[] secondaryElements,
+ @NotNull FindUsagesOptions options) {
+ super(primaryElements[0], options);
+ myDescriptor = new UsageInfoToUsageConverter.TargetElementsDescriptor(primaryElements, secondaryElements);
+ }
+
+ @Override
+ public void findUsages() {
+ PsiElement element = getElement();
+ if (element == null) return;
+ FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(element.getProject())).getFindUsagesManager();
+ FindUsagesHandler handler = findUsagesManager.getNewFindUsagesHandler(element, false);
+ boolean skipResultsWithOneUsage = FindSettings.getInstance().isSkipResultsWithOneUsage();
+ findUsagesManager.findUsages(myDescriptor.getPrimaryElements(), myDescriptor.getAdditionalElements(), handler, myOptions, skipResultsWithOneUsage);
+ }
+
+ @Override
+ public VirtualFile[] getFiles() {
+ Set<VirtualFile> files = ContainerUtil.map2Set(myDescriptor.getAllElements(), new Function<PsiElement, VirtualFile>() {
+ @Override
+ public VirtualFile fun(PsiElement element) {
+ return PsiUtilCore.getVirtualFile(element);
+ }
+ });
+ return VfsUtilCore.toVirtualFileArray(files);
+ }
+
+ @NotNull
+ public PsiElement[] getPrimaryElements() {
+ return myDescriptor.getPrimaryElements();
+ }
+ @NotNull
+ public PsiElement[] getSecondaryElements() {
+ return myDescriptor.getAdditionalElements();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.java b/platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.java
new file mode 100644
index 0000000..7bd5147
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/find/findUsages/UsageHistory.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 com.intellij.find.findUsages;
+
+import com.intellij.openapi.util.Condition;
+import com.intellij.usages.ConfigurableUsageTarget;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+public class UsageHistory {
+ // the last element is the most recent
+ private final List<ConfigurableUsageTarget> myHistory = ContainerUtil.createLockFreeCopyOnWriteList();
+
+ public void add(@NotNull ConfigurableUsageTarget usageTarget) {
+ final String descriptiveName = usageTarget.getLongDescriptiveName();
+ ContainerUtil.retainAll(myHistory, new Condition<ConfigurableUsageTarget>() {
+ @Override
+ public boolean value(ConfigurableUsageTarget existing) {
+ return !existing.getLongDescriptiveName().equals(descriptiveName);
+ }
+ });
+ myHistory.add(usageTarget);
+
+ // todo configure history depth limit
+ if (myHistory.size() > 15) {
+ myHistory.remove(0);
+ }
+ }
+
+ @NotNull
+ public List<ConfigurableUsageTarget> getAll() {
+ removeInvalidElementsFromHistory();
+ return Collections.unmodifiableList(myHistory);
+ }
+
+ private void removeInvalidElementsFromHistory() {
+ for (ConfigurableUsageTarget target : myHistory) {
+ if (!target.isValid()) myHistory.remove(target);
+ }
+ }
+
+}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
index 417ad69..e7c4aac 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindDialog.java
@@ -64,8 +64,10 @@
import javax.swing.text.BadLocationException;
import java.awt.*;
import java.awt.event.*;
-import java.util.*;
+import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@@ -766,7 +768,7 @@
}
Arrays.sort(names,String.CASE_INSENSITIVE_ORDER);
- myModuleComboBox = new ComboBox(names, -1);
+ myModuleComboBox = new ComboBox(names);
scopePanel.add(myModuleComboBox, gbConstraints);
if (modules.length == 1) {
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 c088619..48fe5db 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindInProjectUtil.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,11 +20,10 @@
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.CommonDataKeys;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.editor.Document;
@@ -147,7 +146,7 @@
break;
}
if(virtualFile == null){
- virtualFile = file;
+ virtualFile = file;
}
}
}
@@ -206,7 +205,7 @@
return Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
}
- public static void findUsages(@NotNull final FindModel findModel,
+ public static void findUsages(@NotNull FindModel findModel,
final PsiDirectory psiDirectory,
@NotNull final Project project,
boolean showWarnings,
@@ -254,9 +253,10 @@
totalFilesSize += fileLength;
if (totalFilesSize > FILES_SIZE_LIMIT && !warningShown[0]) {
warningShown[0] = true;
- String message = FindBundle.message("find.excessive.total.size.prompt", UsageViewManagerImpl.presentableSize(totalFilesSize),
+ String message = FindBundle.message("find.excessive.total.size.prompt",
+ UsageViewManagerImpl.presentableSize(totalFilesSize),
ApplicationNamesInfo.getInstance().getProductName());
- UsageLimitUtil.showAndCancelIfAborted(project, message);
+ UsageLimitUtil.showAndCancelIfAborted(project, message, processPresentation.getUsageViewPresentation());
}
}
}
@@ -280,11 +280,11 @@
@NotNull final Processor<UsageInfo> consumer) {
if (findModel.getStringToFind().isEmpty()) {
if (!ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
- @Override
- public Boolean compute() {
- return consumer.process(new UsageInfo(psiFile,0,0,true));
- }
- })) {
+ @Override
+ public Boolean compute() {
+ return consumer.process(new UsageInfo(psiFile,0,0,true));
+ }
+ })) {
throw new ProcessCanceledException();
}
return 1;
@@ -328,8 +328,13 @@
private static Collection<PsiFile> getFilesToSearchIn(@NotNull final FindModel findModel,
@NotNull final Project project,
final PsiDirectory psiDirectory) {
- String moduleName = findModel.getModuleName();
- Module module = moduleName == null ? null : ModuleManager.getInstance(project).findModuleByName(moduleName);
+ 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();
@@ -380,8 +385,13 @@
if (psiDirectory == null) {
boolean success = fileIndex.iterateContent(iterator);
if (success && globalCustomScope != null && globalCustomScope.isSearchInLibraries()) {
- OrderEnumerator enumerator = module == null ? OrderEnumerator.orderEntries(project) : OrderEnumerator.orderEntries(module);
- final VirtualFile[] librarySources = enumerator.withoutModuleSourceEntries().withoutDepModules().getSourceRoots();
+ 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);
}
}
@@ -449,7 +459,8 @@
@NotNull final Project project,
@Nullable final PsiDirectory psiDirectory,
final Pattern fileMaskRegExp,
- @Nullable final Module module, FileIndex fileIndex) {
+ @Nullable final Module module,
+ @NotNull FileIndex fileIndex) {
if (DumbService.getInstance(project).isDumb()) {
return new Pair<Boolean, Collection<PsiFile>>(false, Collections.<PsiFile>emptyList());
}
@@ -567,7 +578,7 @@
}
private static int addToUsages(@NotNull Document document, @NotNull Processor<UsageInfo> consumer, @NotNull FindModel findModel,
- @NotNull final PsiFile psiFile, int[] offsetRef, int maxUsages) {
+ @NotNull final PsiFile psiFile, @NotNull int[] offsetRef, int maxUsages) {
int count = 0;
CharSequence text = document.getCharsSequence();
int textLength = document.getTextLength();
@@ -606,45 +617,48 @@
return count;
}
+ @NotNull
private static String getTitleForScope(@NotNull final FindModel findModel) {
- String result;
-
+ String scopeName;
if (findModel.isProjectScope()) {
- result = FindBundle.message("find.scope.project.title");
+ scopeName = FindBundle.message("find.scope.project.title");
}
else if (findModel.getModuleName() != null) {
- result = FindBundle.message("find.scope.module.title", findModel.getModuleName());
+ scopeName = FindBundle.message("find.scope.module.title", findModel.getModuleName());
}
else if(findModel.getCustomScopeName() != null) {
- result = findModel.getCustomScopeName();
+ scopeName = findModel.getCustomScopeName();
}
else {
- result = FindBundle.message("find.scope.directory.title", findModel.getDirectoryName());
+ scopeName = FindBundle.message("find.scope.directory.title", findModel.getDirectoryName());
}
+ String result = scopeName;
if (findModel.getFileFilter() != null) {
- result = FindBundle.message("find.scope.files.with.mask", result, findModel.getFileFilter());
+ result += " "+FindBundle.message("find.scope.files.with.mask", findModel.getFileFilter());
}
return result;
}
@NotNull
- public static UsageViewPresentation setupViewPresentation(final boolean toOpenInNewTab, @NotNull final FindModel findModelCopy) {
+ public static UsageViewPresentation setupViewPresentation(final boolean toOpenInNewTab, @NotNull FindModel findModel) {
final UsageViewPresentation presentation = new UsageViewPresentation();
- final String scope = getTitleForScope(findModelCopy);
- final String stringToFind = findModelCopy.getStringToFind();
+ final String scope = getTitleForScope(findModel);
+ final String stringToFind = findModel.getStringToFind();
presentation.setScopeText(scope);
if (stringToFind.isEmpty()) {
presentation.setTabText("Files");
- presentation.setToolwindowTitle(BundleBase.format("Files in ''{0}''", scope));
+ presentation.setToolwindowTitle(BundleBase.format("Files in {0}", scope));
presentation.setUsagesString("files");
}
else {
presentation.setTabText(FindBundle.message("find.usage.view.tab.text", stringToFind));
presentation.setToolwindowTitle(FindBundle.message("find.usage.view.toolwindow.title", stringToFind, scope));
presentation.setUsagesString(FindBundle.message("find.usage.view.usages.text", stringToFind));
+ presentation.setUsagesWord(FindBundle.message("occurrence"));
+ presentation.setCodeUsagesString(FindBundle.message("found.occurrences"));
}
presentation.setOpenInNewTab(toOpenInNewTab);
presentation.setCodeUsages(false);
@@ -656,9 +670,8 @@
public static FindUsagesProcessPresentation setupProcessPresentation(final Project project,
final boolean showPanelIfOnlyOneUsage,
@NotNull final UsageViewPresentation presentation) {
- FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation();
+ FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation(presentation);
processPresentation.setShowNotFoundMessage(true);
- processPresentation.setShowFindOptionsPrompt(false);
processPresentation.setShowPanelIfOnlyOneUsage(showPanelIfOnlyOneUsage);
processPresentation.setProgressIndicatorFactory(
new Factory<ProgressIndicator>() {
@@ -672,34 +685,43 @@
return processPresentation;
}
- public static class StringUsageTarget implements ConfigurableUsageTarget {
- @NotNull private final Project myProject;
- private final String myStringToFind;
+ public static class StringUsageTarget implements ConfigurableUsageTarget, ItemPresentation {
+ @NotNull protected final Project myProject;
+ @NotNull protected final FindModel myFindModel;
- private final ItemPresentation myItemPresentation = new ItemPresentation() {
- @Override
- public String getPresentableText() {
- return FindBundle.message("find.usage.target.string.text", myStringToFind);
- }
-
- @Override
- public String getLocationString() {
- return myStringToFind + "!!";
- }
-
- @Override
- public Icon getIcon(boolean open) {
- return null;
- }
- };
-
- public StringUsageTarget(@NotNull Project project, @NotNull String _stringToFind) {
+ public StringUsageTarget(@NotNull Project project, @NotNull FindModel findModel) {
myProject = project;
- myStringToFind = _stringToFind;
+ myFindModel = findModel;
}
@Override
- public void findUsages() {}
+ @NotNull
+ public String getPresentableText() {
+ UsageViewPresentation presentation = setupViewPresentation(false, myFindModel);
+ return presentation.getToolwindowTitle();
+ }
+
+ @NotNull
+ @Override
+ public String getLongDescriptiveName() {
+ return getPresentableText();
+ }
+
+ @Override
+ public String getLocationString() {
+ return myFindModel + "!!";
+ }
+
+ @Override
+ public Icon getIcon(boolean open) {
+ return AllIcons.Actions.Menu_find;
+ }
+
+ @Override
+ public void findUsages() {
+ FindInProjectManager.getInstance(myProject).startFindInProject(myFindModel);
+ }
+
@Override
public void findUsagesInEditor(@NotNull FileEditor editor) {}
@Override
@@ -727,12 +749,12 @@
@Override
public String getName() {
- return myStringToFind;
+ return myFindModel.getStringToFind().isEmpty() ? myFindModel.getFileFilter() : myFindModel.getStringToFind();
}
@Override
public ItemPresentation getPresentation() {
- return myItemPresentation;
+ return this;
}
@Override
@@ -757,5 +779,10 @@
FindInProjectManager findInProjectManager = FindInProjectManager.getInstance(myProject);
findInProjectManager.findInProject(DataManager.getInstance().getDataContext(component));
}
+
+ @Override
+ public KeyboardShortcut getShortcut() {
+ return ActionManager.getInstance().getKeyboardShortcut("FindInPath");
+ }
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
index 59c3ca8..6400db8 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindManagerImpl.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,6 @@
import com.intellij.lang.ParserDefinition;
import com.intellij.lexer.LayeredLexer;
import com.intellij.lexer.Lexer;
-import com.intellij.lexer.LexerUtil;
import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
@@ -55,7 +54,6 @@
import com.intellij.openapi.fileTypes.impl.AbstractFileType;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -467,12 +465,9 @@
public Set<Language> compute() {
THashSet<Language> result = new THashSet<Language>();
- for(Project project: ProjectManager.getInstance().getOpenProjects()) {
- FileViewProvider viewProvider = PsiManager.getInstance(project).findViewProvider(file);
- if (viewProvider != null) {
- result.addAll(viewProvider.getLanguages());
- break;
- }
+ FileViewProvider viewProvider = PsiManager.getInstance(myProject).findViewProvider(file);
+ if (viewProvider != null) {
+ result.addAll(viewProvider.getLanguages());
}
if (result.isEmpty()) {
@@ -1059,7 +1054,8 @@
}
});
}
-
+
+ @NotNull
public FindUsagesManager getFindUsagesManager() {
return myFindUsagesManager;
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
index 138af2c..2c37279 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/FindResultUsageInfo.java
@@ -1,3 +1,18 @@
+/*
+ * 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.find.impl;
import com.intellij.find.FindManager;
@@ -16,14 +31,14 @@
import org.jetbrains.annotations.NotNull;
public class FindResultUsageInfo extends UsageInfo {
- private FindManager myFindManager;
- private FindModel myFindModel;
+ private final FindManager myFindManager;
+ private final FindModel myFindModel;
private SmartPsiFileRange myAnchor;
private Boolean myCachedResult;
private long myTimestamp = 0;
- private static Key<Long> ourDocumentTimestampKey = Key.create("com.intellij.find.impl.FindResultUsageInfo.documentTimestamp");
+ private static final Key<Long> ourDocumentTimestampKey = Key.create("com.intellij.find.impl.FindResultUsageInfo.documentTimestamp");
@Override
public boolean isValid() {
@@ -35,40 +50,52 @@
return false;
}
- if (document.getModificationStamp() == myTimestamp && myCachedResult != null) {
- return myCachedResult;
- } else {
- myTimestamp = document.getModificationStamp();
+ Boolean cachedResult = myCachedResult;
+ if (document.getModificationStamp() == myTimestamp && cachedResult != null) {
+ return cachedResult;
}
+ myTimestamp = document.getModificationStamp();
- Segment segment = super.getSegment();
- if (segment == null) return myCachedResult = false;
+ Segment segment = getSegment();
+ if (segment == null) {
+ myCachedResult = false;
+ return false;
+ }
VirtualFile file = getPsiFile().getVirtualFile();
Segment searchOffset;
if (myAnchor != null) {
searchOffset = myAnchor.getRange();
- if (searchOffset == null) return myCachedResult = false;
- } else {
+ if (searchOffset == null) {
+ myCachedResult = false;
+ return false;
+ }
+ }
+ else {
searchOffset = segment;
}
int offset = searchOffset.getStartOffset();
- FindResult result;
Long data = myFindModel.getUserData(ourDocumentTimestampKey);
if (data == null || data != myTimestamp) {
data = myTimestamp;
myFindModel.putUserData(FindManagerImpl.ourCommentsLiteralsSearchDataKey, null);
}
myFindModel.putUserData(ourDocumentTimestampKey, data);
+ FindResult result;
do {
result = myFindManager.findString(document.getCharsSequence(), offset, myFindModel, file);
offset = result.getEndOffset() == offset ? offset + 1 : result.getEndOffset();
- if (!result.isStringFound()) return myCachedResult = false;
+ if (!result.isStringFound()) {
+ myCachedResult = false;
+ return false;
+ }
} while (result.getStartOffset() < segment.getStartOffset());
- return myCachedResult = (segment.getStartOffset() == result.getStartOffset() && segment.getEndOffset() == result.getEndOffset());
+ boolean ret = segment.getStartOffset() == result.getStartOffset() && segment.getEndOffset() == result.getEndOffset();
+ myCachedResult = ret;
+ return ret;
}
private PsiFile getPsiFile() {
diff --git a/platform/lang-impl/src/com/intellij/find/impl/HelpID.java b/platform/lang-impl/src/com/intellij/find/impl/HelpID.java
index 3e769d2..0479f91 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/HelpID.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/HelpID.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -23,10 +23,8 @@
@NonNls String FIND_PACKAGE_USAGES = "reference.dialogs.findUsages.package";
@NonNls String FIND_CLASS_USAGES = "reference.dialogs.findUsages.class";
@NonNls String FIND_METHOD_USAGES = "reference.dialogs.findUsages.method";
- @NonNls String FIND_OTHER_USAGES = "reference.dialogs.findUsages.other";
@NonNls String FIND_THROW_USAGES = "reference.dialogs.findUsages.throwUsages";
-
@NonNls String FIND_IN_PROJECT = "find.findInProject";
@NonNls String REPLACE_IN_PROJECT = "find.findInProject";
diff --git a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java
index 77835ad..4a72450 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesAction.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,21 +19,16 @@
import com.intellij.find.FindBundle;
import com.intellij.find.FindManager;
import com.intellij.find.findUsages.FindUsagesManager;
-import com.intellij.lang.findUsages.DescriptiveNameUtil;
+import com.intellij.navigation.ItemPresentation;
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.project.Project;
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.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.search.ProjectScope;
import com.intellij.ui.awt.RelativePoint;
-import com.intellij.usageView.UsageViewBundle;
-import com.intellij.usageView.UsageViewUtil;
+import com.intellij.usages.ConfigurableUsageTarget;
import com.intellij.usages.UsageView;
import org.jetbrains.annotations.NotNull;
@@ -60,7 +55,7 @@
UsageView usageView = e.getData(UsageView.USAGE_VIEW_KEY);
Project project = e.getData(CommonDataKeys.PROJECT);
final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
- List<FindUsagesManager.SearchData> history = new ArrayList<FindUsagesManager.SearchData>(findUsagesManager.getFindUsageHistory());
+ List<ConfigurableUsageTarget> history = new ArrayList<ConfigurableUsageTarget>(findUsagesManager.getHistory().getAll());
if (!history.isEmpty()) {
// skip most recent find usage, it's under your nose
@@ -68,42 +63,32 @@
Collections.reverse(history);
}
if (history.isEmpty()) {
- history.add(new FindUsagesManager.SearchData()); // to fill the popup
+ history.add(null); // to fill the popup
}
- BaseListPopupStep<FindUsagesManager.SearchData> step =
- new BaseListPopupStep<FindUsagesManager.SearchData>(FindBundle.message("recent.find.usages.action.title"), history) {
+ BaseListPopupStep<ConfigurableUsageTarget> step =
+ new BaseListPopupStep<ConfigurableUsageTarget>(FindBundle.message("recent.find.usages.action.title"), history) {
@Override
- public Icon getIconFor(final FindUsagesManager.SearchData data) {
- if (data.myElements == null) {
- return null;
- }
- PsiElement psiElement = data.myElements[0].getElement();
- if (psiElement == null) return null;
- return psiElement.getIcon(0);
+ public Icon getIconFor(final ConfigurableUsageTarget data) {
+ ItemPresentation presentation = data == null ? null : data.getPresentation();
+ return presentation == null ? null : presentation.getIcon(false);
}
@Override
@NotNull
- public String getTextFor(final FindUsagesManager.SearchData data) {
- if (data.myElements == null) {
+ public String getTextFor(final ConfigurableUsageTarget data) {
+ if (data == null) {
return FindBundle.message("recent.find.usages.action.nothing");
}
- PsiElement psiElement = data.myElements[0].getElement();
- if (psiElement == null) return UsageViewBundle.message("node.invalid");
- String scopeString = data.myOptions.searchScope == null ? null : data.myOptions.searchScope.getDisplayName();
- return FindBundle.message("recent.find.usages.action.description",
- StringUtil.capitalize(UsageViewUtil.getType(psiElement)),
- DescriptiveNameUtil.getDescriptiveName(psiElement),
- scopeString == null ? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName() : scopeString);
+ return data.getLongDescriptiveName();
}
@Override
- public PopupStep onChosen(final FindUsagesManager.SearchData selectedValue, final boolean finalChoice) {
+ public PopupStep onChosen(final ConfigurableUsageTarget selectedValue, final boolean finalChoice) {
return doFinalStep(new Runnable() {
@Override
public void run() {
- if (selectedValue.myElements != null) {
+ if (selectedValue != null) {
findUsagesManager.rerunAndRecallFromHistory(selectedValue);
}
}
@@ -118,6 +103,5 @@
point = new RelativePoint(usageView.getComponent(), new Point(4, 4));
}
JBPopupFactory.getInstance().createListPopup(step).show(point);
-
}
}
diff --git a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java
index d9752a7..ccbb996 100644
--- a/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.java
+++ b/platform/lang-impl/src/com/intellij/find/impl/ShowRecentFindUsagesGroup.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,16 +16,11 @@
package com.intellij.find.impl;
-import com.intellij.find.FindBundle;
import com.intellij.find.FindManager;
import com.intellij.find.findUsages.FindUsagesManager;
-import com.intellij.lang.findUsages.DescriptiveNameUtil;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.search.ProjectScope;
-import com.intellij.usageView.UsageViewUtil;
+import com.intellij.usages.ConfigurableUsageTarget;
import com.intellij.usages.impl.UsageViewImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,27 +47,22 @@
Project project = e.getData(CommonDataKeys.PROJECT);
if (project == null) return EMPTY_ARRAY;
final FindUsagesManager findUsagesManager = ((FindManagerImpl)FindManager.getInstance(project)).getFindUsagesManager();
- List<FindUsagesManager.SearchData> history = new ArrayList<FindUsagesManager.SearchData>(findUsagesManager.getFindUsageHistory());
+ List<ConfigurableUsageTarget> history = new ArrayList<ConfigurableUsageTarget>(findUsagesManager.getHistory().getAll());
Collections.reverse(history);
String description =
ActionManager.getInstance().getAction(UsageViewImpl.SHOW_RECENT_FIND_USAGES_ACTION_ID).getTemplatePresentation().getDescription();
List<AnAction> children = new ArrayList<AnAction>(history.size());
- for (final FindUsagesManager.SearchData data : history) {
- if (data.myElements == null) {
+ for (final ConfigurableUsageTarget usageTarget : history) {
+ if (!usageTarget.isValid()) {
continue;
}
- PsiElement psiElement = data.myElements[0].getElement();
- if (psiElement == null) continue;
- String scopeString = data.myOptions.searchScope == null ? null : data.myOptions.searchScope.getDisplayName();
- String text = FindBundle.message("recent.find.usages.action.popup", StringUtil.capitalize(UsageViewUtil.getType(psiElement)),
- DescriptiveNameUtil.getDescriptiveName(psiElement),
- scopeString == null ? ProjectScope.getAllScope(psiElement.getProject()).getDisplayName() : scopeString);
- AnAction action = new AnAction(text, description, psiElement.getIcon(0)) {
+ String text = usageTarget.getLongDescriptiveName();
+ AnAction action = new AnAction(text, description, null) {
@Override
public void actionPerformed(final AnActionEvent e) {
- findUsagesManager.rerunAndRecallFromHistory(data);
+ findUsagesManager.rerunAndRecallFromHistory(usageTarget);
}
};
children.add(action);
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 b9ceb43..86fe9de 100644
--- a/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
+++ b/platform/lang-impl/src/com/intellij/find/replaceInProject/ReplaceInProjectManager.java
@@ -1,28 +1,31 @@
/*
-* 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.
-*/
+ * Copyright 2000-2014 JetBrains s.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.replaceInProject;
import com.intellij.find.*;
+import com.intellij.find.actions.FindInPathAction;
import com.intellij.find.findInProject.FindInProjectManager;
import com.intellij.find.impl.FindInProjectUtil;
+import com.intellij.ide.DataManager;
import com.intellij.notification.NotificationGroup;
+import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.components.ServiceManager;
@@ -39,14 +42,15 @@
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.StatusBar;
-import com.intellij.openapi.wm.ToolWindowId;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
-import com.intellij.usageView.UsageInfo;
+import com.intellij.ui.content.Content;
+import com.intellij.usageView.*;
import com.intellij.usages.*;
+import com.intellij.usages.UsageViewManager;
import com.intellij.usages.impl.UsageViewImpl;
import com.intellij.usages.rules.UsageInFile;
import com.intellij.util.AdapterProcessor;
@@ -58,7 +62,7 @@
import java.util.*;
public class ReplaceInProjectManager {
- static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("FindInPath", ToolWindowId.FIND, false);
+ static final NotificationGroup NOTIFICATION_GROUP = FindInPathAction.NOTIFICATION_GROUP;
private final Project myProject;
private boolean myIsFindInProgress = false;
@@ -155,6 +159,32 @@
searchAndShowUsages(manager, usageSearcherFactory, findModelCopy, presentation, processPresentation, findManager);
}
+ private static class ReplaceInProjectTarget extends FindInProjectUtil.StringUsageTarget {
+ public ReplaceInProjectTarget(@NotNull Project project, @NotNull FindModel findModel) {
+ super(project, findModel);
+ }
+
+ @NotNull
+ @Override
+ public String getLongDescriptiveName() {
+ UsageViewPresentation presentation = FindInProjectUtil.setupViewPresentation(false, myFindModel);
+ return "Replace "+presentation.getToolwindowTitle()+" with '"+ myFindModel.getStringToReplace()+"'";
+ }
+
+ @Override
+ public KeyboardShortcut getShortcut() {
+ return ActionManager.getInstance().getKeyboardShortcut("ReplaceInPath");
+ }
+
+ @Override
+ public void showSettings() {
+ Content selectedContent = com.intellij.usageView.UsageViewManager.getInstance(myProject).getSelectedContent(true);
+ JComponent component = selectedContent == null ? null : selectedContent.getComponent();
+ ReplaceInProjectManager findInProjectManager = getInstance(myProject);
+ findInProjectManager.replaceInProject(DataManager.getInstance().getDataContext(component));
+ }
+ }
+
public void searchAndShowUsages(@NotNull UsageViewManager manager,
@NotNull Factory<UsageSearcher> usageSearcherFactory,
@NotNull final FindModel findModelCopy,
@@ -163,7 +193,7 @@
final FindManager findManager) {
presentation.setMergeDupLinesAvailable(false);
final ReplaceContext[] context = new ReplaceContext[1];
- manager.searchAndShowUsages(new UsageTarget[]{new FindInProjectUtil.StringUsageTarget(myProject, findModelCopy.getStringToFind())},
+ manager.searchAndShowUsages(new UsageTarget[]{new ReplaceInProjectTarget(myProject, findModelCopy)},
usageSearcherFactory, processPresentation, presentation, new UsageViewManager.UsageViewStateListener() {
@Override
public void usageViewCreated(@NotNull UsageView usageView) {
@@ -490,7 +520,7 @@
FindBundle.message("find.replace.occurrences.in.read.only.files.prompt"),
FindBundle.message("find.replace.occurrences.in.read.only.files.title"),
Messages.getWarningIcon());
- if (result != 0) {
+ if (result != Messages.OK) {
return false;
}
}
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionContextImpl.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionContextImpl.java
index f88f9a3..c4cb76e 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionContextImpl.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/FrameworkDetectionContextImpl.java
@@ -23,12 +23,12 @@
import com.intellij.framework.detection.FacetBasedFrameworkDetector;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.FacetsProvider;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.containers.MultiMapBasedOnSet;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -57,9 +57,9 @@
@Override
public <F extends Facet, C extends FacetConfiguration> List<? extends DetectedFrameworkDescription> createDetectedFacetDescriptions(@NotNull FacetBasedFrameworkDetector<F, C> detector,
@NotNull Collection<VirtualFile> files) {
- MultiMapBasedOnSet<Module, VirtualFile> filesByModule = new MultiMapBasedOnSet<Module, VirtualFile>();
+ MultiMap<Module, VirtualFile> filesByModule = MultiMap.createSet();
for (VirtualFile file : files) {
- final Module module = ModuleUtil.findModuleForFile(file, myProject);
+ final Module module = ModuleUtilCore.findModuleForFile(file, myProject);
if (module != null) {
filesByModule.putValue(module, file);
}
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
index 436ee1c..88d675b 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurable.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.ui.popup.PopupStep;
@@ -39,6 +40,8 @@
import javax.swing.*;
import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.util.*;
import java.util.List;
@@ -50,6 +53,7 @@
private final DetectionExcludesConfigurationImpl myConfiguration;
private final SortedListModel<ExcludeListItem> myModel;
private JPanel myMainPanel;
+ private JCheckBox myEnabledDetectionCheckBox;
public DetectionExcludesConfigurable(@NotNull Project project, @NotNull DetectionExcludesConfigurationImpl configuration) {
myProject = project;
@@ -61,7 +65,7 @@
@Override
@NotNull
public JComponent createComponent() {
- myMainPanel = new JPanel(new BorderLayout());
+ myEnabledDetectionCheckBox = new JCheckBox("Enable framework detection");
final JBList excludesList = new JBList(myModel);
excludesList.setCellRenderer(new ColoredListCellRenderer() {
@Override
@@ -79,8 +83,17 @@
doAddAction(button);
}
});
- myMainPanel.add(new JLabel("Exclude from detection:"), BorderLayout.NORTH);
- myMainPanel.add(decorator.createPanel());
+ myMainPanel = new JPanel(new BorderLayout(0, 5));
+ myMainPanel.add(myEnabledDetectionCheckBox, BorderLayout.NORTH);
+ final LabeledComponent<JPanel> excludesComponent = LabeledComponent.create(decorator.createPanel(), "Exclude from detection:");
+ myMainPanel.add(excludesComponent);
+ myEnabledDetectionCheckBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ GuiUtils.enableChildren(myEnabledDetectionCheckBox.isSelected(), excludesComponent);
+ }
+ });
+ myEnabledDetectionCheckBox.setSelected(true);
return myMainPanel;
}
@@ -218,10 +231,11 @@
@Nullable
private ExcludesConfigurationState computeState() {
- if (myModel.getItems().isEmpty()) {
+ if (myModel.getItems().isEmpty() && myEnabledDetectionCheckBox.isSelected()) {
return null;
}
final ExcludesConfigurationState state = new ExcludesConfigurationState();
+ state.setDetectionEnabled(myEnabledDetectionCheckBox.isSelected());
for (ExcludeListItem item : myModel.getItems()) {
final String url = item.getFileUrl();
final String typeId = item.getFrameworkTypeId();
@@ -239,6 +253,7 @@
public void reset() {
myModel.clear();
final ExcludesConfigurationState state = myConfiguration.getActualState();
+ myEnabledDetectionCheckBox.setSelected(state == null || state.isDetectionEnabled());
if (state != null) {
for (String typeId : state.getFrameworkTypes()) {
final FrameworkType frameworkType = FrameworkDetectorRegistry.getInstance().findFrameworkType(typeId);
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java
index 179c3cf..a110e34 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/DetectionExcludesConfigurationImpl.java
@@ -54,6 +54,7 @@
private Set<String> myExcludedFrameworks;
private final Project myProject;
private VirtualFilePointerManager myPointerManager;
+ private boolean myDetectionEnabled = true;
private boolean myConverted;
public DetectionExcludesConfigurationImpl(Project project, VirtualFilePointerManager pointerManager) {
@@ -143,7 +144,7 @@
@Override
public boolean isExcludedFromDetection(@NotNull FrameworkType frameworkType) {
ensureOldSettingsLoaded();
- return myExcludedFrameworks.contains(frameworkType.getId());
+ return !myDetectionEnabled || myExcludedFrameworks.contains(frameworkType.getId());
}
private boolean isFileExcluded(@NotNull VirtualFile file, @Nullable String typeId) {
@@ -170,7 +171,7 @@
public void removeExcluded(@NotNull Collection<VirtualFile> files, final FrameworkType frameworkType) {
ensureOldSettingsLoaded();
- if (myExcludedFrameworks.contains(frameworkType.getId())) {
+ if (!myDetectionEnabled || myExcludedFrameworks.contains(frameworkType.getId())) {
files.clear();
return;
}
@@ -187,11 +188,12 @@
@Nullable
public ExcludesConfigurationState getActualState() {
ensureOldSettingsLoaded();
- if (myExcludedFiles.isEmpty() && myExcludedFrameworks.isEmpty()) {
+ if (myExcludedFiles.isEmpty() && myExcludedFrameworks.isEmpty() && myDetectionEnabled) {
return null;
}
final ExcludesConfigurationState state = new ExcludesConfigurationState();
+ state.setDetectionEnabled(myDetectionEnabled);
state.getFrameworkTypes().addAll(myExcludedFrameworks);
Collections.sort(state.getFrameworkTypes(), String.CASE_INSENSITIVE_ORDER);
@@ -219,7 +221,7 @@
@Override
public void loadState(@Nullable ExcludesConfigurationState state) {
doLoadState(state);
- if (!myExcludedFiles.isEmpty() || !myExcludedFrameworks.isEmpty()) {
+ if (!myExcludedFiles.isEmpty() || !myExcludedFrameworks.isEmpty() || !myDetectionEnabled) {
markAsConverted();
}
}
@@ -229,6 +231,7 @@
for (VirtualFilePointerContainer container : myExcludedFiles.values()) {
container.clear();
}
+ myDetectionEnabled = state == null || state.isDetectionEnabled();
if (state != null) {
myExcludedFrameworks.addAll(state.getFrameworkTypes());
for (ExcludedFileState fileState : state.getFiles()) {
diff --git a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java
index fd82264..e110b42 100644
--- a/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java
+++ b/platform/lang-impl/src/com/intellij/framework/detection/impl/exclude/ExcludesConfigurationState.java
@@ -17,6 +17,7 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Property;
import java.util.ArrayList;
@@ -28,6 +29,7 @@
public class ExcludesConfigurationState {
private List<String> myFrameworkTypes = new ArrayList<String>();
private List<ExcludedFileState> myFiles = new ArrayList<ExcludedFileState>();
+ private boolean myDetectionEnabled = true;
@Property(surroundWithTag = false)
@AbstractCollection(surroundWithTag = false, elementTag = "type", elementValueAttribute = "id")
@@ -41,6 +43,15 @@
return myFiles;
}
+ @Attribute("detection-enabled")
+ public boolean isDetectionEnabled() {
+ return myDetectionEnabled;
+ }
+
+ public void setDetectionEnabled(boolean detectionEnabled) {
+ myDetectionEnabled = detectionEnabled;
+ }
+
public void setFrameworkTypes(List<String> frameworkTypes) {
myFrameworkTypes = frameworkTypes;
}
@@ -55,11 +66,12 @@
if (!(o instanceof ExcludesConfigurationState)) return false;
ExcludesConfigurationState state = (ExcludesConfigurationState)o;
- return Comparing.haveEqualElements(myFiles, state.myFiles) && Comparing.haveEqualElements(myFrameworkTypes, state.myFrameworkTypes);
+ return myDetectionEnabled == state.myDetectionEnabled && Comparing.haveEqualElements(myFiles, state.myFiles)
+ && Comparing.haveEqualElements(myFrameworkTypes, state.myFrameworkTypes);
}
@Override
public int hashCode() {
- return 31 * myFrameworkTypes.hashCode() + myFiles.hashCode();
+ return 31 * myFrameworkTypes.hashCode() + myFiles.hashCode() + (myDetectionEnabled ? 1 : 0);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/FileListPasteProvider.java b/platform/lang-impl/src/com/intellij/ide/FileListPasteProvider.java
index 16a19eb..8d3a200 100644
--- a/platform/lang-impl/src/com/intellij/ide/FileListPasteProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/FileListPasteProvider.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,7 +21,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -50,6 +49,8 @@
final IdeView ideView = LangDataKeys.IDE_VIEW.getData(dataContext);
if (project == null || ideView == null) return;
+ if (!FileCopyPasteUtil.isFileListFlavorAvailable()) return;
+
final Transferable contents = CopyPasteManager.getInstance().getContents();
if (contents == null) return;
final List<File> fileList = FileCopyPasteUtil.getFileList(contents);
@@ -88,8 +89,7 @@
@Override
public boolean isPasteEnabled(@NotNull DataContext dataContext) {
- final Transferable contents = CopyPasteManager.getInstance().getContents();
- final IdeView ideView = LangDataKeys.IDE_VIEW.getData(dataContext);
- return contents != null && FileCopyPasteUtil.isFileListFlavorSupported(contents) && ideView != null;
+ return LangDataKeys.IDE_VIEW.getData(dataContext) != null &&
+ FileCopyPasteUtil.isFileListFlavorAvailable();
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java b/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java
new file mode 100644
index 0000000..5a6606b
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/GeneratedFileEditingNotificationProvider.java
@@ -0,0 +1,50 @@
+/*
+ * 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.ide;
+
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.EditorNotificationPanel;
+import com.intellij.ui.EditorNotifications;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public class GeneratedFileEditingNotificationProvider extends EditorNotifications.Provider<EditorNotificationPanel> {
+ private static final Key<EditorNotificationPanel> KEY = Key.create("generated.source.file.editing.notification.panel");
+ private final GeneratedSourceFileChangeTracker myChangeTracker;
+
+ public GeneratedFileEditingNotificationProvider(GeneratedSourceFileChangeTracker changeTracker) {
+ myChangeTracker = changeTracker;
+ }
+
+ @Override
+ public Key<EditorNotificationPanel> getKey() {
+ return KEY;
+ }
+
+ @Nullable
+ @Override
+ public EditorNotificationPanel createNotificationPanel(VirtualFile file, FileEditor fileEditor) {
+ if (!myChangeTracker.isEditedGeneratedFile(file)) return null;
+
+ EditorNotificationPanel panel = new EditorNotificationPanel();
+ panel.setText("Generated source files should not be edited. The changes will be lost when sources are regenerated.");
+ return panel;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/GeneratedSourceFileChangeTracker.java b/platform/lang-impl/src/com/intellij/ide/GeneratedSourceFileChangeTracker.java
new file mode 100644
index 0000000..8a655b8
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/GeneratedSourceFileChangeTracker.java
@@ -0,0 +1,37 @@
+/*
+ * 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.ide;
+
+import com.intellij.openapi.components.AbstractProjectComponent;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author nik
+ */
+public abstract class GeneratedSourceFileChangeTracker extends AbstractProjectComponent {
+ @NotNull
+ public static GeneratedSourceFileChangeTracker getInstance(@NotNull Project project) {
+ return project.getComponent(GeneratedSourceFileChangeTracker.class);
+ }
+
+ protected GeneratedSourceFileChangeTracker(Project project) {
+ super(project);
+ }
+
+ public abstract boolean isEditedGeneratedFile(@NotNull VirtualFile file);
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/GeneratedSourceFileChangeTrackerImpl.java b/platform/lang-impl/src/com/intellij/ide/GeneratedSourceFileChangeTrackerImpl.java
new file mode 100644
index 0000000..e1fbe73
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/GeneratedSourceFileChangeTrackerImpl.java
@@ -0,0 +1,143 @@
+/*
+ * 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.ide;
+
+import com.intellij.AppTopics;
+import com.intellij.openapi.application.ReadAction;
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.EditorFactory;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.fileEditor.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.GeneratedSourcesFilter;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.EditorNotifications;
+import com.intellij.util.Alarm;
+import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.ui.update.MergingUpdateQueue;
+import com.intellij.util.ui.update.Update;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.*;
+
+/**
+ * @author nik
+ */
+public class GeneratedSourceFileChangeTrackerImpl extends GeneratedSourceFileChangeTracker {
+ private final FileDocumentManager myDocumentManager;
+ private final EditorNotifications myEditorNotifications;
+ private final MergingUpdateQueue myCheckingQueue;
+ private final Set<VirtualFile> myFilesToCheck = Collections.synchronizedSet(new HashSet<VirtualFile>());
+ private final Set<VirtualFile> myEditedGeneratedFiles = Collections.synchronizedSet(new HashSet<VirtualFile>());
+
+ public GeneratedSourceFileChangeTrackerImpl(Project project, FileDocumentManager documentManager, EditorNotifications editorNotifications) {
+ super(project);
+ myDocumentManager = documentManager;
+ myEditorNotifications = editorNotifications;
+ myCheckingQueue = new MergingUpdateQueue("Checking for changes in generated sources", 500, false, null, project, null, Alarm.ThreadToUse.SHARED_THREAD);
+ }
+
+ @Override
+ public boolean isEditedGeneratedFile(@NotNull VirtualFile file) {
+ return myEditedGeneratedFiles.contains(file);
+ }
+
+ @Override
+ public void projectOpened() {
+ final Update check = new Update("check for changes in generated files") {
+ @Override
+ public void run() {
+ checkFiles();
+ }
+ };
+ EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
+ @Override
+ public void documentChanged(DocumentEvent e) {
+ VirtualFile file = myDocumentManager.getFile(e.getDocument());
+ if (file != null) {
+ myFilesToCheck.add(file);
+ myCheckingQueue.queue(check);
+ }
+ }
+ }, myProject);
+ MessageBusConnection connection = myProject.getMessageBus().connect();
+ connection.subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
+ @Override
+ public void fileContentReloaded(VirtualFile file, @NotNull Document document) {
+ myFilesToCheck.remove(file);
+ if (myEditedGeneratedFiles.remove(file)) {
+ myEditorNotifications.updateNotifications(file);
+ }
+ }
+ });
+ connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
+ @Override
+ public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {
+ myEditedGeneratedFiles.remove(file);
+ }
+ });
+ myCheckingQueue.activate();
+ }
+
+ @Override
+ public void projectClosed() {
+ myCheckingQueue.deactivate();
+ }
+
+ private void checkFiles() {
+ final VirtualFile[] files;
+ synchronized (myFilesToCheck) {
+ files = myFilesToCheck.toArray(new VirtualFile[myFilesToCheck.size()]);
+ myFilesToCheck.clear();
+ }
+ final List<VirtualFile> newEditedGeneratedFiles = new ArrayList<VirtualFile>();
+ new ReadAction() {
+ protected void run(final @NotNull Result result) {
+ if (myProject.isDisposed()) return;
+ for (VirtualFile file : files) {
+ if (isGenerated(file)) {
+ newEditedGeneratedFiles.add(file);
+ }
+ }
+ }
+ }.execute();
+
+ if (!newEditedGeneratedFiles.isEmpty()) {
+ List<VirtualFile> toNotify = new ArrayList<VirtualFile>();
+ synchronized (myEditedGeneratedFiles) {
+ for (VirtualFile file : newEditedGeneratedFiles) {
+ if (myEditedGeneratedFiles.add(file)) {
+ toNotify.add(file);
+ }
+ }
+ }
+ for (VirtualFile file : toNotify) {
+ myEditorNotifications.updateNotifications(file);
+ }
+ }
+ }
+
+ private boolean isGenerated(VirtualFile file) {
+ for (GeneratedSourcesFilter filter : GeneratedSourcesFilter.EP_NAME.getExtensions()) {
+ if (filter.isGeneratedSource(file, myProject)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java
index f42623b..d94bc7b 100644
--- a/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.java
+++ b/platform/lang-impl/src/com/intellij/ide/PsiCopyPasteManager.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,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.ide;
import com.intellij.ide.dnd.LinuxDragAndDropSupport;
@@ -67,26 +66,10 @@
});
}
-
@Nullable
public PsiElement[] getElements(boolean[] isCopied) {
try {
- Transferable content = myCopyPasteManager.getContents();
- if (content == null) {
- return null;
- }
-
- Object transferData;
- try {
- transferData = content.getTransferData(ourDataFlavor);
- }
- catch (UnsupportedFlavorException e) {
- return null;
- }
- catch (IOException e) {
- return null;
- }
-
+ Object transferData = myCopyPasteManager.getContents(ourDataFlavor);
if (!(transferData instanceof MyData)) {
return null;
}
@@ -100,9 +83,7 @@
return myRecentData.getElements();
}
catch (Exception e) {
- if (LOG.isDebugEnabled()) {
- LOG.debug(e);
- }
+ LOG.debug(e);
return null;
}
}
@@ -128,19 +109,13 @@
}
public void clear() {
- Transferable old = myCopyPasteManager.getContents();
myRecentData = null;
- StringSelection _new = new StringSelection("");
- myCopyPasteManager.setSystemClipboardContent(_new);
- myCopyPasteManager.fireContentChanged(old, _new);
+ myCopyPasteManager.setContents(new StringSelection(""));
}
public void setElements(PsiElement[] elements, boolean copied) {
- Transferable old = myCopyPasteManager.getContents();
myRecentData = new MyData(elements, copied);
- MyTransferable _new = new MyTransferable(myRecentData);
- myCopyPasteManager.setSystemClipboardContent(_new);
- myCopyPasteManager.fireContentChanged(old, _new);
+ myCopyPasteManager.setContents(new MyTransferable(myRecentData));
}
public boolean isCutElement(Object element) {
@@ -278,7 +253,7 @@
}
}
else if (flavor.equals(LinuxDragAndDropSupport.kdeCutMarkFlavor) && !myDataProxy.isCopied()) {
- return new ByteArrayInputStream("1".getBytes());
+ return new ByteArrayInputStream("1".getBytes(CharsetToolkit.UTF8_CHARSET));
}
return null;
diff --git a/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java b/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java
index 7a2bd3f..2120751 100644
--- a/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java
+++ b/platform/lang-impl/src/com/intellij/ide/RecentDirectoryProjectsManagerEx.java
@@ -20,7 +20,6 @@
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
import com.intellij.platform.ModuleAttachProcessor;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -37,8 +36,8 @@
)}
)
public class RecentDirectoryProjectsManagerEx extends RecentDirectoryProjectsManager {
- public RecentDirectoryProjectsManagerEx(ProjectManager projectManager, MessageBus messageBus) {
- super(projectManager, messageBus);
+ public RecentDirectoryProjectsManagerEx(MessageBus messageBus) {
+ super(messageBus);
}
@NotNull
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/ApplyIntentionAction.java b/platform/lang-impl/src/com/intellij/ide/actions/ApplyIntentionAction.java
new file mode 100644
index 0000000..70b6b1c
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/actions/ApplyIntentionAction.java
@@ -0,0 +1,83 @@
+/*
+ * 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.ide.actions;
+
+import com.intellij.codeInsight.daemon.impl.HighlightInfo;
+import com.intellij.codeInsight.daemon.impl.ShowIntentionsPass;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.PsiFile;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ApplyIntentionAction extends AnAction {
+
+ private final HighlightInfo.IntentionActionDescriptor myDescriptor;
+ private final Editor myEditor;
+ private final PsiFile myFile;
+
+ public ApplyIntentionAction(HighlightInfo.IntentionActionDescriptor descriptor, Editor editor, PsiFile file) {
+ super(descriptor.getAction().getText());
+ myDescriptor = descriptor;
+ myEditor = editor;
+ myFile = file;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final IntentionAction action = myDescriptor.getAction();
+ ShowIntentionActionsHandler.chooseActionAndInvoke(myFile, myEditor, action, action.getText());
+ }
+
+ public String getName() {
+ return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
+ public String compute() {
+ return myDescriptor.getAction().getText();
+ }
+ });
+ }
+
+ @Nullable
+ public static ApplyIntentionAction[] getAvailableIntentions(final Editor editor, final PsiFile file) {
+ final ShowIntentionsPass.IntentionsInfo info = new ShowIntentionsPass.IntentionsInfo();
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ ShowIntentionsPass.getActionsToShow(editor, file, info, -1);
+ }
+ });
+ if (info.isEmpty()) return null;
+
+ final List<HighlightInfo.IntentionActionDescriptor> actions = new ArrayList<HighlightInfo.IntentionActionDescriptor>();
+ actions.addAll(info.errorFixesToShow);
+ actions.addAll(info.inspectionFixesToShow);
+ actions.addAll(info.intentionsToShow);
+
+ final ApplyIntentionAction[] result = new ApplyIntentionAction[actions.size()];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = new ApplyIntentionAction(actions.get(i), editor, file);
+ }
+ return result;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java b/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java
index 9b8fc33..9393ed6 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/CreateDirectoryOrPackageHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -113,7 +113,7 @@
"File Name Detected", "Yes, create file",
"No, create " + (myIsDirectory ? "directory" : "packages"),
fileType.getIcon());
- if (ec == Messages.OK) {
+ if (ec == Messages.YES) {
createFile = true;
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java b/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java
index 9df72f7..156e3a1 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java
@@ -95,13 +95,13 @@
JBPopupFactory.getInstance().createListPopup(new BaseListPopupStep<String>("Choose external documentation root", ArrayUtil.toStringArray(set)) {
@Override
public PopupStep onChosen(final String selectedValue, final boolean finalChoice) {
- BrowserUtil.launchBrowser(selectedValue);
+ BrowserUtil.browse(selectedValue);
return FINAL_CHOICE;
}
}).showInBestPositionFor(DataManager.getInstance().getDataContext());
}
else if (set.size() == 1) {
- BrowserUtil.launchBrowser(urls.get(0));
+ BrowserUtil.browse(urls.get(0));
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java
index 6aef4e8..1d38710 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/GotoActionAction.java
@@ -27,10 +27,12 @@
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -54,9 +56,11 @@
public void gotoActionPerformed(final AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
final Component component = e.getData(PlatformDataKeys.CONTEXT_COMPONENT);
+ final Editor editor = e.getData(CommonDataKeys.EDITOR);
+ final PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
FeatureUsageTracker.getInstance().triggerFeatureUsed("navigation.popup.action");
- final GotoActionModel model = new GotoActionModel(project, component);
+ final GotoActionModel model = new GotoActionModel(project, component, editor, file);
final GotoActionCallback<Object> callback = new GotoActionCallback<Object>() {
@Override
public void elementChosen(ChooseByNamePopup popup, final Object element) {
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java b/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java
index 9ca024a..e7db94f 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/NewElementAction.java
@@ -17,7 +17,6 @@
package com.intellij.ide.actions;
import com.intellij.ide.IdeBundle;
-import com.intellij.ide.IdeView;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
@@ -85,24 +84,28 @@
@Override
public void update(AnActionEvent e){
- final Presentation presentation = e.getPresentation();
- final DataContext context = e.getDataContext();
- final Project project = CommonDataKeys.PROJECT.getData(context);
+ Presentation presentation = e.getPresentation();
+ Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
if (project == null) {
presentation.setEnabled(false);
return;
}
- if (Boolean.TRUE.equals(LangDataKeys.NO_NEW_ACTION.getData(context))) {
- presentation.setEnabled(false);
- return;
- }
- final IdeView ideView = LangDataKeys.IDE_VIEW.getData(context);
- if (ideView == null) {
+ if (!isEnabled(e)) {
presentation.setEnabled(false);
return;
}
- presentation.setEnabled(!ActionGroupUtil.isGroupEmpty(getGroup(context), e));
+ presentation.setEnabled(!ActionGroupUtil.isGroupEmpty(getGroup(e.getDataContext()), e));
+ }
+
+ protected boolean isEnabled(AnActionEvent e) {
+ if (Boolean.TRUE.equals(LangDataKeys.NO_NEW_ACTION.getData(e.getDataContext()))) {
+ return false;
+ }
+ if (PlatformDataKeys.FILE_EDITOR.getData(e.getDataContext()) != null) {
+ return false;
+ }
+ return true;
}
protected ActionGroup getGroup(DataContext dataContext) {
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java b/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java
index a77e209..9ab0f8e 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/NewElementSamePlaceAction.java
@@ -17,10 +17,17 @@
package com.intellij.ide.actions;
import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.LangDataKeys;
public class NewElementSamePlaceAction extends NewElementAction {
@Override
protected String getPopupTitle() {
return IdeBundle.message("title.popup.new.element.same.place");
}
+
+ @Override
+ protected boolean isEnabled(AnActionEvent e) {
+ return LangDataKeys.IDE_VIEW.getData(e.getDataContext()) != null;
+ }
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/PasteReferenceProvider.java b/platform/lang-impl/src/com/intellij/ide/actions/PasteReferenceProvider.java
index c3a685c..00322d2 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/PasteReferenceProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/PasteReferenceProvider.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,21 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.ide.actions;
import com.intellij.codeInsight.FileModificationService;
-import com.intellij.codeInsight.editorActions.PasteHandler;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.PasteProvider;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
+import com.intellij.openapi.editor.actions.PasteAction;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.project.Project;
@@ -114,30 +112,20 @@
}
@Nullable
- private static String getCopiedFqn(final DataContext dataContext) {
- @SuppressWarnings("unchecked")
- final Producer<Transferable> transferableProducer = (Producer<Transferable>)dataContext.getData(PasteHandler.TRANSFERABLE_PROVIDER);
- if (transferableProducer == null) return null;
+ private static String getCopiedFqn(final DataContext context) {
+ Producer<Transferable> producer = PasteAction.TRANSFERABLE_PROVIDER.getData(context);
- final Transferable transferable = transferableProducer.produce();
- if (transferable != null) {
- try {
- return (String)transferable.getTransferData(CopyReferenceAction.ourFlavor);
- }
- catch (Exception ignored) { }
- }
-
- final CopyPasteManager manager = CopyPasteManager.getInstance();
- if (manager.isDataFlavorAvailable(CopyReferenceAction.ourFlavor)) {
- final Transferable contents = manager.getContents();
- if (contents != null) {
+ if (producer != null) {
+ Transferable transferable = producer.produce();
+ if (transferable != null) {
try {
- return (String)contents.getTransferData(CopyReferenceAction.ourFlavor);
+ return (String)transferable.getTransferData(CopyReferenceAction.ourFlavor);
}
catch (Exception ignored) { }
}
+ return null;
}
- return null;
+ return CopyPasteManager.getInstance().getContents(CopyReferenceAction.ourFlavor);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/actions/ReloadFromDiskAction.java b/platform/lang-impl/src/com/intellij/ide/actions/ReloadFromDiskAction.java
index e52a2c0..01edc24 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/ReloadFromDiskAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/ReloadFromDiskAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -45,7 +45,7 @@
IdeBundle.message("title.reload.file"),
Messages.getWarningIcon()
);
- if (res != 0) return;
+ if (res != Messages.OK) return;
CommandProcessor.getInstance().executeCommand(
project, new Runnable() {
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 6da322a..4dcdfe8 100644
--- a/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/actions/SearchEverywhereAction.java
@@ -27,7 +27,6 @@
import com.intellij.ide.ui.laf.darcula.ui.DarculaTextFieldUI;
import com.intellij.ide.ui.search.BooleanOptionDescription;
import com.intellij.ide.ui.search.OptionDescription;
-import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.ide.util.gotoByName.*;
@@ -37,10 +36,10 @@
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.AnActionListener;
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
-import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
import com.intellij.openapi.actionSystem.impl.ActionToolbarImpl;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actions.TextComponentEditorAction;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
@@ -64,6 +63,7 @@
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFilePathWrapper;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.ToolWindowManager;
@@ -111,7 +111,7 @@
* @author Konstantin Bulenkov
*/
public class SearchEverywhereAction extends AnAction implements CustomComponentAction, DumbAware{
- public static final String SE_HISTORY_KEY = "SearchEverywhereHistory";
+ public static final String SE_HISTORY_KEY = "SearchEverywhereHistoryKey";
public static final int SEARCH_FIELD_COLUMNS = 25;
private static final int MAX_CLASSES = 6;
private static final int MAX_FILES = 6;
@@ -158,6 +158,8 @@
private static AtomicLong ourLastTimePressed = new AtomicLong(0);
private static AtomicBoolean showAll = new AtomicBoolean(false);
private ArrayList<VirtualFile> myAlreadyAddedFiles = new ArrayList<VirtualFile>();
+ private ArrayList<AnAction> myAlreadyAddedActions = new ArrayList<AnAction>();
+ private volatile ActionCallback myCurrentWorker = ActionCallback.DONE;
private int myHistoryIndex = 0;
static {
@@ -257,6 +259,10 @@
private Component myFocusOwner;
private ChooseByNamePopup myFileChooseByName;
+ private Editor myEditor;
+ private PsiFile myFile;
+ private HistoryItem myHistoryItem;
+
@Override
public JComponent createCustomComponent(Presentation presentation) {
JPanel panel = new JPanel(new BorderLayout()) {
@@ -538,6 +544,7 @@
}
final String pattern = getField().getText();
final Object value = myList.getSelectedValue();
+ saveHistory(project, pattern, value);
IdeFocusManager focusManager = IdeFocusManager.findInstanceByComponent(getField().getTextEditor());
if (myPopup != null && myPopup.isVisible()) {
myPopup.cancel();
@@ -601,15 +608,20 @@
}
private void rebuildList(final String pattern) {
- if (myCalcThread != null) {
- myCalcThread.cancel();
+ if (myCalcThread != null && !myCurrentWorker.isProcessed()) {
+ myCurrentWorker = myCalcThread.cancel();
}
final Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(getField().getTextEditor()));
assert project != null;
myRenderer.myProject = project;
- myCalcThread = new CalcThread(project, pattern);
- myCalcThread.start();
+ myCurrentWorker.doWhenProcessed(new Runnable() {
+ @Override
+ public void run() {
+ myCalcThread = new CalcThread(project, pattern);
+ myCurrentWorker = myCalcThread.start();
+ }
+ });
}
@Override
@@ -625,6 +637,11 @@
rebuildList(myPopupField.getText());
return;
}
+ myCurrentWorker = ActionCallback.DONE;
+ if (e != null) {
+ myEditor = e.getData(CommonDataKeys.EDITOR);
+ myFile = e.getData(CommonDataKeys.PSI_FILE);
+ }
if (e == null && myFocusOwner != null) {
e = new AnActionEvent(me, DataManager.getInstance().getDataContext(myFocusOwner), ActionPlaces.UNKNOWN, getTemplatePresentation(), ActionManager.getInstance(), 0);
}
@@ -644,6 +661,13 @@
Disposer.dispose(myPopupField);
}
myPopupField = new MySearchTextField();
+ myPopupField.getTextEditor().addKeyListener(new KeyAdapter() {
+ @Override
+ public void keyTyped(KeyEvent e) {
+ myHistoryIndex = 0;
+ myHistoryItem = null;
+ }
+ });
initSearchField(myPopupField);
myPopupField.setOpaque(false);
final JTextField editor = myPopupField.getTextEditor();
@@ -676,25 +700,6 @@
.setCancelOnClickOutside(true)
.setModalContext(false)
.setRequestFocus(true)
- .setCancelCallback(new Computable<Boolean>() {
- @Override
- public Boolean compute() {
- final String last = editor.getText().trim();
- if (project == null || project.isDisposed() || !project.isInitialized()) {
- return true;
- }
- final PropertiesComponent storage = PropertiesComponent.getInstance(project);
- final String historyString = storage.getValue(SE_HISTORY_KEY);
- List<String> history = StringUtil.isEmpty(historyString) ? new ArrayList<String>() : StringUtil.split(historyString, "\n");
- history.remove(last);
- history.add(0, last);
- if (history.size() > MAX_SEARCH_EVERYWHERE_HISTORY) {
- history = history.subList(0, MAX_SEARCH_EVERYWHERE_HISTORY);
- }
- storage.setValue(SE_HISTORY_KEY, StringUtil.join(history, "\n"));
- return true;
- }
- })
.createPopup();
myBalloon.getContent().setBorder(new EmptyBorder(0,0,0,0));
final Window window = WindowManager.getInstance().suggestParentWindow(e.getProject());
@@ -727,6 +732,44 @@
FeatureUsageTracker.getInstance().triggerFeatureUsed(IdeActions.ACTION_SEARCH_EVERYWHERE);
}
+ private static void saveHistory(Project project, String text, Object value) {
+ if (project == null || project.isDisposed() || !project.isInitialized()) {
+ return;
+ }
+ HistoryType type = null;
+ String fqn = null;
+ if (isActionValue(value)) {
+ type = HistoryType.ACTION;
+ AnAction action = (AnAction)(value instanceof Map.Entry ? ((Map.Entry)value).getKey() : value);
+ fqn = ActionManager.getInstance().getId(action);
+ } else if (value instanceof VirtualFile) {
+ type = HistoryType.FILE;
+ fqn = ((VirtualFile)value).getUrl();
+ }
+ final PropertiesComponent storage = PropertiesComponent.getInstance(project);
+ final String[] values = storage.getValues(SE_HISTORY_KEY);
+ List<HistoryItem> history = new ArrayList<HistoryItem>();
+ if (values != null) {
+ for (String s : values) {
+ final String[] split = s.split("\t");
+ if (split.length != 3 || text.equals(split[0])) {
+ continue;
+ }
+ history.add(new HistoryItem(split[0], split[1], split[2]));
+ }
+ }
+ history.add(0, new HistoryItem(text, type == null ? null : type.name(), fqn));
+
+ if (history.size() > MAX_SEARCH_EVERYWHERE_HISTORY) {
+ history = history.subList(0, MAX_SEARCH_EVERYWHERE_HISTORY);
+ }
+ final String[] newValues = new String[history.size()];
+ for (int i = 0; i < newValues.length; i++) {
+ newValues[i] = history.get(i).toString();
+ }
+ storage.setValues(SE_HISTORY_KEY, newValues);
+ }
+
private void registerDataProvider(JPanel panel) {
DataManager.registerDataProvider(panel, new DataProvider() {
@Nullable
@@ -781,15 +824,15 @@
@Override
public void actionPerformed(AnActionEvent e) {
final PropertiesComponent storage = PropertiesComponent.getInstance(e.getProject());
- final String historyString = storage.getValue(SE_HISTORY_KEY);
- if (historyString != null) {
- final List<String> history = StringUtil.split(historyString, "\n");
- if (history.size() > myHistoryIndex) {
- final String text = history.get(myHistoryIndex);
- editor.setText(text);
- editor.setCaretPosition(text.length());
- editor.moveCaretPosition(0);
+ final String[] values = storage.getValues(SE_HISTORY_KEY);
+ if (values != null) {
+ if (values.length > myHistoryIndex) {
+ final List<String> data = StringUtil.split(values[myHistoryIndex], "\t");
+ myHistoryItem = new HistoryItem(data.get(0), data.get(1), data.get(2));
myHistoryIndex++;
+ editor.setText(myHistoryItem.pattern);
+ editor.setCaretPosition(myHistoryItem.pattern.length());
+ editor.moveCaretPosition(0);
}
}
}
@@ -1074,6 +1117,7 @@
private final Project project;
private final String pattern;
private ProgressIndicator myProgressIndicator = new ProgressIndicatorBase();
+ private final ActionCallback myDone = new ActionCallback();
public CalcThread(Project project, String pattern) {
this.project = project;
@@ -1083,28 +1127,32 @@
@Override
public void run() {
try {
- myList.getEmptyText().setText("Searching...");
+ check();
+
//noinspection SSBasedInspection
- UIUtil.invokeLaterIfNeeded(new Runnable() {
+ SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
+ myList.getEmptyText().setText("Searching...");
myTitleIndexes.clear();
clearModel();
myAlreadyAddedFiles.clear();
+ myAlreadyAddedActions.clear();
}
});
+
if (pattern.trim().length() == 0) {
buildModelFromRecentFiles();
updatePopup();
return;
}
- checkModelsUpToDate();
- buildTopHit(pattern);
- buildRecentFiles(pattern);
- updatePopup();
- buildToolWindows(pattern);
- updatePopup();
+ checkModelsUpToDate(); check();
+ buildTopHit(pattern); check();
+ buildRecentFiles(pattern); check();
+ updatePopup(); check();
+ buildToolWindows(pattern); check();
+ updatePopup(); check();
if (!DumbServiceImpl.getInstance(project).isDumb()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -1135,12 +1183,22 @@
updatePopup();
}
catch (Exception ignore) {
+ myDone.setRejected();
}
finally {
- myList.getEmptyText().setText(StatusText.DEFAULT_EMPTY_TEXT);
+ if (!myProgressIndicator.isCanceled()) {
+ myList.getEmptyText().setText(StatusText.DEFAULT_EMPTY_TEXT);
+ }
+ if (!myDone.isProcessed()) {
+ myDone.setDone();
+ }
}
}
+ protected void check() {
+ myProgressIndicator.checkCanceled();
+ }
+
private void buildToolWindows(String pattern) {
if (myActions == null) {
myActions = myActionModel.getNames(true);
@@ -1148,17 +1206,17 @@
final HashSet<AnAction> toolWindows = new HashSet<AnAction>();
List<MatchResult> matches = collectResults(pattern, myActions, myActionModel);
for (MatchResult o : matches) {
- myProgressIndicator.checkCanceled();
+ check();
Object[] objects = myActionModel.getElementsByName(o.elementName, true, pattern);
for (Object object : objects) {
- myProgressIndicator.checkCanceled();
+ check();
if (isToolWindowAction(object) && toolWindows.size() < MAX_TOOL_WINDOWS) {
toolWindows.add((AnAction)((Map.Entry)object).getKey());
}
}
}
- myProgressIndicator.checkCanceled();
+ check();
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -1185,10 +1243,10 @@
List<MatchResult> matches = collectResults(pattern, myActions, myActionModel);
for (MatchResult o : matches) {
- myProgressIndicator.checkCanceled();
+ check();
Object[] objects = myActionModel.getElementsByName(o.elementName, true, pattern);
for (Object object : objects) {
- myProgressIndicator.checkCanceled();
+ check();
if (isSetting(object) && settings.size() < MAX_SETTINGS) {
if (matcher.matches(getSettingText((OptionDescription)object))) {
settings.add(object);
@@ -1200,7 +1258,7 @@
}
}
- myProgressIndicator.checkCanceled();
+ check();
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -1271,7 +1329,7 @@
}
- myProgressIndicator.checkCanceled();
+ check();
if (files.size() > 0) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@@ -1310,7 +1368,7 @@
}
}
- myProgressIndicator.checkCanceled();
+ check();
if (symbols.size() > 0) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@@ -1349,7 +1407,7 @@
Object[] objects = myClassModel.getElementsByName(matchResult.elementName, includeLibs, pattern);
for (Object object : objects) {
- myProgressIndicator.checkCanceled();
+ check();
if (!myListModel.contains(object)) {
if (object instanceof PsiElement) {
VirtualFile file = PsiUtilCore.getVirtualFile((PsiElement)object);
@@ -1370,7 +1428,7 @@
}
}
- myProgressIndicator.checkCanceled();
+ check();
if (classes.size() > 0) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@@ -1395,16 +1453,10 @@
private void buildRecentFiles(String pattern) {
final MinusculeMatcher matcher = new MinusculeMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE);
final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
- FileEditorManager editorManager = FileEditorManager.getInstance(project);
- //we skip active editor
- boolean skip = editorManager.getOpenFiles().length > 1;
+ final List<VirtualFile> selected = Arrays.asList(FileEditorManager.getInstance(project).getSelectedFiles());
for (VirtualFile file : ArrayUtil.reverseArray(EditorHistoryManager.getInstance(project).getFiles())) {
- if (skip) {
- skip = false;
- continue;
- }
if (StringUtil.isEmptyOrSpaces(pattern) || matcher.matches(file.getName())) {
- if (!files.contains(file)) {
+ if (!files.contains(file) && !selected.contains(file)) {
files.add(file);
}
}
@@ -1430,10 +1482,40 @@
private void buildTopHit(String pattern) {
final List<Object> elements = new ArrayList<Object>();
+ HistoryItem history = myHistoryItem;
+ if (history != null) {
+ final HistoryType type = parseHistoryType(history.type);
+ if (type != null) {
+ switch (type){
+ case CLASS:
+ break;
+ case FILE:
+ final VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(history.fqn);
+ if (file != null) {
+ elements.add(file);
+ }
+ break;
+ case SYMBOL:
+ break;
+ case SETTING:
+ break;
+ case ACTION:
+ final AnAction action = ActionManager.getInstance().getAction(history.fqn);
+ if (action != null) {
+ elements.add(action);
+ myAlreadyAddedActions.add(action);
+ }
+ break;
+ }
+ }
+ }
final Consumer<Object> consumer = new Consumer<Object>() {
@Override
public void consume(Object o) {
if (isSetting(o) || isVirtualFile(o) || isActionValue(o) || o instanceof PsiElement) {
+ if (o instanceof AnAction && myAlreadyAddedActions.contains(o)) {
+ return;
+ }
elements.add(o);
}
}
@@ -1446,7 +1528,7 @@
}
for (SearchTopHitProvider provider : SearchTopHitProvider.EP_NAME.getExtensions()) {
- myProgressIndicator.checkCanceled();
+ check();
provider.consumeTopHits(pattern, consumer);
}
if (elements.size() > 0) {
@@ -1483,87 +1565,21 @@
}
private GotoActionModel createActionModel() {
- return new GotoActionModel(project, myFocusComponent) {
+ return new GotoActionModel(project, myFocusComponent, myEditor, myFile) {
@Override
- public boolean matches(@NotNull String name, @NotNull String pattern) {
- final AnAction anAction = ActionManager.getInstance().getAction(name);
- if (anAction == null) return true;
- return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE).matches(
- anAction.getTemplatePresentation().getText());
- }
-
- @NotNull
- @Override
- public Object[] getElementsByName(String id, boolean checkBoxState, String pattern) {
- final HashMap<AnAction, String> map = new HashMap<AnAction, String>();
- final AnAction act = myActionManager.getAction(id);
- if (act != null) {
- map.put(act, myActionsMap.get(act));
- if (checkBoxState) {
- final Set<String> ids = ((ActionManagerImpl)myActionManager).getActionIds();
- for (AnAction action : map.keySet()) { //do not add already included actions
- ids.remove(getActionId(action));
- }
- if (ids.contains(id)) {
- final AnAction anAction = myActionManager.getAction(id);
- map.put(anAction, null);
- }
- }
- }
- Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]);
- if (Comparing.strEqual(id, SETTINGS_KEY)) {
- final Set<String> words = myIndex.getProcessedWords(pattern);
- Set<OptionDescription> optionDescriptions = null;
- final String actionManagerName = myActionManager.getComponentName();
- for (String word : words) {
- final Set<OptionDescription> descriptions = ((SearchableOptionsRegistrarImpl)myIndex).getAcceptableDescriptions(word);
- if (descriptions != null) {
- for (Iterator<OptionDescription> iterator = descriptions.iterator(); iterator.hasNext(); ) {
- OptionDescription description = iterator.next();
- if (actionManagerName.equals(description.getPath())) {
- iterator.remove();
- }
- }
- if (!descriptions.isEmpty()) {
- if (optionDescriptions == null) {
- optionDescriptions = descriptions;
- }
- else {
- optionDescriptions.retainAll(descriptions);
- }
- }
- }
- else {
- optionDescriptions = null;
- break;
- }
- }
- if (optionDescriptions != null && !optionDescriptions.isEmpty()) {
- Set<String> currentHits = new HashSet<String>();
- for (Iterator<OptionDescription> iterator = optionDescriptions.iterator(); iterator.hasNext(); ) {
- OptionDescription description = iterator.next();
- final String hit = description.getHit();
- if (hit == null || !currentHits.add(hit.trim())) {
- iterator.remove();
- }
- }
- final Object[] descriptions = optionDescriptions.toArray();
- Arrays.sort(descriptions);
- objects = ArrayUtil.mergeArrays(objects, descriptions);
- }
- }
- return objects;
+ protected boolean actionMatches(String pattern, @NotNull AnAction anAction) {
+ return NameUtil.buildMatcher("*" + pattern, NameUtil.MatchingCaseSensitivity.NONE)
+ .matches(anAction.getTemplatePresentation().getText());
}
};
}
@SuppressWarnings("SSBasedInspection")
private void updatePopup() {
- myProgressIndicator.checkCanceled();
+ check();
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- myProgressIndicator.checkCanceled();
myListModel.update();
myList.revalidate();
myList.repaint();
@@ -1612,6 +1628,7 @@
myCalcThread = null;
myPopup = null;
myHistoryIndex = 0;
+ myCurrentWorker = ActionCallback.DONE;
showAll.set(false);
myNonProjectCheckBox.setSelected(false);
ActionToolbarImpl.updateAllToolbarsImmediately();
@@ -1673,7 +1690,7 @@
MatchResult result;
for (String name : names) {
- myProgressIndicator.checkCanceled();
+ check();
result = null;
if (model instanceof CustomMatcherModel) {
try {
@@ -1703,12 +1720,14 @@
return results;
}
- public void cancel() {
+ public ActionCallback cancel() {
myProgressIndicator.cancel();
+ return myDone;
}
- public void start() {
+ public ActionCallback start() {
ApplicationManager.getApplication().executeOnPooledThread(this);
+ return myDone;
}
}
@@ -1940,4 +1959,46 @@
return result;
}
+ private enum HistoryType {CLASS, FILE, SYMBOL, SETTING, ACTION}
+
+ @Nullable
+ private static HistoryType parseHistoryType(@Nullable String name) {
+ try {
+ return HistoryType.valueOf(name);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private static class HistoryItem {
+ final String pattern, type, fqn;
+
+ private HistoryItem(String pattern, String type, String fqn) {
+ this.pattern = pattern;
+ this.type = type;
+ this.fqn = fqn;
+ }
+
+ public String toString() {
+ return pattern + "\t" + type + "\t" + fqn;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ HistoryItem item = (HistoryItem)o;
+
+ if (!pattern.equals(item.pattern)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return pattern.hashCode();
+ }
+ }
}
+
diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/GotoBookmarkActionBase.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/GotoBookmarkActionBase.java
index 5aeb35e..1f843ac 100644
--- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/GotoBookmarkActionBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/GotoBookmarkActionBase.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.
@@ -53,6 +53,7 @@
LogicalPosition pos = new LogicalPosition(line, 0);
editor.getSelectionModel().removeSelection();
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToLogicalPosition(pos);
editor.getScrollingModel().scrollTo(new LogicalPosition(line, 0), ScrollType.CENTER);
}
diff --git a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MnemonicChooser.java b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MnemonicChooser.java
index c17b8a3..950d830 100644
--- a/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MnemonicChooser.java
+++ b/platform/lang-impl/src/com/intellij/ide/bookmarks/actions/MnemonicChooser.java
@@ -26,6 +26,7 @@
import com.intellij.ui.LightColors;
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.LineBorder;
@@ -117,7 +118,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
onMnemonicChosen(c);
return true;
}
diff --git a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/UsageProjectTreeNode.java b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/UsageProjectTreeNode.java
index 2a724b0..279cea9 100644
--- a/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/UsageProjectTreeNode.java
+++ b/platform/lang-impl/src/com/intellij/ide/favoritesTreeView/UsageProjectTreeNode.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.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.usageView.UsageInfo;
+import com.intellij.usageView.UsageViewUtil;
import com.intellij.usages.TextChunk;
import com.intellij.usages.UsageInfo2UsageAdapter;
import com.intellij.usages.UsagePresentation;
@@ -78,12 +79,12 @@
@Override
public void navigate(boolean requestFocus) {
- getValue().navigateTo(requestFocus);
+ UsageViewUtil.navigateTo(getValue(), requestFocus);
}
@Override
public boolean canNavigate() {
- return getValue().getElement().isValid();
+ return canNavigateToSource();
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplate.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplate.java
index a3e7769..ddfe60f 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplate.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplate.java
@@ -33,6 +33,7 @@
FileTemplate[] EMPTY_ARRAY = new FileTemplate[0];
String ATTRIBUTE_EXCEPTION = "EXCEPTION";
+ String ATTRIBUTE_EXCEPTION_TYPE = "EXCEPTION_TYPE";
String ATTRIBUTE_DESCRIPTION = "DESCRIPTION";
String ATTRIBUTE_DISPLAY_NAME = "DISPLAY_NAME";
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateManager.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateManager.java
index 05830b8..ea175a5 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateManager.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/FileTemplateManager.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,7 +21,6 @@
import com.intellij.openapi.util.Key;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.TestOnly;
import java.util.Collection;
import java.util.Properties;
@@ -61,7 +60,7 @@
public abstract Properties getDefaultProperties();
@NotNull
- public Properties getDefaultProperties(Project project) {
+ public Properties getDefaultProperties(@NotNull Project project) {
Properties properties = getDefaultProperties();
properties.setProperty("PROJECT_NAME", project.getName());
return properties;
@@ -69,14 +68,12 @@
/**
* Creates a new template with specified name.
- * @param name
* @return created template
*/
@NotNull
public abstract FileTemplate addTemplate(@NotNull @NonNls String name, @NotNull @NonNls String extension);
public abstract void removeTemplate(@NotNull FileTemplate template);
- //public abstract void removeInternal(@NotNull FileTemplate template);
@NotNull
public abstract Collection<String> getRecentNames();
@@ -84,6 +81,7 @@
public abstract void addRecentName(@NotNull @NonNls String name);
public abstract FileTemplate getInternalTemplate(@NotNull @NonNls String templateName);
+
@NotNull
public abstract FileTemplate[] getInternalTemplates();
@@ -99,18 +97,17 @@
@NotNull
public abstract FileTemplate[] getAllJ2eeTemplates();
- @TestOnly
- public abstract FileTemplate addInternal(@NotNull @NonNls String name, @NotNull @NonNls String extension);
+ @NotNull
+ public abstract String internalTemplateToSubject(@NotNull @NonNls String templateName);
- @NotNull public abstract String internalTemplateToSubject(@NotNull @NonNls String templateName);
-
- @NotNull public abstract String localizeInternalTemplateName(final FileTemplate template);
+ @NotNull
+ public abstract String localizeInternalTemplateName(@NotNull FileTemplate template);
public abstract FileTemplate getPattern(@NotNull @NonNls String name);
@NotNull
public abstract FileTemplate getDefaultTemplate(@NotNull @NonNls String name);
- public abstract void setTemplates(@NotNull String templatesCategory, Collection<FileTemplate> templates);
+ public abstract void setTemplates(@NotNull String templatesCategory, @NotNull Collection<FileTemplate> templates);
}
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
index 0b00557..6ef0f90 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/AllFileTemplatesConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -30,7 +30,6 @@
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.Comparing;
@@ -344,7 +343,7 @@
if (selected instanceof BundledFileTemplate) {
if (Messages.showOkCancelDialog(IdeBundle.message("prompt.reset.to.original.template"),
IdeBundle.message("title.reset.template"), Messages.getQuestionIcon()) !=
- DialogWrapper.OK_EXIT_CODE) {
+ Messages.OK) {
return;
}
((BundledFileTemplate)selected).revertToDefaults();
@@ -489,7 +488,7 @@
}
if (allNames.contains(currName)) {
itemWithError = template;
- errorString = IdeBundle.message("error.template.with.such.name.already.exists");
+ errorString = "Template with name \'" + currName + "\' already exists. Please specify a different template name";
break;
}
if (currExt.length() == 0) {
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java
index 5e425be..3c0d4a4 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FTManager.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.
@@ -159,7 +159,7 @@
}
}
- public void updateTemplates(Collection<FileTemplate> newTemplates) {
+ public void updateTemplates(@NotNull Collection<FileTemplate> newTemplates) {
final Set<String> toDisable = new HashSet<String>();
for (DefaultTemplate template : myDefaultTemplates) {
toDisable.add(template.getQualifiedName());
diff --git a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java
index 8352991..93b239e 100644
--- a/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/fileTemplates/impl/FileTemplateManagerImpl.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,10 +54,10 @@
private final RecentTemplatesManager myRecentList = new RecentTemplatesManager();
- private static final String ELEMENT_DELETED_TEMPLATES = "deleted_templates";
- private static final String ELEMENT_DELETED_INCLUDES = "deleted_includes";
- private static final String ELEMENT_RECENT_TEMPLATES = "recent_templates";
- private static final String ELEMENT_TEMPLATES = "templates";
+ @NonNls private static final String ELEMENT_DELETED_TEMPLATES = "deleted_templates";
+ @NonNls private static final String ELEMENT_DELETED_INCLUDES = "deleted_includes";
+ @NonNls private static final String ELEMENT_RECENT_TEMPLATES = "recent_templates";
+ @NonNls private static final String ELEMENT_TEMPLATES = "templates";
private final FileTypeManagerEx myTypeManager;
@@ -131,12 +131,6 @@
}
@Override
- @TestOnly
- public FileTemplate addInternal(@NotNull String name, @NotNull String extension) {
- return myInternalTemplatesManager.addTemplate(name, extension);
- }
-
- @Override
@NotNull
public Properties getDefaultProperties() {
@NonNls Properties props = new Properties();
@@ -165,6 +159,7 @@
return props;
}
+ @NotNull
private static String getCalendarValue(final Calendar calendar, final int field) {
int val = calendar.get(field);
if (field == Calendar.MONTH) val++;
@@ -189,7 +184,6 @@
@Override
public void readExternal(Element element) throws InvalidDataException {
-
final Element recentElement = element.getChild(ELEMENT_RECENT_TEMPLATES);
if (recentElement != null) {
myRecentList.readExternal(recentElement);
@@ -250,7 +244,7 @@
}
// need this to support options from older format
- private static void applyReformatState(Set<String> templateNamesWithReformatOff, Collection<FileTemplateBase> templates) {
+ private static void applyReformatState(@NotNull Set<String> templateNamesWithReformatOff, @NotNull Collection<FileTemplateBase> templates) {
for (FileTemplateBase template : templates) {
if (templateNamesWithReformatOff.contains(template.getName())) {
template.setReformatCode(false);
@@ -259,7 +253,7 @@
}
// need this to support options from older format
- private static void applyDeletedState(DeletedTemplatesManager deletedDefaults, Collection<FileTemplateBase> templates) {
+ private static void applyDeletedState(@NotNull DeletedTemplatesManager deletedDefaults, @NotNull Collection<FileTemplateBase> templates) {
for (FileTemplateBase template : templates) {
if (template instanceof BundledFileTemplate && deletedDefaults.contains(template.getQualifiedName())) {
((BundledFileTemplate)template).setEnabled(false);
@@ -353,7 +347,8 @@
return template;
}
- private static String normalizeText(String text) {
+ @NotNull
+ private static String normalizeText(@NotNull String text) {
text = StringUtil.convertLineSeparators(text);
text = StringUtil.replace(text, "$NAME$", "${NAME}");
text = StringUtil.replace(text, "$PACKAGE_NAME$", "${PACKAGE_NAME}");
@@ -364,6 +359,7 @@
}
@NonNls
+ @NotNull
private String getTestClassTemplateText(@NotNull @NonNls String templateName) {
return "package $PACKAGE_NAME$;\npublic " + internalTemplateToSubject(templateName) + " $NAME$ { }";
}
@@ -387,6 +383,7 @@
}
@NonNls
+ @NotNull
private String getDefaultClassTemplateText(@NotNull @NonNls String templateName) {
return IdeBundle.message("template.default.class.comment", ApplicationNamesInfo.getInstance().getFullProductName()) +
"package $PACKAGE_NAME$;\n" + "public " + internalTemplateToSubject(templateName) + " $NAME$ { }";
@@ -403,7 +400,7 @@
}
@Nullable
- private static FileTemplate getTemplateFromManager(final @NotNull String templateName, final @NotNull FTManager ftManager) {
+ private static FileTemplate getTemplateFromManager(@NotNull final String templateName, @NotNull final FTManager ftManager) {
FileTemplateBase template = ftManager.getTemplate(templateName);
if (template != null) {
return template;
@@ -423,7 +420,7 @@
@Override
@NotNull
- public FileTemplate getDefaultTemplate(final @NotNull String name) {
+ public FileTemplate getDefaultTemplate(@NotNull final String name) {
final String templateQName = myTypeManager.getExtension(name).isEmpty()? FileTemplateBase.getQualifiedName(name, "java") : name;
for (FTManager manager : myAllManagers) {
@@ -467,7 +464,7 @@
}
@Override
- public void setTemplates(@NotNull String templatesCategory, Collection<FileTemplate> templates) {
+ public void setTemplates(@NotNull String templatesCategory, @NotNull Collection<FileTemplate> templates) {
for (FTManager manager : myAllManagers) {
if (templatesCategory.equals(manager.getName())) {
manager.updateTemplates(templates);
diff --git a/platform/lang-impl/src/com/intellij/ide/hierarchy/actions/BrowseHierarchyActionBase.java b/platform/lang-impl/src/com/intellij/ide/hierarchy/actions/BrowseHierarchyActionBase.java
index 006b99b..a124f2e 100644
--- a/platform/lang-impl/src/com/intellij/ide/hierarchy/actions/BrowseHierarchyActionBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/hierarchy/actions/BrowseHierarchyActionBase.java
@@ -22,6 +22,7 @@
import com.intellij.lang.LanguageExtension;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.wm.ToolWindowId;
@@ -41,6 +42,7 @@
* @author yole
*/
public abstract class BrowseHierarchyActionBase extends AnAction {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.ide.hierarchy.actions.BrowseHierarchyActionBase");
private final LanguageExtension<HierarchyProvider> myExtension;
protected BrowseHierarchyActionBase(final LanguageExtension<HierarchyProvider> extension) {
@@ -110,12 +112,24 @@
private boolean isEnabled(final AnActionEvent e) {
final HierarchyProvider provider = getProvider(e);
- return provider != null && provider.getTarget(e.getDataContext()) != null;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Using provider " + provider);
+ }
+ if (provider == null) return false;
+ PsiElement target = provider.getTarget(e.getDataContext());
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Target: " + target);
+ }
+ return target != null;
}
@Nullable
private HierarchyProvider getProvider(final AnActionEvent e) {
- return findBestHierarchyProvider(myExtension, e.getData(CommonDataKeys.PSI_ELEMENT), e.getDataContext());
+ final HierarchyProvider provider = findBestHierarchyProvider(myExtension, e.getData(CommonDataKeys.PSI_ELEMENT), e.getDataContext());
+ if (provider == null) {
+ return findBestHierarchyProvider(myExtension, e.getData(CommonDataKeys.PSI_FILE), e.getDataContext());
+ }
+ return provider;
}
@Nullable
diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeFoldingBuilder.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeFoldingBuilder.java
new file mode 100644
index 0000000..9dca9c5
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeFoldingBuilder.java
@@ -0,0 +1,100 @@
+/*
+ * 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.ide.highlighter.custom.impl;
+
+import com.intellij.codeInsight.highlighting.BraceMatcher;
+import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
+import com.intellij.ide.highlighter.custom.CustomFileHighlighter;
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.folding.CustomFoldingBuilder;
+import com.intellij.lang.folding.FoldingDescriptor;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.fileTypes.SyntaxHighlighter;
+import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.Trinity;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * @author yole
+ */
+public class CustomFileTypeFoldingBuilder extends CustomFoldingBuilder {
+
+ @Override
+ protected void buildLanguageFoldRegions(@NotNull List<FoldingDescriptor> descriptors,
+ @NotNull PsiElement root,
+ @NotNull Document document,
+ boolean quick) {
+ FileType fileType = root.getContainingFile().getFileType();
+ if (!(fileType instanceof CustomSyntaxTableFileType)) {
+ return;
+ }
+ CustomFileHighlighter highlighter = new CustomFileHighlighter(((CustomSyntaxTableFileType) fileType).getSyntaxTable());
+ buildBraceMatcherBasedFolding(descriptors, root, document, highlighter);
+ }
+
+ public static void buildBraceMatcherBasedFolding(List<FoldingDescriptor> descriptors,
+ PsiElement root,
+ Document document,
+ SyntaxHighlighter highlighter) {
+ LexerEditorHighlighter editorHighlighter = new LexerEditorHighlighter(highlighter, EditorColorsManager.getInstance().getGlobalScheme());
+ editorHighlighter.setText(document.getText());
+ FileType fileType = root.getContainingFile().getFileType();
+ BraceMatcher braceMatcher = BraceMatchingUtil.getBraceMatcher(fileType, root.getLanguage());
+ TextRange totalRange = root.getTextRange();
+ final HighlighterIterator iterator = editorHighlighter.createIterator(totalRange.getStartOffset());
+
+ final LinkedList<Trinity<Integer, Integer, IElementType>> stack = new LinkedList<Trinity<Integer, Integer, IElementType>>();
+ String editorText = document.getText();
+ while (!iterator.atEnd() && iterator.getStart() < totalRange.getEndOffset()) {
+ final Trinity<Integer, Integer, IElementType> last;
+ if (braceMatcher.isLBraceToken(iterator, editorText, fileType) &&
+ braceMatcher.isStructuralBrace(iterator, editorText, fileType)) {
+ stack.addLast(Trinity.create(iterator.getStart(), iterator.getEnd(), iterator.getTokenType()));
+ }
+ else if (braceMatcher.isRBraceToken(iterator, editorText, fileType) &&
+ braceMatcher.isStructuralBrace(iterator, editorText, fileType)
+ && !stack.isEmpty() && braceMatcher.isPairBraces((last = stack.getLast()).third, iterator.getTokenType())) {
+ stack.removeLast();
+ TextRange range = new TextRange(last.first, iterator.getEnd());
+ if (StringUtil.countChars(document.getText(range), '\n') >= 3) {
+ descriptors.add(new FoldingDescriptor(root, range));
+ }
+ }
+ iterator.advance();
+ }
+ }
+
+ @Override
+ protected String getLanguagePlaceholderText(@NotNull ASTNode node, @NotNull TextRange range) {
+ return "{...}";
+ }
+
+ @Override
+ protected boolean isRegionCollapsedByDefault(@NotNull ASTNode node) {
+ return false;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeQuoteHandler.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeQuoteHandler.java
index 8d2cb18..339402b 100644
--- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeQuoteHandler.java
+++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeQuoteHandler.java
@@ -31,9 +31,7 @@
public boolean isClosingQuote(HighlighterIterator iterator, int offset) {
final IElementType tokenType = iterator.getTokenType();
- if (tokenType == CustomHighlighterTokenType.STRING ||
- tokenType == CustomHighlighterTokenType.SINGLE_QUOTED_STRING ||
- tokenType == CustomHighlighterTokenType.CHARACTER){
+ if (isQuotedToken(tokenType)){
int start = iterator.getStart();
int end = iterator.getEnd();
return end - start >= 1 && offset == end - 1;
@@ -41,13 +39,15 @@
return false;
}
+ static boolean isQuotedToken(IElementType tokenType) {
+ return tokenType == CustomHighlighterTokenType.STRING ||
+ tokenType == CustomHighlighterTokenType.SINGLE_QUOTED_STRING ||
+ tokenType == CustomHighlighterTokenType.CHARACTER;
+ }
+
@Override
public boolean isOpeningQuote(HighlighterIterator iterator, int offset) {
- final IElementType tokenType = iterator.getTokenType();
-
- if (tokenType == CustomHighlighterTokenType.STRING ||
- tokenType == CustomHighlighterTokenType.SINGLE_QUOTED_STRING ||
- tokenType == CustomHighlighterTokenType.CHARACTER){
+ if (isQuotedToken(iterator.getTokenType())){
int start = iterator.getStart();
return offset == start;
}
@@ -62,11 +62,7 @@
int lineEnd = doc.getLineEndOffset(doc.getLineNumber(offset));
while (!iterator.atEnd() && iterator.getStart() < lineEnd) {
- IElementType tokenType = iterator.getTokenType();
-
- if (tokenType == CustomHighlighterTokenType.STRING ||
- tokenType == CustomHighlighterTokenType.SINGLE_QUOTED_STRING ||
- tokenType == CustomHighlighterTokenType.CHARACTER) {
+ if (isQuotedToken(iterator.getTokenType())) {
if (iterator.getStart() >= iterator.getEnd() - 1 ||
chars.charAt(iterator.getEnd() - 1) != '\"' && chars.charAt(iterator.getEnd() - 1) != '\'') {
@@ -84,10 +80,6 @@
@Override
public boolean isInsideLiteral(HighlighterIterator iterator) {
- final IElementType tokenType = iterator.getTokenType();
-
- return tokenType == CustomHighlighterTokenType.STRING ||
- tokenType == CustomHighlighterTokenType.SINGLE_QUOTED_STRING ||
- tokenType == CustomHighlighterTokenType.CHARACTER;
+ return isQuotedToken(iterator.getTokenType());
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeSelectWordHandler.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeSelectWordHandler.java
new file mode 100644
index 0000000..6ab6c74
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/CustomFileTypeSelectWordHandler.java
@@ -0,0 +1,59 @@
+/*
+ * 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.ide.highlighter.custom.impl;
+
+import com.intellij.codeInsight.editorActions.BraceMatcherBasedSelectioner;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.highlighter.HighlighterIterator;
+import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.containers.ContainerUtil;
+
+import java.util.List;
+
+/**
+ * @author yole
+ */
+public class CustomFileTypeSelectWordHandler extends BraceMatcherBasedSelectioner {
+ @Override
+ public boolean canSelect(PsiElement e) {
+ return e.getContainingFile().getFileType() instanceof CustomSyntaxTableFileType;
+ }
+
+ @Override
+ public List<TextRange> select(PsiElement e, CharSequence editorText, int cursorOffset, Editor editor) {
+ List<TextRange> superResult = super.select(e, editorText, cursorOffset, editor);
+
+ HighlighterIterator iterator = ((EditorEx)editor).getHighlighter().createIterator(cursorOffset);
+ if (CustomFileTypeQuoteHandler.isQuotedToken(iterator.getTokenType())) {
+ List<TextRange> result = ContainerUtil.newArrayList();
+ int start = iterator.getStart();
+ int end = iterator.getEnd();
+ if (end - start > 2) {
+ result.add(new TextRange(start + 1, end - 1));
+ }
+ result.add(new TextRange(start, end));
+ if (superResult != null) {
+ result.addAll(superResult);
+ }
+ return result;
+ }
+
+ return superResult;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/StandardFileTypeRegistrator.java b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/StandardFileTypeRegistrator.java
index 772adf6..07b5bb5 100644
--- a/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/StandardFileTypeRegistrator.java
+++ b/platform/lang-impl/src/com/intellij/ide/highlighter/custom/impl/StandardFileTypeRegistrator.java
@@ -16,8 +16,6 @@
package com.intellij.ide.highlighter.custom.impl;
-import com.intellij.codeInsight.completion.CompletionUtil;
-import com.intellij.codeInsight.completion.SyntaxTableCompletionData;
import com.intellij.codeInsight.editorActions.TypedHandler;
import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
import com.intellij.ide.highlighter.FileTypeRegistrator;
@@ -37,7 +35,6 @@
private static void init(final AbstractFileType abstractFileType) {
SyntaxTable table = abstractFileType.getSyntaxTable();
- CompletionUtil.registerCompletionData(abstractFileType,new SyntaxTableCompletionData(table));
if (!isEmpty(table.getStartComment()) && !isEmpty(table.getEndComment()) ||
!isEmpty(table.getLineComment())) {
diff --git a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java
index 198b8b6..ec026ca 100644
--- a/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/impl/StructureViewWrapperImpl.java
@@ -31,8 +31,10 @@
import com.intellij.openapi.fileEditor.ex.FileEditorProviderManager;
import com.intellij.openapi.fileEditor.impl.EditorWindow;
import com.intellij.openapi.fileEditor.impl.FileEditorManagerImpl;
+import com.intellij.openapi.module.InternalModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.Comparing;
@@ -293,8 +295,8 @@
if (file != null && file.isValid()) {
if (file.isDirectory()) {
if (ProjectRootsUtil.isModuleContentRoot(file, myProject)) {
- Module module = ModuleUtil.findModuleForFile(file, myProject);
- if (module != null) {
+ Module module = ModuleUtilCore.findModuleForFile(file, myProject);
+ if (module != null && !(ModuleUtil.getModuleType(module) instanceof InternalModuleType)) {
myModuleStructureComponent = new ModuleStructureComponent(module);
focusedComponent = hadFocus ? IdeFocusTraversalPolicy.getPreferredFocusedComponent(myModuleStructureComponent) : null;
createSinglePanel(myModuleStructureComponent.getComponent());
diff --git a/platform/lang-impl/src/com/intellij/ide/macro/ClipboardContentMacro.java b/platform/lang-impl/src/com/intellij/ide/macro/ClipboardContentMacro.java
index 8e92653..a758507 100644
--- a/platform/lang-impl/src/com/intellij/ide/macro/ClipboardContentMacro.java
+++ b/platform/lang-impl/src/com/intellij/ide/macro/ClipboardContentMacro.java
@@ -1,20 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.macro;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ide.CopyPasteManager;
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
/**
* @author nik
*/
public class ClipboardContentMacro extends Macro {
- private static final Logger LOG = Logger.getInstance(ClipboardContentMacro.class);
-
@Override
public String getName() {
return "ClipboardContent";
@@ -28,15 +39,6 @@
@Nullable
@Override
public String expand(DataContext dataContext) throws ExecutionCancelledException {
- Transferable contents = CopyPasteManager.getInstance().getContents();
- if (contents == null) return null;
-
- try {
- return (String)contents.getTransferData(DataFlavor.stringFlavor);
- }
- catch (Exception e) {
- LOG.info(e);
- return null;
- }
+ return CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java
index 8f67377..c286e89 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarItem.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.PlatformIcons;
import com.intellij.util.ui.EmptyIcon;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -157,6 +158,7 @@
super.setOpaque(false);
}
+ @NotNull
@Override
public Dimension getPreferredSize() {
final Dimension size = super.getPreferredSize();
@@ -164,6 +166,7 @@
return new Dimension(size.width + offsets.width, size.height + offsets.height);
}
+ @NotNull
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
diff --git a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java
index 45a7f3b..968c8ca 100644
--- a/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/navigationToolbar/NavBarPanel.java
@@ -31,6 +31,7 @@
import com.intellij.ide.projectView.impl.ProjectRootsUtil;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.customization.CustomActionsSchema;
+import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.ide.util.DeleteHandler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
@@ -114,7 +115,7 @@
myPresentation = new NavBarPresentation(myProject);
myUpdateQueue = new NavBarUpdateQueue(this);
- PopupHandler.installPopupHandler(this, IdeActions.GROUP_NAVBAR_POPUP, ActionPlaces.NAVIGATION_BAR);
+ CustomizationUtil.installPopupHandler(this, IdeActions.GROUP_NAVBAR_POPUP, ActionPlaces.NAVIGATION_BAR);
setOpaque(false);
if (!docked && UIUtil.isUnderDarcula()) {
setBorder(new LineBorder(Gray._120, 1));
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java
index 1ff9a78..8596485 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkExcludeRootAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -35,7 +35,7 @@
String message = files.length == 1 ? FileUtil.toSystemDependentName(files[0].getPath()) : files.length + " selected files";
final int rc = Messages.showOkCancelDialog(e.getData(CommonDataKeys.PROJECT), getPromptText(message), "Mark as Excluded",
Messages.getQuestionIcon());
- if (rc != 0) {
+ if (rc != Messages.OK) {
return;
}
super.actionPerformed(e);
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootGroup.java b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootGroup.java
index 2a9a881..be1f539 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootGroup.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/actions/MarkRootGroup.java
@@ -15,17 +15,10 @@
*/
package com.intellij.ide.projectView.actions;
-import com.intellij.openapi.actionSystem.ActionGroupUtil;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.project.DumbAware;
+import com.intellij.ide.actions.NonTrivialActionGroup;
/**
* @author yole
*/
-public class MarkRootGroup extends DefaultActionGroup implements DumbAware {
- @Override
- public void update(AnActionEvent e) {
- e.getPresentation().setVisible(!ActionGroupUtil.isGroupEmpty(this, e));
- }
+public class MarkRootGroup extends NonTrivialActionGroup {
}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
index 5aedc76..34ccfc6 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/AbstractProjectViewPane.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.
@@ -36,7 +36,6 @@
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.module.Module;
@@ -54,7 +53,7 @@
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.refactoring.move.MoveHandler;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
@@ -256,7 +255,7 @@
if (lastPathComponent instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode node = (DefaultMutableTreeNode)lastPathComponent;
Object userObject = node.getUserObject();
- if (userObject != null && ReflectionCache.isAssignable(nodeClass, userObject.getClass())) {
+ if (userObject != null && ReflectionUtil.isAssignable(nodeClass, userObject.getClass())) {
result.add((T)userObject);
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewDropTarget.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewDropTarget.java
index ce9de80..369301a 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewDropTarget.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ProjectViewDropTarget.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.
@@ -81,7 +81,7 @@
if (targetNode == null || (dropAction & DnDConstants.ACTION_COPY_OR_MOVE) == 0) {
return false;
}
- else if (sourceNodes == null && !FileCopyPasteUtil.isFileListFlavorSupported(event)) {
+ else if (sourceNodes == null && !FileCopyPasteUtil.isFileListFlavorAvailable(event)) {
return false;
}
else if (sourceNodes != null && ArrayUtilRt.find(sourceNodes, targetNode) != -1) {
@@ -124,7 +124,7 @@
assert targetNode != null;
final int dropAction = event.getAction().getActionId();
if (sourceNodes == null) {
- if (FileCopyPasteUtil.isFileListFlavorSupported(event)) {
+ if (FileCopyPasteUtil.isFileListFlavorAvailable(event)) {
List<File> fileList = FileCopyPasteUtil.getFileListFromAttachedObject(attached);
if (!fileList.isEmpty()) {
getDropHandler(dropAction).doDropFiles(fileList, targetNode);
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 1dd47c6..5590975 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
@@ -1160,7 +1160,7 @@
String message = IdeBundle.message("detach.library.from.module", orderEntry.getPresentableName(), module.getName());
String title = IdeBundle.message("detach.library");
int ret = Messages.showOkCancelDialog(project, message, title, Messages.getQuestionIcon());
- if (ret != 0) return;
+ if (ret != Messages.OK) return;
CommandProcessor.getInstance().executeCommand(module.getProject(), new Runnable() {
@Override
public void run() {
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java
index 6430732..6e53e96 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/ShowModulesAction.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.ide.projectView.impl;
import com.intellij.icons.AllIcons;
@@ -11,12 +26,9 @@
import com.intellij.util.PlatformUtils;
/**
-* Created by IntelliJ IDEA.
-* User: anna
-* Date: 8/5/11
-* Time: 9:33 PM
-* To change this template use File | Settings | File Templates.
-*/
+ * @author anna
+ * @since 8/5/11
+ */
public abstract class ShowModulesAction extends ToggleAction {
private final Project myProject;
@@ -48,8 +60,6 @@
}
private static boolean hasModules() {
- return PlatformUtils.isIdea() ||
- PlatformUtils.isCommunity() ||
- PlatformUtils.isFlexIde();
+ return PlatformUtils.isIntelliJ();
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java
index eba28df..c020db9 100644
--- a/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java
+++ b/platform/lang-impl/src/com/intellij/ide/projectView/impl/nodes/ProjectViewProjectNode.java
@@ -25,7 +25,7 @@
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiManager;
@@ -111,7 +111,7 @@
List<VirtualFile> reducedRoots = new ArrayList<VirtualFile>();
while (it.hasNext()) {
VirtualFile next = it.next();
- VirtualFile common = VfsUtil.getCommonAncestor(current, next);
+ VirtualFile common = VfsUtilCore.getCommonAncestor(current, next);
if (common == null || common.getParent() == null || Comparing.equal(common.getPath(), userHome)) {
reducedRoots.add(current);
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
index 256609d..2fbbdc7 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeTreeViewPanel.java
@@ -28,14 +28,16 @@
import com.intellij.ide.projectView.impl.ProjectViewPane;
import com.intellij.ide.projectView.impl.ProjectViewTree;
import com.intellij.ide.scopeView.nodes.BasePsiNode;
-import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.ide.util.DeleteHandler;
import com.intellij.ide.util.DirectoryChooserUtil;
import com.intellij.ide.util.EditorHelper;
import com.intellij.ide.util.treeView.TreeState;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.LangDataKeys;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -47,8 +49,6 @@
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
-import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.IndexNotReadyException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootAdapter;
@@ -298,7 +298,6 @@
}
}
});
- CustomizationUtil.installPopupHandler(myTree, IdeActions.GROUP_PROJECT_VIEW_POPUP, ActionPlaces.PROJECT_VIEW_POPUP);
}
@NotNull
@@ -307,10 +306,13 @@
if (treePaths != null) {
Set<PsiElement> result = new HashSet<PsiElement>();
for (TreePath path : treePaths) {
- PackageDependenciesNode node = (PackageDependenciesNode)path.getLastPathComponent();
- final PsiElement psiElement = node.getPsiElement();
- if (psiElement != null && psiElement.isValid()) {
- result.add(psiElement);
+ final Object component = path.getLastPathComponent();
+ if (component instanceof PackageDependenciesNode) {
+ PackageDependenciesNode node = (PackageDependenciesNode)component;
+ final PsiElement psiElement = node.getPsiElement();
+ if (psiElement != null && psiElement.isValid()) {
+ result.add(psiElement);
+ }
}
}
return PsiUtilCore.toPsiElementArray(result);
diff --git a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
index bf8c41f..8fa7e9b 100644
--- a/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
+++ b/platform/lang-impl/src/com/intellij/ide/scopeView/ScopeViewPane.java
@@ -22,6 +22,7 @@
import com.intellij.ide.projectView.ProjectView;
import com.intellij.ide.projectView.impl.AbstractProjectViewPane;
import com.intellij.ide.projectView.impl.ShowModulesAction;
+import com.intellij.ide.ui.customization.CustomizationUtil;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
@@ -42,14 +43,11 @@
import com.intellij.ui.PopupHandler;
import com.intellij.util.Alarm;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
-import java.util.ArrayList;
-import java.util.List;
/**
* @author cdr
@@ -119,7 +117,7 @@
Disposer.register(this, myViewPanel);
myViewPanel.initListeners();
myTree = myViewPanel.getTree();
- PopupHandler.installPopupHandler(myTree, IdeActions.GROUP_SCOPE_VIEW_POPUP, ActionPlaces.SCOPE_VIEW_POPUP);
+ CustomizationUtil.installPopupHandler(myTree, IdeActions.GROUP_SCOPE_VIEW_POPUP, ActionPlaces.SCOPE_VIEW_POPUP);
enableDnD();
}
diff --git a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java
index e5db940..d49da80 100644
--- a/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.java
+++ b/platform/lang-impl/src/com/intellij/ide/structureView/impl/StructureViewFactoryImpl.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,7 +31,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.ex.ToolWindowEx;
import com.intellij.psi.PsiElement;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -112,7 +112,7 @@
if (result == null) {
MultiValuesMap<Class<? extends PsiElement>, StructureViewExtension> map = myExtensions.getValue();
for (Class<? extends PsiElement> registeredType : map.keySet()) {
- if (ReflectionCache.isAssignable(registeredType, type)) {
+ if (ReflectionUtil.isAssignable(registeredType, type)) {
final Collection<StructureViewExtension> extensions = map.get(registeredType);
for (StructureViewExtension extension : extensions) {
myImplExtensions.put(type, extension);
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java b/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java
index d3d607e..e29c622 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/TodoPanel.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,6 +16,8 @@
package com.intellij.ide.todo;
+import com.intellij.find.FindModel;
+import com.intellij.find.impl.FindInProjectUtil;
import com.intellij.icons.AllIcons;
import com.intellij.ide.*;
import com.intellij.ide.actions.ContextHelpAction;
@@ -151,7 +153,7 @@
);
- myUsagePreviewPanel = new UsagePreviewPanel(myProject);
+ myUsagePreviewPanel = new UsagePreviewPanel(myProject, FindInProjectUtil.setupViewPresentation(false, new FindModel()));
myUsagePreviewPanel.setBorder(IdeBorderFactory.createBorder(SideBorder.LEFT));
Disposer.register(this, myUsagePreviewPanel);
myUsagePreviewPanel.setVisible(mySettings.isShowPreview());
diff --git a/platform/lang-impl/src/com/intellij/ide/todo/configurable/FilterDialog.java b/platform/lang-impl/src/com/intellij/ide/todo/configurable/FilterDialog.java
index 0c73893..2002246 100644
--- a/platform/lang-impl/src/com/intellij/ide/todo/configurable/FilterDialog.java
+++ b/platform/lang-impl/src/com/intellij/ide/todo/configurable/FilterDialog.java
@@ -25,13 +25,13 @@
import com.intellij.psi.search.TodoPattern;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.TableUtil;
import com.intellij.util.ui.Table;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumn;
import java.awt.*;
import java.util.List;
@@ -143,13 +143,7 @@
new GridBagConstraints(0, 0, 1, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(0, 0, 0, 0), 0, 0));
// Column "Available"
-
- int width = new JCheckBox().getPreferredSize().width;
- TableColumn availableColumn = myTable.getColumnModel().getColumn(0);
- availableColumn.setPreferredWidth(width);
- availableColumn.setMaxWidth(width);
- availableColumn.setMinWidth(width);
-
+ TableUtil.setupCheckboxColumn(myTable, 0);
//
panel.add(patternsPanel,
diff --git a/platform/lang-impl/src/com/intellij/ide/util/DeleteHandler.java b/platform/lang-impl/src/com/intellij/ide/util/DeleteHandler.java
index 0df807c..7544d42 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/DeleteHandler.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/DeleteHandler.java
@@ -25,7 +25,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -175,7 +174,7 @@
int result = Messages.showOkCancelDialog(project, warningMessage, IdeBundle.message("title.delete"),
ApplicationBundle.message("button.delete"), CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon());
- if (result != 0) return;
+ if (result != Messages.OK) return;
}
}
@@ -202,7 +201,7 @@
if (!readOnlyFiles.isEmpty()) {
String message = IdeBundle.message("prompt.directory.contains.read.only.files", virtualFile.getPresentableUrl());
int _result = Messages.showYesNoDialog(project, message, IdeBundle.message("title.delete"), Messages.getQuestionIcon());
- if (_result != 0) continue;
+ if (_result != Messages.YES) continue;
boolean success = true;
for (VirtualFile file : readOnlyFiles) {
@@ -223,7 +222,7 @@
.setTitle(IdeBundle.message("title.delete"))
.appendMessage(IdeBundle.message("prompt.delete.it.anyway"))
.askYesNo();
- if (_result != 0) continue;
+ if (_result != Messages.YES) continue;
boolean success = clearReadOnlyFlag(virtualFile, project);
if (!success) continue;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
index 2141894..176e1b7 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/FileStructurePopup.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.
@@ -100,16 +100,16 @@
@NonNls private static final String narrowDownPropertyKey = "FileStructurePopup.narrowDown";
private boolean myShouldNarrowDown = true;
- private FileStructureTree myTree;
+ private final FileStructureTree myTree;
private final FilteringTreeBuilder myAbstractTreeBuilder;
private String myTitle;
- private TreeSpeedSearch mySpeedSearch;
- private SmartTreeStructure myTreeStructure;
+ private final TreeSpeedSearch mySpeedSearch;
+ private final SmartTreeStructure myTreeStructure;
private int myPreferredWidth;
private final FilteringTreeStructure myFilteringStructure;
- private PsiElement myInitialPsiElement;
- private Map<Class, JCheckBox> myCheckBoxes = new HashMap<Class, JCheckBox>();
- private List<JCheckBox> myAutoClicked = new ArrayList<JCheckBox>();
+ private final PsiElement myInitialPsiElement;
+ private final Map<Class, JCheckBox> myCheckBoxes = new HashMap<Class, JCheckBox>();
+ private final List<JCheckBox> myAutoClicked = new ArrayList<JCheckBox>();
private String myTestSearchFilter;
private final ActionCallback myTreeHasBuilt = new ActionCallback();
private boolean myInitialNodeIsLeaf;
@@ -567,7 +567,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
final TreePath path = myTree.getPathForLocation(e.getX(), e.getY());
if (path == null) return false; // user wants to expand/collapse a node
navigateSelectedElement();
@@ -877,7 +877,7 @@
private class FileStructurePopupFilter implements ElementFilter {
private String myLastFilter = null;
- private HashSet<Object> myVisibleParents = new HashSet<Object>();
+ private final Set<Object> myVisibleParents = new HashSet<Object>();
private final boolean isUnitTest = ApplicationManager.getApplication().isUnitTestMode();
@Override
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 9121c5e..01ad4cb 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/PlatformPackageUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -146,7 +146,7 @@
IdeBundle.message("prompt.create.non.existing.package", packageName),
IdeBundle.message("title.package.not.found"),
Messages.getQuestionIcon());
- if (toCreate != 0) {
+ if (toCreate != Messages.YES) {
return null;
}
}
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
index 0627341..d373280 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/ChooseByNameBase.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.
@@ -631,7 +631,7 @@
ListSelectionModel.SINGLE_SELECTION);
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (!myTextField.hasFocus()) {
myTextField.requestFocus();
}
@@ -1698,7 +1698,7 @@
protected boolean isOverflow(@NotNull Set<Object> elementsArray) {
if (elementsArray.size() > UsageLimitUtil.USAGES_LIMIT - myMaximumListSizeLimit && !userAskedToAbort.getAndSet(true)) {
final UsageLimitUtil.Result ret = UsageLimitUtil.showTooManyUsagesWarning(myProject, UsageViewBundle
- .message("find.excessive.usage.count.prompt", elementsArray.size() + myMaximumListSizeLimit));
+ .message("find.excessive.usage.count.prompt", elementsArray.size() + myMaximumListSizeLimit, StringUtil.pluralize(presentation.getUsagesWord())), presentation);
if (ret == UsageLimitUtil.Result.ABORT) {
overFlow[0] = true;
return true;
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
index e53992d..aa6a360 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/DefaultChooseByNameItemProvider.java
@@ -33,7 +33,6 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FindSymbolParameters;
import com.intellij.util.indexing.IdFilter;
-import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -106,7 +105,7 @@
indicator.checkCanceled();
List<Object> sameNameElements = new SmartList<Object>();
- final Map<Object, MatchResult> qualifierMatchResults = new THashMap<Object, MatchResult>();
+ final Map<Object, MatchResult> qualifierMatchResults = ContainerUtil.newIdentityTroveMap();
Comparator<Object> weightComparator = new Comparator<Object>() {
Comparator<Object> modelComparator = model instanceof Comparator ? (Comparator<Object>)model : new PathProximityComparator(myContext.get());
diff --git a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
index 78d18e4..20ebe82 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/gotoByName/GotoActionModel.java
@@ -18,6 +18,7 @@
import com.intellij.ide.DataManager;
import com.intellij.ide.IdeBundle;
+import com.intellij.ide.actions.ApplyIntentionAction;
import com.intellij.ide.ui.search.OptionDescription;
import com.intellij.ide.ui.search.SearchableOptionsRegistrar;
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
@@ -25,11 +26,13 @@
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.actionSystem.impl.ActionManagerImpl;
+import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiFile;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.LightColors;
@@ -48,6 +51,7 @@
public class GotoActionModel implements ChooseByNameModel, CustomMatcherModel, Comparator<Object> {
@NonNls public static final String SETTINGS_KEY = "$$$SETTINGS$$$";
+ @NonNls public static final String INTENTIONS_KEY = "$$$INTENTIONS_KEY$$$";
@Nullable private final Project myProject;
private final Component myContextComponent;
@@ -69,11 +73,25 @@
}
});
+ protected final Map<String, ApplyIntentionAction> myIntentions = new TreeMap<String, ApplyIntentionAction>();
+
public GotoActionModel(@Nullable Project project, final Component component) {
+ this(project, component, null, null);
+ }
+
+ public GotoActionModel(@Nullable Project project, final Component component, @Nullable Editor editor, @Nullable PsiFile file) {
myProject = project;
myContextComponent = component;
final ActionGroup mainMenu = (ActionGroup)myActionManager.getActionOrStub(IdeActions.GROUP_MAIN_MENU);
collectActions(myActionsMap, mainMenu, mainMenu.getTemplatePresentation().getText());
+ if (project != null && editor != null && file != null) {
+ final ApplyIntentionAction[] children = ApplyIntentionAction.getAvailableIntentions(editor, file);
+ if (children != null) {
+ for (ApplyIntentionAction action : children) {
+ myIntentions.put(action.getName(), action);
+ }
+ }
+ }
myIndex = SearchableOptionsRegistrar.getInstance();
}
@@ -211,16 +229,24 @@
.setIcon(icon, 1, (-icon.getIconWidth() + EMPTY_ICON.getIconWidth()) / 2, (EMPTY_ICON.getIconHeight() - icon.getIconHeight()) / 2);
}
- final Shortcut[] shortcutSet = KeymapManager.getInstance().getActiveKeymap().getShortcuts(getActionId(anAction));
- final String actionName = anActionName + (shortcutSet != null && shortcutSet.length > 0
- ? " (" + KeymapUtil.getShortcutText(shortcutSet[0]) + ")"
- : "");
+ final Shortcut shortcut = preferKeyboardShortcut(KeymapManager.getInstance().getActiveKeymap().getShortcuts(getActionId(anAction)));
+ final String actionName = anActionName + (shortcut != null ? " (" + KeymapUtil.getShortcutText(shortcut) + ")" : "");
final JLabel actionLabel = new JLabel(actionName, layeredIcon, SwingConstants.LEFT);
actionLabel.setBackground(bg);
actionLabel.setForeground(fg);
return actionLabel;
}
+ private static Shortcut preferKeyboardShortcut(Shortcut[] shortcuts) {
+ if (shortcuts != null) {
+ for (Shortcut shortcut : shortcuts) {
+ if (shortcut.isKeyboard()) return shortcut;
+ }
+ return shortcuts.length > 0 ? shortcuts[0] : null;
+ }
+ return null;
+ }
+
@Override
public int compare(Object o1, Object o2) {
if (o1 instanceof Map.Entry && !(o2 instanceof Map.Entry)) {
@@ -258,6 +284,7 @@
@NotNull
public String[] getNames(boolean checkBoxState) {
final ArrayList<String> result = new ArrayList<String>();
+ result.add(INTENTIONS_KEY);
for (AnAction action : myActionsMap.keySet()) {
result.add(getActionId(action));
}
@@ -288,6 +315,13 @@
map.put(anAction, null);
}
}
+ } else if (Comparing.strEqual(id, INTENTIONS_KEY)) {
+ for (String intentionText : myIntentions.keySet()) {
+ final ApplyIntentionAction intentionAction = myIntentions.get(intentionText);
+ if (actionMatches(pattern, intentionAction)) {
+ map.put(intentionAction, intentionText);
+ }
+ }
}
Object[] objects = map.entrySet().toArray(new Map.Entry[map.size()]);
if (Comparing.strEqual(id, SETTINGS_KEY)) {
@@ -401,6 +435,10 @@
public boolean matches(@NotNull final String name, @NotNull final String pattern) {
final AnAction anAction = myActionManager.getAction(name);
if (anAction == null) return true;
+ return actionMatches(pattern, anAction);
+ }
+
+ protected boolean actionMatches(String pattern, @NotNull AnAction anAction) {
final Pattern compiledPattern = getPattern(pattern);
final Presentation presentation = anAction.getTemplatePresentation();
final String text = presentation.getText();
diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java
index 896aa6b..5af9651 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/EditScopesDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,7 +19,6 @@
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.InputValidator;
import com.intellij.openapi.ui.Messages;
import com.intellij.packageDependencies.DependencyValidationManager;
@@ -55,8 +54,7 @@
NamedScope scope = manager.getScope(mySelectedScope.getName());
if (scope == null) {
if (Messages.showYesNoDialog(IdeBundle.message("scope.unable.to.save.scope.message"),
- IdeBundle.message("scope.unable.to.save.scope.title"), Messages.getErrorIcon()) == DialogWrapper
- .OK_EXIT_CODE) {
+ IdeBundle.message("scope.unable.to.save.scope.title"), Messages.getErrorIcon()) == Messages.YES) {
final String newName = Messages.showInputDialog(project, IdeBundle.message("add.scope.name.label"),
IdeBundle.message("scopes.save.dialog.title.shared"), Messages.getQuestionIcon(),
mySelectedScope.getName(), new InputValidator() {
diff --git a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java
index 37b1573..b07b60b 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/scopeChooser/ScopeChooserCombo.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.
@@ -24,6 +24,7 @@
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.module.Module;
@@ -31,6 +32,7 @@
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packageDependencies.ChangeListsScopesProvider;
import com.intellij.packageDependencies.DependencyValidationManager;
@@ -110,7 +112,7 @@
addActionListener(createScopeChooserListener());
final JComboBox combo = getComboBox();
- combo.setRenderer(new ScopeDescriptionWithDelimiterRenderer(combo.getRenderer()));
+ combo.setRenderer(new ScopeDescriptionWithDelimiterRenderer());
rebuildModel();
@@ -174,7 +176,7 @@
model.addElement(new ScopeSeparator("VCS Scopes"));
final List<NamedScope> changeLists = ChangeListsScopesProvider.getInstance(myProject).getCustomScopes();
for (NamedScope changeListScope : changeLists) {
- final GlobalSearchScope scope = GlobalSearchScopes.filterScope(myProject, changeListScope);
+ final GlobalSearchScope scope = GlobalSearchScopesCore.filterScope(myProject, changeListScope);
model.addElement(new ScopeDescriptor(scope));
}
@@ -183,7 +185,7 @@
for (NamedScopesHolder holder : holders) {
final NamedScope[] scopes = holder.getEditableScopes(); // predefined scopes already included
for (NamedScope scope : scopes) {
- final GlobalSearchScope searchScope = GlobalSearchScopes.filterScope(myProject, scope);
+ final GlobalSearchScope searchScope = GlobalSearchScopesCore.filterScope(myProject, scope);
customScopes.add(new ScopeDescriptor(searchScope));
}
}
@@ -240,8 +242,8 @@
}
if (!PlatformUtils.isCidr() && ModuleUtil.isSupportedRootType(project, JavaSourceRootType.TEST_SOURCE)) { // TODO: fix these scopes in AppCode
- result.add(GlobalSearchScopes.projectProductionScope(project));
- result.add(GlobalSearchScopes.projectTestScope(project));
+ result.add(GlobalSearchScopesCore.projectProductionScope(project));
+ result.add(GlobalSearchScopesCore.projectTestScope(project));
}
result.add(GlobalSearchScopes.openFilesScope(project));
@@ -273,17 +275,21 @@
if (selectedTextEditor != null) {
final PsiFile psiFile = PsiDocumentManager.getInstance(project).getPsiFile(selectedTextEditor.getDocument());
if (psiFile != null) {
- if (selectedTextEditor.getSelectionModel().hasSelection()) {
- final PsiElement startElement = psiFile.findElementAt(selectedTextEditor.getSelectionModel().getSelectionStart());
+ SelectionModel selectionModel = selectedTextEditor.getSelectionModel();
+ if (selectionModel.hasSelection()) {
+ int start = selectionModel.getSelectionStart();
+ final PsiElement startElement = psiFile.findElementAt(start);
if (startElement != null) {
- final PsiElement endElement = psiFile.findElementAt(selectedTextEditor.getSelectionModel().getSelectionEnd());
+ int end = selectionModel.getSelectionEnd();
+ final PsiElement endElement = psiFile.findElementAt(end);
if (endElement != null) {
final PsiElement parent = PsiTreeUtil.findCommonParent(startElement, endElement);
if (parent != null) {
final List<PsiElement> elements = new ArrayList<PsiElement>();
final PsiElement[] children = parent.getChildren();
+ TextRange selection = new TextRange(start, end);
for (PsiElement child : children) {
- if (!(child instanceof PsiWhiteSpace) && child.getContainingFile() != null) {
+ if (!(child instanceof PsiWhiteSpace) && child.getContainingFile() != null && selection.contains(child.getTextOffset())) {
elements.add(child);
}
}
@@ -445,10 +451,6 @@
}
private static class ScopeDescriptionWithDelimiterRenderer extends ListCellRendererWrapper<ScopeDescriptor> {
- public ScopeDescriptionWithDelimiterRenderer(final ListCellRenderer original) {
- super();
- }
-
@Override
public void customize(JList list, ScopeDescriptor value, int index, boolean selected, boolean hasFocus) {
setText(value.getDisplay());
diff --git a/platform/lang-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java b/platform/lang-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java
index 024dd0c..6ba301a 100644
--- a/platform/lang-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.java
+++ b/platform/lang-impl/src/com/intellij/ide/util/treeView/AbstractTreeStructureBase.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.ide.projectView.TreeStructureProvider;
import com.intellij.ide.projectView.ViewSettings;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.AsyncResult;
@@ -51,6 +52,9 @@
try {
elements = provider.modify(treeNode, (Collection<AbstractTreeNode>)elements, settings);
}
+ catch (ProcessCanceledException e) {
+ throw e;
+ }
catch (Exception e) {
LOG.error(e);
}
diff --git a/platform/lang-impl/src/com/intellij/indentation/AbstractIndentParser.java b/platform/lang-impl/src/com/intellij/indentation/AbstractIndentParser.java
deleted file mode 100644
index 310f3f0..0000000
--- a/platform/lang-impl/src/com/intellij/indentation/AbstractIndentParser.java
+++ /dev/null
@@ -1,205 +0,0 @@
-package com.intellij.indentation;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.lang.PsiBuilder;
-import com.intellij.lang.PsiParser;
-import com.intellij.psi.TokenType;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.util.containers.HashMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * User: Andrey.Vokin
- * Date: 3/20/12
- */
-public abstract class AbstractIndentParser implements PsiParser {
- protected PsiBuilder myBuilder;
-
- protected int myCurrentIndent;
-
- protected HashMap<PsiBuilder.Marker, Integer> myIndents;
- protected HashMap<PsiBuilder.Marker, Boolean> myNewLines;
-
- protected boolean myNewLine = true;
-
- @NotNull
- public ASTNode parse(IElementType root, PsiBuilder builder) {
- myNewLines = new HashMap<PsiBuilder.Marker, Boolean>();
- myIndents = new HashMap<PsiBuilder.Marker, Integer>();
- myBuilder = builder;
- parseRoot(root);
- return myBuilder.getTreeBuilt();
- }
-
- protected abstract void parseRoot(IElementType root);
-
- public PsiBuilder.Marker mark(boolean couldBeRolledBack) {
- final PsiBuilder.Marker marker = myBuilder.mark();
- if (couldBeRolledBack) {
- myIndents.put(marker, myCurrentIndent);
- myNewLines.put(marker, myNewLine);
- }
- return marker;
- }
-
- public PsiBuilder.Marker mark() {
- return mark(false);
- }
-
- public void done(@NotNull final PsiBuilder.Marker marker, @NotNull final IElementType elementType) {
- myIndents.remove(marker);
- myNewLines.remove(marker);
-
- marker.done(elementType);
- }
-
- public static void collapse(@NotNull final PsiBuilder.Marker marker, @NotNull final IElementType elementType) {
- marker.collapse(elementType);
- }
-
- protected static void drop(@NotNull final PsiBuilder.Marker marker) {
- marker.drop();
- }
-
- protected void rollbackTo(@NotNull final PsiBuilder.Marker marker) {
- if (myIndents.get(marker) == null) {
- throw new RuntimeException("Parser can't rollback marker that was created by mark() method, use mark(true) instead");
- }
- myCurrentIndent = myIndents.get(marker);
- myNewLine = myNewLines.get(marker);
-
- myIndents.remove(marker);
- myNewLines.remove(marker);
- marker.rollbackTo();
- }
-
- protected boolean eof() {
- return myBuilder.eof();
- }
-
- protected int getCurrentOffset() {
- return myBuilder.getCurrentOffset();
- }
-
- public int getCurrentIndent() {
- return myCurrentIndent;
- }
-
- protected void error(String message) {
- myBuilder.error(message);
- }
-
- @Nullable
- public IElementType getTokenType() {
- return myBuilder.getTokenType();
- }
-
- protected static boolean tokenIn(@Nullable final IElementType elementType, IElementType... tokens) {
- for (IElementType token : tokens) {
- if (elementType == token) {
- return true;
- }
- }
- return false;
- }
-
- protected boolean currentTokenIn(IElementType... tokens) {
- return tokenIn(getTokenType(), tokens);
- }
-
- protected boolean currentTokenIn(@NotNull final TokenSet tokenSet) {
- return tokenSet.contains(getTokenType());
- }
-
- protected static boolean tokenIn(@Nullable final IElementType elementType, @NotNull final TokenSet tokenSet) {
- return tokenIn(elementType, tokenSet.getTypes());
- }
-
- @NotNull
- protected String getTokenText() {
- String result = myBuilder.getTokenText();
- if (result == null) {
- result = "";
- }
- return result;
- }
-
- protected boolean expect(@NotNull final IElementType elementType) {
- return expect(elementType, "Expected: " + elementType);
- }
-
- protected boolean expect(@NotNull final IElementType elementType, String expectedMessage) {
- if (getTokenType() == elementType) {
- advance();
- return true;
- }
- error(expectedMessage);
- return false;
- }
-
- @Nullable
- public IElementType lookAhead(int step) {
- return myBuilder.lookAhead(step);
- }
-
- @Nullable
- public IElementType rawLookup(int step) {
- return myBuilder.rawLookup(step);
- }
-
- public boolean isNewLine() {
- return myNewLine;
- }
-
- public void advance() {
- final String tokenText = myBuilder.getTokenText();
- final int tokenLength = tokenText == null ? 0 : tokenText.length();
-
- final int whiteSpaceStart = getCurrentOffset() + tokenLength;
- myBuilder.advanceLexer();
- final int whiteSpaceEnd = getCurrentOffset();
- final String whiteSpaceText = myBuilder.getOriginalText().subSequence(whiteSpaceStart, whiteSpaceEnd).toString();
-
- int i = whiteSpaceText.lastIndexOf('\n');
- if (i >= 0) {
- myCurrentIndent = whiteSpaceText.length() - i - 1;
- myNewLine = true;
- }
- else {
- myNewLine = false;
- }
- }
-
- protected void advanceUntil(TokenSet tokenSet) {
- while (getTokenType() != null && !isNewLine() && !tokenSet.contains(getTokenType())) {
- advance();
- }
- }
-
- protected void advanceUntilEol() {
- advanceUntil(TokenSet.EMPTY);
- }
-
- protected void errorUntil(TokenSet tokenSet, String message) {
- PsiBuilder.Marker errorMarker = mark();
- advanceUntil(tokenSet);
- errorMarker.error(message);
- }
-
- protected void errorUntilEol(String message) {
- PsiBuilder.Marker errorMarker = mark();
- advanceUntilEol();
- errorMarker.error(message);
- }
-
- protected void expectEolOrEof() {
- if (!isNewLine() && !eof()) {
- errorUntilEol("End of line expected");
- }
- }
-
- protected abstract IElementType getIndentElementType();
- protected abstract IElementType getEolElementType();
-}
diff --git a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java b/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java
deleted file mode 100644
index 01164ee..0000000
--- a/platform/lang-impl/src/com/intellij/indentation/IndentationFoldingBuilder.java
+++ /dev/null
@@ -1,95 +0,0 @@
-package com.intellij.indentation;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.lang.folding.FoldingBuilder;
-import com.intellij.lang.folding.FoldingDescriptor;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.psi.tree.TokenSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-
-/**
- * @author oleg
- */
-public abstract class IndentationFoldingBuilder implements FoldingBuilder, DumbAware {
- private final TokenSet myTokenSet;
-
- public IndentationFoldingBuilder(final TokenSet tokenSet) {
- myTokenSet = tokenSet;
- }
-
- @Override
- @NotNull
- public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode astNode, @NotNull Document document) {
- List<FoldingDescriptor> descriptors = new LinkedList<FoldingDescriptor>();
- collectDescriptors(astNode, descriptors);
- return descriptors.toArray(new FoldingDescriptor[descriptors.size()]);
- }
-
- private void collectDescriptors(@NotNull final ASTNode node, @NotNull final List<FoldingDescriptor> descriptors) {
- final Queue<ASTNode> toProcess = new LinkedList<ASTNode>();
- toProcess.add(node);
- while (!toProcess.isEmpty()) {
- final ASTNode current = toProcess.remove();
- if (current.getTreeParent() != null
- && current.getTextLength() > 1
- && myTokenSet.contains(current.getElementType()))
- {
- descriptors.add(new FoldingDescriptor(current, current.getTextRange()));
- }
- for (ASTNode child = current.getFirstChildNode(); child != null; child = child.getTreeNext()) {
- toProcess.add(child);
- }
- }
- }
-
- @Override
- @Nullable
- public String getPlaceholderText(@NotNull final ASTNode node) {
- final StringBuilder builder = new StringBuilder();
- ASTNode child = node.getFirstChildNode();
- while (child != null) {
- String text = child.getText();
- if (text == null) {
- if (builder.length() > 0) {
- break;
- }
- }
- else if (!text.contains("\n")) {
- builder.append(text);
- }
- else if (builder.length() > 0) {
- builder.append(text.substring(0, text.indexOf('\n')));
- break;
- }
- else {
- builder.append(getFirstNonEmptyLine(text));
- if (builder.length() > 0) {
- break;
- }
- }
- child = child.getTreeNext();
- }
- return builder.toString();
- }
-
- @NotNull
- private static String getFirstNonEmptyLine(@NotNull final String text) {
- int start = 0;
- int end;
- while ((end = text.indexOf('\n', start)) != -1 && start >= end) {
- start = end + 1;
- }
- return end == -1 ? text.substring(start) : text.substring(start, end);
- }
-
- @Override
- public boolean isCollapsedByDefault(@NotNull ASTNode node) {
- return false;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java b/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java
deleted file mode 100644
index aceefae..0000000
--- a/platform/lang-impl/src/com/intellij/indentation/IndentationParser.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.intellij.indentation;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.lang.PsiBuilder;
-import com.intellij.lang.PsiParser;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.util.containers.Stack;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author oleg
- */
-public abstract class IndentationParser implements PsiParser {
- @NotNull
- private final IElementType myEolTokenType;
- @NotNull
- private final IElementType myIndentTokenType;
- @NotNull
- private final IElementType myBlockElementType;
- @NotNull
- private final IElementType myDocumentType;
-
- public IndentationParser(
- @NotNull IElementType documentType,
- @NotNull final IElementType blockElementType,
- @NotNull final IElementType eolTokenType,
- @NotNull final IElementType indentTokenType)
- {
- myDocumentType = documentType;
- myBlockElementType = blockElementType;
- myEolTokenType = eolTokenType;
- myIndentTokenType = indentTokenType;
- }
-
- @Override
- @NotNull
- public final ASTNode parse(final IElementType root, final PsiBuilder builder) {
- final PsiBuilder.Marker fileMarker = builder.mark();
- final PsiBuilder.Marker documentMarker = builder.mark();
-
- final Stack<BlockInfo> stack = new Stack<BlockInfo>();
- stack.push(new BlockInfo(0, builder.mark(), builder.getTokenType()));
-
- PsiBuilder.Marker startLineMarker = null;
- int currentIndent = 0;
- boolean eolSeen = false;
-
- while (!builder.eof()) {
- final IElementType type = builder.getTokenType();
- // EOL
- if (type == myEolTokenType) {
- // Handle variant with several EOLs
- if (startLineMarker == null) {
- startLineMarker = builder.mark();
- }
- eolSeen = true;
- }
- else {
- if (type == myIndentTokenType) {
- //noinspection ConstantConditions
- currentIndent = builder.getTokenText().length();
- }
- else {
- if (!eolSeen && !stack.isEmpty() && currentIndent > 0 && currentIndent < stack.peek().getIndent()) {
- // sometimes we do not have EOL between indents
- eolSeen = true;
- }
- if (eolSeen) {
- if (startLineMarker != null) {
- startLineMarker.rollbackTo();
- startLineMarker = null;
- }
- // Close indentation blocks
- while (!stack.isEmpty() && currentIndent < stack.peek().getIndent()) {
- final BlockInfo blockInfo = stack.pop();
- closeBlock(builder, blockInfo.getMarker(), blockInfo.getStartTokenType());
- }
-
- if (!stack.isEmpty()) {
- final BlockInfo blockInfo = stack.peek();
- if (currentIndent >= blockInfo.getIndent()) {
- if (currentIndent == blockInfo.getIndent()) {
- final BlockInfo info = stack.pop();
- closeBlock(builder, info.getMarker(), info.getStartTokenType());
- }
- passEOLsAndIndents(builder);
- stack.push(new BlockInfo(currentIndent, builder.mark(), type));
- }
- }
- eolSeen = false;
- currentIndent = 0;
- }
- }
- }
- advanceLexer(builder);
- }
-
- // Close all left opened markers
- if (startLineMarker != null){
- startLineMarker.drop();
- }
- while (!stack.isEmpty()){
- final BlockInfo blockInfo = stack.pop();
- closeBlock(builder, blockInfo.getMarker(), blockInfo.getStartTokenType());
- }
-
- documentMarker.done(myDocumentType);
- fileMarker.done(root);
- return builder.getTreeBuilt();
- }
-
- protected void closeBlock(final @NotNull PsiBuilder builder,
- final @NotNull PsiBuilder.Marker marker,
- final @Nullable IElementType startTokenType)
- {
- marker.done(myBlockElementType);
- }
-
- protected void advanceLexer(@NotNull PsiBuilder builder) {
- builder.advanceLexer();
- }
-
- private void passEOLsAndIndents(@NotNull final PsiBuilder builder) {
- IElementType tokenType = builder.getTokenType();
- while (tokenType == myEolTokenType || tokenType == myIndentTokenType) {
- builder.advanceLexer();
- tokenType = builder.getTokenType();
- }
- }
-
- private static final class BlockInfo {
- private final int myIndent;
- @NotNull
- private final PsiBuilder.Marker myMarker;
- @Nullable
- private final IElementType myStartTokenType;
-
- private BlockInfo(final int indent, final @NotNull PsiBuilder.Marker marker, final @Nullable IElementType type) {
- myIndent = indent;
- myMarker = marker;
- myStartTokenType = type;
- }
-
- public int getIndent() {
- return myIndent;
- }
-
- @NotNull
- public PsiBuilder.Marker getMarker() {
- return myMarker;
- }
-
- @Nullable
- public IElementType getStartTokenType() {
- return myStartTokenType;
- }
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/indentation/OperationParserHelper.java b/platform/lang-impl/src/com/intellij/indentation/OperationParserHelper.java
deleted file mode 100644
index 604fab7..0000000
--- a/platform/lang-impl/src/com/intellij/indentation/OperationParserHelper.java
+++ /dev/null
@@ -1,207 +0,0 @@
-package com.intellij.indentation;
-
-import com.intellij.lang.PsiBuilder;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.tree.TokenSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * User: Andrey.Vokin
- * Date: 3/23/12
- */
-public class OperationParserHelper {
- private static boolean parsePostfixOperation(@NotNull final BinaryOperationParser parser) {
- final PsiBuilder.Marker tempMarker = parser.mark();
- PsiBuilder.Marker lastMarker = tempMarker;
- boolean result = parsePrefixOperation(parser);
- boolean tempMarkerDeleted = false;
- while (parser.getPostfixOperators().contains(parser.getTokenType()) &&
- !parser.getWhitespaceTokenSet().contains(parser.rawLookup(-1)) && !parser.isNewLine()) {
- final PsiBuilder.Marker operationMarker = lastMarker.precede();
- if (!tempMarkerDeleted) {
- tempMarker.drop();
- tempMarkerDeleted = true;
- }
- lastMarker = operationMarker;
- parser.advance();
- parser.done(operationMarker, parser.getPostfixExpressionElementType());
- result = true;
- }
- if (!tempMarkerDeleted) {
- tempMarker.drop();
- }
- return result;
- }
-
- private static boolean parsePrefixOperation(@NotNull final BinaryOperationParser parser) {
- int prefixCount = 0;
- while (parser.getPrefixOperators().contains(parser.lookAhead(prefixCount))) {
- prefixCount++;
- }
- final PsiBuilder.Marker[] prefixMarkers = new PsiBuilder.Marker[prefixCount];
- final IElementType[] elementTypes = new IElementType[prefixCount];
- for (int i = 0; i < prefixCount; i++) {
- prefixMarkers[i] = parser.mark();
- elementTypes[i] = parser.getPrefixExpressionElementType();
- parser.advance();
- }
- final boolean result = parser.parseSimpleExpression() || prefixCount > 0;
- for (int i = prefixCount - 1; i >= 0; i--) {
- parser.done(prefixMarkers[i], elementTypes[i]);
- }
- return result;
- }
-
- public static boolean callParsingBinaryOperation(@NotNull final BinaryOperationParser parser, int level) {
- if (level < 0) {
- return parsePostfixOperation(parser);
- }
- return parseBinaryOperation(parser, level);
- }
-
- private static boolean isBinaryOperator(@NotNull final BinaryOperationParser parser, int level) {
- if (parser instanceof CustomBinaryOperationParser) {
- return ((CustomBinaryOperationParser)parser).isBinaryOperator(level);
- }
- final IElementType tokenType = parser.getTokenType();
- return parser.getOperatorsByPriority()[level].contains(tokenType);
- }
-
- private static void parseBinaryOperator(@NotNull final BinaryOperationParser parser) {
- if (parser instanceof CustomBinaryOperationParser) {
- ((CustomBinaryOperationParser)parser).parseBinaryOperator();
- } else {
- parser.advance();
- }
- }
-
- /**
- * Parses arithmetic mult, arithmetic sum, bit operation, relation operation
- * @param level 0 for mult, 1, for sum, 2 for bit, 3 for relations
- */
- private static boolean parseBinaryOperation(@NotNull final BinaryOperationParser parser, int level) {
- final PsiBuilder.Marker tempMarker = parser.mark();
- PsiBuilder.Marker lastMarker = tempMarker;
- boolean result = callParsingBinaryOperation(parser, level - 1);
- boolean tempMarkerDeleted = false;
- while (isBinaryOperator(parser, level) && !parser.isNewLine()) {
- final PsiBuilder.Marker operationMarker = lastMarker.precede();
- if (!tempMarkerDeleted) {
- tempMarker.drop();
- tempMarkerDeleted = true;
- }
- lastMarker = operationMarker;
- parseBinaryOperator(parser);
- callParsingBinaryOperation(parser, level - 1);
- parser.done(operationMarker, parser.getOperationElementTypes()[level]);
- result = true;
- }
- if (!tempMarkerDeleted) {
- tempMarker.drop();
- }
- return result;
- }
-
- public interface BinaryOperationParser {
- /**
- * Gets the TokenType from PsiBuilder
- * @return IElementType of current element
- */
- IElementType getTokenType();
-
- /**
- * Checks current token starts the line
- * @return true if new line
- */
- boolean isNewLine();
-
- /**
- * Advance current position of PsiBuilder
- */
- void advance();
-
- /**
- * See what token type is in <code>step</code> ahead / benind (including whitespaces)
- * @param step 0 is current token, -1 is previous, 1 is next and so on
- * @return IElementType of the required element
- */
- IElementType rawLookup(int step);
-
- /**
- * See what token type is in <code>step</code> ahead (not including whitespaces)
- * @param step 0 is current token, 1 is next and so on
- * @return IElementType of the required element
- */
- IElementType lookAhead(int step);
-
- /**
- * Create new marker
- * @return PsiBuilder.Marker of created marker
- */
- PsiBuilder.Marker mark();
-
- /**
- * Close marker with element type
- * @param marker to close
- * @param elementType to close marker as
- */
- void done(PsiBuilder.Marker marker, IElementType elementType);
-
- /**
- * Parses operand
- * @return boolean if success
- */
- boolean parseSimpleExpression();
-
- /**
- * Provides all whitespace tokens
- * @return TokenSet of whitespaces
- */
- TokenSet getWhitespaceTokenSet();
-
- /**
- * Provides prefix operators
- * @return TokenSet of prefix operators
- */
- TokenSet getPrefixOperators();
-
- /**
- * Provides postfix operators
- * @return TokenSet of prefix operators
- */
- TokenSet getPostfixOperators();
-
- /**
- * Provides operation priority and operands
- * @return array of TokenSets
- */
- TokenSet[] getOperatorsByPriority();
-
- /**
- * Provides element types to finish postfix element marker
- * @return IElementType
- */
- @Nullable
- IElementType getPostfixExpressionElementType();
-
- /**
- * Provides element types to finish prefix element marker
- * @return IElementType
- */
- @Nullable
- IElementType getPrefixExpressionElementType();
-
- /**
- * Provides element types to finish binary operation element
- * @return array of Element Types
- */
- IElementType[] getOperationElementTypes();
- }
-
- public interface CustomBinaryOperationParser {
- boolean isBinaryOperator(int level);
-
- void parseBinaryOperator();
- }
-}
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 06188e4..a3e4a80 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/CaretModelWindow.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,14 +16,19 @@
package com.intellij.injected.editor;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.VisualPosition;
+import com.intellij.openapi.editor.*;
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.ArrayList;
+import java.util.Collection;
+import java.util.List;
/**
* @author Alexey
@@ -102,7 +107,8 @@
@Override
public void caretPositionChanged(CaretEvent e) {
if (!myEditorWindow.getDocument().isValid()) return; // injected document can be destroyed by now
- CaretEvent event = new CaretEvent(myEditorWindow, myEditorWindow.hostToInjected(e.getOldPosition()),
+ CaretEvent event = new CaretEvent(myEditorWindow, createInjectedCaret(e.getCaret()),
+ myEditorWindow.hostToInjected(e.getOldPosition()),
myEditorWindow.hostToInjected(e.getNewPosition()));
listener.caretPositionChanged(event);
}
@@ -140,4 +146,94 @@
public TextAttributes getTextAttributes() {
return myDelegate.getTextAttributes();
}
+
+ @Override
+ public boolean supportsMultipleCarets() {
+ return myDelegate.supportsMultipleCarets();
+ }
+
+ @NotNull
+ @Override
+ public Caret getCurrentCaret() {
+ return createInjectedCaret(myDelegate.getCurrentCaret());
+ }
+
+ @NotNull
+ @Override
+ public Caret getPrimaryCaret() {
+ return createInjectedCaret(myDelegate.getPrimaryCaret());
+ }
+
+ @NotNull
+ @Override
+ public Collection<Caret> getAllCarets() {
+ Collection<Caret> hostCarets = myDelegate.getAllCarets();
+ Collection<Caret> carets = new ArrayList<Caret>(hostCarets.size());
+ for (Caret hostCaret : hostCarets) {
+ carets.add(createInjectedCaret(hostCaret));
+ }
+ return carets;
+ }
+
+ @Nullable
+ @Override
+ public Caret getCaretAt(@NotNull VisualPosition pos) {
+ LogicalPosition hostPos = myEditorWindow.injectedToHost(myEditorWindow.visualToLogicalPosition(pos));
+ Caret caret = myDelegate.getCaretAt(myHostEditor.logicalToVisualPosition(hostPos));
+ return createInjectedCaret(caret);
+ }
+
+ @Nullable
+ @Override
+ public Caret addCaret(@NotNull VisualPosition pos) {
+ LogicalPosition hostPos = myEditorWindow.injectedToHost(myEditorWindow.visualToLogicalPosition(pos));
+ Caret caret = myDelegate.addCaret(myHostEditor.logicalToVisualPosition(hostPos));
+ return createInjectedCaret(caret);
+ }
+
+ @Override
+ public boolean removeCaret(@NotNull Caret caret) {
+ if (caret instanceof InjectedCaret) {
+ caret = ((InjectedCaret)caret).myDelegate;
+ }
+ return myDelegate.removeCaret(caret);
+ }
+
+ @Override
+ public void removeSecondaryCarets() {
+ myDelegate.removeSecondaryCarets();
+ }
+
+ @Override
+ public void setCarets(@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));
+ }
+ 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.setCarets(convertedPositions, convertedSelections);
+ }
+
+ private InjectedCaret createInjectedCaret(Caret caret) {
+ return caret == null ? null : new InjectedCaret(myEditorWindow, caret);
+ }
+
+ @Override
+ public void runForEachCaret(final @NotNull CaretAction action) {
+ myDelegate.runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ action.perform(createInjectedCaret(caret));
+ }
+ });
+ }
+
+ @Override
+ public void runBatchCaretOperation(@NotNull Runnable runnable) {
+ myDelegate.runBatchCaretOperation(runnable);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java
index a44f1b6..ffb3254 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/DocumentWindowImpl.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,6 +33,7 @@
import com.intellij.psi.impl.source.tree.injected.Place;
import com.intellij.util.Processor;
import com.intellij.util.text.CharArrayUtil;
+import com.intellij.util.text.ImmutableCharSequence;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -170,6 +171,7 @@
return startOffsetOfNextLine == 0 || getText().charAt(startOffsetOfNextLine - 1) != '\n' ? startOffsetOfNextLine : startOffsetOfNextLine - 1;
}
+ @NotNull
@Override
public String getText() {
CachedText cachedText = myCachedText;
@@ -210,6 +212,12 @@
return getText();
}
+ @NotNull
+ @Override
+ public CharSequence getImmutableCharSequence() {
+ return ImmutableCharSequence.asImmutable(getText());
+ }
+
@Override
@NotNull
public char[] getChars() {
@@ -744,11 +752,12 @@
synchronized (myLock) {
Segment hostRangeMarker = myShreds.get(0).getHostRangeMarker();
if (hostRangeMarker == null || end - start > hostRangeMarker.getEndOffset() - hostRangeMarker.getStartOffset()) return false;
+ ProperTextRange query = new ProperTextRange(start, end);
for (PsiLanguageInjectionHost.Shred shred : myShreds) {
Segment hostRange = shred.getHostRangeMarker();
if (hostRange == null) continue;
TextRange textRange = ProperTextRange.create(hostRange);
- if (textRange.contains(new ProperTextRange(start, end))) return true;
+ if (textRange.contains(query)) return true;
}
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
deleted file mode 100644
index 897d87f..0000000
--- a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindow.java
+++ /dev/null
@@ -1,831 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.intellij.injected.editor;
-
-import com.intellij.ide.CopyProvider;
-import com.intellij.ide.CutProvider;
-import com.intellij.ide.DeleteProvider;
-import com.intellij.ide.PasteProvider;
-import com.intellij.ide.highlighter.HighlighterFactory;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.*;
-import com.intellij.openapi.editor.colors.EditorColorsManager;
-import com.intellij.openapi.editor.colors.EditorColorsScheme;
-import com.intellij.openapi.editor.event.EditorMouseEvent;
-import com.intellij.openapi.editor.event.EditorMouseEventArea;
-import com.intellij.openapi.editor.event.EditorMouseListener;
-import com.intellij.openapi.editor.event.EditorMouseMotionListener;
-import com.intellij.openapi.editor.ex.*;
-import com.intellij.openapi.editor.ex.util.EditorUtil;
-import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.LightHighlighterClient;
-import com.intellij.openapi.editor.impl.EditorImpl;
-import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
-import com.intellij.openapi.editor.impl.TextDrawingCallback;
-import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
-import com.intellij.openapi.editor.markup.MarkupModel;
-import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.UserDataHolderBase;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
-import com.intellij.util.containers.WeakList;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.border.Border;
-import java.awt.*;
-import java.awt.event.KeyEvent;
-import java.awt.event.MouseEvent;
-import java.beans.PropertyChangeListener;
-import java.util.*;
-import java.util.List;
-
-/**
- * @author Alexey
- */
-public class EditorWindow extends UserDataHolderBase implements EditorEx {
- private final DocumentWindowImpl myDocumentWindow;
- private final EditorImpl myDelegate;
- private volatile PsiFile myInjectedFile;
- private final boolean myOneLine;
- private final CaretModelWindow myCaretModelDelegate;
- private final SelectionModelWindow mySelectionModelDelegate;
- private static final List<EditorWindow> allEditors = new WeakList<EditorWindow>();
- private boolean myDisposed;
- private final MarkupModelWindow myMarkupModelDelegate;
- private final FoldingModelWindow myFoldingModelWindow;
- private final SoftWrapModelImpl mySoftWrapModel;
-
- public static Editor create(@NotNull final DocumentWindowImpl documentRange, @NotNull final EditorImpl editor, @NotNull final PsiFile injectedFile) {
- assert documentRange.isValid();
- assert injectedFile.isValid();
- EditorWindow window;
- synchronized (allEditors) {
- for (EditorWindow editorWindow : allEditors) {
- if (editorWindow.getDocument() == documentRange && editorWindow.getDelegate() == editor) {
- editorWindow.myInjectedFile = injectedFile;
- if (editorWindow.isValid()) {
- return editorWindow;
- }
- }
- if (editorWindow.getDocument().areRangesEqual(documentRange)) {
- //int i = 0;
- }
- }
- window = new EditorWindow(documentRange, editor, injectedFile, documentRange.isOneLine());
- allEditors.add(window);
- }
- assert window.isValid();
- return window;
- }
-
- private EditorWindow(@NotNull DocumentWindowImpl documentWindow, @NotNull final EditorImpl delegate, @NotNull PsiFile injectedFile, boolean oneLine) {
- myDocumentWindow = documentWindow;
- myDelegate = delegate;
- myInjectedFile = injectedFile;
- myOneLine = oneLine;
- myCaretModelDelegate = new CaretModelWindow(myDelegate.getCaretModel(), this);
- mySelectionModelDelegate = new SelectionModelWindow(myDelegate, myDocumentWindow,this);
- myMarkupModelDelegate = new MarkupModelWindow((MarkupModelEx)myDelegate.getMarkupModel(), myDocumentWindow);
- myFoldingModelWindow = new FoldingModelWindow(delegate.getFoldingModel(), documentWindow, this);
- mySoftWrapModel = new SoftWrapModelImpl(this);
- Disposer.register(myDocumentWindow, mySoftWrapModel);
- }
-
- public static void disposeInvalidEditors() {
- ApplicationManager.getApplication().assertWriteAccessAllowed();
- Iterator<EditorWindow> iterator = allEditors.iterator();
- while (iterator.hasNext()) {
- EditorWindow editorWindow = iterator.next();
- if (!editorWindow.isValid()) {
- editorWindow.dispose();
-
- InjectedLanguageUtil.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
- iterator.remove();
- }
- }
- }
-
- public boolean isValid() {
- return !isDisposed() && !myInjectedFile.getProject().isDisposed() && myInjectedFile.isValid() && myDocumentWindow.isValid();
- }
-
- public PsiFile getInjectedFile() {
- return myInjectedFile;
- }
-
- @NotNull
- public LogicalPosition hostToInjected(@NotNull LogicalPosition hPos) {
- assert isValid();
- DocumentEx hostDocument = myDelegate.getDocument();
- int hLineEndOffset = hPos.line >= hostDocument.getLineCount() ? hostDocument.getTextLength() : hostDocument.getLineEndOffset(hPos.line);
- LogicalPosition hLineEndPos = myDelegate.offsetToLogicalPosition(hLineEndOffset);
- if (hLineEndPos.column < hPos.column) {
- // in virtual space
- LogicalPosition iPos = myDocumentWindow.hostToInjectedInVirtualSpace(hPos);
- if (iPos != null) {
- return iPos;
- }
- }
-
- int hOffset = myDelegate.logicalPositionToOffset(hPos);
- int iOffset = myDocumentWindow.hostToInjected(hOffset);
- return offsetToLogicalPosition(iOffset);
- }
-
- @NotNull
- public LogicalPosition injectedToHost(@NotNull LogicalPosition pos) {
- assert isValid();
- // beware the virtual space
- int column = pos.column;
- int lineStartOffset = myDocumentWindow.getLineStartOffset(pos.line);
- int lineEndOffset = myDocumentWindow.getLineEndOffset(pos.line);
- if (column > lineEndOffset - lineStartOffset) {
- // in virtual space, calculate the host pos as an offset from the line end
- int delta = column - (lineEndOffset - lineStartOffset);
-
- int baseOffsetInHost = myDocumentWindow.injectedToHost(lineEndOffset);
- LogicalPosition lineStartPosInHost = myDelegate.offsetToLogicalPosition(baseOffsetInHost);
- return new LogicalPosition(lineStartPosInHost.line, lineStartPosInHost.column + delta);
- }
- else {
- int offset = lineStartOffset + column;
- int hostOffset = getDocument().injectedToHost(offset);
- int hostLineNumber = getDocument().getDelegate().getLineNumber(hostOffset);
- int hostLineStart = getDocument().getDelegate().getLineStartOffset(hostLineNumber);
-
- return new LogicalPosition(hostLineNumber, hostOffset - hostLineStart);
- }
-
- }
-
- private void dispose() {
- assert !myDisposed;
- myCaretModelDelegate.disposeModel();
-
- for (EditorMouseListener wrapper : myEditorMouseListeners.wrappers()) {
- myDelegate.removeEditorMouseListener(wrapper);
- }
- myEditorMouseListeners.clear();
- for (EditorMouseMotionListener wrapper : myEditorMouseMotionListeners.wrappers()) {
- myDelegate.removeEditorMouseMotionListener(wrapper);
- }
- myEditorMouseMotionListeners.clear();
-
- myDisposed = true;
- Disposer.dispose(myDocumentWindow);
- }
-
- @Override
- public boolean isViewer() {
- return myDelegate.isViewer();
- }
-
- @Override
- public boolean isRendererMode() {
- return myDelegate.isRendererMode();
- }
-
- @Override
- public void setRendererMode(final boolean isRendererMode) {
- myDelegate.setRendererMode(isRendererMode);
- }
-
- @Override
- public void setFile(final VirtualFile vFile) {
- myDelegate.setFile(vFile);
- }
-
- @Override
- public void setHeaderComponent(@Nullable JComponent header) {
-
- }
-
- @Override
- public boolean hasHeaderComponent() {
- return false;
- }
-
- @Override
- @Nullable
- public JComponent getHeaderComponent() {
- return null;
- }
-
- @Override
- public TextDrawingCallback getTextDrawingCallback() {
- return myDelegate.getTextDrawingCallback();
- }
-
- @Override
- @NotNull
- public SelectionModel getSelectionModel() {
- return mySelectionModelDelegate;
- }
-
- @Override
- @NotNull
- public MarkupModel getMarkupModel() {
- return myMarkupModelDelegate;
- }
-
- @Override
- @NotNull
- public FoldingModelEx getFoldingModel() {
- return myFoldingModelWindow;
- }
-
- @Override
- @NotNull
- public CaretModel getCaretModel() {
- return myCaretModelDelegate;
- }
-
- @Override
- @NotNull
- public ScrollingModelEx getScrollingModel() {
- return myDelegate.getScrollingModel();
- }
-
- @Override
- @NotNull
- public SoftWrapModelEx getSoftWrapModel() {
- return mySoftWrapModel;
- }
-
- @Override
- @NotNull
- public EditorSettings getSettings() {
- return myDelegate.getSettings();
- }
-
- @Override
- public void reinitSettings() {
- myDelegate.reinitSettings();
- }
-
- @Override
- public void setFontSize(final int fontSize) {
- myDelegate.setFontSize(fontSize);
- }
-
- @Override
- public void setHighlighter(@NotNull final EditorHighlighter highlighter) {
- myDelegate.setHighlighter(highlighter);
- }
-
- @NotNull
- @Override
- public EditorHighlighter getHighlighter() {
- EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
- EditorHighlighter highlighter = HighlighterFactory.createHighlighter(myInjectedFile.getVirtualFile(), scheme, getProject());
- highlighter.setText(getDocument().getText());
- highlighter.setEditor(new LightHighlighterClient(getDocument(), getProject()));
- return highlighter;
- }
-
- @Override
- public JComponent getPermanentHeaderComponent() {
- return myDelegate.getPermanentHeaderComponent();
- }
-
- @Override
- public void setPermanentHeaderComponent(JComponent component) {
- myDelegate.setPermanentHeaderComponent(component);
- }
-
- @Override
- @NotNull
- public JComponent getContentComponent() {
- return myDelegate.getContentComponent();
- }
-
- @NotNull
- @Override
- public EditorGutterComponentEx getGutterComponentEx() {
- return myDelegate.getGutterComponentEx();
- }
-
- @Override
- public void addPropertyChangeListener(@NotNull final PropertyChangeListener listener) {
- myDelegate.addPropertyChangeListener(listener);
- }
-
- @Override
- public void removePropertyChangeListener(@NotNull final PropertyChangeListener listener) {
- myDelegate.removePropertyChangeListener(listener);
- }
-
- @Override
- public void setInsertMode(final boolean mode) {
- myDelegate.setInsertMode(mode);
- }
-
- @Override
- public boolean isInsertMode() {
- return myDelegate.isInsertMode();
- }
-
- @Override
- public void setColumnMode(final boolean mode) {
- myDelegate.setColumnMode(mode);
- }
-
- @Override
- public boolean isColumnMode() {
- return myDelegate.isColumnMode();
- }
-
- @Override
- @NotNull
- public VisualPosition xyToVisualPosition(@NotNull final Point p) {
- return logicalToVisualPosition(xyToLogicalPosition(p));
- }
-
- @Override
- @NotNull
- public VisualPosition offsetToVisualPosition(final int offset) {
- return logicalToVisualPosition(offsetToLogicalPosition(offset));
- }
-
- @Override
- @NotNull
- public LogicalPosition offsetToLogicalPosition(final int offset) {
- return offsetToLogicalPosition(offset, true);
- }
-
- @Override
- @NotNull
- public LogicalPosition offsetToLogicalPosition(final int offset, boolean softWrapAware) {
- assert isValid();
- int lineNumber = myDocumentWindow.getLineNumber(offset);
- int lineStartOffset = myDocumentWindow.getLineStartOffset(lineNumber);
- int column = calcLogicalColumnNumber(offset-lineStartOffset, lineNumber, lineStartOffset);
- return new LogicalPosition(lineNumber, column);
- }
-
- @NotNull
- @Override
- public EditorColorsScheme createBoundColorSchemeDelegate(@Nullable EditorColorsScheme customGlobalScheme) {
- return myDelegate.createBoundColorSchemeDelegate(customGlobalScheme);
- }
-
- @Override
- @NotNull
- public LogicalPosition xyToLogicalPosition(@NotNull final Point p) {
- assert isValid();
- LogicalPosition hostPos = myDelegate.xyToLogicalPosition(p);
- return hostToInjected(hostPos);
- }
-
- private LogicalPosition fitInsideEditor(LogicalPosition pos) {
- int lineCount = myDocumentWindow.getLineCount();
- if (pos.line >= lineCount) {
- pos = new LogicalPosition(lineCount-1, pos.column);
- }
- int lineLength = myDocumentWindow.getLineEndOffset(pos.line) - myDocumentWindow.getLineStartOffset(pos.line);
- if (pos.column >= lineLength) {
- pos = new LogicalPosition(pos.line, Math.max(0, lineLength-1));
- }
- return pos;
- }
-
- @Override
- @NotNull
- public Point logicalPositionToXY(@NotNull final LogicalPosition pos) {
- assert isValid();
- return myDelegate.logicalPositionToXY(injectedToHost(fitInsideEditor(pos)));
- }
-
- @Override
- @NotNull
- public Point visualPositionToXY(@NotNull final VisualPosition pos) {
- assert isValid();
- return logicalPositionToXY(visualToLogicalPosition(pos));
- }
-
- @Override
- public void repaint(final int startOffset, final int endOffset) {
- assert isValid();
- myDelegate.repaint(myDocumentWindow.injectedToHost(startOffset), myDocumentWindow.injectedToHost(endOffset));
- }
-
- @Override
- @NotNull
- public DocumentWindowImpl getDocument() {
- return myDocumentWindow;
- }
-
- @Override
- @NotNull
- public JComponent getComponent() {
- return myDelegate.getComponent();
- }
-
- private final ListenerWrapperMap<EditorMouseListener> myEditorMouseListeners = new ListenerWrapperMap<EditorMouseListener>();
- @Override
- public void addEditorMouseListener(@NotNull final EditorMouseListener listener) {
- assert isValid();
- EditorMouseListener wrapper = new EditorMouseListener() {
- @Override
- public void mousePressed(EditorMouseEvent e) {
- listener.mousePressed(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
-
- @Override
- public void mouseClicked(EditorMouseEvent e) {
- listener.mouseClicked(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
-
- @Override
- public void mouseReleased(EditorMouseEvent e) {
- listener.mouseReleased(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
-
- @Override
- public void mouseEntered(EditorMouseEvent e) {
- listener.mouseEntered(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
-
- @Override
- public void mouseExited(EditorMouseEvent e) {
- listener.mouseExited(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
- };
- myEditorMouseListeners.registerWrapper(listener, wrapper);
-
- myDelegate.addEditorMouseListener(wrapper);
- }
-
- @Override
- public void removeEditorMouseListener(@NotNull final EditorMouseListener listener) {
- EditorMouseListener wrapper = myEditorMouseListeners.removeWrapper(listener);
- // HintManager might have an old editor instance
- if (wrapper != null) {
- myDelegate.removeEditorMouseListener(wrapper);
- }
- }
-
- private final ListenerWrapperMap<EditorMouseMotionListener> myEditorMouseMotionListeners = new ListenerWrapperMap<EditorMouseMotionListener>();
- @Override
- public void addEditorMouseMotionListener(@NotNull final EditorMouseMotionListener listener) {
- assert isValid();
- EditorMouseMotionListener wrapper = new EditorMouseMotionListener() {
- @Override
- public void mouseMoved(EditorMouseEvent e) {
- listener.mouseMoved(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
-
- @Override
- public void mouseDragged(EditorMouseEvent e) {
- listener.mouseDragged(new EditorMouseEvent(EditorWindow.this, e.getMouseEvent(), e.getArea()));
- }
- };
- myEditorMouseMotionListeners.registerWrapper(listener, wrapper);
- myDelegate.addEditorMouseMotionListener(wrapper);
- }
-
- @Override
- public void removeEditorMouseMotionListener(@NotNull final EditorMouseMotionListener listener) {
- EditorMouseMotionListener wrapper = myEditorMouseMotionListeners.removeWrapper(listener);
- if (wrapper != null) {
- myDelegate.removeEditorMouseMotionListener(wrapper);
- }
- }
-
- @Override
- public boolean isDisposed() {
- return !myDisposed && myDelegate.isDisposed();
- }
-
- @Override
- public void setBackgroundColor(final Color color) {
- myDelegate.setBackgroundColor(color);
- }
-
- @Override
- public Color getBackgroundColor() {
- return myDelegate.getBackgroundColor();
- }
-
- @Override
- public int getMaxWidthInRange(final int startOffset, final int endOffset) {
- return myDelegate.getMaxWidthInRange(startOffset, endOffset);
- }
-
- @Override
- public int getLineHeight() {
- return myDelegate.getLineHeight();
- }
-
- @Override
- public Dimension getContentSize() {
- return myDelegate.getContentSize();
- }
-
- @NotNull
- @Override
- public JScrollPane getScrollPane() {
- return myDelegate.getScrollPane();
- }
-
- @Override
- public void setBorder(Border border) {
- myDelegate.setBorder(border);
- }
-
- @Override
- public Insets getInsets() {
- return myDelegate.getInsets();
- }
-
- @Override
- public int logicalPositionToOffset(@NotNull final LogicalPosition pos) {
- int lineStartOffset = myDocumentWindow.getLineStartOffset(pos.line);
- return calcOffset(pos.column, pos.line, lineStartOffset);
- }
- private int calcLogicalColumnNumber(int offsetInLine, int lineNumber, int lineStartOffset) {
- if (myDocumentWindow.getTextLength() == 0) return 0;
-
- if (offsetInLine==0) return 0;
- int end = myDocumentWindow.getLineEndOffset(lineNumber);
- if (offsetInLine > end- lineStartOffset) offsetInLine = end - lineStartOffset;
-
- CharSequence text = myDocumentWindow.getCharsSequence();
- return EditorUtil.calcColumnNumber(this, text, lineStartOffset, lineStartOffset +offsetInLine, EditorUtil.getTabSize(myDelegate));
- }
- private int calcOffset(int col, int lineNumber, int lineStartOffset) {
- if (myDocumentWindow.getTextLength() == 0) return 0;
-
- int end = myDocumentWindow.getLineEndOffset(lineNumber);
-
- CharSequence text = myDocumentWindow.getCharsSequence();
- return EditorUtil.calcOffset(this, text, lineStartOffset, end, col, EditorUtil.getTabSize(myDelegate), null);
- }
-
- @Override
- public void setLastColumnNumber(final int val) {
- myDelegate.setLastColumnNumber(val);
- }
-
- @Override
- public int getLastColumnNumber() {
- return myDelegate.getLastColumnNumber();
- }
-
- @NotNull
- @Override
- public VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
- assert isValid();
- return new VisualPosition(logicalPos.line, logicalPos.column);
- }
-
- // assuming there is no folding in injected documents
- @Override
- @NotNull
- public VisualPosition logicalToVisualPosition(@NotNull final LogicalPosition pos) {
- return logicalToVisualPosition(pos, false);
- }
-
- @Override
- @NotNull
- public LogicalPosition visualToLogicalPosition(@NotNull final VisualPosition pos) {
- return visualToLogicalPosition(pos, true);
- }
-
- @Override
- @NotNull
- public LogicalPosition visualToLogicalPosition(@NotNull final VisualPosition pos, boolean softWrapAware) {
- assert isValid();
- return new LogicalPosition(pos.line, pos.column);
- }
-
- @NotNull
- @Override
- public DataContext getDataContext() {
- return myDelegate.getDataContext();
- }
-
- @Override
- public EditorMouseEventArea getMouseEventArea(@NotNull final MouseEvent e) {
- return myDelegate.getMouseEventArea(e);
- }
-
- @Override
- public boolean setCaretVisible(final boolean b) {
- return myDelegate.setCaretVisible(b);
- }
-
- @Override
- public boolean setCaretEnabled(boolean enabled) {
- return myDelegate.setCaretEnabled(enabled);
- }
-
- @Override
- public void addFocusListener(@NotNull final FocusChangeListener listener) {
- myDelegate.addFocusListener(listener);
- }
-
- @Override
- public void addFocusListener(@NotNull FocusChangeListener listener, @NotNull Disposable parentDisposable) {
- myDelegate.addFocusListener(listener, parentDisposable);
- }
-
- @Override
- public Project getProject() {
- return myDelegate.getProject();
- }
-
- @Override
- public boolean isOneLineMode() {
- return myOneLine;
- }
-
- @Override
- public void setOneLineMode(final boolean isOneLineMode) {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public boolean isEmbeddedIntoDialogWrapper() {
- return myDelegate.isEmbeddedIntoDialogWrapper();
- }
-
- @Override
- public void setEmbeddedIntoDialogWrapper(final boolean b) {
- myDelegate.setEmbeddedIntoDialogWrapper(b);
- }
-
- @Override
- public VirtualFile getVirtualFile() {
- return myDelegate.getVirtualFile();
- }
-
- @Override
- public void stopOptimizedScrolling() {
- myDelegate.stopOptimizedScrolling();
- }
-
- @Override
- public CopyProvider getCopyProvider() {
- return myDelegate.getCopyProvider();
- }
-
- @Override
- public CutProvider getCutProvider() {
- return myDelegate.getCutProvider();
- }
-
- @Override
- public PasteProvider getPasteProvider() {
- return myDelegate.getPasteProvider();
- }
-
- @Override
- public DeleteProvider getDeleteProvider() {
- return myDelegate.getDeleteProvider();
- }
-
- @Override
- public void setColorsScheme(@NotNull final EditorColorsScheme scheme) {
- myDelegate.setColorsScheme(scheme);
- }
-
- @Override
- @NotNull
- public EditorColorsScheme getColorsScheme() {
- return myDelegate.getColorsScheme();
- }
-
- @Override
- public void setVerticalScrollbarOrientation(final int type) {
- myDelegate.setVerticalScrollbarOrientation(type);
- }
-
- @Override
- public int getVerticalScrollbarOrientation() {
- return myDelegate.getVerticalScrollbarOrientation();
- }
-
- @Override
- public void setVerticalScrollbarVisible(final boolean b) {
- myDelegate.setVerticalScrollbarVisible(b);
- }
-
- @Override
- public void setHorizontalScrollbarVisible(final boolean b) {
- myDelegate.setHorizontalScrollbarVisible(b);
- }
-
- @Override
- public boolean processKeyTyped(@NotNull final KeyEvent e) {
- return myDelegate.processKeyTyped(e);
- }
-
- @Override
- @NotNull
- public EditorGutter getGutter() {
- return myDelegate.getGutter();
- }
-
- public boolean equals(final Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- final EditorWindow that = (EditorWindow)o;
-
- DocumentWindow thatWindow = that.getDocument();
- return myDelegate.equals(that.myDelegate) && myDocumentWindow.equals(thatWindow);
- }
-
- public int hashCode() {
- return myDocumentWindow.hashCode();
- }
-
- public Editor getDelegate() {
- return myDelegate;
- }
-
- @Override
- public int calcColumnNumber(@NotNull final CharSequence text, final int start, final int offset, final int tabSize) {
- int hostStart = myDocumentWindow.injectedToHost(start);
- int hostOffset = myDocumentWindow.injectedToHost(offset);
- return myDelegate.calcColumnNumber(myDelegate.getDocument().getText(), hostStart, hostOffset, tabSize);
- }
-
- @Override
- public int calcColumnNumber(int offset, int lineIndex) {
- return myDelegate.calcColumnNumber(myDocumentWindow.injectedToHost(offset), myDocumentWindow.injectedToHostLine(lineIndex));
- }
-
- @NotNull
- @Override
- public IndentsModel getIndentsModel() {
- return myDelegate.getIndentsModel();
- }
-
- @Override
- public void setSoftWrapAppliancePlace(@NotNull SoftWrapAppliancePlaces place) {
- myDelegate.setSoftWrapAppliancePlace(place);
- }
-
- @Override
- public void setPlaceholder(@Nullable CharSequence text) {
- myDelegate.setPlaceholder(text);
- }
-
- @Override
- public boolean isStickySelection() {
- return myDelegate.isStickySelection();
- }
-
- @Override
- public void setStickySelection(boolean enable) {
- myDelegate.setStickySelection(enable);
- }
-
- @Override
- public boolean isPurePaintingMode() {
- return myDelegate.isPurePaintingMode();
- }
-
- @Override
- public void setPurePaintingMode(boolean enabled) {
- myDelegate.setPurePaintingMode(enabled);
- }
-
- @Override
- public void registerScrollBarRepaintCallback(@Nullable RepaintCallback callback) {
- myDelegate.registerScrollBarRepaintCallback(callback);
- }
-
- @Override
- public void setPrefixTextAndAttributes(@Nullable String prefixText, @Nullable TextAttributes attributes) {
- myDelegate.setPrefixTextAndAttributes(prefixText, attributes);
- }
-
- @Override
- public int getPrefixTextWidthInPixels() {
- return myDelegate.getPrefixTextWidthInPixels();
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java
new file mode 100644
index 0000000..8cb5571
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/injected/editor/EditorWindowImpl.java
@@ -0,0 +1,837 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.injected.editor;
+
+import com.intellij.ide.CopyProvider;
+import com.intellij.ide.CutProvider;
+import com.intellij.ide.DeleteProvider;
+import com.intellij.ide.PasteProvider;
+import com.intellij.ide.highlighter.HighlighterFactory;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.*;
+import com.intellij.openapi.editor.colors.EditorColorsManager;
+import com.intellij.openapi.editor.colors.EditorColorsScheme;
+import com.intellij.openapi.editor.event.EditorMouseEvent;
+import com.intellij.openapi.editor.event.EditorMouseEventArea;
+import com.intellij.openapi.editor.event.EditorMouseListener;
+import com.intellij.openapi.editor.event.EditorMouseMotionListener;
+import com.intellij.openapi.editor.ex.*;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.editor.highlighter.EditorHighlighter;
+import com.intellij.openapi.editor.highlighter.LightHighlighterClient;
+import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
+import com.intellij.openapi.editor.impl.TextDrawingCallback;
+import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
+import com.intellij.openapi.editor.markup.MarkupModel;
+import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.util.containers.WeakList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.Border;
+import java.awt.*;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseEvent;
+import java.beans.PropertyChangeListener;
+import java.util.*;
+import java.util.List;
+
+/**
+ * @author Alexey
+ */
+public class EditorWindowImpl extends UserDataHolderBase implements EditorWindow, EditorEx {
+ private final DocumentWindowImpl myDocumentWindow;
+ private final EditorImpl myDelegate;
+ private volatile PsiFile myInjectedFile;
+ private final boolean myOneLine;
+ private final CaretModelWindow myCaretModelDelegate;
+ private final SelectionModelWindow mySelectionModelDelegate;
+ private static final List<EditorWindowImpl> allEditors = new WeakList<EditorWindowImpl>();
+ private boolean myDisposed;
+ private final MarkupModelWindow myMarkupModelDelegate;
+ private final FoldingModelWindow myFoldingModelWindow;
+ private final SoftWrapModelImpl mySoftWrapModel;
+
+ public static Editor create(@NotNull final DocumentWindowImpl documentRange, @NotNull final EditorImpl editor, @NotNull final PsiFile injectedFile) {
+ assert documentRange.isValid();
+ assert injectedFile.isValid();
+ EditorWindowImpl window;
+ synchronized (allEditors) {
+ for (EditorWindowImpl editorWindow : allEditors) {
+ if (editorWindow.getDocument() == documentRange && editorWindow.getDelegate() == editor) {
+ editorWindow.myInjectedFile = injectedFile;
+ if (editorWindow.isValid()) {
+ return editorWindow;
+ }
+ }
+ if (editorWindow.getDocument().areRangesEqual(documentRange)) {
+ //int i = 0;
+ }
+ }
+ window = new EditorWindowImpl(documentRange, editor, injectedFile, documentRange.isOneLine());
+ allEditors.add(window);
+ }
+ assert window.isValid();
+ return window;
+ }
+
+ private EditorWindowImpl(@NotNull DocumentWindowImpl documentWindow,
+ @NotNull final EditorImpl delegate,
+ @NotNull PsiFile injectedFile,
+ boolean oneLine) {
+ myDocumentWindow = documentWindow;
+ myDelegate = delegate;
+ myInjectedFile = injectedFile;
+ myOneLine = oneLine;
+ myCaretModelDelegate = new CaretModelWindow(myDelegate.getCaretModel(), this);
+ mySelectionModelDelegate = new SelectionModelWindow(myDelegate, myDocumentWindow,this);
+ myMarkupModelDelegate = new MarkupModelWindow((MarkupModelEx)myDelegate.getMarkupModel(), myDocumentWindow);
+ myFoldingModelWindow = new FoldingModelWindow(delegate.getFoldingModel(), documentWindow, this);
+ mySoftWrapModel = new SoftWrapModelImpl(this);
+ Disposer.register(myDocumentWindow, mySoftWrapModel);
+ }
+
+ public static void disposeInvalidEditors() {
+ ApplicationManager.getApplication().assertWriteAccessAllowed();
+ Iterator<EditorWindowImpl> iterator = allEditors.iterator();
+ while (iterator.hasNext()) {
+ EditorWindowImpl editorWindow = iterator.next();
+ if (!editorWindow.isValid()) {
+ editorWindow.dispose();
+
+ InjectedLanguageUtil.clearCaches(editorWindow.myInjectedFile, editorWindow.getDocument());
+ iterator.remove();
+ }
+ }
+ }
+
+ @Override
+ public boolean isValid() {
+ return !isDisposed() && !myInjectedFile.getProject().isDisposed() && myInjectedFile.isValid() && myDocumentWindow.isValid();
+ }
+
+ @Override
+ @NotNull
+ public PsiFile getInjectedFile() {
+ return myInjectedFile;
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition hostToInjected(@NotNull LogicalPosition hPos) {
+ assert isValid();
+ DocumentEx hostDocument = myDelegate.getDocument();
+ int hLineEndOffset = hPos.line >= hostDocument.getLineCount() ? hostDocument.getTextLength() : hostDocument.getLineEndOffset(hPos.line);
+ LogicalPosition hLineEndPos = myDelegate.offsetToLogicalPosition(hLineEndOffset);
+ if (hLineEndPos.column < hPos.column) {
+ // in virtual space
+ LogicalPosition iPos = myDocumentWindow.hostToInjectedInVirtualSpace(hPos);
+ if (iPos != null) {
+ return iPos;
+ }
+ }
+
+ int hOffset = myDelegate.logicalPositionToOffset(hPos);
+ int iOffset = myDocumentWindow.hostToInjected(hOffset);
+ return offsetToLogicalPosition(iOffset);
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition injectedToHost(@NotNull LogicalPosition pos) {
+ assert isValid();
+ // beware the virtual space
+ int column = pos.column;
+ int lineStartOffset = myDocumentWindow.getLineStartOffset(pos.line);
+ int lineEndOffset = myDocumentWindow.getLineEndOffset(pos.line);
+ if (column > lineEndOffset - lineStartOffset) {
+ // in virtual space, calculate the host pos as an offset from the line end
+ int delta = column - (lineEndOffset - lineStartOffset);
+
+ int baseOffsetInHost = myDocumentWindow.injectedToHost(lineEndOffset);
+ LogicalPosition lineStartPosInHost = myDelegate.offsetToLogicalPosition(baseOffsetInHost);
+ return new LogicalPosition(lineStartPosInHost.line, lineStartPosInHost.column + delta);
+ }
+ else {
+ int offset = lineStartOffset + column;
+ int hostOffset = getDocument().injectedToHost(offset);
+ return myDelegate.offsetToLogicalPosition(hostOffset);
+ }
+ }
+
+ private void dispose() {
+ assert !myDisposed;
+ myCaretModelDelegate.disposeModel();
+
+ for (EditorMouseListener wrapper : myEditorMouseListeners.wrappers()) {
+ myDelegate.removeEditorMouseListener(wrapper);
+ }
+ myEditorMouseListeners.clear();
+ for (EditorMouseMotionListener wrapper : myEditorMouseMotionListeners.wrappers()) {
+ myDelegate.removeEditorMouseMotionListener(wrapper);
+ }
+ myEditorMouseMotionListeners.clear();
+
+ myDisposed = true;
+ Disposer.dispose(myDocumentWindow);
+ }
+
+ @Override
+ public boolean isViewer() {
+ return myDelegate.isViewer();
+ }
+
+ @Override
+ public boolean isRendererMode() {
+ return myDelegate.isRendererMode();
+ }
+
+ @Override
+ public void setRendererMode(final boolean isRendererMode) {
+ myDelegate.setRendererMode(isRendererMode);
+ }
+
+ @Override
+ public void setFile(final VirtualFile vFile) {
+ myDelegate.setFile(vFile);
+ }
+
+ @Override
+ public void setHeaderComponent(@Nullable JComponent header) {
+
+ }
+
+ @Override
+ public boolean hasHeaderComponent() {
+ return false;
+ }
+
+ @Override
+ @Nullable
+ public JComponent getHeaderComponent() {
+ return null;
+ }
+
+ @Override
+ public TextDrawingCallback getTextDrawingCallback() {
+ return myDelegate.getTextDrawingCallback();
+ }
+
+ @Override
+ @NotNull
+ public SelectionModel getSelectionModel() {
+ return mySelectionModelDelegate;
+ }
+
+ @Override
+ @NotNull
+ public MarkupModel getMarkupModel() {
+ return myMarkupModelDelegate;
+ }
+
+ @Override
+ @NotNull
+ public FoldingModelEx getFoldingModel() {
+ return myFoldingModelWindow;
+ }
+
+ @Override
+ @NotNull
+ public CaretModel getCaretModel() {
+ return myCaretModelDelegate;
+ }
+
+ @Override
+ @NotNull
+ public ScrollingModelEx getScrollingModel() {
+ return myDelegate.getScrollingModel();
+ }
+
+ @Override
+ @NotNull
+ public SoftWrapModelEx getSoftWrapModel() {
+ return mySoftWrapModel;
+ }
+
+ @Override
+ @NotNull
+ public EditorSettings getSettings() {
+ return myDelegate.getSettings();
+ }
+
+ @Override
+ public void reinitSettings() {
+ myDelegate.reinitSettings();
+ }
+
+ @Override
+ public void setFontSize(final int fontSize) {
+ myDelegate.setFontSize(fontSize);
+ }
+
+ @Override
+ public void setHighlighter(@NotNull final EditorHighlighter highlighter) {
+ myDelegate.setHighlighter(highlighter);
+ }
+
+ @NotNull
+ @Override
+ public EditorHighlighter getHighlighter() {
+ EditorColorsScheme scheme = EditorColorsManager.getInstance().getGlobalScheme();
+ EditorHighlighter highlighter = HighlighterFactory.createHighlighter(myInjectedFile.getVirtualFile(), scheme, getProject());
+ highlighter.setText(getDocument().getText());
+ highlighter.setEditor(new LightHighlighterClient(getDocument(), getProject()));
+ return highlighter;
+ }
+
+ @Override
+ public JComponent getPermanentHeaderComponent() {
+ return myDelegate.getPermanentHeaderComponent();
+ }
+
+ @Override
+ public void setPermanentHeaderComponent(JComponent component) {
+ myDelegate.setPermanentHeaderComponent(component);
+ }
+
+ @Override
+ @NotNull
+ public JComponent getContentComponent() {
+ return myDelegate.getContentComponent();
+ }
+
+ @NotNull
+ @Override
+ public EditorGutterComponentEx getGutterComponentEx() {
+ return myDelegate.getGutterComponentEx();
+ }
+
+ @Override
+ public void addPropertyChangeListener(@NotNull final PropertyChangeListener listener) {
+ myDelegate.addPropertyChangeListener(listener);
+ }
+
+ @Override
+ public void removePropertyChangeListener(@NotNull final PropertyChangeListener listener) {
+ myDelegate.removePropertyChangeListener(listener);
+ }
+
+ @Override
+ public void setInsertMode(final boolean mode) {
+ myDelegate.setInsertMode(mode);
+ }
+
+ @Override
+ public boolean isInsertMode() {
+ return myDelegate.isInsertMode();
+ }
+
+ @Override
+ public void setColumnMode(final boolean mode) {
+ myDelegate.setColumnMode(mode);
+ }
+
+ @Override
+ public boolean isColumnMode() {
+ return myDelegate.isColumnMode();
+ }
+
+ @Override
+ @NotNull
+ public VisualPosition xyToVisualPosition(@NotNull final Point p) {
+ return logicalToVisualPosition(xyToLogicalPosition(p));
+ }
+
+ @Override
+ @NotNull
+ public VisualPosition offsetToVisualPosition(final int offset) {
+ return logicalToVisualPosition(offsetToLogicalPosition(offset));
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition offsetToLogicalPosition(final int offset) {
+ return offsetToLogicalPosition(offset, true);
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition offsetToLogicalPosition(final int offset, boolean softWrapAware) {
+ assert isValid();
+ int lineNumber = myDocumentWindow.getLineNumber(offset);
+ int lineStartOffset = myDocumentWindow.getLineStartOffset(lineNumber);
+ int column = calcLogicalColumnNumber(offset-lineStartOffset, lineNumber, lineStartOffset);
+ return new LogicalPosition(lineNumber, column);
+ }
+
+ @NotNull
+ @Override
+ public EditorColorsScheme createBoundColorSchemeDelegate(@Nullable EditorColorsScheme customGlobalScheme) {
+ return myDelegate.createBoundColorSchemeDelegate(customGlobalScheme);
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition xyToLogicalPosition(@NotNull final Point p) {
+ assert isValid();
+ LogicalPosition hostPos = myDelegate.xyToLogicalPosition(p);
+ return hostToInjected(hostPos);
+ }
+
+ private LogicalPosition fitInsideEditor(LogicalPosition pos) {
+ int lineCount = myDocumentWindow.getLineCount();
+ if (pos.line >= lineCount) {
+ pos = new LogicalPosition(lineCount-1, pos.column);
+ }
+ int lineLength = myDocumentWindow.getLineEndOffset(pos.line) - myDocumentWindow.getLineStartOffset(pos.line);
+ if (pos.column >= lineLength) {
+ pos = new LogicalPosition(pos.line, Math.max(0, lineLength-1));
+ }
+ return pos;
+ }
+
+ @Override
+ @NotNull
+ public Point logicalPositionToXY(@NotNull final LogicalPosition pos) {
+ assert isValid();
+ return myDelegate.logicalPositionToXY(injectedToHost(fitInsideEditor(pos)));
+ }
+
+ @Override
+ @NotNull
+ public Point visualPositionToXY(@NotNull final VisualPosition pos) {
+ assert isValid();
+ return logicalPositionToXY(visualToLogicalPosition(pos));
+ }
+
+ @Override
+ public void repaint(final int startOffset, final int endOffset) {
+ assert isValid();
+ myDelegate.repaint(myDocumentWindow.injectedToHost(startOffset), myDocumentWindow.injectedToHost(endOffset));
+ }
+
+ @Override
+ @NotNull
+ public DocumentWindowImpl getDocument() {
+ return myDocumentWindow;
+ }
+
+ @Override
+ @NotNull
+ public JComponent getComponent() {
+ return myDelegate.getComponent();
+ }
+
+ private final ListenerWrapperMap<EditorMouseListener> myEditorMouseListeners = new ListenerWrapperMap<EditorMouseListener>();
+ @Override
+ public void addEditorMouseListener(@NotNull final EditorMouseListener listener) {
+ assert isValid();
+ EditorMouseListener wrapper = new EditorMouseListener() {
+ @Override
+ public void mousePressed(EditorMouseEvent e) {
+ listener.mousePressed(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+
+ @Override
+ public void mouseClicked(EditorMouseEvent e) {
+ listener.mouseClicked(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+
+ @Override
+ public void mouseReleased(EditorMouseEvent e) {
+ listener.mouseReleased(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+
+ @Override
+ public void mouseEntered(EditorMouseEvent e) {
+ listener.mouseEntered(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+
+ @Override
+ public void mouseExited(EditorMouseEvent e) {
+ listener.mouseExited(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+ };
+ myEditorMouseListeners.registerWrapper(listener, wrapper);
+
+ myDelegate.addEditorMouseListener(wrapper);
+ }
+
+ @Override
+ public void removeEditorMouseListener(@NotNull final EditorMouseListener listener) {
+ EditorMouseListener wrapper = myEditorMouseListeners.removeWrapper(listener);
+ // HintManager might have an old editor instance
+ if (wrapper != null) {
+ myDelegate.removeEditorMouseListener(wrapper);
+ }
+ }
+
+ private final ListenerWrapperMap<EditorMouseMotionListener> myEditorMouseMotionListeners = new ListenerWrapperMap<EditorMouseMotionListener>();
+ @Override
+ public void addEditorMouseMotionListener(@NotNull final EditorMouseMotionListener listener) {
+ assert isValid();
+ EditorMouseMotionListener wrapper = new EditorMouseMotionListener() {
+ @Override
+ public void mouseMoved(EditorMouseEvent e) {
+ listener.mouseMoved(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+
+ @Override
+ public void mouseDragged(EditorMouseEvent e) {
+ listener.mouseDragged(new EditorMouseEvent(EditorWindowImpl.this, e.getMouseEvent(), e.getArea()));
+ }
+ };
+ myEditorMouseMotionListeners.registerWrapper(listener, wrapper);
+ myDelegate.addEditorMouseMotionListener(wrapper);
+ }
+
+ @Override
+ public void removeEditorMouseMotionListener(@NotNull final EditorMouseMotionListener listener) {
+ EditorMouseMotionListener wrapper = myEditorMouseMotionListeners.removeWrapper(listener);
+ if (wrapper != null) {
+ myDelegate.removeEditorMouseMotionListener(wrapper);
+ }
+ }
+
+ @Override
+ public boolean isDisposed() {
+ return myDisposed || myDelegate.isDisposed();
+ }
+
+ @Override
+ public void setBackgroundColor(final Color color) {
+ myDelegate.setBackgroundColor(color);
+ }
+
+ @Override
+ public Color getBackgroundColor() {
+ return myDelegate.getBackgroundColor();
+ }
+
+ @Override
+ public int getMaxWidthInRange(final int startOffset, final int endOffset) {
+ return myDelegate.getMaxWidthInRange(startOffset, endOffset);
+ }
+
+ @Override
+ public int getLineHeight() {
+ return myDelegate.getLineHeight();
+ }
+
+ @Override
+ public Dimension getContentSize() {
+ return myDelegate.getContentSize();
+ }
+
+ @NotNull
+ @Override
+ public JScrollPane getScrollPane() {
+ return myDelegate.getScrollPane();
+ }
+
+ @Override
+ public void setBorder(Border border) {
+ myDelegate.setBorder(border);
+ }
+
+ @Override
+ public Insets getInsets() {
+ return myDelegate.getInsets();
+ }
+
+ @Override
+ public int logicalPositionToOffset(@NotNull final LogicalPosition pos) {
+ int lineStartOffset = myDocumentWindow.getLineStartOffset(pos.line);
+ return calcOffset(pos.column, pos.line, lineStartOffset);
+ }
+ private int calcLogicalColumnNumber(int offsetInLine, int lineNumber, int lineStartOffset) {
+ if (myDocumentWindow.getTextLength() == 0) return 0;
+
+ if (offsetInLine==0) return 0;
+ int end = myDocumentWindow.getLineEndOffset(lineNumber);
+ if (offsetInLine > end- lineStartOffset) offsetInLine = end - lineStartOffset;
+
+ CharSequence text = myDocumentWindow.getCharsSequence();
+ return EditorUtil.calcColumnNumber(this, text, lineStartOffset, lineStartOffset +offsetInLine, EditorUtil.getTabSize(myDelegate));
+ }
+ private int calcOffset(int col, int lineNumber, int lineStartOffset) {
+ if (myDocumentWindow.getTextLength() == 0) return 0;
+
+ int end = myDocumentWindow.getLineEndOffset(lineNumber);
+
+ CharSequence text = myDocumentWindow.getCharsSequence();
+ return EditorUtil.calcOffset(this, text, lineStartOffset, end, col, EditorUtil.getTabSize(myDelegate), null);
+ }
+
+ @Override
+ public void setLastColumnNumber(final int val) {
+ myDelegate.setLastColumnNumber(val);
+ }
+
+ @Override
+ public int getLastColumnNumber() {
+ return myDelegate.getLastColumnNumber();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition logicalToVisualPosition(@NotNull LogicalPosition logicalPos, boolean softWrapAware) {
+ assert isValid();
+ return new VisualPosition(logicalPos.line, logicalPos.column);
+ }
+
+ // assuming there is no folding in injected documents
+ @Override
+ @NotNull
+ public VisualPosition logicalToVisualPosition(@NotNull final LogicalPosition pos) {
+ return logicalToVisualPosition(pos, false);
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition visualToLogicalPosition(@NotNull final VisualPosition pos) {
+ return visualToLogicalPosition(pos, true);
+ }
+
+ @Override
+ @NotNull
+ public LogicalPosition visualToLogicalPosition(@NotNull final VisualPosition pos, boolean softWrapAware) {
+ assert isValid();
+ return new LogicalPosition(pos.line, pos.column);
+ }
+
+ @NotNull
+ @Override
+ public DataContext getDataContext() {
+ return myDelegate.getDataContext();
+ }
+
+ @Override
+ public EditorMouseEventArea getMouseEventArea(@NotNull final MouseEvent e) {
+ return myDelegate.getMouseEventArea(e);
+ }
+
+ @Override
+ public boolean setCaretVisible(final boolean b) {
+ return myDelegate.setCaretVisible(b);
+ }
+
+ @Override
+ public boolean setCaretEnabled(boolean enabled) {
+ return myDelegate.setCaretEnabled(enabled);
+ }
+
+ @Override
+ public void addFocusListener(@NotNull final FocusChangeListener listener) {
+ myDelegate.addFocusListener(listener);
+ }
+
+ @Override
+ public void addFocusListener(@NotNull FocusChangeListener listener, @NotNull Disposable parentDisposable) {
+ myDelegate.addFocusListener(listener, parentDisposable);
+ }
+
+ @Override
+ public Project getProject() {
+ return myDelegate.getProject();
+ }
+
+ @Override
+ public boolean isOneLineMode() {
+ return myOneLine;
+ }
+
+ @Override
+ public void setOneLineMode(final boolean isOneLineMode) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isEmbeddedIntoDialogWrapper() {
+ return myDelegate.isEmbeddedIntoDialogWrapper();
+ }
+
+ @Override
+ public void setEmbeddedIntoDialogWrapper(final boolean b) {
+ myDelegate.setEmbeddedIntoDialogWrapper(b);
+ }
+
+ @Override
+ public VirtualFile getVirtualFile() {
+ return myDelegate.getVirtualFile();
+ }
+
+ @Override
+ public void stopOptimizedScrolling() {
+ myDelegate.stopOptimizedScrolling();
+ }
+
+ @Override
+ public CopyProvider getCopyProvider() {
+ return myDelegate.getCopyProvider();
+ }
+
+ @Override
+ public CutProvider getCutProvider() {
+ return myDelegate.getCutProvider();
+ }
+
+ @Override
+ public PasteProvider getPasteProvider() {
+ return myDelegate.getPasteProvider();
+ }
+
+ @Override
+ public DeleteProvider getDeleteProvider() {
+ return myDelegate.getDeleteProvider();
+ }
+
+ @Override
+ public void setColorsScheme(@NotNull final EditorColorsScheme scheme) {
+ myDelegate.setColorsScheme(scheme);
+ }
+
+ @Override
+ @NotNull
+ public EditorColorsScheme getColorsScheme() {
+ return myDelegate.getColorsScheme();
+ }
+
+ @Override
+ public void setVerticalScrollbarOrientation(final int type) {
+ myDelegate.setVerticalScrollbarOrientation(type);
+ }
+
+ @Override
+ public int getVerticalScrollbarOrientation() {
+ return myDelegate.getVerticalScrollbarOrientation();
+ }
+
+ @Override
+ public void setVerticalScrollbarVisible(final boolean b) {
+ myDelegate.setVerticalScrollbarVisible(b);
+ }
+
+ @Override
+ public void setHorizontalScrollbarVisible(final boolean b) {
+ myDelegate.setHorizontalScrollbarVisible(b);
+ }
+
+ @Override
+ public boolean processKeyTyped(@NotNull final KeyEvent e) {
+ return myDelegate.processKeyTyped(e);
+ }
+
+ @Override
+ @NotNull
+ public EditorGutter getGutter() {
+ return myDelegate.getGutter();
+ }
+
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final EditorWindowImpl that = (EditorWindowImpl)o;
+
+ DocumentWindow thatWindow = that.getDocument();
+ return myDelegate.equals(that.myDelegate) && myDocumentWindow.equals(thatWindow);
+ }
+
+ public int hashCode() {
+ return myDocumentWindow.hashCode();
+ }
+
+ @NotNull
+ @Override
+ public Editor getDelegate() {
+ return myDelegate;
+ }
+
+ @Override
+ public int calcColumnNumber(@NotNull final CharSequence text, final int start, final int offset, final int tabSize) {
+ int hostStart = myDocumentWindow.injectedToHost(start);
+ int hostOffset = myDocumentWindow.injectedToHost(offset);
+ return myDelegate.calcColumnNumber(myDelegate.getDocument().getText(), hostStart, hostOffset, tabSize);
+ }
+
+ @Override
+ public int calcColumnNumber(int offset, int lineIndex) {
+ return myDelegate.calcColumnNumber(myDocumentWindow.injectedToHost(offset), myDocumentWindow.injectedToHostLine(lineIndex));
+ }
+
+ @NotNull
+ @Override
+ public IndentsModel getIndentsModel() {
+ return myDelegate.getIndentsModel();
+ }
+
+ @Override
+ public void setSoftWrapAppliancePlace(@NotNull SoftWrapAppliancePlaces place) {
+ myDelegate.setSoftWrapAppliancePlace(place);
+ }
+
+ @Override
+ public void setPlaceholder(@Nullable CharSequence text) {
+ myDelegate.setPlaceholder(text);
+ }
+
+ @Override
+ public boolean isStickySelection() {
+ return myDelegate.isStickySelection();
+ }
+
+ @Override
+ public void setStickySelection(boolean enable) {
+ myDelegate.setStickySelection(enable);
+ }
+
+ @Override
+ public boolean isPurePaintingMode() {
+ return myDelegate.isPurePaintingMode();
+ }
+
+ @Override
+ public void setPurePaintingMode(boolean enabled) {
+ myDelegate.setPurePaintingMode(enabled);
+ }
+
+ @Override
+ public void registerScrollBarRepaintCallback(@Nullable RepaintCallback callback) {
+ myDelegate.registerScrollBarRepaintCallback(callback);
+ }
+
+ @Override
+ public void setPrefixTextAndAttributes(@Nullable String prefixText, @Nullable TextAttributes attributes) {
+ myDelegate.setPrefixTextAndAttributes(prefixText, attributes);
+ }
+
+ @Override
+ public int getPrefixTextWidthInPixels() {
+ return myDelegate.getPrefixTextWidthInPixels();
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java
index f5476fa..d87aa78 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/FoldingModelWindow.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 com.intellij.injected.editor;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingGroup;
import com.intellij.openapi.editor.ex.FoldingListener;
@@ -163,17 +164,17 @@
}
@Override
- public boolean addListener(@NotNull FoldingListener listener) {
- return myDelegate.addListener(listener);
- }
-
- @Override
- public boolean removeListener(@NotNull FoldingListener listener) {
- return myDelegate.removeListener(listener);
+ public void addListener(@NotNull FoldingListener listener, @NotNull Disposable parentDisposable) {
+ myDelegate.addListener(listener, parentDisposable);
}
@Override
public void rebuild() {
myDelegate.rebuild();
}
+
+ @Override
+ public void clearFoldRegions() {
+ myDelegate.clearFoldRegions();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java b/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java
new file mode 100644
index 0000000..19651a7
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/injected/editor/InjectedCaret.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.injected.editor;
+
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.VisualPosition;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.ProperTextRange;
+import com.intellij.openapi.util.TextRange;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+class InjectedCaret implements Caret {
+ private final EditorWindow myEditorWindow;
+ final Caret myDelegate;
+
+ InjectedCaret(EditorWindow window, Caret delegate) {
+ myEditorWindow = window;
+ myDelegate = delegate;
+ }
+
+ @NotNull
+ @Override
+ public CaretModel getCaretModel() {
+ return myEditorWindow.getCaretModel();
+ }
+
+ @Override
+ public boolean isValid() {
+ return myDelegate.isValid();
+ }
+
+ @Override
+ public void moveCaretRelatively(int columnShift, int lineShift, boolean withSelection, boolean scrollToCaret) {
+ myDelegate.moveCaretRelatively(columnShift, lineShift, withSelection, scrollToCaret);
+ }
+
+ @Override
+ public void moveToLogicalPosition(@NotNull LogicalPosition pos) {
+ LogicalPosition hostPos = myEditorWindow.injectedToHost(pos);
+ myDelegate.moveToLogicalPosition(hostPos);
+ }
+
+ @Override
+ public void moveToVisualPosition(@NotNull VisualPosition pos) {
+ LogicalPosition hostPos = myEditorWindow.injectedToHost(myEditorWindow.visualToLogicalPosition(pos));
+ myDelegate.moveToLogicalPosition(hostPos);
+ }
+
+ @Override
+ public void moveToOffset(int offset) {
+ moveToOffset(offset, false);
+ }
+
+ @Override
+ public void moveToOffset(int offset, boolean locateBeforeSoftWrap) {
+ int hostOffset = myEditorWindow.getDocument().injectedToHost(offset);
+ myDelegate.moveToOffset(hostOffset, locateBeforeSoftWrap);
+ }
+
+ @Override
+ public boolean isUpToDate() {
+ return myDelegate.isUpToDate();
+ }
+
+ @NotNull
+ @Override
+ public LogicalPosition getLogicalPosition() {
+ LogicalPosition hostPos = myDelegate.getLogicalPosition();
+ return myEditorWindow.hostToInjected(hostPos);
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getVisualPosition() {
+ LogicalPosition logicalPosition = getLogicalPosition();
+ return myEditorWindow.logicalToVisualPosition(logicalPosition);
+ }
+
+ @Override
+ public int getOffset() {
+ return myEditorWindow.getDocument().hostToInjected(myDelegate.getOffset());
+ }
+
+ @Override
+ public int getVisualLineStart() {
+ return myEditorWindow.getDocument().hostToInjected(myDelegate.getVisualLineStart());
+ }
+
+ @Override
+ public int getVisualLineEnd() {
+ return myEditorWindow.getDocument().hostToInjected(myDelegate.getVisualLineEnd());
+ }
+
+ @Override
+ public int getSelectionStart() {
+ return myEditorWindow.getDocument().hostToInjected(myDelegate.getSelectionStart());
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getSelectionStartPosition() {
+ return myDelegate.getSelectionStartPosition();
+ }
+
+ @Override
+ public int getSelectionEnd() {
+ return myEditorWindow.getDocument().hostToInjected(myDelegate.getSelectionEnd());
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getSelectionEndPosition() {
+ return myDelegate.getSelectionEndPosition();
+ }
+
+ @Nullable
+ @Override
+ public String getSelectedText() {
+ return myDelegate.getSelectedText();
+ }
+
+ @Override
+ public int getLeadSelectionOffset() {
+ return myEditorWindow.getDocument().hostToInjected(myDelegate.getLeadSelectionOffset());
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getLeadSelectionPosition() {
+ return myDelegate.getLeadSelectionPosition();
+ }
+
+ @Override
+ public boolean hasSelection() {
+ return myDelegate.hasSelection();
+ }
+
+ @Override
+ public void setSelection(int startOffset, int endOffset) {
+ TextRange hostRange = myEditorWindow.getDocument().injectedToHost(new ProperTextRange(startOffset, endOffset));
+ myDelegate.setSelection(hostRange.getStartOffset(), hostRange.getEndOffset());
+ }
+
+ @Override
+ public void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ TextRange hostRange = myEditorWindow.getDocument().injectedToHost(new ProperTextRange(startOffset, endOffset));
+ myDelegate.setSelection(hostRange.getStartOffset(), endPosition, hostRange.getEndOffset());
+ }
+
+ @Override
+ public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ TextRange hostRange = myEditorWindow.getDocument().injectedToHost(new ProperTextRange(startOffset, endOffset));
+ myDelegate.setSelection(startPosition, hostRange.getStartOffset(), endPosition, hostRange.getEndOffset());
+ }
+
+ @Override
+ public void removeSelection() {
+ myDelegate.removeSelection();
+ }
+
+ @Override
+ public void selectLineAtCaret() {
+ myDelegate.selectLineAtCaret();
+ }
+
+ @Override
+ public void selectWordAtCaret(boolean honorCamelWordsSettings) {
+ myDelegate.selectWordAtCaret(honorCamelWordsSettings);
+ }
+
+ @Nullable
+ @Override
+ public Caret clone(boolean above) {
+ Caret clone = myDelegate.clone(above);
+ return clone == null ? null : new InjectedCaret(myEditorWindow, clone);
+ }
+
+ @Override
+ public void dispose() {
+ //noinspection SSBasedInspection
+ myDelegate.dispose();
+ }
+
+ @NotNull
+ @Override
+ public <T> T putUserDataIfAbsent(@NotNull Key<T> key, @NotNull T value) {
+ return myDelegate.putUserDataIfAbsent(key, value);
+ }
+
+ @Override
+ public <T> boolean replace(@NotNull Key<T> key, @Nullable T oldValue, @Nullable T newValue) {
+ return myDelegate.replace(key, oldValue, newValue);
+ }
+
+ @Nullable
+ @Override
+ public <T> T getUserData(@NotNull Key<T> key) {
+ return myDelegate.getUserData(key);
+ }
+
+ @Override
+ public <T> void putUserData(@NotNull Key<T> key, @Nullable T value) {
+ myDelegate.putUserData(key, value);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java b/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java
index 872d775..37d9dd7 100644
--- a/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.java
+++ b/platform/lang-impl/src/com/intellij/injected/editor/SelectionModelWindow.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.
@@ -69,6 +69,12 @@
return myHostModel.getSelectedText();
}
+ @Nullable
+ @Override
+ public String getSelectedText(boolean allCarets) {
+ return myHostModel.getSelectedText(allCarets);
+ }
+
@Override
public int getLeadSelectionOffset() {
return myDocument.hostToInjected(myHostModel.getLeadSelectionOffset());
@@ -86,6 +92,11 @@
}
@Override
+ public boolean hasSelection(boolean anyCaret) {
+ return myHostModel.hasSelection(anyCaret);
+ }
+
+ @Override
public void setSelection(final int startOffset, final int endOffset) {
TextRange hostRange = myDocument.injectedToHost(new ProperTextRange(startOffset, endOffset));
myHostModel.setSelection(hostRange.getStartOffset(), hostRange.getEndOffset());
@@ -109,6 +120,11 @@
}
@Override
+ public void removeSelection(boolean allCarets) {
+ myHostModel.removeSelection(allCarets);
+ }
+
+ @Override
public void addSelectionListener(final SelectionListener listener) {
myHostModel.addSelectionListener(listener);
}
@@ -134,7 +150,7 @@
}
@Override
- public void setBlockSelection(final LogicalPosition blockStart, final LogicalPosition blockEnd) {
+ public void setBlockSelection(@NotNull final LogicalPosition blockStart, @NotNull final LogicalPosition blockEnd) {
myHostModel.setBlockSelection(myInjectedEditor.injectedToHost(blockStart), myInjectedEditor.injectedToHost(blockEnd));
}
diff --git a/platform/lang-impl/src/com/intellij/internal/ShowNonRetinaImagesActions.java b/platform/lang-impl/src/com/intellij/internal/ShowNonRetinaImagesActions.java
new file mode 100644
index 0000000..5c5c742
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/internal/ShowNonRetinaImagesActions.java
@@ -0,0 +1,105 @@
+/*
+ * 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.internal;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.FilenameIndex;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.ui.components.JBScrollPane;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+@SuppressWarnings("UndesirableClassUsage")
+public class ShowNonRetinaImagesActions extends DumbAwareAction {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ final Project project = e.getProject();
+ if (project == null) return;
+ class ImageInfo {
+ boolean retina;
+ boolean normal;
+ boolean dark;
+ boolean retina_dark;
+
+ }
+ HashMap<String, ImageInfo> info = new HashMap<String, ImageInfo>();
+ final Collection<VirtualFile> images = FilenameIndex.getAllFilesByExt(project, "png", GlobalSearchScope.projectScope(project));
+ for (VirtualFile image : images) {
+ final String path = image.getPath();
+ final String key = toKey(path);
+ ImageInfo imageInfo = info.get(key);
+ if (imageInfo == null) {
+ imageInfo = new ImageInfo();
+ info.put(key, imageInfo);
+ }
+ if (path.endsWith("@2x_dark.png")) {
+ imageInfo.retina_dark = true;
+ } else if (path.endsWith("_dark.png")) {
+ imageInfo.dark = true;
+ } else if (path.endsWith("@2x.png")) {
+ imageInfo.retina = true;
+ } else {
+ imageInfo.normal = true;
+ }
+ }
+
+ final ArrayList<String> retinaMissed = new ArrayList<String>();
+ for (String key : info.keySet()) {
+ if (!info.get(key).retina && info.get(key).normal) {
+ retinaMissed.add(key);
+ }
+ }
+ Collections.sort(retinaMissed, String.CASE_INSENSITIVE_ORDER);
+
+ new DialogWrapper(project) {
+ {
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return new JBScrollPane(new JTextArea(StringUtil.join(retinaMissed, "\n")));
+ }
+ }.show();
+ }
+
+ private static String toKey(String path) {
+ if (path.endsWith("@2x_dark.png")) {
+ return path.substring(0, path.lastIndexOf("@2x_dark.png")) + ".png";
+ }
+ if (path.endsWith("_dark.png")) {
+ return path.substring(0, path.lastIndexOf("_dark.png")) + ".png";
+ }
+ if (path.endsWith("@2x.png")) {
+ return path.substring(0, path.lastIndexOf("@2x.png")) + ".png";
+ }
+ return path;
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/lang/SmartEnterProcessorWithFixers.java b/platform/lang-impl/src/com/intellij/lang/SmartEnterProcessorWithFixers.java
index ea98ba5..a09f393 100644
--- a/platform/lang-impl/src/com/intellij/lang/SmartEnterProcessorWithFixers.java
+++ b/platform/lang-impl/src/com/intellij/lang/SmartEnterProcessorWithFixers.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;
import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor;
diff --git a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java
index 3aae0f3..016f7f1 100644
--- a/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.java
+++ b/platform/lang-impl/src/com/intellij/lang/customFolding/GotoCustomRegionAction.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.
@@ -82,6 +82,7 @@
private static void navigateTo(Editor editor, PsiElement element) {
int offset = element.getTextRange().getStartOffset();
if (offset >= 0 && offset < editor.getDocument().getTextLength()) {
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToOffset(offset);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
editor.getSelectionModel().removeSelection();
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java
index faa4673..ae12790 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/NamedElementDuplicateHandler.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.
@@ -36,6 +36,7 @@
private final EditorActionHandler myOriginal;
public NamedElementDuplicateHandler(EditorActionHandler original) {
+ super(true);
myOriginal = original;
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java
index cebf997..b70189f 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/actions/SelectWordAtCaretAction.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.
@@ -51,6 +51,10 @@
}
private static class DefaultHandler extends EditorActionHandler {
+ private DefaultHandler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
@@ -94,6 +98,7 @@
private final EditorActionHandler myDefaultHandler;
private Handler(EditorActionHandler defaultHandler) {
+ super(true);
myDefaultHandler = defaultHandler;
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/editor/ex/util/LayeredLexerEditorHighlighter.java b/platform/lang-impl/src/com/intellij/openapi/editor/ex/util/LayeredLexerEditorHighlighter.java
index 4079f6b..9dc0ea8 100644
--- a/platform/lang-impl/src/com/intellij/openapi/editor/ex/util/LayeredLexerEditorHighlighter.java
+++ b/platform/lang-impl/src/com/intellij/openapi/editor/ex/util/LayeredLexerEditorHighlighter.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.
@@ -116,7 +116,7 @@
}
@Override
- public void setText(final CharSequence text) {
+ public void setText(@NotNull final CharSequence text) {
// do NOT synchronize before updateLayers due to deadlock with PsiLock
updateLayers();
@@ -171,6 +171,7 @@
}
}
+ @NotNull
@Override
public HighlighterIterator createIterator(int startOffset) {
// do NOT synchronize before updateLayers due to deadlock with PsiLock
@@ -468,7 +469,7 @@
}
@Override
- public void setColorScheme(EditorColorsScheme scheme) {
+ public void setColorScheme(@NotNull EditorColorsScheme scheme) {
super.setColorScheme(scheme);
for (MappedRange mapping : getSegments().myRanges) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueVFilePathBuilderImpl.java b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueVFilePathBuilderImpl.java
index 9eba0fb..00f8835 100644
--- a/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueVFilePathBuilderImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/fileEditor/impl/UniqueVFilePathBuilderImpl.java
@@ -16,14 +16,12 @@
package com.intellij.openapi.fileEditor.impl;
import com.intellij.ide.ui.UISettings;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.fileEditor.UniqueVFilePathBuilder;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.UniqueNameBuilder;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.search.ProjectScope;
@@ -31,7 +29,6 @@
import org.jetbrains.annotations.NotNull;
import java.io.File;
-import java.util.Arrays;
import java.util.Collection;
/**
@@ -61,12 +58,19 @@
for (VirtualFile virtualFile: filesWithSameName) {
builder.addPath(virtualFile, virtualFile.getPath());
}
- String result = builder.getShortPath(file);
- if (UISettings.getInstance().HIDE_KNOWN_EXTENSION_IN_TABS) {
- return FileUtil.getNameWithoutExtension(result);
- }
- return result;
+ return getEditorTabText(file, builder, UISettings.getInstance().HIDE_KNOWN_EXTENSION_IN_TABS);
}
return file.getPresentableName();
}
+
+ public static <T> String getEditorTabText(T key, UniqueNameBuilder<T> builder, boolean hideKnownExtensionInTabs) {
+ String result = builder.getShortPath(key);
+ if (hideKnownExtensionInTabs) {
+ String withoutExtension = FileUtil.getNameWithoutExtension(result);
+ if (StringUtil.isNotEmpty(withoutExtension) && !withoutExtension.endsWith(builder.getSeparator())) {
+ return withoutExtension;
+ }
+ }
+ return result;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextParserDefinition.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextParserDefinition.java
deleted file mode 100644
index fb5bbfc..0000000
--- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/PlainTextParserDefinition.java
+++ /dev/null
@@ -1,98 +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.
- */
-
-/*
- * @author max
- */
-package com.intellij.openapi.fileTypes;
-
-import com.intellij.lang.ASTFactory;
-import com.intellij.lang.ASTNode;
-import com.intellij.lang.ParserDefinition;
-import com.intellij.lang.PsiParser;
-import com.intellij.lexer.EmptyLexer;
-import com.intellij.lexer.Lexer;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.FileViewProvider;
-import com.intellij.psi.PlainTextTokenTypes;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.impl.source.PsiPlainTextFileImpl;
-import com.intellij.psi.tree.IFileElementType;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.psi.util.PsiUtilCore;
-import org.jetbrains.annotations.NotNull;
-
-public class PlainTextParserDefinition implements ParserDefinition {
- private static final IFileElementType PLAIN_FILE_ELEMENT_TYPE = new IFileElementType(FileTypes.PLAIN_TEXT.getLanguage()) {
- @Override
- public ASTNode parseContents(ASTNode chameleon) {
- final CharSequence chars = chameleon.getChars();
- return ASTFactory.leaf(PlainTextTokenTypes.PLAIN_TEXT, chars);
- }
- };
-
- @Override
- @NotNull
- public Lexer createLexer(Project project) {
- return new EmptyLexer();
- }
-
- @Override
- @NotNull
- public PsiParser createParser(Project project) {
- throw new UnsupportedOperationException("Not supported");
- }
-
- @Override
- public IFileElementType getFileNodeType() {
- return PLAIN_FILE_ELEMENT_TYPE;
- }
-
- @Override
- @NotNull
- public TokenSet getWhitespaceTokens() {
- return TokenSet.EMPTY;
- }
-
- @Override
- @NotNull
- public TokenSet getCommentTokens() {
- return TokenSet.EMPTY;
- }
-
- @Override
- @NotNull
- public TokenSet getStringLiteralElements() {
- return TokenSet.EMPTY;
- }
-
- @Override
- @NotNull
- public PsiElement createElement(ASTNode node) {
- return PsiUtilCore.NULL_PSI_ELEMENT;
- }
-
- @Override
- public PsiFile createFile(FileViewProvider viewProvider) {
- return new PsiPlainTextFileImpl(viewProvider);
- }
-
- @Override
- public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode left, ASTNode right) {
- return SpaceRequirements.MAY;
- }
-}
diff --git a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java
index 37e7089..efd634f 100644
--- a/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java
+++ b/platform/lang-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeConfigurable.java
@@ -371,7 +371,7 @@
myFileTypesList = new JBList(new DefaultListModel());
myFileTypesList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myFileTypesList.setCellRenderer(new FileTypeRenderer(myFileTypesList.getCellRenderer(), new FileTypeRenderer.FileTypeListProvider() {
+ myFileTypesList.setCellRenderer(new FileTypeRenderer(new FileTypeRenderer.FileTypeListProvider() {
@Override
public Iterable<FileType> getCurrentFileTypeList() {
ArrayList<FileType> result = new ArrayList<FileType>();
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java
index 991ae5f..7a59184 100644
--- a/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java
+++ b/platform/lang-impl/src/com/intellij/openapi/module/WebModuleBuilder.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.ui.ValidationInfo;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.WebProjectGenerator;
import org.jetbrains.annotations.NotNull;
@@ -61,6 +62,16 @@
}
@Override
+ public String getPresentableName() {
+ return getGroupName();
+ }
+
+ @Override
+ public boolean isTemplateBased() {
+ return true;
+ }
+
+ @Override
public String getGroupName() {
return GROUP_NAME;
}
@@ -97,7 +108,7 @@
if (myTemplate == null) {
return super.modifySettingsStep(settingsStep);
}
- WebProjectGenerator.GeneratorPeer peer = myTemplate.getPeer();
+ final WebProjectGenerator.GeneratorPeer peer = myTemplate.getPeer();
peer.buildUI(settingsStep);
return new ModuleWizardStep() {
@Override
@@ -108,7 +119,13 @@
@Override
public void updateDataModel() {
}
+
+ @Override
+ public boolean validate() throws ConfigurationException {
+ ValidationInfo info = peer.validate();
+ if (info != null) throw new ConfigurationException(info.message);
+ 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 3391d4c..eafc1cf 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
@@ -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.
@@ -13,16 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.openapi.module.impl;
import com.intellij.ide.highlighter.ModuleFileType;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
-import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.components.ExtensionAreas;
-import com.intellij.openapi.components.impl.ComponentManagerImpl;
import com.intellij.openapi.components.impl.ModulePathMacroManager;
+import com.intellij.openapi.components.impl.PlatformComponentManagerImpl;
import com.intellij.openapi.components.impl.stores.IComponentStore;
import com.intellij.openapi.components.impl.stores.IModuleStore;
import com.intellij.openapi.components.impl.stores.ModuleStoreImpl;
@@ -53,7 +52,7 @@
/**
* @author max
*/
-public class ModuleImpl extends ComponentManagerImpl implements ModuleEx {
+public class ModuleImpl extends PlatformComponentManagerImpl implements ModuleEx {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.module.impl.ModuleImpl");
@NotNull private final Project myProject;
@@ -79,7 +78,6 @@
myModuleScopeProvider = new ModuleScopeProviderImpl(this);
init(filePath);
-
}
@Override
@@ -113,9 +111,9 @@
@Override
public void loadModuleComponents() {
- final IdeaPluginDescriptor[] plugins = PluginManager.getPlugins();
+ final IdeaPluginDescriptor[] plugins = PluginManagerCore.getPlugins();
for (IdeaPluginDescriptor plugin : plugins) {
- if (PluginManager.shouldSkipPlugin(plugin)) continue;
+ if (PluginManagerCore.shouldSkipPlugin(plugin)) continue;
loadComponentsConfiguration(plugin.getModuleComponents(), plugin, false);
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/RemoveInvalidElementsDialog.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/RemoveInvalidElementsDialog.java
index 4a23088..e9e5704 100644
--- a/platform/lang-impl/src/com/intellij/openapi/module/impl/RemoveInvalidElementsDialog.java
+++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/RemoveInvalidElementsDialog.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.
@@ -24,6 +24,7 @@
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.VerticalFlowLayout;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -62,7 +63,7 @@
panel.add(checkBox, constraints);
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.insets.top = 5;
- panel.add(new JLabel("<html><body>" + StringUtil.replace(error.getDescription(), "\n", "<br>") + "</body></html>"), constraints);
+ panel.add(new JLabel(XmlStringUtil.wrapInHtml(StringUtil.replace(error.getDescription(), "\n", "<br>"))), constraints);
constraints.weightx = 1;
panel.add(new JPanel(), constraints);
myContentPanel.add(panel);
@@ -85,7 +86,7 @@
ConfigurationErrorDescription error = errors.get(0);
String message = error.getDescription() + "\n" + error.getIgnoreConfirmationMessage();
final int answer = Messages.showYesNoDialog(project, message, title, Messages.getErrorIcon());
- if (answer == 0) {
+ if (answer == Messages.YES) {
error.ignoreInvalidElement();
}
return;
diff --git a/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java b/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java
index 2a2a6c7..74e80f0 100644
--- a/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java
+++ b/platform/lang-impl/src/com/intellij/openapi/paths/WebReference.java
@@ -49,8 +49,8 @@
@Override
public void navigate(boolean requestFocus) {
- BrowserUtil.launchBrowser(getValue());
- }
+ BrowserUtil.browse(getValue());
+ }
@Override
public String getPresentableText() {
diff --git a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java
index bd3be40..0ff1656 100644
--- a/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java
+++ b/platform/lang-impl/src/com/intellij/openapi/projectRoots/impl/SdkConfigurationUtil.java
@@ -54,7 +54,7 @@
public static void createSdk(@Nullable final Project project,
final Sdk[] existingSdks,
- final NullableConsumer<Sdk> onSdkCreatedCallBack,
+ final NullableConsumer<Sdk> onSdkCreatedCallBack, final boolean createIfExists,
final SdkType... sdkTypes) {
if (sdkTypes.length == 0) {
onSdkCreatedCallBack.consume(null);
@@ -72,8 +72,19 @@
@Override
public void consume(List<VirtualFile> selectedFiles) {
for (SdkType sdkType : sdkTypes) {
- if (sdkType.isValidSdkHome(selectedFiles.get(0).getPath())) {
- onSdkCreatedCallBack.consume(setupSdk(existingSdks, selectedFiles.get(0), sdkType, false, null, null));
+ final String path = selectedFiles.get(0).getPath();
+ if (sdkType.isValidSdkHome(path)) {
+ Sdk newSdk = null;
+ if (!createIfExists) {
+ for (Sdk sdk : existingSdks) {
+ if (path.equals(sdk.getHomePath())) {
+ newSdk = sdk;
+ }
+ }
+ }
+ if (newSdk == null)
+ newSdk = setupSdk(existingSdks, selectedFiles.get(0), sdkType, false, null, null);
+ onSdkCreatedCallBack.consume(newSdk);
return;
}
}
@@ -85,6 +96,14 @@
onSdkCreatedCallBack.consume(null);
}
});
+
+ }
+
+ public static void createSdk(@Nullable final Project project,
+ final Sdk[] existingSdks,
+ final NullableConsumer<Sdk> onSdkCreatedCallBack,
+ final SdkType... sdkTypes) {
+ createSdk(project, existingSdks, onSdkCreatedCallBack, true, sdkTypes);
}
private static FileChooserDescriptor createCompositeDescriptor(final SdkType... sdkTypes) {
@@ -140,7 +159,7 @@
final ProjectJdkImpl sdk;
try {
String sdkPath = sdkType.sdkPath(homeDir);
-
+
final String sdkName = customSdkSuggestedName == null
? createUniqueSdkName(sdkType, sdkPath, sdksList)
: createUniqueSdkName(customSdkSuggestedName, sdksList);
@@ -313,8 +332,9 @@
@Nullable
private static Sdk findByPath(SdkType sdkType, Sdk[] sdks, String sdkHome) {
for (Sdk sdk : sdks) {
- if (sdk.getSdkType() == sdkType &&
- FileUtil.pathsEqual(FileUtil.toSystemIndependentName(sdk.getHomePath()), FileUtil.toSystemIndependentName(sdkHome))) {
+ final String path = sdk.getHomePath();
+ if (sdk.getSdkType() == sdkType && path != null &&
+ FileUtil.pathsEqual(FileUtil.toSystemIndependentName(path), FileUtil.toSystemIndependentName(sdkHome))) {
return sdk;
}
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
index 8c2948f..d0541e6 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/DirectoryIndexImpl.java
@@ -112,6 +112,7 @@
myState.myProjectExcludeRoots.clear();
myState.myRootTypeId.clear();
myState.myRootTypes.clear();
+ myRootIndex = null;
}
});
}
@@ -176,9 +177,6 @@
}
private class MyVirtualFileListener extends VirtualFileAdapter implements BulkFileListener {
- private static final int MAX_DEPTH_TO_COUNT = 20;
- private static final int DIRECTORIES_CHANGED_THRESHOLD = 50;
-
@Override
public void fileCreated(VirtualFileEvent event) {
VirtualFile file = event.getFile();
@@ -356,29 +354,10 @@
}
myBatchChangePlanned = false;
- int directoriesRemoved = 0;
- int directoriesCreated = 0;
-
- for (VFileEvent event : events) {
- if (event instanceof VFileDeleteEvent) {
- VirtualFile file = event.getFile();
- if (file != null && file.isDirectory()) {
- directoriesRemoved += 1 + countDirectories(file, MAX_DEPTH_TO_COUNT);
- }
- }
- else if (event instanceof VFileCreateEvent) {
- VirtualFile file = event.getFile();
- if (file != null && file.isDirectory() ||
- file == null && ((VFileCreateEvent)event).isDirectory()) {
- directoriesCreated += 1 + countDirectories(file, MAX_DEPTH_TO_COUNT);
- }
- }
- }
-
- final boolean willDoBatchUpdate = directoriesCreated + directoriesRemoved > DIRECTORIES_CHANGED_THRESHOLD;
+ final boolean willDoBatchUpdate = isLargeVfsChange(events);
if (willDoBatchUpdate) {
myBatchChangePlanned = true;
- LOG.info("Too many directories created / deleted: " + directoriesCreated + "," + directoriesRemoved + ", will rebuild index state");
+ LOG.info("will rebuild index state");
}
else {
for (VFileEvent event : events) {
@@ -387,16 +366,6 @@
}
}
- private int countDirectories(@Nullable VirtualFile file, int depth) {
- if (!(file instanceof NewVirtualFile)) return 0;
-
- int counter = 0;
- for (VirtualFile child : ((NewVirtualFile)file).iterInDbChildren()) {
- if (child.isDirectory()) counter += 1 + (depth > 0 ? countDirectories(child, depth - 1) : 0);
- }
- return counter;
- }
-
@Override
public void after(@NotNull List<? extends VFileEvent> events) {
RootIndex rootIndex = myRootIndex;
@@ -507,7 +476,7 @@
}
RootIndex rootIndex = myRootIndex;
if (rootIndex == null) {
- rootIndex = myRootIndex = new RootIndex(myProject);
+ myRootIndex = rootIndex = new RootIndex(myProject);
}
return rootIndex;
}
@@ -621,13 +590,40 @@
return riInfo;
}
- return assertConsistentResult(dir, riInfo, myState.getInfo(((NewVirtualFile)dir).getId()));
+ DirectoryInfo standardResult = myState.getInfo(((NewVirtualFile)dir).getId());
+ assertConsistentResult(dir, riInfo, standardResult);
+ if (standardResult != riInfo && standardResult.equals(riInfo) && rootIndex != null) {
+ rootIndex.cacheInfos(dir, dir, standardResult);
+ }
+ return standardResult;
}
- private static <T> T assertConsistentResult(@NotNull Object arg, @Nullable T rootIndexResult, T standardResult) {
+ private <T> T assertConsistentResult(@NotNull Object arg, @Nullable T rootIndexResult, T standardResult) {
//noinspection ConstantConditions
if (ourCompareImplementations && !Comparing.equal(rootIndexResult, standardResult)) {
- LOG.error("DirectoryIndex differs from RootIndex at " + arg + "\nriInfo=" + rootIndexResult + "\nstandardResult=" + standardResult);
+ String msg = "DirectoryIndex differs from RootIndex at " + arg +
+ "\nriInfo = " + rootIndexResult +
+ "\nstandardResult = " + standardResult +
+ "\nRoot model:";
+ for (Module module : ModuleManager.getInstance(myProject).getModules()) {
+ msg += "\nModule " + module.getName();
+ for (ContentEntry entry : ModuleRootManager.getInstance(module).getContentEntries()) {
+ msg += "\n Content " + entry.getFile();
+ for (VirtualFile file : entry.getSourceFolderFiles()) {
+ msg += "\n Source " + file;
+ }
+ for (VirtualFile file : entry.getExcludeFolderFiles()) {
+ msg += "\n Excluded " + file;
+ }
+ }
+ }
+ for (DirectoryIndexExcludePolicy policy : Extensions.getExtensions(DirectoryIndexExcludePolicy.EP_NAME, myProject)) {
+ for (VirtualFile root : policy.getExcludeRootsForProject()) {
+ msg += "\nProject exclude " + root;
+ }
+ }
+
+ LOG.error(msg);
}
return standardResult;
}
@@ -657,13 +653,12 @@
return getRootIndex().isProjectExcludeRoot(dir);
}
-
//noinspection UnnecessaryLocalVariable
boolean standardResult = myState.myProjectExcludeRoots.contains(((NewVirtualFile)dir).getId());
-/* todo
+/*
RootIndex rootIndex = getRootIndex();
Boolean riResult = rootIndex != null ? rootIndex.isProjectExcludeRoot(dir) : null;
- return assertConsistentResult(dir, riResult, standardResult);
+ assertConsistentResult(dir, riResult, standardResult);
*/
return standardResult;
}
@@ -1636,4 +1631,44 @@
"; path is substring: " + FileUtil.isAncestor(root.getPath(), myFile.getPath(), false)
;
}
+
+ private static final int MAX_DEPTH_TO_COUNT = 20;
+ private static final int DIRECTORIES_CHANGED_THRESHOLD = 50;
+
+ public static boolean isLargeVfsChange(List<? extends VFileEvent> events) {
+ int directoriesRemoved = 0;
+ int directoriesCreated = 0;
+
+ for (VFileEvent event : events) {
+ if (event instanceof VFileDeleteEvent) {
+ VirtualFile file = event.getFile();
+ if (file != null && file.isDirectory()) {
+ directoriesRemoved += 1 + countDirectories(file, MAX_DEPTH_TO_COUNT);
+ }
+ }
+ else if (event instanceof VFileCreateEvent) {
+ VirtualFile file = event.getFile();
+ if (file != null && file.isDirectory() ||
+ file == null && ((VFileCreateEvent)event).isDirectory()) {
+ directoriesCreated += 1 + countDirectories(file, MAX_DEPTH_TO_COUNT);
+ }
+ }
+ }
+
+ boolean largeChange = directoriesCreated + directoriesRemoved > DIRECTORIES_CHANGED_THRESHOLD;
+ if (largeChange) {
+ LOG.info("Too many directories created / deleted: " + directoriesCreated + "," + directoriesRemoved);
+ }
+ return largeChange;
+ }
+
+ private static int countDirectories(@Nullable VirtualFile file, int depth) {
+ if (!(file instanceof NewVirtualFile)) return 0;
+
+ int counter = 0;
+ for (VirtualFile child : ((NewVirtualFile)file).iterInDbChildren()) {
+ if (child.isDirectory()) counter += 1 + (depth > 0 ? countDirectories(child, depth - 1) : 0);
+ }
+ return counter;
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
index 524bf2b..3f75f7f 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerComponent.java
@@ -36,8 +36,11 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.ex.VirtualFileManagerAdapter;
+import com.intellij.openapi.vfs.newvfs.BulkFileListener;
+import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerListener;
+import com.intellij.util.SystemProperties;
import com.intellij.util.containers.HashSet;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
@@ -54,9 +57,11 @@
*/
public class ProjectRootManagerComponent extends ProjectRootManagerImpl {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.roots.impl.ProjectManagerComponent");
-
+ private static final boolean ourScheduleCacheUpdateInDumbMode = SystemProperties.getBooleanProperty(
+ "idea.schedule.cache.update.in.dumb.mode", ApplicationManager.getApplication().isInternal());
private boolean myPointerChangesDetected = false;
private int myInsideRefresh = 0;
+ private boolean myLargeVfsUpdateDetected;
private final BatchUpdateListener myHandler;
private final MessageBusConnection myConnection;
@@ -83,10 +88,22 @@
}
});
+ myConnection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener.Adapter() {
+ @Override
+ public void before(@NotNull List<? extends VFileEvent> events) {
+ myLargeVfsUpdateDetected |= DirectoryIndexImpl.isLargeVfsChange(events);
+ }
+ });
+
VirtualFileManager.getInstance().addVirtualFileManagerListener(new VirtualFileManagerAdapter() {
@Override
+ public void beforeRefreshStart(boolean asynchronous) {
+ myLargeVfsUpdateDetected = false;
+ }
+
+ @Override
public void afterRefreshFinish(boolean asynchronous) {
- doUpdateOnRefresh();
+ doUpdateOnRefresh(myLargeVfsUpdateDetected);
}
}, project);
@@ -168,11 +185,20 @@
getBatchSession(fileTypes).rootsChanged();
}
- private void doUpdateOnRefresh() {
+ private void doUpdateOnRefresh(boolean largeChange) {
if (ApplicationManager.getApplication().isUnitTestMode() && (!myStartupActivityPerformed || myProject.isDisposed())) {
return; // in test mode suppress addition to a queue unless project is properly initialized
}
- DumbServiceImpl.getInstance(myProject).queueCacheUpdate(myRefreshCacheUpdaters);
+ if (myRefreshCacheUpdaters.size() == 0) {
+ return; // default project
+ }
+ DumbServiceImpl dumbService = DumbServiceImpl.getInstance(myProject);
+ if (largeChange && ourScheduleCacheUpdateInDumbMode) {
+ dumbService.queueCacheUpdateInDumbMode(myRefreshCacheUpdaters);
+ }
+ else {
+ dumbService.queueCacheUpdate(myRefreshCacheUpdaters);
+ }
}
private boolean affectsRoots(VirtualFilePointer[] pointers) {
@@ -279,7 +305,13 @@
@Override
protected void doSynchronizeRoots() {
if (!myStartupActivityPerformed) return;
- DumbServiceImpl.getInstance(myProject).queueCacheUpdate(myRootsChangeUpdaters);
+
+ DumbServiceImpl dumbService = DumbServiceImpl.getInstance(myProject);
+ if (ourScheduleCacheUpdateInDumbMode) {
+ dumbService.queueCacheUpdateInDumbMode(myRootsChangeUpdaters);
+ } else {
+ dumbService.queueCacheUpdate(myRootsChangeUpdaters);
+ }
}
private static void addRootsToTrack(final String[] urls, final Collection<String> recursive, final Collection<String> flat) {
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootIndex.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
index 7bc6341..b26aea3 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/RootIndex.java
@@ -18,13 +18,14 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileTypeManager;
-import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.impl.libraries.LibraryEx;
import com.intellij.openapi.roots.libraries.Library;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -34,7 +35,6 @@
import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import java.util.*;
@@ -44,21 +44,35 @@
private static final DirectoryInfo NULL_INFO = DirectoryInfo.createNew();
private final Set<VirtualFile> myProjectExcludedRoots = ContainerUtil.newHashSet();
- private final Set<VirtualFile> myLibraryExcludedRoots = ContainerUtil.newHashSet();
- private final Map<VirtualFile, DirectoryInfo> myRoots = ContainerUtil.newTroveMap();
- private final Map<String, HashSet<VirtualFile>> myPackagePrefixRoots = ContainerUtil.newHashMap();
+ private final MultiMap<String, VirtualFile> myPackagePrefixRoots = new MultiMap<String, VirtualFile>() {
+ @Override
+ protected Collection<VirtualFile> createCollection() {
+ return ContainerUtil.newLinkedHashSet();
+ }
+ };
private final Map<String, List<VirtualFile>> myDirectoriesByPackageNameCache = ContainerUtil.newConcurrentMap();
- private final Map<String, List<VirtualFile>> myDirectoriesByPackageNameCacheWithLibSrc = ContainerUtil.newConcurrentMap();
private final Map<VirtualFile, DirectoryInfo> myInfoCache = ContainerUtil.newConcurrentMap();
private final List<JpsModuleSourceRootType<?>> myRootTypes = ContainerUtil.newArrayList();
private final TObjectIntHashMap<JpsModuleSourceRootType<?>> myRootTypeId = new TObjectIntHashMap<JpsModuleSourceRootType<?>>();
RootIndex(@NotNull final Project project) {
- final MultiMap<VirtualFile, OrderEntry> depEntries = new MultiMap<VirtualFile, OrderEntry>();
- final MultiMap<VirtualFile, OrderEntry> libClassRootEntries = new MultiMap<VirtualFile, OrderEntry>();
- final MultiMap<VirtualFile, OrderEntry> libSourceRootEntries = new MultiMap<VirtualFile, OrderEntry>();
+ final RootInfo info = buildRootInfo(project);
+ Set<VirtualFile> allRoots = info.getAllRoots();
+ for (VirtualFile root : allRoots) {
+ List<VirtualFile> hierarchy = getHierarchy(root, allRoots);
+ Pair<DirectoryInfo, String> pair = hierarchy == null ? new Pair<DirectoryInfo, String>(null, null) : info.calcDirectoryInfo(root, hierarchy);
+ cacheInfos(root, root, pair.first);
+ myPackagePrefixRoots.putValue(pair.second, root);
+ if (info.shouldMarkAsProjectExcluded(root, hierarchy)) {
+ myProjectExcludedRoots.add(root);
+ }
+ }
+ }
+
+ private RootInfo buildRootInfo(Project project) {
+ final RootInfo info = new RootInfo();
for (final Module module : ModuleManager.getInstance(project).getModules()) {
final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
final OrderEntry[] orderEntries = moduleRootManager.getOrderEntries();
@@ -66,35 +80,24 @@
final VirtualFile[] contentRoots = moduleRootManager.getContentRoots();
for (final VirtualFile contentRoot : contentRoots) {
- myRoots.put(contentRoot, getOrCreateDirectoryInfo(contentRoot).with(module, contentRoot, null, null, (byte) 0, null));
+ if (!info.contentRootOf.containsKey(contentRoot)) {
+ info.contentRootOf.put(contentRoot, module);
+ }
}
for (ContentEntry contentEntry : contentEntries) {
- // Init excluded roots
- Collections.addAll(myProjectExcludedRoots, contentEntry.getExcludeFolderFiles());
+ for (VirtualFile excludeRoot : contentEntry.getExcludeFolderFiles()) {
+ info.excludedFromModule.put(excludeRoot, module);
+ }
// Init module sources
- SourceFolder[] sourceFolders = contentEntry.getSourceFolders();
- for (final SourceFolder sourceFolder : sourceFolders) {
+ for (final SourceFolder sourceFolder : contentEntry.getSourceFolders()) {
final VirtualFile sourceFolderRoot = sourceFolder.getFile();
if (sourceFolderRoot != null) {
- final DirectoryInfo info = getOrCreateDirectoryInfo(sourceFolderRoot);
-
- VirtualFile contentRoot = null;
- for (VirtualFile root : contentRoots) {
- if (VfsUtilCore.isAncestor(root, sourceFolderRoot, false)) {
- contentRoot = root;
- break;
- }
- }
-
- int rootTypeId = getRootTypeId(sourceFolder.getRootType());
-
- int sourceRootTypeData = DirectoryInfo.createSourceRootTypeData(true, info.isInLibrarySource(), rootTypeId);
- DirectoryInfo info1 = info.with(module, contentRoot, sourceFolderRoot, null, sourceRootTypeData, null);
-
- myRoots.put(sourceFolderRoot, info1);
- initializePrefix(sourceFolderRoot, sourceFolder.getPackagePrefix());
+ info.rootTypeId.put(sourceFolderRoot, getRootTypeId(sourceFolder.getRootType()));
+ info.classAndSourceRoots.add(sourceFolderRoot);
+ info.sourceRootOf.putValue(sourceFolderRoot, module);
+ info.packagePrefix.put(sourceFolderRoot, sourceFolder.getPackagePrefix());
}
}
}
@@ -106,17 +109,11 @@
if (depModule != null) {
VirtualFile[] importedClassRoots = OrderEnumerator.orderEntries(depModule).exportedOnly().recursively().classes().usingCache().getRoots();
for (VirtualFile importedClassRoot : importedClassRoots) {
- depEntries.putValue(importedClassRoot, orderEntry);
+ info.depEntries.putValue(importedClassRoot, orderEntry);
}
}
for (VirtualFile sourceRoot : orderEntry.getFiles(OrderRootType.SOURCES)) {
- depEntries.putValue(sourceRoot, orderEntry);
- }
- }
- else if (orderEntry instanceof ModuleSourceOrderEntry) {
- final VirtualFile[] sourceRoots = ((ModuleSourceOrderEntry)orderEntry).getRootModel().getSourceRoots();
- for (VirtualFile sourceRoot : sourceRoots) {
- fillMapWithOrderEntries(sourceRoot, Arrays.asList(orderEntry), orderEntry.getOwnerModule(), null, null);
+ info.depEntries.putValue(sourceRoot, orderEntry);
}
}
else if (orderEntry instanceof LibraryOrSdkOrderEntry) {
@@ -124,31 +121,32 @@
final VirtualFile[] sourceRoots = entry.getRootFiles(OrderRootType.SOURCES);
final VirtualFile[] classRoots = entry.getRootFiles(OrderRootType.CLASSES);
- // init library classes
- for (final VirtualFile classRoot : classRoots) {
- libClassRootEntries.putValue(classRoot, orderEntry);
- final DirectoryInfo info = getOrCreateDirectoryInfo(classRoot).with(null, null, null, classRoot, (byte) 0, null);
- myRoots.put(classRoot, info);
- if (!info.isInModuleSource() && !info.isInLibrarySource()) {
- initializePrefix(classRoot, "");
- }
- }
-
// Init library sources
for (final VirtualFile sourceRoot : sourceRoots) {
- libSourceRootEntries.putValue(sourceRoot, orderEntry);
- final DirectoryInfo info = getOrCreateDirectoryInfo(sourceRoot);
+ info.classAndSourceRoots.add(sourceRoot);
+ info.libSourceRootEntries.putValue(sourceRoot, orderEntry);
+ info.packagePrefix.put(sourceRoot, "");
+ }
- int sourceRootTypeData = DirectoryInfo.createSourceRootTypeData(info.isInModuleSource(), true, getRootTypeId(JavaSourceRootType.SOURCE));
-
- myRoots.put(sourceRoot, info.with(null, null, sourceRoot, null, sourceRootTypeData, null));
- initializePrefix(sourceRoot, "");
+ // init library classes
+ for (final VirtualFile classRoot : classRoots) {
+ info.classAndSourceRoots.add(classRoot);
+ info.libClassRootEntries.putValue(classRoot, orderEntry);
+ info.packagePrefix.put(classRoot, "");
}
if (orderEntry instanceof LibraryOrderEntry) {
Library library = ((LibraryOrderEntry)orderEntry).getLibrary();
if (library != null) {
- Collections.addAll(myLibraryExcludedRoots, ((LibraryEx)library).getExcludedRoots());
+ for (VirtualFile root : ((LibraryEx)library).getExcludedRoots()) {
+ info.excludedFromLibraries.putValue(root, library);
+ }
+ for (VirtualFile root : sourceRoots) {
+ info.sourceOfLibraries.putValue(root, library);
+ }
+ for (VirtualFile root : classRoots) {
+ info.classOfLibraries.putValue(root, library);
+ }
}
}
@@ -157,89 +155,19 @@
}
for (DirectoryIndexExcludePolicy policy : Extensions.getExtensions(DirectoryIndexExcludePolicy.EP_NAME, project)) {
- Collections.addAll(myProjectExcludedRoots, policy.getExcludeRootsForProject());
+ Collections.addAll(info.excludedFromProject, policy.getExcludeRootsForProject());
}
-
- // fill ordered entries
- for (Map.Entry<VirtualFile, Collection<OrderEntry>> mapEntry : depEntries.entrySet()) {
- fillMapWithOrderEntries(mapEntry.getKey(), mapEntry.getValue(), null, null, null);
- }
- for (Map.Entry<VirtualFile, Collection<OrderEntry>> mapEntry : libClassRootEntries.entrySet()) {
- fillMapWithOrderEntries(mapEntry.getKey(), mapEntry.getValue(), null, mapEntry.getKey(), null);
- }
- for (Map.Entry<VirtualFile, Collection<OrderEntry>> mapEntry : libSourceRootEntries.entrySet()) {
- fillMapWithOrderEntries(mapEntry.getKey(), mapEntry.getValue(), null, null, mapEntry.getKey());
- }
-
- mergeWithParentInfos();
- }
-
- private void mergeWithParentInfos() {
- for (Map.Entry<VirtualFile, DirectoryInfo> entry : myRoots.entrySet()) {
- DirectoryInfo info = entry.getValue();
- Module module = info.getModule();
- VirtualFile contentRoot = info.getContentRoot();
- VirtualFile libraryClassRoot = info.getLibraryClassRoot();
- boolean inModuleSource = info.isInModuleSource();
- boolean inLibrarySource = info.isInLibrarySource();
-
- OrderEntry[] orderEntries = info.getOrderEntries();
-
- boolean nested = false;
-
- VirtualFile eachFile = entry.getKey().getParent();
- while (eachFile != null) {
- DirectoryInfo eachInfo = myRoots.get(eachFile);
- if (eachInfo != null) {
- nested = true;
-
- if (eachInfo.getLibraryClassRoot() != null && libraryClassRoot == null && !info.isInModuleSource()) {
- orderEntries = eachInfo.getOrderEntries();
- }
-
- if (module == null) {
- module = eachInfo.getModule();
- }
- if (libraryClassRoot == null) {
- libraryClassRoot = eachInfo.getLibraryClassRoot();
- }
- if (contentRoot == null) {
- contentRoot = eachInfo.getContentRoot();
- }
- inModuleSource |= eachInfo.isInModuleSource();
- inLibrarySource |= eachInfo.isInLibrarySource();
- }
- if (isAnyExcludeRoot(eachFile)) {
- break;
- }
-
- eachFile = eachFile.getParent();
- }
- if (nested) {
- int sourceRootTypeData = DirectoryInfo.createSourceRootTypeData(inModuleSource, inLibrarySource, info.getSourceRootTypeId());
- if (orderEntries.length == 0) orderEntries = null;
- entry.setValue(info.with(module, contentRoot, info.getSourceRoot(), libraryClassRoot, sourceRootTypeData, orderEntries));
- }
- }
+ return info;
}
public void checkConsistency() {
for (VirtualFile file : myProjectExcludedRoots) {
assert file.exists() : file.getPath() + " does not exist";
}
- for (VirtualFile file : myLibraryExcludedRoots) {
- assert file.exists() : file.getPath() + " does not exist";
- }
- for (VirtualFile file : myRoots.keySet()) {
+ for (VirtualFile file : myPackagePrefixRoots.values()) {
assert file.exists() : file.getPath() + " does not exist";
}
-
- for (HashSet<VirtualFile> virtualFiles : myPackagePrefixRoots.values()) {
- for (VirtualFile file : virtualFiles) {
- assert file.exists() : file.getPath() + " does not exist";
- }
- }
}
private int getRootTypeId(JpsModuleSourceRootType<?> rootType) {
@@ -256,64 +184,13 @@
return id;
}
-
- private void fillMapWithOrderEntries(final VirtualFile root,
- @NotNull final Collection<OrderEntry> orderEntries,
- @Nullable final Module module,
- @Nullable final VirtualFile libraryClassRoot,
- @Nullable final VirtualFile librarySourceRoot) {
-
- assert root.exists();
-
- if (FileTypeRegistry.getInstance().isFileIgnored(root)) {
- return;
- }
-
- DirectoryInfo info = myRoots.get(root);
- if (info == null) return;
-
- if (module != null) {
- if (info.getModule() != module) return;
- if (!info.isInModuleSource()) return;
- } else if (libraryClassRoot != null) {
- if (info.getLibraryClassRoot() != libraryClassRoot) return;
- if (info.isInModuleSource()) return;
- } else if (librarySourceRoot != null) {
- if (!info.isInLibrarySource()) return;
- if (info.getSourceRoot() != librarySourceRoot) return;
- if (info.getLibraryClassRoot() != null) return;
- }
-
- OrderEntry[] orderEntriesArray = orderEntries.toArray(new OrderEntry[orderEntries.size()]);
- Arrays.sort(orderEntriesArray, DirectoryInfo.BY_OWNER_MODULE);
-
- myRoots.put(root, info.withInternedEntries(info.calcNewOrderEntries(orderEntriesArray, null, info.getOrderEntries())));
- }
-
- @NotNull
- private DirectoryInfo getOrCreateDirectoryInfo(VirtualFile root) {
- final DirectoryInfo existingInfo = myRoots.get(root);
- if (existingInfo != null) {
- return existingInfo;
- }
-
- return DirectoryInfo.createNew();
- }
-
- private void initializePrefix(final VirtualFile root, final String packagePrefix) {
- if (!myPackagePrefixRoots.containsKey(packagePrefix)) {
- myPackagePrefixRoots.put(packagePrefix, new HashSet<VirtualFile>());
- }
- myPackagePrefixRoots.get(packagePrefix).add(root);
- }
-
@Nullable
public DirectoryInfo getInfoForDirectory(@NotNull final VirtualFile dir) {
if (!dir.isValid()) {
return null;
}
if (!dir.isDirectory()) {
- return myRoots.get(dir);
+ return myInfoCache.get(dir);
}
int count = 0;
@@ -324,29 +201,29 @@
DirectoryInfo info = myInfoCache.get(root);
if (info != null) {
if (dir != root) {
- myInfoCache.put(dir, info);
+ cacheInfos(dir, root, info);
}
return info == NULL_INFO ? null : info;
}
-
- info = myRoots.get(root);
- if (info != null) {
- myInfoCache.put(dir, info);
- return info;
- }
-
- if (isAnyExcludeRoot(root) || FileTypeManager.getInstance().isFileIgnored(root)) {
- myInfoCache.put(dir, NULL_INFO);
- return null;
+
+ if (FileTypeManager.getInstance().isFileIgnored(root)) {
+ return cacheInfos(dir, root, null);
}
}
- myInfoCache.put(dir, NULL_INFO);
- return null;
+ return cacheInfos(dir, null, null);
}
- private boolean isAnyExcludeRoot(VirtualFile root) {
- return myProjectExcludedRoots.contains(root) || myLibraryExcludedRoots.contains(root);
+ @Nullable
+ DirectoryInfo cacheInfos(VirtualFile dir, @Nullable VirtualFile stopAt, @Nullable DirectoryInfo info) {
+ while (dir != null) {
+ myInfoCache.put(dir, info == null ? NULL_INFO : info);
+ if (dir.equals(stopAt)) {
+ break;
+ }
+ dir = dir.getParent();
+ }
+ return info;
}
public boolean isProjectExcludeRoot(@NotNull final VirtualFile dir) {
@@ -355,57 +232,48 @@
@NotNull
List<VirtualFile> getDirectoriesByPackageName(@NotNull final String packageName, final boolean includeLibrarySources) {
- Map<String, List<VirtualFile>> cacheMap = includeLibrarySources ?
- myDirectoriesByPackageNameCacheWithLibSrc :
- myDirectoriesByPackageNameCache;
- final List<VirtualFile> cachedResult = cacheMap.get(packageName);
- if (cachedResult != null) {
- return cachedResult;
- }
-
- final ArrayList<VirtualFile> result = ContainerUtil.newArrayList();
- Set<VirtualFile> packagePrefixRoots = myPackagePrefixRoots.get(packageName);
- if (packagePrefixRoots != null) {
- for (VirtualFile file : packagePrefixRoots) {
- if (isValidPackageDirectory(includeLibrarySources, file)) {
- result.add(file);
+ List<VirtualFile> result = myDirectoriesByPackageNameCache.get(packageName);
+ if (result == null) {
+ result = ContainerUtil.newSmartList();
+
+ if (StringUtil.isNotEmpty(packageName) && !packageName.startsWith(".")) {
+ String shortName = StringUtil.getShortName(packageName);
+ for (VirtualFile parentDir : getDirectoriesByPackageName(StringUtil.getPackageName(packageName), true)) {
+ VirtualFile child = parentDir.findChild(shortName);
+ if (child != null && child.isDirectory() && getInfoForDirectory(child) != null && packageName.equals(getPackageName(child))) {
+ result.add(child);
+ }
}
}
+
+ result.addAll(myPackagePrefixRoots.get(packageName));
+
+ if (!result.isEmpty()) {
+ myDirectoriesByPackageNameCache.put(packageName, result);
+ }
}
- if (StringUtil.isNotEmpty(packageName) && !packageName.startsWith(".")) {
- String parentPackage = StringUtil.getPackageName(packageName);
- String shortName = StringUtil.getShortName(packageName);
- for (VirtualFile parentDir : getDirectoriesByPackageName(parentPackage, includeLibrarySources)) {
- VirtualFile child = parentDir.findChild(shortName);
- if (isValidPackageDirectory(includeLibrarySources, child) && child.isDirectory()) {
- result.add(child);
- }
- }
+ if (includeLibrarySources) {
+ return result;
}
- if (!result.isEmpty()) {
- cacheMap.put(packageName, result);
- }
- return result;
- }
-
- private boolean isValidPackageDirectory(boolean includeLibrarySources, @Nullable VirtualFile file) {
- if (file != null) {
- DirectoryInfo info = getInfoForDirectory(file);
- if (info != null) {
- if (includeLibrarySources || !info.isInLibrarySource() || info.isInModuleSource() || info.hasLibraryClassRoot()) {
- return true;
- }
+ return ContainerUtil.filter(result, new Condition<VirtualFile>() {
+ @Override
+ public boolean value(VirtualFile file) {
+ DirectoryInfo info = getInfoForDirectory(file);
+ return info != null && (!info.isInLibrarySource() || info.isInModuleSource() || info.hasLibraryClassRoot());
}
- }
- return false;
+ });
}
@Nullable
public String getPackageName(@NotNull final VirtualFile dir) {
if (dir.isDirectory()) {
- for (final Map.Entry<String, HashSet<VirtualFile>> entry : myPackagePrefixRoots.entrySet()) {
+ if (FileTypeManager.getInstance().isFileIgnored(dir)) {
+ return null;
+ }
+
+ for (final Map.Entry<String, Collection<VirtualFile>> entry : myPackagePrefixRoots.entrySet()) {
if (entry.getValue().contains(dir)) {
return entry.getKey();
}
@@ -441,4 +309,212 @@
return true;
}
+ @Nullable
+ private static List<VirtualFile> getHierarchy(VirtualFile dir, Set<VirtualFile> allRoots) {
+ List<VirtualFile> hierarchy = ContainerUtil.newArrayList();
+ while (dir != null) {
+ if (FileTypeManager.getInstance().isFileIgnored(dir)) {
+ return null;
+ }
+ if (allRoots.contains(dir)) {
+ hierarchy.add(dir);
+ }
+ dir = dir.getParent();
+ }
+ return hierarchy;
+ }
+
+ private static class RootInfo {
+ // getDirectoriesByPackageName used to be in this order, some clients might rely on that
+ @NotNull final LinkedHashSet<VirtualFile> classAndSourceRoots = ContainerUtil.newLinkedHashSet();
+
+ @NotNull final Map<VirtualFile, Module> contentRootOf = ContainerUtil.newHashMap();
+ @NotNull final MultiMap<VirtualFile, Module> sourceRootOf = MultiMap.createSet();
+ @NotNull final TObjectIntHashMap<VirtualFile> rootTypeId = new TObjectIntHashMap<VirtualFile>();
+ @NotNull final MultiMap<VirtualFile, OrderEntry> libClassRootEntries = MultiMap.createSmartList();
+ @NotNull final MultiMap<VirtualFile, OrderEntry> libSourceRootEntries = MultiMap.createSmartList();
+ @NotNull final MultiMap<VirtualFile, OrderEntry> depEntries = MultiMap.createSmartList();
+ @NotNull final MultiMap<VirtualFile, Library> excludedFromLibraries = MultiMap.createSmartList();
+ @NotNull final MultiMap<VirtualFile, Library> classOfLibraries = MultiMap.createSmartList();
+ @NotNull final MultiMap<VirtualFile, Library> sourceOfLibraries = MultiMap.createSmartList();
+ @NotNull final Set<VirtualFile> excludedFromProject = ContainerUtil.newHashSet();
+ @NotNull final Map<VirtualFile, Module> excludedFromModule = ContainerUtil.newHashMap();
+ @NotNull final Map<VirtualFile, String> packagePrefix = ContainerUtil.newHashMap();
+
+ Set<VirtualFile> getAllRoots() {
+ LinkedHashSet<VirtualFile> result = ContainerUtil.newLinkedHashSet();
+ result.addAll(classAndSourceRoots);
+ result.addAll(contentRootOf.keySet());
+ result.addAll(excludedFromLibraries.keySet());
+ result.addAll(excludedFromModule.keySet());
+ result.addAll(excludedFromProject);
+ return result;
+ }
+
+ private boolean shouldMarkAsProjectExcluded(VirtualFile root, @Nullable List<VirtualFile> hierarchy) {
+ if (hierarchy == null) return false;
+ if (!excludedFromProject.contains(root) && !excludedFromModule.containsKey(root)) return false;
+ return ContainerUtil.find(hierarchy, new Condition<VirtualFile>() {
+ @Override
+ public boolean value(VirtualFile ancestor) {
+ return contentRootOf.containsKey(ancestor);
+ }
+ }) == null;
+ }
+
+ @Nullable
+ private VirtualFile findModuleRootInfo(List<VirtualFile> hierarchy) {
+ for (VirtualFile root : hierarchy) {
+ Module module = contentRootOf.get(root);
+ Module excludedFrom = excludedFromModule.get(root);
+ if (module != null && excludedFrom != module) {
+ return root;
+ }
+ if (excludedFromProject.contains(root) || excludedFrom != null || !root.isDirectory()) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ private VirtualFile findLibraryRootInfo(List<VirtualFile> hierarchy, boolean source) {
+ Set<Library> librariesToIgnore = ContainerUtil.newHashSet();
+ for (VirtualFile root : hierarchy) {
+ librariesToIgnore.addAll(excludedFromLibraries.get(root));
+ if (source && libSourceRootEntries.containsKey(root) &&
+ (!sourceOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(sourceOfLibraries.get(root)))) {
+ return root;
+ } else if (!source && libClassRootEntries.containsKey(root) &&
+ (!classOfLibraries.containsKey(root) || !librariesToIgnore.containsAll(classOfLibraries.get(root)))) {
+ return root;
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ private Pair<DirectoryInfo, String> calcDirectoryInfo(VirtualFile root, @NotNull final List<VirtualFile> hierarchy) {
+ VirtualFile moduleContentRoot = findModuleRootInfo(hierarchy);
+ VirtualFile libraryClassRoot = findLibraryRootInfo(hierarchy, false);
+ VirtualFile librarySourceRoot = findLibraryRootInfo(hierarchy, true);
+ if (moduleContentRoot == null && libraryClassRoot == null && librarySourceRoot == null) {
+ return new Pair<DirectoryInfo, String>(null, null);
+ }
+
+ VirtualFile sourceRoot = findPackageRootInfo(hierarchy, moduleContentRoot, null, librarySourceRoot);
+
+ VirtualFile moduleSourceRoot = findPackageRootInfo(hierarchy, moduleContentRoot, null, null);
+ boolean inModuleSources = moduleSourceRoot != null;
+ boolean inLibrarySource = librarySourceRoot != null;
+ int typeId = moduleSourceRoot != null ? rootTypeId.get(moduleSourceRoot) : 0;
+
+ OrderEntry[] entries = getOrderEntries(hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
+ DirectoryInfo directoryInfo = new DirectoryInfo(contentRootOf.get(moduleContentRoot),
+ moduleContentRoot,
+ sourceRoot,
+ libraryClassRoot,
+ (byte)DirectoryInfo.createSourceRootTypeData(inModuleSources, inLibrarySource, typeId),
+ entries);
+
+ String packagePrefix = calcPackagePrefix(root, hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
+
+ return Pair.create(directoryInfo, packagePrefix);
+ }
+
+ private String calcPackagePrefix(VirtualFile root,
+ List<VirtualFile> hierarchy,
+ VirtualFile moduleContentRoot,
+ VirtualFile libraryClassRoot, VirtualFile librarySourceRoot) {
+ VirtualFile packageRoot = findPackageRootInfo(hierarchy, moduleContentRoot, libraryClassRoot, librarySourceRoot);
+ String prefix = packagePrefix.get(packageRoot);
+ if (prefix != null && packageRoot != root) {
+ assert packageRoot != null;
+ String relative = VfsUtilCore.getRelativePath(root, packageRoot, '.');
+ prefix = StringUtil.isEmpty(prefix) ? relative : prefix + '.' + relative;
+ }
+ return prefix;
+ }
+
+ @Nullable
+ private VirtualFile findPackageRootInfo(List<VirtualFile> hierarchy,
+ VirtualFile moduleContentRoot,
+ VirtualFile libraryClassRoot,
+ VirtualFile librarySourceRoot) {
+ for (VirtualFile root : hierarchy) {
+ if (moduleContentRoot != null &&
+ sourceRootOf.get(root).contains(contentRootOf.get(moduleContentRoot)) &&
+ librarySourceRoot == null) {
+ return root;
+ }
+ if (root == libraryClassRoot || root == librarySourceRoot) {
+ return root;
+ }
+ if (root == moduleContentRoot && !sourceRootOf.containsKey(root) && librarySourceRoot == null && libraryClassRoot == null) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ private LinkedHashSet<OrderEntry> getDependencyOrderEntries(List<VirtualFile> hierarchy) {
+ LinkedHashSet<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
+ for (VirtualFile root : hierarchy) {
+ orderEntries.addAll(depEntries.get(root));
+ }
+ return orderEntries;
+ }
+
+ private LinkedHashSet<OrderEntry> getLibraryOrderEntries(List<VirtualFile> hierarchy,
+ @Nullable VirtualFile libraryClassRoot,
+ @Nullable VirtualFile librarySourceRoot) {
+ LinkedHashSet<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
+ for (VirtualFile root : hierarchy) {
+ if (root == libraryClassRoot && !sourceRootOf.containsKey(root)) {
+ orderEntries.addAll(libClassRootEntries.get(root));
+ }
+ if (root == librarySourceRoot && libraryClassRoot == null) {
+ orderEntries.addAll(libSourceRootEntries.get(root));
+ }
+ if (libClassRootEntries.containsKey(root) || sourceRootOf.containsKey(root) && librarySourceRoot == null) {
+ break;
+ }
+ }
+ return orderEntries;
+ }
+
+ @Nullable
+ private ModuleSourceOrderEntry getModuleSourceEntry(List<VirtualFile> hierarchy, @NotNull VirtualFile moduleContentRoot) {
+ Module module = contentRootOf.get(moduleContentRoot);
+ for (VirtualFile root : hierarchy) {
+ if (sourceRootOf.get(root).contains(module)) {
+ return ContainerUtil.findInstance(ModuleRootManager.getInstance(module).getOrderEntries(), ModuleSourceOrderEntry.class);
+ }
+ if (libClassRootEntries.containsKey(root)) {
+ return null;
+ }
+ }
+ return null;
+ }
+
+ private OrderEntry[] getOrderEntries(List<VirtualFile> hierarchy,
+ @Nullable VirtualFile moduleContentRoot,
+ @Nullable VirtualFile libraryClassRoot,
+ @Nullable VirtualFile librarySourceRoot) {
+ Set<OrderEntry> orderEntries = ContainerUtil.newLinkedHashSet();
+ orderEntries.addAll(getLibraryOrderEntries(hierarchy, libraryClassRoot, librarySourceRoot));
+ orderEntries.addAll(getDependencyOrderEntries(hierarchy));
+ if (moduleContentRoot != null) {
+ ContainerUtil.addIfNotNull(orderEntries, getModuleSourceEntry(hierarchy, moduleContentRoot));
+ }
+ if (orderEntries.isEmpty()) {
+ return null;
+ }
+
+ OrderEntry[] array = orderEntries.toArray(new OrderEntry[orderEntries.size()]);
+ Arrays.sort(array, DirectoryInfo.BY_OWNER_MODULE);
+ return array;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
index 2695b1e..dd72da9 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/CheckboxTreeTable.java
@@ -23,6 +23,7 @@
import com.intellij.ui.treeStructure.treetable.TreeTableTree;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
@@ -56,7 +57,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
int row = tree.getRowForLocation(e.getX(), e.getY());
if (row < 0) return false;
final Object o = tree.getPathForRow(row).getLastPathComponent();
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
index d7120f5..ee44bdf 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/libraries/ui/impl/DetectedRootsChooserDialog.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.
@@ -29,6 +29,7 @@
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ComboBoxCellEditor;
import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
@@ -118,9 +119,9 @@
}
private void init(List<SuggestedChildRootInfo> suggestedRoots) {
- myDescription = "<html><body>" + ApplicationNamesInfo.getInstance().getFullProductName() +
+ myDescription = XmlStringUtil.wrapInHtml(ApplicationNamesInfo.getInstance().getFullProductName() +
" just scanned files and detected the following " + StringUtil.pluralize("root", suggestedRoots.size()) + ".<br>" +
- "Select items in the tree below or press Cancel to cancel operation.</body></html>";
+ "Select items in the tree below or press Cancel to cancel operation.");
myTreeTable = createTreeTable(suggestedRoots);
myPane = ScrollPaneFactory.createScrollPane(myTreeTable);
setTitle("Detected Roots");
@@ -165,9 +166,6 @@
}
else {
text = file.getPresentableUrl();
- if (text == null) {
- isValid = false;
- }
attributes = SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES;
icon = PlatformIcons.DIRECTORY_CLOSED_ICON;
}
@@ -176,9 +174,7 @@
if (!isValid) {
textRenderer.append("[INVALID] ", SimpleTextAttributes.ERROR_ATTRIBUTES);
}
- if (text != null) {
- textRenderer.append(text, attributes);
- }
+ textRenderer.append(text, attributes);
}
}, new ColumnInfo[]{ROOT_COLUMN, ROOT_TYPE_COLUMN});
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
index 519082f..72f9c5a 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/CommonContentEntriesEditor.java
@@ -69,7 +69,7 @@
protected ContentEntryTreeEditor myRootTreeEditor;
private MyContentEntryEditorListener myContentEntryEditorListener;
protected JPanel myEditorsPanel;
- private final Map<String, ContentEntryEditor> myEntryToEditorMap = new HashMap<String, ContentEntryEditor>();
+ protected final Map<String, ContentEntryEditor> myEntryToEditorMap = new HashMap<String, ContentEntryEditor>();
private String mySelectedEntryUrl;
private VirtualFile myLastSelectedDir = null;
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java
index dda1790..91c8405 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/ContentEntryEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -121,7 +121,7 @@
final String path = FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(myContentEntryUrl));
final int answer = Messages.showYesNoDialog(ProjectBundle.message("module.paths.remove.content.prompt", path),
ProjectBundle.message("module.paths.remove.content.title"), Messages.getQuestionIcon());
- if (answer != 0) { // no
+ if (answer != Messages.YES) { // no
return;
}
myEventDispatcher.getMulticaster().beforeEntryDeleted(this);
diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java
index edb911b..cecfc44 100644
--- a/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.java
+++ b/platform/lang-impl/src/com/intellij/openapi/roots/ui/configuration/actions/ModuleDeleteProvider.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.
@@ -57,7 +57,7 @@
private static boolean isPrimaryModule(Module[] modules) {
if (!ProjectAttachProcessor.canAttachToProject()) {
- return !PlatformUtils.isIdea();
+ return !PlatformUtils.isIdeaUltimate();
}
for (Module module : modules) {
final File moduleFile = new File(module.getModuleFilePath());
@@ -83,7 +83,7 @@
}
}, ", ");
int ret = Messages.showOkCancelDialog(getConfirmationText(modules, names), getActionTitle(), Messages.getQuestionIcon());
- if (ret != 0) return;
+ if (ret != Messages.OK) return;
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
diff --git a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java
index 24d763d..9e8a17d 100644
--- a/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java
+++ b/platform/lang-impl/src/com/intellij/openapi/util/registry/RegistryUi.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -314,7 +314,7 @@
, Messages.getQuestionIcon());
- if (r == 0) {
+ if (r == Messages.OK) {
LaterInvocator.invokeLater(new Runnable() {
@Override
public void run() {
@@ -327,7 +327,7 @@
private void restoreDefaults() {
final int r = Messages.showYesNoDialog(myContent, "Are you sure you want to revert registry settings to default values?", "Revert To Defaults", Messages.getQuestionIcon());
- if (r == 0) {
+ if (r == Messages.YES) {
Registry.getInstance().restoreDefaults();
myModel.fireChanged();
revaliateActions();
diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java
index 60a854f..c4d63da 100644
--- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java
+++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/CodeAnalysisBeforeCheckinHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,7 +23,6 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.CheckinProjectPanel;
import com.intellij.openapi.vcs.CodeSmellDetector;
@@ -114,11 +113,11 @@
VcsBundle.message("before.commit.files.contain.code.smells.edit.them.confirm.text", errorCount, warningCount),
VcsBundle.message("code.smells.error.messages.tab.name"), VcsBundle.message("code.smells.review.button"),
commitButtonText, CommonBundle.getCancelButtonText(), UIUtil.getWarningIcon());
- if (answer == 0) {
+ if (answer == Messages.YES) {
CodeSmellDetector.getInstance(myProject).showCodeSmellErrors(codeSmells);
return ReturnResult.CLOSE_WINDOW;
}
- else if (answer == 2 || answer == -1) {
+ else if (answer == Messages.CANCEL) {
return ReturnResult.CANCEL;
}
else {
@@ -142,7 +141,7 @@
"Code analysis can't be performed while IntelliJ IDEA updates the indices in background.\n" +
"You can commit the changes without running inspections, or you can wait until indices are built.",
"Code analysis is not possible right now",
- "&Wait", "&Commit", null) == DialogWrapper.OK_EXIT_CODE) {
+ "&Wait", "&Commit", null) == Messages.OK) {
return ReturnResult.CANCEL;
}
return ReturnResult.COMMIT;
@@ -164,7 +163,7 @@
LOG.error(e);
if (Messages.showOkCancelDialog(myProject,
"Code analysis failed with exception: " + e.getClass().getName() + ": " + e.getMessage(),
- "Code analysis failed", "&Commit", "&Cancel", null) == DialogWrapper.OK_EXIT_CODE) {
+ "Code analysis failed", "&Commit", "&Cancel", null) == Messages.OK) {
return ReturnResult.COMMIT;
}
return ReturnResult.CANCEL;
diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/RearrangeBeforeCheckinHandler.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/RearrangeBeforeCheckinHandler.java
new file mode 100644
index 0000000..1c19685
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/RearrangeBeforeCheckinHandler.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.vcs.checkin;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.codeInsight.actions.RearrangeCodeProcessor;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.CheckinProjectPanel;
+import com.intellij.openapi.vcs.VcsBundle;
+import com.intellij.openapi.vcs.VcsConfiguration;
+import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
+import com.sun.istack.internal.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+public class RearrangeBeforeCheckinHandler extends CheckinHandler implements CheckinMetaHandler {
+ public static final String COMMAND_NAME = CodeInsightBundle.message("process.rearrange.code.before.commit");
+
+ private final Project myProject;
+ private final CheckinProjectPanel myPanel;
+
+ public RearrangeBeforeCheckinHandler(@NotNull Project project, @NotNull CheckinProjectPanel panel) {
+ myProject = project;
+ myPanel = panel;
+ }
+
+ @Override
+ @Nullable
+ public RefreshableOnComponent getBeforeCheckinConfigurationPanel() {
+ final JCheckBox rearrangeBox = new JCheckBox(VcsBundle.message("checkbox.checkin.options.rearrange.code"));
+
+ return new RefreshableOnComponent() {
+ @Override
+ public JComponent getComponent() {
+ final JPanel panel = new JPanel(new GridLayout(1, 0));
+ panel.add(rearrangeBox);
+ return panel;
+ }
+
+ @Override
+ public void refresh() {
+ }
+
+ @Override
+ public void saveState() {
+ getSettings().REARRANGE_BEFORE_PROJECT_COMMIT = rearrangeBox.isSelected();
+ }
+
+ @Override
+ public void restoreState() {
+ rearrangeBox.setSelected(getSettings().REARRANGE_BEFORE_PROJECT_COMMIT);
+ }
+ };
+ }
+
+ private VcsConfiguration getSettings() {
+ return VcsConfiguration.getInstance(myProject);
+ }
+
+ @Override
+ public void runCheckinHandlers(final Runnable finishAction) {
+ final Runnable performCheckoutAction = new Runnable() {
+ @Override
+ public void run() {
+ FileDocumentManager.getInstance().saveAllDocuments();
+ finishAction.run();
+ }
+ };
+
+ if (VcsConfiguration.getInstance(myProject).REARRANGE_BEFORE_PROJECT_COMMIT) {
+ new RearrangeCodeProcessor(
+ myProject, BeforeCheckinHandlerUtil.getPsiFiles(myProject, myPanel.getVirtualFiles()), COMMAND_NAME, performCheckoutAction
+ ).run();
+ }
+ else {
+ performCheckoutAction.run();
+ }
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/RearrangeCheckinHandlerFactory.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/RearrangeCheckinHandlerFactory.java
new file mode 100644
index 0000000..287dcfb
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/RearrangeCheckinHandlerFactory.java
@@ -0,0 +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.openapi.vcs.checkin;
+
+import com.intellij.openapi.vcs.CheckinProjectPanel;
+import com.intellij.openapi.vcs.changes.CommitContext;
+import org.jetbrains.annotations.NotNull;
+
+public class RearrangeCheckinHandlerFactory extends CheckinHandlerFactory {
+ @Override
+ @NotNull
+ public CheckinHandler createHandler(final CheckinProjectPanel panel, CommitContext commitContext) {
+ return new RearrangeBeforeCheckinHandler(panel.getProject(), panel);
+ }
+}
diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java
index f0970d0..560760b 100644
--- a/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java
+++ b/platform/lang-impl/src/com/intellij/openapi/vcs/checkin/TodoCheckinHandler.java
@@ -30,7 +30,6 @@
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.CheckinProjectPanel;
import com.intellij.openapi.vcs.VcsBundle;
@@ -154,7 +153,7 @@
" can't be performed while " + ApplicationNamesInfo.getInstance().getFullProductName() + " updates the indices in background.\n" +
"You can commit the changes without running checks, or you can wait until indices are built.",
todoName + " is not possible right now",
- "&Wait", "&Commit", null) == DialogWrapper.OK_EXIT_CODE) {
+ "&Wait", "&Commit", null) == Messages.OK) {
return ReturnResult.CANCEL;
}
return ReturnResult.COMMIT;
diff --git a/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java b/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java
index a72f6fb..407945e 100644
--- a/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java
+++ b/platform/lang-impl/src/com/intellij/openapi/vcs/impl/ModuleVcsDetector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -225,7 +225,7 @@
if (myProject.isDisposed()) return;
final String msg = VcsBundle.message("vcs.root.remove.prompt", FileUtil.toSystemDependentName(mapping.getDirectory()), moduleName);
int rc = Messages.showYesNoDialog(myProject, msg, VcsBundle.message("vcs.root.remove.title"), Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
myVcsManager.removeDirectoryMapping(mapping);
}
}
diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java b/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java
index 60a10f3..b436d0f 100644
--- a/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java
+++ b/platform/lang-impl/src/com/intellij/packageDependencies/actions/AnalyzeDependenciesOnSpecifiedTargetHandler.java
@@ -75,8 +75,9 @@
public void analyze() {
super.analyze();
final Map<PsiFile,Set<PsiFile>> dependencies = getDependencies();
- for (PsiFile file : dependencies.keySet()) {
- final Set<PsiFile> files = dependencies.get(file);
+ for (Iterator<PsiFile> leftTreeIterator = dependencies.keySet().iterator(); leftTreeIterator.hasNext(); ) {
+ final PsiFile leftTreeFile = leftTreeIterator.next();
+ final Set<PsiFile> files = dependencies.get(leftTreeFile);
final Iterator<PsiFile> iterator = files.iterator();
while (iterator.hasNext()) {
PsiFile next = iterator.next();
@@ -85,6 +86,9 @@
iterator.remove();
}
}
+ if (files.isEmpty()) {
+ leftTreeIterator.remove();
+ }
}
}
};
diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java
index 773e099..2d73d8b 100644
--- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.java
+++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/DependenciesUsagesPanel.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.
@@ -32,7 +32,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.usageView.UsageInfo;
-import com.intellij.usages.UsageInfoToUsageConverter;
import com.intellij.util.Consumer;
import javax.swing.*;
@@ -110,7 +109,7 @@
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- showUsages(new UsageInfoToUsageConverter.TargetElementsDescriptor(_elementsToSearch), finalUsages);
+ showUsages(_elementsToSearch, finalUsages);
}
}, ModalityState.stateForComponent(DependenciesUsagesPanel.this));
}
diff --git a/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java b/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java
index 125a4e3..8f4084b 100644
--- a/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.java
+++ b/platform/lang-impl/src/com/intellij/packageDependencies/ui/UsagesPanel.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.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
+import com.intellij.psi.PsiElement;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.*;
import com.intellij.util.Alarm;
@@ -64,12 +65,12 @@
}
}
- protected void showUsages(@NotNull UsageInfoToUsageConverter.TargetElementsDescriptor descriptor, @NotNull UsageInfo[] usageInfos) {
+ protected void showUsages(@NotNull PsiElement[] primaryElements, @NotNull UsageInfo[] usageInfos) {
if (myCurrentUsageView != null) {
Disposer.dispose(myCurrentUsageView);
}
try {
- Usage[] usages = UsageInfoToUsageConverter.convert(descriptor, usageInfos);
+ Usage[] usages = UsageInfoToUsageConverter.convert(primaryElements, usageInfos);
UsageViewPresentation presentation = new UsageViewPresentation();
presentation.setCodeUsagesString(getCodeUsagesString());
myCurrentUsageView = UsageViewManager.getInstance(myProject).createUsageView(UsageTarget.EMPTY_ARRAY, usages, presentation, null);
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManagerImpl.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManagerImpl.java
index 65ad22d..de8ee09 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/InspectionProfileManagerImpl.java
@@ -67,7 +67,7 @@
private final InspectionToolRegistrar myRegistrar;
private final SchemesManager<Profile, InspectionProfileImpl> mySchemesManager;
private final AtomicBoolean myProfilesAreInitialized = new AtomicBoolean(false);
- private final SeverityRegistrar mySeverityRegistrar;
+ private final SeverityRegistrar mySeverityRegistrar = new SeverityRegistrar();
protected static final Logger LOG = Logger.getInstance("#com.intellij.profile.DefaultProfileManager");
@@ -77,37 +77,36 @@
public InspectionProfileManagerImpl(InspectionToolRegistrar registrar, SchemesManagerFactory schemesManagerFactory) {
myRegistrar = registrar;
- mySeverityRegistrar = new SeverityRegistrar();
registerProvidedSeverities();
SchemeProcessor<InspectionProfileImpl> processor = new BaseSchemeProcessor<InspectionProfileImpl>() {
@Override
- public InspectionProfileImpl readScheme(final Document document) {
+ public InspectionProfileImpl readScheme(@NotNull final Document document) {
InspectionProfileImpl profile = new InspectionProfileImpl(InspectionProfileLoadUtil.getProfileName(document), myRegistrar, InspectionProfileManagerImpl.this);
read(profile, document.getRootElement());
return profile;
}
@Override
- public boolean shouldBeSaved(final InspectionProfileImpl scheme) {
+ public boolean shouldBeSaved(@NotNull final InspectionProfileImpl scheme) {
return scheme.wasInitialized();
}
@Override
- public Document writeScheme(final InspectionProfileImpl scheme) throws WriteExternalException {
+ public Document writeScheme(@NotNull final InspectionProfileImpl scheme) throws WriteExternalException {
return scheme.saveToDocument();
}
@Override
- public void onSchemeAdded(final InspectionProfileImpl scheme) {
+ public void onSchemeAdded(@NotNull final InspectionProfileImpl scheme) {
updateProfileImpl(scheme);
fireProfileChanged(scheme);
onProfilesChanged();
}
@Override
- public void onSchemeDeleted(final InspectionProfileImpl scheme) {
+ public void onSchemeDeleted(@NotNull final InspectionProfileImpl scheme) {
onProfilesChanged();
}
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProfilesComboBox.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProfilesComboBox.java
index 9597820..dbb0712 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProfilesComboBox.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/ProfilesComboBox.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -21,7 +21,6 @@
import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.codeInspection.ex.InspectionToolRegistrar;
import com.intellij.icons.AllIcons;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Condition;
import com.intellij.profile.ApplicationProfileManager;
@@ -82,7 +81,7 @@
if (profileManager instanceof ProjectProfileManager && item instanceof Profile && ((Profile)item).isLocal()) {
if (Messages.showOkCancelDialog(InspectionsBundle.message("inspection.new.profile.ide.to.project.warning.message"),
InspectionsBundle.message("inspection.new.profile.ide.to.project.warning.title"),
- Messages.getErrorIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getErrorIcon()) == Messages.OK) {
final String newName = Messages.showInputDialog(InspectionsBundle.message("inspection.new.profile.text"),
InspectionsBundle.message("inspection.new.profile.dialog.title"),
Messages.getInformationIcon());
diff --git a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
index 1b63653..8b980cf 100644
--- a/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.java
+++ b/platform/lang-impl/src/com/intellij/profile/codeInspection/ui/SingleInspectionProfilePanel.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.
@@ -64,6 +64,7 @@
import com.intellij.util.containers.Convertor;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -609,7 +610,7 @@
}
static String renderSeverity(HighlightSeverity severity) {
- return StringUtil.capitalizeWords(severity.toString().toLowerCase(), true);
+ return StringUtil.capitalizeWords(severity.getName().toLowerCase(), true);
}
private void toggleToolNode(final InspectionConfigTreeNode toolNode) {
@@ -756,7 +757,7 @@
catch (IOException e2) {
try {
//noinspection HardCodedStringLiteral
- myBrowser.read(new StringReader("<html><body><b>" + UNDER_CONSTRUCTION + "</b></body></html>"), null);
+ myBrowser.read(new StringReader(XmlStringUtil.wrapInHtml("<b>" + UNDER_CONSTRUCTION + "</b>")), null);
}
catch (IOException e1) {
//Can't be
@@ -1006,7 +1007,7 @@
final Set<HighlightSeverity> severities = ((InspectionProfileImpl)selectedProfile).getUsedSeverities();
for (Iterator<HighlightSeverity> iterator = severities.iterator(); iterator.hasNext();) {
HighlightSeverity severity = iterator.next();
- if (registrar.isSeverityValid(severity.toString())) {
+ if (registrar.isSeverityValid(severity.getName())) {
iterator.remove();
}
}
@@ -1014,9 +1015,9 @@
if (!severities.isEmpty()) {
final SeverityRegistrar oppositeRegister = ((SeverityProvider)selectedProfile.getProfileManager()).getSeverityRegistrar();
for (HighlightSeverity severity : severities) {
- final TextAttributesKey attributesKey = TextAttributesKey.find(severity.toString());
+ final TextAttributesKey attributesKey = TextAttributesKey.find(severity.getName());
final TextAttributes textAttributes = oppositeRegister.getTextAttributesBySeverity(severity);
- LOG.assertTrue(textAttributes != null, severity.toString());
+ LOG.assertTrue(textAttributes != null, severity);
HighlightInfoType.HighlightInfoTypeImpl info = new HighlightInfoType.HighlightInfoTypeImpl(severity, attributesKey);
registrar.registerSeverity(new SeverityRegistrar.SeverityBasedTextAttributes(textAttributes.clone(), info),
textAttributes.getErrorStripeColor());
diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java
index 3bf3534..4f54fa7 100644
--- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java
+++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/ArrangementEngine.java
@@ -53,12 +53,25 @@
*/
public class ArrangementEngine {
+ /**
+ * Arranges given PSI root contents that belong to the given ranges.
+ * <b>Note:</b> After arrangement editor foldings we'll be preserved.
+ *
+ * @param editor
+ * @param file target PSI root
+ * @param ranges target ranges to use within the given root
+ */
public void arrange(@NotNull final Editor editor, @NotNull PsiFile file, Collection<TextRange> ranges) {
- arrange(file, ranges, null);
- // This should be uncommented as soon as cdr pushed fixes for range markers processing.
- //arrange(file, ranges, new RestoreFoldArrangementCallback(editor));
+ arrange(file, ranges, new RestoreFoldArrangementCallback(editor));
}
+ /**
+ * Arranges given PSI root contents that belong to the given ranges.
+ * <b>Note:</b> Editor foldings are not expected to be preserved.
+ *
+ * @param file target PSI root
+ * @param ranges target ranges to use within the given root
+ */
public void arrange(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges) {
arrange(file, ranges, null);
}
@@ -273,14 +286,18 @@
for (int i = 0; i < arranged.size() && !dependent.isEmpty(); i++) {
E e = arranged.get(i);
+ List<E> shouldBeAddedAfterCurrentElement = ContainerUtil.newArrayList();
+
for (Iterator<Pair<Set<ArrangementEntry>, E>> iterator = dependent.iterator(); iterator.hasNext(); ) {
Pair<Set<ArrangementEntry>, E> pair = iterator.next();
pair.first.remove(e);
if (pair.first.isEmpty()) {
iterator.remove();
- arranged.add(i + 1, pair.second);
+ shouldBeAddedAfterCurrentElement.add(pair.second);
}
}
+
+ arranged.addAll(i + 1, shouldBeAddedAfterCurrentElement);
}
return arranged;
diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/RestoreFoldArrangementCallback.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/RestoreFoldArrangementCallback.java
index 8f93afe..b23b79c 100644
--- a/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/RestoreFoldArrangementCallback.java
+++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/arrangement/engine/RestoreFoldArrangementCallback.java
@@ -18,16 +18,10 @@
import com.intellij.codeInsight.folding.CodeFoldingManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
-import com.intellij.openapi.fileEditor.impl.text.CodeFoldingState;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.TextRange;
-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.Collections;
-import java.util.Comparator;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -37,34 +31,48 @@
public class RestoreFoldArrangementCallback implements ArrangementCallback {
@NotNull private final Editor myEditor;
- @Nullable private final CodeFoldingState myCodeFoldingState;
public RestoreFoldArrangementCallback(@NotNull Editor editor) {
myEditor = editor;
-
- Project project = editor.getProject();
- if (project == null) {
- myCodeFoldingState = null;
- }
- else {
- final CodeFoldingManager foldingManager = CodeFoldingManager.getInstance(editor.getProject());
- myCodeFoldingState = foldingManager.saveFoldingState(editor);
- }
}
@Override
public void afterArrangement(@NotNull final List<ArrangementMoveInfo> moveInfos) {
// Restore state for the PSI elements not affected by arrangement.
Project project = myEditor.getProject();
- if (myCodeFoldingState != null && project != null) {
+ if (project != null) {
+ final FoldRegion[] regions = myEditor.getFoldingModel().getAllFoldRegions();
+ final List<FoldRegionInfo> foldRegionsInfo = new ArrayList<FoldRegionInfo>();
+ for (FoldRegion region : regions) {
+ final FoldRegionInfo info = new FoldRegionInfo(region.getStartOffset(), region.getEndOffset(), region.isExpanded());
+ foldRegionsInfo.add(info);
+ }
+
final CodeFoldingManager foldingManager = CodeFoldingManager.getInstance(project);
foldingManager.updateFoldRegions(myEditor);
myEditor.getFoldingModel().runBatchFoldingOperation(new Runnable() {
@Override
public void run() {
- foldingManager.restoreFoldingState(myEditor, myCodeFoldingState);
+ for (FoldRegionInfo info : foldRegionsInfo) {
+ final FoldRegion foldRegion = foldingManager.findFoldRegion(myEditor, info.myStart, info.myEnd);
+ if (foldRegion != null) {
+ foldRegion.setExpanded(info.myIsExpanded);
+ }
+ }
}
});
}
}
+
+ private static class FoldRegionInfo {
+ private int myStart;
+ private int myEnd;
+ private boolean myIsExpanded;
+
+ private FoldRegionInfo(int start, int end, boolean expanded) {
+ myStart = start;
+ myEnd = end;
+ myIsExpanded = expanded;
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
index 70f3e8e..980cd62 100644
--- a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
@@ -15,7 +15,6 @@
*/
package com.intellij.psi.formatter;
-import com.intellij.codeInsight.actions.ReformatAndOptimizeImportsProcessor;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
@@ -40,7 +39,7 @@
public class FormatterUtil {
public static final Collection<String> FORMATTER_ACTION_NAMES = Collections.unmodifiableCollection(ContainerUtilRt.newHashSet(
- ReformatAndOptimizeImportsProcessor.COMMAND_NAME, ReformatCodeProcessor.COMMAND_NAME, ReformatBeforeCheckinHandler.COMMAND_NAME
+ ReformatCodeProcessor.COMMAND_NAME, ReformatBeforeCheckinHandler.COMMAND_NAME
));
private FormatterUtil() {
diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java
index 0cf0d3a..0dad3d0 100644
--- a/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormattingDocumentModelImpl.java
@@ -64,7 +64,7 @@
if (PsiDocumentManager.getInstance(file.getProject()).isUncommited(document)) {
LOG.error("Document is uncommitted");
}
- if (!document.getText().equals(file.getText())) {
+ if (!file.textMatches(document.getImmutableCharSequence())) {
LOG.error("Document and psi file texts should be equal: file " + file);
}
return new FormattingDocumentModelImpl(document, file);
diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/WhiteSpaceFormattingStrategyFactory.java b/platform/lang-impl/src/com/intellij/psi/formatter/WhiteSpaceFormattingStrategyFactory.java
index 77acdd4..4d268f8 100644
--- a/platform/lang-impl/src/com/intellij/psi/formatter/WhiteSpaceFormattingStrategyFactory.java
+++ b/platform/lang-impl/src/com/intellij/psi/formatter/WhiteSpaceFormattingStrategyFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
+import com.intellij.reference.SoftReference;
import com.intellij.util.PatchedWeakReference;
import org.jetbrains.annotations.NotNull;
@@ -74,11 +75,9 @@
@NotNull
public static Collection<WhiteSpaceFormattingStrategy> getAllStrategies() {
final WeakReference<Collection<WhiteSpaceFormattingStrategy>> reference = myCachedStrategies.get();
- if (reference != null) {
- final Collection<WhiteSpaceFormattingStrategy> strategies = reference.get();
- if (strategies != null) {
- return strategies;
- }
+ final Collection<WhiteSpaceFormattingStrategy> strategies = SoftReference.dereference(reference);
+ if (strategies != null) {
+ return strategies;
}
final Collection<Language> languages = Language.getRegisteredLanguages();
if (languages == null) {
diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java b/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java
index 90046df..fda8657 100644
--- a/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java
+++ b/platform/lang-impl/src/com/intellij/psi/formatter/common/InjectedLanguageBlockBuilder.java
@@ -107,11 +107,12 @@
}
}
};
- InjectedLanguageUtil.enumerate(injectionHost.getPsi(), injectedPsiVisitor);
+ final PsiElement injectionHostPsi = injectionHost.getPsi();
+ InjectedLanguageUtil.enumerate(injectionHostPsi, injectionHostPsi.getContainingFile(), false, injectedPsiVisitor);
if (injectedFile[0] != null) {
final Language childLanguage = injectedFile[0].getLanguage();
- final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(childLanguage, injectionHost.getPsi());
+ final FormattingModelBuilder builder = LanguageFormatting.INSTANCE.forContext(childLanguage, injectionHostPsi);
if (builder != null) {
final int startOffset = injectedRangeInsideHost.get().getStartOffset();
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
index 174903b..5168d35 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/DocumentCommitThread.java
@@ -45,7 +45,9 @@
import javax.swing.*;
import java.text.SimpleDateFormat;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
public class DocumentCommitThread extends DocumentCommitProcessor implements Runnable, Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DocumentCommitThread");
@@ -143,7 +145,7 @@
private final StringBuilder log = new StringBuilder();
@Override
- public void log(@NonNls String msg, CommitTask task, boolean synchronously, @NonNls Object... args) {
+ public void log(@NonNls String msg, @Nullable CommitTask task, boolean synchronously, @NonNls Object... args) {
if (true) return;
String indent = new SimpleDateFormat("mm:ss:SSSS").format(new Date()) +
@@ -400,9 +402,16 @@
public void run() {
ApplicationManager.getApplication().assertReadAccessAllowed();
if (project.isDisposed()) return;
+
final PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project);
+ if (documentManager.isCommitted(document)) return;
+
FileViewProvider viewProvider = documentManager.getCachedViewProvider(document);
- if (viewProvider == null) return;
+ if (viewProvider == null) {
+ finishProcessors.add(handleCommitWithoutPsi(documentManager, document, task, synchronously));
+ return;
+ }
+
List<PsiFile> psiFiles = viewProvider.getAllFiles();
for (PsiFile file : psiFiles) {
if (file.isValid()) {
@@ -482,6 +491,25 @@
return finishRunnable;
}
+ private Processor<Document> handleCommitWithoutPsi(final PsiDocumentManagerImpl documentManager,
+ Document document,
+ final CommitTask task, final boolean synchronously) {
+ final long startDocModificationTimeStamp = document.getModificationStamp();
+ return new Processor<Document>() {
+ @Override
+ public boolean process(Document document) {
+ log("Finishing without PSI", task, synchronously, document.getModificationStamp(), startDocModificationTimeStamp);
+ if (document.getModificationStamp() != startDocModificationTimeStamp ||
+ documentManager.getCachedViewProvider(document) != null) {
+ return false;
+ }
+
+ documentManager.handleCommitWithoutPsi(document);
+ return true;
+ }
+ };
+ }
+
private boolean processAll(final Processor<CommitTask> processor) {
final boolean[] result = {true};
synchronized (documentsToCommit) {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
index cfe7594..d96133f 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/PsiDocumentManagerImpl.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 com.intellij.AppTopics;
import com.intellij.injected.editor.DocumentWindow;
-import com.intellij.injected.editor.EditorWindow;
+import com.intellij.injected.editor.EditorWindowImpl;
import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.SettingsSavingComponent;
@@ -44,7 +44,8 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import java.util.*;
+import java.util.Collection;
+import java.util.List;
//todo listen & notifyListeners readonly events?
public class PsiDocumentManagerImpl extends PsiDocumentManagerBase implements SettingsSavingComponent {
@@ -136,7 +137,7 @@
protected boolean finishCommitInWriteAction(@NotNull Document document,
@NotNull List<Processor<Document>> finishProcessors,
boolean synchronously) {
- EditorWindow.disposeInvalidEditors(); // in write action
+ EditorWindowImpl.disposeInvalidEditors(); // in write action
return super.finishCommitInWriteAction(document, finishProcessors, synchronously);
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java
index eeb09fb..1d9ef8c 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.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,7 +37,6 @@
import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.PsiTreeChangeEventImpl;
import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl;
-import com.intellij.util.FileContentUtil;
import com.intellij.util.FileContentUtilCore;
import com.intellij.util.messages.MessageBusConnection;
import org.jetbrains.annotations.NotNull;
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 83df029..43bc2fa 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
@@ -26,6 +26,7 @@
import com.intellij.util.containers.MultiMap;
import com.intellij.util.indexing.*;
import com.intellij.util.io.DataExternalizer;
+import com.intellij.util.io.IOUtil;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
@@ -129,7 +130,7 @@
@Override
public Key read(DataInput in) throws IOException {
boolean isInclude = in.readBoolean();
- return isInclude ? new IncludeKey(in.readUTF()) : new FileKey(in.readInt());
+ return isInclude ? IncludeKey.read(in) : new FileKey(in.readInt());
}
};
}
@@ -192,7 +193,7 @@
@Override
public int getVersion() {
- return 1;
+ return 3;
}
interface Key {
@@ -202,6 +203,7 @@
}
private static class IncludeKey implements Key {
+ private static final byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
private final String myFileName;
public IncludeKey(String fileName) {
@@ -215,7 +217,9 @@
@Override
public void writeValue(DataOutput out) throws IOException {
- out.writeUTF(myFileName);
+ synchronized (myBuffer) {
+ IOUtil.writeUTFFast(myBuffer, out, myFileName);
+ }
}
@Override
@@ -227,6 +231,12 @@
public boolean equals(Object obj) {
return obj instanceof IncludeKey && ((IncludeKey)obj).myFileName.equals(myFileName);
}
+
+ static Key read(DataInput in) throws IOException {
+ synchronized (myBuffer){
+ return new IncludeKey(IOUtil.readUTFFast(myBuffer, in));
+ }
+ }
}
private static class FileKey implements Key {
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java
index 730baed..0e6d59f 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/include/FileIncludeManagerImpl.java
@@ -18,7 +18,6 @@
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileTypes;
-import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
@@ -38,6 +37,7 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,7 +56,7 @@
private final IncludeCacheHolder myIncludedHolder = new IncludeCacheHolder("compile time includes", "runtime includes") {
@Override
protected VirtualFile[] computeFiles(final PsiFile file, final boolean compileTimeOnly) {
- final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
+ final Set<VirtualFile> files = new THashSet<VirtualFile>();
processIncludes(file, new Processor<FileIncludeInfo>() {
@Override
public boolean process(FileIncludeInfo info) {
@@ -87,7 +87,7 @@
private final IncludeCacheHolder myIncludingHolder = new IncludeCacheHolder("compile time contexts", "runtime contexts") {
@Override
protected VirtualFile[] computeFiles(PsiFile context, boolean compileTimeOnly) {
- final ArrayList<VirtualFile> files = new ArrayList<VirtualFile>();
+ final Set<VirtualFile> files = new THashSet<VirtualFile>();
processIncludingFiles(context, new Processor<Pair<VirtualFile, FileIncludeInfo>>() {
@Override
public boolean process(Pair<VirtualFile, FileIncludeInfo> virtualFileFileIncludeInfoPair) {
@@ -136,8 +136,13 @@
@Override
public VirtualFile[] getIncludedFiles(@NotNull VirtualFile file, boolean compileTimeOnly) {
+ return getIncludedFiles(file, compileTimeOnly, false);
+ }
+
+ @Override
+ public VirtualFile[] getIncludedFiles(@NotNull VirtualFile file, boolean compileTimeOnly, boolean recursively) {
if (file instanceof VirtualFileWithId) {
- return myIncludedHolder.getAllFiles(file, compileTimeOnly);
+ return myIncludedHolder.getAllFiles(file, compileTimeOnly, recursively);
}
else {
return VirtualFile.EMPTY_ARRAY;
@@ -146,7 +151,7 @@
@Override
public VirtualFile[] getIncludingFiles(@NotNull VirtualFile file, boolean compileTimeOnly) {
- return myIncludingHolder.getAllFiles(file, compileTimeOnly);
+ return myIncludingHolder.getAllFiles(file, compileTimeOnly, false);
}
@Override
@@ -190,27 +195,37 @@
RUNTIME_KEY = Key.create(runtimeKey);
}
- private VirtualFile[] getAllFiles(@NotNull VirtualFile file, boolean compileTimeOnly) {
- Set<VirtualFile> result = new HashSet<VirtualFile>();
- getFilesRecursively(file, compileTimeOnly, result);
- return VfsUtilCore.toVirtualFileArray(result);
+ @NotNull
+ private VirtualFile[] getAllFiles(@NotNull VirtualFile file, boolean compileTimeOnly, boolean recursively) {
+ if (recursively) {
+ Set<VirtualFile> result = new HashSet<VirtualFile>();
+ getAllFilesRecursively(file, compileTimeOnly, result);
+ return VfsUtilCore.toVirtualFileArray(result);
+ }
+ return getFiles(file, compileTimeOnly);
}
- private void getFilesRecursively(@NotNull VirtualFile file, boolean compileTimeOnly, Set<VirtualFile> result) {
- if (result.contains(file)) return;
- PsiFile psiFile = myPsiManager.findFile(file);
- if (psiFile == null) return;
- VirtualFile[] includes = compileTimeOnly
- ? myCachedValuesManager.getParameterizedCachedValue(psiFile, COMPILE_TIME_KEY, COMPILE_TIME_PROVIDER, false, psiFile)
- : myCachedValuesManager.getParameterizedCachedValue(psiFile, RUNTIME_KEY, RUNTIME_PROVIDER, false, psiFile);
+ private void getAllFilesRecursively(@NotNull VirtualFile file, boolean compileTimeOnly, Set<VirtualFile> result) {
+ if (!result.add(file)) return;
+ VirtualFile[] includes = getFiles(file, compileTimeOnly);
if (includes.length != 0) {
- result.addAll(Arrays.asList(includes));
for (VirtualFile include : includes) {
- getFilesRecursively(include, compileTimeOnly, result);
+ getAllFilesRecursively(include, compileTimeOnly, result);
}
}
}
+ private VirtualFile[] getFiles(@NotNull VirtualFile file, boolean compileTimeOnly) {
+ PsiFile psiFile = myPsiManager.findFile(file);
+ if (psiFile == null) {
+ return VirtualFile.EMPTY_ARRAY;
+ }
+ if (compileTimeOnly) {
+ return myCachedValuesManager.getParameterizedCachedValue(psiFile, COMPILE_TIME_KEY, COMPILE_TIME_PROVIDER, false, psiFile);
+ }
+ return myCachedValuesManager.getParameterizedCachedValue(psiFile, RUNTIME_KEY, RUNTIME_PROVIDER, false, psiFile);
+ }
+
protected abstract VirtualFile[] computeFiles(PsiFile file, boolean compileTimeOnly);
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/LightPsiFileImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/LightPsiFileImpl.java
index de7c965..7d25327 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/LightPsiFileImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/LightPsiFileImpl.java
@@ -258,7 +258,7 @@
@Override
@NotNull
public char[] textToCharArray() {
- return CharArrayUtil.fromSequenceStrict(getViewProvider().getContents());
+ return CharArrayUtil.fromSequence(getViewProvider().getContents());
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java
index af96331..8e33511 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/PostprocessReformattingAspect.java
@@ -50,6 +50,7 @@
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.text.CharArrayUtil;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
@@ -65,6 +66,8 @@
private volatile int myDisabledCounter = 0;
private final Set<FileViewProvider> myUpdatedProviders = new HashSet<FileViewProvider>();
private final AtomicInteger myPostponedCounter = new AtomicInteger();
+ private static final Key<Throwable> REFORMAT_ORIGINATOR = Key.create("REFORMAT_ORIGINATOR");
+ private static final boolean STORE_REFORMAT_ORIGINATOR_STACKTRACE = ApplicationManager.getApplication().isInternal();
public PostprocessReformattingAspect(Project project, PsiManager psiManager, TreeAspect treeAspect,final CommandProcessor processor) {
myProject = project;
@@ -257,19 +260,23 @@
finally {
myUpdatedProviders.remove(viewProvider);
myReformatElements.remove(viewProvider);
+ viewProvider.putUserData(REFORMAT_ORIGINATOR, null);
}
}
});
}
- public boolean isViewProviderLocked(final FileViewProvider fileViewProvider) {
+ public boolean isViewProviderLocked(@NotNull FileViewProvider fileViewProvider) {
return myReformatElements.containsKey(fileViewProvider);
}
- public void beforeDocumentChanged(FileViewProvider viewProvider) {
+ public void beforeDocumentChanged(@NotNull FileViewProvider viewProvider) {
if (isViewProviderLocked(viewProvider)) {
- throw new RuntimeException("Document is locked by write PSI operations. " +
- "Use PsiDocumentManager.doPostponedOperationsAndUnblockDocument() to commit PSI changes to the document.");
+ Throwable cause = viewProvider.getUserData(REFORMAT_ORIGINATOR);
+ @NonNls String message = "Document is locked by write PSI operations. " +
+ "Use PsiDocumentManager.doPostponedOperationsAndUnblockDocument() to commit PSI changes to the document." +
+ (cause == null ? "" : " See cause stacktrace for the reason to lock.");
+ throw cause == null ? new RuntimeException(message): new RuntimeException(message, cause);
}
postponedFormatting(viewProvider);
}
@@ -278,7 +285,7 @@
return project.getComponent(PostprocessReformattingAspect.class);
}
- private void postponeFormatting(final FileViewProvider viewProvider, final ASTNode child) {
+ private void postponeFormatting(@NotNull FileViewProvider viewProvider, @NotNull ASTNode child) {
if (!CodeEditUtil.isNodeGenerated(child) && child.getElementType() != TokenType.WHITE_SPACE) {
final int oldIndent = CodeEditUtil.getOldIndentation(child);
LOG.assertTrue(oldIndent >= 0,
@@ -288,6 +295,9 @@
if (list == null) {
list = new ArrayList<ASTNode>();
myReformatElements.put(viewProvider, list);
+ if (STORE_REFORMAT_ORIGINATOR_STACKTRACE) {
+ viewProvider.putUserData(REFORMAT_ORIGINATOR, new Throwable());
+ }
}
list.add(child);
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
index a38266e..31502db 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleManagerImpl.java
@@ -34,6 +34,7 @@
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.Indent;
+import com.intellij.psi.formatter.FormatterUtil;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
@@ -191,9 +192,13 @@
caretKeeper = new CaretPositionKeeper(editor);
}
+ Collection<TextRange> correctedRanges = FormatterUtil.isFormatterCalledExplicitly()
+ ? removeEndingWhiteSpaceFromEachRange(file, ranges)
+ : ranges;
+
final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(getProject());
List<RangeFormatInfo> infos = new ArrayList<RangeFormatInfo>();
- for (TextRange range : ranges) {
+ for (TextRange range : correctedRanges) {
final PsiElement start = findElementInTreeWithFormatterEnabled(file, range.getStartOffset());
final PsiElement end = findElementInTreeWithFormatterEnabled(file, range.getEndOffset());
if (start != null && !start.isValid()) {
@@ -213,7 +218,7 @@
}
FormatTextRanges formatRanges = new FormatTextRanges();
- for (TextRange range : ranges) {
+ for (TextRange range : correctedRanges) {
formatRanges.add(range, true);
}
codeFormatter.processText(file, formatRanges, true);
@@ -233,6 +238,30 @@
}
}
+ @NotNull
+ private Collection<TextRange> removeEndingWhiteSpaceFromEachRange(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges) {
+ Collection<TextRange> result = new ArrayList<TextRange>();
+
+ for (TextRange range : ranges) {
+ int rangeStart = range.getStartOffset();
+ int rangeEnd = range.getEndOffset();
+
+ PsiElement lastElementInRange = findElementInTreeWithFormatterEnabled(file, range.getEndOffset());
+ if (lastElementInRange instanceof PsiWhiteSpace
+ && rangeStart < lastElementInRange.getTextRange().getStartOffset())
+ {
+ PsiElement prev = lastElementInRange.getPrevSibling();
+ if (prev != null) {
+ rangeEnd = prev.getTextRange().getEndOffset();
+ }
+ }
+
+ result.add(new TextRange(rangeStart, rangeEnd));
+ }
+
+ return result;
+ }
+
private PsiElement reformatRangeImpl(final PsiElement element,
final int startOffset,
final int endOffset,
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java
index 8124814..546a590 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/codeStyle/CodeStyleSchemesImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -52,22 +52,22 @@
public CodeStyleSchemesImpl(SchemesManagerFactory schemesManagerFactory) {
SchemeProcessor<CodeStyleSchemeImpl> processor = new BaseSchemeProcessor<CodeStyleSchemeImpl>() {
@Override
- public CodeStyleSchemeImpl readScheme(final Document schemeContent) throws IOException, JDOMException, InvalidDataException {
+ public CodeStyleSchemeImpl readScheme(@NotNull final Document schemeContent) throws IOException, JDOMException, InvalidDataException {
return CodeStyleSchemeImpl.readScheme(schemeContent);
}
@Override
- public Document writeScheme(final CodeStyleSchemeImpl scheme) throws WriteExternalException {
+ public Document writeScheme(@NotNull final CodeStyleSchemeImpl scheme) throws WriteExternalException {
return scheme.saveToDocument();
}
@Override
- public boolean shouldBeSaved(final CodeStyleSchemeImpl scheme) {
+ public boolean shouldBeSaved(@NotNull final CodeStyleSchemeImpl scheme) {
return !scheme.isDefault();
}
@Override
- public void initScheme(final CodeStyleSchemeImpl scheme) {
+ public void initScheme(@NotNull final CodeStyleSchemeImpl scheme) {
scheme.init(CodeStyleSchemesImpl.this);
}
};
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ClassMapCachingNulls.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ClassMapCachingNulls.java
index 016e91f..6d7d1ed 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ClassMapCachingNulls.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ClassMapCachingNulls.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,7 +15,6 @@
*/
package com.intellij.psi.impl.source.tree.injected;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -72,10 +71,10 @@
assert value.length != 0;
result = new ArrayList<T>(Arrays.asList(value));
}
- for (final Class aClass1 : ReflectionCache.getInterfaces(aClass)) {
+ for (final Class aClass1 : aClass.getInterfaces()) {
result = addFromUpper(result, aClass1);
}
- final Class superclass = ReflectionCache.getSuperClass(aClass);
+ final Class superclass = aClass.getSuperclass();
if (superclass != null) {
result = addFromUpper(result, superclass);
}
@@ -99,6 +98,10 @@
return value;
}
+ public Map<Class, T[]> getBackingMap() {
+ return myBackingMap;
+ }
+
public void clearCache() {
myMap.clear();
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java
index ccdb32d..7c7945d 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageManagerImpl.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.
@@ -22,6 +22,7 @@
import com.intellij.concurrency.JobLauncher;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.DocumentWindowImpl;
+import com.intellij.injected.editor.EditorWindowImpl;
import com.intellij.injected.editor.VirtualFileWindow;
import com.intellij.lang.Language;
import com.intellij.lang.injection.InjectedLanguageManager;
@@ -36,12 +37,12 @@
import com.intellij.openapi.extensions.ExtensionPointListener;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.extensions.PluginDescriptor;
+import com.intellij.openapi.extensions.impl.ExtensionPointImpl;
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.util.Pair;
-import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
@@ -49,10 +50,9 @@
import com.intellij.psi.impl.PsiDocumentManagerBase;
import com.intellij.psi.impl.source.resolve.FileContextUtil;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Processor;
import com.intellij.util.SmartList;
-import com.intellij.util.containers.ConcurrentHashMap;
+import com.intellij.util.containers.ConcurrentList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -60,18 +60,14 @@
import org.jetbrains.annotations.TestOnly;
import java.util.*;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicReference;
/**
* @author cdr
*/
-public class InjectedLanguageManagerImpl extends InjectedLanguageManager implements Disposable{
+public class InjectedLanguageManagerImpl extends InjectedLanguageManager implements Disposable {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl");
private final Project myProject;
private final DumbService myDumbService;
- private final AtomicReference<MultiHostInjector> myPsiManagerRegisteredInjectorsAdapter = new AtomicReference<MultiHostInjector>();
private volatile DaemonProgressIndicator myProgress;
public static InjectedLanguageManagerImpl getInstanceImpl(Project project) {
@@ -83,30 +79,30 @@
myDumbService = dumbService;
final ExtensionPoint<MultiHostInjector> multiPoint = Extensions.getArea(project).getExtensionPoint(MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME);
- multiPoint.addExtensionPointListener(new ExtensionPointListener<MultiHostInjector>() {
+ ((ExtensionPointImpl<MultiHostInjector>)multiPoint).addExtensionPointListener(new ExtensionPointListener<MultiHostInjector>() {
@Override
public void extensionAdded(@NotNull MultiHostInjector injector, @Nullable PluginDescriptor pluginDescriptor) {
- registerMultiHostInjector(injector);
+ clearInjectorCache();
}
@Override
public void extensionRemoved(@NotNull MultiHostInjector injector, @Nullable PluginDescriptor pluginDescriptor) {
- unregisterMultiHostInjector(injector);
+ clearInjectorCache();
}
- },this);
+ }, false, this);
final ExtensionPointListener<LanguageInjector> myListener = new ExtensionPointListener<LanguageInjector>() {
@Override
public void extensionAdded(@NotNull LanguageInjector extension, @Nullable PluginDescriptor pluginDescriptor) {
- psiManagerInjectorsChanged();
+ clearInjectorCache();
}
@Override
public void extensionRemoved(@NotNull LanguageInjector extension, @Nullable PluginDescriptor pluginDescriptor) {
- psiManagerInjectorsChanged();
+ clearInjectorCache();
}
};
final ExtensionPoint<LanguageInjector> psiManagerPoint = Extensions.getRootArea().getExtensionPoint(LanguageInjector.EXTENSION_POINT_NAME);
- psiManagerPoint.addExtensionPointListener(myListener,this);
+ ((ExtensionPointImpl<LanguageInjector>)psiManagerPoint).addExtensionPointListener(myListener, false, this);
myProgress = new DaemonProgressIndicator();
project.getMessageBus().connect(this).subscribe(DaemonCodeAnalyzer.DAEMON_EVENT_TOPIC, new DaemonCodeAnalyzer.DaemonListenerAdapter() {
@Override
@@ -118,6 +114,7 @@
@Override
public void dispose() {
+ EditorWindowImpl.disposeInvalidEditors();
}
@Override
@@ -129,8 +126,7 @@
final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument);
if (hostPsiFile == null) return;
- final CopyOnWriteArrayList<DocumentWindow> injected =
- (CopyOnWriteArrayList<DocumentWindow>)InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
+ final ConcurrentList<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
if (injected.isEmpty()) return;
if (myProgress.isCanceled()) {
@@ -204,22 +200,6 @@
}
}
- public void psiManagerInjectorsChanged() {
- LanguageInjector[] extensions = Extensions.getExtensions(LanguageInjector.EXTENSION_POINT_NAME);
- if (extensions.length == 0) {
- MultiHostInjector prev = myPsiManagerRegisteredInjectorsAdapter.getAndSet(null);
- if (prev != null) {
- unregisterMultiHostInjector(prev);
- }
- }
- else {
- PsiManagerRegisteredInjectorsAdapter adapter = new PsiManagerRegisteredInjectorsAdapter();
- if (myPsiManagerRegisteredInjectorsAdapter.compareAndSet(null, adapter)) {
- registerMultiHostInjector(adapter);
- }
- }
- }
-
@Override
public PsiLanguageInjectionHost getInjectionHost(@NotNull PsiElement element) {
final PsiFile file = element.getContainingFile();
@@ -236,7 +216,7 @@
@Override
@NotNull
public TextRange injectedToHost(@NotNull PsiElement injectedContext, @NotNull TextRange injectedTextRange) {
- ProperTextRange.assertProperRange(injectedTextRange);
+ TextRange.assertProperRange(injectedTextRange);
PsiFile file = injectedContext.getContainingFile();
if (file == null) return injectedTextRange;
Document document = PsiDocumentManager.getInstance(file.getProject()).getCachedDocument(file);
@@ -254,48 +234,56 @@
return documentWindow.injectedToHost(offset);
}
- private final ConcurrentMap<Class, MultiHostInjector[]> injectors = new ConcurrentHashMap<Class, MultiHostInjector[]>();
- private final ClassMapCachingNulls<MultiHostInjector> cachedInjectors = new ClassMapCachingNulls<MultiHostInjector>(injectors, new MultiHostInjector[0]);
+ // used only from tests => no need for complex synchronization
+ private final Set<MultiHostInjector> myManualInjectors = Collections.synchronizedSet(new LinkedHashSet<MultiHostInjector>());
+ private volatile ClassMapCachingNulls<MultiHostInjector> cachedInjectors;
- @Override
- public void registerMultiHostInjector(@NotNull MultiHostInjector injector) {
- for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) {
- LOG.assertTrue(place != null, injector);
- while (true) {
- MultiHostInjector[] injectors = this.injectors.get(place);
- if (injectors == null) {
- if (this.injectors.putIfAbsent(place, new MultiHostInjector[]{injector}) == null) break;
- }
- else {
- MultiHostInjector[] newInfos = ArrayUtil.append(injectors, injector);
- if (this.injectors.replace(place, injectors, newInfos)) break;
- }
+ private ClassMapCachingNulls<MultiHostInjector> getInjectorMap() {
+ ClassMapCachingNulls<MultiHostInjector> cached = cachedInjectors;
+ if (cached != null) {
+ return cached;
+ }
+
+ Map<Class, MultiHostInjector[]> injectors = ContainerUtil.newHashMap();
+
+ List<MultiHostInjector> allInjectors = ContainerUtil.newArrayList();
+ allInjectors.addAll(myManualInjectors);
+ Collections.addAll(allInjectors, MultiHostInjector.MULTIHOST_INJECTOR_EP_NAME.getExtensions(myProject));
+ if (LanguageInjector.EXTENSION_POINT_NAME.getExtensions().length > 0) {
+ allInjectors.add(PsiManagerRegisteredInjectorsAdapter.INSTANCE);
+ }
+
+ for (MultiHostInjector injector : allInjectors) {
+ for (Class<? extends PsiElement> place : injector.elementsToInjectIn()) {
+ LOG.assertTrue(place != null, injector);
+ MultiHostInjector[] existing = injectors.get(place);
+ injectors.put(place, existing == null ? new MultiHostInjector[]{injector} : ArrayUtil.append(existing, injector));
}
}
- cachedInjectors.clearCache();
+
+ ClassMapCachingNulls<MultiHostInjector> result = new ClassMapCachingNulls<MultiHostInjector>(injectors, new MultiHostInjector[0]);
+ cachedInjectors = result;
+ return result;
+ }
+
+ private void clearInjectorCache() {
+ cachedInjectors = null;
}
@Override
+ public void registerMultiHostInjector(@NotNull MultiHostInjector injector) {
+ myManualInjectors.add(injector);
+ clearInjectorCache();
+ }
+
+ @Override
public boolean unregisterMultiHostInjector(@NotNull MultiHostInjector injector) {
- boolean removed = false;
- Iterator<Map.Entry<Class,MultiHostInjector[]>> iterator = injectors.entrySet().iterator();
- while (iterator.hasNext()) {
- Map.Entry<Class,MultiHostInjector[]> entry = iterator.next();
- MultiHostInjector[] infos = entry.getValue();
- int i = ArrayUtilRt.find(infos, injector);
- if (i != -1) {
- MultiHostInjector[] newInfos = ArrayUtil.remove(infos, i);
- if (newInfos.length == 0) {
- iterator.remove();
- }
- else {
- injectors.put(entry.getKey(), newInfos);
- }
- removed = true;
- }
+ try {
+ return myManualInjectors.remove(injector);
}
- cachedInjectors.clearCache();
- return removed;
+ finally {
+ clearInjectorCache();
+ }
}
@@ -418,7 +406,7 @@
finally {
cachedManager.myInjectorsClone.clear();
}
- cachedManager.myInjectorsClone.putAll(cachedManager.injectors);
+ cachedManager.myInjectorsClone.putAll(cachedManager.getInjectorMap().getBackingMap());
}
@TestOnly
public static void checkInjectorsAreDisposed(@NotNull Project project) {
@@ -427,7 +415,9 @@
return;
}
try {
- for (Map.Entry<Class, MultiHostInjector[]> entry : cachedManager.injectors.entrySet()) {
+ ClassMapCachingNulls<MultiHostInjector> cached = cachedManager.cachedInjectors;
+ if (cached == null) return;
+ for (Map.Entry<Class, MultiHostInjector[]> entry : cached.getBackingMap().entrySet()) {
Class key = entry.getKey();
if (cachedManager.myInjectorsClone.isEmpty()) return;
MultiHostInjector[] oldInjectors = cachedManager.myInjectorsClone.get(key);
@@ -447,7 +437,7 @@
boolean process(PsiElement element, MultiHostInjector injector);
}
public void processInPlaceInjectorsFor(@NotNull PsiElement element, @NotNull InjProcessor processor) {
- MultiHostInjector[] infos = cachedInjectors.get(element.getClass());
+ MultiHostInjector[] infos = getInjectorMap().get(element.getClass());
if (infos != null) {
final boolean dumb = myDumbService.isDumb();
for (MultiHostInjector injector : infos) {
@@ -482,13 +472,14 @@
}
private static class PsiManagerRegisteredInjectorsAdapter implements MultiHostInjector {
+ public static final PsiManagerRegisteredInjectorsAdapter INSTANCE = new PsiManagerRegisteredInjectorsAdapter();
@Override
public void getLanguagesToInject(@NotNull final MultiHostRegistrar injectionPlacesRegistrar, @NotNull PsiElement context) {
final PsiLanguageInjectionHost host = (PsiLanguageInjectionHost)context;
InjectedLanguagePlaces placesRegistrar = new InjectedLanguagePlaces() {
@Override
public void addPlace(@NotNull Language language, @NotNull TextRange rangeInsideHost, @NonNls @Nullable String prefix, @NonNls @Nullable String suffix) {
- ProperTextRange.assertProperRange(rangeInsideHost);
+ TextRange.assertProperRange(rangeInsideHost);
injectionPlacesRegistrar
.startInjecting(language)
.addPlace(prefix, suffix, host, rangeInsideHost)
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
index e82c7fe..c6200eb 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectedLanguageUtil.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.
@@ -36,6 +36,7 @@
import com.intellij.psi.impl.source.DummyHolder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.*;
+import com.intellij.util.containers.ConcurrentList;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -158,14 +159,16 @@
SelectionModel selectionModel = hostEditor.getSelectionModel();
if (selectionModel.hasSelection()) {
int selstart = selectionModel.getSelectionStart();
- int selend = selectionModel.getSelectionEnd();
- if (!documentWindow.containsRange(selstart, selend)) {
- // selection spreads out the injected editor range
- return hostEditor;
+ if (selstart != -1) {
+ int selend = Math.max(selstart, selectionModel.getSelectionEnd());
+ if (!documentWindow.containsRange(selstart, selend)) {
+ // selection spreads out the injected editor range
+ return hostEditor;
+ }
}
}
if (!documentWindow.isValid()) return hostEditor; // since the moment we got hold of injectedFile and this moment call, document may have been dirtied
- return EditorWindow.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
+ return EditorWindowImpl.create(documentWindow, (EditorImpl)hostEditor, injectedFile);
}
@Nullable
@@ -318,14 +321,14 @@
return out.get();
}
- private static final Key<List<DocumentWindow>> INJECTED_DOCS_KEY = Key.create("INJECTED_DOCS_KEY");
+ private static final Key<ConcurrentList<DocumentWindow>> INJECTED_DOCS_KEY = Key.create("INJECTED_DOCS_KEY");
@NotNull
- public static List<DocumentWindow> getCachedInjectedDocuments(@NotNull PsiFile hostPsiFile) {
+ public static ConcurrentList<DocumentWindow> getCachedInjectedDocuments(@NotNull PsiFile hostPsiFile) {
// modification of cachedInjectedDocuments must be under PsiLock only
- List<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
+ ConcurrentList<DocumentWindow> injected = hostPsiFile.getUserData(INJECTED_DOCS_KEY);
if (injected == null) {
- injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createEmptyCOWList());
+ injected = ((UserDataHolderEx)hostPsiFile).putUserDataIfAbsent(INJECTED_DOCS_KEY, ContainerUtil.<DocumentWindow>createConcurrentList());
}
return injected;
}
@@ -375,7 +378,7 @@
Editor editor = FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, virtualFile, -1), false);
if (editor == null || editor instanceof EditorWindow || editor.isDisposed()) return editor;
if (document instanceof DocumentWindowImpl) {
- return EditorWindow.create((DocumentWindowImpl)document, (EditorImpl)editor, file);
+ return EditorWindowImpl.create((DocumentWindowImpl)document, (EditorImpl)editor, file);
}
return editor;
}
@@ -410,27 +413,6 @@
return combinedEdiablesLength != elementRange.getLength();
}
- public static boolean isSelectionIsAboutToOverflowInjectedFragment(@NotNull EditorWindow injectedEditor) {
- int selStart = injectedEditor.getSelectionModel().getSelectionStart();
- int selEnd = injectedEditor.getSelectionModel().getSelectionEnd();
-
- DocumentWindow document = injectedEditor.getDocument();
-
- boolean isStartOverflows = selStart == 0;
- if (!isStartOverflows) {
- int hostPrev = document.injectedToHost(selStart - 1);
- isStartOverflows = document.hostToInjected(hostPrev) == selStart;
- }
-
- boolean isEndOverflows = selEnd == document.getTextLength();
- if (!isEndOverflows) {
- int hostNext = document.injectedToHost(selEnd + 1);
- isEndOverflows = document.hostToInjected(hostNext) == selEnd;
- }
-
- return isStartOverflows && isEndOverflows;
- }
-
public static boolean hasInjections(@NotNull PsiLanguageInjectionHost host) {
if (!host.isPhysical()) return false;
final Ref<Boolean> result = Ref.create(false);
@@ -494,4 +476,27 @@
public static boolean isInjectableLanguage(Language language) {
return LanguageUtil.isInjectableLanguage(language);
}
+
+ public static boolean isHighlightInjectionBackground(@Nullable PsiLanguageInjectionHost host) {
+ return !(host instanceof InjectionBackgroundSuppressor);
+ }
+
+ public static int getInjectedStart(@NotNull List<PsiLanguageInjectionHost.Shred> places) {
+ PsiLanguageInjectionHost.Shred shred = places.get(0);
+ PsiLanguageInjectionHost host = shred.getHost();
+ assert host != null;
+ return shred.getRangeInsideHost().getStartOffset() + host.getTextOffset();
+ }
+
+ @Nullable
+ public static PsiElement findElementInInjected(@NotNull PsiLanguageInjectionHost injectionHost, final int offset) {
+ final Ref<PsiElement> ref = Ref.create();
+ enumerate(injectionHost, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
+ @Override
+ public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
+ ref.set(injectedPsi.findElementAt(offset - getInjectedStart(places)));
+ }
+ });
+ return ref.get();
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionBackgroundSuppressor.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionBackgroundSuppressor.java
new file mode 100644
index 0000000..a98d653
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/InjectionBackgroundSuppressor.java
@@ -0,0 +1,24 @@
+/*
+ * 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.psi.impl.source.tree.injected;
+
+/**
+ * Marker interface that suppresses injection background.
+ *
+ * @author ignatov
+ */
+public interface InjectionBackgroundSuppressor {
+}
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 34ba8fd..19f1aa2 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
@@ -40,6 +40,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.DocumentCommitThread;
import com.intellij.psi.impl.PsiDocumentManagerImpl;
import com.intellij.psi.impl.source.PsiFileImpl;
@@ -391,10 +392,16 @@
"\nLanguage: "+parsedNode.getPsi().getLanguage()+
"\nHost file: "+ shreds.get(0).getHost().getContainingFile().getVirtualFile()
;
- for (Map.Entry<LeafElement, String> entry : patcher.newTexts.entrySet()) {
- LeafElement leaf = entry.getKey();
- String newText = entry.getValue();
- leaf.rawReplaceWithText(newText);
+ DebugUtil.startPsiModification("injection leaf patching");
+ try {
+ for (Map.Entry<LeafElement, String> entry : patcher.newTexts.entrySet()) {
+ LeafElement leaf = entry.getKey();
+ String newText = entry.getValue();
+ leaf.rawReplaceWithText(newText);
+ }
+ }
+ finally {
+ DebugUtil.finishPsiModification();
}
TreeUtil.clearCaches((TreeElement)parsedNode);
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
index ed22ad1..aea41ab 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/source/tree/injected/ShredImpl.java
@@ -86,7 +86,7 @@
public String toString() {
PsiLanguageInjectionHost host = getHost();
return "Shred " + (host == null ? null : host.getTextRange()) + ": " + host +
- " Inhost range: " + (relevantRangeInHost.isValid() ? "" : "!") +
+ " In host range: " + (relevantRangeInHost.isValid() ? "" : "!") +
"(" + relevantRangeInHost.getStartOffset() + "," + relevantRangeInHost.getEndOffset() + ");" +
" PSI range: " + range;
}
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 1026321..ac97ea9 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubIndexImpl.java
@@ -36,6 +36,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.PsiFileImpl;
+import com.intellij.psi.impl.source.PsiFileWithStubSupport;
import com.intellij.psi.impl.source.tree.FileElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.CommonProcessors;
@@ -50,10 +51,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.io.DataInput;
-import java.io.DataOutput;
-import java.io.File;
-import java.io.IOException;
+import java.io.*;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicReference;
@@ -443,52 +441,55 @@
}
@Override
- public void updateWithMap(final int inputId, @NotNull final Map<K, StubIdList> newData, @NotNull Callable<Collection<K>> oldKeysGetter) throws StorageException {
+ public void updateWithMap(final int inputId,
+ @NotNull final Map<K, StubIdList> newData,
+ @NotNull Callable<Collection<K>> oldKeysGetter) throws StorageException {
super.updateWithMap(inputId, newData, oldKeysGetter);
}
}
@Override
- protected <Psi extends PsiElement> void reportStubPsiMismatch(Psi psi, VirtualFile file) {
+ protected <Psi extends PsiElement> void reportStubPsiMismatch(Psi psi, VirtualFile file, Class<Psi> requiredClass) {
if (file == null) {
- super.reportStubPsiMismatch(psi, file);
+ super.reportStubPsiMismatch(psi, file, requiredClass);
return;
}
- String msg = "Invalid stub element type in index: " + file;
- msg += "; found: " + psi;
- msg += "\nfile stamp: " + file.getModificationStamp();
- msg += "; file size: " + file.getLength();
- msg += "; file modCount: " + file.getModificationCount();
+ StringWriter writer = new StringWriter();
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ PrintWriter out = new PrintWriter(writer);
+
+ out.print("Invalid stub element type in index:");
+ 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());
Document document = FileDocumentManager.getInstance().getCachedDocument(file);
if (document != null) {
- msg += "\nsaved: " + !FileDocumentManager.getInstance().isDocumentUnsaved(document);
- msg += "; doc stamp: " + document.getModificationStamp();
- msg += "; doc size: " + document.getTextLength();
- msg += "; committed: " + PsiDocumentManager.getInstance(psi.getProject()).isCommitted(document);
+ boolean committed = PsiDocumentManager.getInstance(psi.getProject()).isCommitted(document);
+ boolean saved = !FileDocumentManager.getInstance().isDocumentUnsaved(document);
+ out.printf("\ndocument: size:%s; stamp:%s; committed:%s; saved:%s",
+ document.getTextLength(), document.getModificationStamp(), committed, saved);
}
PsiFile psiFile = psi.getManager().findFile(file);
if (psiFile != null) {
- msg += "\npsiFile size: " + psiFile.getTextLength();
- msg += "; viewProvider stamp: " + psiFile.getViewProvider().getModificationStamp();
- if (psiFile instanceof PsiFileImpl) {
- StubTree stub = ((PsiFileImpl)psiFile).getStubTree();
- if (stub == null) {
- FileElement treeElement = ((PsiFileImpl)psiFile).getTreeElement();
- msg += "; ast loaded: " + (treeElement != null);
- if (treeElement != null) {
- msg += "; ast parsed: " + treeElement.isParsed();
- msg += "; ast size: " + treeElement.getTextLength();
- }
- } else {
- msg += "\nstub info=" + stub.getDebugInfo();
- }
- }
+ out.printf("\npsiFile: size:%s; stamp:%s; class:%s",
+ psiFile.getTextLength(), psiFile.getViewProvider().getModificationStamp(), psiFile.getClass().getName());
}
- msg += "\nindexing info: " + StubUpdatingIndex.getIndexingStampInfo(file);
- LOG.error(msg);
+ StubTree stub = psiFile instanceof PsiFileWithStubSupport ? ((PsiFileWithStubSupport)psiFile).getStubTree() : null;
+ FileElement treeElement = stub == null && psiFile instanceof PsiFileImpl? ((PsiFileImpl)psiFile).getTreeElement() : null;
+ if (stub != null) {
+ out.printf("\nstubInfo: " + stub.getDebugInfo());
+ }
+ else if (treeElement != null) {
+ out.printf("\nfileAST: size:%s; parsed:%s", treeElement.getTextLength(), treeElement.isParsed());
+ }
+
+ out.printf("\nindexing info: " + StubUpdatingIndex.getIndexingStampInfo(file));
+ LOG.error(writer.toString());
}
}
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java
index d1634e9..92844c7 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubProcessingHelper.java
@@ -35,7 +35,7 @@
@Override
- protected String stubTreeAndIndexDoNotMatch(StubTree stubTree,
+ protected Object stubTreeAndIndexDoNotMatch(StubTree stubTree,
PsiFileWithStubSupport psiFile,
List<StubElement<?>> plained,
VirtualFile virtualFile,
@@ -51,6 +51,6 @@
new Attachment("stubTree.txt", ((PsiFileStubImpl)stubTree.getRoot()).printTree()),
new Attachment("stubTreeFromIndex.txt", stubTreeFromIndex == null
? "null"
- : ((PsiFileStubImpl)stubTreeFromIndex.getRoot()).printTree())).toString();
+ : ((PsiFileStubImpl)stubTreeFromIndex.getRoot()).printTree()));
}
}
diff --git a/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java b/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java
index ea22194..9642271 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubTreeLoaderImpl.java
@@ -109,11 +109,12 @@
SerializedStubTree stubTree = datas.get(0);
if (!stubTree.contentLengthMatches(vFile.getLength(), getCurrentTextContentLength(project, vFile, document))) {
- return processError(vFile,
- "Outdated stub in index: " + StubUpdatingIndex.getIndexingStampInfo(vFile) +
- ", docSaved=" + saved +
- ", queried at " + vFile.getTimeStamp(),
- null);
+ //todo find another way of early stub-ast mismatch prevention
+ //return processError(vFile,
+ // "Outdated stub in index: " + StubUpdatingIndex.getIndexingStampInfo(vFile) +
+ // ", docSaved=" + saved +
+ // ", queried at " + vFile.getTimeStamp(),
+ // null);
}
Stub stub;
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 71f3640..93e2b35 100644
--- a/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java
+++ b/platform/lang-impl/src/com/intellij/psi/stubs/StubUpdatingIndex.java
@@ -42,7 +42,7 @@
/*
* @author max
*/
-public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtension<Integer, SerializedStubTree, FileContent> {
+public class StubUpdatingIndex extends CustomImplementationFileBasedIndexExtension<Integer, SerializedStubTree, FileContent> implements PsiDependentIndex {
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.stubs.StubUpdatingIndex");
// todo remove once we don't need this for stub-ast mismatch debug info
@@ -215,7 +215,8 @@
}
}
}
- final BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
+
+ BinaryFileStubBuilder builder = BinaryFileStubBuilders.INSTANCE.forFileType(fileType);
if (builder != null) {
version += builder.getStubVersion();
}
@@ -291,7 +292,9 @@
}
@Override
- protected void updateWithMap(final int inputId, @NotNull final Map<Integer, SerializedStubTree> newData, @NotNull Callable<Collection<Integer>> oldKeysGetter)
+ protected void updateWithMap(final int inputId,
+ @NotNull final Map<Integer, SerializedStubTree> newData,
+ @NotNull Callable<Collection<Integer>> oldKeysGetter)
throws StorageException {
checkNameStorage();
@@ -315,6 +318,7 @@
getWriteLock().lock();
final Map<Integer, SerializedStubTree> oldData = readOldData(inputId);
+
final Map<StubIndexKey, Map<Object, StubIdList>> oldStubTree;
try {
oldStubTree = getStubTree(oldData);
diff --git a/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java b/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java
index 674b0cf..c75b610 100644
--- a/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java
+++ b/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java
@@ -83,21 +83,28 @@
final PsiFile templateFile = createTemplateFile(file, language, chars, viewProvider);
final FileElement parsed = ((PsiFileImpl)templateFile).calcTreeElement();
- prepareParsedTemplateFile(parsed);
- Lexer langLexer = LanguageParserDefinitions.INSTANCE.forLanguage(language).createLexer(file.getProject());
- final Lexer lexer = new MergingLexerAdapter(
- new TemplateBlackAndWhiteLexer(createBaseLexer(viewProvider), langLexer, myTemplateElementType, myOuterElementType),
- TokenSet.create(myTemplateElementType, myOuterElementType));
- lexer.start(chars);
- insertOuters(parsed, lexer, table);
- if (parsed != null) {
- final TreeElement element = parsed.getFirstChildNode();
- if (element != null) {
- parsed.rawRemoveAllChildren();
- treeElement.rawAddChildren(element);
+ DebugUtil.startPsiModification("template language parsing");
+ try {
+ prepareParsedTemplateFile(parsed);
+ Lexer langLexer = LanguageParserDefinitions.INSTANCE.forLanguage(language).createLexer(file.getProject());
+ final Lexer lexer = new MergingLexerAdapter(
+ new TemplateBlackAndWhiteLexer(createBaseLexer(viewProvider), langLexer, myTemplateElementType, myOuterElementType),
+ TokenSet.create(myTemplateElementType, myOuterElementType));
+ lexer.start(chars);
+ insertOuters(parsed, lexer, table);
+
+ if (parsed != null) {
+ final TreeElement element = parsed.getFirstChildNode();
+ if (element != null) {
+ parsed.rawRemoveAllChildren();
+ treeElement.rawAddChildren(element);
+ }
}
}
+ finally {
+ DebugUtil.finishPsiModification();
+ }
treeElement.subtreeChanged();
TreeElement childNode = treeElement.getFirstChildNode();
diff --git a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
index 3ff1f18..773bb2b 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java
@@ -373,7 +373,10 @@
String codeReferencesText = descriptor.getCodeReferencesText(codeUsageCount, codeFiles.size());
presentation.setCodeUsagesString(codeReferencesText);
- presentation.setNonCodeUsagesString(descriptor.getCommentReferencesText(nonCodeUsageCount, nonCodeFiles.size()));
+ final String commentReferencesText = descriptor.getCommentReferencesText(nonCodeUsageCount, nonCodeFiles.size());
+ if (commentReferencesText != null) {
+ presentation.setNonCodeUsagesString(commentReferencesText);
+ }
presentation.setDynamicUsagesString("Dynamic " + StringUtil.decapitalize(descriptor.getCodeReferencesText(dynamicUsagesCount, dynamicUsagesCodeFiles.size())));
String generatedCodeString;
if (codeReferencesText.contains("in code")) {
@@ -446,7 +449,7 @@
return usageInfos;
}
- private void doRefactoring(@NotNull Collection<UsageInfo> usageInfoSet) {
+ private void doRefactoring(@NotNull final Collection<UsageInfo> usageInfoSet) {
for (Iterator<UsageInfo> iterator = usageInfoSet.iterator(); iterator.hasNext();) {
UsageInfo usageInfo = iterator.next();
final PsiElement element = usageInfo.getElement();
@@ -479,7 +482,11 @@
public void run() {
final String refactoringId = getRefactoringId();
if (refactoringId != null) {
- myProject.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(refactoringId, getBeforeData());
+ RefactoringEventData data = getBeforeData();
+ if (data != null) {
+ data.addUsages(usageInfoSet);
+ }
+ myProject.getMessageBus().syncPublisher(RefactoringEventListener.REFACTORING_EVENT_TOPIC).refactoringStarted(refactoringId, data);
}
try {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java
index 22ea5bf..92eae30 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/actions/BasePlatformRefactoringAction.java
@@ -21,7 +21,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.ExtensionPointListener;
import com.intellij.openapi.extensions.PluginDescriptor;
@@ -118,7 +117,7 @@
if (element != null) {
for (RefactoringSupportProvider provider : providers) {
if (provider.isAvailable(element)) {
- return getRefactoringHandler(provider);
+ return getRefactoringHandler(provider, element);
}
}
}
@@ -149,6 +148,11 @@
@Nullable
protected abstract RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider);
+ @Nullable
+ protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider, PsiElement element) {
+ return getRefactoringHandler(provider);
+ }
+
@Override
protected boolean isHidden() {
if (myHidden == null) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/actions/IntroduceVariableAction.java b/platform/lang-impl/src/com/intellij/refactoring/actions/IntroduceVariableAction.java
index 0db5813..8cb58e5 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/actions/IntroduceVariableAction.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/actions/IntroduceVariableAction.java
@@ -16,12 +16,11 @@
package com.intellij.refactoring.actions;
-import com.intellij.lang.Language;
-import com.intellij.lang.LanguageRefactoringSupport;
import com.intellij.lang.refactoring.RefactoringSupportProvider;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringActionHandler;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
public class IntroduceVariableAction extends BasePlatformRefactoringAction {
public IntroduceVariableAction() {
@@ -42,4 +41,9 @@
protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider) {
return provider.getIntroduceVariableHandler();
}
+
+ @Nullable
+ @Override
+ protected RefactoringActionHandler getRefactoringHandler(@NotNull RefactoringSupportProvider provider, PsiElement element) {
+ return provider.getIntroduceVariableHandler(element);}
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/classMembers/AbstractUsesDependencyMemberInfoModel.java b/platform/lang-impl/src/com/intellij/refactoring/classMembers/AbstractUsesDependencyMemberInfoModel.java
index f6f2a31..5052f97 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/classMembers/AbstractUsesDependencyMemberInfoModel.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/classMembers/AbstractUsesDependencyMemberInfoModel.java
@@ -19,6 +19,7 @@
import com.intellij.psi.NavigatablePsiElement;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
/**
* @author Dennis.Ushakov
@@ -26,7 +27,7 @@
public abstract class AbstractUsesDependencyMemberInfoModel<T extends NavigatablePsiElement, C extends PsiElement, M extends MemberInfoBase<T>> extends DependencyMemberInfoModel<T, M> {
protected final C myClass;
- public AbstractUsesDependencyMemberInfoModel(C aClass, C superClass, boolean recursive) {
+ public AbstractUsesDependencyMemberInfoModel(C aClass, @Nullable C superClass, boolean recursive) {
super(new UsesMemberDependencyGraph<T, C, M>(aClass, superClass, recursive), ERROR);
myClass = aClass;
setTooltipProvider(new MemberInfoTooltipManager.TooltipProvider<T, M>() {
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 eb2aa59..fa80f33 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/copy/CopyFilesOrDirectoriesHandler.java
@@ -302,7 +302,8 @@
}
}
- public static boolean checkFileExist(PsiDirectory targetDirectory, int[] choice, PsiFile file, String name, String title) {
+ public static boolean checkFileExist(@Nullable PsiDirectory targetDirectory, int[] choice, PsiFile file, String name, String title) {
+ if (targetDirectory == null) return false;
final PsiFile existing = targetDirectory.findFile(name);
if (existing != null && !existing.equals(file)) {
int selection;
diff --git a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractMethodDialog.java b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractMethodDialog.java
index 7bb0554..1fc9dc3 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractMethodDialog.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractExtractMethodDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -140,7 +140,7 @@
Messages.showInfoMessage(error, RefactoringBundle.message("error.title"));
return;
}
- if (Messages.showOkCancelDialog(error + ". " + RefactoringBundle.message("do.you.wish.to.continue"), RefactoringBundle.message("warning.title"), Messages.getWarningIcon()) != 0){
+ if (Messages.showOkCancelDialog(error + ". " + RefactoringBundle.message("do.you.wish.to.continue"), RefactoringBundle.message("warning.title"), Messages.getWarningIcon()) != Messages.OK){
return;
}
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java
index 70d33b3..122845f 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/AbstractParameterTablePanel.java
@@ -62,7 +62,7 @@
myTable.setTableHeader(null);
myTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN).setMaxWidth(new JCheckBox().getPreferredSize().width);
+ TableUtil.setupCheckboxColumn(myTable, MyTableModel.CHECKMARK_COLUMN);
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_NAME_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHelper.java b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHelper.java
index 9b1dd16..234205d 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHelper.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodHelper.java
@@ -31,7 +31,6 @@
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
@@ -94,8 +93,8 @@
final int exitCode = !isUnittest ? Messages.showYesNoDialog(project, message,
RefactoringBundle.message("refactoring.extract.method.dialog.title"),
Messages.getInformationIcon()) :
- DialogWrapper.OK_EXIT_CODE;
- if (exitCode == DialogWrapper.OK_EXIT_CODE) {
+ Messages.YES;
+ if (exitCode == Messages.YES) {
boolean replaceAll = false;
final Map<SimpleMatch, RangeHighlighter> highlighterMap = new HashMap<SimpleMatch, RangeHighlighter>();
for (SimpleMatch match : duplicates) {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java
index cf4eaf6..e761e9a 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/AbstractInplaceIntroducer.java
@@ -81,7 +81,7 @@
public AbstractInplaceIntroducer(Project project,
Editor editor,
- E expr,
+ @Nullable E expr,
@Nullable V localVariable,
E[] occurrences,
String title,
diff --git a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java
index d60fbb6..b251835 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/introduce/inplace/InplaceVariableIntroducer.java
@@ -109,6 +109,7 @@
myExprMarker = exprMarker;
}
+ @Nullable
public E getExpr() {
return myExpr != null && myExpr.isValid() && myExpr.isPhysical() ? myExpr : null;
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeFileBase.java b/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeFileBase.java
index ae1e20c..811e695 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeFileBase.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/lang/ExtractIncludeFileBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -115,7 +115,7 @@
final String message = RefactoringBundle.message("idea.has.found.fragments.that.can.be.replaced.with.include.directive",
ApplicationNamesInfo.getInstance().getProductName());
final int exitCode = Messages.showYesNoDialog(project, message, getRefactoringName(), Messages.getInformationIcon());
- if (exitCode == DialogWrapper.OK_EXIT_CODE) {
+ if (exitCode == Messages.YES) {
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java b/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java
index 44a4788..ef9150a 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/AutomaticRenamingDialog.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 @@
import com.intellij.ui.TableUtil;
import com.intellij.ui.table.JBTable;
import com.intellij.usageView.UsageInfo;
+import com.intellij.usages.UsageViewPresentation;
import com.intellij.usages.impl.UsagePreviewPanel;
import org.jetbrains.annotations.Nullable;
@@ -83,7 +84,7 @@
super(project, true);
myProject = project;
myRenamer = renamer;
- myUsagePreviewPanel = new UsagePreviewPanel(myProject);
+ myUsagePreviewPanel = new UsagePreviewPanel(myProject, new UsageViewPresentation());
myUsageFileLabel = new JLabel();
populateData();
myTableModel = new MyTableModel(renamer.allowChangeSuggestedName());
@@ -176,9 +177,7 @@
final TableColumnModel columnModel = myTable.getColumnModel();
columnModel.getColumn(CHECK_COLUMN).setCellRenderer(new BooleanTableCellRenderer());
- final int checkBoxWidth = new JCheckBox().getPreferredSize().width;
- columnModel.getColumn(CHECK_COLUMN).setMaxWidth(checkBoxWidth);
- columnModel.getColumn(CHECK_COLUMN).setMinWidth(checkBoxWidth);
+ TableUtil.setupCheckboxColumn(columnModel.getColumn(CHECK_COLUMN));
columnModel.getColumn(NEW_NAME_COLUMN).setCellEditor(new StringTableCellEditor(myProject));
mySelectAllButton.addActionListener(new ActionListener() {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/DirectoryAsPackageRenameHandlerBase.java b/platform/lang-impl/src/com/intellij/refactoring/rename/DirectoryAsPackageRenameHandlerBase.java
index 64a86e3..23cf8be 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/DirectoryAsPackageRenameHandlerBase.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/DirectoryAsPackageRenameHandlerBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
@@ -29,7 +28,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
@@ -159,13 +157,13 @@
RefactoringBundle.message("rename.current.directory"),
RefactoringBundle.message("rename.directories"), CommonBundle.getCancelButtonText(),
Messages.getWarningIcon());
- if (ret == 2) return;
+ if (ret == Messages.CANCEL) return;
renameDirs(project, nameSuggestionContext, editor, psiDirectory, aPackage,
- ret == 0 ? (moduleDirs == null ? new PsiDirectory[]{psiDirectory} : moduleDirs) : projectDirectories);
+ ret == Messages.YES ? (moduleDirs == null ? new PsiDirectory[]{psiDirectory} : moduleDirs) : projectDirectories);
}
else {
if (Messages.showOkCancelDialog(project, promptMessage + "?", RefactoringBundle.message("warning.title"),
- Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getWarningIcon()) == Messages.OK) {
renameDirs(project, nameSuggestionContext, editor, psiDirectory, aPackage, psiDirectory);
}
}
@@ -180,10 +178,10 @@
RefactoringBundle.message("rename.package.button.text"),
RefactoringBundle.message("rename.directory.button.text"), CommonBundle.getCancelButtonText(),
Messages.getWarningIcon());
- if (ret == 0) {
+ if (ret == Messages.YES) {
PsiElementRenameHandler.rename(aPackage, project, nameSuggestionContext, editor);
}
- else if (ret == 1) {
+ else if (ret == Messages.NO) {
renameDirs(project, nameSuggestionContext, editor, psiDirectory, aPackage, psiDirectory);
}
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
index 9b55217..fe34cc6 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/PsiElementRenameHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -20,8 +20,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.DataKey;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
@@ -95,7 +93,7 @@
final String message = "Selected element is used from non-project files. These usages won't be renamed. Proceed anyway?";
if (ApplicationManager.getApplication().isUnitTestMode()) throw new CommonRefactoringUtil.RefactoringErrorHintException(message);
if (Messages.showYesNoDialog(project, message,
- RefactoringBundle.getCannotRefactorMessage(null), Messages.getWarningIcon()) != DialogWrapper.OK_EXIT_CODE) {
+ RefactoringBundle.getCannotRefactorMessage(null), Messages.getWarningIcon()) != Messages.YES) {
return;
}
}
@@ -155,10 +153,10 @@
private static void rename(PsiElement element, final Project project, PsiElement nameSuggestionContext, Editor editor, String defaultName) {
RenamePsiElementProcessor processor = RenamePsiElementProcessor.forElement(element);
- element = processor.substituteElementToRename(element, editor);
- if (element == null || !canRename(project, editor, element)) return;
+ PsiElement substituted = processor.substituteElementToRename(element, editor);
+ if (substituted == null || !canRename(project, editor, substituted)) return;
- final RenameDialog dialog = processor.createRenameDialog(project, element, nameSuggestionContext, editor);
+ RenameDialog dialog = processor.createRenameDialog(project, substituted, nameSuggestionContext, editor);
if (defaultName == null && ApplicationManager.getApplication().isUnitTestMode()) {
String[] strings = dialog.getSuggestedNames();
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java
index fc73355..a94cd0c 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/InplaceRefactoring.java
@@ -54,7 +54,6 @@
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.BalloonBuilder;
@@ -270,7 +269,7 @@
final TemplateBuilderImpl builder = new TemplateBuilderImpl(myScope);
PsiElement nameIdentifier = getNameIdentifier();
- int offset = myEditor.getCaretModel().getOffset();
+ int offset = InjectedLanguageUtil.getTopLevelEditor(myEditor).getCaretModel().getOffset();
PsiElement selectedElement = getSelectedInEditorElement(nameIdentifier, refs, stringUsages, offset);
boolean subrefOnPrimaryElement = false;
@@ -435,11 +434,11 @@
return myCaretRangeMarker.isValid() ? myCaretRangeMarker.getEndOffset() : offset;
}
- protected void navigateToAlreadyStarted(Document oldDocument, int exitCode) {
+ protected void navigateToAlreadyStarted(Document oldDocument, @Messages.YesNoResult int exitCode) {
navigateToStarted(oldDocument, myProject, exitCode);
}
- private static void navigateToStarted(final Document oldDocument, final Project project, final int exitCode) {
+ private static void navigateToStarted(final Document oldDocument, final Project project, @Messages.YesNoResult final int exitCode) {
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(oldDocument);
if (file != null) {
final VirtualFile virtualFile = file.getVirtualFile();
@@ -450,7 +449,7 @@
final Editor textEditor = ((TextEditor)editor).getEditor();
final TemplateState templateState = TemplateManagerImpl.getTemplateState(textEditor);
if (templateState != null) {
- if (exitCode == DialogWrapper.OK_EXIT_CODE) {
+ if (exitCode == Messages.YES) {
final TextRange range = templateState.getVariableRange(PRIMARY_VARIABLE_NAME);
if (range != null) {
new OpenFileDescriptor(project, virtualFile, range.getStartOffset()).navigate(true);
@@ -712,7 +711,7 @@
if (nameIdentifier != null) {
final TextRange range = nameIdentifier.getTextRange();
- if (range != null && range.containsOffset(offset)) return nameIdentifier;
+ if (range != null && checkRangeContainsOffset(offset, range, nameIdentifier, 0)) return nameIdentifier;
}
for (Pair<PsiElement, TextRange> stringUsage : stringUsages) {
@@ -724,7 +723,10 @@
}
private boolean checkRangeContainsOffset(int offset, final TextRange textRange, PsiElement element) {
- int startOffset = element.getTextRange().getStartOffset();
+ return checkRangeContainsOffset(offset, textRange, element, element.getTextRange().getStartOffset());
+ }
+
+ private boolean checkRangeContainsOffset(int offset, final TextRange textRange, PsiElement element, int shiftOffset) {
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(myProject);
final PsiLanguageInjectionHost injectionHost = injectedLanguageManager.getInjectionHost(element);
if (injectionHost != null) {
@@ -733,8 +735,9 @@
if (initialInjectedHost != null && initialInjectedHost != injectionHost) {
return false;
}
+ return injectedLanguageManager.injectedToHost(element, textRange).shiftRight(shiftOffset).contains(offset);
}
- return textRange.shiftRight(startOffset).containsOffset(offset);
+ return textRange.shiftRight(shiftOffset).containsOffset(offset);
}
protected boolean isRestart() {
diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java
index 2d2d0b1..bd3c52a 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/rename/inplace/MemberInplaceRenamer.java
@@ -281,14 +281,15 @@
if (Comparing.strEqual(myOldName, ((PsiNameIdentifierOwner)mySubstituted).getName())) return mySubstituted;
final RangeMarker rangeMarker = mySubstitutedRange != null ? mySubstitutedRange : myRenameOffset;
- if (rangeMarker != null) return PsiTreeUtil.getParentOfType(mySubstituted.getContainingFile().findElementAt(rangeMarker.getStartOffset()), PsiNameIdentifierOwner.class);
+ if (rangeMarker != null)
+ return PsiTreeUtil.findElementOfClassAtRange(mySubstituted.getContainingFile(), rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), PsiNameIdentifierOwner.class);
}
return mySubstituted;
}
if (mySubstitutedRange != null) {
final PsiFile psiFile = PsiDocumentManager.getInstance(myProject).getPsiFile(myEditor.getDocument());
if (psiFile != null) {
- return PsiTreeUtil.getParentOfType(psiFile.findElementAt(mySubstitutedRange.getStartOffset()), PsiNameIdentifierOwner.class);
+ return PsiTreeUtil.findElementOfClassAtRange(psiFile, mySubstitutedRange.getStartOffset(), mySubstitutedRange.getEndOffset(), PsiNameIdentifierOwner.class);
}
}
return getVariable();
diff --git a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
index 2cd0f7e..e6acbaa 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/safeDelete/SafeDeleteProcessor.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.
@@ -279,7 +279,7 @@
}
return manager.showUsages(targets,
- UsageInfoToUsageConverter.convert(new UsageInfoToUsageConverter.TargetElementsDescriptor(myElements), usages),
+ UsageInfoToUsageConverter.convert(myElements, usages),
presentation
);
}
diff --git a/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java b/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java
index 6f22ffa..7d8b57b 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/ui/AbstractMemberSelectionTable.java
@@ -19,7 +19,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.actionSystem.DataSink;
-import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.TypeSafeDataProvider;
import com.intellij.openapi.util.Iconable;
import com.intellij.psi.PsiElement;
@@ -32,9 +31,11 @@
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.EmptyIcon;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.util.ArrayList;
@@ -61,7 +62,7 @@
protected MemberInfoModel<T, M> myMemberInfoModel;
protected MyTableModel<T, M> myTableModel;
- public AbstractMemberSelectionTable(Collection<M> memberInfos, MemberInfoModel<T, M> memberInfoModel, String abstractColumnHeader) {
+ public AbstractMemberSelectionTable(Collection<M> memberInfos, @Nullable MemberInfoModel<T, M> memberInfoModel, @Nullable String abstractColumnHeader) {
myAbstractEnabled = abstractColumnHeader != null;
myAbstractColumnHeader = abstractColumnHeader;
myTableModel = new MyTableModel<T, M>(this);
@@ -78,10 +79,9 @@
TableColumnModel model = getColumnModel();
model.getColumn(DISPLAY_NAME_COLUMN).setCellRenderer(new MyTableRenderer<T, M>(this));
- model.getColumn(CHECKED_COLUMN).setCellRenderer(new MyBooleanRenderer<T, M>(this));
- final int checkBoxWidth = new JCheckBox().getPreferredSize().width;
- model.getColumn(CHECKED_COLUMN).setMaxWidth(checkBoxWidth);
- model.getColumn(CHECKED_COLUMN).setMinWidth(checkBoxWidth);
+ TableColumn checkBoxColumn = model.getColumn(CHECKED_COLUMN);
+ TableUtil.setupCheckboxColumn(checkBoxColumn);
+ checkBoxColumn.setCellRenderer(new MyBooleanRenderer<T, M>(this));
if (myAbstractEnabled) {
int width = (int)(1.3 * getFontMetrics(getFont()).charsWidth(myAbstractColumnHeader.toCharArray(), 0, myAbstractColumnHeader.length()));
model.getColumn(ABSTRACT_COLUMN).setMaxWidth(width);
@@ -174,6 +174,7 @@
scrollSelectionInView();
}
+ @Nullable
protected abstract Object getAbstractColumnValue(M memberInfo);
protected abstract boolean isAbstractColumnEditable(int rowIndex);
diff --git a/platform/lang-impl/src/com/intellij/refactoring/ui/NameSuggestionsField.java b/platform/lang-impl/src/com/intellij/refactoring/ui/NameSuggestionsField.java
index 5c2aeec..59a5dbf 100644
--- a/platform/lang-impl/src/com/intellij/refactoring/ui/NameSuggestionsField.java
+++ b/platform/lang-impl/src/com/intellij/refactoring/ui/NameSuggestionsField.java
@@ -73,7 +73,7 @@
myComponent = createTextFieldForName(nameSuggestions, fileType);
}
else {
- final ComboBox combobox = new ComboBox(nameSuggestions,-1);
+ final ComboBox combobox = new ComboBox(nameSuggestions);
combobox.setSelectedIndex(0);
setupComboBox(combobox, fileType);
myComponent = combobox;
@@ -103,7 +103,7 @@
int myOffset = offset - wordRangeStartOffset;
myEditor.getCaretModel().moveToOffset(myOffset);
TextRange selected = new TextRange(Math.max(0, selectionModel.getSelectionStart() - wordRangeStartOffset),
- selectionModel.getSelectionEnd() - wordRangeStartOffset);
+ Math.max(0, selectionModel.getSelectionEnd() - wordRangeStartOffset));
selected = selected.intersection(new TextRange(0, myEditor.getDocument().getTextLength()));
if (selectionModel.hasSelection() && selected != null && !selected.isEmpty()) {
myEditor.getSelectionModel().setSelection(selected.getStartOffset(), selected.getEndOffset());
diff --git a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java
index 7d2329a..102a439 100644
--- a/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java
+++ b/platform/lang-impl/src/com/intellij/semantic/SemServiceImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -32,7 +32,6 @@
import com.intellij.util.SmartList;
import com.intellij.util.containers.*;
import com.intellij.util.messages.MessageBusConnection;
-import com.intellij.util.pico.IdeaPicoContainer;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -55,8 +54,8 @@
}
};
private final ConcurrentWeakHashMap<PsiElement, SoftReference<SemCacheChunk>> myCache = new ConcurrentWeakHashMap<PsiElement, SoftReference<SemCacheChunk>>();
- private final MultiMap<SemKey, NullableFunction<PsiElement, ? extends SemElement>> myProducers;
- private final MultiMap<SemKey, SemKey> myInheritors;
+ private volatile MultiMap<SemKey, NullableFunction<PsiElement, ? extends SemElement>> myProducers;
+ private volatile MultiMap<SemKey, SemKey> myInheritors;
private final Project myProject;
private boolean myBulkChange = false;
@@ -84,10 +83,6 @@
});
- myProducers = collectProducers();
-
- myInheritors = cacheKeyHierarchy(myProducers.keySet());
-
final LowMemoryWatcher watcher = LowMemoryWatcher.register(new Runnable() {
@Override
public void run() {
@@ -146,10 +141,8 @@
}
};
- final IdeaPicoContainer container = new IdeaPicoContainer(myProject.getPicoContainer());
- container.registerComponentInstance(SemService.class.getName(), this);
for (SemContributorEP contributor : myProject.getExtensions(SemContributor.EP_NAME)) {
- contributor.registerSemProviders(container, registrar);
+ contributor.registerSemProviders(myProject.getPicoContainer(), registrar);
}
return map;
@@ -190,6 +183,8 @@
return cached;
}
+ ensureInitialized();
+
RecursionGuard.StackStamp stamp = RecursionManager.createGuard("semService").markStack();
LinkedHashSet<T> result = new LinkedHashSet<T>();
@@ -210,6 +205,13 @@
return new ArrayList<T>(result);
}
+ private void ensureInitialized() {
+ if (myInheritors == null) {
+ myProducers = collectProducers();
+ myInheritors = cacheKeyHierarchy(myProducers.keySet());
+ }
+ }
+
@NotNull
private List<SemElement> createSemElements(SemKey key, PsiElement psi) {
List<SemElement> result = null;
@@ -282,7 +284,7 @@
@Nullable
private SemCacheChunk obtainChunk(@Nullable PsiElement root) {
final SoftReference<SemCacheChunk> ref = myCache.get(root);
- return ref == null ? null : ref.get();
+ return com.intellij.reference.SoftReference.dereference(ref);
}
@Override
diff --git a/platform/lang-impl/src/com/intellij/tools/BaseToolsPanel.java b/platform/lang-impl/src/com/intellij/tools/BaseToolsPanel.java
index 0d16717..9a9f1bc 100644
--- a/platform/lang-impl/src/com/intellij/tools/BaseToolsPanel.java
+++ b/platform/lang-impl/src/com/intellij/tools/BaseToolsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -76,7 +76,6 @@
private boolean myIsModified = false;
protected BaseToolsPanel() {
-
myTree = new CheckboxTree(
new CheckboxTree.CheckboxTreeCellRenderer() {
@Override
@@ -181,8 +180,7 @@
myTree.requestFocus();
}
}
- }).setButtonComparator("Add", "Copy", "Edit", "Remove", "Up", "Down")
- .createPanel(), BorderLayout.CENTER);
+ }).createPanel(), BorderLayout.CENTER);
myAddButton = ToolbarDecorator.findAddButton(this);
myEditButton = ToolbarDecorator.findEditButton(this);
@@ -415,7 +413,7 @@
CommonBundle.getWarningTitle(),
Messages.getWarningIcon()
);
- if (result != 0) {
+ if (result != Messages.YES) {
return;
}
myIsModified = true;
diff --git a/platform/lang-impl/src/com/intellij/tools/ToolsBundle.java b/platform/lang-impl/src/com/intellij/tools/ToolsBundle.java
index f2ec536..0f060ab 100644
--- a/platform/lang-impl/src/com/intellij/tools/ToolsBundle.java
+++ b/platform/lang-impl/src/com/intellij/tools/ToolsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* @author yole
*/
public class ToolsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.ToolsBundle";
private ToolsBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java b/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java
index 4b1e606..a939cef 100644
--- a/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java
+++ b/platform/lang-impl/src/com/intellij/tools/ToolsProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,6 +25,7 @@
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
@@ -56,7 +57,7 @@
@NonNls private static final String APPLICATION_HOME_MACRO = "$APPLICATION_HOME_DIR$";
@Override
- public ToolsGroup<T> readScheme(final Document document) throws InvalidDataException, IOException, JDOMException {
+ public ToolsGroup<T> readScheme(@NotNull final Document document) throws InvalidDataException, IOException, JDOMException {
Element root = document.getRootElement();
if (root == null || !TOOL_SET.equals(root.getName())) {
throw new InvalidDataException();
@@ -131,7 +132,7 @@
protected abstract T createTool();
@Override
- public Document writeScheme(final ToolsGroup<T> scheme) throws WriteExternalException {
+ public Document writeScheme(@NotNull final ToolsGroup<T> scheme) throws WriteExternalException {
Element groupElement = new Element(TOOL_SET);
if (scheme.getName() != null) {
groupElement.setAttribute(ATTRIBUTE_NAME, scheme.getName());
@@ -145,7 +146,7 @@
}
@Override
- public boolean shouldBeSaved(final ToolsGroup scheme) {
+ public boolean shouldBeSaved(@NotNull final ToolsGroup scheme) {
return true;
}
diff --git a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java
index 403a17f..d23082d 100644
--- a/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/DeferredIconImpl.java
@@ -22,15 +22,14 @@
import com.intellij.concurrency.Job;
import com.intellij.concurrency.JobLauncher;
import com.intellij.ide.PowerSaveMode;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.IndexNotReadyException;
-import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.ui.tabs.impl.TabLabel;
import com.intellij.util.Alarm;
import com.intellij.util.Function;
-import com.intellij.util.Processor;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
@@ -44,7 +43,9 @@
import java.util.Set;
public class DeferredIconImpl<T> implements DeferredIcon {
+ private static final int MIN_AUTO_UPDATE_MILLIS = 950;
private static final RepaintScheduler ourRepaintScheduler = new RepaintScheduler();
+ @NotNull
private volatile Icon myDelegateIcon;
private Function<T, Icon> myEvaluator;
private volatile boolean myIsScheduled = false;
@@ -52,27 +53,31 @@
private static final Icon EMPTY_ICON = EmptyIcon.ICON_16;
private final boolean myNeedReadAction;
private boolean myDone;
+ private final boolean myAutoUpdatable;
+ private long myLastCalcTime = 0L;
+ private long myLastTimeSpent = 0L;
- private IconListener<T> myEvalListener;
- private static final TransferToEDTQueue<Runnable> ourLaterInvocator = new TransferToEDTQueue<Runnable>("Deferred icon later invocator", new Processor<Runnable>() {
- @Override
- public boolean process(Runnable runnable) {
- runnable.run();
- return true;
- }
- }, Condition.FALSE, 200);
+ private final IconListener<T> myEvalListener;
+ private static final TransferToEDTQueue<Runnable> ourLaterInvocator = TransferToEDTQueue.createRunnableMerger("Deferred icon later invocator", 200);
- public DeferredIconImpl(Icon baseIcon, T param, @NotNull Function<T, Icon> evaluator) {
- this(baseIcon, param, true, evaluator);
+ public DeferredIconImpl(Icon baseIcon, T param, @NotNull Function<T, Icon> evaluator, @NotNull IconListener<T> listener, boolean autoUpdatable) {
+ this(baseIcon, param, true, evaluator, listener, autoUpdatable);
}
public DeferredIconImpl(Icon baseIcon, T param, final boolean needReadAction, @NotNull Function<T, Icon> evaluator) {
+ this(baseIcon, param, needReadAction, evaluator, null, false);
+ }
+
+ private DeferredIconImpl(Icon baseIcon, T param, boolean needReadAction, final Function<T, Icon> evaluator, IconListener<T> listener, boolean autoUpdatable) {
myParam = param;
myDelegateIcon = nonNull(baseIcon);
myEvaluator = evaluator;
myNeedReadAction = needReadAction;
+ myEvalListener = listener;
+ myAutoUpdatable = autoUpdatable;
}
+ @NotNull
private static Icon nonNull(final Icon icon) {
return icon == null ? EMPTY_ICON : icon;
}
@@ -83,7 +88,7 @@
myDelegateIcon.paintIcon(c, g, x, y); //SOE protection
}
- if (myIsScheduled || isDone() || PowerSaveMode.isEnabled()) {
+ if (isDone() || myIsScheduled || PowerSaveMode.isEnabled()) {
return;
}
myIsScheduled = true;
@@ -112,11 +117,16 @@
}
};
+ final long startTime = System.currentTimeMillis();
if (myNeedReadAction) {
if (!ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() {
@Override
public void run() {
IconDeferrerImpl.evaluateDeferred(evalRunnable);
+ if (myAutoUpdatable) {
+ myLastCalcTime = System.currentTimeMillis();
+ myLastTimeSpent = myLastCalcTime - startTime;
+ }
}
})) {
myIsScheduled = false;
@@ -125,6 +135,10 @@
}
else {
IconDeferrerImpl.evaluateDeferred(evalRunnable);
+ if (myAutoUpdatable) {
+ myLastCalcTime = System.currentTimeMillis();
+ myLastTimeSpent = myLastCalcTime - startTime;
+ }
}
final Icon result = evaluated[0];
myDelegateIcon = result;
@@ -208,8 +222,10 @@
}
myDone = true;
- myEvaluator = null;
- myParam = null;
+ if (!myAutoUpdatable) {
+ myEvaluator = null;
+ myParam = null;
+ }
}
@NotNull
@@ -264,6 +280,10 @@
}
public boolean isDone() {
+ if (myAutoUpdatable && myDone && myLastCalcTime > 0 && (System.currentTimeMillis() - myLastCalcTime) > Math.max(MIN_AUTO_UPDATE_MILLIS, 10 * myLastTimeSpent)) {
+ myDone = false;
+ myIsScheduled = false;
+ }
return myDone;
}
@@ -271,18 +291,20 @@
private final Alarm myAlarm = new Alarm();
private final Set<RepaintRequest> myQueue = new LinkedHashSet<RepaintRequest>();
- public void pushDirtyComponent(final Component c, final Rectangle rec) {
+ public void pushDirtyComponent(@NotNull Component c, final Rectangle rec) {
+ ApplicationManager.getApplication().assertIsDispatchThread(); // assert myQueue accessed from EDT only
myAlarm.cancelAllRequests();
myAlarm.addRequest(new Runnable() {
@Override
public void run() {
for (RepaintRequest each : myQueue) {
Rectangle r = each.getRectangle();
- if (r != null) {
- each.getComponent().repaint(r.x, r.y, r.width, r.height);
- } else {
+ if (r == null) {
each.getComponent().repaint();
}
+ else {
+ each.getComponent().repaint(r.x, r.y, r.width, r.height);
+ }
}
myQueue.clear();
}
@@ -296,11 +318,12 @@
private final Component myComponent;
private final Rectangle myRectangle;
- private RepaintRequest(Component component, Rectangle rectangle) {
+ private RepaintRequest(@NotNull Component component, Rectangle rectangle) {
myComponent = component;
myRectangle = rectangle;
}
+ @NotNull
public Component getComponent() {
return myComponent;
}
@@ -310,11 +333,6 @@
}
}
- public DeferredIconImpl setDoneListener(@NotNull IconListener<T> disposer) {
- myEvalListener = disposer;
- return this;
- }
-
public interface IconListener<T> {
void evalDone(T key, @NotNull Icon result);
}
diff --git a/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java b/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java
index 96f97c0..7d6f25e 100644
--- a/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java
+++ b/platform/lang-impl/src/com/intellij/ui/IconDeferrerImpl.java
@@ -41,7 +41,8 @@
}
};
private long myLastClearTimestamp = 0;
- @SuppressWarnings("UnusedDeclaration") private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
+ @SuppressWarnings("UnusedDeclaration")
+ private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
@Override
public void run() {
clear();
@@ -73,6 +74,15 @@
@Override
public <T> Icon defer(final Icon base, final T param, @NotNull final Function<T, Icon> f) {
+ return deferImpl(base, param, f, false);
+ }
+
+ @Override
+ public <T> Icon deferAutoUpdatable(Icon base, T param, @NotNull Function<T, Icon> f) {
+ return deferImpl(base, param, f, true);
+ }
+
+ private <T> Icon deferImpl(Icon base, T param, @NotNull Function<T, Icon> f, boolean autoupdatable) {
if (myEvaluationIsInProgress.get().booleanValue()) {
return f.fun(param);
}
@@ -81,7 +91,7 @@
Icon result = myIconsCache.get(param);
if (result == null) {
final long started = myLastClearTimestamp;
- result = new DeferredIconImpl<T>(base, param, f).setDoneListener(new DeferredIconImpl.IconListener<T>() {
+ result = new DeferredIconImpl<T>(base, param, f, new DeferredIconImpl.IconListener<T>() {
@Override
public void evalDone(T key, @NotNull Icon r) {
synchronized (LOCK) {
@@ -91,7 +101,7 @@
}
}
}
- });
+ }, autoupdatable);
myIconsCache.put(param, result);
}
@@ -106,7 +116,7 @@
}
};
- public static void evaluateDeferred(@NotNull Runnable runnable) {
+ static void evaluateDeferred(@NotNull Runnable runnable) {
try {
myEvaluationIsInProgress.set(Boolean.TRUE);
runnable.run();
diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java
index 7285ee0..db45a3f 100644
--- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java
+++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletion.java
@@ -26,6 +26,7 @@
import com.intellij.openapi.editor.ex.FocusChangeListener;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
@@ -134,7 +135,7 @@
return editor;
}
- public static class StringsCompletionProvider extends TextFieldWithAutoCompletionListProvider<String> {
+ public static class StringsCompletionProvider extends TextFieldWithAutoCompletionListProvider<String> implements DumbAware {
@Nullable private final Icon myIcon;
public StringsCompletionProvider(@Nullable final Collection<String> variants,
diff --git a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
index 753dc09..2debdbe 100644
--- a/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
+++ b/platform/lang-impl/src/com/intellij/ui/TextFieldWithAutoCompletionContributor.java
@@ -23,6 +23,8 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiDocumentManager;
@@ -37,7 +39,7 @@
/**
* @author Roman.Chernyatchik
*/
-public class TextFieldWithAutoCompletionContributor<T> extends CompletionContributor {
+public class TextFieldWithAutoCompletionContributor<T> extends CompletionContributor implements DumbAware {
private static final Key<TextFieldWithAutoCompletionListProvider> KEY = Key.create("text field simple completion available");
private static final Key<Boolean> AUTO_POPUP_KEY = Key.create("text Field simple completion auto-popup");
@@ -59,7 +61,7 @@
PsiFile file = parameters.getOriginalFile();
final TextFieldWithAutoCompletionListProvider<T> provider = file.getUserData(KEY);
- if (provider == null) {
+ if (provider == null || (DumbService.isDumb(file.getProject()) && !DumbService.isDumbAware(provider))) {
return;
}
String adv = provider.getAdvertisement();
diff --git a/java/java-impl/src/com/intellij/uiDesigner/SerializedComponentData.java b/platform/lang-impl/src/com/intellij/uiDesigner/SerializedComponentData.java
similarity index 100%
rename from java/java-impl/src/com/intellij/uiDesigner/SerializedComponentData.java
rename to platform/lang-impl/src/com/intellij/uiDesigner/SerializedComponentData.java
diff --git a/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java b/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java
index a687669..34c45ad 100644
--- a/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.java
+++ b/platform/lang-impl/src/com/intellij/unscramble/AnalyzeStacktraceUtil.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.
@@ -48,13 +48,12 @@
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
/**
* @author yole
*/
public class AnalyzeStacktraceUtil {
- public static ExtensionPointName<Filter> EP_NAME = ExtensionPointName.create("com.intellij.analyzeStacktraceFilter");
+ public static final ExtensionPointName<Filter> EP_NAME = ExtensionPointName.create("com.intellij.analyzeStacktraceFilter");
private AnalyzeStacktraceUtil() {
}
@@ -67,16 +66,7 @@
@Nullable
public static String getTextInClipboard() {
- final CopyPasteManager copyPasteManager = CopyPasteManager.getInstance();
- if (copyPasteManager.isDataFlavorAvailable(DataFlavor.stringFlavor)) {
- final Transferable contents = copyPasteManager.getContents();
- if (contents != null) {
- try {
- return (String)contents.getTransferData(DataFlavor.stringFlavor);
- } catch (Exception ignore) { }
- }
- }
- return null;
+ return CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
}
public interface ConsoleFactory {
@@ -116,7 +106,9 @@
toolbarActions.add(new CloseAction(executor, descriptor, project));
ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
consoleView.allowHeavyFilters();
- printStacktrace(consoleView, text);
+ if (consoleFactory == null) {
+ printStacktrace(consoleView, text);
+ }
return descriptor;
}
diff --git a/platform/lang-impl/src/com/intellij/usageView/UsageViewTypeLocation.java b/platform/lang-impl/src/com/intellij/usageView/UsageViewTypeLocation.java
deleted file mode 100644
index a0efac0..0000000
--- a/platform/lang-impl/src/com/intellij/usageView/UsageViewTypeLocation.java
+++ /dev/null
@@ -1,74 +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.usageView;
-
-import com.intellij.ide.TypePresentationService;
-import com.intellij.psi.*;
-import com.intellij.psi.meta.PsiMetaData;
-import com.intellij.psi.meta.PsiMetaOwner;
-import com.intellij.psi.meta.PsiPresentableMetaData;
-import com.intellij.lang.LangBundle;
-import com.intellij.lang.Language;
-import com.intellij.lang.findUsages.FindUsagesProvider;
-import com.intellij.lang.findUsages.LanguageFindUsages;
-import com.intellij.openapi.util.text.StringUtil;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author peter
- */
-public class UsageViewTypeLocation extends ElementDescriptionLocation {
- private UsageViewTypeLocation() {
- }
-
- public static final UsageViewTypeLocation INSTANCE = new UsageViewTypeLocation();
-
- @Override
- public ElementDescriptionProvider getDefaultProvider() {
- return DEFAULT_PROVIDER;
- }
-
- private static final ElementDescriptionProvider DEFAULT_PROVIDER = new ElementDescriptionProvider() {
- @Override
- public String getElementDescription(@NotNull final PsiElement psiElement, @NotNull final ElementDescriptionLocation location) {
- if (!(location instanceof UsageViewTypeLocation)) return null;
-
- if (psiElement instanceof PsiMetaOwner) {
- final PsiMetaData metaData = ((PsiMetaOwner)psiElement).getMetaData();
- if (metaData instanceof PsiPresentableMetaData) {
- return ((PsiPresentableMetaData)metaData).getTypeName();
- }
- }
-
- if (psiElement instanceof PsiFile) {
- return LangBundle.message("terms.file");
- }
- if (psiElement instanceof PsiDirectory) {
- return LangBundle.message("terms.directory");
- }
-
- final Language lang = psiElement.getLanguage();
- FindUsagesProvider provider = LanguageFindUsages.INSTANCE.forLanguage(lang);
- final String type = provider.getType(psiElement);
- if (StringUtil.isNotEmpty(type)) {
- return type;
- }
-
- return TypePresentationService.getService().getTypePresentableName(psiElement.getClass());
- }
- };
-}
\ No newline at end of file
diff --git a/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java b/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java
index de1d7e2..82b4ffe 100644
--- a/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.java
+++ b/platform/lang-impl/src/com/intellij/usageView/UsageViewUtil.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,8 @@
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.GeneratedSourcesFilter;
import com.intellij.openapi.util.TextRange;
@@ -155,4 +157,10 @@
});
}
+ public static void navigateTo(@NotNull UsageInfo info, boolean requestFocus) {
+ int offset = info.getNavigationOffset();
+ VirtualFile file = info.getVirtualFile();
+ Project project = info.getProject();
+ FileEditorManager.getInstance(project).openTextEditor(new OpenFileDescriptor(project, file, offset), requestFocus);
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/usageView/impl/UsageContextCallHierarchyPanel.java b/platform/lang-impl/src/com/intellij/usageView/impl/UsageContextCallHierarchyPanel.java
index 21e8742..ed41617 100644
--- a/platform/lang-impl/src/com/intellij/usageView/impl/UsageContextCallHierarchyPanel.java
+++ b/platform/lang-impl/src/com/intellij/usageView/impl/UsageContextCallHierarchyPanel.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,10 +28,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.usageView.UsageInfo;
import com.intellij.usageView.UsageViewBundle;
-import com.intellij.usages.PsiElementUsageTarget;
-import com.intellij.usages.UsageContextPanel;
-import com.intellij.usages.UsageTarget;
-import com.intellij.usages.UsageView;
+import com.intellij.usages.*;
import com.intellij.usages.impl.UsageContextPanelBase;
import com.intellij.usages.impl.UsageViewImpl;
import org.jetbrains.annotations.NotNull;
@@ -48,7 +45,7 @@
@NotNull
@Override
public UsageContextPanel create(@NotNull UsageView usageView) {
- return new UsageContextCallHierarchyPanel(((UsageViewImpl)usageView).getProject());
+ return new UsageContextCallHierarchyPanel(((UsageViewImpl)usageView).getProject(), usageView.getPresentation());
}
@Override
@@ -75,8 +72,8 @@
}
}
- public UsageContextCallHierarchyPanel(@NotNull Project project) {
- super(project);
+ public UsageContextCallHierarchyPanel(@NotNull Project project, @NotNull UsageViewPresentation presentation) {
+ super(project, presentation);
}
@Override
@@ -101,7 +98,7 @@
removeAll();
if (element == null) {
- JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview"), SwingConstants.CENTER);
+ JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview", myPresentation.getUsagesWord()), SwingConstants.CENTER);
add(titleComp, BorderLayout.CENTER);
revalidate();
}
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 1e8c431..3be0cfa 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/FileBasedIndexImpl.java
@@ -56,6 +56,9 @@
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDocumentTransactionListener;
+import com.intellij.psi.impl.PsiManagerImpl;
+import com.intellij.psi.impl.PsiTreeChangeEventImpl;
+import com.intellij.psi.impl.PsiTreeChangePreprocessor;
import com.intellij.psi.impl.cache.impl.id.PlatformIdTableBuilding;
import com.intellij.psi.impl.source.PsiFileImpl;
import com.intellij.psi.search.EverythingGlobalScope;
@@ -106,6 +109,7 @@
private final TObjectIntHashMap<ID<?, ?>> myIndexIdToVersionMap = new TObjectIntHashMap<ID<?, ?>>();
private final Set<ID<?, ?>> myNotRequiringContentIndices = new THashSet<ID<?, ?>>();
private final Set<ID<?, ?>> myRequiringContentIndices = new THashSet<ID<?, ?>>();
+ private final Set<ID<?, ?>> myPsiDependentIndices = new THashSet<ID<?, ?>>();
private final Set<FileType> myNoLimitCheckTypes = new THashSet<FileType>();
private final PerIndexDocumentVersionMap myLastIndexedDocStamps = new PerIndexDocumentVersionMap();
@@ -123,7 +127,7 @@
private final FileDocumentManager myFileDocumentManager;
private final FileTypeManager myFileTypeManager;
private final ConcurrentHashSet<ID<?, ?>> myUpToDateIndices = new ConcurrentHashSet<ID<?, ?>>();
- private final Map<Document, PsiFile> myTransactionMap = new THashMap<Document, PsiFile>();
+ private volatile SmartFMap<Document, PsiFile> myTransactionMap = SmartFMap.emptyMap();
@Nullable private final String myConfigPath;
@Nullable private final String myLogPath;
@@ -153,18 +157,14 @@
@Override
public void transactionStarted(final Document doc, final PsiFile file) {
if (file != null) {
- synchronized (myTransactionMap) {
- myTransactionMap.put(doc, file);
- }
+ myTransactionMap = myTransactionMap.plus(doc, file);
myUpToDateIndices.clear();
}
}
@Override
public void transactionCompleted(final Document doc, final PsiFile file) {
- synchronized (myTransactionMap) {
- myTransactionMap.remove(doc);
- }
+ myTransactionMap = myTransactionMap.minus(doc);
}
});
@@ -442,6 +442,7 @@
else {
myRequiringContentIndices.add(name);
}
+ if (extension instanceof PsiDependentIndex) myPsiDependentIndices.add(name);
myNoLimitCheckTypes.addAll(extension.getFileTypesWithSizeLimitNotApplicable());
break;
}
@@ -1084,13 +1085,13 @@
if (myProjectsBeingUpdated.contains(project)) return null;
SoftReference<ProjectIndexableFilesFilter> reference = project.getUserData(ourProjectFilesSetKey);
- ProjectIndexableFilesFilter data = reference != null ? reference.get() : null;
+ ProjectIndexableFilesFilter data = com.intellij.reference.SoftReference.dereference(reference);
if (data != null && data.myModificationCount == myFilesModCount) return data;
if (myCalcIndexableFilesLock.tryLock()) { // make best effort for calculating filter
try {
reference = project.getUserData(ourProjectFilesSetKey);
- data = reference != null ? reference.get() : null;
+ data = com.intellij.reference.SoftReference.dereference(reference);
if (data != null && data.myModificationCount == myFilesModCount) {
return data;
}
@@ -1321,20 +1322,21 @@
if (status.compareAndSet(REQUIRES_REBUILD, REBUILD_IN_PROGRESS)) {
cleanupProcessedFlag();
- try {
- clearIndex(indexId);
- } catch (StorageException ex) {
- requestRebuild(indexId, new Throwable(ex));
- }
-
+ advanceIndexVersion(indexId);
+
final Runnable rebuildRunnable = new Runnable() {
@Override
public void run() {
try {
+ doClearIndex(indexId);
if (!cleanupOnly) {
scheduleIndexRebuild(false);
}
}
+ catch (StorageException e) {
+ requestRebuild(indexId);
+ LOG.info(e);
+ }
finally {
status.compareAndSet(REBUILD_IN_PROGRESS, OK);
}
@@ -1380,9 +1382,17 @@
}
private void clearIndex(@NotNull final ID<?, ?> indexId) throws StorageException {
+ advanceIndexVersion(indexId);
+ doClearIndex(indexId);
+ }
+
+ private void doClearIndex(ID<?, ?> indexId) throws StorageException {
final UpdatableIndex<?, ?, FileContent> index = getIndex(indexId);
assert index != null : "Index with key " + indexId + " not found or not registered properly";
index.clear();
+ }
+
+ private void advanceIndexVersion(ID<?, ?> indexId) {
try {
IndexInfrastructure.rewriteVersion(IndexInfrastructure.getVersionFile(indexId), myIndexIdToVersionMap.get(indexId));
}
@@ -1392,12 +1402,13 @@
}
@NotNull
- private Set<Document> getUnsavedOrTransactedDocuments() {
- final Set<Document> docs = new THashSet<Document>(Arrays.asList(myFileDocumentManager.getUnsavedDocuments()));
- synchronized (myTransactionMap) {
- docs.addAll(myTransactionMap.keySet());
- }
- return docs;
+ private Set<Document> getUnsavedDocuments() {
+ return new THashSet<Document>(Arrays.asList(myFileDocumentManager.getUnsavedDocuments()));
+ }
+
+ @NotNull
+ private Set<Document> getTransactedDocuments() {
+ return myTransactionMap.keySet();
}
private void indexUnsavedDocuments(@NotNull ID<?, ?> indexId,
@@ -1408,7 +1419,8 @@
return; // no need to index unsaved docs
}
- final Set<Document> documents = getUnsavedOrTransactedDocuments();
+ Set<Document> documents = myPsiDependentIndices.contains(indexId) ? getTransactedDocuments() : getUnsavedDocuments();
+
if (!documents.isEmpty()) {
// now index unsaved data
final StorageGuard.Holder guard = setDataBufferingEnabled(true);
@@ -1437,7 +1449,11 @@
if (allDocsProcessed && !hasActiveTransactions()) {
ProgressManager.checkCanceled();
// assume all tasks were finished or cancelled in the same time
- myUpToDateIndices.add(indexId); // safe to set the flag here, because it will be cleared under the WriteAction
+ // safe to set the flag here, because it will be cleared under the WriteAction
+
+ // if we have uncommitted documents in unsaved documents, we may index old psi with new uncommitted doc,
+ // to properly reindex with new psi / new doc we don't mark index up to date in this case (IDEA-111448)
+ myUpToDateIndices.add(indexId);
}
}
}
@@ -1448,13 +1464,11 @@
}
private boolean hasActiveTransactions() {
- synchronized (myTransactionMap) {
- return !myTransactionMap.isEmpty();
- }
+ return !myTransactionMap.isEmpty();
}
private interface DocumentContent {
- String getText();
+ CharSequence getText();
long getModificationStamp();
}
@@ -1467,8 +1481,8 @@
}
@Override
- public String getText() {
- return myDocument.getText();
+ public CharSequence getText() {
+ return myDocument.getImmutableCharSequence();
}
@Override
@@ -1487,13 +1501,13 @@
}
@Override
- public String getText() {
+ public CharSequence getText() {
if (myFile.getViewProvider().getModificationStamp() != myDocument.getModificationStamp()) {
final ASTNode node = myFile.getNode();
assert node != null;
- return node.getText();
+ return node.getChars();
}
- return myDocument.getText();
+ return myDocument.getImmutableCharSequence();
}
@Override
@@ -1534,38 +1548,44 @@
final long currentDocStamp = content.getModificationStamp();
final long previousDocStamp = myLastIndexedDocStamps.getAndSet(document, requestedIndexId, currentDocStamp);
if (currentDocStamp != previousDocStamp) {
- final String contentText = content.getText();
- if (!isTooLarge(vFile, contentText.length()) &&
- getAffectedIndexCandidates(vFile).contains(requestedIndexId) &&
- getInputFilter(requestedIndexId).acceptInput(vFile)) {
- // Reasonably attempt to use same file content when calculating indices as we can evaluate them several at once and store in file content
- WeakReference<FileContentImpl> previousContentRef = document.getUserData(ourFileContentKey);
- FileContentImpl previousContent = previousContentRef != null ? previousContentRef.get() : null;
- final FileContentImpl newFc;
- if (previousContent != null && previousContent.getStamp() == currentDocStamp) {
- newFc = previousContent;
- }
- else {
- newFc = new FileContentImpl(vFile, contentText, vFile.getCharset(), currentDocStamp);
- document.putUserData(ourFileContentKey, new WeakReference<FileContentImpl>(newFc));
- }
+ final CharSequence contentText = content.getText();
+ FileTypeManagerImpl.cacheFileType(vFile, getFileType(vFile));
+ try {
+ if (!isTooLarge(vFile, contentText.length()) &&
+ getAffectedIndexCandidates(vFile).contains(requestedIndexId) &&
+ getInputFilter(requestedIndexId).acceptInput(vFile)) {
+ // Reasonably attempt to use same file content when calculating indices as we can evaluate them several at once and store in file content
+ WeakReference<FileContentImpl> previousContentRef = document.getUserData(ourFileContentKey);
+ FileContentImpl previousContent = com.intellij.reference.SoftReference.dereference(previousContentRef);
+ final FileContentImpl newFc;
+ if (previousContent != null && previousContent.getStamp() == currentDocStamp) {
+ newFc = previousContent;
+ }
+ else {
+ newFc = new FileContentImpl(vFile, contentText, vFile.getCharset(), currentDocStamp);
+ document.putUserData(ourFileContentKey, new WeakReference<FileContentImpl>(newFc));
+ }
- initFileContent(newFc, project, dominantContentFile);
+ initFileContent(newFc, project, dominantContentFile);
- if (content instanceof AuthenticContent) {
- newFc.putUserData(PlatformIdTableBuilding.EDITOR_HIGHLIGHTER, EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document));
- }
+ if (content instanceof AuthenticContent) {
+ newFc.putUserData(PlatformIdTableBuilding.EDITOR_HIGHLIGHTER, EditorHighlighterCache.getEditorHighlighterForCachesBuilding(document));
+ }
- final int inputId = Math.abs(getFileId(vFile));
- try {
- getIndex(requestedIndexId).update(inputId, newFc).compute();
- } catch (ProcessCanceledException pce) {
- myLastIndexedDocStamps.getAndSet(document, requestedIndexId, previousDocStamp);
- throw pce;
+ final int inputId = Math.abs(getFileId(vFile));
+ try {
+ getIndex(requestedIndexId).update(inputId, newFc).compute();
+ } catch (ProcessCanceledException pce) {
+ myLastIndexedDocStamps.getAndSet(document, requestedIndexId, previousDocStamp);
+ throw pce;
+ }
+ finally {
+ cleanFileContent(newFc, dominantContentFile);
+ }
}
- finally {
- cleanFileContent(newFc, dominantContentFile);
- }
+ }
+ finally {
+ FileTypeManagerImpl.cacheFileType(vFile, null);
}
}
return true;
@@ -1575,10 +1595,8 @@
@Nullable
private PsiFile findDominantPsiForDocument(@NotNull Document document, @Nullable Project project) {
- synchronized (myTransactionMap) {
- PsiFile psiFile = myTransactionMap.get(document);
- if (psiFile != null) return psiFile;
- }
+ PsiFile psiFile = myTransactionMap.get(document);
+ if (psiFile != null) return psiFile;
return project == null ? null : findLatestKnownPsiForUncomittedDocument(document, project);
}
@@ -1591,6 +1609,7 @@
for (ID<?, ?> indexId : myIndices.keySet()) {
final MapReduceIndex index = (MapReduceIndex)getIndex(indexId);
assert index != null;
+ if (myPsiDependentIndices.contains(indexId)) continue;
final IndexStorage indexStorage = index.getStorage();
((MemoryIndexStorage)indexStorage).setBufferingEnabled(enabled);
}
@@ -1681,10 +1700,20 @@
}
public void indexFileContent(@Nullable Project project, @NotNull com.intellij.ide.caches.FileContent content) {
+ VirtualFile file = content.getVirtualFile();
+ // if file was scheduled for update due to vfs events then it is present in myFilesToUpdate
+ // in this case we consider that current indexing (out of roots backed CacheUpdater) will cover its content
+ // todo this assumption isn't correct for vfs events happened between content loading and indexing itself
+ // proper fix will when events handling will be out of direct execution by EDT
+ myChangedFilesCollector.myFilesToUpdate.remove(file);
+ doIndexFileContent(project, content);
+ }
+
+ private void doIndexFileContent(@Nullable Project project, @NotNull com.intellij.ide.caches.FileContent content) {
myChangedFilesCollector.ensureAllInvalidateTasksCompleted();
final VirtualFile file = content.getVirtualFile();
- FileTypeManagerImpl.cacheFileType(file, file.getFileType());
+ FileTypeManagerImpl.cacheFileType(file, getFileType(file));
try {
PsiFile psiFile = null;
@@ -1737,11 +1766,19 @@
}
}
+ private static FileType getFileType(VirtualFile file) {
+ FileType fileType = file.getFileType();
+ if (fileType == FileTypes.PLAIN_TEXT && FileTypeManagerImpl.isFileTypeDetectedFromContent(file)) {
+ fileType = FileTypes.UNKNOWN;
+ }
+ return fileType;
+ }
+
private List<ID<?, ?>> getAffectedIndexCandidates(VirtualFile file) {
if (file.isDirectory()) {
return isProjectOrWorkspaceFile(file, null) ? Collections.<ID<?,?>>emptyList() : myIndicesForDirectories;
}
- FileType fileType = file.getFileType();
+ FileType fileType = getFileType(file);
if(isProjectOrWorkspaceFile(file, fileType)) return Collections.emptyList();
List<ID<?, ?>> ids = myFileType2IndicesWithFileTypeInfoMap.get(fileType);
if (ids == null) ids = myIndicesWithoutFileTypeInfo;
@@ -1969,26 +2006,32 @@
// can be client that used indices between before and after events, in such case indices are up to date due to force update
// with old content)
if (!fileIsDirectory && !isTooLarge(file)) {
- final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
- //noinspection ForLoopReplaceableByForEach
- boolean scheduleForUpdate = false;
- boolean resetStamp = false;
+ FileTypeManagerImpl.cacheFileType(file, getFileType(file));
+ try {
+ final List<ID<?, ?>> candidates = getAffectedIndexCandidates(file);
+ //noinspection ForLoopReplaceableByForEach
+ boolean scheduleForUpdate = false;
+ boolean resetStamp = false;
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0, size = candidates.size(); i < size; ++i) {
- final ID<?, ?> indexId = candidates.get(i);
- if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
- if (IndexingStamp.isFileIndexed(file, indexId, IndexInfrastructure.getIndexCreationStamp(indexId))) {
- IndexingStamp.update(file, indexId, IndexInfrastructure.INVALID_STAMP2);
- resetStamp = true;
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0, size = candidates.size(); i < size; ++i) {
+ final ID<?, ?> indexId = candidates.get(i);
+ if (needsFileContentLoading(indexId) && getInputFilter(indexId).acceptInput(file)) {
+ if (IndexingStamp.isFileIndexed(file, indexId, IndexInfrastructure.getIndexCreationStamp(indexId))) {
+ IndexingStamp.update(file, indexId, IndexInfrastructure.INVALID_STAMP2);
+ resetStamp = true;
+ }
+ scheduleForUpdate = true;
}
- scheduleForUpdate = true;
+ }
+
+ if (scheduleForUpdate) {
+ if (resetStamp) IndexingStamp.flushCache(file);
+ scheduleForUpdate(file);
}
}
-
- if (scheduleForUpdate) {
- if (resetStamp) IndexingStamp.flushCache(file);
- scheduleForUpdate(file);
+ finally {
+ FileTypeManagerImpl.cacheFileType(file, null);
}
}
@@ -2037,61 +2080,42 @@
cleanProcessedFlag(file);
IndexingStamp.flushCache(file);
- final List<ID<?, ?>> affectedIndexCandidates = IndexingStamp.getIndexedIds(file);
- final List<ID<?, ?>> affectedIndices = new ArrayList<ID<?, ?>>(affectedIndexCandidates.size());
+ Collection<ID<?, ?>> existingIndexedIds = IndexingStamp.getIndexedIds(file);
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0, size = affectedIndexCandidates.size(); i < size; ++i) {
- final ID<?, ?> indexId = affectedIndexCandidates.get(i);
- try {
- if (!needsFileContentLoading(indexId)) {
+ for(ID<?, ?> indexId:existingIndexedIds) {
+ if (myNotRequiringContentIndices.contains(indexId)) {
+ try {
updateSingleIndex(indexId, file, null);
+ } catch (StorageException e) {
+ LOG.info(e);
+ requestRebuild(indexId);
}
- else { // the index requires file content
- affectedIndices.add(indexId);
- }
- }
- catch (StorageException e) {
- LOG.info(e);
- requestRebuild(indexId);
}
}
- if (!affectedIndices.isEmpty()) {
- if (markForReindex && !isTooLarge(file)) {
- // only mark the file as unindexed, reindex will be done lazily
+ final Collection<ID<?, ?>> indexedIdsToUpdate = ContainerUtil.intersection(existingIndexedIds, myRequiringContentIndices);
+
+ if (markForReindex) {
+ // only mark the file as unindexed, reindex will be done lazily
+ if (!indexedIdsToUpdate.isEmpty()) {
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
- for (ID<?, ?> indexId : affectedIndices) {
- IndexingStamp.update(file, indexId, IndexInfrastructure.INVALID_STAMP2);
- }
+ IndexingStamp.removeAllIndexedState(file);
}
});
// the file is for sure not a dir and it was previously indexed by at least one index
- scheduleForUpdate(file);
- }
- else {
- myFutureInvalidations.offer(new InvalidationTask(file) {
- @Override
- public void run() {
- removeFileDataFromIndices(affectedIndices, file);
- }
- });
+ if (!isTooLarge(file)) scheduleForUpdate(file);
}
}
- if (!markForReindex) {
- final boolean removedFromUpdateQueue = myFilesToUpdate.remove(file);// no need to update it anymore
- if (removedFromUpdateQueue && affectedIndices.isEmpty()) {
- // Currently the file is about to be deleted and previously it was scheduled for update and not processed up to now.
- // Because the file was scheduled for update, at the moment of scheduling it was marked as unindexed,
- // so, to be on the safe side, we have to schedule data invalidation from all content-requiring indices for this file
+ else {
+ myFilesToUpdate.remove(file);
+
+ if (!indexedIdsToUpdate.isEmpty()) {
myFutureInvalidations.offer(new InvalidationTask(file) {
@Override
public void run() {
- List<ID<?, ?>> candidates = new ArrayList<ID<?, ?>>(affectedIndexCandidates);
- candidates.retainAll(myRequiringContentIndices);
- removeFileDataFromIndices(candidates, file);
+ removeFileDataFromIndices(indexedIdsToUpdate, file);
}
});
}
@@ -2279,9 +2303,12 @@
}
}
removeFileDataFromIndices(affected, file);
+ if (onlyRemoveOutdatedData && file instanceof VirtualFileSystemEntry) {
+ ((VirtualFileSystemEntry)file).setFileIndexed(false); // we should be able index this file via UnindexedFileFinder later
+ }
}
else {
- indexFileContent(project, fileContent);
+ doIndexFileContent(project, fileContent);
}
}
finally {
@@ -2346,7 +2373,7 @@
if (file instanceof VirtualFileWithId) {
try {
- FileTypeManagerImpl.cacheFileType(file, file.getFileType());
+ FileTypeManagerImpl.cacheFileType(file, getFileType(file));
boolean oldStuff = true;
if (file.isDirectory() || !isTooLarge(file)) {
@@ -2402,7 +2429,6 @@
if (myProgressIndicator != null && file.isDirectory()) { // once for dir is cheap enough
myProgressIndicator.checkCanceled();
myProgressIndicator.setText("Scanning files to index");
- myProgressIndicator.setText2(file.getPresentableUrl());
}
}
return true;
@@ -2430,16 +2456,14 @@
private boolean isTooLarge(@NotNull VirtualFile file) {
if (SingleRootFileViewProvider.isTooLargeForIntelligence(file)) {
- final FileType type = file.getFileType();
- return !myNoLimitCheckTypes.contains(type);
+ return !myNoLimitCheckTypes.contains(getFileType(file));
}
return false;
}
private boolean isTooLarge(@NotNull VirtualFile file, long contentSize) {
if (SingleRootFileViewProvider.isTooLargeForIntelligence(file, contentSize)) {
- final FileType type = file.getFileType();
- return !myNoLimitCheckTypes.contains(type);
+ return !myNoLimitCheckTypes.contains(getFileType(file));
}
return false;
}
@@ -2453,6 +2477,33 @@
public void registerIndexableSet(@NotNull IndexableFileSet set, @Nullable Project project) {
myIndexableSets.add(set);
myIndexableSetToProjectMap.put(set, project);
+ if (project != null) {
+ ((PsiManagerImpl)PsiManager.getInstance(project)).addTreeChangePreprocessor(new PsiTreeChangePreprocessor() {
+ @Override
+ public void treeChanged(@NotNull PsiTreeChangeEventImpl event) {
+ if (event.isGenericChange() &&
+ event.getCode() == PsiTreeChangeEventImpl.PsiEventType.CHILDREN_CHANGED) {
+ PsiFile file = event.getFile();
+ if (file != null) {
+ VirtualFile virtualFile = file.getVirtualFile();
+ if (virtualFile instanceof VirtualFileWithId) {
+ boolean wasIndexed = false;
+ for(ID<?,?> psiBackedIndex:myPsiDependentIndices) {
+ if (isFileIndexed(virtualFile, psiBackedIndex)) {
+ IndexingStamp.update(virtualFile, psiBackedIndex, IndexInfrastructure.INVALID_STAMP2);
+ wasIndexed = true;
+ }
+ }
+ if (wasIndexed) {
+ myChangedFilesCollector.scheduleForUpdate(virtualFile);
+ IndexingStamp.flushCache(virtualFile);
+ }
+ }
+ }
+ }
+ }
+ });
+ }
}
@Override
@@ -2582,10 +2633,6 @@
if (indicator != null) indicator.checkCanceled();
processor.processFile(file);
- if (indicator != null && file.isDirectory()) {
- // once for directory should be cheap enough
- indicator.setText2(file.getPresentableUrl());
- }
return true;
}
});
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 35a304e..ebf6906 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/IndexingStamp.java
@@ -31,7 +31,7 @@
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
-import java.util.List;
+import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.ArrayBlockingQueue;
@@ -51,6 +51,10 @@
private TObjectLongHashMap<ID<?, ?>> myIndexStamps;
private boolean myIsDirty = false;
+ private Timestamps() {
+ myIsDirty = true;
+ }
+
private Timestamps(@Nullable DataInputStream stream) throws IOException {
if (stream != null) {
try {
@@ -181,7 +185,15 @@
}
}
- public static List<ID<?,?>> getIndexedIds(final VirtualFile file) {
+ public static void removeAllIndexedState(VirtualFile file) {
+ synchronized (getStripedLock(file)) {
+ if (file instanceof NewVirtualFile && file.isValid()) {
+ myTimestampsCache.put(file, new Timestamps());
+ }
+ }
+ }
+
+ public static Collection<ID<?,?>> getIndexedIds(final VirtualFile file) {
synchronized (getStripedLock(file)) {
try {
Timestamps stamp = createOrGetTimeStamp(file);
@@ -205,7 +217,6 @@
public static void flushCaches() {
flushCache(null);
- myTimestampsCache.clear();
}
public static void flushCache(@Nullable VirtualFile finishedFile) {
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 77dfef3..f49f70d 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MapReduceIndex.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.Processor;
+import com.intellij.util.SmartList;
import com.intellij.util.io.PersistentHashMap;
import gnu.trove.THashMap;
import gnu.trove.TObjectObjectProcedure;
@@ -203,8 +204,7 @@
}
@Override
- public final Computable<Boolean> update(final int inputId, @Nullable Input content) {
- assert myInputsIndex != null;
+ public final Computable<Boolean> update(final int inputId, @Nullable final Input content) {
final Map<Key, Value> data = content != null ? myIndexer.map(content) : Collections.<Key, Value>emptyMap();
@@ -222,6 +222,9 @@
updateWithMap(inputId, data, new Callable<Collection<Key>>() {
@Override
public Collection<Key> call() throws Exception {
+ if (myInputsIndex == null) {
+ return new SmartList<Key>((Key)(Integer)inputId);
+ }
final Collection<Key> oldKeys = myInputsIndex.get(inputId);
return oldKeys == null? Collections.<Key>emptyList() : oldKeys;
}
@@ -243,7 +246,9 @@
};
}
- protected void updateWithMap(final int inputId, @NotNull Map<Key, Value> newData, @NotNull Callable<Collection<Key>> oldKeysGetter) throws StorageException {
+ protected void updateWithMap(final int inputId,
+ @NotNull Map<Key, Value> newData,
+ @NotNull Callable<Collection<Key>> oldKeysGetter) throws StorageException {
getWriteLock().lock();
try {
try {
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 2b27622..3ef7d2a 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/MemoryIndexStorage.java
@@ -187,9 +187,11 @@
@Override
@NotNull
public ValueContainer<Value> read(final Key key) throws StorageException {
- final ValueContainer<Value> valueContainer = myMap.get(key);
- if (valueContainer != null) {
- return valueContainer;
+ if (myBufferingEnabled.get()) {
+ final ValueContainer<Value> valueContainer = myMap.get(key);
+ if (valueContainer != null) {
+ return valueContainer;
+ }
}
return myBackendStorage.read(key);
diff --git a/platform/lang-impl/src/com/intellij/util/indexing/PsiDependentIndex.java b/platform/lang-impl/src/com/intellij/util/indexing/PsiDependentIndex.java
new file mode 100644
index 0000000..991c75b
--- /dev/null
+++ b/platform/lang-impl/src/com/intellij/util/indexing/PsiDependentIndex.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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;
+
+/**
+ * Created by Maxim.Mossienko on 1/4/14.
+ */
+public interface PsiDependentIndex {
+}
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 51b2330..589db0f 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/UpdatableIndex.java
@@ -17,10 +17,8 @@
package com.intellij.util.indexing;
import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.ThrowableComputable;
import org.jetbrains.annotations.Nullable;
-import java.util.concurrent.Callable;
import java.util.concurrent.locks.Lock;
/**
@@ -33,6 +31,8 @@
void flush() throws StorageException;
+ /**
+ */
Computable<Boolean> update(int inputId, @Nullable Input content);
Lock getReadLock();
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 db33e68..ae9424d 100644
--- a/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java
+++ b/platform/lang-impl/src/com/intellij/util/indexing/ValueContainerImpl.java
@@ -20,10 +20,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.SmartList;
import com.intellij.util.containers.EmptyIterator;
-import gnu.trove.THashMap;
-import gnu.trove.TIntHashSet;
-import gnu.trove.TIntIterator;
-import gnu.trove.TObjectObjectProcedure;
+import gnu.trove.*;
import java.util.*;
@@ -34,6 +31,7 @@
class ValueContainerImpl<Value> extends UpdatableValueContainer<Value> implements Cloneable{
private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.ValueContainerImpl");
private final static Object myNullValue = new Object();
+ private static final int MAX_FILES = 20000;
// there is no volatile as we modify under write lock and read under read lock
// Most often (80%) we store 0 or one mapping, then we store them in two fields: myInputIdMapping, myInputIdMappingValue
// when there are several value mapped, myInputIdMapping is THashMap<Value, Data>, myInputIdMappingValue = null
@@ -52,12 +50,19 @@
if (input instanceof Integer) {
idSet = new IdSet(3);
idSet.add(((Integer)input).intValue());
+ idSet.add(inputId);
resetFileSetForValue(value, idSet);
}
- else {
+ else if (input instanceof TIntHashSet) {
idSet = (TIntHashSet)input;
+ idSet.add(inputId);
+
+ if (idSet.size() > MAX_FILES) {
+ resetFileSetForValue(value, new IdBitSet(idSet));
+ }
+ } else if (input instanceof IdBitSet) {
+ ((IdBitSet)input).set(inputId);
}
- idSet.add(inputId);
}
}
@@ -113,6 +118,10 @@
if (((Integer)input).intValue() != inputId) {
return false;
}
+ } else if (input instanceof IdBitSet) {
+ IdBitSet bitSet = (IdBitSet)input;
+ boolean removed = bitSet.remove(inputId);
+ if (bitSet.numberOfBitsSet() > 0) return removed;
}
if (!(myInputIdMapping instanceof THashMap)) {
@@ -201,6 +210,9 @@
if (input instanceof Integer ){
return inputId == ((Integer)input).intValue();
}
+ if (input instanceof IdBitSet) {
+ return ((IdBitSet)input).get(inputId);
+ }
return false;
}
@@ -217,6 +229,15 @@
}
};
}
+ if (input instanceof IdBitSet) {
+ return new IntPredicate() {
+ final IdBitSet myIdBitSet = (IdBitSet)input;
+ @Override
+ boolean contains(int id) {
+ return myIdBitSet.get(id);
+ }
+ };
+ }
return new IntPredicate() {
final TIntHashSet mySet = (TIntHashSet)input;
@Override
@@ -235,6 +256,28 @@
}
else if (input instanceof Integer ){
it = new SingleValueIterator(((Integer)input).intValue());
+ } else if (input instanceof IdBitSet) {
+ it = new IntIterator() {
+ private final IdBitSet myIdBitSet = (IdBitSet)input;
+ private int nextSetBit = myIdBitSet.nextSetBit(0);
+
+ @Override
+ public boolean hasNext() {
+ return nextSetBit != -1;
+ }
+
+ @Override
+ public int next() {
+ int setBit = nextSetBit;
+ nextSetBit = myIdBitSet.nextSetBit(setBit + 1);
+ return setBit;
+ }
+
+ @Override
+ public int size() {
+ return myIdBitSet.numberOfBitsSet();
+ }
+ };
}
else {
it = EMPTY_ITERATOR;
@@ -265,6 +308,8 @@
clone.myInputIdMapping = mapCopy((THashMap<Value, Object>)myInputIdMapping);
} else if (myInputIdMappingValue instanceof TIntHashSet) {
clone.myInputIdMappingValue = ((TIntHashSet)myInputIdMappingValue).clone();
+ } else if (myInputIdMappingValue instanceof IdBitSet) {
+ clone.myInputIdMappingValue = ((IdBitSet)myInputIdMappingValue).clone();
}
return clone;
}
@@ -303,6 +348,8 @@
public boolean execute(Value key, Object val) {
if (val instanceof TIntHashSet) {
newMapping.put(key, ((TIntHashSet)val).clone());
+ } else if (val instanceof IdBitSet) {
+ newMapping.put(key, ((IdBitSet)val).clone());
}
else {
newMapping.put(key, val);
@@ -313,7 +360,9 @@
} else {
container.myInputIdMapping = myInputIdMapping;
container.myInputIdMappingValue = myInputIdMappingValue instanceof TIntHashSet ?
- ((TIntHashSet)myInputIdMappingValue).clone():myInputIdMappingValue;
+ ((TIntHashSet)myInputIdMappingValue).clone():
+ myInputIdMappingValue instanceof IdBitSet ?
+ ((IdBitSet)myInputIdMappingValue).clone():myInputIdMappingValue;
}
return container;
}
@@ -323,17 +372,23 @@
Object input = getInput(value);
if (input != null) {
- if (input instanceof IdSet) {
- ((IdSet)input).ensureCapacity(count);
- } else if (input instanceof Integer) {
+ if (input instanceof Integer) {
IdSet idSet = new IdSet(count + 1);
idSet.add(((Integer)input).intValue());
resetFileSetForValue(value, idSet);
+ } else if (input instanceof IdSet) {
+ IdSet idSet = (IdSet)input;
+ int nextSize = idSet.size() + count;
+ if (nextSize <= MAX_FILES) idSet.ensureCapacity(count);
+ else {
+ resetFileSetForValue(value, new IdBitSet(idSet));
+ }
}
return;
}
- attachFileSetForNewValue(value, new IdSet(count));
+ final Object fileSet = count > MAX_FILES ? new IdBitSet(count): new IdSet(count);
+ attachFileSetForNewValue(value, fileSet);
}
private void attachFileSetForNewValue(Value value, Object fileSet) {
@@ -413,6 +468,8 @@
public boolean execute(Value key, Object val) {
if (val instanceof TIntHashSet) {
cloned.put(key, ((TIntHashSet)val).clone());
+ } else if (val instanceof IdBitSet) {
+ cloned.put(key, ((IdBitSet)val).clone());
}
return true;
}
@@ -442,4 +499,121 @@
}
}
+ private static class IdBitSet implements Cloneable {
+ private static final int SHIFT = 6;
+ private static final int BITS_PER_WORD = 1 << SHIFT;
+ private static final int MASK = BITS_PER_WORD - 1;
+ private long[] myBitMask;
+ private int myBitsSet;
+ private int myLastUsedSlot;
+
+ public IdBitSet(TIntHashSet set) {
+ this(calcMax(set));
+ set.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ set(value);
+ return true;
+ }
+ });
+ }
+
+ private static int calcMax(TIntHashSet set) {
+ final int[] minMax = new int[2];
+ minMax[0] = set.iterator().next();
+ minMax[1] = minMax[0];
+ set.forEach(new TIntProcedure() {
+ @Override
+ public boolean execute(int value) {
+ minMax[0] = Math.min(minMax[0], value);
+ minMax[1] = Math.max(minMax[1], value);
+ return true;
+ }
+ });
+ return minMax[1];
+ }
+
+ public IdBitSet(int max) {
+ myBitMask = new long[(calcCapacity(max) >> SHIFT) + 1];
+ }
+
+ public void set(int bitIndex) {
+ boolean set = get(bitIndex);
+ if (!set) {
+ ++myBitsSet;
+ int wordIndex = bitIndex >> SHIFT;
+ if (wordIndex >= myBitMask.length) {
+ long[] n = new long[Math.max(calcCapacity(myBitMask.length), wordIndex + 1)];
+ System.arraycopy(myBitMask, 0, n, 0, myBitMask.length);
+ myBitMask = n;
+ }
+ myBitMask[wordIndex] |= 1L << (bitIndex & MASK);
+ myLastUsedSlot = Math.max(myLastUsedSlot, wordIndex);
+ }
+ }
+
+ private static int calcCapacity(int length) {
+ return length + 3 * (length / 5);
+ }
+
+ int numberOfBitsSet() {
+ return myBitsSet;
+ }
+
+ boolean remove(int bitIndex) {
+ if (!get(bitIndex)) return false;
+ --myBitsSet;
+ int wordIndex = bitIndex >> SHIFT;
+ myBitMask[wordIndex] &= ~(1L << (bitIndex & MASK));
+ if (wordIndex == myLastUsedSlot) {
+ while(myLastUsedSlot >= 0 && myBitMask[myLastUsedSlot] == 0) --myLastUsedSlot;
+ }
+ return true;
+ }
+
+ boolean get(int bitIndex) {
+ int wordIndex = bitIndex >> SHIFT;
+ boolean result = false;
+ if (wordIndex < myBitMask.length) {
+ result = (myBitMask[wordIndex] & (1L << (bitIndex & MASK))) != 0;
+ }
+
+ return result;
+ }
+
+ public IdBitSet clone() {
+ try {
+ IdBitSet clone = (IdBitSet)super.clone();
+ if (myBitMask.length != myLastUsedSlot + 1) { // trim to size
+ long[] longs = new long[myLastUsedSlot + 1];
+ System.arraycopy(myBitMask, 0, longs, 0, longs.length);
+ myBitMask = longs;
+ }
+ clone.myBitMask = myBitMask.clone();
+ return clone;
+ } catch (CloneNotSupportedException ex) {
+ LOG.error(ex);
+ return null;
+ }
+ }
+
+ public int nextSetBit(int bitIndex) {
+ int wordIndex = bitIndex >> SHIFT;
+ if (wordIndex >= myBitMask.length) {
+ return -1;
+ }
+
+ long word = myBitMask[wordIndex] & (-1L << bitIndex);
+
+ while (true) {
+ if (word != 0) {
+ return (wordIndex * BITS_PER_WORD) + Long.numberOfTrailingZeros(word);
+ }
+ if (++wordIndex == myBitMask.length) {
+ return -1;
+ }
+ word = myBitMask[wordIndex];
+ }
+ }
+ }
}
diff --git a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java
index 087b646..416d584 100644
--- a/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java
+++ b/platform/lang-impl/src/com/intellij/util/ui/tree/AbstractFileTreeTable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -166,12 +166,12 @@
}
int ret = Messages.showYesNoCancelDialog(myProject, message, title, "Override", "Do Not Override", "Cancel",
Messages.getWarningIcon());
- if (ret == 0) {
+ if (ret == Messages.YES) {
for (VirtualFile file : subdirectoryMappings.keySet()) {
myModel.setValueAt(null, new DefaultMutableTreeNode(file), 1);
}
}
- return ret != 2;
+ return ret != Messages.CANCEL;
}
@NotNull
@@ -336,7 +336,7 @@
}
public static class ProjectRootNode extends ConvenientNode<Project> {
- private VirtualFileFilter myFilter;
+ private final VirtualFileFilter myFilter;
public ProjectRootNode(@NotNull Project project) {
this(project, VirtualFileFilter.ALL);
@@ -437,7 +437,7 @@
public static class FileNode extends ConvenientNode<VirtualFile> {
private final Project myProject;
- private VirtualFileFilter myFilter;
+ private final VirtualFileFilter myFilter;
public FileNode(@NotNull VirtualFile file, @NotNull final Project project) {
this(file, project, VirtualFileFilter.ALL);
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 b181876..2c0317a 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/InstalledPackagesPanel.java
@@ -2,19 +2,24 @@
import com.google.common.collect.Lists;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.ui.Messages;
-import com.intellij.ui.DoubleClickListener;
-import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
import com.intellij.util.CatchingConsumer;
import com.intellij.util.Consumer;
+import com.intellij.util.IconUtil;
import com.intellij.util.ObjectUtils;
-import com.intellij.util.containers.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.ui.StatusText;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,20 +30,16 @@
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.*;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class InstalledPackagesPanel extends JPanel {
- protected final JButton myInstallButton;
- private final JButton myUninstallButton;
- private final JButton myUpgradeButton;
+ private final AnActionButton myUpgradeButton;
+ protected final AnActionButton myInstallButton;
+ private final AnActionButton myUninstallButton;
protected final JBTable myPackagesTable;
private DefaultTableModel myPackagesTableModel;
@@ -50,19 +51,9 @@
private final Set<InstalledPackage> myWaitingToUpgrade = ContainerUtil.newHashSet();
public InstalledPackagesPanel(Project project, PackagesNotificationPanel area) {
- super(new GridBagLayout());
+ super(new BorderLayout());
myProject = project;
myNotificationArea = area;
- myInstallButton = new JButton("Install");
- myUninstallButton = new JButton("Uninstall");
- myUpgradeButton = new JButton("Upgrade");
- myInstallButton.setMnemonic('I');
- myUninstallButton.setMnemonic('U');
- myUpgradeButton.setMnemonic('p');
-
- myInstallButton.setEnabled(false);
- myUninstallButton.setEnabled(false);
- myUpgradeButton.setEnabled(false);
myPackagesTableModel = new DefaultTableModel(new String[]{"Package", "Version", "Latest"}, 0) {
@Override
@@ -79,25 +70,41 @@
};
myPackagesTable.getTableHeader().setReorderingAllowed(false);
- Insets anInsets = new Insets(2, 2, 2, 2);
- JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myPackagesTable,
- ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
- ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- scrollPane.setPreferredSize(new Dimension(500, 500));
- add(scrollPane, new GridBagConstraints(0, 0, 1, 3, 1.0, 1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
- anInsets, 0, 0));
+ myUpgradeButton = new AnActionButton("Upgrade", IconUtil.getMoveUpIcon()) {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ upgradeAction();
+ }
+ };
+ final ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myPackagesTable).disableUpDownActions()
+ .setAddAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ if (myPackageManagementService != null) {
+ ManagePackagesDialog dialog = createManagePackagesDialog();
+ dialog.show();
+ }
+ }
+ })
+ .setRemoveAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ uninstallAction();
+ }
+ })
+ .addExtraAction(myUpgradeButton);
- addUninstallAction();
- addUpgradeAction();
+ decorator.setPreferredSize(new Dimension(500, 500));
+ add(decorator.createPanel());
+ myInstallButton = decorator.getActionsPanel().getAnActionButton(CommonActionsPanel.Buttons.ADD);
+ myUninstallButton = decorator.getActionsPanel().getAnActionButton(CommonActionsPanel.Buttons.REMOVE);
+ myInstallButton.setEnabled(false);
+ myUninstallButton.setEnabled(false);
+ myUpgradeButton.setEnabled(false);
- add(myInstallButton,
- new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- anInsets, 0, 0));
- add(myUninstallButton,
- new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
- anInsets, 0, 0));
- add(myUpgradeButton,
- new GridBagConstraints(1, 2, 1, 1, 0.0, 1.0, GridBagConstraints.NORTH, GridBagConstraints.HORIZONTAL, anInsets, 0, 0));
+ myInstallButton.getTemplatePresentation().setText("Install");
+ myUninstallButton.getTemplatePresentation().setText("Uninstall");
+
myPackagesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
@@ -106,16 +113,6 @@
}
});
- myInstallButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- if (myPackageManagementService != null) {
- ManagePackagesDialog dialog = createManagePackagesDialog();
- dialog.show();
- }
- }
- });
-
new DoubleClickListener() {
@Override
protected boolean onDoubleClick(MouseEvent e) {
@@ -161,38 +158,33 @@
myPathChangedListeners.add(consumer);
}
- private void addUpgradeAction() {
- myUpgradeButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- final int[] rows = myPackagesTable.getSelectedRows();
- if (myPackageManagementService != null) {
- final Set<String> upgradedPackages = new HashSet<String>();
- final Set<String> packagesShouldBePostponed = getPackagesToPostpone();
- for (int row : rows) {
- final Object packageObj = myPackagesTableModel.getValueAt(row, 0);
- if (packageObj instanceof InstalledPackage) {
- InstalledPackage pkg = (InstalledPackage)packageObj;
- final String packageName = pkg.getName();
- final String currentVersion = pkg.getVersion();
- final String availableVersion = (String)myPackagesTableModel.getValueAt(row, 2);
+ private void upgradeAction() {
+ final int[] rows = myPackagesTable.getSelectedRows();
+ if (myPackageManagementService != null) {
+ final Set<String> upgradedPackages = new HashSet<String>();
+ final Set<String> packagesShouldBePostponed = getPackagesToPostpone();
+ for (int row : rows) {
+ final Object packageObj = myPackagesTableModel.getValueAt(row, 0);
+ if (packageObj instanceof InstalledPackage) {
+ InstalledPackage pkg = (InstalledPackage)packageObj;
+ final String packageName = pkg.getName();
+ final String currentVersion = pkg.getVersion();
+ final String availableVersion = (String)myPackagesTableModel.getValueAt(row, 2);
- if (packagesShouldBePostponed.contains(packageName)) {
- myWaitingToUpgrade.add((InstalledPackage)packageObj);
- }
- else if (PackageVersionComparator.VERSION_COMPARATOR.compare(currentVersion, availableVersion) < 0) {
- upgradePackage(pkg, availableVersion);
- upgradedPackages.add(packageName);
- }
- }
+ if (packagesShouldBePostponed.contains(packageName)) {
+ myWaitingToUpgrade.add((InstalledPackage)packageObj);
}
-
- if (myCurrentlyInstalling.isEmpty() && upgradedPackages.isEmpty() && !myWaitingToUpgrade.isEmpty()) {
- upgradePostponedPackages();
+ else if (PackageVersionComparator.VERSION_COMPARATOR.compare(currentVersion, availableVersion) < 0) {
+ upgradePackage(pkg, availableVersion);
+ upgradedPackages.add(packageName);
}
}
}
- });
+
+ if (myCurrentlyInstalling.isEmpty() && upgradedPackages.isEmpty() && !myWaitingToUpgrade.isEmpty()) {
+ upgradePostponedPackages();
+ }
+ }
}
private void upgradePostponedPackages() {
@@ -221,29 +213,39 @@
public void run() {
final PackageManagementService.Listener listener = new PackageManagementService.Listener() {
@Override
- public void operationStarted(String packageName) {
- myPackagesTable.setPaintBusy(true);
- myCurrentlyInstalling.add(packageName);
+ public void operationStarted(final String packageName) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ myPackagesTable.setPaintBusy(true);
+ myCurrentlyInstalling.add(packageName);
+ }
+ });
}
@Override
- public void operationFinished(String packageName, @Nullable String errorDescription) {
- myPackagesTable.clearSelection();
- updatePackages(selPackageManagementService);
- myPackagesTable.setPaintBusy(false);
- myCurrentlyInstalling.remove(packageName);
- if (errorDescription == null) {
- myNotificationArea.showSuccess("Package " + packageName + " successfully upgraded");
- }
- else {
- myNotificationArea.showError("Upgrade packages failed. <a href=\"xxx\">Details...</a>",
- "Upgrade Packages Failed",
- "Upgrade packages failed.\n" + errorDescription);
- }
+ public void operationFinished(final String packageName, @Nullable final String errorDescription) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ myPackagesTable.clearSelection();
+ updatePackages(selPackageManagementService);
+ myPackagesTable.setPaintBusy(false);
+ myCurrentlyInstalling.remove(packageName);
+ if (errorDescription == null) {
+ myNotificationArea.showSuccess("Package " + packageName + " successfully upgraded");
+ }
+ else {
+ myNotificationArea.showError("Upgrade packages failed. <a href=\"xxx\">Details...</a>",
+ "Upgrade Packages Failed",
+ "Upgrade packages failed.\n" + errorDescription);
+ }
- if (myCurrentlyInstalling.isEmpty() && !myWaitingToUpgrade.isEmpty()) {
- upgradePostponedPackages();
- }
+ if (myCurrentlyInstalling.isEmpty() && !myWaitingToUpgrade.isEmpty()) {
+ upgradePostponedPackages();
+ }
+ }
+ });
}
};
PackageManagementServiceEx serviceEx = getServiceEx();
@@ -282,7 +284,7 @@
public void run() {
final int[] selected = myPackagesTable.getSelectedRows();
boolean upgradeAvailable = false;
- boolean canUninstall = true;
+ boolean canUninstall = selected.length != 0;
boolean canUpgrade = true;
if (myPackageManagementService != null && selected.length != 0) {
for (int i = 0; i != selected.length; ++i) {
@@ -321,21 +323,26 @@
return true;
}
- private void addUninstallAction() {
- myUninstallButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(final ActionEvent e) {
- final List<InstalledPackage> packages = getSelectedPackages();
- final PackageManagementService selPackageManagementService = myPackageManagementService;
- if (selPackageManagementService != null) {
- PackageManagementService.Listener listener = new PackageManagementService.Listener() {
+ private void uninstallAction() {
+ final List<InstalledPackage> packages = getSelectedPackages();
+ final PackageManagementService selPackageManagementService = myPackageManagementService;
+ if (selPackageManagementService != null) {
+ PackageManagementService.Listener listener = new PackageManagementService.Listener() {
+ @Override
+ public void operationStarted(String packageName) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
- public void operationStarted(String packageName) {
+ public void run() {
myPackagesTable.setPaintBusy(true);
}
+ });
+ }
+ @Override
+ public void operationFinished(final String packageName, @Nullable final String errorDescription) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
- public void operationFinished(String packageName, @Nullable String errorDescription) {
+ public void run() {
myPackagesTable.clearSelection();
updatePackages(selPackageManagementService);
myPackagesTable.setPaintBusy(false);
@@ -353,11 +360,11 @@
"Uninstall packages failed.\n" + errorDescription);
}
}
- };
- myPackageManagementService.uninstallPackages(packages, listener);
+ });
}
- }
- });
+ };
+ myPackageManagementService.uninstallPackages(packages, listener);
+ }
}
@NotNull
@@ -377,54 +384,65 @@
myPackageManagementService = packageManagementService;
myPackagesTable.clearSelection();
myPackagesTableModel.getDataVector().clear();
- doUpdatePackages(packageManagementService);
+ myPackagesTableModel.fireTableDataChanged();
+ if (packageManagementService != null) {
+ doUpdatePackages(packageManagementService);
+ }
}
- public void doUpdatePackages(final PackageManagementService packageManagementService) {
+ private void onUpdateStarted() {
myPackagesTable.setPaintBusy(true);
+ myPackagesTable.getEmptyText().setText("Loading...");
+ }
+
+ private void onUpdateFinished() {
+ myPackagesTable.setPaintBusy(false);
+ myPackagesTable.getEmptyText().setText(StatusText.DEFAULT_EMPTY_TEXT);
+ }
+
+ public void doUpdatePackages(@NotNull final PackageManagementService packageManagementService) {
+ onUpdateStarted();
final Application application = ApplicationManager.getApplication();
application.executeOnPooledThread(new Runnable() {
@Override
public void run() {
Collection<InstalledPackage> packages = Lists.newArrayList();
- if (packageManagementService != null) {
- try {
- packages = packageManagementService.getInstalledPackages();
- }
- catch (IOException e) {
- // do nothing, we already have an empty list
- }
- finally {
- final Collection<InstalledPackage> finalPackages = packages;
+ try {
+ packages = packageManagementService.getInstalledPackages();
+ }
+ catch (IOException e) {
+ // do nothing, we already have an empty list
+ }
+ finally {
+ final Collection<InstalledPackage> finalPackages = packages;
- final Map<String, RepoPackage> cache = buildNameToPackageMap(packageManagementService.getAllPackagesCached());
- final boolean shouldFetchLatestVersionsForOnlyInstalledPackages = shouldFetchLatestVersionsForOnlyInstalledPackages();
- if (cache.isEmpty()) {
- if (!shouldFetchLatestVersionsForOnlyInstalledPackages) {
- refreshLatestVersions();
- }
+ final Map<String, RepoPackage> cache = buildNameToPackageMap(packageManagementService.getAllPackagesCached());
+ final boolean shouldFetchLatestVersionsForOnlyInstalledPackages = shouldFetchLatestVersionsForOnlyInstalledPackages();
+ if (cache.isEmpty()) {
+ if (!shouldFetchLatestVersionsForOnlyInstalledPackages) {
+ refreshLatestVersions();
}
- application.invokeLater(new Runnable() {
- @Override
- public void run() {
- if (packageManagementService == myPackageManagementService) {
- myPackagesTableModel.getDataVector().clear();
- for (InstalledPackage pkg : finalPackages) {
- RepoPackage repoPackage = cache.get(pkg.getName());
- final String version = repoPackage != null ? repoPackage.getLatestVersion() : null;
- myPackagesTableModel
- .addRow(new Object[]{pkg, pkg.getVersion(), version == null ? "" : version});
- }
- if (!cache.isEmpty()) {
- myPackagesTable.setPaintBusy(false);
- }
- if (shouldFetchLatestVersionsForOnlyInstalledPackages) {
- setLatestVersionsForInstalledPackages();
- }
+ }
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (packageManagementService == myPackageManagementService) {
+ myPackagesTableModel.getDataVector().clear();
+ for (InstalledPackage pkg : finalPackages) {
+ RepoPackage repoPackage = cache.get(pkg.getName());
+ final String version = repoPackage != null ? repoPackage.getLatestVersion() : null;
+ myPackagesTableModel
+ .addRow(new Object[]{pkg, pkg.getVersion(), version == null ? "" : version});
+ }
+ if (!cache.isEmpty()) {
+ onUpdateFinished();
+ }
+ if (shouldFetchLatestVersionsForOnlyInstalledPackages) {
+ setLatestVersionsForInstalledPackages();
}
}
- }, ModalityState.any());
- }
+ }
+ });
}
}
});
@@ -439,21 +457,24 @@
if (serviceEx == null) {
return;
}
- final AtomicInteger restPackageCount = new AtomicInteger(0);
- for (int i = 0; i < myPackagesTableModel.getRowCount(); ++i) {
+ int packageCount = myPackagesTableModel.getRowCount();
+ if (packageCount == 0) {
+ onUpdateFinished();
+ }
+ final AtomicInteger inProgressPackageCount = new AtomicInteger(packageCount);
+ for (int i = 0; i < packageCount; ++i) {
final int finalIndex = i;
final InstalledPackage pkg = getInstalledPackageAt(finalIndex);
- restPackageCount.incrementAndGet();
- serviceEx.fetchLatestVersion(pkg.getName(), new CatchingConsumer<String, Exception>() {
+ serviceEx.fetchLatestVersion(pkg, new CatchingConsumer<String, Exception>() {
private void decrement() {
- if (restPackageCount.decrementAndGet() == 0) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ if (inProgressPackageCount.decrementAndGet() == 0) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
- myPackagesTable.setPaintBusy(false);
+ onUpdateFinished();
}
- }, ModalityState.any());
+ });
}
}
@@ -535,8 +556,10 @@
final JLabel cell = (JLabel)super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
final String version = (String)table.getValueAt(row, 1);
final String availableVersion = (String)table.getValueAt(row, 2);
- cell.setIcon(PackageVersionComparator.VERSION_COMPARATOR.compare(version, availableVersion) < 0 && column == 2 ?
- AllIcons.Vcs.Arrow_right : null);
+ boolean update = column == 2 &&
+ StringUtil.isNotEmpty(availableVersion) &&
+ PackageVersionComparator.VERSION_COMPARATOR.compare(version, availableVersion) < 0;
+ cell.setIcon(update ? AllIcons.Vcs.Arrow_right : null);
final Object pyPackage = table.getValueAt(row, 0);
if (pyPackage instanceof InstalledPackage) {
cell.setToolTipText(((InstalledPackage) pyPackage).getTooltipText());
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
index 07f5477..8bdb938 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/ManagePackagesDialog.java
@@ -275,16 +275,26 @@
}
private void updateInstalledPackages() {
- try {
- Collection<InstalledPackage> installedPackages = myController.getInstalledPackages();
- myInstalledPackages.clear();
- for (InstalledPackage pkg : installedPackages) {
- myInstalledPackages.add(pkg.getName());
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ final Collection<InstalledPackage> installedPackages = myController.getInstalledPackages();
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ myInstalledPackages.clear();
+ for (InstalledPackage pkg : installedPackages) {
+ myInstalledPackages.add(pkg.getName());
+ }
+ }
+ });
+ }
+ catch(IOException e) {
+ LOG.info("Error updating list of installed packages:" + e);
+ }
}
- }
- catch(IOException e) {
- LOG.info("Error updating list of installed packages:" + e);
- }
+ });
}
public void initModel() {
@@ -448,7 +458,7 @@
myVersionCheckBox.setSelected(false);
myVersionComboBox.setEnabled(false);
myOptionsField.setEnabled(false);
- myDescriptionTextArea.setText("");
+ myDescriptionTextArea.setText("<html><body style='text-align: center;padding-top:20px;'>Loading...</body></html>");
setDownloadStatus(true);
final Object pyPackage = myPackages.getSelectedValue();
@@ -483,14 +493,17 @@
myController.fetchPackageDetails(packageName, new CatchingConsumer<String, Exception>() {
@Override
public void consume(final String details) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
if (myPackages.getSelectedValue() == pyPackage) {
myDescriptionTextArea.setText(details);
- }
+ myDescriptionTextArea.setCaretPosition(0);
+ }/* else {
+ do nothing, because other package gets selected
+ }*/
}
- }, ModalityState.any());
+ });
}
@Override
@@ -501,6 +514,7 @@
}
else {
myInstallButton.setEnabled(false);
+ myDescriptionTextArea.setText("");
}
setDownloadStatus(false);
}
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java
index 7fb47ac..923bdf9 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/PackageManagementServiceEx.java
@@ -15,6 +15,6 @@
public abstract boolean shouldFetchLatestVersionsForOnlyInstalledPackages();
- public abstract void fetchLatestVersion(@NotNull String packageName, @NotNull final CatchingConsumer<String, Exception> consumer);
+ public abstract void fetchLatestVersion(@NotNull InstalledPackage pkg, @NotNull final CatchingConsumer<String, Exception> consumer);
}
diff --git a/platform/lang-impl/src/com/intellij/webcore/packaging/RepoPackage.java b/platform/lang-impl/src/com/intellij/webcore/packaging/RepoPackage.java
index 76f7d38..444c205 100644
--- a/platform/lang-impl/src/com/intellij/webcore/packaging/RepoPackage.java
+++ b/platform/lang-impl/src/com/intellij/webcore/packaging/RepoPackage.java
@@ -2,6 +2,9 @@
import org.jetbrains.annotations.Nullable;
+import java.util.Collection;
+import java.util.Collections;
+
/**
* User: catherine
*/
@@ -9,17 +12,21 @@
private final String myName;
private final String myRepoUrl;
@Nullable final String myLatestVersion;
+ private final Collection<String> myKeywords;
public RepoPackage(String name, String repoUrl) {
- myName = name;
- myRepoUrl = repoUrl;
- myLatestVersion = null;
+ this(name, repoUrl, null);
}
public RepoPackage(String name, String repoUrl, @Nullable String latestVersion) {
+ this(name, repoUrl, latestVersion, Collections.<String>emptyList());
+ }
+
+ public RepoPackage(String name, String repoUrl, @Nullable String latestVersion, Collection<String> keywords) {
myName = name;
myRepoUrl = repoUrl;
myLatestVersion = latestVersion;
+ myKeywords = keywords;
}
public String getName() {
@@ -35,6 +42,8 @@
return myLatestVersion;
}
+ public Collection<String> getKeywords() { return myKeywords; }
+
@Override
public int compareTo(Object o) {
if (o instanceof RepoPackage)
diff --git a/platform/lang-impl/testSources/com/intellij/ide/GeneratedSourceFileChangeTrackerTest.java b/platform/lang-impl/testSources/com/intellij/ide/GeneratedSourceFileChangeTrackerTest.java
new file mode 100644
index 0000000..ebed233
--- /dev/null
+++ b/platform/lang-impl/testSources/com/intellij/ide/GeneratedSourceFileChangeTrackerTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.ide;
+
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.GeneratedSourcesFilter;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public class GeneratedSourceFileChangeTrackerTest extends CodeInsightFixtureTestCase {
+ private final GeneratedSourcesFilter myGeneratedSourcesFilter = new GeneratedSourcesFilter() {
+ @Override
+ public boolean isGeneratedSource(@NotNull VirtualFile file, @NotNull Project project) {
+ return file.getName().startsWith("Gen");
+ }
+ };
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ Extensions.getRootArea().getExtensionPoint(GeneratedSourcesFilter.EP_NAME).registerExtension(myGeneratedSourcesFilter);
+ getTracker().projectOpened();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ Extensions.getRootArea().getExtensionPoint(GeneratedSourcesFilter.EP_NAME).unregisterExtension(myGeneratedSourcesFilter);
+ getTracker().projectClosed();
+ super.tearDown();
+ }
+
+ public void testChangeOrdinary() {
+ PsiFile file = myFixture.configureByText("Ordinary.txt", "");
+ myFixture.type('a');
+ assertFalse(isEditedGeneratedFile(file));
+ }
+
+ public void testChangeGenerated() {
+ PsiFile file = myFixture.configureByText("Gen.txt", "");
+ myFixture.type('a');
+ assertTrue(isEditedGeneratedFile(file));
+ }
+
+ public void testChangeGeneratedExternally() throws IOException {
+ PsiFile file = myFixture.configureByText("Gen.txt", "");
+ VfsUtil.saveText(file.getVirtualFile(), "abc");
+ assertFalse(isEditedGeneratedFile(file));
+ }
+
+ private boolean isEditedGeneratedFile(PsiFile file) {
+ return getTracker().isEditedGeneratedFile(file.getVirtualFile());
+ }
+
+ private GeneratedSourceFileChangeTracker getTracker() {
+ return GeneratedSourceFileChangeTracker.getInstance(getProject());
+ }
+}
diff --git a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java
index c833f81..836a6c9 100644
--- a/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java
+++ b/platform/lvcs-impl/src/com/intellij/history/core/ChangeListStorageImpl.java
@@ -138,7 +138,7 @@
@NotNull HyperlinkEvent event) {
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
if ("url".equals(event.getDescription())) {
- BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270");
+ BrowserUtil.browse("http://youtrack.jetbrains.net/issue/IDEA-71270");
}
else {
File file = new File(logFile);
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 50d7a0f..3c30750 100644
--- a/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.java
+++ b/platform/lvcs-impl/src/com/intellij/history/integration/IdeaGateway.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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.history.integration;
import com.intellij.history.core.LocalHistoryFacade;
@@ -35,7 +34,6 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.encoding.EncodingRegistry;
-import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.util.NullableFunction;
@@ -52,7 +50,7 @@
= Key.create("LocalHistory.SAVED_DOCUMENT_CONTENT_AND_STAMP_KEY");
public boolean isVersioned(@NotNull VirtualFile f) {
- if (!isInLocalFS(f)) return false;
+ if (!f.isInLocalFileSystem()) return false;
String fileName = f.getName();
if (!f.isDirectory() && fileName.endsWith(".class")) return false;
@@ -69,10 +67,6 @@
return openProjects.length != 0 || !FileTypeManager.getInstance().isFileIgnored(f);
}
- private static boolean isInLocalFS(VirtualFile file) {
- return file.isInLocalFileSystem() && !(file.getFileSystem() instanceof TempFileSystem);
- }
-
public boolean areContentChangesVersioned(@NotNull VirtualFile f) {
return isVersioned(f) && !f.isDirectory() && areContentChangesVersioned(f.getName());
}
@@ -83,7 +77,7 @@
public boolean ensureFilesAreWritable(@NotNull Project p, @NotNull List<VirtualFile> ff) {
ReadonlyStatusHandler h = ReadonlyStatusHandler.getInstance(p);
- return !h.ensureFilesWritable(VfsUtil.toVirtualFileArray(ff)).hasReadonlyFiles();
+ return !h.ensureFilesWritable(VfsUtilCore.toVirtualFileArray(ff)).hasReadonlyFiles();
}
@Nullable
@@ -166,12 +160,7 @@
}
private static List<VirtualFile> getLocalRoots() {
- return ContainerUtil.filter(ManagingFS.getInstance().getLocalRoots(), new Condition<VirtualFile>() {
- @Override
- public boolean value(VirtualFile file) {
- return isInLocalFS(file);
- }
- });
+ return Arrays.asList(ManagingFS.getInstance().getLocalRoots());
}
private void doCreateChildrenForPathOnly(@NotNull DirectoryEntry parent,
diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryBundle.java b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryBundle.java
index df58d44..993a429 100644
--- a/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryBundle.java
+++ b/platform/lvcs-impl/src/com/intellij/history/integration/LocalHistoryBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
package com.intellij.history.integration;
import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,16 +25,16 @@
import java.util.ResourceBundle;
public class LocalHistoryBundle {
- private static final String PATH_TO_BUNDLE = "com.intellij.history.integration.LocalHistoryBundle";
- private static Reference<ResourceBundle> ourBundle;
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
+ private static final String PATH_TO_BUNDLE = "com.intellij.history.integration.LocalHistoryBundle";
+ private static Reference<ResourceBundle> ourBundle;
+
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java
index b1fc222..8423c9a 100644
--- a/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java
+++ b/platform/lvcs-impl/src/com/intellij/history/integration/ui/views/HistoryDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -408,7 +408,7 @@
if (questions.isEmpty()) return true;
return Messages.showYesNoDialog(myProject, message("message.do.you.want.to.proceed", formatQuestions(questions)),
- CommonBundle.getWarningTitle(), Messages.getWarningIcon()) == 0;
+ CommonBundle.getWarningTitle(), Messages.getWarningIcon()) == Messages.YES;
}
private String formatQuestions(List<String> questions) {
diff --git a/platform/platform-api/platform-api.iml b/platform/platform-api/platform-api.iml
index f6769b4..df91a19 100644
--- a/platform/platform-api/platform-api.iml
+++ b/platform/platform-api/platform-api.iml
@@ -34,6 +34,7 @@
<orderEntry type="module" module-name="editor-ui-api" exported="" />
<orderEntry type="library" name="pty4j" level="project" />
<orderEntry type="library" name="Guava" level="project" />
+ <orderEntry type="library" name="http-client" level="project" />
</component>
</module>
diff --git a/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java b/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java
new file mode 100644
index 0000000..79fff54
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/execution/configurations/EncodingEnvironmentUtil.java
@@ -0,0 +1,105 @@
+/*
+ * 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.execution.configurations;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.encoding.EncodingManager;
+import com.intellij.openapi.vfs.encoding.EncodingProjectManager;
+import com.intellij.util.EnvironmentUtil;
+import com.intellij.util.PlatformUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.nio.charset.Charset;
+import java.util.Map;
+
+public class EncodingEnvironmentUtil {
+
+ private static final Logger LOG = Logger.getInstance(EncodingEnvironmentUtil.class);
+ private static final String LC_ALL = "LC_ALL";
+ private static final String LC_CTYPE = "LC_CTYPE";
+ private static final String LANG = "LANG";
+
+ /**
+ * Sets default encoding on Mac if it's undefined. <br/>
+ * On Mac default character encoding is defined by several environment variables: LC_ALL, LC_CTYPE and LANG.
+ * See <a href='http://www.gnu.org/software/gettext/manual/html_node/Locale-Environment-Variables.html'>details</a>.
+ * <p>
+ * Unfortunately, Mac OSX has a special behavior:<br/>
+ * These environment variables aren't passed to an IDE, if the IDE is launched from Spotlight.<br/>
+ * Unfortunately, even {@link com.intellij.util.EnvironmentUtil#getEnvironment()} doesn't have these variables.<p/>
+ * As a result, no encoding environment variables are passed to Ruby/Node.js/Python/other processes that are launched from IDE.
+ * Thus, these processes wrongly assume that the default encoding is US-ASCII.
+ * <p/>
+ *
+ * The workaround this method applies is to set LC_CTYPE environment variable if LC_ALL, LC_CTYPE or LANG aren't set before. <br/>
+ * LC_CTYPE value is taken from "Settings | File Encodings".
+ *
+ * @param commandLine GeneralCommandLine instance
+ * @param project Project instance if any
+ */
+ public static void fixDefaultEncodingIfMac(@NotNull GeneralCommandLine commandLine, @Nullable Project project) {
+ if (SystemInfo.isMac) {
+ if (!isLocaleDefined(commandLine)) {
+ Charset charset = getCharset(project);
+ commandLine.getEnvironment().put(LC_CTYPE, charset.name());
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Fixed mac locale: " + charset.name());
+ }
+ }
+ }
+ }
+
+ private static boolean isLocaleDefined(@NotNull GeneralCommandLine commandLine) {
+ Map<String, String> env = commandLine.getEnvironment();
+ if (isLocaleDefined(env)) {
+ return true;
+ }
+ if (commandLine.isPassParentEnvironment()) {
+ // 'parentEnv' calculation logic should be kept in sync with GeneralCommandLine.setupEnvironment
+ Map<String, String> parentEnv = PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606
+ : EnvironmentUtil.getEnvironmentMap();
+ if (isLocaleDefined(parentEnv)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isLocaleDefined(@NotNull Map<String, String> env) {
+ return env.containsKey(LC_ALL) || env.containsKey(LC_CTYPE) || env.containsKey(LANG);
+ }
+
+ @NotNull
+ private static Charset getCharset(@Nullable Project project) {
+ Charset charset = null;
+ if (project != null) {
+ charset = EncodingProjectManager.getInstance(project).getDefaultCharset();
+ }
+ if (charset == null) {
+ charset = EncodingManager.getInstance().getDefaultCharset();
+ }
+ if (charset == null) {
+ charset = CharsetToolkit.UTF8_CHARSET;
+ }
+ return charset;
+ }
+
+
+}
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 0b6dc4c..a42a1bf 100644
--- a/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java
+++ b/platform/platform-api/src/com/intellij/execution/configurations/GeneralCommandLine.java
@@ -15,7 +15,6 @@
*/
package com.intellij.execution.configurations;
-import com.google.common.collect.Maps;
import com.intellij.execution.CommandLineUtil;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Platform;
@@ -27,12 +26,10 @@
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
-import com.pty4j.PtyProcess;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -65,10 +62,8 @@
private Charset myCharset = CharsetToolkit.getDefaultSystemCharset();
private boolean myRedirectErrorStream = false;
private Map<Object, Object> myUserData = null;
- private boolean myStartProcessWithPty = false;
- public GeneralCommandLine() {
- }
+ public GeneralCommandLine() { }
public GeneralCommandLine(@NotNull String... command) {
this(Arrays.asList(command));
@@ -147,15 +142,6 @@
return myPassParentEnvironment;
}
- /**
- * If argument is true the process created with Pseudo-Terminal (PTY).
- * This works only on Unix. On Windows the option is ignored.
- */
- public GeneralCommandLine withPty(boolean startProcessWithPty) {
- myStartProcessWithPty = startProcessWithPty;
- return this;
- }
-
public void addParameters(final String... parameters) {
for (String parameter : parameters) {
addParameter(parameter);
@@ -185,6 +171,10 @@
myCharset = charset;
}
+ public boolean isRedirectErrorStream() {
+ return myRedirectErrorStream;
+ }
+
public void setRedirectErrorStream(final boolean redirectErrorStream) {
myRedirectErrorStream = redirectErrorStream;
}
@@ -255,20 +245,6 @@
}
try {
- if (myStartProcessWithPty && SystemInfo.isUnix) {
- try {
- Map<String, String> env = Maps.newHashMap();
- setupEnvironment(env);
- if (myRedirectErrorStream) {
- LOG.error("Launching process with PTY and redirected error stream is unsupported yet");
- }
- return PtyProcessHolder.doExec(myWorkDirectory, commands, env);
- }
- catch (Throwable e) {
- LOG.error("Couldn't run process with PTY", e);
- }
- }
-
return startProcess(commands);
}
catch (IOException e) {
@@ -277,13 +253,7 @@
}
}
- private static class PtyProcessHolder { // holder for lazy PtyProcess class loading
- private static Process doExec(File workDirectory, List<String> commands, Map<String, String> env) throws IOException {
- return PtyProcess.exec(ArrayUtil.toStringArray(commands), env, workDirectory != null ? workDirectory.getPath() : null, true);
- }
- }
-
- private Process startProcess(List<String> commands) throws IOException {
+ protected Process startProcess(@NotNull List<String> commands) throws IOException {
ProcessBuilder builder = new ProcessBuilder(commands);
setupEnvironment(builder.environment());
builder.directory(myWorkDirectory);
@@ -304,11 +274,11 @@
}
}
- private void setupEnvironment(final Map<String, String> environment) {
+ protected void setupEnvironment(@NotNull Map<String, String> environment) {
environment.clear();
if (myPassParentEnvironment) {
- environment.putAll(PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606
+ environment.putAll(PlatformUtils.isAppCode() ? System.getenv() // Temporarily fix for OC-8606
: EnvironmentUtil.getEnvironmentMap());
}
diff --git a/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java b/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java
new file mode 100644
index 0000000..5e3d74c
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/execution/configurations/PtyCommandLine.java
@@ -0,0 +1,61 @@
+/*
+ * 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.execution.configurations;
+
+import com.google.common.collect.Maps;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.util.ArrayUtil;
+import com.pty4j.PtyProcess;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A flavor of GeneralCommandLine to start processes with Pseudo-Terminal (PTY).
+ *
+ * Note: this works only on Unix, on Windows regular processes are used instead.
+ */
+public class PtyCommandLine extends GeneralCommandLine {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.execution.configurations.PtyCommandLine");
+
+ public PtyCommandLine() { }
+
+ @Override
+ protected Process startProcess(@NotNull List<String> commands) throws IOException {
+ if (SystemInfo.isUnix) {
+ try {
+ Map<String, String> env = Maps.newHashMap();
+ setupEnvironment(env);
+
+ if (isRedirectErrorStream()) {
+ LOG.error("Launching process with PTY and redirected error stream is unsupported yet");
+ }
+
+ File workDirectory = getWorkDirectory();
+ return PtyProcess.exec(ArrayUtil.toStringArray(commands), env, workDirectory != null ? workDirectory.getPath() : null, true);
+ }
+ catch (Throwable e) {
+ LOG.error("Couldn't run process with PTY", e);
+ }
+ }
+
+ return super.startProcess(commands);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java b/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java
index 8c27990..cf1129a 100644
--- a/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java
+++ b/platform/platform-api/src/com/intellij/execution/filters/BrowserHyperlinkInfo.java
@@ -33,6 +33,6 @@
}
public static void openUrl(String url) {
- BrowserUtil.launchBrowser(url);
+ BrowserUtil.browse(url);
}
}
diff --git a/platform/platform-api/src/com/intellij/execution/filters/HyperlinkInfoBase.java b/platform/platform-api/src/com/intellij/execution/filters/HyperlinkInfoBase.java
new file mode 100644
index 0000000..2529ca8
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/execution/filters/HyperlinkInfoBase.java
@@ -0,0 +1,33 @@
+/*
+ * 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.execution.filters;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.awt.RelativePoint;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author nik
+ */
+public abstract class HyperlinkInfoBase implements HyperlinkInfo {
+ public abstract void navigate(@NotNull Project project, @Nullable RelativePoint hyperlinkLocationPoint);
+
+ @Override
+ public void navigate(Project project) {
+ navigate(project, null);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java
index 1039fe4..fb8c9a4 100644
--- a/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java
+++ b/platform/platform-api/src/com/intellij/execution/process/CapturingProcessHandler.java
@@ -18,6 +18,7 @@
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
import org.jetbrains.annotations.NotNull;
import java.nio.charset.Charset;
@@ -70,6 +71,16 @@
* @param timeoutInMilliseconds non-positive means infinity
*/
public ProcessOutput runProcess(int timeoutInMilliseconds) {
+ return runProcess(timeoutInMilliseconds, true);
+ }
+
+ /**
+ * Starts process with specified timeout
+ *
+ * @param timeoutInMilliseconds non-positive means infinity
+ * @param destroyOnTimeout whether to kill the process after timeout passes
+ */
+ public ProcessOutput runProcess(int timeoutInMilliseconds, boolean destroyOnTimeout) {
if (timeoutInMilliseconds <= 0) {
return runProcess();
}
@@ -79,7 +90,9 @@
myOutput.setExitCode(getProcess().exitValue());
}
else {
- destroyProcess();
+ if (destroyOnTimeout) {
+ destroyProcess();
+ }
myOutput.setTimeout();
}
return myOutput;
@@ -93,4 +106,24 @@
}
return super.getCharset();
}
+
+ @NotNull
+ public ProcessOutput runProcessWithProgressIndicator(@NotNull ProgressIndicator indicator) {
+ startNotify();
+ while (!waitFor(100)) {
+ if (indicator.isCanceled()) {
+ if (!isProcessTerminating() && !isProcessTerminated()) {
+ destroyProcess();
+ }
+ break;
+ }
+ }
+ if (waitFor()) {
+ myOutput.setExitCode(getProcess().exitValue());
+ }
+ else {
+ LOG.info("runProcess: exit value unavailable");
+ }
+ return myOutput;
+ }
}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java b/platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java
index 06c9c4b..75e4acd 100644
--- a/platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.java
+++ b/platform/platform-api/src/com/intellij/execution/process/ProcessTerminatedListener.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,19 +19,22 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.StatusBar;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
/**
* @author dyoma
*/
public class ProcessTerminatedListener extends ProcessAdapter {
+ @NonNls protected static final String EXIT_CODE_ENTRY = "$EXIT_CODE$";
+ @NonNls protected static final String EXIT_CODE_REGEX = "\\$EXIT_CODE\\$";
+
private static final Key<ProcessTerminatedListener> KEY = new Key<ProcessTerminatedListener>("processTerminatedListener");
+
private final String myProcessFinishedMessage;
private final Project myProject;
- @NonNls protected static final String EXIT_CODE_ENTRY = "$EXIT_CODE$";
- @NonNls
- protected static final String EXIT_CODE_REGEX = "\\$EXIT_CODE\\$";
private ProcessTerminatedListener(final Project project, final String processFinishedMessage) {
myProject = project;
@@ -62,7 +65,7 @@
public void processTerminated(ProcessEvent event) {
final ProcessHandler processHandler = event.getProcessHandler();
processHandler.removeProcessListener(this);
- final String message = myProcessFinishedMessage.replaceAll(EXIT_CODE_REGEX, String.valueOf(event.getExitCode()));
+ final String message = myProcessFinishedMessage.replaceAll(EXIT_CODE_REGEX, stringifyExitCode(event.getExitCode()));
processHandler.notifyTextAvailable(message, ProcessOutputTypes.SYSTEM);
if (myProject != null) ApplicationManager.getApplication().invokeLater(new Runnable(){
public void run() {
@@ -71,4 +74,23 @@
}
});
}
+
+ @NotNull
+ private static String stringifyExitCode(int exitCode) {
+ // Quote from http://support.microsoft.com/kb/308558:
+ // If the result code has the "C0000XXX" format, the task did not complete successfully (the "C" indicates an error condition).
+ // The most common "C" error code is "0xC000013A: The application terminated as a result of a CTRL+C".
+ if (SystemInfo.isWindows && exitCode >= 0xC0000000 && exitCode < 0xD0000000) {
+ StringBuilder result = new StringBuilder();
+ result.append(exitCode);
+ result.append(" (0x").append(Integer.toHexString(exitCode).toUpperCase());
+ if (exitCode == 0xC000013A) {
+ // reporting a detailed reason for a well-known exit code
+ result.append(": interrupted by Ctrl+C");
+ }
+ result.append(")");
+ return result.toString();
+ }
+ return String.valueOf(exitCode);
+ }
}
diff --git a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java
index 3191ac0..00c2073 100644
--- a/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java
+++ b/platform/platform-api/src/com/intellij/execution/util/ExecUtil.java
@@ -29,6 +29,7 @@
import org.jetbrains.annotations.Nullable;
import java.io.*;
+import java.nio.charset.Charset;
import java.util.*;
public class ExecUtil {
@@ -160,9 +161,24 @@
@Nullable
public static String execAndReadLine(final String... command) {
+ return execAndReadLine(null, command);
+ }
+
+ @Nullable
+ public static String execAndReadLine(@Nullable Charset charset, final String... command) {
try {
- final Process process = new GeneralCommandLine(command).createProcess();
- final BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
+ return readFirstLine(new GeneralCommandLine(command).createProcess().getInputStream(), charset);
+ }
+ catch (Exception ignored) {
+ return null;
+ }
+ }
+
+ @Nullable
+ public static String readFirstLine(@NotNull InputStream inputStream, @Nullable Charset charset) {
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ BufferedReader reader = new BufferedReader(charset == null ? new InputStreamReader(inputStream) : new InputStreamReader(inputStream, charset));
+ try {
try {
return reader.readLine();
}
@@ -170,8 +186,9 @@
reader.close();
}
}
- catch (Exception ignored) { }
- return null;
+ catch (IOException ignored) {
+ return null;
+ }
}
/**
diff --git a/platform/platform-api/src/com/intellij/featureStatistics/FeatureStatisticsBundle.java b/platform/platform-api/src/com/intellij/featureStatistics/FeatureStatisticsBundle.java
index b4d2bf4..317ee64 100644
--- a/platform/platform-api/src/com/intellij/featureStatistics/FeatureStatisticsBundle.java
+++ b/platform/platform-api/src/com/intellij/featureStatistics/FeatureStatisticsBundle.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -29,18 +30,18 @@
* @author max
*/
public class FeatureStatisticsBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(key), key, params);
+ }
+
private static Reference<ResourceBundle> ourBundle;
private static final Logger LOG = Logger.getInstance(FeatureStatisticsBundle.class);
-
@NonNls private static final String BUNDLE = "messages.FeatureStatisticsBundle";
private FeatureStatisticsBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(key), key, params);
- }
-
private static ResourceBundle getBundle(final String key) {
ResourceBundle providerBundle = ProvidersBundles.INSTANCE.get(key);
if (providerBundle != null) {
@@ -54,8 +55,7 @@
}
}
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/ide/BrowserSettingsProvider.java b/platform/platform-api/src/com/intellij/ide/BrowserSettingsProvider.java
deleted file mode 100644
index 6357628..0000000
--- a/platform/platform-api/src/com/intellij/ide/BrowserSettingsProvider.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide;
-
-import com.intellij.openapi.options.UnnamedConfigurable;
-
-/**
- * @author spleaner
- */
-public abstract class BrowserSettingsProvider implements UnnamedConfigurable {
- @Override
- public void disposeUIResources() { }
-}
diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
index 881bda6..2f18d3c 100644
--- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
+++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java
@@ -15,57 +15,29 @@
*/
package com.intellij.ide;
-import com.intellij.CommonBundle;
-import com.intellij.Patches;
-import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.util.ExecUtil;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Ref;
+import com.intellij.ide.browsers.BrowserLauncher;
import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.*;
-import com.intellij.ui.GuiUtils;
-import com.intellij.util.io.ZipUtil;
-import com.intellij.util.ui.OptionsDialog;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.swing.*;
-import java.awt.*;
import java.io.File;
-import java.io.FilenameFilter;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.Collections;
import java.util.List;
-import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-import static com.intellij.util.containers.ContainerUtil.newSmartList;
import static com.intellij.util.containers.ContainerUtilRt.newArrayList;
public class BrowserUtil {
- private static final Logger LOG = Logger.getInstance(BrowserUtil.class);
-
// The pattern for 'scheme' mainly according to RFC1738.
// We have to violate the RFC since we need to distinguish
// real schemes from local Windows paths; The only difference
@@ -96,154 +68,40 @@
}
public static void browse(@NotNull File file) {
- browse(VfsUtil.toUri(file));
+ BrowserLauncher.getInstance().browse(file);
}
public static void browse(@NotNull URL url) {
browse(url.toExternalForm());
}
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated Use {@link #browse(String)}
+ */
public static void launchBrowser(@NotNull @NonNls String url) {
browse(url);
}
public static void browse(@NotNull @NonNls String url) {
- openOrBrowse(url, true);
+ BrowserLauncher.getInstance().browse(url, null);
}
public static void open(@NotNull @NonNls String url) {
- openOrBrowse(url, false);
- }
-
- private static void openOrBrowse(@NotNull @NonNls String url, boolean browse) {
- url = url.trim();
-
- if (url.startsWith("jar:")) {
- String files = extractFiles(url);
- if (files == null) {
- return;
- }
- url = files;
- }
-
- URI uri;
- if (isAbsoluteURL(url)) {
- uri = VfsUtil.toUri(url);
- }
- else {
- File file = new File(url);
- if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) {
- try {
- Desktop.getDesktop().open(file);
- return;
- }
- catch (IOException e) {
- LOG.debug(e);
- }
- }
-
- browse(file);
- return;
- }
-
- if (uri == null) {
- showErrorMessage(IdeBundle.message("error.malformed.url", url), CommonBundle.getErrorTitle());
- }
- else {
- browse(uri);
- }
+ BrowserLauncher.getInstance().open(url);
}
/**
* Main method: tries to launch a browser using every possible way
*/
public static void browse(@NotNull URI uri) {
- LOG.debug("Launch browser: [" + uri + "]");
-
- GeneralSettings settings = getGeneralSettingsInstance();
- if (settings.isUseDefaultBrowser()) {
- if (isDesktopActionSupported(Desktop.Action.BROWSE)) {
- try {
- Desktop.getDesktop().browse(uri);
- LOG.debug("Browser launched using JDK 1.6 API");
- return;
- }
- catch (Exception e) {
- LOG.warn("Error while using Desktop API, fallback to CLI", e);
- }
- }
-
- List<String> command = getDefaultBrowserCommand();
- if (command != null) {
- launchBrowserByCommand(uri, command);
- return;
- }
- }
-
- String browserPath = settings.getBrowserPath();
- if (StringUtil.isEmptyOrSpaces(browserPath)) {
- String message = IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath());
- showErrorMessage(message, IdeBundle.message("title.browser.not.found"));
- return;
- }
-
- launchBrowserByCommand(uri, getOpenBrowserCommand(browserPath));
+ BrowserLauncher.getInstance().browse(uri);
}
- private static boolean isDesktopActionSupported(Desktop.Action action) {
- return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 &&
- Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action);
- }
-
- private static GeneralSettings getGeneralSettingsInstance() {
- if (ApplicationManager.getApplication() != null) {
- GeneralSettings settings = GeneralSettings.getInstance();
- if (settings != null) {
- return settings;
- }
- }
-
- return new GeneralSettings();
- }
-
- public static boolean canStartDefaultBrowser() {
- return isDesktopActionSupported(Desktop.Action.BROWSE) ||
- SystemInfo.isMac || SystemInfo.isWindows ||
- SystemInfo.isUnix && SystemInfo.hasXdgOpen();
- }
-
- @Nullable
- @NonNls
- private static List<String> getDefaultBrowserCommand() {
- if (SystemInfo.isWindows) {
- return newArrayList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote(""));
- }
- else if (SystemInfo.isMac) {
- return newSmartList(ExecUtil.getOpenCommandPath());
- }
- else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) {
- return newSmartList("xdg-open");
- }
-
- return null;
- }
-
- private static void launchBrowserByCommand(@NotNull final URI uri, @NotNull final List<String> command) {
- try {
- GeneralCommandLine commandLine = new GeneralCommandLine(command);
- commandLine.addParameter(uri.toString());
- commandLine.createProcess();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Browser launched with command line: " + commandLine);
- }
- }
- catch (ExecutionException e) {
- showErrorMessage(IdeBundle.message("error.cannot.start.browser", e.getMessage()), CommonBundle.getErrorTitle());
- }
- }
-
+ @SuppressWarnings("UnusedDeclaration")
@NotNull
+ @Deprecated
public static List<String> getOpenBrowserCommand(@NonNls @NotNull String browserPathOrName) {
return getOpenBrowserCommand(browserPathOrName, false);
}
@@ -251,7 +109,7 @@
@NotNull
public static List<String> getOpenBrowserCommand(@NonNls @NotNull String browserPathOrName, boolean newWindowIfPossible) {
if (new File(browserPathOrName).isFile()) {
- return newSmartList(browserPathOrName);
+ return Collections.singletonList(browserPathOrName);
}
else if (SystemInfo.isMac) {
List<String> command = newArrayList(ExecUtil.getOpenCommandPath(), "-a", browserPathOrName);
@@ -261,214 +119,27 @@
return command;
}
else if (SystemInfo.isWindows) {
- return newArrayList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote(""), browserPathOrName);
+ return Arrays.asList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote(""), browserPathOrName);
}
else {
- return newSmartList(browserPathOrName);
+ return Collections.singletonList(browserPathOrName);
}
}
- private static void showErrorMessage(final String message, final String title) {
- final Application app = ApplicationManager.getApplication();
- if (app == null) {
- return; // Not started yet. Not able to show message up. (Could happen in License panel under Linux).
- }
-
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- Messages.showMessageDialog(message, title, Messages.getErrorIcon());
- }
- };
-
- if (app.isDispatchThread()) {
- runnable.run();
- }
- else {
- app.invokeLater(runnable, ModalityState.NON_MODAL);
- }
- }
-
- @Nullable
- private static String extractFiles(String url) {
- try {
- int sharpPos = url.indexOf('#');
- String anchor = "";
- if (sharpPos != -1) {
- anchor = url.substring(sharpPos);
- url = url.substring(0, sharpPos);
- }
-
- VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
- if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null;
-
- JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem();
- VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file);
- if (jarVirtualFile == null) return null;
-
- String targetFilePath = file.getPath();
- String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR);
- LOG.assertTrue(targetFileRelativePath != null);
-
- String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode());
- final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash);
-
- final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified());
- final File timestampFile = new File(outputDir, ".idea.timestamp");
-
- String previousTimestamp = null;
- if (timestampFile.exists()) {
- previousTimestamp = FileUtil.loadFile(timestampFile);
- }
-
- if (!currentTimestamp.equals(previousTimestamp)) {
- final Ref<Boolean> extract = new Ref<Boolean>();
- Runnable r = new Runnable() {
- @Override
- public void run() {
- final ConfirmExtractDialog dialog = new ConfirmExtractDialog();
- if (dialog.isToBeShown()) {
- dialog.show();
- extract.set(dialog.isOK());
- }
- else {
- dialog.close(DialogWrapper.OK_EXIT_CODE);
- extract.set(true);
- }
- }
- };
-
- try {
- GuiUtils.runOrInvokeAndWait(r);
- }
- catch (InvocationTargetException ignored) {
- extract.set(false);
- }
- catch (InterruptedException ignored) {
- extract.set(false);
- }
-
- if (!extract.get()) return null;
-
- @SuppressWarnings("ConstantConditions")
- final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile();
- if (zipFile == null) return null;
- ZipEntry entry = zipFile.getEntry(targetFileRelativePath);
- if (entry == null) return null;
- InputStream is = zipFile.getInputStream(entry);
- try {
- ZipUtil.extractEntry(entry, is, outputDir);
- }
- finally {
- is.close();
- }
-
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- new Task.Backgroundable(null, "Extracting files...", true) {
- @Override
- public void run(@NotNull final ProgressIndicator indicator) {
- final int size = zipFile.size();
- final int[] counter = new int[]{0};
-
- class MyFilter implements FilenameFilter {
- private final Set<File> myImportantDirs = new HashSet<File>(
- Arrays.asList(outputDir, new File(outputDir, "resources")));
- private final boolean myImportantOnly;
-
- private MyFilter(boolean importantOnly) {
- myImportantOnly = importantOnly;
- }
-
- @Override
- public boolean accept(@NotNull File dir, @NotNull String name) {
- indicator.checkCanceled();
- boolean result = myImportantOnly == myImportantDirs.contains(dir);
- if (result) {
- indicator.setFraction(((double)counter[0]) / size);
- counter[0]++;
- }
- return result;
- }
- }
-
- try {
- ZipUtil.extract(zipFile, outputDir, new MyFilter(true));
- ZipUtil.extract(zipFile, outputDir, new MyFilter(false));
- FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes());
- }
- catch (IOException ignore) {
- }
- }
- }.queue();
- }
- });
- }
-
- return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor;
- }
- catch (IOException e) {
- LOG.warn(e);
- Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error");
- return null;
- }
- }
-
- public static void clearExtractedFiles() {
- FileUtil.delete(getExtractedFilesDir());
- }
-
- private static File getExtractedFilesDir() {
- return new File(PathManager.getSystemPath(), "ExtractedFiles");
- }
-
public static boolean isOpenCommandSupportArgs() {
return SystemInfo.isMacOSSnowLeopard;
}
- private static class ConfirmExtractDialog extends OptionsDialog {
- private ConfirmExtractDialog() {
- super(null);
- setTitle("Confirmation");
- init();
+ @NotNull
+ public static String getDefaultAlternativeBrowserPath() {
+ if (SystemInfo.isWindows) {
+ return "C:\\Program Files\\Internet Explorer\\IExplore.exe";
}
-
- @Override
- protected boolean isToBeShown() {
- return getGeneralSettingsInstance().isConfirmExtractFiles();
+ else if (SystemInfo.isMac) {
+ return "open";
}
-
- @Override
- protected void setToBeShown(boolean value, boolean onOk) {
- getGeneralSettingsInstance().setConfirmExtractFiles(value);
- }
-
- @Override
- protected boolean shouldSaveOptionsOnCancel() {
- return true;
- }
-
- @Override
- @NotNull
- protected Action[] createActions() {
- setOKButtonText(CommonBundle.getYesButtonText());
- return new Action[]{getOKAction(), getCancelAction()};
- }
-
- @Override
- protected JComponent createCenterPanel() {
- JPanel panel = new JPanel(new BorderLayout());
- String message = "The files are inside an archive, do you want them to be extracted?";
- JLabel label = new JLabel(message);
-
- label.setIconTextGap(10);
- label.setIcon(Messages.getQuestionIcon());
-
- panel.add(label, BorderLayout.CENTER);
- panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH);
-
- return panel;
+ else {
+ return "";
}
}
}
diff --git a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java
index 3c5ae9b..3758a2a 100644
--- a/platform/platform-api/src/com/intellij/ide/GeneralSettings.java
+++ b/platform/platform-api/src/com/intellij/ide/GeneralSettings.java
@@ -19,7 +19,7 @@
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.ExportableApplicationComponent;
import com.intellij.openapi.util.NamedJDOMExternalizable;
-import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import org.intellij.lang.annotations.MagicConstant;
@@ -95,18 +95,8 @@
}
public GeneralSettings() {
- myInactiveTimeout=DEFAULT_INACTIVE_TIMEOUT;
-
- if (SystemInfo.isWindows) {
- myBrowserPath = "C:\\Program Files\\Internet Explorer\\IExplore.exe";
- }
- else if (SystemInfo.isMac) {
- myBrowserPath = "open";
- }
- else {
- myBrowserPath = "";
- }
-
+ myInactiveTimeout = DEFAULT_INACTIVE_TIMEOUT;
+ myBrowserPath = BrowserUtil.getDefaultAlternativeBrowserPath();
myPropertyChangeSupport = new PropertyChangeSupport(this);
}
@@ -118,8 +108,10 @@
myPropertyChangeSupport.removePropertyChangeListener(listener);
}
+ @Override
public void initComponent() { }
+ @Override
public void disposeComponent() { }
public String getBrowserPath() {
@@ -222,6 +214,7 @@
}
//todo use DefaultExternalizer
+ @Override
public void readExternal(Element parentNode) {
boolean safeWriteSettingRead = false;
@@ -371,8 +364,9 @@
}
}
+ @Override
public void writeExternal(Element parentNode) {
- if (myBrowserPath != null) {
+ if (!StringUtil.isEmpty(myBrowserPath) && !myBrowserPath.equals(BrowserUtil.getDefaultAlternativeBrowserPath())) {
Element element = new Element(ELEMENT_OPTION);
element.setAttribute(ATTRIBUTE_NAME, OPTION_BROWSER_PATH);
element.setAttribute(ATTRIBUTE_VALUE, myBrowserPath);
@@ -457,20 +451,24 @@
}
}
+ @Override
public String getExternalFileName() {
return "ide.general";
}
+ @Override
@NotNull
public File[] getExportFiles() {
return new File[]{PathManager.getOptionsFile(this)};
}
+ @Override
@NotNull
public String getPresentableName() {
return IdeBundle.message("general.settings");
}
+ @Override
@NotNull
public String getComponentName() {
return "GeneralSettings";
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
new file mode 100644
index 0000000..f6826b5
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserFamily.java
@@ -0,0 +1,84 @@
+package com.intellij.ide.browsers;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.browsers.chrome.ChromeSettings;
+import com.intellij.ide.browsers.firefox.FirefoxSettings;
+import com.intellij.openapi.util.Iconable;
+import com.intellij.openapi.util.SystemInfo;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public enum BrowserFamily implements Iconable {
+ CHROME(IdeBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) {
+ @Override
+ public BrowserSpecificSettings createBrowserSpecificSettings() {
+ return new ChromeSettings();
+ }
+ },
+ FIREFOX(IdeBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) {
+ @Override
+ public BrowserSpecificSettings createBrowserSpecificSettings() {
+ return new FirefoxSettings();
+ }
+ },
+ EXPLORER(IdeBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16),
+ OPERA(IdeBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16),
+ SAFARI(IdeBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16);
+
+ private final String myName;
+ private final String myWindowsPath;
+ private final String myUnixPath;
+ private final String myMacPath;
+ private final Icon myIcon;
+
+ BrowserFamily(@NotNull String name,
+ @NotNull final String windowsPath,
+ @Nullable final String unixPath,
+ @Nullable final String macPath,
+ @NotNull Icon icon) {
+ myName = name;
+ myWindowsPath = windowsPath;
+ myUnixPath = unixPath;
+ myMacPath = macPath;
+ myIcon = icon;
+ }
+
+ @Nullable
+ public BrowserSpecificSettings createBrowserSpecificSettings() {
+ return null;
+ }
+
+ @Nullable
+ public String getExecutionPath() {
+ if (SystemInfo.isWindows) {
+ return myWindowsPath;
+ }
+ else if (SystemInfo.isMac) {
+ return myMacPath;
+ }
+ else {
+ return myUnixPath;
+ }
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public Icon getIcon() {
+ return myIcon;
+ }
+
+ @Override
+ public String toString() {
+ return myName;
+ }
+
+ @Override
+ public Icon getIcon(@IconFlags int flags) {
+ return getIcon();
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java
new file mode 100644
index 0000000..e4717d1
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserLauncher.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers;
+
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.net.URI;
+
+public abstract class BrowserLauncher {
+ public static BrowserLauncher getInstance() {
+ return ServiceManager.getService(BrowserLauncher.class);
+ }
+
+ public abstract void open(@NotNull String url);
+
+ public abstract void browse(@NotNull URI uri);
+
+ public abstract void browse(@NotNull File file);
+
+ public abstract void browse(@NotNull String url, @Nullable WebBrowser browser);
+
+ public abstract void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project);
+
+ public abstract boolean browseUsingPath(@Nullable String url,
+ @Nullable String browserPath,
+ @Nullable WebBrowser browser,
+ @Nullable Project project,
+ @NotNull String... additionalParameters);
+}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
new file mode 100644
index 0000000..344fe85
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
@@ -0,0 +1,41 @@
+/*
+ * 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.ide.browsers;
+
+import com.intellij.openapi.options.Configurable;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+public abstract class BrowserSpecificSettings implements Cloneable {
+ @NotNull
+ public abstract Configurable createConfigurable();
+
+ @NotNull
+ public List<String> getAdditionalParameters() {
+ return Collections.emptyList();
+ }
+
+ public BrowserSpecificSettings clone() {
+ try {
+ return (BrowserSpecificSettings)super.clone();
+ }
+ catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java b/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java
new file mode 100644
index 0000000..1119f72
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/UrlOpener.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+@SuppressWarnings("deprecation")
+public abstract class UrlOpener {
+ public static final ExtensionPointName<UrlOpener> EP_NAME = ExtensionPointName.create("org.jetbrains.urlOpener");
+
+ @Deprecated
+ /**
+ * @deprecated Use {@link com.intellij.ide.browsers.BrowserLauncher#browse(String, WebBrowser)}
+ */
+ public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser) {
+ BrowserLauncher.getInstance().browse(url, browser);
+ }
+
+ @Deprecated
+ /**
+ * @deprecated Use {@link com.intellij.ide.browsers.BrowserLauncher#browse(String, WebBrowser, com.intellij.openapi.project.Project)}
+ */
+ public static void launchBrowser(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) {
+ BrowserLauncher.getInstance().browse(url, browser, project);
+ }
+
+ public abstract boolean openUrl(@NotNull WebBrowser browser, @NotNull String url, @Nullable Project project);
+}
+
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/WebBrowser.java b/platform/platform-api/src/com/intellij/ide/browsers/WebBrowser.java
new file mode 100644
index 0000000..04eaa34
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/WebBrowser.java
@@ -0,0 +1,30 @@
+package com.intellij.ide.browsers;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.UUID;
+
+public abstract class WebBrowser {
+ @NotNull
+ public abstract String getName();
+
+ @NotNull
+ public abstract UUID getId();
+
+ @NotNull
+ public abstract BrowserFamily getFamily();
+
+ @NotNull
+ public abstract Icon getIcon();
+
+ @Nullable
+ public abstract String getPath();
+
+ @NotNull
+ public abstract String getBrowserNotFoundMessage();
+
+ @Nullable
+ public abstract BrowserSpecificSettings getSpecificSettings();
+}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
new file mode 100644
index 0000000..b6ca3e7
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers.chrome;
+
+import com.intellij.ide.browsers.BrowserSpecificSettings;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.PathUtil;
+import com.intellij.util.execution.ParametersListUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collections;
+import java.util.List;
+
+public final class ChromeSettings extends BrowserSpecificSettings {
+ public static final String USER_DATA_DIR_ARG = "--user-data-dir=";
+ private @Nullable String myCommandLineOptions;
+ private @Nullable String myUserDataDirectoryPath;
+ private boolean myUseCustomProfile;
+
+ public ChromeSettings() {
+ }
+
+ @Nullable
+ @Tag("user-data-dir")
+ public String getUserDataDirectoryPath() {
+ return myUserDataDirectoryPath;
+ }
+
+ @Tag("use-custom-profile")
+ public boolean isUseCustomProfile() {
+ return myUseCustomProfile;
+ }
+
+ @Nullable
+ @Tag("command-line-options")
+ public String getCommandLineOptions() {
+ return myCommandLineOptions;
+ }
+
+ public void setCommandLineOptions(@Nullable String value) {
+ myCommandLineOptions = StringUtil.nullize(value);
+ }
+
+ public void setUserDataDirectoryPath(@Nullable String value) {
+ myUserDataDirectoryPath = PathUtil.toSystemIndependentName(StringUtil.nullize(value));
+ }
+
+ public void setUseCustomProfile(boolean useCustomProfile) {
+ myUseCustomProfile = useCustomProfile;
+ }
+
+ @NotNull
+ @Override
+ public List<String> getAdditionalParameters() {
+ if (myCommandLineOptions == null) {
+ if (myUseCustomProfile && myUserDataDirectoryPath != null) {
+ return Collections.singletonList(USER_DATA_DIR_ARG + FileUtilRt.toSystemDependentName(myUserDataDirectoryPath));
+ }
+ else {
+ return Collections.emptyList();
+ }
+ }
+
+ List<String> cliOptions = ParametersListUtil.parse(myCommandLineOptions);
+ if (myUseCustomProfile && myUserDataDirectoryPath != null) {
+ cliOptions.add(USER_DATA_DIR_ARG + FileUtilRt.toSystemDependentName(myUserDataDirectoryPath));
+ }
+ return cliOptions;
+ }
+
+ @NotNull
+ @Override
+ public ChromeSettingsConfigurable createConfigurable() {
+ return new ChromeSettingsConfigurable(this);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ ChromeSettings settings = (ChromeSettings)o;
+ return myUseCustomProfile == settings.myUseCustomProfile &&
+ Comparing.equal(myCommandLineOptions, settings.myCommandLineOptions) &&
+ (!myUseCustomProfile || Comparing.equal(myUserDataDirectoryPath, settings.myUserDataDirectoryPath));
+ }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form
similarity index 100%
rename from xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form
rename to platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.form
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java
new file mode 100644
index 0000000..5cc4167
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java
@@ -0,0 +1,136 @@
+/*
+ * 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 com.intellij.ide.browsers.chrome;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.RawCommandLineEditor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author nik
+ */
+public class ChromeSettingsConfigurable implements Configurable {
+ private final ChromeSettings mySettings;
+ private JPanel myMainPanel;
+ private JCheckBox myUseCustomProfileCheckBox;
+ private TextFieldWithBrowseButton myUserDataDirField;
+ private JLabel myCommandLineOptionsLabel;
+ private RawCommandLineEditor myCommandLineOptionsEditor;
+ private final String myDefaultUserDirPath;
+
+ public ChromeSettingsConfigurable(@NotNull ChromeSettings settings) {
+ mySettings = settings;
+ myUserDataDirField.addBrowseFolderListener("Select User Data Directory", "Specifies the directory that user data (your \"profile\") is kept in", null,
+ FileChooserDescriptorFactory.createSingleFolderDescriptor());
+ myUseCustomProfileCheckBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myUserDataDirField.setEnabled(myUseCustomProfileCheckBox.isSelected());
+ }
+ });
+ myDefaultUserDirPath = getDefaultUserDataPath();
+ myCommandLineOptionsEditor.setDialogCaption("Chrome Command Line Options");
+ myCommandLineOptionsLabel.setLabelFor(myCommandLineOptionsEditor.getTextField());
+ }
+
+ @Override
+ public JComponent createComponent() {
+ return myMainPanel;
+ }
+
+ @Override
+ public boolean isModified() {
+ if (myUseCustomProfileCheckBox.isSelected() != mySettings.isUseCustomProfile()
+ || !myCommandLineOptionsEditor.getText().equals(StringUtil.notNullize(mySettings.getCommandLineOptions()))) {
+ return true;
+ }
+
+ String configuredPath = getConfiguredUserDataDirPath();
+ String storedPath = mySettings.getUserDataDirectoryPath();
+ if (myDefaultUserDirPath.equals(configuredPath) && storedPath == null) return false;
+ return !configuredPath.equals(storedPath);
+ }
+
+
+ private String getConfiguredUserDataDirPath() {
+ return FileUtil.toSystemIndependentName(myUserDataDirField.getText());
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ mySettings.setCommandLineOptions(myCommandLineOptionsEditor.getText());
+ mySettings.setUseCustomProfile(myUseCustomProfileCheckBox.isSelected());
+ mySettings.setUserDataDirectoryPath(getConfiguredUserDataDirPath());
+ }
+
+ @Override
+ public void reset() {
+ myCommandLineOptionsEditor.setText(mySettings.getCommandLineOptions());
+ myUseCustomProfileCheckBox.setSelected(mySettings.isUseCustomProfile());
+ myUserDataDirField.setEnabled(mySettings.isUseCustomProfile());
+ String path = mySettings.getUserDataDirectoryPath();
+ if (path != null) {
+ myUserDataDirField.setText(FileUtil.toSystemDependentName(path));
+ }
+ else {
+ myUserDataDirField.setText(FileUtil.toSystemDependentName(myDefaultUserDirPath));
+ }
+ }
+
+ public void enableRecommendedOptions() {
+ if (!myUseCustomProfileCheckBox.isSelected()) {
+ myUseCustomProfileCheckBox.doClick(0);
+ }
+ }
+
+ private static String getDefaultUserDataPath() {
+ File dir = new File(PathManager.getConfigPath(), "chrome-user-data");
+ try {
+ return FileUtil.toSystemIndependentName(dir.getCanonicalPath());
+ }
+ catch (IOException e) {
+ return FileUtil.toSystemIndependentName(dir.getAbsolutePath());
+ }
+ }
+
+ @Override
+ public void disposeUIResources() {
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return "Chrome Settings";
+ }
+
+ @Override
+ public String getHelpTopic() {
+ return null;
+ }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java
similarity index 100%
rename from xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java
rename to platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxProfile.java
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java
new file mode 100644
index 0000000..e9920a4
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers.firefox;
+
+import com.intellij.ide.browsers.BrowserSpecificSettings;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public final class FirefoxSettings extends BrowserSpecificSettings {
+ private String myProfilesIniPath;
+ private String myProfile;
+
+ public FirefoxSettings() {
+ }
+
+ public FirefoxSettings(@Nullable String profilesIniPath, @Nullable String profile) {
+ myProfilesIniPath = StringUtil.nullize(profilesIniPath);
+ myProfile = StringUtil.nullize(profile);
+ }
+
+ @Nullable
+ @Tag("profiles-ini-path")
+ public String getProfilesIniPath() {
+ return myProfilesIniPath;
+ }
+
+ public void setProfilesIniPath(@Nullable String value) {
+ myProfilesIniPath = FileUtilRt.toSystemIndependentName(StringUtil.nullize(value));
+ }
+
+ @Nullable
+ @Tag("profile")
+ public String getProfile() {
+ return myProfile;
+ }
+
+ public void setProfile(@Nullable String value) {
+ myProfile = StringUtil.nullize(value);
+ }
+
+ @NotNull
+ @Override
+ public Configurable createConfigurable() {
+ return new FirefoxSettingsConfigurable(this);
+ }
+
+ @Nullable
+ public File getProfilesIniFile() {
+ if (myProfilesIniPath != null) {
+ return new File(FileUtil.toSystemDependentName(myProfilesIniPath));
+ }
+ return FirefoxUtil.getDefaultProfileIniPath();
+ }
+
+ @NotNull
+ @Override
+ public List<String> getAdditionalParameters() {
+ List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(getProfilesIniFile());
+ if (profiles.size() >= 2) {
+ FirefoxProfile profile = FirefoxUtil.findProfileByNameOrDefault(myProfile, profiles);
+ if (profile != null && !profile.isDefault()) {
+ return Arrays.asList("-P", profile.getName());
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ FirefoxSettings settings = (FirefoxSettings)o;
+ return Comparing.equal(myProfilesIniPath, settings.myProfilesIniPath) &&
+ Comparing.equal(myProfile, settings.myProfile);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form
new file mode 100644
index 0000000..27890c5
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.browsers.firefox.FirefoxSettingsConfigurable">
+ <grid id="27dc6" binding="myMainPanel" 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>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <vspacer id="90b50">
+ <constraints>
+ <grid row="1" 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="735f0" 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>
+ <grid row="0" 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 id="f9834" layout-manager="GridLayoutManager" row-count="1" 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="0" 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>
+ <hspacer id="d637d">
+ <constraints>
+ <grid row="0" 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="852e3" class="javax.swing.JLabel">
+ <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>
+ <text resource-bundle="messages/IdeBundle" key="label.text.path.to.profiles.ini"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="a31a5" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myProfilesIniPathField">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false">
+ <preferred-size width="350" height="-1"/>
+ </grid>
+ </constraints>
+ <properties/>
+ </component>
+ <grid id="baf65" layout-manager="GridLayoutManager" row-count="1" 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="2" 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>
+ <component id="11a5c" class="javax.swing.JLabel">
+ <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="c6e14"/>
+ <text resource-bundle="messages/IdeBundle" key="label.text.profile"/>
+ </properties>
+ </component>
+ <hspacer id="d3289">
+ <constraints>
+ <grid row="0" column="2" 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="c6e14" class="javax.swing.JComboBox" binding="myProfileCombobox">
+ <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"/>
+ </constraints>
+ <properties/>
+ </component>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
new file mode 100644
index 0000000..349c396
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
@@ -0,0 +1,155 @@
+/*
+ * 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.ide.browsers.firefox;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.PathChooserDialog;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class FirefoxSettingsConfigurable implements Configurable {
+ private static final FileChooserDescriptor PROFILES_INI_CHOOSER_DESCRIPTOR = createProfilesIniChooserDescriptor();
+
+ private JPanel myMainPanel;
+ private JComboBox myProfileCombobox;
+ private TextFieldWithBrowseButton myProfilesIniPathField;
+ private final FirefoxSettings mySettings;
+ private String myLastProfilesIniPath;
+ private String myDefaultProfilesIniPath;
+ private String myDefaultProfile;
+
+ public FirefoxSettingsConfigurable(FirefoxSettings settings) {
+ mySettings = settings;
+ myProfilesIniPathField.addBrowseFolderListener(IdeBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR);
+ myProfilesIniPathField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ updateProfilesList();
+ }
+ });
+ }
+
+ public static FileChooserDescriptor createProfilesIniChooserDescriptor() {
+ FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) {
+ @Override
+ public boolean isFileSelectable(VirtualFile file) {
+ return file.getName().equals(FirefoxUtil.PROFILES_INI_FILE) && super.isFileSelectable(file);
+ }
+ };
+ if (SystemInfo.isMac) {
+ descriptor.putUserData(PathChooserDialog.NATIVE_MAC_CHOOSER_SHOW_HIDDEN_FILES, Boolean.TRUE);
+ }
+ return descriptor;
+ }
+
+ @Override
+ public JComponent createComponent() {
+ return myMainPanel;
+ }
+
+ @Override
+ public boolean isModified() {
+ return !Comparing.equal(mySettings.getProfile(), getConfiguredProfileName()) ||
+ !Comparing.equal(mySettings.getProfilesIniPath(), getConfiguredProfileIniPath());
+ }
+
+ @Nullable
+ private String getConfiguredProfileIniPath() {
+ String path = PathUtil.toSystemIndependentName(StringUtil.nullize(myProfilesIniPathField.getText()));
+ return myDefaultProfilesIniPath.equals(path) ? null : path;
+ }
+
+ @Nullable
+ private String getConfiguredProfileName() {
+ final String selected = (String)myProfileCombobox.getSelectedItem();
+ if (Comparing.equal(myDefaultProfile, selected)) {
+ return null;
+ }
+ return selected;
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ mySettings.setProfile(getConfiguredProfileName());
+ mySettings.setProfilesIniPath(getConfiguredProfileIniPath());
+ }
+
+ @Override
+ public void reset() {
+ File defaultFile = FirefoxUtil.getDefaultProfileIniPath();
+ myDefaultProfilesIniPath = defaultFile != null ? defaultFile.getAbsolutePath() : "";
+
+ String path = mySettings.getProfilesIniPath();
+ myProfilesIniPathField.setText(path != null ? FileUtilRt.toSystemDependentName(path) : myDefaultProfilesIniPath);
+ updateProfilesList();
+ myProfileCombobox.setSelectedItem(ObjectUtils.notNull(mySettings.getProfile(), myDefaultProfile));
+ }
+
+ private void updateProfilesList() {
+ final String profilesIniPath = myProfilesIniPathField.getText();
+ if (myLastProfilesIniPath != null && myLastProfilesIniPath.equals(profilesIniPath)) {
+ return;
+ }
+
+ myProfileCombobox.removeAllItems();
+ final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(new File(profilesIniPath));
+ final FirefoxProfile defaultProfile = FirefoxUtil.getDefaultProfile(profiles);
+ myDefaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
+ for (FirefoxProfile profile : profiles) {
+ //noinspection unchecked
+ myProfileCombobox.addItem(profile.getName());
+ }
+ if (!profiles.isEmpty()) {
+ myProfileCombobox.setSelectedIndex(0);
+ }
+ myLastProfilesIniPath = profilesIniPath;
+ }
+
+ @Override
+ public void disposeUIResources() {
+ }
+
+ @Override
+ @Nls
+ public String getDisplayName() {
+ return IdeBundle.message("display.name.firefox.settings");
+ }
+
+ @Override
+ public String getHelpTopic() {
+ return null;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java
new file mode 100644
index 0000000..00b83be
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java
@@ -0,0 +1,185 @@
+/*
+ * 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.ide.browsers.firefox;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.SystemProperties;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public class FirefoxUtil {
+ private static final Logger LOG = Logger.getInstance(FirefoxUtil.class);
+ @NonNls public static final String PROFILES_INI_FILE = "profiles.ini";
+
+ private FirefoxUtil() {
+ }
+
+ @Nullable
+ public static File getDefaultProfileIniPath() {
+ File[] roots = getProfilesDirs();
+ for (File profilesDir : roots) {
+ File profilesFile = new File(profilesDir, PROFILES_INI_FILE);
+ if (profilesFile.isFile()) {
+ return profilesFile;
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ public static File getFirefoxExtensionsDir(FirefoxSettings settings) {
+ File profilesFile = settings.getProfilesIniFile();
+ if (profilesFile != null && profilesFile.exists()) {
+ List<FirefoxProfile> profiles = computeProfiles(profilesFile);
+ FirefoxProfile profile = findProfileByNameOrDefault(settings.getProfile(), profiles);
+ if (profile != null) {
+ File profileDir = profile.getProfileDirectory(profilesFile);
+ if (profileDir.isDirectory()) {
+ return new File(profileDir, "extensions");
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ public static FirefoxProfile findProfileByNameOrDefault(@Nullable String name, @NotNull List<FirefoxProfile> profiles) {
+ for (FirefoxProfile profile : profiles) {
+ if (profile.getName().equals(name)) {
+ return profile;
+ }
+ }
+ return getDefaultProfile(profiles);
+ }
+
+ @Nullable
+ public static FirefoxProfile getDefaultProfile(List<FirefoxProfile> profiles) {
+ if (profiles.isEmpty()) {
+ return null;
+ }
+
+ for (FirefoxProfile profile : profiles) {
+ if (profile.isDefault()) {
+ return profile;
+ }
+ }
+ return profiles.get(0);
+ }
+
+ @NotNull
+ public static List<FirefoxProfile> computeProfiles(@Nullable File profilesFile) {
+ if (profilesFile == null || !profilesFile.isFile()) {
+ return Collections.emptyList();
+ }
+
+ try {
+ BufferedReader reader;
+ reader = new BufferedReader(new FileReader(profilesFile));
+ try {
+ final List<FirefoxProfile> profiles = new SmartList<FirefoxProfile>();
+ boolean insideProfile = false;
+ String currentName = null;
+ String currentPath = null;
+ boolean isDefault = false;
+ boolean isRelative = false;
+ boolean eof = false;
+ while (!eof) {
+ String line = reader.readLine();
+ if (line == null) {
+ eof = true;
+ line = "[]";
+ }
+ else {
+ line = line.trim();
+ }
+
+ if (line.startsWith("[") && line.endsWith("]")) {
+ if (!StringUtil.isEmpty(currentPath) && !StringUtil.isEmpty(currentName)) {
+ profiles.add(new FirefoxProfile(currentName, currentPath, isDefault, isRelative));
+ }
+ currentName = null;
+ currentPath = null;
+ isDefault = false;
+ isRelative = false;
+ insideProfile = StringUtil.startsWithIgnoreCase(line, "[Profile");
+ continue;
+ }
+
+ final int i = line.indexOf('=');
+ if (i != -1 && insideProfile) {
+ String name = line.substring(0, i).trim();
+ String value = line.substring(i + 1).trim();
+ if (name.equalsIgnoreCase("path")) {
+ currentPath = value;
+ }
+ else if (name.equalsIgnoreCase("name")) {
+ currentName = value;
+ }
+ else if (name.equalsIgnoreCase("default") && value.equals("1")) {
+ isDefault = true;
+ }
+ else //noinspection SpellCheckingInspection
+ if (name.equalsIgnoreCase("isrelative") && value.equals("1")) {
+ isRelative = true;
+ }
+ }
+ }
+ return profiles;
+ }
+ finally {
+ reader.close();
+ }
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ return Collections.emptyList();
+ }
+ }
+
+ private static File[] getProfilesDirs() {
+ final String userHome = SystemProperties.getUserHome();
+ if (SystemInfo.isMac) {
+ return new File[] {
+ new File(userHome, "Library" + File.separator + "Mozilla" + File.separator + "Firefox"),
+ new File(userHome, "Library" + File.separator + "Application Support" + File.separator + "Firefox"),
+ };
+ }
+ if (SystemInfo.isUnix) {
+ return new File[] {new File(userHome, ".mozilla" + File.separator + "firefox")};
+ }
+
+ String localPath = "Mozilla" + File.separator + "Firefox";
+ return new File[] {
+ new File(System.getenv("APPDATA"), localPath),
+ new File(userHome, "AppData" + File.separator + "Roaming" + File.separator + localPath),
+ new File(userHome, "Application Data" + File.separator + localPath)
+ };
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ide/util/PropertyName.java b/platform/platform-api/src/com/intellij/ide/util/PropertyName.java
deleted file mode 100644
index 7dfa9a2..0000000
--- a/platform/platform-api/src/com/intellij/ide/util/PropertyName.java
+++ /dev/null
@@ -1,32 +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.ide.util;
-
-import java.lang.annotation.*;
-
-/**
- * Allows to pass property name of field
- *
- * @author Konstantin Bulenkov
- */
-@Documented
-@Retention(RetentionPolicy.RUNTIME)
-@Target({ElementType.FIELD})
-public @interface PropertyName {
- String NOT_SET = "";
- String value();
- String defaultValue() default NOT_SET;
-}
diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java
index d56d0c6..5f4417c 100644
--- a/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java
+++ b/platform/platform-api/src/com/intellij/ide/util/treeView/AbstractTreeBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,8 +25,8 @@
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.AsyncResult;
import com.intellij.openapi.util.Condition;
+import com.intellij.reference.SoftReference;
import com.intellij.util.Processor;
-import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.TransferToEDTQueue;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.MergingUpdateQueue;
@@ -212,10 +212,9 @@
/**
* node descriptor getElement contract is as follows:
- * 1.TreeStructure always returns & recieves "treestructure" element returned by getTreeStructureElement
+ * 1.TreeStructure always returns & receives "treeStructure" element returned by getTreeStructureElement
* 2.Paths contain "model" element returned by getElement
*/
-
protected Object getTreeStructureElement(NodeDescriptor nodeDescriptor) {
return nodeDescriptor.getElement();
}
@@ -432,6 +431,7 @@
return true;
}
+ @SuppressWarnings("SpellCheckingInspection")
protected void runOnYeildingDone(Runnable onDone) {
if (isDisposed()) return;
@@ -490,10 +490,22 @@
}
}
+ @SuppressWarnings({"UnusedDeclaration", "SpellCheckingInspection"})
+ @Deprecated
@NotNull
+ /**
+ * @deprecated use {@link #getInitialized()}
+ * to remove in IDEA 14
+ */
public final ActionCallback getIntialized() {
- if (isDisposed()) return new ActionCallback.Rejected();
+ return getInitialized();
+ }
+ @NotNull
+ public final ActionCallback getInitialized() {
+ if (isDisposed()) {
+ return new ActionCallback.Rejected();
+ }
return myUi.getInitialized();
}
@@ -623,20 +635,23 @@
@Nullable
public static AbstractTreeBuilder getBuilderFor(@NotNull JTree tree) {
final WeakReference ref = (WeakReference)tree.getClientProperty(TREE_BUILDER);
- return ref != null ? (AbstractTreeBuilder)ref.get() : null;
+ return (AbstractTreeBuilder)SoftReference.dereference(ref);
}
@Nullable
- public final <T> Object accept(@NotNull Class nodeClass, @NotNull TreeVisitor<T> visitor) {
+ public final <T> Object accept(@NotNull Class<?> nodeClass, @NotNull TreeVisitor<T> visitor) {
return accept(nodeClass, getRootElement(), visitor);
}
@Nullable
- private <T> Object accept(@NotNull Class nodeClass, Object element, @NotNull TreeVisitor<T> visitor) {
- if (element == null) return null;
+ private <T> Object accept(@NotNull Class<?> nodeClass, Object element, @NotNull TreeVisitor<T> visitor) {
+ if (element == null) {
+ return null;
+ }
- if (nodeClass.isAssignableFrom(element.getClass())) {
- if (visitor.visit((T)element)) return element;
+ //noinspection unchecked
+ if (nodeClass.isAssignableFrom(element.getClass()) && visitor.visit((T)element)) {
+ return element;
}
final Object[] children = getTreeStructure().getChildElements(element);
diff --git a/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java b/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java
index 61fda59..94277ae 100644
--- a/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java
+++ b/platform/platform-api/src/com/intellij/ide/util/treeView/TreeState.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Progressive;
import com.intellij.openapi.util.*;
+import com.intellij.reference.SoftReference;
import com.intellij.util.ui.tree.TreeUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -442,10 +443,8 @@
@Override
public ActionCallback getInitialized() {
final WeakReference<ActionCallback> ref = (WeakReference<ActionCallback>)myTree.getClientProperty(CALLBACK);
- if (ref != null) {
- final ActionCallback callback = ref.get();
- if (callback != null) return callback;
- }
+ final ActionCallback callback = SoftReference.dereference(ref);
+ if (callback != null) return callback;
return new ActionCallback.Done();
}
diff --git a/platform/platform-api/src/com/intellij/ide/wizard/AbstractWizard.java b/platform/platform-api/src/com/intellij/ide/wizard/AbstractWizard.java
index 7c379da..42a9487 100644
--- a/platform/platform-api/src/com/intellij/ide/wizard/AbstractWizard.java
+++ b/platform/platform-api/src/com/intellij/ide/wizard/AbstractWizard.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.
@@ -150,7 +150,7 @@
final GroupLayout.SequentialGroup hGroup = layout.createSequentialGroup();
final GroupLayout.ParallelGroup vGroup = layout.createParallelGroup();
- final Collection<Component> buttons = ContainerUtil.newArrayListWithExpectedSize(5);
+ final Collection<Component> buttons = ContainerUtil.newArrayListWithCapacity(5);
final boolean helpAvailable = ApplicationInfo.contextHelpAvailable();
if (helpAvailable && UIUtil.isUnderGTKLookAndFeel()) {
diff --git a/platform/platform-api/src/com/intellij/idea/ActionsBundle.java b/platform/platform-api/src/com/intellij/idea/ActionsBundle.java
index 43318d0..615468e 100644
--- a/platform/platform-api/src/com/intellij/idea/ActionsBundle.java
+++ b/platform/platform-api/src/com/intellij/idea/ActionsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,8 +29,12 @@
* Date: Aug 29, 2005
*/
public class ActionsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = IDEA_ACTIONS_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String IDEA_ACTIONS_BUNDLE = "messages.ActionsBundle";
@SuppressWarnings({"HardCodedStringLiteral", "UnresolvedPropertyKey"})
@@ -47,13 +52,8 @@
return message("action." + actionId + ".description");
}
- public static String message(@PropertyKey(resourceBundle = IDEA_ACTIONS_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(IDEA_ACTIONS_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/notification/Notification.java b/platform/platform-api/src/com/intellij/notification/Notification.java
index 5a538dc..674e202 100644
--- a/platform/platform-api/src/com/intellij/notification/Notification.java
+++ b/platform/platform-api/src/com/intellij/notification/Notification.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupAdapter;
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
+import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -129,8 +130,7 @@
balloon.addListener(new JBPopupAdapter() {
@Override
public void onClosed(LightweightWindowEvent event) {
- WeakReference<Balloon> ref = myBalloonRef;
- if (ref != null && ref.get() == balloon) {
+ if (SoftReference.dereference(myBalloonRef) == balloon) {
myBalloonRef = null;
}
}
@@ -139,7 +139,7 @@
@Nullable
public Balloon getBalloon() {
- return myBalloonRef == null ? null : myBalloonRef.get();
+ return SoftReference.dereference(myBalloonRef);
}
public void notify(@Nullable Project project) {
diff --git a/platform/platform-api/src/com/intellij/notification/NotificationGroup.java b/platform/platform-api/src/com/intellij/notification/NotificationGroup.java
index 4c9000a..7285a8e 100644
--- a/platform/platform-api/src/com/intellij/notification/NotificationGroup.java
+++ b/platform/platform-api/src/com/intellij/notification/NotificationGroup.java
@@ -15,15 +15,25 @@
*/
package com.intellij.notification;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.ui.MessageType;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Map;
+
/**
* @author peter
*/
-public class NotificationGroup {
- private final String myDisplayId;
+public final class NotificationGroup {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.notification.NotificationGroup");
+ private static final Map<String, NotificationGroup> ourRegisteredGroups = ContainerUtil.newConcurrentMap();
+
+ @NotNull private final String myDisplayId;
+ @NotNull private final NotificationDisplayType myDisplayType;
+ private final boolean myLogByDefault;
+ @Nullable private final String myToolWindowId;
public NotificationGroup(@NotNull String displayId, @NotNull NotificationDisplayType defaultDisplayType, boolean logByDefault) {
this(displayId, defaultDisplayType, logByDefault, null);
@@ -34,12 +44,14 @@
boolean logByDefault,
@Nullable String toolWindowId) {
myDisplayId = displayId;
+ myDisplayType = defaultDisplayType;
+ myLogByDefault = logByDefault;
+ myToolWindowId = toolWindowId;
- NotificationsConfiguration configuration = NotificationsConfiguration.getNotificationsConfiguration();
- configuration.register(displayId, defaultDisplayType, logByDefault);
- if (toolWindowId != null) {
- configuration.registerToolWindowCapability(displayId, toolWindowId);
+ if (ourRegisteredGroups.containsKey(displayId)) {
+ LOG.info("Notification group " + displayId + " is already registered", new Throwable());
}
+ ourRegisteredGroups.put(displayId, this);
}
public static NotificationGroup balloonGroup(@NotNull String displayId) {
@@ -72,4 +84,29 @@
@Nullable NotificationListener listener) {
return new Notification(myDisplayId, title, content, type, listener);
}
+
+ @NotNull
+ public NotificationDisplayType getDisplayType() {
+ return myDisplayType;
+ }
+
+ public boolean isLogByDefault() {
+ return myLogByDefault;
+ }
+
+ @Nullable
+ public String getToolWindowId() {
+ return myToolWindowId;
+ }
+
+ @Nullable
+ public static NotificationGroup findRegisteredGroup(String displayId) {
+ return ourRegisteredGroups.get(displayId);
+ }
+
+ @NotNull
+ public static Iterable<NotificationGroup> getAllRegisteredGroups() {
+ return ourRegisteredGroups.values();
+ }
+
}
diff --git a/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java b/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java
index bfaf9c7..b2f55dd 100644
--- a/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java
+++ b/platform/platform-api/src/com/intellij/notification/NotificationsConfiguration.java
@@ -25,5 +25,6 @@
return ApplicationManager.getApplication().getComponent(NotificationsConfiguration.class);
}
+ @Deprecated
public abstract void registerToolWindowCapability(@NotNull String groupId, @NotNull String toolWindowId);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java
index a23b9ec..221733e 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ActionPlaces.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.
@@ -109,7 +109,7 @@
public static final String PHING_EXPLORER_POPUP = "PhingExplorerPopup";
public static final String PHING_EXPLORER_TOOLBAR = "PhingExplorerToolbar";
public static final String DOCK_MENU = "DockMenu";
- public static String PHING_MESSAGES_TOOLBAR = "PhingMessagesToolbar";
+ public static final String PHING_MESSAGES_TOOLBAR = "PhingMessagesToolbar";
public static final String CHANGES_LOCAL_DIFF_SETTINGS = "CHANGES_LOCAL_DIFF_SETTINGS";
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java
index 4077dff..0e21560 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/DefaultActionGroup.java
@@ -35,6 +35,13 @@
* to implement your own <code>ActionGroup</code>.
*
* @see Constraints
+ *
+ * @see com.intellij.openapi.actionSystem.ComputableActionGroup
+ *
+ * @see com.intellij.ide.actions.NonEmptyActionGroup
+ * @see com.intellij.ide.actions.NonTrivialActionGroup
+ * @see com.intellij.ide.actions.SmartPopupActionGroup
+ *
*/
public class DefaultActionGroup extends ActionGroup {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.actionSystem.DefaultActionGroup");
@@ -85,15 +92,15 @@
* @param actionManager ActionManager instance
*/
public final void add(@NotNull AnAction action, @NotNull ActionManager actionManager) {
- add(action, new Constraints(Anchor.LAST, null), actionManager);
+ add(action, Constraints.LAST, actionManager);
}
public final void add(@NotNull AnAction action) {
- addAction(action, new Constraints(Anchor.LAST, null));
+ addAction(action, Constraints.LAST);
}
public final ActionInGroup addAction(@NotNull AnAction action) {
- return addAction(action, new Constraints(Anchor.LAST, null));
+ return addAction(action, Constraints.LAST);
}
/**
@@ -236,6 +243,43 @@
myPairs.clear();
}
+
+ /**
+ * Replaces specified action with the a one.
+ */
+ public boolean replaceAction(@NotNull AnAction oldAction, @NotNull AnAction newAction) {
+ int index = mySortedChildren.indexOf(oldAction);
+ if (index >= 0) {
+ mySortedChildren.set(index, newAction);
+ return true;
+ }
+ else {
+ for (int i = 0; i < myPairs.size(); i++) {
+ Pair<AnAction, Constraints> pair = myPairs.get(i);
+ if (pair.first.equals(newAction)) {
+ myPairs.set(i, Pair.create(newAction, pair.second));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Copies content from <code>group</code>.
+ * @param other group to copy from
+ */
+ public void copyFromGroup(@NotNull DefaultActionGroup other) {
+ copyFrom(other);
+ setPopup(other.isPopup());
+
+ mySortedChildren.clear();
+ mySortedChildren.addAll(other.mySortedChildren);
+
+ myPairs.clear();
+ myPairs.addAll(other.myPairs);
+ }
+
/**
* Returns group's children in the order determined by constraints.
*
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 afc6080..4ae67c9 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyAction.java
@@ -22,10 +22,17 @@
import java.util.ArrayList;
/**
+ * This class purpose is to reserve action-id in a plugin.xml so the action appears in Keymap.
+ * Then Keymap assignments can be used for non-registered actions created on runtime.
+ *
+ * Another usage is to override (hide) already registered actions by means of plugin.xml, see {@link EmptyActionGroup} as well.
+ *
+ * @see EmptyActionGroup
+ *
* @author Gregory.Shrago
* @author Konstantin Bulenkov
*/
-public class EmptyAction extends AnAction {
+public final class EmptyAction extends AnAction {
private boolean myEnabled;
public EmptyAction() {
@@ -67,8 +74,9 @@
}
public static void registerActionShortcuts(JComponent component, final JComponent fromComponent) {
+ @SuppressWarnings("unchecked")
final ArrayList<AnAction> actionList =
- (ArrayList<AnAction>)fromComponent.getClientProperty(ourClientProperty);
+ (ArrayList<AnAction>)fromComponent.getClientProperty(ourClientProperty);
if (actionList != null) {
for (AnAction anAction : actionList) {
anAction.registerCustomShortcutSet(anAction.getShortcutSet(), component);
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyActionGroup.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyActionGroup.java
new file mode 100644
index 0000000..19ea69b
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/EmptyActionGroup.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.actionSystem;
+
+/**
+ * This class purpose is to override (hide) already registered action groups by means of plugin.xml.
+ *
+ * @see EmptyAction
+ *
+ * @author gregsh
+ */
+public final class EmptyActionGroup extends DefaultActionGroup {
+ public EmptyActionGroup() {
+ getTemplatePresentation().setEnabledAndVisible(false);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ getTemplatePresentation().setEnabledAndVisible(false);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionManagerEx.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionManagerEx.java
index e1f198d..ab26123 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionManagerEx.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ActionManagerEx.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.openapi.actionSystem.*;
import com.intellij.openapi.extensions.PluginId;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -31,7 +32,7 @@
return (ActionManagerEx)getInstance();
}
- public abstract ActionToolbar createActionToolbar(String place, ActionGroup group, boolean horizontal, boolean decorateButtons);
+ public abstract ActionToolbar createActionToolbar(String place, @NotNull ActionGroup group, boolean horizontal, boolean decorateButtons);
public abstract void fireBeforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event);
@@ -67,48 +68,28 @@
*
* @return null if string cannot be parsed.
*/
-
@Nullable
-
public static KeyStroke getKeyStroke(String s) {
-
KeyStroke result = null;
-
try {
-
result = KeyStroke.getKeyStroke(s);
-
}
catch (Exception ex) {
-
//ok
-
}
-
-
if (result == null && s != null && s.length() >= 2 && s.charAt(s.length() - 2) == ' ') {
-
try {
-
String s1 = s.substring(0, s.length() - 1) + Character.toUpperCase(s.charAt(s.length() - 1));
-
result = KeyStroke.getKeyStroke(s1);
-
}
- catch (Exception ex) {
-
- // ok
-
+ catch (Exception ignored) {
}
-
}
-
-
return result;
-
}
+ @NotNull
public abstract String[] getPluginActions(PluginId pluginId);
public abstract void queueActionPerformedEvent(final AnAction action, DataContext context, AnActionEvent event);
@@ -117,10 +98,12 @@
public abstract boolean isTransparentOnlyActionsUpdateNow();
+ @NotNull
public List<String> getAbbreviations() {
return Collections.emptyList();
}
+ @NotNull
public List<String> findActionIdsByAbbreviation(String abbreviation) {
return Collections.emptyList();
}
diff --git a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
index 6573917..d93bc12 100644
--- a/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/actionSystem/ex/ComboBoxAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -23,10 +23,13 @@
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.IconLoader;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.ColorUtil;
+import com.intellij.ui.Gray;
import com.intellij.ui.IdeBorderFactory;
+import com.intellij.ui.JBColor;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
@@ -40,7 +43,8 @@
import java.beans.PropertyChangeListener;
public abstract class ComboBoxAction extends AnAction implements CustomComponentAction {
- private static final Icon DISABLED_ARROW_ICON = IconLoader.getDisabledIcon(AllIcons.General.ComboArrow);
+ private static final Icon ARROW_ICON = UIUtil.isUnderDarcula() ? AllIcons.General.ComboArrow : AllIcons.General.ComboBoxButtonArrow;
+ private static final Icon DISABLED_ARROW_ICON = IconLoader.getDisabledIcon(ARROW_ICON);
private boolean mySmallVariant = true;
private DataContext myDataContext;
@@ -321,7 +325,7 @@
@Override
public Insets getInsets() {
final Insets insets = super.getInsets();
- return new Insets(insets.top, insets.left, insets.bottom, insets.right + AllIcons.General.ComboArrow.getIconWidth());
+ return new Insets(insets.top, insets.left, insets.bottom, insets.right + ARROW_ICON.getIconWidth());
}
@Override
@@ -332,10 +336,10 @@
result.top += 2;
result.left += 8;
result.bottom += 2;
- result.right += 4 + AllIcons.General.ComboArrow.getIconWidth();
+ result.right += 4 + ARROW_ICON.getIconWidth();
}
else {
- result.right += AllIcons.General.ComboArrow.getIconWidth();
+ result.right += ARROW_ICON.getIconWidth();
}
return result;
@@ -349,7 +353,7 @@
@Override
public Dimension getPreferredSize() {
final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
- int width = isEmpty ? 10 + AllIcons.General.ComboArrow.getIconWidth() : super.getPreferredSize().width;
+ int width = isEmpty ? 10 + ARROW_ICON.getIconWidth() : super.getPreferredSize().width;
if (isSmallVariant()) width += 4;
return new Dimension(width, isSmallVariant() ? 19 : UIUtil.isUnderNimbusLookAndFeel() ? 24 : 21);
}
@@ -357,6 +361,7 @@
@Override
public void paint(Graphics g) {
GraphicsUtil.setupAntialiasing(g);
+ GraphicsUtil.setupAAPainting(g);
final Dimension size = getSize();
final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
@@ -364,7 +369,7 @@
final Icon icon = getIcon();
int x = 7;
if (icon != null) {
- icon.paintIcon(null, g, x, (size.height - icon.getIconHeight()) / 2);
+ icon.paintIcon(this, g, x, (size.height - icon.getIconHeight()) / 2);
x += icon.getIconWidth() + 3;
}
if (!StringUtil.isEmpty(getText())) {
@@ -384,31 +389,22 @@
g2.setPaint(UIUtil.getGradientPaint(0, 0, UIUtil.getControlColor(), 0, h, ColorUtil.shift(UIUtil.getControlColor(), 0.8)));
}
else {
- g2.setPaint(
- UIUtil.getGradientPaint(0, 0, ColorUtil.shift(UIUtil.getControlColor(), 1.1), 0, h, ColorUtil.shift(UIUtil.getControlColor(), 0.9)));
- }
- g2.fillRect(2, 0, w - 2, h);
- GraphicsUtil.setupAntialiasing(g2);
- if (!UIUtil.isUnderDarcula()) {
- if (!myMouseInside) {
- g2.setPaint(UIUtil.getGradientPaint(0, 0, UIUtil.getBorderColor(), 0, h, UIUtil.getBorderColor().darker()));
+ if (UIUtil.isUnderDarcula()) {
+ g2.setPaint(UIUtil.getGradientPaint(0, 0, ColorUtil.shift(UIUtil.getControlColor(), 1.1), 0, h, ColorUtil.shift(UIUtil.getControlColor(), 0.9)));
} else {
- g2.setPaint(UIUtil.getGradientPaint(0, 0, UIUtil.getBorderColor().darker(), 0, h, UIUtil.getBorderColor().darker().darker()));
- }
- } else {
- if (!myMouseInside) {
- g2.setPaint(UIUtil.getGradientPaint(0, 0, ColorUtil.shift(UIUtil.getControlColor(), 1.2), 0, h, ColorUtil.shift(UIUtil.getControlColor(), 1.3)));
- } else {
- g2.setPaint(UIUtil.getGradientPaint(0, 0, ColorUtil.shift(UIUtil.getControlColor(), 1.4), 0, h, ColorUtil.shift(UIUtil.getControlColor(), 1.5)));
+ g2.setPaint(UIUtil.getGradientPaint(0, 0, new JBColor(SystemInfo.isMac? Gray._226 : Gray._245, Gray._131), 0, h, new JBColor(SystemInfo.isMac? Gray._198 : Gray._208, Gray._128)));
}
}
+ g2.fillRoundRect(2, 0, w - 2, h, 5, 5);
- g2.drawRect(2, 0, w - 3, h - 1);
+ Color borderColor = myMouseInside ? new JBColor(Gray._111, Gray._118) : new JBColor(Gray._151, Gray._95);
+ g2.setPaint(borderColor);
+ g2.drawRoundRect(2, 0, w - 3, h - 1, 5, 5);
final Icon icon = getIcon();
int x = 7;
if (icon != null) {
- icon.paintIcon(null, g, x, (size.height - icon.getIconHeight()) / 2);
+ icon.paintIcon(this, g, x, (size.height - icon.getIconHeight()) / 2);
x += icon.getIconWidth() + 3;
}
if (!StringUtil.isEmpty(getText())) {
@@ -423,7 +419,7 @@
}
}
final Insets insets = super.getInsets();
- final Icon icon = isEnabled() ? AllIcons.General.ComboArrow : DISABLED_ARROW_ICON;
+ final Icon icon = isEnabled() ? ARROW_ICON : DISABLED_ARROW_ICON;
final int x;
if (isEmpty) {
x = (size.width - icon.getIconWidth()) / 2;
diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationBundle.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationBundle.java
index c64536b..cc30402 100644
--- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationBundle.java
+++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* Provides access to localized properties for the application component of IDEA.
*/
public class ApplicationBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls public static final String BUNDLE = "messages.ApplicationBundle";
private ApplicationBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java b/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java
index 4661dbd..18434f7 100644
--- a/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java
+++ b/platform/platform-api/src/com/intellij/openapi/application/ApplicationInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,18 +22,8 @@
public abstract class ApplicationInfo {
public abstract Calendar getBuildDate();
-
- @Deprecated()
- /**
- * Use {@link #getBuild()} instead
- */
- public String getBuildNumber() {
- return getBuild().asString();
- }
-
public abstract BuildNumber getBuild();
public abstract String getApiVersion();
-
public abstract String getMajorVersion();
public abstract String getMinorVersion();
public abstract String getVersionName();
@@ -65,7 +55,6 @@
return ApplicationManager.getApplication().getComponent(ApplicationInfo.class);
}
-
public static boolean helpAvailable() {
return ApplicationManager.getApplication() != null && getInstance() != null && getInstance().hasHelp();
}
@@ -73,4 +62,10 @@
public static boolean contextHelpAvailable() {
return ApplicationManager.getApplication() != null && getInstance() != null && getInstance().hasContextHelp();
}
+
+ /** @deprecated use {@link #getBuild()} instead (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
+ public String getBuildNumber() {
+ return getBuild().asString();
+ }
}
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java b/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java
index 00e7216..a8dbcdb 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/ActionButtonPresentation.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -35,7 +35,7 @@
if (Messages.showYesNoDialog(dialog.getRootPane(),
DiffBundle.message("merge.dialog.exit.without.applying.changes.confirmation.message"),
DiffBundle.message("cancel.visual.merge.dialog.title"),
- Messages.getQuestionIcon()) == 0) {
+ Messages.getQuestionIcon()) == Messages.YES) {
dialog.close(DialogWrapper.CANCEL_EXIT_CODE);
}
}
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java b/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java
index 849dd4c..b73c59e 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/BinaryContent.java
@@ -20,6 +20,8 @@
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.UIBasedFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -34,9 +36,10 @@
import java.nio.charset.IllegalCharsetNameException;
/**
- * Represents bytes as content. May has text representaion.
+ * A {@link DiffContent} represented as a byte array. It still contain a text though.
*/
public class BinaryContent extends DiffContent {
+ @NotNull private final Project myProject;
@NotNull
private final FileType myFileType;
private final byte[] myBytes;
@@ -45,11 +48,12 @@
private String myFilePath;
/**
- * @param charset use to convert bytes to String. null means bytes can't be converted to text.
- * Has no sense if fileType.isBinary()
+ * @param charset use to convert bytes to String. null means bytes can't be converted to text. Has no sense if fileType.isBinary()
* @param fileType type of content
*/
- public BinaryContent(byte[] bytes, Charset charset, @NotNull FileType fileType) {
+ public BinaryContent(@NotNull Project project, byte[] bytes, @Nullable Charset charset, @NotNull FileType fileType,
+ @Nullable String filePath) {
+ myProject = project;
myFileType = fileType;
myBytes = bytes;
if (fileType.isBinary()) {
@@ -58,11 +62,21 @@
else {
myCharset = charset;
}
+ myFilePath = filePath;
+ }
+
+ /**
+ * @deprecated to remove in IDEA 14. Use {@link #BinaryContent(Project, byte[], Charset, FileType, String)}.
+ */
+ public BinaryContent(byte[] bytes, Charset charset, @NotNull FileType fileType) {
+ this(bytes, charset, fileType, null);
}
+ /**
+ * @deprecated to remove in IDEA 14. Use {@link #BinaryContent(Project, byte[], Charset, FileType, String)}.
+ */
public BinaryContent(byte[] bytes, Charset charset, @NotNull FileType fileType, String filePath) {
- this(bytes, charset, fileType);
- myFilePath = filePath;
+ this(ProjectManager.getInstance().getDefaultProject(), bytes, charset, fileType, filePath);
}
@Override
@@ -95,19 +109,22 @@
return myDocument;
}
- /**
- * @return null
- */
@Override
public OpenFileDescriptor getOpenFileDescriptor(int offset) {
- return null;
+ VirtualFile file = findVirtualFile();
+ return file == null ? null : new OpenFileDescriptor(myProject, file, offset);
+ }
+
+ @Nullable
+ private VirtualFile findVirtualFile() {
+ return LocalFileSystem.getInstance().findFileByIoFile(new File(myFilePath));
}
@Override
@Nullable
public VirtualFile getFile() {
if (myFileType instanceof UIBasedFileType) {
- final VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(new File(myFilePath));
+ final VirtualFile file = findVirtualFile();
if (file != null) {
final LightVirtualFile lightFile = new LightVirtualFile(file, new String(myBytes), 1);
lightFile.setOriginalFile(file);
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/DiffBundle.java b/platform/platform-api/src/com/intellij/openapi/diff/DiffBundle.java
index 42fda76..ceea52e 100644
--- a/platform/platform-api/src/com/intellij/openapi/diff/DiffBundle.java
+++ b/platform/platform-api/src/com/intellij/openapi/diff/DiffBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author lesya
*/
public class DiffBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "messages.DiffBundle";
private DiffBundle() {
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/openapi/diff/ShiftedSimpleContent.java b/platform/platform-api/src/com/intellij/openapi/diff/ShiftedSimpleContent.java
deleted file mode 100644
index eb74d8b..0000000
--- a/platform/platform-api/src/com/intellij/openapi/diff/ShiftedSimpleContent.java
+++ /dev/null
@@ -1,48 +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 com.intellij.openapi.diff;
-
-import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.fileTypes.FileType;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * @author irengrig
- * Date: 6/18/11
- * Time: 2:38 PM
- */
-public class ShiftedSimpleContent extends SimpleContent {
- private final int myLineShift;
-
- public ShiftedSimpleContent(String text, int lineShift) {
- super(text);
- myLineShift = lineShift;
- }
-
- public ShiftedSimpleContent(@NotNull String text, FileType type, int lineShift) {
- super(text, type);
- myLineShift = lineShift;
- }
-
- public ShiftedSimpleContent(@NotNull String text, FileType type, EditorFactory f, int lineShift) {
- super(text, type, f);
- myLineShift = lineShift;
- }
-
- public int getLineShift() {
- return myLineShift;
- }
-}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java b/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
new file mode 100644
index 0000000..afc58b8
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/editor/ClipboardTextPerCaretSplitter.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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 java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ClipboardTextPerCaretSplitter {
+ public List<String> split(String input, int caretCount) {
+ if (caretCount <= 0) {
+ throw new IllegalArgumentException("Caret count must be positive");
+ }
+ if (caretCount == 1) {
+ return Collections.singletonList(input);
+ }
+ List<String> result = new ArrayList<String>(caretCount);
+ String[] lines = input.split("\n", -1);
+ for (int i = 0; i < caretCount; i++) {
+ if (lines.length == 0) {
+ result.add("");
+ }
+ else if (lines.length == 1) {
+ result.add(lines[0]);
+ }
+ else if (lines.length % caretCount == 0) {
+ StringBuilder b = new StringBuilder();
+ int linesPerSegment = lines.length / caretCount;
+ for (int j = 0; j < linesPerSegment; j++) {
+ if (j > 0) {
+ b.append('\n');
+ }
+ b.append(lines[i * linesPerSegment + j]);
+ }
+ result.add(b.toString());
+ }
+ else {
+ result.add(i < lines.length ? lines[i] : "");
+ }
+ }
+ return result;
+ }
+}
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 ceb08a7..cf674d6 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/EditorModificationUtil.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,18 +23,19 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.LineTokenizer;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
+import com.intellij.util.Producer;
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
+import java.util.Iterator;
import java.util.List;
public class EditorModificationUtil {
- private EditorModificationUtil() {}
+ private EditorModificationUtil() { }
public static void deleteSelectedText(Editor editor) {
SelectionModel selectionModel = editor.getSelectionModel();
@@ -125,102 +126,107 @@
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
selectionModel.removeSelection();
}
+ else if (editor.getCaretModel().getOffset() != oldOffset) { // handling the case when caret model tracks document changes
+ editor.getCaretModel().moveToOffset(oldOffset);
+ }
return offset;
}
@Nullable
- public static TextRange pasteFromClipboard(Editor editor) {
- return pasteFromTransferrable(CopyPasteManager.getInstance().getContents(), editor);
+ public static TextRange pasteTransferable(final Editor editor, @Nullable Producer<Transferable> producer) {
+ String text = getStringContent(producer);
+ if (text == null) return null;
+
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ int caretCount = editor.getCaretModel().getAllCarets().size();
+ final Iterator<String> segments = new ClipboardTextPerCaretSplitter().split(text, caretCount).iterator();
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ insertStringAtCaret(editor, segments.next(), false, true);
+ }
+ });
+ return null;
+ }
+ else {
+ int caretOffset = editor.getCaretModel().getOffset();
+ insertStringAtCaret(editor, text, false, true);
+ return new TextRange(caretOffset, caretOffset + text.length());
+ }
+ }
+
+ public static void pasteTransferableAsBlock(Editor editor, @Nullable Producer<Transferable> producer) {
+ String text = getStringContent(producer);
+ if (text == null) return;
+
+ int caretLine = editor.getCaretModel().getLogicalPosition().line;
+ int originalCaretLine = caretLine;
+ int selectedLinesCount = 0;
+
+ final SelectionModel selectionModel = editor.getSelectionModel();
+ if (selectionModel.hasBlockSelection()) {
+ final LogicalPosition start = selectionModel.getBlockStart();
+ final LogicalPosition end = selectionModel.getBlockEnd();
+ assert start != null;
+ assert end != null;
+ LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
+ selectedLinesCount = Math.abs(end.line - start.line);
+ caretLine = caret.line;
+
+ deleteSelectedText(editor);
+ editor.getCaretModel().moveToLogicalPosition(caret);
+ }
+
+ LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
+
+ String[] lines = LineTokenizer.tokenize(text.toCharArray(), false);
+ if (lines.length > 1 || selectedLinesCount == 0) {
+ int longestLineLength = 0;
+ for (int i = 0; i < lines.length; i++) {
+ String line = lines[i];
+ longestLineLength = Math.max(longestLineLength, line.length());
+ editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
+ insertStringAtCaret(editor, line, false, true);
+ }
+ caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
+ }
+ else {
+ for (int i = 0; i <= selectedLinesCount; i++) {
+ editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
+ insertStringAtCaret(editor, text, false, true);
+ }
+ caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + text.length());
+ }
+
+ editor.getCaretModel().moveToLogicalPosition(caretToRestore);
+ zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
}
@Nullable
- public static TextRange pasteFromTransferrable(Transferable content, Editor editor) {
- if (content != null) {
- try {
- String s = getStringContent(content);
-
- int caretOffset = editor.getCaretModel().getOffset();
- insertStringAtCaret(editor, s, false, true);
- return new TextRange(caretOffset, caretOffset + s.length());
- } catch (Exception exception) {
- editor.getComponent().getToolkit().beep();
- }
- }
-
- return null;
- }
-
- private static String getStringContent(final Transferable content) throws UnsupportedFlavorException, IOException {
- RawText raw = RawText.fromTransferable(content);
- String s;
- if (raw != null) {
- s = raw.rawText;
+ private static String getStringContent(@Nullable Producer<Transferable> producer) {
+ Transferable content = null;
+ if (producer != null) {
+ content = producer.produce();
}
else {
- s = (String)content.getTransferData(DataFlavor.stringFlavor);
- }
-
- s = StringUtil.convertLineSeparators(s);
- return s;
- }
-
- public static void pasteFromClipboardAsBlock(Editor editor) {
- pasteTransferableAsBlock(editor, null);
- }
-
- public static void pasteTransferableAsBlock(Editor editor, @Nullable Transferable content) {
- if (content == null) {
- content = CopyPasteManager.getInstance().getContents();
- }
-
- if (content != null) {
- try {
- int caretLine = editor.getCaretModel().getLogicalPosition().line;
- int originalCaretLine = caretLine;
-
- int selectedLinesCount = 0;
- final SelectionModel selectionModel = editor.getSelectionModel();
- if (selectionModel.hasBlockSelection()) {
- final LogicalPosition start = selectionModel.getBlockStart();
- final LogicalPosition end = selectionModel.getBlockEnd();
- assert start != null;
- assert end != null;
- LogicalPosition caret = new LogicalPosition(Math.min(start.line, end.line), Math.min(start.column, end.column));
- selectedLinesCount = Math.abs(end.line - start.line);
- caretLine = caret.line;
-
- deleteSelectedText(editor);
- editor.getCaretModel().moveToLogicalPosition(caret);
- }
-
- LogicalPosition caretToRestore = editor.getCaretModel().getLogicalPosition();
- String s = getStringContent(content);
-
- String[] lines = LineTokenizer.tokenize(s.toCharArray(), false);
- if (lines.length > 1 || selectedLinesCount == 0) {
- int longestLineLength = 0;
- for (int i = 0; i < lines.length; i++) {
- String line = lines[i];
- longestLineLength = Math.max(longestLineLength, line.length());
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
- insertStringAtCaret(editor, line, false, true);
- }
- caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + longestLineLength);
- }
- else {
- for (int i = 0; i <= selectedLinesCount; i++) {
- editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(caretLine + i, caretToRestore.column));
- insertStringAtCaret(editor, s, false, true);
- }
- caretToRestore = new LogicalPosition(originalCaretLine, caretToRestore.column + s.length());
- }
- editor.getCaretModel().moveToLogicalPosition(caretToRestore);
- zeroWidthBlockSelectionAtCaretColumn(editor, caretLine, caretLine + selectedLinesCount);
- } catch (Exception exception) {
- editor.getComponent().getToolkit().beep();
+ CopyPasteManager manager = CopyPasteManager.getInstance();
+ if (manager.areDataFlavorsAvailable(DataFlavor.stringFlavor)) {
+ content = manager.getContents();
}
}
+ if (content == null) return null;
+
+ RawText raw = RawText.fromTransferable(content);
+ if (raw != null) return raw.rawText;
+
+ try {
+ return (String)content.getTransferData(DataFlavor.stringFlavor);
+ }
+ catch (UnsupportedFlavorException ignore) { }
+ catch (IOException ignore) { }
+
+ return null;
}
/**
@@ -358,4 +364,40 @@
insertStringAtCaret(editor, str, toProcessOverwriteMode, true);
}
}
+
+ /** @deprecated use {@link #pasteTransferable(Editor, Producer)} (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
+ public static TextRange pasteFromClipboard(Editor editor) {
+ return pasteTransferable(editor, null);
+ }
+
+ /** @deprecated use {@link #pasteTransferable(Editor, Producer)} (to remove in IDEA 14) */
+ @SuppressWarnings("SpellCheckingInspection,UnusedDeclaration")
+ public static TextRange pasteFromTransferrable(final Transferable content, Editor editor) {
+ return pasteTransferable(editor, new Producer<Transferable>() {
+ @Nullable
+ @Override
+ public Transferable produce() {
+ return content;
+ }
+ });
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ /** @deprecated use {@link #pasteTransferableAsBlock(Editor, Producer)} (to remove in IDEA 14) */
+ public static void pasteFromClipboardAsBlock(Editor editor) {
+ pasteTransferableAsBlock(editor, (Producer<Transferable>)null);
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ /** @deprecated use {@link #pasteTransferableAsBlock(Editor, Producer)} (to remove in IDEA 14) */
+ public static void pasteTransferableAsBlock(Editor editor, @Nullable final Transferable content) {
+ pasteTransferableAsBlock(editor, new Producer<Transferable>() {
+ @Nullable
+ @Override
+ public Transferable produce() {
+ return content;
+ }
+ });
+ }
}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/RawText.java b/platform/platform-api/src/com/intellij/openapi/editor/RawText.java
index 5f4ca25..5d69d1f 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/RawText.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/RawText.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,13 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: Sep 5, 2006
- * Time: 9:31:06 PM
- */
package com.intellij.openapi.editor;
import org.jetbrains.annotations.NonNls;
@@ -31,8 +24,14 @@
import java.io.IOException;
import java.io.Serializable;
+/**
+ * @author max
+ * @since Sep 5, 2006
+ */
public class RawText implements Cloneable, Serializable {
+ /** @deprecated use {@link #getDataFlavor()} (to make private in IDEA 14) */
public static @NonNls DataFlavor ourFlavor;
+
public String rawText;
public RawText(final String rawText) {
@@ -40,45 +39,41 @@
}
public Object clone() {
- try{
+ try {
return super.clone();
}
- catch(CloneNotSupportedException e){
+ catch (CloneNotSupportedException e) {
throw new RuntimeException();
}
}
+ @SuppressWarnings("deprecation")
public static DataFlavor getDataFlavor() {
- if (ourFlavor != null) {
- return ourFlavor;
- }
+ if (ourFlavor != null) return ourFlavor;
+
try {
- ourFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + RawText.class.getName(), "Raw Text");
+ DataFlavor flavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType + ";class=" + RawText.class.getName(), "Raw Text");
+ ourFlavor = flavor;
+ return flavor;
}
- catch (NoClassDefFoundError e) {
- return null;
- }
- catch (IllegalArgumentException e) {
- return null;
- }
- return ourFlavor;
+ catch (NoClassDefFoundError ignore) { }
+ catch (IllegalArgumentException ignore) { }
+
+ return null;
}
@Nullable
public static RawText fromTransferable(Transferable content) {
- RawText raw = null;
- final DataFlavor flavor = getDataFlavor();
+ DataFlavor flavor = getDataFlavor();
+
if (flavor != null) {
try {
- raw = (RawText)content.getTransferData(flavor);
+ return (RawText)content.getTransferData(flavor);
}
- catch (UnsupportedFlavorException e) {
- // OK. raw will be null and we'll get plain string
- }
- catch (IOException e) {
- // OK. raw will be null and we'll get plain string
- }
+ catch (UnsupportedFlavorException ignore) { }
+ catch (IOException ignore) { }
}
- return raw;
+
+ return null;
}
}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
index 3333167..211d1eb 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorAction.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,7 @@
setEnabledInModalContext(true);
}
- public final EditorActionHandler setupHandler(EditorActionHandler newHandler) {
+ public final EditorActionHandler setupHandler(@NotNull EditorActionHandler newHandler) {
ensureHandlersLoaded();
EditorActionHandler tmp = myHandler;
myHandler = newHandler;
@@ -51,8 +51,9 @@
if (!myHandlersLoaded) {
myHandlersLoaded = true;
final String id = ActionManager.getInstance().getId(this);
- for (int i = Extensions.getExtensions(EditorActionHandlerBean.EP_NAME).length - 1; i >= 0; i--) {
- final EditorActionHandlerBean handlerBean = Extensions.getExtensions(EditorActionHandlerBean.EP_NAME)[i];
+ EditorActionHandlerBean[] extensions = Extensions.getExtensions(EditorActionHandlerBean.EP_NAME);
+ for (int i = extensions.length - 1; i >= 0; i--) {
+ final EditorActionHandlerBean handlerBean = extensions[i];
if (handlerBean.action.equals(id)) {
myHandler = handlerBean.getHandler(myHandler);
}
@@ -68,7 +69,7 @@
}
@Nullable
- protected Editor getEditor(final DataContext dataContext) {
+ protected Editor getEditor(@NotNull DataContext dataContext) {
return CommonDataKeys.EDITOR.getData(dataContext);
}
@@ -79,7 +80,7 @@
Runnable command = new Runnable() {
@Override
public void run() {
- handler.execute(editor, getProjectAwareDataContext(editor, dataContext));
+ handler.executeInCaretContext(editor, null, getProjectAwareDataContext(editor, dataContext));
}
};
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java
index 8b61ce8..9633d2d 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorActionHandler.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,14 +16,34 @@
package com.intellij.openapi.editor.actionSystem;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
+import org.jetbrains.annotations.Nullable;
/**
* Interface for actions activated by keystrokes in the editor.
+ * Implementations should override {@link #execute(com.intellij.openapi.editor.Editor, com.intellij.openapi.actionSystem.DataContext)} or
+ * {@link #execute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
+ * (preferrably).
+ * <p>
+ * Two types of handlers are supported: the ones which are executed once, and the ones which are executed for each caret. The latter can be
+ * created using {@link com.intellij.openapi.editor.actionSystem.EditorActionHandler#EditorActionHandler(boolean)} constructor.
*
* @see EditorActionManager#setActionHandler(String, EditorActionHandler)
*/
public abstract class EditorActionHandler {
+ private final boolean myRunForEachCaret;
+ private boolean inExecution;
+
+ protected EditorActionHandler() {
+ this(false);
+ }
+
+ protected EditorActionHandler(boolean runForEachCaret) {
+ myRunForEachCaret = runForEachCaret;
+ }
+
/**
* Checks if the action handler is currently enabled.
*
@@ -36,15 +56,76 @@
}
/**
- * Executes the action.
+ * Executes the action in the context of the current caret. This method exists for historical reasons, in most cases you should use
+ * {@link #execute(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
+ * instead.
+ *
+ * @param editor the editor in which the action is invoked.
+ * @param dataContext the data context for the action.
+ *
+ * @see {@link com.intellij.openapi.editor.CaretModel#getCurrentCaret()}
+ */
+ public void execute(Editor editor, DataContext dataContext) {
+ if (inExecution) {
+ return;
+ }
+ try {
+ inExecution = true;
+ execute(editor, editor.getCaretModel().getCurrentCaret(), dataContext);
+ }
+ finally {
+ inExecution = false;
+ }
+ }
+
+ /**
+ * Executes the action in the context of given caret
+ *
+ * @param editor the editor in which the action is invoked.
+ * @param caret the caret for which the action is performed at the moment or <code>null</code> if it's a 'one-off' action executed
+ * without current context
+ * @param dataContext the data context for the action.
+ */
+ public void execute(Editor editor, @Nullable Caret caret, DataContext dataContext) {
+ if (inExecution) {
+ return;
+ }
+ try {
+ inExecution = true;
+ execute(editor, dataContext);
+ }
+ finally {
+ inExecution = false;
+ }
+ }
+
+ public boolean executeInCommand(Editor editor, DataContext dataContext) {
+ return true;
+ }
+
+ public boolean runForAllCarets() {
+ return myRunForEachCaret;
+ }
+
+ /**
+ * Executes the action in the context of given caret. If the caret is <code>null</code>, and the handler is a 'per-caret' handler,
+ * it's executed for all carets.
*
* @param editor the editor in which the action is invoked.
* @param dataContext the data context for the action.
*/
- public abstract void execute(Editor editor, DataContext dataContext);
-
- public boolean executeInCommand(Editor editor, DataContext dataContext) {
- return true;
+ public void executeInCaretContext(final Editor editor, Caret caret, final DataContext dataContext) {
+ if (caret == null && runForAllCarets()) {
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ execute(editor, caret, dataContext);
+ }
+ });
+ }
+ else {
+ execute(editor, caret, dataContext);
+ }
}
public DocCommandGroupId getCommandGroupId(Editor editor) {
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorWriteActionHandler.java b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorWriteActionHandler.java
index 235214b..3c8f7f9 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorWriteActionHandler.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/actionSystem/EditorWriteActionHandler.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,17 +17,26 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.MockDocumentEvent;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
+import org.jetbrains.annotations.Nullable;
public abstract class EditorWriteActionHandler extends EditorActionHandler {
+ private boolean inExecution;
+
+ protected EditorWriteActionHandler() {
+ }
+
+ protected EditorWriteActionHandler(boolean runForEachCaret) {
+ super(runForEachCaret);
+ }
+
@Override
- public final void execute(final Editor editor, final DataContext dataContext) {
+ public final void execute(final Editor editor, @Nullable final Caret caret, final DataContext dataContext) {
if (editor.isViewer()) return;
if (dataContext != null) {
@@ -52,7 +61,7 @@
doc.startGuardedBlockChecking();
try {
- executeWriteAction(editor, dataContext);
+ executeWriteAction(editor, caret, dataContext);
}
catch (ReadOnlyFragmentModificationException e) {
EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
@@ -64,5 +73,34 @@
});
}
- public abstract void executeWriteAction(Editor editor, DataContext dataContext);
+ /**
+ * This method exists for historical reasons. For most purposes one should use/override
+ * {@link #executeWriteAction(com.intellij.openapi.editor.Editor, com.intellij.openapi.editor.Caret, com.intellij.openapi.actionSystem.DataContext)}
+ * method.
+ */
+ public void executeWriteAction(Editor editor, DataContext dataContext) {
+ if (inExecution) {
+ return;
+ }
+ try {
+ inExecution = true;
+ executeWriteAction(editor, editor.getCaretModel().getCurrentCaret(), dataContext);
+ }
+ finally {
+ inExecution = false;
+ }
+ }
+
+ public void executeWriteAction(Editor editor, @Nullable Caret caret, DataContext dataContext) {
+ if (inExecution) {
+ return;
+ }
+ try {
+ inExecution = true;
+ executeWriteAction(editor, dataContext);
+ }
+ finally {
+ inExecution = false;
+ }
+ }
}
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 30458b0..c52ec73 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
@@ -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.
@@ -50,6 +50,7 @@
}
private static class Handler implements TypedActionHandler {
+ @Override
public void execute(@NotNull Editor editor, char charTyped, @NotNull DataContext dataContext) {
if (editor.isViewer()) return;
@@ -121,20 +122,27 @@
myDataContext = dataContext;
}
+ @Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new DocumentRunnable(myEditor.getDocument(), myEditor.getProject()) {
+ @Override
public void run() {
- Document doc = myEditor.getDocument();
- doc.startGuardedBlockChecking();
- try {
- getHandler().execute(myEditor, myCharTyped, myDataContext);
- }
- catch (ReadOnlyFragmentModificationException e) {
- EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
- }
- finally {
- doc.stopGuardedBlockChecking();
- }
+ myEditor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ Document doc = myEditor.getDocument();
+ doc.startGuardedBlockChecking();
+ try {
+ getHandler().execute(myEditor, myCharTyped, myDataContext);
+ }
+ catch (ReadOnlyFragmentModificationException e) {
+ EditorActionManager.getInstance().getReadonlyFragmentModificationHandler(doc).handle(e);
+ }
+ finally {
+ doc.stopGuardedBlockChecking();
+ }
+ }
+ });
}
});
}
diff --git a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
index 489ab12..d3f7d9f 100644
--- a/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.java
+++ b/platform/platform-api/src/com/intellij/openapi/editor/highlighter/FragmentedEditorHighlighter.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.editor.markup.TextAttributes;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
import java.util.List;
import java.util.Map;
@@ -90,6 +91,7 @@
}
}
+ @NotNull
@Override
public HighlighterIterator createIterator(int startOffset) {
Map.Entry<Integer, Element> entry = myPieces.ceilingEntry(startOffset);
@@ -97,15 +99,15 @@
}
@Override
- public void setText(CharSequence text) {
+ public void setText(@NotNull CharSequence text) {
}
@Override
- public void setEditor(HighlighterClient editor) {
+ public void setEditor(@NotNull HighlighterClient editor) {
}
@Override
- public void setColorScheme(EditorColorsScheme scheme) {
+ public void setColorScheme(@NotNull EditorColorsScheme scheme) {
}
@Override
diff --git a/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorBuilder.java b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorBuilder.java
new file mode 100644
index 0000000..c772b4a
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/fileChooser/FileChooserDescriptorBuilder.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.fileChooser;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author traff
+ */
+public class FileChooserDescriptorBuilder {
+ private boolean myChooseFiles;
+ private boolean myChooseFolders;
+ private boolean myChooseJars;
+ private boolean myChooseJarsAsFiles;
+ private boolean myChooseJarContents;
+ private boolean myChooseMultiple;
+
+ private String myTitle = null;
+ private String myDescription = null;
+ private Boolean myShowFileSystemRoots = null;
+
+ private Boolean myHideIgnored = null;
+ private Boolean myTreeRootVisible = null;
+
+ private List<VirtualFile> myRoots = null;
+
+
+
+ public FileChooserDescriptorBuilder(boolean chooseFiles,
+ boolean chooseFolders,
+ boolean chooseJars,
+ boolean chooseJarsAsFiles,
+ boolean chooseJarContents,
+ boolean chooseMultiple) {
+ myChooseFiles = chooseFiles;
+ myChooseFolders = chooseFolders;
+ myChooseJars = chooseJars;
+ myChooseJarsAsFiles = chooseJarsAsFiles;
+ myChooseJarContents = chooseJarContents;
+ myChooseMultiple = chooseMultiple;
+ }
+
+
+ public static FileChooserDescriptorBuilder onlyFiles() {
+ return new FileChooserDescriptorBuilder(true, false, false, false, false, false);
+ }
+
+ public static FileChooserDescriptorBuilder filesAndFolders() {
+ return new FileChooserDescriptorBuilder(true, true, false, false, false, false);
+ }
+
+ public FileChooserDescriptorBuilder chooseMultiple() {
+ myChooseMultiple = true;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder chooseJars(boolean chooseJars, boolean chooseJarsAsFiles, boolean chooseJarContents) {
+ myChooseJars = chooseJars;
+ myChooseJarsAsFiles = chooseJarsAsFiles;
+ myChooseJarContents = chooseJarContents;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder withTitle(@NotNull String title) {
+ myTitle = title;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder withDescription(@NotNull String description) {
+ myDescription = description;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder showFileSystemRoots(boolean showFileSystemRoots) {
+ myShowFileSystemRoots = showFileSystemRoots;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder hideIgnored(boolean hideIgnored) {
+ myHideIgnored = hideIgnored;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder withTreeRootVisible(boolean isTreeRootVisible) {
+ myTreeRootVisible = isTreeRootVisible;
+ return this;
+ }
+
+ public FileChooserDescriptorBuilder withRoots(List<VirtualFile> roots) {
+ myRoots = roots;
+ return this;
+ }
+
+
+ public FileChooserDescriptor build() {
+ FileChooserDescriptor descriptor = new FileChooserDescriptor(myChooseFiles, myChooseFolders, myChooseJars, myChooseJarsAsFiles, myChooseJarContents, myChooseMultiple);
+
+ if (myTitle != null) {
+ descriptor.setTitle(myTitle);
+ }
+
+ if (myDescription != null) {
+ descriptor.setDescription(myDescription);
+ }
+
+ if (myShowFileSystemRoots != null) {
+ descriptor.setShowFileSystemRoots(myShowFileSystemRoots);
+ }
+
+ if (myHideIgnored != null) {
+ descriptor.setHideIgnored(myHideIgnored);
+ }
+
+ if (myTreeRootVisible != null) {
+ descriptor.setIsTreeRootVisible(myTreeRootVisible);
+ }
+
+ if (myRoots != null) {
+ descriptor.setRoots(myRoots);
+ }
+
+ return descriptor;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
index aba033d..366f69d 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManager.java
@@ -137,11 +137,11 @@
/**
* @deprecated use addTopComponent
*/
- public abstract void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent);
+ public abstract void showEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComponent);
/**
* @deprecated use removeTopComponent
*/
- public abstract void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComoponent);
+ public abstract void removeEditorAnnotation(@NotNull FileEditor editor, @NotNull JComponent annotationComponent);
public abstract void addTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component);
public abstract void removeTopComponent(@NotNull final FileEditor editor, @NotNull final JComponent component);
diff --git a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerAdapter.java b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerAdapter.java
index 6d25562..7e0f3ff 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerAdapter.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/FileEditorManagerAdapter.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,9 +19,12 @@
import org.jetbrains.annotations.NotNull;
public abstract class FileEditorManagerAdapter implements FileEditorManagerListener{
+ @Override
public void fileOpened(@NotNull FileEditorManager source, @NotNull VirtualFile file) {}
+ @Override
public void fileClosed(@NotNull FileEditorManager source, @NotNull VirtualFile file) {}
+ @Override
public void selectionChanged(@NotNull FileEditorManagerEvent event) {}
}
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 d8f6572..9561581 100644
--- a/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.java
+++ b/platform/platform-api/src/com/intellij/openapi/fileEditor/OpenFileDescriptor.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.
@@ -204,11 +204,13 @@
if (myLogicalLine >= 0) {
LogicalPosition pos = new LogicalPosition(myLogicalLine, Math.max(myLogicalColumn, 0));
if (offset < 0 || offset == e.logicalPositionToOffset(pos)) {
+ caretModel.removeSecondaryCarets();
caretModel.moveToLogicalPosition(pos);
caretMoved = true;
}
}
if (!caretMoved && offset >= 0) {
+ caretModel.removeSecondaryCarets();
caretModel.moveToOffset(Math.min(offset, e.getDocument().getTextLength()));
caretMoved = true;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ide/CopyPasteManager.java b/platform/platform-api/src/com/intellij/openapi/ide/CopyPasteManager.java
index 51f67a6..c96ce0a 100644
--- a/platform/platform-api/src/com/intellij/openapi/ide/CopyPasteManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/ide/CopyPasteManager.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,11 +39,20 @@
public abstract void removeContentChangedListener(ContentChangedListener listener);
- public abstract boolean isDataFlavorAvailable(@Nullable DataFlavor flavor);
+ /** @deprecated use {@link #getContents(DataFlavor)} or {@link #areDataFlavorsAvailable(DataFlavor...)} (to remove in IDEA 14) */
+ @SuppressWarnings("unused")
+ public boolean isDataFlavorAvailable(@Nullable DataFlavor flavor) {
+ return flavor != null && areDataFlavorsAvailable(flavor);
+ }
+
+ public abstract boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors);
@Nullable
public abstract Transferable getContents();
+ @Nullable
+ public abstract <T> T getContents(@NotNull DataFlavor flavor);
+
public abstract Transferable[] getAllContents();
public abstract void setContents(@NotNull Transferable content);
@@ -56,11 +65,11 @@
* <p/>
* However, there are situations when all 'kill rings' should be stopped manually (e.g. on undo). Hence, we need
* a handle to ask for that. This method works like such a handle.
- *
+ *
* @see KillRingTransferable
*/
public abstract void stopKillRings();
-
+
public interface ContentChangedListener extends EventListener {
void contentChanged(@Nullable final Transferable oldTransferable, final Transferable newTransferable);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/keymap/KeyMapBundle.java b/platform/platform-api/src/com/intellij/openapi/keymap/KeyMapBundle.java
index 2e6d14f..066fc86 100644
--- a/platform/platform-api/src/com/intellij/openapi/keymap/KeyMapBundle.java
+++ b/platform/platform-api/src/com/intellij/openapi/keymap/KeyMapBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -31,21 +32,20 @@
* Time: 17:13:10
*/
public class KeyMapBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = "messages.KeyMapBundle") String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
protected static final String PATH_TO_BUNDLE = "messages.KeyMapBundle";
private KeyMapBundle() {
}
- public static String message(@PropertyKey(resourceBundle = "messages.KeyMapBundle")String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/openapi/options/OptionsBundle.java b/platform/platform-api/src/com/intellij/openapi/options/OptionsBundle.java
index d80d570..faaa562 100644
--- a/platform/platform-api/src/com/intellij/openapi/options/OptionsBundle.java
+++ b/platform/platform-api/src/com/intellij/openapi/options/OptionsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author lesya
*/
public class OptionsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "messages.OptionsBundle";
private OptionsBundle() {
}
- public static String message(@NonNls @PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java b/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java
index a5ac412..aa6d961 100644
--- a/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/options/ShowSettingsUtil.java
@@ -39,7 +39,7 @@
public abstract boolean editConfigurable(Project project, Configurable configurable);
- public abstract boolean editConfigurable(Project project, Configurable configurable, Runnable advancedInitialization);
+ public abstract boolean editConfigurable(@Nullable Project project, Configurable configurable, @Nullable Runnable advancedInitialization);
public abstract boolean editConfigurable(Component parent, Configurable configurable);
diff --git a/platform/platform-api/src/com/intellij/openapi/progress/RunBackgroundable.java b/platform/platform-api/src/com/intellij/openapi/progress/RunBackgroundable.java
index 2dac114..2aa2163 100644
--- a/platform/platform-api/src/com/intellij/openapi/progress/RunBackgroundable.java
+++ b/platform/platform-api/src/com/intellij/openapi/progress/RunBackgroundable.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.progress;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -46,11 +47,12 @@
}
final boolean finalCanceled = canceled;
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
if (finalCanceled) {
task.onCancel();
- } else {
+ }
+ else {
task.onSuccess();
}
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java b/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
index ee1782a..3f4a92a 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/Banner.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/Banner.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.
@@ -21,7 +21,7 @@
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.PlatformColors;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -32,8 +32,7 @@
import java.util.Map;
import java.util.Set;
-public class Banner extends NonOpaquePanel implements PropertyChangeListener{
-
+class Banner extends NonOpaquePanel implements PropertyChangeListener{
private int myBannerMinHeight;
private final JComponent myText = new MyText();
@@ -53,6 +52,7 @@
public void addAction(final Action action) {
action.addPropertyChangeListener(this);
final LinkLabel label = new LinkLabel(null, null, new LinkListener() {
+ @Override
public void linkSelected(final LinkLabel aSource, final Object aLinkData) {
action.actionPerformed(new ActionEvent(Banner.this, ActionEvent.ACTION_PERFORMED, Action.ACTION_COMMAND_KEY));
}
@@ -75,10 +75,11 @@
label.setToolTipText((String)action.getValue(Action.SHORT_DESCRIPTION));
}
+ @Override
public void propertyChange(final PropertyChangeEvent evt) {
final Object source = evt.getSource();
if (source instanceof Action) {
- updateAction(((Action)source));
+ updateAction((Action)source);
}
}
@@ -91,12 +92,14 @@
myActionsPanel.removeAll();
}
+ @Override
public Dimension getMinimumSize() {
final Dimension size = super.getMinimumSize();
size.height = Math.max(myBannerMinHeight, size.height);
return size;
}
+ @Override
public Dimension getPreferredSize() {
final Dimension size = super.getPreferredSize();
size.height = getMinimumSize().height;
@@ -109,19 +112,17 @@
repaint();
}
- public void setText(@Nullable final String... text) {
+ public void setText(@NotNull final String... text) {
myText.removeAll();
- if (text == null) return;
-
for (int i = 0; i < text.length; i++) {
- final JLabel eachLabel = new JLabel(text[i], JLabel.CENTER);
+ final JLabel eachLabel = new JLabel(text[i], SwingConstants.CENTER);
final int gap = eachLabel.getIconTextGap();
eachLabel.setBorder(new EmptyBorder(0, 0, 0, gap));
- eachLabel.setVerticalTextPosition(JLabel.TOP);
+ eachLabel.setVerticalTextPosition(SwingConstants.TOP);
eachLabel.setFont(eachLabel.getFont().deriveFont(Font.BOLD, eachLabel.getFont().getSize()));
myText.add(eachLabel);
if (i < text.length - 1) {
- final JLabel eachIcon = new JLabel(AllIcons.General.ComboArrowRight, JLabel.CENTER);
+ final JLabel eachIcon = new JLabel(AllIcons.General.ComboArrowRight, SwingConstants.CENTER);
eachIcon.setBorder(new EmptyBorder(0, 0, 0, gap));
myText.add(eachIcon);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java b/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java
index beded7f..7894408 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ComboBox.java
@@ -23,10 +23,12 @@
import com.intellij.ui.components.JBList;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.plaf.basic.ComboPopup;
+import javax.swing.table.TableCellEditor;
import java.awt.*;
import java.awt.event.*;
import java.util.List;
@@ -46,6 +48,8 @@
* @author Vladimir Kondratyev
*/
public class ComboBox extends ComboBoxWithWidePopup implements AWTEventListener {
+ public static final String TABLE_CELL_EDITOR_PROPERTY = "tableCellEditor";
+
private int myMinimumAndPreferredWidth;
private boolean mySwingPopup = true;
private JBPopup myJBPopup;
@@ -86,6 +90,15 @@
}
}
+ public static void registerTableCellEditor(@NotNull JComboBox comboBox, @NotNull TableCellEditor cellEditor) {
+ comboBox.putClientProperty(TABLE_CELL_EDITOR_PROPERTY, cellEditor);
+ comboBox.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
+ }
+
+ public void registerTableCellEditor(@NotNull TableCellEditor cellEditor) {
+ registerTableCellEditor(this, cellEditor);
+ }
+
@Override
public void setPopupVisible(boolean visible) {
if (!isSwingPopup()) {
@@ -194,6 +207,9 @@
registerCancelOnEscape();
}
+ public ComboBox(@NotNull Object[] items) {
+ this(items, -1);
+ }
public boolean isSwingPopup() {
return mySwingPopup;
@@ -217,7 +233,7 @@
}
else {
//noinspection HardCodedStringLiteral
- final Object clientProperty = getClientProperty("tableCellEditor");
+ final Object clientProperty = getClientProperty(TABLE_CELL_EDITOR_PROPERTY);
if (clientProperty instanceof CellEditor) {
// If combo box is inside editable table then we need to cancel editing
// and do not close heavy weight dialog container (if any)
@@ -293,8 +309,7 @@
myComboBox.setPopupVisible(false);
}
else {
- //noinspection HardCodedStringLiteral
- final Object clientProperty = myComboBox.getClientProperty("tableCellEditor");
+ final Object clientProperty = myComboBox.getClientProperty(TABLE_CELL_EDITOR_PROPERTY);
if (clientProperty instanceof CellEditor) {
// If combo box is inside editable table then we need to cancel editing
// and do not close heavy weight dialog container (if any)
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
index 841a807..5eb15bd 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/DetailsComponent.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,19 +18,16 @@
import com.intellij.ui.components.panels.NonOpaquePanel;
import com.intellij.ui.components.panels.Wrapper;
-import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
-import javax.swing.border.LineBorder;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.awt.geom.GeneralPath;
import java.util.ArrayList;
@@ -57,14 +54,13 @@
public DetailsComponent() {
myComponent = new JPanel(new BorderLayout()) {
+ @Override
protected void paintComponent(final Graphics g) {
if (NullableComponent.Check.isNull(myContent) || !myDetailsEnabled) return;
GraphicsConfig c = new GraphicsConfig(g);
c.setAntialiasing(true);
- int arc = 8;
-
Insets insets = getInsets();
if (insets == null) {
insets = new Insets(0, 0, 0, 0);
@@ -81,6 +77,7 @@
final int rightY = banner.y + banner.height;
header.moveTo(leftX, rightY);
+ int arc = 8;
header.lineTo(leftX, leftY + arc);
header.quadTo(leftX, leftY, leftX + arc, leftY);
header.lineTo(rightX - arc, leftY);
@@ -114,7 +111,7 @@
myBanner.add(myBannerLabel, BorderLayout.CENTER);
- myEmptyContentLabel = new JLabel("", JLabel.CENTER);
+ myEmptyContentLabel = new JLabel("", SwingConstants.CENTER);
revalidateDetailsMode();
}
@@ -203,12 +200,7 @@
}
private void updateBanner() {
- if (NullableComponent.Check.isNull(myContent)) {
- myBannerLabel.setText(null);
- }
- else {
- myBannerLabel.setText(myBannerText);
- }
+ myBannerLabel.setText(NullableComponent.Check.isNull(myContent) || myBannerText == null ? ArrayUtil.EMPTY_STRING_ARRAY : myBannerText);
myBannerLabel.revalidate();
myBannerLabel.repaint();
@@ -219,7 +211,7 @@
}
public DetailsComponent setEmptyContentText(@Nullable final String emptyContentText) {
- @NonNls final String s = "<html><body><center>" + (emptyContentText != null ? emptyContentText : "") + "</center></body><html>";
+ @NonNls final String s = XmlStringUtil.wrapInHtml("<center>" + (emptyContentText != null ? emptyContentText : "") + "</center>");
myEmptyContentLabel.setText(s);
return this;
}
@@ -253,17 +245,16 @@
}
- public static interface Facade {
-
+ public interface Facade {
DetailsComponent getDetailsComponent();
-
}
private class MyWrapper extends Wrapper implements NullableComponent {
public MyWrapper(final JComponent c) {
- super(c == null || NullableComponent.Check.isNull(c) ? DetailsComponent.this.myEmptyContentLabel : c);
+ super(c == null || NullableComponent.Check.isNull(c) ? myEmptyContentLabel : c);
}
+ @Override
public boolean isNull() {
return getTargetComponent() == myEmptyContentLabel;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java
index d6d8bbf..0f19ff2 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/DialogWrapper.java
@@ -68,7 +68,7 @@
* The standard base class for modal dialog boxes. The dialog wrapper could be used only on event dispatch thread.
* In case when the dialog must be created from other threads use
* {@link EventQueue#invokeLater(Runnable)} or {@link EventQueue#invokeAndWait(Runnable)}.
- *
+ * <p/>
* See also http://confluence.jetbrains.net/display/IDEADEV/IntelliJ+IDEA+DialogWrapper.
*/
@SuppressWarnings({"SSBasedInspection", "MethodMayBeStatic", "UnusedDeclaration"})
@@ -79,11 +79,14 @@
PROJECT,
MODELESS;
- public Dialog.ModalityType toAwtModality () {
+ public Dialog.ModalityType toAwtModality() {
switch (this) {
- case IDE: return Dialog.ModalityType.APPLICATION_MODAL;
- case PROJECT: return Dialog.ModalityType.DOCUMENT_MODAL;
- case MODELESS: return Dialog.ModalityType.MODELESS;
+ case IDE:
+ return Dialog.ModalityType.APPLICATION_MODAL;
+ case PROJECT:
+ return Dialog.ModalityType.DOCUMENT_MODAL;
+ case MODELESS:
+ return Dialog.ModalityType.MODELESS;
}
return null;
}
@@ -180,6 +183,7 @@
public void setDoNotAskOption(@Nullable DoNotAskOption doNotAsk) {
myDoNotAsk = doNotAsk;
}
+
private ErrorText myErrorText;
private int myMaxErrorTextLength;
@@ -223,9 +227,9 @@
* Creates modal <code>DialogWrapper</code> that can be parent for other windows.
* The currently active window will be the dialog's parent.
*
- * @param project parent window for the dialog will be calculated based on focused window for the
- * specified <code>project</code>. This parameter can be <code>null</code>. In this case parent window
- * will be suggested based on current focused window.
+ * @param project parent window for the dialog will be calculated based on focused window for the
+ * specified <code>project</code>. This parameter can be <code>null</code>. In this case parent window
+ * will be suggested based on current focused window.
* @throws IllegalStateException if the dialog is invoked not on the event dispatch thread
* @see com.intellij.openapi.ui.DialogWrapper#DialogWrapper(com.intellij.openapi.project.Project, boolean)
*/
@@ -244,12 +248,13 @@
this((Project)null, canBeParent);
}
- /** Typically, we should set a parent explicitly. Use WindowManager#suggestParentWindow
- * method to find out the best parent for your dialog. Exceptions are cases
- * when we do not have a project to figure out which window
- * is more suitable as an owner for the dialog.
- *
- * Instead, use {@link DialogWrapper#DialogWrapper(com.intellij.openapi.project.Project, boolean, boolean)}
+ /**
+ * Typically, we should set a parent explicitly. Use WindowManager#suggestParentWindow
+ * method to find out the best parent for your dialog. Exceptions are cases
+ * when we do not have a project to figure out which window
+ * is more suitable as an owner for the dialog.
+ * <p/>
+ * Instead, use {@link DialogWrapper#DialogWrapper(com.intellij.openapi.project.Project, boolean, boolean)}
*/
@Deprecated
protected DialogWrapper(boolean canBeParent, boolean applicationModalIfPossible) {
@@ -259,7 +264,9 @@
protected DialogWrapper(Project project, boolean canBeParent, boolean applicationModalIfPossible) {
ensureEventDispatchThread();
if (ApplicationManager.getApplication() != null) {
- myPeer = createPeer(WindowManager.getInstance().suggestParentWindow(project), canBeParent, applicationModalIfPossible);
+ myPeer = createPeer(
+ project != null ? WindowManager.getInstance().suggestParentWindow(project) : WindowManager.getInstance().findVisibleFrame()
+ , canBeParent, applicationModalIfPossible);
}
else {
myPeer = createPeer(null, canBeParent, applicationModalIfPossible);
@@ -268,8 +275,8 @@
}
/**
- * @param parent parent component which is used to calculate heavy weight window ancestor.
- * <code>parent</code> cannot be <code>null</code> and must be showing.
+ * @param parent parent component which is used to calculate heavy weight window ancestor.
+ * <code>parent</code> cannot be <code>null</code> and must be showing.
* @param canBeParent can be parent
* @throws IllegalStateException if the dialog is invoked not on the event dispatch thread
*/
@@ -322,7 +329,7 @@
installErrorPainter();
myErrorPainter.setValidationInfo(info);
- if (! myErrorText.isTextSet(info.message)) {
+ if (!myErrorText.isTextSet(info.message)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
@@ -348,7 +355,7 @@
private void clearProblems() {
myErrorPainter.setValidationInfo(null);
- if (! myErrorText.isTextSet(null)) {
+ if (!myErrorText.isTextSet(null)) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
@@ -387,7 +394,7 @@
* Closes and disposes the dialog and sets the specified exit code.
*
* @param exitCode exit code
- * @param isOk is OK
+ * @param isOk is OK
* @throws IllegalStateException if the dialog is invoked not on the event dispatch thread
*/
public final void close(int exitCode, boolean isOk) {
@@ -403,7 +410,8 @@
if (isOk) {
processDoNotAskOnOk(exitCode);
- } else {
+ }
+ else {
processDoNotAskOnCancel();
}
@@ -471,11 +479,12 @@
buttonsPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 20)); // leave some space between button groups
}
lrButtonsPanel.add(buttonsPanel,
- new GridBagConstraints(gridX++, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0));
-
+ new GridBagConstraints(gridX++, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0,
+ 0));
}
lrButtonsPanel.add(Box.createHorizontalGlue(), // left strut
- new GridBagConstraints(gridX++, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insets, 0, 0));
+ new GridBagConstraints(gridX++, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insets, 0,
+ 0));
if (actions.length > 0) {
if (SystemInfo.isMac) {
// move ok action to the right
@@ -487,7 +496,7 @@
// move cancel action to the left
int cancelNdx = ArrayUtil.indexOf(actions, getCancelAction());
if (cancelNdx > 0) {
- actions = ArrayUtil.mergeArrays(new Action[] {getCancelAction()}, ArrayUtil.remove(actions, getCancelAction()));
+ actions = ArrayUtil.mergeArrays(new Action[]{getCancelAction()}, ArrayUtil.remove(actions, getCancelAction()));
}
/*if (!hasFocusedAction(actions)) {
@@ -500,11 +509,13 @@
JPanel buttonsPanel = createButtons(actions, buttons);
lrButtonsPanel.add(buttonsPanel,
- new GridBagConstraints(gridX++, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0, 0));
+ new GridBagConstraints(gridX++, 0, 1, 1, 0, 0, GridBagConstraints.CENTER, GridBagConstraints.NONE, insets, 0,
+ 0));
}
if (SwingConstants.CENTER == myButtonAlignment) {
lrButtonsPanel.add(Box.createHorizontalGlue(), // right strut
- new GridBagConstraints(gridX, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insets, 0, 0));
+ new GridBagConstraints(gridX, 0, 1, 1, 1, 0, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insets, 0,
+ 0));
}
myButtons = buttons.toArray(new JButton[buttons.size()]);
}
@@ -598,7 +609,6 @@
final Action[] options = ((OptionAction)action).getOptions();
actionList.addAll(Arrays.asList(options));
}
-
}
if (actionList.size() != actions.length) {
actions = actionList.toArray(actionList.toArray(new Action[actionList.size()]));
@@ -638,7 +648,6 @@
*
* @param action action for the button
* @return button with action specified
- *
* @see com.intellij.openapi.ui.DialogWrapper#DEFAULT_ACTION
*/
protected JButton createJButtonForAction(Action action) {
@@ -654,7 +663,7 @@
final Set<JBOptionButton.OptionInfo> infos = eachOptionsButton.getOptionInfos();
for (final JBOptionButton.OptionInfo eachInfo : infos) {
- if (eachInfo.getMnemonic() >=0) {
+ if (eachInfo.getMnemonic() >= 0) {
final CustomShortcutSet sc =
new CustomShortcutSet(KeyStroke.getKeyStroke("alt pressed " + Character.valueOf((char)eachInfo.getMnemonic())));
@@ -667,7 +676,6 @@
}.registerCustomShortcutSet(sc, getPeer().getRootPane());
}
}
-
}
else {
button = new JButton(action);
@@ -751,10 +759,13 @@
@Deprecated
protected DialogWrapperPeer createPeer(final Window owner, final boolean canBeParent, final boolean applicationModalIfPossible) {
- return DialogWrapperPeerFactory.getInstance().createPeer(this, owner, canBeParent, applicationModalIfPossible ? IdeModalityType.IDE : IdeModalityType.PROJECT);
+ return DialogWrapperPeerFactory.getInstance()
+ .createPeer(this, owner, canBeParent, applicationModalIfPossible ? IdeModalityType.IDE : IdeModalityType.PROJECT);
}
- protected DialogWrapperPeer createPeer(@Nullable final Project project, final boolean canBeParent, final IdeModalityType ideModalityType) {
+ protected DialogWrapperPeer createPeer(@Nullable final Project project,
+ final boolean canBeParent,
+ final IdeModalityType ideModalityType) {
return DialogWrapperPeerFactory.getInstance().createPeer(this, project, canBeParent, ideModalityType);
}
@@ -806,9 +817,10 @@
protected boolean setAutoAdjustable(boolean autoAdjustable) {
JRootPane rootPane = getRootPane();
if (rootPane == null) return false;
- rootPane.putClientProperty(NO_AUTORESIZE, autoAdjustable? null : Boolean.TRUE);
+ rootPane.putClientProperty(NO_AUTORESIZE, autoAdjustable ? null : Boolean.TRUE);
return true;
}
+
//true by default
public boolean isAutoAdjustable() {
JRootPane rootPane = getRootPane();
@@ -940,7 +952,7 @@
/**
* @return whether the native window cross button closes the window or not.
- * <code>true</code> means that cross performs hide or dispose of the dialog.
+ * <code>true</code> means that cross performs hide or dispose of the dialog.
*/
public boolean shouldCloseOnCross() {
return myCrossClosesWindow;
@@ -956,7 +968,6 @@
* These buttons are then placed into {@link #createSouthPanel() south panel} of dialog.
*
* @return dialog actions
- *
* @see #createSouthPanel
* @see #createJButtonForAction
*/
@@ -984,7 +995,7 @@
/**
* @return default implementation of "OK" action. This action just invokes
- * <code>doOKAction()</code> method.
+ * <code>doOKAction()</code> method.
* @see #doOKAction
*/
@NotNull
@@ -994,7 +1005,7 @@
/**
* @return default implementation of "Cancel" action. This action just invokes
- * <code>doCancelAction()</code> method.
+ * <code>doCancelAction()</code> method.
* @see #doCancelAction
*/
@NotNull
@@ -1004,7 +1015,7 @@
/**
* @return default implementation of "Help" action. This action just invokes
- * <code>doHelpAction()</code> method.
+ * <code>doHelpAction()</code> method.
* @see #doHelpAction
*/
@NotNull
@@ -1069,7 +1080,7 @@
/**
* @return component which should be focused when the dialog appears
- * on the screen.
+ * on the screen.
*/
@Nullable
public JComponent getPreferredFocusedComponent() {
@@ -1078,8 +1089,8 @@
/**
* @return horizontal stretch of the dialog. It means that the dialog's horizontal size is
- * the product of horizontal stretch by horizontal size of packed dialog. The default value
- * is <code>1.0f</code>
+ * the product of horizontal stretch by horizontal size of packed dialog. The default value
+ * is <code>1.0f</code>
*/
public final float getHorizontalStretch() {
return myHorizontalStretch;
@@ -1087,8 +1098,8 @@
/**
* @return vertical stretch of the dialog. It means that the dialog's vertical size is
- * the product of vertical stretch by vertical size of packed dialog. The default value
- * is <code>1.0f</code>
+ * the product of vertical stretch by vertical size of packed dialog. The default value
+ * is <code>1.0f</code>
*/
public final float getVerticalStretch() {
return myVerticalStretch;
@@ -1103,8 +1114,8 @@
}
/**
- * @see java.awt.Window#getOwner
* @return window owner
+ * @see java.awt.Window#getOwner
*/
public Window getOwner() {
return myPeer.getOwner();
@@ -1119,24 +1130,24 @@
}
/**
- * @see javax.swing.JDialog#getRootPane
* @return root pane
+ * @see javax.swing.JDialog#getRootPane
*/
public JRootPane getRootPane() {
return myPeer.getRootPane();
}
/**
- * @see java.awt.Window#getSize
* @return dialog size
+ * @see java.awt.Window#getSize
*/
public Dimension getSize() {
return myPeer.getSize();
}
/**
- * @see java.awt.Dialog#getTitle
* @return dialog title
+ * @see java.awt.Dialog#getTitle
*/
public String getTitle() {
return myPeer.getTitle();
@@ -1246,7 +1257,6 @@
if (myCurrentOptionsButtonIndex >= 0 && myCurrentOptionsButtonIndex < myOptionsButtons.size()) {
myOptionsButtons.get(myCurrentOptionsButtonIndex).showPopup(null, true);
}
-
}
void startTrackingValidation() {
@@ -1283,7 +1293,8 @@
if (getValidationThreadToUse() == Alarm.ThreadToUse.SWING_THREAD) {
myValidationAlarm.addRequest(validateRequest, myValidationDelay, ModalityState.current());
- } else {
+ }
+ else {
myValidationAlarm.addRequest(validateRequest, myValidationDelay);
}
}
@@ -1321,8 +1332,7 @@
* @param alignment alignment of the buttons. Acceptable values are
* <code>SwingConstants.CENTER</code> and <code>SwingConstants.RIGHT</code>.
* The <code>SwingConstants.RIGHT</code> is the default value.
- * @throws java.lang.IllegalArgumentException
- * if <code>alignment</code> isn't acceptable
+ * @throws java.lang.IllegalArgumentException if <code>alignment</code> isn't acceptable
*/
protected final void setButtonsAlignment(@MagicConstant(intValues = {SwingConstants.CENTER, SwingConstants.RIGHT}) int alignment) {
if (SwingConstants.CENTER != alignment && SwingConstants.RIGHT != alignment) {
@@ -1333,6 +1343,7 @@
/**
* Sets margin for command buttons ("OK", "Cancel", "Help").
+ *
* @param insets buttons margin
*/
public final void setButtonsMargin(@Nullable Insets insets) {
@@ -1426,23 +1437,23 @@
}
/**
- * @see java.awt.Component#isVisible
* @return <code>true</code> if and only if visible
+ * @see java.awt.Component#isVisible
*/
public boolean isVisible() {
return myPeer.isVisible();
}
/**
- * @see java.awt.Window#isShowing
* @return <code>true</code> if and only if showing
+ * @see java.awt.Window#isShowing
*/
public boolean isShowing() {
return myPeer.isShowing();
}
/**
- * @param width width
+ * @param width width
* @param height height
* @see javax.swing.JDialog#setSize
*/
@@ -1474,8 +1485,8 @@
}
/**
- * @see javax.swing.JDialog#getLocation
* @return dialog location
+ * @see javax.swing.JDialog#getLocation
*/
public Point getLocation() {
return myPeer.getLocation();
@@ -1492,7 +1503,7 @@
/**
* @param x x
* @param y y
- * @see javax.swing.JDialog#setLocation(int,int)
+ * @see javax.swing.JDialog#setLocation(int, int)
*/
public void setLocation(int x, int y) {
myPeer.setLocation(x, y);
@@ -1518,6 +1529,7 @@
/**
* You need this method ONLY for NON-MODAL dialogs. Otherwise, use {@link #show()} or {@link #showAndGet()}.
+ *
* @return result callback
*/
@NotNull
@@ -1547,7 +1559,7 @@
/**
* @return Location in absolute coordinates which is used when dialog has no dimension service key or no position was stored yet.
- * Can return null. In that case dialog will be centered relative to its owner.
+ * Can return null. In that case dialog will be centered relative to its owner.
*/
@Nullable
public Point getInitialLocation() {
@@ -1624,7 +1636,7 @@
}
private void registerForEveryKeyboardShortcut(ActionListener action, @NotNull ShortcutSet shortcuts) {
- for (Shortcut shortcut : shortcuts.getShortcuts()){
+ for (Shortcut shortcut : shortcuts.getShortcuts()) {
if (shortcut instanceof KeyboardShortcut) {
KeyboardShortcut ks = (KeyboardShortcut)shortcut;
KeyStroke first = ks.getFirstKeyStroke();
@@ -1833,7 +1845,7 @@
@Nullable
public static DialogWrapper findInstance(Component c) {
- while (c != null){
+ while (c != null) {
if (c instanceof DialogWrapperDialog) {
return ((DialogWrapperDialog)c).getDialogWrapper();
}
@@ -1854,6 +1866,7 @@
new Thread("DialogWrapper resizer") {
int time = 200;
int steps = 7;
+
@Override
public void run() {
int step = 0;
@@ -1861,11 +1874,13 @@
int h = (size.height - cur.height) / steps;
int w = (size.width - cur.width) / steps;
while (step++ < steps) {
- setSize(cur.width + w * step, cur.height + h*step);
+ setSize(cur.width + w * step, cur.height + h * step);
try {
//noinspection BusyWait
sleep(time / steps);
- } catch (InterruptedException ignore) {}
+ }
+ catch (InterruptedException ignore) {
+ }
}
setSize(size.width, size.height);
//repaint();
@@ -1909,7 +1924,8 @@
setBorder(null);
}
else {
- myLabel.setText(XmlStringUtil.wrapInHtml("<font color='#" + ColorUtil.toHex(JBColor.RED)+ "'><left>" + text + "</left></b></font>"));
+ myLabel
+ .setText(XmlStringUtil.wrapInHtml("<font color='#" + ColorUtil.toHex(JBColor.RED) + "'><left>" + text + "</left></b></font>"));
myLabel.setIcon(AllIcons.Actions.Lightning);
myLabel.setBorder(new EmptyBorder(4, 10, 0, 2));
setVisible(true);
@@ -2016,25 +2032,25 @@
@Override
public void executePaint(Component component, Graphics2D g) {
- if (myInfo != null && myInfo.component != null) {
+ if (myInfo != null && myInfo.component != null) {
final JComponent comp = myInfo.component;
final int w = comp.getWidth();
final int h = comp.getHeight();
Point p;
switch (getErrorPaintingType()) {
case DOT:
- p = SwingUtilities.convertPoint(comp, 2, h/2 , component);
+ p = SwingUtilities.convertPoint(comp, 2, h / 2, component);
AllIcons.Ide.ErrorPoint.paintIcon(component, g, p.x, p.y);
break;
case SIGN:
- p = SwingUtilities.convertPoint(comp, w, 0, component);
+ p = SwingUtilities.convertPoint(comp, w, 0, component);
AllIcons.General.Error.paintIcon(component, g, p.x - 8, p.y - 8);
break;
case LINE:
- p = SwingUtilities.convertPoint(comp, 0, h, component);
+ p = SwingUtilities.convertPoint(comp, 0, h, component);
final GraphicsConfig config = new GraphicsConfig(g);
- g.setColor(new Color(255, 0, 0 , 100));
- g.fillRoundRect(p.x, p.y-2, w, 4, 2, 2);
+ g.setColor(new Color(255, 0, 0, 100));
+ g.fillRoundRect(p.x, p.y - 2, w, 4, 2, 2);
config.restore();
break;
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/FixedSizeButton.java b/platform/platform-api/src/com/intellij/openapi/ui/FixedSizeButton.java
index f60713a..bdb9660 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/FixedSizeButton.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/FixedSizeButton.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -48,7 +48,7 @@
setMargin(new Insets(0, 0, 0, 0));
setDefaultCapable(false);
setFocusable(false);
- if (UIUtil.isUnderAquaLookAndFeel() && size == -1) {
+ if (((UIUtil.isUnderAquaLookAndFeel())&& size == -1) || UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula()) {
putClientProperty("JButton.buttonType", "square");
}
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/LoadingDecorator.java b/platform/platform-api/src/com/intellij/openapi/ui/LoadingDecorator.java
index 7509200..733a84b 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/LoadingDecorator.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/LoadingDecorator.java
@@ -62,8 +62,8 @@
Disposer.register(parent, myFadeOutAnimator);
- myPane.add(content, 0, JLayeredPane.DEFAULT_LAYER);
- myPane.add(myLoadingLayer, 1, JLayeredPane.DRAG_LAYER);
+ myPane.add(content, JLayeredPane.DEFAULT_LAYER, 0);
+ myPane.add(myLoadingLayer, JLayeredPane.DRAG_LAYER, 1);
Disposer.register(parent, myLoadingLayer.myProgress);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
index a286a80..677de18 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/MasterDetailsComponent.java
@@ -541,7 +541,7 @@
protected Comparator<MyNode> getNodeComparator() {
return new Comparator<MyNode>() {
public int compare(final MyNode o1, final MyNode o2) {
- return o1.getDisplayName().compareToIgnoreCase(o2.getDisplayName());
+ return StringUtil.naturalCompare(o1.getDisplayName(), o2.getDisplayName());
}
};
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java b/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java
index 56520d4..ab193af 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/MessageDialogBuilder.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,12 +95,14 @@
public int show() {
String yesText = ObjectUtils.chooseNotNull(myYesText, Messages.YES_BUTTON);
String noText = ObjectUtils.chooseNotNull(myNoText, Messages.NO_BUTTON);
- if (Messages.canShowMacSheetPanel() && !Messages.isApplicationInUnitTestOrHeadless()) {
- return MacMessages.getInstance().showYesNoDialog(myTitle, myMessage, yesText, noText, WindowManager.getInstance().suggestParentWindow(myProject), myDoNotAskOption);
- }
- else {
- return Messages.showDialog(myProject, myMessage, myTitle, new String[]{yesText, noText}, 0, myIcon, myDoNotAskOption) == 0 ? Messages.YES : Messages.NO;
- }
+ try {
+ if (Messages.canShowMacSheetPanel() && !Messages.isApplicationInUnitTestOrHeadless()) {
+ return MacMessages.getInstance().showYesNoDialog(myTitle, myMessage, yesText, noText, WindowManager.getInstance().suggestParentWindow(myProject), myDoNotAskOption);
+ }
+ } catch (Exception ignored) {}
+
+ return Messages.showDialog(myProject, myMessage, myTitle, new String[]{yesText, noText}, 0, myIcon, myDoNotAskOption) == 0 ? Messages.YES : Messages.NO;
+
}
}
@@ -126,13 +128,16 @@
String yesText = ObjectUtils.chooseNotNull(myYesText, Messages.YES_BUTTON);
String noText = ObjectUtils.chooseNotNull(myNoText, Messages.NO_BUTTON);
String cancelText = ObjectUtils.chooseNotNull(myCancelText, Messages.CANCEL_BUTTON);
- if (Messages.canShowMacSheetPanel() && !Messages.isApplicationInUnitTestOrHeadless()) {
- return MacMessages.getInstance().showYesNoCancelDialog(myTitle, myMessage, yesText, noText, cancelText, WindowManager.getInstance().suggestParentWindow(myProject), myDoNotAskOption);
+ try {
+ if (Messages.canShowMacSheetPanel() && !Messages.isApplicationInUnitTestOrHeadless()) {
+ return MacMessages.getInstance().showYesNoCancelDialog(myTitle, myMessage, yesText, noText, cancelText, WindowManager.getInstance().suggestParentWindow(myProject), myDoNotAskOption);
+ }
}
- else {
- int buttonNumber = Messages.showDialog(myProject, myMessage, myTitle, new String[]{yesText, noText, cancelText}, 0, myIcon, myDoNotAskOption);
- return buttonNumber == 0 ? Messages.YES : buttonNumber == 1 ? Messages.NO : Messages.CANCEL;
- }
+ catch (Exception ignored) {}
+
+ int buttonNumber = Messages.showDialog(myProject, myMessage, myTitle, new String[]{yesText, noText, cancelText}, 0, myIcon, myDoNotAskOption);
+ return buttonNumber == 0 ? Messages.YES : buttonNumber == 1 ? Messages.NO : Messages.CANCEL;
+
}
}
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/MessageType.java b/platform/platform-api/src/com/intellij/openapi/ui/MessageType.java
index c9f9a28..ac68f41 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/MessageType.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/MessageType.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.notification.NotificationType;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -34,19 +35,22 @@
private final Icon myDefaultIcon;
private final Color myPopupBackground;
- private MessageType(final Icon defaultIcon, Color popupBackground) {
+ private MessageType(@NotNull Icon defaultIcon, @NotNull Color popupBackground) {
myDefaultIcon = defaultIcon;
myPopupBackground = popupBackground;
}
+ @NotNull
public Icon getDefaultIcon() {
return myDefaultIcon;
}
+ @NotNull
public Color getPopupBackground() {
return myPopupBackground;
}
+ @NotNull
public NotificationType toNotificationType() {
return this == ERROR ? NotificationType.ERROR : this == WARNING ? NotificationType.WARNING : NotificationType.INFORMATION;
}
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 e95efbc..b4502de 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/Messages.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/Messages.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.
@@ -141,10 +141,14 @@
return ourTestImplementation.show(message);
}
- if (canShowMacSheetPanel()) {
- Window parentWindow = WindowManager.getInstance().suggestParentWindow(project);
- return MacMessages.getInstance()
- .showMessageDialog(title, message, options, false, parentWindow, defaultOptionIndex, defaultOptionIndex, doNotAskOption);
+ try {
+ if (canShowMacSheetPanel()) {
+ Window parentWindow = WindowManager.getInstance().suggestParentWindow(project);
+ return MacMessages.getInstance()
+ .showMessageDialog(title, message, options, false, parentWindow, defaultOptionIndex, defaultOptionIndex, doNotAskOption);
+ }
+ }
+ catch (Exception ignored) {
}
return showIdeaMessageDialog(project, message, title, options, defaultOptionIndex, icon, doNotAskOption);
@@ -169,7 +173,8 @@
return SystemInfo.isMac
&& !isApplicationInUnitTestOrHeadless()
&& Registry.is("ide.mac.message.dialogs.as.sheets")
- && !DialogWrapper.isMultipleModalDialogs();
+ && !SystemInfo.isJavaVersionAtLeast("1.8");
+ //&& !DialogWrapper.isMultipleModalDialogs();
}
public static boolean isMacSheetEmulation() {
@@ -191,9 +196,14 @@
return ourTestImplementation.show(message);
}
- if (canShowMacSheetPanel() && moreInfo == null) {
- return MacMessages.getInstance()
- .showMessageDialog(title, message, options, false, WindowManager.getInstance().suggestParentWindow(project), defaultOptionIndex, focusedOptionIndex, null);
+ try {
+ if (canShowMacSheetPanel() && moreInfo == null) {
+ return MacMessages.getInstance()
+ .showMessageDialog(title, message, options, false, WindowManager.getInstance().suggestParentWindow(project), defaultOptionIndex,
+ focusedOptionIndex, null);
+ }
+ }
+ catch (Exception ignored) {
}
MessageDialog dialog = new MoreInfoMessageDialog(project, message, title, moreInfo, options, defaultOptionIndex, focusedOptionIndex, icon);
@@ -214,9 +224,13 @@
return ourTestImplementation.show(message);
}
else {
- if (canShowMacSheetPanel()) {
- return MacMessages.getInstance()
- .showMessageDialog(title, message, options, false, SwingUtilities.getWindowAncestor(parent), defaultOptionIndex, defaultOptionIndex, null);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showMessageDialog(title, message, options, false, SwingUtilities.getWindowAncestor(parent),
+ defaultOptionIndex, defaultOptionIndex, null);
+ }
+ }
+ catch (Exception ignored) {
}
MessageDialog dialog = new MessageDialog(parent, message, title, options, defaultOptionIndex, defaultOptionIndex, icon, false);
@@ -242,8 +256,13 @@
if (isApplicationInUnitTestOrHeadless()) {
return ourTestImplementation.show(message);
}
- if (canShowMacSheetPanel()) {
- return MacMessages.getInstance().showMessageDialog(title, message, options, false, null, defaultOptionIndex, focusedOptionIndex, doNotAskOption);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showMessageDialog(title, message, options, false, null, defaultOptionIndex, focusedOptionIndex,
+ doNotAskOption);
+ }
+ }
+ catch (Exception ignored) {
}
//what's it? if (application.isUnitTestMode()) throw new RuntimeException(message);
@@ -278,18 +297,26 @@
* @see com.intellij.openapi.ui.DialogWrapper#DialogWrapper(Project,boolean)
*/
public static void showMessageDialog(@Nullable Project project, String message, @NotNull String title, @Nullable Icon icon) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(project, message, title, new String[]{OK_BUTTON}, 0, icon);
}
public static void showMessageDialog(Component parent, String message, @NotNull String title, @Nullable Icon icon) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(parent));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(parent));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(parent, message, title, new String[]{OK_BUTTON}, 0, icon);
@@ -319,9 +346,17 @@
*/
@YesNoResult
public static int showYesNoDialog(@Nullable Project project, String message, @NotNull String title, @NotNull String yesText, @NotNull String noText, @Nullable Icon icon) {
- int result = canShowMacSheetPanel()
- ? MacMessages.getInstance().showYesNoDialog(title, message, yesText, noText, WindowManager.getInstance().suggestParentWindow(project))
- : showDialog(project, message, title, new String[]{yesText, noText}, 0, icon) == 0 ? YES : NO;
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance()
+ .showYesNoDialog(title, message, yesText, noText, WindowManager.getInstance().suggestParentWindow(project));
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ int result = showDialog(project, message, title, new String[]{yesText, noText}, 0, icon) == 0 ? YES : NO;
+ //noinspection ConstantConditions
LOG.assertTrue(result == YES || result == NO, result);
return result;
}
@@ -331,9 +366,17 @@
*/
@YesNoResult
public static int showYesNoDialog(@Nullable Project project, String message, @NotNull String title, @Nullable Icon icon) {
- int result = canShowMacSheetPanel()
- ? MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, WindowManager.getInstance().suggestParentWindow(project))
- : showYesNoDialog(project, message, title, YES_BUTTON, NO_BUTTON, icon);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON,
+ WindowManager.getInstance().suggestParentWindow(project));
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ int result = showYesNoDialog(project, message, title, YES_BUTTON, NO_BUTTON, icon);
+
LOG.assertTrue(result == YES || result == NO, result);
return result;
}
@@ -344,9 +387,16 @@
*/
@YesNoResult
public static int showYesNoDialog(Component parent, String message, @NotNull String title, @Nullable Icon icon) {
- int result = canShowMacSheetPanel()
- ? MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, SwingUtilities.getWindowAncestor(parent))
- : showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon) == 0 ? YES : NO;
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, SwingUtilities.getWindowAncestor(parent));
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ int result = showDialog(parent, message, title, new String[]{YES_BUTTON, NO_BUTTON}, 0, icon) == 0 ? YES : NO;
+ //noinspection ConstantConditions
LOG.assertTrue(result == YES || result == NO, result);
return result;
}
@@ -361,9 +411,16 @@
@YesNoResult
public static int showYesNoDialog(String message, @NotNull String title, @NotNull String yesText, @NotNull String noText, @Nullable Icon icon,
@Nullable DialogWrapper.DoNotAskOption doNotAskOption) {
- int result = canShowMacSheetPanel()
- ? MacMessages.getInstance().showYesNoDialog(title, message, yesText, noText, null, doNotAskOption)
- : showDialog(message, title, new String[]{yesText, noText}, 0, icon, doNotAskOption) == 0 ? YES : NO;
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoDialog(title, message, yesText, noText, null, doNotAskOption);
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ int result = showDialog(message, title, new String[]{yesText, noText}, 0, icon, doNotAskOption) == 0 ? YES : NO;
+ //noinspection ConstantConditions
LOG.assertTrue(result == YES || result == NO, result);
return result;
}
@@ -389,9 +446,15 @@
*/
@YesNoResult
public static int showYesNoDialog(String message, @NotNull String title, @Nullable Icon icon) {
- int result = canShowMacSheetPanel()
- ? MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, null)
- : showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, icon);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoDialog(title, message, YES_BUTTON, NO_BUTTON, null);
+ }
+ }
+ catch (Exception ignored) {
+ }
+
+ int result = showYesNoDialog(message, title, YES_BUTTON, NO_BUTTON, icon);
LOG.assertTrue(result == YES || result == NO, result);
return result;
}
@@ -411,11 +474,15 @@
@NotNull String cancelText,
Icon icon,
DialogWrapper.DoNotAskOption doNotAskOption) {
- if (canShowMacSheetPanel()) {
- int result = MacMessages.getInstance()
- .showYesNoDialog(title, message, okText, cancelText, WindowManager.getInstance().suggestParentWindow(project),
- doNotAskOption);
- return result == YES ? OK : CANCEL;
+ try {
+ if (canShowMacSheetPanel()) {
+ int result = MacMessages.getInstance()
+ .showYesNoDialog(title, message, okText, cancelText, WindowManager.getInstance().suggestParentWindow(project),
+ doNotAskOption);
+ return result == YES ? OK : CANCEL;
+ }
+ }
+ catch (Exception ignored) {
}
return showDialog(project, message, title, new String[]{okText, cancelText}, 0, icon, doNotAskOption) == 0 ? OK : CANCEL;
@@ -426,13 +493,7 @@
*/
@OkCancelResult
public static int showOkCancelDialog(Project project, String message, @NotNull String title, @NotNull String okText, @NotNull String cancelText, Icon icon) {
- if (canShowMacSheetPanel()) {
- int result = MacMessages.getInstance()
- .showYesNoDialog(title, message, okText, cancelText, WindowManager.getInstance().suggestParentWindow(project));
- return result == YES ? OK : CANCEL;
- }
-
- return showDialog(project, message, title, new String[]{okText, cancelText}, 0, icon) == 0 ? OK : CANCEL;
+ return showOkCancelDialog(project, message, title, okText, cancelText, icon, null);
}
/**
@@ -448,9 +509,14 @@
*/
@OkCancelResult
public static int showOkCancelDialog(Component parent, String message, @NotNull String title, @NotNull String okText, @NotNull String cancelText, Icon icon) {
- if (canShowMacSheetPanel()) {
- int result = MacMessages.getInstance().showYesNoDialog(title, message, okText, cancelText, SwingUtilities.getWindowAncestor(parent));
- return result == YES ? OK : CANCEL;
+ try {
+ if (canShowMacSheetPanel()) {
+ int result =
+ MacMessages.getInstance().showYesNoDialog(title, message, okText, cancelText, SwingUtilities.getWindowAncestor(parent));
+ return result == YES ? OK : CANCEL;
+ }
+ }
+ catch (Exception ignored) {
}
return showDialog(parent, message, title, new String[]{okText, cancelText}, 0, icon) == 0 ? OK : CANCEL;
@@ -497,16 +563,20 @@
*/
@OkCancelResult
public static int showOkCancelDialog(String message, @NotNull String title, @NotNull String okText, @NotNull String cancelText, Icon icon, @Nullable DialogWrapper.DoNotAskOption doNotAskOption) {
- if (canShowMacSheetPanel()) {
- int result = MacMessages.getInstance().showYesNoDialog(title, message, okText, cancelText, null, doNotAskOption);
- return result == YES ? OK : CANCEL;
+ try {
+ if (canShowMacSheetPanel()) {
+ int result = MacMessages.getInstance().showYesNoDialog(title, message, okText, cancelText, null, doNotAskOption);
+ return result == YES ? OK : CANCEL;
+ }
+ }
+ catch (Exception ignored) {
}
return showDialog(message, title, new String[]{okText, cancelText}, 0, icon, doNotAskOption) == 0 ? OK : CANCEL;
}
public static int showCheckboxOkCancelDialog(String message, String title, String checkboxText, final boolean checked,
- final int defaultOptionIndex, final int focusedOptionIndex, Icon icon) {
+ final int defaultOptionIndex, final int focusedOptionIndex, Icon icon) {
return showCheckboxMessageDialog(message, title, new String[]{OK_BUTTON, CANCEL_BUTTON}, checkboxText, checked, defaultOptionIndex,
focusedOptionIndex, icon,
new PairFunction<Integer, JCheckBox, Integer>() {
@@ -518,8 +588,8 @@
}
public static int showCheckboxMessageDialog(String message, String title, @NotNull String[] options, String checkboxText, final boolean checked,
- final int defaultOptionIndex, final int focusedOptionIndex, Icon icon,
- @Nullable final PairFunction<Integer, JCheckBox, Integer> exitFunc) {
+ final int defaultOptionIndex, final int focusedOptionIndex, Icon icon,
+ @Nullable final PairFunction<Integer, JCheckBox, Integer> exitFunc) {
if (isApplicationInUnitTestOrHeadless()) {
return ourTestImplementation.show(message);
}
@@ -537,28 +607,40 @@
}
public static void showErrorDialog(@Nullable Project project, @Nls String message, @Nls @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon());
}
public static void showErrorDialog(Component component, String message, @Nls @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(component, message, title, new String[]{OK_BUTTON}, 0, getErrorIcon());
}
public static void showErrorDialog(Component component, String message) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, SwingUtilities.getWindowAncestor(
- component));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(CommonBundle.getErrorTitle(), message, OK_BUTTON, SwingUtilities.getWindowAncestor(
+ component));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(component, message, CommonBundle.getErrorTitle(), new String[]{OK_BUTTON}, 0, getErrorIcon());
@@ -571,27 +653,39 @@
* @see #showErrorDialog(Component, String, String)
*/
public static void showErrorDialog(String message, @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, null);
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, null);
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(message, title, new String[]{OK_BUTTON}, 0, getErrorIcon());
}
public static void showWarningDialog(@Nullable Project project, String message, @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(project, message, title, new String[]{OK_BUTTON}, 0, getWarningIcon());
}
public static void showWarningDialog(Component component, String message, @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(component, message, title, new String[]{OK_BUTTON}, 0, getWarningIcon());
@@ -604,9 +698,13 @@
* @see #showWarningDialog(Component, String, String)
*/
public static void showWarningDialog(String message, @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, null);
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showErrorDialog(title, message, OK_BUTTON, null);
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showDialog(message, title, new String[]{OK_BUTTON}, 0, getWarningIcon());
@@ -628,9 +726,13 @@
@NotNull String no,
@NotNull String cancel,
@Nullable Icon icon) {
- if (canShowMacSheetPanel()) {
- return MacMessages.getInstance().showYesNoCancelDialog(title, message, yes, no, cancel,
- WindowManager.getInstance().suggestParentWindow(project), null);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoCancelDialog(title, message, yes, no, cancel,
+ WindowManager.getInstance().suggestParentWindow(project), null);
+ }
+ }
+ catch (Exception ignored) {
}
int buttonNumber = showDialog(project, message, title, new String[]{yes, no, cancel}, 0, icon);
@@ -656,9 +758,13 @@
@NotNull String no,
@NotNull String cancel,
Icon icon) {
- if (canShowMacSheetPanel()) {
- return MacMessages.getInstance().showYesNoCancelDialog(title, message, yes, no, cancel,
- SwingUtilities.getWindowAncestor(parent), null);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoCancelDialog(title, message, yes, no, cancel,
+ SwingUtilities.getWindowAncestor(parent), null);
+ }
+ }
+ catch (Exception ignored) {
}
int buttonNumber = showDialog(parent, message, title, new String[]{yes, no, cancel}, 0, icon);
@@ -689,8 +795,12 @@
@NotNull String cancel,
Icon icon,
@Nullable DialogWrapper.DoNotAskOption doNotAskOption) {
- if (canShowMacSheetPanel()) {
- return MacMessages.getInstance().showYesNoCancelDialog(title, message, yes, no, cancel, null, doNotAskOption);
+ try {
+ if (canShowMacSheetPanel()) {
+ return MacMessages.getInstance().showYesNoCancelDialog(title, message, yes, no, cancel, null, doNotAskOption);
+ }
+ }
+ catch (Exception ignored) {
}
int buttonNumber = showDialog(message, title, new String[]{yes, no, cancel}, 0, icon, doNotAskOption);
@@ -888,13 +998,13 @@
@NotNull
public static Pair<String, Boolean> showInputDialogWithCheckBox(String message,
- String title,
- String checkboxText,
- boolean checked,
- boolean checkboxEnabled,
- @Nullable Icon icon,
- @NonNls String initialValue,
- @Nullable InputValidator validator) {
+ String title,
+ String checkboxText,
+ boolean checked,
+ boolean checkboxEnabled,
+ @Nullable Icon icon,
+ @NonNls String initialValue,
+ @Nullable InputValidator validator) {
if (isApplicationInUnitTestOrHeadless()) {
return new Pair<String, Boolean>(ourTestInputImplementation.show(message), checked);
}
@@ -972,9 +1082,13 @@
* Shows dialog with given message and title, information icon {@link #getInformationIcon()} and OK button
*/
public static void showInfoMessage(Component component, String message, @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, SwingUtilities.getWindowAncestor(component));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showMessageDialog(component, message, title, getInformationIcon());
@@ -984,9 +1098,13 @@
* Shows dialog with given message and title, information icon {@link #getInformationIcon()} and OK button
*/
public static void showInfoMessage(@Nullable Project project, @Nls String message, @Nls @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, WindowManager.getInstance().suggestParentWindow(project));
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showMessageDialog(project, message, title, getInformationIcon());
@@ -1001,9 +1119,13 @@
* @see #showInputDialog(Component, String, String, Icon, String, InputValidator)
*/
public static void showInfoMessage(String message, @NotNull String title) {
- if (canShowMacSheetPanel()) {
- MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, null);
- return;
+ try {
+ if (canShowMacSheetPanel()) {
+ MacMessages.getInstance().showOkMessageDialog(title, message, OK_BUTTON, null);
+ return;
+ }
+ }
+ catch (Exception ignored) {
}
showMessageDialog(message, title, getInformationIcon());
@@ -1054,7 +1176,7 @@
showTextAreaDialog(textField, title, dimensionServiceKey, ParametersListUtil.DEFAULT_LINE_PARSER, ParametersListUtil.DEFAULT_LINE_JOINER);
}
- private static class MoreInfoMessageDialog extends MessageDialog {
+ private static class MoreInfoMessageDialog extends MessageDialog {
@Nullable private final String myInfoText;
public MoreInfoMessageDialog(Project project,
@@ -1218,22 +1340,12 @@
actions[i].putValue(FOCUSED_ACTION, Boolean.TRUE);
}
- assignMnemonic(option, actions[i]);
+ UIUtil.assignMnemonic(option, actions[i]);
}
return actions;
}
- private static void assignMnemonic(@NotNull String option, Action action) {
- int mnemoPos = option.indexOf("&");
- if (mnemoPos >= 0 && mnemoPos < option.length() - 2) {
- String mnemoChar = option.substring(mnemoPos + 1, mnemoPos + 2).trim();
- if (mnemoChar.length() == 1) {
- action.putValue(Action.MNEMONIC_KEY, Integer.valueOf(mnemoChar.charAt(0)));
- }
- }
- }
-
@Override
public void doCancelAction() {
close(-1);
@@ -1446,13 +1558,13 @@
private final boolean myChecked;
private final PairFunction<Integer, JCheckBox, Integer> myExitFunc;
- public TwoStepConfirmationDialog(String message, String title, @NotNull String[] options, String checkboxText, boolean checked, final int defaultOptionInxed,
+ public TwoStepConfirmationDialog(String message, String title, @NotNull String[] options, String checkboxText, boolean checked, final int defaultOptionIndexed,
final int focusedOptionIndex, Icon icon, @Nullable final PairFunction<Integer, JCheckBox, Integer> exitFunc) {
myCheckboxText = checkboxText;
myChecked = checked;
myExitFunc = exitFunc;
- _init(title, message, options, defaultOptionInxed, focusedOptionIndex, icon, null);
+ _init(title, message, options, defaultOptionIndexed, focusedOptionIndex, icon, null);
}
@Override
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java b/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java
index 510ec59..26a3b15 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/TextComponentAccessor.java
@@ -17,6 +17,7 @@
import com.intellij.ui.TextFieldWithHistory;
import com.intellij.ui.TextFieldWithStoredHistory;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -33,11 +34,13 @@
* The accessor that gets and changes whole text
*/
TextComponentAccessor<JTextField> TEXT_FIELD_WHOLE_TEXT = new TextComponentAccessor<JTextField>() {
+ @Override
public String getText(JTextField textField) {
return textField.getText();
}
- public void setText(JTextField textField, String text) {
+ @Override
+ public void setText(JTextField textField, @NotNull String text) {
textField.setText(text);
}
};
@@ -46,12 +49,14 @@
* The accessor that replaces selection or whole text if there is no selection
*/
TextComponentAccessor<JTextField> TEXT_FIELD_SELECTED_TEXT = new TextComponentAccessor<JTextField>() {
+ @Override
public String getText(JTextField textField) {
String selectedText = textField.getSelectedText();
return selectedText != null ? selectedText : textField.getText();
}
- public void setText(JTextField textField, String text) {
+ @Override
+ public void setText(JTextField textField, @NotNull String text) {
if (textField.getSelectedText() != null) textField.replaceSelection(text);
else textField.setText(text);
}
@@ -61,12 +66,14 @@
* The accessor that gets and changes whole text
*/
TextComponentAccessor<JComboBox> STRING_COMBOBOX_WHOLE_TEXT = new TextComponentAccessor<JComboBox>() {
+ @Override
public String getText(JComboBox comboBox) {
Object item = comboBox.getEditor().getItem();
return item.toString();
}
- public void setText(JComboBox comboBox, String text) {
+ @Override
+ public void setText(JComboBox comboBox, @NotNull String text) {
comboBox.getEditor().setItem(text);
}
};
@@ -74,11 +81,13 @@
* The accessor that gets and changes whole text
*/
TextComponentAccessor<TextFieldWithHistory> TEXT_FIELD_WITH_HISTORY_WHOLE_TEXT = new TextComponentAccessor<TextFieldWithHistory>() {
+ @Override
public String getText(TextFieldWithHistory textField) {
return textField.getText();
}
- public void setText(TextFieldWithHistory textField, String text) {
+ @Override
+ public void setText(TextFieldWithHistory textField, @NotNull String text) {
textField.setText(text);
}
};
@@ -87,11 +96,13 @@
* The accessor that gets and changes whole text
*/
TextComponentAccessor<TextFieldWithStoredHistory> TEXT_FIELD_WITH_STORED_HISTORY_WHOLE_TEXT = new TextComponentAccessor<TextFieldWithStoredHistory>() {
+ @Override
public String getText(TextFieldWithStoredHistory textField) {
return textField.getText();
}
- public void setText(TextFieldWithStoredHistory textField, String text) {
+ @Override
+ public void setText(TextFieldWithStoredHistory textField, @NotNull String text) {
textField.setText(text);
}
};
@@ -108,5 +119,5 @@
* @param component the component
* @param text the text to set
*/
- void setText(T component, String text);
+ void setText(T component, @NotNull String text);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java b/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java
index a5b9bf5..86480d3 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/ThreeComponentsSplitter.java
@@ -24,6 +24,7 @@
import com.intellij.ui.UIBundle;
import com.intellij.util.ui.update.Activatable;
import com.intellij.util.ui.update.UiNotifyConnector;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -534,7 +535,7 @@
.message("splitter.right.tooltip.text"));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myInnerComponent != null) {
final int income = myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth();
if (myIsFirst) {
@@ -560,7 +561,7 @@
splitCenterlabel.setToolTipText(UIBundle.message("splitter.center.tooltip.text"));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
center();
return true;
}
@@ -576,7 +577,7 @@
.message("splitter.left.tooltip.text"));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myInnerComponent != null) {
final int income = myVerticalSplit ? myInnerComponent.getHeight() : myInnerComponent.getWidth();
if (myIsFirst) {
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/dialogs/AgreementDialog.java b/platform/platform-api/src/com/intellij/openapi/ui/dialogs/AgreementDialog.java
new file mode 100644
index 0000000..9addc1c
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/openapi/ui/dialogs/AgreementDialog.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.dialogs;
+
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.ui.ScrollPaneFactory;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+public class AgreementDialog extends DialogWrapper {
+ private final Font myFont = new Font("SansSerif", Font.PLAIN, 12);
+ private final ResourceBundle myBundle = ResourceBundle.getBundle("messages.LicenseCommonBundle");
+
+ private final String myText;
+ private JCheckBox myAcceptCheckBox;
+ private boolean myOK = false;
+
+ public AgreementDialog(String text, String programName) {
+ super(null, false, true);
+ getPeer().setAppIcons();
+
+ myText = text;
+ String title;
+ if (programName != null) {
+ title = MessageFormat.format(myBundle.getString("license.agreement.title.for"), programName);
+ }
+ else {
+ title = myBundle.getString("license.agreement.title");
+ }
+
+ setTitle(title);
+
+ init();
+
+ getOKAction().setEnabled(false);
+ }
+
+ protected void doOKAction() {
+ myOK = true;
+ super.doOKAction();
+ }
+
+ protected JComponent createNorthPanel() {
+ JPanel panel = new JPanel(new BorderLayout());
+ String text = myBundle.getString("license.agreement.prompt");
+ JLabel licensePrompt = new JLabel(text);
+ licensePrompt.setFocusable(false);
+ licensePrompt.setFont(myFont);
+ licensePrompt.setBorder(BorderFactory.createEmptyBorder(10, 20, 10, 5));
+ panel.add(licensePrompt, BorderLayout.WEST);
+ panel.add(new JPanel(), BorderLayout.CENTER);
+ return panel;
+ }
+
+ public boolean isAgreed() {
+ return myOK && myAcceptCheckBox.isSelected();
+ }
+
+ protected JComponent createCenterPanel() {
+ JPanel optionsPanel = new JPanel(new BorderLayout());
+ JTextArea licenseTextArea = new JTextArea(myText, 20, 50);
+ licenseTextArea.getCaret().setDot(0);
+ licenseTextArea.setFont(myFont);
+ licenseTextArea.setLineWrap(true);
+ licenseTextArea.setWrapStyleWord(true);
+ licenseTextArea.setEditable(false);
+ JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(licenseTextArea);
+
+ optionsPanel.add(scrollPane, BorderLayout.CENTER);
+ JPanel agreePanel = new JPanel(new GridLayout(1, 1));
+ agreePanel.setBorder(BorderFactory.createEmptyBorder(10, 5, 5, 5));
+ myAcceptCheckBox = new JCheckBox(myBundle.getString("license.agreement.accept.checkbox"));
+ myAcceptCheckBox.setMnemonic(myAcceptCheckBox.getText().charAt(0));
+ myAcceptCheckBox.setFont(myFont);
+
+ agreePanel.add(myAcceptCheckBox);
+ optionsPanel.add(agreePanel, BorderLayout.SOUTH);
+
+ myAcceptCheckBox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent event) {
+ getOKAction().setEnabled(myAcceptCheckBox.isSelected());
+ }
+ });
+ return optionsPanel;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java
index 4b2752b..c99438f 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/Balloon.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.
@@ -18,6 +18,7 @@
import com.intellij.openapi.Disposable;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.ui.PositionTracker;
+import org.jetbrains.annotations.NotNull;
import javax.swing.JComponent;
import javax.swing.JLayeredPane;
@@ -42,7 +43,7 @@
void setBounds(Rectangle bounds);
- void addListener(JBPopupListener listener);
+ void addListener(@NotNull JBPopupListener listener);
void hide();
void hide(boolean ok);
diff --git a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java
index e777617..ae9dee1 100644
--- a/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java
+++ b/platform/platform-api/src/com/intellij/openapi/ui/popup/ListItemDescriptor.java
@@ -22,18 +22,18 @@
/**
* @author kir
*/
-public interface ListItemDescriptor {
+public interface ListItemDescriptor<T> {
@Nullable
- String getTextFor(Object value);
+ String getTextFor(T value);
@Nullable
- String getTooltipFor(Object value);
+ String getTooltipFor(T value);
@Nullable
- Icon getIconFor(Object value);
+ Icon getIconFor(T value);
- boolean hasSeparatorAboveOf(Object value);
+ boolean hasSeparatorAboveOf(T value);
@Nullable
- String getCaptionAboveOf(Object value);
+ String getCaptionAboveOf(T value);
}
diff --git a/platform/platform-api/src/com/intellij/openapi/vcs/FileStatusManager.java b/platform/platform-api/src/com/intellij/openapi/vcs/FileStatusManager.java
index ebf5910..f2fad70 100644
--- a/platform/platform-api/src/com/intellij/openapi/vcs/FileStatusManager.java
+++ b/platform/platform-api/src/com/intellij/openapi/vcs/FileStatusManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
import java.awt.*;
@@ -29,7 +30,7 @@
return project.getComponent(FileStatusManager.class);
}
- public abstract FileStatus getStatus(VirtualFile virtualFile);
+ public abstract FileStatus getStatus(@NotNull VirtualFile virtualFile);
public abstract void fileStatusesChanged();
public abstract void fileStatusChanged(VirtualFile file);
diff --git a/platform/platform-api/src/com/intellij/openapi/vcs/VcsBundle.java b/platform/platform-api/src/com/intellij/openapi/vcs/VcsBundle.java
index 54dac0e..20cf6cb 100644
--- a/platform/platform-api/src/com/intellij/openapi/vcs/VcsBundle.java
+++ b/platform/platform-api/src/com/intellij/openapi/vcs/VcsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,24 +28,23 @@
* @author lesya
*/
public class VcsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "messages.VcsBundle";
private VcsBundle() {
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
public static String getString(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) final String key) {
return getBundle().getString(key);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java
index a5085ad..1abfc73 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.vfs;
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
+import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,8 +25,8 @@
public abstract class JarFileSystem extends NewVirtualFileSystem implements JarCopyingFileSystem, LocalFileProvider {
@NonNls public static final String PROTOCOL = StandardFileSystems.JAR_PROTOCOL;
- @NonNls public static final String PROTOCOL_PREFIX = "jar://";
- @NonNls public static final String JAR_SEPARATOR = StandardFileSystems.JAR_SEPARATOR;
+ @NonNls public static final String PROTOCOL_PREFIX = StandardFileSystems.JAR_PROTOCOL_PREFIX;
+ @NonNls public static final String JAR_SEPARATOR = URLUtil.JAR_SEPARATOR;
public static JarFileSystem getInstance(){
return (JarFileSystem)VirtualFileManager.getInstance().getFileSystem(PROTOCOL);
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java
index 58b5469..c524f2c 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/LocalFileSystem.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,7 +17,6 @@
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
-import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
import com.intellij.util.Processor;
import com.intellij.util.io.fs.IFile;
@@ -101,12 +100,11 @@
public abstract void refreshFiles(@NotNull Iterable<VirtualFile> files, boolean async, boolean recursive, @Nullable Runnable onFinish);
- @NotNull
+ /** @deprecated fake root considered harmful (to remove in IDEA 14) */
public final VirtualFile getRoot() {
- final String rootPath = SystemInfo.isWindows ? "" : "/";
- final NewVirtualFile root = ManagingFS.getInstance().findRoot(rootPath, this);
- assert root != null : SystemInfo.OS_NAME;
- return root;
+ VirtualFile[] roots = ManagingFS.getInstance().getLocalRoots();
+ assert roots.length > 0 : SystemInfo.OS_NAME;
+ return roots[0];
}
public interface WatchRequest {
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
index d9f4355..ce1b7c6 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/VfsUtil.java
@@ -177,35 +177,6 @@
}
/**
- * Gets the common ancestor for passed files, or null if the files do not have common ancestors.
- *
- * @param file1 fist file
- * @param file2 second file
- * @return common ancestor for the passed files. Returns <code>null</code> if
- * the files do not have common ancestor
- */
- @Nullable
- public static VirtualFile getCommonAncestor(@NotNull VirtualFile file1, @NotNull VirtualFile file2) {
- if (!file1.getFileSystem().equals(file2.getFileSystem())) {
- return null;
- }
-
- VirtualFile[] path1 = getPathComponents(file1);
- VirtualFile[] path2 = getPathComponents(file2);
-
- int lastEqualIdx = -1;
- for (int i = 0; i < path1.length && i < path2.length; i++) {
- if (path1[i].equals(path2[i])) {
- lastEqualIdx = i;
- }
- else {
- break;
- }
- }
- return lastEqualIdx == -1 ? null : path1[lastEqualIdx];
- }
-
- /**
* Gets the common ancestor for passed files, or {@code null} if the files do not have common ancestors.
*/
@Nullable
@@ -223,27 +194,6 @@
return ancestor;
}
- /**
- * Gets an array of files representing paths from root to the passed file.
- *
- * @param file the file
- * @return virtual files which represents paths from root to the passed file
- */
- @NotNull
- private static VirtualFile[] getPathComponents(@NotNull VirtualFile file) {
- ArrayList<VirtualFile> componentsList = new ArrayList<VirtualFile>();
- while (file != null) {
- componentsList.add(file);
- file = file.getParent();
- }
- int size = componentsList.size();
- VirtualFile[] components = new VirtualFile[size];
- for (int i = 0; i < size; i++) {
- components[i] = componentsList.get(size - i - 1);
- }
- return components;
- }
-
@Nullable
public static VirtualFile findRelativeFile(@Nullable VirtualFile base, String ... path) {
VirtualFile file = base;
diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java
index 5bde8f3..e5c056c 100644
--- a/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java
+++ b/platform/platform-api/src/com/intellij/openapi/vfs/newvfs/NewVirtualFileSystem.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
index 54a4365..3d8c4ff 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/FocusCommand.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,8 @@
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.util.ActiveRunnable;
import com.intellij.openapi.util.Expirable;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -149,8 +151,26 @@
@NotNull
public final ActionCallback run() {
if (myToFocus != null) {
- if (!myToFocus.requestFocusInWindow()) {
- myToFocus.requestFocus();
+ if (Registry.is("actionSystem.doNotStealFocus")) {
+ Window topWindow = SwingUtilities.windowForComponent(myToFocus);
+ UIUtil.setAutoRequestFocus(topWindow, topWindow.isActive());
+ while (topWindow.getOwner() != null) {
+ topWindow = SwingUtilities.windowForComponent(topWindow);
+ UIUtil.setAutoRequestFocus(topWindow, topWindow.isActive());
+ }
+
+ if (topWindow.isActive()) {
+ if (!myToFocus.requestFocusInWindow()) {
+ myToFocus.requestFocus();
+ }
+ } else {
+ myToFocus.requestFocusInWindow();
+ }
+
+ } else {
+ if (!myToFocus.requestFocusInWindow()) {
+ myToFocus.requestFocus();
+ }
}
}
clear();
diff --git a/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java b/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java
index c5cee6c..836c15e 100644
--- a/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.java
+++ b/platform/platform-api/src/com/intellij/openapi/wm/WindowInfo.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,9 +16,12 @@
package com.intellij.openapi.wm;
+import org.jetbrains.annotations.NotNull;
+
import java.awt.*;
public interface WindowInfo {
+ @NotNull
ToolWindowAnchor getAnchor();
Rectangle getFloatingBounds();
diff --git a/platform/platform-api/src/com/intellij/ui/AbstractCollectionComboBoxModel.java b/platform/platform-api/src/com/intellij/ui/AbstractCollectionComboBoxModel.java
index 8352f43..c5413cc 100644
--- a/platform/platform-api/src/com/intellij/ui/AbstractCollectionComboBoxModel.java
+++ b/platform/platform-api/src/com/intellij/ui/AbstractCollectionComboBoxModel.java
@@ -24,27 +24,37 @@
/**
* @author traff
*/
-public abstract class AbstractCollectionComboBoxModel extends AbstractListModel implements ComboBoxModel {
- private Object mySelection;
+public abstract class AbstractCollectionComboBoxModel<T> extends AbstractListModel implements ComboBoxModel {
+ private T mySelection;
- public AbstractCollectionComboBoxModel(Object selection) {
+ public AbstractCollectionComboBoxModel(@Nullable T selection) {
mySelection = selection;
}
+ @Override
public int getSize() {
return getItems().size();
}
- public Object getElementAt(final int index) {
+ @Override
+ public T getElementAt(final int index) {
return getItems().get(index);
}
- public void setSelectedItem(@Nullable final Object anItem) {
- mySelection = anItem;
+ @Override
+ public void setSelectedItem(@Nullable Object anItem) {
+ //noinspection unchecked
+ mySelection = (T)anItem;
+ }
+
+ @Override
+ @Nullable
+ public Object getSelectedItem() {
+ return mySelection;
}
@Nullable
- public Object getSelectedItem() {
+ public T getSelected() {
return mySelection;
}
@@ -52,10 +62,10 @@
super.fireContentsChanged(this, -1, -1);
}
- public boolean contains(Object item) {
+ public boolean contains(T item) {
return getItems().contains(item);
}
@NotNull
- abstract protected List getItems();
+ abstract protected List<T> getItems();
}
diff --git a/platform/platform-api/src/com/intellij/ui/AnActionButton.java b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
index 0e84519..01e8e4a 100644
--- a/platform/platform-api/src/com/intellij/ui/AnActionButton.java
+++ b/platform/platform-api/src/com/intellij/ui/AnActionButton.java
@@ -18,13 +18,13 @@
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
-import java.util.HashSet;
import java.util.Set;
/**
@@ -104,7 +104,7 @@
public final void addCustomUpdater(@NotNull AnActionButtonUpdater updater) {
if (myUpdaters == null) {
- myUpdaters = new HashSet<AnActionButtonUpdater>();
+ myUpdaters = new SmartHashSet<AnActionButtonUpdater>();
}
myUpdaters.add(updater);
}
diff --git a/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java b/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java
index 7dbf1d9..be2f245 100644
--- a/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java
+++ b/platform/platform-api/src/com/intellij/ui/AutoScrollToSourceHandler.java
@@ -34,6 +34,7 @@
import com.intellij.pom.Navigatable;
import com.intellij.util.Alarm;
import com.intellij.util.OpenSourceUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
@@ -55,7 +56,7 @@
myAutoScrollAlarm = new Alarm();
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (clickCount > 1) return false;
TreePath location = tree.getPathForLocation(e.getPoint().x, e.getPoint().y);
@@ -86,7 +87,7 @@
myAutoScrollAlarm = new Alarm();
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (clickCount >= 2) return false;
Component location = table.getComponentAt(e.getPoint());
@@ -117,7 +118,7 @@
myAutoScrollAlarm = new Alarm();
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (clickCount >= 2) return false;
final Object source = e.getSource();
final int index = jList.locationToIndex(SwingUtilities.convertPoint(source instanceof Component ? (Component)source : null, e.getPoint(), jList));
diff --git a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java
index 04f0ebd..810c4c9 100644
--- a/platform/platform-api/src/com/intellij/ui/CheckBoxList.java
+++ b/platform/platform-api/src/com/intellij/ui/CheckBoxList.java
@@ -4,6 +4,7 @@
import com.intellij.util.Function;
import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -23,7 +24,7 @@
public class CheckBoxList<T> extends JBList {
private static final int DEFAULT_CHECK_BOX_WIDTH = 20;
private CheckBoxListListener checkBoxListListener;
- private BidirectionalMap<Object, JCheckBox> myItemMap = new BidirectionalMap<Object, JCheckBox>();
+ private final BidirectionalMap<T, JCheckBox> myItemMap = new BidirectionalMap<T, JCheckBox>();
public CheckBoxList(final CheckBoxListListener checkBoxListListener) {
this(new DefaultListModel(), checkBoxListListener);
@@ -39,6 +40,7 @@
public CheckBoxList(final DefaultListModel dataModel) {
super();
+ //noinspection unchecked
setModel(dataModel);
setCellRenderer(new CellRenderer());
setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
@@ -47,8 +49,7 @@
@Override
public void keyTyped(KeyEvent e) {
if (e.getKeyChar() == ' ') {
- int[] indices = CheckBoxList.this.getSelectedIndices();
- for (int index : indices) {
+ for (int index : getSelectedIndices()) {
if (index >= 0) {
JCheckBox checkbox = (JCheckBox)getModel().getElementAt(index);
setSelected(checkbox, index);
@@ -59,7 +60,7 @@
});
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (isEnabled()) {
int index = locationToIndex(e.getPoint());
@@ -88,7 +89,8 @@
public void setStringItems(final Map<String, Boolean> items) {
clear();
for (Map.Entry<String, Boolean> entry : items.entrySet()) {
- addItem(entry.getKey(), entry.getKey(), entry.getValue());
+ //noinspection unchecked
+ addItem((T)entry.getKey(), entry.getKey(), entry.getValue());
}
}
@@ -100,19 +102,26 @@
}
}
- private void addItem(Object item, String text, boolean selected) {
+ public void addItem(T item, String text, boolean selected) {
JCheckBox checkBox = new JCheckBox(text, selected);
myItemMap.put(item, checkBox);
+ //noinspection unchecked
((DefaultListModel) getModel()).addElement(checkBox);
}
- public Object getItemAt(int index) {
+ public void updateItem(@NotNull T oldItem, @NotNull T newItem) {
+ JCheckBox checkBox = myItemMap.remove(oldItem);
+ myItemMap.put(newItem, checkBox);
+ }
+
+ @Nullable
+ public T getItemAt(int index) {
JCheckBox checkBox = (JCheckBox)getModel().getElementAt(index);
- List<Object> value = myItemMap.getKeysByValue(checkBox);
+ List<T> value = myItemMap.getKeysByValue(checkBox);
return value == null || value.isEmpty() ? null : value.get(0);
}
- private void clear() {
+ public void clear() {
((DefaultListModel) getModel()).clear();
myItemMap.clear();
}
@@ -121,12 +130,12 @@
return ((JCheckBox)getModel().getElementAt(index)).isSelected();
}
- public boolean isItemSelected(Object item) {
+ public boolean isItemSelected(T item) {
JCheckBox checkBox = myItemMap.get(item);
return checkBox != null && checkBox.isSelected();
}
- public void setItemSelected(Object item, boolean selected) {
+ public void setItemSelected(T item, boolean selected) {
JCheckBox checkBox = myItemMap.get(item);
if (checkBox != null) {
checkBox.setSelected(selected);
@@ -141,6 +150,7 @@
// fire change notification in case if we've already initialized model
final ListModel model = getModel();
if (model instanceof DefaultListModel) {
+ //noinspection unchecked
((DefaultListModel)model).setElementAt(getModel().getElementAt(index), index);
}
@@ -166,6 +176,7 @@
myBorder = new EmptyBorder(borderInsets);
}
+ @Override
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JCheckBox checkbox = (JCheckBox)value;
if (!UIUtil.isUnderNimbusLookAndFeel()) {
diff --git a/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java b/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java
index 109acad..baa0d26 100644
--- a/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java
+++ b/platform/platform-api/src/com/intellij/ui/CheckBoxWithColorChooser.java
@@ -16,6 +16,7 @@
package com.intellij.ui;
import com.intellij.openapi.util.SystemInfo;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -76,7 +77,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myCheckbox.isSelected()) {
final Color color = ColorChooser.chooseColor(myCheckbox, "Chose color", CheckBoxWithColorChooser.this.myColor);
if (color != null) {
diff --git a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
index c5dcc9e..d9755f3 100644
--- a/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
+++ b/platform/platform-api/src/com/intellij/ui/CheckboxTreeBase.java
@@ -18,6 +18,7 @@
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -87,7 +88,7 @@
setCellRenderer(cellRenderer);
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
int row = getRowForLocation(e.getX(), e.getY());
if (row < 0) return false;
final Object o = getPathForRow(row).getLastPathComponent();
diff --git a/platform/platform-api/src/com/intellij/ui/CollectionListModel.java b/platform/platform-api/src/com/intellij/ui/CollectionListModel.java
index 6ce291a..c301aa3 100644
--- a/platform/platform-api/src/com/intellij/ui/CollectionListModel.java
+++ b/platform/platform-api/src/com/intellij/ui/CollectionListModel.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,6 +16,7 @@
package com.intellij.ui;
+import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.EditableModel;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -29,12 +30,16 @@
public class CollectionListModel<T> extends AbstractListModel implements EditableModel {
private final List<T> myItems;
- public CollectionListModel(@NotNull final List<? extends T> items) {
+ public CollectionListModel(@NotNull final Collection<? extends T> items) {
myItems = new ArrayList<T>(items);
}
+ public CollectionListModel(@NotNull final List<? extends T> items) {
+ this((Collection<? extends T>)items);
+ }
+
public CollectionListModel(final T... items) {
- myItems = new ArrayList<T>(Arrays.asList(items));
+ myItems = ContainerUtilRt.newArrayList(items);
}
@Override
diff --git a/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java b/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java
index 372c4b5..b7ec855 100644
--- a/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java
+++ b/platform/platform-api/src/com/intellij/ui/ColoredListCellRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -88,6 +88,7 @@
}
}
+ @NotNull
public Dimension getPreferredSize() {
// There is a bug in BasicComboPopup. It does not add renderer into CellRendererPane,
// so font can be null here.
diff --git a/platform/platform-api/src/com/intellij/ui/ColoredTextContainer.java b/platform/platform-api/src/com/intellij/ui/ColoredTextContainer.java
index dfc59ca..a96b53f 100644
--- a/platform/platform-api/src/com/intellij/ui/ColoredTextContainer.java
+++ b/platform/platform-api/src/com/intellij/ui/ColoredTextContainer.java
@@ -6,8 +6,11 @@
import javax.swing.*;
public interface ColoredTextContainer {
- void append(@NotNull final String fragment, @NotNull final SimpleTextAttributes attributes);
- void setIcon(@Nullable final Icon icon);
+ void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes);
- void setToolTipText(String text);
+ void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes, Object tag);
+
+ void setIcon(@Nullable Icon icon);
+
+ void setToolTipText(@Nullable String text);
}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java b/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java
index 168f4ee..132d9b6 100644
--- a/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java
+++ b/platform/platform-api/src/com/intellij/ui/ColoredTreeCellRenderer.java
@@ -45,15 +45,13 @@
private boolean myOpaque = true;
@Override
- public final Component getTreeCellRendererComponent(
- JTree tree,
- Object value,
- boolean selected,
- boolean expanded,
- boolean leaf,
- int row,
- boolean hasFocus
- ){
+ public final Component getTreeCellRendererComponent(JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus){
myTree = tree;
clear();
@@ -72,20 +70,18 @@
setBackground(hasFocus ? UIUtil.getTreeSelectionBackground() : UIUtil.getTreeUnfocusedSelectionBackground());
}
}
- else {
- if (selected) {
- setPaintFocusBorder(true);
- if (isFocused()) {
- setBackground(UIUtil.getTreeSelectionBackground());
- }
- else {
- setBackground(null);
- }
+ else if (selected) {
+ setPaintFocusBorder(true);
+ if (isFocused()) {
+ setBackground(UIUtil.getTreeSelectionBackground());
}
else {
setBackground(null);
}
}
+ else {
+ setBackground(null);
+ }
if (value instanceof LoadingNode) {
setForeground(JBColor.GRAY);
@@ -176,13 +172,11 @@
* This method is invoked only for customization of component.
* All component attributes are cleared when this method is being invoked.
*/
- public abstract void customizeCellRenderer(
- JTree tree,
- Object value,
- boolean selected,
- boolean expanded,
- boolean leaf,
- int row,
- boolean hasFocus
- );
+ public abstract void customizeCellRenderer(@NotNull JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus);
}
diff --git a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
index 3d19b63..846378c 100644
--- a/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
+++ b/platform/platform-api/src/com/intellij/ui/CommonActionsPanel.java
@@ -22,12 +22,15 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.speedSearch.SpeedSearchSupply;
import com.intellij.util.IconUtil;
+import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
import java.util.*;
/**
@@ -78,10 +81,15 @@
void doEdit();
class Adapter implements Listener {
+ @Override
public void doAdd() {}
+ @Override
public void doRemove() {}
+ @Override
public void doUp() {}
+ @Override
public void doDown() {}
+ @Override
public void doEdit() {}
}
}
@@ -95,7 +103,7 @@
Icon addIcon, Buttons... buttons) {
super(new BorderLayout());
final Listener listener = factory.createListener(this);
- AnActionButton[] actions = new AnActionButton[buttons.length];
+ AnActionButton[] actions = new AnActionButton[buttons.length + (additionalActions == null ? 0 : additionalActions.length)];
for (int i = 0; i < buttons.length; i++) {
Buttons button = buttons[i];
String name = null;
@@ -111,9 +119,10 @@
myButtons.put(button, b);
}
if (additionalActions != null && additionalActions.length > 0) {
- final ArrayList<AnActionButton> allActions = new ArrayList<AnActionButton>(Arrays.asList(actions));
- allActions.addAll(Arrays.asList(additionalActions));
- actions = allActions.toArray(new AnActionButton[allActions.size()]);
+ int i = buttons.length;
+ for (AnActionButton button : additionalActions) {
+ actions[i++] = button;
+ }
}
myActions = actions;
for (AnActionButton action : actions) {
@@ -122,7 +131,7 @@
if (buttonComparator != null) {
Arrays.sort(myActions, buttonComparator);
}
- ArrayList<AnAction> toolbarActions = new ArrayList<AnAction>(Arrays.asList(myActions));
+ ArrayList<AnAction> toolbarActions = ContainerUtilRt.<AnAction>newArrayList(myActions);
for (int i = 0; i < toolbarActions.size(); i++) {
if (toolbarActions.get(i) instanceof AnActionButton.CheckedAnActionButton) {
toolbarActions.set(i, ((AnActionButton.CheckedAnActionButton)toolbarActions.get(i)).getDelegate());
@@ -234,6 +243,18 @@
final JComponent c = getContextComponent();
if (c instanceof JTable || c instanceof JList) {
+ if (myButton == Buttons.EDIT) {
+ InputEvent inputEvent = e.getInputEvent();
+ if (inputEvent instanceof KeyEvent &&
+ c instanceof JTable &&
+ ((JTable)c).isEditing() &&
+ !(inputEvent.getComponent() instanceof ActionButtonComponent) // action button active in any case in the toolbar
+ ) {
+ e.getPresentation().setEnabled(false);
+ return;
+ }
+ }
+
final ListSelectionModel model = c instanceof JTable ? ((JTable)c).getSelectionModel()
: ((JList)c).getSelectionModel();
final int size = c instanceof JTable ? ((JTable)c).getRowCount()
diff --git a/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java b/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java
index 7269f97..cbcceb3 100644
--- a/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.java
+++ b/platform/platform-api/src/com/intellij/ui/ComponentTreeWatcher.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,7 +15,7 @@
*/
package com.intellij.ui;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import javax.swing.*;
import java.awt.*;
@@ -51,7 +51,7 @@
return true;
}
for (Class aClass : myControlsToIgnore) {
- if (ReflectionCache.isAssignable(aClass, object.getClass())) {
+ if (ReflectionUtil.isAssignable(aClass, object.getClass())) {
return true;
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/DefaultIconDeferrer.java b/platform/platform-api/src/com/intellij/ui/DefaultIconDeferrer.java
index cd437ac..77cdec5 100644
--- a/platform/platform-api/src/com/intellij/ui/DefaultIconDeferrer.java
+++ b/platform/platform-api/src/com/intellij/ui/DefaultIconDeferrer.java
@@ -29,4 +29,9 @@
public <T> Icon defer(final Icon base, final T param, @NotNull final Function<T, Icon> f) {
return f.fun(param);
}
+
+ @Override
+ public <T> Icon deferAutoUpdatable(Icon base, T param, @NotNull Function<T, Icon> f) {
+ return f.fun(param);
+ }
}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ui/DoubleClickListener.java b/platform/platform-api/src/com/intellij/ui/DoubleClickListener.java
index 048ab41..2cec8b0 100644
--- a/platform/platform-api/src/com/intellij/ui/DoubleClickListener.java
+++ b/platform/platform-api/src/com/intellij/ui/DoubleClickListener.java
@@ -19,11 +19,13 @@
*/
package com.intellij.ui;
+import org.jetbrains.annotations.NotNull;
+
import java.awt.event.MouseEvent;
public abstract class DoubleClickListener extends ClickListener {
@Override
- public final boolean onClick(MouseEvent event, int clickCount) {
+ public final boolean onClick(@NotNull MouseEvent event, int clickCount) {
if (clickCount == 2 && event.getButton() == MouseEvent.BUTTON1) {
return onDoubleClick(event);
}
diff --git a/platform/platform-api/src/com/intellij/ui/EditorNotificationPanel.java b/platform/platform-api/src/com/intellij/ui/EditorNotificationPanel.java
index 30560c3..deb1f05 100644
--- a/platform/platform-api/src/com/intellij/ui/EditorNotificationPanel.java
+++ b/platform/platform-api/src/com/intellij/ui/EditorNotificationPanel.java
@@ -25,10 +25,10 @@
import com.intellij.util.ui.PlatformColors;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
-import javax.swing.event.HyperlinkListener;
import java.awt.*;
/**
@@ -55,6 +55,16 @@
myLabel.setText(text);
}
+ public EditorNotificationPanel text(@NotNull String text) {
+ myLabel.setText(text);
+ return this;
+ }
+
+ public EditorNotificationPanel icon(@NotNull Icon icon) {
+ myLabel.setIcon(icon);
+ return this;
+ }
+
@Override
public Color getBackground() {
Color color = EditorColorsManager.getInstance().getGlobalScheme().getColor(EditorColors.NOTIFICATION_BACKGROUND);
@@ -63,6 +73,7 @@
public HyperlinkLabel createActionLabel(final String text, @NonNls final String actionId) {
return createActionLabel(text, new Runnable() {
+ @Override
public void run() {
executeAction(actionId);
}
@@ -71,11 +82,10 @@
public HyperlinkLabel createActionLabel(final String text, final Runnable action) {
HyperlinkLabel label = new HyperlinkLabel(text, PlatformColors.BLUE, getBackground(), PlatformColors.BLUE);
- label.addHyperlinkListener(new HyperlinkListener() {
- public void hyperlinkUpdate(final HyperlinkEvent e) {
- if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- action.run();
- }
+ label.addHyperlinkListener(new HyperlinkAdapter() {
+ @Override
+ protected void hyperlinkActivated(HyperlinkEvent e) {
+ action.run();
}
});
myLinksPanel.add(label);
diff --git a/platform/platform-api/src/com/intellij/ui/GuiUtils.java b/platform/platform-api/src/com/intellij/ui/GuiUtils.java
index ac7810c..ec37897 100644
--- a/platform/platform-api/src/com/intellij/ui/GuiUtils.java
+++ b/platform/platform-api/src/com/intellij/ui/GuiUtils.java
@@ -17,7 +17,6 @@
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
@@ -388,4 +387,12 @@
invokeAndWait(runnable);
}
}
+
+ public static JTextField createUndoableTextField() {
+ JTextField field = new JTextField();
+ if (ApplicationManager.getApplication() != null) {
+ new TextComponentUndoProvider(field);
+ }
+ return field;
+ }
}
diff --git a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java
index 564b097..27324c9 100644
--- a/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java
+++ b/platform/platform-api/src/com/intellij/ui/HyperlinkLabel.java
@@ -147,7 +147,7 @@
myHyperlinkListener = new HyperlinkListener() {
@Override
public void hyperlinkUpdate(HyperlinkEvent e) {
- BrowserUtil.launchBrowser(url);
+ BrowserUtil.browse(url);
}
};
addHyperlinkListener(myHyperlinkListener);
diff --git a/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java
index 7a7592f..bfae84f 100644
--- a/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java
+++ b/platform/platform-api/src/com/intellij/ui/ListToolbarDecorator.java
@@ -29,7 +29,7 @@
*/
class ListToolbarDecorator extends ToolbarDecorator {
private final JList myList;
- private EditableModel myEditableModel;
+ private final EditableModel myEditableModel;
ListToolbarDecorator(JList list, @Nullable EditableModel editableModel) {
myList = list;
@@ -83,31 +83,34 @@
protected void updateButtons() {
final CommonActionsPanel p = getActionsPanel();
if (p != null) {
+ boolean someElementSelected;
if (myList.isEnabled()) {
final int index = myList.getSelectedIndex();
- if (0 <= index && index < myList.getModel().getSize()) {
+ someElementSelected = 0 <= index && index < myList.getModel().getSize();
+ if (someElementSelected) {
final boolean downEnable = myList.getMaxSelectionIndex() < myList.getModel().getSize() - 1;
final boolean upEnable = myList.getMinSelectionIndex() > 0;
final boolean editEnabled = myList.getSelectedIndices().length == 1;
p.setEnabled(CommonActionsPanel.Buttons.EDIT, editEnabled);
- p.setEnabled(CommonActionsPanel.Buttons.REMOVE, true);
p.setEnabled(CommonActionsPanel.Buttons.UP, upEnable);
p.setEnabled(CommonActionsPanel.Buttons.DOWN, downEnable);
}
else {
p.setEnabled(CommonActionsPanel.Buttons.EDIT, false);
- p.setEnabled(CommonActionsPanel.Buttons.REMOVE, false);
p.setEnabled(CommonActionsPanel.Buttons.UP, false);
p.setEnabled(CommonActionsPanel.Buttons.DOWN, false);
}
p.setEnabled(CommonActionsPanel.Buttons.ADD, true);
}
else {
+ someElementSelected = false;
p.setEnabled(CommonActionsPanel.Buttons.ADD, false);
- p.setEnabled(CommonActionsPanel.Buttons.REMOVE, false);
p.setEnabled(CommonActionsPanel.Buttons.UP, false);
p.setEnabled(CommonActionsPanel.Buttons.DOWN, false);
}
+
+ p.setEnabled(CommonActionsPanel.Buttons.REMOVE, someElementSelected);
+ updateExtraElementActions(someElementSelected);
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/LoadingNode.java b/platform/platform-api/src/com/intellij/ui/LoadingNode.java
index d5bd442..0ac9102 100644
--- a/platform/platform-api/src/com/intellij/ui/LoadingNode.java
+++ b/platform/platform-api/src/com/intellij/ui/LoadingNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package com.intellij.ui;
import com.intellij.ide.IdeBundle;
+import org.jetbrains.annotations.NotNull;
import javax.swing.tree.DefaultMutableTreeNode;
@@ -24,11 +25,12 @@
this(getText());
}
+ @NotNull
public static String getText() {
return IdeBundle.message("treenode.loading");
}
- public LoadingNode(String text) {
+ public LoadingNode(@NotNull String text) {
super(text);
}
}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ui/MutableCollectionComboBoxModel.java b/platform/platform-api/src/com/intellij/ui/MutableCollectionComboBoxModel.java
index 191d9b3..92408f5 100644
--- a/platform/platform-api/src/com/intellij/ui/MutableCollectionComboBoxModel.java
+++ b/platform/platform-api/src/com/intellij/ui/MutableCollectionComboBoxModel.java
@@ -15,29 +15,45 @@
*/
package com.intellij.ui;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author traff
*/
-public class MutableCollectionComboBoxModel extends AbstractCollectionComboBoxModel {
- private List myItems;
+public class MutableCollectionComboBoxModel<T> extends AbstractCollectionComboBoxModel<T> {
+ private List<T> myItems;
- public MutableCollectionComboBoxModel(List items, Object selection) {
+ public MutableCollectionComboBoxModel(@NotNull List<T> items) {
+ this(items, ContainerUtil.getFirstItem(items));
+ }
+
+ public MutableCollectionComboBoxModel(@NotNull List<T> items, @Nullable T selection) {
super(selection);
+
myItems = items;
}
@NotNull
@Override
- final protected List getItems() {
+ final protected List<T> getItems() {
return myItems;
}
- public void update(List items) {
+ public void update(@NotNull List<T> items) {
myItems = items;
super.update();
}
+
+ public void addItem(T item) {
+ myItems.add(item);
+
+ fireIntervalAdded(this, myItems.size() - 1, myItems.size() - 1);
+ if (myItems.size() == 1 && getSelectedItem() == null && item != null) {
+ setSelectedItem(item);
+ }
+ }
}
diff --git a/platform/platform-api/src/com/intellij/ui/OrderPanel.java b/platform/platform-api/src/com/intellij/ui/OrderPanel.java
index 5f14f2c..d744780 100644
--- a/platform/platform-api/src/com/intellij/ui/OrderPanel.java
+++ b/platform/platform-api/src/com/intellij/ui/OrderPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -28,9 +28,10 @@
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
-public abstract class OrderPanel<T> extends JPanel{
+public abstract class OrderPanel<T> extends JPanel {
private String CHECKBOX_COLUMN_NAME;
private final Class<T> myEntryClass;
@@ -55,25 +56,22 @@
myEntryTable.setShowHorizontalLines(false);
myEntryTable.setShowVerticalLines(false);
myEntryTable.setIntercellSpacing(new Dimension(0, 0));
-
myEntryTable.getSelectionModel().setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
-
myEntryTable.registerKeyboardAction(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
- if(getCheckboxColumn() == -1) return;
+ if (getCheckboxColumn() == -1) return;
- final int[] selectedRows = myEntryTable.getSelectedRows();
+ int[] selectedRows = myEntryTable.getSelectedRows();
boolean currentlyMarked = true;
- for (int idx = 0; idx < selectedRows.length; idx++) {
- final int selectedRow = selectedRows[idx];
+ for (int selectedRow : selectedRows) {
if (selectedRow < 0 || !myEntryTable.isCellEditable(selectedRow, getCheckboxColumn())) {
return;
}
currentlyMarked &= ((Boolean)myEntryTable.getValueAt(selectedRow, getCheckboxColumn())).booleanValue();
}
- for (int idx = 0; idx < selectedRows.length; idx++) {
- myEntryTable.setValueAt(currentlyMarked? Boolean.FALSE : Boolean.TRUE, selectedRows[idx], getCheckboxColumn());
+ for (int selectedRow : selectedRows) {
+ myEntryTable.setValueAt(currentlyMarked ? Boolean.FALSE : Boolean.TRUE, selectedRow, getCheckboxColumn());
}
}
},
@@ -84,7 +82,7 @@
add(ScrollPaneFactory.createScrollPane(myEntryTable), BorderLayout.CENTER);
if (myEntryTable.getRowCount() > 0) {
- myEntryTable.getSelectionModel().setSelectionInterval(0,0);
+ myEntryTable.getSelectionModel().setSelectionInterval(0, 0);
}
}
@@ -93,22 +91,20 @@
}
public void setCheckboxColumnName(final String name) {
- final int width;
+ TableColumn checkboxColumn = myEntryTable.getColumnModel().getColumn(getCheckboxColumn());
if (StringUtil.isEmpty(name)) {
CHECKBOX_COLUMN_NAME = "";
- width = new JCheckBox().getPreferredSize().width;
+ TableUtil.setupCheckboxColumn(checkboxColumn);
}
else {
CHECKBOX_COLUMN_NAME = name;
final FontMetrics fontMetrics = myEntryTable.getFontMetrics(myEntryTable.getFont());
- width = fontMetrics.stringWidth(" " + name + " ") + 4;
+ final int width = fontMetrics.stringWidth(" " + name + " ") + 4;
+ checkboxColumn.setWidth(width);
+ checkboxColumn.setPreferredWidth(width);
+ checkboxColumn.setMaxWidth(width);
+ checkboxColumn.setMinWidth(width);
}
-
- final TableColumn checkboxColumn = myEntryTable.getColumnModel().getColumn(getCheckboxColumn());
- checkboxColumn.setWidth(width);
- checkboxColumn.setPreferredWidth(width);
- checkboxColumn.setMaxWidth(width);
- checkboxColumn.setMinWidth(width);
}
public void moveSelectedItemsUp() {
@@ -158,26 +154,26 @@
}
public void clear() {
- MyTableModel model = ((MyTableModel)myEntryTable.getModel());
- while(model.getRowCount() > 0){
+ MyTableModel model = getModel();
+ while (model.getRowCount() > 0) {
model.removeRow(0);
}
}
public void remove(T orderEntry) {
- MyTableModel model = ((MyTableModel)myEntryTable.getModel());
+ MyTableModel model = getModel();
int rowCount = model.getRowCount();
for (int i = 0; i < rowCount; i++) {
- if(getValueAt(i) == orderEntry) {
- model.removeRow(i);
- return;
- }
+ if (getValueAt(i) == orderEntry) {
+ model.removeRow(i);
+ return;
+ }
}
}
public void add(T orderEntry) {
- MyTableModel model = ((MyTableModel)myEntryTable.getModel());
- if(getCheckboxColumn() == -1) {
+ MyTableModel model = getModel();
+ if (getCheckboxColumn() == -1) {
model.addRow(new Object[]{orderEntry});
}
else {
@@ -185,12 +181,23 @@
}
}
+ public void addAll(Collection<T> orderEntries) {
+ for (T orderEntry : orderEntries) {
+ add(orderEntry);
+ }
+ }
+
protected int getEntryColumn() {
- return ((MyTableModel)myEntryTable.getModel()).getEntryColumn();
+ return getModel().getEntryColumn();
}
private int getCheckboxColumn() {
- return ((MyTableModel)myEntryTable.getModel()).getCheckboxColumn();
+ return getModel().getCheckboxColumn();
+ }
+
+ private MyTableModel getModel() {
+ @SuppressWarnings("unchecked") MyTableModel model = (MyTableModel)myEntryTable.getModel();
+ return model;
}
private class MyTableModel extends DefaultTableModel {
@@ -248,13 +255,15 @@
}
public T getValueAt(int row) {
- //noinspection unchecked
- return (T)myEntryTable.getModel().getValueAt(row, getEntryColumn());
+ @SuppressWarnings("unchecked") T t = (T)myEntryTable.getModel().getValueAt(row, getEntryColumn());
+ return t;
}
public abstract boolean isCheckable(T entry);
- public abstract boolean isChecked (T entry);
- public abstract void setChecked (T entry, boolean checked);
+
+ public abstract boolean isChecked(T entry);
+
+ public abstract void setChecked(T entry, boolean checked);
public String getCheckboxColumnName() {
if (CHECKBOX_COLUMN_NAME == null) {
diff --git a/platform/platform-api/src/com/intellij/ui/PaintingParent.java b/platform/platform-api/src/com/intellij/ui/PaintingParent.java
index 170acdb..6211581 100644
--- a/platform/platform-api/src/com/intellij/ui/PaintingParent.java
+++ b/platform/platform-api/src/com/intellij/ui/PaintingParent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -15,6 +15,7 @@
*/
package com.intellij.ui;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -41,16 +42,16 @@
* @return a rectangle, if null -- the whole component will be repainted
*/
@Nullable
- Rectangle getChildRec(Component c);
+ Rectangle getChildRec(@NotNull Component c);
class Wrapper extends JPanel implements PaintingParent {
- public Wrapper(Component component) {
+ public Wrapper(@NotNull Component component) {
super(new BorderLayout(0,0));
add(component);
}
@Override
- public Rectangle getChildRec(Component c) {
+ public Rectangle getChildRec(@NotNull Component c) {
return null;
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/PopupMenuListenerAdapter.java b/platform/platform-api/src/com/intellij/ui/PopupMenuListenerAdapter.java
new file mode 100644
index 0000000..412dd1e
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/PopupMenuListenerAdapter.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui;
+
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+
+public abstract class PopupMenuListenerAdapter implements PopupMenuListener {
+ @Override
+ public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+ }
+
+ @Override
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ }
+
+ @Override
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java
index 00300b3..76bb6f2 100644
--- a/platform/platform-api/src/com/intellij/ui/ScreenUtil.java
+++ b/platform/platform-api/src/com/intellij/ui/ScreenUtil.java
@@ -165,7 +165,7 @@
}
private static Insets calcInsets(GraphicsConfiguration gc) {
- if (Patches.SUN_BUG_ID_9000030 && GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length > 1) {
+ if (Patches.SUN_BUG_ID_7172665 && GraphicsEnvironment.getLocalGraphicsEnvironment().getScreenDevices().length > 1) {
return new Insets(0, 0, 0, 0);
}
diff --git a/platform/platform-api/src/com/intellij/ui/SearchTextField.java b/platform/platform-api/src/com/intellij/ui/SearchTextField.java
index 738cc7e..c4a5551 100644
--- a/platform/platform-api/src/com/intellij/ui/SearchTextField.java
+++ b/platform/platform-api/src/com/intellij/ui/SearchTextField.java
@@ -233,8 +233,9 @@
}
}
- public void setHistorySize(int aHistorySize) {
- myHistorySize = aHistorySize;
+ public void setHistorySize(int historySize) {
+ if (historySize <= 0) throw new IllegalArgumentException("history size must be a positive number");
+ myHistorySize = historySize;
}
public void setHistory(List<String> aHistory) {
diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
index 25bd8ba..9d8e1de 100644
--- a/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
+++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredComponent.java
@@ -56,11 +56,11 @@
public static final Color SHADOW_COLOR = new JBColor(new Color(250, 250, 250, 140), Gray._0.withAlpha(50));
public static final Color STYLE_SEARCH_MATCH_BACKGROUND = SHADOW_COLOR; //api compatibility
- public static final int FRAGMENT_ICON = -2;
+ public static final int FRAGMENT_ICON = -2;
- private final ArrayList<String> myFragments;
- private final ArrayList<SimpleTextAttributes> myAttributes;
- private ArrayList<Object> myFragmentTags = null;
+ private final List<String> myFragments;
+ private final List<SimpleTextAttributes> myAttributes;
+ private List<Object> myFragmentTags = null;
/**
* Component's icon. It can be <code>null</code>.
@@ -116,6 +116,7 @@
setOpaque(true);
}
+ @NotNull
public ColoredIterator iterator() {
return new MyIterator();
}
@@ -128,6 +129,7 @@
myIconOnTheRight = iconOnTheRight;
}
+ @NotNull
public final SimpleColoredComponent append(@NotNull String fragment) {
append(fragment, SimpleTextAttributes.REGULAR_ATTRIBUTES);
return this;
@@ -172,6 +174,7 @@
repaint();
}
+ @Override
public void append(@NotNull final String fragment, @NotNull final SimpleTextAttributes attributes, Object tag) {
_append(fragment, attributes, tag);
revalidateAndRepaint();
@@ -182,7 +185,7 @@
if (myFragmentTags == null) {
myFragmentTags = new ArrayList<Object>();
}
- while(myFragmentTags.size() < myFragments.size()-1) {
+ while (myFragmentTags.size() < myFragments.size() - 1) {
myFragmentTags.add(null);
}
myFragmentTags.add(tag);
@@ -229,7 +232,7 @@
* @param icon icon
*/
@Override
- public final void setIcon(final @Nullable Icon icon) {
+ public final void setIcon(@Nullable final Icon icon) {
myIcon = icon;
revalidateAndRepaint();
}
@@ -237,6 +240,7 @@
/**
* @return "leave" (internal) internal paddings of the component
*/
+ @NotNull
public Insets getIpad() {
return myIpad;
}
@@ -245,7 +249,7 @@
* Sets specified internal paddings
* @param ipad insets
*/
- public void setIpad(final Insets ipad) {
+ public void setIpad(@NotNull Insets ipad) {
myIpad = ipad;
revalidateAndRepaint();
@@ -315,12 +319,14 @@
}
@Override
+ @NotNull
public Dimension getPreferredSize() {
return computePreferredSize(false);
}
@Override
+ @NotNull
public Dimension getMinimumSize() {
return computePreferredSize(false);
}
@@ -333,6 +339,7 @@
return null;
}
+ @NotNull
public final synchronized Dimension computePreferredSize(final boolean mainTextOnly) {
// Calculate width
int width = myIpad.left;
@@ -457,10 +464,17 @@
return -1;
}
+ @Nullable
+ public Object getFragmentTagAt(int x) {
+ int index = findFragmentAt(x);
+ return index < 0 ? null : getFragmentTag(index);
+ }
+
+ @NotNull
protected JLabel formatToLabel(@NotNull JLabel label) {
label.setIcon(myIcon);
- if (myFragments.size() > 0) {
+ if (!myFragments.isEmpty()) {
final StringBuilder text = new StringBuilder();
text.append("<html><body style=\"white-space:nowrap\">");
@@ -484,7 +498,7 @@
}
static void formatText(@NotNull StringBuilder builder, @NotNull String fragment, @NotNull SimpleTextAttributes attributes) {
- if (fragment.length() > 0) {
+ if (!fragment.isEmpty()) {
builder.append("<span");
formatStyle(builder, attributes);
builder.append('>').append(convertFragment(fragment)).append("</span>");
@@ -492,7 +506,7 @@
}
static void formatLink(@NotNull StringBuilder builder, @NotNull String fragment, @NotNull SimpleTextAttributes attributes, @NotNull String url) {
- if (fragment.length() > 0) {
+ if (!fragment.isEmpty()) {
builder.append("<a href=\"").append(StringUtil.replace(url, "\"", "%22")).append("\"");
formatStyle(builder, attributes);
builder.append('>').append(convertFragment(fragment)).append("</a>");
@@ -575,7 +589,7 @@
g.fillRect(x, 0, width, height);
}
- protected void doPaintIcon(Graphics2D g, Icon icon, int offset) {
+ protected void doPaintIcon(@NotNull Graphics2D g, @NotNull Icon icon, int offset) {
final Container parent = getParent();
Color iconBackgroundColor = null;
if ((isOpaque() || isIconOpaque()) && !isTransparentIconBackground()) {
@@ -761,11 +775,11 @@
return false;
}
- protected void paintIcon(Graphics g, Icon icon, int offset) {
+ protected void paintIcon(@NotNull Graphics g, @NotNull Icon icon, int offset) {
icon.paintIcon(this, g, offset, (getHeight() - icon.getIconHeight()) / 2);
}
- protected void applyAdditionalHints(final Graphics g) {
+ protected void applyAdditionalHints(@NotNull Graphics g) {
}
@Override
@@ -782,7 +796,7 @@
myTransparentIconBackground = transparentIconBackground;
}
- public static int getTextBaseLine(FontMetrics metrics, final int height) {
+ public static int getTextBaseLine(@NotNull FontMetrics metrics, final int height) {
return (height - metrics.getHeight()) / 2 + metrics.getAscent();
}
@@ -803,12 +817,13 @@
}
}
+ @NotNull
private String logSwingPath() {
//noinspection HardCodedStringLiteral
final StringBuilder buffer = new StringBuilder("Components hierarchy:\n");
for (Container c = this; c != null; c = c.getParent()) {
buffer.append('\n');
- buffer.append(c.toString());
+ buffer.append(c);
}
return buffer.toString();
}
@@ -849,6 +864,7 @@
}
}
+ @NotNull
public CharSequence getCharSequence(boolean mainOnly) {
List<String> fragments = mainOnly && myMainTextLastIndex > -1 && myMainTextLastIndex + 1 < myFragments.size()?
myFragments.subList(0, myMainTextLastIndex + 1) : myFragments;
@@ -917,7 +933,7 @@
@Override
public void run() {
- BrowserUtil.launchBrowser(myUrl);
+ BrowserUtil.browse(myUrl);
}
}
diff --git a/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java b/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java
index a9e007c..af85195 100644
--- a/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java
+++ b/platform/platform-api/src/com/intellij/ui/SimpleColoredText.java
@@ -46,11 +46,16 @@
}
@Override
+ public void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes, Object tag) {
+ append(fragment, attributes);
+ }
+
+ @Override
public void setIcon(@Nullable Icon icon) {
}
@Override
- public void setToolTipText(String text) {
+ public void setToolTipText(@Nullable String text) {
}
public void clear() {
@@ -59,9 +64,9 @@
myAttributes.clear();
}
- public void appendToComponent(SimpleColoredComponent component) {
+ public void appendToComponent(@NotNull ColoredTextContainer component) {
int size = myTexts.size();
- for (int i=0; i < size; i++){
+ for (int i = 0; i < size; i++) {
String text = myTexts.get(i);
SimpleTextAttributes attribute = myAttributes.get(i);
component.append(text, attribute);
diff --git a/platform/platform-api/src/com/intellij/ui/SingleSelectionModel.java b/platform/platform-api/src/com/intellij/ui/SingleSelectionModel.java
new file mode 100644
index 0000000..ed6ef74
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/SingleSelectionModel.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.ui;
+
+import javax.swing.*;
+
+/**
+* @author Dmitry Avdeev
+*/
+public class SingleSelectionModel extends DefaultListSelectionModel {
+ {
+ setSelectionMode(SINGLE_SELECTION);
+ }
+
+ @Override
+ public void clearSelection() {
+ }
+
+ @Override
+ public void removeSelectionInterval(int index0, int index1) {
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java
index 06c0b0e..89d4d40 100644
--- a/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java
+++ b/platform/platform-api/src/com/intellij/ui/TableToolbarDecorator.java
@@ -18,7 +18,6 @@
import com.intellij.util.ui.EditableModel;
import com.intellij.util.ui.ElementProducer;
import com.intellij.util.ui.ListTableModel;
-import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -65,33 +64,36 @@
protected void updateButtons() {
final CommonActionsPanel p = getActionsPanel();
if (p != null) {
+ boolean someElementSelected;
if (myTable.isEnabled()) {
final int index = myTable.getSelectedRow();
final int size = myTable.getModel().getRowCount();
- if (0 <= index && index < size) {
+ someElementSelected = 0 <= index && index < size;
+ if (someElementSelected) {
final boolean downEnable = myTable.getSelectionModel().getMaxSelectionIndex() < size - 1;
final boolean upEnable = myTable.getSelectionModel().getMinSelectionIndex() > 0;
final boolean editEnabled = myTable.getSelectedRowCount() == 1;
p.setEnabled(CommonActionsPanel.Buttons.EDIT, editEnabled);
- p.setEnabled(CommonActionsPanel.Buttons.REMOVE, true);
p.setEnabled(CommonActionsPanel.Buttons.UP, upEnable);
p.setEnabled(CommonActionsPanel.Buttons.DOWN, downEnable);
}
else {
p.setEnabled(CommonActionsPanel.Buttons.EDIT, false);
- p.setEnabled(CommonActionsPanel.Buttons.REMOVE, false);
p.setEnabled(CommonActionsPanel.Buttons.UP, false);
p.setEnabled(CommonActionsPanel.Buttons.DOWN, false);
}
p.setEnabled(CommonActionsPanel.Buttons.ADD, myProducer == null || myProducer.canCreateElement());
}
else {
+ someElementSelected = false;
p.setEnabled(CommonActionsPanel.Buttons.ADD, false);
p.setEnabled(CommonActionsPanel.Buttons.EDIT, false);
- p.setEnabled(CommonActionsPanel.Buttons.REMOVE, false);
p.setEnabled(CommonActionsPanel.Buttons.UP, false);
p.setEnabled(CommonActionsPanel.Buttons.DOWN, false);
}
+
+ p.setEnabled(CommonActionsPanel.Buttons.REMOVE, someElementSelected);
+ updateExtraElementActions(someElementSelected);
}
}
@@ -117,7 +119,8 @@
table.setColumnSelectionInterval(0, 0);
table.editCellAt(index, 0);
- updateScroller(table, table.getCellEditor() instanceof Animated);
+ boolean temporaryHideVerticalScrollBar = table.getCellEditor() instanceof Animated;
+ TableUtil.updateScroller(table, temporaryHideVerticalScrollBar);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
@@ -138,24 +141,11 @@
myRemoveAction = new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
- TableUtil.stopEditing(table);
- int index = table.getSelectedRow();
- if (0 <= index && index < table.getModel().getRowCount()) {
- tableModel.removeRow(index);
- if (index < table.getModel().getRowCount()) {
- table.setRowSelectionInterval(index, index);
- }
- else {
- if (index > 0) {
- table.setRowSelectionInterval(index - 1, index - 1);
- }
- }
+ if (TableUtil.doRemoveSelectedItems(table, tableModel, null)) {
updateButtons();
+ table.requestFocus();
+ TableUtil.updateScroller(table, false);
}
-
- table.requestFocus();
-
- updateScroller(table, false);
}
};
@@ -201,20 +191,6 @@
};
}
- private static void updateScroller(JTable table, boolean temporaryHideVerticalScrollBar) {
- JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, table);
- if (scrollPane != null) {
- if (temporaryHideVerticalScrollBar) {
- final JScrollBar bar = scrollPane.getVerticalScrollBar();
- if (bar == null || !bar.isVisible()) {
- scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
- }
- }
- scrollPane.revalidate();
- scrollPane.repaint();
- }
- }
-
@Override
protected void installDnDSupport() {
RowsDnDSupport.install(myTable, (EditableModel)myTable.getModel());
diff --git a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java
index e654e33..61a3ae0 100644
--- a/platform/platform-api/src/com/intellij/ui/TitledSeparator.java
+++ b/platform/platform-api/src/com/intellij/ui/TitledSeparator.java
@@ -21,16 +21,19 @@
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.Border;
import java.awt.*;
/**
* @author cdr
*/
public class TitledSeparator extends JPanel {
- public static int TOP_INSET = 7;
- public static int BOTTOM_INSET = 5;
- public static int SEPARATOR_LEFT_INSET = 6;
- public static int SEPARATOR_RIGHT_INSET = 3;
+ public static final int TOP_INSET = 7;
+ public static final int BOTTOM_INSET = 5;
+ public static final int SEPARATOR_LEFT_INSET = 6;
+ public static final int SEPARATOR_RIGHT_INSET = 3;
+
+ public static final Border EMPTY_BORDER = IdeBorderFactory.createEmptyBorder(TOP_INSET, 0, BOTTOM_INSET, 0);
protected final JBLabel myLabel = new JBLabel() {
@Override
@@ -56,7 +59,7 @@
add(mySeparator,
new GridBagConstraints(1, 0, GridBagConstraints.REMAINDER, 1, 1, 1, GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL,
new Insets(2, SEPARATOR_LEFT_INSET, 0, SEPARATOR_RIGHT_INSET), 0, 0));
- setBorder(IdeBorderFactory.createEmptyBorder(TOP_INSET, 0, BOTTOM_INSET, 0));
+ setBorder(EMPTY_BORDER);
setText(text);
setLabelFor(labelFor);
diff --git a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java
index 0cd8245..aa8572d 100644
--- a/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java
+++ b/platform/platform-api/src/com/intellij/ui/ToolbarDecorator.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.border.CustomLineBorder;
import com.intellij.ui.table.TableView;
+import com.intellij.util.SmartList;
import com.intellij.util.ui.EditableModel;
import com.intellij.util.ui.ElementProducer;
import com.intellij.util.ui.UIUtil;
@@ -52,7 +53,7 @@
protected boolean myUpActionEnabled;
protected boolean myDownActionEnabled;
protected Border myActionsPanelBorder;
- private List<AnActionButton> myExtraActions = new ArrayList<AnActionButton>();
+ private final List<AnActionButton> myExtraActions = new SmartList<AnActionButton>();
private ActionToolbarPosition myToolbarPosition;
protected AnActionButtonRunnable myAddAction;
protected AnActionButtonRunnable myEditAction;
@@ -80,6 +81,14 @@
protected abstract void updateButtons();
+ protected void updateExtraElementActions(boolean someElementSelected) {
+ for (AnActionButton action : myExtraActions) {
+ if (action instanceof ElementActionButton) {
+ action.setEnabled(someElementSelected);
+ }
+ }
+ }
+
public final CommonActionsPanel getActionsPanel() {
return myActionsPanel;
}
@@ -399,6 +408,7 @@
return buttons.toArray(new CommonActionsPanel.Buttons[buttons.size()]);
}
+ @Override
public CommonActionsPanel.Listener createListener(final CommonActionsPanel panel) {
return new CommonActionsPanel.Listener() {
@Override
@@ -466,4 +476,24 @@
//noinspection ConstantConditions
return null;
}
+
+ /**
+ * Marker interface, button will be disabled if no selected element
+ */
+ public abstract static class ElementActionButton extends AnActionButton {
+ public ElementActionButton(String text, String description, @Nullable Icon icon) {
+ super(text, description, icon);
+ }
+
+ public ElementActionButton(String text, Icon icon) {
+ super(text, icon);
+ }
+
+ public ElementActionButton() {
+ }
+
+ public ElementActionButton(String text) {
+ super(text);
+ }
+ }
}
diff --git a/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java b/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java
index 9d8f884..e78b09e 100644
--- a/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java
+++ b/platform/platform-api/src/com/intellij/ui/border/IdeaTitledBorder.java
@@ -14,8 +14,8 @@
public class IdeaTitledBorder extends TitledBorder {
private final TitledSeparator titledSeparator;
- private Insets insideInsets;
- private Insets outsideInsets;
+ private final Insets insideInsets;
+ private final Insets outsideInsets;
public IdeaTitledBorder(String title, int indent, Insets insets) {
super(title);
@@ -23,9 +23,8 @@
titledSeparator.setText(title);
DialogUtil.registerMnemonic(titledSeparator.getLabel(), null);
- this.outsideInsets = new Insets(insets.top, insets.left, insets.bottom, insets.right);
-
- this.insideInsets = new Insets(TitledSeparator.BOTTOM_INSET, indent, 0, 0);
+ outsideInsets = new Insets(insets.top, insets.left, insets.bottom, insets.right);
+ insideInsets = new Insets(TitledSeparator.BOTTOM_INSET, indent, 0, 0);
}
@Override
diff --git a/platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java b/platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java
index e89b893..ec1145b 100644
--- a/platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java
+++ b/platform/platform-api/src/com/intellij/ui/components/JBCheckBox.java
@@ -66,7 +66,7 @@
* @return true in case of success and false otherwise
*/
public boolean setTextIcon(@NotNull Icon icon) {
- if (UIUtil.isUnderDarcula()) {
+ if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
return false;
}
ButtonUI ui = getUI();
diff --git a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java
index 9d760cc..5b9d1da 100644
--- a/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java
+++ b/platform/platform-api/src/com/intellij/ui/components/JBScrollPane.java
@@ -65,6 +65,7 @@
setCorner(LOWER_LEFT_CORNER, new Corner(LOWER_LEFT_CORNER));
}
+ @Override
public void setUI(ScrollPaneUI ui) {
super.setUI(ui);
updateViewportBorder();
diff --git a/platform/platform-api/src/com/intellij/ui/components/JBTextField.java b/platform/platform-api/src/com/intellij/ui/components/JBTextField.java
index 594e774..d3bfc54 100644
--- a/platform/platform-api/src/com/intellij/ui/components/JBTextField.java
+++ b/platform/platform-api/src/com/intellij/ui/components/JBTextField.java
@@ -50,13 +50,13 @@
myEmptyText = new StatusText(this) {
@Override
protected boolean isStatusVisible() {
- return JBTextField.this.getText().isEmpty() && !JBTextField.this.isFocusOwner();
+ return JBTextField.this.getText().isEmpty() && !isFocusOwner();
}
@Override
protected Rectangle getTextComponentBound() {
- Rectangle b = JBTextField.this.getBounds();
- return new Rectangle(JBTextField.this.getInsets().left >> 1, 0, b.width, b.height);
+ Rectangle b = getBounds();
+ return new Rectangle(getInsets().left >> 1, 0, b.width, b.height);
}
};
myEmptyText.clear();
diff --git a/platform/platform-api/src/com/intellij/ui/mac/MacMessages.java b/platform/platform-api/src/com/intellij/ui/mac/MacMessages.java
index 03a390c..99182f8 100644
--- a/platform/platform-api/src/com/intellij/ui/mac/MacMessages.java
+++ b/platform/platform-api/src/com/intellij/ui/mac/MacMessages.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.openapi.components.ServiceManager;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.registry.Registry;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,7 +38,9 @@
@Nullable DialogWrapper.DoNotAskOption doNotAskOption);
public static MacMessages getInstance() {
- return ServiceManager.getService(MacMessages.class);
+ return Registry.is("ide.mac.message.sheets.java.emulation.dialogs")
+ ? ServiceManager.getService(MacMessagesEmulation.class)
+ : ServiceManager.getService(MacMessages.class);
}
/**
diff --git a/platform/platform-api/src/com/intellij/ui/mac/MacMessagesEmulation.java b/platform/platform-api/src/com/intellij/ui/mac/MacMessagesEmulation.java
new file mode 100644
index 0000000..85b7ecb
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/ui/mac/MacMessagesEmulation.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.mac;
+
+/**
+ * Created by Denis Fokin
+ */
+public abstract class MacMessagesEmulation extends MacMessages {}
diff --git a/platform/platform-api/src/com/intellij/ui/roots/IconActionComponent.java b/platform/platform-api/src/com/intellij/ui/roots/IconActionComponent.java
index 411d5f0..d9ce8ef 100644
--- a/platform/platform-api/src/com/intellij/ui/roots/IconActionComponent.java
+++ b/platform/platform-api/src/com/intellij/ui/roots/IconActionComponent.java
@@ -16,6 +16,7 @@
package com.intellij.ui.roots;
import com.intellij.ui.ClickListener;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -43,7 +44,7 @@
});
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (action != null) {
action.run();
return true;
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 f7f183f..421f7dc 100644
--- a/platform/platform-api/src/com/intellij/ui/table/JBTable.java
+++ b/platform/platform-api/src/com/intellij/ui/table/JBTable.java
@@ -38,8 +38,8 @@
import java.util.EventObject;
public class JBTable extends JTable implements ComponentWithEmptyText, ComponentWithExpandableItems<TableCell> {
- private StatusText myEmptyText;
- private ExpandableItemsHandler<TableCell> myExpandableItemsHandler;
+ private final StatusText myEmptyText;
+ private final ExpandableItemsHandler<TableCell> myExpandableItemsHandler;
private MyCellEditorRemover myEditorRemover;
private boolean myEnableAntialiasing;
@@ -65,7 +65,7 @@
myEmptyText = new StatusText(this) {
@Override
protected boolean isStatusVisible() {
- return JBTable.this.isEmpty();
+ return isEmpty();
}
};
@@ -75,21 +75,26 @@
addMouseListener(new MyMouseListener());
getColumnModel().addColumnModelListener(new TableColumnModelListener() {
+ @Override
public void columnMarginChanged(ChangeEvent e) {
if (cellEditor != null && !(cellEditor instanceof Animated)) {
cellEditor.stopCellEditing();
}
}
+ @Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
+ @Override
public void columnAdded(TableColumnModelEvent e) {
}
+ @Override
public void columnMoved(TableColumnModelEvent e) {
}
+ @Override
public void columnRemoved(TableColumnModelEvent e) {
}
});
@@ -201,7 +206,7 @@
}
@Override
- public void setModel(final TableModel model) {
+ public void setModel(@NotNull TableModel model) {
super.setModel(model);
if (model instanceof SortableColumnModel) {
@@ -293,6 +298,7 @@
myExpandableItemsHandler.setEnabled(enabled);
}
+ @Override
public void removeNotify() {
if (ScreenUtil.isStandardAddRemoveNotify(this)) {
final KeyboardFocusManager keyboardFocusManager = KeyboardFocusManager.getCurrentKeyboardFocusManager();
@@ -364,6 +370,7 @@
myBusyIcon.suspend();
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
if (myBusyIcon != null) {
repaint();
@@ -390,6 +397,7 @@
}
}
+ @Override
public boolean editCellAt(final int row, final int column, final EventObject e) {
if (cellEditor != null && !cellEditor.stopCellEditing()) {
return false;
@@ -493,6 +501,7 @@
myFocusManager = IdeFocusManager.findInstanceByComponent(JBTable.this);
}
+ @Override
public void propertyChange(final PropertyChangeEvent e) {
if (!isEditing()) {
return;
@@ -527,6 +536,7 @@
}
private final class MyMouseListener extends MouseAdapter {
+ @Override
public void mousePressed(final MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
final int[] selectedRows = getSelectedRows();
@@ -566,6 +576,7 @@
return super.getComparator(column);
}
+ @Override
protected boolean useToString(int column) {
return false;
}
@@ -584,24 +595,28 @@
}
private class TableRowSorterModelWrapper extends ModelWrapper<TableModel, Integer> {
- private TableModel myModel;
+ private final TableModel myModel;
- private TableRowSorterModelWrapper(@NotNull final TableModel model) {
+ private TableRowSorterModelWrapper(@NotNull TableModel model) {
myModel = model;
}
+ @Override
public TableModel getModel() {
return myModel;
}
+ @Override
public int getColumnCount() {
- return (myModel == null) ? 0 : myModel.getColumnCount();
+ return myModel.getColumnCount();
}
+ @Override
public int getRowCount() {
- return (myModel == null) ? 0 : myModel.getRowCount();
+ return myModel.getRowCount();
}
+ @Override
public Object getValueAt(int row, int column) {
if (myModel instanceof SortableColumnModel) {
return ((SortableColumnModel)myModel).getRowValue(row);
@@ -610,6 +625,7 @@
return myModel.getValueAt(row, column);
}
+ @Override
public String getStringValueAt(int row, int column) {
TableStringConverter converter = getStringConverter();
if (converter != null) {
@@ -634,6 +650,7 @@
return string;
}
+ @Override
public Integer getIdentifier(int index) {
return index;
}
diff --git a/platform/platform-api/src/com/intellij/ui/table/TableView.java b/platform/platform-api/src/com/intellij/ui/table/TableView.java
index 889c496..a563c82 100644
--- a/platform/platform-api/src/com/intellij/ui/table/TableView.java
+++ b/platform/platform-api/src/com/intellij/ui/table/TableView.java
@@ -15,7 +15,9 @@
*/
package com.intellij.ui.table;
+import com.intellij.ui.GuiUtils;
import com.intellij.ui.TableUtil;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
@@ -28,7 +30,6 @@
import javax.swing.event.TableModelEvent;
import javax.swing.table.*;
import java.awt.*;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -43,7 +44,8 @@
setModelAndUpdateColumns(model);
}
- public void setModel(final TableModel dataModel) {
+ @Override
+ public void setModel(@NotNull final TableModel dataModel) {
assert dataModel instanceof SortableColumnModel : "SortableColumnModel required";
super.setModel(dataModel);
}
@@ -67,9 +69,10 @@
return (ListTableModel<Item>)super.getModel();
}
+ @Override
public TableCellRenderer getCellRenderer(int row, int column) {
final ColumnInfo<Item, ?> columnInfo = getListTableModel().getColumnInfos()[convertColumnIndexToModel(column)];
- final Item item = getListTableModel().getItems().get(convertRowIndexToModel(row));
+ final Item item = getRow(row);
final TableCellRenderer renderer = columnInfo.getCustomizedRenderer(item, columnInfo.getRenderer(item));
if (renderer == null) {
return super.getCellRenderer(row, column);
@@ -79,6 +82,7 @@
}
}
+ @Override
public void tableChanged(TableModelEvent e) {
if (isEditing()) getCellEditor().cancelCellEditing();
super.tableChanged(e);
@@ -181,62 +185,67 @@
}
+ @Override
public Collection<Item> getSelection() {
- ArrayList<Item> result = new ArrayList<Item>();
- int[] selectedRows = getSelectedRows();
- if (selectedRows == null) return result;
- final List<Item> items = getItems();
- if (! items.isEmpty()) {
- for (int selectedRow : selectedRows) {
- final int modelIndex = convertRowIndexToModel(selectedRow);
- if (modelIndex >= 0 && modelIndex < items.size()) {
- result.add(items.get(modelIndex));
+ return getSelectedObjects();
+ }
+
+ @Nullable
+ public Item getSelectedObject() {
+ final int row = getSelectedRow();
+ ListTableModel<Item> model = getListTableModel();
+ return row >= 0 && row < model.getRowCount() ? model.getRowValue(convertRowIndexToModel(row)) : null;
+ }
+
+ @NotNull
+ public List<Item> getSelectedObjects() {
+ ListSelectionModel selectionModel = getSelectionModel();
+ int minSelectionIndex = selectionModel.getMinSelectionIndex();
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ if (minSelectionIndex == -1 || maxSelectionIndex == -1) {
+ return Collections.emptyList();
+ }
+
+ List<Item> result = new SmartList<Item>();
+ ListTableModel<Item> model = getListTableModel();
+ for (int i = minSelectionIndex; i <= maxSelectionIndex; i++) {
+ if (selectionModel.isSelectedIndex(i)) {
+ int modelIndex = convertRowIndexToModel(i);
+ if (modelIndex >= 0 && modelIndex < model.getRowCount()) {
+ result.add(model.getRowValue(modelIndex));
}
}
}
return result;
}
- @Nullable
- public Item getSelectedObject() {
- final int row = getSelectedRow();
- final List<Item> list = getItems();
- return row >= 0 && row < list.size() ? list.get(convertRowIndexToModel(row)) : null;
- }
-
- @NotNull
- public List<Item> getSelectedObjects() {
- final int[] selectedRows = getSelectedRows();
- if (selectedRows == null || (selectedRows.length == 0)) return Collections.emptyList();
- final List<Item> items = getItems();
- final List<Item> result = new ArrayList<Item>();
- for (int selectedRow : selectedRows) {
- result.add(items.get(convertRowIndexToModel(selectedRow)));
- }
- return result;
- }
-
+ @Override
public void addSelection(Object item) {
- List items = getItems();
- if (!items.contains(item)) return;
- int index = items.indexOf(item);
+ @SuppressWarnings("unchecked")
+ int index = getListTableModel().indexOf((Item)item);
+ if (index < 0) {
+ return;
+ }
+
getSelectionModel().addSelectionInterval(convertRowIndexToView(index), convertRowIndexToView(index));
// fix cell selection case
getColumnModel().getSelectionModel().addSelectionInterval(0, getColumnCount()-1);
}
+ @Override
public TableCellEditor getCellEditor(int row, int column) {
- final ColumnInfo<Item, ?> columnInfo = getListTableModel().getColumnInfos()[convertColumnIndexToModel(column)];
- final TableCellEditor editor = columnInfo.getEditor(getListTableModel().getItems().get(convertRowIndexToModel(row)));
+ @SuppressWarnings("unchecked")
+ TableCellEditor editor = getListTableModel().getColumnInfos()[convertColumnIndexToModel(column)].getEditor(getRow(row));
return editor == null ? super.getCellEditor(row, column) : editor;
}
+ @Override
public List<Item> getItems() {
return getListTableModel().getItems();
}
public Item getRow(int row) {
- return getItems().get(convertRowIndexToModel(row));
+ return getListTableModel().getRowValue(convertRowIndexToModel(row));
}
public void setMinRowHeight(int i) {
@@ -254,4 +263,17 @@
public void stopEditing() {
TableUtil.stopEditing(this);
}
+
+ @Override
+ protected void createDefaultEditors() {
+ super.createDefaultEditors();
+
+ //noinspection unchecked
+ defaultEditorsByColumnClass.put(String.class, new UIDefaults.LazyValue() {
+ @Override
+ public Object createValue(UIDefaults table) {
+ return new DefaultCellEditor(GuiUtils.createUndoableTextField());
+ }
+ });
+ }
}
diff --git a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
index 40cbb9a..302ad81 100644
--- a/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
+++ b/platform/platform-api/src/com/intellij/ui/tabs/TabInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.ui.Queryable;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.PlaceProvider;
import com.intellij.ui.SimpleColoredText;
import com.intellij.ui.SimpleTextAttributes;
@@ -237,7 +238,7 @@
@Nullable
public JComponent getLastFocusOwner() {
- return myLastFocusOwner != null ? myLastFocusOwner.get() : null;
+ return SoftReference.dereference(myLastFocusOwner);
}
public TabInfo setAlertIcon(final AlertIcon alertIcon) {
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTree.java
index 1cbf31e..4ce2384 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTree.java
@@ -507,8 +507,8 @@
return super.getPreferredSize();
}
- public SimpleNodeRenderer getRenderer() {
- return (SimpleNodeRenderer)getCellRenderer();
+ public NodeRenderer getRenderer() {
+ return (NodeRenderer)getCellRenderer();
}
public String toString() {
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTreeBuilder.java b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTreeBuilder.java
index d6ca5bf..c584835 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTreeBuilder.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/SimpleTreeBuilder.java
@@ -28,21 +28,22 @@
import java.util.Comparator;
public class SimpleTreeBuilder extends AbstractTreeBuilder {
-
public SimpleTreeBuilder(JTree tree, DefaultTreeModel treeModel, AbstractTreeStructure treeStructure, @Nullable Comparator comparator) {
+ //noinspection unchecked
super(tree, treeModel, treeStructure, comparator);
}
+ @Override
public boolean isAlwaysShowPlus(NodeDescriptor nodeDescriptor) {
return ((SimpleNode) nodeDescriptor).isAlwaysShowPlus();
}
+ @Override
public boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
return ((SimpleNode) nodeDescriptor).isAutoExpandNode();
}
-
-
+ @Override
public final void updateFromRoot() {
updateFromRoot(false);
}
@@ -53,12 +54,14 @@
}
if (EventQueue.isDispatchThread()) {
- SimpleTreeBuilder.super.updateFromRoot();
- } else {
+ SimpleTreeBuilder.super.queueUpdate();
+ }
+ else {
ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
public void run() {
if (!isDisposed()) {
- SimpleTreeBuilder.super.updateFromRoot();
+ SimpleTreeBuilder.super.queueUpdate();
}
}
});
diff --git a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
index 322475b..0f62f53 100644
--- a/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
+++ b/platform/platform-api/src/com/intellij/ui/treeStructure/Tree.java
@@ -48,8 +48,8 @@
public class Tree extends JTree implements ComponentWithEmptyText, ComponentWithExpandableItems<Integer>, Autoscroll, Queryable,
ComponentWithFileColors {
- private StatusText myEmptyText;
- private ExpandableItemsHandler<Integer> myExpandableItemsHandler;
+ private final StatusText myEmptyText;
+ private final ExpandableItemsHandler<Integer> myExpandableItemsHandler;
private AsyncProcessIcon myBusyIcon;
private boolean myBusy;
@@ -60,20 +60,15 @@
private boolean myHorizontalAutoScrolling = true;
public Tree() {
- initTree_();
+ this(getDefaultTreeModel());
+ }
+
+ public Tree(TreeNode root) {
+ this(new DefaultTreeModel(root, false));
}
public Tree(TreeModel treemodel) {
super(treemodel);
- initTree_();
- }
-
- public Tree(TreeNode root) {
- super(root);
- initTree_();
- }
-
- private void initTree_() {
myEmptyText = new StatusText(this) {
@Override
protected boolean isStatusVisible() {
@@ -151,6 +146,7 @@
return Condition.TRUE;
}
+ @Override
public boolean isFileColorsEnabled() {
return false;
}
@@ -297,6 +293,7 @@
myBusyIcon.setToolTipText(null);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
if (myBusyIcon != null) {
repaint();
@@ -348,7 +345,7 @@
component = pathObjects[pathObjects.length - 2];
}
- Color color = getFileColorFor(((DefaultMutableTreeNode)component));
+ Color color = getFileColorFor((DefaultMutableTreeNode)component);
if (color != null) {
g.setColor(color);
g.fillRect(0, bounds.y, getWidth(), bounds.height);
@@ -390,6 +387,7 @@
*
* Another hack to match selection UI (wide) and selection behavior (narrow) in Nimbus/GTK+.
*/
+ @Override
protected void processMouseEvent(final MouseEvent e) {
MouseEvent e2 = e;
@@ -406,7 +404,7 @@
if (path != null) {
final Rectangle bounds = getPathBounds(path);
if (bounds != null &&
- (e.getY() > bounds.y && e.getY() < bounds.y + bounds.height) &&
+ e.getY() > bounds.y && e.getY() < bounds.y + bounds.height &&
(e.getX() >= bounds.x + bounds.width ||
e.getX() < bounds.x && !isLocationInExpandControl(path, e.getX(), e.getY()))) {
int newX = bounds.x + bounds.width - 2;
@@ -443,16 +441,19 @@
/**
* Disable Sun's speed search
*/
+ @Override
public TreePath getNextMatch(String prefix, int startingRow, Position.Bias bias) {
return null;
}
private static final int AUTOSCROLL_MARGIN = 10;
+ @Override
public Insets getAutoscrollInsets() {
return new Insets(getLocation().y + AUTOSCROLL_MARGIN, 0, getParent().getHeight() - AUTOSCROLL_MARGIN, getWidth() - 1);
}
+ @Override
public void autoscroll(Point p) {
int realRow = getClosestRowForLocation(p.x, p.y);
if (getLocation().y + p.y <= AUTOSCROLL_MARGIN) {
@@ -666,6 +667,7 @@
}
private class MyMouseListener extends MouseAdapter {
+ @Override
public void mousePressed(MouseEvent mouseevent) {
if (!SwingUtilities.isLeftMouseButton(mouseevent) &&
(SwingUtilities.isRightMouseButton(mouseevent) || SwingUtilities.isMiddleMouseButton(mouseevent))) {
@@ -712,8 +714,8 @@
else {
boxLeftX = getWidth() - boxLeftX - insets.right + treeUI.getRightChildIndent() - 1;
}
- boxLeftX -= (getComponentOrientation().isLeftToRight() ? (int)Math.ceil(boxWidth / 2.0) : (int)Math.floor(boxWidth / 2.0));
- return (mouseX >= boxLeftX && mouseX < (boxLeftX + boxWidth));
+ boxLeftX -= getComponentOrientation().isLeftToRight() ? (int)Math.ceil(boxWidth / 2.0) : (int)Math.floor(boxWidth / 2.0);
+ return mouseX >= boxLeftX && mouseX < boxLeftX + boxWidth;
}
return false;
}
@@ -736,10 +738,12 @@
}
}
+ @Override
public void focusGained(FocusEvent e) {
focusChanges();
}
+ @Override
public void focusLost(FocusEvent e) {
focusChanges();
}
@@ -770,6 +774,7 @@
boolean accept(T node);
}
+ @Override
public void putInfo(@NotNull Map<String, String> info) {
final TreePath[] selection = getSelectionPaths();
if (selection == null) return;
@@ -785,7 +790,7 @@
if (nodesText.length() > 0) {
nodesText.append(";");
}
- nodesText.append(c.toString());
+ nodesText.append(c);
}
}
@@ -803,6 +808,7 @@
}
}
+ @Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
diff --git a/platform/platform-api/src/com/intellij/util/Alarm.java b/platform/platform-api/src/com/intellij/util/Alarm.java
index 4ead10e..1462df1 100644
--- a/platform/platform-api/src/com/intellij/util/Alarm.java
+++ b/platform/platform-api/src/com/intellij/util/Alarm.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.
@@ -226,6 +226,27 @@
return count;
}
+ public void flush() {
+ List<Request> requests;
+ synchronized (LOCK) {
+ if (myRequests.isEmpty()) {
+ return;
+ }
+
+ requests = new SmartList<Request>();
+ for (Request request : myRequests) {
+ if (request.cancel()) {
+ requests.add(request);
+ }
+ }
+ myRequests.clear();
+ }
+
+ for (Request request : requests) {
+ request.run();
+ }
+ }
+
public int getActiveRequestCount() {
synchronized (LOCK) {
return myRequests.size();
@@ -268,7 +289,9 @@
return;
}
synchronized (LOCK) {
- if (myTask == null) return;
+ if (myTask == null) {
+ return;
+ }
}
final Runnable scheduledTask = new Runnable() {
@@ -289,7 +312,9 @@
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
- QueueProcessor.runSafely(task);
+ if (!myDisposed) {
+ QueueProcessor.runSafely(task);
+ }
}
});
}
@@ -297,6 +322,11 @@
QueueProcessor.runSafely(task);
}
}
+
+ @Override
+ public String toString() {
+ return "ScheduledTask "+Request.this;
+ }
};
if (myModalityState == null) {
@@ -311,6 +341,9 @@
//noinspection SSBasedInspection
SwingUtilities.invokeLater(scheduledTask);
}
+ else if (app.isDispatchThread() && app.getCurrentModalityState().equals(myModalityState)) {
+ scheduledTask.run();
+ }
else {
app.invokeLater(scheduledTask, myModalityState);
}
@@ -337,22 +370,27 @@
return myModalityState;
}
- private void cancel() {
+ private boolean cancel() {
+ boolean result;
synchronized (LOCK) {
if (myFuture != null) {
- myFuture.cancel(false);
+ result = myFuture.cancel(false);
// TODO Use java.util.concurrent.ScheduledThreadPoolExecutor.setRemoveOnCancelPolicy(true) when on jdk 1.7
((ScheduledThreadPoolExecutor)JobScheduler.getScheduler()).remove((Runnable)myFuture);
myFuture = null;
}
+ else {
+ result = false;
+ }
myTask = null;
}
+ return result;
}
@Override
public String toString() {
Runnable task = getTask();
- return super.toString() + (task != null ? task.toString():null);
+ return super.toString() + (task != null ? ": "+task : "");
}
}
diff --git a/platform/platform-api/src/com/intellij/util/PlatformUtils.java b/platform/platform-api/src/com/intellij/util/PlatformUtils.java
index b8e66c5..51bda4c 100644
--- a/platform/platform-api/src/com/intellij/util/PlatformUtils.java
+++ b/platform/platform-api/src/com/intellij/util/PlatformUtils.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,73 +16,110 @@
package com.intellij.util;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.Nullable;
/**
* @author Konstantin Bulenkov
*/
-public class PlatformUtils extends PlatformUtilsCore {
- private PlatformUtils() {
- }
+@SuppressWarnings({"deprecation", "UnusedDeclaration"})
+public class PlatformUtils {
+ public static final String PLATFORM_PREFIX_KEY = PlatformUtilsCore.PLATFORM_PREFIX_KEY;
+
+ public static final String IDEA_PREFIX = PlatformUtilsCore.IDEA_PREFIX;
+ public static final String IDEA_CE_PREFIX = PlatformUtilsCore.COMMUNITY_PREFIX;
+ public static final String APPCODE_PREFIX = PlatformUtilsCore.APPCODE_PREFIX;
+ public static final String CPP_PREFIX = PlatformUtilsCore.CPP_PREFIX;
+ public static final String PYCHARM_PREFIX = PlatformUtilsCore.PYCHARM_PREFIX;
+ public static final String PYCHARM_CE_PREFIX = PlatformUtilsCore.PYCHARM_PREFIX2;
+ public static final String RUBY_PREFIX = PlatformUtilsCore.RUBY_PREFIX;
+ public static final String PHP_PREFIX = PlatformUtilsCore.PHP_PREFIX;
+ public static final String WEB_PREFIX = PlatformUtilsCore.WEB_PREFIX;
+
+ private PlatformUtils() { }
public static String getPlatformPrefix() {
- return getPlatformPrefix(IDEA_PREFIX);
+ return PlatformUtilsCore.getPlatformPrefix();
}
public static String getPlatformPrefix(String defaultPrefix) {
- return System.getProperty(PLATFORM_PREFIX_KEY, defaultPrefix);
+ return PlatformUtilsCore.getPlatformPrefix(defaultPrefix);
}
- public static boolean isIdea() {
- return IDEA_PREFIX.equals(getPlatformPrefix());
+ public static boolean isIntelliJ() {
+ return PlatformUtilsCore.isIntelliJ();
}
- public static boolean isCommunity() {
- return COMMUNITY_PREFIX.equals(getPlatformPrefix());
+ public static boolean isIdeaUltimate() {
+ return PlatformUtilsCore.isIdea();
+ }
+
+ public static boolean isIdeaCommunity() {
+ return PlatformUtilsCore.isCommunity();
}
public static boolean isRubyMine() {
- return RUBY_PREFIX.equals(getPlatformPrefix());
+ return PlatformUtilsCore.isRubyMine();
+ }
+
+ public static boolean isAppCode() {
+ return PlatformUtilsCore.isAppCode();
+ }
+
+ public static boolean isCppIde() {
+ return PlatformUtilsCore.isCppIde();
}
public static boolean isCidr() {
return isAppCode() || isCppIde();
}
- public static boolean isAppCode() {
- return APPCODE_PREFIX.equals(getPlatformPrefix());
- }
-
- public static boolean isCppIde() {
- return CPP_PREFIX.equals(getPlatformPrefix());
- }
-
public static boolean isPyCharm() {
- String prefix = getPlatformPrefix();
- return PYCHARM_PREFIX.equals(prefix) || (prefix != null && prefix.startsWith(PYCHARM_PREFIX2));
+ return PlatformUtilsCore.isPyCharm();
+ }
+
+ public static boolean isPyCharmPro() {
+ return PlatformUtilsCore.isPyCharmPro();
+ }
+
+ public static boolean isPyCharmCommunity() {
+ return PlatformUtilsCore.isPyCharmCommunity();
}
public static boolean isPhpStorm() {
- return PHP_PREFIX.equals(getPlatformPrefix());
+ return PlatformUtilsCore.isPhpStorm();
}
public static boolean isWebStorm() {
- return WEB_PREFIX.equals(getPlatformPrefix());
+ return PlatformUtilsCore.isWebStorm();
}
- public static boolean isFlexIde() {
- return FLEX_PREFIX.equals(getPlatformPrefix());
- }
-
- public static boolean isIntelliJ() {
- return isIdea() || isCommunity();
- }
-
+ /** @deprecated not a common API; use DevKit's PsiUtil.isIdeaProject() when needed (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
public static boolean isIdeaProject(@Nullable Project project) {
- if (project == null) return false;
- final VirtualFile baseDir = project.getBaseDir();
- if (baseDir == null) return false;
- return baseDir.findChild("idea.iml") != null || baseDir.findChild("community-main.iml") != null;
+ return false;
}
+
+ /** @deprecated use {@link #IDEA_CE_PREFIX} (to remove in IDEA 15) */
+ @SuppressWarnings("UnusedDeclaration")
+ public static final String COMMUNITY_PREFIX = IDEA_CE_PREFIX;
+
+ /** @deprecated use {@link #isIdeaUltimate()} (to remove in IDEA 15) */
+ @SuppressWarnings("UnusedDeclaration")
+ public static boolean isIdea() { return isIdeaUltimate(); }
+
+ /** @deprecated use {@link #isIdeaCommunity()} (to remove in IDEA 15) */
+ @SuppressWarnings("UnusedDeclaration")
+ public static boolean isCommunity() { return isIdeaCommunity(); }
+
+ /** @deprecated use {@link #PYCHARM_CE_PREFIX} (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
+ public static final String PYCHARM_PREFIX2 = PYCHARM_CE_PREFIX;
+
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
+ public static final String FLEX_PREFIX = PlatformUtilsCore.FLEX_PREFIX;
+
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
+ public static boolean isFlexIde() { return false; }
}
diff --git a/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java b/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java
deleted file mode 100644
index 1a66186..0000000
--- a/platform/platform-api/src/com/intellij/util/net/CertificatesManager.java
+++ /dev/null
@@ -1,318 +0,0 @@
-package com.intellij.util.net;
-
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.io.StreamUtil;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * {@code CertificatesManager} is responsible for negotiation SSL connection with server
- * that using trusted or self-signed certificates.
- *
- * @author Mikhail Golubev
- */
-public class CertificatesManager {
- private static final Logger LOG = Logger.getInstance(CertificatesManager.class);
- private static final X509Certificate[] NO_CERTIFICATES = new X509Certificate[0];
-
- @NonNls private static final String DEFAULT_PATH = FileUtil.join(PathManager.getSystemPath(), "tasks", "cacerts");
- @NonNls private static final String DEFAULT_PASSWORD = "changeit";
-
- @NotNull
- public static CertificatesManager createDefault() {
- return createInstance(DEFAULT_PATH, DEFAULT_PASSWORD);
- }
-
-
- @NotNull
- public static CertificatesManager createInstance(@NotNull String cacertsPath, @NotNull String cacertsPassword) {
- return new CertificatesManager(cacertsPath, cacertsPassword);
- }
-
- private final String myCacertsPath;
- private final String myPassword;
-
- private CertificatesManager(@NotNull String cacertsPath, @NotNull String cacertsPassword) {
- myCacertsPath = cacertsPath;
- myPassword = cacertsPassword;
- }
-
- /**
- * Creates special kind of {@code SSLContext} which X509TrustManager first checks certificate presence in
- * in default system-wide trust store (usually located at {@code ${JAVA_HOME}/lib/security/cacerts} or specified by
- * {@code javax.net.ssl.trustStore} property) and when in the one specified by first argument of factory method
- * {@link CertificatesManager#createInstance(String, String)}.
- * If certificate wasn't found in either, manager will ask user whether it can be
- * accepted (like web-browsers do) and if can, certificate will be added to specified trust store.
- * </p>
- * This method may be used for transition to HttpClient 4.x (see {@code HttpClients.custom().setSslContext(SSLContext)})
- *
- * @return instance of SSLContext with described behavior
- */
- @NotNull
- public SSLContext createSslContext() throws Exception {
- // SSLContext context = SSLContext.getDefault();
- SSLContext context = SSLContext.getInstance("TLS");
- TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- factory.init((KeyStore)null);
- // assume that only X509 TrustManagers exist
- X509TrustManager systemManager = findX509TrustManager(factory.getTrustManagers());
-
- MutableX509TrustManager customManager = new MutableX509TrustManager(myCacertsPath, myPassword);
- MyX509TrustManager trustManager = new MyX509TrustManager(systemManager, customManager);
- // use default key store and secure random
- context.init(null, new TrustManager[]{trustManager}, null);
- return context;
- }
-
-
- private static class MyX509TrustManager implements X509TrustManager {
- private final X509TrustManager mySystemManager;
- private final MutableX509TrustManager myCustomManager;
-
-
- private MyX509TrustManager(X509TrustManager system, MutableX509TrustManager custom) {
- mySystemManager = system;
- myCustomManager = custom;
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] certificates, String s) throws CertificateException {
- // Not called by client
- throw new UnsupportedOperationException();
- }
-
- @Override
- public void checkServerTrusted(final X509Certificate[] certificates, String s) throws CertificateException {
- try {
- mySystemManager.checkServerTrusted(certificates, s);
- }
- catch (CertificateException e1) {
- X509Certificate certificate = certificates[0];
- // looks like self-signed certificate
- if (certificates.length == 1 && certificateIsSelfSigned(certificate)) {
- // check-then-act sequence
- synchronized (myCustomManager) {
- try {
- myCustomManager.checkServerTrusted(certificates, s);
- }
- catch (CertificateException e2) {
- if (myCustomManager.isBroken() || !updateTrustStore(certificate)) {
- throw e1;
- }
- }
- }
- }
- }
- }
-
- private boolean updateTrustStore(final X509Certificate certificate) {
- Application app = ApplicationManager.getApplication();
- if (app.isUnitTestMode() || app.isHeadlessEnvironment()) {
- myCustomManager.addCertificate(certificate);
- return true;
- }
-
- // can't use Application#invokeAndWait because of ReadAction
- final CountDownLatch proceeded = new CountDownLatch(1);
- final AtomicBoolean accepted = new AtomicBoolean();
- app.invokeLater(new Runnable() {
- @Override
- public void run() {
- try {
- UntrustedCertificateWarningDialog dialog =
- new UntrustedCertificateWarningDialog(certificate, myCustomManager.myPath, myCustomManager.myPassword);
- accepted.set(dialog.showAndGet());
- if (accepted.get()) {
- LOG.debug("Certificate was accepted");
- myCustomManager.addCertificate(certificate);
- }
- }
- finally {
- proceeded.countDown();
- }
- }
- }, ModalityState.any());
- try {
- proceeded.await();
- }
- catch (InterruptedException e) {
- LOG.error(e);
- }
- return accepted.get();
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- return mySystemManager.getAcceptedIssuers();
- }
- }
-
- /**
- * Trust manager that supports addition of new certificates (most likely self-signed) to corresponding physical
- * key store.
- */
- private static class MutableX509TrustManager implements X509TrustManager {
- private final String myPath;
- private final String myPassword;
- private final TrustManagerFactory myFactory;
- private final KeyStore myKeyStore;
- private volatile X509TrustManager myTrustManager;
- private volatile boolean broken = false;
-
- private MutableX509TrustManager(@NotNull String path, @NotNull String password) {
- myPath = path;
- myPassword = password;
- myKeyStore = loadKeyStore(path, password);
- myFactory = createFactory();
- myTrustManager = initFactoryAndGetManager();
- }
-
- private TrustManagerFactory createFactory() {
- try {
- return TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- }
- catch (NoSuchAlgorithmException e) {
- LOG.error(e);
- broken = true;
- }
- return null;
- }
-
- private KeyStore loadKeyStore(String path, String password) {
- KeyStore keyStore = null;
- try {
- keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
- File cacertsFile = new File(path);
- if (cacertsFile.exists()) {
- FileInputStream stream = null;
- try {
- stream = new FileInputStream(path);
- keyStore.load(stream, password.toCharArray());
- }
- finally {
- StreamUtil.closeStream(stream);
- }
- }
- else {
- FileUtil.createParentDirs(cacertsFile);
- keyStore.load(null, password.toCharArray());
- }
- }
- catch (Exception e) {
- LOG.error(e);
- broken = true;
- }
- return keyStore;
- }
-
- public boolean addCertificate(X509Certificate certificate) {
- if (broken) {
- return false;
- }
- String alias = certificate.getIssuerX500Principal().getName();
- FileOutputStream stream = null;
- try {
- myKeyStore.setCertificateEntry(alias, certificate);
- stream = new FileOutputStream(myPath);
- myKeyStore.store(stream, myPassword.toCharArray());
- // trust manager should be updated each time its key store was modified
- myTrustManager = initFactoryAndGetManager();
- return true;
- }
- catch (Exception e) {
- LOG.error(e);
- return false;
- }
- finally {
- StreamUtil.closeStream(stream);
- }
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] certificates, String s) throws CertificateException {
- if (keyStoreIsEmpty() || broken) {
- throw new CertificateException();
- }
- myTrustManager.checkClientTrusted(certificates, s);
- }
-
- @Override
- public void checkServerTrusted(X509Certificate[] certificates, String s) throws CertificateException {
- if (keyStoreIsEmpty() || broken) {
- throw new CertificateException();
- }
- myTrustManager.checkServerTrusted(certificates, s);
- }
-
- @Override
- public X509Certificate[] getAcceptedIssuers() {
- // trust no one if broken
- if (keyStoreIsEmpty() || broken) {
- return NO_CERTIFICATES;
- }
- return myTrustManager.getAcceptedIssuers();
- }
-
- private boolean keyStoreIsEmpty() {
- try {
- return myKeyStore.size() == 0;
- }
- catch (KeyStoreException e) {
- LOG.error(e);
- return true;
- }
- }
-
- private X509TrustManager initFactoryAndGetManager() {
- if (!broken) {
- try {
- myFactory.init(myKeyStore);
- return findX509TrustManager(myFactory.getTrustManagers());
- }
- catch (KeyStoreException e) {
- LOG.error(e);
- broken = true;
- }
- }
- return null;
- }
-
- public boolean isBroken() {
- return broken;
- }
- }
-
- private static X509TrustManager findX509TrustManager(TrustManager[] managers) {
- for (TrustManager manager : managers) {
- if (manager instanceof X509TrustManager) {
- return (X509TrustManager)manager;
- }
- }
- return null;
- }
-
- private static boolean certificateIsSelfSigned(X509Certificate certificate) {
- return certificate.getIssuerX500Principal().equals(certificate.getSubjectX500Principal());
- }
-}
diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form
index 01a6388..72db588 100644
--- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form
+++ b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettings.form
@@ -207,14 +207,6 @@
</component>
</children>
</grid>
- <component id="c299" class="javax.swing.JButton" binding="myClearPasswordsButton" default-binding="true">
- <constraints>
- <grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/CommonBundle" key="autodetected.proxies.clear.button"/>
- </properties>
- </component>
<component id="ffae6" class="javax.swing.JLabel" binding="myErrorLabel">
<constraints>
<grid row="9" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
@@ -237,6 +229,45 @@
</constraints>
<properties/>
</component>
+ <grid id="fee34" layout-manager="GridLayoutManager" row-count="2" 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="4" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="true"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="8f836" class="javax.swing.JCheckBox" binding="myPacUrlCheckBox">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/CommonBundle" key="checkbox.automatic.proxy.configuration.url"/>
+ </properties>
+ </component>
+ <component id="c299" class="javax.swing.JButton" binding="myClearPasswordsButton" default-binding="true">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="2" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text resource-bundle="messages/CommonBundle" key="autodetected.proxies.clear.button"/>
+ </properties>
+ </component>
+ <component id="77d11" class="javax.swing.JTextField" binding="myPacUrlTextField">
+ <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>
+ <hspacer id="21dc">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
</children>
</grid>
</form>
diff --git a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java
index 6fe52ab..46ea422 100644
--- a/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java
+++ b/platform/platform-api/src/com/intellij/util/net/HTTPProxySettingsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -78,6 +78,8 @@
private JLabel myProxyExceptionsLabel;
private JTextArea myProxyExceptions;
private JLabel myNoProxyForLabel;
+ private JCheckBox myPacUrlCheckBox;
+ private JTextField myPacUrlTextField;
private final HttpConfigurable myHttpConfigurable;
private volatile boolean myConnectionCheckInProgress;
@@ -86,6 +88,8 @@
HttpConfigurable httpConfigurable = myHttpConfigurable;
if (! Comparing.equal(myProxyExceptions.getText().trim(), httpConfigurable.PROXY_EXCEPTIONS)) return true;
isModified |= httpConfigurable.USE_PROXY_PAC != myAutoDetectProxyRb.isSelected();
+ isModified |= httpConfigurable.USE_PAC_URL != myPacUrlCheckBox.isSelected();
+ isModified |= !Comparing.strEqual(httpConfigurable.PAC_URL, myPacUrlTextField.getText());
isModified |= httpConfigurable.USE_HTTP_PROXY != myUseHTTPProxyRb.isSelected();
isModified |= httpConfigurable.PROXY_AUTHENTICATION != myProxyAuthCheckBox.isSelected();
isModified |= httpConfigurable.KEEP_PROXY_PASSWORD != myRememberProxyPasswordCheckBox.isSelected();
@@ -130,6 +134,12 @@
enableProxyAuthentication(myProxyAuthCheckBox.isSelected());
}
});
+ myPacUrlCheckBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ myPacUrlTextField.setEnabled(myPacUrlCheckBox.isSelected());
+ }
+ });
final ActionListener listener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
@@ -239,6 +249,8 @@
myNoProxyRb.setSelected(true); // default
HttpConfigurable httpConfigurable = myHttpConfigurable;
myAutoDetectProxyRb.setSelected(httpConfigurable.USE_PROXY_PAC);
+ myPacUrlCheckBox.setSelected(httpConfigurable.USE_PAC_URL);
+ myPacUrlTextField.setText(httpConfigurable.PAC_URL);
myUseHTTPProxyRb.setSelected(httpConfigurable.USE_HTTP_PROXY);
myProxyAuthCheckBox.setSelected(httpConfigurable.PROXY_AUTHENTICATION);
@@ -278,6 +290,8 @@
httpConfigurable.AUTHENTICATION_CANCELLED = false;
}
httpConfigurable.USE_PROXY_PAC = myAutoDetectProxyRb.isSelected();
+ httpConfigurable.USE_PAC_URL = myPacUrlCheckBox.isSelected();
+ httpConfigurable.PAC_URL = trimFieldText(myPacUrlTextField);
httpConfigurable.USE_HTTP_PROXY = myUseHTTPProxyRb.isSelected();
httpConfigurable.PROXY_TYPE_IS_SOCKS = mySocks.isSelected();
httpConfigurable.PROXY_AUTHENTICATION = myProxyAuthCheckBox.isSelected();
@@ -316,6 +330,11 @@
myProxyAuthCheckBox.setEnabled(enabled);
enableProxyAuthentication(enabled && myProxyAuthCheckBox.isSelected());
myCheckButton.setEnabled(canEnableConnectionCheck());
+
+ final boolean autoDetectProxy = myAutoDetectProxyRb.isSelected();
+ myPacUrlCheckBox.setEnabled(autoDetectProxy);
+ myClearPasswordsButton.setEnabled(autoDetectProxy);
+ myPacUrlTextField.setEnabled(autoDetectProxy && myPacUrlCheckBox.isSelected());
}
private void enableProxyAuthentication (boolean enabled) {
diff --git a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
index a0f72e4..685d814 100644
--- a/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
+++ b/platform/platform-api/src/com/intellij/util/net/HttpConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -80,6 +80,8 @@
public transient Getter<PasswordAuthentication> myTestAuthRunnable = new StaticGetter<PasswordAuthentication>(null);
public transient Getter<PasswordAuthentication> myTestGenericAuthRunnable = new StaticGetter<PasswordAuthentication>(null);
public String PROXY_EXCEPTIONS = "";
+ public boolean USE_PAC_URL = false;
+ public String PAC_URL = "";
public static HttpConfigurable getInstance() {
return ServiceManager.getService(HttpConfigurable.class);
diff --git a/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java b/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java
index 5e76ac1..df986ea 100644
--- a/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java
+++ b/platform/platform-api/src/com/intellij/util/net/IdeaWideProxySelector.java
@@ -16,6 +16,9 @@
package com.intellij.util.net;
import com.btr.proxy.search.ProxySearch;
+import com.btr.proxy.selector.pac.PacProxySelector;
+import com.btr.proxy.selector.pac.PacScriptSource;
+import com.btr.proxy.selector.pac.UrlPacScriptSource;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
@@ -73,7 +76,11 @@
if (myHttpConfigurable.USE_PROXY_PAC) {
ProxySelector pacProxySelector = myPacProxySelector.get();
- if (pacProxySelector == null) {
+ if (myHttpConfigurable.USE_PAC_URL && !StringUtil.isEmpty(myHttpConfigurable.PAC_URL)) {
+ PacScriptSource pacSource = new UrlPacScriptSource(myHttpConfigurable.PAC_URL);
+ myPacProxySelector.set(new PacProxySelector(pacSource));
+ }
+ else if (pacProxySelector == null) {
ProxySearch proxySearch = ProxySearch.getDefaultProxySearch();
proxySearch.setPacCacheSettings(32, 10 * 60 * 1000); // Cache 32 urls for up to 10 min.
pacProxySelector = proxySearch.getProxySelector();
diff --git a/platform/platform-api/src/com/intellij/util/net/NetUtils.java b/platform/platform-api/src/com/intellij/util/net/NetUtils.java
index ae18326..eb56e08 100644
--- a/platform/platform-api/src/com/intellij/util/net/NetUtils.java
+++ b/platform/platform-api/src/com/intellij/util/net/NetUtils.java
@@ -29,9 +29,6 @@
import java.io.OutputStream;
import java.net.*;
-/**
- * @author yole
- */
public class NetUtils {
private static final Logger LOG = Logger.getInstance(NetUtils.class);
diff --git a/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form
deleted file mode 100644
index c47867b..0000000
--- a/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.form
+++ /dev/null
@@ -1,94 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.UntrustedCertificateWarningDialog">
- <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="0" left="10" bottom="0" right="10"/>
- <constraints>
- <xy x="20" y="20" width="500" height="224"/>
- </constraints>
- <properties>
- <minimumSize width="-1" height="-1"/>
- <opaque value="false"/>
- <preferredSize width="400" height="550"/>
- </properties>
- <border type="none"/>
- <children>
- <grid id="d0af6" layout-manager="GridLayoutManager" row-count="1" 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="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="61118" class="javax.swing.JTextPane">
- <constraints>
- <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
- <preferred-size width="400" height="50"/>
- </grid>
- </constraints>
- <properties>
- <contentType value="text/plain"/>
- <opaque value="false"/>
- <text value="Server's certificate is untrusted and appears to be self-signed"/>
- </properties>
- </component>
- <component id="7dcbe" class="javax.swing.JLabel" binding="myWarningSign">
- <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>
- <text value=""/>
- </properties>
- </component>
- </children>
- </grid>
- <grid id="ccf25" binding="myCertificateInfoPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="empty">
- <title-color color="-16777216"/>
- <size top="0" left="0" bottom="0" right="0"/>
- </border>
- <children>
- <component id="63708" class="com.intellij.ui.components.JBLabel">
- <constraints border-constraint="North"/>
- <properties>
- <font style="1"/>
- <requestFocusEnabled value="true"/>
- <text value="Certificate details"/>
- </properties>
- </component>
- </children>
- </grid>
- <grid id="7551" 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="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"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="2a804" class="javax.swing.JTextPane" binding="myNoticePane">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="2" fill="1" indent="0" use-parent-layout="false">
- <preferred-size width="50" height="50"/>
- </grid>
- </constraints>
- <properties>
- <contentType value="text/html"/>
- <opaque value="false"/>
- <text value="<html> <head> </head> <body> <p style="margin-top: 0"> </p> </body> </html> "/>
- </properties>
- </component>
- </children>
- </grid>
- <vspacer id="d6d14">
- <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/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java b/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java
deleted file mode 100644
index b2a74ab..0000000
--- a/platform/platform-api/src/com/intellij/util/net/UntrustedCertificateWarningDialog.java
+++ /dev/null
@@ -1,121 +0,0 @@
-package com.intellij.util.net;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.ui.IdeBorderFactory;
-import com.intellij.ui.TitledSeparator;
-import com.intellij.ui.components.JBLabel;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.ui.FormBuilder;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.security.auth.x500.X500Principal;
-import javax.swing.*;
-import java.awt.*;
-import java.security.cert.X509Certificate;
-import java.text.DateFormat;
-import java.util.Map;
-
-import static com.intellij.openapi.util.Pair.create;
-
-/**
- * @author Mikhail Golubev
- */
-public class UntrustedCertificateWarningDialog extends DialogWrapper {
- private static final Logger LOG = Logger.getInstance(UntrustedCertificateWarningDialog.class);
- private static DateFormat DATE_FORMAT = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);
-
- private static final Map<String, String> FIELD_ABBREVIATIONS = ContainerUtil.newHashMap(
- create("CN", "Common Name"),
- create("O", "Organization"),
- create("OU", "Organizational Unit"),
- create("L", "Location"),
- create("C", "Country"),
- create("ST", "State")
- );
-
- private JPanel myRootPanel;
- private JLabel myWarningSign;
- private JPanel myCertificateInfoPanel;
- private JTextPane myNoticePane;
- private final X509Certificate myCertificate;
- private final String myPath, myPassword;
-
- public UntrustedCertificateWarningDialog(@NotNull X509Certificate certificate, @NotNull String storePath, @NotNull String password) {
- super((Project)null, false);
-
- myCertificate = certificate;
- myPath = FileUtil.toCanonicalPath(storePath);
-
- myPassword = password;
-
- FormBuilder builder = FormBuilder.createFormBuilder();
-
- // I'm not using separate panels and form builders to preserve alignment of labels
- builder = updateBuilderWithTitle(builder, "Issued To");
- builder = updateBuilderWithPrincipalData(builder, myCertificate.getSubjectX500Principal());
- builder = updateBuilderWithTitle(builder, "Issued By");
- builder = updateBuilderWithPrincipalData(builder, myCertificate.getIssuerX500Principal());
- builder = updateBuilderWithTitle(builder, "Validity Period");
- builder = builder
- .setIndent(IdeBorderFactory.TITLED_BORDER_INDENT)
- .addLabeledComponent("Valid from", new JBLabel(DATE_FORMAT.format(myCertificate.getNotBefore())))
- .addLabeledComponent("Valid until", new JBLabel(DATE_FORMAT.format(myCertificate.getNotAfter())));
- myCertificateInfoPanel.add(builder.getPanel(), BorderLayout.CENTER);
-
- setTitle("Untrusted Server's Certificate");
- setOKButtonText("Accept");
- setCancelButtonText("Reject");
- myWarningSign.setIcon(AllIcons.General.WarningDialog);
-
- Messages.installHyperlinkSupport(myNoticePane);
-// myNoticePane.setFont(myNoticePane.getFont().deriveFont((float)FontSize.SMALL.getSize()));
- myNoticePane.setText(
- String.format("<html><p><small>" +
- "Accepted certificate will be saved in truststore <code>%s</code> with password <code>%s</code>" +
- "</small></p><html>",
- myPath, myPassword));
-
- init();
- LOG.debug("Preferred size: " + getPreferredSize());
- }
-
- @SuppressWarnings("MethodMayBeStatic")
- private FormBuilder updateBuilderWithPrincipalData(FormBuilder builder, X500Principal principal) {
- builder = builder.setIndent(IdeBorderFactory.TITLED_BORDER_INDENT);
- for (String field : principal.getName().split(",")) {
- field = field.trim();
- String[] parts = field.split("=", 2);
- if (parts.length != 2) {
- continue;
- }
-
- String name = parts[0];
- String value = parts[1];
-
- String longName = FIELD_ABBREVIATIONS.get(name.toUpperCase());
- if (longName == null) {
- continue;
- }
-
- builder = builder.addLabeledComponent(String.format("<html>%s (<b>%s</b>)</html>", longName, name), new JBLabel(value));
- }
- return builder.setIndent(0);
- }
-
- @SuppressWarnings("MethodMayBeStatic")
- private FormBuilder updateBuilderWithTitle(FormBuilder builder, String title) {
- return builder.addComponent(new TitledSeparator(title), IdeBorderFactory.TITLED_BORDER_TOP_INSET);
- }
-
- @Nullable
- @Override
- protected JComponent createCenterPanel() {
- return myRootPanel;
- }
-}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.form b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.form
new file mode 100644
index 0000000..ae7b278
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.form
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.ssl.CertificateConfigurable">
+ <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="503" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="4918" binding="myCertificatesListPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="2" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <clientProperties>
+ <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithoutIndent"/>
+ </clientProperties>
+ <border type="etched" title="Accepted certificates"/>
+ <children/>
+ </grid>
+ <grid id="16d1c" layout-manager="GridLayoutManager" row-count="1" 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="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="5" 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"/>
+ <children>
+ <component id="89f9b" class="com.intellij.ui.components.JBCheckBox" binding="myCheckHostname">
+ <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>
+ <text value="Check &hostname"/>
+ </properties>
+ </component>
+ <component id="fd372" class="com.intellij.ui.components.JBCheckBox" binding="myCheckValidityPeriod">
+ <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="Check &validity period"/>
+ </properties>
+ </component>
+ <hspacer id="30a6f">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ <grid id="9a985" binding="myDetailsPanel" layout-manager="CardLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="499" height="24"/>
+ </grid>
+ </constraints>
+ <properties/>
+ <border type="none">
+ <title-color color="-16777216"/>
+ </border>
+ <children>
+ <grid id="2c4f3" binding="myEmptyPanel" 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>
+ <card name="Card1"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="fa818" 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="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="No certificate selected"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <component id="3a890" class="com.intellij.openapi.ui.Splitter">
+ <constraints>
+ <grid row="2" 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>
+ <firstComponent value="4918"/>
+ <orientation value="true"/>
+ <proportion value="0.3"/>
+ <secondComponent value="9a985"/>
+ <showDividerControls value="false"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java
new file mode 100644
index 0000000..598903c
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateConfigurable.java
@@ -0,0 +1,268 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.fileChooser.FileTypeDescriptor;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.AnActionButton;
+import com.intellij.ui.AnActionButtonRunnable;
+import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.components.JBCheckBox;
+import com.intellij.ui.components.JBScrollPane;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.Consumer;
+import com.intellij.util.containers.HashSet;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.TreeSelectionModel;
+import java.awt.*;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.Set;
+
+import static com.intellij.util.net.ssl.CertificateUtil.getCommonName;
+import static com.intellij.util.net.ssl.ConfirmingTrustManager.MutableTrustManager;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class CertificateConfigurable implements SearchableConfigurable, Configurable.NoScroll, CertificateListener {
+ private static final FileTypeDescriptor CERTIFICATE_DESCRIPTOR = new FileTypeDescriptor("Choose Certificate", ".crt", ".cer", ".pem");
+ @NonNls public static final String EMPTY_PANEL = "empty.panel";
+
+ private JPanel myRootPanel;
+ private JBCheckBox myCheckHostname;
+ private JBCheckBox myCheckValidityPeriod;
+
+ private JPanel myCertificatesListPanel;
+ private JPanel myDetailsPanel;
+ private JPanel myEmptyPanel;
+ private MutableTrustManager myTrustManager;
+
+ private Tree myTree;
+ private CertificateTreeBuilder myTreeBuilder;
+ private Set<X509Certificate> myCertificates = new HashSet<X509Certificate>();
+
+ private void initializeUI() {
+ myTree = new Tree();
+ myTreeBuilder = new CertificateTreeBuilder(myTree);
+
+ // not fully functional by now
+ myCheckHostname.setVisible(false);
+ myCheckValidityPeriod.setVisible(false);
+
+ myTrustManager = CertificatesManager.getInstance().getCustomTrustManager();
+ // show newly added certificates
+ myTrustManager.addListener(this);
+
+ myTree.getEmptyText().setText("No certificates");
+ myTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+ myTree.setRootVisible(false);
+ //myTree.setShowsRootHandles(false);
+
+ ToolbarDecorator decorator = ToolbarDecorator.createDecorator(myTree).disableUpDownActions();
+ decorator.setAddAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ // show choose file dialog, add certificate
+ FileChooser.chooseFile(CERTIFICATE_DESCRIPTOR, null, null, new Consumer<VirtualFile>() {
+ @Override
+ public void consume(VirtualFile file) {
+ String path = file.getPath();
+ X509Certificate certificate = CertificateUtil.loadX509Certificate(path);
+ if (certificate == null) {
+ Messages.showErrorDialog(myRootPanel, "Malformed X509 server certificate", "Not Imported");
+ }
+ else if (myCertificates.contains(certificate)) {
+ Messages.showWarningDialog(myRootPanel, "Certificate already exists", "Not Imported");
+ }
+ else {
+ myCertificates.add(certificate);
+ myTreeBuilder.addCertificate(certificate);
+ addCertificatePanel(certificate);
+ myTreeBuilder.selectCertificate(certificate);
+ }
+ }
+ });
+ }
+ }).setRemoveAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ // allow to delete several certificates at once
+ for (X509Certificate certificate : myTreeBuilder.getSelectedCertificates(true)) {
+ myCertificates.remove(certificate);
+ myTreeBuilder.removeCertificate(certificate);
+ }
+ if (myCertificates.isEmpty()) {
+ showCard(EMPTY_PANEL);
+ }
+ else {
+ myTreeBuilder.selectFirstCertificate();
+ }
+ }
+ });
+
+ myTree.addTreeSelectionListener(new TreeSelectionListener() {
+ @Override
+ public void valueChanged(TreeSelectionEvent e) {
+ X509Certificate certificate = myTreeBuilder.getFirstSelectedCertificate(true);
+ if (certificate != null) {
+ showCard(getCardName(certificate));
+ }
+ }
+ });
+ myCertificatesListPanel.add(decorator.createPanel(), BorderLayout.CENTER);
+ }
+
+ private void showCard(@NotNull String cardName) {
+ ((CardLayout)myDetailsPanel.getLayout()).show(myDetailsPanel, cardName);
+ }
+
+ private void addCertificatePanel(@NotNull X509Certificate certificate) {
+ String uniqueName = getCardName(certificate);
+ JPanel infoPanel = new CertificateInfoPanel(certificate);
+ UIUtil.addInsets(infoPanel, UIUtil.PANEL_REGULAR_INSETS);
+ JBScrollPane scrollPane = new JBScrollPane(infoPanel);
+ //scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
+ myDetailsPanel.add(scrollPane, uniqueName);
+ }
+
+ private static String getCardName(@NotNull X509Certificate certificate) {
+ return certificate.getSubjectX500Principal().getName();
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return "http.certificates";
+ }
+
+ @Nullable
+ @Override
+ public Runnable enableSearch(String option) {
+ return null;
+ }
+
+ @Nls
+ @Override
+ public String getDisplayName() {
+ return "Server Certificates";
+ }
+
+ @Nullable
+ @Override
+ public String getHelpTopic() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public JComponent createComponent() {
+ // lazily initialized to ensure that disposeUIResources() will be called, if
+ // tree builder was created
+ initializeUI();
+ return myRootPanel;
+ }
+
+ @Override
+ public boolean isModified() {
+ CertificatesManager.Config state = CertificatesManager.getInstance().getState();
+ return myCheckHostname.isSelected() != state.checkHostname ||
+ myCheckValidityPeriod.isSelected() != state.checkValidity ||
+ !myCertificates.equals(new HashSet<X509Certificate>(myTrustManager.getCertificates()));
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ List<X509Certificate> existing = myTrustManager.getCertificates();
+
+ Set<X509Certificate> added = new HashSet<X509Certificate>(myCertificates);
+ added.removeAll(existing);
+
+ Set<X509Certificate> removed = new HashSet<X509Certificate>(existing);
+ removed.removeAll(myCertificates);
+
+ for (X509Certificate certificate : added) {
+ if (!myTrustManager.addCertificate(certificate)) {
+ throw new ConfigurationException("Cannot add certificate for " + getCommonName(certificate), "Cannot Add Certificate");
+ }
+ }
+
+ for (X509Certificate certificate : removed) {
+ if (!myTrustManager.removeCertificate(certificate)) {
+ throw new ConfigurationException("Cannot remove certificate for " + getCommonName(certificate), "Cannot Remove Certificate");
+ }
+ }
+ CertificatesManager.Config state = CertificatesManager.getInstance().getState();
+ state.checkHostname = myCheckHostname.isSelected();
+ state.checkValidity = myCheckValidityPeriod.isSelected();
+ }
+
+ @Override
+ public void reset() {
+ List<X509Certificate> original = myTrustManager.getCertificates();
+ myTreeBuilder.reset(original);
+
+ myCertificates.clear();
+ myCertificates.addAll(original);
+
+ myDetailsPanel.removeAll();
+ myDetailsPanel.add(myEmptyPanel, EMPTY_PANEL);
+
+ // fill lower panel with cards
+ for (X509Certificate certificate : original) {
+ addCertificatePanel(certificate);
+ }
+
+ if (!myCertificates.isEmpty()) {
+ myTreeBuilder.selectFirstCertificate();
+ }
+
+ CertificatesManager.Config state = CertificatesManager.getInstance().getState();
+ myCheckHostname.setSelected(state.checkHostname);
+ myCheckValidityPeriod.setSelected(state.checkValidity);
+ }
+
+ @Override
+ public void disposeUIResources() {
+ Disposer.dispose(myTreeBuilder);
+ myTrustManager.removeListener(this);
+ }
+
+ @Override
+ public void certificateAdded(final X509Certificate certificate) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ if (myTreeBuilder != null && !myCertificates.contains(certificate)) {
+ myCertificates.add(certificate);
+ myTreeBuilder.addCertificate(certificate);
+ addCertificatePanel(certificate);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void certificateRemoved(final X509Certificate certificate) {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ public void run() {
+ if (myTreeBuilder != null && myCertificates.contains(certificate)) {
+ myCertificates.remove(certificate);
+ myTreeBuilder.removeCertificate(certificate);
+ }
+ }
+ });
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateInfoPanel.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateInfoPanel.java
new file mode 100644
index 0000000..cb147f6
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateInfoPanel.java
@@ -0,0 +1,110 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.ui.*;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.ui.FormBuilder;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.util.Map;
+
+import static com.intellij.util.net.ssl.CertificateWrapper.CommonField;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class CertificateInfoPanel extends JPanel {
+ private static DateFormat DATE_FORMAT = DateFormat.getDateInstance(DateFormat.SHORT);
+
+ private JPanel myPanel;
+ private final CertificateWrapper myCertificateWrapper;
+
+ public CertificateInfoPanel(@NotNull X509Certificate certificate) {
+ myCertificateWrapper = new CertificateWrapper(certificate);
+ setLayout(new BorderLayout());
+
+ FormBuilder builder = FormBuilder.createFormBuilder();
+
+ // I'm not using separate panels and form builders to preserve alignment of labels
+ builder = updateBuilderWithTitle(builder, "Issued To");
+ builder = updateBuilderWithPrincipalData(builder, myCertificateWrapper.getSubjectFields());
+ builder = updateBuilderWithTitle(builder, "Issued By");
+ builder = updateBuilderWithPrincipalData(builder, myCertificateWrapper.getIssuerFields());
+ builder = updateBuilderWithTitle(builder, "Validity Period");
+ String notBefore = DATE_FORMAT.format(myCertificateWrapper.getNotBefore());
+ String notAfter = DATE_FORMAT.format(myCertificateWrapper.getNotAfter());
+ builder = builder
+ .setIndent(IdeBorderFactory.TITLED_BORDER_INDENT)
+ .addLabeledComponent("Valid from:", createColoredComponent(notBefore, "not yet valid", myCertificateWrapper.isNotYetValid()))
+ .addLabeledComponent("Valid until:", createColoredComponent(notAfter, "expired", myCertificateWrapper.isExpired()));
+ builder = builder.setIndent(0);
+ builder = updateBuilderWithTitle(builder, "Fingerprints");
+ builder = builder.setIndent(IdeBorderFactory.TITLED_BORDER_INDENT);
+ builder = builder.addLabeledComponent("SHA-256:", getTextPane(formatHex(myCertificateWrapper.getSha256Fingerprint())));
+ builder = builder.addLabeledComponent("SHA-1:", getTextPane(formatHex(myCertificateWrapper.getSha1Fingerprint())));
+ add(builder.getPanel(), BorderLayout.NORTH);
+
+ SimpleColoredComponent component = new SimpleColoredComponent();
+ }
+
+ @NotNull
+ private static String formatHex(@NotNull String hex) {
+ StringBuilder builder = new StringBuilder();
+ for (int i = 0; i < hex.length(); i += 2) {
+ // split at 16th byte
+ if (i == 32) {
+ builder.append('\n');
+ }
+ builder.append(hex.substring(i, i + 2));
+ builder.append(' ');
+ }
+ if (hex.length() > 0) {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ return builder.toString().toUpperCase();
+ }
+
+ public X509Certificate getCertificate() {
+ return myCertificateWrapper.getCertificate();
+ }
+
+ private static FormBuilder updateBuilderWithPrincipalData(FormBuilder builder, Map<String, String> fields) {
+ builder = builder.setIndent(IdeBorderFactory.TITLED_BORDER_INDENT);
+ for (CommonField field : CommonField.values()) {
+ String value = fields.get(field.getShortName());
+ if (value == null) {
+ continue;
+ }
+ String label = String.format("<html>%s (<b>%s</b>)</html>", field.getShortName(), field.getLongName());
+ builder = builder.addLabeledComponent(label, new JBLabel(value));
+ }
+ return builder.setIndent(0);
+ }
+
+ private static FormBuilder updateBuilderWithTitle(FormBuilder builder, String title) {
+ return builder.addComponent(new TitledSeparator(title), IdeBorderFactory.TITLED_BORDER_TOP_INSET);
+ }
+
+ private static JComponent getTextPane(String text) {
+ JTextPane pane = new JTextPane();
+ pane.setOpaque(false);
+ pane.setEditable(false);
+ pane.setContentType("text/plain");
+ pane.setText(text);
+ //Messages.installHyperlinkSupport(pane);
+ return pane;
+ }
+
+ private static JComponent createColoredComponent(String mainText, String errorText, boolean hasError) {
+ SimpleColoredComponent component = new SimpleColoredComponent();
+ if (hasError) {
+ component.append(mainText + " (" + errorText + ")", new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, JBColor.RED));
+ } else {
+ component.append(mainText);
+ }
+ return component;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateListener.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateListener.java
new file mode 100644
index 0000000..91e0c30
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateListener.java
@@ -0,0 +1,13 @@
+package com.intellij.util.net.ssl;
+
+import java.security.cert.X509Certificate;
+import java.util.EventListener;
+
+/**
+ * @author Mikhail Golubev
+ */
+public interface CertificateListener extends EventListener {
+ void certificateAdded(X509Certificate certificate);
+
+ void certificateRemoved(X509Certificate certificate);
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateTreeBuilder.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateTreeBuilder.java
new file mode 100644
index 0000000..0d1141b
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateTreeBuilder.java
@@ -0,0 +1,268 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.ide.projectView.PresentationData;
+import com.intellij.ide.util.treeView.AbstractTreeBuilder;
+import com.intellij.ide.util.treeView.AbstractTreeStructure;
+import com.intellij.ide.util.treeView.NodeDescriptor;
+import com.intellij.ide.util.treeView.PresentableNodeDescriptor;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
+import com.intellij.util.ui.tree.TreeUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+import static com.intellij.util.net.ssl.CertificateWrapper.CommonField.COMMON_NAME;
+import static com.intellij.util.net.ssl.CertificateWrapper.CommonField.ORGANIZATION;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class CertificateTreeBuilder extends AbstractTreeBuilder {
+ private static final SimpleTextAttributes STRIKEOUT_ATTRIBUTES = new SimpleTextAttributes(SimpleTextAttributes.STYLE_STRIKEOUT, null);
+ private static final RootDescriptor ROOT_DESCRIPTOR = new RootDescriptor();
+
+ private final MultiMap<String, CertificateWrapper> myCertificates = new MultiMap<String, CertificateWrapper>();
+
+ public CertificateTreeBuilder(@NotNull Tree tree) {
+ init(tree, new DefaultTreeModel(new DefaultMutableTreeNode()), new MyTreeStructure(), new Comparator<NodeDescriptor>() {
+ @Override
+ public int compare(NodeDescriptor o1, NodeDescriptor o2) {
+ if (o1 instanceof OrganizationDescriptor && o2 instanceof OrganizationDescriptor) {
+ return ((String)o1.getElement()).compareTo((String)o2.getElement());
+ }
+ else if (o1 instanceof CertificateDescriptor && o2 instanceof CertificateDescriptor) {
+ String cn1 = ((CertificateDescriptor)o1).getElement().getSubjectField(COMMON_NAME);
+ String cn2 = ((CertificateDescriptor)o2).getElement().getSubjectField(COMMON_NAME);
+ return cn1.compareTo(cn2);
+ }
+ return 0;
+ }
+ }, true);
+ initRootNode();
+ }
+
+ public void reset(@NotNull Collection<X509Certificate> certificates) {
+ myCertificates.clear();
+ for (X509Certificate certificate : certificates) {
+ addCertificate(certificate);
+ }
+ // expand organization nodes at the same time
+ //initRootNode();
+ queueUpdateFrom(RootDescriptor.ROOT, true).doWhenDone(new Runnable() {
+ @Override
+ public void run() {
+ CertificateTreeBuilder.this.expandAll(null);
+ }
+ });
+ }
+
+ public void addCertificate(@NotNull X509Certificate certificate) {
+ CertificateWrapper wrapper = new CertificateWrapper(certificate);
+ myCertificates.putValue(wrapper.getSubjectField(ORGANIZATION), wrapper);
+ queueUpdateFrom(RootDescriptor.ROOT, true);
+ }
+
+ /**
+ * Remove specified certificate and corresponding organization, if after removal it contains no certificates.
+ */
+ public void removeCertificate(@NotNull X509Certificate certificate) {
+ CertificateWrapper wrapper = new CertificateWrapper(certificate);
+ myCertificates.remove(wrapper.getSubjectField(ORGANIZATION), wrapper);
+ queueUpdateFrom(RootDescriptor.ROOT, true);
+ }
+
+ public List<X509Certificate> getCertificates() {
+ return ContainerUtil.map(myCertificates.values(), new Function<CertificateWrapper, X509Certificate>() {
+ @Override
+ public X509Certificate fun(CertificateWrapper wrapper) {
+ return wrapper.getCertificate();
+ }
+ });
+ }
+
+ public boolean isEmpty() {
+ return myCertificates.isEmpty();
+ }
+
+ public void selectCertificate(@NotNull X509Certificate certificate) {
+ select(new CertificateWrapper(certificate));
+ }
+
+ public void selectFirstCertificate() {
+ if (!isEmpty()) {
+ Tree tree = (Tree)getTree();
+ TreePath path = TreeUtil.getFirstLeafNodePath(tree);
+ tree.addSelectionPath(path);
+ }
+ }
+
+ /**
+ * Returns certificates selected in the tree. If organization node is selected, all its certificates
+ * will be returned.
+ *
+ * @return - selected certificates
+ */
+ @NotNull
+ public Set<X509Certificate> getSelectedCertificates(boolean addFromOrganization) {
+ Set<X509Certificate> selected = getSelectedElements(X509Certificate.class);
+ if (addFromOrganization) {
+ for (String s : getSelectedElements(String.class)) {
+ selected.addAll(getCertificatesByOrganization(s));
+ }
+ }
+ return selected;
+ }
+
+ @Nullable
+ public X509Certificate getFirstSelectedCertificate(boolean addFromOrganization) {
+ Set<X509Certificate> certificates = getSelectedCertificates(addFromOrganization);
+ return certificates.isEmpty() ? null : certificates.iterator().next();
+ }
+
+ @NotNull
+ public List<X509Certificate> getCertificatesByOrganization(@NotNull String organizationName) {
+ Collection<CertificateWrapper> wrappers = myCertificates.get(organizationName);
+ return extract(wrappers);
+ }
+
+ private static List<X509Certificate> extract(Collection<CertificateWrapper> wrappers) {
+ return ContainerUtil.map(wrappers, new Function<CertificateWrapper, X509Certificate>() {
+ @Override
+ public X509Certificate fun(CertificateWrapper wrapper) {
+ return wrapper.getCertificate();
+ }
+ });
+ }
+
+ @Override
+ protected Object transformElement(Object object) {
+ if (object instanceof CertificateWrapper) {
+ return ((CertificateWrapper)object).getCertificate();
+ }
+ return object;
+ }
+
+ @Override
+ protected boolean isAutoExpandNode(NodeDescriptor nodeDescriptor) {
+ return super.isAutoExpandNode(nodeDescriptor) || nodeDescriptor instanceof OrganizationDescriptor;
+ }
+
+ class MyTreeStructure extends AbstractTreeStructure {
+ @Override
+ public Object getRootElement() {
+ return RootDescriptor.ROOT;
+ }
+
+ @Override
+ public Object[] getChildElements(Object element) {
+ if (element == RootDescriptor.ROOT) {
+ return ArrayUtil.toStringArray(myCertificates.keySet());
+ }
+ else if (element instanceof String) {
+ return ArrayUtil.toObjectArray(myCertificates.get((String)element));
+ }
+ return ArrayUtil.EMPTY_OBJECT_ARRAY;
+ }
+
+ @Nullable
+ @Override
+ public Object getParentElement(Object element) {
+ if (element == RootDescriptor.ROOT) {
+ return null;
+ }
+ else if (element instanceof String) {
+ return RootDescriptor.ROOT;
+ }
+ return ((CertificateWrapper)element).getSubjectField(ORGANIZATION);
+ }
+
+ @NotNull
+ @Override
+ public NodeDescriptor createDescriptor(Object element, NodeDescriptor parentDescriptor) {
+ if (element == RootDescriptor.ROOT) {
+ return ROOT_DESCRIPTOR;
+ }
+ else if (element instanceof String) {
+ return new OrganizationDescriptor(parentDescriptor, (String)element);
+ }
+ return new CertificateDescriptor(parentDescriptor, (CertificateWrapper)element);
+ }
+
+
+ @Override
+ public void commit() {
+ // do nothing
+ }
+
+ @Override
+ public boolean hasSomethingToCommit() {
+ return false;
+ }
+ }
+
+ // Auxiliary node descriptors
+
+ static abstract class MyNodeDescriptor<T> extends PresentableNodeDescriptor<T> {
+ private final T myObject;
+
+ MyNodeDescriptor(@Nullable NodeDescriptor parentDescriptor, @NotNull T object) {
+ super(null, parentDescriptor);
+ myObject = object;
+ }
+
+ @Override
+ public T getElement() {
+ return myObject;
+ }
+ }
+
+ static class RootDescriptor extends MyNodeDescriptor<Object> {
+ public static final Object ROOT = new Object();
+
+ private RootDescriptor() {
+ super(null, ROOT);
+ }
+
+ @Override
+ protected void update(PresentationData presentation) {
+ presentation.addText("<root>", SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ }
+ }
+
+ static class OrganizationDescriptor extends MyNodeDescriptor<String> {
+ private OrganizationDescriptor(@Nullable NodeDescriptor parentDescriptor, @NotNull String object) {
+ super(parentDescriptor, object);
+ }
+
+ @Override
+ protected void update(PresentationData presentation) {
+ presentation.addText(getElement(), SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
+ }
+ }
+
+ static class CertificateDescriptor extends MyNodeDescriptor<CertificateWrapper> {
+ private CertificateDescriptor(@Nullable NodeDescriptor parentDescriptor, @NotNull CertificateWrapper object) {
+ super(parentDescriptor, object);
+ }
+
+ @Override
+ protected void update(PresentationData presentation) {
+ CertificateWrapper wrapper = getElement();
+ SimpleTextAttributes attr = wrapper.isValid() ? SimpleTextAttributes.REGULAR_ATTRIBUTES : STRIKEOUT_ATTRIBUTES;
+ presentation.addText(wrapper.getSubjectField(COMMON_NAME), attr);
+ }
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java
new file mode 100644
index 0000000..a1e3623
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateUtil.java
@@ -0,0 +1,73 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.StreamUtil;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class CertificateUtil {
+ private static final Logger LOG = Logger.getInstance(CertificateUtil.class);
+
+ private static final CertificateFactory ourFactory = createFactory();
+
+ private static CertificateFactory createFactory() {
+ try {
+ return CertificateFactory.getInstance("X509");
+ }
+ catch (CertificateException e) {
+ throw new AssertionError("Can't initialize X509 certificate factory");
+ }
+ }
+
+ // Standard Names
+ // See complete reference at http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html
+ // certificate format
+ @Nls public static final String X509 = "X.509";
+ // Java Key Store - standard type of keystores used by keytool utility
+ @Nls public static final String JKS = "JKS";
+ // another standard type of keystore
+ @Nls public static final String PKCS12 = "PKCS12";
+ // type of trust manager factory
+ @Nls public static final String PKIX = "PKIX";
+ @Nls public static final String TLS = "TLS";
+
+ /**
+ * Utility class
+ */
+ private CertificateUtil() {
+ // empty
+ }
+
+ @Nullable
+ public static X509Certificate loadX509Certificate(@NotNull String path) {
+ InputStream stream = null;
+ try {
+ stream = new FileInputStream(path);
+ return (X509Certificate)ourFactory.generateCertificate(stream);
+ }
+ catch (Exception e) {
+ LOG.error("Can't add certificate for path: " + path, e);
+ return null;
+ }
+ finally {
+ StreamUtil.closeStream(stream);
+ }
+ }
+
+ /**
+ * @return subjects common name, usually it's domain name pattern, e.g. *.github.com
+ */
+ public static String getCommonName(@NotNull X509Certificate certificate) {
+ return new CertificateWrapper(certificate).getSubjectField(CertificateWrapper.CommonField.COMMON_NAME);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWarningDialog.form b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWarningDialog.form
new file mode 100644
index 0000000..3421747
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWarningDialog.form
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.util.net.ssl.CertificateWarningDialog">
+ <grid id="27dc6" binding="myRootPanel" 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="10" bottom="0" right="10"/>
+ <constraints>
+ <xy x="20" y="20" width="500" height="224"/>
+ </constraints>
+ <properties>
+ <minimumSize width="-1" height="-1"/>
+ <opaque value="false"/>
+ <preferredSize width="550" height="650"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <grid id="ccf25" binding="myCertificateInfoPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="2" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="empty">
+ <title-color color="-16777216"/>
+ <size top="0" left="0" bottom="0" right="0"/>
+ </border>
+ <children>
+ <component id="63708" class="com.intellij.ui.components.JBLabel">
+ <constraints border-constraint="North"/>
+ <properties>
+ <font style="1"/>
+ <requestFocusEnabled value="true"/>
+ <text value="Certificate details"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="7551" 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="3" 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"/>
+ <children>
+ <component id="2a804" class="javax.swing.JTextPane" binding="myNoticePane">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="2" fill="1" indent="0" use-parent-layout="false">
+ <preferred-size width="50" height="50"/>
+ </grid>
+ </constraints>
+ <properties>
+ <contentType value="text/html"/>
+ <opaque value="false"/>
+ <text value="<html> <head> </head> <body> <p style="margin-top: 0"> </p> </body> </html> "/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <vspacer id="d6d14">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="7dcbe" class="javax.swing.JLabel" binding="myWarningSign">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value=""/>
+ </properties>
+ </component>
+ <component id="192db" class="javax.swing.JTextPane" binding="myMessagePane">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="2" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="50"/>
+ </grid>
+ </constraints>
+ <properties>
+ <contentType value="text/html"/>
+ <editable value="false"/>
+ <opaque value="true"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWarningDialog.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWarningDialog.java
new file mode 100644
index 0000000..1884f05
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWarningDialog.java
@@ -0,0 +1,85 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.security.cert.X509Certificate;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class CertificateWarningDialog extends DialogWrapper {
+ private static final Logger LOG = Logger.getInstance(CertificateWarningDialog.class);
+
+ public static CertificateWarningDialog createUntrustedCertificateWarning(@NotNull X509Certificate certificate) {
+ return new CertificateWarningDialog(certificate,
+ "Untrusted Server's Certificate",
+ "Server's certificate is not trusted");
+ }
+
+ public static CertificateWarningDialog createExpiredCertificateWarning(@NotNull X509Certificate certificate) {
+ throw new UnsupportedOperationException("Not supported");
+ }
+
+ public static CertificateWarningDialog createHostnameMismatchWarning(@NotNull X509Certificate certificate,
+ @NotNull String hostname) {
+ String message = String.format("Server's certificate common name doesn't match hostname in URL: '%s' != '%s'",
+ new CertificateWrapper(certificate).getSubjectField(CertificateWrapper.CommonField.COMMON_NAME),
+ hostname);
+ return new CertificateWarningDialog(certificate, "Invalid hostname", message);
+ }
+
+ private JPanel myRootPanel;
+ private JLabel myWarningSign;
+ private JPanel myCertificateInfoPanel;
+ private JTextPane myNoticePane;
+ private JTextPane myMessagePane;
+ private final X509Certificate myCertificate;
+
+ public CertificateWarningDialog(@NotNull X509Certificate certificate, @NotNull String title, @NotNull String message) {
+ super((Project)null, false);
+
+ myCertificate = certificate;
+
+ CertificatesManager manager = CertificatesManager.getInstance();
+ setTitle(title);
+ myMessagePane.setText(String.format("<html><body><p>%s</p></body></html>", message));
+ myMessagePane.setBackground(UIUtil.getPanelBackground());
+ setOKButtonText("Accept");
+ setCancelButtonText("Reject");
+ myWarningSign.setIcon(AllIcons.General.WarningDialog);
+
+ Messages.installHyperlinkSupport(myNoticePane);
+ // myNoticePane.setFont(myNoticePane.getFont().deriveFont((float)FontSize.SMALL.getSize()));
+
+ String path = FileUtil.toCanonicalPath(manager.getCacertsPath());
+ String password = manager.getPassword();
+
+ myNoticePane.setText(
+ String.format("<html><p>" +
+ "Accepted certificate will be saved in truststore <code>%s</code> with default password <code>%s</code>" +
+ "</p><html>",
+ path, password
+ )
+ );
+ myCertificateInfoPanel.add(new CertificateInfoPanel(certificate), BorderLayout.CENTER);
+ setResizable(false);
+ init();
+ LOG.debug("Preferred size: " + getPreferredSize());
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return myRootPanel;
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWrapper.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWrapper.java
new file mode 100644
index 0000000..8c55767
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificateWrapper.java
@@ -0,0 +1,202 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.util.containers.HashMap;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.security.auth.x500.X500Principal;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+
+/**
+ * @author Mikhail Golubev
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class CertificateWrapper {
+ @NonNls public static final String NOT_AVAILABLE = "N/A";
+
+ private final X509Certificate myCertificate;
+ private final Map<String, String> myIssuerFields;
+ private final Map<String, String> mySubjectFields;
+
+ public CertificateWrapper(@NotNull X509Certificate certificate) {
+ myCertificate = certificate;
+ myIssuerFields = extractFields(certificate.getIssuerX500Principal());
+ mySubjectFields = extractFields(certificate.getSubjectX500Principal());
+ }
+
+ /**
+ * @param name - Common name of desired issuer field
+ * @return field value of {@link #NOT_AVAILABLE}. if it doesn't exist
+ */
+ @NotNull
+ public String getIssuerField(@NotNull CommonField name) {
+ String field = myIssuerFields.get(name.getShortName());
+ return field == null ? NOT_AVAILABLE : field;
+ }
+
+ /**
+ * @param name - Common name of desired subject field
+ * @return field value of {@link #NOT_AVAILABLE}, if it doesn't exist
+ */
+ @NotNull
+ public String getSubjectField(@NotNull CommonField name) {
+ String field = mySubjectFields.get(name.getShortName());
+ return field == null ? NOT_AVAILABLE : field;
+ }
+
+ /**
+ * Returns SHA-256 fingerprint of the certificate.
+ *
+ * @return SHA-256 fingerprint or {@link #NOT_AVAILABLE} in case of any error
+ */
+ @NotNull
+ public String getSha256Fingerprint() {
+ try {
+ return DigestUtils.sha256Hex(myCertificate.getEncoded());
+ }
+ catch (CertificateEncodingException e) {
+ return NOT_AVAILABLE;
+ }
+ }
+
+ /**
+ * Returns SHA-1 fingerprint of the certificate.
+ *
+ * @return SHA-1 fingerprint or {@link #NOT_AVAILABLE} in case of any error
+ */
+ public String getSha1Fingerprint() {
+ try {
+ return DigestUtils.sha1Hex(myCertificate.getEncoded());
+ }
+ catch (Exception e) {
+ return NOT_AVAILABLE;
+ }
+ }
+
+ /**
+ * Check whether certificate is valid. It's considered invalid it it either expired or
+ * not yet valid.
+ *
+ * @see #isExpired()
+ * @see #isNotYetValid()
+ */
+ public boolean isValid() {
+ try {
+ myCertificate.checkValidity();
+ return true;
+ }
+ catch (Exception e) {
+ return false;
+ }
+ }
+
+ public boolean isExpired() {
+ return new Date().getTime() > myCertificate.getNotAfter().getTime();
+ }
+
+ public boolean isNotYetValid() {
+ return new Date().getTime() < myCertificate.getNotBefore().getTime();
+ }
+
+ /**
+ * Check whether certificate is self-signed. It's considered self-signed if
+ * its issuer and subject are the same.
+ */
+ public boolean isSelfSigned() {
+ return myCertificate.getIssuerX500Principal().equals(myCertificate.getSubjectX500Principal());
+ }
+
+ public int getVersion() {
+ return myCertificate.getVersion();
+ }
+
+ @NotNull
+ public String getSerialNumber() {
+ return myCertificate.getSerialNumber().toString();
+ }
+
+ public X509Certificate getCertificate() {
+ return myCertificate;
+ }
+
+ public X500Principal getIssuerX500Principal() {
+ return myCertificate.getIssuerX500Principal();
+ }
+
+ public X500Principal getSubjectX500Principal() {
+ return myCertificate.getSubjectX500Principal();
+ }
+
+ public Date getNotBefore() {
+ return myCertificate.getNotBefore();
+ }
+
+ public Date getNotAfter() {
+ return myCertificate.getNotAfter();
+ }
+
+ public Map<String, String> getIssuerFields() {
+ return myIssuerFields;
+ }
+
+ public Map<String, String> getSubjectFields() {
+ return mySubjectFields;
+ }
+
+ // E.g. CN=*.github.com,O=GitHub\, Inc.,L=San Francisco,ST=California,C=US
+ private static Map<String, String> extractFields(X500Principal principal) {
+ Map<String, String> fields = new HashMap<String, String>();
+ for (String field : principal.getName().split("(?<!\\\\),")) {
+ String[] parts = field.trim().split("=", 2);
+ if (parts.length != 2) {
+ continue;
+ }
+ fields.put(parts[0], parts[1].replaceAll("\\\\,", ","));
+ }
+ return Collections.unmodifiableMap(fields);
+ }
+
+ @Override
+ public final boolean equals(Object other) {
+ return other instanceof CertificateWrapper && myCertificate.equals(((CertificateWrapper)other).getCertificate());
+ }
+
+ @Override
+ public final int hashCode() {
+ return myCertificate.hashCode();
+ }
+
+ /**
+ * Find out full list of names from specification.
+ * See http://tools.ietf.org/html/rfc5280#section-4.1.2.2 for details.
+ */
+ public enum CommonField {
+ COMMON_NAME("CN", "Common Name"),
+ ORGANIZATION("O", "Organization"),
+ ORGANIZATION_UNIT("OU", "Organizational Unit"),
+ LOCATION("L", "Locality"),
+ COUNTRY("C", "Country"),
+ STATE("ST", "State or Province");
+
+ private final String myShortName;
+ private final String myLongName;
+
+ CommonField(@NotNull String shortName, @NotNull String longName) {
+ myShortName = shortName;
+ myLongName = longName;
+ }
+
+ public String getShortName() {
+ return myShortName;
+ }
+
+ public String getLongName() {
+ return myLongName;
+ }
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/CertificatesManager.java b/platform/platform-api/src/com/intellij/util/net/ssl/CertificatesManager.java
new file mode 100644
index 0000000..bc1f526
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/CertificatesManager.java
@@ -0,0 +1,245 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import com.intellij.util.xmlb.annotations.AbstractCollection;
+import com.intellij.util.xmlb.annotations.Property;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import java.security.NoSuchAlgorithmException;
+import java.util.LinkedHashSet;
+import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.apache.http.conn.ssl.SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER;
+
+/**
+ * {@code CertificatesManager} is responsible for negotiation SSL connection with server
+ * and deals with untrusted/self-singed/expired and other kinds of digital certificates.
+ * <h1>Integration details:</h1>
+ * If you're using httpclient-3.1 without custom {@code Protocol} instance for HTTPS you don't have to do anything
+ * at all: default {@code HttpClient} will use "Default" {@code SSLContext}, which is set up by this component itself.
+ * <p/>
+ * However for httpclient-4.x you have several of choices:
+ * <pre>
+ * <ol>
+ * <li>Client returned by {@code HttpClients.createSystem()} will use "Default" SSL context as it does in httpclient-3.1.</li>
+ * <li>If you want to customize {@code HttpClient} using {@code HttpClients.custom()}, you can use the following methods of the builder
+ * (in the order of increasing complexity/flexibility)
+ * <ol>
+ * <li>{@code useSystemProperties()} methods makes {@code HttpClient} use "Default" SSL context again</li>
+ * <li>{@code setSSLContext()} and pass result of the {@link #getSslContext()}</li>
+ * <li>{@code setSSLSocketFactory()} and specify instance {@code SSLConnectionSocketFactory} which uses result of {@link #getSslContext()}.</li>
+ * <li>{@code setConnectionManager} and initialize it with {@code Registry} that binds aforementioned {@code SSLConnectionSocketFactory} to HTTPS protocol</li>
+ * </ol>
+ * </li>
+ * </ol>
+ * </pre>
+ *
+ * @author Mikhail Golubev
+ */
+
+@State(
+ name = "CertificatesManager",
+ storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml")
+)
+public class CertificatesManager implements ApplicationComponent, PersistentStateComponent<CertificatesManager.Config> {
+
+ @NonNls public static final String COMPONENT_NAME = "Certificates Manager";
+ @NonNls private static final String DEFAULT_PATH = FileUtil.join(PathManager.getSystemPath(), "tasks", "cacerts");
+ @NonNls private static final String DEFAULT_PASSWORD = "changeit";
+
+ private static final Logger LOG = Logger.getInstance(CertificatesManager.class);
+
+ /**
+ * Special version of hostname verifier, that asks user whether he accepts certificate, which subject's common name
+ * doesn't match requested hostname.
+ */
+ public static final HostnameVerifier HOSTNAME_VERIFIER = new ConfirmingHostnameVerifier(BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+
+ public static CertificatesManager getInstance() {
+ return (CertificatesManager)ApplicationManager.getApplication().getComponent(COMPONENT_NAME);
+ }
+
+ private final String myCacertsPath;
+ private final String myPassword;
+ private final Config myConfig;
+
+ private final ConfirmingTrustManager myTrustManager;
+
+ /**
+ * Lazy initialized
+ */
+ private SSLContext mySslContext;
+
+ /**
+ * Component initialization constructor
+ */
+ public CertificatesManager() {
+ myCacertsPath = DEFAULT_PATH;
+ myPassword = DEFAULT_PASSWORD;
+ myConfig = new Config();
+ myTrustManager = ConfirmingTrustManager.createForStorage(myCacertsPath, myPassword);
+ }
+
+ @Override
+ public void initComponent() {
+ try {
+ // Don't do this: protocol created this way will ignore SSL tunnels. See IDEA-115708.
+ // Protocol.registerProtocol("https", CertificatesManager.createDefault().createProtocol());
+ SSLContext.setDefault(getSslContext());
+ LOG.debug("Default SSL context initialized");
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ }
+ }
+
+ @Override
+ public void disposeComponent() {
+ // empty
+ }
+
+ @NotNull
+ @Override
+ public String getComponentName() {
+ return COMPONENT_NAME;
+ }
+
+ /**
+ * Creates special kind of {@code SSLContext}, which X509TrustManager first checks certificate presence in
+ * in default system-wide trust store (usually located at {@code ${JAVA_HOME}/lib/security/cacerts} or specified by
+ * {@code javax.net.ssl.trustStore} property) and when in the one specified by field {@link #myCacertsPath}.
+ * If certificate wasn't found in either, manager will ask user, whether it can be
+ * accepted (like web-browsers do) and then, if it does, certificate will be added to specified trust store.
+ * <p/>
+ * If any error occurred during creation its message will be logged and system default SSL context will be returned
+ * so clients don't have to deal with awkward JSSE errors.
+ * </p>
+ * This method may be used for transition to HttpClient 4.x (see {@code HttpClientBuilder#setSslContext(SSLContext)})
+ * and {@code org.apache.http.conn.ssl.SSLConnectionSocketFactory()}.
+ *
+ * @return instance of SSLContext with described behavior or default SSL context in case of error
+ */
+ @NotNull
+ public synchronized SSLContext getSslContext() {
+ if (mySslContext == null) {
+ try {
+ mySslContext = createSslContext();
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ mySslContext = getSystemSslContext();
+ }
+ }
+ return mySslContext;
+ }
+
+ @NotNull
+ public SSLContext createSslContext() throws Exception {
+ // SSLContext context = SSLContext.getDefault();
+ // can also check, that default trust store exists, on this step
+ //assert systemManager.getAcceptedIssuers().length != 0
+
+ SSLContext context = getSystemSslContext();
+ context.init(null, new TrustManager[]{getTrustManager()}, null);
+ return context;
+ }
+
+ @NotNull
+ public static SSLContext getSystemSslContext() {
+ // NOTE SSLContext.getDefault() should not be called because it automatically creates
+ // default context with can't be initialized twice
+ try {
+ // actually TLSv1 support is mandatory for Java platform
+ return SSLContext.getInstance(CertificateUtil.TLS);
+ }
+ catch (NoSuchAlgorithmException e) {
+ LOG.error(e);
+ throw new AssertionError("Can't get system SSL context");
+ }
+ }
+
+ @NotNull
+ public String getCacertsPath() {
+ return myCacertsPath;
+ }
+
+ @NotNull
+ public String getPassword() {
+ return myPassword;
+ }
+
+ @NotNull
+ public ConfirmingTrustManager getTrustManager() {
+ return myTrustManager;
+ }
+
+ @NotNull
+ public ConfirmingTrustManager.MutableTrustManager getCustomTrustManager() {
+ return myTrustManager.getCustomManager();
+ }
+
+ public static boolean showAcceptDialog(final @NotNull Callable<? extends DialogWrapper> dialogFactory) {
+ Application app = ApplicationManager.getApplication();
+ final CountDownLatch proceeded = new CountDownLatch(1);
+ final AtomicBoolean accepted = new AtomicBoolean();
+ app.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ DialogWrapper dialog = dialogFactory.call();
+ accepted.set(dialog.showAndGet());
+ }
+ catch (Exception e) {
+ LOG.error("Unexpected error", e);
+ }
+ finally {
+ proceeded.countDown();
+ }
+ }
+ }, ModalityState.any());
+ try {
+ proceeded.await();
+ }
+ catch (InterruptedException e) {
+ LOG.error("Interrupted", e);
+ }
+ return accepted.get();
+ }
+
+ @NotNull
+ @Override
+ public Config getState() {
+ return myConfig;
+ }
+
+ @Override
+ public void loadState(Config state) {
+ XmlSerializerUtil.copyBean(state, myConfig);
+ }
+
+ public static class Config {
+ // ensure that request's hostname matches certificate's common name (CN)
+ public volatile boolean checkHostname;
+ // ensure that certificate is neither expired nor not yet eligible
+ public volatile boolean checkValidity;
+ @Tag("expired")
+ @Property(surroundWithTag = false)
+ @AbstractCollection(elementTag = "commonName")
+ public volatile LinkedHashSet<String> brokenCertificates = new LinkedHashSet<String>();
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/ClientOnlyTrustManager.java b/platform/platform-api/src/com/intellij/util/net/ssl/ClientOnlyTrustManager.java
new file mode 100644
index 0000000..79ecb88
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/ClientOnlyTrustManager.java
@@ -0,0 +1,15 @@
+package com.intellij.util.net.ssl;
+
+import javax.net.ssl.X509TrustManager;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+
+/**
+* @author Mikhail Golubev
+*/
+public abstract class ClientOnlyTrustManager implements X509TrustManager {
+ @Override
+ public void checkClientTrusted(X509Certificate[] certificates, String s) throws CertificateException {
+ throw new UnsupportedOperationException("Should not be called by client");
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingHostnameVerifier.java b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingHostnameVerifier.java
new file mode 100644
index 0000000..44e56a0
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingHostnameVerifier.java
@@ -0,0 +1,114 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.openapi.ui.DialogWrapper;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.jetbrains.annotations.NotNull;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocket;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.concurrent.Callable;
+
+/**
+* @author Mikhail Golubev
+*/ /*
+ * BrowserCompatibleHostnameVerifier has all final/package-private methods, so direct
+ * inheritance from it makes no sense. Inheriting from AbstractVerifier also makes no sense, because
+ * the only method I can override verify(String, String[], String[]), and I have no access to certificate for the dialog
+ * in this case. Why the heck verify(String, X509Certificate) is final? It basically means, that I should copy half of the
+ * AbstractVerifier here, which gives me a strong feel of stupidity.
+ *
+ * I submit a bug about this problem https://issues.apache.org/jira/browse/HTTPCLIENT-1449 and it seems to be
+ * resolved in httpclient4.4.
+ */
+class ConfirmingHostnameVerifier implements X509HostnameVerifier {
+ private final X509HostnameVerifier myVerifier;
+
+ public ConfirmingHostnameVerifier(@NotNull X509HostnameVerifier verifier) {
+ myVerifier = verifier;
+ }
+
+ // Copied from httpclient 4.2 sources, read class level commentary for explanation.
+ @Override
+ public void verify(String host, SSLSocket ssl) throws IOException {
+ if (host == null) {
+ throw new NullPointerException("host to verify is null");
+ }
+
+ SSLSession session = ssl.getSession();
+ if (session == null) {
+ // In our experience this only happens under IBM 1.4.x when
+ // spurious (unrelated) certificates show up in the server'
+ // chain. Hopefully this will unearth the real problem:
+ final InputStream in = ssl.getInputStream();
+ in.available();
+ // If ssl.getInputStream().available() didn't cause an
+ // exception, maybe at least now the session is available?
+ session = ssl.getSession();
+ if (session == null) {
+ // If it's still null, probably a startHandshake() will
+ // unearth the real problem.
+ ssl.startHandshake();
+
+ // Okay, if we still haven't managed to cause an exception,
+ // might as well go for the NPE. Or maybe we're okay now?
+ session = ssl.getSession();
+ }
+ }
+
+ final Certificate[] certs = session.getPeerCertificates();
+ final X509Certificate x509 = (X509Certificate)certs[0];
+ verify(host, x509);
+ }
+
+ @Override
+ public void verify(final String host, final X509Certificate cert) throws SSLException {
+ if (!CertificatesManager.getInstance().getState().checkHostname) {
+ return;
+ }
+ try {
+ myVerifier.verify(host, cert);
+ }
+ catch (SSLException e) {
+ //noinspection ConstantConditions
+ if (!accepted(host, cert)) {
+ throw e;
+ }
+ // TODO: inclusion in some kind of persistent settings
+ // Read/Write lock to protect storage?
+ }
+ }
+
+ private static boolean accepted(final String host, final X509Certificate cert) {
+ return CertificatesManager.showAcceptDialog(new Callable<DialogWrapper>() {
+ @Override
+ public DialogWrapper call() throws Exception {
+ return CertificateWarningDialog.createHostnameMismatchWarning(cert, host);
+ }
+ });
+ }
+
+ // Copied from httpclient 4.2 sources, read class level commentary for explanation.
+ @Override
+ public boolean verify(String host, SSLSession session) {
+ try {
+ final Certificate[] certs = session.getPeerCertificates();
+ final X509Certificate x509 = (X509Certificate)certs[0];
+ verify(host, x509);
+ return true;
+ }
+ catch (final SSLException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public void verify(String host, String[] cns, String[] subjectAlts) throws SSLException {
+ // actually never used, because it's only used in verify(final String host, final X509Certificate cert)
+ myVerifier.verify(host, cns, subjectAlts);
+ }
+}
diff --git a/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java
new file mode 100644
index 0000000..82dd36e
--- /dev/null
+++ b/platform/platform-api/src/com/intellij/util/net/ssl/ConfirmingTrustManager.java
@@ -0,0 +1,430 @@
+package com.intellij.util.net.ssl;
+
+import com.intellij.openapi.application.Application;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.EventDispatcher;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * The central piece of our SSL support - special kind of trust manager, that asks user to confirm
+ * untrusted certificate, e.g. if it wasn't found in system-wide storage.
+ *
+ * @author Mikhail Golubev
+ */
+public class ConfirmingTrustManager extends ClientOnlyTrustManager {
+ private static final Logger LOG = Logger.getInstance(ConfirmingTrustManager.class);
+ private static final X509Certificate[] NO_CERTIFICATES = new X509Certificate[0];
+ private static final X509TrustManager MISSING_TRUST_MANAGER = new ClientOnlyTrustManager() {
+ @Override
+ public void checkServerTrusted(X509Certificate[] certificates, String s) throws CertificateException {
+ LOG.debug("Trust manager is missing. Retreating.");
+ throw new CertificateException("Missing trust manager");
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return NO_CERTIFICATES;
+ }
+ };
+
+ public static ConfirmingTrustManager createForStorage(@NotNull String path, @NotNull String password) {
+ return new ConfirmingTrustManager(getSystemDefault(), new MutableTrustManager(path, password));
+ }
+
+ private static X509TrustManager getSystemDefault() {
+ try {
+ TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ // hacky way to get default trust store
+ factory.init((KeyStore)null);
+ // assume that only X509 TrustManagers exist
+ X509TrustManager systemManager = findX509TrustManager(factory.getTrustManagers());
+ if (systemManager != null && systemManager.getAcceptedIssuers().length != 0) {
+ return systemManager;
+ }
+ }
+ catch (Exception e) {
+ LOG.error("Cannot get system trust store", e);
+ }
+ return MISSING_TRUST_MANAGER;
+ }
+
+ private final X509TrustManager mySystemManager;
+ private final MutableTrustManager myCustomManager;
+
+
+ private ConfirmingTrustManager(X509TrustManager system, MutableTrustManager custom) {
+ mySystemManager = system;
+ myCustomManager = custom;
+ }
+
+ private static X509TrustManager findX509TrustManager(TrustManager[] managers) {
+ for (TrustManager manager : managers) {
+ if (manager instanceof X509TrustManager) {
+ return (X509TrustManager)manager;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void checkServerTrusted(final X509Certificate[] certificates, String s) throws CertificateException {
+ try {
+ mySystemManager.checkServerTrusted(certificates, s);
+ }
+ catch (CertificateException e) {
+ // check-then-act sequence
+ synchronized (myCustomManager) {
+ try {
+ myCustomManager.checkServerTrusted(certificates, s);
+ }
+ catch (CertificateException e2) {
+ if (myCustomManager.isBroken() || !confirmAndUpdate(certificates)) {
+ throw e;
+ }
+ }
+ }
+ }
+ }
+
+ private boolean confirmAndUpdate(final X509Certificate[] chain) {
+ Application app = ApplicationManager.getApplication();
+ final X509Certificate endPoint = chain[0];
+ if (app.isUnitTestMode() || app.isHeadlessEnvironment()) {
+ myCustomManager.addCertificate(endPoint);
+ return true;
+ }
+ boolean accepted = CertificatesManager.showAcceptDialog(new Callable<DialogWrapper>() {
+ @Override
+ public DialogWrapper call() throws Exception {
+ // TODO may be another kind of warning, if default trust store is missing
+ return CertificateWarningDialog.createUntrustedCertificateWarning(endPoint);
+ }
+ });
+ if (accepted) {
+ LOG.info("Certificate was accepted");
+ myCustomManager.addCertificate(endPoint);
+ }
+ return accepted;
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return ArrayUtil.mergeArrays(mySystemManager.getAcceptedIssuers(), myCustomManager.getAcceptedIssuers());
+ }
+
+ public X509TrustManager getSystemManager() {
+ return mySystemManager;
+ }
+
+ public MutableTrustManager getCustomManager() {
+ return myCustomManager;
+ }
+
+ /**
+ * Trust manager that supports modifications of underlying physical key store.
+ * It can also notify clients about such modifications, see {@link #addListener(CertificateListener)}.
+ *
+ * @see com.intellij.util.net.ssl.CertificateListener
+ */
+ public static class MutableTrustManager extends ClientOnlyTrustManager {
+ private final String myPath;
+ private final String myPassword;
+ private final TrustManagerFactory myFactory;
+ private final KeyStore myKeyStore;
+ private final ReadWriteLock myLock = new ReentrantReadWriteLock();
+ private final Lock myReadLock = myLock.readLock();
+ private final Lock myWriteLock = myLock.writeLock();
+ // reloaded after each modification
+ private X509TrustManager myTrustManager;
+
+ private final EventDispatcher<CertificateListener> myDispatcher = EventDispatcher.create(CertificateListener.class);
+
+ private MutableTrustManager(@NotNull String path, @NotNull String password) {
+ myPath = path;
+ myPassword = password;
+ // initialization step
+ myWriteLock.lock();
+ try {
+ myFactory = createFactory();
+ myKeyStore = createKeyStore(path, password);
+ myTrustManager = initFactoryAndGetManager();
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ }
+
+ private static TrustManagerFactory createFactory() {
+ try {
+ return TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ }
+ catch (NoSuchAlgorithmException e) {
+ return null;
+ }
+ }
+
+ private static KeyStore createKeyStore(@NotNull String path, @NotNull String password) {
+ KeyStore keyStore;
+ try {
+ keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
+ File cacertsFile = new File(path);
+ if (cacertsFile.exists()) {
+ FileInputStream stream = null;
+ try {
+ stream = new FileInputStream(path);
+ keyStore.load(stream, password.toCharArray());
+ }
+ finally {
+ StreamUtil.closeStream(stream);
+ }
+ }
+ else {
+ if (!FileUtil.createParentDirs(cacertsFile)) {
+ LOG.error("Cannot create directories: " + cacertsFile.getParent());
+ return null;
+ }
+ keyStore.load(null, password.toCharArray());
+ }
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ return null;
+ }
+ return keyStore;
+ }
+
+
+ /**
+ * Add certificate to underlying trust store.
+ *
+ * @param certificate server's certificate
+ * @return whether the operation was successful
+ */
+ public boolean addCertificate(@NotNull X509Certificate certificate) {
+ myWriteLock.lock();
+ try {
+ if (isBroken()) {
+ return false;
+ }
+ myKeyStore.setCertificateEntry(createAlias(certificate), certificate);
+ flushKeyStore();
+ // trust manager should be updated each time its key store was modified
+ myTrustManager = initFactoryAndGetManager();
+ myDispatcher.getMulticaster().certificateAdded(certificate);
+ return true;
+ }
+ catch (Exception e) {
+ LOG.error("Can't add certificate", e);
+ return false;
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ }
+
+ /**
+ * Add certificate, loaded from file at {@code path}, to underlying trust store.
+ *
+ * @param path path to file containing certificate
+ * @return whether the operation was successful
+ */
+ public boolean addCertificate(@NotNull String path) {
+ X509Certificate certificate = CertificateUtil.loadX509Certificate(path);
+ return certificate != null && addCertificate(certificate);
+ }
+
+ private static String createAlias(@NotNull X509Certificate certificate) {
+ return CertificateUtil.getCommonName(certificate);
+ }
+
+ /**
+ * Remove certificate from underlying trust store.
+ *
+ * @param certificate certificate alias
+ * @return whether the operation was successful
+ */
+ public boolean removeCertificate(@NotNull X509Certificate certificate) {
+ return removeCertificate(createAlias(certificate));
+ }
+
+ /**
+ * Remove certificate, specified by its alias, from underlying trust store.
+ *
+ * @param alias certificate's alias
+ * @return true if removal operation was successful and false otherwise
+ */
+ public boolean removeCertificate(@NotNull String alias) {
+ myWriteLock.lock();
+ try {
+ if (isBroken()) {
+ return false;
+ }
+ // for listeners
+ X509Certificate certificate = getCertificate(alias);
+ if (certificate == null) {
+ LOG.error("No certificate found for alias: " + alias);
+ return false;
+ }
+ myKeyStore.deleteEntry(alias);
+ flushKeyStore();
+ // trust manager should be updated each time its key store was modified
+ myTrustManager = initFactoryAndGetManager();
+ myDispatcher.getMulticaster().certificateRemoved(certificate);
+ return true;
+ }
+ catch (Exception e) {
+ LOG.error("Can't remove certificate for alias: " + alias, e);
+ return false;
+ }
+ finally {
+ myWriteLock.unlock();
+ }
+ }
+
+ /**
+ * Get certificate, specified by its alias, from underlying trust store.
+ *
+ * @param alias certificate's alias
+ * @return certificate or null if it's not present
+ */
+ @Nullable
+ public X509Certificate getCertificate(@NotNull String alias) {
+ myReadLock.lock();
+ try {
+ return (X509Certificate)myKeyStore.getCertificate(alias);
+ }
+ catch (KeyStoreException e) {
+ return null;
+ }
+ finally {
+ myReadLock.unlock();
+ }
+ }
+
+ /**
+ * Select all available certificates from underlying trust store. Returned list is not supposed to be modified.
+ *
+ * @return certificates
+ */
+ public List<X509Certificate> getCertificates() {
+ myReadLock.lock();
+ try {
+ List<X509Certificate> certificates = new ArrayList<X509Certificate>();
+ for (String alias : Collections.list(myKeyStore.aliases())) {
+ certificates.add(getCertificate(alias));
+ }
+ return ContainerUtil.immutableList(certificates);
+ }
+ catch (Exception e) {
+ LOG.error(e);
+ return ContainerUtil.emptyList();
+ }
+ finally {
+ myReadLock.unlock();
+ }
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] certificates, String s) throws CertificateException {
+ myReadLock.lock();
+ try {
+ if (keyStoreIsEmpty() || isBroken()) {
+ throw new CertificateException();
+ }
+ myTrustManager.checkServerTrusted(certificates, s);
+ }
+ finally {
+ myReadLock.unlock();
+ }
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ myReadLock.lock();
+ try {
+ // trust no one if broken
+ if (keyStoreIsEmpty() || isBroken()) {
+ return NO_CERTIFICATES;
+ }
+ return myTrustManager.getAcceptedIssuers();
+ }
+ finally {
+ myReadLock.unlock();
+ }
+ }
+
+ public void addListener(@NotNull CertificateListener listener) {
+ myDispatcher.addListener(listener);
+ }
+
+ public void removeListener(@NotNull CertificateListener listener) {
+ myDispatcher.removeListener(listener);
+ }
+
+ // Guarded by caller's lock
+ private boolean keyStoreIsEmpty() {
+ try {
+ return myKeyStore.size() == 0;
+ }
+ catch (KeyStoreException e) {
+ LOG.error(e);
+ return true;
+ }
+ }
+
+ // Guarded by caller's lock
+ private X509TrustManager initFactoryAndGetManager() {
+ try {
+ if (myFactory != null && myKeyStore != null) {
+ myFactory.init(myKeyStore);
+ return findX509TrustManager(myFactory.getTrustManagers());
+ }
+ }
+ catch (KeyStoreException e) {
+ LOG.error(e);
+ }
+ return null;
+ }
+
+ // Guarded by caller's lock
+ private boolean isBroken() {
+ return myKeyStore == null || myFactory == null || myTrustManager == null;
+ }
+
+ private void flushKeyStore() throws Exception {
+ FileOutputStream stream = new FileOutputStream(myPath);
+ try {
+ myKeyStore.store(stream, myPassword.toCharArray());
+ }
+ finally {
+ StreamUtil.closeStream(stream);
+ }
+ }
+ }
+}
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 89611b2..a7d9301 100644
--- a/platform/platform-api/src/com/intellij/util/ui/Animator.java
+++ b/platform/platform-api/src/com/intellij/util/ui/Animator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,7 +29,7 @@
import java.util.concurrent.atomic.AtomicBoolean;
public abstract class Animator implements Disposable {
- private final static ScheduledExecutorService scheduler = ConcurrencyUtil.newSingleScheduledThreadExecutor("Animations");
+ private static final ScheduledExecutorService scheduler = ConcurrencyUtil.newSingleScheduledThreadExecutor("Animations");
private final int myTotalFrames;
private final int myCycleDuration;
@@ -106,6 +106,7 @@
stopTicker();
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
paintCycleEnd();
}
@@ -159,6 +160,7 @@
public abstract void paintNow(int frame, int totalFrames, int cycle);
+ @Override
public void dispose() {
myDisposed = true;
stopTicker();
diff --git a/platform/platform-api/src/com/intellij/util/ui/PositionTracker.java b/platform/platform-api/src/com/intellij/util/ui/PositionTracker.java
index 9889286..5db4440 100644
--- a/platform/platform-api/src/com/intellij/util/ui/PositionTracker.java
+++ b/platform/platform-api/src/com/intellij/util/ui/PositionTracker.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.
@@ -18,13 +18,14 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.Disposer;
import com.intellij.ui.awt.RelativePoint;
+import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.*;
public abstract class PositionTracker<T> implements Disposable, HierarchyBoundsListener, HierarchyListener, ComponentListener {
- private Component myComponent;
+ private final Component myComponent;
private Client<T> myClient;
public PositionTracker(Component component) {
@@ -45,30 +46,37 @@
return myComponent;
}
+ @Override
public final void ancestorMoved(HierarchyEvent e) {
revalidate();
}
+ @Override
public final void ancestorResized(HierarchyEvent e) {
revalidate();
}
+ @Override
public final void hierarchyChanged(HierarchyEvent e) {
revalidate();
}
+ @Override
public void componentResized(ComponentEvent e) {
revalidate();
}
+ @Override
public void componentMoved(ComponentEvent e) {
revalidate();
}
+ @Override
public void componentShown(ComponentEvent e) {
revalidate();
}
+ @Override
public void componentHidden(ComponentEvent e) {
revalidate();
}
@@ -79,6 +87,7 @@
public abstract RelativePoint recalculateLocation(T object);
+ @Override
public final void dispose() {
myComponent.removeHierarchyBoundsListener(this);
myComponent.removeHierarchyListener(this);
@@ -87,7 +96,7 @@
public static final class Static<T> extends PositionTracker<T> {
- private RelativePoint myPoint;
+ private final RelativePoint myPoint;
public Static(RelativePoint point) {
super(point.getComponent());
@@ -103,7 +112,7 @@
public interface Client<T> extends Disposable {
void revalidate();
- void revalidate(PositionTracker<T> tracker);
+ void revalidate(@NotNull PositionTracker<T> tracker);
}
diff --git a/platform/platform-api/src/com/intellij/util/ui/StatusText.java b/platform/platform-api/src/com/intellij/util/ui/StatusText.java
index 3aa1dd0..84f1e75 100644
--- a/platform/platform-api/src/com/intellij/util/ui/StatusText.java
+++ b/platform/platform-api/src/com/intellij/util/ui/StatusText.java
@@ -52,7 +52,7 @@
public StatusText() {
myClickListener = new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (e.getButton() == MouseEvent.BUTTON1 && clickCount == 1) {
ActionListener actionListener = findActionListenerAt(e.getPoint());
if (actionListener != null) {
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 6d8b97d..97ecd97 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
@@ -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.
@@ -604,7 +604,7 @@
Long ts = (Long)tree.getClientProperty(TREE_UTIL_SCROLL_TIME_STAMP);
if (ts == null) {
- ts = new Long(0);
+ ts = 0L;
}
ts = ts.longValue() + 1;
tree.putClientProperty(TREE_UTIL_SCROLL_TIME_STAMP, ts);
diff --git a/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java b/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java
index f8e2f4c..c15d162 100644
--- a/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java
+++ b/platform/platform-api/src/org/jetbrains/ide/BinaryRequestHandler.java
@@ -16,7 +16,7 @@
package org.jetbrains.ide;
import com.intellij.openapi.extensions.ExtensionPointName;
-import io.netty.channel.ChannelInboundHandler;
+import io.netty.channel.ChannelHandler;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
@@ -30,5 +30,5 @@
*/
public abstract UUID getId();
- public abstract ChannelInboundHandler getInboundHandler();
+ public abstract ChannelHandler getInboundHandler();
}
\ No newline at end of file
diff --git a/platform/platform-impl/platform-impl.iml b/platform/platform-impl/platform-impl.iml
index 41aecc3..a0880c4 100644
--- a/platform/platform-impl/platform-impl.iml
+++ b/platform/platform-impl/platform-impl.iml
@@ -23,7 +23,6 @@
<orderEntry type="library" name="JavaHelp" level="project" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="library" name="jna" level="project" />
- <orderEntry type="library" name="http-client-3.1" level="project" />
<orderEntry type="library" name="winp" level="project" />
<orderEntry type="library" name="swingx" level="project" />
<orderEntry type="module" module-name="core-impl" exported="" />
@@ -40,6 +39,7 @@
<orderEntry type="library" name="jayatana" level="project" />
<orderEntry type="module" module-name="editor-ui-ex" exported="" />
<orderEntry type="library" name="gson" level="project" />
+ <orderEntry type="library" name="http-client" level="project" />
</component>
</module>
diff --git a/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java b/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java
index fd1c276..b020da2 100644
--- a/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java
+++ b/platform/platform-impl/src/com/intellij/application/options/OptionsConstants.java
@@ -21,8 +21,12 @@
*/
public class OptionsConstants {
+ public static final int MIN_EDITOR_FONT_SIZE = 4;
public static final int MAX_EDITOR_FONT_SIZE = 40;
public static final int DEFAULT_EDITOR_FONT_SIZE = 12;
+ public static final float MIN_EDITOR_LINE_SPACING = .6F;
+ public static final float MAX_EDITOR_LINE_SPACING = 3;
+ public static final float DEFAULT_EDITOR_LINE_SPACING = 1;
private OptionsConstants() {
}
diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroEditor.java b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroEditor.java
index 04f9af7..23e2990 100644
--- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroEditor.java
+++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroEditor.java
@@ -60,7 +60,7 @@
return component.getText();
}
- public void setText(JTextField component, String text) {
+ public void setText(JTextField component, @NotNull String text) {
final int len = text.length();
if (len > 0 && text.charAt(len - 1) == File.separatorChar) {
text = text.substring(0, len - 1);
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 c3be510..d8e4246 100644
--- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintManagerImpl.java
@@ -332,10 +332,9 @@
});
}
- final HintInfo info = new HintInfo(hint, flags, reviveOnEditorChange);
- myHintsStack.add(info);
+ myHintsStack.add(new HintInfo(hint, flags, reviveOnEditorChange));
if (timeout > 0) {
- Timer timer = UIUtil.createNamedTimer("Hint timeout",timeout, new ActionListener() {
+ Timer timer = UIUtil.createNamedTimer("Hint timeout", timeout, new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
hint.hide();
diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java
index ddb790b..0d3b085 100644
--- a/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java
+++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/HintUtil.java
@@ -90,6 +90,7 @@
@NotNull
public static HintHint getInformationHint() {
+ //noinspection UseJBColor
return new HintHint().setTextBg(INFORMATION_COLOR)
.setTextFg(UIUtil.isUnderDarcula() ? UIUtil.getLabelForeground() : Color.black)
.setFont(getBoldFont())
@@ -97,12 +98,14 @@
}
public static CompoundBorder createHintBorder() {
+ //noinspection UseJBColor
return BorderFactory.createCompoundBorder(
new ColoredSideBorder(Color.white, Color.white, Color.gray, Color.gray, 1),
BorderFactory.createEmptyBorder(2, 2, 2, 2)
);
}
+ @NotNull
public static JComponent createInformationLabel(SimpleColoredText text) {
return createInformationLabel(text, null);
}
@@ -127,19 +130,21 @@
return label;
}
- public static JComponent createInformationLabel(final SimpleColoredText text, final Icon icon) {
- SimpleColoredComponent highlighted = new SimpleColoredComponent();
+ @NotNull
+ public static SimpleColoredComponent createInformationComponent() {
+ SimpleColoredComponent component = new SimpleColoredComponent();
+ component.setBackground(INFORMATION_COLOR);
+ component.setForeground(JBColor.foreground());
+ component.setFont(getBoldFont());
+ return component;
+ }
- highlighted.setIcon(icon);
- highlighted.setBackground(INFORMATION_COLOR);
- highlighted.setForeground(JBColor.foreground());
- highlighted.setFont(getBoldFont());
- text.appendToComponent(highlighted);
-
- HintLabel label = new HintLabel();
- label.setText(highlighted);
-
- return label;
+ @NotNull
+ public static JComponent createInformationLabel(@NotNull SimpleColoredText text, @Nullable Icon icon) {
+ SimpleColoredComponent component = createInformationComponent();
+ component.setIcon(icon);
+ text.appendToComponent(component);
+ return new HintLabel(component);
}
public static JComponent createErrorLabel(String text) {
@@ -193,7 +198,6 @@
}
private static class HintLabel extends JPanel {
-
private JEditorPane myPane;
private SimpleColoredComponent myColored;
private JLabel myIcon;
@@ -202,8 +206,12 @@
setLayout(new BorderLayout());
}
+ private HintLabel(@NotNull SimpleColoredComponent component) {
+ this();
+ setText(component);
+ }
- public void setText(SimpleColoredComponent colored) {
+ public void setText(@NotNull SimpleColoredComponent colored) {
clearText();
myColored = colored;
diff --git a/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java b/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java
index f2bfbcf..bcace21 100644
--- a/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.java
+++ b/platform/platform-impl/src/com/intellij/codeInsight/hint/LineTooltipRenderer.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.
@@ -30,6 +30,7 @@
import com.intellij.util.ui.Html;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.update.ComparableObject;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -45,7 +46,6 @@
* @author cdr
*/
public class LineTooltipRenderer extends ComparableObject.Impl implements TooltipRenderer {
- @NonNls protected static final String BORDER_LINE = "<hr size=1 noshade>";
@NonNls protected String myText;
@@ -323,9 +323,9 @@
else {
String html1 = UIUtil.getHtmlBody(myText);
String html2 = UIUtil.getHtmlBody(text);
- newBody = html1 + BORDER_LINE + html2;
+ newBody = html1 + UIUtil.BORDER_LINE + html2;
}
- myText = "<html><body>" + newBody + "</body></html>";
+ myText = XmlStringUtil.wrapInHtml(newBody);
}
public String getText() {
diff --git a/platform/platform-impl/src/com/intellij/concurrency/ApplierCompleter.java b/platform/platform-impl/src/com/intellij/concurrency/ApplierCompleter.java
index 1644e54..4db4b3c 100644
--- a/platform/platform-impl/src/com/intellij/concurrency/ApplierCompleter.java
+++ b/platform/platform-impl/src/com/intellij/concurrency/ApplierCompleter.java
@@ -219,7 +219,7 @@
}
}
});
- assert task.failedSubTasks == null;
+ assert task.failedSubTasks == null : task.failedSubTasks;
}
return result[0];
}
diff --git a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java
index d87b9ae..cface15 100644
--- a/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.java
+++ b/platform/platform-impl/src/com/intellij/concurrency/JobLauncherImpl.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,7 +19,7 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.util.ProgressIndicatorBase;
+import com.intellij.openapi.progress.util.AbstractProgressIndicatorBase;
import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
@@ -120,7 +120,7 @@
@NotNull final Processor<T> thingProcessor) throws ProcessCanceledException {
if (things.isEmpty()) return true;
// supply our own indicator even if we haven't given one - to support cancellation
- final ProgressIndicator wrapper = progress == null ? new ProgressIndicatorBase() : new SensitiveProgressWrapper(progress);
+ final ProgressIndicator wrapper = progress == null ? new AbstractProgressIndicatorBase() : new SensitiveProgressWrapper(progress);
if (things.size() <= 1 || JobSchedulerImpl.CORES_COUNT <= CORES_FORK_THRESHOLD) {
final AtomicBoolean result = new AtomicBoolean(true);
@@ -185,7 +185,6 @@
@Override
protected void setRawResult(Void value) {
-
}
@Override
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 3470d77..9ea8047 100644
--- a/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java
+++ b/platform/platform-impl/src/com/intellij/designer/propertyTable/PropertyTable.java
@@ -25,6 +25,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
@@ -308,7 +309,13 @@
}
public void update(@NotNull List<? extends PropertiesContainer> containers, @Nullable Property initialSelection) {
- finishEditing();
+ update(containers, initialSelection, true);
+ }
+
+ private void update(@NotNull List<? extends PropertiesContainer> containers, @Nullable Property initialSelection, boolean finishEditing) {
+ if (finishEditing) {
+ finishEditing();
+ }
if (mySkipUpdate) {
return;
@@ -316,7 +323,7 @@
mySkipUpdate = true;
try {
- if (isEditing()) {
+ if (finishEditing && isEditing()) {
cellEditor.stopCellEditing();
}
@@ -841,7 +848,7 @@
if (isSetValue) {
if (property.needRefreshPropertyList() || needRefresh[0]) {
- update();
+ update(myContainers, null, false);
}
else {
myModel.fireTableRowsUpdated(row, row);
@@ -1107,7 +1114,9 @@
if (setValueAtRow(editingRow, value)) {
if (!continueEditing) {
- tableCellEditor.stopCellEditing();
+ PropertyEditor editor = myProperties.get(editingRow).getEditor();
+ editor.removePropertyEditorListener(myPropertyEditorListener);
+ removeEditor();
}
}
else if (closeEditorOnError) {
@@ -1141,8 +1150,7 @@
JComponent component = myEditor.getComponent(getCurrentComponent(), getPropertyContext(), getValue((Property)value), null);
if (component instanceof JComboBox) {
- component.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
- component.putClientProperty("tableCellEditor", this);
+ ComboBox.registerTableCellEditor((JComboBox)component, this);
}
else if (component instanceof JCheckBox) {
component.putClientProperty("JComponent.sizeVariant", UIUtil.isUnderAquaLookAndFeel() ? "small" : null);
diff --git a/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java b/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java
index 984eb24..145f2a9 100644
--- a/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java
+++ b/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/BooleanEditor.java
@@ -40,7 +40,7 @@
myCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
if (!myInsideChange) {
- fireValueCommitted(true, false);
+ fireValueCommitted(false, true);
}
}
});
diff --git a/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/TextEditor.java b/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/TextEditor.java
index 6dbe405..c6ddc0a 100644
--- a/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/TextEditor.java
+++ b/platform/platform-impl/src/com/intellij/designer/propertyTable/editors/TextEditor.java
@@ -40,7 +40,7 @@
myTextField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- fireValueCommitted(true, false);
+ fireValueCommitted(true, true);
}
});
myTextField.getDocument().addDocumentListener(
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/AttachmentFactory.java b/platform/platform-impl/src/com/intellij/diagnostic/AttachmentFactory.java
index 0fb4baf..9e107ed 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/AttachmentFactory.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/AttachmentFactory.java
@@ -4,9 +4,11 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
+import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
@@ -26,6 +28,20 @@
file.getFileType().isBinary() ? "File is binary" : LoadTextUtil.loadText(file).toString());
}
+ public static Attachment createAttachment(@NotNull File file, boolean isBinary) {
+ byte[] bytes = getBytes(file);
+ return new Attachment(file.getPath(), bytes, isBinary ? "File is binary" : new String(bytes));
+ }
+
+ private static byte[] getBytes(File file) {
+ try {
+ return FileUtil.loadFileBytes(file);
+ }
+ catch (IOException e) {
+ return Attachment.getBytes(MessageFormat.format(ERROR_MESSAGE_PATTERN, e.getMessage()));
+ }
+ }
+
private static byte[] getBytes(VirtualFile file) {
try {
return file.contentsToByteArray();
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/DevelopersLoader.java b/platform/platform-impl/src/com/intellij/diagnostic/DevelopersLoader.java
index 6b3eff0..b1a0281 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/DevelopersLoader.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/DevelopersLoader.java
@@ -16,9 +16,8 @@
package com.intellij.diagnostic;
import com.intellij.openapi.progress.ProgressIndicator;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.methods.GetMethod;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import org.apache.http.client.fluent.Request;
import java.io.BufferedReader;
import java.io.IOException;
@@ -29,7 +28,6 @@
class DevelopersLoader {
private static final String DEVELOPERS_LIST_URL = "http://ea-engine.labs.intellij.net/data?category=developers";
- private static final String DATA_CHARSET = "utf-8";
public static final int TIMEOUT = 1000;
private DevelopersLoader() {
@@ -38,33 +36,24 @@
public static Collection<Developer> fetchDevelopers(ProgressIndicator indicator) throws IOException {
List<Developer> developers = new LinkedList<Developer>();
developers.add(Developer.NULL);
-
- HttpClient client = new HttpClient();
- client.getHttpConnectionManager().getParams().setConnectionTimeout(TIMEOUT);
- HttpMethod method = new GetMethod(DEVELOPERS_LIST_URL);
-
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(Request.Get(DEVELOPERS_LIST_URL).connectTimeout(TIMEOUT).execute().returnContent().asStream(),
+ CharsetToolkit.UTF8_CHARSET));
try {
- client.executeMethod(method);
-
- BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream(), DATA_CHARSET));
-
- try {
- while (true) {
- String line = reader.readLine();
- if (line == null) break;
- int i = line.indexOf('\t');
- if (i == -1) throw new IOException("Protocol error");
- int id = Integer.parseInt(line.substring(0, i));
- String name = line.substring(i + 1);
- developers.add(new Developer(id, name));
- indicator.checkCanceled();
- }
- return developers;
- } finally {
- reader.close();
+ while (true) {
+ String line = reader.readLine();
+ if (line == null) break;
+ int i = line.indexOf('\t');
+ if (i == -1) throw new IOException("Protocol error");
+ int id = Integer.parseInt(line.substring(0, i));
+ String name = line.substring(i + 1);
+ developers.add(new Developer(id, name));
+ indicator.checkCanceled();
}
- } finally {
- method.releaseConnection();
+ return developers;
+ }
+ finally {
+ reader.close();
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/DiagnosticBundle.java b/platform/platform-impl/src/com/intellij/diagnostic/DiagnosticBundle.java
index 3e0b118..71e7829 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/DiagnosticBundle.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/DiagnosticBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author yole
*/
public class DiagnosticBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.DiagnosticBundle";
private DiagnosticBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java b/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java
index 891984f..2fbb2d1 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/DialogAppender.java
@@ -103,7 +103,7 @@
Throwable throwable = info.getThrowable();
//noinspection ThrowableResultOfMethodCallIgnored
Throwable rootCause = ExceptionUtil.getRootCause(throwable);
- ideaEvent = rootCause instanceof LogEventException ? ((LogEventException)rootCause).getLogMessage() :
+ ideaEvent = rootCause instanceof LogEventException ? ((LogEventException)rootCause).getLogMessage() :
new IdeaLoggingEvent(message == null ? "<null> " : message.toString(), throwable);
}
for (int i = errorLoggers.length - 1; i >= 0; i--) {
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java
index 5eabd41..e430f9f 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/ITNReporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -29,7 +29,6 @@
import com.intellij.notification.NotificationType;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.ErrorReportSubmitter;
import com.intellij.openapi.diagnostic.IdeaLoggingEvent;
@@ -198,7 +197,7 @@
showMessageDialog(parentComponent, project, message, CommonBundle.getWarningTitle(), Messages.getWarningIcon());
callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
}
- else if (showYesNoDialog(parentComponent, project, msg, ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != 0) {
+ else if (showYesNoDialog(parentComponent, project, msg, ReportMessages.ERROR_REPORT, Messages.getErrorIcon()) != Messages.YES) {
callback.consume(new SubmittedReportInfo(null, "0", SubmittedReportInfo.SubmissionStatus.FAILED));
}
else {
@@ -234,6 +233,7 @@
}
}
+ @Messages.YesNoResult
private static int showYesNoDialog(Component parentComponent, Project project, String message, String title, Icon icon) {
if (parentComponent.isShowing()) {
return Messages.showYesNoDialog(parentComponent, message, title, icon);
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
index f848013..06627dc 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeErrorsDialog.java
@@ -897,11 +897,11 @@
public void update() {
AbstractMessage logMessage = getSelectedMessage();
- if (logMessage != null && !logMessage.isSubmitted()) {
+ if (logMessage != null) {
ErrorReportSubmitter submitter = getSubmitter(logMessage.getThrowable());
if (submitter != null) {
putValue(NAME, submitter.getReportActionText());
- setEnabled(true);
+ setEnabled(!logMessage.isSubmitted());
return;
}
}
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/IdeFatalErrorsIcon.java b/platform/platform-impl/src/com/intellij/diagnostic/IdeFatalErrorsIcon.java
index 5ff6aac..3371ed2 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/IdeFatalErrorsIcon.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/IdeFatalErrorsIcon.java
@@ -4,6 +4,7 @@
import com.intellij.icons.AllIcons;
import com.intellij.ui.ClickListener;
import com.intellij.ui.LayeredIcon;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -31,7 +32,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myState != State.NoErrors) {
myListener.actionPerformed(null);
return true;
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java
index 9548e7e..092c346 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/JetBrainsAccountDialog.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.ClickListener;
import com.intellij.util.net.HTTPProxySettingsDialog;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -78,7 +79,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
HTTPProxySettingsDialog settingsDialog = new HTTPProxySettingsDialog ();
settingsDialog.pack();
settingsDialog.show();
@@ -92,8 +93,8 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
- BrowserUtil.launchBrowser("http://account.jetbrains.com");
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
+ BrowserUtil.browse("http://account.jetbrains.com");
return true;
}
}.installOn(myCreateAccountLabel);
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java b/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java
index 74206ed..8879838 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/SubmitPerformanceReportAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -93,7 +93,7 @@
int rc = Messages.showYesNoDialog(project, "The performance report has been saved to\n" + reportPath +
"\n\nWould you like to submit it to JetBrains?", MESSAGE_TITLE,
Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
ProgressManager.getInstance().run(new Task.Backgroundable(project, "Uploading Performance Report") {
public void run(@NotNull final ProgressIndicator indicator) {
final String error = uploadFileToFTP(reportPath, "ftp.intellij.net", ".uploads", indicator);
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.form b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.form
index 5f9377d..20e24dc 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.form
+++ b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.form
@@ -10,25 +10,27 @@
<size top="5" left="5" bottom="5" right="5"/>
</border>
<children>
- <component id="c3482" class="com.intellij.openapi.ui.LabeledComponent" binding="myErrorComponent">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <componentClass value="javax.swing.JTextArea"/>
- <text value="&Error message"/>
- </properties>
- </component>
<vspacer id="9872d">
<constraints>
<grid row="1" 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="c37ed" form-file="com/intellij/diagnostic/errordialog/LabeledTextComponent.form" binding="myCommentsArea">
+ <grid id="cdd81" binding="myErrorPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="0" 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>
+ <grid id="8e8fc" binding="myCommentsPanel" layout-manager="BorderLayout" hgap="0" vgap="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>
- </nested-form>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
</children>
</grid>
</form>
diff --git a/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.java b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.java
index feb4e6a..3ef12d5 100644
--- a/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.java
+++ b/platform/platform-impl/src/com/intellij/diagnostic/errordialog/CommentsTabForm.java
@@ -1,13 +1,10 @@
package com.intellij.diagnostic.errordialog;
import com.intellij.diagnostic.DiagnosticBundle;
-import com.intellij.diagnostic.IdeErrorsDialog;
-import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
-import java.awt.*;
/**
* @author ksafonov
@@ -15,14 +12,28 @@
public class CommentsTabForm {
private LabeledTextComponent myCommentsArea;
private JPanel myContentPane;
- private LabeledComponent<JTextArea> myErrorComponent;
+ private LabeledTextComponent myErrorComponent;
+ private JPanel myErrorPanel;
+ private JPanel myCommentsPanel;
public CommentsTabForm() {
+ myErrorComponent = new LabeledTextComponent();
+ myErrorComponent.setTitle(DiagnosticBundle.message("error.dialog.error.prompt"));
+
+ myCommentsArea = new LabeledTextComponent();
myCommentsArea.setTitle(DiagnosticBundle.message("error.dialog.comment.prompt"));
- myErrorComponent.getComponent().setPreferredSize(new Dimension(IdeErrorsDialog.COMPONENTS_WIDTH, -1));
- myErrorComponent.getComponent().setEditable(false);
- myErrorComponent.getComponent().setBackground(UIUtil.getTextFieldBackground());
- myErrorComponent.getComponent().setBorder(IdeBorderFactory.createBorder());
+
+ JTextArea errorArea = myErrorComponent.getTextComponent();
+ //errorArea.setPreferredSize(new Dimension(IdeErrorsDialog.COMPONENTS_WIDTH, -1));
+ errorArea.setLineWrap(true);
+ errorArea.setEditable(false);
+ errorArea.setBackground(UIUtil.getTextFieldBackground());
+ errorArea.setBorder(IdeBorderFactory.createBorder());
+
+ myCommentsArea.getTextComponent().setLineWrap(true);
+
+ myErrorPanel.add(myErrorComponent.getContentPane());
+ myCommentsPanel.add(myCommentsArea.getContentPane());
}
public JPanel getContentPane() {
@@ -30,8 +41,8 @@
}
public void setErrorText(String s) {
- myErrorComponent.getComponent().setText(s);
- myErrorComponent.getComponent().setCaretPosition(0);
+ myErrorComponent.getTextComponent().setText(s);
+ myErrorComponent.getTextComponent().setCaretPosition(0);
}
public void setCommentText(String s) {
diff --git a/platform/platform-impl/src/com/intellij/execution/ExecutableValidator.java b/platform/platform-impl/src/com/intellij/execution/ExecutableValidator.java
index 7dd67a0..79e76f0 100644
--- a/platform/platform-impl/src/com/intellij/execution/ExecutableValidator.java
+++ b/platform/platform-impl/src/com/intellij/execution/ExecutableValidator.java
@@ -46,7 +46,7 @@
private static final Logger LOG = Logger.getInstance(ExecutableValidator.class);
- private final NotificationGroup myNotificationGroup = new NotificationGroup("External Executable Critical Failures",
+ private static final NotificationGroup ourNotificationGroup = new NotificationGroup("External Executable Critical Failures",
STICKY_BALLOON, true);
@NotNull protected final Project myProject;
@NotNull private final NotificationsManager myNotificationManager;
@@ -200,7 +200,7 @@
private class ExecutableNotValidNotification extends Notification {
private ExecutableNotValidNotification() {
- super(myNotificationGroup.getDisplayId(), "", prepareDescription(), NotificationType.ERROR, new NotificationListener.Adapter() {
+ super(ourNotificationGroup.getDisplayId(), "", prepareDescription(), NotificationType.ERROR, new NotificationListener.Adapter() {
@Override
protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
showSettingsAndExpireIfFixed(notification);
diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorCopyAction.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorCopyAction.java
deleted file mode 100644
index 88f6bea..0000000
--- a/platform/platform-impl/src/com/intellij/execution/impl/EditorCopyAction.java
+++ /dev/null
@@ -1,59 +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 com.intellij.execution.impl;
-
-import com.intellij.execution.ExecutionBundle;
-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.project.DumbAwareAction;
-
-/**
- * @author peter
- */
-public class EditorCopyAction extends DumbAwareAction {
-
- @Override
- public void update(AnActionEvent e) {
- final boolean enabled = isEnabled(e);
- e.getPresentation().setEnabled(enabled);
- e.getPresentation().setVisible(enabled);
-
- final Editor editor = e.getData(CommonDataKeys.EDITOR);
- e.getPresentation().setText(editor != null && editor.getSelectionModel().hasSelection()
- ? ExecutionBundle.message("copy.selected.content.action.name")
- : ExecutionBundle.message("copy.content.action.name"));
- }
-
- protected boolean isEnabled(AnActionEvent e) {
- return e.getData(CommonDataKeys.EDITOR) != null;
- }
-
- public void actionPerformed(final AnActionEvent e) {
- final Editor editor = e.getData(CommonDataKeys.EDITOR);
- assert editor != null;
- if (editor.getSelectionModel().hasSelection()) {
- editor.getSelectionModel().copySelectionToClipboard();
- }
- else {
- editor.getSelectionModel().setSelection(0, editor.getDocument().getTextLength());
- editor.getSelectionModel().copySelectionToClipboard();
- editor.getSelectionModel().removeSelection();
- }
- }
-}
-
diff --git a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java
index dfb004f..1973cb3 100644
--- a/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java
+++ b/platform/platform-impl/src/com/intellij/execution/impl/EditorHyperlinkSupport.java
@@ -18,6 +18,7 @@
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.FilterMixin;
import com.intellij.execution.filters.HyperlinkInfo;
+import com.intellij.execution.filters.HyperlinkInfoBase;
import com.intellij.ide.OccurenceNavigator;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -36,6 +37,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.pom.NavigatableAdapter;
+import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.BeforeAfter;
import com.intellij.util.Consumer;
import com.intellij.util.SmartList;
@@ -87,7 +89,12 @@
if (range != null) {
final HyperlinkInfo info = myHighlighterToMessageInfoMap.get(range);
if (info != null) {
- info.navigate(project);
+ if (info instanceof HyperlinkInfoBase) {
+ ((HyperlinkInfoBase)info).navigate(project, new RelativePoint(mouseEvent));
+ }
+ else {
+ info.navigate(project);
+ }
linkFollowed(editor, getHyperlinks().keySet(), range);
}
}
@@ -322,6 +329,10 @@
Collection<RangeHighlighter> sortedHighlighters,
final int delta,
final Consumer<RangeHighlighter> action) {
+ if (sortedHighlighters.isEmpty()) {
+ return null;
+ }
+
final List<RangeHighlighter> ranges = new ArrayList<RangeHighlighter>(sortedHighlighters);
int i;
for (i = 0; i < ranges.size(); i++) {
@@ -330,8 +341,8 @@
break;
}
}
- int initial = i > 0 ? i % ranges.size() : 0;
- int newIndex = initial;
+ i = i % ranges.size();
+ int newIndex = i;
while (newIndex < ranges.size() && newIndex >= 0) {
newIndex = (newIndex + delta + ranges.size()) % ranges.size();
final RangeHighlighter next = ranges.get(newIndex);
@@ -343,7 +354,7 @@
}
}, newIndex == -1 ? -1 : newIndex + 1, ranges.size());
}
- if (newIndex == initial) {
+ if (newIndex == i) {
break; // cycled through everything, found no next/prev hyperlink
}
}
diff --git a/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java b/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java
index b62778a..c0f4e93 100644
--- a/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java
+++ b/platform/platform-impl/src/com/intellij/execution/process/KillableColoredProcessHandler.java
@@ -79,8 +79,8 @@
@Override
protected void destroyProcessImpl() {
- // call super.closeStreams() after process termination, because
- // otherwise process's output stream can also be closed for no reason
+ // Don't close streams, because a process may survive graceful termination.
+ // Streams will be closed after the process is really terminated.
try {
myProcess.getOutputStream().flush();
}
diff --git a/platform/platform-impl/src/com/intellij/featureStatistics/actions/ShowFeatureUsageStatisticsDialog.java b/platform/platform-impl/src/com/intellij/featureStatistics/actions/ShowFeatureUsageStatisticsDialog.java
index 7922b18..2c328ff 100644
--- a/platform/platform-impl/src/com/intellij/featureStatistics/actions/ShowFeatureUsageStatisticsDialog.java
+++ b/platform/platform-impl/src/com/intellij/featureStatistics/actions/ShowFeatureUsageStatisticsDialog.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 @@
import com.intellij.util.ui.ColumnInfo;
import com.intellij.util.ui.ListTableModel;
import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -181,7 +182,7 @@
" (~" + fstats.invocations / fstats.dayCount + " per working day)";
}
- controlsPanel.add(new JLabel("<html><body>" + labelText + "</body></html>"), BorderLayout.NORTH);
+ controlsPanel.add(new JLabel(XmlStringUtil.wrapInHtml(labelText)), BorderLayout.NORTH);
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.add(controlsPanel, BorderLayout.NORTH);
diff --git a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java
index dbfd012..ac197b1 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java
@@ -64,7 +64,7 @@
}
if (myHelpSet == null) {
- BrowserUtil.launchBrowser(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id);
+ BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id);
return;
}
diff --git a/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java b/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java
index 53ef590..976da51 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/IdeaHelpContentViewUI.java
@@ -45,7 +45,7 @@
protected void linkActivated(URL u){
String url=u.toExternalForm();
if(url.startsWith("http") || url.startsWith("ftp")){
- BrowserUtil.launchBrowser(url);
+ BrowserUtil.browse(url);
} else{
super.linkActivated(u);
}
diff --git a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
index 2728c45..90d633f 100644
--- a/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.java
+++ b/platform/platform-impl/src/com/intellij/help/impl/MacHelpUtil.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.
@@ -41,6 +41,7 @@
}
static boolean isApplicable() {
- return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isCidr() && !PlatformUtils.isCommunity();
+ return SystemInfo.isMac && Registry.is("ide.mac.show.native.help", false) && !PlatformUtils.isCidr() && !PlatformUtils
+ .isIdeaCommunity();
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/BrowserSettings.java b/platform/platform-impl/src/com/intellij/ide/BrowserSettings.java
deleted file mode 100644
index 63545bb..0000000
--- a/platform/platform-impl/src/com/intellij/ide/BrowserSettings.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.ide;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.SearchableConfigurable;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-/**
- * @author spleaner
- */
-public class BrowserSettings implements Configurable, SearchableConfigurable {
- private BrowserSettingsPanel mySettingsPanel;
-
- @NotNull
- public String getId() {
- return getHelpTopic();
- }
-
- public Runnable enableSearch(final String option) {
- return null;
- }
-
- @Nls
- public String getDisplayName() {
- return IdeBundle.message("browsers.settings");
- }
-
- public String getHelpTopic() {
- return "reference.settings.ide.settings.web.browsers";
- }
-
- public JComponent createComponent() {
- if (mySettingsPanel == null) {
- mySettingsPanel = new BrowserSettingsPanel();
- }
-
- return mySettingsPanel;
- }
-
- public boolean isModified() {
- return mySettingsPanel != null && mySettingsPanel.isModified();
- }
-
- public void apply() throws ConfigurationException {
- if (mySettingsPanel != null) {
- mySettingsPanel.apply();
- }
- }
-
- public void reset() {
- if (mySettingsPanel != null) {
- mySettingsPanel.reset();
- }
- }
-
- public void disposeUIResources() {
- if (mySettingsPanel != null) {
- mySettingsPanel.disposeUIResources();
- mySettingsPanel = null;
- }
- }
-
-}
diff --git a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java b/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java
deleted file mode 100644
index 0a66235..0000000
--- a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsPanel.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide;
-
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.options.ex.ConfigurableWrapper;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.IdeBorderFactory;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.List;
-
-/**
- * @author spleaner
- */
-public class BrowserSettingsPanel extends JPanel {
- private final JRadioButton myUseDefaultBrowser;
- private final JRadioButton myUseAlternativeBrowser;
- private final List<BrowserSettingsProvider> mySettingsProviders;
- private final TextFieldWithBrowseButton myBrowserPathField;
- private final JCheckBox myConfirmExtractFiles;
- private final JButton myClearExtractedFiles;
-
- public BrowserSettingsPanel() {
- setLayout(new BorderLayout());
-
- final JPanel outerPanel = new JPanel();
- outerPanel.setLayout(new BoxLayout(outerPanel, BoxLayout.Y_AXIS));
-
- // generic system browser
- final JPanel genericPanel = new JPanel();
- genericPanel.setBorder(IdeBorderFactory.createTitledBorder("Default Web Browser", true));
- genericPanel.setLayout(new BoxLayout(genericPanel, BoxLayout.Y_AXIS));
- final JPanel innerPanel1 = new JPanel(new BorderLayout());
-
- final ButtonGroup group = new ButtonGroup();
- myUseDefaultBrowser = new JRadioButton("Use system default browser");
- group.add(myUseDefaultBrowser);
-
- innerPanel1.add(myUseDefaultBrowser, BorderLayout.WEST);
- genericPanel.add(innerPanel1);
- final JPanel innerPanel2 = new JPanel(new BorderLayout());
-
- myUseAlternativeBrowser = new JRadioButton("Use");
- group.add(myUseAlternativeBrowser);
-
- innerPanel2.add(myUseAlternativeBrowser, BorderLayout.WEST);
- myBrowserPathField = new TextFieldWithBrowseButton();
- innerPanel2.add(myBrowserPathField, BorderLayout.CENTER);
- genericPanel.add(innerPanel2);
-
- JPanel innerPanel3 = new JPanel(new BorderLayout());
- myConfirmExtractFiles = new JCheckBox("Show confirmation before extracting files");
- myClearExtractedFiles = new JButton("Clear extracted files");
- myClearExtractedFiles.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- BrowserUtil.clearExtractedFiles();
- }
- });
- innerPanel3.add(myConfirmExtractFiles, BorderLayout.CENTER);
- innerPanel3.add(myClearExtractedFiles, BorderLayout.EAST);
- genericPanel.add(innerPanel3);
-
- outerPanel.add(genericPanel);
-
- FileChooserDescriptor descriptor = SystemInfo.isMac ?
- new FileChooserDescriptor(false, true, false, false, false, false) {
- @Override
- public boolean isFileSelectable(VirtualFile file) {
- return file.getName().endsWith(".app");
- }
- } : FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
- myBrowserPathField.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null, descriptor);
-
- if (BrowserUtil.canStartDefaultBrowser()) {
- ActionListener actionListener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- updateBrowserField();
- }
- };
- myUseDefaultBrowser.addActionListener(actionListener);
- myUseAlternativeBrowser.addActionListener(actionListener);
- }
- else {
- myUseDefaultBrowser.setVisible(false);
- myUseAlternativeBrowser.setVisible(false);
- }
-
- mySettingsProviders = ConfigurableWrapper.createConfigurables(BrowserSettingsProviderEP.EP_NAME);
- for (BrowserSettingsProvider settingsProvider : mySettingsProviders) {
- outerPanel.add(settingsProvider.createComponent());
- }
-
- add(outerPanel, BorderLayout.NORTH);
- }
-
- public boolean isModified() {
- boolean isModified = false;
- GeneralSettings settings = GeneralSettings.getInstance();
- isModified |= !Comparing.strEqual(settings.getBrowserPath(), myBrowserPathField.getText());
- isModified |= settings.isUseDefaultBrowser() != myUseDefaultBrowser.isSelected();
- isModified |= settings.isConfirmExtractFiles() != myConfirmExtractFiles.isSelected();
-
- if (isModified) {
- return true;
- }
-
- for (BrowserSettingsProvider provider : mySettingsProviders) {
- if (provider.isModified()) {
- return true;
- }
- }
-
- return false;
- }
-
- private void updateBrowserField() {
- if (!BrowserUtil.canStartDefaultBrowser()) {
- return;
- }
-
- myBrowserPathField.getTextField().setEnabled(myUseAlternativeBrowser.isSelected());
- myBrowserPathField.getButton().setEnabled(myUseAlternativeBrowser.isSelected());
- }
-
- public void apply() throws ConfigurationException {
- GeneralSettings settings = GeneralSettings.getInstance();
-
- settings.setBrowserPath(myBrowserPathField.getText());
- settings.setUseDefaultBrowser(myUseDefaultBrowser.isSelected());
- settings.setConfirmExtractFiles(myConfirmExtractFiles.isSelected());
-
- for (BrowserSettingsProvider provider : mySettingsProviders) {
- provider.apply();
- }
- }
-
- public void reset() {
- GeneralSettings settings = GeneralSettings.getInstance();
- myBrowserPathField.setText(settings.getBrowserPath());
-
- if (settings.isUseDefaultBrowser()) {
- myUseDefaultBrowser.setSelected(true);
- }
- else {
- myUseAlternativeBrowser.setSelected(true);
- }
- myConfirmExtractFiles.setSelected(settings.isConfirmExtractFiles());
-
- updateBrowserField();
-
- for (BrowserSettingsProvider provider : mySettingsProviders) {
- provider.reset();
- }
- }
-
- public void disposeUIResources() {
- for (BrowserSettingsProvider provider : mySettingsProviders) {
- provider.disposeUIResources();
- }
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java b/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java
deleted file mode 100644
index 7c5f61f..0000000
--- a/platform/platform-impl/src/com/intellij/ide/BrowserSettingsProviderEP.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.ide;
-
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.options.ConfigurableEP;
-
-/**
- * @author nik
- */
-public class BrowserSettingsProviderEP extends ConfigurableEP<BrowserSettingsProvider> {
- public static ExtensionPointName<BrowserSettingsProviderEP> EP_NAME = ExtensionPointName.create("com.intellij.browserSettingsProvider");
-}
diff --git a/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java b/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java
index d46b868..562afc3 100644
--- a/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.java
+++ b/platform/platform-impl/src/com/intellij/ide/ClipboardSynchronizer.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.
@@ -26,7 +26,6 @@
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.sun.jna.IntegerType;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import sun.awt.datatransfer.DataTransferer;
@@ -56,10 +55,6 @@
public class ClipboardSynchronizer implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.ClipboardSynchronizer");
- @NonNls private static final String DATA_TRANSFER_TIMEOUT_PROPERTY = "sun.awt.datatransfer.timeout";
- @NonNls private static final String LONG_TIMEOUT = "2000";
- @NonNls private static final String SHORT_TIMEOUT = "100";
-
private final ClipboardHandler myClipboardHandler;
public static ClipboardSynchronizer getInstance() {
@@ -97,9 +92,9 @@
return "ClipboardSynchronizer";
}
- public boolean isDataFlavorAvailable(@NotNull final DataFlavor dataFlavor) {
+ public boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors) {
try {
- return myClipboardHandler.isDataFlavorAvailable(dataFlavor);
+ return myClipboardHandler.areDataFlavorsAvailable(flavors);
}
catch (IllegalStateException e) {
LOG.info(e);
@@ -128,14 +123,18 @@
private static class ClipboardHandler {
- public void init() {
- }
+ public void init() { }
- public void dispose() {
- }
+ public void dispose() { }
- public boolean isDataFlavorAvailable(@NotNull final DataFlavor dataFlavor) {
- return Toolkit.getDefaultToolkit().getSystemClipboard().isDataFlavorAvailable(dataFlavor);
+ public boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors) {
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ for (DataFlavor flavor : flavors) {
+ if (clipboard.isDataFlavorAvailable(flavor)) {
+ return true;
+ }
+ }
+ return false;
}
@Nullable
@@ -197,9 +196,9 @@
}
@Override
- public boolean isDataFlavorAvailable(@NotNull final DataFlavor dataFlavor) {
- final Transferable contents = getContents();
- return contents != null && contents.isDataFlavorSupported(dataFlavor);
+ public boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors) {
+ Transferable contents = getContents();
+ return contents != null && ClipboardSynchronizer.areDataFlavorsAvailable(contents, flavors);
}
@Override
@@ -251,7 +250,7 @@
}
@Nullable
- public static Transferable getContentsSafe() {
+ private static Transferable getContentsSafe() {
final Ref<Transferable> result = new Ref<Transferable>();
Foundation.executeOnMainThread(new Runnable() {
@@ -308,6 +307,9 @@
private static class XWinClipboardHandler extends ClipboardHandler {
+ private static final String DATA_TRANSFER_TIMEOUT_PROPERTY = "sun.awt.datatransfer.timeout";
+ private static final String LONG_TIMEOUT = "2000";
+ private static final String SHORT_TIMEOUT = "100";
private static final FlavorTable FLAVOR_MAP = (FlavorTable)SystemFlavorMap.getDefaultFlavorMap();
private volatile Transferable myCurrentContent = null;
@@ -325,19 +327,19 @@
}
@Override
- public boolean isDataFlavorAvailable(@NotNull final DataFlavor dataFlavor) {
- final Transferable currentContent = myCurrentContent;
+ public boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors) {
+ Transferable currentContent = myCurrentContent;
if (currentContent != null) {
- return currentContent.isDataFlavorSupported(dataFlavor);
+ return ClipboardSynchronizer.areDataFlavorsAvailable(currentContent, flavors);
}
try {
- final Collection<DataFlavor> contents = checkContentsQuick();
+ Collection<DataFlavor> contents = checkContentsQuick();
if (contents != null) {
- return contents.contains(dataFlavor);
+ return ClipboardSynchronizer.areDataFlavorsAvailable(contents, flavors);
}
- return super.isDataFlavorAvailable(dataFlavor);
+ return super.areDataFlavorsAvailable(flavors);
}
catch (NullPointerException e) {
LOG.warn("Java bug #6322854", e);
@@ -438,9 +440,9 @@
private volatile Transferable myContent = null;
@Override
- public boolean isDataFlavorAvailable(@NotNull final DataFlavor dataFlavor) {
- final Transferable content = myContent;
- return content != null && content.isDataFlavorSupported(dataFlavor);
+ public boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors) {
+ Transferable content = myContent;
+ return content != null && ClipboardSynchronizer.areDataFlavorsAvailable(content, flavors);
}
@Override
@@ -458,4 +460,23 @@
myContent = null;
}
}
+
+
+ private static boolean areDataFlavorsAvailable(Transferable contents, DataFlavor... flavors) {
+ for (DataFlavor flavor : flavors) {
+ if (contents.isDataFlavorSupported(flavor)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean areDataFlavorsAvailable(Collection<DataFlavor> contents, DataFlavor... flavors) {
+ for (DataFlavor flavor : flavors) {
+ if (contents.contains(flavor)) {
+ return true;
+ }
+ }
+ return false;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/ide/CopyPasteManagerEx.java b/platform/platform-impl/src/com/intellij/ide/CopyPasteManagerEx.java
index d6f998d..d4bd50a 100644
--- a/platform/platform-impl/src/com/intellij/ide/CopyPasteManagerEx.java
+++ b/platform/platform-impl/src/com/intellij/ide/CopyPasteManagerEx.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.
@@ -36,6 +36,7 @@
private final List<Transferable> myData = new ArrayList<Transferable>();
private final EventDispatcher<ContentChangedListener> myDispatcher = EventDispatcher.create(ContentChangedListener.class);
private final ClipboardSynchronizer myClipboardSynchronizer;
+ private boolean myOwnContent = false;
public static CopyPasteManagerEx getInstanceEx() {
return (CopyPasteManagerEx)getInstance();
@@ -45,43 +46,50 @@
myClipboardSynchronizer = clipboardSynchronizer;
}
+ @Override
public void lostOwnership(Clipboard clipboard, Transferable contents) {
+ myOwnContent = false;
myClipboardSynchronizer.resetContent();
fireContentChanged(contents, null);
}
- void fireContentChanged(@Nullable final Transferable oldTransferable, @Nullable final Transferable _new) {
- myDispatcher.getMulticaster().contentChanged(oldTransferable, _new);
+ private void fireContentChanged(@Nullable Transferable oldContent, @Nullable Transferable newContent) {
+ myDispatcher.getMulticaster().contentChanged(oldContent, newContent);
}
+ @Override
public void addContentChangedListener(ContentChangedListener listener) {
myDispatcher.addListener(listener);
}
+ @Override
public void addContentChangedListener(final ContentChangedListener listener, Disposable parentDisposable) {
myDispatcher.addListener(listener, parentDisposable);
}
+ @Override
public void removeContentChangedListener(ContentChangedListener listener) {
myDispatcher.removeListener(listener);
}
@Override
- public boolean isDataFlavorAvailable(@Nullable DataFlavor flavor) {
- return flavor != null && myClipboardSynchronizer.isDataFlavorAvailable(flavor);
+ public boolean areDataFlavorsAvailable(@NotNull DataFlavor... flavors) {
+ return flavors.length > 0 && myClipboardSynchronizer.areDataFlavorsAvailable(flavors);
}
- public void setContents(@NotNull final Transferable content) {
- Transferable old = getContents();
- Transferable contentToUse = addNewContentToStack(content);
+ @Override
+ public void setContents(@NotNull Transferable content) {
+ Transferable oldContent = myOwnContent && !myData.isEmpty() ? myData.get(0) : null;
+ Transferable contentToUse = addNewContentToStack(content);
setSystemClipboardContent(contentToUse);
- fireContentChanged(old, contentToUse);
+ fireContentChanged(oldContent, contentToUse);
}
+ @Override
public boolean isCutElement(@Nullable final Object element) {
- for(CutElementMarker marker: Extensions.getExtensions(CutElementMarker.EP_NAME)) {
+ for (CutElementMarker marker : Extensions.getExtensions(CutElementMarker.EP_NAME)) {
if (marker.isCutElement(element)) return true;
}
return false;
@@ -96,16 +104,17 @@
}
}
- void setSystemClipboardContent(final Transferable content) {
+ private void setSystemClipboardContent(Transferable content) {
myClipboardSynchronizer.setContent(content, this);
+ myOwnContent = true;
}
/**
* Stores given content within the current manager. It is merged with already stored ones
* if necessary (see {@link KillRingTransferable}).
- *
- * @param content content to store
- * @return content that is either the given one or the one that was assembled from it and already stored one
+ *
+ * @param content content to store
+ * @return content that is either the given one or the one that was assembled from it and already stored one
*/
@NotNull
private Transferable addNewContentToStack(@NotNull Transferable content) {
@@ -114,7 +123,7 @@
if (clipString == null) {
return content;
}
-
+
if (content instanceof KillRingTransferable) {
KillRingTransferable killRingContent = (KillRingTransferable)content;
if (killRingContent.isReadyToCombine() && !myData.isEmpty()) {
@@ -132,7 +141,7 @@
return killRingContent;
}
}
-
+
Transferable same = null;
for (Transferable old : myData) {
if (clipString.equals(getStringContent(old))) {
@@ -145,7 +154,7 @@
addToTheTopOfTheStack(content);
}
else {
- moveContentTopStackTop(same);
+ moveContentToStackTop(same);
}
}
catch (UnsupportedFlavorException ignore) { }
@@ -157,29 +166,28 @@
myData.add(0, content);
deleteAfterAllowedMaximum();
}
-
+
/**
* Merges given new data with the given old one and returns merge result in case of success.
- *
- * @param newData new data to merge
- * @param oldData old data to merge
- * @return merge result of the given data if possible; <code>null</code> otherwise
- * @throws IOException as defined by {@link Transferable#getTransferData(DataFlavor)}
- * @throws UnsupportedFlavorException as defined by {@link Transferable#getTransferData(DataFlavor)}
+ *
+ * @param newData new data to merge
+ * @param oldData old data to merge
+ * @return merge result of the given data if possible; <code>null</code> otherwise
+ * @throws IOException as defined by {@link Transferable#getTransferData(DataFlavor)}
+ * @throws UnsupportedFlavorException as defined by {@link Transferable#getTransferData(DataFlavor)}
*/
@Nullable
private static Transferable merge(@NotNull KillRingTransferable newData, @NotNull KillRingTransferable oldData)
- throws IOException, UnsupportedFlavorException
- {
+ throws IOException, UnsupportedFlavorException {
if (!oldData.isReadyToCombine() || !newData.isReadyToCombine()) {
return null;
}
-
+
Document document = newData.getDocument();
if (document == null || document != oldData.getDocument()) {
return null;
}
-
+
Object newDataText = newData.getTransferData(DataFlavor.stringFlavor);
Object oldDataText = oldData.getTransferData(DataFlavor.stringFlavor);
if (newDataText == null || oldDataText == null) {
@@ -193,24 +201,29 @@
);
}
}
-
+
if (newData.getStartOffset() == oldData.getEndOffset()) {
return new KillRingTransferable(
oldDataText.toString() + newDataText, document, oldData.getStartOffset(), newData.getEndOffset(), false
);
}
-
+
if (newData.getEndOffset() == oldData.getStartOffset()) {
return new KillRingTransferable(
newDataText.toString() + oldDataText, document, newData.getStartOffset(), oldData.getEndOffset(), false
);
}
-
+
return null;
}
-
- private static String getStringContent(Transferable content) throws UnsupportedFlavorException, IOException {
- return (String) content.getTransferData(DataFlavor.stringFlavor);
+
+ private static String getStringContent(Transferable content) {
+ try {
+ return (String)content.getTransferData(DataFlavor.stringFlavor);
+ }
+ catch (UnsupportedFlavorException ignore) { }
+ catch (IOException ignore) { }
+ return null;
}
private void deleteAfterAllowedMaximum() {
@@ -220,55 +233,61 @@
}
}
+ @Override
public Transferable getContents() {
return myClipboardSynchronizer.getContents();
}
- public Transferable[] getAllContents() {
- deleteAfterAllowedMaximum();
-
- Transferable content = getContents();
- if (content != null) {
+ @Nullable
+ @Override
+ public <T> T getContents(@NotNull DataFlavor flavor) {
+ if (areDataFlavorsAvailable(flavor)) {
try {
- String clipString = getStringContent(content);
- String dataString = null;
-
- if (!myData.isEmpty()) {
- dataString = getStringContent(myData.get(0));
- }
-
- if (clipString != null && clipString.length() > 0 && !Comparing.equal(clipString, dataString)) {
- myData.add(0, content);
+ Transferable contents = getContents();
+ if (contents != null) {
+ @SuppressWarnings("unchecked") T data = (T)contents.getTransferData(flavor);
+ return data;
}
}
catch (UnsupportedFlavorException ignore) { }
catch (IOException ignore) { }
}
+ return null;
+ }
+
+ @Override
+ public Transferable[] getAllContents() {
+ String clipString = getContents(DataFlavor.stringFlavor);
+ if (clipString != null && (myData.isEmpty() || !Comparing.equal(clipString, getStringContent(myData.get(0))))) {
+ addToTheTopOfTheStack(new StringSelection(clipString));
+ }
return myData.toArray(new Transferable[myData.size()]);
}
public void removeContent(Transferable t) {
- Transferable old = getContents();
- boolean isCurrentClipboardContent = myData.indexOf(t) == 0;
+ Transferable current = myData.isEmpty() ? null : myData.get(0);
myData.remove(t);
- Transferable _new = null;
- if (isCurrentClipboardContent) {
- if (!myData.isEmpty()) {
- _new = myData.get(0);
- setSystemClipboardContent(_new);
- }
- else {
- _new = new StringSelection("");
- setSystemClipboardContent(_new);
- }
+ if (Comparing.equal(t, current)) {
+ Transferable newContent = !myData.isEmpty() ? myData.get(0) : new StringSelection("");
+ setSystemClipboardContent(newContent);
+ fireContentChanged(current, newContent);
}
- fireContentChanged(old, _new);
}
+ /** @deprecated use {@link #moveContentToStackTop(Transferable)} (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
public void moveContentTopStackTop(Transferable t) {
- setSystemClipboardContent(t);
- myData.remove(t);
- myData.add(0, t);
+ moveContentToStackTop(t);
+ }
+
+ public void moveContentToStackTop(Transferable t) {
+ Transferable current = myData.isEmpty() ? null : myData.get(0);
+ if (!Comparing.equal(t, current)) {
+ myData.remove(t);
+ myData.add(0, t);
+ setSystemClipboardContent(t);
+ fireContentChanged(current, t);
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
index bb2cf49..8aa0e38 100644
--- a/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/IdeRepaintManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,6 +23,7 @@
package com.intellij.ide;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
@@ -160,7 +161,7 @@
return;
}
//ignore the last processed component
- if (myLastComponent != null && c == myLastComponent.get()) {
+ if (SoftReference.dereference(myLastComponent) == c) {
return;
}
myLastComponent = new WeakReference<JComponent>(c);
diff --git a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java
index bdae017..4189b6a 100644
--- a/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/RecentDirectoryProjectsManager.java
@@ -20,7 +20,6 @@
import com.intellij.openapi.components.Storage;
import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
@@ -42,8 +41,8 @@
)}
)
public class RecentDirectoryProjectsManager extends RecentProjectsManagerBase {
- public RecentDirectoryProjectsManager(ProjectManager projectManager, MessageBus messageBus) {
- super(projectManager, messageBus);
+ public RecentDirectoryProjectsManager(MessageBus messageBus) {
+ super(messageBus);
}
@Nullable
diff --git a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
index f379dd0..e77e289 100644
--- a/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
+++ b/platform/platform-impl/src/com/intellij/ide/RecentProjectsManagerBase.java
@@ -21,9 +21,11 @@
import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.project.ProjectManagerAdapter;
+import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
@@ -33,6 +35,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.impl.SystemDock;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -44,16 +47,35 @@
/**
* @author yole
*/
-public abstract class RecentProjectsManagerBase implements PersistentStateComponent<RecentProjectsManagerBase.State> {
+public abstract class RecentProjectsManagerBase implements ProjectManagerListener, PersistentStateComponent<RecentProjectsManagerBase.State> {
public static RecentProjectsManagerBase getInstance() {
- return ApplicationManager.getApplication().getComponent(RecentProjectsManagerBase.class);
+ return ServiceManager.getService(RecentProjectsManagerBase.class);
}
public static class State {
- public List<String> recentPaths = new ArrayList<String>();
- public List<String> openPaths = new ArrayList<String>();
- public Map<String, String> names = new HashMap<String, String>();
+ public List<String> recentPaths = ContainerUtil.newArrayList();
+ public List<String> openPaths = ContainerUtil.newArrayList();
+ public Map<String, String> names = ContainerUtil.newLinkedHashMap();
public String lastPath;
+
+ void validateRecentProjects() {
+ //noinspection StatementWithEmptyBody
+ while (recentPaths.remove(null)) ;
+ Collection<String> displayNames = names.values();
+ //noinspection StatementWithEmptyBody
+ while (displayNames.remove("")) ;
+
+ while (recentPaths.size() > Registry.intValue("ide.max.recent.projects")) {
+ int index = recentPaths.size() - 1;
+ names.remove(recentPaths.get(index));
+ recentPaths.remove(index);
+ }
+ }
+
+ void removePath(String path) {
+ recentPaths.remove(path);
+ names.remove(path);
+ }
}
private final Object myStateLock = new Object();
@@ -61,14 +83,13 @@
private final Map<String, String> myNameCache = Collections.synchronizedMap(new HashMap<String, String>());
- public RecentProjectsManagerBase(ProjectManager projectManager, MessageBus messageBus) {
- projectManager.addProjectManagerListener(new MyProjectManagerListener());
+ protected RecentProjectsManagerBase(MessageBus messageBus) {
messageBus.connect().subscribe(AppLifecycleListener.TOPIC, new MyAppLifecycleListener());
}
public State getState() {
synchronized (myStateLock) {
- validateRecentProjects();
+ myState.validateRecentProjects();
return myState;
}
}
@@ -88,37 +109,16 @@
}
}
- private void validateRecentProjects() {
- synchronized (myStateLock) {
- for (Iterator i = myState.recentPaths.iterator(); i.hasNext();) {
- String s = (String)i.next();
-
- if (s == null) {
- i.remove();
- }
- }
- while (myState.recentPaths.size() > Registry.intValue("ide.max.recent.projects")) {
- final int index = myState.recentPaths.size() - 1;
- myState.names.remove(myState.recentPaths.get(index));
- myState.recentPaths.remove(index);
- }
- }
- }
-
public void removePath(final String path) {
if (path == null) return;
synchronized (myStateLock) {
if (SystemInfo.isFileSystemCaseSensitive) {
- myState.recentPaths.remove(path);
- myState.names.remove(path);
+ myState.removePath(path);
}
else {
- Iterator<String> i = myState.recentPaths.iterator();
- while (i.hasNext()) {
- String p = i.next();
+ for (String p : ArrayUtil.toStringArray(myState.recentPaths)) {
if (path.equalsIgnoreCase(p)) {
- myState.names.remove(p);
- i.remove();
+ myState.removePath(path);
}
}
}
@@ -137,13 +137,16 @@
if (openProjects.length == 0) {
myState.lastPath = null;
myState.openPaths = Collections.emptyList();
- } else {
+ }
+ else {
myState.lastPath = getProjectPath(openProjects[openProjects.length - 1]);
- myState.openPaths = new ArrayList<String>();
+ myState.openPaths = ContainerUtil.newArrayList();
for (Project openProject : openProjects) {
- final String path = getProjectPath(openProject);
- ContainerUtil.addIfNotNull(myState.openPaths, path);
- myState.names.put(path, getProjectDisplayName(openProject));
+ String path = getProjectPath(openProject);
+ if (path != null) {
+ myState.openPaths.add(path);
+ myState.names.put(path, getProjectDisplayName(openProject));
+ }
}
}
}
@@ -157,17 +160,11 @@
private Set<String> getDuplicateProjectNames(Set<String> openedPaths, Set<String> recentPaths) {
Set<String> names = ContainerUtil.newHashSet();
Set<String> duplicates = ContainerUtil.newHashSet();
- for (String path : openedPaths) {
+ for (String path : ContainerUtil.concat(openedPaths, recentPaths)) {
if (!names.add(getProjectName(path))) {
duplicates.add(path);
}
}
- for (String path : recentPaths) {
- if (!names.add(getProjectName(path))) {
- duplicates.add(path);
- }
- }
-
return duplicates;
}
@@ -177,17 +174,17 @@
* @return
*/
public AnAction[] getRecentProjectsActions(boolean addClearListItem) {
- validateRecentProjects();
+ final Set<String> paths;
+ synchronized (myStateLock) {
+ myState.validateRecentProjects();
+ paths = ContainerUtil.newLinkedHashSet(myState.recentPaths);
+ }
final Set<String> openedPaths = ContainerUtil.newHashSet();
for (Project openProject : ProjectManager.getInstance().getOpenProjects()) {
ContainerUtil.addIfNotNull(openedPaths, getProjectPath(openProject));
}
- final LinkedHashSet<String> paths;
- synchronized (myStateLock) {
- paths = ContainerUtil.newLinkedHashSet(myState.recentPaths);
- }
paths.remove(null);
paths.removeAll(openedPaths);
@@ -220,14 +217,14 @@
list.add(action);
}
if (addClearListItem) {
- AnAction clearListAction = new AnAction(IdeBundle.message("action.clear.list")) {
+ AnAction clearListAction = new DumbAwareAction(IdeBundle.message("action.clear.list")) {
public void actionPerformed(AnActionEvent e) {
final int rc = Messages.showOkCancelDialog(e.getData(CommonDataKeys.PROJECT),
"Would you like to clear the list of recent projects?",
"Clear Recent Projects List",
Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.OK) {
synchronized (myStateLock) {
myState.recentPaths.clear();
}
@@ -261,34 +258,35 @@
return file.exists() && (!file.isDirectory() || new File(file, Project.DIRECTORY_STORE_FOLDER).exists());
}
- private class MyProjectManagerListener extends ProjectManagerAdapter {
- public void projectOpened(final Project project) {
- if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
- String path = getProjectPath(project);
+ public void projectOpened(final Project project) {
+ String path = getProjectPath(project);
+ if (path != null) {
+ markPathRecent(path);
+ }
+ SystemDock.updateMenu();
+ }
+
+ @Override
+ public final boolean canCloseProject(Project project) {
+ return true;
+ }
+
+ @Override
+ public void projectClosing(Project project) {
+ synchronized (myStateLock) {
+ myState.names.put(getProjectPath(project), getProjectDisplayName(project));
+ }
+ }
+
+ public void projectClosed(final Project project) {
+ Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
+ if (openProjects.length > 0) {
+ String path = getProjectPath(openProjects[openProjects.length - 1]);
if (path != null) {
markPathRecent(path);
}
- SystemDock.updateMenu();
}
-
- @Override
- public void projectClosing(Project project) {
- synchronized (myStateLock) {
- myState.names.put(getProjectPath(project), getProjectDisplayName(project));
- }
- }
-
- public void projectClosed(final Project project) {
- if (ApplicationManager.getApplication().isHeadlessEnvironment()) return;
- Project[] openProjects = ProjectManager.getInstance().getOpenProjects();
- if (openProjects.length > 0) {
- String path = getProjectPath(openProjects[openProjects.length - 1]);
- if (path != null) {
- markPathRecent(path);
- }
- }
- SystemDock.updateMenu();
- }
+ SystemDock.updateMenu();
}
@NotNull
@@ -330,35 +328,46 @@
}
}
+ protected boolean willReopenProjectOnStart() {
+ return GeneralSettings.getInstance().isReopenLastProject() && getLastProjectPath() != null;
+ }
+
+ protected void doReopenLastProject() {
+ GeneralSettings generalSettings = GeneralSettings.getInstance();
+ if (generalSettings.isReopenLastProject()) {
+ Collection<String> openPaths;
+ synchronized (myStateLock) {
+ openPaths = ContainerUtil.newLinkedHashSet(myState.openPaths);
+ }
+ if (!openPaths.isEmpty()) {
+ for (String openPath : openPaths) {
+ if (isValidProjectPath(openPath)) {
+ doOpenProject(openPath, null, true);
+ }
+ }
+ }
+ else {
+ String lastProjectPath = getLastProjectPath();
+ if (lastProjectPath != null) {
+ if (isValidProjectPath(lastProjectPath)) doOpenProject(lastProjectPath, null, false);
+ }
+ }
+ }
+ }
+
private class MyAppLifecycleListener extends AppLifecycleListener.Adapter {
public void appFrameCreated(final String[] commandLineArgs, @NotNull final Ref<Boolean> willOpenProject) {
- if (GeneralSettings.getInstance().isReopenLastProject() && getLastProjectPath() != null) {
+ if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
+ ProjectManager.getInstance().addProjectManagerListener(RecentProjectsManagerBase.this);
+ }
+ if (willReopenProjectOnStart()) {
willOpenProject.set(Boolean.TRUE);
}
}
- public void appStarting(final Project projectFromCommandLine) {
+ public void appStarting(Project projectFromCommandLine) {
if (projectFromCommandLine != null) return;
- GeneralSettings generalSettings = GeneralSettings.getInstance();
- if (generalSettings.isReopenLastProject()) {
- List<String> openPaths;
- synchronized (myStateLock) {
- openPaths = ContainerUtil.newArrayList(myState.openPaths);
- }
- if (!openPaths.isEmpty()) {
- for (String openPath : openPaths) {
- if (isValidProjectPath(openPath)) {
- doOpenProject(openPath, null, true);
- }
- }
- }
- else {
- String lastProjectPath = getLastProjectPath();
- if (lastProjectPath != null) {
- if (isValidProjectPath(lastProjectPath)) doOpenProject(lastProjectPath, null, false);
- }
- }
- }
+ doReopenLastProject();
}
public void projectFrameClosed() {
diff --git a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
index d8673e5..6e6c052 100644
--- a/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
+++ b/platform/platform-impl/src/com/intellij/ide/SystemHealthMonitor.java
@@ -17,10 +17,7 @@
import com.intellij.concurrency.JobScheduler;
import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.notification.NotificationDisplayType;
-import com.intellij.notification.NotificationGroup;
-import com.intellij.notification.NotificationType;
-import com.intellij.notification.NotificationsConfiguration;
+import com.intellij.notification.*;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
@@ -31,9 +28,7 @@
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.ui.HyperlinkAdapter;
@@ -53,6 +48,14 @@
public class SystemHealthMonitor extends ApplicationComponent.Adapter {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.SystemHealthMonitor");
+ private static final NotNullLazyValue<NotificationGroup> LOG_GROUP = new AtomicNotNullLazyValue<NotificationGroup>() {
+ @NotNull
+ @Override
+ protected NotificationGroup compute() {
+ return NotificationGroup.logOnlyGroup("System Health Log Messages");
+ }
+ };
+
@NotNull private final PropertiesComponent myProperties;
public SystemHealthMonitor(@NotNull PropertiesComponent properties) {
@@ -86,9 +89,10 @@
public void appFrameCreated(String[] commandLineArgs, @NotNull Ref<Boolean> willOpenProject) {
app.invokeLater(new Runnable() {
public void run() {
+ String message = IdeBundle.message(key) + IdeBundle.message("unsupported.jvm.link");
+
JComponent component = WindowManager.getInstance().findVisibleFrame().getRootPane();
if (component != null) {
- String message = IdeBundle.message(key) + IdeBundle.message("unsupported.jvm.link");
Rectangle rect = component.getVisibleRect();
JBPopupFactory.getInstance()
.createHtmlTextBalloonBuilder(message, MessageType.WARNING, new HyperlinkAdapter() {
@@ -104,6 +108,10 @@
.createBalloon()
.show(new RelativePoint(component, new Point(rect.x + 30, rect.y + rect.height - 10)), Balloon.Position.above);
}
+
+ Notification notification = LOG_GROUP.getValue().createNotification(message, NotificationType.WARNING);
+ notification.setImportant(true);
+ Notifications.Bus.notify(notification);
}
});
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java
index dc120b6..4d2529e 100644
--- a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroConfigurationPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -177,7 +177,7 @@
if (macro.getName().equals(name)) {
if (Messages.showYesNoDialog(IdeBundle.message("message.macro.exists", name),
IdeBundle.message("title.macro.name.already.used"),
- Messages.getWarningIcon()) != 0) {
+ Messages.getWarningIcon()) != Messages.YES) {
return false;
}
myMacrosModel.removeElement(macro);
diff --git a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroManager.java b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroManager.java
index 2f2e77a..29d5671 100644
--- a/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroManager.java
+++ b/platform/platform-impl/src/com/intellij/ide/actionMacro/ActionMacroManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -491,7 +491,7 @@
if (actionManager.getAction(actionId) != null) {
if (Messages.showYesNoDialog(IdeBundle.message("message.macro.exists", name),
IdeBundle.message("title.macro.name.already.used"),
- Messages.getWarningIcon()) != 0) {
+ Messages.getWarningIcon()) != Messages.YES) {
return false;
}
actionManager.unregisterAction(actionId);
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java
index 8e54b8b..544c489 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/AboutDialog.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,7 +17,6 @@
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.IdeBundle;
-import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CustomShortcutSet;
import com.intellij.openapi.application.ApplicationInfo;
@@ -35,6 +34,7 @@
import com.intellij.ui.UI;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -118,7 +118,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent event, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent event, int clickCount) {
dispose();
return true;
}
@@ -219,7 +219,7 @@
public void mousePressed(MouseEvent event) {
if (myActiveLink != null) {
event.consume();
- BrowserUtil.launchBrowser(myActiveLink.url);
+ BrowserUtil.browse(myActiveLink.url);
}
}
});
@@ -260,7 +260,7 @@
myImage.paintIcon(this, g2, 0, 0);
g2.setColor(col);
- TextRenderer renderer = new TextRenderer(0, 145, 398, 120, g2);
+ TextRenderer renderer = new TextRenderer(0, 165, 398, 120, g2);
UIUtil.setupComposite(g2);
myFont = labelFont.deriveFont(Font.PLAIN, labelSize);
myBoldFont = labelFont.deriveFont(Font.BOLD, labelSize + 1);
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ActivateToolWindowAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ActivateToolWindowAction.java
index 5a409d8..fc05f1a 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ActivateToolWindowAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ActivateToolWindowAction.java
@@ -45,7 +45,7 @@
public void update(AnActionEvent event){
Presentation presentation = event.getPresentation();
Project project = event.getData(CommonDataKeys.PROJECT);
- if (project == null) {
+ if (project == null || project.isDisposed()) {
presentation.setEnabled(false);
presentation.setVisible(false);
return;
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
index 61ffde9..7728781 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateDesktopEntryAction.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.
@@ -50,8 +50,6 @@
public class CreateDesktopEntryAction extends DumbAwareAction {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.actions.CreateDesktopEntryAction");
- private static final int MIN_ICON_SIZE = 32;
-
public static boolean isAvailable() {
return SystemInfo.isUnix && SystemInfo.hasXdgOpen();
}
@@ -136,9 +134,9 @@
assert new File(binPath).isDirectory() : "Invalid bin/ path: '" + binPath + "'";
String name = ApplicationNamesInfo.getInstance().getFullProductName();
- if (PlatformUtils.isCommunity()) name += " Community Edition";
+ if (PlatformUtils.isIdeaCommunity()) name += " Community Edition";
- final String iconPath = findIcon(binPath);
+ final String iconPath = AppUIUtil.findIcon(binPath);
if (iconPath == null) {
throw new RuntimeException(ApplicationBundle.message("desktop.entry.icon.missing", binPath));
}
@@ -162,34 +160,6 @@
}
@Nullable
- private static String findIcon(final String iconsPath) {
- final File iconsDir = new File(iconsPath);
-
- // 1. look for .svg icon
- for (String child : iconsDir.list()) {
- if (child.endsWith(".svg")) {
- return iconsPath + '/' + child;
- }
- }
-
- // 2. look for .png icon of max size
- int max = 0;
- String iconPath = null;
- for (String child : iconsDir.list()) {
- if (!child.endsWith(".png")) continue;
- final String path = iconsPath + '/' + child;
- final Icon icon = new ImageIcon(path);
- final int size = icon.getIconHeight();
- if (size >= MIN_ICON_SIZE && size > max && size == icon.getIconWidth()) {
- max = size;
- iconPath = path;
- }
- }
-
- return iconPath;
- }
-
- @Nullable
private static String findScript(final String binPath) {
final String productName = ApplicationNamesInfo.getInstance().getProductName();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
index 315e3ad..b76839f 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/CreateLauncherScriptAction.java
@@ -86,7 +86,7 @@
if (target.exists()) {
int rc = Messages.showOkCancelDialog(project, ApplicationBundle.message("launcher.script.overwrite", target),
"Create Launcher Script", Messages.getQuestionIcon());
- if (rc != 0) {
+ if (rc != Messages.OK) {
return;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
index 7a15f84..e82e22d 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ExportSettingsAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -73,7 +73,7 @@
final int ret = Messages.showOkCancelDialog(
IdeBundle.message("prompt.overwrite.settings.file", FileUtil.toSystemDependentName(saveFile.getPath())),
IdeBundle.message("title.file.already.exists"), Messages.getWarningIcon());
- if (ret != 0) return;
+ if (ret != Messages.OK) return;
}
final JarOutputStream output = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(saveFile)));
try {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
index efe1ac6..1e98994 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ImportSettingsAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -119,7 +119,7 @@
ApplicationNamesInfo.getInstance().getProductName(),
ApplicationNamesInfo.getInstance().getFullProductName()),
IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon());
- if (ret == 0) {
+ if (ret == Messages.OK) {
((ApplicationEx)ApplicationManager.getApplication()).restart(true);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/NonEmptyActionGroup.java b/platform/platform-impl/src/com/intellij/ide/actions/NonEmptyActionGroup.java
index fff18a3..58fd865 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/NonEmptyActionGroup.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/NonEmptyActionGroup.java
@@ -20,6 +20,12 @@
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.project.DumbAware;
+/**
+ * This group hides itself when there's no registered children.
+ *
+ * @see com.intellij.ide.actions.SmartPopupActionGroup
+ * @see com.intellij.ide.actions.NonTrivialActionGroup
+ */
public class NonEmptyActionGroup extends DefaultActionGroup implements DumbAware {
public NonEmptyActionGroup() {
super();
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/NonTrivialActionGroup.java b/platform/platform-impl/src/com/intellij/ide/actions/NonTrivialActionGroup.java
new file mode 100644
index 0000000..1739c25
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/actions/NonTrivialActionGroup.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.ide.actions;
+
+import com.intellij.openapi.actionSystem.ActionGroupUtil;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
+import com.intellij.openapi.project.DumbAware;
+
+/**
+ * This group hides itself when there's no enabled and visible child.
+ *
+ * @see com.intellij.ide.actions.SmartPopupActionGroup
+ * @see com.intellij.ide.actions.NonEmptyActionGroup
+ *
+ * @author gregsh
+ */
+public class NonTrivialActionGroup extends DefaultActionGroup implements DumbAware {
+ public NonTrivialActionGroup() {
+ super();
+ }
+
+ public void update(AnActionEvent e) {
+ e.getPresentation().setVisible(!ActionGroupUtil.isGroupEmpty(this, e));
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java b/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java
index ea1d379..08aa037 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/OnlineDocAction.java
@@ -26,7 +26,7 @@
*/
public class OnlineDocAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
- BrowserUtil.launchBrowser(ApplicationInfoImpl.getShadowInstance().getDocumentationUrl());
+ BrowserUtil.browse(ApplicationInfoImpl.getShadowInstance().getDocumentationUrl());
}
public void update(final AnActionEvent e) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java b/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
index 204f973..4cabfe9 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/OpenFileAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -118,13 +118,12 @@
return;
}
- if (OpenProjectFileChooserDescriptor.isProjectFile(file)) {
- int answer = Messages.showYesNoDialog(project,
- IdeBundle.message("message.open.file.is.project", file.getName()),
- IdeBundle.message("title.open.project"),
- Messages.getQuestionIcon());
- if (answer == 0) {
- FileChooserUtil.setLastOpenedFile(ProjectUtil.openOrImport(file.getPath(), project, false), file);
+ if (OpenProjectFileChooserDescriptor.isProjectFile(file) &&
+ // if the ipr-based project is already open, just open the ipr file
+ (project == null || !file.equals(project.getProjectFile()))) {
+ Project openedProject = ProjectUtil.openOrImport(file.getPath(), project, false);
+ if (openedProject != null) {
+ FileChooserUtil.setLastOpenedFile(openedProject, file);
return;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java b/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java
index 0979210..df50bb8 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/RefCardAction.java
@@ -44,7 +44,7 @@
final ApplicationInfoEx appInfo = ApplicationInfoEx.getInstanceEx();
String webUrl = SystemInfo.isMac ? appInfo.getMacKeymapUrl() : appInfo.getWinKeymapUrl();
if (webUrl != null) {
- BrowserUtil.launchBrowser(webUrl);
+ BrowserUtil.browse(webUrl);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SaveAsDirectoryBasedFormatAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SaveAsDirectoryBasedFormatAction.java
index 0716a52..3161855 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SaveAsDirectoryBasedFormatAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SaveAsDirectoryBasedFormatAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -49,7 +49,7 @@
final int result = Messages.showOkCancelDialog(project,
"Project will be saved and reopened in new Directory-Based format.\nAre you sure you want to continue?",
"Save project to Directory-Based format", Messages.getWarningIcon());
- if (result == 0) {
+ if (result == Messages.OK) {
final VirtualFile baseDir = project.getBaseDir();
assert baseDir != null;
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java
index 6678247..af387e8 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SearchWebAction.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,7 +23,6 @@
import com.intellij.openapi.util.text.StringUtil;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
import java.net.URLEncoder;
public class SearchWebAction extends AnAction implements DumbAware {
@@ -34,16 +33,9 @@
return;
}
provider.performCopy(dataContext);
- Transferable contents = CopyPasteManager.getInstance().getContents();
- String string;
- try {
- string = contents == null? null : (String)contents.getTransferData(DataFlavor.stringFlavor);
- }
- catch (Exception ex) {
- return;
- }
+ String string = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
if (StringUtil.isNotEmpty(string)) {
- BrowserUtil.launchBrowser("http://www.google.com/search?q="+ URLEncoder.encode(string));
+ BrowserUtil.browse("http://www.google.com/search?q=" + URLEncoder.encode(string));
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
index 4f7e826..c700091 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SendFeedbackAction.java
@@ -46,7 +46,7 @@
.replace("$TIMEZONE", System.getProperty("user.timezone"))
.replace("$EVAL", isEvaluationLicense() ? "true" : "false")
.replace("$DESCR", getDescription());
- BrowserUtil.launchBrowser(urlTemplate);
+ BrowserUtil.browse(urlTemplate);
}
private static String getDescription() {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java
index 534114b..c8ce3d2 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowFilePathAction.java
@@ -383,7 +383,7 @@
public static void showDialog(Project project, String message, String title, File file, DialogWrapper.DoNotAskOption option) {
if (Messages.showOkCancelDialog(project, message, title, RevealFileAction.getActionName(),
- IdeBundle.message("action.close"), Messages.getInformationIcon(), option) == 0) {
+ IdeBundle.message("action.close"), Messages.getInformationIcon(), option) == Messages.OK) {
openFile(file);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
index b05f142..59ac567 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ShowRecentFilesAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * 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.
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/SmartPopupActionGroup.java b/platform/platform-impl/src/com/intellij/ide/actions/SmartPopupActionGroup.java
index 04303ec..3b38863 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/SmartPopupActionGroup.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/SmartPopupActionGroup.java
@@ -20,6 +20,10 @@
import com.intellij.openapi.actionSystem.DefaultActionGroup;
/**
+ * This group turns itself into a popup if there's more than one child.
+ *
+ * @see com.intellij.ide.actions.NonEmptyActionGroup
+ * @see com.intellij.ide.actions.NonTrivialActionGroup
* @author yole
*/
public class SmartPopupActionGroup extends DefaultActionGroup {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
index 8884e7d..46a6c34 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/Switcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2014 JetBrains s.r.o.
+ * 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.
@@ -205,7 +205,7 @@
final SwitcherSpeedSearch mySpeedSearch;
final ClickListener myClickListener = new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myPinned && (e.isControlDown() || e.isMetaDown() || e.isShiftDown())) return false;
final Object source = e.getSource();
if (source instanceof JList) {
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java b/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java
index 99d3089..78fd65c 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/TechnicalSupportAction.java
@@ -30,7 +30,7 @@
public class TechnicalSupportAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
- BrowserUtil.launchBrowser(ApplicationInfoImpl.getShadowInstance().getSupportUrl());
+ BrowserUtil.browse(ApplicationInfoImpl.getShadowInstance().getSupportUrl());
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/ToggleReadOnlyAttributeAction.java b/platform/platform-impl/src/com/intellij/ide/actions/ToggleReadOnlyAttributeAction.java
index f54540d..a09bc3f 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/ToggleReadOnlyAttributeAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/ToggleReadOnlyAttributeAction.java
@@ -20,35 +20,39 @@
package com.intellij.ide.actions;
import com.intellij.CommonBundle;
-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.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.ReadOnlyAttributeUtil;
import java.io.IOException;
import java.util.ArrayList;
public class ToggleReadOnlyAttributeAction extends AnAction implements DumbAware {
- static VirtualFile[] getFiles(DataContext dataContext){
- ArrayList<VirtualFile> filesList = new ArrayList<VirtualFile>();
+ static VirtualFile[] getFiles(DataContext dataContext) {
+ ArrayList<VirtualFile> filesList = ContainerUtil.newArrayList();
VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(dataContext);
- for(int i=0;files!=null&&i<files.length;i++){
- VirtualFile file=files[i];
- if(file.isInLocalFileSystem()){
+ for (int i = 0; files != null && i < files.length; i++) {
+ VirtualFile file = files[i];
+ if (file.isInLocalFileSystem()) {
filesList.add(file);
}
}
- return VfsUtil.toVirtualFileArray(filesList);
+ return VfsUtilCore.toVirtualFileArray(filesList);
}
- public void update(AnActionEvent e){
- VirtualFile[] files=getFiles(e.getDataContext());
- e.getPresentation().setEnabled(files.length>0);
+ public void update(AnActionEvent e) {
+ VirtualFile[] files = getFiles(e.getDataContext());
+ e.getPresentation().setEnabledAndVisible(files.length > 0);
if (files.length > 0) {
boolean allReadOnly = true;
boolean allWritable = true;
@@ -70,28 +74,27 @@
e.getPresentation().setText("Toggle Read-only Attribute");
}
}
-
}
- public void actionPerformed(final AnActionEvent e){
+ public void actionPerformed(final AnActionEvent e) {
ApplicationManager.getApplication().runWriteAction(
- new Runnable(){
- public void run(){
+ new Runnable() {
+ public void run() {
// Save all documents. We won't be able to save changes to the files that became read-only afterwards.
FileDocumentManager.getInstance().saveAllDocuments();
try {
- VirtualFile[] files=getFiles(e.getDataContext());
+ VirtualFile[] files = getFiles(e.getDataContext());
for (VirtualFile file : files) {
ReadOnlyAttributeUtil.setReadOnlyAttribute(file, file.isWritable());
}
}
- catch(IOException exc){
+ catch (IOException exc) {
Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
Messages.showMessageDialog(
project,
exc.getMessage(),
- CommonBundle.getErrorTitle(),Messages.getErrorIcon()
+ CommonBundle.getErrorTitle(), Messages.getErrorIcon()
);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java
index 9065452..1ca0649 100644
--- a/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java
+++ b/platform/platform-impl/src/com/intellij/ide/actions/WhatsNewAction.java
@@ -28,7 +28,7 @@
*/
public class WhatsNewAction extends AnAction implements DumbAware {
public void actionPerformed(AnActionEvent e) {
- BrowserUtil.launchBrowser(ApplicationInfoEx.getInstanceEx().getWhatsNewUrl());
+ BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWhatsNewUrl());
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java
index 84d5162..621ff0d 100644
--- a/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/dnd/DnDManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.awt.RelativeRectangle;
import com.intellij.util.ui.GeometryUtil;
import com.intellij.util.ui.UIUtil;
@@ -741,6 +742,6 @@
@Nullable
public Component getLastDropHandler() {
- return myLastDropHandler != null ? myLastDropHandler.get() : null;
+ return SoftReference.dereference(myLastDropHandler);
}
}
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 0ebdccb..cecde70 100644
--- a/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/dnd/FileCopyPasteUtil.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,9 +16,9 @@
package com.intellij.ide.dnd;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeRegistry;
import com.intellij.openapi.fileTypes.UnknownFileType;
+import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
@@ -36,9 +36,6 @@
import java.util.Collections;
import java.util.List;
-/**
- * todo: migrate all CCP/DnD support classes to JDK6 TransferHandlers (IDEA 12?)
- */
public class FileCopyPasteUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.ide.dnd.FileCopyPasteUtil");
@@ -77,19 +74,19 @@
return createDataFlavor(DataFlavor.javaJVMLocalObjectMimeType, klass, false);
}
- public static boolean isFileListFlavorSupported(@NotNull final Transferable transferable) {
- return transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ||
- transferable.isDataFlavorSupported(LinuxDragAndDropSupport.uriListFlavor) ||
- transferable.isDataFlavorSupported(LinuxDragAndDropSupport.gnomeFileListFlavor);
+ public static boolean isFileListFlavorAvailable() {
+ return CopyPasteManager.getInstance().areDataFlavorsAvailable(
+ DataFlavor.javaFileListFlavor, LinuxDragAndDropSupport.uriListFlavor, LinuxDragAndDropSupport.gnomeFileListFlavor
+ );
}
- public static boolean isFileListFlavorSupported(@NotNull final DnDEvent event) {
+ public static boolean isFileListFlavorAvailable(@NotNull DnDEvent event) {
return event.isDataFlavorSupported(DataFlavor.javaFileListFlavor) ||
event.isDataFlavorSupported(LinuxDragAndDropSupport.uriListFlavor) ||
event.isDataFlavorSupported(LinuxDragAndDropSupport.gnomeFileListFlavor);
}
- public static boolean isFileListFlavorSupported(@NotNull final DataFlavor[] transferFlavors) {
+ public static boolean isFileListFlavorAvailable(@NotNull DataFlavor[] transferFlavors) {
for (DataFlavor flavor : transferFlavors) {
if (flavor != null && (flavor.equals(DataFlavor.javaFileListFlavor) ||
flavor.equals(LinuxDragAndDropSupport.uriListFlavor) ||
diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeRenderer.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeRenderer.java
index ab2bf8e..f9d8d9c 100644
--- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeRenderer.java
+++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeRenderer.java
@@ -24,6 +24,7 @@
import com.intellij.ui.SimpleColoredComponent;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -137,12 +138,8 @@
}
}
- protected void initComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
- final ErrorTreeElement element = getElement(value);
- if(element instanceof GroupingElement) {
- setFont(getFont().deriveFont(Font.BOLD));
- }
-
+ @NotNull
+ static String calcPrefix(@Nullable ErrorTreeElement element) {
if(element instanceof SimpleMessageElement || element instanceof NavigatableMessageElement) {
String prefix = element.getKind().getPresentableText();
@@ -151,9 +148,19 @@
if (!StringUtil.isEmpty(rendPrefix)) prefix += rendPrefix + " ";
}
- setText(element.getText(), prefix);
+ return prefix;
}
- else if (element != null){
+ return "";
+ }
+
+ protected void initComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
+ final ErrorTreeElement element = getElement(value);
+ if(element instanceof GroupingElement) {
+ setFont(getFont().deriveFont(Font.BOLD));
+ }
+
+ String prefix = calcPrefix(element);
+ if (element != null) {
String[] text = element.getText();
if (text == null) {
text = ArrayUtil.EMPTY_STRING_ARRAY;
@@ -161,7 +168,7 @@
if(text.length > 0 && text[0] == null) {
text[0] = "";
}
- setText(text, null);
+ setText(text, prefix);
}
Icon icon = null;
diff --git a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java
index 20d2d92..08a5a53 100644
--- a/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/errorTreeView/NewErrorTreeViewPanel.java
@@ -39,6 +39,8 @@
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.Alarm;
import com.intellij.util.EditSourceOnDoubleClickHandler;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.MutableErrorTreeView;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
@@ -53,6 +55,7 @@
import java.awt.datatransfer.StringSelection;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
+import java.util.Collections;
import java.util.List;
public class NewErrorTreeViewPanel extends JPanel implements DataProvider, OccurenceNavigator, MutableErrorTreeView, CopyProvider {
@@ -184,16 +187,21 @@
@Override
public void performCopy(@NotNull DataContext dataContext) {
- final ErrorTreeNodeDescriptor descriptor = getSelectedNodeDescriptor();
- if (descriptor != null) {
- final String[] lines = descriptor.getElement().getText();
- CopyPasteManager.getInstance().setContents(new StringSelection(StringUtil.join(lines, "\n")));
+ List<ErrorTreeNodeDescriptor> descriptors = getSelectedNodeDescriptors();
+ if (!descriptors.isEmpty()) {
+ CopyPasteManager.getInstance().setContents(new StringSelection(StringUtil.join(descriptors, new Function<ErrorTreeNodeDescriptor, String>() {
+ @Override
+ public String fun(ErrorTreeNodeDescriptor descriptor) {
+ ErrorTreeElement element = descriptor.getElement();
+ return NewErrorTreeRenderer.calcPrefix(element) + StringUtil.join(element.getText(), "\n");
+ }
+ }, "\n")));
}
}
@Override
public boolean isCopyEnabled(@NotNull DataContext dataContext) {
- return getSelectedNodeDescriptor() != null;
+ return !getSelectedNodeDescriptors().isEmpty();
}
@Override
@@ -259,11 +267,6 @@
return false;
}
- public void clearMessages() {
- myErrorViewStructure.clear();
- myBuilder.updateTree();
- }
-
public void updateTree() {
if (!myIsDisposed) {
myBuilder.updateTree();
@@ -346,16 +349,24 @@
@Nullable
public ErrorTreeNodeDescriptor getSelectedNodeDescriptor() {
- TreePath path = myTree.getSelectionPath();
- if (path == null) {
- return null;
+ List<ErrorTreeNodeDescriptor> descriptors = getSelectedNodeDescriptors();
+ return descriptors.size() == 1 ? descriptors.get(0) : null;
+ }
+
+ private List<ErrorTreeNodeDescriptor> getSelectedNodeDescriptors() {
+ TreePath[] paths = myTree.getSelectionPaths();
+ if (paths == null) {
+ return Collections.emptyList();
}
- DefaultMutableTreeNode lastPathNode = (DefaultMutableTreeNode)path.getLastPathComponent();
- Object userObject = lastPathNode.getUserObject();
- if (!(userObject instanceof ErrorTreeNodeDescriptor)) {
- return null;
+ List<ErrorTreeNodeDescriptor> result = ContainerUtil.newArrayList();
+ for (TreePath path : paths) {
+ DefaultMutableTreeNode lastPathNode = (DefaultMutableTreeNode)path.getLastPathComponent();
+ Object userObject = lastPathNode.getUserObject();
+ if (userObject instanceof ErrorTreeNodeDescriptor) {
+ result.add((ErrorTreeNodeDescriptor)userObject);
+ }
}
- return (ErrorTreeNodeDescriptor)userObject;
+ return result;
}
private void navigateToSource(final boolean focusEditor) {
diff --git a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java
index d495641..e4401a6 100644
--- a/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/impl/ProjectUtil.java
@@ -214,7 +214,7 @@
IdeBundle.message("button.newframe"),
Messages.getQuestionIcon(),
new ProjectNewWindowDoNotAskOption());
- return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW;
+ return exitCode == Messages.YES ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW : GeneralSettings.OPEN_PROJECT_NEW_WINDOW;
}
else {
int exitCode = Messages.showYesNoCancelDialog(IdeBundle.message("prompt.open.project.in.new.frame"),
@@ -224,8 +224,8 @@
CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon(),
new ProjectNewWindowDoNotAskOption());
- return exitCode == 0 ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW :
- exitCode == 1 ? GeneralSettings.OPEN_PROJECT_NEW_WINDOW : Messages.CANCEL;
+ return exitCode == Messages.YES ? GeneralSettings.OPEN_PROJECT_SAME_WINDOW :
+ exitCode == Messages.NO ? GeneralSettings.OPEN_PROJECT_NEW_WINDOW : Messages.CANCEL;
}
}
return confirmOpenNewProject;
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java
index bac148d..ee1fc7b 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionInstallPlugin.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,11 +23,12 @@
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.intellij.util.net.IOExceptionDialog;
+import com.intellij.xml.util.XmlStringUtil;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.IOException;
@@ -84,10 +85,10 @@
@Override
public void actionPerformed(AnActionEvent e) {
- install();
+ install(null);
}
- public void install() {
+ public void install(@Nullable final Runnable onSuccess) {
IdeaPluginDescriptor[] selection = getPluginTable().getSelectedObjects();
if (userConfirm(selection)) {
@@ -158,6 +159,9 @@
PluginManagerMain.notifyPluginsWereInstalled(list.size() == 1 ? list.get(0).getName() : null, null);
}
}
+ if (onSuccess != null) {
+ onSuccess.run();
+ }
}
};
PluginManagerMain.downloadPlugins(list, pluginTableModel.getAllPlugins(), onInstallRunnable, new Runnable(){
@@ -186,10 +190,11 @@
final Set<IdeaPluginDescriptor> disabledDependants,
final ArrayList<PluginNode> list) {
if (!disabled.isEmpty() || !disabledDependants.isEmpty()) {
- String message = "<html><body>";
+ String message = "";
if (disabled.size() == 1) {
message += "Updated plugin '" + disabled.iterator().next().getName() + "' is disabled.";
- } else if (!disabled.isEmpty()) {
+ }
+ else if (!disabled.isEmpty()) {
message += "Updated plugins " + StringUtil.join(disabled, new Function<IdeaPluginDescriptor, String>() {
@Override
public String fun(IdeaPluginDescriptor pluginDescriptor) {
@@ -203,7 +208,8 @@
message += "Updated plugin" + (list.size() > 1 ? "s depend " : " depends ") + "on disabled";
if (disabledDependants.size() == 1) {
message += " plugin '" + disabledDependants.iterator().next().getName() + "'.";
- } else {
+ }
+ else {
message += " plugins " + StringUtil.join(disabledDependants, new Function<IdeaPluginDescriptor, String>() {
@Override
public String fun(IdeaPluginDescriptor pluginDescriptor) {
@@ -217,11 +223,12 @@
int result;
if (!disabled.isEmpty() && !disabledDependants.isEmpty()) {
result =
- Messages.showYesNoCancelDialog(message + "</body></html>", CommonBundle.getWarningTitle(), "Enable all",
+ Messages.showYesNoCancelDialog(XmlStringUtil.wrapInHtml(message), CommonBundle.getWarningTitle(), "Enable all",
"Enable updated plugin" + (disabled.size() > 1 ? "s" : ""), CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon());
- if (result == DialogWrapper.NEXT_USER_EXIT_CODE) return false;
- } else {
+ if (result == Messages.CANCEL) return false;
+ }
+ else {
message += "<br>Would you like to enable ";
if (!disabled.isEmpty()) {
message += "updated plugin" + (disabled.size() > 1 ? "s" : "");
@@ -232,13 +239,14 @@
}
message += "?</body></html>";
result = Messages.showYesNoDialog(message, CommonBundle.getWarningTitle(), Messages.getQuestionIcon());
- if (result == DialogWrapper.CANCEL_EXIT_CODE) return false;
+ if (result == Messages.NO) return false;
}
- if (result == DialogWrapper.OK_EXIT_CODE) {
+ if (result == Messages.YES) {
disabled.addAll(disabledDependants);
pluginsModel.enableRows(disabled.toArray(new IdeaPluginDescriptor[disabled.size()]), true);
- } else if (result == DialogWrapper.CANCEL_EXIT_CODE && !disabled.isEmpty()) {
+ }
+ else if (result == Messages.NO && !disabled.isEmpty()) {
pluginsModel.enableRows(disabled.toArray(new IdeaPluginDescriptor[disabled.size()]), true);
}
return true;
@@ -286,6 +294,6 @@
message = IdeBundle.message("prompt.install.several.plugins", selection.length);
}
- return Messages.showYesNoDialog(host.getMainPanel(), message, IdeBundle.message("action.download.and.install.plugin"), Messages.getQuestionIcon()) == 0;
+ return Messages.showYesNoDialog(host.getMainPanel(), message, IdeBundle.message("action.download.and.install.plugin"), Messages.getQuestionIcon()) == Messages.YES;
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/ActionUninstallPlugin.java b/platform/platform-impl/src/com/intellij/ide/plugins/ActionUninstallPlugin.java
index 40f676a..25769a3 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/ActionUninstallPlugin.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/ActionUninstallPlugin.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.
@@ -72,6 +72,10 @@
}
public void actionPerformed(AnActionEvent e) {
+ uninstall(host, pluginTable);
+ }
+
+ public static void uninstall(PluginManagerMain host, PluginTable pluginTable) {
String message;
IdeaPluginDescriptor[] selection = pluginTable.getSelectedObjects();
@@ -81,7 +85,7 @@
else {
message = IdeBundle.message("prompt.uninstall.several.plugins", selection.length);
}
- if (Messages.showYesNoDialog(host.getMainPanel(), message, promptTitle, Messages.getQuestionIcon()) != 0) return;
+ if (Messages.showYesNoDialog(host.getMainPanel(), message, promptTitle, Messages.getQuestionIcon()) != Messages.YES) return;
for (IdeaPluginDescriptor descriptor : selection) {
IdeaPluginDescriptorImpl pluginDescriptor = (IdeaPluginDescriptorImpl)descriptor;
@@ -93,14 +97,14 @@
ArrayList<IdeaPluginDescriptorImpl> dependant = host.getDependentList(pluginDescriptor);
if (dependant.size() > 0) {
message = IdeBundle.message("several.plugins.depend.on.0.continue.to.remove", pluginDescriptor.getName());
- actualDelete = (Messages.showYesNoDialog(host.getMainPanel(), message, promptTitle, Messages.getQuestionIcon()) == 0);
+ actualDelete = (Messages.showYesNoDialog(host.getMainPanel(), message, promptTitle, Messages.getQuestionIcon()) == Messages.YES);
}
- if (actualDelete) uninstallPlugin(pluginDescriptor);
+ if (actualDelete) uninstallPlugin(pluginDescriptor, host, pluginTable);
}
}
- private void uninstallPlugin(IdeaPluginDescriptorImpl descriptor) {
+ private static void uninstallPlugin(IdeaPluginDescriptorImpl descriptor, PluginManagerMain host, PluginTable pluginTable) {
PluginId pluginId = descriptor.getPluginId();
descriptor.setDeleted(true);
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java
index fcdfad7..c9427cf 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginColumnInfo.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,111 +15,19 @@
*/
package com.intellij.ide.plugins;
-import com.intellij.icons.AllIcons;
-import com.intellij.ide.IdeBundle;
-import com.intellij.openapi.extensions.PluginId;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.ui.Gray;
-import com.intellij.ui.JBColor;
-import com.intellij.util.ui.UIUtil;
-
-import javax.swing.*;
-import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
-import java.awt.*;
/**
- * User: anna
- * Date: 10/13/11
+ * @author anna
+ * @author Konstantin Bulenkov
*/
class AvailablePluginColumnInfo extends PluginManagerColumnInfo {
-
public AvailablePluginColumnInfo(AvailablePluginsTableModel model) {
super(PluginManagerColumnInfo.COLUMN_NAME, model);
}
@Override
public TableCellRenderer getRenderer(final IdeaPluginDescriptor pluginDescriptor) {
- return new AvailableTableRenderer(pluginDescriptor);
+ return new PluginsTableRenderer(pluginDescriptor);
}
-
- private static class AvailableTableRenderer extends DefaultTableCellRenderer {
- private static final int LEFT_MARGIN = new JLabel().getFontMetrics(UIUtil.getLabelFont()).stringWidth(" ");
- private final JLabel myNameLabel = new JLabel();
- private final JLabel myStatusLabel = new JLabel();
- private final JLabel myCategoryLabel = new JLabel();
- private final JPanel myPanel = new JPanel(new GridBagLayout());
-
- private final IdeaPluginDescriptor myPluginDescriptor;
-
- public AvailableTableRenderer(IdeaPluginDescriptor pluginDescriptor) {
- myPluginDescriptor = pluginDescriptor;
-
- myNameLabel.setFont(getNameFont());
-
- final Font smallFont = UIUtil.getLabelFont(UIUtil.FontSize.SMALL);
- myStatusLabel.setFont(smallFont);
- myCategoryLabel.setFont(smallFont);
-
- myPanel.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
-
- final GridBagConstraints gn = new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 0, 0, GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(0, 0, 0,0), 0,0);
- myPanel.add(myNameLabel, gn);
- myPanel.add(myStatusLabel, gn);
- gn.weightx = 1;
- gn.fill = GridBagConstraints.HORIZONTAL;
- myPanel.add(Box.createHorizontalBox(), gn);
-
- gn.fill = GridBagConstraints.NONE;
- gn.weightx = 0;
- myPanel.add(myCategoryLabel, gn);
- }
-
- @Override
- public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
- Component orig = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
- if (myPluginDescriptor != null) {
- final PluginNode pluginNode = (PluginNode)myPluginDescriptor;
- myNameLabel.setText(myPluginDescriptor.getName());
-
- final Color fg = orig.getForeground();
- final Color bg = orig.getBackground();
- final Color grayedFg = isSelected ? fg : new JBColor(Color.DARK_GRAY, Gray._128);
- myNameLabel.setForeground(fg);
- myStatusLabel.setForeground(grayedFg);
-
-
- myPanel.setBackground(bg);
- myNameLabel.setBackground(bg);
- myNameLabel.setIcon(AllIcons.Nodes.Plugin);
- String category = myPluginDescriptor.getCategory();
- if (category != null) {
- myCategoryLabel.setText(category);
- myCategoryLabel.setForeground(grayedFg);
- }
- final IdeaPluginDescriptor installed = PluginManager.getPlugin(pluginNode.getPluginId());
- if (isDownloaded(pluginNode) || (installed != null && InstalledPluginsTableModel.wasUpdated(installed.getPluginId()))) {
- if (!isSelected) myNameLabel.setForeground(FileStatus.ADDED.getColor());
- myStatusLabel.setText("[Downloaded]");
- myPanel.setToolTipText(IdeBundle.message("plugin.download.status.tooltip"));
- myStatusLabel.setBorder(BorderFactory.createEmptyBorder(0, LEFT_MARGIN, 0, 0));
- }
- else if (pluginNode.getStatus() == PluginNode.STATUS_INSTALLED) {
- PluginId pluginId = pluginNode.getPluginId();
- final boolean hasNewerVersion = InstalledPluginsTableModel.hasNewerVersion(pluginId);
- if (!isSelected) myNameLabel.setForeground(FileStatus.MODIFIED.getColor());
- if (hasNewerVersion) {
- if (!isSelected){
- myNameLabel.setForeground(JBColor.RED);
- }
- myNameLabel.setIcon(AllIcons.Nodes.Pluginobsolete);
- }
- myStatusLabel.setText("v." + pluginNode.getInstalledVersion() + (hasNewerVersion ? (" -> " + pluginNode.getVersion()) : ""));
- myStatusLabel.setBorder(BorderFactory.createEmptyBorder(0, LEFT_MARGIN, 0, 0));
- }
- }
- return myPanel;
- }
- }
-
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java
index 620c73c..fb58c61 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsManagerMain.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,6 +25,7 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.TableUtil;
import com.intellij.util.net.HTTPProxySettingsDialog;
import com.intellij.util.ui.update.UiNotifyConnector;
import org.jetbrains.annotations.NotNull;
@@ -93,16 +94,16 @@
pluginsModel = model;
pluginTable = new PluginTable(pluginsModel);
pluginTable.getTableHeader().setReorderingAllowed(false);
- pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_DOWNLOADS, 70);
- pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_DATE, 80);
- pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_RATE, 80);
+ //pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_DOWNLOADS, 70);
+ //pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_DATE, 80);
+ //pluginTable.setColumnWidth(PluginManagerColumnInfo.COLUMN_RATE, 80);
return ScrollPaneFactory.createScrollPane(pluginTable);
}
@Override
- protected void installTableActions(final PluginTable pluginTable) {
- super.installTableActions(pluginTable);
+ protected void installTableActions() {
+ super.installTableActions();
new DoubleClickListener() {
@Override
protected boolean onDoubleClick(MouseEvent e) {
@@ -140,7 +141,7 @@
}
}
if (enabled) {
- new ActionInstallPlugin(this, installed).install();
+ new ActionInstallPlugin(this, installed).install(null);
}
return true;
}
@@ -159,11 +160,21 @@
}
@Override
+ protected PluginManagerMain getAvailable() {
+ return this;
+ }
+
+ @Override
+ protected PluginManagerMain getInstalled() {
+ return installed;
+ }
+
+ @Override
protected ActionGroup getActionGroup(boolean inToolbar) {
DefaultActionGroup actionGroup = new DefaultActionGroup();
actionGroup.add(new RefreshAction());
actionGroup.add(Separator.getInstance());
- actionGroup.add(new ActionInstallPlugin(this, installed));
+ actionGroup.add(new ActionInstallPlugin(getAvailable(), getInstalled()));
if (inToolbar) {
actionGroup.add(new SortByStatusAction("Sort Installed First"));
actionGroup.add(new MyFilterRepositoryAction());
@@ -255,6 +266,7 @@
public void actionPerformed(AnActionEvent e) {
final String filter = myFilter.getFilter().toLowerCase();
((AvailablePluginsTableModel)pluginsModel).setRepository(host, filter);
+ TableUtil.ensureSelectionExists(getPluginTable());
}
};
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsTableModel.java
index 60ca692..5ab37c1 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsTableModel.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/AvailablePluginsTableModel.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,9 +52,10 @@
public AvailablePluginsTableModel() {
super.columns = new ColumnInfo[] {
new AvailablePluginColumnInfo(this),
- new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_DOWNLOADS, this),
- new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_RATE, this),
- new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_DATE, this)/*,
+ //new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_DOWNLOADS, this),
+ //new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_RATE, this),
+ //new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_DATE, this)
+ /*,
new PluginManagerColumnInfo(PluginManagerColumnInfo.COLUMN_CATEGORY, this)*/};
setSortKey(new RowSorter.SortKey(getNameColumn(), SortOrder.ASCENDING));
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java
index 7e2f499..a55cfa7 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsManagerMain.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,7 +25,6 @@
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.options.ex.SingleConfigurableEditor;
import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.util.Comparing;
@@ -75,7 +74,7 @@
installPluginFromFileSystem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- final FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, true, true, false, false){
+ final FileChooserDescriptor descriptor = new FileChooserDescriptor(false, false, true, true, false, false){
@Override
public boolean isFileSelectable(VirtualFile file) {
final String extension = file.getExtension();
@@ -178,7 +177,7 @@
}, ", ") +
". Enable " + disabledPluginsMessage.trim() + "?";
if (Messages.showOkCancelDialog(myActionsPanel, message, CommonBundle.getWarningTitle(), Messages.getWarningIcon()) ==
- DialogWrapper.OK_EXIT_CODE) {
+ Messages.OK) {
((InstalledPluginsTableModel)pluginsModel).enableRows(dependencies.toArray(new IdeaPluginDescriptor[dependencies.size()]), Boolean.TRUE);
}
}
@@ -207,7 +206,8 @@
pluginTable = new PluginTable(pluginsModel);
pluginTable.setTableHeader(null);
- JScrollPane installedScrollPane = ScrollPaneFactory.createScrollPane(pluginTable);
+ JScrollPane installedScrollPane = ScrollPaneFactory.createScrollPane(pluginTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
+ ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
pluginTable.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
final int column = InstalledPluginsTableModel.getCheckboxColumn();
@@ -228,20 +228,33 @@
pluginTable.repaint();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), JComponent.WHEN_FOCUSED);
+ pluginTable.setExpandableItemsEnabled(false);
return installedScrollPane;
}
@Override
+ protected PluginManagerMain getAvailable() {
+ return this;
+ }
+
+ @Override
+ protected PluginManagerMain getInstalled() {
+ return this;
+ }
+
+ @Override
protected ActionGroup getActionGroup(boolean inToolbar) {
final DefaultActionGroup actionGroup = new DefaultActionGroup();
- actionGroup.add(new RefreshAction());
- actionGroup.add(Separator.getInstance());
- actionGroup.add(new ActionInstallPlugin(this, this));
- actionGroup.add(new ActionUninstallPlugin(this, pluginTable));
if (inToolbar) {
- actionGroup.add(new SortByStatusAction("Sort by Status"));
+ //actionGroup.add(new SortByStatusAction("Sort by Status"));
actionGroup.add(new MyFilterEnabledAction());
//actionGroup.add(new MyFilterBundleAction());
+ } else {
+
+ actionGroup.add(new RefreshAction());
+ actionGroup.add(Separator.getInstance());
+ actionGroup.add(new ActionInstallPlugin(getAvailable(), getInstalled()));
+ actionGroup.add(new UninstallPluginAction(this, pluginTable));
}
return actionGroup;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java
index 1f2de10..7325685 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/InstalledPluginsTableModel.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,7 +23,6 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
@@ -76,7 +75,7 @@
public InstalledPluginsTableModel() {
- super.columns = new ColumnInfo[]{new EnabledPluginInfo(), new MyPluginManagerColumnInfo()};
+ super.columns = new ColumnInfo[]{new MyPluginManagerColumnInfo(), new EnabledPluginInfo()};
view = new ArrayList<IdeaPluginDescriptor>(Arrays.asList(PluginManager.getPlugins()));
view.addAll(myInstalled);
reset(view);
@@ -118,11 +117,11 @@
}
public static int getCheckboxColumn() {
- return 0;
+ return 1;
}
public int getNameColumn() {
- return 1;
+ return 0;
}
private void reset(final List<IdeaPluginDescriptor> list) {
@@ -369,7 +368,7 @@
private class EnabledPluginInfo extends ColumnInfo<IdeaPluginDescriptor, Boolean> {
public EnabledPluginInfo() {
- super(IdeBundle.message("plugin.manager.enable.column.title"));
+ super(/*IdeBundle.message("plugin.manager.enable.column.title")*/"");
}
public Boolean valueOf(IdeaPluginDescriptor ideaPluginDescriptor) {
@@ -432,6 +431,11 @@
}
};
}
+
+ @Override
+ public int getWidth(JTable table) {
+ return new JCheckBox().getPreferredSize().width;
+ }
}
private void warnAboutMissedDependencies(final Boolean newVal, final IdeaPluginDescriptor... ideaPluginDescriptors) {
@@ -503,7 +507,7 @@
"<br>Would you like to disable them too?</html>"
: "<html>The following plugins on which " + listOfSelectedPlugins + " depend" + (ideaPluginDescriptors.length == 1 ? "s" : "") +
" are disabled:<br>" + listOfDependencies + "<br>Would you like to enable them?</html>";
- if (Messages.showOkCancelDialog(message, newVal ? "Enable Dependant Plugins" : "Disable Plugins with Dependency on this", Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ if (Messages.showOkCancelDialog(message, newVal ? "Enable Dependant Plugins" : "Disable Plugins with Dependency on this", Messages.getQuestionIcon()) == Messages.OK) {
for (PluginId pluginId : deps) {
myEnabled.put(pluginId, newVal);
}
@@ -638,7 +642,7 @@
@Override
public TableCellRenderer getRenderer(final IdeaPluginDescriptor pluginDescriptor) {
- return new InstalledPluginsTableRenderer(pluginDescriptor);
+ return new PluginsTableRenderer(pluginDescriptor);
}
@Override
@@ -703,5 +707,10 @@
}
};
}
+
+ @Override
+ public int getWidth(JTable table) {
+ return super.getWidth(table);
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.form b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.form
new file mode 100644
index 0000000..5a3e4f7
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.form
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.plugins.PluginHeaderPanel">
+ <grid id="27dc6" binding="myRoot" 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="500" height="400"/>
+ </constraints>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <component id="e654" class="com.intellij.ui.components.JBLabel" binding="myCategory">
+ <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>
+ <text value="CATEGORY"/>
+ </properties>
+ </component>
+ <hspacer id="a85a3">
+ <constraints>
+ <grid row="0" 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>
+ <vspacer id="a9eec">
+ <constraints>
+ <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>
+ <component id="48afa" class="com.intellij.ui.components.JBLabel" binding="myName">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Name name name"/>
+ </properties>
+ </component>
+ <grid id="79c3d" binding="myDownloadsPanel" layout-manager="GridLayoutManager" row-count="1" 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="5" 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>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <hspacer id="7f4">
+ <constraints>
+ <grid row="0" column="2" 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="9456a" class="com.intellij.ide.plugins.RatesPanel" binding="myRating">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="55a8f" class="com.intellij.ui.components.JBLabel" binding="myDownloads">
+ <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="777 downloads"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="11cd7" binding="myVersionInfoPanel" layout-manager="GridLayoutManager" row-count="1" 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="6" 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>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <component id="bfda6" class="com.intellij.ui.components.JBLabel" binding="myUpdated">
+ <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>
+ <text value="Updated: 11/12/13"/>
+ </properties>
+ </component>
+ <component id="1845c" class="com.intellij.ui.components.JBLabel" binding="myVersion">
+ <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="v 1.2.3"/>
+ </properties>
+ </component>
+ <hspacer id="5a6c2">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ <grid id="5bca5" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="4" 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>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <grid id="13a9c" binding="myButtonPanel" 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="2" column="0" row-span="2" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <vspacer id="c9483">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </vspacer>
+ <component id="d0aa4" class="javax.swing.JButton" binding="myInstallButton" custom-create="true" default-binding="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Install"/>
+ </properties>
+ </component>
+ <hspacer id="71c7f">
+ <constraints>
+ <grid row="0" 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>
+ </children>
+ </grid>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java
new file mode 100644
index 0000000..0c27f99
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHeaderPanel.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.plugins;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.ui.GraphicsConfig;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.text.DateFormatUtil;
+import com.intellij.util.ui.GraphicsUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class PluginHeaderPanel {
+ private IdeaPluginDescriptor myPlugin;
+ @Nullable
+ private final PluginManagerMain myManager;
+ private final JTable myPluginTable;
+ private JBLabel myCategory;
+ private JBLabel myName;
+ private JBLabel myDownloads;
+ private RatesPanel myRating;
+ private JBLabel myUpdated;
+ private JButton myInstallButton;
+ private JBLabel myVersion;
+ private JPanel myRoot;
+ private JPanel myButtonPanel;
+ private JPanel myDownloadsPanel;
+ private JPanel myVersionInfoPanel;
+
+ enum ACTION_ID {UPDATE, INSTALL, UNINSTALL, RESTART}
+ private ACTION_ID myActionId = ACTION_ID.INSTALL;
+
+ public PluginHeaderPanel(@Nullable PluginManagerMain manager, JTable pluginTable) {
+ myManager = manager;
+ myPluginTable = pluginTable;
+ final Font font = myName.getFont();
+ myName.setFont(new Font(font.getFontName(), font.getStyle(), font.getSize() + 2));
+ final JBColor greyed = new JBColor(Gray._130, Gray._200);
+ myCategory.setForeground(greyed);
+ myDownloads.setForeground(greyed);
+ myUpdated.setForeground(greyed);
+ myVersion.setForeground(greyed);
+ final Font smallFont = new Font(font.getFontName(), font.getStyle(), font.getSize() - 1);
+ myCategory.setFont(smallFont);
+ myVersion.setFont(smallFont);
+ myDownloads.setFont(smallFont);
+ myUpdated.setFont(smallFont);
+ myRoot.setVisible(false);
+ }
+
+ public void setPlugin(IdeaPluginDescriptor plugin) {
+ myPlugin = plugin;
+ myRoot.setVisible(true);
+ myCategory.setVisible(true);
+ myDownloadsPanel.setVisible(true);
+ myButtonPanel.setVisible(true);
+ myUpdated.setVisible(true);
+
+ //data
+ myName.setText("<html><body>" + plugin.getName() + "</body></html>");
+ myCategory.setText(plugin.getCategory() == null ? "UNKNOWN" : plugin.getCategory().toUpperCase());
+ if (plugin instanceof PluginNode) {
+ final PluginNode node = (PluginNode)plugin;
+
+
+ myRating.setRate(node.getRating());
+ myDownloads.setText(node.getDownloads() + " downloads");
+ myVersion.setText(" ver " + node.getVersion());
+ 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;
+ break;
+ case PluginNode.STATUS_DOWNLOADED:
+ myActionId = ACTION_ID.RESTART;
+ break;
+ default:
+ myActionId = ACTION_ID.INSTALL;
+ }
+ if (node.getRepositoryName() != null) {
+ myCategory.setVisible(false);
+ myDownloadsPanel.setVisible(false);
+ myUpdated.setVisible(false);
+ }
+ } else {
+ myActionId = null;
+ myVersionInfoPanel.remove(myUpdated);
+ myCategory.setVisible(false);
+ myDownloadsPanel.setVisible(false);
+ final String version = plugin.getVersion();
+ myVersion.setText("Version: " + (version == null ? "N/A" : version));
+ myUpdated.setVisible(false);
+ if (!plugin.isBundled()) {
+ myActionId = ((IdeaPluginDescriptorImpl)plugin).isDeleted() ? ACTION_ID.RESTART : ACTION_ID.UNINSTALL;
+ }
+ if (myActionId == ACTION_ID.RESTART && myManager != null && !myManager.isRequireShutdown()) {
+ myActionId = null;
+ }
+ }
+ if (myManager == null || myActionId == null || (myManager.getInstalled() != myManager.getAvailable() && myActionId == ACTION_ID.UNINSTALL)) {
+ myActionId = ACTION_ID.INSTALL;
+ myButtonPanel.setVisible(false);
+ }
+ myRoot.revalidate();
+ ((JComponent)myInstallButton.getParent()).revalidate();
+ myInstallButton.revalidate();
+ ((JComponent)myVersion.getParent()).revalidate();
+ myVersion.revalidate();
+ }
+
+ private void createUIComponents() {
+ myInstallButton = new JButton() {
+ {
+ setOpaque(false);
+ setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ }
+ @Override
+ public Dimension getPreferredSize() {
+ final FontMetrics metrics = getFontMetrics(getFont());
+ final int textWidth = metrics.stringWidth(getText());
+ final int width = 8 + 16 + 4 + textWidth + 8;
+ final int height = 2 + Math.max(16, metrics.getHeight()) + 2;
+ return new Dimension(width, height);
+ }
+
+ @Override
+ public void paint(Graphics g2) {
+ final Graphics2D g = (Graphics2D)g2;
+ final GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
+ final int w = g.getClipBounds().width;
+ final int h = g.getClipBounds().height;
+
+ g.setPaint(getBackgroundBorderPaint());
+ g.fillRoundRect(0, 0, w, h, 7, 7);
+
+ g.setPaint(getBackgroundPaint());
+ g.fillRoundRect(1, 1, w - 2, h - 2, 6, 6);
+ g.setColor(getButtonForeground());
+ g.drawString(getText(), 8 + 16 + 4, getBaseline(w, h));
+ getIcon().paintIcon(this, g, 8, (getHeight() - getIcon().getIconHeight()) / 2);
+ config.restore();
+ }
+
+ private Color getButtonForeground() {
+ switch (myActionId) {
+ case UPDATE: return new JBColor(Gray._0, Gray._20);
+ case INSTALL: return new JBColor(Gray._255, Gray._210);
+ case UNINSTALL: return new JBColor(Gray._0, Gray._140);
+ case RESTART:
+ break;
+ }
+
+ return new JBColor(Gray._80, Gray._60);
+ }
+
+ private Paint getBackgroundPaint() {
+ switch (myActionId) {
+ case UPDATE: return new JBColor(new Color(209, 190, 114), new Color(132, 116, 66));
+ case INSTALL: return new JBColor(new Color(0x4DA864), new Color(49, 98, 49));
+ case UNINSTALL: return UIUtil.isUnderDarcula()
+ ? new GradientPaint(0, 0, UIManager.getColor("Button.darcula.color1"),
+ 0, getHeight(), UIManager.getColor("Button.darcula.color2"))
+ : Gray._240;
+ case RESTART:
+ break;
+ }
+ return Gray._238;
+ }
+
+ private Paint getBackgroundBorderPaint() {
+ switch (myActionId) {
+ case UPDATE: return new JBColor(new Color(164, 145, 82), Gray._85);
+ case INSTALL: return new JBColor(new Color(0x337043), Gray._80);
+ case UNINSTALL: return new JBColor(Gray._220, Gray._100.withAlpha(180));
+ case RESTART:
+ }
+ return Gray._208;
+ }
+
+
+ @Override
+ public String getText() {
+ switch (myActionId) {
+ case UPDATE: return "Update plugin";
+ case INSTALL: return "Install plugin";
+ case UNINSTALL: return "Uninstall plugin";
+ case RESTART: return "Restart " + ApplicationNamesInfo.getInstance().getFullProductName();
+ }
+ return super.getText();
+ }
+
+ @Override
+ public Icon getIcon() {
+ switch (myActionId) {
+ case UPDATE: return AllIcons.Actions.Refresh;
+ case INSTALL: return AllIcons.General.DownloadPlugin;
+ case UNINSTALL: return AllIcons.Actions.Delete;
+ case RESTART: return AllIcons.Actions.Restart;
+ }
+ return super.getIcon();
+
+ }
+ };
+ myInstallButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ switch (myActionId) {
+ case UPDATE:
+ break;
+ case INSTALL:
+ new ActionInstallPlugin(myManager.getAvailable(), myManager.getInstalled()).install(new Runnable() {
+ @Override
+ public void run() {
+ setPlugin(myPlugin);
+ }
+ });
+ break;
+ case UNINSTALL:
+ //try {
+ UninstallPluginAction.uninstall(myManager.getInstalled(), myPlugin);
+ //}
+ //catch (IOException e1) {
+ // e1.printStackTrace();
+ //}
+ break;
+ case RESTART:
+ if (myManager != null) {
+ myManager.apply();
+ }
+ break;
+ }
+ setPlugin(myPlugin);
+ }
+ });
+ }
+
+ public JBLabel getCategory() {
+ return myCategory;
+ }
+
+ public JBLabel getName() {
+ return myName;
+ }
+
+ public JBLabel getDownloads() {
+ return myDownloads;
+ }
+
+ public RatesPanel getRating() {
+ return myRating;
+ }
+
+ public JBLabel getUpdated() {
+ return myUpdated;
+ }
+
+ public JButton getInstallButton() {
+ return myInstallButton;
+ }
+
+ public JPanel getPanel() {
+ return myRoot;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java
index 94f7e51..919c7bb 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginHostsConfigurable.java
@@ -27,13 +27,13 @@
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFileManager;
-import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
import com.intellij.ui.AnActionButton;
import com.intellij.ui.AnActionButtonRunnable;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.ToolbarDecorator;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -158,7 +158,7 @@
private static String correctRepositoryRule(String input) {
String protocol = VirtualFileManager.extractProtocol(input);
if (protocol == null) {
- input = VirtualFileManager.constructUrl(HttpFileSystem.PROTOCOL, input);
+ input = VirtualFileManager.constructUrl(URLUtil.HTTP_PROTOCOL, input);
}
return input;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java
index 1bc0813..2dfc3eb 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginInstaller.java
@@ -23,7 +23,6 @@
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.updateSettings.impl.PluginDownloader;
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
@@ -113,7 +112,7 @@
public void run() {
String title = IdeBundle.message("plugin.manager.dependencies.detected.title");
String message = IdeBundle.message("plugin.manager.dependencies.detected.message", depends.size(), buf.substring(0, buf.length() - 1));
- proceed[0] = Messages.showYesNoDialog(message, title, Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE;
+ proceed[0] = Messages.showYesNoDialog(message, title, Messages.getWarningIcon()) == Messages.YES;
}
});
}
@@ -143,7 +142,7 @@
Messages.showYesNoDialog(IdeBundle.message("plugin.manager.optional.dependencies.detected.message", optionalDeps.size(),
buf.substring(0, buf.length() - 1)),
IdeBundle.message("plugin.manager.dependencies.detected.title"),
- Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE;
+ Messages.getWarningIcon()) == Messages.YES;
}
});
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java
index f1dc4e1..591798a 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerColumnInfo.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,11 +15,9 @@
*/
package com.intellij.ide.plugins;
-import com.intellij.icons.AllIcons;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.LightColors;
import com.intellij.util.text.DateFormatUtil;
@@ -101,7 +99,7 @@
protected boolean isSortByName() {
return COLUMN_NAME == columnIdx;
}
-
+
protected boolean isSortByDownloads() {
return columnIdx == COLUMN_DOWNLOADS;
}
@@ -319,48 +317,4 @@
return myLabel;
}
}
-
- //waiting for rates available in IDEA
- private static class RatesPanel extends JPanel {
- public static int MAX_RATE = 5;
-
- private static final Icon STAR = AllIcons.Ide.Rating;
-
- private static final Icon STAR3 = AllIcons.Ide.Rating1;
- private static final Icon STAR4 = AllIcons.Ide.Rating2;
- private static final Icon STAR5 = AllIcons.Ide.Rating3;
- private static final Icon STAR6 = AllIcons.Ide.Rating4;
- private static final Icon[] STARs = new Icon[]{IconLoader.getDisabledIcon(STAR), STAR3, STAR3, STAR4, STAR4, STAR5, STAR5, STAR6, STAR6, STAR};
-
- private JLabel[] myLabels = new JLabel[MAX_RATE];
-
- private RatesPanel() {
- super(new GridBagLayout());
- GridBagConstraints gc =
- new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
- new Insets(0, 0, 0, 0), 0, 0);
- for (int i = 0, myLabelsLength = myLabels.length; i < myLabelsLength; i++) {
- myLabels[i] = new JLabel();
- myLabels[i].setOpaque(false);
- add(myLabels[i], gc);
- }
- }
-
- public void setRate(String rating) {
- final Double dblRating = Double.valueOf(rating);
-
- final int intRating = dblRating.intValue();
-
- for (int i = 0; i < intRating; i++) {
- myLabels[i].setIcon(STAR);
- }
-
- if (intRating < MAX_RATE) {
- myLabels[intRating].setIcon(STARs[((Double)(dblRating * 10)).intValue() % 10]);
- for (int i = 1 + intRating; i < MAX_RATE; i++) {
- myLabels[i].setIcon(IconLoader.getDisabledIcon(STAR));
- }
- }
- }
- }
}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java
index e1974cb..534ade3 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -142,7 +142,7 @@
final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
int response = app.isRestartCapable() ? showRestartIDEADialog() : showShutDownIDEADialog();
- if (response == 0) {
+ if (response == Messages.YES) {
app.restart(true);
}
else {
@@ -158,20 +158,24 @@
return myPluginManagerMain;
}
+ @Messages.YesNoResult
public static int showShutDownIDEADialog() {
return showShutDownIDEADialog(IdeBundle.message("title.plugins.changed"));
}
- public static int showShutDownIDEADialog(final String title) {
+ @Messages.YesNoResult
+ private static int showShutDownIDEADialog(final String title) {
String message = IdeBundle.message("message.idea.shutdown.required", ApplicationNamesInfo.getInstance().getFullProductName());
return Messages.showYesNoDialog(message, title, "Shut Down", POSTPONE, Messages.getQuestionIcon());
}
+ @Messages.YesNoResult
public static int showRestartIDEADialog() {
return showRestartIDEADialog(IdeBundle.message("title.plugins.changed"));
}
- public static int showRestartIDEADialog(final String title) {
+ @Messages.YesNoResult
+ private static int showRestartIDEADialog(final String title) {
String message = IdeBundle.message("message.idea.restart.required", ApplicationNamesInfo.getInstance().getFullProductName());
return Messages.showYesNoDialog(message, title, "Restart", POSTPONE, Messages.getQuestionIcon());
}
@@ -179,7 +183,7 @@
public static void shutdownOrRestartApp(String title) {
final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
int response = app.isRestartCapable() ? showRestartIDEADialog(title) : showShutDownIDEADialog(title);
- if (response == 0) app.restart(true);
+ if (response == Messages.YES) app.restart(true);
}
public boolean isModified() {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form
index 5381a96..d93a0d0 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.form
@@ -50,24 +50,19 @@
</properties>
<border type="empty"/>
<children>
- <grid id="7d113" 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"/>
+ <grid id="7d113" binding="myInfoPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<splitpane position="right"/>
</constraints>
<properties/>
<border type="none">
- <size top="0" left="0" bottom="0" right="0"/>
+ <size top="2" left="4" bottom="2" right="4"/>
</border>
<children>
<scrollpane id="8853a" class="com.intellij.ui.components.JBScrollPane">
- <constraints>
- <grid row="0" 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>
- <verticalScrollBarPolicy value="22"/>
- </properties>
- <border type="none"/>
+ <constraints border-constraint="Center"/>
+ <properties/>
+ <border type="empty"/>
<children>
<component id="db08a" class="javax.swing.JEditorPane" binding="myDescriptionTextArea">
<constraints/>
@@ -82,6 +77,14 @@
</component>
</children>
</scrollpane>
+ <grid id="a6a17" binding="myHeader" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints border-constraint="North"/>
+ <properties/>
+ <border type="empty">
+ <size top="2" left="4" bottom="2" right="4"/>
+ </border>
+ <children/>
+ </grid>
</children>
</grid>
<grid id="83ed3" binding="myTablePanel" layout-manager="BorderLayout" hgap="0" vgap="0">
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
index 5c80c01..bf59ca5 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerMain.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,7 +30,10 @@
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.*;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
@@ -48,11 +51,14 @@
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import javax.swing.border.Border;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
+import javax.swing.plaf.BorderUIResource;
import javax.swing.text.html.HTMLDocument;
+import javax.swing.text.html.HTMLEditorKit;
import javax.swing.text.html.HTMLFrameHyperlinkEvent;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
@@ -93,6 +99,9 @@
private JPanel myTablePanel;
protected JPanel myActionsPanel;
+ private JPanel myHeader;
+ private PluginHeaderPanel myPluginHeaderPanel;
+ private JPanel myInfoPanel;
protected PluginTableModel pluginsModel;
@@ -112,19 +121,26 @@
protected void init() {
GuiUtils.replaceJSplitPaneWithIDEASplitter(main);
-
+ myDescriptionTextArea.setEditorKit(new HTMLEditorKit());
+ myDescriptionTextArea.setEditable(false);
myDescriptionTextArea.addHyperlinkListener(new MyHyperlinkListener());
JScrollPane installedScrollPane = createTable();
- installTableActions(pluginTable);
+ myPluginHeaderPanel = new PluginHeaderPanel(this, getPluginTable());
+ myHeader.setBackground(UIUtil.getTextFieldBackground());
+ myHeader.add(myPluginHeaderPanel.getPanel(), BorderLayout.CENTER);
+ installTableActions();
myTablePanel.add(installedScrollPane, BorderLayout.CENTER);
myToolbarPanel.setLayout(new BorderLayout());
- myActionToolbar = ActionManager.getInstance().createActionToolbar("PluginManaer", getActionGroup(true), true);
+ myActionToolbar = ActionManager.getInstance().createActionToolbar("PluginManager", getActionGroup(true), true);
final JComponent component = myActionToolbar.getComponent();
- myToolbarPanel.add(component, BorderLayout.WEST);
- myToolbarPanel.add(myFilter, BorderLayout.EAST);
+ myToolbarPanel.add(component, BorderLayout.CENTER);
+ myToolbarPanel.add(myFilter, BorderLayout.WEST);
+
+ Border border = new BorderUIResource.LineBorderUIResource(new JBColor(Gray._220, Gray._55), 1);
+ myInfoPanel.setBorder(border);
}
protected abstract JScrollPane createTable();
@@ -159,13 +175,10 @@
return pluginsModel;
}
- protected void installTableActions(final PluginTable pluginTable) {
+ protected void installTableActions() {
pluginTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
public void valueChanged(ListSelectionEvent e) {
- final IdeaPluginDescriptor[] descriptors = pluginTable.getSelectedObjects();
- pluginInfoUpdate(descriptors != null && descriptors.length == 1 ? descriptors[0] : null,
- myFilter.getFilter(), myDescriptionTextArea);
- myActionToolbar.updateActionsImmediately();
+ refresh();
}
});
@@ -174,6 +187,16 @@
new MySpeedSearchBar(pluginTable);
}
+ public void refresh() {
+ final IdeaPluginDescriptor[] descriptors = pluginTable.getSelectedObjects();
+ pluginInfoUpdate(descriptors != null && descriptors.length == 1 ? descriptors[0] : null,
+ myFilter.getFilter(), myDescriptionTextArea, myPluginHeaderPanel, this);
+ myActionToolbar.updateActionsImmediately();
+ final JComponent parent = (JComponent)myHeader.getParent();
+ parent.revalidate();
+ parent.repaint();
+ }
+
public void setRequireShutdown(boolean val) {
requireShutdown |= val;
}
@@ -185,7 +208,10 @@
protected void modifyPluginsList(List<IdeaPluginDescriptor> list) {
IdeaPluginDescriptor[] selected = pluginTable.getSelectedObjects();
pluginsModel.updatePluginsList(list);
- pluginTable.getRowSorter().setSortKeys(Collections.singletonList(pluginsModel.getDefaultSortKey()));
+ final RowSorter.SortKey key = pluginsModel.getDefaultSortKey();
+ if (key != null) {
+ pluginTable.getRowSorter().setSortKeys(Collections.singletonList(key));
+ }
//pluginsModel.sort();
pluginsModel.filter(myFilter.getFilter().toLowerCase());
if (selected != null) {
@@ -195,6 +221,9 @@
protected abstract ActionGroup getActionGroup(boolean inToolbar);
+ protected abstract PluginManagerMain getAvailable();
+ protected abstract PluginManagerMain getInstalled();
+
public JPanel getMainPanel() {
return main;
}
@@ -254,7 +283,7 @@
propagateUpdates(list);
}
if (!errorMessages.isEmpty()) {
- if (0 == Messages.showOkCancelDialog(
+ if (Messages.OK == Messages.showOkCancelDialog(
IdeBundle.message("error.list.of.plugins.was.not.loaded", StringUtil.join(errorMessages, ", ")),
IdeBundle.message("title.plugins"),
CommonBundle.message("button.retry"), CommonBundle.getCancelButtonText(), Messages.getErrorIcon())) {
@@ -337,61 +366,62 @@
requireShutdown = false;
}
- public static void pluginInfoUpdate(Object plugin, @Nullable String filter, @NotNull JEditorPane descriptionTextArea) {
- if (plugin instanceof IdeaPluginDescriptor) {
- IdeaPluginDescriptor pluginDescriptor = (IdeaPluginDescriptor)plugin;
- StringBuilder sb = new StringBuilder();
+ public static void pluginInfoUpdate(IdeaPluginDescriptor plugin,
+ @Nullable String filter,
+ @NotNull JEditorPane descriptionTextArea,
+ @NotNull PluginHeaderPanel header, PluginManagerMain manager) {
- String description = pluginDescriptor.getDescription();
- if (!isEmptyOrSpaces(description)) {
- sb.append(description);
- }
-
- String changeNotes = pluginDescriptor.getChangeNotes();
- if (!isEmptyOrSpaces(changeNotes)) {
- sb.append("<h4>Change Notes</h4>");
- sb.append(changeNotes);
- }
-
- if (!pluginDescriptor.isBundled()) {
- String vendor = pluginDescriptor.getVendor();
- String vendorEmail = pluginDescriptor.getVendorEmail();
- String vendorUrl = pluginDescriptor.getVendorUrl();
- if (!isEmptyOrSpaces(vendor) || !isEmptyOrSpaces(vendorEmail) || !isEmptyOrSpaces(vendorUrl)) {
- sb.append("<h4>Vendor</h4>");
-
- if (!isEmptyOrSpaces(vendor)) {
- sb.append(vendor);
- }
- if (!isEmptyOrSpaces(vendorUrl)) {
- sb.append("<br>").append(composeHref(vendorUrl));
- }
- if (!isEmptyOrSpaces(vendorEmail)) {
- sb.append("<br>").append(composeHref("mailto:" + vendorEmail));
- }
- }
-
- String pluginDescriptorUrl = pluginDescriptor.getUrl();
- if (!isEmptyOrSpaces(pluginDescriptorUrl)) {
- sb.append("<h4>Plugin homepage</h4>").append(composeHref(pluginDescriptorUrl));
- }
-
- String version = pluginDescriptor.getVersion();
- if (!isEmptyOrSpaces(version)) {
- sb.append("<h4>Version</h4>").append(version);
- }
-
- String size = plugin instanceof PluginNode ? ((PluginNode)plugin).getSize() : null;
- if (!isEmptyOrSpaces(size)) {
- sb.append("<h4>Size</h4>").append(PluginManagerColumnInfo.getFormattedSize(size));
- }
- }
-
- setTextValue(sb, filter, descriptionTextArea);
- }
- else {
+ if (plugin == null) {
setTextValue(null, filter, descriptionTextArea);
+ header.getPanel().setVisible(false);
+ return;
}
+ StringBuilder sb = new StringBuilder();
+ header.setPlugin(plugin);
+ String description = plugin.getDescription();
+ if (!isEmptyOrSpaces(description)) {
+ sb.append(description);
+ }
+
+ String changeNotes = plugin.getChangeNotes();
+ if (!isEmptyOrSpaces(changeNotes)) {
+ sb.append("<h4>Change Notes</h4>");
+ sb.append(changeNotes);
+ }
+
+ if (!plugin.isBundled()) {
+ String vendor = plugin.getVendor();
+ String vendorEmail = plugin.getVendorEmail();
+ String vendorUrl = plugin.getVendorUrl();
+ if (!isEmptyOrSpaces(vendor) || !isEmptyOrSpaces(vendorEmail) || !isEmptyOrSpaces(vendorUrl)) {
+ sb.append("<h4>Vendor</h4>");
+
+ if (!isEmptyOrSpaces(vendor)) {
+ sb.append(vendor);
+ }
+ if (!isEmptyOrSpaces(vendorUrl)) {
+ sb.append("<br>").append(composeHref(vendorUrl));
+ }
+ if (!isEmptyOrSpaces(vendorEmail)) {
+ sb.append("<br>")
+ .append(HTML_PREFIX)
+ .append("mailto:").append(vendorEmail)
+ .append("\">").append(vendorEmail).append(HTML_SUFFIX);
+ }
+ }
+
+ String pluginDescriptorUrl = plugin.getUrl();
+ if (!isEmptyOrSpaces(pluginDescriptorUrl)) {
+ sb.append("<h4>Plugin homepage</h4>").append(composeHref(pluginDescriptorUrl));
+ }
+
+ String size = plugin instanceof PluginNode ? ((PluginNode)plugin).getSize() : null;
+ if (!isEmptyOrSpaces(size)) {
+ sb.append("<h4>Size</h4>").append(PluginManagerColumnInfo.getFormattedSize(size));
+ }
+ }
+
+ setTextValue(sb, filter, descriptionTextArea);
}
private static void setTextValue(@Nullable StringBuilder text, @Nullable String filter, JEditorPane pane) {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java
index 4010f46..d5e320a 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginManagerUISettings.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,10 +20,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.PerformInBackgroundOption;
import com.intellij.openapi.ui.SplitterProportionsData;
-import com.intellij.openapi.util.DefaultJDOMExternalizer;
-import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizableStringList;
-import com.intellij.openapi.util.WriteExternalException;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import org.jdom.Element;
@@ -47,7 +44,7 @@
public int AVAILABLE_SORT_COLUMN_ORDER = SortOrder.ASCENDING.ordinal();
- public int AVAILABLE_SORT_MODE = 0;
+ public int AVAILABLE_SORT_MODE = 1;
public boolean AVAILABLE_SORT_BY_STATUS = false;
public boolean INSTALLED_SORT_BY_STATUS = false;
public boolean UPDATE_IN_BACKGROUND = false;
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java
index e205a5f..21c2b41 100644
--- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.java
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginTable.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.
@@ -49,11 +49,7 @@
final ColumnInfo columnInfo = model.getColumnInfos()[i];
column.setCellEditor(columnInfo.getEditor(null));
if (columnInfo.getColumnClass() == Boolean.class) {
- final int width = new JCheckBox().getPreferredSize().width;
- column.setWidth(width);
- column.setPreferredWidth(width);
- column.setMaxWidth(width);
- column.setMinWidth(width);
+ TableUtil.setupCheckboxColumn(column);
}
}
@@ -86,6 +82,9 @@
return COPY;
}
});
+ if (model.getColumnCount() > 1) {
+ setColumnWidth(1, new JCheckBox().getPreferredSize().width + 4);
+ }
}
public void setColumnWidth(final int columnIndex, final int width) {
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form
new file mode 100644
index 0000000..597fc45
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.form
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.plugins.PluginsTableRenderer">
+ <grid id="27dc6" binding="myPanel" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <xy x="20" y="20" width="500" height="148"/>
+ </constraints>
+ <properties/>
+ <border type="none">
+ <size top="2" left="3" bottom="2" right="3"/>
+ </border>
+ <children>
+ <grid id="89d6b" 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 border-constraint="West"/>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="empty">
+ <size top="0" left="3" bottom="0" right="6"/>
+ </border>
+ <children>
+ <component id="7f1f5" class="com.intellij.ui.components.JBLabel" binding="myStatus">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Status"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <grid id="cebe0" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints border-constraint="Center"/>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <grid id="80605" layout-manager="GridLayoutManager" row-count="1" 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 border-constraint="South"/>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <component id="a2a1e" class="com.intellij.ui.components.JBLabel" binding="myCategory">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Category"/>
+ </properties>
+ </component>
+ <hspacer id="e204">
+ <constraints>
+ <grid row="0" 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>
+ </children>
+ </grid>
+ <grid id="6aad3" 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 border-constraint="North"/>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="empty">
+ <size top="0" left="0" bottom="2" right="0"/>
+ </border>
+ <children>
+ <component id="a5e28" class="com.intellij.ui.components.JBLabel" binding="myName">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Plugin Name"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ <grid id="10578" binding="myRightPanel" 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 border-constraint="East"/>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ <border type="empty">
+ <size top="0" left="3" bottom="0" right="3"/>
+ </border>
+ <children>
+ <component id="eeabb" class="com.intellij.ui.components.JBLabel" binding="myDownloads">
+ <constraints>
+ <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Downloads"/>
+ </properties>
+ </component>
+ <component id="8265" class="com.intellij.ui.components.JBLabel" binding="myLastUpdated">
+ <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="Last Updated"/>
+ </properties>
+ </component>
+ <vspacer id="10ec0">
+ <constraints>
+ <grid row="0" 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="37969" layout-manager="GridLayoutManager" row-count="1" 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>
+ <opaque value="false"/>
+ </properties>
+ <border type="none"/>
+ <children>
+ <component id="274f0" class="com.intellij.ide.plugins.RatesPanel" binding="myRating" custom-create="true">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <opaque value="false"/>
+ </properties>
+ </component>
+ <hspacer id="e5696">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
+ </children>
+ </grid>
+ </children>
+ </grid>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java
new file mode 100644
index 0000000..b20d9a6
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsTableRenderer.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.plugins;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.extensions.PluginId;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.ui.Gray;
+import com.intellij.ui.JBColor;
+import com.intellij.util.text.DateFormatUtil;
+import com.intellij.util.ui.UIUtil;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.table.DefaultTableCellRenderer;
+import java.awt.*;
+import java.text.DecimalFormat;
+
+/**
+* @author Konstantin Bulenkov
+*/
+public class PluginsTableRenderer extends DefaultTableCellRenderer {
+ private JLabel myName;
+ private JLabel myStatus;
+ private RatesPanel myRating;
+ private JLabel myDownloads;
+ private JLabel myLastUpdated;
+ private JPanel myPanel;
+
+ private JLabel myCategory;
+ private JPanel myRightPanel;
+ private final IdeaPluginDescriptor myPluginDescriptor;
+
+ public PluginsTableRenderer(IdeaPluginDescriptor pluginDescriptor) {
+ myPluginDescriptor = pluginDescriptor;
+
+ final Font smallFont = UIUtil.getLabelFont(SystemInfo.isMac ? UIUtil.FontSize.MINI : UIUtil.FontSize.SMALL);
+ myName.setFont(UIUtil.getLabelFont().deriveFont(UIUtil.getLabelFont().getSize() + 1.0f));
+ myStatus.setFont(smallFont);
+ myCategory.setFont(smallFont);
+ myDownloads.setFont(smallFont);
+ myStatus.setText("");
+ myCategory.setText("");
+ myLastUpdated.setFont(smallFont);
+ if (! (pluginDescriptor instanceof PluginNode)) {
+ myPanel.remove(myRightPanel);
+ }
+ myPanel.setBorder(UIUtil.isRetina() ? new EmptyBorder(4,3,4,3) : new EmptyBorder(2,3,2,3));
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
+ if (myPluginDescriptor != null) {
+ myName.setText(myPluginDescriptor.getName() + " ");
+
+ final Color fg = UIUtil.getTableForeground(isSelected);
+ final Color bg = UIUtil.getTableBackground(isSelected);
+ final Color grayedFg = isSelected ? fg : new JBColor(Gray._130, Gray._200);
+ myName.setForeground(fg);
+ myStatus.setForeground(grayedFg);
+ myStatus.setIcon(AllIcons.Nodes.Plugin);
+ String category = myPluginDescriptor.getCategory();
+ myCategory.setForeground(grayedFg);
+ if (category != null) {
+ myCategory.setText(category.toUpperCase() + " ");
+ }
+ if (myPluginDescriptor.isBundled()) {
+ myCategory.setText(myCategory.getText() + "[Bundled]");
+ }
+
+ myPanel.setBackground(bg);
+ myLastUpdated.setForeground(grayedFg);
+ myLastUpdated.setText("");
+ myDownloads.setForeground(grayedFg);
+ myDownloads.setText("");
+
+ final PluginNode pluginNode = myPluginDescriptor instanceof PluginNode ? (PluginNode)myPluginDescriptor : null;
+ if (pluginNode != null && pluginNode.getRepositoryName() == null) {
+ String downloads = pluginNode.getDownloads();
+ if (downloads == null) downloads= "";
+ if (downloads.length() > 3) {
+ downloads = new DecimalFormat("#,###").format(Integer.parseInt(downloads));
+ }
+ myDownloads.setText(downloads);
+
+ myRating.setRate(pluginNode.getRating());
+ myLastUpdated.setText(DateFormatUtil.formatBetweenDates(pluginNode.getDate(), System.currentTimeMillis()));
+ }
+
+ final IdeaPluginDescriptor installed = PluginManager.getPlugin(myPluginDescriptor.getPluginId());
+ if ((pluginNode != null && PluginManagerColumnInfo.isDownloaded(pluginNode)) ||
+ (installed != null && InstalledPluginsTableModel.wasUpdated(installed.getPluginId()))) {
+ if (!isSelected) myName.setForeground(FileStatus.ADDED.getColor());
+ //todo[kb] set proper icon
+ //myStatus.setText("[Downloaded]");
+ //myPanel.setToolTipText(IdeBundle.message("plugin.download.status.tooltip"));
+ //myStatus.setBorder(BorderFactory.createEmptyBorder(0, LEFT_MARGIN, 0, 0));
+ }
+ else if (pluginNode != null && pluginNode.getStatus() == PluginNode.STATUS_INSTALLED) {
+ PluginId pluginId = pluginNode.getPluginId();
+ final boolean hasNewerVersion = InstalledPluginsTableModel.hasNewerVersion(pluginId);
+ if (!isSelected) myName.setForeground(FileStatus.MODIFIED.getColor());
+ if (hasNewerVersion) {
+ if (!isSelected) {
+ myName.setForeground(JBColor.RED);
+ }
+ myName.setIcon(AllIcons.Nodes.Pluginobsolete);
+ }
+ //todo[kb] set proper icon
+ //myStatus.setText("v." + pluginNode.getInstalledVersion() + (hasNewerVersion ? (" -> " + pluginNode.getVersion()) : ""));
+ }
+ }
+
+ return myPanel;
+ }
+
+ private void createUIComponents() {
+ myRating = new RatesPanel();
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/RatesPanel.java b/platform/platform-impl/src/com/intellij/ide/plugins/RatesPanel.java
new file mode 100644
index 0000000..18e5b1c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/RatesPanel.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.plugins;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.IconLoader;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+* @author Konstantin Bulenkov
+*/
+public class RatesPanel extends JPanel {
+ public static int MAX_RATE = 5;
+
+ private static final Icon STAR = AllIcons.Ide.Rating;
+
+ private static final Icon STAR3 = AllIcons.Ide.Rating1;
+ private static final Icon STAR4 = AllIcons.Ide.Rating2;
+ private static final Icon STAR5 = AllIcons.Ide.Rating3;
+ private static final Icon STAR6 = AllIcons.Ide.Rating4;
+ private static final Icon[] STARs = new Icon[]{IconLoader.getDisabledIcon(STAR), STAR3, STAR3, STAR4, STAR4, STAR5, STAR5, STAR6, STAR6, STAR};
+
+ private JLabel[] myLabels = new JLabel[MAX_RATE];
+
+ public RatesPanel() {
+ super(new GridBagLayout());
+ setOpaque(false);
+ GridBagConstraints gc =
+ new GridBagConstraints(GridBagConstraints.RELATIVE, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE,
+ new Insets(0, 0, 0, 0), 0, 0);
+ for (int i = 0, myLabelsLength = myLabels.length; i < myLabelsLength; i++) {
+ myLabels[i] = new JLabel();
+ myLabels[i].setOpaque(false);
+ add(myLabels[i], gc);
+ }
+ }
+
+ public void setRate(String rating) {
+ Double dblRating = 0d;
+ try {
+ dblRating = Double.valueOf(rating);
+ } catch (Exception ignore) {}
+
+ final int intRating = dblRating.intValue();
+
+ for (int i = 0; i < intRating; i++) {
+ myLabels[i].setIcon(STAR);
+ }
+
+ if (intRating < MAX_RATE) {
+ myLabels[intRating].setIcon(STARs[((Double)(dblRating * 10)).intValue() % 10]);
+ for (int i = 1 + intRating; i < MAX_RATE; i++) {
+ myLabels[i].setIcon(IconLoader.getDisabledIcon(STAR));
+ }
+ }
+ }
+
+ @Override
+ public Dimension getPreferredSize() {
+ return new Dimension(55, 11);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/UninstallPluginAction.java b/platform/platform-impl/src/com/intellij/ide/plugins/UninstallPluginAction.java
new file mode 100644
index 0000000..f666148
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/plugins/UninstallPluginAction.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.plugins;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.extensions.PluginId;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.JDOMExternalizableStringList;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class UninstallPluginAction extends AnAction implements DumbAware {
+ private final PluginTable pluginTable;
+ private final PluginManagerMain host;
+
+ public UninstallPluginAction(PluginManagerMain mgr, PluginTable table) {
+ super(IdeBundle.message("action.uninstall.plugin"), IdeBundle.message("action.uninstall.plugin"), AllIcons.Actions.Uninstall);
+
+ pluginTable = table;
+ host = mgr;
+ }
+
+ public void update(AnActionEvent e) {
+ Presentation presentation = e.getPresentation();
+ if (!pluginTable.isShowing()) {
+ presentation.setEnabled(false);
+ return;
+ }
+ IdeaPluginDescriptor[] selection = pluginTable.getSelectedObjects();
+ boolean enabled = (selection != null);
+
+ if (enabled) {
+ for (IdeaPluginDescriptor descriptor : selection) {
+ if (descriptor instanceof IdeaPluginDescriptorImpl) {
+ final IdeaPluginDescriptorImpl ideaPluginDescriptor = (IdeaPluginDescriptorImpl)descriptor;
+ if (ideaPluginDescriptor.isDeleted() || ideaPluginDescriptor.isBundled()) {
+ enabled = false;
+ break;
+ }
+ }
+ if (descriptor instanceof PluginNode) {
+ enabled = false;
+ break;
+ }
+ }
+ }
+ presentation.setEnabled(enabled);
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ uninstall(host, pluginTable.getSelectedObjects());
+ pluginTable.updateUI();
+ }
+
+ public static void uninstall(PluginManagerMain host, IdeaPluginDescriptor... selection) {
+ String message;
+
+ if (selection.length == 1) {
+ message = IdeBundle.message("prompt.uninstall.plugin", selection[0].getName());
+ }
+ else {
+ message = IdeBundle.message("prompt.uninstall.several.plugins", selection.length);
+ }
+ if (Messages.showYesNoDialog(host.getMainPanel(), message, IdeBundle.message("title.plugin.uninstall"), Messages.getQuestionIcon()) != Messages.YES) return;
+
+ for (IdeaPluginDescriptor descriptor : selection) {
+ IdeaPluginDescriptorImpl pluginDescriptor = (IdeaPluginDescriptorImpl)descriptor;
+
+ boolean actualDelete = true;
+
+ // Get the list of plugins which depend on this one. If this list is
+ // not empty - issue warning instead of simple prompt.
+ ArrayList<IdeaPluginDescriptorImpl> dependant = host.getDependentList(pluginDescriptor);
+ if (dependant.size() > 0) {
+ message = IdeBundle.message("several.plugins.depend.on.0.continue.to.remove", pluginDescriptor.getName());
+ actualDelete = (Messages.showYesNoDialog(host.getMainPanel(), message, IdeBundle.message("title.plugin.uninstall"), Messages.getQuestionIcon()) == Messages.YES);
+ }
+
+ if (actualDelete) {
+ uninstallPlugin(pluginDescriptor, host);
+ }
+ }
+ }
+
+ private static void uninstallPlugin(IdeaPluginDescriptorImpl descriptor, PluginManagerMain host) {
+ PluginId pluginId = descriptor.getPluginId();
+ descriptor.setDeleted(true);
+
+ try {
+ PluginInstaller.prepareToUninstall(pluginId);
+ final JDOMExternalizableStringList installedPlugins = PluginManagerUISettings.getInstance().getInstalledPlugins();
+ final String pluginIdString = pluginId.getIdString();
+ while (installedPlugins.contains(pluginIdString)) {
+ installedPlugins.remove(pluginIdString);
+ }
+ host.setRequireShutdown(descriptor.isEnabled());
+ }
+ catch (IOException e1) {
+ PluginManagerMain.LOG.error(e1);
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ide/startupWizard/SelectPluginsStep.java b/platform/platform-impl/src/com/intellij/ide/startupWizard/SelectPluginsStep.java
index c2f9787..e000ecb 100644
--- a/platform/platform-impl/src/com/intellij/ide/startupWizard/SelectPluginsStep.java
+++ b/platform/platform-impl/src/com/intellij/ide/startupWizard/SelectPluginsStep.java
@@ -25,6 +25,7 @@
import com.intellij.ui.wizard.WizardStep;
import com.intellij.util.Function;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -98,7 +99,7 @@
final int clickableArea = new JCheckBox("").getMinimumSize().width;
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (e.getX() < clickableArea) {
toggleSelection();
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizableActionsPanel.java b/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizableActionsPanel.java
index 4e84378..c28c7b0 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizableActionsPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/customization/CustomizableActionsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -47,6 +47,7 @@
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.ImageLoader;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
import com.intellij.util.ui.tree.TreeUtil;
@@ -329,7 +330,7 @@
final int exitCode = Messages.showOkCancelDialog(IdeBundle.message("error.adding.action.without.icon.to.toolbar"),
IdeBundle.message("title.unable.to.add.action.without.icon.to.toolbar"),
Messages.getInformationIcon());
- if (exitCode == DialogWrapper.OK_EXIT_CODE) {
+ if (exitCode == Messages.OK) {
mySelectedSchema.addIconCustomization(actionId, null);
anAction.getTemplatePresentation().setIcon(AllIcons.Toolbar.Unknown);
anAction.setDefaultIcon(false);
@@ -458,10 +459,7 @@
Group group = (Group)userObject;
String name = group.getName();
setText(name != null ? name : group.getId());
- icon = group.getIcon();
- if (icon == null) {
- icon = getClosedIcon();
- }
+ icon = ObjectUtils.notNull(group.getIcon(), AllIcons.Nodes.Folder);
}
else if (userObject instanceof String) {
String actionId = (String)userObject;
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java
index 47558fe..e03e3c3 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/IdeaLaf.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,9 @@
package com.intellij.ide.ui.laf;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ColoredSideBorder;
import com.intellij.ui.plaf.beg.*;
import com.intellij.util.ui.UIUtil;
@@ -41,7 +43,8 @@
LafManagerImpl.initInputMapDefaults(defaults);
initIdeaDefaults(defaults);
- Pair<String, Integer> systemFont = UIUtil.getSystemFontData();
+ final UISettings ui = UISettings.getInstance();
+ Pair<String, Integer> systemFont = SystemInfo.isWindows ? Pair.create(ui.FONT_FACE, ui.FONT_SIZE) : UIUtil.getSystemFontData();
if (systemFont != null) {
LafManagerImpl.initFontDefaults(defaults, systemFont.first, systemFont.second);
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
index 97b6745..738868c 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/LafManagerImpl.java
@@ -135,12 +135,11 @@
}
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) {
String name = laf.getName();
- if (Registry.is("show.all.look.and.feels") ||
- ( !"Metal".equalsIgnoreCase(name)
- && !"CDE/Motif".equalsIgnoreCase(name)
- && !"Nimbus".equalsIgnoreCase(name)
- && !"Windows Classic".equalsIgnoreCase(name)
- && !name.startsWith("JGoodies"))) {
+ if ( !"Metal".equalsIgnoreCase(name)
+ && !"CDE/Motif".equalsIgnoreCase(name)
+ && !"Nimbus".equalsIgnoreCase(name)
+ && !"Windows Classic".equalsIgnoreCase(name)
+ && !name.startsWith("JGoodies")) {
lafList.add(laf);
}
}
@@ -155,6 +154,7 @@
if (!SystemInfo.isMac) {
// do not sort LaFs on mac - the order is determined as Default, Darcula.
// when we leave only system LaFs on other OSes, the order also should be determined as Default, Darcula
+
Arrays.sort(myLaFs, new Comparator<UIManager.LookAndFeelInfo>() {
@Override
public int compare(UIManager.LookAndFeelInfo obj1, UIManager.LookAndFeelInfo obj2) {
@@ -460,7 +460,7 @@
if (confirm) {
final String[] options = {IdeBundle.message("confirm.set.look.and.feel"), CommonBundle.getCancelButtonText()};
final int result = Messages.showOkCancelDialog(message, CommonBundle.getWarningTitle(), options[0], options[1], Messages.getWarningIcon());
- if (result == 0) {
+ if (result == Messages.OK) {
myLastWarning = message;
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java
index 8344afb..4a9b85c 100644
--- a/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java
+++ b/platform/platform-impl/src/com/intellij/ide/ui/laf/darcula/ui/DarculaButtonPainter.java
@@ -36,19 +36,19 @@
final Graphics2D g2d = (Graphics2D)g;
final Insets ins = getBorderInsets(c);
final int yOff = (ins.top + ins.bottom) / 4;
- int offset = getOffset();
+ final boolean square = DarculaButtonUI.isSquare(c);
+ int offset = square ? 1 : getOffset();
if (c.hasFocus()) {
DarculaUIUtil.paintFocusRing(g2d, offset, yOff, width - 2 * offset, height - 2 * yOff);
} else {
final GraphicsConfig config = new GraphicsConfig(g);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_DEFAULT);
- g2d.setPaint(
- UIUtil.getGradientPaint(width / 2, y + yOff + 1, Gray._80.withAlpha(90), width / 2, height - 2 * yOff, Gray._90.withAlpha(90)));
+ g2d.setPaint(UIUtil.getGradientPaint(width / 2, y + yOff + 1, Gray._80.withAlpha(90), width / 2, height - 2 * yOff, Gray._90.withAlpha(90)));
//g.drawRoundRect(x + offset + 1, y + yOff + 1, width - 2 * offset, height - 2*yOff, 5, 5);
((Graphics2D)g).setPaint(Gray._100.withAlpha(180));
- g.drawRoundRect(x + offset, y + yOff, width - 2 * offset, height - 2*yOff, 5, 5);
+ g.drawRoundRect(x + offset, y + yOff, width - 2 * offset, height - 2*yOff, square ? 3 : 5, square ? 3 : 5);
config.restore();
}
@@ -56,6 +56,9 @@
@Override
public Insets getBorderInsets(Component c) {
+ if (DarculaButtonUI.isSquare(c)) {
+ return new InsetsUIResource(2, 0, 2, 0);
+ }
return new InsetsUIResource(8, 16, 8, 14);
}
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 5d36876..f4fbc75 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
@@ -37,20 +37,27 @@
return new DarculaButtonUI();
}
+ public static boolean isSquare(Component c) {
+ return c instanceof JButton && "square".equals(((JButton)c).getClientProperty("JButton.buttonType"));
+ }
+
@Override
public void paint(Graphics g, JComponent c) {
final Border border = c.getBorder();
final GraphicsConfig config = GraphicsUtil.setupAAPainting(g);
+ final boolean square = isSquare(c);
if (c.isEnabled() && border != null) {
final Insets ins = border.getBorderInsets(c);
final int yOff = (ins.top + ins.bottom) / 4;
- if (((JButton)c).isDefaultButton()) {
- ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(0, 0, getSelectedButtonColor1(), 0, c.getHeight(), getSelectedButtonColor2()));
+ if (!square) {
+ if (((JButton)c).isDefaultButton()) {
+ ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(0, 0, getSelectedButtonColor1(), 0, c.getHeight(), getSelectedButtonColor2()));
+ }
+ else {
+ ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(0, 0, getButtonColor1(), 0, c.getHeight(), getButtonColor2()));
+ }
}
- else {
- ((Graphics2D)g).setPaint(UIUtil.getGradientPaint(0, 0, getButtonColor1(), 0, c.getHeight(), getButtonColor2()));
- }
- g.fillRoundRect(4, yOff, c.getWidth() - 2 * 4, c.getHeight() - 2 * yOff, 5, 5);
+ g.fillRoundRect(square ? 2 : 4, yOff, c.getWidth() - 2 * 4, c.getHeight() - 2 * yOff, square ? 3 : 5, square ? 3 : 5);
}
config.restore();
super.paint(g, c);
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 388f9c4..116adfe 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
@@ -31,7 +31,7 @@
link.foreground=589df6
ScrollBarUI=com.intellij.ide.ui.laf.darcula.ui.DarculaScrollBarUI
-Label.disabledForeground=999999
+Label.disabledForeground=777777
TableHeaderUI=com.intellij.ide.ui.laf.darcula.DarculaTableHeaderUI
Table.gridColor=dddddd
@@ -151,6 +151,8 @@
Tree.textBackground=ffffff
Tree.selectionBorderColor=3875d6
+EditorPane.background=ffffff
+
List.background=ffffff
Hyperlink.linkColor=589df6
diff --git a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
index 83d4893..2b8a8a4 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/ElementsChooser.java
@@ -71,13 +71,11 @@
myTable.setColumnSelectionAllowed(false);
JScrollPane pane = ScrollPaneFactory.createScrollPane(myTable);
pane.setPreferredSize(new Dimension(100, 155));
- int width = new JCheckBox().getPreferredSize().width;
TableColumnModel columnModel = myTable.getColumnModel();
if (elementsCanBeMarked) {
TableColumn checkMarkColumn = columnModel.getColumn(myTableModel.CHECK_MARK_COLUM_INDEX);
- checkMarkColumn.setPreferredWidth(width);
- checkMarkColumn.setMaxWidth(width);
+ TableUtil.setupCheckboxColumn(checkMarkColumn);
checkMarkColumn.setCellRenderer(new CheckMarkColumnCellRenderer(myTable.getDefaultRenderer(Boolean.class)));
}
columnModel.getColumn(myTableModel.ELEMENT_COLUMN_INDEX).setCellRenderer(new MyElementColumnCellRenderer());
diff --git a/platform/platform-impl/src/com/intellij/ide/util/ExportToFileUtil.java b/platform/platform-impl/src/com/intellij/ide/util/ExportToFileUtil.java
index b5fda7d..96e5a15 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/ExportToFileUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/ExportToFileUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -69,10 +69,10 @@
Messages.getWarningIcon()
);
- if (result != 1 && result != 0) {
+ if (result != Messages.NO && result != Messages.YES) {
return;
}
- if (result == 1) {
+ if (result == Messages.NO) {
char[] buf = new char[(int)file.length()];
try {
FileReader reader = new FileReader(fileName);
diff --git a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java
index 8d0387a..10d360b 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/GotoLineNumberDialog.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.
@@ -45,6 +45,7 @@
try {
final int offset = Integer.parseInt(myOffsetField.getText());
if (offset < myEditor.getDocument().getTextLength()) {
+ myEditor.getCaretModel().removeSecondaryCarets();
myEditor.getCaretModel().moveToOffset(offset);
myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
myEditor.getSelectionModel().removeSelection();
@@ -60,6 +61,7 @@
if (lineNumber < 0) return;
int columnNumber = getColumnNumber(currentPosition.column);
+ myEditor.getCaretModel().removeSecondaryCarets();
myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(Math.max(0, lineNumber - 1), Math.max(0, columnNumber - 1)));
myEditor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
myEditor.getSelectionModel().removeSelection();
diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipAndTrickBean.java b/platform/platform-impl/src/com/intellij/ide/util/TipAndTrickBean.java
new file mode 100644
index 0000000..fcaa09c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ide/util/TipAndTrickBean.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.util;
+
+import com.intellij.openapi.extensions.AbstractExtensionPointBean;
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.util.xmlb.annotations.Attribute;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author gregsh
+ */
+public class TipAndTrickBean extends AbstractExtensionPointBean {
+ public static final ExtensionPointName<TipAndTrickBean> EP_NAME = ExtensionPointName.create("com.intellij.tipAndTrick");
+
+ @Attribute("file")
+ public String myFileName;
+
+ @Attribute("feature-id")
+ public String myFeatureId;
+
+ public String getFileName() {
+ return myFileName;
+ }
+
+ public String getFeatureId() {
+ return myFeatureId;
+ }
+
+ @Nullable
+ public static TipAndTrickBean findByFileName(String tipFileName) {
+ for (TipAndTrickBean tip : Extensions.getExtensions(EP_NAME)) {
+ if (Comparing.equal(tipFileName, tip.getFileName())) {
+ return tip;
+ }
+ }
+ return null;
+ }
+}
+
diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java
index 7f50043..2ef145f 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/TipDialog.java
@@ -19,6 +19,7 @@
import com.intellij.CommonBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.impl.DialogWrapperPeerImpl;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -37,6 +38,9 @@
setHorizontalStretch(1.33f);
setVerticalStretch(1.25f);
init();
+ if (getPeer() instanceof DialogWrapperPeerImpl) {
+ ((DialogWrapperPeerImpl)getPeer()).setAutoRequestFocus(false);
+ }
}
@NotNull
diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java b/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java
index 8ccdda2..e44be06 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/TipPanel.java
@@ -15,18 +15,17 @@
*/
package com.intellij.ide.util;
-import com.intellij.featureStatistics.FeatureDescriptor;
-import com.intellij.featureStatistics.ProductivityFeaturesProvider;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.BrowserUtil;
import com.intellij.ide.GeneralSettings;
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.extensions.Extensions;
import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
-import org.jdom.Document;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
@@ -35,20 +34,16 @@
import java.awt.*;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
-import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.List;
public class TipPanel extends JPanel {
private static final int DEFAULT_WIDTH = 400;
private static final int DEFAULT_HEIGHT = 200;
- private final JCheckBox myCheckBox;
- private final JEditorPane browser;
- private final ArrayList<String> myTipPaths = new ArrayList<String>();
- private final HashMap<String, Class< ? extends ProductivityFeaturesProvider>> myPathsToProviderMap = new HashMap<String, Class<? extends ProductivityFeaturesProvider>>();
- @NonNls
- private static final String ELEMENT_TIP = "tip";
- @NonNls
- private static final String ATTRIBUTE_FILE = "file";
+
+ private final JEditorPane myBrowserPanel;
+ private final JLabel myPoweredByLabel;
+ private final List<TipAndTrickBean> myTips = ContainerUtil.newArrayList();
public TipPanel() {
setLayout(new BorderLayout());
@@ -63,45 +58,42 @@
jpanel.add(jlabel1, BorderLayout.CENTER);
jpanel.setBorder(BorderFactory.createEmptyBorder(5, 0, 5, 0));
add(jpanel, BorderLayout.NORTH);
- browser = new JEditorPane();
- browser.setEditable(false);
- browser.setEditorKit(new HTMLEditorKit());
- browser.setBackground(UIUtil.getTextFieldBackground());
- browser.addHyperlinkListener(
+ myBrowserPanel = new JEditorPane();
+ myBrowserPanel.setEditable(false);
+ myBrowserPanel.setEditorKit(new HTMLEditorKit());
+ myBrowserPanel.setBackground(UIUtil.getTextFieldBackground());
+ myBrowserPanel.addHyperlinkListener(
new HyperlinkListener() {
public void hyperlinkUpdate(HyperlinkEvent e) {
if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- //TODO: Open url in browser
+ BrowserUtil.browse(e.getURL());
}
}
}
);
- JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(browser);
+ JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myBrowserPanel);
add(scrollPane, BorderLayout.CENTER);
- myCheckBox = new JCheckBox(IdeBundle.message("checkbox.show.tips.on.startup"), true);
- myCheckBox.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
+
+ JPanel southPanel = new JPanel(new BorderLayout());
+ JCheckBox showOnStartCheckBox = new JCheckBox(IdeBundle.message("checkbox.show.tips.on.startup"), true);
+ showOnStartCheckBox.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
final GeneralSettings settings = GeneralSettings.getInstance();
- myCheckBox.setSelected(settings.showTipsOnStartup());
- myCheckBox.addItemListener(new ItemListener() {
+ showOnStartCheckBox.setSelected(settings.showTipsOnStartup());
+ showOnStartCheckBox.addItemListener(new ItemListener() {
public void itemStateChanged(ItemEvent e) {
settings.setShowTipsOnStartup(e.getStateChange() == ItemEvent.SELECTED);
}
});
- add(myCheckBox, BorderLayout.SOUTH);
- try {
- readTips("/tips/tips.xml");
- readTips("/tips/IdeSpecificTips.xml");
- }
- catch (Exception exception) {//
- }
+ southPanel.add(showOnStartCheckBox, BorderLayout.WEST);
- for (ProductivityFeaturesProvider provider : ProductivityFeaturesProvider.EP_NAME.getExtensions()) {
- final FeatureDescriptor[] descriptors = provider.getFeatureDescriptors();
- for (int j = 0; descriptors != null && j < descriptors.length; j++) {
- FeatureDescriptor descriptor = descriptors[j];
- myPathsToProviderMap.put(descriptor.getTipFileName(), descriptor.getProvider());
- }
- }
+ myPoweredByLabel = new JBLabel();
+ myPoweredByLabel.setHorizontalAlignment(SwingConstants.RIGHT);
+ myPoweredByLabel.setForeground(SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES.getFgColor());
+
+ southPanel.add(myPoweredByLabel, BorderLayout.EAST);
+ add(southPanel, BorderLayout.SOUTH);
+
+ Collections.addAll(myTips, Extensions.getExtensions(TipAndTrickBean.EP_NAME));
}
public Dimension getPreferredSize() {
@@ -109,57 +101,49 @@
}
public void prevTip() {
- if (myTipPaths.size() == 0) {
- browser.setText(IdeBundle.message("error.tips.not.found", ApplicationNamesInfo.getInstance().getFullProductName()));
+ if (myTips.size() == 0) {
+ myBrowserPanel.setText(IdeBundle.message("error.tips.not.found", ApplicationNamesInfo.getInstance().getFullProductName()));
return;
}
final GeneralSettings settings = GeneralSettings.getInstance();
int lastTip = settings.getLastTip();
- final String path;
+ final TipAndTrickBean tip;
lastTip--;
if (lastTip <= 0) {
- path = myTipPaths.get(myTipPaths.size() - 1);
- lastTip = myTipPaths.size();
+ tip = myTips.get(myTips.size() - 1);
+ lastTip = myTips.size();
}
else {
- path = myTipPaths.get(lastTip - 1);
+ tip = myTips.get(lastTip - 1);
}
- setTip(path, lastTip, browser, settings);
+ setTip(tip, lastTip, myBrowserPanel, settings);
}
- private void setTip (String path, int lastTip, JEditorPane browser, GeneralSettings settings) {
- TipUIUtil.openTipInBrowser(path, browser, myPathsToProviderMap.get(path));
+ private void setTip (TipAndTrickBean tip, int lastTip, JEditorPane browser, GeneralSettings settings) {
+ TipUIUtil.openTipInBrowser(tip, browser);
+ myPoweredByLabel.setText(TipUIUtil.getPoweredByText(tip));
settings.setLastTip(lastTip);
}
public void nextTip() {
- if (myTipPaths.size() == 0) {
- browser.setText(IdeBundle.message("error.tips.not.found", ApplicationNamesInfo.getInstance().getFullProductName()));
+ if (myTips.size() == 0) {
+ myBrowserPanel.setText(IdeBundle.message("error.tips.not.found", ApplicationNamesInfo.getInstance().getFullProductName()));
return;
}
GeneralSettings settings = GeneralSettings.getInstance();
int lastTip = settings.getLastTip();
- String path;
+ TipAndTrickBean tip;
lastTip++;
- if (lastTip - 1 >= myTipPaths.size()) {
- path = myTipPaths.get(0);
+ if (lastTip - 1 >= myTips.size()) {
+ tip = myTips.get(0);
lastTip = 1;
}
else {
- path = myTipPaths.get(lastTip - 1);
+ tip = myTips.get(lastTip - 1);
}
- setTip(path, lastTip, browser, settings);
- }
-
- private void readTips(String tipsURL) throws Exception {
- final Document document = JDOMUtil.loadDocument(getClass().getResource(tipsURL).openStream());
-
- for (Object o : document.getRootElement().getChildren(ELEMENT_TIP)) {
- Element tip = (Element)o;
- myTipPaths.add(tip.getAttributeValue(ATTRIBUTE_FILE));
- }
+ setTip(tip, lastTip, myBrowserPanel, settings);
}
}
diff --git a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java
index 758d411..0fb2bbe 100644
--- a/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ide/util/TipUIUtil.java
@@ -16,17 +16,23 @@
package com.intellij.ide.util;
import com.intellij.ide.IdeBundle;
+import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.actionSystem.KeyboardShortcut;
import com.intellij.openapi.actionSystem.Shortcut;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationNamesInfo;
+import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.keymap.Keymap;
import com.intellij.openapi.keymap.KeymapManager;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.keymap.impl.DefaultKeymap;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.ResourceUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.imageio.ImageIO;
@@ -38,6 +44,7 @@
/**
* @author dsl
+ * @author Konstantin Bulenkov
*/
public class TipUIUtil {
@NonNls private static final String SHORTCUT_ENTITY = "&shortcut:";
@@ -45,7 +52,25 @@
private TipUIUtil() {
}
- public static void openTipInBrowser(String tipPath, JEditorPane browser, Class providerClass) {
+ @NotNull
+ public static String getPoweredByText(@NotNull TipAndTrickBean tip) {
+ PluginDescriptor descriptor = tip.getPluginDescriptor();
+ return descriptor instanceof IdeaPluginDescriptor &&
+ !PluginManagerCore.CORE_PLUGIN_ID.equals(descriptor.getPluginId().getIdString()) ?
+ ((IdeaPluginDescriptor)descriptor).getName() : "";
+ }
+
+ public static void openTipInBrowser(String tipFileName, JEditorPane browser, Class providerClass) {
+ TipAndTrickBean tip = TipAndTrickBean.findByFileName(tipFileName);
+ if (tip == null && StringUtil.isNotEmpty(tipFileName)) {
+ tip = new TipAndTrickBean();
+ tip.myFileName = tipFileName;
+ }
+ openTipInBrowser(tip, browser);
+ }
+
+ public static void openTipInBrowser(@Nullable TipAndTrickBean tip, JEditorPane browser) {
+ if (tip == null) return;
/* TODO: detect that file is not present
if (!file.exists()) {
browser.read(new StringReader("Tips for '" + feature.getDisplayName() + "' not found. Make sure you installed IntelliJ IDEA correctly."), null);
@@ -53,18 +78,20 @@
}
*/
try {
- if (tipPath == null) return;
- if (providerClass == null) providerClass = TipUIUtil.class;
- URL url = ResourceUtil.getResource(providerClass, "/tips/", tipPath);
+ PluginDescriptor pluginDescriptor = tip.getPluginDescriptor();
+ ClassLoader tipLoader = pluginDescriptor == null ? TipUIUtil.class.getClassLoader() :
+ ObjectUtils.notNull(pluginDescriptor.getPluginClassLoader(), TipUIUtil.class.getClassLoader());
+
+ URL url = ResourceUtil.getResource(tipLoader, "/tips/", tip.getFileName());
if (url == null) {
- setCantReadText(browser, tipPath);
+ setCantReadText(browser, tip);
return;
}
StringBuffer text = new StringBuffer(ResourceUtil.loadText(url));
updateShortcuts(text);
- updateImages(text, providerClass);
+ updateImages(text, tipLoader);
String replaced = text.toString().replace("&productName;", ApplicationNamesInfo.getInstance().getFullProductName());
replaced = replaced.replace("&majorVersion;", ApplicationInfo.getInstance().getMajorVersion());
replaced = replaced.replace("&minorVersion;", ApplicationInfo.getInstance().getMinorVersion());
@@ -74,11 +101,11 @@
browser.read(new StringReader(replaced), url);
}
catch (IOException e) {
- setCantReadText(browser, tipPath);
+ setCantReadText(browser, tip);
}
}
- private static void setCantReadText(JEditorPane browser, String missingFile) {
+ private static void setCantReadText(JEditorPane browser, TipAndTrickBean missingFile) {
try {
browser.read(new StringReader(
IdeBundle.message("error.unable.to.read.tip.of.the.day", missingFile, ApplicationNamesInfo.getInstance().getFullProductName())), null);
@@ -87,7 +114,7 @@
}
}
- private static void updateImages(StringBuffer text, Class providerClass) {
+ private static void updateImages(StringBuffer text, ClassLoader tipLoader) {
final boolean dark = UIUtil.isUnderDarcula();
final boolean retina = UIUtil.isRetina();
// if (!dark && !retina) {
@@ -108,7 +135,7 @@
String path = img.substring(srcIndex + 5, endIndex);
if (!path.endsWith("_dark") && !path.endsWith("@2x")) {
path += suffix + ".png";
- URL url = ResourceUtil.getResource(providerClass, "/tips/", path);
+ URL url = ResourceUtil.getResource(tipLoader, "/tips/", path);
if (url != null) {
String newImgTag = "<img src=\"" + path + "\" ";
if (retina) {
diff --git a/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java b/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java
index ca5d6c2..e7df9e4 100644
--- a/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java
+++ b/platform/platform-impl/src/com/intellij/idea/CommandLineApplication.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,6 @@
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.UserDataHolderBase;
-import com.intellij.openapi.vfs.impl.local.FileWatcher;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -28,32 +27,20 @@
public class CommandLineApplication {
private static final Logger LOG = Logger.getInstance("#com.intellij.idea.CommandLineApplication");
+
protected static CommandLineApplication ourInstance = null;
static {
- System.setProperty(FileWatcher.PROPERTY_WATCHER_DISABLED, Boolean.TRUE.toString());
-
- /*
- final Category category = Category.getRoot();
- final Enumeration enumeration = category.getAllAppenders();
- while (enumeration.hasMoreElements()) {
- Object o = enumeration.nextElement();
- if (o instanceof DialogAppender) {
- category.removeAppender((Appender)o);
- break;
- }
- }
- */
+ System.setProperty("idea.filewatcher.disabled", "true");
}
- protected CommandLineApplication() {}
-
protected CommandLineApplication(boolean isInternal, boolean isUnitTestMode, boolean isHeadless) {
- this(isInternal, isUnitTestMode, isHeadless, "idea");
+ this(isInternal, isUnitTestMode, isHeadless, ApplicationManagerEx.IDEA_APPLICATION);
}
protected CommandLineApplication(boolean isInternal, boolean isUnitTestMode, boolean isHeadless, @NotNull @NonNls String appName) {
LOG.assertTrue(ourInstance == null, "Only one instance allowed.");
+ //noinspection AssignmentToStaticFieldFromInstanceMethod
ourInstance = this;
ApplicationManagerEx.createApplication(isInternal, isUnitTestMode, isHeadless, true, appName, null);
}
diff --git a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
index 7e09043..53dae25 100644
--- a/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
+++ b/platform/platform-impl/src/com/intellij/idea/IdeaApplication.java
@@ -23,7 +23,10 @@
import com.intellij.ide.IdeRepaintManager;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
-import com.intellij.openapi.application.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationStarter;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
@@ -32,13 +35,10 @@
import com.intellij.openapi.extensions.ExtensionPoint;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.updateSettings.impl.UpdateChecker;
-import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.SystemDock;
import com.intellij.openapi.wm.impl.WindowManagerImpl;
@@ -98,7 +98,7 @@
}
}
- ApplicationManagerEx.createApplication(isInternal, false, false, false, "idea", splash);
+ ApplicationManagerEx.createApplication(isInternal, false, false, false, ApplicationManagerEx.IDEA_APPLICATION, splash);
}
if (myStarter == null) {
@@ -261,16 +261,6 @@
loadProject();
}
- final UpdateSettings settings = UpdateSettings.getInstance();
- if (settings != null) {
- final ApplicationInfo appInfo = ApplicationInfo.getInstance();
- if (StringUtil.compareVersionNumbers(settings.LAST_BUILD_CHECKED, appInfo.getBuild().asString()) < 0 ||
- (UpdateChecker.isMyVeryFirstOpening() && UpdateChecker.checkNeeded())) {
- UpdateChecker.setMyVeryFirstOpening(false);
- UpdateChecker.updateAndShowResult();
- }
- }
-
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
diff --git a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
index 0a49856..4f315ee 100644
--- a/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
+++ b/platform/platform-impl/src/com/intellij/idea/StartupUtil.java
@@ -32,15 +32,16 @@
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.SnappyInitializer;
import com.intellij.util.lang.UrlClassLoader;
-import com.intellij.util.text.DateFormatUtilRt;
import com.sun.jna.Native;
import org.jetbrains.annotations.NonNls;
import javax.swing.*;
import java.io.File;
import java.lang.management.ManagementFactory;
+import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.List;
+import java.util.Locale;
/**
* @author yole
@@ -213,6 +214,9 @@
}
private static void fixProcessEnvironment(Logger log) {
+ if (!Main.isCommandLine()) {
+ System.setProperty("__idea.mac.env.lock", "unlocked");
+ }
boolean envReady = EnvironmentUtil.isEnvironmentReady(); // trigger environment loading
if (!envReady) {
log.info("initializing environment");
@@ -281,8 +285,8 @@
ApplicationInfo appInfo = ApplicationInfoImpl.getShadowInstance();
ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance();
- log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild() + ", " +
- DateFormatUtilRt.formatBuildDate(appInfo.getBuildDate()) + ")");
+ String buildDate = new SimpleDateFormat("dd MMM yyyy HH:ss", Locale.US).format(appInfo.getBuildDate().getTime());
+ log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild() + ", " + buildDate + ")");
log.info("OS: " + SystemInfoRt.OS_NAME + " (" + SystemInfoRt.OS_VERSION + ", " + SystemInfo.OS_ARCH + ")");
log.info("JRE: " + System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")");
log.info("JVM: " + System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")");
diff --git a/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java b/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java
index bf0a80d..5af732f 100644
--- a/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java
+++ b/platform/platform-impl/src/com/intellij/internal/focus/FocusTracesAction.java
@@ -52,7 +52,7 @@
@Override
public void eventDispatched(AWTEvent event) {
if (event instanceof FocusEvent && event.getID() == FocusEvent.FOCUS_GAINED) {
- focusManager.getRequests().add(new FocusRequestInfo(((FocusEvent)event).getComponent(), new Throwable(), false));
+ focusManager.recordFocusRequest(((FocusEvent)event).getComponent(), false);
}
}
};
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/OsVersionUsageCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/OsVersionUsageCollector.java
index 9ba27af..53ed410 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/OsVersionUsageCollector.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/OsVersionUsageCollector.java
@@ -32,7 +32,21 @@
@NotNull
@Override
public Set<UsageDescriptor> getUsages(@Nullable Project project) throws CollectUsagesException {
- return Collections.singleton(new UsageDescriptor(SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION, 1));
+ UsageDescriptor descriptor = null;
+
+ if (SystemInfo.isUnix && !SystemInfo.isMac) {
+ String releaseName = SystemInfo.getUnixReleaseName();
+ String releaseVersion = SystemInfo.getUnixReleaseVersion();
+ if (releaseName != null && releaseVersion != null) {
+ descriptor = new UsageDescriptor(SystemInfo.OS_NAME + " " + releaseName + " " + releaseVersion, 1);
+ }
+ }
+
+ if (descriptor == null) {
+ descriptor = new UsageDescriptor(SystemInfo.OS_NAME + " " + SystemInfo.OS_VERSION, 1);
+ }
+
+ return Collections.singleton(descriptor);
}
@NotNull
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsBundle.java b/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsBundle.java
index 483efa8..76cc768 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsBundle.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsBundle.java
@@ -16,6 +16,7 @@
package com.intellij.internal.statistic;
import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
@@ -24,14 +25,14 @@
*/
public class StatisticsBundle extends AbstractBundle {
- public static final String PATH_TO_BUNDLE = "messages.StatisticsBundle";
- private static final StatisticsBundle BUNDLE = new StatisticsBundle();
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return BUNDLE.getMessage(key, params);
+ }
+
+ public static final String PATH_TO_BUNDLE = "messages.StatisticsBundle";
+ private static final StatisticsBundle BUNDLE = new StatisticsBundle();
public StatisticsBundle() {
super(PATH_TO_BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
- return BUNDLE.getMessage(key, params);
- }
}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java
index c3f3fb4..954babd 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java
@@ -20,53 +20,38 @@
import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.net.HttpConfigurable;
-import org.apache.commons.httpclient.Header;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpStatus;
-import org.apache.commons.httpclient.NameValuePair;
-import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.http.Header;
+import org.apache.http.HttpStatus;
+import org.apache.http.client.fluent.Form;
+import org.apache.http.client.fluent.Request;
+import org.apache.http.client.fluent.Response;
import org.jetbrains.annotations.NotNull;
public class StatisticsHttpClientSender implements StatisticsDataSender {
-
+ @Override
public void send(@NotNull String url, @NotNull String content) throws StatServiceException {
- PostMethod post = null;
-
try {
HttpConfigurable.getInstance().prepareURL(url);
- HttpClient httpclient = new HttpClient();
- post = new PostMethod(url);
-
- post.setRequestBody(new NameValuePair[]{
- new NameValuePair("content", content),
- new NameValuePair("uuid", UpdateChecker.getInstallationUID(PropertiesComponent.getInstance())),
- new NameValuePair("ide", ApplicationNamesInfo.getInstance().getProductName()),
- });
-
- httpclient.executeMethod(post);
-
- if (post.getStatusCode() != HttpStatus.SC_OK) {
- throw new StatServiceException("Error during data sending... Code: " + post.getStatusCode());
+ Response response = Request.Post(url).bodyForm(Form.form().
+ add("content", content).
+ add("uuid", UpdateChecker.getInstallationUID(PropertiesComponent.getInstance())).
+ add("ide", ApplicationNamesInfo.getInstance().getProductName()).build()).execute();
+ if (response.returnResponse().getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
+ throw new StatServiceException("Error during data sending... Code: " + response.returnResponse().getStatusLine().getStatusCode());
}
- final Header errors = post.getResponseHeader("errors");
+ final Header errors = response.returnResponse().getFirstHeader("errors");
if (errors != null) {
- final String value = errors.getValue();
-
+ String value = errors.getValue();
throw new StatServiceException("Error during updating statistics " + (!StringUtil.isEmptyOrSpaces(value) ? " : " + value : ""));
}
}
catch (StatServiceException e) {
- throw e;
+ throw e;
}
catch (Exception e) {
throw new StatServiceException("Error during data sending...", e);
}
- finally {
- if (post != null) {
- post.releaseConnection();
- }
- }
}
}
diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsService.java b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsService.java
index 23cb562..c0acb84 100644
--- a/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsService.java
+++ b/platform/platform-impl/src/com/intellij/internal/statistic/ideSettings/IdeSettingsStatisticsService.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.
@@ -30,7 +30,7 @@
public class IdeSettingsStatisticsService extends SettingsConnectionService {
private static final Logger LOG = Logger.getInstance("#com.intellij.internal.statistic.ideSettings.IdeSettingsUsagesCollector");
- private static String FILE_NAME = "ide-settings-statistics.xml";
+ private static final String FILE_NAME = "ide-settings-statistics.xml";
private static final IdeSettingsStatisticsService myInstance = new IdeSettingsStatisticsService();
private IdeSettingsDescriptor[] myDescriptors;
diff --git a/platform/platform-impl/src/com/intellij/notification/EventLog.java b/platform/platform-impl/src/com/intellij/notification/EventLog.java
index 1cf1e80..973acd2 100644
--- a/platform/platform-impl/src/com/intellij/notification/EventLog.java
+++ b/platform/platform-impl/src/com/intellij/notification/EventLog.java
@@ -175,7 +175,7 @@
}
private static String getStatusText(DocumentImpl logDoc, AtomicBoolean showMore, List<RangeMarker> lineSeparators, boolean hasHtml) {
- DocumentImpl statusDoc = new DocumentImpl(logDoc.getText(),true);
+ DocumentImpl statusDoc = new DocumentImpl(logDoc.getImmutableCharSequence(),true);
List<RangeMarker> statusSeparators = new ArrayList<RangeMarker>();
for (RangeMarker separator : lineSeparators) {
if (separator.isValid()) {
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java
index 804b677..ab62eb2 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/IdeNotificationArea.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.
@@ -63,7 +63,7 @@
}, this);
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
EventLog.toggleLog(getProject(), null);
return true;
}
@@ -209,6 +209,8 @@
@Override
public void paintIcon(Component c, Graphics g, int x, int y) {
+ UIUtil.applyRenderingHints(g);
+
Font originalFont = g.getFont();
Color originalColor = g.getColor();
g.setFont(calcFont());
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java
index 770a347..24ecbd5 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationSettings.java
@@ -23,11 +23,11 @@
/**
* @author spleaner
*/
-public class NotificationSettings {
+public final class NotificationSettings {
private final String myGroupId;
- private NotificationDisplayType myDisplayType;
- private boolean myShouldLog;
- private boolean myShouldReadAloud;
+ private final NotificationDisplayType myDisplayType;
+ private final boolean myShouldLog;
+ private final boolean myShouldReadAloud;
public NotificationSettings(String groupId, NotificationDisplayType displayType, boolean shouldLog, boolean shouldReadAloud) {
myGroupId = groupId;
@@ -50,18 +50,21 @@
return myShouldLog;
}
- public void setShouldLog(boolean shouldLog) {
- myShouldLog = shouldLog;
+ public NotificationSettings withShouldLog(boolean shouldLog) {
+ return new NotificationSettings(myGroupId, myDisplayType, shouldLog, myShouldReadAloud);
}
public boolean isShouldReadAloud() {
return myShouldReadAloud;
}
- public void setShouldReadAloud(boolean shouldReadAloud) {
- myShouldReadAloud = shouldReadAloud;
+ public NotificationSettings withShouldReadAloud(boolean shouldReadAloud) {
+ return new NotificationSettings(myGroupId, myDisplayType, myShouldLog, shouldReadAloud);
}
+ public NotificationSettings withDisplayType(NotificationDisplayType displayType) {
+ return new NotificationSettings(myGroupId, displayType, myShouldLog, myShouldReadAloud);
+ }
@Nullable
public static NotificationSettings load(@NotNull final Element element) {
@@ -104,7 +107,27 @@
return result;
}
- public void setDisplayType(final NotificationDisplayType displayType) {
- myDisplayType = displayType;
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof NotificationSettings)) return false;
+
+ NotificationSettings settings = (NotificationSettings)o;
+
+ if (myShouldLog != settings.myShouldLog) return false;
+ if (myShouldReadAloud != settings.myShouldReadAloud) return false;
+ if (myDisplayType != settings.myDisplayType) return false;
+ if (!myGroupId.equals(settings.myGroupId)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myGroupId.hashCode();
+ result = 31 * result + myDisplayType.hashCode();
+ result = 31 * result + (myShouldLog ? 1 : 0);
+ result = 31 * result + (myShouldReadAloud ? 1 : 0);
+ return result;
}
}
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java
index d946f5c..98694bb 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/NotificationsConfigurationImpl.java
@@ -15,14 +15,13 @@
*/
package com.intellij.notification.impl;
-import com.intellij.notification.Notification;
import com.intellij.notification.NotificationDisplayType;
+import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationsConfiguration;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Function;
-import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBus;
import org.jdom.Element;
@@ -62,12 +61,13 @@
}
public synchronized boolean hasToolWindowCapability(@NotNull String groupId) {
- return myToolWindowCapable.containsKey(groupId);
+ return getToolWindowId(groupId) != null || myToolWindowCapable.containsKey(groupId);
}
@Nullable
- public synchronized String getToolWindowId(@NotNull String groupId) {
- return myToolWindowCapable.get(groupId);
+ public String getToolWindowId(@NotNull String groupId) {
+ NotificationGroup group = NotificationGroup.findRegisteredGroup(groupId);
+ return group == null ? null : group.getToolWindowId();
}
public static NotificationSettings[] getAllSettings() {
@@ -91,11 +91,15 @@
private synchronized void _remove(String... toRemove) {
for (final String id : toRemove) {
myIdToSettingsMap.remove(id);
+ myToolWindowCapable.remove(id);
}
}
private synchronized NotificationSettings[] _getAllSettings() {
- Collection<NotificationSettings> settings = myIdToSettingsMap.values();
+ Collection<NotificationSettings> settings = ContainerUtil.newHashSet(myIdToSettingsMap.values());
+ for (NotificationGroup group : NotificationGroup.getAllRegisteredGroups()) {
+ settings.add(getSettings(group.getDisplayId()));
+ }
NotificationSettings[] result = settings.toArray(new NotificationSettings[settings.size()]);
Arrays.sort(result, new Comparator<NotificationSettings>() {
@Override
@@ -114,7 +118,16 @@
@NotNull
public static NotificationSettings getSettings(@NotNull final String groupId) {
final NotificationSettings settings = getNotificationsConfigurationImpl()._getSettings(groupId);
- return settings == null ? new NotificationSettings(groupId, NotificationDisplayType.BALLOON, true, false) : settings;
+ return settings == null ? getDefaultSettings(groupId) : settings;
+ }
+
+ @NotNull
+ private static NotificationSettings getDefaultSettings(String groupId) {
+ NotificationGroup group = NotificationGroup.findRegisteredGroup(groupId);
+ if (group != null) {
+ return new NotificationSettings(groupId, group.getDisplayType(), group.isLogByDefault(), false);
+ }
+ return new NotificationSettings(groupId, NotificationDisplayType.BALLOON, true, false);
}
@Override
@@ -154,19 +167,27 @@
changeSettings(groupDisplayName, displayType, shouldLog, shouldReadAloud);
} else if (displayType == NotificationDisplayType.TOOL_WINDOW && !hasToolWindowCapability(groupDisplayName)) {
// the first time with tool window capability
- ObjectUtils.assertNotNull(_getSettings(groupDisplayName)).setDisplayType(NotificationDisplayType.TOOL_WINDOW);
+ changeSettings(getSettings(groupDisplayName).withDisplayType(NotificationDisplayType.TOOL_WINDOW));
myToolWindowCapable.put(groupDisplayName, null);
}
-
}
@Override
public void changeSettings(String groupDisplayName, NotificationDisplayType displayType, boolean shouldLog, boolean shouldReadAloud) {
- myIdToSettingsMap.put(groupDisplayName, new NotificationSettings(groupDisplayName, displayType, shouldLog, shouldReadAloud));
+ changeSettings(new NotificationSettings(groupDisplayName, displayType, shouldLog, shouldReadAloud));
+ }
+
+ public synchronized void changeSettings(NotificationSettings settings) {
+ String groupDisplayName = settings.getGroupId();
+ if (settings.equals(getDefaultSettings(groupDisplayName))) {
+ myIdToSettingsMap.remove(groupDisplayName);
+ } else {
+ myIdToSettingsMap.put(groupDisplayName, settings);
+ }
}
public synchronized boolean isRegistered(@NotNull final String id) {
- return myIdToSettingsMap.containsKey(id);
+ return myIdToSettingsMap.containsKey(id) || NotificationGroup.findRegisteredGroup(id) != null;
}
@Override
@@ -178,6 +199,12 @@
for (String entry: myToolWindowCapable.keySet()) {
element.addContent(new Element("toolWindow").setAttribute("group", entry));
}
+ for (NotificationGroup group : NotificationGroup.getAllRegisteredGroups()) {
+ String displayId = group.getDisplayId();
+ if (!myToolWindowCapable.containsKey(displayId) && group.getToolWindowId() != null) {
+ element.addContent(new Element("toolWindow").setAttribute("group", displayId));
+ }
+ }
//noinspection NonPrivateFieldAccessedInSynchronizedContext
if (!SHOW_BALLOONS) {
element.setAttribute(SHOW_BALLOONS_ATTRIBUTE, "false");
diff --git a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
index c1e316e..73af2c3 100644
--- a/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
+++ b/platform/platform-impl/src/com/intellij/notification/impl/ui/NotificationsConfigurablePanel.java
@@ -236,20 +236,16 @@
}
}
- private static class SettingsWrapper extends NotificationSettings {
- private final NotificationSettings myOriginal;
+ private static class SettingsWrapper {
private boolean myRemoved = false;
+ private NotificationSettings myVersion;
- private SettingsWrapper(@NotNull final NotificationSettings original) {
- super(original.getGroupId(), original.getDisplayType(), original.isShouldLog(), original.isShouldReadAloud());
- myOriginal = original;
+ private SettingsWrapper(NotificationSettings settings) {
+ myVersion = settings;
}
public boolean hasChanged() {
- return !getDisplayType().equals(myOriginal.getDisplayType())
- || isShouldLog() != myOriginal.isShouldLog()
- || isShouldReadAloud() != myOriginal.isShouldReadAloud()
- || myRemoved;
+ return myRemoved || !getOriginalSettings().equals(myVersion);
}
public void remove() {
@@ -260,24 +256,27 @@
return myRemoved;
}
+ @NotNull
+ private NotificationSettings getOriginalSettings() {
+ return NotificationsConfigurationImpl.getSettings(getGroupId());
+ }
+
public void apply() {
if (myRemoved) {
- NotificationsConfigurationImpl.remove(myOriginal.getGroupId());
+ NotificationsConfigurationImpl.remove(getGroupId());
}
else {
- if (hasChanged()) {
- myOriginal.setDisplayType(getDisplayType());
- myOriginal.setShouldLog(isShouldLog());
- myOriginal.setShouldReadAloud(isShouldReadAloud());
- }
+ NotificationsConfigurationImpl.getNotificationsConfigurationImpl().changeSettings(myVersion);
}
}
public void reset() {
- if (hasChanged()) {
- setDisplayType(myOriginal.getDisplayType());
- myRemoved = false;
- }
+ myVersion = getOriginalSettings();
+ myRemoved = false;
+ }
+
+ String getGroupId() {
+ return myVersion.getGroupId();
}
}
@@ -285,9 +284,8 @@
private final List<SettingsWrapper> mySettings;
public NotificationsTableModel() {
- final NotificationSettings[] settings = NotificationsConfigurationImpl.getAllSettings();
final List<SettingsWrapper> list = new ArrayList<SettingsWrapper>();
- for (NotificationSettings setting : settings) {
+ for (NotificationSettings setting : NotificationsConfigurationImpl.getAllSettings()) {
list.add(new SettingsWrapper(setting));
}
@@ -300,17 +298,17 @@
@Override
public void setValueAt(final Object value, final int rowIndex, final int columnIndex) {
- final NotificationSettings settings = getSettings(rowIndex);
+ final SettingsWrapper wrapper = getSettings(rowIndex);
switch (columnIndex) {
case NotificationsTable.DISPLAY_TYPE_COLUMN:
- settings.setDisplayType((NotificationDisplayType)value);
+ wrapper.myVersion = wrapper.myVersion.withDisplayType((NotificationDisplayType)value);
break;
case NotificationsTable.LOG_COLUMN:
- settings.setShouldLog((Boolean)value);
+ wrapper.myVersion = wrapper.myVersion.withShouldLog((Boolean)value);
break;
case NotificationsTable.READ_ALOUD_COLUMN:
- settings.setShouldReadAloud((Boolean)value);
+ wrapper.myVersion = wrapper.myVersion.withShouldReadAloud((Boolean)value);
break;
}
}
@@ -319,7 +317,7 @@
return getSettings().size();
}
- public NotificationSettings getSettings(int row) {
+ public SettingsWrapper getSettings(int row) {
return getSettings().get(row);
}
@@ -366,12 +364,12 @@
case NotificationsTable.ID_COLUMN:
return getSettings().get(rowIndex).getGroupId();
case NotificationsTable.LOG_COLUMN:
- return getSettings().get(rowIndex).isShouldLog();
+ return getSettings().get(rowIndex).myVersion.isShouldLog();
case NotificationsTable.READ_ALOUD_COLUMN:
- return getSettings().get(rowIndex).isShouldReadAloud();
+ return getSettings().get(rowIndex).myVersion.isShouldReadAloud();
case NotificationsTable.DISPLAY_TYPE_COLUMN:
default:
- return getSettings().get(rowIndex).getDisplayType();
+ return getSettings().get(rowIndex).myVersion.getDisplayType();
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java
new file mode 100644
index 0000000..b5027fd
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ComputableActionGroup.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.actionSystem;
+
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.util.ModificationTracker;
+import com.intellij.psi.util.CachedValue;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.util.CachedValueImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class ComputableActionGroup extends ActionGroup implements DumbAware {
+ private CachedValue<AnAction[]> myChildren;
+
+ protected ComputableActionGroup() {
+ }
+
+ protected ComputableActionGroup(boolean popup) {
+ super(null, popup);
+ }
+
+ @Override
+ public boolean hideIfNoVisibleChildren() {
+ return true;
+ }
+
+ @Override
+ @NotNull
+ public final AnAction[] getChildren(@Nullable AnActionEvent e) {
+ if (e == null) {
+ return EMPTY_ARRAY;
+ }
+
+ if (myChildren == null) {
+ myChildren = new CachedValueImpl<AnAction[]>(createChildrenProvider(e.getActionManager()));
+ }
+ return myChildren.getValue();
+ }
+
+ @NotNull
+ protected abstract CachedValueProvider<AnAction[]> createChildrenProvider(@NotNull ActionManager actionManager);
+
+ public abstract static class Simple extends ComputableActionGroup {
+ @NotNull
+ @Override
+ protected final CachedValueProvider<AnAction[]> createChildrenProvider(@NotNull final ActionManager actionManager) {
+ return new CachedValueProvider<AnAction[]>() {
+ @Nullable
+ @Override
+ public Result<AnAction[]> compute() {
+ return Result.create(computeChildren(actionManager), ModificationTracker.NEVER_CHANGED);
+ }
+ };
+ }
+
+ @NotNull
+ protected abstract AnAction[] computeChildren(@NotNull ActionManager manager);
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
index 176db43..a17370e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/ex/QuickListsManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -65,17 +65,17 @@
mySchemesManager = schemesManagerFactory.createSchemesManager(
"$ROOT_CONFIG$/quicklists",
new BaseSchemeProcessor<QuickList>(){
- public QuickList readScheme(final Document schemeContent) throws InvalidDataException, IOException, JDOMException {
+ public QuickList readScheme(@NotNull final Document schemeContent) throws InvalidDataException, IOException, JDOMException {
return loadListFromDocument(schemeContent);
}
- public Document writeScheme(final QuickList scheme) throws WriteExternalException {
+ public Document writeScheme(@NotNull final QuickList scheme) throws WriteExternalException {
Element element = new Element(LIST_TAG);
scheme.writeExternal(element);
return new Document(element);
}
- public boolean shouldBeSaved(final QuickList scheme) {
+ public boolean shouldBeSaved(@NotNull final QuickList scheme) {
return true;
}
},
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
index f67aae3..ff2a354 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ActionManagerImpl.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.ide.DataManager;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.idea.IdeaLogger;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
@@ -47,7 +48,9 @@
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.IdeFrame;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
@@ -78,6 +81,7 @@
private final Map<PluginId, THashSet<String>> myPlugin2Id = new THashMap<PluginId, THashSet<String>>();
private final TObjectIntHashMap<String> myId2Index = new TObjectIntHashMap<String>();
private final Map<Object,String> myAction2Id = new THashMap<Object, String>();
+ private final MultiMap<String,String> myId2GroupId = new MultiMap<String, String>();
private final List<String> myNotRegisteredInternalActionIds = new ArrayList<String>();
private MyTimer myTimer;
@@ -88,6 +92,7 @@
private final DataManager myDataManager;
private String myPrevPerformedActionId;
private long myLastTimeEditorWasTypedIn = 0;
+
@NonNls public static final String ACTION_ELEMENT_NAME = "action";
@NonNls public static final String GROUP_ELEMENT_NAME = "group";
@NonNls public static final String ACTIONS_ELEMENT_NAME = "actions";
@@ -123,6 +128,8 @@
@NonNls public static final String VALUE_ATTR_NAME = "value";
@NonNls public static final String ACTIONS_BUNDLE = "messages.ActionsBundle";
@NonNls public static final String USE_SHORTCUT_OF_ATTR_NAME = "use-shortcut-of";
+ @NonNls public static final String OVERRIDES_ATTR_NAME = "overrides";
+ @NonNls public static final String KEEP_CONTENT_ATTR_NAME = "keep-content";
private final List<ActionPopupMenuImpl> myPopups = new ArrayList<ActionPopupMenuImpl>();
@@ -197,20 +204,20 @@
}
@Override
- public ActionToolbar createActionToolbar(final String place, final ActionGroup group, final boolean horizontal) {
+ public ActionToolbar createActionToolbar(final String place, @NotNull final ActionGroup group, final boolean horizontal) {
return createActionToolbar(place, group, horizontal, false);
}
@Override
- public ActionToolbar createActionToolbar(final String place, final ActionGroup group, final boolean horizontal, final boolean decorateButtons) {
+ public ActionToolbar createActionToolbar(final String place, @NotNull final ActionGroup group, final boolean horizontal, final boolean decorateButtons) {
return new ActionToolbarImpl(place, group, horizontal, decorateButtons, myDataManager, this, (KeymapManagerEx)myKeymapManager);
}
private void registerPluginActions() {
- final IdeaPluginDescriptor[] plugins = PluginManager.getPlugins();
+ final IdeaPluginDescriptor[] plugins = PluginManagerCore.getPlugins();
for (IdeaPluginDescriptor plugin : plugins) {
- if (PluginManager.shouldSkipPlugin(plugin)) continue;
+ if (PluginManagerCore.shouldSkipPlugin(plugin)) continue;
final List<Element> elementList = plugin.getActionsDescriptionElements();
if (elementList != null) {
for (Element e : elementList) {
@@ -332,7 +339,7 @@
}
@Override
- public JComponent createButtonToolbar(final String actionPlace, final ActionGroup messageActionGroup) {
+ public JComponent createButtonToolbar(final String actionPlace, @NotNull final ActionGroup messageActionGroup) {
return new ButtonToolbarImpl(actionPlace, messageActionGroup, myDataManager, this);
}
@@ -412,11 +419,29 @@
((KeymapManagerEx)myKeymapManager).bindShortcuts(element.getAttributeValue(USE_SHORTCUT_OF_ATTR_NAME), id);
}
- // register action
- registerAction(id, stub, pluginId);
+ registerOrReplaceActionInner(element, id, stub, pluginId);
return stub;
}
+ private void registerOrReplaceActionInner(@NotNull Element element, @NotNull String id, @NotNull AnAction action, @Nullable PluginId pluginId) {
+ synchronized (myLock) {
+ if (Boolean.valueOf(element.getAttributeValue(OVERRIDES_ATTR_NAME))) {
+ if (getActionOrStub(id) == null) {
+ throw new RuntimeException(element.getName() + " '" + id + "' doesn't override anything");
+ }
+ AnAction prev = replaceAction(id, action, pluginId);
+ if (action instanceof DefaultActionGroup && prev instanceof DefaultActionGroup) {
+ if (Boolean.valueOf(element.getAttributeValue(KEEP_CONTENT_ATTR_NAME))) {
+ ((DefaultActionGroup)action).copyFromGroup((DefaultActionGroup)prev);
+ }
+ }
+ }
+ else {
+ registerAction(id, action, pluginId);
+ }
+ }
+ }
+
private static void processAbbreviationNode(Element e, String id) {
final String abbr = e.getAttributeValue(VALUE_ATTR_NAME);
if (!StringUtil.isEmpty(abbr)) {
@@ -427,7 +452,8 @@
@Nullable
private static ResourceBundle getActionsResourceBundle(ClassLoader loader, IdeaPluginDescriptor plugin) {
- @NonNls final String resBundleName = plugin != null && !plugin.getPluginId().getIdString().equals("com.intellij") ? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE;
+ @NonNls final String resBundleName = plugin != null && !"com.intellij".equals(plugin.getPluginId().getIdString())
+ ? plugin.getResourceBundleBaseName() : ACTIONS_BUNDLE;
ResourceBundle bundle = null;
if (resBundleName != null) {
bundle = AbstractBundle.getResourceBundle(resBundleName, loader);
@@ -560,7 +586,7 @@
}
if (id != null) {
- registerAction(id, group);
+ registerOrReplaceActionInner(element, id, group, pluginId);
}
Presentation presentation = group.getTemplatePresentation();
@@ -593,7 +619,7 @@
AnAction action = processActionElement(child, loader, pluginId);
if (action != null) {
assertActionIsGroupOrStub(action);
- ((DefaultActionGroup)group).addAction(action, Constraints.LAST, this).setAsSecondary(isSecondary(child));
+ addToGroupInner(group, action, Constraints.LAST, isSecondary(child));
}
}
else if (SEPARATOR_ELEMENT_NAME.equals(name)) {
@@ -602,7 +628,7 @@
else if (GROUP_ELEMENT_NAME.equals(name)) {
AnAction action = processGroupElement(child, loader, pluginId);
if (action != null) {
- ((DefaultActionGroup)group).add(action, this);
+ addToGroupInner(group, action, Constraints.LAST, false);
}
}
else if (ADD_TO_GROUP_ELEMENT_NAME.equals(name)) {
@@ -611,7 +637,7 @@
else if (REFERENCE_ELEMENT_NAME.equals(name)) {
AnAction action = processReferenceElement(child, pluginId);
if (action != null) {
- ((DefaultActionGroup)group).addAction(action, Constraints.LAST, this).setAsSecondary(isSecondary(child));
+ addToGroupInner(group, action, Constraints.LAST, isSecondary(child));
}
}
else {
@@ -679,8 +705,7 @@
}
// anchor attribute
- final Anchor anchor = parseAnchor(element.getAttributeValue(ANCHOR_ELEMENT_NAME),
- actionName, pluginId);
+ final Anchor anchor = parseAnchor(element.getAttributeValue(ANCHOR_ELEMENT_NAME), actionName, pluginId);
if (anchor == null) {
return;
}
@@ -689,8 +714,12 @@
if (!checkRelativeToAction(relativeToActionId, anchor, actionName, pluginId)) {
return;
}
- final DefaultActionGroup group = (DefaultActionGroup)parentGroup;
- group.addAction(action, new Constraints(anchor, relativeToActionId), this).setAsSecondary(secondary);
+ addToGroupInner(parentGroup, action, new Constraints(anchor, relativeToActionId), secondary);
+ }
+
+ private void addToGroupInner(AnAction group, AnAction action, Constraints constraints, boolean secondary) {
+ ((DefaultActionGroup)group).addAction(action, constraints, this).setAsSecondary(secondary);
+ myId2GroupId.putValue(myAction2Id.get(action), myAction2Id.get(group));
}
public static boolean checkRelativeToAction(final String relativeToActionId,
@@ -916,7 +945,7 @@
public void registerAction(@NotNull String actionId, @NotNull AnAction action, @Nullable PluginId pluginId) {
synchronized (myLock) {
if (myId2Action.containsKey(actionId)) {
- reportActionError(pluginId, "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action.toString() +
+ reportActionError(pluginId, "action with the ID \"" + actionId + "\" was already registered. Action being registered is " + action +
"; Registered action is " +
myId2Action.get(actionId) + getPluginInfo(pluginId));
return;
@@ -1007,6 +1036,7 @@
};
}
+ @NotNull
@Override
public String[] getPluginActions(PluginId pluginName) {
if (myPlugin2Id.containsKey(pluginName)){
@@ -1047,6 +1077,33 @@
return myTransparentOnlyUpdate;
}
+ //@Override
+ //public AnAction replaceAction(String actionId, @NotNull AnAction newAction) {
+ // synchronized (myLock) {
+ // return replaceAction(actionId, newAction, null);
+ // }
+ //}
+
+ private AnAction replaceAction(@NotNull String actionId, @NotNull AnAction newAction, @Nullable PluginId pluginId) {
+ AnAction oldAction = getActionOrStub(actionId);
+ if (oldAction != null) {
+ boolean isGroup = oldAction instanceof ActionGroup;
+ if (isGroup != newAction instanceof ActionGroup) {
+ throw new IllegalStateException("cannot replace a group with an action and vice versa: " + actionId);
+ }
+ unregisterAction(actionId);
+ if (isGroup) {
+ myId2GroupId.values().remove(actionId);
+ }
+ }
+ registerAction(actionId, newAction, pluginId);
+ for (String groupId : myId2GroupId.get(actionId)) {
+ DefaultActionGroup group = ObjectUtils.assertNotNull((DefaultActionGroup)getActionOrStub(groupId));
+ group.replaceAction(oldAction, newAction);
+ }
+ return oldAction;
+ }
+
private void flushActionPerformed() {
final Set<AnAction> actions = myQueuedNotifications.keySet();
for (final AnAction eachAction : actions) {
@@ -1178,6 +1235,7 @@
preloadActionGroup(IdeActions.GROUP_EDITOR_TAB_POPUP);
preloadActionGroup(IdeActions.GROUP_PROJECT_VIEW_POPUP);
preloadActionGroup(IdeActions.GROUP_MAIN_MENU);
+ preloadActionGroup(IdeActions.GROUP_NEW);
// TODO anything else?
LOG.debug("Actions preloading completed");
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ButtonToolbarImpl.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ButtonToolbarImpl.java
index 6b0a55f..e3496b8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ButtonToolbarImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/ButtonToolbarImpl.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.actionSystem.ex.ActionManagerEx;
import com.intellij.openapi.actionSystem.ex.ActionUtil;
import com.intellij.openapi.application.ModalityState;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -40,7 +41,7 @@
private final ArrayList<ActionJButton> myActions = new ArrayList<ActionJButton>();
public ButtonToolbarImpl(final String place,
- final ActionGroup actionGroup,
+ @NotNull ActionGroup actionGroup,
DataManager dataManager,
ActionManagerEx actionManager) {
super(new GridBagLayout());
@@ -57,7 +58,7 @@
}
- private void initButtons(final ActionGroup actionGroup) {
+ private void initButtons(@NotNull ActionGroup actionGroup) {
final AnAction[] actions = actionGroup.getChildren(null);
if (actions.length > 0) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java
index 82afa01..01aa0ff 100644
--- a/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java
+++ b/platform/platform-impl/src/com/intellij/openapi/actionSystem/impl/config/ActionBean.java
@@ -50,9 +50,12 @@
@Attribute(ActionManagerImpl.INTERNAL_ATTR_NAME)
public boolean internal;
- @Attribute("use-shortcut-of")
+ @Attribute(ActionManagerImpl.USE_SHORTCUT_OF_ATTR_NAME)
public boolean useShortcutOf;
@Attribute(ActionManagerImpl.KEYMAP_ATTR_NAME)
public String keymap;
+
+ @Attribute(ActionManagerImpl.OVERRIDES_ATTR_NAME)
+ public boolean overrides;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
index bb7f1e2..36bd876 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ConfigImportHelper.java
@@ -114,19 +114,15 @@
if (parent == null || !parent.exists()) return null;
File maxFile = null;
long lastModified = 0;
- final String selector;
- if (customPathSelector != null) {
- selector = customPathSelector;
- }
- else {
- selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName();
- }
+ final String selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName();
- final String prefix = (SystemInfo.isMac ? "" : ".") + selector.replaceAll("\\d", "");
+ final String prefix = getPrefixFromSelector(selector);
+ final String customPrefix = customPathSelector != null ? getPrefixFromSelector(customPathSelector) : null;
for (File file : parent.listFiles(new FilenameFilter() {
@Override
public boolean accept(File file, String name) {
- return StringUtil.startsWithIgnoreCase(name, prefix);
+ return StringUtil.startsWithIgnoreCase(name, prefix) ||
+ customPrefix != null && StringUtil.startsWithIgnoreCase(name, customPrefix);
}
})) {
final File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
@@ -140,6 +136,10 @@
return maxFile != null ? new File(maxFile, CONFIG_RELATED_PATH) : null;
}
+ private static String getPrefixFromSelector(String selector) {
+ return (SystemInfo.isMac ? "" : ".") + selector.replaceAll("\\d", "");
+ }
+
public static void doImport(final String newConfigPath, final File oldConfigDir) {
try {
xcopy(oldConfigDir, new File(newConfigPath));
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java b/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java
index f08eb5f..f241f39 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationInfoEx.java
@@ -13,26 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * Created by IntelliJ IDEA.
- * User: mike
- * Date: Sep 16, 2002
- * Time: 5:17:44 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
package com.intellij.openapi.application.ex;
import com.intellij.openapi.application.ApplicationInfo;
-import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.util.Calendar;
import java.util.List;
+/**
+ * @author mike
+ * @since Sep 16, 2002
+ */
public abstract class ApplicationInfoEx extends ApplicationInfo {
-
public static ApplicationInfoEx getInstanceEx() {
return (ApplicationInfoEx) getInstance();
}
@@ -49,19 +42,10 @@
public abstract String getSmallIconUrl();
- @Nullable
- public String getBigIconUrl() {
- return null;
- }
-
- public abstract String getOpaqueIconUrl();
+ public abstract String getBigIconUrl();
public abstract String getToolWindowIconUrl();
- public abstract String getWelcomeScreenCaptionUrl();
-
- public abstract String getWelcomeScreenDeveloperSloganUrl();
-
public abstract String getWelcomeScreenLogoUrl();
public abstract String getEditorBackgroundImageUrl();
@@ -72,10 +56,8 @@
public abstract boolean showLicenseeInfo();
-
public abstract boolean isEAP();
-
public abstract UpdateUrls getUpdateUrls();
public abstract String getDocumentationUrl();
@@ -117,4 +99,15 @@
public abstract boolean isEssentialPlugin(String pluginId);
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
+ public abstract String getOpaqueIconUrl();
+
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
+ public abstract String getWelcomeScreenCaptionUrl();
+
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
+ public abstract String getWelcomeScreenDeveloperSloganUrl();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationManagerEx.java
index a10f828..e61df0d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationManagerEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/ex/ApplicationManagerEx.java
@@ -26,10 +26,16 @@
* @author max
*/
public class ApplicationManagerEx extends ApplicationManager {
+
+ public static final String IDEA_APPLICATION = "idea";
+
public static ApplicationEx getApplicationEx() {
return (ApplicationEx) ourApplication;
}
+ /**
+ * @param appName used to load default configs; if you are not sure, use {@link #IDEA_APPLICATION}.
+ */
public static void createApplication(boolean internal,
boolean isUnitTestMode,
boolean isHeadlessMode,
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
index 7e5eab7..0e2e240 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationImpl.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,7 +37,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.progress.ProcessCanceledException;
@@ -616,6 +615,10 @@
}
final ProgressWindow progress = new ProgressWindow(canBeCanceled, false, project, parentComponent, cancelText);
+ // in case of abrupt application exit when 'ProgressManager.getInstance().runProcess(process, progress)' below
+ // does not have a chance to run, and as a result the progress won't be disposed
+ Disposer.register(this, progress);
+
progress.setTitle(progressTitle);
try {
@@ -1013,7 +1016,7 @@
for (int i = myWriteActionsStack.size() - 1; i >= 0; i--) {
Class action = myWriteActionsStack.get(i);
- if (actionClass == action || action != null && actionClass != null && ReflectionCache.isAssignable(actionClass, action)) return true;
+ if (actionClass == action || action != null && actionClass != null && ReflectionUtil.isAssignable(actionClass, action)) return true;
}
return false;
}
@@ -1157,12 +1160,6 @@
return true;
}
- @Nullable
- @Override
- public PluginId getPluginByClassName(@NotNull String className) {
- return PluginManagerCore.getPluginByClassName(className);
- }
-
public boolean tryToApplyActivationState(boolean active, Window window) {
final Component frame = UIUtil.findUltimateParent(window);
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java
index 14346fe..4f30ec1 100755
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ApplicationInfoImpl.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.
@@ -191,10 +191,10 @@
private static String getProductPrefix() {
String prefix = null;
- if (PlatformUtils.isCommunity()) {
+ if (PlatformUtils.isIdeaCommunity()) {
prefix = "IC";
}
- else if (PlatformUtils.isIdea()) {
+ else if (PlatformUtils.isIdeaUltimate()) {
prefix = "IU";
}
return prefix;
diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java
index 58288a2..adb7647 100644
--- a/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java
+++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.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.
@@ -57,10 +57,10 @@
}
private static class RunnableInfo {
- final Runnable runnable;
- final ModalityState modalityState;
- final Condition<Object> expired;
- final ActionCallback callback;
+ @NotNull private final Runnable runnable;
+ @NotNull private final ModalityState modalityState;
+ @NotNull private final Condition<Object> expired;
+ @NotNull private final ActionCallback callback;
public RunnableInfo(@NotNull Runnable runnable,
@NotNull ModalityState modalityState,
@@ -74,7 +74,7 @@
@NonNls
public String toString() {
- return "[runnable: " + runnable + "; state=" + modalityState + "] ";
+ return "[runnable: " + runnable + "; state=" + modalityState + (expired.value(null) ? "; expired" : "")+"] ";
}
}
@@ -85,26 +85,15 @@
private static final Stack<AWTEvent> ourEventStack = new Stack<AWTEvent>(); // guarded by RUN_LOCK
- static boolean IS_TEST_MODE = false;
-
private static final EventDispatcher<ModalityStateListener> ourModalityStateMulticaster =
EventDispatcher.create(ModalityStateListener.class);
-
- private static final ArrayList<RunnableInfo> ourForcedFlushQueue = new ArrayList<RunnableInfo>();
-
- public static void addModalityStateListener(@NotNull ModalityStateListener listener) {
- ourModalityStateMulticaster.addListener(listener);
- }
+ private static final List<RunnableInfo> ourForcedFlushQueue = new ArrayList<RunnableInfo>();
public static void addModalityStateListener(@NotNull ModalityStateListener listener, @NotNull Disposable parentDisposable) {
ourModalityStateMulticaster.addListener(listener, parentDisposable);
}
- public static void removeModalityStateListener(@NotNull ModalityStateListener listener) {
- ourModalityStateMulticaster.removeListener(listener);
- }
-
@NotNull
static ModalityStateEx modalityStateForWindow(@NotNull Window window) {
int index = ourModalEntities.indexOf(window);
@@ -115,9 +104,7 @@
if (window instanceof Dialog && ((Dialog)window).isModal()) {
return ownerState.appendEntity(window);
}
- else {
- return ownerState;
- }
+ return ownerState;
}
ArrayList<Object> result = new ArrayList<Object>();
@@ -134,27 +121,32 @@
return new ModalityStateEx(result.toArray());
}
+ @NotNull
public static ActionCallback invokeLater(@NotNull Runnable runnable) {
return invokeLater(runnable, Conditions.FALSE);
}
+ @NotNull
public static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull Condition expired) {
ModalityState modalityState = ModalityState.defaultModalityState();
return invokeLater(runnable, modalityState, expired);
}
+ @NotNull
public static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState modalityState) {
return invokeLater(runnable, modalityState, Conditions.FALSE);
}
+ @NotNull
public static ActionCallback invokeLater(@NotNull Runnable runnable,
@NotNull ModalityState modalityState,
@NotNull Condition<Object> expired) {
ourFrequentEventDetector.eventHappened();
final ActionCallback callback = new ActionCallback();
+ RunnableInfo runnableInfo = new RunnableInfo(runnable, modalityState, expired, callback);
synchronized (LOCK) {
- ourQueue.add(new RunnableInfo(runnable, modalityState, expired, callback));
+ ourQueue.add(runnableInfo);
}
requestFlush();
return callback;
@@ -179,7 +171,7 @@
@NonNls
public String toString() {
- return "InvokeAndWait[" + runnable.toString() + "]";
+ return "InvokeAndWait[" + runnable + "]";
}
};
invokeLater(runnable1, modalityState);
@@ -187,33 +179,25 @@
}
public static void enterModal(@NotNull Object modalEntity) {
- if (!IS_TEST_MODE) {
- LOG.assertTrue(isDispatchThread(), "enterModal() should be invoked in event-dispatch thread");
- }
+ LOG.assertTrue(isDispatchThread(), "enterModal() should be invoked in event-dispatch thread");
if (LOG.isDebugEnabled()) {
LOG.debug("enterModal:" + modalEntity);
}
- if (!IS_TEST_MODE) {
- ourModalityStateMulticaster.getMulticaster().beforeModalityStateChanged(true);
- }
+ ourModalityStateMulticaster.getMulticaster().beforeModalityStateChanged(true);
ourModalEntities.add(modalEntity);
}
public static void leaveModal(@NotNull Object modalEntity) {
- if (!IS_TEST_MODE) {
- LOG.assertTrue(isDispatchThread(), "leaveModal() should be invoked in event-dispatch thread");
- }
+ LOG.assertTrue(isDispatchThread(), "leaveModal() should be invoked in event-dispatch thread");
if (LOG.isDebugEnabled()) {
LOG.debug("leaveModal:" + modalEntity);
}
- if (!IS_TEST_MODE) {
- ourModalityStateMulticaster.getMulticaster().beforeModalityStateChanged(false);
- }
+ ourModalityStateMulticaster.getMulticaster().beforeModalityStateChanged(false);
boolean removed = ourModalEntities.remove(modalEntity);
LOG.assertTrue(removed, modalEntity);
@@ -237,15 +221,8 @@
}
}
+ @TestOnly
static void leaveAllModals() {
- LOG.assertTrue(IS_TEST_MODE);
-
- /*
- if (!IS_TEST_MODE) {
- ourModalityStateMulticaster.getMulticaster().beforeModalityStateChanged();
- }
- */
-
ourModalEntities.clear();
ourQueueSkipCount = 0;
requestFlush();
@@ -253,9 +230,7 @@
@NotNull
public static Object[] getCurrentModalEntities() {
- if (!IS_TEST_MODE) {
- ApplicationManager.getApplication().assertIsDispatchThread();
- }
+ ApplicationManager.getApplication().assertIsDispatchThread();
//TODO!
//LOG.assertTrue(IdeEventQueue.getInstance().isInInputEvent() || isInMyRunnable());
@@ -263,9 +238,7 @@
}
public static boolean isInModalContext() {
- if (!IS_TEST_MODE) {
- LOG.assertTrue(isDispatchThread());
- }
+ LOG.assertTrue(isDispatchThread());
return !ourModalEntities.isEmpty();
}
@@ -347,7 +320,7 @@
lastInfo.callback.setDone();
}
catch (ProcessCanceledException ex) {
- // ignore
+ // ignore
}
catch (Throwable t) {
if (t instanceof StackOverflowError) {
@@ -369,20 +342,23 @@
@NonNls
public String toString() {
- return "LaterInvocator[lastRunnable=" + myLastInfo + "]";
+ return "LaterInvocator.FlushQueue" + (myLastInfo == null ? "" : " lastInfo="+myLastInfo);
}
}
@TestOnly
- public static List<Object> dumpQueue() {
+ static String dumpQueue() {
synchronized (LOCK) {
- if (!ourQueue.isEmpty()) {
- ArrayList<Object> r = new ArrayList<Object>();
- r.addAll(ourQueue);
- Collections.reverse(r);
- return r;
+ @NonNls String result = "";
+ if (!ourForcedFlushQueue.isEmpty()) {
+ result = "(Forced queue: " + ourForcedFlushQueue + ") ";
}
+ List<RunnableInfo> r = new ArrayList<RunnableInfo>(ourQueue);
+ result += r + (ourQueueSkipCount == 0 ? "" : " (ourQueueSkipCount="+ourQueueSkipCount+")")
+ + (ourModalEntities.isEmpty() ? " (non-modal)" : " (modal entities: "+ourModalEntities+")"
+ + (FLUSHER_SCHEDULED.get() ? " (Flusher scheduled)" : "")
+ );
+ return result;
}
- return null;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentUndoProvider.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentUndoProvider.java
index 710e037..5895026 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentUndoProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/DocumentUndoProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -45,6 +45,7 @@
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(documentListener, this);
}
+ @Override
public void dispose() {
}
@@ -61,6 +62,7 @@
}
private class MyEditorDocumentListener extends DocumentAdapter {
+ @Override
public void documentChanged(final DocumentEvent e) {
Document document = e.getDocument();
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/NonUndoableAction.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/NonUndoableAction.java
index 0d829ef..ec685c1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/NonUndoableAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/NonUndoableAction.java
@@ -28,6 +28,9 @@
protected NonUndoableAction(DocumentReference ref, boolean isGlobal) {
myGlobal = isGlobal;
myRefs = new DocumentReference[]{ref};
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("global=" + isGlobal + "; doc=" + ref, new Throwable());
+ }
}
public final void undo() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedo.java b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedo.java
index 6c45b12..9e4e26f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedo.java
+++ b/platform/platform-impl/src/com/intellij/openapi/command/impl/UndoRedo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,7 +23,6 @@
import com.intellij.openapi.fileEditor.FileEditorState;
import com.intellij.openapi.fileEditor.FileEditorStateLevel;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.ReadonlyStatusHandler;
@@ -189,7 +188,7 @@
}
return Messages.showOkCancelDialog(myManager.getProject(), actionText + "?", getActionName(),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE;
+ Messages.getQuestionIcon()) == Messages.OK;
}
private boolean restore(EditorAndState pair) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
index 036a786..575717f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.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,6 @@
import com.intellij.openapi.util.*;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.io.fs.IFile;
import gnu.trove.THashMap;
@@ -281,7 +280,7 @@
nextSuperClass:
while (true) {
- final Class[] interfaces = ReflectionCache.getInterfaces(componentClass);
+ final Class[] interfaces = componentClass.getInterfaces();
for (Class anInterface : interfaces) {
if (anInterface.equals(persistentStateComponentClass)) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java
index 0c20859..51cc717 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/CompoundSaveSession.java
@@ -17,33 +17,30 @@
import com.intellij.openapi.components.StateStorage;
import com.intellij.openapi.components.StateStorageException;
+import com.intellij.util.SmartList;
import com.intellij.util.io.fs.IFile;
+import gnu.trove.THashMap;
-import java.util.*;
+import java.util.List;
+import java.util.Map;
/**
* @author mike
*/
public class CompoundSaveSession {
- private final Map<StateStorage, StateStorage.SaveSession> mySaveSessions = new HashMap<StateStorage, StateStorage.SaveSession>();
+ private final Map<StateStorage, StateStorage.SaveSession> mySaveSessions = new THashMap<StateStorage, StateStorage.SaveSession>();
public CompoundSaveSession(final CompoundExternalizationSession compoundExternalizationSession) {
- final Collection<StateStorage> stateStorages = compoundExternalizationSession.getStateStorages();
-
- for (StateStorage stateStorage : stateStorages) {
+ for (StateStorage stateStorage : compoundExternalizationSession.getStateStorages()) {
mySaveSessions.put(stateStorage, stateStorage.startSave(compoundExternalizationSession.getExternalizationSession(stateStorage)));
}
}
public List<IFile> getAllStorageFilesToSave() throws StateStorageException {
- List<IFile> result = new ArrayList<IFile>();
-
- for (StateStorage stateStorage : mySaveSessions.keySet()) {
- final StateStorage.SaveSession saveSession = mySaveSessions.get(stateStorage);
-
+ List<IFile> result = new SmartList<IFile>();
+ for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
result.addAll(saveSession.getStorageFilesToSave());
}
-
return result;
}
@@ -56,11 +53,11 @@
public void finishSave() {
RuntimeException re = null;
for (StateStorage stateStorage : mySaveSessions.keySet()) {
- final StateStorage.SaveSession saveSession = mySaveSessions.get(stateStorage);
try {
- stateStorage.finishSave(saveSession);
- } catch(RuntimeException t) {
- re = t;
+ stateStorage.finishSave(mySaveSessions.get(stateStorage));
+ }
+ catch (RuntimeException e) {
+ re = e;
}
}
@@ -74,11 +71,10 @@
}
public List<IFile> getAllStorageFiles() {
- List<IFile> result = new ArrayList<IFile>();
+ List<IFile> result = new SmartList<IFile>();
for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
result.addAll(saveSession.getAllStorageFiles());
}
-
return result;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java
index 75b0999..8334e81 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/FileBasedStorage.java
@@ -23,6 +23,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.StateStorageException;
+import com.intellij.openapi.components.StoragePathMacros;
import com.intellij.openapi.components.TrackingPathMacroSubstitutor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
@@ -271,7 +272,7 @@
@Nullable
private Document processReadException(@Nullable final Exception e) {
boolean contentTruncated = e == null;
- myBlockSavingTheContent = isProjectOrModuleFile() && !contentTruncated;
+ myBlockSavingTheContent = isProjectOrModuleOrWorkspaceFile() && !contentTruncated;
if (!ApplicationManager.getApplication().isUnitTestMode() && !ApplicationManager.getApplication().isHeadlessEnvironment()) {
if (e != null) {
LOG.info(e);
@@ -285,12 +286,12 @@
return null;
}
- private boolean isProjectOrModuleFile() {
- return StorageUtil.isProjectOrModuleFile(myFileSpec);
+ private boolean isProjectOrModuleOrWorkspaceFile() {
+ return StorageUtil.isProjectOrModuleFile(myFileSpec) || myFileSpec.equals(StoragePathMacros.WORKSPACE_FILE);
}
private String getInvalidContentMessage(boolean contentTruncated) {
- return isProjectOrModuleFile() && !contentTruncated ? "Please correct the file content" : "File content will be recreated";
+ return isProjectOrModuleOrWorkspaceFile() && !contentTruncated ? "Please correct the file content" : "File content will be recreated";
}
private static Document loadDocumentImpl(final VirtualFile file) throws IOException, JDOMException {
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java
index 33f1751..6288c62 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ProjectStoreImpl.java
@@ -86,7 +86,7 @@
String message = ProjectBundle.message("project.convert.old.prompt", projectFile.getName(),
appNamesInfo.getProductName(),
name + OLD_PROJECT_SUFFIX + projectFile.getExtension());
- if (Messages.showYesNoDialog(message, CommonBundle.getWarningTitle(), Messages.getWarningIcon()) != 0) return false;
+ if (Messages.showYesNoDialog(message, CommonBundle.getWarningTitle(), Messages.getWarningIcon()) != Messages.YES) return false;
final ArrayList<String> conversionProblems = getConversionProblemsStorage();
if (conversionProblems != null && !conversionProblems.isEmpty()) {
@@ -100,7 +100,7 @@
final int result = Messages.showOkCancelDialog(myProject, buffer.toString(), ProjectBundle.message("project.convert.problems.title"),
ProjectBundle.message("project.convert.problems.help.button"),
CommonBundle.getCloseButtonText(), Messages.getWarningIcon());
- if (result == 0) {
+ if (result == Messages.OK) {
HelpManager.getInstance().invokeHelp("project.migrationProblems");
}
}
@@ -137,7 +137,7 @@
String message =
ProjectBundle.message("project.load.new.version.warning", myProject.getName(), appNamesInfo.getProductName());
- if (Messages.showYesNoDialog(message, CommonBundle.getWarningTitle(), Messages.getWarningIcon()) != 0) return false;
+ if (Messages.showYesNoDialog(message, CommonBundle.getWarningTitle(), Messages.getWarningIcon()) != Messages.YES) return false;
}
return true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
index c7c4aec..1b7da8f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StateStorageManagerImpl.java
@@ -31,6 +31,7 @@
import com.intellij.util.SmartList;
import com.intellij.util.io.fs.IFile;
import gnu.trove.THashMap;
+import gnu.trove.THashSet;
import gnu.trove.TObjectLongHashMap;
import org.jdom.Document;
import org.jdom.Element;
@@ -468,19 +469,18 @@
@Override
@Nullable
public Set<String> analyzeExternalChanges(@NotNull final Set<Pair<VirtualFile, StateStorage>> changedFiles) {
- Set<String> result = new HashSet<String>();
-
- nextStorage:
+ Set<String> result = new THashSet<String>();
for (Pair<VirtualFile, StateStorage> pair : changedFiles) {
- final StateStorage stateStorage = pair.second;
- final StateStorage.SaveSession saveSession = myCompoundSaveSession.getSaveSession(stateStorage);
- if (saveSession == null) continue nextStorage;
- final Set<String> s = saveSession.analyzeExternalChanges(changedFiles);
-
- if (s == null) return null;
- result.addAll(s);
+ final StateStorage.SaveSession saveSession = myCompoundSaveSession.getSaveSession(pair.second);
+ if (saveSession == null) {
+ continue;
+ }
+ final Set<String> changes = saveSession.analyzeExternalChanges(changedFiles);
+ if (changes == null) {
+ return null;
+ }
+ result.addAll(changes);
}
-
return result;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java
index 966ed46..583fd3a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ClipboardVsValueContents.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.
@@ -26,7 +26,6 @@
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
/**
* @author Jeka
@@ -72,15 +71,7 @@
@Nullable
public static DiffContent createClipboardContent() {
- Transferable content = CopyPasteManager.getInstance().getContents();
- if (content != null) {
- try {
- String text = (String)(content.getTransferData(DataFlavor.stringFlavor));
- return text != null ? new SimpleContent(text) : null;
- }
- catch (Exception ignored) {
- }
- }
- return null;
+ String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
+ return text != null ? new SimpleContent(text) : null;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffWalkerAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffWalkerAction.java
index bb02c94..99766df 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffWalkerAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/DiffWalkerAction.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 @@
Editor editor = side.getEditor();
if (line >= 0 && editor != null) {
LogicalPosition pos = new LogicalPosition(line, 0);
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToLogicalPosition(pos);
editor.getScrollingModel().scrollToCaret(ScrollType.CENTER);
}
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
new file mode 100644
index 0000000..8ae6fa2
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/HighlightModeAction.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.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 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;
+ }
+
+ @NotNull
+ protected DefaultActionGroup createPopupActionGroup(JComponent button) {
+ DefaultActionGroup actionGroup = new DefaultActionGroup();
+ for (HighlightMode comparisonPolicy : ourActionOrder) {
+ actionGroup.add(myActions.get(comparisonPolicy));
+ }
+ return actionGroup;
+ }
+
+ 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);
+ }
+ }
+
+ private static class SetHighlightModeAction extends DumbAwareAction {
+ private final HighlightMode myHighlightMode;
+
+ public SetHighlightModeAction(String text, HighlightMode mode) {
+ super(text);
+ myHighlightMode = mode;
+ }
+
+ public void actionPerformed(AnActionEvent e) {
+ final DiffPanelImpl diffPanel = DiffPanelImpl.fromDataContext(e.getDataContext());
+ if (diffPanel != null) {
+ 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 78c5ba7..930db0e 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,7 +15,6 @@
*/
package com.intellij.openapi.diff.actions;
-import com.intellij.CommonBundle;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
@@ -26,6 +25,7 @@
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;
@@ -49,7 +49,7 @@
@Override
public JComponent createCustomComponent(final Presentation presentation) {
JPanel panel = new JPanel(new BorderLayout());
- final JLabel label = new JLabel(CommonBundle.message("comparison.ignore.whitespace.acton.name"));
+ 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);
@@ -82,7 +82,7 @@
}
}
- private static class IgnoringPolicyAction extends AnAction {
+ private static class IgnoringPolicyAction extends DumbAwareAction {
private final ComparisonPolicy myPolicy;
public IgnoringPolicyAction(String text, ComparisonPolicy policy) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/actions/ToggleAutoScrollAction.java b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ToggleAutoScrollAction.java
new file mode 100644
index 0000000..e1dec0c
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/actions/ToggleAutoScrollAction.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.actions;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.diff.DiffViewer;
+import com.intellij.openapi.diff.ex.DiffPanelEx;
+import com.intellij.openapi.diff.impl.DiffPanelImpl;
+import com.intellij.openapi.diff.impl.incrementalMerge.ui.MergePanel2;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.ui.ToggleActionButton;
+
+public class ToggleAutoScrollAction extends ToggleActionButton implements DumbAware {
+ public ToggleAutoScrollAction() {
+ super("Auto Scroll", AllIcons.General.AutoscrollToSource);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ DiffViewer viewer = PlatformDataKeys.DIFF_VIEWER.getData(e.getDataContext());
+ if (viewer instanceof DiffPanelEx) return ((DiffPanelEx)viewer).isAutoScrollEnabled();
+ if (viewer instanceof MergePanel2) return ((MergePanel2)viewer).isAutoScrollEnabled();
+ return true;
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ DiffViewer viewer = PlatformDataKeys.DIFF_VIEWER.getData(e.getDataContext());
+ if (viewer instanceof DiffPanelEx) ((DiffPanelEx)viewer).setAutoScrollEnabled(state);
+ if (viewer instanceof MergePanel2) ((MergePanel2)viewer).setAutoScrollEnabled(state);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java
index e0df0bb..bf07a4a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelEx.java
@@ -27,7 +27,9 @@
import com.intellij.openapi.Disposable;
import com.intellij.openapi.diff.DiffPanel;
import com.intellij.openapi.diff.impl.ComparisonPolicy;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
import com.intellij.openapi.editor.Editor;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public interface DiffPanelEx extends DiffPanel, Disposable {
@@ -41,4 +43,13 @@
void setComparisonPolicy(ComparisonPolicy comparisonPolicy);
ComparisonPolicy getComparisonPolicy();
+
+ void setAutoScrollEnabled(boolean enabled);
+
+ boolean isAutoScrollEnabled();
+
+ void setHighlightMode(@NotNull HighlightMode highlightMode);
+
+ @NotNull
+ HighlightMode getHighlightMode();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
index d4ca3d2..538058d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/ex/DiffPanelOptions.java
@@ -90,7 +90,7 @@
while (window instanceof DialogWrapperDialog) {
DialogWrapperDialog dlg = (DialogWrapperDialog)window;
window = window.getParent();
- dlg.getDialogWrapper().close(DialogWrapper.OK_EXIT_CODE);
+ dlg.getDialogWrapper().close(DialogWrapper.CLOSE_EXIT_CODE);
}
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
index bba05ac..fbd04aa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/DiffPanelImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.diff.impl;
+import com.intellij.icons.AllIcons;
import com.intellij.ide.actions.EditSourceAction;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
@@ -25,6 +26,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.*;
import com.intellij.openapi.diff.actions.MergeActionGroup;
+import com.intellij.openapi.diff.actions.ToggleAutoScrollAction;
import com.intellij.openapi.diff.ex.DiffPanelEx;
import com.intellij.openapi.diff.ex.DiffPanelOptions;
import com.intellij.openapi.diff.impl.external.DiffManagerImpl;
@@ -32,6 +34,7 @@
import com.intellij.openapi.diff.impl.fragments.FragmentList;
import com.intellij.openapi.diff.impl.highlighting.DiffPanelState;
import com.intellij.openapi.diff.impl.highlighting.FragmentSide;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
import com.intellij.openapi.diff.impl.processing.HorizontalDiffSplitter;
import com.intellij.openapi.diff.impl.settings.DiffMergeEditorSetting;
import com.intellij.openapi.diff.impl.settings.DiffMergeSettings;
@@ -109,11 +112,22 @@
public void customize(DiffToolbar toolbar) {
ActionManager actionManager = ActionManager.getInstance();
toolbar.addAction(actionManager.getAction("DiffPanel.Toolbar"));
+ toolbar.addSeparator();
+ toolbar.addAction(new ToggleAutoScrollAction());
+ toolbar.addSeparator();
toolbar.addAction(actionManager.getAction("ContextHelp"));
+ toolbar.addAction(getEditSourceAction());
toolbar.addSeparator();
toolbar.addAction(new DiffMergeSettingsAction(Arrays.asList(getEditor1(), getEditor2()),
ServiceManager.getService(myProject, DiffToolSettings.class)));
}
+
+ @NotNull
+ private AnAction getEditSourceAction() {
+ AnAction editSourceAction = new EditSourceAction();
+ editSourceAction.getTemplatePresentation().setIcon(AllIcons.Actions.EditSource);
+ return editSourceAction;
+ }
};
}
@@ -162,10 +176,15 @@
final ComparisonPolicy comparisonPolicy = getComparisonPolicy();
final ComparisonPolicy defaultComparisonPolicy = DiffManagerImpl.getInstanceEx().getComparisonPolicy();
+ final HighlightMode highlightMode = getHighlightMode();
+ final HighlightMode defaultHighlightMode = DiffManagerImpl.getInstanceEx().getHighlightMode();
if (defaultComparisonPolicy != null && comparisonPolicy != defaultComparisonPolicy) {
setComparisonPolicy(defaultComparisonPolicy);
}
+ if (defaultHighlightMode != null && highlightMode != defaultHighlightMode) {
+ setHighlightMode(defaultHighlightMode);
+ }
myVisibleAreaListener = new VisibleAreaListener() {
@Override
public void visibleAreaChanged(VisibleAreaEvent e) {
@@ -449,6 +468,10 @@
return myData.getComparisonPolicy();
}
+ public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) {
+ setComparisonPolicy(comparisonPolicy, true);
+ }
+
private void setComparisonPolicy(ComparisonPolicy policy, boolean notifyManager) {
myData.setComparisonPolicy(policy);
rediff();
@@ -458,8 +481,30 @@
}
}
- public void setComparisonPolicy(ComparisonPolicy comparisonPolicy) {
- setComparisonPolicy(comparisonPolicy, true);
+ @NotNull
+ public HighlightMode getHighlightMode() {
+ return myData.getHighlightMode();
+ }
+
+ public void setHighlightMode(@NotNull HighlightMode mode) {
+ setHighlightMode(mode, true);
+ }
+
+ public void setHighlightMode(@NotNull HighlightMode mode, boolean notifyManager) {
+ myData.setHighlightMode(mode);
+ rediff();
+
+ if (notifyManager) {
+ DiffManagerImpl.getInstanceEx().setHighlightMode(mode);
+ }
+ }
+
+ public void setAutoScrollEnabled(boolean enabled) {
+ myScrollSupport.setEnabled(enabled);
+ }
+
+ public boolean isAutoScrollEnabled() {
+ return myScrollSupport.isEnabled();
}
public Rediffers getDiffUpdater() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java
index f48a5f5..3f87cdb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/external/DiffManagerImpl.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.diff.impl.ComparisonPolicy;
import com.intellij.openapi.diff.impl.DiffPanelImpl;
import com.intellij.openapi.diff.impl.mergeTool.MergeTool;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.markup.MarkupEditorFilter;
import com.intellij.openapi.project.Project;
@@ -78,7 +79,10 @@
}
};
private ComparisonPolicy myComparisonPolicy;
+ private HighlightMode myHighlightMode;
+
@NonNls public static final String COMPARISON_POLICY_ATTR_NAME = "COMPARISON_POLICY";
+ @NonNls public static final String HIGHLIGHT_MODE_ATTR_NAME = "HIGHLIGHT_MODE";
public DiffManagerImpl() {
myProperties = new ExternalizablePropertyContainer();
@@ -153,12 +157,13 @@
return (DiffManagerImpl)DiffManager.getInstance();
}
- public void readExternal(Element element) throws InvalidDataException {
+ public void readExternal(@NotNull Element element) throws InvalidDataException {
myProperties.readExternal(element);
readPolicy(element);
+ readMode(element);
}
- private void readPolicy(final Element element) {
+ private void readPolicy(@NotNull final Element element) {
final String policyName = element.getAttributeValue(COMPARISON_POLICY_ATTR_NAME);
if (policyName != null) {
ComparisonPolicy[] policies = ComparisonPolicy.getAllInstances();
@@ -171,11 +176,25 @@
}
}
- public void writeExternal(Element element) throws WriteExternalException {
+ private void readMode(@NotNull final Element element) {
+ final String modeName = element.getAttributeValue(HIGHLIGHT_MODE_ATTR_NAME);
+ if (modeName != null) {
+ try {
+ myHighlightMode = HighlightMode.valueOf(modeName);
+ }
+ catch (IllegalArgumentException ignore) {
+ }
+ }
+ }
+
+ public void writeExternal(@NotNull Element element) throws WriteExternalException {
myProperties.writeExternal(element);
if (myComparisonPolicy != null) {
element.setAttribute(COMPARISON_POLICY_ATTR_NAME, myComparisonPolicy.getName());
}
+ if (myHighlightMode != null) {
+ element.setAttribute(HIGHLIGHT_MODE_ATTR_NAME, myHighlightMode.name());
+ }
}
public AbstractProperty.AbstractPropertyContainer getProperties() { return myProperties; }
@@ -206,4 +225,13 @@
public ComparisonPolicy getComparisonPolicy() {
return myComparisonPolicy;
}
+
+ public void setHighlightMode(HighlightMode highlightMode) {
+ myHighlightMode = highlightMode;
+ }
+
+ @Nullable
+ public HighlightMode getHighlightMode() {
+ return myHighlightMode;
+ }
}
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 5446f66..14c2354 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
@@ -19,11 +19,9 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diff.impl.ComparisonPolicy;
import com.intellij.openapi.diff.impl.ContentChangeListener;
-import com.intellij.openapi.diff.impl.fragments.FragmentHighlighterImpl;
-import com.intellij.openapi.diff.impl.fragments.FragmentList;
-import com.intellij.openapi.diff.impl.fragments.FragmentListImpl;
-import com.intellij.openapi.diff.impl.fragments.LineFragment;
+import com.intellij.openapi.diff.impl.fragments.*;
import com.intellij.openapi.diff.impl.processing.DiffPolicy;
+import com.intellij.openapi.diff.impl.processing.HighlightMode;
import com.intellij.openapi.diff.impl.processing.TextCompareProcessor;
import com.intellij.openapi.diff.impl.splitter.LineBlocks;
import com.intellij.openapi.project.Project;
@@ -32,11 +30,13 @@
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Iterator;
public abstract class SimpleDiffPanelState implements Disposable {
protected ComparisonPolicy myComparisonPolicy = ComparisonPolicy.DEFAULT;
protected DiffPolicy myDiffPolicy;
+ protected HighlightMode myHighlightMode;
protected final EditorPlaceHolder myAppender1;
protected final EditorPlaceHolder myAppender2;
protected FragmentList myFragmentList = FragmentList.EMPTY;
@@ -47,6 +47,7 @@
myAppender2 = createEditorWrapper(project, changeListener, FragmentSide.SIDE2);
myProject = project;
myDiffPolicy = DiffPolicy.LINES_WO_FORMATTING;
+ myHighlightMode = HighlightMode.BY_WORD;
Disposer.register(parentDisposable, this);
}
@@ -72,6 +73,14 @@
return myComparisonPolicy;
}
+ public HighlightMode getHighlightMode() {
+ return myHighlightMode;
+ }
+
+ public void setHighlightMode(HighlightMode highlightMode) {
+ myHighlightMode = highlightMode;
+ }
+
public void dispose() {
}
@@ -105,7 +114,12 @@
return LineBlocks.EMPTY;
}
- return addMarkup(new TextCompareProcessor(myComparisonPolicy, myDiffPolicy).process(myAppender1.getText(), myAppender2.getText()));
+ 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()));
}
public Project getProject() { return myProject; }
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
index 7281b72..9ba62d5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/incrementalMerge/ui/MergePanel2.java
@@ -16,16 +16,15 @@
package com.intellij.openapi.diff.impl.incrementalMerge.ui;
import com.intellij.icons.AllIcons;
+import com.intellij.ide.actions.EditSourceAction;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.actionSystem.ActionManager;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.*;
import com.intellij.openapi.diff.actions.NextDiffAction;
import com.intellij.openapi.diff.actions.PreviousDiffAction;
+import com.intellij.openapi.diff.actions.ToggleAutoScrollAction;
import com.intellij.openapi.diff.impl.DiffUtil;
import com.intellij.openapi.diff.impl.EditingSides;
import com.intellij.openapi.diff.impl.GenericDataProvider;
@@ -151,6 +150,8 @@
toolbar.addAction(new OpenPartialDiffAction(0, 2, AllIcons.Diff.BranchDiff));
toolbar.addSeparator();
toolbar.addAction(new ApplyNonConflicts(myPanel));
+ toolbar.addSeparator();
+ toolbar.addAction(new ToggleAutoScrollAction());
Project project = myData.getProject();
if (project != null) {
toolbar.addSeparator();
@@ -262,6 +263,14 @@
return new MyEditingSides(FragmentSide.SIDE2);
}
+ public void setAutoScrollEnabled(boolean enabled) {
+ myScrollSupport.setEnabled(enabled);
+ }
+
+ public boolean isAutoScrollEnabled() {
+ return myScrollSupport.isEnabled();
+ }
+
public void setHighlighterSettings(@Nullable EditorColorsScheme settings) {
for (EditorPlace place : getEditorPlaces()) {
setHighlighterSettings(settings, place);
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
index 1510183..3b1385e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/mergeTool/MergeRequestImpl.java
@@ -293,7 +293,7 @@
DiffBundle.message("all.changes.processed.dialog.title"),
DiffBundle.message("merge.save.and.finish.button"), DiffBundle.message("merge.continue.button"),
Messages.getQuestionIcon());
- if (doApply != 0) return;
+ if (doApply != Messages.OK) return;
myDialogWrapper.close(DialogWrapper.OK_EXIT_CODE);
}
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 1555656..b2da49e 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
@@ -32,28 +32,42 @@
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;
- public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) {
+ public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy,
+ final DiffPolicy diffPolicy,
+ boolean searchForSubFragments) {
myComparisonPolicy = comparisonPolicy;
myDiffPolicy = diffPolicy;
+ mySearchForSubFragments = searchForSubFragments;
}
- public TextCompareProcessor(ComparisonPolicy comparisonPolicy) {
+ public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy, final DiffPolicy diffPolicy) {
+ this(comparisonPolicy, diffPolicy, true);
+ }
+
+ public TextCompareProcessor(@NotNull ComparisonPolicy comparisonPolicy) {
this(comparisonPolicy, DiffPolicy.LINES_WO_FORMATTING);
}
public ArrayList<LineFragment> process(String text1, String text2) throws FilesTooBigForDiffException {
+ if (text1.isEmpty() || text2.isEmpty()) {
+ return new DummyDiffFragmentsProcessor().process(text1, text2);
+ }
+
DiffFragment[] woFormattingBlocks = myDiffPolicy.buildFragments(text1, text2);
- DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).
- correctAndNormalize(woFormattingBlocks);
+ DiffFragment[] step1lineFragments = new DiffCorrection.TrueLineBlocks(myComparisonPolicy).correctAndNormalize(woFormattingBlocks);
ArrayList<LineFragment> lineBlocks = new DiffFragmentsProcessor().process(step1lineFragments);
- for (LineFragment lineBlock : lineBlocks) {
- if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
- String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
- String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
- ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
- lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
- lineBlock.adjustTypeFromChildrenTypes();
+
+ if (mySearchForSubFragments) {
+ for (LineFragment lineBlock : lineBlocks) {
+ if (lineBlock.isOneSide() || lineBlock.isEqual()) continue;
+ String subText1 = lineBlock.getText(text1, FragmentSide.SIDE1);
+ String subText2 = lineBlock.getText(text2, FragmentSide.SIDE2);
+ ArrayList<LineFragment> subFragments = findSubFragments(subText1, subText2);
+ lineBlock.setChildren(new ArrayList<Fragment>(subFragments));
+ lineBlock.adjustTypeFromChildrenTypes();
+ }
}
return lineBlocks;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/LineBlocks.java b/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/LineBlocks.java
index 3046c87..d89bc27 100644
--- a/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/LineBlocks.java
+++ b/platform/platform-impl/src/com/intellij/openapi/diff/impl/splitter/LineBlocks.java
@@ -165,7 +165,7 @@
return LinearTransformation.oneToOne(location, leftInterval.getStart(), rightInterval);
}
- public static LineBlocks fromLineFragments(ArrayList<LineFragment> lines) {
+ public static LineBlocks fromLineFragments(List<LineFragment> lines) {
ArrayList<LineBlock> filtered = new ArrayList<LineBlock>();
for (LineFragment fragment : lines) {
if (fragment.getType() != null) filtered.add(fragment);
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 ab45e1e..e169a9c 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
@@ -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.
@@ -36,6 +36,7 @@
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>();
+ private boolean myEnabled = true;
public void install(EditingSides[] sideContainers) {
Disposer.dispose(this);
@@ -58,6 +59,14 @@
myScrollers.clear();
}
+ public void setEnabled(boolean enabled) {
+ myEnabled = enabled;
+ }
+
+ public boolean isEnabled() {
+ 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]));
@@ -100,7 +109,7 @@
}
public void visibleAreaChanged(VisibleAreaEvent e) {
- if (myDuringVerticalScroll) return;
+ if (!myEnabled || myDuringVerticalScroll) return;
Rectangle newRectangle = e.getNewRectangle();
Rectangle oldRectangle = e.getOldRectangle();
if (newRectangle == null || oldRectangle == null) return;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java
index 5fbec80..ad5d0c2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/BackspaceAction.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.
@@ -24,12 +24,14 @@
*/
package com.intellij.openapi.editor.actions;
+import com.intellij.injected.editor.EditorWindow;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.util.ui.MacUIUtil;
+import org.jetbrains.annotations.NotNull;
public class BackspaceAction extends EditorAction {
public BackspaceAction() {
@@ -37,10 +39,19 @@
}
private static class Handler extends EditorWriteActionHandler {
+ private Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
MacUIUtil.hideCursor();
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
+ if (editor instanceof EditorWindow) {
+ // manipulate actual document/editor instead of injected
+ // since the latter have trouble finding the right location of caret movement in the case of multi-shred injected fragments
+ editor = ((EditorWindow)editor).getDelegate();
+ }
final SelectionModel selectionModel = editor.getSelectionModel();
if (selectionModel.hasBlockSelection()) {
final LogicalPosition start = selectionModel.getBlockStart();
@@ -65,7 +76,7 @@
}
}
- private static void doBackSpaceAtCaret(Editor editor) {
+ private static void doBackSpaceAtCaret(@NotNull Editor editor) {
if(editor.getSelectionModel().hasSelection()) {
int newOffset = editor.getSelectionModel().getSelectionStart();
if (EditorActionUtil.canEditAtOffset(editor, newOffset)) {
@@ -82,13 +93,12 @@
int offset = editor.getCaretModel().getOffset();
if(colNumber > 0) {
if(EditorModificationUtil.calcAfterLineEnd(editor) > 0) {
- int columnShift = -1;
if (EditorActionUtil.canEditAtOffset(editor, offset - 1)) {
+ int columnShift = -1;
editor.getCaretModel().moveCaretRelatively(columnShift, 0, false, false, true);
}
}
else {
-
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
editor.getSelectionModel().removeSelection();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
new file mode 100644
index 0000000..4b91f52
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretAbove.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.actionSystem.EditorAction;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import org.jetbrains.annotations.NotNull;
+
+public class CloneCaretAbove extends EditorAction {
+ public CloneCaretAbove() {
+ super(new Handler());
+ }
+
+ private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
+ @Override
+ public void execute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ caret.clone(true);
+ }
+
+ @Override
+ public boolean isEnabled(Editor editor, DataContext dataContext) {
+ return editor.getCaretModel().supportsMultipleCarets();
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
new file mode 100644
index 0000000..df3a966
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CloneCaretBelow.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.CaretModel;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.actionSystem.EditorAction;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import org.jetbrains.annotations.NotNull;
+
+public class CloneCaretBelow extends EditorAction {
+ public CloneCaretBelow() {
+ super(new Handler());
+ }
+
+ private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
+ @Override
+ public void execute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ CaretModel caretModel = editor.getCaretModel();
+ if (caretModel.supportsMultipleCarets()) {
+ caret.clone(false);
+ }
+ }
+
+ @Override
+ public boolean isEnabled(Editor editor, DataContext dataContext) {
+ return editor.getCaretModel().supportsMultipleCarets();
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java
index 0c96516..0928cba 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ContentChooser.java
@@ -122,7 +122,7 @@
myList.setCellRenderer(new MyListCellRenderer());
myList.addKeyListener(new KeyAdapter() {
@Override
- public void keyReleased(KeyEvent e) {
+ public void keyPressed(KeyEvent e) {
if (e.getKeyCode() == KeyEvent.VK_DELETE) {
int newSelectionIndex = -1;
for (Object o : myList.getSelectedValues()) {
@@ -150,6 +150,8 @@
int idx = aChar == '0' ? 9 : aChar - '1';
if (idx < myAllContents.size()) {
myList.setSelectedIndex(idx);
+ e.consume();
+ doOKAction();
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CopyAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CopyAction.java
index 7fc93e8..24e5e55 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CopyAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CopyAction.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,8 @@
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -40,12 +42,18 @@
private static class Handler extends EditorActionHandler {
@Override
- public void execute(Editor editor, DataContext dataContext) {
- if (!editor.getSelectionModel().hasSelection() && !editor.getSelectionModel().hasBlockSelection()) {
+ public void execute(final Editor editor, DataContext dataContext) {
+ if (!editor.getSelectionModel().hasSelection(true) && !editor.getSelectionModel().hasBlockSelection()) {
if (Registry.is(SKIP_COPY_AND_CUT_FOR_EMPTY_SELECTION_KEY)) {
return;
}
- editor.getSelectionModel().selectLineAtCaret();
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ editor.getSelectionModel().selectLineAtCaret();
+ EditorActionUtil.moveCaretToLineStartIgnoringSoftWraps(editor);
+ }
+ });
}
editor.getSelectionModel().copySelectionToClipboard();
}
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 0f6cec3..4fc378e 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
@@ -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.
@@ -24,11 +24,13 @@
*/
package com.intellij.openapi.editor.actions;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
+import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
-import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.util.registry.Registry;
public class CutAction extends EditorAction {
@@ -38,15 +40,25 @@
public static class Handler extends EditorWriteActionHandler {
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
- if(!editor.getSelectionModel().hasSelection()) {
+ public void executeWriteAction(final Editor editor, DataContext dataContext) {
+ if(!editor.getSelectionModel().hasSelection(true)) {
if (Registry.is(CopyAction.SKIP_COPY_AND_CUT_FOR_EMPTY_SELECTION_KEY)) {
return;
}
- editor.getSelectionModel().selectLineAtCaret();
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ editor.getSelectionModel().selectLineAtCaret();
+ }
+ });
}
editor.getSelectionModel().copySelectionToClipboard();
- EditorModificationUtil.deleteSelectedText(editor);
+ editor.getCaretModel().runForEachCaret(new CaretAction() {
+ @Override
+ public void perform(Caret caret) {
+ EditorModificationUtil.deleteSelectedText(editor);
+ }
+ });
}
}
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineEndAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineEndAction.java
index ca52dba..91e0105 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineEndAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/CutLineEndAction.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.
@@ -29,6 +29,7 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
+import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
@@ -54,6 +55,10 @@
final int lineNumber = doc.getLineNumber(caretOffset);
int lineEndOffset = doc.getLineEndOffset(lineNumber);
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets() && caretOffset == lineEndOffset) {
+ return;
+ }
+
int start;
int end;
if (caretOffset >= lineEndOffset) {
@@ -75,6 +80,9 @@
if (myCopyToClipboard) {
KillRingUtil.copyToKillRing(editor, start, end, true);
}
+ else {
+ CopyPasteManager.getInstance().stopKillRings();
+ }
editor.getDocument().deleteString(start, end);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java
index 4f03351..98d941b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteAction.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.
@@ -30,6 +30,7 @@
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ui.MacUIUtil;
@@ -39,10 +40,15 @@
}
public static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
MacUIUtil.hideCursor();
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
+ CopyPasteManager.getInstance().stopKillRings();
SelectionModel selectionModel = editor.getSelectionModel();
final LogicalPosition logicalBlockSelectionStart = selectionModel.getBlockStart();
final LogicalPosition logicalBlockSelectionEnd = selectionModel.getBlockEnd();
@@ -102,9 +108,12 @@
public static void deleteCharAtCaret(Editor editor) {
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
+ int offset = editor.getCaretModel().getOffset();
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets() && offset == editor.getDocument().getLineEndOffset(lineNumber)) {
+ return;
+ }
int afterLineEnd = EditorModificationUtil.calcAfterLineEnd(editor);
Document document = editor.getDocument();
- int offset = editor.getCaretModel().getOffset();
if (!EditorActionUtil.canEditAtOffset(editor, offset + 1)) return;
if (afterLineEnd < 0
// There is a possible case that caret is located right before the soft wrap position at the last logical line
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java
index b9ea85b..4b5201e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteLineAction.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,6 +28,7 @@
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
+import com.intellij.openapi.ide.CopyPasteManager;
public class DeleteLineAction extends TextComponentEditorAction {
public DeleteLineAction() {
@@ -35,9 +36,14 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
+ CopyPasteManager.getInstance().stopKillRings();
SelectionModel selectionModel = editor.getSelectionModel();
Document document = editor.getDocument();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java
index 92c8317..c261c6c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordEndAction.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.
@@ -29,6 +29,7 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
+import com.intellij.openapi.ide.CopyPasteManager;
public class DeleteToWordEndAction extends TextComponentEditorAction {
public DeleteToWordEndAction() {
@@ -40,12 +41,21 @@
private final boolean myNegateCamelMode;
Handler(boolean negateCamelMode) {
+ super(true);
myNegateCamelMode = negateCamelMode;
}
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
+ CopyPasteManager.getInstance().stopKillRings();
+
+ int lineNumber = editor.getCaretModel().getLogicalPosition().line;
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets()
+ && editor.getCaretModel().getOffset() == editor.getDocument().getLineEndOffset(lineNumber)) {
+ return;
+ }
+
boolean camelMode = editor.getSettings().isCamelWords();
if (myNegateCamelMode) {
camelMode = !camelMode;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java
index cc8399a..76e2516 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DeleteToWordStartAction.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.
@@ -74,6 +74,7 @@
private final boolean myNegateCamelMode;
Handler(boolean negateCamelMode) {
+ super(true);
myNegateCamelMode = negateCamelMode;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java
index 5e73400..0e92fcf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateAction.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,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
duplicateLineOrSelectedBlockAtCaret(editor);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java
index 2560098..0a2db77 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/DuplicateLinesAction.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,6 +31,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
if (editor.getSelectionModel().hasSelection()) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java
index f9d7f6e..e86bc16 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EditorActionUtil.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.
@@ -44,6 +44,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EditorPopupHandler;
+import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.awt.event.MouseEvent;
@@ -79,7 +80,7 @@
* @param columnShift defines viewport position's horizontal change length
* @param moveCaret flag that identifies whether caret should be moved if its current position becomes off-screen
*/
- public static void scrollRelatively(Editor editor, int lineShift, int columnShift, boolean moveCaret) {
+ public static void scrollRelatively(@NotNull Editor editor, int lineShift, int columnShift, boolean moveCaret) {
if (lineShift != 0) {
editor.getScrollingModel().scrollVertically(
editor.getScrollingModel().getVerticalScrollOffset() + lineShift * editor.getLineHeight()
@@ -97,21 +98,19 @@
Rectangle viewRectangle = editor.getScrollingModel().getVisibleArea();
int lineNumber = editor.getCaretModel().getVisualPosition().line;
- if (viewRectangle != null) {
- VisualPosition startPos = editor.xyToVisualPosition(new Point(0, viewRectangle.y));
- int start = startPos.line + 1;
- VisualPosition endPos = editor.xyToVisualPosition(new Point(0, viewRectangle.y + viewRectangle.height));
- int end = endPos.line - 2;
- if (lineNumber < start) {
- editor.getCaretModel().moveCaretRelatively(0, start - lineNumber, false, false, true);
- }
- else if (lineNumber > end) {
- editor.getCaretModel().moveCaretRelatively(0, end - lineNumber, false, false, true);
- }
+ VisualPosition startPos = editor.xyToVisualPosition(new Point(0, viewRectangle.y));
+ int start = startPos.line + 1;
+ VisualPosition endPos = editor.xyToVisualPosition(new Point(0, viewRectangle.y + viewRectangle.height));
+ int end = endPos.line - 2;
+ if (lineNumber < start) {
+ editor.getCaretModel().moveCaretRelatively(0, start - lineNumber, false, false, true);
+ }
+ else if (lineNumber > end) {
+ editor.getCaretModel().moveCaretRelatively(0, end - lineNumber, false, false, true);
}
}
- public static void moveCaretRelativelyAndScroll(Editor editor,
+ public static void moveCaretRelativelyAndScroll(@NotNull Editor editor,
int columnShift,
int lineShift,
boolean withSelection) {
@@ -131,19 +130,18 @@
}
}
- @SuppressWarnings({"AssignmentToForLoopParameter"})
- public static void indentLine(Project project, Editor editor, int lineNumber, int indent) {
+ public static void indentLine(Project project, @NotNull Editor editor, int lineNumber, int indent) {
EditorSettings editorSettings = editor.getSettings();
Document document = editor.getDocument();
int spacesEnd = 0;
int lineStart = 0;
int tabsEnd = 0;
- boolean inTabs = true;
if (lineNumber < document.getLineCount()) {
lineStart = document.getLineStartOffset(lineNumber);
int lineEnd = document.getLineEndOffset(lineNumber);
spacesEnd = lineStart;
CharSequence text = document.getCharsSequence();
+ boolean inTabs = true;
for (; spacesEnd <= lineEnd; spacesEnd++) {
if (spacesEnd == lineEnd) {
break;
@@ -206,15 +204,14 @@
editor.getCaretModel().moveToOffset(Math.min(document.getTextLength(), newCaretOffset));
}
- private static boolean shouldUseSmartTabs(Project project, Editor editor) {
+ private static boolean shouldUseSmartTabs(Project project, @NotNull Editor editor) {
if (!(editor instanceof EditorEx)) return false;
VirtualFile file = ((EditorEx)editor).getVirtualFile();
FileType fileType = file == null ? null : file.getFileType();
- if (fileType == null) return false;
- return CodeStyleFacade.getInstance(project).isSmartTabs(fileType);
+ return fileType != null && CodeStyleFacade.getInstance(project).isSmartTabs(fileType);
}
- public static boolean isWordStart(CharSequence text, int offset, boolean isCamel) {
+ public static boolean isWordStart(@NotNull CharSequence text, int offset, boolean isCamel) {
char prev = offset > 0 ? text.charAt(offset - 1) : 0;
char current = text.charAt(offset);
@@ -236,7 +233,7 @@
return Character.isLowerCase(c) || Character.isDigit(c);
}
- public static boolean isWordEnd(CharSequence text, int offset, boolean isCamel) {
+ public static boolean isWordEnd(@NotNull CharSequence text, int offset, boolean isCamel) {
char prev = offset > 0 ? text.charAt(offset - 1) : 0;
char current = text.charAt(offset);
char next = offset + 1 < text.length() ? text.charAt(offset + 1) : 0;
@@ -261,7 +258,15 @@
(Character.isWhitespace(current) || secondIsIdentifierPart);
}
- public static void moveCaretToLineStart(Editor editor, boolean isWithSelection) {
+ /**
+ * Depending on the current caret position and 'smart Home' editor settings, moves caret to the start of current visual line
+ * or to the first non-whitespace character on it.
+ *
+ * @param isWithSelection if true - sets selection from old caret position to the new one, if false - clears selection
+ *
+ * @see com.intellij.openapi.editor.actions.EditorActionUtil#moveCaretToLineStartIgnoringSoftWraps(com.intellij.openapi.editor.Editor)
+ */
+ public static void moveCaretToLineStart(@NotNull Editor editor, boolean isWithSelection) {
Document document = editor.getDocument();
SelectionModel selectionModel = editor.getSelectionModel();
int selectionStart = selectionModel.getLeadSelectionOffset();
@@ -320,10 +325,10 @@
}
else {
int line = logLineEndVis.line;
- int column = 0;
if (currentVisCaret.column == 0 && editorSettings.isSmartHome()) {
findSmartIndentColumn(editor, line);
}
+ int column = 0;
caretModel.moveToVisualPosition(new VisualPosition(line, column));
}
}
@@ -332,7 +337,7 @@
editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
- private static void moveCaretToStartOfSoftWrappedLine(Editor editor, VisualPosition currentVisual, int softWrappedLines) {
+ private static void moveCaretToStartOfSoftWrappedLine(@NotNull Editor editor, VisualPosition currentVisual, int softWrappedLines) {
CaretModel caretModel = editor.getCaretModel();
LogicalPosition startLineLogical = editor.visualToLogicalPosition(new VisualPosition(currentVisual.line, 0));
int startLineOffset = editor.logicalPositionToOffset(startLineLogical);
@@ -342,7 +347,7 @@
// Don't expect to be here.
int column = findFirstNonSpaceColumnOnTheLine(editor, currentVisual.line);
int columnToMove = column;
- if (column < 0 || (currentVisual.column <= column && currentVisual.column > 0)) {
+ if (column < 0 || currentVisual.column <= column && currentVisual.column > 0) {
columnToMove = 0;
}
caretModel.moveToVisualPosition(new VisualPosition(currentVisual.line, columnToMove));
@@ -373,7 +378,7 @@
}
}
- private static int findSmartIndentColumn(Editor editor, int visualLine) {
+ private static int findSmartIndentColumn(@NotNull Editor editor, int visualLine) {
for (int i = visualLine; i >= 0; i--) {
int column = findFirstNonSpaceColumnOnTheLine(editor, i);
if (column >= 0) {
@@ -391,7 +396,7 @@
* @return visual column that points to the first non-white space symbol at the target visual line if the one exists;
* <code>'-1'</code> otherwise
*/
- public static int findFirstNonSpaceColumnOnTheLine(Editor editor, int visualLineNumber) {
+ public static int findFirstNonSpaceColumnOnTheLine(@NotNull Editor editor, int visualLineNumber) {
Document document = editor.getDocument();
VisualPosition visLine = new VisualPosition(visualLineNumber, 0);
int logLine = editor.visualToLogicalPosition(visLine).line;
@@ -464,7 +469,7 @@
return -1;
}
- public static int findFirstNonSpaceOffsetOnTheLine(Document document, int lineNumber) {
+ public static int findFirstNonSpaceOffsetOnTheLine(@NotNull Document document, int lineNumber) {
int lineStart = document.getLineStartOffset(lineNumber);
int lineEnd = document.getLineEndOffset(lineNumber);
int result = findFirstNonSpaceOffsetInRange(document.getCharsSequence(), lineStart, lineEnd);
@@ -480,7 +485,7 @@
* @return index of the first non-white space character at the given document at the given range if the one is found;
* <code>'-1'</code> otherwise
*/
- public static int findFirstNonSpaceOffsetInRange(CharSequence text, int start, int end) {
+ public static int findFirstNonSpaceOffsetInRange(@NotNull CharSequence text, int start, int end) {
for (; start < end; start++) {
char c = text.charAt(start);
if (c != ' ' && c != '\t') {
@@ -490,7 +495,7 @@
return -1;
}
- public static void moveCaretToLineEnd(Editor editor, boolean isWithSelection) {
+ public static void moveCaretToLineEnd(@NotNull Editor editor, boolean isWithSelection) {
Document document = editor.getDocument();
SelectionModel selectionModel = editor.getSelectionModel();
int selectionStart = selectionModel.getLeadSelectionOffset();
@@ -536,12 +541,10 @@
}
}
- int offset;
- int newOffset;
LogicalPosition logLineEnd = editor.visualToLogicalPosition(visualEndOfLineWithCaret);
- offset = editor.logicalPositionToOffset(logLineEnd);
+ int offset = editor.logicalPositionToOffset(logLineEnd);
lineNumber = logLineEnd.line;
- newOffset = offset;
+ int newOffset = offset;
CharSequence text = document.getCharsSequence();
for (int i = newOffset - 1; i >= document.getLineStartOffset(lineNumber); i--) {
@@ -569,7 +572,7 @@
setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
}
- public static void moveCaretToNextWord(Editor editor, boolean isWithSelection, boolean camel) {
+ public static void moveCaretToNextWord(@NotNull Editor editor, boolean isWithSelection, boolean camel) {
Document document = editor.getDocument();
SelectionModel selectionModel = editor.getSelectionModel();
int selectionStart = selectionModel.getLeadSelectionOffset();
@@ -604,9 +607,10 @@
setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
}
- private static void setupSelection(Editor editor,
+ private static void setupSelection(@NotNull Editor editor,
boolean isWithSelection,
- int selectionStart, LogicalPosition blockSelectionStart) {
+ int selectionStart,
+ @NotNull LogicalPosition blockSelectionStart) {
SelectionModel selectionModel = editor.getSelectionModel();
CaretModel caretModel = editor.getCaretModel();
if (isWithSelection) {
@@ -624,8 +628,8 @@
selectNonexpandableFold(editor);
}
- private final static Key<VisualPosition> PREV_POS = Key.create("PREV_POS");
- public static void selectNonexpandableFold(Editor editor) {
+ private static final Key<VisualPosition> PREV_POS = Key.create("PREV_POS");
+ public static void selectNonexpandableFold(@NotNull Editor editor) {
final CaretModel caretModel = editor.getCaretModel();
final VisualPosition pos = caretModel.getVisualPosition();
@@ -650,7 +654,7 @@
editor.putUserData(PREV_POS, pos);
}
- public static void moveCaretToPreviousWord(Editor editor, boolean isWithSelection, boolean camel) {
+ public static void moveCaretToPreviousWord(@NotNull Editor editor, boolean isWithSelection, boolean camel) {
Document document = editor.getDocument();
SelectionModel selectionModel = editor.getSelectionModel();
int selectionStart = selectionModel.getLeadSelectionOffset();
@@ -675,7 +679,7 @@
setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
}
- public static void moveCaretPageUp(Editor editor, boolean isWithSelection) {
+ public static void moveCaretPageUp(@NotNull Editor editor, boolean isWithSelection) {
((EditorEx)editor).stopOptimizedScrolling();
int lineHeight = editor.getLineHeight();
Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
@@ -685,7 +689,7 @@
editor.getCaretModel().moveCaretRelatively(0, lineShift, isWithSelection, editor.isColumnMode(), true);
}
- public static void moveCaretPageDown(Editor editor, boolean isWithSelection) {
+ public static void moveCaretPageDown(@NotNull Editor editor, boolean isWithSelection) {
((EditorEx)editor).stopOptimizedScrolling();
int lineHeight = editor.getLineHeight();
Rectangle visibleArea = editor.getScrollingModel().getVisibleArea();
@@ -696,7 +700,7 @@
editor.getCaretModel().moveCaretRelatively(0, linesIncrement, isWithSelection, editor.isColumnMode(), true);
}
- public static void moveCaretPageTop(Editor editor, boolean isWithSelection) {
+ public static void moveCaretPageTop(@NotNull Editor editor, boolean isWithSelection) {
int lineHeight = editor.getLineHeight();
SelectionModel selectionModel = editor.getSelectionModel();
int selectionStart = selectionModel.getLeadSelectionOffset();
@@ -714,7 +718,7 @@
setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
}
- public static void moveCaretPageBottom(Editor editor, boolean isWithSelection) {
+ public static void moveCaretPageBottom(@NotNull Editor editor, boolean isWithSelection) {
int lineHeight = editor.getLineHeight();
SelectionModel selectionModel = editor.getSelectionModel();
int selectionStart = selectionModel.getLeadSelectionOffset();
@@ -729,7 +733,7 @@
setupSelection(editor, isWithSelection, selectionStart, blockSelectionStart);
}
- public static EditorPopupHandler createEditorPopupHandler(final String groupId) {
+ public static EditorPopupHandler createEditorPopupHandler(@NotNull final String groupId) {
return new EditorPopupHandler() {
@Override
public void invokePopup(final EditorMouseEvent event) {
@@ -747,7 +751,7 @@
};
}
- public static boolean canEditAtOffset(Editor editor, int offset) {
+ public static boolean canEditAtOffset(@NotNull Editor editor, int offset) {
final Pair<String,String> markers = editor.getUserData(EditorImpl.EDITABLE_AREA_MARKER);
if (markers != null) {
final String text = editor.getDocument().getText();
@@ -758,7 +762,7 @@
return true;
}
- public static boolean isHumpBound(CharSequence editorText, int offset, boolean start) {
+ public static boolean isHumpBound(@NotNull CharSequence editorText, int offset, boolean start) {
final char prevChar = editorText.charAt(offset - 1);
final char curChar = editorText.charAt(offset);
final char nextChar = offset + 1 < editorText.length() ? editorText.charAt(offset + 1) : 0; // 0x00 is not lowercase.
@@ -770,4 +774,14 @@
!start && Character.isLetterOrDigit(prevChar) && curChar == '$' ||
Character.isUpperCase(prevChar) && Character.isUpperCase(curChar) && Character.isLowerCase(nextChar);
}
+
+ /**
+ * This method moves caret to the nearest preceding visual line start, which is not a soft line wrap
+ *
+ * @see com.intellij.openapi.editor.ex.util.EditorUtil#calcCaretLineRange(com.intellij.openapi.editor.Editor)
+ * @see com.intellij.openapi.editor.actions.EditorActionUtil#moveCaretToLineStart(com.intellij.openapi.editor.Editor, boolean)
+ */
+ public static void moveCaretToLineStartIgnoringSoftWraps(@NotNull Editor editor) {
+ editor.getCaretModel().moveToLogicalPosition(EditorUtil.calcCaretLineRange(editor).first);
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java
index 10f3b2e..cc7b217 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/EnterAction.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,6 +38,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandName(EditorBundle.message("typing.command.name"));
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 5280eb3..16b6676 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
@@ -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.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.actionSystem.EditorAction;
@@ -41,15 +42,15 @@
editorEx.setStickySelection(false);
}
}
-
+ editor.getCaretModel().removeSecondaryCarets();
editor.getSelectionModel().removeSelection();
}
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
SelectionModel selectionModel = editor.getSelectionModel();
- return //PlatformDataKeys.IS_MODAL_CONTEXT.getData(dataContext) != Boolean.TRUE &&
- (selectionModel.hasSelection() || selectionModel.hasBlockSelection());
+ CaretModel caretModel = editor.getCaretModel();
+ return selectionModel.hasSelection() || selectionModel.hasBlockSelection() || caretModel.getAllCarets().size() > 1;
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.java
index 548b4ff..094c952 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/HungryBackspaceAction.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.
@@ -41,6 +41,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(@NotNull Editor editor, DataContext dataContext) {
final Document document = editor.getDocument();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/InactiveEditorAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/InactiveEditorAction.java
index 7a0460e..96690b5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/InactiveEditorAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/InactiveEditorAction.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class InactiveEditorAction extends EditorAction {
@@ -33,7 +34,7 @@
@Override
@Nullable
- protected Editor getEditor(final DataContext dataContext) {
+ protected Editor getEditor(@NotNull final DataContext dataContext) {
return CommonDataKeys.EDITOR_EVEN_IF_INACTIVE.getData(dataContext);
}
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java
index 30362f5..214004d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/IndentSelectionAction.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,6 +40,7 @@
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -51,6 +52,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
@@ -75,7 +80,29 @@
}
protected static boolean originalIsEnabled(Editor editor, boolean wantSelection) {
- return (!wantSelection || editor.getSelectionModel().hasSelection()) && !editor.isOneLineMode();
+ return (!wantSelection || hasSuitableSelection(editor)) && !editor.isOneLineMode();
+ }
+
+ /**
+ * Returns true if there is a selection in the editor and it spans multiple lines or the whole single line (potentially without leading and
+ * trailing whitespaces).
+ */
+ private static boolean hasSuitableSelection(Editor editor) {
+ if (!editor.getSelectionModel().hasSelection()) {
+ return false;
+ }
+ Document document = editor.getDocument();
+ int selectionStart = editor.getSelectionModel().getSelectionStart();
+ int selectionEnd = editor.getSelectionModel().getSelectionEnd();
+ int selectionLineStart = document.getLineNumber(selectionStart);
+ int selectionLineEnd = document.getLineNumber(selectionEnd);
+ if (selectionLineStart != selectionLineEnd) {
+ return true;
+ }
+ int lineStart = document.getLineStartOffset(selectionLineStart);
+ int lineEnd = document.getLineEndOffset(selectionLineEnd);
+ return (selectionStart <= lineStart || CharArrayUtil.containsOnlyWhiteSpaces(document.getCharsSequence().subSequence(lineStart, selectionStart)))
+ && (selectionEnd >= lineEnd || CharArrayUtil.containsOnlyWhiteSpaces(document.getCharsSequence().subSequence(selectionEnd, lineEnd)));
}
private static void indentSelection(Editor editor, Project project) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/JoinLinesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/JoinLinesAction.java
index 626714c..306cdfa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/JoinLinesAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/JoinLinesAction.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.
@@ -37,6 +37,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
final Document doc = editor.getDocument();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndAction.java
index f8ce304..9fcbbe8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndAction.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,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToLineEnd(editor, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndWithSelectionAction.java
index 7db0895..3b7ce32 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineEndWithSelectionAction.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,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToLineEnd(editor, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartAction.java
index 6c41cdb..cff12d2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartAction.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,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToLineStart(editor, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartWithSelectionAction.java
index cb62d8e..f39026f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/LineStartWithSelectionAction.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,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToLineStart(editor, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownAction.java
index 0b35906..80f3a34 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
editor.getCaretModel().moveCaretRelatively(0, 1, false, false, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownWithSelectionAction.java
index 8499ced..607def6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretDownWithSelectionAction.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,9 +25,11 @@
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import org.jetbrains.annotations.NotNull;
public class MoveCaretDownWithSelectionAction extends EditorAction {
public MoveCaretDownWithSelectionAction() {
@@ -35,9 +37,18 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
- public void execute(Editor editor, DataContext dataContext) {
- editor.getCaretModel().moveCaretRelatively(0, 1, true, editor.isColumnMode(), true);
+ public void execute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets()) {
+ caret.clone(false);
+ }
+ else {
+ editor.getCaretModel().moveCaretRelatively(0, 1, true, editor.isColumnMode(), true);
+ }
}
}
}
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 8ad4329..1883cb5 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
@@ -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.
@@ -31,6 +31,7 @@
private final Direction myDirection;
MoveCaretLeftOrRightHandler(Direction direction) {
+ super(true);
myDirection = direction;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftWithSelectionAction.java
index a8f22a2..1bdeaf5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretLeftWithSelectionAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
int columnShift = -1;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretRightWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretRightWithSelectionAction.java
index b84ce85..19d729f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretRightWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretRightWithSelectionAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
editor.getCaretModel().moveCaretRelatively(1, 0, true, editor.isColumnMode(), true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpAction.java
index 4a31803..45992dd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
int lineShift = -1;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpWithSelectionAction.java
index d137d4b..f4bb99e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MoveCaretUpWithSelectionAction.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,9 +25,11 @@
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import org.jetbrains.annotations.NotNull;
public class MoveCaretUpWithSelectionAction extends EditorAction {
public MoveCaretUpWithSelectionAction() {
@@ -35,10 +37,18 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
- public void execute(Editor editor, DataContext dataContext) {
- int lineShift = -1;
- editor.getCaretModel().moveCaretRelatively(0, lineShift, true, editor.isColumnMode(), true);
+ public void execute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets()) {
+ caret.clone(true);
+ }
+ else {
+ editor.getCaretModel().moveCaretRelatively(0, -1, true, editor.isColumnMode(), true);
+ }
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MultiplePasteAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MultiplePasteAction.java
index 416c0a9..f2d26ef 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/MultiplePasteAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/MultiplePasteAction.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.
@@ -92,7 +92,7 @@
if (chooser.isOK()) {
final int[] selectedIndices = chooser.getSelectedIndices();
if (selectedIndices.length == 1) {
- copyPasteManager.moveContentTopStackTop(chooser.getAllContents().get(selectedIndices[0]));
+ copyPasteManager.moveContentToStackTop(chooser.getAllContents().get(selectedIndices[0]));
}
else {
copyPasteManager.setContents(new StringSelection(chooser.getSelectedText()));
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordAction.java
index 4c35622..9db48b4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToNextWord(editor, false, editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeAction.java
index d0fb2bc..4f1f306 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeAction.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,6 +30,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToNextWord(editor, false, !editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeWithSelectionAction.java
index bf1c4da..0e5afda 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordInDifferentHumpsModeWithSelectionAction.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,6 +30,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToNextWord(editor, true, !editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordWithSelectionAction.java
index 8967c0e..6de8960 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/NextWordWithSelectionAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToNextWord(editor, true, editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomAction.java
index c82e839..1515baf 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretPageBottom(editor, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomWithSelectionAction.java
index 221ce42..be3a04c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageBottomWithSelectionAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretPageBottom(editor, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownAction.java
index 4fc4c85..1da22ea 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownAction.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.
@@ -31,6 +31,10 @@
public class PageDownAction extends EditorAction {
public static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretPageDown(editor, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownWithSelectionAction.java
index 0e78282..07b6b66 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageDownWithSelectionAction.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.
@@ -24,16 +24,34 @@
*/
package com.intellij.openapi.editor.actions;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import com.intellij.openapi.actionSystem.DataContext;
+import org.jetbrains.annotations.NotNull;
public class PageDownWithSelectionAction extends EditorAction {
public static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
- public void execute(Editor editor, DataContext dataContext) {
- EditorActionUtil.moveCaretPageDown(editor, true);
+ public void execute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets()) {
+ int lines = editor.getScrollingModel().getVisibleArea().height / editor.getLineHeight();
+ Caret currentCaret = caret;
+ for (int i = 0; i < lines; i++) {
+ currentCaret = currentCaret.clone(false);
+ if (currentCaret == null) {
+ break;
+ }
+ }
+ }
+ else {
+ EditorActionUtil.moveCaretPageDown(editor, true);
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopAction.java
index d86b68c..58846c6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretPageTop(editor, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopWithSelectionAction.java
index 9b7cc77..d24d4a8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageTopWithSelectionAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretPageTop(editor, true);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpAction.java
index 3a69510..a222681 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpAction.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.
@@ -31,6 +31,10 @@
public class PageUpAction extends EditorAction {
public static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretPageUp(editor, false);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpWithSelectionAction.java
index 5bb39c7..e5a6a08 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PageUpWithSelectionAction.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.
@@ -24,16 +24,34 @@
*/
package com.intellij.openapi.editor.actions;
+import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.actionSystem.DataContext;
+import org.jetbrains.annotations.NotNull;
public class PageUpWithSelectionAction extends EditorAction {
public static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
- public void execute(Editor editor, DataContext dataContext) {
- EditorActionUtil.moveCaretPageUp(editor, true);
+ public void execute(Editor editor, @NotNull Caret caret, DataContext dataContext) {
+ if (editor.isColumnMode() && editor.getCaretModel().supportsMultipleCarets()) {
+ int lines = editor.getScrollingModel().getVisibleArea().height / editor.getLineHeight();
+ Caret currentCaret = caret;
+ for (int i = 0; i < lines; i++) {
+ currentCaret = currentCaret.clone(true);
+ if (currentCaret == null) {
+ break;
+ }
+ }
+ }
+ else {
+ EditorActionUtil.moveCaretPageUp(editor, true);
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteAction.java
index a0d99d8..76a2ae6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteAction.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,30 +13,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: May 13, 2002
- * Time: 7:50:36 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.util.TextRange;
import com.intellij.util.Producer;
import java.awt.datatransfer.Transferable;
+/**
+ * @author max
+ * @since May 13, 2002
+ */
public class PasteAction extends EditorAction {
- public static final String TRANSFERABLE_PROVIDER = "PasteTransferableProvider";
-
+ public static final DataKey<Producer<Transferable>> TRANSFERABLE_PROVIDER = DataKey.create("PasteTransferableProvider");
+
public PasteAction() {
super(new Handler());
}
@@ -44,15 +41,13 @@
private static class Handler extends EditorWriteActionHandler {
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
- Producer<Transferable> producer = (Producer<Transferable>)dataContext.getData(TRANSFERABLE_PROVIDER);
-
- if (editor.isColumnMode() || editor.getSelectionModel().hasBlockSelection()) {
- EditorModificationUtil.pasteTransferableAsBlock(editor, producer == null ? null : producer.produce());
+ Producer<Transferable> producer = TRANSFERABLE_PROVIDER.getData(dataContext);
+ if (!editor.getCaretModel().supportsMultipleCarets() && (editor.isColumnMode() || editor.getSelectionModel().hasBlockSelection())) {
+ EditorModificationUtil.pasteTransferableAsBlock(editor, producer);
}
else {
- editor.putUserData(EditorEx.LAST_PASTED_REGION,
- producer == null ? EditorModificationUtil.pasteFromClipboard(editor) :
- EditorModificationUtil.pasteFromTransferrable(producer.produce(), editor));
+ TextRange range = EditorModificationUtil.pasteTransferable(editor, producer);
+ editor.putUserData(EditorEx.LAST_PASTED_REGION, range);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteFromX11Action.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteFromX11Action.java
index fcd7b97..3e20ba8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteFromX11Action.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PasteFromX11Action.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,18 +18,18 @@
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.actionSystem.Presentation;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.ex.EditorEx;
-import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.util.Producer;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -74,21 +74,27 @@
public static class Handler extends EditorWriteActionHandler {
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
- final Clipboard clip = editor.getComponent().getToolkit().getSystemSelection();
- if (clip != null) {
- Transferable res = null;
- try {
- res = clip.getContents(null);
- }
- catch (Exception e) {
- if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
- LOG.info(e);
- Messages.showErrorDialog(editor.getProject(), "Cannot paste from X11 clipboard: " + e.getLocalizedMessage(), "Cannot Paste");
- return;
- }
- }
- editor.putUserData(EditorEx.LAST_PASTED_REGION, EditorModificationUtil.pasteFromTransferrable(res, editor));
+ Clipboard clip = editor.getComponent().getToolkit().getSystemSelection();
+ if (clip == null) return;
+
+ final Transferable content;
+ try {
+ content = clip.getContents(null);
}
+ catch (Exception e) {
+ LOG.info(e);
+ return;
+ }
+ if (content == null) return;
+
+ TextRange range = EditorModificationUtil.pasteTransferable(editor, new Producer<Transferable>() {
+ @Nullable
+ @Override
+ public Transferable produce() {
+ return content;
+ }
+ });
+ editor.putUserData(EditorEx.LAST_PASTED_REGION, range);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordAction.java
index cf423d9..9c9e980 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordAction.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.
@@ -35,6 +35,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToPreviousWord(editor, false, editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeAction.java
index d5debd1..4b6960d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeAction.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,6 +30,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToPreviousWord(editor, false, !editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeWithSelectionAction.java
index c6b4f2e..fdfdc05 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordInDifferentHumpsModeWithSelectionAction.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,6 +30,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToPreviousWord(editor, true, !editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordWithSelectionAction.java
index c1e3817..c1c5b39 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/PreviousWordWithSelectionAction.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.
@@ -36,6 +36,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
EditorActionUtil.moveCaretToPreviousWord(editor, true, editor.getSettings().isCamelWords());
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SelectLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SelectLineAction.java
index a2af2f7..2398866 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SelectLineAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SelectLineAction.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,9 +34,14 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
editor.getSelectionModel().selectLineAtCaret();
+ EditorActionUtil.moveCaretToLineStartIgnoringSoftWraps(editor);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SimplePasteAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SimplePasteAction.java
index 40a9adb..59a6cbc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SimplePasteAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SimplePasteAction.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,29 +13,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * Created by IntelliJ IDEA.
- * User: max
- * Date: May 13, 2002
- * Time: 7:50:36 PM
- * To change template for new class use
- * Code Style | Class Templates options (Tools | IDE Options).
- */
package com.intellij.openapi.editor.actions;
import com.intellij.openapi.actionSystem.ActionPlaces;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.util.TextRange;
import com.intellij.util.Producer;
import java.awt.datatransfer.Transferable;
+/**
+ * @author max
+ * @since May 13, 2002
+ */
public class SimplePasteAction extends EditorAction {
public SimplePasteAction() {
super(new Handler());
@@ -45,23 +42,21 @@
public void update(AnActionEvent e) {
super.update(e);
if (ActionPlaces.isPopupPlace(e.getPlace())) {
- e.getPresentation().setVisible(e.getPresentation().isEnabled());
+ Presentation presentation = e.getPresentation();
+ presentation.setVisible(presentation.isEnabled());
}
}
private static class Handler extends EditorWriteActionHandler {
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
- Producer<Transferable> producer = (Producer<Transferable>) dataContext.getData(PasteAction.TRANSFERABLE_PROVIDER);
-
- if (editor.isColumnMode()) {
- EditorModificationUtil.pasteTransferableAsBlock(editor, producer == null ? null : producer.produce());
- } else {
- editor.putUserData(EditorEx.LAST_PASTED_REGION,
- producer == null ?
- EditorModificationUtil.pasteFromClipboard(editor)
- : EditorModificationUtil.pasteFromTransferrable(producer.produce(), editor));
-
+ Producer<Transferable> producer = PasteAction.TRANSFERABLE_PROVIDER.getData(dataContext);
+ if (!editor.getCaretModel().supportsMultipleCarets() && editor.isColumnMode()) {
+ EditorModificationUtil.pasteTransferableAsBlock(editor, producer);
+ }
+ else {
+ TextRange range = EditorModificationUtil.pasteTransferable(editor, producer);
+ editor.putUserData(EditorEx.LAST_PASTED_REGION, range);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java
index 4db22a8..7716a90 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SplitLineAction.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 com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.util.Key;
import com.intellij.util.text.CharArrayUtil;
@@ -42,6 +43,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, dataContext) &&
@@ -50,6 +55,7 @@
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
+ CopyPasteManager.getInstance().stopKillRings();
final Document document = editor.getDocument();
final RangeMarker rangeMarker =
document.createRangeMarker(editor.getCaretModel().getOffset(), editor.getCaretModel().getOffset() );
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java
index a16a2f4..0302e48 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineAction.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.
@@ -23,6 +23,7 @@
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
+import com.intellij.openapi.ide.CopyPasteManager;
/**
* @author max
@@ -33,6 +34,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getEnterHandler().isEnabled(editor, dataContext);
@@ -40,6 +45,7 @@
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
+ CopyPasteManager.getInstance().stopKillRings();
if (editor.getDocument().getLineCount() != 0) {
editor.getSelectionModel().removeSelection();
LogicalPosition caretPosition = editor.getCaretModel().getLogicalPosition();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java
index 115c8c9..fc2ae40 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/StartNewLineBeforeAction.java
@@ -1,7 +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.openapi.editor.actions;
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.LogicalPosition;
import com.intellij.openapi.editor.actionSystem.EditorAction;
@@ -21,21 +37,25 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public boolean isEnabled(Editor editor, DataContext dataContext) {
return getHandler(IdeActions.ACTION_EDITOR_ENTER).isEnabled(editor, dataContext);
}
@Override
- public void executeWriteAction(Editor editor, DataContext dataContext) {
+ public void executeWriteAction(Editor editor, Caret caret, DataContext dataContext) {
editor.getSelectionModel().removeSelection();
LogicalPosition caretPosition = editor.getCaretModel().getLogicalPosition();
final int line = caretPosition.line;
int lineStartOffset = editor.getDocument().getLineStartOffset(line);
editor.getCaretModel().moveToOffset(lineStartOffset);
- getHandler(IdeActions.ACTION_EDITOR_ENTER).execute(editor, dataContext);
+ getHandler(IdeActions.ACTION_EDITOR_ENTER).execute(editor, caret, dataContext);
editor.getCaretModel().moveToOffset(editor.getDocument().getLineStartOffset(line));
- getHandler(IdeActions.ACTION_EDITOR_MOVE_LINE_END).execute(editor, dataContext);
+ getHandler(IdeActions.ACTION_EDITOR_MOVE_LINE_END).execute(editor, caret, dataContext);
}
private static EditorActionHandler getHandler(@NotNull String actionId) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SwapSelectionBoundariesAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SwapSelectionBoundariesAction.java
index cde980e..d694178 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/SwapSelectionBoundariesAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/SwapSelectionBoundariesAction.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.
@@ -37,6 +37,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
if (!(editor instanceof EditorEx)) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java
index e0c9a52..9054e12 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TabAction.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.
@@ -48,6 +48,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.EDIT_COMMAND_GROUP);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java
index b71f376..4f76b92 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextComponentEditorAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.textarea.TextComponentEditor;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.text.JTextComponent;
@@ -30,18 +31,18 @@
* @author yole
*/
public abstract class TextComponentEditorAction extends EditorAction {
- protected TextComponentEditorAction(final EditorActionHandler defaultHandler) {
+ protected TextComponentEditorAction(@NotNull EditorActionHandler defaultHandler) {
super(defaultHandler);
}
@Override
@Nullable
- protected Editor getEditor(final DataContext dataContext) {
+ protected Editor getEditor(@NotNull final DataContext dataContext) {
return getEditorFromContext(dataContext);
}
@Nullable
- public static Editor getEditorFromContext(final DataContext dataContext) {
+ public static Editor getEditorFromContext(@NotNull DataContext dataContext) {
final Editor editor = CommonDataKeys.EDITOR.getData(dataContext);
if (editor != null) return editor;
final Object data = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndAction.java
index 4531af8..ae96512 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndAction.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.
@@ -36,6 +36,7 @@
private static class Handler extends EditorActionHandler {
@Override
public void execute(Editor editor, DataContext dataContext) {
+ editor.getCaretModel().removeSecondaryCarets();
int offset = editor.getDocument().getTextLength();
editor.getCaretModel().moveToOffset(offset);
editor.getSelectionModel().removeSelection();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndWithSelectionAction.java
index 4b23744..aa7e598 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextEndWithSelectionAction.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.
@@ -28,7 +28,6 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.ScrollingModel;
-import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
public class TextEndWithSelectionAction extends TextComponentEditorAction {
@@ -37,6 +36,10 @@
}
private static class Handler extends EditorActionHandler {
+ protected Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
int selectionStart = editor.getSelectionModel().getLeadSelectionOffset();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartAction.java
index d63ca3b..2fe51b3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartAction.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.
@@ -36,6 +36,7 @@
private static class Handler extends EditorActionHandler {
@Override
public void execute(Editor editor, DataContext dataContext) {
+ editor.getCaretModel().removeSecondaryCarets();
editor.getCaretModel().moveToOffset(0);
editor.getSelectionModel().removeSelection();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartWithSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartWithSelectionAction.java
index 4c44132..f5937fd 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartWithSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/TextStartWithSelectionAction.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.
@@ -28,7 +28,6 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.ScrollingModel;
-import com.intellij.openapi.editor.actionSystem.EditorAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
public class TextStartWithSelectionAction extends TextComponentEditorAction {
@@ -37,6 +36,10 @@
}
private static class Handler extends EditorActionHandler {
+ protected Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
int selectionStart = editor.getSelectionModel().getLeadSelectionOffset();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleCaseAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleCaseAction.java
index d147ab4..4253c2c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleCaseAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleCaseAction.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.
@@ -36,6 +36,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
final SelectionModel selectionModel = editor.getSelectionModel();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleColumnModeAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleColumnModeAction.java
index ff88189..64659ce 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleColumnModeAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/ToggleColumnModeAction.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,6 +38,10 @@
@Override
public void setSelected(AnActionEvent e, boolean state) {
final EditorEx editor = getEditor(e);
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ editor.setColumnMode(state);
+ return;
+ }
final SelectionModel selectionModel = editor.getSelectionModel();
if (state) {
boolean hasSelection = selectionModel.hasSelection();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnindentSelectionAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnindentSelectionAction.java
index 231c7e9..7a0ca1a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnindentSelectionAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnindentSelectionAction.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,6 @@
import com.intellij.codeStyle.CodeStyleFacade;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.actionSystem.EditorAction;
@@ -35,7 +34,6 @@
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -45,6 +43,10 @@
}
private static class Handler extends EditorWriteActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void executeWriteAction(Editor editor, DataContext dataContext) {
Project project = CommonDataKeys.PROJECT.getData(dataContext);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java
index ad9ce08..a1ae088 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/actions/UnselectWordAtCaretAction.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.
@@ -37,6 +37,10 @@
}
private static class Handler extends EditorActionHandler {
+ public Handler() {
+ super(true);
+ }
+
@Override
public void execute(Editor editor, DataContext dataContext) {
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
index d8dea9a..4d262dc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/colors/impl/EditorColorsManagerImpl.java
@@ -157,6 +157,7 @@
return loadSchemeFromDocument(document, false);
}
+ @NotNull
private static EditorColorsSchemeImpl loadSchemeFromDocument(final Document document,
final boolean isEditable)
throws InvalidDataException {
@@ -369,14 +370,14 @@
private final class MySchemeProcessor extends BaseSchemeProcessor<EditorColorsSchemeImpl> implements SchemeExtensionProvider {
@Override
- public EditorColorsSchemeImpl readScheme(final Document document)
+ public EditorColorsSchemeImpl readScheme(@NotNull final Document document)
throws InvalidDataException {
return loadSchemeFromDocument(document, true);
}
@Override
- public Document writeScheme(final EditorColorsSchemeImpl scheme) {
+ public Document writeScheme(@NotNull final EditorColorsSchemeImpl scheme) {
Element root = new Element(SCHEME_NODE_NAME);
try {
scheme.writeExternal(root);
@@ -394,7 +395,7 @@
}
@Override
- public boolean shouldBeSaved(final EditorColorsSchemeImpl scheme) {
+ public boolean shouldBeSaved(@NotNull final EditorColorsSchemeImpl scheme) {
return !(scheme instanceof ReadOnlyColorsScheme);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java
index ca884ef..1f2b60a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/FoldingModelEx.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,7 @@
*/
package com.intellij.openapi.editor.ex;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingGroup;
import com.intellij.openapi.editor.FoldingModel;
@@ -47,9 +48,9 @@
FoldRegion createFoldRegion(int startOffset, int endOffset, @NotNull String placeholder, @Nullable FoldingGroup group,
boolean neverExpands);
- boolean addListener(@NotNull FoldingListener listener);
+ void addListener(@NotNull FoldingListener listener, @NotNull Disposable parentDisposable);
- boolean removeListener(@NotNull FoldingListener listener);
+ void clearFoldRegions();
void rebuild();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java
index 4e8d60b..48d43bc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/SoftWrapModelEx.java
@@ -16,7 +16,6 @@
package com.intellij.openapi.editor.ex;
import com.intellij.openapi.editor.*;
-import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
import org.jetbrains.annotations.NotNull;
@@ -108,18 +107,6 @@
boolean addSoftWrapChangeListener(@NotNull SoftWrapChangeListener listener);
/**
- * Instructs current soft wrap model about the place where corresponding editor is used.
- * <p/>
- * {@link SoftWrapAppliancePlaces#MAIN_EDITOR} is used by default.
- *
- * @param place place where corresponding editor is used
- */
- void setPlace(@NotNull SoftWrapAppliancePlaces place);
-
- /** Asks the model to completely recalculate soft wraps. */
- void recalculate();
-
- /**
* IJ editor defines a notion of {@link EditorSettings#getAdditionalColumnsCount() additional columns}. They define additional
* amount of space to be used during editor component's width calculation (IJ editor perform 'preventive UI component expansion'
* when user types near the right edge).
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 4c09c61..c1f1b5a 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
@@ -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.
@@ -301,14 +301,14 @@
// text fragment.
boolean useOptimization = true;
boolean hasTabs;
- if ((editor instanceof EditorImpl) && !((EditorImpl)editor).hasTabs()) {
+ if (editor instanceof EditorImpl && !((EditorImpl)editor).hasTabs()) {
hasTabs = false;
useOptimization = true;
}
else {
- boolean hasNonTabs = false;
hasTabs = false;
int scanEndOffset = Math.min(end, start + columnNumber - currentColumn[0] + 1);
+ boolean hasNonTabs = false;
for (int i = start; i < scanEndOffset; i++) {
char c = text.charAt(i);
if (debugBuffer != null) {
@@ -463,7 +463,7 @@
}
boolean hasTabs = true;
if (useOptimization) {
- if ((editor instanceof EditorImpl) && !((EditorImpl)editor).hasTabs()) {
+ if (editor instanceof EditorImpl && !((EditorImpl)editor).hasTabs()) {
hasTabs = false;
}
else {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EmptyEditorHighlighter.java b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EmptyEditorHighlighter.java
index be49185..1374053 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EmptyEditorHighlighter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/ex/util/EmptyEditorHighlighter.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.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
public class EmptyEditorHighlighter implements EditorHighlighter, PrioritizedDocumentListener {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.ex.util.EmptyEditorHighlighter");
@@ -43,18 +44,18 @@
}
@Override
- public void setText(CharSequence text) {
+ public void setText(@NotNull CharSequence text) {
myTextLength = text.length();
}
@Override
- public void setEditor(HighlighterClient editor) {
+ public void setEditor(@NotNull HighlighterClient editor) {
LOG.assertTrue(myEditor == null, "Highlighters cannot be reused with different editors");
myEditor = editor;
}
@Override
- public void setColorScheme(EditorColorsScheme scheme) {
+ public void setColorScheme(@NotNull EditorColorsScheme scheme) {
setAttributes(scheme.getAttributes(HighlighterColors.TEXT));
}
@@ -71,6 +72,7 @@
return 2;
}
+ @NotNull
@Override
public HighlighterIterator createIterator(int startOffset) {
return new HighlighterIterator(){
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java
index b5b9e69..bbbd71f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ArrowPainter.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.
@@ -30,10 +30,19 @@
public class ArrowPainter {
private final ColorProvider myColorHolder;
+ private final Computable<Integer> myWidthProvider;
private final Computable<Integer> myHeightProvider;
- public ArrowPainter(@NotNull ColorProvider colorHolder, @NotNull Computable<Integer> heightProvider) {
+ /**
+ * Creates an ArrowPainter with specified parameters.
+ *
+ * @param colorHolder defines arrow color
+ * @param widthProvider defines character width, it is used to calculate an inset for the arrow's tip
+ * @param heightProvider defines character height, it's used to calculate an arrow's width and height
+ */
+ public ArrowPainter(@NotNull ColorProvider colorHolder, @NotNull Computable<Integer> widthProvider, @NotNull Computable<Integer> heightProvider) {
myColorHolder = colorHolder;
+ myWidthProvider = widthProvider;
myHeightProvider = heightProvider;
}
@@ -46,7 +55,7 @@
* @param stop ending <code>'x'</code> position to use during drawing
*/
public void paint(Graphics g, int y, int start, int stop) {
- stop -= g.getFontMetrics().charWidth(' ') / 2;
+ stop -= myWidthProvider.compute() / 4;
Color oldColor = g.getColor();
g.setColor(myColorHolder.getColor());
final int height = myHeightProvider.compute();
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
new file mode 100644
index 0000000..1b79d35
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/CaretImpl.java
@@ -0,0 +1,1447 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diagnostic.LogMessageEx;
+import com.intellij.openapi.actionSystem.IdeActions;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.*;
+import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
+import com.intellij.openapi.editor.actionSystem.EditorActionManager;
+import com.intellij.openapi.editor.actions.EditorActionUtil;
+import com.intellij.openapi.editor.event.CaretEvent;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.editor.ex.DocumentEx;
+import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
+import com.intellij.openapi.editor.ex.FoldingModelEx;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
+import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
+import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.diff.FilesTooBigForDiffException;
+import com.intellij.util.text.CharArrayUtil;
+import com.intellij.util.ui.EmptyClipboardOwner;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+
+public class CaretImpl extends UserDataHolderBase implements Caret {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.CaretImpl");
+
+ private final EditorImpl myEditor;
+ private boolean isValid = true;
+
+ private LogicalPosition myLogicalCaret;
+ private VerticalInfo myCaretInfo;
+ private VisualPosition myVisibleCaret;
+ private int myOffset;
+ private int myVirtualSpaceOffset;
+ private int myVisualLineStart;
+ private int myVisualLineEnd;
+ private RangeMarker savedBeforeBulkCaretMarker;
+ private boolean mySkipChangeRequests;
+ private int myLastColumnNumber = 0;
+ /**
+ * We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However,
+ * it's possible that the following situation occurs:
+ * <p/>
+ * <pre>
+ * <ol>
+ * <li>Some client subscribes to caret change events;</li>
+ * <li>{@link #moveToLogicalPosition(LogicalPosition)} is called;</li>
+ * <li>Caret position is changed during {@link #moveToLogicalPosition(LogicalPosition)} processing;</li>
+ * <li>The client receives caret position change event and adjusts the position;</li>
+ * <li>{@link #moveToLogicalPosition(LogicalPosition)} processing is finished;</li>
+ * <li>{@link #moveToLogicalPosition(LogicalPosition)} reports an error because the caret is not located at the target offset;</li>
+ * </ol>
+ * </pre>
+ * <p/>
+ * This field serves as a flag that reports unexpected caret position change requests nested from {@link #moveToOffset(int, boolean)}.
+ */
+ private boolean myReportCaretMoves;
+ /**
+ * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different
+ * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve
+ * its initial visual position when possible.
+ * <p/>
+ * This field holds desired value for visual <code>'x'</code> caret coordinate (negative value if no coordinate should be preserved).
+ */
+ private int myDesiredX = -1;
+
+ private volatile MyRangeMarker mySelectionMarker;
+ private int startBefore;
+ private int endBefore;
+ boolean myUnknownDirection;
+
+ CaretImpl(EditorImpl editor) {
+ myEditor = editor;
+
+ myLogicalCaret = new LogicalPosition(0, 0);
+ myVisibleCaret = new VisualPosition(0, 0);
+ myCaretInfo = new VerticalInfo(0, 0);
+ myOffset = 0;
+ myVisualLineStart = 0;
+ Document doc = myEditor.getDocument();
+ myVisualLineEnd = doc.getLineCount() > 1 ? doc.getLineStartOffset(1) : doc.getLineCount() == 0 ? 0 : doc.getLineEndOffset(0);
+ }
+
+ void onBulkDocumentUpdateStarted(@NotNull Document doc) {
+ if (doc != myEditor.getDocument() || myOffset > doc.getTextLength() || savedBeforeBulkCaretMarker != null) return;
+ savedBeforeBulkCaretMarker = doc.createRangeMarker(myOffset, myOffset);
+ }
+
+ void onBulkDocumentUpdateFinished(@NotNull Document doc) {
+ if (doc != myEditor.getDocument() || myEditor.getCaretModel().myIsInUpdate) return;
+ LOG.assertTrue(!myReportCaretMoves);
+
+ if (savedBeforeBulkCaretMarker != null) {
+ if(savedBeforeBulkCaretMarker.isValid()) {
+ if(savedBeforeBulkCaretMarker.getStartOffset() != myOffset) {
+ moveToOffset(savedBeforeBulkCaretMarker.getStartOffset());
+ }
+ } else if (myOffset > doc.getTextLength()) {
+ moveToOffset(doc.getTextLength());
+ }
+ releaseBulkCaretMarker();
+ }
+ }
+
+ public void beforeDocumentChange() {
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null && marker.isValid()) {
+ startBefore = marker.getStartOffset();
+ endBefore = marker.getEndOffset();
+ }
+ }
+
+ public void documentChanged() {
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null) {
+ int endAfter;
+ int startAfter;
+ if (marker.isValid()) {
+ startAfter = marker.getStartOffset();
+ endAfter = marker.getEndOffset();
+ }
+ else {
+ startAfter = endAfter = getOffset();
+ marker.release();
+ mySelectionMarker = null;
+ }
+
+ if (startBefore != startAfter || endBefore != endAfter) {
+ myEditor.getSelectionModel().fireSelectionChanged(startBefore, endBefore, startAfter, endAfter);
+ }
+ }
+ }
+
+ @Override
+ public void moveToOffset(int offset) {
+ moveToOffset(offset, false);
+ }
+
+ @Override
+ public void moveToOffset(final int offset, final boolean locateBeforeSoftWrap) {
+ assertIsDispatchThread();
+ validateCallContext();
+ if (mySkipChangeRequests) {
+ return;
+ }
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ final LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(offset);
+ CaretEvent event = moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, null, false);
+ final LogicalPosition positionByOffsetAfterMove = myEditor.offsetToLogicalPosition(myOffset);
+ if (!myEditor.getCaretModel().myIgnoreWrongMoves && !positionByOffsetAfterMove.equals(logicalPosition)) {
+ StringBuilder debugBuffer = new StringBuilder();
+ moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, debugBuffer, true);
+ int textStart = Math.max(0, Math.min(offset, myOffset) - 1);
+ final DocumentEx document = myEditor.getDocument();
+ int textEnd = Math.min(document.getTextLength() - 1, Math.max(offset, myOffset) + 1);
+ CharSequence text = document.getCharsSequence().subSequence(textStart, textEnd);
+ StringBuilder positionToOffsetTrace = new StringBuilder();
+ int inverseOffset = myEditor.logicalPositionToOffset(logicalPosition, positionToOffsetTrace);
+ LogMessageEx.error(
+ LOG, "caret moved to wrong offset. Please submit a dedicated ticket and attach current editor's text to it.",
+ String.format(
+ "Requested: offset=%d, logical position='%s' but actual: offset=%d, logical position='%s' (%s). %s%n"
+ + "interested text [%d;%d): '%s'%n debug trace: %s%nLogical position -> offset ('%s'->'%d') trace: %s",
+ offset, logicalPosition, myOffset, myLogicalCaret, positionByOffsetAfterMove, myEditor.dumpState(),
+ textStart, textEnd, text, debugBuffer, logicalPosition, inverseOffset, positionToOffsetTrace
+ )
+ );
+ }
+ if (event != null) {
+ myEditor.getCaretModel().fireCaretPositionChanged(event);
+ EditorActionUtil.selectNonexpandableFold(myEditor);
+ }
+ }
+ });
+ }
+
+ @NotNull
+ @Override
+ public CaretModel getCaretModel() {
+ return myEditor.getCaretModel();
+ }
+
+ @Override
+ public boolean isValid() {
+ return isValid;
+ }
+
+ @Override
+ public void moveCaretRelatively(int columnShift, int lineShift, boolean withSelection, boolean scrollToCaret) {
+ moveCaretRelatively(columnShift, lineShift, withSelection, false, scrollToCaret);
+ }
+
+ void moveCaretRelatively(final int columnShift,
+ final int lineShift,
+ final boolean withSelection,
+ final boolean blockSelection,
+ final boolean scrollToCaret) {
+ assertIsDispatchThread();
+ if (mySkipChangeRequests) {
+ return;
+ }
+ if (myReportCaretMoves) {
+ LogMessageEx.error(LOG, "Unexpected caret move request");
+ }
+ if (!myEditor.isStickySelection() && !myEditor.getCaretModel().isDocumentChanged) {
+ CopyPasteManager.getInstance().stopKillRings();
+ }
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ SelectionModelImpl selectionModel = myEditor.getSelectionModel();
+ final int leadSelectionOffset = selectionModel.getLeadSelectionOffset();
+ LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
+ ? selectionModel.getBlockStart()
+ : getLogicalPosition();
+ EditorSettings editorSettings = myEditor.getSettings();
+ VisualPosition visualCaret = getVisualPosition();
+
+ int desiredX = myDesiredX;
+ if (columnShift == 0) {
+ if (myDesiredX < 0) {
+ desiredX = myEditor.visualPositionToXY(visualCaret).x;
+ }
+ }
+ else {
+ myDesiredX = desiredX = -1;
+ }
+
+ int newLineNumber = visualCaret.line + lineShift;
+ int newColumnNumber = visualCaret.column + columnShift;
+ if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
+ newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
+ }
+
+ Document document = myEditor.getDocument();
+ if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
+ newColumnNumber = myEditor.getCaretModel().supportsMultipleCarets() ? myLastColumnNumber : myEditor.getLastColumnNumber();
+ }
+ else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
+ int lastLine = document.getLineCount() - 1;
+ if (lastLine < 0) lastLine = 0;
+ if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 &&
+ newLineNumber < myEditor.logicalToVisualPosition(new LogicalPosition(lastLine, 0)).line) {
+ newColumnNumber = 0;
+ newLineNumber++;
+ }
+ }
+ else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == -1) {
+ if (newColumnNumber < 0 && newLineNumber > 0) {
+ newLineNumber--;
+ newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
+ }
+ }
+
+ if (newColumnNumber < 0) newColumnNumber = 0;
+
+ // There is a possible case that caret is located at the first line and user presses 'Shift+Up'. We want to select all text
+ // from the document start to the current caret position then. So, we have a dedicated flag for tracking that.
+ boolean selectToDocumentStart = false;
+ if (newLineNumber < 0) {
+ selectToDocumentStart = true;
+ newLineNumber = 0;
+
+ // We want to move caret to the first column if it's already located at the first line and 'Up' is pressed.
+ newColumnNumber = 0;
+ desiredX = -1;
+ }
+
+ VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
+ int lastColumnNumber = newColumnNumber;
+ if (!editorSettings.isCaretInsideTabs() && !myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
+ LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
+ int offset = myEditor.logicalPositionToOffset(log);
+ if (offset >= document.getTextLength()) {
+ int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
+ // We want to move caret to the last column if if it's located at the last line and 'Down' is pressed.
+ newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
+ desiredX = -1;
+ }
+ CharSequence text = document.getCharsSequence();
+ if (offset >= 0 && offset < document.getTextLength()) {
+ if (text.charAt(offset) == '\t' && (columnShift <= 0 || offset == myOffset)) {
+ if (columnShift <= 0) {
+ newColumnNumber = myEditor.offsetToVisualPosition(offset).column;
+ }
+ else {
+ SoftWrap softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset + 1);
+ // There is a possible case that tabulation symbol is the last document symbol represented on a visual line before
+ // soft wrap. We can't just use column from 'offset + 1' because it would point on a next visual line.
+ if (softWrap == null) {
+ newColumnNumber = myEditor.offsetToVisualPosition(offset + 1).column;
+ }
+ else {
+ newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
+ }
+ }
+ }
+ }
+ }
+
+ pos = new VisualPosition(newLineNumber, newColumnNumber);
+ if (columnShift != 0 && lineShift == 0 && myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
+ LogicalPosition logical = myEditor.visualToLogicalPosition(pos);
+ int softWrapOffset = myEditor.logicalPositionToOffset(logical);
+ if (columnShift >= 0) {
+ moveToOffset(softWrapOffset);
+ }
+ else {
+ int line = myEditor.offsetToVisualLine(softWrapOffset - 1);
+ moveToVisualPosition(new VisualPosition(line, EditorUtil.getLastVisualLineColumnNumber(myEditor, line)));
+ }
+ }
+ else {
+ moveToVisualPosition(pos);
+ if (!editorSettings.isVirtualSpace() && columnShift == 0) {
+ setLastColumnNumber(lastColumnNumber);
+ }
+ }
+
+ if (withSelection) {
+ if (blockSelection && !myEditor.getCaretModel().supportsMultipleCarets()) {
+ selectionModel.setBlockSelection(blockSelectionStart, getLogicalPosition());
+ }
+ else {
+ if (selectToDocumentStart) {
+ selectionModel.setSelection(leadSelectionOffset, 0);
+ }
+ else if (pos.line >= myEditor.getVisibleLineCount()) {
+ if (leadSelectionOffset < document.getTextLength()) {
+ selectionModel.setSelection(leadSelectionOffset, document.getTextLength());
+ }
+ }
+ else {
+ int selectionStartToUse = leadSelectionOffset;
+ if (selectionModel.isUnknownDirection()) {
+ if (getOffset() > leadSelectionOffset) {
+ selectionStartToUse = Math.min(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+ }
+ else {
+ selectionStartToUse = Math.max(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
+ }
+ }
+ selectionModel.setSelection(selectionStartToUse, getVisualPosition(), getOffset());
+ }
+ }
+ }
+ else {
+ removeSelection();
+ }
+
+ if (scrollToCaret) {
+ myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ }
+
+ if (desiredX >= 0) {
+ myDesiredX = desiredX;
+ }
+
+ EditorActionUtil.selectNonexpandableFold(myEditor);
+ }
+ });
+ }
+
+ @Override
+ public void moveToLogicalPosition(@NotNull final LogicalPosition pos) {
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ moveToLogicalPosition(pos, false, null, true);
+ }
+ });
+ }
+
+
+ private CaretEvent doMoveToLogicalPosition(@NotNull LogicalPosition pos,
+ boolean locateBeforeSoftWrap,
+ @NonNls @Nullable StringBuilder debugBuffer,
+ boolean fireListeners) {
+ assertIsDispatchThread();
+ if (debugBuffer != null) {
+ debugBuffer.append("Start moveToLogicalPosition(). Locate before soft wrap: " + locateBeforeSoftWrap + ", position: " + pos + "\n");
+ }
+ myDesiredX = -1;
+ validateCallContext();
+ int column = pos.column;
+ int line = pos.line;
+ int softWrapLinesBefore = pos.softWrapLinesBeforeCurrentLogicalLine;
+ int softWrapLinesCurrent = pos.softWrapLinesOnCurrentLogicalLine;
+ int softWrapColumns = pos.softWrapColumnDiff;
+
+ Document doc = myEditor.getDocument();
+
+ if (column < 0) {
+ if (debugBuffer != null) {
+ debugBuffer.append("Resetting target logical column to zero as it is negative (").append(column).append(")\n");
+ }
+ column = 0;
+ softWrapColumns = 0;
+ }
+ if (line < 0) {
+ if (debugBuffer != null) {
+ debugBuffer.append("Resetting target logical line to zero as it is negative (").append(line).append(")\n");
+ }
+ line = 0;
+ softWrapLinesBefore = 0;
+ softWrapLinesCurrent = 0;
+ }
+
+ int lineCount = doc.getLineCount();
+ if (lineCount == 0) {
+ if (debugBuffer != null) {
+ debugBuffer.append("Resetting target logical line to zero as the document is empty\n");
+ }
+ line = 0;
+ }
+ else if (line > lineCount - 1) {
+ if (debugBuffer != null) {
+ debugBuffer.append("Resetting target logical line (" + line + ") to " + (lineCount - 1) + " as it is greater than total document lines number\n");
+ }
+ line = lineCount - 1;
+ softWrapLinesBefore = 0;
+ softWrapLinesCurrent = 0;
+ }
+
+ EditorSettings editorSettings = myEditor.getSettings();
+
+ if (!editorSettings.isVirtualSpace() && line < lineCount && !myEditor.getSelectionModel().hasBlockSelection()) {
+ int lineEndOffset = doc.getLineEndOffset(line);
+ final LogicalPosition endLinePosition = myEditor.offsetToLogicalPosition(lineEndOffset);
+ int lineEndColumnNumber = endLinePosition.column;
+ if (column > lineEndColumnNumber) {
+ int oldColumn = column;
+ column = lineEndColumnNumber;
+ if (softWrapColumns != 0) {
+ softWrapColumns -= column - lineEndColumnNumber;
+ }
+ if (debugBuffer != null) {
+ debugBuffer.append(
+ "Resetting target logical column (" + oldColumn + ") to " + lineEndColumnNumber +
+ " because caret is not allowed to be located after line end (offset: " +lineEndOffset + ", "
+ + "logical position: " + endLinePosition+ "). Current soft wrap columns value: " + softWrapColumns+ "\n");
+ }
+ }
+ }
+
+ myEditor.getFoldingModel().flushCaretPosition();
+
+ VerticalInfo oldInfo = myCaretInfo;
+ LogicalPosition oldCaretPosition = myLogicalCaret;
+
+ LogicalPosition logicalPositionToUse;
+ if (pos.visualPositionAware) {
+ logicalPositionToUse = new LogicalPosition(
+ line, column, softWrapLinesBefore, softWrapLinesCurrent, softWrapColumns, pos.foldedLines, pos.foldingColumnDiff
+ );
+ }
+ else {
+ logicalPositionToUse = new LogicalPosition(line, column);
+ }
+ setCurrentLogicalCaret(logicalPositionToUse);
+ final int offset = myEditor.logicalPositionToOffset(myLogicalCaret);
+ if (debugBuffer != null) {
+ debugBuffer.append("Resulting logical position to use: " + myLogicalCaret+
+ ". It's mapped to offset " + offset+ "\n");
+ }
+
+ FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset);
+
+ if (collapsedAt != null && offset > collapsedAt.getStartOffset()) {
+ if (debugBuffer != null) {
+ debugBuffer.append("Scheduling expansion of fold region ").append(collapsedAt).append("\n");
+ }
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ FoldRegion[] allCollapsedAt = myEditor.getFoldingModel().fetchCollapsedAt(offset);
+ for (FoldRegion foldRange : allCollapsedAt) {
+ foldRange.setExpanded(true);
+ }
+ }
+ };
+
+ mySkipChangeRequests = true;
+ try {
+ myEditor.getFoldingModel().runBatchFoldingOperation(runnable, false);
+ }
+ finally {
+ mySkipChangeRequests = false;
+ }
+ }
+
+ setLastColumnNumber(myLogicalCaret.column);
+ myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
+
+ updateOffsetsFromLogicalPosition();
+ if (debugBuffer != null) {
+ debugBuffer.append("Storing offset " + myOffset + " (mapped from logical position " + myLogicalCaret + ")\n");
+ }
+ LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());
+
+ updateVisualLineInfo();
+
+ myEditor.updateCaretCursor();
+ requestRepaint(oldInfo);
+
+ if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) {
+ int lineToUse = myVisibleCaret.line - 1;
+ if (lineToUse >= 0) {
+ final VisualPosition visualPosition = new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse));
+ if (debugBuffer != null) {
+ debugBuffer.append("Adjusting caret position by moving it before soft wrap. Moving to visual position "+ visualPosition+"\n");
+ }
+ final LogicalPosition logicalPosition = myEditor.visualToLogicalPosition(visualPosition);
+ final int tmpOffset = myEditor.logicalPositionToOffset(logicalPosition);
+ if (tmpOffset == myOffset) {
+ boolean restore = myReportCaretMoves;
+ myReportCaretMoves = false;
+ try {
+ moveToVisualPosition(visualPosition);
+ return null;
+ }
+ finally {
+ myReportCaretMoves = restore;
+ }
+ }
+ else {
+ LogMessageEx.error(LOG, "Invalid editor dimension mapping", String.format(
+ "Expected to map visual position '%s' to offset %d but got the following: -> logical position '%s'; -> offset %d. "
+ + "State: %s", visualPosition, myOffset, logicalPosition, tmpOffset, myEditor.dumpState()
+ ));
+ }
+ }
+ }
+
+ if (!oldCaretPosition.toVisualPosition().equals(myLogicalCaret.toVisualPosition())) {
+ CaretEvent event = new CaretEvent(myEditor, myEditor.getCaretModel().supportsMultipleCarets() ? this : null, oldCaretPosition, myLogicalCaret);
+ if (fireListeners) {
+ myEditor.getCaretModel().fireCaretPositionChanged(event);
+ }
+ else {
+ return event;
+ }
+ }
+ return null;
+ }
+
+ private void updateOffsetsFromLogicalPosition() {
+ myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
+ myVirtualSpaceOffset = myLogicalCaret.column - myEditor.offsetToLogicalPosition(myOffset).column;
+ }
+
+ private void setLastColumnNumber(int lastColumnNumber) {
+ myLastColumnNumber = lastColumnNumber;
+ myEditor.setLastColumnNumber(lastColumnNumber);
+ }
+
+ private void requestRepaint(VerticalInfo oldCaretInfo) {
+ int lineHeight = myEditor.getLineHeight();
+ Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea();
+ final EditorGutterComponentEx gutter = myEditor.getGutterComponentEx();
+ final EditorComponentImpl content = myEditor.getContentComponent();
+
+ int updateWidth = myEditor.getScrollPane().getHorizontalScrollBar().getValue() + visibleArea.width;
+ if (Math.abs(myCaretInfo.y - oldCaretInfo.y) <= 2 * lineHeight) {
+ int minY = Math.min(oldCaretInfo.y, myCaretInfo.y);
+ int maxY = Math.max(oldCaretInfo.y + oldCaretInfo.height, myCaretInfo.y + myCaretInfo.height);
+ content.repaintEditorComponent(0, minY, updateWidth, maxY - minY);
+ gutter.repaint(0, minY, gutter.getWidth(), maxY - minY);
+ }
+ else {
+ content.repaintEditorComponent(0, oldCaretInfo.y, updateWidth, oldCaretInfo.height + lineHeight);
+ gutter.repaint(0, oldCaretInfo.y, updateWidth, oldCaretInfo.height + lineHeight);
+ content.repaintEditorComponent(0, myCaretInfo.y, updateWidth, myCaretInfo.height + lineHeight);
+ gutter.repaint(0, myCaretInfo.y, updateWidth, myCaretInfo.height + lineHeight);
+ }
+ }
+
+ @Override
+ public void moveToVisualPosition(@NotNull final VisualPosition pos) {
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ moveToVisualPosition(pos, true);
+ }
+ });
+ }
+
+ void moveToVisualPosition(@NotNull VisualPosition pos, boolean fireListeners) {
+ assertIsDispatchThread();
+ validateCallContext();
+ if (mySkipChangeRequests) {
+ return;
+ }
+ if (myReportCaretMoves) {
+ LogMessageEx.error(LOG, "Unexpected caret move request");
+ }
+ if (!myEditor.isStickySelection() && !myEditor.getCaretModel().isDocumentChanged && !pos.equals(myVisibleCaret)) {
+ CopyPasteManager.getInstance().stopKillRings();
+ }
+
+ myDesiredX = -1;
+ int column = pos.column;
+ int line = pos.line;
+
+ if (column < 0) column = 0;
+
+ if (line < 0) line = 0;
+
+ int lastLine = myEditor.getVisibleLineCount() - 1;
+ if (lastLine <= 0) {
+ lastLine = 0;
+ }
+
+ if (line > lastLine) {
+ line = lastLine;
+ }
+
+ EditorSettings editorSettings = myEditor.getSettings();
+
+ if (!editorSettings.isVirtualSpace() && line <= lastLine) {
+ int lineEndColumn = EditorUtil.getLastVisualLineColumnNumber(myEditor, line);
+ if (column > lineEndColumn) {
+ column = lineEndColumn;
+ }
+
+ if (column < 0 && line > 0) {
+ line--;
+ column = EditorUtil.getLastVisualLineColumnNumber(myEditor, line);
+ }
+ }
+
+ myVisibleCaret = new VisualPosition(line, column);
+
+ VerticalInfo oldInfo = myCaretInfo;
+ LogicalPosition oldPosition = myLogicalCaret;
+
+ setCurrentLogicalCaret(myEditor.visualToLogicalPosition(myVisibleCaret));
+ updateOffsetsFromLogicalPosition();
+ LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());
+
+ updateVisualLineInfo();
+
+ myEditor.getFoldingModel().flushCaretPosition();
+
+ setLastColumnNumber(column);
+ myEditor.updateCaretCursor();
+ requestRepaint(oldInfo);
+
+ if (fireListeners && !oldPosition.equals(myLogicalCaret)) {
+ CaretEvent event = new CaretEvent(myEditor, myEditor.getCaretModel().supportsMultipleCarets() ? this : null, oldPosition, myLogicalCaret);
+ myEditor.getCaretModel().fireCaretPositionChanged(event);
+ }
+ }
+
+ @Nullable
+ CaretEvent moveToLogicalPosition(@NotNull LogicalPosition pos,
+ boolean locateBeforeSoftWrap,
+ @Nullable StringBuilder debugBuffer,
+ boolean fireListeners) {
+ if (mySkipChangeRequests) {
+ return null;
+ }
+ if (myReportCaretMoves) {
+ LogMessageEx.error(LOG, "Unexpected caret move request");
+ }
+ if (!myEditor.isStickySelection() && !myEditor.getCaretModel().isDocumentChanged && !pos.equals(myLogicalCaret)) {
+ CopyPasteManager.getInstance().stopKillRings();
+ }
+
+ myReportCaretMoves = true;
+ try {
+ return doMoveToLogicalPosition(pos, locateBeforeSoftWrap, debugBuffer, fireListeners);
+ }
+ finally {
+ myReportCaretMoves = false;
+ }
+ }
+
+ private void assertIsDispatchThread() {
+ myEditor.assertIsDispatchThread();
+ }
+
+ private void validateCallContext() {
+ LOG.assertTrue(!myEditor.getCaretModel().myIsInUpdate, "Caret model is in its update process. All requests are illegal at this point.");
+ }
+
+ private void releaseBulkCaretMarker() {
+ if (savedBeforeBulkCaretMarker != null) {
+ savedBeforeBulkCaretMarker.dispose();
+ savedBeforeBulkCaretMarker = null;
+ }
+ }
+
+ @Override
+ public void dispose() {
+ if (mySelectionMarker != null) {
+ mySelectionMarker.release();
+ mySelectionMarker = null;
+ }
+ releaseBulkCaretMarker();
+ isValid = false;
+ }
+
+ @Override
+ public boolean isUpToDate() {
+ return !myEditor.getCaretModel().myIsInUpdate && !myReportCaretMoves;
+ }
+
+ @NotNull
+ @Override
+ public LogicalPosition getLogicalPosition() {
+ validateCallContext();
+ return myLogicalCaret;
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getVisualPosition() {
+ validateCallContext();
+ return myVisibleCaret;
+ }
+
+ @Override
+ public int getOffset() {
+ validateCallContext();
+ return myOffset;
+ }
+
+ @Override
+ public int getVisualLineStart() {
+ return myVisualLineStart;
+ }
+
+ @Override
+ public int getVisualLineEnd() {
+ return myVisualLineEnd;
+ }
+
+ @NotNull
+ private VerticalInfo createVerticalInfo(LogicalPosition position) {
+ Document document = myEditor.getDocument();
+ int logicalLine = position.line;
+ if (logicalLine >= document.getLineCount()) {
+ logicalLine = Math.max(0, document.getLineCount() - 1);
+ }
+ int startOffset = document.getLineStartOffset(logicalLine);
+ int endOffset = document.getLineEndOffset(logicalLine);
+
+ // There is a possible case that active logical line is represented on multiple lines due to soft wraps processing.
+ // We want to highlight those visual lines as 'active' then, so, we calculate 'y' position for the logical line start
+ // and height in accordance with the number of occupied visual lines.
+ VisualPosition visualPosition = myEditor.offsetToVisualPosition(document.getLineStartOffset(logicalLine));
+ int y = myEditor.visualPositionToXY(visualPosition).y;
+ int lineHeight = myEditor.getLineHeight();
+ int height = lineHeight;
+ java.util.List<? extends SoftWrap> softWraps = myEditor.getSoftWrapModel().getSoftWrapsForRange(startOffset, endOffset);
+ for (SoftWrap softWrap : softWraps) {
+ height += StringUtil.countNewLines(softWrap.getText()) * lineHeight;
+ }
+
+ return new VerticalInfo(y, height);
+ }
+
+ /**
+ * Recalculates caret visual position without changing its logical position (called when soft wraps are changing)
+ */
+ public void updateVisualPosition() {
+ VerticalInfo oldInfo = myCaretInfo;
+ LogicalPosition visUnawarePos = new LogicalPosition(myLogicalCaret.line, myLogicalCaret.column);
+ setCurrentLogicalCaret(visUnawarePos);
+ myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
+ updateVisualLineInfo();
+
+ myEditor.updateCaretCursor();
+ requestRepaint(oldInfo);
+ }
+
+ private void updateVisualLineInfo() {
+ myVisualLineStart = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
+ myVisualLineEnd = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));
+ }
+
+ void updateCaretPosition(@NotNull final DocumentEventImpl event) {
+ final DocumentEx document = myEditor.getDocument();
+ boolean performSoftWrapAdjustment = event.getNewLength() > 0 // We want to put caret just after the last added symbol
+ // There is a possible case that the user removes text just before the soft wrap. We want to keep caret
+ // on a visual line with soft wrap start then.
+ || myEditor.getSoftWrapModel().getSoftWrap(event.getOffset()) != null;
+
+ if (event.isWholeTextReplaced()) {
+ int newLength = document.getTextLength();
+ if (myOffset == newLength - event.getNewLength() + event.getOldLength() || newLength == 0) {
+ moveToOffset(newLength, performSoftWrapAdjustment);
+ }
+ else {
+ try {
+ final int line = event.translateLineViaDiff(myLogicalCaret.line);
+ moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment, null, true);
+ }
+ catch (FilesTooBigForDiffException e1) {
+ LOG.info(e1);
+ moveToOffset(0);
+ }
+ }
+ }
+ else {
+ if (document.isInBulkUpdate()) return;
+ int startOffset = event.getOffset();
+ int oldEndOffset = startOffset + event.getOldLength();
+
+ int newOffset = myOffset;
+
+ if (myOffset > oldEndOffset || myOffset == oldEndOffset && needToShiftWhiteSpaces(event)) {
+ newOffset += event.getNewLength() - event.getOldLength();
+ }
+ else if (myOffset >= startOffset && myOffset <= oldEndOffset) {
+ newOffset = Math.min(newOffset, startOffset + event.getNewLength());
+ }
+
+ newOffset = Math.min(newOffset, document.getTextLength());
+
+ if (myEditor.getCaretModel().supportsMultipleCarets() && myOffset != startOffset) {
+ LogicalPosition pos = myEditor.offsetToLogicalPosition(newOffset);
+ moveToLogicalPosition(new LogicalPosition(pos.line, pos.column + myVirtualSpaceOffset), // retain caret in the virtual space
+ performSoftWrapAdjustment, null, true);
+ }
+ else {
+ moveToOffset(newOffset, performSoftWrapAdjustment);
+ }
+ }
+
+ updateVisualLineInfo();
+ }
+
+ private boolean needToShiftWhiteSpaces(final DocumentEvent e) {
+ if (!CharArrayUtil.containsOnlyWhiteSpaces(e.getNewFragment()) || CharArrayUtil.containLineBreaks(e.getNewFragment()))
+ return e.getOldLength() > 0;
+ if (e.getOffset() == 0) return false;
+ final char charBefore = myEditor.getDocument().getCharsSequence().charAt(e.getOffset() - 1);
+ //final char charAfter = myEditor.getDocument().getCharsSequence().charAt(e.getOffset() + e.getNewLength());
+ return Character.isWhitespace(charBefore)/* || !Character.isWhitespace(charAfter)*/;
+ }
+
+ private void setCurrentLogicalCaret(@NotNull LogicalPosition position) {
+ myLogicalCaret = position;
+ myCaretInfo = createVerticalInfo(position);
+ }
+
+ int getWordAtCaretStart() {
+ Document document = myEditor.getDocument();
+ int offset = getOffset();
+ if (offset == 0) return 0;
+ int lineNumber = getLogicalPosition().line;
+ CharSequence text = document.getCharsSequence();
+ int newOffset = offset - 1;
+ int minOffset = lineNumber > 0 ? document.getLineEndOffset(lineNumber - 1) : 0;
+ boolean camel = myEditor.getSettings().isCamelWords();
+ for (; newOffset > minOffset; newOffset--) {
+ if (EditorActionUtil.isWordStart(text, newOffset, camel)) break;
+ }
+
+ return newOffset;
+ }
+
+ int getWordAtCaretEnd() {
+ Document document = myEditor.getDocument();
+ int offset = getOffset();
+
+ CharSequence text = document.getCharsSequence();
+ if (offset >= document.getTextLength() - 1 || document.getLineCount() == 0) return offset;
+
+ int newOffset = offset + 1;
+
+ int lineNumber = getLogicalPosition().line;
+ int maxOffset = document.getLineEndOffset(lineNumber);
+ if (newOffset > maxOffset) {
+ if (lineNumber + 1 >= document.getLineCount()) return offset;
+ maxOffset = document.getLineEndOffset(lineNumber + 1);
+ }
+ boolean camel = myEditor.getSettings().isCamelWords();
+ for (; newOffset < maxOffset; newOffset++) {
+ if (EditorActionUtil.isWordEnd(text, newOffset, camel)) break;
+ }
+
+ return newOffset;
+ }
+
+ CaretImpl cloneWithoutSelection() {
+ CaretImpl clone = new CaretImpl(myEditor);
+ clone.myLogicalCaret = this.myLogicalCaret;
+ clone.myCaretInfo = this.myCaretInfo;
+ clone.myVisibleCaret = this.myVisibleCaret;
+ clone.myOffset = this.myOffset;
+ clone.myVirtualSpaceOffset = this.myVirtualSpaceOffset;
+ clone.myVisualLineStart = this.myVisualLineStart;
+ clone.myVisualLineEnd = this.myVisualLineEnd;
+ clone.savedBeforeBulkCaretMarker = this.savedBeforeBulkCaretMarker;
+ clone.mySkipChangeRequests = this.mySkipChangeRequests;
+ clone.myLastColumnNumber = this.myLastColumnNumber;
+ clone.myReportCaretMoves = this.myReportCaretMoves;
+ clone.myDesiredX = this.myDesiredX;
+ return clone;
+ }
+
+ @Nullable
+ @Override
+ public Caret clone(boolean above) {
+ assertIsDispatchThread();
+ int lineShift = above ? -1 : 1;
+ final CaretImpl clone = cloneWithoutSelection();
+ final int newSelectionStartOffset, newSelectionEndOffset;
+ 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;
+ }
+ else {
+ newSelectionStartOffset = 0;
+ newSelectionEndOffset = 0;
+ hasNewSelection = false;
+ }
+ LogicalPosition oldPosition = hasSelection() && !hasNewSelection ? myEditor.offsetToLogicalPosition(getSelectionStart()) : getLogicalPosition();
+ int newLine = oldPosition.line + lineShift;
+ if (newLine < 0 || newLine >= myEditor.getDocument().getLineCount()) {
+ Disposer.dispose(clone);
+ return null;
+ }
+ clone.moveToLogicalPosition(new LogicalPosition(newLine, oldPosition.column), false, null, false);
+ if (myEditor.getCaretModel().addCaret(clone)) {
+ if (hasSelection() && hasNewSelection) {
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ @Override
+ public void run() {
+ clone.setSelection(Math.min(newSelectionStartOffset, newSelectionEndOffset), Math.max(newSelectionStartOffset, newSelectionEndOffset));
+ }
+ });
+ if (!clone.isValid()) {
+ return null;
+ }
+ }
+ myEditor.getScrollingModel().scrollTo(clone.getLogicalPosition(), ScrollType.RELATIVE);
+ return clone;
+ }
+ else {
+ Disposer.dispose(clone);
+ return null;
+ }
+ }
+
+ private int getTruncatedOffset(LogicalPosition position) {
+ if (position.line < 0) {
+ return 0;
+ }
+ else if (position.line >= myEditor.getDocument().getLineCount()) {
+ return myEditor.getDocument().getTextLength();
+ }
+ else {
+ return myEditor.logicalPositionToOffset(position);
+ }
+ }
+
+ /**
+ * @return information on whether current selection's direction in known
+ * @see #setUnknownDirection(boolean)
+ */
+ public boolean isUnknownDirection() {
+ return myUnknownDirection;
+ }
+
+ /**
+ * There is a possible case that we don't know selection's direction. For example, a user might triple-click editor (select the
+ * whole line). We can't say what selection end is a {@link #getLeadSelectionOffset() leading end} then. However, that matters
+ * in a situation when a user clicks before or after that line holding Shift key. It's expected that the selection is expanded
+ * up to that point than.
+ * <p/>
+ * That's why we allow to specify that the direction is unknown and {@link #isUnknownDirection() expose this information}
+ * later.
+ * <p/>
+ * <b>Note:</b> when this method is called with <code>'true'</code>, subsequent calls are guaranteed to return <code>'true'</code>
+ * until selection is changed. 'Unknown direction' flag is automatically reset then.
+ *
+ * @param unknownDirection
+ */
+ public void setUnknownDirection(boolean unknownDirection) {
+ myUnknownDirection = unknownDirection;
+ }
+
+ @Override
+ public int getSelectionStart() {
+ validateContext(false);
+ if (hasSelection()) {
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null) {
+ return marker.getStartOffset();
+ }
+ }
+ return getOffset();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getSelectionStartPosition() {
+ VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionStart());
+ if (!hasSelection()) {
+ return defaultPosition;
+ }
+
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker == null) {
+ return defaultPosition;
+ }
+
+ VisualPosition result = marker.getStartPosition();
+ return result == null ? defaultPosition : result;
+ }
+
+ @Override
+ public int getSelectionEnd() {
+ validateContext(false);
+ if (hasSelection()) {
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null) {
+ return marker.getEndOffset();
+ }
+ }
+ return getOffset();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getSelectionEndPosition() {
+ VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionEnd());
+ if (!hasSelection()) {
+ return defaultPosition;
+ }
+
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker == null) {
+ return defaultPosition;
+ }
+
+ VisualPosition result = marker.getEndPosition();
+ return result == null ? defaultPosition : result;
+ }
+
+ @Override
+ public boolean hasSelection() {
+ validateContext(false);
+ MyRangeMarker marker = mySelectionMarker;
+ return marker != null && marker.isValid() && marker.getEndOffset() > marker.getStartOffset();
+ }
+
+ @Override
+ public void setSelection(int startOffset, int endOffset) {
+ doSetSelection(myEditor.offsetToVisualPosition(startOffset), startOffset, myEditor.offsetToVisualPosition(endOffset), endOffset, false);
+ }
+
+ @Override
+ public void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ VisualPosition startPosition;
+ if (hasSelection()) {
+ startPosition = getLeadSelectionPosition();
+ }
+ else {
+ startPosition = myEditor.offsetToVisualPosition(startOffset);
+ }
+ setSelection(startPosition, startOffset, endPosition, endOffset);
+ }
+
+ @Override
+ public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ VisualPosition startPositionToUse = startPosition == null ? myEditor.offsetToVisualPosition(startOffset) : startPosition;
+ VisualPosition endPositionToUse = endPosition == null ? myEditor.offsetToVisualPosition(endOffset) : endPosition;
+ doSetSelection(startPositionToUse, startOffset, endPositionToUse, endOffset, true);
+ }
+
+ private void doSetSelection(@NotNull final VisualPosition _startPosition,
+ final int _startOffset,
+ @NotNull final VisualPosition _endPosition,
+ final int _endOffset,
+ final boolean visualPositionAware)
+ {
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ VisualPosition startPosition = _startPosition;
+ int startOffset = _startOffset;
+ VisualPosition endPosition = _endPosition;
+ int endOffset = _endOffset;
+ myUnknownDirection = false;
+ final Document doc = myEditor.getDocument();
+ final Pair<String, String> markers = myEditor.getUserData(EditorImpl.EDITABLE_AREA_MARKER);
+ if (markers != null) {
+ final String text = doc.getText();
+ final int start = text.indexOf(markers.first) + markers.first.length();
+ final int end = text.indexOf(markers.second);
+ if (startOffset < endOffset) {
+ if (startOffset < start) {
+ startOffset = start;
+ startPosition = myEditor.offsetToVisualPosition(startOffset);
+ }
+ if (endOffset > end) {
+ endOffset = end;
+ endPosition = myEditor.offsetToVisualPosition(endOffset);
+ }
+ }
+ else {
+ if (endOffset < start) {
+ endOffset = start;
+ endPosition = myEditor.offsetToVisualPosition(startOffset);
+ }
+ if (startOffset > end) {
+ startOffset = end;
+ startPosition = myEditor.offsetToVisualPosition(endOffset);
+ }
+ }
+ }
+
+ validateContext(true);
+
+ myEditor.getSelectionModel().removeBlockSelection();
+
+ int textLength = doc.getTextLength();
+ if (startOffset < 0 || startOffset > textLength) {
+ LOG.error("Wrong startOffset: " + startOffset + ", textLength=" + textLength);
+ }
+ if (endOffset < 0 || endOffset > textLength) {
+ LOG.error("Wrong endOffset: " + endOffset + ", textLength=" + textLength);
+ }
+
+ if (!visualPositionAware && startOffset == endOffset) {
+ removeSelection();
+ return;
+ }
+
+ /* Normalize selection */
+ if (startOffset > endOffset) {
+ int tmp = startOffset;
+ startOffset = endOffset;
+ endOffset = tmp;
+ }
+
+ FoldingModelEx foldingModel = myEditor.getFoldingModel();
+ FoldRegion startFold = foldingModel.getCollapsedRegionAtOffset(startOffset);
+ if (startFold != null && startFold.getStartOffset() < startOffset) {
+ startOffset = startFold.getStartOffset();
+ }
+
+ FoldRegion endFold = foldingModel.getCollapsedRegionAtOffset(endOffset);
+ if (endFold != null && endFold.getStartOffset() < endOffset) {
+ // All visual positions that lay at collapsed fold region placeholder are mapped to the same offset. Hence, there are
+ // at least two distinct situations - selection end is located inside collapsed fold region placeholder and just before it.
+ // We want to expand selection to the fold region end at the former case and keep selection as-is at the latest one.
+ endOffset = endFold.getEndOffset();
+ }
+
+ int oldSelectionStart;
+ int oldSelectionEnd;
+
+ if (hasSelection()) {
+ oldSelectionStart = getSelectionStart();
+ oldSelectionEnd = getSelectionEnd();
+ if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset && !visualPositionAware) return;
+ }
+ else {
+ oldSelectionStart = oldSelectionEnd = getOffset();
+ }
+
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null) {
+ marker.release();
+ }
+
+ marker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset);
+ if (visualPositionAware) {
+ if (endPosition.after(startPosition)) {
+ marker.setStartPosition(startPosition);
+ marker.setEndPosition(endPosition);
+ marker.setEndPositionIsLead(false);
+ }
+ else {
+ marker.setStartPosition(endPosition);
+ marker.setEndPosition(startPosition);
+ marker.setEndPositionIsLead(true);
+ }
+ }
+ mySelectionMarker = marker;
+
+ myEditor.getSelectionModel().fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset);
+
+ updateSystemSelection();
+ }
+ });
+ }
+
+ private void updateSystemSelection() {
+ if (GraphicsEnvironment.isHeadless()) return;
+
+ final Clipboard clip = myEditor.getComponent().getToolkit().getSystemSelection();
+ if (clip != null) {
+ clip.setContents(new StringSelection(myEditor.getSelectionModel().getSelectedText(true)), EmptyClipboardOwner.INSTANCE);
+ }
+ }
+
+ @Override
+ public void removeSelection() {
+ if (myEditor.isStickySelection()) {
+ // Most of our 'change caret position' actions (like move caret to word start/end etc) remove active selection.
+ // However, we don't want to do that for 'sticky selection'.
+ return;
+ }
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ validateContext(true);
+ myEditor.getSelectionModel().removeBlockSelection();
+ int caretOffset = getOffset();
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null) {
+ int startOffset = marker.getStartOffset();
+ int endOffset = marker.getEndOffset();
+ marker.release();
+ mySelectionMarker = null;
+ myEditor.getSelectionModel().fireSelectionChanged(startOffset, endOffset, caretOffset, caretOffset);
+ }
+ }
+ });
+ }
+
+ @Override
+ public int getLeadSelectionOffset() {
+ validateContext(false);
+ int caretOffset = getOffset();
+ if (hasSelection()) {
+ MyRangeMarker marker = mySelectionMarker;
+ if (marker != null) {
+ int startOffset = marker.getStartOffset();
+ int endOffset = marker.getEndOffset();
+ if (caretOffset != startOffset && caretOffset != endOffset) {
+ // Try to check if current selection is tweaked by fold region.
+ FoldingModelEx foldingModel = myEditor.getFoldingModel();
+ FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(caretOffset);
+ if (foldRegion != null) {
+ if (foldRegion.getStartOffset() == startOffset) {
+ return endOffset;
+ }
+ else if (foldRegion.getEndOffset() == endOffset) {
+ return startOffset;
+ }
+ }
+ }
+
+ if (caretOffset == endOffset) {
+ return startOffset;
+ }
+ else {
+ return endOffset;
+ }
+ }
+ }
+ return caretOffset;
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getLeadSelectionPosition() {
+ MyRangeMarker marker = mySelectionMarker;
+ VisualPosition caretPosition = getVisualPosition();
+ if (marker == null) {
+ return caretPosition;
+ }
+
+ if (marker.isEndPositionIsLead()) {
+ VisualPosition result = marker.getEndPosition();
+ return result == null ? getSelectionEndPosition() : result;
+ }
+ else {
+ VisualPosition result = marker.getStartPosition();
+ return result == null ? getSelectionStartPosition() : result;
+ }
+ }
+
+ @Override
+ public void selectLineAtCaret() {
+ validateContext(true);
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ SelectionModelImpl.doSelectLineAtCaret(myEditor);
+ }
+ });
+ }
+
+ @Override
+ public void selectWordAtCaret(final boolean honorCamelWordsSettings) {
+ validateContext(true);
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ removeSelection();
+ final EditorSettings settings = myEditor.getSettings();
+ boolean camelTemp = settings.isCamelWords();
+
+ final boolean needOverrideSetting = camelTemp && !honorCamelWordsSettings;
+ if (needOverrideSetting) {
+ settings.setCamelWords(false);
+ }
+
+ try {
+ EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(
+ IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
+ handler.execute(myEditor, myEditor.getDataContext());
+ }
+ finally {
+ if (needOverrideSetting) {
+ settings.resetCamelWords();
+ }
+ }
+ }
+ });
+ }
+
+ @Nullable
+ @Override
+ public String getSelectedText() {
+ if (!hasSelection()) {
+ return null;
+ }
+ CharSequence text = myEditor.getDocument().getCharsSequence();
+ int selectionStart = getSelectionStart();
+ int selectionEnd = getSelectionEnd();
+ return text.subSequence(selectionStart, selectionEnd).toString();
+ }
+
+ private void validateContext(boolean isWrite) {
+ if (!myEditor.getComponent().isShowing()) return;
+ if (isWrite) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ }
+ else {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+ }
+ }
+
+ /**
+ * Encapsulates information about target vertical range info - its <code>'y'</code> coordinate and height in pixels.
+ */
+ public static class VerticalInfo {
+ public final int y;
+ public final int height;
+
+ private VerticalInfo(int y, int height) {
+ this.y = y;
+ this.height = height;
+ }
+ }
+
+ private class MyRangeMarker extends RangeMarkerImpl {
+ private VisualPosition myStartPosition;
+ private VisualPosition myEndPosition;
+ private boolean myEndPositionIsLead;
+ private boolean myIsReleased;
+
+ MyRangeMarker(DocumentEx document, int start, int end) {
+ super(document, start, end, true);
+ myIsReleased = false;
+ }
+
+ public void release() {
+ myIsReleased = true;
+ dispose();
+ }
+
+ @Nullable
+ public VisualPosition getStartPosition() {
+ invalidateVisualPositions();
+ return myStartPosition;
+ }
+
+ public void setStartPosition(@NotNull VisualPosition startPosition) {
+ myStartPosition = startPosition;
+ }
+
+ @Nullable
+ public VisualPosition getEndPosition() {
+ invalidateVisualPositions();
+ return myEndPosition;
+ }
+
+ public void setEndPosition(@NotNull VisualPosition endPosition) {
+ myEndPosition = endPosition;
+ }
+
+ public boolean isEndPositionIsLead() {
+ return myEndPositionIsLead;
+ }
+
+ public void setEndPositionIsLead(boolean endPositionIsLead) {
+ myEndPositionIsLead = endPositionIsLead;
+ }
+
+ int startBefore;
+ int endBefore;
+
+ @Override
+ protected void changedUpdateImpl(DocumentEvent e) {
+ if (myIsReleased) return;
+ startBefore = getStartOffset();
+ endBefore = getEndOffset();
+ super.changedUpdateImpl(e);
+ }
+
+ private void invalidateVisualPositions() {
+ SoftWrapModelImpl model = myEditor.getSoftWrapModel();
+ if (!myEditor.offsetToVisualPosition(getStartOffset()).equals(myStartPosition) && model.getSoftWrap(getStartOffset()) == null
+ || !myEditor.offsetToVisualPosition(getEndOffset()).equals(myEndPosition) && model.getSoftWrap(getEndOffset()) == null) {
+ myStartPosition = null;
+ myEndPosition = null;
+ }
+ }
+ }
+}
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 b34f292..cb0aee7 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
@@ -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,233 +24,104 @@
*/
package com.intellij.openapi.editor.impl;
-import com.intellij.diagnostic.LogMessageEx;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
-import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.colors.EditorColors;
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.DocumentEx;
-import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
-import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
-import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.ide.CopyPasteManager;
-import com.intellij.openapi.util.text.StringUtil;
+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 com.intellij.util.diff.FilesTooBigForDiffException;
-import com.intellij.util.text.CharArrayUtil;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.awt.*;
-import java.util.List;
+import java.util.*;
public class CaretModelImpl implements CaretModel, PrioritizedDocumentListener, Disposable {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.CaretModelImpl");
-
private final EditorImpl myEditor;
- private final EventDispatcher<CaretListener> myCaretListeners = EventDispatcher.create(CaretListener.class);
- private LogicalPosition myLogicalCaret;
- private VerticalInfo myCaretInfo;
- private VisualPosition myVisibleCaret;
- private int myOffset;
- private int myVisualLineStart;
- private int myVisualLineEnd;
+
+ private final EventDispatcher<MultipleCaretListener> myCaretListeners = EventDispatcher.create(MultipleCaretListener.class);
+ private final Map<CaretListener, MultipleCaretListener> myListenerMap = new HashMap<CaretListener, MultipleCaretListener>();
+ private final boolean mySupportsMultipleCarets = Registry.is("editor.allow.multiple.carets");
+
private TextAttributes myTextAttributes;
- private boolean myIsInUpdate;
- private RangeMarker savedBeforeBulkCaretMarker;
- private boolean myIgnoreWrongMoves = false;
- private boolean mySkipChangeRequests;
- /**
- * We check that caret is located at the target offset at the end of {@link #moveToOffset(int, boolean)} method. However,
- * it's possible that the following situation occurs:
- * <p/>
- * <pre>
- * <ol>
- * <li>Some client subscribes to caret change events;</li>
- * <li>{@link #moveToLogicalPosition(LogicalPosition)} is called;</li>
- * <li>Caret position is changed during {@link #moveToLogicalPosition(LogicalPosition)} processing;</li>
- * <li>The client receives caret position change event and adjusts the position;</li>
- * <li>{@link #moveToLogicalPosition(LogicalPosition)} processing is finished;</li>
- * <li>{@link #moveToLogicalPosition(LogicalPosition)} reports an error because the caret is not located at the target offset;</li>
- * </ol>
- * </pre>
- * <p/>
- * This field serves as a flag that reports unexpected caret position change requests nested from {@link #moveToOffset(int, boolean)}.
- */
- private boolean myReportCaretMoves;
+ boolean myIgnoreWrongMoves = false;
+ boolean myIsInUpdate;
+ boolean isDocumentChanged;
- /**
- * There is a possible case that user defined non-monospaced font for editor. That means that various symbols have different
- * visual widths. That means that if we move caret vertically it may deviate to the left/right. However, we can try to preserve
- * its initial visual position when possible.
- * <p/>
- * This field holds desired value for visual <code>'x'</code> caret coordinate (negative value if no coordinate should be preserved).
- */
- private int myDesiredX = -1;
+ private final LinkedList<CaretImpl> myCarets = new LinkedList<CaretImpl>();
+ private CaretImpl myCurrentCaret; // active caret in the context of 'runForEachCaret' call
+ private boolean myPerformCaretMergingAfterCurrentOperation;
public CaretModelImpl(EditorImpl editor) {
myEditor = editor;
- myLogicalCaret = new LogicalPosition(0, 0);
- myVisibleCaret = new VisualPosition(0, 0);
- myCaretInfo = new VerticalInfo(0, 0);
- myOffset = 0;
- myVisualLineStart = 0;
- Document doc = editor.getDocument();
- myVisualLineEnd = doc.getLineCount() > 1 ? doc.getLineStartOffset(1) : doc.getLineCount() == 0 ? 0 : doc.getLineEndOffset(0);
+ myCarets.add(new CaretImpl(myEditor));
+
DocumentBulkUpdateListener bulkUpdateListener = new DocumentBulkUpdateListener() {
@Override
public void updateStarted(@NotNull Document doc) {
- if (doc != myEditor.getDocument() || myOffset > doc.getTextLength() || savedBeforeBulkCaretMarker != null) return;
- savedBeforeBulkCaretMarker = doc.createRangeMarker(myOffset, myOffset);
+ for (CaretImpl caret : myCarets) {
+ caret.onBulkDocumentUpdateStarted(doc);
+ }
}
@Override
- public void updateFinished(@NotNull Document doc) {
- if (doc != myEditor.getDocument() || myIsInUpdate) return;
- LOG.assertTrue(!myReportCaretMoves);
-
- if (savedBeforeBulkCaretMarker != null) {
- if(savedBeforeBulkCaretMarker.isValid()) {
- if(savedBeforeBulkCaretMarker.getStartOffset() != myOffset) {
- moveToOffset(savedBeforeBulkCaretMarker.getStartOffset());
+ public void updateFinished(@NotNull final Document doc) {
+ doWithCaretMerging(new Runnable() {
+ @Override
+ public void run() {
+ for (CaretImpl caret : myCarets) {
+ caret.onBulkDocumentUpdateFinished(doc);
}
- } else if (myOffset > doc.getTextLength()) {
- moveToOffset(doc.getTextLength());
}
- releaseBulkCaretMarker();
- }
+ });
}
};
ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(DocumentBulkUpdateListener.TOPIC, bulkUpdateListener);
}
- private void releaseBulkCaretMarker() {
- if (savedBeforeBulkCaretMarker != null) {
- savedBeforeBulkCaretMarker.dispose();
- savedBeforeBulkCaretMarker = null;
+ @Override
+ public void documentChanged(final DocumentEvent e) {
+ isDocumentChanged = true;
+ try {
+ myIsInUpdate = false;
+ doWithCaretMerging(new Runnable() {
+ @Override
+ public void run() {
+ for (CaretImpl caret : myCarets) {
+ caret.updateCaretPosition((DocumentEventImpl)e);
+ }
+ }
+ });
+ }
+ finally {
+ isDocumentChanged = false;
}
}
@Override
- public void moveToVisualPosition(@NotNull VisualPosition pos) {
- assertIsDispatchThread();
- validateCallContext();
- if (mySkipChangeRequests) {
- return;
- }
- if (myReportCaretMoves) {
- LogMessageEx.error(LOG, "Unexpected caret move request");
- }
- if (!myEditor.isStickySelection() && !pos.equals(myVisibleCaret)) {
- CopyPasteManager.getInstance().stopKillRings();
- }
-
- myDesiredX = -1;
- int column = pos.column;
- int line = pos.line;
-
- if (column < 0) column = 0;
-
- if (line < 0) line = 0;
-
- int lastLine = myEditor.getVisibleLineCount() - 1;
- if (lastLine <= 0) {
- lastLine = 0;
- }
-
- if (line > lastLine) {
- line = lastLine;
- }
-
- EditorSettings editorSettings = myEditor.getSettings();
-
- if (!editorSettings.isVirtualSpace() && line <= lastLine) {
- int lineEndColumn = EditorUtil.getLastVisualLineColumnNumber(myEditor, line);
- if (column > lineEndColumn) {
- column = lineEndColumn;
- }
-
- if (column < 0 && line > 0) {
- line--;
- column = EditorUtil.getLastVisualLineColumnNumber(myEditor, line);
- }
- }
-
- myVisibleCaret = new VisualPosition(line, column);
-
- VerticalInfo oldInfo = myCaretInfo;
- LogicalPosition oldPosition = myLogicalCaret;
-
- setCurrentLogicalCaret(myEditor.visualToLogicalPosition(myVisibleCaret));
- myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
- LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());
-
- myVisualLineStart = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
- myVisualLineEnd = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));
-
- myEditor.getFoldingModel().flushCaretPosition();
-
- myEditor.setLastColumnNumber(myVisibleCaret.column);
- myEditor.updateCaretCursor();
- requestRepaint(oldInfo);
-
- if (!oldPosition.equals(myLogicalCaret)) {
- CaretEvent event = new CaretEvent(myEditor, oldPosition, myLogicalCaret);
- myCaretListeners.getMulticaster().caretPositionChanged(event);
- }
- }
-
- private void assertIsDispatchThread() {
- myEditor.assertIsDispatchThread();
+ public void beforeDocumentChange(DocumentEvent e) {
+ myIsInUpdate = true;
}
@Override
- public void moveToOffset(int offset) {
- moveToOffset(offset, false);
+ public int getPriority() {
+ return EditorDocumentPriorities.CARET_MODEL;
}
@Override
- public void moveToOffset(int offset, boolean locateBeforeSoftWrap) {
- assertIsDispatchThread();
- validateCallContext();
- if (mySkipChangeRequests) {
- return;
- }
- final LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(offset);
- CaretEvent event = moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, null, false);
- final LogicalPosition positionByOffsetAfterMove = myEditor.offsetToLogicalPosition(myOffset);
- if (!myIgnoreWrongMoves && !positionByOffsetAfterMove.equals(logicalPosition)) {
- StringBuilder debugBuffer = new StringBuilder();
- moveToLogicalPosition(logicalPosition, locateBeforeSoftWrap, debugBuffer, true);
- int textStart = Math.max(0, Math.min(offset, myOffset) - 1);
- final DocumentEx document = myEditor.getDocument();
- int textEnd = Math.min(document.getTextLength() - 1, Math.max(offset, myOffset) + 1);
- CharSequence text = document.getCharsSequence().subSequence(textStart, textEnd);
- StringBuilder positionToOffsetTrace = new StringBuilder();
- int inverseOffset = myEditor.logicalPositionToOffset(logicalPosition, positionToOffsetTrace);
- LogMessageEx.error(
- LOG, "caret moved to wrong offset. Please submit a dedicated ticket and attach current editor's text to it.",
- String.format(
- "Requested: offset=%d, logical position='%s' but actual: offset=%d, logical position='%s' (%s). %s%n"
- + "interested text [%d;%d): '%s'%n debug trace: %s%nLogical position -> offset ('%s'->'%d') trace: %s",
- offset, logicalPosition, myOffset, myLogicalCaret, positionByOffsetAfterMove, myEditor.dumpState(),
- textStart, textEnd, text, debugBuffer, logicalPosition, inverseOffset, positionToOffsetTrace
- ));
- }
- if (event != null) {
- myCaretListeners.getMulticaster().caretPositionChanged(event);
- EditorActionUtil.selectNonexpandableFold(myEditor);
+ public void dispose() {
+ for (CaretImpl caret : myCarets) {
+ Disposer.dispose(caret);
}
}
@@ -258,443 +129,111 @@
myIgnoreWrongMoves = ignoreWrongMoves;
}
+ public void updateVisualPosition() {
+ for (CaretImpl caret : myCarets) {
+ caret.updateVisualPosition();
+ }
+ }
+
@Override
- public void moveCaretRelatively(int columnShift,
- int lineShift,
- boolean withSelection,
- boolean blockSelection,
- boolean scrollToCaret) {
- assertIsDispatchThread();
- if (mySkipChangeRequests) {
- return;
- }
- if (myReportCaretMoves) {
- LogMessageEx.error(LOG, "Unexpected caret move request");
- }
- if (!myEditor.isStickySelection()) {
- CopyPasteManager.getInstance().stopKillRings();
- }
- SelectionModelImpl selectionModel = myEditor.getSelectionModel();
- final int leadSelectionOffset = selectionModel.getLeadSelectionOffset();
- LogicalPosition blockSelectionStart = selectionModel.hasBlockSelection()
- ? selectionModel.getBlockStart()
- : getLogicalPosition();
- EditorSettings editorSettings = myEditor.getSettings();
- VisualPosition visualCaret = getVisualPosition();
-
- int desiredX = myDesiredX;
- if (columnShift == 0) {
- if (myDesiredX < 0) {
- desiredX = myEditor.visualPositionToXY(visualCaret).x;
- }
- }
- else {
- myDesiredX = desiredX = -1;
- }
-
- int newLineNumber = visualCaret.line + lineShift;
- int newColumnNumber = visualCaret.column + columnShift;
- if (desiredX >= 0 && !ApplicationManager.getApplication().isUnitTestMode()) {
- newColumnNumber = myEditor.xyToVisualPosition(new Point(desiredX, Math.max(0, newLineNumber) * myEditor.getLineHeight())).column;
- }
-
- Document document = myEditor.getDocument();
- if (!editorSettings.isVirtualSpace() && columnShift == 0 && getLogicalPosition().softWrapLinesOnCurrentLogicalLine <= 0) {
- newColumnNumber = myEditor.getLastColumnNumber();
- }
- else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == 1) {
- int lastLine = document.getLineCount() - 1;
- if (lastLine < 0) lastLine = 0;
- if (EditorModificationUtil.calcAfterLineEnd(myEditor) >= 0 &&
- newLineNumber < myEditor.logicalToVisualPosition(new LogicalPosition(lastLine, 0)).line) {
- newColumnNumber = 0;
- newLineNumber++;
- }
- }
- else if (!editorSettings.isVirtualSpace() && lineShift == 0 && columnShift == -1) {
- if (newColumnNumber < 0 && newLineNumber > 0) {
- newLineNumber--;
- newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
- }
- }
-
- if (newColumnNumber < 0) newColumnNumber = 0;
-
- // There is a possible case that caret is located at the first line and user presses 'Shift+Up'. We want to select all text
- // from the document start to the current caret position then. So, we have a dedicated flag for tracking that.
- boolean selectToDocumentStart = false;
- if (newLineNumber < 0) {
- selectToDocumentStart = true;
- newLineNumber = 0;
-
- // We want to move caret to the first column if it's already located at the first line and 'Up' is pressed.
- newColumnNumber = 0;
- desiredX = -1;
- }
-
- VisualPosition pos = new VisualPosition(newLineNumber, newColumnNumber);
- int lastColumnNumber = newColumnNumber;
- if (!editorSettings.isCaretInsideTabs() && !myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
- LogicalPosition log = myEditor.visualToLogicalPosition(new VisualPosition(newLineNumber, newColumnNumber));
- int offset = myEditor.logicalPositionToOffset(log);
- if (offset >= document.getTextLength()) {
- int lastOffsetColumn = myEditor.offsetToVisualPosition(document.getTextLength()).column;
- // We want to move caret to the last column if if it's located at the last line and 'Down' is pressed.
- newColumnNumber = lastColumnNumber = Math.max(lastOffsetColumn, newColumnNumber);
- desiredX = -1;
- }
- CharSequence text = document.getCharsSequence();
- if (offset >= 0 && offset < document.getTextLength()) {
- if (text.charAt(offset) == '\t' && (columnShift <= 0 || offset == myOffset)) {
- if (columnShift <= 0) {
- newColumnNumber = myEditor.offsetToVisualPosition(offset).column;
- }
- else {
- SoftWrap softWrap = myEditor.getSoftWrapModel().getSoftWrap(offset + 1);
- // There is a possible case that tabulation symbol is the last document symbol represented on a visual line before
- // soft wrap. We can't just use column from 'offset + 1' because it would point on a next visual line.
- if (softWrap == null) {
- newColumnNumber = myEditor.offsetToVisualPosition(offset + 1).column;
- }
- else {
- newColumnNumber = EditorUtil.getLastVisualLineColumnNumber(myEditor, newLineNumber);
- }
- }
- }
- }
- }
-
- pos = new VisualPosition(newLineNumber, newColumnNumber);
- if (columnShift != 0 && lineShift == 0 && myEditor.getSoftWrapModel().isInsideSoftWrap(pos)) {
- LogicalPosition logical = myEditor.visualToLogicalPosition(pos);
- int softWrapOffset = myEditor.logicalPositionToOffset(logical);
- if (columnShift >= 0) {
- moveToOffset(softWrapOffset);
- }
- else {
- int line = myEditor.offsetToVisualLine(softWrapOffset - 1);
- moveToVisualPosition(new VisualPosition(line, EditorUtil.getLastVisualLineColumnNumber(myEditor, line)));
- }
- }
- else {
- moveToVisualPosition(pos);
- if (!editorSettings.isVirtualSpace() && columnShift == 0) {
- myEditor.setLastColumnNumber(lastColumnNumber);
- }
- }
-
- if (withSelection) {
- if (blockSelection) {
- selectionModel.setBlockSelection(blockSelectionStart, getLogicalPosition());
- }
- else {
- if (selectToDocumentStart) {
- selectionModel.setSelection(leadSelectionOffset, 0);
- }
- else if (pos.line >= myEditor.getVisibleLineCount()) {
- if (leadSelectionOffset < document.getTextLength()) {
- selectionModel.setSelection(leadSelectionOffset, document.getTextLength());
- }
- }
- else {
- int selectionStartToUse = leadSelectionOffset;
- if (selectionModel.isUnknownDirection()) {
- if (getOffset() > leadSelectionOffset) {
- selectionStartToUse = Math.min(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
- }
- else {
- selectionStartToUse = Math.max(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
- }
- }
- selectionModel.setSelection(selectionStartToUse, getVisualPosition(), getOffset());
- }
- }
- }
- else {
- selectionModel.removeSelection();
- }
-
- if (scrollToCaret) {
- myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
- }
-
- if (desiredX >= 0) {
- myDesiredX = desiredX;
- }
-
- EditorActionUtil.selectNonexpandableFold(myEditor);
+ public void moveCaretRelatively(final int columnShift, final int lineShift, final boolean withSelection, final boolean blockSelection, final boolean scrollToCaret) {
+ getCurrentCaret().moveCaretRelatively(columnShift, lineShift, withSelection, blockSelection, scrollToCaret);
}
@Override
public void moveToLogicalPosition(@NotNull LogicalPosition pos) {
- moveToLogicalPosition(pos, false, null, true);
+ getCurrentCaret().moveToLogicalPosition(pos);
}
- @Nullable
- private CaretEvent moveToLogicalPosition(@NotNull LogicalPosition pos,
- boolean locateBeforeSoftWrap,
- @Nullable StringBuilder debugBuffer,
- boolean fireListeners) {
- if (mySkipChangeRequests) {
- return null;
- }
- if (myReportCaretMoves) {
- LogMessageEx.error(LOG, "Unexpected caret move request");
- }
- if (!myEditor.isStickySelection() && !pos.equals(myLogicalCaret)) {
- CopyPasteManager.getInstance().stopKillRings();
- }
-
- myReportCaretMoves = true;
- try {
- return doMoveToLogicalPosition(pos, locateBeforeSoftWrap, debugBuffer, fireListeners);
- }
- finally {
- myReportCaretMoves = false;
- }
+ @Override
+ public void moveToVisualPosition(@NotNull VisualPosition pos) {
+ getCurrentCaret().moveToVisualPosition(pos);
}
- private CaretEvent doMoveToLogicalPosition(@NotNull LogicalPosition pos,
- boolean locateBeforeSoftWrap,
- @NonNls @Nullable StringBuilder debugBuffer,
- boolean fireListeners) {
- assertIsDispatchThread();
- if (debugBuffer != null) {
- debugBuffer.append("Start moveToLogicalPosition(). Locate before soft wrap: " + locateBeforeSoftWrap + ", position: " + pos + "\n");
- }
- myDesiredX = -1;
- validateCallContext();
- int column = pos.column;
- int line = pos.line;
- int softWrapLinesBefore = pos.softWrapLinesBeforeCurrentLogicalLine;
- int softWrapLinesCurrent = pos.softWrapLinesOnCurrentLogicalLine;
- int softWrapColumns = pos.softWrapColumnDiff;
-
- Document doc = myEditor.getDocument();
-
- if (column < 0) {
- if (debugBuffer != null) {
- debugBuffer.append("Resetting target logical column to zero as it is negative (").append(column).append(")\n");
- }
- column = 0;
- softWrapColumns = 0;
- }
- if (line < 0) {
- if (debugBuffer != null) {
- debugBuffer.append("Resetting target logical line to zero as it is negative (").append(line).append(")\n");
- }
- line = 0;
- softWrapLinesBefore = 0;
- softWrapLinesCurrent = 0;
- }
-
- int lineCount = doc.getLineCount();
- if (lineCount == 0) {
- if (debugBuffer != null) {
- debugBuffer.append("Resetting target logical line to zero as the document is empty\n");
- }
- line = 0;
- }
- else if (line > lineCount - 1) {
- if (debugBuffer != null) {
- debugBuffer.append("Resetting target logical line (" + line + ") to " + (lineCount - 1) + " as it is greater than total document lines number\n");
- }
- line = lineCount - 1;
- softWrapLinesBefore = 0;
- softWrapLinesCurrent = 0;
- }
-
- EditorSettings editorSettings = myEditor.getSettings();
-
- if (!editorSettings.isVirtualSpace() && line < lineCount && !myEditor.getSelectionModel().hasBlockSelection()) {
- int lineEndOffset = doc.getLineEndOffset(line);
- final LogicalPosition endLinePosition = myEditor.offsetToLogicalPosition(lineEndOffset);
- int lineEndColumnNumber = endLinePosition.column;
- if (column > lineEndColumnNumber) {
- int oldColumn = column;
- column = lineEndColumnNumber;
- if (softWrapColumns != 0) {
- softWrapColumns -= column - lineEndColumnNumber;
- }
- if (debugBuffer != null) {
- debugBuffer.append(
- "Resetting target logical column (" + oldColumn + ") to " + lineEndColumnNumber +
- " because caret is not allowed to be located after line end (offset: " +lineEndOffset + ", "
- + "logical position: " + endLinePosition+ "). Current soft wrap columns value: " + softWrapColumns+ "\n");
- }
- }
- }
-
- myEditor.getFoldingModel().flushCaretPosition();
-
- VerticalInfo oldInfo = myCaretInfo;
- LogicalPosition oldCaretPosition = myLogicalCaret;
-
- LogicalPosition logicalPositionToUse;
- if (pos.visualPositionAware) {
- logicalPositionToUse = new LogicalPosition(
- line, column, softWrapLinesBefore, softWrapLinesCurrent, softWrapColumns, pos.foldedLines, pos.foldingColumnDiff
- );
- }
- else {
- logicalPositionToUse = new LogicalPosition(line, column);
- }
- setCurrentLogicalCaret(logicalPositionToUse);
- final int offset = myEditor.logicalPositionToOffset(myLogicalCaret);
- if (debugBuffer != null) {
- debugBuffer.append("Resulting logical position to use: " + myLogicalCaret+
- ". It's mapped to offset " + offset+ "\n");
- }
-
- FoldRegion collapsedAt = myEditor.getFoldingModel().getCollapsedRegionAtOffset(offset);
-
- if (collapsedAt != null && offset > collapsedAt.getStartOffset()) {
- if (debugBuffer != null) {
- debugBuffer.append("Scheduling expansion of fold region ").append(collapsedAt).append("\n");
- }
- Runnable runnable = new Runnable() {
- @Override
- public void run() {
- FoldRegion[] allCollapsedAt = myEditor.getFoldingModel().fetchCollapsedAt(offset);
- for (FoldRegion foldRange : allCollapsedAt) {
- foldRange.setExpanded(true);
- }
- }
- };
-
- mySkipChangeRequests = true;
- try {
- myEditor.getFoldingModel().runBatchFoldingOperation(runnable, false);
- }
- finally {
- mySkipChangeRequests = false;
- }
- }
-
- myEditor.setLastColumnNumber(myLogicalCaret.column);
- myVisibleCaret = myEditor.logicalToVisualPosition(myLogicalCaret);
-
- myOffset = myEditor.logicalPositionToOffset(myLogicalCaret);
- if (debugBuffer != null) {
- debugBuffer.append("Storing offset " + myOffset + " (mapped from logical position " + myLogicalCaret + ")\n");
- }
- LOG.assertTrue(myOffset >= 0 && myOffset <= myEditor.getDocument().getTextLength());
-
- myVisualLineStart = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
- myVisualLineEnd = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));
-
- myEditor.updateCaretCursor();
- requestRepaint(oldInfo);
-
- if (locateBeforeSoftWrap && SoftWrapHelper.isCaretAfterSoftWrap(myEditor)) {
- int lineToUse = myVisibleCaret.line - 1;
- if (lineToUse >= 0) {
- final VisualPosition visualPosition = new VisualPosition(lineToUse, EditorUtil.getLastVisualLineColumnNumber(myEditor, lineToUse));
- if (debugBuffer != null) {
- debugBuffer.append("Adjusting caret position by moving it before soft wrap. Moving to visual position "+ visualPosition+"\n");
- }
- final LogicalPosition logicalPosition = myEditor.visualToLogicalPosition(visualPosition);
- final int tmpOffset = myEditor.logicalPositionToOffset(logicalPosition);
- if (tmpOffset == myOffset) {
- boolean restore = myReportCaretMoves;
- myReportCaretMoves = false;
- try {
- moveToVisualPosition(visualPosition);
- return null;
- }
- finally {
- myReportCaretMoves = restore;
- }
- }
- else {
- LogMessageEx.error(LOG, "Invalid editor dimension mapping", String.format(
- "Expected to map visual position '%s' to offset %d but got the following: -> logical position '%s'; -> offset %d. "
- + "State: %s", visualPosition, myOffset, logicalPosition, tmpOffset, myEditor.dumpState()
- ));
- }
- }
- }
-
- if (!oldCaretPosition.toVisualPosition().equals(myLogicalCaret.toVisualPosition())) {
- CaretEvent event = new CaretEvent(myEditor, oldCaretPosition, myLogicalCaret);
- if (fireListeners) {
- myCaretListeners.getMulticaster().caretPositionChanged(event);
- }
- else {
- return event;
- }
- }
- return null;
+ @Override
+ public void moveToOffset(int offset) {
+ getCurrentCaret().moveToOffset(offset);
}
- private void requestRepaint(VerticalInfo oldCaretInfo) {
- int lineHeight = myEditor.getLineHeight();
- Rectangle visibleArea = myEditor.getScrollingModel().getVisibleArea();
- final EditorGutterComponentEx gutter = myEditor.getGutterComponentEx();
- final EditorComponentImpl content = myEditor.getContentComponent();
-
- int updateWidth = myEditor.getScrollPane().getHorizontalScrollBar().getValue() + visibleArea.width;
- if (Math.abs(myCaretInfo.y - oldCaretInfo.y) <= 2 * lineHeight) {
- int minY = Math.min(oldCaretInfo.y, myCaretInfo.y);
- int maxY = Math.max(oldCaretInfo.y + oldCaretInfo.height, myCaretInfo.y + myCaretInfo.height);
- content.repaintEditorComponent(0, minY, updateWidth, maxY - minY);
- gutter.repaint(0, minY, gutter.getWidth(), maxY - minY);
- }
- else {
- content.repaintEditorComponent(0, oldCaretInfo.y, updateWidth, oldCaretInfo.height + lineHeight);
- gutter.repaint(0, oldCaretInfo.y, updateWidth, oldCaretInfo.height + lineHeight);
- content.repaintEditorComponent(0, myCaretInfo.y, updateWidth, myCaretInfo.height + lineHeight);
- gutter.repaint(0, myCaretInfo.y, updateWidth, myCaretInfo.height + lineHeight);
- }
+ @Override
+ public void moveToOffset(int offset, boolean locateBeforeSoftWrap) {
+ getCurrentCaret().moveToOffset(offset, locateBeforeSoftWrap);
}
@Override
public boolean isUpToDate() {
- return !myIsInUpdate && !myReportCaretMoves;
+ return getCurrentCaret().isUpToDate();
}
- @Override
@NotNull
+ @Override
public LogicalPosition getLogicalPosition() {
- validateCallContext();
- return myLogicalCaret;
+ return getCurrentCaret().getLogicalPosition();
}
- private void validateCallContext() {
- LOG.assertTrue(!myIsInUpdate, "Caret model is in its update process. All requests are illegal at this point.");
- }
-
- @Override
@NotNull
+ @Override
public VisualPosition getVisualPosition() {
- validateCallContext();
- return myVisibleCaret;
+ return getCurrentCaret().getVisualPosition();
}
@Override
public int getOffset() {
- validateCallContext();
- return myOffset;
+ return getCurrentCaret().getOffset();
}
@Override
public int getVisualLineStart() {
- return myVisualLineStart;
+ return getCurrentCaret().getVisualLineStart();
}
@Override
public int getVisualLineEnd() {
- return myVisualLineEnd;
+ return getCurrentCaret().getVisualLineEnd();
+ }
+
+ int getWordAtCaretStart() {
+ return getCurrentCaret().getWordAtCaretStart();
+ }
+
+ int getWordAtCaretEnd() {
+ return getCurrentCaret().getWordAtCaretEnd();
}
@Override
- public void addCaretListener(@NotNull CaretListener listener) {
- myCaretListeners.addListener(listener);
+ 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);
}
@Override
public void removeCaretListener(@NotNull CaretListener listener) {
- myCaretListeners.removeListener(listener);
+ MultipleCaretListener newListener = myListenerMap.remove(listener);
+ if (newListener != null) {
+ myCaretListeners.removeListener(newListener);
+ }
}
@Override
@@ -712,128 +251,288 @@
}
@Override
- public void documentChanged(DocumentEvent e) {
- finishUpdate();
+ public boolean supportsMultipleCarets() {
+ return mySupportsMultipleCarets;
+ }
- DocumentEventImpl event = (DocumentEventImpl)e;
- final DocumentEx document = myEditor.getDocument();
- boolean performSoftWrapAdjustment = e.getNewLength() > 0 // We want to put caret just after the last added symbol
- // There is a possible case that the user removes text just before the soft wrap. We want to keep caret
- // on a visual line with soft wrap start then.
- || myEditor.getSoftWrapModel().getSoftWrap(e.getOffset()) != null;
+ @Override
+ @NotNull
+ public CaretImpl getCurrentCaret() {
+ return ApplicationManager.getApplication().isDispatchThread() && myCurrentCaret != null ? myCurrentCaret : getPrimaryCaret();
+ }
- if (event.isWholeTextReplaced()) {
- int newLength = document.getTextLength();
- if (myOffset == newLength - e.getNewLength() + e.getOldLength() || newLength == 0) {
- moveToOffset(newLength, performSoftWrapAdjustment);
- }
- else {
- try {
- final int line = event.translateLineViaDiff(myLogicalCaret.line);
- moveToLogicalPosition(new LogicalPosition(line, myLogicalCaret.column), performSoftWrapAdjustment, null, true);
- }
- catch (FilesTooBigForDiffException e1) {
- LOG.info(e1);
- moveToOffset(0);
+ @Override
+ @NotNull
+ public CaretImpl getPrimaryCaret() {
+ synchronized (myCarets) {
+ return myCarets.get(myCarets.size() - 1);
+ }
+ }
+
+ @Override
+ @NotNull
+ public Collection<Caret> getAllCarets() {
+ List<Caret> carets;
+ synchronized (myCarets) {
+ carets = new ArrayList<Caret>(myCarets);
+ }
+ Collections.sort(carets, CaretPositionComparator.INSTANCE);
+ return carets;
+ }
+
+ @Nullable
+ @Override
+ public Caret getCaretAt(@NotNull VisualPosition pos) {
+ synchronized (myCarets) {
+ for (CaretImpl caret : myCarets) {
+ if (caret.getVisualPosition().equals(pos)) {
+ return caret;
}
}
+ return null;
+ }
+ }
+
+ @Nullable
+ @Override
+ public Caret addCaret(@NotNull VisualPosition pos) {
+ myEditor.assertIsDispatchThread();
+ CaretImpl caret = new CaretImpl(myEditor);
+ caret.moveToVisualPosition(pos, false);
+ if (addCaret(caret)) {
+ return caret;
}
else {
- if (document.isInBulkUpdate()) return;
- int startOffset = e.getOffset();
- int oldEndOffset = startOffset + e.getOldLength();
+ Disposer.dispose(caret);
+ return null;
+ }
+ }
- int newOffset = myOffset;
-
- if (myOffset > oldEndOffset || myOffset == oldEndOffset && needToShiftWhiteSpaces(e)) {
- newOffset += e.getNewLength() - e.getOldLength();
+ boolean addCaret(CaretImpl caretToAdd) {
+ for (CaretImpl caret : myCarets) {
+ VisualPosition newVisualPosition = caretToAdd.getVisualPosition();
+ int newOffset = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(newVisualPosition));
+ if (caret.getVisualPosition().equals(newVisualPosition) || newOffset >= caret.getSelectionStart() && newOffset <= caret.getSelectionEnd()) {
+ return false;
}
- else if (myOffset >= startOffset && myOffset <= oldEndOffset) {
- newOffset = Math.min(newOffset, startOffset + e.getNewLength());
+ }
+ synchronized (myCarets) {
+ myCarets.add(caretToAdd);
+ }
+ fireCaretAdded(caretToAdd);
+ return true;
+ }
+
+ @Override
+ public boolean removeCaret(@NotNull Caret caret) {
+ myEditor.assertIsDispatchThread();
+ if (myCarets.size() <= 1 || !(caret instanceof CaretImpl)) {
+ return false;
+ }
+ synchronized (myCarets) {
+ if (!myCarets.remove(caret)) {
+ return false;
}
-
- newOffset = Math.min(newOffset, document.getTextLength());
-
- // if (newOffset != myOffset) {
- moveToOffset(newOffset, performSoftWrapAdjustment);
- //}
- //else {
- // moveToVisualPosition(oldPosition);
- //}
}
-
- myVisualLineStart = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line, 0)));
- myVisualLineEnd = myEditor.logicalPositionToOffset(myEditor.visualToLogicalPosition(new VisualPosition(myVisibleCaret.line + 1, 0)));
- }
-
- private void finishUpdate() {
- myIsInUpdate = false;
- }
-
- private boolean needToShiftWhiteSpaces(final DocumentEvent e) {
- if (!CharArrayUtil.containsOnlyWhiteSpaces(e.getNewFragment()) || CharArrayUtil.containLineBreaks(e.getNewFragment()))
- return e.getOldLength() > 0;
- if (e.getOffset() == 0) return false;
- final char charBefore = myEditor.getDocument().getCharsSequence().charAt(e.getOffset() - 1);
- //final char charAfter = myEditor.getDocument().getCharsSequence().charAt(e.getOffset() + e.getNewLength());
- return Character.isWhitespace(charBefore)/* || !Character.isWhitespace(charAfter)*/;
+ fireCaretRemoved(caret);
+ Disposer.dispose(caret);
+ return true;
}
@Override
- public void beforeDocumentChange(DocumentEvent e) {
- myIsInUpdate = true;
+ public void removeSecondaryCarets() {
+ myEditor.assertIsDispatchThread();
+ if (!supportsMultipleCarets()) {
+ return;
+ }
+ ListIterator<CaretImpl> caretIterator = myCarets.listIterator(myCarets.size() - 1);
+ while (caretIterator.hasPrevious()) {
+ CaretImpl caret = caretIterator.previous();
+ synchronized (myCarets) {
+ caretIterator.remove();
+ }
+ fireCaretRemoved(caret);
+ Disposer.dispose(caret);
+ }
}
@Override
- public int getPriority() {
- return EditorDocumentPriorities.CARET_MODEL;
- }
-
- private void setCurrentLogicalCaret(@NotNull LogicalPosition position) {
- myLogicalCaret = position;
- myCaretInfo = createVerticalInfo(position);
- }
-
- @NotNull
- private VerticalInfo createVerticalInfo(LogicalPosition position) {
- Document document = myEditor.getDocument();
- int logicalLine = position.line;
- if (logicalLine >= document.getLineCount()) {
- logicalLine = Math.max(0, document.getLineCount() - 1);
+ public void runForEachCaret(@NotNull final CaretAction action) {
+ myEditor.assertIsDispatchThread();
+ if (!supportsMultipleCarets()) {
+ action.perform(getPrimaryCaret());
+ return;
}
- int startOffset = document.getLineStartOffset(logicalLine);
- int endOffset = document.getLineEndOffset(logicalLine);
-
- // There is a possible case that active logical line is represented on multiple lines due to soft wraps processing.
- // We want to highlight those visual lines as 'active' then, so, we calculate 'y' position for the logical line start
- // and height in accordance with the number of occupied visual lines.
- VisualPosition visualPosition = myEditor.offsetToVisualPosition(document.getLineStartOffset(logicalLine));
- int y = myEditor.visualPositionToXY(visualPosition).y;
- int lineHeight = myEditor.getLineHeight();
- int height = lineHeight;
- List<? extends SoftWrap> softWraps = myEditor.getSoftWrapModel().getSoftWrapsForRange(startOffset, endOffset);
- for (SoftWrap softWrap : softWraps) {
- height += StringUtil.countNewLines(softWrap.getText()) * lineHeight;
+ if (myCurrentCaret != null) {
+ throw new IllegalStateException("Current caret is defined, cannot operate on other ones");
}
-
- return new VerticalInfo(y, height);
+ doWithCaretMerging(new Runnable() {
+ public void run() {
+ try {
+ Collection<Caret> sortedCarets = getAllCarets();
+ for (Caret caret : sortedCarets) {
+ myCurrentCaret = (CaretImpl)caret;
+ action.perform(caret);
+ }
+ }
+ finally {
+ myCurrentCaret = null;
+ }
+ }
+ });
}
@Override
- public void dispose() {
- releaseBulkCaretMarker();
+ public void runBatchCaretOperation(@NotNull Runnable runnable) {
+ myEditor.assertIsDispatchThread();
+ doWithCaretMerging(runnable);
}
- /**
- * Encapsulates information about target vertical range info - its <code>'y'</code> coordinate and height in pixels.
- */
- public static class VerticalInfo {
- public final int y;
- public final int height;
+ private void mergeOverlappingCaretsAndSelections() {
+ if (!supportsMultipleCarets() || myCarets.size() <= 1) {
+ return;
+ }
+ LinkedList<CaretImpl> carets = new LinkedList<CaretImpl>(myCarets);
+ Collections.sort(carets, CaretPositionComparator.INSTANCE);
+ ListIterator<CaretImpl> it = carets.listIterator();
+ while (it.hasNext()) {
+ CaretImpl prevCaret = null;
+ if (it.hasPrevious()) {
+ prevCaret = it.previous();
+ it.next();
+ }
+ CaretImpl currCaret = it.next();
+ if (prevCaret != null && (currCaret.getVisualPosition().equals(prevCaret.getVisualPosition())
+ || regionsIntersect(currCaret.getSelectionStart(), currCaret.getSelectionEnd(),
+ prevCaret.getSelectionStart(), prevCaret.getSelectionEnd()))) {
+ int newSelectionStart = Math.min(currCaret.getSelectionStart(), prevCaret.getSelectionStart());
+ int newSelectionEnd = Math.max(currCaret.getSelectionEnd(), prevCaret.getSelectionEnd());
+ CaretImpl toRetain, toRemove;
+ if (currCaret.getOffset() >= prevCaret.getSelectionStart() && currCaret.getOffset() <= prevCaret.getSelectionEnd()) {
+ toRetain = prevCaret;
+ toRemove = currCaret;
+ it.remove();
+ it.previous();
+ }
+ else {
+ toRetain = currCaret;
+ toRemove = prevCaret;
+ it.previous();
+ it.previous();
+ it.remove();
+ }
+ removeCaret(toRemove);
+ if (newSelectionStart < newSelectionEnd) {
+ toRetain.setSelection(newSelectionStart, newSelectionEnd);
+ }
+ }
+ }
+ }
- private VerticalInfo(int y, int height) {
- this.y = y;
- this.height = height;
+ 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;
+ }
+
+ void doWithCaretMerging(Runnable runnable) {
+ if (myPerformCaretMergingAfterCurrentOperation) {
+ runnable.run();
+ }
+ else {
+ myPerformCaretMergingAfterCurrentOperation = true;
+ try {
+ runnable.run();
+ }
+ finally {
+ myPerformCaretMergingAfterCurrentOperation = false;
+ }
+ mergeOverlappingCaretsAndSelections();
+ }
+ }
+
+ @Override
+ public void setCarets(@NotNull final List<LogicalPosition> caretPositions, @NotNull final List<? extends Segment> selections) {
+ myEditor.assertIsDispatchThread();
+ if (caretPositions.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) {
+ CaretImpl caret;
+ boolean caretAdded;
+ if (index++ < oldCaretCount) {
+ caret = caretIterator.next();
+ caretAdded = false;
+ }
+ else {
+ caret = new CaretImpl(myEditor);
+ caret.moveToLogicalPosition(caretPosition, false, null, false);
+ synchronized (myCarets) {
+ myCarets.add(caret);
+ }
+ fireCaretAdded(caret);
+ caretAdded = true;
+ }
+ if (caretPosition != null && !caretAdded) {
+ caret.moveToLogicalPosition(caretPosition);
+ }
+ Segment selection = selectionIterator.next();
+ if (selection != null) {
+ caret.setSelection(selection.getStartOffset(), selection.getEndOffset());
+ }
+ }
+ int caretsToRemove = myCarets.size() - caretPositions.size();
+ for (int i = 0; i < caretsToRemove; i++) {
+ CaretImpl caret;
+ synchronized (myCarets) {
+ caret = myCarets.removeLast();
+ }
+ fireCaretRemoved(caret);
+ Disposer.dispose(caret);
+ }
+ }
+ });
+ }
+
+ void fireCaretPositionChanged(CaretEvent caretEvent) {
+ myCaretListeners.getMulticaster().caretPositionChanged(caretEvent);
+ }
+
+ void fireCaretAdded(@NotNull Caret caret) {
+ myCaretListeners.getMulticaster().caretAdded(new CaretEvent(myEditor, caret, caret.getLogicalPosition(), caret.getLogicalPosition()));
+ }
+
+ void fireCaretRemoved(@NotNull Caret caret) {
+ myCaretListeners.getMulticaster().caretRemoved(new CaretEvent(myEditor, caret, caret.getLogicalPosition(), caret.getLogicalPosition()));
+ }
+
+ private static class VisualPositionComparator implements Comparator<VisualPosition> {
+ private static final VisualPositionComparator INSTANCE = new VisualPositionComparator();
+
+ @Override
+ public int compare(VisualPosition o1, VisualPosition o2) {
+ if (o1.line != o2.line) {
+ return o1.line - o2.line;
+ }
+ return o1.column - o2.column;
+ }
+ }
+
+ private static class CaretPositionComparator implements Comparator<Caret> {
+ private static final CaretPositionComparator INSTANCE = new CaretPositionComparator();
+
+ @Override
+ public int compare(Caret o1, Caret o2) {
+ return VisualPositionComparator.INSTANCE.compare(o1.getVisualPosition(), o2.getVisualPosition());
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/DisplayedFoldingAnchor.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DisplayedFoldingAnchor.java
new file mode 100644
index 0000000..d5f70dc
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/DisplayedFoldingAnchor.java
@@ -0,0 +1,34 @@
+/*
+ * 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.openapi.editor.impl;
+
+import com.intellij.openapi.editor.FoldRegion;
+
+class DisplayedFoldingAnchor {
+ enum Type {COLLAPSED, EXPANDED_TOP, EXPANDED_BOTTOM}
+
+ public final FoldRegion foldRegion;
+ public final int visualLine;
+ public final int foldRegionVisualLines;
+ public final Type type;
+
+ DisplayedFoldingAnchor(FoldRegion foldRegion, int visualLine, int foldRegionVisualLines, Type type) {
+ this.foldRegion = foldRegion;
+ this.visualLine = visualLine;
+ this.foldRegionVisualLines = foldRegionVisualLines;
+ this.type = type;
+ }
+}
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 745d40f..2b3ae68 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
@@ -73,10 +73,8 @@
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
-import java.util.ArrayList;
+import java.util.*;
import java.util.List;
-import java.util.Map;
-import java.util.TreeMap;
class EditorGutterComponentImpl extends EditorGutterComponentEx implements MouseListener, MouseMotionListener {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorGutterComponentImpl");
@@ -86,6 +84,7 @@
private static final TooltipGroup GUTTER_TOOLTIP_GROUP = new TooltipGroup("GUTTER_TOOLTIP_GROUP", 0);
private final EditorImpl myEditor;
+ private final FoldingAnchorsOverlayStrategy myAnchorsDisplayStrategy;
private int myLineMarkerAreaWidth = START_ICON_AREA_WIDTH + FREE_PAINTERS_AREA_WIDTH;
private int myIconsAreaWidth = START_ICON_AREA_WIDTH;
private int myLineNumberAreaWidth = 0;
@@ -118,6 +117,7 @@
}
});
}
+ myAnchorsDisplayStrategy = new FoldingAnchorsOverlayStrategy(editor);
}
@SuppressWarnings({"ConstantConditions"})
@@ -237,7 +237,8 @@
try {
int firstVisibleOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, clip.y - myEditor.getLineHeight())));
int lastVisibleOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, clip.y + clip.height + myEditor.getLineHeight())));
- paintFoldingBackground(g, clip, firstVisibleOffset, lastVisibleOffset);
+ paintFoldingBackground(g, clip);
+ paintFoldingLines((Graphics2D)g, clip);
paintLineMarkers(g, clip, firstVisibleOffset, lastVisibleOffset);
paintFoldingTree(g, clip, firstVisibleOffset, lastVisibleOffset);
paintLineNumbers(g, clip);
@@ -339,7 +340,7 @@
doPaintFoldingTree((Graphics2D)g, clip, firstVisibleOffset, lastVisibleOffset);
}
else {
- UIUtil.drawVDottedLine((Graphics2D)g, clip.x + clip.width -1, clip.y, clip.y + clip.height, null, getOutlineColor(false));
+ UIUtil.drawVDottedLine((Graphics2D)g, clip.x + clip.width - 1, clip.y, clip.y + clip.height, null, getOutlineColor(false));
}
}
@@ -816,51 +817,18 @@
updateSize();
}
- private int offsetToVisualLine(int offset) {
- offset = Math.min(myEditor.getDocument().getTextLength() - 1, offset);
- return myEditor.offsetToVisualLine(offset);
- }
-
private void doPaintFoldingTree(final Graphics2D g, final Rectangle clip, int firstVisibleOffset, int lastVisibleOffset) {
final int anchorX = getFoldingAreaOffset();
final int width = getFoldingAnchorWidth();
- doForVisibleFoldRegions(
- new NullableFunction<FoldRegion, Void>() {
- @Override
- public Void fun(FoldRegion foldRegion) {
- drawAnchor(foldRegion, width, clip, g, anchorX, false, false);
- return null;
- }
- },
- firstVisibleOffset,
- lastVisibleOffset
- );
-
- if (myActiveFoldRegion != null) {
- drawAnchor(myActiveFoldRegion, width, clip, g, anchorX, true, true);
- drawAnchor(myActiveFoldRegion, width, clip, g, anchorX, true, false);
+ Collection<DisplayedFoldingAnchor> anchorsToDisplay =
+ myAnchorsDisplayStrategy.getAnchorsToDisplay(firstVisibleOffset, lastVisibleOffset, myActiveFoldRegion);
+ for (DisplayedFoldingAnchor anchor : anchorsToDisplay) {
+ drawAnchor(width, clip, g, anchorX, anchor.visualLine, anchor.type, anchor.foldRegion == myActiveFoldRegion);
}
}
- private void doForVisibleFoldRegions(@NotNull NullableFunction<FoldRegion, Void> action, int firstVisibleOffset, int lastVisibleOffset) {
- FoldRegion[] visibleFoldRegions = myEditor.getFoldingModel().fetchVisible();
- final Document document = myEditor.getDocument();
- for (FoldRegion visibleFoldRegion : visibleFoldRegions) {
- if (!visibleFoldRegion.isValid()) continue;
- final int startOffset = visibleFoldRegion.getStartOffset();
- if (startOffset > lastVisibleOffset) continue;
- final int endOffset = getEndOffset(visibleFoldRegion);
- if (endOffset < firstVisibleOffset) continue;
- if (document.getLineNumber(startOffset) >= document.getLineNumber(endOffset)) {
- //TODO den remove this check as soon as editor performance on dimension mapping is improved (IDEA-69317)
- continue;
- }
- action.fun(visibleFoldRegion);
- }
- }
-
- private void paintFoldingBackground(Graphics g, Rectangle clip, int firstVisibleOffset, int lastVisibleOffset) {
+ private void paintFoldingBackground(Graphics g, Rectangle clip) {
int lineX = getWhitespaceSeparatorOffset();
paintBackground(g, clip, getFoldingAreaOffset(), getFoldingAreaWidth());
@@ -868,11 +836,9 @@
g.fillRect(lineX, clip.y, getFoldingAreaWidth(), clip.height);
paintCaretRowBackground(g, lineX, getFoldingAnchorWidth());
-
- doPaintFoldingBoxBackground((Graphics2D)g, clip, firstVisibleOffset, lastVisibleOffset);
}
- private void doPaintFoldingBoxBackground(final Graphics2D g, final Rectangle clip, int firstVisibleOffset, int lastVisibleOffset) {
+ private void paintFoldingLines(final Graphics2D g, final Rectangle clip) {
if (!isFoldingOutlineShown()) return;
UIUtil.drawVDottedLine(g, getWhitespaceSeparatorOffset(), clip.y, clip.y + clip.height, null, getOutlineColor(false));
@@ -880,21 +846,20 @@
final int anchorX = getFoldingAreaOffset();
final int width = getFoldingAnchorWidth();
- if (myActiveFoldRegion != null) {
- drawFoldingLines(myActiveFoldRegion, clip, width, anchorX, g);
- }
+ if (myActiveFoldRegion != null && myActiveFoldRegion.isExpanded() && myActiveFoldRegion.isValid()) {
+ int foldStart = myEditor.offsetToVisualLine(myActiveFoldRegion.getStartOffset());
+ int foldEnd = myEditor.offsetToVisualLine(getEndOffset(myActiveFoldRegion));
+ int startY = myEditor.visibleLineToY(foldStart + 1) - myEditor.getDescent();
+ int endY = myEditor.visibleLineToY(foldEnd) + myEditor.getLineHeight() -
+ myEditor.getDescent();
- doForVisibleFoldRegions(
- new NullableFunction<FoldRegion, Void>() {
- @Override
- public Void fun(FoldRegion foldRegion) {
- drawAnchor(foldRegion, width, clip, g, anchorX, false, true);
- return null;
- }
- },
- firstVisibleOffset,
- lastVisibleOffset
- );
+ if (startY <= clip.y + clip.height && endY + 1 + myEditor.getDescent() >= clip.y) {
+ int lineX = anchorX + width / 2;
+
+ g.setColor(getOutlineColor(true));
+ UIUtil.drawLine(g, lineX, startY, lineX, endY);
+ }
+ }
}
@Override
@@ -911,52 +876,35 @@
public int getHeadCenterY(FoldRegion foldRange) {
int width = getFoldingAnchorWidth();
- int foldStart = offsetToVisualLine(foldRange.getStartOffset());
+ int foldStart = myEditor.offsetToVisualLine(foldRange.getStartOffset());
return myEditor.visibleLineToY(foldStart) + myEditor.getLineHeight() - myEditor.getDescent() - width / 2;
}
- private void drawAnchor(FoldRegion foldRange, int width, Rectangle clip, Graphics2D g,
- int anchorX, boolean active, boolean paintBackground) {
- if (!foldRange.isValid()) {
- return;
- }
- int startOffset = foldRange.getStartOffset();
+ private void drawAnchor(int width, Rectangle clip, Graphics2D g, int anchorX, int visualLine,
+ DisplayedFoldingAnchor.Type type, boolean active) {
- final int endOffset = getEndOffset(foldRange);
- if (!isFoldingPossible(startOffset, endOffset)) {
- return;
- }
-
- int foldStart = offsetToVisualLine(startOffset);
- int y = myEditor.visibleLineToY(foldStart) + myEditor.getLineHeight() - myEditor.getDescent() -
- width;
int height = width + 2;
-
- final FoldingGroup group = foldRange.getGroup();
-
- final boolean drawTop = group == null || myEditor.getFoldingModel().getFirstRegion(group, foldRange) == foldRange;
- if (!foldRange.isExpanded()) {
- if (y <= clip.y + clip.height && y + height >= clip.y) {
- if (drawTop) {
- drawSquareWithPlus(g, anchorX, y, width, active, paintBackground);
+ int y;
+ switch (type) {
+ case COLLAPSED:
+ y = myEditor.visibleLineToY(visualLine) + myEditor.getLineHeight() - myEditor.getDescent() - width;
+ if (y <= clip.y + clip.height && y + height >= clip.y) {
+ drawSquareWithPlus(g, anchorX, y, width, active);
}
- }
- }
- else {
- int foldEnd = offsetToVisualLine(endOffset);
- int endY = myEditor.visibleLineToY(foldEnd) + myEditor.getLineHeight() -
- myEditor.getDescent();
-
- if (y <= clip.y + clip.height && y + height >= clip.y) {
- if (drawTop) {
- drawDirectedBox(g, anchorX, y, width, height, width - 2, active, paintBackground);
+ break;
+ case EXPANDED_TOP:
+ y = myEditor.visibleLineToY(visualLine) + myEditor.getLineHeight() - myEditor.getDescent() - width;
+ if (y <= clip.y + clip.height && y + height >= clip.y) {
+ drawDirectedBox(g, anchorX, y, width, height, width - 2, active);
}
- }
-
- if (endY - height <= clip.y + clip.height && endY >= clip.y) {
- drawDirectedBox(g, anchorX, endY, width, -height, -width + 2, active, paintBackground);
- }
+ break;
+ case EXPANDED_BOTTOM:
+ y = myEditor.visibleLineToY(visualLine) + myEditor.getLineHeight() - myEditor.getDescent();
+ if (y - height <= clip.y + clip.height && y >= clip.y) {
+ drawDirectedBox(g, anchorX, y, width, -height, -width + 2, active);
+ }
+ break;
}
}
@@ -972,7 +920,7 @@
int width,
int height,
int baseHeight,
- boolean active, boolean paintBackground) {
+ boolean active) {
Object antialiasing = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
if (SystemInfo.isMac && SystemInfo.JAVA_VERSION.startsWith("1.4.1") || UIUtil.isRetina()) {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
@@ -982,19 +930,15 @@
int[] xPoints = {anchorX, anchorX + width, anchorX + width, anchorX + width / 2, anchorX};
int[] yPoints = {y, y, y + baseHeight, y + height, y + baseHeight};
- if (paintBackground) {
- g.setColor(myEditor.getBackgroundColor());
+ g.setColor(myEditor.getBackgroundColor());
+ g.fillPolygon(xPoints, yPoints, 5);
- g.fillPolygon(xPoints, yPoints, 5);
- }
- else {
- g.setColor(getOutlineColor(active));
- g.drawPolygon(xPoints, yPoints, 5);
+ g.setColor(getOutlineColor(active));
+ g.drawPolygon(xPoints, yPoints, 5);
- //Minus
- int minusHeight = y + baseHeight / 2 + (height - baseHeight) / 4;
- UIUtil.drawLine(g, anchorX + 2, minusHeight, anchorX + width - 2, minusHeight);
- }
+ //Minus
+ int minusHeight = y + baseHeight / 2 + (height - baseHeight) / 4;
+ UIUtil.drawLine(g, anchorX + 2, minusHeight, anchorX + width - 2, minusHeight);
}
finally {
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialiasing);
@@ -1005,9 +949,8 @@
int anchorX,
int y,
int width,
- boolean active,
- boolean paintBackground) {
- drawSquareWithMinus(g, anchorX, y, width, active, paintBackground);
+ boolean active) {
+ drawSquareWithMinus(g, anchorX, y, width, active);
UIUtil.drawLine(g, anchorX + width / 2, y + 2, anchorX + width / 2, y + width - 2);
}
@@ -1017,37 +960,16 @@
int anchorX,
int y,
int width,
- boolean active,
- boolean paintBackground) {
- if (paintBackground) {
- g.setColor(myEditor.getBackgroundColor());
- g.fillRect(anchorX, y, width, width);
- }
- else {
- g.setColor(getOutlineColor(active));
- g.drawRect(anchorX, y, width, width);
+ boolean active) {
+ g.setColor(myEditor.getBackgroundColor());
+ g.fillRect(anchorX, y, width, width);
- // Draw plus
- if (!active) g.setColor(getOutlineColor(true));
- UIUtil.drawLine(g, anchorX + 2, y + width / 2, anchorX + width - 2, y + width / 2);
- }
- }
+ g.setColor(getOutlineColor(active));
+ g.drawRect(anchorX, y, width, width);
- private void drawFoldingLines(FoldRegion foldRange, Rectangle clip, int width, int anchorX, Graphics2D g) {
- if (foldRange.isExpanded() && foldRange.isValid()) {
- int foldStart = offsetToVisualLine(foldRange.getStartOffset());
- int foldEnd = offsetToVisualLine(getEndOffset(foldRange));
- int startY = myEditor.visibleLineToY(foldStart + 1) - myEditor.getDescent();
- int endY = myEditor.visibleLineToY(foldEnd) + myEditor.getLineHeight() -
- myEditor.getDescent();
-
- if (startY > clip.y + clip.height || endY + 1 + myEditor.getDescent() < clip.y) return;
-
- int lineX = anchorX + width / 2;
-
- g.setColor(getOutlineColor(true));
- UIUtil.drawLine(g, lineX, startY, lineX, endY);
- }
+ // Draw plus
+ if (!active) g.setColor(getOutlineColor(true));
+ UIUtil.drawLine(g, anchorX + 2, y + width / 2, anchorX + width - 2, y + width / 2);
}
private int getFoldingAnchorWidth() {
@@ -1135,55 +1057,17 @@
int anchorX = getFoldingAreaOffset();
int anchorWidth = getFoldingAnchorWidth();
- FoldRegion[] visibleRanges = myEditor.getFoldingModel().fetchVisible();
- for (FoldRegion foldRange : visibleRanges) {
- if (!foldRange.isValid()) continue;
- final FoldingGroup group = foldRange.getGroup();
- if (group != null && myEditor.getFoldingModel().getFirstRegion(group, foldRange) != foldRange) {
- continue;
- }
+ int neighbourhoodStartOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, y - myEditor.getLineHeight())));
+ int neighbourhoodEndOffset = myEditor.logicalPositionToOffset(myEditor.xyToLogicalPosition(new Point(0, y + myEditor.getLineHeight())));
- int foldStart = offsetToVisualLine(foldRange.getStartOffset());
- final int endOffset = getEndOffset(foldRange);
- int foldEnd = offsetToVisualLine(endOffset);
- if (!isFoldingPossible(foldRange.getStartOffset(), endOffset)) {
- continue;
- }
-
- if (rectangleByFoldOffset(foldStart, anchorWidth, anchorX).contains(x, y)) return foldRange;
- if ((group == null || foldRange.isExpanded()) && rectangleByFoldOffset(foldEnd, anchorWidth, anchorX).contains(x, y)) return foldRange;
+ Collection<DisplayedFoldingAnchor> displayedAnchors = myAnchorsDisplayStrategy.getAnchorsToDisplay(neighbourhoodStartOffset, neighbourhoodEndOffset, null);
+ for (DisplayedFoldingAnchor anchor : displayedAnchors) {
+ if (rectangleByFoldOffset(anchor.visualLine, anchorWidth, anchorX).contains(x, y)) return anchor.foldRegion;
}
return null;
}
- /**
- * Allows to answer if there may be folding for the given offsets.
- * <p/>
- * The rule is that we can fold range that occupies multiple logical or visual lines.
- *
- * @param startOffset start offset of the target region to check
- * @param endOffset end offset of the target region to check
- * @return
- */
- private boolean isFoldingPossible(int startOffset, int endOffset) {
- Document document = myEditor.getDocument();
- if (startOffset >= document.getTextLength()) {
- return false;
- }
-
- int endOffsetToUse = Math.min(endOffset, document.getTextLength());
- if (endOffsetToUse <= startOffset) {
- return false;
- }
-
- if (document.getLineNumber(startOffset) != document.getLineNumber(endOffsetToUse)) {
- return true;
- }
- return myEditor.getSettings().isAllowSingleLogicalLineFolding()
- && !myEditor.getSoftWrapModel().getSoftWrapsForRange(startOffset, endOffsetToUse).isEmpty();
- }
-
@SuppressWarnings("SuspiciousNameCombination")
private Rectangle rectangleByFoldOffset(int foldStart, int anchorWidth, int anchorX) {
int anchorY = myEditor.visibleLineToY(foldStart) + myEditor.getLineHeight() -
@@ -1426,14 +1310,20 @@
@Override
@Nullable
- public Point getPoint(GutterIconRenderer renderer) {
+ public Point getPoint(final GutterIconRenderer renderer) {
+ final Ref<Point> result = Ref.create();
for (int line : myLineToGutterRenderers.keys()) {
- for (GutterMark gutterIconRenderer : myLineToGutterRenderers.get(line)) {
- if (gutterIconRenderer.equals(renderer)) {
- int x = getLineMarkerAreaOffset() + 1;
- final int y = myEditor.logicalPositionToXY(new LogicalPosition(line, 0)).y;
- return new Point(x, y);
+ processIconsRow(line, myLineToGutterRenderers.get(line), new LineGutterIconRendererProcessor() {
+ @Override
+ public void process(int x, int y, GutterMark r) {
+ if (result.isNull() && r.equals(renderer)) {
+ result.set(new Point(x, y));
+ }
}
+ });
+
+ if (!result.isNull()) {
+ return result.get();
}
}
return null;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
index a90d575..c1499a7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorHighlighterCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
import com.intellij.openapi.editor.ex.util.LexerEditorHighlighter;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
import com.intellij.openapi.util.Key;
+import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,7 +44,7 @@
return null;
}
final WeakReference<EditorHighlighter> editorHighlighterWeakReference = document.getUserData(ourSomeEditorSyntaxHighlighter);
- final EditorHighlighter someEditorHighlighter = editorHighlighterWeakReference != null ? editorHighlighterWeakReference.get() : null;
+ final EditorHighlighter someEditorHighlighter = SoftReference.dereference(editorHighlighterWeakReference);
if (someEditorHighlighter instanceof LexerEditorHighlighter &&
((LexerEditorHighlighter)someEditorHighlighter).isValid()
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 c126a15..fc68bf4 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
@@ -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,7 +17,6 @@
import com.intellij.Patches;
import com.intellij.application.options.OptionsConstants;
-import com.intellij.codeInsight.daemon.GutterMark;
import com.intellij.codeInsight.hint.DocumentFragmentTooltipRenderer;
import com.intellij.codeInsight.hint.EditorFragmentComponent;
import com.intellij.codeInsight.hint.TooltipController;
@@ -56,7 +55,6 @@
import com.intellij.openapi.editor.impl.event.MarkupModelListener;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapAppliancePlaces;
import com.intellij.openapi.editor.impl.softwrap.SoftWrapDrawingType;
-import com.intellij.openapi.editor.impl.softwrap.SoftWrapHelper;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
@@ -87,6 +85,7 @@
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Convertor;
import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.text.CharArrayCharSequence;
import com.intellij.util.text.CharArrayUtil;
import com.intellij.util.ui.ButtonlessScrollBarUI;
import com.intellij.util.ui.GraphicsUtil;
@@ -98,7 +97,6 @@
import gnu.trove.TIntIntHashMap;
import org.intellij.lang.annotations.JdkConstants;
import org.intellij.lang.annotations.MagicConstant;
-import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -160,10 +158,10 @@
ComplementaryFontsRegistry.getFontAbleToDisplay(' ', 0, 0, UIManager.getFont("Label.font").getFamily()); // load costly font info
}
- private final CommandProcessor myCommandProcessor;
- @NotNull private final MyScrollBar myVerticalScrollBar;
+ private final CommandProcessor myCommandProcessor;
+ @NotNull private final MyScrollBar myVerticalScrollBar;
- private final List<EditorMouseListener> myMouseListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final List<EditorMouseListener> myMouseListeners = ContainerUtil.createLockFreeCopyOnWriteList();
@NotNull private final List<EditorMouseMotionListener> myMouseMotionListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private int myCharHeight = -1;
@@ -195,15 +193,16 @@
private final PropertyChangeSupport myPropertyChangeSupport = new PropertyChangeSupport(this);
private MyEditable myEditable;
- private EditorColorsScheme myScheme;
- private ArrowPainter myTabPainter;
- private final boolean myIsViewer;
- @NotNull private final SelectionModelImpl mySelectionModel;
+ @NotNull
+ private EditorColorsScheme myScheme;
+ private ArrowPainter myTabPainter;
+ private final boolean myIsViewer;
+ @NotNull private final SelectionModelImpl mySelectionModel;
@NotNull private final EditorMarkupModelImpl myMarkupModel;
- @NotNull private final FoldingModelImpl myFoldingModel;
- @NotNull private final ScrollingModelImpl myScrollingModel;
- @NotNull private final CaretModelImpl myCaretModel;
- @NotNull private final SoftWrapModelImpl mySoftWrapModel;
+ @NotNull private final FoldingModelImpl myFoldingModel;
+ @NotNull private final ScrollingModelImpl myScrollingModel;
+ @NotNull private final CaretModelImpl myCaretModel;
+ @NotNull private final SoftWrapModelImpl mySoftWrapModel;
@NotNull private static final RepaintCursorCommand ourCaretBlinkingCommand;
private MessageBusConnection myConnection;
@@ -216,6 +215,7 @@
private static final int MOUSE_SELECTION_STATE_LINE_SELECTED = 2;
private EditorHighlighter myHighlighter;
+ private Disposable myHighlighterDisposable = Disposer.newDisposable();
private final TextDrawingCallback myTextDrawingCallback = new MyTextDrawingCallback();
@MagicConstant(intValues = {VERTICAL_SCROLLBAR_LEFT, VERTICAL_SCROLLBAR_RIGHT})
@@ -234,31 +234,31 @@
private final EditorSizeContainer mySizeContainer = new EditorSizeContainer();
private boolean myUpdateCursor;
- private int myCaretUpdateVShift;
+ private int myCaretUpdateVShift;
@Nullable
private final Project myProject;
- private long myMouseSelectionChangeTimestamp;
- private int mySavedCaretOffsetForDNDUndoHack;
+ private long myMouseSelectionChangeTimestamp;
+ private int mySavedCaretOffsetForDNDUndoHack;
private final List<FocusChangeListener> myFocusListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private MyInputMethodHandler myInputMethodRequestsHandler;
- private InputMethodRequests myInputMethodRequestsSwingWrapper;
- private boolean myIsOneLineMode;
- private boolean myIsRendererMode;
- private VirtualFile myVirtualFile;
- private boolean myIsColumnMode = false;
- @Nullable private Color myForcedBackground = null;
+ private InputMethodRequests myInputMethodRequestsSwingWrapper;
+ private boolean myIsOneLineMode;
+ private boolean myIsRendererMode;
+ private VirtualFile myVirtualFile;
+ private boolean myIsColumnMode = false;
+ @Nullable private Color myForcedBackground = null;
@Nullable private Dimension myPreferredSize;
- private int myVirtualPageHeight;
+ private int myVirtualPageHeight;
@Nullable private Runnable myGutterSizeUpdater = null;
- private boolean myGutterNeedsUpdate = false;
+ private boolean myGutterNeedsUpdate = false;
private Alarm myAppleRepaintAlarm;
private final Alarm myMouseSelectionStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
private Runnable myMouseSelectionStateResetRunnable;
- private boolean myEmbeddedIntoDialogWrapper;
+ private boolean myEmbeddedIntoDialogWrapper;
@Nullable private CachedFontContent myLastCache;
private int myDragOnGutterSelectionStartLine = -1;
@@ -270,7 +270,7 @@
/**
* There is a possible case that specific font is used for particular text drawing operation (e.g. for 'before' and 'after'
- * soft wraps drawings). Hence, even if {@link #mySpacesHaveSameWidth} is <code>true</code>, space size for that specific
+ * soft wraps drawings). Hence, even if mySpacesHaveSameWidth is <code>true</code>, space size for that specific
* font may be different. So, we define additional flag that should indicate that {@link #myLastCache} should be reset.
*/
private boolean myForceRefreshFont;
@@ -283,28 +283,34 @@
@NotNull private final JPanel myHeaderPanel;
@Nullable private MouseEvent myInitialMouseEvent;
- private boolean myIgnoreMouseEventsConsecutiveToInitial;
+ private boolean myIgnoreMouseEventsConsecutiveToInitial;
private EditorDropHandler myDropHandler;
- private char[] myPrefixText;
- private TextAttributes myPrefixAttributes;
- private int myPrefixWidthInPixels;
- @NotNull private final IndentsModel myIndentsModel;
+ private char[] myPrefixText;
+ private TextAttributes myPrefixAttributes;
+ private int myPrefixWidthInPixels;
+ @NotNull private final IndentsModel myIndentsModel;
@Nullable
private CharSequence myPlaceholderText;
- private int myLastPaintedPlaceholderWidth;
+ private int myLastPaintedPlaceholderWidth;
private boolean myStickySelection;
- private int myStickySelectionStart;
+ private int myStickySelectionStart;
private boolean myScrollToCaret = true;
private boolean myPurePaintingMode;
private boolean myPaintSelection;
private final EditorSizeAdjustmentStrategy mySizeAdjustmentStrategy = new EditorSizeAdjustmentStrategy();
- private final Disposable myDisposable = Disposer.newDisposable();
+ private final Disposable myDisposable = Disposer.newDisposable();
+
+ private LogicalPosition myLastMousePressedLocation;
+ private VisualPosition myTargetMultiSelectionPosition;
+ private boolean myMultiSelectionInProgress;
+
+ private CaretImpl myPrimaryCaret;
static {
ourCaretBlinkingCommand = new RepaintCursorCommand();
@@ -334,18 +340,24 @@
}
MarkupModelListener markupModelListener = new MarkupModelListener() {
+ private boolean areRenderersInvolved(@NotNull RangeHighlighterEx highlighter) {
+ return highlighter.getCustomRenderer() != null ||
+ highlighter.getGutterIconRenderer() != null ||
+ highlighter.getLineMarkerRenderer() != null ||
+ highlighter.getLineSeparatorRenderer() != null;
+ }
@Override
public void afterAdded(@NotNull RangeHighlighterEx highlighter) {
- attributesChanged(highlighter);
+ attributesChanged(highlighter, areRenderersInvolved(highlighter));
}
@Override
public void beforeRemoved(@NotNull RangeHighlighterEx highlighter) {
- attributesChanged(highlighter);
+ attributesChanged(highlighter, areRenderersInvolved(highlighter));
}
@Override
- public void attributesChanged(@NotNull RangeHighlighterEx highlighter) {
+ public void attributesChanged(@NotNull RangeHighlighterEx highlighter, boolean renderersChanged) {
if (myDocument.isInBulkUpdate()) return; // bulkUpdateFinished() will repaint anything
int textLength = myDocument.getTextLength();
@@ -355,14 +367,13 @@
int startLine = start == -1 ? 0 : myDocument.getLineNumber(start);
int endLine = end == -1 ? myDocument.getLineCount() : myDocument.getLineNumber(end);
repaintLines(Math.max(0, startLine - 1), Math.min(endLine + 1, getDocument().getLineCount()));
- GutterMark renderer = highlighter.getGutterIconRenderer();
// optimization: there is no need to repaint error stripe if the highlighter is invisible on it
- if (renderer != null || highlighter.getErrorStripeMarkColor() != null) {
+ if (renderersChanged || highlighter.getErrorStripeMarkColor() != null) {
((EditorMarkupModelImpl)getMarkupModel()).repaint(start, end);
}
- if (renderer != null) {
+ if (renderersChanged) {
updateGutterSize();
}
updateCaretCursor();
@@ -379,10 +390,10 @@
myDocument.addDocumentListener(new EditorDocumentAdapter(), myCaretModel);
myDocument.addDocumentListener(mySoftWrapModel, myCaretModel);
- myFoldingModel.addListener(mySoftWrapModel);
+ myFoldingModel.addListener(mySoftWrapModel, myCaretModel);
myIndentsModel = new IndentsModelImpl(this);
- myCaretModel.addCaretListener(new CaretListener() {
+ myCaretModel.addCaretListener(new MultipleCaretListener() {
@Nullable private LightweightHint myCurrentHint = null;
@Nullable private IndentGuideDescriptor myCurrentCaretGuide = null;
@@ -415,6 +426,22 @@
}
}
}
+
+ @Override
+ public void caretAdded(CaretEvent e) {
+ if (myPrimaryCaret != null) {
+ myPrimaryCaret.updateVisualPosition(); // repainting old primary caret's row background
+ }
+ ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+ myPrimaryCaret = myCaretModel.getPrimaryCaret();
+ }
+
+ @Override
+ public void caretRemoved(CaretEvent e) {
+ ((CaretImpl)e.getCaret()).updateVisualPosition(); // repainting caret region
+ myPrimaryCaret = myCaretModel.getPrimaryCaret(); // repainting new primary caret's row background
+ myPrimaryCaret.updateVisualPosition();
+ }
});
myCaretCursor = new CaretCursor();
@@ -423,22 +450,10 @@
myScrollBarOrientation = VERTICAL_SCROLLBAR_RIGHT;
mySoftWrapModel.addSoftWrapChangeListener(new SoftWrapChangeListenerAdapter() {
-
@Override
public void recalculationEnds() {
- if (myCaretModel.isUpToDate()
- // There is a possible sequence of actions:
- // 1. Caret is inside expanded fold region;
- // 2. The region is collapsed;
- // 3. Soft wrap model is notified on fold model state change;
- // 4. This method is called on soft wrap recalculation end;
- // 5. Caret is moved to the current offset (which is inside fold region);
- // 6. The fold region is automatically expanded;
- // That's why we don't refresh caret position if it's inside collapsed fold region.
- && myFoldingModel.getCollapsedRegionAtOffset(myCaretModel.getOffset()) == null)
- {
- myCaretModel.moveToOffset(myCaretModel.getOffset());
- myScrollingModel.scrollToCaret(ScrollType.RELATIVE);
+ if (myCaretModel.isUpToDate()) {
+ myCaretModel.updateVisualPosition();
}
}
@@ -525,10 +540,7 @@
}
public static boolean isPresentationMode(Project project) {
- if (project != null && !project.isDefault()) {
- return PropertiesComponent.getInstance(project).isTrueValue("editor.presentation.mode");
- }
- return false;
+ return project != null && !project.isDefault() && PropertiesComponent.getInstance(project).isTrueValue("editor.presentation.mode");
}
@NotNull
@@ -702,16 +714,22 @@
myIgnoreMouseEventsConsecutiveToInitial = true;
}
- // There is a possible case that 'use soft wrap' setting value is changed and we need to repaint all affected lines then.
- repaintToScreenBottom(getCaretModel().getLogicalPosition().line);
- int y = getCaretModel().getVisualLineStart() * getLineHeight();
- myGutterComponent.repaint(0, y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - y);
- getCaretModel().moveToOffset(getCaretModel().getOffset());
+ if (myCaretModel.supportsMultipleCarets()) {
+ myCaretModel.updateVisualPosition();
+ }
+ else {
+ // There is a possible case that 'use soft wrap' setting value is changed and we need to repaint all affected lines then.
+ repaintToScreenBottom(getCaretModel().getLogicalPosition().line);
+ int y = getCaretModel().getVisualLineStart() * getLineHeight();
+ myGutterComponent.repaint(0, y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - y);
+ getCaretModel().moveToOffset(getCaretModel().getOffset());
+ }
}
private void initTabPainter() {
myTabPainter = new ArrowPainter(
ColorProvider.byColorsScheme(myScheme, EditorColors.WHITESPACES_COLOR),
+ new Computable.PredefinedValueComputable(EditorUtil.getSpaceWidth(Font.PLAIN, this)),
new Computable<Integer>() {
@Override
public Integer compute() {
@@ -733,9 +751,7 @@
myTraceableDisposable.kill(null);
isReleased = true;
- myDocument.removeDocumentListener(myHighlighter);
- myFoldingModel.removeListener(mySoftWrapModel);
myFoldingModel.dispose();
mySoftWrapModel.release();
@@ -755,6 +771,8 @@
clearCaretThread();
myFocusListeners.clear();
+ myMouseListeners.clear();
+ myMouseMotionListeners.clear();
if (myConnection != null) {
myConnection.disconnect();
@@ -771,9 +789,6 @@
}
private void initComponent() {
-// myStatusBar = new EditorStatusBarImpl();
-
- //myPanel.setLayout(new BoxLayout(myPanel, BoxLayout.Y_AXIS));
myPanel.setLayout(new BorderLayout());
myPanel.add(myHeaderPanel, BorderLayout.NORTH);
@@ -851,8 +866,10 @@
@Override
public void focusGained(FocusEvent e) {
myCaretCursor.activate();
- int caretLine = getCaretModel().getLogicalPosition().line;
- repaintLines(caretLine, caretLine);
+ for (Caret caret : myCaretModel.getAllCarets()) {
+ int caretLine = caret.getLogicalPosition().line;
+ repaintLines(caretLine, caretLine);
+ }
fireFocusGained();
if (myGutterNeedsUpdate) {
updateGutterSize();
@@ -862,8 +879,10 @@
@Override
public void focusLost(FocusEvent e) {
clearCaretThread();
- int caretLine = getCaretModel().getLogicalPosition().line;
- repaintLines(caretLine, caretLine);
+ for (Caret caret : myCaretModel.getAllCarets()) {
+ int caretLine = caret.getLogicalPosition().line;
+ repaintLines(caretLine, caretLine);
+ }
fireFocusLost();
}
});
@@ -880,7 +899,7 @@
public void dragOver(@NotNull DropTargetDragEvent e) {
Point location = e.getLocation();
- moveCaretToScreenPos(location.x, location.y);
+ getCaretModel().moveToLogicalPosition(getLogicalPositionForScreenPos(location.x, location.y, true));
getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
});
@@ -905,12 +924,39 @@
@Override
public void setFontSize(final int fontSize) {
+ setFontSize(fontSize, null);
+ }
+
+ /**
+ * Changes editor font size, attempting to keep a given point unmoved. If point is not given, top left screen corner is assumed.
+ *
+ * @param fontSize new font size
+ * @param zoomCenter zoom point, relative to viewport
+ */
+ private void setFontSize(final int fontSize, @Nullable Point zoomCenter) {
int oldFontSize = myScheme.getEditorFontSize();
+
+ Rectangle visibleArea = myScrollingModel.getVisibleArea();
+ Point zoomCenterRelative = zoomCenter == null ? new Point() : zoomCenter;
+ Point zoomCenterAbsolute = new Point(visibleArea.x + zoomCenterRelative.x, visibleArea.y + zoomCenterRelative.y);
+ LogicalPosition zoomCenterLogical = xyToLogicalPosition(zoomCenterAbsolute).withoutVisualPositionInfo();
+ int oldLineHeight = getLineHeight();
+ int intraLineOffset = zoomCenterAbsolute.y % oldLineHeight;
+
myScheme.setEditorFontSize(fontSize);
myPropertyChangeSupport.firePropertyChange(PROP_FONT_SIZE, oldFontSize, fontSize);
// Update vertical scroll bar bounds if necessary (we had a problem that use increased editor font size and it was not possible
// to scroll to the bottom of the document).
myScrollPane.getViewport().invalidate();
+
+ Point shiftedZoomCenterAbsolute = logicalPositionToXY(zoomCenterLogical);
+ myScrollingModel.disableAnimation();
+ try {
+ myScrollingModel.scrollToOffsets(visibleArea.x == 0 ? 0 : shiftedZoomCenterAbsolute.x - zoomCenterRelative.x, // stick to left border if it's visible
+ shiftedZoomCenterAbsolute.y - zoomCenterRelative.y + (intraLineOffset * getLineHeight() + oldLineHeight / 2) / oldLineHeight);
+ } finally {
+ myScrollingModel.enableAnimation();
+ }
}
public int getFontSize() {
@@ -975,17 +1021,22 @@
}
@Override
- public void setHighlighter(@NotNull EditorHighlighter highlighter) {
+ public void setHighlighter(@NotNull final EditorHighlighter highlighter) {
assertIsDispatchThread();
final Document document = getDocument();
- if (myHighlighter != null && !isDisposed()) {
- document.removeDocumentListener(myHighlighter);
- }
+ Disposer.dispose(myHighlighterDisposable);
document.addDocumentListener(highlighter);
+ myHighlighter = highlighter;
+ myHighlighterDisposable = new Disposable() {
+ @Override
+ public void dispose() {
+ document.removeDocumentListener(highlighter);
+ }
+ };
+ Disposer.register(myDisposable, myHighlighterDisposable);
highlighter.setEditor(this);
highlighter.setText(document.getCharsSequence());
- myHighlighter = highlighter;
EditorHighlighterCache.rememberEditorHighlighterForCachesOptimization(document, highlighter);
if (myPanel != null) {
@@ -1028,9 +1079,14 @@
boolean oldValue = myIsInsertMode;
myIsInsertMode = mode;
myPropertyChangeSupport.firePropertyChange(PROP_INSERT_MODE, oldValue, mode);
- //Repaint the caret line by moving caret to the same place
- LogicalPosition caretPosition = getCaretModel().getLogicalPosition();
- getCaretModel().moveToLogicalPosition(caretPosition);
+ if (myCaretModel.supportsMultipleCarets()) {
+ myCaretCursor.repaint();
+ }
+ else {
+ //Repaint the caret line by moving caret to the same place
+ LogicalPosition caretPosition = getCaretModel().getLogicalPosition();
+ getCaretModel().moveToLogicalPosition(caretPosition);
+ }
}
@Override
@@ -1056,7 +1112,7 @@
return y / getLineHeight();
}
- int yPositionToLogicalLine(int y) {
+ public int yPositionToLogicalLine(int y) {
int line = yPositionToVisibleLine(y);
if (line <= 0) {
return 0;
@@ -1177,10 +1233,10 @@
else {
prevX = x;
c = text.charAt(offset);
- charWidth = charToVisibleWidth(c, fontType, x);
- if (charWidth == 0) {
+ if (c == '\n') {
break;
}
+ charWidth = charToVisibleWidth(c, fontType, x);
x += charWidth;
if (x >= px) {
@@ -1283,11 +1339,7 @@
public int offsetToVisualLine(int offset) {
int textLength = getDocument().getTextLength();
if (offset >= textLength) {
- int result = Math.max(0, getVisibleLineCount() - 1); // lines are 0 based
- if (textLength > 0 && getDocument().getCharsSequence().charAt(textLength - 1) == '\n') {
- result++;
- }
- return result;
+ return Math.max(0, getVisibleLineCount() - 1); // lines are 0 based
}
int line = offsetToLogicalLine(offset);
int lineStartOffset = line >= myDocument.getLineCount() ? myDocument.getTextLength() : myDocument.getLineStartOffset(line);
@@ -1636,6 +1688,7 @@
stopOptimizedScrolling();
mySelectionModel.removeBlockSelection();
+ setMouseSelectionState(MOUSE_SELECTION_STATE_NONE);
mySizeContainer.reset();
validateSize();
@@ -1670,6 +1723,7 @@
clearTextWidthCache();
stopOptimizedScrolling();
mySelectionModel.removeBlockSelection();
+ setMouseSelectionState(MOUSE_SELECTION_STATE_NONE);
// We assume that size container is already notified with the visual line widths during soft wraps processing
if (!mySoftWrapModel.isSoftWrappingEnabled()) {
@@ -1706,7 +1760,7 @@
updateHasTabsFlag(e.getNewFragment());
}
- private void updateHasTabsFlag(CharSequence newChars) {
+ private void updateHasTabsFlag(@NotNull CharSequence newChars) {
if (!hasTabs) {
hasTabs = StringUtil.contains(newChars, 0, newChars.length(), '\t');
}
@@ -1806,7 +1860,7 @@
@Override
public void removeEditorMouseListener(@NotNull EditorMouseListener listener) {
boolean success = myMouseListeners.remove(listener);
- LOG.assertTrue(success);
+ LOG.assertTrue(success || isReleased);
}
@Override
@@ -1817,7 +1871,7 @@
@Override
public void removeEditorMouseMotionListener(@NotNull EditorMouseMotionListener listener) {
boolean success = myMouseMotionListeners.remove(listener);
- LOG.assertTrue(success);
+ LOG.assertTrue(success || isReleased);
}
@Override
@@ -1965,11 +2019,13 @@
return header != null && header != getPermanentHeaderComponent();
}
+ @Override
@Nullable
public JComponent getPermanentHeaderComponent() {
return getUserData(PERMANENT_HEADER);
}
+ @Override
public void setPermanentHeaderComponent(@Nullable JComponent component) {
putUserData(PERMANENT_HEADER, component);
}
@@ -2167,9 +2223,9 @@
int visibleLine = yPositionToVisibleLine(clip.y);
Point position = new Point(0, visibleLine * lineHeight);
- char[] prefixText = myPrefixText;
+ CharSequence prefixText = myPrefixText == null ? null : new CharArrayCharSequence(myPrefixText);
if (clipStartVisualPos.line == 0 && prefixText != null) {
- position.x = drawBackground(g, myPrefixAttributes.getBackgroundColor(), prefixText, 0, prefixText.length, position,
+ position.x = drawBackground(g, myPrefixAttributes.getBackgroundColor(), prefixText, 0, prefixText.length(), position,
myPrefixAttributes.getFontType(),
defaultBackground, clip);
}
@@ -2182,7 +2238,6 @@
myLastBackgroundPosition = null;
myLastBackgroundColor = null;
- boolean locateBeforeSoftWrap = !SoftWrapHelper.isCaretAfterSoftWrap(this);
int start = clipStartOffset;
int end = clipEndOffset;
if (!myPurePaintingMode) {
@@ -2232,7 +2287,7 @@
// background is already drawn.
boolean[] caretRowPainted = new boolean[1];
- char[] text = myDocument.getChars();
+ CharSequence text = myDocument.getCharsSequence();
while (!iterationState.atEnd() && !lIterator.atEnd()) {
int hEnd = iterationState.getEndOffset();
@@ -2271,8 +2326,8 @@
defaultBackground, clip, softWrapsToSkip, caretRowPainted
);
}
- char[] chars = collapsedFolderAt.getPlaceholderText().toCharArray();
- position.x = drawBackground(g, backColor, chars, 0, chars.length, position, fontType, defaultBackground, clip);
+ CharSequence chars = collapsedFolderAt.getPlaceholderText();
+ position.x = drawBackground(g, backColor, chars, 0, chars.length(), position, fontType, defaultBackground, clip);
}
lIterator.advance();
@@ -2287,8 +2342,8 @@
defaultBackground, clip, softWrapsToSkip, caretRowPainted
);
}
- char[] chars = collapsedFolderAt.getPlaceholderText().toCharArray();
- position.x = drawBackground(g, backColor, chars, 0, chars.length, position, fontType, defaultBackground, clip);
+ CharSequence chars = collapsedFolderAt.getPlaceholderText();
+ position.x = drawBackground(g, backColor, chars, 0, chars.length(), position, fontType, defaultBackground, clip);
}
else if (hEnd > lEnd - lIterator.getSeparatorLength()) {
position.x = drawSoftWrapAwareBackground(
@@ -2332,9 +2387,6 @@
// Repaint gutter at all space that is located after active clip in order to ensure that line numbers are correctly redrawn
// in accordance with the newly introduced soft wrap(s).
myGutterComponent.repaint(0, clip.y, myGutterComponent.getWidth(), myGutterComponent.getHeight() - clip.y);
-
- // Ask caret model to update visual caret position.
- getCaretModel().moveToOffset(getCaretModel().getOffset(), locateBeforeSoftWrap);
}
}
@@ -2384,7 +2436,7 @@
private int drawSoftWrapAwareBackground(@NotNull Graphics g,
Color backColor,
- @NotNull char[] text,
+ @NotNull CharSequence text,
int start,
int end,
@NotNull Point position,
@@ -2453,7 +2505,7 @@
paintSelectionOnFirstSoftWrapLineIfNecessary(g, position, clip, defaultBackground, fontType);
int i = CharArrayUtil.lastIndexOf(softWrapText, "\n", softWrapText.length()) + 1;
- int width = getTextSegmentWidth(CharArrayUtil.fromSequence(softWrapText), i, softWrapText.length(), 0, fontType, clip)
+ int width = getTextSegmentWidth(softWrapText, i, softWrapText.length(), 0, fontType, clip)
+ getSoftWrapModel().getMinDrawingWidthInPixels(SoftWrapDrawingType.AFTER_SOFT_WRAP);
position.x = 0;
position.y += getLineHeight();
@@ -2587,7 +2639,7 @@
private int drawBackground(@NotNull Graphics g,
Color backColor,
- @NotNull char[] text,
+ @NotNull CharSequence text,
int start,
int end,
@NotNull Point position,
@@ -2669,7 +2721,7 @@
Point position = new Point(0, visibleLine * lineHeight);
if (startLine == 0 && myPrefixText != null) {
- position.x = drawStringWithSoftWraps(g, myPrefixText, 0, myPrefixText.length, position, clip,
+ position.x = drawStringWithSoftWraps(g, new CharArrayCharSequence(myPrefixText), 0, myPrefixText.length, position, clip,
myPrefixAttributes.getEffectColor(), myPrefixAttributes.getEffectType(),
myPrefixAttributes.getFontType(), myPrefixAttributes.getForegroundColor(), logicalPosition);
}
@@ -2696,7 +2748,7 @@
int fontType = attributes.getFontType();
g.setColor(currentColor);
- char[] chars = myDocument instanceof DocumentImpl ? ((DocumentImpl)myDocument).getRawChars() : myDocument.getChars();
+ CharSequence chars = myDocument.getCharsSequence();
while (!iterationState.atEnd() && !lIterator.atEnd()) {
int hEnd = iterationState.getEndOffset();
@@ -2795,7 +2847,7 @@
}
else {
myLastPaintedPlaceholderWidth = drawString(
- g, CharArrayUtil.fromSequence(hintText), 0, hintText.length(), new Point(0, 0), clip, null, null, Font.PLAIN,
+ g, hintText, 0, hintText.length(), new Point(0, 0), clip, null, null, Font.PLAIN,
myFoldingModel.getPlaceholderAttributes().getForegroundColor()
);
flushCachedChars(g);
@@ -2825,7 +2877,7 @@
}
private class CachedFontContent {
- final char[][] data = new char[CACHED_CHARS_BUFFER_SIZE][];
+ final CharSequence[] data = new CharSequence[CACHED_CHARS_BUFFER_SIZE];
final int[] starts = new int[CACHED_CHARS_BUFFER_SIZE];
final int[] ends = new int[CACHED_CHARS_BUFFER_SIZE];
final int[] x = new int[CACHED_CHARS_BUFFER_SIZE];
@@ -2837,7 +2889,7 @@
final boolean myHasBreakSymbols;
final int spaceWidth;
- @Nullable private char[] myLastData;
+ @Nullable private CharSequence myLastData;
private CachedFontContent(@NotNull FontInfo fontInfo) {
myFontType = fontInfo;
@@ -2868,14 +2920,14 @@
}
}
- private void addContent(@NotNull Graphics g, char[] _data, int _start, int _end, int _x, int _y, @Nullable Color _color) {
+ private void addContent(@NotNull Graphics g, CharSequence _data, int _start, int _end, int _x, int _y, @Nullable Color _color) {
final int count = myCount;
if (count > 0) {
final int lastCount = count - 1;
final Color lastColor = color[lastCount];
if (_data == myLastData && _start == ends[lastCount] && (_color == null || lastColor == null || _color.equals(lastColor))
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */
- && (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data[ends[lastCount] - 1]))) {
+ && (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data.charAt(ends[lastCount] - 1)))) {
ends[lastCount] = _end;
if (lastColor == null) color[lastCount] = _color;
return;
@@ -2978,12 +3030,12 @@
@JdkConstants.FontStyle int fontType,
Color fontColor,
@NotNull Ref<LogicalPosition> startDrawingLogicalPosition) {
- return drawStringWithSoftWraps(g, text.toCharArray(), 0, text.length(), position, clip, effectColor, effectType,
+ return drawStringWithSoftWraps(g, text, 0, text.length(), position, clip, effectColor, effectType,
fontType, fontColor, startDrawingLogicalPosition);
}
private int drawStringWithSoftWraps(@NotNull Graphics g,
- final char[] text,
+ final CharSequence text,
final int start,
final int end,
@NotNull Point position,
@@ -3031,6 +3083,7 @@
outer:
for (SoftWrap softWrap : getSoftWrapModel().getSoftWrapsForRange(startToUse, softWrapRetrievalEndOffset)) {
char[] softWrapChars = softWrap.getChars();
+ CharArrayCharSequence softWrapSeq = new CharArrayCharSequence(softWrapChars);
if (softWrap.equals(lastSkippedSoftWrap)) {
// If we are here that means that we are located on soft wrap-introduced visual line just after soft wrap. Hence, we need
@@ -3039,7 +3092,7 @@
if (i < softWrapChars.length - 1) {
position.x = 0; // Soft wrap starts new visual line
position.x = drawString(
- g, softWrapChars, i + 1, softWrapChars.length, position, clip, null, null, fontType, fontColor
+ g, softWrapSeq, i + 1, softWrapChars.length, position, clip, null, null, fontType, fontColor
);
}
position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight());
@@ -3068,7 +3121,7 @@
// Draw soft wrap symbols on current visual line if any.
if (i - softWrapSegmentStartIndex > 0) {
drawString(
- g, softWrapChars, softWrapSegmentStartIndex, i, position, clip, null, null, fontType, fontColor
+ g, softWrapSeq, softWrapSegmentStartIndex, i, position, clip, null, null, fontType, fontColor
);
}
mySoftWrapModel.paint(g, SoftWrapDrawingType.BEFORE_SOFT_WRAP_LINE_FEED, position.x, position.y, getLineHeight());
@@ -3088,7 +3141,7 @@
// Draw remaining soft wrap symbols from its last line if any.
if (softWrapSegmentStartIndex < softWrapChars.length) {
position.x += drawString(
- g, softWrapChars, softWrapSegmentStartIndex, softWrapChars.length, position, clip, null, null, fontType, fontColor
+ g, softWrapSeq, softWrapSegmentStartIndex, softWrapChars.length, position, clip, null, null, fontType, fontColor
);
}
position.x += mySoftWrapModel.paint(g, SoftWrapDrawingType.AFTER_SOFT_WRAP, position.x, position.y, getLineHeight());
@@ -3098,7 +3151,7 @@
}
private int drawString(@NotNull Graphics g,
- final char[] text,
+ final CharSequence text,
int start,
int end,
@NotNull Point position,
@@ -3137,11 +3190,11 @@
int y = getAscent() + position.y;
int x = position.x;
- return drawTabbedString(g, text.toCharArray(), 0, text.length(), x, y, effectColor, effectType, fontType, fontColor, clip);
+ return drawTabbedString(g, text, 0, text.length(), x, y, effectColor, effectType, fontType, fontColor, clip);
}
private int drawTabbedString(@NotNull Graphics g,
- char[] text,
+ CharSequence text,
int start,
int end,
int x,
@@ -3154,7 +3207,7 @@
int xStart = x;
for (int i = start; i < end; i++) {
- if (text[i] != '\t') continue;
+ if (text.charAt(i) != '\t') continue;
x = drawTablessString(text, start, i, g, x, y, fontType, fontColor, clip);
@@ -3214,7 +3267,7 @@
return x;
}
- private int drawTablessString(final char[] text,
+ private int drawTablessString(final CharSequence text,
int start,
final int end,
@NotNull final Graphics g,
@@ -3225,9 +3278,9 @@
@NotNull final Rectangle clip) {
int endX = x;
if (start < end) {
- FontInfo font = EditorUtil.fontForChar(text[start], fontType, this);
+ FontInfo font = EditorUtil.fontForChar(text.charAt(start), fontType, this);
for (int j = start; j < end; j++) {
- final char c = text[j];
+ final char c = text.charAt(j);
FontInfo newFont = EditorUtil.fontForChar(c, fontType, this);
if (font != newFont || endX > clip.x + clip.width) {
if (!(x < clip.x && endX < clip.x || x > clip.x + clip.width && endX > clip.x + clip.width)) {
@@ -3284,7 +3337,7 @@
}
private void drawCharsCached(@NotNull Graphics g,
- char[] data,
+ CharSequence data,
int start,
int end,
int x,
@@ -3296,13 +3349,13 @@
}
else {
myForceRefreshFont = false;
- FontInfo fnt = EditorUtil.fontForChar(data[start], fontType, this);
+ FontInfo fnt = EditorUtil.fontForChar(data.charAt(start), fontType, this);
drawCharsCached(g, data, start, end, x, y, fnt, color);
}
}
private void drawCharsCached(@NotNull Graphics g,
- @NotNull char[] data,
+ @NotNull CharSequence data,
int start,
int end,
int x,
@@ -3325,17 +3378,17 @@
cache.addContent(g, data, start, end, x, y, color);
}
- private static boolean spacesOnly(char[] chars, int start, int end) {
+ private static boolean spacesOnly(CharSequence chars, int start, int end) {
for (int i = start; i < end; i++) {
- if (chars[i] != ' ') return false;
+ if (chars.charAt(i) != ' ') return false;
}
return true;
}
private static final char IDEOGRAPHIC_SPACE = '\u3000'; // http://www.marathon-studios.com/unicode/U3000/Ideographic_Space
- private void drawChars(@NotNull Graphics g, char[] data, int start, int end, int x, int y) {
- g.drawChars(data, start, end - start, x, y);
+ private void drawChars(@NotNull Graphics g, CharSequence data, int start, int end, int x, int y) {
+ g.drawString(data.subSequence(start, end).toString(), x, y);
if (mySettings.isWhitespacesShown()) {
Color oldColor = g.getColor();
@@ -3343,7 +3396,7 @@
final FontMetrics metrics = g.getFontMetrics();
for (int i = start; i < end; i++) {
- final char c = data[i];
+ final char c = data.charAt(i);
final int charWidth = isOracleRetina ? GraphicsUtil.charWidth(c, g.getFont()) : metrics.charWidth(c);
if (c == ' ') {
@@ -3378,7 +3431,7 @@
UIUtil.drawLine(g, x + WAVE_SEGMENT_LENGTH / 2, y, x + WAVE_SEGMENT_LENGTH, y + WAVE_HEIGHT);
}
- private int getTextSegmentWidth(@NotNull char[] text,
+ private int getTextSegmentWidth(@NotNull CharSequence text,
int start,
int end,
int xStart,
@@ -3387,7 +3440,7 @@
int x = xStart;
for (int i = start; i < end && xStart < clip.x + clip.width; i++) {
- char c = text[i];
+ char c = text.charAt(i);
if (c == '\t') {
x = EditorUtil.nextTabStop(x, this);
}
@@ -3421,7 +3474,7 @@
return lineHeight;
}
- int getDescent() {
+ public int getDescent() {
if (myDescent != -1) {
return myDescent;
}
@@ -3431,7 +3484,7 @@
}
@NotNull
- FontMetrics getFontMetrics(@JdkConstants.FontStyle int fontType) {
+ public FontMetrics getFontMetrics(@JdkConstants.FontStyle int fontType) {
if (myPlainFontMetrics == null) {
assertIsDispatchThread();
myPlainFontMetrics = myEditorComponent.getFontMetrics(myScheme.getFont(EditorFontType.PLAIN));
@@ -3477,13 +3530,15 @@
? mySettings.getAdditionalColumnsCount() * EditorUtil.getSpaceWidth(Font.PLAIN, this)
: 0;
- if (!myDocument.isInBulkUpdate() && getCaretModel().isUpToDate()) {
- int caretX = visualPositionToXY(getCaretModel().getVisualPosition()).x;
- draft.width = Math.max(caretX, draft.width) + additionalSpace;
+ if (!myDocument.isInBulkUpdate()) {
+ for (Caret caret : myCaretModel.getAllCarets()) {
+ if (caret.isUpToDate()) {
+ int caretX = visualPositionToXY(caret.getVisualPosition()).x;
+ draft.width = Math.max(caretX, draft.width);
+ }
+ }
}
- else {
- draft.width += additionalSpace;
- }
+ draft.width += additionalSpace;
return draft;
}
@@ -3590,7 +3645,7 @@
* lines (considering that single logical document line may be represented on multiple visual lines because of
* soft wraps appliance) minus number of folded lines
*/
- int getVisibleLineCount() {
+ public int getVisibleLineCount() {
return getVisibleLogicalLinesCount() + getSoftWrapModel().getSoftWrapsIntroducedLinesNumber();
}
@@ -3847,7 +3902,7 @@
}
}
- private void moveCaretToScreenPos(int x, int y) {
+ private LogicalPosition getLogicalPositionForScreenPos(int x, int y, boolean trimToLineWidth) {
if (x < 0) {
x = 0;
}
@@ -3870,8 +3925,7 @@
final int totalLines = myDocument.getLineCount();
if (totalLines <= 0) {
- getCaretModel().moveToOffset(0);
- return;
+ return new LogicalPosition(0, 0);
}
if (line >= totalLines && totalLines > 0) {
@@ -3884,11 +3938,10 @@
LogMessageEx.error(LOG, "cycled moveCaretToScreenPos() detected", String.format("x=%d, y=%d\nstate=%s", x, y, dumpState()));
throw new IllegalStateException("cycled moveCaretToScreenPos() detected");
}
- moveCaretToScreenPos(x, newY);
- return;
+ return getLogicalPositionForScreenPos(x, newY, trimToLineWidth);
}
- if (!mySettings.isVirtualSpace() && !mySelectionModel.hasBlockSelection()) {
+ if (!mySettings.isVirtualSpace() && !mySelectionModel.hasBlockSelection() && trimToLineWidth) {
int lineEndOffset = myDocument.getLineEndOffset(line);
int lineEndColumn = calcColumnNumber(lineEndOffset, line);
if (column > lineEndColumn) {
@@ -3908,11 +3961,10 @@
}
}
}
- LogicalPosition pos1 = new LogicalPosition(
+ return new LogicalPosition(
line, column, softWrapLinesBeforeTargetLogicalLine, softWrapLinesOnTargetLogicalLine, softWrapColumns,
pos.foldedLines, pos.foldingColumnDiff
);
- getCaretModel().moveToLogicalPosition(pos1);
}
private boolean checkIgnore(@NotNull MouseEvent e, boolean isFinalCheck) {
@@ -4080,7 +4132,8 @@
// further dragging (if any).
if (myDragOnGutterSelectionStartLine >= 0) {
mySelectionModel.removeSelection();
- myCaretModel.moveToOffset(myDocument.getLineStartOffset(myDragOnGutterSelectionStartLine));
+ myCaretModel.moveToOffset(myDragOnGutterSelectionStartLine < myDocument.getLineCount()
+ ? myDocument.getLineStartOffset(myDragOnGutterSelectionStartLine) : myDocument.getTextLength());
}
myDragOnGutterSelectionStartLine = - 1;
}
@@ -4121,8 +4174,17 @@
VisualPosition oldVisLeadSelectionStart = selectionModel.getLeadSelectionPosition();
int oldCaretOffset = getCaretModel().getOffset();
LogicalPosition oldLogicalCaret = getCaretModel().getLogicalPosition();
- moveCaretToScreenPos(x, y);
- getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ boolean multiCaretSelection = myCaretModel.supportsMultipleCarets() && (isColumnMode() || e.isAltDown());
+ LogicalPosition newLogicalCaret = getLogicalPositionForScreenPos(x, y, !multiCaretSelection);
+ if (multiCaretSelection) {
+ myMultiSelectionInProgress = true;
+ myTargetMultiSelectionPosition = xyToVisualPosition(new Point(Math.max(x, 0), Math.max(y, 0)));
+ getScrollingModel().scrollTo(newLogicalCaret, ScrollType.RELATIVE);
+ }
+ else {
+ getCaretModel().moveToLogicalPosition(newLogicalCaret);
+ getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ }
int newCaretOffset = getCaretModel().getOffset();
VisualPosition newVisualCaret = getCaretModel().getVisualPosition();
@@ -4134,16 +4196,19 @@
}
else {
if (isColumnMode() || e.isAltDown()) {
- final LogicalPosition blockStart = selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : oldLogicalCaret;
- selectionModel.setBlockSelection(blockStart, getCaretModel().getLogicalPosition());
- IdeEventQueue.getInstance().blockNextEvents(e); // don't process action on mouse released (IDEA-53663)
+ if (myCaretModel.supportsMultipleCarets()) {
+ selectionModel.setBlockSelection(myLastMousePressedLocation, newLogicalCaret);
+ } else {
+ final LogicalPosition blockStart = selectionModel.hasBlockSelection() ? selectionModel.getBlockStart() : oldLogicalCaret;
+ selectionModel.setBlockSelection(blockStart, getCaretModel().getLogicalPosition());
+ }
}
else {
if (getMouseSelectionState() != MOUSE_SELECTION_STATE_NONE) {
if (caretShift < 0) {
int newSelection = newCaretOffset;
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_WORD_SELECTED) {
- newSelection = mySelectionModel.getWordAtCaretStart();
+ newSelection = myCaretModel.getWordAtCaretStart();
}
else {
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_LINE_SELECTED) {
@@ -4158,7 +4223,7 @@
else {
int newSelection = newCaretOffset;
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_WORD_SELECTED) {
- newSelection = mySelectionModel.getWordAtCaretEnd();
+ newSelection = myCaretModel.getWordAtCaretEnd();
}
else {
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_LINE_SELECTED) {
@@ -4293,10 +4358,22 @@
}
private void setCursorPosition() {
- VisualPosition caretPosition = getCaretModel().getVisualPosition();
- Point pos1 = visualPositionToXY(caretPosition);
- Point pos2 = visualPositionToXY(new VisualPosition(caretPosition.line, caretPosition.column + 1));
- myCaretCursor.setPosition(pos1, pos2.x - pos1.x);
+ if (myCaretModel.supportsMultipleCarets()) {
+ final List<CaretRectangle> caretPoints = new ArrayList<CaretRectangle>();
+ for (Caret caret : getCaretModel().getAllCarets()) {
+ VisualPosition caretPosition = caret.getVisualPosition();
+ Point pos1 = visualPositionToXY(caretPosition);
+ Point pos2 = visualPositionToXY(new VisualPosition(caretPosition.line, caretPosition.column + 1));
+ caretPoints.add(new CaretRectangle(pos1, pos2.x - pos1.x, caret));
+ }
+ myCaretCursor.setPositions(caretPoints.toArray(new CaretRectangle[caretPoints.size()]));
+ }
+ else {
+ VisualPosition caretPosition = getCaretModel().getVisualPosition();
+ Point pos1 = visualPositionToXY(caretPosition);
+ Point pos2 = visualPositionToXY(new VisualPosition(caretPosition.line, caretPosition.column + 1));
+ myCaretCursor.setPosition(pos1, pos2.x - pos1.x);
+ }
}
@Override
@@ -4370,9 +4447,22 @@
//myEditorComponent.setOpaque(true);
}
+ private class CaretRectangle {
+ private final Point myPoint;
+ private final int myWidth;
+ private final Caret myCaret;
+
+ private CaretRectangle(Point point, int width, Caret caret) {
+ myPoint = point;
+ myWidth = Math.max(width, 2);
+ myCaret = caret;
+ }
+ }
+
private class CaretCursor {
private Point myLocation;
private int myWidth;
+ private CaretRectangle[] myLocations;
private boolean myEnabled;
@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"})
@@ -4381,6 +4471,7 @@
private CaretCursor() {
myLocation = new Point(0, 0);
+ myLocations = new CaretRectangle[] {new CaretRectangle(new Point(0, 0), 0, null)};
setEnabled(true);
}
@@ -4423,16 +4514,39 @@
repaint();
}
+ private void setPositions(CaretRectangle[] locations) {
+ myStartTime = System.currentTimeMillis();
+ myLocations = locations;
+ myIsShown = true;
+ repaint();
+ }
+
private void repaint() {
- myEditorComponent.repaintEditorComponent(myLocation.x, myLocation.y, myWidth, getLineHeight());
+ if (myCaretModel.supportsMultipleCarets()) {
+ for (CaretRectangle location : myLocations) {
+ myEditorComponent.repaintEditorComponent(location.myPoint.x, location.myPoint.y, location.myWidth, getLineHeight());
+ }
+ }
+ else {
+ myEditorComponent.repaintEditorComponent(myLocation.x, myLocation.y, myWidth, getLineHeight());
+ }
}
private void paint(@NotNull Graphics g) {
if (!isEnabled() || !myIsShown || !IJSwingUtilities.hasFocus(getContentComponent()) || isRendererMode()) return;
- int x = myLocation.x;
+ if (myCaretModel.supportsMultipleCarets()) {
+ for (CaretRectangle location : myLocations) {
+ paintAt(g, location.myPoint.x, location.myPoint.y, location.myWidth, location.myCaret);
+ }
+ }
+ else {
+ paintAt(g, myLocation.x, myLocation.y, myWidth, null);
+ }
+ }
+
+ private void paintAt(@NotNull Graphics g, int x, int y, int width, Caret caret) {
int lineHeight = getLineHeight();
- int y = myLocation.y;
Rectangle viewRectangle = getScrollingModel().getVisibleArea();
if (x - viewRectangle.x < 0) {
@@ -4456,24 +4570,24 @@
Color caretColor = myScheme.getColor(EditorColors.CARET_COLOR);
if (caretColor == null) caretColor = new JBColor(Color.BLACK, Color.WHITE);
g.setColor(caretColor);
- g.fillRect(x, y, myWidth, lineHeight - 1);
- final LogicalPosition startPosition = getCaretModel().getLogicalPosition();
+ g.fillRect(x, y, width, lineHeight - 1);
+ final LogicalPosition startPosition = caret == null ? getCaretModel().getLogicalPosition() : caret.getLogicalPosition();
final int offset = logicalPositionToOffset(startPosition);
- char[] chars = myDocument instanceof DocumentImpl ? ((DocumentImpl)myDocument).getRawChars() : myDocument.getChars();
- if (chars.length > offset && myDocument.getTextLength() > offset) {
+ CharSequence chars = myDocument.getCharsSequence();
+ if (chars.length() > offset && myDocument.getTextLength() > offset) {
FoldRegion folding = myFoldingModel.getCollapsedRegionAtOffset(offset);
final char ch;
if (folding == null || folding.isExpanded()) {
- ch = chars[offset];
+ ch = chars.charAt(offset);
}
else {
- VisualPosition visual = getCaretModel().getVisualPosition();
+ VisualPosition visual = caret == null ? getCaretModel().getVisualPosition() : caret.getVisualPosition();
VisualPosition foldingPosition = offsetToVisualPosition(folding.getStartOffset());
if (visual.line == foldingPosition.line) {
ch = folding.getPlaceholderText().charAt(visual.column - foldingPosition.column);
}
else {
- ch = chars[offset];
+ ch = chars.charAt(offset);
}
}
IterationState state = null;
@@ -4481,11 +4595,9 @@
//don't worry it's cheap. Cache is not required
state = new IterationState(EditorImpl.this, offset, offset + 1, true);
TextAttributes attributes = state.getMergedAttributes();
- if (attributes != null) {
- FontInfo info = EditorUtil.fontForChar(ch, attributes.getFontType(), EditorImpl.this);
- if (info != null) {
- g.setFont(info.getFont());
- }
+ FontInfo info = EditorUtil.fontForChar(ch, attributes.getFontType(), EditorImpl.this);
+ if (info != null) {
+ g.setFont(info.getFont());
}
//todo[kb]
//in case of italic style we paint out of the cursor block. Painting the symbol to a dedicated buffered image
@@ -4558,7 +4670,7 @@
return;
}
int oldSelectionStart = mySelectionModel.getLeadSelectionOffset();
- VisualPosition caretPosition = getCaretModel().getVisualPosition();
+ VisualPosition caretPosition = myMultiSelectionInProgress ? myTargetMultiSelectionPosition : getCaretModel().getVisualPosition();
int column = caretPosition.column;
xPassedCycles++;
if (xPassedCycles >= myXCycles) {
@@ -4576,8 +4688,10 @@
line = Math.max(0, line);
column = Math.max(0, column);
VisualPosition pos = new VisualPosition(line, column);
- getCaretModel().moveToVisualPosition(pos);
- getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ if (!myMultiSelectionInProgress) {
+ getCaretModel().moveToVisualPosition(pos);
+ getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
+ }
int newCaretOffset = getCaretModel().getOffset();
int caretShift = newCaretOffset - mySavedSelectionStart;
@@ -4586,7 +4700,7 @@
if (caretShift < 0) {
int newSelection = newCaretOffset;
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_WORD_SELECTED) {
- newSelection = mySelectionModel.getWordAtCaretStart();
+ newSelection = myCaretModel.getWordAtCaretStart();
}
else {
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_LINE_SELECTED) {
@@ -4601,7 +4715,7 @@
else {
int newSelection = newCaretOffset;
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_WORD_SELECTED) {
- newSelection = mySelectionModel.getWordAtCaretEnd();
+ newSelection = myCaretModel.getWordAtCaretEnd();
}
else {
if (getMouseSelectionState() == MOUSE_SELECTION_STATE_LINE_SELECTED) {
@@ -4616,7 +4730,13 @@
return;
}
- if (mySelectionModel.hasBlockSelection()) {
+ if (myMultiSelectionInProgress) {
+ myTargetMultiSelectionPosition = pos;
+ LogicalPosition newLogicalPosition = visualToLogicalPosition(pos);
+ getScrollingModel().scrollTo(newLogicalPosition, ScrollType.RELATIVE);
+ mySelectionModel.setBlockSelection(myLastMousePressedLocation, newLogicalPosition);
+ }
+ else if (mySelectionModel.hasBlockSelection()) {
mySelectionModel.setBlockSelection(mySelectionModel.getBlockStart(), getCaretModel().getLogicalPosition());
}
else {
@@ -4813,7 +4933,7 @@
@Override
public boolean isCopyVisible(@NotNull DataContext dataContext) {
- return getSelectionModel().hasSelection() || getSelectionModel().hasBlockSelection();
+ return getSelectionModel().hasSelection(true) || getSelectionModel().hasBlockSelection();
}
@Override
@@ -4829,7 +4949,7 @@
@Override
public boolean isCutVisible(@NotNull DataContext dataContext) {
if (!isCutEnabled(dataContext)) return false;
- return getSelectionModel().hasSelection() || getSelectionModel().hasBlockSelection();
+ return getSelectionModel().hasSelection(true) || getSelectionModel().hasBlockSelection();
}
@Override
@@ -5349,8 +5469,9 @@
}
private void runMousePressedCommand(@NotNull final MouseEvent e) {
+ myLastMousePressedLocation = xyToLogicalPosition(e.getPoint());
- final int clickOffset = logicalPositionToOffset(xyToLogicalPosition(e.getPoint()));
+ final int clickOffset = logicalPositionToOffset(myLastMousePressedLocation);
putUserData(EditorActionUtil.EXPECTED_CARET_OFFSET, clickOffset);
mySelectionTweaked = false;
@@ -5403,6 +5524,8 @@
}
private void runMouseReleasedCommand(@NotNull final MouseEvent e) {
+ myMultiSelectionInProgress = false;
+
myDragOnGutterSelectionStartLine = -1;
if (!mySelectionTweaked) {
tweakSelectionIfNecessary(e);
@@ -5494,6 +5617,7 @@
y = myGutterComponent.getHeadCenterY(range);
getScrollingModel().scrollVertically(y - scrollShift);
myGutterComponent.updateSize();
+ validateMousePointer(e);
return isNavigation;
}
}
@@ -5524,7 +5648,23 @@
if (e.getSource() != myGutterComponent
|| (eventArea != EditorMouseEventArea.LINE_MARKERS_AREA && eventArea != EditorMouseEventArea.ANNOTATIONS_AREA))
{
- moveCaretToScreenPos(x, y);
+ boolean toggleCaret =
+ myCaretModel.supportsMultipleCarets() && e.getSource() != myGutterComponent && e.isAltDown() && e.isShiftDown() && !e.isControlDown();
+ LogicalPosition pos = getLogicalPositionForScreenPos(x, y, true);
+ if (toggleCaret) {
+ VisualPosition visualPosition = logicalToVisualPosition(pos);
+ Caret caret = getCaretModel().getCaretAt(visualPosition);
+ if (caret == null) {
+ getCaretModel().addCaret(visualPosition);
+ }
+ else {
+ getCaretModel().removeCaret(caret);
+ }
+ }
+ else {
+ getCaretModel().removeSecondaryCarets();
+ getCaretModel().moveToLogicalPosition(pos);
+ }
}
if (e.isPopupTrigger()) return isNavigation;
@@ -5779,7 +5919,6 @@
}
private class MyColorSchemeDelegate extends DelegateColorScheme {
-
private final FontPreferences myFontPreferences = new FontPreferences();
private final Map<TextAttributesKey, TextAttributes> myOwnAttributes = ContainerUtilRt.newHashMap();
private final Map<ColorKey, Color> myOwnColors = ContainerUtilRt.newHashMap();
@@ -5914,14 +6053,6 @@
return null;
}
- @Override
- public void readExternal(Element element) throws InvalidDataException {
- }
-
- @Override
- public void writeExternal(Element element) throws WriteExternalException {
- }
-
public void updateGlobalScheme() {
setDelegate(myCustomGlobalScheme == null ? EditorColorsManager.getInstance().getGlobalScheme() : myCustomGlobalScheme);
}
@@ -5975,6 +6106,7 @@
public void run() {
try {
editor.getSelectionModel().removeSelection();
+
final int offset;
if (myDraggedRange != null) {
editor.getCaretModel().moveToOffset(caretOffset);
@@ -5983,16 +6115,15 @@
else {
offset = editor.getCaretModel().getOffset();
}
- if (editor.getDocument().getRangeGuard(offset, offset) != null) return;
-
- EditorActionHandler pasteHandler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_PASTE);
+ if (editor.getDocument().getRangeGuard(offset, offset) != null) {
+ return;
+ }
editor.putUserData(LAST_PASTED_REGION, null);
+ EditorActionHandler pasteHandler = EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_PASTE);
LOG.assertTrue(pasteHandler instanceof EditorTextInsertHandler);
-
- EditorTextInsertHandler handler = (EditorTextInsertHandler)pasteHandler;
- handler.execute(editor, editor.getDataContext(), new Producer<Transferable>() {
+ ((EditorTextInsertHandler)pasteHandler).execute(editor, editor.getDataContext(), new Producer<Transferable>() {
@Override
public Transferable produce() {
return t;
@@ -6110,7 +6241,7 @@
}
}
- class EditorDocumentBulkUpdateAdapter implements DocumentBulkUpdateListener {
+ private class EditorDocumentBulkUpdateAdapter implements DocumentBulkUpdateListener {
@Override
public void updateStarted(@NotNull Document doc) {
if (doc != getDocument()) return;
@@ -6292,13 +6423,10 @@
int documentLength = myDocument.getTextLength();
int x = 0;
boolean lastLineLengthCalculated = false;
- final int fontSize = myScheme.getEditorFontSize();
- final String fontName = myScheme.getEditorFontName();
List<? extends SoftWrap> softWraps = getSoftWrapModel().getRegisteredSoftWraps();
int softWrapsIndex = -1;
- FontInfo lastFontInfo = null;
for (int line = 0; line < lineCount; line++) {
if (myLineWidths.getQuick(line) != -1) continue;
if (line == lineCount - 1) {
@@ -6397,10 +6525,7 @@
}
}
else {
- if (lastFontInfo == null || !lastFontInfo.canDisplay(c)) {
- lastFontInfo = ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName);
- }
- x += lastFontInfo.charWidth(c);
+ x += EditorUtil.charWidth(c, fontType, EditorImpl.this);
offset++;
}
}
@@ -6511,8 +6636,6 @@
}
private class MyScrollPane extends JBScrollPane {
-
-
private MyScrollPane() {
setViewportBorder(new EmptyBorder(0, 0, 0, 0));
}
@@ -6523,7 +6646,7 @@
if (EditorUtil.isChangeFontSize(e)) {
int size = myScheme.getEditorFontSize() - e.getWheelRotation();
if (size >= MIN_FONT_SIZE) {
- setFontSize(size);
+ setFontSize(size, SwingUtilities.convertPoint(this, e.getPoint(), getViewport()));
}
return;
}
@@ -6647,7 +6770,7 @@
Color color,
@NotNull FontInfo fontInfo)
{
- drawCharsCached(g, data, start, end, x, y, fontInfo, color);
+ drawCharsCached(g, new CharArrayCharSequence(data), start, end, x, y, fontInfo, color);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
index 56efb05..74b770b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorMarkupModelImpl.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.
@@ -300,7 +300,7 @@
int lineEnd = doc.getLineEndOffset(doc.getLineNumber(offset));
myEditor.getCaretModel().moveToOffset(lineEnd);
}
-
+ myEditor.getCaretModel().removeSecondaryCarets();
myEditor.getCaretModel().moveToOffset(offset);
myEditor.getSelectionModel().removeSelection();
ScrollingModel scrollingModel = myEditor.getScrollingModel();
@@ -1170,6 +1170,7 @@
if (tooltip == null) continue;
String s = String.valueOf(tooltip);
if (s.isEmpty()) continue;
+ s = s.replaceAll(" ", " ").replaceAll("\\s+", " ");
LogicalPosition logicalPosition = myEditor.offsetToLogicalPosition(hEndOffset);
int endOfLineOffset = myEditor.getDocument().getLineEndOffset(logicalPosition.line);
@@ -1247,7 +1248,7 @@
}
Point point = new Point(hintInfo.getOriginalPoint());
hintInfo.setTextBg(myEditor.getColorsScheme().getDefaultBackground());
- hintInfo.setBorderColor(new JBColor(Gray._0, Gray._111));
+ hintInfo.setBorderColor(myEditor.getColorsScheme().getDefaultForeground());
point = SwingUtilities.convertPoint(((EditorImpl)editor).getVerticalScrollBar(), point, myEditor.getComponent().getRootPane());
myPointHolder.set(point);
myHintHolder.set(hintInfo);
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java
index 038bc3b..0acfbbc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldRegionsTree.java
@@ -81,35 +81,28 @@
ArrayList<FoldRegion> topLevels = new ArrayList<FoldRegion>(myRegions.size() / 2);
ArrayList<FoldRegion> visible = new ArrayList<FoldRegion>(myRegions.size());
FoldRegion[] regions = toFoldArray(myRegions);
- FoldRegion currentToplevel = null;
+ FoldRegion currentCollapsed = null;
for (FoldRegion region : regions) {
- if (region.isValid()) {
+ if (!region.isValid()) {
+ continue;
+ }
+
+ if (currentCollapsed == null || !contains(currentCollapsed, region)) {
visible.add(region);
- if (!region.isExpanded()) {
- if (currentToplevel == null || currentToplevel.getEndOffset() < region.getStartOffset()) {
- currentToplevel = region;
- topLevels.add(region);
- }
+ }
+
+ if (!region.isExpanded()) {
+ if (currentCollapsed == null || currentCollapsed.getEndOffset() < region.getStartOffset()) {
+ currentCollapsed = region;
+ topLevels.add(region);
}
}
}
myCachedTopLevelRegions = toFoldArray(topLevels);
-
- Arrays.sort(myCachedTopLevelRegions, BY_END_OFFSET);
-
- FoldRegion[] visibleArrayed = toFoldArray(visible);
- for (FoldRegion visibleRegion : visibleArrayed) {
- for (FoldRegion topLevelRegion : myCachedTopLevelRegions) {
- if (contains(topLevelRegion, visibleRegion)) {
- visible.remove(visibleRegion);
- break;
- }
- }
- }
-
myCachedVisible = toFoldArray(visible);
+ Arrays.sort(myCachedTopLevelRegions, BY_END_OFFSET);
Arrays.sort(myCachedVisible, BY_END_OFFSET_REVERSE);
updateCachedOffsets();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingAnchorsOverlayStrategy.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingAnchorsOverlayStrategy.java
new file mode 100644
index 0000000..932a8b0
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingAnchorsOverlayStrategy.java
@@ -0,0 +1,113 @@
+/*
+ * 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.openapi.editor.impl;
+
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.FoldRegion;
+import com.intellij.openapi.editor.FoldingGroup;
+import com.intellij.util.containers.hash.HashMap;
+
+import java.util.Collection;
+import java.util.Map;
+
+class FoldingAnchorsOverlayStrategy {
+ private final EditorImpl myEditor;
+
+ public FoldingAnchorsOverlayStrategy(EditorImpl editor) {
+ myEditor = editor;
+ }
+
+ public Collection<DisplayedFoldingAnchor> getAnchorsToDisplay(int firstVisibleOffset, int lastVisibleOffset, FoldRegion activeFoldRegion) {
+ Map<Integer, DisplayedFoldingAnchor> result = new HashMap<Integer, DisplayedFoldingAnchor>();
+ FoldRegion[] visibleFoldRegions = myEditor.getFoldingModel().fetchVisible();
+ for (FoldRegion region : visibleFoldRegions) {
+ if (!region.isValid()) continue;
+ final int startOffset = region.getStartOffset();
+ if (startOffset > lastVisibleOffset) continue;
+ final int endOffset = getEndOffset(region);
+ if (endOffset < firstVisibleOffset) continue;
+ if (!isFoldingPossible(startOffset, endOffset)) continue;
+
+ final FoldingGroup group = region.getGroup();
+ if (group != null && myEditor.getFoldingModel().getFirstRegion(group, region) != region) continue;
+
+ //offset = Math.min(myEditor.getDocument().getTextLength() - 1, offset);
+ int foldStart = myEditor.offsetToVisualLine(startOffset);
+
+ if (!region.isExpanded()) {
+ tryAdding(result, region, foldStart, 0, DisplayedFoldingAnchor.Type.COLLAPSED, activeFoldRegion);
+ }
+ else {
+ //offset = Math.min(myEditor.getDocument().getTextLength() - 1, offset);
+ int foldEnd = myEditor.offsetToVisualLine(endOffset);
+ tryAdding(result, region, foldStart, foldEnd - foldStart, DisplayedFoldingAnchor.Type.EXPANDED_TOP, activeFoldRegion);
+ tryAdding(result, region, foldEnd, foldEnd - foldStart, DisplayedFoldingAnchor.Type.EXPANDED_BOTTOM, activeFoldRegion);
+ }
+ }
+ return result.values();
+ }
+
+ private static void tryAdding(Map<Integer, DisplayedFoldingAnchor> resultsMap,
+ FoldRegion region,
+ int visualLine,
+ int visualHeight,
+ DisplayedFoldingAnchor.Type type,
+ FoldRegion activeRegion) {
+ DisplayedFoldingAnchor prev = resultsMap.get(visualLine);
+ if (prev != null) {
+ if (prev.foldRegion == activeRegion) {
+ return;
+ }
+ if (region != activeRegion && prev.foldRegionVisualLines < visualHeight) {
+ return;
+ }
+ }
+ resultsMap.put(visualLine, new DisplayedFoldingAnchor(region, visualLine, visualHeight, type));
+ }
+
+ private int getEndOffset(FoldRegion foldRange) {
+ FoldingGroup group = foldRange.getGroup();
+ return group == null ? foldRange.getEndOffset() : myEditor.getFoldingModel().getEndOffset(group);
+ }
+
+ /**
+ * Allows to answer if there may be folding for the given offsets.
+ * <p/>
+ * The rule is that we can fold range that occupies multiple logical or visual lines.
+ *
+ * @param startOffset start offset of the target region to check
+ * @param endOffset end offset of the target region to check
+ * @return
+ */
+ private boolean isFoldingPossible(int startOffset, int endOffset) {
+ Document document = myEditor.getDocument();
+ if (startOffset >= document.getTextLength()) {
+ return false;
+ }
+
+ int endOffsetToUse = Math.min(endOffset, document.getTextLength());
+ if (endOffsetToUse <= startOffset) {
+ return false;
+ }
+
+ if (document.getLineNumber(startOffset) != document.getLineNumber(endOffsetToUse)) {
+ return true;
+ }
+ return myEditor.getSettings().isAllowSingleLogicalLineFolding()
+ && !myEditor.getSoftWrapModel().getSoftWrapsForRange(startOffset, endOffsetToUse).isEmpty();
+ }
+
+}
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 1d24154..962230e 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
@@ -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.
@@ -25,11 +25,13 @@
package com.intellij.openapi.editor.impl;
import com.intellij.diagnostic.Dumpable;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.FoldRegion;
import com.intellij.openapi.editor.FoldingGroup;
import com.intellij.openapi.editor.LogicalPosition;
+import com.intellij.openapi.editor.ScrollingModel;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.ex.DocumentEx;
@@ -37,6 +39,8 @@
import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
import com.intellij.openapi.editor.markup.TextAttributes;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,13 +49,11 @@
import java.awt.*;
import java.util.Arrays;
import java.util.List;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentListener, Dumpable {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.EditorFoldingModelImpl");
- private final Set<FoldingListener> myListeners = new CopyOnWriteArraySet<FoldingListener>();
+ private final List<FoldingListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private boolean myIsFoldingEnabled;
private final EditorImpl myEditor;
@@ -63,7 +65,7 @@
private int mySavedCaretX;
private int mySavedCaretY;
- private int mySavedCaretShift;
+ private int mySavedCaretPositionBeforeBatchFolding;
private boolean myCaretPositionSaved;
private final MultiMap<FoldingGroup, FoldRegion> myGroups = new MultiMap<FoldingGroup, FoldRegion>();
private boolean myDocumentChangeProcessed = true;
@@ -205,8 +207,7 @@
myDoNotCollapseCaret |= dontCollapseCaret;
boolean oldBatchFlag = myIsBatchFoldingProcessing;
if (!oldBatchFlag) {
- mySavedCaretShift =
- myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - myEditor.getScrollingModel().getVerticalScrollOffset();
+ mySavedCaretPositionBeforeBatchFolding = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line);
}
myIsBatchFoldingProcessing = true;
@@ -229,8 +230,12 @@
runBatchFoldingOperation(operation, true, true);
}
+ /**
+ * Disables caret position adjustment after batch folding operation is finished.
+ * Should be called from inside batch operation runnable.
+ */
public void flushCaretShift() {
- mySavedCaretShift = -1;
+ mySavedCaretPositionBeforeBatchFolding = -1;
}
@Override
@@ -287,6 +292,19 @@
}
public void dispose() {
+ doClearFoldRegions();
+ }
+
+ @Override
+ public void clearFoldRegions() {
+ if (!myIsBatchFoldingProcessing) {
+ LOG.error("Fold regions must be added or removed inside batchFoldProcessing() only.");
+ return;
+ }
+ doClearFoldRegions();
+ }
+
+ public void doClearFoldRegions() {
myGroups.clear();
myFoldTree.clear();
}
@@ -413,11 +431,18 @@
myEditor.getSelectionModel().setSelection(selectionStart, selectionEnd);
}
- if (mySavedCaretShift > 0) {
- myEditor.getScrollingModel().disableAnimation();
- int scrollTo = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - mySavedCaretShift;
- myEditor.getScrollingModel().scrollVertically(scrollTo);
- myEditor.getScrollingModel().enableAnimation();
+ if (mySavedCaretPositionBeforeBatchFolding >= 0) {
+ final int offset = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - mySavedCaretPositionBeforeBatchFolding;
+ final ScrollingModel scrollingModel = myEditor.getScrollingModel();
+ scrollingModel.runActionOnScrollingFinished(new Runnable() {
+ @Override
+ public void run() {
+ scrollingModel.disableAnimation();
+ int pos = scrollingModel.getVerticalScrollOffset();
+ scrollingModel.scrollVertically(pos + offset);
+ scrollingModel.enableAnimation();
+ }
+ });
}
}
@@ -515,14 +540,16 @@
}
@Override
- public boolean addListener(@NotNull FoldingListener listener) {
- return myListeners.add(listener);
+ public void addListener(@NotNull final FoldingListener listener, @NotNull Disposable parentDisposable) {
+ myListeners.add(listener);
+ Disposer.register(parentDisposable, new Disposable() {
+ @Override
+ public void dispose() {
+ myListeners.remove(listener);
+ }
+ });
}
- @Override
- public boolean removeListener(@NotNull FoldingListener listener) {
- return myListeners.remove(listener);
- }
private void notifyListenersOnFoldRegionStateChange(@NotNull FoldRegion foldRegion) {
for (FoldingListener listener : myListeners) {
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 d1169db..3f3ed7e 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
@@ -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.
@@ -25,6 +25,7 @@
import com.intellij.openapi.editor.highlighter.HighlighterIterator;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.util.Comparing;
+import com.intellij.util.ArrayUtilRt;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -86,14 +87,14 @@
private int myEndOffset;
private final int myEnd;
- private final int mySelectionStart;
+ private final int[] mySelectionStarts;
+ private final int[] mySelectionEnds;
+ private int myCurrentSelectionIndex = 0;
- private final int mySelectionEnd;
private final List<RangeHighlighterEx> myCurrentHighlighters = new ArrayList<RangeHighlighterEx>();
private final FoldingModelEx myFoldingModel;
- private final boolean hasSelection;
private FoldRegion myCurrentFold = null;
private final TextAttributes myFoldTextAttributes;
private final TextAttributes mySelectionAttributes;
@@ -121,9 +122,9 @@
LOG.assertTrue(myStartOffset <= myEnd);
myHighlighterIterator = editor.getHighlighter().createIterator(start);
- hasSelection = useCaretAndSelection && editor.getSelectionModel().hasSelection();
- mySelectionStart = hasSelection ? editor.getSelectionModel().getSelectionStart() : -1;
- mySelectionEnd = hasSelection ? editor.getSelectionModel().getSelectionEnd() : -1;
+ 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;
myFoldingModel = editor.getFoldingModel();
myFoldTextAttributes = myFoldingModel.getPlaceholderAttributes();
@@ -235,13 +236,14 @@
public void advance() {
myStartOffset = myEndOffset;
advanceSegmentHighlighters();
+ advanceCurrentSelectionIndex();
myCurrentFold = myFoldingModel.fetchOutermost(myStartOffset);
if (myCurrentFold != null) {
myEndOffset = myCurrentFold.getEndOffset();
}
else {
- myEndOffset = Math.min(getHighlighterEnd(myStartOffset), getSelectionEnd(myStartOffset));
+ myEndOffset = Math.min(getHighlighterEnd(myStartOffset), getSelectionEnd());
myEndOffset = Math.min(myEndOffset, getMinSegmentHighlightersEnd());
myEndOffset = Math.min(myEndOffset, getFoldRangesEnd(myStartOffset));
myEndOffset = Math.min(myEndOffset, getCaretEnd(myStartOffset));
@@ -290,17 +292,26 @@
return min;
}
- private int getSelectionEnd(int start) {
- if (!hasSelection) {
+ private void advanceCurrentSelectionIndex() {
+ while (myCurrentSelectionIndex < mySelectionEnds.length && myStartOffset >= mySelectionEnds[myCurrentSelectionIndex]) {
+ myCurrentSelectionIndex++;
+ }
+ }
+
+ private int getSelectionEnd() {
+ if (myCurrentSelectionIndex >= mySelectionStarts.length) {
return myEnd;
}
- if (mySelectionStart > start) {
- return mySelectionStart;
+ if (myStartOffset < mySelectionStarts[myCurrentSelectionIndex]) {
+ return mySelectionStarts[myCurrentSelectionIndex];
}
- if (mySelectionEnd > start) {
- return mySelectionEnd;
+ else {
+ return mySelectionEnds[myCurrentSelectionIndex];
}
- return myEnd;
+ }
+
+ private boolean isInSelection() {
+ return myCurrentSelectionIndex < mySelectionStarts.length && myStartOffset >= mySelectionStarts[myCurrentSelectionIndex];
}
private void advanceSegmentHighlighters() {
@@ -362,7 +373,7 @@
return;
}
- boolean isInSelection = hasSelection && myStartOffset >= mySelectionStart && myStartOffset < mySelectionEnd;
+ boolean isInSelection = isInSelection();
boolean isInCaretRow = myStartOffset >= myCaretRowStart && myStartOffset < myCaretRowEnd;
boolean isInGuardedBlock = myDocument.getOffsetGuard(myStartOffset) != null;
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java
index 8db2028..175889d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -36,6 +36,7 @@
import com.intellij.openapi.editor.event.VisibleAreaListener;
import com.intellij.openapi.editor.ex.ScrollingModelEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.util.Disposer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.Animator;
import org.jetbrains.annotations.NotNull;
@@ -124,19 +125,18 @@
return myEditor.getScrollPane().getViewport().getViewRect();
}
+ @NotNull
@Override
public Rectangle getVisibleAreaOnScrollingFinished() {
assertIsDispatchThread();
if (myCurrentAnimationRequest != null) {
return myCurrentAnimationRequest.getTargetVisibleArea();
}
- else {
- return getVisibleArea();
- }
+ return getVisibleArea();
}
@Override
- public void scrollToCaret(ScrollType scrollType) {
+ public void scrollToCaret(@NotNull ScrollType scrollType) {
assertIsDispatchThread();
LogicalPosition caretPosition = myEditor.getCaretModel().getLogicalPosition();
myEditor.validateSize();
@@ -144,7 +144,7 @@
}
@Override
- public void scrollTo(LogicalPosition pos, ScrollType scrollType) {
+ public void scrollTo(@NotNull LogicalPosition pos, @NotNull ScrollType scrollType) {
assertIsDispatchThread();
if (myEditor.getScrollPane() == null) return;
@@ -160,7 +160,7 @@
}
@Override
- public void runActionOnScrollingFinished(Runnable action) {
+ public void runActionOnScrollingFinished(@NotNull Runnable action) {
assertIsDispatchThread();
if (myCurrentAnimationRequest != null) {
@@ -317,7 +317,7 @@
scrollbar.setValue(scrollOffset);
}
- private void scrollToOffsets(int hOffset, int vOffset) {
+ void scrollToOffsets(int hOffset, int vOffset) {
if (myAccumulateViewportChanges) {
myAccumulatedXOffset = hOffset;
myAccumulatedYOffset = vOffset;
@@ -372,12 +372,12 @@
}
@Override
- public void addVisibleAreaListener(VisibleAreaListener listener) {
+ public void addVisibleAreaListener(@NotNull VisibleAreaListener listener) {
myVisibleAreaListeners.add(listener);
}
@Override
- public void removeVisibleAreaListener(VisibleAreaListener listener) {
+ public void removeVisibleAreaListener(@NotNull VisibleAreaListener listener) {
boolean success = myVisibleAreaListeners.remove(listener);
LOG.assertTrue(success);
}
@@ -435,7 +435,6 @@
private final ArrayList<Runnable> myPostRunnables = new ArrayList<Runnable>();
- private final Runnable myStartCommand;
private final int myHDist;
private final int myVDist;
private final int myMaxDistToScroll;
@@ -474,8 +473,6 @@
}
myPow = myScrollDist > 0 ? setupPow(firstStepTime, firstScrollDist / myScrollDist) : 1;
- myStartCommand = CommandProcessor.getInstance().getCurrentCommand();
-
myAnimator = new Animator("Animated scroller", myStepCount, SCROLL_DURATION, false, true) {
@Override
public void paintNow(int frame, int totalFrames, int cycle) {
@@ -498,16 +495,12 @@
myAnimator.resume();
}
+ @NotNull
public Rectangle getTargetVisibleArea() {
Rectangle viewRect = getVisibleArea();
return new Rectangle(myEndHOffset, myEndVOffset, viewRect.width, viewRect.height);
}
- // Commented as the method is not used
- //public Runnable getStartCommand() {
- // return myStartCommand;
- //}
-
public void cancel(boolean scrollToTarget) {
assertIsDispatchThread();
finish(scrollToTarget);
@@ -524,7 +517,7 @@
executePostRunnables();
}
- myAnimator.dispose();
+ Disposer.dispose(myAnimator);
if (myCurrentAnimationRequest == this) {
myCurrentAnimationRequest = null;
}
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 98bab58..90780f1 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
@@ -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,128 +24,55 @@
*/
package com.intellij.openapi.editor.impl;
-import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
-import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
-import com.intellij.openapi.editor.actionSystem.EditorActionManager;
-import com.intellij.openapi.editor.actions.EditorActionUtil;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsScheme;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.SelectionEvent;
import com.intellij.openapi.editor.event.SelectionListener;
import com.intellij.openapi.editor.ex.DocumentEx;
-import com.intellij.openapi.editor.ex.FoldingModelEx;
import com.intellij.openapi.editor.ex.PrioritizedDocumentListener;
import com.intellij.openapi.editor.ex.util.EditorUtil;
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;
-import com.intellij.util.ui.EmptyClipboardOwner;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.awt.*;
-import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
-import java.util.List;
+import java.util.*;
public class SelectionModelImpl implements SelectionModel, PrioritizedDocumentListener {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.impl.SelectionModelImpl");
private final List<SelectionListener> mySelectionListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- private volatile MyRangeMarker mySelectionMarker;
private final EditorImpl myEditor;
- private int myLastSelectionStart;
+
+ private TextAttributes myTextAttributes;
+
private LogicalPosition myBlockStart;
private LogicalPosition myBlockEnd;
- private TextAttributes myTextAttributes;
- private DocumentEvent myIsInUpdate;
private int[] myBlockSelectionStarts;
private int[] myBlockSelectionEnds;
- private boolean myUnknownDirection;
- private class MyRangeMarker extends RangeMarkerImpl {
- private VisualPosition myStartPosition;
- private VisualPosition myEndPosition;
- private boolean myEndPositionIsLead;
- private boolean myIsReleased;
+ private DocumentEvent myIsInUpdate;
- MyRangeMarker(DocumentEx document, int start, int end) {
- super(document, start, end, true);
- myIsReleased = false;
- }
-
- public void release() {
- myIsReleased = true;
- dispose();
- }
-
- @Nullable
- public VisualPosition getStartPosition() {
- invalidateVisualPositions();
- return myStartPosition;
- }
-
- public void setStartPosition(@NotNull VisualPosition startPosition) {
- myStartPosition = startPosition;
- }
-
- @Nullable
- public VisualPosition getEndPosition() {
- invalidateVisualPositions();
- return myEndPosition;
- }
-
- public void setEndPosition(@NotNull VisualPosition endPosition) {
- myEndPosition = endPosition;
- }
-
- public boolean isEndPositionIsLead() {
- return myEndPositionIsLead;
- }
-
- public void setEndPositionIsLead(boolean endPositionIsLead) {
- myEndPositionIsLead = endPositionIsLead;
- }
-
- int startBefore;
- int endBefore;
-
- @Override
- protected void changedUpdateImpl(DocumentEvent e) {
- if (myIsReleased) return;
- startBefore = getStartOffset();
- endBefore = getEndOffset();
- super.changedUpdateImpl(e);
- }
-
- private void invalidateVisualPositions() {
- SoftWrapModelImpl model = myEditor.getSoftWrapModel();
- if (!myEditor.offsetToVisualPosition(getStartOffset()).equals(myStartPosition) && model.getSoftWrap(getStartOffset()) == null
- || !myEditor.offsetToVisualPosition(getEndOffset()).equals(myEndPosition) && model.getSoftWrap(getEndOffset()) == null) {
- myStartPosition = null;
- myEndPosition = null;
- }
- }
+ public SelectionModelImpl(EditorImpl editor) {
+ myEditor = editor;
}
- private int startBefore;
- private int endBefore;
-
@Override
public void beforeDocumentChange(DocumentEvent event) {
myIsInUpdate = event;
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null && marker.isValid()) {
- startBefore = marker.getStartOffset();
- endBefore = marker.getEndOffset();
+ for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
+ ((CaretImpl)caret).beforeDocumentChange();
}
}
@@ -153,25 +80,13 @@
public void documentChanged(DocumentEvent event) {
if (myIsInUpdate == event) {
myIsInUpdate = null;
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null) {
- int endAfter;
- int startAfter;
- if (marker.isValid()) {
- startAfter = marker.getStartOffset();
- endAfter = marker.getEndOffset();
+ myEditor.getCaretModel().doWithCaretMerging(new Runnable() {
+ public void run() {
+ for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
+ ((CaretImpl)caret).documentChanged();
+ }
}
- else {
- myLastSelectionStart = myEditor.getCaretModel().getOffset();
- marker.release();
- mySelectionMarker = null;
- startAfter = endAfter = myLastSelectionStart;
- }
-
- if (startBefore != startAfter || endBefore != endAfter) {
- fireSelectionChanged(startBefore, endBefore, startAfter, endAfter);
- }
- }
+ });
}
}
@@ -180,265 +95,76 @@
return EditorDocumentPriorities.SELECTION_MODEL;
}
- public SelectionModelImpl(EditorImpl editor) {
- myEditor = editor;
+ /**
+ * @see CaretImpl#setUnknownDirection(boolean)
+ */
+ public boolean isUnknownDirection() {
+ return myEditor.getCaretModel().getCurrentCaret().isUnknownDirection();
+ }
+
+ /**
+ * @see CaretImpl#setUnknownDirection(boolean)
+ */
+ public void setUnknownDirection(boolean unknownDirection) {
+ myEditor.getCaretModel().getCurrentCaret().setUnknownDirection(unknownDirection);
}
@Override
public int getSelectionStart() {
- validateContext(false);
- if (hasSelection()) {
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null) {
- return marker.getStartOffset();
- }
- }
- return myEditor.getCaretModel().getOffset();
+ return myEditor.getCaretModel().getCurrentCaret().getSelectionStart();
}
@NotNull
@Override
public VisualPosition getSelectionStartPosition() {
- VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionStart());
- if (!hasSelection()) {
- return defaultPosition;
- }
-
- MyRangeMarker marker = mySelectionMarker;
- if (marker == null) {
- return defaultPosition;
- }
-
- VisualPosition result = marker.getStartPosition();
- return result == null ? defaultPosition : result;
- }
-
- private void validateContext(boolean isWrite) {
-
- if (!myEditor.getComponent().isShowing()) return;
- if (isWrite) {
- ApplicationManager.getApplication().assertIsDispatchThread();
- }
- else {
- ApplicationManager.getApplication().assertReadAccessAllowed();
- }
-
- //if (myIsInUpdate != null) {
- // documentChanged(myIsInUpdate);
- //}
- }
-
- /**
- * @return information on whether current selection's direction in known
- * @see #setUnknownDirection(boolean)
- */
- public boolean isUnknownDirection() {
- return myUnknownDirection;
- }
-
- /**
- * There is a possible case that we don't know selection's direction. For example, a user might triple-click editor (select the
- * whole line). We can't say what selection end is a {@link #getLeadSelectionOffset() leading end} then. However, that matters
- * in a situation when a user clicks before or after that line holding Shift key. It's expected that the selection is expanded
- * up to that point than.
- * <p/>
- * That's why we allow to specify that the direction is unknown and {@link #isUnknownDirection() expose this information}
- * later.
- * <p/>
- * <b>Note:</b> when this method is called with <code>'true'</code>, subsequent calls are guaranteed to return <code>'true'</code>
- * until selection is changed. 'Unknown direction' flag is automatically reset then.
- *
- * @param unknownDirection
- */
- public void setUnknownDirection(boolean unknownDirection) {
- myUnknownDirection = unknownDirection;
+ return myEditor.getCaretModel().getCurrentCaret().getSelectionStartPosition();
}
@Override
public int getSelectionEnd() {
- validateContext(false);
- if (hasSelection()) {
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null) {
- return marker.getEndOffset();
- }
- }
- return myEditor.getCaretModel().getOffset();
+ return myEditor.getCaretModel().getCurrentCaret().getSelectionEnd();
}
@NotNull
@Override
public VisualPosition getSelectionEndPosition() {
- VisualPosition defaultPosition = myEditor.offsetToVisualPosition(getSelectionEnd());
- if (!hasSelection()) {
- return defaultPosition;
- }
-
- MyRangeMarker marker = mySelectionMarker;
- if (marker == null) {
- return defaultPosition;
- }
-
- VisualPosition result = marker.getEndPosition();
- return result == null ? defaultPosition : result;
+ return myEditor.getCaretModel().getCurrentCaret().getSelectionEndPosition();
}
@Override
public boolean hasSelection() {
- validateContext(false);
- MyRangeMarker marker = mySelectionMarker;
- //if (marker != null && !marker.isValid()) {
- // removeSelection();
- //}
+ return hasSelection(false);
+ }
- return marker != null && marker.isValid() && marker.getEndOffset() > marker.getStartOffset();
+ @Override
+ public boolean hasSelection(boolean anyCaret) {
+ if (!anyCaret) {
+ return myEditor.getCaretModel().getCurrentCaret().hasSelection();
+ }
+ for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
+ if (caret.hasSelection()) {
+ return true;
+ }
+ }
+ return false;
}
@Override
public void setSelection(int startOffset, int endOffset) {
- doSetSelection(myEditor.offsetToVisualPosition(startOffset), startOffset, myEditor.offsetToVisualPosition(endOffset), endOffset, false);
+ myEditor.getCaretModel().getCurrentCaret().setSelection(startOffset, endOffset);
}
@Override
public void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
- VisualPosition startPosition;
- if (hasSelection()) {
- startPosition = getLeadSelectionPosition();
- }
- else {
- startPosition = myEditor.offsetToVisualPosition(startOffset);
- }
- setSelection(startPosition, startOffset, endPosition, endOffset);
+ myEditor.getCaretModel().getCurrentCaret().setSelection(startOffset, endPosition, endOffset);
}
@Override
public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
- VisualPosition startPositionToUse = startPosition == null ? myEditor.offsetToVisualPosition(startOffset) : startPosition;
- VisualPosition endPositionToUse = endPosition == null ? myEditor.offsetToVisualPosition(endOffset) : endPosition;
- doSetSelection(startPositionToUse, startOffset, endPositionToUse, endOffset, true);
+ myEditor.getCaretModel().getCurrentCaret().setSelection(startPosition, startOffset, endPosition, endOffset);
}
- private void doSetSelection(@NotNull VisualPosition startPosition,
- int startOffset,
- @NotNull VisualPosition endPosition,
- int endOffset,
- boolean visualPositionAware)
- {
- myUnknownDirection = false;
- final Document doc = myEditor.getDocument();
- final Pair<String, String> markers = myEditor.getUserData(EditorImpl.EDITABLE_AREA_MARKER);
- if (markers != null) {
- final String text = doc.getText();
- final int start = text.indexOf(markers.first) + markers.first.length();
- final int end = text.indexOf(markers.second);
- if (startOffset < endOffset) {
- if (startOffset < start) {
- startOffset = start;
- startPosition = myEditor.offsetToVisualPosition(startOffset);
- }
- if (endOffset > end) {
- endOffset = end;
- endPosition = myEditor.offsetToVisualPosition(endOffset);
- }
- }
- else {
- if (endOffset < start) {
- endOffset = start;
- endPosition = myEditor.offsetToVisualPosition(startOffset);
- }
- if (startOffset > end) {
- startOffset = end;
- startPosition = myEditor.offsetToVisualPosition(endOffset);
- }
- }
- }
-
- validateContext(true);
-
- removeBlockSelection();
-
- int textLength = doc.getTextLength();
- if (startOffset < 0 || startOffset > textLength) {
- LOG.error("Wrong startOffset: " + startOffset + ", textLength=" + textLength);
- }
- if (endOffset < 0 || endOffset > textLength) {
- LOG.error("Wrong endOffset: " + endOffset + ", textLength=" + textLength);
- }
-
- myLastSelectionStart = startOffset;
- if (!visualPositionAware && startOffset == endOffset) {
- removeSelection();
- return;
- }
-
- /* Normalize selection */
- if (startOffset > endOffset) {
- int tmp = startOffset;
- startOffset = endOffset;
- endOffset = tmp;
- }
-
- FoldingModelEx foldingModel = myEditor.getFoldingModel();
- FoldRegion startFold = foldingModel.getCollapsedRegionAtOffset(startOffset);
- if (startFold != null && startFold.getStartOffset() < startOffset) {
- startOffset = startFold.getStartOffset();
- }
-
- FoldRegion endFold = foldingModel.getCollapsedRegionAtOffset(endOffset);
- if (endFold != null && endFold.getStartOffset() < endOffset) {
- // All visual positions that lay at collapsed fold region placeholder are mapped to the same offset. Hence, there are
- // at least two distinct situations - selection end is located inside collapsed fold region placeholder and just before it.
- // We want to expand selection to the fold region end at the former case and keep selection as-is at the latest one.
- endOffset = endFold.getEndOffset();
- }
-
- int oldSelectionStart;
- int oldSelectionEnd;
-
- if (hasSelection()) {
- oldSelectionStart = getSelectionStart();
- oldSelectionEnd = getSelectionEnd();
- if (oldSelectionStart == startOffset && oldSelectionEnd == endOffset && !visualPositionAware) return;
- }
- else {
- oldSelectionStart = oldSelectionEnd = myEditor.getCaretModel().getOffset();
- }
-
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null) {
- marker.release();
- }
-
- marker = new MyRangeMarker((DocumentEx)doc, startOffset, endOffset);
- if (visualPositionAware) {
- if (endPosition.after(startPosition)) {
- marker.setStartPosition(startPosition);
- marker.setEndPosition(endPosition);
- marker.setEndPositionIsLead(false);
- }
- else {
- marker.setStartPosition(endPosition);
- marker.setEndPosition(startPosition);
- marker.setEndPositionIsLead(true);
- }
- }
- mySelectionMarker = marker;
-
- fireSelectionChanged(oldSelectionStart, oldSelectionEnd, startOffset, endOffset);
-
- updateSystemSelection();
- }
-
- private void updateSystemSelection() {
- if (GraphicsEnvironment.isHeadless()) return;
-
- final Clipboard clip = myEditor.getComponent().getToolkit().getSystemSelection();
- if (clip != null) {
- clip.setContents(new StringSelection(getSelectedText()), EmptyClipboardOwner.INSTANCE);
- }
- }
-
- private void fireSelectionChanged(int oldSelectionStart, int oldSelectionEnd, int startOffset, int endOffset) {
+ void fireSelectionChanged(int oldSelectionStart, int oldSelectionEnd, int startOffset, int endOffset) {
repaintBySelectionChange(oldSelectionStart, startOffset, oldSelectionEnd, endOffset);
SelectionEvent event = new SelectionEvent(myEditor,
@@ -465,77 +191,99 @@
}
@Override
- public void setBlockSelection(LogicalPosition blockStart, LogicalPosition blockEnd) {
- removeSelection();
+ public void removeSelection() {
+ removeSelection(false);
+ }
- int oldStartLine = 0;
- int oldEndLine = 0;
-
- if (hasBlockSelection()) {
- oldStartLine = myBlockStart.line;
- oldEndLine = myBlockEnd.line;
- if (oldStartLine > oldEndLine) {
- int t = oldStartLine;
- oldStartLine = oldEndLine;
- oldEndLine = t;
+ @Override
+ public void removeSelection(boolean allCarets) {
+ if (!allCarets) {
+ myEditor.getCaretModel().getCurrentCaret().removeSelection();
+ }
+ else {
+ for (Caret caret : myEditor.getCaretModel().getAllCarets()) {
+ caret.removeSelection();
}
}
-
- int newStartLine = blockStart.line;
- int newEndLine = blockEnd.line;
-
- if (newStartLine > newEndLine) {
- int t = newStartLine;
- newStartLine = newEndLine;
- newEndLine = t;
- }
-
- myEditor.repaintLines(Math.min(oldStartLine, newStartLine), Math.max(newEndLine, oldEndLine));
-
- final int[] oldStarts = getBlockSelectionStarts();
- final int[] oldEnds = getBlockSelectionEnds();
-
- myBlockStart = blockStart;
- myBlockEnd = blockEnd;
- recalculateBlockOffsets();
-
- final int[] newStarts = getBlockSelectionStarts();
- final int[] newEnds = getBlockSelectionEnds();
-
- broadcastSelectionEvent(new SelectionEvent(myEditor, oldStarts, oldEnds, newStarts, newEnds));
}
@Override
- public void removeSelection() {
- if (myEditor.isStickySelection()) {
- // Most of our 'change caret position' actions (like move caret to word start/end etc) remove active selection.
- // However, we don't want to do that for 'sticky selection'.
- return;
+ public void setBlockSelection(@NotNull LogicalPosition blockStart, @NotNull LogicalPosition blockEnd) {
+ if (myEditor.getCaretModel().supportsMultipleCarets()) {
+ int startLine = Math.max(Math.min(blockStart.line, myEditor.getDocument().getLineCount() - 1), 0);
+ 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>();
+ 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 caretPos = new LogicalPosition(line, Math.min(startColumn, endColumn));
+ positions.add(caretPos);
+ selections.add(new TextRange(lineEndOffset, lineEndOffset));
+ }
+ else {
+ LogicalPosition startPos = new LogicalPosition(line, Math.min(startColumn, lineWidth));
+ LogicalPosition endPos = new LogicalPosition(line, 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)));
+ 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();
+ }
+ }
+ }
+ myEditor.getCaretModel().setCarets(positions, selections);
}
- validateContext(true);
- removeBlockSelection();
- myLastSelectionStart = myEditor.getCaretModel().getOffset();
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null) {
- int startOffset = marker.getStartOffset();
- int endOffset = marker.getEndOffset();
- marker.release();
- mySelectionMarker = null;
- fireSelectionChanged(startOffset, endOffset, myLastSelectionStart, myLastSelectionStart);
- }
- }
+ else {
+ removeSelection();
- @Override
- public void removeBlockSelection() {
- myUnknownDirection = false;
- if (hasBlockSelection()) {
- myEditor.repaint(0, myEditor.getDocument().getTextLength());
+ int oldStartLine = 0;
+ int oldEndLine = 0;
+
+ if (hasBlockSelection()) {
+ oldStartLine = myBlockStart.line;
+ oldEndLine = myBlockEnd.line;
+ if (oldStartLine > oldEndLine) {
+ int t = oldStartLine;
+ oldStartLine = oldEndLine;
+ oldEndLine = t;
+ }
+ }
+
+ int newStartLine = blockStart.line;
+ int newEndLine = blockEnd.line;
+
+ if (newStartLine > newEndLine) {
+ int t = newStartLine;
+ newStartLine = newEndLine;
+ newEndLine = t;
+ }
+
+ myEditor.repaintLines(Math.min(oldStartLine, newStartLine), Math.max(newEndLine, oldEndLine));
final int[] oldStarts = getBlockSelectionStarts();
final int[] oldEnds = getBlockSelectionEnds();
- myBlockStart = null;
- myBlockEnd = null;
+ myBlockStart = blockStart;
+ myBlockEnd = blockEnd;
+ recalculateBlockOffsets();
final int[] newStarts = getBlockSelectionStarts();
final int[] newEnds = getBlockSelectionEnds();
@@ -545,6 +293,27 @@
}
@Override
+ public void removeBlockSelection() {
+ if (!myEditor.getCaretModel().supportsMultipleCarets()) {
+ myEditor.getCaretModel().getCurrentCaret().setUnknownDirection(false);
+ if (hasBlockSelection()) {
+ myEditor.repaint(0, myEditor.getDocument().getTextLength());
+
+ final int[] oldStarts = getBlockSelectionStarts();
+ final int[] oldEnds = getBlockSelectionEnds();
+
+ myBlockStart = null;
+ myBlockEnd = null;
+
+ final int[] newStarts = getBlockSelectionStarts();
+ final int[] newEnds = getBlockSelectionEnds();
+
+ broadcastSelectionEvent(new SelectionEvent(myEditor, oldStarts, oldEnds, newStarts, newEnds));
+ }
+ }
+ }
+
+ @Override
public boolean hasBlockSelection() {
return myBlockStart != null;
}
@@ -648,28 +417,48 @@
@Override
@NotNull
public int[] getBlockSelectionStarts() {
- if (hasSelection()) {
- return new int[]{getSelectionStart()};
- }
- else if (!hasBlockSelection() || myBlockSelectionStarts == null) {
- return ArrayUtil.EMPTY_INT_ARRAY;
- }
- else {
- return myBlockSelectionStarts;
+ if (myEditor.getCaretModel().supportsMultipleCarets()) {
+ Collection<Caret> carets = myEditor.getCaretModel().getAllCarets();
+ int[] result = new int[carets.size()];
+ int i = 0;
+ for (Caret caret : carets) {
+ result[i++] = caret.getSelectionStart();
+ }
+ return result;
+ } else {
+ if (hasSelection()) {
+ return new int[]{getSelectionStart()};
+ }
+ else if (!hasBlockSelection() || myBlockSelectionStarts == null) {
+ return ArrayUtil.EMPTY_INT_ARRAY;
+ }
+ else {
+ return myBlockSelectionStarts;
+ }
}
}
@Override
@NotNull
public int[] getBlockSelectionEnds() {
- if (hasSelection()) {
- return new int[]{getSelectionEnd()};
- }
- else if (!hasBlockSelection() || myBlockSelectionEnds == null) {
- return ArrayUtil.EMPTY_INT_ARRAY;
- }
- else {
- return myBlockSelectionEnds;
+ if (myEditor.getCaretModel().supportsMultipleCarets()) {
+ Collection<Caret> carets = myEditor.getCaretModel().getAllCarets();
+ int[] result = new int[carets.size()];
+ int i = 0;
+ for (Caret caret : carets) {
+ result[i++] = caret.getSelectionEnd();
+ }
+ return result;
+ } else {
+ if (hasSelection()) {
+ return new int[]{getSelectionEnd()};
+ }
+ else if (!hasBlockSelection() || myBlockSelectionEnds == null) {
+ return ArrayUtil.EMPTY_INT_ARRAY;
+ }
+ else {
+ return myBlockSelectionEnds;
+ }
}
}
@@ -686,14 +475,18 @@
@Override
public String getSelectedText() {
+ return getSelectedText(false);
+ }
+
+ @Override
+ public String getSelectedText(boolean allCarets) {
validateContext(false);
- if (!hasSelection() && !hasBlockSelection()) return null;
CharSequence text = myEditor.getDocument().getCharsSequence();
- if (hasBlockSelection()) {
+ if (hasBlockSelection() || (myEditor.getCaretModel().supportsMultipleCarets() && allCarets)) {
int[] starts = getBlockSelectionStarts();
int[] ends = getBlockSelectionEnds();
- int width = Math.abs(myBlockEnd.column - myBlockStart.column);
+ int width = myEditor.getCaretModel().supportsMultipleCarets() ? 0 : Math.abs(myBlockEnd.column - myBlockStart.column);
final StringBuilder buf = new StringBuilder();
for (int i = 0; i < starts.length; i++) {
if (i > 0) buf.append('\n');
@@ -704,9 +497,7 @@
return buf.toString();
}
- int selectionStart = getSelectionStart();
- int selectionEnd = getSelectionEnd();
- return text.subSequence(selectionStart, selectionEnd).toString();
+ return myEditor.getCaretModel().getCurrentCaret().getSelectedText();
}
private static void appendCharSequence(@NotNull StringBuilder buf, @NotNull CharSequence s, int srcOffset, int len) {
@@ -722,65 +513,6 @@
}
}
- @Override
- public int getLeadSelectionOffset() {
- validateContext(false);
- int caretOffset = myEditor.getCaretModel().getOffset();
- if (hasSelection()) {
- MyRangeMarker marker = mySelectionMarker;
- if (marker != null) {
- int startOffset = marker.getStartOffset();
- int endOffset = marker.getEndOffset();
- if (caretOffset != startOffset && caretOffset != endOffset) {
- // Try to check if current selection is tweaked by fold region.
- FoldingModelEx foldingModel = myEditor.getFoldingModel();
- FoldRegion foldRegion = foldingModel.getCollapsedRegionAtOffset(caretOffset);
- if (foldRegion != null) {
- if (foldRegion.getStartOffset() == startOffset) {
- return endOffset;
- }
- else if (foldRegion.getEndOffset() == endOffset) {
- return startOffset;
- }
- }
- }
-
- if (caretOffset == endOffset) {
- return startOffset;
- }
- else {
- return endOffset;
- }
- }
- }
- return caretOffset;
- }
-
- @NotNull
- @Override
- public VisualPosition getLeadSelectionPosition() {
- MyRangeMarker marker = mySelectionMarker;
- VisualPosition caretPosition = myEditor.getCaretModel().getVisualPosition();
- if (marker == null) {
- return caretPosition;
- }
-
- if (marker.isEndPositionIsLead()) {
- VisualPosition result = marker.getEndPosition();
- return result == null ? getSelectionEndPosition() : result;
- }
- else {
- VisualPosition result = marker.getStartPosition();
- return result == null ? getSelectionStartPosition() : result;
- }
- }
-
- @Override
- public void selectLineAtCaret() {
- validateContext(true);
- doSelectLineAtCaret(myEditor);
- }
-
public static void doSelectLineAtCaret(Editor editor) {
int lineNumber = editor.getCaretModel().getLogicalPosition().line;
Document document = editor.getDocument();
@@ -802,72 +534,30 @@
}
@Override
+ public int getLeadSelectionOffset() {
+ return myEditor.getCaretModel().getCurrentCaret().getLeadSelectionOffset();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getLeadSelectionPosition() {
+ return myEditor.getCaretModel().getCurrentCaret().getLeadSelectionPosition();
+ }
+
+ @Override
+ public void selectLineAtCaret() {
+ myEditor.getCaretModel().getCurrentCaret().selectLineAtCaret();
+ }
+
+ @Override
public void selectWordAtCaret(boolean honorCamelWordsSettings) {
- validateContext(true);
- removeSelection();
- final EditorSettings settings = myEditor.getSettings();
- boolean camelTemp = settings.isCamelWords();
-
- final boolean needOverrideSetting = camelTemp && !honorCamelWordsSettings;
- if (needOverrideSetting) {
- settings.setCamelWords(false);
- }
-
- try {
- EditorActionHandler handler = EditorActionManager.getInstance().getActionHandler(
- IdeActions.ACTION_EDITOR_SELECT_WORD_AT_CARET);
- handler.execute(myEditor, myEditor.getDataContext());
- }
- finally {
- if (needOverrideSetting) {
- settings.resetCamelWords();
- }
- }
- }
-
- int getWordAtCaretStart() {
- Document document = myEditor.getDocument();
- int offset = myEditor.getCaretModel().getOffset();
- if (offset == 0) return 0;
- int lineNumber = myEditor.getCaretModel().getLogicalPosition().line;
- CharSequence text = document.getCharsSequence();
- int newOffset = offset - 1;
- int minOffset = lineNumber > 0 ? document.getLineEndOffset(lineNumber - 1) : 0;
- boolean camel = myEditor.getSettings().isCamelWords();
- for (; newOffset > minOffset; newOffset--) {
- if (EditorActionUtil.isWordStart(text, newOffset, camel)) break;
- }
-
- return newOffset;
- }
-
- int getWordAtCaretEnd() {
- Document document = myEditor.getDocument();
- int offset = myEditor.getCaretModel().getOffset();
-
- CharSequence text = document.getCharsSequence();
- if (offset >= document.getTextLength() - 1 || document.getLineCount() == 0) return offset;
-
- int newOffset = offset + 1;
-
- int lineNumber = myEditor.getCaretModel().getLogicalPosition().line;
- int maxOffset = document.getLineEndOffset(lineNumber);
- if (newOffset > maxOffset) {
- if (lineNumber + 1 >= document.getLineCount()) return offset;
- maxOffset = document.getLineEndOffset(lineNumber + 1);
- }
- boolean camel = myEditor.getSettings().isCamelWords();
- for (; newOffset < maxOffset; newOffset++) {
- if (EditorActionUtil.isWordEnd(text, newOffset, camel)) break;
- }
-
- return newOffset;
+ myEditor.getCaretModel().getCurrentCaret().selectWordAtCaret(honorCamelWordsSettings);
}
@Override
public void copySelectionToClipboard() {
validateContext(true);
- String s = myEditor.getSelectionModel().getSelectedText();
+ String s = getSelectedText(true);
if (s == null) return;
s = StringUtil.convertLineSeparators(s);
@@ -891,4 +581,14 @@
public void reinitSettings() {
myTextAttributes = null;
}
+
+ private void validateContext(boolean isWrite) {
+ if (!myEditor.getComponent().isShowing()) return;
+ if (isWrite) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+ }
+ else {
+ ApplicationManager.getApplication().assertReadAccessAllowed();
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java
index 237453d..dabf5e9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SettingsImpl.java
@@ -185,9 +185,9 @@
}
@Override
- public void setAdditionalColumnsCount(int additinalColumnsCount) {
- if (myAdditionalColumnsCount == additinalColumnsCount) return;
- myAdditionalColumnsCount = additinalColumnsCount;
+ public void setAdditionalColumnsCount(int additionalColumnsCount) {
+ if (myAdditionalColumnsCount == additionalColumnsCount) return;
+ myAdditionalColumnsCount = additionalColumnsCount;
fireEditorRefresh();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
index 9971e82..819a057 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/SoftWrapModelImpl.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.
@@ -70,7 +70,6 @@
private final FoldProcessingEndTask myFoldProcessingEndTask = new FoldProcessingEndTask();
private final List<DocumentListener> myDocumentListeners = new ArrayList<DocumentListener>();
- private final List<SoftWrapFoldingListener> myFoldListeners = new ArrayList<SoftWrapFoldingListener>();
private final List<SoftWrapChangeListener> mySoftWrapListeners = new ArrayList<SoftWrapChangeListener>();
/**
@@ -160,7 +159,6 @@
myVisualSizeManager = new SoftWrapAwareVisualSizeManager(painter);
myDocumentListeners.add(myApplianceManager);
- myFoldListeners.add(myApplianceManager);
applianceManager.addListener(myVisualSizeManager);
applianceManager.addListener(new SoftWrapAwareDocumentParsingListenerAdapter() {
@Override
@@ -551,7 +549,6 @@
caretModel.moveToVisualPosition(visualCaretPosition);
}
- @Override
public void setPlace(@NotNull SoftWrapAppliancePlaces place) {
myFoldBasedApplianceStrategy.setCurrentPlace(place);
}
@@ -625,7 +622,9 @@
myDirty = true;
return;
}
-
+
+ // We delay processing of changed fold regions till the invocation of onFoldProcessingEnd(), as
+ // FoldingModel can return inconsistent data before that moment.
myDeferredFoldRegions.add(new FoldRegionInfo(region));
}
@@ -663,7 +662,6 @@
myDeferredFoldRegions.clear();
}
- @Override
public void recalculate() {
myApplianceManager.reset();
myStorage.removeAll();
@@ -691,7 +689,7 @@
try {
task.run(true);
} catch (Throwable e) {
- if (Boolean.getBoolean(DEBUG_PROPERTY_NAME)) {
+ if (Boolean.getBoolean(DEBUG_PROPERTY_NAME) || ApplicationManager.getApplication().isUnitTestMode()) {
String info = "";
if (myEditor instanceof EditorImpl) {
info = ((EditorImpl)myEditor).dumpState();
@@ -815,28 +813,26 @@
}
try {
- for (FoldRegionInfo info : myDeferredFoldRegions) {
- // There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process
- // such nested region then.
- FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start);
- if (outerRegion != null && outerRegion != info.region && outerRegion.getStartOffset() <= info.start
- && outerRegion.getEndOffset() >= info.end)
- {
- continue;
- }
-
- for (SoftWrapFoldingListener listener : myFoldListeners) {
- listener.onFoldRegionStateChange(info.start, info.end);
+ if (!myDirty) { // no need to recalculate specific areas if the whole document will be reprocessed
+ for (FoldRegionInfo info : myDeferredFoldRegions) {
+ // There is a possible case that given fold region is contained inside another collapsed fold region. We don't want to process
+ // such nested region then.
+ FoldRegion outerRegion = myEditor.getFoldingModel().getCollapsedRegionAtOffset(info.start);
+ if (outerRegion != null && outerRegion != info.region && outerRegion.getStartOffset() <= info.start
+ && outerRegion.getEndOffset() >= info.end)
+ {
+ continue;
+ }
+
+ myApplianceManager.onFoldRegionStateChange(info.start, info.end);
}
}
}
finally {
myDeferredFoldRegions.clear();
}
-
- for (SoftWrapFoldingListener listener : myFoldListeners) {
- listener.onFoldProcessingEnd();
- }
+
+ myApplianceManager.onFoldProcessingEnd();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java
index ccd241e..d00eb48 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/ArrowSoftWrapPainter.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 @@
public ArrowSoftWrapPainter(Editor editor) {
myEditor = editor;
- myArrowPainter = new ArrowPainter(ColorProvider.byColor(myEditor.getColorsScheme().getDefaultForeground()), myHeightProvider);
+ myArrowPainter = new ArrowPainter(ColorProvider.byColor(myEditor.getColorsScheme().getDefaultForeground()), new WidthProvider(), myHeightProvider);
}
@Override
@@ -102,4 +102,11 @@
return myHeight;
}
}
+
+ private class WidthProvider implements Computable<Integer> {
+ @Override
+ public Integer compute() {
+ return EditorUtil.getSpaceWidth(Font.PLAIN, myEditor);
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java
deleted file mode 100644
index 0291cdb..0000000
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/SoftWrapFoldingListener.java
+++ /dev/null
@@ -1,51 +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 com.intellij.openapi.editor.impl.softwrap;
-
-import com.intellij.openapi.editor.FoldRegion;
-import com.intellij.openapi.editor.ex.FoldingListener;
-
-/**
- * Adapts {@link FoldingListener} to soft wraps specific.
- * <p/>
- * Generally, replaces {@link FoldingListener#onFoldRegionStateChange(FoldRegion)} by {@link #onFoldRegionStateChange(int, int)}.
- * The reason is that soft wraps are assumed to be processed after fold regions, i.e. every time the document is changed, folding
- * is processed at first place (notifying soft wraps via {@link FoldingListener}) and soft wraps are assumed to be processed
- * only on {@link #onFoldProcessingEnd()}. Hence, there is a possible case that changed {@link FoldRegion} object
- * is out-of-date (e.g. its offsets info is dropped if the region is removed), so, we can't use
- * {@link FoldingListener#onFoldRegionStateChange(FoldRegion)}.
- *
- * @author Denis Zhdanov
- * @since 5/4/11 3:48 PM
- */
-public interface SoftWrapFoldingListener {
-
- /**
- * Informs that <code>'collapsed'</code> state of fold region that is/was located at the target range is just changed.
- * <p/>
- * <b>Note:</b> listener should delay fold region state processing until {@link #onFoldProcessingEnd()} is called.
- * I.e. folding model may return inconsistent data between current moment and {@link #onFoldProcessingEnd()}.
- *
- * @param startOffset start offset of the target fold region (inclusive)
- * @param endOffset end offset of the target fold region (exclusive)
- */
- void onFoldRegionStateChange(int startOffset, int endOffset);
-
- /**
- * Informs that fold processing is done.
- */
- void onFoldProcessingEnd();
-}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
index ddcfa87..3b596c6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceManager.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.
@@ -56,7 +56,7 @@
* @author Denis Zhdanov
* @since Jul 5, 2010 10:01:27 AM
*/
-public class SoftWrapApplianceManager implements SoftWrapFoldingListener, DocumentListener, Dumpable {
+public class SoftWrapApplianceManager implements DocumentListener, Dumpable {
private static final Logger LOG = Logger.getInstance("#" + SoftWrapApplianceManager.class.getName());
@@ -986,7 +986,6 @@
}
}
- @Override
public void onFoldRegionStateChange(int startOffset, int endOffset) {
assert ApplicationManagerEx.getApplicationEx().isDispatchThread();
@@ -1002,7 +1001,6 @@
myEventsStorage.add(document, new IncrementalCacheUpdateEvent(document, recalculationStartOffset, recalculationEndOffset));
}
- @Override
public void onFoldProcessingEnd() {
//CachingSoftWrapDataMapper.log("xxxxxxxxxxx On fold region processing end");
recalculateSoftWraps();
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java
new file mode 100644
index 0000000..5541e61
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentCaret.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.textarea;
+
+import com.intellij.openapi.editor.*;
+import com.intellij.openapi.util.UserDataHolderBase;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class TextComponentCaret extends UserDataHolderBase implements Caret {
+ private final Editor myEditor;
+
+ public TextComponentCaret(Editor editor) {
+ myEditor = editor;
+ }
+
+ @NotNull
+ @Override
+ public CaretModel getCaretModel() {
+ return myEditor.getCaretModel();
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public void moveCaretRelatively(int columnShift, int lineShift, boolean withSelection, boolean scrollToCaret) {
+ getCaretModel().moveCaretRelatively(columnShift, lineShift, withSelection, false, scrollToCaret);
+ }
+
+ @Override
+ public void moveToLogicalPosition(@NotNull LogicalPosition pos) {
+ getCaretModel().moveToLogicalPosition(pos);
+ }
+
+ @Override
+ public void moveToVisualPosition(@NotNull VisualPosition pos) {
+ getCaretModel().moveToVisualPosition(pos);
+ }
+
+ @Override
+ public void moveToOffset(int offset) {
+ getCaretModel().moveToOffset(offset);
+ }
+
+ @Override
+ public void moveToOffset(int offset, boolean locateBeforeSoftWrap) {
+ getCaretModel().moveToOffset(offset, locateBeforeSoftWrap);
+ }
+
+ @Override
+ public boolean isUpToDate() {
+ return getCaretModel().isUpToDate();
+ }
+
+ @NotNull
+ @Override
+ public LogicalPosition getLogicalPosition() {
+ return getCaretModel().getLogicalPosition();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getVisualPosition() {
+ return getCaretModel().getVisualPosition();
+ }
+
+ @Override
+ public int getOffset() {
+ return getCaretModel().getOffset();
+ }
+
+ @Override
+ public int getVisualLineStart() {
+ return getCaretModel().getVisualLineStart();
+ }
+
+ @Override
+ public int getVisualLineEnd() {
+ return getCaretModel().getVisualLineEnd();
+ }
+
+ @Override
+ public int getSelectionStart() {
+ return getSelectionModel().getSelectionStart();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getSelectionStartPosition() {
+ return myEditor.offsetToVisualPosition(getSelectionModel().getSelectionStart());
+ }
+
+ @Override
+ public int getSelectionEnd() {
+ return getSelectionModel().getSelectionEnd();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getSelectionEndPosition() {
+ return myEditor.offsetToVisualPosition(getSelectionModel().getSelectionEnd());
+ }
+
+ @Nullable
+ @Override
+ public String getSelectedText() {
+ return getSelectionModel().getSelectedText();
+ }
+
+ @Override
+ public int getLeadSelectionOffset() {
+ return getSelectionModel().getLeadSelectionOffset();
+ }
+
+ @NotNull
+ @Override
+ public VisualPosition getLeadSelectionPosition() {
+ return myEditor.offsetToVisualPosition(getSelectionModel().getLeadSelectionOffset());
+ }
+
+ @Override
+ public boolean hasSelection() {
+ return getSelectionModel().hasSelection();
+ }
+
+ @Override
+ public void setSelection(int startOffset, int endOffset) {
+ getSelectionModel().setSelection(startOffset, endOffset);
+ }
+
+ @Override
+ public void setSelection(int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ getSelectionModel().setSelection(startOffset, endPosition, endOffset);
+ }
+
+ @Override
+ public void setSelection(@Nullable VisualPosition startPosition, int startOffset, @Nullable VisualPosition endPosition, int endOffset) {
+ getSelectionModel().setSelection(startPosition, startOffset, endPosition, endOffset);
+ }
+
+ @Override
+ public void removeSelection() {
+ getSelectionModel().removeSelection();
+ }
+
+ @Override
+ public void selectLineAtCaret() {
+ getSelectionModel().selectLineAtCaret();
+ }
+
+ @Override
+ public void selectWordAtCaret(boolean honorCamelWordsSettings) {
+ getSelectionModel().selectWordAtCaret(honorCamelWordsSettings);
+ }
+
+ @Nullable
+ @Override
+ public Caret clone(boolean above) {
+ return null;
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ private SelectionModel getSelectionModel() {
+ return myEditor.getSelectionModel();
+ }
+}
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 9319b3c..32e8f3b 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
@@ -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,16 +15,19 @@
*/
package com.intellij.openapi.editor.textarea;
-import com.intellij.openapi.editor.CaretModel;
-import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.VisualPosition;
+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;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.JTextComponent;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
/**
* @author yole
@@ -32,10 +35,12 @@
public class TextComponentCaretModel implements CaretModel {
private final JTextComponent myTextComponent;
private final TextComponentEditor myEditor;
+ private final Caret myCaret;
- public TextComponentCaretModel(final JTextComponent textComponent, TextComponentEditor editor) {
+ public TextComponentCaretModel(@NotNull JTextComponent textComponent, @NotNull TextComponentEditor editor) {
myTextComponent = textComponent;
myEditor = editor;
+ myCaret = new TextComponentCaret(editor);
}
@Override
@@ -129,4 +134,63 @@
public TextAttributes getTextAttributes() {
return null;
}
+
+ @Override
+ public boolean supportsMultipleCarets() {
+ return false;
+ }
+
+ @NotNull
+ @Override
+ public Caret getCurrentCaret() {
+ return myCaret;
+ }
+
+ @NotNull
+ @Override
+ public Caret getPrimaryCaret() {
+ return myCaret;
+ }
+
+ @NotNull
+ @Override
+ public Collection<Caret> getAllCarets() {
+ return Collections.singleton(myCaret);
+ }
+
+ @Nullable
+ @Override
+ public Caret getCaretAt(@NotNull VisualPosition pos) {
+ return myCaret.getVisualPosition().equals(pos) ? myCaret : null;
+ }
+
+ @Nullable
+ @Override
+ public Caret addCaret(@NotNull VisualPosition pos) {
+ return null;
+ }
+
+ @Override
+ public boolean removeCaret(@NotNull Caret caret) {
+ return false;
+ }
+
+ @Override
+ public void removeSecondaryCarets() {
+ }
+
+ @Override
+ public void setCarets(@NotNull List<LogicalPosition> caretPositions, @NotNull List<? extends Segment> selections) {
+ throw new UnsupportedOperationException("Multiple carets are not supported");
+ }
+
+ @Override
+ public void runForEachCaret(@NotNull CaretAction action) {
+ action.perform(myCaret);
+ }
+
+ @Override
+ public void runBatchCaretOperation(@NotNull Runnable runnable) {
+ runnable.run();
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentDocument.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentDocument.java
index 1bfab20..6fcbc2b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentDocument.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentDocument.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,6 +38,7 @@
myTextComponent = textComponent;
}
+ @NotNull
@Override
public String getText() {
try {
@@ -67,6 +68,12 @@
return getText();
}
+ @NotNull
+ @Override
+ public CharSequence getImmutableCharSequence() {
+ return getText();
+ }
+
@Override
@NotNull
public char[] getChars() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java
index 16ed917..80e0cbb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentEditor.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.
@@ -48,7 +48,7 @@
private final TextComponentFoldingModel myFoldingModel;
private EditorSettings mySettings;
- public TextComponentEditor(final Project project, final JTextComponent textComponent) {
+ public TextComponentEditor(final Project project, @NotNull JTextComponent textComponent) {
myProject = project;
myTextComponent = textComponent;
if (textComponent instanceof JTextArea) {
@@ -98,7 +98,7 @@
@Override
@NotNull
- public SelectionModel getSelectionModel() {
+ public TextComponentSelectionModel getSelectionModel() {
return mySelectionModel;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentScrollingModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentScrollingModel.java
index 348a18d..e68f4d8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentScrollingModel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentScrollingModel.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.
@@ -31,7 +31,7 @@
public class TextComponentScrollingModel implements ScrollingModel {
private final JTextComponent myTextComponent;
- public TextComponentScrollingModel(final JTextComponent textComponent) {
+ public TextComponentScrollingModel(@NotNull JTextComponent textComponent) {
myTextComponent = textComponent;
}
@@ -41,13 +41,14 @@
throw new UnsupportedOperationException("Not implemented");
}
+ @NotNull
@Override
public Rectangle getVisibleAreaOnScrollingFinished() {
throw new UnsupportedOperationException("Not implemented");
}
@Override
- public void scrollToCaret(final ScrollType scrollType) {
+ public void scrollToCaret(@NotNull final ScrollType scrollType) {
final int position = myTextComponent.getCaretPosition();
try {
final Rectangle rectangle = myTextComponent.modelToView(position);
@@ -59,12 +60,12 @@
}
@Override
- public void scrollTo(final LogicalPosition pos, final ScrollType scrollType) {
+ public void scrollTo(@NotNull final LogicalPosition pos, @NotNull final ScrollType scrollType) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
- public void runActionOnScrollingFinished(final Runnable action) {
+ public void runActionOnScrollingFinished(@NotNull final Runnable action) {
throw new UnsupportedOperationException("Not implemented");
}
@@ -97,12 +98,12 @@
}
@Override
- public void addVisibleAreaListener(final VisibleAreaListener listener) {
+ public void addVisibleAreaListener(@NotNull final VisibleAreaListener listener) {
throw new UnsupportedOperationException("Not implemented");
}
@Override
- public void removeVisibleAreaListener(final VisibleAreaListener listener) {
+ public void removeVisibleAreaListener(@NotNull final VisibleAreaListener listener) {
throw new UnsupportedOperationException("Not implemented");
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java
index a95a8d6..0b61205 100644
--- a/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/editor/textarea/TextComponentSelectionModel.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,7 @@
private final JTextComponent myTextComponent;
private final TextComponentEditor myEditor;
- public TextComponentSelectionModel(final JTextComponent textComponent, final TextComponentEditor textComponentEditor) {
+ public TextComponentSelectionModel(@NotNull JTextComponent textComponent, @NotNull TextComponentEditor textComponentEditor) {
myTextComponent = textComponent;
myEditor = textComponentEditor;
}
@@ -71,6 +71,12 @@
return myTextComponent.getSelectedText();
}
+ @Nullable
+ @Override
+ public String getSelectedText(boolean allCarets) {
+ return getSelectedText();
+ }
+
@Override
public int getLeadSelectionOffset() {
final int caretPosition = myTextComponent.getCaretPosition();
@@ -91,6 +97,11 @@
}
@Override
+ public boolean hasSelection(boolean anyCaret) {
+ return hasSelection();
+ }
+
+ @Override
public void setSelection(final int startOffset, final int endOffset) {
if (myTextComponent.getCaretPosition() == startOffset) { // avoid moving caret (required for correct Ctrl-W operation)
myTextComponent.setCaretPosition(endOffset);
@@ -119,6 +130,11 @@
}
@Override
+ public void removeSelection(boolean allCarets) {
+ removeSelection();
+ }
+
+ @Override
public void addSelectionListener(final SelectionListener listener) {
throw new UnsupportedOperationException("Not implemented");
}
@@ -148,7 +164,7 @@
}
@Override
- public void setBlockSelection(final LogicalPosition blockStart, final LogicalPosition blockEnd) {
+ public void setBlockSelection(@NotNull final LogicalPosition blockStart, @NotNull final LogicalPosition blockEnd) {
throw new UnsupportedOperationException("Not implemented");
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/VirtualFileDeleteProvider.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/VirtualFileDeleteProvider.java
index 3a23ba1..72e80de 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/VirtualFileDeleteProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/actions/VirtualFileDeleteProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -51,7 +51,7 @@
String message = createConfirmationMessage(files);
int returnValue = Messages.showOkCancelDialog(message, UIBundle.message("delete.dialog.title"), ApplicationBundle.message("button.delete"),
CommonBundle.getCancelButtonText(), Messages.getQuestionIcon());
- if (returnValue != 0) return;
+ if (returnValue != Messages.OK) return;
Arrays.sort(files, FileComparator.getInstance());
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
index b11c28b..b116547 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
@@ -196,7 +196,7 @@
label.setToolTipText("Recent files");
new ClickListener() {
@Override
- public boolean onClick(MouseEvent event, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent event, int clickCount) {
showRecentFilesPopup();
return true;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java
index 64552eb..8181136 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileSaverDialogImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -183,7 +183,7 @@
protected void doOKAction() {
final File file = getFile();
if (file != null && file.exists()) {
- if (OK_EXIT_CODE != Messages.showYesNoDialog(this.getRootPane(),
+ if (Messages.YES != Messages.showYesNoDialog(this.getRootPane(),
UIBundle.message("file.chooser.save.dialog.confirmation", file.getName()),
UIBundle.message("file.chooser.save.dialog.confirmation.title"),
Messages.getWarningIcon())) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorProviderManager.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorProviderManager.java
index 57301ae..a0671d5 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorProviderManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/ex/FileEditorProviderManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -39,7 +39,8 @@
* an empty array if there are no such providers. Please note that returned array
* is constructed with respect to editor policies.
*/
- public abstract @NotNull FileEditorProvider[] getProviders(@NotNull Project project, @NotNull VirtualFile file);
+ @NotNull
+ public abstract FileEditorProvider[] getProviders(@NotNull Project project, @NotNull VirtualFile file);
/**
* @return may be null
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
index a2f0f18..648cd2a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorComposite.java
@@ -298,6 +298,7 @@
* @return editors which are opened in the composite. <b>Do not modify
* this array</b>.
*/
+ @NotNull
public FileEditor[] getEditors() {
return myEditors;
}
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 a608003..978c260 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
@@ -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.
@@ -32,13 +32,16 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.util.ArrayUtilRt;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.LinkedHashSet;
import java.util.List;
public final class EditorHistoryManager extends AbstractProjectComponent implements JDOMExternalizable {
@@ -166,8 +169,7 @@
private void updateHistoryEntry(@Nullable final VirtualFile file,
@Nullable final FileEditor fallbackEditor,
@Nullable FileEditorProvider fallbackProvider,
- final boolean changeEntryOrderOnly)
- {
+ final boolean changeEntryOrderOnly) {
if (file == null) {
return;
}
@@ -239,7 +241,7 @@
}
/**
- * @return array of valid files that are in the history. The greater is index the more recent the file is.
+ * @return array of valid files that are in the history, oldest first. May contain duplicates.
*/
public VirtualFile[] getFiles(){
validateEntries();
@@ -250,6 +252,19 @@
return result;
}
+ /**
+ * @return a set of valid files that are in the history, oldest first.
+ */
+ public LinkedHashSet<VirtualFile> getFileSet() {
+ LinkedHashSet<VirtualFile> result = ContainerUtil.newLinkedHashSet();
+ for (VirtualFile file : getFiles()) {
+ // if the file occurs several times in the history, only its last occurrence counts
+ result.remove(file);
+ result.add(file);
+ }
+ return result;
+ }
+
public boolean hasBeenOpen(@NotNull VirtualFile f) {
for (HistoryEntry each : myEntriesList) {
if (Comparing.equal(each.myFile, f)) return true;
@@ -343,8 +358,15 @@
@Override
public void selectionChanged(@NotNull final FileEditorManagerEvent event){
- updateHistoryEntry(event.getOldFile(), event.getOldEditor(), event.getOldProvider(), false);
- updateHistoryEntry(event.getNewFile(), true);
+ // updateHistoryEntry does commitDocument which is 1) very expensive and 2) cannot be performed from within PSI change listener
+ // so defer updating history entry until documents committed to improve responsiveness
+ PsiDocumentManager.getInstance(myProject).performWhenAllCommitted(new Runnable() {
+ @Override
+ public void run() {
+ updateHistoryEntry(event.getOldFile(), event.getOldEditor(), event.getOldProvider(), false);
+ updateHistoryEntry(event.getNewFile(), true);
+ }
+ });
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
index 9ddd1a3..7819584 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWindow.java
@@ -41,6 +41,7 @@
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.IconUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import com.intellij.util.ui.EmptyIcon;
import com.intellij.util.ui.UIUtil;
@@ -52,10 +53,8 @@
import java.awt.*;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
-import java.util.ArrayList;
-import java.util.Arrays;
+import java.util.*;
import java.util.List;
-import java.util.Set;
/**
* Author: msk
@@ -1077,130 +1076,77 @@
}
private void doTrimSize(int limit, @Nullable VirtualFile fileToIgnore, boolean closeNonModifiedFilesFirst, boolean transferFocus) {
- while_label:
- while (myTabbedPane.getTabCount() > limit && myTabbedPane.getTabCount() > 0) {
- // If all tabs are pinned then do nothings. Othrwise we will get infinitive loop
- boolean allTabsArePinned = true;
- for (int i = myTabbedPane.getTabCount() - 1; i >= 0; i--) {
- final VirtualFile file = getFileAt(i);
- if (fileCanBeClosed(file, fileToIgnore)) {
- allTabsArePinned = false;
- break;
- }
- }
- if (allTabsArePinned) {
+ LinkedHashSet<VirtualFile> closingOrder = getTabClosingOrder(closeNonModifiedFilesFirst);
+
+ for (VirtualFile file : closingOrder) {
+ if (myTabbedPane.getTabCount() <= limit || myTabbedPane.getTabCount() == 0 || areAllTabsPinned(fileToIgnore)) {
return;
}
+ if (fileCanBeClosed(file, fileToIgnore)) {
+ defaultCloseFile(file, transferFocus);
+ }
+ }
- // Try to close non-modified files first (is specified in option)
- if (closeNonModifiedFilesFirst) {
- // Search in history
- final VirtualFile[] allFiles = getFiles();
- final VirtualFile[] histFiles = EditorHistoryManager.getInstance(getManager ().getProject()).getFiles();
+ }
- // first, we search for files not in history
- for (int i = 0; i != allFiles.length; ++ i) {
- final VirtualFile file = allFiles[i];
- if (fileCanBeClosed(file, fileToIgnore)) {
- boolean found = false;
- for (int j = 0; j != histFiles.length; j++) {
- if (Comparing.equal(histFiles[j], file)) {
- found = true;
- break;
- }
- }
- if (!found) {
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
- }
- }
+ private LinkedHashSet<VirtualFile> getTabClosingOrder(boolean closeNonModifiedFilesFirst) {
+ final VirtualFile[] allFiles = getFiles();
+ final Set<VirtualFile> histFiles = EditorHistoryManager.getInstance(getManager().getProject()).getFileSet();
- for (final VirtualFile file : histFiles) {
- if (!fileCanBeClosed(file, fileToIgnore)) {
- continue;
- }
+ LinkedHashSet<VirtualFile> closingOrder = ContainerUtil.newLinkedHashSet();
- final EditorComposite composite = findFileComposite(file);
- //LOG.assertTrue(composite != null);
- if (composite != null && composite.getInitialFileTimeStamp() == file.getTimeStamp()) {
- // we found non modified file
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
- }
+ // first, we search for files not in history
+ for (final VirtualFile file : allFiles) {
+ if (!histFiles.contains(file)) {
+ closingOrder.add(file);
+ }
+ }
- // Search in tabbed pane
- final VirtualFile selectedFile = getSelectedFile();
- for (int i = 0; i < myTabbedPane.getTabCount(); i++) {
- final VirtualFile file = getFileAt(i);
- final EditorComposite composite = getEditorAt(i);
- if (!fileCanBeClosed(file, fileToIgnore)) {
- continue;
- }
- if (!selectedFile.equals(file)) {
- if (composite.getInitialFileTimeStamp() == file.getTimeStamp()) {
- // we found non modified file
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
- }
+ if (closeNonModifiedFilesFirst) {
+ // Search in history
+ for (final VirtualFile file : histFiles) {
+ if (isFileModified(findFileComposite(file), file)) {
+ // we found non modified file
+ closingOrder.add(file);
}
}
- // It's non enough to close non-modified files only. Try all other files.
- // Search in history from less frequently used.
- {
- final VirtualFile[] allFiles = getFiles();
- final VirtualFile[] histFiles = EditorHistoryManager.getInstance(getManager ().getProject()).getFiles();
-
- // first, we search for files not in history
- for (int i = 0; i != allFiles.length; ++ i) {
- final VirtualFile file = allFiles[i];
- if (fileCanBeClosed(file, fileToIgnore)) {
- boolean found = false;
- for (int j = 0; j != histFiles.length; j++) {
- if (Comparing.equal(histFiles[j], file)) {
- found = true;
- break;
- }
- }
- if (!found) {
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
- }
- }
-
-
- for (final VirtualFile file : histFiles) {
- if (fileCanBeClosed(file, fileToIgnore)) {
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
- }
- }
-
- // Close first opened file in tabbed pane that isn't a selected one
- {
- final VirtualFile selectedFile = getSelectedFile();
- for (int i = 0; i < myTabbedPane.getTabCount(); i++) {
- final VirtualFile file = getFileAt(i);
- if (!fileCanBeClosed(file, fileToIgnore)) {
- continue;
- }
- if (!selectedFile.equals(file)) {
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
- else if (i == myTabbedPane.getTabCount() - 1) {
- // if file is selected one and it's last file that we have no choice as close it
- defaultCloseFile(file, transferFocus);
- continue while_label;
- }
+ // Search in tabbed pane
+ for (int i = 0; i < myTabbedPane.getTabCount(); i++) {
+ final VirtualFile file = getFileAt(i);
+ if (isFileModified(getEditorAt(i), file)) {
+ // we found non modified file
+ closingOrder.add(file);
}
}
}
+
+ // If it's not enough to close non-modified files only, try all other files.
+ // Search in history from less frequently used.
+ closingOrder.addAll(histFiles);
+
+ // finally, close tabs by their order
+ for (int i = 0; i < myTabbedPane.getTabCount(); i++) {
+ closingOrder.add(getFileAt(i));
+ }
+
+ final VirtualFile selectedFile = getSelectedFile();
+ closingOrder.remove(selectedFile);
+ closingOrder.add(selectedFile); // selected should be closed last
+ return closingOrder;
+ }
+
+ private static boolean isFileModified(EditorComposite composite, VirtualFile file) {
+ return composite != null && (composite.getInitialFileTimeStamp() == file.getTimeStamp() || composite.isModified());
+ }
+
+ private boolean areAllTabsPinned(VirtualFile fileToIgnore) {
+ for (int i = myTabbedPane.getTabCount() - 1; i >= 0; i--) {
+ if (fileCanBeClosed(getFileAt(i), fileToIgnore)) {
+ return false;
+ }
+ }
+ return true;
}
private void defaultCloseFile(VirtualFile file, boolean transferFocus) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java
index f3ccbef..aef6dc7 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorWithProviderComposite.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -33,23 +33,22 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.fileEditor.impl.EditorWithProviderComposite");
private final FileEditorProvider[] myProviders;
- EditorWithProviderComposite (
- final VirtualFile file,
- final FileEditor[] editors,
- final FileEditorProvider[] providers,
- final FileEditorManagerEx fileEditorManager
- ) {
+ EditorWithProviderComposite(@NotNull VirtualFile file,
+ @NotNull FileEditor[] editors,
+ @NotNull FileEditorProvider[] providers,
+ @NotNull FileEditorManagerEx fileEditorManager) {
super(file, editors, fileEditorManager);
myProviders = providers;
}
+ @NotNull
public FileEditorProvider[] getProviders() {
return myProviders;
}
@Override
public boolean isModified() {
- final FileEditor [] editors = getEditors ();
+ final FileEditor[] editors = getEditors();
for (FileEditor editor : editors) {
if (editor.isModified()) {
return true;
@@ -62,22 +61,23 @@
@NotNull
public Pair<FileEditor, FileEditorProvider> getSelectedEditorWithProvider() {
LOG.assertTrue(myEditors.length > 0, myEditors.length);
- if(myEditors.length==1){
- LOG.assertTrue(myTabbedPaneWrapper==null);
- return Pair.create (myEditors[0], myProviders [0]);
+ if (myEditors.length == 1) {
+ LOG.assertTrue(myTabbedPaneWrapper == null);
+ return Pair.create(myEditors[0], myProviders[0]);
}
- else{ // we have to get myEditor from tabbed pane
- LOG.assertTrue(myTabbedPaneWrapper!=null);
+ else { // we have to get myEditor from tabbed pane
+ LOG.assertTrue(myTabbedPaneWrapper != null);
int index = myTabbedPaneWrapper.getSelectedIndex();
if (index == -1) {
index = 0;
}
- LOG.assertTrue(index>=0, index);
- LOG.assertTrue(index<myEditors.length, index);
- return Pair.create (myEditors[index], myProviders [index]);
+ LOG.assertTrue(index >= 0, index);
+ LOG.assertTrue(index < myEditors.length, index);
+ return Pair.create(myEditors[index], myProviders[index]);
}
}
+ @NotNull
public HistoryEntry currentStateAsHistoryEntry() {
final FileEditor[] editors = getEditors();
final FileEditorState[] states = new FileEditorState[editors.length];
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
index a4c3fea..7b095fa 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/EditorsSplitters.java
@@ -192,7 +192,7 @@
}
painter.appendLine("Open a file by name with " + getActionShortcutText("GotoFile")).smaller().withBullet()
- .appendLine("Open Recent files with " + getActionShortcutText(IdeActions.ACTION_RECENT_FILES)).smaller().withBullet()
+ .appendLine("Open Recent Files with " + getActionShortcutText(IdeActions.ACTION_RECENT_FILES)).smaller().withBullet()
.appendLine("Open Navigation Bar with " + getActionShortcutText("ShowNavBar")).smaller().withBullet()
.appendLine("Drag and Drop file(s) here from " + ShowFilePathAction.getFileManagerName()).smaller().withBullet()
.draw(g, new PairFunction<Integer, Integer, Pair<Integer, Integer>>() {
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 cd979c4..5c26205 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
@@ -18,6 +18,7 @@
import com.intellij.AppTopics;
import com.intellij.CommonBundle;
import com.intellij.codeStyle.CodeStyleFacade;
+import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
@@ -49,12 +50,14 @@
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.ex.dummy.DummyFileSystem;
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
+import com.intellij.pom.core.impl.PomModelImpl;
import com.intellij.psi.ExternalChangeAction;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.SingleRootFileViewProvider;
@@ -62,6 +65,8 @@
import com.intellij.ui.UIBundle;
import com.intellij.ui.components.JBScrollPane;
import com.intellij.util.Function;
+import com.intellij.util.PairProcessor;
+import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ConcurrentHashSet;
import com.intellij.util.messages.MessageBus;
import org.jetbrains.annotations.NotNull;
@@ -397,7 +402,7 @@
}
}
- private void doSaveDocumentInWriteAction(@NotNull Document document, @NotNull VirtualFile file) throws IOException {
+ private void doSaveDocumentInWriteAction(@NotNull final Document document, @NotNull final VirtualFile file) throws IOException {
if (!file.isValid()) {
removeFromUnsaved(document);
return;
@@ -416,22 +421,26 @@
return;
}
- myMultiCaster.beforeDocumentSaving(document);
+ PomModelImpl.guardPsiModificationsIn(new ThrowableRunnable<IOException>() {
+ @Override
+ public void run() throws IOException {
+ myMultiCaster.beforeDocumentSaving(document);
+ LOG.assertTrue(file.isValid());
- LOG.assertTrue(file.isValid());
+ String text = document.getText();
+ String lineSeparator = getLineSeparator(document, file);
+ if (!lineSeparator.equals("\n")) {
+ text = StringUtil.convertLineSeparators(text, lineSeparator);
+ }
- String text = document.getText();
- String lineSeparator = getLineSeparator(document, file);
- if (!lineSeparator.equals("\n")) {
- text = StringUtil.convertLineSeparators(text, lineSeparator);
- }
+ Project project = ProjectLocator.getInstance().guessProjectForFile(file);
+ LoadTextUtil.write(project, file, FileDocumentManagerImpl.this, text, document.getModificationStamp());
- Project project = ProjectLocator.getInstance().guessProjectForFile(file);
- LoadTextUtil.write(project, file, this, text, document.getModificationStamp());
-
- myUnsavedDocuments.remove(document);
- LOG.assertTrue(!myUnsavedDocuments.contains(document));
- myTrailingSpacesStripper.clearLineModificationFlags(document);
+ myUnsavedDocuments.remove(document);
+ LOG.assertTrue(!myUnsavedDocuments.contains(document));
+ myTrailingSpacesStripper.clearLineModificationFlags(document);
+ }
+ });
}
private static void updateModifiedProperty(@NotNull VirtualFile file) {
@@ -643,47 +652,67 @@
myMultiCaster.fileContentReloaded(file, document);
}
- protected boolean askReloadFromDisk(final VirtualFile file, final Document document) {
+ private PairProcessor<VirtualFile, Document> askReloadFromDisk = new PairProcessor<VirtualFile, Document>() {
+ @Override
+ public boolean process(final VirtualFile file, final Document document) {
+ String message = UIBundle.message("file.cache.conflict.message.text", file.getPresentableUrl());
+
+ final DialogBuilder builder = new DialogBuilder((Project)null);
+ builder.setCenterPanel(new JLabel(message, Messages.getQuestionIcon(), SwingConstants.CENTER));
+ builder.addOkAction().setText(UIBundle.message("file.cache.conflict.load.fs.changes.button"));
+ builder.addCancelAction().setText(UIBundle.message("file.cache.conflict.keep.memory.changes.button"));
+ builder.addAction(new AbstractAction(UIBundle.message("file.cache.conflict.show.difference.button")) {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String title = UIBundle.message("file.cache.conflict.for.file.dialog.title", file.getPresentableUrl());
+ final ProjectEx project = (ProjectEx)ProjectLocator.getInstance().guessProjectForFile(file);
+
+ SimpleDiffRequest request = new SimpleDiffRequest(project, title);
+ FileType fileType = file.getFileType();
+ String fsContent = LoadTextUtil.loadText(file).toString();
+ request.setContents(new SimpleContent(fsContent, fileType),
+ new DocumentContent(project, document, fileType));
+ request.setContentTitles(UIBundle.message("file.cache.conflict.diff.content.file.system.content"),
+ UIBundle.message("file.cache.conflict.diff.content.memory.content"));
+ DialogBuilder diffBuilder = new DialogBuilder(project);
+ DiffPanelImpl diffPanel = (DiffPanelImpl)DiffManager.getInstance().createDiffPanel(diffBuilder.getWindow(), project, diffBuilder, null);
+ diffPanel.getOptions().setShowSourcePolicy(DiffPanelOptions.ShowSourcePolicy.DONT_SHOW);
+ diffBuilder.setCenterPanel(diffPanel.getComponent());
+ diffBuilder.setDimensionServiceKey("FileDocumentManager.FileCacheConflict");
+ diffPanel.setDiffRequest(request);
+ diffBuilder.addOkAction().setText(UIBundle.message("file.cache.conflict.save.changes.button"));
+ diffBuilder.addCancelAction();
+ diffBuilder.setTitle(title);
+ if (diffBuilder.show() == DialogWrapper.OK_EXIT_CODE) {
+ builder.getDialogWrapper().close(DialogWrapper.CANCEL_EXIT_CODE);
+ }
+ }
+ });
+ builder.setTitle(UIBundle.message("file.cache.conflict.dialog.title"));
+ builder.setButtonsAlignment(SwingConstants.CENTER);
+ builder.setHelpId("reference.dialogs.fileCacheConflict");
+ return builder.show() == 0;
+ }
+ };
+
+ @TestOnly
+ public void setAskReloadFromDisk(@NotNull Disposable disposable,
+ @NotNull PairProcessor<VirtualFile, Document> newProcessor) {
+ final PairProcessor<VirtualFile, Document> old = askReloadFromDisk;
+ askReloadFromDisk = newProcessor;
+ Disposer.register(disposable, new Disposable() {
+ @Override
+ public void dispose() {
+ askReloadFromDisk = old;
+ }
+ });
+ }
+
+ private boolean askReloadFromDisk(final VirtualFile file, final Document document) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (!isDocumentUnsaved(document)) return true;
- String message = UIBundle.message("file.cache.conflict.message.text", file.getPresentableUrl());
- if (ApplicationManager.getApplication().isUnitTestMode()) throw new RuntimeException(message);
- final DialogBuilder builder = new DialogBuilder((Project)null);
- builder.setCenterPanel(new JLabel(message, Messages.getQuestionIcon(), SwingConstants.CENTER));
- builder.addOkAction().setText(UIBundle.message("file.cache.conflict.load.fs.changes.button"));
- builder.addCancelAction().setText(UIBundle.message("file.cache.conflict.keep.memory.changes.button"));
- builder.addAction(new AbstractAction(UIBundle.message("file.cache.conflict.show.difference.button")) {
- @Override
- public void actionPerformed(ActionEvent e) {
- String title = UIBundle.message("file.cache.conflict.for.file.dialog.title", file.getPresentableUrl());
- final ProjectEx project = (ProjectEx)ProjectLocator.getInstance().guessProjectForFile(file);
-
- SimpleDiffRequest request = new SimpleDiffRequest(project, title);
- FileType fileType = file.getFileType();
- String fsContent = LoadTextUtil.loadText(file).toString();
- request.setContents(new SimpleContent(fsContent, fileType),
- new DocumentContent(project, document, fileType));
- request.setContentTitles(UIBundle.message("file.cache.conflict.diff.content.file.system.content"),
- UIBundle.message("file.cache.conflict.diff.content.memory.content"));
- DialogBuilder diffBuilder = new DialogBuilder(project);
- DiffPanelImpl diffPanel = (DiffPanelImpl)DiffManager.getInstance().createDiffPanel(diffBuilder.getWindow(), project, diffBuilder, null);
- diffPanel.getOptions().setShowSourcePolicy(DiffPanelOptions.ShowSourcePolicy.DONT_SHOW);
- diffBuilder.setCenterPanel(diffPanel.getComponent());
- diffBuilder.setDimensionServiceKey("FileDocumentManager.FileCacheConflict");
- diffPanel.setDiffRequest(request);
- diffBuilder.addOkAction().setText(UIBundle.message("file.cache.conflict.save.changes.button"));
- diffBuilder.addCancelAction();
- diffBuilder.setTitle(title);
- if (diffBuilder.show() == DialogWrapper.OK_EXIT_CODE) {
- builder.getDialogWrapper().close(DialogWrapper.CANCEL_EXIT_CODE);
- }
- }
- });
- builder.setTitle(UIBundle.message("file.cache.conflict.dialog.title"));
- builder.setButtonsAlignment(SwingConstants.CENTER);
- builder.setHelpId("reference.dialogs.fileCacheConflict");
- return builder.show() == 0;
+ return askReloadFromDisk.process(file, document);
}
@Override
@@ -793,7 +822,13 @@
return FileDocumentManagerListener.EP_NAME.getExtensions();
}
- protected void handleErrorsOnSave(@NotNull Map<Document, IOException> failures) {
+ private void handleErrorsOnSave(@NotNull Map<Document, IOException> failures) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ for (IOException exception : failures.values()) {
+ throw new RuntimeException(exception);
+ }
+ return;
+ }
for (IOException exception : failures.values()) {
LOG.warn(exception);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
index 90437f8..455e57d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorManagerImpl.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,7 +17,7 @@
import com.intellij.ProjectTopics;
import com.intellij.ide.IdeBundle;
-import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.injected.editor.VirtualFileWindow;
@@ -68,7 +68,8 @@
import com.intellij.ui.docking.DockManager;
import com.intellij.ui.docking.impl.DockManagerImpl;
import com.intellij.ui.tabs.impl.JBTabsImpl;
-import com.intellij.util.Consumer;
+import com.intellij.util.Function;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.messages.impl.MessageListenerList;
@@ -523,15 +524,12 @@
@NotNull
private AsyncResult<EditorWindow> _getActiveWindow(boolean now) {
- final AsyncResult<EditorWindow> result = new AsyncResult<EditorWindow>();
- getActiveSplitters(now).doWhenDone(new Consumer<EditorsSplitters>() {
+ return getActiveSplitters(now).subResult(new Function<EditorsSplitters, EditorWindow>() {
@Override
- public void consume(EditorsSplitters editorsSplitters) {
- result.setDone(editorsSplitters.getCurrentWindow());
+ public EditorWindow fun(EditorsSplitters splitters) {
+ return splitters.getCurrentWindow();
}
});
-
- return result;
}
@Override
@@ -794,7 +792,7 @@
for (int i = 0; i < providers.length; i++) {
try {
final FileEditorProvider provider = providers[i];
- LOG.assertTrue(provider != null);
+ LOG.assertTrue(provider != null, "Provider for file "+file+" is null. All providers: "+Arrays.asList(providers));
LOG.assertTrue(provider.accept(myProject, file), "Provider " + provider + " doesn't accept file " + file);
final FileEditor editor = provider.createEditor(myProject, file);
LOG.assertTrue(editor != null);
@@ -1040,7 +1038,7 @@
return openEditor(realDescriptor, focusEditor);
}
- final List<FileEditor> result = new ArrayList<FileEditor>();
+ final List<FileEditor> result = new SmartList<FileEditor>();
CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
@Override
public void run() {
@@ -1383,7 +1381,7 @@
StartupManager.getInstance(myProject).registerPostStartupActivity(new DumbAwareRunnable() {
@Override
public void run() {
-
+ if (myProject.isDisposed()) return;
setTabsMode(UISettings.getInstance().EDITOR_TAB_PLACEMENT != UISettings.TABS_NONE);
ToolWindowManager.getInstance(myProject).invokeLater(new Runnable() {
@@ -1400,10 +1398,10 @@
Long startTime = myProject.getUserData(ProjectImpl.CREATION_TIME);
if (startTime != null) {
LOG.info("Project opening took " + (currentTime - startTime.longValue()) / 1000000 + " ms");
- PluginManager.dumpPluginClassStatistics();
+ PluginManagerCore.dumpPluginClassStatistics();
}
}
- });
+ }, myProject.getDisposed());
// group 1
}
}, "", null);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java
index 9483073..81425e1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/FileEditorProviderManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -31,6 +31,7 @@
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
@@ -46,15 +47,15 @@
* @author Anton Katilin
* @author Vladimir Kondratyev
*/
-@State(name = "FileEditorProviderManager", storages = {@Storage( file = StoragePathMacros.APP_CONFIG + "/other.xml")})
-public final class FileEditorProviderManagerImpl extends FileEditorProviderManager implements PersistentStateComponent<FileEditorProviderManagerImpl> {
- private static final FileEditorProvider[] EMPTY_ARRAY=new FileEditorProvider[]{};
+@State(name = "FileEditorProviderManager", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/other.xml")})
+public final class FileEditorProviderManagerImpl extends FileEditorProviderManager
+ implements PersistentStateComponent<FileEditorProviderManagerImpl> {
+ private static final FileEditorProvider[] EMPTY_ARRAY = new FileEditorProvider[0];
private static final String SEPARATOR = ",";
- private final ArrayList<FileEditorProvider> myProviders = new ArrayList<FileEditorProvider>();
- private final ArrayList<FileEditorProvider> mySharedProviderList = new ArrayList<FileEditorProvider>();
+ private final List<FileEditorProvider> myProviders = new ArrayList<FileEditorProvider>();
- public FileEditorProviderManagerImpl(FileEditorProvider[] providers) {
+ public FileEditorProviderManagerImpl(@NotNull FileEditorProvider[] providers) {
Extensions.getRootArea().getExtensionPoint(FileEditorProvider.EP_FILE_EDITOR_PROVIDER).addExtensionPointListener(
new ExtensionPointListener<FileEditorProvider>() {
@Override
@@ -78,70 +79,63 @@
@Override
@NotNull
- public synchronized FileEditorProvider[] getProviders(@NotNull final Project project, @NotNull final VirtualFile file){
+ public synchronized FileEditorProvider[] getProviders(@NotNull final Project project, @NotNull final VirtualFile file) {
// Collect all possible editors
- mySharedProviderList.clear();
+ List<FileEditorProvider> mySharedProviderList = new ArrayList<FileEditorProvider>();
boolean doNotShowTextEditor = false;
final boolean dumb = DumbService.getInstance(project).isDumb();
- for(int i = myProviders.size() -1 ; i >= 0; i--){
- final FileEditorProvider provider=myProviders.get(i);
- if((!dumb || DumbService.isDumbAware(provider)) && ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
- @Override
- public Boolean compute() {
- return provider.accept(project, file);
- }
- })){
+ for (final FileEditorProvider provider : myProviders) {
+ boolean canUseProvider = !dumb || DumbService.isDumbAware(provider);
+ if (canUseProvider && ApplicationManager.getApplication().runReadAction(new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ return provider.accept(project, file);
+ }
+ })) {
mySharedProviderList.add(provider);
doNotShowTextEditor |= provider.getPolicy() == FileEditorPolicy.HIDE_DEFAULT_EDITOR;
}
}
// Throw out default editors provider if necessary
- if(doNotShowTextEditor){
- for(int i = mySharedProviderList.size() - 1; i >= 0; i--){
- if(mySharedProviderList.get(i) instanceof TextEditorProvider){
- mySharedProviderList.remove(i);
+ if (doNotShowTextEditor) {
+ ContainerUtil.retainAll(mySharedProviderList, new Condition<FileEditorProvider>() {
+ @Override
+ public boolean value(FileEditorProvider provider) {
+ return !(provider instanceof TextEditorProvider);
}
- }
+ });
}
// Sort editors according policies
Collections.sort(mySharedProviderList, MyComparator.ourInstance);
- if(!mySharedProviderList.isEmpty()){
- return mySharedProviderList.toArray(new FileEditorProvider[mySharedProviderList.size()]);
- }
- else{
+ if (mySharedProviderList.isEmpty()) {
return EMPTY_ARRAY;
}
+ return mySharedProviderList.toArray(new FileEditorProvider[mySharedProviderList.size()]);
}
@Override
@Nullable
- public synchronized FileEditorProvider getProvider(@NotNull String editorTypeId){
- for(int i=myProviders.size()-1;i>=0;i--){
- FileEditorProvider provider=myProviders.get(i);
- if(provider.getEditorTypeId().equals(editorTypeId)){
+ public synchronized FileEditorProvider getProvider(@NotNull String editorTypeId) {
+ for (FileEditorProvider provider : myProviders) {
+ if (provider.getEditorTypeId().equals(editorTypeId)) {
return provider;
}
}
return null;
}
- private void registerProvider(FileEditorProvider provider) {
+ private void registerProvider(@NotNull FileEditorProvider provider) {
String editorTypeId = provider.getEditorTypeId();
- for(int i=myProviders.size()-1;i>=0;i--){
- FileEditorProvider _provider=myProviders.get(i);
- if(editorTypeId.equals(_provider.getEditorTypeId())){
- throw new IllegalArgumentException(
- "attempt to register provider with non unique editorTypeId: "+_provider.getEditorTypeId()
- );
- }
+ if (getProvider(editorTypeId) != null) {
+ throw new IllegalArgumentException("attempt to register provider with non unique editorTypeId: " + editorTypeId);
}
myProviders.add(provider);
}
- private void unregisterProvider(FileEditorProvider provider) {
+ private void unregisterProvider(@NotNull FileEditorProvider provider) {
final boolean b = myProviders.remove(provider);
assert b;
}
@@ -158,7 +152,7 @@
mySelectedProviders.putAll(state.mySelectedProviders);
}
- private static final Function<FileEditorProvider,String> EDITOR_PROVIDER_STRING_FUNCTION = new Function<FileEditorProvider, String>() {
+ private static final Function<FileEditorProvider, String> EDITOR_PROVIDER_STRING_FUNCTION = new Function<FileEditorProvider, String>() {
@Override
public String fun(FileEditorProvider provider) {
return provider.getEditorTypeId();
@@ -206,12 +200,12 @@
mySelectedProviders.clear();
}
- private static final class MyComparator implements Comparator<FileEditorProvider>{
+ private static final class MyComparator implements Comparator<FileEditorProvider> {
public static final MyComparator ourInstance = new MyComparator();
private static double getWeight(FileEditorProvider provider) {
return provider instanceof WeighedFileEditorProvider
- ? ((WeighedFileEditorProvider) provider).getWeight()
+ ? ((WeighedFileEditorProvider)provider).getWeight()
: Double.MAX_VALUE;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
index f75449b..53b3e26 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/TrailingSpacesStripper.java
@@ -19,7 +19,6 @@
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
@@ -31,17 +30,23 @@
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileDocumentManagerAdapter;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.util.text.CharArrayUtil;
import gnu.trove.THashSet;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.util.Set;
public final class TrailingSpacesStripper extends FileDocumentManagerAdapter {
+
+ public static final Key<String> OVERRIDE_STRIP_TRAILING_SPACES_KEY = Key.create("OVERRIDE_TRIM_TRAILING_SPACES_KEY");
+ public static final Key<Boolean> OVERRIDE_ENSURE_NEWLINE_KEY = Key.create("OVERRIDE_ENSURE_NEWLINE_KEY");
+
private final Set<Document> myDocumentsToStripLater = new THashSet<Document>();
@Override
@@ -67,9 +72,11 @@
final EditorSettingsExternalizable settings = EditorSettingsExternalizable.getInstance();
if (settings == null) return;
- String stripTrailingSpaces = settings.getStripTrailingSpaces();
+ final String overrideStripTrailingSpacesData = file.getUserData(OVERRIDE_STRIP_TRAILING_SPACES_KEY);
+ final Boolean overrideEnsureNewlineData = file.getUserData(OVERRIDE_ENSURE_NEWLINE_KEY);
+ final String stripTrailingSpaces = overrideStripTrailingSpacesData != null ? overrideStripTrailingSpacesData : settings.getStripTrailingSpaces();
final boolean doStrip = !stripTrailingSpaces.equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE);
- final boolean ensureEOL = settings.isEnsureNewLineAtEOF();
+ final boolean ensureEOL = overrideEnsureNewlineData != null ? overrideEnsureNewlineData.booleanValue() : settings.isEnsureNewLineAtEOF();
if (doStrip) {
final boolean inChangedLinesOnly = !stripTrailingSpaces.equals(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java
index 972ac67..342cb09 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/FileDropHandler.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.
@@ -44,21 +44,18 @@
myEditor = editor;
}
-
@Override
public boolean canHandleDrop(final DataFlavor[] transferFlavors) {
- return transferFlavors != null && FileCopyPasteUtil.isFileListFlavorSupported(transferFlavors);
+ return transferFlavors != null && FileCopyPasteUtil.isFileListFlavorAvailable(transferFlavors);
}
@Override
public void handleDrop(@NotNull final Transferable t, @Nullable final Project project, EditorWindow editorWindow) {
- if (project == null || !FileCopyPasteUtil.isFileListFlavorSupported(t)) {
- return;
- }
-
- final List<File> fileList = FileCopyPasteUtil.getFileList(t);
- if (fileList != null) {
- openFiles(project, fileList, editorWindow);
+ if (project != null) {
+ final List<File> fileList = FileCopyPasteUtil.getFileList(t);
+ if (fileList != null) {
+ openFiles(project, fileList, editorWindow);
+ }
}
}
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 e756be0..46a55ea 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
@@ -41,6 +41,7 @@
import com.intellij.openapi.fileTypes.FileTypeListener;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileAdapter;
import com.intellij.openapi.vfs.VirtualFileEvent;
@@ -347,7 +348,9 @@
// File can be invalidated after file changes name (extension also
// can changes). The editor should be removed if it's invalid.
updateValidProperty();
- updateHighlighters();
+ if (Comparing.equal(e.getFile(), myFile) && !Comparing.equal(e.getOldValue(), e.getNewValue())) {
+ updateHighlighters();
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorImpl.java
index fac9ff6..b849424 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileEditor/impl/text/TextEditorImpl.java
@@ -163,8 +163,7 @@
@Override
public void navigateTo(@NotNull final Navigatable navigatable) {
- OpenFileDescriptor d = (OpenFileDescriptor)navigatable;
- d.navigateIn(getEditor());
+ ((OpenFileDescriptor)navigatable).navigateIn(getEditor());
}
@Override
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 3a6913c..e07a85c 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
@@ -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,10 +19,7 @@
import com.intellij.ide.structureView.StructureViewBuilder;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.ScrollType;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.ex.util.EditorUtil;
import com.intellij.openapi.fileEditor.*;
@@ -32,9 +29,7 @@
import com.intellij.openapi.project.DumbAware;
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.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
@@ -46,6 +41,9 @@
import javax.swing.*;
import java.beans.PropertyChangeListener;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
/**
* @author Anton Katilin
@@ -64,6 +62,7 @@
@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";
+ @NonNls private static final String CARET_ELEMENT = "caret";
public static TextEditorProvider getInstance() {
return ApplicationManager.getApplication().getComponent(TextEditorProvider.class);
@@ -100,11 +99,19 @@
TextEditorState state = new TextEditorState();
try {
- state.LINE = Integer.parseInt(element.getAttributeValue(LINE_ATTR));
- state.COLUMN = Integer.parseInt(element.getAttributeValue(COLUMN_ATTR));
- state.SELECTION_START = Integer.parseInt(element.getAttributeValue(SELECTION_START_ATTR));
- state.SELECTION_END = Integer.parseInt(element.getAttributeValue(SELECTION_END_ATTR));
- state.VERTICAL_SCROLL_PROPORTION = Float.parseFloat(element.getAttributeValue(VERTICAL_SCROLL_PROPORTION_ATTR));
+ List<Element> caretElements = element.getChildren(CARET_ELEMENT);
+ if (caretElements.isEmpty()) { // legacy format
+ state.CARETS = new TextEditorState.CaretState[] {readCaretInfo(element)};
+ }
+ else { // new format
+ state.CARETS = new TextEditorState.CaretState[caretElements.size()];
+ for (int i = 0; i < caretElements.size(); i++) {
+ state.CARETS[i] = readCaretInfo(caretElements.get(i));
+ }
+ }
+
+ String verticalScrollProportion = element.getAttributeValue(VERTICAL_SCROLL_PROPORTION_ATTR);
+ state.VERTICAL_SCROLL_PROPORTION = verticalScrollProportion == null ? 0 : Float.parseFloat(verticalScrollProportion);
String verticalOffset = element.getAttributeValue(VERTICAL_OFFSET_ATTR);
String maxVerticalOffset = element.getAttributeValue(MAX_VERTICAL_OFFSET_ATTR);
if (!StringUtil.isEmpty(verticalOffset) && !StringUtil.isEmpty(maxVerticalOffset)) {
@@ -118,17 +125,37 @@
return state;
}
+ private static TextEditorState.CaretState readCaretInfo(Element element) {
+ 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);
+ return caretState;
+ }
+
+ private static int parseWithDefault(Element element, String attributeName) {
+ String value = element.getAttributeValue(attributeName);
+ return value == null ? 0 : Integer.parseInt(value);
+ }
+
@Override
public void writeState(@NotNull FileEditorState _state, @NotNull Project project, @NotNull Element element) {
TextEditorState state = (TextEditorState)_state;
- element.setAttribute(LINE_ATTR, Integer.toString(state.LINE));
- element.setAttribute(COLUMN_ATTR, Integer.toString(state.COLUMN));
- element.setAttribute(SELECTION_START_ATTR, Integer.toString(state.SELECTION_START));
- element.setAttribute(SELECTION_END_ATTR, Integer.toString(state.SELECTION_END));
element.setAttribute(VERTICAL_SCROLL_PROPORTION_ATTR, Float.toString(state.VERTICAL_SCROLL_PROPORTION));
element.setAttribute(VERTICAL_OFFSET_ATTR, Integer.toString(state.VERTICAL_SCROLL_OFFSET));
element.setAttribute(MAX_VERTICAL_OFFSET_ATTR, Integer.toString(state.MAX_VERTICAL_SCROLL_OFFSET));
+ if (state.CARETS != null) {
+ for (TextEditorState.CaretState caretState : state.CARETS) {
+ 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));
+ element.addContent(e);
+ }
+ }
}
@Override
@@ -192,10 +219,17 @@
protected TextEditorState getStateImpl(final Project project, @NotNull Editor editor, @NotNull FileEditorStateLevel level){
TextEditorState state = new TextEditorState();
- state.LINE = editor.getCaretModel().getLogicalPosition().line;
- state.COLUMN = editor.getCaretModel().getLogicalPosition().column;
- state.SELECTION_START = editor.getSelectionModel().getSelectionStart();
- state.SELECTION_END = editor.getSelectionModel().getSelectionEnd();
+ CaretModel caretModel = editor.getCaretModel();
+ Collection<Caret> allCarets = caretModel.getAllCarets();
+ state.CARETS = new TextEditorState.CaretState[allCarets.size()];
+ int i = 0;
+ for (Caret caret : allCarets) {
+ 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();
+ }
// Saving scrolling proportion on UNDO may cause undesirable results of undo action fails to perform since
// scrolling proportion restored slightly differs from what have been saved.
@@ -210,9 +244,20 @@
}
protected void setStateImpl(final Project project, final Editor editor, final TextEditorState state){
- LogicalPosition pos = new LogicalPosition(state.LINE, state.COLUMN);
- editor.getCaretModel().moveToLogicalPosition(pos);
- editor.getSelectionModel().removeSelection();
+ if (editor.getCaretModel().supportsMultipleCarets()) {
+ CaretModel caretModel = editor.getCaretModel();
+ ArrayList<LogicalPosition> positions = new ArrayList<LogicalPosition>();
+ ArrayList<Segment> selections = new ArrayList<Segment>();
+ for (TextEditorState.CaretState caretState : state.CARETS) {
+ positions.add(new LogicalPosition(caretState.LINE, caretState.COLUMN));
+ selections.add(new TextRange(caretState.SELECTION_START, caretState.SELECTION_END));
+ }
+ caretModel.setCarets(positions, selections);
+ } else {
+ LogicalPosition pos = new LogicalPosition(state.CARETS[0].LINE, state.CARETS[0].COLUMN);
+ editor.getCaretModel().moveToLogicalPosition(pos);
+ editor.getSelectionModel().removeSelection();
+ }
EditorEx editorEx = editor instanceof EditorEx ? (EditorEx)editor : null;
boolean preciselyScrollVertically =
state.VERTICAL_SCROLL_OFFSET > 0
@@ -232,13 +277,15 @@
final Document document = editor.getDocument();
- if (state.SELECTION_START == state.SELECTION_END) {
- editor.getSelectionModel().removeSelection();
- }
- else {
- int startOffset = Math.min(state.SELECTION_START, document.getTextLength());
- int endOffset = Math.min(state.SELECTION_END, document.getTextLength());
- editor.getSelectionModel().setSelection(startOffset, endOffset);
+ if (!editor.getCaretModel().supportsMultipleCarets()) {
+ if (state.CARETS[0].SELECTION_START == state.CARETS[0].SELECTION_END) {
+ 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());
+ editor.getSelectionModel().setSelection(startOffset, endOffset);
+ }
}
if (editorEx != null && !preciselyScrollVertically) {
((EditorEx) editor).stopOptimizedScrolling();
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 c000e16..3319d51 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
@@ -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,16 +22,16 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
+
/**
* @author Vladimir Kondratyev
*/
public final class TextEditorState implements FileEditorState {
- public int LINE;
- public int COLUMN;
+ public CaretState[] CARETS;
+
public float VERTICAL_SCROLL_PROPORTION;
- public int SELECTION_START;
- public int SELECTION_END;
public int VERTICAL_SCROLL_OFFSET;
public int MAX_VERTICAL_SCROLL_OFFSET;
@@ -84,11 +84,8 @@
final TextEditorState textEditorState = (TextEditorState)o;
- if (COLUMN != textEditorState.COLUMN) return false;
- if (LINE != textEditorState.LINE) return false;
+ if (!Arrays.equals(CARETS, textEditorState.CARETS)) return false;
if (VERTICAL_SCROLL_PROPORTION != textEditorState.VERTICAL_SCROLL_PROPORTION) return false;
- if (SELECTION_START != textEditorState.SELECTION_START) return false;
- if (SELECTION_END != textEditorState.SELECTION_END) return false;
CodeFoldingState localFoldingState = getFoldingState();
CodeFoldingState theirFoldingState = textEditorState.getFoldingState();
if (localFoldingState == null ? theirFoldingState != null : !localFoldingState.equals(theirFoldingState)) return false;
@@ -97,17 +94,59 @@
}
public int hashCode() {
- return LINE + COLUMN;
+ int result = 0;
+ if (CARETS != null) {
+ for (CaretState caretState : CARETS) {
+ if (caretState != null) {
+ result += caretState.hashCode();
+ }
+ }
+ }
+ return result;
}
@Override
public boolean canBeMergedWith(FileEditorState otherState, FileEditorStateLevel level) {
if (!(otherState instanceof TextEditorState)) return false;
TextEditorState other = (TextEditorState)otherState;
- return level == FileEditorStateLevel.NAVIGATION && Math.abs(LINE - other.LINE) < MIN_CHANGE_DISTANCE;
+ return level == FileEditorStateLevel.NAVIGATION
+ && CARETS != null && CARETS.length == 1
+ && other.CARETS != null && other.CARETS.length == 1
+ && Math.abs(CARETS[0].LINE - other.CARETS[0].LINE) < MIN_CHANGE_DISTANCE;
}
public String toString() {
- return "[" + LINE + "," + COLUMN + "]";
+ return Arrays.toString(CARETS);
+ }
+
+ public static class CaretState {
+ public int LINE;
+ public int COLUMN;
+ public int SELECTION_START;
+ public int SELECTION_END;
+
+ public boolean equals(Object o) {
+ if (!(o instanceof CaretState)) {
+ return false;
+ }
+
+ final CaretState caretState = (CaretState)o;
+
+ 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;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return LINE + COLUMN;
+ }
+
+ public String toString() {
+ return "[" + LINE + "," + COLUMN + "]";
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java
index 9821e94..bd4db49 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/ex/FileTypeChooser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -30,7 +30,7 @@
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.DoubleClickListener;
import com.intellij.ui.ListScrollingUtil;
-import com.intellij.util.ArrayUtil;
+import com.intellij.util.FunctionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,8 +41,7 @@
import java.awt.event.MouseEvent;
import java.util.Arrays;
import java.util.Comparator;
-import java.util.Deque;
-import java.util.LinkedList;
+import java.util.List;
public class FileTypeChooser extends DialogWrapper {
private JList myList;
@@ -53,7 +52,7 @@
private JRadioButton myOpenAsNative;
private final String myFileName;
- private FileTypeChooser(@NotNull String[] patterns, @NotNull String fileName) {
+ private FileTypeChooser(@NotNull List<String> patterns, @NotNull String fileName) {
super(true);
myFileName = fileName;
@@ -80,7 +79,7 @@
}
}
myList.setModel(model);
- myPattern.setModel(new CollectionComboBoxModel(ContainerUtil.map(patterns, com.intellij.util.FunctionUtil.<String>id()), patterns[0]));
+ myPattern.setModel(new CollectionComboBoxModel(ContainerUtil.map(patterns, FunctionUtil.<String>id()), patterns.get(0)));
setTitle(FileTypesBundle.message("filetype.chooser.title"));
init();
@@ -91,7 +90,7 @@
myTitleLabel.setText(FileTypesBundle.message("filetype.chooser.prompt", myFileName));
myList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myList.setCellRenderer(new FileTypeRenderer(myList.getCellRenderer()));
+ myList.setCellRenderer(new FileTypeRenderer());
new DoubleClickListener() {
@Override
@@ -179,17 +178,18 @@
}
@NotNull
- static String[] suggestPatterns(@NotNull final String fileName) {
- final Deque<String> patterns = new LinkedList<String>();
- patterns.addFirst(fileName);
+ static List<String> suggestPatterns(@NotNull String fileName) {
+ List<String> patterns = ContainerUtil.newLinkedList(fileName);
+
int i = -1;
while ((i = fileName.indexOf('.', i + 1)) > 0) {
- final String extension = fileName.substring(i);
+ String extension = fileName.substring(i);
if (!StringUtil.isEmpty(extension)) {
- patterns.addFirst("*" + extension);
+ patterns.add(0, "*" + extension);
}
}
- return ArrayUtil.toStringArray(patterns);
+
+ return patterns;
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
index bca20ac..3e21d9c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeManagerImpl.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.
@@ -168,7 +168,7 @@
myMessageBus = bus;
mySchemesManager = schemesManagerFactory.createSchemesManager(FILE_SPEC, new BaseSchemeProcessor<AbstractFileType>() {
@Override
- public AbstractFileType readScheme(final Document document) throws InvalidDataException {
+ public AbstractFileType readScheme(@NotNull final Document document) throws InvalidDataException {
if (document == null) {
throw new InvalidDataException();
}
@@ -195,12 +195,12 @@
}
@Override
- public boolean shouldBeSaved(final AbstractFileType fileType) {
+ public boolean shouldBeSaved(@NotNull final AbstractFileType fileType) {
return shouldBeSavedToFile(fileType);
}
@Override
- public Document writeScheme(final AbstractFileType fileType) throws WriteExternalException {
+ public Document writeScheme(@NotNull final AbstractFileType fileType) throws WriteExternalException {
Element root = new Element(ELEMENT_FILETYPE);
writeHeader(root, fileType);
@@ -221,7 +221,7 @@
}
@Override
- public void onSchemeAdded(final AbstractFileType scheme) {
+ public void onSchemeAdded(@NotNull final AbstractFileType scheme) {
fireBeforeFileTypesChanged();
if (scheme instanceof ReadFileType) {
loadFileType((ReadFileType)scheme);
@@ -230,7 +230,7 @@
}
@Override
- public void onSchemeDeleted(final AbstractFileType scheme) {
+ public void onSchemeDeleted(@NotNull final AbstractFileType scheme) {
fireBeforeFileTypesChanged();
myPatternsTable.removeAllAssociations(scheme);
fireFileTypesChanged();
@@ -355,6 +355,10 @@
return fileType;
}
+ public static boolean isFileTypeDetectedFromContent(@NotNull VirtualFile file) {
+ return file.getUserData(DETECTED_FROM_CONTENT_FILE_TYPE_KEY) != null;
+ }
+
@Override
public FileType findFileTypeByName(String fileTypeName) {
FileType type = getStdFileType(fileTypeName);
@@ -1072,7 +1076,7 @@
}
public static String getFileTypeComponentName() {
- return PlatformUtils.isCommunity() ? "CommunityFileTypes" : "FileTypeManager";
+ return PlatformUtils.isIdeaCommunity() ? "CommunityFileTypes" : "FileTypeManager";
}
public FileTypeAssocTable getExtensionMap() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeRenderer.java b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeRenderer.java
index 050f912..f6b55da 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeRenderer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.ui.EmptyIcon;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.util.Arrays;
@@ -34,15 +35,27 @@
private final FileTypeListProvider myFileTypeListProvider;
- public FileTypeRenderer(final ListCellRenderer renderer) {
- this(renderer, new DefaultFileTypeListProvider());
+ public FileTypeRenderer() {
+ this(new DefaultFileTypeListProvider());
}
- public FileTypeRenderer(final ListCellRenderer renderer, final FileTypeListProvider fileTypeListProvider) {
+ public FileTypeRenderer(@NotNull FileTypeListProvider fileTypeListProvider) {
super();
myFileTypeListProvider = fileTypeListProvider;
}
+ /** @deprecated use {@link #FileTypeRenderer()} (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
+ public FileTypeRenderer(final ListCellRenderer renderer) {
+ this();
+ }
+
+ /** @deprecated use {@link #FileTypeRenderer(FileTypeListProvider)} (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
+ public FileTypeRenderer(final ListCellRenderer renderer, final FileTypeListProvider fileTypeListProvider) {
+ this(fileTypeListProvider);
+ }
+
@Override
public void customize(JList list, FileType type, int index, boolean selected, boolean hasFocus) {
LayeredIcon layeredIcon = new LayeredIcon(2);
@@ -79,10 +92,6 @@
return false;
}
- //public Dimension getPreferredSize() {
- // return new Dimension(0, 20);
- //}
-
private static class DefaultFileTypeListProvider implements FileTypeListProvider {
private final List<FileType> myFileTypes;
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 42a8d94..b809539 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
@@ -56,6 +56,7 @@
private final ArrayList<AnAction> myActions = new ArrayList<AnAction>(1);
private final Map<Container, Integer> myRootPane2BlockedId = new HashMap<Container, Integer>();
private int myLastHorScrolledComponentHash = 0;
+ private MouseEvent myPreviousMouseEvent;
// Don't compare MouseEvent ids. Swing has wrong sequence of events: first is mouse_clicked(500)
// then mouse_pressed(501), mouse_released(502) etc. Here, mouse events sorted so we can compare
@@ -125,6 +126,9 @@
* to normal event dispatching.
*/
public boolean dispatchMouseEvent(MouseEvent e) {
+ MouseEvent previousEvent = myPreviousMouseEvent;
+ myPreviousMouseEvent = e;
+
Component c = e.getComponent();
//frame activation by mouse click
@@ -160,6 +164,10 @@
ignore = true;
}
+ if (e.getID() == MOUSE_RELEASED && previousEvent != null && previousEvent.getID() == MOUSE_DRAGGED) {
+ ignore = true; // we don't want to process action bindings on mouse release at the end of drag operation
+ }
+
final JRootPane root = findRoot(e);
if (root != null) {
final Integer lastId = myRootPane2BlockedId.get(root);
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeyProcessorContext.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeyProcessorContext.java
index d01bc8e..e832caae 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeyProcessorContext.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeyProcessorContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,7 +45,7 @@
@Nullable
public JComponent getFoundComponent() {
- return myFoundComponent != null ? myFoundComponent.get() : null;
+ return SoftReference.dereference(myFoundComponent);
}
public void setFoundComponent(final JComponent foundComponent) {
@@ -77,7 +78,7 @@
@Nullable
public Component getFocusOwner() {
- return myFocusOwner != null ? myFocusOwner.get() : null;
+ return SoftReference.dereference(myFocusOwner);
}
public void setFocusOwner(final Component focusOwner) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
index 8e709b8..54f3fa0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/KeymapManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -67,17 +67,17 @@
"$ROOT_CONFIG$/keymaps",
new BaseSchemeProcessor<KeymapImpl>() {
@Override
- public KeymapImpl readScheme(final Document schemeContent) throws InvalidDataException, IOException, JDOMException {
+ public KeymapImpl readScheme(@NotNull final Document schemeContent) throws InvalidDataException, IOException, JDOMException {
return readKeymap(schemeContent);
}
@Override
- public Document writeScheme(final KeymapImpl scheme) throws WriteExternalException {
+ public Document writeScheme(@NotNull final KeymapImpl scheme) throws WriteExternalException {
return new Document(scheme.writeExternal());
}
@Override
- public boolean shouldBeSaved(final KeymapImpl scheme) {
+ public boolean shouldBeSaved(@NotNull final KeymapImpl scheme) {
return scheme.canModify();
}
},
@@ -233,6 +233,7 @@
mySchemesManager.loadSchemes();
}
+ @NotNull
private KeymapImpl readKeymap(Document document) throws JDOMException, InvalidDataException, IOException {
if (document == null) throw new InvalidDataException();
Element root = document.getRootElement();
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java
index eeb31e0..1b0c17f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTree.java
@@ -440,6 +440,7 @@
}
private class KeymapsRenderer extends ColoredTreeCellRenderer {
+ // Make sure that the text rendered by this method is 'searchable' via com.intellij.openapi.keymap.impl.ui.ActionsTree.filter method.
public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
final boolean showIcons = UISettings.getInstance().SHOW_ICONS_IN_MENUS;
Keymap originalKeymap = myKeymap != null ? myKeymap.getParent() : null;
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java
index f77ab13..51dda98 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/ActionsTreeUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -485,26 +485,18 @@
if (filter == null) return true;
if (action == null) return false;
final String insensitiveFilter = filter.toLowerCase();
- final String text = action.getTemplatePresentation().getText();
- if (text != null) {
- final String lowerText = text.toLowerCase();
- if (SearchUtil
- .isComponentHighlighted(lowerText, insensitiveFilter, force, null)) {
- return true;
- }
- else if (lowerText.contains(insensitiveFilter)) {
- return true;
- }
- }
- final String description = action.getTemplatePresentation().getDescription();
- if (description != null) {
- final String insensitiveDescription = description.toLowerCase();
- if (SearchUtil
- .isComponentHighlighted(insensitiveDescription, insensitiveFilter, force, null)) {
- return true;
- }
- else if (insensitiveDescription.contains(insensitiveFilter)) {
- return true;
+ for (String text : new String[]{action.getTemplatePresentation().getText(),
+ action.getTemplatePresentation().getDescription(),
+ action instanceof ActionStub ? ((ActionStub)action).getId() : ActionManager.getInstance().getId(action)}) {
+ if (text != null) {
+ final String lowerText = text.toLowerCase();
+
+ if (SearchUtil.isComponentHighlighted(lowerText, insensitiveFilter, force, null)) {
+ return true;
+ }
+ else if (lowerText.contains(insensitiveFilter)) {
+ return true;
+ }
}
}
return false;
diff --git a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
index 388e31e..69c8af9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/keymap/impl/ui/KeymapPanel.java
@@ -577,14 +577,14 @@
KeyMapBundle.message("conflict.shortcut.dialog.cancel.button"),
Messages.getWarningIcon());
- if(result == 0) {
+ if(result == Messages.YES) {
for (String id : conflicts.keySet()) {
for (KeyboardShortcut s : conflicts.get(id)) {
mySelectedKeymap.removeShortcut(id, s);
}
}
}
- else if (result != 1) {
+ else if (result != Messages.NO) {
return;
}
}
@@ -649,12 +649,12 @@
KeyMapBundle.message("conflict.shortcut.dialog.cancel.button"),
Messages.getWarningIcon());
- if(result == 0) {
+ if(result == Messages.YES) {
for (String id : actionIds) {
mySelectedKeymap.removeShortcut(id, mouseShortcut);
}
}
- else if (result != 1) {
+ else if (result != Messages.NO) {
return;
}
}
@@ -778,7 +778,7 @@
}
int result = Messages.showYesNoDialog(this, KeyMapBundle.message("delete.keymap.dialog.message"),
KeyMapBundle.message("delete.keymap.dialog.title"), Messages.getWarningIcon());
- if (result != 0) {
+ if (result != Messages.YES) {
return;
}
myKeymapListModel.removeElement(myKeymapList.getSelectedItem());
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
index 593abf3..323394a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerFactoryImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -66,7 +66,7 @@
}
@Override
- public void exportScheme(final E scheme, final String name, final String description) {
+ public void exportScheme(@NotNull final E scheme, final String name, final String description) {
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
index 376cfcf..92d7d87 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/SchemesManagerImpl.java
@@ -101,9 +101,7 @@
//noinspection ResultOfMethodCallIgnored
myBaseDir.mkdirs();
- if (ApplicationManager.getApplication().isUnitTestMode() || !ApplicationManager.getApplication().isCommandLine()) {
- addVFSListener();
- }
+ addVFSListener();
}
@Override
@@ -112,10 +110,7 @@
if (myVFSBaseDir != null) {
return doLoad();
}
- else {
- return Collections.emptyList();
- }
-
+ return Collections.emptyList();
}
private Collection<E> doLoad() {
@@ -166,7 +161,7 @@
VirtualFile file = event.getFile();
if (event.getRequestor() == null && isFileUnder(file, myVFSBaseDir) && !myInsideSave) {
- ArrayList<E> read = new ArrayList<E>();
+ List<E> read = new ArrayList<E>();
readSchemeFromFile(read, file, true);
if (!read.isEmpty()) {
E readScheme = read.get(0);
@@ -290,7 +285,7 @@
return result;
}
- private void initLoadedSchemes(final Collection<E> read) {
+ private void initLoadedSchemes(@NotNull Collection<E> read) {
for (E scheme : read) {
myProcessor.initScheme(scheme);
checkCurrentScheme(scheme);
@@ -325,10 +320,8 @@
deleteServerFiles(subPath);
}
- if (scheme != null) {
- loadScheme(scheme, false, fileName);
- result.add(scheme);
- }
+ loadScheme(scheme, false, fileName);
+ result.add(scheme);
}
}
catch (Exception e) {
@@ -341,7 +334,7 @@
}
private VirtualFile ensureFileText(final String fileName, final byte[] text) throws IOException {
- final IOException[] ex = new IOException[] {null};
+ final IOException[] ex = {null};
final VirtualFile _file = ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
@@ -605,12 +598,18 @@
}
- class SharedSchemeData {
- Document original;
- String name;
- String user;
- String description;
- E scheme;
+ private static class SharedSchemeData {
+ @NotNull private final Document original;
+ private final String name;
+ private final String user;
+ private final String description;
+
+ private SharedSchemeData(@NotNull Document original, String name, String user, String description) {
+ this.original = original;
+ this.name = name;
+ this.user = user;
+ this.description = description;
+ }
}
@Override
@@ -652,18 +651,20 @@
return result.values();
}
- private SharedSchemeData unwrap(final Document subDocument) {
- SharedSchemeData result = new SharedSchemeData();
+ @NotNull
+ private static SharedSchemeData unwrap(@NotNull Document subDocument) {
Element rootElement = subDocument.getRootElement();
+ SharedSchemeData result;
+ String name = rootElement.getAttributeValue(NAME);
if (rootElement.getName().equals(SHARED_SCHEME_ORIGINAL)) {
- result.name = rootElement.getAttributeValue(NAME);
- result.description = rootElement.getAttributeValue(DESCRIPTION);
- result.user = rootElement.getAttributeValue(USER);
- result.original = new Document(rootElement.getChildren().iterator().next().clone());
+ String description = rootElement.getAttributeValue(DESCRIPTION);
+ String user = rootElement.getAttributeValue(USER);
+ Document original = new Document(rootElement.getChildren().iterator().next().clone());
+ result = new SharedSchemeData(original, name, user, description);
}
else {
- result.name = rootElement.getAttributeValue(NAME);
- result.original = subDocument;
+ Document original = subDocument;
+ result = new SharedSchemeData(original, name, null, null);
}
return result;
}
@@ -687,7 +688,7 @@
}
@Override
- public void exportScheme(final E scheme, final String name, final String description) throws WriteExternalException, IOException {
+ public void exportScheme(@NotNull final E scheme, final String name, final String description) throws WriteExternalException, IOException {
StreamProvider provider = getProvider();
if (provider == null) {
return;
@@ -712,7 +713,7 @@
}
}
- private static Document wrap(final Document original, final String name, final String description) {
+ private static Document wrap(@NotNull Document original, @NotNull String name, @NotNull String description) {
Element sharedElement = new Element(SHARED_SCHEME_ORIGINAL);
sharedElement.setAttribute(NAME, name);
sharedElement.setAttribute(DESCRIPTION, description);
diff --git a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
index 877e75c..dd2fb73 100644
--- a/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
+++ b/platform/platform-impl/src/com/intellij/openapi/options/ex/ConfigurableWrapper.java
@@ -56,7 +56,7 @@
}
public static <T extends UnnamedConfigurable> List<T> createConfigurables(ExtensionPointName<? extends ConfigurableEP<T>> name) {
- return ContainerUtil.mapNotNull(Extensions.getExtensions(name), new NullableFunction<ConfigurableEP<T>, T>() {
+ return ContainerUtil.mapNotNull(name.getExtensions(), new NullableFunction<ConfigurableEP<T>, T>() {
@Override
public T fun(ConfigurableEP<T> ep) {
return wrapConfigurable(ep);
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java
index 49fef72..2c6bfe1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/BackgroundTaskQueue.java
@@ -84,6 +84,10 @@
public boolean isEmpty() {
return myProcessor.isEmpty();
}
+
+ public void waitForTasksToFinish() {
+ myProcessor.waitFor();
+ }
public void run(Task.Backgroundable task) {
run(task, null, null);
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
index 5fca6cb..b98f19b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressIndicatorUtils.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.
@@ -19,6 +19,7 @@
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationAdapter;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import org.jetbrains.annotations.NotNull;
@@ -43,8 +44,24 @@
return progress;
}
- public static void runWithWriteActionPriority(final Runnable action) {
- final ProgressIndicator progressIndicator = new ProgressIndicatorBase();
+ public static void runWithWriteActionPriority(@NotNull final Runnable action) {
+ runWithWriteActionPriority(new ReadTask() {
+ @Override
+ public void computeInReadAction(@NotNull ProgressIndicator indicator) {
+ action.run();
+ }
+
+ @Override
+ public void onCanceled(@NotNull ProgressIndicator indicator) {
+ }
+ });
+ }
+
+ public static void runWithWriteActionPriority(@NotNull final ReadTask task) {
+ runWithWriteActionPriority(new ProgressIndicatorBase(), task);
+ }
+
+ public static void runWithWriteActionPriority(final ProgressIndicator progressIndicator, final ReadTask task) {
final ApplicationAdapter listener = new ApplicationAdapter() {
@Override
public void beforeWriteActionStart(Object action) {
@@ -57,9 +74,23 @@
ProgressManager.getInstance().runProcess(new Runnable(){
@Override
public void run() {
- // This read action can possibe last for a long time, we want it to stop immediately on the first write access.
+ // This read action can possible last for a long time, we want it to stop immediately on the first write access.
// For this purpose we launch it under empty progress and invoke progressIndicator#cancel on write access to avoid possible write lock delays.
- application.runReadAction(action);
+ try {
+ application.runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ task.computeInReadAction(progressIndicator);
+ }
+ });
+ }
+ catch (ProcessCanceledException ignore) {
+ }
+ finally {
+ if (progressIndicator.isCanceled()) {
+ task.onCanceled(progressIndicator);
+ }
+ }
}
}, progressIndicator);
}
@@ -67,4 +98,17 @@
application.removeApplicationListener(listener);
}
}
+
+ public static void scheduleWithWriteActionPriority(@NotNull final ReadTask task) {
+ scheduleWithWriteActionPriority(new ProgressIndicatorBase(), task);
+ }
+
+ public static void scheduleWithWriteActionPriority(final ProgressIndicator indicator, final ReadTask task) {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ runWithWriteActionPriority(indicator, task);
+ }
+ });
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java
index 04a6146..0460a71 100644
--- a/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ProgressWindow.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.DialogWrapperPeer;
+import com.intellij.openapi.ui.impl.DialogWrapperPeerImpl;
import com.intellij.openapi.ui.impl.FocusTrackbackProvider;
import com.intellij.openapi.ui.impl.GlassPaneDialogWrapperPeer;
import com.intellij.openapi.util.*;
@@ -612,6 +613,14 @@
? new MyDialogWrapper(myParentWindow, myShouldShowCancel)
: new MyDialogWrapper(myProject, myShouldShowCancel);
myPopup.setUndecorated(true);
+ if (SystemInfo.isAppleJvm) {
+ // With Apple JDK we look for MacMessage parent by the window title.
+ // Let's set just the title as the window title for simplicity.
+ myPopup.setTitle(myTitle);
+ }
+ if (myPopup.getPeer() instanceof DialogWrapperPeerImpl) {
+ ((DialogWrapperPeerImpl)myPopup.getPeer()).setAutoRequestFocus(false);
+ }
myPopup.pack();
SwingUtilities.invokeLater(new Runnable() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/progress/util/ReadTask.java b/platform/platform-impl/src/com/intellij/openapi/progress/util/ReadTask.java
new file mode 100644
index 0000000..4f8f747
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/progress/util/ReadTask.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.progress.util;
+
+import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A computation that needs to be run in background and inside a read action, and canceled whenever a write action is about to occur.
+ *
+ * @see com.intellij.openapi.progress.util.ProgressIndicatorUtils#scheduleWithWriteActionPriority(ReadTask)
+ *
+ */
+public interface ReadTask {
+ /**
+ * Performs the computation.
+ * Is invoked inside a read action and under a progress indicator that's canceled when a write action is about to occur.
+ */
+ void computeInReadAction(@NotNull ProgressIndicator indicator);
+
+ /**
+ * Is invoked on the background computation thread whenever the computation is canceled by a write action.
+ * A likely implementation is to restart the computation, maybe based on the new state of the system.
+ */
+ void onCanceled(@NotNull ProgressIndicator indicator);
+
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java
index 3b68d0c..05c2031 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/CacheUpdateRunner.java
@@ -85,20 +85,9 @@
processed.add(virtualFile);
indicator.setFraction(processed.size() / total);
if (ApplicationManager.getApplication().isInternal()) {
- if (virtualFile.isValid()) {
- indicator.setText2(virtualFile.getPresentableUrl());
- }
- else {
- indicator.setText2("");
- }
+ indicator.setText2(virtualFile.getPresentableUrl());
}
}
- if (virtualFile.isValid()) {
- indicator.setText2(virtualFile.getPresentableUrl());
- }
- else {
- indicator.setText2("");
- }
}
};
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java
index 7315999..923935b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/FileContentQueue.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.
@@ -57,7 +57,7 @@
private final Object myProceedWithProcessingLock = new Object();
private static final boolean ourAllowParallelFileReading = SystemProperties.getBooleanProperty("idea.allow.parallel.file.reading", true);
- public void queue(final Collection<VirtualFile> files, @NotNull final ProgressIndicator indicator) {
+ public void queue(@NotNull Collection<VirtualFile> files, @NotNull final ProgressIndicator indicator) {
myFilesToLoadQueue.addAll(files);
final Runnable contentLoadingRunnable = new Runnable() {
@Override
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 570e644..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
@@ -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,14 +15,17 @@
*/
package com.intellij.openapi.project.impl;
+import com.intellij.openapi.project.ProjectManager;
import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class DefaultProject extends ProjectImpl {
- protected DefaultProject(@NotNull ProjectManagerImpl manager, @NotNull String filePath, boolean isOptimiseTestLoadSpeed, @NotNull String projectName) {
- super(manager, filePath, isOptimiseTestLoadSpeed, projectName);
+ private static final String TEMPLATE_PROJECT_NAME = "Default (Template) Project";
+
+ protected DefaultProject(@NotNull ProjectManager manager, @NotNull String filePath, boolean optimiseTestLoadSpeed) {
+ super(manager, filePath, optimiseTestLoadSpeed, TEMPLATE_PROJECT_NAME);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
index a47e306..5e29b31 100644
--- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectImpl.java
@@ -18,7 +18,7 @@
import com.intellij.diagnostic.PluginException;
import com.intellij.ide.RecentProjectsManagerBase;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
-import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.notification.*;
import com.intellij.openapi.application.ApplicationManager;
@@ -42,10 +42,7 @@
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressIndicatorProvider;
-import com.intellij.openapi.project.DumbAwareRunnable;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectBundle;
-import com.intellij.openapi.project.ProjectManagerAdapter;
+import com.intellij.openapi.project.*;
import com.intellij.openapi.project.ex.ProjectEx;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.startup.StartupManager;
@@ -77,26 +74,21 @@
public class ProjectImpl extends PlatformComponentManagerImpl implements ProjectEx {
private static final Logger LOG = Logger.getInstance("#com.intellij.project.impl.ProjectImpl");
private static final String PLUGIN_SETTINGS_ERROR = "Plugin Settings Error";
+
public static final String NAME_FILE = ".name";
+ public static Key<Long> CREATION_TIME = Key.create("ProjectImpl.CREATION_TIME");
- private ProjectManagerImpl myManager;
-
+ private ProjectManager myManager;
private volatile IProjectStore myComponentStore;
-
private MyProjectManagerListener myProjectManagerListener;
-
private final AtomicBoolean mySavingInProgress = new AtomicBoolean(false);
-
public boolean myOptimiseTestLoadSpeed;
- @NonNls public static final String TEMPLATE_PROJECT_NAME = "Default (Template) Project";
-
private String myName;
private String myOldName;
- public static Key<Long> CREATION_TIME = Key.create("ProjectImpl.CREATION_TIME");
+ protected ProjectImpl(@NotNull ProjectManager manager, @NotNull String filePath, boolean optimiseTestLoadSpeed, @Nullable String projectName) {
+ super(ApplicationManager.getApplication(), "Project " + (projectName == null ? filePath : projectName));
- protected ProjectImpl(@NotNull ProjectManagerImpl manager, @NotNull String filePath, boolean isOptimiseTestLoadSpeed, String projectName) {
- super(ApplicationManager.getApplication(), "Project "+(projectName == null ? filePath : projectName));
putUserData(CREATION_TIME, System.nanoTime());
getPicoContainer().registerComponentInstance(Project.class, this);
@@ -105,11 +97,10 @@
getStateStore().setProjectFilePath(filePath);
}
- myOptimiseTestLoadSpeed = isOptimiseTestLoadSpeed;
-
+ myOptimiseTestLoadSpeed = optimiseTestLoadSpeed;
myManager = manager;
- myName = isDefault() ? TEMPLATE_PROJECT_NAME : projectName == null ? getStateStore().getProjectName() : projectName;
+ myName = projectName == null ? getStateStore().getProjectName() : projectName;
if (!isDefault() && projectName != null && getStateStore().getStorageScheme().equals(StorageScheme.DIRECTORY_BASED)) {
myOldName = ""; // new project
}
@@ -141,20 +132,17 @@
super.bootstrapPicoContainer(name);
final MutablePicoContainer picoContainer = getPicoContainer();
- final ProjectStoreClassProvider projectStoreClassProvider = (ProjectStoreClassProvider)picoContainer.getComponentInstanceOfType(ProjectStoreClassProvider.class);
-
+ final ProjectStoreClassProvider projectStoreClassProvider =
+ (ProjectStoreClassProvider)picoContainer.getComponentInstanceOfType(ProjectStoreClassProvider.class);
picoContainer.registerComponentImplementation(ProjectPathMacroManager.class);
picoContainer.registerComponent(new ComponentAdapter() {
ComponentAdapter myDelegate;
-
public ComponentAdapter getDelegate() {
if (myDelegate == null) {
-
final Class storeClass = projectStoreClassProvider.getProjectStoreClass(isDefault());
- myDelegate = new CachingComponentAdapter(
- new ConstructorInjectionComponentAdapter(storeClass, storeClass, null, true));
+ myDelegate = new CachingComponentAdapter(new ConstructorInjectionComponentAdapter(storeClass, storeClass, null, true));
}
return myDelegate;
@@ -186,7 +174,6 @@
getDelegate().accept(visitor);
}
});
-
}
@NotNull
@@ -194,6 +181,8 @@
public IProjectStore getStateStore() {
IProjectStore componentStore = myComponentStore;
if (componentStore != null) return componentStore;
+
+ //noinspection SynchronizeOnThis
synchronized (this) {
componentStore = myComponentStore;
if (componentStore == null) {
@@ -228,9 +217,9 @@
}
public void loadProjectComponents() {
- final IdeaPluginDescriptor[] plugins = PluginManager.getPlugins();
+ final IdeaPluginDescriptor[] plugins = PluginManagerCore.getPlugins();
for (IdeaPluginDescriptor plugin : plugins) {
- if (PluginManager.shouldSkipPlugin(plugin)) continue;
+ if (PluginManagerCore.shouldSkipPlugin(plugin)) continue;
loadComponentsConfiguration(plugin.getProjectComponents(), plugin, isDefault());
}
}
@@ -299,7 +288,7 @@
@Override
public void init() {
long start = System.currentTimeMillis();
-// ProfilingUtil.startCPUProfiling();
+
final ProgressIndicator progressIndicator = isDefault() ? null : ProgressIndicatorProvider.getGlobalProgressIndicator();
if (progressIndicator != null) {
progressIndicator.pushState();
@@ -308,13 +297,17 @@
if (progressIndicator != null) {
progressIndicator.popState();
}
-// ProfilingUtil.captureCPUSnapshot();
+
long time = System.currentTimeMillis() - start;
LOG.info(getComponentConfigurations().length + " project components initialized in " + time + " ms");
+
getMessageBus().syncPublisher(ProjectLifecycleListener.TOPIC).projectComponentsInitialized(this);
- myProjectManagerListener = new MyProjectManagerListener();
- myManager.addProjectManagerListener(this, myProjectManagerListener);
+ //noinspection SynchronizeOnThis
+ synchronized (this) {
+ myProjectManagerListener = new MyProjectManagerListener();
+ myManager.addProjectManagerListener(this, myProjectManagerListener);
+ }
}
public boolean isToSaveProjectName() {
@@ -364,7 +357,7 @@
LOG.info(e);
}
catch (PluginException e) {
- PluginManager.disablePlugin(e.getPluginId().getIdString());
+ PluginManagerCore.disablePlugin(e.getPluginId().getIdString());
Notification notification = new Notification(
PLUGIN_SETTINGS_ERROR,
"Unable to save plugin settings!",
@@ -444,9 +437,7 @@
}
public String getDefaultName() {
- if (isDefault()) return TEMPLATE_PROJECT_NAME;
-
- return getStateStore().getProjectName();
+ return isDefault() ? myName : getStateStore().getProjectName();
}
private class MyProjectManagerListener extends ProjectManagerAdapter {
@@ -521,7 +512,7 @@
}
else {
if (Messages.showYesNoDialog(this, "Component could not be reloaded. Reload project?", "Configuration Changed",
- Messages.getQuestionIcon()) == 0) {
+ Messages.getQuestionIcon()) == Messages.YES) {
ProjectManagerEx.getInstanceEx().reloadProject(this);
}
}
@@ -585,9 +576,8 @@
}
private static String buildMessage() {
- final StringBuilder sb = new StringBuilder(
- "<p>Unable to save project files. Please ensure project files are writable and you have permissions to modify them.");
- return sb.append(" <a href=\"\">Try to save project again</a>.</p>").toString();
+ return "<p>Unable to save project files. Please ensure project files are writable and you have permissions to modify them." +
+ " <a href=\"\">Try to save project again</a>.</p>";
}
public Project getProject() {
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 0aafaae..35586cf 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
@@ -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 @@
import com.intellij.conversion.ConversionResult;
import com.intellij.conversion.ConversionService;
import com.intellij.ide.AppLifecycleListener;
+import com.intellij.ide.RecentProjectsManagerBase;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.notification.NotificationsManager;
@@ -118,7 +119,10 @@
return array;
}
- public ProjectManagerImpl(VirtualFileManager virtualFileManager, ProgressManager progressManager) {
+ /** @noinspection UnusedParameters*/
+ public ProjectManagerImpl(VirtualFileManager virtualFileManager,
+ RecentProjectsManagerBase recentProjectsManager,
+ ProgressManager progressManager) {
myProgressManager = progressManager;
Application app = ApplicationManager.getApplication();
MessageBus messageBus = app.getMessageBus();
@@ -258,10 +262,9 @@
}
private void initProject(@NotNull ProjectImpl project, @Nullable ProjectImpl template) throws IOException {
-
final ProgressIndicator indicator = myProgressManager.getProgressIndicator();
if (indicator != null) {
- indicator.setText(ProjectBundle.message("loading.components.for", project.isDefault() ? "Default" : project.getName()));
+ indicator.setText(ProjectBundle.message("loading.components.for", project.getName()));
indicator.setIndeterminate(true);
}
@@ -291,7 +294,7 @@
@NotNull String filePath,
boolean isDefault,
boolean isOptimiseTestLoadSpeed) {
- return isDefault ? new DefaultProject(this, "", isOptimiseTestLoadSpeed, projectName)
+ return isDefault ? new DefaultProject(this, "", isOptimiseTestLoadSpeed)
: new ProjectImpl(this, new File(filePath).getAbsolutePath(), isOptimiseTestLoadSpeed, projectName);
}
@@ -347,7 +350,7 @@
LOG.assertTrue(!myDefaultProjectWasDisposed, "Default project has been already disposed!");
if (myDefaultProject == null) {
try {
- myDefaultProject = createProject("Default project", "Default project", true, ApplicationManager.getApplication().isUnitTestMode());
+ myDefaultProject = createProject(null, "", true, ApplicationManager.getApplication().isUnitTestMode());
initProject(myDefaultProject, null);
myDefaultProjectRootElement = null;
}
@@ -655,7 +658,7 @@
message += ApplicationNamesInfo.getInstance().getProductName() + "?";
if (Messages.showYesNoDialog(message,
- "Application Configuration Reload", Messages.getQuestionIcon()) == 0) {
+ "Application Configuration Reload", Messages.getQuestionIcon()) == Messages.YES) {
for (Pair<VirtualFile, StateStorage> cause : causes) {
StateStorage stateStorage = cause.getSecond();
if (stateStorage instanceof XmlElementStorage) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java b/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java
index 543efbf..493a087 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/ex/MessagesEx.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -150,6 +150,7 @@
}, ApplicationManager.getApplication().getDisposed());
}
+ @YesNoResult
public int askYesNo() {
setIcon(getQuestionIcon());
return showYesNoDialog(getProject(), getMessage(), getTitle(), getIcon());
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
index 5a09049..dc9821e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/DialogWrapperPeerImpl.java
@@ -43,6 +43,7 @@
import com.intellij.openapi.wm.ex.WindowManagerEx;
import com.intellij.openapi.wm.impl.IdeFrameImpl;
import com.intellij.openapi.wm.impl.IdeGlassPaneImpl;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.*;
import com.intellij.ui.components.JBLayeredPane;
import com.intellij.ui.mac.foundation.Foundation;
@@ -762,12 +763,12 @@
queue.getKeyEventDispatcher().resetState();
}
- if (myProject != null) {
- Project project = myProject.get();
- if (project != null && !project.isDisposed() && project.isInitialized()) {
- IdeFocusManager.findInstanceByComponent(this).requestFocus(new MyFocusCommand(dialogWrapper), true);
- }
- }
+ // if (myProject != null) {
+ // Project project = myProject.get();
+ //if (project != null && !project.isDisposed() && project.isInitialized()) {
+ // // IdeFocusManager.findInstanceByComponent(this).requestFocus(new MyFocusCommand(dialogWrapper), true);
+ //}
+ // }
}
if (SystemInfo.isMac && myProject != null && Registry.is("ide.mac.fix.dialog.showing") && !dialogWrapper.isModalProgress()) {
@@ -788,7 +789,7 @@
@Nullable
private Project getProject() {
- return myProject != null ? myProject.get() : null;
+ return SoftReference.dereference(myProject);
}
@Override
@@ -1197,4 +1198,8 @@
public void centerInParent() {
myDialog.centerInParent();
}
+
+ public void setAutoRequestFocus(boolean b) {
+ UIUtil.setAutoRequestFocus((JDialog)myDialog, b);
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java
index f305db1..0c83d39 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/impl/GlassPaneDialogWrapperPeer.java
@@ -63,6 +63,7 @@
private Project myProject;
private MyDialog myDialog;
private boolean myCanBeParent;
+ private String myTitle;
public GlassPaneDialogWrapperPeer(DialogWrapper wrapper, Project project, boolean canBeParent) throws GlasspanePeerUnavailableException {
myWrapper = wrapper;
@@ -236,7 +237,7 @@
}
public void setTitle(final String title) {
- throw new UnsupportedOperationException("Not implemented in " + getClass().getCanonicalName());
+ myTitle = title;
}
// TODO: WTF?! VOID?!!!
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AbstractCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AbstractCommand.java
index 3c23452..da4ac90 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AbstractCommand.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AbstractCommand.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,14 +18,13 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.ui.playback.PlaybackCommand;
import com.intellij.openapi.ui.playback.PlaybackContext;
-import com.intellij.openapi.ui.playback.PlaybackRunner;
import com.intellij.openapi.util.ActionCallback;
import java.io.File;
public abstract class AbstractCommand implements PlaybackCommand {
- public static String CMD_PREFIX = "%";
+ public static final String CMD_PREFIX = "%";
private final String myText;
private final int myLine;
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AssertFocused.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AssertFocused.java
index 7993aae..657f39d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AssertFocused.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/AssertFocused.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,7 +17,6 @@
import com.intellij.openapi.ui.Queryable;
import com.intellij.openapi.ui.playback.PlaybackContext;
-import com.intellij.openapi.ui.playback.PlaybackRunner;
import com.intellij.openapi.util.ActionCallback;
import com.intellij.openapi.wm.IdeFocusManager;
@@ -26,7 +25,7 @@
public class AssertFocused extends AbstractCommand {
- public static String PREFIX = CMD_PREFIX + "assert focused";
+ public static final String PREFIX = CMD_PREFIX + "assert focused";
public AssertFocused(String text, int line) {
super(text, line);
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/DelayCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/DelayCommand.java
index c4689dd..ba773d4 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/DelayCommand.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/DelayCommand.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,7 +19,7 @@
import com.intellij.openapi.util.ActionCallback;
public class DelayCommand extends AbstractCommand {
- public static String PREFIX = CMD_PREFIX + "delay";
+ public static final String PREFIX = CMD_PREFIX + "delay";
public DelayCommand(String text, int line) {
super(text, line);
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyShortcutCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyShortcutCommand.java
index c272125..5031ec3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyShortcutCommand.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyShortcutCommand.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,8 +20,8 @@
public class KeyShortcutCommand extends TypeCommand {
- public static String PREFIX = CMD_PREFIX + "[";
- public static String POSTFIX = "]";
+ public static final String PREFIX = CMD_PREFIX + "[";
+ public static final String POSTFIX = "]";
public KeyShortcutCommand(String text, int line) {
super(text, line);
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStokeMap.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStokeMap.java
deleted file mode 100644
index 04a3214..0000000
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStokeMap.java
+++ /dev/null
@@ -1,191 +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.openapi.ui.playback.commands;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ReflectionUtil;
-
-import javax.swing.*;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.HashMap;
-import java.util.Map;
-
-public class KeyStokeMap {
-
- private static final Logger LOG = Logger.getInstance("#com.intellij.ui.debugger.extensions.playback.KeyStokeMap");
-
- private Map<Character, KeyStroke> myMap;
-
- public KeyStroke get(char c) {
- Character mappedChar = new Character(c);
-
- if (getMap().containsKey(mappedChar)) {
- return getMap().get(mappedChar);
- } else {
- return KeyStroke.getKeyStroke(c);
- }
- }
-
- public boolean containsChar(char c) {
- return getMap().containsKey(c);
- }
-
- public KeyStroke get(String strokeText) {
- String s = strokeText.trim();
-
- assert s.length() > 0;
-
- final String lowerCaseS = s.toLowerCase();
- boolean hasModifiers = lowerCaseS.contains("shift") || lowerCaseS.contains("control") || lowerCaseS.contains("alt") || lowerCaseS.contains("meta");
-
- String symbol = null;
- int beforeSymbol = -1;
- boolean haveSymbol = false;
- KeyStroke symbolStroke = null;
-
- if (hasModifiers) {
- beforeSymbol = s.lastIndexOf(" ");
- haveSymbol = beforeSymbol > 0;
- } else {
- symbol = s;
- haveSymbol = true;
- }
-
- int modifiers = 0;
- if (haveSymbol) {
- if (symbol == null) {
- symbol = s.substring(beforeSymbol + 1);
- }
-
- if (symbol.length() > 1) {
- final Integer code = (Integer)ReflectionUtil.getField(KeyEvent.class, null, int.class, "VK_" + StringUtil.toUpperCase(symbol));
- if (code == null) {
- return throwUnrecognized(symbol);
- }
- symbolStroke = KeyStroke.getKeyStroke(code.intValue(), 0);
- }
-
- String modifierPlusA = s.substring(0, s.length() - (s.length() - beforeSymbol - 1)) + "A";
- final KeyStroke modifierPlusAStroke = KeyStroke.getKeyStroke(modifierPlusA);
-
- if (symbolStroke == null) {
- symbol = String.valueOf(symbol.charAt(0));
- symbolStroke = get(symbol.charAt(0));
- }
-
- modifiers = modifierPlusAStroke.getModifiers();
- if ((symbolStroke.getModifiers() & KeyEvent.SHIFT_MASK) > 0) {
- modifiers |= KeyEvent.SHIFT_MASK;
- }
- }
-
- if (symbolStroke == null || symbolStroke.getKeyCode() == KeyEvent.VK_UNDEFINED) {
- return throwUnrecognized(symbol);
- }
-
-
- return KeyStroke.getKeyStroke(symbolStroke.getKeyCode(), modifiers, false);
- }
-
- private KeyStroke throwUnrecognized(String symbol) {
- throw new IllegalArgumentException("Unrecoginzed symbol: " + symbol);
- }
-
- private static Map<Character, KeyStroke> generateKeyStrokeMappings() {
- LOG.debug("Generating default keystroke mappings");
- // character, keycode, modifiers
- int shift = InputEvent.SHIFT_MASK;
- //int alt = InputEvent.ALT_MASK;
- //int altg = InputEvent.ALT_GRAPH_MASK;
- int ctrl = InputEvent.CTRL_MASK;
- //int meta = InputEvent.META_MASK;
- // These are assumed to be standard across all keyboards (?)
- int[][] universalMappings = {{'', KeyEvent.VK_ESCAPE, 0}, // No escape sequence exists
- {'\b', KeyEvent.VK_BACK_SPACE, 0}, {'', KeyEvent.VK_DELETE, 0}, // None for this one either
- {'\n', KeyEvent.VK_ENTER, 0}, {'\r', KeyEvent.VK_ENTER, 0},};
- // Add to these as needed; note that this is based on a US keyboard
- // mapping, and will likely fail for others.
- int[][] mappings =
- {{' ', KeyEvent.VK_SPACE, 0,}, {'\t', KeyEvent.VK_TAB, 0,}, {'~', KeyEvent.VK_BACK_QUOTE, shift,}, {'`', KeyEvent.VK_BACK_QUOTE, 0,},
- {'!', KeyEvent.VK_1, shift,}, {'@', KeyEvent.VK_2, shift,}, {'#', KeyEvent.VK_3, shift,}, {'$', KeyEvent.VK_4, shift,},
- {'%', KeyEvent.VK_5, shift,}, {'^', KeyEvent.VK_6, shift,}, {'&', KeyEvent.VK_7, shift,}, {'*', KeyEvent.VK_8, shift,},
- {'(', KeyEvent.VK_9, shift,}, {')', KeyEvent.VK_0, shift,}, {'-', KeyEvent.VK_MINUS, 0,}, {'_', KeyEvent.VK_MINUS, shift,},
- {'=', KeyEvent.VK_EQUALS, 0,}, {'+', KeyEvent.VK_EQUALS, shift,}, {'[', KeyEvent.VK_OPEN_BRACKET, 0,},
- {'{', KeyEvent.VK_OPEN_BRACKET, shift,},
- // NOTE: The following does NOT produce a left brace
- //{ '{', KeyEvent.VK_BRACELEFT, 0, },
- {']', KeyEvent.VK_CLOSE_BRACKET, 0,}, {'}', KeyEvent.VK_CLOSE_BRACKET, shift,}, {'|', KeyEvent.VK_BACK_SLASH, shift,},
- {';', KeyEvent.VK_SEMICOLON, 0,}, {':', KeyEvent.VK_SEMICOLON, shift,}, {',', KeyEvent.VK_COMMA, 0,},
- {'<', KeyEvent.VK_COMMA, shift,}, {'.', KeyEvent.VK_PERIOD, 0,}, {'>', KeyEvent.VK_PERIOD, shift,}, {'/', KeyEvent.VK_SLASH, 0,},
- {'?', KeyEvent.VK_SLASH, shift,}, {'\\', KeyEvent.VK_BACK_SLASH, 0,}, {'|', KeyEvent.VK_BACK_SLASH, shift,},
- {'\'', KeyEvent.VK_QUOTE, 0,}, {'"', KeyEvent.VK_QUOTE, shift,},};
- HashMap<Character, KeyStroke> map = new HashMap<Character, KeyStroke>();
- // Universal mappings
- for (int i = 0; i < universalMappings.length; i++) {
- int[] entry = universalMappings[i];
- KeyStroke stroke = KeyStroke.getKeyStroke(entry[1], entry[2]);
- map.put(new Character((char)entry[0]), stroke);
- }
-
- //// If the locale is not en_US/GB, provide only a very basic map and
- //// rely on key_typed events instead
- //Locale locale = Locale.getDefault();
- //if (!Locale.US.equals(locale) && !Locale.UK.equals(locale)) {
- // LOG.debug("Not US: " + locale);
- // return map;
- //}
-
- // Basic symbol/punctuation mappings
- for (int i = 0; i < mappings.length; i++) {
- int[] entry = mappings[i];
- KeyStroke stroke = KeyStroke.getKeyStroke(entry[1], entry[2]);
- map.put(new Character((char)entry[0]), stroke);
- }
- // Lowercase
- for (int i = 'a'; i <= 'z'; i++) {
- KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_A + i - 'a', 0);
- map.put(new Character((char)i), stroke);
- // control characters
- stroke = KeyStroke.getKeyStroke(KeyEvent.VK_A + i - 'a', ctrl);
- Character key = new Character((char)(i - 'a' + 1));
- // Make sure we don't overwrite something already there
- if (map.get(key) == null) {
- map.put(key, stroke);
- }
- }
- // Capitals
- for (int i = 'A'; i <= 'Z'; i++) {
- KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_A + i - 'A', shift);
- map.put(new Character((char)i), stroke);
- }
- // digits
- for (int i = '0'; i <= '9'; i++) {
- KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_0 + i - '0', 0);
- map.put(new Character((char)i), stroke);
- }
- return map;
- }
-
- private Map<Character, KeyStroke> getMap() {
- if (myMap == null) {
- myMap = generateKeyStrokeMappings();
- }
-
- return myMap;
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java
new file mode 100644
index 0000000..edc6300
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/KeyStrokeMap.java
@@ -0,0 +1,191 @@
+/*
+ * 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.openapi.ui.playback.commands;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.ReflectionUtil;
+
+import javax.swing.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.HashMap;
+import java.util.Map;
+
+public class KeyStrokeMap {
+
+ private static final Logger LOG = Logger.getInstance("#com.intellij.ui.debugger.extensions.playback.KeyStokeMap");
+
+ private Map<Character, KeyStroke> myMap;
+
+ public KeyStroke get(char c) {
+ Character mappedChar = new Character(c);
+
+ if (getMap().containsKey(mappedChar)) {
+ return getMap().get(mappedChar);
+ } else {
+ return KeyStroke.getKeyStroke(c);
+ }
+ }
+
+ public boolean containsChar(char c) {
+ return getMap().containsKey(c);
+ }
+
+ public KeyStroke get(String strokeText) {
+ String s = strokeText.trim();
+
+ assert s.length() > 0;
+
+ final String lowerCaseS = s.toLowerCase();
+ boolean hasModifiers = lowerCaseS.contains("shift") || lowerCaseS.contains("control") || lowerCaseS.contains("alt") || lowerCaseS.contains("meta");
+
+ String symbol = null;
+ int beforeSymbol = -1;
+ boolean haveSymbol = false;
+ KeyStroke symbolStroke = null;
+
+ if (hasModifiers) {
+ beforeSymbol = s.lastIndexOf(" ");
+ haveSymbol = beforeSymbol > 0;
+ } else {
+ symbol = s;
+ haveSymbol = true;
+ }
+
+ int modifiers = 0;
+ if (haveSymbol) {
+ if (symbol == null) {
+ symbol = s.substring(beforeSymbol + 1);
+ }
+
+ if (symbol.length() > 1) {
+ final Integer code = (Integer)ReflectionUtil.getField(KeyEvent.class, null, int.class, "VK_" + StringUtil.toUpperCase(symbol));
+ if (code == null) {
+ return throwUnrecognized(symbol);
+ }
+ symbolStroke = KeyStroke.getKeyStroke(code.intValue(), 0);
+ }
+
+ String modifierPlusA = s.substring(0, s.length() - (s.length() - beforeSymbol - 1)) + "A";
+ final KeyStroke modifierPlusAStroke = KeyStroke.getKeyStroke(modifierPlusA);
+
+ if (symbolStroke == null) {
+ symbol = String.valueOf(symbol.charAt(0));
+ symbolStroke = get(symbol.charAt(0));
+ }
+
+ modifiers = modifierPlusAStroke.getModifiers();
+ if ((symbolStroke.getModifiers() & KeyEvent.SHIFT_MASK) > 0) {
+ modifiers |= KeyEvent.SHIFT_MASK;
+ }
+ }
+
+ if (symbolStroke == null || symbolStroke.getKeyCode() == KeyEvent.VK_UNDEFINED) {
+ return throwUnrecognized(symbol);
+ }
+
+
+ return KeyStroke.getKeyStroke(symbolStroke.getKeyCode(), modifiers, false);
+ }
+
+ private KeyStroke throwUnrecognized(String symbol) {
+ throw new IllegalArgumentException("Unrecoginzed symbol: " + symbol);
+ }
+
+ private static Map<Character, KeyStroke> generateKeyStrokeMappings() {
+ LOG.debug("Generating default keystroke mappings");
+ // character, keycode, modifiers
+ int shift = InputEvent.SHIFT_MASK;
+ //int alt = InputEvent.ALT_MASK;
+ //int altg = InputEvent.ALT_GRAPH_MASK;
+ int ctrl = InputEvent.CTRL_MASK;
+ //int meta = InputEvent.META_MASK;
+ // These are assumed to be standard across all keyboards (?)
+ int[][] universalMappings = {{'', KeyEvent.VK_ESCAPE, 0}, // No escape sequence exists
+ {'\b', KeyEvent.VK_BACK_SPACE, 0}, {'', KeyEvent.VK_DELETE, 0}, // None for this one either
+ {'\n', KeyEvent.VK_ENTER, 0}, {'\r', KeyEvent.VK_ENTER, 0},};
+ // Add to these as needed; note that this is based on a US keyboard
+ // mapping, and will likely fail for others.
+ int[][] mappings =
+ {{' ', KeyEvent.VK_SPACE, 0,}, {'\t', KeyEvent.VK_TAB, 0,}, {'~', KeyEvent.VK_BACK_QUOTE, shift,}, {'`', KeyEvent.VK_BACK_QUOTE, 0,},
+ {'!', KeyEvent.VK_1, shift,}, {'@', KeyEvent.VK_2, shift,}, {'#', KeyEvent.VK_3, shift,}, {'$', KeyEvent.VK_4, shift,},
+ {'%', KeyEvent.VK_5, shift,}, {'^', KeyEvent.VK_6, shift,}, {'&', KeyEvent.VK_7, shift,}, {'*', KeyEvent.VK_8, shift,},
+ {'(', KeyEvent.VK_9, shift,}, {')', KeyEvent.VK_0, shift,}, {'-', KeyEvent.VK_MINUS, 0,}, {'_', KeyEvent.VK_MINUS, shift,},
+ {'=', KeyEvent.VK_EQUALS, 0,}, {'+', KeyEvent.VK_EQUALS, shift,}, {'[', KeyEvent.VK_OPEN_BRACKET, 0,},
+ {'{', KeyEvent.VK_OPEN_BRACKET, shift,},
+ // NOTE: The following does NOT produce a left brace
+ //{ '{', KeyEvent.VK_BRACELEFT, 0, },
+ {']', KeyEvent.VK_CLOSE_BRACKET, 0,}, {'}', KeyEvent.VK_CLOSE_BRACKET, shift,}, {'|', KeyEvent.VK_BACK_SLASH, shift,},
+ {';', KeyEvent.VK_SEMICOLON, 0,}, {':', KeyEvent.VK_SEMICOLON, shift,}, {',', KeyEvent.VK_COMMA, 0,},
+ {'<', KeyEvent.VK_COMMA, shift,}, {'.', KeyEvent.VK_PERIOD, 0,}, {'>', KeyEvent.VK_PERIOD, shift,}, {'/', KeyEvent.VK_SLASH, 0,},
+ {'?', KeyEvent.VK_SLASH, shift,}, {'\\', KeyEvent.VK_BACK_SLASH, 0,}, {'|', KeyEvent.VK_BACK_SLASH, shift,},
+ {'\'', KeyEvent.VK_QUOTE, 0,}, {'"', KeyEvent.VK_QUOTE, shift,},};
+ HashMap<Character, KeyStroke> map = new HashMap<Character, KeyStroke>();
+ // Universal mappings
+ for (int i = 0; i < universalMappings.length; i++) {
+ int[] entry = universalMappings[i];
+ KeyStroke stroke = KeyStroke.getKeyStroke(entry[1], entry[2]);
+ map.put(new Character((char)entry[0]), stroke);
+ }
+
+ //// If the locale is not en_US/GB, provide only a very basic map and
+ //// rely on key_typed events instead
+ //Locale locale = Locale.getDefault();
+ //if (!Locale.US.equals(locale) && !Locale.UK.equals(locale)) {
+ // LOG.debug("Not US: " + locale);
+ // return map;
+ //}
+
+ // Basic symbol/punctuation mappings
+ for (int i = 0; i < mappings.length; i++) {
+ int[] entry = mappings[i];
+ KeyStroke stroke = KeyStroke.getKeyStroke(entry[1], entry[2]);
+ map.put(new Character((char)entry[0]), stroke);
+ }
+ // Lowercase
+ for (int i = 'a'; i <= 'z'; i++) {
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_A + i - 'a', 0);
+ map.put(new Character((char)i), stroke);
+ // control characters
+ stroke = KeyStroke.getKeyStroke(KeyEvent.VK_A + i - 'a', ctrl);
+ Character key = new Character((char)(i - 'a' + 1));
+ // Make sure we don't overwrite something already there
+ if (map.get(key) == null) {
+ map.put(key, stroke);
+ }
+ }
+ // Capitals
+ for (int i = 'A'; i <= 'Z'; i++) {
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_A + i - 'A', shift);
+ map.put(new Character((char)i), stroke);
+ }
+ // digits
+ for (int i = '0'; i <= '9'; i++) {
+ KeyStroke stroke = KeyStroke.getKeyStroke(KeyEvent.VK_0 + i - '0', 0);
+ map.put(new Character((char)i), stroke);
+ }
+ return map;
+ }
+
+ private Map<Character, KeyStroke> getMap() {
+ if (myMap == null) {
+ myMap = generateKeyStrokeMappings();
+ }
+
+ return myMap;
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/RegistryValueCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/RegistryValueCommand.java
index 36c4d3f..b4f7b2f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/RegistryValueCommand.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/RegistryValueCommand.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,7 +21,7 @@
public class RegistryValueCommand extends AbstractCommand {
- public static String PREFIX = CMD_PREFIX + "set";
+ public static final String PREFIX = CMD_PREFIX + "set";
public RegistryValueCommand(String text, int line) {
super(text, line);
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/StopCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/StopCommand.java
index 5e44570..1d122fe 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/StopCommand.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/StopCommand.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,7 @@
public class StopCommand extends AbstractCommand {
- public static String PREFIX = CMD_PREFIX + "stop";
+ public static final String PREFIX = CMD_PREFIX + "stop";
public StopCommand(String text, int line) {
super(text, line);
diff --git a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/TypeCommand.java b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/TypeCommand.java
index 471d391..4753d45 100644
--- a/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/TypeCommand.java
+++ b/platform/platform-impl/src/com/intellij/openapi/ui/playback/commands/TypeCommand.java
@@ -25,7 +25,7 @@
public abstract class TypeCommand extends AbstractCommand {
- private static final KeyStokeMap ourMap = new KeyStokeMap();
+ private static final KeyStrokeMap ourMap = new KeyStrokeMap();
public TypeCommand(String text, int line) {
super(text, line);
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java
index 319ad85..1b60dd3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java
@@ -13,11 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
-/*
- * User: anna
- * Date: 04-Dec-2007
- */
package com.intellij.openapi.updateSettings.impl;
import com.intellij.CommonBundle;
@@ -28,114 +23,87 @@
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.IdeBorderFactory;
-import com.intellij.ui.TableUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import java.awt.*;
-import java.util.List;
+/**
+ * @author anna
+ */
public abstract class AbstractUpdateDialog extends DialogWrapper {
private final boolean myEnableLink;
- protected final List<PluginDownloader> myUploadedPlugins;
- protected boolean myShowConfirmation = true;
- protected AbstractUpdateDialog(boolean canBeParent, boolean enableLink, final List<PluginDownloader> updatePlugins) {
- super(canBeParent);
+ protected AbstractUpdateDialog(boolean enableLink) {
+ super(true);
myEnableLink = enableLink;
- myUploadedPlugins = updatePlugins;
+ setTitle(IdeBundle.message("updates.info.dialog.title"));
}
@Override
protected void init() {
- setButtonsText();
- super.init();
- }
-
- protected void initPluginsPanel(final JPanel panel, JPanel pluginsPanel, JEditorPane updateLinkPane) {
- pluginsPanel.setVisible(myUploadedPlugins != null);
- if (myUploadedPlugins != null) {
- final DetectedPluginsPanel foundPluginsPanel = new DetectedPluginsPanel();
-
- foundPluginsPanel.addStateListener(new DetectedPluginsPanel.Listener() {
- public void stateChanged() {
- setButtonsText();
- }
- });
- for (PluginDownloader uploadedPlugin : myUploadedPlugins) {
- foundPluginsPanel.add(uploadedPlugin);
- }
- TableUtil.ensureSelectionExists(foundPluginsPanel.getEntryTable());
- pluginsPanel.add(foundPluginsPanel, BorderLayout.CENTER);
- }
- updateLinkPane.setBackground(UIUtil.getPanelBackground());
- String css = UIUtil.getCssFontDeclaration(UIUtil.getLabelFont());
- if (UIUtil.isUnderDarcula()) {
- css += "<style>body {background: #" + ColorUtil.toHex(UIUtil.getPanelBackground()) + ";}</style>";
- }
- updateLinkPane.setBorder(IdeBorderFactory.createEmptyBorder());
- updateLinkPane.setText(IdeBundle.message("updates.configure.label", css, ShowSettingsUtil.getSettingsMenuName()));
- updateLinkPane.setEditable(false);
- LabelTextReplacingUtil.replaceText(panel);
-
- if (myEnableLink) {
- updateLinkPane.addHyperlinkListener(new HyperlinkListener() {
- public void hyperlinkUpdate(final HyperlinkEvent e) {
- if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
- final ShowSettingsUtil util = ShowSettingsUtil.getInstance();
- UpdateSettingsConfigurable updatesSettings = new UpdateSettingsConfigurable();
- updatesSettings.setCheckNowEnabled(false);
- util.editConfigurable(panel, updatesSettings);
- }
- }
- });
- }
- }
-
- private void setButtonsText() {
setOKButtonText(getOkButtonText());
setCancelButtonText(getCancelButtonText());
- }
-
- protected String getCancelButtonText() {
- return CommonBundle.getCancelButtonText();
+ super.init();
}
protected String getOkButtonText() {
return CommonBundle.getOkButtonText();
}
- protected void doOKAction() {
- if (doDownloadAndPrepare() && isShowConfirmation()) {
- final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
- // do not stack several modal dialogs (native & swing)
- app.invokeLater(new Runnable() {
- @Override
- public void run() {
- app.restart(true);
- }
- });
- }
- super.doOKAction();
+ protected String getCancelButtonText() {
+ return CommonBundle.getCancelButtonText();
}
- protected boolean doDownloadAndPrepare() {
- if (myUploadedPlugins != null) {
- UpdateChecker.saveDisabledToUpdatePlugins();
- if (UpdateChecker.install(myUploadedPlugins)) {
- return true;
+ protected void restart() {
+ final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
+ // do not stack several modal dialogs (native & swing)
+ app.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ app.restart(true);
}
+ });
+ }
+
+ protected void configureMessageArea(@NotNull JEditorPane area) {
+ configureMessageArea(area, IdeBundle.message("updates.configure.label", ShowSettingsUtil.getSettingsMenuName()), null, null);
+ }
+
+ protected void configureMessageArea(final @NotNull JEditorPane area,
+ @NotNull String messageBody,
+ @Nullable Color fontColor,
+ @Nullable HyperlinkListener listener) {
+ String text = "<html><head>" +
+ UIUtil.getCssFontDeclaration(UIUtil.getLabelFont(), fontColor, null, null) +
+ "<style>body {background: #" + ColorUtil.toHex(UIUtil.getPanelBackground()) + ";}</style>" +
+ "</head><body>" +
+ messageBody +
+ "</body></html>";
+
+ area.setBackground(UIUtil.getPanelBackground());
+ area.setBorder(IdeBorderFactory.createEmptyBorder());
+ area.setText(text);
+ area.setEditable(false);
+
+ if (listener == null && myEnableLink) {
+ listener = new HyperlinkListener() {
+ @Override
+ public void hyperlinkUpdate(final HyperlinkEvent e) {
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ UpdateSettingsConfigurable settings = new UpdateSettingsConfigurable();
+ settings.setCheckNowEnabled(false);
+ ShowSettingsUtil.getInstance().editConfigurable(area, settings);
+ }
+ }
+ };
}
- return false;
- }
-
- public void setShowConfirmation(boolean showConfirmation) {
- myShowConfirmation = showConfirmation;
- }
-
- public boolean isShowConfirmation() {
- return myShowConfirmation;
+ if (listener != null) {
+ area.addHyperlinkListener(listener);
+ }
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
index d685317..6401fbb 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -15,61 +15,20 @@
*/
package com.intellij.openapi.updateSettings.impl;
-import com.intellij.ide.plugins.PluginHostsConfigurable;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.List;
public class CheckForUpdateAction extends AnAction implements DumbAware {
-
+ @Override
public void update(AnActionEvent e) {
e.getPresentation().setVisible(!SystemInfo.isMacSystemMenu);
}
+ @Override
public void actionPerformed(AnActionEvent e) {
- Project project = e.getData(CommonDataKeys.PROJECT);
- actionPerformed(project, true, null, UpdateSettings.getInstance());
- }
-
- public static void actionPerformed(Project project,
- final boolean enableLink,
- final @Nullable PluginHostsConfigurable hostsConfigurable,
- final UpdateSettings instance) {
- ProgressManager.getInstance().run(new Task.Backgroundable(project, "Checking for updates", true) {
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- indicator.setIndeterminate(true);
- final CheckForUpdateResult result = UpdateChecker.checkForUpdates(instance, true);
-
- if (result.getState() == UpdateStrategy.State.CONNECTION_ERROR) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- public void run() {
- UpdateChecker.showConnectionErrorDialog();
- }
- });
- return;
- }
-
- final List<PluginDownloader> updatedPlugins = UpdateChecker.updatePlugins(true, hostsConfigurable, indicator);
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- instance.saveLastCheckedInfo();
- UpdateChecker.showUpdateResult(result, updatedPlugins, true, enableLink, true);
- }
- });
- }
- });
+ UpdateChecker.updateAndShowResult(e.getData(CommonDataKeys.PROJECT), false, null, UpdateSettings.getInstance());
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateResult.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateResult.java
index 4d5b99c..82aac76 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateResult.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/CheckForUpdateResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -15,78 +15,50 @@
*/
package com.intellij.openapi.updateSettings.impl;
-
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class CheckForUpdateResult {
- @Nullable
+ private final BuildInfo myNewBuildInSelectedChannel;
private final UpdateChannel myUpdatedChannel;
-
- @Nullable
- private final BuildInfo newBuildInSelectedChannel;
-
- @NotNull
- private final Collection<UpdateChannel> myNewChannels;
-
- @NotNull
private final List<String> myAllChannelIds;
-
- @Nullable
- private UpdateChannel myChannelToPropose;
-
- @NotNull
- private final UpdateStrategy.State state;
- @Nullable
- private final Exception error;
-
+ private final UpdateStrategy.State myState;
+ private final Exception myError;
+ private UpdateChannel myChannelToPropose = null;
public CheckForUpdateResult(@Nullable UpdateChannel updated,
@Nullable BuildInfo newBuildInSelectedChannel,
@NotNull List<String> allChannelsIds) {
- this.newBuildInSelectedChannel = newBuildInSelectedChannel;
+ myNewBuildInSelectedChannel = newBuildInSelectedChannel;
myUpdatedChannel = updated;
- myNewChannels = new ArrayList<UpdateChannel>();
- this.myAllChannelIds = allChannelsIds;
- this.state = UpdateStrategy.State.LOADED;
- this.error = null;
+ myAllChannelIds = allChannelsIds;
+ myState = UpdateStrategy.State.LOADED;
+ myError = null;
}
- public CheckForUpdateResult(UpdateStrategy.State state, Exception e) {
- this.newBuildInSelectedChannel = null;
- myNewChannels = Collections.emptyList();
+ public CheckForUpdateResult(@NotNull UpdateStrategy.State state, @Nullable Exception e) {
+ myNewBuildInSelectedChannel = null;
+ myUpdatedChannel = null;
myAllChannelIds = Collections.emptyList();
- this.myChannelToPropose = null;
- this.myUpdatedChannel = null;
- this.state = state;
- this.error = e;
+ myState = state;
+ myError = e;
}
- public CheckForUpdateResult(UpdateStrategy.State state) {
- this(state,null);
+ public CheckForUpdateResult(@NotNull UpdateStrategy.State state) {
+ this(state, null);
}
@Nullable
public BuildInfo getNewBuildInSelectedChannel() {
- return newBuildInSelectedChannel;
+ return myNewBuildInSelectedChannel;
}
- public boolean hasNewBuildInSelectedChannel(){
- return newBuildInSelectedChannel!=null;
- }
-
- public void addNewChannel(UpdateChannel channel) {
- myNewChannels.add(channel);
- }
-
- @NotNull
- public Collection<UpdateChannel> getNewChannels() {
- return myNewChannels;
+ @Nullable
+ public UpdateChannel getUpdatedChannel() {
+ return myUpdatedChannel;
}
@NotNull
@@ -94,6 +66,16 @@
return myAllChannelIds;
}
+ @NotNull
+ public UpdateStrategy.State getState() {
+ return myState;
+ }
+
+ @Nullable
+ public Exception getError() {
+ return myError;
+ }
+
@Nullable
public UpdateChannel getChannelToPropose() {
return myChannelToPropose;
@@ -102,19 +84,4 @@
public void setChannelToPropose(@Nullable UpdateChannel channelToPropose) {
myChannelToPropose = channelToPropose;
}
-
- @NotNull
- public UpdateStrategy.State getState() {
- return state;
- }
-
- @Nullable
- public Exception getError() {
- return error;
- }
-
- @NotNull
- public UpdateChannel getUpdatedChannel() {
- return myUpdatedChannel;
- }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java
index 99739ef..e37e1ad 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/DetectedPluginsPanel.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,6 +16,7 @@
package com.intellij.openapi.updateSettings.impl;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
+import com.intellij.ide.plugins.PluginHeaderPanel;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerMain;
import com.intellij.openapi.extensions.PluginId;
@@ -32,8 +33,8 @@
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
-import java.util.*;
import java.util.List;
+import java.util.Set;
/**
* @author anna
@@ -42,11 +43,13 @@
public class DetectedPluginsPanel extends OrderPanel<PluginDownloader> {
private final List<Listener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- private static JEditorPane myDescriptionPanel = new JEditorPane();
+ private JEditorPane myDescriptionPanel = new JEditorPane();
+ private PluginHeaderPanel myHeader;
public DetectedPluginsPanel() {
super(PluginDownloader.class);
final JTable entryTable = getEntryTable();
+ myHeader = new PluginHeaderPanel(null, entryTable);
entryTable.setTableHeader(null);
entryTable.setDefaultRenderer(PluginDownloader.class, new ColoredTableCellRenderer() {
protected void customizeCellRenderer(final JTable table,
@@ -85,7 +88,7 @@
final PluginDownloader selection = getValueAt(selectedRow);
final IdeaPluginDescriptor descriptor = selection.getDescriptor();
if (descriptor != null) {
- PluginManagerMain.pluginInfoUpdate(descriptor, null, myDescriptionPanel);
+ PluginManagerMain.pluginInfoUpdate(descriptor, null, myDescriptionPanel, myHeader , null);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java
index 28ab727..65cdf28 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -16,105 +16,117 @@
package com.intellij.openapi.updateSettings.impl;
import com.intellij.ide.BrowserUtil;
-import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ide.IdeBundle;
import com.intellij.ui.BrowserHyperlinkListener;
import com.intellij.ui.LicensingFacade;
-import com.intellij.ui.components.JBScrollPane;
-import com.intellij.util.ui.UIUtil;
-import com.intellij.xml.util.XmlStringUtil;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ActionEvent;
+import java.util.List;
/**
* @author yole
*/
-public class NewChannelDialog extends DialogWrapper {
+class NewChannelDialog extends AbstractUpdateDialog {
private final UpdateChannel myChannel;
- private String myInformationText;
+ private final BuildInfo myLatestBuild;
private boolean myShowUpgradeButton = false;
+ private String myLicenseInfo = null;
- public NewChannelDialog(UpdateChannel channel) {
- super(true);
+ public NewChannelDialog(@NotNull UpdateChannel channel) {
+ super(false);
myChannel = channel;
- setTitle("New " + ApplicationNamesInfo.getInstance().getFullProductName() + " Version Available");
- initInfo();
+ myLatestBuild = channel.getLatestBuild();
+ assert myLatestBuild != null;
+
+ LicensingFacade facade = LicensingFacade.getInstance();
+ if (facade != null) {
+ if (!myChannel.getLicensing().equals(UpdateChannel.LICENSING_EAP)) {
+ Boolean paidUpgrade = facade.isPaidUpgrade(myChannel.getMajorVersion(), myLatestBuild.getReleaseDate());
+ if (paidUpgrade == Boolean.TRUE) {
+ myShowUpgradeButton = true;
+ myLicenseInfo = IdeBundle.message("updates.channel.key.needed", myChannel.getEvalDays());
+ }
+ else if (paidUpgrade == Boolean.FALSE) {
+ myLicenseInfo = IdeBundle.message("updates.channel.existing.key");
+ }
+ }
+ else {
+ myLicenseInfo = IdeBundle.message("updates.channel.bundled.key");
+ }
+ }
+
init();
- setOKButtonText("More Info...");
- setOKButtonMnemonic('M');
- setCancelButtonText("Ignore This Update");
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+ return new NewChannelPanel().myPanel;
}
@NotNull
@Override
protected Action[] createActions() {
- Action remindLater = new AbstractAction("Remind Me Later") {
+ List<Action> actions = ContainerUtil.newArrayList(getOKAction());
+
+ if (myShowUpgradeButton) {
+ actions.add(new AbstractAction(IdeBundle.message("updates.buy.online.button")) {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ LicensingFacade facade = LicensingFacade.getInstance();
+ assert facade != null;
+ BrowserUtil.browse(facade.getUpgradeUrl());
+ doCancelAction();
+ }
+ });
+ }
+
+ actions.add(new AbstractAction(IdeBundle.message("updates.remind.later.button")) {
@Override
public void actionPerformed(ActionEvent e) {
UpdateSettings.getInstance().forgetChannelId(myChannel.getId());
doCancelAction();
}
- };
- if (myShowUpgradeButton) {
- Action upgrade = new AbstractAction("Buy Upgrade Online") {
- @Override
- public void actionPerformed(ActionEvent e) {
- LicensingFacade facade = LicensingFacade.getInstance();
- assert facade != null;
- BrowserUtil.launchBrowser(facade.getUpgradeUrl());
- doCancelAction();
- }
- };
- return new Action[] { getOKAction(), upgrade, remindLater, getCancelAction() };
- }
- return new Action[] { getOKAction(), remindLater, getCancelAction() };
+ });
+
+ actions.add(getCancelAction());
+
+ return actions.toArray(new Action[actions.size()]);
}
@Override
- protected JComponent createCenterPanel() {
- JEditorPane pane = new JEditorPane(UIUtil.HTML_MIME, myInformationText);
- pane.addHyperlinkListener(new BrowserHyperlinkListener());
- pane.setEditable(false);
- pane.setBackground(UIUtil.getLabelBackground());
- JBScrollPane scrollPane = new JBScrollPane(pane);
- scrollPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
- return scrollPane;
+ protected String getOkButtonText() {
+ return IdeBundle.message("updates.more.info.button");
}
- private void initInfo() {
- StringBuilder builder = new StringBuilder();
- builder.append("<head>").append(UIUtil.getCssFontDeclaration(UIUtil.getLabelFont())).append("</head><body>");
- builder.append("<b>").append(myChannel.getName()).append("</b><br>");
- builder.append(StringUtil.formatLinks(myChannel.getLatestBuild().getMessage())).append("<br><br>");
- LicensingFacade facade = LicensingFacade.getInstance();
- if (facade != null) {
- if (!myChannel.getLicensing().equals(UpdateChannel.LICENSING_EAP)) {
- Boolean paidUpgrade = facade.isPaidUpgrade(myChannel.getMajorVersion(), myChannel.getLatestBuild().getReleaseDate());
- if (paidUpgrade != null) {
- if (paidUpgrade) {
- builder.append("You can evaluate the new version for ")
- .append(myChannel.getEvalDays())
- .append(" days or buy a license key or an upgrade online.");
- myShowUpgradeButton = true;
- }
- else {
- builder.append("The new version can be used with your existing license key.");
- }
- }
- }
- else {
- builder.append("The new version has an expiration date and does not require a license key.");
- }
- }
- myInformationText = XmlStringUtil.wrapInHtml(builder);
+ @Override
+ protected String getCancelButtonText() {
+ return IdeBundle.message("updates.ignore.update.button");
}
@Override
protected void doOKAction() {
- BrowserUtil.launchBrowser(myChannel.getHomePageUrl());
+ BrowserUtil.browse(myChannel.getHomePageUrl());
super.doOKAction();
}
+
+ private class NewChannelPanel {
+ private JPanel myPanel;
+ private JEditorPane myMessageArea;
+ private JEditorPane myLicenseArea;
+
+ private NewChannelPanel() {
+ String message = IdeBundle.message("updates.channel.name.message", myChannel.getName(), myLatestBuild.getMessage());
+ configureMessageArea(myMessageArea, message, null, new BrowserHyperlinkListener());
+
+ if (myLicenseInfo != null) {
+ configureMessageArea(myLicenseArea, myLicenseInfo, null, new BrowserHyperlinkListener());
+ }
+ else {
+ myLicenseArea.setVisible(false);
+ }
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelForm.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelForm.form
new file mode 100644
index 0000000..ed73b2a
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NewChannelForm.form
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.updateSettings.impl.NewChannelDialog.NewChannelPanel">
+ <grid id="27dc6" binding="myPanel" layout-manager="GridBagLayout">
+ <constraints>
+ <xy x="20" y="20" width="515" height="56"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="1f0d5" class="javax.swing.JEditorPane" binding="myMessageArea">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="50"/>
+ </grid>
+ <gridbag weightx="1.0" weighty="0.0"/>
+ </constraints>
+ <properties>
+ <contentType value="text/html"/>
+ </properties>
+ </component>
+ <component id="63fa1" class="javax.swing.JEditorPane" binding="myLicenseArea">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="50"/>
+ </grid>
+ <gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
+ </constraints>
+ <properties>
+ <contentType value="text/html"/>
+ </properties>
+ </component>
+ <vspacer id="e7d5c">
+ <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"/>
+ <gridbag weightx="0.0" weighty="0.0"/>
+ </constraints>
+ </vspacer>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java
index 54d4c28..fb7f811 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -17,63 +17,44 @@
import com.intellij.CommonBundle;
import com.intellij.ide.IdeBundle;
-import com.intellij.ide.plugins.PluginManagerConfigurable;
import com.intellij.openapi.application.ApplicationInfo;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import java.util.List;
/**
* @author pti
*/
class NoUpdatesDialog extends AbstractUpdateDialog {
- protected NoUpdatesDialog(final boolean canBeParent, final List<PluginDownloader> updatePlugins, boolean enableLink) {
- super(canBeParent, enableLink, updatePlugins);
- setTitle(IdeBundle.message("updates.info.dialog.title"));
+ protected NoUpdatesDialog(boolean enableLink) {
+ super(enableLink);
init();
}
+ @Override
protected JComponent createCenterPanel() {
return new NoUpdatesPanel().myPanel;
}
@Override
protected String getOkButtonText() {
- return myUploadedPlugins == null ? CommonBundle.getCloseButtonText() : IdeBundle.message("update.plugins.update.action");
+ return CommonBundle.getCloseButtonText();
}
@NotNull
+ @Override
protected Action[] createActions() {
- final Action cancelAction = getCancelAction();
- if (myUploadedPlugins != null) {
- return new Action[] {getOKAction(), cancelAction};
- }
- return new Action[] {getOKAction()};
+ return new Action[]{getOKAction()};
}
- @Override
- protected boolean doDownloadAndPrepare() {
- boolean hasSmthToUpdate = super.doDownloadAndPrepare();
- if (hasSmthToUpdate && isShowConfirmation() && PluginManagerConfigurable.showRestartIDEADialog() != 0) {
- hasSmthToUpdate = false;
- }
- return hasSmthToUpdate;
- }
-
private class NoUpdatesPanel {
private JPanel myPanel;
- private JPanel myPluginsPanel;
- private JEditorPane myEditorPane;
- private JLabel myNothingFoundToUpdateLabel;
- private JLabel myPluginsToUpdateLabel;
+ private JLabel myNothingToUpdateLabel;
+ private JEditorPane myMessageArea;
public NoUpdatesPanel() {
- initPluginsPanel(myPanel, myPluginsPanel, myEditorPane);
- myPluginsToUpdateLabel.setVisible(myUploadedPlugins != null);
- myNothingFoundToUpdateLabel.setVisible(myUploadedPlugins == null);
- myNothingFoundToUpdateLabel.setText("You already have the latest version of " +
- ApplicationInfo.getInstance().getVersionName()+ " installed.");
+ myNothingToUpdateLabel.setText(IdeBundle.message("updates.no.updates.message", ApplicationInfo.getInstance().getVersionName()));
+ configureMessageArea(myMessageArea);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form
index ffd4253..2cee5d3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/NoUpdatesPanel.form
@@ -2,62 +2,35 @@
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.updateSettings.impl.NoUpdatesDialog.NoUpdatesPanel">
<grid id="18751" binding="myPanel" layout-manager="GridBagLayout">
<constraints>
- <xy x="63" y="44" width="604" height="510"/>
+ <xy x="89" y="44" width="578" height="56"/>
</constraints>
<properties/>
<border type="none"/>
<children>
- <component id="6b492" class="javax.swing.JLabel" binding="myPluginsToUpdateLabel">
+ <component id="8b5e0" class="javax.swing.JLabel" binding="myNothingToUpdateLabel">
<constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
- <gridbag top="0" left="0" bottom="3" right="0" weightx="1.0" weighty="0.0"/>
- </constraints>
- <properties>
- <maximumSize width="-2147483645" height="30"/>
- <minimumSize width="64" height="30"/>
- <preferredSize width="268" height="30"/>
- <text value="<html><b>Plugins from configured hosts are ready to update.</b><br> Uncheck plugins you do not want to update. </html>"/>
- </properties>
- </component>
- <grid id="3559e" binding="myPluginsPanel" layout-manager="BorderLayout" hgap="0" vgap="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"/>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
<gridbag weightx="1.0" weighty="0.0"/>
</constraints>
<properties>
- <autoscrolls value="false"/>
- <maximumSize width="600" height="400"/>
- <minimumSize width="600" height="400"/>
- <preferredSize width="600" height="400"/>
- </properties>
- <border type="none"/>
- <children/>
- </grid>
- <component id="8b5e0" class="javax.swing.JLabel" binding="myNothingFoundToUpdateLabel">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
- <gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
- </constraints>
- <properties>
- <text value="<html><b>Nothing found to update</b></html>"/>
+ <text value="(nothing to update)"/>
</properties>
</component>
- <component id="bc72e" class="javax.swing.JEditorPane" binding="myEditorPane">
+ <component id="bc72e" class="javax.swing.JEditorPane" binding="myMessageArea">
<constraints>
- <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="1" fill="1" indent="0" use-parent-layout="false">
+ <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="3" indent="0" use-parent-layout="false">
<preferred-size width="250" height="70"/>
</grid>
<gridbag top="10" left="0" bottom="0" right="0" weightx="0.0" weighty="0.0"/>
</constraints>
<properties>
<contentType value="text/html"/>
- <maximumSize width="2147483647" height="25"/>
- <text value="<html> <head> </head> <body> <p style="margin-top: 0"> </p> </body> </html> "/>
+ <text value="<html> <head> </head> <body> <p style="margin-top: 0"> </p> </body> </html> "/>
</properties>
</component>
<vspacer id="bf1d9">
<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="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"/>
<gridbag weightx="0.0" weighty="1.0"/>
</constraints>
</vspacer>
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoDialog.java
new file mode 100644
index 0000000..60a8c8e
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoDialog.java
@@ -0,0 +1,95 @@
+/*
+ * 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.openapi.updateSettings.impl;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.plugins.PluginManagerConfigurable;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.ui.TableUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.List;
+
+/**
+ * @author pti
+ */
+class PluginUpdateInfoDialog extends AbstractUpdateDialog {
+ private final List<PluginDownloader> myUploadedPlugins;
+
+ protected PluginUpdateInfoDialog(@NotNull List<PluginDownloader> updatePlugins, boolean enableLink) {
+ super(enableLink);
+ myUploadedPlugins = updatePlugins;
+ init();
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+ return new PluginUpdateInfoPanel().myPanel;
+ }
+
+ @Override
+ protected String getOkButtonText() {
+ return IdeBundle.message("update.plugins.update.action");
+ }
+
+ @NotNull
+ @Override
+ protected Action[] createActions() {
+ return new Action[]{getOKAction(), getCancelAction()};
+ }
+
+ @Override
+ protected void doOKAction() {
+ if (downloadPlugins() && PluginManagerConfigurable.showRestartIDEADialog() == Messages.YES) {
+ restart();
+ }
+
+ super.doOKAction();
+ }
+
+ private boolean downloadPlugins() {
+ UpdateChecker.saveDisabledToUpdatePlugins();
+ return UpdateChecker.install(myUploadedPlugins);
+ }
+
+ private class PluginUpdateInfoPanel {
+ private JPanel myPanel;
+ private JLabel myPluginsToUpdateLabel;
+ private JPanel myPluginsPanel;
+ private JEditorPane myMessageArea;
+
+ public PluginUpdateInfoPanel() {
+ myPluginsToUpdateLabel.setVisible(true);
+ myPluginsPanel.setVisible(true);
+
+ final DetectedPluginsPanel foundPluginsPanel = new DetectedPluginsPanel();
+ foundPluginsPanel.addAll(myUploadedPlugins);
+ TableUtil.ensureSelectionExists(foundPluginsPanel.getEntryTable());
+ foundPluginsPanel.addStateListener(new DetectedPluginsPanel.Listener() {
+ @Override
+ public void stateChanged() {
+ boolean allSkipped = foundPluginsPanel.getSkippedPlugins().size() == myUploadedPlugins.size();
+ getOKAction().setEnabled(!allSkipped);
+ }
+ });
+ myPluginsPanel.add(foundPluginsPanel, BorderLayout.CENTER);
+
+ configureMessageArea(myMessageArea);
+ }
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form
new file mode 100644
index 0000000..167e5ef
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/PluginUpdateInfoPanel.form
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.updateSettings.impl.PluginUpdateInfoDialog.PluginUpdateInfoPanel">
+ <grid id="18751" binding="myPanel" layout-manager="GridBagLayout">
+ <constraints>
+ <xy x="63" y="44" width="604" height="510"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="6b492" class="javax.swing.JLabel" binding="myPluginsToUpdateLabel">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="1" fill="1" indent="0" use-parent-layout="false"/>
+ <gridbag weightx="1.0" weighty="0.0"/>
+ </constraints>
+ <properties>
+ <preferredSize width="268" height="30"/>
+ <text resource-bundle="messages/IdeBundle" key="updates.plugins.ready.header"/>
+ </properties>
+ </component>
+ <grid id="3559e" binding="myPluginsPanel" layout-manager="BorderLayout" hgap="0" vgap="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"/>
+ <gridbag top="3" left="0" bottom="3" right="0" weightx="1.0" weighty="0.0"/>
+ </constraints>
+ <properties>
+ <autoscrolls value="false"/>
+ <minimumSize width="600" height="400"/>
+ <preferredSize width="600" height="400"/>
+ </properties>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <component id="bc72e" class="javax.swing.JEditorPane" binding="myMessageArea">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="250" height="70"/>
+ </grid>
+ <gridbag weightx="0.0" weighty="0.0"/>
+ </constraints>
+ <properties>
+ <contentType value="text/html"/>
+ </properties>
+ </component>
+ <vspacer id="bf1d9">
+ <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"/>
+ <gridbag weightx="0.0" weighty="1.0"/>
+ </constraints>
+ </vspacer>
+ </children>
+ </grid>
+</form>
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
index acd207d..53d197e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java
@@ -20,9 +20,9 @@
import com.intellij.ide.reporter.ConnectionException;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.*;
-import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.diagnostic.Logger;
@@ -30,148 +30,159 @@
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.project.ProjectManager;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.ActionCallback;
-import com.intellij.openapi.util.BuildNumber;
import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.StandardFileSystems;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.net.HttpConfigurable;
-import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.io.*;
-import java.net.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
import java.util.*;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
- * XML sample:
- * <pre>{@code
- * <idea>
- * <build>456</build>
- * <version>4.5.2</version>
- * <title>New Intellij IDEA Version</title>
- * <message>
- * New version of IntelliJ IDEA is available.
- * Please visit http://www.intellij.com/ for more info.
- * </message>
- * </idea>
- * }</pre>
+ * See XML file by {@link com.intellij.openapi.application.ex.ApplicationInfoEx#getUpdateUrls()} for reference.
*
* @author mike
- * Date: Oct 31, 2002
+ * @since Oct 31, 2002
*/
public final class UpdateChecker {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.updateSettings.impl.UpdateChecker");
- private static Map<String, String> ADDITIONAL_REQUEST_OPTIONS = new HashMap<String, String>();
-
- @NonNls private static final String INSTALLATION_UID = "installation.uid";
-
- private UpdateChecker() {
- }
-
- public static void showConnectionErrorDialog() {
- Messages.showErrorDialog(IdeBundle.message("error.checkforupdates.connection.failed"),
- IdeBundle.message("title.connection.error"));
- }
-
public enum DownloadPatchResult {
SUCCESS, FAILED, CANCELED
}
- private static boolean myVeryFirstOpening = true;
+ private static final NotNullLazyValue<NotificationGroup> GROUP = new NotNullLazyValue<NotificationGroup>() {
+ @NotNull
+ @Override
+ protected NotificationGroup compute() {
+ return new NotificationGroup(IdeBundle.message("update.available.group"), NotificationDisplayType.STICKY_BALLOON, true);
+ }
+ };
- @NonNls
- private static final String DISABLED_UPDATE = "disabled_update.txt";
- private static TreeSet<String> ourDisabledToUpdatePlugins;
+ @NonNls private static final String INSTALLATION_UID = "installation.uid";
+ @NonNls private static final String DISABLED_UPDATE = "disabled_update.txt";
- private static class StringHolder {
+ private static Set<String> ourDisabledToUpdatePlugins;
+ private static Map<String, String> ourAdditionalRequestOptions = new HashMap<String, String>();
+
+ private static class Holder {
private static final String UPDATE_URL = ApplicationInfoEx.getInstanceEx().getUpdateUrls().getCheckingUrl();
private static final String PATCHES_URL = ApplicationInfoEx.getInstanceEx().getUpdateUrls().getPatchesUrl();
- private StringHolder() { }
}
+ private UpdateChecker() { }
+
private static String getUpdateUrl() {
String url = System.getProperty("idea.updates.url");
- if (url != null) {
- return url;
- }
- return StringHolder.UPDATE_URL;
+ return url != null ? url : Holder.UPDATE_URL;
}
private static String getPatchesUrl() {
String url = System.getProperty("idea.patches.url");
- if (url != null) {
- return url;
- }
- return StringHolder.PATCHES_URL;
+ return url != null ? url : Holder.PATCHES_URL;
}
- public static boolean isMyVeryFirstOpening() {
- return myVeryFirstOpening;
- }
-
- public static void setMyVeryFirstOpening(final boolean myVeryFirstProjectOpening) {
- myVeryFirstOpening = myVeryFirstProjectOpening;
- }
-
- public static boolean checkNeeded() {
- final UpdateSettings settings = UpdateSettings.getInstance();
- if (settings == null || getUpdateUrl() == null) return false;
-
- final long timeDelta = System.currentTimeMillis() - settings.LAST_TIME_CHECKED;
- if (Math.abs(timeDelta) < DateFormatUtil.DAY) return false;
-
- return settings.CHECK_NEEDED;
- }
-
+ // for scheduled update checks
public static ActionCallback updateAndShowResult() {
- final ActionCallback result = new ActionCallback();
- final Application app = ApplicationManager.getApplication();
- final UpdateSettings updateSettings = UpdateSettings.getInstance();
- if (!updateSettings.CHECK_NEEDED) {
- result.setDone();
- return result;
- }
- app.executeOnPooledThread(new Runnable() {
+ final ActionCallback callback = new ActionCallback();
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
- final CheckForUpdateResult checkForUpdateResult = checkForUpdates(updateSettings, false);
-
- final List<PluginDownloader> updatedPlugins = updatePlugins(false, null, null);
- app.invokeLater(new Runnable() {
- @Override
- public void run() {
- showUpdateResult(checkForUpdateResult, updatedPlugins, true, true, false);
- result.setDone();
- }
- });
+ doUpdateAndShowResult(null, true, false, null, UpdateSettings.getInstance(), null, callback);
}
});
- return result;
+ return callback;
}
- public static List<PluginDownloader> updatePlugins(final boolean showErrorDialog,
- final @Nullable PluginHostsConfigurable hostsConfigurable,
- @Nullable ProgressIndicator indicator) {
+ // for manual update checks (Help | Check for Updates)
+ public static void updateAndShowResult(final @Nullable Project project,
+ final boolean fromSettings,
+ final @Nullable PluginHostsConfigurable hostsConfigurable,
+ final UpdateSettings settings) {
+ ProgressManager.getInstance().run(new Task.Backgroundable(project, IdeBundle.message("updates.checking.progress"), true) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
+ doUpdateAndShowResult(project, !fromSettings, true, hostsConfigurable, settings, indicator, null);
+ }
+
+ @Override
+ public boolean isConditionalModal() {
+ return fromSettings;
+ }
+
+ @Override
+ public boolean shouldStartInBackground() {
+ return !fromSettings;
+ }
+ });
+ }
+
+ private static void doUpdateAndShowResult(final @Nullable Project project,
+ final boolean enableLink,
+ final boolean showDialog,
+ final @Nullable PluginHostsConfigurable hostsConfigurable,
+ final UpdateSettings updateSettings,
+ final @Nullable ProgressIndicator indicator,
+ final @Nullable ActionCallback callback) {
+ final CheckForUpdateResult result = checkForUpdates(updateSettings);
+
+ if (result.getState() == UpdateStrategy.State.LOADED) {
+ UpdateSettings settings = UpdateSettings.getInstance();
+ settings.saveLastCheckedInfo();
+ settings.setKnownChannelIds(result.getAllChannelsIds());
+ }
+ else if (result.getState() == UpdateStrategy.State.CONNECTION_ERROR) {
+ showErrorMessage(showDialog, project, IdeBundle.message("updates.error.connection.failed"));
+ return;
+ }
+
+ boolean platformUpdate = newChannelReady(result.getChannelToPropose()) || result.getUpdatedChannel() != null;
+ final List<PluginDownloader> updatedPlugins = platformUpdate ? null : updatePlugins(showDialog, project, hostsConfigurable, indicator);
+
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ showUpdateResult(project, result, updatedPlugins, enableLink, showDialog);
+ if (callback != null) {
+ callback.setDone();
+ }
+ }
+ });
+ }
+
+ private static List<PluginDownloader> updatePlugins(boolean showDialog,
+ @Nullable Project project,
+ @Nullable PluginHostsConfigurable hostsConfigurable,
+ @Nullable ProgressIndicator indicator) {
final List<PluginDownloader> downloaded = new ArrayList<PluginDownloader>();
final Set<String> failed = new HashSet<String>();
for (String host : getPluginHosts(hostsConfigurable)) {
@@ -239,13 +250,14 @@
return null;
}
catch (Exception e) {
- showErrorMessage(showErrorDialog, e.getMessage());
+ showErrorMessage(showDialog, project, e.getMessage());
}
}
if (!failed.isEmpty()) {
- showErrorMessage(showErrorDialog, IdeBundle.message("connection.failed.message", StringUtil.join(failed, ",")));
+ showErrorMessage(showDialog, project, IdeBundle.message("updates.error.plugin.description.failed", StringUtil.join(failed, ",")));
}
+
return downloaded.isEmpty() ? null : downloaded;
}
@@ -256,17 +268,18 @@
}
}
- private static void showErrorMessage(boolean showErrorDialog, final String failedMessage) {
- if (showErrorDialog) {
+ private static void showErrorMessage(boolean showDialog, Project project, final String message) {
+ if (showDialog) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
- Messages.showErrorDialog(failedMessage, IdeBundle.message("title.connection.error"));
+ Messages.showErrorDialog(message, IdeBundle.message("updates.error.connection.title"));
}
});
}
else {
- LOG.info(failedMessage);
+ showNotification(project, message, true, null);
+ LOG.warn(message);
}
}
@@ -328,7 +341,7 @@
} else {
description = null;
}
-
+
final List<PluginId> dependsPlugins = new ArrayList<PluginId>();
final List depends = pluginElement.getChildren("depends");
for (Object depend : depends) {
@@ -370,7 +383,8 @@
}
};
if (ApplicationManager.getApplication().isDispatchThread()) {
- ProgressManager.getInstance().runProcessWithProgressSynchronously(updatePluginRunnable, IdeBundle.message("update.uploading.plugin.progress.title"), true, null);
+ String title = IdeBundle.message("update.uploading.plugin.progress.title");
+ ProgressManager.getInstance().runProcessWithProgressSynchronously(updatePluginRunnable, title, true, null);
}
else {
updatePluginRunnable.run();
@@ -399,13 +413,10 @@
}
@NotNull
- public static CheckForUpdateResult doCheckForUpdates(final UpdateSettings settings) {
- ApplicationInfo appInfo = ApplicationInfo.getInstance();
- BuildNumber currentBuild = appInfo.getBuild();
- int majorVersion = Integer.parseInt(appInfo.getMajorVersion());
- final UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl());
- final UpdatesInfo info;
+ private static CheckForUpdateResult checkForUpdates(final UpdateSettings settings) {
+ UpdatesInfo info;
try {
+ UpdatesXmlLoader loader = new UpdatesXmlLoader(getUpdateUrl());
info = loader.loadUpdatesInfo();
if (info == null) {
return new CheckForUpdateResult(UpdateStrategy.State.NOTHING_LOADED);
@@ -415,7 +426,9 @@
return new CheckForUpdateResult(UpdateStrategy.State.CONNECTION_ERROR, e);
}
- UpdateStrategy strategy = new UpdateStrategy(majorVersion, currentBuild, info, settings);
+ ApplicationInfo appInfo = ApplicationInfo.getInstance();
+ int majorVersion = Integer.parseInt(appInfo.getMajorVersion());
+ UpdateStrategy strategy = new UpdateStrategy(majorVersion, appInfo.getBuild(), info, settings);
return strategy.checkForUpdates();
}
@@ -424,134 +437,96 @@
}
public static void addUpdateRequestParameter(@NotNull String name, @NotNull String value) {
- ADDITIONAL_REQUEST_OPTIONS.put(name, value);
+ ourAdditionalRequestOptions.put(name, value);
}
- @NotNull
- public static CheckForUpdateResult checkForUpdates(final UpdateSettings updateSettings,
- final boolean disregardIgnoredBuilds) {
- if (LOG.isDebugEnabled()) {
- LOG.debug("enter: auto checkForUpdates()");
+ @Contract("null -> false")
+ private static boolean newChannelReady(@Nullable UpdateChannel channelToPropose) {
+ return channelToPropose != null && channelToPropose.getLatestBuild() != null;
+ }
+
+ @SuppressWarnings("AssignmentToStaticFieldFromInstanceMethod")
+ private static void showUpdateResult(@Nullable final Project project,
+ final CheckForUpdateResult checkForUpdateResult,
+ final List<PluginDownloader> updatedPlugins,
+ final boolean enableLink,
+ final boolean alwaysShowResults) {
+ final UpdateChannel channelToPropose = checkForUpdateResult.getChannelToPropose();
+ final UpdateChannel updatedChannel = checkForUpdateResult.getUpdatedChannel();
+
+ if (newChannelReady(channelToPropose)) {
+ Runnable runnable = new Runnable() {
+ public void run() {
+ new NewChannelDialog(channelToPropose).show();
+ }
+ };
+
+ if (alwaysShowResults) {
+ runnable.run();
+ }
+ else {
+ String message = IdeBundle.message("updates.new.version.available", ApplicationNamesInfo.getInstance().getFullProductName());
+ showNotification(project, message, false, runnable);
+ }
}
-
- UserUpdateSettings settings = updateSettings;
- if (disregardIgnoredBuilds) {
- settings = new UserUpdateSettings() {
- @NotNull
+ else if (updatedChannel != null) {
+ Runnable runnable = new Runnable() {
@Override
- public List<String> getKnownChannelsIds() {
- return updateSettings.getKnownChannelsIds();
+ public void run() {
+ new UpdateInfoDialog(updatedChannel, enableLink).show();
}
+ };
+ if (alwaysShowResults) {
+ runnable.run();
+ }
+ else {
+ String message = IdeBundle.message("updates.ready.message", ApplicationNamesInfo.getInstance().getFullProductName());
+ showNotification(project, message, false, runnable);
+ }
+ }
+ else if (updatedPlugins != null && !updatedPlugins.isEmpty()) {
+ Runnable runnable = new Runnable() {
@Override
- public List<String> getIgnoredBuildNumbers() {
- return Collections.emptyList();
+ public void run() {
+ new PluginUpdateInfoDialog(updatedPlugins, enableLink).show();
}
+ };
- @Override
- public void setKnownChannelIds(List<String> ids) {
- updateSettings.setKnownChannelIds(ids);
- }
+ if (alwaysShowResults) {
+ runnable.run();
+ }
+ else {
+ String plugins = StringUtil.join(updatedPlugins, new Function<PluginDownloader, String>() {
+ @Override
+ public String fun(PluginDownloader downloader) {
+ return downloader.getPluginName();
+ }
+ }, ", ");
+ String message = IdeBundle.message("updates.plugins.ready.message", updatedPlugins.size(), plugins);
+ showNotification(project, message, false, runnable);
+ }
+ }
+ else if (alwaysShowResults) {
+ new NoUpdatesDialog(enableLink).show();
+ }
+ }
- @NotNull
+ private static void showNotification(@Nullable Project project, String message, boolean error, final @Nullable Runnable runnable) {
+ NotificationListener listener = null;
+ if (runnable != null) {
+ listener = new NotificationListener() {
@Override
- public ChannelStatus getSelectedChannelStatus() {
- return updateSettings.getSelectedChannelStatus();
+ public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
+ notification.expire();
+ runnable.run();
}
};
}
- final CheckForUpdateResult result = doCheckForUpdates(updateSettings);
-
- if (result.getState() == UpdateStrategy.State.LOADED) {
- updateSettings.saveLastCheckedInfo();
- settings.setKnownChannelIds(result.getAllChannelsIds());
- }
-
- return result;
- }
-
- private static boolean ourUpdateInfoDialogShown = false;
-
- public static void showUpdateResult(final CheckForUpdateResult checkForUpdateResult,
- final List<PluginDownloader> updatedPlugins,
- final boolean showConfirmation,
- final boolean enableLink,
- final boolean alwaysShowResults) {
- UpdateChannel channelToPropose = checkForUpdateResult.getChannelToPropose();
- if (channelToPropose != null && channelToPropose.getLatestBuild() != null) {
- NewChannelDialog dialog = new NewChannelDialog(channelToPropose);
- dialog.setModal(alwaysShowResults);
- dialog.show();
- }
- else {
- final boolean showBalloonNotification = !alwaysShowResults && ProjectManager.getInstance().getOpenProjects().length > 0;
- if (checkForUpdateResult.hasNewBuildInSelectedChannel() && !ourUpdateInfoDialogShown) {
- final Runnable showUpdatesDialogRunnable = new Runnable() {
- public void run() {
- UpdateInfoDialog dialog = new UpdateInfoDialog(true, checkForUpdateResult.getUpdatedChannel(), updatedPlugins, enableLink) {
- @Override
- protected void dispose() {
- ourUpdateInfoDialogShown = false;
- super.dispose();
- }
- };
- dialog.setModal(alwaysShowResults);
- ourUpdateInfoDialogShown = true;
- dialog.show();
- }
- };
- if (showBalloonNotification) {
- final String message = ApplicationInfo.getInstance().getVersionName() + " is ready to <a href=\"update\">update</a>";
- showBalloonNotification(showUpdatesDialogRunnable, message);
- }
- else {
- showUpdatesDialogRunnable.run();
- }
- }
- else {
- final Runnable showPluginsUpdateDialogRunnable = new Runnable() {
- public void run() {
- final NoUpdatesDialog dialog = new NoUpdatesDialog(true, updatedPlugins, enableLink) {
- @Override
- protected void dispose() {
- ourUpdateInfoDialogShown = false;
- super.dispose();
- }
- };
- dialog.setShowConfirmation(showConfirmation);
- ourUpdateInfoDialogShown = true;
- dialog.show();
- }
- };
- if (showBalloonNotification && updatedPlugins != null) {
- final String updatedPluginsList = StringUtil.join(updatedPlugins, new Function<PluginDownloader, String>() {
- @Override
- public String fun(PluginDownloader downloader) {
- return downloader.getPluginName();
- }
- }, ", ");
- String message = "You have the latest version of " + ApplicationInfo.getInstance().getVersionName() + " installed.<br> ";
- message += "The following plugin" + (updatedPlugins.size() == 1 ? " is" : "s are") + " ready to <a href=\"update\">update</a>: " + updatedPluginsList;
- showBalloonNotification(showPluginsUpdateDialogRunnable, message);
- }
- else if ((updatedPlugins != null || alwaysShowResults) && !ourUpdateInfoDialogShown) {
- showPluginsUpdateDialogRunnable.run();
- }
- }
- }
- }
-
- private static void showBalloonNotification(final Runnable showUpdatesDialogRunnable, String message) {
- new NotificationGroup(IdeBundle.message("update.available.group"), NotificationDisplayType.STICKY_BALLOON, true)
- .createNotification(IdeBundle.message("updates.info.dialog.title"), message, NotificationType.INFORMATION,
- new NotificationListener() {
- @Override
- public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
- notification.expire();
- showUpdatesDialogRunnable.run();
- }
- }).notify(null);
+ String title = IdeBundle.message("updates.info.dialog.title");
+ NotificationType type = error ? NotificationType.ERROR : NotificationType.INFORMATION;
+ Notifications.Bus.notify(GROUP.getValue().createNotification(title, message, type, listener), project);
}
public static String prepareUpdateCheckArgs() {
@@ -565,14 +540,14 @@
StringBuilder args = new StringBuilder();
try {
- for (String name : ADDITIONAL_REQUEST_OPTIONS.keySet()) {
+ for (String name : ourAdditionalRequestOptions.keySet()) {
if (args.length() > 0) {
args.append('&');
}
args.append(URLEncoder.encode(name, "UTF-8"));
- String value = ADDITIONAL_REQUEST_OPTIONS.get(name);
+ String value = ourAdditionalRequestOptions.get(name);
if (!StringUtil.isEmpty(value)) {
args.append('=').append(URLEncoder.encode(value, "UTF-8"));
}
@@ -586,9 +561,6 @@
}
private static InputStream loadVersionInfo(final String url) throws Exception {
- if (LOG.isDebugEnabled()) {
- LOG.debug("enter: loadVersionInfo(UPDATE_URL='" + url + "' )");
- }
final InputStream[] inputStreams = new InputStream[]{null};
final Exception[] exception = new Exception[]{null};
Future<?> downloadThreadFuture = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@@ -610,9 +582,7 @@
try {
downloadThreadFuture.get(5, TimeUnit.SECONDS);
}
- catch (TimeoutException e) {
- // ignore
- }
+ catch (TimeoutException ignored) { }
if (!downloadThreadFuture.isDone()) {
downloadThreadFuture.cancel(true);
@@ -652,6 +622,7 @@
if (permanentIdFile.exists()) {
return FileUtil.loadFile(permanentIdFile).trim();
}
+
String uuid;
if (propertiesComponent.isValueSet(INSTALLATION_UID)) {
uuid = propertiesComponent.getValue(INSTALLATION_UID);
@@ -662,11 +633,10 @@
FileUtil.writeToFile(permanentIdFile, uuid);
return uuid;
}
- catch (IOException e) {
- // ignore
- }
+ catch (IOException ignored) { }
}
}
+
return null;
}
@@ -674,10 +644,9 @@
try {
return UUID.randomUUID().toString();
}
- catch (Exception ignored) {
- }
- catch (InternalError ignored) {
- }
+ catch (Exception ignored) { }
+ catch (InternalError ignored) { }
+
return "";
}
@@ -700,7 +669,6 @@
return installed;
}
-
public static DownloadPatchResult downloadAndInstallPatch(final BuildInfo newVersion) {
final DownloadPatchResult[] result = new DownloadPatchResult[]{DownloadPatchResult.CANCELED};
@@ -733,7 +701,7 @@
String fromBuildNumber = patch.getFromBuild().asStringWithoutProductCode();
String toBuildNumber = newVersion.getNumber().asStringWithoutProductCode();
- String bundledJdk = "jdk-bundled".equals(System.getProperty("idea.java.redist")) ? "-jdk-bundled":"";
+ String bundledJdk = "jdk-bundled".equals(System.getProperty("idea.java.redist")) ? "-jdk-bundled" : "";
String fileName = productCode + "-" + fromBuildNumber + "-" + toBuildNumber + "-patch" + bundledJdk + osSuffix + ".jar";
@@ -748,7 +716,7 @@
InputStream in = UrlConnectionUtil.getConnectionInputStreamWithException(connection, i);
try {
int total = connection.getContentLength();
- i.setIndeterminate(total > 0);
+ i.setIndeterminate(total <= 0);
byte[] buffer = new byte[10 * 1024];
int count;
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
index e56793f..a53c2b3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateCheckerComponent.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -15,9 +15,11 @@
*/
package com.intellij.openapi.updateSettings.impl;
+import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.components.ApplicationComponent;
import com.intellij.openapi.updateSettings.impl.pluginsAdvertisement.PluginsAdvertiser;
import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Alarm;
import com.intellij.util.text.DateFormatUtil;
import org.jetbrains.annotations.NotNull;
@@ -27,6 +29,7 @@
*/
public class UpdateCheckerComponent implements ApplicationComponent {
private static final long CHECK_INTERVAL = DateFormatUtil.DAY;
+
private final Alarm myCheckForUpdatesAlarm = new Alarm(Alarm.ThreadToUse.SHARED_THREAD);
private final Runnable myCheckRunnable = new Runnable() {
@Override
@@ -34,22 +37,37 @@
UpdateChecker.updateAndShowResult().doWhenDone(new Runnable() {
@Override
public void run() {
- queueNextUpdateCheck(CHECK_INTERVAL);
+ queueNextCheck(CHECK_INTERVAL);
}
});
}
};
+ private final UpdateSettings mySettings;
+
+ public UpdateCheckerComponent(@NotNull UpdateSettings settings) {
+ mySettings = settings;
+ }
@Override
public void initComponent() {
PluginsAdvertiser.ensureDeleted();
- final long interval = UpdateSettings.getInstance().LAST_TIME_CHECKED + CHECK_INTERVAL - System.currentTimeMillis();
- queueNextUpdateCheck(UpdateChecker.checkNeeded()
- ? CHECK_INTERVAL
- : Math.max(interval, DateFormatUtil.MINUTE));
+
+ if (!mySettings.CHECK_NEEDED) {
+ return;
+ }
+
+ String currentBuild = ApplicationInfo.getInstance().getBuild().asString();
+ long timeToNextCheck = mySettings.LAST_TIME_CHECKED + CHECK_INTERVAL - System.currentTimeMillis();
+
+ if (StringUtil.compareVersionNumbers(mySettings.LAST_BUILD_CHECKED, currentBuild) < 0 || timeToNextCheck <= 0) {
+ myCheckRunnable.run();
+ }
+ else {
+ queueNextCheck(timeToNextCheck);
+ }
}
- private void queueNextUpdateCheck(long interval) {
+ private void queueNextCheck(long interval) {
myCheckForUpdatesAlarm.addRequest(myCheckRunnable, interval);
}
@@ -63,4 +81,12 @@
public String getComponentName() {
return "UpdateCheckerComponent";
}
+
+ public void queueNextCheck() {
+ queueNextCheck(CHECK_INTERVAL);
+ }
+
+ public void cancelChecks() {
+ myCheckForUpdatesAlarm.cancelAllRequests();
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java
index 5c30639..6e56a21 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -20,16 +20,16 @@
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.application.PathManager;
import com.intellij.ui.BrowserHyperlinkListener;
-import com.intellij.ui.components.JBScrollPane;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.ui.JBColor;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ActionEvent;
-import java.util.ArrayList;
+import java.io.File;
import java.util.List;
/**
@@ -38,190 +38,155 @@
class UpdateInfoDialog extends AbstractUpdateDialog {
private final UpdateChannel myUpdatedChannel;
private final BuildInfo myLatestBuild;
+ private final PatchInfo myPatch;
+ private final boolean myWriteProtected;
- protected UpdateInfoDialog(final boolean canBeParent,
- UpdateChannel channel,
- final List<PluginDownloader> uploadedPlugins,
- final boolean enableLink) {
- super(canBeParent, enableLink, uploadedPlugins);
+ protected UpdateInfoDialog(@NotNull UpdateChannel channel, boolean enableLink) {
+ super(enableLink);
myUpdatedChannel = channel;
myLatestBuild = channel.getLatestBuild();
- setTitle(IdeBundle.message("updates.info.dialog.title"));
+ myPatch = myLatestBuild != null ? myLatestBuild.findPatchForCurrentBuild() : null;
+ myWriteProtected = myPatch != null && !new File(PathManager.getHomePath()).canWrite();
getCancelAction().putValue(DEFAULT_ACTION, Boolean.TRUE);
init();
}
+ @Override
+ protected JComponent createCenterPanel() {
+ return new UpdateInfoPanel().myPanel;
+ }
+
@NotNull
@Override
protected Action[] createActions() {
- List<Action> actions = new ArrayList<Action>();
- actions.add(getOKAction());
+ List<Action> actions = ContainerUtil.newArrayList();
- final List<ButtonInfo> buttons = myLatestBuild.getButtons();
+ if (myPatch != null) {
+ boolean canRestart = ApplicationManager.getApplication().isRestartCapable();
+ String button = IdeBundle.message(canRestart ? "updates.download.and.restart.button" : "updates.download.and.install.button");
+ actions.add(new AbstractAction(button) {
+ {
+ setEnabled(!myWriteProtected);
+ }
- if (hasPatch()) {
- if (buttons.isEmpty()) {
- actions.add(new AbstractAction(IdeBundle.message("updates.more.info.button")) {
- public void actionPerformed(ActionEvent e) {
- openDownloadPage();
- }
- });
- }
- else {
- for (ButtonInfo info : buttons) {
- if (!info.isDownload()) {
- actions.add(new ButtonAction(info));
- }
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ downloadPatch();
+ }
+ });
+ }
+
+ List<ButtonInfo> buttons = myLatestBuild.getButtons();
+ if (buttons.isEmpty()) {
+ actions.add(new AbstractAction(IdeBundle.message("updates.more.info.button")) {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ openDownloadPage();
+ }
+ });
+ }
+ else {
+ for (ButtonInfo info : buttons) {
+ if (!info.isDownload() || myPatch == null) {
+ actions.add(new ButtonAction(info));
}
}
}
- else {
- // the first button replaces the OK action
- for (int i = 1; i < buttons.size(); i++) {
- actions.add(new ButtonAction(buttons.get(i)));
+
+ actions.add(new AbstractAction(IdeBundle.message("updates.ignore.update.button")) {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String build = myLatestBuild.getNumber().asStringWithoutProductCode();
+ UpdateSettings.getInstance().getIgnoredBuildNumbers().add(build);
+ doCancelAction();
}
- }
+ });
+
actions.add(getCancelAction());
- actions.add(new AbstractAction("&Ignore This Update") {
- @Override
- public void actionPerformed(ActionEvent e) {
- UpdateSettings.getInstance().getIgnoredBuildNumbers().add(myLatestBuild.getNumber().asStringWithoutProductCode());
- doCancelAction();
- }
- });
- return actions.toArray(new Action[buttons.size()]);
- }
-
- private void openDownloadPage() {
- BrowserUtil.launchBrowser(myUpdatedChannel.getHomePageUrl());
- }
-
- protected String getOkButtonText() {
- if (hasPatch()) {
- return ApplicationManager.getApplication().isRestartCapable()
- ? IdeBundle.message("updates.download.and.install.patch.button.restart")
- : IdeBundle.message("updates.download.and.install.patch.button");
- }
- else if (myLatestBuild.getButtons().size() > 0) {
- return myLatestBuild.getButtons().get(0).getName();
- }
- else {
- return IdeBundle.message("updates.more.info.button");
- }
+ return actions.toArray(new Action[actions.size()]);
}
@Override
protected String getCancelButtonText() {
- return "&Remind Me Later";
+ return IdeBundle.message("updates.remind.later.button");
}
- protected JComponent createCenterPanel() {
- UpdateInfoPanel updateInfoPanel = new UpdateInfoPanel();
- return updateInfoPanel.myPanel;
- }
-
- @Override
- protected void doOKAction() {
- if (hasPatch()) {
- super.doOKAction();
- return;
+ private void downloadPatch() {
+ UpdateChecker.DownloadPatchResult result = UpdateChecker.downloadAndInstallPatch(myLatestBuild);
+ if (result == UpdateChecker.DownloadPatchResult.SUCCESS) {
+ restart();
}
-
- if (myLatestBuild.getButtons().size() > 0) {
- BrowserUtil.launchBrowser(myLatestBuild.getButtons().get(0).getUrl());
- }
- else {
+ else if (result == UpdateChecker.DownloadPatchResult.FAILED) {
openDownloadPage();
}
- super.doOKAction();
}
- @Override
- protected boolean doDownloadAndPrepare() {
- if (hasPatch()) {
- switch (UpdateChecker.downloadAndInstallPatch(myLatestBuild)) {
- case CANCELED:
- return false;
- case FAILED:
- openDownloadPage();
- return false;
- case SUCCESS:
- super.doDownloadAndPrepare();
- return true;
- }
- }
- return super.doDownloadAndPrepare();
+ private void openDownloadPage() {
+ BrowserUtil.browse(myUpdatedChannel.getHomePageUrl());
}
- private boolean hasPatch() {
- return myLatestBuild.findPatchForCurrentBuild() != null;
- }
-
private static class ButtonAction extends AbstractAction {
- private ButtonInfo myInfo;
+ private final String myUrl;
private ButtonAction(ButtonInfo info) {
super(info.getName());
- myInfo = info;
+ myUrl = info.getUrl();
}
@Override
public void actionPerformed(ActionEvent e) {
- BrowserUtil.launchBrowser(myInfo.getUrl());
+ BrowserUtil.browse(myUrl);
}
}
private class UpdateInfoPanel {
private JPanel myPanel;
- private JLabel myBuildNumber;
- private JLabel myVersionNumber;
- private JLabel myNewVersionNumber;
- private JLabel myNewBuildNumber;
- private JLabel myPatchAvailableLabel;
- private JLabel myPatchSizeLabel;
- private JEditorPane myUpdateMessageLabel;
- private JBScrollPane myScrollPane;
- private JLabel myManualCheckLabel;
+ private JEditorPane myUpdateMessage;
+ private JBLabel myCurrentVersion;
+ private JBLabel myNewVersion;
+ private JBLabel myPatchLabel;
+ private JBLabel myPatchInfo;
+ private JEditorPane myMessageArea;
public UpdateInfoPanel() {
ApplicationInfo appInfo = ApplicationInfo.getInstance();
- myBuildNumber.setText(appInfo.getBuild().asStringWithoutProductCode() + ")");
- final String version = appInfo.getFullVersion();
+ ApplicationNamesInfo appNames = ApplicationNamesInfo.getInstance();
- myVersionNumber.setText(version);
- myNewBuildNumber.setText(myLatestBuild.getNumber().asStringWithoutProductCode() + ")");
- myNewVersionNumber.setText(myLatestBuild.getVersion());
- myUpdateMessageLabel.setBackground(UIUtil.getLabelBackground());
- myScrollPane.setBackground(UIUtil.getLabelBackground());
- myScrollPane.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
- if (myLatestBuild.getMessage() != null) {
- StringBuilder builder = new StringBuilder();
- builder.append("<html><head>").append(UIUtil.getCssFontDeclaration(UIUtil.getLabelFont())).append("</head><body>")
- .append(StringUtil.formatLinks(myLatestBuild.getMessage()))
- .append("</body></html>");
- myUpdateMessageLabel.setText(builder.toString());
- myUpdateMessageLabel.addHyperlinkListener(new BrowserHyperlinkListener());
+ String message = myLatestBuild.getMessage();
+ if (message == null) {
+ message = IdeBundle.message("updates.new.version.available", appNames.getFullProductName());
+ }
+ configureMessageArea(myUpdateMessage, message, null, new BrowserHyperlinkListener());
+
+ myCurrentVersion.setText(formatVersion(appInfo.getFullVersion(), appInfo.getBuild().asStringWithoutProductCode()));
+ myNewVersion.setText(formatVersion(myLatestBuild.getVersion(), myLatestBuild.getNumber().asStringWithoutProductCode()));
+
+ if (myPatch != null) {
+ myPatchInfo.setText(myPatch.getSize() + " MB");
}
else {
- myUpdateMessageLabel.setVisible(false);
+ myPatchLabel.setVisible(false);
+ myPatchInfo.setVisible(false);
}
- PatchInfo patch = myLatestBuild.findPatchForCurrentBuild();
- if (patch == null) {
- myPatchAvailableLabel.setVisible(false);
- myPatchSizeLabel.setVisible(false);
+ if (myWriteProtected) {
+ message = IdeBundle.message("updates.write.protected", appNames.getProductName(), PathManager.getHomePath());
+ configureMessageArea(myMessageArea, message, JBColor.RED, null);
}
else {
- myPatchSizeLabel.setText(patch.getSize() + "MB");
+ configureMessageArea(myMessageArea);
}
+ }
- if (SystemInfo.isMac) {
- myManualCheckLabel.setText("<html><br>To check for new updates manually, use the <b>" +
- ApplicationNamesInfo.getInstance().getProductName() + " | Check for Updates</b> command.</html>");
- }
+ private String formatVersion(String version, String build) {
+ String[] parts = version.split("\\.", 3);
+ String major = parts.length > 0 ? parts[0] : "0";
+ String minor = parts.length > 1 ? parts[1] : "0";
+ String patch = parts.length > 2 ? parts[2] : "0";
+ version = major + '.' + minor + '.' + patch;
- LabelTextReplacingUtil.replaceText(myPanel);
+ return IdeBundle.message("updates.version.info", version, build);
}
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoPanel.form b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoPanel.form
index 11fb6fc..27b7eb2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoPanel.form
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateInfoPanel.form
@@ -1,154 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.openapi.updateSettings.impl.UpdateInfoDialog.UpdateInfoPanel">
- <grid id="18751" binding="myPanel" layout-manager="GridBagLayout">
+ <grid id="27dc6" binding="myPanel" layout-manager="GridBagLayout">
<constraints>
- <xy x="122" y="198" width="478" height="184"/>
+ <xy x="20" y="20" width="500" height="140"/>
</constraints>
<properties/>
- <border type="etched"/>
+ <border type="none"/>
<children>
- <component id="bc6f7" class="javax.swing.JLabel">
+ <component id="f7184" class="javax.swing.JEditorPane" binding="myUpdateMessage">
<constraints>
- <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- <gridbag weightx="0.0" weighty="0.0"/>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="2" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="50"/>
+ </grid>
+ <gridbag weightx="1.0" weighty="0.0"/>
</constraints>
<properties>
- <text value=""/>
+ <contentType value="text/html"/>
</properties>
</component>
- <grid id="3b4cd" layout-manager="GridLayoutManager" row-count="3" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
- <margin top="0" left="0" bottom="0" right="0"/>
+ <grid id="d6625" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="10" left="5" bottom="10" right="5"/>
<constraints>
- <grid row="3" column="1" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ <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"/>
<gridbag weightx="1.0" weighty="0.0"/>
</constraints>
<properties/>
<border type="none"/>
<children>
- <component id="bd9c5" class="javax.swing.JLabel" binding="myVersionNumber">
- <constraints>
- <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="4.5.4"/>
- </properties>
- </component>
- <component id="6af7e" class="javax.swing.JLabel">
- <constraints>
- <grid row="0" column="2" 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 resource-bundle="messages/IdeBundle" key="updates.build.number"/>
- </properties>
- </component>
- <component id="b6709" class="javax.swing.JLabel" binding="myBuildNumber">
- <constraints>
- <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="3352)"/>
- </properties>
- </component>
- <component id="36fbb" class="javax.swing.JLabel">
+ <component id="6ab75" 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>
- <text resource-bundle="messages/IdeBundle" key="updates.current.idea.version"/>
+ <text resource-bundle="messages/IdeBundle" key="updates.current.version"/>
</properties>
</component>
- <component id="3a2f5" class="javax.swing.JLabel" binding="myNewBuildNumber">
+ <component id="d276e" class="com.intellij.ui.components.JBLabel" binding="myCurrentVersion">
<constraints>
- <grid row="1" column="3" 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="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
- <text value="3389)"/>
+ <text value="X.Y (build XXX.YYY)"/>
</properties>
</component>
- <component id="7bf1c" class="javax.swing.JLabel">
- <constraints>
- <grid row="1" column="2" 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 resource-bundle="messages/IdeBundle" key="updates.build.number"/>
- </properties>
- </component>
- <component id="340b7" class="javax.swing.JLabel">
+ <component id="5a935" 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 resource-bundle="messages/IdeBundle" key="updates.available.idea.version"/>
+ <text resource-bundle="messages/IdeBundle" key="updates.available.version"/>
</properties>
</component>
- <component id="5797d" class="javax.swing.JLabel" binding="myNewVersionNumber">
+ <component id="ef80e" class="com.intellij.ui.components.JBLabel" binding="myNewVersion">
<constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="1" 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="4.5.5"/>
+ <text value="X.Y (build XXX.YYY)"/>
</properties>
</component>
- <component id="56242" class="javax.swing.JLabel" binding="myPatchAvailableLabel">
+ <component id="f145c" class="com.intellij.ui.components.JBLabel" binding="myPatchLabel">
<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="<html><b>Patch is available to install.</b> Total size is:</html>"/>
+ <text resource-bundle="messages/IdeBundle" key="updates.patch.label"/>
</properties>
</component>
- <component id="59b69" class="javax.swing.JLabel" binding="myPatchSizeLabel">
+ <component id="b16ba" class="com.intellij.ui.components.JBLabel" binding="myPatchInfo">
<constraints>
- <grid row="2" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="2" 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="0 mb"/>
+ <text value="XX MB"/>
</properties>
</component>
+ <hspacer id="2c1a8">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </hspacer>
</children>
</grid>
- <component id="969e3" class="javax.swing.JLabel" binding="myManualCheckLabel">
+ <component id="63ccb" class="javax.swing.JEditorPane" binding="myMessageArea">
<constraints>
- <grid row="5" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- <gridbag weightx="1.0" weighty="0.0"/>
+ <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false">
+ <preferred-size width="150" height="50"/>
+ </grid>
+ <gridbag weightx="0.0" weighty="0.0"/>
</constraints>
<properties>
- <text resource-bundle="messages/IdeBundle" key="updates.check.manually.label"/>
+ <contentType value="text/html"/>
</properties>
</component>
- <component id="f06b4" class="javax.swing.JLabel">
+ <vspacer id="c963e">
<constraints>
- <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- <gridbag weightx="1.0" weighty="0.0"/>
- </constraints>
- <properties>
- <text resource-bundle="messages/IdeBundle" key="updates.new.version.available"/>
- </properties>
- </component>
- <vspacer id="59641">
- <constraints>
- <grid row="6" column="1" 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="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<gridbag weightx="0.0" weighty="0.0"/>
</constraints>
</vspacer>
- <scrollpane id="aeca2" class="com.intellij.ui.components.JBScrollPane" binding="myScrollPane">
- <constraints>
- <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- <gridbag weightx="0.0" weighty="0.0"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="54ce5" class="javax.swing.JEditorPane" binding="myUpdateMessageLabel">
- <constraints/>
- <properties>
- <contentType value="text/html"/>
- <editable value="false"/>
- <text value="<html> <head> </head> <body> <p style="margin-top: 0"> </p> </body> </html> "/>
- </properties>
- </component>
- </children>
- </scrollpane>
</children>
</grid>
</form>
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java
index a7543ae..b042f9f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateSettingsConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
import com.intellij.ide.IdeBundle;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.application.ApplicationInfo;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.options.BaseConfigurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
@@ -58,7 +59,20 @@
public void apply() throws ConfigurationException {
UpdateSettings settings = UpdateSettings.getInstance();
+
+ boolean wasEnabled = settings.CHECK_NEEDED;
settings.CHECK_NEEDED = myUpdatesSettingsPanel.myCbCheckForUpdates.isSelected();
+ if (wasEnabled != settings.CHECK_NEEDED) {
+ UpdateCheckerComponent checker = ApplicationManager.getApplication().getComponent(UpdateCheckerComponent.class);
+ if (checker != null) {
+ if (wasEnabled) {
+ checker.cancelChecks();
+ }
+ else {
+ checker.queueNextCheck();
+ }
+ }
+ }
settings.UPDATE_CHANNEL_TYPE = myUpdatesSettingsPanel.getSelectedChannelType().getCode();
}
@@ -83,18 +97,15 @@
}
private class UpdatesSettingsPanel {
-
private JPanel myPanel;
private JButton myBtnCheckNow;
private JCheckBox myCbCheckForUpdates;
private JLabel myBuildNumber;
private JLabel myVersionNumber;
private JLabel myLastCheckedDate;
-
private JComboBox myUpdateChannelsBox;
public UpdatesSettingsPanel() {
-
final ApplicationInfo appInfo = ApplicationInfo.getInstance();
final String majorVersion = appInfo.getMajorVersion();
String versionNumber = "";
@@ -116,7 +127,7 @@
UpdateSettings settings = new UpdateSettings();
settings.loadState(UpdateSettings.getInstance().getState());
settings.UPDATE_CHANNEL_TYPE = getSelectedChannelType().getCode();
- CheckForUpdateAction.actionPerformed(project, false, null, settings); //todo load configured hosts on the fly
+ UpdateChecker.updateAndShowResult(project, true, null, settings); //todo load configured hosts on the fly
updateLastCheckedLabel();
}
});
@@ -129,9 +140,8 @@
}
private void updateLastCheckedLabel() {
- final long lastChecked = UpdateSettings.getInstance().LAST_TIME_CHECKED;
- myLastCheckedDate
- .setText(lastChecked == 0 ? IdeBundle.message("updates.last.check.never") : DateFormatUtil.formatPrettyDateTime(lastChecked));
+ long time = UpdateSettings.getInstance().LAST_TIME_CHECKED;
+ myLastCheckedDate.setText(time == 0 ? IdeBundle.message("updates.last.check.never") : DateFormatUtil.formatPrettyDateTime(time));
}
public ChannelStatus getSelectedChannelType() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateStrategy.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateStrategy.java
index 770d713..e29c2c6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateStrategy.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateStrategy.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -15,7 +15,6 @@
*/
package com.intellij.openapi.updateSettings.impl;
-
import com.intellij.openapi.util.BuildNumber;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +22,7 @@
import java.util.List;
public class UpdateStrategy {
- public static enum State {LOADED, CONNECTION_ERROR, NOTHING_LOADED}
+ public enum State {LOADED, CONNECTION_ERROR, NOTHING_LOADED}
private UserUpdateSettings myUpdateSettings;
private int myMajorVersion;
@@ -32,8 +31,9 @@
private ChannelStatus myChannelStatus;
private UpdatesInfo myUpdatesInfo;
-
- public UpdateStrategy(int majorVersion, @NotNull BuildNumber currentBuild, @NotNull UpdatesInfo updatesInfo,
+ public UpdateStrategy(int majorVersion,
+ @NotNull BuildNumber currentBuild,
+ @NotNull UpdatesInfo updatesInfo,
@NotNull UserUpdateSettings updateSettings) {
myMajorVersion = majorVersion;
myUpdatesInfo = updatesInfo;
@@ -68,7 +68,6 @@
channel.getMajorVersion() >= myMajorVersion &&
channel.getStatus().compareTo(myChannelStatus) >= 0 &&
hasNewVersion(channel)) {
- result.addNewChannel(channel);
if (channelToPropose == null || isBetter(channelToPropose, channel)) {
channelToPropose = channel;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java
index 31141fe..18c5f76 100644
--- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/pluginsAdvertisement/PluginAdvertiserEditorNotificationProvider.java
@@ -117,7 +117,7 @@
try {
myAllPlugins = RepositoryHelper.loadPluginsFromRepository(indicator);
for (IdeaPluginDescriptor loadedPlugin : myAllPlugins) {
- if (plugins.contains(new PluginsAdvertiser.Plugin(loadedPlugin.getPluginId(), false))) {
+ if (plugins.contains(new PluginsAdvertiser.Plugin(loadedPlugin.getPluginId(), null, false))) {
myPlugins.add(PluginDownloader.createDownloader(loadedPlugin));
}
}
@@ -138,7 +138,7 @@
});
}
});
- } else if (PluginsAdvertiser.hasBundledPluginToInstall(plugins)){
+ } else if (PluginsAdvertiser.hasBundledPluginToInstall(plugins) != null){
if (PropertiesComponent.getInstance().isTrueValue(PluginsAdvertiser.IGNORE_ULTIMATE_EDITION)) {
return null;
}
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 b45e3ae..034fd0e 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
@@ -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,10 +23,7 @@
import com.intellij.ide.plugins.*;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.notification.*;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationInfo;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileTypes.FileTypeFactory;
@@ -89,8 +86,10 @@
for (JsonElement jsonElement : jsonRootElement.getAsJsonArray()) {
final JsonObject jsonObject = jsonElement.getAsJsonObject();
final JsonElement pluginId = jsonObject.get("pluginId");
+ final JsonElement pluginName = jsonObject.get("pluginName");
final JsonElement bundled = jsonObject.get("bundled");
- result.add(new Plugin(PluginId.getId(StringUtil.unquoteString(pluginId.toString())),
+ result.add(new Plugin(PluginId.getId(StringUtil.unquoteString(pluginId.toString())),
+ pluginName != null ? StringUtil.unquoteString(pluginName.toString()) : null,
Boolean.parseBoolean(StringUtil.unquoteString(bundled.toString()))));
}
return result;
@@ -132,7 +131,7 @@
final IdeaPluginDescriptor loadedPlugin = PluginManager.getPlugin(PluginId.getId(pluginId));
if (loadedPlugin != null && loadedPlugin.isEnabled()) continue;
- if (loadedPlugin != null && fromServerPluginDescription != null &&
+ if (loadedPlugin != null && fromServerPluginDescription != null &&
StringUtil.compareVersionNumbers(loadedPlugin.getVersion(), fromServerPluginDescription.getVersion()) >= 0) continue;
final JsonElement ext = jsonObject.get("implementationName");
@@ -142,7 +141,8 @@
pluginIds = new HashSet<Plugin>();
result.put(extension, pluginIds);
}
- pluginIds.add(new Plugin(PluginId.getId(pluginId), isBundled));
+ final JsonElement pluginNameElement = jsonObject.get("pluginName");
+ pluginIds.add(new Plugin(PluginId.getId(pluginId), pluginNameElement != null ? StringUtil.unquoteString(pluginNameElement.toString()) : null, isBundled));
}
saveExtensions(result);
return result;
@@ -188,7 +188,7 @@
}
public static void openDownloadPage() {
- BrowserUtil.open(ApplicationInfo.getInstance().getCompanyURL());
+ BrowserUtil.open(ApplicationInfo.getInstance().getCompanyURL());
}
static void enablePlugins(Project project, final Collection<IdeaPluginDescriptor> disabledPlugins) {
@@ -215,14 +215,15 @@
return null;
}
- static boolean hasBundledPluginToInstall(Collection<Plugin> plugins) {
- if (PlatformUtils.isIdea()) return false;
+ static List<String> hasBundledPluginToInstall(Collection<Plugin> plugins) {
+ if (PlatformUtils.isIdeaUltimate()) return null;
+ final List<String> bundled = new ArrayList<String>();
for (Plugin plugin : plugins) {
if (plugin.myBundled && PluginManager.getPlugin(PluginId.getId(plugin.myPluginId)) == null) {
- return true;
+ bundled.add(plugin.myPluginName != null ? plugin.myPluginName : plugin.myPluginId);
}
}
- return false;
+ return bundled.isEmpty() ? null : bundled;
}
@Override
@@ -236,32 +237,30 @@
public void run() {
final Application application = ApplicationManager.getApplication();
if (application.isUnitTestMode() || application.isHeadlessEnvironment()) return;
- ProgressManager.getInstance().run(new Task.Backgroundable(project, "Search for non-bundled plugins in plugin repository...") {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
private final Set<PluginDownloader> myPlugins = new HashSet<PluginDownloader>();
private List<IdeaPluginDescriptor> myAllPlugins;
private Map<Plugin, IdeaPluginDescriptor> myDisabledPlugins = new HashMap<Plugin, IdeaPluginDescriptor>();
- private boolean myBundledPlugins = false;
+ private List<String> myBundledPlugin;
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
+ public void run() {
try {
- myAllPlugins = RepositoryHelper.loadPluginsFromRepository(indicator);
+ myAllPlugins = RepositoryHelper.loadPluginsFromRepository(null);
+ if (project.isDisposed()) return;
if (extensions == null) {
loadSupportedExtensions(myAllPlugins);
EditorNotifications.getInstance(project).updateAllNotifications();
}
- int idx = 0;
final Map<String, Plugin> ids = new HashMap<String, Plugin>();
for (UnknownFeature feature : unknownFeatures) {
- indicator.setText("Searching for plugin supporting \'" + feature.getImplementationName() + "\'");
+ ProgressManager.checkCanceled();
final List<Plugin> pluginId = retrieve(feature);
if (pluginId != null) {
for (Plugin plugin : pluginId) {
ids.put(plugin.myPluginId, plugin);
}
}
- indicator.setFraction(((double)idx++) / unknownFeatures.size());
}
final List<String> disabledPlugins = PluginManagerCore.getDisabledPlugins();
@@ -273,10 +272,10 @@
if (pluginDescriptor != null) {
myDisabledPlugins.put(plugin, pluginDescriptor);
}
- }
+ }
}
- myBundledPlugins = hasBundledPluginToInstall(ids.values());
+ myBundledPlugin = hasBundledPluginToInstall(ids.values());
for (IdeaPluginDescriptor loadedPlugin : myAllPlugins) {
final PluginId pluginId = loadedPlugin.getPluginId();
@@ -284,14 +283,21 @@
myPlugins.add(PluginDownloader.createDownloader(loadedPlugin));
}
}
+
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ onSuccess();
+ }
+ }, ModalityState.NON_MODAL);
+
}
catch (Exception e) {
LOG.info(e);
}
}
- @Override
- public void onSuccess() {
+ private void onSuccess() {
String message = null;
if (!myPlugins.isEmpty() || !myDisabledPlugins.isEmpty()) {
message = "Features covered by non-bundled plugins are detected.<br>";
@@ -305,8 +311,8 @@
message += "<a href=\"ignore\">Ignore All</a>";
}
- else if (myBundledPlugins && !PropertiesComponent.getInstance().isTrueValue(IGNORE_ULTIMATE_EDITION)) {
- message = "Features covered by IntelliJ IDEA Ultimate Edition are detected.<br>" +
+ else if (myBundledPlugin != null && !PropertiesComponent.getInstance().isTrueValue(IGNORE_ULTIMATE_EDITION)) {
+ message = "Features covered by IntelliJ IDEA Ultimate Edition (" + StringUtil.join(myBundledPlugin, ", ") + ") are detected.<br>" +
"<a href=\"open\">" + CHECK_ULTIMATE_EDITION_TITLE + "</a><br>" +
"<a href=\"ignoreUltimate\">" + ULTIMATE_EDITION_SUGGESTION + "</a>";
}
@@ -361,15 +367,17 @@
}
}
}
-
+
@Tag("plugin")
public static class Plugin implements Comparable<Plugin> {
public String myPluginId;
+ public String myPluginName;
public boolean myBundled;
- public Plugin(PluginId pluginId, boolean bundled) {
+ public Plugin(PluginId pluginId, String pluginName, boolean bundled) {
myPluginId = pluginId.getIdString();
myBundled = bundled;
+ myPluginName = pluginName;
}
public Plugin() {
@@ -384,6 +392,7 @@
if (myBundled != plugin.myBundled) return false;
if (!myPluginId.equals(plugin.myPluginId)) return false;
+ if (myPluginName != null && !myPluginName.equals(plugin.myPluginName)) return false;
return true;
}
@@ -392,6 +401,7 @@
public int hashCode() {
int result = myPluginId.hashCode();
result = 31 * result + (myBundled ? 1 : 0);
+ result = 31 * result + (myPluginName != null ? myPluginName.hashCode() : 0);
return result;
}
@@ -413,7 +423,7 @@
public ConfigurePluginsListener(Set<UnknownFeature> unknownFeatures,
Project project,
List<IdeaPluginDescriptor> allPlugins,
- Set<PluginDownloader> plugins,
+ Set<PluginDownloader> plugins,
Map<Plugin, IdeaPluginDescriptor> disabledPlugins) {
myUnknownFeatures = unknownFeatures;
myProject = project;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java
index 9b91ea4..402d88c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/LinkMouseListenerBase.java
@@ -16,47 +16,71 @@
package com.intellij.openapi.vcs.changes.issueLinks;
import com.intellij.ui.ClickListener;
+import com.intellij.ui.SimpleColoredComponent;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
-public abstract class LinkMouseListenerBase extends ClickListener implements MouseMotionListener {
+public abstract class LinkMouseListenerBase<T> extends ClickListener implements MouseMotionListener {
+ public static void installSingleTagOn(@NotNull SimpleColoredComponent component) {
+ new LinkMouseListenerBase<Consumer<MouseEvent>>() {
+ @Nullable
+ @Override
+ protected Consumer<MouseEvent> getTagAt(@NotNull MouseEvent e) {
+ //noinspection unchecked
+ return (Consumer<MouseEvent>)((SimpleColoredComponent)e.getSource()).getFragmentTagAt(e.getX());
+ }
+
+ @Override
+ protected void handleTagClick(@Nullable Consumer<MouseEvent> tag, @NotNull MouseEvent event) {
+ if (tag != null) {
+ tag.consume(event);
+ }
+ }
+ }.installOn(component);
+ }
+
@Nullable
- protected abstract Object getTagAt(final MouseEvent e);
+ protected abstract T getTagAt(@NotNull MouseEvent e);
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
- if (e.getButton() == 1) {
- Object tag = getTagAt(e);
- handleTagClick(tag, e);
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
+ if (e.getButton() == MouseEvent.BUTTON1) {
+ handleTagClick(getTagAt(e), e);
}
return false;
}
- protected void handleTagClick(final Object tag, MouseEvent event) {
+ protected void handleTagClick(@Nullable T tag, @NotNull MouseEvent event) {
if (tag instanceof Runnable) {
- ((Runnable) tag).run();
+ ((Runnable)tag).run();
}
}
-
+
+ @Override
public void mouseDragged(MouseEvent e) {
}
+ @Override
public void mouseMoved(MouseEvent e) {
- Component tree = (Component)e.getSource();
+ Component component = (Component)e.getSource();
Object tag = getTagAt(e);
if (tag != null) {
- tree.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ component.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
}
else {
- tree.setCursor(Cursor.getDefaultCursor());
+ component.setCursor(Cursor.getDefaultCursor());
}
}
- public void installOn(Component tree) {
- super.installOn(tree);
- tree.addMouseMotionListener(this);
+ @Override
+ public void installOn(@NotNull Component component) {
+ super.installOn(component);
+
+ component.addMouseMotionListener(this);
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeLinkMouseListener.java b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeLinkMouseListener.java
index fb829bd..2b8e792 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeLinkMouseListener.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeLinkMouseListener.java
@@ -17,6 +17,7 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.ui.ColoredTreeCellRenderer;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -27,7 +28,7 @@
/**
* @author yole
-*/
+ */
public class TreeLinkMouseListener extends LinkMouseListenerBase {
private final ColoredTreeCellRenderer myRenderer;
protected TreeNode myLastHitNode;
@@ -39,31 +40,30 @@
protected void showTooltip(final JTree tree, final MouseEvent e, final HaveTooltip launcher) {
final String text = tree.getToolTipText(e);
final String newText = launcher == null ? null : launcher.getTooltip();
- if (! Comparing.equal(text, newText)) {
+ if (!Comparing.equal(text, newText)) {
tree.setToolTipText(newText);
}
}
- @Nullable @Override
- protected Object getTagAt(final MouseEvent e) {
- JTree tree = (JTree) e.getSource();
+ @Nullable
+ @Override
+ protected Object getTagAt(@NotNull final MouseEvent e) {
+ JTree tree = (JTree)e.getSource();
Object tag = null;
HaveTooltip haveTooltip = null;
final TreePath path = tree.getPathForLocation(e.getX(), e.getY());
if (path != null) {
final Rectangle rectangle = tree.getPathBounds(path);
+ assert rectangle != null;
int dx = e.getX() - rectangle.x;
- final TreeNode treeNode = (TreeNode) path.getLastPathComponent();
+ final TreeNode treeNode = (TreeNode)path.getLastPathComponent();
if (myLastHitNode != treeNode) {
myLastHitNode = treeNode;
myRenderer.getTreeCellRendererComponent(tree, treeNode, false, false, treeNode.isLeaf(), -1, false);
}
- int i = myRenderer.findFragmentAt(dx);
- if (i >= 0) {
- tag = myRenderer.getFragmentTag(i);
- if (treeNode instanceof HaveTooltip) {
- haveTooltip = (HaveTooltip) treeNode;
- }
+ tag = myRenderer.getFragmentTagAt(dx);
+ if (tag != null && treeNode instanceof HaveTooltip) {
+ haveTooltip = (HaveTooltip)treeNode;
}
}
showTooltip(tree, e, haveTooltip);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeNodePartListener.java b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeNodePartListener.java
index 0ba0e80..a3a1553 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeNodePartListener.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TreeNodePartListener.java
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.vcs.changes.issueLinks;
+import org.jetbrains.annotations.NotNull;
+
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
@@ -31,7 +33,7 @@
myRenderer = renderer;
}
- protected Object getTagAt(final MouseEvent e) {
+ protected Object getTagAt(@NotNull final MouseEvent e) {
final JTree tree = (JTree) e.getSource();
final TreePath path = tree.getPathForLocation(e.getX(), e.getY());
if (path != null) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusManagerImpl.java
index 70100dc..29a1ab9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusManagerImpl.java
@@ -99,6 +99,7 @@
@Override
public void run() {
DocumentAdapter documentListener = new DocumentAdapter() {
+ @Override
public void documentChanged(DocumentEvent event) {
VirtualFile file = FileDocumentManager.getInstance().getFile(event.getDocument());
if (file != null) {
@@ -114,6 +115,7 @@
}
});
startupManager.registerPostStartupActivity(new DumbAwareRunnable() {
+ @Override
public void run() {
fileStatusesChanged();
}
@@ -139,47 +141,58 @@
return getDefaultStatus(virtualFile);
}
+ @NotNull
public static FileStatus getDefaultStatus(@NotNull final VirtualFile file) {
return file.isValid() && file.is(VFileProperty.SPECIAL) ? FileStatus.IGNORED : FileStatus.NOT_CHANGED;
}
+ @Override
public void projectClosed() {
}
+ @Override
public void projectOpened() {
}
+ @Override
public void disposeComponent() {
myCachedStatuses.clear();
}
+ @Override
@NotNull
public String getComponentName() {
return "FileStatusManager";
}
+ @Override
public void initComponent() {
}
+ @Override
public void addFileStatusListener(@NotNull FileStatusListener listener) {
myListeners.add(listener);
}
+ @Override
public void addFileStatusListener(final FileStatusListener listener, Disposable parentDisposable) {
addFileStatusListener(listener);
Disposer.register(parentDisposable, new Disposable() {
+ @Override
public void dispose() {
removeFileStatusListener(listener);
}
});
}
+ @Override
public void fileStatusesChanged() {
if (myProject.isDisposed()) {
return;
}
if (!ApplicationManager.getApplication().isDispatchThread()) {
ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() {
+ @Override
public void run() {
fileStatusesChanged();
}
@@ -195,26 +208,28 @@
}
}
- private void cacheChangedFileStatus(final VirtualFile vf, final FileStatus fs) {
- myCachedStatuses.put(vf, fs);
+ private void cacheChangedFileStatus(final VirtualFile virtualFile, final FileStatus fs) {
+ myCachedStatuses.put(virtualFile, fs);
if (FileStatus.NOT_CHANGED.equals(fs)) {
- final ThreeState parentingStatus = myFileStatusProvider.getNotChangedDirectoryParentingStatus(vf);
+ final ThreeState parentingStatus = myFileStatusProvider.getNotChangedDirectoryParentingStatus(virtualFile);
if (ThreeState.YES.equals(parentingStatus)) {
- myWhetherExactlyParentToChanged.put(vf, true);
+ myWhetherExactlyParentToChanged.put(virtualFile, true);
}
else if (ThreeState.UNSURE.equals(parentingStatus)) {
- myWhetherExactlyParentToChanged.put(vf, false);
+ myWhetherExactlyParentToChanged.put(virtualFile, false);
}
}
else {
- myWhetherExactlyParentToChanged.remove(vf);
+ myWhetherExactlyParentToChanged.remove(virtualFile);
}
}
+ @Override
public void fileStatusChanged(final VirtualFile file) {
final Application application = ApplicationManager.getApplication();
if (!application.isDispatchThread() && !application.isUnitTestMode()) {
ApplicationManager.getApplication().invokeLater(new DumbAwareRunnable() {
+ @Override
public void run() {
fileStatusChanged(file);
}
@@ -222,7 +237,7 @@
return;
}
- if ((file == null) || (!file.isValid())) return;
+ if (file == null || !file.isValid()) return;
FileStatus cachedStatus = getCachedStatus(file);
if (cachedStatus == FileStatusNull.INSTANCE) {
return;
@@ -240,7 +255,8 @@
}
}
- public FileStatus getStatus(final VirtualFile file) {
+ @Override
+ public FileStatus getStatus(@NotNull final VirtualFile file) {
if (file instanceof LightVirtualFile) {
return FileStatus.NOT_CHANGED; // do not leak light files via cache
}
@@ -258,6 +274,7 @@
return myCachedStatuses.get(file);
}
+ @Override
public void removeFileStatusListener(FileStatusListener listener) {
myListeners.remove(listener);
}
@@ -271,7 +288,7 @@
final Boolean exactMatch = myWhetherExactlyParentToChanged.get(vf);
return exactMatch == null
? notChangedColor
- : (exactMatch ? FileStatus.NOT_CHANGED_IMMEDIATE.getColor() : FileStatus.NOT_CHANGED_RECURSIVE.getColor());
+ : exactMatch ? FileStatus.NOT_CHANGED_IMMEDIATE.getColor() : FileStatus.NOT_CHANGED_RECURSIVE.getColor();
}
public void refreshFileStatusFromDocument(final VirtualFile file, final Document doc) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusProvider.java b/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusProvider.java
index 955430e..e9ba482 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vcs/impl/FileStatusProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ThreeState;
+import org.jetbrains.annotations.NotNull;
/**
* @author yole
@@ -28,8 +29,9 @@
ExtensionPointName<FileStatusProvider> EP_NAME = ExtensionPointName.create("com.intellij.vcs.fileStatusProvider");
- FileStatus getFileStatus(final VirtualFile virtualFile);
- void refreshFileStatusFromDocument(final VirtualFile file, final Document doc);
+ FileStatus getFileStatus(@NotNull VirtualFile virtualFile);
+ void refreshFileStatusFromDocument(@NotNull VirtualFile virtualFile, @NotNull Document doc);
- ThreeState getNotChangedDirectoryParentingStatus(VirtualFile vf);
+ @NotNull
+ ThreeState getNotChangedDirectoryParentingStatus(@NotNull VirtualFile virtualFile);
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/ChangeFileEncodingAction.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/ChangeFileEncodingAction.java
index 9c3704d..be87a94 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/ChangeFileEncodingAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/ChangeFileEncodingAction.java
@@ -69,6 +69,7 @@
VirtualFile myFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
boolean enabled = myFile != null && checkEnabled(myFile);
e.getPresentation().setEnabled(enabled);
+ e.getPresentation().setVisible(myFile != null);
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java
index c77e1c0..409950a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java
@@ -122,7 +122,7 @@
if (virtualFile == null) return;
Project project = guessProject(virtualFile);
if (project != null && project.isDisposed()) return;
- Charset charset = LoadTextUtil.charsetFromContentOrNull(project, virtualFile, document.getText());
+ Charset charset = LoadTextUtil.charsetFromContentOrNull(project, virtualFile, document.getImmutableCharSequence());
Charset oldCached = getCachedCharsetFromContent(document);
if (!Comparing.equal(charset, oldCached)) {
setCachedCharsetFromContent(charset, oldCached, document);
@@ -144,7 +144,7 @@
return ApplicationManager.getApplication().runReadAction(new Computable<Charset>() {
@Override
public Charset compute() {
- Charset charsetFromContent = LoadTextUtil.charsetFromContentOrNull(project, virtualFile, document.getText());
+ Charset charsetFromContent = LoadTextUtil.charsetFromContentOrNull(project, virtualFile, document.getImmutableCharSequence());
if (charsetFromContent != null) {
setCachedCharsetFromContent(charsetFromContent, cached, document);
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java
index 4e4adfa..7470f92 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/IncompatibleEncodingDialog.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,6 +21,7 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.xml.util.XmlStringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,11 +51,10 @@
@Nullable
@Override
protected JComponent createCenterPanel() {
- JLabel label = new JLabel("<html><body>" +
+ JLabel label = new JLabel(XmlStringUtil.wrapInHtml(
"The encoding you've chosen ('" + charset.displayName() + "') may change the contents of '" + virtualFile.getName() + "'.<br>" +
"Do you want to reload the file from disk or<br>" +
- "convert the text and save in the new encoding?" +
- "</body></html>");
+ "convert the text and save in the new encoding?"));
label.setIcon(Messages.getQuestionIcon());
label.setIconTextGap(10);
return label;
@@ -74,23 +74,21 @@
byte[] bom = virtualFile.getBOM();
if (bom != null) {
Messages
- .showErrorDialog("<html><body>" +
+ .showErrorDialog(XmlStringUtil.wrapInHtml(
"File '" + virtualFile.getName() + "' can't be reloaded in the '" + charset.displayName() + "' encoding.<br><br>" +
(failReason == null ? "" : "Why: "+ failReason +"<br>") +
- (autoDetected == null ? "" : "Detected encoding: '"+ autoDetected.displayName()+"'") +
- "</body></html>",
- "Incompatible Encoding: " + charset.displayName()
+ (autoDetected == null ? "" : "Detected encoding: '"+ autoDetected.displayName()+"'")),
+ "Incompatible Encoding: " + charset.displayName()
);
res = -1;
}
else {
res = Messages
- .showDialog("<html><body>" +
+ .showDialog(XmlStringUtil.wrapInHtml(
"File '" + virtualFile.getName() + "' most likely isn't stored in the '" + charset.displayName() + "' encoding." +
"<br><br>" +
(failReason == null ? "" : "Why: " + failReason + "<br>") +
- (autoDetected == null ? "" : "Detected encoding: '" + autoDetected.displayName() + "'") +
- "</body></html>",
+ (autoDetected == null ? "" : "Detected encoding: '" + autoDetected.displayName() + "'")),
"Incompatible Encoding: " + charset.displayName(), new String[]{"Reload anyway", "Cancel"}, 1,
AllIcons.General.WarningDialog);
}
@@ -111,10 +109,9 @@
protected void doAction(ActionEvent e) {
if (safeToConvert == EncodingUtil.Magic8.NO_WAY) {
String error = EncodingUtil.checkCanConvert(virtualFile);
- int res = Messages.showDialog("<html><body>" +
+ int res = Messages.showDialog(XmlStringUtil.wrapInHtml(
"Please do not convert to '"+charset.displayName()+"'.<br><br>" +
- (error == null ? "Encoding '" + charset.displayName() + "' does not support some characters from the text." : error)+
- "</body></html>",
+ (error == null ? "Encoding '" + charset.displayName() + "' does not support some characters from the text." : error)),
"Incompatible Encoding: " + charset.displayName(), new String[]{"Convert anyway", "Cancel"}, 1,
AllIcons.General.WarningDialog);
if (res != 0) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
index 5d27509..b581b7d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyCachingFileSystem.java
@@ -25,6 +25,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.FactoryMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
@@ -32,7 +33,6 @@
import java.io.IOException;
import java.util.Collection;
import java.util.List;
-import java.util.Map;
/**
* @author gregsh
@@ -44,7 +44,7 @@
private final BidirectionalMap<Project, String> myProject2Id = new BidirectionalMap<Project, String>();
- private final Map<String, T> myCachedFiles = new ConcurrentFactoryMap<String, T>() {
+ private final FactoryMap<String, T> myCachedFiles = new ConcurrentFactoryMap<String, T>() {
@Override
protected T create(String key) {
if (ApplicationManager.getApplication().isUnitTestMode()) {
@@ -122,7 +122,7 @@
@NotNull
public Collection<T> getCachedFiles() {
- return myCachedFiles.values();
+ return myCachedFiles.notNullValues();
}
public void onProjectClosed(Project project) {
@@ -169,12 +169,12 @@
}
}
- protected void beforeFileRename(VirtualFile file, Object requestor, String oldName, String newName) {
+ protected void beforeFileRename(@NotNull VirtualFile file, Object requestor, @NotNull String oldName, @NotNull String newName) {
fireBeforePropertyChange(requestor, file, VirtualFile.PROP_NAME, oldName, newName);
myCachedFiles.remove(file.getPath());
}
- protected void fileRenamed(VirtualFile file, Object requestor, String oldName, String newName) {
+ protected void fileRenamed(@NotNull VirtualFile file, Object requestor, String oldName, String newName) {
//noinspection unchecked
myCachedFiles.put(file.getPath(), (T)file);
firePropertyChanged(requestor, file, VirtualFile.PROP_NAME, oldName, newName);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java
index 1c182d3..ee751e6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.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.
@@ -118,7 +118,7 @@
@Override
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
- final VirtualFileDirectoryImpl dir = ((VirtualFileDirectoryImpl)vDir);
+ final VirtualFileDirectoryImpl dir = (VirtualFileDirectoryImpl)vDir;
VirtualFileImpl child = new VirtualFileDataImpl(this, dir, fileName);
dir.addChild(child);
fireFileCreated(requestor, child);
@@ -138,7 +138,7 @@
@Override
@NotNull
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
- final VirtualFileDirectoryImpl dir = ((VirtualFileDirectoryImpl)vDir);
+ final VirtualFileDirectoryImpl dir = (VirtualFileDirectoryImpl)vDir;
VirtualFileImpl child = new VirtualFileDirectoryImpl(this, dir, dirName);
dir.addChild(child);
fireFileCreated(requestor, child);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
index 92e7ed7..8744cd2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/temp/TempFileSystem.java
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.openapi.vfs.ex.temp;
import com.intellij.openapi.application.ApplicationManager;
@@ -46,6 +45,7 @@
public class TempFileSystem extends LocalFileSystemBase {
private final FSItem myRoot = new FSDir(null, "/");
+ @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
public static TempFileSystem getInstance() {
return ApplicationManager.getApplication().getComponent(TempFileSystem.class);
}
@@ -53,7 +53,6 @@
@NotNull
@Override
protected String extractRootPath(@NotNull final String path) {
- //return path.startsWith("/") ? "/" : "";
return "/";
}
@@ -66,6 +65,7 @@
private FSItem convert(VirtualFile file) {
final VirtualFile parentFile = file.getParent();
if (parentFile == null) return myRoot;
+
FSItem parentItem = convert(parentFile);
if (parentItem == null || !parentItem.isDirectory()) {
return null;
@@ -75,14 +75,8 @@
}
@Override
- public VirtualFile copyFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent, @NotNull final String copyName)
- throws IOException {
- return VfsUtilCore.copyFile(requestor, file, newParent, copyName);
- }
-
- @Override
@NotNull
- public VirtualFile createChildDirectory(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String dir) throws IOException {
+ public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile parent, @NotNull String dir) throws IOException {
final FSItem fsItem = convert(parent);
assert fsItem != null && fsItem.isDirectory();
@@ -95,28 +89,35 @@
throw new IOException("Directory already contains a file named " + dir);
}
-
return new FakeVirtualFile(parent, dir);
}
@Override
- public VirtualFile createChildFile(final Object requestor, @NotNull final VirtualFile parent, @NotNull final String file) throws IOException {
+ public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile parent, @NotNull String file) throws IOException {
final FSItem fsItem = convert(parent);
if (fsItem == null) {
FSRecords.invalidateCaches();
throw new IllegalStateException("cannot find parent directory: " + parent.getPath());
}
- assert fsItem.isDirectory(): "parent is not a directory: " + parent.getPath();
+ assert fsItem.isDirectory() : "parent is not a directory: " + parent.getPath();
final FSDir fsDir = (FSDir)fsItem;
- assert fsDir.findChild(file) == null: "File " + file + " already exists in " + parent.getPath();
+ assert fsDir.findChild(file) == null : "File " + file + " already exists in " + parent.getPath();
fsDir.addChild(new FSFile(fsDir, file));
return new FakeVirtualFile(parent, file);
}
@Override
+ public VirtualFile copyFile(Object requestor,
+ @NotNull VirtualFile file,
+ @NotNull VirtualFile newParent,
+ @NotNull String copyName) throws IOException {
+ return VfsUtilCore.copyFile(requestor, file, newParent, copyName);
+ }
+
+ @Override
public void deleteFile(final Object requestor, @NotNull final VirtualFile file) throws IOException {
final FSItem fsItem = convert(file);
if (fsItem == null) {
@@ -129,23 +130,22 @@
@Override
public void moveFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final VirtualFile newParent) throws IOException {
final FSItem fsItem = convert(file);
- assert fsItem != null: "failed to move file " + file.getPath();
+ assert fsItem != null : "failed to move file " + file.getPath();
final FSItem newParentItem = convert(newParent);
- assert newParentItem != null && newParentItem.isDirectory(): "failed to find move target " + file.getPath();
- FSDir newDir = (FSDir) newParentItem;
+ assert newParentItem != null && newParentItem.isDirectory() : "failed to find move target " + file.getPath();
+ FSDir newDir = (FSDir)newParentItem;
if (newDir.findChild(file.getName()) != null) {
throw new IOException("Directory already contains a file named " + file.getName());
}
fsItem.getParent().removeChild(fsItem);
- ((FSDir) newParentItem).addChild(fsItem);
+ ((FSDir)newParentItem).addChild(fsItem);
}
@Override
public void renameFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) throws IOException {
final FSItem fsItem = convert(file);
assert fsItem != null;
-
fsItem.setName(newName);
}
@@ -165,7 +165,6 @@
public String[] list(@NotNull final VirtualFile file) {
final FSItem fsItem = convert(file);
assert fsItem != null;
-
return fsItem.list();
}
@@ -177,8 +176,7 @@
@Override
public long getTimeStamp(@NotNull final VirtualFile file) {
final FSItem fsItem = convert(file);
- assert fsItem != null: "cannot find item for path " + file.getPath();
-
+ assert fsItem != null : "cannot find item for path " + file.getPath();
return fsItem.myTimestamp;
}
@@ -186,7 +184,6 @@
public void setTimeStamp(@NotNull final VirtualFile file, final long timeStamp) {
final FSItem fsItem = convert(file);
assert fsItem != null;
-
fsItem.myTimestamp = timeStamp > 0 ? timeStamp : LocalTimeCounter.currentTime();
}
@@ -194,7 +191,6 @@
public boolean isWritable(@NotNull final VirtualFile file) {
final FSItem fsItem = convert(file);
assert fsItem != null;
-
return fsItem.myWritable;
}
@@ -202,7 +198,6 @@
public void setWritable(@NotNull final VirtualFile file, final boolean writableFlag) throws IOException {
final FSItem fsItem = convert(file);
assert fsItem != null;
-
fsItem.myWritable = writableFlag;
}
@@ -211,9 +206,7 @@
public byte[] contentsToByteArray(@NotNull final VirtualFile file) throws IOException {
final FSItem fsItem = convert(file);
if (fsItem == null) throw new FileNotFoundException("Cannot find temp for " + file.getPath());
-
assert fsItem instanceof FSFile;
-
return ((FSFile)fsItem).myContent;
}
@@ -225,8 +218,10 @@
@Override
@NotNull
- public OutputStream getOutputStream(@NotNull final VirtualFile file, final Object requestor, final long modStamp, final long timeStamp)
- throws IOException {
+ public OutputStream getOutputStream(@NotNull final VirtualFile file,
+ final Object requestor,
+ final long modStamp,
+ final long timeStamp) throws IOException {
return new ByteArrayOutputStream() {
@Override
public void close() throws IOException {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java
index 092588c..bf2a0d6 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/DefaultRemoteContentProvider.java
@@ -25,9 +25,10 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.PathUtil;
+import com.intellij.util.PathUtilRt;
+import com.intellij.util.Url;
import com.intellij.util.io.UrlConnectionUtil;
-import com.intellij.util.net.CertificatesManager;
+import com.intellij.util.net.ssl.CertificatesManager;
import org.jetbrains.annotations.NotNull;
import javax.net.ssl.HostnameVerifier;
@@ -46,12 +47,12 @@
private static final int READ_TIMEOUT = 60 * 1000;
@Override
- public boolean canProvideContent(@NotNull final String url) {
+ public boolean canProvideContent(@NotNull Url url) {
return true;
}
@Override
- public void saveContent(final String url, @NotNull final File file, @NotNull final DownloadingCallback callback) {
+ public void saveContent(@NotNull final Url url, @NotNull final File file, @NotNull final DownloadingCallback callback) {
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
@@ -60,14 +61,14 @@
});
}
- private static void downloadContent(final String url, final File file, final DownloadingCallback callback) {
+ private static void downloadContent(@NotNull final Url url, final File file, final DownloadingCallback callback) {
LOG.debug("Downloading started: " + url);
InputStream input = null;
OutputStream output = null;
try {
- String presentableUrl = StringUtil.first(url, 40, true);
+ String presentableUrl = StringUtil.trimMiddle(url.trimParameters().toDecodedForm(), 40);
callback.setProgressText(VfsBundle.message("download.progress.connecting", presentableUrl), true);
- HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
+ HttpURLConnection connection = (HttpURLConnection)new URL(url.toExternalForm()).openConnection();
connection.setConnectTimeout(CONNECT_TIMEOUT);
connection.setReadTimeout(READ_TIMEOUT);
if (connection instanceof HttpsURLConnection) {
@@ -79,7 +80,7 @@
return true;
}
});
- httpsConnection.setSSLSocketFactory(CertificatesManager.createDefault().createSslContext().getSocketFactory());
+ httpsConnection.setSSLSocketFactory(CertificatesManager.getInstance().createSslContext().getSocketFactory());
}
catch (Exception e) {
LOG.warn(e);
@@ -93,14 +94,16 @@
}
final int size = connection.getContentLength();
+ //noinspection IOResourceOpenedButNotSafelyClosed
output = new BufferedOutputStream(new FileOutputStream(file));
callback.setProgressText(VfsBundle.message("download.progress.downloading", presentableUrl), size == -1);
if (size != -1) {
callback.setProgressFraction(0);
}
+
FileType fileType = RemoteFileUtil.getFileType(connection.getContentType());
if (fileType == FileTypes.PLAIN_TEXT) {
- FileType fileTypeByFileName = FileTypeRegistry.getInstance().getFileTypeByFileName(PathUtil.getFileName(url));
+ FileType fileTypeByFileName = FileTypeRegistry.getInstance().getFileTypeByFileName(PathUtilRt.getFileName(url.getPath()));
if (fileTypeByFileName != FileTypes.UNKNOWN) {
fileType = fileTypeByFileName;
}
@@ -149,7 +152,7 @@
}
@Override
- public boolean isUpToDate(@NotNull final String url, @NotNull final VirtualFile local) {
+ public boolean isUpToDate(@NotNull final Url url, @NotNull final VirtualFile local) {
return false;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
index feb9bdb..7665e94 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
import com.intellij.openapi.vfs.ex.http.HttpVirtualFileListener;
+import com.intellij.util.Urls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -41,8 +42,7 @@
public VirtualFile findFileByPath(@NotNull String path, boolean isDirectory) {
try {
- String url = VirtualFileManager.constructUrl(myProtocol, path);
- return getRemoteFileManager().getOrCreateFile(url, path, isDirectory);
+ return getRemoteFileManager().getOrCreateFile(Urls.newFromIdea(VirtualFileManager.constructUrl(myProtocol, path)), path, isDirectory);
}
catch (IOException e) {
return null;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java
index 4694c4d..02a102c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemImpl.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.vfs.impl.http;
+import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
/**
@@ -22,7 +23,7 @@
*/
public class HttpFileSystemImpl extends HttpFileSystemBase {
public HttpFileSystemImpl() {
- super(PROTOCOL);
+ super(URLUtil.HTTP_PROTOCOL);
}
public static HttpFileSystemImpl getInstanceImpl() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/LocalFileStorage.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/LocalFileStorage.java
index e772c3b..5f07fb1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/LocalFileStorage.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/LocalFileStorage.java
@@ -17,7 +17,9 @@
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.util.PathUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.util.PathUtilRt;
+import com.intellij.util.Url;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -31,30 +33,19 @@
public LocalFileStorage() {
myStorageIODirectory = new File(PathManager.getSystemPath(), "httpFileSystem");
+ //noinspection ResultOfMethodCallIgnored
myStorageIODirectory.mkdirs();
}
- public File createLocalFile(@NotNull String url) throws IOException {
- int ast = url.indexOf('?');
- if (ast != -1) {
- url = url.substring(0, ast);
- }
- int last = url.lastIndexOf('/');
- String baseName;
- if (last == url.length() - 1) {
- baseName = url.substring(url.lastIndexOf('/', last-1) + 1, last);
- }
- else {
- baseName = url.substring(last + 1);
- }
-
+ public File createLocalFile(@NotNull Url url) throws IOException {
+ String baseName = PathUtilRt.getFileName(url.getPath());
int index = baseName.lastIndexOf('.');
String prefix = index == -1 ? baseName : baseName.substring(0, index);
String suffix = index == -1 ? "" : baseName.substring(index+1);
- prefix = PathUtil.suggestFileName(prefix);
- suffix = PathUtil.suggestFileName(suffix);
+ prefix = PathUtilRt.suggestFileName(prefix);
+ suffix = PathUtilRt.suggestFileName(suffix);
File file = FileUtil.findSequentNonexistentFile(myStorageIODirectory, prefix, suffix);
- FileUtil.createIfDoesntExist(file);
+ FileUtilRt.createIfNotExists(file);
return file;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteContentProvider.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteContentProvider.java
index 7e12941..49c9af0 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteContentProvider.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteContentProvider.java
@@ -15,8 +15,9 @@
*/
package com.intellij.openapi.vfs.impl.http;
-import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Url;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,12 +27,11 @@
* @author nik
*/
public abstract class RemoteContentProvider {
+ public abstract boolean canProvideContent(@NotNull Url url);
- public abstract boolean canProvideContent(@NotNull String url);
+ public abstract void saveContent(@NotNull Url url, @NotNull File targetFile, @NotNull DownloadingCallback callback);
- public abstract void saveContent(final String url, @NotNull File targetFile, @NotNull DownloadingCallback callback);
-
- public abstract boolean isUpToDate(@NotNull String url, @NotNull VirtualFile local);
+ public abstract boolean isUpToDate(@NotNull Url url, @NotNull VirtualFile local);
public interface DownloadingCallback {
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java
index 59293f2..6854607 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileInfoImpl.java
@@ -25,6 +25,7 @@
import com.intellij.openapi.vfs.VfsBundle;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Url;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,7 +41,7 @@
public class RemoteFileInfoImpl implements RemoteContentProvider.DownloadingCallback, RemoteFileInfo {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.http.RemoteFileInfoImpl");
private final Object myLock = new Object();
- private final String myUrl;
+ private final Url myUrl;
private final RemoteFileManagerImpl myManager;
private @Nullable RemoteContentProvider myContentProvider;
private File myLocalFile;
@@ -51,7 +52,7 @@
private final AtomicBoolean myCancelled = new AtomicBoolean();
private final List<FileDownloadingListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- public RemoteFileInfoImpl(final @NotNull String url, final @NotNull RemoteFileManagerImpl manager) {
+ public RemoteFileInfoImpl(final @NotNull Url url, final @NotNull RemoteFileManagerImpl manager) {
myUrl = url;
myManager = manager;
}
@@ -66,10 +67,6 @@
myListeners.remove(listener);
}
- public String getUrl() {
- return myUrl;
- }
-
@Override
public void restartDownloading() {
synchronized (myLock) {
@@ -126,7 +123,7 @@
String fileName = myLocalFile.getName();
int dot = fileName.lastIndexOf('.');
String extension = fileType.getDefaultExtension();
- if (dot == -1 || !extension.equals(fileName.substring(dot + 1))) {
+ if (dot == -1 || !extension.regionMatches(true, 0, fileName, dot + 1, extension.length())) {
File newFile = FileUtil.findSequentNonexistentFile(myLocalFile.getParentFile(), fileName, extension);
try {
FileUtil.rename(myLocalFile, newFile);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
index 09d7cf2..a514518 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileManagerImpl.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.ex.http.HttpVirtualFileListener;
import com.intellij.util.EventDispatcher;
+import com.intellij.util.Url;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
@@ -34,19 +35,18 @@
*/
public class RemoteFileManagerImpl extends RemoteFileManager implements Disposable {
private final LocalFileStorage myStorage;
- private final Map<Pair<Boolean, String>, VirtualFileImpl> myRemoteFiles;
+ private final Map<Pair<Boolean, Url>, VirtualFileImpl> myRemoteFiles = new THashMap<Pair<Boolean, Url>, VirtualFileImpl>();
private final EventDispatcher<HttpVirtualFileListener> myDispatcher = EventDispatcher.create(HttpVirtualFileListener.class);
private final List<RemoteContentProvider> myProviders = new ArrayList<RemoteContentProvider>();
private final DefaultRemoteContentProvider myDefaultRemoteContentProvider;
public RemoteFileManagerImpl() {
myStorage = new LocalFileStorage();
- myRemoteFiles = new THashMap<Pair<Boolean, String>, VirtualFileImpl>();
myDefaultRemoteContentProvider = new DefaultRemoteContentProvider();
}
@NotNull
- public RemoteContentProvider findContentProvider(final @NotNull String url) {
+ public RemoteContentProvider findContentProvider(final @NotNull Url url) {
for (RemoteContentProvider provider : myProviders) {
if (provider.canProvideContent(url)) {
return provider;
@@ -55,10 +55,9 @@
return myDefaultRemoteContentProvider;
}
- public synchronized VirtualFileImpl getOrCreateFile(final @NotNull String url, final @NotNull String path, final boolean directory) throws IOException {
- Pair<Boolean, String> key = Pair.create(directory, url);
+ public synchronized VirtualFileImpl getOrCreateFile(final @NotNull Url url, final @NotNull String path, final boolean directory) throws IOException {
+ Pair<Boolean, Url> key = Pair.create(directory, url);
VirtualFileImpl file = myRemoteFiles.get(key);
-
if (file == null) {
if (!directory) {
RemoteFileInfoImpl fileInfo = new RemoteFileInfoImpl(url, this);
@@ -73,8 +72,9 @@
return file;
}
- private static HttpFileSystemBase getHttpFileSystem(@NotNull String url) {
- return url.startsWith(HttpsFileSystem.HTTPS_PROTOCOL) ? HttpsFileSystem.getHttpsInstance() : HttpFileSystemImpl.getInstanceImpl();
+ private static HttpFileSystemBase getHttpFileSystem(@NotNull Url url) {
+ return HttpsFileSystem.HTTPS_PROTOCOL.equals(url.getScheme())
+ ? HttpsFileSystem.getHttpsInstance() : HttpFileSystemImpl.getInstanceImpl();
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileUtil.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileUtil.java
index 43507a3..5366cff 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileUtil.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/RemoteFileUtil.java
@@ -32,7 +32,9 @@
int end = contentType.indexOf(';');
String mimeType = end == -1 ? contentType : contentType.substring(0, end);
- if (mimeType.length() == 0) return null;
+ if (mimeType.isEmpty()) {
+ return null;
+ }
for (Language language : Language.getRegisteredLanguages()) {
String[] types = language.getMimeTypes();
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 f07b22f..3c354bc 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
@@ -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,11 +19,9 @@
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
-import com.intellij.openapi.vfs.newvfs.BulkFileListener;
-import com.intellij.openapi.vfs.newvfs.events.VFilePropertyChangeEvent;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.FileContentUtilCore;
import com.intellij.util.UriUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -31,17 +29,16 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.util.Collections;
class VirtualFileImpl extends HttpVirtualFile {
private final HttpFileSystemBase myFileSystem;
- private final @Nullable RemoteFileInfoImpl myFileInfo;
+ @Nullable private final RemoteFileInfoImpl myFileInfo;
private FileType myInitialFileType;
private final String myPath;
private final String myParentPath;
private final String myName;
- VirtualFileImpl(HttpFileSystemBase fileSystem, String path, final @Nullable RemoteFileInfoImpl fileInfo) {
+ VirtualFileImpl(HttpFileSystemBase fileSystem, String path, @Nullable final RemoteFileInfoImpl fileInfo) {
myFileSystem = fileSystem;
myPath = path;
myFileInfo = fileInfo;
@@ -55,9 +52,7 @@
VirtualFileImpl file = VirtualFileImpl.this;
FileDocumentManager.getInstance().reloadFiles(file);
if (!localFile.getFileType().equals(myInitialFileType)) {
- VFilePropertyChangeEvent event = new VFilePropertyChangeEvent(this, file, PROP_NAME, file.getName(), file.getName(), false);
- BulkFileListener publisher = ApplicationManager.getApplication().getMessageBus().asyncPublisher(VirtualFileManager.VFS_CHANGES);
- publisher.after(Collections.singletonList(event));
+ FileContentUtilCore.reparseFiles(file);
}
}
});
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
index 972165f..42d2064 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
@@ -30,7 +30,6 @@
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.util.SmartList;
import com.intellij.util.TimeoutUtil;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
@@ -53,8 +52,7 @@
* @author max
*/
public class FileWatcher {
- @NonNls public static final String PROPERTY_WATCHER_DISABLED = "idea.filewatcher.disabled";
- @NonNls public static final String PROPERTY_WATCHER_EXECUTABLE_PATH = "idea.filewatcher.executable.path";
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.FileWatcher");
public static final NotNullLazyValue<NotificationGroup> NOTIFICATION_GROUP = new NotNullLazyValue<NotificationGroup>() {
@NotNull @Override
@@ -75,11 +73,10 @@
}
}
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.impl.local.FileWatcher");
-
- @NonNls private static final String ROOTS_COMMAND = "ROOTS";
- @NonNls private static final String EXIT_COMMAND = "EXIT";
-
+ private static final String PROPERTY_WATCHER_DISABLED = "idea.filewatcher.disabled";
+ private static final String PROPERTY_WATCHER_EXECUTABLE_PATH = "idea.filewatcher.executable.path";
+ private static final String ROOTS_COMMAND = "ROOTS";
+ private static final String EXIT_COMMAND = "EXIT";
private static final int MAX_PROCESS_LAUNCH_ATTEMPT_COUNT = 10;
private final ManagingFS myManagingFS;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java
index 6648e7c..94f9420 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/LocalFileSystemImpl.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.
@@ -62,7 +62,7 @@
if (index >= 0) rootPath = rootPath.substring(0, index);
File rootFile = new File(FileUtil.toSystemDependentName(rootPath));
- if (index > 0 || !rootFile.isDirectory()) {
+ if (index > 0 || !(FileUtil.isRootPath(rootFile) || rootFile.isDirectory())) {
File parentFile = rootFile.getParentFile();
if (parentFile == null) {
throw new FileNotFoundException(rootPath);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java
index f21d2c0..aef53ed 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/win32/Win32FsCache.java
@@ -44,8 +44,7 @@
@NotNull
private Map<String, FileAttributes> getMap() {
- Reference<Map<String, FileAttributes>> cache = myCache;
- Map<String, FileAttributes> map = cache == null ? null : cache.get();
+ Map<String, FileAttributes> map = com.intellij.reference.SoftReference.dereference(myCache);
if (map == null) {
map = new THashMap<String, FileAttributes>(FileUtil.PATH_HASHING_STRATEGY);
myCache = new SoftReference<Map<String, FileAttributes>>(map);
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshProgress.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshProgress.java
index ded68ba..2400415 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshProgress.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshProgress.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.
@@ -24,23 +24,19 @@
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.ex.StatusBarEx;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
-import javax.swing.*;
-
/**
* @author max
*/
public class RefreshProgress extends ProgressIndicatorBase {
+ private static final Project[] NULL_ARRAY = {null};
+
@NotNull
public static ProgressIndicator create(@NotNull String message) {
Application app = ApplicationManager.getApplication();
- if (app == null || app.isUnitTestMode()) {
- return new EmptyProgressIndicator();
- }
- else {
- return new RefreshProgress(message);
- }
+ return app == null || app.isUnitTestMode() ? new EmptyProgressIndicator() : new RefreshProgress(message);
}
private final String myMessage;
@@ -53,52 +49,36 @@
@Override
public void start() {
super.start();
-
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(new Runnable() {
- @Override
- public void run() {
- if (ApplicationManager.getApplication().isDisposed()) return;
- final WindowManager windowManager = WindowManager.getInstance();
- if (windowManager == null) return;
-
- Project[] projects= ProjectManager.getInstance().getOpenProjects();
- if(projects.length==0){
- projects=new Project[]{null};
- }
-
- for (Project project : projects) {
- final StatusBarEx statusBar = (StatusBarEx) windowManager.getStatusBar(project);
- if (statusBar == null) continue;
-
- statusBar.startRefreshIndication(myMessage);
- }
- }
- });
+ updateIndicators(true);
}
@Override
public void stop() {
super.stop();
+ updateIndicators(false);
+ }
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(new Runnable() {
- @Override
+ private void updateIndicators(final boolean start) {
+ // wrapping in invokeLater here reduces the number of events posted to EDT in case of multiple IDE frames
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
public void run() {
if (ApplicationManager.getApplication().isDisposed()) return;
- final WindowManager windowManager = WindowManager.getInstance();
+
+ WindowManager windowManager = WindowManager.getInstance();
if (windowManager == null) return;
- Project[] projects= ProjectManager.getInstance().getOpenProjects();
- if(projects.length==0){
- projects=new Project[]{null};
- }
-
+ Project[] projects = ProjectManager.getInstance().getOpenProjects();
+ if (projects.length == 0) projects = NULL_ARRAY;
for (Project project : projects) {
- final StatusBarEx statusBar = (StatusBarEx) windowManager.getStatusBar(project);
- if (statusBar == null) continue;
-
- statusBar.stopRefreshIndication();
+ StatusBarEx statusBar = (StatusBarEx)windowManager.getStatusBar(project);
+ if (statusBar != null) {
+ if (start) {
+ statusBar.startRefreshIndication(myMessage);
+ }
+ else {
+ statusBar.stopRefreshIndication();
+ }
+ }
}
}
});
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java
index 6a0be3f..009f4ef 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/RefreshQueueImpl.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 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationEx;
+import com.intellij.openapi.diagnostic.FrequentEventDetector;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.DumbAwareRunnable;
@@ -42,6 +43,7 @@
private final ExecutorService myQueue = ConcurrencyUtil.newSingleThreadExecutor("FS Synchronizer");
private final ProgressIndicator myRefreshIndicator = RefreshProgress.create(VfsBundle.message("file.synchronize.progress"));
private final TLongObjectHashMap<RefreshSession> mySessions = new TLongObjectHashMap<RefreshSession>();
+ private final FrequentEventDetector myEventCounter = new FrequentEventDetector(100, 100, FrequentEventDetector.Level.ERROR);
public void execute(@NotNull RefreshSessionImpl session) {
if (session.isAsynchronous()) {
@@ -56,8 +58,8 @@
}
else {
if (((ApplicationEx)app).holdsReadLock()) {
- LOG.error("Do not call synchronous refresh from inside read action except for event dispatch thread. " +
- "This will eventually cause deadlock if there are any events to fire");
+ LOG.error("Do not call synchronous refresh under read lock (except from EDT) - " +
+ "this will cause a deadlock if there are any events to fire.");
return;
}
queueSession(session, ModalityState.defaultModalityState());
@@ -91,6 +93,7 @@
}
}
});
+ myEventCounter.eventHappened();
}
private void doScan(RefreshSessionImpl session) {
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 a13998c..ab9655a 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
@@ -23,7 +23,6 @@
import com.intellij.util.io.IOUtil;
import com.intellij.util.io.PersistentStringEnumerator;
import com.intellij.util.text.StringFactory;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,7 +31,6 @@
*/
public class FileNameCache {
private static final PersistentStringEnumerator ourNames = FSRecords.getNames();
- @NonNls private static final String EMPTY = "";
@SuppressWarnings("unchecked") private static final IntSLRUCache<IntObjectLinkedMap.MapEntry<Object>>[] ourNameCache = new IntSLRUCache[16];
static {
final int protectedSize = 40000 / ourNameCache.length;
@@ -75,12 +73,13 @@
return h % ourNameCache.length;
}
+ @NotNull
private static Object convertToBytesIfAsciiString(@NotNull String name) {
int length = name.length();
- if (length == 0) return EMPTY;
+ if (length == 0) return "";
if (!IOUtil.isAscii(name)) {
- return name;
+ return new String(name); // So we don't hold whole char[] buffer of a lengthy path on JDK 6
}
byte[] bytes = new byte[length];
@@ -125,7 +124,7 @@
IntObjectLinkedMap.MapEntry<Object> entry = getEntry(nameId);
Object rawName = entry.value;
if (rawName instanceof String) {
- String thisName = getVFileName(nameId);
+ String thisName = (String)rawName;
return VirtualFileSystemEntry.compareNames(thisName, name, ignoreCase);
}
@@ -135,20 +134,21 @@
int d = bytesLength - name.length();
if (d != 0) return d;
- return compareBytes(bytes, 0, name, 0, bytesLength, ignoreCase);
+ return compareBytes(bytes, name, bytesLength, ignoreCase);
}
- private static int compareBytes(@NotNull byte[] name1, int offset1, @NotNull String name2, int offset2, int len, boolean ignoreCase) {
- for (int i1 = offset1, i2=offset2; i1 < offset1 + len; i1++, i2++) {
- char c1 = (char)name1[i1];
- char c2 = name2.charAt(i2);
+ private static int compareBytes(@NotNull byte[] name1, @NotNull String name2, int len, boolean ignoreCase) {
+ for (int i = 0; i < len; i++) {
+ char c1 = (char)name1[i];
+ char c2 = name2.charAt(i);
int d = StringUtil.compare(c1, c2, ignoreCase);
if (d != 0) return d;
}
return 0;
}
- static char[] appendPathOnFileSystem(int nameId, @Nullable VirtualFileSystemEntry parent, int accumulatedPathLength, int[] positionRef) {
+ @NotNull
+ static char[] appendPathOnFileSystem(int nameId, @Nullable VirtualFileSystemEntry parent, int accumulatedPathLength, @NotNull int[] positionRef) {
IntObjectLinkedMap.MapEntry<Object> entry = getEntry(nameId);
Object o = entry.value;
int nameLength = o instanceof String ? ((String)o).length() : ((byte[])o).length;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java
index 5a31321..611d014 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VirtualDirectoryImpl.java
@@ -19,10 +19,12 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
@@ -57,9 +59,10 @@
* @author max
*/
public class VirtualDirectoryImpl extends VirtualFileSystemEntry {
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl");
public static boolean CHECK = ApplicationManager.getApplication().isUnitTestMode();
- static final VirtualDirectoryImpl NULL_VIRTUAL_FILE = new VirtualDirectoryImpl("*?;%NULL", null, LocalFileSystem.getInstance(), -42, 0) {
+ static final VirtualDirectoryImpl NULL_VIRTUAL_FILE = new VirtualDirectoryImpl(FileNameCache.storeName("*?;%NULL"), null, LocalFileSystem.getInstance(), -42, 0) {
public String toString() {
return "NULL";
}
@@ -80,12 +83,12 @@
*/
private VirtualFileSystemEntry[] myChildren = EMPTY_ARRAY;
- public VirtualDirectoryImpl(@NonNls @NotNull final String name,
+ public VirtualDirectoryImpl(@NonNls final int nameId,
@Nullable final VirtualDirectoryImpl parent,
@NotNull final NewVirtualFileSystem fs,
final int id,
@PersistentFS.Attributes final int attributes) {
- super(name, parent, id, attributes);
+ super(nameId, parent, id, attributes);
myFS = fs;
}
@@ -97,25 +100,25 @@
@Nullable
private VirtualFileSystemEntry findChild(@NotNull String name,
- final boolean doRefresh,
+ boolean doRefresh,
boolean ensureCanonicalName,
@NotNull NewVirtualFileSystem delegate) {
boolean ignoreCase = !delegate.isCaseSensitive();
Comparator comparator = getComparator(ignoreCase);
VirtualFileSystemEntry result = doFindChild(name, ensureCanonicalName, delegate, comparator);
+
if (result == NULL_VIRTUAL_FILE) {
result = doRefresh ? createAndFindChildWithEventFire(name, delegate) : null;
}
- else if (result != null) {
- if (doRefresh && delegate.isDirectory(result) != result.isDirectory()) {
- RefreshQueue.getInstance().refresh(false, false, null, result);
- result = findChild(name, false, ensureCanonicalName, delegate);
- }
+ else if (result != null && doRefresh && delegate.isDirectory(result) != result.isDirectory()) {
+ RefreshQueue.getInstance().refresh(false, false, null, result);
+ result = findChild(name, false, ensureCanonicalName, delegate);
}
if (result == null) {
addToAdoptedChildren(!delegate.isCaseSensitive(), name, comparator);
}
+
return result;
}
@@ -139,8 +142,38 @@
}
private static class AdoptedChild extends VirtualFileImpl {
+ private final String myName;
+
private AdoptedChild(String name) {
- super(name, NULL_VIRTUAL_FILE, -42, -1);
+ super(-1, NULL_VIRTUAL_FILE, -42, -1);
+ myName = name;
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public void setNewName(@NotNull String newName) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public int compareNameTo(@NotNull String name, boolean ignoreCase) {
+ return compareNames(myName, name, ignoreCase);
+ }
+
+ @Override
+ protected char[] appendPathOnFileSystem(int accumulatedPathLength, int[] positionRef) {
+ char[] chars = getParent().appendPathOnFileSystem(accumulatedPathLength + 1 + myName.length(), positionRef);
+ if (positionRef[0] > 0 && chars[positionRef[0] - 1] != '/') {
+ chars[positionRef[0]++] = '/';
+ }
+ positionRef[0] = VirtualFileSystemEntry.copyString(chars, positionRef[0], myName);
+ return chars;
+
}
}
@@ -183,11 +216,6 @@
}
synchronized (this) {
- // do not extract getId outside the synchronized block since it will cause a concurrency problem.
- int id = ourPersistence.getId(this, name, delegate);
- if (id <= 0) {
- return null;
- }
// maybe another doFindChild() sneaked in the middle
VirtualFileSystemEntry[] array = myChildren;
long r = findIndexInBoth(array, name, comparator);
@@ -199,8 +227,12 @@
return array[indexInReal];
}
- String shorty = new String(name);
- VirtualFileSystemEntry child = createChild(shorty, id, delegate); // So we don't hold whole char[] buffer of a lengthy path
+ // do not extract getId outside the synchronized block since it will cause a concurrency problem.
+ int id = ourPersistence.getId(this, name, delegate);
+ if (id <= 0) {
+ return null;
+ }
+ VirtualFileSystemEntry child = createChild(FileNameCache.storeName(name), id, delegate);
VirtualFileSystemEntry[] after = myChildren;
if (after != array) {
@@ -238,15 +270,20 @@
}
@NotNull
- public VirtualFileSystemEntry createChild(@NotNull String name, int id, @NotNull NewVirtualFileSystem delegate) {
+ public VirtualFileSystemEntry createChild(String name, int id, @NotNull NewVirtualFileSystem delegate) {
+ return createChild(FileNameCache.storeName(name), id, delegate);
+ }
+
+ @NotNull
+ private VirtualFileSystemEntry createChild(int nameId, int id, @NotNull NewVirtualFileSystem delegate) {
VirtualFileSystemEntry child;
final int attributes = ourPersistence.getFileAttributes(id);
if (PersistentFS.isDirectory(attributes)) {
- child = new VirtualDirectoryImpl(name, this, delegate, id, attributes);
+ child = new VirtualDirectoryImpl(nameId, this, delegate, id, attributes);
}
else {
- child = new VirtualFileImpl(name, this, id, attributes);
+ child = new VirtualFileImpl(nameId, this, id, attributes);
//noinspection TestOnlyProblems
assertAccessInTests(child, delegate);
}
@@ -501,7 +538,8 @@
return children;
}
- FSRecords.NameId[] childrenIds = ourPersistence.listAll(this);
+ final boolean wasChildrenLoaded = ourPersistence.areChildrenLoaded(this);
+ final FSRecords.NameId[] childrenIds = ourPersistence.listAll(this);
VirtualFileSystemEntry[] result;
if (childrenIds.length == 0) {
result = EMPTY_ARRAY;
@@ -512,7 +550,17 @@
public int compare(FSRecords.NameId o1, FSRecords.NameId o2) {
String name1 = o1.name;
String name2 = o2.name;
- return compareNames(name1, name2, ignoreCase);
+ int cmp = compareNames(name1, name2, ignoreCase);
+ if (cmp == 0 && name1 != name2) {
+ LOG.error(ourPersistence + " returned duplicate file names("+name1+","+name2+")" +
+ " ignoreCase: "+ignoreCase+
+ " SystemInfo.isFileSystemCaseSensitive: "+ SystemInfo.isFileSystemCaseSensitive+
+ " SystemInfo.OS: "+ SystemInfo.OS_NAME+" "+SystemInfo.OS_VERSION+
+ " wasChildrenLoaded: "+wasChildrenLoaded+
+ " in the dir: "+VirtualDirectoryImpl.this+";" +
+ " children: "+Arrays.toString(childrenIds));
+ }
+ return cmp;
}
});
result = new VirtualFileSystemEntry[childrenIds.length];
@@ -532,7 +580,7 @@
resultFile = children[i++];
}
else {
- resultFile = createChild(nameId.name, nameId.id, delegate);
+ resultFile = createChild(nameId.nameId, nameId.id, delegate);
}
result[delegateI++] = resultFile;
}
@@ -563,38 +611,45 @@
String prevName = prev.getName();
int cmp = file.compareNameTo(prevName, ignoreCase);
if (cmp == 0) {
- Function<VirtualFileSystemEntry, String> verboseToString = new Function<VirtualFileSystemEntry, String>() {
- @Override
- public String fun(VirtualFileSystemEntry entry) {
- return entry + " (name: '" + entry.getName()
- + "', " + entry.getClass()
- + ", parent:"+entry.getParent()
- + "; id:"+entry.getId()
- + "; FS:" +entry.getFileSystem()
- + "; delegate.attrs:" +entry.getFileSystem().getAttributes(entry)
- + "; caseSensitive:" +entry.getFileSystem().isCaseSensitive()
- + "; canonical:" +entry.getFileSystem().getCanonicallyCasedName(entry)
- + ") ";
- }
- };
- String children = StringUtil.join(array, verboseToString, ",");
- throw new AssertionError(
- verboseToString.fun(prev) + " equals to " + verboseToString.fun(file) + "; children: " + children + "\nDetails: " + ContainerUtil.map(
- details, new Function<Object, Object>() {
- @Override
- public Object fun(Object o) {
- return o instanceof Object[] ? Arrays.toString((Object[])o) : o;
- }
- }));
+ error(verboseToString.fun(prev) + " equals to " + verboseToString.fun(file), array, details);
}
if (isAdopted == isAdoptedChild(prev)) {
- assert cmp > 0 : "Not sorted. "+Arrays.toString(details);
+ if (cmp <= 0) {
+ error("Not sorted: "+verboseToString.fun(prev) + " is not less than " + verboseToString.fun(file), array, details);
+ }
}
}
}
}
+ private static final Function<VirtualFileSystemEntry, String> verboseToString = new Function<VirtualFileSystemEntry, String>() {
+ @Override
+ public String fun(VirtualFileSystemEntry file) {
+ //noinspection HardCodedStringLiteral
+ return file + " (name: '" + file.getName()
+ + "', " + file.getClass()
+ + ", parent: "+file.getParent()
+ + "; id: "+file.getId()
+ + "; FS: " +file.getFileSystem()
+ + "; delegate.attrs: " +file.getFileSystem().getAttributes(file)
+ + "; caseSensitive: " +file.getFileSystem().isCaseSensitive()
+ + "; canonical: " +file.getFileSystem().getCanonicallyCasedName(file)
+ + ") ";
+ }
+ };
+ private static void error(@NonNls String message, VirtualFileSystemEntry[] array, Object... details) {
+ String children = StringUtil.join(array, verboseToString, ",");
+ throw new AssertionError(
+ message + "; children: " + children + "\nDetails: " + ContainerUtil.map(
+ details, new Function<Object, Object>() {
+ @Override
+ public Object fun(Object o) {
+ return o instanceof Object[] ? Arrays.toString((Object[])o) : o;
+ }
+ }));
+ }
+
@Override
@Nullable
public VirtualFileSystemEntry findChild(@NotNull final String name) {
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 995670f..33c024f 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
@@ -39,8 +39,8 @@
public class VirtualFileImpl extends VirtualFileSystemEntry {
private Charset myCharset;
- VirtualFileImpl(String name, VirtualDirectoryImpl parent, int id, @PersistentFS.Attributes final int attributes) {
- super(name, parent, id, attributes);
+ VirtualFileImpl(int nameId, VirtualDirectoryImpl parent, int id, @PersistentFS.Attributes final int attributes) {
+ super(nameId, parent, id, attributes);
}
@Override
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 7da918a..2d5b519 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
@@ -48,7 +48,6 @@
public abstract class VirtualFileSystemEntry extends NewVirtualFile {
public static final VirtualFileSystemEntry[] EMPTY_ARRAY = new VirtualFileSystemEntry[0];
- @NonNls protected static final String FS_ROOT_FAKE_NAME = "";
protected static final PersistentFS ourPersistence = PersistentFS.getInstance();
private static final Key<String> SYMLINK_TARGET = Key.create("local.vfs.symlink.target");
@@ -70,13 +69,10 @@
private volatile int myFlags;
private volatile int myId;
- public VirtualFileSystemEntry(@NotNull String name, VirtualDirectoryImpl parent, int id, @PersistentFS.Attributes int attributes) {
+ public VirtualFileSystemEntry(int nameId, VirtualDirectoryImpl parent, int id, @PersistentFS.Attributes int attributes) {
myParent = parent;
myId = id;
-
- if (name != FS_ROOT_FAKE_NAME) {
- storeName(name);
- }
+ myNameId = nameId;
if (parent != null && parent != VirtualDirectoryImpl.NULL_VIRTUAL_FILE) {
setFlagInt(IS_SYMLINK_FLAG, PersistentFS.isSymLink(attributes));
@@ -90,10 +86,6 @@
setModificationStamp(LocalTimeCounter.currentTime());
}
- private void storeName(@NotNull String name) {
- myNameId = FileNameCache.storeName(name.replace('\\', '/')); // note: on Unix-style FS names may contain backslashes
- }
-
private void updateLinkStatus() {
boolean isSymLink = is(VFileProperty.SYMLINK);
if (isSymLink) {
@@ -113,7 +105,7 @@
return FileNameCache.compareNameTo(myNameId, name, ignoreCase);
}
- static int compareNames(@NotNull String name1, @NotNull String name2, boolean ignoreCase) {
+ protected static int compareNames(@NotNull String name1, @NotNull String name2, boolean ignoreCase) {
return compareNames(name1, name2, ignoreCase, 0);
}
@@ -350,7 +342,7 @@
}
myParent.removeChild(this);
- storeName(newName);
+ myNameId = FileNameCache.storeName(newName);
myParent.addChild(this);
}
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 bd6691f..c1c7cd6 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
@@ -29,6 +29,7 @@
import com.intellij.openapi.util.io.ByteSequence;
import com.intellij.openapi.util.io.FileAttributes;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.newvfs.impl.FileNameCache;
import com.intellij.util.ArrayUtil;
import com.intellij.util.SystemProperties;
import com.intellij.util.containers.ConcurrentHashMap;
@@ -879,9 +880,11 @@
public static final NameId[] EMPTY_ARRAY = new NameId[0];
public final int id;
public final String name;
+ public final int nameId;
- public NameId(int id, @NotNull String name) {
+ public NameId(int id, int nameId, @NotNull String name) {
this.id = id;
+ this.nameId = nameId;
this.name = name;
}
@@ -904,7 +907,8 @@
for (int i = 0; i < count; i++) {
int id = DataInputOutputUtil.readINT(input);
id = id >= 0 ? id + parentId : -id;
- result[i] = new NameId(id, getName(id));
+ int nameId = getNameId(id);
+ result[i] = new NameId(id, nameId, FileNameCache.getVFileName(nameId));
}
input.close();
return result;
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
index dd07cb6..03b6309 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/persistent/PersistentFSImpl.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.
@@ -24,14 +24,17 @@
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.*;
import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.openapi.vfs.newvfs.*;
import com.intellij.openapi.vfs.newvfs.events.*;
import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
+import com.intellij.openapi.vfs.newvfs.impl.FileNameCache;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.util.*;
import com.intellij.util.containers.ConcurrentIntObjectMap;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.EmptyIntHashSet;
import com.intellij.util.containers.StripedLockIntObjectConcurrentHashMap;
import com.intellij.util.io.ReplicatorInputStream;
import com.intellij.util.io.URLUtil;
@@ -44,6 +47,7 @@
import java.io.*;
import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -53,30 +57,25 @@
public class PersistentFSImpl extends PersistentFS implements ApplicationComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vfs.newvfs.persistent.PersistentFS");
- private final MessageBus myEventsBus;
+ private final MessageBus myEventBus;
private final ReadWriteLock myRootsLock = new ReentrantReadWriteLock();
- // (normalized)url -> root. guarded by myRootsLock
- private final Map<String, VirtualFileSystemEntry> myRoots = new THashMap<String, VirtualFileSystemEntry>(FileUtil.PATH_HASHING_STRATEGY);
- // root.getId() -> root. guarded by myRootsLock
+ private final Map<String, VirtualFileSystemEntry> myRoots = ContainerUtil.newTroveMap(FileUtil.PATH_HASHING_STRATEGY);
private final TIntObjectHashMap<VirtualFileSystemEntry> myRootsById = new TIntObjectHashMap<VirtualFileSystemEntry>();
private final ConcurrentIntObjectMap<VirtualFileSystemEntry> myIdToDirCache = new StripedLockIntObjectConcurrentHashMap<VirtualFileSystemEntry>();
private final Object myInputLock = new Object();
- // the root of all roots. All roots in myRoots and myRootsById maps are children of this super root. guarded by myRootsLock
- @Nullable private volatile VirtualFileSystemEntry mySuperRoot;
- private boolean myShutDown = false;
- @SuppressWarnings("UnusedDeclaration")
- private final LowMemoryWatcher myLowMemoryWatcher = LowMemoryWatcher.register(new Runnable() {
- @Override
- public void run() {
- clearIdCache();
- }
- });
+ private final AtomicBoolean myShutDown = new AtomicBoolean(false);
- public PersistentFSImpl(@NotNull final MessageBus bus) {
- myEventsBus = bus;
+ public PersistentFSImpl(@NotNull MessageBus bus) {
+ myEventBus = bus;
+ LowMemoryWatcher.register(new Runnable() {
+ @Override
+ public void run() {
+ clearIdCache();
+ }
+ });
ShutDownTracker.getInstance().registerShutdownTask(new Runnable() {
@Override
public void run() {
@@ -86,13 +85,17 @@
}
@Override
+ public void initComponent() {
+ FSRecords.connect();
+ }
+
+ @Override
public void disposeComponent() {
performShutdown();
}
- private synchronized void performShutdown() {
- if (!myShutDown) {
- myShutDown = true;
+ private void performShutdown() {
+ if (myShutDown.compareAndSet(false, true)) {
LOG.info("VFS dispose started");
FSRecords.dispose();
LOG.info("VFS dispose completed");
@@ -107,11 +110,6 @@
}
@Override
- public void initComponent() {
- FSRecords.connect();
- }
-
- @Override
public boolean areChildrenLoaded(@NotNull final VirtualFile dir) {
return areChildrenLoaded(getFileId(dir));
}
@@ -164,8 +162,7 @@
}
@NotNull
- private FSRecords.NameId[] persistAllChildren(@NotNull final VirtualFile file, final int id, @NotNull FSRecords.NameId[] current) {
- assert file != mySuperRoot;
+ private static FSRecords.NameId[] persistAllChildren(@NotNull final VirtualFile file, final int id, @NotNull FSRecords.NameId[] current) {
final NewVirtualFileSystem fs = replaceWithNativeFS(getDelegate(file));
String[] delegateNames = VfsUtil.filterNames(fs.list(file));
@@ -173,43 +170,26 @@
return current;
}
- THashMap<String, FSRecords.NameId> result = new THashMap<String, FSRecords.NameId>();
- if (current.length == 0) {
- for (String name : delegateNames) {
- result.put(name, new FSRecords.NameId(-1, name));
- }
- }
- else {
- for (FSRecords.NameId nameId : current) {
- result.put(nameId.name, nameId);
- }
- for (String name : delegateNames) {
- if (!result.containsKey(name)) {
- result.put(name, new FSRecords.NameId(-1, name));
- }
- }
+ Set<String> toAdd = ContainerUtil.newHashSet(delegateNames);
+ for (FSRecords.NameId nameId : current) {
+ toAdd.remove(nameId.name);
}
- final TIntArrayList childrenIds = new TIntArrayList(result.size());
- final List<FSRecords.NameId> nameIds = ContainerUtil.newArrayListWithExpectedSize(result.size());
- result.forEachValue(new TObjectProcedure<FSRecords.NameId>() {
- @Override
- public boolean execute(FSRecords.NameId nameId) {
- if (nameId.id < 0) {
- FakeVirtualFile child = new FakeVirtualFile(file, nameId.name);
- FileAttributes attributes = fs.getAttributes(child);
- if (attributes != null) {
- int childId = createAndFillRecord(fs, child, id, attributes);
- nameId = new FSRecords.NameId(childId, nameId.name);
- }
- }
- if (nameId.id > 0) {
- childrenIds.add(nameId.id);
- nameIds.add(nameId);
- }
- return true;
+ final TIntArrayList childrenIds = new TIntArrayList(current.length + toAdd.size());
+ final List<FSRecords.NameId> nameIds = ContainerUtil.newArrayListWithCapacity(current.length + toAdd.size());
+ for (FSRecords.NameId nameId : current) {
+ childrenIds.add(nameId.id);
+ nameIds.add(nameId);
+ }
+ for (String newName : toAdd) {
+ FakeVirtualFile child = new FakeVirtualFile(file, newName);
+ FileAttributes attributes = fs.getAttributes(child);
+ if (attributes != null) {
+ int childId = createAndFillRecord(fs, child, id, attributes);
+ childrenIds.add(childId);
+ nameIds.add(new FSRecords.NameId(childId, FileNameCache.storeName(newName), newName));
}
- });
+ }
FSRecords.updateList(id, childrenIds.toNativeArray());
setChildrenCached(id);
@@ -382,17 +362,14 @@
@Override
public void setWritable(@NotNull final VirtualFile file, final boolean writableFlag) throws IOException {
getDelegate(file).setWritable(file, writableFlag);
- processEvent(new VFilePropertyChangeEvent(this, file, VirtualFile.PROP_WRITABLE, isWritable(file), writableFlag, false));
+ boolean oldWritable = isWritable(file);
+ if (oldWritable != writableFlag) {
+ processEvent(new VFilePropertyChangeEvent(this, file, VirtualFile.PROP_WRITABLE, oldWritable, writableFlag, false));
+ }
}
@Override
- public int getId(@NotNull final VirtualFile parent, @NotNull final String childName, @NotNull final NewVirtualFileSystem fs) {
- if (parent == mySuperRoot) {
- String rootUrl = normalizeRootUrl(childName, fs);
- VirtualFileSystemEntry root = myRoots.get(rootUrl);
- return root == null ? 0 : root.getId();
- }
-
+ public int getId(@NotNull VirtualFile parent, @NotNull String childName, @NotNull NewVirtualFileSystem fs) {
int parentId = getFileId(parent);
int[] children = FSRecords.list(parentId);
@@ -483,9 +460,12 @@
}
@Override
- public void renameFile(final Object requestor, @NotNull final VirtualFile file, @NotNull final String newName) throws IOException {
+ public void renameFile(final Object requestor, @NotNull VirtualFile file, @NotNull String newName) throws IOException {
getDelegate(file).renameFile(requestor, file, newName);
- processEvent(new VFilePropertyChangeEvent(requestor, file, VirtualFile.PROP_NAME, file.getName(), newName, false));
+ String oldName = file.getName();
+ if (!newName.equals(oldName)) {
+ processEvent(new VFilePropertyChangeEvent(requestor, file, VirtualFile.PROP_NAME, oldName, newName, false));
+ }
}
@Override
@@ -642,7 +622,7 @@
VFileContentChangeEvent event = new VFileContentChangeEvent(requestor, file, file.getModificationStamp(), modStamp, false);
List<VFileContentChangeEvent> events = Collections.singletonList(event);
- BulkFileListener publisher = myEventsBus.syncPublisher(VirtualFileManager.VFS_CHANGES);
+ BulkFileListener publisher = myEventBus.syncPublisher(VirtualFileManager.VFS_CHANGES);
publisher.before(events);
NewVirtualFileSystem delegate = getDelegate(file);
@@ -722,28 +702,34 @@
}
}
- ContainerUtil.quickSort(deletionEvents, DEPTH_COMPARATOR);
+ final TIntHashSet invalidIDs;
+ if (deletionEvents.isEmpty()) {
+ invalidIDs = EmptyIntHashSet.INSTANCE;
+ }
+ else {
+ ContainerUtil.quickSort(deletionEvents, DEPTH_COMPARATOR);
- final TIntHashSet invalidIDs = new TIntHashSet(deletionEvents.size());
- final Set<VirtualFile> dirsToBeDeleted = new THashSet<VirtualFile>(deletionEvents.size());
- nextEvent:
- for (EventWrapper wrapper : deletionEvents) {
- final VirtualFile candidate = wrapper.event.getFile();
- VirtualFile parent = candidate;
- while (parent != null) {
- if (dirsToBeDeleted.contains(parent)) {
- invalidIDs.add(wrapper.id);
- continue nextEvent;
+ invalidIDs = new TIntHashSet(deletionEvents.size());
+ final Set<VirtualFile> dirsToBeDeleted = new THashSet<VirtualFile>(deletionEvents.size());
+ nextEvent:
+ for (EventWrapper wrapper : deletionEvents) {
+ final VirtualFile candidate = wrapper.event.getFile();
+ VirtualFile parent = candidate;
+ while (parent != null) {
+ if (dirsToBeDeleted.contains(parent)) {
+ invalidIDs.add(wrapper.id);
+ continue nextEvent;
+ }
+ parent = parent.getParent();
}
- parent = parent.getParent();
- }
- if (candidate.isDirectory()) {
- dirsToBeDeleted.add(candidate);
+ if (candidate.isDirectory()) {
+ dirsToBeDeleted.add(candidate);
+ }
}
}
- final List<VFileEvent> filtered = ContainerUtil.newArrayListWithCapacity(events.size() - invalidIDs.size());
+ final List<VFileEvent> filtered = new ArrayList<VFileEvent>(events.size() - invalidIDs.size());
for (int i = 0, size = events.size(); i < size; i++) {
final VFileEvent event = events.get(i);
if (event.isValid() && !(event instanceof VFileDeleteEvent && invalidIDs.contains(i))) {
@@ -759,7 +745,7 @@
List<VFileEvent> validated = validateEvents(events);
- BulkFileListener publisher = myEventsBus.syncPublisher(VirtualFileManager.VFS_CHANGES);
+ BulkFileListener publisher = myEventBus.syncPublisher(VirtualFileManager.VFS_CHANGES);
publisher.before(validated);
THashMap<VirtualFile, List<VFileEvent>> parentToChildrenEventsChanges = null;
@@ -805,7 +791,7 @@
TIntArrayList childrenIdsUpdated = new TIntArrayList();
List<VirtualFile> childrenToBeUpdated = new SmartList<VirtualFile>();
- assert parent != null && parent != mySuperRoot;
+ assert parent != null;
final int parentId = getFileId(parent);
assert parentId != 0;
TIntHashSet parentChildrenIds = new TIntHashSet(FSRecords.list(parentId));
@@ -866,74 +852,64 @@
@Override
@Nullable
public VirtualFileSystemEntry findRoot(@NotNull String basePath, @NotNull NewVirtualFileSystem fs) {
+ if (basePath.isEmpty()) {
+ LOG.error("Invalid root, fs=" + fs);
+ return null;
+ }
+
String rootUrl = normalizeRootUrl(basePath, fs);
- boolean isFakeRoot = basePath.isEmpty();
- VirtualFileSystemEntry root;
myRootsLock.readLock().lock();
try {
- root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl);
+ VirtualFileSystemEntry root = myRoots.get(rootUrl);
if (root != null) return root;
}
finally {
myRootsLock.readLock().unlock();
}
+ VirtualFileSystemEntry newRoot;
+ int rootId = FSRecords.findRootRecord(rootUrl);
+
+ if (fs instanceof JarFileSystem) {
+ // optimization: for jar roots do not store base path in the myName field, use local FS file's getPath()
+ String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR));
+ VirtualFile parentFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
+ if (parentFile == null) return null;
+ newRoot = new JarRoot(fs, rootId, parentFile);
+ }
+ else {
+ newRoot = new FsRoot(fs, rootId, basePath);
+ }
+
+ FileAttributes attributes = fs.getAttributes(newRoot);
+ if (attributes == null || !attributes.isDirectory()) {
+ return null;
+ }
+
+ boolean mark = false;
+
myRootsLock.writeLock().lock();
try {
- root = isFakeRoot ? mySuperRoot : myRoots.get(rootUrl);
+ VirtualFileSystemEntry root = myRoots.get(rootUrl);
if (root != null) return root;
- int rootId = FSRecords.findRootRecord(rootUrl);
- root = myRootsById.get(rootId);
- if (root != null) return root;
+ mark = writeAttributesToRecord(rootId, 0, newRoot, fs, attributes);
- if (isFakeRoot) {
- // fake super-root
- root = new FakeRoot(fs, rootId);
- }
- else if (fs instanceof JarFileSystem) {
- // optimization: for jar roots do not store base path in the myName field, use local FS file's getPath()
- String parentPath = basePath.substring(0, basePath.indexOf(JarFileSystem.JAR_SEPARATOR));
- VirtualFile parentLocalFile = LocalFileSystem.getInstance().findFileByPath(parentPath);
- if (parentLocalFile == null) return null;
-
- // check one more time since the findFileByPath could have created the root (by reentering the findRoot)
- root = myRoots.get(rootUrl);
- if (root != null) return root;
- root = myRootsById.get(rootId);
- if (root != null) return root;
-
- root = new JarRoot(fs, rootId, parentLocalFile);
- }
- else {
- root = new FsRoot(fs, rootId, basePath);
- }
-
- if (isFakeRoot) {
- mySuperRoot = root;
- }
- else {
- FileAttributes attributes = fs.getAttributes(root);
- if (attributes == null || !attributes.isDirectory()) {
- return null;
- }
- final boolean newRoot = writeAttributesToRecord(rootId, 0, root, fs, attributes);
- if (!newRoot && attributes.lastModified != FSRecords.getTimestamp(rootId)) {
- root.markDirtyRecursively();
- }
-
- myRoots.put(rootUrl, root);
- myRootsById.put(rootId, root);
-
- if (rootId != root.getId()) throw new AssertionError();
- }
-
- return root;
+ myRoots.put(rootUrl, newRoot);
+ myRootsById.put(rootId, newRoot);
}
finally {
myRootsLock.writeLock().unlock();
}
+
+ if (!mark && attributes.lastModified != FSRecords.getTimestamp(rootId)) {
+ newRoot.markDirtyRecursively();
+ }
+
+ LOG.assertTrue(rootId == newRoot.getId(), "root=" + newRoot + " expected=" + rootId + " actual=" + newRoot.getId());
+
+ return newRoot;
}
@NotNull
@@ -1046,12 +1022,12 @@
@Override
@NotNull
public VirtualFile[] getLocalRoots() {
- final List<VirtualFile> roots = new ArrayList<VirtualFile>();
+ List<VirtualFile> roots = ContainerUtil.newSmartList();
myRootsLock.readLock().lock();
try {
for (NewVirtualFile root : myRoots.values()) {
- if (root.isInLocalFileSystem()) {
+ if (root.isInLocalFileSystem() && !(root.getFileSystem() instanceof TempFileSystem)) {
roots.add(root);
}
}
@@ -1295,7 +1271,7 @@
private abstract static class AbstractRoot extends VirtualDirectoryImpl {
protected AbstractRoot(@NotNull NewVirtualFileSystem fs, int id) {
- super(FS_ROOT_FAKE_NAME, null, fs, id, 0);
+ super(-1, null, fs, id, 0);
}
@NotNull
@@ -1303,51 +1279,24 @@
public abstract String getName();
@Override
+ public int compareNameTo(@NotNull String name, boolean ignoreCase) {
+ return VirtualFileSystemEntry.compareNames(getName(), name, ignoreCase);
+ }
+
+ @Override
protected abstract char[] appendPathOnFileSystem(int accumulatedPathLength, int[] positionRef);
@Override
+ public void setNewName(@NotNull String newName) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
public final void setParent(@NotNull VirtualFile newParent) {
throw new IncorrectOperationException();
}
}
- private class FakeRoot extends AbstractRoot {
- private FakeRoot(@NotNull NewVirtualFileSystem fs, int rootId) {
- super(fs, rootId);
- }
-
- @NotNull
- @Override
- public String getName() {
- return FS_ROOT_FAKE_NAME;
- }
-
- @SuppressWarnings("NonSynchronizedMethodOverridesSynchronizedMethod")
- @Override
- @NotNull
- public VirtualFile[] getChildren() {
- return getRoots(getFileSystem());
- }
-
- @Override
- public VirtualFileSystemEntry findChild(@NotNull String name) {
- if (name.isEmpty()) return null;
- return findRoot(name, getFileSystem());
- }
-
- @Override
- protected char[] appendPathOnFileSystem(int pathLength, int[] position) {
- // getPath() for super-root should never be called.
- // however, when new FakeVirtualFile(superRoot, "name") is constructed,
- // return garbage to make sure they won't find anything by the name returned
- String fakeName = "@&^%$#*/\\(";
- int rootPathLength = pathLength + fakeName.length();
- char[] chars = new char[rootPathLength];
- position[0] = copyString(chars, position[0], fakeName);
- return chars;
- }
- }
-
private static class JarRoot extends AbstractRoot {
private final VirtualFile myParentLocalFile;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/ex/WindowManagerEx.java b/platform/platform-impl/src/com/intellij/openapi/wm/ex/WindowManagerEx.java
index 36dd639..5d019be 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/ex/WindowManagerEx.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/ex/WindowManagerEx.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.
@@ -72,6 +72,7 @@
public abstract IdeFrame findFrameFor(@Nullable Project project);
+ @NotNull
public abstract CommandProcessor getCommandProcessor();
/**
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java
index 150fdef..62c77fc 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/DesktopLayout.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.util.containers.HashMap;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -35,11 +36,11 @@
/**
* Map between <code>id</code>s and registered <code>WindowInfo</code>s.
*/
- private final HashMap<String, WindowInfoImpl> myRegisteredId2Info;
+ private final Map<String, WindowInfoImpl> myRegisteredId2Info;
/**
* Map between <code>id</code>s and unregistered <code>WindowInfo</code>s.
*/
- private final HashMap<String, WindowInfoImpl> myUnregisteredId2Info;
+ private final Map<String, WindowInfoImpl> myUnregisteredId2Info;
/**
*
*/
@@ -107,9 +108,8 @@
*
* @param id <code>id</code> of tool window to be registered.
* @param anchor the default tool window anchor.
- * @return
*/
- final WindowInfoImpl register(final String id, final ToolWindowAnchor anchor, final boolean splitMode) {
+ final WindowInfoImpl register(@NotNull String id, @NotNull ToolWindowAnchor anchor, final boolean splitMode) {
WindowInfoImpl info = myUnregisteredId2Info.get(id);
if (info != null) { // tool window has been already registered some time
myUnregisteredId2Info.remove(id);
@@ -289,7 +289,9 @@
for (Object o : layoutElement.getChildren()) {
final Element e = (Element)o;
if (WindowInfoImpl.TAG.equals(e.getName())) {
- final WindowInfoImpl info = new WindowInfoImpl(e.getAttributeValue(ID_ATTR));
+ String id = e.getAttributeValue(ID_ATTR);
+ assert id != null;
+ final WindowInfoImpl info = new WindowInfoImpl(id);
info.readExternal(e);
if (info.getOrder() == -1) { // if order isn't defined then window's button will be the last one in the stripe
info.setOrder(getMaxOrder(info.getAnchor()) + 1);
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
index 46c5190..6daf1ab 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/FocusManagerImpl.java
@@ -35,6 +35,7 @@
import com.intellij.openapi.wm.*;
import com.intellij.openapi.wm.ex.IdeFocusTraversalPolicy;
import com.intellij.openapi.wm.ex.LayoutFocusTraversalPolicyExt;
+import com.intellij.reference.SoftReference;
import com.intellij.ui.FocusTrackback;
import com.intellij.util.containers.WeakValueHashMap;
import com.intellij.util.ui.UIUtil;
@@ -73,7 +74,7 @@
private FocusCommand myFocusCommandOnAppActivation;
private ActionCallback myCallbackOnActivation;
private final boolean isInternalMode = ApplicationManagerEx.getApplicationEx().isInternal();
- private final List<FocusRequestInfo> myRequests = new ArrayList<FocusRequestInfo>();
+ private final LinkedList<FocusRequestInfo> myRequests = new LinkedList<FocusRequestInfo>();
private final IdeEventQueue myQueue;
private final KeyProcessorContext myKeyProcessorContext = new KeyProcessorContext();
@@ -240,9 +241,16 @@
return myRequests;
}
+ public void recordFocusRequest(Component c, boolean forced) {
+ myRequests.add(new FocusRequestInfo(c, new Throwable(), forced));
+ if (myRequests.size() > 200) {
+ myRequests.removeFirst();
+ }
+ }
+
private void recordCommand(@NotNull FocusCommand command, @NotNull Throwable trace, boolean forced) {
if (FocusTracesAction.isActive()) {
- myRequests.add(new FocusRequestInfo(command.getDominationComponent(), trace, forced));
+ recordFocusRequest(command.getDominationComponent(), forced);
}
}
@@ -417,8 +425,7 @@
@Nullable
private FocusCommand getLastEffectiveForcedRequest() {
- if (myLastForcedRequest == null) return null;
- final FocusCommand request = myLastForcedRequest.get();
+ final FocusCommand request = SoftReference.dereference(myLastForcedRequest);
return request != null && !request.isExpired() ? request : null;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java
index f928ec1..8d3d0c1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeMenuBar.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.
@@ -198,22 +198,6 @@
super.menuSelectionChanged(isIncluded);
}
- private static boolean isDescendingFrom(@Nullable Component a, @NotNull Component b) {
- while (a != null) {
- if (a == b) {
- return true;
- }
-
- if (a instanceof JPopupMenu) {
- a = ((JPopupMenu)a).getInvoker();
- }
- else {
- a = a.getParent();
- }
- }
- return false;
- }
-
private boolean isActivated() {
int index = getSelectionModel().getSelectedIndex();
if (index == -1) {
@@ -311,7 +295,7 @@
Component component = findActualComponent(mouseEvent);
if (myState != State.EXPANDED /*&& !myState.isInProgress()*/) {
- boolean mouseInside = myActivated || isDescendingFrom(component, this);
+ boolean mouseInside = myActivated || UIUtil.isDescendingFrom(component, this);
if (e.getID() == MouseEvent.MOUSE_EXITED && e.getSource() == SwingUtilities.windowForComponent(this) && !myActivated) mouseInside = false;
if (mouseInside && myState == State.COLLAPSED) {
setState(State.EXPANDING);
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java
index 775dc6b..1f073f9 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/InternalDecorator.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.
@@ -88,7 +88,7 @@
private ToolWindowHeader myHeader;
- InternalDecorator(final Project project, final WindowInfoImpl info, final ToolWindowImpl toolWindow) {
+ InternalDecorator(final Project project, @NotNull WindowInfoImpl info, final ToolWindowImpl toolWindow) {
super(new BorderLayout());
myProject = project;
myToolWindow = toolWindow;
@@ -156,7 +156,7 @@
/**
* Applies specified decoration.
*/
- public final void apply(final WindowInfoImpl info) {
+ public final void apply(@NotNull WindowInfoImpl info) {
if (Comparing.equal(myInfo, info) || myProject == null || myProject.isDisposed()) {
return;
}
@@ -463,6 +463,7 @@
else if (myInfo.isSliding()) {
group.add(myToggleDockModeAction);
group.add(myToggleFloatingModeAction);
+ group.add(myToggleSideModeAction);
}
return group;
}
@@ -497,6 +498,7 @@
/**
* @return last window info applied to the decorator.
*/
+ @NotNull
final WindowInfoImpl getWindowInfo() {
return myInfo;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java
index 0fd1023..bb62139 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/LibraryDependentToolWindowManager.java
@@ -9,9 +9,9 @@
import com.intellij.openapi.roots.ModuleRootEvent;
import com.intellij.openapi.roots.ModuleRootListener;
import com.intellij.openapi.startup.StartupManager;
+import com.intellij.openapi.wm.ext.LibraryDependentToolWindow;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ex.ToolWindowManagerEx;
-import com.intellij.openapi.wm.ext.LibraryDependentToolWindow;
import com.intellij.psi.PsiManager;
import com.intellij.util.messages.MessageBusConnection;
@@ -28,7 +28,11 @@
public void projectOpened() {
final ModuleRootListener rootListener = new ModuleRootAdapter() {
public void rootsChanged(ModuleRootEvent event) {
- checkToolWindowStatuses();
+ DumbService.getInstance(myProject).smartInvokeLater(new Runnable() {
+ public void run() {
+ checkToolWindowStatuses();
+ }
+ });
}
};
@@ -42,29 +46,24 @@
}
private void checkToolWindowStatuses() {
- DumbService.getInstance(myProject).smartInvokeLater(new Runnable() {
- public void run() {
- if (myProject.isDisposed()) {
- return;
- }
- final PsiManager psiManager = PsiManager.getInstance(myProject);
- if (psiManager.isDisposed()) {
- return;
- }
+ if (myProject.isDisposed()) {
+ return;
+ }
+ final PsiManager psiManager = PsiManager.getInstance(myProject);
+ if (psiManager.isDisposed()) {
+ return;
+ }
- for (LibraryDependentToolWindow libraryToolWindow : Extensions.getExtensions(LibraryDependentToolWindow.EXTENSION_POINT_NAME)) {
- if (libraryToolWindow.getLibrarySearchHelper().isLibraryExists(myProject)) {
- ensureToolWindowExists(libraryToolWindow);
- }
- else {
- ToolWindow toolWindow = myToolWindowManager.getToolWindow(libraryToolWindow.id);
- if (toolWindow != null) {
- myToolWindowManager.unregisterToolWindow(libraryToolWindow.id);
- }
- }
- }
- }
- });
+ for (LibraryDependentToolWindow libraryToolWindow : Extensions.getExtensions(LibraryDependentToolWindow.EXTENSION_POINT_NAME)) {
+ if (libraryToolWindow.getLibrarySearchHelper().isLibraryExists(myProject)) {
+ ensureToolWindowExists(libraryToolWindow);
+ } else {
+ ToolWindow toolWindow = myToolWindowManager.getToolWindow(libraryToolWindow.id);
+ if (toolWindow != null) {
+ myToolWindowManager.unregisterToolWindow(libraryToolWindow.id);
+ }
+ }
+ }
}
private void ensureToolWindowExists(LibraryDependentToolWindow extension) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java
index 5540797..92814fe 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/Stripe.java
@@ -210,11 +210,11 @@
private LayoutData recomputeBounds(boolean setBounds, Dimension toFitWith, boolean noDrop) {
final LayoutData data = new LayoutData();
- final int horizontaloffset = getHeight();
+ final int horizontaloffset = getHeight() - 2;
data.eachY = 0;
data.size = new Dimension();
- data.gap = 1;
+ data.gap = 0;
data.horizontal = isHorizontal();
data.dragInsertPosition = -1;
if (data.horizontal) {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java
index ed13323..3c112ee 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButton.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.
@@ -102,6 +102,7 @@
return getWindowInfo().getAnchor();
}
+ @NotNull
WindowInfoImpl getWindowInfo() {
return myDecorator.getWindowInfo();
}
@@ -290,7 +291,7 @@
myPressedWhenSelected = false;
}
- public void apply(final WindowInfoImpl info) {
+ public void apply(@NotNull WindowInfoImpl info) {
setSelected(info.isVisible() || info.isActive());
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButtonUI.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButtonUI.java
index 9c863e4..eb360e3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButtonUI.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/StripeButtonUI.java
@@ -112,7 +112,7 @@
if (anchor == ToolWindowAnchor.LEFT) g2.translate(-1, 0);
if (anchor.isHorizontal()) g2.translate(0, -1);
final boolean dark = UIUtil.isUnderDarcula();
- g2.setColor(dark ? Gray._15.withAlpha(85) : Gray._85.withAlpha(85));
+ g2.setColor(dark ? Gray._15.withAlpha(model.isSelected() ? 85: 40) : Gray._85.withAlpha(model.isSelected()? 85: 40));
g2.fillRect(0, 0, button.getWidth(), button.getHeight());
if (anchor == ToolWindowAnchor.LEFT) g2.translate(1, 0);
if (anchor.isHorizontal()) g2.translate(0, 1);
@@ -157,7 +157,7 @@
/* Draw the Text */
if(model.isEnabled()){
/*** paint the text normally */
- g2.setColor(UIUtil.isUnderDarcula() && (model.isSelected() || model.isRollover()) ? button.getForeground().brighter() : button.getForeground());
+ g2.setColor(UIUtil.isUnderDarcula() && model.isSelected() ? button.getForeground().brighter() : button.getForeground());
BasicGraphicsUtils.drawString(g2,clippedText,button.getMnemonic2(),ourTextRect.x,ourTextRect.y+fm.getAscent());
} else{
/*** paint the text disabled ***/
@@ -175,31 +175,4 @@
g2.dispose();
}
-
-
- private static void paintLegacyDecoration(Graphics2D g2, AnchoredButton button, ButtonModel model, boolean vertical) {
- final boolean dark = UIUtil.isUnderDarcula();
- Color toBorder = model.isRollover() ? dark ? Gray._90 : new Color(0, 0, 0, 50) : null;
- if (model.isArmed() && model.isPressed() || model.isSelected()) {
- g2.setColor(dark ? Gray._85.withAlpha(85) : new Color(0, 0, 0, 30));
- g2.fillRect(3, 3, button.getWidth() - (vertical ? 6 : 5), button.getHeight() - 6);
-
- g2.setColor(dark ? Gray._40 : new Color(0, 0, 0, 120));
- g2.drawLine(2, 2, 3 + button.getWidth() - (vertical ? 7 : 6), 2);
- g2.drawLine(2, 3, 2, 3 + button.getHeight() - 7);
-
- g2.setColor(dark ? Gray._65 : new Color(0, 0, 0, 40));
- g2.drawRect(3, 3, button.getWidth() - (vertical ? 7 : 6), button.getHeight() - 7);
-
- g2.setColor(dark ? Gray._75 : new Color(255, 255, 255, 110));
- g2.drawLine(3, button.getHeight() - 3, 3 + button.getWidth() - (vertical ? 6 : 5), button.getHeight() - 3);
- g2.drawLine(3 + button.getWidth() - (vertical ? 6 : 5), 2, 3 + button.getWidth() - (vertical ? 6 : 5),
- 3 + button.getHeight() - 7);
- toBorder = null;
- }
- if (toBorder != null) {
- g2.setColor(toBorder);
- g2.drawRect(2, 2, button.getWidth() - (vertical ? 6 : 5), button.getHeight() - 6);
- }
- }
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java
index 13b4b25..cce1a67 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/TestWindowManager.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.
@@ -269,6 +269,7 @@
throw new UnsupportedOperationException();
}
+ @NotNull
@Override
public final CommandProcessor getCommandProcessor() {
throw new UnsupportedOperationException();
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java
index 7c89fd6..e84028e 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowHeader.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.
@@ -63,10 +63,10 @@
private BufferedImage myImage;
private BufferedImage myActiveImage;
private ToolWindowType myImageType;
- private JPanel myButtonPanel;
+ private final JPanel myButtonPanel;
private final ToolWindowHeader.ActionButton myGearButton;
- public ToolWindowHeader(final ToolWindowImpl toolWindow, WindowInfoImpl info, @NotNull final Producer<ActionGroup> gearProducer) {
+ public ToolWindowHeader(final ToolWindowImpl toolWindow, @NotNull WindowInfoImpl info, @NotNull final Producer<ActionGroup> gearProducer) {
setLayout(new BorderLayout());
myToolWindow = toolWindow;
@@ -380,10 +380,10 @@
private class ActionButton extends Wrapper implements ActionListener, AltStateManager.AltListener {
private final InplaceButton myButton;
private final AnAction myAction;
- private AnAction myAlternativeAction;
- private Icon myActiveIcon;
- private Icon myInactiveIcon;
- private Icon myAlternativeIcon;
+ private final AnAction myAlternativeAction;
+ private final Icon myActiveIcon;
+ private final Icon myInactiveIcon;
+ private final Icon myAlternativeIcon;
private AnAction myCurrentAction;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
index c2b7e7b..29a3f14 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.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.
@@ -582,7 +582,7 @@
* This is helper method. It delegated its functionality to the WindowManager.
* Before delegating it fires state changed.
*/
- public void execute(final ArrayList<FinalizableCommand> commandList) {
+ public void execute(@NotNull List<FinalizableCommand> commandList) {
for (FinalizableCommand each : commandList) {
if (each.willChangeState()) {
fireStateChanged();
@@ -604,6 +604,7 @@
private void activateEditorComponent(final boolean forced) {
activateEditorComponent(forced, false); //TODO[kirillk]: runnable in activateEditorComponent(boolean, boolean) never runs
}
+
private void activateEditorComponent(final boolean forced, boolean now) {
if (LOG.isDebugEnabled()) {
LOG.debug("enter: activateEditorComponent()");
@@ -622,7 +623,8 @@
if (!runnable.isExpired()) {
runnable.run();
}
- } else {
+ }
+ else {
final FocusRequestor requestor = getFocusManager().getFurtherRequestor();
getFocusManager().doWhenFocusSettlesDown(new ExpirableRunnable.ForProject(myProject) {
@Override
@@ -644,7 +646,9 @@
return FileEditorManagerEx.getInstanceEx(myProject).getSplitters();
}
- private void activateEditorComponentImpl(EditorsSplitters splitters, final ArrayList<FinalizableCommand> commandList, final boolean forced) {
+ private void activateEditorComponentImpl(EditorsSplitters splitters,
+ List<FinalizableCommand> commandList,
+ final boolean forced) {
final String active = getActiveToolWindowId();
// Now we have to request focus into most recent focused editor
appendRequestFocusInEditorComponentCmd(splitters, commandList, forced).doWhenDone(new Runnable() {
@@ -721,7 +725,7 @@
*/
private void showAndActivate(final String id,
final boolean dirtyMode,
- final ArrayList<FinalizableCommand> commandsList,
+ List<FinalizableCommand> commandsList,
boolean autoFocusContents,
boolean forcedFocusRequest) {
if (!getToolWindow(id).isAvailable()) {
@@ -763,7 +767,7 @@
}
private void activateToolWindowImpl(final String id,
- final ArrayList<FinalizableCommand> commandList,
+ List<FinalizableCommand> commandList,
boolean forced,
boolean autoFocusContents) {
if (!FocusManagerImpl.getInstance().isUnforcedRequestAllowed() && !forced) return;
@@ -1009,7 +1013,8 @@
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
if (hasOpenEditorFiles()) {
activateEditorComponentImpl(getSplittersFromFocus(), commandList, false);
- } else {
+ }
+ else {
focusToolWinowByDefault(id);
}
}
@@ -1177,7 +1182,7 @@
final StripeButton button = new StripeButton(decorator, myToolWindowsPane);
myId2StripeButton.put(id, button);
- final ArrayList<FinalizableCommand> commandsList = new ArrayList<FinalizableCommand>();
+ List<FinalizableCommand> commandsList = new ArrayList<FinalizableCommand>();
appendAddButtonCmd(button, info, commandsList);
if (canWorkInDumbMode) {
@@ -1347,7 +1352,7 @@
@Override
public void invokeLater(final Runnable runnable) {
- final ArrayList<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
+ List<FinalizableCommand> commandList = new ArrayList<FinalizableCommand>();
commandList.add(new InvokeLaterCmd(runnable, myWindowManager.getCommandProcessor()));
execute(commandList);
}
@@ -1364,7 +1369,6 @@
}
final Stripe stripe = myToolWindowsPane.getStripeFor(toolWindowId);
return stripe.getButtonFor(toolWindowId) != null;
-
}
@Override
@@ -1412,7 +1416,8 @@
final BalloonHyperlinkListener listenerWrapper = new BalloonHyperlinkListener(listener);
final Balloon balloon =
- JBPopupFactory.getInstance().createHtmlTextBalloonBuilder(text.replace("\n", "<br>"), icon, type.getPopupBackground(), listenerWrapper)
+ JBPopupFactory.getInstance()
+ .createHtmlTextBalloonBuilder(text.replace("\n", "<br>"), icon, type.getPopupBackground(), listenerWrapper)
.setHideOnClickOutside(false).setHideOnFrameResize(false).createBalloon();
FrameStateManager.getInstance().getApplicationActive().doWhenDone(new Runnable() {
@Override
@@ -1790,7 +1795,9 @@
commandsList.add(command);
}
- private ActionCallback appendRequestFocusInEditorComponentCmd(EditorsSplitters splitters, final ArrayList<FinalizableCommand> commandList, boolean forced) {
+ private ActionCallback appendRequestFocusInEditorComponentCmd(EditorsSplitters splitters,
+ List<FinalizableCommand> commandList,
+ boolean forced) {
if (myProject.isDisposed()) return new ActionCallback.Done();
final CommandProcessor commandProcessor = myWindowManager.getCommandProcessor();
final RequestFocusInEditorComponentCmd command =
@@ -1799,7 +1806,7 @@
return command.getDoneCallback();
}
- private void appendRequestFocusInToolWindowCmd(final String id, final ArrayList<FinalizableCommand> commandList, boolean forced) {
+ private void appendRequestFocusInToolWindowCmd(final String id, List<FinalizableCommand> commandList, boolean forced) {
final ToolWindowImpl toolWindow = (ToolWindowImpl)getToolWindow(id);
final FocusWatcher focusWatcher = myId2FocusWatcher.get(id);
commandList
@@ -1823,8 +1830,8 @@
/**
* @return <code>true</code> if tool window with the specified <code>id</code>
- * is floating and has modal showing child dialog. Such windows should not be closed
- * when auto-hide windows are gone.
+ * is floating and has modal showing child dialog. Such windows should not be closed
+ * when auto-hide windows are gone.
*/
private boolean hasModalChild(final WindowInfoImpl info) {
if (!info.isVisible() || !info.isFloating()) {
@@ -1954,7 +1961,6 @@
if (type != null) {
toolWindow.setType(type, null);
}
-
}
public void setDefaultContentUiType(ToolWindowImpl toolWindow, ToolWindowContentUiType type) {
@@ -2184,7 +2190,9 @@
*/
@Override
public void resized(final InternalDecorator source) {
- if (!source.isShowing()) return; // do not recalculate the tool window size if it is not yet shown (and, therefore, has 0,0,0,0 bounds)
+ if (!source.isShowing()) {
+ return; // do not recalculate the tool window size if it is not yet shown (and, therefore, has 0,0,0,0 bounds)
+ }
final WindowInfoImpl info = getInfo(source.getToolWindow().getId());
InternalDecorator another = null;
@@ -2202,7 +2210,8 @@
if (splitter.getSecondComponent() == source) {
sizeInSplit += splitter.getDividerWidth();
another = (InternalDecorator)splitter.getFirstComponent();
- } else {
+ }
+ else {
another = (InternalDecorator)splitter.getSecondComponent();
}
if (anchor.isSplitVertically()) {
@@ -2214,8 +2223,8 @@
}
float paneWeight = anchor.isHorizontal()
- ? (float)source.getHeight() / (float)myToolWindowsPane.getMyLayeredPane().getHeight()
- : (float)source.getWidth() / (float)myToolWindowsPane.getMyLayeredPane().getWidth();
+ ? (float)source.getHeight() / (float)myToolWindowsPane.getMyLayeredPane().getHeight()
+ : (float)source.getWidth() / (float)myToolWindowsPane.getMyLayeredPane().getWidth();
info.setWeight(paneWeight);
if (another != null && anchor.isSplitVertically()) {
paneWeight = anchor.isHorizontal()
@@ -2330,7 +2339,8 @@
JRootPane root = null;
if (activeWindow instanceof JDialog) {
root = ((JDialog)activeWindow).getRootPane();
- } else if (activeWindow instanceof JFrame) {
+ }
+ else if (activeWindow instanceof JFrame) {
root = ((JFrame)activeWindow).getRootPane();
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java
index caf75bf..49e101a 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowsPane.java
@@ -23,23 +23,19 @@
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.ThreeComponentsSplitter;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.wm.ToolWindow;
import com.intellij.openapi.wm.ToolWindowAnchor;
import com.intellij.openapi.wm.ToolWindowType;
import com.intellij.openapi.wm.ex.ToolWindowEx;
import com.intellij.openapi.wm.impl.commands.FinalizableCommand;
-import com.intellij.reference.SoftReference;
import com.intellij.ui.ScreenUtil;
import com.intellij.ui.components.JBLayeredPane;
import com.intellij.util.containers.HashMap;
-import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.FadeInFadeOut;
import javax.swing.*;
import java.awt.*;
-import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
@@ -53,12 +49,12 @@
* @author Vladimir Kondratyev
*/
public final class ToolWindowsPane extends JBLayeredPane implements Disposable {
- private static final Logger LOG=Logger.getInstance("#com.intellij.openapi.wm.impl.ToolWindowsPane");
+ private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.wm.impl.ToolWindowsPane");
private final IdeFrameImpl myFrame;
- private final HashMap<String,StripeButton> myId2Button;
- private final HashMap<String,InternalDecorator> myId2Decorator;
+ private final HashMap<String, StripeButton> myId2Button;
+ private final HashMap<String, InternalDecorator> myId2Decorator;
private final HashMap<StripeButton, WindowInfoImpl> myButton2Info;
private final HashMap<InternalDecorator, WindowInfoImpl> myDecorator2Info;
private final HashMap<String, Float> myId2SplitProportion;
@@ -92,16 +88,16 @@
private boolean myLeftHorizontalSplit = false;
private boolean myRightHorizontalSplit = false;
- ToolWindowsPane(final IdeFrameImpl frame, ToolWindowManagerImpl manager){
+ ToolWindowsPane(final IdeFrameImpl frame, ToolWindowManagerImpl manager) {
myManager = manager;
setOpaque(false);
- myFrame=frame;
- myId2Button=new HashMap<String,StripeButton>();
- myId2Decorator=new HashMap<String,InternalDecorator>();
- myButton2Info=new HashMap<StripeButton, WindowInfoImpl>();
- myDecorator2Info=new HashMap<InternalDecorator, WindowInfoImpl>();
- myUISettingsListener=new MyUISettingsListenerImpl();
+ myFrame = frame;
+ myId2Button = new HashMap<String, StripeButton>();
+ myId2Decorator = new HashMap<String, InternalDecorator>();
+ myButton2Info = new HashMap<StripeButton, WindowInfoImpl>();
+ myDecorator2Info = new HashMap<InternalDecorator, WindowInfoImpl>();
+ myUISettingsListener = new MyUISettingsListenerImpl();
myId2SplitProportion = new HashMap<String, Float>();
// Splitters
@@ -128,28 +124,28 @@
// Tool stripes
- myTopStripe=new Stripe(SwingConstants.TOP, manager);
+ myTopStripe = new Stripe(SwingConstants.TOP, manager);
myStripes.add(myTopStripe);
- myLeftStripe=new Stripe(SwingConstants.LEFT, manager);
+ myLeftStripe = new Stripe(SwingConstants.LEFT, manager);
myStripes.add(myLeftStripe);
- myBottomStripe=new Stripe(SwingConstants.BOTTOM, manager);
+ myBottomStripe = new Stripe(SwingConstants.BOTTOM, manager);
myStripes.add(myBottomStripe);
- myRightStripe=new Stripe(SwingConstants.RIGHT, manager);
+ myRightStripe = new Stripe(SwingConstants.RIGHT, manager);
myStripes.add(myRightStripe);
updateToolStripesVisibility();
// Layered pane
- myLayeredPane=new MyLayeredPane(myWidescreen ? myHorizontalSplitter : myVerticalSplitter);
+ myLayeredPane = new MyLayeredPane(myWidescreen ? myHorizontalSplitter : myVerticalSplitter);
// Compose layout
add(myTopStripe, JLayeredPane.POPUP_LAYER);
- add(myLeftStripe, JLayeredPane.POPUP_LAYER);
- add(myBottomStripe, JLayeredPane.POPUP_LAYER);
- add(myRightStripe, JLayeredPane.POPUP_LAYER);
- add(myLayeredPane, JLayeredPane.DEFAULT_LAYER);
+ add(myLeftStripe, JLayeredPane.POPUP_LAYER);
+ add(myBottomStripe, JLayeredPane.POPUP_LAYER);
+ add(myRightStripe, JLayeredPane.POPUP_LAYER);
+ add(myLayeredPane, JLayeredPane.DEFAULT_LAYER);
}
@Override
@@ -161,7 +157,8 @@
myLeftStripe.setBounds(0, 0, 0, 0);
myRightStripe.setBounds(0, 0, 0, 0);
myLayeredPane.setBounds(0, 0, getWidth(), getHeight());
- } else {
+ }
+ else {
Dimension topSize = myTopStripe.getPreferredSize();
Dimension bottomSize = myBottomStripe.getPreferredSize();
Dimension leftSize = myLeftStripe.getPreferredSize();
@@ -169,13 +166,16 @@
myTopStripe.setBounds(0, 0, size.width, topSize.height);
myLeftStripe.setBounds(0, topSize.height, leftSize.width, size.height - topSize.height - bottomSize.height);
- myRightStripe.setBounds(size.width - rightSize.width, topSize.height, rightSize.width, size.height - topSize.height - bottomSize.height);
+ myRightStripe
+ .setBounds(size.width - rightSize.width, topSize.height, rightSize.width, size.height - topSize.height - bottomSize.height);
myBottomStripe.setBounds(0, size.height - bottomSize.height, size.width, bottomSize.height);
if (UISettings.getInstance().HIDE_TOOL_STRIPES || UISettings.getInstance().PRESENTATION_MODE) {
myLayeredPane.setBounds(0, 0, size.width, size.height);
- } else {
- myLayeredPane.setBounds(leftSize.width, topSize.height, size.width - leftSize.width - rightSize.width, size.height - topSize.height - bottomSize.height);
+ }
+ else {
+ myLayeredPane.setBounds(leftSize.width, topSize.height, size.width - leftSize.width - rightSize.width,
+ size.height - topSize.height - bottomSize.height);
}
}
}
@@ -188,17 +188,17 @@
/**
* Invoked when enclosed frame is being shown.
*/
- public final void addNotify(){
+ public final void addNotify() {
super.addNotify();
if (ScreenUtil.isStandardAddRemoveNotify(this)) {
- UISettings.getInstance().addUISettingsListener(myUISettingsListener,myDisposable);
+ UISettings.getInstance().addUISettingsListener(myUISettingsListener, myDisposable);
}
}
/**
* Invoked when enclosed frame is being disposed.
*/
- public final void removeNotify(){
+ public final void removeNotify() {
if (ScreenUtil.isStandardAddRemoveNotify(this)) {
Disposer.dispose(myDisposable);
}
@@ -212,129 +212,141 @@
/**
* Creates command which adds button into the specified tool stripe.
* Command uses copy of passed <code>info</code> object.
- * @param button button which should be added.
- * @param info window info for the corresponded tool window.
- * @param comparator which is used to sort buttons within the stripe.
+ *
+ * @param button button which should be added.
+ * @param info window info for the corresponded tool window.
+ * @param comparator which is used to sort buttons within the stripe.
* @param finishCallBack invoked when the command is completed.
*/
- final FinalizableCommand createAddButtonCmd(final StripeButton button,final WindowInfoImpl info,final Comparator<StripeButton> comparator,final Runnable finishCallBack){
- final WindowInfoImpl copiedInfo=info.copy();
+ final FinalizableCommand createAddButtonCmd(final StripeButton button,
+ final WindowInfoImpl info,
+ final Comparator<StripeButton> comparator,
+ final Runnable finishCallBack) {
+ final WindowInfoImpl copiedInfo = info.copy();
myId2Button.put(copiedInfo.getId(), button);
- myButton2Info.put(button,copiedInfo);
- return new AddToolStripeButtonCmd(button,copiedInfo,comparator,finishCallBack);
+ myButton2Info.put(button, copiedInfo);
+ return new AddToolStripeButtonCmd(button, copiedInfo, comparator, finishCallBack);
}
/**
* Creates command which shows tool window with specified set of parameters.
* Command uses cloned copy of passed <code>info</code> object.
+ *
* @param dirtyMode if <code>true</code> then JRootPane will not be validated and repainted after adding
- * the decorator. Moreover in this (dirty) mode animation doesn't work.
+ * the decorator. Moreover in this (dirty) mode animation doesn't work.
*/
final FinalizableCommand createAddDecoratorCmd(
final InternalDecorator decorator,
final WindowInfoImpl info,
final boolean dirtyMode,
final Runnable finishCallBack
- ){
- final WindowInfoImpl copiedInfo=info.copy();
- final String id=copiedInfo.getId();
+ ) {
+ final WindowInfoImpl copiedInfo = info.copy();
+ final String id = copiedInfo.getId();
- myDecorator2Info.put(decorator,copiedInfo);
- myId2Decorator.put(id,decorator);
-
- if(info.isDocked()){
+ myDecorator2Info.put(decorator, copiedInfo);
+ myId2Decorator.put(id, decorator);
+
+ if (info.isDocked()) {
WindowInfoImpl sideInfo = getDockedInfoAt(info.getAnchor(), !info.isSplit());
if (sideInfo == null) {
- return new AddDockedComponentCmd(decorator,info,dirtyMode,finishCallBack);
+ return new AddDockedComponentCmd(decorator, info, dirtyMode, finishCallBack);
}
else {
return new AddAndSplitDockedComponentCmd(decorator, info, dirtyMode, finishCallBack);
}
- } else if(info.isSliding()) {
- return new AddSlidingComponentCmd(decorator,info,dirtyMode,finishCallBack);
- }else{
- throw new IllegalArgumentException("Unknown window type: "+info.getType());
+ }
+ else if (info.isSliding()) {
+ return new AddSlidingComponentCmd(decorator, info, dirtyMode, finishCallBack);
+ }
+ else {
+ throw new IllegalArgumentException("Unknown window type: " + info.getType());
}
}
/**
* Creates command which removes tool button from tool stripe.
+ *
* @param id <code>ID</code> of the button to be removed.
*/
- final FinalizableCommand createRemoveButtonCmd(final String id,final Runnable finishCallBack){
- final StripeButton button=getButtonById(id);
- final WindowInfoImpl info=getButtonInfoById(id);
+ final FinalizableCommand createRemoveButtonCmd(final String id, final Runnable finishCallBack) {
+ final StripeButton button = getButtonById(id);
+ final WindowInfoImpl info = getButtonInfoById(id);
//
myButton2Info.remove(button);
myId2Button.remove(id);
- return new RemoveToolStripeButtonCmd(button,info,finishCallBack);
+ return new RemoveToolStripeButtonCmd(button, info, finishCallBack);
}
/**
* Creates command which hides tool window with specified set of parameters.
+ *
* @param dirtyMode if <code>true</code> then JRootPane will not be validated and repainted after removing
- * the decorator. Moreover in this (dirty) mode animation doesn't work.
+ * the decorator. Moreover in this (dirty) mode animation doesn't work.
*/
- final FinalizableCommand createRemoveDecoratorCmd(final String id, final boolean dirtyMode, final Runnable finishCallBack){
- final Component decorator=getDecoratorById(id);
- final WindowInfoImpl info=getDecoratorInfoById(id);
+ final FinalizableCommand createRemoveDecoratorCmd(final String id, final boolean dirtyMode, final Runnable finishCallBack) {
+ final Component decorator = getDecoratorById(id);
+ final WindowInfoImpl info = getDecoratorInfoById(id);
myDecorator2Info.remove(decorator);
myId2Decorator.remove(id);
WindowInfoImpl sideInfo = getDockedInfoAt(info.getAnchor(), !info.isSplit());
- if(info.isDocked()){
+ if (info.isDocked()) {
if (sideInfo == null) {
- return new RemoveDockedComponentCmd(info,dirtyMode,finishCallBack);
+ return new RemoveDockedComponentCmd(info, dirtyMode, finishCallBack);
}
else {
return new RemoveSplitAndDockedComponentCmd(info, dirtyMode, finishCallBack);
}
- }else if(info.isSliding()){
- return new RemoveSlidingComponentCmd(decorator,info,dirtyMode,finishCallBack);
- }else{
+ }
+ else if (info.isSliding()) {
+ return new RemoveSlidingComponentCmd(decorator, info, dirtyMode, finishCallBack);
+ }
+ else {
throw new IllegalArgumentException("Unknown window type");
}
}
/**
* Creates command which sets specified document component.
+ *
* @param component component to be set.
*/
- final FinalizableCommand createSetEditorComponentCmd(final JComponent component,final Runnable finishCallBack){
- return new SetEditorComponentCmd(component,finishCallBack);
+ final FinalizableCommand createSetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) {
+ return new SetEditorComponentCmd(component, finishCallBack);
}
final FinalizableCommand createUpdateButtonPositionCmd(String id, final Runnable finishCallback) {
return new UpdateButtonPositionCmd(id, finishCallback);
}
- final JComponent getMyLayeredPane(){
+ final JComponent getMyLayeredPane() {
return myLayeredPane;
}
- private StripeButton getButtonById(final String id){
+ private StripeButton getButtonById(final String id) {
return myId2Button.get(id);
}
- private Component getDecoratorById(final String id){
+ private Component getDecoratorById(final String id) {
return myId2Decorator.get(id);
}
/**
- * @return <code>WindowInfo</code> associated with specified tool stripe button.
* @param id <code>ID</code> of tool stripe butoon.
+ * @return <code>WindowInfo</code> associated with specified tool stripe button.
*/
- private WindowInfoImpl getButtonInfoById(final String id){
+ private WindowInfoImpl getButtonInfoById(final String id) {
return myButton2Info.get(myId2Button.get(id));
}
/**
- * @return <code>WindowInfo</code> associated with specified window decorator.
* @param id <code>ID</code> of decorator.
+ * @return <code>WindowInfo</code> associated with specified window decorator.
*/
- private WindowInfoImpl getDecoratorInfoById(final String id){
+ private WindowInfoImpl getDecoratorInfoById(final String id) {
return myDecorator2Info.get(myId2Decorator.get(id));
}
@@ -342,20 +354,24 @@
* Sets (docks) specified component to the specified anchor.
*/
private void setComponent(final JComponent component, final ToolWindowAnchor anchor, final float weight) {
- if(ToolWindowAnchor.TOP==anchor){
+ if (ToolWindowAnchor.TOP == anchor) {
myVerticalSplitter.setFirstComponent(component);
myVerticalSplitter.setFirstSize((int)(myLayeredPane.getHeight() * weight));
- }else if(ToolWindowAnchor.LEFT==anchor){
+ }
+ else if (ToolWindowAnchor.LEFT == anchor) {
myHorizontalSplitter.setFirstComponent(component);
myHorizontalSplitter.setFirstSize((int)(myLayeredPane.getWidth() * weight));
- }else if(ToolWindowAnchor.BOTTOM==anchor){
+ }
+ else if (ToolWindowAnchor.BOTTOM == anchor) {
myVerticalSplitter.setLastComponent(component);
myVerticalSplitter.setLastSize((int)(myLayeredPane.getHeight() * weight));
- }else if(ToolWindowAnchor.RIGHT==anchor){
+ }
+ else if (ToolWindowAnchor.RIGHT == anchor) {
myHorizontalSplitter.setLastComponent(component);
myHorizontalSplitter.setLastSize((int)(myLayeredPane.getWidth() * weight));
- }else{
- LOG.error("unknown anchor: "+anchor);
+ }
+ else {
+ LOG.error("unknown anchor: " + anchor);
}
}
@@ -366,10 +382,10 @@
else if (ToolWindowAnchor.LEFT == anchor) {
return myHorizontalSplitter.getFirstComponent();
}
- else if (ToolWindowAnchor.BOTTOM == anchor){
+ else if (ToolWindowAnchor.BOTTOM == anchor) {
return myVerticalSplitter.getLastComponent();
}
- else if (ToolWindowAnchor.RIGHT == anchor){
+ else if (ToolWindowAnchor.RIGHT == anchor) {
return myHorizontalSplitter.getLastComponent();
}
else {
@@ -393,11 +409,11 @@
return null;
}
- public void setDocumentComponent(final JComponent component){
+ public void setDocumentComponent(final JComponent component) {
(myWidescreen ? myVerticalSplitter : myHorizontalSplitter).setInnerComponent(component);
}
- private void updateToolStripesVisibility(){
+ private void updateToolStripesVisibility() {
boolean oldVisible = myLeftStripe.isVisible();
final boolean showButtons = !UISettings.getInstance().HIDE_TOOL_STRIPES && !UISettings.getInstance().PRESENTATION_MODE;
@@ -416,8 +432,8 @@
if (oldVisible != visible) {
- revalidate();
- repaint();
+ revalidate();
+ repaint();
}
}
@@ -425,11 +441,14 @@
final ToolWindowAnchor anchor = myManager.getToolWindow(id).getAnchor();
if (ToolWindowAnchor.TOP == anchor) {
return myTopStripe;
- } else if (ToolWindowAnchor.BOTTOM == anchor) {
+ }
+ else if (ToolWindowAnchor.BOTTOM == anchor) {
return myBottomStripe;
- } else if (ToolWindowAnchor.LEFT == anchor) {
+ }
+ else if (ToolWindowAnchor.LEFT == anchor) {
return myLeftStripe;
- } else if (ToolWindowAnchor.RIGHT == anchor) {
+ }
+ else if (ToolWindowAnchor.RIGHT == anchor) {
return myRightStripe;
}
@@ -481,9 +500,14 @@
if (cmp != null) {
if (wnd.getAnchor().isHorizontal()) {
- resizer = myVerticalSplitter.getFirstComponent() == cmp ? new Resizer.Splitter.FirstComponent(myVerticalSplitter) : new Resizer.Splitter.LastComponent(myVerticalSplitter);
- } else {
- resizer = myHorizontalSplitter.getFirstComponent() == cmp ? new Resizer.Splitter.FirstComponent(myHorizontalSplitter) : new Resizer.Splitter.LastComponent(myHorizontalSplitter);
+ resizer = myVerticalSplitter.getFirstComponent() == cmp
+ ? new Resizer.Splitter.FirstComponent(myVerticalSplitter)
+ : new Resizer.Splitter.LastComponent(myVerticalSplitter);
+ }
+ else {
+ resizer = myHorizontalSplitter.getFirstComponent() == cmp
+ ? new Resizer.Splitter.FirstComponent(myHorizontalSplitter)
+ : new Resizer.Splitter.LastComponent(myHorizontalSplitter);
}
}
}
@@ -497,11 +521,14 @@
if (cmp != null) {
if (wnd.getAnchor() == ToolWindowAnchor.TOP) {
resizer = new Resizer.LayeredPane.Top(cmp);
- } else if (wnd.getAnchor() == ToolWindowAnchor.BOTTOM) {
+ }
+ else if (wnd.getAnchor() == ToolWindowAnchor.BOTTOM) {
resizer = new Resizer.LayeredPane.Bottom(cmp);
- } else if (wnd.getAnchor() == ToolWindowAnchor.LEFT) {
+ }
+ else if (wnd.getAnchor() == ToolWindowAnchor.LEFT) {
resizer = new Resizer.LayeredPane.Left(cmp);
- } else if (wnd.getAnchor() == ToolWindowAnchor.RIGHT) {
+ }
+ else if (wnd.getAnchor() == ToolWindowAnchor.RIGHT) {
resizer = new Resizer.LayeredPane.Right(cmp);
}
}
@@ -513,7 +540,8 @@
int actualSize = currentValue + value;
- int minValue = wnd.getAnchor().isHorizontal() ? ((ToolWindowEx)wnd).getDecorator().getHeaderHeight() : 16 + myHorizontalSplitter.getDividerWidth();
+ int minValue =
+ wnd.getAnchor().isHorizontal() ? ((ToolWindowEx)wnd).getDecorator().getHeaderHeight() : 16 + myHorizontalSplitter.getDividerWidth();
int maxValue = wnd.getAnchor().isHorizontal() ? myLayeredPane.getHeight() : myLayeredPane.getWidth();
@@ -550,7 +578,9 @@
Splitter splitter = (Splitter)component;
InternalDecorator first = (InternalDecorator)splitter.getFirstComponent();
InternalDecorator second = (InternalDecorator)splitter.getSecondComponent();
- setComponent(splitter, ToolWindowAnchor.LEFT, ToolWindowAnchor.LEFT.isSplitVertically() ? first.getWindowInfo().getWeight() : first.getWindowInfo().getWeight() + second.getWindowInfo().getWeight());
+ setComponent(splitter, ToolWindowAnchor.LEFT, ToolWindowAnchor.LEFT.isSplitVertically()
+ ? first.getWindowInfo().getWeight()
+ : first.getWindowInfo().getWeight() + second.getWindowInfo().getWeight());
}
myLeftHorizontalSplit = UISettings.getInstance().LEFT_HORIZONTAL_SPLIT;
}
@@ -560,7 +590,9 @@
Splitter splitter = (Splitter)component;
InternalDecorator first = (InternalDecorator)splitter.getFirstComponent();
InternalDecorator second = (InternalDecorator)splitter.getSecondComponent();
- setComponent(splitter, ToolWindowAnchor.RIGHT, ToolWindowAnchor.RIGHT.isSplitVertically() ? first.getWindowInfo().getWeight() : first.getWindowInfo().getWeight() + second.getWindowInfo().getWeight());
+ setComponent(splitter, ToolWindowAnchor.RIGHT, ToolWindowAnchor.RIGHT.isSplitVertically()
+ ? first.getWindowInfo().getWeight()
+ : first.getWindowInfo().getWeight() + second.getWindowInfo().getWeight());
}
myRightHorizontalSplit = UISettings.getInstance().RIGHT_HORIZONTAL_SPLIT;
}
@@ -668,27 +700,31 @@
}
}
- private final class AddDockedComponentCmd extends FinalizableCommand{
+ private final class AddDockedComponentCmd extends FinalizableCommand {
private final JComponent myComponent;
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
- public AddDockedComponentCmd(final JComponent component, final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack){
+ public AddDockedComponentCmd(final JComponent component,
+ final WindowInfoImpl info,
+ final boolean dirtyMode,
+ final Runnable finishCallBack) {
super(finishCallBack);
- myComponent=component;
- myInfo=info;
- myDirtyMode=dirtyMode;
+ myComponent = component;
+ myInfo = info;
+ myDirtyMode = dirtyMode;
}
- public final void run(){
- try{
+ public final void run() {
+ try {
final ToolWindowAnchor anchor = myInfo.getAnchor();
setComponent(myComponent, anchor, normalizeWeigh(myInfo.getWeight()));
- if(!myDirtyMode){
+ if (!myDirtyMode) {
myLayeredPane.validate();
myLayeredPane.repaint();
}
- }finally{
+ }
+ finally {
finish();
}
}
@@ -700,7 +736,7 @@
private final boolean myDirtyMode;
private AddAndSplitDockedComponentCmd(final JComponent newComponent,
- final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) {
+ final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) {
super(finishCallBack);
myNewComponent = newComponent;
myInfo = info;
@@ -758,7 +794,7 @@
}
});
}
- InternalDecorator oldComponent = (InternalDecorator) getComponentAt(anchor);
+ InternalDecorator oldComponent = (InternalDecorator)getComponentAt(anchor);
if (myInfo.isSplit()) {
splitter.setFirstComponent(oldComponent);
splitter.setSecondComponent(myNewComponent);
@@ -769,7 +805,8 @@
splitter.setProportion(proportion);
if (!anchor.isHorizontal() && !anchor.isSplitVertically()) {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight() + myInfo.getWeight());
- } else {
+ }
+ else {
newWeight = normalizeWeigh(oldComponent.getWindowInfo().getWeight());
}
}
@@ -786,168 +823,159 @@
}
setComponent(splitter, anchor, newWeight);
- if(!myDirtyMode){
+ if (!myDirtyMode) {
myLayeredPane.validate();
myLayeredPane.repaint();
}
- } finally {
+ }
+ finally {
finish();
}
}
-
}
- private final class AddSlidingComponentCmd extends FinalizableCommand{
+ private final class AddSlidingComponentCmd extends FinalizableCommand {
private final Component myComponent;
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
- public AddSlidingComponentCmd(final Component component, final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack){
+ public AddSlidingComponentCmd(final Component component,
+ final WindowInfoImpl info,
+ final boolean dirtyMode,
+ final Runnable finishCallBack) {
super(finishCallBack);
- myComponent=component;
- myInfo=info;
- myDirtyMode=dirtyMode;
+ myComponent = component;
+ myInfo = info;
+ myDirtyMode = dirtyMode;
}
- public final void run(){
- try{
- // Show component.
- final UISettings uiSettings=UISettings.getInstance();
- if(!myDirtyMode && uiSettings.ANIMATE_WINDOWS && !UISettings.isRemoteDesktopConnected()){
- // Prepare top image. This image is scrolling over bottom image.
- final Image topImage=myLayeredPane.getTopImage();
- final Graphics topGraphics=topImage.getGraphics();
-
- Rectangle bounds;
-
- try{
- myLayeredPane.add(myComponent,JLayeredPane.PALETTE_LAYER);
- myLayeredPane.moveToFront(myComponent);
- myLayeredPane.setBoundsInPaletteLayer(myComponent,myInfo.getAnchor(),myInfo.getWeight());
- bounds=myComponent.getBounds();
- myComponent.paint(topGraphics);
- myLayeredPane.remove(myComponent);
- }finally{
- topGraphics.dispose();
- }
- // Prepare bottom image.
- final Image bottomImage=myLayeredPane.getBottomImage();
- final Graphics bottomGraphics=bottomImage.getGraphics();
- try{
- bottomGraphics.setClip(0,0,bounds.width,bounds.height);
- bottomGraphics.translate(-bounds.x,-bounds.y);
- myLayeredPane.paint(bottomGraphics);
- }finally{
- bottomGraphics.dispose();
- }
- // Start animation.
- final Surface surface=new Surface(topImage,bottomImage,1,myInfo.getAnchor(),uiSettings.ANIMATION_SPEED);
- myLayeredPane.add(surface,JLayeredPane.PALETTE_LAYER);
- surface.setBounds(bounds);
- myLayeredPane.validate();
- myLayeredPane.repaint();
-
- surface.runMovement();
- myLayeredPane.remove(surface);
- myLayeredPane.add(myComponent,JLayeredPane.PALETTE_LAYER);
- }else{ // not animated
- myLayeredPane.add(myComponent,JLayeredPane.PALETTE_LAYER);
- myLayeredPane.setBoundsInPaletteLayer(myComponent,myInfo.getAnchor(),myInfo.getWeight());
- }
- if(!myDirtyMode){
- myLayeredPane.validate();
+ public final void run() {
+ // Show component.
+ final UISettings uiSettings = UISettings.getInstance();
+ if (!myDirtyMode && uiSettings.ANIMATE_WINDOWS && !UISettings.isRemoteDesktopConnected()) {
+ myLayeredPane.add(myComponent, JLayeredPane.PALETTE_LAYER);
+ myLayeredPane.moveToFront(myComponent);
+ myLayeredPane.setBoundsInPaletteLayer(myComponent, myInfo.getAnchor(), myInfo.getWeight());
+ final FadeInFadeOut fadeIn = new FadeInFadeOut(myComponent, 250, true, myId2Button.get(myInfo.getId()));
+ add(fadeIn, FadeInFadeOut.LAYER);
+ fadeIn.setBounds(0, 0, getWidth(), getHeight());
+ myLayeredPane.remove(myComponent);
+ fadeIn.doAnimation();
+ remove(fadeIn);
+ myLayeredPane.add(myComponent, JLayeredPane.PALETTE_LAYER);
+ repaint();
+ finish();
+ }
+ else { // not animated
+ myLayeredPane.add(myComponent, JLayeredPane.PALETTE_LAYER);
+ myLayeredPane.setBoundsInPaletteLayer(myComponent, myInfo.getAnchor(), myInfo.getWeight());
+ if (!myDirtyMode) {
+ myLayeredPane.revalidate();
myLayeredPane.repaint();
}
- }finally{
finish();
}
}
}
- private final class AddToolStripeButtonCmd extends FinalizableCommand{
+ private final class AddToolStripeButtonCmd extends FinalizableCommand {
private final StripeButton myButton;
private final WindowInfoImpl myInfo;
private final Comparator<StripeButton> myComparator;
- public AddToolStripeButtonCmd(final StripeButton button,final WindowInfoImpl info,final Comparator<StripeButton> comparator,final Runnable finishCallBack){
+ public AddToolStripeButtonCmd(final StripeButton button,
+ final WindowInfoImpl info,
+ final Comparator<StripeButton> comparator,
+ final Runnable finishCallBack) {
super(finishCallBack);
- myButton=button;
- myInfo=info;
- myComparator=comparator;
+ myButton = button;
+ myInfo = info;
+ myComparator = comparator;
}
- public final void run(){
- try{
- final ToolWindowAnchor anchor=myInfo.getAnchor();
- if(ToolWindowAnchor.TOP==anchor){
- myTopStripe.addButton(myButton,myComparator);
- }else if(ToolWindowAnchor.LEFT==anchor){
- myLeftStripe.addButton(myButton,myComparator);
- }else if(ToolWindowAnchor.BOTTOM==anchor){
- myBottomStripe.addButton(myButton,myComparator);
- }else if(ToolWindowAnchor.RIGHT==anchor){
- myRightStripe.addButton(myButton,myComparator);
- }else{
- LOG.error("unknown anchor: "+anchor);
+ public final void run() {
+ try {
+ final ToolWindowAnchor anchor = myInfo.getAnchor();
+ if (ToolWindowAnchor.TOP == anchor) {
+ myTopStripe.addButton(myButton, myComparator);
+ }
+ else if (ToolWindowAnchor.LEFT == anchor) {
+ myLeftStripe.addButton(myButton, myComparator);
+ }
+ else if (ToolWindowAnchor.BOTTOM == anchor) {
+ myBottomStripe.addButton(myButton, myComparator);
+ }
+ else if (ToolWindowAnchor.RIGHT == anchor) {
+ myRightStripe.addButton(myButton, myComparator);
+ }
+ else {
+ LOG.error("unknown anchor: " + anchor);
}
validate();
repaint();
- }finally{
+ }
+ finally {
finish();
}
}
}
- private final class RemoveToolStripeButtonCmd extends FinalizableCommand{
+ private final class RemoveToolStripeButtonCmd extends FinalizableCommand {
private final StripeButton myButton;
private final WindowInfoImpl myInfo;
- public RemoveToolStripeButtonCmd(final StripeButton button,final WindowInfoImpl info,final Runnable finishCallBack){
+ public RemoveToolStripeButtonCmd(final StripeButton button, final WindowInfoImpl info, final Runnable finishCallBack) {
super(finishCallBack);
- myButton=button;
- myInfo=info;
+ myButton = button;
+ myInfo = info;
}
- public final void run(){
- try{
- final ToolWindowAnchor anchor=myInfo.getAnchor();
- if(ToolWindowAnchor.TOP==anchor){
+ public final void run() {
+ try {
+ final ToolWindowAnchor anchor = myInfo.getAnchor();
+ if (ToolWindowAnchor.TOP == anchor) {
myTopStripe.removeButton(myButton);
- }else if(ToolWindowAnchor.LEFT==anchor){
+ }
+ else if (ToolWindowAnchor.LEFT == anchor) {
myLeftStripe.removeButton(myButton);
- }else if(ToolWindowAnchor.BOTTOM==anchor){
+ }
+ else if (ToolWindowAnchor.BOTTOM == anchor) {
myBottomStripe.removeButton(myButton);
- }else if(ToolWindowAnchor.RIGHT==anchor){
+ }
+ else if (ToolWindowAnchor.RIGHT == anchor) {
myRightStripe.removeButton(myButton);
- }else{
- LOG.error("unknown anchor: "+anchor);
+ }
+ else {
+ LOG.error("unknown anchor: " + anchor);
}
validate();
repaint();
- }finally{
+ }
+ finally {
finish();
}
}
}
- private final class RemoveDockedComponentCmd extends FinalizableCommand{
+ private final class RemoveDockedComponentCmd extends FinalizableCommand {
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
- public RemoveDockedComponentCmd(final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack){
+ public RemoveDockedComponentCmd(final WindowInfoImpl info, final boolean dirtyMode, final Runnable finishCallBack) {
super(finishCallBack);
- myInfo=info;
- myDirtyMode=dirtyMode;
+ myInfo = info;
+ myDirtyMode = dirtyMode;
}
- public final void run(){
- try{
- setComponent(null,myInfo.getAnchor(), 0);
- if(!myDirtyMode){
+ public final void run() {
+ try {
+ setComponent(null, myInfo.getAnchor(), 0);
+ if (!myDirtyMode) {
myLayeredPane.validate();
myLayeredPane.repaint();
}
- }finally{
+ }
+ finally {
finish();
}
}
@@ -967,7 +995,7 @@
public void run() {
try {
- Splitter splitter = (Splitter) getComponentAt(myInfo.getAnchor());
+ Splitter splitter = (Splitter)getComponentAt(myInfo.getAnchor());
if (myInfo.isSplit()) {
InternalDecorator component = (InternalDecorator)splitter.getFirstComponent();
@@ -975,99 +1003,71 @@
setComponent(component, myInfo.getAnchor(), component.getWindowInfo().getWeight());
}
else {
- InternalDecorator component = (InternalDecorator) splitter.getSecondComponent();
+ InternalDecorator component = (InternalDecorator)splitter.getSecondComponent();
setComponent(component, myInfo.getAnchor(), component.getWindowInfo().getWeight());
}
- if(!myDirtyMode){
+ if (!myDirtyMode) {
myLayeredPane.validate();
myLayeredPane.repaint();
}
- } finally {
+ }
+ finally {
finish();
}
}
}
-
- private final class RemoveSlidingComponentCmd extends FinalizableCommand{
+ private final class RemoveSlidingComponentCmd extends FinalizableCommand {
private final Component myComponent;
private final WindowInfoImpl myInfo;
private final boolean myDirtyMode;
- public RemoveSlidingComponentCmd(
- final Component component,
- final WindowInfoImpl info,
- final boolean dirtyMode,
- final Runnable finishCallBack
- ){
+ public RemoveSlidingComponentCmd(Component component, WindowInfoImpl info, boolean dirtyMode, Runnable finishCallBack) {
super(finishCallBack);
- myComponent=component;
- myInfo=info;
- myDirtyMode=dirtyMode;
+ myComponent = component;
+ myInfo = info;
+ myDirtyMode = dirtyMode;
}
- public final void run(){
- try{
- final UISettings uiSettings=UISettings.getInstance();
- if(!myDirtyMode && uiSettings.ANIMATE_WINDOWS && !UISettings.isRemoteDesktopConnected()){
- final Rectangle bounds=myComponent.getBounds();
- // Prepare top image. This image is scrolling over bottom image. It contains
- // picture of component is being removed.
- final Image topImage=myLayeredPane.getTopImage();
- final Graphics topGraphics=topImage.getGraphics();
- try{
- myComponent.paint(topGraphics);
- }finally{
- topGraphics.dispose();
- }
- // Prepare bottom image. This image contains picture of component that is located
- // under the component to is being removed.
- final Image bottomImage=myLayeredPane.getBottomImage();
- final Graphics bottomGraphics = bottomImage.getGraphics();
- try{
- myLayeredPane.remove(myComponent);
- bottomGraphics.clipRect(0,0,bounds.width,bounds.height);
- bottomGraphics.translate(-bounds.x,-bounds.y);
- myLayeredPane.paint(bottomGraphics);
- }finally{
- bottomGraphics.dispose();
- }
- // Remove component from the layered pane and start animation.
- final Surface surface=new Surface(topImage,bottomImage,-1,myInfo.getAnchor(),uiSettings.ANIMATION_SPEED * 2);
- myLayeredPane.add(surface,JLayeredPane.PALETTE_LAYER);
- surface.setBounds(bounds);
- myLayeredPane.validate();
- myLayeredPane.repaint();
-
- surface.runMovement();
- myLayeredPane.remove(surface);
- }else{ // not animated
- myLayeredPane.remove(myComponent);
- }
- if(!myDirtyMode){
- myLayeredPane.validate();
+ public final void run() {
+ final UISettings uiSettings = UISettings.getInstance();
+ if (!myDirtyMode && uiSettings.ANIMATE_WINDOWS && !UISettings.isRemoteDesktopConnected()) {
+ // Remove component from the layered pane and start animation.
+ final FadeInFadeOut fadeOut = new FadeInFadeOut(myComponent, 450, false, getButtonById(myInfo.getId()));
+ add(fadeOut, FadeInFadeOut.LAYER);
+ fadeOut.setBounds(0, 0, getWidth(), getHeight());
+ myLayeredPane.remove(myComponent);
+ fadeOut.doAnimation();
+ remove(fadeOut);
+ repaint();
+ finish();
+ }
+ else { // not animated
+ myLayeredPane.remove(myComponent);
+ if (!myDirtyMode) {
+ myLayeredPane.revalidate();
myLayeredPane.repaint();
}
- }finally{
finish();
}
}
}
- private final class SetEditorComponentCmd extends FinalizableCommand{
+ private final class SetEditorComponentCmd extends FinalizableCommand {
private final JComponent myComponent;
- public SetEditorComponentCmd(final JComponent component,final Runnable finishCallBack){
+ public SetEditorComponentCmd(final JComponent component, final Runnable finishCallBack) {
super(finishCallBack);
- myComponent=component;
+ myComponent = component;
}
- public void run(){
- try{
+ public void run() {
+ try {
setDocumentComponent(myComponent);
myLayeredPane.validate();
myLayeredPane.repaint();
- }finally{
+ }
+ finally {
finish();
}
}
@@ -1079,7 +1079,6 @@
private UpdateButtonPositionCmd(String id, final Runnable finishCallBack) {
super(finishCallBack);
myId = id;
-
}
public void run() {
@@ -1087,10 +1086,10 @@
WindowInfoImpl info = getButtonById(myId).getWindowInfo();
ToolWindowAnchor anchor = info.getAnchor();
- if (ToolWindowAnchor.TOP == anchor){
+ if (ToolWindowAnchor.TOP == anchor) {
myTopStripe.revalidate();
}
- else if (ToolWindowAnchor.LEFT == anchor){
+ else if (ToolWindowAnchor.LEFT == anchor) {
myLeftStripe.revalidate();
}
else if (ToolWindowAnchor.BOTTOM == anchor) {
@@ -1102,14 +1101,15 @@
else {
LOG.error("unknown anchor: " + anchor);
}
- } finally {
+ }
+ finally {
finish();
}
}
}
- private final class MyUISettingsListenerImpl implements UISettingsListener{
- public final void uiSettingsChanged(final UISettings source){
+ private final class MyUISettingsListenerImpl implements UISettingsListener {
+ public final void uiSettingsChanged(final UISettings source) {
updateToolStripesVisibility();
updateLayout();
}
@@ -1120,110 +1120,74 @@
* These images are used to perform animated showing and hiding of components.
* They are the member for performance reason.
*/
- private SoftReference<BufferedImage> myBottomImageRef;
- private SoftReference<BufferedImage> myTopImageRef;
public MyLayeredPane(final JComponent splitter) {
- myBottomImageRef=new SoftReference<BufferedImage>(null);
- myTopImageRef=new SoftReference<BufferedImage>(null);
setOpaque(false);
- add(splitter,JLayeredPane.DEFAULT_LAYER);
- }
-
- public final Image getBottomImage(){
- Pair<BufferedImage, SoftReference<BufferedImage>> result = getImage(myBottomImageRef);
- myBottomImageRef = result.second;
- return result.first;
- }
-
- public final Image getTopImage(){
- Pair<BufferedImage, SoftReference<BufferedImage>> result = getImage(myTopImageRef);
- myTopImageRef = result.second;
- return result.first;
- }
-
- private Pair<BufferedImage, SoftReference<BufferedImage>> getImage(SoftReference<BufferedImage> imageRef) {
- LOG.assertTrue(UISettings.getInstance().ANIMATE_WINDOWS);
- BufferedImage image= imageRef.get();
- if(
- image==null ||
- image.getWidth(null) < getWidth() || image.getHeight(null) < getHeight()
- ){
- final int width=Math.max(Math.max(1,getWidth()),myFrame.getWidth());
- final int height=Math.max(Math.max(1,getHeight()),myFrame.getHeight());
- if (SystemInfo.isWindows) {
- image = myFrame.getGraphicsConfiguration().createCompatibleImage(width, height);
- }
- else {
- // Under Linux we have found that images created by createCompatibleImage(),
- // createVolatileImage(), etc extremely slow for rendering. TrueColor buffered image
- // is MUCH faster.
- // On Mac we create a retina-compatible image
-
- image = UIUtil.createImage(width, height, BufferedImage.TYPE_INT_RGB);
- }
- imageRef = new SoftReference<BufferedImage>(image);
- }
- return Pair.create(image, imageRef);
+ add(splitter, JLayeredPane.DEFAULT_LAYER);
}
/**
* When component size becomes larger then bottom and top images should be enlarged.
*/
public void doLayout() {
- final int width=getWidth();
- final int height=getHeight();
- if(width<0||height<0){
- return;
+ final int width = getWidth();
+ final int height = getHeight();
+ if (width < 0 || height < 0) {
+ return;
+ }
+ // Resize component at the DEFAULT layer. It should be only on component in that layer
+ Component[] components = getComponentsInLayer(JLayeredPane.DEFAULT_LAYER.intValue());
+ LOG.assertTrue(components.length <= 1);
+ for (final Component component : components) {
+ component.setBounds(0, 0, getWidth(), getHeight());
+ }
+ // Resize components at the PALETTE layer
+ components = getComponentsInLayer(JLayeredPane.PALETTE_LAYER.intValue());
+ for (final Component component : components) {
+ if (!(component instanceof InternalDecorator)) {
+ continue;
}
- // Resize component at the DEFAULT layer. It should be only on component in that layer
- Component[] components=getComponentsInLayer(JLayeredPane.DEFAULT_LAYER.intValue());
- LOG.assertTrue(components.length<=1);
- for (final Component component : components) {
- component.setBounds(0, 0, getWidth(), getHeight());
+ final WindowInfoImpl info = myDecorator2Info.get(component);
+ // In normal situation info is not null. But sometimes Swing sends resize
+ // event to removed component. See SCR #19566.
+ if (info == null) {
+ continue;
}
- // Resize components at the PALETTE layer
- components=getComponentsInLayer(JLayeredPane.PALETTE_LAYER.intValue());
- for (final Component component : components) {
- if (!(component instanceof InternalDecorator)) {
- continue;
- }
- final WindowInfoImpl info = myDecorator2Info.get(component);
- // In normal situation info is not null. But sometimes Swing sends resize
- // event to removed component. See SCR #19566.
- if (info == null) {
- continue;
- }
- final float weight;
- if (info.getAnchor().isHorizontal()) {
- weight = (float)component.getHeight() / (float)getHeight();
- }
- else {
- weight = (float)component.getWidth() / (float)getWidth();
- }
- setBoundsInPaletteLayer(component, info.getAnchor(), weight);
+ final float weight;
+ if (info.getAnchor().isHorizontal()) {
+ weight = (float)component.getHeight() / (float)getHeight();
}
+ else {
+ weight = (float)component.getWidth() / (float)getWidth();
+ }
+ setBoundsInPaletteLayer(component, info.getAnchor(), weight);
+ }
}
- public final void setBoundsInPaletteLayer(final Component component,final ToolWindowAnchor anchor,float weight){
- if(weight<.0f){
- weight= WindowInfoImpl.DEFAULT_WEIGHT;
- }else if(weight>1.0f){
- weight=1.0f;
+ public final void setBoundsInPaletteLayer(final Component component, final ToolWindowAnchor anchor, float weight) {
+ if (weight < .0f) {
+ weight = WindowInfoImpl.DEFAULT_WEIGHT;
}
- if(ToolWindowAnchor.TOP==anchor){
- component.setBounds(0,0,getWidth(),(int)(getHeight()*weight+.5f));
- }else if(ToolWindowAnchor.LEFT==anchor){
- component.setBounds(0,0,(int)(getWidth()*weight+.5f),getHeight());
- }else if(ToolWindowAnchor.BOTTOM==anchor){
- final int height=(int)(getHeight()*weight+.5f);
- component.setBounds(0,getHeight()-height,getWidth(),height);
- }else if(ToolWindowAnchor.RIGHT==anchor){
- final int width=(int)(getWidth()*weight+.5f);
- component.setBounds(getWidth()-width,0,width,getHeight());
- }else{
- LOG.error("unknown anchor "+anchor);
+ else if (weight > 1.0f) {
+ weight = 1.0f;
+ }
+ if (ToolWindowAnchor.TOP == anchor) {
+ component.setBounds(0, 0, getWidth(), (int)(getHeight() * weight + .5f));
+ }
+ else if (ToolWindowAnchor.LEFT == anchor) {
+ component.setBounds(0, 0, (int)(getWidth() * weight + .5f), getHeight());
+ }
+ else if (ToolWindowAnchor.BOTTOM == anchor) {
+ final int height = (int)(getHeight() * weight + .5f);
+ component.setBounds(0, getHeight() - height, getWidth(), height);
+ }
+ else if (ToolWindowAnchor.RIGHT == anchor) {
+ final int width = (int)(getWidth() * weight + .5f);
+ component.setBounds(getWidth() - width, 0, width, getHeight());
+ }
+ else {
+ LOG.error("unknown anchor " + anchor);
}
}
}
@@ -1234,12 +1198,12 @@
}
@Override
- public void dispose() {
+ public void dispose() {
}
private static float normalizeWeigh(final float weight) {
if (weight <= 0) return WindowInfoImpl.DEFAULT_WEIGHT;
- if (weight >= 1 ) return 1 - WindowInfoImpl.DEFAULT_WEIGHT;
+ if (weight >= 1) return 1 - WindowInfoImpl.DEFAULT_WEIGHT;
return weight;
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java
index eafd0a0..5463b43 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowInfoImpl.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,6 +43,7 @@
static final float DEFAULT_SIDE_WEIGHT = 0.5f;
private boolean myActive;
+ @NotNull
private ToolWindowAnchor myAnchor;
private boolean myAutoHide;
/**
@@ -85,35 +86,37 @@
private boolean myWasRead;
/**
- * Creates <code>WindowInfo</code> for tool window with wpecified <code>ID</code>.
+ * Creates <code>WindowInfo</code> for tool window with specified <code>ID</code>.
*/
- WindowInfoImpl(final String id){
- myActive=false;
- myAnchor=ToolWindowAnchor.LEFT;
- myAutoHide=false;
- myFloatingBounds=null;
- myId=id;
+ WindowInfoImpl(@NotNull String id) {
+ myActive = false;
+ myAnchor = ToolWindowAnchor.LEFT;
+ myAutoHide = false;
+ myFloatingBounds = null;
+ myId = id;
setType(ToolWindowType.DOCKED);
- myVisible=false;
- myWeight=DEFAULT_WEIGHT;
+ myVisible = false;
+ myWeight = DEFAULT_WEIGHT;
mySideWeight = DEFAULT_SIDE_WEIGHT;
- myOrder=-1;
- mySplitMode =false;
+ myOrder = -1;
+ mySplitMode = false;
}
/**
* Creates copy of <code>WindowInfo</code> object.
*/
- @SuppressWarnings({"EmptyCatchBlock"})
- public WindowInfoImpl copy(){
- WindowInfoImpl info=null;
- try{
- info=(WindowInfoImpl)clone();
- if(myFloatingBounds!=null){
- info.myFloatingBounds=(Rectangle)myFloatingBounds.clone();
+ @NotNull
+ public WindowInfoImpl copy() {
+ try {
+ WindowInfoImpl info = (WindowInfoImpl)clone();
+ if (myFloatingBounds != null) {
+ info.myFloatingBounds = (Rectangle)myFloatingBounds.clone();
}
- }catch(CloneNotSupportedException ignored){}
- return info;
+ return info;
+ }
+ catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
}
/**
@@ -137,6 +140,7 @@
/**
* @return tool window's anchor in internal mode.
*/
+ @NotNull
@Override
public ToolWindowAnchor getAnchor(){
return myAnchor;
@@ -162,6 +166,7 @@
/**
* @return <code>ID</code> of the tool window.
*/
+ @NotNull
String getId(){
return myId;
}
@@ -258,6 +263,7 @@
throw new IllegalArgumentException(text);
}
+ @NotNull
private static ToolWindowAnchor parseToolWindowAnchor(final String text) {
if (ToolWindowAnchor.TOP.toString().equalsIgnoreCase(text)) {
return ToolWindowAnchor.TOP;
@@ -422,22 +428,19 @@
@SuppressWarnings({"HardCodedStringLiteral"})
public String toString(){
- final StringBuilder buffer = new StringBuilder();
- buffer.append(getClass().getName()).append('[');
- buffer.append("myId=").append(myId).append("; ");
- buffer.append("myVisible=").append(myVisible).append("; ");
- buffer.append("myActive=").append(myActive).append("; ");
- buffer.append("myAnchor=").append(myAnchor).append("; ");
- buffer.append("myOrder=").append(myOrder).append("; ");
- buffer.append("myAutoHide=").append(myAutoHide).append("; ");
- buffer.append("myWeight=").append(myWeight).append("; ");
- buffer.append("mySideWeight=").append(mySideWeight).append("; ");
- buffer.append("myType=").append(myType).append("; ");
- buffer.append("myInternalType=").append(myInternalType).append("; ");
- buffer.append("myFloatingBounds=").append(myFloatingBounds).append("; ");
- buffer.append("mySplitMode=").append(mySplitMode);
- buffer.append(']');
- return buffer.toString();
+ return getClass().getName() + "[myId=" + myId
+ + "; myVisible=" + myVisible
+ + "; myActive=" + myActive
+ + "; myAnchor=" + myAnchor
+ + "; myOrder=" + myOrder
+ + "; myAutoHide=" + myAutoHide
+ + "; myWeight=" + myWeight
+ + "; mySideWeight=" + mySideWeight
+ + "; myType=" + myType
+ + "; myInternalType=" + myInternalType
+ + "; myFloatingBounds=" + myFloatingBounds
+ + "; mySplitMode=" + mySplitMode +
+ ']';
}
public boolean wasRead() {
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java
index 4130602..0495d41 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/WindowManagerImpl.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.
@@ -93,7 +93,7 @@
}
private static final boolean ORACLE_BUG_8007219 = SystemInfo.isMac && SystemInfo.isJavaVersionAtLeast("1.7");
- private static final int ORACLE_BUG_8007219_THRESHOLD = 10;
+ private static final int ORACLE_BUG_8007219_THRESHOLD = 5;
private Boolean myAlphaModeSupported = null;
@@ -471,6 +471,9 @@
IdeFrame frame = null;
if (project != null) {
frame = project.isDefault() ? WelcomeFrame.getInstance() : getFrame(project);
+ if (frame == null) {
+ frame = myProject2Frame.get(null);
+ }
}
else {
Container eachParent = getMostRecentFocusedWindow();
@@ -554,34 +557,49 @@
private void fixForOracleBug8007219(IdeFrameImpl frame) {
if ((myFrameExtendedState & Frame.MAXIMIZED_BOTH) > 0 && ORACLE_BUG_8007219) {
- final Rectangle rect = ScreenUtil.getMainScreenBounds();
+ final Rectangle screenBounds = ScreenUtil.getMainScreenBounds();
final Insets screenInsets = ScreenUtil.getScreenInsets(frame.getGraphicsConfiguration());
+ final int leftGap = myFrameBounds.x - screenInsets.left;
- myFrameBounds.x = myFrameBounds.x - screenInsets.left > ORACLE_BUG_8007219_THRESHOLD ?
+ myFrameBounds.x = leftGap > ORACLE_BUG_8007219_THRESHOLD ?
myFrameBounds.x :
screenInsets.left + ORACLE_BUG_8007219_THRESHOLD + 1;
- myFrameBounds.y = myFrameBounds.y - screenInsets.top > ORACLE_BUG_8007219_THRESHOLD ?
+ final int topGap = myFrameBounds.y - screenInsets.top;
+
+ myFrameBounds.y = topGap > ORACLE_BUG_8007219_THRESHOLD ?
myFrameBounds.y :
screenInsets.top + ORACLE_BUG_8007219_THRESHOLD + 1;
- myFrameBounds.width = rect.width - (myFrameBounds.width + myFrameBounds.x) > ORACLE_BUG_8007219_THRESHOLD ?
- myFrameBounds.width :
- rect.width - ORACLE_BUG_8007219_THRESHOLD - 1;
+ final int maximumFrameWidth = screenBounds.width - screenInsets.right - myFrameBounds.x;
- myFrameBounds.height = rect.height - (myFrameBounds.height + myFrameBounds.y) > ORACLE_BUG_8007219_THRESHOLD ?
+ final int rightGap = maximumFrameWidth - myFrameBounds.width;
+
+ myFrameBounds.width = rightGap > ORACLE_BUG_8007219_THRESHOLD ?
+ myFrameBounds.width :
+ maximumFrameWidth - ORACLE_BUG_8007219_THRESHOLD - 1;
+
+ final int maximumFrameHeight = screenBounds.height - screenInsets.bottom - myFrameBounds.y;
+
+ final int bottomGap = maximumFrameHeight - myFrameBounds.height;
+
+ myFrameBounds.height = bottomGap > ORACLE_BUG_8007219_THRESHOLD ?
myFrameBounds.height :
- rect.height - ORACLE_BUG_8007219_THRESHOLD - 1;
+ - ORACLE_BUG_8007219_THRESHOLD - 1;
}
}
+ private IdeFrameImpl getDefaultEmptyIdeFrame() {
+ return myProject2Frame.get(null);
+ }
+
public final IdeFrameImpl allocateFrame(final Project project) {
LOG.assertTrue(!myProject2Frame.containsKey(project));
final IdeFrameImpl frame;
if (myProject2Frame.containsKey(null)) {
- frame = myProject2Frame.get(null);
+ frame = getDefaultEmptyIdeFrame();
myProject2Frame.remove(null);
myProject2Frame.put(project, frame);
frame.setProject(project);
@@ -681,6 +699,7 @@
/**
* Private part
*/
+ @NotNull
public final CommandProcessor getCommandProcessor() {
return myCommandProcessor;
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/ApplyWindowInfoCmd.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/ApplyWindowInfoCmd.java
index df8a868..27c4df1 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/ApplyWindowInfoCmd.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/commands/ApplyWindowInfoCmd.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.
@@ -28,28 +28,28 @@
* Apply <code>info</code> to the corresponded tool button and decarator.
* Command uses freezed copy of passed <code>info</code> object.
*/
-public final class ApplyWindowInfoCmd extends FinalizableCommand{
+public final class ApplyWindowInfoCmd extends FinalizableCommand {
private final WindowInfoImpl myInfo;
private final StripeButton myButton;
private final InternalDecorator myDecorator;
- public ApplyWindowInfoCmd(
- @NotNull final WindowInfoImpl info,
- @NotNull final StripeButton button,
- @NotNull final InternalDecorator decorator,
- final Runnable finishCallBack
- ){
+ public ApplyWindowInfoCmd(@NotNull final WindowInfoImpl info,
+ @NotNull final StripeButton button,
+ @NotNull final InternalDecorator decorator,
+ @NotNull Runnable finishCallBack) {
super(finishCallBack);
- myInfo=info.copy();
- myButton=button;
- myDecorator=decorator;
+ myInfo = info.copy();
+ myButton = button;
+ myDecorator = decorator;
}
- public final void run(){
- try{
+ @Override
+ public final void run() {
+ try {
myButton.apply(myInfo);
myDecorator.apply(myInfo);
- }finally{
+ }
+ finally {
finish();
}
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/EncodingPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/EncodingPanel.java
index e923b62..62c0355 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/EncodingPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/EncodingPanel.java
@@ -89,7 +89,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
update();
showPopup(e);
return true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java
index 894f50d..f9fed06 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/IdeStatusBarImpl.java
@@ -699,7 +699,7 @@
setToolTipText(presentation.getTooltipText());
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
final ListPopup popup = myPresentation.getPopupStep();
if (popup == null) return false;
final Dimension dimension = popup.getContent().getPreferredSize();
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java
index 5231808..27a476b 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.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.
@@ -168,7 +168,6 @@
setRefreshVisible(false);
InlineProgressIndicator[] indicators = getCurrentInlineIndicators().toArray(new InlineProgressIndicator[0]);
for (InlineProgressIndicator indicator : indicators) {
- System.out.println("Disposing "+indicator);
Disposer.dispose(indicator);
}
myInline2Original.clear();
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/LineSeparatorPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/LineSeparatorPanel.java
index c81ef03..03bea0d 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/LineSeparatorPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/LineSeparatorPanel.java
@@ -76,7 +76,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
update();
showPopup(e);
return true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ProcessPopup.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ProcessPopup.java
index cc50913..aadf11c 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ProcessPopup.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ProcessPopup.java
@@ -129,7 +129,6 @@
builder.setResizable(true);
builder.setTitle(IdeBundle.message("progress.window.title"));
builder.setDimensionServiceKey(null, "ProcessPopupWindow", true);
- builder.setMinSize(getMinSize());
builder.setCancelOnClickOutside(false);
builder.setRequestFocus(requestFocus);
builder.setBelongsToGlobalPopupStack(false);
@@ -138,15 +137,14 @@
builder.setCancelButton(new MinimizeButton("Hide"));
JFrame frame = (JFrame)UIUtil.findUltimateParent(myProgressPanel);
- Dimension contentSize = myRootContent.getPreferredSize();
if (frame != null) {
+ Dimension contentSize = myRootContent.getPreferredSize();
Rectangle bounds = frame.getBounds();
int width = Math.max(bounds.width / 4, contentSize.width);
int height = Math.min(bounds.height / 4, contentSize.height);
int x = (int)(bounds.getMaxX() - width);
int y = (int)(bounds.getMaxY() - height);
- builder.setMinSize(new Dimension(width, height));
myPopup = builder.createPopup();
StatusBarEx sb = (StatusBarEx)((IdeFrame)frame).getStatusBar();
@@ -154,7 +152,6 @@
y -= sb.getSize().height;
}
-
myPopup.showInScreenCoordinates(myProgressPanel.getRootPane(), new Point(x - 5, y - 5));
} else {
myPopup = builder.createPopup();
@@ -191,13 +188,6 @@
return size;
}
- private static Dimension getMinSize() {
- final Dimension size = ScreenUtil.getMainScreenBounds().getSize();
- size.width *= 0.1d;
- size.height *= 0.1d;
- return size;
- }
-
public void hide() {
if (myPopup != null) {
final JBPopup popup = myPopup;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java
index d2cb6e9..be3912f 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/StatusPanel.java
@@ -35,6 +35,7 @@
import com.intellij.ui.JBColor;
import com.intellij.util.Alarm;
import com.intellij.util.text.DateFormatUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -99,7 +100,7 @@
myTextPanel.setBorder(new EmptyBorder(0, 5, 0, 0));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (myCurrentNotification != null || myAfterClick) {
EventLog.toggleLog(getActiveProject(), myCurrentNotification);
myAfterClick = true;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java
index 68ad6d1..184f344 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/JetBrainsTvAction.java
@@ -42,6 +42,6 @@
@Override
public void actionPerformed(AnActionEvent e) {
- BrowserUtil.launchBrowser(myUrl);
+ BrowserUtil.browse(myUrl);
}
}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java
index 9e60bb2..c9f5dd3 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/NewWelcomeScreen.java
@@ -24,7 +24,7 @@
import com.intellij.openapi.application.ApplicationInfo;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
-import com.intellij.openapi.updateSettings.impl.CheckForUpdateAction;
+import com.intellij.openapi.updateSettings.impl.UpdateChecker;
import com.intellij.openapi.updateSettings.impl.UpdateSettings;
import com.intellij.openapi.util.DimensionService;
import com.intellij.openapi.util.IconLoader;
@@ -93,7 +93,7 @@
footerPanel.add(makeSmallFont(new LinkLabel("Check", null, new LinkListener() {
@Override
public void linkSelected(LinkLabel aSource, Object aLinkData) {
- CheckForUpdateAction.actionPerformed(null, true, null, UpdateSettings.getInstance());
+ UpdateChecker.updateAndShowResult(null, false, null, UpdateSettings.getInstance());
}
})));
footerPanel.add(makeSmallFont(new JLabel(" for updates now.")));
@@ -108,7 +108,7 @@
private static JPanel createHeaderPanel() {
JPanel header = new JPanel(new BorderLayout());
JLabel welcome = new JLabel("Welcome to " + ApplicationNamesInfo.getInstance().getFullProductName(),
- IconLoader.getIcon(ApplicationInfoEx.getInstanceEx().getWelcomeScreenLogoUrl()),
+ IconLoader.getIcon(ApplicationInfoEx.getInstanceEx().getWelcomeScreenLogoUrl()),
SwingConstants.LEFT);
welcome.setBorder(new EmptyBorder(10, 15, 10, 15));
welcome.setFont(welcome.getFont().deriveFont((float) 32));
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
index 76d9e2c..9140fc2 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/welcomeScreen/RecentProjectPanel.java
@@ -67,7 +67,7 @@
new ClickListener(){
@Override
- public boolean onClick(MouseEvent event, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent event, int clickCount) {
int selectedIndex = myList.getSelectedIndex();
if (selectedIndex >= 0) {
if (myList.getCellBounds(selectedIndex, selectedIndex).contains(event.getPoint())) {
@@ -111,7 +111,7 @@
"' from recent projects list?",
"Remove Recent Project",
Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.OK) {
final RecentProjectsManagerBase manager = RecentProjectsManagerBase.getInstance();
for (Object projectAction : selection) {
manager.removePath(((ReopenProjectAction)projectAction).getProjectPath());
diff --git a/platform/platform-impl/src/com/intellij/patterns/compiler/PatternCompilerImpl.java b/platform/platform-impl/src/com/intellij/patterns/compiler/PatternCompilerImpl.java
index 4690ba5..8606560 100644
--- a/platform/platform-impl/src/com/intellij/patterns/compiler/PatternCompilerImpl.java
+++ b/platform/platform-impl/src/com/intellij/patterns/compiler/PatternCompilerImpl.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,6 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Stack;
import com.intellij.util.containers.StringInterner;
@@ -100,7 +99,7 @@
private static Set<Method> getStaticMethods(List<Class> patternClasses) {
return new THashSet<Method>(ContainerUtil.concat(patternClasses, new Function<Class, Collection<? extends Method>>() {
public Collection<Method> fun(final Class aClass) {
- return ContainerUtil.findAll(ReflectionCache.getMethods(aClass), new Condition<Method>() {
+ return ContainerUtil.findAll(aClass.getMethods(), new Condition<Method>() {
public boolean value(final Method method) {
return Modifier.isStatic(method.getModifiers())
&& Modifier.isPublic(method.getModifiers())
diff --git a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java
index e3a926a..33b26e8 100644
--- a/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java
+++ b/platform/platform-impl/src/com/intellij/platform/NewDirectoryProjectAction.java
@@ -21,7 +21,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.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
@@ -79,7 +78,7 @@
"The directory '" + location +
"' is not empty. Would you like to create a project from existing sources instead?",
"Create New Project", Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
return PlatformProjectOpenProcessor.getInstance().doOpenProject(baseDir, null, false);
}
}
diff --git a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java
index ab45d39..0e10875 100644
--- a/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java
+++ b/platform/platform-impl/src/com/intellij/platform/PlatformProjectOpenProcessor.java
@@ -32,6 +32,8 @@
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ToolWindowManager;
import com.intellij.openapi.wm.impl.welcomeScreen.WelcomeFrame;
@@ -43,6 +45,7 @@
import javax.swing.*;
import java.io.File;
+import java.io.IOException;
/**
* @author max
@@ -94,6 +97,9 @@
@Nullable ProjectOpenedCallback callback,
final boolean isReopen) {
VirtualFile baseDir = virtualFile;
+ boolean dummyProject = false;
+ String dummyProjectName = null;
+
if (!baseDir.isDirectory()) {
baseDir = virtualFile.getParent();
while (baseDir != null) {
@@ -102,8 +108,18 @@
}
baseDir = baseDir.getParent();
}
- if (baseDir == null) {
- baseDir = virtualFile.getParent();
+ if (baseDir == null) { // no reasonable directory -> create new temp one or use parent
+ if (Registry.is("ide.open.file.in.temp.project.dir")) {
+ try {
+ dummyProjectName = virtualFile.getPath();
+ File directory = FileUtil.createTempDirectory(dummyProjectName, null, true);
+ baseDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(directory);
+ dummyProject = true;
+ } catch (IOException ex) {
+ LOG.error(ex);
+ }
+ }
+ if (baseDir == null) baseDir = virtualFile.getParent();
}
}
@@ -167,12 +183,13 @@
}
if (project == null) {
- project = projectManager.newProject(projectDir.getParentFile().getName(), projectDir.getParent(), true, false);
+ String projectName = dummyProject ? dummyProjectName : projectDir.getParentFile().getName();
+ project = projectManager.newProject(projectName, projectDir.getParent(), true, dummyProject);
}
if (project == null) return null;
ProjectBaseDirectory.getInstance(project).setBaseDir(baseDir);
- final Module module = runConfigurators ? runDirectoryProjectConfigurators(baseDir, project) : null;
+ final Module module = runConfigurators ? runDirectoryProjectConfigurators(baseDir, project) : ModuleManager.getInstance(project).getModules()[0];
openFileFromCommandLine(project, virtualFile, line);
if (!projectManager.openProject(project)) {
@@ -187,7 +204,7 @@
return project;
}
- if (callback != null && runConfigurators) {
+ if (callback != null) {
callback.projectOpened(project, module);
}
diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectTemplateEP.java b/platform/platform-impl/src/com/intellij/platform/ProjectTemplateEP.java
index b91a09b..314cd74 100644
--- a/platform/platform-impl/src/com/intellij/platform/ProjectTemplateEP.java
+++ b/platform/platform-impl/src/com/intellij/platform/ProjectTemplateEP.java
@@ -33,4 +33,6 @@
@Attribute("templatePath")
public String templatePath;
+ @Attribute("category")
+ public boolean category;
}
diff --git a/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java b/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java
index ec17fd4..cb66ab0 100644
--- a/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java
+++ b/platform/platform-impl/src/com/intellij/platform/ProjectTemplatesFactory.java
@@ -45,4 +45,8 @@
public int getGroupWeight(String group) {
return 0;
}
+
+ public String getParentGroup(String group) {
+ return null;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/platform/WebProjectGenerator.java b/platform/platform-impl/src/com/intellij/platform/WebProjectGenerator.java
index ec58890..94f09af 100644
--- a/platform/platform-impl/src/com/intellij/platform/WebProjectGenerator.java
+++ b/platform/platform-impl/src/com/intellij/platform/WebProjectGenerator.java
@@ -98,6 +98,7 @@
@NotNull
T getSettings();
+ // null if ok
@Nullable
ValidationInfo validate();
diff --git a/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java
index 9a52a56..2367e4d 100644
--- a/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java
+++ b/platform/platform-impl/src/com/intellij/psi/impl/UrlPsiReference.java
@@ -38,7 +38,7 @@
@Override
public void navigate(boolean requestFocus) {
- BrowserUtil.launchBrowser(getValue());
+ BrowserUtil.browse(getValue());
}
};
}
diff --git a/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java b/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java
index 9d28881..a62832a 100644
--- a/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/psi/statistics/impl/StatisticsManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -138,11 +138,9 @@
private StatisticsUnit getUnit(int unitNumber) {
SoftReference ref = myUnits[unitNumber];
- if (ref != null){
- StatisticsUnit unit = (StatisticsUnit)ref.get();
- if (unit != null) return unit;
- }
- StatisticsUnit unit = loadUnit(unitNumber);
+ StatisticsUnit unit = (StatisticsUnit)SoftReference.dereference(ref);
+ if (unit != null) return unit;
+ unit = loadUnit(unitNumber);
if (unit == null){
unit = new StatisticsUnit(unitNumber);
}
diff --git a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
index 8cc9b3d..c3ba3a3 100644
--- a/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/AbstractExpandableItemsHandler.java
@@ -207,7 +207,7 @@
if (selected == null
|| !myComponent.isShowing()
- || (!myComponent.isFocusOwner() && !processIfUnfocused)
+ || !myComponent.isFocusOwner() && !processIfUnfocused
|| isPopup()) {
hideHint();
return;
@@ -333,7 +333,7 @@
if (isPaintBorder()) {
- g.translate((visibleRect.x + visibleRect.width - cellBounds.x), 0);
+ g.translate(visibleRect.x + visibleRect.width - cellBounds.x, 0);
g.setColor(getBorderColor());
int rightX = size.width - 1;
final int h = size.height;
diff --git a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
index c0bfb6f..ff99bf2 100644
--- a/platform/platform-impl/src/com/intellij/ui/AppUIUtil.java
+++ b/platform/platform-impl/src/com/intellij/ui/AppUIUtil.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.
@@ -34,7 +34,9 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import java.awt.*;
+import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
@@ -54,7 +56,7 @@
@SuppressWarnings({"UnnecessaryFullyQualifiedName", "deprecation"})
private static List<Image> getAppIconImages() {
ApplicationInfoEx appInfo = ApplicationInfoImpl.getShadowInstance();
- List<Image> images = ContainerUtil.newArrayListWithExpectedSize(3);
+ List<Image> images = ContainerUtil.newArrayListWithCapacity(3);
if (SystemInfo.isXWindow) {
String bigIconUrl = appInfo.getBigIconUrl();
@@ -120,7 +122,7 @@
if ("true".equals(System.getProperty("idea.debug.mode"))) {
wmClass += "-debug";
}
- return PlatformUtils.isCommunity() ? wmClass + "-ce" : wmClass;
+ return PlatformUtils.isIdeaCommunity() ? wmClass + "-ce" : wmClass;
}
public static void registerBundledFonts() {
@@ -163,4 +165,43 @@
}
});
}
+
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * to remove in IDEA 14
+ */
+ public static JTextField createUndoableTextField() {
+ return GuiUtils.createUndoableTextField();
+ }
+
+ private static final int MIN_ICON_SIZE = 32;
+
+ @Nullable
+ public static String findIcon(final String iconsPath) {
+ final File iconsDir = new File(iconsPath);
+
+ // 1. look for .svg icon
+ for (String child : iconsDir.list()) {
+ if (child.endsWith(".svg")) {
+ return iconsPath + '/' + child;
+ }
+ }
+
+ // 2. look for .png icon of max size
+ int max = 0;
+ String iconPath = null;
+ for (String child : iconsDir.list()) {
+ if (!child.endsWith(".png")) continue;
+ final String path = iconsPath + '/' + child;
+ final Icon icon = new ImageIcon(path);
+ final int size = icon.getIconHeight();
+ if (size >= MIN_ICON_SIZE && size > max && size == icon.getIconWidth()) {
+ max = size;
+ iconPath = path;
+ }
+ }
+
+ return iconPath;
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
index 42a7e92..ac59758 100644
--- a/platform/platform-impl/src/com/intellij/ui/BalloonImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/BalloonImpl.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.
@@ -41,9 +41,9 @@
import com.intellij.ui.components.panels.Wrapper;
import com.intellij.util.Alarm;
import com.intellij.util.IJSwingUtilities;
-import com.intellij.util.Range;
import com.intellij.util.containers.HashSet;
import com.intellij.util.ui.*;
+import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -60,12 +60,7 @@
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
-import static java.awt.event.KeyEvent.KEY_PRESSED;
-import static java.awt.event.MouseEvent.MOUSE_CLICKED;
-import static java.awt.event.MouseEvent.MOUSE_PRESSED;
-
-public class BalloonImpl implements Balloon, IdeTooltip.Ui, SwingConstants {
-
+public class BalloonImpl implements Balloon, IdeTooltip.Ui {
public static final int DIALOG_ARC = 6;
public static final int ARC = 3;
public static final int DIALOG_TOPBOTTOM_POINTER_WIDTH = 24;
@@ -101,20 +96,21 @@
private CloseButton myCloseRec;
private final AWTEventListener myAwtActivityListener = new AWTEventListener() {
+ @Override
public void eventDispatched(final AWTEvent e) {
final int id = e.getID();
if (e instanceof MouseEvent) {
final MouseEvent me = (MouseEvent)e;
final boolean insideBalloon = isInsideBalloon(me);
- if (myHideOnMouse && id == MOUSE_PRESSED) {
+ if (myHideOnMouse && id == MouseEvent.MOUSE_PRESSED) {
if (!insideBalloon && !hasModalDialog(me)) {
hide();
}
return;
}
- if (myClickHandler != null && id == MOUSE_CLICKED) {
+ if (myClickHandler != null && id == MouseEvent.MOUSE_CLICKED) {
if (!(me.getComponent() instanceof CloseButton) && insideBalloon) {
myClickHandler.actionPerformed(new ActionEvent(BalloonImpl.this, ActionEvent.ACTION_PERFORMED, "click", me.getModifiersEx()));
if (myCloseOnClick) {
@@ -130,7 +126,7 @@
if (moveChanged) {
if (insideBalloon && myFadeoutAlarm.getActiveRequestCount() > 0) { //Pause hiding timer when mouse is hover
myFadeoutAlarm.cancelAllRequests();
- myFadeoutRequestDelay -= (System.currentTimeMillis() - myFadeoutRequestMillis);
+ myFadeoutRequestDelay -= System.currentTimeMillis() - myFadeoutRequestMillis;
}
if (!insideBalloon && myFadeoutRequestDelay > 0) {
startFadeoutTimer(myFadeoutRequestDelay);
@@ -145,7 +141,7 @@
}
}
- if (myHideOnKey && e instanceof KeyEvent && id == KEY_PRESSED) {
+ if (myHideOnKey && e instanceof KeyEvent && id == KeyEvent.KEY_PRESSED) {
final KeyEvent ke = (KeyEvent)e;
if (ke.getKeyCode() != KeyEvent.VK_SHIFT &&
ke.getKeyCode() != KeyEvent.VK_CONTROL &&
@@ -176,19 +172,19 @@
private boolean myFadedIn;
private boolean myFadedOut;
- private int myCalloutShift;
+ private final int myCalloutShift;
- private int myPositionChangeXShift;
- private int myPositionChangeYShift;
+ private final int myPositionChangeXShift;
+ private final int myPositionChangeYShift;
private boolean myDialogMode;
private IdeFocusManager myFocusManager;
- private String myTitle;
+ private final String myTitle;
private JLabel myTitleLabel;
private boolean myAnimationEnabled = true;
private boolean myShadow = false;
- private Layer myLayer;
- private boolean myBlockClicks;
+ private final Layer myLayer;
+ private final boolean myBlockClicks;
private RelativePoint myPrevMousePoint = null;
public boolean isInsideBalloon(MouseEvent me) {
@@ -201,7 +197,7 @@
if (!cmp.isShowing()) return true;
if (cmp == myCloseRec) return true;
- if (SwingUtilities.isDescendingFrom(cmp, myComp) || cmp == myComp) return true;
+ if (UIUtil.isDescendingFrom(cmp, myComp)) return true;
if (myComp == null || !myComp.isShowing()) return false;
Rectangle rectangleOnScreen = new Rectangle(myComp.getLocationOnScreen(), myComp.getSize());
return rectangleOnScreen.contains(target.getScreenPoint());
@@ -221,6 +217,7 @@
}
private final ComponentAdapter myComponentListener = new ComponentAdapter() {
+ @Override
public void componentResized(final ComponentEvent e) {
if (myHideOnFrameResize) {
hide();
@@ -234,13 +231,13 @@
private final JComponent myContent;
private boolean myHideOnMouse;
private final boolean myHideOnKey;
- private boolean myHideOnAction;
+ private final boolean myHideOnAction;
private final boolean myEnableCloseButton;
- public BalloonImpl(JComponent content,
- Color borderColor,
+ public BalloonImpl(@NotNull JComponent content,
+ @NotNull Color borderColor,
Insets borderInsets,
- Color fillColor,
+ @NotNull Color fillColor,
boolean hideOnMouse,
boolean hideOnKey,
boolean hideOnAction,
@@ -322,6 +319,7 @@
}
}
+ @Override
public void show(final RelativePoint target, final Balloon.Position position) {
AbstractPosition pos = getAbstractPositionFor(position);
@@ -361,6 +359,7 @@
return pos;
}
+ @Override
public void show(PositionTracker<Balloon> tracker, Balloon.Position position) {
AbstractPosition pos = BELOW;
switch (position) {
@@ -599,9 +598,7 @@
}
private void createComponent() {
- myComp = new MyComponent(myContent, this, myShowPointer
- ? myPosition.createBorder(this)
- : getPointlessBorder());
+ myComp = new MyComponent(myContent, this, myShowPointer ? myPosition.createBorder(this) : getPointlessBorder());
myCloseRec = new CloseButton();
myComp.clear();
@@ -634,15 +631,18 @@
}
+ @NotNull
private EmptyBorder getPointlessBorder() {
return new EmptyBorder(myBorderInsets);
}
+ @Override
public void revalidate() {
revalidate(myTracker);
}
- public void revalidate(PositionTracker<Balloon> tracker) {
+ @Override
+ public void revalidate(@NotNull PositionTracker<Balloon> tracker) {
RelativePoint newPosition = tracker.recalculateLocation(this);
if (newPosition != null) {
@@ -655,6 +655,7 @@
return myShadow && Registry.is("ide.balloon.shadowEnabled") ? Registry.intValue("ide.balloon.shadow.size") : 0;
}
+ @Override
public void show(JLayeredPane pane) {
show(pane, null);
}
@@ -678,9 +679,10 @@
Disposer.dispose(myAnimator);
}
myAnimator = new Animator("Balloon", 8, myAnimationEnabled ? myAnimationCycle : 0, false, forward) {
+ @Override
public void paintNow(final int frame, final int totalFrames, final int cycle) {
if (myComp == null || myComp.getParent() == null || !myAnimationEnabled) return;
- myComp.setAlpha(((float)frame) / ((float)totalFrames));
+ myComp.setAlpha((float)frame / totalFrames);
}
@Override
@@ -693,7 +695,7 @@
myFadedIn = true;
- startFadeoutTimer((int)BalloonImpl.this.myFadeoutTime);
+ startFadeoutTimer((int)myFadeoutTime);
}
else {
layeredPane.remove(myComp);
@@ -722,6 +724,7 @@
myFadeoutRequestMillis = System.currentTimeMillis();
myFadeoutRequestDelay = fadeoutDelay;
myFadeoutAlarm.addRequest(new Runnable() {
+ @Override
public void run() {
hide();
}
@@ -782,6 +785,7 @@
myDisposed = true;
final Runnable disposeRunnable = new Runnable() {
+ @Override
public void run() {
myFadedOut = true;
@@ -797,13 +801,16 @@
Toolkit.getDefaultToolkit().removeAWTEventListener(myAwtActivityListener);
if (myLayeredPane != null) {
myLayeredPane.removeComponentListener(myComponentListener);
+ Disposer.register(ApplicationManager.getApplication(), this); // to be safe if Application suddenly exits and animation wouldn't have a chance to complete
+
runAnimation(false, myLayeredPane, new Runnable() {
@Override
public void run() {
disposeRunnable.run();
}
});
- } else {
+ }
+ else {
disposeRunnable.run();
}
@@ -814,7 +821,7 @@
protected void onDisposed() { }
@Override
- public void addListener(JBPopupListener listener) {
+ public void addListener(@NotNull JBPopupListener listener) {
myListeners.add(listener);
}
@@ -835,6 +842,7 @@
return AllIcons.General.BalloonClose;
}
+ @Override
public void setBounds(Rectangle bounds) {
myForcedBounds = bounds;
if (myPosition != null) {
@@ -842,21 +850,20 @@
}
}
+ @Override
public Dimension getPreferredSize() {
if (myComp != null) {
return myComp.getPreferredSize();
- } else {
- if (myDefaultPrefSize == null) {
- final EmptyBorder border = getPointlessBorder();
- final MyComponent c = new MyComponent(myContent, this, border);
- myDefaultPrefSize = c.getPreferredSize();
- }
- return myDefaultPrefSize;
}
+ if (myDefaultPrefSize == null) {
+ final EmptyBorder border = getPointlessBorder();
+ final MyComponent c = new MyComponent(myContent, this, border);
+ myDefaultPrefSize = c.getPreferredSize();
+ }
+ return myDefaultPrefSize;
}
- public abstract static class AbstractPosition {
-
+ private abstract static class AbstractPosition {
abstract EmptyBorder createBorder(final BalloonImpl balloon);
@@ -919,9 +926,9 @@
Insets inset = getTitleInsets(getNormalInset() - 1 + shadow, balloon.getPointerLength(this) + 50 + shadow);
titleBounds.x -= inset.left + 1;
- titleBounds.width += (inset.left + inset.right + 50);
+ titleBounds.width += inset.left + inset.right + 50;
titleBounds.y -= inset.top + 1;
- titleBounds.height += (inset.top + inset.bottom + 1);
+ titleBounds.height += inset.top + inset.bottom + 1;
Area area = new Area(shape);
area.intersect(new Area(titleBounds));
@@ -962,17 +969,18 @@
int size = getDistanceToTarget(pointless, targetPoint);
if (size < pointerLength - 1) return false;
- Range<Integer> balloonRange;
- Range<Integer> pointerRange;
+ UnfairTextRange balloonRange;
+ UnfairTextRange pointerRange;
if (isTopBottomPointer()) {
- balloonRange = new Range<Integer>(bounds.x + arc, bounds.x + bounds.width - arc * 2);
- pointerRange = new Range<Integer>(targetPoint.x - pointerWidth / 2, targetPoint.x + pointerWidth / 2);
- } else {
- balloonRange = new Range<Integer>(bounds.y + arc, bounds.y + bounds.height - arc * 2);
- pointerRange = new Range<Integer>(targetPoint.y - pointerWidth / 2, targetPoint.y + pointerWidth / 2);
+ balloonRange = new UnfairTextRange(bounds.x + arc, bounds.x + bounds.width - arc * 2);
+ pointerRange = new UnfairTextRange(targetPoint.x - pointerWidth / 2, targetPoint.x + pointerWidth / 2);
+ }
+ else {
+ balloonRange = new UnfairTextRange(bounds.y + arc, bounds.y + bounds.height - arc * 2);
+ pointerRange = new UnfairTextRange(targetPoint.y - pointerWidth / 2, targetPoint.y + pointerWidth / 2);
}
- return balloonRange.isWithin(pointerRange.getFrom()) && balloonRange.isWithin(pointerRange.getTo());
+ return balloonRange.contains(pointerRange);
}
protected abstract int getDistanceToTarget(Rectangle rectangle, Point targetPoint);
@@ -1028,6 +1036,7 @@
return new Rectangle(bounds.x, bounds.y + pointerLength, bounds.width, bounds.height - pointerLength);
}
+ @Override
EmptyBorder createBorder(final BalloonImpl balloon) {
Insets insets = balloon.getInsetsCopy();
insets.top += balloon.getPointerLength(this);
@@ -1039,6 +1048,7 @@
rec.setLocation(new Point(targetPoint.x - rec.width / 2, targetPoint.y));
}
+ @Override
Point getLocation(final Dimension containerSize, final Point targetPoint, final Dimension balloonSize) {
final Point center = UIUtil.getCenterPoint(new Rectangle(targetPoint, new Dimension(0, 0)), balloonSize);
return new Point(center.x, targetPoint.y);
@@ -1049,8 +1059,9 @@
return new Insets(pointerLength, normalInset, normalInset, normalInset);
}
+ @Override
protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) {
- final Shaper shaper = new Shaper(balloon, bounds, pointTarget, TOP);
+ final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingConstants.TOP);
shaper.line(balloon.getPointerWidth(this) / 2, balloon.getPointerLength(this)).toRightCurve().roundRightDown().toBottomCurve().roundLeftDown()
.toLeftCurve().roundLeftUp().toTopCurve().roundUpRight()
.lineTo(pointTarget.x - balloon.getPointerWidth(this) / 2, shaper.getCurrent().y).lineTo(pointTarget.x, pointTarget.y);
@@ -1082,6 +1093,7 @@
return new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height - pointerLength);
}
+ @Override
EmptyBorder createBorder(final BalloonImpl balloon) {
Insets insets = balloon.getInsetsCopy();
insets.bottom = balloon.getPointerLength(this);
@@ -1093,6 +1105,7 @@
rec.setLocation(targetPoint.x - rec.width / 2, targetPoint.y - rec.height);
}
+ @Override
Point getLocation(final Dimension containerSize, final Point targetPoint, final Dimension balloonSize) {
final Point center = UIUtil.getCenterPoint(new Rectangle(targetPoint, new Dimension(0, 0)), balloonSize);
return new Point(center.x, targetPoint.y - balloonSize.height);
@@ -1105,7 +1118,7 @@
@Override
protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) {
- final Shaper shaper = new Shaper(balloon, bounds, pointTarget, BOTTOM);
+ final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingConstants.BOTTOM);
shaper.line(-balloon.getPointerWidth(this) / 2, -balloon.getPointerLength(this) + 1);
shaper.toLeftCurve().roundLeftUp().toTopCurve().roundUpRight().toRightCurve().roundRightDown().toBottomCurve().line(0, 2)
.roundLeftDown().lineTo(pointTarget.x + balloon.getPointerWidth(this) / 2, shaper.getCurrent().y).lineTo(pointTarget.x, pointTarget.y)
@@ -1138,6 +1151,7 @@
return new Rectangle(bounds.x + pointerLength, bounds.y, bounds.width - pointerLength, bounds.height);
}
+ @Override
EmptyBorder createBorder(final BalloonImpl balloon) {
Insets insets = balloon.getInsetsCopy();
insets.left += balloon.getPointerLength(this);
@@ -1149,6 +1163,7 @@
rec.setLocation(targetPoint.x, targetPoint.y - rec.height / 2);
}
+ @Override
Point getLocation(final Dimension containerSize, final Point targetPoint, final Dimension balloonSize) {
final Point center = UIUtil.getCenterPoint(new Rectangle(targetPoint, new Dimension(0, 0)), balloonSize);
return new Point(targetPoint.x, center.y);
@@ -1161,7 +1176,7 @@
@Override
protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) {
- final Shaper shaper = new Shaper(balloon, bounds, pointTarget, LEFT);
+ final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingConstants.LEFT);
shaper.line(balloon.getPointerLength(this), -balloon.getPointerWidth(this) / 2).toTopCurve().roundUpRight().toRightCurve().roundRightDown()
.toBottomCurve().roundLeftDown().toLeftCurve().roundLeftUp()
.lineTo(shaper.getCurrent().x, pointTarget.y + balloon.getPointerWidth(this) / 2).lineTo(pointTarget.x, pointTarget.y).close();
@@ -1193,6 +1208,7 @@
return new Rectangle(bounds.x, bounds.y, bounds.width - pointerLength, bounds.height);
}
+ @Override
EmptyBorder createBorder(final BalloonImpl balloon) {
Insets insets = balloon.getInsetsCopy();
insets.right += balloon.getPointerLength(this);
@@ -1204,6 +1220,7 @@
rec.setLocation(targetPoint.x - rec.width, targetPoint.y - rec.height / 2);
}
+ @Override
Point getLocation(final Dimension containerSize, final Point targetPoint, final Dimension balloonSize) {
final Point center = UIUtil.getCenterPoint(new Rectangle(targetPoint, new Dimension(0, 0)), balloonSize);
return new Point(targetPoint.x - balloonSize.width, center.y);
@@ -1216,8 +1233,8 @@
@Override
protected Shape getPointingShape(final Rectangle bounds, final Graphics2D g, final Point pointTarget, final BalloonImpl balloon) {
- final Shaper shaper = new Shaper(balloon, bounds, pointTarget, RIGHT);
- shaper.lineTo((int)bounds.getMaxX() - shaper.getTargetDelta(RIGHT) - 1, pointTarget.y + balloon.getPointerWidth(this) / 2);
+ final Shaper shaper = new Shaper(balloon, bounds, pointTarget, SwingConstants.RIGHT);
+ shaper.lineTo((int)bounds.getMaxX() - shaper.getTargetDelta(SwingConstants.RIGHT) - 1, pointTarget.y + balloon.getPointerWidth(this) / 2);
shaper.toBottomCurve().roundLeftDown().toLeftCurve().roundLeftUp().toTopCurve().roundUpRight().toRightCurve().roundRightDown()
.lineTo(shaper.getCurrent().x, pointTarget.y - balloon.getPointerWidth(this) / 2).lineTo(pointTarget.x, pointTarget.y).close();
return shaper.getShape();
@@ -1226,14 +1243,16 @@
private class CloseButton extends NonOpaquePanel {
- private BaseButtonBehavior myButton;
+ private final BaseButtonBehavior myButton;
private CloseButton() {
myButton = new BaseButtonBehavior(this, TimedDeadzone.NULL) {
+ @Override
protected void execute(MouseEvent e) {
if (!myEnableCloseButton) return;
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
BalloonImpl.this.hide();
}
@@ -1254,7 +1273,7 @@
if (getWidth() > 0 && myLastMoveWasInsideBalloon) {
final boolean pressed = myButton.isPressedByMouse();
- getCloseButton().paintIcon(this, g, (pressed ? 1 : 0), (pressed ? 1 : 0));
+ getCloseButton().paintIcon(this, g, pressed ? 1 : 0, pressed ? 1 : 0);
}
}
}
@@ -1279,7 +1298,7 @@
myContent = new JPanel(new BorderLayout(2, 2));
Wrapper contentWrapper = new Wrapper(content);
if (myTitle != null) {
- myTitleLabel = new JLabel(myTitle, CENTER);
+ myTitleLabel = new JLabel(myTitle, SwingConstants.CENTER);
myTitleLabel.setForeground(UIManager.getColor("List.background"));
myTitleLabel.setBorder(new EmptyBorder(0, 4, 0, 4));
myContent.add(myTitleLabel, BorderLayout.NORTH);
@@ -1332,8 +1351,8 @@
private Dimension addInsets(Dimension size) {
final Insets insets = getInsets();
if (insets != null) {
- size.width += (insets.left + insets.right);
- size.height += (insets.top + insets.bottom);
+ size.width += insets.left + insets.right;
+ size.height += insets.top + insets.bottom;
}
return size;
@@ -1452,10 +1471,11 @@
private final GeneralPath myPath = new GeneralPath();
Rectangle myBounds;
+ @JdkConstants.TabPlacement
private final int myTargetSide;
private final BalloonImpl myBalloon;
- public Shaper(BalloonImpl balloon, Rectangle bounds, Point targetPoint, int targetSide) {
+ public Shaper(BalloonImpl balloon, Rectangle bounds, Point targetPoint, @JdkConstants.TabPlacement int targetSide) {
myBalloon = balloon;
myBounds = bounds;
myTargetSide = targetSide;
@@ -1504,28 +1524,27 @@
return this;
}
-
- private int getTargetDelta(int effectiveSide) {
+ private int getTargetDelta(@JdkConstants.TabPlacement int effectiveSide) {
return effectiveSide == myTargetSide ? myBalloon.getPointerLength(myBalloon.myPosition) : 0;
}
public Shaper toRightCurve() {
- myPath.lineTo((int)myBounds.getMaxX() - myBalloon.getArc() - getTargetDelta(RIGHT) - 1, getCurrent().y);
+ myPath.lineTo((int)myBounds.getMaxX() - myBalloon.getArc() - getTargetDelta(SwingConstants.RIGHT) - 1, getCurrent().y);
return this;
}
public Shaper toBottomCurve() {
- myPath.lineTo(getCurrent().x, (int)myBounds.getMaxY() - myBalloon.getArc() - getTargetDelta(BOTTOM) - 1);
+ myPath.lineTo(getCurrent().x, (int)myBounds.getMaxY() - myBalloon.getArc() - getTargetDelta(SwingConstants.BOTTOM) - 1);
return this;
}
public Shaper toLeftCurve() {
- myPath.lineTo((int)myBounds.getX() + myBalloon.getArc() + getTargetDelta(LEFT), getCurrent().y);
+ myPath.lineTo((int)myBounds.getX() + myBalloon.getArc() + getTargetDelta(SwingConstants.LEFT), getCurrent().y);
return this;
}
public Shaper toTopCurve() {
- myPath.lineTo(getCurrent().x, (int)myBounds.getY() + myBalloon.getArc() + getTargetDelta(TOP));
+ myPath.lineTo(getCurrent().x, (int)myBounds.getY() + myBalloon.getArc() + getTargetDelta(SwingConstants.TOP));
return this;
}
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java b/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java
index 114b6fa..769296b 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorComboBox.java
@@ -33,6 +33,7 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -53,7 +54,7 @@
}
@Override
- public void setText(EditorComboBox component, String text) {
+ public void setText(EditorComboBox component, @NotNull String text) {
component.setText(text);
}
};
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java b/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java
index 2b9dce1..f4dfb10 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorComboBoxEditor.java
@@ -38,6 +38,7 @@
myTextField.setName(NAME);
}
+ @Override
public void selectAll() {
myTextField.selectAll();
myTextField.requestFocus();
@@ -48,18 +49,22 @@
return myTextField.getEditor();
}
+ @Override
public EditorTextField getEditorComponent() {
return myTextField;
}
+ @Override
public void addActionListener(ActionListener l) {
}
+ @Override
public void removeActionListener(ActionListener l) {
}
+ @Override
public Object getItem() {
return getDocument();
}
@@ -68,6 +73,7 @@
return myTextField.getDocument();
}
+ @Override
public void setItem(Object anObject) {
myTextField.setDocument((Document)anObject);
}
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
index 7fed54d..6664c2e 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorTextField.java
@@ -62,7 +62,7 @@
* @author max
*/
public class EditorTextField extends NonOpaquePanel implements DocumentListener, TextComponent, DataProvider,
- DocumentBasedComponent {
+ DocumentBasedComponent, FocusListener {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.EditorTextField");
public static final Key<Boolean> SUPPLEMENTARY_KEY = Key.create("Supplementary");
@@ -73,6 +73,7 @@
private Component myNextFocusable = null;
private boolean myWholeTextSelected = false;
private final List<DocumentListener> myDocumentListeners = ContainerUtil.createLockFreeCopyOnWriteList();
+ private final List<FocusListener> myFocusListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private boolean myIsListenerInstalled = false;
private boolean myIsViewer;
private boolean myIsSupplementary;
@@ -119,7 +120,7 @@
// todo[dsl,max]
setFocusable(true);
// dsl: this is a weird way of doing things....
- addFocusListener(new FocusListener() {
+ super.addFocusListener(new FocusListener() {
@Override
public void focusGained(FocusEvent e) {
requestFocus();
@@ -321,6 +322,9 @@
}
remove(editor.getComponent());
+
+ editor.getContentComponent().removeFocusListener(this);
+
final Application application = ApplicationManager.getApplication();
final Runnable runnable = new Runnable() {
@Override
@@ -522,6 +526,7 @@
editor.putUserData(SUPPLEMENTARY_KEY, myIsSupplementary);
editor.getContentComponent().setFocusCycleRoot(false);
+ editor.getContentComponent().addFocusListener(this);
editor.setPlaceholder(myHintText);
@@ -747,6 +752,30 @@
}
@Override
+ public synchronized void addFocusListener(FocusListener l) {
+ myFocusListeners.add(l);
+ }
+
+ @Override
+ public synchronized void removeFocusListener(FocusListener l) {
+ myFocusListeners.remove(l);
+ }
+
+ @Override
+ public void focusGained(FocusEvent e) {
+ for (FocusListener listener : myFocusListeners) {
+ listener.focusGained(e);
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ for (FocusListener listener : myFocusListeners) {
+ listener.focusLost(e);
+ }
+ }
+
+ @Override
public Object getData(String dataId) {
if (myEditor != null && myEditor.isRendererMode()) return null;
diff --git a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java
index 10b2cd6..36f13f0 100644
--- a/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.java
+++ b/platform/platform-impl/src/com/intellij/ui/EditorTextFieldCellRenderer.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.ui;
import com.intellij.openapi.Disposable;
@@ -186,9 +201,11 @@
@NotNull @Override public List<RangeMarker> getGuardedBlocks() { return Collections.emptyList(); }
@Override public boolean processRangeMarkers(@NotNull Processor<RangeMarker> processor) { return myRangeMarkers.process(processor); }
@Override public boolean processRangeMarkersOverlappingWith(int start, int end, @NotNull Processor<RangeMarker> processor) { return myRangeMarkers.processOverlappingWith(start, end, processor); }
+ @NotNull
@Override public String getText() { return myString; }
@NotNull @Override public String getText(@NotNull TextRange range) { return range.substring(getText()); }
@NotNull @Override public CharSequence getCharsSequence() { return myString; }
+ @NotNull @Override public CharSequence getImmutableCharSequence() { return getText(); }
@NotNull @Override public char[] getChars() { return myChars; }
@Override public int getTextLength() { return myChars.length; }
@Override public int getLineCount() { return myLineSet.findLineIndex(myChars.length) + 1; }
diff --git a/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java b/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java
deleted file mode 100644
index 1e9af99..0000000
--- a/platform/platform-impl/src/com/intellij/ui/HideableDetailsUnderSeparator.java
+++ /dev/null
@@ -1,52 +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 com.intellij.ui;
-
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.*;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 8/22/11
- * Time: 2:54 PM
- */
-public abstract class HideableDetailsUnderSeparator extends AbstractTitledSeparatorWithIcon {
- public HideableDetailsUnderSeparator(@NotNull Icon icon,
- @NotNull Icon iconOpen,
- @NotNull String text) {
- super(icon, iconOpen, text);
- }
-
- public void on() {
- initDetails();
- myLabel.setIcon(myIconOpen);
- myWrapper.add(myDetailsComponent.getPanel(), BorderLayout.CENTER);
- myOn = true;
- revalidate();
- repaint();
- }
-
- public void off() {
- myLabel.setIcon(myIcon);
- myWrapper.removeAll();
- myOn = false;
- revalidate();
- repaint();
- }
-}
diff --git a/platform/platform-impl/src/com/intellij/ui/HoverHyperlinkLabel.java b/platform/platform-impl/src/com/intellij/ui/HoverHyperlinkLabel.java
index fe7984f..59cf375 100644
--- a/platform/platform-impl/src/com/intellij/ui/HoverHyperlinkLabel.java
+++ b/platform/platform-impl/src/com/intellij/ui/HoverHyperlinkLabel.java
@@ -19,6 +19,7 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.PlatformColors;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
@@ -62,7 +63,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
HyperlinkEvent event = new HyperlinkEvent(HoverHyperlinkLabel.this, HyperlinkEvent.EventType.ACTIVATED, null);
for (HyperlinkListener listener : myListeners) {
listener.hyperlinkUpdate(event);
diff --git a/platform/platform-impl/src/com/intellij/ui/LabeledIcon.java b/platform/platform-impl/src/com/intellij/ui/LabeledIcon.java
index 994059c..79b5304 100644
--- a/platform/platform-impl/src/com/intellij/ui/LabeledIcon.java
+++ b/platform/platform-impl/src/com/intellij/ui/LabeledIcon.java
@@ -28,7 +28,7 @@
private final Icon myIcon;
private final String myMnemonic;
private final String[] myStrings;
- private int myIconTextGap = 0;
+ private int myIconTextGap = 5;
private Font myFont = UIUtil.getLabelFont();
diff --git a/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
new file mode 100644
index 0000000..fcc0f65
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/LibNotifyWrapper.java
@@ -0,0 +1,67 @@
+/*
+ * 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.ui;
+
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationGroup;
+import com.intellij.notification.NotificationType;
+import com.intellij.notification.Notifications;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.util.lang.UrlClassLoader;
+
+/**
+ * @author Denis Fokin
+ */
+public class LibNotifyWrapper {
+
+ private final static String message = "Looks like you have run 32-bit Java on a 64-bit version of OS " +
+ "or just have not installed appropriate libnotify.so library";
+
+ private static boolean available = true;
+
+ static{
+ UrlClassLoader.loadPlatformLibrary("notifywrapper");
+ }
+
+ native private static void showNotification(final String title, final String description, final String iconPath);
+
+ public static void show(final String title, final String description, final String iconPath) {
+ if (! available) return;
+ try {
+ showNotification(title, description, iconPath);
+ } catch (UnsatisfiedLinkError ule) {
+ available = false;
+ NotificationGroup.balloonGroup("Linux configuration messages");
+ Notifications.Bus.notify(
+ new Notification("Linux configuration messages",
+ "Notification library has not been installed",
+ message, NotificationType.INFORMATION)
+ );
+ }
+ }
+
+ /**
+ * Shows a libnotify notification with an icon from the ide bin directory.
+ * If there is no such icon a default information icon is shown.
+ * @param title notification title
+ * @param description notification description
+ */
+ public static void showWithAppIcon(final String title, final String description) {
+ String iconPath = AppUIUtil.findIcon(PathManager.getBinPath());
+ show(title, description, (iconPath == null) ? "dialog-information" : iconPath);
+ }
+
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java
index 63665c1..3240b3e 100644
--- a/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/SystemNotificationsImpl.java
@@ -44,6 +44,11 @@
public void notify(@NotNull String notificationName, @NotNull String title, @NotNull String text) {
if (!areNotificationsEnabled() || ApplicationManager.getApplication().isActive()) return;
+ if (SystemInfo.isLinux && Registry.is("ide.linux.gtk.notifications.enabled") ) {
+ LibNotifyWrapper.showWithAppIcon(title, text);
+ return;
+ }
+
final MacNotifications notifications;
try {
notifications = getMacNotifications();
@@ -63,14 +68,18 @@
}
private boolean areNotificationsEnabled() {
- if (myGrowlDisabled || !SystemInfo.isMac) return false;
- if (SystemInfo.isMacOSMountainLion && Registry.is("ide.mac.mountain.lion.notifications.enabled")) return true;
+ boolean enabled = false;
- if ("true".equalsIgnoreCase(System.getProperty("growl.disable"))) {
- myGrowlDisabled = true;
+ if (SystemInfo.isMac) {
+ enabled = !(myGrowlDisabled || "true".equalsIgnoreCase(System.getProperty("growl.disable")));
+ if (!enabled) {
+ enabled = SystemInfo.isMacOSMountainLion && Registry.is("ide.mac.mountain.lion.notifications.enabled");
+ }
+ } else {
+ enabled = SystemInfo.isLinux && Registry.is("ide.linux.gtk.notifications.enabled");
}
- return !myGrowlDisabled;
+ return enabled;
}
public State getState() {
diff --git a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java
index 5ed5694..93a9d93 100644
--- a/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java
+++ b/platform/platform-impl/src/com/intellij/ui/TableSpeedSearch.java
@@ -25,8 +25,9 @@
public class TableSpeedSearch extends SpeedSearchBase<JTable> {
private static final PairFunction<Object, Cell, String> TO_STRING = new PairFunction<Object, Cell, String>() {
+ @Override
public String fun(Object o, Cell cell) {
- return o == null ? "" : o.toString();
+ return o == null || o instanceof Boolean ? "" : o.toString();
}
};
private final PairFunction<Object, Cell, String> myToStringConvertor;
@@ -46,9 +47,13 @@
public TableSpeedSearch(JTable table, final PairFunction<Object, Cell, String> toStringConvertor) {
super(table);
+
myToStringConvertor = toStringConvertor;
+ // edit on F2 & double click, do not interfere with quick search
+ table.putClientProperty("JTable.autoStartsEdit", Boolean.FALSE);
}
+ @Override
protected boolean isSpeedSearchEnabled() {
return !getComponent().isEditing() && super.isSpeedSearchEnabled();
}
@@ -58,11 +63,13 @@
return new MyListIterator(startingIndex);
}
+ @Override
protected int getElementCount() {
final TableModel tableModel = myComponent.getModel();
return tableModel.getRowCount() * tableModel.getColumnCount();
}
+ @Override
protected void selectElement(Object element, String selectedText) {
final int index = ((Integer)element).intValue();
final TableModel model = myComponent.getModel();
@@ -73,6 +80,7 @@
TableUtil.scrollSelectionToVisible(myComponent);
}
+ @Override
protected int getSelectedIndex() {
final int row = myComponent.getSelectedRow();
final int col = myComponent.getSelectedColumn();
@@ -80,10 +88,12 @@
return row > -1 && col > -1 ? row * myComponent.getModel().getColumnCount() + col : -1;
}
+ @Override
protected Object[] getAllElements() {
throw new UnsupportedOperationException("Not implemented");
}
+ @Override
protected String getElementText(Object element) {
final int index = ((Integer)element).intValue();
final TableModel model = myComponent.getModel();
@@ -102,38 +112,47 @@
myCursor = startingIndex < 0 ? total : startingIndex;
}
+ @Override
public boolean hasNext() {
return myCursor < getElementCount();
}
+ @Override
public Object next() {
return myCursor++;
}
+ @Override
public boolean hasPrevious() {
return myCursor > 0;
}
+ @Override
public Object previous() {
return (myCursor--) - 1;
}
+ @Override
public int nextIndex() {
return myCursor;
}
+ @Override
public int previousIndex() {
return myCursor - 1;
}
+ @Override
public void remove() {
throw new AssertionError("Not Implemented");
}
+ @Override
public void set(Object o) {
throw new AssertionError("Not Implemented");
}
+ @Override
public void add(Object o) {
throw new AssertionError("Not Implemented");
}
diff --git a/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java b/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java
index 5d45908..ad54662 100644
--- a/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java
+++ b/platform/platform-impl/src/com/intellij/ui/TreeExpandableItemsHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -38,6 +38,7 @@
protected TreeExpandableItemsHandler(final JTree tree) {
super(tree);
final TreeSelectionListener selectionListener = new TreeSelectionListener() {
+ @Override
public void valueChanged(TreeSelectionEvent e) {
updateSelection(tree);
}
@@ -97,14 +98,16 @@
private void updateSelection(JTree tree) {
int selection = tree.getSelectionCount() == 1 ? tree.getSelectionModel().getLeadSelectionRow() : -1;
- handleSelectionChange(selection == -1 ? null : new Integer(selection));
+ handleSelectionChange(selection == -1 ? null : selection);
}
+ @Override
protected Integer getCellKeyForPoint(Point point) {
int rowIndex = myComponent.getRowForLocation(point.x, point.y);
- return rowIndex != -1 ? new Integer(rowIndex) : null;
+ return rowIndex != -1 ? rowIndex : null;
}
+ @Override
protected Pair<Component, Rectangle> getCellRendererAndBounds(Integer key) {
int rowIndex = key.intValue();
diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java
index 0b2231e..c316cc5 100644
--- a/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/mac/MacFileChooserDialogImpl.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,8 +21,10 @@
import com.intellij.openapi.fileChooser.PathChooserDialog;
import com.intellij.openapi.fileChooser.impl.FileChooserUtil;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.ex.WindowManagerEx;
@@ -57,45 +59,52 @@
private final Project myProject;
private Consumer<List<VirtualFile>> myCallback;
- private static final Callback SHOULD_ENABLE_URL = new Callback() {
- @SuppressWarnings("UnusedDeclaration")
- public boolean callback(ID self, String selector, ID panel, ID url) {
- if (ourImplMap.get(self) == null) {
+ private static boolean checkFile(@NotNull ID self, ID url, boolean checkDirectories) {
+ MacFileChooserDialogImpl dialog = ourImplMap.get(self);
+ if (dialog == null) {
// Since it has already been removed from the map, the file is likely to be valid if the user was able to select it
return true;
}
- if (url == null || url.intValue() == 0) return false;
- final ID filename = Foundation.invoke(url, "path");
- final String fileName = Foundation.toStringViaUTF8(filename);
- if (fileName == null) return false;
- final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(fileName);
- return virtualFile == null || (virtualFile.isDirectory() || ourImplMap.get(self).myChooserDescriptor.isFileSelectable(virtualFile));
+
+ if (url == null || url.intValue() == 0) {
+ return false;
+ }
+
+ ID filename = Foundation.invoke(url, "path");
+ String fileName = Foundation.toStringViaUTF8(filename);
+ if (fileName == null) {
+ return false;
+ }
+
+ VirtualFile file = LocalFileSystem.getInstance().findFileByPath(fileName);
+ return file == null || (!checkDirectories && file.isDirectory()) || dialog.myChooserDescriptor.isFileSelectable(file);
+ }
+
+ private static final Callback SHOULD_ENABLE_CALLBACK = new Callback() {
+ @SuppressWarnings("UnusedDeclaration")
+ public boolean callback(ID self, String selector, ID panel, ID url) {
+ // allow any directory - ability to select nested directories
+ return checkFile(self, url, false);
}
};
- /*
- private static final Callback SHOULD_SHOW_FILENAME_CALLBACK = new Callback() {
+ private static final Callback VALIDATE_URL_CALLBACK = new Callback() {
@SuppressWarnings("UnusedDeclaration")
- public boolean callback(ID self, String selector, ID panel, ID filename) {
- if (filename == null || filename.intValue() == 0) return false;
- final String fileName = Foundation.toStringViaUTF8(filename);
- if (fileName == null) return false;
- final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(fileName);
- return virtualFile == null || (virtualFile.isDirectory() || myChooserDescriptor.isFileSelectable(virtualFile));
- }
- };
+ public boolean callback(ID self, String selector, ID panel, ID url, ID outError) {
+ if (checkFile(self, url, true)) {
+ return true;
+ }
- private static final Callback IS_VALID_FILENAME_CALLBACK = new Callback() {
- @SuppressWarnings("UnusedDeclaration")
- public boolean callback(ID self, String selector, ID panel, ID filename) {
- if (filename == null || filename.intValue() == 0) return false;
- final String fileName = Foundation.toStringViaUTF8(filename);
- if (fileName == null) return false;
- final VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByPath(fileName);
- return virtualFile == null || (!virtualFile.isDirectory() || myChooserDescriptor.isFileSelectable(virtualFile));
+ /*
+ if (!outError.equals(ID.NIL)) {
+ ID error = Foundation.invoke("NSError", "errorWithDomain:code:userInfo:", Foundation.nsString("org.jetbrains"),
+ Foundation.createDict(new String[]{"NSLocalizedDescriptionKey"}, new Object[]{"Not allowed"}));
+ // todo "*outError = error"
+ }
+ */
+ return false;
}
};
- */
private static final Callback OPEN_PANEL_DID_END = new Callback() {
@SuppressWarnings("UnusedDeclaration")
@@ -105,6 +114,7 @@
try {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
final IdeMenuBar bar = getMenuBar();
if (bar != null) {
@@ -117,9 +127,10 @@
if (resultPaths.size() > 0) {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
- final List<VirtualFile> files = getChosenFiles(resultPaths, impl.myChooserDescriptor);
- if (!files.isEmpty()) {
+ final List<VirtualFile> files = getChosenFiles(resultPaths);
+ if (files.size() > 0) {
FileChooserUtil.setLastOpenedFile(impl.myProject, files.get(files.size() - 1));
impl.myCallback.consume(files);
}
@@ -128,6 +139,7 @@
} else if (impl.myCallback instanceof FileChooser.FileChooserConsumer) {
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
((FileChooser.FileChooserConsumer)impl.myCallback).cancelled();
}
@@ -166,17 +178,17 @@
}
@NotNull
- private static List<VirtualFile> getChosenFiles(@Nullable List<String> paths, @NotNull FileChooserDescriptor chooserDescriptor) {
+ private static List<VirtualFile> getChosenFiles(final List<String> paths) {
if (ContainerUtil.isEmpty(paths)) {
return Collections.emptyList();
}
final LocalFileSystem fs = LocalFileSystem.getInstance();
- final List<VirtualFile> files = ContainerUtil.newArrayListWithExpectedSize(paths.size());
+ final List<VirtualFile> files = ContainerUtil.newArrayListWithCapacity(paths.size());
for (String path : paths) {
final String vfsPath = FileUtil.toSystemIndependentName(path);
final VirtualFile file = fs.refreshAndFindFileByPath(vfsPath);
- if (file != null && file.isValid() && chooserDescriptor.isFileSelectable(file)) {
+ if (file != null && file.isValid()) {
files.add(file);
}
}
@@ -199,6 +211,12 @@
invoke(chooser, "setCanChooseDirectories:", chooserDescriptor.isChooseFolders());
invoke(chooser, "setAllowsMultipleSelection:", chooserDescriptor.isChooseMultiple());
invoke(chooser, "setTreatsFilePackagesAsDirectories:", chooserDescriptor.isChooseFolders());
+ invoke(chooser, "setResolvesAliases:", false);
+
+ String description = chooserDescriptor.getDescription();
+ if (!StringUtil.isEmpty(description)) {
+ invoke(chooser, "setMessage:", Foundation.nsString(description));
+ }
if (Foundation.isClassRespondsToSelector(nsOpenPanel, Foundation.createSelector("setCanCreateDirectories:"))) {
invoke(chooser, "setCanCreateDirectories:", true);
@@ -232,7 +250,7 @@
ID types = null;
if (!chooserDescriptor.isChooseFiles() && chooserDescriptor.isChooseJars()) {
- types = invoke("NSArray", "arrayWithObject:", Foundation.nsString("jar"));
+ types = invoke("NSArray", "arrayWithObjects:", Foundation.nsString("jar"), Foundation.nsString("zip"), null);
}
final Window activeWindow = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
@@ -255,25 +273,22 @@
};
static {
- final ID delegate = Foundation.allocateObjcClassPair(Foundation.getObjcClass("NSObject"), "NSOpenPanelDelegate_");
- //if (!Foundation.addMethod(delegate, Foundation.createSelector("panel:shouldShowFilename:"), SHOULD_SHOW_FILENAME_CALLBACK, "B*")) {
- // throw new RuntimeException("Unable to add method to objective-c delegate class!");
- //}
- //if (!Foundation.addMethod(delegate, Foundation.createSelector("panel:isValidFilename:"), IS_VALID_FILENAME_CALLBACK, "B*")) {
- // throw new RuntimeException("Unable to add method to objective-c delegate class!");
- //}
- if (!Foundation.addMethod(delegate, Foundation.createSelector("showOpenPanel:"), MAIN_THREAD_RUNNABLE, "v*")) {
- throw new RuntimeException("Unable to add method to objective-c delegate class!");
- }
- if (!Foundation.addMethod(delegate, Foundation.createSelector("openPanelDidEnd:returnCode:contextInfo:"), OPEN_PANEL_DID_END, "v*i")) {
- throw new RuntimeException("Unable to add method to objective-c delegate class!");
- }
- if (!Foundation.addMethod(delegate, Foundation.createSelector("panel:shouldEnableURL:"), SHOULD_ENABLE_URL, "B@@")) {
- throw new RuntimeException("Unable to add method to objective-c delegate class!");
+ ID delegate = Foundation.allocateObjcClassPair(Foundation.getObjcClass("NSObject"), "NSOpenPanelDelegate_");
+ addFoundationMethod(delegate, "showOpenPanel:", MAIN_THREAD_RUNNABLE, "v*");
+ addFoundationMethod(delegate, "openPanelDidEnd:returnCode:contextInfo:", OPEN_PANEL_DID_END, "v*i");
+ addFoundationMethod(delegate, "panel:shouldEnableURL:", SHOULD_ENABLE_CALLBACK, "B@@");
+ if (SystemInfo.isMacOSSnowLeopard) {
+ addFoundationMethod(delegate, "panel:validateURL:error:", VALIDATE_URL_CALLBACK, "B@@o");
}
Foundation.registerObjcClassPair(delegate);
}
+ private static void addFoundationMethod(@NotNull ID delegate, @NotNull String selector, @NotNull Callback callback, @NotNull String types) {
+ if (!Foundation.addMethod(delegate, Foundation.createSelector(selector), callback, types)) {
+ throw new RuntimeException("Unable to add method " + selector + " to objective-c delegate class!");
+ }
+ }
+
public MacFileChooserDialogImpl(@NotNull final FileChooserDescriptor chooserDescriptor, final Project project) {
myChooserDescriptor = chooserDescriptor;
myProject = project;
@@ -292,6 +307,7 @@
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
showNativeChooserAsSheet(MacFileChooserDialogImpl.this, selectPath);
}
diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMessageException.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMessageException.java
new file mode 100644
index 0000000..a6609cd
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMessageException.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.mac;
+
+/**
+ * Created by denis on 28/01/14.
+ */
+public class MacMessageException extends RuntimeException {
+ public MacMessageException(final String message) {
+ super(message);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java
index a4e5dce..1ffa4e2 100644
--- a/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/mac/MacMessagesImpl.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.
@@ -24,7 +24,6 @@
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.ModalityHelper;
-import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.intellij.ui.mac.foundation.MacUtil;
import com.intellij.util.ui.UIUtil;
@@ -36,6 +35,8 @@
import javax.swing.*;
import java.awt.*;
import java.awt.event.InputEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@@ -120,6 +121,8 @@
// invoke(invoke(alert, "buttons"), "objectAtIndex:", count == 1 ? 0 : 1));
//}
+ enableEscapeToCloseTheMessage(alert);
+
String doNotAsk = toStringViaUTF8(doNotAskText);
if (!"-1".equals(doNotAsk)) {
invoke(alert, "setShowsSuppressionButton:", 1);
@@ -161,10 +164,10 @@
//invoke(window, "makeFirstResponder:",
// invoke(invoke(alert, "buttons"), "objectAtIndex:", alternateExist ? 2 : otherExist ? 1 : 0));
//
- ////it is impossible to override ESCAPE key behavior -> key should be named "Cancel" to be bound to ESC
- //if (!alternateExist) {
- // invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:", 1), "setKeyEquivalent:", nsString("\\e"));
- //}
+
+ if (!alternateExist) {
+ enableEscapeToCloseTheMessage(alert);
+ }
String doNotAsk = toStringViaUTF8(doNotAskText);
if (!"-1".equals(doNotAsk)) {
@@ -200,6 +203,13 @@
}
}
+ private static void enableEscapeToCloseTheMessage(ID alert) {
+ int buttonsNumber = invoke(invoke(alert, "buttons"), "count").intValue();
+ if (buttonsNumber < 2) return;
+ invoke(invoke(invoke(alert, "buttons"), "objectAtIndex:",
+ buttonsNumber - 1), "setKeyEquivalent:", nsString("\033"));
+ }
+
private MacMessagesImpl() {}
private static final Callback windowDidBecomeMainCallback = new Callback() {
@@ -232,14 +242,14 @@
if (SystemInfo.isJavaVersionAtLeast("1.7")) {
- ID awtWindow = Foundation.getObjcClass("AWTWindow");
+ ID awtWindow = getObjcClass("AWTWindow");
- Pointer windowWillEnterFullScreenMethod = Foundation.createSelector("windowDidBecomeMain:");
- ID originalWindowWillEnterFullScreen = Foundation.class_replaceMethod(awtWindow, windowWillEnterFullScreenMethod,
- windowDidBecomeMainCallback, "v@::@");
+ Pointer windowWillEnterFullScreenMethod = createSelector("windowDidBecomeMain:");
+ ID originalWindowWillEnterFullScreen = class_replaceMethod(awtWindow, windowWillEnterFullScreenMethod,
+ windowDidBecomeMainCallback, "v@::@");
- Foundation.addMethodByID(awtWindow, Foundation.createSelector("oldWindowDidBecomeMain:"),
- originalWindowWillEnterFullScreen, "v@::@");
+ addMethodByID(awtWindow, createSelector("oldWindowDidBecomeMain:"),
+ originalWindowWillEnterFullScreen, "v@::@");
}
}
@@ -322,6 +332,9 @@
method.invoke(theQueue, event);
}
}
+ catch (MacMessageException mme) {
+ throw mme;
+ }
catch (Throwable e) {
LOG.error(e);
}
@@ -414,7 +427,9 @@
}
private ID getParamsAsID() {
- LOG.assertTrue(window != null, "Native window must be set first.");
+ if (window == null) {
+ throw new MacMessageException("Window should be in the list.");
+ }
params.put(COMMON_DIALOG_PARAM_TYPE.nativeFocusedWindow, window);
ID paramsAsID = null;
@@ -562,7 +577,7 @@
}
//title, message, errorStyle, window, paramsArray, doNotAskDialogOption, "showVariableButtonsSheet:"
- private static Window showDialog(@Nullable Window window, final String methodName, DialogParamsWrapper paramsWrapper) {
+ private static Window showDialog(@Nullable Window window, final String methodName, final DialogParamsWrapper paramsWrapper) {
final Window foremostWindow = getForemostWindow(window);
@@ -574,6 +589,19 @@
final ID paramsArray = paramsWrapper.getParamsAsID();
+ foremostWindow.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosed(WindowEvent e) {
+ super.windowClosed(e);
+ //if (blockedDocumentRoots.get(documentRoot) != null) {
+ // LOG.assertTrue(blockedDocumentRoots.get(documentRoot) < 2);
+ //}
+ queuesFromDocumentRoot.remove(documentRoot);
+ if (blockedDocumentRoots.remove(documentRoot) != null) {
+ throw new MacMessageException("Owner window has been removed");
+ }
+ }
+ });
final ID delegate = invoke(invoke(getObjcClass("NSAlertDelegate_"), "alloc"), "init");
@@ -701,8 +729,11 @@
}
}
- //Actually can, but not in this implementation. If you know a reasonable scenario, please ask Denis Fokin for the improvement.
- LOG.assertTrue(MacUtil.getWindowTitle(_window) != null, "A window without a title should not be used for showing MacMessages");
+ if (SystemInfo.isAppleJvm && MacUtil.getWindowTitle(_window) == null) {
+ // With Apple JDK we cannot find a window if it does not have a title
+ // Let's show a dialog instead of the message.
+ throw new MacMessageException("MacMessage parent does not have a title.");
+ }
while (_window != null && MacUtil.getWindowTitle(_window) == null) {
_window = _window.getOwner();
//At least our frame should have a title
diff --git a/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java b/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java
index f47bb1f..3316a0d 100644
--- a/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java
+++ b/platform/platform-impl/src/com/intellij/ui/mac/growl/Growl.java
@@ -15,7 +15,6 @@
*/
package com.intellij.ui.mac.growl;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
import com.sun.jna.Pointer;
@@ -25,8 +24,6 @@
* @author spleaner
*/
public class Growl {
- private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.Growl");
-
private static final String GROWL_APPLICATION_REGISTRATION_NOTIFICATION = "GrowlApplicationRegistrationNotification";
private static final String GROWL_APP_NAME = "ApplicationName";
private static final String GROWL_APP_ICON = "ApplicationIcon";
@@ -48,10 +45,10 @@
public void register() {
final ID autoReleasePool = createAutoReleasePool();
final ID applicationIcon = getApplicationIcon();
- final ID defaultNotifications = fillArray(myDefaultNotification);
- final ID allNotifications = fillArray(myAllNotifications);
+ final ID defaultNotifications = Foundation.fillArray(myDefaultNotification);
+ final ID allNotifications = Foundation.fillArray(myAllNotifications);
- final ID userDict = createDict(new String[]{GROWL_APP_NAME, GROWL_APP_ICON, GROWL_DEFAULT_NOTIFICATIONS, GROWL_ALL_NOTIFICATIONS},
+ final ID userDict = Foundation.createDict(new String[]{GROWL_APP_NAME, GROWL_APP_ICON, GROWL_DEFAULT_NOTIFICATIONS, GROWL_ALL_NOTIFICATIONS},
new Object[]{myProductName, applicationIcon, defaultNotifications, allNotifications});
final ID center = invoke("NSDistributedNotificationCenter", "defaultCenter");
@@ -62,7 +59,7 @@
public void notifyGrowlOf(final String notification, final String title, final String description) {
final ID autoReleasePool = createAutoReleasePool();
- final ID dict = createDict(new String[]{
+ final ID dict = Foundation.createDict(new String[]{
GROWL_NOTIFICATION_NAME, GROWL_NOTIFICATION_TITLE, GROWL_NOTIFICATION_DESCRIPTION, GROWL_APP_NAME},
new Object[]{notification, title, description, myProductName});
final ID center = invoke("NSDistributedNotificationCenter", "defaultCenter");
@@ -84,41 +81,6 @@
return invoke("NSAutoreleasePool", "new");
}
- private static ID fillArray(final Object[] a) {
- final ID result = invoke("NSMutableArray", "array");
- for (Object s : a) {
- invoke(result, "addObject:", convertType(s));
- }
-
- return result;
- }
-
- private static ID createDict(@NotNull final String[] keys, @NotNull final Object[] values) {
- final ID nsKeys = invoke("NSArray", "arrayWithObjects:", convertTypes(keys));
- final ID nsData = invoke("NSArray", "arrayWithObjects:", convertTypes(values));
-
- return invoke("NSDictionary", "dictionaryWithObjects:forKeys:", nsData, nsKeys);
- }
-
- private static Object convertType(final Object o) {
- if (o instanceof Pointer || o instanceof ID) {
- return o;
- } else if (o instanceof String) {
- return Foundation.nsString((String)o);
- } else {
- throw new IllegalArgumentException("Unsupported type! " + o.getClass());
- }
- }
-
- private static Object[] convertTypes(@NotNull final Object[] v) {
- final Object[] result = new Object[v.length];
- for (int i = 0; i < v.length; i++) {
- result[i] = convertType(v[i]);
- }
-
- return result;
- }
-
private static ID getApplicationIcon() {
final ID sharedApp = invoke("NSApplication", "sharedApplication");
final ID nsImage = invoke(sharedApp, "applicationIconImage");
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java
new file mode 100644
index 0000000..8fa7a04
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/messages/JBMacMessages.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.messages;
+
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.wm.IdeFocusManager;
+import com.intellij.openapi.wm.WindowManager;
+import com.intellij.openapi.wm.impl.ModalityHelper;
+import com.intellij.ui.mac.MacMessageException;
+import com.intellij.ui.mac.MacMessagesEmulation;
+import com.intellij.ui.mac.foundation.MacUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * Created by Denis Fokin
+ */
+public class JBMacMessages extends MacMessagesEmulation {
+
+ @Override
+ public int showYesNoCancelDialog(@NotNull String title,
+ String message,
+ @NotNull String defaultButton,
+ String alternateButton,
+ String otherButton,
+ @Nullable Window window,
+ @Nullable DialogWrapper.DoNotAskOption doNotAskOption) {
+ if (window == null) {
+ window = getForemostWindow(null);
+ }
+ SheetMessage sheetMessage = new SheetMessage(window, title, message, null,
+ new String [] {defaultButton, alternateButton, otherButton}, null, defaultButton, alternateButton);
+ int result = sheetMessage.getResult().equals(defaultButton) ? Messages.YES : Messages.NO;
+ if (doNotAskOption != null) {
+ doNotAskOption.setToBeShown(sheetMessage.toBeShown(), result);
+ }
+ return result;
+ }
+
+ @Override
+ public int showMessageDialog(@NotNull String title,
+ String message,
+ @NotNull String[] buttons,
+ boolean errorStyle,
+ @Nullable Window window,
+ int defaultOptionIndex,
+ int focusedOptionIndex,
+ @Nullable DialogWrapper.DoNotAskOption doNotAskDialogOption) {
+ if (window == null) {
+ window = getForemostWindow(null);
+ }
+ SheetMessage sheetMessage = new SheetMessage(window, title, message, null, buttons, null, buttons[defaultOptionIndex], buttons[focusedOptionIndex]);
+ String result = sheetMessage.getResult();
+ for (int i = 0; i < buttons.length; i++) {
+ if (result.equals(buttons[i])) {
+ if (doNotAskDialogOption != null) {
+ doNotAskDialogOption.setToBeShown(sheetMessage.toBeShown(), i);
+ }
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ @Override
+ public void showOkMessageDialog(@NotNull String title, String message, @NotNull String okText, @Nullable Window window) {
+ if (window == null) {
+ window = getForemostWindow(null);
+ }
+ new SheetMessage(window, title, message, null, new String [] {okText}, null, null, okText);
+ }
+
+ @Override
+ public void showOkMessageDialog(@NotNull String title, String message, @NotNull String okText) {
+ final Window foremostWindow = getForemostWindow(null);
+ new SheetMessage(foremostWindow, title, message, null, new String [] {okText},null, null, okText);
+ }
+
+ private static Window getForemostWindow(final Window window) {
+ Window _window = null;
+ IdeFocusManager ideFocusManager = IdeFocusManager.getGlobalInstance();
+
+ Component focusOwner = IdeFocusManager.findInstance().getFocusOwner();
+ // Let's ask for a focused component first
+ if (focusOwner != null) {
+ _window = SwingUtilities.getWindowAncestor(focusOwner);
+ }
+
+ if (_window == null) {
+ // Looks like ide lost focus, let's ask about the last focused component
+ focusOwner = ideFocusManager.getLastFocusedFor(ideFocusManager.getLastFocusedFrame());
+ if (focusOwner != null) {
+ _window = SwingUtilities.getWindowAncestor(focusOwner);
+ }
+ }
+
+ if (_window == null) {
+ _window = WindowManager.getInstance().findVisibleFrame();
+ }
+
+ if (_window == null && window != null) {
+ // It might be we just has not opened a frame yet.
+ // So let's ask AWT
+ focusOwner = window.getMostRecentFocusOwner();
+ if (focusOwner != null) {
+ _window = SwingUtilities.getWindowAncestor(focusOwner);
+ }
+ }
+
+ if (_window != null) {
+ // We have successfully found the window
+ // Let's check that we have not missed a blocker
+ if (ModalityHelper.isModalBlocked(_window)) {
+ _window = ModalityHelper.getModalBlockerFor(_window);
+ }
+ }
+
+ if (SystemInfo.isAppleJvm && MacUtil.getWindowTitle(_window) == null) {
+ // With Apple JDK we cannot find a window if it does not have a title
+ // Let's show a dialog instead of the message.
+ throw new MacMessageException("MacMessage parent does not have a title.");
+ }
+ while (_window != null && MacUtil.getWindowTitle(_window) == null) {
+ _window = _window.getOwner();
+ //At least our frame should have a title
+ }
+
+ while (Registry.is("skip.untitled.windows.for.mac.messages") && _window != null && _window instanceof JDialog && !((JDialog)_window).isModal()) {
+ _window = _window.getOwner();
+ }
+
+ return _window;
+ }
+
+ @Override
+ public int showYesNoDialog(@NotNull String title,
+ String message,
+ @NotNull String yesButton,
+ @NotNull String noButton,
+ @Nullable Window window) {
+ if (window == null) {
+ window = getForemostWindow(null);
+ }
+ SheetMessage sheetMessage = new SheetMessage(window, title, message, null, new String [] {yesButton, noButton}, null, noButton, yesButton);
+ return sheetMessage.getResult().equals(yesButton) ? Messages.YES : Messages.NO;
+ }
+
+ @Override
+ public int showYesNoDialog(@NotNull String title,
+ String message,
+ @NotNull String yesButton,
+ @NotNull String noButton,
+ @Nullable Window window,
+ @Nullable DialogWrapper.DoNotAskOption doNotAskDialogOption) {
+ if (window == null) {
+ window = getForemostWindow(null);
+ }
+ SheetMessage sheetMessage = new SheetMessage(window, title, message, null, new String [] {noButton, yesButton}, doNotAskDialogOption, noButton, yesButton);
+ int result = sheetMessage.getResult().equals(yesButton) ? Messages.YES : Messages.NO;
+ if (doNotAskDialogOption != null) {
+ doNotAskDialogOption.setToBeShown(sheetMessage.toBeShown(), result);
+ }
+ return result;
+ }
+
+ @Override
+ public void showErrorDialog(@NotNull String title, String message, @NotNull String okButton, @Nullable Window window) {
+ if (window == null) {
+ window = getForemostWindow(null);
+ }
+ new SheetMessage(window, title, message, null, new String [] {okButton}, null, null, okButton);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
new file mode 100755
index 0000000..80f33f6
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetController.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.messages;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.ui.Gray;
+
+import javax.swing.*;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.StyledDocument;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.awt.geom.Area;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
+import java.awt.image.BufferedImage;
+
+/**
+ * Created by Denis Fokin
+ */
+public class SheetController {
+
+ private static String fontName = "Lucida Grande";
+ private static Font regularFont = new Font(fontName, Font.PLAIN, 12);
+ private static Font boldFont = new Font(fontName, Font.BOLD, 14).deriveFont(Font.BOLD);
+ private final DialogWrapper.DoNotAskOption myDoNotAskOption;
+ private JCheckBox doNotAskCheckBox;
+ private boolean myDoNotAskResult;
+
+
+ private JLabel myHeaderLabel = new JLabel();
+ private MultilineLabel myMessageLabel;
+ private JButton[] buttons;
+ private JButton myDefaultButton;
+ private JButton myFocusedButton;
+ public static int SHEET_WIDTH = 400;
+ public int SHEET_HEIGHT = 150;
+
+ private String myResult;
+ private JPanel mySheetPanel;
+ private SheetMessage mySheetMessage;
+ private JTextArea myTextArea;
+
+ SheetController(final SheetMessage sheetMessage,
+ final String title,
+ final String message,
+ final Icon icon,
+ final String[] buttonTitles,
+ final String defaultButtonTitle,
+ final DialogWrapper.DoNotAskOption doNotAskOption,
+ final String focusedButton) {
+ myDoNotAskOption = doNotAskOption;
+ mySheetMessage = sheetMessage;
+ buttons = new JButton[buttonTitles.length];
+ for (int i = 0; i < buttonTitles.length; i++) {
+ buttons[i] = new JButton(buttonTitles[i]);
+ if (buttonTitles[i].equals(defaultButtonTitle)) {
+ myDefaultButton = buttons[i];
+ }
+ if (buttonTitles[i].equals(focusedButton)) {
+ myFocusedButton = buttons[i];
+ }
+ }
+ mySheetPanel = createSheetPanel(title, message, buttons);
+
+
+ }
+
+ void requestFocus() {
+ final JComponent focusedComponent = (myDoNotAskOption == null) ? myFocusedButton : doNotAskCheckBox;
+ if (focusedComponent == null) return; // it might be we have only one button. it is a default one in that case
+ focusedComponent.requestFocusInWindow();
+ }
+
+ JPanel getPanel(final JDialog w) {
+ w.getRootPane().setDefaultButton(myDefaultButton);
+
+
+ ActionListener actionListener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (e.getSource() instanceof JButton) {
+ myResult = ((JButton)e.getSource()).getText();
+ }
+ mySheetMessage.startAnimation();
+
+ }
+ };
+
+ for (JButton button: buttons) {
+ button.addActionListener(actionListener);
+ }
+ return mySheetPanel;
+ }
+
+
+ private JPanel createSheetPanel(String title, String message, JButton[] buttons) {
+ JPanel sheetPanel = new JPanel() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ final Graphics2D g2d = (Graphics2D) g.create();
+ 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);
+ g2d.fill(dialog);
+ paintShadow(g2d, dialog);
+ }
+
+ };
+
+ sheetPanel.setOpaque(false);
+ sheetPanel.setLayout(null);
+
+ JPanel ico = new JPanel() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ AllIcons.Logo_welcomeScreen.paintIcon(this, g, 0, 0);
+ }
+ };
+
+
+ myHeaderLabel = new JLabel(title);
+
+ myHeaderLabel.setFont(boldFont);
+
+ myHeaderLabel.repaint();
+ myHeaderLabel.setSize(myHeaderLabel.getPreferredSize());
+
+ sheetPanel.add(myHeaderLabel);
+
+ myTextArea = new JTextArea(message);
+
+ myTextArea.setFont(regularFont);
+ myTextArea.setLineWrap(true);
+ myTextArea.setWrapStyleWord(true);
+
+ myTextArea.setSize(250, 10);
+ myTextArea.setOpaque(false);
+
+
+
+ sheetPanel.add(myTextArea);
+
+ myTextArea.repaint();
+ myTextArea.setSize(myTextArea.getPreferredSize());
+
+ SHEET_HEIGHT = myTextArea.getPreferredSize().height + myHeaderLabel.getPreferredSize().height + 20 + 10 + 100;
+
+ 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);
+ sheetPanel.add(ico);
+ myHeaderLabel.setLocation(120, 20);
+ myTextArea.setLocation(120, 20 + myHeaderLabel.getPreferredSize().height + 10);
+ layoutWithAbsoluteLayout(title, message, buttons, sheetPanel);
+
+ return sheetPanel;
+ }
+
+ private void layoutWithAbsoluteLayout(String title, String message, JButton[] buttons, JPanel sheetPanel) {
+ layoutButtons(buttons, sheetPanel);
+
+ if (myDoNotAskOption != null) {
+ layoutDoNotAskCheckbox();
+ sheetPanel.add(doNotAskCheckBox);
+ }
+ }
+
+
+
+
+ private void paintShadow(Graphics2D g2d, Rectangle2D dialog) {
+ Area shadow = new Area(new RoundRectangle2D.Double(0, 0, mySheetPanel.getBounds().width, mySheetPanel.getBounds().height, 10, 10));
+
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.80f));
+
+ Color color1 = Gray._130;
+ Color color2 = 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);
+ }
+
+ private void layoutButtons(final JButton[] buttons, JPanel panel) {
+ for (int i = 0; i < buttons.length ; i ++) {
+ panel.add(buttons[i]);
+ buttons[i].repaint();
+
+ Dimension size = buttons[i].getPreferredSize();
+ buttons[i].setBounds(SHEET_WIDTH - (size.width + 10) * (buttons.length - i) - 15, SHEET_HEIGHT - 45,
+ size.width, size.height);
+ }
+ }
+
+ private void layoutDoNotAskCheckbox() {
+ doNotAskCheckBox = new JCheckBox(myDoNotAskOption.getDoNotShowMessage());
+ doNotAskCheckBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ myDoNotAskResult = e.getStateChange() == ItemEvent.SELECTED;
+ }
+ });
+ doNotAskCheckBox.repaint();
+ doNotAskCheckBox.setSize(doNotAskCheckBox.getPreferredSize());
+ doNotAskCheckBox.setLocation(120, SHEET_HEIGHT - 70);
+ }
+
+ /**
+ * This method is used to show an image during message showing
+ * @return image to show
+ */
+ private Image getStaticImage() {
+ final JFrame myOffScreenFrame = new JFrame() ;
+ myOffScreenFrame.add(mySheetPanel);
+ myOffScreenFrame.getRootPane().setDefaultButton(myDefaultButton);
+
+ final BufferedImage image = new BufferedImage(SHEET_WIDTH, SHEET_HEIGHT, BufferedImage.TYPE_INT_ARGB);
+
+ mySheetPanel.paint(image.createGraphics());
+ myOffScreenFrame.dispose();
+ return image;
+ }
+
+ public JPanel getStaticPanel() {
+ final Image staticImage = getStaticImage();
+ JPanel jPanel = new JPanel() {
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ Graphics2D g2d = (Graphics2D) g.create();
+ int zeroOffset = getHeight() - SHEET_HEIGHT;
+ g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.95f));
+ g2d.drawImage(staticImage, 0 , zeroOffset, null);
+ }
+ };
+ jPanel.setOpaque(false);
+ return jPanel;
+ }
+
+ public boolean getDoNotAskResult () {
+ return myDoNotAskResult;
+ }
+
+ public String getResult() {
+ return myResult;
+ }
+}
+
+class MultilineLabel extends JTextPane {
+ private static final long serialVersionUID = 1L;
+ public MultilineLabel(){
+ super();
+ setEditable(false);
+ setCursor(null);
+ setOpaque(false);
+ setFocusable(false);
+
+ setPreferredSize(new Dimension(200,50));
+
+ StyledDocument doc = getStyledDocument();
+ SimpleAttributeSet center = new SimpleAttributeSet();
+ StyleConstants.setAlignment(center, StyleConstants.ALIGN_LEFT);
+ doc.setParagraphAttributes(0, doc.getLength(), center, false);
+ }
+}
diff --git a/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
new file mode 100755
index 0000000..317313f
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/ui/messages/SheetMessage.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.messages;
+
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.ui.JBColor;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+
+
+/**
+ * Created by Denis Fokin
+ */
+public class SheetMessage implements ActionListener {
+ private JDialog myWindow;
+ private Window myParent;
+ private SheetController myController;
+ private Timer myAnimator = new Timer(2, this);
+
+ private boolean myShouldEnlarge = true;
+
+ private final static int SHEET_ANIMATION_STEP = 4;
+
+ public SheetMessage(final Window owner,
+ final String title,
+ final String message,
+ final Icon icon,
+ final String[] buttons,
+ final DialogWrapper.DoNotAskOption doNotAskOption,
+ final String focusedButton,
+ final String defaultButton)
+ {
+ myWindow = new JDialog(owner, "This should not be shown", Dialog.ModalityType.APPLICATION_MODAL) ;
+ myParent = owner;
+ myWindow.setSize(SheetController.SHEET_WIDTH, 0);
+ myWindow.setUndecorated(true);
+ 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);
+ myWindow.setContentPane(myController.getStaticPanel());
+ registerMoveResizeHandler();
+ myWindow.setFocusableWindowState(true);
+ myWindow.setFocusable(true);
+
+ myAnimator.start();
+ myWindow.setVisible(true);
+ }
+
+ public boolean toBeShown() {
+ return !myController.getDoNotAskResult();
+ }
+
+ public String getResult() {
+ return myController.getResult();
+ }
+
+ void startAnimation () {
+ myWindow.setContentPane(myController.getStaticPanel());
+ myAnimator.start();
+ }
+
+
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+
+ int windowHeight = (myShouldEnlarge) ? myWindow.getHeight() + SHEET_ANIMATION_STEP
+ : myWindow.getHeight() - SHEET_ANIMATION_STEP;
+
+ myWindow.setSize(myWindow.getWidth(), windowHeight);
+ setPositionRelativeToParent();
+ if (myWindow.getHeight() > myController.SHEET_HEIGHT) {
+ myAnimator.stop();
+ myWindow.setContentPane(
+ myController.getPanel(myWindow)
+ );
+ myController.requestFocus();
+ myShouldEnlarge = false;
+ }
+
+ if (myWindow.getHeight() < 0) {
+ myAnimator.stop();
+ myWindow.dispose();
+ }
+ }
+
+ private void setPositionRelativeToParent () {
+ int width = myParent.getWidth();
+ myWindow.setLocation(width / 2 - SheetController.SHEET_WIDTH / 2 + myParent.getLocation().x, myParent.getInsets().top
+ + myParent.getLocation().y);
+ }
+
+ private void registerMoveResizeHandler () {
+ myParent.addComponentListener(new ComponentAdapter() {
+ @Override
+ public void componentResized(ComponentEvent e) {
+ super.componentResized(e);
+ setPositionRelativeToParent();
+ }
+
+ @Override
+ public void componentMoved(ComponentEvent e) {
+ super.componentMoved(e);
+ setPositionRelativeToParent();
+ }
+ });
+ }
+}
+
+
+
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
index fc5a96d..0e09ea5 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/AbstractPopup.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,7 +95,6 @@
private boolean myCancelOnWindowDeactivation = true;
private Dimension myForcedSize;
private Point myForcedLocation;
- private ChildFocusWatcher myFocusWatcher;
private boolean myCancelKeyEnabled;
private boolean myLocateByContent;
protected FocusTrackback myFocusTrackback;
@@ -165,8 +164,6 @@
private UiActivity myActivityKey;
private Disposable myProjectDisposable;
-
-
AbstractPopup() {
}
@@ -701,17 +698,9 @@
sizeToSet = myForcedSize;
}
- if (myMinSize == null) {
- myMinSize = myContent.getMinimumSize();
- }
-
- if (sizeToSet == null) {
- sizeToSet = myContent.getPreferredSize();
- }
-
if (sizeToSet != null) {
- sizeToSet.width = Math.max(sizeToSet.width, myMinSize.width);
- sizeToSet.height = Math.max(sizeToSet.height, myMinSize.height);
+ sizeToSet.width = Math.max(sizeToSet.width, myContent.getMinimumSize().width);
+ sizeToSet.height = Math.max(sizeToSet.height, myContent.getMinimumSize().height);
myContent.setSize(sizeToSet);
myContent.setPreferredSize(sizeToSet);
@@ -839,6 +828,7 @@
}
}
+ setMinimumSize(myMinSize);
final Runnable afterShow = new Runnable() {
@Override
@@ -929,9 +919,16 @@
return;
}
- if (ourXWindowIDEA94683FocusBug && isFocused() && !myRequestFocus && prevOwner != null &&
+ if (ourXWindowIDEA94683FocusBug && !myRequestFocus && prevOwner != null &&
Registry.is("actionSystem.xWindow.remove.focus.from.nonFocusable.popups")) {
- IdeFocusManager.getInstance(myProject).requestFocus(prevOwner, false);
+ new Alarm().addRequest(new Runnable() {
+ @Override
+ public void run() {
+ if (isFocused()) {
+ IdeFocusManager.getInstance(myProject).requestFocus(prevOwner, false);
+ }
+ }
+ }, Registry.intValue("actionSystem.xWindow.remove.focus.from.nonFocusable.popups.delay"));
}
afterShow.run();
@@ -1030,7 +1027,7 @@
}
- myFocusWatcher = new ChildFocusWatcher(myContent) {
+ ChildFocusWatcher focusWatcher = new ChildFocusWatcher(myContent) {
@Override
protected void onFocusGained(final FocusEvent event) {
setWindowActive(true);
@@ -1040,8 +1037,8 @@
protected void onFocusLost(final FocusEvent event) {
setWindowActive(false);
}
-
};
+ Disposer.register(this, focusWatcher);
mySpeedSearchPatternField = new JTextField();
if (SystemInfo.isMac) {
@@ -1051,7 +1048,7 @@
}
private Window updateMaskAndAlpha(Window window) {
- if (window == null) return window;
+ if (window == null) return null;
final WindowManagerEx wndManager = getWndManager();
if (wndManager == null) return window;
@@ -1242,11 +1239,6 @@
}
myMouseOutCanceller = null;
- if (myFocusWatcher != null) {
- myFocusWatcher.dispose();
- myFocusWatcher = null;
- }
-
resetWindow();
if (myFinalRunnable != null) {
@@ -1467,8 +1459,6 @@
public static Window setSize(JComponent content, final Dimension size) {
final Window popupWindow = SwingUtilities.windowForComponent(content);
- final Point location = popupWindow.getLocation();
- popupWindow.setLocation(location.x, location.y);
Insets insets = content.getInsets();
if (insets != null) {
size.width += insets.left + insets.right;
@@ -1657,7 +1647,29 @@
@Override
public void setMinimumSize(Dimension size) {
- myMinSize = size;
+ //todo: consider changing only the caption panel minimum size
+ Dimension sizeFromHeader = myHeaderPanel.getPreferredSize();
+
+ if (sizeFromHeader == null) {
+ sizeFromHeader = myHeaderPanel.getMinimumSize();
+ }
+
+ if (sizeFromHeader == null) {
+ int minimumSize = myWindow.getGraphics().getFontMetrics(myHeaderPanel.getFont()).getHeight();
+ sizeFromHeader = new Dimension(minimumSize, minimumSize);
+ }
+
+ if (size == null) {
+ myMinSize = sizeFromHeader;
+ } else {
+ final int width = Math.max(size.width, sizeFromHeader.width);
+ final int height = Math.max(size.height, sizeFromHeader.height);
+ myMinSize = new Dimension(width, height);
+ }
+
+ if (myWindow != null) {
+ myWindow.setMinimumSize(myMinSize);
+ }
}
public Runnable getFinalRunnable() {
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/BalloonPopupBuilderImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/BalloonPopupBuilderImpl.java
index c721abc..0c7416b 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/BalloonPopupBuilderImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/BalloonPopupBuilderImpl.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,7 +39,7 @@
@Nullable private final Map<Disposable, List<Balloon>> myStorage;
@Nullable private Disposable myAnchor;
- private JComponent myContent;
+ private final JComponent myContent;
private Color myBorder = new JBColor(JBColor.GRAY, Gray._200);
@Nullable private Insets myBorderInsets = null;
diff --git a/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java b/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java
index 59435cf..de41197 100644
--- a/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java
+++ b/platform/platform-impl/src/com/intellij/ui/popup/tree/TreePopupImpl.java
@@ -17,6 +17,7 @@
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.treeView.AlphaComparator;
+import com.intellij.ide.util.treeView.NodeRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.PopupStep;
@@ -24,7 +25,6 @@
import com.intellij.openapi.ui.popup.TreePopupStep;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.ui.popup.WizardPopup;
-import com.intellij.ui.treeStructure.SimpleNodeRenderer;
import com.intellij.ui.treeStructure.SimpleTree;
import com.intellij.ui.treeStructure.filtered.FilteringTreeBuilder;
import com.intellij.ui.treeStructure.filtered.FilteringTreeStructure;
@@ -359,7 +359,7 @@
myChild.show(getContent(), point.x - STEP_X_PADDING, point.y, true);
}
- private class MyRenderer extends SimpleNodeRenderer {
+ private class MyRenderer extends NodeRenderer {
@Override
public void customizeCellRenderer(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
diff --git a/platform/platform-impl/src/com/intellij/util/LocalFileUrl.java b/platform/platform-impl/src/com/intellij/util/LocalFileUrl.java
index 0ac07b5..93fa003 100644
--- a/platform/platform-impl/src/com/intellij/util/LocalFileUrl.java
+++ b/platform/platform-impl/src/com/intellij/util/LocalFileUrl.java
@@ -6,6 +6,9 @@
public final class LocalFileUrl implements Url {
private final String path;
+ /**
+ * Use {@link Urls#newLocalFileUrl(String)} instead
+ */
public LocalFileUrl(@NotNull String path) {
this.path = path;
}
diff --git a/platform/platform-impl/src/com/intellij/util/SingleAlarm.java b/platform/platform-impl/src/com/intellij/util/SingleAlarm.java
index 3d53d6c..09bda6a 100644
--- a/platform/platform-impl/src/com/intellij/util/SingleAlarm.java
+++ b/platform/platform-impl/src/com/intellij/util/SingleAlarm.java
@@ -28,6 +28,10 @@
this.delay = delay;
}
+ public SingleAlarm(@NotNull Runnable task, int delay, @NotNull Disposable parentDisposable) {
+ this(task, delay, Alarm.ThreadToUse.SWING_THREAD, parentDisposable);
+ }
+
public SingleAlarm(@NotNull Runnable task, int delay, @NotNull ThreadToUse threadToUse, @NotNull Disposable parentDisposable) {
super(threadToUse, parentDisposable);
diff --git a/platform/platform-impl/src/com/intellij/util/UriUtil.java b/platform/platform-impl/src/com/intellij/util/UriUtil.java
index 345cb23..48069bf 100644
--- a/platform/platform-impl/src/com/intellij/util/UriUtil.java
+++ b/platform/platform-impl/src/com/intellij/util/UriUtil.java
@@ -16,28 +16,18 @@
package com.intellij.util;
import com.google.common.base.CharMatcher;
-import com.google.common.base.Charsets;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
-import com.google.common.io.BaseEncoding;
-import com.google.common.net.MediaType;
import com.intellij.openapi.util.Pair;
import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import static com.intellij.openapi.util.text.StringUtil.stripQuotesAroundValue;
public final class UriUtil {
public static final CharMatcher PARAM_CHAR_MATCHER = CharMatcher.anyOf("?#;");
public static final CharMatcher SLASH_MATCHER = CharMatcher.is('/');
- private static final Pattern DATA_URI_PATTERN = Pattern.compile("data:([^,;]+/[^,;]+)(;charset=[^,;]+)?(;base64)?,(.+)");
-
private UriUtil() {
}
@@ -56,52 +46,6 @@
return end != -1 ? url.substring(0, end) : url;
}
- public static boolean isDataUri(@NotNull String value) {
- return !value.isEmpty() && value.startsWith("data:", value.charAt(0) == '"' || value.charAt(0) == '\'' ? 1 : 0);
- }
-
- /**
- * Extracts byte array from given data:URL string.
- * data:URL will be decoded from base64 if it contains the marker of base64 encoding.
- *
- * @param dataUrl data:URL-like string (may be quoted)
- * @return extracted byte array or {@code null} if it cannot be extracted.
- */
- @Nullable
- public static byte[] getBytesFromDataUri(@NotNull String dataUrl) {
- Matcher matcher = DATA_URI_PATTERN.matcher(stripQuotesAroundValue(dataUrl));
- if (matcher.matches()) {
- try {
- String content = matcher.group(4);
- return ";base64".equalsIgnoreCase(matcher.group(3)) ? BaseEncoding.base64().decode(content) : content.getBytes(Charsets.UTF_8);
- }
- catch (IllegalArgumentException e) {
- return null;
- }
- }
- return null;
- }
-
- /**
- * Extracts mime-type of given data:URL string
- *
- * @param dataUrl data:URL-like string (may be quoted)
- * @return mime-type extracted from image or {@code null} if string doesn't contain mime definition.
- */
- @Nullable
- public static MediaType getMediaTypeFromDataUri(@NotNull String dataUrl) {
- Matcher matcher = DATA_URI_PATTERN.matcher(stripQuotesAroundValue(dataUrl));
- if (matcher.matches()) {
- try {
- return MediaType.parse(matcher.group(1));
- }
- catch (IllegalArgumentException e) {
- return null;
- }
- }
- return null;
- }
-
/**
* Splits the url into 2 parts: the scheme ("http", for instance) and the rest of the URL. <br/>
* Scheme separator is not included neither to the scheme part, nor to the url part. <br/>
diff --git a/platform/platform-impl/src/com/intellij/util/Urls.java b/platform/platform-impl/src/com/intellij/util/Urls.java
index 6a1ee01..64e577d 100644
--- a/platform/platform-impl/src/com/intellij/util/Urls.java
+++ b/platform/platform-impl/src/com/intellij/util/Urls.java
@@ -28,7 +28,7 @@
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.List;
+import java.util.Collection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -44,6 +44,16 @@
}
@NotNull
+ public static Url newLocalFileUrl(@NotNull String path) {
+ return new LocalFileUrl(path);
+ }
+
+ @NotNull
+ public static Url newLocalFileUrl(@NotNull VirtualFile file) {
+ return newLocalFileUrl(file.getPath());
+ }
+
+ @NotNull
public static Url newFromEncoded(@NotNull String url) {
Url result = parseEncoded(url);
LOG.assertTrue(result != null, url);
@@ -78,14 +88,18 @@
// java.net.URI.create cannot parse "file:///Test Stuff" - but you don't need to worry about it - this method is aware
@Nullable
public static Url parseFromIdea(@NotNull String url) {
- return URLUtil.containsScheme(url) ? parseUrl(url) : new LocalFileUrl(url);
+ return URLUtil.containsScheme(url) ? parseUrl(url) : newLocalFileUrl(url);
}
@Nullable
public static Url parse(@NotNull String url, boolean asLocalIfNoScheme) {
+ if (url.isEmpty()) {
+ return null;
+ }
+
if (asLocalIfNoScheme && !URLUtil.containsScheme(url)) {
// nodejs debug — files only in local filesystem
- return new LocalFileUrl(url);
+ return newLocalFileUrl(url);
}
return parseUrl(VfsUtilCore.toIdeaUrl(url));
}
@@ -101,7 +115,7 @@
return toUriWithoutParameters(asUrl);
}
catch (Exception e) {
- LOG.info("Can't parse " + url, e);
+ LOG.info("Cannot parse url " + url, e);
return null;
}
}
@@ -118,7 +132,6 @@
Matcher matcher = URI_PATTERN.matcher(urlToParse);
if (!matcher.matches()) {
- LOG.warn("Cannot parse url " + url);
return null;
}
String scheme = matcher.group(1);
@@ -151,7 +164,7 @@
}
}
- public static boolean equalsIgnoreParameters(@NotNull Url url, @NotNull List<Url> urls) {
+ public static boolean equalsIgnoreParameters(@NotNull Url url, @NotNull Collection<Url> urls) {
for (Url otherUrl : urls) {
if (url.equalsIgnoreParameters(otherUrl)) {
return true;
diff --git a/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java b/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java
index 7e6e3d3..74cd55b 100644
--- a/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java
+++ b/platform/platform-impl/src/com/intellij/util/graph/impl/KShortestPathsFinder.java
@@ -102,14 +102,12 @@
for (int j = 1; j < heapNodes.size(); j++) {
HeapNode<Node> heapNode = heapNodes.get(j);
HeapNode<Node> parent = heapNodes.get((j+1)/2 - 1);
- heapNode.myParent = parent;
parent.myChildren[(j+1) % 2] = heapNode;
}
for (int j = heapNodes.size() / 2 - 1; j >= 0; j--) {
heapify(heapNodes.get(j));
}
root.myChildren[2] = heapNodes.get(0);
- root.myChildren[2].myParent = root;
}
}
}
@@ -271,38 +269,37 @@
public Heap<Node> insert(HeapNode<Node> node) {
int pos = mySize + 1;
int pow = 1;
- while (pos > pow << 2) {
+ while (pos >= pow << 2) {
pow <<= 1;
}
- HeapNode<Node> place = myRoot;
+ HeapNode<Node> newRoot = myRoot.copy();
+ HeapNode<Node> place = newRoot;
+ List<HeapNode<Node>> parents = new ArrayList<HeapNode<Node>>();
while (true) {
+ parents.add(place);
final int ind = (pos & pow) != 0 ? 1 : 0;
if (pow == 1) {
- HeapNode<Node> placeCopy = place.copy();
- placeCopy.myChildren[ind] = node;
- node.myParent = placeCopy;
+ place.myChildren[ind] = node;
break;
}
- place = place.myChildren[ind];
+ HeapNode<Node> copy = place.myChildren[ind].copy();
+ place.myChildren[ind] = copy;
+ place = copy;
pow >>= 1;
}
- while (true) {
- final HeapNode<Node> parent = node.myParent;
- if (parent == null || parent.myEdge.getDelta() < node.myEdge.getDelta()) {
+
+ for (int i = parents.size() - 1; i >= 0; i--) {
+ HeapNode<Node> parent = parents.get(i);
+ if (parent.myEdge.getDelta() < node.myEdge.getDelta()) {
break;
}
- final HeapNode<Node> parentCopy = parent.copy();
- final GraphEdge<Node> t = parentCopy.myEdge;
- parentCopy.myEdge = node.myEdge;
+ final GraphEdge<Node> t = parent.myEdge;
+ parent.myEdge = node.myEdge;
node.myEdge = t;
- final HeapNode<Node> t2 = parentCopy.myChildren[2];
- parentCopy.myChildren[2] = node.myChildren[2];
+ final HeapNode<Node> t2 = parent.myChildren[2];
+ parent.myChildren[2] = node.myChildren[2];
node.myChildren[2] = t2;
- node = parentCopy;
- }
- HeapNode<Node> newRoot = node;
- while (newRoot.myParent != null) {
- newRoot = newRoot.myParent;
+ node = parent;
}
return new Heap<Node>(mySize + 1, newRoot);
}
@@ -310,7 +307,6 @@
private static class HeapNode<Node> {
public HeapNode<Node>[] myChildren;
- public HeapNode<Node> myParent;
public GraphEdge<Node> myEdge;
private HeapNode(GraphEdge<Node> edge) {
@@ -321,7 +317,6 @@
public HeapNode(HeapNode<Node> node) {
myEdge = node.myEdge;
myChildren = node.myChildren.clone();
- myParent = node.myParent;
}
public HeapNode<Node> copy() {
diff --git a/platform/platform-impl/src/com/intellij/util/io/UrlConnectionUtil.java b/platform/platform-impl/src/com/intellij/util/io/UrlConnectionUtil.java
index c99e1fe..9d7836c 100644
--- a/platform/platform-impl/src/com/intellij/util/io/UrlConnectionUtil.java
+++ b/platform/platform-impl/src/com/intellij/util/io/UrlConnectionUtil.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
@@ -35,7 +36,9 @@
private UrlConnectionUtil() {
}
- public static @Nullable InputStream getConnectionInputStream(URLConnection connection, ProgressIndicator pi) {
+ public static
+ @Nullable
+ InputStream getConnectionInputStream(URLConnection connection, ProgressIndicator pi) {
try {
return getConnectionInputStreamWithException(connection, pi);
}
@@ -48,25 +51,30 @@
}
- public static InputStream getConnectionInputStreamWithException(URLConnection connection, ProgressIndicator pi) throws IOException {
+ public static InputStream getConnectionInputStreamWithException(@NotNull URLConnection connection, @NotNull ProgressIndicator pi)
+ throws IOException {
InputStreamGetter getter = new InputStreamGetter(connection);
final Future<?> getterFuture = ApplicationManager.getApplication().executeOnPooledThread(getter);
-
while (true) {
pi.checkCanceled();
try {
try {
getterFuture.get(50, TimeUnit.MILLISECONDS);
}
- catch (TimeoutException e) {}
+ catch (TimeoutException ignored) {
+ }
+
pi.setIndeterminate(true);
pi.setText(pi.getText());
- if (getterFuture.isDone()) break;
+ if (getterFuture.isDone()) {
+ break;
+ }
}
catch (Exception e) {
throw new ProcessCanceledException(e);
}
}
+ //noinspection ThrowableResultOfMethodCallIgnored
if (getter.getException() != null) {
throw getter.getException();
}
@@ -91,6 +99,7 @@
return myInputStream;
}
+ @Override
public void run() {
try {
myInputStream = myUrlConnection.getInputStream();
diff --git a/platform/platform-impl/src/com/intellij/util/io/socketConnection/impl/SocketConnectionImpl.java b/platform/platform-impl/src/com/intellij/util/io/socketConnection/impl/SocketConnectionImpl.java
index 6ef2f31..cfe3db1 100644
--- a/platform/platform-impl/src/com/intellij/util/io/socketConnection/impl/SocketConnectionImpl.java
+++ b/platform/platform-impl/src/com/intellij/util/io/socketConnection/impl/SocketConnectionImpl.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.io.socketConnection.*;
+import com.intellij.util.net.NetUtils;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
@@ -71,7 +72,7 @@
host = InetAddress.getLocalHost();
}
catch (UnknownHostException ignored) {
- host = InetAddress.getByName(null);
+ host = NetUtils.getLoopbackAddress();
}
}
@@ -89,6 +90,56 @@
throw exc;
}
+ public void connect() {
+ setStatus(ConnectionStatus.WAITING_FOR_CONNECTION, null);
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ Exception exception = null;
+ InetAddress host = myHost;
+ if (host == null) {
+ host = NetUtils.getLoopbackAddress();
+ }
+
+ for (int attempt = 0; attempt < MAX_CONNECTION_ATTEMPTS; attempt++) {
+ for (int i = 0; i < myPortsNumberToTry; i++) {
+ Socket socket;
+ try {
+ //noinspection SocketOpenedButNotSafelyClosed
+ socket = new Socket(host, myInitialPort + i);
+ }
+ catch (IOException e) {
+ LOG.debug(e);
+ exception = e;
+ continue;
+ }
+
+ setPort(socket.getPort());
+ try {
+ attachToSocket(socket);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ }
+ return;
+ }
+
+ try {
+ //noinspection BusyWait
+ Thread.sleep(CONNECTION_ATTEMPT_DELAY);
+ }
+ catch (InterruptedException e) {
+ exception = e;
+ break;
+ }
+ }
+
+ setStatus(ConnectionStatus.CONNECTION_FAILED,
+ exception == null ? "Connection failed" : "Connection failed: " + exception.getMessage());
+ }
+ });
+ }
+
@Override
public void startPolling() {
setStatus(ConnectionStatus.WAITING_FOR_CONNECTION, null);
diff --git a/platform/platform-impl/src/com/intellij/util/ui/CellEditorComponentWithBrowseButton.java b/platform/platform-impl/src/com/intellij/util/ui/CellEditorComponentWithBrowseButton.java
index dbb87f4..0725e4e 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/CellEditorComponentWithBrowseButton.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/CellEditorComponentWithBrowseButton.java
@@ -33,14 +33,16 @@
private final ComponentWithBrowseButton<Comp> myComponent;
private final TableCellEditor myEditor;
private final CellEditorListener myCellEditorListener = new CellEditorListener() {
- public void editingCanceled(ChangeEvent e) {
- onEditingFinished();
- }
+ @Override
+ public void editingCanceled(ChangeEvent e) {
+ onEditingFinished();
+ }
- public void editingStopped(ChangeEvent e) {
- onEditingFinished();
- }
- };
+ @Override
+ public void editingStopped(ChangeEvent e) {
+ onEditingFinished();
+ }
+ };
private boolean myEditingFinished = false;
public CellEditorComponentWithBrowseButton(ComponentWithBrowseButton<Comp> component, TableCellEditor editor) {
@@ -49,11 +51,13 @@
myEditor = editor;
add(myComponent, BorderLayout.CENTER);
registerKeyboardAction(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
myEditor.stopCellEditing();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
registerKeyboardAction(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
myEditor.cancelCellEditing();
}
@@ -68,20 +72,25 @@
return getComponentWithButton().getChildComponent();
}
+ @Override
public void requestFocus() {
myComponent.requestFocus();
}
+ @SuppressWarnings("deprecation")
+ @Override
public void setNextFocusableComponent(Component aComponent) {
myComponent.setNextFocusableComponent(aComponent);
}
+ @Override
public void addNotify() {
super.addNotify();
myEditingFinished = false;
myEditor.addCellEditorListener(myCellEditorListener);
}
+ @Override
public void removeNotify() {
if (!myEditingFinished) {
myEditor.stopCellEditing();
@@ -96,6 +105,7 @@
}
private KeyEvent myCurrentEvent = null;
+ @Override
protected boolean processKeyBinding(KeyStroke ks, KeyEvent e, int condition, boolean pressed) {
if (condition == WHEN_FOCUSED && myCurrentEvent != e)
try {
diff --git a/platform/platform-impl/src/com/intellij/util/ui/CheckBoxListModelEditor.java b/platform/platform-impl/src/com/intellij/util/ui/CheckBoxListModelEditor.java
new file mode 100644
index 0000000..a1a2b64
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/util/ui/CheckBoxListModelEditor.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.util.Pair;
+import com.intellij.ui.AnActionButton;
+import com.intellij.ui.AnActionButtonRunnable;
+import com.intellij.ui.CheckBoxList;
+import com.intellij.ui.ToolbarDecorator;
+import com.intellij.util.Consumer;
+import com.intellij.util.EditSourceOnDoubleClickHandler;
+import com.intellij.util.Function;
+import com.intellij.util.PlatformIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CheckBoxListModelEditor<T> {
+ private final CheckBoxList<T> list;
+ private final ToolbarDecorator toolbarDecorator;
+ private final Function<T, String> toNameConverter;
+
+ public CheckBoxListModelEditor(@NotNull Function<T, String> toNameConverter, @NotNull String emptyText) {
+ this.toNameConverter = toNameConverter;
+ list = new CheckBoxList<T>();
+ list.setEmptyText(emptyText);
+ // toolbar decorator is responsible for border
+ list.setBorder(null);
+ toolbarDecorator = ToolbarDecorator.createDecorator(list);
+ }
+
+ @NotNull
+ public CheckBoxListModelEditor<T> editAction(final @NotNull Function<T, T> consumer) {
+ final Runnable action = new Runnable() {
+ @Override
+ public void run() {
+ T item = getSelectedItem();
+ if (item != null) {
+ T newItem = consumer.fun(item);
+ if (newItem != null) {
+ list.updateItem(item, newItem);
+ }
+ list.repaint();
+ list.requestFocus();
+ }
+ }
+ };
+ toolbarDecorator.setEditAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ action.run();
+ }
+ });
+ EditSourceOnDoubleClickHandler.install(list, action);
+ return this;
+ }
+
+ @NotNull
+ public CheckBoxListModelEditor<T> copyAction(final @NotNull Consumer<T> consumer) {
+ toolbarDecorator.addExtraAction(new ToolbarDecorator.ElementActionButton(IdeBundle.message("button.copy"), PlatformIcons.COPY_ICON) {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ int[] indices = list.getSelectedIndices();
+ if (indices == null || indices.length == 0) {
+ return;
+ }
+
+ for (int index : indices) {
+ T item = list.getItemAt(index);
+ if (item != null) {
+ consumer.consume(item);
+ }
+ }
+ }
+ });
+ return this;
+ }
+
+ public ToolbarDecorator getToolbar() {
+ return toolbarDecorator;
+ }
+
+ @NotNull
+ public JComponent createComponent() {
+ return toolbarDecorator.createPanel();
+ }
+
+ @NotNull
+ public DefaultListModel getModel() {
+ return ((DefaultListModel)list.getModel());
+ }
+
+ public void selectItemByName(@NotNull String name) {
+ for (int i = 0; i < list.getItemsCount(); i++) {
+ T item = list.getItemAt(i);
+ if (item != null && name.equalsIgnoreCase(toNameConverter.fun(item))) {
+ list.setSelectedIndex(i);
+ }
+ }
+ }
+
+ @Nullable
+ private T getSelectedItem() {
+ int index = list.getSelectedIndex();
+ return index == -1 ? null : list.getItemAt(index);
+ }
+
+ public CheckBoxList<T> getList() {
+ return list;
+ }
+
+ public void reset(@NotNull List<Pair<T, Boolean>> items) {
+ list.clear();
+ for (Pair<T, Boolean> item : items) {
+ list.addItem(item.first, toNameConverter.fun(item.first), item.second);
+ }
+ }
+
+ public boolean isModified(@NotNull List<Pair<T, Boolean>> oldItems) {
+ if (oldItems.size() != list.getItemsCount()) {
+ return true;
+ }
+
+ for (int i = 0; i < list.getItemsCount(); i++) {
+ T item = list.getItemAt(i);
+ if (item == null) {
+ return true;
+ }
+
+ Pair<T, Boolean> oldItem = oldItems.get(i);
+ if (oldItem.second != list.isItemSelected(i) || !oldItem.first.equals(item)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @NotNull
+ public List<T> getItems() {
+ int count = list.getItemsCount();
+ List<T> result = new ArrayList<T>(count);
+ for (int i = 0; i < count; i++) {
+ T item = list.getItemAt(i);
+ if (item != null) {
+ result.add(item);
+ }
+ }
+ return result;
+ }
+
+ @NotNull
+ public List<Pair<T, Boolean>> apply() {
+ int count = list.getItemsCount();
+ List<Pair<T, Boolean>> result = new ArrayList<Pair<T, Boolean>>(count);
+ for (int i = 0; i < count; i++) {
+ T item = list.getItemAt(i);
+ if (item != null) {
+ result.add(Pair.create(item, list.isItemSelected(i)));
+ }
+ }
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java b/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java
index d6977c5..8fac256 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/LocalPathCellEditor.java
@@ -17,12 +17,17 @@
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Consumer;
+import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -33,44 +38,78 @@
private final String myTitle;
private final Project myProject;
- private CellEditorComponentWithBrowseButton<JTextField> myComponent;
+ private FileChooserDescriptor myFileChooserDescriptor;
+ private boolean myNormalizePath;
- public LocalPathCellEditor(String title, Project project) {
+ protected CellEditorComponentWithBrowseButton<JTextField> myComponent;
+
+ public LocalPathCellEditor(@Nullable String title, @Nullable Project project) {
myTitle = title;
myProject = project;
}
- public Object getCellEditorValue() {
- return myComponent.getChildComponent().getText();
+ public LocalPathCellEditor(@Nullable Project project) {
+ this(null, project);
}
+ public LocalPathCellEditor() {
+ this(null, null);
+ }
+
+ public LocalPathCellEditor fileChooserDescriptor(@NotNull FileChooserDescriptor value) {
+ myFileChooserDescriptor = value;
+ return this;
+ }
+
+ /**
+ * If true, path will be nullified and converted to system dependent
+ */
+ public LocalPathCellEditor normalizePath(boolean value) {
+ myNormalizePath = value;
+ return this;
+ }
+
+ @Override
+ public Object getCellEditorValue() {
+ String value = myComponent.getChildComponent().getText();
+ return myNormalizePath ? PathUtil.toSystemDependentName(StringUtil.nullize(value)) : value;
+ }
+
+ @Override
public Component getTableCellEditorComponent(final JTable table, Object value, boolean isSelected, final int row, int column) {
- ActionListener listener = new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- final FileChooserDescriptor d = getFileChooserDescriptor();
- String initial = (String)getCellEditorValue();
- VirtualFile initialFile = StringUtil.isNotEmpty(initial) ? LocalFileSystem.getInstance().findFileByPath(initial) : null;
- VirtualFile file = FileChooser.chooseFile(d, table, myProject, initialFile);
- if (file != null) {
- String path = file.getPresentableUrl();
- if (SystemInfo.isWindows && path.length() == 2 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') {
- path += "\\"; // make path absolute
- }
- myComponent.getChildComponent().setText(path);
- }
- }
- };
- myComponent = new CellEditorComponentWithBrowseButton<JTextField>(new TextFieldWithBrowseButton(listener), this);
+ myComponent = new CellEditorComponentWithBrowseButton<JTextField>(new TextFieldWithBrowseButton(createActionListener(table)), this);
myComponent.getChildComponent().setText((String)value);
return myComponent;
}
+ protected ActionListener createActionListener(final JTable table) {
+ return new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ String initial = (String)getCellEditorValue();
+ VirtualFile initialFile = StringUtil.isNotEmpty(initial) ? LocalFileSystem.getInstance().findFileByPath(initial) : null;
+ FileChooser.chooseFile(getFileChooserDescriptor(), myProject, table, initialFile, new Consumer<VirtualFile>() {
+ @Override
+ public void consume(VirtualFile file) {
+ String path = file.getPresentableUrl();
+ if (SystemInfo.isWindows && path.length() == 2 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') {
+ path += "\\"; // make path absolute
+ }
+ myComponent.getChildComponent().setText(path);
+ }
+ });
+ }
+ };
+ }
+
public FileChooserDescriptor getFileChooserDescriptor() {
- FileChooserDescriptor d = new FileChooserDescriptor(false, true, false, true, false, false);
- if (myTitle != null) {
- d.setTitle(myTitle);
+ if (myFileChooserDescriptor == null) {
+ myFileChooserDescriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
+ if (myTitle != null) {
+ myFileChooserDescriptor.setTitle(myTitle);
+ }
+ myFileChooserDescriptor.setShowFileSystemRoots(true);
}
- d.setShowFileSystemRoots(true);
- return d;
+ return myFileChooserDescriptor;
}
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/TextTransferable.java b/platform/platform-impl/src/com/intellij/util/ui/TextTransferable.java
index ea77f72..f6b622a 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/TextTransferable.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/TextTransferable.java
@@ -16,7 +16,12 @@
package com.intellij.util.ui;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.ui.ColoredTextContainer;
+import com.intellij.ui.SimpleTextAttributes;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
@@ -57,10 +62,12 @@
myPlainContent = plainContent;
}
+ @Override
public DataFlavor[] getTransferDataFlavors() {
return getFlavours().clone();
}
+ @Override
public boolean isDataFlavorSupported(DataFlavor flavor) {
for (DataFlavor f : getFlavours()) {
if (flavor.equals(f)) {
@@ -70,6 +77,7 @@
return false;
}
+ @Override
public Object getTransferData(final DataFlavor flavor) throws UnsupportedFlavorException, IOException {
if (flavor.equals(html)) {
return myHtmlContent;
@@ -82,4 +90,37 @@
}
throw new UnsupportedFlavorException(flavor);
}
+
+ public static class ColoredStringBuilder implements ColoredTextContainer {
+ private final StringBuilder builder = new StringBuilder();
+
+ public void appendTo(@NotNull StringBuilder... subBuilders) {
+ for (StringBuilder subBuilder : subBuilders) {
+ subBuilder.append(builder);
+ }
+ builder.setLength(0);
+ }
+
+ @Override
+ public void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes) {
+ builder.append(fragment);
+ }
+
+ @Override
+ public void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes, Object tag) {
+ builder.append(fragment);
+ }
+
+ @Override
+ public void setIcon(@Nullable Icon icon) {
+ }
+
+ @Override
+ public void setToolTipText(@Nullable String text) {
+ }
+
+ public StringBuilder getBuilder() {
+ return builder;
+ }
+ }
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/ComboBoxTableCellEditor.java b/platform/platform-impl/src/com/intellij/util/ui/table/ComboBoxTableCellEditor.java
new file mode 100644
index 0000000..1dc8759
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/util/ui/table/ComboBoxTableCellEditor.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.table;
+
+import com.intellij.openapi.util.Iconable;
+import com.intellij.ui.EnumComboBoxModel;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.ui.PopupMenuListenerAdapter;
+import com.intellij.util.ListWithSelection;
+import org.jdesktop.swingx.combobox.ListComboBoxModel;
+
+import javax.swing.*;
+import javax.swing.event.PopupMenuEvent;
+import java.awt.*;
+import java.util.Collections;
+
+/**
+ * Supported value type: {@link ListWithSelection} and {@link java.lang.Enum}.
+ * Value type can implement {@link com.intellij.openapi.util.Iconable} to display icon.
+ */
+public class ComboBoxTableCellEditor extends DefaultCellEditor {
+ public static final ComboBoxTableCellEditor INSTANCE = new ComboBoxTableCellEditor();
+
+ private final JComboBox comboBox;
+
+ public ComboBoxTableCellEditor() {
+ //noinspection unchecked,UndesirableClassUsage
+ super(new JComboBox(new ListComboBoxModel(Collections.emptyList())));
+
+ comboBox = (JComboBox)getComponent();
+
+ // problem: pop-up opened - closed by esc - editing is not canceled, but must be
+ comboBox.addPopupMenuListener(new PopupMenuListenerAdapter() {
+ @Override
+ public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+ cancelCellEditing();
+ }
+
+ @Override
+ public void popupMenuCanceled(PopupMenuEvent e) {
+ cancelCellEditing();
+ }
+ });
+
+ //noinspection unchecked
+ comboBox.setRenderer(new ListCellRendererWrapper() {
+ @Override
+ public void customize(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ setIcon(value instanceof Iconable ? ((Iconable)value).getIcon(Iconable.ICON_FLAG_VISIBILITY) : null);
+ }
+ });
+ }
+
+ @Override
+ public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
+ if (value instanceof ListWithSelection) {
+ ListWithSelection options = (ListWithSelection)value;
+ //noinspection unchecked
+ comboBox.setModel(new ListComboBoxModel(options));
+
+ if (options.getSelection() == null) {
+ options.selectFirst();
+ }
+ comboBox.setSelectedItem(options.getSelection());
+ }
+ else {
+ Enum enumValue = (Enum)value;
+ Class enumClass = enumValue.getDeclaringClass();
+ //noinspection unchecked
+ ComboBoxModel model = comboBox.getModel();
+ if (!(model instanceof EnumComboBoxModel && model.getSize() > 0 && ((Enum)model.getElementAt(0)).getDeclaringClass() == enumClass)) {
+ //noinspection unchecked
+ comboBox.setModel(new EnumComboBoxModel(enumClass));
+ }
+ comboBox.setSelectedItem(value);
+ }
+
+ return comboBox;
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/IconTableCellRenderer.java b/platform/platform-impl/src/com/intellij/util/ui/table/IconTableCellRenderer.java
new file mode 100644
index 0000000..5da0b04
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/util/ui/table/IconTableCellRenderer.java
@@ -0,0 +1,49 @@
+package com.intellij.util.ui.table;
+
+import com.intellij.openapi.util.Iconable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.table.DefaultTableCellRenderer;
+import javax.swing.table.TableCellRenderer;
+import java.awt.*;
+
+public abstract class IconTableCellRenderer<T> extends DefaultTableCellRenderer {
+ public static final IconTableCellRenderer<Iconable> ICONABLE = new IconTableCellRenderer<Iconable>() {
+ @Nullable
+ @Override
+ protected Icon getIcon(@NotNull Iconable value, JTable table, int row) {
+ return value.getIcon(Iconable.ICON_FLAG_VISIBILITY);
+ }
+ };
+
+ public static TableCellRenderer create(@NotNull final Icon icon) {
+ return new IconTableCellRenderer() {
+ @Nullable
+ @Override
+ protected Icon getIcon(@NotNull Object value, JTable table, int row) {
+ return icon;
+ }
+ };
+ }
+
+ @Override
+ public Component getTableCellRendererComponent(JTable table, Object value, boolean selected, boolean focus, int row, int column) {
+ super.getTableCellRendererComponent(table, value, selected, focus, row, column);
+ //noinspection unchecked
+ setIcon(value == null ? null : getIcon((T)value, table, row));
+ if (isCenterAlignment()) {
+ setHorizontalAlignment(CENTER);
+ setVerticalAlignment(CENTER);
+ }
+ return this;
+ }
+
+ protected boolean isCenterAlignment() {
+ return false;
+ }
+
+ @Nullable
+ protected abstract Icon getIcon(@NotNull T value, JTable table, int row);
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java
index 7aa8d29..f5c83fb 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTable.java
@@ -324,7 +324,12 @@
sleep(50);
final JScrollBar bar = myScrollPane.getVerticalScrollBar();
if (bar == null || !bar.isVisible()) {
- myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
+ }
+ });
+ sleep(15);
}
while (currentHeight != neededHeight) {
if (Math.abs(currentHeight - neededHeight) < step) {
@@ -359,11 +364,11 @@
}
catch (InterruptedException ignore) {
} finally {
- TableUtil.scrollSelectionToVisible(myTable);
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
+ TableUtil.scrollSelectionToVisible(myTable);
if (exitEditing && !myTable.isEditing()) {
myScrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
}
diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java
index 0dce4bb..3f4b99b 100644
--- a/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.java
+++ b/platform/platform-impl/src/com/intellij/util/ui/table/JBListTableModel.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.
diff --git a/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java b/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java
new file mode 100644
index 0000000..23f49f6
--- /dev/null
+++ b/platform/platform-impl/src/com/intellij/util/ui/table/TableModelEditor.java
@@ -0,0 +1,401 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ui.table;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.Ref;
+import com.intellij.ui.*;
+import com.intellij.ui.table.TableView;
+import com.intellij.util.Function;
+import com.intellij.util.FunctionUtil;
+import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.ColumnInfo;
+import com.intellij.util.ui.ElementProducer;
+import com.intellij.util.ui.ListTableModel;
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import gnu.trove.THashMap;
+import gnu.trove.TObjectObjectProcedure;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+import javax.swing.table.TableModel;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TableModelEditor<T> implements ElementProducer<T> {
+ private final TableView<T> table;
+ private final ToolbarDecorator toolbarDecorator;
+
+ private final ItemEditor<T> itemEditor;
+
+ private final MyListTableModel<T> model;
+
+ /**
+ * source will be copied, passed list will not be used directly
+ *
+ * Implement {@link DialogItemEditor} instead of {@link ItemEditor} if you want provide dialog to edit.
+ */
+ public TableModelEditor(@NotNull List<T> items, @NotNull ColumnInfo[] columns, @NotNull ItemEditor<T> itemEditor, @NotNull String emptyText) {
+ this.itemEditor = itemEditor;
+
+ model = new MyListTableModel<T>(columns, new ArrayList<T>(items), this);
+ table = new TableView<T>(model);
+ table.setDefaultEditor(Enum.class, ComboBoxTableCellEditor.INSTANCE);
+ table.setStriped(true);
+ new TableSpeedSearch(table);
+ if (columns[0].getColumnClass() == Boolean.class && columns[0].getName().isEmpty()) {
+ TableUtil.setupCheckboxColumn(table.getColumnModel().getColumn(0));
+ }
+
+ table.getEmptyText().setText(emptyText);
+ MyRemoveAction removeAction = new MyRemoveAction();
+ toolbarDecorator = ToolbarDecorator.createDecorator(table, this).setRemoveAction(removeAction).setRemoveActionUpdater(removeAction);
+
+ if (itemEditor instanceof DialogItemEditor) {
+ toolbarDecorator.setEditAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ T item = table.getSelectedObject();
+ if (item != null) {
+ Function<T, T> mutator;
+ if (model.isMutable(item)) {
+ mutator = FunctionUtil.id();
+ }
+ else {
+ final int selectedRow = table.getSelectedRow();
+ mutator = new Function<T, T>() {
+ @Override
+ public T fun(T item) {
+ return model.getMutable(selectedRow, item);
+ }
+ };
+ }
+ ((DialogItemEditor<T>)TableModelEditor.this.itemEditor).edit(item, mutator);
+ table.requestFocus();
+ }
+ }
+ }).setEditActionUpdater(new AnActionButtonUpdater() {
+ @Override
+ public boolean isEnabled(AnActionEvent e) {
+ T item = table.getSelectedObject();
+ return item != null && ((DialogItemEditor<T>)TableModelEditor.this.itemEditor).isEditable(item);
+ }
+ });
+ }
+ }
+
+ public static abstract class DataChangedListener<T> implements TableModelListener {
+ public abstract void dataChanged(@NotNull ColumnInfo<T, ?> columnInfo, int rowIndex);
+
+ @Override
+ public void tableChanged(TableModelEvent e) {
+ }
+ }
+
+ public TableModelEditor<T> modelListener(@NotNull DataChangedListener<T> listener) {
+ model.dataChangedListener = listener;
+ model.addTableModelListener(listener);
+ return this;
+ }
+
+ @NotNull
+ public ListTableModel<T> getModel() {
+ return model;
+ }
+
+ public static abstract class ItemEditor<T> {
+ /**
+ * Used for "copy" and "in place edit" actions.
+ *
+ * You must perform deep clone in case of "add" operation, but in case of "in place edit" you should copy only exposed (via column) properties.
+ */
+ public abstract T clone(@NotNull T item, boolean forInPlaceEditing);
+
+ @NotNull
+ /**
+ * Class must have empty constructor.
+ */
+ public abstract Class<T> getItemClass();
+
+ public boolean isRemovable(@NotNull T item) {
+ return true;
+ }
+ }
+
+ public static abstract class DialogItemEditor<T> extends ItemEditor<T> {
+ public abstract void edit(@NotNull T item, @NotNull Function<T, T> mutator);
+
+ public abstract void applyEdited(@NotNull T oldItem, @NotNull T newItem);
+
+ public boolean isEditable(@NotNull T item) {
+ return true;
+ }
+ }
+
+ @NotNull
+ public static <T> T cloneUsingXmlSerialization(@NotNull T oldItem, @NotNull T newItem) {
+ Element serialized = XmlSerializer.serialize(oldItem, new SkipDefaultValuesSerializationFilters());
+ if (!JDOMUtil.isEmpty(serialized)) {
+ XmlSerializer.deserializeInto(newItem, serialized);
+ }
+ return newItem;
+ }
+
+ private static final class MyListTableModel<T> extends ListTableModel<T> {
+ private List<T> items;
+ private final TableModelEditor<T> editor;
+ private final THashMap<T, T> modifiedToOriginal = new THashMap<T, T>();
+ private DataChangedListener<T> dataChangedListener;
+
+ public MyListTableModel(@NotNull ColumnInfo[] columns, @NotNull List<T> items, @NotNull TableModelEditor<T> editor) {
+ super(columns, items);
+
+ this.items = items;
+ this.editor = editor;
+ }
+
+ @Override
+ public void setItems(@NotNull List<T> items) {
+ modifiedToOriginal.clear();
+ this.items = items;
+ super.setItems(items);
+ }
+
+ @Override
+ public void removeRow(int index) {
+ modifiedToOriginal.remove(getItem(index));
+ super.removeRow(index);
+ }
+
+ @Override
+ public void setValueAt(Object newValue, int rowIndex, int columnIndex) {
+ if (rowIndex < getRowCount()) {
+ @SuppressWarnings("unchecked")
+ ColumnInfo<T, Object> column = (ColumnInfo<T, Object>)getColumnInfos()[columnIndex];
+ T item = getItem(rowIndex);
+ Object oldValue = column.valueOf(item);
+ if (column.getColumnClass() == String.class
+ ? !Comparing.strEqual(((String)oldValue), ((String)newValue))
+ : !Comparing.equal(oldValue, newValue)) {
+
+ column.setValue(getMutable(rowIndex, item), newValue);
+ if (dataChangedListener != null) {
+ dataChangedListener.dataChanged(column, rowIndex);
+ }
+ }
+ }
+ }
+
+ private T getMutable(int rowIndex, T item) {
+ if (isMutable(item)) {
+ return item;
+ }
+ else {
+ T mutable = editor.itemEditor.clone(item, true);
+ modifiedToOriginal.put(mutable, item);
+ items.set(rowIndex, mutable);
+ return mutable;
+ }
+ }
+
+ private boolean isMutable(T item) {
+ return modifiedToOriginal.containsKey(item);
+ }
+
+ public boolean isModified(@NotNull List<T> oldItems) {
+ if (items.size() != oldItems.size()) {
+ return true;
+ }
+ else {
+ for (int i = 0, size = items.size(); i < size; i++) {
+ if (!items.get(i).equals(oldItems.get(i))) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ @NotNull
+ public List<T> apply() {
+ if (modifiedToOriginal.isEmpty()) {
+ return items;
+ }
+
+ @SuppressWarnings("unchecked")
+ final ColumnInfo<T, Object>[] columns = getColumnInfos();
+ modifiedToOriginal.forEachEntry(new TObjectObjectProcedure<T, T>() {
+ @Override
+ public boolean execute(T newItem, @Nullable T oldItem) {
+ if (oldItem == null) {
+ // it is added item, we don't need to sync
+ return true;
+ }
+
+ for (ColumnInfo<T, Object> column : columns) {
+ if (column.isCellEditable(newItem)) {
+ column.setValue(oldItem, column.valueOf(newItem));
+ }
+ }
+
+ if (editor.itemEditor instanceof DialogItemEditor) {
+ ((DialogItemEditor<T>)editor.itemEditor).applyEdited(oldItem, newItem);
+ }
+
+ items.set(ContainerUtil.indexOfIdentity(items, newItem), oldItem);
+ return true;
+ }
+ });
+
+ modifiedToOriginal.clear();
+ return items;
+ }
+ }
+
+ public abstract static class EditableColumnInfo<Item, Aspect> extends ColumnInfo<Item, Aspect> {
+ public EditableColumnInfo(@NotNull String name) {
+ super(name);
+ }
+
+ public EditableColumnInfo() {
+ super("");
+ }
+
+ @Override
+ public boolean isCellEditable(Item item) {
+ return true;
+ }
+ }
+
+ @NotNull
+ public JComponent createComponent() {
+ return toolbarDecorator.addExtraAction(
+ new ToolbarDecorator.ElementActionButton(IdeBundle.message("button.copy"), PlatformIcons.COPY_ICON) {
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ TableUtil.stopEditing(table);
+
+ List<T> selectedItems = table.getSelectedObjects();
+ if (selectedItems.isEmpty()) {
+ return;
+ }
+
+ for (T item : selectedItems) {
+ model.addRow(itemEditor.clone(item, false));
+ }
+
+ table.requestFocus();
+ TableUtil.updateScroller(table, false);
+ }
+ }
+ ).createPanel();
+ }
+
+ @Override
+ public T createElement() {
+ try {
+ Constructor<T> constructor = itemEditor.getItemClass().getDeclaredConstructor();
+ try {
+ constructor.setAccessible(true);
+ }
+ catch (SecurityException e) {
+ return itemEditor.getItemClass().newInstance();
+ }
+ return constructor.newInstance();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ @Override
+ public boolean canCreateElement() {
+ return true;
+ }
+
+ public boolean isModified(@NotNull List<T> oldItems) {
+ return model.isModified(oldItems);
+ }
+
+ public void selectItem(@NotNull final T item) {
+ table.clearSelection();
+
+ final Ref<T> ref;
+ if (model.modifiedToOriginal.isEmpty()) {
+ ref = null;
+ }
+ else {
+ ref = Ref.create();
+ model.modifiedToOriginal.forEachEntry(new TObjectObjectProcedure<T, T>() {
+ @Override
+ public boolean execute(T modified, T original) {
+ if (item == original) {
+ ref.set(modified);
+ }
+ return ref.isNull();
+ }
+ });
+ }
+
+ table.addSelection(ref == null || ref.isNull() ? item : ref.get());
+ }
+
+ @NotNull
+ public List<T> apply() {
+ return model.apply();
+ }
+
+ public void reset(@NotNull List<T> items) {
+ model.setItems(new ArrayList<T>(items));
+ }
+
+ private class MyRemoveAction implements AnActionButtonRunnable, AnActionButtonUpdater, TableUtil.ItemChecker {
+ @Override
+ public void run(AnActionButton button) {
+ if (TableUtil.doRemoveSelectedItems(table, model, this)) {
+ table.requestFocus();
+ TableUtil.updateScroller(table, false);
+ }
+ }
+
+ @Override
+ public boolean isOperationApplyable(@NotNull TableModel ignored, int row) {
+ T item = model.getItem(row);
+ return item != null && itemEditor.isRemovable(item);
+ }
+
+ @Override
+ public boolean isEnabled(AnActionEvent e) {
+ for (T item : table.getSelectedObjects()) {
+ if (itemEditor.isRemovable(item)) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-impl/src/net/sf/cglib/core/AbstractClassGenerator.java b/platform/platform-impl/src/net/sf/cglib/core/AbstractClassGenerator.java
index 9f2bbc1..42bc230 100644
--- a/platform/platform-impl/src/net/sf/cglib/core/AbstractClassGenerator.java
+++ b/platform/platform-impl/src/net/sf/cglib/core/AbstractClassGenerator.java
@@ -15,6 +15,7 @@
*/
package net.sf.cglib.core;
+import com.intellij.reference.SoftReference;
import org.objectweb.asm.ClassReader;
import java.lang.ref.Reference;
@@ -199,7 +200,7 @@
source.cache.put(loader, cache2);
} else if (useCache) {
Reference ref = (Reference)cache2.get(key);
- gen = (Class) (( ref == null ) ? null : ref.get());
+ gen = (Class) SoftReference.dereference(ref);
}
if (gen == null) {
Object save = CURRENT.get();
diff --git a/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java b/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java
index 7f77a0a..f13ca66 100644
--- a/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java
+++ b/platform/platform-impl/src/net/sf/cglib/proxy/AdvancedEnhancer.java
@@ -17,11 +17,11 @@
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.cl.PluginClassLoader;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
+import net.sf.cglib.core.*;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.Label;
import org.objectweb.asm.Type;
-import net.sf.cglib.core.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -567,7 +567,7 @@
continue;
}
- if (ReflectionCache.isAssignable(actualMethod.getReturnType(), method.getReturnType())) {
+ if (ReflectionUtil.isAssignable(actualMethod.getReturnType(), method.getReturnType())) {
if ((actualMethod.getModifiers() & Constants.ACC_ABSTRACT) != 0 || (actualMethod.getModifiers() & Constants.ACC_SYNTHETIC) != 0) {
covariantMethods.put(actualMethod, method); //generate bridge
}
diff --git a/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java b/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
index b1ee562..c5609e1 100644
--- a/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
+++ b/platform/platform-impl/src/org/jetbrains/ide/BuiltInServerManagerImpl.java
@@ -20,6 +20,7 @@
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.io.BuiltInServer;
+import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -39,6 +40,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");
+ }
+
@Override
public int getPort() {
return detectedPortNumber == -1 ? getDefaultPort() : detectedPortNumber;
diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java b/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
index 748d222..478a3fa 100644
--- a/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/ChannelExceptionHandler.java
@@ -17,22 +17,21 @@
import com.intellij.openapi.diagnostic.Logger;
import io.netty.channel.ChannelHandler;
+import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandler;
-import io.netty.channel.ChannelInboundHandlerAdapter;
import java.net.ConnectException;
@ChannelHandler.Sharable
-public final class ChannelExceptionHandler extends ChannelInboundHandlerAdapter {
+public final class ChannelExceptionHandler extends ChannelHandlerAdapter {
private static final Logger LOG = Logger.getInstance(ChannelExceptionHandler.class);
- private static final ChannelInboundHandler INSTANCE = new ChannelExceptionHandler();
+ private static final ChannelHandler INSTANCE = new ChannelExceptionHandler();
private ChannelExceptionHandler() {
}
- public static ChannelInboundHandler getInstance() {
+ public static ChannelHandler getInstance() {
return INSTANCE;
}
diff --git a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
index 5565e77..537ef90 100644
--- a/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
+++ b/platform/platform-impl/src/org/jetbrains/io/ChannelRegistrar.java
@@ -9,7 +9,7 @@
import java.util.concurrent.TimeUnit;
@ChannelHandler.Sharable
-public final class ChannelRegistrar extends ChannelInboundHandlerAdapter {
+public final class ChannelRegistrar extends ChannelHandlerAdapter {
private final ChannelGroup openChannels = new DefaultChannelGroup(ImmediateEventExecutor.INSTANCE);
public boolean isEmpty() {
diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
index 305565a..4ed354d 100644
--- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandler.java
@@ -37,7 +37,7 @@
@ChannelHandler.Sharable
final class DelegatingHttpRequestHandler extends DelegatingHttpRequestHandlerBase {
- private static final AttributeKey<HttpRequestHandler> PREV_HANDLER = new AttributeKey<HttpRequestHandler>("DelegatingHttpRequestHandler.handler");
+ private static final AttributeKey<HttpRequestHandler> PREV_HANDLER = AttributeKey.valueOf("DelegatingHttpRequestHandler.handler");
@Override
protected boolean process(ChannelHandlerContext context, FullHttpRequest request, QueryStringDecoder urlDecoder) throws IOException, ImageWriteException {
diff --git a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java
index 7509e60..3758762 100644
--- a/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java
+++ b/platform/platform-impl/src/org/jetbrains/io/DelegatingHttpRequestHandlerBase.java
@@ -23,7 +23,7 @@
abstract class DelegatingHttpRequestHandlerBase extends SimpleChannelInboundHandler<FullHttpRequest> {
@Override
- protected void channelRead0(ChannelHandlerContext context, FullHttpRequest message) throws Exception {
+ protected void messageReceived(ChannelHandlerContext context, FullHttpRequest message) throws Exception {
if (BuiltInServer.LOG.isDebugEnabled()) {
// BuiltInServer.LOG.debug("IN HTTP:\n" + message);
BuiltInServer.LOG.debug("IN HTTP: " + message.getUri());
diff --git a/platform/platform-impl/src/org/jetbrains/io/LocalFileFinder.java b/platform/platform-impl/src/org/jetbrains/io/LocalFileFinder.java
index bffc7a9..2cd8fb4 100644
--- a/platform/platform-impl/src/org/jetbrains/io/LocalFileFinder.java
+++ b/platform/platform-impl/src/org/jetbrains/io/LocalFileFinder.java
@@ -28,13 +28,15 @@
Method is not generic and is not suitable for all.
*/
public static VirtualFile findFile(@NotNull String path) {
- if (!SystemInfo.isWindows || windowsDriveExists(path)) {
+ if (windowsDriveExists(path)) {
return LocalFileSystem.getInstance().findFileByPath(path);
}
return null;
}
- private static boolean windowsDriveExists(@NotNull String path) {
+ public static boolean windowsDriveExists(@NotNull String path) {
+ if (!SystemInfo.isWindows) return true;
+
if (path.length() > 2 && Character.isLetter(path.charAt(0)) && path.charAt(1) == ':') {
final char driveLetter = Character.toUpperCase(path.charAt(0));
final Boolean driveExists = myWindowsDrivesMap.getIfPresent(driveLetter);
diff --git a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
index e70f0ca..0e9fc6a 100644
--- a/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
+++ b/platform/platform-impl/src/org/jetbrains/io/PortUnificationServerHandler.java
@@ -78,7 +78,7 @@
}
@Override
- protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+ protected void messageReceived(ChannelHandlerContext context, ByteBuf message) throws Exception {
ByteBuf buffer = getBufferIfSufficient(message, 5, context);
if (buffer == null) {
message.release();
@@ -107,7 +107,7 @@
NettyUtil.initHttpHandlers(pipeline);
pipeline.addLast(delegatingHttpRequestHandler);
if (BuiltInServer.LOG.isDebugEnabled()) {
- pipeline.addLast(new ChannelOutboundHandlerAdapter() {
+ pipeline.addLast(new ChannelHandlerAdapter() {
@Override
public void write(ChannelHandlerContext context, Object message, ChannelPromise promise) throws Exception {
if (message instanceof HttpResponse) {
@@ -136,7 +136,7 @@
}
private static void ensureThatExceptionHandlerIsLast(ChannelPipeline pipeline) {
- ChannelInboundHandler exceptionHandler = ChannelExceptionHandler.getInstance();
+ ChannelHandler exceptionHandler = ChannelExceptionHandler.getInstance();
if (pipeline.last() != exceptionHandler || pipeline.context(exceptionHandler) == null) {
return;
}
@@ -162,7 +162,7 @@
private static final int UUID_LENGTH = 16;
@Override
- protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+ protected void messageReceived(ChannelHandlerContext context, ByteBuf message) throws Exception {
ByteBuf buffer = getBufferIfSufficient(message, UUID_LENGTH, context);
if (buffer == null) {
message.release();
diff --git a/platform/platform-main/src/com/intellij/idea/MainImpl.java b/platform/platform-main/src/com/intellij/idea/MainImpl.java
index afaf62e..32a41d4 100644
--- a/platform/platform-main/src/com/intellij/idea/MainImpl.java
+++ b/platform/platform-main/src/com/intellij/idea/MainImpl.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,7 +17,6 @@
import com.intellij.ide.plugins.PluginManager;
import com.intellij.util.PlatformUtils;
-import com.intellij.util.PlatformUtilsCore;
import javax.swing.*;
@@ -29,7 +28,7 @@
* Called from PluginManager via reflection.
*/
protected static void start(final String[] args) {
- System.setProperty(PlatformUtilsCore.PLATFORM_PREFIX_KEY, PlatformUtils.getPlatformPrefix(PlatformUtilsCore.COMMUNITY_PREFIX));
+ System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, PlatformUtils.getPlatformPrefix(PlatformUtils.IDEA_CE_PREFIX));
StartupUtil.prepareAndStart(args, new StartupUtil.AppStarter() {
@Override
diff --git a/platform/platform-resources-en/src/fileTemplates/internal/Html5.html.ft b/platform/platform-resources-en/src/fileTemplates/internal/Html5.html.ft
index 80455ed..19a0fbd 100644
--- a/platform/platform-resources-en/src/fileTemplates/internal/Html5.html.ft
+++ b/platform/platform-resources-en/src/fileTemplates/internal/Html5.html.ft
@@ -1,6 +1,7 @@
<!DOCTYPE html>
<html>
-<head>
+<head lang="en">
+ <meta charset="UTF-8">
<title></title>
</head>
<body>
diff --git a/platform/platform-resources-en/src/inspectionDescriptions/Duplicates.html b/platform/platform-resources-en/src/inspectionDescriptions/Duplicates.html
new file mode 100644
index 0000000..512169c
--- /dev/null
+++ b/platform/platform-resources-en/src/inspectionDescriptions/Duplicates.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+Finds duplicated code
+</body>
+</html>
diff --git a/platform/platform-resources-en/src/messages/ActionsBundle.properties b/platform/platform-resources-en/src/messages/ActionsBundle.properties
index a65aac0..ac04bd2 100644
--- a/platform/platform-resources-en/src/messages/ActionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/ActionsBundle.properties
@@ -105,6 +105,8 @@
action.EditorMoveDownAndScroll.text=Move Down and Scroll
action.EditorMoveUpAndScrollWithSelection.text=Move Up and Scroll with Selection
action.EditorMoveDownAndScrollWithSelection.text=Move Down and Scroll with Selection
+action.EditorCloneCaretBelow.text=Clone Caret Below
+action.EditorCloneCaretAbove.text=Clone Caret Above
action.EditorToggleStickySelection.text=Toggle Sticky Selection
action.EditorSwapSelectionBoundaries.text=Swap selection boundaries
action.EditorLineStart.text=Move Caret to Line Start
@@ -245,7 +247,7 @@
action.OpenProject.description=Open an existing project
action.OpenFile.text=_Open...
action.OpenFile.description=Open a project or a file in editor
-group.reopen.win.text=_Reopen
+group.reopen.win.text=_Reopen Project
group.reopen.mac.text=Open _Recent
group.$LRU.description=List of recently opened projects
action.CloseProject.text=Close Pro_ject
@@ -687,7 +689,7 @@
action.Runner.CloseOtherViews.description=Close other views
action.Runner.CloseAllViews.text=Close All
action.Runner.CloseAllViews.description=Close all views
-action.Runner.CloseAllUnpinnedViews.text=Close All But Pinned
+action.Runner.CloseAllUnpinnedViews.text=Close All but Pinned
action.Runner.CloseAllUnpinnedViews.description=Close all tabs which are not pinned
action.Runner.MoveViewToGrid.text=Move To Grid
action.Runner.MoveViewToGrid.description=Move view to the debugger grid container
@@ -821,7 +823,7 @@
action.CloseAllEditorsButActive.description=Close all open editors except the active one
action.CloseAllUnmodifiedEditors.text=Close _Unmodified
action.CloseAllUnmodifiedEditors.description=Close all non-modified editors
-action.CloseAllUnpinnedEditors.text=Close All But Pinned
+action.CloseAllUnpinnedEditors.text=Close All but Pinned
action.CloseAllUnpinnedEditors.description=Close all editors which are not pinned
action.CloseContent.text=_Close
action.CloseContent.description=Close currently focused content
@@ -1291,7 +1293,7 @@
action.RerunFailedTests.description=Run only tests that failed/crashed after last run
group.AnalyzeJavaMenu.text=Analyze Java Menu
group.AnalyzeJavaMenu.description=Analyze Java Menu
-action.InvalidateCaches.text=Invalidate Caches...
+action.InvalidateCaches.text=Invalidate Caches / Restart...
action.InvalidateCaches.description=Force rebuild of all caches and indices on next startup
group.ToolsBasicGroup.text=Tools Basic Group
group.ToolsBasicGroup.description=Tools Basic Group
@@ -1365,8 +1367,8 @@
action.Diff.UpdatedFiles.text=Show Diff
action.Diff.UpdatedFiles.description=Show diff with version before update
-action.TabList.text=Show All Tabs
-action.TabList.description=Show dropdown with the list of all tabs in single-row tab layout
+action.TabList.text=Show Hidden Tabs
+action.TabList.description=Show dropdown with the list of tabs that don't fit on the screen in single-row tab layout
action.FillParagraph.text=Fill Paragraph
action.FillParagraph.description=Reformat string literal or comment to fit maximum width (usually 80)
diff --git a/platform/platform-resources-en/src/messages/ApplicationBundle.properties b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
index 0b45e23..89e0f4e 100644
--- a/platform/platform-resources-en/src/messages/ApplicationBundle.properties
+++ b/platform/platform-resources-en/src/messages/ApplicationBundle.properties
@@ -248,6 +248,8 @@
group.spaces.within=Within
group.spaces.in.ternary.operator=In Ternary Operator (?:)
group.spaces.in.type.arguments=Within Type Arguments
+group.spaces.in.type.arguments.block=Type Arguments
+group.spaces.in.type.parameters.block=Type Parameters
group.spaces.other=Other
checkbox.spaces.method.call.parentheses=Method call parentheses
checkbox.spaces.method.declaration.parentheses=Method declaration parentheses
@@ -346,6 +348,7 @@
checkbox.collapse.annotations=<html>Annotations</html>
checkbox.collapse.inner.classes=Inner classes
checkbox.collapse.simple.property.accessors=<html>Simple property accessors<html>
+checkbox.collapse.one.line.methods=<html>One-line methods<html>
checkbox.collapse.method.bodies=Method bodies
checkbox.collapse.javadoc.comments=Documentation comments
checkbox.collapse.title.imports=Imports
diff --git a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties
index c9ac1ac..999edfc 100644
--- a/platform/platform-resources-en/src/messages/CodeInsightBundle.properties
+++ b/platform/platform-resources-en/src/messages/CodeInsightBundle.properties
@@ -26,6 +26,7 @@
progress.reformat.stage.applying.changes=Storing changes...
process.reformat.code=Reformat Code
process.reformat.code.before.commit=Reformat Code Before Commit
+process.rearrange.code.before.commit=Rearrange Code Before Commit
dialog.reformat.files.title=Reformat Files
dialog.reformat.files.optimize.imports.checkbox=&Optimize imports
dialog.reformat.files.reformat.selected.files.label=Reformat selected files?
@@ -104,7 +105,7 @@
generate.equals.hashcode.warning.hashcode.for.arrays.is.not.supported=hashCode () for arrays is not supported
highlight.thrown.exceptions.chooser.all.entry=All listed
highlight.exceptions.thrown.chooser.title=Choose Exception Classes to Highlight
-highlight.exceptions.thrown.notfound=No exceptions thrown in the method found
+highlight.exceptions.thrown.notfound=No exceptions thrown in the method found
status.bar.exit.points.highlighted.message={0} exit {0, choice, 1#point|2#points} highlighted (press {1} again to remove the highlighting, Escape to remove all highlighting)
status.bar.highlighted.usages.message={0} {0, choice, 1#usage|2#usages} of {1} found (press {2} again to remove the highlighting, Escape to remove all highlighting)
status.bar.highlighted.usages.no.target.message={0} {0, choice, 1#usage|2#usages} found (press {2} again to remove the highlighting, Escape to remove all highlighting)
@@ -273,7 +274,7 @@
javadoc.documentation.not.found.title=No Documentation
javadoc.fetching.progress=Fetching Documentation...
no.documentation.found=No documentation found.
-javadoc.candiates=<html>Candidates for method call <b>{0}</b> are:<br><br>{1}</html>
+javadoc.candidates=<html>Candidates for method call <b>{0}</b> are:<br><br>{1}</html>
javadoc.candidates.not.found=<html>No candidates found for method call <b>{0}</b>.</html>
declaration.navigation.title=Choose Declaration
template.shortcut.enter=Enter
@@ -491,4 +492,4 @@
dialog.edit.template.checkbox.xsl.text=XSL Text
highlight.imported.classes.chooser.title=Choose Imported Classes to Highlight
highlight.imported.members.chooser.title=Choose Imported Members to Highlight
-javadoc.resolved.value=Resolved value\:
\ No newline at end of file
+javadoc.resolved.value=Resolved value\:
diff --git a/platform/platform-resources-en/src/messages/CommonBundle.properties b/platform/platform-resources-en/src/messages/CommonBundle.properties
index f6fa936..7820960 100644
--- a/platform/platform-resources-en/src/messages/CommonBundle.properties
+++ b/platform/platform-resources-en/src/messages/CommonBundle.properties
@@ -13,7 +13,7 @@
editbox.password=&Password:
checkbox.remember.password=&Remember password
editbox.login=&Login:
-checkbox.use.http.proxy=&Use proxy
+checkbox.use.http.proxy=Manual proxy configuration
checkbox.proxy.authentication=Proxy &authentication
checkbox.use.http.proxy.pac=Auto-detect proxy settings
tooltip.http.proxy.pac=This will attempt to use your system settings and is useful if your system uses a proxy autoconfiguration file (.pac).
@@ -155,7 +155,6 @@
comparison.policy.default.name=Default
comparison.policy.trim.space.name=Trim space
comparison.policy.ignore.spaces.name=Ignore spaces
-comparison.ignore.whitespace.acton.name=Ignore whitespace:
safe.write.failed=Cannot save {0}.\nUnable to create a backup file ({1}).\nThe file left unchanged.
safe.write.rename.original=Cannot save {0}.\nThe file left unchanged.\nYour changes were written to {1}.
@@ -166,7 +165,7 @@
label.system.proxy.used=You have JVM property 'java.net.useSystemProxies' set to true.\n\
This will cause some network calls to go through operating system-defined proxy.\n\
If you didn't intend to use system-defined proxy, disable this property
-http.noproxy=No Proxy
+http.noproxy=No proxy
http.proxy.type=HTTP
socks.proxy.type=SOCKS
autodetected.proxies.clear.button=Clear passwords
@@ -174,4 +173,5 @@
This may lead to incorrect behaviour. Proxy should be set in Settings | HTTP Proxy\n\
This JVM property is old and its usage is not recommended by Oracle.\n\
\n(Note: It could have been assigned by some code dynamically.)
-label.proxy.exceptions.text=Example\: *.domain.com, 192.168.*
\ No newline at end of file
+label.proxy.exceptions.text=Example\: *.domain.com, 192.168.*
+checkbox.automatic.proxy.configuration.url=Automatic proxy configuration URL\:
\ No newline at end of file
diff --git a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties
index 0d8fd8f..1cbcb0c 100644
--- a/platform/platform-resources-en/src/messages/DiagnosticBundle.properties
+++ b/platform/platform-resources-en/src/messages/DiagnosticBundle.properties
@@ -71,6 +71,7 @@
log.console.filter.show.errors.warnings.and.infos=infos
log.console.filter.show.prefix=Log level:
error.comments.tab.title=Comments
+error.dialog.error.prompt=&Error message
error.dialog.comment.prompt=<html><u>P</u>lease fill in any details that may be important: steps to reproduce, what were you doing when problem occurred, etc.:</html>
error.details.tab.title=Details
error.dialog.disable.plugin.prompt.dependants=<html>Are you sure you would like to disable plugin <b>{0}</b>?<br/>Functionality provided by the plugin and dependent plugins will no longer be available.</html>
diff --git a/platform/platform-resources-en/src/messages/DiffBundle.properties b/platform/platform-resources-en/src/messages/DiffBundle.properties
index cb6a0d7..e604d4f 100644
--- a/platform/platform-resources-en/src/messages/DiffBundle.properties
+++ b/platform/platform-resources-en/src/messages/DiffBundle.properties
@@ -31,6 +31,7 @@
diff.acton.ignore.whitespace.policy.do.not.ignore=Do not ignore
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.dialog.select.change.action.name=Select Change
diff.dialog.select.change.action.description=Select changed text in this version and corresponding in other
@@ -83,3 +84,8 @@
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 --git a/platform/platform-resources-en/src/messages/DomBundle.properties b/platform/platform-resources-en/src/messages/DomBundle.properties
index d262608..1493234 100644
--- a/platform/platform-resources-en/src/messages/DomBundle.properties
+++ b/platform/platform-resources-en/src/messages/DomBundle.properties
@@ -7,7 +7,7 @@
remove.attribute.fix.name=Remove "{0}" attribute
message.invalid.value.quotation=Bad quotation for ''{0}''
-dom.usage.type=Usage in XML descriptor
+dom.usage.type={0} in XML descriptor
create.new.element=Create new {0} ''{1}''
choose.file=Choose file
diff --git a/platform/platform-resources-en/src/messages/FindBundle.properties b/platform/platform-resources-en/src/messages/FindBundle.properties
index 0dcd53a..20ec783 100644
--- a/platform/platform-resources-en/src/messages/FindBundle.properties
+++ b/platform/platform-resources-en/src/messages/FindBundle.properties
@@ -66,7 +66,7 @@
find.button=Find
find.all.button=Find &All
find.text.to.find.label=Text to &find:
-find.replace.with.label=&Replace with:
+find.replace.with.label=Replace &with:
find.filter.file.name.group=File name filter
find.filter.file.mask.checkbox=File m&ask(s)
find.directory.not.found.error=Directory {0} is not found
@@ -76,7 +76,7 @@
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.whole.words.only=&Whole words only (may be faster)
+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
find.options.regular.expressions=Re&gular expression
@@ -97,19 +97,18 @@
find.origin.entire.scope.radio=E&ntire scope
find.searching.for.string.in.file.progress=Searching for ''{0}'' in {1}...
find.searching.for.string.in.file.occurrences.progress={0,choice,0#No|1#{0}} {0,choice,0#occurrences|1#occurrence|2#occurrences} found so far
-find.excessive.total.size.prompt=Usages in files of total size {0} found. {1} may become unresponsive or even fail with OutOfMemoryError if you continue. Continue?
+find.excessive.total.size.prompt=Occurrences in files of total size {0} found. {1} may become unresponsive or even fail with OutOfMemoryError if you continue. Continue?
find.progress.search.completed=Search completed
find.scope.project.title=Project
-find.scope.module.title=Module {0}
+find.scope.module.title=Module ''{0}''
find.scope.directory.title=Directory {0}
-find.scope.files.with.mask={0} Files with Mask {1}
-find.usage.target.string.text=String ''{0}''
+find.scope.files.with.mask=with mask ''{0}''
find.replace.invalid.replacement.string=You have entered malformed replacement string: ''{0}''
find.replace.invalid.replacement.string.title=Replace Error
find.highlight.no.more.highlights.found=No more highlights found
find.scope.all.project.classes=All Project Classes
find.usage.view.tab.text=Occurrences of ''{0}''
-find.usage.view.toolwindow.title=Occurrences of ''{0}'' in ''{1}''
+find.usage.view.toolwindow.title=Occurrences of ''{0}'' in {1}
find.usage.view.usages.text=occurrences of ''{0}''
@@ -125,3 +124,5 @@
find.scope.custom.radio=Cu&stom:
find.usages.ambiguous.title=Find Usages Of {0}
0.occurrences.replaced={0,choice,0#No|1#{0}} {0,choice,0#occurrences|1#occurrence|2#occurrences} replaced
+found.occurrences=Found Occurrences
+occurrence=occurrence
\ No newline at end of file
diff --git a/platform/platform-resources-en/src/messages/IdeBundle.properties b/platform/platform-resources-en/src/messages/IdeBundle.properties
index 1bdb05e..0c44be2 100644
--- a/platform/platform-resources-en/src/messages/IdeBundle.properties
+++ b/platform/platform-resources-en/src/messages/IdeBundle.properties
@@ -1,10 +1,21 @@
-title.cannot.start.browser=Cannot start browser
error.malformed.url=Malformed url: {0}
-error.cannot.start.browser=Cannot start browser: {0}
error.please.specify.path.to.web.browser=Please specify a path to web browser in {0} | Web Browsers
-error.0.browser.path.not.specified={0} browser path is not specified in {1} | Web Browsers
title.browser.not.found=Browser Not Found
-title.browser.path.not.found=Browser Path Not Found
+browser.error=Browser Error
+error.0.browser.path.not.specified={0} browser path is not specified.
+
+chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File
+label.text.path.to.profiles.ini=Path to \"profiles.ini\":
+label.text.profile=&Profile:
+button.text.settings=Settings...
+display.name.firefox.settings=Firefox Settings
+
+browsers.explorer=Internet Explorer
+browsers.safari=Safari
+browsers.opera=Opera
+browsers.firefox=Firefox
+browsers.chrome=Chrome
+
action.sort.alphabetically=Sort Alphabetically
button.finish=&Finish
button.ok=&OK
@@ -57,7 +68,7 @@
bookmark.file.X.line.Y={0}, line {1}
button.view.source=&View Source
action.bookmark.toggle=Toggle _Bookmark
-action.bookmark.toggle.mnemonic=Toggle Bookmark With Mnemonic
+action.bookmark.toggle.mnemonic=Toggle Bookmark with Mnemonic
action.bookmark.delete=Delete Bookmark
action.bookmark.edit.description=Edit Description
action.bookmark.edit.description.description=Assign short description for the bookmark to be shown along the file name
@@ -127,7 +138,6 @@
tab.filetemplates.code=Code
tab.filetemplates.j2ee=Java EE
error.please.specify.template.name=Please specify template name
-error.template.with.such.name.already.exists=Template with such name already exists. Please specify a different template name
title.cannot.save.current.template=Cannot save current template
error.please.specify.template.extension=Please specify template extension
action.create.template=Create Template
@@ -305,8 +315,6 @@
radio.evaluate=&Evaluate for free for {0} days
radio.default.license.server=&Default License Server
action.activate.tool.window=Activate {0} window
-error.checkforupdates.connection.failed=Connection failed. Please check your network connection and try again.
-title.connection.error=Connection Error
editbox.export.settings.to=Export settings to:
title.export.file.location=Export File Location
prompt.choose.export.settings.file.path=Choose export file path or directory where to create new file
@@ -316,8 +324,8 @@
command.close.all.unmodified.editors=Close All Unmodified Editors
action.close.all.unmodified.editors.in.tab.group=Close _Unmodified In Group
action.close.all.unmodified.editors=Close _Unmodified
-action.close.all.unpinned.editors.in.tab.group=Close All But Pinned In Group
-action.close.all.unpinned.editors=Close All But Pinned
+action.close.all.unpinned.editors.in.tab.group=Close All but Pinned In Group
+action.close.all.unpinned.editors=Close All but Pinned
action.copy.path=C_opy Path
action.copy.paths=C_opy Paths
message.reference.to.fqn.has.been.copied=Reference to ''{0}'' has been copied.
@@ -401,7 +409,6 @@
title.popup.new.element.same.place=New in Current Directory
command.go.to.next.split=Go to next split
message.occurrence.N.of.M=Occurrence {0} of {1}
-message.open.file.is.project={0} is a project file.\nWould you like to open this project?
error.files.of.this.type.cannot.be.opened=Files of this type cannot be opened in {0}
title.cannot.open.file=Cannot Open File
filter.all.file.types=All file types
@@ -765,7 +772,7 @@
action.do.not.mark=Do Not Mark
error.source.directory.should.be.under.module.content.root.directory=Source directory should be under module content root directory
progress.searching.for.sources=Searching for sources in {0}. Please wait.
-prompt.select.source.directory=Select source directory
+prompt.select.source.directory=Select Source Directory
prompt.new.project.file.name=Enter a file name to create a new {0} {1}
prompt.enter.project.file.location=Enter {0} file location
directory.project.file.directory=The {0} file directory\n
@@ -887,22 +894,38 @@
unscramble.unscrambled.threaddump.tab=<Threads>
unscramble.unscrambled.deadlock.tab=<Deadlock>
+updates.checking.progress=Checking for updates
+updates.error.connection.title=Connection Error
+updates.error.connection.failed=Connection failed. Please check your network connection and try again.
+updates.error.plugin.description.failed=Failed to load plugin descriptions from: \"{0}\"
updates.info.dialog.title=Update Info
-updates.no.updates.message=<html><h4>You are using the latest version of $FULLNAME$.</h4></html>
-updates.configure.label=<html><head>{0}</head><br>To configure automatic update settings, see the <b><a href=\"updates\">Updates</a></b> dialog of your IDE {1}</html>
+updates.channel.name.message=<b>{0}</b>: {1}
+updates.channel.key.needed=You can evaluate the new version for {0} days or buy a license key or an upgrade online.
+updates.channel.existing.key=The new version can be used with your existing license key.
+updates.channel.bundled.key=The new version has an expiration date and does not require a license key.
+updates.ready.message={0} is ready to <a href=\"update\">update</a>.
+updates.plugins.ready.message=The following plugin{0,choice,1# is|2#s are} ready to <a href=\"update\">update</a>: {1}
+updates.no.updates.message=You already have the latest version of {0} installed.
+updates.plugins.ready.header=<html><b>Plugins from configured hosts are ready to update.</b><br> \
+ Uncheck plugins you do not want to update.</html>
+updates.configure.label=To configure automatic update settings, see the <b><a href=\"updates\">Updates</a></b> dialog of your IDE {0}.
updates.timeout.error=Connection timed out
-updates.download.and.install.patch.button=&Download Patch and Shutdown
-updates.download.and.install.patch.button.restart=Up&date and Restart
+updates.download.and.install.button=&Download Patch and Shutdown
+updates.download.and.restart.button=Up&date and Restart
updates.more.info.button=&More Info...
-updates.new.version.available=<html><h4>A new version of $FULLNAME$ is available.</h4></html>
-updates.available.idea.version=New version:
-updates.build.number=(Build number:
-updates.current.idea.version=Current version:
-updates.press.more.info.label=<html><br>Press <b>More Info...</b> to open a web page where you can download $PRODUCT$ manually or learn more about its new version.</HTML>
-updates.check.manually.label=<html><br>To check for new updates manually, use the <b>Help | Check for Updates</b> command.</html>
+updates.ignore.update.button=&Ignore This Update
+updates.remind.later.button=&Remind Me Later
+updates.buy.online.button=&Buy Upgrade Online
+updates.new.version.available=<b>A new version of {0} is available!</b>
+updates.current.version=Current version:
+updates.available.version=New version:
+updates.patch.label=Patch size:
+updates.version.info={0} (build {1})
+updates.write.protected={0} does not have write access to {1}. Please run it by a privileged user to update.
updates.settings.title=Updates
updates.last.check.never=Never
-updates.settings.caption.1=<html>$FULLNAME$ can automatically check for new and updated versions of itself, using your internet connection (when active).<html>
+updates.settings.caption.1=<html>$FULLNAME$ can automatically check for new and updated versions of itself, \
+ using your internet connection (when active).<html>
updates.settings.check.now.button=&Check Now
updates.settings.checkbox=Check for updates in channel
updates.settings.build.number= Build number:
@@ -994,7 +1017,7 @@
maven.repository.presentable.name=Maven repository
label.missed.libraries.prefix=The following libraries are missing:
label.missed.libraries.text=''{0}'' library not found in the module dependencies list
-missing.libraries.fix.button=Fix...
+button.fix=Fix\u2026
setup.library.dialog.title=Setup Library
label.library.will.be.created.description.text={0} level library <b>{1}</b> with {2} {2, choice, 1#file|2#files} will be created
new.library.file.chooser.title=New Library Files
@@ -1052,7 +1075,6 @@
fail.open.project.message=Unable to open project from ''{0}''
disabled.plugins.warning.message=<li>Plugin <b>\"{0}\"</b> won''t be able to load because required {2, choice, 1#plugin|2#plugins} {1} {2, choice, 1#is|2#are} disabled.</li>
plugin.updated.status.tooltip=Updated plugin will be activated on next startup
-connection.failed.message=Failed to load plugin descriptions from: \"{0}\"
checkbox.show.icons.in.menu.items=Display icons in menu items
custom.icon.validation.message=Icon is too big to appear in menu
custom.icon.validation.title=Icon size is invalid
diff --git a/platform/platform-resources-en/src/messages/InspectionsBundle.properties b/platform/platform-resources-en/src/messages/InspectionsBundle.properties
index 0665e5c..4f7d14a 100644
--- a/platform/platform-resources-en/src/messages/InspectionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/InspectionsBundle.properties
@@ -35,7 +35,7 @@
#can be final
inspection.can.be.final.display.name=Declaration can have final modifier
-inspection.can.be.final.accept.quickfix=Accept Suggested Final Modifier
+inspection.can.be.final.accept.quickfix=Make final
inspection.can.be.final.option=Report classes
inspection.can.be.final.option1=Report methods
inspection.can.be.final.option2=Report fields
@@ -117,7 +117,7 @@
inspection.equals.hashcode.only.one.defined.problem.descriptor=Class has {0} defined but does not define {1}
inspection.1.5.display.name=Usages of API documented as @since 1.5 (1.6|1.7)
-inspection.1.5.problem.descriptor=Usage of API documented as @since {0}
+inspection.1.5.problem.descriptor=Usage of API documented as @since {0}+
inspection.1.7.problem.descriptor=Usage of generified after 1.6 API which would cause compilation problems with JDK {0}
inspection.local.can.be.final.display.name=Local variable or parameter can be final
@@ -130,10 +130,9 @@
inspection.nullable.problems.display.name=@NotNull/@Nullable problems
#check box options
-inspection.nullable.problems.method.overrides.notnull.option=<html>report @NotNull ¶meter overrides @Nullable and <br>@Nullable method overrides @NotNull</html>
-inspection.nullable.problems.method.overrides.option=report non-&annotated parameter or method overrides @NotNull
-inspection.nullable.problems.not.annotated.getters.for.annotated.fields=report non-annotated &setter parameter or getter of annotated fields
-inspection.nullable.problems.annotation.not.propagated=report @NotNull not propagated to ove&rridden methods
+inspection.nullable.problems.method.overrides.notnull.option=<html>Report @NotNull ¶meter overrides @Nullable and <br>@Nullable method overrides @NotNull</html>
+inspection.nullable.problems.method.overrides.option=Report non-&annotated parameter or method overrides @NotNull
+inspection.nullable.problems.not.annotated.getters.for.annotated.fields=Report non-annotated &setter parameter or getter of annotated fields
#problem descriptor messages
inspection.nullable.problems.Nullable.NotNull.conflict=Cannot annotate with both @{0} and @{1}
@@ -227,7 +226,7 @@
inspection.export.results.error.title=Inspection Results Export
inspection.export.inspections.link.text=Inspections
inspection.export.open.source.link.text=Open source
-inspection.offline.view.empty.browser.text=<HTML><BODY>Select tree node for detailed information</BODY></HTML>
+inspection.offline.view.empty.browser.text=<HTML><BODY>Select inspection result on the left to see details</BODY></HTML>
inspection.offline.view.tool.display.name.title=Name
inspection.generating.html.progress.title=Generating HTML...
inspection.generating.xml.progress.title=Dumping XML...
@@ -663,6 +662,7 @@
severities.default.settings.message=Edit Settings|Colors \\& Fonts
unsupported.character.for.the.charset=Unsupported characters for the charset ''{0}''
lossy.encoding=Lossy encoding
+inspection.duplicated.code.display.name=Duplicated Code
inconsistent.line.separators=Inconsistent line separators
inspection.unused.symbol.public.method.parameters=Check parameters in &Non-private methods
introduce.constant.across.the.project=Introduce Constant Across the Project
diff --git a/platform/platform-resources-en/src/messages/OptionsBundle.properties b/platform/platform-resources-en/src/messages/OptionsBundle.properties
index b1ff8c4..364c5b4 100644
--- a/platform/platform-resources-en/src/messages/OptionsBundle.properties
+++ b/platform/platform-resources-en/src/messages/OptionsBundle.properties
@@ -98,13 +98,6 @@
options.java.attribute.descriptor.annotation.name=Annotation name
options.java.attribute.descriptor.annotation.attribute.name=Annotation attribute name
-options.properties.attribute.descriptor.property.key=Property key
-options.properties.attribute.descriptor.property.value=Property value
-options.properties.attribute.descriptor.key.value.separator=Key/value separator
-options.properties.attribute.descriptor.comment=Comment
-options.properties.attribute.descriptor.valid.string.escape=Valid string escape
-options.properties.attribute.descriptor.invalid.string.escape=Invalid string escape
-
options.xml.attribute.descriptor.prologue=Prologue
options.xml.attribute.descriptor.comment=Comment
options.xml.attribute.descriptor.tag=Tag
diff --git a/platform/platform-resources-en/src/messages/RefactoringBundle.properties b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
index 592d20c..e435074 100644
--- a/platform/platform-resources-en/src/messages/RefactoringBundle.properties
+++ b/platform/platform-resources-en/src/messages/RefactoringBundle.properties
@@ -299,7 +299,7 @@
0.already.contains.inner.class.named.1={0} already contains inner class named {1}
0.uses.1.which.is.pushed.down={0} uses {1}, which is pushed down
refactoring.cannot.be.performed=Refactoring cannot be performed
-there.is.already.a.0.it.will.conflict.with.an.introduced.parameter=There is already a {0}. It will conflict with an introduced parameter
+there.is.already.a.0.it.will.conflict.with.an.introduced.parameter=There is already a {0}. It will conflict with the introduced parameter
introduce.parameter.command=Extracting parameter to {0}
parameter.initializer.contains.0.but.not.all.calls.to.method.are.in.its.class=Parameter initializer contains {0}, but not all calls to method are in its class
0.is.not.accessible.from.1.value.for.introduced.parameter.in.that.method.call.will.be.incorrect={0} is not accessible from {1}. Value for introduced parameter in that method call will be incorrect.
diff --git a/platform/platform-resources-en/src/messages/UsageView.properties b/platform/platform-resources-en/src/messages/UsageView.properties
index 134c257..ab29484 100644
--- a/platform/platform-resources-en/src/messages/UsageView.properties
+++ b/platform/platform-resources-en/src/messages/UsageView.properties
@@ -44,7 +44,7 @@
usage.type.return=Method return type
usage.type.string.constant=Usage in string constants
usage.type.comment=Usage in comments
-usage.type.unclassified=Unclassified usage
+usage.type.unclassified=Unclassified {0}
occurence.info.usage={0,choice, 0#Not Found|1#1 usage|2#{0,number} usages}{1,choice, 0#|1# in 1 file|2# in {1,number} files}
occurence.info.occurence={0,choice, 0#Not Found|1#1 occurrence|2#{0,number} occurrences}{1,choice, 0#|1# in 1 file|2# in {1,number} files}
occurence.info.reference={0,choice, 0#Not Found|1#1 reference|2#{0,number} references}{1,choice, 0#|1# in 1 file|2# in {1,number} files}
@@ -60,8 +60,8 @@
usage.type.type.parameter=Type parameter
usage.type.read=Value read
usage.type.write=Value write
-preview.usages.action.text=Preview Usages
-select.the.usage.to.preview=Select the usage to preview
+preview.usages.action.text=Preview {0}
+select.the.usage.to.preview=Select {0} to preview
usages.were.filtered.out={0,number} {0,choice, 1#usage was|2#usages were} filtered out
show.usages.only.usage=It''s the only usage in {0}
all.usages.are.in.this.line=All {0} usages in {1} are in this line
@@ -69,8 +69,8 @@
sort.alphabetically.action.text=Sort Members Alphabetically
button.text.continue=Continue
button.text.abort=Abort
-find.excessive.usages.title=Too Many Usages
-find.excessive.usage.count.prompt={0} usages found so far. Are you sure you wish to continue?
+find.excessive.usages.title=Too Many {0}
+find.excessive.usage.count.prompt={0} {1} found so far. Are you sure you wish to continue?
find.file.size.megabytes={0} megabytes
large.files.were.ignored={0,choice, 0#No|1#1 too large file was ignored|2#{0,number} too large files were ignored}
usage.excluded=excluded
diff --git a/platform/platform-resources-en/src/messages/VcsBundle.properties b/platform/platform-resources-en/src/messages/VcsBundle.properties
index d08931e..ce2f577 100644
--- a/platform/platform-resources-en/src/messages/VcsBundle.properties
+++ b/platform/platform-resources-en/src/messages/VcsBundle.properties
@@ -35,6 +35,7 @@
checkbox.checkin.options.check.files.up.to.date=Check remote status
checkbox.checkin.options.optimize.imports=&Optimize imports
checkbox.checkin.options.reformat.code=&Reformat code
+checkbox.checkin.options.rearrange.code=Rearra&nge code
progress.text.searching.for.modified.files=Searching for modified files
button.text.overwrite.modified.file=&Overwrite Modified File
button.text.overwrite.modified.files=&Overwrite Modified Files
@@ -489,6 +490,7 @@
action.name.show.history.for.class=Class
action.name.show.history.for.field=Field
action.name.show.history.for.method=Method
+action.name.show.history.for.function=Function
action.name.show.history.for.tag=Tag
action.name.show.history.for.text=Text
action.name.show.history.for.code.block=Code Block
diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties
index dfb3b08..e761b3c 100644
--- a/platform/platform-resources-en/src/messages/XmlBundle.properties
+++ b/platform/platform-resources-en/src/messages/XmlBundle.properties
@@ -145,18 +145,6 @@
cannot.resolve.anchor=Cannot resolve anchor #{0}
cannot.resolve.anchor.in.file=Cannot resolve anchor #{0} in file {1}
-
-# web browsers
-browsers.configuration.name=Web Browsers
-browsers.explorer=Internet Explorer
-browsers.safari=Safari
-browsers.opera=Opera
-browsers.firefox=Firefox
-browsers.chrome=Chrome
-browser.description=Open file in {0}
-browser.active=Active
-browser.default.settings=Default
-browser.error=Browser Error
web.editor.configuration.title=Web
browser.select.in.default.name=Web Browser
@@ -164,8 +152,8 @@
xml.split.tag.intention.action=Split current tag
tag.name.completion.hint=Press {0} to view tags from other namespaces
tag.name.completion.display.name=Tag Name Completion
-open_in.list.popup.title=Preview file in...
-open_in.list.prefix=Preview file in
+open_in.list.popup.title=Preview File in...
+open_in.list.prefix=Preview File in
xml.inspections.unbound.prefix=Unbound XML namespace prefix
html.add.table.column.after.action=Add a new column to the table after the current one
@@ -226,12 +214,6 @@
cant.delete.file=Can't delete file {0}
select.xsd.schema.dialog.title=Select XSD Schema
-chooser.title.select.profiles.ini.file=Select \"profiles.ini\" File
-label.text.path.to.profiles.ini=Path to \"profiles.ini\":
-label.text.profile=&Profile:
-button.text.settings=Settings...
-display.name.firefox.settings=Firefox Settings
-
emmet.title=Emmet
emmet.configuration.title=Emmet (Zen Coding)
emmet.enable.label=&Enable XML Emmet
@@ -246,8 +228,6 @@
new.html.file.action.description=Creates new HTML file
html5.outline.mode=HTML5 Outline
-read.win.registry=Retrieve settings from &Windows registry
-
start.browser.startup.page=Startup pa&ge:
start.browser.border.label.open.browser=Open browser
start.browser.checkbox.start.browser=After launch
diff --git a/platform/platform-resources-en/src/misc/registry.properties b/platform/platform-resources-en/src/misc/registry.properties
index 9dfe64a..fd9d8fc 100644
--- a/platform/platform-resources-en/src/misc/registry.properties
+++ b/platform/platform-resources-en/src/misc/registry.properties
@@ -1,18 +1,3 @@
-#
-# 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.
-#
localHistory.daysToKeep=5
# suppress inspection "UnusedProperty"
localHistory.daysToKeep.description=Specify how many working days changes should be remembered.\n\
@@ -42,9 +27,11 @@
actionSystem.focusIdleTimeout=20
actionSystem.mac.screenMenuNotUpdatedFix=false
actionSystem.keyGestures.enabled=false
-actionSystem.keyGestureDblClickTime=500
+actionSystem.keyGestureDblClickTime=650
actionSystem.suspendFocusTransferIfApplicationInactive=true
+actionSystem.doNotStealFocus=false
actionSystem.xWindow.remove.focus.from.nonFocusable.popups=true
+actionSystem.xWindow.remove.focus.from.nonFocusable.popups.delay=50
actionSystem.noContextComponentWhileFocusTransfer=true
actionSystem.secondKeystrokeTimeout=2000
actionSystem.secondKeystrokeAutoPopupEnabled=false
@@ -143,9 +130,9 @@
ide.mac.file.chooser.show.hidden.files=false
ide.mac.file.chooser.native=true
ide.mac.message.dialogs.as.sheets=true
-ide.mac.mountain.lion.notifications.enabled=true
-skip.untitled.windows.for.mac.messages=true
+skip.untitled.windows.for.mac.messages=false
skip.untitled.windows.for.mac.messages.description=Temporary key to test a fix for MacMessages
+ide.mac.mountain.lion.notifications.enabled=true
ide.mac.inplaceDialogMnemonicsFix=true
ide.mac.fix.dialog.showing=false
ide.mac.hide.cursor.when.typing=true
@@ -159,6 +146,7 @@
ide.mac.retina.disableDrawingFix=false
ide.new.preferences=false
+ide.new.license.dialog=true
debugger.valueTooltipAutoShow=true
# suppress inspection "UnusedProperty"
@@ -207,14 +195,14 @@
compiler.document.save.trigger.delay=1500
# suppress inspection "UnusedProperty"
-compiler.document.save.trigger.delay.description=Delay in milliseconds before triggering save of unchenged documents in response to document changed events
+compiler.document.save.trigger.delay.description=Delay in milliseconds before triggering save in response to document changes
vcs.show.colored.annotations=true
vcs.showConsole=true
psi.incremental.reparse.depth.limit=1000
-psi.viewer.selection.color=0,153,153
psi.deferIconLoading=true
+psi.track.invalidation=true
ide.suggest.file.when.creating.filename.like.directory=true
ide.suggest.file.when.creating.filename.like.directory.description=When creating a directory named foo.txt, suggest to create a file with such a name instead
@@ -237,7 +225,7 @@
projectView.showHierarchyErrors=true
projectView.hide.dot.idea=true
show.live.templates.in.completion=false
-ide.completion.autopopup.select.live.templates=false
+ide.completion.autopopup.select.live.templates=true
ide.completion.autopopup.choose.by.enter=true
documentation.component.editor.font=false
@@ -245,6 +233,10 @@
# suppress inspection "UnusedProperty"
ide.completion.show.better.matching.classes.description=Show non-imported but good matching classes in basic completion
+ide.completion.show.lower.case.classes=false
+# suppress inspection "UnusedProperty"
+ide.completion.show.lower.case.classes.description=Show non-imported classes starting with a lowercase letter in basic completion
+
ide.completion.delay.autopopup.until.completed=false
# suppress inspection "UnusedProperty"
ide.completion.delay.autopopup.until.completed.description=Controls if completion autopopup is shown immediately and populated in background, or delayed until all suggestion are calculated
@@ -257,6 +249,9 @@
ide.goto.middle.matching.description=Suggest items in goto actions that contain the entered string somewhere in the middle.
ide.goto.rebuild.delay=0
+ide.structural.navigation.visit.fields=false
+ide.structural.navigation.visit.fields.description=Whether fields should be stopped at when navigating to the nex/previous structural member by Alt+Down/Up.
+
ide.non.english.keyboard.layout.fix=false
ide.non.english.keyboard.layout.fix.description=Enables a fix for key codes with non-English keyboard layouts
@@ -276,7 +271,7 @@
file.structure.tree.mode=true
-directory.index.use.root.index=false
+directory.index.use.root.index=true
directory.index.use.root.index.description=Requires restart
directory.index.compare.implementations=false
directory.index.compare.implementations.description=Will make the IDE slow. Requires restart
@@ -333,6 +328,7 @@
testng_sm_runner=false
show.flex.debug.design.view=false
git.new.log=true
+diff.patience.alg=false
svn.use.terminal=false
@@ -340,9 +336,13 @@
ide.mac.message.sheets.java.emulation=false
# suppress inspection "UnusedProperty"
ide.mac.message.sheets.java.emulation.description=Use Java message sheets instead of native ones
+ide.mac.message.sheets.java.emulation.dialogs=false
+# suppress inspection "UnusedProperty"
+ide.mac.message.sheets.java.emulation.dialogs.description=Use Java message sheets based on awt dialogs instead of native sheets
linux.native.menu=false
linux.native.menu.description=Enables native menu on Ubuntu
windows.jumplist=true
+# suppress inspection "UnusedProperty"
windows.jumplist.description=Enables JumpLists on Windows
# suppress inspection "UnusedProperty"
@@ -356,9 +356,14 @@
darcula.use.native.fonts.on.linux=true
darcula.use.native.fonts.on.linux.description=If false, uses DejaVu Sans 13pt
idea.4.5.laf.enabled=false
-show.all.look.and.feels=false
-show.all.look.and.feels.description=Make accessible all available Look and Feels
+ide.linux.gtk.notifications.enabled=true
+ide.linux.gtk.notifications.enabled.description=Enables GTK notifications on linux
cvs.roots.refresh.uses.vfs=true
cvs.roots.refresh.uses.vfs.description=Should CVS roots refresh after update use VFS
editor.wrap.collapsed.region.at.line.start=false
+vcs.add.remove.silent=true
+ide.open.file.in.temp.project.dir=true
+ide.open.file.in.temp.project.dir.description=Enables opening file in temp project directory
+editor.allow.multiple.carets=false
+embed.scene.builder=false
diff --git a/platform/platform-resources-en/src/tips/CtrlShiftIForLookup.html b/platform/platform-resources-en/src/tips/CtrlShiftIForLookup.html
index a13ccd2..a4d116b 100644
--- a/platform/platform-resources-en/src/tips/CtrlShiftIForLookup.html
+++ b/platform/platform-resources-en/src/tips/CtrlShiftIForLookup.html
@@ -6,7 +6,7 @@
<p>The <span class="emphasis">Quick Definition Viewer</span>
- (<span class="shortcut">&shortcut:QuickImplementations;</span>) can be also used for items in lookup lists that appear on code
+ (<span class="shortcut">&shortcut:QuickImplementations;</span>) can also be used for items in lookup lists that appear on code
completion and class/file/symbol navigaton commands.</p>
<p class="image"><img width="532" height="167" src="images/ctrl_shift_in_lookup.png"></p>
diff --git a/platform/platform-resources-en/src/tips/FindUsages.html b/platform/platform-resources-en/src/tips/FindUsages.html
index a716213..55dc7dd 100644
--- a/platform/platform-resources-en/src/tips/FindUsages.html
+++ b/platform/platform-resources-en/src/tips/FindUsages.html
@@ -6,7 +6,7 @@
<p>
You can quickly find all places where a particular class, method or variable is used in the whole project
by positioning the caret at the symbol's name or at its usage in code and pressing <span class="shortcut">&shortcut:FindUsages;</span>
- (<span class="control">Find Usages</span>
+ (<span class="control">Edit | Find | Find Usages</span>
in the popup menu).</p>
</body>
</html>
diff --git a/platform/platform-resources-en/src/tips/GoToDeclaration.html b/platform/platform-resources-en/src/tips/GoToDeclaration.html
index 7a3d876..d5a703d 100644
--- a/platform/platform-resources-en/src/tips/GoToDeclaration.html
+++ b/platform/platform-resources-en/src/tips/GoToDeclaration.html
@@ -6,7 +6,7 @@
<p>To navigate to the declaration of a class, method or variable used somewhere in the code,
- position the caret at the usage and press <span class="shortcut">&shortcut:GotoDeclaration;</span>. You can also click the mouse
+ position the caret at the usage and press <span class="shortcut">&shortcut:GotoDeclaration;</span> (<span class="control">Navigate | Declaration</span>). You can also click the mouse
on usages with the <span class="shortcut">Ctrl</span>
key pressed to jump to declarations.</p>
<p class="image"><img width="856" height="145" src="images/ctrl_click.png"></p>
diff --git a/platform/platform-resources-en/src/tips/IntroduceVariable.html b/platform/platform-resources-en/src/tips/IntroduceVariable.html
index 0bfb856..b2a032f 100644
--- a/platform/platform-resources-en/src/tips/IntroduceVariable.html
+++ b/platform/platform-resources-en/src/tips/IntroduceVariable.html
@@ -9,7 +9,7 @@
refactoring helps you simplify complicated statements in your code. For example, in the code fragment below,
you can select an expression in the code:</p>
<p class="image"><img width="498" height="15" src="images/introduce_variable_1.png"></p>
- <p>and press <span class="shortcut">&shortcut:IntroduceVariable;</span> (<span class="control">Refactor | Extract Variable</span>).
+ <p>and press <span class="shortcut">&shortcut:IntroduceVariable;</span> (<span class="control">Refactor | Extract | Variable...</span>).
This will result in the following:</p>
<p class="image"><img width="484" height="84" src="images/introduce_variable_2.png"></p>
diff --git a/platform/platform-resources-en/src/tips/IssueNavigation.html b/platform/platform-resources-en/src/tips/IssueNavigation.html
index ab62e94..9b1e936 100644
--- a/platform/platform-resources-en/src/tips/IssueNavigation.html
+++ b/platform/platform-resources-en/src/tips/IssueNavigation.html
@@ -8,7 +8,7 @@
<p>&productName; lets you jump from your check-in comment to an issue in your task tracker.</p>
<p>All you have to do is to define issue navigation patterns in the
- <span class="control">Settings | Version Control</span>
+ <span class="control">Settings | Version Control | Issue Navigation</span>
dialog:</p>
<p class="image"><img width="520" height="348" src="images/issueNavigation1.png"></p>
<p>When you commit a changelist, and type the check-in comment, make sure it matches one of your issue navigation patterns.
diff --git a/platform/platform-resources-en/src/tips/MoveToChangelist.html b/platform/platform-resources-en/src/tips/MoveToChangelist.html
index 440cc9c..8bf63fc 100644
--- a/platform/platform-resources-en/src/tips/MoveToChangelist.html
+++ b/platform/platform-resources-en/src/tips/MoveToChangelist.html
@@ -8,7 +8,7 @@
<p>If you don't want to commit some of your changes to the repository, you can set them aside for a while, by moving
to a separate changelist, or by putting them to a shelf. Select such file in the <span class="control">Local</span> tab of the <span class="control">Changes</span> tool
- window, and on the context menu choose <span class="control">Move to another changelist</span>,
+ window, and on the context menu choose <span class="control">Move to Another Changelist</span>,
or <span class="control">Shelve Changes</span>.</p>
diff --git a/platform/platform-resources-en/src/tips/ShowHideSideBars.html b/platform/platform-resources-en/src/tips/ShowHideSideBars.html
index 8da8779..ed0d286 100644
--- a/platform/platform-resources-en/src/tips/ShowHideSideBars.html
+++ b/platform/platform-resources-en/src/tips/ShowHideSideBars.html
Binary files differ
diff --git a/platform/platform-resources-en/src/tips/images/issueNavigation1_dark.png b/platform/platform-resources-en/src/tips/images/issueNavigation1_dark.png
index e83520f..bcea535 100644
--- a/platform/platform-resources-en/src/tips/images/issueNavigation1_dark.png
+++ b/platform/platform-resources-en/src/tips/images/issueNavigation1_dark.png
Binary files differ
diff --git a/platform/platform-resources-en/src/tips/moveFileToChangelist.html b/platform/platform-resources-en/src/tips/moveFileToChangelist.html
index a4fc64a..7cf5bdb 100644
--- a/platform/platform-resources-en/src/tips/moveFileToChangelist.html
+++ b/platform/platform-resources-en/src/tips/moveFileToChangelist.html
@@ -7,7 +7,7 @@
<p>
You can move any file to a changelist of your choice. To do that, just choose
-<span class="control">Move to Changelist</span> on the file context menu in the Changes tool window:
+<span class="control">Move to Another Changelist</span> on the file context menu in the Changes tool window:
</p>
<p class="image"><img width="406" height="78" src="images/move_to_changelist.png"></p>
diff --git a/platform/platform-resources/src/DefaultColorSchemesManager.xml b/platform/platform-resources/src/DefaultColorSchemesManager.xml
index 7bac479..d43993b 100644
--- a/platform/platform-resources/src/DefaultColorSchemesManager.xml
+++ b/platform/platform-resources/src/DefaultColorSchemesManager.xml
@@ -654,7 +654,7 @@
<option name="ERROR_STRIPE_COLOR" />
</value>
</option>
-
+
<option name="EXECUTIONPOINT_ATTRIBUTES">
<value>
<option name="BACKGROUND" value="ff"/>
@@ -1052,7 +1052,43 @@
<option name="ERROR_STRIPE_COLOR" />
</value>
</option>
+ <option name="SPY-JS.FUNCTION_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="ffffd7"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PROGRAM_SCOPE">
+ <value>
+ <option name="BACKGROUND" value="ffffd7"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.EXCEPTION">
+ <value>
+ <option name="BACKGROUND" value="FFCCCC"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_ONE">
+ <value>
+ <option name="BACKGROUND" value="E2FFE2"/>
+ <option name="EFFECT_TYPE" value="2"/>
+ </value>
+ </option>
+ <option name="SPY-JS.PATH_LEVEL_TWO">
+ <value>
+ <option name="EFFECT_COLOR" value="000000"/>
+ <option name="EFFECT_TYPE" value="1"/>
+ </value>
+ </option>
+ <option name="SPY-JS.VALUE_HINT">
+ <value>
+ <option name="EFFECT_COLOR" value="a9a9a9"/>
+ <option name="EFFECT_TYPE" value="0"/>
+ </value>
+ </option>
</attributes>
-
+
</scheme>
</component>
diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml
index 2c2d9ec..1a1ce72 100644
--- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml
@@ -514,7 +514,9 @@
<extensionPoint name="scopeParserExtension" interface="com.intellij.psi.search.scope.packageSet.PackageSetParserExtension"/>
- <extensionPoint name="referenceProviderType" beanClass="com.intellij.util.KeyedLazyInstanceEP"/>
+ <extensionPoint name="referenceProviderType" beanClass="com.intellij.util.KeyedLazyInstanceEP">
+ <with attribute="implementationClass" implements="com.intellij.psi.PsiReferenceProvider"/>
+ </extensionPoint>
<extensionPoint name="colorSettingsPage" interface="com.intellij.openapi.options.colors.ColorSettingsPage"/>
<extensionPoint name="colorAndFontPanelFactory" interface="com.intellij.application.options.colors.ColorAndFontPanelFactory"/>
@@ -597,6 +599,7 @@
<with attribute="implementationClass" implements="com.intellij.psi.stubs.BinaryFileStubBuilder"/>
</extensionPoint>
+ <!--suppress ExtensionPointBeanClass -->
<extensionPoint name="stubElementTypeHolder"
beanClass="com.intellij.psi.stubs.StubElementTypeHolderEP"/>
diff --git a/platform/platform-resources/src/META-INF/LangExtensions.xml b/platform/platform-resources/src/META-INF/LangExtensions.xml
index e008245..c554cf3 100644
--- a/platform/platform-resources/src/META-INF/LangExtensions.xml
+++ b/platform/platform-resources/src/META-INF/LangExtensions.xml
@@ -44,6 +44,8 @@
<applicationService serviceInterface="com.intellij.execution.filters.TextConsoleBuilderFactory"
serviceImplementation="com.intellij.execution.filters.TextConsoleBuilderFactoryImpl"/>
+ <applicationService serviceInterface="com.intellij.execution.filters.HyperlinkInfoFactory"
+ serviceImplementation="com.intellij.execution.filters.impl.HyperlinkInfoFactoryImpl"/>
<applicationService serviceInterface="com.intellij.lang.PsiBuilderFactory"
serviceImplementation="com.intellij.lang.impl.PsiBuilderFactoryImpl"/>
@@ -143,6 +145,9 @@
<applicationService serviceInterface="com.intellij.ui.mac.MacMessages"
serviceImplementation="com.intellij.ui.mac.MacMessagesImpl"/>
+ <applicationService serviceInterface="com.intellij.ui.mac.MacMessagesEmulation"
+ serviceImplementation="com.intellij.ui.messages.JBMacMessages"/>
+
<applicationService serviceInterface="com.intellij.psi.codeStyle.AppCodeStyleSettingsManager"
serviceImplementation="com.intellij.psi.codeStyle.AppCodeStyleSettingsManager"/>
@@ -372,6 +377,7 @@
<applicationConfigurable instance="com.intellij.codeInsight.template.impl.LiveTemplatesConfigurable" id="editing.templates"
key="templates.settings.page.title" bundle="messages.CodeInsightBundle"/>
<lookup.actionProvider implementation="com.intellij.codeInsight.template.impl.LiveTemplateLookupActionProvider"/>
+ <documentationProvider implementation="com.intellij.codeInsight.template.impl.LiveTemplateDocumentationProvider"/>
<!-- File Templates-->
<applicationConfigurable instance="com.intellij.ide.fileTemplates.impl.AllFileTemplatesConfigurable" id="fileTemplates"
@@ -561,6 +567,7 @@
<extendWordSelectionHandler implementation="com.intellij.codeInsight.editorActions.wordSelection.NaturalLanguageTextSelectioner"/>
<extendWordSelectionHandler implementation="com.intellij.codeInsight.editorActions.wordSelection.WordSelectioner"/>
<extendWordSelectionHandler implementation="com.intellij.codeInsight.editorActions.wordSelection.LineCommentSelectioner"/>
+ <extendWordSelectionHandler implementation="com.intellij.ide.highlighter.custom.impl.CustomFileTypeSelectWordHandler"/>
<syntaxHighlighter factoryClass="com.intellij.ide.highlighter.custom.impl.CustomFileTypeHighlighterProvider"/>
<fileTypeRegistrator implementation="com.intellij.ide.highlighter.custom.impl.StandardFileTypeRegistrator"/>
@@ -619,6 +626,19 @@
<category>Language Injection</category>
</intentionAction>
+ <!-- LookupManagerActions -->
+ <editorActionHandler action="EditorUp" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$UpHandler"/>
+ <editorActionHandler action="EditorDown" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$DownHandler"/>
+ <editorActionHandler action="EditorPageUp"
+ implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$PageUpHandler"/>
+ <editorActionHandler action="EditorPageDown"
+ implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$PageDownHandler"/>
+ <editorActionHandler action="EditorLeft" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$LeftHandler"/>
+ <editorActionHandler action="EditorRight" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$RightHandler"/>
+ <editorActionHandler action="EditorLineStart" implementationClass="com.intellij.codeInsight.lookup.impl.HomeHandler"/>
+ <editorActionHandler action="EditorLineEnd" implementationClass="com.intellij.codeInsight.lookup.impl.EndHandler"/>
+ <editorActionHandler action="EditorBackSpace" implementationClass="com.intellij.codeInsight.lookup.impl.BackspaceHandler"/>
+
<!-- CodeInsightSettings -->
<editorActionHandler action="EditorEnter" implementationClass="com.intellij.codeInsight.editorActions.EnterHandler" id="editorEnter"/>
<editorActionHandler action="EditorLineEnd" implementationClass="com.intellij.codeInsight.editorActions.EndHandler"/>
@@ -635,19 +655,6 @@
<editorActionHandler action="EditorDuplicate" implementationClass="com.intellij.openapi.editor.actions.NamedElementDuplicateHandler"/>
- <!-- LookupManagerActions -->
- <editorActionHandler action="EditorUp" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$UpHandler"/>
- <editorActionHandler action="EditorDown" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$DownHandler"/>
- <editorActionHandler action="EditorPageUp"
- implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$PageUpHandler"/>
- <editorActionHandler action="EditorPageDown"
- implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$PageDownHandler"/>
- <editorActionHandler action="EditorLeft" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$LeftHandler"/>
- <editorActionHandler action="EditorRight" implementationClass="com.intellij.codeInsight.lookup.impl.LookupActionHandler$RightHandler"/>
- <editorActionHandler action="EditorLineStart" implementationClass="com.intellij.codeInsight.lookup.impl.HomeHandler"/>
- <editorActionHandler action="EditorLineEnd" implementationClass="com.intellij.codeInsight.lookup.impl.EndHandler"/>
- <editorActionHandler action="EditorBackSpace" implementationClass="com.intellij.codeInsight.lookup.impl.BackspaceHandler"/>
-
<!-- TemplateManagerActions -->
<editorActionHandler action="EditorEscape" implementationClass="com.intellij.codeInsight.template.impl.editorActions.EscapeHandler"
id="templateEscape" order="after hide-hints"/>
@@ -809,10 +816,14 @@
<codeHighlighting.iconCreator implementation="com.intellij.codeHighlighting.DefaultIconCreator"/>
<checkinHandlerFactory implementation="com.intellij.openapi.vcs.checkin.ReformatCheckinHandlerFactory"/>
+ <checkinHandlerFactory implementation="com.intellij.openapi.vcs.checkin.RearrangeCheckinHandlerFactory"/>
<checkinHandlerFactory implementation="com.intellij.openapi.vcs.checkin.OptimizeOptionsCheckinHandlerFactory"/>
<checkinHandlerFactory implementation="com.intellij.openapi.vcs.checkin.CodeAnalysisCheckinHandlerFactory"/>
<checkinHandlerFactory implementation="com.intellij.openapi.vcs.checkin.TodoCheckinHandlerFactory"/>
+ <defaultHighlightingSettingProvider implementation="com.intellij.codeInsight.daemon.impl.analysis.GeneratedSourcesHighlightingSettingProvider"/>
+ <editorNotificationProvider implementation="com.intellij.ide.GeneratedFileEditingNotificationProvider"/>
+
<projectService serviceInterface="com.intellij.openapi.vcs.CodeSmellDetector"
serviceImplementation="com.intellij.openapi.vcs.impl.CodeSmellDetectorImpl"/>
@@ -836,6 +847,8 @@
<completion.contributor language="TEXT" implementationClass="com.intellij.util.CompletionContributorForTextField"
order="first, before commitCompletion"/>
+ <completion.contributor language="any" implementationClass="com.intellij.codeInsight.completion.CustomFileTypeCompletionContributor"/>
+
<pathMacroFilter implementation="com.intellij.execution.configuration.RunConfigurationPathMacroFilter"/>
<pathMacroFilter implementation="com.intellij.openapi.application.StructuralSearchPathMacroFilter"/>
@@ -860,6 +873,8 @@
<actionPromoter implementation="com.intellij.ui.EditorTextFieldActionPromoter"/>
<stepsBeforeRunProvider implementation="com.intellij.execution.impl.RunConfigurationBeforeRunProvider"/>
+
+ <lang.foldingBuilder language="TEXT" implementationClass="com.intellij.ide.highlighter.custom.impl.CustomFileTypeFoldingBuilder"/>
</extensions>
</idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
index 091006a..eaff367 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml
@@ -127,10 +127,6 @@
</extensionPoint>
<extensionPoint name="contentBasedClassFileProcessor" interface="com.intellij.openapi.fileTypes.ContentBasedClassFileProcessor"/>
- <extensionPoint name="browserSettingsProvider" beanClass="com.intellij.ide.BrowserSettingsProviderEP">
- <with attribute="instance" implements="com.intellij.ide.BrowserSettingsProvider"/>
- </extensionPoint>
-
<extensionPoint name="additionalTextAttributes" beanClass="com.intellij.openapi.editor.colors.impl.AdditionalTextAttributesEP" />
<extensionPoint name="bundledColorScheme" beanClass="com.intellij.openapi.editor.colors.impl.BundledColorSchemeEP"/>
<extensionPoint name="bundledQuickListsProvider" interface="com.intellij.openapi.actionSystem.impl.BundledQuickListsProvider"/>
@@ -217,5 +213,8 @@
<with attribute="schemeClass" implements="com.intellij.openapi.options.Scheme"/>
<with attribute="implementationClass" implements="com.intellij.openapi.options.SchemeImporter"/>
</extensionPoint>
+
+ <extensionPoint qualifiedName="org.jetbrains.urlOpener" interface="com.intellij.ide.browsers.UrlOpener"/>
+ <extensionPoint name="tipAndTrick" beanClass="com.intellij.ide.util.TipAndTrickBean"/>
</extensionPoints>
</idea-plugin>
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index b1c2f3a..d02dd82 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -205,10 +205,6 @@
<applicationConfigurable instance="com.intellij.ide.ui.customization.CustomizationConfigurable" id="preferences.customizations"
key="title.customizations" bundle="messages.IdeBundle"/>
- <!-- Web Browser -->
- <applicationConfigurable instance="com.intellij.ide.BrowserSettings" id="reference.settings.ide.settings.web.browsers"
- key="browsers.settings" bundle="messages.IdeBundle"/>
-
<!-- Notifications -->
<applicationConfigurable instance="com.intellij.notification.impl.NotificationsConfigurable"/>
@@ -216,6 +212,7 @@
<applicationConfigurable instance="com.intellij.ide.plugins.PluginManagerConfigurable" id="preferences.pluginManager"
displayName="Plugins"/>
<applicationConfigurable instance="com.intellij.util.net.HTTPProxySettingsPanel" id="http.proxy" displayName="HTTP Proxy" />
+ <applicationConfigurable instance="com.intellij.util.net.ssl.CertificateConfigurable"/>
<applicationConfigurable instance="com.intellij.openapi.diff.impl.external.DiffOptionsForm" id="diff" displayName="External Diff Tools" />
<!--<applicationConfigurable instance="com.intellij.ui.switcher.QuickAccessConfigurable"/>-->
diff --git a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
index 426575e..943f3f5 100644
--- a/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
+++ b/platform/platform-resources/src/META-INF/PlatformLangPlugin.xml
@@ -22,6 +22,9 @@
<xi:include href="/META-INF/VcsExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
<xi:include href="/META-INF/LangExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
+ <applicationService serviceInterface="com.intellij.ide.RecentProjectsManagerBase"
+ serviceImplementation="com.intellij.ide.RecentDirectoryProjectsManagerEx"/>
+
<applicationService serviceInterface="com.intellij.packageDependencies.DependenciesVisitorFactory"
serviceImplementation="com.intellij.packageDependencies.DependenciesVisitorFactory"/>
<applicationService serviceInterface="com.intellij.openapi.projectRoots.ProjectJdkTable"
diff --git a/platform/platform-resources/src/META-INF/PlatformPlugin.xml b/platform/platform-resources/src/META-INF/PlatformPlugin.xml
index fefb33c..8cca39a 100644
--- a/platform/platform-resources/src/META-INF/PlatformPlugin.xml
+++ b/platform/platform-resources/src/META-INF/PlatformPlugin.xml
@@ -18,6 +18,9 @@
<xi:include href="/META-INF/PlatformExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
<xi:include href="/META-INF/VcsExtensions.xml" xpointer="xpointer(/idea-plugin/extensions/*)"/>
+ <applicationService serviceInterface="com.intellij.ide.RecentProjectsManagerBase"
+ serviceImplementation="com.intellij.ide.RecentDirectoryProjectsManager"/>
+
<applicationService serviceInterface="com.intellij.codeStyle.CodeStyleFacade"
serviceImplementation="com.intellij.codeStyle.DefaultCodeStyleFacade"/>
@@ -29,6 +32,9 @@
<applicationService serviceInterface="com.intellij.ui.mac.MacMessages"
serviceImplementation="com.intellij.ui.mac.MacMessagesImpl"/>
+
+ <applicationService serviceInterface="com.intellij.ui.mac.MacMessagesEmulation"
+ serviceImplementation="com.intellij.ui.messages.JBMacMessages"/>
<projectService serviceInterface="com.intellij.openapi.roots.FileIndexFacade"
serviceImplementation="com.intellij.openapi.vcs.impl.DefaultFileIndexFacade"/>
diff --git a/platform/platform-resources/src/META-INF/XmlActions.xml b/platform/platform-resources/src/META-INF/XmlActions.xml
index ca19e8d..8f4df7d 100644
--- a/platform/platform-resources/src/META-INF/XmlActions.xml
+++ b/platform/platform-resources/src/META-INF/XmlActions.xml
@@ -62,7 +62,7 @@
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFromTemplate"/>
</group>
- <group id="NewXmlDescriptor" class="com.intellij.ide.actions.NonEmptyActionGroup" text="XML Configuration File" popup="true" icon="AllIcons.FileTypes.Xml">
+ <group id="NewXmlDescriptor" class="com.intellij.ide.actions.NonTrivialActionGroup" text="XML Configuration File" popup="true" icon="AllIcons.FileTypes.Xml">
<add-to-group group-id="NewGroup" anchor="last"/>
</group>
@@ -72,14 +72,24 @@
<add-to-group group-id="GenerateGroup" anchor="first"/>
</action>
- <action id="OpenInBrowser" class="com.intellij.ide.browsers.OpenFileInDefaultBrowserAction"
- text="Open in _Browser" description="Open a selected file in default browser"
+ <!-- id should be "OpenInDefaultBrowser", but existing name preserved to keep compatibility - if user configured shortcut for action, it should not be lost -->
+ <action id="OpenInBrowser" class="com.intellij.ide.browsers.actions.OpenFileInDefaultBrowserAction"
+ text="Open in default _browser" description="Open selected file in default browser"
icon="AllIcons.Nodes.PpWeb">
+ </action>
+
+ <group id="OpenInBrowserGroup"
+ class="com.intellij.ide.browsers.actions.OpenInBrowserBaseGroupAction$OpenInBrowserGroupAction"
+ text="Open in _Browser" description="Open selected file in browser" icon="AllIcons.Nodes.PpWeb">
<add-to-group group-id="ViewMenu" anchor="after" relative-to-action="ViewSource"/>
<add-to-group group-id="RunContextPopupGroup" anchor="last"/>
- <!--<add-to-group group-id="ProjectViewPopupMenu" anchor="after" relative-to-action="EditSource"/>-->
- </action>
-
+ </group>
+ <group id="OpenInBrowserEditorContextBarGroupAction"
+ class="com.intellij.ide.browsers.actions.OpenInBrowserBaseGroupAction$OpenInBrowserEditorContextBarGroupAction"
+ description="Open In...">
+ <add-to-group group-id="EditorContextBarMenu" anchor="last"/>
+ </group>
+
<action id="SurroundWithEmmet" class="com.intellij.codeInsight.template.emmet.SurroundWithEmmetAction"
text="Surround with Emmet" description="Surround selected code with Emmet abbreviation"/>
</actions>
diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml
index d66fc02..88c3d8b 100644
--- a/platform/platform-resources/src/META-INF/XmlPlugin.xml
+++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml
@@ -70,10 +70,8 @@
<extensionPoint name="xml.html5SchemaProvider" interface="com.intellij.xml.Html5SchemaProvider"/>
<extensionPoint name="xml.implicitIdRefProvider" interface="com.intellij.psi.impl.source.resolve.reference.impl.providers.ImplicitIdRefProvider"/>
- <extensionPoint qualifiedName="org.jetbrains.urlOpener" interface="com.intellij.ide.browsers.UrlOpener"/>
<extensionPoint qualifiedName="org.jetbrains.javaScriptDebuggerStarter" interface="com.intellij.ide.browsers.JavaScriptDebuggerStarter"/>
-
<extensionPoint name="html.scriptContentProvider"
beanClass="com.intellij.lang.LanguageExtensionPoint">
<with attribute="implementationClass" implements="com.intellij.lang.HtmlScriptContentProvider"/>
@@ -104,6 +102,8 @@
</project-components>
<extensions defaultExtensionNs="com.intellij">
+ <tipAndTrick file="TagNameCompletion.html"/>
+
<fileTypeFactory implementation="com.intellij.xml.XmlFileTypeFactory"/>
<lang.syntaxHighlighterFactory key="XML" implementationClass="com.intellij.lang.xml.XmlSyntaxHighlighterFactory"/>
@@ -194,8 +194,8 @@
serviceImplementation="com.intellij.application.options.XmlSettings"/>
<exportable serviceInterface="com.intellij.application.options.XmlSettings"/>
- <applicationService serviceInterface="com.intellij.ide.browsers.BrowsersConfiguration"
- serviceImplementation="com.intellij.ide.browsers.BrowsersConfiguration"/>
+ <applicationService serviceInterface="com.intellij.ide.browsers.WebBrowserManager"
+ serviceImplementation="com.intellij.ide.browsers.WebBrowserManager"/>
<projectService serviceInterface="com.intellij.psi.XmlElementFactory"
serviceImplementation="com.intellij.psi.XmlElementFactoryImpl"/>
@@ -203,6 +203,7 @@
<highlightVisitor implementation="com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor"/>
<customLiveTemplate implementation="com.intellij.codeInsight.template.emmet.ZenCodingTemplate"/>
+ <lookup.actionProvider implementation="com.intellij.codeInsight.template.emmet.completion.EmmetLookupActionProvider"/>
<externalAnnotator language="XML" implementationClass="com.intellij.lang.xml.XMLExternalAnnotator"/>
<externalAnnotator language="HTML" implementationClass="com.intellij.lang.xml.XMLExternalAnnotator"/>
@@ -361,6 +362,8 @@
<applicationService serviceInterface="com.intellij.ide.browsers.WebBrowserService"
serviceImplementation="com.intellij.ide.browsers.impl.WebBrowserServiceImpl"/>
+ <applicationService serviceInterface="com.intellij.ide.browsers.BrowserLauncher" serviceImplementation="com.intellij.ide.browsers.BrowserLauncherImpl"/>
+
<patterns.patternClass className="com.intellij.patterns.XmlPatterns" alias="xml"/>
<lang.smartEnterProcessor language="XML" implementationClass="com.intellij.codeInsight.completion.XmlSmartEnterProcessor"/>
@@ -433,8 +436,6 @@
<metaDataContributor implementation="com.intellij.xml.util.XmlApplicationComponent"/>
- <browserSettingsProvider instance="com.intellij.ide.browsers.impl.BrowserSettingsProviderImpl"/>
-
<xml.xmlSuppressionProvider implementation="com.intellij.codeInspection.DefaultXmlSuppressionProvider" order="last"/>
<multiHostInjector implementation="com.intellij.psi.impl.source.html.HtmlConditionalCommentInjector"/>
@@ -514,9 +515,11 @@
<codeInsight.unresolvedReferenceQuickFixProvider
implementation="com.intellij.psi.impl.source.resolve.reference.impl.providers.DependentNSReferenceQuickFixProvider"/>
- <selectInTarget implementation="com.intellij.ide.browsers.SelectInDefaultBrowserTarget"/>
+ <selectInTarget implementation="com.intellij.ide.browsers.actions.SelectInDefaultBrowserTarget"/>
<xml.xmlExtension implementation="com.intellij.xml.HtmlXmlExtension"/>
+ <applicationConfigurable instance="com.intellij.ide.browsers.BrowserSettings" id="reference.settings.ide.settings.web.browsers"
+ key="browsers.settings" bundle="messages.IdeBundle"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains">
<urlOpener implementation="com.intellij.ide.browsers.impl.DefaultUrlOpener" order="last"/>
diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt
index 5983a4d..a67cc57 100644
--- a/platform/platform-resources/src/brokenPlugins.txt
+++ b/platform/platform-resources/src/brokenPlugins.txt
@@ -2,12 +2,12 @@
// Each line contains plugin ID and list of versions that are broken.
// If plugin name or version contains a space you can quote it like in command line.
-NodeJS 133.74 133.50 133.373 133.293 133.260 133.195 133.162 133.134
-com.jetbrains.php 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
-org.intellij.clojure 0.7.60
-org.intellij.scala 0.29.464 0.28.366 0.23.308
-org.jetbrains.plugins.ruby 6.0.0.20131207 6.0.0.20131121
-Karma 133.50
-com.jetbrains.lang.ejs 131.17 131.12
-com.jetbrains.twig 133.51 130.1639
-org.jetbrains.kannotator 0.2.420
\ No newline at end of file
+NodeJS 134.1145 134.1081 134.1039 134.985 134.680 134.31 134.307 134.262 134.198 134.125
+com.jetbrains.php 133.679 133.51 133.326 131.98 131.374 131.332 131.235 131.205 130.1639 130.1481 130.1176 129.91 129.814 129.672 129.362 127.67 127.100 126.334 123.66 122.875 121.62 121.390 121.215 121.12
+com.jetbrains.lang.ejs 131.17 131.12
+com.jetbrains.twig 133.51 130.1639
+//org.jetbrains.plugins.ruby 6.0.0.20140207
+Pythonid 3.1
+Karma 134.686 134.31
+org.intellij.scala 0.32.512
+org.jetbrains.kannotator 0.2.420
diff --git a/platform/platform-resources/src/componentSets/Lang.xml b/platform/platform-resources/src/componentSets/Lang.xml
index fbb77b2..dc2fabf 100644
--- a/platform/platform-resources/src/componentSets/Lang.xml
+++ b/platform/platform-resources/src/componentSets/Lang.xml
@@ -230,6 +230,10 @@
<skipForDefaultProject/>
</component>
+ <component>
+ <interface-class>com.intellij.ide.GeneratedSourceFileChangeTracker</interface-class>
+ <implementation-class>com.intellij.ide.GeneratedSourceFileChangeTrackerImpl</implementation-class>
+ </component>
</project-components>
<module-components>
diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml
index ef911ec..77d5050 100644
--- a/platform/platform-resources/src/componentSets/Platform.xml
+++ b/platform/platform-resources/src/componentSets/Platform.xml
@@ -134,6 +134,10 @@
</component>
<component>
+ <implementation-class>com.intellij.util.net.ssl.CertificatesManager</implementation-class>
+ </component>
+
+ <component>
<implementation-class>com.intellij.ide.SystemHealthMonitor</implementation-class>
<headless-implementation-class/>
</component>
diff --git a/platform/platform-resources/src/componentSets/PlatformComponents.xml b/platform/platform-resources/src/componentSets/PlatformComponents.xml
index 29037ab..8aa305c 100644
--- a/platform/platform-resources/src/componentSets/PlatformComponents.xml
+++ b/platform/platform-resources/src/componentSets/PlatformComponents.xml
@@ -15,10 +15,6 @@
<interface-class>com.intellij.openapi.project.impl.ProjectStoreClassProvider</interface-class>
<implementation-class>com.intellij.openapi.components.impl.stores.PlatformProjectStoreClassProvider</implementation-class>
</component>
- <component>
- <interface-class>com.intellij.ide.RecentProjectsManagerBase</interface-class>
- <implementation-class>com.intellij.ide.RecentDirectoryProjectsManager</implementation-class>
- </component>
</application-components>
<project-components>
<component>
@@ -53,7 +49,7 @@
<component>
<implementation-class>com.intellij.platform.PlatformVcsDetector</implementation-class>
- <headless-implementation-class></headless-implementation-class>
+ <headless-implementation-class/>
</component>
</project-components>
diff --git a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml
index 7e4cbdc..dc70e39 100644
--- a/platform/platform-resources/src/componentSets/PlatformLangComponents.xml
+++ b/platform/platform-resources/src/componentSets/PlatformLangComponents.xml
@@ -15,10 +15,6 @@
<interface-class>com.intellij.openapi.project.impl.ProjectStoreClassProvider</interface-class>
<implementation-class>com.intellij.openapi.components.impl.stores.PlatformLangProjectStoreClassProvider</implementation-class>
</component>
- <component>
- <interface-class>com.intellij.ide.RecentProjectsManagerBase</interface-class>
- <implementation-class>com.intellij.ide.RecentDirectoryProjectsManagerEx</implementation-class>
- </component>
</application-components>
<project-components>
<component>
diff --git a/platform/platform-resources/src/componentSets/UICore.xml b/platform/platform-resources/src/componentSets/UICore.xml
index f813dd2..8d7d5d6 100644
--- a/platform/platform-resources/src/componentSets/UICore.xml
+++ b/platform/platform-resources/src/componentSets/UICore.xml
@@ -61,10 +61,13 @@
<component>
<implementation-class>com.intellij.ui.switcher.QuickAccessSettings</implementation-class>
</component>
+
<component>
<implementation-class>com.intellij.openapi.updateSettings.impl.UpdateCheckerComponent</implementation-class>
+ <headless-implementation-class/>
</component>
</application-components>
+
<project-components>
<component>
<implementation-class>com.intellij.ui.switcher.SwitchManager</implementation-class>
diff --git a/platform/platform-resources/src/idea/Keymap_ReSharper_OSX.xml b/platform/platform-resources/src/idea/Keymap_ReSharper_OSX.xml
index f42c0a4..f13ad3e 100755
--- a/platform/platform-resources/src/idea/Keymap_ReSharper_OSX.xml
+++ b/platform/platform-resources/src/idea/Keymap_ReSharper_OSX.xml
@@ -18,9 +18,6 @@
<keyboard-shortcut first-keystroke="meta alt ENTER"/>
</action>
<action id="Console.TableResult.Reload"/>
- <action id="DatabaseView.AddAction">
- <keyboard-shortcut first-keystroke="meta alt ENTER"/>
- </action>
<action id="ExportTestResults">
<keyboard-shortcut first-keystroke="control alt U"/>
</action>
diff --git a/platform/platform-resources/src/idea/Keymap_VisualStudio.xml b/platform/platform-resources/src/idea/Keymap_VisualStudio.xml
index 5762770..7df5974 100644
--- a/platform/platform-resources/src/idea/Keymap_VisualStudio.xml
+++ b/platform/platform-resources/src/idea/Keymap_VisualStudio.xml
@@ -101,7 +101,6 @@
<keyboard-shortcut first-keystroke="shift control I"/>
</action>
<action id="SmartTypeCompletion">
- <keyboard-shortcut first-keystroke="alt SPACE"/>
<keyboard-shortcut first-keystroke="shift alt SPACE"/>
</action>
<action id="GotoDeclaration">
diff --git a/platform/platform-resources/src/idea/PlatformActions.xml b/platform/platform-resources/src/idea/PlatformActions.xml
index f31b83c..3fe320b 100644
--- a/platform/platform-resources/src/idea/PlatformActions.xml
+++ b/platform/platform-resources/src/idea/PlatformActions.xml
@@ -89,6 +89,8 @@
<action id="EditorMoveDownAndScroll" class="com.intellij.openapi.editor.actions.MoveDownAndScrollAction"/>
<action id="EditorMoveUpAndScrollWithSelection" class="com.intellij.openapi.editor.actions.MoveUpWithSelectionAndScrollAction"/>
<action id="EditorMoveDownAndScrollWithSelection" class="com.intellij.openapi.editor.actions.MoveDownWithSelectionAndScrollAction"/>
+ <action id="EditorCloneCaretBelow" class="com.intellij.openapi.editor.actions.CloneCaretBelow"/>
+ <action id="EditorCloneCaretAbove" class="com.intellij.openapi.editor.actions.CloneCaretAbove"/>
<action id="EditorToggleStickySelection" class="com.intellij.openapi.editor.actions.ToggleStickySelectionModeAction"/>
<action id="EditorSwapSelectionBoundaries" class="com.intellij.openapi.editor.actions.SwapSelectionBoundariesAction"/>
<action id="EditorLineStart" class="com.intellij.openapi.editor.actions.LineStartAction"/>
@@ -189,7 +191,7 @@
<action id="ChangeFileEncodingAction" class="com.intellij.openapi.vfs.encoding.ChangeFileEncodingAction"/>
- <group id="ChangeLineSeparators" text="Line Separators" popup="true">
+ <group id="ChangeLineSeparators" text="Line Separators" popup="true" class="com.intellij.ide.actions.NonTrivialActionGroup">
<action id="ConvertToWindowsLineSeparators" class="com.intellij.codeStyle.ConvertToWindowsLineSeparatorsAction"/>
<action id="ConvertToUnixLineSeparators" class="com.intellij.codeStyle.ConvertToUnixLineSeparatorsAction"/>
<action id="ConvertToMacLineSeparators" class="com.intellij.codeStyle.ConvertToMacLineSeparatorsAction"/>
@@ -550,6 +552,8 @@
<reference ref="NextDiff"/>
<separator/>
<action id="Diff.IgnoreWhitespace" class="com.intellij.openapi.diff.actions.IgnoreWhiteSpacesAction" text=""/>
+ <separator/>
+ <action id="Diff.HighlightMode" class="com.intellij.openapi.diff.actions.HighlightModeAction" text=""/>
</group>
<group id="ChangeScheme">
@@ -615,6 +619,7 @@
</group>
<group id="TopAnomalies" internal="true" class="com.intellij.internal.anomalies.TopAnomaliesAction" text="Top Anomalies" popup="true"/>
<action id="ImageDuplicates" internal="true" class="com.intellij.internal.ShowImageDuplicatesAction" text="Find Image Duplicates"/>
+ <action id="ShowNonRetinaImages" internal="true" class="com.intellij.internal.ShowNonRetinaImagesActions" text="Show Non Retina Images"/>
<separator/>
<reference ref="MaintenanceGroup"/>
diff --git a/platform/platform-tests/testData/editor/multiCaret/$SelectAll-after.txt b/platform/platform-tests/testData/editor/multiCaret/$SelectAll-after.txt
new file mode 100644
index 0000000..cceb844
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/$SelectAll-after.txt
@@ -0,0 +1,2 @@
+<selection>some text
+some <caret>other text</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/$SelectAll-before.txt b/platform/platform-tests/testData/editor/multiCaret/$SelectAll-before.txt
new file mode 100644
index 0000000..c117ff5
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/$SelectAll-before.txt
@@ -0,0 +1,2 @@
+some<caret> text
+some <selection><caret>other</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorBackSpace-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorBackSpace-after.txt
new file mode 100644
index 0000000..0247661
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorBackSpace-after.txt
@@ -0,0 +1,2 @@
+<caret>some <caret>xt<caret>ot<caret> t<caret>
+another <caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorBackSpace-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorBackSpace-before.txt
new file mode 100644
index 0000000..3c90879
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorBackSpace-before.txt
@@ -0,0 +1,3 @@
+<caret>some t<caret>e<caret>xt
+<caret>ot<selection><caret>her</selection> t<selection>ext<caret></selection>
+another <selection>l<caret>ine</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-after.txt
new file mode 100644
index 0000000..7a9d374
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-after.txt
@@ -0,0 +1,3 @@
+s<caret>ome te<caret>xt
+s<caret>ome oth<selection><caret>er t</selection>ext
+a<caret>nother <selection><caret>line</selection> of text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-before.txt
new file mode 100644
index 0000000..caad4cb
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretAbove-before.txt
@@ -0,0 +1,3 @@
+some te<caret>xt
+s<caret>ome other text
+a<caret>nother <selection><caret>line</selection> of text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-after.txt
new file mode 100644
index 0000000..a24e034
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-after.txt
@@ -0,0 +1,3 @@
+s<caret>ome text
+s<caret>ome other <selection>text<caret></selection>
+a<caret>not<caret>her lin<selection>e of<caret></selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-before.txt
new file mode 100644
index 0000000..3758a93
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCloneCaretBelow-before.txt
@@ -0,0 +1,3 @@
+s<caret>ome text
+s<caret>ome other <selection>text<caret></selection>
+anot<caret>her line of text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEnd-after.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEnd-after.java
new file mode 100644
index 0000000..419656f
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEnd-after.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {
+
+ <caret>}
+
+ void m2() {
+ System.out.println();
+ <caret>}
+
+<caret>}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEnd-before.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEnd-before.java
new file mode 100644
index 0000000..d1657bd
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEnd-before.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {
+<caret>
+ }
+
+ void m2() {
+ System<caret>.out.<selection>println<caret></selection>();
+<selection> }
+<caret></selection>
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEndWithSelection-after.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEndWithSelection-after.java
new file mode 100644
index 0000000..ec769f7
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEndWithSelection-after.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {
+<selection>
+ <caret></selection>}
+
+ void m2() {
+ System.out.<selection>println();
+ }
+
+<caret></selection>}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEndWithSelection-before.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEndWithSelection-before.java
new file mode 100644
index 0000000..c71c825
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockEndWithSelection-before.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {
+<caret>
+ }
+
+ void m2() {
+ System.out.<selection>println<caret></selection>();
+<selection> }
+<caret></selection>
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStart-after.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStart-after.java
new file mode 100644
index 0000000..ead153d
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStart-after.java
@@ -0,0 +1,10 @@
+public class Test {<caret>
+ void m1() {<caret>
+
+ }
+
+ void m2() {<caret>
+ System.out.println();
+ }
+
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStart-before.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStart-before.java
new file mode 100644
index 0000000..d1657bd
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStart-before.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {
+<caret>
+ }
+
+ void m2() {
+ System<caret>.out.<selection>println<caret></selection>();
+<selection> }
+<caret></selection>
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStartWithSelection-after.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStartWithSelection-after.java
new file mode 100644
index 0000000..bdd168d
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStartWithSelection-after.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {<selection><caret>
+</selection>
+ }
+
+ <selection>void m2() {<caret>
+ System.out.</selection>println();
+ }
+
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStartWithSelection-before.java b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStartWithSelection-before.java
new file mode 100644
index 0000000..f32eea5
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorCodeBlockStartWithSelection-before.java
@@ -0,0 +1,10 @@
+public class Test {
+ void m1() {
+<caret>
+ }
+
+ <selection>void m2() {
+ <caret></selection>System<caret>.out.<selection>println<caret></selection>();
+ }
+
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDelete-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDelete-after.txt
new file mode 100644
index 0000000..e699575
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDelete-after.txt
@@ -0,0 +1,2 @@
+<caret>ome t<caret>t<caret>ot<caret> t<caret>
+another <caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDelete-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDelete-before.txt
new file mode 100644
index 0000000..6c5d11a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDelete-before.txt
@@ -0,0 +1,3 @@
+<caret>some t<caret>e<caret>xt<caret>
+ot<selection><caret>her</selection> t<selection>ext<caret></selection>
+another <selection>l<caret>ine</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteLine-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteLine-after.txt
new file mode 100644
index 0000000..c398185
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteLine-after.txt
@@ -0,0 +1,2 @@
+<caret>blah
+<caret>blah
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteLine-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteLine-before.txt
new file mode 100644
index 0000000..0821bf0
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteLine-before.txt
@@ -0,0 +1,6 @@
+<selection>some <caret></selection>text
+blah
+another text<caret>
+anot<caret>he<caret>r line
+yet another line
+blah
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt
new file mode 100644
index 0000000..59aa5d7
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-after.txt
@@ -0,0 +1,2 @@
+s<caret>text<caret>o<selection>t<caret></selection> text
+an<caret> l<caret>yet a<selection>not<caret></selection> line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-before.txt
new file mode 100644
index 0000000..1910298
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEnd-before.txt
@@ -0,0 +1,4 @@
+s<caret>o<caret>me text<caret>
+o<selection>t<caret>he</selection>r text
+an<selection><caret>oth</selection>er l<caret>i<caret>ne
+yet a<selection>not<caret></selection>her line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt
new file mode 100644
index 0000000..74c13ea
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-after.txt
@@ -0,0 +1,2 @@
+Ab<caret>Dabra<caret>Hum<selection><caret>D</selection>ump Hu<selection>mpDu<caret></selection>
+<selection>YetAnot<caret>HumpedWord</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-before.txt
new file mode 100644
index 0000000..f37f1bd
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordEndInDifferentHumpsMode-before.txt
@@ -0,0 +1,3 @@
+Ab<caret>r<caret>aCaDabra<caret>
+Hum<selection><caret>pD</selection>ump Hu<selection>mpDu<caret></selection>mp
+<selection>YetAnot<caret>herHumpedWord</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt
new file mode 100644
index 0000000..7c5d3fc
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-after.txt
@@ -0,0 +1,3 @@
+<caret>some <caret>t
+<caret>ther <caret>t
+<caret>other line<caret>yet another line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-before.txt
new file mode 100644
index 0000000..e6aea30
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStart-before.txt
@@ -0,0 +1,4 @@
+<caret>some t<caret>ex<caret>t
+o<selection><caret>th</selection>er t<selection>ex<caret></selection>t
+<selection>an<caret>other</selection> line
+<caret>yet another line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt
new file mode 100644
index 0000000..eefa20b
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-after.txt
@@ -0,0 +1,3 @@
+<caret>aCa<caret>
+<caret>pDump Hump<caret>mp
+Yet<caret>herHumpedWord
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-before.txt
new file mode 100644
index 0000000..f37f1bd
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDeleteToWordStartInDifferentHumpsMode-before.txt
@@ -0,0 +1,3 @@
+Ab<caret>r<caret>aCaDabra<caret>
+Hum<selection><caret>pD</selection>ump Hu<selection>mpDu<caret></selection>mp
+<selection>YetAnot<caret>herHumpedWord</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDown-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDown-after.txt
new file mode 100644
index 0000000..bf92db9
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDown-after.txt
@@ -0,0 +1,3 @@
+yet another line
+some <caret>other text<caret>
+some text<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDown-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDown-before.txt
new file mode 100644
index 0000000..525efc9
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDown-before.txt
@@ -0,0 +1,3 @@
+yet a<selection><caret>no</selection>ther line<caret>
+some other te<caret>xt
+some<caret> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDownWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDownWithSelection-after.txt
new file mode 100644
index 0000000..1098f44
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDownWithSelection-after.txt
@@ -0,0 +1,5 @@
+yet ano<selection>ther line
+blah <caret></selection>blah<selection>
+<caret></selection>
+some ot<selection>her text
+some text<caret></selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDownWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDownWithSelection-before.txt
new file mode 100644
index 0000000..d759609
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDownWithSelection-before.txt
@@ -0,0 +1,5 @@
+yet a<selection><caret>no</selection>ther line
+blah blah<caret>
+
+some ot<caret>her text
+some<caret> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDuplicate-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicate-after.txt
new file mode 100644
index 0000000..ac4bd67
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicate-after.txt
@@ -0,0 +1,4 @@
+some<selection>me<caret></selection> text<selection>xt<caret></selection>
+some other text
+some other t<caret>ext
+another line<selection>line<caret></selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDuplicate-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicate-before.txt
new file mode 100644
index 0000000..f0e8d46
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicate-before.txt
@@ -0,0 +1,3 @@
+so<selection><caret>me</selection> te<selection>xt<caret></selection>
+some other t<caret>ext
+another <selection>l<caret>ine</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDuplicateLines-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicateLines-after.txt
new file mode 100644
index 0000000..39a4e45
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicateLines-after.txt
@@ -0,0 +1,12 @@
+line1
+lin<caret>e1
+line2
+<selection>li<caret>ne2</selection>
+line3
+<selection>li<caret>ne3</selection>
+line4
+line5
+line6
+<selection>line5
+lin<caret>e6</selection>
+line7
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorDuplicateLines-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicateLines-before.txt
new file mode 100644
index 0000000..594737a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorDuplicateLines-before.txt
@@ -0,0 +1,7 @@
+lin<caret>e1
+li<selection><caret>ne2</selection>
+<selection>li<caret>ne3</selection>
+line4
+li<selection>ne5
+lin<caret></selection>e6
+line7
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorEnter-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorEnter-after.txt
new file mode 100644
index 0000000..fb34812
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorEnter-after.txt
@@ -0,0 +1,7 @@
+some
+ <caret>te
+ <caret>xt
+other
+<caret>
+
+<caret> line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorEnter-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorEnter-before.txt
new file mode 100644
index 0000000..74b66fe
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorEnter-before.txt
@@ -0,0 +1,3 @@
+some<caret> te<caret>xt
+other<selection>text<caret></selection>
+<selection>an<caret>other</selection> line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorEscape-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorEscape-after.txt
new file mode 100644
index 0000000..4c01060
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorEscape-after.txt
@@ -0,0 +1,2 @@
+some text
+some other t<caret>ext
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorEscape-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorEscape-before.txt
new file mode 100644
index 0000000..913fd00
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorEscape-before.txt
@@ -0,0 +1,2 @@
+so<caret>me <selection><caret>text</selection>
+some other <selection>t<caret>ext</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorIndentLineOrSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorIndentLineOrSelection-after.txt
new file mode 100644
index 0000000..a3fae67
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorIndentLineOrSelection-after.txt
@@ -0,0 +1,4 @@
+<selection><caret> some text
+ another line</selection>
+ <selection>some other text<caret></selection>
+ yet ano<caret>ther line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorIndentLineOrSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorIndentLineOrSelection-before.txt
new file mode 100644
index 0000000..f44ad7e
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorIndentLineOrSelection-before.txt
@@ -0,0 +1,4 @@
+<selection><caret> some text
+ another line</selection>
+ <selection>some other text<caret></selection>
+yet ano<caret>ther line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorIndentSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorIndentSelection-after.txt
new file mode 100644
index 0000000..36c8931
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorIndentSelection-after.txt
@@ -0,0 +1,3 @@
+<selection><caret> some text
+ another line</selection>
+ <selection>some other text<caret></selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorIndentSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorIndentSelection-before.txt
new file mode 100644
index 0000000..cb98de7
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorIndentSelection-before.txt
@@ -0,0 +1,3 @@
+<selection><caret> some text
+ another line</selection>
+ <selection>some other text<caret></selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorJoinLines-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorJoinLines-after.txt
new file mode 100644
index 0000000..469268b
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorJoinLines-after.txt
@@ -0,0 +1,4 @@
+line1<caret> line2
+<selection>line3<caret></selection>
+li<selection>ne4 li<caret></selection>ne5<caret> line6
+line7
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorJoinLines-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorJoinLines-before.txt
new file mode 100644
index 0000000..3bd2a4b
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorJoinLines-before.txt
@@ -0,0 +1,7 @@
+lin<caret>e1
+line2
+<selection><caret>line3</selection>
+li<selection><caret>ne4
+li</selection>ne<caret>5
+line6
+line7
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLeft-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLeft-after.txt
new file mode 100644
index 0000000..dd6abb8
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLeft-after.txt
@@ -0,0 +1,3 @@
+<caret>some text<caret>
+some <caret>other text
+yet a<caret>nother <caret>line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLeft-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLeft-before.txt
new file mode 100644
index 0000000..7fc02d7
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLeft-before.txt
@@ -0,0 +1,3 @@
+<caret>s<caret>ome text
+<caret>some <selection><caret>other</selection> text
+yet a<selection>no<caret></selection>ther <selection>l<caret>ine</selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLeftWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLeftWithSelection-after.txt
new file mode 100644
index 0000000..60bf827
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLeftWithSelection-after.txt
@@ -0,0 +1,3 @@
+<selection><caret>s</selection>ome text<selection><caret>
+</selection>some<selection><caret> other text</selection>
+yet an<caret>other <selection><caret>line</selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLeftWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLeftWithSelection-before.txt
new file mode 100644
index 0000000..de28df8
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLeftWithSelection-before.txt
@@ -0,0 +1,3 @@
+<caret>s<caret>ome text
+<caret>some <selection><caret>other</selection><selection><caret> text</selection>
+yet an<selection>o<caret></selection>ther <selection>l<caret>ine</selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineEnd-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineEnd-after.txt
new file mode 100644
index 0000000..a53eaaf
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineEnd-after.txt
@@ -0,0 +1,2 @@
+some text<caret>
+other line<caret>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineEnd-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineEnd-before.txt
new file mode 100644
index 0000000..034485a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineEnd-before.txt
@@ -0,0 +1,2 @@
+some <caret>te<caret>xt
+ot<selection><caret>her</selection> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineEndWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineEndWithSelection-after.txt
new file mode 100644
index 0000000..fcf8abd
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineEndWithSelection-after.txt
@@ -0,0 +1,2 @@
+some <selection>text<caret></selection>
+other<selection> line<caret></selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineEndWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineEndWithSelection-before.txt
new file mode 100644
index 0000000..034485a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineEndWithSelection-before.txt
@@ -0,0 +1,2 @@
+some <caret>te<caret>xt
+ot<selection><caret>her</selection> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineStart-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineStart-after.txt
new file mode 100644
index 0000000..a12c056
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineStart-after.txt
@@ -0,0 +1,2 @@
+<caret>some text
+<caret>other line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineStart-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineStart-before.txt
new file mode 100644
index 0000000..034485a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineStart-before.txt
@@ -0,0 +1,2 @@
+some <caret>te<caret>xt
+ot<selection><caret>her</selection> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineStartWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineStartWithSelection-after.txt
new file mode 100644
index 0000000..f2bb632
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineStartWithSelection-after.txt
@@ -0,0 +1,2 @@
+<selection><caret>some te</selection>xt
+<selection><caret>other</selection> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorLineStartWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorLineStartWithSelection-before.txt
new file mode 100644
index 0000000..034485a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorLineStartWithSelection-before.txt
@@ -0,0 +1,2 @@
+some <caret>te<caret>xt
+ot<selection><caret>her</selection> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorMatchBrace-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorMatchBrace-after.txt
new file mode 100644
index 0000000..d3f9c9e
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorMatchBrace-after.txt
@@ -0,0 +1,4 @@
+{ a }<caret>
+{<caret> b }
+{<caret> c }
+text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorMatchBrace-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorMatchBrace-before.txt
new file mode 100644
index 0000000..4b0b53b
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorMatchBrace-before.txt
@@ -0,0 +1,4 @@
+{ <selection><caret>a</selection> }
+{ b <caret>}
+{ c }<caret>
+text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWord-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWord-after.txt
new file mode 100644
index 0000000..0e7d1fe
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWord-after.txt
@@ -0,0 +1,3 @@
+soMe <caret>text
+other line
+<caret>yet another <caret>line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWord-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWord-before.txt
new file mode 100644
index 0000000..98e6718
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWord-before.txt
@@ -0,0 +1,3 @@
+<selection>s<caret>oMe te</selection>xt
+other line<caret>
+yet another<caret> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsMode-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsMode-after.txt
new file mode 100644
index 0000000..7f487d9
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsMode-after.txt
@@ -0,0 +1,4 @@
+so<caret>Me text
+other line
+<caret>yet another <caret>line
+HeavilyHumped<caret>Word
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsMode-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsMode-before.txt
new file mode 100644
index 0000000..7ceb7dc
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsMode-before.txt
@@ -0,0 +1,4 @@
+<selection>s<caret>oMe te</selection>xt
+other line<caret>
+yet anot<caret>her<caret> line
+Heavily<caret>HumpedWord
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsModeWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsModeWithSelection-after.txt
new file mode 100644
index 0000000..d48ea72
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsModeWithSelection-after.txt
@@ -0,0 +1,5 @@
+so<selection><caret>Me te</selection>xt
+other line<selection>
+<caret></selection>yet ano<selection>ther <caret></selection>line
+Heavily<selection>Humped<caret></selection>Word
+HeavilyHum<selection>ped<caret></selection>Word
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsModeWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsModeWithSelection-before.txt
new file mode 100644
index 0000000..4c9fbb1
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordInDifferentHumpsModeWithSelection-before.txt
@@ -0,0 +1,5 @@
+<selection>s<caret>oMe te</selection>xt
+other line<caret>
+yet ano<selection>ther<caret></selection> line
+Heavily<caret>HumpedWord
+Heavily<selection><caret>Hum</selection>p<selection><caret>e</selection>dWord
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWordWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordWithSelection-after.txt
new file mode 100644
index 0000000..53cf730
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordWithSelection-after.txt
@@ -0,0 +1,5 @@
+soMe <selection><caret>te</selection>xt
+other line<selection>
+<caret></selection>yet another<selection> <caret></selection>line
+<selection>another line <caret></selection>again
+an<selection>d <caret></selection>again
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorNextWordWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordWithSelection-before.txt
new file mode 100644
index 0000000..0b6172c
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorNextWordWithSelection-before.txt
@@ -0,0 +1,5 @@
+<selection>s<caret>oMe te</selection>xt
+other line<caret>
+yet another<caret> line
+<selection>another li<caret></selection>ne again
+a<selection><caret>n</selection>d again
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageDown-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageDown-after.txt
new file mode 100644
index 0000000..6343b31
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageDown-after.txt
@@ -0,0 +1,23 @@
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+<caret>
+The quick brown fox jumps ov<caret>er the la<caret>zy dog.
+ The quick brown fox jumps over the lazy dog.<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageDown-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageDown-before.txt
new file mode 100644
index 0000000..f47968f
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageDown-before.txt
@@ -0,0 +1,23 @@
+The quick <caret>brown <selection><caret>fox</selection> jumps over the lazy dog.
+ The quick brown fox jumps <caret>over the <selection><caret>lazy</selection> dog.
+
+
+
+
+
+<caret>
+<caret>
+
+
+
+
+
+
+
+
+
+
+
+
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-1-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-1-after.txt
new file mode 100644
index 0000000..51e5a48
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-1-after.txt
@@ -0,0 +1,23 @@
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps <selection>over the lazy dog.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The quick brown fox jumps over the la<caret></selection>zy dog.
+ The quick brown fox jumps over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-1-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-1-before.txt
new file mode 100644
index 0000000..6b23f3f
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-1-before.txt
@@ -0,0 +1,23 @@
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps <caret>over the <selection><caret>lazy</selection> dog.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-2-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-2-after.txt
new file mode 100644
index 0000000..a016532
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-2-after.txt
@@ -0,0 +1,2 @@
+The quick brown<selection> fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.<caret></selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-2-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-2-before.txt
new file mode 100644
index 0000000..57e220c
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageDownWithSelection-2-before.txt
@@ -0,0 +1,2 @@
+The quick <selection><caret>brown</selection> fox jumps<caret> over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageUp-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageUp-after.txt
new file mode 100644
index 0000000..0c36e77
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageUp-after.txt
@@ -0,0 +1,23 @@
+<caret>The quick brown fox jumps over the lazy dog.
+ The quick<caret> brown<caret> fox jumps over the lazy dog.
+<caret>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageUp-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageUp-before.txt
new file mode 100644
index 0000000..ff95d78
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageUp-before.txt
@@ -0,0 +1,23 @@
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
+
+
+
+
+
+
+
+<caret>
+
+<caret>
+
+
+
+
+
+
+
+
+
+The quick <caret>brown <selection><caret>fox</selection> jumps over the lazy dog.
+ The quick brown fox jumps <caret>over the <selection><caret>lazy</selection> dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-1-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-1-after.txt
new file mode 100644
index 0000000..e578afb
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-1-after.txt
@@ -0,0 +1,23 @@
+The quick brown fox jumps over the lazy dog.
+ The quick<selection><caret> brown fox jumps over the lazy dog.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The quick brown fox</selection> jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-1-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-1-before.txt
new file mode 100644
index 0000000..a65c597
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-1-before.txt
@@ -0,0 +1,23 @@
+The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+The quick <caret>brown <selection><caret>fox</selection> jumps over the lazy dog.
+ The quick brown fox jumps over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-2-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-2-after.txt
new file mode 100644
index 0000000..7761199
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-2-after.txt
@@ -0,0 +1,2 @@
+<selection><caret>The quick brown fox jumps over the lazy dog.
+ The quick brown fox jumps</selection> over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-2-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-2-before.txt
new file mode 100644
index 0000000..6e81d83
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPageUpWithSelection-2-before.txt
@@ -0,0 +1,2 @@
+The quick brown fox jumps over the lazy dog.
+ The quick <selection><caret>brown</selection> fox jumps<caret> over the lazy dog.
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWord-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWord-after.txt
new file mode 100644
index 0000000..1028b6d
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWord-after.txt
@@ -0,0 +1,3 @@
+some <caret>tExt
+other <caret>line<caret>
+yet <caret>another line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWord-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWord-before.txt
new file mode 100644
index 0000000..b3f0256
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWord-before.txt
@@ -0,0 +1,3 @@
+some tE<selection>x<caret>t</selection>
+other l<caret>ine<caret>
+<caret>yet another<caret> <caret>line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsMode-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsMode-after.txt
new file mode 100644
index 0000000..06206c0
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsMode-after.txt
@@ -0,0 +1,4 @@
+some t<caret>Ext
+other <caret>line<caret>
+yet <caret>another line
+<caret>HeavilyHumped<caret>Word
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsMode-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsMode-before.txt
new file mode 100644
index 0000000..7f2e780
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsMode-before.txt
@@ -0,0 +1,4 @@
+some tE<selection>x<caret>t</selection>
+other l<caret>ine<caret>
+<caret>yet another<caret> <caret>line
+Heavily<caret>HumpedWor<caret>d
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsModeWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsModeWithSelection-after.txt
new file mode 100644
index 0000000..abc4266
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsModeWithSelection-after.txt
@@ -0,0 +1,5 @@
+so<selection><caret>Me te</selection>xt<selection><caret>
+</selection>other line
+yet <selection><caret>another</selection> line
+<selection><caret>Heavily</selection>HumpedWord
+<selection><caret>HeavilyHump</selection>edWord
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsModeWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsModeWithSelection-before.txt
new file mode 100644
index 0000000..9652755
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordInDifferentHumpsModeWithSelection-before.txt
@@ -0,0 +1,5 @@
+<selection>soM<caret>e te</selection>xt
+<caret>other line
+yet ano<selection><caret>ther</selection> line
+Heavily<caret>HumpedWord
+Heavily<selection><caret>Hum</selection>p<selection>e<caret></selection>dWord
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordWithSelection-after.txt
new file mode 100644
index 0000000..d1d92d5
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordWithSelection-after.txt
@@ -0,0 +1,4 @@
+some <selection><caret>tExt</selection>
+other <selection><caret>li</selection>ne<selection><caret>
+</selection>yet <selection><caret>another </selection>line
+some <selection><caret>othe</selection>r text
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordWithSelection-before.txt
new file mode 100644
index 0000000..5986e09
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorPreviousWordWithSelection-before.txt
@@ -0,0 +1,4 @@
+some tE<selection>x<caret>t</selection>
+other l<caret>i<selection>ne<caret></selection>
+<caret>yet another<caret> <caret>line
+some ot<selection><caret>he</selection>r text
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorRight-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorRight-after.txt
new file mode 100644
index 0000000..3c8e694
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorRight-after.txt
@@ -0,0 +1,4 @@
+some text
+<caret>some other<caret> text
+yet ano<caret>ther line<caret>
+<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorRight-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorRight-before.txt
new file mode 100644
index 0000000..bce0256
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorRight-before.txt
@@ -0,0 +1,4 @@
+some text<caret>
+some <selection><caret>other</selection> text
+yet a<selection>no<caret></selection>ther <selection>l<caret>ine</selection>
+<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorRightWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorRightWithSelection-after.txt
new file mode 100644
index 0000000..b6b755d
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorRightWithSelection-after.txt
@@ -0,0 +1,4 @@
+some text<selection>
+<caret></selection>some o<selection><caret>ther</selection> text
+yet a<selection>not<caret></selection>her li<selection><caret>ne</selection>
+<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorRightWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorRightWithSelection-before.txt
new file mode 100644
index 0000000..bce0256
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorRightWithSelection-before.txt
@@ -0,0 +1,4 @@
+some text<caret>
+some <selection><caret>other</selection> text
+yet a<selection>no<caret></selection>ther <selection>l<caret>ine</selection>
+<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorSelectWord-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorSelectWord-after.txt
new file mode 100644
index 0000000..7c4037f
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorSelectWord-after.txt
@@ -0,0 +1,3 @@
+<selection>s<caret>ome</selection> <selection>t<caret>ext</selection>
+<selection>s<caret>ome</selection> other
+<selection>another li<caret>ne</selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorSelectWord-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorSelectWord-before.txt
new file mode 100644
index 0000000..40b750e
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorSelectWord-before.txt
@@ -0,0 +1,3 @@
+s<caret>ome t<caret>e<caret>xt
+s<selection><caret>o</selection>me other
+another <selection>li<caret>ne</selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLine-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLine-after.txt
new file mode 100644
index 0000000..8c6a029
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLine-after.txt
@@ -0,0 +1,7 @@
+some text
+<caret>
+<caret>
+another text
+<caret>
+some longer line here
+<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLine-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLine-before.txt
new file mode 100644
index 0000000..5276b16
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLine-before.txt
@@ -0,0 +1,3 @@
+som<caret>e te<caret>xt
+an<selection><caret>ot</selection>her text
+some longer line <selection>h<caret>ere</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLineBefore-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLineBefore-after.txt
new file mode 100644
index 0000000..62140cb
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLineBefore-after.txt
@@ -0,0 +1,7 @@
+<caret>
+<caret>
+some text
+<caret>
+another text
+<caret>
+some longer line here
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLineBefore-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLineBefore-before.txt
new file mode 100644
index 0000000..5276b16
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorStartNewLineBefore-before.txt
@@ -0,0 +1,3 @@
+som<caret>e te<caret>xt
+an<selection><caret>ot</selection>her text
+some longer line <selection>h<caret>ere</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorSwapSelectionBoundaries-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorSwapSelectionBoundaries-after.txt
new file mode 100644
index 0000000..b51f7dd
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorSwapSelectionBoundaries-after.txt
@@ -0,0 +1,2 @@
+s<caret>ome <selection>text<caret></selection>
+some <selection><caret>other</selection> <selection><caret>t</selection>ext
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorSwapSelectionBoundaries-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorSwapSelectionBoundaries-before.txt
new file mode 100644
index 0000000..add7166
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorSwapSelectionBoundaries-before.txt
@@ -0,0 +1,2 @@
+s<caret>ome <selection><caret>text</selection>
+some <selection>other<caret></selection> <selection>t<caret>ext</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTab-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTab-after.txt
new file mode 100644
index 0000000..567853f
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTab-after.txt
@@ -0,0 +1,2 @@
+so <caret>me t <caret>t
+ <caret> <caret> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTab-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTab-before.txt
new file mode 100644
index 0000000..dd8da64
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTab-before.txt
@@ -0,0 +1,2 @@
+so<caret>me t<selection><caret>ex</selection>t
+<selection>some<caret></selection> <selection>ot<caret>her</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextEnd-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextEnd-after.txt
new file mode 100644
index 0000000..d1d4d2a
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextEnd-after.txt
@@ -0,0 +1,2 @@
+some text
+some other text<caret>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextEnd-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextEnd-before.txt
new file mode 100644
index 0000000..20c0039
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextEnd-before.txt
@@ -0,0 +1,2 @@
+some <caret>text
+some <selection><caret>other</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextEndWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextEndWithSelection-after.txt
new file mode 100644
index 0000000..ca33935
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextEndWithSelection-after.txt
@@ -0,0 +1,2 @@
+some text<selection>
+some other text<caret></selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextEndWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextEndWithSelection-before.txt
new file mode 100644
index 0000000..1861168
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextEndWithSelection-before.txt
@@ -0,0 +1,2 @@
+some <selection><caret>text</selection>
+some <selection><caret>other</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextStart-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextStart-after.txt
new file mode 100644
index 0000000..4449625
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextStart-after.txt
@@ -0,0 +1,2 @@
+<caret>some text
+some other text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextStart-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextStart-before.txt
new file mode 100644
index 0000000..20c0039
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextStart-before.txt
@@ -0,0 +1,2 @@
+some <caret>text
+some <selection><caret>other</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextStartWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextStartWithSelection-after.txt
new file mode 100644
index 0000000..962e634
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextStartWithSelection-after.txt
@@ -0,0 +1,2 @@
+<selection><caret>some text
+some other</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorTextStartWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorTextStartWithSelection-before.txt
new file mode 100644
index 0000000..20c0039
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorTextStartWithSelection-before.txt
@@ -0,0 +1,2 @@
+some <caret>text
+some <selection><caret>other</selection> text
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorToggleCase-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorToggleCase-after.txt
new file mode 100644
index 0000000..7718a92
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorToggleCase-after.txt
@@ -0,0 +1,2 @@
+<selection><caret>SOME</selection> <selection>t<caret>ext</selection>
+<selection><caret>some</selection> <selection>other<caret> t</selection>ext
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorToggleCase-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorToggleCase-before.txt
new file mode 100644
index 0000000..cbce286
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorToggleCase-before.txt
@@ -0,0 +1,2 @@
+<caret>some t<caret>e<caret>xt
+<selection><caret>SOME</selection> <selection>oThEr<caret> t</selection>ext
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUnSelectWord-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUnSelectWord-after.txt
new file mode 100644
index 0000000..b587219
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUnSelectWord-after.txt
@@ -0,0 +1,3 @@
+some <caret>text
+some other <selection>text<caret></selection>
+<selection>an<caret>other</selection> line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUnSelectWord-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUnSelectWord-before.txt
new file mode 100644
index 0000000..055d696
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUnSelectWord-before.txt
@@ -0,0 +1,3 @@
+some <selection><caret>text</selection>
+some <selection>other text<caret></selection>
+<selection>an<caret>other line</selection>
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUnindentSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUnindentSelection-after.txt
new file mode 100644
index 0000000..1561b39
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUnindentSelection-after.txt
@@ -0,0 +1,4 @@
+<selection><caret>some text
+ another line</selection>
+ <selection>some other text<caret></selection>
+ yet ano<caret>ther line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUnindentSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUnindentSelection-before.txt
new file mode 100644
index 0000000..d9dc944
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUnindentSelection-before.txt
@@ -0,0 +1,4 @@
+<selection><caret> some text
+ another line</selection>
+ <selection>some other text<caret></selection>
+ yet ano<caret>ther line
\ No newline at end of file
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUp-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUp-after.txt
new file mode 100644
index 0000000..87936c9
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUp-after.txt
@@ -0,0 +1,3 @@
+<caret>some text<caret>
+some <caret>other text
+yet another line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUp-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUp-before.txt
new file mode 100644
index 0000000..51d3f48
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUp-before.txt
@@ -0,0 +1,3 @@
+some<caret> text
+some other te<caret>x<caret>t
+yet a<selection><caret>no</selection>ther line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUpWithSelection-after.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUpWithSelection-after.txt
new file mode 100644
index 0000000..d294eae
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUpWithSelection-after.txt
@@ -0,0 +1,4 @@
+<selection><caret>some</selection> text<selection><caret>
+some other te</selection>xt
+blah <selection><caret>blah
+yet ano</selection>ther line
diff --git a/platform/platform-tests/testData/editor/multiCaret/EditorUpWithSelection-before.txt b/platform/platform-tests/testData/editor/multiCaret/EditorUpWithSelection-before.txt
new file mode 100644
index 0000000..bad29db
--- /dev/null
+++ b/platform/platform-tests/testData/editor/multiCaret/EditorUpWithSelection-before.txt
@@ -0,0 +1,4 @@
+some<caret> text
+some other t<caret>e<selection>x<caret></selection>t
+blah blah
+yet a<selection><caret>no</selection>ther line
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after1.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after1.cs
new file mode 100644
index 0000000..359af75
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after1.cs
@@ -0,0 +1,3 @@
+if (true) {
+ x = foo[bar(<selection>xyzzy</selection> + fizzy)];
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after2.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after2.cs
new file mode 100644
index 0000000..ec957fb
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after2.cs
@@ -0,0 +1,3 @@
+if (true) {
+ x = foo[bar(<selection>xyzzy + fizzy</selection>)];
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after3.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after3.cs
new file mode 100644
index 0000000..4f6eb29
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after3.cs
@@ -0,0 +1,3 @@
+if (true) {
+ x = foo[bar<selection>(xyzzy + fizzy)</selection>];
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after4.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after4.cs
new file mode 100644
index 0000000..6357e59
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after4.cs
@@ -0,0 +1,3 @@
+if (true) {
+ x = foo[<selection>bar(xyzzy + fizzy)</selection>];
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after5.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after5.cs
new file mode 100644
index 0000000..414d4e1
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after5.cs
@@ -0,0 +1,3 @@
+if (true) {
+ x = foo<selection>[bar(xyzzy + fizzy)]</selection>;
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after6.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after6.cs
new file mode 100644
index 0000000..054e064
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after6.cs
@@ -0,0 +1,3 @@
+if (true) {
+ <selection>x = foo[bar(xyzzy + fizzy)];</selection>
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after7.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after7.cs
new file mode 100644
index 0000000..a1a1e9e
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after7.cs
@@ -0,0 +1,3 @@
+if (true) {
+<selection> x = foo[bar(xyzzy + fizzy)];</selection>
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/after8.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after8.cs
new file mode 100644
index 0000000..ba5a733
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/after8.cs
@@ -0,0 +1,3 @@
+if (true) {
+<selection> x = foo[bar(xyzzy + fizzy)];
+</selection>}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeBraces/before.cs b/platform/platform-tests/testData/selectWord/customFileTypeBraces/before.cs
new file mode 100644
index 0000000..d45787f
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeBraces/before.cs
@@ -0,0 +1,3 @@
+if (true) {
+ x = foo[bar(xy<caret>zzy + fizzy)];
+}
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after1.cs b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after1.cs
new file mode 100644
index 0000000..ca1383e
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after1.cs
@@ -0,0 +1 @@
+"foo" + "<selection>ba<caret>r</selection> goo"
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after2.cs b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after2.cs
new file mode 100644
index 0000000..feb4449
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after2.cs
@@ -0,0 +1 @@
+"foo" + "<selection>ba<caret>r goo</selection>"
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after3.cs b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after3.cs
new file mode 100644
index 0000000..b3357ba
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after3.cs
@@ -0,0 +1 @@
+"foo" + <selection>"ba<caret>r goo"</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after4.cs b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after4.cs
new file mode 100644
index 0000000..b062e25
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/after4.cs
@@ -0,0 +1 @@
+<selection>"foo" + "ba<caret>r goo"</selection>
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeQuotes/before.cs b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/before.cs
new file mode 100644
index 0000000..5bd7088
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeQuotes/before.cs
@@ -0,0 +1 @@
+"foo" + "ba<caret>r goo"
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/after1.cs b/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/after1.cs
new file mode 100644
index 0000000..96bd024
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/after1.cs
@@ -0,0 +1 @@
+if (!<selection>gets_s</selection>(buffer, sizeof(buffer)-1))
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/after2.cs b/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/after2.cs
new file mode 100644
index 0000000..5602c0f
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/after2.cs
@@ -0,0 +1 @@
+if (<selection>!gets_s(buffer, sizeof(buffer)-1)</selection>)
\ No newline at end of file
diff --git a/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/before.cs b/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/before.cs
new file mode 100644
index 0000000..a21f832
--- /dev/null
+++ b/platform/platform-tests/testData/selectWord/customFileTypeSkipMatchedPair/before.cs
@@ -0,0 +1 @@
+if (!gets<caret>_s(buffer, sizeof(buffer)-1))
\ No newline at end of file
diff --git a/platform/platform-tests/testSrc/com/intellij/application/BadPluginTest.java b/platform/platform-tests/testSrc/com/intellij/application/BadPluginTest.java
index 9a4463c..8c2c7f3 100644
--- a/platform/platform-tests/testSrc/com/intellij/application/BadPluginTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/application/BadPluginTest.java
@@ -2,6 +2,7 @@
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.util.io.FileUtil;
@@ -24,7 +25,7 @@
IdeaPluginDescriptor plugin = PluginManager.getPlugin(PluginId.getId(COM_YOURCOMPANY_UNIQUE_PLUGIN_ID));
if (plugin == null) return;
List<String> disabledPlugins = new ArrayList<String>();
- PluginManager.loadDisabledPlugins(PathManager.getConfigPath(), disabledPlugins);
+ PluginManagerCore.loadDisabledPlugins(PathManager.getConfigPath(), disabledPlugins);
assertEquals(1, disabledPlugins.size());
assertEquals(COM_YOURCOMPANY_UNIQUE_PLUGIN_ID, disabledPlugins.get(0));
}
diff --git a/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java b/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java
index cf8f1c0..997f64b 100644
--- a/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/diff/SelectedBlockHistoryTest.java
@@ -194,13 +194,13 @@
}
- private void doTest(
- String[] beforePrevBlock,
- String[] prevBlock,
- String[] afterPrevBlock,
- String[] beforeBlock,
- String[] block,
- String[] afterBlock) throws FilesTooBigForDiffException {
+ private static void doTest(
+ String[] beforePrevBlock,
+ String[] prevBlock,
+ String[] afterPrevBlock,
+ String[] beforeBlock,
+ String[] block,
+ String[] afterBlock) throws FilesTooBigForDiffException {
String[] prevVersion = composeVersion(beforePrevBlock, prevBlock, afterPrevBlock);
String[] currentVersion = composeVersion(beforeBlock, block, afterBlock);
@@ -214,12 +214,11 @@
}
- private String[] composeVersion(String[] beforeBlock, String[] block, String[] afterBlock) {
- List beforeList = new ArrayList();
+ private static String[] composeVersion(String[] beforeBlock, String[] block, String[] afterBlock) {
+ List<String> beforeList = new ArrayList<String>();
ContainerUtil.addAll(beforeList, beforeBlock);
ContainerUtil.addAll(beforeList, block);
ContainerUtil.addAll(beforeList, afterBlock);
- return (String[])ArrayUtil.toStringArray(beforeList);
-
+ return ArrayUtil.toStringArray(beforeList);
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/formatting/TestFormattingModel.java b/platform/platform-tests/testSrc/com/intellij/formatting/TestFormattingModel.java
index 319a492..877709f 100644
--- a/platform/platform-tests/testSrc/com/intellij/formatting/TestFormattingModel.java
+++ b/platform/platform-tests/testSrc/com/intellij/formatting/TestFormattingModel.java
@@ -1,7 +1,23 @@
+/*
+ * 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.formatting;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.openapi.util.TextRange;
@@ -49,7 +65,7 @@
final String whiteSpace
) {
if (ApplicationManager.getApplication() != null) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
myDocument.replaceString(textRange.getStartOffset(), textRange.getEndOffset(), whiteSpace);
diff --git a/platform/platform-tests/testSrc/com/intellij/history/core/LocalHistoryTestCase.java b/platform/platform-tests/testSrc/com/intellij/history/core/LocalHistoryTestCase.java
index dab5afc..2fe04ea 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/core/LocalHistoryTestCase.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/core/LocalHistoryTestCase.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.
diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/ActionsTest.java b/platform/platform-tests/testSrc/com/intellij/history/integration/ActionsTest.java
index 3b196ce..6d552ae 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/integration/ActionsTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/integration/ActionsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -13,15 +13,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.history.integration;
-
import com.intellij.history.LocalHistory;
import com.intellij.history.LocalHistoryAction;
import com.intellij.history.core.revisions.Revision;
import com.intellij.history.utils.RunnableAdapter;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.VirtualFile;
@@ -31,11 +30,12 @@
public class ActionsTest extends IntegrationTestCase {
public void testSavingDocumentBeforeAndAfterAction() throws Exception {
VirtualFile f = createFile("f.txt", "file1");
+
setContent(f, "file2");
setDocumentTextFor(f, "doc1");
- LocalHistoryAction a = LocalHistory.getInstance().startAction("name");
+ LocalHistoryAction a = LocalHistory.getInstance().startAction("name");
setDocumentTextFor(f, "doc2");
a.finish();
@@ -48,10 +48,12 @@
assertContent("file1", rr.get(3).findEntry());
}
+ /**
+ * <strong>This is very important test.</strong>
+ * Almost all actions are performed inside surrounding command.
+ * Therefore we have to correctly handle such situations.
+ */
public void testActionInsideCommand() throws Exception {
- // This is very important test. Mostly all actions are performed
- // inside surrounding command. Therefore we have to correctly
- // handle such situation.
final VirtualFile f = createFile("f.txt");
setContent(f, "file");
setDocumentTextFor(f, "doc1");
@@ -104,8 +106,10 @@
assertNull(rr.get(2).getChangeSetName());
}
- private void saveDocument(VirtualFile f) {
+ private static void saveDocument(VirtualFile f) {
FileDocumentManager dm = FileDocumentManager.getInstance();
- dm.saveDocument(dm.getDocument(f));
+ Document document = dm.getDocument(f);
+ assertNotNull(f.getPath(), document);
+ dm.saveDocument(document);
}
}
\ No newline at end of file
diff --git a/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java b/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java
index bca4cc9..83836c1 100644
--- a/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java
+++ b/platform/platform-tests/testSrc/com/intellij/history/integration/IntegrationTestCase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.history.integration;
import com.intellij.history.core.LocalHistoryFacade;
@@ -24,6 +23,7 @@
import com.intellij.history.core.tree.RootEntry;
import com.intellij.history.utils.RunnableAdapter;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ContentEntry;
@@ -43,7 +43,7 @@
import java.util.List;
public abstract class IntegrationTestCase extends PlatformTestCase {
- public static final int TIMESTAMP_INCREMENT = 3000;
+ protected static final int TIMESTAMP_INCREMENT = 3000;
protected static final String FILTERED_DIR_NAME = "CVS";
protected VirtualFile myRoot;
@@ -93,12 +93,16 @@
@NotNull
protected VirtualFile createFile(String name, String content) throws IOException {
- return LocalFileSystem.getInstance().refreshAndFindFileByPath(createFileExternally(name, content));
+ VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(createFileExternally(name, content));
+ assertNotNull(name, file);
+ return file;
}
@NotNull
protected VirtualFile createDirectory(String name) throws IOException {
- return LocalFileSystem.getInstance().refreshAndFindFileByPath(createDirectoryExternally(name));
+ VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(createDirectoryExternally(name));
+ assertNotNull(name, file);
+ return file;
}
protected void setContent(VirtualFile f, String content) throws IOException {
@@ -106,7 +110,7 @@
}
protected void setContent(VirtualFile f, String content, long timestamp) throws IOException {
- f.setBinaryContent(content.getBytes(), -1, timestamp);
+ f.setBinaryContent(content.getBytes("UTF-8"), -1, timestamp);
}
protected String createFileExternally(String name) throws IOException {
@@ -115,26 +119,28 @@
protected String createFileExternally(String name, String content) throws IOException {
File f = new File(myRoot.getPath(), name);
- f.getParentFile().mkdirs();
- f.createNewFile();
- if (content != null) FileUtil.writeToFile(f, content.getBytes());
+ assertTrue(f.getPath(), f.getParentFile().mkdirs() || f.getParentFile().isDirectory());
+ assertTrue(f.getPath(), f.createNewFile() || f.exists());
+ if (content != null) FileUtil.writeToFile(f, content.getBytes("UTF-8"));
return FileUtil.toSystemIndependentName(f.getPath());
}
protected String createDirectoryExternally(String name) throws IOException {
File f = new File(myRoot.getPath(), name);
- f.mkdirs();
+ assertTrue(f.getPath(), f.mkdirs() || f.isDirectory());
return FileUtil.toSystemIndependentName(f.getPath());
}
protected void setContentExternally(String path, String content) throws IOException {
File f = new File(path);
- FileUtil.writeToFile(f, content.getBytes());
- f.setLastModified(f.lastModified() + 2000);
+ FileUtil.writeToFile(f, content.getBytes("UTF-8"));
+ assertTrue(f.getPath(), f.setLastModified(f.lastModified() + 2000));
}
protected void setDocumentTextFor(VirtualFile f, String text) {
- FileDocumentManager.getInstance().getDocument(f).setText(text);
+ Document document = FileDocumentManager.getInstance().getDocument(f);
+ assertNotNull(f.getPath(), document);
+ document.setText(text);
}
protected LocalHistoryFacade getVcs() {
@@ -196,7 +202,6 @@
}
}
-
protected static void assertContent(String expected, Entry e) {
assertEquals(expected, new String(e.getContent().getBytes()));
}
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java b/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java
index 5f2f557..98d5d27 100644
--- a/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/ide/BinaryRequestHandlerTest.java
@@ -8,8 +8,8 @@
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
-import io.netty.channel.ChannelInboundHandler;
import io.netty.channel.ChannelInitializer;
import io.netty.util.CharsetUtil;
import org.jetbrains.annotations.NotNull;
@@ -31,7 +31,7 @@
protected void initChannel(Channel channel) throws Exception {
channel.pipeline().addLast(new Decoder() {
@Override
- protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+ protected void messageReceived(ChannelHandlerContext context, ByteBuf message) throws Exception {
int requiredLength = 4 + text.length();
ByteBuf buffer = getBufferIfSufficient(message, requiredLength, context);
if (buffer == null) {
@@ -87,7 +87,7 @@
}
@Override
- public ChannelInboundHandler getInboundHandler() {
+ public ChannelHandler getInboundHandler() {
return new MyDecoder();
}
@@ -100,7 +100,7 @@
}
@Override
- protected void channelRead0(ChannelHandlerContext context, ByteBuf message) throws Exception {
+ protected void messageReceived(ChannelHandlerContext context, ByteBuf message) throws Exception {
while (true) {
switch (state) {
case HEADER: {
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy b/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy
index a3b6294..0ac9a1e 100644
--- a/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy
+++ b/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeLexerTest.groovy
@@ -52,25 +52,29 @@
table.addKeyword1("then");
table.addKeyword2("return");
table.addKeyword1("length");
- table.addKeyword1("sysvar ");
return table;
}
public void testSpacesInsideKeywords() {
- doTest createGenericTable(), 'if length(variable)then return 1', '''\
+ def table = createGenericTable()
+ table.addKeyword1("sysvar ");
+ doTest table, 'if length(if_variable)then return 1 sysvar ', '''\
KEYWORD_1 ('if')
WHITESPACE (' ')
KEYWORD_1 ('length')
CHARACTER ('(')
-IDENTIFIER ('variable')
+IDENTIFIER ('if_variable')
CHARACTER (')')
KEYWORD_1 ('then')
WHITESPACE (' ')
KEYWORD_2 ('return')
WHITESPACE (' ')
NUMBER ('1')
+WHITESPACE (' ')
+KEYWORD_1 ('sysvar ')
+WHITESPACE (' ')
'''
}
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeWordSelectionTest.java b/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeWordSelectionTest.java
new file mode 100644
index 0000000..40f8fbf
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/ide/highlighter/custom/CustomFileTypeWordSelectionTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ide.highlighter.custom;
+
+import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+/**
+ * @author yole
+ */
+public class CustomFileTypeWordSelectionTest extends LightPlatformCodeInsightFixtureTestCase {
+ public CustomFileTypeWordSelectionTest() {
+ PlatformTestCase.initPlatformLangPrefix();
+ }
+
+ public void testCustomFileTypeBraces() {
+ doTest();
+ }
+
+ public void testCustomFileTypeQuotes() { doTest(); }
+
+ public void testCustomFileTypeSkipMatchedPair() {
+ doTest();
+ }
+
+ @Override
+ protected boolean isCommunity() {
+ return true;
+ }
+
+ @Override
+ protected String getBasePath() {
+ return "/platform/platform-tests/testData/selectWord/";
+ }
+
+ private void doTest() {
+ CodeInsightTestUtil.doWordSelectionTestOnDirectory(myFixture, getTestName(true), "cs");
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/ide/severities/HighlightSeveritiesTest.java b/platform/platform-tests/testSrc/com/intellij/ide/severities/HighlightSeveritiesTest.java
index 2e4f8b9..a34c0e7 100644
--- a/platform/platform-tests/testSrc/com/intellij/ide/severities/HighlightSeveritiesTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/ide/severities/HighlightSeveritiesTest.java
@@ -1,5 +1,17 @@
/*
- * Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
+ * 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.
*/
/*
@@ -15,28 +27,10 @@
import org.jdom.Element;
public class HighlightSeveritiesTest extends TestCase {
- private int myOldSeverity;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- myOldSeverity = HighlightSeverity.ERROR.myVal;
- }
-
-
- @Override
- protected void tearDown() throws Exception {
- HighlightSeverity.ERROR.myVal = myOldSeverity;
- super.tearDown();
- }
-
public void testSeveritiesMigration() throws Exception{
- HighlightSeverity.ERROR.myVal = 200;
final Element element = new Element("temp");
new HighlightSeverity(HighlightSeverity.ERROR.myName, 500).writeExternal(element);
- HighlightSeverity.ERROR.readExternal(element);
- assertEquals(500, HighlightSeverity.ERROR.myVal);
+ HighlightSeverity newSeverity = new HighlightSeverity(element);
+ assertEquals(500, newSeverity.myVal);
}
-
-
}
\ No newline at end of file
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/DocumentTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/DocumentTest.java
index 9c30573..ed5d01d 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/DocumentTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/DocumentTest.java
@@ -1,10 +1,28 @@
+/*
+ * 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.openapi.editor;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.impl.DocumentImpl;
import com.intellij.testFramework.LightPlatformTestCase;
+import com.intellij.util.IncorrectOperationException;
public class DocumentTest extends LightPlatformTestCase {
public void testCorrectlyAddingAndRemovingListeners() throws Exception {
@@ -56,4 +74,73 @@
}
}.execute().throwException();
}
+
+ public void testModificationInsideCommandAssertion() {
+ CommandProcessor commandProcessor = CommandProcessor.getInstance();
+ assertTrue(!commandProcessor.isUndoTransparentActionInProgress() &&
+ commandProcessor.getCurrentCommand() == null);
+
+ final Document doc = new DocumentImpl("xxx");
+
+ mustThrow(new Runnable(){
+ @Override
+ public void run() {
+ doc.insertString(1,"x");
+ }
+ });
+ mustThrow(new Runnable(){
+ @Override
+ public void run() {
+ doc.deleteString(1, 2);
+ }
+ });
+ mustThrow(new Runnable(){
+ @Override
+ public void run() {
+ doc.replaceString(1, 2, "s");
+ }
+ });
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ doc.insertString(1,"s");
+ }
+ });
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ doc.deleteString(1,2);
+ }
+ });
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ doc.replaceString(1,2,"xxx");
+ }
+ });
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ doc.setText("sss");
+ }
+ });
+
+ DocumentImpl console = new DocumentImpl("xxxx", true);
+ // need no stinking command
+ console.insertString(1,"s");
+ console.deleteString(1, 2);
+ console.replaceString(1, 2, "xxx");
+ console.setText("sss");
+
+
+ }
+
+ private static void mustThrow(Runnable runnable) {
+ try {
+ ApplicationManager.getApplication().runWriteAction(runnable);
+ fail("Must throw IncorrectOperationException");
+ }
+ catch (IncorrectOperationException e) {
+ }
+ }
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorModificationUtilTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorModificationUtilTest.java
new file mode 100644
index 0000000..8c1cee4
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorModificationUtilTest.java
@@ -0,0 +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.openapi.editor;
+
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+public class EditorModificationUtilTest extends LightPlatformCodeInsightTestCase {
+ public void testInsertStringAtCaretNotMovingCaret() throws Exception {
+ configureFromFileText(getTestName(false) + ".txt", "text <caret>");
+ EditorModificationUtil.insertStringAtCaret(myEditor, " ", false, false);
+ checkResultByText("text <caret> ");
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretStateRestoreTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretStateRestoreTest.java
new file mode 100644
index 0000000..d915753
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretStateRestoreTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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 com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.editor.impl.DocumentImpl;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.HeavyFileEditorManagerTestCase;
+import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.EditorTestUtil;
+import org.jetbrains.annotations.NotNull;
+
+public class EditorMultiCaretStateRestoreTest extends HeavyFileEditorManagerTestCase {
+ public void testRestoreState() throws Exception {
+ EditorTestUtil.enableMultipleCarets();
+ try {
+ String text = "some<caret> text<caret>\n" +
+ "some <selection><caret>other</selection> <selection>text<caret></selection>\n" +
+ "<selection>ano<caret>ther</selection> line";
+ PsiFile psiFile = myFixture.configureByText(PlainTextFileType.INSTANCE, text);
+ VirtualFile virtualFile = psiFile.getVirtualFile();
+ assertNotNull(virtualFile);
+ myManager.openFile(virtualFile, false);
+ myManager.closeAllFiles();
+ FileEditor[] fileEditors = myManager.openFile(virtualFile, false);
+ assertNotNull(fileEditors);
+ assertEquals(1, fileEditors.length);
+ Editor editor = ((TextEditor)fileEditors[0]).getEditor();
+
+ verifyEditorState(editor, text);
+ }
+ finally {
+ EditorTestUtil.disableMultipleCarets();
+ }
+ }
+
+ private static void verifyEditorState(Editor editor, String textWithMarkup) {
+ final Document document = new DocumentImpl(textWithMarkup);
+ EditorTestUtil.CaretsState caretAndSelectionState = new WriteCommandAction<EditorTestUtil.CaretsState>(null) {
+ @Override
+ protected void run(@NotNull Result<EditorTestUtil.CaretsState> result) throws Throwable {
+ result.setResult(EditorTestUtil.extractCaretAndSelectionMarkers(document));
+ }
+ }.execute().getResultObject();
+ assertEquals(document.getCharsSequence().toString(), editor.getDocument().getText());
+ EditorTestUtil.verifyCaretAndSelectionState(editor, caretAndSelectionState);
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java
new file mode 100644
index 0000000..7dc1784
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretTest.java
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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 com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.fileEditor.impl.EditorHistoryManager;
+import com.intellij.openapi.project.ex.ProjectManagerEx;
+import com.intellij.openapi.project.impl.ProjectManagerImpl;
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.TestFileType;
+import com.intellij.testFramework.fixtures.EditorScrollingFixture;
+
+public class EditorMultiCaretTest extends AbstractEditorTest {
+ private boolean myStoredVirtualSpaceSetting;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ EditorTestUtil.enableMultipleCarets();
+ myStoredVirtualSpaceSetting = EditorSettingsExternalizable.getInstance().isVirtualSpace();
+ EditorSettingsExternalizable.getInstance().setVirtualSpace(false);
+ }
+
+ public void tearDown() throws Exception {
+ EditorSettingsExternalizable.getInstance().setVirtualSpace(myStoredVirtualSpaceSetting);
+ EditorTestUtil.disableMultipleCarets();
+ super.tearDown();
+ }
+
+ public void testCaretAddingAndRemoval() throws Exception {
+ init("some <selection>t<caret>ext</selection>\n" +
+ "another line",
+ TestFileType.TEXT);
+
+ mouse().alt().shift().clickAt(1,1); // alt-shift-click in a 'free space'
+ checkResultByText("some <selection>t<caret>ext</selection>\n" +
+ "a<caret>nother line");
+
+ mouse().alt().shift().clickAt(0,8); // alt-shift-click in existing selection
+ checkResultByText("some <selection>t<caret>ext</selection>\n" +
+ "a<caret>nother line");
+
+ mouse().alt().shift().clickAt(0,6); // alt-shift-click at existing caret with selection
+ checkResultByText("some text\n" +
+ "a<caret>nother line");
+
+ mouse().alt().shift().clickAt(1,1); // alt-shift-click at the sole caret
+ checkResultByText("some text\n" +
+ "a<caret>nother line");
+
+ mouse().alt().shift().clickAt(0,30); // alt-shift-click in virtual space
+ checkResultByText("some text<caret>\n" +
+ "a<caret>nother line");
+
+ mouse().clickAt(0, 0); // plain mouse click
+ checkResultByText("<caret>some text\n" +
+ "another line");
+ }
+
+ public void testAltDragStartingFromWithinLine() throws Exception {
+ init("<caret>line\n" +
+ "long line\n" +
+ "very long line\n" +
+ "long line\n" +
+ "line",
+ TestFileType.TEXT);
+ EditorScrollingFixture.setVisibleSize(myEditor, 1000, 1000);
+
+ mouse().alt().pressAt(1, 6);
+ checkResultByText("line\n" +
+ "long l<caret>ine\n" +
+ "very long line\n" +
+ "long line\n" +
+ "line");
+
+ mouse().alt().dragTo(4, 6);
+ checkResultByText("line\n" +
+ "long l<caret>ine\n" +
+ "very l<caret>ong line\n" +
+ "long l<caret>ine\n" +
+ "line<caret>");
+
+ mouse().alt().dragTo(4, 8);
+ checkResultByText("line\n" +
+ "long l<selection>in<caret></selection>e\n" +
+ "very l<selection>on<caret></selection>g line\n" +
+ "long l<selection>in<caret></selection>e\n" +
+ "line");
+
+ mouse().alt().dragTo(4, 10).release();
+ checkResultByText("line\n" +
+ "long l<selection>ine<caret></selection>\n" +
+ "very l<selection>ong <caret></selection>line\n" +
+ "long l<selection>ine<caret></selection>\n" +
+ "line");
+ }
+
+ public void testMiddleButtonDragStartingFromVirtualSpace() throws Exception {
+ init("<caret>line\n" +
+ "long line\n" +
+ "very long line\n" +
+ "long line\n" +
+ "line",
+ TestFileType.TEXT);
+ EditorScrollingFixture.setVisibleSize(myEditor, 1000, 1000);
+
+ mouse().middle().pressAt(1, 17);
+ checkResultByText("line\n" +
+ "long line<caret>\n" +
+ "very long line\n" +
+ "long line\n" +
+ "line");
+
+ mouse().middle().dragTo(2, 16);
+ checkResultByText("line\n" +
+ "long line<caret>\n" +
+ "very long line<caret>\n" +
+ "long line\n" +
+ "line");
+
+ mouse().middle().dragTo(3, 12);
+ checkResultByText("line\n" +
+ "long line\n" +
+ "very long li<selection><caret>ne</selection>\n" +
+ "long line\n" +
+ "line");
+
+ mouse().middle().dragTo(3, 6).release();
+ checkResultByText("line\n" +
+ "long l<selection><caret>ine</selection>\n" +
+ "very l<selection><caret>ong line</selection>\n" +
+ "long l<selection><caret>ine</selection>\n" +
+ "line");
+ }
+
+ public void testTyping() 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);
+ type('A');
+ checkResultByText("someA<caret> textA<caret>\n" +
+ "some A<caret> A<caret>\n" +
+ "A<caret> line");
+ }
+
+ public void testCopyPaste() throws Exception {
+ init("<selection><caret>one</selection> two \n" +
+ "<selection><caret>three</selection> four ",
+ TestFileType.TEXT);
+ executeAction("EditorCopy");
+ executeAction("EditorLineEnd");
+ executeAction("EditorPaste");
+ checkResultByText("one twoone<caret> \n" +
+ "three fourthree<caret> ");
+ }
+
+ public void testCutAndPaste() throws Exception {
+ init("<selection>one<caret></selection> two \n" +
+ "<selection>three<caret></selection> four ",
+ TestFileType.TEXT);
+ executeAction("EditorCut");
+ executeAction("EditorLineEnd");
+ executeAction("EditorPaste");
+ checkResultByText(" twoone<caret> \n" +
+ " fourthree<caret> ");
+ }
+
+ public void testPasteSingleItem() throws Exception {
+ init("<selection>one<caret></selection> two \n" +
+ "three four ",
+ TestFileType.TEXT);
+ executeAction("EditorCopy");
+ executeAction("EditorCloneCaretBelow");
+ executeAction("EditorLineEnd");
+ executeAction("EditorPaste");
+ checkResultByText("one twoone<caret> \n" +
+ "three fourone<caret> ");
+ }
+
+ public void testCutAndPasteMultiline() throws Exception {
+ init("one <selection>two \n" +
+ "three<caret></selection> four \n" +
+ "five <selection>six \n" +
+ "seven<caret></selection> eight",
+ TestFileType.TEXT);
+ executeAction("EditorCut");
+ executeAction("EditorLineEnd");
+ executeAction("EditorPaste");
+ checkResultByText("one fourtwo \n" +
+ "three<caret> \n" +
+ "five eightsix \n" +
+ "seven<caret>");
+ }
+
+ public void testStateStoreAndLoad() 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);
+ EditorHistoryManager.getInstance(ourProject).projectOpened();
+ FileEditorManager fileEditorManager = FileEditorManager.getInstance(ourProject);
+ fileEditorManager.closeFile(myVFile);
+ myEditor = fileEditorManager.openTextEditor(new OpenFileDescriptor(getProject(), myVFile, 0), false);
+ checkResultByText("some<caret> text<caret>\n" +
+ "some <selection><caret>other</selection> <selection>text<caret></selection>\n" +
+ "<selection>ano<caret>ther</selection> line");
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java
new file mode 100644
index 0000000..8bafc3e
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/EditorMultiCaretUndoRedoTest.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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 com.intellij.openapi.application.Result;
+import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.command.CommandProcessor;
+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.EditorSettingsExternalizable;
+import com.intellij.openapi.editor.impl.AbstractEditorTest;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.TestFileType;
+import com.intellij.testFramework.fixtures.EditorScrollingFixture;
+import org.jetbrains.annotations.NotNull;
+
+public class EditorMultiCaretUndoRedoTest extends AbstractEditorTest {
+ private CurrentEditorProvider mySavedCurrentEditorProvider;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ EditorTestUtil.enableMultipleCarets();
+ mySavedCurrentEditorProvider = getUndoManager().getEditorProvider();
+ }
+
+ public void tearDown() throws Exception {
+ getUndoManager().setEditorProvider(mySavedCurrentEditorProvider);
+ EditorTestUtil.disableMultipleCarets();
+ super.tearDown();
+ }
+
+ @Override
+ // disabling execution of tests in command
+ protected void runTest() throws Throwable {
+ new WriteAction<Void>() {
+ @Override
+ protected void run(@NotNull Result<Void> result) throws Throwable {
+ doRunTest();
+ }
+ }.execute();
+ }
+
+ 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();
+ type('A');
+ executeAction("EditorDelete");
+ mouse().clickAt(0, 1);
+ undo();
+ checkResult("someA<caret>textA<caret>some A<caret>A<caret>A<caret>line");
+ undo();
+ checkResult("someA<caret> textA<caret>\n" +
+ "some A<caret> A<caret>\n" +
+ "A<caret> line");
+ undo();
+ checkResult("some<caret> text<caret>\n" +
+ "some <selection><caret>other</selection> <selection>text<caret></selection>\n" +
+ "<selection>ano<caret>ther</selection> line");
+ redo();
+ checkResult("someA<caret> textA<caret>\n" +
+ "some A<caret> A<caret>\n" +
+ "A<caret> line");
+ }
+
+ private void checkResult(final String text) {
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ @Override
+ public void run() {
+ checkResultByText(text);
+ }
+ });
+ }
+
+ private static void undo() {
+ getUndoManager().undo(getTextEditor());
+ }
+
+ private static void redo() {
+ getUndoManager().redo(getTextEditor());
+ }
+
+ private static UndoManagerImpl getUndoManager() {
+ return (UndoManagerImpl) UndoManager.getInstance(ourProject);
+ }
+
+ private static TextEditor getTextEditor() {
+ return TextEditorProvider.getInstance().getTextEditor(myEditor);
+ }
+
+ private static void setupEditorProvider() {
+ getUndoManager().setEditorProvider(new CurrentEditorProvider() {
+ @Override
+ public FileEditor getCurrentEditor() {
+ return getTextEditor();
+ }
+ });
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java
index b65b377..66384b9 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/StripTrailingSpacesTest.java
@@ -1,7 +1,23 @@
+/*
+ * 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.openapi.editor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -45,7 +61,7 @@
}
private static void stripTrailingSpaces() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
TrailingSpacesStripper.stripIfNotCurrentLine(getEditor().getDocument(), true);
@@ -155,4 +171,25 @@
FileDocumentManager.getInstance().saveAllDocuments();
checkResultByText(" xxx <caret>\nyyy\n\t\t\t\n");
}
-}
+
+ public void testOverrideStripTrailingSpaces() throws IOException {
+ EditorSettingsExternalizable settings = EditorSettingsExternalizable.getInstance();
+ settings.setStripTrailingSpaces(EditorSettingsExternalizable.STRIP_TRAILING_SPACES_NONE);
+ configureFromFileText("x.txt", "xxx<caret>\n 222 \nyyy");
+ myVFile.putUserData(TrailingSpacesStripper.OVERRIDE_STRIP_TRAILING_SPACES_KEY,
+ EditorSettingsExternalizable.STRIP_TRAILING_SPACES_WHOLE);
+ type(' ');
+ FileDocumentManager.getInstance().saveAllDocuments();
+ checkResultByText("xxx <caret>\n 222\nyyy");
+ }
+
+ public void testOverrideEnsureNewline() throws IOException {
+ EditorSettingsExternalizable settings = EditorSettingsExternalizable.getInstance();
+ settings.setEnsureNewLineAtEOF(false);
+ configureFromFileText("x.txt", "XXX<caret>\nYYY");
+ myVFile.putUserData(TrailingSpacesStripper.OVERRIDE_ENSURE_NEWLINE_KEY, Boolean.TRUE);
+ type(' ');
+ FileDocumentManager.getInstance().saveAllDocuments();
+ checkResultByText("XXX <caret>\nYYY\n");
+ }
+}
\ No newline at end of file
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/CopyActionSimpleHandlerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/CopyActionSimpleHandlerTest.java
new file mode 100644
index 0000000..3960e14
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/CopyActionSimpleHandlerTest.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.openapi.editor.actions;
+
+import com.intellij.codeInsight.CodeInsightSettings;
+
+public class CopyActionSimpleHandlerTest extends CopyActionTest {
+ private int myPrevValue;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myPrevValue = CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE;
+ CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE = CodeInsightSettings.NO;
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ CodeInsightSettings.getInstance().ADD_IMPORTS_ON_PASTE = myPrevValue;
+ super.tearDown();
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/CopyActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/CopyActionTest.java
new file mode 100644
index 0000000..254437d
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/CopyActionTest.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.openapi.editor.actions;
+
+import com.intellij.openapi.ide.CopyPasteManager;
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+import java.awt.datatransfer.DataFlavor;
+import java.io.IOException;
+
+public class CopyActionTest extends LightPlatformCodeInsightTestCase {
+ public void testCopyWithoutSelection() throws Exception {
+ prepare("first line\n" +
+ "second<caret> line\n" +
+ "third line");
+ copy();
+ verifyResult("first line\n" +
+ "<caret><selection>second line\n" +
+ "</selection>third line",
+ "second line\n"
+ );
+ }
+
+ public void testCopyWithoutSelectionWithSoftWraps() throws Exception {
+ prepare("first line\n" +
+ "second line<caret>\n" + // this line will be wrapped and caret is positioned after the wrap
+ "third line");
+ assertTrue("Failed to activate soft wrapping", EditorTestUtil.configureSoftWraps(myEditor, 6));
+ copy();
+ verifyResult("first line\n" +
+ "<caret><selection>second line\n" +
+ "</selection>third line",
+ "second line\n"
+ );
+ }
+
+ private void prepare(String documentContents) throws IOException {
+ configureFromFileText(getTestName(false) + ".txt", documentContents);
+ }
+
+ private void verifyResult(String expectedDocumentContents, String expectedClipboardContents) {
+ checkResultByText(expectedDocumentContents);
+ assertEquals("Clipboard contents mismatch",
+ expectedClipboardContents,
+ CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor));
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorMultiCaretActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorMultiCaretActionTest.java
new file mode 100644
index 0000000..2ac32da
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/EditorMultiCaretActionTest.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.editor.actions;
+
+import com.intellij.openapi.application.Result;
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.FileBasedTestCaseHelper;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+import com.intellij.testFramework.TestDataPath;
+import com.intellij.testFramework.fixtures.EditorScrollingFixture;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SuppressWarnings("JUnit4AnnotatedMethodInJUnit3TestCase")
+@RunWith(com.intellij.testFramework.Parameterized.class)
+@TestDataPath("/testData/../../../platform/platform-tests/testData/editor/multiCaret/")
+public class EditorMultiCaretActionTest extends LightPlatformCodeInsightTestCase implements FileBasedTestCaseHelper {
+ @BeforeClass
+ public static void enableMultipleCarets() {
+ EditorTestUtil.enableMultipleCarets();
+ }
+
+ @AfterClass
+ public static void disableMultipleCarets() {
+ EditorTestUtil.disableMultipleCarets();
+ }
+
+ @Test
+ public void testAction() {
+ new WriteCommandAction<Void>(null) {
+ @Override
+ protected void run(@NotNull Result<Void> result) throws Throwable {
+ configureByFile(getBeforeFileName());
+ EditorScrollingFixture.setVisibleSize(myEditor, 120, 20); // some actions require visible area to be defined, like EditorPageUp
+ executeAction(getActionName());
+ checkResultByFile(getAfterFileName());
+ }
+ }.execute();
+ }
+
+ @Nullable
+ @Override
+ public String getFileSuffix(String fileName) {
+ int pos = fileName.indexOf("-before.");
+ if (pos < 0) {
+ return null;
+ }
+ return pos < 0 ? null : fileName.substring(0, pos) + '(' + fileName.substring(pos + 8) + ')';
+ }
+
+ private String getBeforeFileName() {
+ int pos = myFileSuffix.indexOf('(');
+ return myFileSuffix.substring(0, pos) + "-before." + myFileSuffix.substring(pos + 1, myFileSuffix.length() - 1);
+ }
+
+ private String getAfterFileName() {
+ int pos = myFileSuffix.indexOf('(');
+ return myFileSuffix.substring(0, pos) + "-after." + myFileSuffix.substring(pos + 1, myFileSuffix.length() - 1);
+ }
+
+ private String getActionName() {
+ return myFileSuffix.split("[-(]")[0];
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/IndentSelectionActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/IndentSelectionActionTest.java
new file mode 100644
index 0000000..55dd0ea
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/IndentSelectionActionTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.openapi.editor.actions;
+
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+public class IndentSelectionActionTest extends LightPlatformCodeInsightFixtureTestCase {
+
+ public void testWithoutSelection() throws Exception {
+ verifyAction("some text",
+ null);
+ }
+
+ public void testWithInlineSelection() throws Exception {
+ verifyAction("some <selection>text</selection>",
+ null);
+ }
+
+ public void testWithLineSelection() throws Exception {
+ verifyAction("<selection>some text</selection>",
+ " <selection>some text</selection>");
+ }
+
+ public void testWithLineSelectionExcludingSpaces() throws Exception {
+ verifyAction(" <selection>some text</selection>",
+ " <selection>some text</selection>");
+ }
+
+ private void verifyAction(String input, String expectedResult) {
+ myFixture.configureByText(getTestName(false) + ".txt", input);
+ IndentSelectionAction action = new IndentSelectionAction();
+ assertEquals(expectedResult != null, myFixture.testAction(action).isEnabled());
+ if (expectedResult != null) {
+ myFixture.checkResult(expectedResult);
+ }
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRegionActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRegionActionTest.java
index 818257c..2c05207 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRegionActionTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRegionActionTest.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.
@@ -20,7 +20,6 @@
import org.jetbrains.annotations.NotNull;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
/**
* @author Denis Zhdanov
@@ -33,11 +32,10 @@
Pair<String,String> parseResult = parse();
killRegion();
if (parseResult.first != null) {
- Transferable contents = CopyPasteManager.getInstance().getContents();
- assertNotNull(contents);
- assertEquals(parseResult.first, contents.getTransferData(DataFlavor.stringFlavor));
+ String contents = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
+ assertEquals(parseResult.first, contents);
}
-
+
assertEquals(parseResult.second, myEditor.getDocument().getText());
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRingSaveActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRingSaveActionTest.java
index 21c9e78..f436175 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRingSaveActionTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillRingSaveActionTest.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.
@@ -20,7 +20,6 @@
import org.jetbrains.annotations.NotNull;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
/**
* @author Denis Zhdanov
@@ -37,9 +36,8 @@
return;
}
- Transferable contents = CopyPasteManager.getInstance().getContents();
- assertNotNull(contents);
- assertEquals(parseResult.first, contents.getTransferData(DataFlavor.stringFlavor));
+ String contents = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
+ assertEquals(parseResult.first, contents);
assertEquals(textBefore, myEditor.getDocument().getText());
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillToWordEndActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillToWordEndActionTest.java
index 31b8aaa..9373480 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillToWordEndActionTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/KillToWordEndActionTest.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.
@@ -15,13 +15,20 @@
*/
package com.intellij.openapi.editor.actions;
+import com.intellij.openapi.editor.*;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.impl.CaretModelImpl;
+import com.intellij.openapi.editor.impl.EditorImpl;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.ide.CopyPasteManager;
import com.intellij.openapi.ide.KillRingTransferable;
+import com.intellij.openapi.util.Disposer;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import org.jetbrains.annotations.NotNull;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
/**
@@ -36,7 +43,7 @@
"this is a <caret>"
);
}
-
+
public void testInTheMiddle() throws IOException {
doTest(
"th<caret>is is a string",
@@ -79,7 +86,7 @@
"this is a string<caret>"
);
}
-
+
public void testAtWhiteSpaceAtLineEnd() throws IOException {
doTest(
"this is the first string <caret> \n" +
@@ -87,7 +94,7 @@
"this is the first string <caret>this is the second string"
);
}
-
+
private void doTest(@NotNull String before, @NotNull String after) throws IOException {
configureFromFileText(getTestName(false) + ".txt", before);
killToWordEnd();
@@ -99,13 +106,11 @@
configureFromFileText(getTestName(false) + ".txt", text);
killToWordEnd();
checkResultByText(" second third");
-
+
getEditor().getCaretModel().moveCaretRelatively(1, 0, false, false, false);
getEditor().getCaretModel().moveCaretRelatively(-1, 0, false, false, false);
killToWordEnd();
- Transferable contents = CopyPasteManager.getInstance().getContents();
- assertTrue(contents instanceof KillRingTransferable);
- Object string = contents.getTransferData(DataFlavor.stringFlavor);
+ Object string = getContents();
assertEquals(" second", string);
}
@@ -116,9 +121,201 @@
killToWordEnd();
checkResultByText(" third");
+ Object string = getContents();
+ assertEquals("first second", string);
+ }
+
+ public void testSubsequentKillsInterruptedBySave() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ cutToLineEnd();
+ final FileDocumentManager manager = FileDocumentManager.getInstance();
+ manager.saveAllDocuments();
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " public Insets getBorderInsets( }");
+
+ Object string = getContents();
+ assertEquals("Component c) {\n }\n", string);
+ }
+
+ public void testSubsequentKillsWithFolding() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ final FoldingModel model = myEditor.getFoldingModel();
+ model.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ final FoldRegion foldRegion = model.addFoldRegion(70, 90, "");
+ assertNotNull(foldRegion);
+ foldRegion.setExpanded(false);
+ assertFalse(foldRegion.isExpanded());
+ }
+ });
+
+ cutToLineEnd();
+ cutToLineEnd();
+ model.runBatchFoldingOperationDoNotCollapseCaret(new Runnable() {
+ @Override
+ public void run() {
+ final FoldRegion[] regions = model.getAllFoldRegions();
+ for (FoldRegion region : regions) {
+ assertNotNull(region);
+ region.setExpanded(true);
+ }
+
+ }
+ });
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " public Insets getBorderInsets( }");
+
+ Object string = getContents();
+ assertEquals("Component c) {\n }\n", string);
+ }
+
+ public void testDoubleEditors() throws Exception {
+ String text = "<caret>first second third";
+ configureFromFileText(getTestName(false) + ".txt", text);
+ final Document document = myEditor.getDocument();
+ EditorFactory editorFactory = EditorFactory.getInstance();
+ Editor otherEditor = editorFactory.createEditor(document, ourProject);
+ try {
+ otherEditor.getCaretModel().moveToOffset(document.getTextLength() - 1);
+ killToWordEnd();
+ killToWordEnd();
+ checkResultByText(" third");
+
+ Object string = getContents();
+ assertEquals("first second", string);
+ }
+ finally {
+ editorFactory.releaseEditor(otherEditor);
+ }
+ }
+
+
+ public void testKillsInterruptedByDelete() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ deleteLine();
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " }");
+
+ Object string = getContents();
+ assertEquals("\n" +
+ " }", string);
+ }
+
+ public void testKillsInterruptedByDeleteLine() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ deleteLine();
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " }");
+
+ Object string = getContents();
+ assertEquals("\n" +
+ " }", string);
+ }
+
+ public void testKillsInterruptedByDeleteLineEnd() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ executeAction("EditorDeleteToLineEnd");
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " public Insets getBorderInsets( }");
+
+ Object string = getContents();
+ assertEquals(" }\n", string);
+ }
+
+ public void testKillsInterruptedByDeleteWord() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ executeAction("EditorDeleteToWordEnd");
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " public Insets getBorderInsets( }");
+
+ Object string = getContents();
+ assertEquals("}\n", string);
+ }
+
+ public void testKillsInterruptedBySplit() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ executeAction("EditorSplitLine");
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " public Insets getBorderInsets( }\n" +
+ " }");
+
+ Object string = getContents();
+ assertEquals("\n" +
+ " \n", string);
+ }
+
+ public void testKillsInterruptedByStartNewLine() throws Exception {
+ String text = "public class ParentCopy {\n" +
+ " public Insets getBorderInsets(<caret>Component c) {\n" +
+ " }\n" +
+ " }";
+ configureFromFileText(getTestName(false) + ".java", text);
+ cutToLineEnd();
+ executeAction("EditorStartNewLine");
+ cutToLineEnd();
+ cutToLineEnd();
+ checkResultByText("public class ParentCopy {\n" +
+ " public Insets getBorderInsets(\n" +
+ " \n" +
+ " }");
+
+ Object string = getContents();
+ assertEquals("\n" +
+ " }", string);
+ }
+
+ private static String getContents() throws UnsupportedFlavorException, IOException {
Transferable contents = CopyPasteManager.getInstance().getContents();
assertTrue(contents instanceof KillRingTransferable);
- Object string = contents.getTransferData(DataFlavor.stringFlavor);
- assertEquals("first second", string);
+ return (String)contents.getTransferData(DataFlavor.stringFlavor);
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/MultiCaretBlockSelectionTest.groovy b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/MultiCaretBlockSelectionTest.groovy
new file mode 100644
index 0000000..648bf43
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/MultiCaretBlockSelectionTest.groovy
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.testFramework.EditorTestUtil
+
+class MultiCaretBlockSelectionTest extends BlockSelectionTest {
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp()
+ EditorTestUtil.enableMultipleCarets()
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ EditorTestUtil.disableMultipleCarets()
+ super.tearDown()
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectLineActionTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectLineActionTest.java
new file mode 100644
index 0000000..6ee9d7c
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/actions/SelectLineActionTest.java
@@ -0,0 +1,50 @@
+/*
+ * 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.openapi.editor.actions;
+
+import com.intellij.testFramework.EditorTestUtil;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+import java.io.IOException;
+
+public class SelectLineActionTest extends LightPlatformCodeInsightTestCase {
+ public void test() throws Exception {
+ prepare("first line\n" +
+ "second<caret> line\n" +
+ "third line");
+ selectLine();
+ checkResultByText("first line\n" +
+ "<caret><selection>second line\n" +
+ "</selection>third line"
+ );
+ }
+
+ public void testWithSoftWraps() throws Exception {
+ prepare("first line\n" +
+ "second line<caret>\n" + // this line will be wrapped and caret is positioned after the wrap
+ "third line");
+ assertTrue("Failed to activate soft wrapping", EditorTestUtil.configureSoftWraps(myEditor, 6));
+ selectLine();
+ checkResultByText("first line\n" +
+ "<caret><selection>second line\n" +
+ "</selection>third line"
+ );
+ }
+
+ private void prepare(String documentContents) throws IOException {
+ configureFromFileText(getTestName(false) + ".txt", documentContents);
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java
new file mode 100644
index 0000000..755e9c6
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/FontPreferencesTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.openapi.editor.colors;
+
+
+import org.junit.Test;
+
+import java.awt.*;
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+public class FontPreferencesTest {
+ private final FontPreferences myPreferences = new FontPreferences();
+
+ @Test
+ public void testDefaults() {
+ checkState(Collections.<String>emptyList(),
+ Collections.<String>emptyList(),
+ FontPreferences.DEFAULT_FONT_NAME,
+ FontPreferences.DEFAULT_FONT_NAME, null);
+ }
+
+ @Test
+ public void testRegisterExistingFont() {
+ String fontName = getExistingNonDefaultFontName();
+ myPreferences.register(fontName, 25);
+ checkState(Arrays.asList(fontName),
+ Arrays.asList(fontName),
+ fontName,
+ fontName, 25);
+ }
+
+ @Test
+ public void testRegisterTwoExistingFonts() {
+ String fontName = getExistingNonDefaultFontName();
+ myPreferences.register(fontName, 25);
+ String fontName2 = getAnotherExistingNonDefaultFontName();
+ myPreferences.register(fontName2, 13);
+ checkState(Arrays.asList(fontName, fontName2),
+ Arrays.asList(fontName, fontName2),
+ fontName,
+ fontName, 25,
+ fontName2, 13);
+ }
+
+ @Test
+ public void testRegisterNonExistingFont() {
+ String fontName = getNonExistingFontName();
+ myPreferences.register(fontName, 25);
+ checkState(Arrays.asList(fontName),
+ Arrays.asList(FontPreferences.DEFAULT_FONT_NAME),
+ FontPreferences.DEFAULT_FONT_NAME,
+ fontName, 25);
+ }
+
+ @Test
+ public void testAddExistingFont() {
+ String fontName = getExistingNonDefaultFontName();
+ myPreferences.addFontFamily(fontName);
+ checkState(Arrays.asList(fontName),
+ Arrays.asList(fontName),
+ fontName,
+ fontName, null);
+ }
+
+ @Test
+ public void testAddNonExistingFont() {
+ String fontName = getNonExistingFontName();
+ myPreferences.addFontFamily(fontName);
+ checkState(Arrays.asList(fontName),
+ Arrays.asList(FontPreferences.DEFAULT_FONT_NAME),
+ FontPreferences.DEFAULT_FONT_NAME,
+ fontName, null);
+ }
+
+ private void checkState(java.util.List<String> expectedRealFontFamilies,
+ java.util.List<String> expectedEffectiveFontFamilies,
+ String expectedFontFamily,
+ Object... namesAndSizes) {
+ checkState(myPreferences,
+ expectedRealFontFamilies,
+ expectedEffectiveFontFamilies,
+ expectedFontFamily,
+ namesAndSizes);
+ }
+
+ @SuppressWarnings("AssignmentToForLoopParameter")
+ public static void checkState(FontPreferences fontPreferences,
+ java.util.List<String> expectedRealFontFamilies,
+ java.util.List<String> expectedEffectiveFontFamilies,
+ String expectedFontFamily,
+ Object... namesAndSizes) {
+ assertEquals("Wrong real font families", expectedRealFontFamilies, fontPreferences.getRealFontFamilies());
+ assertEquals("Wrong effective font families", expectedEffectiveFontFamilies, fontPreferences.getEffectiveFontFamilies());
+ assertEquals("Wrong font family", expectedFontFamily, fontPreferences.getFontFamily());
+ for (int i = 0; i < namesAndSizes.length - 1; ) {
+ String fontName = (String)namesAndSizes[i++];
+ Integer fontSize = (Integer)namesAndSizes[i++];
+ assertEquals("Wrong hasSize", fontSize != null, fontPreferences.hasSize(fontName));
+ assertEquals("Wrong font size", fontSize == null ? FontPreferences.DEFAULT_FONT_SIZE : fontSize.intValue(), fontPreferences.getSize(fontName));
+ }
+ }
+
+ public static String getExistingNonDefaultFontName() {
+ return getExistingFontNameButNot(FontPreferences.DEFAULT_FONT_NAME);
+ }
+
+ public static String getAnotherExistingNonDefaultFontName() {
+ String firstOne = getExistingFontNameButNot(FontPreferences.DEFAULT_FONT_NAME);
+ return getExistingFontNameButNot(FontPreferences.DEFAULT_FONT_NAME, firstOne);
+ }
+
+ private static String getExistingFontNameButNot(String... names) {
+ String[] fontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
+ for (String name : fontFamilyNames) {
+ if (name != null && !Arrays.asList(names).contains(name)) {
+ return name;
+ }
+ }
+ fail("Couldn't find existing font not in " + Arrays.toString(names));
+ return null;
+ }
+
+ public static String getNonExistingFontName() {
+ return "DefinitelyNonExistingFontName";
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java
new file mode 100644
index 0000000..0d5abd1
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/colors/impl/EditorColorsSchemeImplTest.java
@@ -0,0 +1,163 @@
+/*
+ * 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.openapi.editor.colors.impl;
+
+import com.intellij.openapi.editor.colors.FontPreferences;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static com.intellij.openapi.editor.colors.FontPreferencesTest.checkState;
+import static com.intellij.openapi.editor.colors.FontPreferencesTest.getAnotherExistingNonDefaultFontName;
+import static com.intellij.openapi.editor.colors.FontPreferencesTest.getExistingNonDefaultFontName;
+
+public class EditorColorsSchemeImplTest extends LightPlatformCodeInsightTestCase {
+ EditorColorsSchemeImpl myScheme = new EditorColorsSchemeImpl(null, null);
+
+ public void testDefaults() {
+ checkState(myScheme.getFontPreferences(),
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList(),
+ FontPreferences.DEFAULT_FONT_NAME,
+ FontPreferences.DEFAULT_FONT_NAME, null);
+ assertEquals(FontPreferences.DEFAULT_FONT_NAME, myScheme.getEditorFontName());
+ assertEquals(FontPreferences.DEFAULT_FONT_SIZE, myScheme.getEditorFontSize());
+ checkState(myScheme.getConsoleFontPreferences(),
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList(),
+ FontPreferences.DEFAULT_FONT_NAME,
+ FontPreferences.DEFAULT_FONT_NAME, null);
+ assertEquals(FontPreferences.DEFAULT_FONT_NAME, myScheme.getConsoleFontName());
+ assertEquals(FontPreferences.DEFAULT_FONT_SIZE, myScheme.getConsoleFontSize());
+ }
+
+ public void testSetPreferences() throws Exception {
+ String fontName1 = getExistingNonDefaultFontName();
+ String fontName2 = getAnotherExistingNonDefaultFontName();
+ myScheme.getFontPreferences().register(fontName1, 25);
+ myScheme.getFontPreferences().register(fontName2, 13);
+ myScheme.getConsoleFontPreferences().register(fontName1, 21);
+ myScheme.getConsoleFontPreferences().register(fontName2, 15);
+
+ checkState(myScheme.getFontPreferences(),
+ Arrays.asList(fontName1, fontName2),
+ Arrays.asList(fontName1, fontName2),
+ fontName1,
+ fontName1, 25,
+ fontName2, 13);
+ assertEquals(fontName1, myScheme.getEditorFontName());
+ assertEquals(25, myScheme.getEditorFontSize());
+ checkState(myScheme.getConsoleFontPreferences(),
+ Arrays.asList(fontName1, fontName2),
+ Arrays.asList(fontName1, fontName2),
+ fontName1,
+ fontName1, 21,
+ fontName2, 15);
+ assertEquals(fontName1, myScheme.getConsoleFontName());
+ assertEquals(21, myScheme.getConsoleFontSize());
+ }
+
+ public void testSetName() throws Exception {
+ String fontName1 = getExistingNonDefaultFontName();
+ String fontName2 = getAnotherExistingNonDefaultFontName();
+ myScheme.setEditorFontName(fontName1);
+ myScheme.setConsoleFontName(fontName2);
+
+ checkState(myScheme.getFontPreferences(),
+ Arrays.asList(fontName1),
+ Arrays.asList(fontName1),
+ fontName1,
+ fontName1, FontPreferences.DEFAULT_FONT_SIZE);
+ assertEquals(fontName1, myScheme.getEditorFontName());
+ assertEquals(FontPreferences.DEFAULT_FONT_SIZE, myScheme.getEditorFontSize());
+ checkState(myScheme.getConsoleFontPreferences(),
+ Arrays.asList(fontName2),
+ Arrays.asList(fontName2),
+ fontName2,
+ fontName2, FontPreferences.DEFAULT_FONT_SIZE);
+ assertEquals(fontName2, myScheme.getConsoleFontName());
+ assertEquals(FontPreferences.DEFAULT_FONT_SIZE, myScheme.getConsoleFontSize());
+ }
+
+ public void testSetSize() throws Exception {
+ myScheme.setEditorFontSize(25);
+ myScheme.setConsoleFontSize(21);
+
+ checkState(myScheme.getFontPreferences(),
+ Arrays.asList(FontPreferences.DEFAULT_FONT_NAME),
+ Arrays.asList(FontPreferences.DEFAULT_FONT_NAME),
+ FontPreferences.DEFAULT_FONT_NAME,
+ FontPreferences.DEFAULT_FONT_NAME, 25);
+ assertEquals(FontPreferences.DEFAULT_FONT_NAME, myScheme.getEditorFontName());
+ assertEquals(25, myScheme.getEditorFontSize());
+ checkState(myScheme.getConsoleFontPreferences(),
+ Arrays.asList(FontPreferences.DEFAULT_FONT_NAME),
+ Arrays.asList(FontPreferences.DEFAULT_FONT_NAME),
+ FontPreferences.DEFAULT_FONT_NAME,
+ FontPreferences.DEFAULT_FONT_NAME, 21);
+ assertEquals(FontPreferences.DEFAULT_FONT_NAME, myScheme.getConsoleFontName());
+ assertEquals(21, myScheme.getConsoleFontSize());
+ }
+
+ public void testSetNameAndSize() throws Exception {
+ String fontName1 = getExistingNonDefaultFontName();
+ String fontName2 = getAnotherExistingNonDefaultFontName();
+ myScheme.setEditorFontName(fontName1);
+ myScheme.setEditorFontSize(25);
+ myScheme.setConsoleFontName(fontName2);
+ myScheme.setConsoleFontSize(21);
+
+ checkState(myScheme.getFontPreferences(),
+ Arrays.asList(fontName1),
+ Arrays.asList(fontName1),
+ fontName1,
+ fontName1, 25);
+ assertEquals(fontName1, myScheme.getEditorFontName());
+ assertEquals(25, myScheme.getEditorFontSize());
+ checkState(myScheme.getConsoleFontPreferences(),
+ Arrays.asList(fontName2),
+ Arrays.asList(fontName2),
+ fontName2,
+ fontName2, 21);
+ assertEquals(fontName2, myScheme.getConsoleFontName());
+ assertEquals(21, myScheme.getConsoleFontSize());
+ }
+
+ public void testSetSizeAndName() throws Exception {
+ String fontName1 = getExistingNonDefaultFontName();
+ String fontName2 = getAnotherExistingNonDefaultFontName();
+ myScheme.setEditorFontSize(25);
+ myScheme.setEditorFontName(fontName1);
+ myScheme.setConsoleFontSize(21);
+ myScheme.setConsoleFontName(fontName2);
+
+ checkState(myScheme.getFontPreferences(),
+ Arrays.asList(fontName1),
+ Arrays.asList(fontName1),
+ fontName1,
+ fontName1, 25);
+ assertEquals(fontName1, myScheme.getEditorFontName());
+ assertEquals(25, myScheme.getEditorFontSize());
+ checkState(myScheme.getConsoleFontPreferences(),
+ Arrays.asList(fontName2),
+ Arrays.asList(fontName2),
+ fontName2,
+ fontName2, 21);
+ assertEquals(fontName2, myScheme.getConsoleFontName());
+ assertEquals(21, myScheme.getConsoleFontSize());
+ }
+}
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 be88019..bbb8de3 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
@@ -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,6 +25,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
import com.intellij.testFramework.TestFileType;
+import com.intellij.testFramework.fixtures.EditorMouseFixture;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -204,4 +205,19 @@
mapper.rawAdd(visualLine, startOffset, endOffset, startLogicalLine, startLogicalColumn, endLogicalLine, endLogicalColumn, endVisualColumn, foldRegions, tabData);
}
}
+
+ public void assertSelectionRanges(int[][] ranges) {
+ int[] selectionStarts = myEditor.getSelectionModel().getBlockSelectionStarts();
+ int[] selectionEnds = myEditor.getSelectionModel().getBlockSelectionEnds();
+ int actualRangeCount = selectionStarts.length;
+ int[][] actualRanges = new int[actualRangeCount][];
+ for (int i = 0; i < actualRangeCount; i++) {
+ actualRanges[i] = new int[] {selectionStarts[i], selectionEnds[i]};
+ }
+ assertEquals("Wrong selected ranges", Arrays.deepToString(ranges), Arrays.deepToString(actualRanges));
+ }
+
+ public EditorMouseFixture mouse() {
+ return new EditorMouseFixture((EditorImpl)myEditor);
+ }
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
new file mode 100644
index 0000000..577ff50
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/EditorImplTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.openapi.editor.impl;
+
+import com.intellij.openapi.editor.VisualPosition;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+public class EditorImplTest extends LightPlatformCodeInsightTestCase {
+ public void testPositionCalculationForZeroWidthChars() throws Exception {
+ configureFromFileText(getTestName(false) + ".txt", "some\u2044text");
+ VisualPosition pos = new VisualPosition(0, 6);
+ VisualPosition recalculatedPos = myEditor.xyToVisualPosition(myEditor.visualPositionToXY(pos));
+ assertEquals(pos, recalculatedPos);
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/FoldingAnchorsOverlayStrategyTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/FoldingAnchorsOverlayStrategyTest.java
new file mode 100644
index 0000000..9480319
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/FoldingAnchorsOverlayStrategyTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.openapi.editor.impl;
+
+import com.intellij.codeInsight.folding.CodeFoldingManager;
+import com.intellij.openapi.editor.FoldRegion;
+import com.intellij.openapi.editor.FoldingModel;
+import com.intellij.openapi.fileTypes.FileTypes;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+import java.util.*;
+
+import static com.intellij.openapi.editor.impl.DisplayedFoldingAnchor.Type;
+
+public class FoldingAnchorsOverlayStrategyTest extends LightPlatformCodeInsightFixtureTestCase {
+ public void testExpanded() {
+ prepareEditor("<body><div>\n" +
+ "</div><div>\n" +
+ "some text\n" +
+ "some text\n" +
+ "some text\n" +
+ "</div><div>\n" +
+ "</div></body>");
+ verifyAnchors(null,
+ 0, Type.EXPANDED_TOP,
+ 1, Type.EXPANDED_BOTTOM,
+ 5, Type.EXPANDED_TOP,
+ 6, Type.EXPANDED_BOTTOM);
+ }
+
+ public void testCollapsed() {
+ prepareEditor("<body><div>\n" +
+ "</div><div>\n" +
+ "some text\n" +
+ "some text\n" +
+ "some text\n" +
+ "</div><div>\n" +
+ "</div></body>");
+ collapseFoldingRegion(2);
+ verifyAnchors(null,
+ 0, Type.EXPANDED_TOP,
+ 1, Type.COLLAPSED,
+ 2, Type.EXPANDED_BOTTOM);
+ }
+
+ public void testWithActiveRegion() {
+ prepareEditor("<body><div>\n" +
+ "</div><div>\n" +
+ "some text\n" +
+ "some text\n" +
+ "some text\n" +
+ "</div><div>\n" +
+ "</div></body>");
+ collapseFoldingRegion(2);
+ verifyAnchors(myFixture.getEditor().getFoldingModel().getAllFoldRegions()[1],
+ 0, Type.EXPANDED_TOP,
+ 1, Type.EXPANDED_BOTTOM,
+ 2, Type.EXPANDED_BOTTOM);
+ }
+
+ public void testWithEmptyLastLine() {
+ myFixture.configureByText(FileTypes.PLAIN_TEXT, "some text\n");
+ final FoldingModel foldingModel = myFixture.getEditor().getFoldingModel();
+ foldingModel.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ foldingModel.addFoldRegion(0, 10, "...");
+ }
+ });
+ verifyAnchors(null,
+ 0, Type.EXPANDED_TOP,
+ 1, Type.EXPANDED_BOTTOM);
+ }
+
+ private void prepareEditor(String text) {
+ myFixture.configureByText(StdFileTypes.XML, text);
+ CodeFoldingManager.getInstance(myFixture.getProject()).updateFoldRegions(myFixture.getEditor());
+ }
+
+ private void collapseFoldingRegion(int n) {
+ FoldingModel foldingModel = myFixture.getEditor().getFoldingModel();
+ final FoldRegion foldRegion = foldingModel.getAllFoldRegions()[n];
+ foldingModel.runBatchFoldingOperation(new Runnable() {
+ @Override
+ public void run() {
+ foldRegion.setExpanded(false);
+ }
+ });
+ }
+
+ private void verifyAnchors(FoldRegion activeFoldRegion, Object... expectedAnchorParameters) {
+ Collection<DisplayedFoldingAnchor> actualAnchors = new FoldingAnchorsOverlayStrategy((EditorImpl)myFixture.getEditor())
+ .getAnchorsToDisplay(0, myFixture.getEditor().getDocument().getTextLength(), activeFoldRegion);
+ List<DisplayedFoldingAnchor> sortedActualAnchors = new ArrayList<DisplayedFoldingAnchor>(actualAnchors);
+ Collections.sort(sortedActualAnchors, new Comparator<DisplayedFoldingAnchor>() {
+ @Override
+ public int compare(DisplayedFoldingAnchor o1, DisplayedFoldingAnchor o2) {
+ return o1.visualLine - o2.visualLine;
+ }
+ });
+
+ assertEquals("Wrong number of anchors", expectedAnchorParameters.length / 2, sortedActualAnchors.size());
+ int i = 0;
+ for (DisplayedFoldingAnchor anchor : sortedActualAnchors) {
+ int expectedVisualLine = (Integer) expectedAnchorParameters[i++];
+ assertEquals("Folding anchor at wrong line found", expectedVisualLine, anchor.visualLine);
+ Type expectedType = (Type)expectedAnchorParameters[i++];
+ assertEquals("Folding anchor of wrong type found at line " + expectedVisualLine, expectedType, anchor.type);
+ }
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java
index 4e880b7..d441c61 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/GuardBlockTest.java
@@ -1,20 +1,22 @@
package com.intellij.openapi.editor.impl;
+import com.intellij.codeInsight.lookup.LookupManager;
+import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.RangeMarker;
-import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
/**
* @author cdr
*/
-public class GuardBlockTest extends LightPlatformCodeInsightTestCase {
- private static RangeMarker createGuard(final int start, final int end) {
- final Document document = getEditor().getDocument();
+public class GuardBlockTest extends LightPlatformCodeInsightFixtureTestCase {
+ private RangeMarker createGuard(final int start, final int end) {
+ final Document document = myFixture.getEditor().getDocument();
return document.createGuardedBlock(start, end);
}
public void testZero() throws Exception {
- configureFromFileText("x.txt", "xxxx");
+ myFixture.configureByText("x.txt", "xxxx");
RangeMarker guard = createGuard(0, 0);
guard.setGreedyToLeft(true);
guard.setGreedyToRight(true);
@@ -23,14 +25,14 @@
}
public void testInTheMiddle() throws Exception {
- configureFromFileText("x.txt", "xxxxxxxx");
+ myFixture.configureByText("x.txt", "xxxxxxxx");
createGuard(1, 4);
checkUnableToTypeIn(2);
checkCanTypeIn(0);
}
public void testGreedy() throws Exception {
- configureFromFileText("x.txt", "012345678");
+ myFixture.configureByText("x.txt", "012345678");
{
RangeMarker guard = createGuard(0, 5);
guard.setGreedyToLeft(true);
@@ -45,7 +47,7 @@
checkUnableToTypeIn(0);
}
public void testGreedyEnd() throws Exception {
- configureFromFileText("x.txt", "012345678");
+ myFixture.configureByText("x.txt", "012345678");
{
RangeMarker guard = createGuard(0, 5);
guard.setGreedyToLeft(true);
@@ -54,22 +56,46 @@
checkUnableToTypeIn(5);
}
- private static void checkUnableToTypeIn(int offset) {
- String text = getEditor().getDocument().getText();
+ private void checkUnableToTypeIn(int offset) {
+ String text = myFixture.getEditor().getDocument().getText();
try {
- getEditor().getCaretModel().moveToOffset(offset);
- type("y");
+ myFixture.getEditor().getCaretModel().moveToOffset(offset);
+ myFixture.type("y");
}
catch (RuntimeException e) {
assertEquals("Unable to perform an action since it changes read-only fragments of the current document",e.getMessage());
- assertEquals(text, getEditor().getDocument().getText());
+ assertEquals(text, myFixture.getEditor().getDocument().getText());
return;
}
fail("must be read only at "+offset);
}
- private static void checkCanTypeIn(int offset) {
- getEditor().getCaretModel().moveToOffset(offset);
- type("yy");
+ private void checkCanTypeIn(int offset) {
+ myFixture.getEditor().getCaretModel().moveToOffset(offset);
+ myFixture.type("yy");
+ }
+
+ public void testNoCompletion() throws Exception {
+ String text = "abc abd a<caret> abx";
+ myFixture.configureByText("x.txt", text);
+ int offset = myFixture.getEditor().getCaretModel().getOffset();
+ createGuard(offset - 1, myFixture.getFile().getTextLength()).setGreedyToRight(true);
+
+ assertNull(myFixture.completeBasic());
+ myFixture.checkResult(text);
+
+ //no hippie completion
+ myFixture.performEditorAction(IdeActions.ACTION_HIPPIE_BACKWARD_COMPLETION);
+ assertNull(LookupManager.getInstance(getProject()).getActiveLookup());
+ myFixture.checkResult(text);
+
+ //no completion at the file end
+ myFixture.getEditor().getCaretModel().moveToOffset(myFixture.getFile().getTextLength());
+ assertNull(myFixture.completeBasic());
+ myFixture.checkResult("abc abd a abx<caret>");
+
+ //completion at the beginning of the guard fragment
+ myFixture.getEditor().getCaretModel().moveToOffset(offset - 1);
+ assertNotNull(myFixture.completeBasic());
}
}
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
new file mode 100644
index 0000000..2b8f99e
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/IterationStateTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.editor.ex.EditorEx;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.testFramework.EditorTestUtil;
+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.List;
+
+public class IterationStateTest extends LightPlatformCodeInsightFixtureTestCase {
+
+ public void testBlockSelection() {
+ verifySplitting("aa,<block>bb\ncc,d</block>d",
+ new Segment(0, 3, Color.BLACK),
+ new Segment(3, 4, Color.WHITE),
+ new Segment(4, 5, Color.BLACK),
+ new Segment(5, 6, Color.BLACK),
+ new Segment(6, 9, Color.BLACK),
+ new Segment(9, 10, Color.WHITE),
+ new Segment(10, 11, Color.BLACK));
+ }
+
+ public void testMultiCaretBlockSelection() {
+ EditorTestUtil.enableMultipleCarets();
+ try {
+ testBlockSelection();
+ }
+ finally {
+ EditorTestUtil.disableMultipleCarets();
+ }
+ }
+
+ private void verifySplitting(String text, Segment... expectedSegments) {
+ myFixture.configureByText(PlainTextFileType.INSTANCE, text);
+ 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()));
+ iterationState.advance();
+ }
+ while (!iterationState.atEnd());
+
+ Assert.assertArrayEquals(expectedSegments, actualSegments.toArray());
+ }
+ finally {
+ iterationState.dispose();
+ }
+ }
+
+ private static class Segment {
+ private final int start;
+ private final int end;
+ private final Color fgColor;
+
+ private Segment(int start, int end, @NotNull Color fgColor) {
+ this.start = start;
+ this.end = end;
+ this.fgColor = fgColor;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ Segment segment = (Segment)o;
+
+ if (end != segment.end) return false;
+ if (start != segment.start) return false;
+ if (!fgColor.equals(segment.fgColor)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = start;
+ result = 31 * result + end;
+ result = 31 * result + fgColor.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "Segment{" +
+ "start=" + start +
+ ", end=" + end +
+ ", color=" + fgColor +
+ '}';
+ }
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java
index c5e4b95..d8d0f5d 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/editor/impl/softwrap/mapping/SoftWrapApplianceOnDocumentModificationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java
index dffec2b..a5cdcbe 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/FileDocumentManagerImplTest.java
@@ -15,87 +15,54 @@
*/
package com.intellij.openapi.fileEditor;
-import com.intellij.codeStyle.CodeStyleFacade;
-import com.intellij.codeStyle.DefaultCodeStyleFacade;
-import com.intellij.ide.DataManager;
-import com.intellij.ide.impl.DataManagerImpl;
-import com.intellij.mock.MockCommandProcessor;
-import com.intellij.mock.MockEditorFactory;
+import com.intellij.AppTopics;
import com.intellij.mock.MockVirtualFile;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.command.UndoConfirmationPolicy;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.ex.DocumentEx;
import com.intellij.openapi.fileEditor.impl.FileDocumentManagerImpl;
-import com.intellij.openapi.fileTypes.*;
-import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl;
-import com.intellij.openapi.fileTypes.impl.InternalFileTypeFactory;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.project.ProjectLocator;
-import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.project.impl.DefaultProjectLocator;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.IoTestUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileEvent;
-import com.intellij.openapi.vfs.VirtualFileManager;
-import com.intellij.testFramework.MockSchemesManagerFactory;
-import com.intellij.testFramework.PlatformLiteFixture;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiFile;
+import com.intellij.testFramework.PlatformLangTestCase;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.LocalTimeCounter;
-import org.easymock.classextension.EasyMock;
+import com.intellij.util.PairProcessor;
import org.jetbrains.annotations.NotNull;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-public class FileDocumentManagerImplTest extends PlatformLiteFixture {
- private MyMockFileDocumentManager myDocumentManager;
+public class FileDocumentManagerImplTest extends PlatformLangTestCase {
+ private FileDocumentManagerImpl myDocumentManager;
+ public Boolean myReloadFromDisk;
@Override
protected void setUp() throws Exception {
super.setUp();
- initApplication();
- registerExtension(FileTypeFactory.FILE_TYPE_FACTORY_EP, new InternalFileTypeFactory());
- registerExtensionPoint(FileDocumentSynchronizationVetoer.EP_NAME, FileDocumentSynchronizationVetoer.class);
- getApplication().registerService(CommandProcessor.class, new MyMockCommandProcessor());
- getApplication().registerService(CodeStyleFacade.class, new DefaultCodeStyleFacade());
- getApplication().registerService(ProjectLocator.class, new DefaultProjectLocator());
-
- MockEditorFactory editorFactory = new MockEditorFactory();
- getApplication().registerService(EditorFactory.class, editorFactory);
- final LanguageFileType[] fileType = {null};
- getApplication().addComponent(FileTypeManager.class, new FileTypeManagerImpl(null, new MockSchemesManagerFactory()) {
- @NotNull
+ myReloadFromDisk = Boolean.TRUE;
+ FileDocumentManagerImpl impl = (FileDocumentManagerImpl)FileDocumentManager.getInstance();
+ impl.setAskReloadFromDisk(getTestRootDisposable(), new PairProcessor<VirtualFile, Document>() {
@Override
- public FileType getFileTypeByFileName(@NotNull String fileName) {
- return fileType[0];
- }
-
- @NotNull
- @Override
- public FileType getFileTypeByFile(@NotNull VirtualFile file) {
- return fileType[0];
- }
-
- @NotNull
- @Override
- public FileType getFileTypeByExtension(@NotNull String extension) {
- return fileType[0];
+ public boolean process(VirtualFile file, Document document) {
+ if (myReloadFromDisk == null) {
+ fail();
+ return false;
+ }
+ return myReloadFromDisk.booleanValue();
}
});
-
- fileType[0] = StdFileTypes.JAVA;
-
- getApplication().getComponent(FileTypeManager.class);
-
- final VirtualFileManager virtualFileManager = EasyMock.createMock(VirtualFileManager.class);
- final ProjectManager projectManager = EasyMock.createMock(ProjectManager.class);
- myDocumentManager = new MyMockFileDocumentManager(virtualFileManager, projectManager);
- getApplication().registerService(FileDocumentManager.class, myDocumentManager);
- getApplication().registerService(DataManager.class, new DataManagerImpl());
+ myDocumentManager = impl;
}
public void testGetCachedDocument_Cached() throws Exception {
@@ -104,14 +71,14 @@
}
public void testGetCachedDocument_NotCached() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
final Document document = myDocumentManager.getDocument(file);
assertSame(myDocumentManager.getCachedDocument(file), document);
}
public void testGetDocument_CreateNew() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
final Document document = myDocumentManager.getDocument(file);
assertNotNull(document);
assertEquals("test", document.getText());
@@ -120,7 +87,7 @@
}
public void testGetDocument_CreateNew_ReadOnly() throws Exception {
- final MockVirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
file.setWritable(false);
final Document document = myDocumentManager.getDocument(file);
assertNotNull(document);
@@ -130,7 +97,7 @@
}
public void testGetDocument_ReturnCachedValueTwice() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
final Document document = myDocumentManager.getDocument(file);
assertNotNull(document);
assertEquals("test", document.getText());
@@ -140,7 +107,7 @@
}
public void testGetDocument_CreatesNewAfterGCed() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
Document document = myDocumentManager.getDocument(file);
int idCode = System.identityHashCode(document);
//noinspection UnusedAssignment
@@ -159,7 +126,7 @@
}
public void testGetUnsavedDocuments_CreatedDocument() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
myDocumentManager.getDocument(file);
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
@@ -167,10 +134,16 @@
}
public void testGetUnsavedDocuments_ModifiedDocument() throws Exception {
- final VirtualFile file = newTextFile();
- Document document = myDocumentManager.getDocument(file);
+ final VirtualFile file = createFile();
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx");
+ }
+ });
+
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
assertEquals(1, unsavedDocuments.length);
@@ -179,10 +152,16 @@
}
public void testGetUnsavedDocuments_afterSaveAllDocuments() throws Exception {
- final VirtualFile file = newTextFile();
- Document document = myDocumentManager.getDocument(file);
+ final VirtualFile file = createFile();
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx");
+ }
+ });
+
myDocumentManager.saveAllDocuments();
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
@@ -190,10 +169,16 @@
}
public void testGetUnsavedDocuments_afterSaveDocuments() throws Exception {
- final VirtualFile file = newTextFile();
- Document document = myDocumentManager.getDocument(file);
+ final VirtualFile file = createFile();
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx");
+ }
+ });
+
myDocumentManager.saveDocument(document);
final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
@@ -201,34 +186,55 @@
}
public void testGetUnsavedDocuments_afterSaveDocumentWithProblems() throws Exception {
- final VirtualFile file = new MockVirtualFile("test.txt", "test") {
- @Override
- @NotNull
- public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
- throw new IOException("");
+ try {
+ final VirtualFile file = new MockVirtualFile("test.txt", "test") {
+ @Override
+ @NotNull
+ public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
+ throw new IOException("");
+ }
+ };
+
+ final Document document = myDocumentManager.getDocument(file);
+ assertNotNull(file.toString(), document);
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx");
+ }
+ });
+
+
+ try {
+ myDocumentManager.saveDocument(document);
+ fail("must throw IOException");
}
- };
+ catch (RuntimeException e) {
+ assertTrue(e.getCause() instanceof IOException);
+ }
- Document document = myDocumentManager.getDocument(file);
- assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
-
- myDocumentManager.saveDocument(document);
-
- assertNotNull(myDocumentManager.myExceptionOnSave);
-
- final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
- assertEquals(1, unsavedDocuments.length);
- assertSame(document, unsavedDocuments[0]);
- assertTrue(Arrays.equals("test".getBytes("UTF-8"), file.contentsToByteArray()));
+ final Document[] unsavedDocuments = myDocumentManager.getUnsavedDocuments();
+ assertEquals(1, unsavedDocuments.length);
+ assertSame(document, unsavedDocuments[0]);
+ assertTrue(Arrays.equals("test".getBytes("UTF-8"), file.contentsToByteArray()));
+ }
+ finally {
+ myDocumentManager.dropAllUnsavedDocuments();
+ }
}
public void testUnsavedDocument_DoNotGC() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
Document document = myDocumentManager.getDocument(file);
- assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
int idCode = System.identityHashCode(document);
+ assertNotNull(file.toString(), document);
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ myDocumentManager.getDocument(file).insertString(0, "xxx");
+ }
+ });
+
//noinspection UnusedAssignment
document = null;
@@ -240,10 +246,16 @@
}
public void testUnsavedDocument_GcAfterSave() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ myDocumentManager.getDocument(file).insertString(0, "xxx");
+ }
+ });
+
int idCode = System.identityHashCode(document);
//noinspection UnusedAssignment
document = null;
@@ -258,7 +270,7 @@
}
public void testSaveDocument_DocumentWasNotChanged() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
final long stamp = file.getModificationStamp();
Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
@@ -267,11 +279,17 @@
}
public void testSaveDocument_DocumentWasChanged() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
final long stamp = file.getModificationStamp();
- Document document = myDocumentManager.getDocument(file);
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx ");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx ");
+ }
+ });
+
myDocumentManager.saveDocument(document);
assertTrue(stamp != file.getModificationStamp());
@@ -280,11 +298,17 @@
}
public void testSaveAllDocuments_DocumentWasChanged() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
final long stamp = file.getModificationStamp();
- Document document = myDocumentManager.getDocument(file);
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx ");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx ");
+ }
+ });
+
myDocumentManager.saveAllDocuments();
assertTrue(stamp != file.getModificationStamp());
@@ -292,7 +316,7 @@
}
public void testGetFile() throws Exception {
- final VirtualFile file = newTextFile();
+ final VirtualFile file = createFile();
Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
assertSame(file, myDocumentManager.getFile(document));
@@ -307,35 +331,51 @@
public void testRememberSeparators() throws Exception {
final VirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
- Document document = myDocumentManager.getDocument(file);
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx ");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx ");
+ }
+ });
+
myDocumentManager.saveAllDocuments();
assertTrue(Arrays.equals("xxx test\rtest".getBytes("UTF-8"), file.contentsToByteArray()));
}
public void testContentChanged_noDocument() throws Exception {
- final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
- file.setListener(myDocumentManager);
- file.setContent(null, "xxx", true);
+ final VirtualFile file = createFile();
+ setContent(file, "xxx");
assertNull(myDocumentManager.getCachedDocument(file));
}
+ VirtualFile createFile(String name, String content) throws IOException {
+ File file = createTempFile(name, content);
+ VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
+ assertNotNull(virtualFile);
+ return virtualFile;
+ }
+ VirtualFile createFile() throws IOException {
+ return createFile("test.txt", "test");
+ }
+ void setContent(VirtualFile file, String content) throws IOException {
+ file.setBinaryContent(content.getBytes(CharsetToolkit.UTF8_CHARSET));
+ }
+
public void testContentChanged_documentPresent() throws Exception {
- final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
- file.setListener(myDocumentManager);
+ VirtualFile file = createFile();
Document document = myDocumentManager.getDocument(file);
- file.setContent(null, "xxx", true);
+ setContent(file, "xxx");
assertNotNull(file.toString(), document);
assertEquals("xxx", document.getText());
assertEquals(file.getModificationStamp(), document.getModificationStamp());
}
public void testContentChanged_ignoreEventsFromSelf() throws Exception {
- final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
- file.setListener(myDocumentManager);
+ final VirtualFile file = createFile("test.txt", "test\rtest");
Document document = myDocumentManager.getDocument(file);
- file.setContent(myDocumentManager, "xxx", true);
+ file.setBinaryContent("xxx".getBytes(CharsetToolkit.UTF8_CHARSET), -1,-1,myDocumentManager);
assertNotNull(file.toString(), document);
assertEquals("test\ntest", document.getText());
}
@@ -358,9 +398,15 @@
};
}
};
- Document document = myDocumentManager.getDocument(file);
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "xxx");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "xxx");
+ }
+ });
+
final long stamp = document.getModificationStamp();
myDocumentManager.saveAllDocuments();
@@ -368,59 +414,63 @@
}
public void testContentChanged_reloadChangedDocument() throws Exception {
- final MockVirtualFile file = new MockVirtualFile("test.txt", "test\rtest");
- file.setListener(myDocumentManager);
- Document document = myDocumentManager.getDocument(file);
+ final VirtualFile file = createFile();
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "zzz");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "zzz");
+ }
+ });
- myDocumentManager.myReloadFromDisk = Boolean.TRUE;
- try {
- file.setContent(null, "xxx", true);
- assertEquals("xxx", document.getText());
- assertEquals(file.getModificationStamp(), document.getModificationStamp());
- assertEquals(0, myDocumentManager.getUnsavedDocuments().length);
- }
- finally {
- myDocumentManager.myReloadFromDisk = null;
- }
+ myReloadFromDisk = Boolean.TRUE;
+ setContent(file, "xxx");
+
+ assertEquals("xxx", document.getText());
+ assertEquals(file.getModificationStamp(), document.getModificationStamp());
+ assertEquals(0, myDocumentManager.getUnsavedDocuments().length);
}
public void testContentChanged_DoNotReloadChangedDocument() throws Exception {
- final MockVirtualFile file = newTextFile();
- file.setListener(myDocumentManager);
- Document document = myDocumentManager.getDocument(file);
+ final VirtualFile file = createFile();
+ final Document document = myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "old ");
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "old ");
+ }
+ });
- myDocumentManager.myReloadFromDisk = Boolean.FALSE;
- try {
- long oldDocumentStamp = document.getModificationStamp();
+ myReloadFromDisk = Boolean.FALSE;
+ long oldDocumentStamp = document.getModificationStamp();
- file.setContent(null, "xxx", true);
+ file.setBinaryContent("xxx".getBytes(CharsetToolkit.UTF8_CHARSET));
- assertEquals("old test", document.getText());
- assertEquals(oldDocumentStamp, document.getModificationStamp());
- }
- finally {
- myDocumentManager.myReloadFromDisk = null;
- }
+ assertEquals("old test", document.getText());
+ assertEquals(oldDocumentStamp, document.getModificationStamp());
}
public void testSaveDocument_DoNotSaveIfModStampEqualsToFile() throws Exception {
- final VirtualFile file = new MockVirtualFile("test.txt", "test") {
- @NotNull
- @Override
- public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
- fail();
- throw new IOException();
- }
- };
- DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
+ final VirtualFile file = createFile();
+ final DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
assertNotNull(file.toString(), document);
- document.insertString(0, "zzz");
- document.setModificationStamp(file.getModificationStamp());
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "zzz");
+ document.setModificationStamp(file.getModificationStamp());
+ }
+ });
+
+ getProject().getMessageBus().connect(getTestRootDisposable()).subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
+ @Override
+ public void beforeDocumentSaving(@NotNull Document documentToSave) {
+ assertNotSame(document, documentToSave);
+ }
+ });
myDocumentManager.saveDocument(document);
}
@@ -442,23 +492,19 @@
document.insertString(0, "zzz");
file.setContent(null, "xxx", false);
- myDocumentManager.myReloadFromDisk = Boolean.TRUE;
- try {
- myDocumentManager.saveAllDocuments();
- long fileStamp = file.getModificationStamp();
+ myReloadFromDisk = Boolean.TRUE;
+ myDocumentManager.saveAllDocuments();
+ long fileStamp = file.getModificationStamp();
- assertEquals("xxx", document.getText());
- assertEquals(file.getModificationStamp(), document.getModificationStamp());
- assertEquals(file.getModificationStamp(), fileStamp);
- assertEquals(0, myDocumentManager.getUnsavedDocuments().length);
- }
- finally {
- myDocumentManager.myReloadFromDisk = null;
- }
+ assertEquals("xxx", document.getText());
+ assertEquals(file.getModificationStamp(), document.getModificationStamp());
+ assertEquals(file.getModificationStamp(), fileStamp);
+ assertEquals(0, myDocumentManager.getUnsavedDocuments().length);
}
public void testContentChanged_doNotReloadChangedDocumentOnSave() throws Exception {
- final MockVirtualFile file = new MockVirtualFile("test.txt", "test") {
+ final MockVirtualFile file =
+ new MockVirtualFile("test.txt", "test") {
@Override
public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
long oldStamp = getModificationStamp();
@@ -467,154 +513,150 @@
}
};
- myDocumentManager.myReloadFromDisk = Boolean.FALSE;
- try {
- Document document = myDocumentManager.getDocument(file);
- assertNotNull(file.toString(), document);
- document.insertString(0, "old ");
- long documentStamp = document.getModificationStamp();
+ myReloadFromDisk = Boolean.FALSE;
+ final Document document = myDocumentManager.getDocument(file);
+ assertNotNull(file.toString(), document);
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(0, "old ");
+ }
+ });
- file.setContent(null, "xxx", false);
+ long documentStamp = document.getModificationStamp();
- myDocumentManager.saveAllDocuments();
+ file.setContent(null, "xxx", false);
- assertEquals("old test", document.getText());
- assertEquals(file.getModificationStamp(), document.getModificationStamp());
- assertTrue(Arrays.equals("old test".getBytes("UTF-8"), file.contentsToByteArray()));
- assertEquals(documentStamp, document.getModificationStamp());
- }
- finally {
- myDocumentManager.myReloadFromDisk = null;
- }
+ myDocumentManager.saveAllDocuments();
+
+ assertEquals("old test", document.getText());
+ assertEquals(file.getModificationStamp(), document.getModificationStamp());
+ assertTrue(Arrays.equals("old test".getBytes("UTF-8"), file.contentsToByteArray()));
+ assertEquals(documentStamp, document.getModificationStamp());
}
- public void testReplaceDocumentTestWithTheSameTest() throws Exception {
- final boolean[] canCallSave = {true};
- final VirtualFile file = new MockVirtualFile("test.txt", "test") {
- @NotNull
- @Override
- public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
- if (!canCallSave[0]) fail();
- return super.getOutputStream(requestor, newModificationStamp, newTimeStamp);
- }
- };
- DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
+ public void testReplaceDocumentTextWithTheSameText() throws Exception {
+ final VirtualFile file = createFile();
+ final DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
- String newText = "test text";
+ final String newText = "test text";
assertNotNull(file.toString(), document);
- document.replaceString(0, document.getTextLength(), newText);
- assertTrue(myDocumentManager.isDocumentUnsaved(document));
- myDocumentManager.saveDocument(document);
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
+ @Override
+ public void run() {
+ document.replaceString(0, document.getTextLength(), newText);
+ assertTrue(myDocumentManager.isDocumentUnsaved(document));
+ myDocumentManager.saveDocument(document);
- canCallSave[0] = false;
+ getProject().getMessageBus().connect(getTestRootDisposable())
+ .subscribe(AppTopics.FILE_DOCUMENT_SYNC, new FileDocumentManagerAdapter() {
+ @Override
+ public void beforeDocumentSaving(@NotNull Document documentToSave) {
+ assertNotSame(document, documentToSave);
+ }
+ });
- final long modificationStamp = document.getModificationStamp();
+ final long modificationStamp = document.getModificationStamp();
- document.replaceString(0, document.getTextLength(), newText);
-
- if (myDocumentManager.isDocumentUnsaved(document)) {
- assertTrue(document.getModificationStamp() > modificationStamp);
- }
- else {
- assertEquals(modificationStamp, document.getModificationStamp());
- }
+ document.replaceString(0, document.getTextLength(), newText);
+ if (myDocumentManager.isDocumentUnsaved(document)) {
+ assertTrue(document.getModificationStamp() > modificationStamp);
+ }
+ else {
+ assertEquals(modificationStamp, document.getModificationStamp());
+ }
+ }
+ });
}
public void testExternalReplaceWithTheSameText() throws Exception {
- final long[] modificationStamp = new long[1];
- modificationStamp[0] = 1;
-
- final VirtualFile file = new MockVirtualFile("test.txt", "test") {
- @NotNull
- @Override
- public OutputStream getOutputStream(Object requestor, long newModificationStamp, long newTimeStamp) throws IOException {
- fail();
- throw new IOException();
- }
-
- @Override
- public long getModificationStamp() {
- return modificationStamp[0];
- }
-
- @Override
- public void refresh(boolean asynchronous, boolean recursive, Runnable postRunnable) {
- myDocumentManager.contentsChanged(new VirtualFileEvent(null, this, null, 1, 2));
- }
- };
+ final VirtualFile file = createFile();
+ long modificationStamp = file.getModificationStamp();
DocumentEx document = (DocumentEx)myDocumentManager.getDocument(file);
- modificationStamp[0] = 2;
+ FileUtil.writeToFile(new File(file.getPath()), "xxx");
file.refresh(false, false);
assertNotNull(file.toString(), document);
- assertEquals(2, document.getModificationStamp());
+
+ assertNotSame(file.getModificationStamp(), modificationStamp);
+ assertEquals(file.getModificationStamp(), document.getModificationStamp());
}
- private static MockVirtualFile newTextFile() {
- return new MockVirtualFile("test.txt", "test");
+
+ public void testFileTypeModificationDocumentPreservation() throws Exception {
+ File ioFile = IoTestUtil.createTestFile("test.html", "<html>some text</html>");
+ VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
+ assertNotNull(ioFile.getPath(), file);
+
+ FileDocumentManager documentManager = FileDocumentManager.getInstance();
+ Document original = documentManager.getDocument(file);
+ assertNotNull(file.getPath(), original);
+
+ renameFile(file, "test.wtf");
+ Document afterRename = documentManager.getDocument(file);
+ assertTrue(afterRename + " != " + original, afterRename == original);
}
- private static class MyMockFileDocumentManager extends FileDocumentManagerImpl {
- private static final FileDocumentManagerListener[] LISTENERS = new FileDocumentManagerListener[0];
+ public void testFileTypeChangeDocumentDetach() throws Exception {
+ File ioFile = IoTestUtil.createTestFile("test.html", "<html>some text</html>");
+ VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
+ assertNotNull(ioFile.getPath(), file);
- private Collection<IOException> myExceptionOnSave = null;
- private Boolean myReloadFromDisk = null;
+ FileDocumentManager documentManager = FileDocumentManager.getInstance();
+ Document original = documentManager.getDocument(file);
+ assertNotNull(file.getPath(), original);
- public MyMockFileDocumentManager(VirtualFileManager virtualFileManager, ProjectManager projectManager) {
- super(virtualFileManager, projectManager);
+ renameFile(file, "test.png");
+ Document afterRename = documentManager.getDocument(file);
+ assertNull(afterRename + " != null", afterRename);
+ }
+
+ private static void renameFile(VirtualFile file, String newName) throws IOException {
+ AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(null);
+ try {
+ file.rename(null, newName);
}
-
- @Override
- protected void handleErrorsOnSave(@NotNull Map<Document, IOException> failures) {
- myExceptionOnSave = failures.values();
+ finally {
+ token.finish();
}
+ }
- @Override
- protected boolean askReloadFromDisk(VirtualFile file, Document document) {
- if (myReloadFromDisk == null) {
- fail();
- return false;
+ public void testNoPSIModificationsDuringSave() throws IOException {
+ File ioFile = IoTestUtil.createTestFile("test.txt", "<html>some text</html>");
+ VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
+ assertNotNull(ioFile.getPath(), virtualFile);
+
+ FileDocumentManager documentManager = FileDocumentManager.getInstance();
+ Document original = documentManager.getDocument(virtualFile);
+ assertNotNull(virtualFile.getPath(), original);
+
+ final PsiFile file = getPsiFile(original);
+ FileDocumentManagerListener saveListener = new FileDocumentManagerAdapter() {
+ @Override
+ public void beforeDocumentSaving(@NotNull Document document) {
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ try {
+ file.getFirstChild().delete();
+ fail("Must not modify PSI inside save listener");
+ }
+ catch (IncorrectOperationException e) {
+ assertEquals("Must not modify PSI inside save listener", e.getMessage());
+ }
+ }
+ });
}
- else {
- return myReloadFromDisk.booleanValue();
+ };
+ getProject().getMessageBus().connect(getTestRootDisposable()).subscribe(AppTopics.FILE_DOCUMENT_SYNC, saveListener);
+ final Document document = PsiDocumentManager.getInstance(getProject()).getDocument(file);
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
+ @Override
+ public void run() {
+ document.insertString(1,"y");
}
- }
+ });
- @NotNull
- @Override
- protected FileDocumentManagerListener[] getListeners() {
- return LISTENERS;
- }
- }
-
- private static class MyMockCommandProcessor extends MockCommandProcessor {
- @Override
- public void executeCommand(Project project, @NotNull Runnable runnable, String name, Object groupId) {
- runnable.run();
- }
-
- @Override
- public void executeCommand(Project project,
- @NotNull Runnable runnable,
- String name,
- Object groupId,
- @NotNull UndoConfirmationPolicy confirmationPolicy,
- Document document) {
- runnable.run();
- }
-
- @Override
- public void executeCommand(Project project,
- @NotNull Runnable runnable,
- String name,
- Object groupId,
- @NotNull UndoConfirmationPolicy confirmationPolicy) {
- runnable.run();
- }
-
- @Override
- public void executeCommand(@NotNull Runnable runnable, String name, Object groupId) {
- runnable.run();
- }
+ FileDocumentManager.getInstance().saveAllDocuments();
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java
deleted file mode 100644
index fca92e9..0000000
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/RealFileDocumentManagerTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.openapi.fileEditor;
-
-import com.intellij.openapi.application.AccessToken;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.util.io.IoTestUtil;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.testFramework.LightPlatformLangTestCase;
-
-import java.io.File;
-import java.io.IOException;
-
-public class RealFileDocumentManagerTest extends LightPlatformLangTestCase {
- public void testFileTypeModificationDocumentPreservation() throws Exception {
- File ioFile = IoTestUtil.createTestFile("test.html", "<html>some text</html>");
- VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
- assertNotNull(ioFile.getPath(), file);
-
- FileDocumentManager documentManager = FileDocumentManager.getInstance();
- Document original = documentManager.getDocument(file);
- assertNotNull(file.getPath(), original);
-
- renameFile(file, "test.wtf");
- Document afterRename = documentManager.getDocument(file);
- assertTrue(afterRename + " != " + original, afterRename == original);
- }
-
- public void testFileTypeChangeDocumentDetach() throws Exception {
- File ioFile = IoTestUtil.createTestFile("test.html", "<html>some text</html>");
- VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
- assertNotNull(ioFile.getPath(), file);
-
- FileDocumentManager documentManager = FileDocumentManager.getInstance();
- Document original = documentManager.getDocument(file);
- assertNotNull(file.getPath(), original);
-
- renameFile(file, "test.png");
- Document afterRename = documentManager.getDocument(file);
- assertNull(afterRename + " != null", afterRename);
- }
-
- private static void renameFile(VirtualFile file, String newName) throws IOException {
- AccessToken token = ApplicationManager.getApplication().acquireWriteActionLock(RealFileDocumentManagerTest.class);
- try {
- file.rename(RealFileDocumentManagerTest.class, newName);
- }
- finally {
- token.finish();
- }
- }
-}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/UniqueNameBuilderTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/UniqueNameBuilderTest.java
index 816454d..e63eccd 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/UniqueNameBuilderTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileEditor/UniqueNameBuilderTest.java
@@ -1,5 +1,6 @@
package com.intellij.openapi.fileEditor;
+import com.intellij.openapi.fileEditor.impl.UniqueVFilePathBuilderImpl;
import com.intellij.openapi.util.io.UniqueNameBuilder;
import junit.framework.TestCase;
@@ -65,4 +66,13 @@
assertEquals("something/\u2026/default.php", builder.getShortPath("A"));
assertEquals("something_else/\u2026/default.php", builder.getShortPath("B"));
}
+
+ public void testFilesWithoutExtensions() {
+ UniqueNameBuilder<String> builder = new UniqueNameBuilder<String>("", "/", 25);
+ builder.addPath("A", "foo/.htaccess");
+ builder.addPath("B", "bar/.htaccess");
+ assertEquals("foo/.htaccess", UniqueVFilePathBuilderImpl.getEditorTabText("A", builder, false));
+ assertEquals("foo/.htaccess", UniqueVFilePathBuilderImpl.getEditorTabText("A", builder, true));
+
+ }
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/ex/FileTypeChooserTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/ex/FileTypeChooserTest.java
index 8b57b54..eb193b1 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/ex/FileTypeChooserTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/fileTypes/ex/FileTypeChooserTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -15,18 +15,18 @@
*/
package com.intellij.openapi.fileTypes.ex;
-import com.intellij.testFramework.UsefulTestCase;
+import org.junit.Test;
+
+import static com.intellij.testFramework.UsefulTestCase.assertSameElements;
/**
* @author Nikolay Matveev
*/
-public class FileTypeChooserTest extends UsefulTestCase {
-
+public class FileTypeChooserTest {
+ @Test
public void testSuggestPatterns() {
assertSameElements(FileTypeChooser.suggestPatterns("a"), "a");
assertSameElements(FileTypeChooser.suggestPatterns("a.b"), "a.b", "*.b");
assertSameElements(FileTypeChooser.suggestPatterns("a.b.c"), "a.b.c", "*.c", "*.b.c");
}
-
}
-
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcherTest.java
new file mode 100644
index 0000000..f411c4b
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/IdeMouseEventDispatcherTest.java
@@ -0,0 +1,93 @@
+/*
+ * 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.openapi.keymap.impl;
+
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.MouseShortcut;
+import com.intellij.openapi.keymap.Keymap;
+import com.intellij.openapi.keymap.ex.KeymapManagerEx;
+import com.intellij.testFramework.LightPlatformTestCase;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.MouseEvent;
+
+public class IdeMouseEventDispatcherTest extends LightPlatformTestCase {
+ private static final String OUR_KEYMAP_NAME = "IdeMouseEventDispatcherTestKeymap";
+ private static final String OUR_TEST_ACTION = "IdeMouseEventDispatcherTestAction";
+ private static final MouseShortcut OUR_SHORTCUT = new MouseShortcut(MouseEvent.BUTTON2, 0, 1);
+
+ private KeymapImpl keymap;
+ private Keymap mySavedKeymap;
+ private Component myEventSource;
+ private int myActionExecutionCount;
+
+ public void setUp() throws Exception {
+ super.setUp();
+
+ ActionManager.getInstance().registerAction(OUR_TEST_ACTION, new EmptyAction());
+
+ keymap = new KeymapImpl();
+ keymap.setName(OUR_KEYMAP_NAME);
+ keymap.addShortcut(OUR_TEST_ACTION, OUR_SHORTCUT);
+ KeymapManagerEx.getInstanceEx().getSchemesManager().addNewScheme(keymap, false);
+ mySavedKeymap = KeymapManagerEx.getInstanceEx().getActiveKeymap();
+ KeymapManagerEx.getInstanceEx().setActiveKeymap(keymap);
+
+ myEventSource = new JPanel();
+ myEventSource.setSize(1,1);
+ }
+
+ @Override
+ public void tearDown() throws Exception {
+ KeymapManagerEx.getInstanceEx().getSchemesManager().removeScheme(keymap);
+ KeymapManagerEx.getInstanceEx().setActiveKeymap(mySavedKeymap);
+ ActionManager.getInstance().unregisterAction(OUR_TEST_ACTION);
+ super.tearDown();
+ }
+
+ public void testActionTriggering() throws Exception {
+ IdeMouseEventDispatcher dispatcher = new IdeMouseEventDispatcher();
+
+ assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_PRESSED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2)));
+ assertTrue(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_RELEASED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2)));
+ assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_CLICKED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2)));
+ assertEquals(1, myActionExecutionCount);
+ }
+
+ public void testActionSuppressionAfterDrag() throws Exception {
+ IdeMouseEventDispatcher dispatcher = new IdeMouseEventDispatcher();
+
+ assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_PRESSED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2)));
+ assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_DRAGGED, 0, 0, 0, 0, 0, false, MouseEvent.BUTTON2)));
+ assertFalse(dispatcher.dispatchMouseEvent(new MouseEvent(myEventSource, MouseEvent.MOUSE_RELEASED, 0, 0, 0, 0, 1, false, MouseEvent.BUTTON2)));
+ assertEquals(0, myActionExecutionCount);
+ }
+
+ private class EmptyAction extends AnAction {
+ private EmptyAction() {
+ setEnabledInModalContext(true);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e){
+ myActionExecutionCount++;
+ }
+ }
+
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java
new file mode 100644
index 0000000..582ddb3
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/keymap/impl/ui/ActionsTreeTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.openapi.keymap.impl.ui;
+
+import com.intellij.openapi.actionSystem.ex.QuickList;
+import com.intellij.openapi.keymap.KeymapManager;
+import com.intellij.testFramework.LightPlatformCodeInsightTestCase;
+
+public class ActionsTreeTest extends LightPlatformCodeInsightTestCase {
+ private static final String ACTION_WITHOUT_TEXT_AND_DESCRIPTION = "EditorDeleteToLineEnd";
+ private static final String ACTION_WITH_TEXT_ONLY = "EditorCutLineEnd";
+ private static final String ACTION_WITH_TEXT_AND_DESCRIPTION = "EditorHungryBackSpace";
+
+ private ActionsTree myActionsTree;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ myActionsTree = new ActionsTree();
+ myActionsTree.reset(KeymapManager.getInstance().getActiveKeymap(), new QuickList[0]);
+ }
+
+ public void testVariousActionsArePresent() {
+ doTest(null,
+ ACTION_WITHOUT_TEXT_AND_DESCRIPTION,
+ ACTION_WITH_TEXT_ONLY,
+ ACTION_WITH_TEXT_AND_DESCRIPTION);
+ }
+
+ public void testFiltering() {
+ doTest("Editor",
+ // all below actions should still be present, as they contain 'Editor' in their actionId
+ ACTION_WITHOUT_TEXT_AND_DESCRIPTION,
+ ACTION_WITH_TEXT_ONLY,
+ ACTION_WITH_TEXT_AND_DESCRIPTION);
+ }
+
+ private void doTest(String filter, String... idsThatMustBePresent) {
+ if (filter != null) {
+ myActionsTree.filter(filter, new QuickList[0]);
+ }
+
+ for (String actionId : idsThatMustBePresent) {
+ assertTrue(actionId + " is absent", myActionsTree.getMainGroup().containsId(actionId));
+ }
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java
index 3604d85..ecc3692 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/VfsUtilTest.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,6 +16,7 @@
package com.intellij.openapi.vfs;
import com.intellij.concurrency.JobLauncher;
+import com.intellij.idea.Bombed;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.application.ex.PathManagerEx;
@@ -32,6 +33,7 @@
import com.intellij.testFramework.vcs.DirectoryData;
import com.intellij.util.Processor;
import com.intellij.util.ThrowableRunnable;
+import com.intellij.util.TimeoutUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -39,10 +41,8 @@
import java.io.IOException;
import java.net.URI;
import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
+import java.nio.charset.Charset;
+import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -83,7 +83,6 @@
}
public void testFindFileByUrl() throws Exception {
-
File file1 = new File(PathManagerEx.getTestDataPath());
file1 = new File(file1, "vfs");
file1 = new File(file1, "findFileByUrl");
@@ -165,14 +164,18 @@
}
}
+ @Bombed(user = "Roman Shevchenko", year = 2014, month = Calendar.JANUARY, day = 21)
public void testAsyncRefresh() throws Throwable {
+ final File tempDir = createTempDirectory();
+
final Throwable[] ex = {null};
boolean success = JobLauncher.getInstance().invokeConcurrentlyUnderProgress(
- Arrays.asList(new Object[8]), ProgressManager.getInstance().getProgressIndicator(), true, new Processor<Object>() {
+ Arrays.asList(new Object[8]),
+ ProgressManager.getInstance().getProgressIndicator(), true, new Processor<Object>() {
@Override
public boolean process(Object o) {
try {
- doAsyncRefreshTest();
+ doAsyncRefreshTest(tempDir);
}
catch (Throwable t) {
ex[0] = t;
@@ -180,21 +183,15 @@
return true;
}
});
+
if (ex[0] != null) throw ex[0];
- if (!success) System.out.println("!success");
+ if (!success) fail("!success");
}
- private void doAsyncRefreshTest() throws Exception {
+ private static void doAsyncRefreshTest(File temp) throws Exception {
final int N = 1000;
- final byte[] data = "xxx".getBytes();
+ final byte[] data = "xxx".getBytes("UTF-8");
- File temp = new WriteAction<File>() {
- @Override
- protected void run(Result<File> result) throws Throwable {
- File res = createTempDirectory();
- result.setResult(res);
- }
- }.execute().getResultObject();
LocalFileSystem fs = LocalFileSystem.getInstance();
VirtualFile vTemp = fs.findFileByIoFile(temp);
assertNotNull(vTemp);
@@ -222,7 +219,7 @@
for (int i = 0; i < N; i++) {
File file = new File(temp, i + ".txt");
- FileUtil.writeToFile(file, "xxx".getBytes());
+ FileUtil.writeToFile(file, data);
assertTrue(file.setLastModified(timestamp[i] - 2000));
long modified = file.lastModified();
assertTrue("File:" + file.getPath() + "; time:" + modified, timestamp[i] != modified);
@@ -238,11 +235,11 @@
latch.countDown();
}
});
+ TimeoutUtil.sleep(10);
}
- while (true) {
+ while (latch.getCount() > 0) {
latch.await(100, TimeUnit.MILLISECONDS);
UIUtil.pump();
- if (latch.getCount() == 0) break;
}
for (int i = 0; i < N; i++) {
@@ -298,6 +295,19 @@
assertTrue(vFile2.isDirectory());
}
+ public void testPresentableUrlSurvivesDeletion() throws IOException {
+ final VirtualFile file = createTempFile("txt", null, "content", Charset.defaultCharset());
+ String url = file.getPresentableUrl();
+ assertNotNull(url);
+ new WriteAction() {
+ @Override
+ protected void run(@NotNull Result result) throws Throwable {
+ file.delete(this);
+ }
+ }.execute();
+ assertEquals(url, file.getPresentableUrl());
+ }
+
public void testToUri() {
if (!SystemInfo.isWindows) {
assertEquals("file:///asd", VfsUtil.toUri(new File("/asd")).toASCIIString());
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java
index 744b493..0471db8 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/impl/VirtualFilePointerTest.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.
@@ -450,7 +450,7 @@
}
private static VirtualFile refreshAndFind(@NotNull final String url) {
- return ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
+ return WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
return VirtualFileManager.getInstance().refreshAndFindFileByUrl(url);
@@ -524,27 +524,27 @@
JobLauncher.getInstance().submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- VirtualFile file = pointer.getFile();
- if (file != null && !file.isValid()) {
- throw new IncorrectOperationException("I've caught it. I am that good");
- }
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ @Override
+ public void run() {
+ VirtualFile file = pointer.getFile();
+ if (file != null && !file.isValid()) {
+ throw new IncorrectOperationException("I've caught it. I am that good");
}
- });
+ }
+ });
}
}, new Consumer<Future>() {
- @Override
- public void consume(Future future) {
- try {
- future.get();
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
+ @Override
+ public void consume(Future future) {
+ try {
+ future.get();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ });
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java
index b3eedcd..f15f19d 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/FileWatcherTest.java
@@ -142,15 +142,15 @@
try {
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, file.getPath());
myAccept = true;
FileUtil.delete(file);
- assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, file.getPath());
myAccept = true;
FileUtil.writeToFile(file, "re-creation");
- assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, file.getPath());
}
finally {
unwatch(request);
@@ -167,20 +167,20 @@
File file = createTestFile("test.txt");
refresh(file);
- String watchRoot = file.getAbsolutePath().toUpperCase(Locale.US);
+ String watchRoot = file.getPath().toUpperCase(Locale.US);
LocalFileSystem.WatchRequest request = watch(new File(watchRoot));
try {
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, file.getPath());
myAccept = true;
FileUtil.delete(file);
- assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, file.getPath());
myAccept = true;
FileUtil.writeToFile(file, "re-creation");
- assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, file.getPath());
}
finally {
unwatch(request);
@@ -196,24 +196,24 @@
try {
myAccept = true;
File subDir = createTestDir(topDir, "sub");
- assertEvent(VFileCreateEvent.class, subDir.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, subDir.getPath());
refresh(subDir);
myAccept = true;
File file = createTestFile(subDir, "test.txt");
- assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, file.getPath());
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileContentChangeEvent.class, file.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, file.getPath());
myAccept = true;
FileUtil.delete(file);
- assertEvent(VFileDeleteEvent.class, file.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, file.getPath());
myAccept = true;
FileUtil.writeToFile(file, "re-creation");
- assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, file.getPath());
}
finally {
unwatch(request);
@@ -232,7 +232,7 @@
try {
myAccept = true;
FileUtil.writeToFile(watchedFile, "new content");
- assertEvent(VFileContentChangeEvent.class, watchedFile.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, watchedFile.getPath());
myTimeout = 10 * INTER_RESPONSE_DELAY;
myAccept = true;
@@ -263,7 +263,7 @@
FileUtil.writeToFile(watchedFile1, "new content");
FileUtil.writeToFile(watchedFile2, "new content");
FileUtil.writeToFile(unwatchedFile, "new content");
- assertEvent(VFileContentChangeEvent.class, watchedFile1.getAbsolutePath(), watchedFile2.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, watchedFile1.getPath(), watchedFile2.getPath());
}
finally {
unwatch(subRequest, topRequest);
@@ -281,12 +281,12 @@
try {
myAccept = true;
assertTrue(subDir.toString(), subDir.mkdir());
- assertEvent(VFileCreateEvent.class, subDir.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, subDir.getPath());
refresh(subDir);
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileCreateEvent.class, file.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, file.getPath());
}
finally {
unwatch(request);
@@ -331,7 +331,7 @@
FileUtil.writeToFile(fileInTopDir, "new content");
FileUtil.writeToFile(fileInSubDir, "new content");
FileUtil.writeToFile(fileInSideDir, "new content");
- assertEvent(VFileContentChangeEvent.class, fileInSubDir.getAbsolutePath(), fileInSideDir.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, fileInSubDir.getPath(), fileInSideDir.getPath());
LocalFileSystem.WatchRequest requestForTopDir = watch(topDir);
try {
@@ -339,7 +339,7 @@
FileUtil.writeToFile(fileInTopDir, "newer content");
FileUtil.writeToFile(fileInSubDir, "newer content");
FileUtil.writeToFile(fileInSideDir, "newer content");
- assertEvent(VFileContentChangeEvent.class, fileInTopDir.getAbsolutePath(), fileInSubDir.getAbsolutePath(), fileInSideDir.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, fileInTopDir.getPath(), fileInSubDir.getPath(), fileInSideDir.getPath());
}
finally {
unwatch(requestForTopDir);
@@ -349,13 +349,13 @@
FileUtil.writeToFile(fileInTopDir, "newest content");
FileUtil.writeToFile(fileInSubDir, "newest content");
FileUtil.writeToFile(fileInSideDir, "newest content");
- assertEvent(VFileContentChangeEvent.class, fileInSubDir.getAbsolutePath(), fileInSideDir.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, fileInSubDir.getPath(), fileInSideDir.getPath());
myAccept = true;
FileUtil.delete(fileInTopDir);
FileUtil.delete(fileInSubDir);
FileUtil.delete(fileInSideDir);
- assertEvent(VFileDeleteEvent.class, fileInTopDir.getAbsolutePath(), fileInSubDir.getAbsolutePath(), fileInSideDir.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, fileInTopDir.getPath(), fileInSubDir.getPath(), fileInSideDir.getPath());
}
finally {
unwatch(requestForSubDir, requestForSideDir);
@@ -366,7 +366,7 @@
/*
public void testSymlinkAboveWatchRoot() throws Exception {
final File topDir = FileUtil.createTempDirectory("top.", null);
- final File topLink = IoTestUtil.createTempLink(topDir.getAbsolutePath(), "link");
+ final File topLink = IoTestUtil.createTempLink(topDir.getPath(), "link");
final File subDir = FileUtil.createTempDirectory(topDir, "sub.", null);
final File file = FileUtil.createTempFile(subDir, "test.", ".txt");
final File fileLink = new File(new File(topLink, subDir.getName()), file.getName());
@@ -377,15 +377,15 @@
try {
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileContentChangeEvent.class, fileLink.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, fileLink.getPath());
myAccept = true;
FileUtil.delete(file);
- assertEvent(VFileDeleteEvent.class, fileLink.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, fileLink.getPath());
myAccept = true;
FileUtil.writeToFile(file, "re-creation");
- assertEvent(VFileCreateEvent.class, fileLink.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, fileLink.getPath());
}
finally {
myFileSystem.removeWatchedRoot(request);
@@ -399,7 +399,7 @@
final File file = FileUtil.createTempFile(targetDir, "test.", ".txt");
final File linkDir = FileUtil.createTempDirectory("link.", null);
final File link = new File(linkDir, "link");
- IoTestUtil.createTempLink(targetDir.getAbsolutePath(), link.getAbsolutePath());
+ IoTestUtil.createTempLink(targetDir.getPath(), link.getPath());
final File fileLink = new File(link, file.getName());
refresh(targetDir);
refresh(linkDir);
@@ -408,15 +408,15 @@
try {
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileContentChangeEvent.class, fileLink.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, fileLink.getPath());
myAccept = true;
FileUtil.delete(file);
- assertEvent(VFileDeleteEvent.class, fileLink.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, fileLink.getPath());
myAccept = true;
FileUtil.writeToFile(file, "re-creation");
- assertEvent(VFileCreateEvent.class, fileLink.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, fileLink.getPath());
}
finally {
myFileSystem.removeWatchedRoot(request);
@@ -435,7 +435,7 @@
File targetDir = createTestDir("top");
File subDir = createTestDir(targetDir, "sub");
File file = createTestFile(subDir, "test.txt");
- File rootFile = createSubst(targetDir.getAbsolutePath());
+ File rootFile = createSubst(targetDir.getPath());
VirtualDirectoryImpl.allowRootAccess(rootFile.getPath());
VirtualFile vfsRoot = myFileSystem.findFileByIoFile(rootFile);
@@ -451,13 +451,13 @@
try {
myAccept = true;
FileUtil.writeToFile(file, "new content");
- assertEvent(VFileContentChangeEvent.class, substFile.getAbsolutePath());
+ assertEvent(VFileContentChangeEvent.class, substFile.getPath());
LocalFileSystem.WatchRequest request2 = watch(targetDir);
try {
myAccept = true;
FileUtil.delete(file);
- assertEvent(VFileDeleteEvent.class, file.getAbsolutePath(), substFile.getAbsolutePath());
+ assertEvent(VFileDeleteEvent.class, file.getPath(), substFile.getPath());
}
finally {
unwatch(request2);
@@ -465,7 +465,7 @@
myAccept = true;
FileUtil.writeToFile(file, "re-creation");
- assertEvent(VFileCreateEvent.class, substFile.getAbsolutePath());
+ assertEvent(VFileCreateEvent.class, substFile.getPath());
}
finally {
unwatch(request);
@@ -725,7 +725,7 @@
getEvents("events to add watch " + watchFile, new Runnable() {
@Override
public void run() {
- request.set(myFileSystem.addRootToWatch(watchFile.getAbsolutePath(), recursive));
+ request.set(myFileSystem.addRootToWatch(watchFile.getPath(), recursive));
}
});
assertFalse(request.isNull());
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java
index 37122a7..e4a8d1e 100644
--- a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/LocalFileSystemTest.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.
@@ -27,7 +27,6 @@
import com.intellij.openapi.vfs.newvfs.events.VFileCreateEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileDeleteEvent;
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
-import com.intellij.openapi.vfs.newvfs.impl.FakeVirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VirtualDirectoryImpl;
import com.intellij.openapi.vfs.newvfs.impl.VirtualFileSystemEntry;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
@@ -46,6 +45,8 @@
import java.util.Locale;
public class LocalFileSystemTest extends PlatformLangTestCase {
+ private LocalFileSystem myFS;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -68,13 +69,21 @@
}
}
});
+
+ myFS = LocalFileSystem.getInstance();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ myFS = null;
+ super.tearDown();
}
public void testChildrenAccessedButNotCached() throws Exception {
File dir = createTempDirectory(false);
ManagingFS managingFS = ManagingFS.getInstance();
- VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile vFile = myFS.refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/'));
assertNotNull(vFile);
assertFalse(managingFS.areChildrenLoaded(vFile));
assertFalse(managingFS.wereChildrenAccessed(vFile));
@@ -91,12 +100,12 @@
boolean subChildCreated = subChild.createNewFile();
assertTrue(subChildCreated);
- VirtualFile childVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(child.getPath().replace(File.separatorChar, '/'));
+ VirtualFile childVFile = myFS.refreshAndFindFileByPath(child.getPath().replace(File.separatorChar, '/'));
assertNotNull(childVFile);
assertFalse(managingFS.areChildrenLoaded(vFile));
assertTrue(managingFS.wereChildrenAccessed(vFile));
- VirtualFile subdirVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile subdirVFile = myFS.refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/'));
assertNotNull(subdirVFile);
assertFalse(managingFS.areChildrenLoaded(subdirVFile));
assertFalse(managingFS.wereChildrenAccessed(subdirVFile));
@@ -109,7 +118,7 @@
assertFalse(managingFS.areChildrenLoaded(subdirVFile));
assertFalse(managingFS.wereChildrenAccessed(subdirVFile));
- VirtualFile subChildVFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(subChild.getPath().replace(File.separatorChar, '/'));
+ VirtualFile subChildVFile = myFS.refreshAndFindFileByPath(subChild.getPath().replace(File.separatorChar, '/'));
assertNotNull(subChildVFile);
assertTrue(managingFS.areChildrenLoaded(vFile));
assertTrue(managingFS.wereChildrenAccessed(vFile));
@@ -120,7 +129,7 @@
public void testRefreshAndFindFile() throws Exception {
File dir = createTempDirectory();
- VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile vFile = myFS.refreshAndFindFileByPath(dir.getPath().replace(File.separatorChar, '/'));
assertNotNull(vFile);
vFile.getChildren();
@@ -132,7 +141,7 @@
File subdir = new File(dir, "aaa");
assertTrue(subdir.mkdir());
- VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile file = myFS.refreshAndFindFileByPath(subdir.getPath().replace(File.separatorChar, '/'));
assertNotNull(file);
}
@@ -140,8 +149,8 @@
File fromDir = createTempDirectory();
File toDir = createTempDirectory();
- VirtualFile fromVDir = LocalFileSystem.getInstance().findFileByPath(fromDir.getPath().replace(File.separatorChar, '/'));
- VirtualFile toVDir = LocalFileSystem.getInstance().findFileByPath(toDir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile fromVDir = myFS.findFileByPath(fromDir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile toVDir = myFS.findFileByPath(toDir.getPath().replace(File.separatorChar, '/'));
assertNotNull(fromVDir);
assertNotNull(toVDir);
final VirtualFile fileToCopy = fromVDir.createChildData(this, "temp_file");
@@ -157,8 +166,8 @@
File fromDir = createTempDirectory();
File toDir = createTempDirectory();
- VirtualFile fromVDir = LocalFileSystem.getInstance().findFileByPath(fromDir.getPath().replace(File.separatorChar, '/'));
- VirtualFile toVDir = LocalFileSystem.getInstance().findFileByPath(toDir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile fromVDir = myFS.findFileByPath(fromDir.getPath().replace(File.separatorChar, '/'));
+ VirtualFile toVDir = myFS.findFileByPath(toDir.getPath().replace(File.separatorChar, '/'));
assertNotNull(fromVDir);
assertNotNull(toVDir);
final VirtualFile dirToCopy = fromVDir.createChildDirectory(this, "dir");
@@ -177,48 +186,54 @@
boolean created = childFile.createNewFile();
assert created || childFile.exists() : childFile;
- final VirtualFile dir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(dirFile);
+ final VirtualFile dir = myFS.refreshAndFindFileByIoFile(dirFile);
assertNotNull(dir);
- final VirtualFile child = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(childFile);
+ final VirtualFile child = myFS.refreshAndFindFileByIoFile(childFile);
assertNotNull(child);
assertTrue(childFile.delete());
}
public void testFindRoot() throws IOException {
- VirtualFile root = LocalFileSystem.getInstance().findFileByPath("wrong_path");
+ VirtualFile root = myFS.findFileByPath("wrong_path");
assertNull(root);
VirtualFile root2;
if (SystemInfo.isWindows) {
- root = LocalFileSystem.getInstance().findFileByPath("\\\\unit-133");
+ root = myFS.findFileByPath("\\\\unit-133");
assertNotNull(root);
- root2 = LocalFileSystem.getInstance().findFileByPath("//UNIT-133");
+ root2 = myFS.findFileByPath("//UNIT-133");
assertNotNull(root2);
assertEquals(String.valueOf(root2), root, root2);
RefreshQueue.getInstance().processSingleEvent(new VFileDeleteEvent(this, root, false));
- root = LocalFileSystem.getInstance().findFileByIoFile(new File("\\\\unit-133"));
+ root = myFS.findFileByIoFile(new File("\\\\unit-133"));
assertNotNull(root);
RefreshQueue.getInstance().processSingleEvent(new VFileDeleteEvent(this, root, false));
if (new File("c:").exists()) {
- root = LocalFileSystem.getInstance().findFileByPath("c:");
+ root = myFS.findFileByPath("c:");
assertNotNull(root);
assertEquals("C:/", root.getPath());
- root2 = LocalFileSystem.getInstance().findFileByPath("C:\\");
- assertEquals(String.valueOf(root2), root, root2);
+ root2 = myFS.findFileByPath("C:\\");
+ assertSame(String.valueOf(root), root, root2);
+
+ VirtualFileManager fm = VirtualFileManager.getInstance();
+ root = fm.findFileByUrl("file://C:/");
+ assertNotNull(root);
+ root2 = fm.findFileByUrl("file:///c:/");
+ assertSame(String.valueOf(root), root, root2);
}
}
else if (SystemInfo.isUnix) {
- root = LocalFileSystem.getInstance().findFileByPath("/");
+ root = myFS.findFileByPath("/");
assertNotNull(root);
assertEquals(root.getPath(), "/");
}
- root = LocalFileSystem.getInstance().findFileByPath("");
+ root = myFS.findFileByPath("");
assertNotNull(root);
File jarFile = IoTestUtil.createTestJar();
@@ -237,7 +252,7 @@
public void testFileLength() throws Exception {
File file = FileUtil.createTempFile("test", "txt");
FileUtil.writeToFile(file, "hello");
- VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ VirtualFile virtualFile = myFS.refreshAndFindFileByIoFile(file);
assertNotNull(virtualFile);
String s = VfsUtilCore.loadText(virtualFile);
assertEquals("hello", s);
@@ -266,12 +281,12 @@
assertTrue(targetFile.createNewFile());
final File hardLinkFile = IoTestUtil.createHardLink(targetFile.getAbsolutePath(), "hardLinkFile");
- final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(targetFile);
+ final VirtualFile file = myFS.refreshAndFindFileByIoFile(targetFile);
assertNotNull(file);
file.setBinaryContent("hello".getBytes("UTF-8"), 0, 0, requestor);
assertTrue(file.getLength() > 0);
- final VirtualFile check = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(hardLinkFile);
+ final VirtualFile check = myFS.refreshAndFindFileByIoFile(hardLinkFile);
assertNotNull(check);
assertEquals(file.getLength(), check.getLength());
assertEquals("hello", VfsUtilCore.loadText(check));
@@ -297,7 +312,7 @@
String parent = FileUtil.toSystemIndependentName(file.getParent());
VirtualDirectoryImpl.allowRootAccess(parent);
try {
- VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ VirtualFile virtualFile = myFS.refreshAndFindFileByIoFile(file);
assertNotNull(virtualFile);
NewVirtualFileSystem fs = (NewVirtualFileSystem)virtualFile.getFileSystem();
@@ -316,8 +331,7 @@
String content = "";
FileUtil.writeToFile(new File(testDir, "Foo.java"), content);
- LocalFileSystem local = LocalFileSystem.getInstance();
- VirtualFile virtualDir = local.findFileByIoFile(testDir);
+ VirtualFile virtualDir = myFS.findFileByIoFile(testDir);
assert virtualDir != null : testDir;
virtualDir.getChildren();
virtualDir.refresh(false, true);
@@ -341,7 +355,7 @@
public void testSingleFileRootRefresh() throws Exception {
File file = FileUtil.createTempFile("test.", ".txt");
- VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ VirtualFile virtualFile = myFS.refreshAndFindFileByIoFile(file);
assertNotNull(virtualFile);
assertTrue(virtualFile.exists());
assertTrue(virtualFile.isValid());
@@ -365,46 +379,26 @@
final File dir = FileUtil.createTempDirectory("test.", ".dir");
final File file = FileUtil.createTempFile(dir, "test\\", "\\txt", true);
- final VirtualFile vDir = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(dir);
+ final VirtualFile vDir = myFS.refreshAndFindFileByIoFile(dir);
assertNotNull(vDir);
assertEquals(0, vDir.getChildren().length);
((VirtualFileSystemEntry)vDir).markDirtyRecursively();
vDir.refresh(false, true);
- final VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ final VirtualFile vFile = myFS.refreshAndFindFileByIoFile(file);
assertNull(vFile);
}
- public void testGetAttributesConvertsToAbsolute() throws Exception {
- PersistentFS fs = PersistentFS.getInstance();
- LocalFileSystem lfs = LocalFileSystem.getInstance();
- NewVirtualFile fakeRoot = fs.findRoot("", lfs);
- assertNotNull(fakeRoot);
- File userDir = new File(System.getProperty("user.dir"));
- File[] files = userDir.listFiles();
- File fileToQuery;
- if (files != null && files.length != 0) {
- fileToQuery = files[0];
+ public void testNoMoreFakeRoots() throws Exception {
+ try {
+ PersistentFS.getInstance().findRoot("", myFS);
+ fail("should fail by assertion in PersistentFsImpl.findRoot()");
}
- else if (userDir.isDirectory()) {
- fileToQuery = FileUtil.createTempFile(userDir, getTestName(false), "", true);
- myFilesToDelete.add(fileToQuery);
+ catch (AssertionError e) {
+ String message = e.getMessage();
+ assertTrue(message, message.startsWith("Invalid root"));
}
- else {
- // can't test
- return;
- }
-
- FileAttributes attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, fileToQuery.getName()));
- assertNull(attributes);
-
- attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, "windows"));
- assertNull(attributes);
- attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, "usr"));
- assertNull(attributes);
- attributes = lfs.getAttributes(new FakeVirtualFile(fakeRoot, "Users"));
- assertNull(attributes);
}
public void testCopyToPointDir() throws Exception {
@@ -412,12 +406,11 @@
File sub = IoTestUtil.createTestDir(top, "sub");
File file = IoTestUtil.createTestFile(top, "file.txt", "hi there");
- LocalFileSystem lfs = LocalFileSystem.getInstance();
- VirtualFile topDir = lfs.refreshAndFindFileByIoFile(top);
+ VirtualFile topDir = myFS.refreshAndFindFileByIoFile(top);
assertNotNull(topDir);
- VirtualFile sourceFile = lfs.refreshAndFindFileByIoFile(file);
+ VirtualFile sourceFile = myFS.refreshAndFindFileByIoFile(file);
assertNotNull(sourceFile);
- VirtualFile parentDir = lfs.refreshAndFindFileByIoFile(sub);
+ VirtualFile parentDir = myFS.refreshAndFindFileByIoFile(sub);
assertNotNull(parentDir);
assertEquals(2, topDir.getChildren().length);
@@ -444,10 +437,9 @@
File file = IoTestUtil.createTestFile(top, "file.txt", "test");
File intermediate = new File(top, "_intermediate_");
- LocalFileSystem lfs = LocalFileSystem.getInstance();
- VirtualFile topDir = lfs.refreshAndFindFileByIoFile(top);
+ VirtualFile topDir = myFS.refreshAndFindFileByIoFile(top);
assertNotNull(topDir);
- VirtualFile sourceFile = lfs.refreshAndFindFileByIoFile(file);
+ VirtualFile sourceFile = myFS.refreshAndFindFileByIoFile(file);
assertNotNull(sourceFile);
String newName = StringUtil.capitalize(file.getName());
@@ -514,14 +506,13 @@
File target = IoTestUtil.createTestDir(top, "target");
File link = IoTestUtil.createSymLink(target.getPath(), top.getPath() + "/link");
- LocalFileSystem lfs = LocalFileSystem.getInstance();
- VirtualFile vTop = lfs.refreshAndFindFileByIoFile(top);
+ VirtualFile vTop = myFS.refreshAndFindFileByIoFile(top);
assertNotNull(vTop);
assertTrue(vTop.isValid());
- VirtualFile vTarget = lfs.refreshAndFindFileByIoFile(target);
+ VirtualFile vTarget = myFS.refreshAndFindFileByIoFile(target);
assertNotNull(vTarget);
assertTrue(vTarget.isValid());
- VirtualFile vLink = lfs.refreshAndFindFileByIoFile(link);
+ VirtualFile vLink = myFS.refreshAndFindFileByIoFile(link);
assertNotNull(vLink);
assertTrue(vLink.isValid());
assertTrue(vLink.isDirectory());
@@ -530,7 +521,7 @@
vTop.refresh(false, true);
assertFalse(vTarget.isValid());
assertFalse(vLink.isValid());
- vLink = lfs.refreshAndFindFileByIoFile(link);
+ vLink = myFS.refreshAndFindFileByIoFile(link);
assertNotNull(vLink);
assertTrue(vLink.isValid());
assertFalse(vLink.isDirectory());
@@ -538,7 +529,7 @@
FileUtil.createDirectory(target);
vTop.refresh(false, true);
assertFalse(vLink.isValid());
- vLink = lfs.refreshAndFindFileByIoFile(link);
+ vLink = myFS.refreshAndFindFileByIoFile(link);
assertNotNull(vLink);
assertTrue(vLink.isValid());
assertTrue(vLink.isDirectory());
diff --git a/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/PersistentFsTest.java b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/PersistentFsTest.java
new file mode 100644
index 0000000..5f1be61
--- /dev/null
+++ b/platform/platform-tests/testSrc/com/intellij/openapi/vfs/local/PersistentFsTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.vfs.local;
+
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.IoTestUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
+import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
+import com.intellij.testFramework.PlatformLangTestCase;
+
+import java.io.File;
+
+public class PersistentFsTest extends PlatformLangTestCase {
+ private PersistentFS myFs;
+ private LocalFileSystem myLocalFs;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myFs = PersistentFS.getInstance();
+ myLocalFs = LocalFileSystem.getInstance();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ myLocalFs = null;
+ myFs = null;
+ super.tearDown();
+ }
+
+ public void testAccessingFileByID() throws Exception {
+ File dir = createTempDirectory();
+ File file = new File(dir, "test.txt");
+ assertTrue(file.createNewFile());
+
+ VirtualFile vFile = myLocalFs.refreshAndFindFileByIoFile(file);
+ assertNotNull(vFile);
+
+ int id = ((VirtualFileWithId)vFile).getId();
+ assertSame(vFile, myFs.findFileById(id));
+
+ vFile.delete(this);
+ assertNull(myFs.findFileById(id));
+ }
+
+ public void testFindRootShouldNotBeFooledByRelativePath() throws Exception {
+ File tmp = createTempDirectory();
+ File x = new File(tmp, "x.jar");
+ assertTrue(x.createNewFile());
+
+ VirtualFile vx = myLocalFs.refreshAndFindFileByIoFile(x);
+ assertNotNull(vx);
+
+ JarFileSystem jfs = JarFileSystem.getInstance();
+ VirtualFile root = jfs.getJarRootForLocalFile(vx);
+ String path = vx.getPath() + "/../" + vx.getName() + JarFileSystem.JAR_SEPARATOR;
+ assertSame(myFs.findRoot(path, jfs), root);
+ }
+
+ public void testDeleteSubstRoots() throws Exception {
+ if (!SystemInfo.isWindows) return;
+
+ File tempDirectory = FileUtil.createTempDirectory(getTestName(false), null);
+ File substRoot = IoTestUtil.createSubst(tempDirectory.getPath());
+ VirtualFile subst = myLocalFs.refreshAndFindFileByIoFile(substRoot);
+ assertNotNull(subst);
+
+ try {
+ final File[] children = substRoot.listFiles();
+ assertNotNull(children);
+ }
+ finally {
+ IoTestUtil.deleteSubst(substRoot.getPath());
+ }
+ subst.refresh(false, true);
+
+ VirtualFile[] roots = myFs.getRoots(myLocalFs);
+ for (VirtualFile root : roots) {
+ String rootPath = root.getPath();
+ String prefix = StringUtil.commonPrefix(rootPath, substRoot.getPath());
+ assertEmpty(prefix);
+ }
+ }
+
+ public void testLocalRoots() {
+ VirtualFile tempRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
+ assertNotNull(tempRoot);
+
+ VirtualFile[] roots = myFs.getLocalRoots();
+ for (VirtualFile root : roots) {
+ assertTrue("root=" + root, root.isInLocalFileSystem());
+ VirtualFileSystem fs = root.getFileSystem();
+ assertTrue("fs=" + fs, fs instanceof LocalFileSystem);
+ assertFalse("fs=" + fs, fs instanceof TempFileSystem);
+ }
+ }
+}
diff --git a/platform/platform-tests/testSrc/com/intellij/psi/TextBlockTest.java b/platform/platform-tests/testSrc/com/intellij/psi/TextBlockTest.java
deleted file mode 100644
index 0498c37..0000000
--- a/platform/platform-tests/testSrc/com/intellij/psi/TextBlockTest.java
+++ /dev/null
@@ -1,193 +0,0 @@
-package com.intellij.psi;
-
-import com.intellij.mock.MockDocument;
-import com.intellij.openapi.editor.impl.event.DocumentEventImpl;
-import com.intellij.psi.impl.TextBlock;
-import junit.framework.TestCase;
-
-public class TextBlockTest extends TestCase {
- private TextBlock myTextBlock;
- private MockDocument myDocument;
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- myDocument = new MockDocument();
- myTextBlock = new TextBlock();
- }
-
- public void testIsEmpty_AfterCreate() throws Exception {
- assertTrue(myTextBlock.isEmpty());
- }
-
- public void testTextInserted_Once() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(13, myTextBlock.getTextEndOffset());
- assertEquals(10, myTextBlock.getPsiEndOffset());
- }
-
- public void testReset() throws Exception {
- assertTrue(myTextBlock.isEmpty());
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
- assertTrue(!myTextBlock.isEmpty());
- myTextBlock.clear();
- assertTrue(myTextBlock.isEmpty());
- }
-
- public void testTextInserted_SecondNonAdjFragmentsAfter() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 20, "", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(23, myTextBlock.getTextEndOffset());
- assertEquals(17, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextInserted_SecondNonAdjFragmentsBefore() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 5, "", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(5, myTextBlock.getStartOffset());
- assertEquals(16, myTextBlock.getTextEndOffset());
- assertEquals(10, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextInserted_SecondAdjFragmentsAfter() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 13, "", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(16, myTextBlock.getTextEndOffset());
- assertEquals(10, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextInserted_SecondAdjFragmentsBefore() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(16, myTextBlock.getTextEndOffset());
- assertEquals(10, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextDeleted_Once() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(10, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextDeleted_SecondNonAdjFragmentAfter() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 17, "xxx", "", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(17, myTextBlock.getTextEndOffset());
- assertEquals(23, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextDeleted_SecondNonAdjFragmentBefore() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 5, "xxx", "", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(5, myTextBlock.getStartOffset());
- assertEquals(7, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextDeleted_SecondAdjFragment() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(10, myTextBlock.getTextEndOffset());
- assertEquals(16, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToTheSameSize_Once1() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(13, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToTheSameSize_Once2() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 0, "xxx", "yyy", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(0, myTextBlock.getStartOffset());
- assertEquals(3, myTextBlock.getTextEndOffset());
- assertEquals(3, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToTheSameSize_SecondNonAdjFragmentAfter() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 20, "xxx", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(23, myTextBlock.getTextEndOffset());
- assertEquals(23, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToTheSameSize_SecondNonAdjFragmentBefore() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 5, "xxx", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(5, myTextBlock.getStartOffset());
- assertEquals(13, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToTheSameSize_SecondNonFragmentAfter() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 13, "xxx", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(16, myTextBlock.getTextEndOffset());
- assertEquals(16, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToTheSameSize_SecondNonFragmentBefore() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xxx", 1, false));
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 7, "xxx", "xxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(7, myTextBlock.getStartOffset());
- assertEquals(13, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToLessSize() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(12, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-
- public void testTextChanged_ChangedToGreaterSize() throws Exception {
- myTextBlock.documentChanged(new DocumentEventImpl(myDocument, 10, "xxx", "xxxx", 1, false));
-
- assertTrue(!myTextBlock.isEmpty());
- assertEquals(10, myTextBlock.getStartOffset());
- assertEquals(14, myTextBlock.getTextEndOffset());
- assertEquals(13, myTextBlock.getPsiEndOffset());
- }
-}
diff --git a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilMatchingTest.groovy b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilMatchingTest.groovy
index e53770a..ec40982 100644
--- a/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilMatchingTest.groovy
+++ b/platform/platform-tests/testSrc/com/intellij/psi/util/NameUtilMatchingTest.groovy
@@ -26,6 +26,7 @@
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.text.Matcher
import groovy.transform.CompileStatic
+import junit.framework.Assert
import org.jetbrains.annotations.NonNls
/**
* @author max
@@ -120,7 +121,8 @@
assertDoesntMatch("ARS.j", "activity_report_summary.xml");
assertDoesntMatch("ARS.j", "activity_report_summary_justsometingwrong.xml");
- assertDoesntMatch("foo.goo", "foo.bar.goo");
+ assertMatches("foo.goo", "foo.bar.goo");
+ assertDoesntMatch("*.ico", "sm.th.iks.concierge");
}
public void testSpaceForAnyWordsInBetween() {
@@ -177,7 +179,10 @@
assertMatches("ja", "jquery.autocomplete.js");
assertDoesntMatch("ja.js", "jquery.autocomplete.js");
assertMatches("jajs", "jquery.autocomplete.js");
+ assertMatches("jjs", "jquery.autocomplete.js");
+ assertMatches("j.js", "jquery.autocomplete.js");
assertDoesntMatch("j.ajs", "jquery.autocomplete.js");
+ assertMatches("oracle.bnf", "oracle-11.2.bnf");
}
public void testNoExtension() {
@@ -636,11 +641,11 @@
public void run() {
for (int i = 0; i < 100000; i++) {
for (MinusculeMatcher matcher : matching) {
- assertTrue(matcher.toString(), matcher.matches(longName));
+ Assert.assertTrue(matcher.toString(), matcher.matches(longName));
matcher.matchingDegree(longName);
}
for (MinusculeMatcher matcher : nonMatching) {
- assertFalse(matcher.toString(), matcher.matches(longName));
+ Assert.assertFalse(matcher.toString(), matcher.matches(longName));
}
}
}
diff --git a/platform/platform-tests/testSrc/com/intellij/ui/FinderRecursivePanelSelectionUpdateTest.java b/platform/platform-tests/testSrc/com/intellij/ui/FinderRecursivePanelSelectionUpdateTest.java
index ce6c138..86464a8 100644
--- a/platform/platform-tests/testSrc/com/intellij/ui/FinderRecursivePanelSelectionUpdateTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/ui/FinderRecursivePanelSelectionUpdateTest.java
@@ -18,6 +18,7 @@
import com.intellij.idea.Bombed;
import com.intellij.openapi.project.Project;
import com.intellij.testFramework.PlatformTestCase;
+import com.intellij.testFramework.SkipInHeadlessEnvironment;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,6 +28,7 @@
import java.util.Calendar;
import java.util.List;
+@SkipInHeadlessEnvironment
public class FinderRecursivePanelSelectionUpdateTest extends PlatformTestCase {
@Bombed(year = 2014, month = Calendar.MARCH, day = 1, user = "Yann Cebron")
@@ -53,7 +55,6 @@
disposeOnTearDown(panel_0);
panel_0.setTestSelectedIndex(0);
- //panel_0.updateRightComponent(true);
StringFinderRecursivePanel panel_1 = (StringFinderRecursivePanel)panel_0.getSecondComponent();
panel_1.setTestSelectedIndex(1);
diff --git a/platform/platform-tests/testSrc/com/intellij/util/graph/ChunkGraphTest.java b/platform/platform-tests/testSrc/com/intellij/util/graph/ChunkGraphTest.java
index ff28347..9d70e36 100644
--- a/platform/platform-tests/testSrc/com/intellij/util/graph/ChunkGraphTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/util/graph/ChunkGraphTest.java
@@ -1,6 +1,17 @@
/*
- * Copyright (c) 2000-2004 by JetBrains s.r.o. All Rights Reserved.
- * Use is subject to license terms.
+ * Copyright 2000-2014 JetBrains s.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.graph;
diff --git a/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java b/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java
index 71b8809..c7d816d 100644
--- a/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/util/graph/KShortestPathsFinderTest.java
@@ -136,7 +136,29 @@
graph.put("f", "t");
graph.put("t", "");
doTest(graph, "sabct", "sadeft", "sabdeft", "sabcdeft");
+ }
+ public void testBigHeap() {
+ final Map<String, String> graph = new HashMap<String, String>();
+ graph.put("s", "lo");
+ graph.put("a", "tb");
+ graph.put("b", "t");
+ graph.put("c", "ad");
+ graph.put("d", "e");
+ graph.put("e", "b");
+ graph.put("f", "cg");
+ graph.put("g", "h");
+ graph.put("h", "d");
+ graph.put("i", "fj");
+ graph.put("j", "k");
+ graph.put("k", "g");
+ graph.put("l", "im");
+ graph.put("m", "n");
+ graph.put("n", "j");
+ graph.put("o", "p");
+ graph.put("p", "m");
+ graph.put("t", "");
+ doTest(graph, "slifcat", "slifcabt", "slifcdebt", "slifghdebt", "slijkghdebt", "slmnjkghdebt", "sopmnjkghdebt");
}
private static void doTest(Map<String, String> graph, String... expectedPaths) {
diff --git a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentFSTest.java b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentFSTest.java
deleted file mode 100644
index 8aaef1e..0000000
--- a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentFSTest.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.util.io;
-
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.io.IoTestUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.JarFileSystem;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.VirtualFileWithId;
-import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
-import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
-import com.intellij.testFramework.PlatformTestCase;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-
-public class PersistentFSTest extends PlatformTestCase {
- @Override
- public void setUp() throws Exception {
- initPlatformLangPrefix();
- super.setUp();
- }
-
- public void testAccessingFileByID() throws Exception {
- File dir = createTempDirectory();
- File file = new File(dir, "test.txt");
- assertTrue(file.createNewFile());
-
- VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
- assertNotNull(vFile);
-
- int id = ((VirtualFileWithId)vFile).getId();
-
- assertSame(vFile, PersistentFS.getInstance().findFileById(id));
- vFile.delete(this);
-
- assertNull(PersistentFS.getInstance().findFileById(id));
- }
-
- public void testListChildrenOfTheRootOfTheRoot() {
- PersistentFS fs = PersistentFS.getInstance();
- NewVirtualFile fakeRoot = fs.findRoot("", LocalFileSystem.getInstance());
- assertNotNull(fakeRoot);
- int users = fs.getId(fakeRoot, "Users", LocalFileSystem.getInstance());
- assertEquals(0, users);
- users = fs.getId(fakeRoot, "usr", LocalFileSystem.getInstance());
- assertEquals(0, users);
- int win = fs.getId(fakeRoot, "Windows", LocalFileSystem.getInstance());
- assertEquals(0, win);
-
- VirtualFile[] roots = fs.getRoots(LocalFileSystem.getInstance());
- for (VirtualFile root : roots) {
- int rid = fs.getId(fakeRoot, root.getName(), LocalFileSystem.getInstance());
- assertTrue(root.getPath()+"; Roots:"+ Arrays.toString(roots), 0 != rid);
- }
-
- NewVirtualFile c = fakeRoot.refreshAndFindChild("Users");
- assertNull(c);
- c = fakeRoot.refreshAndFindChild("Users");
- assertNull(c);
- c = fakeRoot.refreshAndFindChild("Windows");
- assertNull(c);
- c = fakeRoot.refreshAndFindChild("Windows");
- assertNull(c);
- }
-
- public void testFindRootShouldNotBeFooledByRelativePath() throws IOException {
- File tmp = createTempDirectory();
- File x = new File(tmp, "x.jar");
- x.createNewFile();
- LocalFileSystem lfs = LocalFileSystem.getInstance();
- VirtualFile vx = lfs.refreshAndFindFileByIoFile(x);
- assertNotNull(vx);
- JarFileSystem jfs = JarFileSystem.getInstance();
- VirtualFile root = jfs.getJarRootForLocalFile(vx);
-
- PersistentFS fs = PersistentFS.getInstance();
-
- String path = vx.getPath() + "/../" + vx.getName() + JarFileSystem.JAR_SEPARATOR;
- NewVirtualFile root1 = fs.findRoot(path, jfs);
-
- assertSame(root1, root);
- }
-
- public void testDeleteSubstRoots() throws IOException, InterruptedException {
- if (!SystemInfo.isWindows) return;
-
- File tempDirectory = FileUtil.createTempDirectory(getTestName(false), null);
- File substRoot = IoTestUtil.createSubst(tempDirectory.getPath());
- VirtualFile subst = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(substRoot);
- assertNotNull(subst);
- try {
- final File[] children = substRoot.listFiles();
- assertNotNull(children);
- }
- finally {
- IoTestUtil.deleteSubst(substRoot.getPath());
- }
- subst.refresh(false, true);
- PersistentFS fs = PersistentFS.getInstance();
-
- VirtualFile[] roots = fs.getRoots(LocalFileSystem.getInstance());
- for (VirtualFile root : roots) {
- String rootPath = root.getPath();
- String prefix = StringUtil.commonPrefix(rootPath, substRoot.getPath());
- assertEmpty(prefix);
- }
- }
-}
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 1bb5345..f40716b 100644
--- a/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java
+++ b/platform/platform-tests/testSrc/com/intellij/util/io/PersistentMapTest.java
@@ -5,15 +5,13 @@
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.IntObjectCache;
-import com.intellij.util.io.storage.Storage;
+import com.intellij.util.io.storage.AbstractStorage;
import gnu.trove.THashSet;
import junit.framework.TestCase;
import java.io.*;
import java.util.*;
-import static com.intellij.util.io.StringEnumeratorTest.createRandomString;
-
/**
* @author Eugene Zhuravlev
* Date: Dec 19, 2007
@@ -300,7 +298,7 @@
myMap.close();
System.out.printf("File size = %d bytes\n", myFile.length());
System.out
- .printf("Data file size = %d bytes\n", new File(myDataFile.getParentFile(), myDataFile.getName() + Storage.DATA_EXTENSION).length());
+ .printf("Data file size = %d bytes\n", new File(myDataFile.getParentFile(), myDataFile.getName() + AbstractStorage.DATA_EXTENSION).length());
}
public void testPerformance1() throws IOException {
@@ -335,7 +333,7 @@
myMap.close();
System.out.printf("File size = %d bytes\n", myFile.length());
System.out
- .printf("Data file size = %d bytes\n", new File(myDataFile.getParentFile(), myDataFile.getName() + Storage.DATA_EXTENSION).length());
+ .printf("Data file size = %d bytes\n", new File(myDataFile.getParentFile(), myDataFile.getName() + AbstractStorage.DATA_EXTENSION).length());
}
private static final boolean DO_SLOW_TEST = false;
diff --git a/platform/projectModel-api/src/com/intellij/openapi/project/ProjectBundle.java b/platform/projectModel-api/src/com/intellij/openapi/project/ProjectBundle.java
index 8bdea29..5e1f24a 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/project/ProjectBundle.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/project/ProjectBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,20 +25,19 @@
import java.util.ResourceBundle;
public class ProjectBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.ProjectBundle";
private ProjectBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModel.java b/platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModel.java
index bcbe831..c3fa2eb 100644
--- a/platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModel.java
+++ b/platform/projectModel-api/src/com/intellij/openapi/roots/ModuleRootModel.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.
@@ -58,61 +58,62 @@
@NotNull
OrderEntry[] getOrderEntries();
- /*
- * Returns the JDK used by the module.
- *
- * @return either module-specific or inherited JDK
- * @see #isSdkInherited()
- */
- @Nullable
- Sdk getSdk();
-
- /**
- * Returns <code>true</code> if JDK for this module is inherited from a project.
- *
- * @return true if the JDK is inherited, false otherwise
- * @see ProjectRootManager#getProjectSdk()
- * @see ProjectRootManager#setProjectSdk(com.intellij.openapi.projectRoots.Sdk)
- */
- boolean isSdkInherited();
-
-
- /**
+ /*
+ * Returns the SDK used by the module.
+ *
+ * @return either module-specific or inherited SDK
+ * @see #isSdkInherited()
+ */
+ @Nullable
+ Sdk getSdk();
/**
- * Returns an array of content roots from all content entries. A helper method.
+ * Returns <code>true</code> if SDK for this module is inherited from a project.
+ *
+ * @return true if the SDK is inherited, false otherwise
+ * @see ProjectRootManager#getProjectSdk()
+ * @see ProjectRootManager#setProjectSdk(com.intellij.openapi.projectRoots.Sdk)
+ */
+ boolean isSdkInherited();
+
+ /**
+ * Returns an array of content roots from all content entries.
*
* @return the array of content roots.
* @see #getContentEntries()
*/
- @NotNull VirtualFile[] getContentRoots();
+ @NotNull
+ VirtualFile[] getContentRoots();
/**
- * Returns an array of content root urls from all content entries. A helper method.
+ * Returns an array of content root urls from all content entries.
*
* @return the array of content root URLs.
* @see #getContentEntries()
*/
- @NotNull String[] getContentRootUrls();
+ @NotNull
+ String[] getContentRootUrls();
/**
- * Returns an array of exclude roots from all content entries. A helper method.
+ * Returns an array of exclude roots from all content entries.
*
* @return the array of excluded roots.
* @see #getContentEntries()
*/
- @NotNull VirtualFile[] getExcludeRoots();
+ @NotNull
+ VirtualFile[] getExcludeRoots();
/**
- * Returns an array of exclude root urls from all content entries. A helper method.
+ * Returns an array of exclude root urls from all content entries.
*
* @return the array of excluded root URLs.
* @see #getContentEntries()
*/
- @NotNull String[] getExcludeRootUrls();
+ @NotNull
+ String[] getExcludeRootUrls();
/**
- * Returns an array of source roots from all content entries. A helper method.
+ * Returns an array of source roots from all content entries.
*
* @return the array of source roots.
* @see #getContentEntries()
@@ -122,7 +123,7 @@
VirtualFile[] getSourceRoots();
/**
- * Returns an array of source roots from all content entries. A helper method.
+ * Returns an array of source roots from all content entries.
*
* @param includingTests determines whether test source roots should be included in the result
* @return the array of source roots.
@@ -133,7 +134,8 @@
VirtualFile[] getSourceRoots(boolean includingTests);
/**
- * Return a list of source roots of the specified type
+ * Return a list of source roots of the specified type.
+ *
* @param rootType type of source roots
* @return list of source roots
*/
@@ -141,7 +143,7 @@
List<VirtualFile> getSourceRoots(@NotNull JpsModuleSourceRootType<?> rootType);
/**
- * Return a list of source roots which types belong to the specified set
+ * Return a list of source roots which types belong to the specified set.
*
* @param rootTypes types of source roots
* @return list of source roots
@@ -150,23 +152,25 @@
List<VirtualFile> getSourceRoots(@NotNull Set<? extends JpsModuleSourceRootType<?>> rootTypes);
/**
- * Returns an array of source root urls from all content entries. A helper method.
+ * Returns an array of source root urls from all content entries.
*
* @return the array of source root URLs.
* @see #getContentEntries()
* @see #getSourceRootUrls(boolean)
*/
- @NotNull String[] getSourceRootUrls();
+ @NotNull
+ String[] getSourceRootUrls();
/**
- * Returns an array of source root urls from all content entries. A helper method.
+ * Returns an array of source root urls from all content entries.
*
* @param includingTests determines whether test source root urls should be included in the result
* @return the array of source root URLs.
* @see #getContentEntries()
* @since 10.0
*/
- @NotNull String[] getSourceRootUrls(boolean includingTests);
+ @NotNull
+ String[] getSourceRootUrls(boolean includingTests);
/**
* Passes all order entries in the module to the specified visitor.
@@ -180,7 +184,7 @@
/**
* Returns {@link OrderEnumerator} instance which can be used to process order entries of the module (with or without dependencies) and
- * collect classes or source roots
+ * collect classes or source roots.
*
* @return {@link OrderEnumerator} instance
* @since 10.0
@@ -193,7 +197,8 @@
*
* @return the list of module names this module depends on.
*/
- @NotNull String[] getDependencyModuleNames();
+ @NotNull
+ String[] getDependencyModuleNames();
<T> T getModuleExtension(Class<T> klass);
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java
index d90f2d5..177aecd 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java
@@ -40,7 +40,8 @@
import java.util.*;
public class BasePathMacroManager extends PathMacroManager {
- private static CompositePathMacroFilter ourFilter = new CompositePathMacroFilter(Extensions.getExtensions(PathMacrosCollector.MACRO_FILTER_EXTENSION_POINT_NAME));
+ private static final CompositePathMacroFilter ourFilter = new CompositePathMacroFilter(Extensions.getExtensions(PathMacrosCollector.MACRO_FILTER_EXTENSION_POINT_NAME));
+
private PathMacrosImpl myPathMacros;
public BasePathMacroManager(@Nullable PathMacros pathMacros) {
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 c8ac87e..6041f61 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
@@ -43,11 +43,15 @@
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
import com.intellij.util.containers.StringInterner;
+import com.intellij.util.containers.hash.EqualityPolicy;
+import com.intellij.util.containers.hash.LinkedHashMap;
import com.intellij.util.graph.CachingSemiGraph;
import com.intellij.util.graph.DFSTBuilder;
import com.intellij.util.graph.Graph;
import com.intellij.util.graph.GraphGenerator;
+import com.intellij.util.io.URLUtil;
import com.intellij.util.messages.MessageBus;
+import com.intellij.util.text.FilePathHashingStrategy;
import gnu.trove.THashMap;
import gnu.trove.TObjectHashingStrategy;
import org.jdom.Element;
@@ -367,7 +371,7 @@
public final void writeExternal(Element parentElement) {
Element moduleElement = new Element(ELEMENT_MODULE);
final String moduleFilePath = getModuleFilePath();
- final String url = VirtualFileManager.constructUrl(StandardFileSystems.FILE_PROTOCOL, moduleFilePath);
+ final String url = VirtualFileManager.constructUrl(URLUtil.FILE_PROTOCOL, moduleFilePath);
moduleElement.setAttribute(ATTRIBUTE_FILEURL, url);
// [dsl] support for older builds
moduleElement.setAttribute(ATTRIBUTE_FILEPATH, moduleFilePath);
@@ -602,7 +606,7 @@
protected abstract ModuleEx createAndLoadModule(String filePath) throws IOException;
class ModuleModelImpl implements ModifiableModuleModel {
- final Map<String, Module> myPathToModule = new LinkedHashMap<String, Module>();
+ final Map<String, Module> myPathToModule = new LinkedHashMap<String, Module>(new EqualityPolicy.ByHashingStrategy<String>(FilePathHashingStrategy.create()));
private Module[] myModulesCache;
private final List<Module> myModulesToDispose = new ArrayList<Module>();
@@ -726,13 +730,7 @@
@Nullable
private ModuleEx getModuleByFilePath(String filePath) {
- final Collection<Module> modules = myPathToModule.values();
- for (Module module : modules) {
- if (FileUtil.pathsEqual(filePath, module.getModuleFilePath())) {
- return (ModuleEx)module;
- }
- }
- return null;
+ return (ModuleEx)myPathToModule.get(filePath);
}
@Override
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java
index 6b7826e..999add6 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/projectRoots/impl/SimpleProjectRoot.java
@@ -20,11 +20,11 @@
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.PathUtil;
+import com.intellij.util.io.URLUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -61,8 +61,8 @@
@NotNull
public String getPresentableString() {
String path = VirtualFileManager.extractPath(myUrl);
- if (path.endsWith(StandardFileSystems.JAR_SEPARATOR)) {
- path = path.substring(0, path.length() - StandardFileSystems.JAR_SEPARATOR.length());
+ if (path.endsWith(URLUtil.JAR_SEPARATOR)) {
+ path = path.substring(0, path.length() - URLUtil.JAR_SEPARATOR.length());
}
return path.replace('/', File.separatorChar);
}
@@ -112,7 +112,7 @@
}
private boolean canHaveChildren() {
- return myFile.getFileSystem().getProtocol().equals(StandardFileSystems.HTTP_PROTOCOL) || myFile.isDirectory();
+ return myFile.getFileSystem().getProtocol().equals(URLUtil.HTTP_PROTOCOL) || myFile.isDirectory();
}
public String getUrl() {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
index 25b4192..4298046 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/DirectoryInfo.java
@@ -56,7 +56,7 @@
return new DirectoryInfo(null, null, null, null, (byte)0, null);
}
- private DirectoryInfo(Module module,
+ DirectoryInfo(Module module,
VirtualFile contentRoot,
VirtualFile sourceRoot,
VirtualFile libraryClassRoot,
@@ -105,6 +105,7 @@
", libraryClassRoot=" + getLibraryClassRoot() +
", contentRoot=" + getContentRoot() +
", sourceRoot=" + getSourceRoot() +
+ ", orderEntries=" + Arrays.toString(orderEntries) +
"}";
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java
index 3d3b285..0a6047a 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ModuleRootManagerImpl.java
@@ -52,6 +52,7 @@
private RootModelImpl myRootModel;
private final ModuleFileIndexImpl myFileIndex;
private boolean myIsDisposed = false;
+ private boolean myLoaded = false;
private boolean isModuleAdded = false;
private final OrderRootsCache myOrderRootsCache;
private final Map<RootModelImpl, Throwable> myModelCreations = new THashMap<RootModelImpl, Throwable>();
@@ -344,7 +345,8 @@
}
public void loadState(ModuleRootManagerState object) {
- loadState(object, myRootModel != null);
+ loadState(object, myLoaded || isModuleAdded);
+ myLoaded = true;
}
protected void loadState(ModuleRootManagerState object, boolean throwEvent) {
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
index 25d9b5b..057f6b0 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectFileIndexFacade.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.roots.FileIndexFacade;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -86,4 +87,10 @@
childDir = childDir.getParent();
}
}
+
+ @NotNull
+ @Override
+ public ModificationTracker getRootModificationTracker() {
+ return ProjectRootManager.getInstance(myProject);
+ }
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
index f937c6d..42c2634 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/ProjectRootManagerImpl.java
@@ -33,7 +33,6 @@
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
-import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiManager;
@@ -42,6 +41,7 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.HashSet;
+import com.intellij.util.io.URLUtil;
import com.intellij.util.messages.MessageBusConnection;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
@@ -318,8 +318,11 @@
@Override
public void mergeRootsChangesDuring(@NotNull Runnable runnable) {
if (getBatchSession(false).myBatchLevel == 0 && !myMergedCallStarted) {
- LOG.assertTrue(myRootsChangesDepth == 0,
- "Merged rootsChanged not allowed inside rootsChanged, rootsChanged level == " + myRootsChangesDepth);
+ if (myRootsChangesDepth != 0) {
+ int depth = myRootsChangesDepth;
+ myRootsChangesDepth = 0;
+ LOG.error("Merged rootsChanged not allowed inside rootsChanged, rootsChanged level == " + depth);
+ }
myMergedCallStarted = true;
myMergedCallHasRootChange = false;
try {
@@ -408,6 +411,10 @@
myRootsChangesDepth--;
if (myRootsChangesDepth > 0) return false;
+ if (myRootsChangesDepth < 0) {
+ LOG.info("Restoring from roots change start/finish mismatch: ", new Throwable());
+ myRootsChangesDepth = 0;
+ }
clearScopesCaches();
@@ -441,7 +448,7 @@
public static String extractLocalPath(final String url) {
final String path = VfsUtilCore.urlToPath(url);
- final int jarSeparatorIndex = path.indexOf(StandardFileSystems.JAR_SEPARATOR);
+ final int jarSeparatorIndex = path.indexOf(URLUtil.JAR_SEPARATOR);
if (jarSeparatorIndex > 0) {
return path.substring(0, jarSeparatorIndex);
}
diff --git a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java
index c223636..3f811b6 100644
--- a/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java
+++ b/platform/projectModel-impl/src/com/intellij/openapi/roots/impl/PushedFilePropertiesUpdater.java
@@ -20,11 +20,9 @@
package com.intellij.openapi.roots.impl;
import com.intellij.ProjectTopics;
-import com.intellij.diagnostic.PluginException;
-import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionException;
import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -193,8 +191,7 @@
}
}
catch (AbstractMethodError ame) { // acceptsDirectory is missed
- PluginId pluginId = pusher != null ? PluginManagerCore.getPluginByClassName(pusher.getClass().getName()) : null;
- if (pluginId != null) throw new PluginException("Incompatible plugin", ame, pluginId);
+ if (pusher != null) throw new ExtensionException(pusher.getClass());
throw ame;
}
}
diff --git a/platform/projectModel-impl/src/messages/ProjectBundle.properties b/platform/projectModel-impl/src/messages/ProjectBundle.properties
index 60001e6..4ae4330 100644
--- a/platform/projectModel-impl/src/messages/ProjectBundle.properties
+++ b/platform/projectModel-impl/src/messages/ProjectBundle.properties
@@ -188,7 +188,7 @@
library.configure.module.title=Configure Module Library
library.configure.project.title=Configure Project Libraries
library.configure.global.title=Configure Global Libraries
-library.detach.action=Detach
+library.remove.action=Remove
library.root.node=Root
library.sources.node=Sources
project.order.entry.project=<Project>
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudApplication.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudApplication.java
new file mode 100644
index 0000000..7e55765
--- /dev/null
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudApplication.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.remoteServer.agent.util;
+
+/**
+ * @author michael.golubev
+ */
+public interface CloudApplication {
+
+ String getName();
+
+ String getWebUrl();
+}
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgentDeployment.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgentDeployment.java
index d349b95..cbf0d9d 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgentDeployment.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitAgentDeployment.java
@@ -25,4 +25,6 @@
CloudGitApplication findApplication();
void deleteApplication();
+
+ CloudGitApplication findApplication4Repository(String[] repositoryUrls);
}
diff --git a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitApplication.java b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitApplication.java
index 9e8513d..a258bc6 100644
--- a/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitApplication.java
+++ b/platform/remote-servers/agent-rt/src/com/intellij/remoteServer/agent/util/CloudGitApplication.java
@@ -18,11 +18,7 @@
/**
* @author michael.golubev
*/
-public interface CloudGitApplication {
-
- String getName();
+public interface CloudGitApplication extends CloudApplication {
String getGitUrl();
-
- String getWebUrl();
}
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
index 53f608c..6a50170 100644
--- a/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/ServerType.java
@@ -3,6 +3,7 @@
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.ServerConfiguration;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator;
import com.intellij.remoteServer.runtime.ServerConnector;
@@ -46,6 +47,11 @@
@NotNull
public abstract ServerConnector<?> createConnector(@NotNull C configuration, @NotNull ServerTaskExecutor asyncTasksExecutor);
+ @NotNull
+ public ServerConnector<?> createConnector(@NotNull RemoteServer<C> server, @NotNull ServerTaskExecutor asyncTasksExecutor) {
+ return createConnector(server.getConfiguration(), asyncTasksExecutor);
+ }
+
/**
* @return a non-null instance of {@link DebugConnector} if the server supports deployment in debug mode
*/
diff --git a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/log/LoggingHandler.java b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/log/LoggingHandler.java
index a042687..a4d7818 100644
--- a/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/log/LoggingHandler.java
+++ b/platform/remote-servers/api/src/com/intellij/remoteServer/runtime/log/LoggingHandler.java
@@ -1,5 +1,6 @@
package com.intellij.remoteServer.runtime.log;
+import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.process.ProcessHandler;
import org.jetbrains.annotations.NotNull;
@@ -10,5 +11,7 @@
void print(@NotNull String s);
void printHyperlink(@NotNull String url);
+ void printHyperlink(@NotNull String text, HyperlinkInfo info);
+
void attachToProcess(@NotNull ProcessHandler handler);
}
diff --git a/plugins/git4idea/remote-servers-git/resources/resources/cloud.properties b/platform/remote-servers/impl/resources/resources/cloud.properties
similarity index 100%
rename from plugins/git4idea/remote-servers-git/resources/resources/cloud.properties
rename to platform/remote-servers/impl/resources/resources/cloud.properties
diff --git a/platform/remote-servers/impl/src/META-INF/RemoteServers.xml b/platform/remote-servers/impl/src/META-INF/RemoteServers.xml
index cabac1d..c18f18d 100644
--- a/platform/remote-servers/impl/src/META-INF/RemoteServers.xml
+++ b/platform/remote-servers/impl/src/META-INF/RemoteServers.xml
@@ -3,6 +3,9 @@
<extensionPoint name="remoteServer.type" interface="com.intellij.remoteServer.ServerType"/>
<extensionPoint name="remoteServer.deploymentSource.type" interface="com.intellij.remoteServer.configuration.deployment.DeploymentSourceType"/>
<extensionPoint name="remoteServer.viewContributor" interface="com.intellij.remoteServer.impl.runtime.ui.RemoteServersViewContributor"/>
+
+ <extensionPoint name="remoteServer.util.CloudDeploymentRuntimeProvider"
+ interface="com.intellij.remoteServer.util.CloudDeploymentRuntimeProvider"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java
index ab034c1..ec69360 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/configuration/deployment/DeployToServerSettingsEditor.java
@@ -175,6 +175,8 @@
@Override
protected void applyEditorTo(DeployToServerRunConfiguration<S,D> configuration) throws ConfigurationException {
+ updateDeploymentSettingsEditor();
+
configuration.setServerName(myServerListModel.getSelectedItem());
DeploymentSource deploymentSource = mySourceListModel.getSelectedItem();
configuration.setDeploymentSource(deploymentSource);
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
index d480270..b1a9965 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ServerConnectionManagerImpl.java
@@ -27,7 +27,7 @@
ServerConnection connection = myConnections.get(server);
if (connection == null) {
ServerTaskExecutorImpl executor = new ServerTaskExecutorImpl();
- connection = new ServerConnectionImpl(server, server.getType().createConnector(server.getConfiguration(), executor), this);
+ connection = new ServerConnectionImpl(server, server.getType().createConnector(server, executor), this);
myConnections.put(server, connection);
myEventDispatcher.fireConnectionCreated(connection);
}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java
index 8189a3c..7434b10 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/log/LoggingHandlerImpl.java
@@ -1,6 +1,7 @@
package com.intellij.remoteServer.impl.runtime.log;
import com.intellij.execution.filters.BrowserHyperlinkInfo;
+import com.intellij.execution.filters.HyperlinkInfo;
import com.intellij.execution.filters.TextConsoleBuilderFactory;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.ui.ConsoleView;
@@ -31,7 +32,12 @@
@Override
public void printHyperlink(@NotNull String url) {
- myConsole.printHyperlink(url, new BrowserHyperlinkInfo(url));
+ printHyperlink(url, new BrowserHyperlinkInfo(url));
+ }
+
+ @Override
+ public void printHyperlink(@NotNull String text, HyperlinkInfo info) {
+ myConsole.printHyperlink(text, info);
}
public void printlnSystemMessage(@NotNull String s) {
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudBundle.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudBundle.java
new file mode 100644
index 0000000..6353510
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudBundle.java
@@ -0,0 +1,51 @@
+/*
+ * 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.remoteServer.util;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ResourceBundle;
+
+/**
+ * @author michael.golubev
+ */
+public class CloudBundle {
+
+ private static Reference<ResourceBundle> ourBundle;
+
+ @NonNls private static final String BUNDLE = "resources.cloud";
+
+ private CloudBundle() {
+
+ }
+
+ public static String getText(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
+ if (bundle == null) {
+ bundle = ResourceBundle.getBundle(BUNDLE);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
+ }
+ return bundle;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudConnectionTask.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudConnectionTask.java
index 3906d5f..2ec4f41 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudConnectionTask.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudConnectionTask.java
@@ -15,10 +15,6 @@
*/
package com.intellij.remoteServer.util;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.Progressive;
-import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.remoteServer.configuration.RemoteServer;
import com.intellij.remoteServer.configuration.ServerConfigurationBase;
@@ -29,6 +25,7 @@
import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
import com.intellij.util.concurrency.Semaphore;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.concurrent.atomic.AtomicReference;
@@ -39,95 +36,34 @@
T,
SC extends ServerConfigurationBase,
DC extends DeploymentConfiguration,
- SR extends CloudServerRuntimeInstance<DC>> {
+ SR extends CloudServerRuntimeInstance<DC>> extends CloudRuntimeTask<T, DC, SR> {
- private static final Logger LOG = Logger.getInstance("#" + CloudConnectionTask.class.getName());
+ private final RemoteServer<SC> myServer;
- private final Project myProject;
- private final String myTitle;
- private final boolean myModal;
- private final boolean myCancellable;
-
- public CloudConnectionTask(Project project, String title, boolean modal, boolean cancellable) {
- myProject = project;
- myTitle = title;
- myModal = modal;
- myCancellable = cancellable;
+ public CloudConnectionTask(Project project, String title, @Nullable RemoteServer<SC> server) {
+ super(project, title);
+ myServer = server;
}
- public T perform() {
- RemoteServer<SC> server = getServer();
- if (server == null) {
- return null;
+ @Override
+ protected void run(final Semaphore semaphore, final AtomicReference<T> result) {
+ if (myServer == null) {
+ semaphore.up();
+ return;
}
- ServerConnection<DC> connection = ServerConnectionManager.getInstance().getOrCreateConnection(server);
-
- final Semaphore semaphore = new Semaphore();
- semaphore.down();
-
- final Progressive progressive = new Progressive() {
-
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- indicator.setIndeterminate(true);
- while (!indicator.isCanceled()) {
- if (semaphore.waitFor(500)) {
- break;
- }
- }
- }
- };
-
- Task task;
- if (myModal) {
- task = new Task.Modal(myProject, myTitle, myCancellable) {
-
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- progressive.run(indicator);
- }
- };
- }
- else {
- task = new Task.Backgroundable(myProject, myTitle, myCancellable) {
-
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- progressive.run(indicator);
- }
- };
- }
-
- AtomicReference<T> result = new AtomicReference<T>();
+ final ServerConnection<DC> connection = ServerConnectionManager.getInstance().getOrCreateConnection(myServer);
run(connection, semaphore, result);
-
- task.queue();
-
- return result.get();
}
- protected void run(final ServerConnection<DC> connection, final Semaphore semaphore, final AtomicReference<T> result) {
+ protected void run(final ServerConnection<DC> connection,
+ final Semaphore semaphore,
+ final AtomicReference<T> result) {
connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
@Override
public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
- final SR serverRuntime = (SR)serverRuntimeInstance;
- serverRuntime.getTaskExecutor().submit(new Runnable() {
-
- @Override
- public void run() {
- try {
- result.set(CloudConnectionTask.this.run(serverRuntime));
- }
- catch (ServerRuntimeException e) {
- runtimeErrorOccurred(e.getMessage());
- }
- finally {
- semaphore.up();
- }
- }
- });
+ run((SR)serverRuntimeInstance, semaphore, result);
}
@Override
@@ -138,11 +74,12 @@
});
}
- protected void runtimeErrorOccurred(@NotNull String errorMessage) {
- LOG.info(errorMessage);
+ @Override
+ protected SR getServerRuntime() {
+ throw new UnsupportedOperationException();
}
- protected abstract RemoteServer<SC> getServer();
-
- protected abstract T run(SR serverRuntime) throws ServerRuntimeException;
+ public final RemoteServer<SC> getServer() {
+ return myServer;
+ }
}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentConfiguratorBase.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentConfiguratorBase.java
new file mode 100644
index 0000000..19b1895
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentConfiguratorBase.java
@@ -0,0 +1,50 @@
+package com.intellij.remoteServer.util;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.ServerConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurator;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author michael.golubev
+ */
+public abstract class CloudDeploymentConfiguratorBase<D extends DeploymentConfiguration, S extends ServerConfiguration>
+ extends DeploymentConfigurator<D, S> {
+
+ private final Project myProject;
+ private ServerType<S> myServerType;
+
+ public CloudDeploymentConfiguratorBase(Project project, ServerType<S> serverType) {
+ myProject = project;
+ myServerType = serverType;
+ }
+
+ public static List<CloudDeploymentRuntimeProvider> getDeploymentRuntimeProviders(ServerType<?> serverType) {
+ List<CloudDeploymentRuntimeProvider> result = new ArrayList<CloudDeploymentRuntimeProvider>();
+ for (CloudDeploymentRuntimeProvider provider : CloudDeploymentRuntimeProvider.EP_NAME.getExtensions()) {
+ ServerType<?> providerServerType = provider.getServerType();
+ if (providerServerType == null || providerServerType == serverType) {
+ result.add(provider);
+ }
+ }
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public List<DeploymentSource> getAvailableDeploymentSources() {
+ if (myProject.isDefault()) return Collections.emptyList();
+ List<DeploymentSource> result = new ArrayList<DeploymentSource>();
+ for (CloudDeploymentRuntimeProvider provider : getDeploymentRuntimeProviders(myServerType)) {
+ result.addAll(provider.getDeploymentSources(myProject));
+ }
+ return result;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentNameConfiguration.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentNameConfiguration.java
index bf2e850..f2e4820 100644
--- a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentNameConfiguration.java
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentNameConfiguration.java
@@ -1,6 +1,7 @@
package com.intellij.remoteServer.util;
import com.intellij.remoteServer.configuration.deployment.DeploymentConfigurationBase;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
/**
* @author michael.golubev
@@ -27,4 +28,12 @@
public void setDeploymentName(String deploymentName) {
myDeploymentName = deploymentName;
}
+
+ public String getDeploymentSourceName(DeploymentSource deploymentSource) {
+ return isDefaultDeploymentName() ? getDefaultDeploymentSourceName(deploymentSource) : getDeploymentName();
+ }
+
+ protected String getDefaultDeploymentSourceName(DeploymentSource deploymentSource) {
+ return CloudDeploymentNameProvider.DEFAULT_NAME_PROVIDER.getDeploymentName(deploymentSource);
+ }
}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentRuntime.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentRuntime.java
new file mode 100644
index 0000000..d21c319
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentRuntime.java
@@ -0,0 +1,167 @@
+/*
+ * 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.remoteServer.util;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Ref;
+import com.intellij.remoteServer.agent.util.CloudApplication;
+import com.intellij.remoteServer.agent.util.CloudGitAgentDeployment;
+import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentRuntime;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
+import com.intellij.remoteServer.runtime.log.LoggingHandler;
+import com.intellij.util.ThrowableRunnable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author michael.golubev
+ */
+public abstract class CloudDeploymentRuntime extends DeploymentRuntime {
+
+ private final CloudMultiSourceServerRuntimeInstance myServerRuntime;
+ private final DeploymentTask myTask;
+
+ private final CloudGitAgentDeployment myDeployment;
+ private final String myApplicationName;
+ private final String myPresentableName;
+ private final CloudLoggingHandler myLoggingHandler;
+ @Nullable private final DeploymentLogManager myLogManager;
+
+ public CloudDeploymentRuntime(CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentSource source,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> task,
+ @Nullable DeploymentLogManager logManager) throws ServerRuntimeException {
+ myServerRuntime = serverRuntime;
+ myTask = task;
+
+ myLogManager = logManager;
+ myLoggingHandler = logManager == null ? new CloudSilentLoggingHandlerImpl() : new CloudLoggingHandlerImpl(logManager);
+
+ CloudDeploymentNameConfiguration deploymentConfiguration = task.getConfiguration();
+ myApplicationName = deploymentConfiguration.getDeploymentSourceName(source);
+
+ myPresentableName = source.getPresentableName();
+
+ myDeployment = serverRuntime.getAgent().createDeployment(myApplicationName, myLoggingHandler);
+ }
+
+ protected CloudMultiSourceServerRuntimeInstance getServerRuntime() {
+ return myServerRuntime;
+ }
+
+ protected DeploymentTask getTask() {
+ return myTask;
+ }
+
+ @Nullable
+ protected DeploymentLogManager getLogManager() {
+ return myLogManager;
+ }
+
+ public void deploy(ServerRuntimeInstance.DeploymentOperationCallback callback) {
+ try {
+ CloudApplication application = deploy();
+
+ if (myLogManager != null) {
+ LoggingHandler loggingHandler = myLogManager.getMainLoggingHandler();
+ loggingHandler.print("Application is available at ");
+ loggingHandler.printHyperlink(application.getWebUrl());
+ loggingHandler.print("\n");
+ }
+
+ callback.succeeded(this);
+ }
+ catch (ServerRuntimeException e) {
+ callback.errorOccurred(e.getMessage());
+ }
+ }
+
+ @Override
+ public void undeploy(final @NotNull UndeploymentTaskCallback callback) {
+ myServerRuntime.getTaskExecutor().submit(new ThrowableRunnable<Exception>() {
+
+ @Override
+ public void run() throws Exception {
+ try {
+ if (!confirmUndeploy()) {
+ throw new ServerRuntimeException("Undeploy cancelled");
+ }
+
+ undeploy();
+
+ callback.succeeded();
+ }
+ catch (ServerRuntimeException e) {
+ callback.errorOccurred(e.getMessage());
+ }
+ }
+ }, callback);
+ }
+
+ public CloudGitAgentDeployment getDeployment() {
+ return myDeployment;
+ }
+
+ public Project getProject() {
+ return myTask.getProject();
+ }
+
+ public String getApplicationName() {
+ return myApplicationName;
+ }
+
+ public AgentTaskExecutor getAgentTaskExecutor() {
+ return myServerRuntime.getAgentTaskExecutor();
+ }
+
+ public CloudLoggingHandler getLoggingHandler() {
+ return myLoggingHandler;
+ }
+
+ public boolean confirmUndeploy() {
+ final Ref<Boolean> confirmed = new Ref<Boolean>(false);
+ ApplicationManager.getApplication().invokeAndWait(new Runnable() {
+
+ @Override
+ public void run() {
+ String title = CloudBundle.getText("cloud.undeploy.confirm.title");
+ while (true) {
+ String password = Messages.showPasswordDialog(CloudBundle.getText("cloud.undeploy.confirm.message", myPresentableName), title);
+ if (password == null) {
+ return;
+ }
+ if (password.equals(myServerRuntime.getConfiguration().getPassword())) {
+ confirmed.set(true);
+ return;
+ }
+ Messages.showErrorDialog(CloudBundle.getText("cloud.undeploy.confirm.password.incorrect"), title);
+ }
+ }
+ }, ModalityState.defaultModalityState());
+ return confirmed.get();
+ }
+
+ public abstract CloudApplication deploy() throws ServerRuntimeException;
+
+ public abstract void undeploy() throws ServerRuntimeException;
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentRuntimeProvider.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentRuntimeProvider.java
new file mode 100644
index 0000000..e8aafc7
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudDeploymentRuntimeProvider.java
@@ -0,0 +1,44 @@
+/*
+ * 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.remoteServer.util;
+
+import com.intellij.openapi.extensions.ExtensionPointName;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+
+import java.util.Collection;
+
+/**
+ * @author michael.golubev
+ */
+public interface CloudDeploymentRuntimeProvider {
+
+ ExtensionPointName<CloudDeploymentRuntimeProvider> EP_NAME
+ = ExtensionPointName.create("com.intellij.remoteServer.util.CloudDeploymentRuntimeProvider");
+
+ ServerType<?> getServerType();
+
+ Collection<DeploymentSource> getDeploymentSources(Project project);
+
+ CloudDeploymentRuntime createDeploymentRuntime(DeploymentSource source,
+ CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager)
+ throws ServerRuntimeException;
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudMultiSourceServerRuntimeInstance.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudMultiSourceServerRuntimeInstance.java
new file mode 100644
index 0000000..8db26a7
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudMultiSourceServerRuntimeInstance.java
@@ -0,0 +1,233 @@
+package com.intellij.remoteServer.util;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
+import com.intellij.remoteServer.ServerType;
+import com.intellij.remoteServer.agent.RemoteAgentManager;
+import com.intellij.remoteServer.agent.util.CloudAgentConfigBase;
+import com.intellij.remoteServer.agent.util.CloudAgentLogger;
+import com.intellij.remoteServer.agent.util.CloudGitAgent;
+import com.intellij.remoteServer.agent.util.DeploymentData;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
+import com.intellij.remoteServer.runtime.ServerConnector;
+import com.intellij.remoteServer.runtime.ServerTaskExecutor;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
+import com.intellij.util.ThrowableRunnable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author michael.golubev
+ */
+public abstract class CloudMultiSourceServerRuntimeInstance<
+ DC extends CloudDeploymentNameConfiguration,
+ AC extends CloudAgentConfigBase,
+ A extends CloudGitAgent<AC, ?>,
+ SC extends AC>
+ extends CloudServerRuntimeInstance<DC> {
+
+ private static final Logger LOG = Logger.getInstance("#" + CloudMultiSourceServerRuntimeInstance.class.getName());
+
+ private final A myAgent;
+ private final AgentTaskExecutor myAgentTaskExecutor;
+
+ private final ServerType<?> myServerType;
+ private final SC myConfiguration;
+ private final ServerTaskExecutor myTasksExecutor;
+
+ public CloudMultiSourceServerRuntimeInstance(ServerType<?> serverType,
+ SC configuration,
+ ServerTaskExecutor tasksExecutor,
+ List<File> libraries,
+ List<Class<?>> commonJarClasses,
+ String specificsModuleName,
+ String specificJarPath,
+ Class<A> agentInterface,
+ String agentClassName) throws Exception {
+ myServerType = serverType;
+ myConfiguration = configuration;
+ myTasksExecutor = tasksExecutor;
+
+ RemoteAgentManager agentManager = RemoteAgentManager.getInstance();
+ myAgent = agentManager.createAgent(agentManager.createReflectiveThreadProxyFactory(getClass().getClassLoader()),
+ libraries,
+ commonJarClasses,
+ specificsModuleName,
+ specificJarPath,
+ agentInterface,
+ agentClassName,
+ getClass());
+ myAgentTaskExecutor = new AgentTaskExecutor();
+ }
+
+ @NotNull
+ @Override
+ public String getDeploymentName(@NotNull DeploymentSource source) {
+ return CloudDeploymentNameProvider.DEFAULT_NAME_PROVIDER.getDeploymentName(source);
+ }
+
+ public void connect(final ServerConnector.ConnectionCallback<DC> callback) {
+ myAgentTaskExecutor.execute(new Computable() {
+
+ @Override
+ public Object compute() {
+ doConnect(myConfiguration,
+ new CloudAgentLogger() {
+
+ @Override
+ public void debugEx(Exception e) {
+ LOG.debug(e);
+ }
+
+ @Override
+ public void debug(String message) {
+ LOG.debug(message);
+ }
+ });
+ return null;
+ }
+ }, new CallbackWrapper() {
+
+ @Override
+ public void onSuccess(Object result) {
+ callback.connected(CloudMultiSourceServerRuntimeInstance.this);
+ }
+
+ @Override
+ public void onError(String message) {
+ callback.errorOccurred(message);
+ }
+ }
+ );
+ }
+
+ @Override
+ public void deploy(@NotNull final DeploymentTask<DC> task,
+ @NotNull final DeploymentLogManager logManager,
+ @NotNull final ServerRuntimeInstance.DeploymentOperationCallback callback) {
+ myTasksExecutor.submit(new ThrowableRunnable<Exception>() {
+
+ @Override
+ public void run() throws Exception {
+ createDeploymentRuntime(task, logManager).deploy(callback);
+ }
+ }, callback);
+ }
+
+ @Override
+ public void computeDeployments(@NotNull final ServerRuntimeInstance.ComputeDeploymentsCallback callback) {
+ myTasksExecutor.submit(new ThrowableRunnable<Exception>() {
+ @Override
+ public void run() throws Exception {
+ myAgentTaskExecutor.execute(new Computable<DeploymentData[]>() {
+
+ @Override
+ public DeploymentData[] compute() {
+ return myAgent.getDeployments();
+ }
+ },
+ new CallbackWrapper<DeploymentData[]>() {
+
+ @Override
+ public void onSuccess(DeploymentData[] deployments) {
+ for (DeploymentData deployment : deployments) {
+ callback.addDeployment(deployment.getName());
+ }
+ callback.succeeded();
+ }
+
+ @Override
+ public void onError(String message) {
+ callback.errorOccurred(message);
+ }
+ }
+ );
+ }
+ }, callback);
+ }
+
+ @Override
+ public void disconnect() {
+ myTasksExecutor.submit(new Runnable() {
+
+ @Override
+ public void run() {
+ myAgent.disconnect();
+ }
+ });
+ }
+
+ @Override
+ public ServerTaskExecutor getTaskExecutor() {
+ return myTasksExecutor;
+ }
+
+ protected final A getAgent() {
+ return myAgent;
+ }
+
+ protected final AgentTaskExecutor getAgentTaskExecutor() {
+ return myAgentTaskExecutor;
+ }
+
+ public CloudDeploymentRuntime createDeploymentRuntime(final DeployToServerRunConfiguration<?, DC> runConfiguration)
+ throws ServerRuntimeException {
+ return createDeploymentRuntime(runConfiguration.getDeploymentSource(),
+ runConfiguration.getDeploymentConfiguration(),
+ runConfiguration.getProject());
+ }
+
+ public CloudDeploymentRuntime createDeploymentRuntime(final DeploymentSource source, final DC configuration, final Project project)
+ throws ServerRuntimeException {
+ return createDeploymentRuntime(new DeploymentTask<DC>() {
+
+ @NotNull
+ @Override
+ public DeploymentSource getSource() {
+ return source;
+ }
+
+ @NotNull
+ @Override
+ public DC getConfiguration() {
+ return configuration;
+ }
+
+ @NotNull
+ @Override
+ public Project getProject() {
+ return project;
+ }
+
+ @Override
+ public boolean isDebugMode() {
+ return false;
+ }
+ }, null);
+ }
+
+ private CloudDeploymentRuntime createDeploymentRuntime(DeploymentTask<DC> deploymentTask,
+ @Nullable DeploymentLogManager logManager) throws ServerRuntimeException {
+ DeploymentSource source = deploymentTask.getSource();
+ for (CloudDeploymentRuntimeProvider provider : CloudDeploymentConfiguratorBase.getDeploymentRuntimeProviders(myServerType)) {
+ CloudDeploymentRuntime result = provider.createDeploymentRuntime(source, this, deploymentTask, logManager);
+ if (result != null) {
+ return result;
+ }
+ }
+ throw new ServerRuntimeException("Unknown deployment source");
+ }
+
+ public CloudConfigurationBase getConfiguration() {
+ return (CloudConfigurationBase)myConfiguration;
+ }
+
+ protected abstract void doConnect(SC configuration, CloudAgentLogger logger);
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudNotifier.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudNotifier.java
new file mode 100644
index 0000000..029e47c
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudNotifier.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.notification.Notification;
+import com.intellij.notification.NotificationGroup;
+import com.intellij.notification.NotificationListener;
+import com.intellij.openapi.ui.MessageType;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author michael.golubev
+ */
+public class CloudNotifier {
+
+ private final String myNotificationDisplayId;
+
+ public CloudNotifier(String notificationDisplayId) {
+ myNotificationDisplayId = notificationDisplayId;
+ }
+
+ public void showMessage(String message, MessageType messageType) {
+ showMessage(message, messageType, null);
+ }
+
+ public void showMessage(String message, MessageType messageType, @Nullable NotificationListener listener) {
+ NotificationGroup notificationGroup = NotificationGroup.balloonGroup(myNotificationDisplayId);
+ Notification notification = notificationGroup.createNotification("", message, messageType.toNotificationType(), listener);
+ notification.notify(null);
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRuntimeTask.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRuntimeTask.java
new file mode 100644
index 0000000..6ead156
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudRuntimeTask.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Progressive;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.configuration.deployment.DeploymentConfiguration;
+import com.intellij.util.concurrency.Semaphore;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+public abstract class CloudRuntimeTask<
+ T,
+ DC extends DeploymentConfiguration,
+ SR extends CloudServerRuntimeInstance<DC>> {
+
+ private static final Logger LOG = Logger.getInstance("#" + CloudRuntimeTask.class.getName());
+
+ private final Project myProject;
+ private final String myTitle;
+
+ public CloudRuntimeTask(Project project, String title) {
+ myProject = project;
+ myTitle = title;
+ }
+
+ public T performSync() {
+ return perform(true);
+ }
+
+ public void performAsync() {
+ perform(false);
+ }
+
+ private T perform(boolean modal) {
+ final Semaphore semaphore = new Semaphore();
+ semaphore.down();
+
+ final Progressive progressive = new Progressive() {
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ indicator.setIndeterminate(true);
+ while (!indicator.isCanceled()) {
+ if (semaphore.waitFor(500)) {
+ break;
+ }
+ }
+ }
+ };
+
+ Task task;
+ boolean cancellable = isCancellable(modal);
+ if (modal) {
+ task = new Task.Modal(myProject, myTitle, cancellable) {
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ progressive.run(indicator);
+ }
+ };
+ }
+ else {
+ task = new Task.Backgroundable(myProject, myTitle, cancellable) {
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ progressive.run(indicator);
+ }
+ };
+ }
+
+ AtomicReference<T> result = new AtomicReference<T>();
+ run(semaphore, result);
+
+ task.queue();
+
+ return result.get();
+ }
+
+ protected boolean isCancellable(boolean modal) {
+ return modal;
+ }
+
+ protected void run(final Semaphore semaphore, final AtomicReference<T> result) {
+ run(getServerRuntime(), semaphore, result);
+ }
+
+ protected void run(final SR serverRuntime, final Semaphore semaphore, final AtomicReference<T> result) {
+ serverRuntime.getTaskExecutor().submit(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ result.set(CloudRuntimeTask.this.run(serverRuntime));
+ }
+ catch (ServerRuntimeException e) {
+ runtimeErrorOccurred(e.getMessage());
+ }
+ finally {
+ semaphore.up();
+ }
+ }
+ });
+ }
+
+ protected void runtimeErrorOccurred(@NotNull String errorMessage) {
+ LOG.info(errorMessage);
+ }
+
+ protected abstract SR getServerRuntime();
+
+ protected abstract T run(SR serverRuntime) throws ServerRuntimeException;
+}
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
new file mode 100644
index 0000000..e27a892
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java
@@ -0,0 +1,293 @@
+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.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;
+
+/**
+ * @author michael.golubev
+ */
+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) {
+ myModelProject = frameworkSupportModel.getProject();
+ myCloudType = cloudType;
+ }
+
+ @Override
+ public void dispose() {
+ myServerConfigurable.disposeUIResources();
+ }
+
+ 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));
+ }
+
+ protected void reloadExistingApplications() {
+ Collection<Deployment> deployments = new ConnectionTask<Collection<Deployment>>("Loading existing applications list") {
+
+ @Override
+ protected void run(final ServerConnection<DC> connection,
+ final Semaphore semaphore,
+ final AtomicReference<Collection<Deployment>> result) {
+ connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
+
+ @Override
+ public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
+ connection.computeDeployments(new Runnable() {
+
+ @Override
+ public void run() {
+ result.set(connection.getDeployments());
+ semaphore.up();
+ }
+ });
+ }
+
+ @Override
+ public void errorOccurred(@NotNull String errorMessage) {
+ runtimeErrorOccurred(errorMessage);
+ semaphore.up();
+ }
+ });
+ }
+
+ @Override
+ protected Collection<Deployment> run(SR serverRuntimeInstance) throws ServerRuntimeException {
+ return null;
+ }
+ }.performSync();
+
+ if (deployments == null) {
+ return;
+ }
+
+ JComboBox existingComboBox = getExistingComboBox();
+ existingComboBox.removeAllItems();
+ for (Deployment deployment : deployments) {
+ existingComboBox.addItem(deployment.getName());
+ }
+ }
+
+ @Override
+ public void onFrameworkSelectionChanged(boolean selected) {
+ if (selected && !myInitialized) {
+ myInitialized = true;
+ initUI();
+ updateApplicationUI();
+ }
+ }
+
+ 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);
+ }
+
+ protected Project getProject() {
+ 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;
+ }
+
+ protected void runOnModuleAdded(final Module module, final Runnable runnable) {
+ if (myModelProject == null) {
+ StartupManager.getInstance(module.getProject()).runWhenProjectIsInitialized(runnable);
+ }
+ else {
+ MessageBusConnection connection = myModelProject.getMessageBus().connect(myModelProject);
+ connection.subscribe(ProjectTopics.MODULES, new ModuleAdapter() {
+
+ public void moduleAdded(Project project, Module addedModule) {
+ if (addedModule == module) {
+ runnable.run();
+ }
+ }
+ });
+ }
+ }
+
+ protected abstract JComboBox getExistingComboBox();
+
+ protected abstract JComboBox getServerComboBox();
+
+ 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) {
+ super(myModelProject, title, CloudSupportConfigurableBase.this.getServer());
+ }
+
+ public ConnectionTask(Module module, String title) {
+ super(module.getProject(), title, CloudSupportConfigurableBase.this.getServer());
+ }
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/TooltipUtil.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/TooltipUtil.java
new file mode 100644
index 0000000..126dee1
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/TooltipUtil.java
@@ -0,0 +1,36 @@
+package com.intellij.remoteServer.util;
+
+import com.intellij.codeInsight.hint.HintManager;
+import com.intellij.codeInsight.hint.HintUtil;
+import com.intellij.icons.AllIcons;
+import com.intellij.ui.HyperlinkAdapter;
+import com.intellij.ui.HyperlinkLabel;
+import com.intellij.ui.awt.RelativePoint;
+
+import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
+
+/**
+ * @author michael.golubev
+ */
+public class TooltipUtil {
+
+ public static HyperlinkLabel createTooltip(final String message) {
+ final HyperlinkLabel link = new HyperlinkLabel("");
+ link.setIcon(AllIcons.General.Help_small);
+ link.setUseIconAsLink(true);
+ link.setIconTextGap(0);
+ link.addHyperlinkListener(new HyperlinkAdapter() {
+ @Override
+ protected void hyperlinkActivated(HyperlinkEvent e) {
+ final JLabel label = new JLabel(message);
+ label.setBorder(HintUtil.createHintBorder());
+ label.setBackground(HintUtil.INFORMATION_COLOR);
+ label.setOpaque(true);
+ HintManager.getInstance()
+ .showHint(label, RelativePoint.getSouthEastOf(link), HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE, -1);
+ }
+ });
+ return link;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyDialog.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyDialog.java
new file mode 100644
index 0000000..38c5a13
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyDialog.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ssh;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.ValidationInfo;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.io.File;
+
+/**
+ * @author michael.golubev
+ */
+public class PublicSshKeyDialog extends DialogWrapper {
+
+ private PublicSshKeyFilePanel myPanel;
+
+ public PublicSshKeyDialog(@Nullable Project project) {
+ super(project);
+ setTitle("Upload Public SSH Key");
+ myPanel = new PublicSshKeyFilePanel();
+ init();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ return myPanel.getMainPanel();
+ }
+
+ public File getSshKey() {
+ return new File(myPanel.getSshKey());
+ }
+
+ @Nullable
+ @Override
+ protected ValidationInfo doValidate() {
+ return getSshKey().isFile() ? null : new ValidationInfo("Public SSH key file does not exist");
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyFilePanel.form b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyFilePanel.form
new file mode 100644
index 0000000..c22dc65
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyFilePanel.form
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.remoteServer.util.ssh.PublicSshKeyFilePanel">
+ <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="2" 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>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <vspacer id="edf98">
+ <constraints>
+ <grid row="1" 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>
+ <component id="fe2d2" 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="b8838"/>
+ <text value="Public SSH key file:"/>
+ </properties>
+ </component>
+ <component id="856a6" class="com.intellij.ui.HyperlinkLabel" binding="myPublicSshKeyTooltipHyperlink" custom-create="true">
+ <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>
+ <iconTextGap value="2"/>
+ </properties>
+ </component>
+ <component id="50045" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myPublicSshKeyFileField">
+ <constraints>
+ <grid row="0" column="2" 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>
+ </children>
+ </grid>
+</form>
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyFilePanel.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyFilePanel.java
new file mode 100644
index 0000000..c16ff33
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/PublicSshKeyFilePanel.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ssh;
+
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.remoteServer.util.TooltipUtil;
+import com.intellij.ui.HyperlinkLabel;
+
+import javax.swing.*;
+
+/**
+ * @author michael.golubev
+ */
+public class PublicSshKeyFilePanel {
+
+ private TextFieldWithBrowseButton myPublicSshKeyFileField;
+ private HyperlinkLabel myPublicSshKeyTooltipHyperlink;
+ private JPanel myMainPanel;
+
+ public PublicSshKeyFilePanel() {
+ myPublicSshKeyFileField.addBrowseFolderListener("SSH key file", "Select public SSH key file", null,
+ FileChooserDescriptorFactory.createSingleLocalFileDescriptor());
+ }
+
+ public String getSshKey() {
+ return myPublicSshKeyFileField.getText();
+ }
+
+ private void createUIComponents() {
+ myPublicSshKeyTooltipHyperlink =
+ TooltipUtil.createTooltip(
+ "Specify the location of your public SSH key file (.pub). You won’t be able to use the cloud unless you register you public key there. However, if you’ve already done that, you don’t have to specify the key now.");
+ }
+
+ public JComponent getMainPanel() {
+ return myMainPanel;
+ }
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/SshKeyAwareServerRuntime.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/SshKeyAwareServerRuntime.java
new file mode 100644
index 0000000..9c6008f
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/SshKeyAwareServerRuntime.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ssh;
+
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.util.CloudServerRuntimeInstance;
+import com.intellij.remoteServer.util.ServerRuntimeException;
+
+import java.io.File;
+
+/**
+ * @author michael.golubev
+ */
+public interface SshKeyAwareServerRuntime {
+
+ void addSshKey(File sshKey) throws ServerRuntimeException;
+
+ CloudServerRuntimeInstance asCloudServerRuntime();
+
+ RemoteServer getServer();
+}
diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/SshKeyChecker.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/SshKeyChecker.java
new file mode 100644
index 0000000..9eb3ea3
--- /dev/null
+++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/util/ssh/SshKeyChecker.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.ssh;
+
+import com.intellij.execution.filters.HyperlinkInfo;
+import com.intellij.notification.Notification;
+import com.intellij.notification.NotificationListener;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.MessageType;
+import com.intellij.remoteServer.runtime.ServerConnection;
+import com.intellij.remoteServer.runtime.ServerConnectionManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+import com.intellij.remoteServer.runtime.log.LoggingHandler;
+import com.intellij.remoteServer.runtime.ui.RemoteServersView;
+import com.intellij.remoteServer.util.*;
+import com.intellij.util.ParameterizedRunnable;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.event.HyperlinkEvent;
+import java.io.File;
+
+/**
+ * @author michael.golubev
+ */
+public class SshKeyChecker {
+
+ private static boolean isSshKeyErrorMessage(String errorMessage) {
+ return errorMessage.contains("Could not read from remote repository") || errorMessage.contains("The remote end hung up unexpectedly");
+ }
+
+ public void checkServerError(String errorMessage,
+ CloudNotifier notifier,
+ Project project,
+ CloudConnectionTask connectionTask) {
+ if (isSshKeyErrorMessage(errorMessage)) {
+ new ServerHandler(notifier, project, connectionTask).handle(errorMessage);
+ }
+ else {
+ notifier.showMessage(errorMessage, MessageType.ERROR);
+ }
+ }
+
+ public void checkDeploymentError(String errorMessage,
+ SshKeyAwareServerRuntime serverRuntime,
+ DeploymentLogManager logManager,
+ DeploymentTask deploymentTask) {
+ if (isSshKeyErrorMessage(errorMessage) && logManager != null) {
+ new DeploymentHandler(serverRuntime, logManager.getMainLoggingHandler(), deploymentTask).handle();
+ }
+ }
+
+ private class ServerHandler extends HandlerBase {
+
+ private final CloudNotifier myNotifier;
+ private final Project myProject;
+ private final CloudConnectionTask myConnectionTask;
+
+ private Notification myErrorNotification;
+
+ public ServerHandler(CloudNotifier notifier, Project project, CloudConnectionTask connectionTask) {
+ myNotifier = notifier;
+ myProject = project;
+ myConnectionTask = connectionTask;
+ }
+
+ @Override
+ public Project getProject() {
+ return myProject;
+ }
+
+ public void handle(String errorMessage) {
+ myNotifier.showMessage(errorMessage + "<br/>You may need to <a href=\"#\">upload SSH public key</a>",
+ MessageType.ERROR,
+ new NotificationListener() {
+
+ @Override
+ public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
+ myErrorNotification = notification;
+ chooseKey();
+ }
+ });
+ }
+
+ @Override
+ protected void uploadKey(final File sskKey) {
+ new CloudConnectionTask(myProject, "Uploading SSH key", myConnectionTask.getServer()) {
+
+ @Override
+ protected Object run(CloudServerRuntimeInstance serverRuntime) throws ServerRuntimeException {
+ ((SshKeyAwareServerRuntime)serverRuntime).addSshKey(sskKey);
+ myErrorNotification.expire();
+ myNotifier.showMessage("SSH key was uploaded, you may <a href=\"#\">reconnect</a>",
+ MessageType.INFO,
+ new NotificationListener() {
+
+ @Override
+ public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
+ notification.expire();
+ reconnect();
+ }
+ });
+ return null;
+ }
+
+ @Override
+ protected void runtimeErrorOccurred(@NotNull String errorMessage) {
+ myNotifier.showMessage(errorMessage, MessageType.ERROR);
+ }
+ }.performSync();
+ }
+
+ private void reconnect() {
+ myConnectionTask.performAsync();
+ }
+ }
+
+ private class DeploymentHandler extends HandlerBase {
+
+ private final SshKeyAwareServerRuntime myServerRuntime;
+ private final DeploymentTask myDeploymentTask;
+ private final LoggingHandler myLoggingHandler;
+
+ private DeploymentHandler(SshKeyAwareServerRuntime serverRuntime,
+ LoggingHandler loggingHandler,
+ DeploymentTask deploymentTask) {
+ myServerRuntime = serverRuntime;
+ myDeploymentTask = deploymentTask;
+ myLoggingHandler = loggingHandler;
+ }
+
+ @Override
+ protected Project getProject() {
+ return myDeploymentTask.getProject();
+ }
+
+ public void handle() {
+ myLoggingHandler.print("You may need to ");
+ myLoggingHandler.printHyperlink("upload SSH public key", new HyperlinkInfo() {
+
+ @Override
+ public void navigate(Project project) {
+ chooseKey();
+ }
+ });
+ myLoggingHandler.print("\n");
+ }
+
+ @Override
+ protected void uploadKey(final File sskKey) {
+ new CloudRuntimeTask(getProject(), "Uploading SSH key") {
+
+ @Override
+ protected CloudServerRuntimeInstance getServerRuntime() {
+ return myServerRuntime.asCloudServerRuntime();
+ }
+
+ @Override
+ protected Object run(CloudServerRuntimeInstance serverRuntimeInstance) throws ServerRuntimeException {
+ myServerRuntime.addSshKey(sskKey);
+
+ myLoggingHandler.print("SSH key was uploaded, you may ");
+ myLoggingHandler.printHyperlink("redeploy", new HyperlinkInfo() {
+
+
+ @Override
+ public void navigate(Project project) {
+ redeploy();
+ }
+ });
+ myLoggingHandler.print("\n");
+
+ return null;
+ }
+
+ @Override
+ protected void runtimeErrorOccurred(@NotNull String errorMessage) {
+ myLoggingHandler.print("Unable to upload SSH key: " + errorMessage + "\n");
+ }
+ }.performSync();
+ }
+
+ private void redeploy() {
+ final ServerConnection connection = ServerConnectionManager.getInstance().getOrCreateConnection(myServerRuntime.getServer());
+
+ final RemoteServersView view = RemoteServersView.getInstance(myDeploymentTask.getProject());
+ view.showServerConnection(connection);
+
+ connection.deploy(myDeploymentTask,
+ new ParameterizedRunnable<String>() {
+
+ @Override
+ public void run(String s) {
+ view.showDeployment(connection, s);
+ }
+ });
+ }
+ }
+
+ private static abstract class HandlerBase {
+
+ protected void chooseKey() {
+ PublicSshKeyDialog dialog = new PublicSshKeyDialog(getProject());
+ if (dialog.showAndGet()) {
+ uploadKey(dialog.getSshKey());
+ }
+ }
+
+ protected abstract void uploadKey(File sskKeyFile);
+
+ protected abstract Project getProject();
+ }
+}
diff --git a/platform/remote-servers/util/remote-servers-util.iml b/platform/remote-servers/util/remote-servers-util.iml
deleted file mode 100644
index e3c6316..0000000
--- a/platform/remote-servers/util/remote-servers-util.iml
+++ /dev/null
@@ -1,21 +0,0 @@
-<?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$">
- <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/../sandbox/resources" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
- </content>
- <orderEntry type="inheritedJdk" />
- <orderEntry type="sourceFolder" forTests="false" />
- <orderEntry type="module" module-name="git4idea" exported="" />
- <orderEntry type="module" module-name="remote-servers-impl" exported="" />
- <orderEntry type="module" module-name="core-api" exported="" />
- <orderEntry type="module" module-name="remote-servers-api" />
- <orderEntry type="module" module-name="vcs-api" />
- <orderEntry type="module" module-name="lang-api" />
- <orderEntry type="module" module-name="lang-impl" />
- </component>
-</module>
-
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestsRunnerBundle.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestsRunnerBundle.java
index c1d6798..f343e7d 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestsRunnerBundle.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/SMTestsRunnerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author Roman Chernyatchik
*/
public class SMTestsRunnerBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.SMTestsRunnerBundle";
private SMTestsRunnerBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java
index 22ebe09..72e984b 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralIdBasedToSMTRunnerEventsConvertor.java
@@ -39,7 +39,7 @@
private static final Logger LOG = Logger.getInstance(GeneralIdBasedToSMTRunnerEventsConvertor.class.getName());
private final TIntObjectHashMap<Node> myNodeByIdMap = new TIntObjectHashMap<Node>();
- private final Set<Node> myRunningNodes = ContainerUtil.newHashSet();
+ private final Set<Node> myRunningTestNodes = ContainerUtil.newHashSet();
private final List<SMTRunnerEventsListener> myEventsListeners = ContainerUtil.createLockFreeCopyOnWriteList();
private final SMTestProxy.SMRootTestProxy myTestsRootProxy;
private final Node myTestsRootNode;
@@ -51,10 +51,9 @@
public GeneralIdBasedToSMTRunnerEventsConvertor(@NotNull SMTestProxy.SMRootTestProxy testsRootProxy,
@NotNull String testFrameworkName) {
myTestsRootProxy = testsRootProxy;
- myTestsRootNode = new Node(0, null, testsRootProxy, State.RUNNING);
+ myTestsRootNode = new Node(0, null, testsRootProxy);
myTestFrameworkName = testFrameworkName;
myNodeByIdMap.put(myTestsRootNode.getId(), myTestsRootNode);
- myRunningNodes.add(myTestsRootNode);
}
public void setLocator(@NotNull TestLocationProvider customLocator) {
@@ -68,8 +67,8 @@
public void onStartTesting() {
addToInvokeLater(new Runnable() {
public void run() {
+ myTestsRootNode.setState(State.RUNNING);
myTestsRootProxy.setStarted();
-
fireOnTestingStarted();
}
});
@@ -95,22 +94,38 @@
// We don't know whether process was destroyed by user
// or it finished after all tests have been run
- // Lets assume, if at finish all suites except root suite are passed
+ // Lets assume, if at finish all nodes except root suite have final state (passed, failed or ignored),
// then all is ok otherwise process was terminated by user
- if (myRunningNodes.size() == 1 && myRunningNodes.contains(myTestsRootNode)) {
+ boolean completeTree = isTreeComplete();
+ if (completeTree) {
myTestsRootProxy.setFinished();
} else {
- logProblem("Unexpected running nodes: " + myRunningNodes);
myTestsRootProxy.setTerminated();
}
+ if (!myRunningTestNodes.isEmpty()) {
+ logProblem("Unexpected running nodes: " + myRunningTestNodes);
+ }
myNodeByIdMap.clear();
- myRunningNodes.clear();
+ myRunningTestNodes.clear();
fireOnTestingFinished();
}
});
}
+ private boolean isTreeComplete() {
+ if (!myRunningTestNodes.isEmpty()) {
+ return false;
+ }
+ List<? extends SMTestProxy> children = myTestsRootProxy.getChildren();
+ for (SMTestProxy child : children) {
+ if (!child.isFinal() || child.wasTerminated()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
@Override
public void setPrinterProvider(@NotNull TestProxyPrinterProvider printerProvider) {
myTestProxyPrinterProvider = printerProvider;
@@ -135,15 +150,8 @@
private void doStartNode(@NotNull BaseStartedNodeEvent startedNodeEvent, boolean suite) {
Node node = findNode(startedNodeEvent);
if (node != null) {
- if (node.getState() == State.REGISTERED && startedNodeEvent.isRunning()) {
- node.setState(State.RUNNING);
- myRunningNodes.add(node);
- node.getProxy().setStarted();
- if (suite) {
- fireOnSuiteStarted(node.getProxy());
- } else {
- fireOnTestStarted(node.getProxy());
- }
+ if (node.getState() == State.NOT_RUNNING && startedNodeEvent.isRunning()) {
+ setNodeAndAncestorsRunning(node);
}
else {
logProblem(startedNodeEvent + " has been already started: " + node + "!");
@@ -170,23 +178,14 @@
childProxy.setPreferredPrinter(printer);
}
}
- State initialState = startedNodeEvent.isRunning() ? State.RUNNING : State.REGISTERED;
- node = new Node(startedNodeEvent.getId(), parentNode, childProxy, initialState);
+ node = new Node(startedNodeEvent.getId(), parentNode, childProxy);
myNodeByIdMap.put(startedNodeEvent.getId(), node);
if (myLocator != null) {
childProxy.setLocator(myLocator);
}
parentNode.getProxy().addChild(childProxy);
-
- if (node.getState() == State.RUNNING) {
- myRunningNodes.add(node);
- // progress started
- childProxy.setStarted();
- if (suite) {
- fireOnSuiteStarted(childProxy);
- } else {
- fireOnTestStarted(childProxy);
- }
+ if (startedNodeEvent.isRunning()) {
+ setNodeAndAncestorsRunning(node);
}
}
@@ -202,7 +201,7 @@
logProblem("Parent node is undefined for " + startedNodeEvent + ".", true);
return null;
}
- if (parentNode.getState() != State.REGISTERED && parentNode.getState() != State.RUNNING) {
+ if (parentNode.getState() != State.NOT_RUNNING && parentNode.getState() != State.RUNNING) {
logProblem("Parent node should be registered or running: " + parentNode + ", " + startedNodeEvent);
return null;
}
@@ -212,11 +211,13 @@
public void onTestFinished(@NotNull final TestFinishedEvent testFinishedEvent) {
addToInvokeLater(new Runnable() {
public void run() {
- SMTestProxy testProxy = getProxyToFinish(testFinishedEvent);
- if (testProxy != null) {
+ Node node = findNodeToTerminate(testFinishedEvent);
+ if (node != null) {
+ SMTestProxy testProxy = node.getProxy();
testProxy.setDuration(testFinishedEvent.getDuration());
testProxy.setFinished();
fireOnTestFinished(testProxy);
+ terminateNode(node, State.FINISHED);
}
}
});
@@ -225,24 +226,25 @@
public void onSuiteFinished(@NotNull final TestSuiteFinishedEvent suiteFinishedEvent) {
addToInvokeLater(new Runnable() {
public void run() {
- SMTestProxy suiteProxy = getProxyToFinish(suiteFinishedEvent);
- if (suiteProxy != null) {
+ Node node = findNodeToTerminate(suiteFinishedEvent);
+ if (node != null) {
+ SMTestProxy suiteProxy = node.getProxy();
suiteProxy.setFinished();
fireOnSuiteFinished(suiteProxy);
+ terminateNode(node, State.FINISHED);
}
}
});
}
@Nullable
- private SMTestProxy getProxyToFinish(@NotNull TreeNodeEvent treeNodeEvent) {
- Node finishedNode = findNode(treeNodeEvent);
- if (finishedNode == null) {
- logProblem("Trying to finish not started node: " + treeNodeEvent);
+ private Node findNodeToTerminate(@NotNull TreeNodeEvent treeNodeEvent) {
+ Node node = findNode(treeNodeEvent);
+ if (node == null) {
+ logProblem("Trying to finish not existent node: " + treeNodeEvent);
return null;
}
- stopRunningNode(finishedNode, State.FINISHED, treeNodeEvent);
- return finishedNode.getProxy();
+ return node;
}
public void onUncapturedOutput(@NotNull final String text, final Key outputType) {
@@ -301,12 +303,10 @@
public void onTestFailure(@NotNull final TestFailedEvent testFailedEvent) {
addToInvokeLater(new Runnable() {
public void run() {
- Node node = findNode(testFailedEvent);
+ Node node = findNodeToTerminate(testFailedEvent);
if (node == null) {
- logProblem("Test wasn't started! " + testFailedEvent + ".");
return;
}
- stopRunningNode(node, State.FAILED, testFailedEvent);
SMTestProxy testProxy = node.getProxy();
@@ -329,6 +329,8 @@
// fire event
fireOnTestFailed(testProxy);
+
+ terminateNode(node, State.FAILED);
}
});
}
@@ -336,18 +338,14 @@
public void onTestIgnored(@NotNull final TestIgnoredEvent testIgnoredEvent) {
addToInvokeLater(new Runnable() {
public void run() {
- Node node = findNode(testIgnoredEvent);
- if (node == null) {
- logProblem("Test wasn't started! " + testIgnoredEvent + ".");
- return;
+ Node node = findNodeToTerminate(testIgnoredEvent);
+ if (node != null) {
+ SMTestProxy testProxy = node.getProxy();
+ testProxy.setTestIgnored(testIgnoredEvent.getIgnoreComment(), testIgnoredEvent.getStacktrace());
+ // fire event
+ fireOnTestIgnored(testProxy);
+ terminateNode(node, State.IGNORED);
}
- stopRunningNode(node, State.IGNORED, testIgnoredEvent);
-
- SMTestProxy testProxy = node.getProxy();
- testProxy.setTestIgnored(testIgnoredEvent.getIgnoreComment(), testIgnoredEvent.getStacktrace());
-
- // fire event
- fireOnTestIgnored(testProxy);
}
});
}
@@ -479,75 +477,45 @@
public void run() {
myEventsListeners.clear();
- if (!myRunningNodes.isEmpty()) {
+ if (!myRunningTestNodes.isEmpty()) {
Application application = ApplicationManager.getApplication();
if (!application.isHeadlessEnvironment() && !application.isUnitTestMode()) {
logProblem("Not all events were processed!");
}
}
- myRunningNodes.clear();
+ myRunningTestNodes.clear();
myNodeByIdMap.clear();
}
});
}
- private void stopRunningNode(@NotNull Node node, @NotNull State stoppedState, @NotNull TreeNodeEvent event) {
- if (stoppedState == State.RUNNING) {
- throw new RuntimeException("newState shouldn't be " + State.RUNNING);
+ private void setNodeAndAncestorsRunning(@NotNull Node lowestNode) {
+ Node node = lowestNode;
+ while (node != null && node != myTestsRootNode && node.getState() == State.NOT_RUNNING) {
+ node.setState(State.RUNNING);
+ SMTestProxy proxy = node.getProxy();
+ proxy.setStarted();
+ if (proxy.isSuite()) {
+ fireOnSuiteStarted(proxy);
+ } else {
+ myRunningTestNodes.add(lowestNode);
+ fireOnTestStarted(proxy);
+ }
+ node = node.getParentNode();
}
- // check if has been already processed
- if (node.getState() != State.RUNNING) {
- logProblem("Can't change state of already stopped node" + node + " to " + stoppedState + ", " + event + ".");
- return;
- }
- myRunningNodes.remove(node);
- node.setState(stoppedState);
+ }
+
+ private void terminateNode(@NotNull Node node, @NotNull State terminateState) {
+ node.setState(terminateState);
+ myRunningTestNodes.remove(node);
}
@NotNull
private Node findActiveNode() {
- List<Node> runningLeaves = ContainerUtil.newArrayListWithExpectedSize(1);
- for (Node node : myRunningNodes) {
- if (!node.hasRunningChildren()) {
- runningLeaves.add(node);
- }
- }
- if (runningLeaves.isEmpty()) {
+ if (myRunningTestNodes.isEmpty()) {
return myTestsRootNode;
}
- if (runningLeaves.size() == 1) {
- return runningLeaves.iterator().next();
- }
- List<Node> commonPathToRoot = null;
- for (Node leaf : runningLeaves) {
- List<Node> pathToRoot = leaf.getAncestorsFromParentToRoot();
- if (commonPathToRoot == null) {
- commonPathToRoot = pathToRoot;
- } else {
- commonPathToRoot = intersectPathsToRoot(commonPathToRoot, pathToRoot);
- }
- }
- if (commonPathToRoot == null || commonPathToRoot.isEmpty()) {
- throw new RuntimeException("Unexpected common path to root: " + commonPathToRoot + ", running leaves: " + runningLeaves);
- }
- return commonPathToRoot.get(0);
- }
-
- @NotNull
- private static List<Node> intersectPathsToRoot(@NotNull List<Node> pathToRoot1, @NotNull List<Node> pathToRoot2) {
- final int minSize = Math.min(pathToRoot1.size(), pathToRoot2.size());
- final int shift1 = pathToRoot1.size() - minSize;
- final int shift2 = pathToRoot2.size() - minSize;
- int commonSize = 0;
- for (int i = 0; i < minSize; i++) {
- Node node1 = pathToRoot1.get(i + shift1);
- Node node2 = pathToRoot2.get(i + shift2);
- if (node1 == node2) {
- commonSize = minSize - i;
- break;
- }
- }
- return pathToRoot1.subList(pathToRoot1.size() - commonSize, pathToRoot1.size());
+ return myRunningTestNodes.iterator().next();
}
private void logProblem(@NotNull String msg) {
@@ -565,7 +533,7 @@
}
private enum State {
- REGISTERED, RUNNING, FINISHED, FAILED, IGNORED
+ NOT_RUNNING, RUNNING, FINISHED, FAILED, IGNORED
}
private static class Node {
@@ -573,16 +541,12 @@
private final Node myParentNode;
private final SMTestProxy myProxy;
private State myState;
- private int myRunningChildCount = 0;
- Node(int id, @Nullable Node parentNode, @NotNull SMTestProxy proxy, @NotNull State initialState) {
+ Node(int id, @Nullable Node parentNode, @NotNull SMTestProxy proxy) {
myId = id;
myParentNode = parentNode;
myProxy = proxy;
- myState = initialState;
- if (myParentNode != null) {
- myParentNode.myRunningChildCount++;
- }
+ myState = State.NOT_RUNNING;
}
public int getId() {
@@ -606,17 +570,11 @@
public void setState(@NotNull State newState) {
boolean accepted = false;
- if (myState == State.REGISTERED) {
- accepted = newState != State.REGISTERED;
- }
- else if (myState == State.RUNNING) {
- accepted = newState != State.REGISTERED && newState != State.RUNNING;
- }
- if (myParentNode != null && newState != State.REGISTERED && newState != State.RUNNING) {
- myParentNode.myRunningChildCount--;
+ if (myState == State.NOT_RUNNING || myState == State.RUNNING) {
+ accepted = myState.ordinal() < newState.ordinal();
}
if (!accepted) {
- throw new RuntimeException("Attempt to change state from " + myState + " to " + newState + ":" + toString());
+ throw new RuntimeException("Illegal state change [" + myState + " -> " + newState + "]: " + toString());
}
myState = newState;
}
@@ -646,20 +604,6 @@
", state=" + myState +
'}';
}
-
- public boolean hasRunningChildren() {
- return myRunningChildCount > 0;
- }
-
- @NotNull
- public List<Node> getAncestorsFromParentToRoot() {
- List<Node> ancestors = ContainerUtil.newArrayList();
- Node parent = getParentNode();
- while (parent != null) {
- ancestors.add(parent);
- parent = parent.getParentNode();
- }
- return ancestors;
- }
}
+
}
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
index 6119de8..8532b9a 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/GeneralToSMTRunnerEventsConvertor.java
@@ -17,13 +17,14 @@
import com.intellij.execution.process.ProcessOutputTypes;
import com.intellij.execution.testframework.AbstractTestProxy;
-import com.intellij.execution.testframework.sm.SMRunnerUtil;
import com.intellij.execution.testframework.sm.SMTestRunnerConnectionUtil;
+import com.intellij.execution.testframework.sm.SMTestsRunnerBundle;
import com.intellij.execution.testframework.sm.runner.events.*;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.testIntegration.TestLocationProvider;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
@@ -339,7 +340,10 @@
addToInvokeLater(new Runnable() {
public void run() {
final String testName = ObjectUtils.assertNotNull(testIgnoredEvent.getName());
- final String ignoreComment = testIgnoredEvent.getIgnoreComment();
+ String ignoreComment = testIgnoredEvent.getIgnoreComment();
+ if (StringUtil.isEmpty(ignoreComment)) {
+ ignoreComment = SMTestsRunnerBundle.message("sm.test.runner.states.test.is.ignored");
+ }
final String stackTrace = testIgnoredEvent.getStacktrace();
final String fullTestName = getFullTestName(testName);
SMTestProxy testProxy = getProxyByFullTestName(fullTestName);
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java
index 1ee0b76..14a9495 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputLineSplitter.java
@@ -131,9 +131,8 @@
myStdOutChunks.clear();
}
- final boolean isTCLikeFakeOutput = chunks.size() == 1;
for (OutputChunk chunk : chunks) {
- onLineAvailable(chunk.getText(), chunk.getKey(), isTCLikeFakeOutput);
+ onLineAvailable(chunk.getText(), chunk.getKey(), false);
}
}
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java
index d03730c..3768422 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestEventsConverter.java
@@ -363,7 +363,7 @@
}
public void visitTestStdErr(@NotNull final TestStdErr testStdErr) {
- fireOnTestOutput(new TestOutputEvent(testStdErr.getTestName(), testStdErr.getStdErr(), false));
+ fireOnTestOutput(new TestOutputEvent(testStdErr, testStdErr.getStdErr(), false));
}
public void visitTestFailed(@NotNull final TestFailed testFailed) {
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java
index 685b71e..977a28f 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleProperties.java
@@ -45,27 +45,44 @@
public class SMTRunnerConsoleProperties extends TestConsoleProperties implements SMStacktraceParser {
private final RunConfiguration myConfiguration;
protected final CompositeFilter myCustomFilter;
+ private final boolean myPrintTestingStartedTime;
/**
* @param config
* @param testFrameworkName Prefix for storage which keeps runner settings. E.g. "RubyTestUnit"
* @param executor
*/
- public SMTRunnerConsoleProperties(@NotNull final RunConfiguration config,
- @NotNull final String testFrameworkName,
- @NotNull final Executor executor)
- {
+ public SMTRunnerConsoleProperties(@NotNull RunConfiguration config,
+ @NotNull String testFrameworkName,
+ @NotNull Executor executor) {
+ this(config, testFrameworkName, executor, true);
+ }
+
+ /**
+ * @param config
+ * @param testFrameworkName Prefix for storage which keeps runner settings. E.g. "RubyTestUnit"
+ * @param executor
+ */
+ public SMTRunnerConsoleProperties(@NotNull RunConfiguration config,
+ @NotNull String testFrameworkName,
+ @NotNull Executor executor,
+ boolean printTestingStartedTime) {
super(new Storage.PropertiesComponentStorage(testFrameworkName + "Support.", PropertiesComponent.getInstance()),
config.getProject(),
executor);
myConfiguration = config;
myCustomFilter = new CompositeFilter(config.getProject());
+ myPrintTestingStartedTime = printTestingStartedTime;
}
public RunConfiguration getConfiguration() {
return myConfiguration;
}
+ public boolean isPrintTestingStartedTime() {
+ return myPrintTestingStartedTime;
+ }
+
@Override
public Navigatable getErrorNavigatable(@NotNull final Project project, final @NotNull String stacktrace) {
if (myCustomFilter.isEmpty()) {
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
index 8eeed5e..632be05 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java
@@ -143,6 +143,13 @@
return false;
}
+ /**
+ * @return true if the state is final (PASSED, FAILED, IGNORED, TERMINATED)
+ */
+ public boolean isFinal() {
+ return myState.isFinal();
+ }
+
private void setStacktraceIfNotSet(@Nullable String stacktrace) {
if (myStacktrace == null) myStacktrace = stacktrace;
}
@@ -397,8 +404,7 @@
fireOnNewPrintable(myState);
}
- public void setTestIgnored(@NotNull final String ignoreComment,
- @Nullable final String stackTrace) {
+ public void setTestIgnored(@Nullable String ignoreComment, @Nullable String stackTrace) {
setStacktraceIfNotSet(stackTrace);
myState = new TestIgnoredState(ignoreComment, stackTrace);
fireOnNewPrintable(myState);
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestIgnoredEvent.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestIgnoredEvent.java
index 2237a86..ada2b8c 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestIgnoredEvent.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/events/TestIgnoredEvent.java
@@ -38,7 +38,7 @@
myStacktrace = stacktrace;
}
- @NotNull
+ @Nullable
public String getIgnoreComment() {
return myIgnoreComment;
}
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
index d428020..d454ae0 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/SuiteInProgressState.java
@@ -25,27 +25,27 @@
*/
public class SuiteInProgressState extends TestInProgressState {
private final SMTestProxy mySuiteProxy;
- private Boolean isDefectWasReallyFound = null; // null - is unset
+ private boolean myDefectFound = false;
public SuiteInProgressState(@NotNull final SMTestProxy suiteProxy) {
mySuiteProxy = suiteProxy;
}
-
- ///**
- // * If any of child failed proxy also is defect
- // * @return
- // */
+
+ /**
+ * If any of child failed proxy also is defect
+ * @return
+ */
@Override
public boolean isDefect() {
- if (isDefectWasReallyFound != null) {
- return isDefectWasReallyFound.booleanValue();
+ if (myDefectFound) {
+ return true;
}
//Test suit fails if any of its tests fails
final List<? extends SMTestProxy> children = mySuiteProxy.getChildren();
for (SMTestProxy child : children) {
if (child.isDefect()) {
- isDefectWasReallyFound = true;
+ myDefectFound = true;
return true;
}
}
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestIgnoredState.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestIgnoredState.java
index 73fb154..f2363a2 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestIgnoredState.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/states/TestIgnoredState.java
@@ -17,24 +17,24 @@
import com.intellij.execution.testframework.CompositePrintable;
import com.intellij.execution.testframework.Printer;
-import com.intellij.execution.testframework.sm.SMTestsRunnerBundle;
-import com.intellij.execution.testframework.sm.runner.SMTestProxy;
import com.intellij.execution.ui.ConsoleViewContentType;
import com.intellij.openapi.util.text.StringUtil;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
/**
* @author Roman Chernyatchik
*/
public class TestIgnoredState extends AbstractState {
- @NonNls private static final String IGNORED_TEST_TEXT = SMTestsRunnerBundle.message("sm.test.runner.states.test.is.ignored");
private final String myText;
private final String myStacktrace;
- public TestIgnoredState(final String ignoredComment, @Nullable final String stackTrace) {
- final String ignored_msg = StringUtil.isEmpty(ignoredComment) ? IGNORED_TEST_TEXT : ignoredComment;
- myText = CompositePrintable.NEW_LINE + ignored_msg;
+ public TestIgnoredState(@Nullable String ignoredMsg, @Nullable final String stackTrace) {
+ if (StringUtil.isEmpty(ignoredMsg)) {
+ myText = null;
+ }
+ else {
+ myText = CompositePrintable.NEW_LINE + ignoredMsg;
+ }
myStacktrace = stackTrace == null ? null : stackTrace + CompositePrintable.NEW_LINE;
}
@@ -66,11 +66,10 @@
public void printOn(final Printer printer) {
super.printOn(printer);
- printer.print(myText, ConsoleViewContentType.SYSTEM_OUTPUT);
- if (StringUtil.isEmptyOrSpaces(myStacktrace)) {
- printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.SYSTEM_OUTPUT);
+ if (myText != null) {
+ printer.print(myText, ConsoleViewContentType.SYSTEM_OUTPUT);
}
- else {
+ if (!StringUtil.isEmptyOrSpaces(myStacktrace)) {
printer.print(CompositePrintable.NEW_LINE, ConsoleViewContentType.ERROR_OUTPUT);
printer.mark();
printer.print(myStacktrace, ConsoleViewContentType.ERROR_OUTPUT);
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerConsoleView.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerConsoleView.java
index 7aea8e9..5f52099 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerConsoleView.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTRunnerConsoleView.java
@@ -55,6 +55,7 @@
mySplitterProperty = splitterProperty;
}
+ @Override
protected TestResultsPanel createTestResultsPanel() {
// Results View
myResultsViewer = new SMTestRunnerResultsForm(myProperties.getConfiguration(),
@@ -72,6 +73,7 @@
// Console
myResultsViewer.addEventsListener(new TestResultsViewer.SMEventsAdapter() {
+ @Override
public void onSelected(@Nullable final SMTestProxy selectedTestProxy,
@NotNull final TestResultsViewer viewer,
@NotNull final TestFrameworkRunningModel model) {
@@ -81,6 +83,7 @@
// print selected content
SMRunnerUtil.runInEventDispatchThread(new Runnable() {
+ @Override
public void run() {
getPrinter().updateOnTestSelected(selectedTestProxy);
}
@@ -100,8 +103,9 @@
* @param contentType given type
*/
@Override
- public void print(final String s, final ConsoleViewContentType contentType) {
+ public void print(@NotNull final String s, @NotNull final ConsoleViewContentType contentType) {
myResultsViewer.getRoot().addLast(new Printable() {
+ @Override
public void printOn(final Printer printer) {
printer.print(s, contentType);
}
diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java
index b2ea380..cb219ff 100644
--- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java
+++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/ui/SMTestRunnerResultsForm.java
@@ -19,10 +19,7 @@
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.testframework.*;
import com.intellij.execution.testframework.sm.SMRunnerUtil;
-import com.intellij.execution.testframework.sm.runner.SMTRunnerEventsListener;
-import com.intellij.execution.testframework.sm.runner.SMTRunnerTreeBuilder;
-import com.intellij.execution.testframework.sm.runner.SMTRunnerTreeStructure;
-import com.intellij.execution.testframework.sm.runner.SMTestProxy;
+import com.intellij.execution.testframework.sm.runner.*;
import com.intellij.execution.testframework.sm.runner.ui.statistics.StatisticsPanel;
import com.intellij.execution.testframework.ui.AbstractTestTreeBuilder;
import com.intellij.execution.testframework.ui.TestResultsPanel;
@@ -89,6 +86,7 @@
// custom progress
private String myCurrentCustomProgressCategory;
private final Set<String> myMentionedCategories = new LinkedHashSet<String>();
+ private boolean myTestsRunning = true;
public SMTestRunnerResultsForm(final RunConfiguration runConfiguration,
@NotNull final JComponent console,
@@ -217,9 +215,15 @@
selectAndNotify(myTestsRootNode);
myStartTime = System.currentTimeMillis();
- myTestsRootNode.addSystemOutput("Testing started at "
- + DateFormatUtil.formatTime(myStartTime)
- + " ...\n");
+ boolean printTestingStartedTime = true;
+ if (myConsoleProperties instanceof SMTRunnerConsoleProperties) {
+ printTestingStartedTime = ((SMTRunnerConsoleProperties) myConsoleProperties).isPrintTestingStartedTime();
+ }
+ if (printTestingStartedTime) {
+ myTestsRootNode.addSystemOutput("Testing started at "
+ + DateFormatUtil.formatTime(myStartTime)
+ + " ...\n");
+ }
updateStatusLabel(false);
@@ -244,10 +248,12 @@
LvcsHelper.addLabel(this);
- SMTestProxy root = getTestsRootNode();
- if (root != null) {
- selectAndNotify(root);
- }
+ selectAndNotify(myTestsRootNode, new Runnable() {
+ @Override
+ public void run() {
+ myTestsRunning = false;
+ }
+ });
fireOnTestingFinished();
}
@@ -331,7 +337,7 @@
}
public boolean isRunning() {
- return getRoot().isInProgress();
+ return myTestsRunning;
}
public TestTreeView getTreeView() {
@@ -362,8 +368,13 @@
*
* @param testProxy Test or suite
*/
- public void selectAndNotify(@Nullable final AbstractTestProxy testProxy) {
- selectWithoutNotify(testProxy);
+ @Override
+ public void selectAndNotify(AbstractTestProxy testProxy) {
+ selectAndNotify(testProxy, null);
+ }
+
+ private void selectAndNotify(@Nullable final AbstractTestProxy testProxy, @Nullable Runnable onDone) {
+ selectWithoutNotify(testProxy, onDone);
// Is used by Statistic tab to differ use selection in tree
// from manual selection from API (e.g. test runner events)
@@ -471,7 +482,7 @@
}
}
- private void selectWithoutNotify(final AbstractTestProxy testProxy) {
+ private void selectWithoutNotify(final AbstractTestProxy testProxy, @Nullable final Runnable onDone) {
if (testProxy == null) {
return;
}
@@ -481,7 +492,7 @@
if (myTreeBuilder.isDisposed()) {
return;
}
- myTreeBuilder.select(testProxy, null);
+ myTreeBuilder.select(testProxy, onDone);
}
}, ModalityState.NON_MODAL);
}
@@ -544,7 +555,7 @@
final boolean requestFocus) {
SMRunnerUtil.addToInvokeLater(new Runnable() {
public void run() {
- selectWithoutNotify(selectedTestProxy);
+ selectWithoutNotify(selectedTestProxy, null);
// Request focus if necessary
if (requestFocus) {
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java
index 2fafd49..409d992 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/OutputToGeneralTestsEventsConverterTest.java
@@ -43,40 +43,35 @@
}
public void testLineBreaks_ServiceMessage() {
- doCheckOutptut("\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\n", "", true);
+ doCheckOutptut("\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\n", "[stdout]\n", true);
}
public void testLineBreaks_NormalOutput() {
doCheckOutptut("\na\nb\n\nc\n", "[stdout]\n" +
- "[stdout]a" +
+ "[stdout]a\n" +
+ "[stdout]b\n" +
"[stdout]\n" +
- "[stdout]b" +
- "[stdout]\n" +
- "[stdout]\n" +
- "[stdout]c" +
- "[stdout]\n",
+ "[stdout]c\n",
true);
}
public void testLineBreaks_OutptutAndCommands() {
doCheckOutptut("\na\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\nb\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\n\nc\n",
"[stdout]\n" +
- "[stdout]a" +
- "[stdout]b" +
+ "[stdout]a\n" +
+ "[stdout]b\n" +
"[stdout]\n" +
- "[stdout]c" +
- "[stdout]\n",
+ "[stdout]c\n",
true);
}
public void testLineBreaks_AutoSplitIfProcessHandlerDoestSupportIt() {
doCheckOutptut("\na\n##teamcity[enteredTheMatrix timestamp = '2011-06-03T13:00:08.259+0400']\nb\n##teamcity[testCount count = '1' timestamp = '2011-06-03T13:00:08.259+0400']\n\nc\n",
"[stdout]\n" +
- "[stdout]a" +
- "[stdout]b" +
+ "[stdout]a\n" +
+ "[stdout]b\n" +
"[stdout]\n" +
- "[stdout]c" +
- "[stdout]\n",
+ "[stdout]c\n",
false);
}
diff --git a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java
index 4593c6f..0682c4f 100644
--- a/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java
+++ b/platform/smRunner/testSrc/com/intellij/execution/testframework/sm/runner/SMTRunnerConsoleTest.java
@@ -394,11 +394,11 @@
myEventsProcessor.onTestOutput(new TestOutputEvent("my_test", "stdout1 ", true));
myEventsProcessor.onTestOutput(new TestOutputEvent("my_test", "stderr1 ", false));
- assertAllOutputs(myMockResettablePrinter, "stdout1 ", "stderr1 ", "\nignored msg\n");
+ assertAllOutputs(myMockResettablePrinter, "stdout1 ", "stderr1 ", "\nignored msg");
final MockPrinter mockPrinter1 = new MockPrinter(true);
mockPrinter1.onNewAvailable(myTest1);
- assertAllOutputs(mockPrinter1, "stdout1 ", "stderr1 ", "\nignored msg\n");
+ assertAllOutputs(mockPrinter1, "stdout1 ", "stderr1 ", "\nignored msg");
//other output order
final SMTestProxy myTest2 = startTestWithPrinter("my_test2");
@@ -406,10 +406,10 @@
myEventsProcessor.onTestOutput(new TestOutputEvent("my_test2", "stderr1 ", false));
myEventsProcessor.onTestIgnored(new TestIgnoredEvent("my_test2", "ignored msg", null));
- assertAllOutputs(myMockResettablePrinter, "stdout1 ", "stderr1 ", "\nignored msg\n");
+ assertAllOutputs(myMockResettablePrinter, "stdout1 ", "stderr1 ", "\nignored msg");
final MockPrinter mockPrinter2 = new MockPrinter(true);
mockPrinter2.onNewAvailable(myTest2);
- assertAllOutputs(mockPrinter2, "stdout1 ", "stderr1 ", "\nignored msg\n");
+ assertAllOutputs(mockPrinter2, "stdout1 ", "stderr1 ", "\nignored msg");
}
public void testProcessor_OnIgnored_WithStacktrace() {
diff --git a/platform/testFramework/src/com/intellij/ClassFinder.java b/platform/testFramework/src/com/intellij/ClassFinder.java
index b4a8f7d..e69c9b6 100644
--- a/platform/testFramework/src/com/intellij/ClassFinder.java
+++ b/platform/testFramework/src/com/intellij/ClassFinder.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 @@
package com.intellij;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
import java.io.File;
@@ -33,7 +34,6 @@
import java.util.Collection;
import java.util.List;
-import static com.intellij.util.containers.ContainerUtil.addIfNotNull;
public class ClassFinder {
private final List<String> classNameList = new ArrayList<String>();
@@ -61,7 +61,7 @@
}
}
else {
- addIfNotNull(classNameList, computeClassName(current));
+ ContainerUtil.addIfNotNull(classNameList, computeClassName(current));
}
}
diff --git a/platform/testFramework/src/com/intellij/TestAll.java b/platform/testFramework/src/com/intellij/TestAll.java
index 3f842e7..d827982 100644
--- a/platform/testFramework/src/com/intellij/TestAll.java
+++ b/platform/testFramework/src/com/intellij/TestAll.java
@@ -146,7 +146,7 @@
currentThread.interrupt();
if (!currentThread.isInterrupted()) {
//noinspection deprecation
- currentThread.stop(new RuntimeException("Current Test Interrupted: OUT OF TIME!"));
+ currentThread.stop();
}
break;
diff --git a/platform/testFramework/src/com/intellij/idea/Bombed.java b/platform/testFramework/src/com/intellij/idea/Bombed.java
index 733b54d..8eb5480 100644
--- a/platform/testFramework/src/com/intellij/idea/Bombed.java
+++ b/platform/testFramework/src/com/intellij/idea/Bombed.java
@@ -25,7 +25,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface Bombed {
- int year() default 2013;
+ int year() default 2014;
@JdkConstants.CalendarMonth int month();
int day();
int time() default 0;
diff --git a/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java b/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java
index 154e04e..79aac28 100644
--- a/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java
+++ b/platform/testFramework/src/com/intellij/idea/IdeaTestApplication.java
@@ -15,7 +15,7 @@
*/
package com.intellij.idea;
-import com.intellij.ide.plugins.PluginManager;
+import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.Application;
@@ -25,6 +25,7 @@
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.util.Disposer;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class IdeaTestApplication extends CommandLineApplication implements Disposable {
@@ -46,10 +47,10 @@
public static synchronized IdeaTestApplication getInstance(@Nullable final String configPath) {
if (ourInstance == null) {
new IdeaTestApplication();
- PluginManager.getPlugins();
+ PluginManagerCore.getPlugins();
final ApplicationEx app = ApplicationManagerEx.getApplicationEx();
new WriteAction() {
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
app.load(configPath);
}
}.execute();
diff --git a/platform/testFramework/src/com/intellij/mock/MockApplicationEx.java b/platform/testFramework/src/com/intellij/mock/MockApplicationEx.java
deleted file mode 100644
index b334270..0000000
--- a/platform/testFramework/src/com/intellij/mock/MockApplicationEx.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.mock;
-
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ex.ApplicationEx;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.InvalidDataException;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.io.IOException;
-
-public class MockApplicationEx extends MockApplication implements ApplicationEx {
- public MockApplicationEx(@NotNull Disposable parentDisposable) {
- super(parentDisposable);
- }
-
- @NotNull
- @Override
- public String getName() {
- return "mock";
- }
-
- @Override
- public boolean holdsReadLock() {
- return false;
- }
-
- @Override
- public void load(String path) throws IOException, InvalidDataException {
- }
-
- @Override
- public boolean isLoaded() {
- return true;
- }
-
- @Override
- public void exit(boolean force) {
- }
-
- @Override
- public void restart(boolean force) {
- }
-
- @Override
- public void doNotSave() {
- }
-
- @Override
- public void doNotSave(boolean value) {
- }
-
- @Override
- public boolean isDoNotSave() {
- return false;
- }
-
- @Override
- public boolean runProcessWithProgressSynchronously(@NotNull final Runnable process, @NotNull final String progressTitle, final boolean canBeCanceled, @Nullable final Project project,
- final JComponent parentComponent) {
- return false;
- }
-
- @Override
- public boolean runProcessWithProgressSynchronously(@NotNull Runnable process,
- @NotNull String progressTitle,
- boolean canBeCanceled,
- @Nullable Project project,
- JComponent parentComponent,
- String cancelText) {
- return false;
- }
-
- @Override
- public boolean runProcessWithProgressSynchronously(@NotNull Runnable process,
- @NotNull String progressTitle,
- boolean canBeCanceled,
- Project project) {
- return false;
- }
-
- @NotNull
- @Override
- public <T> T[] getExtensions(@NotNull final ExtensionPointName<T> extensionPointName) {
- return Extensions.getRootArea().getExtensionPoint(extensionPointName).getExtensions();
- }
-
- @Override
- public void assertIsDispatchThread(@Nullable final JComponent component) {
- }
-
- @Override
- public void assertTimeConsuming() {
- }
-
- @Override
- public void runEdtSafeAction(@NotNull Runnable runnable) {
- runnable.run();
- }
-
- @Override
- public boolean tryRunReadAction(@NotNull Runnable runnable) {
- return false;
- }
-}
diff --git a/platform/testFramework/src/com/intellij/mock/MockDocument.java b/platform/testFramework/src/com/intellij/mock/MockDocument.java
index 6d62466..fc7b2d7 100644
--- a/platform/testFramework/src/com/intellij/mock/MockDocument.java
+++ b/platform/testFramework/src/com/intellij/mock/MockDocument.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.
@@ -46,6 +46,7 @@
myText.append(text);
}
+ @NotNull
@Override
public String getText() {
return myText.toString();
@@ -85,6 +86,12 @@
return getText();
}
+ @NotNull
+ @Override
+ public CharSequence getImmutableCharSequence() {
+ return getText();
+ }
+
@Override
public int getTextLength() {
return myText.length();
diff --git a/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java b/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java
index 05e865a..2881d4b 100644
--- a/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java
+++ b/platform/testFramework/src/com/intellij/mock/MockPsiDocumentManager.java
@@ -56,6 +56,12 @@
public void commitDocument(@NotNull Document document) {
}
+ @NotNull
+ @Override
+ public CharSequence getLastCommittedText(@NotNull Document document) {
+ return document.getImmutableCharSequence();
+ }
+
@Override
@NotNull
public Document[] getUncommittedDocuments() {
diff --git a/platform/testFramework/src/com/intellij/mock/MockRunManager.java b/platform/testFramework/src/com/intellij/mock/MockRunManager.java
index 9223337..b0797c7 100644
--- a/platform/testFramework/src/com/intellij/mock/MockRunManager.java
+++ b/platform/testFramework/src/com/intellij/mock/MockRunManager.java
@@ -188,10 +188,6 @@
}
@Override
- public void invalidateConfigurationIcon(@NotNull RunnerAndConfigurationSettings settings) {
- }
-
- @Override
@NotNull
public Collection<RunnerAndConfigurationSettings> getSortedConfigurations() {
return Collections.emptyList();
diff --git a/platform/testFramework/src/com/intellij/openapi/application/ex/PathManagerEx.java b/platform/testFramework/src/com/intellij/openapi/application/ex/PathManagerEx.java
index 3780351..4844851 100644
--- a/platform/testFramework/src/com/intellij/openapi/application/ex/PathManagerEx.java
+++ b/platform/testFramework/src/com/intellij/openapi/application/ex/PathManagerEx.java
@@ -338,7 +338,7 @@
}
private static boolean isJUnitClass(Class<?> clazz) {
- return TestCase.class.isAssignableFrom(clazz) || TestRunnerUtil.isJUnit4TestClass(clazz);
+ return TestCase.class.isAssignableFrom(clazz) || TestRunnerUtil.isJUnit4TestClass(clazz) || com.intellij.testFramework.Parameterized.class.isAssignableFrom(clazz);
}
@Nullable
@@ -358,6 +358,13 @@
return result;
}
+ public static void replaceLookupStrategy(Class<?> substitutor, Class<?>... initial) {
+ CLASS_STRATEGY_CACHE.clear();
+ for (Class<?> aClass : initial) {
+ CLASS_STRATEGY_CACHE.put(aClass, determineLookupStrategy(substitutor));
+ }
+ }
+
private static FileSystemLocation computeClassLocation(Class<?> clazz) {
String classRootPath = PathManager.getJarPathForClass(clazz);
if (classRootPath == null) {
diff --git a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
index 2400ed5..b80b235 100644
--- a/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/EditorTestUtil.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,7 +17,7 @@
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actionSystem.EditorActionManager;
import com.intellij.openapi.editor.actionSystem.TypedAction;
@@ -26,13 +26,20 @@
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.TextRange;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.tree.IElementType;
import junit.framework.Assert;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
/**
* User: Maxim.Mossienko
* Date: 15.03.2010
@@ -44,6 +51,8 @@
public static final String SELECTION_START_TAG = "<selection>";
public static final String SELECTION_END_TAG = "</selection>";
+ public static final String BLOCK_SELECTION_START_TAG = "<block>";
+ public static final String BLOCK_SELECTION_END_TAG = "</block>";
public static final char BACKSPACE_FAKE_CHAR = '\uFFFF';
public static final char SMART_ENTER_FAKE_CHAR = '\uFFFE';
@@ -173,4 +182,162 @@
applianceManager.registerSoftWrapIfNecessary();
return !model.getRegisteredSoftWraps().isEmpty();
}
+
+ /**
+ * Equivalent to <code>extractCaretAndSelectionMarkers(document, true)</code>.
+ *
+ * @see #extractCaretAndSelectionMarkers(com.intellij.openapi.editor.Document, boolean)
+ */
+ public static CaretsState extractCaretAndSelectionMarkers(Document document) {
+ return extractCaretAndSelectionMarkers(document, true);
+ }
+
+ /**
+ * Removes <caret>, <selection> and </selection> tags from document and returns a list of caret positions and selection
+ * ranges for each caret. Both caret positions and selection ranges can be null in the returned data.
+ *
+ * Should be invoked in write action, as it modifies the document!
+ *
+ * @param processBlockSelection if <code>true</code>, <block> and </block> tags describing a block selection state will also be extracted.
+ */
+ public static CaretsState extractCaretAndSelectionMarkers(Document document, boolean processBlockSelection) {
+ CaretsState result = new CaretsState();
+
+ String fileText = document.getText();
+
+ RangeMarker blockSelectionStartMarker = null;
+ RangeMarker blockSelectionEndMarker = null;
+ if (processBlockSelection) {
+ int blockSelectionStart = fileText.indexOf(BLOCK_SELECTION_START_TAG);
+ int blockSelectionEnd = fileText.indexOf(BLOCK_SELECTION_END_TAG);
+ if ((blockSelectionStart ^ blockSelectionEnd) < 0) {
+ throw new IllegalArgumentException("Both block selection opening and closing tag must be present");
+ }
+ if (blockSelectionStart >= 0) {
+ blockSelectionStartMarker = document.createRangeMarker(blockSelectionStart, blockSelectionStart);
+ blockSelectionEndMarker = document.createRangeMarker(blockSelectionEnd, blockSelectionEnd);
+ document.deleteString(blockSelectionStartMarker.getStartOffset(), blockSelectionStartMarker.getStartOffset() + BLOCK_SELECTION_START_TAG.length());
+ document.deleteString(blockSelectionEndMarker.getStartOffset(), blockSelectionEndMarker.getStartOffset() + BLOCK_SELECTION_END_TAG.length());
+ }
+ }
+
+ boolean multiCaret = StringUtil.getOccurrenceCount(document.getText(), CARET_TAG) > 1
+ || StringUtil.getOccurrenceCount(document.getText(), SELECTION_START_TAG) > 1;
+ int pos = 0;
+ while (pos < document.getTextLength()) {
+ fileText = document.getText();
+ int caretIndex = fileText.indexOf(CARET_TAG, pos);
+ int selStartIndex = fileText.indexOf(SELECTION_START_TAG, pos);
+ int selEndIndex = fileText.indexOf(SELECTION_END_TAG, pos);
+
+ if ((selStartIndex ^ selEndIndex) < 0) {
+ selStartIndex = -1;
+ selEndIndex = -1;
+ }
+ if (0 <= selEndIndex && selEndIndex < selStartIndex) {
+ throw new IllegalArgumentException("Wrong order of selection opening and closing tags");
+ }
+ if (caretIndex < 0 && selStartIndex < 0 && selEndIndex < 0) {
+ break;
+ }
+ if (multiCaret && 0 <= caretIndex && caretIndex < selStartIndex) {
+ selStartIndex = -1;
+ selEndIndex = -1;
+ }
+ if (multiCaret && caretIndex > selEndIndex && selEndIndex >= 0) {
+ caretIndex = -1;
+ }
+
+ final RangeMarker caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex) : null;
+ final RangeMarker selStartMarker = selStartIndex >= 0
+ ? document.createRangeMarker(selStartIndex, selStartIndex)
+ : null;
+ final RangeMarker selEndMarker = selEndIndex >= 0
+ ? document.createRangeMarker(selEndIndex, selEndIndex)
+ : null;
+
+ if (caretMarker != null) {
+ document.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_TAG.length());
+ }
+ if (selStartMarker != null) {
+ document.deleteString(selStartMarker.getStartOffset(),
+ selStartMarker.getStartOffset() + SELECTION_START_TAG.length());
+ }
+ if (selEndMarker != null) {
+ document.deleteString(selEndMarker.getStartOffset(),
+ selEndMarker.getStartOffset() + SELECTION_END_TAG.length());
+ }
+
+ result.carets.add(new Caret(caretMarker == null ? null : caretMarker.getStartOffset(),
+ selStartMarker == null || selEndMarker == null
+ ? null
+ : new TextRange(selStartMarker.getStartOffset(), selEndMarker.getEndOffset())));
+
+ pos = Math.max(caretMarker == null ? -1 : caretMarker.getStartOffset(), selEndMarker == null ? -1 : selEndMarker.getEndOffset());
+ }
+ if (result.carets.isEmpty()) {
+ result.carets.add(new Caret(null, null));
+ }
+ if (blockSelectionStartMarker != null) {
+ result.blockSelection = new TextRange(blockSelectionStartMarker.getStartOffset(), blockSelectionEndMarker.getStartOffset());
+ }
+
+ return result;
+ }
+
+ public static void verifyCaretAndSelectionState(Editor editor, CaretsState caretState) {
+ CaretModel caretModel = editor.getCaretModel();
+ List<com.intellij.openapi.editor.Caret> allCarets = new ArrayList<com.intellij.openapi.editor.Caret>(caretModel.getAllCarets());
+ assertEquals("Unexpected number of carets", caretState.carets.size(), allCarets.size());
+ for (int i = 0; i < caretState.carets.size(); i++) {
+ String caretDescription = caretState.carets.size() == 1 ? "" : "caret " + (i + 1) + "/" + caretState.carets.size() + " ";
+ com.intellij.openapi.editor.Caret currentCaret = allCarets.get(i);
+ LogicalPosition actualCaretPosition = currentCaret.getLogicalPosition();
+ LogicalPosition actualSelectionStart = editor.offsetToLogicalPosition(currentCaret.getSelectionStart());
+ LogicalPosition actualSelectionEnd = editor.offsetToLogicalPosition(currentCaret.getSelectionEnd());
+ EditorTestUtil.Caret expected = caretState.carets.get(i);
+ if (expected.offset != null) {
+ LogicalPosition expectedCaretPosition = editor.offsetToLogicalPosition(expected.offset);
+ assertEquals(caretDescription + "unexpected caret position", expectedCaretPosition, actualCaretPosition);
+ }
+ if (expected.selection != null) {
+ LogicalPosition expectedSelectionStart = editor.offsetToLogicalPosition(expected.selection.getStartOffset());
+ LogicalPosition expectedSelectionEnd = editor.offsetToLogicalPosition(expected.selection.getEndOffset());
+
+ assertEquals(caretDescription + "unexpected selection start", expectedSelectionStart, actualSelectionStart);
+ assertEquals(caretDescription + "unexpected selection end", expectedSelectionEnd, actualSelectionEnd);
+ }
+ else {
+ assertFalse(caretDescription + "should has no selection, but was: (" + actualSelectionStart + ", " + actualSelectionEnd + ")",
+ currentCaret.hasSelection());
+ }
+ }
+ }
+
+ public static void enableMultipleCarets() {
+ Registry.get("editor.allow.multiple.carets").setValue(true);
+ }
+
+ public static void disableMultipleCarets() {
+ Registry.get("editor.allow.multiple.carets").setValue(false);
+ }
+
+ public static class CaretsState {
+ @NotNull
+ public final List<Caret> carets = new ArrayList<Caret>();
+ @Nullable
+ public TextRange blockSelection;
+ }
+
+ public static class Caret {
+ @Nullable
+ public final Integer offset;
+ @Nullable
+ public final TextRange selection;
+
+ public Caret(Integer offset, TextRange selection) {
+ this.offset = offset;
+ this.selection = selection;
+ }
+ }
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java
index 4ae3f36..93de7cc 100644
--- a/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.java
+++ b/platform/testFramework/src/com/intellij/testFramework/ExpectedHighlightingData.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,11 @@
import com.intellij.codeInsight.daemon.impl.HighlightInfoType;
import com.intellij.codeInsight.daemon.impl.SeveritiesProvider;
import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.EffectType;
@@ -96,13 +97,14 @@
private final Map<RangeMarker, LineMarkerInfo> lineMarkerInfos = new THashMap<RangeMarker, LineMarkerInfo>();
public void init() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ new WriteCommandAction(null){
+ @Override
+ protected void run(Result result) throws Throwable {
extractExpectedLineMarkerSet(myDocument);
extractExpectedHighlightsSet(myDocument);
refreshLineMarkers();
}
- });
+ }.execute();
}
public ExpectedHighlightingData(@NotNull Document document,boolean checkWarnings, boolean checkInfos) {
@@ -136,7 +138,7 @@
for (SeveritiesProvider provider : Extensions.getExtensions(SeveritiesProvider.EP_NAME)) {
for (HighlightInfoType type : provider.getSeveritiesHighlightInfoTypes()) {
final HighlightSeverity severity = type.getSeverity(null);
- highlightingTypes.put(severity.toString(), new ExpectedHighlightingSet(severity, false, true));
+ highlightingTypes.put(severity.getName(), new ExpectedHighlightingSet(severity, false, true));
}
}
highlightingTypes.put(END_LINE_HIGHLIGHT_MARKER, new ExpectedHighlightingSet(HighlightSeverity.ERROR, true, true));
@@ -344,7 +346,8 @@
return toContinueFrom;
}
- private static final HighlightInfoType WHATEVER = new HighlightInfoType.HighlightInfoTypeImpl();
+ private static final HighlightInfoType WHATEVER = new HighlightInfoType.HighlightInfoTypeImpl(HighlightSeverity.INFORMATION,
+ HighlighterColors.TEXT);
public void checkLineMarkers(Collection<LineMarkerInfo> markerInfos, String text) {
String fileName = myFile == null ? "" : myFile.getName() + ": ";
diff --git a/platform/testFramework/src/com/intellij/testFramework/FileBasedTestCaseHelper.java b/platform/testFramework/src/com/intellij/testFramework/FileBasedTestCaseHelper.java
new file mode 100644
index 0000000..6156569
--- /dev/null
+++ b/platform/testFramework/src/com/intellij/testFramework/FileBasedTestCaseHelper.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 com.intellij.testFramework;
+
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Should be implemented by a test together with annotation @RunWith(com.intellij.testFramework.Parameterized.class)
+ * in order to get test run on all test data files located in directory. The desired directory could be configured
+ * whether by implementing {@link FileBasedTestCaseHelperEx#getRelativeBasePath()} or by annotating test case
+ * with {@link com.intellij.testFramework.TestDataPath} (annotation would enable additional test assistance support, e.g.
+ * navigation from test data to test class/method as well as starting tests right from test data files).
+ * <br/><br/>
+ * BTW @RunWith works also on abstract super classes.
+ * @see LightPlatformCodeInsightTestCase#params(java.lang.Class<?>)
+ */
+public interface FileBasedTestCaseHelper {
+ /**
+ * @return for 'before' files should return core file name or null otherwise
+ */
+ @Nullable
+ String getFileSuffix(String fileName);
+}
diff --git a/platform/testFramework/src/com/intellij/testFramework/FileBasedTestCaseHelperEx.java b/platform/testFramework/src/com/intellij/testFramework/FileBasedTestCaseHelperEx.java
new file mode 100644
index 0000000..f14df27
--- /dev/null
+++ b/platform/testFramework/src/com/intellij/testFramework/FileBasedTestCaseHelperEx.java
@@ -0,0 +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.testFramework;
+
+
+public interface FileBasedTestCaseHelperEx extends FileBasedTestCaseHelper {
+ /**
+ * @return path related to the test data root according to {@link LightPlatformCodeInsightTestCase#getTestDataPath()}
+ */
+ String getRelativeBasePath();
+}
diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
index 89feff1..e0e8e3d 100644
--- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformCodeInsightTestCase.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,15 @@
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.DocumentWindow;
import com.intellij.injected.editor.EditorWindow;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
@@ -36,7 +41,7 @@
import com.intellij.openapi.fileEditor.impl.TrailingSpacesStripper;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.ProjectManager;
-import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
@@ -54,9 +59,15 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runners.Parameterized;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
public abstract class LightPlatformCodeInsightTestCase extends LightPlatformTestCase {
private static final Logger LOG = Logger.getInstance("#com.intellij.testFramework.LightCodeInsightTestCase");
@@ -65,10 +76,6 @@
protected static PsiFile myFile;
protected static VirtualFile myVFile;
- private static final String CARET_MARKER = "<caret>";
- @NonNls private static final String SELECTION_START_MARKER = "<selection>";
- @NonNls private static final String SELECTION_END_MARKER = "</selection>";
-
@Override
protected void runTest() throws Throwable {
final Throwable[] throwable = {null};
@@ -114,7 +121,6 @@
* has <caret> marker where caret should be placed when file is loaded in editor and <selection></selection>
* denoting selection bounds.
* @param filePath - relative path from %IDEA_INSTALLATION_HOME%/testData/
- * @throws Exception
*/
protected void configureByFile(@TestDataFile @NonNls @NotNull String filePath) {
try {
@@ -130,6 +136,9 @@
@NonNls
@NotNull
protected String getTestDataPath() {
+ if (myTestDataPath != null) {
+ return myTestDataPath;
+ }
return PathManagerEx.getTestDataPath();
}
@@ -149,9 +158,9 @@
*/
@NotNull
protected static Document configureFromFileText(@NonNls @NotNull final String fileName, @NonNls @NotNull final String fileText) throws IOException {
- return ApplicationManager.getApplication().runWriteAction(new Computable<Document>() {
+ return new WriteCommandAction<Document>(null) {
@Override
- public Document compute() {
+ protected void run(@NotNull Result<Document> result) throws Throwable {
if (myVFile != null) {
// avoid messing with invalid files, in case someone calls configureXXX() several times
PsiDocumentManager.getInstance(ourProject).commitAllDocuments();
@@ -166,25 +175,7 @@
}
final Document fakeDocument = new DocumentImpl(fileText);
- int caretIndex = fileText.indexOf(CARET_MARKER);
- int selStartIndex = fileText.indexOf(SELECTION_START_MARKER);
- int selEndIndex = fileText.indexOf(SELECTION_END_MARKER);
-
- final RangeMarker caretMarker = caretIndex >= 0 ? fakeDocument.createRangeMarker(caretIndex, caretIndex) : null;
- final RangeMarker selStartMarker = selStartIndex >= 0 ? fakeDocument.createRangeMarker(selStartIndex, selStartIndex) : null;
- final RangeMarker selEndMarker = selEndIndex >= 0 ? fakeDocument.createRangeMarker(selEndIndex, selEndIndex) : null;
-
- if (caretMarker != null) {
- fakeDocument.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_MARKER.length());
- }
- if (selStartMarker != null) {
- fakeDocument.deleteString(selStartMarker.getStartOffset(),
- selStartMarker.getStartOffset() + SELECTION_START_MARKER.length());
- }
- if (selEndMarker != null) {
- fakeDocument.deleteString(selEndMarker.getStartOffset(),
- selEndMarker.getStartOffset() + SELECTION_END_MARKER.length());
- }
+ EditorTestUtil.CaretsState caretsState = EditorTestUtil.extractCaretAndSelectionMarkers(fakeDocument);
String newFileText = fakeDocument.getText();
Document document;
@@ -194,28 +185,46 @@
catch (IOException e) {
throw new RuntimeException(e);
}
- setupCaret(caretMarker, newFileText);
- setupSelection(selStartMarker, selEndMarker);
+ setupCaretAndSelection(caretsState, newFileText);
setupEditorForInjectedLanguage();
- return document;
+ result.setResult(document);
}
- });
+ }.execute().getResultObject();
}
- private static void setupSelection(final RangeMarker selStartMarker, final RangeMarker selEndMarker) {
- if (selStartMarker != null) {
- myEditor.getSelectionModel().setSelection(selStartMarker.getStartOffset(), selEndMarker.getStartOffset());
+ private static void setupCaretAndSelection(EditorTestUtil.CaretsState caretsState, String fileText) {
+ List<EditorTestUtil.Caret> carets = caretsState.carets;
+ if (myEditor.getCaretModel().supportsMultipleCarets()) {
+ List<LogicalPosition> caretPositions = new ArrayList<LogicalPosition>();
+ List<Segment> selections = new ArrayList<Segment>();
+ for (EditorTestUtil.Caret caret : carets) {
+ LogicalPosition pos = null;
+ if (caret.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(fileText, caret.offset);
+ int caretCol = EditorUtil.calcColumnNumber(null, myEditor.getDocument().getText(),
+ myEditor.getDocument().getLineStartOffset(caretLine), caret.offset,
+ CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE);
+ pos = new LogicalPosition(caretLine, caretCol);
+ }
+ caretPositions.add(pos);
+ selections.add(caret.selection == null ? null : caret.selection);
+ }
+ myEditor.getCaretModel().setCarets(caretPositions, selections);
}
- }
-
- private static void setupCaret(final RangeMarker caretMarker, String fileText) {
- if (caretMarker != null) {
- int caretLine = StringUtil.offsetToLineNumber(fileText, caretMarker.getStartOffset());
- int caretCol = EditorUtil.calcColumnNumber(null, myEditor.getDocument().getText(),
- myEditor.getDocument().getLineStartOffset(caretLine), caretMarker.getStartOffset(),
- CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE);
- LogicalPosition pos = new LogicalPosition(caretLine, caretCol);
- myEditor.getCaretModel().moveToLogicalPosition(pos);
+ else {
+ assertEquals("Caret model doesn't support multiple carets", 1, carets.size());
+ EditorTestUtil.Caret caret = carets.get(0);
+ if (caret.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(fileText, caret.offset);
+ int caretCol = EditorUtil.calcColumnNumber(null, myEditor.getDocument().getText(),
+ myEditor.getDocument().getLineStartOffset(caretLine), caret.offset,
+ CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE);
+ LogicalPosition pos = new LogicalPosition(caretLine, caretCol);
+ myEditor.getCaretModel().moveToLogicalPosition(pos);
+ }
+ if (caret.selection != null) {
+ myEditor.getSelectionModel().setSelection(caret.selection.getStartOffset(), caret.selection.getEndOffset());
+ }
}
}
@@ -290,7 +299,6 @@
* Validates that content of the editor as well as caret and selection matches one specified in data file that
* should be formed with the same format as one used in configureByFile
* @param filePath - relative path from %IDEA_INSTALLATION_HOME%/testData/
- * @throws Exception
*/
protected void checkResultByFile(@TestDataFile @NonNls @NotNull String filePath) {
checkResultByFile(null, filePath, false);
@@ -302,7 +310,6 @@
* @param message - this check specific message. Added to text, caret position, selection checking. May be null
* @param filePath - relative path from %IDEA_INSTALLATION_HOME%/testData/
* @param ignoreTrailingSpaces - whether trailing spaces in editor in data file should be stripped prior to comparing.
- * @throws Exception
*/
protected void checkResultByFile(@Nullable String message, @TestDataFile @NotNull String filePath, final boolean ignoreTrailingSpaces) {
bringRealEditorBack();
@@ -332,7 +339,6 @@
/**
* Same as checkResultByFile but text is provided directly.
- * @param fileText
*/
protected void checkResultByText(@NonNls @NotNull String fileText) {
checkResultByText(null, fileText, false, null);
@@ -341,7 +347,6 @@
/**
* Same as checkResultByFile but text is provided directly.
* @param message - this check specific message. Added to text, caret position, selection checking. May be null
- * @param fileText
* @param ignoreTrailingSpaces - whether trailing spaces in editor in data file should be stripped prior to comparing.
*/
protected void checkResultByText(final String message, @NotNull String fileText, final boolean ignoreTrailingSpaces) {
@@ -351,7 +356,6 @@
/**
* Same as checkResultByFile but text is provided directly.
* @param message - this check specific message. Added to text, caret position, selection checking. May be null
- * @param fileText
* @param ignoreTrailingSpaces - whether trailing spaces in editor in data file should be stripped prior to comparing.
*/
protected void checkResultByText(final String message, @NotNull final String fileText, final boolean ignoreTrailingSpaces, final String filePath) {
@@ -362,34 +366,11 @@
public void run() {
final Document document = EditorFactory.getInstance().createDocument(fileText);
- int caretIndex = fileText.indexOf(CARET_MARKER);
- int selStartIndex = fileText.indexOf(SELECTION_START_MARKER);
- int selEndIndex = fileText.indexOf(SELECTION_END_MARKER);
-
- final RangeMarker caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex) : null;
- final RangeMarker selStartMarker = selStartIndex >= 0
- ? document.createRangeMarker(selStartIndex, selStartIndex)
- : null;
- final RangeMarker selEndMarker = selEndIndex >= 0
- ? document.createRangeMarker(selEndIndex, selEndIndex)
- : null;
-
if (ignoreTrailingSpaces) {
((DocumentImpl)document).stripTrailingSpaces(getProject());
}
- if (caretMarker != null) {
- document.deleteString(caretMarker.getStartOffset(), caretMarker.getStartOffset() + CARET_MARKER.length());
- }
- if (selStartMarker != null) {
- document.deleteString(selStartMarker.getStartOffset(),
- selStartMarker.getStartOffset() + SELECTION_START_MARKER.length());
- }
- if (selEndMarker != null) {
- document.deleteString(selEndMarker.getStartOffset(),
- selEndMarker.getStartOffset() + SELECTION_END_MARKER.length());
- }
-
+ EditorTestUtil.CaretsState carets = EditorTestUtil.extractCaretAndSelectionMarkers(document);
PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
String newFileText = document.getText();
@@ -402,8 +383,7 @@
}
assertEquals(failMessage, newFileText, fileText);
- checkCaretPosition(caretMarker, newFileText, message);
- checkSelection(selStartMarker, selEndMarker, newFileText, message);
+ checkCaretAndSelectionPositions(carets, newFileText, message);
}
});
}
@@ -413,53 +393,60 @@
return userMessage + " [" + engineMessage + "]";
}
- private static void checkSelection(final RangeMarker selStartMarker, final RangeMarker selEndMarker, String newFileText, String message) {
- if (selStartMarker != null && selEndMarker != null) {
- int selStartLine = StringUtil.offsetToLineNumber(newFileText, selStartMarker.getStartOffset());
- int selStartCol = selStartMarker.getStartOffset() - StringUtil.lineColToOffset(newFileText, selStartLine, 0);
-
- int selEndLine = StringUtil.offsetToLineNumber(newFileText, selEndMarker.getEndOffset());
- int selEndCol = selEndMarker.getEndOffset() - StringUtil.lineColToOffset(newFileText, selEndLine, 0);
-
- assertEquals(
- getMessage("selectionStartLine", message),
- selStartLine + 1,
- StringUtil.offsetToLineNumber(newFileText, myEditor.getSelectionModel().getSelectionStart()) + 1);
-
- assertEquals(
- getMessage("selectionStartCol", message),
- selStartCol + 1,
- myEditor.getSelectionModel().getSelectionStart() -
- StringUtil.lineColToOffset(newFileText, selStartLine, 0) +
- 1);
-
- assertEquals(
- getMessage("selectionEndLine", message),
- selEndLine + 1,
- StringUtil.offsetToLineNumber(newFileText, myEditor.getSelectionModel().getSelectionEnd()) + 1);
-
- assertEquals(
- getMessage("selectionEndCol", message),
- selEndCol + 1,
- myEditor.getSelectionModel().getSelectionEnd() - StringUtil.lineColToOffset(newFileText, selEndLine, 0) +
- 1);
- }
- else {
- assertTrue(getMessage("must not have selection", message), !myEditor.getSelectionModel().hasSelection());
- }
+ private static String getCaretDescription(int caretNumber, int totalCarets) {
+ return totalCarets == 1 ? "" : "(caret " + (caretNumber + 1) + "/" + totalCarets + ")";
}
- private static void checkCaretPosition(final RangeMarker caretMarker, String newFileText, String message) {
- if (caretMarker != null) {
- int caretLine = StringUtil.offsetToLineNumber(newFileText, caretMarker.getStartOffset());
- //int caretCol = caretMarker.getStartOffset() - StringUtil.lineColToOffset(newFileText, caretLine, 0);
- int caretCol = EditorUtil.calcColumnNumber(null, newFileText,
- StringUtil.lineColToOffset(newFileText, caretLine, 0),
- caretMarker.getStartOffset(),
- CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE);
+ @SuppressWarnings("ConstantConditions")
+ private static void checkCaretAndSelectionPositions(EditorTestUtil.CaretsState caretState, String newFileText, String message) {
+ CaretModel caretModel = myEditor.getCaretModel();
+ List<Caret> allCarets = new ArrayList<Caret>(caretModel.getAllCarets());
+ assertEquals("Unexpected number of carets", caretState.carets.size(), allCarets.size());
+ for (int i = 0; i < caretState.carets.size(); i++) {
+ String caretDescription = getCaretDescription(i, caretState.carets.size());
+ Caret currentCaret = allCarets.get(i);
+ LogicalPosition actualCaretPosition = currentCaret.getLogicalPosition();
+ EditorTestUtil.Caret expected = caretState.carets.get(i);
+ if (expected.offset != null) {
+ int caretLine = StringUtil.offsetToLineNumber(newFileText, expected.offset);
+ int caretCol = EditorUtil.calcColumnNumber(null, newFileText,
+ StringUtil.lineColToOffset(newFileText, caretLine, 0),
+ expected.offset,
+ CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE);
- assertEquals(getMessage("caretLine", message), caretLine, myEditor.getCaretModel().getLogicalPosition().line);
- assertEquals(getMessage("caretColumn", message), caretCol, myEditor.getCaretModel().getLogicalPosition().column);
+ assertEquals(getMessage("caretLine" + caretDescription, message), caretLine + 1, actualCaretPosition.line + 1);
+ assertEquals(getMessage("caretColumn" + caretDescription, message), caretCol + 1, actualCaretPosition.column + 1);
+ }
+ if (expected.selection != null) {
+ int selStartLine = StringUtil.offsetToLineNumber(newFileText, expected.selection.getStartOffset());
+ int selStartCol = expected.selection.getStartOffset() - StringUtil.lineColToOffset(newFileText, selStartLine, 0);
+
+ int selEndLine = StringUtil.offsetToLineNumber(newFileText, expected.selection.getEndOffset());
+ int selEndCol = expected.selection.getEndOffset() - StringUtil.lineColToOffset(newFileText, selEndLine, 0);
+
+ assertEquals(
+ getMessage("selectionStartLine" + caretDescription, message),
+ selStartLine + 1,
+ StringUtil.offsetToLineNumber(newFileText, currentCaret.getSelectionStart()) + 1);
+
+ assertEquals(
+ getMessage("selectionStartCol" + caretDescription, message),
+ selStartCol + 1,
+ currentCaret.getSelectionStart() - StringUtil.lineColToOffset(newFileText, selStartLine, 0) + 1);
+
+ assertEquals(
+ getMessage("selectionEndLine" + caretDescription, message),
+ selEndLine + 1,
+ StringUtil.offsetToLineNumber(newFileText, currentCaret.getSelectionEnd()) + 1);
+
+ assertEquals(
+ getMessage("selectionEndCol" + caretDescription, message),
+ selEndCol + 1,
+ currentCaret.getSelectionEnd() - StringUtil.lineColToOffset(newFileText, selEndLine, 0) + 1);
+ }
+ else {
+ assertFalse(getMessage("must not have selection" + caretDescription, message), currentCaret.hasSelection());
+ }
}
}
@@ -596,7 +583,11 @@
protected static void unindent() {
executeAction("EditorUnindentSelection");
}
-
+
+ protected static void selectLine() {
+ executeAction("EditorSelectLine");
+ }
+
protected static void lineComment() {
new CommentByLineCommentHandler().invoke(getProject(), getEditor(), getFile());
}
@@ -607,7 +598,7 @@
public void run() {
EditorActionManager actionManager = EditorActionManager.getInstance();
EditorActionHandler actionHandler = actionManager.getActionHandler(actionId);
- actionHandler.execute(getEditor(), DataManager.getInstance().getDataContext());
+ actionHandler.executeInCaretContext(getEditor(), null, DataManager.getInstance().getDataContext());
}
}, "", null);
}
@@ -638,4 +629,122 @@
}
};
}
+
+ /**
+ * file parameterized tests support
+ * @see FileBasedTestCaseHelperEx
+ */
+
+ /**
+ * @Parameterized.Parameter fields are injected on parameterized test creation.
+ */
+ @Parameterized.Parameter(0)
+ public String myFileSuffix;
+
+ /**
+ * path to the root of test data in case of com.intellij.testFramework.FileBasedTestCaseHelperEx
+ * or
+ * path to the directory with current test data in case of @TestDataPath
+ */
+ @Parameterized.Parameter(1)
+ public String myTestDataPath;
+
+ @Parameterized.Parameters(name = "{0}")
+ public static List<Object[]> params() throws Throwable {
+ return Collections.emptyList();
+ }
+
+ @com.intellij.testFramework.Parameterized.Parameters(name = "{0}")
+ public static List<Object[]> params(Class<?> klass) throws Throwable{
+ final LightPlatformCodeInsightTestCase testCase = (LightPlatformCodeInsightTestCase)klass.newInstance();
+ if (!(testCase instanceof FileBasedTestCaseHelper)) {
+ fail("Parameterized test should implement FileBasedTestCaseHelper");
+ }
+
+ PathManagerEx.replaceLookupStrategy(klass, com.intellij.testFramework.Parameterized.class);
+
+ final FileBasedTestCaseHelper fileBasedTestCase = (FileBasedTestCaseHelper)testCase;
+ String testDataPath = testCase.getTestDataPath();
+
+ File testDir = null;
+ if (fileBasedTestCase instanceof FileBasedTestCaseHelperEx) {
+ testDir = new File(testDataPath, ((FileBasedTestCaseHelperEx)fileBasedTestCase).getRelativeBasePath());
+ } else {
+ final TestDataPath annotation = klass.getAnnotation(TestDataPath.class);
+ if (annotation == null) {
+ fail("TestCase should implement com.intellij.testFramework.FileBasedTestCaseHelperEx or be annotated with com.intellij.testFramework.TestDataPath");
+ } else {
+ final String trimmedRoot = StringUtil.trimStart(StringUtil.trimStart(annotation.value(), "$CONTENT_ROOT"), "$PROJECT_ROOT");
+ final String lastPathComponent = new File(testDataPath).getName();
+ final int idx = trimmedRoot.indexOf(lastPathComponent);
+ testDataPath = testDataPath.replace(File.separatorChar, '/') + (idx > 0 ? trimmedRoot.substring(idx + lastPathComponent.length()) : trimmedRoot);
+ testDir = new File(testDataPath);
+ }
+ }
+
+ final File[] files = testDir.listFiles();
+
+ if (files == null) {
+ fail("Test files not found in " + testDir.getPath());
+ }
+
+ final List<Object[]> result = new ArrayList<Object[]>();
+ for (File file : files) {
+ final String fileSuffix = fileBasedTestCase.getFileSuffix(file.getName());
+ if (fileSuffix != null) {
+ result.add(new Object[] {fileSuffix, testDataPath});
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public String getName() {
+ if (myFileSuffix != null) {
+ return "test" + myFileSuffix;
+ }
+ return super.getName();
+ }
+
+ @Before
+ public void before() throws Throwable {
+ final Throwable[] throwables = new Throwable[1];
+
+ invokeTestRunnable(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ setUp();
+ }
+ catch (Throwable e) {
+ throwables[0] = e;
+ }
+ }
+ });
+
+ if (throwables[0] != null) {
+ throw throwables[0];
+ }
+ }
+
+ @After
+ public void after() throws Throwable {
+ final Throwable[] throwables = new Throwable[1];
+
+ invokeTestRunnable(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ tearDown();
+ }
+ catch (Throwable e) {
+ throwables[0] = e;
+ }
+ }
+ });
+ if (throwables[0] != null) {
+ throw throwables[0];
+ }
+ }
+
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/Parameterized.java b/platform/testFramework/src/com/intellij/testFramework/Parameterized.java
new file mode 100644
index 0000000..0d08d58
--- /dev/null
+++ b/platform/testFramework/src/com/intellij/testFramework/Parameterized.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.testFramework;
+
+import org.junit.runners.model.FrameworkMethod;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.reflect.Method;
+import java.util.List;
+
+public class Parameterized extends org.junit.runners.Parameterized {
+
+ @Retention(RetentionPolicy.RUNTIME)
+ @Target(ElementType.METHOD)
+ public @interface Parameters {
+ String name() default "{index}";
+ }
+
+ public Parameterized(Class<?> klass) throws Throwable {
+ super(klass);
+ FrameworkMethod parametersMethod = getParametersMethod();
+ if (parametersMethod != null) {
+ Parameters parameters = parametersMethod.getAnnotation(Parameters.class);
+ Method declaredMethod =
+ org.junit.runners.Parameterized.class.getDeclaredMethod("createRunnersForParameters", Iterable.class, String.class);
+ declaredMethod.setAccessible(true);
+ declaredMethod.invoke(this, allParameters(klass, parametersMethod), parameters.name());
+ }
+ }
+
+ private FrameworkMethod getParametersMethod() throws Exception {
+ List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(Parameters.class);
+ for (FrameworkMethod each : methods) {
+ if (each.isStatic() && each.isPublic()) {
+ return each;
+ }
+ }
+
+ return null;
+ }
+
+ private static Iterable<Object[]> allParameters(Class<?> klass, FrameworkMethod parametersMethod) throws Throwable {
+ Object parameters = parametersMethod.invokeExplosively(null, klass);
+ if (parameters instanceof Iterable) {
+ return (Iterable<Object[]>) parameters;
+ } else {
+ throw new IllegalArgumentException("Wrong return type");
+ }
+ }
+
+
+}
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
index 1c34017..e1e6907 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestCase.java
@@ -141,7 +141,7 @@
}
}
- private static String[] PREFIX_CANDIDATES = new String[] { "Python", "PyCharmCore", "UltimateLangXml", "Idea" };
+ private static String[] PREFIX_CANDIDATES = new String[] { "AppCode", "CppIde", "Python", "PyCharmCore", "UltimateLangXml", "Idea" };
public static void autodetectPlatformPrefix() {
if (ourPlatformPrefixInitialized) {
@@ -829,6 +829,7 @@
private static void setPlatformPrefix(String prefix) {
System.setProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
+ ourPlatformPrefixInitialized = true;
}
@Retention(RetentionPolicy.RUNTIME)
diff --git a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
index 37f360c..26c9c89 100644
--- a/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
+++ b/platform/testFramework/src/com/intellij/testFramework/PlatformTestUtil.java
@@ -462,6 +462,7 @@
public void assertTiming() {
assert expectedMs != 0 : "Must call .expect() before run test";
if (COVERAGE_ENABLED_BUILD) return;
+ Timings.getStatistics(); // warmup, measure
while (true) {
attempts--;
diff --git a/platform/testFramework/src/com/intellij/testFramework/TestDataPath.java b/platform/testFramework/src/com/intellij/testFramework/TestDataPath.java
index c8d6945..01362db 100644
--- a/platform/testFramework/src/com/intellij/testFramework/TestDataPath.java
+++ b/platform/testFramework/src/com/intellij/testFramework/TestDataPath.java
@@ -27,7 +27,7 @@
*
* @author yole
*/
-@Retention(RetentionPolicy.SOURCE)
+@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface TestDataPath {
String value();
diff --git a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
index 5c262a0..d7e6e5a 100644
--- a/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/UsefulTestCase.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 @@
import com.intellij.diagnostic.PerformanceWatcher;
import com.intellij.mock.MockApplication;
import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.command.CommandProcessor;
@@ -72,6 +73,7 @@
/**
* @author peter
*/
+@SuppressWarnings("UseOfSystemOutOrSystemErr")
public abstract class UsefulTestCase extends TestCase {
public static final String IDEA_MARKER_CLASS = "com.intellij.openapi.components.impl.stores.IdeaProjectStoreImpl";
public static final String TEMP_DIR_MARKER = "unitTest_";
@@ -123,8 +125,6 @@
protected void setUp() throws Exception {
super.setUp();
- PathManager.ensureConfigFolderExists();
-
if (shouldContainTempFiles()) {
String testName = getTestName(true);
if (StringUtil.isEmptyOrSpaces(testName)) testName = "";
@@ -175,8 +175,7 @@
aClass = Class.forName("java.io.DeleteOnExitHook");
files = ReflectionUtil.getField(aClass, null, Set.class, "files");
}
- catch (Exception e) {
- }
+ catch (Exception ignored) { }
DELETE_ON_EXIT_HOOK_CLASS = aClass;
DELETE_ON_EXIT_HOOK_DOT_FILES = files;
}
@@ -216,19 +215,14 @@
Object map = mapF.get(manager);
((Map)map).clear();
}
-
- //Constructor<?> ctr = aClass.getDeclaredConstructor();
- //ctr.setAccessible(true);
- //Object newManager = ctr.newInstance();
- //Method setter = aClass.getDeclaredMethod("setCurrentManager", aClass);
- //setter.setAccessible(true);
- //setter.invoke(null, newManager);
}
protected void checkForSettingsDamage() throws Exception {
- if (isPerformanceTest() || ApplicationManager.getApplication() == null || ApplicationManager.getApplication() instanceof MockApplication) {
+ Application app = ApplicationManager.getApplication();
+ if (isPerformanceTest() || app == null || app instanceof MockApplication) {
return;
}
+
CodeStyleSettings oldCodeStyleSettings = myOldCodeStyleSettings;
myOldCodeStyleSettings = null;
@@ -343,6 +337,7 @@
super.runBare();
}
+ @Override
public void runBare() throws Throwable {
if (!shouldRunTest()) return;
@@ -427,7 +422,7 @@
String expectedString = toString(expected);
String actualString = toString(actual);
Assert.assertEquals(erroMsg, expectedString, actualString);
- Assert.fail("Warning! 'toString' do not reflect the difference.\nExpected: " + expectedString + "\nActual: " + actualString);
+ Assert.fail("Warning! 'toString' does not reflect the difference.\nExpected: " + expectedString + "\nActual: " + actualString);
}
}
@@ -575,7 +570,8 @@
public static <T> T assertInstanceOf(Object o, Class<T> aClass) {
Assert.assertNotNull("Expected instance of: " + aClass.getName() + " actual: " + null, o);
Assert.assertTrue("Expected instance of: " + aClass.getName() + " actual: " + o.getClass().getName(), aClass.isInstance(o));
- return (T)o;
+ @SuppressWarnings("unchecked") T t = (T)o;
+ return t;
}
public static <T> T assertOneElement(Collection<T> collection) {
@@ -593,11 +589,11 @@
public static <T> void assertOneOf(T value, T... values) {
boolean found = false;
for (T v : values) {
- if (value == v || (value != null && value.equals(v))) {
+ if (value == v || value != null && value.equals(v)) {
found = true;
}
}
- Assert.assertTrue("" + value + " should be equal to one of " + Arrays.toString(values), found);
+ Assert.assertTrue(value + " should be equal to one of " + Arrays.toString(values), found);
}
public static void printThreadDump() {
@@ -608,6 +604,11 @@
assertOrderedEquals(array);
}
+ public static void assertNotEmpty(final Collection<?> collection) {
+ if (collection == null) return;
+ assertTrue(!collection.isEmpty());
+ }
+
public static void assertEmpty(final Collection<?> collection) {
assertEmpty(collection.toString(), collection);
}
@@ -620,9 +621,8 @@
assertTrue(s, StringUtil.isEmpty(s));
}
- public static void assertEmpty(final String errorMsg, final Collection<?> collection) {
- Iterable<Object> i = (Iterable<Object>)collection;
- assertOrderedEquals(errorMsg, i);
+ public static <T> void assertEmpty(final String errorMsg, final Collection<T> collection) {
+ assertOrderedEquals(errorMsg, collection);
}
public static void assertSize(int expectedSize, final Object[] array) {
@@ -730,13 +730,10 @@
}
}
+ @SuppressWarnings("deprecation")
protected static void checkSettingsEqual(JDOMExternalizable expected, JDOMExternalizable settings, String message) throws Exception {
- if (expected == null) {
- return;
- }
- if (settings == null) {
- return;
- }
+ if (expected == null || settings == null) return;
+
Element oldS = new Element("temp");
expected.writeExternal(oldS);
Element newS = new Element("temp");
@@ -871,7 +868,7 @@
}
protected boolean annotatedWith(@NotNull Class annotationClass) {
- Class aClass = getClass();
+ Class<?> aClass = getClass();
String methodName = "test" + getTestName(false);
boolean methodChecked = false;
while (aClass != null && aClass != Object.class) {
@@ -882,8 +879,7 @@
if (method.getAnnotation(annotationClass) != null) return true;
methodChecked = true;
}
- catch (NoSuchMethodException e) {
- }
+ catch (NoSuchMethodException ignored) { }
}
aClass = aClass.getSuperclass();
}
@@ -909,7 +905,8 @@
file.refresh(false, true);
}
- public static @NotNull Test filteredSuite(@RegExp String regexp, @NotNull Test test) {
+ @NotNull
+ public static Test filteredSuite(@RegExp String regexp, @NotNull Test test) {
final Pattern pattern = Pattern.compile(regexp);
final TestSuite testSuite = new TestSuite();
new Processor<Test>() {
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
index da04e8f..92e56f8 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/CodeInsightTestFixture.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.
@@ -62,10 +62,6 @@
public interface CodeInsightTestFixture extends IdeaProjectTestFixture {
@NonNls String CARET_MARKER = "<caret>";
- @NonNls String SELECTION_START_MARKER = "<selection>";
- @NonNls String SELECTION_END_MARKER = "</selection>";
- @NonNls String BLOCK_START_MARKER = "<block>";
- @NonNls String BLOCK_END_MARKER = "</block>";
@NonNls String ERROR_MARKER = "error";
@NonNls String WARNING_MARKER = "warning";
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/EditorMouseFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/EditorMouseFixture.java
new file mode 100644
index 0000000..12fbf70
--- /dev/null
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/EditorMouseFixture.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.testFramework.fixtures;
+
+import com.intellij.openapi.editor.ex.util.EditorUtil;
+import com.intellij.openapi.editor.impl.EditorImpl;
+
+import javax.swing.JComponent;
+import java.awt.Font;
+import java.awt.event.InputEvent;
+import java.awt.event.MouseEvent;
+
+@SuppressWarnings("MagicConstant")
+public class EditorMouseFixture {
+ private final EditorImpl myEditor;
+ private int myX;
+ private int myY;
+ private int myModifiers;
+ private int myButton = MouseEvent.NOBUTTON;
+ private int myLastId;
+
+ public EditorMouseFixture(EditorImpl editor) {
+ myEditor = editor;
+ }
+
+ public EditorMouseFixture pressAt(int visualLine, int visualColumn) {
+ JComponent component = myEditor.getContentComponent();
+ component.dispatchEvent(new MouseEvent(component,
+ myLastId = MouseEvent.MOUSE_PRESSED,
+ System.currentTimeMillis(),
+ getModifiers(),
+ myX = getX(visualColumn),
+ myY = getY(visualLine),
+ 1,
+ false,
+ myButton));
+ return this;
+ }
+
+ public EditorMouseFixture release() {
+ int oldLastId = myLastId;
+ JComponent component = myEditor.getContentComponent();
+ component.dispatchEvent(new MouseEvent(component,
+ myLastId = MouseEvent.MOUSE_RELEASED,
+ System.currentTimeMillis(),
+ getModifiers(),
+ myX,
+ myY,
+ 1,
+ false,
+ myButton));
+ if (oldLastId == MouseEvent.MOUSE_PRESSED) {
+ component.dispatchEvent(new MouseEvent(component,
+ myLastId = MouseEvent.MOUSE_CLICKED,
+ System.currentTimeMillis(),
+ getModifiers(),
+ myX,
+ myY,
+ 1,
+ false,
+ myButton));
+ }
+ return this;
+ }
+
+ public EditorMouseFixture clickAt(int visualLine, int visualColumn) {
+ return pressAt(visualLine, visualColumn).release();
+ }
+
+ public EditorMouseFixture dragTo(int visualLine, int visualColumn) {
+ JComponent component = myEditor.getContentComponent();
+ component.dispatchEvent(new MouseEvent(component,
+ myLastId = MouseEvent.MOUSE_DRAGGED,
+ System.currentTimeMillis(),
+ getModifiers(),
+ myX = getX(visualColumn),
+ myY = getY(visualLine),
+ 1,
+ false,
+ myButton));
+ return this;
+ }
+
+ public EditorMouseFixture alt() {
+ myModifiers |= InputEvent.ALT_MASK;
+ return this;
+ }
+
+ public EditorMouseFixture shift() {
+ myModifiers |= InputEvent.SHIFT_MASK;
+ return this;
+ }
+
+ public EditorMouseFixture middle() {
+ myButton = MouseEvent.BUTTON2;
+ return this;
+ }
+
+ private int getX(int visualColumn) {
+ return visualColumn * EditorUtil.getSpaceWidth(Font.PLAIN, myEditor);
+ }
+
+ private int getY(int visualLine) {
+ return visualLine * myEditor.getLineHeight();
+ }
+
+ private int getModifiers() {
+ if (myButton == MouseEvent.BUTTON2) {
+ return myModifiers | InputEvent.ALT_MASK;
+ }
+ else {
+ return myModifiers;
+ }
+ }
+}
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/EditorScrollingFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/EditorScrollingFixture.java
new file mode 100644
index 0000000..4b960f6
--- /dev/null
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/EditorScrollingFixture.java
@@ -0,0 +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.testFramework.fixtures;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.editor.ex.util.EditorUtil;
+
+import java.awt.*;
+
+public class EditorScrollingFixture {
+ public static void setVisibleSize(Editor editor, int widthInChars, int heightInChars) {
+ Dimension size = new Dimension(widthInChars * EditorUtil.getSpaceWidth(Font.PLAIN, editor), heightInChars * editor.getLineHeight());
+ ((EditorEx)editor).getScrollPane().getViewport().setExtentSize(size);
+ }
+}
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
index d25e689..490d2c3 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/HeavyIdeaTestFixture.java
@@ -21,6 +21,7 @@
import java.io.IOException;
/**
+ * Creates new application for each test.
* @author peter
*/
public interface HeavyIdeaTestFixture extends IdeaProjectTestFixture {
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
index 23ae57f..82a3ad6 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/CodeInsightTestFixtureImpl.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.
@@ -123,6 +123,10 @@
import java.io.IOException;
import java.util.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
/**
* @author Dmitry Avdeev
*/
@@ -667,13 +671,17 @@
@NotNull
public PsiElement getElementAtCaret() {
assertInitialized();
- final PsiElement element = TargetElementUtilBase.findTargetElement(getCompletionEditor(),
- TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED |
- TargetElementUtilBase.ELEMENT_NAME_ACCEPTED);
- assert element != null : "element not found in file " +
- myFile.getName() +
- " at caret position, offset " +
- myEditor.getCaretModel().getOffset() + "\"" +
+ Editor editor = getCompletionEditor();
+ int findTargetFlags = TargetElementUtilBase.REFERENCED_ELEMENT_ACCEPTED | TargetElementUtilBase.ELEMENT_NAME_ACCEPTED;
+ PsiElement element = TargetElementUtilBase.findTargetElement(editor, findTargetFlags);
+
+ // if no references found in injected fragment, try outer document
+ if (element == null && editor instanceof EditorWindow) {
+ element = TargetElementUtilBase.findTargetElement(((EditorWindow)editor).getDelegate(), findTargetFlags);
+ }
+
+ assert element != null : "element not found in file " + myFile.getName() +
+ " at caret position, offset " + myEditor.getCaretModel().getOffset() + "\"" +
" psi structure: " + DebugUtil.psiToString(myFile, true, true);
return element;
}
@@ -778,22 +786,27 @@
private boolean _performEditorAction(String actionId) {
final DataContext dataContext = getEditorDataContext();
- ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
- AnAction action = managerEx.getAction(actionId);
- AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, new Presentation(), managerEx, 0);
+ final ActionManagerEx managerEx = ActionManagerEx.getInstanceEx();
+ final AnAction action = managerEx.getAction(actionId);
+ final AnActionEvent event = new AnActionEvent(null, dataContext, ActionPlaces.UNKNOWN, new Presentation(), managerEx, 0);
- action.update(event);
+ return WriteCommandAction.runWriteCommandAction(getProject(), new Computable<Boolean>() {
+ @Override
+ public Boolean compute() {
+ action.update(event);
- if (!event.getPresentation().isEnabled()) {
- return false;
- }
+ if (!event.getPresentation().isEnabled()) {
+ return false;
+ }
- managerEx.fireBeforeActionPerformed(action, dataContext, event);
+ managerEx.fireBeforeActionPerformed(action, dataContext, event);
- action.actionPerformed(event);
+ action.actionPerformed(event);
- managerEx.fireAfterActionPerformed(action, dataContext, event);
- return true;
+ managerEx.fireAfterActionPerformed(action, dataContext, event);
+ return true;
+ }
+ });
}
@Override
@@ -1346,21 +1359,32 @@
assert myEditor != null : "Editor couldn't be created for file: " +
copy.getPath() +
", use copyFileToProject(..) method for this file instead of configureByFile(..)";
- int offset = loader.caretMarker != null ? loader.caretMarker.getStartOffset() : 0;
- myEditor.getCaretModel().moveToOffset(offset);
- if (loader.selStartMarker != null && loader.selEndMarker != null) {
- int start = loader.selStartMarker.getStartOffset();
- int end = loader.selEndMarker.getStartOffset();
- if (loader.blockSelection) {
- myEditor.getSelectionModel().setBlockSelection(myEditor.offsetToLogicalPosition(start), myEditor.offsetToLogicalPosition(end));
+ if (myEditor.getCaretModel().supportsMultipleCarets()) {
+ List<LogicalPosition> caretPositions = new ArrayList<LogicalPosition>();
+ List<Segment> selections = new ArrayList<Segment>();
+ for (EditorTestUtil.Caret caret : loader.caretState.carets) {
+ caretPositions.add(caret.offset == null ? null : myEditor.offsetToLogicalPosition(caret.offset));
+ selections.add(caret.selection == null ? null : caret.selection);
}
- else {
- myEditor.getSelectionModel().setSelection(start, end);
- }
+ myEditor.getCaretModel().setCarets(caretPositions, selections);
}
else {
- myEditor.getSelectionModel().removeSelection();
+ assert loader.caretState.carets.size() == 1 : "Multiple carets are not supported by the model";
+ EditorTestUtil.Caret caret = loader.caretState.carets.get(0);
+ int offset = caret.offset != null ? caret.offset : 0;
+ myEditor.getCaretModel().moveToOffset(offset);
+
+ if (caret.selection != null) {
+ myEditor.getSelectionModel().setSelection(caret.selection.getStartOffset(), caret.selection.getEndOffset());
+ }
+ else {
+ myEditor.getSelectionModel().removeSelection();
+ }
+ }
+ if (loader.caretState.blockSelection != null) {
+ myEditor.getSelectionModel().setBlockSelection(myEditor.offsetToLogicalPosition(loader.caretState.blockSelection.getStartOffset()),
+ myEditor.offsetToLogicalPosition(loader.caretState.blockSelection.getEndOffset()));
}
Module module = getModule();
@@ -1437,17 +1461,17 @@
List<HighlightInfo> infos;
final long start = System.currentTimeMillis();
- try {
- ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(myJavaFilesFilter);
+ ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(myJavaFilesFilter, myTestRootDisposable);
-// ProfilingUtil.startCPUProfiling();
+ // ProfilingUtil.startCPUProfiling();
+ try {
infos = doHighlighting();
removeDuplicatedRangesForInjected(infos);
-// ProfilingUtil.captureCPUSnapshot("testing");
}
finally {
- ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
+ ((PsiManagerImpl)PsiManager.getInstance(project)).setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
}
+ // ProfilingUtil.captureCPUSnapshot("testing");
final long elapsed = System.currentTimeMillis() - start;
data.checkResult(infos, file.getText());
@@ -1623,10 +1647,7 @@
static class SelectionAndCaretMarkupLoader {
final String filePath;
final String newFileText;
- final RangeMarker caretMarker;
- final RangeMarker selStartMarker;
- final RangeMarker selEndMarker;
- final boolean blockSelection;
+ final EditorTestUtil.CaretsState caretState;
static SelectionAndCaretMarkupLoader fromFile(String path, Project project, String charset) throws IOException {
return new SelectionAndCaretMarkupLoader(
@@ -1652,38 +1673,12 @@
this.filePath = filePath;
final Document document = EditorFactory.getInstance().createDocument(fileText);
- int caretIndex = fileText.indexOf(CARET_MARKER);
- int selStartIndex = fileText.indexOf(SELECTION_START_MARKER);
- int selEndIndex = fileText.indexOf(SELECTION_END_MARKER);
- int blockStartIndex = fileText.indexOf(BLOCK_START_MARKER);
- int blockEndIndex = fileText.indexOf(BLOCK_END_MARKER);
-
- caretMarker = caretIndex >= 0 ? document.createRangeMarker(caretIndex, caretIndex + CARET_MARKER.length()) : null;
- if (selStartIndex >= 0 || selEndIndex >= 0) {
- blockSelection = false;
- selStartMarker = selStartIndex >= 0? document.createRangeMarker(selStartIndex, selStartIndex + SELECTION_START_MARKER.length()) : null;
- selEndMarker = selEndIndex >= 0? document.createRangeMarker(selEndIndex, selEndIndex + SELECTION_END_MARKER.length()) : null;
- }
- else {
- selStartMarker = blockStartIndex >= 0 ? document.createRangeMarker(blockStartIndex, blockStartIndex + BLOCK_START_MARKER.length()) : null;
- selEndMarker = blockEndIndex >= 0 ? document.createRangeMarker(blockEndIndex, blockEndIndex + BLOCK_END_MARKER.length()) : null;
- blockSelection = selStartMarker != null || selEndMarker != null;
- }
-
- new WriteCommandAction(project) {
+ caretState = new WriteCommandAction<EditorTestUtil.CaretsState>(project) {
@Override
- protected void run(Result result) throws Exception {
- if (caretMarker != null) {
- document.deleteString(caretMarker.getStartOffset(), caretMarker.getEndOffset());
- }
- if (selStartMarker != null) {
- document.deleteString(selStartMarker.getStartOffset(), selStartMarker.getEndOffset());
- }
- if (selEndMarker != null) {
- document.deleteString(selEndMarker.getStartOffset(), selEndMarker.getEndOffset());
- }
+ protected void run(@NotNull Result<EditorTestUtil.CaretsState> result) throws Exception {
+ result.setResult(EditorTestUtil.extractCaretAndSelectionMarkers(document));
}
- }.execute();
+ }.execute().getResultObject();
newFileText = document.getText();
}
@@ -1711,6 +1706,7 @@
}
+ @SuppressWarnings("ConstantConditions")
private void checkResult(final String expectedFile,
final boolean stripTrailingSpaces,
final SelectionAndCaretMarkupLoader loader,
@@ -1747,57 +1743,74 @@
}
}
- if (loader.caretMarker != null) {
- final int tabSize = CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE;
-
- int caretLine = StringUtil.offsetToLineNumber(loader.newFileText, loader.caretMarker.getStartOffset());
- int caretCol = EditorUtil.calcColumnNumber(null, loader.newFileText, StringUtil.lineColToOffset(loader.newFileText, caretLine, 0),
- loader.caretMarker.getStartOffset(), tabSize);
-
- final int actualLine = editor.getCaretModel().getLogicalPosition().line;
- final int actualCol = editor.getCaretModel().getLogicalPosition().column;
- boolean caretPositionEquals = caretLine == actualLine && caretCol == actualCol;
- Assert.assertTrue("Caret position in " + expectedFile + " differs. Expected " + genCaretPositionPresentation(caretLine, caretCol) +
- ". Actual " + genCaretPositionPresentation(actualLine, actualCol), caretPositionEquals);
- }
-
- if (loader.selStartMarker != null && loader.selEndMarker != null) {
- int selStartLine = StringUtil.offsetToLineNumber(loader.newFileText, loader.selStartMarker.getStartOffset());
- int selStartCol = loader.selStartMarker.getStartOffset() - StringUtil.lineColToOffset(loader.newFileText, selStartLine, 0);
-
- int selEndLine = StringUtil.offsetToLineNumber(loader.newFileText, loader.selEndMarker.getEndOffset());
- int selEndCol = loader.selEndMarker.getEndOffset() - StringUtil.lineColToOffset(loader.newFileText, selEndLine, 0);
-
- int selectionStart;
- int selectionEnd;
- if (editor.getSelectionModel().hasBlockSelection()) {
- int[] starts = editor.getSelectionModel().getBlockSelectionStarts();
- int[] ends = editor.getSelectionModel().getBlockSelectionEnds();
- selectionStart = starts[starts.length-1];
- selectionEnd = ends[ends.length-1];
+ boolean hasChecks = false;
+ for (int i = 0; i < loader.caretState.carets.size(); i++) {
+ EditorTestUtil.Caret expected = loader.caretState.carets.get(i);
+ if (expected.offset != null || expected.selection != null) {
+ hasChecks = true;
+ break;
}
- else {
- selectionStart = editor.getSelectionModel().getSelectionStart();
- selectionEnd = editor.getSelectionModel().getSelectionEnd();
+ }
+ if (!hasChecks) {
+ return; // nothing to check, so we skip caret/selection assertions
+ }
+ CaretModel caretModel = editor.getCaretModel();
+ List<Caret> allCarets = new ArrayList<Caret>(caretModel.getAllCarets());
+ assertEquals("Unexpected number of carets", loader.caretState.carets.size(), allCarets.size());
+ for (int i = 0; i < loader.caretState.carets.size(); i++) {
+ EditorTestUtil.Caret expected = loader.caretState.carets.get(i);
+ String caretDescription = loader.caretState.carets.size() == 1 ? "" : "(" + (i + 1) + "/" + loader.caretState.carets.size() + ") ";
+ if (expected.offset != null) {
+ final int tabSize = CodeStyleSettingsManager.getSettings(getProject()).getIndentOptions(StdFileTypes.JAVA).TAB_SIZE;
+
+ int caretLine = StringUtil.offsetToLineNumber(loader.newFileText, expected.offset);
+ int caretCol = EditorUtil.calcColumnNumber(null, loader.newFileText, StringUtil.lineColToOffset(loader.newFileText, caretLine, 0), expected.offset, tabSize);
+
+ final int actualLine = allCarets.get(i).getLogicalPosition().line;
+ final int actualCol = allCarets.get(i).getLogicalPosition().column;
+ boolean caretPositionEquals = caretLine == actualLine && caretCol == actualCol;
+ assertTrue("Caret" + caretDescription + " position in " + expectedFile + " differs. Expected " + genCaretPositionPresentation(caretLine, caretCol)
+ + ". Actual " + genCaretPositionPresentation(actualLine, actualCol), caretPositionEquals);
}
- final int selStartLineActual = StringUtil.offsetToLineNumber(loader.newFileText, selectionStart);
- final int selStartColActual = selectionStart - StringUtil.lineColToOffset(loader.newFileText, selStartLineActual, 0);
+ if (expected.selection != null) {
+ int selStartLine = StringUtil.offsetToLineNumber(loader.newFileText, expected.selection.getStartOffset());
+ int selStartCol = expected.selection.getStartOffset() - StringUtil.lineColToOffset(loader.newFileText, selStartLine, 0);
- final int selEndLineActual = StringUtil.offsetToLineNumber(loader.newFileText, selectionEnd);
- final int selEndColActual = selectionEnd - StringUtil.lineColToOffset(loader.newFileText, selEndLineActual, 0);
+ int selEndLine = StringUtil.offsetToLineNumber(loader.newFileText, expected.selection.getEndOffset());
+ int selEndCol = expected.selection.getEndOffset() - StringUtil.lineColToOffset(loader.newFileText, selEndLine, 0);
- final boolean selectionEquals = selStartCol == selStartColActual &&
- selStartLine == selStartLineActual &&
- selEndCol == selEndColActual &&
- selEndLine == selEndLineActual;
- Assert.assertTrue("selection in " + expectedFile +
- " differs. Expected " + genSelectionPresentation(selStartLine, selStartCol, selEndLine, selEndCol) +
- ". Actual " + genSelectionPresentation(selStartLineActual, selStartColActual, selEndLineActual, selEndColActual),
- selectionEquals);
- }
- else if (editor != null) {
- Assert.assertTrue("has no selection in " + expectedFile, !editor.getSelectionModel().hasSelection());
+ int selectionStart;
+ int selectionEnd;
+ if (editor.getSelectionModel().hasBlockSelection()) {
+ int[] starts = editor.getSelectionModel().getBlockSelectionStarts();
+ int[] ends = editor.getSelectionModel().getBlockSelectionEnds();
+ selectionStart = starts[starts.length-1];
+ selectionEnd = ends[ends.length-1];
+ }
+ else {
+ selectionStart = allCarets.get(i).getSelectionStart();
+ selectionEnd = allCarets.get(i).getSelectionEnd();
+ }
+
+ final int selStartLineActual = StringUtil.offsetToLineNumber(loader.newFileText, selectionStart);
+ final int selStartColActual = selectionStart - StringUtil.lineColToOffset(loader.newFileText, selStartLineActual, 0);
+
+ final int selEndLineActual = StringUtil.offsetToLineNumber(loader.newFileText, selectionEnd);
+ final int selEndColActual = selectionEnd - StringUtil.lineColToOffset(loader.newFileText, selEndLineActual, 0);
+
+ final boolean selectionEquals = selStartCol == selStartColActual &&
+ selStartLine == selStartLineActual &&
+ selEndCol == selEndColActual &&
+ selEndLine == selEndLineActual;
+ assertTrue(caretDescription + "selection in " + expectedFile + " differs. Expected " + genSelectionPresentation(selStartLine, selStartCol, selEndLine, selEndCol) +
+ ". Actual " + genSelectionPresentation(selStartLineActual, selStartColActual, selEndLineActual, selEndColActual),
+ selectionEquals
+ );
+ }
+ else if (editor != null) {
+ assertFalse(caretDescription + "has no selection in " + expectedFile, editor.getSelectionModel().hasSelection());
+ }
}
}
@@ -1932,6 +1945,9 @@
if (!actual.equals(Arrays.asList(expected))) {
UsefulTestCase.assertOrderedEquals(DumpLookupElementWeights.getLookupElementWeights(lookup), expected);
}
+ if (selected != list.getSelectedIndex()) {
+ System.out.println(DumpLookupElementWeights.getLookupElementWeights(lookup));
+ }
Assert.assertEquals(selected, list.getSelectedIndex());
}
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
index eb04e4b..87a0745 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/HeavyIdeaTestFixtureImpl.java
@@ -23,7 +23,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
@@ -72,11 +71,11 @@
import java.util.Set;
/**
+ * Creates new project for each test.
* @author mike
*/
class HeavyIdeaTestFixtureImpl extends BaseFixture implements HeavyIdeaTestFixture {
- @NonNls private static final String PROJECT_FILE_PREFIX = "temp";
@NonNls private static final String PROJECT_FILE_SUFFIX = ProjectFileType.DOT_DEFAULT_EXTENSION;
private Project myProject;
diff --git a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/ModuleFixtureBuilderImpl.java b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/ModuleFixtureBuilderImpl.java
index 578d8c0..f6e6d40 100644
--- a/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/ModuleFixtureBuilderImpl.java
+++ b/platform/testFramework/src/com/intellij/testFramework/fixtures/impl/ModuleFixtureBuilderImpl.java
@@ -26,7 +26,7 @@
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.builders.ModuleFixtureBuilder;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
@@ -136,12 +136,16 @@
VirtualFile vf = LocalFileSystem.getInstance().refreshAndFindFileByPath(s);
if (vf == null) {
final VirtualFile file = LocalFileSystem.getInstance().refreshAndFindFileByPath(sourceRoot);
- if (file != null && VfsUtil.isAncestor(virtualFile, file, false)) vf = file;
+ if (file != null && VfsUtilCore.isAncestor(virtualFile, file, false)) vf = file;
}
- //assert vf != null : "cannot find source root: " + sourceRoot;
+// assert vf != null : "cannot find source root: " + sourceRoot;
if (vf != null) {
contentEntry.addSourceFolder(vf, false);
}
+ else {
+ // files are not created yet
+ contentEntry.addSourceFolder(VfsUtilCore.pathToUrl(s), false);
+ }
}
}
setupRootModel(rootModel);
diff --git a/platform/testFramework/testSrc/com/intellij/psi/formatter/FormatterTestCase.java b/platform/testFramework/testSrc/com/intellij/psi/formatter/FormatterTestCase.java
index 2f6b526..2afd091 100644
--- a/platform/testFramework/testSrc/com/intellij/psi/formatter/FormatterTestCase.java
+++ b/platform/testFramework/testSrc/com/intellij/psi/formatter/FormatterTestCase.java
@@ -1,33 +1,17 @@
/*
- * Copyright (c) 2004 JetBrains s.r.o. All Rights Reserved.
+ * Copyright 2000-2013 JetBrains s.r.o.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
+ * 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
*
- * -Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
+ * http://www.apache.org/licenses/LICENSE-2.0
*
- * -Redistribution in binary form must reproduct the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the distribution.
- *
- * Neither the name of JetBrains or IntelliJ IDEA
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * This software is provided "AS IS," without a warranty of any kind. ALL
- * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
- * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
- * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. JETBRAINS AND ITS LICENSORS SHALL NOT
- * BE LIABLE FOR ANY DAMAGES OR LIABILITIES SUFFERED BY LICENSEE AS A RESULT
- * OF OR RELATING TO USE, MODIFICATION OR DISTRIBUTION OF THE SOFTWARE OR ITS
- * DERIVATIVES. IN NO EVENT WILL JETBRAINS OR ITS LICENSORS BE LIABLE FOR ANY LOST
- * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
- * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
- * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE SOFTWARE, EVEN
- * IF JETBRAINS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
- *
+ * 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.formatter;
@@ -38,6 +22,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.command.impl.UndoManagerImpl;
import com.intellij.openapi.command.undo.UndoManager;
import com.intellij.openapi.editor.Document;
@@ -206,38 +191,34 @@
editor = null;
}
- CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
+ WriteCommandAction.runWriteCommandAction(getProject(), new Runnable() {
@Override
public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- document.replaceString(0, document.getTextLength(), text);
- PsiDocumentManager.getInstance(getProject()).commitDocument(document);
- assertEquals(file.getText(), document.getText());
+ document.replaceString(0, document.getTextLength(), text);
+ PsiDocumentManager.getInstance(getProject()).commitDocument(document);
+ assertEquals(file.getText(), document.getText());
- if (false && doCheckDocumentUpdate()) {
- makeFolding(file, editor);
- }
- try {
- if (doReformatRangeTest) {
- CodeStyleManager.getInstance(getProject()).reformatRange(file, file.getTextRange().getStartOffset(), file.getTextRange().getEndOffset());
- } else if (myTextRange != null) {
- CodeStyleManager.getInstance(getProject()).reformatText(file, myTextRange.getStartOffset(), myTextRange.getEndOffset());
- }
- else {
- CodeStyleManager.getInstance(getProject())
- .reformatText(file, file.getTextRange().getStartOffset(), file.getTextRange().getEndOffset());
- }
- }
- catch (IncorrectOperationException e) {
- fail();
- }
-
+ if (false && doCheckDocumentUpdate()) {
+ makeFolding(file, editor);
+ }
+ try {
+ if (doReformatRangeTest) {
+ CodeStyleManager.getInstance(getProject())
+ .reformatRange(file, file.getTextRange().getStartOffset(), file.getTextRange().getEndOffset());
}
- });
+ else if (myTextRange != null) {
+ CodeStyleManager.getInstance(getProject()).reformatText(file, myTextRange.getStartOffset(), myTextRange.getEndOffset());
+ }
+ else {
+ CodeStyleManager.getInstance(getProject())
+ .reformatText(file, file.getTextRange().getStartOffset(), file.getTextRange().getEndOffset());
+ }
+ }
+ catch (IncorrectOperationException e) {
+ fail();
+ }
}
- }, "", "");
+ });
assertEquals(textAfter, document.getText());
PsiDocumentManager.getInstance(getProject()).commitDocument(document);
diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
index a4869d9..b355723 100644
--- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
+++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/MockChangeListManager.java
@@ -1,3 +1,18 @@
+/*
+ * 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.testFramework.vcs;
import com.intellij.openapi.application.ModalityState;
@@ -204,8 +219,9 @@
return changes;
}
+ @NotNull
@Override
- public ThreeState haveChangesUnder(VirtualFile vf) {
+ public ThreeState haveChangesUnder(@NotNull VirtualFile vf) {
throw new UnsupportedOperationException();
}
diff --git a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/TestClientRunner.java b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/TestClientRunner.java
index 88985a8..087769f 100644
--- a/platform/testFramework/testSrc/com/intellij/testFramework/vcs/TestClientRunner.java
+++ b/platform/testFramework/testSrc/com/intellij/testFramework/vcs/TestClientRunner.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,11 +17,11 @@
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
+import com.intellij.openapi.diagnostic.LogUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.util.EnvironmentUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,7 +93,7 @@
}
final CapturingProcessHandler handler = new CapturingProcessHandler(clientProcess, CharsetToolkit.getDefaultSystemCharset());
- final ProcessOutput result = handler.runProcess(100*1000);
+ final ProcessOutput result = handler.runProcess(100*1000, false);
if (myTraceClient || result.isTimeout()) {
LOG.debug("*** result: " + result.getExitCode());
final String out = result.getStdout().trim();
@@ -107,8 +107,11 @@
}
if (result.isTimeout()) {
- throw new RuntimeException("Timeout waiting for VCS client to finish execution:\n" + EnvironmentUtil.getProcessList());
+ String processList = LogUtil.getProcessList();
+ handler.destroyProcess();
+ throw new RuntimeException("Timeout waiting for VCS client to finish execution:\n" + processList);
}
+
return result;
}
}
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java b/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java
index 822a5ab..2ecb0fc 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/TestTreeView.java
@@ -20,6 +20,7 @@
*/
package com.intellij.execution.testframework;
+import com.intellij.execution.Location;
import com.intellij.execution.testframework.actions.ViewAssertEqualsDiffAction;
import com.intellij.ide.CopyProvider;
import com.intellij.ide.actions.CopyReferenceAction;
@@ -104,6 +105,24 @@
return els.isEmpty() ? null : els.toArray(new PsiElement[els.size()]);
}
}
+
+ if (Location.DATA_KEYS.is(dataId)) {
+ TreePath[] paths = getSelectionPaths();
+ if (paths != null && paths.length > 1) {
+ final List<Location<?>> locations = new ArrayList<Location<?>>(paths.length);
+ for (TreePath path : paths) {
+ if (isPathSelected(path.getParentPath())) continue;
+ AbstractTestProxy test = getSelectedTest(path);
+ if (test != null) {
+ final Location<?> location = (Location<?>)TestsUIUtil.getData(test, Location.DATA_KEY.getName(), myModel);
+ if (location != null) {
+ locations.add(location);
+ }
+ }
+ }
+ return locations.isEmpty() ? null : locations.toArray(new Location[locations.size()]);
+ }
+ }
final TreePath selectionPath = getSelectionPath();
if (selectionPath == null) return null;
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/TrackRunningTestUtil.java b/platform/testRunner/src/com/intellij/execution/testframework/TrackRunningTestUtil.java
index d94de74..eac1656 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/TrackRunningTestUtil.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/TrackRunningTestUtil.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pass;
import com.intellij.ui.ClickListener;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -40,7 +41,7 @@
public static void installStopListeners(final JTree tree, final Disposable parentDisposable, final Pass<AbstractTestProxy> setSelection) {
final ClickListener userSelectionListener = new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
setSelection.pass(setUserSelection(tree.getPathForLocation(e.getX(), e.getY())));
return true;
}
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java b/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java
index f9e58e9..ab43544 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/export/ExportTestResultsAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -24,7 +24,6 @@
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.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Attachment;
@@ -36,7 +35,6 @@
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
@@ -128,7 +126,7 @@
ExecutionBundle.message("export.test.results.file.exists.message", filename),
ExecutionBundle.message("export.test.results.file.exists.title"),
Messages.getQuestionIcon()
- ) != DialogWrapper.OK_EXIT_CODE;
+ ) != Messages.OK;
}
final String filename_ = filename;
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java b/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java
index 901fc76..717e9aa 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/ui/BaseTestsOutputConsoleView.java
@@ -59,12 +59,15 @@
protected abstract TestResultsPanel createTestResultsPanel();
+ @Override
public void attachToProcess(final ProcessHandler processHandler) {
myConsole.attachToProcess(processHandler);
}
- public void print(final String s, final ConsoleViewContentType contentType) {
+ @Override
+ public void print(@NotNull final String s, @NotNull final ConsoleViewContentType contentType) {
printNew(new Printable() {
+ @Override
public void printOn(final Printer printer) {
printer.print(s, contentType);
}
@@ -75,67 +78,82 @@
public void allowHeavyFilters() {
}
+ @Override
public void clear() {
myConsole.clear();
}
+ @Override
public void scrollTo(final int offset) {
myConsole.scrollTo(offset);
}
+ @Override
public void setOutputPaused(final boolean value) {
if (myPrinter != null) {
myPrinter.pause(value);
}
}
+ @Override
public boolean isOutputPaused() {
//noinspection SimplifiableConditionalExpression
return myPrinter == null ? true : myPrinter.isPaused();
}
+ @Override
public boolean hasDeferredOutput() {
return myConsole.hasDeferredOutput();
}
+ @Override
public void performWhenNoDeferredOutput(final Runnable runnable) {
myConsole.performWhenNoDeferredOutput(runnable);
}
+ @Override
public void setHelpId(final String helpId) {
myConsole.setHelpId(helpId);
}
+ @Override
public void addMessageFilter(final Filter filter) {
myConsole.addMessageFilter(filter);
}
+ @Override
public void printHyperlink(final String hyperlinkText, final HyperlinkInfo info) {
printNew(new HyperLink(hyperlinkText, info));
}
+ @Override
public int getContentSize() {
return myConsole.getContentSize();
}
+ @Override
public boolean canPause() {
return myPrinter != null && myPrinter.canPause() && myConsole.canPause();
}
+ @Override
public JComponent getComponent() {
return myTestResultsPanel;
}
+ @Override
public JComponent getPreferredFocusableComponent() {
return myConsole.getPreferredFocusableComponent();
}
+ @Override
public void dispose() {
myPrinter = null;
myProperties = null;
myConsole = null;
}
+ @Override
public void addChangeListener(@NotNull final ChangeListener listener, @NotNull final Disposable parent) {
if (myConsole instanceof ObservableConsoleView) {
((ObservableConsoleView)myConsole).addChangeListener(listener, parent);
@@ -144,6 +162,7 @@
}
}
+ @Override
@NotNull
public AnAction[] createConsoleActions() {
return AnAction.EMPTY_ARRAY;
diff --git a/platform/testRunner/src/com/intellij/execution/testframework/ui/TestResultsPanel.java b/platform/testRunner/src/com/intellij/execution/testframework/ui/TestResultsPanel.java
index 5a7814f..a751942 100644
--- a/platform/testRunner/src/com/intellij/execution/testframework/ui/TestResultsPanel.java
+++ b/platform/testRunner/src/com/intellij/execution/testframework/ui/TestResultsPanel.java
@@ -115,6 +115,7 @@
});
rightPanel.add(myStatisticsSplitter, BorderLayout.CENTER);
splitter.setSecondComponent(rightPanel);
+ testTreeView.setBorder(BorderFactory.createEmptyBorder(0, 3, 0, 0));
setLeftComponent(testTreeView);
}
diff --git a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
index dc9068e..930321f 100644
--- a/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
+++ b/platform/usageView/src/com/intellij/usages/ChunkExtractor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -36,6 +36,7 @@
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
+import com.intellij.reference.SoftReference;
import com.intellij.usageView.UsageTreeColors;
import com.intellij.usageView.UsageTreeColorsScheme;
import com.intellij.util.Processor;
@@ -75,7 +76,7 @@
@NotNull
public T getValue() {
- final T cur = myRef == null ? null : myRef.get();
+ final T cur = SoftReference.dereference(myRef);
if (cur != null) return cur;
final T result = create();
myRef = new WeakReference<T>(result);
diff --git a/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java b/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java
index 5d250eb..5f51c2e 100644
--- a/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.java
+++ b/platform/usageView/src/com/intellij/usages/ConfigurableUsageTarget.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,12 @@
*/
package com.intellij.usages;
+import com.intellij.openapi.actionSystem.KeyboardShortcut;
+import org.jetbrains.annotations.NotNull;
+
public interface ConfigurableUsageTarget extends UsageTarget {
void showSettings();
+ KeyboardShortcut getShortcut();
+ @NotNull
+ String getLongDescriptiveName();
}
diff --git a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
index 142a54e..d608303 100644
--- a/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.java
+++ b/platform/usageView/src/com/intellij/usages/FindUsagesProcessPresentation.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,15 +33,17 @@
public class FindUsagesProcessPresentation {
@NonNls
public static final String NAME_WITH_MNEMONIC_KEY = "NameWithMnemonic";
+ private final UsageViewPresentation myUsageViewPresentation;
private List<Action> myNotFoundActions;
private boolean myShowPanelIfOnlyOneUsage;
private boolean myShowNotFoundMessage;
private Factory<ProgressIndicator> myProgressIndicatorFactory;
private Collection<PsiFile> myLargeFiles;
- private boolean myShowFindOptionsPrompt = true; // in the case of find in path, "find options" does not make sense
+ private boolean myShowFindOptionsPrompt = true;
- public FindUsagesProcessPresentation() {
+ public FindUsagesProcessPresentation(@NotNull UsageViewPresentation presentation) {
+ myUsageViewPresentation = presentation;
}
public void addNotFoundAction(@NotNull Action action) {
@@ -91,8 +93,14 @@
return myShowFindOptionsPrompt;
}
+ @NotNull
+ public UsageViewPresentation getUsageViewPresentation() {
+ return myUsageViewPresentation;
+ }
+
public void setShowFindOptionsPrompt(boolean showFindOptionsPrompt) {
myShowFindOptionsPrompt = showFindOptionsPrompt;
}
}
+
diff --git a/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java b/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java
index 79c14cb..71cad73 100644
--- a/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.java
+++ b/platform/usageView/src/com/intellij/usages/PsiElementUsageTarget.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,6 @@
/**
* @author max
*/
-public interface PsiElementUsageTarget extends ConfigurableUsageTarget {
+public interface PsiElementUsageTarget extends UsageTarget {
PsiElement getElement();
}
\ No newline at end of file
diff --git a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
index da6d75f..aaccbff 100644
--- a/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
+++ b/platform/usageView/src/com/intellij/usages/UsageInfo2UsageAdapter.java
@@ -168,7 +168,8 @@
@Override
public boolean isReadOnly() {
- return isValid() && !getElement().isWritable();
+ PsiFile psiFile = getPsiFile();
+ return psiFile == null || psiFile.isValid() && !psiFile.isWritable();
}
@Override
@@ -437,8 +438,7 @@
@Override
@NotNull
public TextChunk[] getText() {
- Reference<TextChunk[]> reference = myTextChunks;
- TextChunk[] chunks = reference == null ? null : reference.get();
+ TextChunk[] chunks = SoftReference.dereference(myTextChunks);
final long currentModificationStamp = getCurrentModificationStamp();
boolean isModified = currentModificationStamp != myModificationStamp;
if (chunks == null || isValid() && isModified) {
@@ -480,11 +480,15 @@
Icon icon = myIcon;
if (icon == null) {
PsiElement psiElement = getElement();
- myIcon = icon = psiElement != null && psiElement.isValid() ? psiElement.getIcon(0) : null;
+ myIcon = icon = psiElement != null && psiElement.isValid() && !isFindInPathUsage(psiElement) ? psiElement.getIcon(0) : null;
}
return icon;
}
+ private boolean isFindInPathUsage(PsiElement psiElement) {
+ return psiElement instanceof PsiFile && getUsageInfo().getPsiFileRange() != null;
+ }
+
@Override
public String getTooltipText() {
return myUsageInfo.getTooltipText();
diff --git a/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java b/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java
index b55b441..4382cff 100644
--- a/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.java
+++ b/platform/usageView/src/com/intellij/usages/UsageInfoToUsageConverter.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.
@@ -128,6 +128,11 @@
public static Usage convert(@NotNull TargetElementsDescriptor descriptor, @NotNull UsageInfo usageInfo) {
PsiElement[] primaryElements = descriptor.getPrimaryElements();
+ return convert(primaryElements, usageInfo);
+ }
+
+ @NotNull
+ public static Usage convert(@NotNull PsiElement[] primaryElements, @NotNull UsageInfo usageInfo) {
PsiElement usageElement = usageInfo.getElement();
for(ReadWriteAccessDetector detector: Extensions.getExtensions(ReadWriteAccessDetector.EP_NAME)) {
if (isReadWriteAccessibleElements(primaryElements, detector)) {
@@ -149,6 +154,17 @@
return usages;
}
+ @NotNull
+ public static Usage[] convert(@NotNull final PsiElement[] primaryElements, @NotNull UsageInfo[] usageInfos) {
+ Usage[] usages = ContainerUtil.map(usageInfos, new Function<UsageInfo, Usage>() {
+ @Override
+ public Usage fun(UsageInfo info) {
+ return convert(primaryElements, info);
+ }
+ }, new Usage[usageInfos.length]);
+ return usages;
+ }
+
private static boolean isReadWriteAccessibleElements(@NotNull PsiElement[] elements, @NotNull ReadWriteAccessDetector detector) {
if (elements.length == 0) {
return false;
diff --git a/platform/usageView/src/com/intellij/usages/UsageLimitUtil.java b/platform/usageView/src/com/intellij/usages/UsageLimitUtil.java
index 85bf70d..61fd1d9 100644
--- a/platform/usageView/src/com/intellij/usages/UsageLimitUtil.java
+++ b/platform/usageView/src/com/intellij/usages/UsageLimitUtil.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 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.GuiUtils;
import com.intellij.usageView.UsageViewBundle;
import org.jetbrains.annotations.NotNull;
@@ -29,8 +30,10 @@
public class UsageLimitUtil {
public static final int USAGES_LIMIT = 1000;
- public static void showAndCancelIfAborted(final Project project, final String message) {
- Result retCode = showTooManyUsagesWarning(project, message);
+ public static void showAndCancelIfAborted(@NotNull Project project,
+ @NotNull String message,
+ @NotNull UsageViewPresentation usageViewPresentation) {
+ Result retCode = showTooManyUsagesWarning(project, message, usageViewPresentation);
if (retCode != Result.CONTINUE) {
throw new ProcessCanceledException();
@@ -42,19 +45,23 @@
}
@NotNull
- public static Result showTooManyUsagesWarning(@NotNull final Project project, @NotNull final String message) {
+ public static Result showTooManyUsagesWarning(@NotNull final Project project,
+ @NotNull final String message,
+ @NotNull final UsageViewPresentation usageViewPresentation) {
final String[] buttons = {UsageViewBundle.message("button.text.continue"), UsageViewBundle.message("button.text.abort")};
int result = runOrInvokeAndWait(new Computable<Integer>() {
@Override
public Integer compute() {
- return Messages.showOkCancelDialog(project, message, UsageViewBundle.message("find.excessive.usages.title"), buttons[0], buttons[1],
+ String title = UsageViewBundle.message("find.excessive.usages.title", StringUtil.capitalize(StringUtil.pluralize(usageViewPresentation.getUsagesWord())));
+ return Messages.showOkCancelDialog(project, message,
+ title, buttons[0], buttons[1],
Messages.getWarningIcon());
}
});
return result == Messages.OK ? Result.CONTINUE : Result.ABORT;
}
- private static int runOrInvokeAndWait(final Computable<Integer> f) {
+ private static int runOrInvokeAndWait(@NotNull final Computable<Integer> f) {
final int[] answer = new int[1];
try {
GuiUtils.runOrInvokeAndWait(new Runnable() {
diff --git a/platform/usageView/src/com/intellij/usages/UsageModelTracker.java b/platform/usageView/src/com/intellij/usages/UsageModelTracker.java
index b3c60fa..6aa9940 100644
--- a/platform/usageView/src/com/intellij/usages/UsageModelTracker.java
+++ b/platform/usageView/src/com/intellij/usages/UsageModelTracker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -33,7 +33,7 @@
private final List<UsageModelTrackerListener> myListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- public UsageModelTracker(Project project) {
+ public UsageModelTracker(@NotNull Project project) {
final PsiTreeChangeListener myPsiListener = new PsiTreeChangeAdapter() {
@Override
public void childAdded(@NotNull PsiTreeChangeEvent event) {
@@ -68,7 +68,7 @@
PsiManager.getInstance(project).addPsiTreeChangeListener(myPsiListener, this);
}
- private void doFire(final PsiTreeChangeEvent event, boolean propertyChange) {
+ private void doFire(@NotNull PsiTreeChangeEvent event, boolean propertyChange) {
if (!(event.getFile() instanceof PsiCodeFragment)) {
for (UsageModelTrackerListener listener : myListeners) {
listener.modelChanged(propertyChange);
@@ -80,11 +80,11 @@
public void dispose() {
}
- public void addListener(UsageModelTrackerListener listener) {
+ public void addListener(@NotNull UsageModelTrackerListener listener) {
myListeners.add(listener);
}
- public void removeListener(UsageModelTrackerListener listener) {
+ public void removeListener(@NotNull UsageModelTrackerListener listener) {
myListeners.remove(listener);
}
}
diff --git a/platform/usageView/src/com/intellij/usages/UsageTarget.java b/platform/usageView/src/com/intellij/usages/UsageTarget.java
index fd50a20..f9a555d 100644
--- a/platform/usageView/src/com/intellij/usages/UsageTarget.java
+++ b/platform/usageView/src/com/intellij/usages/UsageTarget.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,7 +29,7 @@
public interface UsageTarget extends NavigationItem {
UsageTarget[] EMPTY_ARRAY = new UsageTarget[0];
/**
- * Should display a usage dialog, open usage view and look for usages of itself
+ * Should open usage view and look for usages
*/
void findUsages();
diff --git a/platform/usageView/src/com/intellij/usages/UsageView.java b/platform/usageView/src/com/intellij/usages/UsageView.java
index 2736f74..46906ba 100644
--- a/platform/usageView/src/com/intellij/usages/UsageView.java
+++ b/platform/usageView/src/com/intellij/usages/UsageView.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -71,6 +71,7 @@
*/
void addPerformOperationAction(@NotNull Runnable processRunnable, String commandName, String cannotMakeString, @NotNull String shortDescription, boolean checkReadOnlyStatus);
+ @NotNull
UsageViewPresentation getPresentation();
@NotNull
diff --git a/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java b/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java
index 3467dcc..832d592 100644
--- a/platform/usageView/src/com/intellij/usages/UsageViewPresentation.java
+++ b/platform/usageView/src/com/intellij/usages/UsageViewPresentation.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,7 @@
package com.intellij.usages;
import com.intellij.usageView.UsageViewBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -96,19 +97,21 @@
myShowCancelButton = showCancelButton;
}
+ @NotNull
public String getNonCodeUsagesString() {
return myNonCodeUsagesString;
}
- public void setNonCodeUsagesString(String nonCodeUsagesString) {
+ public void setNonCodeUsagesString(@NotNull String nonCodeUsagesString) {
myNonCodeUsagesString = nonCodeUsagesString;
}
+ @NotNull
public String getCodeUsagesString() {
return myCodeUsagesString;
}
- public void setCodeUsagesString(String codeUsagesString) {
+ public void setCodeUsagesString(@NotNull String codeUsagesString) {
myCodeUsagesString = codeUsagesString;
}
@@ -137,11 +140,12 @@
return myNotFoundActions;
}
+ @NotNull
public String getUsagesWord() {
return myUsagesWord;
}
- public void setUsagesWord(final String usagesWord) {
+ public void setUsagesWord(@NotNull String usagesWord) {
myUsagesWord = usagesWord;
}
@@ -177,11 +181,12 @@
return myDynamicCodeUsagesString;
}
+ @NotNull
public String getUsagesInGeneratedCodeString() {
return myUsagesInGeneratedCodeString;
}
- public void setUsagesInGeneratedCodeString(String usagesInGeneratedCodeString) {
+ public void setUsagesInGeneratedCodeString(@NotNull String usagesInGeneratedCodeString) {
myUsagesInGeneratedCodeString = usagesInGeneratedCodeString;
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/ExporterToTextFile.java b/platform/usageView/src/com/intellij/usages/impl/ExporterToTextFile.java
index 31accc9..d55a24d 100644
--- a/platform/usageView/src/com/intellij/usages/impl/ExporterToTextFile.java
+++ b/platform/usageView/src/com/intellij/usages/impl/ExporterToTextFile.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import com.intellij.usages.UsageGroup;
import com.intellij.usages.UsageViewSettings;
import com.intellij.util.SystemProperties;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.ChangeListener;
@@ -33,7 +34,7 @@
class ExporterToTextFile implements com.intellij.ide.ExporterToTextFile {
private final UsageViewImpl myUsageView;
- public ExporterToTextFile(UsageViewImpl usageView) {
+ public ExporterToTextFile(@NotNull UsageViewImpl usageView) {
myUsageView = usageView;
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/PreviewUsageAction.java b/platform/usageView/src/com/intellij/usages/impl/PreviewUsageAction.java
index d06f936..107e157 100644
--- a/platform/usageView/src/com/intellij/usages/impl/PreviewUsageAction.java
+++ b/platform/usageView/src/com/intellij/usages/impl/PreviewUsageAction.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,7 @@
package com.intellij.usages.impl;
import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usages.UsageView;
import com.intellij.usages.UsageViewSettings;
@@ -26,7 +27,7 @@
*/
class PreviewUsageAction extends RuleAction {
PreviewUsageAction(@NotNull UsageView usageView) {
- super(usageView, UsageViewBundle.message("preview.usages.action.text"), AllIcons.Actions.PreviewDetails);
+ super(usageView, UsageViewBundle.message("preview.usages.action.text", StringUtil.capitalize(StringUtil.pluralize(usageView.getPresentation().getUsagesWord()))), AllIcons.Actions.PreviewDetails);
}
@Override
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java b/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java
index e1cb636..d807c5b 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageContextPanelBase.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.ui.IdeBorderFactory;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.UsageContextPanel;
+import com.intellij.usages.UsageViewPresentation;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -33,10 +34,12 @@
*/
public abstract class UsageContextPanelBase extends JPanel implements UsageContextPanel {
protected final Project myProject;
+ @NotNull protected final UsageViewPresentation myPresentation;
protected volatile boolean isDisposed;
- public UsageContextPanelBase(@NotNull Project project) {
+ public UsageContextPanelBase(@NotNull Project project, @NotNull UsageViewPresentation presentation) {
myProject = project;
+ myPresentation = presentation;
setLayout(new BorderLayout());
setBorder(IdeBorderFactory.createBorder());
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java
index a9f4831..e2c023d 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsagePreviewPanel.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.
@@ -31,6 +31,7 @@
import com.intellij.usageView.UsageViewBundle;
import com.intellij.usages.UsageContextPanel;
import com.intellij.usages.UsageView;
+import com.intellij.usages.UsageViewPresentation;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -45,15 +46,15 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.usages.impl.UsagePreviewPanel");
private Editor myEditor;
- public UsagePreviewPanel(@NotNull Project project) {
- super(project);
+ public UsagePreviewPanel(@NotNull Project project, @NotNull UsageViewPresentation presentation) {
+ super(project, presentation);
}
public static class Provider implements UsageContextPanel.Provider {
@NotNull
@Override
public UsageContextPanel create(@NotNull UsageView usageView) {
- return new UsagePreviewPanel(((UsageViewImpl)usageView).getProject());
+ return new UsagePreviewPanel(((UsageViewImpl)usageView).getProject(), usageView.getPresentation());
}
@Override
@@ -189,7 +190,7 @@
if (infos == null) {
releaseEditor();
removeAll();
- JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview"), SwingConstants.CENTER);
+ JComponent titleComp = new JLabel(UsageViewBundle.message("select.the.usage.to.preview", myPresentation.getUsagesWord()), SwingConstants.CENTER);
add(titleComp, BorderLayout.CENTER);
revalidate();
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java
index eba23c2..35463f0 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewImpl.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 @@
import com.intellij.icons.AllIcons;
import com.intellij.ide.*;
import com.intellij.ide.actions.CloseTabToolbarAction;
+import com.intellij.navigation.NavigationItem;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
@@ -43,6 +44,7 @@
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
+import com.intellij.psi.impl.PsiDocumentManagerBase;
import com.intellij.ui.*;
import com.intellij.ui.components.JBTabbedPane;
import com.intellij.ui.content.Content;
@@ -59,6 +61,7 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.TransferToEDTQueue;
+import com.intellij.util.enumeration.EmptyEnumeration;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.DialogUtil;
import com.intellij.util.ui.UIUtil;
@@ -95,8 +98,8 @@
private final Factory<UsageSearcher> myUsageSearcherFactory;
private final Project myProject;
- private boolean mySearchInProgress = true;
- private ExporterToTextFile myTextFileExporter;
+ private volatile boolean mySearchInProgress = true;
+ private final ExporterToTextFile myTextFileExporter = new ExporterToTextFile(this);
private final Alarm myUpdateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
private final UsageModelTracker myModelTracker;
@@ -144,6 +147,13 @@
private Splitter myPreviewSplitter;
private volatile ProgressIndicator associatedProgress; // the progress that current find usages is running under
+ // true if usages tree is currently expanding
+ // (either at the end of find usages thanks to the 'expand usages after find' setting or
+ // because the user pressed 'expand all' button. During this, some ugly hacks applied
+ // to speed up the expanding (see getExpandedDescendants() here and UsageViewTreeCellRenderer.customizeCellRenderer())
+ private boolean expandingAll;
+ private final UsageViewTreeCellRenderer myUsageViewTreeCellRenderer;
+
UsageViewImpl(@NotNull final Project project,
@NotNull UsageViewPresentation presentation,
@NotNull UsageTarget[] targets,
@@ -161,7 +171,7 @@
TreePath path = getPathForLocation(e.getX(), e.getY());
if (path != null) {
if (getCellRenderer() instanceof UsageViewTreeCellRenderer) {
- return UsageViewTreeCellRenderer.getTooltipText(path.getLastPathComponent());
+ return UsageViewTreeCellRenderer.getTooltipFromPresentation(path.getLastPathComponent());
}
}
return null;
@@ -171,6 +181,12 @@
public boolean isPathEditable(final TreePath path) {
return path.getLastPathComponent() instanceof UsageViewTreeModelBuilder.TargetsRootNode;
}
+
+ // hack to avoid quadratic expandAll()
+ @Override
+ public Enumeration<TreePath> getExpandedDescendants(TreePath parent) {
+ return expandingAll ? EmptyEnumeration.<TreePath>getInstance() : super.getExpandedDescendants(parent);
+ }
};
myRootPanel = new MyPanel(myTree);
Disposer.register(this, myRootPanel);
@@ -189,6 +205,7 @@
}
});
+ myUsageViewTreeCellRenderer = new UsageViewTreeCellRenderer(this);
if (!myPresentation.isDetachedMode()) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
@@ -214,7 +231,7 @@
initTree();
toolWindowPanel.setContent(myCentralPanel);
- myTree.setCellRenderer(new UsageViewTreeCellRenderer(UsageViewImpl.this));
+ myTree.setCellRenderer(myUsageViewTreeCellRenderer);
collapseAll();
myModelTracker.addListener(UsageViewImpl.this);
@@ -253,7 +270,7 @@
}, new Condition<Object>() {
@Override
public boolean value(Object o) {
- return isDisposed || project.isDisposed() || searchHasBeenCancelled();
+ return isDisposed || project.isDisposed();
}
},200);
}
@@ -275,6 +292,16 @@
disposeUsageContextPanels();
JScrollPane treePane = ScrollPaneFactory.createScrollPane(myTree);
+ // add reaction to scrolling:
+ // since the UsageViewTreeCellRenderer ignores invisible nodes (outside the viewport), their preferred size is incorrect
+ // and we need to recalculate it when the node scrolled into visible rectangle
+ treePane.getViewport().addChangeListener(new ChangeListener() {
+ @Override
+ public void stateChanged(ChangeEvent e) {
+ // clear renderer cache of node preferred size
+ myTree.setCellRenderer(myUsageViewTreeCellRenderer);
+ }
+ });
myPreviewSplitter = new Splitter(false, 0.5f, 0.1f, 0.9f);
myPreviewSplitter.setFirstComponent(treePane);
@@ -431,7 +458,7 @@
Object component = path.getLastPathComponent();
if (!(component instanceof Node)) return;
Node node = (Node)component;
- if (node.needsUpdate()) {
+ if (!expandingAll && node.needsUpdate()) {
checkNodeValidity(node, path);
}
}
@@ -448,13 +475,9 @@
TreeCellRenderer renderer = myTree.getCellRenderer();
if (renderer instanceof UsageViewTreeCellRenderer) {
UsageViewTreeCellRenderer coloredRenderer = (UsageViewTreeCellRenderer)renderer;
- coloredRenderer.clear();
- coloredRenderer.customizeCellRenderer(null, value, false, false, false, 0, false);
- return coloredRenderer.getCharSequence(true).toString();
+ return coloredRenderer.getPlainTextForNode(value);
}
- else {
- return value == null? null : value.toString();
- }
+ return value == null ? null : value.toString();
}
}, true);
}
@@ -556,8 +579,6 @@
CommonActionsManager actionsManager = CommonActionsManager.getInstance();
- myTextFileExporter = new ExporterToTextFile(this);
-
final JComponent component = getComponent();
final AnAction expandAllAction = actionsManager.createExpandAllAction(treeExpander, component);
@@ -573,7 +594,7 @@
return new AnAction[] {
- showSettings(),
+ canShowSettings() ? showSettings() : null,
canPerformReRun() ? new ReRunAction() : null,
new CloseAction(),
ActionManager.getInstance().getAction("PinToolwindowTab"),
@@ -588,11 +609,19 @@
};
}
+ private boolean canShowSettings() {
+ if (myTargets.length == 0) return false;
+ NavigationItem target = myTargets[0];
+ return target instanceof ConfigurableUsageTarget;
+ }
+
@NotNull
private AnAction showSettings() {
- return new AnAction("Settings...", "Show find usages settings dialog", AllIcons.General.ProjectSettings) {
+ final ConfigurableUsageTarget configurableUsageTarget = getConfigurableTarget(myTargets);
+ String description = configurableUsageTarget == null ? "Show find usages settings dialog" : "Show settings for "+configurableUsageTarget.getLongDescriptiveName();
+ return new AnAction("Settings...", description, AllIcons.General.ProjectSettings) {
{
- KeyboardShortcut shortcut = getShowUsagesWithSettingsShortcut();
+ KeyboardShortcut shortcut = configurableUsageTarget == null ? getShowUsagesWithSettingsShortcut() : configurableUsageTarget.getShortcut();
if (shortcut != null) {
registerCustomShortcutSet(new CustomShortcutSet(shortcut), getComponent());
}
@@ -604,6 +633,17 @@
};
}
+ private static ConfigurableUsageTarget getConfigurableTarget(@NotNull UsageTarget[] targets) {
+ ConfigurableUsageTarget configurableUsageTarget = null;
+ if (targets.length != 0) {
+ NavigationItem target = targets[0];
+ if (target instanceof ConfigurableUsageTarget) {
+ configurableUsageTarget = (ConfigurableUsageTarget)target;
+ }
+ }
+ return configurableUsageTarget;
+ }
+
@NotNull
private AnAction createRecentFindUsagesAction() {
AnAction action = ActionManager.getInstance().getAction(SHOW_RECENT_FIND_USAGES_ACTION_ID);
@@ -694,7 +734,13 @@
}
private void expandAll() {
- TreeUtil.expandAll(myTree);
+ expandingAll = true;
+ try {
+ TreeUtil.expandAll(myTree);
+ }
+ finally {
+ expandingAll = false;
+ }
}
private void collapseAll() {
@@ -722,6 +768,11 @@
return ActionManager.getInstance().getKeyboardShortcut("ShowSettingsAndFindUsages");
}
+ static KeyboardShortcut getShowUsagesWithSettingsShortcut(@NotNull UsageTarget[] targets) {
+ ConfigurableUsageTarget configurableTarget = getConfigurableTarget(targets);
+ return configurableTarget == null ? getShowUsagesWithSettingsShortcut() : configurableTarget.getShortcut();
+ }
+
void associateProgress(ProgressIndicator indicator) {
associatedProgress = indicator;
}
@@ -805,7 +856,7 @@
if (usageCount > UsageLimitUtil.USAGES_LIMIT) {
if (tooManyUsagesStatus.switchTooManyUsagesStatus()) {
UsageViewManagerImpl
- .showTooManyUsagesWarning(project, tooManyUsagesStatus, indicator, usageCountWithoutDefinition.get(), UsageViewImpl.this);
+ .showTooManyUsagesWarning(project, tooManyUsagesStatus, indicator, getPresentation(), usageCountWithoutDefinition.get(), UsageViewImpl.this);
}
}
ApplicationManager.getApplication().runReadAction(new Runnable() {
@@ -870,6 +921,10 @@
myTransferToEDTQueue.offer(runnable);
}
});
+ if (node != null) {
+ // update and cache flags while the node is still hot
+ node.update(this);
+ }
myUsageNodes.put(usage, node == null ? NULL_NODE : node);
return node;
}
@@ -973,7 +1028,7 @@
return myUsageNodes.size();
}
- public void setContent(@NotNull Content content) {
+ void setContent(@NotNull Content content) {
myContent = content;
content.setDisposer(this);
}
@@ -1019,7 +1074,12 @@
shouldCheckChildren = false;
// optimization: do not call expensive update() on invisible node
}
- if (shouldCheckChildren) {
+ UsageViewTreeCellRenderer.RowLocation isVisible =
+ myUsageViewTreeCellRenderer.isRowVisible(myTree.getRowForPath(new TreePath(((DefaultMutableTreeNode)node).getPath())),
+ myTree.getVisibleRect());
+
+ // if row is below visible rectangle, no sense to update it or any children
+ if (shouldCheckChildren && isVisible != UsageViewTreeCellRenderer.RowLocation.AFTER_VISIBLE_RECT) {
for (int i=0; i < node.getChildCount(); i++) {
TreeNode child = node.getChildAt(i);
checkNodeValidity(child, path.pathByAddingChild(child));
@@ -1027,7 +1087,7 @@
}
// call update last, to let children a chance to update their cache first
- if (node instanceof Node && node != getModelRoot()) {
+ if (node instanceof Node && node != getModelRoot() && isVisible == UsageViewTreeCellRenderer.RowLocation.INSIDE_VISIBLE_RECT) {
((Node)node).update(this);
}
}
@@ -1038,9 +1098,13 @@
@Override
public void run() {
if (myProject.isDisposed()) return;
- PsiDocumentManager.getInstance(myProject).commitAllDocuments();
-
- updateImmediately();
+ PsiDocumentManagerBase documentManager = (PsiDocumentManagerBase)PsiDocumentManager.getInstance(myProject);
+ documentManager.cancelAndRunWhenAllCommitted("UpdateUsageView", new Runnable() {
+ @Override
+ public void run() {
+ updateImmediately();
+ }
+ });
}
}, 300);
}
@@ -1172,6 +1236,7 @@
return true;
}
+ @NotNull
@Override
public UsageViewPresentation getPresentation() {
return myPresentation;
@@ -1377,6 +1442,7 @@
@Override
protected Navigatable createDescriptorForNode(DefaultMutableTreeNode node) {
if (node.getChildCount() > 0) return null;
+ if (node instanceof Node && ((Node)node).isExcluded()) return null;
return getNavigatableForNode(node);
}
@@ -1603,7 +1669,7 @@
String[] options = {UsageViewBundle.message("action.description.rerun"), UsageViewBundle.message("usage.view.cancel.button")};
String message = myCannotMakeString + "\n\n" + UsageViewBundle.message("dialog.rerun.search");
int answer = Messages.showOkCancelDialog(myProject, message, title, options[0], options[1], Messages.getErrorIcon());
- if (answer == 0) {
+ if (answer == Messages.OK) {
refreshUsages();
}
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
index 7b14c97..0e7bae2 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewManagerImpl.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.
@@ -137,7 +137,7 @@
@Nullable final UsageViewStateListener listener) {
final AtomicReference<UsageViewImpl> usageViewRef = new AtomicReference<UsageViewImpl>();
- final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation();
+ final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation(presentation);
processPresentation.setShowNotFoundMessage(showNotFoundMessage);
processPresentation.setShowPanelIfOnlyOneUsage(showPanelIfOnlyOneUsage);
@@ -211,10 +211,11 @@
@NotNull
public static String getProgressTitle(@NotNull UsageViewPresentation presentation) {
final String scopeText = presentation.getScopeText();
- if (scopeText == null) {
- return UsageViewBundle.message("progress.searching.for", StringUtil.capitalize(presentation.getUsagesString()));
- }
- return UsageViewBundle.message("progress.searching.for.in", StringUtil.capitalize(presentation.getUsagesString()), scopeText);
+ String usagesString = StringUtil.capitalize(presentation.getUsagesString());
+ String result = scopeText == null
+ ? UsageViewBundle.message("progress.searching.for", usagesString)
+ : UsageViewBundle.message("progress.searching.for.in", usagesString, scopeText);
+ return StringUtil.escapeXml(result);
}
private void showToolWindow(boolean activateWindow) {
@@ -237,17 +238,18 @@
}
- public static void showTooManyUsagesWarning(@NotNull final Project project,
- @NotNull final TooManyUsagesStatus tooManyUsagesStatus,
- @NotNull final ProgressIndicator indicator,
- final int usageCount,
- final UsageViewImpl usageView) {
+ static void showTooManyUsagesWarning(@NotNull final Project project,
+ @NotNull final TooManyUsagesStatus tooManyUsagesStatus,
+ @NotNull final ProgressIndicator indicator,
+ @NotNull final UsageViewPresentation presentation,
+ final int usageCount,
+ final UsageViewImpl usageView) {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
if (usageView != null && usageView.searchHasBeenCancelled() || indicator.isCanceled()) return;
- String message = UsageViewBundle.message("find.excessive.usage.count.prompt", usageCount);
- UsageLimitUtil.Result ret = UsageLimitUtil.showTooManyUsagesWarning(project, message);
+ String message = UsageViewBundle.message("find.excessive.usage.count.prompt", usageCount, StringUtil.pluralize(presentation.getUsagesWord()));
+ UsageLimitUtil.Result ret = UsageLimitUtil.showTooManyUsagesWarning(project, message, presentation);
if (ret == UsageLimitUtil.Result.ABORT && usageView != null) {
usageView.cancelCurrentSearch();
indicator.cancel();
@@ -260,7 +262,8 @@
private class SearchForUsagesRunnable implements Runnable {
private final AtomicInteger myUsageCountWithoutDefinition = new AtomicInteger(0);
private final AtomicReference<Usage> myFirstUsage = new AtomicReference<Usage>();
- @NotNull private final Project myProject;
+ @NotNull
+ private final Project myProject;
private final AtomicReference<UsageViewImpl> myUsageViewRef;
private final UsageViewPresentation myPresentation;
private final UsageTarget[] mySearchFor;
@@ -316,6 +319,7 @@
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
+ if (myProject.isDisposed()) return;
addContent(usageView, myPresentation);
if (myListener != null) {
myListener.usageViewCreated(usageView);
@@ -339,7 +343,7 @@
findUsagesStartedBalloon.addRequest(new Runnable() {
@Override
public void run() {
- String balloon = "Searching for " + myPresentation.getUsagesString()+"...";
+ String balloon = UsageViewBundle.message("progress.searching.for", StringUtil.escapeXml(myPresentation.getUsagesString()));
notifyByFindBalloon(null, MessageType.WARNING, myProcessPresentation, UsageViewManagerImpl.this.myProject,
balloon);
findStartedBalloonShown.set(true);
@@ -363,10 +367,8 @@
final UsageViewImpl usageView = getUsageView(indicator);
- if (usageCount > UsageLimitUtil.USAGES_LIMIT) {
- if (tooManyUsagesStatus.switchTooManyUsagesStatus()) {
- showTooManyUsagesWarning(myProject, tooManyUsagesStatus, indicator, myUsageCountWithoutDefinition.get(), usageView);
- }
+ if (usageCount > UsageLimitUtil.USAGES_LIMIT && tooManyUsagesStatus.switchTooManyUsagesStatus()) {
+ showTooManyUsagesWarning(myProject, tooManyUsagesStatus, indicator, myPresentation, usageCount, usageView);
}
if (usageView != null) {
@@ -416,7 +418,7 @@
myPresentation.getScopeText());
if (notFoundActions.isEmpty()) {
- String[] lines = myProcessPresentation.isShowFindOptionsPrompt() ? new String[] {StringUtil.escapeXml(message), createOptionsHtml()} : new String[]{StringUtil.escapeXml(message)};
+ String[] lines = myProcessPresentation.isShowFindOptionsPrompt() ? new String[] {StringUtil.escapeXml(message), createOptionsHtml(mySearchFor)} : new String[]{StringUtil.escapeXml(message)};
notifyByFindBalloon(createGotToOptionsListener(mySearchFor),
MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject, lines);
findStartedBalloonShown.set(false);
@@ -451,7 +453,8 @@
flashUsageScriptaculously(usage);
}
notifyByFindBalloon(createGotToOptionsListener(mySearchFor),
- MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject,"Only one usage found.", createOptionsHtml());
+ MessageType.INFO, myProcessPresentation, UsageViewManagerImpl.this.myProject,"Only one usage found.", createOptionsHtml(
+ mySearchFor));
}
}, ModalityState.NON_MODAL, myProject.getDisposed());
}
@@ -591,9 +594,9 @@
}
@NotNull
- private static String createOptionsHtml() {
+ private static String createOptionsHtml(@NonNls UsageTarget[] searchFor) {
+ KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut(searchFor);
String shortcutText = "";
- KeyboardShortcut shortcut = UsageViewImpl.getShowUsagesWithSettingsShortcut();
if (shortcut != null) {
shortcutText = " (" + KeymapUtil.getShortcutText(shortcut) + ")";
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java b/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java
index 06815ac..25ef683 100644
--- a/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java
+++ b/platform/usageView/src/com/intellij/usages/impl/UsageViewTreeCellRenderer.java
@@ -45,18 +45,22 @@
private static final EditorColorsScheme ourColorsScheme = UsageTreeColorsScheme.getInstance().getScheme();
private static final SimpleTextAttributes ourInvalidAttributes = SimpleTextAttributes.fromTextAttributes(ourColorsScheme.getAttributes(UsageTreeColors.INVALID_PREFIX));
private static final SimpleTextAttributes ourReadOnlyAttributes = SimpleTextAttributes.fromTextAttributes(ourColorsScheme.getAttributes(UsageTreeColors.READONLY_PREFIX));
+ private static final SimpleTextAttributes ourNumberOfUsagesAttribute = SimpleTextAttributes.fromTextAttributes(ourColorsScheme.getAttributes(UsageTreeColors.NUMBER_OF_USAGES));
private static final SimpleTextAttributes ourInvalidAttributesDarcula = new SimpleTextAttributes(null, DarculaColors.RED, null, ourInvalidAttributes.getStyle());
+ public static final Insets STANDARD_IPAD_NOWIFI = new Insets(1, 2, 1, 2);
+ private static final Rectangle EMPTY_RECTANGLE = new Rectangle();
+ private boolean myRowBoundsCalled = false;
- private final SimpleTextAttributes myNumberOfUsagesAttribute;
private final UsageViewPresentation myPresentation;
private final UsageView myView;
- UsageViewTreeCellRenderer(UsageView view) {
+ UsageViewTreeCellRenderer(@NotNull UsageView view) {
myView = view;
myPresentation = view.getPresentation();
- myNumberOfUsagesAttribute = SimpleTextAttributes.fromTextAttributes(ourColorsScheme.getAttributes(UsageTreeColors.NUMBER_OF_USAGES));
}
+ private Dimension cachedPreferredSize;
+
@Override
public void customizeCellRenderer(@Nullable JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) {
boolean showAsReadOnly = false;
@@ -74,6 +78,23 @@
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
Object userObject = treeNode.getUserObject();
+ Rectangle visibleRect = tree == null ? EMPTY_RECTANGLE : ((JViewport)tree.getParent()).getViewRect();
+ if (!visibleRect.isEmpty()) {
+ //Protection against SOE on some OSes and JDKs IDEA-120631
+ RowLocation visible = myRowBoundsCalled ? RowLocation.INSIDE_VISIBLE_RECT : isRowVisible(row, visibleRect);
+ myRowBoundsCalled = false;
+ if (visible != RowLocation.INSIDE_VISIBLE_RECT) {
+ // for the node outside visible rect just set its preferred size to the whole visible rect
+ // and do not compute (expensive) presentation
+ setIpad(new Insets(1,visibleRect.width, 1, 0));
+ return;
+ }
+ if (!getIpad().equals(STANDARD_IPAD_NOWIFI)) {
+ // for the visible node, return its ipad to the standard value
+ setIpad(STANDARD_IPAD_NOWIFI);
+ }
+ }
+
if (userObject instanceof UsageTarget) {
UsageTarget usageTarget = (UsageTarget)userObject;
if (!usageTarget.isValid()) {
@@ -87,7 +108,7 @@
append(UsageViewBundle.message("node.readonly") + " ", ourReadOnlyAttributes);
}
final String text = presentation.getPresentableText();
- append(text != null ? text : "", SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ append(text == null ? "" : text, SimpleTextAttributes.REGULAR_ATTRIBUTES);
setIcon(presentation.getIcon(expanded));
}
else if (treeNode instanceof GroupNode) {
@@ -104,7 +125,7 @@
int count = node.getRecursiveUsageCount();
append(" (" + StringUtil.pluralize(count + " " + myPresentation.getUsagesWord(), count) + ")",
- patchAttrs(node, myNumberOfUsagesAttribute));
+ patchAttrs(node, ourNumberOfUsagesAttribute));
}
else if (treeNode instanceof UsageNode) {
UsageNode node = (UsageNode)treeNode;
@@ -136,7 +157,106 @@
}
}
- private static SimpleTextAttributes patchAttrs(Node node, SimpleTextAttributes original) {
+ // computes the node text regardless of the node visibility
+ @NotNull
+ public String getPlainTextForNode(Object value) {
+ boolean showAsReadOnly = false;
+ StringBuilder result = new StringBuilder();
+ if (value instanceof Node) {
+ Node node = (Node)value;
+ if (!node.isValid()) {
+ result.append(UsageViewBundle.message("node.invalid") + " ");
+ }
+ if (myPresentation.isShowReadOnlyStatusAsRed() && node.isReadOnly()) {
+ showAsReadOnly = true;
+ }
+ }
+
+ if (value instanceof DefaultMutableTreeNode) {
+ DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
+ Object userObject = treeNode.getUserObject();
+
+ if (userObject instanceof UsageTarget) {
+ UsageTarget usageTarget = (UsageTarget)userObject;
+ if (usageTarget.isValid()) {
+ final ItemPresentation presentation = usageTarget.getPresentation();
+ LOG.assertTrue(presentation != null);
+ if (showAsReadOnly) {
+ result.append(UsageViewBundle.message("node.readonly") + " ");
+ }
+ final String text = presentation.getPresentableText();
+ result.append(text == null ? "" : text);
+ }
+ else {
+ result.append(UsageViewBundle.message("node.invalid"));
+ }
+ }
+ else if (treeNode instanceof GroupNode) {
+ GroupNode node = (GroupNode)treeNode;
+
+ if (node.isRoot()) {
+ result.append(StringUtil.capitalize(myPresentation.getUsagesWord()));
+ }
+ else {
+ result.append(node.getGroup().getText(myView));
+ }
+
+ int count = node.getRecursiveUsageCount();
+ result.append(" (" + StringUtil.pluralize(count + " " + myPresentation.getUsagesWord(), count) + ")");
+ }
+ else if (treeNode instanceof UsageNode) {
+ UsageNode node = (UsageNode)treeNode;
+
+ if (showAsReadOnly) {
+ result.append(UsageViewBundle.message("node.readonly") + " ");
+ }
+
+ if (node.isValid()) {
+ TextChunk[] text = node.getUsage().getPresentation().getText();
+ for (TextChunk textChunk : text) {
+ result.append(textChunk.getText());
+ }
+ }
+ }
+ else if (userObject instanceof String) {
+ result.append((String)userObject);
+ }
+ else {
+ result.append(userObject == null ? "" : userObject.toString());
+ }
+ }
+ else {
+ result.append(value);
+ }
+ return result.toString();
+ }
+
+ enum RowLocation {
+ BEFORE_VISIBLE_RECT, INSIDE_VISIBLE_RECT, AFTER_VISIBLE_RECT
+ }
+ @NotNull
+ public RowLocation isRowVisible(int row, @NotNull Rectangle visibleRect) {
+ Dimension pref;
+ if (cachedPreferredSize == null) {
+ pref = cachedPreferredSize = getPreferredSize();
+ }
+ else {
+ pref = cachedPreferredSize;
+ }
+ pref.width = Math.max(visibleRect.width, pref.width);
+ myRowBoundsCalled = true;
+ final Rectangle bounds = getTree().getRowBounds(row);
+ myRowBoundsCalled = false;
+ int y = bounds == null ? 0 : bounds.y;
+ TextRange vis = TextRange.from(Math.max(0, visibleRect.y - pref.height), visibleRect.height + pref.height * 2);
+ boolean inside = vis.contains(y);
+ if (inside) {
+ return RowLocation.INSIDE_VISIBLE_RECT;
+ }
+ return y < vis.getStartOffset() ? RowLocation.BEFORE_VISIBLE_RECT : RowLocation.AFTER_VISIBLE_RECT;
+ }
+
+ private static SimpleTextAttributes patchAttrs(@NotNull Node node, @NotNull SimpleTextAttributes original) {
if (node.isExcluded()) {
original = new SimpleTextAttributes(original.getStyle() | SimpleTextAttributes.STYLE_STRIKEOUT, original.getFgColor(), original.getWaveColor());
}
@@ -155,7 +275,7 @@
return original;
}
- public static String getTooltipText(final Object value) {
+ static String getTooltipFromPresentation(final Object value) {
if (value instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)value;
if (treeNode instanceof UsageNode) {
diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/DirectoryGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/DirectoryGroupingRule.java
index 38081a2..ebd9665 100644
--- a/platform/usageView/src/com/intellij/usages/impl/rules/DirectoryGroupingRule.java
+++ b/platform/usageView/src/com/intellij/usages/impl/rules/DirectoryGroupingRule.java
@@ -72,7 +72,7 @@
return null;
}
- protected UsageGroup getGroupForFile(VirtualFile dir) {
+ protected UsageGroup getGroupForFile(@NotNull VirtualFile dir) {
return new DirectoryGroup(dir);
}
@@ -87,7 +87,7 @@
public void update() {
}
- private DirectoryGroup(VirtualFile dir) {
+ private DirectoryGroup(@NotNull VirtualFile dir) {
myDir = dir;
}
@@ -99,13 +99,9 @@
@Override
@NotNull
public String getText(UsageView view) {
- String relativePath = VfsUtilCore.getRelativePath(myDir, myProject.getBaseDir(), File.separatorChar);
- if (relativePath != null) {
- return relativePath;
- }
- String url = myDir.getPresentableUrl();
-
- return url != null ? url : "<invalid>";
+ VirtualFile baseDir = myProject.getBaseDir();
+ String relativePath = baseDir == null ? null : VfsUtilCore.getRelativePath(myDir, baseDir, File.separatorChar);
+ return relativePath == null ? myDir.getPresentableUrl() : relativePath;
}
@Override
diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java
index c8b2932..6df4677 100644
--- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.java
+++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageType.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,7 +15,11 @@
*/
package com.intellij.usages.impl.rules;
+import com.intellij.BundleBase;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.usageView.UsageViewBundle;
+import com.intellij.usages.UsageViewPresentation;
+import org.jetbrains.annotations.NotNull;
public final class UsageType {
public static final UsageType CLASS_INSTANCE_OF = new UsageType(UsageViewBundle.message("usage.type.instanceof"));
@@ -43,6 +47,7 @@
public static final UsageType LITERAL_USAGE = new UsageType(UsageViewBundle.message("usage.type.string.constant"));
public static final UsageType COMMENT_USAGE = new UsageType(UsageViewBundle.message("usage.type.comment"));
+ @SuppressWarnings("UnresolvedPropertyKey")
public static final UsageType UNCLASSIFIED = new UsageType(UsageViewBundle.message("usage.type.unclassified"));
public static final UsageType RECURSION = new UsageType("Recursion");
@@ -53,10 +58,17 @@
private final String myName;
- public UsageType(String name) {
+ public UsageType(@NotNull String name) {
myName = name;
}
+ @NotNull
+ public String toString(@NotNull UsageViewPresentation presentation) {
+ String word = presentation.getUsagesWord();
+ String usageWord = StringUtil.startsWithChar(myName, '{') ? StringUtil.capitalize(word) : word;
+ return BundleBase.format(myName, usageWord);
+ }
+
public String toString() {
return myName;
}
diff --git a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
index b741a22..b182bc3 100644
--- a/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.java
+++ b/platform/usageView/src/com/intellij/usages/impl/rules/UsageTypeGroupingRule.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.
@@ -81,7 +81,7 @@
return null;
}
- private class UsageTypeGroup implements UsageGroup {
+ private static class UsageTypeGroup implements UsageGroup {
private final UsageType myUsageType;
private UsageTypeGroup(@NotNull UsageType usageType) {
@@ -99,8 +99,8 @@
@Override
@NotNull
- public String getText(UsageView view) {
- return myUsageType.toString();
+ public String getText(@Nullable UsageView view) {
+ return view == null ? myUsageType.toString() : myUsageType.toString(view.getPresentation());
}
@Override
@@ -129,12 +129,11 @@
if (this == o) return true;
if (!(o instanceof UsageTypeGroup)) return false;
final UsageTypeGroup usageTypeGroup = (UsageTypeGroup)o;
- if (myUsageType != null ? !myUsageType.equals(usageTypeGroup.myUsageType) : usageTypeGroup.myUsageType != null) return false;
- return true;
+ return myUsageType.equals(usageTypeGroup.myUsageType);
}
public int hashCode() {
- return myUsageType != null ? myUsageType.hashCode() : 0;
+ return myUsageType.hashCode();
}
}
}
diff --git a/platform/util-rt/src/com/intellij/BundleBase.java b/platform/util-rt/src/com/intellij/BundleBase.java
index 6cc40fd..687d101 100644
--- a/platform/util-rt/src/com/intellij/BundleBase.java
+++ b/platform/util-rt/src/com/intellij/BundleBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -32,9 +32,9 @@
public static boolean assertKeyIsFound = false;
public static String messageOrDefault(@Nullable final ResourceBundle bundle,
- final String key,
+ @NotNull String key,
@Nullable final String defaultValue,
- final Object... params) {
+ @NotNull Object... params) {
if (bundle == null) return defaultValue;
String value;
diff --git a/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java b/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java
index dd8ef83..83ff9c3 100644
--- a/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java
+++ b/platform/util-rt/src/com/intellij/execution/rmi/RemoteServer.java
@@ -15,6 +15,7 @@
*/
package com.intellij.execution.rmi;
+import com.intellij.execution.rmi.ssl.SslSocketFactory;
import org.jetbrains.annotations.Nullable;
import javax.naming.Context;
@@ -28,6 +29,7 @@
import java.rmi.registry.Registry;
import java.rmi.server.ExportException;
import java.rmi.server.UnicastRemoteObject;
+import java.security.Security;
import java.util.Hashtable;
import java.util.Random;
@@ -43,6 +45,7 @@
protected static void start(Remote remote) throws Exception {
setupRMI();
banJNDI();
+ setupSSL();
if (ourRemote != null) throw new AssertionError("Already started");
ourRemote = remote;
@@ -101,6 +104,12 @@
}
}
+ public static void setupSSL() {
+ if (System.getProperty(SslSocketFactory.SSL_CA_CERT_PATH) != null) {
+ Security.setProperty("ssl.SocketFactory.provider", "com.intellij.execution.rmi.ssl.SslSocketFactory");
+ }
+ }
+
@SuppressWarnings("UnusedDeclaration")
public static class Jndi implements InitialContextFactory, InvocationHandler {
@Override
diff --git a/platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java b/platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java
new file mode 100644
index 0000000..6bdbcab
--- /dev/null
+++ b/platform/util-rt/src/com/intellij/execution/rmi/ssl/SslSocketFactory.java
@@ -0,0 +1,102 @@
+package com.intellij.execution.rmi.ssl;
+
+import javax.net.ssl.*;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.UUID;
+
+public class SslSocketFactory extends SSLSocketFactory {
+ public static final String SSL_CA_CERT_PATH = "sslCaCertPath";
+ private SSLSocketFactory myFactory;
+
+ public SslSocketFactory() throws GeneralSecurityException, IOException {
+ super();
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ TrustManager tm;
+ try {
+ tm = new MyX509TrustManager();
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+
+ ctx.init(new KeyManager[]{}, new TrustManager[]{tm}, null);
+ myFactory = ctx.getSocketFactory();
+ }
+
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ return myFactory.createSocket(host, port);
+ }
+
+ public Socket createSocket(String host, int port) throws IOException {
+ return myFactory.createSocket(host, port);
+ }
+
+ public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
+ return myFactory.createSocket(host, port, localHost, localPort);
+ }
+
+ public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
+ return myFactory.createSocket(address, port, localAddress, localPort);
+ }
+
+ public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {
+ return myFactory.createSocket(socket, host, port, autoClose);
+ }
+
+ public String[] getDefaultCipherSuites() {
+ return myFactory.getDefaultCipherSuites();
+ }
+
+ public String[] getSupportedCipherSuites() {
+ return myFactory.getSupportedCipherSuites();
+ }
+
+ private static class MyX509TrustManager implements X509TrustManager {
+ String serverCertFile;
+ X509TrustManager trustManager;
+
+ public MyX509TrustManager() throws Exception {
+ serverCertFile = System.getProperty(SSL_CA_CERT_PATH);
+ InputStream inStream = new FileInputStream(serverCertFile);
+
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate ca = (X509Certificate)cf.generateCertificate(inStream);
+ inStream.close();
+ KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
+ ks.load(null);
+ ks.setCertificateEntry(UUID.randomUUID().toString(), ca);
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ tmf.init(ks);
+ for (TrustManager tm : tmf.getTrustManagers()) {
+ if (tm instanceof X509TrustManager) {
+ trustManager = (X509TrustManager)tm;
+ break;
+ }
+ }
+ if (trustManager == null) {
+ throw new RuntimeException("No X509TrustManager found");
+ }
+ }
+
+ public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ }
+
+ public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ if (trustManager == null) throw new RuntimeException("No X509TrustManager found");
+ trustManager.checkServerTrusted(x509Certificates, s);
+ }
+
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ }
+}
diff --git a/platform/util-rt/src/com/intellij/openapi/util/Bitness.java b/platform/util-rt/src/com/intellij/openapi/util/Bitness.java
new file mode 100644
index 0000000..625679b
--- /dev/null
+++ b/platform/util-rt/src/com/intellij/openapi/util/Bitness.java
@@ -0,0 +1,21 @@
+/*
+ * 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.openapi.util;
+
+/**
+* @author egor
+*/
+public enum Bitness {x32, x64}
diff --git a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java b/platform/util-rt/src/com/intellij/openapi/util/Conditions.java
index 48bb91a..e591f22 100644
--- a/platform/util-rt/src/com/intellij/openapi/util/Conditions.java
+++ b/platform/util-rt/src/com/intellij/openapi/util/Conditions.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.
diff --git a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java
index d63c9bc..2b6b8de 100644
--- a/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java
+++ b/platform/util-rt/src/com/intellij/openapi/util/io/FileUtilRt.java
@@ -25,6 +25,8 @@
import java.io.*;
import java.nio.channels.FileChannel;
+import java.util.ArrayList;
+import java.util.List;
import java.util.UUID;
/**
@@ -83,18 +85,18 @@
}
@NotNull
- public static String toSystemDependentName(@NonNls @NotNull String aFileName) {
- return toSystemDependentName(aFileName, File.separatorChar);
+ public static String toSystemDependentName(@NonNls @NotNull String fileName) {
+ return toSystemDependentName(fileName, File.separatorChar);
}
@NotNull
- public static String toSystemDependentName(@NonNls @NotNull String aFileName, final char separatorChar) {
- return aFileName.replace('/', separatorChar).replace('\\', separatorChar);
+ public static String toSystemDependentName(@NonNls @NotNull String fileName, final char separatorChar) {
+ return fileName.replace('/', separatorChar).replace('\\', separatorChar);
}
@NotNull
- public static String toSystemIndependentName(@NonNls @NotNull String aFileName) {
- return aFileName.replace('\\', '/');
+ public static String toSystemIndependentName(@NonNls @NotNull String fileName) {
+ return fileName.replace('\\', '/');
}
@Nullable
@@ -382,6 +384,50 @@
}
@NotNull
+ public static List<String> loadLines(@NotNull File file) throws IOException {
+ return loadLines(file.getPath());
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull File file, @Nullable @NonNls String encoding) throws IOException {
+ return loadLines(file.getPath(), encoding);
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull String path) throws IOException {
+ return loadLines(path, null);
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull String path, @Nullable @NonNls String encoding) throws IOException {
+ InputStream stream = new FileInputStream(path);
+ try {
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ InputStreamReader in = encoding == null ? new InputStreamReader(stream) : new InputStreamReader(stream, encoding);
+ BufferedReader reader = new BufferedReader(in);
+ try {
+ return loadLines(reader);
+ }
+ finally {
+ reader.close();
+ }
+ }
+ finally {
+ stream.close();
+ }
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull BufferedReader reader) throws IOException {
+ List<String> lines = new ArrayList<String>();
+ String line;
+ while ((line = reader.readLine()) != null) {
+ lines.add(line);
+ }
+ return lines;
+ }
+
+ @NotNull
public static byte[] loadBytes(@NotNull InputStream stream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
final byte[] bytes = BUFFER.get();
diff --git a/platform/util-rt/src/com/intellij/reference/SoftLazyValue.java b/platform/util-rt/src/com/intellij/reference/SoftLazyValue.java
index 379ab3c..1f301ec 100644
--- a/platform/util-rt/src/com/intellij/reference/SoftLazyValue.java
+++ b/platform/util-rt/src/com/intellij/reference/SoftLazyValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -27,8 +27,8 @@
private SoftReference<T> myReference;
public T getValue() {
- T t;
- if (myReference == null || (t = myReference.get()) == null) {
+ T t = com.intellij.reference.SoftReference.dereference(myReference);
+ if (t == null) {
t = compute();
myReference = new SoftReference<T>(t);
}
diff --git a/platform/util-rt/src/com/intellij/util/NullableConsumer.java b/platform/util-rt/src/com/intellij/util/NullableConsumer.java
index 6706d69..6d28de8 100644
--- a/platform/util-rt/src/com/intellij/util/NullableConsumer.java
+++ b/platform/util-rt/src/com/intellij/util/NullableConsumer.java
@@ -21,5 +21,6 @@
* @author nik
*/
public interface NullableConsumer<T> extends Consumer<T> {
+ @Override
void consume(@Nullable T t);
}
diff --git a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
index 2304be0..e4b3153 100644
--- a/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.java
+++ b/platform/util-rt/src/com/intellij/util/containers/ContainerUtilRt.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.
@@ -62,7 +62,8 @@
return map;
}
- public static <K, V> Map<K,V> newHashMap(Pair<K, V> first, Pair<K, V>[] entries) {
+ @NotNull
+ public static <K, V> Map<K,V> newHashMap(@NotNull Pair<K, V> first, Pair<K, V>[] entries) {
Map<K, V> map = newHashMap();
map.put(first.getFirst(), first.getSecond());
for (Pair<K, V> entry : entries) {
@@ -92,6 +93,16 @@
}
@NotNull
+ public static <K, V> LinkedHashMap<K,V> newLinkedHashMap(@NotNull Pair<K, V> first, Pair<K, V>[] entries) {
+ LinkedHashMap<K, V> map = newLinkedHashMap();
+ map.put(first.getFirst(), first.getSecond());
+ for (Pair<K, V> entry : entries) {
+ map.put(entry.getFirst(), entry.getSecond());
+ }
+ return map;
+ }
+
+ @NotNull
public static <T> LinkedList<T> newLinkedList() {
return new LinkedList<T>();
}
@@ -129,18 +140,14 @@
return copy(ContainerUtilRt.<T>newArrayList(), elements);
}
- @NotNull
+ /** @deprecated Use {@link #newArrayListWithCapacity(int)} (to remove in IDEA 15) */
public static <T> ArrayList<T> newArrayListWithExpectedSize(int size) {
- return new ArrayList<T>(size);
+ return newArrayListWithCapacity(size);
}
@NotNull
public static <T> ArrayList<T> newArrayListWithCapacity(int size) {
- return new ArrayList<T>(computeArrayListCapacity(size));
- }
-
- private static int computeArrayListCapacity(int size) {
- return 5 + size + size / 5;
+ return new ArrayList<T>(size);
}
@NotNull
@@ -157,6 +164,11 @@
}
@NotNull
+ public static <T> HashSet<T> newHashSet(int initialCapacity) {
+ return new com.intellij.util.containers.HashSet<T>(initialCapacity);
+ }
+
+ @NotNull
public static <T> HashSet<T> newHashSet(@NotNull T... elements) {
return new com.intellij.util.containers.HashSet<T>(Arrays.asList(elements));
}
diff --git a/platform/util-rt/src/com/intellij/util/containers/Stack.java b/platform/util-rt/src/com/intellij/util/containers/Stack.java
index 7df0c93..29337c9 100644
--- a/platform/util-rt/src/com/intellij/util/containers/Stack.java
+++ b/platform/util-rt/src/com/intellij/util/containers/Stack.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.
diff --git a/platform/util-rt/src/com/intellij/util/text/DateFormatUtilRt.java b/platform/util-rt/src/com/intellij/util/text/DateFormatUtilRt.java
index c7fbdd9..43462ae 100644
--- a/platform/util-rt/src/com/intellij/util/text/DateFormatUtilRt.java
+++ b/platform/util-rt/src/com/intellij/util/text/DateFormatUtilRt.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -21,6 +21,8 @@
import java.util.Calendar;
import java.util.Locale;
+@SuppressWarnings("UnusedDeclaration")
+/** @deprecated to remove in IDEA 14 */
public class DateFormatUtilRt {
private static final SimpleDateFormat BUILD_DATE_FORMAT = new SimpleDateFormat("dd MMM yyyy HH:ss", Locale.US);
diff --git a/platform/util/src/com/intellij/AbstractBundle.java b/platform/util/src/com/intellij/AbstractBundle.java
index 52ef3ef..70502e8 100644
--- a/platform/util/src/com/intellij/AbstractBundle.java
+++ b/platform/util/src/com/intellij/AbstractBundle.java
@@ -55,13 +55,12 @@
myPathToBundle = pathToBundle;
}
- public String getMessage(@NotNull String key, Object... params) {
+ public String getMessage(@NotNull String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
private ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (myBundle != null) bundle = myBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(myBundle);
if (bundle == null) {
bundle = getResourceBundle(myPathToBundle, getClass().getClassLoader());
myBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/util/src/com/intellij/CommonBundle.java b/platform/util/src/com/intellij/CommonBundle.java
index fdcdb06..25d0711 100644
--- a/platform/util/src/com/intellij/CommonBundle.java
+++ b/platform/util/src/com/intellij/CommonBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -31,20 +31,20 @@
*/
@SuppressWarnings("MethodOverridesStaticMethodOfSuperclass")
public class CommonBundle extends BundleBase {
- @NonNls private static final String BUNDLE = "messages.CommonBundle";
- private static Reference<ResourceBundle> ourBundle;
- private CommonBundle() {}
-
- @NotNull
public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return message(getCommonBundle(), key, params);
}
+ @NonNls private static final String BUNDLE = "messages.CommonBundle";
+ private static Reference<ResourceBundle> ourBundle;
+
+ private CommonBundle() {
+ }
+
@NotNull
private static ResourceBundle getCommonBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
@@ -53,9 +53,9 @@
}
public static String messageOrDefault(@Nullable final ResourceBundle bundle,
- final String key,
+ @NotNull String key,
@Nullable final String defaultValue,
- final Object... params) {
+ @NotNull Object... params) {
return BundleBase.messageOrDefault(bundle, key, defaultValue, params);
}
@@ -89,23 +89,22 @@
return message("tree.node.loading");
}
- public static String getOkButtonText(){
+ public static String getOkButtonText() {
return message("button.ok");
}
- public static String getYesButtonText(){
+ public static String getYesButtonText() {
return message("button.yes");
}
- public static String getNoButtonText(){
+ public static String getNoButtonText() {
return message("button.no");
}
- public static String getContinueButtonText(){
+ public static String getContinueButtonText() {
return message("button.continue");
}
-
public static String getYesForAllButtonText() {
return message("button.yes.for.all");
}
diff --git a/platform/util/src/com/intellij/Patches.java b/platform/util/src/com/intellij/Patches.java
index 055a673..40c5176 100644
--- a/platform/util/src/com/intellij/Patches.java
+++ b/platform/util/src/com/intellij/Patches.java
@@ -113,9 +113,9 @@
/**
* Java 7 incorrectly calculates screen insets on multi-monitor X Window configurations.
- * See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=9000030.
+ * See http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7172665.
*/
- public static final boolean SUN_BUG_ID_9000030 = SystemInfo.isXWindow && SystemInfo.isJavaVersionAtLeast("1.7");
+ public static final boolean SUN_BUG_ID_7172665 = SystemInfo.isXWindow && SystemInfo.isJavaVersionAtLeast("1.7");
/**
* On some WMs modal dialogs may show behind full screen window.
diff --git a/platform/util/src/com/intellij/execution/CommandLineUtil.java b/platform/util/src/com/intellij/execution/CommandLineUtil.java
index a47d649..107131d 100644
--- a/platform/util/src/com/intellij/execution/CommandLineUtil.java
+++ b/platform/util/src/com/intellij/execution/CommandLineUtil.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.
@@ -45,7 +45,7 @@
// please keep an implementation in sync with [junit-rt] ProcessBuilder.createProcess()
@NotNull
public static List<String> toCommandLine(@NotNull String command, @NotNull List<String> parameters, @NotNull Platform platform) {
- List<String> commandLine = ContainerUtil.newArrayListWithExpectedSize(parameters.size() + 1);
+ List<String> commandLine = ContainerUtil.newArrayListWithCapacity(parameters.size() + 1);
commandLine.add(FileUtilRt.toSystemDependentName(command, platform.fileSeparator));
diff --git a/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java b/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java
index a2e103b..a62af9a 100644
--- a/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.java
+++ b/platform/util/src/com/intellij/execution/configurations/CommandLineTokenizer.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.
@@ -26,7 +26,7 @@
*/
public class CommandLineTokenizer extends StringTokenizer {
- private static String DEFAULT_DELIMITERS = " \t\n\r\f";
+ private static final String DEFAULT_DELIMITERS = " \t\n\r\f";
// keep source level 1.4
private List myTokens = new ArrayList();
private int myCurrentToken = 0;
diff --git a/platform/util/src/com/intellij/execution/process/WinProcessManager.java b/platform/util/src/com/intellij/execution/process/WinProcessManager.java
new file mode 100644
index 0000000..d2df82e
--- /dev/null
+++ b/platform/util/src/com/intellij/execution/process/WinProcessManager.java
@@ -0,0 +1,55 @@
+/*
+ * 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.execution.process;
+
+import com.sun.jna.Pointer;
+import com.sun.jna.platform.win32.Kernel32;
+import com.sun.jna.platform.win32.WinNT;
+
+import java.lang.reflect.Field;
+
+/**
+ * @author Alexey.Ushakov
+ */
+public class WinProcessManager {
+
+ private WinProcessManager() {}
+
+ /**
+ * Returns {@code pid} for Windows process
+ * @param process Windows process
+ * @return pid of the {@code process}
+ */
+ public static int getProcessPid(Process process) {
+ if (process.getClass().getName().equals("java.lang.Win32Process") ||
+ process.getClass().getName().equals("java.lang.ProcessImpl")) {
+ try {
+ Field f = process.getClass().getDeclaredField("handle");
+ f.setAccessible(true);
+ long handle = f.getLong(process);
+
+ Kernel32 kernel = Kernel32.INSTANCE;
+ WinNT.HANDLE winHandle = new WinNT.HANDLE();
+ winHandle.setPointer(Pointer.createConstant(handle));
+ return kernel.GetProcessId(winHandle);
+ } catch (Throwable e) {
+ throw new IllegalStateException(e);
+ }
+ } else {
+ throw new IllegalStateException("Unknown Process implementation");
+ }
+ }
+}
diff --git a/platform/util/src/com/intellij/icons/AllIcons.java b/platform/util/src/com/intellij/icons/AllIcons.java
index 35f60df..0c24d8b 100644
--- a/platform/util/src/com/intellij/icons/AllIcons.java
+++ b/platform/util/src/com/intellij/icons/AllIcons.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.
@@ -361,6 +361,7 @@
public static final Icon ComboArrowLeftPassive = IconLoader.getIcon("/general/comboArrowLeftPassive.png"); // 5x9
public static final Icon ComboArrowRight = IconLoader.getIcon("/general/comboArrowRight.png"); // 5x9
public static final Icon ComboArrowRightPassive = IconLoader.getIcon("/general/comboArrowRightPassive.png"); // 5x9
+ public static final Icon ComboBoxButtonArrow = IconLoader.getIcon("/general/comboBoxButtonArrow.png"); // 16x16
public static final Icon ComboUpPassive = IconLoader.getIcon("/general/comboUpPassive.png"); // 16x16
public static final Icon ConfigurableDefault = IconLoader.getIcon("/general/configurableDefault.png"); // 32x32
public static final Icon Configure = IconLoader.getIcon("/general/Configure.png"); // 32x32
@@ -369,6 +370,7 @@
public static final Icon Debug = IconLoader.getIcon("/general/debug.png"); // 16x16
public static final Icon DefaultKeymap = IconLoader.getIcon("/general/defaultKeymap.png"); // 32x32
public static final Icon Divider = IconLoader.getIcon("/general/divider.png"); // 2x19
+ public static final Icon DownloadPlugin = IconLoader.getIcon("/general/downloadPlugin.png"); // 16x16
public static final Icon Dropdown = IconLoader.getIcon("/general/dropdown.png"); // 16x16
public static final Icon EditColors = IconLoader.getIcon("/general/editColors.png"); // 16x16
public static final Icon EditItemInSection = IconLoader.getIcon("/general/editItemInSection.png"); // 16x16
@@ -479,6 +481,7 @@
public static final Icon TodoDefault = IconLoader.getIcon("/general/todoDefault.png"); // 12x12
public static final Icon TodoImportant = IconLoader.getIcon("/general/todoImportant.png"); // 12x12
public static final Icon TodoQuestion = IconLoader.getIcon("/general/todoQuestion.png"); // 12x12
+ public static final Icon UninstallPlugin = IconLoader.getIcon("/general/uninstallPlugin.png"); // 16x16
public static final Icon Warning = IconLoader.getIcon("/general/warning.png"); // 16x16
public static final Icon WarningDecorator = IconLoader.getIcon("/general/warningDecorator.png"); // 16x16
public static final Icon WarningDialog = IconLoader.getIcon("/general/warningDialog.png"); // 32x32
@@ -682,6 +685,7 @@
public static class Modules {
public static final Icon AddContentEntry = IconLoader.getIcon("/modules/addContentEntry.png"); // 16x16
+ public static final Icon AddExcludedRoot = IconLoader.getIcon("/modules/addExcludedRoot.png"); // 16x16
public static final Icon Annotation = IconLoader.getIcon("/modules/annotation.png"); // 16x16
public static final Icon DeleteContentFolder = IconLoader.getIcon("/modules/deleteContentFolder.png"); // 9x9
public static final Icon DeleteContentFolderRollover = IconLoader.getIcon("/modules/deleteContentFolderRollover.png"); // 9x9
@@ -712,6 +716,7 @@
public static final Icon JavaeeAppModule = IconLoader.getIcon("/modules/types/JavaeeAppModule.png"); // 24x24
public static final Icon JavaModule = IconLoader.getIcon("/modules/types/javaModule.png"); // 24x24
public static final Icon PluginModule = IconLoader.getIcon("/modules/types/pluginModule.png"); // 24x24
+ public static final Icon UserDefined = IconLoader.getIcon("/modules/types/userDefined.png"); // 24x24
public static final Icon WebModule = IconLoader.getIcon("/modules/types/webModule.png"); // 24x24
}
@@ -1125,11 +1130,14 @@
public static class Xml {
public static class Browsers {
+ public static final Icon Canary16 = IconLoader.getIcon("/xml/browsers/canary16.png"); // 16x16
public static final Icon Chrome16 = IconLoader.getIcon("/xml/browsers/chrome16.png"); // 16x16
+ public static final Icon Chromium16 = IconLoader.getIcon("/xml/browsers/chromium16.png"); // 16x16
public static final Icon Explorer16 = IconLoader.getIcon("/xml/browsers/explorer16.png"); // 16x16
public static final Icon Firefox16 = IconLoader.getIcon("/xml/browsers/firefox16.png"); // 16x16
public static final Icon Opera16 = IconLoader.getIcon("/xml/browsers/opera16.png"); // 16x16
public static final Icon Safari16 = IconLoader.getIcon("/xml/browsers/safari16.png"); // 16x16
+ public static final Icon Yandex16 = IconLoader.getIcon("/xml/browsers/yandex16.png"); // 16x16
}
public static final Icon Css_class = IconLoader.getIcon("/xml/css_class.png"); // 16x16
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/FrequentEventDetector.java b/platform/util/src/com/intellij/openapi/diagnostic/FrequentEventDetector.java
index 42ae6a3..7f28c8f 100644
--- a/platform/util/src/com/intellij/openapi/diagnostic/FrequentEventDetector.java
+++ b/platform/util/src/com/intellij/openapi/diagnostic/FrequentEventDetector.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,6 +16,7 @@
package com.intellij.openapi.diagnostic;
import com.intellij.util.ExceptionUtil;
+import org.jetbrains.annotations.NotNull;
import java.util.concurrent.atomic.AtomicInteger;
@@ -24,32 +25,50 @@
*/
public class FrequentEventDetector {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.diagnostic.FrequentEventDetector");
+
+ public enum Level {INFO, WARN, ERROR}
+
private long myStartedCounting = System.currentTimeMillis();
private final AtomicInteger myEventsPosted = new AtomicInteger();
private final int myEventCountThreshold;
private final int myTimeSpanMs;
+ private final Level myLevel;
public FrequentEventDetector(int eventCountThreshold, int timeSpanMs) {
+ this(eventCountThreshold, timeSpanMs, Level.INFO);
+ }
+
+ public FrequentEventDetector(int eventCountThreshold, int timeSpanMs, @NotNull Level level) {
myEventCountThreshold = eventCountThreshold;
myTimeSpanMs = timeSpanMs;
+ myLevel = level;
}
public void eventHappened() {
if (myEventsPosted.incrementAndGet() > myEventCountThreshold) {
+ boolean shouldLog = false;
+
synchronized (myEventsPosted) {
- boolean shouldLog = false;
if (myEventsPosted.get() > myEventCountThreshold) {
long timeNow = System.currentTimeMillis();
shouldLog = timeNow - myStartedCounting < myTimeSpanMs;
myEventsPosted.set(0);
myStartedCounting = timeNow;
}
- if (shouldLog) {
- LOG.info("Too many events posted\n" + ExceptionUtil.getThrowableText(new Throwable()));
+ }
+
+ if (shouldLog) {
+ String message = "Too many events posted\n" + ExceptionUtil.getThrowableText(new Throwable());
+ if (myLevel == Level.INFO) {
+ LOG.info(message);
+ }
+ else if (myLevel == Level.WARN) {
+ LOG.warn(message);
+ }
+ else {
+ LOG.error(message);
}
}
}
-
}
-
}
diff --git a/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java b/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java
index a462210..55441ae 100644
--- a/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.java
+++ b/platform/util/src/com/intellij/openapi/diagnostic/LogUtil.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,9 +15,15 @@
*/
package com.intellij.openapi.diagnostic;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.ExceptionUtil;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.IOException;
+
public class LogUtil {
private LogUtil() { }
@@ -28,9 +34,22 @@
/**
* Format string syntax as in {@linkplain String#format(String, Object...)}.
*/
- public static void debug(@NotNull Logger logger, @NotNull String format, @Nullable Object... args) {
+ public static void debug(@NotNull Logger logger, @NonNls @NotNull String format, @Nullable Object... args) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(format, args));
}
}
+
+ public static String getProcessList() {
+ try {
+ @SuppressWarnings("SpellCheckingInspection") Process process = new ProcessBuilder()
+ .command(SystemInfo.isWindows ? new String[]{System.getenv("windir") + "\\system32\\tasklist.exe", "/v"} : new String[]{"ps", "a"})
+ .redirectErrorStream(true)
+ .start();
+ return FileUtil.loadTextAndClose(process.getInputStream());
+ }
+ catch (IOException e) {
+ return ExceptionUtil.getThrowableText(e);
+ }
+ }
}
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 e84e98c..0767413 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/ComparisonPolicy.java
@@ -201,18 +201,13 @@
}
private Object getWrapper(String line) {
- line = line.trim();
- char[] chars = new char[line.length()];
- line.getChars(0, line.length(), chars, 0);
- char[] result = new char[chars.length];
- int resultLength = 0;
- for (int i = 0; i < chars.length; i++) {
- char aChar = chars[i];
- if (Character.isWhitespace(aChar)) continue;
- result[resultLength] = aChar;
- resultLength++;
+ 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 new String(result, 0, resultLength);
+ return builder.toString();
}
@Override
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 e333aca..3b6a00b 100644
--- a/platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java
+++ b/platform/util/src/com/intellij/openapi/diff/impl/DiffFragmentBuilder.java
@@ -156,7 +156,9 @@
}
private static String concatenate(String[] strings, int start, int end) {
- StringBuffer buffer = new StringBuffer();
+ 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();
}
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 0d6e1f7..83cfa98 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
@@ -232,23 +232,33 @@
}
public static DiffFragment concatenate(DiffFragment[] line, int from, int to) {
- StringBuffer buffer1 = new StringBuffer();
- StringBuffer buffer2 = new StringBuffer();
+ String[] data1 = new String[to - from];
+ String[] data2 = new String[to - from];
+
+ int len1 = 0;
+ int len2 = 0;
boolean isEqual = true;
- for (int j = from; j < to; j++) {
- DiffFragment fragment = line[j];
- isEqual &= fragment.isEqual();
- String text1 = fragment.getText1();
- String text2 = fragment.getText2();
- if (text1 != null) buffer1.append(text1);
- if (text2 != null) buffer2.append(text2);
+ 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();
}
+
+ 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);
return isEqual ? DiffFragment.unchanged(text1, text2) : new DiffFragment(text1, text2);
}
- private static String notEmptyContent(StringBuffer buffer) {
+ private static String notEmptyContent(StringBuilder buffer) {
return buffer.length() > 0 ? buffer.toString() : null;
}
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 7a7515a..21740dc 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
@@ -199,8 +199,8 @@
int lastIndex = myFragments.size() - 1;
DiffFragment prevFragment = myFragments.get(lastIndex);
if (prevFragment.isEqual()) {
- prevFragment.appendText1(fragment.getText1());
- prevFragment.appendText2(fragment.getText2());
+ prevFragment.appendText1(text1);
+ prevFragment.appendText2(text2);
return;
}
}
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/DummyDiffFragmentsProcessor.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/DummyDiffFragmentsProcessor.java
new file mode 100644
index 0000000..10753bb
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/DummyDiffFragmentsProcessor.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.processing;
+
+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 java.util.ArrayList;
+
+public class DummyDiffFragmentsProcessor {
+ public ArrayList<LineFragment> process(String text1, String text2) {
+ ArrayList<LineFragment> lineFragments = new ArrayList<LineFragment>();
+
+ TextDiffTypeEnum type;
+ if (text1.isEmpty() && text2.isEmpty()) {
+ type = TextDiffTypeEnum.NONE;
+ }
+ else if (text1.isEmpty()) {
+ type = TextDiffTypeEnum.INSERT;
+ }
+ else if (text2.isEmpty()) {
+ type = TextDiffTypeEnum.DELETED;
+ }
+ else {
+ type = TextDiffTypeEnum.CHANGED;
+ }
+ lineFragments.add(new LineFragment(0, countLines(text1), 0, countLines(text2), type, new TextRange(0, text1.length()),
+ new TextRange(0, text2.length())));
+
+ return lineFragments;
+ }
+
+ private static int countLines(String text) {
+ if (text == null || text.isEmpty()) return 0;
+ int count = StringUtil.countNewLines(text);
+ if (text.charAt(text.length() - 1) != '\n') count++;
+ return count;
+ }
+
+}
diff --git a/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java b/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java
new file mode 100644
index 0000000..441aca3
--- /dev/null
+++ b/platform/util/src/com/intellij/openapi/diff/impl/processing/HighlightMode.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.processing;
+
+public enum HighlightMode {
+ BY_WORD, BY_LINE, NO_HIGHLIGHTING
+}
diff --git a/platform/util/src/com/intellij/openapi/ui/Splitter.java b/platform/util/src/com/intellij/openapi/ui/Splitter.java
index cb0dfb8..44d2317 100644
--- a/platform/util/src/com/intellij/openapi/ui/Splitter.java
+++ b/platform/util/src/com/intellij/openapi/ui/Splitter.java
@@ -22,6 +22,7 @@
import com.intellij.ui.ClickListener;
import com.intellij.ui.UIBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -523,7 +524,7 @@
.message("splitter.right.tooltip.text"));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
setProportion(1.0f - getMinProportion(mySecondComponent));
return true;
}
@@ -541,7 +542,7 @@
splitCenterlabel.setToolTipText(UIBundle.message("splitter.center.tooltip.text"));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
setProportion(.5f);
return true;
}
@@ -559,7 +560,7 @@
.message("splitter.left.tooltip.text"));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
setProportion(getMinProportion(myFirstComponent));
return true;
}
diff --git a/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java b/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java
index 5232033..182fda8 100644
--- a/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.java
+++ b/platform/util/src/com/intellij/openapi/util/DefaultJDOMExternalizer.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,7 +16,7 @@
package com.intellij.openapi.util;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jdom.Element;
import org.jdom.Verifier;
import org.jetbrains.annotations.NotNull;
@@ -100,7 +100,7 @@
value = Integer.toString(color.getRGB() & 0xFFFFFF, 16);
}
}
- else if (ReflectionCache.isAssignable(JDOMExternalizable.class, type)) {
+ else if (ReflectionUtil.isAssignable(JDOMExternalizable.class, type)) {
Element element = new Element("option");
parentNode.addContent(element);
element.setAttribute("name", field.getName());
@@ -173,7 +173,7 @@
if ((modifiers & Modifier.FINAL) != 0) {
// read external contents of final field
Object value = field.get(data);
- if (ReflectionCache.isInstance(value, JDOMExternalizable.class)) {
+ if (JDOMExternalizable.class.isInstance(value)) {
final List children = e.getChildren("value");
for (Object child : children) {
Element valueTag = (Element)child;
@@ -202,12 +202,8 @@
}
}
else if (type.equals(int.class)) {
- try {
- field.setInt(data, Integer.parseInt(value));
- }
- catch (NumberFormatException ex) {
- throw new InvalidDataException();
- }
+ int i = toInt(value);
+ field.setInt(data, i);
}
else if (type.equals(long.class)) {
try {
@@ -259,21 +255,10 @@
field.set(data, value);
}
else if (type.equals(Color.class)) {
- if (value != null) {
- try {
- int rgb = Integer.parseInt(value, 16);
- field.set(data, new Color(rgb));
- }
- catch (NumberFormatException ex) {
- LOG.debug("Wrong color value: " + value, ex);
- throw new InvalidDataException();
- }
- }
- else {
- field.set(data, null);
- }
+ Color color = toColor(value);
+ field.set(data, color);
}
- else if (ReflectionCache.isAssignable(JDOMExternalizable.class, type)) {
+ else if (ReflectionUtil.isAssignable(JDOMExternalizable.class, type)) {
final List children = e.getChildren("value");
if (!children.isEmpty()) {
// compatibility with Selena's serialization which writes an empty tag for a bean which has a default value
@@ -305,4 +290,33 @@
}
}
}
+
+ public static int toInt(@NotNull String value) throws InvalidDataException {
+ int i;
+ try {
+ i = Integer.parseInt(value);
+ }
+ catch (NumberFormatException ex) {
+ throw new InvalidDataException(value, ex);
+ }
+ return i;
+ }
+
+ public static Color toColor(@Nullable String value) throws InvalidDataException {
+ Color color;
+ if (value == null) {
+ color = null;
+ }
+ else {
+ try {
+ int rgb = Integer.parseInt(value, 16);
+ color = new Color(rgb);
+ }
+ catch (NumberFormatException ex) {
+ LOG.debug("Wrong color value: " + value, ex);
+ throw new InvalidDataException("Wrong color value: " + value, ex);
+ }
+ }
+ return color;
+ }
}
diff --git a/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java
index 7f56aaa..c9bf217 100644
--- a/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,19 +15,14 @@
*/
package com.intellij.openapi.util;
-import com.intellij.openapi.diagnostic.Logger;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.List;
-
@SuppressWarnings({"HardCodedStringLiteral"})
public class JDOMExternalizerUtil {
- private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.JDOMExternalizerUtil");
-
- public static void writeField(Element root, @NonNls String fieldName, String value) {
+ public static void writeField(@NotNull Element root, @NotNull @NonNls String fieldName, String value) {
Element element = new Element("option");
element.setAttribute("name", fieldName);
element.setAttribute("value", value == null ? "" : value);
@@ -35,20 +30,14 @@
}
@NotNull
- public static String readField(Element parent, @NonNls String fieldName, @NotNull String defaultValue) {
+ public static String readField(@NotNull Element parent, @NotNull @NonNls String fieldName, @NotNull String defaultValue) {
String val = readField(parent, fieldName);
- if (val != null) {
- return val;
- } else {
- return defaultValue;
- }
+ return val == null ? defaultValue : val;
}
@Nullable
- public static String readField(Element parent, @NonNls String fieldName) {
- List list = parent.getChildren("option");
- for (int i = 0; i < list.size(); i++) {
- Element element = (Element)list.get(i);
+ public static String readField(@NotNull Element parent, @NotNull @NonNls String fieldName) {
+ for (Element element : JDOMUtil.getChildren(parent, "option")) {
String childName = element.getAttributeValue("name");
if (Comparing.strEqual(childName, fieldName)) {
return element.getAttributeValue("value");
@@ -56,4 +45,22 @@
}
return null;
}
+
+ public static Element getOption(@NotNull Element parent, @NotNull @NonNls String fieldName) {
+ for (Element element : JDOMUtil.getChildren(parent, "option")) {
+ String childName = element.getAttributeValue("name");
+ if (Comparing.strEqual(childName, fieldName)) {
+ return element;
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ public static Element writeOption(@NotNull Element root, @NotNull @NonNls String fieldName) {
+ Element element = new Element("option");
+ element.setAttribute("name", fieldName);
+ root.addContent(element);
+ return element;
+ }
}
diff --git a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java
index 665776f..2cd5ed0 100644
--- a/platform/util/src/com/intellij/openapi/util/JDOMUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/JDOMUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -315,7 +315,7 @@
private static SAXBuilder getSaxBuilder() {
SoftReference<SAXBuilder> reference = ourSaxBuilder.get();
- SAXBuilder saxBuilder = reference != null ? reference.get() : null;
+ SAXBuilder saxBuilder = com.intellij.reference.SoftReference.dereference(reference);
if (saxBuilder == null) {
saxBuilder = new SAXBuilder();
saxBuilder.setEntityResolver(new EntityResolver() {
@@ -769,4 +769,8 @@
}
return hasContent ? result : null;
}
+
+ public static boolean isEmpty(@NotNull Element element) {
+ return element.getAttributes().isEmpty() && element.getContent().isEmpty();
+ }
}
diff --git a/platform/util/src/com/intellij/openapi/util/MultiValuesMap.java b/platform/util/src/com/intellij/openapi/util/MultiValuesMap.java
index 03037b2..41feba6 100644
--- a/platform/util/src/com/intellij/openapi/util/MultiValuesMap.java
+++ b/platform/util/src/com/intellij/openapi/util/MultiValuesMap.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.
diff --git a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java
index 4768ac6..96eefe8 100644
--- a/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java
+++ b/platform/util/src/com/intellij/openapi/util/NotNullLazyValue.java
@@ -37,4 +37,14 @@
}
return myValue;
}
+
+ public static <T> NotNullLazyValue<T> createConstantValue(@NotNull final T value) {
+ return new NotNullLazyValue<T>() {
+ @NotNull
+ @Override
+ protected T compute() {
+ return value;
+ }
+ };
+ }
}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/openapi/util/SystemInfo.java b/platform/util/src/com/intellij/openapi/util/SystemInfo.java
index aff4475..3a7fafa 100644
--- a/platform/util/src/com/intellij/openapi/util/SystemInfo.java
+++ b/platform/util/src/com/intellij/openapi/util/SystemInfo.java
@@ -15,12 +15,18 @@
*/
package com.intellij.openapi.util;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.SystemProperties;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
@SuppressWarnings({"HardCodedStringLiteral", "UtilityClassWithoutPrivateConstructor", "UnusedDeclaration"})
public class SystemInfo extends SystemInfoRt {
@@ -56,6 +62,42 @@
public static final boolean isXWindow = isUnix && !isMac;
+ // http://www.freedesktop.org/software/systemd/man/os-release.html
+ private static NotNullLazyValue<Map<String, String>> ourOsReleaseInfo = new AtomicNotNullLazyValue<Map<String, String>>() {
+ @NotNull
+ @Override
+ protected Map<String, String> compute() {
+ if (isUnix && !isMac) {
+ try {
+ List<String> lines = FileUtil.loadLines("/etc/os-release");
+ Map<String, String> info = ContainerUtil.newHashMap();
+ for (String line : lines) {
+ int p = line.indexOf('=');
+ if (p > 0) {
+ String name = line.substring(0, p);
+ String value = StringUtil.unquoteString(line.substring(p + 1));
+ if (!StringUtil.isEmptyOrSpaces(name) && !StringUtil.isEmptyOrSpaces(value)) {
+ info.put(name, value);
+ }
+ }
+ }
+ return info;
+ }
+ catch (IOException ignored) { }
+ }
+
+ return Collections.emptyMap();
+ }
+ };
+ @Nullable
+ public static String getUnixReleaseName() {
+ return ourOsReleaseInfo.getValue().get("NAME");
+ }
+ @Nullable
+ public static String getUnixReleaseVersion() {
+ return ourOsReleaseInfo.getValue().get("VERSION");
+ }
+
public static final boolean isMacSystemMenu = isMac && "true".equals(System.getProperty("apple.laf.useScreenMenuBar"));
public static final boolean isFileSystemCaseSensitive = SystemInfoRt.isFileSystemCaseSensitive;
diff --git a/platform/util/src/com/intellij/openapi/util/WriteExternalException.java b/platform/util/src/com/intellij/openapi/util/WriteExternalException.java
index 3d61f6e..7671414 100644
--- a/platform/util/src/com/intellij/openapi/util/WriteExternalException.java
+++ b/platform/util/src/com/intellij/openapi/util/WriteExternalException.java
@@ -15,6 +15,10 @@
*/
package com.intellij.openapi.util;
+/**
+ * Throw this exception from {@link JDOMExternalizable#writeExternal(org.jdom.Element)} method if you don't want to store any settings.
+ * If you simply return from the method empty '<component name=... />' tag will be written leading to unneeded modification of configuration files.
+ */
public class WriteExternalException extends Exception {
public WriteExternalException() {
super();
diff --git a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java b/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
index 8e9ae27..0542b18 100644
--- a/platform/util/src/com/intellij/openapi/util/io/FileUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/FileUtil.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.
@@ -105,6 +105,7 @@
return !ThreeState.NO.equals(isAncestorThreeState(ancestor, file, strict));
}
+ @NotNull
public static ThreeState isAncestorThreeState(@NotNull String ancestor, @NotNull String file, boolean strict) {
String ancestorPath = toCanonicalPath(ancestor);
String filePath = toCanonicalPath(file);
@@ -127,6 +128,7 @@
/**
* @return ThreeState.YES if same path or immediate parent
*/
+ @NotNull
private static ThreeState startsWith(@NotNull String path, @NotNull String start, boolean strict, boolean caseSensitive,
boolean checkImmediateParent) {
final int length1 = path.length();
@@ -138,12 +140,11 @@
return strict ? ThreeState.NO : ThreeState.YES;
}
char last2 = start.charAt(length2 - 1);
- char next1;
int slashOrSeparatorIdx = length2;
if (last2 == '/' || last2 == File.separatorChar) {
slashOrSeparatorIdx = length2 - 1;
}
- next1 = path.charAt(slashOrSeparatorIdx);
+ char next1 = path.charAt(slashOrSeparatorIdx);
if (next1 == '/' || next1 == File.separatorChar) {
if (!checkImmediateParent) return ThreeState.YES;
@@ -374,7 +375,7 @@
final Method executeOnPooledThreadMethod = application.getClass().getMethod("executeOnPooledThread", Runnable.class);
executeOnPooledThreadMethod.invoke(application, deleteFilesTask);
}
- catch (Exception e) {
+ catch (Exception ignored) {
new Thread(deleteFilesTask, "File deletion thread").start();
}
return deleteFilesTask;
@@ -599,16 +600,13 @@
return findSequentNonexistentFile(aParentFolder, aFilePrefix, aExtension).getName();
}
- public static File findSequentNonexistentFile(@NotNull File aParentFolder,
- @NotNull @NonNls final String aFilePrefix,
- @NotNull String aExtension) {
+ public static File findSequentNonexistentFile(@NotNull File parentFolder, @NotNull String filePrefix, @NotNull String extension) {
int postfix = 0;
- String ext = aExtension.isEmpty() ? "" : "." + aExtension;
-
- File candidate = new File(aParentFolder, aFilePrefix + ext);
+ String ext = extension.isEmpty() ? "" : '.' + extension;
+ File candidate = new File(parentFolder, filePrefix + ext);
while (candidate.exists()) {
postfix++;
- candidate = new File(aParentFolder, aFilePrefix + Integer.toString(postfix) + ext);
+ candidate = new File(parentFolder, filePrefix + Integer.toString(postfix) + ext);
}
return candidate;
}
@@ -843,7 +841,7 @@
}
public static int pathHashCode(@Nullable String path) {
- return StringUtil.isEmpty(path) || path == null ? 0 : PATH_HASHING_STRATEGY.computeHashCode(toCanonicalPath(path));
+ return StringUtil.isEmpty(path) ? 0 : PATH_HASHING_STRATEGY.computeHashCode(toCanonicalPath(path));
}
/**
@@ -989,6 +987,7 @@
File toFile = new File(toDir, fromFile.getName());
success = success && fromFile.renameTo(toFile);
}
+ //noinspection ResultOfMethodCallIgnored
fromDir.delete();
return success;
@@ -1022,7 +1021,7 @@
return file.canExecute();
}
- public static void setReadOnlyAttribute(@NotNull String path, boolean readOnlyFlag) throws IOException {
+ public static void setReadOnlyAttribute(@NotNull String path, boolean readOnlyFlag) {
final boolean writableFlag = !readOnlyFlag;
final File file = new File(path);
if (!file.setWritable(writableFlag) && file.canWrite() != writableFlag) {
@@ -1073,11 +1072,11 @@
while (!queue.isEmpty()) {
final File file = queue.removeFirst();
if (!processor.process(file)) return false;
- if (file.isDirectory() && (directoryFilter == null || directoryFilter.process(file))) {
- final File[] children = file.listFiles();
- if (children != null) {
- ContainerUtil.addAll(queue, children);
- }
+ if (directoryFilter != null && (!file.isDirectory() || !directoryFilter.process(file))) continue;
+
+ final File[] children = file.listFiles();
+ if (children != null) {
+ ContainerUtil.addAll(queue, children);
}
}
return true;
@@ -1350,25 +1349,46 @@
}
@NotNull
- public static List<String> loadLines(@NotNull InputStream stream) throws IOException {
- //noinspection IOResourceOpenedButNotSafelyClosed
- return loadLines(new InputStreamReader(stream));
+ public static List<String> loadLines(@NotNull File file) throws IOException {
+ return FileUtilRt.loadLines(file);
}
@NotNull
+ public static List<String> loadLines(@NotNull File file, @Nullable @NonNls String encoding) throws IOException {
+ return FileUtilRt.loadLines(file, encoding);
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull String path) throws IOException {
+ return FileUtilRt.loadLines(path);
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull String path, @Nullable @NonNls String encoding) throws IOException {
+ return FileUtilRt.loadLines(path, encoding);
+ }
+
+ @NotNull
+ public static List<String> loadLines(@NotNull BufferedReader reader) throws IOException {
+ return FileUtilRt.loadLines(reader);
+ }
+
+ /** @deprecated unclear closing policy, do not use (to remove in IDEA 14) */
+ @SuppressWarnings({"UnusedDeclaration", "deprecation"})
+ public static List<String> loadLines(@NotNull InputStream stream) throws IOException {
+ return loadLines(new InputStreamReader(stream));
+ }
+
+ /** @deprecated unclear closing policy, do not use (to remove in IDEA 14) */
+ @SuppressWarnings("UnusedDeclaration")
public static List<String> loadLines(@NotNull Reader reader) throws IOException {
- List<String> lines = new ArrayList<String>();
BufferedReader bufferedReader = new BufferedReader(reader);
try {
- String line;
- while ((line = bufferedReader.readLine()) != null) {
- lines.add(line);
- }
+ return loadLines(bufferedReader);
}
finally {
bufferedReader.close();
}
- return lines;
}
@NotNull
@@ -1438,4 +1458,12 @@
return map;
}
+
+ public static boolean isRootPath(@NotNull File file) {
+ return isRootPath(file.getPath());
+ }
+
+ public static boolean isRootPath(@NotNull String path) {
+ return path.equals("/") || path.matches("[a-zA-Z]:[/\\\\]");
+ }
}
diff --git a/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java b/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java
index dcd9647..72754dd 100644
--- a/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/io/StreamUtil.java
@@ -16,6 +16,7 @@
package com.intellij.openapi.util.io;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.util.io.UnsyncByteArrayOutputStream;
import com.intellij.util.text.StringFactory;
import org.jetbrains.annotations.Nullable;
@@ -45,7 +46,7 @@
}
public static byte[] loadFromStream(InputStream inputStream) throws IOException {
- final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ final UnsyncByteArrayOutputStream outputStream = new UnsyncByteArrayOutputStream();
try {
copyStreamContent(inputStream, outputStream);
}
diff --git a/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java b/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java
index 6697b4f..36ac7dc 100644
--- a/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java
+++ b/platform/util/src/com/intellij/openapi/util/io/UniqueNameBuilder.java
@@ -99,4 +99,8 @@
}
return b.toString();
}
+
+ public String getSeparator() {
+ return mySeparator;
+ }
}
diff --git a/platform/util/src/com/intellij/openapi/util/registry/Registry.java b/platform/util/src/com/intellij/openapi/util/registry/Registry.java
index 0b86055..e418e55 100644
--- a/platform/util/src/com/intellij/openapi/util/registry/Registry.java
+++ b/platform/util/src/com/intellij/openapi/util/registry/Registry.java
@@ -91,8 +91,7 @@
}
static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(REGISTRY_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
index 34c9cc2..93fb443 100644
--- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
+++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java
@@ -42,6 +42,7 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.text.StringUtil");
@NonNls private static final String VOWELS = "aeiouy";
+ @NonNls private static final Pattern EOL_SPLIT_KEEP_SEPARATORS = Pattern.compile("(?<=(\r\n|\n))|(?<=\r)(?=[^\n])");
@NonNls private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *");
@NonNls private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *");
@NonNls private static final Pattern EOL_SPLIT_DONT_TRIM_PATTERN = Pattern.compile("(\r|\n|\r\n)+");
@@ -433,8 +434,10 @@
}
}
- @NonNls private static final String[] ourPrepositions = {"at", "the", "and", "not", "if", "a", "or", "to", "in", "on", "into", "by"};
-
+ @NonNls private static final String[] ourPrepositions = {
+ "a", "an", "and", "as", "at", "but", "by", "down", "for", "from", "if", "in", "into", "not", "of", "on", "onto", "or", "out", "over",
+ "per", "nor", "the", "to", "up", "upon", "via", "with"
+ };
public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar) {
return isPreposition(s, firstChar, lastChar, ourPrepositions);
@@ -569,6 +572,15 @@
return s.substring(1, s.length() - 1);
}
+ @NotNull
+ public static String unquoteString(@NotNull String s, char quotationChar) {
+ char c;
+ if (s.length() <= 1 || (c = s.charAt(0)) != quotationChar || s.charAt(s.length() - 1) != c) {
+ return s;
+ }
+ return s.substring(1, s.length() - 1);
+ }
+
/**
* This is just an optimized version of Matcher.quoteReplacement
*/
@@ -1710,7 +1722,7 @@
}
@NotNull
- private static String escapeChar(@NotNull final String str, final char character) {
+ public static String escapeChar(@NotNull final String str, final char character) {
final StringBuilder buf = new StringBuilder(str);
escapeChar(buf, character);
return buf.toString();
@@ -1797,6 +1809,12 @@
}
@NotNull
+ public static String htmlEmphasize(String text) {
+ return "<b><code>" + escapeXml(text) + "</code></b>";
+ }
+
+
+ @NotNull
public static String escapeToRegexp(@NotNull String text) {
final StringBuilder result = new StringBuilder(text.length());
return escapeToRegexp(text, result).toString();
@@ -2133,7 +2151,7 @@
for (int i = 0; i < name.length(); i++) {
final char ch = name.charAt(i);
- if (Character.isLetterOrDigit(ch)) {
+ if (Character.isJavaIdentifierPart(ch)) {
if (result.length() == 0 && !Character.isJavaIdentifierStart(ch)) {
result.append("_");
}
@@ -2206,6 +2224,25 @@
return EOL_SPLIT_DONT_TRIM_PATTERN.split(string);
}
+ /**
+ * Splits string by lines, keeping all line separators at the line ends and in the empty lines.
+ * <br> E.g. splitting text
+ * <blockquote>
+ * foo\r\n<br>
+ * \n<br>
+ * bar\n<br>
+ * \r\n<br>
+ * baz\r<br>
+ * \r<br>
+ * </blockquote>
+ * will return the following array: foo\r\n, \n, bar\n, \r\n, baz\r, \r
+ *
+ */
+ @NotNull
+ public static String[] splitByLinesKeepSeparators(@NotNull String string) {
+ return EOL_SPLIT_KEEP_SEPARATORS.split(string);
+ }
+
@NotNull
public static List<Pair<String, Integer>> getWordsWithOffset(@NotNull String s) {
List<Pair<String, Integer>> res = ContainerUtil.newArrayList();
diff --git a/platform/util/src/com/intellij/openapi/wm/FocusWatcher.java b/platform/util/src/com/intellij/openapi/wm/FocusWatcher.java
index f3f522b..d8b774b 100644
--- a/platform/util/src/com/intellij/openapi/wm/FocusWatcher.java
+++ b/platform/util/src/com/intellij/openapi/wm/FocusWatcher.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.wm;
+import com.intellij.reference.SoftReference;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -111,11 +112,11 @@
* @return last focused component or <code>null</code>.
*/
public final Component getFocusedComponent(){
- return myFocusedComponent != null ? myFocusedComponent.get() : null;
+ return SoftReference.dereference(myFocusedComponent);
}
public final Component getNearestFocusableComponent() {
- return myNearestFocusableComponent != null ? myNearestFocusableComponent.get() : null;
+ return SoftReference.dereference(myNearestFocusableComponent);
}
public final void install(@NotNull Component component){
diff --git a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java
index f93dfaa..1c490fa 100644
--- a/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java
+++ b/platform/util/src/com/intellij/psi/codeStyle/MinusculeMatcher.java
@@ -292,7 +292,8 @@
return null;
}
// if the user has typed a dot, don't skip other dots between humps
- if (!allowSpecialChars && myHasDots && StringUtil.contains(name, nameIndex, nextOccurrence, '.')) {
+ // but one pattern dot may match several name dots
+ if (!allowSpecialChars && myHasDots && !isPatternChar(patternIndex - 1, '.') && StringUtil.contains(name, nameIndex, nextOccurrence, '.')) {
return null;
}
// uppercase should match either uppercase or a word start
diff --git a/platform/util/src/com/intellij/ui/ClickListener.java b/platform/util/src/com/intellij/ui/ClickListener.java
index 82e3d8a..03dd687 100644
--- a/platform/util/src/com/intellij/ui/ClickListener.java
+++ b/platform/util/src/com/intellij/ui/ClickListener.java
@@ -19,6 +19,8 @@
*/
package com.intellij.ui;
+import org.jetbrains.annotations.NotNull;
+
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
@@ -30,9 +32,9 @@
private static final long TIME_EPS = 500; // TODO: read system mouse sensitivity settings?
private MouseAdapter myListener;
- public abstract boolean onClick(MouseEvent event, int clickCount);
+ public abstract boolean onClick(@NotNull MouseEvent event, int clickCount);
- public void installOn(final Component c) {
+ public void installOn(@NotNull Component c) {
myListener = new MouseAdapter() {
private Point pressPoint;
private Point lastClickPoint;
@@ -64,11 +66,9 @@
lastClickPoint = clickedAt;
pressPoint = null;
- if (e.isConsumed()) return;
-
- if (clickedAt == null) return;
- if (e.isPopupTrigger()) return;
- if (!e.getComponent().contains(e.getPoint())) return;
+ if (e.isConsumed() || clickedAt == null || e.isPopupTrigger() || !e.getComponent().contains(e.getPoint())) {
+ return;
+ }
if (isWithinEps(releasedAt, clickedAt) && onClick(e, clickCount)) {
e.consume();
diff --git a/platform/util/src/com/intellij/ui/TableUtil.java b/platform/util/src/com/intellij/ui/TableUtil.java
index 51a98cb..28aa8d9 100644
--- a/platform/util/src/com/intellij/ui/TableUtil.java
+++ b/platform/util/src/com/intellij/ui/TableUtil.java
@@ -15,16 +15,19 @@
*/
package com.intellij.ui;
+import com.intellij.util.SmartList;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.ItemRemovable;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;
import java.awt.*;
import java.util.ArrayList;
-import java.util.LinkedList;
import java.util.List;
public class TableUtil {
@@ -70,43 +73,70 @@
@NotNull
public static List<Object[]> removeSelectedItems(@NotNull JTable table, @Nullable ItemChecker applyable) {
- if (table.isEditing()){
- table.getCellEditor().stopCellEditing();
- }
- TableModel model = table.getModel();
+ final TableModel model = table.getModel();
if (!(model instanceof ItemRemovable)) {
throw new RuntimeException("model must be instance of ItemRemovable");
}
+ if (table.getSelectionModel().isSelectionEmpty()) {
+ return new ArrayList<Object[]>(0);
+ }
+
+ final List<Object[]> removedItems = new SmartList<Object[]>();
+ final ItemRemovable itemRemovable = (ItemRemovable)model;
+ final int columnCount = model.getColumnCount();
+ doRemoveSelectedItems(table, new ItemRemovable() {
+ @Override
+ public void removeRow(int index) {
+ Object[] row = new Object[columnCount];
+ for (int column = 0; column < columnCount; column++) {
+ row[column] = model.getValueAt(index, column);
+ }
+ removedItems.add(row);
+ itemRemovable.removeRow(index);
+ }
+ }, applyable);
+ return ContainerUtil.reverse(removedItems);
+ }
+
+ public static boolean doRemoveSelectedItems(@NotNull JTable table, @NotNull ItemRemovable itemRemovable, @Nullable ItemChecker applyable) {
+ if (table.isEditing()) {
+ table.getCellEditor().stopCellEditing();
+ }
+
ListSelectionModel selectionModel = table.getSelectionModel();
int minSelectionIndex = selectionModel.getMinSelectionIndex();
- if (minSelectionIndex == -1) return new ArrayList<Object[]>(0);
+ int maxSelectionIndex = selectionModel.getMaxSelectionIndex();
+ if (minSelectionIndex == -1 || maxSelectionIndex == -1) {
+ return false;
+ }
- List<Object[]> removedItems = new LinkedList<Object[]>();
-
- final int columnCount = model.getColumnCount();
- for (int idx = table.getRowCount() - 1; idx >= 0; idx--) {
- if (selectionModel.isSelectedIndex(idx) && (applyable == null || applyable.isOperationApplyable(model, idx))) {
- final Object[] row = new Object[columnCount];
- for(int column = 0; column < columnCount; column++){
- row[column] = model.getValueAt(idx, column);
- }
- removedItems.add(0, row);
- ((ItemRemovable)model).removeRow(idx);
+ TableModel model = table.getModel();
+ boolean removed = false;
+ for (int index = maxSelectionIndex; index >= 0; index--) {
+ if (selectionModel.isSelectedIndex(index) && (applyable == null || applyable.isOperationApplyable(model, index))) {
+ itemRemovable.removeRow(index);
+ removed = true;
}
}
+
+ if (!removed) {
+ return false;
+ }
+
int count = model.getRowCount();
if (count == 0) {
table.clearSelection();
}
- else if (table.getSelectedRow() == -1) {
+ else if (selectionModel.getMinSelectionIndex() == -1) {
if (minSelectionIndex >= model.getRowCount()) {
selectionModel.setSelectionInterval(model.getRowCount() - 1, model.getRowCount() - 1);
- } else {
+ }
+ else {
selectionModel.setSelectionInterval(minSelectionIndex, minSelectionIndex);
}
}
- return removedItems;
+ return true;
}
public static int moveSelectedItemsUp(@NotNull JTable table) {
@@ -196,4 +226,30 @@
if (table.getSelectedRow() != -1 || table.getRowCount() == 0) return;
table.setRowSelectionInterval(0, 0);
}
+
+ public static void setupCheckboxColumn(@NotNull JTable table, int columnIndex) {
+ setupCheckboxColumn(table.getColumnModel().getColumn(columnIndex));
+ }
+
+ public static void setupCheckboxColumn(@NotNull TableColumn column) {
+ int checkboxWidth = new JCheckBox().getPreferredSize().width;
+ column.setResizable(false);
+ column.setPreferredWidth(checkboxWidth);
+ column.setMaxWidth(checkboxWidth);
+ column.setMinWidth(checkboxWidth);
+ }
+
+ public static void updateScroller(@NotNull JTable table, boolean temporaryHideVerticalScrollBar) {
+ JScrollPane scrollPane = UIUtil.getParentOfType(JScrollPane.class, table);
+ if (scrollPane != null) {
+ if (temporaryHideVerticalScrollBar) {
+ final JScrollBar bar = scrollPane.getVerticalScrollBar();
+ if (bar == null || !bar.isVisible()) {
+ scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_NEVER);
+ }
+ }
+ scrollPane.revalidate();
+ scrollPane.repaint();
+ }
+ }
}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/ui/UIBundle.java b/platform/util/src/com/intellij/ui/UIBundle.java
index 4d63e4b..8802f9d 100644
--- a/platform/util/src/com/intellij/ui/UIBundle.java
+++ b/platform/util/src/com/intellij/ui/UIBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,20 +25,19 @@
import java.util.ResourceBundle;
public class UIBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = "messages.UIBundle") String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "messages.UIBundle";
private UIBundle() {
}
- public static String message(@PropertyKey(resourceBundle = "messages.UIBundle")String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java b/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java
index 03494f4..8b4ed40 100644
--- a/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java
+++ b/platform/util/src/com/intellij/ui/mac/foundation/Foundation.java
@@ -27,6 +27,7 @@
/**
* @author spleaner
+ * @@see http://developer.apple.com/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
*/
public class Foundation {
private static final FoundationLibrary myFoundationLibrary;
@@ -90,6 +91,15 @@
return myFoundationLibrary.class_respondsToSelector(cls, selectorName);
}
+ /**
+ *
+ * @param cls The class to which to add a method.
+ * @param selectorName A selector that specifies the name of the method being added.
+ * @param impl A function which is the implementation of the new method. The function must take at least two arguments—self and _cmd.
+ * @param types An array of characters that describe the types of the arguments to the method.
+ * See <a href="https://developer.apple.com/library/IOs/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html#//apple_ref/doc/uid/TP40008048-CH100"></a>
+ * @return true if the method was added successfully, otherwise false (for example, the class already contains a method implementation with that name).
+ */
public static boolean addMethod(ID cls, Pointer selectorName, Callback impl, String types) {
return myFoundationLibrary.class_addMethod(cls, selectorName, impl, types);
}
@@ -213,7 +223,7 @@
return invoke("NSThread", "isMainThread").intValue() > 0;
}
- private static Map<String, RunnableInfo> ourMainThreadRunnables = new HashMap<String, RunnableInfo>();
+ private static final Map<String, RunnableInfo> ourMainThreadRunnables = new HashMap<String, RunnableInfo>();
private static long ourCurrentRunnableCount = 0;
private static final Object RUNNABLE_LOCK = new Object();
@@ -248,17 +258,18 @@
registerObjcClassPair(runnableClass);
final Callback callback = new Callback() {
+ @SuppressWarnings("UnusedDeclaration")
public void callback(ID self, String selector, ID keyObject) {
final String key = toStringViaUTF8(keyObject);
-
RunnableInfo info;
synchronized (RUNNABLE_LOCK) {
info = ourMainThreadRunnables.remove(key);
}
- if (info == null) return;
-
+ if (info == null) {
+ return;
+ }
ID pool = null;
try {
@@ -283,7 +294,7 @@
}
public static class NSDictionary {
- private ID myDelegate;
+ private final ID myDelegate;
public NSDictionary(ID delegate) {
myDelegate = delegate;
@@ -303,7 +314,7 @@
}
public static class NSArray {
- private ID myDelegate;
+ private final ID myDelegate;
public NSArray(ID delegate) {
myDelegate = delegate;
@@ -319,7 +330,7 @@
}
public static class NSAutoreleasePool {
- private ID myDelegate;
+ private final ID myDelegate;
public NSAutoreleasePool() {
myDelegate = invoke(invoke("NSAutoreleasePool", "alloc"), "init");
@@ -335,8 +346,8 @@
public NSSize size;
public NSRect(double x, double y, double w, double h) {
- this.origin = new NSPoint(x, y);
- this.size = new NSSize(w, h);
+ origin = new NSPoint(x, y);
+ size = new NSSize(w, h);
}
}
@@ -415,4 +426,39 @@
throw new IllegalStateException();
}
}
+
+ public static ID fillArray(final Object[] a) {
+ final ID result = invoke("NSMutableArray", "array");
+ for (Object s : a) {
+ invoke(result, "addObject:", convertType(s));
+ }
+
+ return result;
+ }
+
+ public static ID createDict(@NotNull final String[] keys, @NotNull final Object[] values) {
+ final ID nsKeys = invoke("NSArray", "arrayWithObjects:", convertTypes(keys));
+ final ID nsData = invoke("NSArray", "arrayWithObjects:", convertTypes(values));
+ return invoke("NSDictionary", "dictionaryWithObjects:forKeys:", nsData, nsKeys);
+ }
+
+ private static Object[] convertTypes(@NotNull Object[] v) {
+ final Object[] result = new Object[v.length];
+ for (int i = 0; i < v.length; i++) {
+ result[i] = convertType(v[i]);
+ }
+ return result;
+ }
+
+ private static Object convertType(@NotNull Object o) {
+ if (o instanceof Pointer || o instanceof ID) {
+ return o;
+ }
+ else if (o instanceof String) {
+ return nsString((String)o);
+ }
+ else {
+ throw new IllegalArgumentException("Unsupported type! " + o.getClass());
+ }
+ }
}
diff --git a/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java b/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java
index 64aa444..a5a308b 100644
--- a/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java
+++ b/platform/util/src/com/intellij/ui/mac/foundation/MacUtil.java
@@ -31,6 +31,7 @@
import java.awt.event.KeyEvent;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
+import java.util.concurrent.atomic.AtomicBoolean;
import static com.intellij.ui.mac.foundation.Foundation.invoke;
import static com.intellij.ui.mac.foundation.Foundation.toStringViaUTF8;
@@ -41,7 +42,7 @@
public class MacUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.ui.mac.foundation.MacUtil");
public static final String MAC_NATIVE_WINDOW_SHOWING = "MAC_NATIVE_WINDOW_SHOWING";
-
+
private MacUtil() {
}
@@ -111,14 +112,21 @@
catch (InterruptedException ignored) {
}
}
-
+
public static synchronized void startModal(JComponent component) {
startModal(component, MAC_NATIVE_WINDOW_SHOWING);
}
public static boolean isFullKeyboardAccessEnabled() {
- return SystemInfo.isMacOSSnowLeopard
- && invoke(invoke("NSApplication", "sharedApplication"), "isFullKeyboardAccessEnabled").intValue() == 1;
+ if (!SystemInfo.isMacOSSnowLeopard) return false;
+ final AtomicBoolean result = new AtomicBoolean();
+ Foundation.executeOnMainThread(new Runnable() {
+ @Override
+ public void run() {
+ result.set(invoke(invoke("NSApplication", "sharedApplication"), "isFullKeyboardAccessEnabled").intValue() == 1);
+ }
+ }, true, true);
+ return result.get();
}
public static void adjustFocusTraversal(@NotNull Disposable disposable) {
diff --git a/platform/util/src/com/intellij/util/AdapterProcessor.java b/platform/util/src/com/intellij/util/AdapterProcessor.java
index a80f451..549249b 100644
--- a/platform/util/src/com/intellij/util/AdapterProcessor.java
+++ b/platform/util/src/com/intellij/util/AdapterProcessor.java
@@ -19,11 +19,13 @@
*/
package com.intellij.util;
+import org.jetbrains.annotations.NotNull;
+
public class AdapterProcessor<T, S> implements Processor<T> {
private final Processor<S> myAdaptee;
private final Function<T, S> myConversion;
- public AdapterProcessor(Processor<S> adaptee, Function<T, S> conversion) {
+ public AdapterProcessor(@NotNull Processor<S> adaptee, @NotNull Function<T, S> conversion) {
myAdaptee = adaptee;
myConversion = conversion;
}
diff --git a/platform/util/src/com/intellij/util/ArrayConsumer.java b/platform/util/src/com/intellij/util/ArrayConsumer.java
index 6e5d02e..e69174b 100644
--- a/platform/util/src/com/intellij/util/ArrayConsumer.java
+++ b/platform/util/src/com/intellij/util/ArrayConsumer.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.
diff --git a/platform/util/src/com/intellij/util/ArrayUtil.java b/platform/util/src/com/intellij/util/ArrayUtil.java
index 667ee6e..1f75e0c 100644
--- a/platform/util/src/com/intellij/util/ArrayUtil.java
+++ b/platform/util/src/com/intellij/util/ArrayUtil.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.
@@ -370,7 +370,7 @@
}
@NotNull
- public static <T> T[] remove(@NotNull final T[] src, int idx, ArrayFactory<T> factory) {
+ public static <T> T[] remove(@NotNull final T[] src, int idx, @NotNull ArrayFactory<T> factory) {
int length = src.length;
if (idx < 0 || idx >= length) {
throw new IllegalArgumentException("invalid index: " + idx);
@@ -390,7 +390,7 @@
}
@NotNull
- public static <T> T[] remove(@NotNull final T[] src, T element, ArrayFactory<T> factory) {
+ public static <T> T[] remove(@NotNull final T[] src, T element, @NotNull ArrayFactory<T> factory) {
final int idx = find(src, element);
if (idx == -1) return src;
@@ -441,14 +441,10 @@
return indexOf(src, obj);
}
- public static boolean startsWith(byte[] array, byte[] prefix) {
+ public static boolean startsWith(@NotNull byte[] array, @NotNull byte[] prefix) {
if (array == prefix) {
return true;
}
- if (array == null || prefix == null) {
- return false;
- }
-
int length = prefix.length;
if (array.length < length) {
return false;
@@ -463,14 +459,10 @@
return true;
}
- public static <E> boolean startsWith(E[] array, E[] subArray) {
+ public static <E> boolean startsWith(@NotNull E[] array, @NotNull E[] subArray) {
if (array == subArray) {
return true;
}
- if (array == null || subArray == null) {
- return false;
- }
-
int length = subArray.length;
if (array.length < length) {
return false;
@@ -500,13 +492,10 @@
return true;
}
- public static <T> boolean equals(T[] a1, T[] a2, @NotNull Equality<? super T> comparator) {
+ public static <T> boolean equals(@NotNull T[] a1, @NotNull T[] a2, @NotNull Equality<? super T> comparator) {
if (a1 == a2) {
return true;
}
- if (a1 == null || a2 == null) {
- return false;
- }
int length = a2.length;
if (a1.length != length) {
@@ -521,14 +510,10 @@
return true;
}
- public static <T> boolean equals(T[] a1, T[] a2, @NotNull Comparator<? super T> comparator) {
+ public static <T> boolean equals(@NotNull T[] a1, @NotNull T[] a2, @NotNull Comparator<? super T> comparator) {
if (a1 == a2) {
return true;
}
- if (a1 == null || a2 == null) {
- return false;
- }
-
int length = a2.length;
if (a1.length != length) {
return false;
@@ -681,11 +666,11 @@
return -1;
}
- public static boolean contains(@Nullable final Object o, final Object... objects) {
+ public static boolean contains(@Nullable final Object o, @NotNull Object... objects) {
return indexOf(objects, o) >= 0;
}
- public static boolean contains(@Nullable final String s, final String... strings) {
+ public static boolean contains(@Nullable final String s, @NotNull String... strings) {
if (s == null) {
for (String str : strings) {
if (str == null) return true;
diff --git a/platform/util/src/com/intellij/util/EnvironmentUtil.java b/platform/util/src/com/intellij/util/EnvironmentUtil.java
index d8a1c71..1d70164 100644
--- a/platform/util/src/com/intellij/util/EnvironmentUtil.java
+++ b/platform/util/src/com/intellij/util/EnvironmentUtil.java
@@ -22,7 +22,6 @@
import com.intellij.openapi.util.NotNullLazyValue;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.concurrency.FixedFuture;
@@ -33,7 +32,6 @@
import org.jetbrains.annotations.TestOnly;
import java.io.File;
-import java.io.IOException;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
@@ -47,7 +45,7 @@
private static final Future<Map<String, String>> ourEnvGetter;
static {
- if (SystemInfo.isMac && Registry.is("idea.fix.mac.env")) {
+ if (SystemInfo.isMac && "unlocked".equals(System.getProperty("__idea.mac.env.lock")) && Registry.is("idea.fix.mac.env")) {
ExecutorService executor = Executors.newSingleThreadExecutor();
ourEnvGetter = executor.submit(new Callable<Map<String, String>>() {
@Override
@@ -154,7 +152,7 @@
File envFile = FileUtil.createTempFile("intellij-shell-env", null, false);
try {
- String[] command = {shell, "-l", "-c", "'" + reader.getAbsolutePath() + "' '" + envFile.getAbsolutePath() + "'"};
+ String[] command = {shell, "-l", "-i", "-c", ("'" + reader.getAbsolutePath() + "' '" + envFile.getAbsolutePath() + "'")};
LOG.info("loading shell env: " + StringUtil.join(command, " "));
Process process = Runtime.getRuntime().exec(command);
@@ -198,17 +196,6 @@
return Collections.unmodifiableMap(newEnv);
}
- public static String getProcessList() {
- String diagnostics;
- try {
- Process p = Runtime.getRuntime().exec(SystemInfo.isWindows ? System.getenv("windir") +"\\system32\\tasklist.exe /v" : "ps a");
- diagnostics = StreamUtil.readText(p.getInputStream());
- }
- catch (IOException e) {
- diagnostics = ExceptionUtil.getThrowableText(e);
- }
- return diagnostics;
- }
private static class ProcessKiller {
private final Process myProcess;
diff --git a/platform/util/src/com/intellij/util/LineSeparator.java b/platform/util/src/com/intellij/util/LineSeparator.java
index d657c52..67d7cc8 100644
--- a/platform/util/src/com/intellij/util/LineSeparator.java
+++ b/platform/util/src/com/intellij/util/LineSeparator.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.
@@ -37,7 +37,7 @@
private static final Logger LOG = Logger.getInstance(LineSeparator.class);
private final String mySeparatorString;
- LineSeparator(String separatorString) {
+ LineSeparator(@NotNull String separatorString) {
mySeparatorString = separatorString;
}
diff --git a/platform/util/src/com/intellij/util/PairFunction.java b/platform/util/src/com/intellij/util/PairFunction.java
index 1f92657..b4c540e 100644
--- a/platform/util/src/com/intellij/util/PairFunction.java
+++ b/platform/util/src/com/intellij/util/PairFunction.java
@@ -15,13 +15,11 @@
*/
package com.intellij.util;
-import org.jetbrains.annotations.Nullable;
-
/**
* @author max
*/
public interface PairFunction<Arg1, Arg2, ResultType> {
- @Nullable
+
ResultType fun(Arg1 t, Arg2 v);
}
diff --git a/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java b/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java
index a5a1c68..3ef4aea 100644
--- a/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.java
+++ b/platform/util/src/com/intellij/util/ReflectionAssignabilityCache.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,7 +19,6 @@
/**
* @author peter
- * @see ReflectionCache
*/
public class ReflectionAssignabilityCache {
private final ConcurrentFactoryMap<Class, ConcurrentFactoryMap<Class, Boolean>> myCache = new ConcurrentFactoryMap<Class, ConcurrentFactoryMap<Class, Boolean>>() {
diff --git a/platform/util/src/com/intellij/util/ReflectionCache.java b/platform/util/src/com/intellij/util/ReflectionCache.java
index 9fc9672..706649c 100644
--- a/platform/util/src/com/intellij/util/ReflectionCache.java
+++ b/platform/util/src/com/intellij/util/ReflectionCache.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,102 +15,75 @@
*/
package com.intellij.util;
-import com.intellij.util.containers.ConcurrentFactoryMap;
import org.jetbrains.annotations.NotNull;
-import java.lang.reflect.*;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
/**
+ * Contrary to the name, this class doesn't do any caching. So the usages may be safely dropped in favor of plain reflection calls.
+ *
+ * Consider caching higher-level things, if you see reflection in your snapshots.
+ *
+ * @deprecated
* @author peter
*/
@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"})
public class ReflectionCache {
- private static final ConcurrentFactoryMap<Class,Class> ourSuperClasses = new ConcurrentFactoryMap<Class, Class>() {
- @Override
- protected Class create(final Class key) {
- return key.getSuperclass();
- }
- };
- private static final ConcurrentFactoryMap<Class,Class[]> ourInterfaces = new ConcurrentFactoryMap<Class, Class[]>() {
- @Override
- @NotNull
- protected Class[] create(final Class key) {
- Class[] classes = key.getInterfaces();
- return classes.length == 0 ? ArrayUtil.EMPTY_CLASS_ARRAY : classes;
- }
- };
- private static final ConcurrentFactoryMap<Class,Boolean> ourIsInterfaces = new ConcurrentFactoryMap<Class, Boolean>() {
- @Override
- @NotNull
- protected Boolean create(final Class key) {
- return key.isInterface();
- }
- };
- private static final ConcurrentFactoryMap<Class, TypeVariable[]> ourTypeParameters = new ConcurrentFactoryMap<Class, TypeVariable[]>() {
- @Override
- @NotNull
- protected TypeVariable[] create(final Class key) {
- return key.getTypeParameters();
- }
- };
- private static final ConcurrentFactoryMap<Class, Type[]> ourGenericInterfaces = new ConcurrentFactoryMap<Class, Type[]>() {
- @Override
- @NotNull
- protected Type[] create(final Class key) {
- return key.getGenericInterfaces();
- }
- };
- private static final ConcurrentFactoryMap<ParameterizedType, Type[]> ourActualTypeArguments = new ConcurrentFactoryMap<ParameterizedType, Type[]>() {
- @Override
- @NotNull
- protected Type[] create(final ParameterizedType key) {
- return key.getActualTypeArguments();
- }
- };
-
- private ReflectionCache() {
- }
-
+ @Deprecated
public static Class getSuperClass(@NotNull Class aClass) {
- return ourSuperClasses.get(aClass);
+ return aClass.getSuperclass();
}
@NotNull
+ @Deprecated
public static Class[] getInterfaces(@NotNull Class aClass) {
- return ourInterfaces.get(aClass);
+ return aClass.getInterfaces();
}
@NotNull
+ @Deprecated
public static Method[] getMethods(@NotNull Class aClass) {
return aClass.getMethods();
}
+ /**
+ * @deprecated
+ * @see com.intellij.util.ReflectionUtil#isAssignable(Class, Class)
+ */
public static boolean isAssignable(@NotNull Class ancestor, Class descendant) {
return ancestor == descendant || ancestor.isAssignableFrom(descendant);
}
+ @Deprecated
public static boolean isInstance(Object instance, @NotNull Class clazz) {
return clazz.isInstance(instance);
}
+ @Deprecated
public static boolean isInterface(@NotNull Class aClass) {
- return ourIsInterfaces.get(aClass);
+ return aClass.isInterface();
}
@NotNull
+ @Deprecated
public static <T> TypeVariable<Class<T>>[] getTypeParameters(@NotNull Class<T> aClass) {
- return ourTypeParameters.get(aClass);
+ return aClass.getTypeParameters();
}
@NotNull
+ @Deprecated
public static Type[] getGenericInterfaces(@NotNull Class aClass) {
- return ourGenericInterfaces.get(aClass);
+ return aClass.getGenericInterfaces();
}
@NotNull
+ @Deprecated
public static Type[] getActualTypeArguments(@NotNull ParameterizedType type) {
- return ourActualTypeArguments.get(type);
+ return type.getActualTypeArguments();
}
}
diff --git a/platform/util/src/com/intellij/util/ReflectionUtil.java b/platform/util/src/com/intellij/util/ReflectionUtil.java
index c43812c..897c3c3 100644
--- a/platform/util/src/com/intellij/util/ReflectionUtil.java
+++ b/platform/util/src/com/intellij/util/ReflectionUtil.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 @@
package com.intellij.util;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Condition;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,20 +41,20 @@
@Nullable
public static Type resolveVariable(@NotNull TypeVariable variable, @NotNull Class classType, boolean resolveInInterfacesOnly) {
final Class aClass = getRawType(classType);
- int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), variable);
+ int index = ArrayUtilRt.find(aClass.getTypeParameters(), variable);
if (index >= 0) {
return variable;
}
- final Class[] classes = ReflectionCache.getInterfaces(aClass);
- final Type[] genericInterfaces = ReflectionCache.getGenericInterfaces(aClass);
+ final Class[] classes = aClass.getInterfaces();
+ final Type[] genericInterfaces = aClass.getGenericInterfaces();
for (int i = 0; i <= classes.length; i++) {
Class anInterface;
if (i < classes.length) {
anInterface = classes[i];
}
else {
- anInterface = ReflectionCache.getSuperClass(aClass);
+ anInterface = aClass.getSuperclass();
if (resolveInInterfacesOnly || anInterface == null) {
continue;
}
@@ -64,7 +65,7 @@
}
if (resolved instanceof TypeVariable) {
final TypeVariable typeVariable = (TypeVariable)resolved;
- index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(anInterface), typeVariable);
+ index = ArrayUtilRt.find(anInterface.getTypeParameters(), typeVariable);
if (index < 0) {
LOG.error("Cannot resolve type variable:\n" + "typeVariable = " + typeVariable + "\n" + "genericDeclaration = " +
declarationToString(typeVariable.getGenericDeclaration()) + "\n" + "searching in " + declarationToString(anInterface));
@@ -82,6 +83,7 @@
return null;
}
+ @SuppressWarnings("HardCodedStringLiteral")
@NotNull
public static String declarationToString(@NotNull GenericDeclaration anInterface) {
return anInterface.toString()
@@ -106,7 +108,7 @@
@NotNull
public static Type[] getActualTypeArguments(@NotNull ParameterizedType parameterizedType) {
- return ReflectionCache.getActualTypeArguments(parameterizedType);
+ return parameterizedType.getActualTypeArguments();
}
@Nullable
@@ -121,12 +123,13 @@
return (Class<?>)((ParameterizedType)type).getRawType();
}
if (type instanceof TypeVariable && classType instanceof ParameterizedType) {
- final int index = ArrayUtilRt.find(ReflectionCache.getTypeParameters(aClass), type);
+ final int index = ArrayUtilRt.find(aClass.getTypeParameters(), type);
if (index >= 0) {
return getRawType(getActualTypeArguments((ParameterizedType)classType)[index]);
}
}
- } else {
+ }
+ else {
return getRawType(genericType);
}
return null;
@@ -140,23 +143,28 @@
}
@NotNull
- public static Field findField(@NotNull Class clazz, @Nullable Class type, @NotNull String name) throws NoSuchFieldException {
- List<Field> fields = collectFields(clazz);
- for (Field each : fields) {
- if (name.equals(each.getName()) && (type == null || each.getType().equals(type))) return each;
- }
+ public static Field findField(@NotNull Class clazz, @Nullable final Class type, @NotNull final String name) throws NoSuchFieldException {
+ Field result = processFields(clazz, new Condition<Field>() {
+ @Override
+ public boolean value(Field field) {
+ return name.equals(field.getName()) && (type == null || field.getType().equals(type));
+ }
+ });
+ if (result != null) return result;
throw new NoSuchFieldException("Class: " + clazz + " name: " + name + " type: " + type);
}
@NotNull
- public static Field findAssignableField(@NotNull Class clazz, @NotNull Class type, @NotNull String name) throws NoSuchFieldException {
- List<Field> fields = collectFields(clazz);
- for (Field each : fields) {
- if (name.equals(each.getName()) && type.isAssignableFrom(each.getType())) return each;
- }
-
- throw new NoSuchFieldException("Class: " + clazz + " name: " + name + " type: " + type);
+ public static Field findAssignableField(@NotNull Class<?> clazz, @NotNull final Class<?> fieldType, @NotNull final String fieldName) throws NoSuchFieldException {
+ Field result = processFields(clazz, new Condition<Field>() {
+ @Override
+ public boolean value(Field field) {
+ return fieldName.equals(field.getName()) && fieldType.isAssignableFrom(field.getType());
+ }
+ });
+ if (result != null) return result;
+ throw new NoSuchFieldException("Class: " + clazz + " fieldName: " + fieldName + " fieldType: " + fieldType);
}
private static void collectFields(@NotNull Class clazz, @NotNull List<Field> result) {
@@ -172,6 +180,23 @@
}
}
+ private static Field processFields(@NotNull Class clazz, @NotNull Condition<Field> checker) {
+ for (Field field : clazz.getDeclaredFields()) {
+ if (checker.value(field)) return field;
+ }
+ final Class superClass = clazz.getSuperclass();
+ if (superClass != null) {
+ Field result = processFields(superClass, checker);
+ if (result != null) return result;
+ }
+ final Class[] interfaces = clazz.getInterfaces();
+ for (Class each : interfaces) {
+ Field result = processFields(each, checker);
+ if (result != null) return result;
+ }
+ return null;
+ }
+
public static void resetField(@NotNull Class clazz, @NotNull Class type, @NotNull String name) {
try {
resetField(null, findField(clazz, type, name));
@@ -207,13 +232,13 @@
field.set(object, Boolean.FALSE);
}
else if (int.class.equals(type)) {
- field.set(object, new Integer(0));
+ field.set(object, Integer.valueOf(0));
}
else if (double.class.equals(type)) {
- field.set(object, new Double(0));
+ field.set(object, Double.valueOf(0));
}
else if (float.class.equals(type)) {
- field.set(object, new Float(0));
+ field.set(object, Float.valueOf(0));
}
}
else {
@@ -235,7 +260,7 @@
@Nullable
public static Method getMethod(@NotNull Class aClass, @NonNls @NotNull String name, @NotNull Class... parameters) {
- return findMethod(ReflectionCache.getMethods(aClass), name, parameters);
+ return findMethod(aClass.getMethods(), name, parameters);
}
@Nullable
@@ -243,9 +268,15 @@
return findMethod(aClass.getDeclaredMethods(), name, parameters);
}
- public static <T> T getField(@NotNull Class objectClass, Object object, @NotNull Class<T> type, @NotNull @NonNls String name) {
+ @Nullable
+ public static Class getMethodDeclaringClass(@NotNull Class<?> instanceClass, @NonNls @NotNull String name, @NotNull Class... parameters) {
+ Method method = getMethod(instanceClass, name, parameters);
+ return method == null ? null : method.getDeclaringClass();
+ }
+
+ public static <T> T getField(@NotNull Class objectClass, Object object, @NotNull Class<T> fieldType, @NotNull @NonNls String fieldName) {
try {
- final Field field = findAssignableField(objectClass, type, name);
+ final Field field = findAssignableField(objectClass, fieldType, fieldName);
field.setAccessible(true);
return (T)field.get(object);
}
@@ -263,7 +294,7 @@
Type type;
Class current = aClass;
while ((type = resolveVariable(variable, current, false)) == null) {
- current = ReflectionCache.getSuperClass(current);
+ current = current.getSuperclass();
if (current == null) {
return null;
}
@@ -335,4 +366,8 @@
return null;
}
}
+
+ public static boolean isAssignable(@NotNull Class<?> ancestor, Class<?> descendant) {
+ return ancestor == descendant || ancestor.isAssignableFrom(descendant);
+ }
}
diff --git a/platform/util/src/com/intellij/util/ResourceUtil.java b/platform/util/src/com/intellij/util/ResourceUtil.java
index 469e79d..a2a857b 100644
--- a/platform/util/src/com/intellij/util/ResourceUtil.java
+++ b/platform/util/src/com/intellij/util/ResourceUtil.java
@@ -15,6 +15,7 @@
*/
package com.intellij.util;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.io.URLUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -38,11 +39,15 @@
}
public static URL getResource(@NotNull Class loaderClass, @NonNls @NotNull String basePath, @NonNls @NotNull String fileName) {
- if (basePath.endsWith("/")) basePath = basePath.substring(0, basePath.length() - 1);
+ return getResource(loaderClass.getClassLoader(), basePath, fileName);
+ }
- final List<String> bundles = calculateBundleNames(basePath, Locale.getDefault());
+ public static URL getResource(@NotNull ClassLoader loader, @NonNls @NotNull String basePath, @NonNls @NotNull String fileName) {
+ String fixedPath = StringUtil.trimStart(StringUtil.trimEnd(basePath, "/"), "/");
+
+ List<String> bundles = calculateBundleNames(fixedPath, Locale.getDefault());
for (String bundle : bundles) {
- URL url = loaderClass.getResource(bundle + "/" + fileName);
+ URL url = loader.getResource(bundle + "/" + fileName);
if (url == null) continue;
try {
@@ -55,7 +60,7 @@
return url;
}
- return loaderClass.getResource(basePath + "/" + fileName);
+ return loader.getResource(fixedPath + "/" + fileName);
}
/**
diff --git a/platform/util/src/com/intellij/util/SmartFMap.java b/platform/util/src/com/intellij/util/SmartFMap.java
index f341442..a4b95a1 100644
--- a/platform/util/src/com/intellij/util/SmartFMap.java
+++ b/platform/util/src/com/intellij/util/SmartFMap.java
@@ -203,6 +203,8 @@
@NotNull
@Override
public Set<K> keySet() {
+ if (isEmpty()) return Collections.emptySet();
+
LinkedHashSet<K> result = new LinkedHashSet<K>();
for (Entry<K, V> entry : entrySet()) {
result.add(entry.getKey());
@@ -213,6 +215,8 @@
@NotNull
@Override
public Collection<V> values() {
+ if (isEmpty()) return Collections.emptyList();
+
ArrayList<V> result = new ArrayList<V>();
for (Entry<K, V> entry : entrySet()) {
result.add(entry.getValue());
@@ -242,6 +246,8 @@
@NotNull
@Override
public Set<Entry<K, V>> entrySet() {
+ if (isEmpty()) return Collections.emptySet();
+
LinkedHashSet<Entry<K, V>> set = new LinkedHashSet<Entry<K, V>>();
if (myMap instanceof Map) {
for (Entry<K, V> entry : ((Map<K, V>)myMap).entrySet()) {
diff --git a/platform/util/src/com/intellij/util/SmartList.java b/platform/util/src/com/intellij/util/SmartList.java
index c106e68..207c132 100644
--- a/platform/util/src/com/intellij/util/SmartList.java
+++ b/platform/util/src/com/intellij/util/SmartList.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,8 +16,10 @@
package com.intellij.util;
import com.intellij.util.containers.EmptyIterator;
+import com.intellij.util.containers.SingletonIteratorBase;
import org.jetbrains.annotations.NotNull;
+import java.lang.reflect.Array;
import java.util.*;
/**
@@ -208,8 +210,7 @@
return super.iterator();
}
- private class SingletonIterator implements Iterator<E> {
- private boolean myVisited;
+ private class SingletonIterator extends SingletonIteratorBase<E> {
private final int myInitialModCount;
public SingletonIterator() {
@@ -217,25 +218,20 @@
}
@Override
- public boolean hasNext() {
- return !myVisited;
- }
-
- @Override
- public E next() {
- if (myVisited) throw new NoSuchElementException();
- myVisited = true;
- if (modCount != myInitialModCount) {
- throw new ConcurrentModificationException("ModCount: " + modCount + "; expected: " + myInitialModCount);
- }
+ protected E getElement() {
return (E)myElem;
}
@Override
- public void remove() {
+ protected void checkCoModification() {
if (modCount != myInitialModCount) {
throw new ConcurrentModificationException("ModCount: " + modCount + "; expected: " + myInitialModCount);
}
+ }
+
+ @Override
+ public void remove() {
+ checkCoModification();
clear();
}
}
@@ -253,18 +249,29 @@
@NotNull
@Override
public <T> T[] toArray(@NotNull T[] a) {
+ int aLength = a.length;
if (mySize == 1) {
- int length = a.length;
- if (length != 0) {
+ if (aLength != 0) {
a[0] = (T)myElem;
- if (length > 1) {
- a[1] = null;
- }
- return a;
+ }
+ else {
+ T[] r = (T[])Array.newInstance(a.getClass().getComponentType(), 1);
+ r[0] = (T)myElem;
+ return r;
}
}
- //noinspection SuspiciousToArrayCall
- return super.toArray(a);
+ else if (aLength < mySize) {
+ return (T[])Arrays.copyOf((E[])myElem, mySize, a.getClass());
+ }
+ else if (mySize != 0) {
+ //noinspection SuspiciousSystemArraycopy
+ System.arraycopy(myElem, 0, a, 0, mySize);
+ }
+
+ if (aLength > mySize) {
+ a[mySize] = null;
+ }
+ return a;
}
/**
diff --git a/platform/util/src/com/intellij/util/cls/ClsFormatException.java b/platform/util/src/com/intellij/util/cls/ClsFormatException.java
index 4e5b5f7..21e27e8 100644
--- a/platform/util/src/com/intellij/util/cls/ClsFormatException.java
+++ b/platform/util/src/com/intellij/util/cls/ClsFormatException.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,12 +16,13 @@
package com.intellij.util.cls;
public class ClsFormatException extends Exception {
-
- public ClsFormatException() {
- }
+ public ClsFormatException() { }
public ClsFormatException(String message) {
super(message);
}
-}
+ public ClsFormatException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/platform/util/src/com/intellij/util/containers/ClassMap.java b/platform/util/src/com/intellij/util/containers/ClassMap.java
index de53022..078dfd6 100644
--- a/platform/util/src/com/intellij/util/containers/ClassMap.java
+++ b/platform/util/src/com/intellij/util/containers/ClassMap.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,7 +15,6 @@
*/
package com.intellij.util.containers;
-import com.intellij.util.ReflectionCache;
import gnu.trove.THashMap;
import java.util.Collection;
@@ -46,14 +45,14 @@
if (t != null) {
return t;
}
- for (final Class aClass1 : ReflectionCache.getInterfaces(aClass)) {
+ for (final Class aClass1 : aClass.getInterfaces()) {
t = get(aClass1);
if (t != null) {
myMap.put(aClass, t);
return t;
}
}
- final Class superclass = ReflectionCache.getSuperClass(aClass);
+ final Class superclass = aClass.getSuperclass();
if (superclass != null) {
t = get(superclass);
if (t != null) {
diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentList.java b/platform/util/src/com/intellij/util/containers/ConcurrentList.java
new file mode 100644
index 0000000..50ae7a2
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/ConcurrentList.java
@@ -0,0 +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.util.containers;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.List;
+
+public interface ConcurrentList<E> extends List<E> {
+ boolean addIfAbsent(E e);
+ int addAllAbsent(@NotNull Collection<? extends E> c);
+}
diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java
index 0822e34..a5d5bd8 100644
--- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java
+++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.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 @@
}
@NotNull
- public static <K, V> Map<K, V> newHashMap(Pair<K, V> first, Pair<K, V>... entries) {
+ public static <K, V> Map<K, V> newHashMap(@NotNull Pair<K, V> first, Pair<K, V>... entries) {
return ContainerUtilRt.newHashMap(first, entries);
}
@@ -84,6 +84,11 @@
}
@NotNull
+ public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(@NotNull Pair<K, V> first, Pair<K, V>... entries) {
+ return ContainerUtilRt.newLinkedHashMap(first, entries);
+ }
+
+ @NotNull
public static <K, V> THashMap<K, V> newTroveMap() {
return new THashMap<K, V>();
}
@@ -145,9 +150,10 @@
return ContainerUtilRt.newArrayList(iterable);
}
- @NotNull
+ /** @deprecated Use {@link #newArrayListWithCapacity(int)} (to remove in IDEA 15) */
+ @SuppressWarnings("deprecation")
public static <T> ArrayList<T> newArrayListWithExpectedSize(int size) {
- return ContainerUtilRt.newArrayListWithExpectedSize(size);
+ return ContainerUtilRt.newArrayListWithCapacity(size);
}
@NotNull
@@ -193,6 +199,11 @@
}
@NotNull
+ public static <T> HashSet<T> newHashSet(int initialCapacity) {
+ return ContainerUtilRt.newHashSet(initialCapacity);
+ }
+
+ @NotNull
public static <T> HashSet<T> newHashSet(@NotNull T... elements) {
return ContainerUtilRt.newHashSet(elements);
}
@@ -208,6 +219,12 @@
}
@NotNull
+ public static <T> Set<T> newHashOrEmptySet(@Nullable Iterable<? extends T> iterable) {
+ boolean empty = iterable == null || iterable instanceof Collection && ((Collection)iterable).isEmpty();
+ return empty ? Collections.<T>emptySet() : ContainerUtilRt.newHashSet(iterable);
+ }
+
+ @NotNull
public static <T> LinkedHashSet<T> newLinkedHashSet() {
return ContainerUtilRt.newLinkedHashSet();
}
@@ -314,6 +331,10 @@
@NotNull
public static <E> List<E> reverse(@NotNull final List<E> elements) {
+ if (elements.isEmpty()) {
+ return ContainerUtilRt.emptyList();
+ }
+
return new AbstractList<E>() {
@Override
public E get(int index) {
@@ -1022,6 +1043,21 @@
return modified;
}
+ // returns true if the collection was modified
+ public static <T> boolean retainAll(@NotNull Collection<T> collection, @NotNull Condition<? super T> condition) {
+ boolean modified = false;
+
+ for (Iterator<T> iterator = collection.iterator(); iterator.hasNext(); ) {
+ T next = iterator.next();
+ if (!condition.value(next)) {
+ iterator.remove();
+ modified = true;
+ }
+ }
+
+ return modified;
+ }
+
public static <T, U extends T> U findInstance(@NotNull Iterable<T> iterable, @NotNull Class<U> aClass) {
return findInstance(iterable.iterator(), aClass);
}
@@ -1935,7 +1971,7 @@
*/
@NotNull
public static <T> List<T> createLockFreeCopyOnWriteList() {
- return new LockFreeCopyOnWriteArrayList<T>();
+ return createConcurrentList();
}
@NotNull
@@ -1943,6 +1979,11 @@
return new LockFreeCopyOnWriteArrayList<T>(c);
}
+ @NotNull
+ public static <T> ConcurrentList<T> createConcurrentList() {
+ return new LockFreeCopyOnWriteArrayList<T>();
+ }
+
public static <T> void addIfNotNull(@Nullable T element, @NotNull Collection<T> result) {
ContainerUtilRt.addIfNotNull(element, result);
}
@@ -2054,7 +2095,10 @@
return new java.util.concurrent.ConcurrentHashMap<T,V>(initialCapacity);
}
- public <T, V> ConcurrentMap<T, V> createMap(TObjectHashingStrategy<T> hashStrategy) {
+ public <T, V> ConcurrentMap<T, V> createMap(TObjectHashingStrategy<T> hashingStrategy) {
+ if (hashingStrategy != canonicalStrategy()) {
+ throw new UnsupportedOperationException("Custom hashStrategy is not supported in java.util.concurrent.ConcurrentHashMap");
+ }
// ignoring strategy parameter, because it is not supported by this implementation
return createMap();
}
@@ -2064,6 +2108,9 @@
}
public <T, V> ConcurrentMap<T, V> createMap(int initialCapacity, float loadFactor, int concurrencyLevel, @NotNull TObjectHashingStrategy<T> hashingStrategy) {
+ if (hashingStrategy != canonicalStrategy()) {
+ throw new UnsupportedOperationException("Custom hashStrategy is not supported in java.util.concurrent.ConcurrentHashMap");
+ }
// ignoring strategy parameter, because it is not supported by this implementation
return createMap(initialCapacity, loadFactor, concurrencyLevel);
}
diff --git a/platform/util/src/com/intellij/util/containers/EmptyIntHashSet.java b/platform/util/src/com/intellij/util/containers/EmptyIntHashSet.java
new file mode 100644
index 0000000..7124164
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/EmptyIntHashSet.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.containers;
+
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
+import gnu.trove.TIntHashSet;
+import gnu.trove.TIntIterator;
+import gnu.trove.TIntProcedure;
+
+import java.util.NoSuchElementException;
+
+public class EmptyIntHashSet extends TIntHashSet {
+ public static final TIntHashSet INSTANCE = new EmptyIntHashSet();
+ public static final TIntIterator EMPTY_INT_ITERATOR = new TIntIterator(INSTANCE) {
+ @Override
+ public int next() {
+ throw new NoSuchElementException();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return false;
+ }
+
+ @Override
+ public void remove() {
+ throw new NoSuchElementException();
+ }
+ };
+
+ private EmptyIntHashSet() {
+ super(0);
+ }
+
+ @Override
+ public boolean add(int val) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public int[] toArray() {
+ return ArrayUtil.EMPTY_INT_ARRAY;
+ }
+
+ @Override
+ public TIntIterator iterator() {
+ return EMPTY_INT_ITERATOR;
+ }
+
+ @Override
+ public void clear() {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean remove(int val) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean containsAll(int[] array) {
+ return false;
+ }
+
+ @Override
+ public boolean addAll(int[] array) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean removeAll(int[] array) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean retainAll(int[] array) {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public boolean contains(int val) {
+ return false;
+ }
+
+ @Override
+ public boolean forEach(TIntProcedure procedure) {
+ return true;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return true;
+ }
+
+ @Override
+ public int size() {
+ return 0;
+ }
+
+ @Override
+ public void compact() {
+ throw new IncorrectOperationException();
+ }
+
+ @Override
+ public String toString() {
+ return "Empty Int Hash Set";
+ }
+}
diff --git a/platform/util/src/com/intellij/util/containers/FilteringIterator.java b/platform/util/src/com/intellij/util/containers/FilteringIterator.java
index 655d844..c6b7173 100644
--- a/platform/util/src/com/intellij/util/containers/FilteringIterator.java
+++ b/platform/util/src/com/intellij/util/containers/FilteringIterator.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,7 +17,7 @@
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Conditions;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Iterator;
@@ -132,7 +132,7 @@
}
public boolean isClassAcceptable(Class hintClass) {
- return ReflectionCache.isAssignable(myInstancesClass, hintClass);
+ return ReflectionUtil.isAssignable(myInstancesClass, hintClass);
}
public T cast(Object object) {
diff --git a/platform/util/src/com/intellij/util/containers/IntIntHashMap.java b/platform/util/src/com/intellij/util/containers/IntIntHashMap.java
new file mode 100644
index 0000000..7ba87fd
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/IntIntHashMap.java
@@ -0,0 +1,18 @@
+package com.intellij.util.containers;
+
+import gnu.trove.TIntIntHashMap;
+
+public final class IntIntHashMap extends TIntIntHashMap {
+ public IntIntHashMap(int initialCapacity) {
+ super(initialCapacity);
+ }
+
+ public IntIntHashMap() {
+ }
+
+ @Override
+ public int get(int key) {
+ int index = index(key);
+ return index < 0 ? -1 : _values[index];
+ }
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/containers/LinkedMultiMap.java b/platform/util/src/com/intellij/util/containers/LinkedMultiMap.java
index 2bc0dcd..8fce1e5 100644
--- a/platform/util/src/com/intellij/util/containers/LinkedMultiMap.java
+++ b/platform/util/src/com/intellij/util/containers/LinkedMultiMap.java
@@ -16,8 +16,9 @@
package com.intellij.util.containers;
+import com.intellij.util.containers.hash.LinkedHashMap;
+
import java.util.Collection;
-import java.util.LinkedHashMap;
import java.util.Map;
/**
diff --git a/platform/util/src/com/intellij/util/containers/LockFreeCopyOnWriteArrayList.java b/platform/util/src/com/intellij/util/containers/LockFreeCopyOnWriteArrayList.java
index 3bbf2b8..5376a92 100644
--- a/platform/util/src/com/intellij/util/containers/LockFreeCopyOnWriteArrayList.java
+++ b/platform/util/src/com/intellij/util/containers/LockFreeCopyOnWriteArrayList.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.
@@ -21,6 +21,7 @@
import com.intellij.util.concurrency.AtomicFieldUpdater;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import java.util.*;
@@ -33,7 +34,7 @@
* It generally is faster than COWAL in case of low write-contention.
* (Note that it is not advisable to use COWAL in high write-contention code anyway, consider using {@link ConcurrentHashMap}) instead)
*/
-class LockFreeCopyOnWriteArrayList<E> implements List<E>, RandomAccess {
+class LockFreeCopyOnWriteArrayList<E> implements List<E>, RandomAccess, ConcurrentList<E> {
@SuppressWarnings("FieldMayBeFinal")
private volatile Object[] array;
@@ -45,6 +46,7 @@
}
@NotNull
+ @TestOnly
Object[] getArray() {
return array;
}
@@ -500,7 +502,7 @@
* @param fromIndex index of first element to be removed
* @param toIndex index after last element to be removed
* @throws IndexOutOfBoundsException if fromIndex or toIndex out of range
- * ({@code{fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
+ * ({@code {fromIndex < 0 || toIndex > size() || toIndex < fromIndex})
*/
private void removeRange(int fromIndex, int toIndex) {
Object[] elements;
@@ -532,6 +534,7 @@
* @param e element to be added to this list, if absent
* @return <tt>true</tt> if the element was added
*/
+ @Override
public boolean addIfAbsent(E e) {
Object[] elements;
Object[] newElements;
@@ -679,6 +682,7 @@
* @throws NullPointerException if the specified collection is null
* @see #addIfAbsent(Object)
*/
+ @Override
public int addAllAbsent(@NotNull Collection<? extends E> c) {
Object[] cs = c.toArray();
if (cs.length == 0) {
@@ -826,7 +830,7 @@
* be the same if they have the same length and corresponding
* elements at the same position in the sequence are <em>equal</em>.
* Two elements {@code e1} and {@code e2} are considered
- * <em>equal</em> if {@code (e1==null ? e2==null : e1.equals(e2))}.
+ * <em>equal</em> if {@code (e1 == null ? e2 == null : e1.equals(e2))}.
*
* @param o the object to be compared for equality with this list
* @return {@code true} if the specified object is equal to this list
@@ -880,7 +884,7 @@
Object[] elements = array;
if (elements.length == 0) return EmptyIterator.getInstance();
- return new COWIterator<E>(elements, 0);
+ return new COWIterator(elements, 0);
}
/**
@@ -916,10 +920,10 @@
throw new IndexOutOfBoundsException("Index: " + index);
}
- return elements.length == 0 ? EmptyListIterator.<E>getInstance() : new COWIterator<E>(elements, index);
+ return elements.length == 0 ? EmptyListIterator.<E>getInstance() : new COWIterator(elements, index);
}
- private static class COWIterator<E> implements ListIterator<E> {
+ private class COWIterator implements ListIterator<E> {
/**
* Snapshot of the array
*/
@@ -928,6 +932,7 @@
* Index of element to be returned by subsequent call to next.
*/
private int cursor;
+ private int lastRet = -1; // index of last element returned; -1 if no such
private COWIterator(@NotNull Object[] elements, int initialCursor) {
cursor = initialCursor;
@@ -950,6 +955,7 @@
if (!hasNext()) {
throw new NoSuchElementException();
}
+ lastRet = cursor;
return (E)snapshot[cursor++];
}
@@ -974,7 +980,13 @@
@Override
public void remove() {
- throw new UnsupportedOperationException();
+ if (lastRet < 0) {
+ throw new IllegalStateException();
+ }
+ @SuppressWarnings("unchecked")
+ E e = (E)snapshot[lastRet];
+ lastRet = -1;
+ LockFreeCopyOnWriteArrayList.this.remove(e);
}
@Override
diff --git a/platform/util/src/com/intellij/util/containers/MultiMap.java b/platform/util/src/com/intellij/util/containers/MultiMap.java
index b4fb559..c7471c3 100644
--- a/platform/util/src/com/intellij/util/containers/MultiMap.java
+++ b/platform/util/src/com/intellij/util/containers/MultiMap.java
@@ -18,6 +18,7 @@
import com.intellij.util.SmartList;
import gnu.trove.THashMap;
+import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -25,6 +26,9 @@
import java.util.*;
/**
+ * Consider to use factory methods {@link #createLinked()}, {@link #createSet()}, {@link #createSmartList()}, {@link #create(gnu.trove.TObjectHashingStrategy)} instead of override.
+ * @see com.intellij.util.containers.BidirectionalMultiMap
+ * @see com.intellij.util.containers.ConcurrentMultiMap
* @author Dmitry Avdeev
*/
public class MultiMap<K, V> implements Serializable {
@@ -51,7 +55,7 @@
return new HashMap<K, Collection<V>>();
}
- protected Map<K, Collection<V>> createMap(int initialCapacity, float loadFactor) {
+ protected Map<K, Collection<V>> createMap(int initialCapacity, float loadFactor) {
return new HashMap<K, Collection<V>>(initialCapacity, loadFactor);
}
@@ -243,6 +247,26 @@
}
@NotNull
+ public static <K, V> MultiMap<K, V> create(@NotNull final TObjectHashingStrategy<K> strategy) {
+ return new MultiMap<K, V>() {
+ @Override
+ protected Map<K, Collection<V>> createMap() {
+ return new THashMap<K, Collection<V>>(strategy);
+ }
+
+ @Override
+ protected Collection<V> createCollection() {
+ return new SmartList<V>();
+ }
+ };
+ }
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createLinked() {
+ return new LinkedMultiMap<K, V>();
+ }
+
+ @NotNull
public static <K, V> MultiMap<K, V> createSmartList() {
return new MultiMap<K, V>() {
@Override
@@ -258,6 +282,26 @@
}
@NotNull
+ public static <K, V> MultiMap<K, V> createSet() {
+ return new MultiMap<K, V>() {
+ @Override
+ protected Collection<V> createCollection() {
+ return new SmartHashSet<V>();
+ }
+
+ @Override
+ protected Collection<V> createEmptyCollection() {
+ return Collections.emptySet();
+ }
+
+ @Override
+ protected Map<K, Collection<V>> createMap() {
+ return new THashMap<K, Collection<V>>();
+ }
+ };
+ }
+
+ @NotNull
public static <K, V> MultiMap<K, V> create(int i, float v) {
return new MultiMap<K, V>(i, v);
}
diff --git a/platform/util/src/com/intellij/util/containers/MultiMapBasedOnSet.java b/platform/util/src/com/intellij/util/containers/MultiMapBasedOnSet.java
index 800c412..0fefb79 100644
--- a/platform/util/src/com/intellij/util/containers/MultiMapBasedOnSet.java
+++ b/platform/util/src/com/intellij/util/containers/MultiMapBasedOnSet.java
@@ -15,10 +15,16 @@
*/
package com.intellij.util.containers;
-import java.util.*;
+import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+import java.util.Collections;
+
+@Deprecated
/**
* @author Sergey Evdokimov
+ * @deprecated Please use {@link MultiMap#createSet()}
+ * to remove in IDEA 15
*/
public class MultiMapBasedOnSet<K, V> extends MultiMap<K, V> {
@@ -31,4 +37,10 @@
protected Collection<V> createEmptyCollection() {
return Collections.emptySet();
}
+
+ @NotNull
+ public static <K, V> MultiMap<K, V> createBasedOnSet() {
+ return MultiMap.createSet();
+ }
+
}
diff --git a/platform/util/src/com/intellij/util/containers/OpenTHashSet.java b/platform/util/src/com/intellij/util/containers/OpenTHashSet.java
index 5834cb9..0785ca3 100644
--- a/platform/util/src/com/intellij/util/containers/OpenTHashSet.java
+++ b/platform/util/src/com/intellij/util/containers/OpenTHashSet.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.
diff --git a/platform/util/src/com/intellij/util/containers/OrderedSet.java b/platform/util/src/com/intellij/util/containers/OrderedSet.java
index ce03ffc..9900eb9 100644
--- a/platform/util/src/com/intellij/util/containers/OrderedSet.java
+++ b/platform/util/src/com/intellij/util/containers/OrderedSet.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,54 @@
*/
package com.intellij.util.containers;
+import com.intellij.util.IncorrectOperationException;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.util.*;
-public class OrderedSet<T> extends AbstractList<T> implements Set<T>, RandomAccess {
+// have to extend ArrayList because otherwise the spliterator() methods declared in Set and List are in conflict
+public class OrderedSet<T> extends ArrayList<T> implements Set<T>, RandomAccess {
private final OpenTHashSet<T> myHashSet;
- private final ArrayList<T> myElements;
public OrderedSet() {
this(ContainerUtil.<T>canonicalStrategy());
}
- public OrderedSet(TObjectHashingStrategy<T> hashingStrategy) {
+ public OrderedSet(@NotNull TObjectHashingStrategy<T> hashingStrategy) {
this(hashingStrategy, 4);
}
- public OrderedSet(TObjectHashingStrategy<T> hashingStrategy, int capacity) {
+ public OrderedSet(@NotNull TObjectHashingStrategy<T> hashingStrategy, int capacity) {
+ super(capacity);
myHashSet = new OpenTHashSet<T>(capacity, hashingStrategy);
- myElements = new ArrayList<T>(capacity);
}
@Override
- public int size() {
- return myElements.size();
+ public boolean removeAll(@NotNull Collection<?> c) {
+ boolean removed = false;
+ for (Object o : c) {
+ removed |= remove(o);
+ }
+ return removed;
+ }
+
+ @Override
+ public boolean retainAll(@NotNull Collection<?> c) {
+ boolean removed = false;
+ for (int i = size() - 1; i >= 0; i--) {
+ Object o = get(i);
+ if (!c.contains(o)) {
+ removed |= remove(o);
+ }
+ }
+ return removed;
+ }
+
+ @NotNull
+ @Override
+ public List<T> subList(int fromIndex, int toIndex) {
+ throw new IncorrectOperationException();
}
@Override
@@ -48,9 +71,18 @@
}
@Override
+ public boolean addAll(@NotNull Collection<? extends T> c) {
+ boolean result = false;
+ for (T t : c) {
+ result |= add(t);
+ }
+ return result;
+ }
+
+ @Override
public boolean add(T o) {
if (myHashSet.add(o)){
- myElements.add(o);
+ super.add(o);
return true;
}
return false;
@@ -59,7 +91,7 @@
@Override
public boolean remove(Object o) {
if (myHashSet.remove(o)){
- myElements.remove(o);
+ super.remove(o);
return true;
}
return false;
@@ -68,19 +100,7 @@
@Override
public void clear() {
myHashSet.clear();
- myElements.clear();
- }
-
- @NotNull
- @Override
- public Object[] toArray() {
- return myElements.toArray();
- }
-
- @NotNull
- @Override
- public <T> T[] toArray(@NotNull T[] a) {
- return myElements.toArray(a);
+ super.clear();
}
@Override
@@ -89,11 +109,6 @@
}
@Override
- public T get(final int index) {
- return myElements.get(index);
- }
-
- @Override
public T set(final int index, final T element) {
final T removed = remove(index);
add(index, element);
@@ -103,13 +118,13 @@
@Override
public void add(final int index, final T element) {
if (myHashSet.add(element)){
- myElements.add(index, element);
+ super.add(index, element);
}
}
@Override
public T remove(final int index) {
- final T t = myElements.remove(index);
+ final T t = super.remove(index);
myHashSet.remove(t);
return t;
}
@@ -117,24 +132,12 @@
@Override
public int indexOf(final Object o) {
final int index = myHashSet.index((T)o);
- return index >= 0? myElements.indexOf(myHashSet.get(index)) : -1;
+ return index >= 0? super.indexOf(myHashSet.get(index)) : -1;
}
@Override
public int lastIndexOf(final Object o) {
final int index = myHashSet.index((T)o);
- return index >= 0 ? myElements.lastIndexOf(myHashSet.get(index)) : -1;
- }
-
- @NotNull
- @Override
- public ListIterator<T> listIterator() {
- return myElements.listIterator();
- }
-
- @NotNull
- @Override
- public ListIterator<T> listIterator(final int index) {
- return myElements.listIterator(index);
+ return index >= 0 ? super.lastIndexOf(myHashSet.get(index)) : -1;
}
}
diff --git a/platform/util/src/com/intellij/util/containers/SequenceIterator.java b/platform/util/src/com/intellij/util/containers/SequenceIterator.java
index b0bbeff..35e7b83 100644
--- a/platform/util/src/com/intellij/util/containers/SequenceIterator.java
+++ b/platform/util/src/com/intellij/util/containers/SequenceIterator.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.
diff --git a/platform/util/src/com/intellij/util/containers/SingletonIterator.java b/platform/util/src/com/intellij/util/containers/SingletonIterator.java
index 2749b01..2cc8319 100644
--- a/platform/util/src/com/intellij/util/containers/SingletonIterator.java
+++ b/platform/util/src/com/intellij/util/containers/SingletonIterator.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,26 +17,19 @@
import com.intellij.util.IncorrectOperationException;
-import java.util.Iterator;
-import java.util.NoSuchElementException;
-
-public class SingletonIterator<T> implements Iterator<T> {
+public class SingletonIterator<T> extends SingletonIteratorBase<T> {
private final T myElement;
- private boolean myVisited;
public SingletonIterator(T element) {
myElement = element;
}
@Override
- public boolean hasNext() {
- return !myVisited;
+ protected void checkCoModification() {
}
@Override
- public T next() {
- if (myVisited) throw new NoSuchElementException();
- myVisited = true;
+ protected T getElement() {
return myElement;
}
diff --git a/platform/util/src/com/intellij/util/containers/SingletonIteratorBase.java b/platform/util/src/com/intellij/util/containers/SingletonIteratorBase.java
new file mode 100644
index 0000000..ac044b0
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/SingletonIteratorBase.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.containers;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+public abstract class SingletonIteratorBase<T> implements Iterator<T> {
+ private boolean myVisited;
+
+ @Override
+ public final boolean hasNext() {
+ return !myVisited;
+ }
+
+ @Override
+ public final T next() {
+ if (myVisited) {
+ throw new NoSuchElementException();
+ }
+ myVisited = true;
+ checkCoModification();
+ return getElement();
+ }
+
+ protected abstract void checkCoModification();
+
+ protected abstract T getElement();
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/containers/SmartHashSet.java b/platform/util/src/com/intellij/util/containers/SmartHashSet.java
new file mode 100644
index 0000000..dc68fc0
--- /dev/null
+++ b/platform/util/src/com/intellij/util/containers/SmartHashSet.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.containers;
+
+import gnu.trove.THashSet;
+import gnu.trove.TObjectHashingStrategy;
+import gnu.trove.TObjectProcedure;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.Set;
+
+/**
+ * Hash set (based on THashSet) which is fast when contains one or zero elements (avoids to calculate hash codes and call equals whenever possible).
+ * For other sizes it delegates to THashSet.
+ * Null keys are NOT PERMITTED.
+ */
+public class SmartHashSet<T> extends THashSet<T> {
+ private T theElement; // contains the only element if size() == 1
+
+ public SmartHashSet() {
+ }
+
+ public SmartHashSet(@NotNull TObjectHashingStrategy<T> strategy) {
+ super(strategy);
+ }
+
+ public SmartHashSet(int initialCapacity) {
+ super(initialCapacity);
+ }
+
+ public SmartHashSet(int initialCapacity, TObjectHashingStrategy<T> strategy) {
+ super(initialCapacity, strategy);
+ }
+
+ public SmartHashSet(int initialCapacity, float loadFactor) {
+ super(initialCapacity, loadFactor);
+ }
+
+ public SmartHashSet(int initialCapacity, float loadFactor, TObjectHashingStrategy<T> strategy) {
+ super(initialCapacity, loadFactor, strategy);
+ }
+
+ public SmartHashSet(Collection<? extends T> collection) {
+ super(collection);
+ }
+
+ public SmartHashSet(Collection<? extends T> collection, TObjectHashingStrategy<T> strategy) {
+ super(collection, strategy);
+ }
+
+ @Override
+ public boolean contains(@NotNull Object obj) {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ return eq(theElement, (T)obj);
+ }
+ return !super.isEmpty() && super.contains(obj);
+ }
+
+ @Override
+ public boolean add(@NotNull T obj) {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ if (eq(theElement, obj)) return false;
+ super.add(theElement);
+ this.theElement = null;
+ // fallthrough
+ }
+ else if (super.isEmpty()) {
+ this.theElement = obj;
+ return true;
+ }
+ return super.add(obj);
+ }
+
+ private boolean eq(T obj, T theElement) {
+ return theElement == obj || _hashingStrategy.equals(theElement, obj);
+ }
+
+ @Override
+ public boolean equals(@NotNull Object other) {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ return other instanceof Set && ((Set)other).size() == 1 && eq(theElement, (T)((Set)other).iterator().next());
+ }
+
+ return super.equals(other);
+ }
+
+ @Override
+ public int hashCode() {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ return _hashingStrategy.computeHashCode(theElement);
+ }
+ return super.hashCode();
+ }
+
+ @Override
+ public void clear() {
+ theElement = null;
+ super.clear();
+ }
+
+ @Override
+ public int size() {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ return 1;
+ }
+ return super.size();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ T theElement = this.theElement;
+ return theElement == null && super.isEmpty();
+ }
+
+ @Override
+ public boolean remove(@NotNull Object obj) {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ if (eq(theElement, (T)obj)) {
+ this.theElement = null;
+ return true;
+ }
+ return false;
+ }
+ return super.remove(obj);
+ }
+
+ @NotNull
+ @Override
+ public Iterator<T> iterator() {
+ if (theElement != null) {
+ return new SingletonIteratorBase<T>() {
+ @Override
+ protected void checkCoModification() {
+ if (theElement == null) {
+ throw new ConcurrentModificationException();
+ }
+ }
+
+ @Override
+ protected T getElement() {
+ return theElement;
+ }
+
+ @Override
+ public void remove() {
+ checkCoModification();
+ clear();
+ }
+ };
+ }
+ return super.iterator();
+ }
+
+ @Override
+ public boolean forEach(@NotNull TObjectProcedure<T> procedure) {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ return procedure.execute(theElement);
+ }
+ return super.forEach(procedure);
+ }
+
+ @NotNull
+ @Override
+ public Object[] toArray() {
+ T theElement = this.theElement;
+ if (theElement != null) {
+ return new Object[]{theElement};
+ }
+ return super.toArray();
+ }
+
+ @NotNull
+ @Override
+ public <T> T[] toArray(@NotNull T[] a) {
+ T theElement = (T)this.theElement;
+ if (theElement != null) {
+ if (a.length == 0) {
+ a = (T[]) Array.newInstance(a.getClass().getComponentType(), 1);
+ }
+ a[0] = theElement;
+ if (a.length > 1) {
+ a[1] = null;
+ }
+ return a;
+ }
+ return super.toArray(a);
+ }
+
+}
diff --git a/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java b/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java
index 17ba065..3a620a8 100644
--- a/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java
+++ b/platform/util/src/com/intellij/util/containers/SoftFactoryMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -31,17 +31,15 @@
public final V get(T key) {
final SoftReference<V> reference = myMap.get(key);
- if (reference != null) {
- final V v = reference.get();
- if (v != null) {
- return v == NULL ? null : v;
- }
+ final V v = com.intellij.reference.SoftReference.dereference(reference);
+ if (v != null) {
+ return v == NULL ? null : v;
}
final V value = create(key);
SoftReference<V> valueRef = new SoftReference<V>(value == null ? (V)NULL : value);
SoftReference<V> prevRef = myMap.putIfAbsent(key, valueRef);
- V prev = prevRef == null ? null : prevRef.get();
+ V prev = com.intellij.reference.SoftReference.dereference(prevRef);
return prev == null || prev == NULL ? value : prev;
}
diff --git a/platform/util/src/com/intellij/util/containers/SoftKeySoftValueHashMap.java b/platform/util/src/com/intellij/util/containers/SoftKeySoftValueHashMap.java
index f5398d5..076ecd7 100644
--- a/platform/util/src/com/intellij/util/containers/SoftKeySoftValueHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/SoftKeySoftValueHashMap.java
@@ -50,8 +50,7 @@
@Override
public V get(Object key) {
MyValueReference<K,V> ref = mySoftKeyMap.get(key);
- if (ref == null) return null;
- return ref.get();
+ return com.intellij.reference.SoftReference.dereference(ref);
}
@Override
@@ -60,14 +59,14 @@
SoftHashMap.Key<K> softKey = mySoftKeyMap.createKey(key);
MyValueReference<K, V> reference = new MyValueReference<K, V>(softKey, value, myQueue);
MyValueReference<K,V> oldRef = mySoftKeyMap.putKey(softKey, reference);
- return oldRef == null ? null : oldRef.get();
+ return com.intellij.reference.SoftReference.dereference(oldRef);
}
@Override
public V remove(Object key) {
processQueue();
MyValueReference<K,V> ref = mySoftKeyMap.remove(key);
- return ref != null ? ref.get() : null;
+ return com.intellij.reference.SoftReference.dereference(ref);
}
@Override
diff --git a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java
index 565311e..787ebc3 100644
--- a/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java
+++ b/platform/util/src/com/intellij/util/containers/TransferToEDTQueue.java
@@ -72,6 +72,16 @@
myShutUpCondition = shutUpCondition;
myMaxUnitOfWorkThresholdMs = maxUnitOfWorkThresholdMs;
}
+
+ public static TransferToEDTQueue<Runnable> createRunnableMerger(@NotNull @NonNls String name, int maxUnitOfWorkThresholdMs) {
+ return new TransferToEDTQueue<Runnable>(name, new Processor<Runnable>() {
+ @Override
+ public boolean process(Runnable runnable) {
+ runnable.run();
+ return true;
+ }
+ }, Condition.FALSE, maxUnitOfWorkThresholdMs);
+ }
private boolean isEmpty() {
synchronized (myQueue) {
diff --git a/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java b/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java
index d2b71e2..7be7ad6 100644
--- a/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java
+++ b/platform/util/src/com/intellij/util/containers/UnsafeWeakList.java
@@ -16,6 +16,7 @@
package com.intellij.util.containers;
import com.intellij.openapi.util.Condition;
+import com.intellij.reference.SoftReference;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -159,8 +160,7 @@
nextElement = null;
nextIndex = -1;
for (int i= curIndex +1; i<myList.size();i++) {
- MyReference<T> reference = myList.get(i);
- T t = reference == null ? null : reference.get();
+ T t = SoftReference.dereference(myList.get(i));
if (t != null) {
nextElement = t;
nextIndex = i;
@@ -194,8 +194,7 @@
public boolean remove(@NotNull Object o) {
processQueue();
for (int i = 0; i < myList.size(); i++) {
- MyReference<T> reference = myList.get(i);
- T t = reference == null ? null : reference.get();
+ T t = SoftReference.dereference(myList.get(i));
if (t != null && t.equals(o)) {
nullizeAt(i);
return true;
@@ -219,10 +218,10 @@
private static final Function<MyReference<Object>, Object> DEREF = new Function<MyReference<Object>, Object>() {
@Override
public Object fun(MyReference<Object> reference) {
- return reference == null ? null : reference.get();
+ return SoftReference.dereference(reference);
}
};
- private static <T> Function<MyReference<T>, T> deref() {
+ private static <X> Function<MyReference<X>, X> deref() {
return (Function)DEREF;
}
@NotNull
@@ -250,7 +249,7 @@
private static final Condition<MyReference<Object>> NOT_NULL = new Condition<MyReference<Object>>() {
@Override
public boolean value(MyReference<Object> reference) {
- return reference != null && reference.get() != null;
+ return SoftReference.dereference(reference) != null;
}
};
diff --git a/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java b/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java
index 2df74cd..eee100e 100644
--- a/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java
+++ b/platform/util/src/com/intellij/util/containers/WeakFactoryMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,6 +15,8 @@
*/
package com.intellij.util.containers;
+import com.intellij.reference.SoftReference;
+
import java.lang.ref.WeakReference;
import java.util.concurrent.ConcurrentMap;
@@ -30,17 +32,15 @@
public final V get(T key) {
final WeakReference<V> reference = myMap.get(key);
- if (reference != null) {
- final V v = reference.get();
- if (v != null) {
- return v == NULL ? null : v;
- }
+ final V v = SoftReference.dereference(reference);
+ if (v != null) {
+ return v == NULL ? null : v;
}
final V value = create(key);
WeakReference<V> valueRef = new WeakReference<V>(value == null ? (V)NULL : value);
WeakReference<V> prevRef = myMap.putIfAbsent(key, valueRef);
- V prev = prevRef == null ? null : prevRef.get();
+ V prev = SoftReference.dereference(prevRef);
return prev == null || prev == NULL ? value : prev;
}
diff --git a/platform/util/src/com/intellij/util/containers/WeakKeyWeakValueHashMap.java b/platform/util/src/com/intellij/util/containers/WeakKeyWeakValueHashMap.java
index 84eacc1..ed0e001 100644
--- a/platform/util/src/com/intellij/util/containers/WeakKeyWeakValueHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/WeakKeyWeakValueHashMap.java
@@ -15,6 +15,7 @@
*/
package com.intellij.util.containers;
+import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -50,8 +51,7 @@
@Override
public V get(Object key) {
MyValueReference<K,V> ref = myWeakKeyMap.get(key);
- if (ref == null) return null;
- return ref.get();
+ return SoftReference.dereference(ref);
}
@Override
@@ -60,14 +60,14 @@
WeakHashMap.Key<K> weakKey = myWeakKeyMap.createKey(key);
MyValueReference<K, V> reference = new MyValueReference<K, V>(weakKey, value, myQueue);
MyValueReference<K,V> oldRef = myWeakKeyMap.putKey(weakKey, reference);
- return oldRef == null ? null : oldRef.get();
+ return SoftReference.dereference(oldRef);
}
@Override
public V remove(Object key) {
processQueue();
MyValueReference<K,V> ref = myWeakKeyMap.remove(key);
- return ref != null ? ref.get() : null;
+ return SoftReference.dereference(ref);
}
@Override
diff --git a/platform/util/src/com/intellij/util/containers/WeakValueIntObjectHashMap.java b/platform/util/src/com/intellij/util/containers/WeakValueIntObjectHashMap.java
index e58460a..b3731e2 100644
--- a/platform/util/src/com/intellij/util/containers/WeakValueIntObjectHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/WeakValueIntObjectHashMap.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -15,6 +15,7 @@
*/
package com.intellij.util.containers;
+import com.intellij.reference.SoftReference;
import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
@@ -56,8 +57,7 @@
public final V get(int key) {
MyReference<V> ref = myMap.get(key);
- if (ref == null) return null;
- return ref.get();
+ return SoftReference.dereference(ref);
}
public final V put(int key, @NotNull V value) {
@@ -65,13 +65,13 @@
MyReference<V> ref = new MyReference<V>(key, value, myQueue);
ref.name = value.toString();
MyReference<V> oldRef = myMap.put(key, ref);
- return oldRef != null ? oldRef.get() : null;
+ return SoftReference.dereference(oldRef);
}
public final V remove(int key) {
processQueue();
MyReference<V> ref = myMap.remove(key);
- return ref != null ? ref.get() : null;
+ return SoftReference.dereference(ref);
}
public final void clear() {
diff --git a/platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java b/platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java
index 138997f..2b44e52 100644
--- a/platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java
+++ b/platform/util/src/com/intellij/util/containers/hash/EqualityPolicy.java
@@ -16,6 +16,8 @@
package com.intellij.util.containers.hash;
+import gnu.trove.TObjectHashingStrategy;
+
public interface EqualityPolicy<T> {
EqualityPolicy<?> IDENTITY = new EqualityPolicy() {
@@ -42,6 +44,24 @@
return val1 != null ? val1.equals(val2) : val2 == null;
}
};
+
+ class ByHashingStrategy<T> implements EqualityPolicy<T> {
+ private final TObjectHashingStrategy<T> myStrategy;
+
+ public ByHashingStrategy(TObjectHashingStrategy<T> strategy) {
+ myStrategy = strategy;
+ }
+
+ @Override
+ public int getHashCode(T value) {
+ return myStrategy.computeHashCode(value);
+ }
+
+ @Override
+ public boolean isEqual(T val1, T val2) {
+ return myStrategy.equals(val1, val2);
+ }
+ }
int getHashCode(T value);
diff --git a/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java b/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java
index d50bc4e..c0ad258 100644
--- a/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java
+++ b/platform/util/src/com/intellij/util/containers/hash/LinkedHashMap.java
@@ -50,7 +50,7 @@
this(capacity, loadFactor, (EqualityPolicy)EqualityPolicy.CANONICAL, accessOrder);
}
- public LinkedHashMap(EqualityPolicy hashingStrategy) {
+ public LinkedHashMap(EqualityPolicy<K> hashingStrategy) {
this(0, HashUtil.DEFAULT_LOAD_FACTOR, hashingStrategy);
}
@@ -310,7 +310,7 @@
private abstract class LinkedHashIterator<T> implements Iterator<T> {
- private LinkedHashMap.Entry<K, V> e = top;
+ private LinkedHashMap.Entry<K, V> e = back;
private LinkedHashMap.Entry<K, V> last;
@Override
@@ -329,7 +329,7 @@
protected LinkedHashMap.Entry<K, V> nextEntry() {
final LinkedHashMap.Entry<K, V> result = last = e;
- e = result.next;
+ e = result.previous;
return result;
}
}
diff --git a/platform/util/src/com/intellij/util/diff/Diff.java b/platform/util/src/com/intellij/util/diff/Diff.java
index d5d9688..d41175f 100644
--- a/platform/util/src/com/intellij/util/diff/Diff.java
+++ b/platform/util/src/com/intellij/util/diff/Diff.java
@@ -16,6 +16,7 @@
package com.intellij.util.diff;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.LineTokenizer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Enumerator;
@@ -24,6 +25,7 @@
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
+import java.util.BitSet;
/**
* @author dyoma
@@ -49,15 +51,41 @@
final int startShift = getStartShift(objects1, objects2);
final int endCut = getEndCut(objects1, objects2, startShift);
+ ChangeBuilder builder = new ChangeBuilder(startShift);
+ int trimmedLength1 = objects1.length - startShift - endCut;
+ int trimmedLength2 = objects2.length - startShift - endCut;
+ if (trimmedLength1 == 0 || trimmedLength2 == 0) {
+ if (trimmedLength1 != 0 || trimmedLength2 != 0) {
+ builder.addChange(trimmedLength1, trimmedLength2);
+ }
+ return builder.getFirstChange();
+ }
+
Enumerator<T> enumerator = new Enumerator<T>(objects1.length + objects2.length, ContainerUtil.<T>canonicalStrategy());
int[] ints1 = enumerator.enumerate(objects1, startShift, endCut);
int[] ints2 = enumerator.enumerate(objects2, startShift, endCut);
- Reindexer reindexer = new Reindexer();
+ Reindexer reindexer = new Reindexer(); // discard unique elements, that have no chance to be matched
int[][] discarded = reindexer.discardUnique(ints1, ints2);
- IntLCS intLCS = new IntLCS(discarded[0], discarded[1]);
- intLCS.execute();
- ChangeBuilder builder = new ChangeBuilder(startShift);
- reindexer.reindex(intLCS.getPaths(), builder);
+
+ if (discarded[0].length == 0 && discarded[1].length == 0) {
+ // assert trimmedLength > 0
+ builder.addChange(ints1.length, ints2.length);
+ return builder.getFirstChange();
+ }
+
+ BitSet[] changes;
+ if (Registry.is("diff.patience.alg")) {
+ PatienceIntLCS patienceIntLCS = new PatienceIntLCS(discarded[0], discarded[1]);
+ patienceIntLCS.execute();
+ changes = patienceIntLCS.getChanges();
+ }
+ else {
+ IntLCS intLCS = new IntLCS(discarded[0], discarded[1]);
+ intLCS.execute();
+ changes = intLCS.getChanges();
+ }
+
+ reindexer.reindex(changes, builder);
return builder.getFirstChange();
}
diff --git a/platform/util/src/com/intellij/util/diff/IntLCS.java b/platform/util/src/com/intellij/util/diff/IntLCS.java
index 1a65294..7fc7162 100644
--- a/platform/util/src/com/intellij/util/diff/IntLCS.java
+++ b/platform/util/src/com/intellij/util/diff/IntLCS.java
@@ -16,6 +16,7 @@
package com.intellij.util.diff;
import java.util.Arrays;
+import java.util.BitSet;
/**
* @author dyoma
@@ -24,6 +25,9 @@
private final int[] myFirst;
private final int[] mySecond;
+ private final int myStart1;
+ private final int myStart2;
+
private final LinkedDiffPaths myPathsMatrix;
private final int[] myPrevPathKey;
private int[] myPrevEnds;
@@ -31,11 +35,23 @@
private final int myMaxX;
private final int myMaxY;
+ private final BitSet myChanges1;
+ private final BitSet myChanges2;
+
public IntLCS(int[] first, int[] second) {
+ this(first, second, 0, first.length, 0, second.length, new BitSet(first.length), new BitSet(second.length));
+ }
+
+ public IntLCS(int[] first, int[] second, int start1, int count1, int start2, int count2, BitSet changes1, BitSet changes2) {
myFirst = first;
mySecond = second;
- myMaxX = myFirst.length;
- myMaxY = mySecond.length;
+ myStart1 = start1;
+ myStart2 = start2;
+ myMaxX = count1;
+ myMaxY = count2;
+
+ myChanges1 = changes1;
+ myChanges2 = changes2;
myPathsMatrix = new LinkedDiffPaths(myMaxX, myMaxY);
myPrevPathKey = new int[myMaxX + myMaxY + 1];
@@ -82,7 +98,10 @@
}
}
myCurrentEnds[k + myMaxY] = end;
- if (k == myMaxX - myMaxY && end == myMaxX) return d;
+ if (k == myMaxX - myMaxY && end == myMaxX) {
+ myPathsMatrix.applyChanges(myStart1, myStart2, myChanges1, myChanges2);
+ return d;
+ }
}
int[] temps = myCurrentEnds;
myCurrentEnds = myPrevEnds;
@@ -91,8 +110,8 @@
throw new RuntimeException();
}
- public LinkedDiffPaths getPaths() {
- return myPathsMatrix;
+ public BitSet[] getChanges() {
+ return new BitSet[]{myChanges1, myChanges2};
}
private int findDiagonalEnd(int prevDiagonal, int prevEnd, boolean isVertical) {
@@ -122,7 +141,7 @@
private int skipEquals(int x, int y) {
int skipped = 0;
- while (x < myMaxX && y < myMaxY && myFirst[x] == mySecond[y]) {
+ while (x < myMaxX && y < myMaxY && myFirst[myStart1 + x] == mySecond[myStart2 + y]) {
skipped += 1;
x++;
y++;
diff --git a/platform/util/src/com/intellij/util/diff/LinkedDiffPaths.java b/platform/util/src/com/intellij/util/diff/LinkedDiffPaths.java
index 21eea48..bc75820 100644
--- a/platform/util/src/com/intellij/util/diff/LinkedDiffPaths.java
+++ b/platform/util/src/com/intellij/util/diff/LinkedDiffPaths.java
@@ -15,6 +15,8 @@
*/
package com.intellij.util.diff;
+import java.util.BitSet;
+
/**
* @author dyoma
*/
@@ -30,10 +32,38 @@
private static final int DISTANCE_MASK = ~VERTICAL_DIRECTION_FLAG;
public LinkedDiffPaths(int maxX, int maxY) {
- myMaxX = maxX-1;
- myMaxY = maxY-1;
+ myMaxX = maxX;
+ myMaxY = maxY;
}
+ public void applyChanges(final int start1, final int start2, final BitSet changes1, final BitSet changes2) {
+ decodePath(new LCSBuilder() {
+ int x = myMaxX;
+ int y = myMaxY;
+
+ @Override
+ public void addEqual(int length) {
+ x -= length;
+ y -= length;
+ }
+
+ @Override
+ public void addChange(int first, int second) {
+ if (first > 0) {
+ changes1.set(start1 + x - first, start1 + x);
+ x -= first;
+ }
+ if (second > 0) {
+ changes2.set(start2 + y - second, start2 + y);
+ y -= second;
+ }
+ }
+ });
+ }
+
+ /**
+ * Path is decoded in reverse order (from the last change to the first)
+ */
public <Builder extends LCSBuilder> Builder decodePath(Builder builder) {
Decoder decoder = new Decoder(getXSize(), getYSize(), builder);
int index = myCornerIndex;
@@ -47,11 +77,11 @@
}
public int getXSize() {
- return myMaxX + 1;
+ return myMaxX;
}
public int getYSize() {
- return myMaxY + 1;
+ return myMaxY;
}
public int encodeStep(int x, int y, int diagLength, boolean afterVertical, int prevIndex) throws FilesTooBigForDiffException {
@@ -61,7 +91,7 @@
myPrevSteps[position] = prevIndex;
mySteps[position] = encodedPath;
- if (x == myMaxX && y == myMaxY) myCornerIndex = position;
+ if (x == myMaxX - 1 && y == myMaxY - 1) myCornerIndex = position;
return position;
}
diff --git a/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java b/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java
new file mode 100644
index 0000000..8f04dfa
--- /dev/null
+++ b/platform/util/src/com/intellij/util/diff/PatienceIntLCS.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diff;
+
+import java.util.BitSet;
+
+public class PatienceIntLCS {
+ private final int[] myFirst;
+ private final int[] mySecond;
+
+ private final int myStart1;
+ private final int myStart2;
+ private final int myCount1;
+ private final int myCount2;
+
+ private final BitSet myChanges1;
+ private final BitSet myChanges2;
+
+ public PatienceIntLCS(int[] first, int[] second) {
+ this(first, second, 0, first.length, 0, second.length, new BitSet(first.length), new BitSet(second.length));
+ }
+
+ public PatienceIntLCS(int[] first, int[] second, int start1, int count1, int start2, int count2, BitSet changes1, BitSet changes2) {
+ myFirst = first;
+ mySecond = second;
+ myStart1 = start1;
+ myStart2 = start2;
+ myCount1 = count1;
+ myCount2 = count2;
+
+ myChanges1 = changes1;
+ myChanges2 = changes2;
+ }
+
+ public void execute() throws FilesTooBigForDiffException {
+ if (myCount1 == 0 && myCount2 == 0) {
+ return;
+ }
+
+ if (myCount1 == 0 || myCount2 == 0) {
+ addChange(myStart1, myCount1, myStart2, myCount2);
+ return;
+ }
+
+ int startOffset = matchForward(0, 0);
+ int start1 = myStart1 + startOffset;
+ int start2 = myStart2 + startOffset;
+
+ int endOffset = matchBackward(myStart1 + myCount1 - 1, myStart2 + myCount2 - 1, start1, start2);
+ int count1 = myCount1 - startOffset - endOffset;
+ int count2 = myCount2 - startOffset - endOffset;
+
+ if (count1 == 0 || count2 == 0) {
+ addChange(start1, count1, start2, count2);
+ }
+ else {
+ UniqueLCS uniqueLCS = new UniqueLCS(myFirst, mySecond, start1, count1, start2, count2);
+ int[][] matching = uniqueLCS.execute();
+
+ if (matching == null) {
+ IntLCS intLCS = new IntLCS(myFirst, mySecond, start1, count1, start2, count2, myChanges1, myChanges2);
+ intLCS.execute();
+ }
+ else {
+ int s1, s2, c1, c2;
+ int matched = matching[0].length;
+ assert matched > 0;
+
+ PatienceIntLCS patienceDiff =
+ new PatienceIntLCS(myFirst, mySecond, start1, matching[0][0], start2, matching[1][0], myChanges1, myChanges2);
+ patienceDiff.execute();
+
+ for (int i = 1; i < matching[0].length; i++) {
+ s1 = matching[0][i - 1] + 1;
+ s2 = matching[1][i - 1] + 1;
+
+ c1 = matching[0][i] - s1;
+ c2 = matching[1][i] - s2;
+
+ if (c1 > 0 || c2 > 0) {
+ patienceDiff = new PatienceIntLCS(myFirst, mySecond, start1 + s1, c1, start2 + s2, c2, myChanges1, myChanges2);
+ patienceDiff.execute();
+ }
+ }
+
+ if (matching[0][matched - 1] == count1 - 1) {
+ s1 = count1 - 1;
+ c1 = 0;
+ }
+ else {
+ s1 = matching[0][matched - 1] + 1;
+ c1 = count1 - s1;
+ }
+ if (matching[1][matched - 1] == count2 - 1) {
+ s2 = count2 - 1;
+ c2 = 0;
+ }
+ else {
+ s2 = matching[1][matched - 1] + 1;
+ c2 = count2 - s2;
+ }
+
+ patienceDiff = new PatienceIntLCS(myFirst, mySecond, start1 + s1, c1, start2 + s2, c2, myChanges1, myChanges2);
+ patienceDiff.execute();
+ }
+ }
+ }
+
+ private int matchForward(int offset1, int offset2) {
+ final int size = Math.min(myCount1 - offset1, myCount2 - offset2);
+ int idx = 0;
+ for (int i = 0; i < size; i++) {
+ if (!(myFirst[offset1 + i] == mySecond[offset2 + i])) break;
+ ++idx;
+ }
+ return idx;
+ }
+
+ private int matchBackward(int offset1, int offset2, int processedOffset1, int processedOffset2) {
+ final int size = Math.min(offset1 - processedOffset1 - 1, offset2 - processedOffset2 - 1);
+ int idx = 0;
+ for (int i = 0; i < size; i++) {
+ if (!(myFirst[offset1 - i] == mySecond[offset2 - i])) break;
+ ++idx;
+ }
+ return idx;
+ }
+
+ public void addChange(int start1, int count1, int start2, int count2) {
+ myChanges1.set(start1, start1 + count1);
+ myChanges2.set(start2, start2 + count2);
+ }
+
+ public BitSet[] getChanges() {
+ return new BitSet[]{myChanges1, myChanges2};
+ }
+}
diff --git a/platform/util/src/com/intellij/util/diff/Reindexer.java b/platform/util/src/com/intellij/util/diff/Reindexer.java
index c390e69..e30849e 100644
--- a/platform/util/src/com/intellij/util/diff/Reindexer.java
+++ b/platform/util/src/com/intellij/util/diff/Reindexer.java
@@ -18,6 +18,7 @@
import gnu.trove.TIntArrayList;
import java.util.Arrays;
+import java.util.BitSet;
/**
* @author dyoma
@@ -25,6 +26,7 @@
class Reindexer {
private final int[][] myOldIndecies = new int[2][];
private final int[] myOriginalLengths = new int[]{-1, -1};
+ private final int[] myDiscardedLengths = new int[]{-1, -1};
public int[][] discardUnique(int[] ints1, int[] ints2) {
int[] discarded1 = discard(ints2, ints1, 0);
@@ -34,6 +36,8 @@
void idInit(int length1, int length2) {
myOriginalLengths[0] = length1;
myOriginalLengths[1] = length2;
+ myDiscardedLengths[0] = length1;
+ myDiscardedLengths[1] = length2;
for (int j = 0; j < 2; j++) {
int originalLength = myOriginalLengths[j];
myOldIndecies[j] = new int[originalLength];
@@ -59,6 +63,7 @@
}
}
myOldIndecies[arrayIndex] = oldIndecies.toNativeArray();
+ myDiscardedLengths[arrayIndex] = discarded.size();
return discarded.toNativeArray();
}
@@ -69,67 +74,77 @@
return sorted1;
}
- public void reindex(LinkedDiffPaths paths, LCSBuilder builder) {
- final boolean[] changes1 = new boolean[myOriginalLengths[0]];
- final boolean[] changes2 = new boolean[myOriginalLengths[1]];
- Arrays.fill(changes1, true);
- Arrays.fill(changes2, true);
- paths.decodePath(new LCSBuilder() {
- private int x = myOldIndecies[0].length - 1;
- private int y = myOldIndecies[1].length - 1;
- private int originalX = myOriginalLengths[0] - 1;
- private int originalY = myOriginalLengths[1] - 1;
+ public void reindex(BitSet[] discardedChanges, LCSBuilder builder) {
+ BitSet changes1 = new BitSet(myOriginalLengths[0]);
+ BitSet changes2 = new BitSet(myOriginalLengths[1]);
- @Override
- public void addChange(int first, int second) {
- x -= first;
- y -= second;
- originalX = markChanged(changes1, originalX, myOldIndecies[0], x);
- originalY = markChanged(changes2, originalY, myOldIndecies[1], y);
- }
-
- @Override
- public void addEqual(int length) {
- for (int i = length; i > 0; i--) {
- originalX = markChanged(changes1, originalX, myOldIndecies[0], x);
- originalY = markChanged(changes2, originalY, myOldIndecies[1], y);
- x--;
- y--;
- changes1[originalX] = false;
- changes2[originalY] = false;
- originalX--;
- originalY--;
- }
- }
- });
int x = 0;
int y = 0;
- while (x < changes1.length && y < changes2.length) {
+ while (x < myDiscardedLengths[0] || y < myDiscardedLengths[1]) {
+ if ((x < myDiscardedLengths[0] && y < myDiscardedLengths[1]) && !discardedChanges[0].get(x) && !discardedChanges[1].get(y)) {
+ x = increment(myOldIndecies[0], x, changes1, myOriginalLengths[0]);
+ y = increment(myOldIndecies[1], y, changes2, myOriginalLengths[1]);
+ continue;
+ }
+ if (discardedChanges[0].get(x)) {
+ changes1.set(getOriginal(myOldIndecies[0], x));
+ x = increment(myOldIndecies[0], x, changes1, myOriginalLengths[0]);
+ continue;
+ }
+ if (discardedChanges[1].get(y)) {
+ changes2.set(getOriginal(myOldIndecies[1], y));
+ y = increment(myOldIndecies[1], y, changes2, myOriginalLengths[1]);
+ continue;
+ }
+ }
+ if (myDiscardedLengths[0] == 0) {
+ changes1.set(0, myOriginalLengths[0]);
+ }
+ else {
+ changes1.set(0, myOldIndecies[0][0]);
+ }
+ if (myDiscardedLengths[1] == 0) {
+ changes2.set(0, myOriginalLengths[1]);
+ }
+ else {
+ changes2.set(0, myOldIndecies[1][0]);
+ }
+
+ x = 0;
+ y = 0;
+ while (x < myOriginalLengths[0] && y < myOriginalLengths[1]) {
int startX = x;
- while (x < changes1.length && y < changes2.length && !changes1[x] && !changes2[y]) {
+ while (x < myOriginalLengths[0] && y < myOriginalLengths[1] && !changes1.get(x) && !changes2.get(y)) {
x++;
y++;
}
if (x> startX) builder.addEqual(x - startX);
int dx = 0;
int dy = 0;
- while (x < changes1.length && changes1[x]) {
+ while (x < myOriginalLengths[0] && changes1.get(x)) {
dx++;
x++;
}
- while (y < changes2.length && changes2[y]) {
+ while (y < myOriginalLengths[1] && changes2.get(y)) {
dy++;
y++;
}
if (dx != 0 || dy != 0) builder.addChange(dx, dy);
}
- if (x != changes1.length || y != changes2.length)
- builder.addChange(changes1.length - x, changes2.length - y);
+ if (x != myOriginalLengths[0] || y != myOriginalLengths[1]) builder.addChange(myOriginalLengths[0] - x, myOriginalLengths[1] - y);
}
- private int markChanged(final boolean[] changes, int from, int[] oldIndecies, int newTo) {
- int oldTo = newTo != -1 ? oldIndecies[newTo] : -1;
- for (int i = from; i > oldTo; i--) changes[i] = true;
- return oldTo;
+ private int getOriginal(int[] indexes, int i) {
+ return indexes[i];
+ }
+
+ private int increment(int[] indexes, int i, BitSet set, int length) {
+ if (i + 1 < indexes.length) {
+ set.set(indexes[i] + 1, indexes[i + 1]);
+ }
+ else {
+ set.set(indexes[i] + 1, length);
+ }
+ return i + 1;
}
}
diff --git a/platform/util/src/com/intellij/util/diff/UniqueLCS.java b/platform/util/src/com/intellij/util/diff/UniqueLCS.java
new file mode 100644
index 0000000..636a0c8
--- /dev/null
+++ b/platform/util/src/com/intellij/util/diff/UniqueLCS.java
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diff;
+
+import gnu.trove.TIntIntHashMap;
+
+public class UniqueLCS {
+ private final int[] myFirst;
+ private final int[] mySecond;
+
+ private final int myStart1;
+ private final int myStart2;
+ private final int myCount1;
+ private final int myCount2;
+
+ public UniqueLCS(int[] first, int[] second) {
+ this(first, second, 0, first.length, 0, second.length);
+ }
+
+ public UniqueLCS(int[] first, int[] second, int start1, int count1, int start2, int count2) {
+ myFirst = first;
+ mySecond = second;
+ myStart1 = start1;
+ myStart2 = start2;
+ myCount1 = count1;
+ myCount2 = count2;
+ }
+
+ public int[][] execute() {
+ // map: key -> (offset1 + 1)
+ // match: offset1 -> (offset2 + 1)
+ TIntIntHashMap map = new TIntIntHashMap(myCount1 + myCount2);
+ int[] match = new int[myCount1];
+
+ for (int i = 0; i < myCount1; i++) {
+ int index = myStart1 + i;
+ int val = map.get(myFirst[index]);
+
+ if (val == -1) continue;
+ if (val == 0) {
+ map.put(myFirst[index], i + 1);
+ }
+ else {
+ map.put(myFirst[index], -1);
+ }
+ }
+
+ int count = 0;
+ for (int i = 0; i < myCount2; i++) {
+ int index = myStart2 + i;
+ int val = map.get(mySecond[index]);
+
+ if (val == 0 || val == -1) continue;
+ if (match[val - 1] == 0) {
+ match[val - 1] = i + 1;
+ count++;
+ }
+ else {
+ match[val - 1] = 0;
+ map.put(mySecond[index], -1);
+ count--;
+ }
+ }
+
+ if (count == 0) {
+ return null;
+ }
+
+ // Largest increasing subsequence on unique elements
+ int[] sequence = new int[count];
+ int[] lastElement = new int[count];
+ int[] predecessor = new int[myCount1];
+
+ int length = 0;
+ for (int i = 0; i < myCount1; i++) {
+ if (match[i] == 0) continue;
+
+ int j = binarySearch(sequence, match[i], length);
+ if (j == length || match[i] < sequence[j]) {
+ sequence[j] = match[i];
+ lastElement[j] = i;
+ predecessor[i] = j > 0 ? lastElement[j - 1] : -1;
+ if (j == length) {
+ length++;
+ }
+ }
+ }
+
+ int[][] ret = new int[][]{new int[length], new int[length]};
+
+ int i = length - 1;
+ int curr = lastElement[length - 1];
+ while (curr != -1) {
+ ret[0][i] = curr;
+ ret[1][i] = match[curr] - 1;
+ i--;
+ curr = predecessor[curr];
+ }
+
+ return ret;
+ }
+
+ // find max i: a[i] < val
+ // return i + 1
+ // assert a[i] != val
+ private static int binarySearch(int[] sequence, int val, int length) {
+ int left = -1;
+ int right = length;
+
+ while (right - left > 1) {
+ int middle = (left + right) / 2;
+ if (sequence[middle] > val) {
+ right = middle;
+ }
+ else {
+ left = middle;
+ }
+ }
+ return left + 1;
+ }
+}
diff --git a/platform/util/src/com/intellij/util/enumeration/EmptyEnumeration.java b/platform/util/src/com/intellij/util/enumeration/EmptyEnumeration.java
index ac9e9c8..cd86477 100644
--- a/platform/util/src/com/intellij/util/enumeration/EmptyEnumeration.java
+++ b/platform/util/src/com/intellij/util/enumeration/EmptyEnumeration.java
@@ -15,10 +15,12 @@
*/
package com.intellij.util.enumeration;
+import org.jetbrains.annotations.NotNull;
+
import java.util.Enumeration;
import java.util.NoSuchElementException;
-public final class EmptyEnumeration implements Enumeration {
+public final class EmptyEnumeration<E> implements Enumeration<E> {
public static Enumeration INSTANCE = new EmptyEnumeration();
private EmptyEnumeration(){
@@ -30,9 +32,15 @@
}
@Override
- public Object nextElement(){
+ public E nextElement(){
throw new NoSuchElementException();
}
+
+ @NotNull
+ public static <E> Enumeration<E> getInstance() {
+ //noinspection unchecked
+ return INSTANCE;
+ }
}
diff --git a/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java b/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java
new file mode 100644
index 0000000..6f936d7
--- /dev/null
+++ b/platform/util/src/com/intellij/util/io/AppendableStorageBackedByResizableMappedFile.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.BufferExposingByteArrayOutputStream;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+
+/**
+ * Created by Maxim.Mossienko on 1/9/14.
+ */
+public class AppendableStorageBackedByResizableMappedFile extends ResizeableMappedFile {
+ private final MyDataIS myReadStream;
+ private byte[] myAppendBuffer;
+ private volatile int myFileLength;
+ private volatile int myBufferPosition;
+ private static final int ourAppendBufferLength = 4096;
+
+ public AppendableStorageBackedByResizableMappedFile(File file,
+ int initialSize,
+ @Nullable PagedFileStorage.StorageLockContext lockContext,
+ int pageSize,
+ boolean valuesAreBufferAligned) throws IOException {
+ super(file, initialSize, lockContext, pageSize, valuesAreBufferAligned);
+ myReadStream = new MyDataIS(this);
+ myFileLength = (int)length();
+ }
+
+ private void flushKeyStoreBuffer() {
+ if (myBufferPosition > 0) {
+ put(myFileLength, myAppendBuffer, 0, myBufferPosition);
+ myFileLength += myBufferPosition;
+ myBufferPosition = 0;
+ }
+ }
+
+ @Override
+ public void force() {
+ flushKeyStoreBuffer();
+ super.force();
+ }
+
+ @Override
+ public void close() {
+ flushKeyStoreBuffer();
+ super.close();
+ }
+
+ public <Data> Data read(int addr, KeyDescriptor<Data> descriptor) throws IOException {
+ if (myFileLength <= addr) {
+ return descriptor.read(new DataInputStream(new UnsyncByteArrayInputStream(myAppendBuffer, addr - myFileLength, myBufferPosition)));
+ }
+ // we do not need to flushKeyBuffer since we store complete records
+ myReadStream.setup(addr, myFileLength);
+ return descriptor.read(myReadStream);
+ }
+
+ public <Data> boolean processAll(Processor<Data> processor, KeyDescriptor<Data> descriptor) throws IOException {
+ force();
+
+ DataInputStream keysStream = new DataInputStream(new BufferedInputStream(new LimitedInputStream(new FileInputStream(getPagedFileStorage().getFile()),
+ myFileLength) {
+ @Override
+ public int available() throws IOException {
+ return remainingLimit();
+ }
+ }, 32768));
+ try {
+ try {
+ while (true) {
+ Data key = descriptor.read(keysStream);
+ if (!processor.process(key)) return false;
+ }
+ }
+ catch (EOFException e) {
+ // Done
+ }
+ return true;
+ }
+ finally {
+ keysStream.close();
+ }
+ }
+
+ public int getCurrentLength() {
+ return myBufferPosition + myFileLength;
+ }
+
+ public <Data> int append(Data value, KeyDescriptor<Data> descriptor) throws IOException {
+ final BufferExposingByteArrayOutputStream bos = new BufferExposingByteArrayOutputStream();
+ DataOutput out = new DataOutputStream(bos);
+ descriptor.save(out, value);
+ final int size = bos.size();
+ final byte[] buffer = bos.getInternalBuffer();
+
+ int currentLength = getCurrentLength();
+ if (size > ourAppendBufferLength) {
+ flushKeyStoreBuffer();
+ put(currentLength, buffer, 0, size);
+ myFileLength += size;
+ }
+ else {
+ if (size > ourAppendBufferLength - myBufferPosition) {
+ flushKeyStoreBuffer();
+ }
+ // myAppendBuffer will contain complete records
+ if (myAppendBuffer == null) {
+ myAppendBuffer = new byte[ourAppendBufferLength];
+ }
+ System.arraycopy(buffer, 0, myAppendBuffer, myBufferPosition, size);
+ myBufferPosition += size;
+ }
+ return currentLength;
+ }
+
+ public <Data> boolean checkBytesAreTheSame(final int addr, Data value, KeyDescriptor<Data> descriptor) throws IOException {
+ final boolean[] sameValue = new boolean[1];
+ OutputStream comparer;
+
+ final PagedFileStorage storage = getPagedFileStorage();
+
+ if (myFileLength <= addr) {
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ comparer = new OutputStream() {
+ int address = addr - myFileLength;
+ boolean same = true;
+ @Override
+ public void write(int b) {
+ if (same) {
+ same = address < myBufferPosition && myAppendBuffer[address++] == (byte)b;
+ }
+ }
+ @Override
+ public void close() {
+ sameValue[0] = same;
+ }
+ };
+ }
+ else {
+ //noinspection IOResourceOpenedButNotSafelyClosed
+ comparer = new OutputStream() {
+ int base = addr;
+ int address = storage.getOffsetInPage(addr);
+ boolean same = true;
+ ByteBuffer buffer = storage.getByteBuffer(addr, false);
+ final int myPageSize = storage.myPageSize;
+
+ @Override
+ public void write(int b) {
+ if (same) {
+ if (myPageSize == address && address < myFileLength) { // reached end of current byte buffer
+ base += address;
+ buffer = storage.getByteBuffer(base, false);
+ address = 0;
+ }
+ same = address < myFileLength && buffer.get(address++) == (byte)b;
+ }
+ }
+
+ @Override
+ public void close() {
+ sameValue[0] = same;
+ }
+ };
+
+ }
+
+ DataOutput out = new DataOutputStream(comparer);
+ descriptor.save(out, value);
+ comparer.close();
+
+ return sameValue[0];
+ }
+
+ private static class MyDataIS extends DataInputStream {
+ private MyDataIS(ResizeableMappedFile raf) {
+ super(new MyBufferedIS(new MappedFileInputStream(raf, 0, 0)));
+ }
+
+ public void setup(long pos, long limit) {
+ ((MyBufferedIS)in).setup(pos, limit);
+ }
+ }
+
+ private static class MyBufferedIS extends BufferedInputStream {
+ public MyBufferedIS(final InputStream in) {
+ super(in, 512);
+ }
+
+ public void setup(long pos, long limit) {
+ this.pos = 0;
+ count = 0;
+ ((MappedFileInputStream)in).setup(pos, limit);
+ }
+ }
+}
diff --git a/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java b/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java
index d6030d8..5b9f205 100644
--- a/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java
+++ b/platform/util/src/com/intellij/util/io/ByteBufferWrapper.java
@@ -58,7 +58,7 @@
return new ReadWriteDirectBufferWrapper(file, offset, length);
}
- public static ByteBufferWrapper readWriteDirect(final File file, final int offset, final int length) {
+ public static ByteBufferWrapper readWriteDirect(final File file, final long offset, final int length) {
return new ReadWriteDirectBufferWrapper(file, offset, length);
}
diff --git a/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java b/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java
index 3022a3a..1621cf3 100644
--- a/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java
+++ b/platform/util/src/com/intellij/util/io/EnumeratorStringDescriptor.java
@@ -26,8 +26,6 @@
* Date: Dec 18, 2007
*/
public class EnumeratorStringDescriptor implements KeyDescriptor<String> {
- private final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
-
@Override
public int getHashCode(final String value) {
return value.hashCode();
@@ -40,11 +38,13 @@
@Override
public void save(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 {
+ final byte[] buffer = IOUtil.allocReadWriteUTFBuffer();
return IOUtil.readUTFFast(buffer, storage);
}
}
diff --git a/platform/util/src/com/intellij/util/io/PagedFileStorage.java b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
index 6c4c9a3..1d5e9d7 100644
--- a/platform/util/src/com/intellij/util/io/PagedFileStorage.java
+++ b/platform/util/src/com/intellij/util/io/PagedFileStorage.java
@@ -136,10 +136,10 @@
return myFile;
}
- public void putInt(int addr, int value) {
+ public void putInt(long addr, int value) {
if (myValuesAreBufferAligned) {
- int page = addr / myPageSize;
- int page_offset = addr % myPageSize;
+ long page = addr / myPageSize;
+ int page_offset = (int)(addr % myPageSize);
getBuffer(page).putInt(page_offset, value);
} else {
Bits.putInt(myTypedIOBuffer, 0, value);
@@ -147,10 +147,10 @@
}
}
- public int getInt(int addr) {
+ public int getInt(long addr) {
if (myValuesAreBufferAligned) {
- int page = addr / myPageSize;
- int page_offset = addr % myPageSize;
+ long page = addr / myPageSize;
+ int page_offset = (int) (addr % myPageSize);
return getBuffer(page, false).getInt(page_offset);
} else {
get(addr, myTypedIOBuffer, 0, 4);
@@ -158,10 +158,10 @@
}
}
- public final void putShort(int addr, short value) {
+ public final void putShort(long addr, short value) {
if (myValuesAreBufferAligned) {
- int page = addr / myPageSize;
- int page_offset = addr % myPageSize;
+ long page = addr / myPageSize;
+ int page_offset = (int)(addr % myPageSize);
getBuffer(page).putShort(page_offset, value);
} else {
Bits.putShort(myTypedIOBuffer, 0, value);
@@ -169,18 +169,18 @@
}
}
- int getOffsetInPage(int addr) {
- return addr % myPageSize;
+ int getOffsetInPage(long addr) {
+ return (int)(addr % myPageSize);
}
- ByteBuffer getByteBuffer(int address, boolean modify) {
+ ByteBuffer getByteBuffer(long address, boolean modify) {
return getBuffer(address / myPageSize, modify);
}
- public final short getShort(int addr) {
+ public final short getShort(long addr) {
if (myValuesAreBufferAligned) {
- int page = addr / myPageSize;
- int page_offset = addr % myPageSize;
+ long page = addr / myPageSize;
+ int page_offset = (int)(addr % myPageSize);
return getBuffer(page, false).getShort(page_offset);
} else {
get(addr, myTypedIOBuffer, 0, 2);
@@ -188,10 +188,10 @@
}
}
- public void putLong(int addr, long value) {
+ public void putLong(long addr, long value) {
if (myValuesAreBufferAligned) {
- int page = addr / myPageSize;
- int page_offset = addr % myPageSize;
+ long page = addr / myPageSize;
+ int page_offset = (int)(addr % myPageSize);
getBuffer(page).putLong(page_offset, value);
} else {
Bits.putLong(myTypedIOBuffer, 0, value);
@@ -200,18 +200,18 @@
}
@SuppressWarnings({"UnusedDeclaration"})
- public void putByte(final int addr, final byte b) {
+ public void putByte(final long addr, final byte b) {
put(addr, b);
}
- public byte getByte(int addr) {
+ public byte getByte(long addr) {
return get(addr);
}
- public long getLong(int addr) {
+ public long getLong(long addr) {
if (myValuesAreBufferAligned) {
- int page = addr / myPageSize;
- int page_offset = addr % myPageSize;
+ long page = addr / myPageSize;
+ int page_offset = (int)(addr % myPageSize);
return getBuffer(page, false).getLong(page_offset);
} else {
get(addr, myTypedIOBuffer, 0, 8);
@@ -219,28 +219,28 @@
}
}
- public byte get(int index) {
- int page = index / myPageSize;
- int offset = index % myPageSize;
+ public byte get(long index) {
+ long page = index / myPageSize;
+ int offset = (int)(index % myPageSize);
return getBuffer(page, false).get(offset);
}
- public void put(int index, byte value) {
- int page = index / myPageSize;
- int offset = index % myPageSize;
+ public void put(long index, byte value) {
+ long page = index / myPageSize;
+ int offset = (int)(index % myPageSize);
getBuffer(page).put(offset, value);
}
- public void get(int index, byte[] dst, int offset, int length) {
- int i = index;
+ public void get(long index, byte[] dst, int offset, int length) {
+ long i = index;
int o = offset;
int l = length;
while (l > 0) {
- int page = i / myPageSize;
- int page_offset = i % myPageSize;
+ long page = i / myPageSize;
+ int page_offset = (int) (i % myPageSize);
int page_len = Math.min(l, myPageSize - page_offset);
final ByteBuffer buffer = getBuffer(page, false);
@@ -262,14 +262,14 @@
}
}
- public void put(int index, byte[] src, int offset, int length) {
- int i = index;
+ public void put(long index, byte[] src, int offset, int length) {
+ long i = index;
int o = offset;
int l = length;
while (l > 0) {
- int page = i / myPageSize;
- int page_offset = i % myPageSize;
+ long page = i / myPageSize;
+ int page_offset = (int) (i % myPageSize);
int page_len = Math.min(l, myPageSize - page_offset);
final ByteBuffer buffer = getBuffer(page);
@@ -311,12 +311,12 @@
}
}
- public void resize(int newSize) throws IOException {
- int oldSize = (int)myFile.length();
+ public void resize(long newSize) throws IOException {
+ long oldSize = myFile.length();
if (oldSize == newSize && oldSize == length()) return;
final long started = IOStatistics.DEBUG ? System.currentTimeMillis():0;
- myStorageLockContext.myStorageLock.invalidateBuffer(myStorageIndex | (oldSize / myPageSize));
+ myStorageLockContext.myStorageLock.invalidateBuffer(myStorageIndex | (int)(oldSize / myPageSize)); // TODO long page
//unmapAll(); // we do not need it since all page alighned buffers can be reused
final long unmapAllFinished = IOStatistics.DEBUG ? System.currentTimeMillis():0;
@@ -324,7 +324,7 @@
// it is not guaranteed that new partition will consist of null
// after resize, so we should fill it manually
- int delta = newSize - oldSize;
+ long delta = newSize - oldSize;
if (delta > 0) fillWithZeros(oldSize, delta);
if (IOStatistics.DEBUG) {
@@ -335,7 +335,7 @@
}
}
- private void resizeFile(int newSize) throws IOException {
+ private void resizeFile(long newSize) throws IOException {
RandomAccessFile raf = new RandomAccessFile(myFile, RW);
mySize = -1;
try {
@@ -348,12 +348,12 @@
}
private static final int MAX_FILLER_SIZE = 8192;
- private void fillWithZeros(int from, int length) {
+ private void fillWithZeros(long from, long length) {
byte[] buff = new byte[MAX_FILLER_SIZE];
Arrays.fill(buff, (byte)0);
while (length > 0) {
- final int filled = Math.min(length, MAX_FILLER_SIZE);
+ final int filled = Math.min((int)length, MAX_FILLER_SIZE);
put(from, buff, 0, filled);
length -= filled;
from += filled;
@@ -368,11 +368,11 @@
return size;
}
- private ByteBuffer getBuffer(int page) {
+ private ByteBuffer getBuffer(long page) {
return getBuffer(page, true);
}
- private ByteBuffer getBuffer(int page, boolean modify) {
+ private ByteBuffer getBuffer(long page, boolean modify) {
synchronized (myLastAccessedBufferCacheLock) {
if (myLastPage == page) {
ByteBuffer buf = myLastBuffer.getCachedBuffer();
@@ -401,7 +401,7 @@
if (myStorageIndex == -1) {
myStorageIndex = myStorageLockContext.myStorageLock.registerPagedFileStorage(this);
}
- ByteBufferWrapper byteBufferWrapper = myStorageLockContext.myStorageLock.get(myStorageIndex | page);
+ ByteBufferWrapper byteBufferWrapper = myStorageLockContext.myStorageLock.get(myStorageIndex | (int)page); // TODO: long page
if (modify) markDirty(byteBufferWrapper);
ByteBuffer buf = byteBufferWrapper.getBuffer();
if (myNativeBytesOrder && buf.order() != ourNativeByteOrder) {
@@ -419,7 +419,7 @@
myLastChangeCount2 = myLastChangeCount;
myLastBuffer = byteBufferWrapper;
- myLastPage = page;
+ myLastPage = (int)page; // TODO long page
} else {
myLastBuffer = byteBufferWrapper;
}
diff --git a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java
index 56fa7f7..a91c7e0 100644
--- a/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java
+++ b/platform/util/src/com/intellij/util/io/PersistentEnumeratorBase.java
@@ -17,7 +17,6 @@
import com.intellij.openapi.Forceable;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.CommonProcessors;
import com.intellij.util.IncorrectOperationException;
@@ -28,8 +27,10 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
-import java.io.*;
-import java.nio.ByteBuffer;
+import java.io.Closeable;
+import java.io.File;
+import java.io.Flushable;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -48,10 +49,7 @@
protected final ResizeableMappedFile myStorage;
private final boolean myAssumeDifferentSerializedBytesMeansObjectsInequality;
- private byte[] myKeyStoreFileBuffer;
- private volatile int myKeyStoreFileLength;
- private volatile int myKeyStoreBufferPosition;
- private final ResizeableMappedFile myKeyStorage;
+ private final AppendableStorageBackedByResizableMappedFile myKeyStorage;
private boolean myClosed = false;
private boolean myDirty = false;
@@ -61,7 +59,6 @@
protected final File myFile;
private boolean myCorrupted = false;
- private final MyDataIS myKeyReadStream;
private final int myInitialSize;
private final Version myVersion;
private RecordBufferHandler<PersistentEnumeratorBase> myRecordHandler;
@@ -151,7 +148,7 @@
public static class VersionUpdatedException extends CorruptedException {
@SuppressWarnings({"HardCodedStringLiteral"})
public VersionUpdatedException(File file) {
- super("PersistentEnumerator storage version updated " + file.getPath());
+ super("PersistentEnumerator storage corrupted " + file.getPath());
}
}
@@ -228,12 +225,9 @@
if (myDataDescriptor instanceof InlineKeyDescriptor) {
myKeyStorage = null;
- myKeyReadStream = null;
}
else {
- myKeyStorage = new ResizeableMappedFile(keystreamFile(), initialSize, myStorage.getPagedFileStorage().getStorageLockContext(), PagedFileStorage.MB, false);
- myKeyReadStream = new MyDataIS(myKeyStorage);
- myKeyStoreFileLength = (int)myKeyStorage.length();
+ myKeyStorage = new AppendableStorageBackedByResizableMappedFile(keystreamFile(), initialSize, myStorage.getPagedFileStorage().getStorageLockContext(), PagedFileStorage.MB, false);
}
myAssumeDifferentSerializedBytesMeansObjectsInequality = myDataDescriptor instanceof DifferentSerializableBytesImplyNonEqualityPolicy;
}
@@ -388,59 +382,10 @@
// check if previous serialized state is the same as for value
// this is much faster than myDataDescriptor.isEqualTo(valueOf(idx), value) for identical objects
- final boolean[] sameValue = new boolean[1]; // TODO: key storage lock
+ // TODO: key storage lock
final int addr = indexToAddr(idx);
- OutputStream comparer;
- if (myKeyStoreFileLength <= addr) {
- comparer = new OutputStream() {
- int address = addr - myKeyStoreFileLength;
- boolean same = true;
- @Override
- public void write(int b) {
- if (same) {
- same = address < myKeyStoreBufferPosition && myKeyStoreFileBuffer[address++] == (byte)b;
- }
- }
- @Override
- public void close() {
- sameValue[0] = same;
- }
- };
- }
- else {
- comparer = new OutputStream() {
- int base = addr;
- int address = myKeyStorage.getPagedFileStorage().getOffsetInPage(addr);
- boolean same = true;
- ByteBuffer buffer = myKeyStorage.getPagedFileStorage().getByteBuffer(addr, false);
- final int myPageSize = myKeyStorage.getPagedFileStorage().myPageSize;
-
- @Override
- public void write(int b) {
- if (same) {
- if (myPageSize == address && address < myKeyStoreFileLength) { // reached end of current byte buffer
- base += address;
- buffer = myKeyStorage.getPagedFileStorage().getByteBuffer(base, false);
- address = 0;
- }
- same = address < myKeyStoreFileLength && buffer.get(address++) == (byte)b;
- }
- }
-
- @Override
- public void close() {
- sameValue[0] = same;
- }
- };
-
- }
-
- DataOutput out = new DataOutputStream(comparer);
- myDataDescriptor.save(out, value);
- comparer.close();
-
- if (sameValue[0]) return true;
+ if (myKeyStorage.checkBytesAreTheSame(addr, value, myDataDescriptor)) return true;
if (myAssumeDifferentSerializedBytesMeansObjectsInequality) return false;
return myDataDescriptor.isEqual(valueOf(idx), value);
}
@@ -460,47 +405,15 @@
public int getLargestId() {
assert myKeyStorage != null;
- return myKeyStoreBufferPosition + myKeyStoreFileLength;
+ return myKeyStorage.getCurrentLength();
}
protected int doWriteData(Data value) throws IOException {
- final int dataOff = myKeyStorage != null ?
- myKeyStoreBufferPosition + myKeyStoreFileLength :
- ((InlineKeyDescriptor<Data>)myDataDescriptor).toInt(value);
-
if (myKeyStorage != null) {
- final BufferExposingByteArrayOutputStream bos = new BufferExposingByteArrayOutputStream();
- DataOutput out = new DataOutputStream(bos);
- myDataDescriptor.save(out, value);
- final int size = bos.size();
- final byte[] buffer = bos.getInternalBuffer();
+ return myKeyStorage.append(value, myDataDescriptor);
- if (size > myInitialSize) {
- flushKeyStoreBuffer();
- myKeyStorage.put(dataOff, buffer, 0, size);
- myKeyStoreFileLength += size;
- }
- else {
- if (size > myInitialSize - myKeyStoreBufferPosition) {
- flushKeyStoreBuffer();
- }
- // myKeyStoreFileBuffer will contain complete records
- if (myKeyStoreFileBuffer == null) {
- myKeyStoreFileBuffer = new byte[myInitialSize];
- }
- System.arraycopy(buffer, 0, myKeyStoreFileBuffer, myKeyStoreBufferPosition, size);
- myKeyStoreBufferPosition += size;
- }
}
- return dataOff;
- }
-
- private void flushKeyStoreBuffer() {
- if (myKeyStoreBufferPosition > 0) {
- myKeyStorage.put(myKeyStoreFileLength, myKeyStoreFileBuffer, 0, myKeyStoreBufferPosition);
- myKeyStoreFileLength += myKeyStoreBufferPosition;
- myKeyStoreBufferPosition = 0;
- }
+ return ((InlineKeyDescriptor<Data>)myDataDescriptor).toInt(value);
}
protected int setupValueId(int hashCode, int dataOff) {
@@ -513,37 +426,13 @@
}
public boolean iterateData(final Processor<Data> processor) throws IOException {
- lockStorage();
+ if (myKeyStorage == null) {
+ throw new UnsupportedOperationException("Iteration over InlineIntegerKeyDescriptors is not supported");
+ }
+
+ lockStorage(); // todo locking in key storage
try {
- if (myKeyStorage == null) {
- throw new UnsupportedOperationException("Iteration over InlineIntegerKeyDescriptors is not supported");
- }
-
- flushKeyStoreBuffer();
- myKeyStorage.force();
-
- DataInputStream keysStream = new DataInputStream(new BufferedInputStream(new LimitedInputStream(new FileInputStream(keystreamFile()),
- myKeyStoreFileLength) {
- @Override
- public int available() throws IOException {
- return remainingLimit();
- }
- }, 32768));
- try {
- try {
- while (true) {
- Data key = myDataDescriptor.read(keysStream);
- if (!processor.process(key)) return false;
- }
- }
- catch (EOFException e) {
- // Done
- }
- return true;
- }
- finally {
- keysStream.close();
- }
+ return myKeyStorage.processAll(processor, myDataDescriptor);
}
finally {
unlockStorage();
@@ -559,14 +448,8 @@
try {
int addr = indexToAddr(idx);
- if (myKeyReadStream == null) return ((InlineKeyDescriptor<Data>)myDataDescriptor).fromInt(addr);
-
- if (myKeyStoreFileLength <= addr) {
- return myDataDescriptor.read(new DataInputStream(new UnsyncByteArrayInputStream(myKeyStoreFileBuffer, addr - myKeyStoreFileLength, myKeyStoreBufferPosition)));
- }
- // we do not need to flushKeyBuffer since we store complete records
- myKeyReadStream.setup(addr, myKeyStoreFileLength);
- return myDataDescriptor.read(myKeyReadStream);
+ if (myKeyStorage == null) return ((InlineKeyDescriptor<Data>)myDataDescriptor).fromInt(addr);
+ return myKeyStorage.read(addr, myDataDescriptor);
}
catch (IOException io) {
markCorrupted();
@@ -592,28 +475,6 @@
protected abstract int indexToAddr(int idx);
- private static class MyDataIS extends DataInputStream {
- private MyDataIS(ResizeableMappedFile raf) {
- super(new MyBufferedIS(new MappedFileInputStream(raf, 0, 0)));
- }
-
- public void setup(long pos, long limit) {
- ((MyBufferedIS)in).setup(pos, limit);
- }
- }
-
- private static class MyBufferedIS extends BufferedInputStream {
- public MyBufferedIS(final InputStream in) {
- super(in, 512);
- }
-
- public void setup(long pos, long limit) {
- this.pos = 0;
- count = 0;
- ((MappedFileInputStream)in).setup(pos, limit);
- }
- }
-
@Override
public synchronized void close() throws IOException {
lockStorage();
@@ -631,7 +492,6 @@
protected void doClose() throws IOException {
try {
if (myKeyStorage != null) {
- flushKeyStoreBuffer();
myKeyStorage.close();
}
flush();
@@ -673,7 +533,6 @@
try {
if (myKeyStorage != null) {
- flushKeyStoreBuffer();
myKeyStorage.force();
}
flush();
diff --git a/platform/util/src/com/intellij/util/io/PersistentHashMap.java b/platform/util/src/com/intellij/util/io/PersistentHashMap.java
index 20ce92b..8f59c11 100644
--- a/platform/util/src/com/intellij/util/io/PersistentHashMap.java
+++ b/platform/util/src/com/intellij/util/io/PersistentHashMap.java
@@ -64,7 +64,7 @@
private final boolean myCanReEnumerate;
private int myLargeIndexWatermarkId; // starting with this id we store offset in adjacent file in long format
private boolean myIntAddressForNewRecord;
- private static final boolean doHardConsistencyChecks = false;
+ private static final boolean doHardConsistencyChecks = true;
private static class AppendStream extends DataOutputStream {
private AppendStream() {
diff --git a/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java b/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java
index f7a74f5..7b508c7 100644
--- a/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java
+++ b/platform/util/src/com/intellij/util/io/ResizeableMappedFile.java
@@ -80,7 +80,7 @@
return myStorage.length();
}
- private void resize(final int size) {
+ private void resize(final long size) {
try {
myStorage.resize(size);
}
@@ -175,47 +175,47 @@
}
}
- public int getInt(int index) {
+ public int getInt(long index) {
return myStorage.getInt(index);
}
- public void putInt(int index, int value) {
+ public void putInt(long index, int value) {
ensureSize(index + 4);
myStorage.putInt(index, value);
}
- public short getShort(int index) {
+ public short getShort(long index) {
return myStorage.getShort(index);
}
- public void putShort(int index, short value) {
+ public void putShort(long index, short value) {
ensureSize(index + 2);
myStorage.putShort(index, value);
}
- public long getLong(int index) {
+ public long getLong(long index) {
return myStorage.getLong(index);
}
- public void putLong(int index, long value) {
+ public void putLong(long index, long value) {
ensureSize(index + 8);
myStorage.putLong(index, value);
}
- public byte get(int index) {
+ public byte get(long index) {
return myStorage.get(index);
}
- public void put(int index, byte value) {
+ public void put(long index, byte value) {
ensureSize(index + 1);
myStorage.put(index, value);
}
- public void get(int index, byte[] dst, int offset, int length) {
+ public void get(long index, byte[] dst, int offset, int length) {
myStorage.get(index, dst, offset, length);
}
- public void put(int index, byte[] src, int offset, int length) {
+ public void put(long index, byte[] src, int offset, int length) {
ensureSize(index + length);
myStorage.put(index, src, offset, length);
}
diff --git a/platform/util/src/com/intellij/util/io/URLUtil.java b/platform/util/src/com/intellij/util/io/URLUtil.java
index 7e6daec..ad577ca 100644
--- a/platform/util/src/com/intellij/util/io/URLUtil.java
+++ b/platform/util/src/com/intellij/util/io/URLUtil.java
@@ -18,6 +18,8 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.util.Base64Converter;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -30,15 +32,22 @@
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.Charset;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
+import static com.intellij.openapi.util.text.StringUtil.stripQuotesAroundValue;
+
public class URLUtil {
public static final String SCHEME_SEPARATOR = "://";
- public static final String JAR_PROTOCOL = "jar";
public static final String FILE_PROTOCOL = "file";
+ public static final String HTTP_PROTOCOL = "http";
+ public static final String JAR_PROTOCOL = "jar";
public static final String JAR_SEPARATOR = "!/";
+ public static final Pattern DATA_URI_PATTERN = Pattern.compile("data:([^,;]+/[^,;]+)(;charset=[^,;]+)?(;base64)?,(.+)");
+
private URLUtil() { }
/**
@@ -87,6 +96,7 @@
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed") final ZipFile zipFile = new ZipFile(FileUtil.unquote(paths.first));
ZipEntry zipEntry = zipFile.getEntry(paths.second);
if (zipEntry == null) {
+ zipFile.close();
throw new FileNotFoundException("Entry " + paths.second + " not found in " + paths.first);
}
@@ -166,4 +176,30 @@
public static boolean containsScheme(@NotNull String url) {
return url.contains(SCHEME_SEPARATOR);
}
-}
+
+ public static boolean isDataUri(@NotNull String value) {
+ return !value.isEmpty() && value.startsWith("data:", value.charAt(0) == '"' || value.charAt(0) == '\'' ? 1 : 0);
+ }
+
+ /**
+ * Extracts byte array from given data:URL string.
+ * data:URL will be decoded from base64 if it contains the marker of base64 encoding.
+ *
+ * @param dataUrl data:URL-like string (may be quoted)
+ * @return extracted byte array or {@code null} if it cannot be extracted.
+ */
+ @Nullable
+ public static byte[] getBytesFromDataUri(@NotNull String dataUrl) {
+ Matcher matcher = DATA_URI_PATTERN.matcher(stripQuotesAroundValue(dataUrl));
+ if (matcher.matches()) {
+ try {
+ String content = matcher.group(4);
+ return ";base64".equalsIgnoreCase(matcher.group(3)) ? Base64Converter.decode(content.getBytes(CharsetToolkit.UTF8_CHARSET)) : content.getBytes(CharsetToolkit.UTF8_CHARSET);
+ }
+ catch (IllegalArgumentException e) {
+ return null;
+ }
+ }
+ return null;
+ }
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java b/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java
index 243aa48..c270a13 100644
--- a/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java
+++ b/platform/util/src/com/intellij/util/io/UnsyncByteArrayOutputStream.java
@@ -15,6 +15,8 @@
*/
package com.intellij.util.io;
+import com.intellij.util.ArrayUtil;
+
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
@@ -22,6 +24,7 @@
public class UnsyncByteArrayOutputStream extends OutputStream {
protected byte[] myBuffer;
protected int myCount;
+ private boolean myIsShared;
public UnsyncByteArrayOutputStream() {
this(32);
@@ -34,8 +37,9 @@
@Override
public void write(int b) {
int newcount = myCount + 1;
- if (newcount > myBuffer.length) {
- myBuffer = Arrays.copyOf(myBuffer, Math.max(myBuffer.length << 1, newcount));
+ if (newcount > myBuffer.length || myIsShared) {
+ myBuffer = Arrays.copyOf(myBuffer, newcount > myBuffer.length ? Math.max(myBuffer.length << 1, newcount):myBuffer.length);
+ myIsShared = false;
}
myBuffer[myCount] = (byte)b;
myCount = newcount;
@@ -50,8 +54,9 @@
return;
}
int newcount = myCount + len;
- if (newcount > myBuffer.length) {
- myBuffer = Arrays.copyOf(myBuffer, Math.max(myBuffer.length << 1, newcount));
+ if (newcount > myBuffer.length || myIsShared) {
+ myBuffer = Arrays.copyOf(myBuffer, newcount > myBuffer.length ? Math.max(myBuffer.length << 1, newcount): myBuffer.length);
+ myIsShared = false;
}
System.arraycopy(b, off, myBuffer, myCount, len);
myCount = newcount;
@@ -66,6 +71,10 @@
}
public byte[] toByteArray() {
+ if (myBuffer.length == myCount) {
+ myIsShared = true;
+ return myBuffer;
+ }
return Arrays.copyOf(myBuffer, myCount);
}
diff --git a/platform/util/src/com/intellij/util/io/storage/RefCountingStorage.java b/platform/util/src/com/intellij/util/io/storage/RefCountingStorage.java
index f2d3566..7227a34 100644
--- a/platform/util/src/com/intellij/util/io/storage/RefCountingStorage.java
+++ b/platform/util/src/com/intellij/util/io/storage/RefCountingStorage.java
@@ -69,19 +69,20 @@
private BufferExposingByteArrayOutputStream internalReadStream(int record) throws IOException {
waitForPendingWriteForRecord(record);
+ byte[] result;
synchronized (myLock) {
+ result = super.readBytes(record);
+ }
- byte[] result = super.readBytes(record);
- InflaterInputStream in = new CustomInflaterInputStream(result);
- try {
- final BufferExposingByteArrayOutputStream outputStream = new BufferExposingByteArrayOutputStream();
- StreamUtil.copyStreamContent(in, outputStream);
- return outputStream;
- }
- finally {
- in.close();
- }
+ InflaterInputStream in = new CustomInflaterInputStream(result);
+ try {
+ final BufferExposingByteArrayOutputStream outputStream = new BufferExposingByteArrayOutputStream();
+ StreamUtil.copyStreamContent(in, outputStream);
+ return outputStream;
+ }
+ finally {
+ in.close();
}
}
diff --git a/platform/util/src/com/intellij/util/lang/JarLoader.java b/platform/util/src/com/intellij/util/lang/JarLoader.java
index 72323c1..8f3937e 100644
--- a/platform/util/src/com/intellij/util/lang/JarLoader.java
+++ b/platform/util/src/com/intellij/util/lang/JarLoader.java
@@ -147,12 +147,10 @@
@Nullable
Resource getResource(String name, boolean flag) {
final long started = myDebugTime ? System.nanoTime():0;
- if (myMemoryLoader != null) {
- JarMemoryLoader loader = myMemoryLoader.get();
- if (loader != null) {
- Resource resource = loader.getResource(name);
- if (resource != null) return resource;
- }
+ JarMemoryLoader loader = com.intellij.reference.SoftReference.dereference(myMemoryLoader);
+ if (loader != null) {
+ Resource resource = loader.getResource(name);
+ if (resource != null) return resource;
}
ZipFile file = null;
try {
diff --git a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java
index b6f9816..33733e5 100644
--- a/platform/util/src/com/intellij/util/lang/UrlClassLoader.java
+++ b/platform/util/src/com/intellij/util/lang/UrlClassLoader.java
@@ -235,7 +235,8 @@
if (!new File(libPath = PathManager.getHomePath() + "/community/bin/" + platform + libFileName).exists()) {
if (!new File(libPath = PathManager.getHomePath() + "/bin/" + platform + libFileName).exists()) {
if (!new File(libPath = PathManager.getHomePathFor(IdeaWin32.class) + "/bin/" + libFileName).exists()) {
- throw new UnsatisfiedLinkError("'" + libFileName + "' not found among " + Arrays.toString(new File(PathManager.getBinPath()).listFiles()));
+ File libDir = new File(PathManager.getBinPath());
+ throw new UnsatisfiedLinkError("'" + libFileName + "' not found in '" + libDir + "' among " + Arrays.toString(libDir.list()));
}
}
}
diff --git a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java
index 1b8f35a..0b92057 100644
--- a/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.java
+++ b/platform/util/src/com/intellij/util/pico/DefaultPicoContainer.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,7 +15,7 @@
*/
package com.intellij.util.pico;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.FList;
import org.jetbrains.annotations.NotNull;
@@ -59,7 +59,7 @@
protected LinkedList<ComponentAdapter> getNonAssignableAdaptersOfType(final Class componentType) {
LinkedList<ComponentAdapter> result = new LinkedList<ComponentAdapter>();
for (final ComponentAdapter componentAdapter : nonAssignableComponentAdapters.get()) {
- if (ReflectionCache.isAssignable(componentType, componentAdapter.getComponentImplementation())) {
+ if (ReflectionUtil.isAssignable(componentType, componentAdapter.getComponentImplementation())) {
result.addFirst(componentAdapter);
}
}
@@ -128,7 +128,7 @@
for (final Object o : getComponentAdapters()) {
ComponentAdapter componentAdapter = (ComponentAdapter)o;
- if (ReflectionCache.isAssignable(componentType, componentAdapter.getComponentImplementation())) {
+ if (ReflectionUtil.isAssignable(componentType, componentAdapter.getComponentImplementation())) {
found.add(componentAdapter);
}
}
@@ -184,7 +184,7 @@
List<Object> result = new ArrayList<Object>();
for (final ComponentAdapter componentAdapter : componentAdapters.getImmutableSet()) {
- if (ReflectionCache.isAssignable(componentType, componentAdapter.getComponentImplementation())) {
+ if (ReflectionUtil.isAssignable(componentType, componentAdapter.getComponentImplementation())) {
// may be null in the case of the "implicit" adapter representing "this".
ContainerUtil.addIfNotNull(result, getInstance(componentAdapter));
}
diff --git a/platform/util/src/com/intellij/util/text/CharArrayExternalizable.java b/platform/util/src/com/intellij/util/text/CharArrayExternalizable.java
new file mode 100644
index 0000000..49a9a89
--- /dev/null
+++ b/platform/util/src/com/intellij/util/text/CharArrayExternalizable.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.util.text;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * A char sequence that supports fast copying of its full or partial contents to a char array. May be useful for performance optimizations
+ * @see com.intellij.util.text.CharSequenceBackedByArray
+ * @see com.intellij.util.text.CharArrayUtil#getChars(CharSequence, char[], int)
+ */
+public interface CharArrayExternalizable extends CharSequence {
+
+ /**
+ * Copies own character sub-sequence to the given array
+ * @param start the index where to start taking chars from in this sequence
+ * @param end the index where to end taking chars in this sequence
+ * @param dest the array to put characters into
+ * @param destPos the index where to put the characters in the dest array
+ */
+ void getChars(int start, int end, @NotNull char[] dest, int destPos);
+}
diff --git a/platform/util/src/com/intellij/util/text/CharArrayUtil.java b/platform/util/src/com/intellij/util/text/CharArrayUtil.java
index 3889596..5396650 100644
--- a/platform/util/src/com/intellij/util/text/CharArrayUtil.java
+++ b/platform/util/src/com/intellij/util/text/CharArrayUtil.java
@@ -67,9 +67,14 @@
* @param len number of source data symbols to copy to the given buffer
*/
public static void getChars(@NotNull CharSequence src, @NotNull char[] dst, int srcOffset, int dstOffset, int len) {
+ if (src instanceof CharArrayExternalizable) {
+ ((CharArrayExternalizable)src).getChars(srcOffset, srcOffset + len, dst, dstOffset);
+ return;
+ }
+
if (len >= GET_CHARS_THRESHOLD) {
if (src instanceof String) {
- ((String)src).getChars(srcOffset, len, dst, dstOffset);
+ ((String)src).getChars(srcOffset, srcOffset + len, dst, dstOffset);
return;
}
else if (src instanceof CharBuffer) {
@@ -81,7 +86,7 @@
return;
}
else if (src instanceof CharSequenceBackedByArray) {
- ((CharSequenceBackedByArray)src.subSequence(srcOffset, len)).getChars(dst, dstOffset);
+ ((CharSequenceBackedByArray)src.subSequence(srcOffset, srcOffset + len)).getChars(dst, dstOffset);
return;
}
else if (src instanceof StringBuffer) {
@@ -99,13 +104,12 @@
}
}
+ /**
+ * @deprecated use {@link #fromSequence(CharSequence)}
+ */
@NotNull
public static char[] fromSequenceStrict(@NotNull CharSequence seq) {
- char[] chars = fromSequence(seq);
- if (seq.length() == chars.length) return chars;
- char[] strictChars = new char[seq.length()];
- System.arraycopy(chars, 0, strictChars, 0, seq.length());
- return strictChars;
+ return fromSequence(seq);
}
@Nullable
@@ -126,71 +130,21 @@
/**
* @return the underlying char[] array if any, or the new chara array if not
- * NOTE RETURNED ARRAY LENGTH MAY HAVE BE DIFFERENT FROM THE seq.length()
*/
@NotNull
public static char[] fromSequence(@NotNull CharSequence seq) {
- if (seq instanceof CharSequenceBackedByArray) {
- return ((CharSequenceBackedByArray)seq).getChars();
- }
-
- if (seq instanceof CharBuffer) {
- final CharBuffer buffer = (CharBuffer)seq;
- if (buffer.hasArray() && !buffer.isReadOnly() && buffer.arrayOffset() == 0) {
- return buffer.array();
- // final char[] bufArray = buffer.array();
- // return larger array. Clients may use seq.length() to calculate correct processing range.
- // if (bufArray.length == seq.length())
- // return bufArray;
- }
-
- char[] chars = new char[seq.length()];
- buffer.position(0);
- buffer.get(chars);
- buffer.position(0);
- return chars;
- }
-
- if (seq instanceof StringBuffer) {
- char[] chars = new char[seq.length()];
- ((StringBuffer)seq).getChars(0, seq.length(), chars, 0);
- return chars;
- }
-
- if (seq instanceof String) {
- char[] chars = new char[seq.length()];
- ((String)seq).getChars(0, seq.length(), chars, 0);
- return chars;
- }
-
- return seq.toString().toCharArray();
+ char[] underlying = fromSequenceWithoutCopying(seq);
+ return underlying != null ? Arrays.copyOf(underlying, underlying.length) : fromSequence(seq, 0, seq.length());
}
+ /**
+ * @return a new char array containing the sub-sequence's chars
+ */
@NotNull
public static char[] fromSequence(@NotNull CharSequence seq, int start, int end) {
- if (seq instanceof CharSequenceBackedByArray) {
- return Arrays.copyOfRange(((CharSequenceBackedByArray)seq).getChars(), start, end);
- }
-
- if (seq instanceof CharBuffer) {
- CharBuffer buffer = (CharBuffer)seq;
- char[] chars = new char[end-start];
- buffer.position(start);
- buffer.get(chars, 0, end-start);
- buffer.position(0);
- return chars;
- }
-
- if (seq instanceof StringBuffer) {
- char[] chars = new char[end-start];
- ((StringBuffer)seq).getChars(start, end, chars, 0);
- return chars;
- }
-
- String s = seq.toString();
- char[] chars = new char[end-start];
- s.getChars(start, end, chars, 0);
- return chars;
+ char[] result = new char[end - start];
+ getChars(seq, result, start, 0, end - start);
+ return result;
}
public static int shiftForward(@NotNull CharSequence buffer, int offset, @NotNull String chars) {
diff --git a/platform/util/src/com/intellij/util/text/CharSequenceBackedByArray.java b/platform/util/src/com/intellij/util/text/CharSequenceBackedByArray.java
index 786dfa8..0f41b25 100644
--- a/platform/util/src/com/intellij/util/text/CharSequenceBackedByArray.java
+++ b/platform/util/src/com/intellij/util/text/CharSequenceBackedByArray.java
@@ -19,7 +19,12 @@
import org.jetbrains.annotations.NotNull;
/**
+ * A char sequence base on a char array, Gives access to that array. May be used for performance optimizations
+ *
* @author Maxim.Mossienko
+ * @see com.intellij.util.text.CharArrayExternalizable
+ * @see com.intellij.util.text.CharArrayUtil#getChars(CharSequence, char[], int)
+ * @see com.intellij.util.text.CharArrayUtil#fromSequenceWithoutCopying(CharSequence)
*/
public interface CharSequenceBackedByArray extends CharSequence {
@NotNull
diff --git a/platform/util/src/com/intellij/util/text/CharSequenceHashingStrategy.java b/platform/util/src/com/intellij/util/text/CharSequenceHashingStrategy.java
index 9933b2a..b19f6cd 100644
--- a/platform/util/src/com/intellij/util/text/CharSequenceHashingStrategy.java
+++ b/platform/util/src/com/intellij/util/text/CharSequenceHashingStrategy.java
@@ -15,6 +15,7 @@
*/
package com.intellij.util.text;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import gnu.trove.TObjectHashingStrategy;
@@ -22,27 +23,26 @@
* @author max
*/
public final class CharSequenceHashingStrategy implements TObjectHashingStrategy<CharSequence> {
- private static final int COMPARISON_THRESHOLD = 5;
+ public static final CharSequenceHashingStrategy CASE_SENSITIVE = new CharSequenceHashingStrategy(true);
+ public static final CharSequenceHashingStrategy CASE_INSENSITIVE = new CharSequenceHashingStrategy(false);
+ private final boolean myCaseSensitive;
+
+ @Deprecated
+ public CharSequenceHashingStrategy() {
+ this(true);
+ }
+
+ private CharSequenceHashingStrategy(boolean caseSensitive) {
+ myCaseSensitive = caseSensitive;
+ }
@Override
public int computeHashCode(final CharSequence chars) {
- return StringUtil.stringHashCode(chars);
+ return myCaseSensitive ? StringUtil.stringHashCode(chars) : StringUtil.stringHashCodeInsensitive(chars);
}
@Override
public boolean equals(final CharSequence s1, final CharSequence s2) {
- if(s1 == null || s2 == null) return false;
- if(s1 == s2) return true;
- int len = s1.length();
- if (len != s2.length()) return false;
-
- if (len > COMPARISON_THRESHOLD && s1 instanceof String && s2 instanceof String) {
- return s1.equals(s2);
- }
-
- for (int i = 0; i < len; i++) {
- if (s1.charAt(i) != s2.charAt(i)) return false;
- }
- return true;
+ return Comparing.equal(s1, s2, myCaseSensitive);
}
}
diff --git a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java
index 780b993..78974b3 100644
--- a/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java
+++ b/platform/util/src/com/intellij/util/text/CharSequenceSubSequence.java
@@ -59,4 +59,8 @@
if (myChars instanceof String) return ((String)myChars).substring(myStart, myEnd);
return StringFactory.createShared(CharArrayUtil.fromSequence(myChars, myStart, myEnd));
}
+
+ public CharSequence getBaseSequence() {
+ return myChars;
+ }
}
diff --git a/platform/util/src/com/intellij/util/text/DateFormatUtil.java b/platform/util/src/com/intellij/util/text/DateFormatUtil.java
index b438c2a..85ac4bc 100644
--- a/platform/util/src/com/intellij/util/text/DateFormatUtil.java
+++ b/platform/util/src/com/intellij/util/text/DateFormatUtil.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.mac.foundation.Foundation;
import com.intellij.ui.mac.foundation.ID;
+import com.intellij.util.EnvironmentUtil;
import org.jetbrains.annotations.NotNull;
import java.text.DateFormat;
@@ -41,58 +42,18 @@
public static final long YEAR = DAY * 365;
public static final long DAY_FACTOR = 24L * 60 * 60 * 1000;
+ private enum Period {YEAR, MONTH, WEEK, DAY, HOUR, MINUTE}
+ private enum DateType {TIME, DATE, DATETIME}
+
// do not expose this constants - they are very likely to be changed in future
private static final SyncDateFormat DATE_FORMAT = getFormat(DateFormat.SHORT, DateType.DATE);
private static final SyncDateFormat TIME_FORMAT = getFormat(DateFormat.SHORT, DateType.TIME);
private static final SyncDateFormat TIME_WITH_SECONDS_FORMAT = getFormat(DateFormat.MEDIUM, DateType.TIME);
private static final SyncDateFormat DATE_TIME_FORMAT = getFormat(DateFormat.SHORT, DateType.DATETIME);
- // fixed formats - should be locale-independent
- private static final DateFormat ABOUT_DATE_FORMAT = DateFormat.getDateInstance(DateFormat.LONG, Locale.US);
+ private static final SyncDateFormat ABOUT_DATE_FORMAT = new SyncDateFormat(DateFormat.getDateInstance(DateFormat.LONG, Locale.US));
- private static final long[] DENOMINATORS = new long[]{YEAR, MONTH, WEEK, DAY, HOUR, MINUTE};
-
- private enum Period {
- YEAR, MONTH, WEEK, DAY, HOUR, MINUTE
- }
-
- private static final Period[] PERIODS = new Period[]{Period.YEAR, Period.MONTH, Period.WEEK, Period.DAY, Period.HOUR, Period.MINUTE};
-
- private enum DateType {
- TIME, DATE, DATETIME
- }
-
- private static final int MacFormatterNoStyle = 0;
- private static final int MacFormatterShortStyle = 1;
- private static final int MacFormatterMediumStyle = 2;
- private static final int MacFormatterLongStyle = 3;
- private static final int MacFormatterFullStyle = 4;
- private static final int MacFormatterBehavior_10_4 = 1040;
-
- private static SyncDateFormat getFormat(int format, DateType type) {
- DateFormat result = null;
- if (SystemInfo.isMac) {
- try {
- result = new SimpleDateFormat(getMacTimeFormat(format, type).trim());
- }
- catch (Throwable e) {
- LOG.error(e);
- }
- }
- if (result == null) {
- switch (type) {
- case TIME:
- result = DateFormat.getTimeInstance(format);
- break;
- case DATE:
- result = DateFormat.getDateInstance(format);
- break;
- case DATETIME:
- result = DateFormat.getDateTimeInstance(format, format);
- break;
- }
- }
- return new SyncDateFormat(result);
- }
+ private static final long[] DENOMINATORS = {YEAR, MONTH, WEEK, DAY, HOUR, MINUTE};
+ private static final Period[] PERIODS = {Period.YEAR, Period.MONTH, Period.WEEK, Period.DAY, Period.HOUR, Period.MINUTE};
private DateFormatUtil() { }
@@ -296,6 +257,51 @@
return "";
}
+ @NotNull
+ public static String formatAboutDialogDate(@NotNull Date date) {
+ return ABOUT_DATE_FORMAT.format(date);
+ }
+
+ // helpers
+
+ private static SyncDateFormat getFormat(int format, DateType type) {
+ DateFormat result = null;
+
+ if (SystemInfo.isMac) {
+ try {
+ result = getMacTimeFormat(format, type);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ }
+ }
+
+ if (SystemInfo.isUnix && !SystemInfo.isMac) {
+ try {
+ result = getUnixTimeFormat(format, type);
+ }
+ catch (Throwable t) {
+ LOG.error(t);
+ }
+ }
+
+ if (result == null) {
+ switch (type) {
+ case TIME:
+ result = DateFormat.getTimeInstance(format);
+ break;
+ case DATE:
+ result = DateFormat.getDateInstance(format);
+ break;
+ case DATETIME:
+ result = DateFormat.getDateTimeInstance(format, format);
+ break;
+ }
+ }
+
+ return new SyncDateFormat(result);
+ }
+
private static String someTimeAgoMessage(final Period period, final int n) {
switch (period) {
case DAY:
@@ -330,8 +336,15 @@
}
}
+ private static final int MacFormatterNoStyle = 0;
+ private static final int MacFormatterShortStyle = 1;
+ private static final int MacFormatterMediumStyle = 2;
+ private static final int MacFormatterLongStyle = 3;
+ private static final int MacFormatterFullStyle = 4;
+ private static final int MacFormatterBehavior_10_4 = 1040;
+
@NotNull
- static String getMacTimeFormat(final int type, @NotNull final DateType dateType) {
+ private static SimpleDateFormat getMacTimeFormat(final int type, @NotNull final DateType dateType) {
final ID autoReleasePool = Foundation.invoke("NSAutoreleasePool", "new");
try {
final ID dateFormatter = Foundation.invoke("NSDateFormatter", "new");
@@ -376,100 +389,41 @@
Foundation.invoke(dateFormatter, Foundation.createSelector("setDateStyle:"), dateStyle);
String format = Foundation.toStringViaUTF8(Foundation.invoke(dateFormatter, Foundation.createSelector("dateFormat")));
assert format != null;
- return format;
+ return new SimpleDateFormat(format.trim());
}
finally {
Foundation.invoke(autoReleasePool, Foundation.createSelector("release"));
}
}
- @NotNull
- static String convertMacPattern(@NotNull String macPattern) {
- StringBuilder b = new StringBuilder();
- boolean isSpecial = false;
- boolean isText = false;
+ private static DateFormat getUnixTimeFormat(int format, DateType type) {
+ String localeStr = EnvironmentUtil.getValue("LC_TIME");
+ if (localeStr == null) return null;
- for (int i = 0; i < macPattern.length(); i++) {
- char c = macPattern.charAt(i);
- if (isSpecial) {
- String replacement = null;
- if (c == '%') replacement = "$";
+ localeStr = localeStr.trim();
+ int p = localeStr.indexOf('.');
+ if (p > 0) localeStr = localeStr.substring(0, p);
+ p = localeStr.indexOf('@');
+ if (p > 0) localeStr = localeStr.substring(0, p);
- // year
- if (c == 'y') replacement = "yy";
- if (c == 'Y') replacement = "yyyy";
-
- // month
- if (c == 'm') replacement = "MM";
- if (c == 'b') replacement = "MMM";
- if (c == 'B') replacement = "MMMMM";
-
- // day on month
- if (c == 'e') replacement = "d";
- if (c == 'd') replacement = "dd";
-
- // day of year
- if (c == 'j') replacement = "DDD";
-
- // day of week
- if (c == 'w') replacement = "E"; // SimpleDateFormat doesn't support formatting weekday as a number
- if (c == 'a') replacement = "EEE";
- if (c == 'A') replacement = "EEEEE";
-
- // hours
- if (c == 'H') replacement = "HH"; // 0-24
- //if (c == 'H') replacement = "k"; // 1-24
- //if (c == 'I') replacement = "K"; // 0-11
- if (c == 'I') replacement = "hh"; // 1-12
-
- //minute
- if (c == 'M') replacement = "mm";
- //second
- if (c == 'S') replacement = "ss";
- //millisecond
- if (c == 'F') replacement = "SSS";
-
- //millisecond
- if (c == 'p') replacement = "a";
-
- //millisecond
- if (c == 'Z') replacement = "zzz";
- //millisecond
- if (c == 'z') replacement = "Z";
-
-
- //todo if (c == 'c') replacement = "MMMMM";, x, X
-
- if (replacement == null) replacement = "'?%" + c + "?'";
-
- b.append(replacement);
- isSpecial = false;
- }
- else {
- isSpecial = c == '%';
- if (isSpecial) {
- isText = false;
- }
- else {
- if (isText) {
- if (c == '\'' || Character.isWhitespace(c)) b.append('\'');
- isText = !Character.isWhitespace(c);
- }
- else {
- if (c == '\'' || !Character.isWhitespace(c)) b.append('\'');
- isText = !Character.isWhitespace(c) && c != '\'';
- }
- b.append(c);
-
- if (isText && i == macPattern.length() - 1) b.append('\'');
- }
- }
+ Locale locale;
+ p = localeStr.indexOf('_');
+ if (p < 0) {
+ locale = new Locale(localeStr);
}
- return b.toString();
- }
+ else {
+ locale = new Locale(localeStr.substring(0, p), localeStr.substring(p + 1));
+ }
- @NotNull
- public static String formatAboutDialogDate(@NotNull Date date) {
- return ABOUT_DATE_FORMAT.format(date);
+ switch (type) {
+ case TIME:
+ return DateFormat.getTimeInstance(format, locale);
+ case DATE:
+ return DateFormat.getDateInstance(format, locale);
+ case DATETIME:
+ return DateFormat.getDateTimeInstance(format, format, locale);
+ }
+
+ return null;
}
}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/text/ImmutableCharSequence.java b/platform/util/src/com/intellij/util/text/ImmutableCharSequence.java
new file mode 100644
index 0000000..6c2823a
--- /dev/null
+++ b/platform/util/src/com/intellij/util/text/ImmutableCharSequence.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.intellij.util.text;
+
+import org.jetbrains.annotations.NotNull;
+
+public abstract class ImmutableCharSequence implements CharSequence {
+
+ public static CharSequence asImmutable(@NotNull final CharSequence cs) {
+ return isImmutable(cs) ? cs : cs.toString();
+ }
+
+ public static boolean isImmutable(@NotNull final CharSequence cs) {
+ if (cs instanceof ImmutableCharSequence) return true;
+ if (cs instanceof CharSequenceSubSequence) return isImmutable(((CharSequenceSubSequence)cs).getBaseSequence());
+ return false;
+ }
+
+}
diff --git a/platform/util/src/com/intellij/util/text/ImmutableText.java b/platform/util/src/com/intellij/util/text/ImmutableText.java
new file mode 100644
index 0000000..c739be1
--- /dev/null
+++ b/platform/util/src/com/intellij/util/text/ImmutableText.java
@@ -0,0 +1,851 @@
+/*
+ * Javolution - Java(tm) Solution for Real-Time and Embedded Systems
+ * Copyright (c) 2012, Javolution (http://javolution.org/)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package com.intellij.util.text;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.Writer;
+
+/**
+ * A pruned and optimized version of javolution.text.Text
+ *
+ * <p> This class represents an immutable character sequence with
+ * fast {@link #concat concatenation}, {@link #insert insertion} and
+ * {@link #delete deletion} capabilities (O[Log(n)]) instead of
+ * O[n] for StringBuffer/StringBuilder).</p>
+ * <p> This class has the same methods as
+ * <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html">
+ * Java String</a> with the following benefits:<ul>
+ * <li> No need for an intermediate
+ * {@link StringBuffer}/{@link StringBuilder} in order to manipulate
+ * textual documents (insertion, deletion or concatenation).</li>
+ * <li> More flexible as they allows for search and comparison with any
+ * <code>java.lang.String</code> or <code>CharSequence</code>.</li>
+ * </ul></p>
+ *
+ * <p><i> Implementation Note: To avoid expensive copy operations ,
+ * {@link ImmutableText} instances are broken down into smaller immutable
+ * sequences, they form a minimal-depth binary tree.
+ * The tree is maintained balanced automatically through <a
+ * href="http://en.wikipedia.org/wiki/Tree_rotation">tree rotations</a>.
+ * Insertion/deletions are performed in <code>O[Log(n)]</code>
+ * instead of <code>O[n]</code> for
+ * <code>StringBuffer/StringBuilder</code>.</i></p>
+ *
+ * @author <a href="mailto:jean-marie@dautelle.com">Jean-Marie Dautelle</a>
+ * @author Wilfried Middleton
+ * @version 5.3, January 10, 2007
+ */
+@SuppressWarnings("AssignmentToForLoopParameter")
+public final class ImmutableText extends ImmutableCharSequence implements CharArrayExternalizable {
+
+ /**
+ * Holds the default size for primitive blocks of characters.
+ */
+ private static final int BLOCK_SIZE = 1 << 6;
+
+ /**
+ * Holds the mask used to ensure a block boundary cesures.
+ */
+ private static final int BLOCK_MASK = ~(BLOCK_SIZE - 1);
+
+ /**
+ * Holds the primitive text factory.
+ */
+
+ /**
+ * Holds the raw data (primitive) or <code>null</code> (composite).
+ */
+ private final char[] _data;
+
+ /**
+ * Holds the total number of characters.
+ */
+ private final int _count;
+
+ /**
+ * Holds the head block of character (composite).
+ */
+ private final ImmutableText _head;
+
+ /**
+ * Holds the tail block of character (composite).
+ */
+ private final ImmutableText _tail;
+
+ private ImmutableText(char[] data) {
+ _data = data;
+ _count = data.length;
+ _head = _tail = null;
+ }
+
+ private ImmutableText(ImmutableText head, ImmutableText tail) {
+ _count = head._count + tail._count;
+ _data = null;
+ _head = head;
+ _tail = tail;
+ }
+
+ /**
+ * Returns the text representing the specified object.
+ *
+ * @param obj the object to represent as text.
+ * @return the textual representation of the specified object.
+ */
+ public static ImmutableText valueOf(@NotNull Object obj) {
+ if (obj instanceof ImmutableText) return (ImmutableText)obj;
+ if (obj instanceof CharSequence) return ((CharSequence)obj).length() == 0 ? EMPTY : valueOf((CharSequence)obj);
+ return valueOf(String.valueOf(obj));
+ }
+
+ private static ImmutableText valueOf(@NotNull CharSequence str) {
+ return valueOf(str, 0, str.length());
+ }
+
+ private static ImmutableText valueOf(@NotNull CharSequence str, int start, int end) {
+ int length = end - start;
+ if (length <= BLOCK_SIZE) {
+ return new ImmutableText(CharArrayUtil.fromSequence(str, start, end));
+ }
+
+ // Splits on a block boundary.
+ int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
+ return new ImmutableText(valueOf(str, start, start + half), valueOf(str, start + half, end));
+ }
+
+ /**
+ * Returns the text that contains the characters from the specified
+ * array.
+ *
+ * @param chars the array source of the characters.
+ * @return the corresponding instance.
+ */
+ public static ImmutableText valueOf(@NotNull char[] chars) {
+ return valueOf(chars, 0, chars.length);
+ }
+
+ /**
+ * Returns the text that contains the characters from the specified
+ * subarray of characters.
+ *
+ * @param chars the source of the characters.
+ * @param offset the index of the first character in the data source.
+ * @param length the length of the text returned.
+ * @return the corresponding instance.
+ * @throws IndexOutOfBoundsException if <code>(offset < 0) ||
+ * (length < 0) || ((offset + length) > chars.length)</code>
+ */
+ public static ImmutableText valueOf(@NotNull char[] chars, int offset, int length) {
+ if ((offset < 0) || (length < 0) || ((offset + length) > chars.length))
+ throw new IndexOutOfBoundsException();
+ if (length <= BLOCK_SIZE) {
+ if (offset == 0 && length == chars.length) {
+ return new ImmutableText(chars);
+ }
+ char[] subArray = new char[length];
+ System.arraycopy(chars, offset, subArray, 0, length);
+ return new ImmutableText(subArray);
+ } else { // Splits on a block boundary.
+ int half = ((length + BLOCK_SIZE) >> 1) & BLOCK_MASK;
+ return new ImmutableText(valueOf(chars, offset, half), valueOf(chars, offset + half, length - half));
+ }
+ }
+
+
+ /**
+ * Returns the text representation of the <code>boolean</code> argument.
+ *
+ * @param b a <code>boolean</code>.
+ * @return if the argument is <code>true</code>, the text
+ * <code>"true"</code> is returned; otherwise, the text
+ * <code>"false"</code> is returned.
+ */
+ public static ImmutableText valueOf(boolean b) {
+ return b ? TRUE : FALSE;
+ }
+
+ private static final ImmutableText TRUE = valueOf("true");
+
+ private static final ImmutableText FALSE = valueOf("false");
+
+ private static final ImmutableText EMPTY = valueOf("");
+
+ /**
+ * Returns the length of this text.
+ *
+ * @return the number of characters (16-bits Unicode) composing this text.
+ */
+ public int length() {
+ return _count;
+ }
+
+ /**
+ * Returns the concatenation of this text and the textual
+ * representation of the specified object.
+ *
+ * @param obj the object whose textual representation is concatenated.
+ * @return <code>this.concat(Text.valueOf(obj))</code>
+ */
+ public ImmutableText plus(Object obj) {
+ return this.concat(valueOf(obj));
+ }
+
+ /**
+ * Returns the concatenation of this text and the specified
+ * <code>String</code> (optimization).
+ *
+ * @param str the string whose characters are concatenated.
+ * @return <code>this.concat(Text.valueOf(obj))</code>
+ */
+ public ImmutableText plus(String str) {
+
+ ImmutableText merge = this.append(str);
+ return merge != null ? merge : concat(valueOf(str));
+ }
+
+ private ImmutableText append(String str) { // Try to append, returns null if cannot.
+ int length = str.length();
+ if (_data == null) {
+ ImmutableText merge = _tail.append(str);
+ return merge != null ? new ImmutableText(_head, merge) : null;
+ } else { // Primitive.
+ if (_count + length > BLOCK_SIZE) return null; // Cannot merge.
+ char[] chars = new char[_count + length];
+ System.arraycopy(_data, 0, chars, 0, _count);
+ str.getChars(0, length, chars, _count);
+ return new ImmutableText(chars);
+ }
+ }
+
+ /**
+ * Concatenates the specified text to the end of this text.
+ * This method is very fast (faster even than
+ * <code>StringBuffer.append(String)</code>) and still returns
+ * a text instance with an internal binary tree of minimal depth!
+ *
+ * @param that the text that is concatenated.
+ * @return <code>this + that</code>
+ */
+ public ImmutableText concat(ImmutableText that) {
+ if (that.length() == 0) {
+ return this;
+ }
+
+ // All Text instances are maintained balanced:
+ // (head < tail * 2) & (tail < head * 2)
+
+ final int length = this._count + that._count;
+ if (length <= BLOCK_SIZE) { // Merges to primitive.
+ char[] chars = new char[length];
+ this.getChars(0, this._count, chars, 0);
+ that.getChars(0, that._count, chars, this._count);
+ return new ImmutableText(chars);
+ } else { // Returns a composite.
+ ImmutableText head = this;
+ ImmutableText tail = that;
+
+ if (((head._count << 1) < tail._count) && (tail._data == null)) { // tail is composite
+ // head too small, returns (head + tail/2) + (tail/2)
+ if (tail._head._count > tail._tail._count) {
+ // Rotates to concatenate with smaller part.
+ tail = tail.rightRotation();
+ }
+ head = head.concat(tail._head);
+ tail = tail._tail;
+
+ } else if (((tail._count << 1) < head._count)
+ && (head._data == null)) { // head is composite.
+ // tail too small, returns (head/2) + (head/2 concat tail)
+ if (head._tail._count > head._head._count) {
+ // Rotates to concatenate with smaller part.
+ head = head.leftRotation();
+ }
+ tail = head._tail.concat(tail);
+ head = head._head;
+ }
+ return new ImmutableText(head, tail);
+ }
+ }
+
+ private ImmutableText rightRotation() {
+ // See: http://en.wikipedia.org/wiki/Tree_rotation
+ ImmutableText P = this._head;
+ if (P._data != null)
+ return this; // Head not a composite, cannot rotate.
+ ImmutableText A = P._head;
+ ImmutableText B = P._tail;
+ ImmutableText C = this._tail;
+ return new ImmutableText(A, new ImmutableText(B, C));
+ }
+
+ private ImmutableText leftRotation() {
+ // See: http://en.wikipedia.org/wiki/Tree_rotation
+ ImmutableText Q = this._tail;
+ if (Q._data != null)
+ return this; // Tail not a composite, cannot rotate.
+ ImmutableText B = Q._head;
+ ImmutableText C = Q._tail;
+ ImmutableText A = this._head;
+ return new ImmutableText(new ImmutableText(A, B), C);
+ }
+
+ /**
+ * Returns a portion of this text.
+ *
+ * @param start the index of the first character inclusive.
+ * @return the sub-text starting at the specified position.
+ * @throws IndexOutOfBoundsException if <code>(start < 0) ||
+ * (start > this.length())</code>
+ */
+ public ImmutableText subtext(int start) {
+ return subtext(start, length());
+ }
+
+ /**
+ * Returns the text having the specified text inserted at
+ * the specified location.
+ *
+ * @param index the insertion position.
+ * @param txt the text being inserted.
+ * @return <code>subtext(0, index).concat(txt).concat(subtext(index))</code>
+ * @throws IndexOutOfBoundsException if <code>(index < 0) ||
+ * (index > this.length())</code>
+ */
+ public ImmutableText insert(int index, ImmutableText txt) {
+ return subtext(0, index).concat(txt).concat(subtext(index));
+ }
+
+ public ImmutableText insert(int index, CharSequence seq) {
+ return insert(index, valueOf(seq));
+ }
+
+ /**
+ * Returns the text without the characters between the specified indexes.
+ *
+ * @param start the beginning index, inclusive.
+ * @param end the ending index, exclusive.
+ * @return <code>subtext(0, start).concat(subtext(end))</code>
+ * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+ * (start > end) || (end > this.length()</code>
+ */
+ public ImmutableText delete(int start, int end) {
+ if (start == end) return this;
+ if (start > end)
+ throw new IndexOutOfBoundsException();
+ return subtext(0, start).concat(subtext(end));
+ }
+
+ /**
+ * Replaces each character sequence of this text that matches the specified
+ * target sequence with the specified replacement sequence.
+ *
+ * @param target the character sequence to be replaced.
+ * @param replacement the replacement sequence.
+ * @return the resulting text.
+ */
+ public ImmutableText replace(CharSequence target, CharSequence replacement) {
+ int i = indexOf(target);
+ return (i < 0) ? this : // No target sequence found.
+ subtext(0, i).concat(valueOf(replacement)).concat(
+ subtext(i + target.length()).replace(target,
+ replacement));
+ }
+
+ public CharSequence subSequence(final int start, final int end) {
+ if (start == 0 && end == length()) return this;
+ return new CharSequenceSubSequence(this, start, end);
+ }
+
+ /**
+ * Returns the index within this text of the first occurrence
+ * of the specified character sequence searching forward.
+ *
+ * @param csq a character sequence.
+ * @return the index of the first character of the character sequence found;
+ * or <code>-1</code> if the character sequence is not found.
+ */
+ public int indexOf(CharSequence csq) {
+ return indexOf(csq, 0);
+ }
+
+ /**
+ * Returns the index within this text of the first occurrence
+ * of the specified characters sequence searching forward from
+ * the specified index.
+ *
+ * @param csq a character sequence.
+ * @param fromIndex the index to start the search from.
+ * @return the index in the range
+ * <code>[fromIndex, length() - csq.length()]</code>
+ * or <code>-1</code> if the character sequence is not found.
+ */
+ public int indexOf(CharSequence csq, int fromIndex) {
+
+ // Limit cases.
+ final int csqLength = csq.length();
+ final int min = Math.max(0, fromIndex);
+ final int max = _count - csqLength;
+ if (csqLength == 0) {
+ return (min > max) ? -1 : min;
+ }
+
+ // Searches for csq.
+ final char c = csq.charAt(0);
+ for (int i = indexOf(c, min); (i >= 0) && (i <= max); i = indexOf(c,
+ ++i)) {
+ boolean match = true;
+ for (int j = 1; j < csqLength; j++) {
+ if (this.charAt(i + j) != csq.charAt(j)) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ /**
+ * Returns the index within this text of the last occurrence of
+ * the specified characters sequence searching backward.
+ *
+ * @param csq a character sequence.
+ * @return the index of the first character of the character sequence found;
+ * or <code>-1</code> if the character sequence is not found.
+ */
+ public int lastIndexOf(CharSequence csq) {
+ return lastIndexOf(csq, _count);
+ }
+
+ /**
+ * Returns the index within this text of the last occurrence of
+ * the specified character sequence searching backward from the specified
+ * index.
+ *
+ * @param csq a character sequence.
+ * @param fromIndex the index to start the backward search from.
+ * @return the index in the range <code>[0, fromIndex]</code> or
+ * <code>-1</code> if the character sequence is not found.
+ */
+ public int lastIndexOf(CharSequence csq, int fromIndex) {
+
+ // Limit cases.
+ final int csqLength = csq.length();
+ final int min = 0;
+ final int max = Math.min(fromIndex, _count - csqLength);
+ if (csqLength == 0) {
+ return (min > max) ? -1 : max;
+ }
+
+ // Searches for csq.
+ final char c = csq.charAt(0);
+ for (int i = lastIndexOf(c, max); (i >= 0); i = lastIndexOf(c, --i)) {
+ boolean match = true;
+ for (int j = 1; j < csqLength; j++) {
+ if (this.charAt(i + j) != csq.charAt(j)) {
+ match = false;
+ break;
+ }
+ }
+ if (match) {
+ return i;
+ }
+ }
+ return -1;
+
+ }
+
+ /**
+ * Indicates if this text starts with the specified prefix.
+ *
+ * @param prefix the prefix.
+ * @return <code>true</code> if the character sequence represented by the
+ * argument is a prefix of the character sequence represented by
+ * this text; <code>false</code> otherwise.
+ */
+ public boolean startsWith(CharSequence prefix) {
+ return startsWith(prefix, 0);
+ }
+
+ /**
+ * Indicates if this text ends with the specified suffix.
+ *
+ * @param suffix the suffix.
+ * @return <code>true</code> if the character sequence represented by the
+ * argument is a suffix of the character sequence represented by
+ * this text; <code>false</code> otherwise.
+ */
+ public boolean endsWith(CharSequence suffix) {
+ return startsWith(suffix, length() - suffix.length());
+ }
+
+ /**
+ * Indicates if this text starts with the specified prefix
+ * at the specified index.
+ *
+ * @param prefix the prefix.
+ * @param index the index of the prefix location in this string.
+ * @return <code>this.substring(index).startsWith(prefix)</code>
+ */
+ public boolean startsWith(CharSequence prefix, int index) {
+ final int prefixLength = prefix.length();
+ if ((index >= 0) && (index <= (this.length() - prefixLength))) {
+ for (int i = 0, j = index; i < prefixLength;) {
+ if (prefix.charAt(i++) != this.charAt(j++)) {
+ return false;
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns a copy of this text, with leading and trailing
+ * whitespace omitted.
+ *
+ * @return a copy of this text with leading and trailing white
+ * space removed, or this text if it has no leading or
+ * trailing white space.
+ */
+ public ImmutableText trim() {
+ int first = 0; // First character index.
+ int last = length() - 1; // Last character index.
+ while ((first <= last) && (charAt(first) <= ' ')) {
+ first++;
+ }
+ while ((last >= first) && (charAt(last) <= ' ')) {
+ last--;
+ }
+ return subtext(first, last + 1);
+ }
+
+ /**
+ * Indicates if this text has the same character content as the specified
+ * character sequence.
+ *
+ * @param csq the character sequence to compare with.
+ * @return <code>true</code> if the specified character sequence has the
+ * same character content as this text; <code>false</code> otherwise.
+ */
+ public boolean contentEquals(CharSequence csq) {
+ if (csq.length() != _count)
+ return false;
+ for (int i = 0; i < _count;) {
+ if (this.charAt(i) != csq.charAt(i++))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Compares this text against the specified object for equality.
+ * Returns <code>true</code> if the specified object is a text having
+ * the same character sequence as this text.
+ * For generic comparison with any character sequence the
+ * {@link #contentEquals(CharSequence)} should be used.
+ *
+ * @param obj the object to compare with or <code>null</code>.
+ * @return <code>true</code> if that is a text with the same character
+ * sequence as this text; <code>false</code> otherwise.
+ */
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (!(obj instanceof ImmutableText))
+ return false;
+ final ImmutableText that = (ImmutableText) obj;
+ if (this._count != that._count)
+ return false;
+ for (int i = 0; i < _count;) {
+ if (this.charAt(i) != that.charAt(i++))
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Returns the hash code for this text.
+ *
+ * @return the hash code value.
+ */
+ public int hashCode() {
+ int h = 0;
+ final int length = this.length();
+ for (int i = 0; i < length;) {
+ h = 31 * h + charAt(i++);
+ }
+ return h;
+ }
+
+ /**
+ * Prints the current statistics on this text tree structure.
+ *
+ * @param out the stream to use for output (e.g. <code>System.out</code>)
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public void printStatistics(PrintStream out) {
+ int length = this.length();
+ int leaves = getNbrOfLeaves();
+ out.print("LENGTH: " + length());
+ out.print(", MAX DEPTH: " + getDepth());
+ out.print(", NBR OF BRANCHES: " + getNbrOfBranches());
+ out.print(", NBR OF LEAVES: " + leaves);
+ out.print(", AVG LEAVE LENGTH: " + (length + (leaves >> 1)) / leaves);
+ out.println();
+ }
+ private int getDepth() {
+ if (_data != null) // Primitive.
+ return 0;
+ return Math.max(_head.getDepth(), _tail.getDepth()) + 1;
+ }
+ private int getNbrOfBranches() {
+ return (_data == null) ?
+ _head.getNbrOfBranches() + _tail.getNbrOfBranches() + 1 : 0;
+ }
+ private int getNbrOfLeaves() {
+ return (_data == null) ?
+ _head.getNbrOfLeaves() + _tail.getNbrOfLeaves() : 1;
+ }
+
+ /**
+ * Prints out this text to the specified writer.
+ *
+ * @param writer the destination writer.
+ */
+ public void print(Writer writer) throws IOException {
+ if (_data != null) { // Primitive
+ writer.write(_data, 0, _count);
+ } else { // Composite.
+ _head.print(writer);
+ _tail.print(writer);
+ }
+ }
+
+ /**
+ * Prints out this text to the specified writer and then terminates
+ * the line.
+ *
+ * @param writer the destination writer.
+ */
+ public void println(Writer writer) throws IOException {
+ print(writer);
+ writer.write('\n');
+ }
+
+ /**
+ * Returns the character at the specified index.
+ *
+ * @param index the index of the character.
+ * @return the character at the specified index.
+ * @throws IndexOutOfBoundsException if <code>(index < 0) ||
+ * (index >= this.length())</code>
+ */
+ public char charAt(int index) {
+ InnerLeaf leaf = myLastLeaf;
+ if (leaf == null || index < leaf.offset || index >= leaf.offset + leaf.leafText._count) {
+ myLastLeaf = leaf = findLeaf(index, 0);
+ }
+ return leaf.leafText._data[index - leaf.offset];
+ }
+ private volatile InnerLeaf myLastLeaf;
+
+ private InnerLeaf findLeaf(int index, int offset) {
+ ImmutableText node = this;
+ while (true) {
+ if (index >= node._count) {
+ throw new IndexOutOfBoundsException();
+ }
+ if (node._data != null) {
+ return new InnerLeaf(node, offset);
+ }
+ if (index < node._head._count) {
+ node = node._head;
+ } else {
+ offset += node._head._count;
+ index -= node._head._count;
+ node = node._tail;
+ }
+ }
+ }
+
+ private static class InnerLeaf {
+ final ImmutableText leafText;
+ final int offset;
+
+ private InnerLeaf(ImmutableText leafText, int offset) {
+ this.leafText = leafText;
+ this.offset = offset;
+ }
+ }
+
+ /**
+ * Returns the index within this text of the first occurrence of the
+ * specified character, starting the search at the specified index.
+ *
+ * @param c the character to search for.
+ * @param fromIndex the index to start the search from.
+ * @return the index of the first occurrence of the character in this text
+ * that is greater than or equal to <code>fromIndex</code>,
+ * or <code>-1</code> if the character does not occur.
+ */
+ public int indexOf(char c, int fromIndex) {
+ if (_data != null) { // Primitive.
+ for (int i = Math.max(fromIndex, 0); i < _count; i++) {
+ if (_data[i] == c)
+ return i;
+ }
+ return -1;
+ } else { // Composite.
+ final int cesure = _head._count;
+ if (fromIndex < cesure) {
+ final int headIndex = _head.indexOf(c, fromIndex);
+ if (headIndex >= 0)
+ return headIndex; // Found in head.
+ }
+ final int tailIndex = _tail.indexOf(c, fromIndex - cesure);
+ return (tailIndex >= 0) ? tailIndex + cesure : -1;
+ }
+ }
+
+ /**
+ * Returns the index within this text of the first occurrence of the
+ * specified character, searching backward and starting at the specified
+ * index.
+ *
+ * @param c the character to search for.
+ * @param fromIndex the index to start the search backward from.
+ * @return the index of the first occurrence of the character in this text
+ * that is less than or equal to <code>fromIndex</code>,
+ * or <code>-1</code> if the character does not occur.
+ */
+ public int lastIndexOf(char c, int fromIndex) {
+ if (_data != null) { // Primitive.
+ for (int i = Math.min(fromIndex, _count - 1); i >= 0; i--) {
+ if (_data[i] == c)
+ return i;
+ }
+ return -1;
+ } else { // Composite.
+ final int cesure = _head._count;
+ if (fromIndex >= cesure) {
+ final int tailIndex = _tail.lastIndexOf(c, fromIndex - cesure);
+ if (tailIndex >= 0)
+ return tailIndex + cesure; // Found in tail.
+ }
+ return _head.lastIndexOf(c, fromIndex);
+ }
+ }
+
+ /**
+ * Returns a portion of this text.
+ *
+ * @param start the index of the first character inclusive.
+ * @param end the index of the last character exclusive.
+ * @return the sub-text starting at the specified start position and
+ * ending just before the specified end position.
+ * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+ * (start > end) || (end > this.length())</code>
+ */
+ public ImmutableText subtext(int start, int end) {
+ if (_data != null) { // Primitive.
+ if ((start < 0) || (start > end) || (end > _count))
+ throw new IndexOutOfBoundsException();
+ if ((start == 0) && (end == _count))
+ return this;
+ if (start == end)
+ return EMPTY;
+ int length = end - start;
+ char[] chars = new char[length];
+ System.arraycopy(_data, start, chars, 0, length);
+ return new ImmutableText(chars);
+ } else { // Composite.
+ final int cesure = _head._count;
+ if (end <= cesure)
+ return _head.subtext(start, end);
+ if (start >= cesure)
+ return _tail.subtext(start - cesure, end - cesure);
+ if ((start == 0) && (end == _count))
+ return this;
+ // Overlaps head and tail.
+ return _head.subtext(start, cesure).concat(
+ _tail.subtext(0, end - cesure));
+ }
+ }
+
+ /**
+ * Copies the characters from this text into the destination
+ * character array.
+ *
+ * @param start the index of the first character to copy.
+ * @param end the index after the last character to copy.
+ * @param dest the destination array.
+ * @param destPos the start offset in the destination array.
+ * @throws IndexOutOfBoundsException if <code>(start < 0) || (end < 0) ||
+ * (start > end) || (end > this.length())</code>
+ */
+ public void getChars(int start, int end, @NotNull char[] dest, int destPos) {
+ if (_data != null) { // Primitive.
+ if ((start < 0) || (end > _count) || (start > end))
+ throw new IndexOutOfBoundsException();
+ System.arraycopy(_data, start, dest, destPos, end - start);
+ } else { // Composite.
+ final int cesure = _head._count;
+ if (end <= cesure) {
+ _head.getChars(start, end, dest, destPos);
+ } else if (start >= cesure) {
+ _tail.getChars(start - cesure, end - cesure, dest, destPos);
+ } else { // Overlaps head and tail.
+ _head.getChars(start, cesure, dest, destPos);
+ _tail.getChars(0, end - cesure, dest, destPos + cesure - start);
+ }
+ }
+ }
+
+ /**
+ * Returns the <code>String</code> representation of this text.
+ *
+ * @return the <code>java.lang.String</code> for this text.
+ */
+ @NotNull
+ public String toString() {
+ if (_data != null) { // Primitive.
+ return new String(_data, 0, _count);
+ } else { // Composite.
+ char[] data = new char[_count];
+ this.getChars(0, _count, data, 0);
+ return new String(data, 0, _count);
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/text/VersionComparatorUtil.java b/platform/util/src/com/intellij/util/text/VersionComparatorUtil.java
index 9ad45ae..3408e63 100644
--- a/platform/util/src/com/intellij/util/text/VersionComparatorUtil.java
+++ b/platform/util/src/com/intellij/util/text/VersionComparatorUtil.java
@@ -169,14 +169,7 @@
}
private static int comparePriorities(VersionTokenType t1, VersionTokenType t2) {
- final int p1 = t1.getPriority();
- final int p2 = t2.getPriority();
-
- if (p1 == p2) {
- return 0;
- } else {
- return p1 > p2 ? 1 : -1;
- }
+ return Integer.signum(t1.getPriority() - t2.getPriority());
}
private static int compareNumbers(String n1, String n2) {
diff --git a/platform/util/src/com/intellij/util/ui/ColumnInfo.java b/platform/util/src/com/intellij/util/ui/ColumnInfo.java
index c581ec1..8289633 100644
--- a/platform/util/src/com/intellij/util/ui/ColumnInfo.java
+++ b/platform/util/src/com/intellij/util/ui/ColumnInfo.java
@@ -80,6 +80,10 @@
}
@Nullable
+ /**
+ * @see com.intellij.util.ui.table.IconTableCellRenderer
+ * @see com.intellij.util.ui.LocalPathCellEditor
+ */
public TableCellRenderer getRenderer(Item item) {
return null;
}
@@ -89,7 +93,10 @@
}
@Nullable
- public TableCellEditor getEditor(Item o) {
+ /**
+ * @see com.intellij.util.ui.table.ComboBoxTableCellEditor
+ */
+ public TableCellEditor getEditor(Item item) {
return null;
}
diff --git a/platform/util/src/com/intellij/util/ui/ComboBoxTableCellEditor.java b/platform/util/src/com/intellij/util/ui/ComboBoxTableCellEditor.java
index 2c89507..79ae369 100644
--- a/platform/util/src/com/intellij/util/ui/ComboBoxTableCellEditor.java
+++ b/platform/util/src/com/intellij/util/ui/ComboBoxTableCellEditor.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,10 +22,10 @@
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.Iterator;
+@Deprecated
/**
- * author: lesya
+ * @deprecated Please use {@link com.intellij.util.ui.table.ComboBoxTableCellEditor}
*/
public class ComboBoxTableCellEditor extends AbstractTableCellEditor {
public static final ComboBoxTableCellEditor INSTANCE = new ComboBoxTableCellEditor();
@@ -53,8 +53,9 @@
options.selectFirst();
}
myComboBox.removeAllItems();
- for (Iterator each = options.iterator(); each.hasNext();) {
- myComboBox.addItem(each.next());
+ for (Object option : options) {
+ //noinspection unchecked
+ myComboBox.addItem(option);
}
myComboBox.setSelectedItem(options.getSelection());
diff --git a/platform/util/src/com/intellij/util/ui/EditableModel.java b/platform/util/src/com/intellij/util/ui/EditableModel.java
index f468979..c80ecda 100644
--- a/platform/util/src/com/intellij/util/ui/EditableModel.java
+++ b/platform/util/src/com/intellij/util/ui/EditableModel.java
@@ -19,11 +19,9 @@
* @author Konstantin Bulenkov
* @since 11.0
*/
-public interface EditableModel {
+public interface EditableModel extends ItemRemovable {
void addRow();
- void removeRow(int index);
-
void exchangeRows(int oldIndex, int newIndex);
boolean canExchangeRows(int oldIndex, int newIndex);
diff --git a/platform/util/src/com/intellij/util/ui/FadeInFadeOut.java b/platform/util/src/com/intellij/util/ui/FadeInFadeOut.java
new file mode 100644
index 0000000..3e1ec9e
--- /dev/null
+++ b/platform/util/src/com/intellij/util/ui/FadeInFadeOut.java
@@ -0,0 +1,104 @@
+/*
+ * 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.util.ui;
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+
+/**
+ * It supposed to cover whole area of JLayeredPane and process "FadeIn&Out" effects with its inner components
+ */
+
+public class FadeInFadeOut extends JComponent {
+ public static final Integer LAYER = new Integer(JLayeredPane.POPUP_LAYER + 1);
+
+ @NotNull
+ private final Component myComponent;
+ private final BufferedImage myComponentImage;
+ private Rectangle myComponentBounds;
+
+ @NotNull
+ private final Component myIcon;
+ private Rectangle myIconBounds;
+
+ private final boolean myFadeIn;
+
+ private boolean myTriggered = false;
+ private final int myTimeToComplete;
+ private double myRatio = 0;
+
+ public FadeInFadeOut(@NotNull Component component, int timeToComplete, boolean fadeIn, @NotNull Component icon) {
+ setFocusable(false);
+ myComponent = component;
+ myTimeToComplete = timeToComplete;
+ myFadeIn = fadeIn;
+ myRatio = myFadeIn ? 0 : 1;
+ myIcon = icon;
+
+ myComponentImage = UIUtil.createImage(myComponent.getWidth(), myComponent.getHeight(), BufferedImage.TYPE_INT_ARGB);
+ Graphics2D graphics = myComponentImage.createGraphics();
+ myComponent.paint(graphics);
+ graphics.dispose();
+ }
+
+ @Override
+ public void reshape(int x, int y, int w, int h) {
+ super.reshape(x, y, w, h);
+ if (!myTriggered) {
+ myComponentBounds = SwingUtilities.convertRectangle(myComponent.getParent(), myComponent.getBounds(), this);
+ myIconBounds = SwingUtilities.convertRectangle(myIcon.getParent(), myIcon.getBounds(), this);
+ }
+ }
+
+ public void doAnimation() {
+ if (myTriggered || !isShowing()) return;
+
+ myTriggered = true;
+ long startTime = System.currentTimeMillis();
+ while (true) {
+ paintImmediately(0, 0, getWidth(), getHeight());
+ final long timeSpent = System.currentTimeMillis() - startTime;
+ if (timeSpent >= myTimeToComplete) {
+ return;
+ }
+ double linearProgress = Math.max(0, Math.min(1, (double)timeSpent / myTimeToComplete));
+ if (!myFadeIn) linearProgress = 1 - linearProgress;
+ myRatio = (1 - Math.cos(Math.PI * linearProgress)) / 2;
+ }
+ }
+
+ public final void paint(final Graphics g_) {
+ long l = System.currentTimeMillis();
+ int x = (int)(myIconBounds.x * (1 - myRatio) + myComponentBounds.x * myRatio);
+ int y = (int)(myIconBounds.y * (1 - myRatio) + myComponentBounds.y * myRatio);
+ int width = (int)(myIconBounds.width * (1 - myRatio) + myComponentBounds.width * myRatio);
+ int height = (int)(myIconBounds.height * (1 - myRatio) + myComponentBounds.height * myRatio);
+ Graphics2D g = (Graphics2D)g_.create();
+ try {
+ g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .5F + (float)(myRatio / 2)));
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
+ g.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
+ g.drawImage(myComponentImage, x, y, width, height, this);
+ }
+ finally {
+ g.dispose();
+ }
+ }
+}
diff --git a/platform/util/src/com/intellij/util/ui/Html.java b/platform/util/src/com/intellij/util/ui/Html.java
index 6189ebc..d322030 100644
--- a/platform/util/src/com/intellij/util/ui/Html.java
+++ b/platform/util/src/com/intellij/util/ui/Html.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,7 +17,7 @@
public class Html {
- private String myText;
+ private final String myText;
private boolean myKeepFont = false;
public Html(String text) {
diff --git a/platform/util/src/com/intellij/util/ui/ListTableModel.java b/platform/util/src/com/intellij/util/ui/ListTableModel.java
index df39acc..9577ab2 100644
--- a/platform/util/src/com/intellij/util/ui/ListTableModel.java
+++ b/platform/util/src/com/intellij/util/ui/ListTableModel.java
@@ -22,7 +22,7 @@
import javax.swing.*;
import java.util.*;
-public class ListTableModel<Item> extends TableViewModel<Item> implements ItemRemovable, EditableModel {
+public class ListTableModel<Item> extends TableViewModel<Item> implements EditableModel {
private ColumnInfo[] myColumnInfos;
private List<Item> myItems;
private int mySortByColumn;
@@ -38,6 +38,10 @@
this(columnNames, items, selectedColumn, SortOrder.ASCENDING);
}
+ public ListTableModel(@NotNull ColumnInfo[] columnNames, @NotNull List<Item> items) {
+ this(columnNames, items, 0);
+ }
+
public ListTableModel(@NotNull ColumnInfo[] columnNames, @NotNull List<Item> items, int selectedColumn, @NotNull SortOrder order) {
myColumnInfos = columnNames;
myItems = items;
@@ -87,7 +91,7 @@
}
@Override
- public Object getRowValue(int row) {
+ public Item getRowValue(int row) {
return myItems.get(row);
}
@@ -104,21 +108,18 @@
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
- return myColumnInfos[columnIndex].valueOf(myItems.get(rowIndex));
+ return myColumnInfos[columnIndex].valueOf(getItem(rowIndex));
}
@Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
if (rowIndex < myItems.size()) {
- myColumnInfos[columnIndex].setValue(myItems.get(rowIndex), aValue);
+ myColumnInfos[columnIndex].setValue(getItem(rowIndex), aValue);
}
}
/**
* true if changed
- *
- * @param columnInfos
- * @return
*/
public boolean setColumnInfos(ColumnInfo[] columnInfos) {
if (myColumnInfos != null && Arrays.equals(columnInfos, myColumnInfos)) {
@@ -198,7 +199,7 @@
}
}
- public Object getItem(final int rowIndex) {
- return getItems().get(rowIndex);
+ public Item getItem(final int rowIndex) {
+ return myItems.get(rowIndex);
}
}
diff --git a/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java b/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java
index 65c6827..37aedba 100644
--- a/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java
+++ b/platform/util/src/com/intellij/util/ui/ThreeStateCheckBox.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -118,7 +118,9 @@
if (icon == null) {
icon = UIManager.getIcon("CheckBox.icon");
}
-
+ if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
+ icon = EmptyIcon.create(20, 18);
+ }
if (icon != null) {
final Insets i = getInsets();
final Rectangle r = getBounds();
diff --git a/platform/util/src/com/intellij/util/ui/UIUtil.java b/platform/util/src/com/intellij/util/ui/UIUtil.java
index ec92502..e9eebf3 100644
--- a/platform/util/src/com/intellij/util/ui/UIUtil.java
+++ b/platform/util/src/com/intellij/util/ui/UIUtil.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.
@@ -55,6 +55,7 @@
import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
@@ -69,6 +70,8 @@
@SuppressWarnings("StaticMethodOnlyUsedInOneClass")
public class UIUtil {
+ @NonNls public static final String BORDER_LINE = "<hr size=1 noshade>";
+
private static final AtomicNotNullLazyValue<Boolean> X_RENDER_ACTIVE = new AtomicNotNullLazyValue<Boolean>() {
@NotNull
@Override
@@ -353,6 +356,11 @@
public static void setEnabled(Component component, boolean enabled, boolean recursively) {
component.setEnabled(enabled);
+ if (component instanceof JComboBox && isUnderAquaLookAndFeel()) {
+ // On Mac JComboBox instances have children: com.apple.laf.AquaComboBoxButton and javax.swing.CellRendererPane.
+ // Disabling these children results in ugly UI: WEB-10733
+ return;
+ }
if (component instanceof JLabel) {
Color color = enabled ? getLabelForeground() : getLabelDisabledForeground();
if (color != null) {
@@ -430,18 +438,22 @@
return ArrayUtil.toStringArray(lines);
}
- public static void setActionNameAndMnemonic(String text, Action action) {
- int mnemoPos = text.indexOf('&');
- if (mnemoPos >= 0 && mnemoPos < text.length() - 2) {
- String mnemoChar = text.substring(mnemoPos + 1, mnemoPos + 2).trim();
- if (mnemoChar.length() == 1) {
- action.putValue(Action.MNEMONIC_KEY, Integer.valueOf((int)mnemoChar.charAt(0)));
- }
- }
+ public static void setActionNameAndMnemonic(@NotNull String text, @NotNull Action action) {
+ assignMnemonic(text, action);
text = text.replaceAll("&", "");
action.putValue(Action.NAME, text);
}
+ public static void assignMnemonic(@NotNull String text, @NotNull Action action) {
+ int mnemoPos = text.indexOf('&');
+ if (mnemoPos >= 0 && mnemoPos < text.length() - 2) {
+ String mnemoChar = text.substring(mnemoPos + 1, mnemoPos + 2).trim();
+ if (mnemoChar.length() == 1) {
+ action.putValue(Action.MNEMONIC_KEY, Integer.valueOf(mnemoChar.charAt(0)));
+ }
+ }
+ }
+
public static Font getLabelFont(@NotNull FontSize size) {
return getFont(size, null);
@@ -497,13 +509,14 @@
return UIManager.getColor("Label.disabledText");
}
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
public static Icon getOptionPanelWarningIcon() {
- return UIManager.getIcon("OptionPane.warningIcon");
+ return getWarningIcon();
}
- /**
- * @deprecated use com.intellij.util.ui.UIUtil#getQuestionIcon()
- */
+ /** @deprecated to remove in IDEA 14 */
+ @SuppressWarnings("UnusedDeclaration")
public static Icon getOptionPanelQuestionIcon() {
return getQuestionIcon();
}
@@ -2009,6 +2022,7 @@
* is event queue thread.
*
* @param runnable a runnable to invoke
+ * @see #invokeAndWaitIfNeeded(com.intellij.util.ThrowableRunnable)
*/
public static void invokeAndWaitIfNeeded(@NotNull Runnable runnable) {
if (SwingUtilities.isEventDispatchThread()) {
@@ -2024,6 +2038,27 @@
}
}
+ public static void invokeAndWaitIfNeeded(@NotNull final ThrowableRunnable runnable) throws Throwable {
+ if (SwingUtilities.isEventDispatchThread()) {
+ runnable.run();
+ }
+ else {
+ final Ref<Throwable> ref = new Ref<Throwable>();
+ SwingUtilities.invokeAndWait(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ runnable.run();
+ }
+ catch (Throwable throwable) {
+ ref.set(throwable);
+ }
+ }
+ });
+ if (!ref.isNull()) throw ref.get();
+ }
+ }
+
public static boolean isFocusProxy(@Nullable Component c) {
return c instanceof JComponent && Boolean.TRUE.equals(((JComponent)c).getClientProperty(FOCUS_PROXY_KEY));
}
@@ -2208,6 +2243,24 @@
return SystemInfo.isMac && isUnderAquaLookAndFeel() ? 28 : height;
}
+
+ /**
+ * The main difference from javax.swing.SwingUtilities#isDescendingFrom(Component, Component) is that this method
+ * uses getInvoker() instead of getParent() when it meets JPopupMenu
+ * @param child child component
+ * @param parent parent component
+ * @return true if parent if a top parent of child, false otherwise
+ *
+ * @see javax.swing.SwingUtilities#isDescendingFrom(java.awt.Component, java.awt.Component)
+ */
+ public static boolean isDescendingFrom(@Nullable Component child, @NotNull Component parent) {
+ while (child != null && child != parent) {
+ child = child instanceof JPopupMenu ? ((JPopupMenu)child).getInvoker()
+ : child.getParent();
+ }
+ return child == parent;
+ }
+
@Nullable
public static <T> T getParentOfType(Class<? extends T> cls, Component c) {
Component eachParent = c;
@@ -2638,7 +2691,7 @@
}
}
- private static final Color DECORATED_ROW_BG_COLOR = new JBColor(new Color(242, 245, 249), new Color(79, 83, 84));
+ private static final Color DECORATED_ROW_BG_COLOR = new JBColor(new Color(242, 245, 249), new Color(65, 69, 71));
public static Color getDecoratedRowColor() {
return DECORATED_ROW_BG_COLOR;
@@ -2676,4 +2729,17 @@
}
return JOptionPane.getRootFrame();
}
+
+ public static void setAutoRequestFocus (final Window onWindow, final boolean set){
+ if (SystemInfo.isMac) return;
+ if (SystemInfo.isJavaVersionAtLeast("1.7")) {
+ try {
+ Method setAutoRequestFocusMethod = onWindow.getClass().getMethod("setAutoRequestFocus",new Class [] {boolean.class});
+ setAutoRequestFocusMethod.invoke(onWindow, set);
+ }
+ catch (NoSuchMethodException e) { LOG.debug(e); }
+ catch (InvocationTargetException e) { LOG.debug(e); }
+ catch (IllegalAccessException e) { LOG.debug(e); }
+ }
+ }
}
diff --git a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java
index 8ab496c..579a425 100644
--- a/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.java
+++ b/platform/util/src/com/intellij/util/ui/tree/WideSelectionTreeUI.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.
@@ -51,6 +51,7 @@
private boolean myOldRepaintAllRowValue;
private boolean invertLineColor;
private boolean myForceDontPaintLines = false;
+ private boolean mySkinny = false;
@SuppressWarnings("unchecked")
public WideSelectionTreeUI() {
@@ -69,6 +70,23 @@
myWideSelectionCondition = wideSelectionCondition;
}
+ @Override
+ public int getRightChildIndent() {
+ return isSkinny() ? 8 : super.getRightChildIndent();
+ }
+
+ public boolean isSkinny() {
+ return mySkinny;
+ }
+
+ /**
+ * Setting to <code>true</code> make tree to reduce row offset
+ * @param skinny <code>true</code> to reduce row offset
+ */
+ public void setSkinny(boolean skinny) {
+ mySkinny = skinny;
+ }
+
private final MouseListener mySelectionListener = new MouseAdapter() {
boolean handled = false;
@Override
@@ -244,6 +262,16 @@
}
@Override
+ protected int getRowX(int row, int depth) {
+ if (isSkinny()) {
+ int off = tree.isRootVisible() ? 8 : 0;
+ return 8 * depth + 8 + off;
+ } else {
+ return super.getRowX(row, depth);
+ }
+ }
+
+ @Override
protected void paintHorizontalPartOfLeg(final Graphics g,
final Rectangle clipBounds,
final Insets insets,
diff --git a/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java b/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java
index 0206a54..189f614 100644
--- a/platform/util/src/com/intellij/util/xmlb/AttributeBinding.java
+++ b/platform/util/src/com/intellij/util/xmlb/AttributeBinding.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.
@@ -22,41 +22,50 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class AttributeBinding implements Binding {
- private final Accessor myAccessor;
- private final Attribute myAttribute;
- private Binding myBinding;
-
- public AttributeBinding(final Accessor accessor, final Attribute attribute) {
- myAccessor = accessor;
- myAttribute = attribute;
+public class AttributeBinding extends BasePrimitiveBinding {
+ public AttributeBinding(@NotNull Accessor accessor, @NotNull Attribute attribute) {
+ super(accessor, attribute.value(), attribute.converter());
}
@Override
public Object serialize(@NotNull Object o, Object context, SerializationFilter filter) {
- final Object v = myAccessor.read(o);
- final Object node = myBinding.serialize(v, context, filter);
+ Object value = myAccessor.read(o);
+ if (value == null) {
+ return context;
+ }
- return new org.jdom.Attribute(myAttribute.value(), ((Content)node).getValue());
+ String stringValue;
+ if (myConverter != null) {
+ stringValue = myConverter.toString(value);
+ }
+ else {
+ assert myBinding != null;
+ stringValue = ((Content)myBinding.serialize(value, context, filter)).getValue();
+ }
+ return new org.jdom.Attribute(myName, stringValue);
}
@Override
@Nullable
public Object deserialize(Object context, @NotNull Object... nodes) {
assert nodes.length == 1;
- Object node = nodes[0];
+ org.jdom.Attribute node = (org.jdom.Attribute)nodes[0];
assert isBoundTo(node);
-
- org.jdom.Attribute attr = (org.jdom.Attribute)node;
- final String value = attr.getValue();
- final Text text = new Text(value);
- myAccessor.write(context, myBinding.deserialize(context, text));
+ Object value;
+ if (myConverter != null) {
+ value = myConverter.fromString(node.getValue());
+ }
+ else {
+ assert myBinding != null;
+ value = myBinding.deserialize(context, new Text(node.getValue()));
+ }
+ myAccessor.write(context, value);
return context;
}
@Override
public boolean isBoundTo(Object node) {
- return node instanceof org.jdom.Attribute && ((org.jdom.Attribute)node).getName().equals(myAttribute.value());
+ return node instanceof org.jdom.Attribute && ((org.jdom.Attribute)node).getName().equals(myName);
}
@Override
@@ -66,8 +75,8 @@
@Override
public void init() {
- myBinding = XmlSerializerImpl.getBinding(myAccessor);
- if (!Text.class.isAssignableFrom(myBinding.getBoundNodeType())) {
+ super.init();
+ if (myBinding != null && !Text.class.isAssignableFrom(myBinding.getBoundNodeType())) {
throw new XmlSerializationException("Can't use attribute binding for non-text content: " + myAccessor);
}
}
diff --git a/platform/util/src/com/intellij/util/xmlb/BasePrimitiveBinding.java b/platform/util/src/com/intellij/util/xmlb/BasePrimitiveBinding.java
new file mode 100644
index 0000000..f5c5040
--- /dev/null
+++ b/platform/util/src/com/intellij/util/xmlb/BasePrimitiveBinding.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.xmlb;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+abstract class BasePrimitiveBinding implements Binding {
+ protected final Accessor myAccessor;
+ protected final String myName;
+
+ protected final @Nullable Converter<Object> myConverter;
+ @Nullable protected Binding myBinding;
+
+ protected BasePrimitiveBinding(@NotNull Accessor accessor, @Nullable String suggestedName, @Nullable Class<? extends Converter> converterClass) {
+ myAccessor = accessor;
+ myName = StringUtil.isEmpty(suggestedName) ? myAccessor.getName() : suggestedName;
+ if (converterClass == null || converterClass == Converter.class) {
+ myConverter = null;
+ }
+ else {
+ //noinspection unchecked
+ myConverter = XmlSerializerImpl.newInstance(converterClass);
+ }
+ }
+
+ @Override
+ public void init() {
+ if (myConverter == null) {
+ myBinding = XmlSerializerImpl.getBinding(myAccessor);
+ }
+ }
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java
index 1a03a9b..d795dea 100644
--- a/platform/util/src/com/intellij/util/xmlb/BeanBinding.java
+++ b/platform/util/src/com/intellij/util/xmlb/BeanBinding.java
@@ -50,7 +50,7 @@
@NonNls private static final String CLASS_PROPERTY = "class";
private final Accessor myAccessor;
- public BeanBinding(Class<?> beanClass, final Accessor accessor) {
+ public BeanBinding(Class<?> beanClass, @Nullable Accessor accessor) {
myAccessor = accessor;
assert !beanClass.isArray() : "Bean is an array: " + beanClass;
assert !beanClass.isPrimitive() : "Bean is primitive type: " + beanClass;
@@ -169,18 +169,7 @@
}
private Object instantiateBean() {
- Object result;
-
- try {
- result = myBeanClass.newInstance();
- }
- catch (InstantiationException e) {
- throw new XmlSerializationException(e);
- }
- catch (IllegalAccessException e) {
- throw new XmlSerializationException(e);
- }
- return result;
+ return XmlSerializerImpl.newInstance(myBeanClass);
}
@Override
diff --git a/platform/util/src/com/intellij/util/xmlb/Converter.java b/platform/util/src/com/intellij/util/xmlb/Converter.java
new file mode 100644
index 0000000..645cead
--- /dev/null
+++ b/platform/util/src/com/intellij/util/xmlb/Converter.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.xmlb;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public abstract class Converter<T> {
+ @Nullable
+ public abstract T fromString(@NotNull String value);
+
+ @NotNull
+ public abstract String toString(@NotNull T t);
+}
\ No newline at end of file
diff --git a/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java b/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java
index ae4bb9c..cf88358 100644
--- a/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.java
+++ b/platform/util/src/com/intellij/util/xmlb/OptionTagBinding.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 @@
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.SmartList;
import com.intellij.util.xmlb.annotations.OptionTag;
import org.jdom.Attribute;
import org.jdom.Content;
@@ -29,31 +30,24 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
import java.util.List;
-class OptionTagBinding implements Binding {
- private static final Logger LOG = Logger.getInstance("#" + OptionTagBinding.class.getName());
+class OptionTagBinding extends BasePrimitiveBinding {
+ private static final Logger LOG = Logger.getInstance(OptionTagBinding.class);
- private final Accessor accessor;
- private final String myName;
- private final Binding myBinding;
private final String myTagName;
private final String myNameAttribute;
private final String myValueAttribute;
- public OptionTagBinding(Accessor accessor, @Nullable OptionTag optionTag) {
- this.accessor = accessor;
- myBinding = XmlSerializerImpl.getBinding(accessor);
+ public OptionTagBinding(@NotNull Accessor accessor, @Nullable OptionTag optionTag) {
+ super(accessor, optionTag == null ? null : optionTag.value(), optionTag == null ? null : optionTag.converter());
+
if (optionTag != null) {
- String name = optionTag.value();
- myName = name.isEmpty() ? accessor.getName() : name;
myTagName = optionTag.tag();
myNameAttribute = optionTag.nameAttribute();
myValueAttribute = optionTag.valueAttribute();
}
else {
- myName = accessor.getName();
myTagName = Constants.OPTION;
myNameAttribute = Constants.NAME;
myValueAttribute = Constants.VALUE;
@@ -63,21 +57,27 @@
@Override
public Object serialize(Object o, Object context, SerializationFilter filter) {
Element targetElement = new Element(myTagName);
- Object value = accessor.read(o);
+ Object value = myAccessor.read(o);
if (!StringUtil.isEmpty(myNameAttribute)) {
targetElement.setAttribute(myNameAttribute, myName);
}
- if (value == null) return targetElement;
+ if (value == null) {
+ return targetElement;
+ }
- Object node = myBinding.serialize(value, targetElement, filter);
- if (node instanceof Text) {
- Text text = (Text)node;
- targetElement.setAttribute(myValueAttribute, text.getText());
+ if (myConverter != null) {
+ targetElement.setAttribute(myValueAttribute, myConverter.toString(value));
}
else {
- if (targetElement != node) {
+ assert myBinding != null;
+ Object node = myBinding.serialize(value, targetElement, filter);
+ if (node instanceof Text) {
+ Text text = (Text)node;
+ targetElement.setAttribute(myValueAttribute, text.getText());
+ }
+ else if (targetElement != node) {
JDOMUtil.addContent(targetElement, node);
}
}
@@ -86,38 +86,45 @@
}
@Override
- public Object deserialize(Object o, @NotNull Object... nodes) {
+ public Object deserialize(Object context, @NotNull Object... nodes) {
if (nodes.length > 1) {
- LOG.info("Duplicate options for " + o + " will be ignored");
+ LOG.info("Duplicate options for " + context + " will be ignored");
}
assert nodes.length != 0 : "Empty nodes passed to: " + this;
Element element = ((Element)nodes[0]);
- Attribute valueAttr = element.getAttribute(myValueAttribute);
+ Attribute valueAttribute = element.getAttribute(myValueAttribute);
- if (valueAttr != null) {
- Object value = myBinding.deserialize(o, valueAttr);
- accessor.write(o, value);
+ if (valueAttribute != null) {
+ Object value;
+ if (myConverter != null) {
+ value = myConverter.fromString(valueAttribute.getValue());
+ }
+ else {
+ assert myBinding != null;
+ value = myBinding.deserialize(context, valueAttribute);
+ }
+ myAccessor.write(context, value);
}
else {
- final Content[] childElements = JDOMUtil.getContent(element);
- List<Object> children = new ArrayList<Object>();
-
- for (final Content child : childElements) {
- if (XmlSerializerImpl.isIgnoredNode(child)) continue;
- children.add(child);
+ List<Object> children = new SmartList<Object>();
+ for (Content child : element.getContent()) {
+ if (!XmlSerializerImpl.isIgnoredNode(child)) {
+ children.add(child);
+ }
}
if (!children.isEmpty()) {
- Object value = myBinding.deserialize(accessor.read(o), ArrayUtil.toObjectArray(children));
- accessor.write(o, value);
+ assert myBinding != null;
+ Object value = myBinding.deserialize(myAccessor.read(context), ArrayUtil.toObjectArray(children));
+ myAccessor.write(context, value);
}
else {
- accessor.write(o, null);
+ myAccessor.write(context, null);
}
}
- return o;
+ return context;
}
@Override
@@ -137,11 +144,6 @@
throw new UnsupportedOperationException("Method getBoundNodeType is not supported in " + getClass());
}
- @Override
- public void init() {
- }
-
-
@NonNls
public String toString() {
return "OptionTagBinding[" + myName + ", binding=" + myBinding + "]";
diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java
index 4ab7d6e..872e17e 100644
--- a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java
+++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.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,16 +18,18 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMUtil;
+import gnu.trove.THashMap;
import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.HashMap;
import java.util.Map;
public class SkipDefaultValuesSerializationFilters implements SerializationFilter {
- private final Map<Class, Object> myDefaultBeans = new HashMap<Class, Object>();
+ private final Map<Class<?>, Object> myDefaultBeans = new THashMap<Class<?>, Object>();
@Override
- public boolean accepts(final Accessor accessor, final Object bean) {
+ public boolean accepts(final Accessor accessor, @Nullable Object bean) {
if (bean == null) {
return true;
}
@@ -36,35 +38,28 @@
final Object defValue = accessor.read(defaultBean);
final Object beanValue = accessor.read(bean);
if (defValue instanceof Element && beanValue instanceof Element) {
- return !JDOMUtil.writeElement((Element)defValue, "\n").equals(JDOMUtil.writeElement((Element)beanValue, "\n"));
+ return !JDOMUtil.areElementsEqual((Element)beanValue, (Element)defValue);
}
-
- return !Comparing.equal(beanValue, defValue);
+ else {
+ return !Comparing.equal(beanValue, defValue);
+ }
}
- private Object getDefaultBean(final Object bean) {
- Class c = bean.getClass();
+ private Object getDefaultBean(@NotNull Object bean) {
+ Class<?> c = bean.getClass();
Object o = myDefaultBeans.get(c);
-
if (o == null) {
- try {
- o = c.newInstance();
- configure(o);
- }
- catch (InstantiationException e) {
- throw new XmlSerializationException(e);
- }
- catch (IllegalAccessException e) {
- throw new XmlSerializationException(e);
- }
+ o = XmlSerializerImpl.newInstance(c);
+ configure(o);
myDefaultBeans.put(c, o);
}
-
return o;
}
- protected void configure(final Object o) {
- //todo put your own default object configuration here
+ /**
+ * Override to put your own default object configuration
+ */
+ protected void configure(@NotNull Object o) {
}
}
diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
index 49b4e8a..132067d 100644
--- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
+++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
import java.lang.annotation.Annotation;
import java.lang.ref.SoftReference;
+import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
@@ -72,7 +73,7 @@
throw new UnsupportedOperationException("Can't get binding for: " + type);
}
- private static synchronized Binding _getClassBinding(Class<?> aClass, Type originalType, final Accessor accessor) {
+ private static synchronized Binding _getClassBinding(Class<?> aClass, Type originalType, @Nullable Accessor accessor) {
final Pair<Type, Accessor> p = new Pair<Type, Accessor>(originalType, accessor);
Map<Pair<Type, Accessor>, Binding> map = getBindingCacheMap();
@@ -88,8 +89,7 @@
}
private static Map<Pair<Type, Accessor>, Binding> getBindingCacheMap() {
- SoftReference<Map<Pair<Type, Accessor>, Binding>> ref = ourBindings;
- Map<Pair<Type, Accessor>, Binding> map = ref == null ? null : ref.get();
+ Map<Pair<Type, Accessor>, Binding> map = com.intellij.reference.SoftReference.dereference(ourBindings);
if (map == null) {
map = new ConcurrentHashMap<Pair<Type, Accessor>, Binding>();
ourBindings = new SoftReference<Map<Pair<Type, Accessor>, Binding>>(map);
@@ -97,7 +97,7 @@
return map;
}
- private static Binding _getNonCachedClassBinding(final Class<?> aClass, final Accessor accessor, final Type originalType) {
+ private static Binding _getNonCachedClassBinding(final Class<?> aClass, @Nullable Accessor accessor, final Type originalType) {
if (aClass.isPrimitive()) return new PrimitiveValueBinding(aClass);
if (aClass.isArray()) {
return Element.class.isAssignableFrom(aClass.getComponentType())
@@ -180,4 +180,23 @@
return result.toArray(new Content[result.size()]);
}
+
+ /**
+ * {@link Class#newInstance()} cannot instantiate private classes
+ */
+ static <T> T newInstance(Class<T> aClass) {
+ try {
+ Constructor<T> constructor = aClass.getDeclaredConstructor();
+ try {
+ constructor.setAccessible(true);
+ }
+ catch (SecurityException e) {
+ return aClass.newInstance();
+ }
+ return constructor.newInstance();
+ }
+ catch (Exception e) {
+ throw new XmlSerializationException(e);
+ }
+ }
}
diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java b/platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java
index 3ee2f46..9a7902c 100644
--- a/platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java
+++ b/platform/util/src/com/intellij/util/xmlb/annotations/Attribute.java
@@ -16,6 +16,8 @@
package com.intellij.util.xmlb.annotations;
+import com.intellij.util.xmlb.Converter;
+
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -24,5 +26,7 @@
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD})
public @interface Attribute {
- String value();
+ String value() default "";
+
+ Class<? extends Converter> converter() default Converter.class;
}
diff --git a/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java b/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java
index 669d011..29eac3a 100644
--- a/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.java
+++ b/platform/util/src/com/intellij/util/xmlb/annotations/OptionTag.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.
@@ -16,6 +16,7 @@
package com.intellij.util.xmlb.annotations;
import com.intellij.util.xmlb.Constants;
+import com.intellij.util.xmlb.Converter;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -32,7 +33,12 @@
@Target({ElementType.FIELD, ElementType.METHOD})
public @interface OptionTag {
String value() default "";
+
String tag() default Constants.OPTION;
+
String nameAttribute() default Constants.NAME;
+
String valueAttribute() default Constants.VALUE;
+
+ Class<? extends Converter> converter() default Converter.class;
}
diff --git a/platform/util/src/com/intellij/xml/util/XmlStringUtil.java b/platform/util/src/com/intellij/xml/util/XmlStringUtil.java
index b9e3f1a..7643e9a 100644
--- a/platform/util/src/com/intellij/xml/util/XmlStringUtil.java
+++ b/platform/util/src/com/intellij/xml/util/XmlStringUtil.java
@@ -108,6 +108,11 @@
return HTML_HEADER + result + HTML_FOOTER;
}
+ public static boolean isWrappedInHtml(@NotNull String tooltip) {
+ return StringUtil.startsWithIgnoreCase(tooltip, HTML_HEADER) &&
+ StringUtil.endsWithIgnoreCase(tooltip, HTML_FOOTER);
+ }
+
@NotNull
public static String stripHtml(@NotNull String toolTip) {
toolTip = StringUtil.trimStart(toolTip, HTML_HEADER);
diff --git a/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java b/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java
index 1e1295c..4b4fef3 100644
--- a/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.java
+++ b/platform/util/testSrc/com/intellij/openapi/util/io/FileUtilLightTest.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.
@@ -156,4 +156,16 @@
Map<String, String> map = FileUtil.loadProperties(new StringReader(data));
assertEquals(ContainerUtil.newArrayList("key2", "key1", "key3"), ContainerUtil.newArrayList(map.keySet()));
}
+
+ @Test
+ public void testRootPath() {
+ assertTrue(FileUtil.isRootPath("/"));
+ assertTrue(FileUtil.isRootPath("c:/"));
+ assertTrue(FileUtil.isRootPath("Z:\\"));
+
+ assertFalse(FileUtil.isRootPath(""));
+ assertFalse(FileUtil.isRootPath("/tmp"));
+ assertFalse(FileUtil.isRootPath("c:"));
+ assertFalse(FileUtil.isRootPath("X:\\Temp"));
+ }
}
diff --git a/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java b/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java
index fb942c7..fc68077 100644
--- a/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/EnvironmentUtilTest.java
@@ -30,7 +30,6 @@
public class EnvironmentUtilTest {
@Test(timeout = 30000)
public void map() throws Exception {
- System.setProperty("idea.fix.mac.env", "true");
assertNotNull(EnvironmentUtil.getEnvironmentMap());
}
diff --git a/platform/util/testSrc/com/intellij/util/FoundationTest.java b/platform/util/testSrc/com/intellij/util/FoundationTest.java
index 1e2e738..b9bafae 100644
--- a/platform/util/testSrc/com/intellij/util/FoundationTest.java
+++ b/platform/util/testSrc/com/intellij/util/FoundationTest.java
@@ -17,34 +17,45 @@
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.mac.foundation.Foundation;
-import junit.framework.TestCase;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
-public class FoundationTest extends TestCase {
- public void testStrings() throws Exception {
- if (!SystemInfo.isMac) return;
- assertEquals("Test", Foundation.toStringViaUTF8(Foundation.nsString("Test")));
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class FoundationTest {
+ @BeforeClass
+ public static void assumeMac() {
+ Assume.assumeTrue(SystemInfo.isMac);
}
+ @Test
+ public void testStrings() throws Exception {
+ assertThat(Foundation.toStringViaUTF8(Foundation.nsString("Test")), equalTo("Test"));
+ }
+
+ @Test
public void testEncodings() throws Exception {
- if (!SystemInfo.isMac) return;
+ assertThat(Foundation.getEncodingName(4), equalTo("utf-8"));
+ assertThat(Foundation.getEncodingName(0), nullValue());
+ assertThat(Foundation.getEncodingName(-1), nullValue());
- assertEquals("utf-8", Foundation.getEncodingName(4));
- assertEquals(null, Foundation.getEncodingName(0));
- assertEquals(null, Foundation.getEncodingName(-1));
+ assertThat(Foundation.getEncodingCode("utf-8"), equalTo(4L));
+ assertThat(Foundation.getEncodingCode("UTF-8"), equalTo(4L));
- assertEquals(4, Foundation.getEncodingCode("utf-8"));
- assertEquals(4, Foundation.getEncodingCode("UTF-8"));
+ assertThat(Foundation.getEncodingCode(""), equalTo(-1L));
+ //noinspection SpellCheckingInspection
+ assertThat(Foundation.getEncodingCode("asdasd"), equalTo(-1L));
+ assertThat(Foundation.getEncodingCode(null), equalTo(-1L));
- assertEquals(-1, Foundation.getEncodingCode(""));
- assertEquals(-1, Foundation.getEncodingCode("asdasd"));
- assertEquals(-1, Foundation.getEncodingCode(null));
+ assertThat(Foundation.getEncodingName(10), equalTo("utf-16"));
+ assertThat(Foundation.getEncodingCode("utf-16"), equalTo(10L));
- assertEquals("utf-16", Foundation.getEncodingName(10));
- assertEquals(10, Foundation.getEncodingCode("utf-16"));
-
- assertEquals("utf-16le", Foundation.getEncodingName(2483028224l));
- assertEquals(2483028224l, Foundation.getEncodingCode("utf-16le"));
- assertEquals("utf-16be", Foundation.getEncodingName(2415919360l));
- assertEquals(2415919360l, Foundation.getEncodingCode("utf-16be"));
+ assertThat(Foundation.getEncodingName(2483028224l), equalTo("utf-16le"));
+ assertThat(Foundation.getEncodingCode("utf-16le"), equalTo(2483028224l));
+ assertThat(Foundation.getEncodingName(2415919360l), equalTo("utf-16be"));
+ assertThat(Foundation.getEncodingCode("utf-16be"), equalTo(2415919360l));
}
}
diff --git a/platform/util/testSrc/com/intellij/util/SmartListTest.java b/platform/util/testSrc/com/intellij/util/SmartListTest.java
index ec8375a..db167eb 100644
--- a/platform/util/testSrc/com/intellij/util/SmartListTest.java
+++ b/platform/util/testSrc/com/intellij/util/SmartListTest.java
@@ -230,4 +230,31 @@
assertEquals(42, l.get(1).intValue());
assertEquals(1, l.get(2).intValue());
}
+
+ @Test
+ public void testEmptyToArray() {
+ SmartList<Integer> l = new SmartList<Integer>();
+ assertArrayEquals(l.toArray(), new Integer[]{});
+ assertArrayEquals(l.toArray(new Integer[]{}), new Integer[]{});
+ }
+
+ @Test
+ public void testSingleToArray() {
+ SmartList<String> l = new SmartList<String>("foo");
+ assertArrayEquals(l.toArray(ArrayUtilRt.EMPTY_STRING_ARRAY), new String[]{"foo"});
+ }
+
+ @Test
+ public void testToArray() {
+ SmartList<Integer> l = new SmartList<Integer>(0, 1);
+ assertArrayEquals(l.toArray(), new Object[]{0, 1});
+ assertArrayEquals(l.toArray(), new Integer[]{0, 1});
+ assertArrayEquals(l.toArray(new Integer[0]), new Integer[]{0, 1});
+
+ assertArrayEquals(l.toArray(new Integer[4]), new Integer[]{0, 1, null, null});
+
+ l.remove(1);
+ assertArrayEquals(l.toArray(new Integer[4]), new Integer[]{0, null, null, null});
+ assertArrayEquals(l.toArray(), new Integer[]{0});
+ }
}
diff --git a/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java b/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java
index e579a16..a52bdbc 100644
--- a/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/containers/ContainerUtilTest.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.
@@ -234,4 +234,42 @@
Iterator<Object> iterator = my.iterator();
assertSame(EmptyIterator.getInstance(), iterator);
}
+
+ public void testLockFreeCOWIteratorRemove() {
+ List<String> seq = Arrays.asList("0", "1", "2", "3", "4");
+ LockFreeCopyOnWriteArrayList<String> my = (LockFreeCopyOnWriteArrayList<String>)ContainerUtil.createLockFreeCopyOnWriteList(seq);
+ {
+ Iterator<String> iterator = my.iterator();
+ try {
+ iterator.remove();
+ fail("must not be able to remove before next() call");
+ }
+ catch (IllegalStateException ignored) {
+ }
+ }
+ int size = my.size();
+ Iterator<String> iterator = my.iterator();
+ for (int i = 0; i<size; i++) {
+ assertTrue(iterator.hasNext());
+ String next = iterator.next();
+ assertEquals(next, String.valueOf(i));
+ iterator.remove();
+ assertEquals(my.size(), size - i-1);
+ if (i == size-1) {
+ assertTrue(my.isEmpty());
+ }
+ else {
+ assertEquals(my.toArray()[0], String.valueOf(i+1));
+ assertEquals(my.toString(), seq.subList(i+1,seq.size()).toString());
+ }
+ }
+
+ try {
+ iterator.remove();
+ fail("must not be able to double remove()");
+ }
+ catch (IllegalStateException ignored) {
+ }
+ }
+
}
diff --git a/platform/util/testSrc/com/intellij/util/containers/SmartHashSetTest.java b/platform/util/testSrc/com/intellij/util/containers/SmartHashSetTest.java
new file mode 100644
index 0000000..126baa7
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/containers/SmartHashSetTest.java
@@ -0,0 +1,22 @@
+package com.intellij.util.containers;
+
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.Set;
+
+import static org.junit.Assert.*;
+
+public class SmartHashSetTest {
+ @Test
+ public void testIterator() {
+ Set<Integer> set = new SmartHashSet<Integer>();
+ set.add(30);
+ Iterator<Integer> iterator = set.iterator();
+ assertEquals((int)iterator.next(), 30);
+ assertFalse(iterator.hasNext());
+ assertFalse(set.isEmpty());
+ iterator.remove();
+ assertTrue(set.isEmpty());
+ }
+}
\ No newline at end of file
diff --git a/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java b/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java
index 70aa78e..db86e63 100644
--- a/platform/util/testSrc/com/intellij/util/containers/WeakListTest.java
+++ b/platform/util/testSrc/com/intellij/util/containers/WeakListTest.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.
@@ -13,10 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package com.intellij.util.containers;
-import junit.framework.TestCase;
+import org.junit.Test;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -24,60 +23,54 @@
import java.util.List;
import java.util.NoSuchElementException;
-public class WeakListTest extends TestCase {
+import static org.junit.Assert.*;
+
+public class WeakListTest {
+ private static final String HARD_REFERENCED = "xxx";
+
private final WeakList<Object> myWeakList = new WeakList<Object>();
- protected final List<Object> myHolder = new ArrayList<Object>();
+ private final List<Object> myHolder = new ArrayList<Object>();
- private void addElement(Object element) {
- myWeakList.add(element);
- myHolder.add(element);
- }
-
+ @Test
public void testCompresses() {
- for (int i = 0; i < 20; i++) {
- addElement(new Object());
- }
+ fillWithObjects(20);
assertEquals(20, myWeakList.listSize());
- String obj = "xxx";
- addElement(obj);
+ addElement(HARD_REFERENCED);
+ assertEquals(21, myWeakList.listSize());
myHolder.clear();
- gc();
- myWeakList.remove(new Object()); // invoke processQueue()
- //obj is held here in the codeblock
+ while (myWeakList.toStrongList().size() == 21) {
+ synchronized (myWeakList) {
+ gc();
+ }
+ }
+ synchronized (myWeakList) {
+ boolean processed = myWeakList.processQueue();
+ assertTrue(processed); // some refs must be in the queue
+ }
+ //HARD_REFERENCED is held there
assertEquals(1, myWeakList.listSize());
}
- private static void gc() {
- ConcurrentMapsTest.tryGcSoftlyReachableObjects();
- WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
- do {
- System.gc();
- }
- while (weakReference.get() != null);
- }
-
+ @Test
public void testClear() {
- for (int i = 0; i < 20; i++) {
- addElement(new Object());
- }
+ fillWithObjects(20);
assertEquals(20, myWeakList.listSize());
myHolder.clear();
gc();
myWeakList.clear();
assertFalse(myWeakList.iterator().hasNext());
}
-
+
+ @Test
public void testIterator() {
int N = 10;
- for (int i=0; i< N;i++) {
- addElement(i);
- }
+ fillWithInts(N);
gc();
- Iterator<Integer> iterator = (Iterator)myWeakList.iterator();
- for (int i=0; i< N;i++) {
+ Iterator<?> iterator = myWeakList.iterator();
+ for (int i = 0; i < N; i++) {
assertTrue(iterator.hasNext());
assertTrue(iterator.hasNext());
- int element = iterator.next();
+ int element = (Integer)iterator.next();
assertEquals(i, element);
}
assertFalse(iterator.hasNext());
@@ -89,7 +82,8 @@
}
assertEquals(N, elementCount);
}
-
+
+ @Test
public void testRemoveViaIterator() {
addElement(new Object());
addElement(new Object());
@@ -107,14 +101,13 @@
myHolder.remove(1);
}
+ @Test
public void testRemoveAllViaIterator() {
int N = 10;
- for (int i=0; i< N;i++) {
- addElement(i);
- }
+ fillWithInts(N);
gc();
Iterator<Object> iterator = myWeakList.iterator();
- for (int i=0; i< N;i++) {
+ for (int i = 0; i < N; i++) {
assertTrue(iterator.hasNext());
int element = (Integer)iterator.next();
assertEquals(i, element);
@@ -124,6 +117,7 @@
assertTrue(myWeakList.toStrongList().isEmpty());
}
+ @Test
public void testRemoveLastViaIterator() {
addElement(new Object());
addElement(new Object());
@@ -135,6 +129,7 @@
iterator.remove();
}
+ @Test
public void testIteratorKeepsFirstElement() {
addElement(new Object());
addElement(new Object());
@@ -145,7 +140,8 @@
assertNotNull(iterator.next());
assertFalse(iterator.hasNext());
}
-
+
+ @Test
public void testIteratorKeepsNextElement() {
addElement(new Object());
addElement(new Object());
@@ -159,6 +155,7 @@
assertFalse(iterator.hasNext());
}
+ @Test
public void testIteratorRemoveEmpty() {
Iterator<Object> iterator = myWeakList.iterator();
assertFalse(iterator.hasNext());
@@ -166,30 +163,31 @@
iterator.next();
fail("must not allow to next");
}
- catch (NoSuchElementException e) {
+ catch (NoSuchElementException ignored) {
}
try {
iterator.remove();
fail("must not allow to remove");
}
- catch (NoSuchElementException e) {
+ catch (NoSuchElementException ignored) {
}
}
- public void testElementGetsGcedInTheMiddleAndListRebuildsItself() {
+ @Test
+ public void testElementGetsCollectedInTheMiddleAndListRebuildsItself() {
int N = 200;
- for (int i = 0; i < N; i++) {
- addElement(new Object());
- }
+ fillWithObjects(N);
String x = new String("xxx");
addElement(x);
- for (int i = 0; i < N; i++) {
- addElement(new Object());
- }
+ fillWithObjects(N);
gc();
assertEquals(N + 1 + N, myWeakList.listSize());
myHolder.clear();
- gc();
+ while (myWeakList.toStrongList().size() == N + 1 + N) {
+ synchronized (myWeakList) {
+ gc();
+ }
+ }
boolean removed = myWeakList.remove("zzz");
assertFalse(removed);
assertEquals(1, myWeakList.listSize());
@@ -197,6 +195,7 @@
assertSame(x, element);
}
+ @Test
public void testIsEmpty() {
assertTrue(myWeakList.isEmpty());
addElement(new Object());
@@ -206,4 +205,30 @@
assertEquals(1, myWeakList.listSize());
assertTrue(myWeakList.isEmpty());
}
+
+ private void addElement(Object element) {
+ myWeakList.add(element);
+ myHolder.add(element);
+ }
+
+ private void fillWithObjects(int n) {
+ for (int i = n - 1; i >= 0; i--) {
+ addElement(new Object());
+ }
+ }
+
+ private void fillWithInts(int n) {
+ for (int i = 0; i < n; i++) {
+ addElement(i);
+ }
+ }
+
+ private static void gc() {
+ ConcurrentMapsTest.tryGcSoftlyReachableObjects();
+ WeakReference<Object> weakReference = new WeakReference<Object>(new Object());
+ do {
+ System.gc();
+ }
+ while (weakReference.get() != null);
+ }
}
diff --git a/platform/util/testSrc/com/intellij/util/containers/hash/LinkedHashMapTest.java b/platform/util/testSrc/com/intellij/util/containers/hash/LinkedHashMapTest.java
index a1791cd..8f3ee03 100644
--- a/platform/util/testSrc/com/intellij/util/containers/hash/LinkedHashMapTest.java
+++ b/platform/util/testSrc/com/intellij/util/containers/hash/LinkedHashMapTest.java
@@ -87,9 +87,9 @@
for (int i = 0; i < 10000; ++i) {
tested.put(i, Integer.toString(i));
}
- int i = 10000;
+ int i = 0;
for (Integer key : tested.keySet()) {
- assertEquals(--i, key.intValue());
+ assertEquals(i++, key.intValue());
}
}
@@ -109,7 +109,7 @@
assertEquals(5000, tested.size());
it = tested.keySet().iterator();
- for (int i = 9999; i > 0; i -= 2) {
+ for (int i = 1; i <= 9999; i += 2) {
Assert.assertTrue(it.hasNext());
assertEquals(i, it.next().intValue());
}
@@ -180,16 +180,28 @@
}
@Test
- public void iteration() {
- ///todo[nik] it iterates in reversed order, may be it is a bug?
+ public void valuesIteration() {
Map<Integer, String> map = new LinkedHashMap<Integer, String>();
map.put(1, "a");
map.put(2, "b");
map.put(3, "c");
Iterator<String> iterator = map.values().iterator();
- assertEquals("c", iterator.next());
- assertEquals("b", iterator.next());
assertEquals("a", iterator.next());
+ assertEquals("b", iterator.next());
+ assertEquals("c", iterator.next());
+ assertFalse(iterator.hasNext());
+ }
+
+ @Test
+ public void accessOrderValuesIteration() {
+ Map<Integer, String> map = new LinkedHashMap<Integer, String>(0, true);
+ map.put(1, "a");
+ map.put(2, "b");
+ map.put(3, "c");
+ Iterator<String> iterator = map.values().iterator();
+ assertEquals("a", iterator.next());
+ assertEquals("b", iterator.next());
+ assertEquals("c", iterator.next());
assertFalse(iterator.hasNext());
}
diff --git a/platform/util/testSrc/com/intellij/util/diff/IntLCSNewTest.java b/platform/util/testSrc/com/intellij/util/diff/IntLCSNewTest.java
new file mode 100644
index 0000000..31fd1ad
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/diff/IntLCSNewTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diff;
+
+import junit.framework.TestCase;
+
+import java.util.BitSet;
+
+public class IntLCSNewTest extends TestCase {
+ public void testEqual() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3}, new int[]{1, 2, 3});
+ checkChange(change, new int[]{0, 0, 0}, new int[]{0, 0, 0});
+ }
+
+ public void testOneAtBegging() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2}, new int[]{1, 3});
+ checkChange(change, new int[]{0, 1}, new int[]{0, 1});
+ }
+
+ public void testOneAntEnd() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 3}, new int[]{2, 3});
+ checkChange(change, new int[]{1, 0}, new int[]{1, 0});
+ }
+
+ public void testOneOverAtEnd() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2}, new int[]{1, 2, 3});
+ checkChange(change, new int[]{0, 0}, new int[]{0, 0, 1});
+ }
+
+ public void testOneOverAtBegging() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3}, new int[]{2, 3});
+ checkChange(change, new int[]{1, 0, 0}, new int[]{0, 0});
+ }
+
+ public void testSingleMiddle() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3}, new int[]{4, 2, 5});
+ checkChange(change, new int[]{1, 0, 1}, new int[]{1, 0, 1});
+ }
+
+ public void testAbsolutelyDifferent() throws FilesTooBigForDiffException {
+ BitSet[] change1 = buildChange(new int[]{1, 2}, new int[]{3, 4});
+ checkChange(change1, new int[]{1, 1}, new int[]{1, 1});
+
+ BitSet[] change2 = buildChange(new int[]{1, 2, 3}, new int[]{4, 5, 6});
+ checkChange(change2, new int[]{1, 1, 1}, new int[]{1, 1, 1});
+ }
+
+ public void testSingleUniqueMoved() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 1, 2, 2, 10}, new int[]{10, 1, 1, 2, 2});
+ checkChange(change, new int[]{0, 0, 0, 0, 1}, new int[]{1, 0, 0, 0, 0});
+ }
+
+ public void testSingleFunctionMoved() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 7, 9, 10, 2, 11, 12, 5, 13, 7, 8, 7},
+ new int[]{10, 2, 11, 12, 5, 13, 7, 8, 7, 9, 1, 2, 3, 4, 5, 6, 7, 8, 7});
+ checkChange(change, new int[]{1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1},
+ new int[]{1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1});
+ }
+
+ private static BitSet[] buildChange(int[] first, int[] second) throws FilesTooBigForDiffException {
+ IntLCS intLCS = new IntLCS(first, second);
+ intLCS.execute();
+ return intLCS.getChanges();
+ }
+
+ private static void checkChange(BitSet[] change, int[] expected1, int[] expected2) {
+ for (int i = 0; i < expected1.length; i++) {
+ assertEquals(change[0].get(i), expected1[i] == 1);
+ }
+ for (int i = 0; i < expected2.length; i++) {
+ assertEquals(change[1].get(i), expected2[i] == 1);
+ }
+ }
+}
diff --git a/platform/util/testSrc/com/intellij/util/diff/IntLCSTest.java b/platform/util/testSrc/com/intellij/util/diff/IntLCSTest.java
index c2a350d..87d1fad 100644
--- a/platform/util/testSrc/com/intellij/util/diff/IntLCSTest.java
+++ b/platform/util/testSrc/com/intellij/util/diff/IntLCSTest.java
@@ -68,7 +68,7 @@
Reindexer reindexer = new Reindexer();
reindexer.idInit(first.length, second.length);
Diff.ChangeBuilder builder = new Diff.ChangeBuilder(0);
- reindexer.reindex(intLCS.getPaths(), builder);
+ reindexer.reindex(intLCS.getChanges(), builder);
return builder.getFirstChange();
}
diff --git a/platform/util/testSrc/com/intellij/util/diff/LinkedDiffPathsTest.java b/platform/util/testSrc/com/intellij/util/diff/LinkedDiffPathsTest.java
index befb38a..0f9300a 100644
--- a/platform/util/testSrc/com/intellij/util/diff/LinkedDiffPathsTest.java
+++ b/platform/util/testSrc/com/intellij/util/diff/LinkedDiffPathsTest.java
@@ -18,6 +18,8 @@
import junit.framework.TestCase;
+import java.util.BitSet;
+
/**
* @author dyoma
*/
@@ -67,10 +69,12 @@
}
private Diff.Change decode(LinkedDiffPaths paths) {
+ BitSet[] changes = new BitSet[]{new BitSet(), new BitSet()};
+ paths.applyChanges(0, 0, changes[0], changes[1]);
Reindexer reindexer = new Reindexer();
reindexer.idInit(paths.getXSize(), paths.getYSize());
Diff.ChangeBuilder builder = new Diff.ChangeBuilder(0);
- reindexer.reindex(paths, builder);
+ reindexer.reindex(changes, builder);
return builder.getFirstChange();
}
}
diff --git a/platform/util/testSrc/com/intellij/util/diff/PatienceIntLCSTest.java b/platform/util/testSrc/com/intellij/util/diff/PatienceIntLCSTest.java
new file mode 100644
index 0000000..eb9c1dc
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/diff/PatienceIntLCSTest.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diff;
+
+import junit.framework.TestCase;
+
+import java.util.BitSet;
+
+public class PatienceIntLCSTest extends TestCase {
+ public void testEqual() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3}, new int[]{1, 2, 3});
+ checkChange(change, new int[]{0, 0, 0}, new int[]{0, 0, 0});
+ }
+
+ public void testOneAtBegging() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2}, new int[]{1, 3});
+ checkChange(change, new int[]{0, 1}, new int[]{0, 1});
+ }
+
+ public void testOneAntEnd() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 3}, new int[]{2, 3});
+ checkChange(change, new int[]{1, 0}, new int[]{1, 0});
+ }
+
+ public void testOneOverAtEnd() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2}, new int[]{1, 2, 3});
+ checkChange(change, new int[]{0, 0}, new int[]{0, 0, 1});
+ }
+
+ public void testOneOverAtBegging() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3}, new int[]{2, 3});
+ checkChange(change, new int[]{1, 0, 0}, new int[]{0, 0});
+ }
+
+ public void testSingleMiddle() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3}, new int[]{4, 2, 5});
+ checkChange(change, new int[]{1, 0, 1}, new int[]{1, 0, 1});
+ }
+
+ public void testAbsolutelyDifferent() throws FilesTooBigForDiffException {
+ BitSet[] change1 = buildChange(new int[]{1, 2}, new int[]{3, 4});
+ checkChange(change1, new int[]{1, 1}, new int[]{1, 1});
+
+ BitSet[] change2 = buildChange(new int[]{1, 2, 3}, new int[]{4, 5, 6});
+ checkChange(change2, new int[]{1, 1, 1}, new int[]{1, 1, 1});
+ }
+
+ public void testSingleUniqueMoved() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 1, 2, 2, 10}, new int[]{10, 1, 1, 2, 2});
+ checkChange(change, new int[]{1, 1, 1, 1, 0}, new int[]{0, 1, 1, 1, 1});
+ }
+
+ public void testSingleFunctionMoved() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 7, 9, 10, 2, 11, 12, 5, 13, 7, 8, 7},
+ new int[]{10, 2, 11, 12, 5, 13, 7, 8, 7, 9, 1, 2, 3, 4, 5, 6, 7, 8, 7});
+ checkChange(change, new int[]{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
+ new int[]{0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
+ }
+
+ public void testInnerChunks1() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0}, new int[]{1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1});
+ checkChange(change, new int[]{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}, new int[]{1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1});
+ }
+
+ public void testInnerChunks2() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{0, 2, 3, 0, 4, 5, 0}, new int[]{1, 2, 1, 3, 4, 5, 1});
+ checkChange(change, new int[]{1, 0, 0, 1, 0, 0, 1}, new int[]{1, 0, 1, 0, 0, 0, 1});
+ }
+
+ public void testInnerChunks3() throws FilesTooBigForDiffException {
+ BitSet[] change = buildChange(new int[]{15, 1, 2, 3, 1, 4, 5, 1, 15}, new int[]{13, 1, 2, 1, 3, 4, 5, 1, 13});
+ checkChange(change, new int[]{1, 0, 0, 0, 1, 0, 0, 0, 1}, new int[]{1, 0, 0, 1, 0, 0, 0, 0, 1});
+ }
+
+ public void testInnerChunks4() throws FilesTooBigForDiffException {
+ BitSet[] change =
+ buildChange(new int[]{15, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 15}, new int[]{13, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 13});
+ checkChange(change, new int[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}, new int[]{1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1});
+ }
+
+ private static BitSet[] buildChange(int[] first, int[] second) throws FilesTooBigForDiffException {
+ PatienceIntLCS patienceIntLCS = new PatienceIntLCS(first, second);
+ patienceIntLCS.execute();
+ return patienceIntLCS.getChanges();
+ }
+
+ private static void checkChange(BitSet[] change, int[] expected1, int[] expected2) {
+ for (int i = 0; i < expected1.length; i++) {
+ assertEquals(change[0].get(i), expected1[i] == 1);
+ }
+ for (int i = 0; i < expected2.length; i++) {
+ assertEquals(change[1].get(i), expected2[i] == 1);
+ }
+ }
+}
diff --git a/platform/util/testSrc/com/intellij/util/diff/ReindexerNewTest.java b/platform/util/testSrc/com/intellij/util/diff/ReindexerNewTest.java
new file mode 100644
index 0000000..c9fe6fb
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/diff/ReindexerNewTest.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diff;
+
+import junit.framework.TestCase;
+
+import java.util.BitSet;
+import java.util.Random;
+
+public class ReindexerNewTest extends TestCase {
+ public void testAllUnique() throws FilesTooBigForDiffException {
+ checkCase(new int[]{1, 2, 3}, new int[]{4, 5});
+ checkCase(new int[]{}, new int[]{4, 5});
+ checkCase(new int[]{1, 2, 3}, new int[]{});
+ }
+
+ public void testUniqueBeginning() throws FilesTooBigForDiffException {
+ checkCase(new int[]{13, 15, 1, 2, 3}, new int[]{17, 1, 3});
+ }
+
+ public void testUniqueEnd() throws FilesTooBigForDiffException {
+ checkCase(new int[]{1, 2, 3, 13, 15}, new int[]{1, 3, 17});
+ }
+
+ public void testSingleUniqueMoved() throws FilesTooBigForDiffException {
+ checkCase(new int[]{1, 1, 2, 2, 10}, new int[]{10, 1, 1, 2, 2});
+ }
+
+ public void testSingleFunctionMoved() throws FilesTooBigForDiffException {
+ checkCase(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 7, 9, 10, 2, 11, 12, 5, 13, 7, 8, 7},
+ new int[]{10, 2, 11, 12, 5, 13, 7, 8, 7, 9, 1, 2, 3, 4, 5, 6, 7, 8, 7});
+ }
+
+ public void testInnerChunks() throws FilesTooBigForDiffException {
+ checkCase(new int[]{0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0}, new int[]{1, 2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1});
+ checkCase(new int[]{0, 2, 3, 0, 4, 5, 0}, new int[]{1, 2, 1, 3, 4, 5, 1});
+ checkCase(new int[]{15, 1, 2, 3, 1, 4, 5, 1, 15}, new int[]{13, 1, 2, 1, 3, 4, 5, 1, 13});
+ checkCase(new int[]{15, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 15}, new int[]{13, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 13});
+ }
+
+ public void testRandomExample() throws FilesTooBigForDiffException {
+ int[] ints1 = new int[100];
+ int[] ints2 = new int[100];
+ Random rng = new Random();
+ for (int i = 0; i < 10; i++) {
+ for (int j = 0; j < 100; j++) {
+ ints1[j] = rng.nextInt(60);
+ ints2[j] = rng.nextInt(60);
+ }
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("{");
+ for (int j = 0; j < 100; j++) {
+ builder.append(ints1[j]).append(", ");
+ }
+ builder.append("}\n{");
+ for (int j = 0; j < 100; j++) {
+ builder.append(ints2[j]).append(", ");
+ }
+ builder.append("}\n");
+
+ checkCase(ints1, ints2, builder.toString());
+ }
+ }
+
+ public static void checkCase(int[] ints1, int[] ints2) throws FilesTooBigForDiffException {
+ checkCase(ints1, ints2, null);
+ }
+
+ public static void checkCase(int[] ints1, int[] ints2, String message) throws FilesTooBigForDiffException {
+ final BitSet[] reindexChanges = new BitSet[]{new BitSet(), new BitSet()};
+ LCSBuilder builder = new LCSBuilder() {
+ private int myIndex1 = 0;
+ private int myIndex2 = 0;
+
+ @Override
+ public void addEqual(int length) {
+ myIndex1 += length;
+ myIndex2 += length;
+ }
+
+ @Override
+ public void addChange(int first, int second) {
+ reindexChanges[0].set(myIndex1, myIndex1 + first);
+ reindexChanges[1].set(myIndex2, myIndex2 + second);
+
+ myIndex1 += first;
+ myIndex2 += second;
+ }
+ };
+
+ IntLCS lcs = new IntLCS(ints1, ints2);
+ lcs.execute();
+ BitSet[] expectedChanges = lcs.getChanges();
+
+ Reindexer reindexer = new Reindexer();
+ int[][] discarded = reindexer.discardUnique(ints1, ints2);
+ lcs = new IntLCS(discarded[0], discarded[1]);
+ lcs.execute();
+ BitSet[] changes = lcs.getChanges();
+ reindexer.reindex(changes, builder);
+
+ if (message != null) {
+ assertEquals(message, expectedChanges[0], reindexChanges[0]);
+ assertEquals(message, expectedChanges[1], reindexChanges[1]);
+ }
+ else {
+ assertEquals(expectedChanges[0], reindexChanges[0]);
+ assertEquals(expectedChanges[1], reindexChanges[1]);
+ }
+ }
+}
diff --git a/platform/util/testSrc/com/intellij/util/diff/UniqueLCSTest.java b/platform/util/testSrc/com/intellij/util/diff/UniqueLCSTest.java
new file mode 100644
index 0000000..231d961
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/diff/UniqueLCSTest.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.diff;
+
+import junit.framework.TestCase;
+
+public class UniqueLCSTest extends TestCase {
+ public void testNoUnique() throws FilesTooBigForDiffException {
+ int[][] change = buildChange(new int[]{1, 2, 3}, new int[]{4, 5, 6});
+ assertNull(change);
+
+ change = buildChange(new int[]{1, 2, 1}, new int[]{1, 3, 1});
+ assertNull(change);
+
+ change = buildChange(new int[]{1, 2, 3, 3, 2, 1}, new int[]{1, 2, 3});
+ assertNull(change);
+
+ change = buildChange(new int[]{1, 2, 3}, new int[]{1, 2, 3, 3, 2, 1});
+ assertNull(change);
+
+ change = buildChange(new int[]{1, 2, 3}, new int[]{1, 2, 3, 3, 2, 1});
+ assertNull(change);
+
+ change = buildChange(new int[]{1, 2, 1}, new int[]{2, 1, 2});
+ assertNull(change);
+
+ change = buildChange(new int[]{}, new int[]{2, 1, 2});
+ assertNull(change);
+
+ change = buildChange(new int[]{1, 2, 2}, new int[]{});
+ assertNull(change);
+
+ change = buildChange(new int[]{}, new int[]{});
+ assertNull(change);
+ }
+
+ public void testSingleUnique() throws FilesTooBigForDiffException {
+ int[][] change = buildChange(new int[]{1}, new int[]{1});
+ checkChange(change, new int[]{0}, new int[]{0});
+
+ change = buildChange(new int[]{5, 1}, new int[]{1});
+ checkChange(change, new int[]{1}, new int[]{0});
+
+ change = buildChange(new int[]{1}, new int[]{2, 1});
+ checkChange(change, new int[]{0}, new int[]{1});
+
+ change = buildChange(new int[]{1}, new int[]{1, 4});
+ checkChange(change, new int[]{0}, new int[]{0});
+
+ change = buildChange(new int[]{1, 3}, new int[]{1});
+ checkChange(change, new int[]{0}, new int[]{0});
+
+ change = buildChange(new int[]{5, 1, 3}, new int[]{2, 1, 4});
+ checkChange(change, new int[]{1}, new int[]{1});
+ }
+
+ public void testSingleSequence() throws FilesTooBigForDiffException {
+ int[][] change = buildChange(new int[]{2, 4, 6, 1, 8, 3, 8, 2, 6, 5, 2, 4, 7, 11, 13}, new int[]{1, 10, 2, 3, 5, 7, 11, 13, 12});
+ checkChange(change, new int[]{3, 5, 9, 12, 13, 14}, new int[]{0, 3, 4, 5, 6, 7});
+ }
+
+ public void testLargestLCS1() throws FilesTooBigForDiffException {
+ checkMaxSequence(new int[]{1, 2, 3}, new int[]{1, 2, 3});
+ }
+
+ public void testLargestLCS2() throws FilesTooBigForDiffException {
+ checkMaxSequence(new int[]{5, 6, 1, 2, 3}, new int[]{1, 2, 3});
+ }
+
+ public void testLargestLCS3() throws FilesTooBigForDiffException {
+ checkMaxSequence(new int[]{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 7, 15}, new int[]{0, 2, 6, 9, 13, 15});
+ }
+
+ public void testLargestLCS4() throws FilesTooBigForDiffException {
+ checkMaxSequence(new int[]{1, 9, 3, 8, 11, 4, 5, 6, 19, 7}, new int[]{1, 3, 4, 5, 6, 7});
+ }
+
+ private static int[][] buildChange(int[] first, int[] second) throws FilesTooBigForDiffException {
+ UniqueLCS uniqueLCS = new UniqueLCS(first, second);
+ return uniqueLCS.execute();
+ }
+
+ private static void checkChange(int[][] change, int[] expected1, int[] expected2) {
+ for (int i = 0; i < expected1.length; i++) {
+ assertEquals(change[0][i], expected1[i]);
+ }
+ for (int i = 0; i < expected2.length; i++) {
+ assertEquals(change[1][i], expected2[i]);
+ }
+ }
+
+ private static void checkMaxSequence(int[] sequence, int[] expected) throws FilesTooBigForDiffException {
+ int max = 0;
+ for (int i = 0; i < sequence.length; i++) {
+ max = Math.max(sequence[i] + 1, max);
+ }
+
+ int[] first = new int[sequence.length];
+ int[] second = new int[max + 2];
+
+ for (int i = 0; i < sequence.length; i++) {
+ assertEquals("Elements in sequence should be unique", second[sequence[i]], 0);
+ first[i] = i + 1;
+ second[sequence[i]] = i + 1;
+ }
+
+ int[][] result = buildChange(first, second);
+
+ assertEquals(result[0].length, result[1].length);
+ assertEquals(result[0].length, expected.length);
+ for (int i = 0; i < expected.length; i++) {
+ assertEquals(expected[i], sequence[result[0][i]]);
+ }
+ }
+}
diff --git a/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java b/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java
index 42602b9..03b785e 100644
--- a/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/text/DateFormatUtilTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -15,19 +15,30 @@
*/
package com.intellij.util.text;
+import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.Clock;
import com.intellij.openapi.util.SystemInfo;
-import junit.framework.TestCase;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
+import org.junit.Test;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
+import java.util.List;
-public class DateFormatUtilTest extends TestCase {
- private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy hh.mm.ss");
+import static org.junit.Assert.assertEquals;
+public class DateFormatUtilTest {
+ @SuppressWarnings("SpellCheckingInspection") private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy hh.mm.ss");
+
+ @Test
public void testBasics() throws ParseException {
Clock.setTime(2004, 11, 10, 17, 10);
@@ -38,34 +49,35 @@
doTestPrettyDate(DateFormatUtil.formatDate(DATE_FORMAT.parse("10.12.2003 17.00.00")), "10.12.2003 17.00.00");
}
- public void testTime() throws ParseException {
+ @Test
+ public void testTime() throws Exception {
Clock.setTime(2004, 11, 10, 17, 10, 15);
if (SystemInfo.isMac) {
assertEquals("17:10", DateFormatUtil.formatTime(Clock.getTime()));
assertEquals("17:10:15", DateFormatUtil.formatTimeWithSeconds(Clock.getTime()));
}
+ else if (SystemInfo.isUnix) {
+ assertEquals("5:10:15 PM", printTimeForLocale("en_US.UTF-8"));
+ assertEquals("17:10:15", printTimeForLocale("de_DE.UTF-8"));
+ }
else {
assertEquals(DateFormat.getTimeInstance(DateFormat.SHORT).format(Clock.getTime()),
DateFormatUtil.formatTime(Clock.getTime()));
assertEquals(DateFormat.getTimeInstance(DateFormat.MEDIUM).format(Clock.getTime()),
- DateFormatUtil.formatTimeWithSeconds(Clock.getTime()));
+ DateFormatUtil.formatTimeWithSeconds(new Date(Clock.getTime())));
}
}
+ @Test
public void testPrettyDateTime() throws ParseException {
Clock.setTime(2004, 11, 10, 17, 0);
-
doTestDateTime("Moments ago", "10.12.2004 16.59.31");
doTestDateTime("A minute ago", "10.12.2004 16.59.29");
doTestDateTime("5 minutes ago", "10.12.2004 16.55.00");
doTestDateTime("1 hour ago", "10.12.2004 16.00.00");
doTestDateTime("Today " + DateFormatUtil.formatTime(DATE_FORMAT.parse("10.12.2004 15.55.00")), "10.12.2004 15.55.00");
doTestDateTime("Yesterday " + DateFormatUtil.formatTime(DATE_FORMAT.parse("09.12.2004 15.00.00")), "09.12.2004 15.00.00");
-
- doTestDateTime(DateFormatUtil.formatDateTime(DATE_FORMAT.parse("08.12.2004 15.00.00")), "08.12.2004 15.00.00");
- doTestDateTime(DateFormatUtil.formatDateTime(DATE_FORMAT.parse("07.12.2004 15.00.00")), "07.12.2004 15.00.00");
-
doTestDateTime("Today " + DateFormatUtil.formatTime(DATE_FORMAT.parse("10.12.2004 19.00.00")), "10.12.2004 19.00.00");
Clock.setTime(2004, 0, 1, 15, 53);
@@ -73,6 +85,18 @@
doTestDateTime("Yesterday " + DateFormatUtil.formatTime(DATE_FORMAT.parse("31.12.2003 15.00.00")), "31.12.2003 15.00.00");
}
+ @Test
+ public void testAboutDialogDataFormatter() {
+ assertEquals("December 12, 2012", DateFormatUtil.formatAboutDialogDate(date(2012, 12, 12, 15, 35, 12)));
+ assertEquals("January 1, 1999", DateFormatUtil.formatAboutDialogDate(date(1999, 1, 1, 0, 0, 0)));
+ }
+
+ @Test
+ public void testFormatFrequency() {
+ assertEquals("Once in 2 minutes", DateFormatUtil.formatFrequency(2 * 60 * 1000));
+ assertEquals("Once in a few moments", DateFormatUtil.formatFrequency(1000));
+ }
+
private static void doTestPrettyDate(String expected, String date) throws ParseException {
assertEquals(expected, DateFormatUtil.formatPrettyDate(DATE_FORMAT.parse(date)));
}
@@ -85,65 +109,26 @@
return new GregorianCalendar(year, month - 1, day, hour, minute, second).getTime();
}
- public void testConvertingMacToJavaPattern() throws Throwable {
- Clock.setTime(date(2004, 2, 5, 16, 6, 7).getTime() + 8);
+ private static String printTimeForLocale(String locale) throws IOException {
+ List<String> classpath = ContainerUtil.newArrayList();
+ classpath.addAll(PathManager.getUtilClassPath());
+ classpath.add(PathManager.getJarPathForClass(PrintTime.class));
+ ProcessBuilder builder = new ProcessBuilder()
+ .command(System.getProperty("java.home") + "/bin/java",
+ "-classpath",
+ StringUtil.join(classpath, File.pathSeparator),
+ PrintTime.class.getName(),
+ String.valueOf(Clock.getTime()))
+ .redirectErrorStream(true);
+ builder.environment().put("LC_TIME", locale);
+ Process process = builder.start();
- String mon = new SimpleDateFormat("MMM").format(Clock.getTime());
- String month = new SimpleDateFormat("MMMMM").format(Clock.getTime());
- String weekd = new SimpleDateFormat("EEE").format(Clock.getTime());
- String weekday = new SimpleDateFormat("EEEEE").format(Clock.getTime());
-
- assertConvertedFormat("%y %Y", "04 2004");
- assertConvertedFormat("%b %B %m", mon + " " + month + " 02");
- assertConvertedFormat("%d %e %j", "05 5 036");
- assertConvertedFormat("%a %A %w", weekd + " " + weekday + " " + weekd);
-
- assertConvertedFormat("%H %I", "16 04");
- assertConvertedFormat("%M %S %F %p", "06 07 008 PM");
-
- assertConvertedFormatMatches("%z %Z", "\\+\\d{4} \\w{3}");
-
- assertConvertedFormat(" foo bar ", " foo bar ");
- assertConvertedFormat(" 'foo''a'a'' '' ' ", " 'foo''a'a'' '' ' ");
- assertConvertedFormat(" '%a''%a'%a'' '' ' '%a ", " '" + weekd + "''" + weekd + "'" + weekd + "'' '' ' '" + weekd + " ");
- assertConvertedFormat("'a'", "'a'");
- assertConvertedFormat("'", "'");
- assertConvertedFormat("''", "''");
- assertConvertedFormat("a", "a");
- assertConvertedFormat(" ", " ");
- assertConvertedFormat("%1", "?%1?");
- assertConvertedFormat("", "");
-
- assertConvertedFormat("%", "");
- }
-
- private static void assertConvertedFormat(String pattern, String expected) throws Throwable {
- String converted = DateFormatUtil.convertMacPattern(pattern);
+ BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
try {
- assertEquals(expected, new SimpleDateFormat(converted).format(Clock.getTime()));
+ return reader.readLine();
}
- catch (Throwable e) {
- System.out.println("cannot format with [" + converted + "]");
- throw e;
+ finally {
+ reader.close();
}
}
-
- private static void assertConvertedFormatMatches(String pattern, String expectedPattern) throws Throwable {
- String converted = DateFormatUtil.convertMacPattern(pattern);
- try {
- String actual = new SimpleDateFormat(converted).format(Clock.getTime());
- assertTrue(actual, actual.matches(expectedPattern));
- }
- catch (Throwable e) {
- System.out.println("cannot format with [" + converted + "]");
- throw e;
- }
- }
-
- public void testAboutDialogDataFormatter() throws Exception {
- assertEquals("December 12, 2012",
- DateFormatUtil.formatAboutDialogDate(date(2012, 12, 12, 15, 35, 12)));
- assertEquals("January 1, 1999",
- DateFormatUtil.formatAboutDialogDate(date(1999, 1, 1, 0, 0, 0)));
- }
}
diff --git a/platform/util/testSrc/com/intellij/util/text/PrintTime.java b/platform/util/testSrc/com/intellij/util/text/PrintTime.java
new file mode 100644
index 0000000..d062aad
--- /dev/null
+++ b/platform/util/testSrc/com/intellij/util/text/PrintTime.java
@@ -0,0 +1,28 @@
+/*
+ * 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.util.text;
+
+public class PrintTime {
+ public static void main(String[] args) {
+ if (args.length != 1) {
+ throw new IllegalArgumentException("Time expected");
+ }
+
+ long time = Long.parseLong(args[0]);
+ String result = DateFormatUtil.formatTimeWithSeconds(time);
+ System.out.println(result);
+ }
+}
diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
index 26f556e..2f31dc4 100644
--- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
+++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java
@@ -147,8 +147,52 @@
assertEquals("foo\\\"bar'\\\"", StringUtil.escapeQuotes("foo\"bar'\""));
}
+ public void testUnqote() {
+ assertEquals("", StringUtil.unquoteString(""));
+ assertEquals("\"", StringUtil.unquoteString("\""));
+ assertEquals("", StringUtil.unquoteString("\"\""));
+ assertEquals("\"", StringUtil.unquoteString("\"\"\""));
+ assertEquals("foo", StringUtil.unquoteString("\"foo\""));
+ assertEquals("\"foo", StringUtil.unquoteString("\"foo"));
+ assertEquals("foo\"", StringUtil.unquoteString("foo\""));
+ assertEquals("", StringUtil.unquoteString(""));
+ assertEquals("\'", StringUtil.unquoteString("\'"));
+ assertEquals("", StringUtil.unquoteString("\'\'"));
+ assertEquals("\'", StringUtil.unquoteString("\'\'\'"));
+ assertEquals("foo", StringUtil.unquoteString("\'foo\'"));
+ assertEquals("\'foo", StringUtil.unquoteString("\'foo"));
+ assertEquals("foo\'", StringUtil.unquoteString("foo\'"));
+
+ assertEquals("\'\"", StringUtil.unquoteString("\'\""));
+ assertEquals("\"\'", StringUtil.unquoteString("\"\'"));
+ assertEquals("\"foo\'", StringUtil.unquoteString("\"foo\'"));
+ }
+
+ public void testUnqoteWithQuotationChar() {
+ assertEquals("", StringUtil.unquoteString("", '|'));
+ assertEquals("|", StringUtil.unquoteString("|", '|'));
+ assertEquals("", StringUtil.unquoteString("||", '|'));
+ assertEquals("|", StringUtil.unquoteString("|||", '|'));
+ assertEquals("foo", StringUtil.unquoteString("|foo|", '|'));
+ assertEquals("|foo", StringUtil.unquoteString("|foo", '|'));
+ assertEquals("foo|", StringUtil.unquoteString("foo|", '|'));
+ }
+
public void testJoin() {
assertEquals("foo,,bar", StringUtil.join(Arrays.asList("foo", "", "bar"), ","));
assertEquals("foo,,bar", StringUtil.join(new String[]{"foo", "", "bar"}, ","));
}
+
+ public void testSplitByLineKeepingSeparators() {
+ assertEquals(Arrays.asList(""), Arrays.asList(StringUtil.splitByLinesKeepSeparators("")));
+ assertEquals(Arrays.asList("aa"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("aa")));
+ assertEquals(Arrays.asList("\n", "\n", "aa\n", "\n", "bb\n", "cc\n", "\n"),
+ Arrays.asList(StringUtil.splitByLinesKeepSeparators("\n\naa\n\nbb\ncc\n\n")));
+
+ assertEquals(Arrays.asList("\r", "\r\n", "\r"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("\r\r\n\r")));
+ assertEquals(Arrays.asList("\r\n", "\r", "\r\n"), Arrays.asList(StringUtil.splitByLinesKeepSeparators("\r\n\r\r\n")));
+
+ assertEquals(Arrays.asList("\n", "\r\n", "\n", "\r\n", "\r", "\r", "aa\r", "bb\r\n", "cc\n", "\r", "dd\n", "\n", "\r\n", "\r"),
+ Arrays.asList(StringUtil.splitByLinesKeepSeparators("\n\r\n\n\r\n\r\raa\rbb\r\ncc\n\rdd\n\n\r\n\r")));
+ }
}
diff --git a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
index be50223..d705888 100644
--- a/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
+++ b/platform/util/testSrc/com/intellij/util/xmlb/XmlSerializerTest.java
@@ -17,13 +17,16 @@
package com.intellij.util.xmlb;
import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.xmlb.annotations.*;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
-import java.util.Collection;
import java.util.concurrent.atomic.AtomicReference;
/**
@@ -806,6 +809,8 @@
public int COUNT = 3;
@Attribute("name")
public String name = "James";
+ @Attribute("occupation")
+ public String occupation;
}
public void testBeanWithPrimitivePropertyBoundToAttribute() {
final BeanWithPropertiesBoundToAttribute bean = new BeanWithPropertiesBoundToAttribute();
@@ -848,7 +853,7 @@
bean.STRING_V = "skip";
- assertSerializer(bean, "<BeanWithPropertyFilter />", "Serialization failure", null);
+ assertSerializer(bean, "<BeanWithPropertyFilter />", null);
}
public static class BeanWithJDOMElement {
@@ -1086,15 +1091,69 @@
bean);
}
+ private static class BeanWithConverter {
+ private static class MyConverter extends Converter<Ref<String>> {
+ @Nullable
+ @Override
+ public Ref<String> fromString(@NotNull String value) {
+ return Ref.create(value);
+ }
+
+ @NotNull
+ @Override
+ public String toString(@NotNull Ref<String> o) {
+ return StringUtil.notNullize(o.get());
+ }
+ }
+
+ @Attribute(converter = MyConverter.class)
+ public Ref<String> foo;
+
+ @OptionTag(converter = MyConverter.class)
+ public Ref<String> bar;
+ }
+
+ public void testConverter() {
+ BeanWithConverter bean = new BeanWithConverter();
+ doSerializerTest("<BeanWithConverter>\n" +
+ " <option name=\"bar\" />\n" +
+ "</BeanWithConverter>", bean);
+
+ bean.foo = Ref.create("testValue");
+ doSerializerTest("<BeanWithConverter foo=\"testValue\">\n" +
+ " <option name=\"bar\" />\n" +
+ "</BeanWithConverter>", bean);
+
+ bean.foo = Ref.create();
+ bean.bar = Ref.create("testValue2");
+ doSerializerTest("<BeanWithConverter foo=\"\">\n" +
+ " <option name=\"bar\" value=\"testValue2\" />\n" +
+ "</BeanWithConverter>", bean);
+ }
+
+ private static class BeanWithDefaultAttributeName {
+ @Attribute
+ public String getFoo() {
+ return "foo";
+ }
+
+ public void setFoo(@SuppressWarnings("UnusedParameters") String value) {
+ }
+ }
+
+ public void testDefaultAttributeName() {
+ BeanWithDefaultAttributeName bean = new BeanWithDefaultAttributeName();
+ doSerializerTest("<BeanWithDefaultAttributeName foo=\"foo\" />", bean);
+ }
//---------------------------------------------------------------------------------------------------
- private static void assertSerializer(Object bean, String expected, SerializationFilter filter) {
- assertSerializer(bean, expected, "Serialization failure", filter);
+ private static Element assertSerializer(Object bean, String expected, SerializationFilter filter) {
+ return assertSerializer(bean, expected, "Serialization failure", filter);
}
private static Object doSerializerTest(String expectedText, Object bean) {
try {
- Element element = assertSerializer(bean, expectedText, "Serialization failure", null);
+ Element element = assertSerializer(bean, expectedText, null);
//test deserializer
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java
index 1c27bd6..c31dddf 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/AbstractVcs.java
@@ -375,7 +375,7 @@
* from revision numbers.
*
* @param revisionNumberString the string to be parsed
- * @param path the path for which revsion number is queried
+ * @param path the path for which revision number is queried
* @return the parsed revision number
*/
@Nullable
@@ -589,8 +589,7 @@
}
}
};
- final boolean succeded = VcsSynchronousProgressWrapper.wrap(runnable, getProject(), "Load revision contents");
- return succeded ? list[0] : null;
+ return VcsSynchronousProgressWrapper.wrap(runnable, getProject(), "Load revision contents") ? list[0] : null;
}
@Nullable
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ConcurrentTasks.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ConcurrentTasks.java
index f2b0bcb..c045561 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/ConcurrentTasks.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ConcurrentTasks.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.
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java
index 35b3a2a..496acbc 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsConfiguration.java
@@ -135,6 +135,8 @@
public boolean REFORMAT_BEFORE_PROJECT_COMMIT = false;
public boolean REFORMAT_BEFORE_FILE_COMMIT = false;
+ public boolean REARRANGE_BEFORE_PROJECT_COMMIT = false;
+
public float FILE_HISTORY_DIALOG_COMMENTS_SPLITTER_PROPORTION = 0.8f;
public float FILE_HISTORY_DIALOG_SPLITTER_PROPORTION = 0.5f;
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java
index 34fdd62..6f5ea05 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/VcsTaskHandler.java
@@ -36,15 +36,26 @@
public TaskInfo(MultiMap<String, String> branches) {
this.branches = branches;
}
+
+ public String getName() {
+ return branches.isEmpty() ? null : branches.keySet().iterator().next();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return branches.equals(((TaskInfo)obj).branches);
+ }
}
private static final ExtensionPointName<VcsTaskHandler> EXTENSION_POINT_NAME = ExtensionPointName.create("com.intellij.vcs.taskHandler");
public abstract TaskInfo startNewTask(String taskName);
- public abstract void switchToTask(TaskInfo taskInfo);
+ public abstract void switchToTask(TaskInfo taskInfo, Runnable invokeAfter);
public abstract void closeTask(TaskInfo taskInfo, TaskInfo original);
public abstract TaskInfo getActiveTask();
+
+ public abstract TaskInfo[] getCurrentTasks();
}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
index f3f2958..006276b 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/changes/ChangeListManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -157,5 +157,6 @@
public abstract List<VirtualFile> getModifiedWithoutEditing();
- public abstract ThreeState haveChangesUnder(VirtualFile vf);
+ @NotNull
+ public abstract ThreeState haveChangesUnder(@NotNull VirtualFile vf);
}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java b/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java
index e3ab8d9..3dd5cdf 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/impl/ContentRevisionCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -175,7 +175,7 @@
public byte[] getBytes(FilePath path, VcsRevisionNumber number, @NotNull VcsKey vcsKey, @NotNull UniqueType type) {
synchronized (myLock) {
final SoftReference<byte[]> reference = myCache.get(new Key(path, number, vcsKey, type));
- return reference != null ? reference.get() : null;
+ return SoftReference.dereference(reference);
}
}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ui/ReplaceFileConfirmationDialog.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ui/ReplaceFileConfirmationDialog.java
index 4578cd4..2ee0a3d 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/ui/ReplaceFileConfirmationDialog.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ui/ReplaceFileConfirmationDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,18 +15,17 @@
*/
package com.intellij.openapi.vcs.ui;
+import com.intellij.CommonBundle;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.FileStatusManager;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ui.FilePathSplittingPolicy;
-import com.intellij.CommonBundle;
import java.io.File;
import java.util.ArrayList;
@@ -62,7 +61,7 @@
return Messages.showOkCancelDialog(createMessage(modifiedFiles), myActionName,
createOwerriteButtonName(modifiedFiles), getCancelButtonText(),
Messages.getWarningIcon()) ==
- DialogWrapper.OK_EXIT_CODE;
+ Messages.OK;
}
diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/ui/TextFieldAction.java b/platform/vcs-api/src/com/intellij/openapi/vcs/ui/TextFieldAction.java
index b570566..b189f69 100644
--- a/platform/vcs-api/src/com/intellij/openapi/vcs/ui/TextFieldAction.java
+++ b/platform/vcs-api/src/com/intellij/openapi/vcs/ui/TextFieldAction.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.util.SystemInfo;
import com.intellij.ui.ClickListener;
import com.intellij.ui.IdeBorderFactory;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -53,6 +54,7 @@
@Override
public abstract void actionPerformed(@Nullable AnActionEvent e);
+ @Override
public JComponent createCustomComponent(Presentation presentation) {
// honestly borrowed from SearchTextField
@@ -80,7 +82,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
actionPerformed(null);
return true;
}
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/UIVcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/UIVcsUtil.java
index 9bf0a44..36aede3 100644
--- a/platform/vcs-api/src/com/intellij/vcsUtil/UIVcsUtil.java
+++ b/platform/vcs-api/src/com/intellij/vcsUtil/UIVcsUtil.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.util.text.StringUtil;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ui.UIUtil;
+import com.intellij.xml.util.XmlStringUtil;
import javax.swing.*;
import java.awt.*;
@@ -32,7 +33,7 @@
}
public static JPanel errorPanel(final String text, boolean isError) {
- final JLabel label = new JLabel("<html><body>" + escapeXmlAndAddBr(text) + "</body></html>");
+ final JLabel label = new JLabel(XmlStringUtil.wrapInHtml(escapeXmlAndAddBr(text)));
label.setForeground(isError ? SimpleTextAttributes.ERROR_ATTRIBUTES.getFgColor() : UIUtil.getInactiveTextColor());
final JPanel wrapper = new JPanel(new GridBagLayout());
wrapper.add(label, new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE,
@@ -47,8 +48,8 @@
}
public static JPanel infoPanel(final String header, final String text) {
- final JLabel label = new JLabel("<html><body><h4>" + StringUtil.escapeXml(header) +
- "</h4>" + escapeXmlAndAddBr(text) + "</body></html>");
+ final JLabel label = new JLabel(XmlStringUtil.wrapInHtml("<h4>" + StringUtil.escapeXml(header) +
+ "</h4>" + escapeXmlAndAddBr(text)));
final JPanel wrapper = new JPanel(new GridBagLayout());
wrapper.add(label, new GridBagConstraints(0,0,1,1,0,0,GridBagConstraints.CENTER, GridBagConstraints.NONE,
new Insets(1,1,1,1), 0,0));
diff --git a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
index f49131c..bdd9304 100644
--- a/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.java
+++ b/platform/vcs-api/src/com/intellij/vcsUtil/VcsUtil.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,7 +18,6 @@
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
@@ -296,27 +295,25 @@
});
}
- // FileDocumentManager has difficulties in loading the content for files
- // which are outside the project structure?
- public static byte[] getFileByteContent(final File file) throws IOException {
- return ApplicationManager.getApplication().runReadAction(new Computable<byte[]>() {
- public byte[] compute() {
- byte[] content;
- try {
- content = FileUtil.loadFileBytes(file);
- }
- catch (IOException e) {
- content = null;
- }
- return content;
- }
- });
+ @Nullable
+ public static byte[] getFileByteContent(@NotNull File file) throws IOException {
+ try {
+ return FileUtil.loadFileBytes(file);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ return null;
+ }
}
public static FilePath getFilePath(String path) {
return getFilePath(new File(path));
}
+ public static FilePath getFilePath(@NotNull VirtualFile file) {
+ return VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
+ }
+
public static FilePath getFilePath(File file) {
return VcsContextFactory.SERVICE.getInstance().createFilePathOn(file);
}
@@ -325,6 +322,10 @@
return getFilePath(new File(path), isDirectory);
}
+ public static FilePath getFilePathOnNonLocal(String path, boolean isDirectory) {
+ return VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(path, isDirectory);
+ }
+
public static FilePath getFilePath(File file, boolean isDirectory) {
return VcsContextFactory.SERVICE.getInstance().createFilePathOn(file, isDirectory);
}
@@ -588,7 +589,7 @@
return (! s1Trimmed.equals(s2Trimmed)) && s1Trimmed.equalsIgnoreCase(s2Trimmed);
}
- private static String ANNO_ASPECT = "show.vcs.annotation.aspect.";
+ private static final String ANNO_ASPECT = "show.vcs.annotation.aspect.";
//public static boolean isAspectAvailableByDefault(LineAnnotationAspect aspect) {
// if (aspect.getId() == null) return aspect.isShowByDefault();
// return PropertiesComponent.getInstance().getBoolean(ANNO_ASPECT + aspect.getId(), aspect.isShowByDefault());
diff --git a/platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.java b/platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.java
new file mode 100644
index 0000000..79988fc
--- /dev/null
+++ b/platform/vcs-impl/src/com/intellij/diff/FileAwareSimpleContent.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.diff;
+
+import com.intellij.openapi.diff.SimpleContent;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
+import com.intellij.openapi.fileTypes.FileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * A {@link SimpleContent} which content is retrieved from a file which exists or existed in the project.
+ */
+public class FileAwareSimpleContent extends SimpleContent {
+
+ @NotNull private final Project myProject;
+ @NotNull private final FilePath myFilePath;
+
+ public FileAwareSimpleContent(@NotNull Project project, @NotNull FilePath filePath, @NotNull String text, @Nullable FileType type) {
+ super(text, type);
+ myProject = project;
+ myFilePath = filePath;
+ }
+
+ @Override
+ public OpenFileDescriptor getOpenFileDescriptor(int offset) {
+ VirtualFile file = LocalFileSystem.getInstance().findFileByIoFile(myFilePath.getIOFile());
+ return file == null ? null : new OpenFileDescriptor(myProject, file, offset);
+ }
+
+}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java
index cae0b4f..4f7f39f 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/dir/DirDiffPanel.java
@@ -43,6 +43,7 @@
import com.intellij.util.diff.FilesTooBigForDiffException;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
@@ -141,7 +142,7 @@
}.registerCustomShortcutSet(CustomShortcutSet.fromString("SPACE"), myTable);
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (e.getButton() == MouseEvent.BUTTON3) return false;
if (myTable.getRowCount() > 0) {
final int row = myTable.rowAtPoint(e.getPoint());
diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/TriggerAdditionOrDeletion.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/TriggerAdditionOrDeletion.java
index b749375..bd88045 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/TriggerAdditionOrDeletion.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/TriggerAdditionOrDeletion.java
@@ -17,6 +17,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vcs.changes.SortByVcsRoots;
@@ -45,7 +46,7 @@
public TriggerAdditionOrDeletion(final Project project, boolean silentAddDelete) {
myProject = project;
- mySilentAddDelete = silentAddDelete;
+ mySilentAddDelete = Registry.is("vcs.add.remove.silent"); // TODO there is no sense in making add/remove non-silent anywhen; wait for users feedback, then remove
myExisting = new HashSet<FilePath>();
myDeleted = new HashSet<FilePath>();
myVcsManager = ProjectLevelVcsManager.getInstance(myProject);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateActionGroup.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateActionGroup.java
index 8e102f1..fc355fd 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateActionGroup.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateActionGroup.java
@@ -15,7 +15,10 @@
*/
package com.intellij.openapi.vcs.actions;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.Separator;
import com.intellij.openapi.editor.ex.EditorGutterComponentEx;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -27,7 +30,7 @@
* @author Konstantin Bulenkov
*/
public class AnnotateActionGroup extends ActionGroup {
- private AnAction[] myActions;
+ private final AnAction[] myActions;
public AnnotateActionGroup(List<AnnotationFieldGutter> gutters, EditorGutterComponentEx gutterComponent) {
super("View", true);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java
index b869c57..a31a3ae 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/AnnotateToggleAction.java
@@ -63,6 +63,7 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.actions.AnnotateToggleAction");
protected static final Key<Collection<ActiveAnnotationGutter>> KEY_IN_EDITOR = Key.create("Annotations");
+ @Override
public void update(AnActionEvent e) {
super.update(e);
final boolean enabled = isEnabled(VcsContextFactory.SERVICE.getInstance().createContextOn(e));
@@ -71,8 +72,9 @@
private static boolean isEnabled(final VcsContext context) {
VirtualFile[] selectedFiles = context.getSelectedFiles();
- if (selectedFiles == null) return false;
- if (selectedFiles.length != 1) return false;
+ if (selectedFiles.length != 1) {
+ return false;
+ }
VirtualFile file = selectedFiles[0];
if (file.isDirectory()) return false;
Project project = context.getProject();
@@ -98,6 +100,7 @@
return !selectedFile.getFileType().isBinary();
}
+ @Override
public boolean isSelected(AnActionEvent e) {
VcsContext context = VcsContextFactory.SERVICE.getInstance().createContextOn(e);
Editor editor = context.getEditor();
@@ -124,6 +127,7 @@
return annotations != null && !annotations.isEmpty();
}
+ @Override
public void setSelected(AnActionEvent e, boolean selected) {
final VcsContext context = VcsContextFactory.SERVICE.getInstance().createContextOn(e);
Editor editor = context.getEditor();
@@ -153,7 +157,9 @@
private static void doAnnotate(final Editor editor, final Project project) {
final VirtualFile file = FileDocumentManager.getInstance().getFile(editor.getDocument());
- if (project == null) return;
+ if (project == null || file == null) {
+ return;
+ }
final ProjectLevelVcsManager plVcsManager = ProjectLevelVcsManager.getInstance(project);
final AbstractVcs vcs = plVcsManager.getVcsFor(file);
@@ -172,6 +178,7 @@
VcsBundle.message("retrieving.annotations"),
true,
BackgroundFromStartOption.getInstance()) {
+ @Override
public void run(final @NotNull ProgressIndicator indicator) {
try {
fileAnnotationRef.set(annotationProvider.annotate(file));
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java
index 6872073..704b4b5 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/actions/DiffActionExecutor.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.vcs.actions;
+import com.intellij.diff.FileAwareSimpleContent;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diff.*;
import com.intellij.openapi.editor.Document;
@@ -86,7 +87,7 @@
if (content == null) {
throw new VcsException("Failed to load content");
}
- return new SimpleContent(content, mySelectedFile.getFileType());
+ return new FileAwareSimpleContent(myProject, fileRevision.getFile(), content, mySelectedFile.getFileType());
}
return null;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
index 3e9e9b8..825357f 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListManagerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -1088,9 +1088,10 @@
return getChangesIn(new FilePathImpl(dir));
}
+ @NotNull
@Override
- public ThreeState haveChangesUnder(final VirtualFile vf) {
- if (vf == null || ! vf.isValid() || ! vf.isDirectory()) return ThreeState.NO;
+ public ThreeState haveChangesUnder(@NotNull final VirtualFile vf) {
+ if (!vf.isValid() || !vf.isDirectory()) return ThreeState.NO;
synchronized (myDataLock) {
return myWorker.haveChangesUnder(vf);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java
index 3179c0f..e5762dd 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangeListWorker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -28,6 +28,7 @@
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlusMinusModify;
import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -108,10 +109,6 @@
protected Collection<Pair<Change, String>> createCollection() {
return new LinkedList<Pair<Change, String>>();
}
-
- protected Collection<Pair<Change, String>> createEmptyCollection() {
- return Collections.emptyList();
- }
};
for (LocalChangeList changeList : myMap.values()) {
@@ -437,7 +434,7 @@
@NotNull
public List<VirtualFile> getAffectedFiles() {
- final List<VirtualFile> result = new ArrayList<VirtualFile>();
+ final Set<VirtualFile> result = ContainerUtil.newLinkedHashSet();
for (LocalChangeList list : myMap.values()) {
for (Change change : list.getChanges()) {
final ContentRevision before = change.getBeforeRevision();
@@ -456,7 +453,7 @@
}
}
}
- return result;
+ return new ArrayList<VirtualFile>(result);
}
public LocalChangeList getListCopy(@NotNull final VirtualFile file) {
@@ -693,8 +690,9 @@
return null;
}
- public ThreeState haveChangesUnder(final VirtualFile vf) {
- final String absolutePath = new File(vf.getPath()).getAbsolutePath();
+ @NotNull
+ public ThreeState haveChangesUnder(@NotNull VirtualFile virtualFile) {
+ final String absolutePath = new File(virtualFile.getPath()).getAbsolutePath();
final SortedSet<String> tailSet = myIdx.getAffectedPaths().tailSet(absolutePath);
for (String path : tailSet) {
return FileUtil.isAncestorThreeState(absolutePath, path, false);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java
index cb8ddfd..d64298c 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ChangesFragmentedDiffPanel.java
@@ -21,7 +21,6 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diff.DiffPanel;
-import com.intellij.openapi.diff.ShiftedSimpleContent;
import com.intellij.openapi.diff.ex.DiffPanelEx;
import com.intellij.openapi.diff.ex.DiffPanelOptions;
import com.intellij.openapi.diff.impl.DiffPanelImpl;
@@ -36,9 +35,6 @@
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
-import com.intellij.openapi.editor.ScrollingModel;
-import com.intellij.openapi.editor.event.VisibleAreaEvent;
-import com.intellij.openapi.editor.event.VisibleAreaListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.highlighter.FragmentedEditorHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
@@ -49,7 +45,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.DialogWrapperDialog;
-import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
@@ -58,17 +53,13 @@
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.BeforeAfter;
import com.intellij.util.PlatformIcons;
-import com.intellij.util.ui.ButtonlessScrollBarUI;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
-import java.awt.event.AdjustmentEvent;
-import java.awt.event.AdjustmentListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
-import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
@@ -92,7 +83,6 @@
private boolean myCurrentHorizontal;
private JPanel myTopPanel;
private List<Integer> myLeftLines;
- private List<Integer> myRightLines;
private final MyNextDiffAction myNextDiff;
private final MyPreviousDiffAction myPreviousDiff;
private final JLabel myTitleLabel;
@@ -292,7 +282,6 @@
FragmentedDiffPanelState state = (FragmentedDiffPanelState)((DiffPanelImpl)currentPanel).getDiffPanelState();
myTitleLabel.setText(titleText((DiffPanelImpl)currentPanel));
myLeftLines = state.getLeftLines();
- myRightLines = state.getRightLines();
FragmentedEditorHighlighter bh = fragmentedContent.getBeforeHighlighter();
if (bh != null) {
@@ -416,199 +405,9 @@
myNextDiff.registerCustomShortcutSet(myNextDiff.getShortcutSet(), myParent);
}
- private static class MyScrollingHelper {
- private JScrollBar myLeftScroll;
- private int myMaxColumnsLeft;
- private int myMaxColumnsRight;
- private List<ScrollingModel> myLeftModels;
- private List<ScrollingModel> myRightModels;
- private Editor myEditor;
- private boolean myInScrolling;
-
- private final List<Editor> myLeftEditors;
- private final List<Editor> myRightEditors;
-
- private boolean myByLeft;
- private int myIdxLeft;
- private int myIdxRight;
-
- private MyScrollingHelper() {
- myLeftScroll = new JScrollBar(JScrollBar.HORIZONTAL);
- myLeftScroll.setUI(ButtonlessScrollBarUI.createNormal());
-
- myLeftEditors = new ArrayList<Editor>();
- myRightEditors = new ArrayList<Editor>();
-
- myMaxColumnsLeft = 0;
- myMaxColumnsRight = 0;
- myLeftModels = new ArrayList<ScrollingModel>();
- myRightModels = new ArrayList<ScrollingModel>();
- }
-
- public void nextPanel(final BeforeAfter<ShiftedSimpleContent> diff, final DiffPanel diffPanel) {
- final Editor editor1 = ((DiffPanelImpl)diffPanel).getEditor1();
- myLeftModels.add(editor1.getScrollingModel());
- final Editor editor2 = ((DiffPanelImpl)diffPanel).getEditor2();
- myRightModels.add(editor2.getScrollingModel());
- if (myEditor == null) {
- myEditor = editor1;
- }
- myLeftEditors.add(editor1);
- myRightEditors.add(editor2);
- ((EditorEx) editor1).setHorizontalScrollbarVisible(false);
- ((EditorEx) editor1).setVerticalScrollbarVisible(false);
- ((EditorEx) editor1).getScrollPane().setWheelScrollingEnabled(false);
- ((EditorEx) editor2).setHorizontalScrollbarVisible(false);
- ((EditorEx) editor2).setVerticalScrollbarVisible(false);
- ((EditorEx) editor2).getScrollPane().setWheelScrollingEnabled(false);
- }
-
- private void recalculateMaxValues() {
- myIdxLeft = widestEditor(myLeftEditors);
- final Editor leftEditor = myLeftEditors.get(myIdxLeft);
- final int wholeWidth = leftEditor.getContentComponent().getWidth();
- final Rectangle va = leftEditor.getScrollingModel().getVisibleArea();
- final int visibleLeft = leftEditor.xyToVisualPosition(new Point(va.width, 0)).column;
-
- myMaxColumnsLeft = (int)(visibleLeft * ((double) wholeWidth / va.getWidth()));
-
- myIdxRight = widestEditor(myRightEditors);
- final Editor rightEditor = myRightEditors.get(myIdxRight);
- final int wholeWidthRight = rightEditor.getContentComponent().getWidth();
- final Rectangle vaRight = rightEditor.getScrollingModel().getVisibleArea();
- final int visibleRight = rightEditor.xyToVisualPosition(new Point(va.width, 0)).column;
-
- myMaxColumnsRight = (int)(visibleRight * ((double) wholeWidthRight / vaRight.getWidth()));
-
- myByLeft = ! (myMaxColumnsLeft <= visibleLeft);
- if (! myByLeft) {
- // check right editor
- if (myLeftScroll.getVisibleAmount() != visibleRight) {
- myLeftScroll.setVisibleAmount(visibleRight);
- }
- myLeftScroll.setMaximum(myMaxColumnsRight);
- } else {
- if (myLeftScroll.getVisibleAmount() != visibleLeft) {
- myLeftScroll.setVisibleAmount(visibleLeft);
- }
- myLeftScroll.setMaximum(myMaxColumnsLeft);
- }
- }
-
- private int widestEditor(final List<Editor> editors) {
- int maxWidth = 0;
- int idxMax = 0;
- for (int i = 0; i < editors.size(); i++) {
- Editor editor = editors.get(i);
- final int wholeWidth = editor.getContentComponent().getWidth();
- if (wholeWidth > maxWidth) {
- maxWidth = wholeWidth;
- idxMax = i;
- }
- }
- return idxMax;
- }
-
- public void afterPanelsAdded() {
- myLeftScroll.setMinimum(0);
- myLeftScroll.setMaximum(myMaxColumnsLeft);
- myLeftScroll.addAdjustmentListener(new AdjustmentListener() {
- @Override
- public void adjustmentValueChanged(AdjustmentEvent e) {
- myInScrolling = true;
-
- final int scrollPosCorrected = myLeftScroll.getValue() + 1;
- if (myByLeft) {
- scrollMain(myLeftScroll.getValue(), myLeftModels);
- scrollOther(scrollPosCorrected, myMaxColumnsLeft, myMaxColumnsRight, myRightModels);
- } else {
- scrollMain(myLeftScroll.getValue(), myRightModels);
- scrollOther(scrollPosCorrected, myMaxColumnsRight, myMaxColumnsLeft, myLeftModels);
- }
- myInScrolling = false;
- }
- });
- }
-
- private void scrollOther(int scrollPosCorrected, final int maxColumnsOur, int maxColumnsOther, final List<ScrollingModel> models) {
- int pos2;
- if (myLeftScroll.getValue() == 0) {
- pos2 = 0;
- } else if ((scrollPosCorrected + myLeftScroll.getModel().getExtent()) >= maxColumnsOur) {
- pos2 = maxColumnsOther + 1;
- } else {
- pos2 = (int) (scrollPosCorrected * (((double) maxColumnsOther)/ maxColumnsOur));
- }
- final int pointX2 = (int)myEditor.logicalPositionToXY(new LogicalPosition(0, pos2)).getX();
- for (ScrollingModel model : models) {
- model.scrollHorizontally(pointX2);
- }
- }
-
- private void scrollMain(int scrollPosCorrected, final List<ScrollingModel> models) {
- final int pointX = (int)myEditor.logicalPositionToXY(new LogicalPosition(0, scrollPosCorrected)).getX();
- for (ScrollingModel model : models) {
- model.scrollHorizontally(pointX);
- }
- }
-
- public void onEditorAreaChanged(VisibleAreaEvent e) {
- if (myInScrolling) return;
- recalculateMaxValues();
- }
-
- public JScrollBar getLeftScroll() {
- return myLeftScroll;
- }
- }
-
- private static class SplittersSynchronizer {
- private final List<Splitter> mySplitters;
- private final List<Splitter> myListening;
-
- private SplittersSynchronizer() {
- mySplitters = new ArrayList<Splitter>();
- myListening = new ArrayList<Splitter>();
- }
-
- public void addListening(final Splitter splitter) {
- myListening.add(splitter);
- }
-
- public void add(final Splitter splitter, final Editor editor) {
- editor.getScrollingModel().addVisibleAreaListener(new MyVisibleAreaListener(mySplitters.size()));
- mySplitters.add(splitter);
- }
-
- private void adjustTo(final int idx) {
- final Splitter target = mySplitters.get(idx);
- for (int i = 0; i < mySplitters.size(); i++) {
- final Splitter splitter = mySplitters.get(i);
- splitter.setProportion(target.getProportion());
- }
- for (Splitter splitter : myListening) {
- splitter.setProportion(target.getProportion());
- }
- }
-
- private class MyVisibleAreaListener implements VisibleAreaListener {
- private final int myIdx;
-
- private MyVisibleAreaListener(int idx) {
- myIdx = idx;
- }
-
- @Override
- public void visibleAreaChanged(VisibleAreaEvent e) {
- adjustTo(myIdx);
- }
- }
- }
-
private final static Icon ourIcon = PlatformIcons.CHECK_ICON;
private class PopupAction extends DumbAwareAction {
- private Component myParent;
private AnAction myUsual;
private AnAction myNumbered;
private final ChangesFragmentedDiffPanel.MyUseSoftWrapsAction mySoftWrapsAction;
@@ -618,7 +417,6 @@
myUsual = new AnAction("Top | Bottom", "", AllIcons.General.Mdot_empty) {
@Override
public void actionPerformed(AnActionEvent e) {
- boolean was = myConfiguration.SHORT_DIFF_HORIZONTALLY;
myConfiguration.SHORT_DIFF_HORIZONTALLY = false;
ensurePresentation();
}
@@ -632,7 +430,6 @@
myNumbered = new AnAction("Left | Right", "", AllIcons.General.Mdot_empty) {
@Override
public void actionPerformed(AnActionEvent e) {
- boolean was = myConfiguration.SHORT_DIFF_HORIZONTALLY;
myConfiguration.SHORT_DIFF_HORIZONTALLY = true;
ensurePresentation();
}
@@ -643,11 +440,7 @@
e.getPresentation().setIcon(myConfiguration.SHORT_DIFF_HORIZONTALLY ? AllIcons.General.Mdot : AllIcons.General.Mdot_empty);
}
};
- mySoftWrapsAction = new MyUseSoftWrapsAction(myConfiguration.SOFT_WRAPS_IN_SHORT_DIFF);
- }
-
- public void setParent(Component parent) {
- myParent = parent;
+ mySoftWrapsAction = new MyUseSoftWrapsAction();
}
@Override
@@ -753,11 +546,6 @@
boolean commonPartOk = leftPixels == 0 || startLp.line == lp.line;
return new BeforeAfter<Integer>(commonPartOk && startLp.softWrapLinesOnCurrentLogicalLine == 0 ? startLp.line : curStartLine,
commonPartOk && lp.softWrapLinesOnCurrentLogicalLine == 0 ? lp.line : cutEndLine);
- /*if (leftPixels == 0 || startLp.line == lp.line) {
- return new BeforeAfter<Integer>(startLp.line, lp.line);
- } else {
- return new BeforeAfter<Integer>(curStartLine, cutEndLine);
- }*/
}
private final static int[] ourMarks = {1,2,4,8,-1};
@@ -781,7 +569,7 @@
private class MyUseSoftWrapsAction extends ToggleAction implements DumbAware {
private final Icon myIcon;
- private MyUseSoftWrapsAction(boolean turned) {
+ private MyUseSoftWrapsAction() {
super("Use soft wraps", "", ourIcon);
myIcon = ourIcon;
}
@@ -877,11 +665,9 @@
public void actionPerformed(AnActionEvent e) {
int currentLogicalLineIdx = getCurrentLogicalLineIdx(false);
int nextLineIdx = currentLogicalLineIdx == 0 ? 0 : currentLogicalLineIdx - 1;
- int rightIndex = nextLineIdx >= myRightLines.size() ? (myRightLines.size() - 1) : nextLineIdx;
DiffPanelImpl panel = (DiffPanelImpl) getCurrentPanel();
panel.getSideView(FragmentSide.SIDE1).scrollToFirstDiff(myLeftLines.get(nextLineIdx));
- //panel.getSideView(FragmentSide.SIDE2).scrollToFirstDiff(myRightLines.get(rightIndex));
}
public void setEnabled(boolean enabled) {
@@ -906,11 +692,9 @@
public void actionPerformed(AnActionEvent e) {
int currentLogicalLineIdx = getCurrentLogicalLineIdx(true);
int nextLineIdx = currentLogicalLineIdx == (myLeftLines.size() - 1) ? currentLogicalLineIdx : currentLogicalLineIdx + 1;
- int rightIndex = nextLineIdx >= myRightLines.size() ? (myRightLines.size() - 1) : nextLineIdx;
DiffPanelImpl panel = (DiffPanelImpl) getCurrentPanel();
panel.getSideView(FragmentSide.SIDE1).scrollToFirstDiff(myLeftLines.get(nextLineIdx));
- //panel.getSideView(FragmentSide.SIDE2).scrollToFirstDiff(myRightLines.get(rightIndex));
}
public void setEnabled(boolean enabled) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java
index 7a7b6a9..0f79d57 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/LazyRefreshingSelfQueue.java
@@ -32,14 +32,23 @@
*
*/
@SomeQueue
+// TODO: Used only in RemoteRevisionsNumberCache
public class LazyRefreshingSelfQueue<T> {
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.vcs.changes.LazyRefreshingSelfQueue");
+ // provides update interval in milliseconds.
private final Getter<Long> myUpdateInterval;
- // head is old. tail is new
+ // structure:
+ // 1) pairs with First == null
+ // 2) pairs with First != null sorted by First ascending
+ // pair.First - time when T was last processed
+ // pair.Second - some item T
private final LinkedList<Pair<Long, T>> myQueue;
+ // Set of items that should be processed by myUpdater
private final Set<T> myInProgress;
+ // checks if updateStep should be really performed
private final Computable<Boolean> myShouldUpdateOldChecker;
+ // performs some actions on item T, for instance - updates some data for T in cache
private final Consumer<T> myUpdater;
private final Object myLock;
@@ -52,20 +61,14 @@
myLock = new Object();
}
+ // adds item that should be updated at next updateStep() call
public void addRequest(@NotNull final T t) {
synchronized (myLock) {
myQueue.addFirst(new Pair<Long,T>(null, t));
}
}
- public void addRequests(final Collection<T> values) {
- synchronized (myLock) {
- for (T value : values) {
- myQueue.addFirst(new Pair<Long,T>(null, value));
- }
- }
- }
-
+ // unschedules item from update at next updateStep() call
public void forceRemove(@NotNull final T t) {
synchronized (myLock) {
for (Iterator<Pair<Long, T>> iterator = myQueue.iterator(); iterator.hasNext();) {
@@ -80,11 +83,11 @@
// called by outside timer or something
public void updateStep() {
- final List<T> dirty = new LinkedList<T>();
-
final long startTime = System.currentTimeMillis() - myUpdateInterval.get();
boolean onlyAbsolute = true;
- // check if we have some old items at all - if not, we would not check if repository latest revision had changed and will save time
+ // TODO: Actually we could store items with pair.First == null in separate list.
+ // checks item that has smallest update time - i.e. was not updated by the most time
+ // if its update time greater than current - interval => we should not update any item with pair.First != null this time (as they are ordered)
synchronized (myLock) {
for (Pair<Long, T> pair : myQueue) {
if (pair.getFirst() != null) {
@@ -96,9 +99,10 @@
// do not ask under lock
final Boolean shouldUpdateOld = onlyAbsolute ? false : myShouldUpdateOldChecker.compute();
+ final List<T> dirty = new LinkedList<T>();
synchronized (myLock) {
- // get absolute
+ // adds all pairs with pair.First == null to dirty
while (! myQueue.isEmpty()) {
final Pair<Long, T> pair = myQueue.get(0);
if (pair.getFirst() == null) {
@@ -108,6 +112,7 @@
}
}
if (Boolean.TRUE.equals(shouldUpdateOld) && (! myQueue.isEmpty())) {
+ // adds all pairs with update time (pair.First) < current - interval to dirty
while (! myQueue.isEmpty()) {
final Pair<Long, T> pair = myQueue.get(0);
if (pair.getFirst() < startTime) {
@@ -126,6 +131,8 @@
for (T t : dirty) {
myUpdater.consume(t);
synchronized (myLock) {
+ // output value of remove() is tracked not to process items that were removed from myInProgress in forceRemove()
+ // TODO: Probably more clear logic should be implemented
if (myInProgress.remove(t)) {
myQueue.addLast(new Pair<Long,T>(System.currentTimeMillis(), t));
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java
index f9b5fda..30d8f5e 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsNumbersCache.java
@@ -88,11 +88,13 @@
public boolean updateStep() {
mySomethingChanged = false;
+ // copy under lock
final HashMap<VcsRoot, LazyRefreshingSelfQueue> copyMap;
synchronized (myLock) {
copyMap = new HashMap<VcsRoot, LazyRefreshingSelfQueue>(myRefreshingQueues);
}
+ // filter only items for vcs roots that support background operations
for (Iterator<Map.Entry<VcsRoot, LazyRefreshingSelfQueue>> iterator = copyMap.entrySet().iterator(); iterator.hasNext();) {
final Map.Entry<VcsRoot, LazyRefreshingSelfQueue> entry = iterator.next();
final VcsRoot key = entry.getKey();
@@ -103,6 +105,7 @@
}
}
LOG.debug("queues refresh started, queues: " + copyMap.size());
+ // refresh "up to date" info
for (LazyRefreshingSelfQueue queue : copyMap.values()) {
if (myProject.isDisposed()) throw new ProcessCanceledException();
queue.updateStep();
@@ -111,10 +114,12 @@
}
public void directoryMappingChanged() {
+ // copy myData under lock
HashSet<String> keys;
synchronized (myLock) {
keys = new HashSet<String>(myData.keySet());
}
+ // collect new vcs for scheduled files
final Map<String, Pair<VirtualFile, AbstractVcs>> vFiles = new HashMap<String, Pair<VirtualFile, AbstractVcs>>();
for (String key : keys) {
final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(key));
@@ -244,6 +249,7 @@
public void consume(String s) {
LOG.debug("update for: " + s);
//todo check canceled - check VCS's ready for asynchronous queries
+ // get last remote revision for file
final VirtualFile vf = myLfs.refreshAndFindFileByIoFile(new File(s));
final ItemLatestState state;
final DiffProvider diffProvider = myVcsRoot.getVcs().getDiffProvider();
@@ -256,6 +262,7 @@
final VcsRevisionNumber newNumber = (state == null) || state.isDefaultHead() ? UNKNOWN : state.getNumber();
final Pair<VcsRoot, VcsRevisionNumber> oldPair;
+ // update value in cache
synchronized (myLock) {
oldPair = myData.get(s);
myData.put(s, new Pair<VcsRoot, VcsRevisionNumber>(myVcsRoot, newNumber));
@@ -275,6 +282,8 @@
myVcsRoot = vcsRoot;
}
+ // Check if currently cached vcs root latest revision is less than latest vcs root revision
+ // => update should be performed in this case
public Boolean compute() {
final AbstractVcs vcs = myVcsRoot.getVcs();
// won't be called in parallel for same vcs -> just synchronized map is ok
@@ -282,6 +291,8 @@
LOG.debug("should update for: " + vcsName + " root: " + myVcsRoot.getPath().getPath());
final VcsRevisionNumber latestNew = vcs.getDiffProvider().getLatestCommittedRevision(myVcsRoot.getPath());
+ // TODO: Why vcsName is used as key and not myVcsRoot.getKey()???
+ // TODO: This seems to be invalid logic as we get latest revision for vcs root
final VcsRevisionNumber latestKnown = myLatestRevisionsMap.get(vcsName);
// not known
if (latestNew == null) return true;
@@ -307,8 +318,15 @@
return getRevisionState(change.getBeforeRevision()) && getRevisionState(change.getAfterRevision());
}
+ /**
+ * Returns {@code true} if passed revision is up to date, comparing to latest repository revision.
+ *
+ * @param revision
+ * @return
+ */
private boolean getRevisionState(final ContentRevision revision) {
if (revision != null) {
+ // TODO: Seems peg revision should also be tracked here.
final VcsRevisionNumber local = revision.getRevisionNumber();
final String path = revision.getFile().getIOFile().getAbsolutePath();
final VcsRevisionNumber remote = getNumber(path);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java
index adf940b..d5e1976 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/RemoteRevisionsStateCache.java
@@ -27,10 +27,14 @@
public class RemoteRevisionsStateCache implements ChangesOnServerTracker {
private final static long DISCRETE = 3600000;
- // true -> changed
+ // All files that were checked during cache update and were not invalidated.
+ // pair.First - if file is changed (true means changed)
+ // pair.Second - vcs root where file belongs to
private final Map<String, Pair<Boolean, VcsRoot>> myChanged;
+ // All files that needs to be checked during next cache update, grouped by vcs root
private final MultiMap<VcsRoot, String> myQueries;
+ // All vcs roots for which cache update was performed with update timestamp
private final Map<VcsRoot, Long> myTs;
private final Object myLock;
private final ProjectLevelVcsManager myVcsManager;
@@ -104,6 +108,7 @@
myVcsConfiguration.CHANGED_ON_SERVER_INTERVAL * 60000 : DISCRETE);
synchronized (myLock) {
+ // just copies myQueries MultiMap to dirty MultiMap
for (VcsRoot root : myQueries.keySet()) {
final Collection<String> collection = myQueries.get(root);
for (String s : collection) {
@@ -112,15 +117,23 @@
}
myQueries.clear();
+ // collect roots for which cache update should be performed (by timestamp)
final Set<VcsRoot> roots = new HashSet<VcsRoot>();
for (Map.Entry<VcsRoot, Long> entry : myTs.entrySet()) {
+ // ignore timestamp, as still remote changes checking is required
+ // TODO: why not to add in roots anyway??? - as dirty is still checked when adding myChanged files.
if (! dirty.get(entry.getKey()).isEmpty()) continue;
+ // update only if timeout expired
final Long ts = entry.getValue();
if ((ts == null) || (oldPoint > ts)) {
roots.add(entry.getKey());
}
}
+
+ // Add dirty files from those vcs roots, that
+ // - needs to be update by timestamp criteria
+ // - that already contain files for update through manually added requests
for (Map.Entry<String, Pair<Boolean, VcsRoot>> entry : myChanged.entrySet()) {
final VcsRoot vcsRoot = entry.getValue().getSecond();
if ((! dirty.get(vcsRoot).isEmpty()) || roots.contains(vcsRoot)) {
@@ -142,6 +155,8 @@
final Collection<String> paths = dirty.get(vcsRoot);
final Collection<String> remotelyChanged = provider.getRemotelyChanged(vcsRoot.getPath(), paths);
for (String path : paths) {
+ // TODO: Contains invoked for each file - better to use Set (implementations just use List)
+ // TODO: Why to store boolean for changed or not - why not just remove such values from myChanged???
results.put(path, new Pair<Boolean, VcsRoot>(remotelyChanged.contains(path), vcsRoot));
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsAnnotationLocalChangesListenerImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsAnnotationLocalChangesListenerImpl.java
index 5b7dc56..e836ca1 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsAnnotationLocalChangesListenerImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsAnnotationLocalChangesListenerImpl.java
@@ -64,12 +64,7 @@
myDirtyPaths = new HashSet<String>();
myDirtyChanges = new HashMap<String, VcsRevisionNumber>();
myDirtyFiles = new HashSet<VirtualFile>();
- myFileAnnotationMap = new MultiMap<VirtualFile, FileAnnotation>() {
- @Override
- protected Collection<FileAnnotation> createCollection() {
- return new HashSet<FileAnnotation>(1);
- }
- };
+ myFileAnnotationMap = MultiMap.createSet();
myVcsManager = vcsManager;
myVcsKeySet = new HashSet<VcsKey>();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
index f3c0bab..eb44d59 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VcsDirtyScopeImpl.java
@@ -205,12 +205,7 @@
final HashSet<FilePath> newFiles = new HashSet<FilePath>(files);
newFiles.removeAll(dirs); // if the same dir is added recursively and not recursively, prefer recursive mark
- final MultiMap<VirtualFile, FileOrDir> perRoot = new MultiMap<VirtualFile, FileOrDir>() {
- @Override
- protected Collection<FileOrDir> createCollection() {
- return new THashSet<FileOrDir>();
- }
- };
+ final MultiMap<VirtualFile, FileOrDir> perRoot = MultiMap.createSet();
for (Map.Entry<VirtualFile, THashSet<FilePath>> entry : myDirtyDirectoriesRecursively.entrySet()) {
newFiles.removeAll(entry.getValue()); // if the same dir is added recursively and not recursively, prefer recursive mark
for (FilePath path : entry.getValue()) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VetoSavingCommittingDocumentsAdapter.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VetoSavingCommittingDocumentsAdapter.java
index 449b0e0..8582967 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VetoSavingCommittingDocumentsAdapter.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/VetoSavingCommittingDocumentsAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -103,6 +103,6 @@
Project project = documentsToWarn.values().iterator().next();
int rc = Messages.showOkCancelDialog(project, messageBuilder.toString(), "Save Files During Commit", "Save Now", "Postpone Save",
Messages.getQuestionIcon());
- return rc == 0;
+ return rc == Messages.OK;
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/BrowseChangesAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/BrowseChangesAction.java
index 6f79728..87bb5a3 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/BrowseChangesAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/BrowseChangesAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,9 +20,8 @@
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.project.Project;
import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.actions.VcsContextFactory;
@@ -54,10 +53,10 @@
VcsBundle.message("browse.changes.show.all.button"),
CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon());
- if (rc == 2) {
+ if (rc == Messages.CANCEL) {
return;
}
- if (rc == 0) {
+ if (rc == Messages.YES) {
maxCount = 50;
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java
index 9be4537..f2678bd 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/ChangeDiffRequestPresentable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package com.intellij.openapi.vcs.changes.actions;
import com.intellij.CommonBundle;
+import com.intellij.diff.FileAwareSimpleContent;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.diff.DiffContent;
@@ -150,8 +151,9 @@
final VirtualFile vFile = current.getVirtualFile();
return vFile != null ? new FileContent(myProject, vFile) : new SimpleContent("");
}
+ FilePath filePath = revision.getFile();
if (revision instanceof BinaryContentRevision) {
- final String name = revision.getFile().getName();
+ final String name = filePath.getName();
try {
return FileContent.createFromTempFile(myProject, name, name, ((BinaryContentRevision)revision).getBinaryContent());
}
@@ -188,8 +190,8 @@
}
SimpleContent content = revisionContent == null
? new SimpleContent("")
- : new SimpleContent(revisionContent, revision.getFile().getFileType());
- VirtualFile vFile = revision.getFile().getVirtualFile();
+ : new FileAwareSimpleContent(myProject, filePath, revisionContent, filePath.getFileType());
+ VirtualFile vFile = filePath.getVirtualFile();
if (vFile != null) {
content.setCharset(vFile.getCharset());
content.setBOM(vFile.getBOM());
@@ -257,7 +259,7 @@
VcsBundle.message("diff.unknown.file.type.associate"),
CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.OK) {
FileType fileType = FileTypeChooser.associateFileType(file.getName());
return fileType != null && !fileType.isBinary();
} else {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RemoveChangeListAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RemoveChangeListAction.java
index 5450953..17b2e7d 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RemoveChangeListAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RemoveChangeListAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -26,10 +26,8 @@
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.project.DumbAware;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.VcsBundle;
import com.intellij.openapi.vcs.VcsDataKeys;
@@ -69,7 +67,6 @@
if (! canRemoveChangeLists(project, lists)) {
return;
}
- int rc;
for(ChangeList list: lists) {
if (((LocalChangeList) list).isDefault()) {
@@ -78,9 +75,10 @@
}
}
+ int rc;
if (lists.length == 1) {
final LocalChangeList list = (LocalChangeList)lists[0];
- rc = list.getChanges().size() == 0 ? DialogWrapper.OK_EXIT_CODE :
+ rc = list.getChanges().size() == 0 ? Messages.YES :
Messages.showYesNoDialog(project,
VcsBundle.message("changes.removechangelist.warning.text", list.getName()),
VcsBundle.message("changes.removechangelist.warning.title"),
@@ -91,13 +89,13 @@
for (ChangeList list : lists) {
notEmpty |= (list.getChanges().size() > 0);
}
- rc = (! notEmpty) ? DialogWrapper.OK_EXIT_CODE : Messages.showYesNoDialog(project,
+ rc = (! notEmpty) ? Messages.YES : Messages.showYesNoDialog(project,
VcsBundle.message("changes.removechangelist.multiple.warning.text", lists.length),
VcsBundle.message("changes.removechangelist.warning.title"),
Messages.getQuestionIcon());
}
- if (rc == DialogWrapper.OK_EXIT_CODE) {
+ if (rc == Messages.YES) {
for(ChangeList list: lists) {
ChangeListManager.getInstance(project).removeChangeList(list.getName());
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java
index 83e8e9e..8686562 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/actions/RollbackAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -26,13 +26,13 @@
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.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.changes.Change;
@@ -43,6 +43,8 @@
import com.intellij.openapi.vcs.changes.ui.RollbackChangesDialog;
import com.intellij.openapi.vcs.changes.ui.RollbackProgressModifier;
import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.util.containers.ContainerUtil;
@@ -81,8 +83,9 @@
final VirtualFile[] files = e.getData(CommonDataKeys.VIRTUAL_FILE_ARRAY);
if (files != null) {
ChangeListManager clManager = ChangeListManager.getInstance(project);
+ Set<VirtualFile> modifiedWithoutEditing = ContainerUtil.newHashSet(clManager.getModifiedWithoutEditing());
for (VirtualFile file : files) {
- if (!clManager.getChangesIn(file).isEmpty()) {
+ if (!clManager.getChangesIn(file).isEmpty() || modifiedWithoutEditing.contains(file)) {
return true;
}
}
@@ -108,13 +111,14 @@
new RollbackDeletionAction().actionPerformed(e);
}
+ List<Change> changes = getChanges(project, e);
+
LinkedHashSet<VirtualFile> modifiedWithoutEditing = getModifiedWithoutEditing(e, project);
if (modifiedWithoutEditing != null && !modifiedWithoutEditing.isEmpty()) {
hasChanges = true;
rollbackModifiedWithoutEditing(project, modifiedWithoutEditing);
}
- List<Change> changes = getChanges(project, e);
if (changes != null) {
if (modifiedWithoutEditing != null) {
for (Iterator<Change> iterator = changes.iterator(); iterator.hasNext(); ) {
@@ -207,7 +211,7 @@
: VcsBundle.message("rollback.modified.without.editing.confirm.multiple",
operationName, modifiedWithoutEditing.size());
int rc = showYesNoDialog(project, message, VcsBundle.message("changes.action.rollback.title", operationName), getQuestionIcon());
- if (rc != 0) {
+ if (rc != Messages.YES) {
return;
}
final List<VcsException> exceptions = new ArrayList<VcsException>();
@@ -242,6 +246,9 @@
AbstractVcsHelper.getInstance(project).showErrors(exceptions, VcsBundle.message("rollback.modified.without.checkout.error.tab",
operationName));
}
+
+ VfsUtil.markDirty(true, false, VfsUtilCore.toVirtualFileArray(modifiedWithoutEditing));
+
VirtualFileManager.getInstance().asyncRefresh(new Runnable() {
public void run() {
for (VirtualFile virtualFile : modifiedWithoutEditing) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java
index 8c7a324..b6e7f8b 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/ChangeListDetailsAction.java
@@ -74,13 +74,7 @@
detailsBuilder.append("<br>");
if (provider != null) {
- final CommittedChangeList originalChangeList;
- if (changeList instanceof ReceivedChangeList) {
- originalChangeList = ((ReceivedChangeList) changeList).getBaseList();
- }
- else {
- originalChangeList = changeList;
- }
+ final CommittedChangeList originalChangeList = ReceivedChangeList.unwrap(changeList);
for(ChangeListColumn column: provider.getColumns()) {
if (ChangeListColumn.isCustom(column)) {
String value = column.getValue(originalChangeList).toString();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangeListRenderer.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangeListRenderer.java
index cdb2769..0343651 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangeListRenderer.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangeListRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -27,6 +27,7 @@
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.text.DateFormatUtil;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.plaf.TreeUI;
@@ -182,6 +183,7 @@
return description.substring(0, description.length()-1);
}
+ @NotNull
public Dimension getPreferredSize() {
return new Dimension(2000, super.getPreferredSize().height);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java
index 9155a1a..4c13ef0 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/CommittedChangesCache.java
@@ -688,14 +688,13 @@
if (lists.size() == 1) {
return lists.get(0);
}
- final CommittedChangeList victim = lists.get(0) instanceof ReceivedChangeList ? (((ReceivedChangeList) lists.get(0)).getBaseList()) :
- lists.get(0);
+ final CommittedChangeList victim = ReceivedChangeList.unwrap(lists.get(0));
final ReceivedChangeList result = new ReceivedChangeList(victim);
result.setForcePartial(false);
final Set<Change> baseChanges = new HashSet<Change>();
for (CommittedChangeList list : lists) {
- baseChanges.addAll(list instanceof ReceivedChangeList ? ((ReceivedChangeList) list).getBaseList().getChanges() : list.getChanges());
+ baseChanges.addAll(ReceivedChangeList.unwrap(list).getChanges());
final Collection<Change> changes = list.getChanges();
for (Change change : changes) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/GetCommittedChangelistAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/GetCommittedChangelistAction.java
index 3fb2ecb..8c20de2 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/GetCommittedChangelistAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/committed/GetCommittedChangelistAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -63,7 +63,7 @@
int rc = Messages.showOkCancelDialog(
context.getProject(), VcsBundle.message("get.committed.changes.intersecting.prompt", intersectingChanges.size(), selectedChangeLists.size()),
VcsBundle.message("get.committed.changes.title"), Messages.getQuestionIcon());
- if (rc != 0) return;
+ if (rc != Messages.OK) return;
}
super.actionPerformed(context);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictFileStatusProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictFileStatusProvider.java
index d19953e..45cfff7 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictFileStatusProvider.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/conflicts/ChangelistConflictFileStatusProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -24,6 +24,7 @@
import com.intellij.openapi.vcs.impl.FileStatusProvider;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ThreeState;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
@@ -48,8 +49,9 @@
myConflictTracker = changeListManager.getConflictTracker();
}
+ @Override
@Nullable
- public FileStatus getFileStatus(VirtualFile virtualFile) {
+ public FileStatus getFileStatus(@NotNull VirtualFile virtualFile) {
ChangelistConflictTracker.Options options = myConflictTracker.getOptions();
if (!options.TRACKING_ENABLED) {
return null;
@@ -69,12 +71,14 @@
return null;
}
- public void refreshFileStatusFromDocument(VirtualFile file, Document doc) {
+ @Override
+ public void refreshFileStatusFromDocument(@NotNull VirtualFile virtualFile, @NotNull Document doc) {
}
+ @NotNull
@Override
- public ThreeState getNotChangedDirectoryParentingStatus(VirtualFile vf) {
+ public ThreeState getNotChangedDirectoryParentingStatus(@NotNull VirtualFile virtualFile) {
throw new UnsupportedOperationException("Shouldn't be called");
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java
index de7a779..0914434 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/dbCommitted/KnownRepositoryLocations.java
@@ -37,12 +37,7 @@
private final Map<String, Long> myAuthors;
public KnownRepositoryLocations() {
- myMap = new MultiMap<String, String>() {
- @Override
- protected Collection<String> createCollection() {
- return new HashSet<String>();
- }
- };
+ myMap = MultiMap.createSet();
myLocations = new HashMap<Pair<String, String>, Long>();
myLastRevision = new HashMap<Long, RevisionId>();
myFirstRevision = new HashMap<Long, RevisionId>();
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java
index 9df410d..f86be35 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/AbstractBaseTagMouseListener.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,16 +16,13 @@
package com.intellij.openapi.vcs.changes.issueLinks;
import com.intellij.ide.BrowserUtil;
-import com.intellij.ui.ClickListener;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
-import java.awt.*;
import java.awt.event.MouseEvent;
-import java.awt.event.MouseMotionListener;
-public abstract class AbstractBaseTagMouseListener extends ClickListener implements MouseMotionListener {
+public abstract class AbstractBaseTagMouseListener extends LinkMouseListenerBase {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (e.getButton() == 1 && !e.isPopupTrigger()) {
Object tag = getTagAt(e);
if (tag instanceof Runnable) {
@@ -33,34 +30,11 @@
return true;
}
- if ((tag != null) && (! Object.class.getName().equals(tag.getClass().getName()))) {
- BrowserUtil.launchBrowser(tag.toString());
+ if (tag != null && !Object.class.getName().equals(tag.getClass().getName())) {
+ BrowserUtil.browse(tag.toString());
return true;
}
}
return false;
}
-
- @Nullable
- public abstract Object getTagAt(final MouseEvent e);
-
- public void mouseDragged(MouseEvent e) {
- }
-
- public void mouseMoved(MouseEvent e) {
- Component table = (Component) e.getSource();
- Object tag = getTagAt(e);
- if (tag != null) {
- table.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
- }
- else {
- table.setCursor(Cursor.getDefaultCursor());
- }
- }
-
- @Override
- public void installOn(Component c) {
- super.installOn(c);
- c.addMouseMotionListener(this);
- }
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TableLinkMouseListener.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TableLinkMouseListener.java
index 4c88eb7..7646bef 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TableLinkMouseListener.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/issueLinks/TableLinkMouseListener.java
@@ -18,6 +18,7 @@
import com.intellij.ui.ColoredTableCellRenderer;
import com.intellij.ui.dualView.DualView;
import com.intellij.ui.dualView.TreeTableView;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -29,10 +30,11 @@
* @author yole
*/
public class TableLinkMouseListener extends AbstractBaseTagMouseListener {
+ @Override
@Nullable
- public Object getTagAt(final MouseEvent e) {
+ public Object getTagAt(@NotNull final MouseEvent e) {
// TODO[yole]: don't update renderer on every event, like it's done in TreeLinkMouseListener
- Object tag = null;
+ Object tag;
JTable table = (JTable)e.getSource();
int row = table.rowAtPoint(e.getPoint());
int column = table.columnAtPoint(e.getPoint());
@@ -57,13 +59,9 @@
return null;
}
- private Object forColoredRenderer(MouseEvent e, JTable table, int row, int column, ColoredTableCellRenderer renderer) {
+ private static Object forColoredRenderer(MouseEvent e, JTable table, int row, int column, ColoredTableCellRenderer renderer) {
renderer.getTableCellRendererComponent(table, table.getValueAt(row, column), false, false, row, column);
final Rectangle rc = table.getCellRect(row, column, false);
- int index = renderer.findFragmentAt(e.getPoint().x - rc.x);
- if (index >= 0) {
- return renderer.getFragmentTag(index);
- }
- return null;
+ return renderer.getFragmentTagAt(e.getX() - rc.x);
}
}
\ No newline at end of file
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java
index 463b5b0..308281e 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/patch/AutoMatchStrategy.java
@@ -20,10 +20,11 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.MultiMapBasedOnSet;
import org.jetbrains.annotations.Nullable;
-import java.util.*;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
abstract class AutoMatchStrategy {
protected final VirtualFile myBaseDir;
@@ -33,7 +34,7 @@
AutoMatchStrategy(final VirtualFile baseDir) {
myBaseDir = baseDir;
myResult = new LinkedList<FilePatchInProgress>();
- myFolderDecisions = new MultiMapBasedOnSet<String, VirtualFile>();
+ myFolderDecisions = MultiMap.createSet();
}
public abstract void acceptPatch(TextFilePatch patch, final Collection<VirtualFile> foundByName);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DeleteAlreadyUnshelvedAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DeleteAlreadyUnshelvedAction.java
index 34f14e5..441920c 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DeleteAlreadyUnshelvedAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/DeleteAlreadyUnshelvedAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,10 +18,8 @@
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.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.VcsBundle;
@@ -53,7 +51,7 @@
final int result = Messages
.showYesNoDialog(project, VcsBundle.message("delete.all.already.unshelved.confirmation"), myText,
Messages.getWarningIcon());
- if (DialogWrapper.OK_EXIT_CODE == result) {
+ if (Messages.YES == result) {
final ShelveChangesManager manager = ShelveChangesManager.getInstance(project);
manager.clearRecycled();
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ImportIntoShelfAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ImportIntoShelfAction.java
index 9cc205b..7e62df6 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ImportIntoShelfAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ImportIntoShelfAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,13 +17,11 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.AbstractVcsHelper;
@@ -77,7 +75,7 @@
(patchTypeFiles.size() + " patch files.")) +
"\nContinue with import?";
final int toImport = Messages.showYesNoDialog(project, message, "Import Patches", Messages.getQuestionIcon());
- if (DialogWrapper.CANCEL_EXIT_CODE == toImport) return;
+ if (Messages.NO == toImport) return;
}
pm.runProcessWithProgressSynchronously(new Runnable() {
@Override
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java
index 696ad9e..258fd99 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/shelf/ShelvedChangesViewManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -495,7 +495,7 @@
? VcsBundle.message("shelve.changes.delete.confirm", shelvedChangeLists.get(0).DESCRIPTION)
: VcsBundle.message("shelve.changes.delete.multiple.confirm", shelvedChangeLists.size());
int rc = Messages.showOkCancelDialog(myProject, message, VcsBundle.message("shelvedChanges.delete.title"), CommonBundle.message("button.delete"), CommonBundle.getCancelButtonText(), Messages.getWarningIcon());
- if (rc != 0) return;
+ if (rc != Messages.OK) return;
for(ShelvedChangeList changeList: shelvedChangeLists) {
ShelveChangesManager.getInstance(myProject).deleteChangeList(changeList);
}
@@ -536,7 +536,7 @@
final String message = VcsBundle.message("shelve.changes.delete.files.from.list", (changes == null ? 0 : changes.size()) +
(binaryFiles == null ? 0 : binaryFiles.size()));
int rc = Messages.showOkCancelDialog(myProject, message, VcsBundle.message("shelve.changes.delete.files.from.list.title"), Messages.getWarningIcon());
- if (rc != 0) return;
+ if (rc != Messages.OK) return;
final ArrayList<ShelvedBinaryFile> oldBinaries = new ArrayList<ShelvedBinaryFile>(list.getBinaryFiles());
final ArrayList<ShelvedChange> oldChanges = new ArrayList<ShelvedChange>(list.getChanges(project));
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java
index 8df7b62..af9f982 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/ChangesTreeList.java
@@ -189,7 +189,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
final int idx = myList.locationToIndex(e.getPoint());
if (idx >= 0) {
final Rectangle baseRect = myList.getCellBounds(idx, idx);
@@ -544,7 +544,7 @@
//noinspection unchecked
List<T> list = getSelectedObjects((ChangesBrowserNode)path.getLastPathComponent());
for (T object : list) {
- if (!checkSet.add(object.hashCode()) || !changes.contains(object)) {
+ if (checkSet.add(object.hashCode()) || !changes.contains(object)) {
changes.add(object);
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java
index 71c0c8f..4bd75bc 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitChangeListDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -836,7 +836,7 @@
int requestForCheckin = Messages.showYesNoDialog(VcsBundle.message("confirmation.text.check.in.with.empty.comment"),
VcsBundle.message("confirmation.title.check.in.with.empty.comment"),
Messages.getWarningIcon());
- return requestForCheckin == OK_EXIT_CODE;
+ return requestForCheckin == Messages.YES;
}
else {
return true;
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java
index 1735ba5..2e34d78 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/changes/ui/CommitHelper.java
@@ -188,9 +188,9 @@
int failed = changesFailedToCommit.size();
int committed = myIncludedChanges.size() - failed;
- String text = committed + " " + StringUtil.pluralize("change", committed) + " committed";
+ String text = committed + " " + StringUtil.pluralize("file", committed) + " committed";
if (failed > 0) {
- text += ", " + failed + " " + StringUtil.pluralize("change", failed) + " failed to commit";
+ text += ", " + failed + " " + StringUtil.pluralize("file", failed) + " failed to commit";
}
StringBuilder content = new StringBuilder(StringUtil.isEmpty(myCommitMessage) ? text : text + ": " + escape(myCommitMessage));
for (String s : myFeedback) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java
index 6a2ab14..926e5cc 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/CheckoutActionGroup.java
@@ -15,40 +15,28 @@
*/
package com.intellij.openapi.vcs.checkout;
-import com.intellij.openapi.actionSystem.ActionGroup;
+import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.extensions.Extensions;
-import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.actionSystem.ComputableActionGroup;
import com.intellij.openapi.vcs.CheckoutProvider;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
-public class CheckoutActionGroup extends ActionGroup implements DumbAware {
-
- private AnAction[] myChildren;
-
- public void update(AnActionEvent e) {
- super.update(e);
- final CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME);
- if (providers.length == 0) {
- e.getPresentation().setVisible(false);
- }
- }
-
+public class CheckoutActionGroup extends ComputableActionGroup.Simple {
@NotNull
- public AnAction[] getChildren(@Nullable AnActionEvent e) {
- if (myChildren == null) {
- final CheckoutProvider[] providers = Extensions.getExtensions(CheckoutProvider.EXTENSION_POINT_NAME);
- Arrays.sort(providers, new CheckoutProvider.CheckoutProviderComparator());
- myChildren = new AnAction[providers.length];
- for (int i = 0; i < providers.length; i++) {
- CheckoutProvider provider = providers[i];
- myChildren[i] = new CheckoutAction(provider);
- }
+ @Override
+ protected AnAction[] computeChildren(@NotNull ActionManager manager) {
+ CheckoutProvider[] providers = CheckoutProvider.EXTENSION_POINT_NAME.getExtensions();
+ if (providers.length == 0) {
+ return EMPTY_ARRAY;
}
- return myChildren;
+
+ Arrays.sort(providers, new CheckoutProvider.CheckoutProviderComparator());
+ AnAction[] children = new AnAction[providers.length];
+ for (int i = 0; i < providers.length; i++) {
+ children[i] = new CheckoutAction(providers[i]);
+ }
+ return children;
}
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/PlatformProjectCheckoutListener.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/PlatformProjectCheckoutListener.java
index a117fae..21b0a94 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/PlatformProjectCheckoutListener.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/checkout/PlatformProjectCheckoutListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -33,7 +33,7 @@
if (dir != null) {
int rc = Messages.showYesNoDialog(project, VcsBundle.message("checkout.open.directory.prompt", directory.getAbsolutePath()),
VcsBundle.message("checkout.title"), Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
PlatformProjectOpenProcessor.getInstance().doOpenProject(dir, null, false);
return true;
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/IssueNavigationConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/IssueNavigationConfigurationPanel.java
index d51c013..a606a9a 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/IssueNavigationConfigurationPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/IssueNavigationConfigurationPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -44,7 +44,7 @@
* @author yole
*/
public class IssueNavigationConfigurationPanel extends JPanel implements SearchableConfigurable, Configurable.NoScroll {
- private JBTable myLinkTable;
+ private final JBTable myLinkTable;
private final Project myProject;
private List<IssueNavigationLink> myLinks;
private ListTableModel<IssueNavigationLink> myModel;
@@ -86,7 +86,7 @@
@Override
public void run(AnActionButton button) {
if (Messages.showOkCancelDialog(myProject, VcsBundle.message("issue.link.delete.prompt"),
- VcsBundle.message("issue.link.delete.title"), Messages.getQuestionIcon()) == 0) {
+ VcsBundle.message("issue.link.delete.title"), Messages.getQuestionIcon()) == Messages.OK) {
int selRow = myLinkTable.getSelectedRow();
myLinks.remove(selRow);
myModel.fireTableDataChanged();
@@ -101,7 +101,7 @@
}).setEditAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
- IssueNavigationLink link = (IssueNavigationLink) myModel.getItem(myLinkTable.getSelectedRow());
+ IssueNavigationLink link = myModel.getItem(myLinkTable.getSelectedRow());
IssueLinkConfigurationDialog dlg = new IssueLinkConfigurationDialog(myProject);
dlg.setTitle(VcsBundle.message("issue.link.edit.title"));
dlg.setLink(link);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java
index 2b36d77..aad3ad1 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/configurable/VcsDirectoryConfigurationPanel.java
@@ -73,7 +73,7 @@
private final MyDirectoryRenderer myDirectoryRenderer;
private final ColumnInfo<VcsDirectoryMapping, VcsDirectoryMapping> DIRECTORY;
- private JCheckBox myBaseRevisionTexts;
+ private final JCheckBox myBaseRevisionTexts;
private ListTableModel<VcsDirectoryMapping> myModel;
private final Map<String, VcsDescriptor> myAllVcss;
private VcsContentAnnotationConfigurable myRecentlyChangedConfigurable;
@@ -135,22 +135,27 @@
private final ColumnInfo<VcsDirectoryMapping, String> VCS_SETTING =
new ColumnInfo<VcsDirectoryMapping, String>(VcsBundle.message("column.name.configure.vcses.vcs")) {
+ @Override
public String valueOf(final VcsDirectoryMapping object) {
return object.getVcs();
}
+ @Override
public boolean isCellEditable(final VcsDirectoryMapping o) {
return true;
}
+ @Override
public void setValue(final VcsDirectoryMapping o, final String aValue) {
Collection<AbstractVcs> activeVcses = getActiveVcses();
o.setVcs(aValue);
checkNotifyListeners(activeVcses);
}
+ @Override
public TableCellRenderer getRenderer(final VcsDirectoryMapping p0) {
return new ColoredTableCellRenderer() {
+ @Override
protected void customizeCellRenderer(JTable table, Object value, boolean selected, boolean hasFocus, int row, int column) {
final String vcsName = p0.getVcs();
String text;
@@ -174,11 +179,13 @@
@Override
public TableCellEditor getEditor(final VcsDirectoryMapping o) {
return new AbstractTableCellEditor() {
+ @Override
public Object getCellEditorValue() {
final VcsDescriptor selectedVcs = (VcsDescriptor)myVcsComboBox.getComboBox().getSelectedItem();
return ((selectedVcs == null) || selectedVcs.isNone()) ? "" : selectedVcs.getName();
}
+ @Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
String vcsName = (String)value;
myVcsComboBox.getComboBox().setSelectedItem(myAllVcss.get(vcsName));
@@ -232,6 +239,7 @@
myDirectoryRenderer = new MyDirectoryRenderer(myProject);
DIRECTORY = new ColumnInfo<VcsDirectoryMapping, VcsDirectoryMapping>(VcsBundle.message("column.info.configure.vcses.directory")) {
+ @Override
public VcsDirectoryMapping valueOf(final VcsDirectoryMapping mapping) {
return mapping;
}
@@ -246,6 +254,7 @@
final JComboBox comboBox = myVcsComboBox.getComboBox();
comboBox.setModel(buildVcsWrappersModel(myProject));
comboBox.addItemListener(new ItemListener() {
+ @Override
public void itemStateChanged(final ItemEvent e) {
if (myDirectoryMappingTable.isEditing()) {
myDirectoryMappingTable.stopEditing();
@@ -253,6 +262,7 @@
}
});
myVcsComboBox.addActionListener(new ActionListener() {
+ @Override
public void actionPerformed(ActionEvent e) {
final VcsDescriptor vcsWrapper = ((VcsDescriptor)comboBox.getSelectedItem());
new VcsConfigurationsDialog(project, comboBox, vcsWrapper).show();
@@ -500,10 +510,12 @@
return myShowChangedRecursively;
}
+ @Override
public void reset() {
initializeModel();
}
+ @Override
public void apply() throws ConfigurationException {
myVcsManager.setDirectoryMappings(myModel.getItems());
myRecentlyChangedConfigurable.apply();
@@ -516,6 +528,7 @@
initializeModel();
}
+ @Override
public boolean isModified() {
if (myRecentlyChangedConfigurable.isModified()) return true;
if (myLimitHistory.isModified()) return true;
@@ -560,19 +573,23 @@
return vcses;
}
+ @Override
@Nls
public String getDisplayName() {
return "Mappings";
}
+ @Override
public String getHelpTopic() {
return null;
}
+ @Override
public JComponent createComponent() {
return this;
}
+ @Override
public void disposeUIResources() {
myLimitHistory.disposeUIResources();
myScopeFilterConfig.disposeUIResources();
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 3fba542..7711dd3 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
@@ -186,9 +186,9 @@
return CharsetToolkit.bytesToString(bytes, e.getDefaultCharset());
}
- private static DiffContent createContent(Project project, byte[] content1, VcsFileRevision revision, Document doc, Charset charset, FileType fileType, String filePath) {
+ 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); }
- return new BinaryContent(content1, charset, fileType, filePath);
+ return new BinaryContent(project, content1, charset, fileType, filePath);
}
private static boolean isCurrent(VcsFileRevision revision) {
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
index beeb057..a63bbdb 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/DefaultFileIndexFacade.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.FileIndexFacade;
+import com.intellij.openapi.util.ModificationTracker;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.ProjectBaseDirectory;
@@ -73,6 +74,12 @@
return VfsUtil.isAncestor(baseDir, childDir, false);
}
+ @NotNull
+ @Override
+ public ModificationTracker getRootModificationTracker() {
+ return ModificationTracker.NEVER_CHANGED;
+ }
+
private VirtualFile getBaseDir() {
return ProjectBaseDirectory.getInstance(myProject).getBaseDir(myBaseDir);
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsFileStatusProvider.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsFileStatusProvider.java
index 18a1513..f84ac73 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsFileStatusProvider.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/impl/VcsFileStatusProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,6 +29,7 @@
import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ThreeState;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
@@ -60,18 +61,22 @@
myFileStatusManager.setFileStatusProvider(this);
changeListManager.addChangeListListener(new ChangeListAdapter() {
+ @Override
public void changeListAdded(ChangeList list) {
fileStatusesChanged();
}
+ @Override
public void changeListRemoved(ChangeList list) {
fileStatusesChanged();
}
+ @Override
public void changeListChanged(ChangeList list) {
fileStatusesChanged();
}
+ @Override
public void changeListUpdateDone() {
if (myHaveEmptyContentRevisions) {
myHaveEmptyContentRevisions = false;
@@ -89,7 +94,9 @@
myFileStatusManager.fileStatusesChanged();
}
- public FileStatus getFileStatus(final VirtualFile virtualFile) {
+ @Override
+ @NotNull
+ public FileStatus getFileStatus(@NotNull final VirtualFile virtualFile) {
final AbstractVcs vcs = myVcsManager.getVcsFor(virtualFile);
if (vcs == null) {
return FileStatusManagerImpl.getDefaultStatus(virtualFile);
@@ -110,33 +117,35 @@
return FileDocumentManager.getInstance().isFileModified(virtualFile);
}
- public void refreshFileStatusFromDocument(final VirtualFile file, final Document doc) {
+ @Override
+ public void refreshFileStatusFromDocument(@NotNull final VirtualFile virtualFile, @NotNull final Document doc) {
if (LOG.isDebugEnabled()) {
- LOG.debug("refreshFileStatusFromDocument: file.getModificationStamp()=" + file.getModificationStamp() + ", document.getModificationStamp()=" + doc.getModificationStamp());
+ LOG.debug("refreshFileStatusFromDocument: file.getModificationStamp()=" + virtualFile.getModificationStamp() + ", document.getModificationStamp()=" + doc.getModificationStamp());
}
- FileStatus cachedStatus = myFileStatusManager.getCachedStatus(file);
- if (cachedStatus == null || cachedStatus == FileStatus.NOT_CHANGED || !isDocumentModified(file)) {
- final AbstractVcs vcs = myVcsManager.getVcsFor(file);
+ FileStatus cachedStatus = myFileStatusManager.getCachedStatus(virtualFile);
+ if (cachedStatus == null || cachedStatus == FileStatus.NOT_CHANGED || !isDocumentModified(virtualFile)) {
+ final AbstractVcs vcs = myVcsManager.getVcsFor(virtualFile);
if (vcs == null) return;
- if (cachedStatus == FileStatus.MODIFIED && !isDocumentModified(file)) {
+ if (cachedStatus == FileStatus.MODIFIED && !isDocumentModified(virtualFile)) {
if (!((ReadonlyStatusHandlerImpl) ReadonlyStatusHandlerImpl.getInstance(myProject)).getState().SHOW_DIALOG) {
RollbackEnvironment rollbackEnvironment = vcs.getRollbackEnvironment();
if (rollbackEnvironment != null) {
- rollbackEnvironment.rollbackIfUnchanged(file);
+ rollbackEnvironment.rollbackIfUnchanged(virtualFile);
}
}
}
- myFileStatusManager.fileStatusChanged(file);
+ myFileStatusManager.fileStatusChanged(virtualFile);
ChangeProvider cp = vcs.getChangeProvider();
if (cp != null && cp.isModifiedDocumentTrackingRequired()) {
- myDirtyScopeManager.fileDirty(file);
+ myDirtyScopeManager.fileDirty(virtualFile);
}
}
}
+ @NotNull
@Override
- public ThreeState getNotChangedDirectoryParentingStatus(VirtualFile vf) {
- return myConfiguration.SHOW_DIRTY_RECURSIVELY ? myChangeListManager.haveChangesUnder(vf) : ThreeState.NO;
+ public ThreeState getNotChangedDirectoryParentingStatus(@NotNull VirtualFile virtualFile) {
+ return myConfiguration.SHOW_DIRTY_RECURSIVELY ? myChangeListManager.haveChangesUnder(virtualFile) : ThreeState.NO;
}
@Override
@@ -164,6 +173,7 @@
if (isDocumentModified(file)) {
return ApplicationManager.getApplication().runReadAction(new Computable<String>() {
+ @Override
public String compute() {
return LoadTextUtil.loadText(file).toString();
}
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java
index a1f3b7a..6f4292b 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/ui/CommitMessage.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
import com.intellij.ui.*;
@@ -143,7 +144,7 @@
}
public void setText(final String initialMessage) {
- final String text = initialMessage == null ? "" : initialMessage;
+ final String text = initialMessage == null ? "" : StringUtil.convertLineSeparators(initialMessage);
myEditorField.setText(text);
if (myMessageConsumer != null) {
myMessageConsumer.consume(text);
diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java
index 87f37fc..d6158c5 100644
--- a/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java
+++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/update/ShowUpdatedDiffAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -151,11 +151,9 @@
}
public String getContent() throws VcsException {
- if (myContent != null) {
- final String s = myContent.get();
- if (s != null) {
- return s;
- }
+ final String s = com.intellij.reference.SoftReference.dereference(myContent);
+ if (s != null) {
+ return s;
}
final String loaded = myLoader.convert(myPointer);
diff --git a/platform/vcs-impl/src/com/intellij/peer/impl/VcsContextFactoryImpl.java b/platform/vcs-impl/src/com/intellij/peer/impl/VcsContextFactoryImpl.java
index 4787744..ab6b692 100644
--- a/platform/vcs-impl/src/com/intellij/peer/impl/VcsContextFactoryImpl.java
+++ b/platform/vcs-impl/src/com/intellij/peer/impl/VcsContextFactoryImpl.java
@@ -16,9 +16,7 @@
package com.intellij.peer.impl;
import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.FilePathImpl;
import com.intellij.openapi.vcs.actions.VcsContext;
@@ -46,41 +44,24 @@
}
public FilePath createFilePathOn(@NotNull final VirtualFile virtualFile) {
- return ApplicationManager.getApplication().runReadAction(new Computable<FilePath>() {
- public FilePath compute() {
- return new FilePathImpl(virtualFile);
- }
- });
+ return new FilePathImpl(virtualFile);
}
public FilePath createFilePathOn(final File file) {
- return ApplicationManager.getApplication().runReadAction(new Computable<FilePath>() {
- public FilePath compute() {
- return FilePathImpl.create(file);
- }
- });
+ return FilePathImpl.create(file);
}
public FilePath createFilePathOn(final File file, final NotNullFunction<File, Boolean> detector) {
- return ApplicationManager.getApplication().runReadAction(new Computable<FilePath>() {
- public FilePath compute() {
- VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
- if (virtualFile != null) {
- // detector information (loaded here lazily) is not needed - we have real file
- return FilePathImpl.create(file);
- }
-
- return FilePathImpl.create(file, detector.fun(file).booleanValue());
- }
- });
+ VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(file);
+ if (virtualFile != null) {
+ // detector information (loaded here lazily) is not needed - we have real file
+ return FilePathImpl.create(file);
+ }
+ return FilePathImpl.create(file, detector.fun(file).booleanValue());
}
public FilePath createFilePathOn(final File file, final boolean isDirectory) {
- return ApplicationManager.getApplication().runReadAction(new Computable<FilePath>() {
- public FilePath compute() {
- return FilePathImpl.create(file, isDirectory);
- }
- });
+ return FilePathImpl.create(file, isDirectory);
}
@NotNull
@@ -89,19 +70,11 @@
}
public FilePath createFilePathOnDeleted(final File file, final boolean isDirectory) {
- return ApplicationManager.getApplication().runReadAction(new Computable<FilePath>() {
- public FilePath compute() {
- return FilePathImpl.createForDeletedFile(file, isDirectory);
- }
- });
+ return FilePathImpl.createForDeletedFile(file, isDirectory);
}
public FilePath createFilePathOn(final VirtualFile parent, final String name) {
- return ApplicationManager.getApplication().runReadAction(new Computable<FilePath>() {
- public FilePath compute() {
- return new FilePathImpl(parent, name, false);
- }
- });
+ return new FilePathImpl(parent, name, false);
}
public LocalChangeList createLocalChangeList(Project project, @NotNull final String name) {
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
index 5f40300..3e3bd73 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/Executor.java
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.vcs;
+import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.util.SystemInfo;
@@ -30,7 +31,6 @@
import java.util.List;
/**
- *
* @author Kirill Likhodedov
*/
public class Executor {
@@ -135,7 +135,7 @@
}
CapturingProcessHandler handler = new CapturingProcessHandler(clientProcess, CharsetToolkit.getDefaultSystemCharset());
- ProcessOutput result = handler.runProcess(30*1000);
+ ProcessOutput result = handler.runProcess(30 * 1000);
if (result.isTimeout()) {
throw new RuntimeException("Timeout waiting for the command execution. Command: " + StringUtil.join(params, " "));
}
@@ -191,41 +191,29 @@
return split;
}
- protected static String findExecutable(String programName, String unixExec, String winExec, Collection<String> pathEnvs) {
- String exec = findInPathEnvs(programName, pathEnvs);
+ protected static String findExecutable(String programName, String unixExec, String winExec, Collection<String> envs) {
+ String exec = findEnvValue(programName, envs);
if (exec != null) {
return exec;
}
- exec = findInPath(programName, unixExec, winExec);
- if (exec != null) {
- return exec;
+ File fileExec = PathEnvironmentVariableUtil.findInPath(SystemInfo.isWindows ? winExec : unixExec);
+ if (fileExec != null) {
+ return fileExec.getAbsolutePath();
}
- throw new IllegalStateException(programName + " executable not found. " +
- "Please define a valid environment variable " + pathEnvs.iterator().next() +
- " pointing to the " + programName + " executable.");
+ throw new IllegalStateException(programName + " executable not found. " + (envs.size() > 0 ?
+ "Please define a valid environment variable " +
+ envs.iterator().next() +
+ " pointing to the " +
+ programName +
+ " executable." : ""));
}
- protected static String findInPath(String programName, String unixExec, String winExec) {
- String path = System.getenv(SystemInfo.isWindows ? "Path" : "PATH");
- if (path != null) {
- String name = SystemInfo.isWindows ? winExec : unixExec;
- for (String dir : path.split(File.pathSeparator)) {
- File file = new File(dir, name);
- if (file.canExecute()) {
- log("Using " + programName + " from PATH: " + file.getPath());
- return file.getPath();
- }
- }
- }
- return null;
- }
-
- protected static String findInPathEnvs(String programName, Collection<String> pathEnvs) {
- for (String pathEnv : pathEnvs) {
- String exec = System.getenv(pathEnv);
- if (exec != null && new File(exec).canExecute()) {
- log(String.format("Using %s from %s: %s", programName, pathEnv, exec));
- return exec;
+ protected static String findEnvValue(String programNameForLog, Collection<String> envs) {
+ for (String env : envs) {
+ String val = System.getenv(env);
+ if (val != null && new File(val).canExecute()) {
+ log(String.format("Using %s from %s: %s", programNameForLog, env, val));
+ return val;
}
}
return null;
@@ -239,7 +227,7 @@
String[] split = path.split("/");
if (split.length > 3) {
// split[0] is empty, because the path starts from /
- return String.format("/%s/.../%s/%s", split[1], split[split.length-2], split[split.length-1]);
+ return String.format("/%s/.../%s/%s", split[1], split[split.length - 2], split[split.length - 1]);
}
return path;
}
@@ -253,5 +241,4 @@
assert ourCurrentDir != null : "Current dir hasn't been initialized yet. Call cd at least once before any other command.";
return new File(ourCurrentDir);
}
-
}
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootConfiguration.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootConfiguration.java
index d3ac4b3..889394b 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootConfiguration.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootConfiguration.java
@@ -17,13 +17,14 @@
import org.jetbrains.annotations.NotNull;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* @author Nadya Zabrodina
*/
-public class VcsRootConfiguration {
+class VcsRootConfiguration {
@NotNull private Collection<String> myMockRoots;
@NotNull private Collection<String> myContentRoots;
@@ -40,28 +41,28 @@
myExtraErrors = Collections.emptyList();
}
- public VcsRootConfiguration mock(@NotNull Collection<String> mockRoots) {
- myMockRoots = mockRoots;
+ public VcsRootConfiguration mock(@NotNull String... mockRoots) {
+ myMockRoots = Arrays.asList(mockRoots);
return this;
}
- public VcsRootConfiguration roots(@NotNull Collection<String> roots) {
- myRoots = roots;
+ public VcsRootConfiguration roots(@NotNull String... roots) {
+ myRoots = Arrays.asList(roots);
return this;
}
- public VcsRootConfiguration contentRoots(@NotNull Collection<String> contentRoots) {
- myContentRoots = contentRoots;
+ public VcsRootConfiguration contentRoots(@NotNull String... contentRoots) {
+ myContentRoots = Arrays.asList(contentRoots);
return this;
}
- public VcsRootConfiguration unregErrors(@NotNull Collection<String> unregErrors) {
- myUnregErrors = unregErrors;
+ public VcsRootConfiguration unregErrors(@NotNull String... unregErrors) {
+ myUnregErrors = Arrays.asList(unregErrors);
return this;
}
- public VcsRootConfiguration extraErrors(@NotNull Collection<String> extraErrors) {
- myExtraErrors = extraErrors;
+ public VcsRootConfiguration extraErrors(@NotNull String... extraErrors) {
+ myExtraErrors = Arrays.asList(extraErrors);
return this;
}
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java
index aa62381..fed3cf3 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootDetectorTest.java
@@ -32,7 +32,6 @@
import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import static com.intellij.openapi.vcs.Executor.cd;
import static com.intellij.openapi.vcs.Executor.mkdir;
@@ -45,23 +44,23 @@
public class VcsRootDetectorTest extends VcsRootPlatformTest {
public void testNoRootsInProject() throws IOException {
- doTest(new VcsRootConfiguration(), null, Collections.<String>emptyList());
+ doTest(new VcsRootConfiguration(), null);
}
public void testProjectUnderSingleMockRoot() throws IOException {
- doTest(new VcsRootConfiguration().mock(Arrays.asList(".")), myProjectRoot, Arrays.asList("."));
+ doTest(new VcsRootConfiguration().mock("."), myProjectRoot, ".");
}
public void testProjectWithMockRootUnderIt() throws IOException {
cd(myProjectRoot);
mkdir("src");
mkdir(".idea");
- doTest(new VcsRootConfiguration().mock(Arrays.asList("community")), myProjectRoot, Arrays.asList("community"));
+ doTest(new VcsRootConfiguration().mock("community"), myProjectRoot, "community");
}
public void testProjectWithAllSubdirsUnderMockRootShouldStillBeNotFullyControlled() throws IOException {
String[] dirNames = {".idea", "src", "community"};
- doTest(new VcsRootConfiguration().mock(Arrays.asList(dirNames)), myProjectRoot, Arrays.asList(dirNames));
+ doTest(new VcsRootConfiguration().mock(dirNames), myProjectRoot, dirNames);
}
public void testProjectUnderVcsAboveIt() throws IOException {
@@ -69,28 +68,28 @@
cd(myRepository);
mkdir(subdir);
VirtualFile vfile = myRepository.findChild(subdir);
- doTest(new VcsRootConfiguration().mock(Arrays.asList(myRepository.getName())), vfile, Arrays.asList(myRepository.getName())
+ doTest(new VcsRootConfiguration().mock(myRepository.getName()), vfile, myRepository.getName()
);
}
public void testIDEAProject() throws IOException {
String[] names = {"community", "contrib", "."};
- doTest(new VcsRootConfiguration().mock(Arrays.asList(names)), myProjectRoot, Arrays.asList(names));
+ doTest(new VcsRootConfiguration().mock(names), myProjectRoot, names);
}
public void testOneAboveAndOneUnder() throws IOException {
String[] names = {myRepository.getName() + "/community", "."};
- doTest(new VcsRootConfiguration().mock(Arrays.asList(names)), myRepository, Arrays.asList(names));
+ doTest(new VcsRootConfiguration().mock(names), myRepository, names);
}
public void testOneAboveAndOneForProjectShouldShowOnlyProjectRoot() throws IOException {
String[] names = {myRepository.getName(), "."};
- doTest(new VcsRootConfiguration().mock(Arrays.asList(names)), myRepository, Arrays.asList(myRepository.getName()));
+ doTest(new VcsRootConfiguration().mock(names), myRepository, myRepository.getName());
}
public void testOneAboveAndSeveralUnderProject() throws IOException {
String[] names = {".", myRepository.getName() + "/community", myRepository.getName() + "/contrib"};
- doTest(new VcsRootConfiguration().mock(Arrays.asList(names)), myRepository, Arrays.asList(names));
+ doTest(new VcsRootConfiguration().mock(names), myRepository, names);
}
public void testMultipleAboveShouldBeDetectedAsOneAbove() throws IOException {
@@ -98,42 +97,42 @@
cd(myRepository);
mkdir(subdir);
VirtualFile vfile = myRepository.findChild(subdir);
- doTest(new VcsRootConfiguration().mock(Arrays.asList(".", myRepository.getName())), vfile, Arrays.asList(myRepository.getName()));
+ doTest(new VcsRootConfiguration().mock(".", myRepository.getName()), vfile, myRepository.getName());
}
public void testUnrelatedRootShouldNotBeDetected() throws IOException {
- doTest(new VcsRootConfiguration().mock(Arrays.asList("another")), myRepository, Collections.<String>emptyList());
+ doTest(new VcsRootConfiguration().mock("another"), myRepository);
}
public void testLinkedSourceRootAloneShouldBeDetected() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("linked_root"))
- .contentRoots(Arrays.asList("linked_root"));
- doTest(vcsRootConfiguration, myRepository, Arrays.asList("linked_root"));
+ new VcsRootConfiguration().mock("linked_root")
+ .contentRoots("linked_root");
+ doTest(vcsRootConfiguration, myRepository, "linked_root");
}
public void testLinkedSourceRootAndProjectRootShouldBeDetected() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "linked_root"))
- .contentRoots(Arrays.asList("linked_root"));
- doTest(vcsRootConfiguration, myProjectRoot, Arrays.asList(".", "linked_root"));
+ new VcsRootConfiguration().mock(".", "linked_root")
+ .contentRoots("linked_root");
+ doTest(vcsRootConfiguration, myProjectRoot, ".", "linked_root");
}
public void testLinkedSourceBelowMockRoot() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().contentRoots(Arrays.asList("linked_root/src"))
- .mock(Arrays.asList(".", "linked_root"));
- doTest(vcsRootConfiguration, myProjectRoot, Arrays.asList(".", "linked_root"));
+ new VcsRootConfiguration().contentRoots("linked_root/src")
+ .mock(".", "linked_root");
+ doTest(vcsRootConfiguration, myProjectRoot, ".", "linked_root");
}
// This is a test of performance optimization via limitation: don't scan deep though the whole VFS, i.e. don't detect deep roots
public void testDontScanDeeperThan2LevelsBelowAContentRoot() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("community", "content_root/lev1/lev2", "content_root2/lev1/lev2/lev3"))
- .contentRoots(Arrays.asList("content_root"));
+ new VcsRootConfiguration().mock("community", "content_root/lev1/lev2", "content_root2/lev1/lev2/lev3")
+ .contentRoots("content_root");
doTest(vcsRootConfiguration,
- myProjectRoot, Arrays.asList("community", "content_root/lev1/lev2"));
+ myProjectRoot, "community", "content_root/lev1/lev2");
}
void assertRoots(@NotNull Collection<String> expectedRelativePaths, @NotNull Collection<String> actual) {
@@ -176,11 +175,11 @@
public void doTest(@NotNull VcsRootConfiguration vcsRootConfiguration,
@Nullable VirtualFile startDir,
- @NotNull Collection<String> expectedPaths)
+ @NotNull String... expectedPaths)
throws IOException {
initProject(vcsRootConfiguration);
Collection<VcsRoot> vcsRoots = detect(startDir);
- assertRoots(expectedPaths, getPaths(
+ assertRoots(Arrays.asList(expectedPaths), getPaths(
ContainerUtil.filter(vcsRoots, new Condition<VcsRoot>() {
@Override
public boolean value(VcsRoot root) {
diff --git a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java
index cec34c8..198cdbb 100644
--- a/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java
+++ b/platform/vcs-impl/testSrc/com/intellij/openapi/vcs/roots/VcsRootErrorsFinderTest.java
@@ -25,7 +25,6 @@
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
@@ -47,128 +46,128 @@
public void testSameOneRootInBothThenNoErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("."))
- .roots(Arrays.asList("."));
+ new VcsRootConfiguration().mock(".")
+ .roots(".");
doTest(vcsRootConfiguration);
}
public void testSameTwoRootsInBothThenNoErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "community"))
- .roots(Arrays.asList(".", "community"));
+ new VcsRootConfiguration().mock(".", "community")
+ .roots(".", "community");
doTest(vcsRootConfiguration);
}
public void testOneMockRootNoVCSRootsThenError() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("."))
- .unregErrors(Arrays.asList("."));
+ new VcsRootConfiguration().mock(".")
+ .unregErrors(".");
doTest(vcsRootConfiguration);
}
public void testOneVCSRootNoMockRootsThenError() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().roots(Arrays.asList("."))
- .extraErrors(Arrays.asList("."));
+ new VcsRootConfiguration().roots(".")
+ .extraErrors(".");
doTest(vcsRootConfiguration);
}
public void testOneRootButDifferentThenTwoErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("."))
- .roots(Arrays.asList("community"))
- .unregErrors(Arrays.asList(".")).extraErrors(Arrays.asList("community"));
+ new VcsRootConfiguration().mock(".")
+ .roots("community")
+ .unregErrors(".").extraErrors("community");
doTest(vcsRootConfiguration);
}
public void testTwoRootsOneMatchingOneDifferentThenTwoErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "community"))
- .roots(Arrays.asList(".", "contrib"))
- .unregErrors(Arrays.asList("community")).extraErrors(Arrays.asList("contrib"));
+ new VcsRootConfiguration().mock(".", "community")
+ .roots(".", "contrib")
+ .unregErrors("community").extraErrors("contrib");
doTest(vcsRootConfiguration);
}
public void testTwoRootsInMockRootOneMatchingInVCSThenError() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "community"))
- .roots(Arrays.asList("."))
- .unregErrors(Arrays.asList("community"));
+ new VcsRootConfiguration().mock(".", "community")
+ .roots(".")
+ .unregErrors("community");
doTest(vcsRootConfiguration);
}
public void testTwoRootsBothNotMatchingThenFourErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "community"))
- .roots(Arrays.asList("another", "contrib"))
- .unregErrors(Arrays.asList("community", ".")).extraErrors(Arrays.asList("contrib", "another"));
+ new VcsRootConfiguration().mock(".", "community")
+ .roots("another", "contrib")
+ .unregErrors("community", ".").extraErrors("contrib", "another");
doTest(vcsRootConfiguration);
}
public void testProjectRootNoMockRootsThenErrorAboutExtraRoot() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
new VcsRootConfiguration()
- .roots(Arrays.asList(PROJECT))
- .extraErrors(Arrays.asList(PROJECT));
+ .roots(PROJECT)
+ .extraErrors(PROJECT);
doTest(vcsRootConfiguration);
}
public void testProjectRootFullUnderMockRootThenCorrect() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("."))
- .roots(Arrays.asList(PROJECT));
+ new VcsRootConfiguration().mock(".")
+ .roots(PROJECT);
doTest(vcsRootConfiguration);
}
public void testProjectRootMockRootForAContentRootBelowProjectThenError() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("content_root"))
- .contentRoots(Arrays.asList("content_root")).roots(Arrays.asList(PROJECT))
- .unregErrors(Arrays.asList("content_root")).extraErrors(Arrays.asList(PROJECT));
+ new VcsRootConfiguration().mock("content_root")
+ .contentRoots("content_root").roots(PROJECT)
+ .unregErrors("content_root").extraErrors(PROJECT);
doTest(vcsRootConfiguration);
}
public void testProjectRootMockRootBelowProjectFolderNotInAContentRootThenUnregisteredRootError() throws IOException {
// this is to be fixed: auto-detection of MockRoot repositories in subfolders for the <Project> mapping
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList("community"))
- .contentRoots(Arrays.asList(".")).roots(Arrays.asList(PROJECT))
- .unregErrors(Arrays.asList("community")).extraErrors(Arrays.asList(PROJECT));
+ new VcsRootConfiguration().mock("community")
+ .contentRoots(".").roots(PROJECT)
+ .unregErrors("community").extraErrors(PROJECT);
doTest(vcsRootConfiguration);
}
public void testProjectRootMockRootForFullProjectContentRootLinkedSourceFolderBelowProjectThenErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "content_root", "../linked_source_root", "folder"))
- .roots(Arrays.asList(PROJECT))
- .contentRoots(Arrays.asList(".", "content_root", "../linked_source_root"))
- .unregErrors(Arrays.asList("content_root", "../linked_source_root", "folder"));
+ new VcsRootConfiguration().mock(".", "content_root", "../linked_source_root", "folder")
+ .roots(PROJECT)
+ .contentRoots(".", "content_root", "../linked_source_root")
+ .unregErrors("content_root", "../linked_source_root", "folder");
doTest(vcsRootConfiguration);
}
public void testProjectRootForFolderMockRootForFullProjectContentRootLinkedSourceFolderBelowProjectThenErrors() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "content_root", "../linked_source_root", "folder"))
- .roots(Arrays.asList(PROJECT, "folder"))
- .contentRoots(Arrays.asList(".", "content_root", "../linked_source_root"))
- .unregErrors(Arrays.asList("content_root", "../linked_source_root"));
+ new VcsRootConfiguration().mock(".", "content_root", "../linked_source_root", "folder")
+ .roots(PROJECT, "folder")
+ .contentRoots(".", "content_root", "../linked_source_root")
+ .unregErrors("content_root", "../linked_source_root");
doTest(vcsRootConfiguration);
}
public void testProjectRootMockRootLikeInIDEAProjectThenError() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "community", "contrib")).roots(Arrays.asList(PROJECT))
- .contentRoots(Arrays.asList(".", "community", "contrib")).unregErrors(Arrays.asList("community", "contrib"));
+ new VcsRootConfiguration().mock(".", "community", "contrib").roots(PROJECT)
+ .contentRoots(".", "community", "contrib").unregErrors("community", "contrib");
doTest(vcsRootConfiguration);
}
public void testRealMockRootRootDeeperThanThreeLevelsShouldBeDetected() throws IOException {
VcsRootConfiguration vcsRootConfiguration =
- new VcsRootConfiguration().mock(Arrays.asList(".", "community", "contrib", "community/level1/level2/level3"))
- .contentRoots(Arrays.asList(".", "community", "contrib")).roots(Arrays.asList(PROJECT, "community/level1/level2/level3"))
- .unregErrors(Arrays.asList("community", "contrib"));
+ new VcsRootConfiguration().mock(".", "community", "contrib", "community/level1/level2/level3")
+ .contentRoots(".", "community", "contrib").roots(PROJECT, "community/level1/level2/level3")
+ .unregErrors("community", "contrib");
doTest(vcsRootConfiguration);
}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java
index 2b658cb..1c0ddec 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogBranchFilter.java
@@ -17,12 +17,14 @@
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+
/**
* Tells to filter by some branch name.
*/
-public interface VcsLogBranchFilter extends VcsLogFilter {
+public interface VcsLogBranchFilter extends VcsLogGraphFilter {
@NotNull
- String getBranchName();
+ Collection<String> getBranchNames();
}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java
index d080b67..aa59bb6 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDateFilter.java
@@ -23,7 +23,7 @@
* Tells to filter by date. <br/>
* Only before or after dates can be given, or both can be given.
*/
-public interface VcsLogDateFilter {
+public interface VcsLogDateFilter extends VcsLogDetailsFilter {
/**
* If not null, only commits made after the returned date (inclusively) should be accepted.
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java
new file mode 100644
index 0000000..31ce3d4
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogDetailsFilter.java
@@ -0,0 +1,14 @@
+package com.intellij.vcs.log;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Filter which needs {@link VcsFullCommitDetails} to work.
+ *
+ * @see VcsLogGraphFilter
+ */
+public interface VcsLogDetailsFilter extends VcsLogFilter {
+
+ boolean matches(@NotNull VcsFullCommitDetails details);
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java
new file mode 100644
index 0000000..a1c10ec
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogFilterCollection.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.vcs.log;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * Encapsulates filters which can be set to VCS Log commits.
+ * <p/>
+ * All not-null filters are connected with AND, which means that commits should meet all of them. <br/>
+ */
+public interface VcsLogFilterCollection {
+
+ @Nullable
+ VcsLogBranchFilter getBranchFilter();
+
+ @Nullable
+ VcsLogUserFilter getUserFilter();
+
+ @Nullable
+ VcsLogDateFilter getDateFilter();
+
+ @Nullable
+ VcsLogTextFilter getTextFilter();
+
+ @Nullable
+ VcsLogStructureFilter getStructureFilter();
+
+ /**
+ * Returns true if there are no filters in this collection.
+ */
+ boolean isEmpty();
+
+ @NotNull
+ List<VcsLogGraphFilter> getGraphFilters();
+
+ @NotNull
+ List<VcsLogDetailsFilter> getDetailsFilters();
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogGraphFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogGraphFilter.java
new file mode 100644
index 0000000..4475b5d
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogGraphFilter.java
@@ -0,0 +1,10 @@
+package com.intellij.vcs.log;
+
+/**
+ * Filter that is able to work on graph.
+ */
+public interface VcsLogGraphFilter extends VcsLogFilter {
+
+ boolean matches(int hash);
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHashFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHashFilter.java
new file mode 100644
index 0000000..acd39bf
--- /dev/null
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogHashFilter.java
@@ -0,0 +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.vcs.log;
+
+import java.util.Collection;
+
+public interface VcsLogHashFilter {
+
+ Collection<Hash> getHashes();
+
+}
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
index ae8ee64..a325ece 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogProvider.java
@@ -76,19 +76,11 @@
/**
* <p>Return commits with full details, which correspond to the given filters.</p>
*
- * <p>There can be several filters of a single type (e.g. several filters by users).<br/>
- * Filters of different types are concatenated with {@code AND}, while filters of a single type are concatenated with {@code OR}.
- * E.g.: (branch1 OR branch2) AND (user1 OR user2).</p>
- *
* @param maxCount maximum number of commits to request from the VCS, or -1 for unlimited.
*/
@NotNull
List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull VirtualFile root,
- @NotNull Collection<VcsLogBranchFilter> branchFilters,
- @NotNull Collection<VcsLogUserFilter> userFilters,
- @NotNull Collection<VcsLogDateFilter> dateFilters,
- @NotNull Collection<VcsLogTextFilter> textFilters,
- @NotNull Collection<VcsLogStructureFilter> structureFilters,
+ @NotNull VcsLogFilterCollection filterCollection,
int maxCount) throws VcsException;
/**
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
index dd0ed62..2294fc7 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogStructureFilter.java
@@ -23,7 +23,7 @@
/**
* Tells the log to filter by files and folders.
*/
-public interface VcsLogStructureFilter {
+public interface VcsLogStructureFilter extends VcsLogDetailsFilter {
/**
* <p>Returns files from the given VCS root, which are affected by matching commits, and folders containing such files.</p>
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java
index 06d84e9..2ae3ac3 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogTextFilter.java
@@ -20,7 +20,7 @@
/**
* Specifies the log filter by text.
*/
-public interface VcsLogTextFilter {
+public interface VcsLogTextFilter extends VcsLogDetailsFilter {
/**
* Only commits containing the returned text it their commit messages should match the filter.
diff --git a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java
index 1cd6d95..449b087 100644
--- a/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java
+++ b/platform/vcs-log/api/src/com/intellij/vcs/log/VcsLogUserFilter.java
@@ -3,16 +3,21 @@
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
+import java.util.Collection;
+
/**
- * Filters log by user.
+ * Filters commmits by one or several users.
*/
-public interface VcsLogUserFilter extends VcsLogFilter {
+public interface VcsLogUserFilter extends VcsLogDetailsFilter {
/**
- * Returns the user name selected in the filter for the given root.
- * If it is a name-as-text filter, of course, values don't differ per root. The difference appears if the special "me" filter is used.
+ * Returns user names selected in the filter, concerning the passed VCS root.
+ * @param root has no effect if user chooses some user name;
+ * it is needed if user selects the predefined value "me" which means the current user.
+ * Since current user name can be defined differently for different roots, we pass the root for which this value is
+ * requested.
*/
@NotNull
- String getUserName(@NotNull VirtualFile root);
+ Collection<String> getUserNames(@NotNull VirtualFile root);
}
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/elements/Node.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/elements/Node.java
index 87962f3..bae6e91 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/elements/Node.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/elements/Node.java
@@ -22,14 +22,12 @@
/**
* @return if type == COMMIT_NODE - this commit.
- * if type == EDGE_NODE - common Parent
* if type == END_COMMIT_NODE - parent of This Commit
*/
int getCommitIndex();
enum NodeType {
COMMIT_NODE,
- EDGE_NODE,
END_COMMIT_NODE
}
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphAppendBuilder.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphAppendBuilder.java
deleted file mode 100644
index 3beee18..0000000
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphAppendBuilder.java
+++ /dev/null
@@ -1,126 +0,0 @@
-package com.intellij.vcs.log.graph.mutable;
-
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.GraphCommit;
-import com.intellij.vcs.log.VcsRef;
-import com.intellij.vcs.log.graph.mutable.elements.MutableNode;
-import com.intellij.vcs.log.graph.mutable.elements.MutableNodeRow;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.*;
-
-import static com.intellij.vcs.log.graph.elements.Node.NodeType.*;
-
-/**
- * @author erokhins
- */
-//local package
-public class GraphAppendBuilder {
-
-
- private final MutableGraph graph;
- private final Collection<VcsRef> myRefs;
-
- public GraphAppendBuilder(MutableGraph graph, Collection<VcsRef> allRefs) {
- this.graph = graph;
- myRefs = allRefs;
- }
-
- private MutableNodeRow getLastRowInGraph() {
- List<MutableNodeRow> allRows = graph.getAllRows();
- assert !allRows.isEmpty() : "graph is empty!";
- return allRows.get(allRows.size() - 1);
- }
-
- private boolean isSimpleEndOfGraph() {
- List<MutableNodeRow> allRows = graph.getAllRows();
- assert !allRows.isEmpty() : "graph is empty!";
- MutableNodeRow lastRow = getLastRowInGraph();
-
- boolean hasCommitNode = false;
- for (MutableNode node : lastRow.getInnerNodeList()) {
- if (node.getType() == COMMIT_NODE) {
- hasCommitNode = true;
- }
- }
- if (hasCommitNode) {
- if (lastRow.getInnerNodeList().size() == 1) {
- return true;
- }
- else {
- throw new IllegalStateException("graph with commit node and more that 1 node in last row");
- }
- }
- else {
- return false;
- }
- }
-
- private Map<Integer, MutableNode> fixUnderdoneNodes(int firstHash) {
- Map<Integer, MutableNode> underdoneNodes = ContainerUtil.newHashMap();
- List<MutableNode> nodesInLaseRow = getLastRowInGraph().getInnerNodeList();
- MutableNode node;
- for (Iterator<MutableNode> iterator = nodesInLaseRow.iterator(); iterator.hasNext(); ) {
- node = iterator.next();
-
- if (node.getType() != END_COMMIT_NODE) {
- throw new IllegalStateException("bad last row in graph, unexpected node type: " + node.getType());
- }
- // i.e. it is EDGE_NODE
- if (node.getInnerUpEdges().size() > 1) {
- if (node.getCommitIndex() == firstHash) {
- iterator.remove();
- underdoneNodes.put(firstHash, node);
- }
- else {
- node.setType(EDGE_NODE);
- MutableNode newParentNode = new MutableNode(node.getBranch(), node.getCommitIndex());
- GraphBuilder.createUsualEdge(node, newParentNode, node.getBranch());
- underdoneNodes.put(node.getCommitIndex(), newParentNode);
- }
- }
- else {
- iterator.remove();
- underdoneNodes.put(node.getCommitIndex(), node);
- }
- }
-
- return underdoneNodes;
- }
-
- private void simpleAppend(@NotNull List<GraphCommit> commitParentses,
- @NotNull MutableNodeRow nextRow,
- @NotNull Map<Integer, MutableNode> underdoneNodes) {
- int startIndex = nextRow.getRowIndex();
-
- Map<Integer, Integer> commitLogIndexes = new HashMap<Integer, Integer>(commitParentses.size());
- for (int i = 0; i < commitParentses.size(); i++) {
- commitLogIndexes.put(commitParentses.get(i).getIndex(), i + startIndex);
- }
-
- GraphBuilder builder = createGraphBuilder(commitParentses, nextRow, underdoneNodes, startIndex, commitLogIndexes);
- builder.runBuild(commitParentses);
- }
-
- @NotNull
- protected GraphBuilder createGraphBuilder(List<GraphCommit> commitParentses, MutableNodeRow nextRow, Map<Integer, MutableNode> underdoneNodes,
- int startIndex, Map<Integer, Integer> commitLogIndexes) {
- return new GraphBuilder(commitParentses.size() + startIndex - 1, commitLogIndexes, graph, underdoneNodes, nextRow, myRefs);
- }
-
- public void appendToGraph(@NotNull List<GraphCommit> commitParentses) {
- if (commitParentses.size() == 0) {
- throw new IllegalArgumentException("Empty list commitParentses");
- }
- if (isSimpleEndOfGraph()) {
- int startIndex = getLastRowInGraph().getRowIndex() + 1;
- simpleAppend(commitParentses, new MutableNodeRow(graph, startIndex), new HashMap<Integer, MutableNode>());
- }
- else {
- Map<Integer, MutableNode> underdoneNodes = fixUnderdoneNodes(commitParentses.get(0).getIndex());
- MutableNodeRow lastRow = getLastRowInGraph();
- graph.getAllRows().remove(graph.getAllRows().size() - 1);
- simpleAppend(commitParentses, lastRow, underdoneNodes);
- }
- }
-}
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java
index e7c2e82..b07d876 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graph/mutable/GraphBuilder.java
@@ -25,19 +25,10 @@
@NotNull
public static MutableGraph build(@NotNull List<? extends GraphCommit> commitParentses, Collection<VcsRef> allRefs) {
- GraphBuilder builder = new GraphBuilder(commitParentses.size() - 1, calcCommitLogIndices(commitParentses), allRefs);
+ GraphBuilder builder = new GraphBuilder(allRefs);
return builder.runBuild(commitParentses);
}
- @NotNull
- public static Map<Integer, Integer> calcCommitLogIndices(@NotNull List<? extends GraphCommit> commitParentses) {
- Map<Integer, Integer> commitLogIndexes = new HashMap<Integer, Integer>(commitParentses.size());
- for (int i = 0; i < commitParentses.size(); i++) {
- commitLogIndexes.put(commitParentses.get(i).getIndex(), i);
- }
- return commitLogIndexes;
- }
-
// local package
static void createUsualEdge(@NotNull MutableNode up, @NotNull MutableNode down, @NotNull Branch branch) {
UsualEdge edge = new UsualEdge(up, down, branch);
@@ -45,21 +36,13 @@
down.getInnerUpEdges().add(edge);
}
- private final int lastLogIndex;
private final MutableGraph graph;
private final Map<Integer, MutableNode> underdoneNodes;
- private Map<Integer, Integer> commitHashLogIndexes;
private MultiMap<Integer, VcsRef> myRefsOfHashes;
private MutableNodeRow nextRow;
- public GraphBuilder(int lastLogIndex,
- Map<Integer, Integer> commitHashLogIndexes,
- MutableGraph graph,
- Map<Integer, MutableNode> underdoneNodes,
- MutableNodeRow nextRow, Collection<VcsRef> refs) {
- this.lastLogIndex = lastLogIndex;
- this.commitHashLogIndexes = commitHashLogIndexes;
+ public GraphBuilder(MutableGraph graph, Map<Integer, MutableNode> underdoneNodes, MutableNodeRow nextRow, Collection<VcsRef> refs) {
this.graph = graph;
this.underdoneNodes = underdoneNodes;
this.nextRow = nextRow;
@@ -76,25 +59,15 @@
return map;
}
- public GraphBuilder(int lastLogIndex, Map<Integer, Integer> commitHashLogIndexes, MutableGraph graph, Collection<VcsRef> refs) {
- this(lastLogIndex, commitHashLogIndexes, graph, new HashMap<Integer, MutableNode>(), new MutableNodeRow(graph, 0), refs);
+ public GraphBuilder(MutableGraph graph, Collection<VcsRef> refs) {
+ this(graph, new HashMap<Integer, MutableNode>(), new MutableNodeRow(graph, 0), refs);
}
- public GraphBuilder(int lastLogIndex, Map<Integer, Integer> commitHashLogIndexes, Collection<VcsRef> refs) {
- this(lastLogIndex, commitHashLogIndexes, new MutableGraph(), refs);
+ public GraphBuilder(Collection<VcsRef> refs) {
+ this(new MutableGraph(), refs);
}
- private int getLogIndexOfCommit(@NotNull Integer commitHash) {
- Integer index = commitHashLogIndexes.get(commitHash);
- if (index == null) {
- return lastLogIndex + 1;
- }
- else {
- return index;
- }
- }
-
@NotNull
private Collection<VcsRef> findRefForHash(int hash) {
return myRefsOfHashes.get(hash);
@@ -133,31 +106,12 @@
MutableNode parentNode = underdoneNodes.remove(parentHash);
if (parentNode == null) {
parentNode = createNode(parentHash, branch);
- createUsualEdge(node, parentNode, branch);
- underdoneNodes.put(parentHash, parentNode);
}
- else {
- createUsualEdge(node, parentNode, branch);
- int parentRowIndex = getLogIndexOfCommit(parentHash);
-
- // i.e. we need of create EDGE_NODE node
- if (nextRow.getRowIndex() != parentRowIndex) {
- parentNode.setNodeRow(nextRow);
- parentNode.setType(EDGE_NODE);
- nextRow.getInnerNodeList().add(parentNode);
-
- MutableNode newParentNode = createNode(parentHash, parentNode.getBranch());
- createUsualEdge(parentNode, newParentNode, parentNode.getBranch());
- underdoneNodes.put(parentHash, newParentNode);
- }
- else {
- // i.e. node must be added in nextRow, when addCurrentCommitAndFinishRow() will called in next time
- underdoneNodes.put(parentHash, parentNode);
- }
- }
+ createUsualEdge(node, parentNode, branch);
+ underdoneNodes.put(parentHash, parentNode);
}
- private MutableNode createNode(int hash, Branch branch) {
+ private static MutableNode createNode(int hash, Branch branch) {
return new MutableNode(branch, hash);
}
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/GraphModel.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/GraphModel.java
index 6d3c7d2..4573b8b 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/GraphModel.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/GraphModel.java
@@ -18,8 +18,6 @@
@NotNull
public Graph getGraph();
- public void appendCommitsToGraph(@NotNull List<GraphCommit> commitParentses);
-
public void setVisibleBranchesNodes(@NotNull Function<Node, Boolean> isStartedNode);
@NotNull
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentGenerator.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentGenerator.java
index 7fcc15f..3c5bca9 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentGenerator.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentGenerator.java
@@ -53,10 +53,6 @@
@Nullable
public GraphFragment getDownShortFragment(@NotNull Node startNode) {
- if (startNode.getType() == Node.NodeType.EDGE_NODE) {
- throw new IllegalArgumentException("small fragment may start only with COMMIT_NODE, but this node is: " + startNode);
- }
-
Set<Node> upNodes = new HashSet<Node>();
upNodes.add(startNode);
Set<Node> notAddedNodes = new HashSet<Node>();
@@ -122,10 +118,6 @@
@Nullable
public GraphFragment getUpShortFragment(@NotNull Node startNode) {
- if (startNode.getType() == Node.NodeType.EDGE_NODE) {
- throw new IllegalArgumentException("small fragment may start only with COMMIT_NODE, but this node is: " + startNode);
- }
-
Set<Node> downNodes = new HashSet<Node>();
downNodes.add(startNode);
Set<Node> notAddedNodes = new HashSet<Node>();
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/BadVisibleEdgeNodeFixer.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/BadVisibleEdgeNodeFixer.java
deleted file mode 100644
index a91ea97..0000000
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/BadVisibleEdgeNodeFixer.java
+++ /dev/null
@@ -1,74 +0,0 @@
-package com.intellij.vcs.log.graphmodel.impl;
-
-import com.intellij.vcs.log.graph.elements.Edge;
-import com.intellij.vcs.log.graph.elements.Node;
-import com.intellij.vcs.log.graph.mutable.GraphDecorator;
-import com.intellij.vcs.log.graph.mutable.elements.MutableNode;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-import java.util.ListIterator;
-
-/**
- * @author erokhins
- */
-public class BadVisibleEdgeNodeFixer implements GraphDecorator {
- private final GraphDecorator decorator;
-
- public BadVisibleEdgeNodeFixer(GraphDecorator decorator) {
- this.decorator = decorator;
- }
-
-
- private boolean isVisibleBadEdgeNode(@NotNull Node node) {
- if (node.getType() != Node.NodeType.EDGE_NODE || decorator.isVisibleNode(node)) {
- return false;
- }
- boolean isBad = false;
- for (Edge edge : ((MutableNode)node).getInnerUpEdges()) {
- Node upNode = edge.getUpNode();
- if (!decorator.isVisibleNode(upNode) || isVisibleBadEdgeNode(upNode)) {
- isBad = true;
- }
- }
- return isBad;
- }
-
- @Override
- public boolean isVisibleNode(@NotNull Node node) {
- if (isVisibleBadEdgeNode(node)) {
- return false;
- }
- return decorator.isVisibleNode(node);
- }
-
- @NotNull
- private Node getDownNode(@NotNull Node edgeNode) {
- return decorator.getDownEdges(edgeNode, ((MutableNode)edgeNode).getInnerDownEdges()).get(0).getDownNode();
- }
-
-
- @NotNull
- @Override
- public List<Edge> getDownEdges(@NotNull Node node, @NotNull List<Edge> innerDownEdges) {
- List<Edge> prevDownEdges = decorator.getDownEdges(node, innerDownEdges);
- for (ListIterator<Edge> edgeIterator = prevDownEdges.listIterator(); edgeIterator.hasNext(); ) {
- Edge edge = edgeIterator.next();
- if (isVisibleBadEdgeNode(edge.getDownNode())) {
- Node downNode = edge.getDownNode();
- while (isVisibleBadEdgeNode(downNode)) {
- downNode = getDownNode(downNode);
- }
- Edge newEdge = null;
- edgeIterator.set(newEdge);
- }
- }
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-
- @NotNull
- @Override
- public List<Edge> getUpEdges(@NotNull Node node, @NotNull List<Edge> innerUpEdges) {
- return null; //To change body of implemented methods use File | Settings | File Templates.
- }
-}
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java
index 4f052f5..f933385 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/graphmodel/impl/GraphModelImpl.java
@@ -3,12 +3,9 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
-import com.intellij.vcs.log.GraphCommit;
-import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.compressedlist.UpdateRequest;
import com.intellij.vcs.log.graph.Graph;
import com.intellij.vcs.log.graph.elements.Node;
-import com.intellij.vcs.log.graph.mutable.GraphAppendBuilder;
import com.intellij.vcs.log.graph.mutable.MutableGraph;
import com.intellij.vcs.log.graphmodel.FragmentManager;
import com.intellij.vcs.log.graphmodel.GraphModel;
@@ -16,7 +13,6 @@
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -25,7 +21,6 @@
*/
public class GraphModelImpl implements GraphModel {
private final MutableGraph graph;
- private final Collection<VcsRef> myRefs;
private final FragmentManagerImpl fragmentManager;
private final BranchVisibleNodes visibleNodes;
private final List<Consumer<UpdateRequest>> listeners = new ArrayList<Consumer<UpdateRequest>>();
@@ -41,9 +36,8 @@
}
};
- public GraphModelImpl(MutableGraph graph, Collection<VcsRef> allRefs) {
+ public GraphModelImpl(MutableGraph graph) {
this.graph = graph;
- myRefs = allRefs;
this.fragmentManager = new FragmentManagerImpl(graph, new FragmentManagerImpl.CallBackFunction() {
@Override
public UpdateRequest runIntermediateUpdate(@NotNull Node upNode, @NotNull Node downNode) {
@@ -104,17 +98,6 @@
}
@Override
- public void appendCommitsToGraph(@NotNull List<GraphCommit> commitParentses) {
- int oldSize = graph.getNodeRows().size();
- new GraphAppendBuilder(graph, myRefs).appendToGraph(commitParentses);
- visibleNodes.setVisibleNodes(visibleNodes.generateVisibleBranchesNodes(isStartedBranchVisibilityNode));
- graph.updateVisibleRows();
-
- UpdateRequest updateRequest = UpdateRequest.buildFromToInterval(0, oldSize - 1, 0, graph.getNodeRows().size() - 1);
- callUpdateListener(updateRequest);
- }
-
- @Override
public void setVisibleBranchesNodes(@NotNull Function<Node, Boolean> isStartedNode) {
this.isStartedBranchVisibilityNode = isStartedNode;
Set<Node> prevVisibleNodes = visibleNodes.getVisibleNodes();
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/GraphElementsVisibilityController.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/GraphElementsVisibilityController.java
index db7c5f9..3a78b57 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/GraphElementsVisibilityController.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/GraphElementsVisibilityController.java
@@ -18,7 +18,7 @@
class GraphElementsVisibilityController {
private static final int LONG_EDGE = 20;
private static final int EDGE_PART_SHOW = 1;
-
+ private static final boolean SHOW_ARROW_WHEN_SHOW_LONG_EDGES = true;
private final LayoutModel layoutModel;
private boolean hideLongEdge;
@@ -34,7 +34,7 @@
@NotNull
public VisibilityType visibilityTypeEdge(Edge edge, int rowIndex) {
- if (!hideLongEdge) {
+ if (!hideLongEdge && !SHOW_ARROW_WHEN_SHOW_LONG_EDGES) {
return USUAL;
}
int upRowIndex = edge.getUpNode().getRowIndex();
@@ -55,7 +55,11 @@
return FIRST_VISIBLE;
}
- return HIDE;
+ if (hideLongEdge) {
+ return HIDE;
+ } else {
+ return USUAL;
+ }
}
@NotNull
diff --git a/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/PrePrintCellModel.java b/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/PrePrintCellModel.java
index 55ef07f..eeac9e4 100644
--- a/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/PrePrintCellModel.java
+++ b/platform/vcs-log/graph/src/com/intellij/vcs/log/printmodel/impl/PrePrintCellModel.java
@@ -84,13 +84,11 @@
break;
case LAST_VISIBLE:
specialPrintElements
- .add(new SpecialPrintElement(edge, i, SpecialPrintElement.Type.DOWN_ARROW, selectController.isSelected(edge), isMarked(edge),
- 0));
+ .add(new SpecialPrintElement(edge, i, SpecialPrintElement.Type.DOWN_ARROW, selectController.isSelected(edge), isMarked(edge), 0));
break;
case FIRST_VISIBLE:
specialPrintElements
- .add(new SpecialPrintElement(edge, i, SpecialPrintElement.Type.UP_ARROW, selectController.isSelected(edge), isMarked(edge),
- 0));
+ .add(new SpecialPrintElement(edge, i, SpecialPrintElement.Type.UP_ARROW, selectController.isSelected(edge), isMarked(edge), 0));
break;
default:
throw new IllegalStateException();
@@ -130,31 +128,21 @@
}
private static class GetterGraphElementPosition {
- private final Map<Node, Integer> mapNodes = new HashMap<Node, Integer>();
+ private final Map<GraphElement, Integer> mapNodes = new HashMap<GraphElement, Integer>();
public GetterGraphElementPosition(List<GraphElement> graphElements) {
mapNodes.clear();
for (int p = 0; p < graphElements.size(); p++) {
- mapNodes.put(getDownNode(graphElements.get(p)), p);
- }
- }
-
- private Node getDownNode(@NotNull GraphElement element) {
- Node node = element.getNode();
- if (node != null) {
- return node;
- }
- else {
- Edge edge = element.getEdge();
- if (edge == null) {
- throw new IllegalStateException();
- }
- return edge.getDownNode();
+ mapNodes.put(graphElements.get(p), p);
}
}
public int getPosition(Edge edge) {
- Integer p = mapNodes.get(edge.getDownNode());
+ Integer p = mapNodes.get(edge);
+ if (p == null) {
+ p = mapNodes.get(edge.getDownNode());
+ }
+
if (p == null) {
// i.e. hide branch
return -1;
diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/GraphTestUtils.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/GraphTestUtils.java
index b406dbf..a8c7166 100644
--- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/GraphTestUtils.java
+++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/GraphTestUtils.java
@@ -47,7 +47,7 @@
@NotNull
public static MutableGraph buildGraph(@NotNull List<GraphCommit> commitParentses, @NotNull List<VcsRef> refs) {
- GraphBuilder builder = new GraphBuilder(commitParentses.size() - 1, GraphBuilder.calcCommitLogIndices(commitParentses), refs) {
+ GraphBuilder builder = new GraphBuilder(refs) {
@NotNull
@Override
protected Branch createBranch(int commitHash, @NotNull Collection<VcsRef> refs) {
diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphAppendBuildTest.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphAppendBuildTest.java
deleted file mode 100644
index 32cc83f..0000000
--- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphAppendBuildTest.java
+++ /dev/null
@@ -1,159 +0,0 @@
-package com.intellij.vcs.log.graph.mutable;
-
-import com.intellij.vcs.log.GraphCommit;
-import com.intellij.vcs.log.VcsRef;
-import com.intellij.vcs.log.graph.GraphTestUtils;
-import com.intellij.vcs.log.graph.elements.Branch;
-import com.intellij.vcs.log.graph.mutable.elements.MutableNode;
-import com.intellij.vcs.log.graph.mutable.elements.MutableNodeRow;
-import com.intellij.vcs.log.parser.SimpleCommitListParser;
-import org.jetbrains.annotations.NotNull;
-import org.junit.Test;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-
-import static com.intellij.vcs.log.graph.GraphStrUtils.toStr;
-import static junit.framework.Assert.assertEquals;
-
-/**
- * @author erokhins
- */
-public class GraphAppendBuildTest {
- public void runTest(String firstPart, String firstPartStr, String secondPart, String secondPartStr) {
- List<GraphCommit> vcsCommitParentses = SimpleCommitListParser.parseCommitList(firstPart);
- final MutableGraph graph = GraphTestUtils.buildGraph(vcsCommitParentses, Collections.<VcsRef>emptyList());
- assertEquals(firstPartStr, toStr(graph));
-
- vcsCommitParentses = SimpleCommitListParser.parseCommitList(secondPart);
- new GraphAppendBuilder(graph, makeRefs(firstPart)) {
- @NotNull
- @Override
- protected GraphBuilder createGraphBuilder(List<GraphCommit> commitParentses, MutableNodeRow nextRow,
- Map<Integer, MutableNode> underdoneNodes, int startIndex,
- Map<Integer, Integer> commitLogIndexes) {
- return new GraphBuilder(commitParentses.size() + startIndex - 1, commitLogIndexes, graph, underdoneNodes, nextRow,
- Collections.<VcsRef>emptyList()) {
- @NotNull
- @Override
- protected Branch createBranch(int commitHash, @NotNull Collection<VcsRef> refs) {
- return GraphTestUtils.createBranchWithFakeRoot(commitHash, refs);
- }
- };
-
- }
- }.appendToGraph(vcsCommitParentses);
- assertEquals(secondPartStr, toStr(graph));
- }
-
- private static Collection<VcsRef> makeRefs(String log) {
- return null;
- }
-
- @Test
- public void simpleEnd() {
- runTest("a0|-",
-
- "a0|-|-|-COMMIT_NODE|-a0|-0",
-
-
- "a1|-",
-
- "a0|-|-|-COMMIT_NODE|-a0|-0\n" + "a1|-|-|-COMMIT_NODE|-a1|-1");
- }
-
-
- @Test
- public void oneEndNode() {
- runTest("a0|-a2",
-
- "a0|-|-a0:a2:USUAL:a0|-COMMIT_NODE|-a0|-0\n" + "a2|-a0:a2:USUAL:a0|-|-END_COMMIT_NODE|-a0|-1",
-
-
- "a1|-a2\n" + "a2|-",
-
- "a0|-|-a0:a2:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-|-a1:a2:USUAL:a1|-COMMIT_NODE|-a1|-1\n" +
- "a2|-a0:a2:USUAL:a0 a1:a2:USUAL:a1|-|-COMMIT_NODE|-a0|-2");
- }
-
-
- @Test
- public void oneEndAfterNotAddNode() {
- runTest("a0|-a2",
-
- "a0|-|-a0:a2:USUAL:a0|-COMMIT_NODE|-a0|-0\n" + "a2|-a0:a2:USUAL:a0|-|-END_COMMIT_NODE|-a0|-1",
-
-
- "a1|-a2", "a0|-|-a0:a2:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-|-a1:a2:USUAL:a1|-COMMIT_NODE|-a1|-1\n" +
- "a2|-a0:a2:USUAL:a0 a1:a2:USUAL:a1|-|-END_COMMIT_NODE|-a0|-2");
- }
-
-
- @Test
- public void oneEndImmediatelyAddNode() {
- runTest("a0|-a1",
-
- "a0|-|-a0:a1:USUAL:a0|-COMMIT_NODE|-a0|-0\n" + "a1|-a0:a1:USUAL:a0|-|-END_COMMIT_NODE|-a0|-1",
-
-
- "a1|-",
-
- "a0|-|-a0:a1:USUAL:a0|-COMMIT_NODE|-a0|-0\n" + "a1|-a0:a1:USUAL:a0|-|-COMMIT_NODE|-a0|-1"
-
- );
- }
-
- @Test
- public void oneEndImmediatelyAddNode2() {
- runTest("a0|-a1",
-
- "a0|-|-a0:a1:USUAL:a0|-COMMIT_NODE|-a0|-0\n" + "a1|-a0:a1:USUAL:a0|-|-END_COMMIT_NODE|-a0|-1",
-
-
- "a1|-a2\n" + "a2|-",
-
- "a0|-|-a0:a1:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-a0:a1:USUAL:a0|-a1:a2:USUAL:a0|-COMMIT_NODE|-a0|-1\n" +
- "a2|-a1:a2:USUAL:a0|-|-COMMIT_NODE|-a0|-2"
-
- );
- }
-
- @Test
- public void edgeNodeInEndImmediately() {
- runTest("a0|-a2\n" + "a1|-a2",
-
- "a0|-|-a0:a2:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-|-a1:a2:USUAL:a1|-COMMIT_NODE|-a1|-1\n" +
- "a2|-a0:a2:USUAL:a0 a1:a2:USUAL:a1|-|-END_COMMIT_NODE|-a0|-2",
-
-
- "a2|-",
-
- "a0|-|-a0:a2:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-|-a1:a2:USUAL:a1|-COMMIT_NODE|-a1|-1\n" +
- "a2|-a0:a2:USUAL:a0 a1:a2:USUAL:a1|-|-COMMIT_NODE|-a0|-2");
- }
-
- @Test
- public void edgeNodeInEnd() {
- runTest("a0|-a3\n" + "a1|-a3",
-
- "a0|-|-a0:a3:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-|-a1:a3:USUAL:a1|-COMMIT_NODE|-a1|-1\n" +
- "a3|-a0:a3:USUAL:a0 a1:a3:USUAL:a1|-|-END_COMMIT_NODE|-a0|-2",
-
-
- "a2|-a3",
-
- "a0|-|-a0:a3:USUAL:a0|-COMMIT_NODE|-a0|-0\n" +
- "a1|-|-a1:a3:USUAL:a1|-COMMIT_NODE|-a1|-1\n" +
- "a2|-|-a2:a3:USUAL:a2|-COMMIT_NODE|-a2|-2\n" +
- " a3|-a0:a3:USUAL:a0 a1:a3:USUAL:a1|-a3:a3:USUAL:a0|-EDGE_NODE|-a0|-2\n" +
- "a3|-a2:a3:USUAL:a2 a3:a3:USUAL:a0|-|-END_COMMIT_NODE|-a0|-3");
- }
-}
diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphBuilderTest.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphBuilderTest.java
index 1f6a8ee..ca6d93b 100644
--- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphBuilderTest.java
+++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graph/mutable/GraphBuilderTest.java
@@ -71,8 +71,7 @@
"a0|-|-a0:a1:USUAL:a0#a1 a0:a3:USUAL:a0#a3|-COMMIT_NODE|-a0|-0\n" +
"a1|-a0:a1:USUAL:a0#a1|-a1:a2:USUAL:a1#a2 a1:a3:USUAL:a1#a3|-COMMIT_NODE|-a0#a1|-1\n" +
"a2|-a1:a2:USUAL:a1#a2|-|-COMMIT_NODE|-a1#a2|-2\n" +
- " a3|-a0:a3:USUAL:a0#a3 a1:a3:USUAL:a1#a3|-a3:a3:USUAL:a0#a3|-EDGE_NODE|-a0#a3|-2\n" +
- "a3|-a3:a3:USUAL:a0#a3|-|-COMMIT_NODE|-a0#a3|-3");
+ "a3|-a0:a3:USUAL:a0#a3 a1:a3:USUAL:a1#a3|-|-COMMIT_NODE|-a0#a3|-3");
}
@Test
@@ -85,8 +84,7 @@
"a0|-|-a0:a1:USUAL:a0#a1 a0:a3:USUAL:a0#a3|-COMMIT_NODE|-a0|-0\n" +
"a1|-a0:a1:USUAL:a0#a1|-a1:a3:USUAL:a0#a1|-COMMIT_NODE|-a0#a1|-1\n" +
"a2|-|-|-COMMIT_NODE|-a2|-2\n" +
- " a3|-a0:a3:USUAL:a0#a3 a1:a3:USUAL:a0#a1|-a3:a3:USUAL:a0#a3|-EDGE_NODE|-a0#a3|-2\n" +
- "a3|-a3:a3:USUAL:a0#a3|-|-COMMIT_NODE|-a0#a3|-3");
+ "a3|-a0:a3:USUAL:a0#a3 a1:a3:USUAL:a0#a1|-|-COMMIT_NODE|-a0#a3|-3");
}
@Test
diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/GraphModelTest.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/GraphModelTest.java
index 515608c..dd6fc62 100644
--- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/GraphModelTest.java
+++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/GraphModelTest.java
@@ -1,7 +1,6 @@
package com.intellij.vcs.log.graphmodel.fragment;
import com.intellij.util.Function;
-import com.intellij.vcs.log.VcsRef;
import com.intellij.vcs.log.graph.GraphTestUtils;
import com.intellij.vcs.log.graph.elements.Node;
import com.intellij.vcs.log.graph.mutable.MutableGraph;
@@ -14,7 +13,6 @@
import org.junit.Before;
import org.junit.Test;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
@@ -35,7 +33,7 @@
@NotNull
public GraphModel buildGraphModel(@NotNull String inputGraph) {
MutableGraph graph = GraphTestUtils.getNewMutableGraph(inputGraph);
- return new GraphModelImpl(graph, Collections.<VcsRef>emptyList());
+ return new GraphModelImpl(graph);
}
@@ -116,10 +114,10 @@
* | |
* | a8
* | /
- * * a9
- * | /
- * * a10
- * | |
+ * | | a9
+ * | | /
+ * | || a10
+ * |// /
* a11 |
* | |
* a12 |
@@ -169,11 +167,9 @@
"a6|-a2:a6:USUAL:a2#a6 a5:a6:USUAL:a3|-a6:a7:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-6\n" +
"a7|-a6:a7:USUAL:a2#a6|-a7:a8:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-7\n" +
"a8|-a7:a8:USUAL:a2#a6|-a8:a11:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-8\n" +
- "a11|-a2:a11:USUAL:a2#a11 a8:a11:USUAL:a2#a6|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-9\n" +
- " a9|-|-a9:a11:USUAL:a9|-COMMIT_NODE|-a9|-9\n" +
+ "a9|-|-a9:a11:USUAL:a9|-COMMIT_NODE|-a9|-9\n" +
"a10|-|-a10:a13:USUAL:a10|-COMMIT_NODE|-a10|-10\n" +
- " a11|-a11:a11:USUAL:a2#a11 a9:a11:USUAL:a9|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-10\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-11\n" +
+ "a11|-a2:a11:USUAL:a2#a11 a8:a11:USUAL:a2#a6 a9:a11:USUAL:a9|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-11\n" +
"a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-12\n" +
"a13|-a10:a13:USUAL:a10|-a13:a14:USUAL:a10|-COMMIT_NODE|-a10|-13\n" +
"a14|-a13:a14:USUAL:a10|-a14:a15:USUAL:a10|-COMMIT_NODE|-a10|-14\n" +
@@ -286,13 +282,11 @@
"a6|-a2:a6:USUAL:a2#a6|-a6:a7:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-3\n" +
"a7|-a6:a7:USUAL:a2#a6|-a7:a8:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-4\n" +
"a8|-a7:a8:USUAL:a2#a6|-a8:a11:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-5\n" +
- "a11|-a2:a11:USUAL:a2#a11 a8:a11:USUAL:a2#a6|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-6\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-7\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-8\n" +
- "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-9\n" +
- "a15|-a12:a15:USUAL:a2#a11|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-10\n" +
- "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-11\n" +
- "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-12"
+ "a11|-a2:a11:USUAL:a2#a11 a8:a11:USUAL:a2#a6|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-6\n" +
+ "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-7\n" +
+ "a15|-a12:a15:USUAL:a2#a11|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-8\n" +
+ "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-9\n" +
+ "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-10"
);
}
@@ -314,16 +308,14 @@
"a6|-a5:a6:USUAL:a3|-a6:a7:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-3\n" +
"a7|-a6:a7:USUAL:a2#a6|-a7:a8:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-4\n" +
"a8|-a7:a8:USUAL:a2#a6|-a8:a11:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-5\n" +
- "a11|-a8:a11:USUAL:a2#a6|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-6\n" +
- "a10|-|-a10:a13:USUAL:a10|-COMMIT_NODE|-a10|-7\n" +
- " a11|-a11:a11:USUAL:a2#a11|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-7\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-8\n" +
- "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-9\n" +
- "a13|-a10:a13:USUAL:a10|-a13:a14:USUAL:a10|-COMMIT_NODE|-a10|-10\n" +
- "a14|-a13:a14:USUAL:a10|-a14:a15:USUAL:a10|-COMMIT_NODE|-a10|-11\n" +
- "a15|-a12:a15:USUAL:a2#a11 a14:a15:USUAL:a10|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-12\n" +
- "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-13\n" +
- "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-14"
+ "a10|-|-a10:a13:USUAL:a10|-COMMIT_NODE|-a10|-6\n" +
+ "a11|-a8:a11:USUAL:a2#a6|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-7\n" +
+ "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-8\n" +
+ "a13|-a10:a13:USUAL:a10|-a13:a14:USUAL:a10|-COMMIT_NODE|-a10|-9\n" +
+ "a14|-a13:a14:USUAL:a10|-a14:a15:USUAL:a10|-COMMIT_NODE|-a10|-10\n" +
+ "a15|-a12:a15:USUAL:a2#a11 a14:a15:USUAL:a10|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-11\n" +
+ "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-12\n" +
+ "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-13"
);
}
@@ -339,12 +331,11 @@
startNodes,
"a9|-|-a9:a11:USUAL:a9|-COMMIT_NODE|-a9|-0\n" +
- "a11|-a9:a11:USUAL:a9|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-1\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-2\n" +
- "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-3\n" +
- "a15|-a12:a15:USUAL:a2#a11|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-4\n" +
- "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-5\n" +
- "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-6"
+ "a11|-a9:a11:USUAL:a9|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-1\n" +
+ "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-2\n" +
+ "a15|-a12:a15:USUAL:a2#a11|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-3\n" +
+ "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-4\n" +
+ "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-5"
);
}
@@ -470,11 +461,9 @@
"a3|-|-a3:a8:HIDE_FRAGMENT:a3|-COMMIT_NODE|-a3|-0\n" +
"a8|-a3:a8:HIDE_FRAGMENT:a3|-a8:a11:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-1\n" +
- "a11|-a8:a11:USUAL:a2#a6|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-2\n" +
- " a9|-|-a9:a11:USUAL:a9|-COMMIT_NODE|-a9|-2\n" +
+ "a9|-|-a9:a11:USUAL:a9|-COMMIT_NODE|-a9|-2\n" +
"a10|-|-a10:a13:USUAL:a10|-COMMIT_NODE|-a10|-3\n" +
- " a11|-a11:a11:USUAL:a2#a11 a9:a11:USUAL:a9|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-3\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-4\n" +
+ "a11|-a8:a11:USUAL:a2#a6 a9:a11:USUAL:a9|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-4\n" +
"a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-5\n" +
"a13|-a10:a13:USUAL:a10|-a13:a14:USUAL:a10|-COMMIT_NODE|-a10|-6\n" +
"a14|-a13:a14:USUAL:a10|-a14:a15:USUAL:a10|-COMMIT_NODE|-a10|-7\n" +
@@ -527,13 +516,11 @@
"a6|-a2:a6:USUAL:a2#a6|-a6:a7:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-3\n" +
"a7|-a6:a7:USUAL:a2#a6|-a7:a8:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-4\n" +
"a8|-a7:a8:USUAL:a2#a6|-a8:a11:USUAL:a2#a6|-COMMIT_NODE|-a2#a6|-5\n" +
- "a11|-a2:a11:USUAL:a2#a11 a8:a11:USUAL:a2#a6|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-6\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a11:USUAL:a2#a11|-EDGE_NODE|-a2#a11|-7\n" +
- "a11|-a11:a11:USUAL:a2#a11|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-8\n" +
- "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-9\n" +
- "a15|-a12:a15:USUAL:a2#a11|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-10\n" +
- "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-11\n" +
- "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-12",
+ "a11|-a2:a11:USUAL:a2#a11 a8:a11:USUAL:a2#a6|-a11:a12:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-6\n" +
+ "a12|-a11:a12:USUAL:a2#a11|-a12:a15:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-7\n" +
+ "a15|-a12:a15:USUAL:a2#a11|-a15:a16:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-8\n" +
+ "a16|-a15:a16:USUAL:a2#a11|-a16:a17:USUAL:a2#a11|-COMMIT_NODE|-a2#a11|-9\n" +
+ "a17|-a16:a17:USUAL:a2#a11|-|-COMMIT_NODE|-a2#a11|-10",
toStr(hardGraph.getGraph())
);
diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentTest.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentTest.java
index 13ae93d..d5a13f8 100644
--- a/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentTest.java
+++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/graphmodel/fragment/ShortFragmentTest.java
@@ -203,11 +203,11 @@
public void edgeNodesDown() {
runTest(
"a0|-a3 a1\n" +
- "a1|-a2 a3\n" +
- "a2|-a3\n" +
- "a3|-",
+ "a1|-a2 a3\n" +
+ "a2|-a3\n" +
+ "a3|-",
0,
- "a0:0|-a1:1 a2:2 a3:2|-a3:3",
+ "a0:0|-a1:1 a2:2|-a3:3",
true
);
}
@@ -220,7 +220,7 @@
"a2|-a3\n" +
"a3|-",
3,
- "a0:0|-a1:1 a2:2 a3:2|-a3:3",
+ "a0:0|-a1:1 a2:2|-a3:3",
false
);
}
@@ -258,11 +258,11 @@
public void unhiddenEndTestDown() {
runTest(
"a0|-a3 a1\n" +
- "a1|-a2 a3\n" +
- "a2|-a3\n" +
- "a3|-",
+ "a1|-a2 a3\n" +
+ "a2|-a3\n" +
+ "a3|-",
0,
- "a0:0|-a1:1 a2:2 a3:2|-a3:3",
+ "a0:0|-a1:1 a2:2|-a3:3",
"0 3",
true
);
@@ -277,7 +277,7 @@
"a2|-a3\n" +
"a3|-",
3,
- "a0:0|-a1:1 a2:2 a3:2|-a3:3",
+ "a0:0|-a1:1 a2:2|-a3:3",
"0 3",
false
);
diff --git a/platform/vcs-log/graph/test/com/intellij/vcs/log/printmodel/cells/builder/LayoutModelBuilderTest.java b/platform/vcs-log/graph/test/com/intellij/vcs/log/printmodel/cells/builder/LayoutModelBuilderTest.java
index c1c25c6..c5a2cbd 100644
--- a/platform/vcs-log/graph/test/com/intellij/vcs/log/printmodel/cells/builder/LayoutModelBuilderTest.java
+++ b/platform/vcs-log/graph/test/com/intellij/vcs/log/printmodel/cells/builder/LayoutModelBuilderTest.java
@@ -44,7 +44,7 @@
"a3 a1:a4 a2:a8 a2:a5\n" +
"a3:a6 a4 a2:a8 a2:a5\n" +
"a3:a6 a4:a7 a2:a8 a5\n" +
- "a6 a7 a2:a8\n" +
+ "a6 a4:a7 a2:a8 a5:a7\n" +
"a7 a2:a8\n" +
"a8");
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java
index b0b402c..3ddb036 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/DataPack.java
@@ -42,7 +42,7 @@
MutableGraph graph = GraphBuilder.build(commits, allRefs);
- GraphModel graphModel = new GraphModelImpl(graph, allRefs);
+ GraphModel graphModel = new GraphModelImpl(graph);
final GraphPrintCellModel printCellModel = new GraphPrintCellModelImpl(graphModel.getGraph());
graphModel.addUpdateListener(new Consumer<UpdateRequest>() {
@@ -77,10 +77,6 @@
myIndexGetter = indexGetter;
}
- public void appendCommits(@NotNull List<GraphCommit> commitParentsList) {
- myGraphModel.appendCommitsToGraph(commitParentsList);
- }
-
@NotNull
public RefsModel getRefsModel() {
return myRefsModel;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java
index 8f79a75..98d4fe2 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/RefsModel.java
@@ -2,10 +2,12 @@
import com.intellij.openapi.util.Condition;
import com.intellij.util.NotNullFunction;
+import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsRef;
+import gnu.trove.TIntObjectHashMap;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -19,7 +21,7 @@
@NotNull private final Collection<VcsRef> myBranches;
@NotNull private final MultiMap<Hash, VcsRef> myRefsToHashes;
- @NotNull private final MultiMap<Integer, VcsRef> myRefsToIndices;
+ @NotNull private final TIntObjectHashMap<SmartList<VcsRef>> myRefsToIndices;
@NotNull private final NotNullFunction<Hash, Integer> myIndexGetter;
public RefsModel(@NotNull Collection<VcsRef> allRefs, @NotNull NotNullFunction<Hash, Integer> indexGetter) {
@@ -36,17 +38,20 @@
}
@NotNull
- private MultiMap<Integer, VcsRef> prepareRefsToIndicesMap(@NotNull Collection<VcsRef> refs) {
- MultiMap<Integer, VcsRef> map = MultiMap.create();
+ private TIntObjectHashMap<SmartList<VcsRef>> prepareRefsToIndicesMap(@NotNull Collection<VcsRef> refs) {
+ TIntObjectHashMap<SmartList<VcsRef>> map = new TIntObjectHashMap<SmartList<VcsRef>>();
for (VcsRef ref : refs) {
- map.putValue(myIndexGetter.fun(ref.getCommitHash()), ref);
+ int index = myIndexGetter.fun(ref.getCommitHash());
+ SmartList<VcsRef> list = map.get(index);
+ if (list == null) map.put(index, list = new SmartList<VcsRef>());
+ list.add(ref);
}
return map;
}
@NotNull
private static MultiMap<Hash, VcsRef> prepareRefsMap(@NotNull Collection<VcsRef> refs) {
- MultiMap<Hash, VcsRef> map = MultiMap.create();
+ MultiMap<Hash, VcsRef> map = MultiMap.createSmartList();
for (VcsRef ref : refs) {
map.putValue(ref.getCommitHash(), ref);
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java
index 90ca1e3..8872406 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogBranchFilterImpl.java
@@ -3,6 +3,7 @@
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.VcsLogBranchFilter;
+import com.intellij.vcs.log.VcsLogGraphFilter;
import com.intellij.vcs.log.VcsRef;
import org.jetbrains.annotations.NotNull;
@@ -11,14 +12,14 @@
public class VcsLogBranchFilterImpl implements VcsLogBranchFilter, VcsLogGraphFilter {
@NotNull private final Collection<Integer> myMatchingHeads;
- @NotNull private final String myBranchName;
+ @NotNull private final Collection<String> myBranchNames;
- public VcsLogBranchFilterImpl(@NotNull Collection<VcsRef> allRefs, @NotNull final String selectedBranchName) {
- myBranchName = selectedBranchName;
+ public VcsLogBranchFilterImpl(@NotNull Collection<VcsRef> allRefs, @NotNull final Collection<String> branchNames) {
+ myBranchNames = branchNames;
myMatchingHeads = ContainerUtil.mapNotNull(allRefs, new Function<VcsRef, Integer>() {
@Override
public Integer fun(VcsRef ref) {
- if (ref.getName().equals(selectedBranchName)) {
+ if (branchNames.contains(ref.getName())) {
return ref.getCommitIndex();
}
return null;
@@ -33,13 +34,13 @@
@Override
public String toString() {
- return "on: " + myBranchName;
+ return "on: " + myBranchNames;
}
@Override
@NotNull
- public String getBranchName() {
- return myBranchName;
+ public Collection<String> getBranchNames() {
+ return myBranchNames;
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
index f18697a..f5fc5f4 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDataHolder.java
@@ -298,7 +298,8 @@
}, "Loading log structure...");
}
- private List<CompactCommit> compactHashes(List<TimedVcsCommit> commits) {
+ @NotNull
+ private List<CompactCommit> compactHashes(@NotNull List<? extends TimedVcsCommit> commits) {
List<CompactCommit> compactedHashes = ContainerUtil.map(commits, new Function<TimedVcsCommit, CompactCommit>() {
@Override
public CompactCommit fun(final TimedVcsCommit commit) {
@@ -340,7 +341,7 @@
// throw new RuntimeException(e);
// }
- List<TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(myLogData.myLogsByRoot.values());
+ List<? extends TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(myLogData.myLogsByRoot.values());
DataPack fullDataPack = DataPack.build(convertToGraphCommits(compoundLog), myLogData.getAllRefs(), indicator, myHashGetter, myIndexGetter);
myLogData = new LogData(myLogData.getLogs(), myLogData.getRefs(), myLogData.getTopCommits(), fullDataPack, true);
myFullLogShowing = true;
@@ -355,7 +356,7 @@
}, "Building full log...");
}
- private List<? extends GraphCommit> convertToGraphCommits(List<TimedVcsCommit> log) {
+ private List<? extends GraphCommit> convertToGraphCommits(List<? extends TimedVcsCommit> log) {
return compactHashes(log);
}
@@ -396,10 +397,10 @@
refsByRoot.put(root, info.newRefs);
}
- List<TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(logsToBuild.values());
- List<TimedVcsCommit> topPartOfTheLog = compoundLog.subList(0, topCommitCount);
+ List<? extends TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(logsToBuild.values());
+ List<? extends TimedVcsCommit> topPartOfTheLog = compoundLog.subList(0, topCommitCount);
- List<TimedVcsCommit> logToBuild = myFullLogShowing ? compoundLog : topPartOfTheLog; // keep looking at the full log after refresh
+ List<? extends TimedVcsCommit> logToBuild = myFullLogShowing ? compoundLog : topPartOfTheLog; // keep looking at the full log after refresh
DataPack dataPack = DataPack.build(convertToGraphCommits(logToBuild), collectAllRefs(refsByRoot), indicator,
myHashGetter, myIndexGetter);
@@ -431,7 +432,7 @@
refsByRoot.put(root, info.newRefs);
}
- List<TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(logsToBuild.values());
+ List<? extends TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(logsToBuild.values());
// even if the full log was already loaded (and possibly presented to the user),
// build only the data that was retrieved from the VCS:
@@ -481,37 +482,30 @@
return myUserRegistry.getUsers();
}
- public void getFilteredDetailsFromTheVcs(final Collection<VcsLogFilter> filters, final Consumer<List<VcsFullCommitDetails>> success,
+ public void getFilteredDetailsFromTheVcs(@NotNull final VcsLogFilterCollection filterCollection,
+ @NotNull final Consumer<List<VcsFullCommitDetails>> success,
final int maxCount) {
runInBackground(new ThrowableConsumer<ProgressIndicator, VcsException>() {
@Override
public void consume(ProgressIndicator indicator) throws VcsException {
- List<VcsLogBranchFilter> branchFilters = ContainerUtil.findAll(filters, VcsLogBranchFilter.class);
- List<VcsLogUserFilter> userFilters = ContainerUtil.findAll(filters, VcsLogUserFilter.class);
- List<VcsLogDateFilter> dateFilters = ContainerUtil.findAll(filters, VcsLogDateFilter.class);
- List<VcsLogTextFilter> textFilters = ContainerUtil.findAll(filters, VcsLogTextFilter.class);
- List<VcsLogStructureFilter> structureFilters = ContainerUtil.findAll(filters, VcsLogStructureFilter.class);
-
Collection<List<? extends TimedVcsCommit>> logs = ContainerUtil.newArrayList();
final Map<Hash, VcsFullCommitDetails> allDetails = ContainerUtil.newHashMap();
for (Map.Entry<VirtualFile, VcsLogProvider> entry : myLogProviders.entrySet()) {
VirtualFile root = entry.getKey();
- List<VcsLogStructureFilter> rootMatchingStructureFilters = filterStructureFiltersByRoot(root, structureFilters);
- if (rootMatchingStructureFilters.isEmpty() && !structureFilters.isEmpty()) {
- // there were structure filters but none matches the root
+ if (filterCollection.getStructureFilter() != null && filterCollection.getStructureFilter().getFiles(root).isEmpty()) {
+ // there is a structure filter, but it doesn't match this root
continue;
}
- List<? extends VcsFullCommitDetails> details = entry.getValue().getFilteredDetails(
- root, branchFilters, userFilters, dateFilters, textFilters, rootMatchingStructureFilters, maxCount);
+ List<? extends VcsFullCommitDetails> details = entry.getValue().getFilteredDetails(root, filterCollection, maxCount);
logs.add(getCommitsFromDetails(details));
for (VcsFullCommitDetails detail : details) {
allDetails.put(detail.getHash(), detail);
}
}
- final List<TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(logs);
+ final List<? extends TimedVcsCommit> compoundLog = myMultiRepoJoiner.join(logs);
final List<VcsFullCommitDetails> list = ContainerUtil.mapNotNull(compoundLog, new Function<TimedVcsCommit, VcsFullCommitDetails>() {
@Override
@@ -768,12 +762,12 @@
private static class LogData {
@NotNull private final Map<VirtualFile, List<? extends TimedVcsCommit>> myLogsByRoot;
@NotNull private final Map<VirtualFile, Collection<VcsRef>> myRefsByRoot;
- @NotNull private final List<TimedVcsCommit> myCompoundTopCommits;
+ @NotNull private final List<? extends TimedVcsCommit> myCompoundTopCommits;
@NotNull private final DataPack myDataPack;
private final boolean myFullLog;
private LogData(@NotNull Map<VirtualFile, List<? extends TimedVcsCommit>> logsByRoot,
- @NotNull Map<VirtualFile, Collection<VcsRef>> refsByRoot, @NotNull List<TimedVcsCommit> compoundTopCommits,
+ @NotNull Map<VirtualFile, Collection<VcsRef>> refsByRoot, @NotNull List<? extends TimedVcsCommit> compoundTopCommits,
@NotNull DataPack dataPack, boolean fullLog) {
myLogsByRoot = logsByRoot;
myRefsByRoot = refsByRoot;
@@ -825,7 +819,7 @@
}
@NotNull
- public List<TimedVcsCommit> getTopCommits() {
+ public List<? extends TimedVcsCommit> getTopCommits() {
return myCompoundTopCommits;
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java
index c879ddd..439f319 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDateFilterImpl.java
@@ -17,6 +17,7 @@
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLogDateFilter;
+import com.intellij.vcs.log.VcsLogDetailsFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDetailsFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDetailsFilter.java
deleted file mode 100644
index 3d34cbf..0000000
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogDetailsFilter.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.intellij.vcs.log.data;
-
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLogFilter;
-import org.jetbrains.annotations.NotNull;
-
-/**
- * Filter which needs {@link VcsFullCommitDetails} to work.
- *
- * @see VcsLogGraphFilter
- */
-public interface VcsLogDetailsFilter extends VcsLogFilter {
-
- boolean matches(@NotNull VcsFullCommitDetails details);
-
-}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java
index da4d79d..e3b22ce 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogFilterer.java
@@ -9,8 +9,7 @@
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
-import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLogFilter;
+import com.intellij.vcs.log.*;
import com.intellij.vcs.log.graph.elements.Node;
import com.intellij.vcs.log.graphmodel.GraphModel;
import com.intellij.vcs.log.ui.VcsLogUI;
@@ -20,7 +19,6 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Collection;
import java.util.List;
public class VcsLogFilterer {
@@ -44,11 +42,11 @@
myUI = ui;
}
- public void applyFiltersAndUpdateUi(@NotNull Collection<VcsLogFilter> filters) {
+ public void applyFiltersAndUpdateUi(@NotNull VcsLogFilterCollection filters) {
DataPack dataPack = myLogDataHolder.getDataPack();
final GraphModel graphModel = dataPack.getGraphModel();
- List<VcsLogGraphFilter> graphFilters = ContainerUtil.findAll(filters, VcsLogGraphFilter.class);
- List<VcsLogDetailsFilter> detailsFilters = ContainerUtil.findAll(filters, VcsLogDetailsFilter.class);
+ List<VcsLogGraphFilter> graphFilters = filters.getGraphFilters();
+ List<VcsLogDetailsFilter> detailsFilters = filters.getDetailsFilters();
// it is important to apply graph filters first:
// if we apply other filters first, we loose the graph and won't be able to apple graph filters in that case
@@ -94,15 +92,9 @@
});
}
- public void requestVcs(@NotNull Collection<VcsLogFilter> filters, final LoadMoreStage loadMoreStage, @NotNull final Runnable onSuccess) {
+ public void requestVcs(@NotNull VcsLogFilterCollection filters, final LoadMoreStage loadMoreStage, @NotNull final Runnable onSuccess) {
ApplicationManager.getApplication().assertIsDispatchThread();
- int maxCount;
- if (loadMoreStage == LoadMoreStage.INITIAL) {
- maxCount = LOAD_MORE_COMMITS_FIRST_STEP_LIMIT;
- }
- else {
- maxCount = -1;
- }
+ int maxCount = loadMoreStage == LoadMoreStage.INITIAL ? LOAD_MORE_COMMITS_FIRST_STEP_LIMIT : -1;
myLogDataHolder.getFilteredDetailsFromTheVcs(filters, new Consumer<List<VcsFullCommitDetails>>() {
@Override
public void consume(List<VcsFullCommitDetails> details) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogGraphFilter.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogGraphFilter.java
deleted file mode 100644
index 5734dc0..0000000
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogGraphFilter.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.intellij.vcs.log.data;
-
-import com.intellij.vcs.log.VcsLogFilter;
-
-/**
- * Filter that is able to work on graph.
- */
-public interface VcsLogGraphFilter extends VcsLogFilter {
-
- boolean matches(int hash);
-
-}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
index 3bcd247..5a39f4c 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogMultiRepoJoiner.java
@@ -12,7 +12,11 @@
class VcsLogMultiRepoJoiner {
@NotNull
- public List<TimedVcsCommit> join(@NotNull Collection<List<? extends TimedVcsCommit>> logsFromRepos) {
+ public List<? extends TimedVcsCommit> join(@NotNull Collection<List<? extends TimedVcsCommit>> logsFromRepos) {
+ if (logsFromRepos.size() == 1) {
+ return logsFromRepos.iterator().next();
+ }
+
int size = 0;
for (List<? extends TimedVcsCommit> repo : logsFromRepos) {
size += repo.size();
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
index 678cfd6..69ed7b5 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/data/VcsLogStructureFilterImpl.java
@@ -24,6 +24,7 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLogDetailsFilter;
import com.intellij.vcs.log.VcsLogStructureFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -35,12 +36,14 @@
@NotNull private final Collection<VirtualFile> myFiles;
@NotNull private final MultiMap<VirtualFile, VirtualFile> myFilesByRoots;
- public VcsLogStructureFilterImpl(@NotNull Collection<VirtualFile> files, Collection<VirtualFile> roots) {
+ public VcsLogStructureFilterImpl(@NotNull Collection<VirtualFile> files, @NotNull Collection<VirtualFile> roots) {
myFiles = files;
myFilesByRoots = groupFilesByVcsRoots(files, roots);
}
- private static MultiMap<VirtualFile, VirtualFile> groupFilesByVcsRoots(Collection<VirtualFile> files, Collection<VirtualFile> roots) {
+ @NotNull
+ private static MultiMap<VirtualFile, VirtualFile> groupFilesByVcsRoots(@NotNull Collection<VirtualFile> files,
+ @NotNull Collection<VirtualFile> roots) {
MultiMap<VirtualFile, VirtualFile> grouped = MultiMap.create();
for (VirtualFile file : files) {
VirtualFile root = findBestRoot(file, roots);
@@ -79,7 +82,7 @@
return false;
}
- private boolean matches(final String path) {
+ private boolean matches(@NotNull final String path) {
return ContainerUtil.find(myFiles, new Condition<VirtualFile>() {
@Override
public boolean value(VirtualFile file) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.java
new file mode 100644
index 0000000..4920a4e
--- /dev/null
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/impl/VcsLogFilterCollectionImpl.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 com.intellij.vcs.log.impl;
+
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.vcs.log.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+public class VcsLogFilterCollectionImpl implements VcsLogFilterCollection {
+
+ @Nullable private final VcsLogBranchFilter myBranchFilter;
+ @Nullable private final VcsLogUserFilter myUserFilter;
+ @Nullable private final VcsLogDateFilter myDateFilter;
+ @Nullable private final VcsLogTextFilter myTextFilter;
+ @Nullable private final VcsLogStructureFilter myStructureFilter;
+
+ public VcsLogFilterCollectionImpl(@Nullable VcsLogBranchFilter branchFilter,
+ @Nullable VcsLogUserFilter userFilter,
+ @Nullable VcsLogDateFilter dateFilter,
+ @Nullable VcsLogTextFilter textFilter,
+ @Nullable VcsLogStructureFilter structureFilter) {
+ myBranchFilter = branchFilter;
+ myUserFilter = userFilter;
+ myDateFilter = dateFilter;
+ myTextFilter = textFilter;
+ myStructureFilter = structureFilter;
+ }
+
+ @Nullable
+ @Override
+ public VcsLogBranchFilter getBranchFilter() {
+ return myBranchFilter;
+ }
+
+ @Nullable
+ @Override
+ public VcsLogUserFilter getUserFilter() {
+ return myUserFilter;
+ }
+
+ @Nullable
+ @Override
+ public VcsLogDateFilter getDateFilter() {
+ return myDateFilter;
+ }
+
+ @Nullable
+ @Override
+ public VcsLogTextFilter getTextFilter() {
+ return myTextFilter;
+ }
+
+ @Nullable
+ @Override
+ public VcsLogStructureFilter getStructureFilter() {
+ return myStructureFilter;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return getGraphFilters().isEmpty() && getDetailsFilters().isEmpty();
+ }
+
+ @NotNull
+ @Override
+ public List<VcsLogGraphFilter> getGraphFilters() {
+ return ContainerUtil.skipNulls(Collections.<VcsLogGraphFilter>singletonList(myBranchFilter));
+ }
+
+ @NotNull
+ @Override
+ public List<VcsLogDetailsFilter> getDetailsFilters() {
+ return ContainerUtil.skipNulls(Arrays.asList(myUserFilter, myDateFilter, myTextFilter, myStructureFilter));
+ }
+
+}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
index 95d1631..cda36e4 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsLogUI.java
@@ -10,7 +10,7 @@
import com.intellij.util.ui.UIUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsLog;
-import com.intellij.vcs.log.VcsLogFilter;
+import com.intellij.vcs.log.VcsLogFilterCollection;
import com.intellij.vcs.log.VcsLogSettings;
import com.intellij.vcs.log.compressedlist.UpdateRequest;
import com.intellij.vcs.log.data.DataPack;
@@ -31,7 +31,6 @@
import javax.swing.table.TableModel;
import java.awt.*;
-import java.util.Collection;
import java.util.Set;
/**
@@ -326,7 +325,7 @@
}
@NotNull
- public Collection<VcsLogFilter> collectFilters() {
+ public VcsLogFilterCollection collectFilters() {
return myMainFrame.getFilterUi().getFilters();
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsStructureChooser.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsStructureChooser.java
index 31ee7f9..0cbb65b 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsStructureChooser.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/VcsStructureChooser.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -202,7 +202,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
int row = myTree.getRowForLocation(e.getX(), e.getY());
if (row < 0) return false;
final Object o = myTree.getPathForRow(row).getLastPathComponent();
@@ -300,7 +300,7 @@
if (idx != null && idx.length > 0) {
final int answer = Messages
.showYesNoDialog(myProject, "Remove selected paths from filter?", "Remove from filter", Messages.getQuestionIcon());
- if (Messages.OK == answer) {
+ if (Messages.YES == answer) {
Arrays.sort(idx);
for (int i = idx.length - 1; i >= 0; --i) {
int i1 = idx[i];
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java
index aa7f1f9..2a42b6e 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/BranchFilterPopupComponent.java
@@ -28,7 +28,7 @@
import java.util.*;
-class BranchFilterPopupComponent extends FilterPopupComponent {
+class BranchFilterPopupComponent extends FilterPopupComponent<VcsLogBranchFilter> {
@NotNull private final VcsLogUI myUi;
@@ -124,10 +124,10 @@
@Nullable
@Override
- protected Collection<VcsLogFilter> getFilters() {
+ protected VcsLogBranchFilter getFilter() {
String value = getValue();
Collection<VcsRef> allBranches = myUi.getLogDataHolder().getDataPack().getRefsModel().getBranches();
- return value == ALL ? null : Collections.<VcsLogFilter>singleton(new VcsLogBranchFilterImpl(allBranches, value));
+ return value == ALL ? null : new VcsLogBranchFilterImpl(allBranches, Collections.singletonList(value));
}
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java
index abac979..855b926 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/DateFilterPopupComponent.java
@@ -23,17 +23,15 @@
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.versionBrowser.DateFilterComponent;
import com.intellij.util.text.DateFormatUtil;
-import com.intellij.vcs.log.VcsLogFilter;
+import com.intellij.vcs.log.VcsLogDateFilter;
import com.intellij.vcs.log.data.VcsLogDateFilterImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Calendar;
-import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
-class DateFilterPopupComponent extends FilterPopupComponent {
+class DateFilterPopupComponent extends FilterPopupComponent<VcsLogDateFilter> {
private Date myAfter;
private Date myBefore;
@@ -68,8 +66,8 @@
@Nullable
@Override
- protected Collection<VcsLogFilter> getFilters() {
- return myAfter == null && myBefore == null ? null : Collections.<VcsLogFilter>singleton(new VcsLogDateFilterImpl(myAfter, myBefore));
+ protected VcsLogDateFilter getFilter() {
+ return myAfter == null && myBefore == null ? null : new VcsLogDateFilterImpl(myAfter, myBefore);
}
private void setOnlyAfter(Date after) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java
index f8b3148..fa7ad5a 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/FilterPopupComponent.java
@@ -33,12 +33,11 @@
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.event.*;
-import java.util.Collection;
/**
* Base class for components which allow to set up filter for the VCS Log, by displaying a popup with available choices.
*/
-abstract class FilterPopupComponent extends JPanel {
+abstract class FilterPopupComponent<Filter extends VcsLogFilter> extends JPanel {
/**
* Special value that indicates that no filtering is on.
@@ -91,11 +90,10 @@
protected abstract ActionGroup createActionGroup();
/**
- * Return the filters (which would be concatenated with OR) currently selected via this component.</br>
- * Or return null if no filters are selected via this component.
+ * Return the filter currently selected via this component or null if no filters are selected via this component.
*/
@Nullable
- protected abstract Collection<VcsLogFilter> getFilters();
+ protected abstract Filter getFilter();
protected void setValue(@NotNull String newValue) {
setValue(newValue, newValue);
@@ -150,7 +148,7 @@
private void showPopupMenuOnClick() {
new ClickListener() {
@Override
- public boolean onClick(MouseEvent event, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent event, int clickCount) {
showPopupMenu();
return true;
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
index ab5d4dd..6925e52 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/StructureFilterPopupComponent.java
@@ -23,7 +23,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.vcs.log.VcsLogFilter;
+import com.intellij.vcs.log.VcsLogStructureFilter;
import com.intellij.vcs.log.data.VcsLogStructureFilterImpl;
import com.intellij.vcs.log.ui.VcsStructureChooser;
import org.jetbrains.annotations.NotNull;
@@ -33,7 +33,7 @@
import java.util.Collection;
import java.util.Collections;
-class StructureFilterPopupComponent extends FilterPopupComponent {
+class StructureFilterPopupComponent extends FilterPopupComponent<VcsLogStructureFilter> {
public static final int FILTER_LABEL_LENGTH = 20;
@NotNull private final Collection<VirtualFile> myRoots;
@@ -52,8 +52,8 @@
@Nullable
@Override
- protected Collection<VcsLogFilter> getFilters() {
- return getValue() == ALL || myFiles.isEmpty() ? null : Collections.<VcsLogFilter>singleton(new VcsLogStructureFilterImpl(myFiles, myRoots));
+ protected VcsLogStructureFilter getFilter() {
+ return getValue() == ALL || myFiles.isEmpty() ? null : new VcsLogStructureFilterImpl(myFiles, myRoots);
}
private void setValue(@NotNull Collection<VirtualFile> files) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java
index 102d32e..cd03743 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/UserFilterPopupComponent.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.*;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.spellchecker.ui.SpellCheckingEditorCustomization;
@@ -35,10 +36,8 @@
import com.intellij.util.TextFieldCompletionProviderDumbAware;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.VcsFullCommitDetails;
-import com.intellij.vcs.log.VcsLogFilter;
import com.intellij.vcs.log.VcsUser;
import com.intellij.vcs.log.data.VcsLogDataHolder;
-import com.intellij.vcs.log.data.VcsLogDetailsFilter;
import com.intellij.vcs.log.data.VcsLogUiProperties;
import com.intellij.vcs.log.VcsLogUserFilter;
import org.jetbrains.annotations.NotNull;
@@ -53,7 +52,7 @@
/**
* Show a popup to select a user or enter the user name.
*/
-class UserFilterPopupComponent extends FilterPopupComponent {
+class UserFilterPopupComponent extends FilterPopupComponent<VcsLogUserFilter> {
private static final String ME = "me";
private static final char[] USERS_SEPARATORS = { ',', '|', '\n' };
@@ -96,17 +95,12 @@
@Nullable
@Override
- protected Collection<VcsLogFilter> getFilters() {
+ protected VcsLogUserFilter getFilter() {
if (mySelectedUsers == null) {
return null;
}
myUiProperties.addRecentlyFilteredUserGroup(new ArrayList<String>(mySelectedUsers));
- return ContainerUtil.map(mySelectedUsers, new Function<String, VcsLogFilter>() {
- @Override
- public VcsLogFilter fun(String name) {
- return name == ME ? new Me(myDataHolder.getCurrentUser()) : new ByName(name);
- }
- });
+ return new VcsLogUserFilterImpl(mySelectedUsers, myDataHolder.getCurrentUser());
}
private void apply(Collection<String> users, String text, String tooltip) {
@@ -269,53 +263,38 @@
}
}
- /**
- * Filters by the given name or part of it.
- */
- public static class ByName implements VcsLogUserFilter, VcsLogDetailsFilter {
+ private static class VcsLogUserFilterImpl implements VcsLogUserFilter {
- @NotNull private final String myUser;
+ @NotNull private final Collection<String> myUsers;
+ @NotNull private final Map<VirtualFile, VcsUser> myData;
- public ByName(@NotNull String user) {
- myUser = user;
- }
-
- @Override
- public boolean matches(@NotNull VcsFullCommitDetails detail) {
- return detail.getAuthor().getName().toLowerCase().contains(myUser.toLowerCase()) ||
- detail.getAuthor().getEmail().toLowerCase().contains(myUser.toLowerCase());
+ public VcsLogUserFilterImpl(@NotNull Collection<String> users, @NotNull Map<VirtualFile, VcsUser> meData) {
+ myUsers = users;
+ myData = meData;
}
@NotNull
@Override
- public String getUserName(@NotNull VirtualFile root) {
- return myUser;
- }
- }
-
- /**
- * Looks for commits matching the current user,
- * i.e. looks for the value stored in the VCS config and compares the configured name with the one returned in commit details.
- */
- public static class Me implements VcsLogUserFilter, VcsLogDetailsFilter {
-
- @NotNull private final Map<VirtualFile, VcsUser> myMeData;
-
- public Me(@NotNull Map<VirtualFile, VcsUser> meData) {
- myMeData = meData;
+ public Collection<String> getUserNames(@NotNull final VirtualFile root) {
+ return ContainerUtil.map(myUsers, new Function<String, String>() {
+ @Override
+ public String fun(String user) {
+ return ME.equals(user) ? myData.get(root).getName() : user;
+ }
+ });
}
@Override
- public boolean matches(@NotNull VcsFullCommitDetails details) {
- VcsUser meInThisRoot = myMeData.get(details.getRoot());
- return meInThisRoot != null && meInThisRoot.equals(details.getAuthor());
+ public boolean matches(@NotNull final VcsFullCommitDetails commit) {
+ return ContainerUtil.exists(getUserNames(commit.getRoot()), new Condition<String>() {
+ @Override
+ public boolean value(String user) {
+ String lowerUser = user.toLowerCase();
+ return commit.getAuthor().getName().toLowerCase().contains(lowerUser) ||
+ commit.getAuthor().getEmail().toLowerCase().contains(lowerUser);
+ }
+ });
}
- @NotNull
- @Override
- public String getUserName(@NotNull VirtualFile root) {
- return myMeData.get(root).getName();
- }
}
-
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
index 3cdf018..6d66cc7 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogClassicFilterUi.java
@@ -23,28 +23,30 @@
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.ui.SearchTextField;
import com.intellij.ui.SearchTextFieldWithStoredHistory;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
-import com.intellij.vcs.log.VcsLogFilter;
+import com.intellij.vcs.log.VcsLogFilterCollection;
+import com.intellij.vcs.log.VcsLogTextFilter;
+import com.intellij.vcs.log.impl.VcsLogFilterCollectionImpl;
import com.intellij.vcs.log.ui.VcsLogUI;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
/**
*/
public class VcsLogClassicFilterUi implements VcsLogFilterUi {
- @NotNull private final List<FilterPopupComponent> myFilterPopupComponents;
@NotNull private final SearchTextField myTextFilter;
@NotNull private final VcsLogUI myUi;
@NotNull private final DefaultActionGroup myActionGroup;
+ @NotNull private final BranchFilterPopupComponent myBranchFilterComponent;
+ @NotNull private final UserFilterPopupComponent myUserFilterComponent;
+ @NotNull private final DateFilterPopupComponent myDateFilterComponent;
+ @NotNull private final StructureFilterPopupComponent myStructureFilterComponent;
+
public VcsLogClassicFilterUi(@NotNull VcsLogUI ui) {
myUi = ui;
@@ -57,23 +59,17 @@
}
});
- FilterPopupComponent branchFilter = new BranchFilterPopupComponent(this, ui);
- FilterPopupComponent userFilter = new UserFilterPopupComponent(this, ui.getLogDataHolder(), ui.getUiProperties());
- FilterPopupComponent dateFilter = new DateFilterPopupComponent(this);
- FilterPopupComponent structureFilter = new StructureFilterPopupComponent(this, ui.getLogDataHolder().getRoots());
-
- myFilterPopupComponents = ContainerUtil.newArrayList();
- myFilterPopupComponents.add(branchFilter);
- myFilterPopupComponents.add(userFilter);
- myFilterPopupComponents.add(dateFilter);
- myFilterPopupComponents.add(structureFilter);
+ myBranchFilterComponent = new BranchFilterPopupComponent(this, ui);
+ myUserFilterComponent = new UserFilterPopupComponent(this, ui.getLogDataHolder(), ui.getUiProperties());
+ myDateFilterComponent = new DateFilterPopupComponent(this);
+ myStructureFilterComponent = new StructureFilterPopupComponent(this, ui.getLogDataHolder().getRoots());
myActionGroup = new DefaultActionGroup();
myActionGroup.add(new TextFilterComponent(myTextFilter));
- myActionGroup.add(new FilterActionComponent(branchFilter));
- myActionGroup.add(new FilterActionComponent(userFilter));
- myActionGroup.add(new FilterActionComponent(dateFilter));
- myActionGroup.add(new FilterActionComponent(structureFilter));
+ myActionGroup.add(new FilterActionComponent(myBranchFilterComponent));
+ myActionGroup.add(new FilterActionComponent(myUserFilterComponent));
+ myActionGroup.add(new FilterActionComponent(myDateFilterComponent));
+ myActionGroup.add(new FilterActionComponent(myStructureFilterComponent));
}
@Override
@@ -83,24 +79,10 @@
@NotNull
@Override
- public Collection<VcsLogFilter> getFilters() {
- List<VcsLogFilter> filters = getPopupFilters();
- if (!myTextFilter.getText().isEmpty()) {
- filters.add(new VcsLogTextFilterImpl(myTextFilter.getText()));
- }
- return filters;
- }
-
- @NotNull
- private List<VcsLogFilter> getPopupFilters() {
- List<VcsLogFilter> filters = new ArrayList<VcsLogFilter>();
- for (FilterPopupComponent popupComponent : myFilterPopupComponents) {
- Collection<VcsLogFilter> popupFilters = popupComponent.getFilters();
- if (popupFilters != null) {
- filters.addAll(popupFilters);
- }
- }
- return filters;
+ public VcsLogFilterCollection getFilters() {
+ VcsLogTextFilter textFilter = !myTextFilter.getText().isEmpty() ? new VcsLogTextFilterImpl(myTextFilter.getText()) : null;
+ return new VcsLogFilterCollectionImpl(myBranchFilterComponent.getFilter(), myUserFilterComponent.getFilter(),
+ myDateFilterComponent.getFilter(), textFilter, myStructureFilterComponent.getFilter());
}
void applyFilters() {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java
index dec8917..ff43d30 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogFilterUi.java
@@ -1,11 +1,9 @@
package com.intellij.vcs.log.ui.filter;
import com.intellij.openapi.actionSystem.ActionGroup;
-import com.intellij.vcs.log.VcsLogFilter;
+import com.intellij.vcs.log.VcsLogFilterCollection;
import org.jetbrains.annotations.NotNull;
-import java.util.Collection;
-
/**
* Graphical UI for filtering commits in the log.
*
@@ -22,6 +20,6 @@
* Returns the filters currently active, i.e. switched on by user.
*/
@NotNull
- Collection<VcsLogFilter> getFilters();
+ VcsLogFilterCollection getFilters();
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java
index 64bb6ea..fa7363c 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/filter/VcsLogTextFilterImpl.java
@@ -17,7 +17,7 @@
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLogTextFilter;
-import com.intellij.vcs.log.data.VcsLogDetailsFilter;
+import com.intellij.vcs.log.VcsLogDetailsFilter;
import org.jetbrains.annotations.NotNull;
public class VcsLogTextFilterImpl implements VcsLogDetailsFilter, VcsLogTextFilter {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java
index 26e6eec..04b00e0 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/DetailsPanel.java
@@ -23,6 +23,7 @@
import com.intellij.vcs.log.ui.VcsLogColorManager;
import com.intellij.vcs.log.ui.render.RefPainter;
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
+import net.miginfocom.swing.MigLayout;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -63,14 +64,24 @@
myContainingBranchesPanel = new ContainingBranchesPanel();
myMessagePanel = new MessagePanel();
- Box content = Box.createVerticalBox();
- content.add(myRefsPanel);
- content.add(myDataPanel);
- content.add(myContainingBranchesPanel);
+ final JScrollPane scrollPane = ScrollPaneFactory.createScrollPane();
+ JPanel content = new JPanel(new MigLayout("flowy, ins 0, fill, hidemode 3")) {
+ @Override
+ public Dimension getPreferredSize() {
+ Dimension size = super.getPreferredSize();
+ size.width = scrollPane.getViewport().getWidth() - 5;
+ return size;
+ }
+ };
+ content.setOpaque(false);
+ scrollPane.setViewportView(content);
+ content.add(myRefsPanel, "shrinky, pushx, growx");
+ content.add(myDataPanel, "growy, push");
+ content.add(myContainingBranchesPanel, "shrinky, pushx, growx");
content.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
myLoadingPanel = new JBLoadingPanel(new BorderLayout(), logDataHolder, ProgressWindow.DEFAULT_PROGRESS_DIALOG_POSTPONE_TIME_MILLIS);
- myLoadingPanel.add(ScrollPaneFactory.createScrollPane(content));
+ myLoadingPanel.add(scrollPane);
add(myLoadingPanel, STANDARD_LAYER);
add(myMessagePanel, MESSAGE_LAYER);
@@ -153,8 +164,10 @@
}
private String getMessageText(VcsFullCommitDetails commit) {
- String subject = commit.getSubject();
- String description = subject.length() < commit.getFullMessage().length() ? commit.getFullMessage().substring(subject.length()) : "";
+ String fullMessage = commit.getFullMessage();
+ int separator = fullMessage.indexOf("\n\n");
+ String subject = separator > 0 ? fullMessage.substring(0, separator) : fullMessage;
+ String description = fullMessage.substring(subject.length());
return "<b>" + IssueLinkHtmlRenderer.formatTextWithLinks(myProject, subject) + "</b>" +
IssueLinkHtmlRenderer.formatTextWithLinks(myProject, description);
}
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java
index 330474d..3532137 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/frame/VcsLogGraphTable.java
@@ -116,7 +116,7 @@
}
@Override
- public void setModel(TableModel model) {
+ public void setModel(@NotNull TableModel model) {
super.setModel(model);
// initialize sizes once, when the real model is set (not from the constructor).
if (!myColumnsSizeInitialized && !(model instanceof DefaultTableModel)) {
@@ -222,7 +222,6 @@
public List<Change> getSelectedChanges() {
TableModel model = getModel();
if (!(model instanceof AbstractVcsLogTableModel)) {
- LOG.error("Unexpected table model passed to the VcsLogGraphTable: " + model);
return null;
}
List<Change> changes = ((AbstractVcsLogTableModel)model).getSelectedChanges(sortSelectedRows());
@@ -318,6 +317,7 @@
Node jumpToNode = arrowToNode(e);
if (jumpToNode != null) {
jumpToRow(jumpToNode.getRowIndex());
+ return;
}
GraphElement graphElement = overCell(e);
myUI.click(graphElement);
@@ -337,7 +337,12 @@
else {
setCursor(DEFAULT_CURSOR);
}
- myUI.over(overCell(e));
+
+ if (jumpToNode == null) {
+ myUI.over(overCell(e));
+ } else {
+ myUI.over(null);
+ }
}
private boolean isAboveLink(MouseEvent e) {
diff --git a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java
index 5b253d7..12c7600 100644
--- a/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java
+++ b/platform/vcs-log/impl/src/com/intellij/vcs/log/ui/render/GraphCommitCellRender.java
@@ -38,6 +38,9 @@
*/
public class GraphCommitCellRender extends AbstractPaddingCellRender {
+ // In case of diagonal edges, one node can be at most 3 "arrows" + 2 nodes at the left from another - that is enough for sure
+ private static final int IMAGE_WIDTH_RESERVE = 5 * WIDTH_NODE;
+
@NotNull private final GraphCellPainter graphPainter;
@NotNull private final VcsLogDataHolder myDataHolder;
@@ -82,7 +85,7 @@
return;
}
- int width = calcPaddingBeforeText(cell, (Graphics2D)g);
+ int width = calcPaddingBeforeText(cell, (Graphics2D)g) + IMAGE_WIDTH_RESERVE;
BufferedImage image = UIUtil.createImage(width, HEIGHT_CELL, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = image.createGraphics();
diff --git a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogMultiRepoJoinerTest.java b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogMultiRepoJoinerTest.java
index ce48e73..f816acb 100644
--- a/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogMultiRepoJoinerTest.java
+++ b/platform/vcs-log/impl/test/com/intellij/vcs/log/data/VcsLogMultiRepoJoinerTest.java
@@ -22,7 +22,7 @@
List<TimedVcsCommit> expected = log("7|-c1|-c0", "6|-a2|-a0", "5|-c0|-", "4|-b1|-b0", "3|-a1|-a0", "2|-b0|-", "1|-a0|-");
- List<TimedVcsCommit> joined = new VcsLogMultiRepoJoiner().join(Arrays.asList(first, second, third));
+ List<? extends TimedVcsCommit> joined = new VcsLogMultiRepoJoiner().join(Arrays.asList(first, second, third));
assertEquals(expected, joined);
}
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
index 62e2892..6a116d2 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugProcess.java
@@ -59,6 +59,7 @@
/**
* @return breakpoint handlers which will be used to set/clear breakpoints in the underlying debugging process
*/
+ @NotNull
public XBreakpointHandler<?>[] getBreakpointHandlers() {
return XBreakpointHandler.EMPTY_ARRAY;
}
@@ -142,6 +143,13 @@
return true;
}
+ /**
+ * Check is it is possible to init breakpoints. Otherwise you should call {@link XDebugSession#initBreakpoints()} at the appropriate time
+ */
+ public boolean checkCanInitBreakpoints() {
+ return true;
+ }
+
@Nullable
protected ProcessHandler doGetProcessHandler() {
return null;
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
index 48abf0f..5345458 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebugSession.java
@@ -155,6 +155,11 @@
void setPauseActionSupported(boolean isSupported);
+ @SuppressWarnings("UnusedDeclaration")
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 14
+ */
void setAutoInitBreakpoints(boolean value);
void rebuildViews();
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerBundle.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerBundle.java
index c1bfe06..a9594ca 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerBundle.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,24 +29,23 @@
* @author nik
*/
public class XDebuggerBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
@NonNls private static final String BUNDLE = "messages.XDebuggerBundle";
private static Reference<ResourceBundle> ourBundle;
private XDebuggerBundle() {
}
- public static String message(@NonNls @PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
}
return bundle;
}
-
}
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerUtil.java b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerUtil.java
index c4b56d6..e33bcaf 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerUtil.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/XDebuggerUtil.java
@@ -108,4 +108,7 @@
* @param processor processor
*/
public abstract void iterateLine(@NotNull Project project, @NotNull Document document, int line, @NotNull Processor<PsiElement> processor);
+
+ @Nullable
+ public abstract PsiElement findContextElement(@NotNull VirtualFile virtualFile, int offset, @NotNull Project project, boolean checkXml);
}
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java
index 74bc38e..1d0d5b5 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/XBreakpointType.java
@@ -131,6 +131,11 @@
return null;
}
+ @Nullable
+ public XBreakpointCustomPropertiesPanel<B> createCustomRightPropertiesPanel(@NotNull Project project) {
+ return null;
+ }
+
/**
* @deprecated override {@link #getEditorsProvider(B, com.intellij.openapi.project.Project)} instead
*/
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/XBreakpointCustomPropertiesPanel.java b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/XBreakpointCustomPropertiesPanel.java
index 5f6f354..6cc3525 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/XBreakpointCustomPropertiesPanel.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/breakpoints/ui/XBreakpointCustomPropertiesPanel.java
@@ -35,4 +35,8 @@
public void dispose() {
}
+
+ public boolean isVisibleOnPopup(@NotNull B breakpoint) {
+ return true;
+ }
}
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEditorsProviderBase.java b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEditorsProviderBase.java
index bedb621..6a593ab 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEditorsProviderBase.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/evaluation/XDebuggerEditorsProviderBase.java
@@ -1,10 +1,12 @@
package com.intellij.xdebugger.evaluation;
import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XSourcePosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -26,41 +28,8 @@
protected abstract PsiFile createExpressionCodeFragment(@NotNull Project project, @NotNull String text, @Nullable PsiElement context, boolean isPhysical);
+ @Nullable
protected PsiElement getContextElement(@NotNull VirtualFile virtualFile, int offset, @NotNull Project project) {
- return doGetContextElement(virtualFile, offset, project);
- }
-
- public static PsiElement doGetContextElement(@NotNull VirtualFile virtualFile, int offset, @NotNull Project project) {
- Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
- PsiFile file = PsiManager.getInstance(project).findFile(virtualFile);
- if (file == null || document == null) {
- return null;
- }
-
- if (offset < 0) {
- offset = 0;
- }
- if (offset > document.getTextLength()) {
- offset = document.getTextLength();
- }
- int startOffset = offset;
-
- int lineEndOffset = document.getLineEndOffset(document.getLineNumber(offset));
- PsiElement result = null;
- do {
- PsiElement element = file.findElementAt(offset);
- if (!(element instanceof PsiWhiteSpace) && !(element instanceof PsiComment)) {
- result = element;
- break;
- }
-
- offset = element.getTextRange().getEndOffset() + 1;
- }
- while (offset < lineEndOffset);
-
- if (result == null) {
- result = file.findElementAt(startOffset);
- }
- return result;
+ return XDebuggerUtil.getInstance().findContextElement(virtualFile, offset, project, false);
}
}
\ No newline at end of file
diff --git a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java
index 621e59b..0cda555 100644
--- a/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java
+++ b/platform/xdebugger-api/src/com/intellij/xdebugger/frame/XDebuggerTreeNodeHyperlink.java
@@ -24,6 +24,8 @@
* Describes a hyperlink inside a debugger node
*/
public abstract class XDebuggerTreeNodeHyperlink {
+ public static final SimpleTextAttributes TEXT_ATTRIBUTES = SimpleTextAttributes.GRAY_ATTRIBUTES;
+
private final String linkText;
protected XDebuggerTreeNodeHyperlink(@NotNull String linkText) {
@@ -37,7 +39,7 @@
@NotNull
public SimpleTextAttributes getTextAttributes() {
- return SimpleTextAttributes.GRAY_ATTRIBUTES;
+ return TEXT_ATTRIBUTES;
}
public abstract void onClick(MouseEvent event);
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 eedd2e3..bb07eea 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.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.
@@ -158,13 +158,13 @@
}
@Override
- public void setPauseActionSupported(final boolean isSupported) {
- myPauseActionSupported = isSupported;
+ public void setAutoInitBreakpoints(boolean value) {
+ autoInitBreakpoints = value;
}
@Override
- public void setAutoInitBreakpoints(boolean value) {
- autoInitBreakpoints = value;
+ public void setPauseActionSupported(final boolean isSupported) {
+ myPauseActionSupported = isSupported;
}
public List<AnAction> getRestartActions() {
@@ -236,7 +236,7 @@
myDebugProcess = process;
mySessionData = sessionData;
- if (autoInitBreakpoints) {
+ if (autoInitBreakpoints && myDebugProcess.checkCanInitBreakpoints()) {
initBreakpoints();
}
@@ -328,7 +328,7 @@
return myValueMarkers;
}
- private static <B extends XBreakpoint<?>> XBreakpointType<?, ?> getBreakpointTypeClass(final XBreakpointHandler<B> handler) {
+ private static XBreakpointType getBreakpointTypeClass(final XBreakpointHandler handler) {
return XDebuggerUtil.getInstance().findBreakpointType(handler.getBreakpointTypeClass());
}
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 d9bff39..76a360f 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebuggerUtilImpl.java
@@ -23,11 +23,12 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Processor;
import com.intellij.xdebugger.XDebuggerManager;
import com.intellij.xdebugger.XDebuggerUtil;
@@ -100,7 +101,7 @@
final boolean temporary) {
new WriteAction() {
@Override
- protected void run(final Result result) {
+ protected void run(@NotNull final Result result) {
XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
XLineBreakpoint<P> breakpoint = breakpointManager.findBreakpointAtLine(type, file, line);
if (breakpoint != null) {
@@ -118,7 +119,7 @@
public void removeBreakpoint(final Project project, final XBreakpoint<?> breakpoint) {
new WriteAction() {
@Override
- protected void run(final Result result) {
+ protected void run(@NotNull final Result result) {
XDebuggerManager.getInstance(project).getBreakpointManager().removeBreakpoint(breakpoint);
}
}.execute();
@@ -257,4 +258,51 @@
public <B extends XLineBreakpoint<?>> List<XBreakpointGroupingRule<B, ?>> getGroupingByFileRuleAsList() {
return Collections.<XBreakpointGroupingRule<B, ?>>singletonList(this.<B>getGroupingByFileRule());
}
+
+ @Override
+ @Nullable
+ public PsiElement findContextElement(@NotNull VirtualFile virtualFile, int offset, @NotNull Project project, boolean checkXml) {
+ if (!virtualFile.isValid()) {
+ return null;
+ }
+
+ Document document = FileDocumentManager.getInstance().getDocument(virtualFile);
+ PsiFile file = document == null ? null : PsiManager.getInstance(project).findFile(virtualFile);
+ if (file == null) {
+ return null;
+ }
+
+ if (offset < 0) {
+ offset = 0;
+ }
+ if (offset > document.getTextLength()) {
+ offset = document.getTextLength();
+ }
+ int startOffset = offset;
+
+ int lineEndOffset = document.getLineEndOffset(document.getLineNumber(offset));
+ PsiElement result = null;
+ do {
+ PsiElement element = file.findElementAt(offset);
+ if (!(element instanceof PsiWhiteSpace) && !(element instanceof PsiComment)) {
+ result = element;
+ break;
+ }
+
+ offset = element.getTextRange().getEndOffset() + 1;
+ }
+ while (offset < lineEndOffset);
+
+ if (result == null) {
+ result = file.findElementAt(startOffset);
+ }
+
+ if (checkXml && result != null && StdFileTypes.XML.getLanguage().equals(result.getLanguage())) {
+ PsiLanguageInjectionHost parent = PsiTreeUtil.getParentOfType(result, PsiLanguageInjectionHost.class);
+ if (parent != null) {
+ result = InjectedLanguageUtil.findElementInInjected(parent, offset);
+ }
+ }
+ return result;
+ }
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java
index 8c2186c..579798c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XSourcePositionImpl.java
@@ -20,7 +20,9 @@
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
import com.intellij.pom.Navigatable;
+import com.intellij.testFramework.LightVirtualFile;
import com.intellij.xdebugger.XSourcePosition;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -74,16 +76,25 @@
*/
@Nullable
public static XSourcePositionImpl create(@Nullable VirtualFile file, int line) {
- if (file == null) return null;
-
- Document document = FileDocumentManager.getInstance().getDocument(file);
- if (document == null) {
+ if (file == null) {
return null;
}
- if (line < 0){
- line = 0;
+
+ int offset;
+ if (file instanceof LightVirtualFile || file instanceof HttpVirtualFile) {
+ offset = -1;
}
- int offset = line < document.getLineCount() ? document.getLineStartOffset(line) : -1;
+ else {
+ Document document = FileDocumentManager.getInstance().getDocument(file);
+ if (document == null) {
+ return null;
+ }
+ if (line < 0) {
+ line = 0;
+ }
+
+ offset = line < document.getLineCount() ? document.getLineStartOffset(line) : -1;
+ }
return new XSourcePositionImpl(file, line, offset);
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java
index 1e30a9c..dac828e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/EditBreakpointActionHandler.java
@@ -57,7 +57,7 @@
Point point = gutterComponent.getPoint(breakpointGutterRenderer);
if (point == null) return;
final Icon icon = breakpointGutterRenderer.getIcon();
- Point whereToShow = new Point(point.x + icon.getIconWidth() / 2 + gutterComponent.getIconsAreaWidth(), point.y + icon.getIconHeight() / 2);
+ Point whereToShow = new Point(point.x + icon.getIconWidth() / 2, point.y + icon.getIconHeight() / 2);
doShowPopup(project, gutterComponent, whereToShow, breakpoint);
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java
index 8596384..50c5d8d 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/actions/XDebuggerActions.java
@@ -28,6 +28,7 @@
@NonNls String STEP_OVER = "StepOver";
@NonNls String STEP_INTO = "StepInto";
+ @NonNls String SMART_STEP_INTO = "SmartStepInto";
@NonNls String FORCE_STEP_INTO = "ForceStepInto";
@NonNls String STEP_OUT = "StepOut";
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java
index 20a5028..361b2f9 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XBreakpointPanelProvider.java
@@ -56,8 +56,9 @@
@Override
public void addListener(final BreakpointsListener listener, Project project, Disposable disposable) {
- final MyXBreakpointListener listener1 = new MyXBreakpointListener(listener);
- XDebuggerManager.getInstance(project).getBreakpointManager().addBreakpointListener(listener1);
+ XBreakpointManager breakpointManager = XDebuggerManager.getInstance(project).getBreakpointManager();
+ final MyXBreakpointListener listener1 = new MyXBreakpointListener(listener, breakpointManager);
+ breakpointManager.addBreakpointListener(listener1);
myListeners.add(listener1);
Disposer.register(disposable, new Disposable() {
@Override
@@ -71,6 +72,8 @@
protected void removeListener(BreakpointsListener listener) {
for (MyXBreakpointListener breakpointListener : myListeners) {
if (breakpointListener.myListener == listener) {
+ XBreakpointManager manager = breakpointListener.myBreakpointManager;
+ manager.removeBreakpointListener(breakpointListener);
myListeners.remove(breakpointListener);
break;
}
@@ -139,9 +142,11 @@
private static class MyXBreakpointListener implements XBreakpointListener<XBreakpoint<?>> {
public BreakpointsListener myListener;
+ public XBreakpointManager myBreakpointManager;
- public MyXBreakpointListener(BreakpointsListener listener) {
+ public MyXBreakpointListener(BreakpointsListener listener, XBreakpointManager breakpointManager) {
myListener = listener;
+ myBreakpointManager = breakpointManager;
}
@Override
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java
index 96a5fb5..138052e 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/XLineBreakpointManager.java
@@ -33,6 +33,7 @@
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
+import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Disposer;
@@ -125,7 +126,7 @@
public void updateBreakpointsUI() {
if (myProject.isDefault()) return;
- Runnable runnable = new Runnable() {
+ Runnable runnable = new DumbAwareRunnable() {
public void run() {
for (XLineBreakpointImpl breakpoint : myBreakpoints.keySet()) {
breakpoint.updateUI();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItem.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItem.java
index f515bb6..1f28a94 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItem.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/BreakpointItem.java
@@ -107,6 +107,7 @@
public abstract String getDisplayText();
+ protected void dispose() {}
@Override
public boolean equals(Object o) {
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 1363d72..e438b85 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
@@ -135,6 +135,7 @@
void collectItems() {
if (!myBreakpointsPanelProviders.isEmpty()) {
+ disposeItems();
myBreakpointItems.clear();
for (BreakpointPanelProvider panelProvider : myBreakpointsPanelProviders) {
panelProvider.provideBreakpointItems(myProject, myBreakpointItems);
@@ -220,7 +221,12 @@
myDetailController.updateDetailView();
}
};
- JTree tree = new BreakpointsCheckboxTree(myProject, myTreeController);
+ JTree tree = new BreakpointsCheckboxTree(myProject, myTreeController) {
+ @Override
+ protected void onDoubleClick(CheckedTreeNode node) {
+ navigate(false);
+ }
+ };
new AnAction("BreakpointDialog.GoToSource") {
@Override
@@ -233,7 +239,8 @@
new AnAction("BreakpointDialog.ShowSource") {
@Override
public void actionPerformed(AnActionEvent e) {
- navigate(false);
+ navigate(true);
+ close(OK_EXIT_CODE);
}
}.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.ACTION_EDIT_SOURCE).getShortcutSet(), tree);
@@ -294,6 +301,7 @@
public void breakpointsChanged() {
collectItems();
myTreeController.rebuildTree(myBreakpointItems);
+ myDetailController.doUpdateDetailView(true);
}
};
@@ -362,9 +370,16 @@
saveCurrentItem();
Disposer.dispose(myListenerDisposable);
saveBreakpointsDialogState();
+ disposeItems();
super.dispose();
}
+ private void disposeItems() {
+ for (BreakpointItem item : myBreakpointItems) {
+ item.dispose();
+ }
+ }
+
private void saveCurrentItem() {
ItemWrapper item = myDetailController.getSelectedItem();
if (item instanceof BreakpointItem) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
index ff5430f..80efe0d 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.form
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/breakpoints/ui/XLightBreakpointPropertiesPanel.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.intellij.xdebugger.impl.breakpoints.ui.XLightBreakpointPropertiesPanel">
- <grid id="27dc6" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="9" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <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">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="453"/>
@@ -16,7 +16,7 @@
<grid id="8bb86" binding="myConditionPanel" layout-manager="GridLayoutManager" row-count="1" 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="2" 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="2" 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"/>
@@ -41,7 +41,7 @@
</grid>
<nested-form id="11152" form-file="com/intellij/xdebugger/impl/breakpoints/ui/XSuspendPolicyPanel.form" binding="mySuspendPolicyPanel">
<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"/>
+ <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>
</nested-form>
<nested-form id="e13dc" form-file="com/intellij/xdebugger/impl/breakpoints/ui/XBreakpointActionsPanel.form" binding="myActionsPanel">
@@ -56,7 +56,7 @@
</nested-form>
<grid id="24056" binding="myCustomPropertiesPanelWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
- <grid row="6" 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="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"/>
@@ -64,7 +64,7 @@
</grid>
<hspacer id="ab565">
<constraints>
- <grid row="7" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
+ <grid row="7" column="0" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="400" height="-1"/>
</grid>
</constraints>
@@ -72,7 +72,7 @@
<grid id="e59bd" binding="myCustomConditionsPanelWrapper" 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="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="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -87,6 +87,17 @@
<text value="Enabled"/>
</properties>
</component>
+ <grid id="56399" binding="myCustomRightPropertiesPanelWrapper" layout-manager="BorderLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="4" column="1" row-span="2" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <enabled value="true"/>
+ <visible value="true"/>
+ </properties>
+ <border type="none"/>
+ <children/>
+ </grid>
</children>
</grid>
</form>
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 5ece9b5..bc6d5e4 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
@@ -78,6 +78,7 @@
private JPanel myCustomPropertiesPanelWrapper;
private JPanel myCustomConditionsPanelWrapper;
private JCheckBox myEnabledCheckbox;
+ private JPanel myCustomRightPropertiesPanelWrapper;
private final List<XBreakpointCustomPropertiesPanel<B>> myCustomPanels;
private List<XBreakpointPropertiesSubPanel<B>> mySubPanels = new ArrayList<XBreakpointPropertiesSubPanel<B>>();
@@ -133,6 +134,12 @@
myCustomPanels.add(customConditionPanel);
}
+ XBreakpointCustomPropertiesPanel<B> customRightConditionPanel = breakpointType.createCustomRightPropertiesPanel(project);
+ if (customRightConditionPanel != null && (showAllOptions || customRightConditionPanel.isVisibleOnPopup(breakpoint))) {
+ myCustomRightPropertiesPanelWrapper.add(customRightConditionPanel.getComponent(), BorderLayout.CENTER);
+ myCustomPanels.add(customRightConditionPanel);
+ }
+
myMainPanel.addFocusListener(new FocusAdapter() {
@Override
public void focusGained(FocusEvent event) {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XDebuggerTreeCreator.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XDebuggerTreeCreator.java
new file mode 100644
index 0000000..0be9cef
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XDebuggerTreeCreator.java
@@ -0,0 +1,67 @@
+/*
+ * 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.xdebugger.impl.evaluate.quick;
+
+import com.intellij.concurrency.ResultConsumer;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.xdebugger.XSourcePosition;
+import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
+import com.intellij.xdebugger.frame.XValue;
+import com.intellij.xdebugger.impl.actions.XDebuggerActions;
+import com.intellij.xdebugger.impl.evaluate.quick.common.DebuggerTreeCreator;
+import com.intellij.xdebugger.impl.frame.XValueMarkers;
+import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
+import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
+import org.jetbrains.annotations.NotNull;
+
+public class XDebuggerTreeCreator implements DebuggerTreeCreator<Pair<XValue,String>> {
+ @NotNull private final Project myProject;
+ private final XDebuggerEditorsProvider myProvider;
+ private final XSourcePosition myPosition;
+ private final XValueMarkers<?, ?> myMarkers;
+
+ public XDebuggerTreeCreator(@NotNull Project project, XDebuggerEditorsProvider editorsProvider, XSourcePosition sourcePosition,
+ XValueMarkers<?, ?> markers) {
+ myProject = project;
+ myProvider = editorsProvider;
+ myPosition = sourcePosition;
+ myMarkers = markers;
+ }
+
+ @NotNull
+ @Override
+ public Tree createTree(@NotNull Pair<XValue, String> descriptor) {
+ XDebuggerTree tree = new XDebuggerTree(myProject, myProvider, myPosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP, myMarkers);
+ tree.setRoot(new XValueNodeImpl(tree, null, descriptor.getSecond(), descriptor.getFirst()), true);
+ return tree;
+ }
+
+ @NotNull
+ @Override
+ public String getTitle(@NotNull Pair<XValue, String> descriptor) {
+ return descriptor.getSecond();
+ }
+
+ @Override
+ public void createDescriptorByNode(Object node, ResultConsumer<Pair<XValue, String>> resultConsumer) {
+ if (node instanceof XValueNodeImpl) {
+ XValueNodeImpl valueNode = (XValueNodeImpl)node;
+ resultConsumer.onSuccess(Pair.create(valueNode.getValueContainer(), valueNode.getName()));
+ }
+ }
+}
\ No newline at end of file
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 b98a265..8813e70 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
@@ -41,6 +41,7 @@
public class XQuickEvaluateHandler extends QuickEvaluateHandler {
private static final Logger LOG = Logger.getInstance("#com.intellij.xdebugger.impl.evaluate.quick.XQuickEvaluateHandler");
+ @Override
public boolean isEnabled(@NotNull final Project project) {
XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
if (session == null || !session.isSuspended()) {
@@ -50,16 +51,24 @@
return stackFrame != null && stackFrame.getEvaluator() != null;
}
+ @Override
public AbstractValueHint createValueHint(@NotNull final Project project, @NotNull final Editor editor, @NotNull final Point point, final ValueHintType type) {
final XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
- if (session == null) return null;
+ if (session == null) {
+ return null;
+ }
XStackFrame stackFrame = session.getCurrentStackFrame();
- if (stackFrame == null) return null;
+ if (stackFrame == null) {
+ return null;
+ }
final XDebuggerEvaluator evaluator = stackFrame.getEvaluator();
- if (evaluator == null) return null;
+ if (evaluator == null) {
+ return null;
+ }
return PsiDocumentManager.getInstance(project).commitAndRunReadAction(new Computable<XValueHint>() {
+ @Override
public XValueHint compute() {
int offset = AbstractValueHint.calculateOffset(editor, point);
Pair<TextRange, String> expressionData = getExpressionRange(evaluator, project, type, editor, offset);
@@ -93,10 +102,12 @@
return evaluator.getExpressionAtOffset(project, editor.getDocument(), offset, false);
}
+ @Override
public boolean canShowHint(@NotNull final Project project) {
return isEnabled(project);
}
+ @Override
public int getValueLookupDelay(final Project project) {
XDebugSession session = XDebuggerManager.getInstance(project).getCurrentSession();
if (session != null) {
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 29deaf4..415742b 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
@@ -22,24 +22,27 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.vcs.changes.issueLinks.LinkMouseListenerBase;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.SimpleColoredComponent;
import com.intellij.ui.SimpleColoredText;
+import com.intellij.util.Consumer;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerUtil;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
+import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
import com.intellij.xdebugger.frame.XFullValueEvaluator;
import com.intellij.xdebugger.frame.XValue;
import com.intellij.xdebugger.frame.XValuePlace;
import com.intellij.xdebugger.frame.presentation.XValuePresentation;
import com.intellij.xdebugger.impl.XDebugSessionImpl;
-import com.intellij.xdebugger.impl.actions.XDebuggerActions;
import com.intellij.xdebugger.impl.actions.handlers.XDebuggerEvaluateActionHandler;
import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint;
import com.intellij.xdebugger.impl.evaluate.quick.common.ValueHintType;
import com.intellij.xdebugger.impl.frame.XValueMarkers;
+import com.intellij.xdebugger.impl.ui.DebuggerUIUtil;
import com.intellij.xdebugger.impl.ui.XDebuggerUIConstants;
-import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
import com.intellij.xdebugger.impl.ui.tree.nodes.XEvaluationCallbackBase;
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodePresentationConfigurator;
@@ -48,6 +51,7 @@
import javax.swing.*;
import java.awt.*;
+import java.awt.event.MouseEvent;
/**
* @author nik
@@ -83,17 +87,33 @@
@Override
public void evaluated(@NotNull final XValue result) {
result.computePresentation(new XValueNodePresentationConfigurator.ConfigurableXValueNodeImpl() {
+ private XFullValueEvaluator myFullValueEvaluator;
+
@Override
public void applyPresentation(@Nullable Icon icon,
@NotNull XValuePresentation valuePresenter,
boolean hasChildren) {
- if (isHintHidden()) return;
+ if (isHintHidden()) {
+ return;
+ }
SimpleColoredText text = new SimpleColoredText();
text.append(myExpression, XDebuggerUIConstants.VALUE_NAME_ATTRIBUTES);
XValueNodeImpl.buildText(valuePresenter, text);
+
if (!hasChildren) {
- showHint(HintUtil.createInformationLabel(text));
+ SimpleColoredComponent component = HintUtil.createInformationComponent();
+ text.appendToComponent(component);
+ if (myFullValueEvaluator != null) {
+ component.append(myFullValueEvaluator.getLinkText(), XDebuggerTreeNodeHyperlink.TEXT_ATTRIBUTES, new Consumer<MouseEvent>() {
+ @Override
+ public void consume(MouseEvent event) {
+ DebuggerUIUtil.showValuePopup(myFullValueEvaluator, event, getProject(), getEditor());
+ }
+ });
+ LinkMouseListenerBase.installSingleTagOn(component);
+ }
+ showHint(component);
}
else if (getType() == ValueHintType.MOUSE_CLICK_HINT) {
showTree(result, myExpression);
@@ -111,13 +131,12 @@
@Override
public void setFullValueEvaluator(@NotNull XFullValueEvaluator fullValueEvaluator) {
- //todo[nik] implement?
+ myFullValueEvaluator = fullValueEvaluator;
}
@Override
public boolean isObsolete() {
- //todo[nik]
- return false;
+ return isHintHidden();
}
}, XValuePlace.TOOLTIP);
}
@@ -131,10 +150,9 @@
private void showTree(final XValue value, final String name) {
XValueMarkers<?,?> valueMarkers = ((XDebugSessionImpl)myDebugSession).getValueMarkers();
- XDebuggerTree tree = new XDebuggerTree(myDebugSession.getProject(), myDebugSession.getDebugProcess().getEditorsProvider(),
- myDebugSession.getCurrentPosition(), XDebuggerActions.INSPECT_TREE_POPUP_GROUP, valueMarkers);
- tree.getModel().addTreeModelListener(createTreeListener(tree));
- XValueHintTreeComponent component = new XValueHintTreeComponent(this, tree, Pair.create(value, name));
- showTreePopup(component, tree, name);
+ Pair<XValue, String> pair = Pair.create(value, name);
+ XDebuggerTreeCreator creator = new XDebuggerTreeCreator(myDebugSession.getProject(), myDebugSession.getDebugProcess().getEditorsProvider(),
+ myDebugSession.getCurrentPosition(), valueMarkers);
+ showTreePopup(creator, pair);
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java
deleted file mode 100644
index d0142a7..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHintTreeComponent.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.xdebugger.impl.evaluate.quick;
-
-import com.intellij.openapi.util.Pair;
-import com.intellij.xdebugger.frame.XValue;
-import com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHintTreeComponent;
-import com.intellij.xdebugger.impl.ui.tree.XDebuggerTree;
-import com.intellij.xdebugger.impl.ui.tree.nodes.XValueNodeImpl;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class XValueHintTreeComponent extends AbstractValueHintTreeComponent<Pair<XValue, String>> {
- private final XValueHint myValueHint;
- private final XDebuggerTree myTree;
-
- public XValueHintTreeComponent(@Nullable XValueHint valueHint, @NotNull XDebuggerTree tree, @NotNull Pair<XValue, String> initialItem) {
- super(valueHint, tree, initialItem);
-
- myValueHint = valueHint;
- myTree = tree;
- updateTree(initialItem);
- }
-
- @Override
- protected void updateTree(final Pair<XValue, String> selectedItem) {
- myTree.setRoot(new XValueNodeImpl(myTree, null, selectedItem.getSecond(), selectedItem.getFirst()), true);
- if (myValueHint != null) {
- myValueHint.showTreePopup(this, myTree, selectedItem.getSecond());
- }
- }
-
- @Override
- protected void setNodeAsRoot(final Object node) {
- if (node instanceof XValueNodeImpl) {
- if (myValueHint != null) {
- myValueHint.shiftLocation();
- }
-
- XValueNodeImpl valueNode = (XValueNodeImpl)node;
- Pair<XValue, String> item = Pair.create(valueNode.getValueContainer(), valueNode.getName());
- addToHistory(item);
- updateTree(item);
- }
- }
-}
\ No newline at end of file
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java
index e757db8..e7694a8 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHint.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,30 +18,19 @@
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
-import com.intellij.openapi.Disposable;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.event.EditorMouseEvent;
import com.intellij.openapi.editor.markup.*;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.TextRange;
import com.intellij.ui.*;
import com.intellij.ui.awt.RelativePoint;
-import com.intellij.ui.treeStructure.Tree;
import com.intellij.util.IconUtil;
-import com.intellij.util.ui.tree.TreeModelAdapter;
import org.intellij.lang.annotations.JdkConstants;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import javax.swing.event.TreeModelEvent;
-import javax.swing.event.TreeModelListener;
-import javax.swing.tree.TreePath;
import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
@@ -50,38 +39,38 @@
* @author nik
*/
public abstract class AbstractValueHint {
- private static final Logger LOG = Logger.getInstance("#com.intellij.xdebugger.impl.evaluate.quick.common.AbstractValueHint");
- @NonNls private final static String DIMENSION_SERVICE_KEY = "DebuggerActiveHint";
- private static final Icon COLLAPSED_TREE_ICON = IconUtil.getAddIcon();
- private static final int HINT_TIMEOUT = 7000; // ms
- private final KeyListener myEditorKeyListener = new KeyAdapter() {
- @Override
- public void keyReleased(KeyEvent e) {
- if(!isAltMask(e.getModifiers())) {
- ValueLookupManager.getInstance(myProject).hideHint();
- }
- }
- };
+ private static final Logger LOG = Logger.getInstance(AbstractValueHint.class);
+
private static final TextAttributes ourReferenceAttributes = new TextAttributes();
+
static {
ourReferenceAttributes.setForegroundColor(JBColor.BLUE);
ourReferenceAttributes.setEffectColor(JBColor.BLUE);
ourReferenceAttributes.setEffectType(EffectType.LINE_UNDERSCORE);
}
+ private final KeyListener myEditorKeyListener = new KeyAdapter() {
+ @Override
+ public void keyReleased(KeyEvent e) {
+ if (!isAltMask(e.getModifiers())) {
+ ValueLookupManager.getInstance(myProject).hideHint();
+ }
+ }
+ };
+
private RangeHighlighter myHighlighter;
private Cursor myStoredCursor;
private final Project myProject;
private final Editor myEditor;
private final ValueHintType myType;
- private Point myPoint;
+ private final Point myPoint;
private LightweightHint myCurrentHint;
- private JBPopup myPopup;
private boolean myHintHidden;
private TextRange myCurrentRange;
private Runnable myHideRunnable;
- public AbstractValueHint(Project project, Editor editor, Point point, ValueHintType type, final TextRange textRange) {
+ public AbstractValueHint(@NotNull Project project, @NotNull Editor editor, @NotNull Point point, @NotNull ValueHintType type,
+ final TextRange textRange) {
myPoint = point;
myProject = project;
myEditor = editor;
@@ -93,55 +82,21 @@
protected abstract void evaluateAndShowHint();
- private void resize(final TreePath path, JTree tree) {
- if (myPopup == null || !myPopup.isVisible()) return;
- final Window popupWindow = SwingUtilities.windowForComponent(myPopup.getContent());
- if (popupWindow == null) return;
- final Dimension size = tree.getPreferredSize();
- final Point location = popupWindow.getLocation();
- final Rectangle windowBounds = popupWindow.getBounds();
- final Rectangle bounds = tree.getPathBounds(path);
- if (bounds == null) return;
-
- final Rectangle targetBounds = new Rectangle(location.x,
- location.y,
- Math.max(Math.max(size.width, bounds.width) + 20, windowBounds.width),
- Math.max(tree.getRowCount() * bounds.height + 55, windowBounds.height));
- ScreenUtil.cropRectangleToFitTheScreen(targetBounds);
- popupWindow.setBounds(targetBounds);
- popupWindow.validate();
- popupWindow.repaint();
- }
-
- private void updateInitialBounds(final Tree tree) {
- final Window popupWindow = SwingUtilities.windowForComponent(myPopup.getContent());
- final Dimension size = tree.getPreferredSize();
- final Point location = popupWindow.getLocation();
- final Rectangle windowBounds = popupWindow.getBounds();
- final Rectangle targetBounds = new Rectangle(location.x,
- location.y,
- Math.max(size.width + 250, windowBounds.width),
- Math.max(size.height, windowBounds.height));
- ScreenUtil.cropRectangleToFitTheScreen(targetBounds);
- popupWindow.setBounds(targetBounds);
- popupWindow.validate();
- popupWindow.repaint();
- }
-
public boolean isKeepHint(Editor editor, Point point) {
- if (myCurrentHint != null && myCurrentHint.canControlAutoHide()) return true;
+ if (myCurrentHint != null && myCurrentHint.canControlAutoHide()) {
+ return true;
+ }
- if(myType == ValueHintType.MOUSE_ALT_OVER_HINT) {
+ if (myType == ValueHintType.MOUSE_ALT_OVER_HINT) {
return false;
}
- else if(myType == ValueHintType.MOUSE_CLICK_HINT) {
- if(myCurrentHint != null && myCurrentHint.isVisible()) {
+ else if (myType == ValueHintType.MOUSE_CLICK_HINT) {
+ if (myCurrentHint != null && myCurrentHint.isVisible()) {
return true;
}
}
else {
int offset = calculateOffset(editor, point);
-
if (myCurrentRange != null && myCurrentRange.getStartOffset() <= offset && offset <= myCurrentRange.getEndOffset()) {
return true;
}
@@ -150,14 +105,13 @@
}
public static int calculateOffset(@NotNull Editor editor, @NotNull Point point) {
- LogicalPosition pos = editor.xyToLogicalPosition(point);
- return editor.logicalPositionToOffset(pos);
+ return editor.logicalPositionToOffset(editor.xyToLogicalPosition(point));
}
public void hideHint() {
myHintHidden = true;
myCurrentRange = null;
- if(myStoredCursor != null) {
+ if (myStoredCursor != null) {
Component internalComponent = myEditor.getContentComponent();
internalComponent.setCursor(myStoredCursor);
if (LOG.isDebugEnabled()) {
@@ -166,11 +120,11 @@
internalComponent.removeKeyListener(myEditorKeyListener);
}
- if(myCurrentHint != null) {
+ if (myCurrentHint != null) {
myCurrentHint.hide();
myCurrentHint = null;
}
- if(myHighlighter != null) {
+ if (myHighlighter != null) {
myHighlighter.dispose();
myHighlighter = null;
}
@@ -179,7 +133,7 @@
public void invokeHint(Runnable hideRunnable) {
myHideRunnable = hideRunnable;
- if(!canShowHint()) {
+ if (!canShowHint()) {
hideHint();
return;
}
@@ -205,15 +159,6 @@
return Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
}
- public void shiftLocation() {
- if (myPopup != null) {
- final Window window = SwingUtilities.getWindowAncestor(myPopup.getContent());
- if (window != null) {
- myPoint = new RelativePoint(window, new Point(2, 2)).getPoint(myEditor.getContentComponent());
- }
- }
- }
-
public Project getProject() {
return myProject;
}
@@ -226,32 +171,6 @@
return myType;
}
- public void showTreePopup(final AbstractValueHintTreeComponent<?> component, final Tree tree, final String title) {
- if (myPopup != null) {
- myPopup.cancel();
- }
- myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(component.getMainPanel(), tree)
- .setRequestFocus(true)
- .setTitle(title)
- .setResizable(true)
- .setMovable(true)
- .setDimensionServiceKey(getProject(), DIMENSION_SERVICE_KEY, false)
- .createPopup();
-
- if (tree instanceof Disposable) {
- Disposer.register(myPopup, (Disposable)tree);
- }
-
- //Editor may be disposed before later invokator process this action
- if (getEditor().getComponent().getRootPane() == null) {
- myPopup.cancel();
- return;
- }
- myPopup.show(new RelativePoint(getEditor().getContentComponent(), myPoint));
-
- updateInitialBounds(tree);
- }
-
protected boolean showHint(final JComponent component) {
myCurrentHint = new LightweightHint(component);
myCurrentHint.addHintListener(new HintListener() {
@@ -263,17 +182,17 @@
}
});
- //Editor may be disposed before later invokator process this action
- final Editor editor = getEditor();
- final JRootPane rootPane = editor.getComponent().getRootPane();
- if(rootPane == null) return false;
+ // editor may be disposed before later invokator process this action
+ if (myEditor.isDisposed() || myEditor.getComponent().getRootPane() == null) {
+ return false;
+ }
- Point p = HintManagerImpl.getHintPosition(myCurrentHint, editor, editor.xyToLogicalPosition(myPoint), HintManager.UNDER);
- final HintHint hintHint = HintManagerImpl.createHintHint(editor, p, myCurrentHint, HintManager.UNDER, true);
-
- HintManagerImpl.getInstanceImpl().showEditorHint(myCurrentHint, editor, p,
- HintManager.HIDE_BY_ANY_KEY | HintManager.HIDE_BY_TEXT_CHANGE | HintManager.HIDE_BY_SCROLLING, HINT_TIMEOUT, false,
- hintHint);
+ Point p = HintManagerImpl.getHintPosition(myCurrentHint, myEditor, myEditor.xyToLogicalPosition(myPoint), HintManager.UNDER);
+ HintManagerImpl.getInstanceImpl().showEditorHint(myCurrentHint, myEditor, p,
+ HintManager.HIDE_BY_ANY_KEY |
+ HintManager.HIDE_BY_TEXT_CHANGE |
+ HintManager.HIDE_BY_SCROLLING, 0, false,
+ HintManagerImpl.createHintHint(myEditor, p, myCurrentHint, HintManager.UNDER, true));
return true;
}
@@ -282,10 +201,10 @@
}
protected JComponent createExpandableHintComponent(final SimpleColoredText text, final Runnable expand) {
- final JComponent component = HintUtil.createInformationLabel(text, COLLAPSED_TREE_ICON);
+ final JComponent component = HintUtil.createInformationLabel(text, IconUtil.getAddIcon());
addClickListenerToHierarchy(component, new ClickListener() {
@Override
- public boolean onClick(MouseEvent event, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent event, int clickCount) {
if (myCurrentHint != null) {
myCurrentHint.hide();
}
@@ -299,8 +218,7 @@
private static void addClickListenerToHierarchy(Component c, ClickListener l) {
l.installOn(c);
if (c instanceof Container) {
- final Container container = (Container)c;
- Component[] children = container.getComponents();
+ Component[] children = ((Container)c).getComponents();
for (Component child : children) {
addClickListenerToHierarchy(child, l);
}
@@ -311,15 +229,6 @@
return myCurrentRange;
}
- protected TreeModelListener createTreeListener(final Tree tree) {
- return new TreeModelAdapter() {
- @Override
- public void treeStructureChanged(TreeModelEvent e) {
- resize(e.getTreePath(), tree);
- }
- };
- }
-
private static boolean isAltMask(@JdkConstants.InputEventMask int modifiers) {
return modifiers == InputEvent.ALT_MASK;
}
@@ -331,4 +240,8 @@
public boolean isInsideHint(Editor editor, Point point) {
return myCurrentHint != null && myCurrentHint.isInsideHint(new RelativePoint(editor.getContentComponent(), point));
}
+
+ protected <D> void showTreePopup(@NotNull DebuggerTreeCreator<D> creator, @NotNull D descriptor) {
+ DebuggerTreeWithHistoryPopup.showTreePopup(creator, descriptor, getEditor(), myPoint, getProject());
+ }
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHintTreeComponent.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHintTreeComponent.java
deleted file mode 100644
index a8da368..0000000
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/AbstractValueHintTreeComponent.java
+++ /dev/null
@@ -1,146 +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.xdebugger.impl.evaluate.quick.common;
-
-import com.intellij.codeInsight.CodeInsightBundle;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.actionSystem.*;
-import com.intellij.ui.ScrollPaneFactory;
-import com.intellij.ui.treeStructure.Tree;
-import com.intellij.xdebugger.XDebuggerBundle;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.tree.TreePath;
-import java.awt.*;
-import java.awt.event.InputEvent;
-import java.awt.event.KeyEvent;
-import java.util.ArrayList;
-
-/**
- * @author nik
- */
-public abstract class AbstractValueHintTreeComponent<H> {
- private static final int HISTORY_SIZE = 11;
- private final ArrayList<H> myHistory = new ArrayList<H>();
- private int myCurrentIndex = -1;
- private final AbstractValueHint myValueHint;
- private final Tree myTree;
- private JPanel myMainPanel;
-
- protected AbstractValueHintTreeComponent(@Nullable AbstractValueHint valueHint, @NotNull Tree tree, @NotNull H initialItem) {
- myValueHint = valueHint;
- myTree = tree;
- myHistory.add(initialItem);
- }
-
- public JPanel getMainPanel() {
- if (myMainPanel == null) {
- myMainPanel = new JPanel(new BorderLayout());
- myMainPanel.add(ScrollPaneFactory.createScrollPane(myTree), BorderLayout.CENTER);
- myMainPanel.add(createToolbar(myMainPanel), BorderLayout.NORTH);
- }
- return myMainPanel;
- }
-
- private AnAction createGoForwardAction(){
- return new AnAction(CodeInsightBundle.message("quick.definition.forward"), null, AllIcons.Actions.Forward){
- @Override
- public void actionPerformed(AnActionEvent e) {
- if (myHistory.size() > 1 && myCurrentIndex < myHistory.size() - 1){
- myCurrentIndex ++;
- updateHint();
- }
- }
-
- @Override
- public void update(AnActionEvent e) {
- e.getPresentation().setEnabled(myHistory.size() > 1 && myCurrentIndex < myHistory.size() - 1);
- }
- };
- }
-
- private void updateHint() {
- if (myValueHint != null) {
- myValueHint.shiftLocation();
- }
- updateTree(myHistory.get(myCurrentIndex));
- }
-
- private AnAction createGoBackAction(){
- return new AnAction(CodeInsightBundle.message("quick.definition.back"), null, AllIcons.Actions.Back){
- @Override
- public void actionPerformed(AnActionEvent e) {
- if (myHistory.size() > 1 && myCurrentIndex > 0) {
- myCurrentIndex--;
- updateHint();
- }
- }
-
-
- @Override
- public void update(AnActionEvent e) {
- e.getPresentation().setEnabled(myHistory.size() > 1 && myCurrentIndex > 0);
- }
- };
- }
-
- protected abstract void updateTree(H selectedItem);
-
- protected void addToHistory(final H item) {
- if (myCurrentIndex < HISTORY_SIZE) {
- if (myCurrentIndex != -1) {
- myCurrentIndex += 1;
- } else {
- myCurrentIndex = 1;
- }
- myHistory.add(myCurrentIndex, item);
- }
- }
-
- private JComponent createToolbar(JPanel parent) {
- DefaultActionGroup group = new DefaultActionGroup();
- group.add(new AnAction(XDebuggerBundle.message("xdebugger.popup.value.tree.set.root.action.tooltip"),
- XDebuggerBundle.message("xdebugger.popup.value.tree.set.root.action.tooltip"), AllIcons.Modules.UnmarkWebroot) {
- @Override
- public void update(AnActionEvent e) {
- TreePath path = myTree.getSelectionPath();
- e.getPresentation().setEnabled(path != null && path.getPathCount() > 1);
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- TreePath path = myTree.getSelectionPath();
- if (path != null) {
- setNodeAsRoot(path.getLastPathComponent());
- }
- }
- });
-
- AnAction back = createGoBackAction();
- back.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_MASK)), parent);
- group.add(back);
-
- AnAction forward = createGoForwardAction();
- forward.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_MASK)), parent);
- group.add(forward);
-
- return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
- }
-
- protected abstract void setNodeAsRoot(Object node);
-}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeCreator.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeCreator.java
new file mode 100644
index 0000000..aaf01b3
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeCreator.java
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.evaluate.quick.common;
+
+import com.intellij.concurrency.ResultConsumer;
+import com.intellij.ui.treeStructure.Tree;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author nik
+*/
+public interface DebuggerTreeCreator<D> {
+ @NotNull
+ String getTitle(@NotNull D descriptor);
+
+ void createDescriptorByNode(Object node, ResultConsumer<D> resultConsumer);
+
+ @NotNull
+ Tree createTree(@NotNull D descriptor);
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.java
new file mode 100644
index 0000000..c7c5af9
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryContainer.java
@@ -0,0 +1,180 @@
+/*
+ * 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.xdebugger.impl.evaluate.quick.common;
+
+import com.intellij.codeInsight.CodeInsightBundle;
+import com.intellij.concurrency.ResultConsumer;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.xdebugger.XDebuggerBundle;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.util.*;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+abstract class DebuggerTreeWithHistoryContainer<D> {
+ private static final Logger LOG = Logger.getInstance(DebuggerTreeWithHistoryContainer.class);
+ private static final int HISTORY_SIZE = 11;
+ private final List<D> myHistory = new ArrayList<D>();
+ private int myCurrentIndex = -1;
+ protected final DebuggerTreeCreator<D> myTreeCreator;
+ @NotNull protected final Project myProject;
+
+ protected DebuggerTreeWithHistoryContainer(@NotNull D initialItem, @NotNull DebuggerTreeCreator<D> creator, @NotNull Project project) {
+ myTreeCreator = creator;
+ myProject = project;
+ myHistory.add(initialItem);
+ }
+
+ protected JPanel createMainPanel(Tree tree) {
+ JPanel mainPanel = new JPanel(new BorderLayout());
+ mainPanel.add(ScrollPaneFactory.createScrollPane(tree), BorderLayout.CENTER);
+ mainPanel.add(createToolbar(mainPanel, tree), BorderLayout.NORTH);
+ return mainPanel;
+ }
+
+ private void updateTree() {
+ D item = myHistory.get(myCurrentIndex);
+ updateTree(item);
+ }
+
+ protected void updateTree(@NotNull D selectedItem) {
+ updateContainer(myTreeCreator.createTree(selectedItem), myTreeCreator.getTitle(selectedItem));
+ }
+
+ protected abstract void updateContainer(Tree tree, String title);
+
+ protected void addToHistory(final D item) {
+ if (myCurrentIndex < HISTORY_SIZE) {
+ if (myCurrentIndex != -1) {
+ myCurrentIndex += 1;
+ } else {
+ myCurrentIndex = 1;
+ }
+ myHistory.add(myCurrentIndex, item);
+ }
+ }
+
+ private JComponent createToolbar(JPanel parent, Tree tree) {
+ DefaultActionGroup group = new DefaultActionGroup();
+ group.add(new SetAsRootAction(tree));
+
+ AnAction back = new GoBackwardAction();
+ back.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, InputEvent.ALT_MASK)), parent);
+ group.add(back);
+
+ AnAction forward = new GoForwardAction();
+ forward.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, InputEvent.ALT_MASK)), parent);
+ group.add(forward);
+
+ return ActionManager.getInstance().createActionToolbar(ActionPlaces.UNKNOWN, group, true).getComponent();
+ }
+
+ private class GoForwardAction extends AnAction {
+ public GoForwardAction() {
+ super(CodeInsightBundle.message("quick.definition.forward"), null, AllIcons.Actions.Forward);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ if (myHistory.size() > 1 && myCurrentIndex < myHistory.size() - 1){
+ myCurrentIndex ++;
+ updateTree();
+ }
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ e.getPresentation().setEnabled(myHistory.size() > 1 && myCurrentIndex < myHistory.size() - 1);
+ }
+ }
+
+ private class GoBackwardAction extends AnAction {
+ public GoBackwardAction() {
+ super(CodeInsightBundle.message("quick.definition.back"), null, AllIcons.Actions.Back);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ if (myHistory.size() > 1 && myCurrentIndex > 0) {
+ myCurrentIndex--;
+ updateTree();
+ }
+ }
+
+
+ @Override
+ public void update(AnActionEvent e) {
+ e.getPresentation().setEnabled(myHistory.size() > 1 && myCurrentIndex > 0);
+ }
+ }
+
+ private class SetAsRootAction extends AnAction {
+ private Tree myTree;
+
+ public SetAsRootAction(Tree tree) {
+ super(XDebuggerBundle.message("xdebugger.popup.value.tree.set.root.action.tooltip"),
+ XDebuggerBundle.message("xdebugger.popup.value.tree.set.root.action.tooltip"), AllIcons.Modules.UnmarkWebroot);
+ myTree = tree;
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ TreePath path = myTree.getSelectionPath();
+ e.getPresentation().setEnabled(path != null && path.getPathCount() > 1);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ TreePath path = myTree.getSelectionPath();
+ if (path != null) {
+ Object node = path.getLastPathComponent();
+ myTreeCreator.createDescriptorByNode(node, new ResultConsumer<D>() {
+ @Override
+ public void onSuccess(final D value) {
+ if (value != null) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ addToHistory(value);
+ updateTree(value);
+ }
+ });
+ }
+ }
+
+ @Override
+ public void onFailure(Throwable t) {
+ LOG.debug(t);
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryPanel.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryPanel.java
new file mode 100644
index 0000000..379bc82
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryPanel.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.evaluate.quick.common;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.ui.ScrollPaneFactory;
+import com.intellij.ui.treeStructure.Tree;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author nik
+ */
+public class DebuggerTreeWithHistoryPanel<D> extends DebuggerTreeWithHistoryContainer<D> {
+ private final JPanel myMainPanel;
+
+ public DebuggerTreeWithHistoryPanel(@NotNull D initialItem, @NotNull DebuggerTreeCreator<D> creator, @NotNull Project project) {
+ super(initialItem, creator, project);
+ myMainPanel = createMainPanel(myTreeCreator.createTree(initialItem));
+ }
+
+ @Override
+ protected void updateContainer(Tree tree, String title) {
+ Component component = ((BorderLayout)myMainPanel.getLayout()).getLayoutComponent(BorderLayout.CENTER);
+ myMainPanel.remove(component);
+ myMainPanel.add(BorderLayout.CENTER, ScrollPaneFactory.createScrollPane(tree));
+ myMainPanel.revalidate();
+ myMainPanel.repaint();
+ }
+
+ public JPanel getMainPanel() {
+ return myMainPanel;
+ }
+}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryPopup.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryPopup.java
new file mode 100644
index 0000000..e4ea46b
--- /dev/null
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/common/DebuggerTreeWithHistoryPopup.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.evaluate.quick.common;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.ui.ScreenUtil;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.ui.tree.TreeModelAdapter;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import javax.swing.event.TreeModelEvent;
+import javax.swing.event.TreeModelListener;
+import javax.swing.tree.TreePath;
+import java.awt.*;
+
+/**
+ * @author nik
+ */
+class DebuggerTreeWithHistoryPopup<D> extends DebuggerTreeWithHistoryContainer<D> {
+ @NonNls private final static String DIMENSION_SERVICE_KEY = "DebuggerActiveHint";
+ private JBPopup myPopup;
+ private final Editor myEditor;
+ private final Point myPoint;
+
+ private DebuggerTreeWithHistoryPopup(@NotNull D initialItem, @NotNull DebuggerTreeCreator<D> creator, @NotNull Editor editor, @NotNull Point point, @NotNull Project project) {
+ super(initialItem, creator, project);
+ myEditor = editor;
+ myPoint = point;
+ }
+
+ public static <D> void showTreePopup(@NotNull DebuggerTreeCreator<D> creator, @NotNull D initialItem, @NotNull Editor editor,
+ @NotNull Point point, @NotNull Project project) {
+ new DebuggerTreeWithHistoryPopup<D>(initialItem, creator, editor, point, project).updateTree(initialItem);
+ }
+
+ private TreeModelListener createTreeListener(final Tree tree) {
+ return new TreeModelAdapter() {
+ @Override
+ public void treeStructureChanged(TreeModelEvent e) {
+ resize(e.getTreePath(), tree);
+ }
+ };
+ }
+
+ @Override
+ protected void updateContainer(Tree tree, String title) {
+ if (myPopup != null) {
+ myPopup.cancel();
+ }
+ tree.getModel().addTreeModelListener(createTreeListener(tree));
+ myPopup = JBPopupFactory.getInstance().createComponentPopupBuilder(createMainPanel(tree), tree)
+ .setRequestFocus(true)
+ .setTitle(title)
+ .setResizable(true)
+ .setMovable(true)
+ .setDimensionServiceKey(myProject, DIMENSION_SERVICE_KEY, false)
+ .createPopup();
+
+ if (tree instanceof Disposable) {
+ Disposer.register(myPopup, (Disposable)tree);
+ }
+
+ //Editor may be disposed before later invokator process this action
+ if (myEditor.getComponent().getRootPane() == null) {
+ myPopup.cancel();
+ return;
+ }
+ myPopup.show(new RelativePoint(myEditor.getContentComponent(), myPoint));
+
+ updateInitialBounds(tree);
+ }
+
+ private void resize(final TreePath path, JTree tree) {
+ if (myPopup == null || !myPopup.isVisible()) return;
+ final Window popupWindow = SwingUtilities.windowForComponent(myPopup.getContent());
+ if (popupWindow == null) return;
+ final Dimension size = tree.getPreferredSize();
+ final Point location = popupWindow.getLocation();
+ final Rectangle windowBounds = popupWindow.getBounds();
+ final Rectangle bounds = tree.getPathBounds(path);
+ if (bounds == null) return;
+
+ final Rectangle targetBounds = new Rectangle(location.x,
+ location.y,
+ Math.max(Math.max(size.width, bounds.width) + 20, windowBounds.width),
+ Math.max(tree.getRowCount() * bounds.height + 55, windowBounds.height));
+ ScreenUtil.cropRectangleToFitTheScreen(targetBounds);
+ popupWindow.setBounds(targetBounds);
+ popupWindow.validate();
+ popupWindow.repaint();
+ }
+
+ private void updateInitialBounds(final Tree tree) {
+ final Window popupWindow = SwingUtilities.windowForComponent(myPopup.getContent());
+ final Dimension size = tree.getPreferredSize();
+ final Point location = popupWindow.getLocation();
+ final Rectangle windowBounds = popupWindow.getBounds();
+ final Rectangle targetBounds = new Rectangle(location.x,
+ location.y,
+ Math.max(size.width + 250, windowBounds.width),
+ Math.max(size.height, windowBounds.height));
+ ScreenUtil.cropRectangleToFitTheScreen(targetBounds);
+ popupWindow.setBounds(targetBounds);
+ popupWindow.validate();
+ popupWindow.repaint();
+ }
+}
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 973e6c1..cd1cfe2 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
@@ -24,6 +24,7 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.event.EditorMouseEvent;
+import com.intellij.openapi.editor.event.EditorMouseEventArea;
import com.intellij.openapi.editor.event.EditorMouseMotionListener;
import com.intellij.openapi.project.Project;
import com.intellij.util.Alarm;
@@ -35,7 +36,7 @@
private final Project myProject;
private final Alarm myAlarm;
private AbstractValueHint myRequest = null;
- private DebuggerSupport[] mySupports;
+ private final DebuggerSupport[] mySupports;
private boolean myListening;
public ValueLookupManager(Project project) {
@@ -47,18 +48,28 @@
public void startListening() {
if (!myListening) {
myListening = true;
- EditorFactory.getInstance().getEventMulticaster().addEditorMouseMotionListener(this,myProject);
+ EditorFactory.getInstance().getEventMulticaster().addEditorMouseMotionListener(this, myProject);
}
}
+ @Override
public void mouseDragged(EditorMouseEvent e) {
}
+ @Override
public void mouseMoved(EditorMouseEvent e) {
- if (e.isConsumed()) return;
+ if (e.isConsumed()) {
+ return;
+ }
Editor editor = e.getEditor();
- if (editor.getProject() != null && editor.getProject() != myProject) return;
+ if (editor.getProject() != null && editor.getProject() != myProject) {
+ return;
+ }
+
+ if (e.getArea() != EditorMouseEventArea.EDITING_AREA) {
+ return;
+ }
Point point = e.getMouseEvent().getPoint();
if (myRequest != null && !myRequest.isKeepHint(editor, point)) {
@@ -76,19 +87,21 @@
private void requestHint(final QuickEvaluateHandler handler, final Editor editor, final Point point, final ValueHintType type) {
myAlarm.cancelAllRequests();
- if(type == ValueHintType.MOUSE_OVER_HINT) {
+ if (type == ValueHintType.MOUSE_OVER_HINT) {
myAlarm.addRequest(new Runnable() {
+ @Override
public void run() {
showHint(handler, editor, point, type);
}
}, handler.getValueLookupDelay(myProject));
- } else {
+ }
+ else {
showHint(handler, editor, point, type);
}
}
public void hideHint() {
- if(myRequest != null) {
+ if (myRequest != null) {
myRequest.hideHint();
myRequest = null;
}
@@ -96,7 +109,9 @@
public void showHint(final QuickEvaluateHandler handler, Editor editor, Point point, ValueHintType type) {
myAlarm.cancelAllRequests();
- if (editor.isDisposed() || !handler.canShowHint(myProject)) return;
+ if (editor.isDisposed() || !handler.canShowHint(myProject)) {
+ return;
+ }
final AbstractValueHint request = handler.createValueHint(myProject, editor, point, type);
if (request != null) {
@@ -104,8 +119,12 @@
return;
}
- if (!request.canShowHint()) return;
- if (myRequest != null && myRequest.isInsideHint(editor, point)) return;
+ if (!request.canShowHint()) {
+ return;
+ }
+ if (myRequest != null && myRequest.isInsideHint(editor, point)) {
+ return;
+ }
hideHint();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java
index 48685a0..f4b6c2c 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/frame/XDebuggerFramesList.java
@@ -20,7 +20,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.ColoredTextContainer;
import com.intellij.ui.FileColorManager;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.ui.TextTransferable;
@@ -28,8 +27,6 @@
import com.intellij.xdebugger.XDebuggerBundle;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.frame.XStackFrame;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
@@ -39,13 +36,59 @@
* @author nik
*/
public class XDebuggerFramesList extends DebuggerFramesList {
- private static final TransferHandler defaultTransferHandler = new MyListTransferHandler();
+ private static final TransferHandler DEFAULT_TRANSFER_HANDLER = new TransferHandler() {
+ @Override
+ protected Transferable createTransferable(JComponent c) {
+ if (!(c instanceof XDebuggerFramesList)) {
+ return null;
+ }
+ XDebuggerFramesList list = (XDebuggerFramesList)c;
+ //noinspection deprecation
+ Object[] values = list.getSelectedValues();
+ if (values == null || values.length == 0) {
+ return null;
+ }
+
+ StringBuilder plainBuf = new StringBuilder();
+ StringBuilder htmlBuf = new StringBuilder();
+ TextTransferable.ColoredStringBuilder coloredTextContainer = new TextTransferable.ColoredStringBuilder();
+ htmlBuf.append("<html>\n<body>\n<ul>\n");
+ for (Object value : values) {
+ htmlBuf.append(" <li>");
+ if (value != null) {
+ if (value instanceof XStackFrame) {
+ ((XStackFrame)value).customizePresentation(coloredTextContainer);
+ coloredTextContainer.appendTo(plainBuf, htmlBuf);
+ }
+ else {
+ String text = value.toString();
+ plainBuf.append(text);
+ htmlBuf.append(text);
+ }
+ }
+ plainBuf.append('\n');
+ htmlBuf.append("</li>\n");
+ }
+
+ // remove the last newline
+ plainBuf.setLength(plainBuf.length() - 1);
+ htmlBuf.append("</ul>\n</body>\n</html>");
+ return new TextTransferable(htmlBuf.toString(), plainBuf.toString());
+ }
+
+ @Override
+ public int getSourceActions(JComponent c) {
+ return COPY;
+ }
+ };
private XStackFrame mySelectedFrame;
public XDebuggerFramesList(Project project) {
super(project);
+
doInit();
+ setTransferHandler(DEFAULT_TRANSFER_HANDLER);
}
@Override
@@ -117,73 +160,4 @@
stackFrame.customizePresentation(this);
}
}
-
- @Override
- public TransferHandler getTransferHandler() {
- return defaultTransferHandler;
- }
-
- private static class MyColoredTextContainer implements ColoredTextContainer {
- private final StringBuilder builder = new StringBuilder();
- @Override
- public void append(@NotNull String fragment, @NotNull SimpleTextAttributes attributes) {
- builder.append(fragment);
- }
-
- @Override
- public void setIcon(@Nullable Icon icon) {
- }
-
- @Override
- public void setToolTipText(String text) {
- }
- }
-
- private static class MyListTransferHandler extends TransferHandler {
- @Override
- protected Transferable createTransferable(JComponent c) {
- if (!(c instanceof XDebuggerFramesList)) {
- return null;
- }
- XDebuggerFramesList list = (XDebuggerFramesList)c;
- Object[] values = list.getSelectedValues();
- if (values == null || values.length == 0) {
- return null;
- }
-
- StringBuilder plainBuf = new StringBuilder();
- StringBuilder htmlBuf = new StringBuilder();
- MyColoredTextContainer coloredTextContainer = new MyColoredTextContainer();
-
- htmlBuf.append("<html>\n<body>\n<ul>\n");
- for (Object value : values) {
- htmlBuf.append(" <li>");
- if (value != null) {
- if (value instanceof XStackFrame) {
- ((XStackFrame)value).customizePresentation(coloredTextContainer);
- plainBuf.append(coloredTextContainer.builder);
- htmlBuf.append(coloredTextContainer.builder);
- coloredTextContainer.builder.setLength(0);
- }
- else {
- String text = value.toString();
- plainBuf.append(text);
- htmlBuf.append(text);
- }
- }
- plainBuf.append('\n');
- htmlBuf.append("</li>\n");
- }
-
- // remove the last newline
- plainBuf.setLength(plainBuf.length() - 1);
- htmlBuf.append("</ul>\n</body>\n</html>");
- return new TextTransferable(htmlBuf.toString(), plainBuf.toString());
- }
-
- @Override
- public int getSourceActions(JComponent c) {
- return COPY;
- }
- }
}
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 80c9504..abce43b 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
@@ -20,10 +20,7 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.popup.Balloon;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.ui.popup.JBPopupListener;
-import com.intellij.openapi.ui.popup.LightweightWindowEvent;
+import com.intellij.openapi.ui.popup.*;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.DimensionService;
import com.intellij.openapi.util.Ref;
@@ -99,12 +96,12 @@
return new RelativePoint(editor.getContentComponent(), p);
}
- public static void showValuePopup(@NotNull XFullValueEvaluator text, @NotNull MouseEvent event, @NotNull Project project) {
+ public static void showValuePopup(@NotNull XFullValueEvaluator evaluator, @NotNull MouseEvent event, @NotNull Project project, @Nullable Editor editor) {
EditorTextField textArea = new TextViewer("Evaluating...", project);
textArea.setBackground(HintUtil.INFORMATION_COLOR);
final FullValueEvaluationCallbackImpl callback = new FullValueEvaluationCallbackImpl(textArea);
- text.startEvaluation(callback);
+ evaluator.startEvaluation(callback);
Dimension size = DimensionService.getInstance().getSize(FULL_VALUE_POPUP_DIMENSION_KEY, project);
if (size == null) {
@@ -114,7 +111,7 @@
textArea.setPreferredSize(size);
- JBPopupFactory.getInstance().createComponentPopupBuilder(textArea, null)
+ JBPopup popup = JBPopupFactory.getInstance().createComponentPopupBuilder(textArea, null)
.setResizable(true)
.setMovable(true)
.setDimensionServiceKey(project, FULL_VALUE_POPUP_DIMENSION_KEY, false)
@@ -125,8 +122,13 @@
callback.setObsolete();
return true;
}
- })
- .createPopup().show(new RelativePoint(event.getComponent(), new Point(event.getX() - size.width, event.getY() - size.height)));
+ }).createPopup();
+ if (editor == null) {
+ popup.show(new RelativePoint(event.getComponent(), new Point(event.getX() - size.width, event.getY() - size.height)));
+ }
+ else {
+ popup.showInBestPositionFor(editor);
+ }
}
public static void showXBreakpointEditorBalloon(final Project project,
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java
index 90469e5..694ef28 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/XDebuggerExpressionComboBox.java
@@ -60,6 +60,7 @@
return myComboBox;
}
+ @Override
public JComponent getComponent() {
return myComboBox;
}
@@ -70,7 +71,7 @@
}
public JComponent getEditorComponent() {
- return (JComponent)myEditor.getEditorComponent();
+ return myEditor.getEditorComponent();
}
public void setEnabled(boolean enable) {
@@ -89,13 +90,12 @@
private void initEditor() {
myEditor = new EditorComboBoxEditor(getProject(), myDebuggerEditorsProvider.getFileType()) {
+ @Override
public void setItem(Object anObject) {
- if (anObject == null) {
- anObject = "";
- }
- super.setItem(createDocument((String)anObject));
+ super.setItem(createDocument(StringUtil.notNullize((String)anObject)));
}
+ @Override
public Object getItem() {
return ((Document)super.getItem()).getText();
}
@@ -106,6 +106,7 @@
myComboBox.setMaximumRowCount(XDebuggerHistoryManager.MAX_RECENT_EXPRESSIONS);
}
+ @Override
protected void onHistoryChanged() {
fillComboBox();
}
@@ -120,6 +121,7 @@
}
}
+ @Override
protected void doSetText(String text) {
if (myComboBox.getItemCount() > 0) {
myComboBox.setSelectedIndex(0);
@@ -133,15 +135,18 @@
}
}
+ @Override
public String getText() {
final Object value = myComboBox.isPopupVisible() ? myComboBox.getPopup().getList().getSelectedValue() : myEditor.getItem();
return StringUtil.notNullize((String)value);
}
+ @Override
public JComponent getPreferredFocusedComponent() {
return (JComponent)myComboBox.getEditor().getEditorComponent();
}
+ @Override
public void selectAll() {
myComboBox.getEditor().selectAll();
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java
index e450b0c..ee828b2 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/TreeInplaceEditor.java
@@ -25,6 +25,8 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -148,9 +150,11 @@
cancelEditing();
}
};
+ tree.addComponentListener(componentListener);
rootPane.addComponentListener(componentListener);
myRemoveActions.add(new Runnable() {
public void run() {
+ tree.addComponentListener(componentListener);
rootPane.removeComponentListener(componentListener);
}
});
@@ -214,12 +218,7 @@
}
final int id = mouseEvent.getID();
- if (id == MouseEvent.MOUSE_WHEEL) {
- cancelEditing();
- return;
- }
-
- if (id != MouseEvent.MOUSE_PRESSED && id != MouseEvent.MOUSE_RELEASED && id != MouseEvent.MOUSE_CLICKED) {
+ if (id != MouseEvent.MOUSE_PRESSED && id != MouseEvent.MOUSE_RELEASED && id != MouseEvent.MOUSE_CLICKED && id != MouseEvent.MOUSE_WHEEL) {
return;
}
@@ -239,6 +238,14 @@
}
}
+ // do not cancel editing if we click in editor popup
+ final List<JBPopup> popups = JBPopupFactory.getInstance().getChildPopups(myInplaceEditorComponent);
+ for (JBPopup popup : popups) {
+ if (SwingUtilities.isDescendingFrom(sourceComponent, popup.getContent())) {
+ return;
+ }
+ }
+
final Point point = SwingUtilities.convertPoint(sourceComponent, originalPoint, myInplaceEditorComponent);
if (myInplaceEditorComponent.contains(point)) {
return;
@@ -246,7 +253,9 @@
final Component componentAtPoint = SwingUtilities.getDeepestComponentAt(sourceComponent, originalPoint.x, originalPoint.y);
for (Component comp = componentAtPoint; comp != null; comp = comp.getParent()) {
if (comp instanceof ComboPopup) {
- doOKAction();
+ if (id != MouseEvent.MOUSE_WHEEL) {
+ doOKAction();
+ }
return;
}
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
index c84d2a1..2cf8c71 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XDebuggerTree.java
@@ -27,6 +27,7 @@
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
+import com.intellij.util.ui.TextTransferable;
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XDebuggerTreeNodeHyperlink;
@@ -45,6 +46,7 @@
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import java.awt.*;
+import java.awt.datatransfer.Transferable;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
@@ -71,6 +73,54 @@
return StringUtil.notNullize(text);
}
};
+
+ private static final TransferHandler DEFAULT_TRANSFER_HANDLER = new TransferHandler() {
+ @Override
+ protected Transferable createTransferable(JComponent c) {
+ if (!(c instanceof XDebuggerTree)) {
+ return null;
+ }
+ XDebuggerTree tree = (XDebuggerTree)c;
+ //noinspection deprecation
+ TreePath[] selectedPaths = tree.getSelectionPaths();
+ if (selectedPaths == null || selectedPaths.length == 0) {
+ return null;
+ }
+
+ StringBuilder plainBuf = new StringBuilder();
+ StringBuilder htmlBuf = new StringBuilder();
+ htmlBuf.append("<html>\n<body>\n<ul>\n");
+ TextTransferable.ColoredStringBuilder coloredTextContainer = new TextTransferable.ColoredStringBuilder();
+ for (TreePath path : selectedPaths) {
+ htmlBuf.append(" <li>");
+ Object node = path.getLastPathComponent();
+ if (node != null) {
+ if (node instanceof XDebuggerTreeNode) {
+ ((XDebuggerTreeNode)node).appendToComponent(coloredTextContainer);
+ coloredTextContainer.appendTo(plainBuf, htmlBuf);
+ }
+ else {
+ String text = node.toString();
+ plainBuf.append(text);
+ htmlBuf.append(text);
+ }
+ }
+ plainBuf.append('\n');
+ htmlBuf.append("</li>\n");
+ }
+
+ // remove the last newline
+ plainBuf.setLength(plainBuf.length() - 1);
+ htmlBuf.append("</ul>\n</body>\n</html>");
+ return new TextTransferable(htmlBuf.toString(), plainBuf.toString());
+ }
+
+ @Override
+ public int getSourceActions(JComponent c) {
+ return COPY;
+ }
+ };
+
private final DefaultTreeModel myTreeModel;
private final Project myProject;
private final XDebuggerEditorsProvider myEditorsProvider;
@@ -91,7 +141,7 @@
setCellRenderer(new XDebuggerTreeRenderer());
new TreeLinkMouseListener(new XDebuggerTreeRenderer()) {
@Override
- protected void handleTagClick(Object tag, MouseEvent event) {
+ protected void handleTagClick(@Nullable Object tag, @NotNull MouseEvent event) {
if (tag instanceof XDebuggerTreeNodeHyperlink) {
((XDebuggerTreeNodeHyperlink)tag).onClick(event);
}
@@ -134,6 +184,8 @@
}
});
registerShortcuts();
+
+ setTransferHandler(DEFAULT_TRANSFER_HANDLER);
}
private void expandIfEllipsis() {
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java
index c9e22b3..eea2b89 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/XInspectDialog.java
@@ -22,8 +22,8 @@
import com.intellij.xdebugger.XSourcePosition;
import com.intellij.xdebugger.evaluation.XDebuggerEditorsProvider;
import com.intellij.xdebugger.frame.XValue;
-import com.intellij.xdebugger.impl.actions.XDebuggerActions;
-import com.intellij.xdebugger.impl.evaluate.quick.XValueHintTreeComponent;
+import com.intellij.xdebugger.impl.evaluate.quick.XDebuggerTreeCreator;
+import com.intellij.xdebugger.impl.evaluate.quick.common.DebuggerTreeWithHistoryPanel;
import com.intellij.xdebugger.impl.frame.XValueMarkers;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -35,7 +35,7 @@
* @author nik
*/
public class XInspectDialog extends DialogWrapper {
- private final XValueHintTreeComponent myTreePanel;
+ private final DebuggerTreeWithHistoryPanel<Pair<XValue, String>> myDebuggerTreePanel;
public XInspectDialog(@NotNull Project project,
XDebuggerEditorsProvider editorsProvider,
@@ -48,15 +48,16 @@
setTitle(XDebuggerBundle.message("inspect.value.dialog.title", name));
setModal(false);
- XDebuggerTree tree = new XDebuggerTree(project, editorsProvider, sourcePosition, XDebuggerActions.INSPECT_TREE_POPUP_GROUP, markers);
- myTreePanel = new XValueHintTreeComponent(null, tree, Pair.create(value, name));
+ Pair<XValue, String> initialItem = Pair.create(value, name);
+ XDebuggerTreeCreator creator = new XDebuggerTreeCreator(project, editorsProvider, sourcePosition, markers);
+ myDebuggerTreePanel = new DebuggerTreeWithHistoryPanel<Pair<XValue, String>>(initialItem, creator, project);
init();
}
@Override
@Nullable
protected JComponent createCenterPanel() {
- return myTreePanel.getMainPanel();
+ return myDebuggerTreePanel.getMainPanel();
}
@Override
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java
index a70c72b..3197ad8 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/MessageTreeNode.java
@@ -16,7 +16,7 @@
package com.intellij.xdebugger.impl.ui.tree.nodes;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.SimpleColoredComponent;
+import com.intellij.ui.ColoredTextContainer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.util.IJSwingUtilities;
import com.intellij.util.SmartList;
@@ -164,10 +164,10 @@
}
@Override
- public void appendToComponent(SimpleColoredComponent component) {
+ public void appendToComponent(@NotNull ColoredTextContainer component) {
for (Object object : objects) {
if (object instanceof String) {
- component.append((String)object);
+ component.append((String)object, SimpleTextAttributes.REGULAR_ATTRIBUTES);
}
else {
XDebuggerTreeNodeHyperlink hyperlink = (XDebuggerTreeNodeHyperlink)object;
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
index 5af339e..dccd5fd 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XDebuggerTreeNode.java
@@ -15,7 +15,7 @@
*/
package com.intellij.xdebugger.impl.ui.tree.nodes;
-import com.intellij.ui.SimpleColoredComponent;
+import com.intellij.ui.ColoredTextContainer;
import com.intellij.ui.SimpleColoredText;
import com.intellij.ui.TreeSpeedSearch;
import com.intellij.util.ArrayUtilRt;
@@ -181,7 +181,7 @@
public abstract void clearChildren();
- public void appendToComponent(SimpleColoredComponent component) {
+ public void appendToComponent(@NotNull ColoredTextContainer component) {
getText().appendToComponent(component);
XDebuggerTreeNodeHyperlink link = getLink();
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XEvaluationCallbackBase.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XEvaluationCallbackBase.java
index e0e84b5..2ab4287 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XEvaluationCallbackBase.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XEvaluationCallbackBase.java
@@ -16,7 +16,6 @@
package com.intellij.xdebugger.impl.ui.tree.nodes;
import com.intellij.xdebugger.evaluation.XDebuggerEvaluator;
-import org.jetbrains.annotations.NotNull;
/**
* @author nik
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
index 75f927e..8b679f1 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueNodeImpl.java
@@ -183,13 +183,14 @@
return new XDebuggerTreeNodeHyperlink(myFullValueEvaluator.getLinkText()) {
@Override
public void onClick(MouseEvent event) {
- DebuggerUIUtil.showValuePopup(myFullValueEvaluator, event, myTree.getProject());
+ DebuggerUIUtil.showValuePopup(myFullValueEvaluator, event, myTree.getProject(), null);
}
};
}
return null;
}
+ @Override
@Nullable
public String getName() {
return myName;
@@ -200,11 +201,13 @@
return myValuePresentation;
}
+ @Override
@Nullable
public String getRawValue() {
return myRawValue;
}
+ @Override
public boolean isComputed() {
return myValuePresentation != null;
}
diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java
index 06669bb..975d8e4 100644
--- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java
+++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/ui/tree/nodes/XValueTextRendererImpl.java
@@ -30,7 +30,7 @@
class XValueTextRendererImpl extends XValueTextRendererBase {
private final ColoredTextContainer myText;
- public XValueTextRendererImpl(ColoredTextContainer text) {
+ public XValueTextRendererImpl(@NotNull ColoredTextContainer text) {
myText = text;
}
diff --git a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java
index 39b4b88..3e4067f 100644
--- a/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java
+++ b/platform/xdebugger-impl/testSrc/com/intellij/xdebugger/XDebuggerTestUtil.java
@@ -93,7 +93,7 @@
}
public static void assertPosition(XSourcePosition pos, VirtualFile file, int line) throws IOException {
- Assert.assertNotNull(pos);
+ Assert.assertNotNull("No current position", pos);
Assert.assertEquals(new File(file.getPath()).getCanonicalPath(), new File(pos.getFile().getPath()).getCanonicalPath());
if (line != -1) Assert.assertEquals(line, pos.getLine());
}
diff --git a/plugins/IdeaTestAssistant/IdeaTestAssistant.iml b/plugins/IdeaTestAssistant/IdeaTestAssistant.iml
index 02541a7..cb042db 100644
--- a/plugins/IdeaTestAssistant/IdeaTestAssistant.iml
+++ b/plugins/IdeaTestAssistant/IdeaTestAssistant.iml
@@ -13,6 +13,7 @@
<orderEntry type="module" module-name="idea-tests" scope="TEST" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="module" module-name="testFramework" />
+ <orderEntry type="module" module-name="execution-impl" />
</component>
</module>
diff --git a/plugins/IdeaTestAssistant/src/META-INF/plugin.xml b/plugins/IdeaTestAssistant/src/META-INF/plugin.xml
index 7f4d9a5..0958aad 100644
--- a/plugins/IdeaTestAssistant/src/META-INF/plugin.xml
+++ b/plugins/IdeaTestAssistant/src/META-INF/plugin.xml
@@ -13,6 +13,10 @@
<action id="DumpCleanTestData" internal="true" class="com.intellij.internal.DumpCleanHighlightingTestdataAction">
<add-to-group group-id="Internal.Dump"/>
</action>
+ <group>
+ <reference id="TestData.Navigate"/>
+ <add-to-group anchor="first" group-id="TestTreePopupMenu"/>
+ </group>
</actions>
<extensions defaultExtensionNs="com.intellij">
@@ -21,7 +25,9 @@
<codeInsight.lineMarkerProvider language="Groovy" implementationClass="com.intellij.testAssistant.TestDataLineMarkerProvider"/>
<fileEditorProvider implementation="com.intellij.testAssistant.TestDataGroupEditorProvider"/>
<gotoRelatedProvider implementation="com.intellij.testAssistant.TestDataAsRelatedFileProvider"/>
+ <gotoRelatedProvider implementation="com.intellij.testAssistant.TestCaseAsRelatedFileProvider"/>
<psi.referenceContributor implementation="com.intellij.testAssistant.TestDataReferenceContributor"/>
+ <getDataRule key="Location" implementationClass="com.intellij.testAssistant.TestLocationDataRule"/>
</extensions>
<project-components>
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java
index 23fbb4b..cba1dcf 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/NavigateToTestDataAction.java
@@ -15,6 +15,10 @@
*/
package com.intellij.testAssistant;
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.execution.Location;
+import com.intellij.execution.junit.JUnitUtil;
+import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
@@ -23,14 +27,21 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiMethod;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.testFramework.Parameterized;
+import com.intellij.ui.awt.RelativePoint;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
@@ -39,38 +50,62 @@
public class NavigateToTestDataAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
- final PsiMethod method = findTargetMethod(e.getDataContext());
- final Editor editor = e.getData(CommonDataKeys.EDITOR);
- if (method == null || editor == null) {
- return;
- }
- List<String> fileNames = findTestDataFiles(e.getDataContext());
+ final DataContext dataContext = e.getDataContext();
+ final Project project = CommonDataKeys.PROJECT.getData(dataContext);
+ List<String> fileNames = findTestDataFiles(dataContext);
if (fileNames == null || fileNames.isEmpty()) {
String message = "Cannot find testdata files for class";
final Notification notification = new Notification("testdata", "Found no testdata files", message, NotificationType.INFORMATION);
- Notifications.Bus.notify(notification, method.getProject());
+ Notifications.Bus.notify(notification, project);
}
else {
- TestDataNavigationHandler.navigate(method, JBPopupFactory.getInstance().guessBestPopupLocation(editor), fileNames);
+ final Editor editor = e.getData(CommonDataKeys.EDITOR);
+ final JBPopupFactory popupFactory = JBPopupFactory.getInstance();
+ final RelativePoint point = editor != null ? popupFactory.guessBestPopupLocation(editor) : popupFactory.guessBestPopupLocation(dataContext);
+
+ TestDataNavigationHandler.navigate(point, fileNames, project);
}
}
@Nullable
public static List<String> findTestDataFiles(@NotNull DataContext context) {
final PsiMethod method = findTargetMethod(context);
- final Editor editor = CommonDataKeys.EDITOR.getData(context);
- if (method == null || editor == null) {
+ if (method == null) {
return null;
}
final String name = method.getName();
-
- String testDataPath = null;
if (name.startsWith("test")) {
- testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass());
+ String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(method.getContainingClass());
+ final TestDataReferenceCollector collector = new TestDataReferenceCollector(testDataPath, name.substring(4));
+ return collector.collectTestDataReferences(method);
}
- final TestDataReferenceCollector collector = new TestDataReferenceCollector(testDataPath, name.substring(4));
- return collector.collectTestDataReferences(method);
+
+ final Location<?> location = Location.DATA_KEY.getData(context);
+ if (location instanceof PsiMemberParameterizedLocation) {
+ PsiClass containingClass = ((PsiMemberParameterizedLocation)location).getContainingClass();
+ if (containingClass == null) {
+ containingClass = PsiTreeUtil.getParentOfType(location.getPsiElement(), PsiClass.class, false);
+ }
+ if (containingClass != null) {
+ final PsiAnnotation annotation = AnnotationUtil.findAnnotationInHierarchy(containingClass, Collections.singleton(JUnitUtil.RUN_WITH));
+ if (annotation != null) {
+ final PsiAnnotationMemberValue memberValue = annotation.findAttributeValue("value");
+ if (memberValue instanceof PsiClassObjectAccessExpression) {
+ final PsiTypeElement operand = ((PsiClassObjectAccessExpression)memberValue).getOperand();
+ if (operand.getType().equalsToText(Parameterized.class.getName())) {
+ final String testDataPath = TestDataLineMarkerProvider.getTestDataBasePath(containingClass);
+ final String paramSetName = ((PsiMemberParameterizedLocation)location).getParamSetName();
+ final String baseFileName = StringUtil.trimEnd(StringUtil.trimStart(paramSetName, "["), "]");
+ final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(containingClass.getProject()).getFileIndex();
+ return TestDataGuessByExistingFilesUtil.suggestTestDataFiles(fileIndex, baseFileName, testDataPath, containingClass);
+ }
+ }
+ }
+ }
+ }
+
+ return null;
}
@Override
@@ -86,6 +121,14 @@
PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
return PsiTreeUtil.getParentOfType(element, PsiMethod.class);
}
+
+ final Location<?> location = Location.DATA_KEY.getData(context);
+ if (location != null) {
+ final PsiElement element = location.getPsiElement();
+ if (element instanceof PsiMethod) {
+ return (PsiMethod)element;
+ }
+ }
return null;
}
}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestCaseAsRelatedFileProvider.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestCaseAsRelatedFileProvider.java
new file mode 100644
index 0000000..438e82f
--- /dev/null
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestCaseAsRelatedFileProvider.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.testAssistant;
+
+import com.intellij.execution.Location;
+import com.intellij.navigation.GotoRelatedItem;
+import com.intellij.navigation.GotoRelatedProvider;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataContext;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collections;
+import java.util.List;
+
+public class TestCaseAsRelatedFileProvider extends GotoRelatedProvider {
+ @NotNull
+ @Override
+ public List<? extends GotoRelatedItem> getItems(@NotNull DataContext context) {
+ final Editor editor = CommonDataKeys.EDITOR.getData(context);
+ final Project project = CommonDataKeys.PROJECT.getData(context);
+ final VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(context);
+ if (editor == null || file == null || project == null) {
+ return Collections.emptyList();
+ }
+
+ final List<Location> locations = TestLocationDataRule.collectRelativeLocations(project, file);
+ if (locations.isEmpty()) {
+ return Collections.emptyList();
+ }
+
+ return ContainerUtil.map(locations, new Function<Location, GotoRelatedItem>() {
+ @Override
+ public GotoRelatedItem fun(Location location) {
+ return new GotoRelatedItem(location.getPsiElement());
+ }
+ });
+ }
+}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupFileEditor.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupFileEditor.java
index f690d96..3dcdb5e 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupFileEditor.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGroupFileEditor.java
@@ -25,6 +25,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Splitter;
import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -49,12 +50,7 @@
@NotNull
public JComponent getComponent() {
- JComponent result;
- if (myComponent == null) {
- myComponent = new WeakReference<JComponent>(result = createComponent());
- return result;
- }
- result = myComponent.get();
+ JComponent result = SoftReference.dereference(myComponent);
if (result == null) {
myComponent = new WeakReference<JComponent>(result = createComponent());
}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java
index 755a097..78cc06f 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataGuessByExistingFilesUtil.java
@@ -8,6 +8,7 @@
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Trinity;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
@@ -265,6 +266,14 @@
// return result;
//}
+ public static List<String> suggestTestDataFiles(@NotNull ProjectFileIndex fileIndex,
+ @NotNull String testName,
+ String testDataPath,
+ @NotNull PsiClass psiClass){
+ return buildDescriptor(fileIndex, Collections.singletonList(testName), psiClass).generate(testName, testDataPath);
+ }
+
+
@NotNull
private static TestDataDescriptor buildDescriptor(@NotNull ProjectFileIndex fileIndex,
@NotNull Collection<String> testNames,
@@ -446,6 +455,9 @@
}
public void populate(@NotNull String testName, @NotNull VirtualFile matched) {
+ final String withoutExtension = FileUtil.getNameWithoutExtension(testName);
+ boolean excludeExtension = !withoutExtension.equals(testName);
+ testName = withoutExtension;
final String fileName = matched.getNameWithoutExtension();
int i = fileName.indexOf(testName);
final char firstChar = testName.charAt(0);
@@ -465,7 +477,7 @@
filePrefix = fileName.substring(0, i);
fileSuffix = fileName.substring(i + testName.length());
- ext = matched.getExtension();
+ ext = excludeExtension ? "" : matched.getExtension();
dir = matched.getParent().getPath();
}
@@ -523,11 +535,17 @@
@NotNull
public List<String> generate(@NotNull final String testName) {
+ return generate(testName, null);
+ }
+
+ @NotNull
+ public List<String> generate(@NotNull final String testName, String root) {
List<String> result = new ArrayList<String>();
if (StringUtil.isEmpty(testName)) {
return result;
}
for (TestLocationDescriptor descriptor : myDescriptors) {
+ if (root != null && !root.equals(descriptor.dir)) continue;
result.add(String.format(
"%s/%s%c%s%s.%s",
descriptor.dir, descriptor.filePrefix,
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java
index 81d7543..7377691 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataLineMarkerProvider.java
@@ -17,19 +17,24 @@
import com.intellij.codeHighlighting.Pass;
import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
import com.intellij.codeInsight.daemon.LineMarkerInfo;
import com.intellij.codeInsight.daemon.LineMarkerProvider;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
+import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.awt.event.MouseEvent;
+import java.io.File;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -53,6 +58,22 @@
method, method.getModifierList().getTextRange(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null, new TestDataNavigationHandler(),
GutterIconRenderer.Alignment.LEFT);
}
+ } else if (element instanceof PsiClass) {
+ final PsiClass psiClass = (PsiClass)element;
+ final String basePath = getTestDataBasePath(psiClass);
+ if (basePath != null) {
+ return new LineMarkerInfo<PsiClass>(
+ psiClass, psiClass.getModifierList().getTextRange(), PlatformIcons.TEST_SOURCE_FOLDER, Pass.UPDATE_ALL, null, new GutterIconNavigationHandler<PsiClass>() {
+ @Override
+ public void navigate(MouseEvent e, PsiClass elt) {
+ final VirtualFile baseDir = VfsUtil.findFileByIoFile(new File(basePath), true);
+ if (baseDir != null) {
+ new OpenFileDescriptor(psiClass.getProject(), baseDir).navigate(true);
+ }
+ }
+ },
+ GutterIconRenderer.Alignment.LEFT);
+ }
}
return null;
}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java
index 0836963..caa610b 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataNavigationHandler.java
@@ -66,20 +66,22 @@
if (fileNames == null || fileNames.isEmpty()) {
return;
}
- navigate(method, point, fileNames);
+ navigate(point, fileNames, method.getProject());
}
- public static void navigate(@NotNull PsiMethod method, @NotNull final RelativePoint point, @NotNull List<String> testDataFiles) {
+ public static void navigate(@NotNull final RelativePoint point,
+ @NotNull List<String> testDataFiles,
+ final Project project) {
if (testDataFiles.size() == 1) {
- openFileByIndex(method.getProject(), testDataFiles, 0);
+ openFileByIndex(project, testDataFiles, 0);
}
else if (testDataFiles.size() > 1) {
TestDataGroupVirtualFile groupFile = getTestDataGroup(testDataFiles);
if (groupFile != null) {
- new OpenFileDescriptor(method.getProject(), groupFile).navigate(true);
+ new OpenFileDescriptor(project, groupFile).navigate(true);
}
else {
- showNavigationPopup(method.getProject(), testDataFiles, point);
+ showNavigationPopup(project, testDataFiles, point);
}
}
}
@@ -164,7 +166,7 @@
else {
int rc = Messages.showYesNoDialog(project, "The referenced testdata file " + path + " does not exist. Would you like to create it?",
"Create Testdata File", Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
VirtualFile vFile = createFileByName(project, path);
new OpenFileDescriptor(project, vFile).navigate(true);
}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java
index 28de8d3..dbe3cf2 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataReferenceContributor.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,26 +21,26 @@
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileInfoManager;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
-import java.util.Collections;
import static com.intellij.patterns.PsiJavaPatterns.literalExpression;
import static com.intellij.testAssistant.TestDataLineMarkerProvider.*;
/**
- * User: zolotov
- * Date: 9/20/13
+ * @author zolotov
+ * @since 9/20/13
*/
public class TestDataReferenceContributor extends PsiReferenceContributor {
@Override
@@ -82,13 +82,7 @@
@NotNull
@Override
public Collection<PsiFileSystemItem> computeDefaultContexts() {
- final VirtualFile localSystemRoot = LocalFileSystem.getInstance().getRoot();
- final PsiManager psiManager = PsiManager.getInstance(getElement().getProject());
- final PsiDirectory psiRoot = psiManager.findDirectory(localSystemRoot);
- if (psiRoot != null) {
- return Collections.<PsiFileSystemItem>singleton(psiRoot);
- }
- return super.computeDefaultContexts();
+ return toFileSystemItems(ManagingFS.getInstance().getLocalRoots());
}
@Override
@@ -118,8 +112,9 @@
variants.add(FileInfoManager.getFileLookupItem(contentPsiRoot, CONTENT_ROOT_VARIABLE, contentPsiRoot.getIcon(0))
.withTypeText(contentPsiRoot.getVirtualFile().getPath(), true));
}
- return variants.toArray(new Object[variants.size()]);
+ return ArrayUtil.toObjectArray(variants);
}
+
return super.getVariants();
}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataRelatedItem.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataRelatedItem.java
index 9002792..297afc2 100644
--- a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataRelatedItem.java
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestDataRelatedItem.java
@@ -53,6 +53,7 @@
@Override
public void navigate() {
- TestDataNavigationHandler.navigate(myMethod, JBPopupFactory.getInstance().guessBestPopupLocation(myEditor), myTestDataFiles);
+ TestDataNavigationHandler.navigate(JBPopupFactory.getInstance().guessBestPopupLocation(myEditor), myTestDataFiles,
+ myMethod.getProject());
}
}
diff --git a/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestLocationDataRule.java b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestLocationDataRule.java
new file mode 100644
index 0000000..5042f77
--- /dev/null
+++ b/plugins/IdeaTestAssistant/src/com/intellij/testAssistant/TestLocationDataRule.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.testAssistant;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.execution.Location;
+import com.intellij.execution.PsiLocation;
+import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
+import com.intellij.execution.junit2.info.MethodLocation;
+import com.intellij.ide.impl.dataRules.GetDataRule;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.actionSystem.DataProvider;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScopesCore;
+import com.intellij.psi.search.PsiSearchHelper;
+import com.intellij.testFramework.Parameterized;
+import com.intellij.testFramework.TestDataPath;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.containers.ContainerUtil;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+public class TestLocationDataRule implements GetDataRule {
+ @Nullable
+ @Override
+ public Object getData(DataProvider dataProvider) {
+ final Project project = CommonDataKeys.PROJECT.getData(dataProvider);
+ final VirtualFile file = CommonDataKeys.VIRTUAL_FILE.getData(dataProvider);
+ if (project != null && file != null) {
+ final List<Location> locations = collectRelativeLocations(project, file);
+ return locations.size() == 1 ? locations.get(0) : null;
+ }
+ return null;
+ }
+
+ @NotNull
+ protected static List<Location> collectRelativeLocations(Project project, VirtualFile file) {
+ final List<Location> locations = new ArrayList<Location>();
+ final ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+ if (fileIndex.isInContent(file) && !fileIndex.isInSource(file) && !fileIndex.isInLibraryClasses(file)) {
+ final VirtualFile parent = file.getParent();
+ final VirtualFile contentRoot = fileIndex.getContentRootForFile(file);
+ if (contentRoot != null) {
+ final String relativePath = VfsUtilCore.getRelativePath(parent, contentRoot, '/');
+ if (relativePath != null) {
+ final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(project);
+ final List<String> words = StringUtil.getWordsIn(relativePath);
+ // put longer strings first
+ Collections.sort(words, new Comparator<String>() {
+ @Override
+ public int compare(final String o1, final String o2) {
+ return o2.length() - o1.length();
+ }
+ });
+
+ final GlobalSearchScope testScope = GlobalSearchScopesCore.projectTestScope(project);
+ Set<PsiFile> resultFiles = null;
+ for (String word : words) {
+ if (word.length() < 5) {
+ continue;
+ }
+ final Set<PsiFile> files = new THashSet<PsiFile>();
+ searchHelper.processAllFilesWithWordInLiterals(word, testScope, new CommonProcessors.CollectProcessor<PsiFile>(files));
+ if (resultFiles == null) {
+ resultFiles = files;
+ }
+ else {
+ resultFiles.retainAll(files);
+ }
+ if (resultFiles.isEmpty()) break;
+ }
+ if (resultFiles != null) {
+ for (Iterator<PsiFile> iterator = resultFiles.iterator(); iterator.hasNext(); ) {
+ if (!VfsUtilCore.isAncestor(contentRoot, iterator.next().getVirtualFile(), true)) {
+ iterator.remove();
+ }
+ }
+
+ final String fileName = file.getName();
+ final String nameWithoutExtension = file.getNameWithoutExtension();
+
+
+ for (PsiFile resultFile : resultFiles) {
+ if (resultFile instanceof PsiClassOwner) {
+ final PsiClass[] classes = ((PsiClassOwner)resultFile).getClasses();
+ if (classes.length > 0) {
+ ContainerUtil.addIfNotNull(locations, getLocation(project, fileName, nameWithoutExtension, classes[0]));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return locations;
+ }
+
+ @Nullable
+ private static Location getLocation(Project project,
+ String fileName,
+ String nameWithoutExtension,
+ PsiClass aClass) {
+ final PsiAnnotation annotation = AnnotationUtil.findAnnotation(aClass, TestDataPath.class.getName());
+ if (annotation != null) {
+ final Location parameterizedLocation =
+ PsiMemberParameterizedLocation.getParameterizedLocation(aClass, "[" + fileName + "]", Parameterized.class.getName());
+ if (parameterizedLocation != null) {
+ return parameterizedLocation;
+ }
+ if (StringUtil.isJavaIdentifier(nameWithoutExtension)) {
+ final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
+ PsiMethod method = aClass.findMethodBySignature(elementFactory.createMethod("test" + nameWithoutExtension, PsiType.VOID), true);
+ if (method != null) {
+ return MethodLocation.elementInClass(method, aClass);
+ }
+
+ method = aClass.findMethodBySignature(elementFactory.createMethod("test" + StringUtil.capitalize(nameWithoutExtension), PsiType.VOID), true);
+ if (method != null) {
+ return MethodLocation.elementInClass(method, aClass);
+ }
+ }
+ return new PsiLocation<PsiElement>(project, aClass);
+ }
+ return null;
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
index 0549761..dddb6e1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml
@@ -136,10 +136,6 @@
implementationClass="com.siyeh.ig.bitwise.ShiftOutOfRangeInspection"/>
<!--group.names.probable.bugs-->
- <localInspection language="JAVA" suppressId="UseOfArchaicSystemPropertyAccessors" shortName="ArchaicSystemPropertyAccess"
- bundle="com.siyeh.InspectionGadgetsBundle" key="archaic.system.property.accessors.display.name"
- groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="false" level="WARNING"
- implementationClass="com.siyeh.ig.bugs.ArchaicSystemPropertyAccessInspection"/>
<localInspection language="JAVA" shortName="ArrayEquality" bundle="com.siyeh.InspectionGadgetsBundle" key="array.comparison.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.bugs.ArrayEqualityInspection"/>
@@ -458,10 +454,6 @@
key="missing.deprecated.annotation.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING" runForWholeFile="true"
implementationClass="com.siyeh.ig.classlayout.MissingDeprecatedAnnotationInspection"/>
- <localInspection language="JAVA" suppressId="override" shortName="MissingOverrideAnnotation" bundle="com.siyeh.InspectionGadgetsBundle"
- key="missing.override.annotation.display.name" groupBundle="messages.InspectionsBundle"
- groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
- implementationClass="com.siyeh.ig.classlayout.MissingOverrideAnnotationInspection"/>
<localInspection language="JAVA" shortName="MultipleTopLevelClassesInFile" bundle="com.siyeh.InspectionGadgetsBundle"
key="multiple.top.level.classes.in.file.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
@@ -511,6 +503,10 @@
key="method.return.always.constant.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.classlayout.MethodReturnAlwaysConstantInspection"/>
+ <localInspection language="JAVA" shortName="InterfaceMayBeAnnotatedFunctional" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="interface.may.be.annotated.functional.display.name" groupBundle="messages.InspectionsBundle"
+ groupKey="group.names.class.structure" enabledByDefault="false" level="WARNING"
+ implementationClass="com.siyeh.ig.classlayout.InterfaceMayBeAnnotatedFunctionalInspection"/>
<!--group.names.class.metrics-->
<localInspection language="JAVA" suppressId="OverlyComplexAnonymousInnerClass" shortName="AnonymousClassComplexity"
@@ -764,10 +760,6 @@
key="negatively.named.boolean.variable.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.data.flow.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.dataflow.NegativelyNamedBooleanVariableInspection"/>
- <localInspection language="JAVA" shortName="OrredNotEqualExpression" bundle="com.siyeh.InspectionGadgetsBundle"
- key="orred.not.equal.expression.display.name" groupBundle="messages.InspectionsBundle"
- groupKey="group.names.data.flow.issues" enabledByDefault="true" level="WARNING"
- implementationClass="com.siyeh.ig.dataflow.OrredNotEqualExpressionInspection"/>
<localInspection language="JAVA" shortName="ReuseOfLocalVariable" bundle="com.siyeh.InspectionGadgetsBundle" key="reuse.of.local.variable.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.data.flow.issues" enabledByDefault="false"
level="WARNING" implementationClass="com.siyeh.ig.dataflow.ReuseOfLocalVariableInspection"/>
@@ -1036,6 +1028,10 @@
key="type.parameter.extends.final.class.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.inheritance.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.inheritance.TypeParameterExtendsFinalClassInspection"/>
+ <localInspection language="JAVA" suppressId="override" shortName="MissingOverrideAnnotation" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="missing.override.annotation.display.name" groupBundle="messages.InspectionsBundle"
+ groupKey="group.names.inheritance.issues" enabledByDefault="false" level="WARNING"
+ implementationClass="com.siyeh.ig.inheritance.MissingOverrideAnnotationInspection"/>
<!--group.names.initialization.issues-->
<localInspection language="JAVA" shortName="AbstractMethodCallInConstructor" bundle="com.siyeh.InspectionGadgetsBundle"
@@ -1133,6 +1129,10 @@
key="unnecessary.unicode.escape.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.internationalization.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.internationalization.UnnecessaryUnicodeEscapeInspection"/>
+<localInspection language="JAVA" shortName="ImplicitDefaultCharsetUsage" bundle="com.siyeh.InspectionGadgetsBundle"
+ key="implicit.default.charset.usage.display.name" groupBundle="messages.InspectionsBundle"
+ groupKey="group.names.internationalization.issues" enabledByDefault="false" level="WARNING"
+ implementationClass="com.siyeh.ig.internationalization.ImplicitDefaultCharsetUsageInspection"/>
<!--group.names.j2me.issues-->
<localInspection language="JAVA" shortName="AbstractClassWithOnlyOneDirectInheritor" bundle="com.siyeh.InspectionGadgetsBundle"
@@ -1386,7 +1386,7 @@
groupBundle="messages.InspectionsBundle" groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.junit.MisspelledTearDownInspection"/>
<localInspection language="JAVA" suppressId="MisorderedAssertEqualsArguments" alternativeId="MisorderedAssertEqualsArguments" shortName="MisorderedAssertEqualsParameters"
- bundle="com.siyeh.InspectionGadgetsBundle" key="misordered.assert.equals.parameters.display.name"
+ bundle="com.siyeh.InspectionGadgetsBundle" key="misordered.assert.equals.arguments.display.name"
groupBundle="messages.InspectionsBundle" groupKey="group.names.junit.issues" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.junit.MisorderedAssertEqualsParametersInspection"/>
<localInspection language="JAVA" shortName="MultipleExceptionsDeclaredOnTestMethod" bundle="com.siyeh.InspectionGadgetsBundle"
@@ -1503,7 +1503,7 @@
enabledByDefault="false" level="WARNING" implementationClass="com.siyeh.ig.maturity.ThreadDumpStackInspection"/>
<localInspection language="JAVA" shortName="ThrowablePrintedToSystemOut" bundle="com.siyeh.InspectionGadgetsBundle"
key="throwable.printed.to.system.out.display.name" groupBundle="messages.InspectionsBundle"
- groupKey="group.names.code.maturity.issues" enabledByDefault="false" level="WARNING"
+ groupKey="group.names.code.maturity.issues" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.maturity.ThrowablePrintedToSystemOutInspection"/>
<localInspection language="JAVA" suppressId="UseOfObsoleteCollectionType" shortName="ObsoleteCollection" bundle="com.siyeh.InspectionGadgetsBundle"
key="use.obsolete.collection.type.display.name" groupBundle="messages.InspectionsBundle"
@@ -1584,6 +1584,9 @@
implementationClass="com.siyeh.ig.modularization.ModuleWithTooFewClassesInspection"/>
<!--group.names.naming.conventions-->
+ <localInspection language="JAVA" shortName="AbstractClassNamingConvention" bundle="com.siyeh.InspectionGadgetsBundle" key="abstract.class.naming.convention.display.name"
+ groupBundle="messages.InspectionsBundle" groupKey="group.names.naming.conventions" enabledByDefault="false"
+ level="WARNING" implementationClass="com.siyeh.ig.naming.AbstractClassNamingConventionInspection"/>
<localInspection language="JAVA" shortName="AnnotationNamingConvention" bundle="com.siyeh.InspectionGadgetsBundle"
key="annotation.naming.convention.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.naming.conventions" enabledByDefault="false" level="WARNING"
@@ -2631,7 +2634,7 @@
level="WARNING" implementationClass="com.siyeh.ig.visibility.MethodOverridesStaticMethodInspection"/>
<localInspection language="JAVA" shortName="TypeParameterHidesVisibleType" bundle="com.siyeh.InspectionGadgetsBundle"
key="type.parameter.hides.visible.type.display.name" groupBundle="messages.InspectionsBundle"
- groupKey="group.names.visibility.issues" enabledByDefault="false" level="WARNING"
+ groupKey="group.names.visibility.issues" enabledByDefault="true" level="WARNING"
implementationClass="com.siyeh.ig.visibility.TypeParameterHidesVisibleTypeInspection"/>
<localInspection language="JAVA" suppressId="ParameterHidesMemberVariable" shortName="ParameterHidingMemberVariable"
bundle="com.siyeh.InspectionGadgetsBundle" key="parameter.hides.member.variable.display.name"
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java
index 9015fe3..cf9cbb0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/intellij/codeInspection/booleanIsAlwaysInverted/BooleanMethodIsAlwaysInvertedInspectionBase.java
@@ -21,13 +21,19 @@
import com.intellij.codeInspection.reference.*;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
+import com.intellij.psi.search.LocalSearchScope;
+import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.Processor;
+import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
+import java.util.Set;
public class BooleanMethodIsAlwaysInvertedInspectionBase extends GlobalJavaBatchInspectionTool {
private static final Key<Boolean> ALWAYS_INVERTED = Key.create("ALWAYS_INVERTED_METHOD");
@@ -124,6 +130,20 @@
final PsiMethod psiMethod = (PsiMethod)refMethod.getElement();
final PsiIdentifier psiIdentifier = psiMethod.getNameIdentifier();
if (psiIdentifier != null) {
+ final Collection<RefElement> inReferences = refMethod.getInReferences();
+ if (inReferences.size() == 1) {
+ final RefElement refElement = inReferences.iterator().next();
+ final PsiElement usagesContainer = refElement.getElement();
+ if (usagesContainer == null) return null;
+ if (ReferencesSearch.search(psiMethod, new LocalSearchScope(usagesContainer)).forEach(new Processor<PsiReference>() {
+ private final Set<PsiReference> myFoundRefs = new HashSet<PsiReference>();
+ @Override
+ public boolean process(PsiReference reference) {
+ myFoundRefs.add(reference);
+ return myFoundRefs.size() < 2;
+ }
+ })) return null;
+ }
return new ProblemDescriptor[]{manager.createProblemDescriptor(psiIdentifier,
InspectionsBundle
.message("boolean.method.is.always.inverted.problem.descriptor"),
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.java
index 2b655e4..66847cc 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author max
*/
public class InspectionGadgetsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "com.siyeh.InspectionGadgetsBundle";
private InspectionGadgetsBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
index eb6ec6c..7f61b37 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties
@@ -1,6 +1,3 @@
-plugin.InspectionGadgets.description=Adds over 600 new automated code inspections for IntelliJ IDEA.
-error.message.regexp.malformed.naming.pattern=Malformed Naming Pattern
-error.message.regexp.malformed.pattern=Malformed Regular Expression Pattern
cast.to.concrete.class.display.name=Cast to a concrete class
cast.to.concrete.class.problem.descriptor=Cast to concrete class <code>{0}</code> #loc
class.references.subclass.display.name=Class references one of its subclasses
@@ -22,7 +19,7 @@
instanceof.check.for.this.problem.descriptor='instanceof' check for <code>#ref</code> #loc
local.variable.of.concrete.class.display.name=Local variable of concrete class
local.variable.of.concrete.class.problem.descriptor=Local variable ''{0}'' of concrete class <code>#ref</code> #loc
-magic.number.display.name="Magic number"
+magic.number.display.name=Magic number
magic.number.problem.descriptor=Magic number <code>#ref</code> #loc
magic.number.ignore.option=Ignore constants in 'hashCode()' methods
method.return.concrete.class.display.name=Method return of concrete class
@@ -45,12 +42,6 @@
shift.operation.by.inappropriate.constant.display.name=Shift operation by inappropriate constant
shift.operation.by.inappropriate.constant.problem.descriptor.too.large=Shift operation <code>#ref</code> by overly large constant value #loc
shift.operation.by.inappropriate.constant.problem.descriptor.negative=Shift operation <code>#ref</code> by negative constant value #loc
-archaic.system.property.accessors.display.name=Use of archaic system property accessors
-archaic.system.property.accessors.problem.descriptor.Integer=Call to <code>Integer.#ref()</code> accesses system properties, perhaps confusingly #loc
-archaic.system.property.accessors.problem.descriptor.Long=Call to <code>Long.#ref()</code> accesses system properties, perhaps confusingly #loc
-archaic.system.property.accessors.problem.descriptor.Boolean=Call to <code>Boolean.#ref()</code> accesses system properties, perhaps confusingly #loc
-archaic.system.property.accessors.replace.parse.quickfix=Replace with parse method
-archaic.system.property.accessors.replace.standard.quickfix=Replace with standard property access
equals.called.on.array.display.name='equals()' called on array
equals.called.on.array.problem.descriptor=<code>#ref()</code> between arrays should probably be 'Arrays.equals()' #loc
replace.with.arrays.equals=Replace with 'Arrays.equals()'
@@ -339,8 +330,8 @@
accessing.non.public.field.of.another.object.problem.descriptor=Direct access of non-public field <code>#ref</code> on another object #loc
call.to.date.tostring.display.name=Call to 'Date.toString()'
call.to.date.tostring.problem.descriptor=<code>Date.#ref()</code> used in an internationalized context #loc
-magic.character.display.name="Magic character"
-magic.character.problem.descriptor="Magic character" <code>#ref</code> in an internationalized context #loc
+magic.character.display.name=Magic character
+magic.character.problem.descriptor=Magic character <code>#ref</code> in an internationalized context #loc
call.to.numeric.tostring.display.name=Call to Numeric 'toString()'
call.to.numeric.tostring.problem.descriptor=Numeric <code>#ref()</code> called in an internationalized context #loc
instantiating.simpledateformat.without.locale.display.name=Instantiating a SimpleDateFormat without a Locale
@@ -354,10 +345,9 @@
string.concatenation.ignore.assert.option=Ignore for assert statement arguments
string.concatenation.ignore.exceptions.option=Ignore for throwable arguments
string.concatenation.ignore.constant.initializers.option=Ignore for initializers of constants
-ignore.in.test.code=Ignore in &test code
ignore.in.annotations=Ignore in annotations
ignore.in.tostring=Ignore inside toString() methods
-ignore.as.initial.capacity=Ignore initial capacity argument when constructing StringBuilders and Collections
+ignore.as.initial.capacity=Ignore initial capacity for StringBuilders and Collections
string.equalsignorecase.call.display.name=Call to 'String.equalsIgnoreCase()'
string.equalsignorecase.call.problem.descriptor=<code>String.#ref()</code> using internationalized strings #loc
string.equals.call.display.name=Call to 'String.equals()'
@@ -394,7 +384,8 @@
parameter.hides.member.variable.ignore.abstract.methods.option=Ignore for abstract methods
parameter.hides.member.variable.ignore.static.parameters.option=Ignore for static method parameters hiding instance fields
type.parameter.hides.visible.type.display.name=Type parameter hides visible type
-type.parameter.hides.visible.type.problem.descriptor=Type parameter <code>#ref</code> hides a visible type ''{0}'' #loc
+type.parameter.hides.visible.type.problem.descriptor=Type parameter <code>#ref</code> hides visible type ''{0}'' #loc
+type.parameter.hides.type.parameter.problem.descriptor=Type parameter <code>#ref</code> hides type parameter ''{0}'' #loc
anonymous.class.variable.hides.containing.method.variable.display.name=Anonymous class variable hides variable in containing method
anonymous.class.parameter.hides.containing.method.variable.problem.descriptor=Anonymous class parameter <code>#ref</code> hides variable in containing method #loc
anonymous.class.field.hides.containing.method.variable.problem.descriptor=Anonymous class field <code>#ref</code> hides variable in containing method #loc
@@ -619,6 +610,7 @@
local.variable.naming.convention.display.name=Local variable naming convention
negated.if.else.display.name='if' statement with negated condition
class.naming.convention.display.name=Class naming convention
+abstract.class.naming.convention.display.name=Abstract class naming convention
serializable.inner.class.with.non.serializable.outer.class.display.name=Serializable non-'static' inner class with non-Serializable outer class
pointless.arithmetic.expression.display.name=Pointless arithmetic expression
method.name.same.as.class.name.display.name=Method name same as class name
@@ -679,6 +671,8 @@
string.buffer.must.have.initial.capacity.display.name=StringBuffer or StringBuilder without initial capacity
method.may.be.static.display.name=Method may be 'static'
class.initializer.may.be.static.display.name=Class initializer may be 'static'
+class.initializer.option=Only warn when the class has one or more constructors
+class.initializer.move.code.to.constructor.quickfix=Move initializer code to constructor
nested.switch.statement.display.name=Nested 'switch' statement
c.style.array.declaration.display.name=C-style array declaration
final.method.in.final.class.display.name='final' method in 'final' class
@@ -734,7 +728,7 @@
unnecessary.interface.modifier.display.name=Unnecessary interface modifier
confusing.main.method.display.name=Confusing 'main()' method
octal.literal.display.name=Octal integer
-misordered.assert.equals.parameters.display.name=Misordered 'assertEquals()' arguments
+misordered.assert.equals.arguments.display.name=Misordered 'assertEquals()' arguments
unnecessary.constructor.display.name=Redundant no-arg constructor
method.name.same.as.parent.name.display.name=Method name same as parent class name
java.lang.reflect.display.name=Use of 'java.lang.reflect'
@@ -1043,7 +1037,7 @@
public.field.accessed.in.synchronized.context.problem.descriptor=Non-private field <code>#ref</code> accessed in synchronized context #loc
field.accessed.synchronized.and.unsynchronized.problem.descriptor=Field <code>#ref</code> is accessed in both synchronized and unsynchronized contexts #loc
extended.for.statement.problem.descriptor=Extended <code>#ref</code> statement #loc
-object.allocation.in.loop.problem.descriptor=Object allocation <code>#ref</code> in loop #loc
+object.allocation.in.loop.problem.descriptor=Object allocation <code>new #ref()</code> in loop #loc
instantiating.object.to.get.class.object.problem.descriptor=Instantiating object to get Class object #loc
field.may.be.static.problem.descriptor=Field <code>#ref</code> may be 'static' #loc
method.may.be.static.problem.descriptor=Method <code>#ref()</code> may be 'static' #loc
@@ -1051,15 +1045,15 @@
map.replaceable.by.enum.map.problem.descriptor=<code>#ref</code> replaceable with 'EnumMap' #loc
set.replaceable.by.enum.set.problem.descriptor=<code>#ref</code> replaceable with 'EnumSet' #loc
inner.class.may.be.static.problem.descriptor=Inner class <code>#ref</code> may be 'static' #loc
-string.buffer.must.have.initial.capacity.problem.descriptor=<code>#ref</code> without initial capacity #loc
+string.buffer.must.have.initial.capacity.problem.descriptor=<code>new #ref()</code> without initial capacity #loc
string.buffer.replaceable.by.string.builder.problem.descriptor=<code>StringBuffer #ref</code> may be declared as 'StringBuilder' #loc
string.buffer.replaceable.by.string.problem.descriptor=<code>{0} #ref</code> can be replaced with ''String'' #loc
new.string.buffer.replaceable.by.string.problem.descriptor=<code>#ref</code> can be replaced with 'String' #loc
string.replaceable.by.string.buffer.problem.descriptor=Non-constant <code>String #ref</code> should probably be declared as ''StringBuilder'' #loc
-collections.must.have.initial.capacity.problem.descriptor=<code>#ref</code> without initial capacity #loc
+collections.must.have.initial.capacity.problem.descriptor=<code>new #ref()</code> without initial capacity #loc
string.concatenation.in.loops.problem.descriptor=String concatenation <code>#ref</code> in loop #loc
string.concatenation.inside.string.buffer.append.problem.descriptor=String concatenation as argument to <code>{0}.#ref()</code> call #loc
-boolean.constructor.problem.descriptor=Boolean constructor call <code>#ref</code> #loc
+boolean.constructor.problem.descriptor=Boolean constructor call #loc
string.to.string.problem.descriptor=<code>#ref</code> is redundant #loc
substring.zero.problem.descriptor=<code>#ref</code> is redundant #loc
string.buffer.to.string.in.concatenation.problem.descriptor=Calls to <code>StringBuffer.#ref()</code> in concatenation #loc
@@ -1076,7 +1070,7 @@
test.case.with.constructor.problem.descriptor=Initialization logic in constructor <code>#ref()</code> instead of 'setUp()' #loc
test.case.with.constructor.problem.descriptor.initializer=Initialization logic in initializer instead of 'setUp()'
misspelled.set.up.problem.descriptor=<code>#ref()</code> probably be 'setUp()' #loc
-misordered.assert.equals.parameters.problem.descriptor=Arguments to <code>#ref()</code> in wrong order #loc
+misordered.assert.equals.arguments.problem.descriptor=Arguments to <code>#ref()</code> in wrong order #loc
misspelled.tear.down.problem.descriptor=<code>#ref()</code> method should probably be 'tearDown()' #loc
static.suite.problem.descriptor=JUnit <code>#ref()</code> methods not declared 'static' #loc
setup.calls.super.setup.problem.descriptor=<code>#ref()</code> does not call 'super.setUp()' #loc
@@ -1128,15 +1122,15 @@
annotation.naming.convention.problem.descriptor.long=Annotation name <code>#ref</code> is too long #loc
annotation.naming.convention.problem.descriptor.regex.mismatch=Annotation name <code>#ref</code> doesn''t match regex ''{0}'' #loc
class.name.convention.problem.descriptor.short=Class name <code>#ref</code> is too short #loc
+abstract.class.name.convention.problem.descriptor.short=Abstract class name <code>#ref</code> is too short #loc
class.name.convention.problem.descriptor.long=Class name <code>#ref</code> is too long #loc
+abstract.class.name.convention.problem.descriptor.long=Abstract class name <code>#ref</code> is too long #loc
class.name.convention.problem.descriptor.regex.mismatch=Class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
+abstract.class.name.convention.problem.descriptor.regex.mismatch=Abstract class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
constant.naming.convention.problem.descriptor.short=Constant name <code>#ref</code> is too short #loc
constant.naming.convention.problem.descriptor.long=Constant name <code>#ref</code> is too long #loc
constant.naming.convention.problem.descriptor.regex.mismatch=Constant <code>#ref</code> doesn''t match regex ''{0}'' #loc
constant.naming.convention.immutables.option=Only check 'static final' fields with immutable types
-convention.pattern.option=Pattern:
-convention.min.length.option=Min length:
-convention.max.length.option=Max length:
enumerated.class.naming.convention.problem.descriptor.short=Enumerated class name <code>#ref</code> is too short #loc
enumerated.class.naming.convention.problem.descriptor.long=Enumerated class name <code>#ref</code> is too long #loc
enumerated.class.naming.convention.problem.descriptor.regex.mismatch=Enumerated class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
@@ -1202,7 +1196,7 @@
foreach.replace.quickfix=Replace with 'foreach'
unnecessary.boxing.remove.quickfix=Remove boxing
unnecessary.unboxing.remove.quickfix=Remove unboxing
-misordered.assert.equals.parameters.flip.quickfix=Flip compared arguments
+misordered.assert.equals.arguments.flip.quickfix=Flip compared arguments
setup.calls.super.setup.add.quickfix=Add call to 'super.setUp()'
simplify.junit.assertion.simplify.quickfix=Simplify assertion
teardown.calls.super.teardown.add.quickfix=Add call to 'super.tearDown()'
@@ -1235,12 +1229,10 @@
exception.class.column.name=Exception class
bad.exception.thrown.problem.descriptor=Prohibited exception ''{0}'' thrown #loc
empty.catch.block.comments.option=Comments count as content
-empty.catch.block.ignore.option=Ignore empty 'catch' blocks in tests
-empty.catch.block.ignore.ignore.option=Ignore for 'catch' parameters named 'ignore' or 'ignored'
+empty.catch.block.ignore.ignore.option=Ignore when 'catch' parameter is named 'ignore' or 'ignored'
too.broad.catch.problem.descriptor=''catch'' of <code>#ref</code> is too broad, masking exception ''{0}'' #loc
too.broad.catch.problem.descriptor1=''catch'' of <code>#ref</code> is too broad, masking exceptions ''{0}'' and ''{1}'' #loc
-unused.catch.parameter.ignore.catch.option=Ignore for 'catch' blocks containing comments
-unused.catch.parameter.ignore.empty.option=Ignore unused 'catch' parameters in tests
+unused.catch.parameter.ignore.catch.option=Ignore when 'catch' block contains a comment
add.serialversionuidfield.quickfix=Add 'serialVersionUID' field
delete.import.quickfix=Delete unnecessary import
encapsulate.variable.quickfix=Encapsulate field ''{0}''
@@ -1516,6 +1508,8 @@
cyclic.class.dependency.2.problem.descriptor=Class ''{0}'' is cyclically dependent on classes ''{1}'' and ''{2}''
cyclic.package.dependency.display.name=Cyclic package dependency
cyclic.package.dependency.problem.descriptor=Package ''{0}'' is cyclically dependent on {1} other packages
+cyclic.package.dependency.1.problem.descriptor=Package ''{0}'' is cyclically dependent on package ''{1}''
+cyclic.package.dependency.2.problem.descriptor=Package ''{0}'' is cyclically dependent on packages ''{1}'' and ''{2}''
class.unconnected.to.package.display.name=Class independent of its package
class.unconnected.to.package.problem.descriptor=Class <code>#ref</code> has no dependencies or dependents in its package
package.with.too.many.classes.display.name=Package with too many classes
@@ -1533,7 +1527,7 @@
package.in.multiple.modules.display.name=Package with classes in multiple modules
package.in.multiple.modules.problem.descriptor=Package ''{0}'' has classes in multiple modules
disjoint.package.display.name=Package with disjoint dependency graph
-disjoint.package.problem.descriptor=Package {0} can be decomposed into {1} independent packages #loc
+disjoint.package.problem.descriptor=Package {0} can be decomposed into {1} independent packages
package.naming.convention.display.name=Package naming convention
package.naming.convention.problem.descriptor.short=Package name <code>{0}</code> is too short
package.naming.convention.problem.descriptor.long=Package name <code>{0}</code> is too long
@@ -1592,7 +1586,6 @@
unqualified.method.access.display.name=Instance method call not qualified with 'this'
unqualified.method.access.problem.descriptor=Instance method call <code>#ref</code> is not qualified with 'this' #loc
add.this.qualifier.quickfix=Add 'this' qualifier
-feature.envy.ignore.test.cases.option=Ignore feature envy in tests
while.loop.spins.on.field.ignore.non.empty.loops.option=Only warn if the loop is empty
method.may.be.synchronized.problem.descriptor=Method <code>#ref()</code> with synchronized block could be synchronized method #loc
method.may.be.synchronized.display.name=Method with synchronized block could be synchronized method
@@ -1683,6 +1676,7 @@
synchronization.on.local.variable.problem.descriptor=Synchronization on local variable <code>#ref</code> #loc
synchronization.on.method.parameter.problem.descriptor=Synchronization on method parameter <code>#ref</code> #loc
too.broad.catch.quickfix=Add ''catch'' clause for ''{0}''
+replace.with.catch.clause.for.runtime.exception.quickfix=Replace with 'catch' clause for 'RuntimeException'
too.broad.catch.option=&Only warn on RuntimeException, Exception, Error or Throwable
unnecessary.call.to.string.valueof.display.name=Unnecessary call to 'String.valueOf()'
unnecessary.tostring.call.display.name=Unnecessary call to 'toString()'
@@ -1759,9 +1753,6 @@
assert.with.side.effects.display.name='assert' statement with side effects
assert.with.side.effects.problem.descriptor=<code>#ref</code> has side effects #loc
method.count.ignore.getters.setters.option=&Ignore simple getter and setter methods
-orred.not.equal.expression.display.name=Identical reference in '!=' expression on both sides of '||' expression
-orred.not.equal.expression.problem.descriptor=<code>#ref</code> is always true #loc
-orred.not.equal.expression.quickfix=Change '||' to '\\&\\&'
class.new.instance.display.name=Unsafe call to 'Class.newInstance()'
class.new.instance.problem.descriptor=Call to <code>#ref()</code> may throw undeclared checked exceptions #loc
class.new.instance.quickfix=Replace with 'Class.getConstructor().newInstance()' call
@@ -1813,7 +1804,6 @@
expected.exception.never.thrown.problem.descriptor=Expected <code>#ref</code> never thrown in body of ''{0}()'' #loc
choose.logger.class=Choose logger class
logger.class.name=Logger class name
-ignore.exceptions.declared.in.tests.option=Ignore exceptions declared in &tests
ignore.exceptions.declared.on.library.override.option=Ignore exceptions declared on methods overriding a &library method
allow.resource.to.be.opened.inside.a.try.block=Allow resource to be opened inside a 'try' block
log.method.name=Logging method name
@@ -1915,7 +1905,6 @@
boolean.variable.always.inverted.display.name=Boolean variable is always inverted
boolean.field.always.inverted.problem.descriptor=Boolean field <code>#ref</code> is always inverted #loc
boolean.variable.always.inverted.problem.descriptor=Boolean variable <code>#ref</code> is always inverted #loc
-boolean.variable.always.inverted.quickfix=Invert ''{0}''
unnecessary.explicit.numeric.cast.display.name=Unnecessary explicit numeric cast
unnecessary.explicit.numeric.cast.problem.descriptor=''{0}'' unnecessarily cast to <code>#ref</code> #loc
unnecessary.explicit.numeric.cast.quickfix=Remove cast
@@ -1956,7 +1945,7 @@
class.only.used.in.one.package.problem.descriptor=Class <code>#ref</code> has only dependencies on and/or dependents in package ''{0}'' #loc
unnecessary.return.option=Ignore in then branch of 'if' statement with 'else' branch
usage.of.obsolete.assert.display.name=Usage of obsolete 'junit.framework.Assert'
-use.of.obsolete.assert.problem.descriptor=Call to <code>#ref()</code> from 'org.junit.framework.Assert' should be replaced with call to method from 'org.junit.Assert' #loc
+use.of.obsolete.assert.problem.descriptor=Call to <code>#ref()</code> from 'junit.framework.Assert' should be replaced with call to method from 'org.junit.Assert' #loc
use.of.obsolete.assert.quickfix=Replace with 'org.junit.Assert' method call
properties.object.as.hashtable.set.quickfix=Replace with call to 'setProperty()'
properties.object.as.hashtable.get.quickfix=Replace with call to 'getProperty()'
@@ -2070,3 +2059,10 @@
invert.quickfix=Invert ''{0}''
throwable.printed.to.system.out.display.name='Throwable' printed to 'System.out'
throwable.printed.to.system.out.problem.descriptor='Throwable' argument <code>#ref</code> to ''System.{0}.{1}()'' call
+suppress.for.tests.scope.quickfix=Suppress for 'Tests' scope
+implicit.default.charset.usage.display.name=Implicit usage of platform's default charset
+implicit.default.charset.usage.problem.descriptor=Call to <code>#ref()</code> uses the platform's default charset
+implicit.default.charset.usage.constructor.problem.descriptor=<code>new #ref()</code> call uses the platform's default charset
+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
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspection.java
index d8b12a9..6a389f2 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/BaseInspection.java
@@ -15,11 +15,15 @@
*/
package com.siyeh.ig;
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.ui.DocumentAdapter;
import com.intellij.util.ui.UIUtil;
@@ -209,4 +213,11 @@
timestamp = -1L;
}
}
+
+ public static boolean isInspectionEnabled(@NonNls String shortName, PsiElement context) {
+ final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(context.getProject());
+ final InspectionProfileImpl profile = (InspectionProfileImpl)profileManager.getInspectionProfile();
+ final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
+ return profile.isToolEnabled(key, context);
+ }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
index ab3e0a1..3ac24dd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/InspectionGadgetsFix.java
@@ -71,99 +71,6 @@
element.delete();
}
- protected static void replaceExpression(@NotNull PsiExpression expression, @NotNull @NonNls String newExpressionText) {
- final Project project = expression.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiExpression newExpression = factory.createExpressionFromText(newExpressionText, expression);
- final PsiElement replacementExpression = expression.replace(newExpression);
- final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
- styleManager.reformat(replacementExpression);
- }
-
- protected static void replaceExpressionWithReferenceTo(@NotNull PsiExpression expression, @NotNull PsiMember target) {
- final Project project = expression.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiReferenceExpression newExpression = (PsiReferenceExpression)factory.createExpressionFromText("xxx", expression);
- final PsiReferenceExpression replacementExpression = (PsiReferenceExpression)expression.replace(newExpression);
- final PsiElement element = replacementExpression.bindToElement(target);
- final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
- styleManager.shortenClassReferences(element);
- }
-
- protected static PsiElement replaceExpressionAndShorten(@NotNull PsiExpression expression, @NotNull @NonNls String newExpressionText) {
- final Project project = expression.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiExpression newExpression = factory.createExpressionFromText(newExpressionText, expression);
- final PsiElement replacementExp = expression.replace(newExpression);
- final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
- javaCodeStyleManager.shortenClassReferences(replacementExp);
- final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
- return styleManager.reformat(replacementExp);
- }
-
- protected static PsiElement replaceStatement(@NotNull PsiStatement statement, @NotNull @NonNls String newStatementText) {
- final Project project = statement.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
- final PsiElement replacementExp = statement.replace(newStatement);
- final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
- return styleManager.reformat(replacementExp);
- }
-
- protected static void replaceStatementAndShortenClassNames(@NotNull PsiStatement statement, @NotNull @NonNls String newStatementText) {
- final Project project = statement.getProject();
- final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
- final JavaCodeStyleManager javaStyleManager = JavaCodeStyleManager.getInstance(project);
- if (FileTypeUtils.isInServerPageFile(statement)) {
- final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
- final PsiFile jspFile = PsiUtilCore.getTemplateLanguageFile(statement);
- if (jspFile == null) {
- return;
- }
- final Document document = documentManager.getDocument(jspFile);
- if (document == null) {
- return;
- }
- documentManager.doPostponedOperationsAndUnblockDocument(document);
- final TextRange textRange = statement.getTextRange();
- document.replaceString(textRange.getStartOffset(), textRange.getEndOffset(), newStatementText);
- documentManager.commitDocument(document);
- final FileViewProvider viewProvider = jspFile.getViewProvider();
- PsiElement elementAt = viewProvider.findElementAt(textRange.getStartOffset(), JavaLanguage.INSTANCE);
- if (elementAt == null) {
- return;
- }
- final int endOffset = textRange.getStartOffset() + newStatementText.length();
- while (elementAt.getTextRange().getEndOffset() < endOffset || !(elementAt instanceof PsiStatement)) {
- elementAt = elementAt.getParent();
- if (elementAt == null) {
- LOG.error("Cannot decode statement");
- return;
- }
- }
- final PsiStatement newStatement = (PsiStatement)elementAt;
- javaStyleManager.shortenClassReferences(newStatement);
- final TextRange newTextRange = newStatement.getTextRange();
- final Language baseLanguage = viewProvider.getBaseLanguage();
- final PsiFile element = viewProvider.getPsi(baseLanguage);
- if (element != null) {
- styleManager.reformatRange(element, newTextRange.getStartOffset(), newTextRange.getEndOffset());
- }
- }
- else {
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = facade.getElementFactory();
- PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
- newStatement = (PsiStatement)statement.replace(newStatement);
- javaStyleManager.shortenClassReferences(newStatement);
- styleManager.reformat(newStatement);
- }
- }
-
protected static String getElementText(@NotNull PsiElement element, @Nullable PsiElement elementToReplace, @Nullable String replacement) {
final StringBuilder out = new StringBuilder();
getElementText(element, elementToReplace, replacement, out);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/PsiReplacementUtil.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/PsiReplacementUtil.java
new file mode 100644
index 0000000..cd39633
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/PsiReplacementUtil.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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;
+
+import com.intellij.lang.Language;
+import com.intellij.lang.java.JavaLanguage;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.*;
+import com.intellij.psi.codeStyle.CodeStyleManager;
+import com.intellij.psi.codeStyle.JavaCodeStyleManager;
+import com.intellij.psi.util.FileTypeUtils;
+import com.intellij.psi.util.PsiUtilCore;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class PsiReplacementUtil {
+ private static final Logger LOG = Logger.getInstance("#" + PsiReplacementUtil.class.getName());
+
+ public static void replaceExpression(@NotNull PsiExpression expression, @NotNull @NonNls String newExpressionText) {
+ final Project project = expression.getProject();
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ final PsiElementFactory factory = psiFacade.getElementFactory();
+ final PsiExpression newExpression = factory.createExpressionFromText(newExpressionText, expression);
+ final PsiElement replacementExpression = expression.replace(newExpression);
+ final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
+ styleManager.reformat(replacementExpression);
+ }
+
+ public static PsiElement replaceExpressionAndShorten(@NotNull PsiExpression expression, @NotNull @NonNls String newExpressionText) {
+ final Project project = expression.getProject();
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ final PsiElementFactory factory = psiFacade.getElementFactory();
+ final PsiExpression newExpression = factory.createExpressionFromText(newExpressionText, expression);
+ final PsiElement replacementExp = expression.replace(newExpression);
+ final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
+ javaCodeStyleManager.shortenClassReferences(replacementExp);
+ final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
+ return styleManager.reformat(replacementExp);
+ }
+
+ public static PsiElement replaceStatement(@NotNull PsiStatement statement, @NotNull @NonNls String newStatementText) {
+ final Project project = statement.getProject();
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ final PsiElementFactory factory = psiFacade.getElementFactory();
+ final PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
+ final PsiElement replacementExp = statement.replace(newStatement);
+ final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
+ return styleManager.reformat(replacementExp);
+ }
+
+ public static void replaceStatementAndShortenClassNames(@NotNull PsiStatement statement, @NotNull @NonNls String newStatementText) {
+ final Project project = statement.getProject();
+ final CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
+ final JavaCodeStyleManager javaStyleManager = JavaCodeStyleManager.getInstance(project);
+ if (FileTypeUtils.isInServerPageFile(statement)) {
+ final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
+ final PsiFile jspFile = PsiUtilCore.getTemplateLanguageFile(statement);
+ if (jspFile == null) {
+ return;
+ }
+ final Document document = documentManager.getDocument(jspFile);
+ if (document == null) {
+ return;
+ }
+ documentManager.doPostponedOperationsAndUnblockDocument(document);
+ final TextRange textRange = statement.getTextRange();
+ document.replaceString(textRange.getStartOffset(), textRange.getEndOffset(), newStatementText);
+ documentManager.commitDocument(document);
+ final FileViewProvider viewProvider = jspFile.getViewProvider();
+ PsiElement elementAt = viewProvider.findElementAt(textRange.getStartOffset(), JavaLanguage.INSTANCE);
+ if (elementAt == null) {
+ return;
+ }
+ final int endOffset = textRange.getStartOffset() + newStatementText.length();
+ while (elementAt.getTextRange().getEndOffset() < endOffset || !(elementAt instanceof PsiStatement)) {
+ elementAt = elementAt.getParent();
+ if (elementAt == null) {
+ LOG.error("Cannot decode statement");
+ return;
+ }
+ }
+ final PsiStatement newStatement = (PsiStatement)elementAt;
+ javaStyleManager.shortenClassReferences(newStatement);
+ final TextRange newTextRange = newStatement.getTextRange();
+ final Language baseLanguage = viewProvider.getBaseLanguage();
+ final PsiFile element = viewProvider.getPsi(baseLanguage);
+ if (element != null) {
+ styleManager.reformatRange(element, newTextRange.getStartOffset(), newTextRange.getEndOffset());
+ }
+ }
+ else {
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+ final PsiElementFactory factory = facade.getElementFactory();
+ PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
+ newStatement = (PsiStatement)statement.replace(newStatement);
+ javaStyleManager.shortenClassReferences(newStatement);
+ styleManager.reformat(newStatement);
+ }
+ }
+
+ public static void replaceExpressionWithReferenceTo(@NotNull PsiExpression expression, @NotNull PsiMember target) {
+ final Project project = expression.getProject();
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ final PsiElementFactory factory = psiFacade.getElementFactory();
+ final PsiReferenceExpression newExpression = (PsiReferenceExpression)factory.createExpressionFromText("xxx", expression);
+ final PsiReferenceExpression replacementExpression = (PsiReferenceExpression)expression.replace(newExpression);
+ final PsiElement element = replacementExpression.bindToElement(target);
+ final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(project);
+ styleManager.shortenClassReferences(element);
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
index 96836a7..8db2598 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/DeclareCollectionAsInterfaceInspection.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.
@@ -202,7 +202,7 @@
}
}
final PsiType type = variable.getType();
- if (!CollectionUtils.isCollectionClass(type) || LibraryUtil.isOverrideOfLibraryMethodParameter(variable)) {
+ if (!CollectionUtils.isConcreteCollectionClass(type) || LibraryUtil.isOverrideOfLibraryMethodParameter(variable)) {
return;
}
final PsiTypeElement typeElement = variable.getTypeElement();
@@ -252,7 +252,7 @@
return;
}
final PsiType type = method.getReturnType();
- if (type == null || !CollectionUtils.isCollectionClass(type)) {
+ if (!CollectionUtils.isConcreteCollectionClass(type)) {
return;
}
if (LibraryUtil.isOverrideOfLibraryMethod(method)) {
@@ -302,7 +302,7 @@
final ProgressManager progressManager =
ProgressManager.getInstance();
final PsiSearchHelper searchHelper = PsiSearchHelper.SERVICE.getInstance(element.getProject());
- SearchScope useScope = element.getUseScope();
+ final SearchScope useScope = element.getUseScope();
if (useScope instanceof GlobalSearchScope) {
return searchHelper.isCheapEnoughToSearch(name, (GlobalSearchScope)useScope, null, progressManager.getProgressIndicator()) != PsiSearchHelper.SearchCostResult.TOO_MANY_OCCURRENCES;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/FeatureEnvyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/FeatureEnvyInspection.java
deleted file mode 100644
index 4adf8ad..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/FeatureEnvyInspection.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2003-2010 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.abstraction;
-
-import com.intellij.codeInsight.TestFrameworks;
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiIdentifier;
-import com.intellij.psi.PsiMethod;
-import com.intellij.psi.PsiNamedElement;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.TestUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.util.Set;
-
-public class FeatureEnvyInspection extends BaseInspection {
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreTestCases = false;
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("feature.envy.display.name");
- }
-
- @Override
- @NotNull
- public String buildErrorString(Object... infos) {
- final PsiNamedElement element = (PsiNamedElement)infos[0];
- final String className = element.getName();
- return InspectionGadgetsBundle.message(
- "feature.envy.problem.descriptor", className);
- }
-
- @Override
- @Nullable
- public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel(
- InspectionGadgetsBundle.message(
- "feature.envy.ignore.test.cases.option"), this,
- "ignoreTestCases");
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new FeatureEnvyVisitor();
- }
-
- private class FeatureEnvyVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitMethod(@NotNull PsiMethod method) {
- if (ignoreTestCases) {
- final PsiClass containingClass = method.getContainingClass();
- if (containingClass != null &&
- TestFrameworks.getInstance().isTestClass(containingClass)) {
- return;
- }
- if (TestUtils.isJUnitTestMethod(method)) {
- return;
- }
- }
- final PsiIdentifier nameIdentifier = method.getNameIdentifier();
- if (nameIdentifier == null) {
- return;
- }
- final PsiClass containingClass = method.getContainingClass();
- final ClassAccessVisitor visitor =
- new ClassAccessVisitor(containingClass);
- method.accept(visitor);
- final Set<PsiClass> overaccessedClasses =
- visitor.getOveraccessedClasses();
- for (PsiClass aClass : overaccessedClasses) {
- registerError(nameIdentifier, aClass);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/FeatureEnvyInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/FeatureEnvyInspectionBase.java
new file mode 100644
index 0000000..590e7d6
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/FeatureEnvyInspectionBase.java
@@ -0,0 +1,65 @@
+/*
+ * 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.ig.abstraction;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.PsiNamedElement;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+public class FeatureEnvyInspectionBase extends BaseInspection {
+
+ @SuppressWarnings({"PublicField", "UnusedDeclaration"})
+ public boolean ignoreTestCases = false; // keep for compatibility
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("feature.envy.display.name");
+ }
+
+ @Override
+ @NotNull
+ public String buildErrorString(Object... infos) {
+ final PsiNamedElement element = (PsiNamedElement)infos[0];
+ final String className = element.getName();
+ return InspectionGadgetsBundle.message("feature.envy.problem.descriptor", className);
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new FeatureEnvyVisitor();
+ }
+
+ private static class FeatureEnvyVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethod(@NotNull PsiMethod method) {
+ final PsiClass containingClass = method.getContainingClass();
+ final ClassAccessVisitor visitor = new ClassAccessVisitor(containingClass);
+ method.accept(visitor);
+ final Set<PsiClass> overAccessedClasses = visitor.getOveraccessedClasses();
+ for (PsiClass aClass : overAccessedClasses) {
+ registerMethodError(method, aClass, method);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java
index 051ddcb..04a94dd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/MagicNumberInspectionBase.java
@@ -30,8 +30,8 @@
public class MagicNumberInspectionBase extends BaseInspection {
@SuppressWarnings("PublicField")
public boolean ignoreInHashCode = true;
- @SuppressWarnings("PublicField")
- public boolean ignoreInTestCode = false;
+ @SuppressWarnings({"PublicField", "UnusedDeclaration"})
+ public boolean ignoreInTestCode = false; // keep for compatibility
@SuppressWarnings("PublicField")
public boolean ignoreInAnnotations = true;
@SuppressWarnings("PublicField")
@@ -53,18 +53,12 @@
public JComponent createOptionsPanel() {
final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
panel.addCheckbox(InspectionGadgetsBundle.message("magic.number.ignore.option"), "ignoreInHashCode");
- panel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.test.code"), "ignoreInTestCode");
panel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.annotations"),"ignoreInAnnotations");
panel.addCheckbox(InspectionGadgetsBundle.message("ignore.as.initial.capacity"), "ignoreInitialCapacity");
return panel;
}
@Override
- protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
- return true;
- }
-
- @Override
public BaseInspectionVisitor buildVisitor() {
return new MagicNumberVisitor();
}
@@ -78,7 +72,7 @@
if (!ClassUtils.isPrimitiveNumericType(type) || PsiType.CHAR.equals(type)) {
return;
}
- if (isSpecialCaseLiteral(expression) || ExpressionUtils.isDeclaredConstant(expression)) {
+ if (isSpecialCaseLiteral(expression) || isFinalVariableInitialization(expression)) {
return;
}
if (ignoreInHashCode) {
@@ -87,37 +81,39 @@
return;
}
}
- if (ignoreInTestCode && TestUtils.isInTestCode(expression)) {
- return;
- }
if (ignoreInAnnotations) {
final boolean insideAnnotation = AnnotationUtil.isInsideAnnotation(expression);
if (insideAnnotation) {
return;
}
}
- if (ignoreInitialCapacity) {
- final PsiExpressionList expressionList = PsiTreeUtil.getParentOfType(expression, PsiExpressionList.class, true, PsiMember.class);
- if (expressionList != null) {
- final PsiElement parent = expressionList.getParent();
- if (parent instanceof PsiNewExpression) {
- final PsiNewExpression newExpression = (PsiNewExpression)parent;
- if (TypeUtils.expressionHasTypeOrSubtype(newExpression, CommonClassNames.JAVA_LANG_ABSTRACT_STRING_BUILDER,
- CommonClassNames.JAVA_UTIL_MAP, CommonClassNames.JAVA_UTIL_COLLECTION) != null) {
- return;
- }
- }
- }
+ if (ignoreInitialCapacity && isInitialCapacity(expression)) {
+ return;
}
final PsiElement parent = expression.getParent();
if (parent instanceof PsiPrefixExpression) {
- registerError(parent);
+ registerError(parent, parent);
}
else {
- registerError(expression);
+ registerError(expression, expression);
}
}
+ private boolean isInitialCapacity(PsiLiteralExpression expression) {
+ final PsiElement element =
+ PsiTreeUtil.skipParentsOfType(expression, PsiTypeCastExpression.class, PsiParenthesizedExpression.class, PsiPrefixExpression.class);
+ if (!(element instanceof PsiExpressionList)) {
+ return false;
+ }
+ final PsiElement parent = element.getParent();
+ if (!(parent instanceof PsiNewExpression)) {
+ return false;
+ }
+ final PsiNewExpression newExpression = (PsiNewExpression)parent;
+ return TypeUtils.expressionHasTypeOrSubtype(newExpression, CommonClassNames.JAVA_LANG_ABSTRACT_STRING_BUILDER,
+ CommonClassNames.JAVA_UTIL_MAP, CommonClassNames.JAVA_UTIL_COLLECTION) != null;
+ }
+
private boolean isSpecialCaseLiteral(PsiLiteralExpression expression) {
final Object object = ExpressionUtils.computeConstantExpression(expression);
if (object instanceof Integer) {
@@ -138,5 +134,31 @@
}
return false;
}
+
+ public boolean isFinalVariableInitialization(PsiExpression expression) {
+ final PsiElement parent =
+ PsiTreeUtil.skipParentsOfType(expression, PsiTypeCastExpression.class, PsiParenthesizedExpression.class, PsiPrefixExpression.class);
+ final PsiVariable variable;
+ if (!(parent instanceof PsiVariable)) {
+ if (!(parent instanceof PsiAssignmentExpression)) {
+ return false;
+ }
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
+ final PsiExpression lhs = assignmentExpression.getLExpression();
+ if (!(lhs instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
+ final PsiElement target = referenceExpression.resolve();
+ if (!(target instanceof PsiVariable)) {
+ return false;
+ }
+ variable = (PsiVariable)target;
+ }
+ else {
+ variable = (PsiVariable)parent;
+ }
+ return variable.hasModifierProperty(PsiModifier.FINAL);
+ }
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java
index a312008..bf185ea 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/OverlyStrongTypeCastInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.InstanceOfUtils;
import org.jetbrains.annotations.NonNls;
@@ -93,7 +94,7 @@
}
@NonNls
final String newExpression = '(' + expectedType.getCanonicalText() + ')' + operand.getText();
- replaceExpressionAndShorten(expression, newExpression);
+ PsiReplacementUtil.replaceExpressionAndShorten(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspectionBase.java
index a01120a..b45e610 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/abstraction/StaticMethodOnlyUsedInOneClassInspectionBase.java
@@ -139,7 +139,7 @@
if (usageClass.equals(method.getContainingClass())) {
return;
}
- if (ignoreTestClasses && TestUtils.isTest(usageClass)) {
+ if (ignoreTestClasses && TestUtils.isInTestCode(usageClass)) {
return;
}
if (usageClass instanceof PsiAnonymousClass) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java
index 2081435..087c6d5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/AssignmentUsedAsConditionInspection.java
@@ -22,6 +22,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class AssignmentUsedAsConditionInspection extends BaseInspection {
@@ -64,7 +65,7 @@
final PsiExpression rightExpression = expression.getRExpression();
assert rightExpression != null;
final String newExpression = leftExpression.getText() + "==" + rightExpression.getText();
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java
index bcebcd9..8d7577b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/IncrementDecrementUsedAsExpressionInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -318,7 +319,7 @@
}
}
}
- replaceExpression((PsiExpression)element, operandText);
+ PsiReplacementUtil.replaceExpression((PsiExpression)element, operandText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java
index 478164c..96a5aca 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/assignment/ReplaceAssignmentWithOperatorAssignmentInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
@@ -171,7 +172,7 @@
}
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)rhs;
final String newExpression = calculateReplacementExpression(lhs, polyadicExpression);
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
index 38bafe6..cda88dd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bitwise/PointlessBitwiseExpressionInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -188,7 +189,7 @@
descriptor.getPsiElement();
final String newExpression =
calculateReplacementExpression(expression);
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java
deleted file mode 100644
index 3346fdb..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArchaicSystemPropertyAccessInspection.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2003-2010 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.bugs;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-public class ArchaicSystemPropertyAccessInspection extends BaseInspection {
-
- @Override
- @NotNull
- public String getID() {
- return "UseOfArchaicSystemPropertyAccessors";
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "archaic.system.property.accessors.display.name");
- }
-
- @Override
- @NotNull
- public String buildErrorString(Object... infos) {
- final PsiMethodCallExpression call =
- (PsiMethodCallExpression)infos[0];
- if (isIntegerGetInteger(call)) {
- return InspectionGadgetsBundle.message(
- "archaic.system.property.accessors.problem.descriptor.Integer");
- }
- else if (isLongGetLong(call)) {
- return InspectionGadgetsBundle.message(
- "archaic.system.property.accessors.problem.descriptor.Long");
- }
- else {
- return InspectionGadgetsBundle.message(
- "archaic.system.property.accessors.problem.descriptor.Boolean");
- }
- }
-
- @Override
- @NotNull
- protected InspectionGadgetsFix[] buildFixes(Object... infos) {
- return new InspectionGadgetsFix[]{new ReplaceWithParseMethodFix(),
- new ReplaceWithStandardPropertyAccessFix()};
- }
-
- private static class ReplaceWithParseMethodFix extends InspectionGadgetsFix {
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- @NotNull
- public String getName() {
- return InspectionGadgetsBundle.message(
- "archaic.system.property.accessors.replace.parse.quickfix");
- }
-
- @Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
- final PsiIdentifier location =
- (PsiIdentifier)descriptor.getPsiElement();
- final PsiElement parent = location.getParent();
- assert parent != null;
- final PsiMethodCallExpression call =
- (PsiMethodCallExpression)parent.getParent();
- assert call != null;
- final PsiExpressionList argList = call.getArgumentList();
- final PsiExpression[] args = argList.getExpressions();
- final String argText = args[0].getText();
- @NonNls final String parseMethodCall;
- if (isIntegerGetInteger(call)) {
- parseMethodCall = "Integer.valueOf(" + argText + ')';
- }
- else if (isLongGetLong(call)) {
- parseMethodCall = "Long.valueOf(" + argText + ')';
- }
- else {
- parseMethodCall = "Boolean.valueOf(" + argText + ')';
- }
- replaceExpression(call, parseMethodCall);
- }
- }
-
- private static class ReplaceWithStandardPropertyAccessFix
- extends InspectionGadgetsFix {
-
- @Override
- @NotNull
- public String getName() {
- return InspectionGadgetsBundle.message(
- "archaic.system.property.accessors.replace.standard.quickfix");
- }
-
- @NotNull
- @Override
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
- final PsiIdentifier location =
- (PsiIdentifier)descriptor.getPsiElement();
- final PsiElement parent = location.getParent();
- assert parent != null;
- final PsiMethodCallExpression call =
- (PsiMethodCallExpression)parent.getParent();
- assert call != null;
- final PsiExpressionList argList = call.getArgumentList();
- final PsiExpression[] args = argList.getExpressions();
- final String argText = args[0].getText();
- @NonNls final String parseMethodCall;
- if (isIntegerGetInteger(call)) {
- parseMethodCall = "Integer.parseInt(System.getProperty("
- + argText + "))";
- }
- else if (isLongGetLong(call)) {
- parseMethodCall = "Long.parseLong(System.getProperty("
- + argText + "))";
- }
- else {
- if (!PsiUtil.isLanguageLevel5OrHigher(call)) {
- parseMethodCall = "Boolean.valueOf(System.getProperty("
- + argText + ")).booleanValue()";
- }
- else {
- parseMethodCall = "Boolean.parseBoolean(System.getProperty("
- + argText + "))";
- }
- }
- replaceExpression(call, parseMethodCall);
- }
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new ArchaicSystemPropertyAccessVisitor();
- }
-
- private static class ArchaicSystemPropertyAccessVisitor
- extends BaseInspectionVisitor {
-
- @Override
- public void visitMethodCallExpression(
- @NotNull PsiMethodCallExpression expression) {
- super.visitMethodCallExpression(expression);
- if (isIntegerGetInteger(expression) ||
- isLongGetLong(expression) ||
- isBooleanGetBoolean(expression)) {
- registerMethodCallError(expression, expression);
- }
- }
- }
-
- static boolean isIntegerGetInteger(PsiMethodCallExpression expression) {
- return isCallTo(expression, CommonClassNames.JAVA_LANG_INTEGER,
- "getInteger");
- }
-
- static boolean isLongGetLong(PsiMethodCallExpression expression) {
- return isCallTo(expression, CommonClassNames.JAVA_LANG_LONG, "getLong");
- }
-
- static boolean isBooleanGetBoolean(PsiMethodCallExpression expression) {
- return isCallTo(expression, CommonClassNames.JAVA_LANG_BOOLEAN,
- "getBoolean");
- }
-
- private static boolean isCallTo(PsiMethodCallExpression expression,
- String className, @NonNls String methodName) {
- final PsiReferenceExpression methodExpression =
- expression.getMethodExpression();
- @NonNls final String expressionMethodName =
- methodExpression.getReferenceName();
- if (!methodName.equals(expressionMethodName)) {
- return false;
- }
- final PsiMethod method = expression.resolveMethod();
- if (method == null) {
- return false;
- }
- final PsiClass aClass = method.getContainingClass();
- if (aClass == null) {
- return false;
- }
- final String expressionClassName = aClass.getQualifiedName();
- if (expressionClassName == null) {
- return false;
- }
- return className.equals(expressionClassName);
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java
index ae477e5..b52b9be 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualityInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2011-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.
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -114,8 +115,8 @@
}
newExpressionText.append(rhs.getText());
newExpressionText.append(')');
- replaceExpressionAndShorten(binaryExpression,
- newExpressionText.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(binaryExpression,
+ newExpressionText.toString());
}
}
@@ -127,34 +128,18 @@
private static class ArrayEqualityVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(
- @NotNull PsiBinaryExpression expression) {
+ public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) {
super.visitBinaryExpression(expression);
final PsiExpression rhs = expression.getROperand();
- if (rhs == null) {
- return;
- }
- if (!ComparisonUtils.isEqualityComparison(expression)) {
+ if (rhs == null || !ComparisonUtils.isEqualityComparison(expression)) {
return;
}
final PsiExpression lhs = expression.getLOperand();
final PsiType lhsType = lhs.getType();
- if (!(lhsType instanceof PsiArrayType)) {
+ if (!(lhsType instanceof PsiArrayType) || !(rhs.getType() instanceof PsiArrayType)) {
return;
}
- if (!(rhs.getType() instanceof PsiArrayType)) {
- return;
- }
- final String lhsText = lhs.getText();
- if (PsiKeyword.NULL.equals(lhsText)) {
- return;
- }
- final String rhsText = rhs.getText();
- if (PsiKeyword.NULL.equals(rhsText)) {
- return;
- }
- final PsiJavaToken sign = expression.getOperationSign();
- registerError(sign, lhsType);
+ registerError(expression.getOperationSign(), lhsType);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java
index ae607f1..7aa54cc 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayEqualsInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -115,7 +116,7 @@
newExpressionText.append(", ");
newExpressionText.append(argumentText);
newExpressionText.append(')');
- replaceExpressionAndShorten(call, newExpressionText.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(call, newExpressionText.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java
index d5a3b68..8ed07f9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ArrayHashCodeInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -112,8 +113,8 @@
}
newExpressionText.append(qualifier.getText());
newExpressionText.append(')');
- replaceExpressionAndShorten(methodCallExpression,
- newExpressionText.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(methodCallExpression,
+ newExpressionText.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java
index 55c5da3..4fef7b5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ClassNewInstanceInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -106,7 +107,7 @@
(PsiMethodCallExpression)grandParent;
@NonNls final String newExpression = qualifier.getText() +
".getConstructor().newInstance()";
- replaceExpression(methodCallExpression, newExpression);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression);
}
private static void addThrowsClause(PsiMethod method,
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java
index 20649cf..437c210 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ImplicitArrayToStringInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -151,13 +152,13 @@
final PsiReferenceExpression methodExpression =
methodCallExpression.getMethodExpression();
if ("valueOf".equals(methodExpression.getReferenceName())) {
- replaceExpressionAndShorten(methodCallExpression,
- newExpressionText);
+ PsiReplacementUtil.replaceExpressionAndShorten(methodCallExpression,
+ newExpressionText);
return;
}
}
}
- replaceExpressionAndShorten(expression, newExpressionText);
+ PsiReplacementUtil.replaceExpressionAndShorten(expression, newExpressionText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java
index f3af8bd..63d2f52 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/MathRandomCastToIntInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -108,7 +109,7 @@
}
}
newExpression.append(')');
- replaceExpression(polyadicExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpression.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java
index 0532b9c..bc4149e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NewStringBufferWithCharArgumentInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -94,7 +95,7 @@
final String text = argument.getText();
final String newArgument =
'"' + text.substring(1, text.length() - 1) + '"';
- replaceExpression(argument, newArgument);
+ PsiReplacementUtil.replaceExpression(argument, newArgument);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java
index b7a765d..8299974 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NonShortCircuitBooleanInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class NonShortCircuitBooleanInspection extends BaseInspection {
@@ -82,7 +83,7 @@
}
newExpression.append(operand.getText());
}
- replaceExpression(expression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(expression, newExpression.toString());
}
private static String getShortCircuitOperand(IElementType tokenType) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NumberEqualityInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NumberEqualityInspection.java
index 958ecb8..01e0055 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NumberEqualityInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/NumberEqualityInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -59,35 +59,21 @@
private static class NumberEqualityVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(
- @NotNull PsiBinaryExpression expression) {
+ public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) {
super.visitBinaryExpression(expression);
final PsiExpression rhs = expression.getROperand();
- if (rhs == null) {
- return;
- }
- if (!ComparisonUtils.isEqualityComparison(expression)) {
+ if (rhs == null || !ComparisonUtils.isEqualityComparison(expression)) {
return;
}
final PsiExpression lhs = expression.getLOperand();
if (!hasNumberType(lhs) || !hasNumberType(rhs)) {
return;
}
- final String lhsText = lhs.getText();
- if (PsiKeyword.NULL.equals(lhsText)) {
- return;
- }
- final String rhsText = rhs.getText();
- if (PsiKeyword.NULL.equals(rhsText)) {
- return;
- }
- final PsiJavaToken sign = expression.getOperationSign();
- registerError(sign);
+ registerError(expression.getOperationSign());
}
private static boolean hasNumberType(PsiExpression expression) {
- return TypeUtils.expressionHasTypeOrSubtype(expression,
- CommonClassNames.JAVA_LANG_NUMBER);
+ return TypeUtils.expressionHasTypeOrSubtype(expression, CommonClassNames.JAVA_LANG_NUMBER);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
index 65a1f8e..237ec31 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticCallOnSubclassInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 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.
@@ -23,7 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.ClassUtils;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class StaticCallOnSubclassInspection extends BaseInspection {
@@ -98,8 +98,8 @@
final String containingClassName =
containingClass.getQualifiedName();
final String argText = argumentList.getText();
- replaceExpressionAndShorten(call, containingClassName + '.' +
- methodName + argText);
+ PsiReplacementUtil.replaceExpressionAndShorten(call, containingClassName + '.' +
+ methodName + argText);
}
}
@@ -140,10 +140,8 @@
if (declaringClass.equals(referencedClass)) {
return;
}
- final PsiClass containingClass =
- ClassUtils.getContainingClass(call);
- if (!ClassUtils.isClassVisibleFromClass(containingClass,
- declaringClass)) {
+ final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(call.getProject()).getResolveHelper();
+ if (!resolveHelper.isAccessible(declaringClass, call, null)) {
return;
}
registerMethodCallError(call, declaringClass, referencedClass);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java
index b80bc1d..696df9b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 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.
@@ -23,7 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.ClassUtils;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class StaticFieldReferenceOnSubclassInspection
@@ -82,7 +82,7 @@
assert expression != null;
final PsiField field = (PsiField)expression.resolve();
assert field != null;
- replaceExpressionWithReferenceTo(expression, field);
+ PsiReplacementUtil.replaceExpressionWithReferenceTo(expression, field);
}
}
@@ -123,13 +123,14 @@
if (declaringClass.equals(referencedClass)) {
return;
}
- final PsiClass containingClass =
- ClassUtils.getContainingClass(expression);
- if (!ClassUtils.isClassVisibleFromClass(containingClass,
- declaringClass)) {
+ final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(expression.getProject()).getResolveHelper();
+ if (!resolveHelper.isAccessible(declaringClass, expression, null)) {
return;
}
final PsiElement identifier = expression.getReferenceNameElement();
+ if (identifier == null) {
+ return;
+ }
registerError(identifier, declaringClass, referencedClass);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java
index 2331526..d228809 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/StringConcatenationInFormatCallInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.FormatUtils;
import org.jetbrains.annotations.Nls;
@@ -100,7 +101,7 @@
}
newExpression.append(operand.getText());
}
- replaceExpression(polyadicExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpression.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableResultOfMethodCallIgnoredInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableResultOfMethodCallIgnoredInspection.java
index 36fa262..cbf3312 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableResultOfMethodCallIgnoredInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/ThrowableResultOfMethodCallIgnoredInspection.java
@@ -84,6 +84,13 @@
return;
}
}
+
+ if ("propagate".equals(method.getName())
+ && method.getContainingClass() != null
+ && "com.google.common.base.Throwables".equals(method.getContainingClass().getQualifiedName())) {
+ return;
+ }
+
final PsiLocalVariable variable;
if (parent instanceof PsiAssignmentExpression) {
final PsiAssignmentExpression assignmentExpression =
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java
index 4fa34c6..02c6742 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/UseOfPropertiesAsHashtableInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -136,7 +137,7 @@
newExpression.append(argument.getText());
}
newExpression.append(')');
- replaceExpression(methodCallExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspection.java
index bae56e9..6588356 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/bugs/VariableNotUsedInsideIfInspection.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -56,7 +57,7 @@
@Override
public void visitConditionalExpression(PsiConditionalExpression expression) {
super.visitConditionalExpression(expression);
- final PsiExpression condition = expression.getCondition();
+ final PsiExpression condition = PsiUtil.skipParenthesizedExprDown(expression.getCondition());
if (!(condition instanceof PsiBinaryExpression)) {
return;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassInitializerInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassInitializerInspection.java
index 61267cd..74011bd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassInitializerInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/ClassInitializerInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -15,8 +15,15 @@
*/
package com.siyeh.ig.classlayout;
-import com.intellij.psi.PsiClassInitializer;
-import com.intellij.psi.PsiModifier;
+import com.intellij.codeInsight.daemon.impl.analysis.JavaHighlightUtil;
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.codeInsight.intention.QuickFixFactory;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -25,8 +32,15 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import javax.swing.*;
+import java.util.Collection;
+import java.util.Iterator;
+
public class ClassInitializerInspection extends BaseInspection {
+ @SuppressWarnings("PublicField")
+ public boolean onlyWarnWhenConstructor = false;
+
@Override
@NotNull
public String getID() {
@@ -36,21 +50,107 @@
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "class.initializer.display.name");
+ return InspectionGadgetsBundle.message("class.initializer.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "class.initializer.problem.descriptor");
+ return InspectionGadgetsBundle.message("class.initializer.problem.descriptor");
}
- @Override
@Nullable
- protected InspectionGadgetsFix buildFix(Object... infos) {
- return new ChangeModifierFix(PsiModifier.STATIC);
+ @Override
+ public JComponent createOptionsPanel() {
+ return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("class.initializer.option"), this, "onlyWarnWhenConstructor");
+ }
+
+
+ @NotNull
+ @Override
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final PsiClass aClass = (PsiClass)infos[0];
+ if (PsiUtil.isInnerClass(aClass)) {
+ return new InspectionGadgetsFix[] {new MoveToConstructorFix()};
+ }
+ return new InspectionGadgetsFix[] {
+ new ChangeModifierFix(PsiModifier.STATIC),
+ new MoveToConstructorFix()
+ };
+ }
+
+ private static class MoveToConstructorFix extends InspectionGadgetsFix {
+
+ @NotNull
+ @Override
+ public String getName() {
+ return InspectionGadgetsBundle.message("class.initializer.move.code.to.constructor.quickfix");
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement brace = descriptor.getPsiElement();
+ final PsiElement parent = brace.getParent();
+ if (!(parent instanceof PsiCodeBlock)) {
+ return;
+ }
+ final PsiElement grandParent = parent.getParent();
+ if (!(grandParent instanceof PsiClassInitializer)) {
+ return;
+ }
+ final PsiClassInitializer initializer = (PsiClassInitializer)grandParent;
+ final PsiClass aClass = initializer.getContainingClass();
+ if (aClass == null) {
+ return;
+ }
+ final Collection<PsiMethod> constructors = getOrCreateConstructors(aClass);
+ for (PsiMethod constructor : constructors) {
+ addCodeToMethod(initializer, constructor);
+ }
+ initializer.delete();
+ }
+
+ private static void addCodeToMethod(PsiClassInitializer initializer, PsiMethod constructor) {
+ final PsiCodeBlock body = constructor.getBody();
+ if (body == null) {
+ return;
+ }
+ final PsiCodeBlock codeBlock = initializer.getBody();
+ PsiElement element = codeBlock.getFirstBodyElement();
+ final PsiElement last = codeBlock.getLastBodyElement();
+ while (element != null && element != last) {
+ body.add(element);
+ element = element.getNextSibling();
+ }
+ }
+
+ @NotNull
+ private static Collection<PsiMethod> getOrCreateConstructors(@NotNull PsiClass aClass) {
+ PsiMethod[] constructors = aClass.getConstructors();
+ if (constructors.length == 0) {
+ final IntentionAction addDefaultConstructorFix = QuickFixFactory.getInstance().createAddDefaultConstructorFix(aClass);
+ addDefaultConstructorFix.invoke(aClass.getProject(), null, aClass.getContainingFile());
+ }
+ constructors = aClass.getConstructors();
+ return removeChainedConstructors(ContainerUtil.newArrayList(constructors));
+ }
+
+ @NotNull
+ private static Collection<PsiMethod> removeChainedConstructors(@NotNull Collection<PsiMethod> constructors) {
+ for (final Iterator<PsiMethod> iterator = constructors.iterator(); iterator.hasNext(); ) {
+ final PsiMethod constructor = iterator.next();
+ if (JavaHighlightUtil.getChainedConstructors(constructor) != null) {
+ iterator.remove();
+ }
+ }
+ return constructors;
+ }
}
@Override
@@ -58,7 +158,7 @@
return new ClassInitializerVisitor();
}
- private static class ClassInitializerVisitor extends BaseInspectionVisitor {
+ private class ClassInitializerVisitor extends BaseInspectionVisitor {
@Override
public void visitClassInitializer(PsiClassInitializer initializer) {
@@ -66,7 +166,14 @@
if (initializer.hasModifierProperty(PsiModifier.STATIC)) {
return;
}
- registerClassInitializerError(initializer);
+ final PsiClass aClass = initializer.getContainingClass();
+ if (aClass == null || aClass instanceof PsiAnonymousClass) {
+ return;
+ }
+ if (onlyWarnWhenConstructor && aClass.getConstructors().length == 0) {
+ return;
+ }
+ registerClassInitializerError(initializer, aClass);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/FinalMethodInFinalClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/FinalMethodInFinalClassInspection.java
index 44d815e..968b25b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/FinalMethodInFinalClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/FinalMethodInFinalClassInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 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.
@@ -15,6 +15,7 @@
*/
package com.siyeh.ig.classlayout;
+import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
@@ -59,6 +60,10 @@
if (!method.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
+ if (!method.hasModifierProperty(PsiModifier.STATIC) &&
+ AnnotationUtil.findAnnotation(method, true, "java.lang.SafeVarargs") != null) {
+ return;
+ }
final PsiClass containingClass = method.getContainingClass();
if (containingClass == null || containingClass.isEnum()) {
return;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java
new file mode 100644
index 0000000..58fd9e3
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspection.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.classlayout;
+
+import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
+import com.intellij.psi.LambdaHighlightingUtil;
+import com.intellij.psi.LambdaUtil;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiNameValuePair;
+import com.intellij.psi.util.MethodSignature;
+import com.intellij.psi.util.PsiUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.DelegatingFix;
+import com.siyeh.ig.InspectionGadgetsFix;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class InterfaceMayBeAnnotatedFunctionalInspection extends BaseInspection {
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("interface.may.be.annotated.functional.display.name");
+ }
+
+ @NotNull
+ @Override
+ protected String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("interface.may.be.annotated.functional.problem.descriptor");
+ }
+
+ @Nullable
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final PsiClass aClass = (PsiClass)infos[0];
+ return new DelegatingFix(new AddAnnotationPsiFix(LambdaUtil.JAVA_LANG_FUNCTIONAL_INTERFACE, aClass, PsiNameValuePair.EMPTY_ARRAY));
+
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new InterfaceMayBeAnnotatedFunctionalVisitor();
+ }
+
+ private static class InterfaceMayBeAnnotatedFunctionalVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitClass(PsiClass aClass) {
+ if (!PsiUtil.isLanguageLevel8OrHigher(aClass)) {
+ return;
+ }
+ super.visitClass(aClass);
+ if (!aClass.isInterface()) {
+ return;
+ }
+ if (LambdaHighlightingUtil.checkInterfaceFunctional(aClass) != null) {
+ return;
+ }
+ final List<MethodSignature> candidates = LambdaUtil.findFunctionCandidates(aClass);
+ if (candidates == null || candidates.size() != 1) {
+ return;
+ }
+ final MethodSignature signature = candidates.get(0);
+ if (signature.getTypeParameters().length > 0) {
+ return;
+ }
+ registerClassError(aClass, aClass);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java
deleted file mode 100644
index 3c18cc3..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/MissingOverrideAnnotationInspection.java
+++ /dev/null
@@ -1,247 +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 com.siyeh.ig.classlayout;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PsiUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.SmartList;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.MethodUtils;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class MissingOverrideAnnotationInspection extends BaseInspection {
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreObjectMethods = true;
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreAnonymousClassMethods = false;
-
- @Override
- @NotNull
- public String getID() {
- return "override";
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "missing.override.annotation.display.name");
- }
-
- @Override
- @NotNull
- protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "missing.override.annotation.problem.descriptor");
- }
-
- @Override
- public JComponent createOptionsPanel() {
- final MultipleCheckboxOptionsPanel panel =
- new MultipleCheckboxOptionsPanel(this);
- panel.addCheckbox(InspectionGadgetsBundle.message(
- "ignore.equals.hashcode.and.tostring"), "ignoreObjectMethods");
- panel.addCheckbox(InspectionGadgetsBundle.message(
- "ignore.methods.in.anonymous.classes"),
- "ignoreAnonymousClassMethods");
- return panel;
- }
-
- @Override
- protected InspectionGadgetsFix buildFix(Object... infos) {
- return new MissingOverrideAnnotationFix();
- }
-
- private static class MissingOverrideAnnotationFix
- extends InspectionGadgetsFix {
-
- @Override
- @NotNull
- public String getName() {
- return InspectionGadgetsBundle.message(
- "missing.override.annotation.add.quickfix");
- }
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
- final PsiElement identifier = descriptor.getPsiElement();
- final PsiElement parent = identifier.getParent();
- if (!(parent instanceof PsiModifierListOwner)) {
- return;
- }
- final PsiModifierListOwner modifierListOwner =
- (PsiModifierListOwner)parent;
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiAnnotation annotation =
- factory.createAnnotationFromText("@java.lang.Override",
- modifierListOwner);
- final PsiModifierList modifierList =
- modifierListOwner.getModifierList();
- if (modifierList == null) {
- return;
- }
- modifierList.addAfter(annotation, null);
- }
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new MissingOverrideAnnotationVisitor();
- }
-
- private class MissingOverrideAnnotationVisitor
- extends BaseInspectionVisitor {
-
- @Override
- public void visitMethod(@NotNull PsiMethod method) {
- if (!PsiUtil.isLanguageLevel5OrHigher(method)) {
- return;
- }
- if (method.getNameIdentifier() == null) {
- return;
- }
- if (method.isConstructor()) {
- return;
- }
- if (method.hasModifierProperty(PsiModifier.PRIVATE) ||
- method.hasModifierProperty(PsiModifier.STATIC)) {
- return;
- }
- final PsiClass methodClass = method.getContainingClass();
- if (methodClass == null) {
- return;
- }
- if (ignoreAnonymousClassMethods &&
- methodClass instanceof PsiAnonymousClass) {
- return;
- }
- final boolean useJdk6Rules =
- PsiUtil.isLanguageLevel6OrHigher(method);
- if (useJdk6Rules) {
- if (!isJdk6Override(method, methodClass)) {
- return;
- }
- }
- else if (!isJdk5Override(method, methodClass)) {
- return;
- }
- if (ignoreObjectMethods && (MethodUtils.isHashCode(method) ||
- MethodUtils.isEquals(method) ||
- MethodUtils.isToString(method))) {
- return;
- }
- if (hasOverrideAnnotation(method)) {
- return;
- }
- registerMethodError(method);
- }
-
- private boolean hasOverrideAnnotation(
- PsiModifierListOwner element) {
- final PsiModifierList modifierList = element.getModifierList();
- if (modifierList == null) {
- return false;
- }
- final PsiAnnotation annotation =
- modifierList.findAnnotation("java.lang.Override");
- return annotation != null;
- }
-
- private boolean isJdk6Override(PsiMethod method, PsiClass methodClass) {
- final PsiMethod[] superMethods =
- getSuperMethodsInJavaSense(method, methodClass);
- if (superMethods.length <= 0) {
- return false;
- }
- // is override except if this is an interface method
- // overriding a protected method in java.lang.Object
- // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6501053
- if (!methodClass.isInterface()) {
- return true;
- }
- for (PsiMethod superMethod : superMethods) {
- if (!superMethod.hasModifierProperty(PsiModifier.PROTECTED)) {
- return true;
- }
- }
- return false;
- }
-
- private boolean isJdk5Override(PsiMethod method, PsiClass methodClass) {
- final PsiMethod[] superMethods =
- getSuperMethodsInJavaSense(method, methodClass);
- for (PsiMethod superMethod : superMethods) {
- final PsiClass superClass = superMethod.getContainingClass();
- if (superClass == null) {
- continue;
- }
- if (superClass.isInterface()) {
- continue;
- }
- if (methodClass.isInterface() &&
- superMethod.hasModifierProperty(PsiModifier.PROTECTED)) {
- // only true for J2SE java.lang.Object.clone(), but might
- // be different on other/newer java platforms
- continue;
- }
- return true;
- }
- return false;
- }
-
- private PsiMethod[] getSuperMethodsInJavaSense(
- @NotNull PsiMethod method, @NotNull PsiClass methodClass) {
- final PsiMethod[] superMethods = method.findSuperMethods();
- final List<PsiMethod> toExclude = new SmartList<PsiMethod>();
- for (PsiMethod superMethod : superMethods) {
- final PsiClass superClass = superMethod.getContainingClass();
- if (!InheritanceUtil.isInheritorOrSelf(methodClass, superClass,
- true)) {
- toExclude.add(superMethod);
- }
- }
- if (!toExclude.isEmpty()) {
- final List<PsiMethod> result =
- new ArrayList<PsiMethod>(Arrays.asList(superMethods));
- result.removeAll(toExclude);
- return result.toArray(new PsiMethod[result.size()]);
- }
- return superMethods;
- }
- }
-}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java
index 99180b6..375807f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/classlayout/NoopMethodInAbstractClassInspection.java
@@ -60,7 +60,8 @@
if (!containingClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return;
}
- if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.hasModifierProperty(PsiModifier.NATIVE)) {
+ if (method.hasModifierProperty(PsiModifier.ABSTRACT) || method.hasModifierProperty(PsiModifier.NATIVE) ||
+ method.hasModifierProperty(PsiModifier.FINAL)) {
return;
}
if (!MethodUtils.isEmpty(method)) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneCallsConstructorsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneCallsConstructorsInspection.java
index 40d90c1..bed3208 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneCallsConstructorsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/cloneable/CloneCallsConstructorsInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 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,10 +17,10 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
-import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.CloneUtils;
import org.jetbrains.annotations.NotNull;
public class CloneCallsConstructorsInspection extends BaseInspection {
@@ -49,37 +49,33 @@
@Override
public void visitMethod(@NotNull PsiMethod method) {
- final String methodName = method.getName();
- final PsiParameterList parameterList = method.getParameterList();
- final boolean isClone =
- HardcodedMethodConstants.CLONE.equals(methodName) &&
- parameterList.getParametersCount() == 0;
- if (isClone) {
- method.accept(new JavaRecursiveElementVisitor() {
-
- @Override
- public void visitNewExpression(
- @NotNull PsiNewExpression newExpression) {
- super.visitNewExpression(newExpression);
- final PsiExpression[] arrayDimensions =
- newExpression.getArrayDimensions();
- if (arrayDimensions.length != 0) {
- return;
- }
- if (newExpression.getArrayInitializer() != null) {
- return;
- }
- if (newExpression.getAnonymousClass() != null) {
- return;
- }
- if (PsiTreeUtil.getParentOfType(newExpression,
- PsiThrowStatement.class) != null) {
- return;
- }
- registerError(newExpression);
- }
- });
+ if (!CloneUtils.isClone(method)) {
+ return;
}
+ method.accept(new JavaRecursiveElementVisitor() {
+
+ @Override
+ public void visitNewExpression(
+ @NotNull PsiNewExpression newExpression) {
+ super.visitNewExpression(newExpression);
+ final PsiExpression[] arrayDimensions =
+ newExpression.getArrayDimensions();
+ if (arrayDimensions.length != 0) {
+ return;
+ }
+ if (newExpression.getArrayInitializer() != null) {
+ return;
+ }
+ if (newExpression.getAnonymousClass() != null) {
+ return;
+ }
+ if (PsiTreeUtil.getParentOfType(newExpression,
+ PsiThrowStatement.class) != null) {
+ return;
+ }
+ registerNewExpressionError(newExpression);
+ }
+ });
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java
index c6e9cf8..8e9dfce 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConditionalExpressionWithIdenticalBranchesInspection.java
@@ -19,11 +19,11 @@
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiConditionalExpression;
import com.intellij.psi.PsiExpression;
-import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import org.jetbrains.annotations.NotNull;
@@ -66,7 +66,7 @@
final PsiExpression thenExpression = expression.getThenExpression();
assert thenExpression != null;
final String bodyText = thenExpression.getText();
- replaceExpression(expression, bodyText);
+ PsiReplacementUtil.replaceExpression(expression, bodyText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java
index abb3fb9..d663d91 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import org.jetbrains.annotations.NotNull;
@@ -94,7 +95,7 @@
(PsiConditionalExpression)descriptor.getPsiElement();
final String newExpression =
calculateReplacementExpression(expression);
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
index 1afa566..645fc42 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ConstantIfStatementInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.VariableSearchUtils;
import org.jetbrains.annotations.NotNull;
@@ -109,7 +110,7 @@
PsiTreeUtil.getParentOfType(branch, PsiCodeBlock.class);
if (parentBlock == null) {
final String elseText = branch.getText();
- replaceStatement(statement, elseText);
+ PsiReplacementUtil.replaceStatement(statement, elseText);
return;
}
final PsiCodeBlock block =
@@ -119,7 +120,7 @@
block, parentBlock);
if (hasConflicts) {
final String elseText = branch.getText();
- replaceStatement(statement, elseText);
+ PsiReplacementUtil.replaceStatement(statement, elseText);
}
else {
final PsiElement containingElement = statement.getParent();
@@ -150,7 +151,7 @@
}
else {
final String elseText = branch.getText();
- replaceStatement(statement, elseText);
+ PsiReplacementUtil.replaceStatement(statement, elseText);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java
index c503eac..ff4d3e3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/DoubleNegationInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
@@ -72,7 +73,7 @@
if (expression instanceof PsiPrefixExpression) {
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)expression;
final PsiExpression operand = ParenthesesUtils.stripParentheses(prefixExpression.getOperand());
- replaceExpression(prefixExpression, BoolUtils.getNegatedExpressionText(operand));
+ PsiReplacementUtil.replaceExpression(prefixExpression, BoolUtils.getNegatedExpressionText(operand));
} else if (expression instanceof PsiPolyadicExpression) {
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
final PsiExpression[] operands = polyadicExpression.getOperands();
@@ -81,10 +82,12 @@
final PsiExpression firstOperand = operands[0];
final PsiExpression secondOperand = operands[1];
if (isNegation(firstOperand)) {
- replaceExpression(polyadicExpression, BoolUtils.getNegatedExpressionText(firstOperand) + "==" + secondOperand.getText());
+ PsiReplacementUtil
+ .replaceExpression(polyadicExpression, BoolUtils.getNegatedExpressionText(firstOperand) + "==" + secondOperand.getText());
}
else {
- replaceExpression(polyadicExpression, firstOperand.getText() + "==" + BoolUtils.getNegatedExpressionText(secondOperand));
+ PsiReplacementUtil
+ .replaceExpression(polyadicExpression, firstOperand.getText() + "==" + BoolUtils.getNegatedExpressionText(secondOperand));
}
}
else {
@@ -100,7 +103,7 @@
}
newExpressionText.append(operands[i].getText());
}
- replaceExpression(polyadicExpression, newExpressionText.toString());
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpressionText.toString());
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java
index 2b1ff6b..5d01043 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/ForLoopReplaceableByWhileInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -107,7 +108,7 @@
whileStatement = "while(" + condition.getText() + ')' +
bodyText;
}
- replaceStatement(forStatement, whileStatement);
+ PsiReplacementUtil.replaceStatement(forStatement, whileStatement);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java
index 46eb89e..f756174 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfMayBeConditionalInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ParenthesesUtils;
@@ -159,7 +160,7 @@
return;
}
}
- replaceStatement(ifStatement, replacementText.toString());
+ PsiReplacementUtil.replaceStatement(ifStatement, replacementText.toString());
}
private static void appendExpressionText(@Nullable PsiExpression expression, StringBuilder out) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java
index 6cc7a98..755a4c3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/IfStatementWithIdenticalBranchesInspection.java
@@ -28,6 +28,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import org.jetbrains.annotations.NotNull;
@@ -101,7 +102,7 @@
if (condition1 == null) {
return;
}
- replaceExpression(condition1, buildOrExpressionText(
+ PsiReplacementUtil.replaceExpression(condition1, buildOrExpressionText(
condition1, condition2));
final PsiStatement elseElseBranch =
elseIfStatement.getElseBranch();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java
index cda6605..5d9d11e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/LoopWithImplicitTerminationConditionInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -136,7 +137,7 @@
if (containsUnlabeledBreakStatement(thenBranch)) {
final String negatedExpressionText =
BoolUtils.getNegatedExpressionText(ifCondition);
- replaceExpression(loopCondition, negatedExpressionText);
+ PsiReplacementUtil.replaceExpression(loopCondition, negatedExpressionText);
replaceStatement(ifStatement, elseBranch);
}
else if (containsUnlabeledBreakStatement(elseBranch)) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalExpressionInspection.java
index 73f5d20..72c4ee8 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalExpressionInspection.java
@@ -22,6 +22,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Nls;
@@ -90,7 +91,7 @@
if (elseExpression != null) {
newExpression.append(BoolUtils.getNegatedExpressionText(elseExpression));
}
- replaceExpression(prefixExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(prefixExpression, newExpression.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java
index b8fee88..f51c234 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedConditionalInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
@@ -101,7 +102,7 @@
assert elseBranch != null;
assert thenBranch != null;
final String newStatement = negatedCondition + '?' + elseBranch.getText() + ':' + thenBranch.getText();
- replaceExpression(conditionalExpression, newStatement);
+ PsiReplacementUtil.replaceExpression(conditionalExpression, newStatement);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java
index d7dfbd6..2adfc0f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedEqualityExpressionInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
@@ -94,7 +95,7 @@
if (rhs != null) {
text.append(rhs.getText());
}
- replaceExpression(prefixExpression, text.toString());
+ PsiReplacementUtil.replaceExpression(prefixExpression, text.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java
index 289c74c..5e1135e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/NegatedIfElseInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
@@ -116,7 +117,7 @@
}
}
@NonNls final String newStatement = "if(" + negatedCondition + ')' + elseText + " else " + thenBranch.getText();
- replaceStatement(ifStatement, newStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, newStatement);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
index 84fd514..9d18448 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessBooleanExpressionInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
@@ -283,7 +284,7 @@
return;
}
final PsiExpression expression = (PsiExpression)element;
- replaceExpression(expression, buildSimplifiedExpression(expression, new StringBuilder()).toString());
+ PsiReplacementUtil.replaceExpression(expression, buildSimplifiedExpression(expression, new StringBuilder()).toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
index a958a67..ecb70ea 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/PointlessNullCheckInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -99,10 +100,10 @@
return;
}
if (PsiTreeUtil.isAncestor(rhs, element, false)) {
- replaceExpression(binaryExpression, lhs.getText());
+ PsiReplacementUtil.replaceExpression(binaryExpression, lhs.getText());
}
else if (PsiTreeUtil.isAncestor(lhs, element, false)) {
- replaceExpression(binaryExpression, rhs.getText());
+ PsiReplacementUtil.replaceExpression(binaryExpression, rhs.getText());
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java
index 9263063..155478e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableConditionalExpressionInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NonNls;
@@ -83,7 +84,7 @@
(PsiConditionalExpression)descriptor.getPsiElement();
final String newExpression =
calculateReplacementExpression(expression);
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
index f93948f..7160028 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/SimplifiableEqualsExpressionInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.Nls;
@@ -144,7 +145,7 @@
newExpressionText.append(argument.getText());
}
newExpressionText.append('.').append(referenceName).append('(').append(qualifier.getText()).append(')');
- replaceExpression(polyadicExpression, newExpressionText.toString());
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpressionText.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java
index 92b2e16..e565fe6 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/TrivialIfInspection.java
@@ -21,11 +21,14 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilCore;
+import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
@@ -70,6 +73,7 @@
public String getFamilyName() {
return getName();
}
+
@Override
@NotNull
public String getName() {
@@ -78,208 +82,183 @@
}
@Override
- public void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
+ public void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement ifKeywordElement = descriptor.getPsiElement();
- final PsiIfStatement statement =
- (PsiIfStatement)ifKeywordElement.getParent();
- if (isSimplifiableAssignment(statement)) {
- replaceSimplifiableAssignment(statement);
- }
- else if (isSimplifiableReturn(statement)) {
- repaceSimplifiableReturn(statement);
- }
- else if (isSimplifiableImplicitReturn(statement)) {
- replaceSimplifiableImplicitReturn(statement);
- }
- else if (isSimplifiableAssignmentNegated(statement)) {
- replaceSimplifiableAssignmentNegated(statement);
- }
- else if (isSimplifiableReturnNegated(statement)) {
- repaceSimplifiableReturnNegated(statement);
- }
- else if (isSimplifiableImplicitReturnNegated(statement)) {
- replaceSimplifiableImplicitReturnNegated(statement);
- }
- else if (isSimplifiableImplicitAssignment(statement)) {
- replaceSimplifiableImplicitAssignment(statement);
- }
- else if (isSimplifiableImplicitAssignmentNegated(statement)) {
- replaceSimplifiableImplicitAssignmentNegated(statement);
- }
+ final PsiIfStatement statement = (PsiIfStatement)ifKeywordElement.getParent();
+ simplify(statement);
}
+ }
- private static void replaceSimplifiableImplicitReturn(
- PsiIfStatement statement) throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(statement,
- PsiWhiteSpace.class);
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(statement, newStatement);
- assert nextStatement != null;
- deleteElement(nextStatement);
+ public static void simplify(PsiIfStatement statement) {
+ if (isSimplifiableAssignment(statement)) {
+ replaceSimplifiableAssignment(statement);
}
+ else if (isSimplifiableReturn(statement)) {
+ repaceSimplifiableReturn(statement);
+ }
+ else if (isSimplifiableImplicitReturn(statement)) {
+ replaceSimplifiableImplicitReturn(statement);
+ }
+ else if (isSimplifiableAssignmentNegated(statement)) {
+ replaceSimplifiableAssignmentNegated(statement);
+ }
+ else if (isSimplifiableReturnNegated(statement)) {
+ repaceSimplifiableReturnNegated(statement);
+ }
+ else if (isSimplifiableImplicitReturnNegated(statement)) {
+ replaceSimplifiableImplicitReturnNegated(statement);
+ }
+ else if (isSimplifiableImplicitAssignment(statement)) {
+ replaceSimplifiableImplicitAssignment(statement);
+ }
+ else if (isSimplifiableImplicitAssignmentNegated(statement)) {
+ replaceSimplifiableImplicitAssignmentNegated(statement);
+ }
+ }
- private static void repaceSimplifiableReturn(PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- @NonNls final String newStatement = "return " + conditionText + ';';
- final Collection<PsiComment> comments = PsiTreeUtil.findChildrenOfType(statement, PsiComment.class);
- final PsiElement parent = statement.getParent();
- for (PsiComment comment : comments) {
- parent.addBefore(comment.copy(), statement);
- }
- replaceStatement(statement, newStatement);
+ private static void replaceSimplifiableImplicitReturn(
+ PsiIfStatement statement) throws IncorrectOperationException {
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
}
+ final String conditionText = condition.getText();
+ final PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(statement, PsiWhiteSpace.class);
+ @NonNls final String newStatement = "return " + conditionText + ';';
+ PsiReplacementUtil.replaceStatement(statement, newStatement);
+ assert nextStatement != null;
+ nextStatement.delete();
+ }
- private static void replaceSimplifiableAssignment(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)
- ControlFlowUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)assignmentStatement.getExpression();
- final PsiJavaToken operator =
- assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(statement,
- lhsText + operand + conditionText + ';');
+ private static void repaceSimplifiableReturn(PsiIfStatement statement)
+ throws IncorrectOperationException {
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
}
+ final String conditionText = condition.getText();
+ @NonNls final String newStatement = "return " + conditionText + ';';
+ final Collection<PsiComment> comments = PsiTreeUtil.findChildrenOfType(statement, PsiComment.class);
+ final PsiElement parent = statement.getParent();
+ for (PsiComment comment : comments) {
+ parent.addBefore(comment.copy(), statement);
+ }
+ PsiReplacementUtil.replaceStatement(statement, newStatement);
+ }
- private static void replaceSimplifiableImplicitAssignment(
- PsiIfStatement statement) throws IncorrectOperationException {
- final PsiElement prevStatement =
- PsiTreeUtil.skipSiblingsBackward(statement,
- PsiWhiteSpace.class);
- if (prevStatement == null) {
- return;
- }
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)
- ControlFlowUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)assignmentStatement.getExpression();
- final PsiJavaToken operator =
- assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(statement,
- lhsText + operand + conditionText + ';');
- deleteElement(prevStatement);
+ private static void replaceSimplifiableAssignment(PsiIfStatement statement)
+ throws IncorrectOperationException {
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
}
+ final Collection<PsiComment> comments = ContainerUtil.map(PsiTreeUtil.findChildrenOfType(statement, PsiComment.class),
+ new Function<PsiComment, PsiComment>() {
+ @Override
+ public PsiComment fun(PsiComment comment) {
+ return (PsiComment)comment.copy();
+ }
+ });
+ final String conditionText = condition.getText();
+ final PsiStatement thenBranch = statement.getThenBranch();
+ final PsiExpressionStatement assignmentStatement = (PsiExpressionStatement)ControlFlowUtils.stripBraces(thenBranch);
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)assignmentStatement.getExpression();
+ final PsiJavaToken operator = assignmentExpression.getOperationSign();
+ final String operand = operator.getText();
+ final PsiExpression lhs = assignmentExpression.getLExpression();
+ final String lhsText = lhs.getText();
+ final PsiElement parent = statement.getParent();
+ for (PsiComment comment : comments) {
+ parent.addBefore(comment, statement);
+ }
+ PsiReplacementUtil.replaceStatement(statement, lhsText + operand + conditionText + ';');
+ }
- private static void replaceSimplifiableImplicitAssignmentNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiElement prevStatement =
- PsiTreeUtil.skipSiblingsBackward(statement,
- PsiWhiteSpace.class);
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)
- ControlFlowUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)
- assignmentStatement.getExpression();
- final PsiJavaToken operator =
- assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(statement,
- lhsText + operand + conditionText + ';');
- assert prevStatement != null;
- deleteElement(prevStatement);
+ private static void replaceSimplifiableImplicitAssignment(PsiIfStatement statement) throws IncorrectOperationException {
+ final PsiElement prevStatement = PsiTreeUtil.skipSiblingsBackward(statement, PsiWhiteSpace.class);
+ if (prevStatement == null) {
+ return;
}
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
+ }
+ final String conditionText = condition.getText();
+ final PsiStatement thenBranch = statement.getThenBranch();
+ final PsiExpressionStatement assignmentStatement =
+ (PsiExpressionStatement)
+ ControlFlowUtils.stripBraces(thenBranch);
+ final PsiAssignmentExpression assignmentExpression =
+ (PsiAssignmentExpression)assignmentStatement.getExpression();
+ final PsiJavaToken operator =
+ assignmentExpression.getOperationSign();
+ final String operand = operator.getText();
+ final PsiExpression lhs = assignmentExpression.getLExpression();
+ final String lhsText = lhs.getText();
+ PsiReplacementUtil.replaceStatement(statement, lhsText + operand + conditionText + ';');
+ prevStatement.delete();
+ }
- private static void replaceSimplifiableImplicitReturnNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(statement,
- PsiWhiteSpace.class);
- if (nextStatement == null) {
- return;
- }
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(statement, newStatement);
- deleteElement(nextStatement);
+ private static void replaceSimplifiableImplicitAssignmentNegated(PsiIfStatement statement) {
+ final PsiElement prevStatement = PsiTreeUtil.skipSiblingsBackward(statement, PsiWhiteSpace.class);
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
}
+ final String conditionText = BoolUtils.getNegatedExpressionText(condition);
+ final PsiStatement thenBranch = statement.getThenBranch();
+ final PsiExpressionStatement assignmentStatement = (PsiExpressionStatement)ControlFlowUtils.stripBraces(thenBranch);
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression) assignmentStatement.getExpression();
+ final PsiJavaToken operator =
+ assignmentExpression.getOperationSign();
+ final String operand = operator.getText();
+ final PsiExpression lhs = assignmentExpression.getLExpression();
+ final String lhsText = lhs.getText();
+ PsiReplacementUtil.replaceStatement(statement, lhsText + operand + conditionText + ';');
+ assert prevStatement != null;
+ prevStatement.delete();
+ }
- private static void repaceSimplifiableReturnNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(statement, newStatement);
+ private static void replaceSimplifiableImplicitReturnNegated(PsiIfStatement statement) {
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
}
+ final String conditionText = BoolUtils.getNegatedExpressionText(condition);
+ final PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(statement, PsiWhiteSpace.class);
+ if (nextStatement == null) {
+ return;
+ }
+ @NonNls final String newStatement = "return " + conditionText + ';';
+ PsiReplacementUtil.replaceStatement(statement, newStatement);
+ nextStatement.delete();
+ }
- private static void replaceSimplifiableAssignmentNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)
- ControlFlowUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)
- assignmentStatement.getExpression();
- final PsiJavaToken operator =
- assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(statement,
- lhsText + operand + conditionText + ';');
+ private static void repaceSimplifiableReturnNegated(PsiIfStatement statement) {
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
}
+ final String conditionText = BoolUtils.getNegatedExpressionText(condition);
+ @NonNls final String newStatement = "return " + conditionText + ';';
+ PsiReplacementUtil.replaceStatement(statement, newStatement);
+ }
+
+ private static void replaceSimplifiableAssignmentNegated(PsiIfStatement statement) {
+ final PsiExpression condition = statement.getCondition();
+ if (condition == null) {
+ return;
+ }
+ final String conditionText = BoolUtils.getNegatedExpressionText(condition);
+ final PsiStatement thenBranch = statement.getThenBranch();
+ final PsiExpressionStatement assignmentStatement = (PsiExpressionStatement)ControlFlowUtils.stripBraces(thenBranch);
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)assignmentStatement.getExpression();
+ final PsiJavaToken operator =
+ assignmentExpression.getOperationSign();
+ final String operand = operator.getText();
+ final PsiExpression lhs = assignmentExpression.getLExpression();
+ final String lhsText = lhs.getText();
+ PsiReplacementUtil.replaceStatement(statement, lhsText + operand + conditionText + ';');
}
@Override
@@ -296,53 +275,50 @@
if (condition == null) {
return;
}
- if (PsiUtilCore.hasErrorElementChild(ifStatement)) {
- return;
- }
- if (isSimplifiableAssignment(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableReturn(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableImplicitReturn(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableAssignmentNegated(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableReturnNegated(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableImplicitReturnNegated(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableImplicitAssignment(ifStatement)) {
- registerStatementError(ifStatement);
- return;
- }
- if (isSimplifiableImplicitAssignmentNegated(ifStatement)) {
+ if (isTrivial(ifStatement)) {
registerStatementError(ifStatement);
}
}
}
- public static boolean isSimplifiableImplicitReturn(
- PsiIfStatement ifStatement) {
+ public static boolean isTrivial(PsiIfStatement ifStatement) {
+ if (PsiUtilCore.hasErrorElementChild(ifStatement)) {
+ return false;
+ }
+ if (isSimplifiableAssignment(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableReturn(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableImplicitReturn(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableAssignmentNegated(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableReturnNegated(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableImplicitReturnNegated(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableImplicitAssignment(ifStatement)) {
+ return true;
+ }
+ if (isSimplifiableImplicitAssignmentNegated(ifStatement)) {
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isSimplifiableImplicitReturn(PsiIfStatement ifStatement) {
if (ifStatement.getElseBranch() != null) {
return false;
}
PsiStatement thenBranch = ifStatement.getThenBranch();
thenBranch = ControlFlowUtils.stripBraces(thenBranch);
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(ifStatement,
- PsiWhiteSpace.class);
+ final PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(ifStatement, PsiWhiteSpace.class);
if (!(nextStatement instanceof PsiStatement)) {
return false;
}
@@ -352,8 +328,7 @@
&& ConditionalUtils.isReturn(elseBranch, PsiKeyword.FALSE);
}
- public static boolean isSimplifiableImplicitReturnNegated(
- PsiIfStatement ifStatement) {
+ public static boolean isSimplifiableImplicitReturnNegated(PsiIfStatement ifStatement) {
if (ifStatement.getElseBranch() != null) {
return false;
}
@@ -380,8 +355,7 @@
&& ConditionalUtils.isReturn(elseBranch, PsiKeyword.FALSE);
}
- public static boolean isSimplifiableReturnNegated(
- PsiIfStatement ifStatement) {
+ public static boolean isSimplifiableReturnNegated(PsiIfStatement ifStatement) {
PsiStatement thenBranch = ifStatement.getThenBranch();
thenBranch = ControlFlowUtils.stripBraces(thenBranch);
PsiStatement elseBranch = ifStatement.getElseBranch();
@@ -421,8 +395,7 @@
}
}
- public static boolean isSimplifiableAssignmentNegated(
- PsiIfStatement ifStatement) {
+ public static boolean isSimplifiableAssignmentNegated(PsiIfStatement ifStatement) {
PsiStatement thenBranch = ifStatement.getThenBranch();
thenBranch = ControlFlowUtils.stripBraces(thenBranch);
PsiStatement elseBranch = ifStatement.getElseBranch();
@@ -453,8 +426,7 @@
}
}
- public static boolean isSimplifiableImplicitAssignment(
- PsiIfStatement ifStatement) {
+ public static boolean isSimplifiableImplicitAssignment(PsiIfStatement ifStatement) {
if (ifStatement.getElseBranch() != null) {
return false;
}
@@ -494,8 +466,7 @@
}
}
- public static boolean isSimplifiableImplicitAssignmentNegated(
- PsiIfStatement ifStatement) {
+ public static boolean isSimplifiableImplicitAssignmentNegated(PsiIfStatement ifStatement) {
if (ifStatement.getElseBranch() != null) {
return false;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java
index 446e713..c511cdb 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/controlflow/UnnecessaryConditionalExpressionInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import org.jetbrains.annotations.NotNull;
@@ -105,7 +106,7 @@
(PsiConditionalExpression)descriptor.getPsiElement();
final String newExpression =
calculateReplacementExpression(expression);
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java
deleted file mode 100644
index 0ae7803..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dataflow/OrredNotEqualExpressionInspection.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright 2009 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.dataflow;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.util.IncorrectOperationException;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class OrredNotEqualExpressionInspection extends BaseInspection {
-
- @Override
- @Nls
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "orred.not.equal.expression.display.name");
- }
-
- @Override
- @NotNull
- protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "orred.not.equal.expression.problem.descriptor");
- }
-
- @Override
- public boolean isEnabledByDefault() {
- return true;
- }
-
- @Override
- protected InspectionGadgetsFix buildFix(Object... infos) {
- return new OrredNotEqualExpressionFix();
- }
-
- private static class OrredNotEqualExpressionFix
- extends InspectionGadgetsFix {
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- @NotNull
- public String getName() {
- return InspectionGadgetsBundle.message(
- "orred.not.equal.expression.quickfix");
- }
-
- @Override
- protected void doFix(Project project, ProblemDescriptor descriptor)
- throws IncorrectOperationException {
- final PsiElement element = descriptor.getPsiElement();
- if (!(element instanceof PsiBinaryExpression)) {
- return;
- }
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)element;
- final PsiExpression lhs = binaryExpression.getLOperand();
- final String lhsText = lhs.getText();
- final PsiExpression rhs = binaryExpression.getROperand();
- if (rhs == null) {
- return;
- }
- final String rhsText = rhs.getText();
- replaceExpression(binaryExpression, lhsText + "&&" + rhsText);
- }
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new OrredNotEqualExpressionVisitor();
- }
-
- private static class OrredNotEqualExpressionVisitor
- extends BaseInspectionVisitor {
-
- @Override
- public void visitBinaryExpression(PsiBinaryExpression expression) {
- final IElementType tokenType = expression.getOperationTokenType();
- if (JavaTokenType.OROR != tokenType) {
- return;
- }
- final PsiExpression lhs = expression.getLOperand();
- final PsiExpression rhs = expression.getROperand();
- final Pair<PsiReferenceExpression, PsiExpression> pair1 =
- getReferenceExpressionPair(lhs);
- final Pair<PsiReferenceExpression, PsiExpression> pair2 =
- getReferenceExpressionPair(rhs);
- if (pair1 == null || pair2 == null) {
- return;
- }
- final PsiExpression expression1 = pair1.getSecond();
- final PsiExpression expression2 = pair2.getSecond();
- if (expression1 == null || expression2 == null) {
- return;
- }
- final Project project = expression1.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiConstantEvaluationHelper constantEvaluationHelper =
- psiFacade.getConstantEvaluationHelper();
- final Object constant1 =
- constantEvaluationHelper.computeConstantExpression(expression1);
- final Object constant2 =
- constantEvaluationHelper.computeConstantExpression(expression2);
- if (constant1 == null || constant2 == null || constant1 == constant2) {
- return;
- }
- final PsiReferenceExpression referenceExpression1 = pair1.getFirst();
- final PsiReferenceExpression referenceExpression2 = pair2.getFirst();
- if (referenceExpression1.resolve() == referenceExpression2.resolve()) {
- registerError(expression);
- }
- }
-
- @Nullable
- private static Pair<PsiReferenceExpression, PsiExpression>
- getReferenceExpressionPair(PsiExpression expression) {
- if (!(expression instanceof PsiBinaryExpression)) {
- return null;
- }
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType tokenType =
- binaryExpression.getOperationTokenType();
- if (JavaTokenType.NE != tokenType) {
- return null;
- }
- final PsiExpression lhs = binaryExpression.getLOperand();
- final PsiExpression rhs = binaryExpression.getROperand();
- if (lhs instanceof PsiReferenceExpression) {
- final PsiReferenceExpression lref =
- (PsiReferenceExpression)lhs;
- return new Pair(lref, rhs);
- }
- else if (rhs instanceof PsiReferenceExpression) {
- final PsiReferenceExpression rref =
- (PsiReferenceExpression)rhs;
- return new Pair(rref, lhs);
- }
- return null;
- }
- }
-}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicPackageDependencyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicPackageDependencyInspection.java
index 401cbdb..7a07baf 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicPackageDependencyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/CyclicPackageDependencyInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2006-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.
@@ -21,11 +21,13 @@
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.reference.RefEntity;
import com.intellij.codeInspection.reference.RefPackage;
+import com.intellij.codeInspection.util.RefEntityAlphabeticalComparator;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseGlobalInspection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
@@ -49,21 +51,31 @@
return null;
}
final RefPackage refPackage = (RefPackage)refEntity;
- final Set<RefPackage> dependencies =
- DependencyUtils.calculateTransitiveDependenciesForPackage(refPackage);
- final Set<RefPackage> dependents =
- DependencyUtils.calculateTransitiveDependentsForPackage(refPackage);
- final Set<RefPackage> mutualDependents =
- new HashSet<RefPackage>(dependencies);
+ final Set<RefPackage> dependencies = DependencyUtils.calculateTransitiveDependenciesForPackage(refPackage);
+ final Set<RefPackage> dependents = DependencyUtils.calculateTransitiveDependentsForPackage(refPackage);
+ final Set<RefPackage> mutualDependents = new HashSet<RefPackage>(dependencies);
mutualDependents.retainAll(dependents);
final int numMutualDependents = mutualDependents.size();
- if (numMutualDependents <= 1) {
+ if (numMutualDependents == 0) {
return null;
}
- final String packageName = refEntity.getName();
- final String errorString = InspectionGadgetsBundle.message(
- "cyclic.package.dependency.problem.descriptor",
- packageName, numMutualDependents - 1);
+ final String packageName = refPackage.getQualifiedName();
+ final String errorString;
+ if (numMutualDependents == 1) {
+ final RefPackage[] packages = mutualDependents.toArray(new RefPackage[1]);
+ errorString = InspectionGadgetsBundle.message("cyclic.package.dependency.1.problem.descriptor",
+ packageName, packages[0].getQualifiedName());
+ }
+ else if (numMutualDependents == 2) {
+ final RefPackage[] packages = mutualDependents.toArray(new RefPackage[2]);
+ Arrays.sort(packages, RefEntityAlphabeticalComparator.getInstance());
+ errorString = InspectionGadgetsBundle.message("cyclic.package.dependency.2.problem.descriptor",
+ packageName, packages[0].getQualifiedName(), packages[1].getQualifiedName());
+ }
+ else {
+ errorString = InspectionGadgetsBundle.message("cyclic.package.dependency.problem.descriptor",
+ packageName, Integer.valueOf(numMutualDependents));
+ }
return new CommonProblemDescriptor[]{
inspectionManager.createProblemDescriptor(errorString)
};
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/DependencyUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/DependencyUtils.java
index f66c4c0..f70d3e3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/DependencyUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/dependency/DependencyUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2011 Dave Griffith, Bas Leijdekkers
+ * Copyright 2006-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.
@@ -249,11 +249,10 @@
return newDependents;
}
- static void tabulateDependentPackages(RefEntity entity,
- Set<RefPackage> dependents) {
+ static void tabulateDependentPackages(RefEntity entity, Set<RefPackage> dependents) {
if (entity instanceof RefElement) {
final RefElement element = (RefElement)entity;
- final Collection<RefElement> references = element.getOutReferences();
+ final Collection<RefElement> references = element.getInReferences();
for (RefElement reference : references) {
final RefPackage refPackage = RefJavaUtil.getPackage(reference);
if (refPackage != null) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java
index 786236f..5278ee0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/encapsulation/ReturnOfDateFieldInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -93,7 +94,7 @@
if (type == null) {
return;
}
- replaceExpression(referenceExpression, '(' + type + ')' + referenceExpression.getText() + ".clone()");
+ PsiReplacementUtil.replaceExpression(referenceExpression, '(' + type + ')' + referenceExpression.getText() + ".clone()");
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspectionBase.java
index 147c0e8..293f84c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspectionBase.java
@@ -45,7 +45,7 @@
);
@SuppressWarnings("PublicField")
- public boolean ignoreTestCases = false;
+ public boolean ignoreTestCases = false; // keep for compatibility
@SuppressWarnings("PublicField")
public boolean ignoreLibraryOverrides = false;
@@ -89,13 +89,6 @@
@Override
public void visitMethod(@NotNull PsiMethod method) {
super.visitMethod(method);
- if (ignoreTestCases) {
- final PsiClass containingClass = method.getContainingClass();
- final TestFrameworks testFrameworks = TestFrameworks.getInstance();
- if (containingClass != null && testFrameworks.isTestOrConfig(containingClass)) {
- return;
- }
- }
if (ignoreLibraryOverrides && LibraryUtil.isOverrideOfLibraryMethod(method)) {
return;
}
@@ -109,7 +102,7 @@
final PsiClass thrownClass = (PsiClass)element;
final String qualifiedName = thrownClass.getQualifiedName();
if (qualifiedName != null && exceptions.contains(qualifiedName)) {
- registerError(reference);
+ registerError(reference, reference);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
deleted file mode 100644
index fa50fb4..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.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.ig.errorhandling;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtil;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import com.intellij.psi.util.FileTypeUtils;
-import com.siyeh.ig.psiutils.TestUtils;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-public class EmptyCatchBlockInspection extends BaseInspection {
-
- /**
- * @noinspection PublicField
- */
- public boolean m_includeComments = true;
- /**
- * @noinspection PublicField
- */
- public boolean m_ignoreTestCases = true;
- /**
- * @noinspection PublicField
- */
- public boolean m_ignoreIgnoreParameter = true;
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("empty.catch.block.display.name");
- }
-
- @Override
- @NotNull
- protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message("empty.catch.block.problem.descriptor");
- }
-
- @Override
- public boolean isEnabledByDefault() {
- return true;
- }
-
- @Override
- public JComponent createOptionsPanel() {
- final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("empty.catch.block.comments.option"), "m_includeComments");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("empty.catch.block.ignore.option"), "m_ignoreTestCases");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("empty.catch.block.ignore.ignore.option"), "m_ignoreIgnoreParameter");
- return optionsPanel;
- }
-
- @Override
- @Nullable
- protected InspectionGadgetsFix buildFix(Object... infos) {
- return new EmptyCatchBlockFix();
- }
-
- private static class EmptyCatchBlockFix extends InspectionGadgetsFix {
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- @NotNull
- public String getName() {
- return InspectionGadgetsBundle.message("rename.catch.parameter.to.ignored");
- }
-
- @Override
- protected void doFix(Project project, ProblemDescriptor descriptor) {
- final PsiElement element = descriptor.getPsiElement();
- final PsiElement parent = element.getParent();
- if (!(parent instanceof PsiCatchSection)) {
- return;
- }
- final PsiCatchSection catchSection = (PsiCatchSection)parent;
- final PsiParameter parameter = catchSection.getParameter();
- if (parameter == null) {
- return;
- }
- final PsiIdentifier identifier = parameter.getNameIdentifier();
- if (identifier == null) {
- return;
- }
- final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
- final PsiIdentifier newIdentifier = factory.createIdentifier("ignored");
- identifier.replace(newIdentifier);
- }
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new EmptyCatchBlockVisitor();
- }
-
- private class EmptyCatchBlockVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitTryStatement(@NotNull PsiTryStatement statement) {
- super.visitTryStatement(statement);
- if (FileTypeUtils.isInServerPageFile(statement.getContainingFile())) {
- return;
- }
- if (m_ignoreTestCases && TestUtils.isInTestCode(statement)) {
- return;
- }
- final PsiCatchSection[] catchSections = statement.getCatchSections();
- for (final PsiCatchSection section : catchSections) {
- checkCatchSection(section);
- }
- }
-
- private void checkCatchSection(PsiCatchSection section) {
- final PsiCodeBlock block = section.getCatchBlock();
- if (block == null || !isEmpty(block)) {
- return;
- }
- final PsiParameter parameter = section.getParameter();
- if (parameter == null) {
- return;
- }
- final PsiIdentifier identifier = parameter.getNameIdentifier();
- if (identifier == null) {
- return;
- }
- @NonNls final String parameterName = parameter.getName();
- if (m_ignoreIgnoreParameter && PsiUtil.isIgnoredName(parameterName)) {
- return;
- }
- final PsiElement catchToken = section.getFirstChild();
- if (catchToken == null) {
- return;
- }
- registerError(catchToken);
- }
-
- private boolean isEmpty(PsiElement element) {
- if (!m_includeComments && element instanceof PsiComment) {
- return true;
- } else if (element instanceof PsiEmptyStatement) {
- if (m_includeComments) {
- final PsiElement[] children = element.getChildren();
- for (PsiElement child : children) {
- if (child instanceof PsiComment) {
- return false;
- }
- }
- }
- return true;
- } else if (element instanceof PsiWhiteSpace) {
- return true;
- } else if (element instanceof PsiBlockStatement) {
- final PsiBlockStatement block = (PsiBlockStatement)element;
- return isEmpty(block.getCodeBlock());
- } else if (element instanceof PsiCodeBlock) {
- final PsiCodeBlock codeBlock = (PsiCodeBlock)element;
- PsiElement bodyElement = codeBlock.getFirstBodyElement();
- final PsiElement lastBodyElement = codeBlock.getLastBodyElement();
- while (bodyElement != null) {
- if (!isEmpty(bodyElement)) {
- return false;
- }
- if (bodyElement == lastBodyElement) {
- break;
- }
- bodyElement = bodyElement.getNextSibling();
- }
- return true;
- }
- return false;
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionBase.java
new file mode 100644
index 0000000..628853e
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionBase.java
@@ -0,0 +1,195 @@
+/*
+ * 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.ig.errorhandling;
+
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.FileTypeUtils;
+import com.intellij.psi.util.PsiUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.TestUtils;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+
+public class EmptyCatchBlockInspectionBase extends BaseInspection {
+
+ /**
+ * @noinspection PublicField
+ */
+ public boolean m_includeComments = true;
+ /**
+ * @noinspection PublicField
+ */
+ public boolean m_ignoreTestCases = true; // keep for compatibility
+ /**
+ * @noinspection PublicField
+ */
+ public boolean m_ignoreIgnoreParameter = true;
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("empty.catch.block.display.name");
+ }
+
+ @Override
+ @NotNull
+ protected String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("empty.catch.block.problem.descriptor");
+ }
+
+ @Override
+ public boolean isEnabledByDefault() {
+ return true;
+ }
+
+ @Override
+ public JComponent createOptionsPanel() {
+ final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("empty.catch.block.comments.option"), "m_includeComments");
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("empty.catch.block.ignore.ignore.option"), "m_ignoreIgnoreParameter");
+ return optionsPanel;
+ }
+
+ @Override
+ @Nullable
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ return new EmptyCatchBlockFix();
+ }
+
+ private static class EmptyCatchBlockFix extends InspectionGadgetsFix {
+ @Override
+ @NotNull
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ @NotNull
+ public String getName() {
+ return InspectionGadgetsBundle.message("rename.catch.parameter.to.ignored");
+ }
+
+ @Override
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ final PsiElement parent = element.getParent();
+ if (!(parent instanceof PsiCatchSection)) {
+ return;
+ }
+ final PsiCatchSection catchSection = (PsiCatchSection)parent;
+ final PsiParameter parameter = catchSection.getParameter();
+ if (parameter == null) {
+ return;
+ }
+ final PsiIdentifier identifier = parameter.getNameIdentifier();
+ if (identifier == null) {
+ return;
+ }
+ final PsiElementFactory factory = JavaPsiFacade.getInstance(project).getElementFactory();
+ final PsiIdentifier newIdentifier = factory.createIdentifier("ignored");
+ identifier.replace(newIdentifier);
+ }
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new EmptyCatchBlockVisitor();
+ }
+
+ private class EmptyCatchBlockVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitTryStatement(@NotNull PsiTryStatement statement) {
+ super.visitTryStatement(statement);
+ if (FileTypeUtils.isInServerPageFile(statement.getContainingFile())) {
+ return;
+ }
+ final PsiCatchSection[] catchSections = statement.getCatchSections();
+ for (final PsiCatchSection section : catchSections) {
+ checkCatchSection(section);
+ }
+ }
+
+ private void checkCatchSection(PsiCatchSection section) {
+ final PsiCodeBlock block = section.getCatchBlock();
+ if (block == null || !isEmpty(block)) {
+ return;
+ }
+ final PsiParameter parameter = section.getParameter();
+ if (parameter == null) {
+ return;
+ }
+ final PsiIdentifier identifier = parameter.getNameIdentifier();
+ if (identifier == null) {
+ return;
+ }
+ @NonNls final String parameterName = parameter.getName();
+ if (m_ignoreIgnoreParameter && PsiUtil.isIgnoredName(parameterName)) {
+ return;
+ }
+ final PsiElement catchToken = section.getFirstChild();
+ if (catchToken == null) {
+ return;
+ }
+ registerError(catchToken, catchToken);
+ }
+
+ private boolean isEmpty(PsiElement element) {
+ if (!m_includeComments && element instanceof PsiComment) {
+ return true;
+ } else if (element instanceof PsiEmptyStatement) {
+ if (m_includeComments) {
+ final PsiElement[] children = element.getChildren();
+ for (PsiElement child : children) {
+ if (child instanceof PsiComment) {
+ return false;
+ }
+ }
+ }
+ return true;
+ } else if (element instanceof PsiWhiteSpace) {
+ return true;
+ } else if (element instanceof PsiBlockStatement) {
+ final PsiBlockStatement block = (PsiBlockStatement)element;
+ return isEmpty(block.getCodeBlock());
+ } else if (element instanceof PsiCodeBlock) {
+ final PsiCodeBlock codeBlock = (PsiCodeBlock)element;
+ PsiElement bodyElement = codeBlock.getFirstBodyElement();
+ final PsiElement lastBodyElement = codeBlock.getLastBodyElement();
+ while (bodyElement != null) {
+ if (!isEmpty(bodyElement)) {
+ return false;
+ }
+ if (bodyElement == lastBodyElement) {
+ break;
+ }
+ bodyElement = bodyElement.getNextSibling();
+ }
+ return true;
+ }
+ return false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadCatchInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadCatchInspectionBase.java
index eb292f4..d225e64 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadCatchInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadCatchInspectionBase.java
@@ -21,7 +21,6 @@
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExceptionUtils;
-import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NotNull;
import java.util.*;
@@ -29,8 +28,8 @@
public class TooBroadCatchInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean onlyWarnOnRootExceptions = false;
- @SuppressWarnings("PublicField")
- public boolean ignoreInTestCode = false;
+ @SuppressWarnings({"PublicField", "UnusedDeclaration"})
+ public boolean ignoreInTestCode = false; // keep for compatibility
@SuppressWarnings("PublicField")
public boolean ignoreThrown = false;
@@ -80,9 +79,6 @@
if (tryBlock == null) {
return;
}
- if (ignoreInTestCode && TestUtils.isInTestCode(statement)) {
- return;
- }
final Set<PsiClassType> thrownTypes = ExceptionUtils.calculateExceptionsThrown(tryBlock);
final Set<PsiType> caughtTypes = new HashSet<PsiType>(thrownTypes.size());
final PsiCatchSection[] catchSections = statement.getCatchSections();
@@ -107,7 +103,7 @@
continue;
}
final PsiClass runtimeExceptionClass = ClassUtils.findClass(CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION, parameter);
- registerError(typeElement, Collections.singletonList(runtimeExceptionClass));
+ registerError(typeElement, Collections.singletonList(runtimeExceptionClass), typeElement);
}
}
else {
@@ -126,7 +122,7 @@
if (typeElement == null) {
return;
}
- registerError(typeElement, maskedExceptions);
+ registerError(typeElement, maskedExceptions, typeElement);
}
private List<PsiClass> findMaskedExceptions(Set<PsiClassType> thrownTypes, Set<PsiType> caughtTypes, PsiType caughtType) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
deleted file mode 100644
index 338992a..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- * Copyright 2010-2012 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.errorhandling;
-
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.containers.ContainerUtil;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.ExceptionUtils;
-import com.siyeh.ig.psiutils.LibraryUtil;
-import com.siyeh.ig.psiutils.TestUtils;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.util.*;
-
-public class TooBroadThrowsInspection extends BaseInspection {
-
- @SuppressWarnings({"PublicField"})
- public boolean onlyWarnOnRootExceptions = false;
-
- @SuppressWarnings("PublicField")
- public boolean ignoreInTestCode = false;
-
- @SuppressWarnings("PublicField")
- public boolean ignoreLibraryOverrides = false;
-
- @SuppressWarnings("PublicField")
- public boolean ignoreThrown = false;
-
- @Override
- @NotNull
- public String getID() {
- return "OverlyBroadThrowsClause";
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("overly.broad.throws.clause.display.name");
- }
-
- @Override
- @NotNull
- protected String buildErrorString(Object... infos) {
- final List<SmartTypePointer> typesMasked = (List<SmartTypePointer>)infos[0];
- final PsiType type = typesMasked.get(0).getType();
- String typesMaskedString = type != null ? type.getPresentableText() : "";
- if (typesMasked.size() == 1) {
- return InspectionGadgetsBundle.message(
- "overly.broad.throws.clause.problem.descriptor1",
- typesMaskedString);
- }
- else {
- final int lastTypeIndex = typesMasked.size() - 1;
- for (int i = 1; i < lastTypeIndex; i++) {
- final PsiType psiType = typesMasked.get(i).getType();
- if (psiType != null) {
- typesMaskedString += ", ";
- typesMaskedString += psiType.getPresentableText();
- }
- }
- final PsiType psiType = typesMasked.get(lastTypeIndex).getType();
- final String lastTypeString = psiType != null ? psiType.getPresentableText() : "";
- return InspectionGadgetsBundle.message("overly.broad.throws.clause.problem.descriptor2", typesMaskedString, lastTypeString);
- }
- }
-
- @Override
- public JComponent createOptionsPanel() {
- final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
- panel.addCheckbox(InspectionGadgetsBundle.message("too.broad.catch.option"), "onlyWarnOnRootExceptions");
- panel.addCheckbox(InspectionGadgetsBundle.message("ignore.exceptions.declared.in.tests.option"), "ignoreInTestCode");
- panel.addCheckbox(InspectionGadgetsBundle.message("ignore.exceptions.declared.on.library.override.option"), "ignoreLibraryOverrides");
- panel.addCheckbox(InspectionGadgetsBundle.message("overly.broad.throws.clause.ignore.thrown.option"), "ignoreThrown");
- return panel;
- }
-
- @NotNull
- @Override
- protected InspectionGadgetsFix buildFix(Object... infos) {
- final Collection<SmartTypePointer> maskedExceptions = (Collection<SmartTypePointer>)infos[0];
- final Boolean originalNeeded = (Boolean)infos[1];
- return new AddThrowsClauseFix(maskedExceptions, originalNeeded.booleanValue());
- }
-
- private static class AddThrowsClauseFix extends InspectionGadgetsFix {
-
- private final Collection<SmartTypePointer> types;
- private final boolean originalNeeded;
-
- AddThrowsClauseFix(Collection<SmartTypePointer> types, boolean originalNeeded) {
- this.types = types;
- this.originalNeeded = originalNeeded;
- }
-
- @Override
- @NotNull
- public String getName() {
- if (originalNeeded) {
- return InspectionGadgetsBundle.message("overly.broad.throws.clause.quickfix1");
- }
- else {
- return InspectionGadgetsBundle.message("overly.broad.throws.clause.quickfix2");
- }
- }
-
- @NotNull
- @Override
- public String getFamilyName() {
- return "Fix 'throws' clause";
- }
-
- @Override
- protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
- final PsiElement element = descriptor.getPsiElement();
- final PsiElement parent = element.getParent();
- if (!(parent instanceof PsiReferenceList)) {
- return;
- }
- final PsiReferenceList referenceList = (PsiReferenceList)parent;
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
- if (!originalNeeded) {
- element.delete();
- }
- for (SmartTypePointer type : types) {
- final PsiType psiType = type.getType();
- if (psiType instanceof PsiClassType) {
- final PsiJavaCodeReferenceElement referenceElement = factory.createReferenceElementByType((PsiClassType)psiType);
- referenceList.add(referenceElement);
- }
- }
- }
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new TooBroadThrowsVisitor();
- }
-
- private class TooBroadThrowsVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitMethod(PsiMethod method) {
- super.visitMethod(method);
- final PsiReferenceList throwsList = method.getThrowsList();
- if (!throwsList.isPhysical()) {
- return;
- }
- final PsiJavaCodeReferenceElement[] throwsReferences = throwsList.getReferenceElements();
- if (throwsReferences.length == 0) {
- return;
- }
- final PsiCodeBlock body = method.getBody();
- if (body == null) {
- return;
- }
- if (ignoreInTestCode && TestUtils.isInTestCode(method)) {
- return;
- }
- if (ignoreLibraryOverrides && LibraryUtil.isOverrideOfLibraryMethod(method)) {
- return;
- }
- final Set<PsiClassType> exceptionsThrown = ExceptionUtils.calculateExceptionsThrown(body);
- final PsiClassType[] referencedExceptions = throwsList.getReferencedTypes();
- final Set<PsiClassType> exceptionsDeclared = new HashSet(referencedExceptions.length);
- ContainerUtil.addAll(exceptionsDeclared, referencedExceptions);
- final int referencedExceptionsLength = referencedExceptions.length;
- for (int i = 0; i < referencedExceptionsLength; i++) {
- final PsiClassType referencedException = referencedExceptions[i];
- if (onlyWarnOnRootExceptions) {
- if (!ExceptionUtils.isGenericExceptionClass(
- referencedException)) {
- continue;
- }
- }
- final List<SmartTypePointer> exceptionsMasked = new ArrayList();
- final SmartTypePointerManager pointerManager = SmartTypePointerManager.getInstance(body.getProject());
- for (PsiClassType exceptionThrown : exceptionsThrown) {
- if (referencedException.isAssignableFrom(exceptionThrown) && !exceptionsDeclared.contains(exceptionThrown)) {
- exceptionsMasked.add(pointerManager.createSmartTypePointer(exceptionThrown));
- }
- }
- if (!exceptionsMasked.isEmpty()) {
- final PsiJavaCodeReferenceElement throwsReference = throwsReferences[i];
- final boolean originalNeeded = exceptionsThrown.contains(referencedException);
- if (ignoreThrown && originalNeeded) {
- continue;
- }
- registerError(throwsReference, exceptionsMasked, Boolean.valueOf(originalNeeded));
- }
- }
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionBase.java
new file mode 100644
index 0000000..6100a7c
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspectionBase.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2010-2013 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.errorhandling;
+
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.ExceptionUtils;
+import com.siyeh.ig.psiutils.LibraryUtil;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.*;
+
+public class TooBroadThrowsInspectionBase extends BaseInspection {
+
+ @SuppressWarnings({"PublicField"})
+ public boolean onlyWarnOnRootExceptions = false;
+
+ @SuppressWarnings({"PublicField", "UnusedDeclaration"})
+ public boolean ignoreInTestCode = false; // keep for compatibility
+
+ @SuppressWarnings("PublicField")
+ public boolean ignoreLibraryOverrides = false;
+
+ @SuppressWarnings("PublicField")
+ public boolean ignoreThrown = false;
+
+ @Override
+ @NotNull
+ public String getID() {
+ return "OverlyBroadThrowsClause";
+ }
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("overly.broad.throws.clause.display.name");
+ }
+
+ @Override
+ @NotNull
+ protected String buildErrorString(Object... infos) {
+ final List<SmartTypePointer> typesMasked = (List<SmartTypePointer>)infos[0];
+ final PsiType type = typesMasked.get(0).getType();
+ String typesMaskedString = type != null ? type.getPresentableText() : "";
+ if (typesMasked.size() == 1) {
+ return InspectionGadgetsBundle.message(
+ "overly.broad.throws.clause.problem.descriptor1",
+ typesMaskedString);
+ }
+ else {
+ final int lastTypeIndex = typesMasked.size() - 1;
+ for (int i = 1; i < lastTypeIndex; i++) {
+ final PsiType psiType = typesMasked.get(i).getType();
+ if (psiType != null) {
+ typesMaskedString += ", ";
+ typesMaskedString += psiType.getPresentableText();
+ }
+ }
+ final PsiType psiType = typesMasked.get(lastTypeIndex).getType();
+ final String lastTypeString = psiType != null ? psiType.getPresentableText() : "";
+ return InspectionGadgetsBundle.message("overly.broad.throws.clause.problem.descriptor2", typesMaskedString, lastTypeString);
+ }
+ }
+
+ @Override
+ public JComponent createOptionsPanel() {
+ final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
+ panel.addCheckbox(InspectionGadgetsBundle.message("too.broad.catch.option"), "onlyWarnOnRootExceptions");
+ panel.addCheckbox(InspectionGadgetsBundle.message("ignore.exceptions.declared.on.library.override.option"), "ignoreLibraryOverrides");
+ panel.addCheckbox(InspectionGadgetsBundle.message("overly.broad.throws.clause.ignore.thrown.option"), "ignoreThrown");
+ return panel;
+ }
+
+ @NotNull
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final Collection<SmartTypePointer> maskedExceptions = (Collection<SmartTypePointer>)infos[0];
+ final Boolean originalNeeded = (Boolean)infos[1];
+ return new AddThrowsClauseFix(maskedExceptions, originalNeeded.booleanValue());
+ }
+
+ private static class AddThrowsClauseFix extends InspectionGadgetsFix {
+
+ private final Collection<SmartTypePointer> types;
+ private final boolean originalNeeded;
+
+ AddThrowsClauseFix(Collection<SmartTypePointer> types, boolean originalNeeded) {
+ this.types = types;
+ this.originalNeeded = originalNeeded;
+ }
+
+ @Override
+ @NotNull
+ public String getName() {
+ if (originalNeeded) {
+ return InspectionGadgetsBundle.message("overly.broad.throws.clause.quickfix1");
+ }
+ else {
+ return InspectionGadgetsBundle.message("overly.broad.throws.clause.quickfix2");
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Fix 'throws' clause";
+ }
+
+ @Override
+ protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
+ final PsiElement element = descriptor.getPsiElement();
+ final PsiElement parent = element.getParent();
+ if (!(parent instanceof PsiReferenceList)) {
+ return;
+ }
+ final PsiReferenceList referenceList = (PsiReferenceList)parent;
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
+ if (!originalNeeded) {
+ element.delete();
+ }
+ for (SmartTypePointer type : types) {
+ final PsiType psiType = type.getType();
+ if (psiType instanceof PsiClassType) {
+ final PsiJavaCodeReferenceElement referenceElement = factory.createReferenceElementByType((PsiClassType)psiType);
+ referenceList.add(referenceElement);
+ }
+ }
+ }
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new TooBroadThrowsVisitor();
+ }
+
+ private class TooBroadThrowsVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethod(PsiMethod method) {
+ super.visitMethod(method);
+ final PsiReferenceList throwsList = method.getThrowsList();
+ if (!throwsList.isPhysical()) {
+ return;
+ }
+ final PsiJavaCodeReferenceElement[] throwsReferences = throwsList.getReferenceElements();
+ if (throwsReferences.length == 0) {
+ return;
+ }
+ final PsiCodeBlock body = method.getBody();
+ if (body == null) {
+ return;
+ }
+ if (ignoreLibraryOverrides && LibraryUtil.isOverrideOfLibraryMethod(method)) {
+ return;
+ }
+ final Set<PsiClassType> exceptionsThrown = ExceptionUtils.calculateExceptionsThrown(body);
+ final PsiClassType[] referencedExceptions = throwsList.getReferencedTypes();
+ final Set<PsiClassType> exceptionsDeclared = new HashSet(referencedExceptions.length);
+ ContainerUtil.addAll(exceptionsDeclared, referencedExceptions);
+ final int referencedExceptionsLength = referencedExceptions.length;
+ for (int i = 0; i < referencedExceptionsLength; i++) {
+ final PsiClassType referencedException = referencedExceptions[i];
+ if (onlyWarnOnRootExceptions) {
+ if (!ExceptionUtils.isGenericExceptionClass(
+ referencedException)) {
+ continue;
+ }
+ }
+ final List<SmartTypePointer> exceptionsMasked = new ArrayList();
+ final SmartTypePointerManager pointerManager = SmartTypePointerManager.getInstance(body.getProject());
+ for (PsiClassType exceptionThrown : exceptionsThrown) {
+ if (referencedException.isAssignableFrom(exceptionThrown) && !exceptionsDeclared.contains(exceptionThrown)) {
+ exceptionsMasked.add(pointerManager.createSmartTypePointer(exceptionThrown));
+ }
+ }
+ if (!exceptionsMasked.isEmpty()) {
+ final PsiJavaCodeReferenceElement throwsReference = throwsReferences[i];
+ final boolean originalNeeded = exceptionsThrown.contains(referencedException);
+ if (ignoreThrown && originalNeeded) {
+ continue;
+ }
+ registerError(throwsReference, exceptionsMasked, Boolean.valueOf(originalNeeded), throwsReference);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspectionBase.java
index 5c23349..bb30d1d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspectionBase.java
@@ -35,7 +35,7 @@
/**
* @noinspection PublicField
*/
- public boolean m_ignoreTestCases = false;
+ public boolean m_ignoreTestCases = false; // keep for compatibility
@Override
@NotNull
@@ -51,9 +51,6 @@
optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
"unused.catch.parameter.ignore.catch.option"),
"m_ignoreCatchBlocksWithComments");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message(
- "unused.catch.parameter.ignore.empty.option"),
- "m_ignoreTestCases");
return optionsPanel;
}
@@ -62,12 +59,9 @@
protected String buildErrorString(Object... infos) {
final boolean namedIgnoreButUsed = ((Boolean)infos[0]).booleanValue();
if (namedIgnoreButUsed) {
- return InspectionGadgetsBundle.message(
- "used.catch.parameter.named.ignore.problem.descriptor"
- );
+ return InspectionGadgetsBundle.message("used.catch.parameter.named.ignore.problem.descriptor");
}
- return InspectionGadgetsBundle.message(
- "unused.catch.parameter.problem.descriptor");
+ return InspectionGadgetsBundle.message("unused.catch.parameter.problem.descriptor");
}
@Override
@@ -113,14 +107,14 @@
final boolean namedIgnore = PsiUtil.isIgnoredName(parameterName);
if (visitor.isUsed()) {
if (namedIgnore) {
- registerVariableError(parameter, Boolean.TRUE);
+ registerVariableError(parameter, Boolean.TRUE, parameter);
}
return;
}
else if (namedIgnore) {
return;
}
- registerVariableError(parameter, Boolean.FALSE);
+ registerVariableError(parameter, Boolean.FALSE, parameter);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java
index b649973..a1f9538 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/AddThisQualifierFix.java
@@ -25,6 +25,7 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -75,6 +76,6 @@
}
newExpression = containingClass.getQualifiedName() + ".this." + expression.getText();
}
- replaceExpressionAndShorten(expression, newExpression);
+ PsiReplacementUtil.replaceExpressionAndShorten(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java
index d76a992..deb46ec 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/DeleteUnnecessaryStatementFix.java
@@ -22,6 +22,7 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -61,7 +62,7 @@
parent instanceof PsiDoWhileStatement ||
parent instanceof PsiForeachStatement ||
parent instanceof PsiForStatement) {
- replaceStatement(statement, "{}");
+ PsiReplacementUtil.replaceStatement(statement, "{}");
}
else {
deleteElement(statement);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java
index 7ab4204..ca19cda 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/fixes/EqualityToEqualsFix.java
@@ -25,6 +25,7 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -86,6 +87,6 @@
else {
newExpression = expString;
}
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/StaticImportInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/StaticImportInspectionBase.java
index 0a1182c..db4e8f1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/StaticImportInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/imports/StaticImportInspectionBase.java
@@ -29,7 +29,6 @@
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.StringUtils;
-import com.siyeh.ig.psiutils.TestUtils;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -40,7 +39,8 @@
public class StaticImportInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"}) public boolean ignoreSingleFieldImports = false;
@SuppressWarnings({"PublicField"}) public boolean ignoreSingeMethodImports = false;
- @SuppressWarnings("PublicField") public boolean ignoreInTestCode = false;
+ @SuppressWarnings({"PublicField", "UnusedDeclaration"})
+ public boolean ignoreInTestCode = false; // keep for compatibility
@SuppressWarnings("PublicField") public OrderedSet<String> allowedClasses = new OrderedSet<String>();
@Override
@@ -255,13 +255,10 @@
if (importList == null) {
return;
}
- if (ignoreInTestCode && TestUtils.isTest(aClass)) {
- return;
- }
final PsiImportStaticStatement[] importStatements = importList.getImportStaticStatements();
for (PsiImportStaticStatement importStatement : importStatements) {
if (shouldReportImportStatement(importStatement)) {
- registerError(importStatement);
+ registerError(importStatement, importStatement);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionBase.java
index 5a9f275..158dfea 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionBase.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,12 +15,12 @@
*/
package com.siyeh.ig.inheritance;
-import com.intellij.psi.PsiAnonymousClass;
-import com.intellij.psi.PsiClass;
+import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.CollectionUtils;
+import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NotNull;
public class ExtendsConcreteCollectionInspectionBase extends BaseInspection {
@@ -62,11 +62,26 @@
return;
}
final PsiClass superClass = aClass.getSuperClass();
- if (superClass == null) {
+ if (!CollectionUtils.isConcreteCollectionClass(superClass)) {
return;
}
- if (!CollectionUtils.isCollectionClass(superClass)) {
- return;
+ final String qualifiedName = superClass.getQualifiedName();
+ if ("java.util.LinkedHashMap".equals(qualifiedName)) {
+ final PsiMethod[] methods = aClass.findMethodsByName("removeEldestEntry", false);
+ final PsiClassType entryType = TypeUtils.getType("java.util.Map.Entry", aClass);
+ for (PsiMethod method : methods) {
+ if (!PsiType.BOOLEAN.equals(method.getReturnType())) {
+ continue;
+ }
+ final PsiParameterList parameterList = method.getParameterList();
+ if ( parameterList.getParametersCount() != 1) {
+ continue;
+ }
+ final PsiParameter parameter = parameterList.getParameters()[0];
+ if (entryType.isAssignableFrom(parameter.getType())) {
+ return;
+ }
+ }
}
registerClassError(aClass, superClass, aClass);
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/MissingOverrideAnnotationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/MissingOverrideAnnotationInspection.java
new file mode 100644
index 0000000..fff5d2c
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/MissingOverrideAnnotationInspection.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.inheritance;
+
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.SmartList;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.MethodUtils;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class MissingOverrideAnnotationInspection extends BaseInspection {
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreObjectMethods = true;
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreAnonymousClassMethods = false;
+
+ @Override
+ @NotNull
+ public String getID() {
+ return "override";
+ }
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message(
+ "missing.override.annotation.display.name");
+ }
+
+ @Override
+ @NotNull
+ protected String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message(
+ "missing.override.annotation.problem.descriptor");
+ }
+
+ @Override
+ public JComponent createOptionsPanel() {
+ final MultipleCheckboxOptionsPanel panel =
+ new MultipleCheckboxOptionsPanel(this);
+ panel.addCheckbox(InspectionGadgetsBundle.message(
+ "ignore.equals.hashcode.and.tostring"), "ignoreObjectMethods");
+ panel.addCheckbox(InspectionGadgetsBundle.message(
+ "ignore.methods.in.anonymous.classes"),
+ "ignoreAnonymousClassMethods");
+ return panel;
+ }
+
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ return new MissingOverrideAnnotationFix();
+ }
+
+ private static class MissingOverrideAnnotationFix
+ extends InspectionGadgetsFix {
+
+ @Override
+ @NotNull
+ public String getName() {
+ return InspectionGadgetsBundle.message(
+ "missing.override.annotation.add.quickfix");
+ }
+ @Override
+ @NotNull
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ public void doFix(Project project, ProblemDescriptor descriptor)
+ throws IncorrectOperationException {
+ final PsiElement identifier = descriptor.getPsiElement();
+ final PsiElement parent = identifier.getParent();
+ if (!(parent instanceof PsiModifierListOwner)) {
+ return;
+ }
+ final PsiModifierListOwner modifierListOwner =
+ (PsiModifierListOwner)parent;
+ final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
+ final PsiElementFactory factory = psiFacade.getElementFactory();
+ final PsiAnnotation annotation =
+ factory.createAnnotationFromText("@java.lang.Override",
+ modifierListOwner);
+ final PsiModifierList modifierList =
+ modifierListOwner.getModifierList();
+ if (modifierList == null) {
+ return;
+ }
+ modifierList.addAfter(annotation, null);
+ }
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new MissingOverrideAnnotationVisitor();
+ }
+
+ private class MissingOverrideAnnotationVisitor
+ extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethod(@NotNull PsiMethod method) {
+ if (!PsiUtil.isLanguageLevel5OrHigher(method)) {
+ return;
+ }
+ if (method.getNameIdentifier() == null) {
+ return;
+ }
+ if (method.isConstructor()) {
+ return;
+ }
+ if (method.hasModifierProperty(PsiModifier.PRIVATE) ||
+ method.hasModifierProperty(PsiModifier.STATIC)) {
+ return;
+ }
+ final PsiClass methodClass = method.getContainingClass();
+ if (methodClass == null) {
+ return;
+ }
+ if (ignoreAnonymousClassMethods &&
+ methodClass instanceof PsiAnonymousClass) {
+ return;
+ }
+ final boolean useJdk6Rules =
+ PsiUtil.isLanguageLevel6OrHigher(method);
+ if (useJdk6Rules) {
+ if (!isJdk6Override(method, methodClass)) {
+ return;
+ }
+ }
+ else if (!isJdk5Override(method, methodClass)) {
+ return;
+ }
+ if (ignoreObjectMethods && (MethodUtils.isHashCode(method) ||
+ MethodUtils.isEquals(method) ||
+ MethodUtils.isToString(method))) {
+ return;
+ }
+ if (hasOverrideAnnotation(method)) {
+ return;
+ }
+ registerMethodError(method);
+ }
+
+ private boolean hasOverrideAnnotation(
+ PsiModifierListOwner element) {
+ final PsiModifierList modifierList = element.getModifierList();
+ if (modifierList == null) {
+ return false;
+ }
+ final PsiAnnotation annotation =
+ modifierList.findAnnotation("java.lang.Override");
+ return annotation != null;
+ }
+
+ private boolean isJdk6Override(PsiMethod method, PsiClass methodClass) {
+ final PsiMethod[] superMethods =
+ getSuperMethodsInJavaSense(method, methodClass);
+ if (superMethods.length <= 0) {
+ return false;
+ }
+ // is override except if this is an interface method
+ // overriding a protected method in java.lang.Object
+ // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6501053
+ if (!methodClass.isInterface()) {
+ return true;
+ }
+ for (PsiMethod superMethod : superMethods) {
+ if (!superMethod.hasModifierProperty(PsiModifier.PROTECTED)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isJdk5Override(PsiMethod method, PsiClass methodClass) {
+ final PsiMethod[] superMethods =
+ getSuperMethodsInJavaSense(method, methodClass);
+ for (PsiMethod superMethod : superMethods) {
+ final PsiClass superClass = superMethod.getContainingClass();
+ if (superClass == null) {
+ continue;
+ }
+ if (superClass.isInterface()) {
+ continue;
+ }
+ if (methodClass.isInterface() &&
+ superMethod.hasModifierProperty(PsiModifier.PROTECTED)) {
+ // only true for J2SE java.lang.Object.clone(), but might
+ // be different on other/newer java platforms
+ continue;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private PsiMethod[] getSuperMethodsInJavaSense(
+ @NotNull PsiMethod method, @NotNull PsiClass methodClass) {
+ final PsiMethod[] superMethods = method.findSuperMethods();
+ final List<PsiMethod> toExclude = new SmartList<PsiMethod>();
+ for (PsiMethod superMethod : superMethods) {
+ final PsiClass superClass = superMethod.getContainingClass();
+ if (!InheritanceUtil.isInheritorOrSelf(methodClass, superClass,
+ true)) {
+ toExclude.add(superMethod);
+ }
+ }
+ if (!toExclude.isEmpty()) {
+ final List<PsiMethod> result =
+ new ArrayList<PsiMethod>(Arrays.asList(superMethods));
+ result.removeAll(toExclude);
+ return result.toArray(new PsiMethod[result.size()]);
+ }
+ return superMethods;
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspection.java
index bf121ff..c9605e7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspection.java
@@ -66,7 +66,7 @@
}
final PsiParameter parameter = parameters[parameters.length - 1];
final PsiType type = parameter.getType();
- if (!(type instanceof PsiArrayType)) {
+ if (!(type instanceof PsiArrayType) || type instanceof PsiEllipsisType) {
return;
}
final PsiMethod[] superMethods = method.findDeepestSuperMethods();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java
index 46ef38b..9694d34 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/inheritance/RedundantMethodOverrideInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2005-2007 Bas Leijdekkers
+ * Copyright 2005-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.
@@ -30,6 +30,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.util.*;
+
public class RedundantMethodOverrideInspection extends BaseInspection {
@Override
@@ -107,19 +109,11 @@
if (superBody == null) {
return;
}
- final PsiModifierList superModifierList =
- superMethod.getModifierList();
- final PsiModifierList modifierList = method.getModifierList();
- if (!EquivalenceChecker.modifierListsAreEquivalent(
- modifierList, superModifierList)) {
+ if (!modifierListsAreEquivalent(method.getModifierList(), superMethod.getModifierList())) {
return;
}
final PsiType superReturnType = superMethod.getReturnType();
- if (superReturnType == null) {
- return;
- }
- final PsiType returnType = method.getReturnType();
- if (!superReturnType.equals(returnType)) {
+ if (superReturnType == null || !superReturnType.equals(method.getReturnType())) {
return;
}
if (!EquivalenceChecker.codeBlocksAreEquivalent(body, superBody)) {
@@ -127,5 +121,46 @@
}
registerMethodError(method);
}
+
+ private static boolean modifierListsAreEquivalent(@Nullable PsiModifierList list1, @Nullable PsiModifierList list2) {
+ if (list1 == null) {
+ return list2 == null;
+ }
+ else if (list2 == null) {
+ return false;
+ }
+ final Set<String> annotations1 = new HashSet();
+ for (PsiAnnotation annotation : list1.getAnnotations()) {
+ annotations1.add(annotation.getQualifiedName());
+ }
+ final Set<String> annotations2 = new HashSet();
+ for (PsiAnnotation annotation : list2.getAnnotations()) {
+ annotations2.add(annotation.getQualifiedName());
+ }
+ final Set<String> uniques = disjunction(annotations1, annotations2);
+ uniques.remove(CommonClassNames.JAVA_LANG_OVERRIDE);
+ if (!uniques.isEmpty()) {
+ return false;
+ }
+ return list1.hasModifierProperty(PsiModifier.STRICTFP) == list2.hasModifierProperty(PsiModifier.STRICTFP) &&
+ list1.hasModifierProperty(PsiModifier.SYNCHRONIZED) == list2.hasModifierProperty(PsiModifier.SYNCHRONIZED) &&
+ list1.hasModifierProperty(PsiModifier.PUBLIC) == list2.hasModifierProperty(PsiModifier.PUBLIC) &&
+ list1.hasModifierProperty(PsiModifier.PROTECTED) == list2.hasModifierProperty(PsiModifier.PROTECTED);
+ }
+
+ private static <T> Set<T> disjunction(Collection<T> set1, Collection<T> set2) {
+ final Set<T> result = new HashSet();
+ for (T t : set1) {
+ if (!set2.contains(t)) {
+ result.add(t);
+ }
+ }
+ for (T t : set2) {
+ if (!set1.contains(t)) {
+ result.add(t);
+ }
+ }
+ return result;
+ }
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspection.java
index 9042da9..3ac8a08 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -22,6 +22,7 @@
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.CloneUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.MethodUtils;
import org.jetbrains.annotations.NotNull;
@@ -75,6 +76,12 @@
if (!MethodUtils.isOverriddenInHierarchy(calledMethod, containingClass)) {
return;
}
+ if (CloneUtils.isClone(calledMethod)) {
+ final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expression, PsiMethod.class);
+ if (CloneUtils.isClone(containingMethod)) {
+ return;
+ }
+ }
registerMethodCallError(expression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java
index 9340ff4..662ae31 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/AbsoluteAlignmentInUserInterfaceInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -115,7 +116,7 @@
return;
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)parent;
- replaceExpression(referenceExpression, myClassName + '.' + myReplacement);
+ PsiReplacementUtil.replaceExpression(referenceExpression, myClassName + '.' + myReplacement);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java
new file mode 100644
index 0000000..a2a3b12
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspection.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.internationalization;
+
+import com.intellij.psi.*;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ImplicitDefaultCharsetUsageInspection extends BaseInspection {
+
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("implicit.default.charset.usage.display.name");
+ }
+
+ @NotNull
+ @Override
+ protected String buildErrorString(Object... infos) {
+ if (infos[0] instanceof PsiNewExpression) {
+ return InspectionGadgetsBundle.message("implicit.default.charset.usage.constructor.problem.descriptor");
+ }
+ else {
+ return InspectionGadgetsBundle.message("implicit.default.charset.usage.problem.descriptor");
+ }
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new ImplicitDefaultCharsetUsageVisitor();
+ }
+
+ private static class ImplicitDefaultCharsetUsageVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ @NonNls final String name = methodExpression.getReferenceName();
+ if (!"getBytes".equals(name)) {
+ return;
+ }
+ final PsiMethod method = expression.resolveMethod();
+ if (method == null) {
+ return;
+ }
+ final PsiParameterList parameterList = method.getParameterList();
+ if (parameterList.getParametersCount() == 1) {
+ return;
+ }
+ final PsiClass aClass = method.getContainingClass();
+ if (aClass == null) {
+ return;
+ }
+ final String qName = aClass.getQualifiedName();
+ if (!CommonClassNames.JAVA_LANG_STRING.equals(qName)) {
+ return;
+ }
+ registerMethodCallError(expression, expression);
+ }
+
+ @Override
+ public void visitNewExpression(PsiNewExpression expression) {
+ super.visitNewExpression(expression);
+ final PsiMethod constructor = expression.resolveConstructor();
+ if (constructor == null) {
+ return;
+ }
+ final PsiClass aClass = constructor.getContainingClass();
+ if (aClass == null) {
+ return;
+ }
+ final PsiParameterList parameterList = constructor.getParameterList();
+ final int count = parameterList.getParametersCount();
+ if (count == 0) {
+ return;
+ }
+ final PsiParameter[] parameters = parameterList.getParameters();
+ final String qName = aClass.getQualifiedName();
+ if (CommonClassNames.JAVA_LANG_STRING.equals(qName)) {
+ if (!parameters[0].getType().equalsToText("byte[]") || hasCharsetType(parameters[count - 1])) {
+ return;
+ }
+ }
+ else if ("java.io.InputStreamReader".equals(qName) ||
+ "java.io.OutputStreamWriter".equals(qName) ||
+ "java.io.PrintStream".equals(qName)) {
+ if (hasCharsetType(parameters[count - 1])) {
+ return;
+ }
+ }
+ else if ("java.io.PrintWriter".equals(qName)) {
+ if (count > 1 && hasCharsetType(parameters[count - 1]) || parameters[0].getType().equalsToText("java.io.Writer")) {
+ return;
+ }
+ }
+ else if ("java.util.Formatter".equals(qName)) {
+ if (count > 1 && hasCharsetType(parameters[1])) {
+ return;
+ }
+ final PsiType firstType = parameters[0].getType();
+ if (!firstType.equalsToText(CommonClassNames.JAVA_LANG_STRING) && !firstType.equalsToText("java.io.File") &&
+ !firstType.equalsToText("java.io.OutputStream")) {
+ return;
+ }
+ }
+ else if ("java.util.Scanner".equals(qName)) {
+ if (count > 1 && hasCharsetType(parameters[1])) {
+ return;
+ }
+ final PsiType firstType = parameters[0].getType();
+ if (!firstType.equalsToText("java.io.InputStream") && !firstType.equalsToText("java.io.File") &&
+ !firstType.equalsToText("java.nio.file.Path") && !firstType.equalsToText("java.nio.channels.ReadableByteChannel")) {
+ return;
+ }
+ }
+ else if (!"java.io.FileReader".equals(qName) && !"java.io.FileWriter".equals(qName)) {
+ return;
+ }
+ registerNewExpressionError(expression, expression);
+
+ }
+
+ private static boolean hasCharsetType(PsiVariable variable) {
+ final PsiType lastType = variable.getType();
+ return lastType.equalsToText(CommonClassNames.JAVA_LANG_STRING) ||
+ lastType.equalsToText("java.nio.charset.Charset");
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.java
index ca5ef59..abb2ae4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspection.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.
@@ -61,7 +61,7 @@
return;
}
}
- registerError(expression);
+ registerNewExpressionError(expression);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java
deleted file mode 100644
index 74eb33c..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java
+++ /dev/null
@@ -1,259 +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.ig.internationalization;
-
-import com.intellij.codeInsight.AnnotationUtil;
-import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
-import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.refactoring.util.RefactoringChangeUtil;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.DelegatingFix;
-import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.ExpressionUtils;
-import com.siyeh.ig.psiutils.MethodUtils;
-import com.siyeh.ig.psiutils.TestUtils;
-import com.siyeh.ig.psiutils.TypeUtils;
-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.Collection;
-
-public class StringConcatenationInspection extends BaseInspection {
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreAsserts = false;
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreSystemOuts = false;
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreSystemErrs = false;
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreThrowableArguments = false;
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreConstantInitializers = false;
-
- @SuppressWarnings({"PublicField"})
- public boolean ignoreInTestCode = false;
-
- @SuppressWarnings("PublicField")
- public boolean ignoreInToString = false;
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("string.concatenation.display.name");
- }
-
- @Override
- @NotNull
- public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message("string.concatenation.problem.descriptor");
- }
-
- @Override
- @NotNull
- protected InspectionGadgetsFix[] buildFixes(Object... infos) {
- final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)infos[0];
- final Collection<InspectionGadgetsFix> result = new ArrayList();
- final PsiElement parent = polyadicExpression.getParent();
- if (parent instanceof PsiVariable) {
- final PsiVariable variable = (PsiVariable)parent;
- final InspectionGadgetsFix fix = createAddAnnotationFix(variable);
- result.add(fix);
- }
- else if (parent instanceof PsiAssignmentExpression) {
- final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
- final PsiExpression lhs = assignmentExpression.getLExpression();
- if (lhs instanceof PsiReferenceExpression) {
- final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
- final PsiElement target = referenceExpression.resolve();
- if (target instanceof PsiModifierListOwner) {
- final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target;
- final InspectionGadgetsFix fix = createAddAnnotationFix(modifierListOwner);
- result.add(fix);
- }
- }
- }
- final PsiExpression[] operands = polyadicExpression.getOperands();
- for (PsiExpression operand : operands) {
- final PsiModifierListOwner element1 = getAnnotatableElement(operand);
- if (element1 != null) {
- final InspectionGadgetsFix fix = createAddAnnotationFix(element1);
- result.add(fix);
- }
- }
- final PsiElement expressionParent = PsiTreeUtil.getParentOfType(polyadicExpression, PsiReturnStatement.class, PsiExpressionList.class);
- if (!(expressionParent instanceof PsiExpressionList) && expressionParent != null) {
- final PsiMethod method = PsiTreeUtil.getParentOfType(expressionParent, PsiMethod.class);
- if (method != null) {
- final InspectionGadgetsFix fix = createAddAnnotationFix(method);
- result.add(fix);
- }
- }
- return result.toArray(new InspectionGadgetsFix[result.size()]);
- }
-
- private static DelegatingFix createAddAnnotationFix(PsiModifierListOwner variable) {
- return new DelegatingFix(new AddAnnotationPsiFix(AnnotationUtil.NON_NLS, variable,PsiNameValuePair.EMPTY_ARRAY));
- }
-
- @Nullable
- public static PsiModifierListOwner getAnnotatableElement(PsiExpression expression) {
- if (!(expression instanceof PsiReferenceExpression)) {
- return null;
- }
- final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
- final PsiElement element = referenceExpression.resolve();
- if (!(element instanceof PsiModifierListOwner)) {
- return null;
- }
- return (PsiModifierListOwner)element;
- }
-
- @Override
- @Nullable
- public JComponent createOptionsPanel() {
- final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.assert.option"), "ignoreAsserts");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.system.out.option"), "ignoreSystemOuts");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.system.err.option"), "ignoreSystemErrs");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.exceptions.option"), "ignoreThrowableArguments");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.constant.initializers.option"),
- "ignoreConstantInitializers");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.test.code"), "ignoreInTestCode");
- optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.tostring"), "ignoreInToString");
- return optionsPanel;
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new StringConcatenationVisitor();
- }
-
- private class StringConcatenationVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) {
- super.visitPolyadicExpression(expression);
- final IElementType tokenType = expression.getOperationTokenType();
- if (!JavaTokenType.PLUS.equals(tokenType)) {
- return;
- }
- final PsiType type = expression.getType();
- if (!TypeUtils.isJavaLangString(type)) {
- return;
- }
- final PsiExpression[] operands = expression.getOperands();
- for (PsiExpression operand : operands) {
- if (NonNlsUtils.isNonNlsAnnotated(operand)) {
- return;
- }
- }
- if (AnnotationUtil.isInsideAnnotation(expression)) {
- return;
- }
- if (ignoreInTestCode && TestUtils.isInTestCode(expression)) {
- return;
- }
- if (ignoreAsserts) {
- final PsiAssertStatement assertStatement =
- PsiTreeUtil.getParentOfType(expression, PsiAssertStatement.class, true, PsiCodeBlock.class, PsiClass.class);
- if (assertStatement != null) {
- return;
- }
- }
- if (ignoreSystemErrs || ignoreSystemOuts) {
- final PsiMethodCallExpression methodCallExpression =
- PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class, PsiClass.class);
- if (methodCallExpression != null) {
- final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
- @NonNls
- final String canonicalText = methodExpression.getCanonicalText();
- if (ignoreSystemOuts && "System.out.println".equals(canonicalText) || "System.out.print".equals(canonicalText)) {
- return;
- }
- if (ignoreSystemErrs && "System.err.println".equals(canonicalText) || "System.err.print".equals(canonicalText)) {
- return;
- }
- }
- }
- if (ignoreThrowableArguments) {
- final PsiNewExpression newExpression =
- PsiTreeUtil.getParentOfType(expression, PsiNewExpression.class, true, PsiCodeBlock.class, PsiClass.class);
- if (newExpression != null) {
- final PsiType newExpressionType = newExpression.getType();
- if (InheritanceUtil.isInheritor(newExpressionType, "java.lang.Throwable")) {
- return;
- }
- } else {
- final PsiMethodCallExpression methodCallExpression =
- PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class, PsiClass.class);
- if (RefactoringChangeUtil.isSuperOrThisMethodCall(methodCallExpression)) {
- return;
- }
- }
- }
- if (ignoreConstantInitializers) {
- PsiElement parent = expression.getParent();
- while (parent instanceof PsiBinaryExpression) {
- parent = parent.getParent();
- }
- if (parent instanceof PsiField) {
- final PsiField field = (PsiField)parent;
- if (field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL)) {
- return;
- }
- final PsiClass containingClass = field.getContainingClass();
- if (containingClass != null && containingClass.isInterface()) {
- return;
- }
- }
- }
- if (ignoreInToString) {
- final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class);
- if (MethodUtils.isToString(method)) {
- return;
- }
- }
- if (NonNlsUtils.isNonNlsAnnotatedUse(expression)) {
- return;
- }
- for (int i = 1; i < operands.length; i++) {
- final PsiExpression operand = operands[i];
- if (!ExpressionUtils.isStringConcatenationOperand(operand)) {
- continue;
- }
- final PsiJavaToken token = expression.getTokenBeforeOperand(operand);
- if (token == null) {
- continue;
- }
- registerError(token, expression);
- }
- }
- }
-}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/StringConcatenationInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/StringConcatenationInspectionBase.java
new file mode 100644
index 0000000..df3b8dc
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/internationalization/StringConcatenationInspectionBase.java
@@ -0,0 +1,253 @@
+/*
+ * 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.ig.internationalization;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.codeInsight.intention.AddAnnotationPsiFix;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.refactoring.util.RefactoringChangeUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.DelegatingFix;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.ExpressionUtils;
+import com.siyeh.ig.psiutils.MethodUtils;
+import com.siyeh.ig.psiutils.TypeUtils;
+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.Collection;
+
+public class StringConcatenationInspectionBase extends BaseInspection {
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreAsserts = false;
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreSystemOuts = false;
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreSystemErrs = false;
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreThrowableArguments = false;
+
+ @SuppressWarnings({"PublicField"})
+ public boolean ignoreConstantInitializers = false;
+
+ @SuppressWarnings({"PublicField", "UnusedDeclaration"})
+ public boolean ignoreInTestCode = false; // keep for compatibility
+
+ @SuppressWarnings("PublicField")
+ public boolean ignoreInToString = false;
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("string.concatenation.display.name");
+ }
+
+ @Override
+ @NotNull
+ public String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("string.concatenation.problem.descriptor");
+ }
+
+ @Override
+ @NotNull
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)infos[0];
+ final Collection<InspectionGadgetsFix> result = new ArrayList();
+ final PsiElement parent = polyadicExpression.getParent();
+ if (parent instanceof PsiVariable) {
+ final PsiVariable variable = (PsiVariable)parent;
+ final InspectionGadgetsFix fix = createAddAnnotationFix(variable);
+ result.add(fix);
+ }
+ else if (parent instanceof PsiAssignmentExpression) {
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)parent;
+ final PsiExpression lhs = assignmentExpression.getLExpression();
+ if (lhs instanceof PsiReferenceExpression) {
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)lhs;
+ final PsiElement target = referenceExpression.resolve();
+ if (target instanceof PsiModifierListOwner) {
+ final PsiModifierListOwner modifierListOwner = (PsiModifierListOwner)target;
+ final InspectionGadgetsFix fix = createAddAnnotationFix(modifierListOwner);
+ result.add(fix);
+ }
+ }
+ }
+ final PsiExpression[] operands = polyadicExpression.getOperands();
+ for (PsiExpression operand : operands) {
+ final PsiModifierListOwner element1 = getAnnotatableElement(operand);
+ if (element1 != null) {
+ final InspectionGadgetsFix fix = createAddAnnotationFix(element1);
+ result.add(fix);
+ }
+ }
+ final PsiElement expressionParent = PsiTreeUtil.getParentOfType(polyadicExpression, PsiReturnStatement.class, PsiExpressionList.class);
+ if (!(expressionParent instanceof PsiExpressionList) && expressionParent != null) {
+ final PsiMethod method = PsiTreeUtil.getParentOfType(expressionParent, PsiMethod.class);
+ if (method != null) {
+ final InspectionGadgetsFix fix = createAddAnnotationFix(method);
+ result.add(fix);
+ }
+ }
+ return result.toArray(new InspectionGadgetsFix[result.size()]);
+ }
+
+ private static DelegatingFix createAddAnnotationFix(PsiModifierListOwner variable) {
+ return new DelegatingFix(new AddAnnotationPsiFix(AnnotationUtil.NON_NLS, variable,PsiNameValuePair.EMPTY_ARRAY));
+ }
+
+ @Nullable
+ public static PsiModifierListOwner getAnnotatableElement(PsiExpression expression) {
+ if (!(expression instanceof PsiReferenceExpression)) {
+ return null;
+ }
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
+ final PsiElement element = referenceExpression.resolve();
+ if (!(element instanceof PsiModifierListOwner)) {
+ return null;
+ }
+ return (PsiModifierListOwner)element;
+ }
+
+ @Override
+ @Nullable
+ public JComponent createOptionsPanel() {
+ final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.assert.option"), "ignoreAsserts");
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.system.out.option"), "ignoreSystemOuts");
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.system.err.option"), "ignoreSystemErrs");
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.exceptions.option"), "ignoreThrowableArguments");
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("string.concatenation.ignore.constant.initializers.option"), "ignoreConstantInitializers");
+ optionsPanel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.tostring"), "ignoreInToString");
+ return optionsPanel;
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new StringConcatenationVisitor();
+ }
+
+ private class StringConcatenationVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitPolyadicExpression(@NotNull PsiPolyadicExpression expression) {
+ super.visitPolyadicExpression(expression);
+ final IElementType tokenType = expression.getOperationTokenType();
+ if (!JavaTokenType.PLUS.equals(tokenType)) {
+ return;
+ }
+ final PsiType type = expression.getType();
+ if (!TypeUtils.isJavaLangString(type)) {
+ return;
+ }
+ final PsiExpression[] operands = expression.getOperands();
+ for (PsiExpression operand : operands) {
+ if (NonNlsUtils.isNonNlsAnnotated(operand)) {
+ return;
+ }
+ }
+ if (AnnotationUtil.isInsideAnnotation(expression)) {
+ return;
+ }
+ if (ignoreAsserts) {
+ final PsiAssertStatement assertStatement =
+ PsiTreeUtil.getParentOfType(expression, PsiAssertStatement.class, true, PsiCodeBlock.class, PsiClass.class);
+ if (assertStatement != null) {
+ return;
+ }
+ }
+ if (ignoreSystemErrs || ignoreSystemOuts) {
+ final PsiMethodCallExpression methodCallExpression =
+ PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class, PsiClass.class);
+ if (methodCallExpression != null) {
+ final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
+ @NonNls
+ final String canonicalText = methodExpression.getCanonicalText();
+ if (ignoreSystemOuts && "System.out.println".equals(canonicalText) || "System.out.print".equals(canonicalText)) {
+ return;
+ }
+ if (ignoreSystemErrs && "System.err.println".equals(canonicalText) || "System.err.print".equals(canonicalText)) {
+ return;
+ }
+ }
+ }
+ if (ignoreThrowableArguments) {
+ final PsiNewExpression newExpression =
+ PsiTreeUtil.getParentOfType(expression, PsiNewExpression.class, true, PsiCodeBlock.class, PsiClass.class);
+ if (newExpression != null) {
+ final PsiType newExpressionType = newExpression.getType();
+ if (InheritanceUtil.isInheritor(newExpressionType, "java.lang.Throwable")) {
+ return;
+ }
+ } else {
+ final PsiMethodCallExpression methodCallExpression =
+ PsiTreeUtil.getParentOfType(expression, PsiMethodCallExpression.class, true, PsiCodeBlock.class, PsiClass.class);
+ if (RefactoringChangeUtil.isSuperOrThisMethodCall(methodCallExpression)) {
+ return;
+ }
+ }
+ }
+ if (ignoreConstantInitializers) {
+ PsiElement parent = expression.getParent();
+ while (parent instanceof PsiBinaryExpression) {
+ parent = parent.getParent();
+ }
+ if (parent instanceof PsiField) {
+ final PsiField field = (PsiField)parent;
+ if (field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL)) {
+ return;
+ }
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass != null && containingClass.isInterface()) {
+ return;
+ }
+ }
+ }
+ if (ignoreInToString) {
+ final PsiMethod method = PsiTreeUtil.getParentOfType(expression, PsiMethod.class, true, PsiClass.class);
+ if (MethodUtils.isToString(method)) {
+ return;
+ }
+ }
+ if (NonNlsUtils.isNonNlsAnnotatedUse(expression)) {
+ return;
+ }
+ for (int i = 1; i < operands.length; i++) {
+ final PsiExpression operand = operands[i];
+ if (!ExpressionUtils.isStringConcatenationOperand(operand)) {
+ continue;
+ }
+ final PsiJavaToken token = expression.getTokenBeforeOperand(operand);
+ if (token == null) {
+ continue;
+ }
+ registerError(token, expression);
+ }
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java
index d25349c..217ece7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/MultiplyOrDivideByPowerOfTwoInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.WellFormednessUtils;
@@ -52,16 +53,13 @@
@Nullable
public JComponent createOptionsPanel() {
return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message(
- "multiply.or.divide.by.power.of.two.divide.option"), this,
- "checkDivision");
+ "multiply.or.divide.by.power.of.two.divide.option"), this, "checkDivision");
}
@Override
@NotNull
public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "expression.can.be.replaced.problem.descriptor",
- calculateReplacementShift((PsiExpression)infos[0]));
+ return InspectionGadgetsBundle.message("expression.can.be.replaced.problem.descriptor", calculateReplacementShift((PsiExpression)infos[0]));
}
static String calculateReplacementShift(PsiExpression expression) {
@@ -69,8 +67,7 @@
final PsiExpression rhs;
final String operator;
if (expression instanceof PsiAssignmentExpression) {
- final PsiAssignmentExpression exp =
- (PsiAssignmentExpression)expression;
+ final PsiAssignmentExpression exp = (PsiAssignmentExpression)expression;
lhs = exp.getLExpression();
rhs = exp.getRExpression();
final IElementType tokenType = exp.getOperationTokenType();
@@ -93,16 +90,17 @@
operator = ">>";
}
}
+
+ if (!(rhs instanceof PsiLiteralExpression)) return null;
+
final String lhsText;
- if (ParenthesesUtils.getPrecedence(lhs) >
- ParenthesesUtils.SHIFT_PRECEDENCE) {
+ if (ParenthesesUtils.getPrecedence(lhs) > ParenthesesUtils.SHIFT_PRECEDENCE) {
lhsText = '(' + lhs.getText() + ')';
}
else {
lhsText = lhs.getText();
}
- String expString =
- lhsText + operator + ShiftUtils.getLogBaseTwo(rhs);
+ String expString = lhsText + operator + ShiftUtils.getLogBaseTwo((PsiLiteralExpression)rhs);
final PsiElement parent = expression.getParent();
if (parent instanceof PsiExpression) {
if (!(parent instanceof PsiParenthesizedExpression) &&
@@ -118,19 +116,15 @@
public InspectionGadgetsFix buildFix(Object... infos) {
final PsiExpression expression = (PsiExpression)infos[0];
if (expression instanceof PsiBinaryExpression) {
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType operationTokenType =
- binaryExpression.getOperationTokenType();
+ final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
+ final IElementType operationTokenType = binaryExpression.getOperationTokenType();
if (JavaTokenType.DIV.equals(operationTokenType)) {
return null;
}
}
else if (expression instanceof PsiAssignmentExpression) {
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)expression;
- final IElementType operationTokenType =
- assignmentExpression.getOperationTokenType();
+ final PsiAssignmentExpression assignmentExpression = (PsiAssignmentExpression)expression;
+ final IElementType operationTokenType = assignmentExpression.getOperationTokenType();
if (JavaTokenType.DIVEQ.equals(operationTokenType)) {
return null;
}
@@ -155,10 +149,11 @@
@Override
public void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
- final PsiExpression expression =
- (PsiExpression)descriptor.getPsiElement();
+ final PsiExpression expression = (PsiExpression)descriptor.getPsiElement();
final String newExpression = calculateReplacementShift(expression);
- replaceExpression(expression, newExpression);
+ if (newExpression != null) {
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
+ }
}
}
@@ -170,8 +165,7 @@
private class ConstantShiftVisitor extends BaseInspectionVisitor {
@Override
- public void visitBinaryExpression(
- @NotNull PsiBinaryExpression expression) {
+ public void visitBinaryExpression(@NotNull PsiBinaryExpression expression) {
super.visitBinaryExpression(expression);
final PsiExpression rhs = expression.getROperand();
if (rhs == null) {
@@ -198,8 +192,7 @@
}
@Override
- public void visitAssignmentExpression(
- @NotNull PsiAssignmentExpression expression) {
+ public void visitAssignmentExpression(@NotNull PsiAssignmentExpression expression) {
super.visitAssignmentExpression(expression);
if (!WellFormednessUtils.isWellFormed(expression)) {
return;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
index a1952f0..5973c8b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -59,11 +59,6 @@
final PsiMember member = (PsiMember)infos[1];
@NonNls final String memberName;
if (member instanceof PsiMethod) {
- final PsiMethod method = (PsiMethod)member;
- if (method.isConstructor()) {
-
- }
-
memberName = member.getName() + "()";
}
else {
@@ -168,10 +163,10 @@
@Override
public BaseInspectionVisitor buildVisitor() {
- return new PrivateMemberAccessFromInnerClassVisior();
+ return new PrivateMemberAccessFromInnerClassVisitor();
}
- private static class PrivateMemberAccessFromInnerClassVisior
+ private static class PrivateMemberAccessFromInnerClassVisitor
extends BaseInspectionVisitor {
@Override
@@ -225,9 +220,6 @@
return;
}
super.visitReferenceExpression(expression);
- if (expression.getQualifierExpression() == null) {
- return;
- }
final PsiElement referenceNameElement =
expression.getReferenceNameElement();
if (referenceNameElement == null) {
@@ -246,12 +238,9 @@
if (!member.hasModifierProperty(PsiModifier.PRIVATE)) {
return;
}
- final PsiClass memberClass =
- ClassUtils.getContainingClass(member);
- if (memberClass == null) {
- return;
- }
- if (memberClass.equals(containingClass)) {
+ final PsiClass memberClass = ClassUtils.getContainingClass(member);
+ if (memberClass == null || memberClass.equals(containingClass) ||
+ (!PsiTreeUtil.isAncestor(containingClass, memberClass, true) && !PsiTreeUtil.isAncestor(memberClass, containingClass, true))) {
return;
}
registerError(referenceNameElement, memberClass, member);
@@ -259,14 +248,11 @@
@Nullable
private static PsiClass getContainingContextClass(PsiElement element) {
- final PsiClass aClass =
- ClassUtils.getContainingClass(element);
+ final PsiClass aClass = ClassUtils.getContainingClass(element);
if (aClass instanceof PsiAnonymousClass) {
- final PsiAnonymousClass anonymousClass =
- (PsiAnonymousClass)aClass;
- final PsiExpressionList args = anonymousClass.getArgumentList();
- if (args != null &&
- PsiTreeUtil.isAncestor(args, element, true)) {
+ final PsiAnonymousClass anonymousClass = (PsiAnonymousClass)aClass;
+ final PsiExpressionList arguments = anonymousClass.getArgumentList();
+ if (arguments != null && PsiTreeUtil.isAncestor(arguments, element, true)) {
return ClassUtils.getContainingClass(aClass);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/ShiftUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/ShiftUtils.java
index a4467e1..508298d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/ShiftUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/ShiftUtils.java
@@ -46,9 +46,8 @@
return intValue == 1;
}
- public static int getLogBaseTwo(PsiExpression rhs) {
- final PsiLiteralExpression literal = (PsiLiteralExpression)rhs;
- final Object value = literal.getValue();
+ public static int getLogBaseTwo(PsiLiteralExpression rhs) {
+ final Object value = rhs.getValue();
int log = 0;
if (value == null) {
return log;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java
index 83b3b5b..66ea855 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SimplifiableIfStatementInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -293,7 +294,7 @@
nextStatement.delete();
}
}
- replaceStatement(ifStatement, newStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, newStatement);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java
index c319ff3..9d8e3c5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -99,7 +100,7 @@
qualifierText + ".charAt(" + qualifierText +
".length() - 1) == '" + character + '\'';
}
- replaceExpression(methodCall, newExpression);
+ PsiReplacementUtil.replaceExpression(methodCall, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
index 292d106..5f9f588 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoBoxingInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -155,9 +156,9 @@
final PsiElement parent = expression.getParent();
if (parent instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)parent;
- replaceExpression(typeCastExpression, newExpression);
+ PsiReplacementUtil.replaceExpression(typeCastExpression, newExpression);
} else {
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java
index fa83ad8..5322dcb 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/AutoUnboxingInspection.java
@@ -31,6 +31,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import org.jetbrains.annotations.NonNls;
@@ -145,18 +146,18 @@
final String expressionText = expression.getText();
if (parent instanceof PsiTypeCastExpression) {
final PsiTypeCastExpression typeCastExpression = (PsiTypeCastExpression)parent;
- replaceExpression(typeCastExpression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(typeCastExpression, newExpressionText);
}
else if (parent instanceof PsiPrefixExpression && !unboxedType.equalsToText("boolean")) {
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)parent;
final IElementType tokenType = prefixExpression.getOperationTokenType();
if (JavaTokenType.PLUSPLUS.equals(tokenType)) {
- replaceExpression(prefixExpression, expressionText + '=' + newExpressionText + "+1");
+ PsiReplacementUtil.replaceExpression(prefixExpression, expressionText + '=' + newExpressionText + "+1");
}
else if (JavaTokenType.MINUSMINUS.equals(tokenType)) {
- replaceExpression(prefixExpression, expressionText + '=' + newExpressionText + "-1");
+ PsiReplacementUtil.replaceExpression(prefixExpression, expressionText + '=' + newExpressionText + "-1");
} else {
- replaceExpression(prefixExpression, prefixExpression.getOperationSign().getText() + newExpressionText);
+ PsiReplacementUtil.replaceExpression(prefixExpression, prefixExpression.getOperationSign().getText() + newExpressionText);
}
}
else if (parent instanceof PsiPostfixExpression) {
@@ -165,10 +166,10 @@
final PsiElement grandParent = postfixExpression.getParent();
if (grandParent instanceof PsiExpressionStatement) {
if (JavaTokenType.PLUSPLUS.equals(tokenType)) {
- replaceExpression(postfixExpression, expressionText + '=' + newExpressionText + "+1");
+ PsiReplacementUtil.replaceExpression(postfixExpression, expressionText + '=' + newExpressionText + "+1");
}
else if (JavaTokenType.MINUSMINUS.equals(tokenType)) {
- replaceExpression(postfixExpression, expressionText + '=' + newExpressionText + "-1");
+ PsiReplacementUtil.replaceExpression(postfixExpression, expressionText + '=' + newExpressionText + "-1");
}
}
else {
@@ -204,11 +205,11 @@
assignmentExpression.replace(newExpression);
}
else {
- replaceExpression(expression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(expression, newExpressionText);
}
}
else {
- replaceExpression(expression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(expression, newExpressionText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
index f0b1e40..d762573 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/jdk/ForeachStatementInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -134,7 +135,7 @@
newStatement.append(bodyText);
}
newStatement.append('}');
- replaceStatementAndShortenClassNames(statement, newStatement.toString());
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newStatement.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java
index 8670e0a..99e8d00 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsCalledOnArrayInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ImportUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
@@ -72,10 +73,10 @@
final PsiReferenceExpression methodExpression = (PsiReferenceExpression)parent;
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null && ImportUtils.addStaticImport("org.junit.Assert", "assertArrayEquals", methodExpression)) {
- replaceExpression(methodExpression, "assertArrayEquals");
+ PsiReplacementUtil.replaceExpression(methodExpression, "assertArrayEquals");
}
else {
- replaceExpression(methodExpression, "org.junit.Assert.assertArrayEquals");
+ PsiReplacementUtil.replaceExpression(methodExpression, "org.junit.Assert.assertArrayEquals");
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java
index 8fae6b0..32d1803 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/AssertEqualsMayBeAssertSameInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ImportUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -87,10 +88,10 @@
}
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null && ImportUtils.addStaticImport(className, "assertSame", methodExpression)) {
- replaceExpression(methodExpression, "assertSame");
+ PsiReplacementUtil.replaceExpression(methodExpression, "assertSame");
}
else {
- replaceExpression(methodExpression, className + ".assertSame");
+ PsiReplacementUtil.replaceExpression(methodExpression, className + ".assertSame");
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsArgumentsInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsArgumentsInspectionBase.java
new file mode 100644
index 0000000..0760b14
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsArgumentsInspectionBase.java
@@ -0,0 +1,193 @@
+/*
+ * 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.siyeh.ig.junit;
+
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.util.IncorrectOperationException;
+import com.intellij.util.containers.ContainerUtil;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.ExpressionUtils;
+import com.siyeh.ig.psiutils.TypeUtils;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Set;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public abstract class MisorderedAssertEqualsArgumentsInspectionBase extends BaseInspection {
+
+ @NonNls
+ private static final Set<String> methodNames =
+ ContainerUtil.newHashSet("assertEquals", "assertEqualsNoOrder", "assertNotEquals", "assertArrayEquals", "assertSame",
+ "assertNotSame", "failNotSame", "failNotEquals");
+
+ public abstract boolean checkTestNG();
+
+ @Override
+ @NotNull
+ public final String getDisplayName() {
+ return InspectionGadgetsBundle.message("misordered.assert.equals.arguments.display.name");
+ }
+
+ @Override
+ @NotNull
+ protected final String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("misordered.assert.equals.arguments.problem.descriptor");
+ }
+
+ @Override
+ public final InspectionGadgetsFix buildFix(Object... infos) {
+ return new FlipArgumentsFix();
+ }
+
+ private static class FlipArgumentsFix extends InspectionGadgetsFix {
+ @Override
+ @NotNull
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ @NotNull
+ public String getName() {
+ return InspectionGadgetsBundle.message("misordered.assert.equals.arguments.flip.quickfix");
+ }
+
+ @Override
+ public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
+ final PsiElement methodNameIdentifier = descriptor.getPsiElement();
+ final PsiElement parent = methodNameIdentifier.getParent();
+ if (parent == null) {
+ return;
+ }
+ final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)parent.getParent();
+ if (callExpression == null) {
+ return;
+ }
+ final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
+ final PsiMethod method = (PsiMethod)methodExpression.resolve();
+ if (method == null) {
+ return;
+ }
+ final PsiClass containingClass = method.getContainingClass();
+ final boolean junit;
+ if (InheritanceUtil.isInheritor(containingClass, "org.testng.Assert")) {
+ junit = false;
+ }
+ else if (InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit") ||
+ InheritanceUtil.isInheritor(containingClass, "junit.framework.Assert") ||
+ InheritanceUtil.isInheritor(containingClass, "org.junit.Assert")) {
+ junit = true;
+ }
+ else {
+ return;
+ }
+ final PsiParameterList parameterList = method.getParameterList();
+ final PsiParameter[] parameters = parameterList.getParameters();
+ final PsiType stringType = TypeUtils.getStringType(callExpression);
+ final PsiType parameterType1 = parameters[0].getType();
+ final PsiExpressionList argumentList = callExpression.getArgumentList();
+ final PsiExpression[] arguments = argumentList.getExpressions();
+ final PsiExpression expectedArgument;
+ final PsiExpression actualArgument;
+ if (junit) {
+ if (parameterType1.equals(stringType) && parameters.length > 2) {
+ expectedArgument = arguments[1];
+ actualArgument = arguments[2];
+ }
+ else {
+ expectedArgument = arguments[0];
+ actualArgument = arguments[1];
+ }
+ }
+ else {
+ actualArgument = arguments[0];
+ expectedArgument = arguments[1];
+ }
+ final PsiElement copy = expectedArgument.copy();
+ expectedArgument.replace(actualArgument);
+ actualArgument.replace(copy);
+ }
+ }
+
+ @Override
+ public final BaseInspectionVisitor buildVisitor() {
+ return new MisorderedAssertEqualsParametersVisitor();
+ }
+
+ private class MisorderedAssertEqualsParametersVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ final PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ @NonNls final String methodName = methodExpression.getReferenceName();
+ if (!methodNames.contains(methodName)) {
+ return;
+ }
+ final PsiMethod method = expression.resolveMethod();
+ if (method == null || method.hasModifierProperty(PsiModifier.PRIVATE)) {
+ return;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ final PsiExpression[] arguments = argumentList.getExpressions();
+ if (arguments.length < 2) {
+ return;
+ }
+ final PsiType stringType = TypeUtils.getStringType(expression);
+ final PsiClass containingClass = method.getContainingClass();
+ final PsiExpression expectedArgument;
+ final PsiExpression actualArgument;
+ if (checkTestNG() ?
+ InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit") :
+ InheritanceUtil.isInheritor(containingClass, "junit.framework.Assert") ||
+ InheritanceUtil.isInheritor(containingClass, "org.junit.Assert")) {
+ final PsiType firstArgumentType = arguments[0].getType();
+ if (stringType.equals(firstArgumentType) && arguments.length > 2) {
+ expectedArgument = arguments[1];
+ actualArgument = arguments[2];
+ }
+ else {
+ expectedArgument = arguments[0];
+ actualArgument = arguments[1];
+ }
+ } else if (checkTestNG() && InheritanceUtil.isInheritor(containingClass, "org.testng.Assert")){
+ expectedArgument = arguments[1];
+ actualArgument = arguments[0];
+ } else {
+ return;
+ }
+ if (expectedArgument == null || actualArgument == null) {
+ return;
+ }
+ if (ExpressionUtils.computeConstantExpression(expectedArgument) != null) {
+ return;
+ }
+ if (ExpressionUtils.computeConstantExpression(actualArgument) == null) {
+ return;
+ }
+ registerMethodCallError(expression);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
index edf499d..ecf806b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -15,21 +15,9 @@
*/
package com.siyeh.ig.junit;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.util.IncorrectOperationException;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.InspectionGadgetsFix;
-import com.siyeh.ig.psiutils.TypeUtils;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-public class MisorderedAssertEqualsParametersInspection extends BaseInspection {
+public class MisorderedAssertEqualsParametersInspection extends MisorderedAssertEqualsArgumentsInspectionBase {
@Nullable
@Override
@@ -38,148 +26,7 @@
}
@Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("misordered.assert.equals.parameters.display.name");
- }
-
- @Override
- @NotNull
- protected String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message("misordered.assert.equals.parameters.problem.descriptor");
- }
-
- @Override
- public InspectionGadgetsFix buildFix(Object... infos) {
- return new FlipParametersFix();
- }
-
- private static class FlipParametersFix extends InspectionGadgetsFix {
- @Override
- @NotNull
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- @NotNull
- public String getName() {
- return InspectionGadgetsBundle.message("misordered.assert.equals.parameters.flip.quickfix");
- }
-
- @Override
- public void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
- final PsiElement methodNameIdentifier = descriptor.getPsiElement();
- final PsiElement parent = methodNameIdentifier.getParent();
- assert parent != null;
- final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)parent.getParent();
- assert callExpression != null;
- final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
- final PsiMethod method = (PsiMethod)methodExpression.resolve();
- assert method != null;
- final PsiParameterList parameterList = method.getParameterList();
- final PsiParameter[] parameters = parameterList.getParameters();
- final PsiType stringType = TypeUtils.getStringType(callExpression);
- final PsiType parameterType1 = parameters[0].getType();
- final PsiExpressionList argumentList = callExpression.getArgumentList();
- final PsiExpression[] arguments = argumentList.getExpressions();
- final PsiExpression actualArgument;
- final PsiExpression expectedArgument;
- if (parameterType1.equals(stringType) && parameters.length > 2) {
- expectedArgument = arguments[1];
- actualArgument = arguments[2];
- }
- else {
- expectedArgument = arguments[0];
- actualArgument = arguments[1];
- }
- final String actualArgumentText = actualArgument.getText();
- final String expectedArgumentText = expectedArgument.getText();
- replaceExpression(expectedArgument, actualArgumentText);
- replaceExpression(actualArgument, expectedArgumentText);
- }
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new MisorderedAssertEqualsParametersVisitor();
- }
-
- private static class MisorderedAssertEqualsParametersVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
- super.visitMethodCallExpression(expression);
- final PsiReferenceExpression methodExpression = expression.getMethodExpression();
- @NonNls final String methodName = methodExpression.getReferenceName();
- if (!"assertEquals".equals(methodName) && !"assertArrayEquals".equals(methodName)) {
- return;
- }
- final PsiMethod method = expression.resolveMethod();
- if (method == null) {
- return;
- }
- final PsiClass containingClass = method.getContainingClass();
- if (!InheritanceUtil.isInheritor(containingClass, "junit.framework.Assert") &&
- !InheritanceUtil.isInheritor(containingClass, "org.junit.Assert")) {
- return;
- }
- final PsiExpressionList argumentList = expression.getArgumentList();
- final PsiExpression[] arguments = argumentList.getExpressions();
- if (arguments.length < 2) {
- return;
- }
- final PsiType stringType = TypeUtils.getStringType(expression);
- final PsiType argumentType1 = arguments[0].getType();
- final PsiExpression expectedArgument;
- final PsiExpression actualArgument;
- if (stringType.equals(argumentType1) && arguments.length > 2) {
- expectedArgument = arguments[1];
- actualArgument = arguments[2];
- }
- else {
- expectedArgument = arguments[0];
- actualArgument = arguments[1];
- }
- if (expectedArgument == null || actualArgument == null) {
- return;
- }
- if (isLiteralOrConstant(expectedArgument)) {
- return;
- }
- if (!isLiteralOrConstant(actualArgument)) {
- return;
- }
- registerMethodCallError(expression);
- }
-
- private static boolean isLiteralOrConstant(PsiExpression expression) {
- if (expression instanceof PsiLiteralExpression) {
- return true;
- }
- else if (expression instanceof PsiNewExpression) {
- final PsiNewExpression newExpression = (PsiNewExpression)expression;
- final PsiExpressionList argumentList = newExpression.getArgumentList();
- if (argumentList == null) {
- return true;
- }
- for (PsiExpression argument : argumentList.getExpressions()) {
- if (!isLiteralOrConstant(argument)) {
- return false;
- }
- }
- return true;
- }
- if (!(expression instanceof PsiReferenceExpression)) {
- return false;
- }
- final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
- final PsiElement target = referenceExpression.resolve();
- if (!(target instanceof PsiField)) {
- return false;
- }
- final PsiField field = (PsiField)target;
- return field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL);
- }
+ public boolean checkTestNG() {
+ return false;
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
index e5512ae..b972890 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/SimplifiableJUnitAssertionInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -109,7 +110,7 @@
newExpression.append(message.getText());
}
newExpression.append(')');
- replaceExpressionAndShorten(callExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(callExpression, newExpression.toString());
}
private static void replaceAssertTrueWithAssertEquals(PsiMethodCallExpression callExpression) throws IncorrectOperationException {
@@ -170,7 +171,7 @@
newExpression.append(",0.0");
}
newExpression.append(')');
- replaceExpressionAndShorten(callExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(callExpression, newExpression.toString());
}
private static void replaceAssertWithAssertNull(PsiMethodCallExpression callExpression) throws IncorrectOperationException {
@@ -222,7 +223,7 @@
newExpression.append(message.getText()).append(',');
}
newExpression.append(rhs.getText()).append(')');
- replaceExpressionAndShorten(callExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(callExpression, newExpression.toString());
}
private static void replaceAssertWithAssertSame(PsiMethodCallExpression callExpression) throws IncorrectOperationException {
@@ -276,7 +277,7 @@
newExpression.append(message.getText()).append(',');
}
newExpression.append(lhs.getText()).append(',').append(rhs.getText()).append(')');
- replaceExpressionAndShorten(callExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(callExpression, newExpression.toString());
}
private static void replaceAssertEqualsWithAssertLiteral(
@@ -328,7 +329,7 @@
newExpression.append(message.getText()).append(',');
}
newExpression.append(compareValue).append(')');
- replaceExpressionAndShorten(callExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpressionAndShorten(callExpression, newExpression.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestCaseInProductCodeInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestCaseInProductCodeInspectionBase.java
index 32f412b..aba739b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestCaseInProductCodeInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestCaseInProductCodeInspectionBase.java
@@ -16,7 +16,6 @@
package com.siyeh.ig.junit;
import com.intellij.psi.PsiClass;
-import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -54,16 +53,11 @@
return new TestCaseInProductCodeVisitor();
}
- private static class TestCaseInProductCodeVisitor
- extends BaseInspectionVisitor {
+ private static class TestCaseInProductCodeVisitor extends BaseInspectionVisitor {
@Override
public void visitClass(@NotNull PsiClass aClass) {
- if (TestUtils.isTest(aClass)) {
- return;
- }
- if (!InheritanceUtil.isInheritor(aClass,
- "junit.framework.TestCase")) {
+ if (TestUtils.isInTestSourceContent(aClass) || !TestUtils.isJUnitTestClass(aClass)) {
return;
}
registerClassError(aClass);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java
index 10bc385..ace8cd1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodInProductCodeInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2006-2009 Dave Griffith, Bas Leijdekkers
+ * Copyright 2006-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.
@@ -56,7 +56,7 @@
@Override
public void visitMethod(PsiMethod method) {
final PsiClass containingClass = method.getContainingClass();
- if (TestUtils.isTest(containingClass) ||
+ if (TestUtils.isInTestSourceContent(containingClass) ||
!TestUtils.isJUnit4TestMethod(method)) {
return;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java
index 59710ab..b4a7336 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/junit/TestMethodWithoutAssertionInspectionBase.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.
@@ -45,6 +45,7 @@
"org.junit.Assert,assert.*|fail.*," +
"junit.framework.Assert,assert.*|fail.*," +
"org.mockito.Mockito,verify.*," +
+ "org.mockito.InOrder,verify," +
"org.junit.rules.ExpectedException,expect.*," +
"org.hamcrest.MatcherAssert,assertThat";
@SuppressWarnings({"PublicField"})
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java
index 5a70933..750b723 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/LoggerInitializedWithForeignClassInspectionBase.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -73,7 +74,7 @@
super.readSettings(element);
parseString(loggerClassName, loggerFactoryClassNames);
parseString(loggerFactoryMethodName, loggerFactoryMethodNames);
- if (loggerFactoryClassNames.size() != loggerFactoryMethodNames.size()) {
+ if (loggerFactoryClassNames.size() != loggerFactoryMethodNames.size() || loggerFactoryClassNames.isEmpty()) {
parseString(DEFAULT_LOGGER_CLASS_NAMES, loggerFactoryClassNames);
parseString(DEFAULT_FACTORY_METHOD_NAMES, loggerFactoryMethodNames);
}
@@ -113,7 +114,7 @@
return;
}
final PsiClassObjectAccessExpression classObjectAccessExpression = (PsiClassObjectAccessExpression)element;
- replaceExpression(classObjectAccessExpression, newClassName + ".class");
+ PsiReplacementUtil.replaceExpression(classObjectAccessExpression, newClassName + ".class");
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
index 40925af..2dc9ad3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/logging/StringConcatenationArgumentToLogCallInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
@@ -215,7 +216,7 @@
}
}
newMethodCall.append(')');
- replaceExpression(methodCallExpression, newMethodCall.toString());
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newMethodCall.toString());
}
public static boolean isAvailable(PsiExpression expression) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SuppressionAnnotationInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SuppressionAnnotationInspectionBase.java
index 2eb1cc3..dcbbe34 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SuppressionAnnotationInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SuppressionAnnotationInspectionBase.java
@@ -17,7 +17,9 @@
import com.intellij.codeInspection.BatchSuppressManager;
import com.intellij.codeInspection.JavaSuppressionUtil;
+import com.intellij.codeInspection.SuppressionUtil;
import com.intellij.codeInspection.SuppressionUtilCore;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.siyeh.InspectionGadgetsBundle;
@@ -66,7 +68,16 @@
if (commentText.length() > 2) {
@NonNls final String strippedComment = commentText.substring(2).trim();
if (strippedComment.startsWith(SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME)) {
- registerError(comment);
+ final String suppressedIds = JavaSuppressionUtil.getSuppressedInspectionIdsIn(comment);
+ final Iterable<String> ids = suppressedIds != null ? StringUtil.tokenize(suppressedIds, "[, ]") : null;
+ if (ids != null) {
+ for (String id : ids) {
+ if (!myAllowedSuppressions.contains(id)) {
+ registerError(comment, comment);
+ break;
+ }
+ }
+ }
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SystemOutErrInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SystemOutErrInspection.java
deleted file mode 100644
index 3c8188a..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SystemOutErrInspection.java
+++ /dev/null
@@ -1,98 +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.ig.maturity;
-
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiField;
-import com.intellij.psi.PsiReferenceExpression;
-import com.siyeh.HardcodedMethodConstants;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.TestUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-public class SystemOutErrInspection extends BaseInspection {
-
- @SuppressWarnings("PublicField")
- public boolean ignoreInTestCode = false;
-
- @Override
- @NotNull
- public String getID() {
- return "UseOfSystemOutOrSystemErr";
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "use.system.out.err.display.name");
- }
-
- @Override
- @NotNull
- public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message(
- "use.system.out.err.problem.descriptor");
- }
-
- @Nullable
- @Override
- public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("ignore.in.test.code"), this, "ignoreInTestCode");
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new SystemOutErrVisitor();
- }
-
- private class SystemOutErrVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
- super.visitReferenceExpression(expression);
- final String name = expression.getReferenceName();
- if (!HardcodedMethodConstants.OUT.equals(name) &&
- !HardcodedMethodConstants.ERR.equals(name)) {
- return;
- }
- final PsiElement referent = expression.resolve();
- if (!(referent instanceof PsiField)) {
- return;
- }
- final PsiField field = (PsiField)referent;
- final PsiClass containingClass = field.getContainingClass();
- if (containingClass == null) {
- return;
- }
- final String className = containingClass.getQualifiedName();
- if (!"java.lang.System".equals(className)) {
- return;
- }
- if (ignoreInTestCode && TestUtils.isInTestCode(expression)) {
- return;
- }
- registerError(expression);
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SystemOutErrInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SystemOutErrInspectionBase.java
new file mode 100644
index 0000000..b382e2f
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/SystemOutErrInspectionBase.java
@@ -0,0 +1,81 @@
+/*
+ * 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.ig.maturity;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiField;
+import com.intellij.psi.PsiReferenceExpression;
+import com.siyeh.HardcodedMethodConstants;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import org.jetbrains.annotations.NotNull;
+
+public class SystemOutErrInspectionBase extends BaseInspection {
+
+ @Override
+ @NotNull
+ public String getID() {
+ return "UseOfSystemOutOrSystemErr";
+ }
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message(
+ "use.system.out.err.display.name");
+ }
+
+ @Override
+ @NotNull
+ public String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message(
+ "use.system.out.err.problem.descriptor");
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new SystemOutErrVisitor();
+ }
+
+ private static class SystemOutErrVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
+ final String name = expression.getReferenceName();
+ if (!HardcodedMethodConstants.OUT.equals(name) &&
+ !HardcodedMethodConstants.ERR.equals(name)) {
+ return;
+ }
+ final PsiElement referent = expression.resolve();
+ if (!(referent instanceof PsiField)) {
+ return;
+ }
+ final PsiField field = (PsiField)referent;
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass == null) {
+ return;
+ }
+ final String className = containingClass.getQualifiedName();
+ if (!"java.lang.System".equals(className)) {
+ return;
+ }
+ registerError(expression, expression);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspection.java
deleted file mode 100644
index e7e90e0..0000000
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspection.java
+++ /dev/null
@@ -1,96 +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.ig.maturity;
-
-import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
-import com.intellij.psi.*;
-import com.siyeh.HardcodedMethodConstants;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.BaseInspection;
-import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.MethodCallUtils;
-import com.siyeh.ig.psiutils.TestUtils;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-public class ThrowablePrintStackTraceInspection extends BaseInspection {
-
- @SuppressWarnings("PublicField")
- public boolean ignoreInTestCode = false;
-
- @Override
- @NotNull
- public String getID() {
- return "CallToPrintStackTrace";
- }
-
- @Override
- @NotNull
- public String getDisplayName() {
- return InspectionGadgetsBundle.message("printstacktrace.call.display.name");
- }
-
- @Override
- @NotNull
- public String buildErrorString(Object... infos) {
- return InspectionGadgetsBundle.message("printstacktrace.call.problem.descriptor");
- }
-
- @Nullable
- @Override
- public JComponent createOptionsPanel() {
- return new SingleCheckboxOptionsPanel(InspectionGadgetsBundle.message("ignore.in.test.code"), this, "ignoreInTestCode");
- }
-
- @Override
- public BaseInspectionVisitor buildVisitor() {
- return new ThrowablePrintStackTraceVisitor();
- }
-
- private class ThrowablePrintStackTraceVisitor extends BaseInspectionVisitor {
-
- @Override
- public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
- super.visitMethodCallExpression(expression);
- final String methodName = MethodCallUtils.getMethodName(expression);
- if (!HardcodedMethodConstants.PRINT_STACK_TRACE.equals(methodName)) {
- return;
- }
- final PsiExpressionList argumentList = expression.getArgumentList();
- if (argumentList.getExpressions().length != 0) {
- return;
- }
- final PsiMethod method = expression.resolveMethod();
- if (method == null) {
- return;
- }
- final PsiClass containingClass = method.getContainingClass();
- if (containingClass == null) {
- return;
- }
- final String name = containingClass.getQualifiedName();
- if (!CommonClassNames.JAVA_LANG_THROWABLE.equals(name)) {
- return;
- }
- if (ignoreInTestCode && TestUtils.isInTestCode(expression)) {
- return;
- }
- registerMethodCallError(expression);
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionBase.java
new file mode 100644
index 0000000..69c9e56
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionBase.java
@@ -0,0 +1,79 @@
+/*
+ * 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.ig.maturity;
+
+import com.intellij.psi.*;
+import com.siyeh.HardcodedMethodConstants;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.BaseInspectionVisitor;
+import com.siyeh.ig.psiutils.MethodCallUtils;
+import org.jetbrains.annotations.NotNull;
+
+public class ThrowablePrintStackTraceInspectionBase extends BaseInspection {
+
+ @Override
+ @NotNull
+ public String getID() {
+ return "CallToPrintStackTrace";
+ }
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("printstacktrace.call.display.name");
+ }
+
+ @Override
+ @NotNull
+ public String buildErrorString(Object... infos) {
+ return InspectionGadgetsBundle.message("printstacktrace.call.problem.descriptor");
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new ThrowablePrintStackTraceVisitor();
+ }
+
+ private static class ThrowablePrintStackTraceVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+ final String methodName = MethodCallUtils.getMethodName(expression);
+ if (!HardcodedMethodConstants.PRINT_STACK_TRACE.equals(methodName)) {
+ return;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ if (argumentList.getExpressions().length != 0) {
+ return;
+ }
+ final PsiMethod method = expression.resolveMethod();
+ if (method == null) {
+ return;
+ }
+ final PsiClass containingClass = method.getContainingClass();
+ if (containingClass == null) {
+ return;
+ }
+ final String name = containingClass.getQualifiedName();
+ if (!CommonClassNames.JAVA_LANG_THROWABLE.equals(name)) {
+ return;
+ }
+ registerMethodCallError(expression, expression);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintedToSystemOutInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintedToSystemOutInspection.java
index b44a1a9..49c63ef 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintedToSystemOutInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/maturity/ThrowablePrintedToSystemOutInspection.java
@@ -44,6 +44,11 @@
}
@Override
+ public boolean isEnabledByDefault() {
+ return true;
+ }
+
+ @Override
public BaseInspectionVisitor buildVisitor() {
return new ThrowablePrintedToSystemOutVisitor();
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java
index a8b5918..88c264c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/CollectionsFieldAccessReplaceableByMethodCallInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
@@ -170,8 +171,8 @@
(PsiReferenceExpression)element;
final String newMethodCallText =
getCollectionsMethodCallText(referenceExpression);
- replaceExpression(referenceExpression,
- "java.util." + newMethodCallText);
+ PsiReplacementUtil.replaceExpression(referenceExpression,
+ "java.util." + newMethodCallText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java
index bd7acc8..010cbb4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/IndexOfReplaceableByContainsInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
@@ -109,7 +110,7 @@
else {
return;
}
- replaceExpression(expression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(expression, newExpressionText);
}
@Override
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
index 7777d87..3a761f5 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspection.java
@@ -39,6 +39,9 @@
@SuppressWarnings("PublicField")
public boolean ignoreOverridingMethods = false;
+ @SuppressWarnings("PublicField")
+ public boolean onlyReportPublicMethods = false;
+
@Nls
@NotNull
@Override
@@ -58,6 +61,7 @@
panel.addCheckbox(InspectionGadgetsBundle.message("method.can.be.variable.arity.method.ignore.byte.short.option"),
"ignoreByteAndShortArrayParameters");
panel.addCheckbox(InspectionGadgetsBundle.message("ignore.methods.overriding.super.method"), "ignoreOverridingMethods");
+ panel.addCheckbox(InspectionGadgetsBundle.message("only.report.public.methods.option"), "onlyReportPublicMethods");
return panel;
}
@@ -79,6 +83,9 @@
return;
}
super.visitMethod(method);
+ if (onlyReportPublicMethods && !method.hasModifierProperty(PsiModifier.PUBLIC)) {
+ return;
+ }
final PsiParameterList parameterList = method.getParameterList();
if (parameterList.getParametersCount() == 0) {
return;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java
index 3c0f3d0..4c2c44b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryBoxingInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
@@ -123,10 +124,10 @@
}
final int precedence = ParenthesesUtils.getPrecedence(unboxedExpression);
if (!cast.isEmpty() && precedence > ParenthesesUtils.TYPE_CAST_PRECEDENCE) {
- replaceExpression(expression, cast + '(' + unboxedExpression.getText() + ')');
+ PsiReplacementUtil.replaceExpression(expression, cast + '(' + unboxedExpression.getText() + ')');
}
else {
- replaceExpression(expression, cast + unboxedExpression.getText());
+ PsiReplacementUtil.replaceExpression(expression, cast + unboxedExpression.getText());
}
}
@@ -326,7 +327,8 @@
if (containingClass == null) {
return false;
}
- final PsiType[] types = new PsiType[expressions.length];
+ final PsiType[] types = PsiType.createArray(expressions.length);
+
for (int i = 0; i < expressions.length; i++) {
final PsiExpression expression = expressions[i];
final PsiType type = expression.getType();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java
index 96194b7..9118a79 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/migration/UnnecessaryUnboxingInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
@@ -129,18 +130,18 @@
if (CommonClassNames.JAVA_LANG_BOOLEAN.equals(classname)) {
@NonNls final String name = field.getName();
if ("TRUE".equals(name)) {
- replaceExpression(methodCall, "true");
+ PsiReplacementUtil.replaceExpression(methodCall, "true");
return;
}
else if ("FALSE".equals(name)) {
- replaceExpression(methodCall, "false");
+ PsiReplacementUtil.replaceExpression(methodCall, "false");
return;
}
}
}
}
final String strippedQualifierText = strippedQualifier.getText();
- replaceExpression(methodCall, strippedQualifierText);
+ PsiReplacementUtil.replaceExpression(methodCall, strippedQualifierText);
}
}
@@ -285,7 +286,7 @@
if (containingClass == null) {
return false;
}
- final PsiType[] types = new PsiType[expressions.length];
+ final PsiType[] types = PsiType.createArray(expressions.length);
for (int i = 0; i < expressions.length; i++) {
final PsiExpression expression = expressions[i];
final PsiType type = expression.getType();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/AbstractClassNamingConventionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/AbstractClassNamingConventionInspectionBase.java
new file mode 100644
index 0000000..5dd3cfe
--- /dev/null
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/AbstractClassNamingConventionInspectionBase.java
@@ -0,0 +1,92 @@
+/*
+ * 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.siyeh.ig.naming;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiModifier;
+import com.intellij.psi.PsiTypeParameter;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspectionVisitor;
+import org.jetbrains.annotations.NotNull;
+
+public class AbstractClassNamingConventionInspectionBase extends ConventionInspection {
+
+ private static final int DEFAULT_MIN_LENGTH = 8;
+ private static final int DEFAULT_MAX_LENGTH = 64;
+
+ @Override
+ @NotNull
+ public String getDisplayName() {
+ return InspectionGadgetsBundle.message("abstract.class.naming.convention.display.name");
+ }
+
+ @Override
+ protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
+ return true;
+ }
+
+ @Override
+ @NotNull
+ public String buildErrorString(Object... infos) {
+ final String className = (String)infos[0];
+ if (className.length() < getMinLength()) {
+ return InspectionGadgetsBundle.message("abstract.class.name.convention.problem.descriptor.short");
+ }
+ else if (className.length() > getMaxLength()) {
+ return InspectionGadgetsBundle.message("abstract.class.name.convention.problem.descriptor.long");
+ }
+ return InspectionGadgetsBundle.message("abstract.class.name.convention.problem.descriptor.regex.mismatch",
+ getRegex());
+ }
+
+ @Override
+ protected String getDefaultRegex() {
+ return "[A-Z][A-Za-z\\d]*";
+ }
+
+ @Override
+ protected int getDefaultMinLength() {
+ return DEFAULT_MIN_LENGTH;
+ }
+
+ @Override
+ protected int getDefaultMaxLength() {
+ return DEFAULT_MAX_LENGTH;
+ }
+
+ @Override
+ public BaseInspectionVisitor buildVisitor() {
+ return new NamingConventionsVisitor();
+ }
+
+ private class NamingConventionsVisitor extends BaseInspectionVisitor {
+
+ @Override
+ public void visitClass(@NotNull PsiClass aClass) {
+ if (aClass.isInterface() || aClass.isAnnotationType() || aClass.isEnum()) {
+ return;
+ }
+ if (aClass instanceof PsiTypeParameter || !aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ return;
+ }
+ final String name = aClass.getName();
+ if (name == null || isValid(name)) {
+ return;
+ }
+ registerClassError(aClass, name);
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/ClassNamingConventionInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/ClassNamingConventionInspectionBase.java
index ede181d..0b4e766 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/ClassNamingConventionInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/naming/ClassNamingConventionInspectionBase.java
@@ -16,6 +16,7 @@
package com.siyeh.ig.naming;
import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiTypeParameter;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -78,18 +79,17 @@
@Override
public void visitClass(@NotNull PsiClass aClass) {
- if (aClass.isInterface() || aClass.isAnnotationType() ||
- aClass.isEnum()) {
+ if (aClass.isInterface() || aClass.isAnnotationType() || aClass.isEnum()) {
return;
}
if (aClass instanceof PsiTypeParameter) {
return;
}
- final String name = aClass.getName();
- if (name == null) {
+ if (aClass.hasModifierProperty(PsiModifier.ABSTRACT) && isInspectionEnabled("AbstractClassNamingConvention", aClass)) {
return;
}
- if (isValid(name)) {
+ final String name = aClass.getName();
+ if (name == null || isValid(name)) {
return;
}
registerClassError(aClass, name);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java
index ca0d990..3b3b82e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/BigDecimalEqualsInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.MethodCallUtils;
import org.jetbrains.annotations.NotNull;
@@ -73,7 +74,7 @@
final PsiExpressionList argumentList = call.getArgumentList();
final PsiExpression[] args = argumentList.getExpressions();
final String argText = args[0].getText();
- replaceExpression(call, qualifierText + ".compareTo(" + argText + ")==0");
+ PsiReplacementUtil.replaceExpression(call, qualifierText + ".compareTo(" + argText + ")==0");
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java
index 803e89c..0c3208d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CachedNumberConstructorCallInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
@@ -103,7 +104,7 @@
final PsiExpression[] args = argList.getExpressions();
final PsiExpression arg = args[0];
final String text = arg.getText();
- replaceExpression(expression, className + ".valueOf(" + text + ')');
+ PsiReplacementUtil.replaceExpression(expression, className + ".valueOf(" + text + ')');
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java
index 5b9a4c4..4594a9d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/CharUsedInArithmeticContextInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.TypeUtils;
@@ -102,7 +103,7 @@
return;
}
final String escaped = StringUtil.escapeStringCharacters(literal.toString());
- replaceExpression(literalExpression, '\"' + escaped + '"');
+ PsiReplacementUtil.replaceExpression(literalExpression, '\"' + escaped + '"');
}
}
@@ -134,7 +135,7 @@
}
final PsiExpression expression = (PsiExpression)element;
final String expressionText = expression.getText();
- replaceExpression(expression, '(' + typeText + ')' + expressionText);
+ PsiReplacementUtil.replaceExpression(expression, '(' + typeText + ')' + expressionText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java
index 6ea0bf6..db4e974 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ComparisonToNaNInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -107,7 +108,7 @@
negationText = "!";
}
@NonNls final String newExpressionText = negationText + typeText + ".isNaN(" + operandText + ')';
- replaceExpression(comparison, newExpressionText);
+ PsiReplacementUtil.replaceExpression(comparison, newExpressionText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java
index 5e589a9..8a5d511 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConfusingFloatingPointLiteralInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,7 +68,7 @@
final PsiExpression literalExpression = (PsiExpression)descriptor.getPsiElement();
final String text = literalExpression.getText();
final String newText = getCanonicalForm(text);
- replaceExpression(literalExpression, newText);
+ PsiReplacementUtil.replaceExpression(literalExpression, newText);
}
private static String getCanonicalForm(@NonNls String text) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java
index 71b6a97..9a16aab 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ConstantMathCallInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -139,10 +140,10 @@
return;
}
if (PsiType.LONG.equals(type)) {
- replaceExpressionAndShorten(call, newExpression + 'L');
+ PsiReplacementUtil.replaceExpressionAndShorten(call, newExpression + 'L');
}
else {
- replaceExpressionAndShorten(call, newExpression);
+ PsiReplacementUtil.replaceExpressionAndShorten(call, newExpression);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java
index b08e354..ed61e45 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/DoubleLiteralMayBeFloatLiteralInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -122,7 +123,7 @@
}
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)element;
- replaceExpression(typeCastExpression, replacementString);
+ PsiReplacementUtil.replaceExpression(typeCastExpression, replacementString);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
index cee789f..cec661a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/ImplicitNumericConversionInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
@@ -136,7 +137,7 @@
if (newExpression == null) {
return;
}
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
else {
final String newExpression;
@@ -146,7 +147,7 @@
else {
newExpression = '(' + expectedType.getCanonicalText() + ")(" + expression.getText() + ')';
}
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java
index dfb4832..eb78377 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/IntLiteralMayBeLongLiteralInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -122,7 +123,7 @@
}
final PsiTypeCastExpression typeCastExpression =
(PsiTypeCastExpression)element;
- replaceExpression(typeCastExpression, replacementString);
+ PsiReplacementUtil.replaceExpression(typeCastExpression, replacementString);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java
index bc78f3b..80dab23 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/LongLiteralsEndingWithLowercaseLInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class LongLiteralsEndingWithLowercaseLInspection
@@ -81,7 +82,7 @@
(PsiExpression)descriptor.getPsiElement();
final String text = literal.getText();
final String newText = text.replace('l', 'L');
- replaceExpression(literal, newText);
+ PsiReplacementUtil.replaceExpression(literal, newText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java
index 417f3e8..4e94124 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/NonReproducibleMathCallInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -99,7 +100,7 @@
(PsiReferenceExpression)nameIdentifier.getParent();
assert reference != null;
final String name = reference.getReferenceName();
- replaceExpression(reference, "StrictMath." + name);
+ PsiReplacementUtil.replaceExpression(reference, "StrictMath." + name);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java
index b537995..57af535 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/PointlessArithmeticExpressionInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -26,19 +26,21 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
+import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ExpressionUtils;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import java.util.HashSet;
import java.util.Set;
public class PointlessArithmeticExpressionInspection
extends BaseInspection {
private static final Set<IElementType> arithmeticTokens =
- new HashSet<IElementType>(5);
+ new THashSet<IElementType>(9);
static {
arithmeticTokens.add(JavaTokenType.PLUS);
@@ -86,8 +88,7 @@
}
@NonNls
- String calculateReplacementExpression(
- PsiExpression expression) {
+ String calculateReplacementExpression(PsiExpression expression) {
final PsiBinaryExpression exp = (PsiBinaryExpression)expression;
final PsiExpression lhs = exp.getLOperand();
final PsiExpression rhs = exp.getROperand();
@@ -102,7 +103,10 @@
}
}
else if (tokenType.equals(JavaTokenType.MINUS)) {
- return lhs.getText();
+ if (isZero(rhs)) {
+ return lhs.getText();
+ }
+ return "0";
}
else if (tokenType.equals(JavaTokenType.ASTERISK)) {
if (isOne(lhs)) {
@@ -116,7 +120,10 @@
}
}
else if (tokenType.equals(JavaTokenType.DIV)) {
- return lhs.getText();
+ if (ExpressionUtils.isOne(expression)) {
+ return lhs.getText();
+ }
+ return "1";
}
else if (tokenType.equals(JavaTokenType.PERC)) {
return "0";
@@ -160,7 +167,7 @@
(PsiExpression)descriptor.getPsiElement();
final String newExpression =
calculateReplacementExpression(expression);
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
@@ -197,16 +204,16 @@
isPointless = additionExpressionIsPointless(lhs, rhs);
}
else if (tokenType.equals(JavaTokenType.MINUS)) {
- isPointless = subtractionExpressionIsPointless(rhs);
+ isPointless = subtractionExpressionIsPointless(lhs, rhs);
}
else if (tokenType.equals(JavaTokenType.ASTERISK)) {
isPointless = multiplyExpressionIsPointless(lhs, rhs);
}
else if (tokenType.equals(JavaTokenType.DIV)) {
- isPointless = divideExpressionIsPointless(rhs);
+ isPointless = divideExpressionIsPointless(lhs, rhs);
}
else if (tokenType.equals(JavaTokenType.PERC)) {
- isPointless = modExpressionIsPointless(rhs);
+ isPointless = modExpressionIsPointless(lhs, rhs);
}
else if (tokenType.equals(JavaTokenType.LE) ||
tokenType.equals(JavaTokenType.GE) ||
@@ -233,25 +240,32 @@
registerError(expression, expression);
}
- private boolean subtractionExpressionIsPointless(PsiExpression rhs) {
+ private boolean subtractionExpressionIsPointless(PsiExpression lhs, PsiExpression rhs) {
+ if (PsiType.INT.equals(lhs.getType()) && EquivalenceChecker.expressionsAreEquivalent(lhs, rhs)) {
+ return true;
+ }
return isZero(rhs);
}
- private boolean additionExpressionIsPointless(PsiExpression lhs,
- PsiExpression rhs) {
+ private boolean additionExpressionIsPointless(PsiExpression lhs, PsiExpression rhs) {
return isZero(lhs) || isZero(rhs);
}
- private boolean multiplyExpressionIsPointless(PsiExpression lhs,
- PsiExpression rhs) {
+ private boolean multiplyExpressionIsPointless(PsiExpression lhs, PsiExpression rhs) {
return isZero(lhs) || isZero(rhs) || isOne(lhs) || isOne(rhs);
}
- private boolean divideExpressionIsPointless(PsiExpression rhs) {
+ private boolean divideExpressionIsPointless(PsiExpression lhs, PsiExpression rhs) {
+ if (PsiType.INT.equals(lhs.getType()) && EquivalenceChecker.expressionsAreEquivalent(lhs, rhs)) {
+ return true;
+ }
return isOne(rhs);
}
- private boolean modExpressionIsPointless(PsiExpression rhs) {
+ private boolean modExpressionIsPointless(PsiExpression lhs, PsiExpression rhs) {
+ if (PsiType.INT.equals(lhs.getType()) && EquivalenceChecker.expressionsAreEquivalent(lhs, rhs)) {
+ return true;
+ }
return PsiType.INT.equals(rhs.getType()) && isOne(rhs);
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
index 57ef313..30a1e66 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryExplicitNumericCastInspection.java
@@ -29,15 +29,15 @@
import com.siyeh.ig.psiutils.ExpectedTypeUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.TypeUtils;
+import gnu.trove.THashSet;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
-import java.util.HashSet;
import java.util.Set;
public class UnnecessaryExplicitNumericCastInspection extends BaseInspection {
- private static final Set<IElementType> binaryPromotionOperators = new HashSet();
+ private static final Set<IElementType> binaryPromotionOperators = new THashSet<IElementType>();
static {
binaryPromotionOperators.add(JavaTokenType.ASTERISK);
@@ -128,10 +128,7 @@
return;
}
final PsiType operandType = operand.getType();
- if (operandType == null || operandType.equals(castType)) {
- return;
- }
- if (isPrimitiveNumericCastNecessary(expression)) {
+ if (castType.equals(operandType) || isPrimitiveNumericCastNecessary(expression)) {
return;
}
final PsiTypeElement typeElement = expression.getCastType();
@@ -151,6 +148,9 @@
return true;
}
final PsiType operandType = operand.getType();
+ if (operandType == null) {
+ return true;
+ }
PsiElement parent = expression.getParent();
while (parent instanceof PsiParenthesizedExpression) {
parent = parent.getParent();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java
index da8d231..0d598c4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnnecessaryUnaryMinusInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -106,7 +107,7 @@
return;
}
newExpression.append(operand.getText());
- replaceExpression(parentExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(parentExpression, newExpression.toString());
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
index 95cffc6..d3b62a4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/numeric/UnpredictableBigDecimalConstructorCallInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -119,8 +120,8 @@
return;
}
final PsiExpression firstArgument = arguments[0];
- replaceExpression(firstArgument,
- '"' + firstArgument.getText() + '"');
+ PsiReplacementUtil.replaceExpression(firstArgument,
+ '"' + firstArgument.getText() + '"');
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java
index 9623391..2d4a0f9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ArraysAsListWithZeroOrOneArgumentInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -91,11 +92,11 @@
}
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)element;
if (myEmpty) {
- replaceExpressionAndShorten(methodCallExpression, "java.util.Collections.emptyList()");
+ PsiReplacementUtil.replaceExpressionAndShorten(methodCallExpression, "java.util.Collections.emptyList()");
}
else {
final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
- replaceExpressionAndShorten(methodCallExpression, "java.util.Collections.singletonList" + argumentList.getText());
+ PsiReplacementUtil.replaceExpressionAndShorten(methodCallExpression, "java.util.Collections.singletonList" + argumentList.getText());
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java
index ce85003..1a560a0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/BooleanConstructorInspection.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.
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NonNls;
@@ -127,7 +128,7 @@
}
newExpression = buildText(argument, methodFound);
}
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
@NonNls
@@ -172,7 +173,7 @@
if (expressions.length != 1) {
return;
}
- registerError(expression);
+ registerNewExpressionError(expression);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java
index f360ad1..997e57b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleGetterInClassInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -131,14 +132,14 @@
return;
}
if (variable.equals(field)) {
- replaceExpression(call, fieldName);
+ PsiReplacementUtil.replaceExpression(call, fieldName);
}
else {
- replaceExpression(call, "this." + fieldName);
+ PsiReplacementUtil.replaceExpression(call, "this." + fieldName);
}
}
else {
- replaceExpression(call, qualifier.getText() + '.' + fieldName);
+ PsiReplacementUtil.replaceExpression(call, qualifier.getText() + '.' + fieldName);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java
index 1572b1b..bfcf47c 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CallToSimpleSetterInClassInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -137,11 +138,11 @@
else {
newExpression = "this." + fieldName + " = " + argument.getText();
}
- replaceExpression(call, newExpression);
+ PsiReplacementUtil.replaceExpression(call, newExpression);
}
else {
final String newExpression = qualifier.getText() + '.' + fieldName + " = " + argument.getText();
- replaceExpression(call, newExpression);
+ PsiReplacementUtil.replaceExpression(call, newExpression);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspection.java
index 0010383..5a03626 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 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.
@@ -15,19 +15,39 @@
*/
package com.siyeh.ig.performance;
-import com.intellij.psi.PsiExpression;
-import com.intellij.psi.PsiExpressionList;
-import com.intellij.psi.PsiNewExpression;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
-import com.siyeh.ig.psiutils.CollectionUtils;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.HashSet;
+import java.util.Set;
public class CollectionsMustHaveInitialCapacityInspection
extends BaseInspection {
+ @NonNls
+ private static final Set<String> collectionClassesRequiringCapacity = new HashSet<String>();
+ static {
+ collectionClassesRequiringCapacity.add("java.util.concurrent.ConcurrentHashMap");
+ collectionClassesRequiringCapacity.add("java.util.concurrent.PriorityBlockingQueue");
+ collectionClassesRequiringCapacity.add("java.util.ArrayDeque");
+ collectionClassesRequiringCapacity.add("java.util.ArrayList");
+ collectionClassesRequiringCapacity.add("java.util.BitSet");
+ collectionClassesRequiringCapacity.add("java.util.HashMap");
+ collectionClassesRequiringCapacity.add("java.util.Hashtable");
+ collectionClassesRequiringCapacity.add("java.util.HashSet");
+ collectionClassesRequiringCapacity.add("java.util.IdentityHashMap");
+ collectionClassesRequiringCapacity.add("java.util.LinkedHashMap");
+ collectionClassesRequiringCapacity.add("java.util.LinkedHashSet");
+ collectionClassesRequiringCapacity.add("java.util.PriorityQueue");
+ collectionClassesRequiringCapacity.add("java.util.Vector");
+ collectionClassesRequiringCapacity.add("java.util.WeakHashMap");
+ }
+
@Override
@NotNull
public String getID() {
@@ -60,22 +80,27 @@
public void visitNewExpression(@NotNull PsiNewExpression expression) {
super.visitNewExpression(expression);
final PsiType type = expression.getType();
-
- if (type == null) {
- return;
- }
- if (!CollectionUtils.isCollectionWithInitialCapacity(type)) {
+ if (!isCollectionWithInitialCapacity(type)) {
return;
}
final PsiExpressionList argumentList = expression.getArgumentList();
- if (argumentList == null) {
+ if (argumentList == null || argumentList.getExpressions().length != 0) {
return;
}
- final PsiExpression[] parameters = argumentList.getExpressions();
- if (parameters.length != 0) {
- return;
+ registerNewExpressionError(expression);
+ }
+
+ public static boolean isCollectionWithInitialCapacity(@Nullable PsiType type) {
+ if (!(type instanceof PsiClassType)) {
+ return false;
}
- registerError(expression);
+ final PsiClassType classType = (PsiClassType)type;
+ final PsiClass resolved = classType.resolve();
+ if (resolved == null) {
+ return false;
+ }
+ final String className = resolved.getQualifiedName();
+ return collectionClassesRequiringCapacity.contains(className);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java
index ada80c6..c636a65 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ConstantStringInternInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -81,7 +82,7 @@
return;
}
final String qualifierText = qualifier.getText();
- replaceExpression(call, qualifierText);
+ PsiReplacementUtil.replaceExpression(call, qualifierText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java
index 0c199c4..2599327 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassMayBeStaticInspection.java
@@ -58,7 +58,8 @@
}
private static class InnerClassMayBeStaticFix extends InspectionGadgetsFix {
- @Override
+
+ @Override
@NotNull
public String getFamilyName() {
return getName();
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassReferenceVisitor.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassReferenceVisitor.java
index 46aca8e..45d89b4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassReferenceVisitor.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InnerClassReferenceVisitor.java
@@ -35,10 +35,11 @@
}
private boolean isClassStaticallyAccessible(PsiClass aClass) {
- if (aClass.getContainingClass() != null && aClass.hasModifierProperty(PsiModifier.STATIC)) {
- if (!PsiTreeUtil.isAncestor(aClass, innerClass, false)) {
- return true;
- }
+ if (PsiTreeUtil.isAncestor(innerClass, aClass, false)) {
+ return true;
+ }
+ if (aClass.getContainingClass() != null) {
+ return aClass.hasModifierProperty(PsiModifier.STATIC);
}
if (InheritanceUtil.isInheritorOrSelf(innerClass, aClass, true)) {
return true;
@@ -136,18 +137,13 @@
else if (element instanceof PsiLocalVariable || element instanceof PsiParameter) {
final PsiElement containingMethod = PsiTreeUtil.getParentOfType(reference, PsiMethod.class);
final PsiElement referencedMethod = PsiTreeUtil.getParentOfType(element, PsiMethod.class);
- if (containingMethod != null && referencedMethod != null &&
- !containingMethod.equals(referencedMethod)) {
+ if (containingMethod != null && referencedMethod != null && !containingMethod.equals(referencedMethod)) {
referencesStaticallyAccessible = false;
}
}
- else if ((element instanceof PsiClass)) {
+ else if (element instanceof PsiClass) {
final PsiClass aClass = (PsiClass)element;
- final PsiElement scope = aClass.getScope();
- if (!(scope instanceof PsiClass)) {
- return;
- }
- referencesStaticallyAccessible &= aClass.hasModifierProperty(PsiModifier.STATIC);
+ referencesStaticallyAccessible &= isClassStaticallyAccessible(aClass);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java
index 9a001ed..20d2940 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/InstantiatingObjectToGetClassObjectInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.StringUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -86,8 +87,8 @@
if (type == null) {
return;
}
- replaceExpression(expression,
- getTypeText(type, new StringBuilder()) + ".class");
+ PsiReplacementUtil.replaceExpression(expression,
+ getTypeText(type, new StringBuilder()) + ".class");
}
private static StringBuilder getTypeText(PsiType type,
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java
index 053113b..6979f12 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/KeySetIterationMayUseEntrySetInspection.java
@@ -27,6 +27,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import org.jetbrains.annotations.Nls;
@@ -109,8 +110,8 @@
(PsiReferenceExpression)qualifier;
map = reference.resolve();
final String qualifierText = qualifier.getText();
- replaceExpression(referenceExpression,
- qualifierText + ".entrySet()");
+ PsiReplacementUtil.replaceExpression(referenceExpression,
+ qualifierText + ".entrySet()");
}
else if (element instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression =
@@ -126,8 +127,8 @@
(PsiReferenceExpression)qualifier;
map = referenceExpression.resolve();
final String qualifierText = qualifier.getText();
- replaceExpression(methodCallExpression,
- qualifierText + ".entrySet()");
+ PsiReplacementUtil.replaceExpression(methodCallExpression,
+ qualifierText + ".entrySet()");
}
else {
return;
@@ -192,10 +193,10 @@
collector.getParameterAccesses();
for (PsiExpression access : accesses) {
if (access instanceof PsiMethodCallExpression) {
- replaceExpression(access, variableName + ".getValue()");
+ PsiReplacementUtil.replaceExpression(access, variableName + ".getValue()");
}
else {
- replaceExpression(access, variableName + ".getKey()");
+ PsiReplacementUtil.replaceExpression(access, variableName + ".getKey()");
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java
index 3207f5b..13324bd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringInIndexOfInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -95,7 +96,7 @@
else {
charLiteral = '\'' + character + '\'';
}
- replaceExpression(expression, charLiteral);
+ PsiReplacementUtil.replaceExpression(expression, charLiteral);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java
index b776bd5..b3a0052 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/LengthOneStringsInConcatenationInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -94,7 +95,7 @@
else {
charLiteral = '\'' + character + '\'';
}
- replaceExpression(expression, charLiteral);
+ PsiReplacementUtil.replaceExpression(expression, charLiteral);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java
index cfb3199..eec4d3f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.SideEffectChecker;
@@ -91,7 +92,7 @@
if (newExpression == null) {
return;
}
- replaceStatement(forStatement, newExpression);
+ PsiReplacementUtil.replaceStatement(forStatement, newExpression);
}
@Nullable
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java
index 2c26bd5..a3ef61a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayToCollectionCopyInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.SideEffectChecker;
@@ -89,8 +90,8 @@
if (newExpression == null) {
return;
}
- replaceStatementAndShortenClassNames(forStatement,
- newExpression);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(forStatement,
+ newExpression);
}
else {
final PsiForeachStatement foreachStatement =
@@ -99,8 +100,8 @@
if (newExpression == null) {
return;
}
- replaceStatementAndShortenClassNames(foreachStatement,
- newExpression);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(foreachStatement,
+ newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java
index 15919d4..e0024e0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ObjectAllocationInLoopInspection.java
@@ -71,7 +71,7 @@
if (isAllocatedOnlyOnce(expression)) {
return;
}
- registerError(expression);
+ registerNewExpressionError(expression);
}
private static boolean isAllocatedOnlyOnce(
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java
index e904f47..8f5c30f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/RandomDoubleForRandomIntegerInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -111,8 +112,8 @@
assert multiplierExpression != null;
final String multiplierText = multiplierExpression.getText();
@NonNls final String nextInt = ".nextInt((int) ";
- replaceExpression(cast, qualifierText + nextInt + multiplierText +
- ')');
+ PsiReplacementUtil.replaceExpression(cast, qualifierText + nextInt + multiplierText +
+ ')');
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspection.java
index 554b2f3..ebc8c44 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspection.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.
@@ -72,7 +72,7 @@
if (args.length != 0) {
return;
}
- registerError(expression);
+ registerNewExpressionError(expression);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java
index 40e3ccf..3fd3b80 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringBufferToStringInConcatenationInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
@@ -82,7 +83,7 @@
final PsiExpression qualifier = expression.getQualifierExpression();
assert qualifier != null;
final String newExpression = qualifier.getText();
- replaceExpression(methodCall, newExpression);
+ PsiReplacementUtil.replaceExpression(methodCall, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java
index 1390475..32ce2f3 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringConstructorInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -124,7 +125,7 @@
else {
argText = "\"\"";
}
- replaceExpression(expression, argText);
+ PsiReplacementUtil.replaceExpression(expression, argText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java
index 8a87343..ebd8449 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringEqualsEmptyStringInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.TypeUtils;
@@ -145,7 +146,7 @@
newExpression.append(variableText).append(".length()==0");
}
}
- replaceExpression(expressionToReplace, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(expressionToReplace, newExpression.toString());
}
private String getRemainingText(PsiExpression expression) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java
index 2376f75..4556e1b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/StringToStringInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class StringToStringInspection extends BaseInspection {
@@ -89,7 +90,7 @@
return;
}
final String qualifierText = qualifier.getText();
- replaceExpression(call, qualifierText);
+ PsiReplacementUtil.replaceExpression(call, qualifierText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java
index 7ed0a20..84d82d9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/SubstringZeroInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -80,7 +81,7 @@
return;
}
final String qualifierText = qualifier.getText();
- replaceExpression(call, qualifierText);
+ PsiReplacementUtil.replaceExpression(call, qualifierText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java
index 628503d..1fc44f0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/TrivialStringConcatenationInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
@@ -163,7 +164,7 @@
return;
}
final String newExpression = calculateReplacementExpression(expression);
- replaceExpression((PsiExpression)parent, newExpression);
+ PsiReplacementUtil.replaceExpression((PsiExpression)parent, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java
index 6295e1b..1a2d99b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionFromStringInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -164,7 +165,7 @@
if (newExpression == null) {
return;
}
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java
index d4e814a..ff2a743 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/UnnecessaryTemporaryOnConversionToStringInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -128,7 +129,7 @@
if (newExpression == null) {
return;
}
- replaceExpression(expression, newExpression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BoolUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BoolUtils.java
index 9e86ba9..8d58520 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BoolUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/BoolUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -40,6 +41,7 @@
return ParenthesesUtils.stripParentheses(operand);
}
+ @NotNull
public static String getNegatedExpressionText(@Nullable PsiExpression condition) {
if (condition == null) {
return "";
@@ -89,19 +91,21 @@
}
}
+ @Contract(value = "null -> false", pure = true)
public static boolean isTrue(@Nullable PsiExpression expression) {
+ expression = ParenthesesUtils.stripParentheses(expression);
if (expression == null) {
return false;
}
- final String text = expression.getText();
- return PsiKeyword.TRUE.equals(text);
+ return PsiKeyword.TRUE.equals(expression.getText());
}
+ @Contract(value ="null -> false", pure = true)
public static boolean isFalse(@Nullable PsiExpression expression) {
+ expression = ParenthesesUtils.stripParentheses(expression);
if (expression == null) {
return false;
}
- final String text = expression.getText();
- return PsiKeyword.FALSE.equals(text);
+ return PsiKeyword.FALSE.equals(expression.getText());
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java
index 03ab992..40daa33 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/ClassUtils.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.
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import java.util.HashSet;
@@ -148,7 +149,8 @@
return inSamePackage(fieldClass, fromClass);
}
- public static boolean isPrimitiveNumericType(PsiType type) {
+ @Contract("null -> false")
+ public static boolean isPrimitiveNumericType(@Nullable PsiType type) {
return primitiveNumericTypes.contains(type);
}
@@ -204,21 +206,4 @@
final PsiClass parentClass = (PsiClass)parent;
return !parentClass.isInterface();
}
-
- public static boolean isClassVisibleFromClass(PsiClass baseClass,
- PsiClass referencedClass) {
- if (referencedClass.hasModifierProperty(PsiModifier.PUBLIC)) {
- return true;
- }
- else if (referencedClass.hasModifierProperty(PsiModifier.PROTECTED)) {
- return inSamePackage(baseClass, referencedClass);
- }
- else if (referencedClass.hasModifierProperty(PsiModifier.PRIVATE)) {
- return PsiTreeUtil.findCommonParent(baseClass, referencedClass) !=
- null;
- }
- else {
- return inSamePackage(baseClass, referencedClass);
- }
- }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java
index 6455804..e54b578 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CloneUtils.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.
@@ -44,7 +44,10 @@
return false;
}
- public static boolean isClone(@NotNull PsiMethod method) {
+ public static boolean isClone(@Nullable PsiMethod method) {
+ if (method == null) {
+ return false;
+ }
final PsiClassType javaLangObject;
if (!PsiUtil.isLanguageLevel5OrHigher(method)) {
javaLangObject = TypeUtils.getObjectType(method);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CollectionUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CollectionUtils.java
index 8841763..6964a6d 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CollectionUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CollectionUtils.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.
@@ -16,6 +16,8 @@
package com.siyeh.ig.psiutils;
import com.intellij.psi.*;
+import com.intellij.psi.util.InheritanceUtil;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,16 +32,6 @@
/**
* @noinspection StaticCollection
*/
- @NonNls private static final Set<String> s_collectionClassesRequiringCapacity =
- new HashSet<String>();
- /**
- * @noinspection StaticCollection
- */
- @NonNls private static final Set<String> s_allCollectionClasses =
- new HashSet<String>();
- /**
- * @noinspection StaticCollection
- */
@NonNls private static final Set<String> s_allCollectionClassesAndInterfaces =
new HashSet<String>();
/**
@@ -49,46 +41,6 @@
new HashMap<String, String>();
static {
- s_collectionClassesRequiringCapacity.add("java.util.BitSet");
- s_collectionClassesRequiringCapacity.add("java.util.Vector");
- s_collectionClassesRequiringCapacity.add("java.util.ArrayList");
- s_collectionClassesRequiringCapacity.add("java.util.HashMap");
- s_collectionClassesRequiringCapacity.add("java.util.LinkedHashMap");
- s_collectionClassesRequiringCapacity.add("java.util.WeakHashMap");
- s_collectionClassesRequiringCapacity.add("java.util.Hashtable");
- s_collectionClassesRequiringCapacity.add("java.util.HashSet");
- s_collectionClassesRequiringCapacity.add("java.util.LinkedHashSet");
- s_collectionClassesRequiringCapacity.add("com.sun.java.util.collections.BitSet");
- s_collectionClassesRequiringCapacity.add("com.sun.java.util.collections.Vector");
- s_collectionClassesRequiringCapacity.add("com.sun.java.util.collections.ArrayList");
- s_collectionClassesRequiringCapacity.add("com.sun.java.util.collections.HashMap");
- s_collectionClassesRequiringCapacity.add("com.sun.java.util.collections.Hashtable");
- s_collectionClassesRequiringCapacity.add("com.sun.java.util.collections.HashSet");
-
- s_allCollectionClasses.add("java.util.ArrayList");
- s_allCollectionClasses.add("java.util.EnumMap");
- s_allCollectionClasses.add("java.util.EnumSet");
- s_allCollectionClasses.add("java.util.HashMap");
- s_allCollectionClasses.add("java.util.HashSet");
- s_allCollectionClasses.add("java.util.Hashtable");
- s_allCollectionClasses.add("java.util.IdentityHashMap");
- s_allCollectionClasses.add("java.util.LinkedHashMap");
- s_allCollectionClasses.add("java.util.LinkedHashSet");
- s_allCollectionClasses.add("java.util.LinkedList");
- s_allCollectionClasses.add("java.util.PriorityQueue");
- s_allCollectionClasses.add("java.util.TreeMap");
- s_allCollectionClasses.add("java.util.TreeSet");
- s_allCollectionClasses.add("java.util.Vector");
- s_allCollectionClasses.add("java.util.WeakHashMap");
- s_allCollectionClasses.add("com.sun.java.util.collections.ArrayList");
- s_allCollectionClasses.add("com.sun.java.util.collections.HashMap");
- s_allCollectionClasses.add("com.sun.java.util.collections.HashSet");
- s_allCollectionClasses.add("com.sun.java.util.collections.Hashtable");
- s_allCollectionClasses.add("com.sun.java.util.collections.TreeMap");
- s_allCollectionClasses.add("com.sun.java.util.collections.TreeSet");
- s_allCollectionClasses.add("com.sun.java.util.collections.LinkedList");
- s_allCollectionClasses.add("com.sun.java.util.collections.Vector");
-
s_allCollectionClassesAndInterfaces.add("java.util.AbstractCollection");
s_allCollectionClassesAndInterfaces.add("java.util.AbstractList");
s_allCollectionClassesAndInterfaces.add("java.util.AbstractMap");
@@ -175,8 +127,8 @@
super();
}
- public static boolean isCollectionWithInitialCapacity(
- @Nullable PsiType type) {
+ @Contract("null -> false")
+ public static boolean isConcreteCollectionClass(@Nullable PsiType type) {
if (!(type instanceof PsiClassType)) {
return false;
}
@@ -185,25 +137,21 @@
if (resolved == null) {
return false;
}
- final String className = resolved.getQualifiedName();
- return s_collectionClassesRequiringCapacity.contains(className);
+ return isConcreteCollectionClass(resolved);
}
- public static boolean isCollectionClass(@Nullable PsiType type) {
- if (!(type instanceof PsiClassType)) {
+ @Contract("null -> false")
+ public static boolean isConcreteCollectionClass(PsiClass aClass) {
+ if (aClass == null || aClass.isEnum() || aClass.isInterface() || aClass.isAnnotationType() ||
+ aClass.hasModifierProperty(PsiModifier.ABSTRACT)) {
return false;
}
- final PsiClassType classType = (PsiClassType)type;
- final PsiClass resolved = classType.resolve();
- if (resolved == null) {
+ if (!InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_COLLECTION) &&
+ !InheritanceUtil.isInheritor(aClass, CommonClassNames.JAVA_UTIL_MAP)) {
return false;
}
- return isCollectionClass(resolved);
- }
-
- public static boolean isCollectionClass(PsiClass aClass) {
- final String className = aClass.getQualifiedName();
- return s_allCollectionClasses.contains(className);
+ @NonNls final String name = aClass.getQualifiedName();
+ return name != null && name.startsWith("java.util.");
}
public static boolean isCollectionClassOrInterface(@Nullable PsiType type) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java
index c7a8993..e6f88ab 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/EquivalenceChecker.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.
@@ -27,72 +27,6 @@
private EquivalenceChecker() {}
- public static boolean modifierListsAreEquivalent(
- @Nullable PsiModifierList list1, @Nullable PsiModifierList list2) {
- if (list1 == null) {
- return list2 == null;
- }
- else if (list2 == null) {
- return false;
- }
- final PsiAnnotation[] annotations = list1.getAnnotations();
- for (PsiAnnotation annotation : annotations) {
- final String qualifiedName = annotation.getQualifiedName();
- if (qualifiedName == null) {
- return false;
- }
- if (list2.findAnnotation(qualifiedName) == null) {
- return false;
- }
- }
- if (list1.hasModifierProperty(PsiModifier.ABSTRACT) &&
- !list2.hasModifierProperty(PsiModifier.ABSTRACT)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.FINAL) &&
- !list2.hasModifierProperty(PsiModifier.FINAL)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.NATIVE) &&
- !list2.hasModifierProperty(PsiModifier.NATIVE)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) &&
- !list2.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.PRIVATE) &&
- !list2.hasModifierProperty(PsiModifier.PRIVATE)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.PROTECTED) &&
- !list2.hasModifierProperty(PsiModifier.PROTECTED)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.PUBLIC) &&
- !list2.hasModifierProperty(PsiModifier.PUBLIC)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.STATIC) &&
- !list2.hasModifierProperty(PsiModifier.STATIC)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.STRICTFP) &&
- !list2.hasModifierProperty(PsiModifier.STRICTFP)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.SYNCHRONIZED) &&
- !list2.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
- return false;
- }
- if (list1.hasModifierProperty(PsiModifier.TRANSIENT) &&
- !list2.hasModifierProperty(PsiModifier.TRANSIENT)) {
- return false;
- }
- return !(list1.hasModifierProperty(PsiModifier.VOLATILE) &&
- !list2.hasModifierProperty(PsiModifier.VOLATILE));
- }
-
public static boolean statementsAreEquivalent(@Nullable PsiStatement statement1, @Nullable PsiStatement statement2) {
if (statement1 == null) {
return statement2 == null;
@@ -658,7 +592,7 @@
}
}
else {
- return element2 == null;
+ return false; // incomplete code
}
if (element1 instanceof PsiMember) {
final PsiMember member1 = (PsiMember)element1;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java
index 7058d97..c32e3a1 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodCallUtils.java
@@ -79,7 +79,7 @@
}
final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(expression.getProject());
final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiType[] parameterTypes = new PsiType[parameterTypeStrings.length];
+ final PsiType[] parameterTypes = PsiType.createArray(parameterTypeStrings.length);
final GlobalSearchScope scope = expression.getResolveScope();
for (int i = 0; i < parameterTypeStrings.length; i++) {
final String parameterTypeString = parameterTypeStrings[i];
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodUtils.java
index 248305f..7e51680 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/MethodUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -187,7 +187,7 @@
final PsiElementFactory factory = psiFacade.getElementFactory();
try {
if (parameterTypeStrings != null) {
- final PsiType[] parameterTypes = new PsiType[parameterTypeStrings.length];
+ final PsiType[] parameterTypes = PsiType.createArray(parameterTypeStrings.length);
for (int i = 0; i < parameterTypeStrings.length; i++) {
final String parameterTypeString = parameterTypeStrings[i];
parameterTypes[i] = factory.createTypeFromText(parameterTypeString, method);
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java
index 3e3381c..cf21332 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TestUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -33,18 +33,17 @@
private TestUtils() {
}
- public static boolean isTest(@Nullable PsiClass aClass) {
- if (aClass == null) {
+ public static boolean isInTestSourceContent(@Nullable PsiElement element) {
+ if (element == null) {
return false;
}
- final PsiFile file = aClass.getContainingFile();
+ final PsiFile file = element.getContainingFile();
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) {
return true;
}
- final Project project = aClass.getProject();
- final ProjectRootManager rootManager =
- ProjectRootManager.getInstance(project);
+ final Project project = element.getProject();
+ final ProjectRootManager rootManager = ProjectRootManager.getInstance(project);
final ProjectFileIndex fileIndex = rootManager.getFileIndex();
return fileIndex.isInTestSourceContent(virtualFile);
}
@@ -110,6 +109,9 @@
return true;
}
final PsiClass containingClass = PsiTreeUtil.getParentOfType(element, PsiClass.class);
- return containingClass != null && TestFrameworks.getInstance().isTestClass(containingClass);
+ if (containingClass != null && TestFrameworks.getInstance().isTestOrConfig(containingClass)) {
+ return true;
+ }
+ return isInTestSourceContent(element);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java
index 51a6504..eacce59 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/TypeUtils.java
@@ -65,10 +65,10 @@
return getType(CommonClassNames.JAVA_LANG_STRING, context);
}
- public static boolean isNarrowingConversion(PsiType operandType, PsiType castType) {
+ public static boolean isNarrowingConversion(@NotNull PsiType operandType, @NotNull PsiType castType) {
final Integer operandPrecision = typePrecisions.get(operandType);
final Integer castPrecision = typePrecisions.get(castType);
- return operandPrecision.intValue() > castPrecision.intValue();
+ return operandPrecision != null && castPrecision != null && operandPrecision.intValue() > castPrecision.intValue();
}
public static boolean isJavaLangObject(@Nullable PsiType targetType) {
@@ -95,19 +95,7 @@
}
public static boolean expressionHasTypeOrSubtype(@Nullable PsiExpression expression, @NonNls @NotNull String typeName) {
- if (expression == null) {
- return false;
- }
- final PsiType type = expression.getType();
- if (type == null) {
- return false;
- }
- if (!(type instanceof PsiClassType)) {
- return false;
- }
- final PsiClassType classType = (PsiClassType)type;
- final PsiClass aClass = classType.resolve();
- return aClass != null && InheritanceUtil.isInheritor(aClass, typeName);
+ return expressionHasTypeOrSubtype(expression, new String[] {typeName}) != null;
}
//getTypeIfOneOfOrSubtype
@@ -115,7 +103,10 @@
if (expression == null) {
return null;
}
- final PsiType type = expression.getType();
+ PsiType type = expression.getType();
+ if (type instanceof PsiLambdaExpressionType) {
+ type = ((PsiLambdaExpressionType)type).getExpression().getFunctionalInterfaceType();
+ }
if (type == null) {
return null;
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java
index 8326614..ce80b09 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/redundancy/UnusedLabelInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class UnusedLabelInspection extends BaseInspection {
@@ -81,7 +82,7 @@
return;
}
final String statementText = statement.getText();
- replaceStatement(labeledStatement, statementText);
+ PsiReplacementUtil.replaceStatement(labeledStatement, statementText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java
index 5113ab2..d82b020 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/CallToStringConcatCanBeReplacedByOperatorInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.MethodCallUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
@@ -104,7 +105,7 @@
@NonNls
final String newExpression =
qualifier.getText() + '+' + argument.getText();
- replaceExpression(methodCallExpression, newExpression);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java
index d983cda..5ea4718 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnLHSOfComparisonInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
@@ -87,7 +88,7 @@
final PsiExpression lhs = expression.getLOperand();
final String rhsText = rhs.getText();
final String lhsText = lhs.getText();
- replaceExpression(expression, rhsText + ' ' + flippedComparison + ' ' + lhsText);
+ PsiReplacementUtil.replaceExpression(expression, rhsText + ' ' + flippedComparison + ' ' + lhsText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java
index b0814a5..fce3be4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ConstantOnRHSOfComparisonInspection.java
@@ -25,6 +25,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
@@ -86,7 +87,7 @@
final PsiExpression lhs = expression.getLOperand();
final String rhsText = rhs.getText();
final String lhsText = lhs.getText();
- replaceExpression(expression, rhsText + ' ' + flippedComparison + ' ' + lhsText);
+ PsiReplacementUtil.replaceExpression(expression, rhsText + ' ' + flippedComparison + ' ' + lhsText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java
index e4ea3d0..78804d9 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ControlFlowStatementWithoutBracesInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -104,7 +105,7 @@
}
final String newStatementText =
"{\n" + statementWithoutBraces.getText() + "\n}";
- replaceStatement(statementWithoutBraces, newStatementText);
+ PsiReplacementUtil.replaceStatement(statementWithoutBraces, newStatementText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java
index ca343d0..b1f2bca 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/EqualsCalledOnEnumConstantInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.MethodCallUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.Nls;
@@ -113,10 +114,10 @@
newExpression.append(arguments[0].getText());
}
if (not) {
- replaceExpression(prefixExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(prefixExpression, newExpression.toString());
}
else {
- replaceExpression(methodCallExpression, newExpression.toString());
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression.toString());
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java
index ba1ae8d..7bab0bd 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/ListIndexOfReplaceableByContainsInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
@@ -102,7 +103,7 @@
createContainsExpressionText(callExpression, true,
expression.getOperationTokenType());
}
- replaceExpression(expression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(expression, newExpressionText);
}
@Override
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java
index 3da1133..94e9e6e 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/LiteralAsArgToStringEqualsInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -105,7 +106,7 @@
callString = strippedArg.getText() + '.' + methodName + '(' +
strippedTarget.getText() + ')';
}
- replaceExpression(expression, callString);
+ PsiReplacementUtil.replaceExpression(expression, callString);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspectionBase.java
index f43b9d1..768fea7 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/SizeReplaceableByIsEmptyInspectionBase.java
@@ -28,6 +28,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NonNls;
@@ -93,7 +94,7 @@
newExpression = '!' + newExpression;
}
newExpression += ".isEmpty()";
- replaceExpression(binaryExpression, newExpression);
+ PsiReplacementUtil.replaceExpression(binaryExpression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
index 3ab8cee..ab67542 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/StringBufferReplaceableByStringInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -93,7 +94,7 @@
final PsiExpression stringBuilderExpression = getCompleteExpression(parent);
final StringBuilder stringExpression = buildStringExpression(stringBuilderExpression, new StringBuilder());
if (stringExpression != null && stringBuilderExpression != null) {
- replaceExpression(stringBuilderExpression, stringExpression.toString());
+ PsiReplacementUtil.replaceExpression(stringBuilderExpression, stringExpression.toString());
}
}
return;
@@ -144,7 +145,7 @@
expression.getParent().delete();
}
final PsiMethodCallExpression lastExpression = expressions.get(expressions.size() - 1);
- replaceExpression(lastExpression, stringExpression.toString());
+ PsiReplacementUtil.replaceExpression(lastExpression, stringExpression.toString());
}
@Nullable
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java
index 7e15221..4a74f05 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnclearBinaryExpressionInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -72,7 +73,7 @@
}
final PsiExpression expression = (PsiExpression)element;
final StringBuilder newExpressionText = createReplacementText(expression, new StringBuilder());
- replaceExpression(expression, newExpressionText.toString());
+ PsiReplacementUtil.replaceExpression(expression, newExpressionText.toString());
}
private static StringBuilder createReplacementText(@Nullable PsiExpression expression, StringBuilder out) {
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java
index 09bcd89..e33db81 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspection.java
@@ -87,6 +87,9 @@
@Override
public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
super.visitReferenceElement(reference);
+ if (reference instanceof PsiMethodReferenceExpression) {
+ return;
+ }
final PsiElement qualifier = reference.getQualifier();
if (!(qualifier instanceof PsiJavaCodeReferenceElement)) {
return;
@@ -114,8 +117,7 @@
registerError(qualifier, ProblemHighlightType.LIKE_UNUSED_SYMBOL, member);
}
- private static boolean isReferenceCorrectWithoutQualifier(
- PsiJavaCodeReferenceElement reference, PsiMember member) {
+ private static boolean isReferenceCorrectWithoutQualifier(PsiJavaCodeReferenceElement reference, PsiMember member) {
final String referenceName = reference.getReferenceName();
if (referenceName == null) {
return false;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java
index 8b6091e..0c3474b 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryCallToStringValueOfInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.TypeUtils;
@@ -94,7 +95,7 @@
if (arguments.length != 1) {
return;
}
- replaceExpression(methodCallExpression, calculateReplacementText(arguments[0]));
+ PsiReplacementUtil.replaceExpression(methodCallExpression, calculateReplacementText(arguments[0]));
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java
index ae6faa9..d120d66 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryQualifierForThisInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
@@ -76,7 +77,7 @@
final PsiElement qualifier = descriptor.getPsiElement();
final PsiThisExpression thisExpression =
(PsiThisExpression)qualifier.getParent();
- replaceExpression(thisExpression, PsiKeyword.THIS);
+ PsiReplacementUtil.replaceExpression(thisExpression, PsiKeyword.THIS);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java
index b5a4f53..72ad69a 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryThisInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.VariableSearchUtils;
import org.jetbrains.annotations.NotNull;
@@ -85,7 +86,7 @@
if (newExpression == null) {
return;
}
- replaceExpression(thisExpression, newExpression);
+ PsiReplacementUtil.replaceExpression(thisExpression, newExpression);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
index d920c31..6e82801 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnnecessaryToStringCallInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
@@ -86,7 +87,7 @@
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (qualifier == null) {
- replaceExpression(methodCallExpression, "this");
+ PsiReplacementUtil.replaceExpression(methodCallExpression, "this");
} else {
methodCallExpression.replace(qualifier);
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspectionBase.java
index ced77f8..06b72fe 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspectionBase.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,10 +23,6 @@
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
public class UnqualifiedInnerClassAccessInspectionBase extends BaseInspection {
@SuppressWarnings({"PublicField"})
public boolean ignoreReferencesToLocalInnerClasses = false;
@@ -49,55 +45,6 @@
return new UnqualifiedInnerClassAccessVisitor();
}
- protected static class ReferenceCollector extends JavaRecursiveElementVisitor {
-
- private final String name;
- private final boolean onDemand;
- private final Set<PsiJavaCodeReferenceElement> references = new HashSet<PsiJavaCodeReferenceElement>();
-
- ReferenceCollector(String name, boolean onDemand) {
- this.name = name;
- this.onDemand = onDemand;
- }
-
- @Override
- public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
- super.visitReferenceElement(reference);
- if (reference.isQualified()) {
- return;
- }
- final PsiElement target = reference.resolve();
- if (!(target instanceof PsiClass)) {
- return;
- }
- final PsiClass aClass = (PsiClass)target;
- if (!onDemand) {
- final String qualifiedName = aClass.getQualifiedName();
- if (name.equals(qualifiedName)) {
- references.add(reference);
- }
- return;
- }
- final PsiClass containingClass = aClass.getContainingClass();
- if (containingClass == null) {
- return;
- }
- final String qualifiedName = containingClass.getQualifiedName();
- if (name.equals(qualifiedName)) {
- references.add(reference);
- }
- }
-
- @Override
- public void visitReferenceExpression(PsiReferenceExpression expression) {
- visitReferenceElement(expression);
- }
-
- public Collection<PsiJavaCodeReferenceElement> getReferences() {
- return references;
- }
- }
-
private class UnqualifiedInnerClassAccessVisitor extends BaseInspectionVisitor {
@Override
@@ -111,6 +58,9 @@
return;
}
final PsiClass aClass = (PsiClass)target;
+ if (!aClass.hasModifierProperty(PsiModifier.STATIC) && reference.getParent() instanceof PsiNewExpression) {
+ return;
+ }
final PsiClass containingClass = aClass.getContainingClass();
if (containingClass == null) {
return;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java
index 5a7d421..4db9cd4 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/style/UnqualifiedStaticUsageInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -135,7 +136,7 @@
assert containingClass != null;
final String className = containingClass.getName();
final String text = expression.getText();
- replaceExpression(expression, className + '.' + text);
+ PsiReplacementUtil.replaceExpression(expression, className + '.' + text);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java
index 290aefe..ea3e947 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ConditionSignalInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -84,12 +85,12 @@
.getQualifierExpression();
@NonNls final String signalAll = "signalAll";
if (qualifier == null) {
- replaceExpression(methodExpression, signalAll);
+ PsiReplacementUtil.replaceExpression(methodExpression, signalAll);
}
else {
final String qualifierText = qualifier.getText();
- replaceExpression(methodExpression,
- qualifierText + '.' + signalAll);
+ PsiReplacementUtil.replaceExpression(methodExpression,
+ qualifierText + '.' + signalAll);
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java
index d7127fc..5101f70 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ObjectNotifyInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class ObjectNotifyInspection extends BaseInspection {
@@ -81,14 +82,15 @@
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (qualifier == null) {
- replaceExpression(methodExpression,
- HardcodedMethodConstants.NOTIFY_ALL);
+ PsiReplacementUtil.replaceExpression(methodExpression,
+ HardcodedMethodConstants.NOTIFY_ALL);
}
else {
final String qualifierText = qualifier.getText();
- replaceExpression(methodExpression,
- qualifierText + '.' +
- HardcodedMethodConstants.NOTIFY_ALL);
+ PsiReplacementUtil.replaceExpression(methodExpression,
+ qualifierText + '.' +
+ HardcodedMethodConstants.NOTIFY_ALL
+ );
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java
index c25a23b..54dda14 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadRunInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import org.jetbrains.annotations.NotNull;
public class ThreadRunInspection extends BaseInspection {
@@ -78,11 +79,11 @@
final PsiExpression qualifier =
methodExpression.getQualifierExpression();
if (qualifier == null) {
- replaceExpression(methodExpression, "start");
+ PsiReplacementUtil.replaceExpression(methodExpression, "start");
}
else {
final String qualifierText = qualifier.getText();
- replaceExpression(methodExpression, qualifierText + ".start");
+ PsiReplacementUtil.replaceExpression(methodExpression, qualifierText + ".start");
}
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadWithDefaultRunMethodInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadWithDefaultRunMethodInspection.java
index 92e2073..249335f 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadWithDefaultRunMethodInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/threading/ThreadWithDefaultRunMethodInspection.java
@@ -56,81 +56,52 @@
@Override
public void visitNewExpression(@NotNull PsiNewExpression expression) {
super.visitNewExpression(expression);
- final PsiAnonymousClass anonymousClass =
- expression.getAnonymousClass();
-
+ final PsiAnonymousClass anonymousClass = expression.getAnonymousClass();
if (anonymousClass != null) {
- final PsiJavaCodeReferenceElement baseClassReference =
- anonymousClass.getBaseClassReference();
- final PsiElement referent = baseClassReference.resolve();
- if (referent == null) {
- return;
- }
- final PsiClass referencedClass = (PsiClass)referent;
- final String referencedClassName =
- referencedClass.getQualifiedName();
- if (!"java.lang.Thread".equals(referencedClassName)) {
- return;
- }
if (definesRun(anonymousClass)) {
return;
}
- final PsiExpressionList argumentList =
- expression.getArgumentList();
- if (argumentList == null) {
- return;
- }
- final PsiExpression[] arguments = argumentList.getExpressions();
- for (PsiExpression argument : arguments) {
- if (TypeUtils.expressionHasTypeOrSubtype(argument,
- "java.lang.Runnable")) {
- return;
- }
- }
- registerNewExpressionError(expression);
+ processExpression(expression, anonymousClass.getBaseClassReference());
}
else {
- final PsiJavaCodeReferenceElement classReference =
- expression.getClassReference();
+ final PsiJavaCodeReferenceElement classReference = expression.getClassReference();
if (classReference == null) {
return;
}
- final PsiElement referent = classReference.resolve();
- if (referent == null) {
- return;
- }
- final PsiClass referencedClass = (PsiClass)referent;
- final String referencedClassName =
- referencedClass.getQualifiedName();
- if (!"java.lang.Thread".equals(referencedClassName)) {
- return;
- }
- final PsiExpressionList argumentList =
- expression.getArgumentList();
- if (argumentList == null) {
- return;
- }
- final PsiExpression[] arguments = argumentList.getExpressions();
- for (PsiExpression argument : arguments) {
- if (TypeUtils.expressionHasTypeOrSubtype(argument,
- "java.lang.Runnable")) {
- return;
- }
- }
- registerNewExpressionError(expression);
+ processExpression(expression, classReference);
}
}
+ private void processExpression(PsiNewExpression expression, PsiJavaCodeReferenceElement baseClassReference) {
+ final PsiElement referent = baseClassReference.resolve();
+ if (referent == null) {
+ return;
+ }
+ final PsiClass referencedClass = (PsiClass)referent;
+ final String referencedClassName = referencedClass.getQualifiedName();
+ if (!"java.lang.Thread".equals(referencedClassName)) {
+ return;
+ }
+ final PsiExpressionList argumentList = expression.getArgumentList();
+ if (argumentList == null) {
+ return;
+ }
+ final PsiExpression[] arguments = argumentList.getExpressions();
+ for (PsiExpression argument : arguments) {
+ if (TypeUtils.expressionHasTypeOrSubtype(argument, "java.lang.Runnable")) {
+ return;
+ }
+ }
+
+ registerNewExpressionError(expression);
+ }
+
private static boolean definesRun(PsiAnonymousClass aClass) {
- final PsiMethod[] methods = aClass.getMethods();
+ final PsiMethod[] methods = aClass.findMethodsByName(HardcodedMethodConstants.RUN, false);
for (final PsiMethod method : methods) {
- final String methodName = method.getName();
- if (HardcodedMethodConstants.RUN.equals(methodName)) {
- final PsiParameterList parameterList =
- method.getParameterList();
- if (parameterList.getParametersCount() == 0) {
- return true;
- }
+ final PsiParameterList parameterList = method.getParameterList();
+ if (parameterList.getParametersCount() == 0) {
+ return true;
}
}
return false;
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java
index 26d6684..c0ac266 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousFieldAccessInspection.java
@@ -24,6 +24,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -82,7 +83,7 @@
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
final String newExpressionText = "super." + referenceExpression.getText();
- replaceExpression(referenceExpression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(referenceExpression, newExpressionText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java
index c2f335f..3956c39 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/AmbiguousMethodCallInspection.java
@@ -23,6 +23,7 @@
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -68,7 +69,7 @@
final PsiElement parent = element.getParent();
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)parent.getParent();
final String newExpressionText = "super." + methodCallExpression.getText();
- replaceExpression(methodCallExpression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpressionText);
}
}
diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionBase.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionBase.java
index 3c8ab36..2d752f0 100644
--- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionBase.java
+++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionBase.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -16,6 +16,7 @@
package com.siyeh.ig.visibility;
import com.intellij.psi.*;
+import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
@@ -26,8 +27,7 @@
@Override
@NotNull
public String getDisplayName() {
- return InspectionGadgetsBundle.message(
- "type.parameter.hides.visible.type.display.name");
+ return InspectionGadgetsBundle.message("type.parameter.hides.visible.type.display.name");
}
@Override
@@ -36,12 +36,24 @@
}
@Override
+ public boolean isEnabledByDefault() {
+ return true;
+ }
+
+ @Override
@NotNull
public String buildErrorString(Object... infos) {
final PsiClass aClass = (PsiClass)infos[0];
- return InspectionGadgetsBundle.message(
- "type.parameter.hides.visible.type.problem.descriptor",
- aClass.getQualifiedName());
+ if (aClass instanceof PsiTypeParameter) {
+ return InspectionGadgetsBundle.message("type.parameter.hides.type.parameter.problem.descriptor", aClass.getName());
+ }
+ else {
+ String name = aClass.getQualifiedName();
+ if (name == null) {
+ name = aClass.getName();
+ }
+ return InspectionGadgetsBundle.message("type.parameter.hides.visible.type.problem.descriptor", name);
+ }
}
@Override
@@ -49,28 +61,41 @@
return new TypeParameterHidesVisibleTypeVisitor();
}
- private static class TypeParameterHidesVisibleTypeVisitor
- extends BaseInspectionVisitor {
+ private static class TypeParameterHidesVisibleTypeVisitor extends BaseInspectionVisitor {
@Override
public void visitTypeParameter(PsiTypeParameter parameter) {
super.visitTypeParameter(parameter);
final String unqualifiedClassName = parameter.getName();
-
- final JavaPsiFacade manager = JavaPsiFacade.getInstance(parameter.getProject());
- final PsiFile containingFile = parameter.getContainingFile();
- final PsiResolveHelper resolveHelper = manager.getResolveHelper();
- final PsiClass aClass =
- resolveHelper.resolveReferencedClass(unqualifiedClassName,
- containingFile);
- if (aClass == null) {
+ PsiTypeParameterListOwner context = parameter.getOwner();
+ if (context == null) {
return;
}
- final PsiIdentifier identifier = parameter.getNameIdentifier();
- if (identifier == null) {
- return;
+ final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(parameter.getProject()).getResolveHelper();
+ while (true) {
+ if (context.hasModifierProperty(PsiModifier.STATIC)) {
+ return;
+ }
+ context = PsiTreeUtil.getParentOfType(context, PsiTypeParameterListOwner.class);
+ if (context == null) {
+ return;
+ }
+ final PsiClass aClass = resolveHelper.resolveReferencedClass(unqualifiedClassName, context);
+ if (aClass instanceof PsiTypeParameter) {
+ final PsiTypeParameter typeParameter = (PsiTypeParameter)aClass;
+ final PsiTypeParameterListOwner owner = typeParameter.getOwner();
+ if (owner == null) {
+ return;
+ }
+ if (!owner.equals(context)) {
+ continue;
+ }
+ }
+ if (aClass != null) {
+ registerClassError(parameter, aClass);
+ return;
+ }
}
- registerError(identifier, aClass);
}
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/FeatureEnvyInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/FeatureEnvyInspection.java
new file mode 100644
index 0000000..4694e06
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/FeatureEnvyInspection.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.abstraction;
+
+import com.intellij.psi.PsiElement;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class FeatureEnvyInspection extends FeatureEnvyInspectionBase {
+
+ @Nullable
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final PsiElement context = (PsiElement)infos[1];
+ return SuppressForTestsScopeFix.build(this, context);
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/MagicNumberInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/MagicNumberInspection.java
index 686bc2e..2dde368 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/MagicNumberInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/abstraction/MagicNumberInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -15,13 +15,27 @@
*/
package com.siyeh.ig.abstraction;
+import com.intellij.psi.PsiElement;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.IntroduceConstantFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.NotNull;
public class MagicNumberInspection extends MagicNumberInspectionBase {
+ @NotNull
@Override
- protected InspectionGadgetsFix buildFix(Object... infos) {
- return new IntroduceConstantFix();
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final PsiElement context = (PsiElement)infos[0];
+ final InspectionGadgetsFix fix = SuppressForTestsScopeFix.build(this, context);
+ if (fix == null) {
+ return new InspectionGadgetsFix[] {new IntroduceConstantFix()};
+ }
+ return new InspectionGadgetsFix[] {new IntroduceConstantFix(), fix};
+ }
+
+ @Override
+ protected boolean buildQuickFixesOnlyForOnTheFlyErrors() {
+ return true;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java
index 50923d3..e8d108f 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/encapsulation/ReturnOfCollectionFieldInspection.java
@@ -24,6 +24,7 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.HighlightUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -89,7 +90,7 @@
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
fixContainingMethodReturnType(referenceExpression);
- replaceExpressionAndShorten(referenceExpression, myReplacementText);
+ PsiReplacementUtil.replaceExpressionAndShorten(referenceExpression, myReplacementText);
}
private void fixContainingMethodReturnType(PsiReferenceExpression referenceExpression) {
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
index e37fee0..64252c2 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/BadExceptionDeclaredInspection.java
@@ -17,8 +17,11 @@
import com.intellij.codeInspection.ui.ListTable;
import com.intellij.codeInspection.ui.ListWrappingTableModel;
+import com.intellij.psi.PsiElement;
import com.intellij.util.ui.CheckBox;
import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
import com.siyeh.ig.ui.UiUtils;
import javax.swing.*;
@@ -27,6 +30,12 @@
public class BadExceptionDeclaredInspection extends BadExceptionDeclaredInspectionBase {
@Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final PsiElement context = (PsiElement)infos[0];
+ return SuppressForTestsScopeFix.build(this, context);
+ }
+
+ @Override
public JComponent createOptionsPanel() {
final JComponent panel = new JPanel(new GridBagLayout());
final ListTable table =
@@ -41,17 +50,12 @@
constraints.fill = GridBagConstraints.BOTH;
panel.add(tablePanel, constraints);
- final CheckBox checkBox1 =
- new CheckBox(InspectionGadgetsBundle.message("ignore.exceptions.declared.in.tests.option"), this,
- "ignoreTestCases");
- constraints.gridy = 1;
- constraints.weighty = 0.0;
- panel.add(checkBox1, constraints);
final CheckBox checkBox2 =
new CheckBox(InspectionGadgetsBundle.message("ignore.exceptions.declared.on.library.override.option"), this,
"ignoreLibraryOverrides");
- constraints.gridy = 2;
+ constraints.weighty = 0.0;
+ constraints.gridy = 1;
panel.add(checkBox2, constraints);
return panel;
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
new file mode 100644
index 0000000..354f321
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/EmptyCatchBlockInspection.java
@@ -0,0 +1,38 @@
+/*
+ * 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.siyeh.ig.errorhandling;
+
+import com.intellij.psi.PsiElement;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class EmptyCatchBlockInspection extends EmptyCatchBlockInspectionBase {
+
+ @NotNull
+ @Override
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final PsiElement context = (PsiElement)infos[0];
+ final SuppressForTestsScopeFix fix = SuppressForTestsScopeFix.build(this, context);
+ if (fix == null) {
+ return new InspectionGadgetsFix[] {buildFix(infos)};
+ }
+ return new InspectionGadgetsFix[] {buildFix(infos), fix};
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java
index 8528570..f315547 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadCatchInspection.java
@@ -29,6 +29,7 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -50,6 +51,11 @@
fixes.add(new AddCatchSectionFix(thrown));
}
}
+ final PsiElement context = (PsiElement)infos[1];
+ final InspectionGadgetsFix fix = SuppressForTestsScopeFix.build(this, context);
+ if (fix != null) {
+ fixes.add(fix);
+ }
return fixes.toArray(new InspectionGadgetsFix[fixes.size()]);
}
@@ -57,7 +63,6 @@
public JComponent createOptionsPanel() {
final MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
panel.addCheckbox(InspectionGadgetsBundle.message("too.broad.catch.option"), "onlyWarnOnRootExceptions");
- panel.addCheckbox(InspectionGadgetsBundle.message("ignore.in.test.code"), "ignoreInTestCode");
panel.addCheckbox(InspectionGadgetsBundle.message("overly.broad.throws.clause.ignore.thrown.option"), "ignoreThrown");
return panel;
}
@@ -66,7 +71,7 @@
@NotNull
@Override
public String getName() {
- return "Replace with 'catch' clause for 'RuntimeException'";
+ return InspectionGadgetsBundle.message("replace.with.catch.clause.for.runtime.exception.quickfix");
}
@NotNull
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
new file mode 100644
index 0000000..1e60632
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/TooBroadThrowsInspection.java
@@ -0,0 +1,38 @@
+/*
+ * 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.siyeh.ig.errorhandling;
+
+import com.intellij.psi.PsiElement;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class TooBroadThrowsInspection extends TooBroadThrowsInspectionBase {
+
+ @NotNull
+ @Override
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final PsiElement context = (PsiElement)infos[2];
+ final SuppressForTestsScopeFix suppressFix = SuppressForTestsScopeFix.build(this, context);
+ if (suppressFix == null) {
+ return new InspectionGadgetsFix[] {buildFix(infos)};
+ }
+ return new InspectionGadgetsFix[] {buildFix(infos), suppressFix};
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspection.java
index 26acd18..c20849a 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/errorhandling/UnusedCatchParameterInspection.java
@@ -15,19 +15,30 @@
*/
package com.siyeh.ig.errorhandling;
+import com.intellij.psi.PsiElement;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.RenameFix;
-import org.jetbrains.annotations.Nullable;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.NotNull;
public class UnusedCatchParameterInspection extends UnusedCatchParameterInspectionBase {
+ @NotNull
@Override
- @Nullable
- protected InspectionGadgetsFix buildFix(Object... infos) {
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
final boolean namedIgnoreButUsed = ((Boolean)infos[0]).booleanValue();
+ final PsiElement context = (PsiElement)infos[1];
+ final InspectionGadgetsFix fix = SuppressForTestsScopeFix.build(this, context);
if (namedIgnoreButUsed) {
- return null;
+ if (fix == null) {
+ return InspectionGadgetsFix.EMPTY_ARRAY;
+ }
+ return new InspectionGadgetsFix[] {fix};
}
- return new RenameFix("ignored", false, false);
+ final RenameFix renameFix = new RenameFix("ignored", false, false);
+ if (fix == null) {
+ return new InspectionGadgetsFix[] {renameFix};
+ }
+ return new InspectionGadgetsFix[] {renameFix, fix};
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/SuppressForTestsScopeFix.java b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/SuppressForTestsScopeFix.java
new file mode 100644
index 0000000..aa8c592
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/fixes/SuppressForTestsScopeFix.java
@@ -0,0 +1,111 @@
+/*
+ * 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.siyeh.ig.fixes;
+
+import com.intellij.codeHighlighting.HighlightDisplayLevel;
+import com.intellij.codeInsight.daemon.HighlightDisplayKey;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.codeInspection.ex.InspectionToolWrapper;
+import com.intellij.openapi.command.undo.BasicUndoableAction;
+import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.command.undo.UnexpectedUndoException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.search.scope.packageSet.NamedScope;
+import com.intellij.psi.search.scope.packageSet.NamedScopesHolder;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.BaseInspection;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.TestUtils;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+* @author Bas Leijdekkers
+*/
+public class SuppressForTestsScopeFix extends InspectionGadgetsFix {
+
+ private final BaseInspection myInspection;
+
+ private SuppressForTestsScopeFix(BaseInspection inspection) {
+ myInspection = inspection;
+ }
+
+ @Nullable
+ public static SuppressForTestsScopeFix build(BaseInspection inspection, PsiElement context) {
+ if (!TestUtils.isInTestSourceContent(context)) {
+ return null;
+ }
+ return new SuppressForTestsScopeFix(inspection);
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return InspectionGadgetsBundle.message("suppress.for.tests.scope.quickfix");
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return getName();
+ }
+
+ @Override
+ protected boolean prepareForWriting() {
+ return false;
+ }
+
+ @Override
+ protected void doFix(final Project project, ProblemDescriptor descriptor) {
+ addRemoveTestsScope(project, true);
+ final VirtualFile vFile = descriptor.getPsiElement().getContainingFile().getVirtualFile();
+ UndoManager.getInstance(project).undoableActionPerformed(new BasicUndoableAction(vFile) {
+ @Override
+ public void undo() throws UnexpectedUndoException {
+ addRemoveTestsScope(project, false);
+ }
+
+ @Override
+ public void redo() throws UnexpectedUndoException {
+ addRemoveTestsScope(project, true);
+ }
+ });
+ }
+
+ private void addRemoveTestsScope(Project project, boolean add) {
+ final InspectionProjectProfileManager profileManager = InspectionProjectProfileManager.getInstance(project);
+ final InspectionProfileImpl profile = (InspectionProfileImpl)profileManager.getInspectionProfile();
+ final String shortName = myInspection.getShortName();
+ final InspectionToolWrapper tool = profile.getInspectionTool(shortName, project);
+ if (tool == null) {
+ return;
+ }
+ final NamedScope namedScope = NamedScopesHolder.getScope(project, "Tests");
+ final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
+ final HighlightDisplayLevel level = profile.getErrorLevel(key, namedScope, project);
+ if (add) {
+ profile.addScope(tool, namedScope, level, false, project);
+ }
+ else {
+ profile.removeScope(shortName, 0, project);
+ }
+ profile.scopesChanged();
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
index 100fe8a..6cc339c 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/imports/StaticImportInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2012 Dave Griffith, Bas Leijdekkers
+ * 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.
@@ -15,15 +15,30 @@
*/
package com.siyeh.ig.imports;
+import com.intellij.psi.PsiElement;
import com.intellij.util.ui.CheckBox;
import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
import com.siyeh.ig.ui.UiUtils;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
public class StaticImportInspection extends StaticImportInspectionBase {
+ @NotNull
+ @Override
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final PsiElement context = (PsiElement)infos[0];
+ final SuppressForTestsScopeFix fix = SuppressForTestsScopeFix.build(this, context);
+ if (fix == null) {
+ return new InspectionGadgetsFix[] {buildFix(infos)};
+ }
+ return new InspectionGadgetsFix[] {buildFix(infos), fix};
+ }
+
@Override
public JComponent createOptionsPanel() {
final JComponent panel = new JPanel(new GridBagLayout());
@@ -48,9 +63,6 @@
new CheckBox(InspectionGadgetsBundle.message("ignore.single.method.static.imports.option"), this, "ignoreSingeMethodImports");
panel.add(checkBox2, constraints);
- constraints.gridy = 3;
- final CheckBox checkBox3 = new CheckBox(InspectionGadgetsBundle.message("ignore.in.test.code"), this, "ignoreInTestCode");
- panel.add(checkBox3, constraints);
return panel;
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java
new file mode 100644
index 0000000..8cc10fb
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/internationalization/StringConcatenationInspection.java
@@ -0,0 +1,43 @@
+/*
+ * 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.siyeh.ig.internationalization;
+
+import com.intellij.psi.PsiPolyadicExpression;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class StringConcatenationInspection extends StringConcatenationInspectionBase {
+
+ @NotNull
+ @Override
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ final InspectionGadgetsFix[] fixes = super.buildFixes(infos);
+ final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)infos[0];
+ final SuppressForTestsScopeFix suppressFix = SuppressForTestsScopeFix.build(this, polyadicExpression);
+ if (suppressFix == null) {
+ return fixes;
+ }
+ final InspectionGadgetsFix[] newFixes = Arrays.copyOf(fixes, fixes.length + 1);
+ newFixes[fixes.length] = suppressFix;
+ return newFixes;
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SuppressionAnnotationInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SuppressionAnnotationInspection.java
index 78306b9..b08eed0 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SuppressionAnnotationInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SuppressionAnnotationInspection.java
@@ -15,19 +15,21 @@
*/
package com.siyeh.ig.maturity;
-import com.intellij.codeInspection.InspectionProfile;
-import com.intellij.codeInspection.JavaSuppressionUtil;
-import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInsight.FileModificationService;
+import com.intellij.codeInsight.daemon.impl.RemoveSuppressWarningAction;
+import com.intellij.codeInspection.*;
import com.intellij.codeInspection.ui.ListEditForm;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiAnnotation;
+import com.intellij.psi.PsiComment;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiModifierList;
+import com.siyeh.ig.DelegatingFix;
import com.siyeh.ig.InspectionGadgetsFix;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Collection;
@@ -43,47 +45,78 @@
return form.getContentPanel();
}
- @Nullable
+ @NotNull
@Override
- protected InspectionGadgetsFix buildFix(Object... infos) {
- if (infos.length == 1 && infos[0] instanceof PsiAnnotation) {
- final PsiAnnotation annotation = (PsiAnnotation)infos[0];
- final Collection<String> ids = JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation((PsiModifierList)annotation.getParent());
- if (!ids.isEmpty()) {
- return new InspectionGadgetsFix() {
- @Override
- protected void doFix(Project project, ProblemDescriptor descriptor) {
- final PsiElement psiElement = descriptor.getPsiElement();
- if (psiElement instanceof PsiAnnotation) {
- final Collection<String> ids = JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation((PsiModifierList)psiElement.getParent());
- for (String id : ids) {
- if (!myAllowedSuppressions.contains(id)) {
- myAllowedSuppressions.add(id);
- }
- }
- saveProfile(project);
- }
- }
-
- private void saveProfile(Project project) {
- final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
- InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile);
- }
-
- @NotNull
- @Override
- public String getName() {
- return "Allow these suppressions";
- }
-
- @NotNull
- @Override
- public String getFamilyName() {
- return "Allow suppressions";
- }
- };
+ protected InspectionGadgetsFix[] buildFixes(Object... infos) {
+ if (infos.length == 1) {
+ if (infos[0] instanceof PsiAnnotation) {
+ final PsiAnnotation annotation = (PsiAnnotation)infos[0];
+ PsiElement parent = annotation.getParent();
+ final Collection<String> ids = JavaSuppressionUtil.getInspectionIdsSuppressedInAnnotation((PsiModifierList)parent);
+ if (!ids.isEmpty()) {
+ return new InspectionGadgetsFix[]{new DelegatingFix(new RemoveAnnotationQuickFix(annotation, null)), new AllowSuppressionsFix()};
+ }
+ } else if (infos[0] instanceof PsiComment) {
+ return new InspectionGadgetsFix[]{new RemoveSuppressCommentFix(), new AllowSuppressionsFix()};
}
}
- return null;
+ return InspectionGadgetsFix.EMPTY_ARRAY;
+ }
+
+ private static class RemoveSuppressCommentFix extends InspectionGadgetsFix {
+ @Override
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
+ PsiElement psiElement = descriptor.getPsiElement();
+ if (psiElement != null) {
+ if (!FileModificationService.getInstance().preparePsiElementForWrite(psiElement)) return;
+ psiElement.delete();
+ }
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return getFamilyName();
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Remove //" + SuppressionUtilCore.SUPPRESS_INSPECTIONS_TAG_NAME;
+ }
+ }
+
+ private class AllowSuppressionsFix extends InspectionGadgetsFix {
+ @Override
+ protected void doFix(Project project, ProblemDescriptor descriptor) {
+ final PsiElement psiElement = descriptor.getPsiElement();
+ final String suppressedIds = JavaSuppressionUtil.getSuppressedInspectionIdsIn(psiElement);
+ final Iterable<String> ids = suppressedIds != null ? StringUtil.tokenize(suppressedIds, "[, ]") : null;
+ if (ids != null) {
+ for (String id : ids) {
+ if (!myAllowedSuppressions.contains(id)) {
+ myAllowedSuppressions.add(id);
+ }
+ }
+ saveProfile(project);
+ }
+ }
+
+ private void saveProfile(Project project) {
+ final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
+ InspectionProfileManager.getInstance().fireProfileChanged(inspectionProfile);
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return "Allow these suppressions";
+ }
+
+ @NotNull
+ @Override
+ public String getFamilyName() {
+ return "Allow suppressions";
+ }
}
}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SystemOutErrInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SystemOutErrInspection.java
new file mode 100644
index 0000000..859efaa
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/SystemOutErrInspection.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.maturity;
+
+import com.intellij.psi.PsiElement;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class SystemOutErrInspection extends SystemOutErrInspectionBase {
+
+ @Nullable
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final PsiElement context = (PsiElement)infos[0];
+ return SuppressForTestsScopeFix.build(this, context);
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspection.java
new file mode 100644
index 0000000..d53926f
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspection.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.maturity;
+
+import com.intellij.psi.PsiElement;
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.SuppressForTestsScopeFix;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ThrowablePrintStackTraceInspection extends ThrowablePrintStackTraceInspectionBase {
+
+ @Nullable
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ final PsiElement context = (PsiElement)infos[0];
+ return SuppressForTestsScopeFix.build(this, context);
+ }
+}
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java
index 59b3ed3..c0a3027 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/ForCanBeForeachInspection.java
@@ -26,6 +26,7 @@
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.StringUtils;
import com.siyeh.ig.psiutils.TypeUtils;
@@ -94,7 +95,7 @@
if (newExpression == null) {
return;
}
- replaceStatementAndShortenClassNames(forStatement, newExpression);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(forStatement, newExpression);
}
@Nullable
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
index 62edc2e..6c0ef3f 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/migration/WhileCanBeForeachInspection.java
@@ -30,6 +30,7 @@
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.StringUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NonNls;
@@ -180,7 +181,7 @@
iterator.delete();
}
final String result = out.toString();
- replaceStatementAndShortenClassNames(whileStatement, result);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(whileStatement, result);
}
@Nullable
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/naming/AbstractClassNamingConventionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/AbstractClassNamingConventionInspection.java
new file mode 100644
index 0000000..a0b8f25
--- /dev/null
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/naming/AbstractClassNamingConventionInspection.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2003-2007 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.naming;
+
+import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.fixes.RenameFix;
+
+public class AbstractClassNamingConventionInspection extends AbstractClassNamingConventionInspectionBase {
+
+ @Override
+ protected InspectionGadgetsFix buildFix(Object... infos) {
+ return new RenameFix();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java
index 731a1da..bfa02e2 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/performance/ToArrayCallWithZeroLengthArrayArgumentInspection.java
@@ -22,6 +22,7 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.HighlightUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -83,7 +84,7 @@
if (newExpressionText == null) {
return;
}
- replaceExpression(methodCallExpression, newExpressionText);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpressionText);
return;
}
// need to introduce a variable to prevent calling a method twice
diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java
index bdbe860..0584a64 100644
--- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java
+++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedInnerClassAccessInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2010-2011 Bas Leijdekkers
+ * Copyright 2010-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,14 +23,13 @@
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.InspectionGadgetsFix;
+import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.HighlightUtils;
import com.siyeh.ig.psiutils.ImportUtils;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
+import java.util.*;
public class UnqualifiedInnerClassAccessInspection extends UnqualifiedInnerClassAccessInspectionBase {
@@ -70,8 +69,8 @@
if (!(target instanceof PsiClass)) {
return;
}
- final PsiClass aClass = (PsiClass)target;
- final PsiClass containingClass = aClass.getContainingClass();
+ final PsiClass innerClass = (PsiClass)target;
+ final PsiClass containingClass = innerClass.getContainingClass();
if (containingClass == null) {
return;
}
@@ -84,7 +83,7 @@
return;
}
final PsiJavaFile javaFile = (PsiJavaFile)containingFile;
- final String innerClassName = aClass.getQualifiedName();
+ final String innerClassName = innerClass.getQualifiedName();
if (innerClassName == null) {
return;
}
@@ -115,10 +114,10 @@
}
final ReferenceCollector referenceCollector;
if (onDemand) {
- referenceCollector = new ReferenceCollector(qualifiedName, onDemand);
+ referenceCollector = new ReferenceCollector(qualifiedName, true);
}
else {
- referenceCollector = new ReferenceCollector(innerClassName, onDemand);
+ referenceCollector = new ReferenceCollector(innerClassName, false);
}
final PsiClass[] classes = javaFile.getClasses();
for (PsiClass psiClass : classes) {
@@ -134,7 +133,8 @@
if (referenceImportStatement != null) {
referenceImportStatement.delete();
}
- ImportUtils.addImportIfNeeded(containingClass, referenceElement);
+ final PsiClass outerClass = ClassUtils.getOutermostContainingClass(containingClass);
+ ImportUtils.addImportIfNeeded(outerClass, referenceElement);
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
final Document document = documentManager.getDocument(containingFile);
if (document == null) {
@@ -160,7 +160,7 @@
}
//noinspection SuspiciousMethodCalls
if (references.contains(element)) {
- final String shortClassName = aClass.getName();
+ final String shortClassName = getShortClassName(aClass, new StringBuilder()).toString();
if (isReferenceToTargetClass(shortClassName, aClass, element)) {
out.append(shortClassName);
}
@@ -180,6 +180,16 @@
return out;
}
+ private static StringBuilder getShortClassName(@NotNull PsiClass aClass, @NotNull StringBuilder builder) {
+ final PsiClass containingClass = aClass.getContainingClass();
+ if (containingClass != null) {
+ getShortClassName(containingClass, builder);
+ builder.append('.');
+ }
+ builder.append(aClass.getName());
+ return builder;
+ }
+
private static boolean isReferenceToTargetClass(String referenceText, PsiClass targetClass, PsiElement context) {
final PsiManager manager = targetClass.getManager();
final JavaPsiFacade facade = JavaPsiFacade.getInstance(manager.getProject());
@@ -191,4 +201,53 @@
return manager.areElementsEquivalent(targetClass, referencedClass);
}
}
+
+ private static class ReferenceCollector extends JavaRecursiveElementVisitor {
+
+ private final String name;
+ private final boolean onDemand;
+ private final Set<PsiJavaCodeReferenceElement> references = new HashSet<PsiJavaCodeReferenceElement>();
+
+ ReferenceCollector(String name, boolean onDemand) {
+ this.name = name;
+ this.onDemand = onDemand;
+ }
+
+ @Override
+ public void visitReferenceElement(PsiJavaCodeReferenceElement reference) {
+ super.visitReferenceElement(reference);
+ if (reference.isQualified()) {
+ return;
+ }
+ final PsiElement target = reference.resolve();
+ if (!(target instanceof PsiClass)) {
+ return;
+ }
+ final PsiClass aClass = (PsiClass)target;
+ if (!onDemand) {
+ final String qualifiedName = aClass.getQualifiedName();
+ if (name.equals(qualifiedName)) {
+ references.add(reference);
+ }
+ return;
+ }
+ final PsiClass containingClass = aClass.getContainingClass();
+ if (containingClass == null) {
+ return;
+ }
+ final String qualifiedName = containingClass.getQualifiedName();
+ if (name.equals(qualifiedName)) {
+ references.add(reference);
+ }
+ }
+
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ visitReferenceElement(expression);
+ }
+
+ public Collection<PsiJavaCodeReferenceElement> getReferences() {
+ return references;
+ }
+ }
}
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/AbstractClassNamingConvention.html b/plugins/InspectionGadgets/src/inspectionDescriptions/AbstractClassNamingConvention.html
new file mode 100644
index 0000000..ed5a551
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/AbstractClassNamingConvention.html
@@ -0,0 +1,13 @@
+<html>
+<body>
+Reports <b>abstract</b> classes whose names are either too short, too long, or do not follow the specified regular expression pattern.
+Some coding styles have a special naming convention for <b>abstract</b> classes.
+When this inspection is enabled, the <i>Class naming convention</i> inspection will ignore <b>abstract</b> classes automatically.
+<!-- tooltip end -->
+<p>
+Use the fields below to specify minimum length, maximum length and regular expression expected for class names.
+Specify <b>0</b> to not check the length of names. Regular expressions are in standard <b>java.util.regex</b> format.
+<p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ArchaicSystemPropertyAccess.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ArchaicSystemPropertyAccess.html
deleted file mode 100644
index 3a15c30..0000000
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ArchaicSystemPropertyAccess.html
+++ /dev/null
@@ -1,12 +0,0 @@
-<html>
-<body>
-Reports any calls to <b>Integer.getInteger()</b> or <b>Boolean.getBoolean()</b>.
-These methods fetch integer and boolean values from the
-system properties for a given key. Due to their underexpressive names and confusing
-location of functionality, it's easy for novice programmers to attempt to use these
-for other purposes, such as string parsing.
-<!-- tooltip end -->
-<p>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html
index 775a9b5..82048c0 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/BadExceptionDeclared.html
@@ -6,9 +6,7 @@
<p>
Use the list below to specify which exceptions should be flagged by this inspection.
<p>
-Use the first checkbox below to ignore exceptions declared on test methods.
-<p>
-Use the second checkbox below to ignore exceptions declared on methods which override a library method.
+Use the checkbox below to ignore exceptions declared on methods which override a library method.
<p>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInitializer.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInitializer.html
index 3f59450..e3f57a8 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInitializer.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ClassInitializer.html
@@ -1,12 +1,15 @@
<html>
<body>
-Reports any of non-<b>static</b> initializers
-in classes. Some coding standards prohibit such initializers, preferring initialization to be done
+Reports any non-<b>static</b> initializers
+in classes. Some coding standards prohibit instance initializers, preferring initialization to be done
in constructors or field initializers. Non-<b>static</b> initializers
may also be inadvertently created by deleting the <b>static</b> keyword,
resulting in obscure bugs.
+This inspection does not warn on instance initializers in anonymous classes.
<!-- tooltip end -->
<p>
+Use the checkbox below to ignore instance initializers in classes which do not have any constructors.
+<p>
</body>
</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/DriverManagerGetConnection.html b/plugins/InspectionGadgets/src/inspectionDescriptions/DriverManagerGetConnection.html
index 9794acc..d4e9a99 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/DriverManagerGetConnection.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/DriverManagerGetConnection.html
@@ -1,7 +1,7 @@
<html>
<body>
-Reports any uses to <b>javax.sql.DriverManager</b>
-to acquire a JDBC connection. The <b>javax.sql.DriverManager</b>
+Reports any uses to <b>java.sql.DriverManager</b>
+to acquire a JDBC connection. The <b>java.sql.DriverManager</b>
has been superseded by <b>javax.sql.Datasource</b>, which
allows for connection pooling and other optimizations.
<!-- tooltip end -->
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyCatchBlock.html b/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyCatchBlock.html
index 63b2848..4e07694 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyCatchBlock.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyCatchBlock.html
@@ -1,14 +1,13 @@
<html>
<body>
-Reports empty <b>catch</b> blocks. While occasionally intended, this
+Reports empty <b>catch</b> blocks. While occasionally intended,
empty <b>catch</b> blocks can make debugging extremely difficult.
<p>
At present, this inspection is disabled in JSP files.
<!-- tooltip end -->
<p>
-Use the controls below to indicate whether catch blocks containing only comments,
-empty catch blocks in JUnit tests should be reported and whether to ignore empty
-catch blocks if the parameter is named 'ignore' or 'ignored'.
+Use the controls below to indicate whether catch blocks containing only comments should be reported,
+and whether to ignore empty catch blocks if the parameter is named 'ignore' or 'ignored'.
<p>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyStatementBody.html b/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyStatementBody.html
index d705ee4..e1f5aba 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyStatementBody.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/EmptyStatementBody.html
@@ -1,7 +1,6 @@
<html>
<body>
-Reports <b>if</b>,
-<b>while</b>, <b>do</b> or <b>for</b> statements
+Reports <b>if</b>, <b>while</b>, <b>do</b>, <b>for</b> and <b>switch</b> statements
having empty bodies. While occasionally intended, this construction is confusing, and often the result of a typo.
<!-- tooltip end -->
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ImplicitDefaultCharsetUsage.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ImplicitDefaultCharsetUsage.html
new file mode 100644
index 0000000..a70bc25
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ImplicitDefaultCharsetUsage.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+Reports method and constructor calls which implicitly use the platform's default charset.
+These can produce different results on (e.g. foreign language) systems that use a different default charset,
+resulting in unexpected behaviour.
+<!-- tooltip end -->
+<p>
+<small>New in 13.1</small>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceMayBeAnnotatedFunctional.html b/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceMayBeAnnotatedFunctional.html
new file mode 100644
index 0000000..66ea1b4
--- /dev/null
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/InterfaceMayBeAnnotatedFunctional.html
@@ -0,0 +1,10 @@
+<html>
+<body>
+Reports any <b>interface</b> that may be annotated as <b>@FunctionalInterface</b>, which is available in JDK 1.8.
+Annotating an interface with <b>@FunctionalInterface</b> can be useful to indicate that the interface is supposed to be functional and
+further <b>abstract</b> methods should not be added to it.
+This inspection only reports if the project or module is configured to use a language level of 8.0 or higher.
+<p>
+<small>New in 13.1</small>
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MagicCharacter.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MagicCharacter.html
index 9548316..bb70cee 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MagicCharacter.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MagicCharacter.html
@@ -1,8 +1,8 @@
<html>
<body>
-Reports "magic characters", character constants used without declaration.
-"Magic character" can result in code whose intention is extremely unclear, and may result in errors if a "magic
-character" is changed in one code location but not another. Such use can complicate internationalization
+Reports "magic characters", which are character literals used without being named by a constant declaration.
+Magic characters can result in code whose intention is unclear, and may result in errors if a magic
+character is changed in one code location but not another. Such use can complicate internationalization
efforts.
<!-- tooltip end -->
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/MagicNumber.html b/plugins/InspectionGadgets/src/inspectionDescriptions/MagicNumber.html
index b617007..af21b69 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/MagicNumber.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/MagicNumber.html
@@ -1,18 +1,16 @@
<html>
<body>
-Reports "magic numbers", literal numeric constants used without declaration.
-"Magic numbers" can result in code whose intention is extremely unclear, and may result in errors if a "magic
-number" is changed in one code location but not another. The numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 0L, 1L, 2L,
+Reports "magic numbers", which are numeric literals used without being named by a constant declaration.
+Magic numbers can result in code whose intention is unclear, and may result in errors if a magic
+number is changed in one code location but not another. The numbers 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100, 1000, 0L, 1L, 2L,
0.0, 1.0, 0.0F and 1.0F are not reported by this inspection.
<!-- tooltip end -->
<p>
Use the first checkbox below to disable this inspection within <b>hashCode()</b> methods.
<p>
-Use the second checkbox below to ignore magic numbers in test code.
+Use the second checkbox below to ignore magic numbers in annotations.
<p>
-Use the third checkbox below to ignore magic numbers in annotations.
-<p>
-Use the fourth checkbox below to ignore magic numbers used as initial capacity when constructing <b>Collection</b>, <b>Map</b>,
+Use the third checkbox below to ignore magic numbers used as initial capacity when constructing <b>Collection</b>, <b>Map</b>,
<b>StringBuilder</b> or <b>StringBuffer</b> objects.
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/OrredNotEqualExpression.html b/plugins/InspectionGadgets/src/inspectionDescriptions/OrredNotEqualExpression.html
deleted file mode 100644
index be0921a..0000000
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/OrredNotEqualExpression.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<html>
-<body>
-This inspection highlights expressions where a reference is compared to a different value
-on either side of an or-expression. For example: <code>x != a || x != b</code>.
-Such expressions are always true, and a quickfix is available to change them to the correct
-<code>x != a && x != b</code>
-<!-- tooltip end -->
-<p>
-
-</body>
-</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/OverriddenMethodCallDuringObjectConstruction.html b/plugins/InspectionGadgets/src/inspectionDescriptions/OverriddenMethodCallDuringObjectConstruction.html
index f2a7803..59f7aef 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/OverriddenMethodCallDuringObjectConstruction.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/OverriddenMethodCallDuringObjectConstruction.html
@@ -1,8 +1,8 @@
<html>
<body>
Reports any calls to overridden methods of the current class during object construction.
-A call is during object construction if it is made inside a constructor, in an non-static instance initializer,
-in a non-static field initializer or inside a <b>clone()</b>, <b>readObject()</b> or <b>readObjectNoData()</b> method.
+A call is made during object construction if it is performed in a constructor, in an non-static instance initializer,
+in a non-static field initializer or in a <b>clone()</b>, <b>readObject()</b> or <b>readObjectNoData()</b> method.
Such calls may result in subtle bugs, as the object is not guaranteed to be initialized
before the method call occurs.
<!-- tooltip end -->
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticImport.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticImport.html
index 1a2762d..0edd764 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StaticImport.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StaticImport.html
@@ -1,9 +1,15 @@
<html>
<body>
-Reports <b>static import</b> statements.
-Such import statements are not supported under Java 1.4 or earlier JVMs.
+Reports <b>import static</b> statements.
+Such <b>import</b> statements are not supported under Java 1.4 or earlier JVMs.
<!-- tooltip end -->
<p>
+Use the table below to specify classes which when used in a <b>import static</b> statement, the statement will not be reported.
+<p>
+Use the first checkbox below to ignore single field <b>import static</b> statements.
+<p>
+Use the second checkbox below to ignore single method <b>import static</b> statements.
+<p>
</body>
</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html
index 2de1513..e9350e3 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/StringConcatenation.html
@@ -1,7 +1,7 @@
<html>
<body>
Reports any String concatenation (<b>+</b>). Concatenation is usually
-incorrect in an internationalized environment, and should be replace by uses of
+incorrect in an internationalized environment, and should be replaced by uses of
<b>java.text.MessageFormat</b> or similar classes.
<!-- tooltip end -->
<p>
@@ -20,9 +20,7 @@
Use the fifth checkbox to ignore string concatenations in the initializers
of constant fields.
<p>
-Use the sixth checkbox to ignore string concatenations in test code.
-<p>
-Use the seventh checkbox to ignore string concatentations inside <b>toString()</b> methods.
+Use the sixth checkbox to ignore string concatenations inside <b>toString()</b> methods.
<p>
</body>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/SystemOutErr.html b/plugins/InspectionGadgets/src/inspectionDescriptions/SystemOutErr.html
index 42e70ba..ab401f5 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/SystemOutErr.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/SystemOutErr.html
@@ -5,6 +5,5 @@
logging facility.
<!-- tooltip end -->
<p>
-Use the checkbox below to ignore <b>Throwable.printStackTrace()</b> calls in test code.
</body>
</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodWithoutAssertion.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodWithoutAssertion.html
index 81be6fe..bed7292 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodWithoutAssertion.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TestMethodWithoutAssertion.html
@@ -1,10 +1,10 @@
<html>
<body>
-Reports any test methods of JUnit test case classes which do not contain
+Reports test methods of JUnit test case classes that do not contain
any assertions. Such methods indicate either incomplete or weak test cases.
<!-- tooltip end -->
<p>
-The table below can be used to specify which class name, method name regular expression combinations
+The table below can be used to specify which combinations of class name and method name regular expression
qualify as assertions.
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/ThrowablePrintStackTrace.html b/plugins/InspectionGadgets/src/inspectionDescriptions/ThrowablePrintStackTrace.html
index f012ef1..c702054 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/ThrowablePrintStackTrace.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/ThrowablePrintStackTrace.html
@@ -5,6 +5,5 @@
or replaced with a more robust logging facility.
<!-- tooltip end -->
<p>
-Use the checkbox below to ignore <b>Throwable.printStackTrace()</b> calls in test code.
</body>
</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadCatch.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadCatch.html
index 14b73fa..ccdf0fe 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadCatch.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadCatch.html
@@ -6,9 +6,7 @@
<p>
Use the first checkbox below to have this inspection only warn on the most generic exceptions.
<p>
-Use the second checkbox below to ignore overly broad <b>catch</b> blocks in test code.
-<p>
-Use the third checkbox below to ignore any exceptions which hide other exceptions, but which may be thrown and thus
+Use the second checkbox below to ignore any exceptions which hide other exceptions, but which may be thrown and thus
are technically not overly broad.
<p>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadThrows.html b/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadThrows.html
index 0a0b078..6c94af8 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadThrows.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/TooBroadThrows.html
@@ -6,11 +6,9 @@
<p>
Use the first checkbox below to have this inspection only warn on the most generic exceptions.
<p>
-Use the second checkbox below to ignore overly broad <b>throws</b> clauses in test code.
+Use the second checkbox below to ignore overly broad <b>throws</b> clauses in methods which override a library method.
<p>
-Use the third checkbox below to ignore overly broad <b>throws</b> clauses in methods which override a library method.
-<p>
-Use the fourth checkbox below to ignore any exceptions which hide other exceptions, but which may be thrown from the method body and thus
+Use the third checkbox below to ignore any exceptions which hide other exceptions, but which may be thrown from the method body and thus
are technically not overly broad.
<p>
<small>New in 10</small>
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryBoxing.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryBoxing.html
index d9bc7d4..00c423b 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryBoxing.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnnecessaryBoxing.html
@@ -9,6 +9,5 @@
<p>
Use the checkbox below to only report truly superfluous boxing, where a boxed value will immediately be implicitly or explicitly unboxed.
In this case the entire boxing-unboxing step can be removed. Simple explicit boxing will not be reported.
-again.
</body>
</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/src/inspectionDescriptions/UnusedCatchParameter.html b/plugins/InspectionGadgets/src/inspectionDescriptions/UnusedCatchParameter.html
index 131f651..79c92c6 100644
--- a/plugins/InspectionGadgets/src/inspectionDescriptions/UnusedCatchParameter.html
+++ b/plugins/InspectionGadgets/src/inspectionDescriptions/UnusedCatchParameter.html
@@ -8,8 +8,6 @@
<p>
Use the first checkbox below to disable this inspection for <b>catch</b> blocks with comments.
<p>
-Use the second checkbox below to ignore catch blocks in test code.
-<p>
</body>
</html>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/ChainedConstructor.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/ChainedConstructor.after.java
new file mode 100644
index 0000000..9156d69
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/ChainedConstructor.after.java
@@ -0,0 +1,15 @@
+class ChainedConstructor {
+ String s;
+ String t;
+
+ ChainedConstructor(String s) {
+ this.s = s;
+ System.out.println();
+ t = "b";
+ }
+
+ ChainedConstructor() {
+ this("a");
+ }
+
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/ChainedConstructor.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/ChainedConstructor.java
new file mode 100644
index 0000000..5371239
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/ChainedConstructor.java
@@ -0,0 +1,17 @@
+class ChainedConstructor {
+ String s;
+ String t;
+
+ ChainedConstructor(String s) {
+ this.s = s;
+ }
+
+ ChainedConstructor() {
+ this("a");
+ }
+
+ {<caret>
+ System.out.println();
+ t = "b";
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/NoConstructor.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/NoConstructor.after.java
new file mode 100644
index 0000000..b77c4c4
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/NoConstructor.after.java
@@ -0,0 +1,7 @@
+class NoConstructor {
+
+ NoConstructor() {
+ System.out.println("a");
+ System.out.println("b");
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/NoConstructor.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/NoConstructor.java
new file mode 100644
index 0000000..3cb6194
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/classlayout/class_initializer/NoConstructor.java
@@ -0,0 +1,7 @@
+class NoConstructor {
+
+ <caret>{
+ System.out.println("a");
+ System.out.println("b");
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/trivialIf/CommentsInAssignment.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/trivialIf/CommentsInAssignment.after.java
new file mode 100644
index 0000000..c4e2107
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/trivialIf/CommentsInAssignment.after.java
@@ -0,0 +1,7 @@
+class Test {
+ public static boolean test(String key, String keyValue){
+ boolean b;
+ // some comment goes here
+ b = key != null && key.equals(keyValue);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/trivialIf/CommentsInAssignment.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/trivialIf/CommentsInAssignment.java
new file mode 100644
index 0000000..d1a3eed
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/controlflow/trivialIf/CommentsInAssignment.java
@@ -0,0 +1,11 @@
+class Test {
+ public static boolean test(String key, String keyValue){
+ boolean b;
+ <caret>if(key != null && key.equals(keyValue)) {
+ // some comment goes here
+ b = true;
+ } else {
+ b = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unqualified_inner_class_access/Deep.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unqualified_inner_class_access/Deep.after.java
new file mode 100644
index 0000000..9fbfaab
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unqualified_inner_class_access/Deep.after.java
@@ -0,0 +1,14 @@
+package unqualified_inner_class_access;
+
+class Deep {
+ public static class One {
+ public static class Two {
+ public static class Three {}
+ }
+ }
+}
+class User {
+ public static void main(String[] args) {
+ new Deep.One.Two.Three();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unqualified_inner_class_access/Deep.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unqualified_inner_class_access/Deep.java
new file mode 100644
index 0000000..66f4544
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/style/unqualified_inner_class_access/Deep.java
@@ -0,0 +1,16 @@
+package unqualified_inner_class_access;
+
+import unqualified_inner_class_access.Deep.One.Two.Three;
+
+class Deep {
+ public static class One {
+ public static class Two {
+ public static class Three {}
+ }
+ }
+}
+class User {
+ public static void main(String[] args) {
+ new <caret>Three();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/cyclic_class_dependency/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/cyclic_class_dependency/expected.xml
deleted file mode 100644
index 9a82ac1..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/cyclic_class_dependency/expected.xml
+++ /dev/null
@@ -1,44 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<problems>
- <problem>
- <file>Cyclic.java</file>
- <line>9</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
- <description>Class 'anonymous (java.lang.Object)' is cyclically dependent on 3 other classes</description>
- </problem>
-
- <problem>
- <file>Cyclic.java</file>
- <line>17</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
- <description>Class 'Base' is cyclically dependent on classes 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Cyclic' and 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Top'</description>
- </problem>
-
- <problem>
- <file>Cyclic.java</file>
- <line>29</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
- <description>Class 'Coffee' is cyclically dependent on class 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.FiveOClock'</description>
- </problem>
-
- <problem>
- <file>Cyclic.java</file>
- <line>25</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
- <description>Class 'FiveOClock' is cyclically dependent on class 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Coffee'</description>
- </problem>
-
- <problem>
- <file>Cyclic.java</file>
- <line>22</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
- <description>Class 'Top' is cyclically dependent on classes 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Base' and 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Cyclic'</description>
- </problem>
-
- <problem>
- <file>Cyclic.java</file>
- <line>6</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
- <description>Class 'Cyclic' is cyclically dependent on classes 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Base' and 'com.siyeh.igtest.abstraction.cyclic_class_dependency.src.Top'</description>
- </problem>
-</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/cyclic_class_dependency/src/Cyclic.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/cyclic_class_dependency/src/Cyclic.java
deleted file mode 100644
index adf9298..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/cyclic_class_dependency/src/Cyclic.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package com.siyeh.igtest.abstraction.cyclic_class_dependency.src;
-
-/**
- * @author Bas Leijdekkers
- */
-public class Cyclic extends Base {
-
- Cyclic() {
- new Object() {{
- foo();
- }};
- }
-
- void foo() {}
-
-}
-class Base {
- void a() {
- Top.m();
- }
-}
-class Top extends Cyclic {
- public static void m() {}
-}
-interface FiveOClock {
- void m(Coffee c);
-
-}
-interface Coffee extends FiveOClock {}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/MagicNumber.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/MagicNumber.java
index 77fda32..c8733da 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/MagicNumber.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/MagicNumber.java
@@ -1,20 +1,20 @@
package com.siyeh.igtest.abstraction.magic_number;
-import java.util.Set;
-import java.util.HashSet;
+import java.util.List;
+import java.util.ArrayList;
@Size(max = 15)
public class MagicNumber
{
private static final int s_foo = 400;
- private int m_foo = 400;
+ private int m_foo = -400;
private static int s_foo2 = 400;
- private final int m_foo2 = 400;
- private static final Set s_set = new HashSet(400);
+ private final int m_foo2 = -(-(400));
+ private static final List s_set = new ArrayList(400);
public static void main(String[] args)
{
- final Set set = new HashSet(400);
+ final List set = new ArrayList(400);
set.toString();
}
@@ -36,6 +36,10 @@
result = 29 * result + m_foo2;
return result;
}
+
+ void foo() {
+ final int value = 101 * 55;
+ }
}
@interface Size {
int max();
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/expected.xml
index fc8efb5..acfeb03 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/abstraction/magic_number/expected.xml
@@ -4,21 +4,7 @@
<file>MagicNumber.java</file>
<line>10</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">"Magic number"</problem_class>
- <description>Magic number <code>400</code> #loc</description>
- </problem>
-
- <problem>
- <file>MagicNumber.java</file>
- <line>17</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">"Magic number"</problem_class>
- <description>Magic number <code>400</code> #loc</description>
- </problem>
-
- <problem>
- <file>MagicNumber.java</file>
- <line>12</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">"Magic number"</problem_class>
- <description>Magic number <code>400</code> #loc</description>
+ <description>Magic number <code>-400</code> #loc</description>
</problem>
<problem>
@@ -27,4 +13,18 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">"Magic number"</problem_class>
<description>Magic number <code>400</code> #loc</description>
</problem>
+
+ <problem>
+ <file>MagicNumber.java</file>
+ <line>41</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Magic number</problem_class>
+ <description>Magic number <code>101</code> #loc</description>
+ </problem>
+
+ <problem>
+ <file>MagicNumber.java</file>
+ <line>41</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Magic number</problem_class>
+ <description>Magic number <code>55</code> #loc</description>
+ </problem>
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/DuplicateCondition.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/DuplicateCondition.java
index ef41c37..aad58b5 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/DuplicateCondition.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/DuplicateCondition.java
@@ -16,4 +16,12 @@
{
return true;
}
+
+ void incompleteCode(String s) {
+ if (s.contains(A)) {
+
+ } else if (s.contains(B)) {
+
+ }
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java
deleted file mode 100644
index 55dfea2..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/StaticCallOnSubclass.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.siyeh.igtest.bugs;
-
-import com.siyeh.igtest.abstraction.StaticCallOnSubclassChild;
-
-public class StaticCallOnSubclass {
-
- public void foo() throws InterruptedException {
- Thread.sleep(1000L);
- InnerThread.sleep(1000L, 1000);
- final int priority = InnerThread.MAX_PRIORITY;
- StaticCallOnSubclassChild.foo();
- }
-
- class InnerThread extends Thread
- {
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/array_equality/ArrayEquality.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/array_equality/ArrayEquality.java
new file mode 100644
index 0000000..02efd15
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/array_equality/ArrayEquality.java
@@ -0,0 +1,10 @@
+class ArrayEquality {
+
+ boolean a(String[] a, String[] b) {
+ return a <warning descr="Array objects are compared using '==', not 'Arrays.equals()'">==</warning> b;
+ }
+
+ boolean b(Number[] n) {
+ return n == null;
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/number_equality/NumberEquality.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/number_equality/NumberEquality.java
new file mode 100644
index 0000000..45ed54a
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/number_equality/NumberEquality.java
@@ -0,0 +1,10 @@
+class NumberEquality {
+
+ boolean f(Integer i, Integer j) {
+ return i <warning descr="Number objects are compared using '==', not 'equals()'">==</warning> j;
+ }
+
+ boolean g(Integer i) {
+ return i == null;
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java
index c6d1302..33925ce 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/VariableNotUsedInsideIf.java
@@ -61,4 +61,9 @@
private int someValue() {
return 0;
}
+
+ void perenthesis(String[] args)
+ {
+ String message = (args == null) ? "not null" : "null";
+ }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml
index 603a542..c3a2f76 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/bugs/variable_not_used_inside_if/expected.xml
@@ -41,4 +41,12 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Reference checked for 'null' is not used inside 'if'</problem_class>
<description><code>x</code> checked for 'null' is not used inside conditional #loc</description>
</problem>
+
+ <problem>
+ <file>VariableNotUsedInsideIf.java</file>
+ <line>67</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Reference checked for 'null' is not used inside 'if'</problem_class>
+ <description><code>args</code> checked for 'null' is not used inside conditional #loc</description>
+ </problem>
+
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/ClassInitializerInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/ClassInitializerInspection.java
deleted file mode 100644
index dff8a69..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/ClassInitializerInspection.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.siyeh.igtest.classlayout;
-
-public class ClassInitializerInspection {
- static private int foo;
-
- static {
- foo = 3;
- }
-
- {
- foo = 3;
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/Anonymous.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/Anonymous.java
new file mode 100644
index 0000000..943e388
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/Anonymous.java
@@ -0,0 +1,15 @@
+package classlayout.class_initializer;
+
+class Anonymous {
+
+ void foo() {
+ new Object() {
+
+ int i;
+
+ {
+ i = 9;
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/NoConstructor.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/NoConstructor.java
new file mode 100644
index 0000000..d52b1c2
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/NoConstructor.java
@@ -0,0 +1,3 @@
+package com.siyeh.igtest.classlayout.class_initializer;
+
+public class NoConstructor {{}}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/Simple.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/Simple.java
new file mode 100644
index 0000000..4f1e690
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/class_initializer/Simple.java
@@ -0,0 +1,8 @@
+package com.siyeh.igtest.classlayout.class_initializer;
+
+public class Simple {
+
+ <warning descr="Non-'static' initializer">{</warning>}
+
+ Simple() {}
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/FinalMethodInFinalClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/FinalMethodInFinalClass.java
index db68458..f0bbb90 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/FinalMethodInFinalClass.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/FinalMethodInFinalClass.java
@@ -23,3 +23,12 @@
public final void eatCarbohydrates() {}
}
+final class Soup {
+ @java.lang.SafeVarargs
+ private final void foo(java.util.Collection<String>... args) {
+ // ...
+ }
+
+ @java.lang.SafeVarargs
+ private static final void bar(java.util.Collection<Integer>... args) {}
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/expected.xml
index ab27c0a..ffba162 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/final_method_in_final_class/expected.xml
@@ -7,5 +7,12 @@
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'final' method in 'final' class</problem_class>
<description>Method declared <code>final</code> in 'final' class #loc</description>
</problem>
+
+ <problem>
+ <file>FinalMethodInFinalClass.java</file>
+ <line>33</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">'final' method in 'final' class</problem_class>
+ <description>Method declared <code>final</code> in 'final' class #loc</description>
+ </problem>
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/noop_method_in_abstract_class/NoopMethodInAbstractClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/noop_method_in_abstract_class/NoopMethodInAbstractClass.java
index 214152d..19d2adb 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/noop_method_in_abstract_class/NoopMethodInAbstractClass.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/classlayout/noop_method_in_abstract_class/NoopMethodInAbstractClass.java
@@ -5,4 +5,6 @@
void foo() {}
native int bar();
+
+ final void noop() {}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_calls_constructors/CloneCallsConstructors.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_calls_constructors/CloneCallsConstructors.java
new file mode 100644
index 0000000..84696ac
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/cloneable/clone_calls_constructors/CloneCallsConstructors.java
@@ -0,0 +1,9 @@
+package com.siyeh.igtest.cloneable.clone_calls_constructors;
+
+class CloneCallsConstructors implements Cloneable {
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return new <warning descr="'clone()' creates new 'CloneCallsConstructors' instances">CloneCallsConstructors</warning>();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml
new file mode 100644
index 0000000..4e19f48
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/expected.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>Cyclic.java</file>
+ <line>9</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
+ <description>Class 'anonymous (java.lang.Object)' is cyclically dependent on 3 other classes</description>
+ </problem>
+
+ <problem>
+ <file>Cyclic.java</file>
+ <line>17</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
+ <description>Class 'Base' is cyclically dependent on classes 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Cyclic' and 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Top'</description>
+ </problem>
+
+ <problem>
+ <file>Cyclic.java</file>
+ <line>29</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
+ <description>Class 'Coffee' is cyclically dependent on class 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.FiveOClock'</description>
+ </problem>
+
+ <problem>
+ <file>Cyclic.java</file>
+ <line>25</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
+ <description>Class 'FiveOClock' is cyclically dependent on class 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Coffee'</description>
+ </problem>
+
+ <problem>
+ <file>Cyclic.java</file>
+ <line>22</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
+ <description>Class 'Top' is cyclically dependent on classes 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Base' and 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Cyclic'</description>
+ </problem>
+
+ <problem>
+ <file>Cyclic.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Cyclic class dependency</problem_class>
+ <description>Class 'Cyclic' is cyclically dependent on classes 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Base' and 'com.siyeh.igtest.dependency.cyclic_class_dependency.src.Top'</description>
+ </problem>
+</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java
new file mode 100644
index 0000000..e0f9cf4
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_class_dependency/src/Cyclic.java
@@ -0,0 +1,29 @@
+package com.siyeh.igtest.dependency.cyclic_class_dependency.src;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class Cyclic extends Base {
+
+ Cyclic() {
+ new Object() {{
+ foo();
+ }};
+ }
+
+ void foo() {}
+
+}
+class Base {
+ void a() {
+ Top.m();
+ }
+}
+class Top extends Cyclic {
+ public static void m() {}
+}
+interface FiveOClock {
+ void m(Coffee c);
+
+}
+interface Coffee extends FiveOClock {}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/expected.xml
new file mode 100644
index 0000000..beb3b7c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/expected.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <entry_point TYPE="package" FQNAME="c" />
+ <problem_class>Cyclic package dependency</problem_class>
+ <hints />
+ <description>Package 'c' is cyclically dependent on package 'b'</description>
+ </problem>
+
+ <problem>
+ <entry_point TYPE="package" FQNAME="b" />
+ <problem_class>Cyclic package dependency</problem_class>
+ <hints />
+ <description>Package 'b' is cyclically dependent on package 'c'</description>
+ </problem>
+</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/a/Independent.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/a/Independent.java
new file mode 100644
index 0000000..b8c2cd4
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/a/Independent.java
@@ -0,0 +1,11 @@
+package a;
+
+import a.a.A;
+
+public class Independent {
+
+ void foo() {
+ System.out.println(new String());
+ A a = new A;
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/a/a/A.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/a/a/A.java
new file mode 100644
index 0000000..e796ed9
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/a/a/A.java
@@ -0,0 +1,4 @@
+package com.siyeh.igtest.dependency.cyclic_package_dependency.src.a.a;
+
+public class A {
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/b/Cycle1.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/b/Cycle1.java
new file mode 100644
index 0000000..d61590b
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/b/Cycle1.java
@@ -0,0 +1,30 @@
+/*
+ * 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 b;
+
+import c.Cycle2;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class Cycle1 {
+
+ public void a() {}
+
+ void b(Cycle2 c) {
+ c.b();
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/c/Cycle2.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/c/Cycle2.java
new file mode 100644
index 0000000..39aa6d9
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dependency/cyclic_package_dependency/src/c/Cycle2.java
@@ -0,0 +1,30 @@
+/*
+ * 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 c;
+
+import b.Cycle1;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class Cycle2 {
+
+ public void b() {}
+
+ void c(Cycle1 c) {
+ c.a();
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/inheritance/extends_concrete_collection/ExtendsConcreteCollection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/inheritance/extends_concrete_collection/ExtendsConcreteCollection.java
new file mode 100644
index 0000000..bceca3b
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/inheritance/extends_concrete_collection/ExtendsConcreteCollection.java
@@ -0,0 +1,17 @@
+package com.siyeh.igtest.inheritance.extends_concrete_collection;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+class <warning descr="Class 'ExtendsConcreteCollection' explicitly extends 'java.util.ArrayList'">ExtendsConcreteCollection</warning> extends ArrayList {
+
+}
+class MyMap extends LinkedHashMap<String, String> {
+ @Override
+ protected boolean removeEldestEntry(Map.Entry<String, String> eldest) {
+ return true;
+ }
+}
+class <warning descr="Class 'MyDeque' explicitly extends 'java.util.ArrayDeque'">MyDeque</warning> extends ArrayDeque {}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/inheritance/redundant_method_override/RedundantMethodOverride.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/inheritance/redundant_method_override/RedundantMethodOverride.java
new file mode 100644
index 0000000..797cab3
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/inheritance/redundant_method_override/RedundantMethodOverride.java
@@ -0,0 +1,31 @@
+package redundant_method_override;
+
+public class RedundantMethodOverride extends S {
+
+ @Override
+ void <warning descr="Method 'foo()' is identical to its super method">foo</warning>() {
+ System.out.println();
+ }
+
+ void bar() {
+ System.out.println();
+ }
+
+ public void m() {
+ System.out.println();
+ }
+}
+class S {
+
+ void foo() {
+ System.out.println();
+ }
+
+ synchronized void bar() {
+ System.out.println();
+ }
+
+ void m() {
+ System.out.println();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/Base.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/Base.java
deleted file mode 100644
index cd02633..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/Base.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.igtest.initialization;
-
-public class Base {
-
- public void foo() {
-
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/OverriddenMethodCallInConstructor.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/OverriddenMethodCallInConstructor.java
deleted file mode 100644
index a1cd58a..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/OverriddenMethodCallInConstructor.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.igtest.initialization;
-
-public class OverriddenMethodCallInConstructor extends Base {
-
- OverriddenMethodCallInConstructor() {
- foo();
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/Overrider.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/Overrider.java
deleted file mode 100644
index e244bec..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/Overrider.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.siyeh.igtest.initialization;
-
-public class Overrider extends OverriddenMethodCallInConstructor {
-
- public void foo() {
- System.out.println();
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/overridden_method_call_during_object_construction/OverriddenMethodCallDuringObjectConstruction.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/overridden_method_call_during_object_construction/OverriddenMethodCallDuringObjectConstruction.java
new file mode 100644
index 0000000..83762a6
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/initialization/overridden_method_call_during_object_construction/OverriddenMethodCallDuringObjectConstruction.java
@@ -0,0 +1,36 @@
+package initialization.overridden_method_call_during_object_construction;
+
+public class OverriddenMethodCallDuringObjectConstruction extends Base {
+ OverriddenMethodCallDuringObjectConstruction o;
+ {
+ try {
+ o = (OverriddenMethodCallDuringObjectConstruction)<warning descr="Call to overridden method 'clone()' during object construction">clone</warning>();
+ }
+ catch (CloneNotSupportedException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ OverriddenMethodCallDuringObjectConstruction() {
+ <warning descr="Call to overridden method 'foo()' during object construction">foo</warning>();
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+}
+class Base implements Cloneable {
+ public void foo() {}
+}
+class Overrider extends OverriddenMethodCallDuringObjectConstruction {
+ public void foo() {
+ System.out.println();
+ }
+
+ @Override
+ protected Object clone() throws CloneNotSupportedException {
+ return super.clone();
+ }
+}
+
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java
new file mode 100644
index 0000000..17dd59e
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/implicit_default_charset_usage/ImplicitDefaultCharsetUsage.java
@@ -0,0 +1,40 @@
+package com.siyeh.igtest.internationalization.implicit_default_charset_usage;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.Formatter;
+import java.util.Locale;
+import java.util.Scanner;
+
+class ImplicitDefaultCharsetUsage {
+
+ void f() throws IOException {
+ final byte[] bytes = "asdf".<warning descr="Call to 'getBytes()' uses the platform's default charset">getBytes</warning>();
+ "asdf".getBytes("");
+ new String();
+ new String("asdfas");
+ new String(new byte[10], "asdf");
+ new <warning descr="'new String()' call uses the platform's default charset">String</warning>(new byte[10]);
+ new <warning descr="'new String()' call uses the platform's default charset">String</warning>(new byte[10], 1, 9);
+ new <warning descr="'new InputStreamReader()' call uses the platform's default charset">InputStreamReader</warning>(null);
+ new InputStreamReader(null, "utf-8");
+ new <warning descr="'new OutputStreamWriter()' call uses the platform's default charset">OutputStreamWriter</warning>(null);
+ new OutputStreamWriter(null, "utf-8");
+ new <warning descr="'new FileReader()' call uses the platform's default charset">FileReader</warning>("asdf");
+ new <warning descr="'new FileWriter()' call uses the platform's default charset">FileWriter</warning>((String)null);
+ new <warning descr="'new PrintStream()' call uses the platform's default charset">PrintStream</warning>((OutputStream)null);
+ new PrintStream("filename", "utf-8");
+ new PrintStream("filename");
+ new PrintWriter((Writer)null);
+ new PrintWriter("filename", "utf-8");
+ new <warning descr="'new PrintWriter()' call uses the platform's default charset">PrintWriter</warning>("filename");
+ new <warning descr="'new Formatter()' call uses the platform's default charset">Formatter</warning>(new FileOutputStream("null"));
+ new Formatter(new FileOutputStream("null"), "utf-8");
+ new Formatter(new FileOutputStream("null"), "utf-8", Locale.getDefault());
+ new Formatter(System.out);
+ new <warning descr="'new Scanner()' call uses the platform's default charset">Scanner</warning>(new FileInputStream("null"));
+ new Scanner(new FileInputStream("null"), "utf-8");
+ new Scanner("string input");
+ new ArrayList(10);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/simple_date_format_without_locale/SimpleDateFormatWithoutLocale.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/simple_date_format_without_locale/SimpleDateFormatWithoutLocale.java
new file mode 100644
index 0000000..17f9c30
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/internationalization/simple_date_format_without_locale/SimpleDateFormatWithoutLocale.java
@@ -0,0 +1,12 @@
+package com.siyeh.igtest.internationalization.simple_date_format_without_locale;
+
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+class SimpleDateFormatWithoutLocale {
+
+ void m() {
+ new <warning descr="Instantiating a 'SimpleDateFormat' without specifying a Locale in an internationalized context">SimpleDateFormat</warning>("yyyy");
+ new SimpleDateFormat("yyyy", Locale.getDefault());
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/PrivateMemberAccessBetweenOuterAndInnerClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/PrivateMemberAccessBetweenOuterAndInnerClass.java
deleted file mode 100644
index d5c6f75..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/PrivateMemberAccessBetweenOuterAndInnerClass.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.siyeh.igtest.j2me;
-
-import java.awt.*;
-
-
-public class PrivateMemberAccessBetweenOuterAndInnerClass {
- private String caption = "Button";
-
- private void initialize() {
- Button btn = new Button(caption) {
- public void foo() {
- System.out.println(caption);
- }
- };
- }
-}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/private_member_access_between_outer_and_inner_class/PrivateMemberAccessBetweenOuterAndInnerClass.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/private_member_access_between_outer_and_inner_class/PrivateMemberAccessBetweenOuterAndInnerClass.java
new file mode 100644
index 0000000..a0ebd06
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/private_member_access_between_outer_and_inner_class/PrivateMemberAccessBetweenOuterAndInnerClass.java
@@ -0,0 +1,14 @@
+package com.siyeh.igtest.j2me.private_member_access_between_outer_and_inner_class;
+
+public class PrivateMemberAccessBetweenOuterAndInnerClass {
+ private String caption = "Button";
+
+ private void initialize() {
+ System.out.println(caption);
+ Object btn = new Object() {
+ public void foo() {
+ System.out.println(<warning descr="Access to private member of class 'PrivateMemberAccessBetweenOuterAndInnerClass'">caption</warning>);
+ }
+ };
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/private_member_access_between_outer_and_inner_class/Simple.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/private_member_access_between_outer_and_inner_class/Simple.java
new file mode 100644
index 0000000..72143f8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/j2me/private_member_access_between_outer_and_inner_class/Simple.java
@@ -0,0 +1,21 @@
+package com.siyeh.igtest.j2me.private_member_access_between_outer_and_inner_class;
+
+public class Simple {
+
+ private int i;
+
+ private Simple() {}
+
+ private void foo() {}
+
+ class Inner {{
+ new <warning descr="Access to private member of class 'Simple'">Simple</warning>();
+ System.out.println(<warning descr="Access to private member of class 'Simple'">i</warning>);
+ <warning descr="Access to private member of class 'Simple'">foo</warning>();
+ }}
+}
+class Other {
+ void foo(Simple o) {
+ System.out.println(o.<error descr="'i' has private access in 'com.siyeh.igtest.j2me.private_member_access_between_outer_and_inner_class.Simple'">i</error>);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/misordered_assert_equals_parameters/Simple.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/misordered_assert_equals_parameters/Simple.java
new file mode 100644
index 0000000..e4497c6
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/misordered_assert_equals_parameters/Simple.java
@@ -0,0 +1,16 @@
+import org.junit.Assert;
+
+class Simple {
+
+ public static final int EXPECTED = -9;
+
+ private class BeanCreator {
+
+ public BeanCreator withQuery(int s) {
+ Assert.<warning descr="Arguments to 'assertEquals()' in wrong order">assertEquals</warning>(s, -1);
+ Assert.<warning descr="Arguments to 'assertSame()' in wrong order">assertSame</warning>(s, EXPECTED);
+ junit.framework.Assert.<warning descr="Arguments to 'failNotEquals()' in wrong order">failNotEquals</warning>("asdfasd", s, EXPECTED);
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/use_of_obsolete_assert/ObsoleteAssert.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/use_of_obsolete_assert/ObsoleteAssert.java
new file mode 100644
index 0000000..4087eb8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/junit/use_of_obsolete_assert/ObsoleteAssert.java
@@ -0,0 +1,8 @@
+package com.siyeh.igtest.junit.use_of_obsolete_assert;
+
+public class ObsoleteAssert {
+
+ public void testMe(int s) {
+ junit.framework.Assert.<warning descr="Call to 'assertEquals()' from 'junit.framework.Assert' should be replaced with call to method from 'org.junit.Assert'">assertEquals</warning>("asdfasd", -1, s);
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java
index 0bca769..34b698f 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/MethodCanBeVariableArity.java
@@ -27,4 +27,9 @@
}
class Annotated {
public void nullable(@org.jetbrains.annotations.Nullable String[] ss) {}
+
+ void m(String[] ss) {}
+}
+interface X {
+ void m(String[] ss);
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/expected.xml
index 128a5b6..8158e87 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/migration/method_can_be_variable_arity_method/expected.xml
@@ -8,4 +8,11 @@
<description><code>convertMe()</code> can be converted to variable arity method</description>
</problem>
+ <problem>
+ <file>MethodCanBeVariableArity.java</file>
+ <line>34</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Method can be variable arity method</problem_class>
+ <description><code>m()</code> can be converted to variable arity method #loc</description>
+ </problem>
+
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/abstract_class_naming_convention/Simple.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/abstract_class_naming_convention/Simple.java
new file mode 100644
index 0000000..fdb4e75
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/naming/abstract_class_naming_convention/Simple.java
@@ -0,0 +1,4 @@
+package com.siyeh.igtest.naming.abstract_class_naming_convention;
+
+public abstract class <warning descr="Abstract class name 'Simple' is too short">Simple</warning> {
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/PointlessArithmeticExpression.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/PointlessArithmeticExpression.java
index d71e960..5f6231d 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/PointlessArithmeticExpression.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/PointlessArithmeticExpression.java
@@ -88,4 +88,26 @@
double floatsOrDoubles() {
return 123.001 % 1.0;
}
+
+ void more(int i) {
+ System.out.println(i / i);
+ System.out.println(i - i);
+ System.out.println(i % i);
+ }
}
+class Main {
+ private static final int CONST = 9;
+ int i;
+ Main(int i) {
+ this.i = i;
+ }
+
+ static int doo() {
+ return new Main(1).i - new Main(0).i;
+ }
+
+ int fly(int i) {
+ final Main main = new Main(12);
+ return (CONST + (new Main(5).i) * 8) - (Main.CONST + new Main(5).i * (8));
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/expected.xml
index 8d6ce07..84ac4f2 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/pointless_arithmetic_expression/expected.xml
@@ -120,4 +120,31 @@
<description><code>i < Integer.MIN_VALUE</code> can be replaced with 'false' #loc</description>
</problem>
+ <problem>
+ <file>PointlessArithmeticExpression.java</file>
+ <line>93</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless arithmetic expression</problem_class>
+ <description><code>i / i</code> can be replaced with '1' #loc</description>
+ </problem>
+
+ <problem>
+ <file>PointlessArithmeticExpression.java</file>
+ <line>94</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless arithmetic expression</problem_class>
+ <description><code>i - i</code> can be replaced with '0' #loc</description>
+ </problem>
+
+ <problem>
+ <file>PointlessArithmeticExpression.java</file>
+ <line>95</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless arithmetic expression</problem_class>
+ <description><code>i % i</code> can be replaced with '0' #loc</description>
+ </problem>
+
+ <problem>
+ <file>PointlessArithmeticExpression.java</file>
+ <line>111</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Pointless arithmetic expression</problem_class>
+ <description><code>(CONST + (new Main(5).i) * 8) - (Main.CONST + new Main(5).i * (8))</code> can be replaced with '0' #loc</description>
+ </problem>
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java
index 26cc95a..a625c87 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/numeric/unnecessary_explicit_numeric_cast/UnnecessaryExplicitNumericCast.java
@@ -63,4 +63,8 @@
int i() {
return 10;
}
+
+ boolean redundantTypeCast(long l) {
+ return 0L == (long)l;
+ }
}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/packaging/disjoint_package/extends_implements_reference/Ferrari.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/packaging/disjoint_package/extends_implements_reference/Ferrari.java
index 7bbeb16..716e2a3 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/packaging/disjoint_package/extends_implements_reference/Ferrari.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/packaging/disjoint_package/extends_implements_reference/Ferrari.java
@@ -5,4 +5,7 @@
}
interface Car {
void start();
+}
+class Factory<T extends Car> {
+ T create();
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/CollectionsMustHaveInitialCapacityInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/CollectionsMustHaveInitialCapacityInspection.java
deleted file mode 100644
index 56e19ae..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/CollectionsMustHaveInitialCapacityInspection.java
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.siyeh.igtest.performance;
-
-import java.io.IOException;
-import java.util.*;
-
-public class CollectionsMustHaveInitialCapacityInspection
-{
- public CollectionsMustHaveInitialCapacityInspection()
- {
- }
-
- public void foo() throws IOException
- {
- // new HashMap<String, String>();
- // new HashMap<String, String>(3);
-
- new HashMap();
- new HashMap(3);
-
- new WeakHashMap();
- new WeakHashMap(3);
-
- new HashSet();
- new HashSet(3);
-
- new Hashtable();
- new Hashtable(3);
-
- new BitSet();
- new BitSet(3);
-
- new Vector();
- new Vector(3);
-
- new ArrayList();
- new ArrayList(3);
-
-
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/StringBufferMustHaveInitialCapacityInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/StringBufferMustHaveInitialCapacityInspection.java
deleted file mode 100644
index 7fe4ae3..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/StringBufferMustHaveInitialCapacityInspection.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.siyeh.igtest.performance;
-
-import java.io.IOException;
-
-public class StringBufferMustHaveInitialCapacityInspection
-{
- public StringBufferMustHaveInitialCapacityInspection()
- {
- }
-
- public void foo() throws IOException
- {
- new StringBuffer();
- new StringBuffer(3);
- new StringBuffer("foo");
- new StringBuilder();
- new StringBuilder(3);
- new StringBuilder("foo");
-
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/boolean_constructor/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/boolean_constructor/expected.xml
index d7cc45f..f7bc79d 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/boolean_constructor/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/boolean_constructor/expected.xml
@@ -4,14 +4,14 @@
<file>BooleanConstructor.java</file>
<line>7</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Boolean constructor call</problem_class>
- <description>Boolean constructor call <code>new Boolean(b)</code> #loc</description>
+ <description>Boolean constructor call #loc</description>
</problem>
<problem>
<file>BooleanConstructor.java</file>
<line>8</line>
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Boolean constructor call</problem_class>
- <description>Boolean constructor call <code>new Boolean(true)</code> #loc</description>
+ <description>Boolean constructor call #loc</description>
</problem>
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/InnerClassMayBeStaticInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/InnerClassMayBeStaticInspection.java
index 7b14d86..0db367c 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/InnerClassMayBeStaticInspection.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/InnerClassMayBeStaticInspection.java
@@ -44,16 +44,54 @@
void foo() {
new Object() {
class Y {}
- }
+ };
}
}
class StaticInnerClass {
private int foo;
+ int bar;
public class Baz extends StaticInnerClass {
Baz() {
foo = -1;
}
}
-}
\ No newline at end of file
+ class C extends StaticInnerClass {{
+ bar = 1;
+ }}
+}
+class SomeBeanUnitTest {
+
+ private class BeanCreator {
+
+ public BeanCreator withQuery() {
+ return null;
+ }
+ }
+}
+class Outer {
+ class A { // may not be static
+ B b;
+ }
+ class B extends A {} // may not be static
+
+ class C { // may be static
+ D b;
+ class D extends C {}
+ }
+
+ static class E {
+ G.F b;
+ class G { // may be static
+ class F extends E {}
+ }
+ }
+
+ class H { // may be static
+ J.I b;
+ class J {
+ class I extends H {}
+ }
+ }
+}
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/expected.xml
index 20b5383..0eb4ed3 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/inner_class_may_be_static/expected.xml
@@ -1,9 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<problems>
- <problem>
- <file>InnerClassMayBeStaticInspection.java</file>
- <line>6</line>
- <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
- <description>Inner class <code>Nested</code> may be 'static' #loc</description>
- </problem>
+ <problem>
+ <file>InnerClassMayBeStaticInspection.java</file>
+ <line>6</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
+ <description>Inner class <code>Nested</code> may be 'static' #loc</description>
+ </problem>
+
+ <problem>
+ <file>InnerClassMayBeStaticInspection.java</file>
+ <line>60</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
+ <description>Inner class <code>C</code> may be 'static' #loc</description>
+ </problem>
+
+ <problem>
+ <file>InnerClassMayBeStaticInspection.java</file>
+ <line>66</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
+ <description>Inner class <code>BeanCreator</code> may be 'static' #loc</description>
+ </problem>
+
+ <problem>
+ <file>InnerClassMayBeStaticInspection.java</file>
+ <line>79</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
+ <description>Inner class <code>C</code> may be 'static' #loc</description>
+ </problem>
+
+ <problem>
+ <file>InnerClassMayBeStaticInspection.java</file>
+ <line>86</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
+ <description>Inner class <code>G</code> may be 'static' #loc</description>
+ </problem>
+
+ <problem>
+ <file>InnerClassMayBeStaticInspection.java</file>
+ <line>91</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Inner class may be 'static'</problem_class>
+ <description>Inner class <code>H</code> may be 'static' #loc</description>
+ </problem>
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java
new file mode 100644
index 0000000..58581df
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/object_allocation_in_loop/ObjectAllocationInLoop.java
@@ -0,0 +1,10 @@
+package com.siyeh.igtest.performance.object_allocation_in_loop;
+
+class ObjectAllocationInLoop {
+
+ void m() {
+ while (true) {
+ new <warning descr="Object allocation 'new Object()' in loop">Object</warning>();
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_must_have_initial_capacity/StringBufferMustHaveInitialCapacity.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_must_have_initial_capacity/StringBufferMustHaveInitialCapacity.java
new file mode 100644
index 0000000..ad36725
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/performance/string_buffer_must_have_initial_capacity/StringBufferMustHaveInitialCapacity.java
@@ -0,0 +1,13 @@
+package com.siyeh.igtest.performance.string_buffer_must_have_initial_capacity;
+
+class StringBufferMustHaveInitialCapacity {
+
+ void m() {
+ new <warning descr="'new StringBuffer()' without initial capacity">StringBuffer</warning>();
+ new StringBuffer(3);
+ new StringBuffer("foo");
+ new <warning descr="'new StringBuilder()' without initial capacity">StringBuilder</warning>();
+ new StringBuilder(3);
+ new StringBuilder("foo"); }
+
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/security/ArchaicSystemPropertiesAccessInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/security/ArchaicSystemPropertiesAccessInspection.java
deleted file mode 100644
index bb0721a..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/security/ArchaicSystemPropertiesAccessInspection.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.siyeh.igtest.security;
-
-public class ArchaicSystemPropertiesAccessInspection{
- public void foo(){
- System.getProperties();
- System.getProperty("foo");
- Integer.getInteger("foo");
- Boolean.getBoolean("foo");
- }
-}
diff --git a/java/java-tests/testData/inspection/nullableProblems/notNullFieldNullableParam/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/methodRef/expected.xml
similarity index 100%
rename from java/java-tests/testData/inspection/nullableProblems/notNullFieldNullableParam/expected.xml
rename to plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/methodRef/expected.xml
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/methodRef/src/Test.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/methodRef/src/Test.java
new file mode 100644
index 0000000..cf83f93
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/methodRef/src/Test.java
@@ -0,0 +1,8 @@
+import static java.lang.Character.toLowerCase;
+
+public class StaticImport {
+
+ void example() {
+ "".codePoints().map(Character::toLowerCase);
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/Test.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/Test.java
index c32ed52..a12fa73 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/Test.java
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/Test.java
@@ -1,7 +1,7 @@
package com.siyeh.igtest.style.unqualified_inner_class_access;
import java.util.Map.Entry;
-
+import com.siyeh.igtest.style.unqualified_inner_class_access.A.X;
public class Test<T> {
private Class<Entry> entryClass;
@@ -22,4 +22,9 @@
}
class B extends A {
void foo(X x) {}
+}
+class C {
+ void m(X x) {
+ new A().new X();
+ }
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/expected.xml
index 2bc83c2..2e6c566 100644
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/expected.xml
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/style/unqualified_inner_class_access/expected.xml
@@ -21,4 +21,10 @@
<description><code>Entry</code> is not qualified with outer class #loc</description>
</problem>
+ <problem>
+ <file>Test.java</file>
+ <line>27</line>
+ <problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Unqualified inner class access</problem_class>
+ <description><code>X</code> is not qualified with outer class #loc</description>
+ </problem>
</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/defaultRun/LambdaExpr.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/defaultRun/LambdaExpr.java
new file mode 100644
index 0000000..453a9e9
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/defaultRun/LambdaExpr.java
@@ -0,0 +1,6 @@
+package com.siyeh.igtest.threading.defaultRun;
+class Test {
+ {
+ new Thread(() -> System.out.println("hello")).start();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/defaultRun/expected.xml b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/defaultRun/expected.xml
new file mode 100644
index 0000000..216a575
--- /dev/null
+++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/threading/defaultRun/expected.xml
@@ -0,0 +1 @@
+<problems/>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/visibility/TypeParameterHidesVisibleTypeInspection.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/visibility/TypeParameterHidesVisibleTypeInspection.java
deleted file mode 100644
index b5faef7..0000000
--- a/plugins/InspectionGadgets/test/com/siyeh/igtest/visibility/TypeParameterHidesVisibleTypeInspection.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.siyeh.igtest.visibility;
-import java.util.*;
-
-public abstract class TypeParameterHidesVisibleTypeInspection<List> {
- private Map map = new HashMap();
-
- public abstract List foo();
-
- public abstract <Set> Set bar();
- public abstract <TypeParameterHidesVisibleTypeInspection> TypeParameterHidesVisibleTypeInspection baz();
- public abstract <InputStream> InputStream baz3();
- public abstract <A> A baz2();
-}
diff --git a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInverted/src/Test.java b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInverted/src/Test.java
index 1670e74..b94de8b 100644
--- a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInverted/src/Test.java
+++ b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInverted/src/Test.java
@@ -7,6 +7,7 @@
if (!foo()){
return;
}
+ System.out.println(!foo());
}
int bah() {
diff --git a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedByRange/src/Test.java b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedByRange/src/Test.java
index 1670e74..d82a24d 100644
--- a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedByRange/src/Test.java
+++ b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedByRange/src/Test.java
@@ -10,6 +10,7 @@
}
int bah() {
+ System.out.println(!foo());
return bah();
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedDelegation/expected.xml b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedDelegation/expected.xml
new file mode 100644
index 0000000..01b4314
--- /dev/null
+++ b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedDelegation/expected.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<problems>
+ <problem>
+ <file>Test.java</file>
+ <line>2</line>
+ <problem_class>Boolean method is always inverted</problem_class>
+ <description>inverted</description>
+ </problem>
+</problems>
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedDelegation/src/Test.java b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedDelegation/src/Test.java
new file mode 100644
index 0000000..1ee5b4c
--- /dev/null
+++ b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedDelegation/src/Test.java
@@ -0,0 +1,20 @@
+class SuperClass {
+ boolean foo(){
+ return false;
+ }
+
+ void bar(){
+ if (!foo()){
+ return;
+ }
+ }
+
+ int bah() {
+ return bah();
+ }
+}
+class Test extends SuperClass{
+ boolean foo(){
+ return super.foo();
+ }
+}
\ No newline at end of file
diff --git a/java/java-tests/testData/inspection/nullableProblems/notNullFieldNullableParam/expected.xml b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedOneUsage/expected.xml
similarity index 100%
copy from java/java-tests/testData/inspection/nullableProblems/notNullFieldNullableParam/expected.xml
copy to plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedOneUsage/expected.xml
diff --git a/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedOneUsage/src/Test.java b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedOneUsage/src/Test.java
new file mode 100644
index 0000000..fd78cb8
--- /dev/null
+++ b/plugins/InspectionGadgets/test/invertedBoolean/alwaysInvertedOneUsage/src/Test.java
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+class Test {
+ boolean foo(){
+ return false;
+ }
+
+ void bar(){
+ if (!foo()){
+ return;
+ }
+ }
+
+ int bah() {
+ return bah();
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/intellij/codeInspection/BooleanMethodInvertedTest.java b/plugins/InspectionGadgets/testsrc/com/intellij/codeInspection/BooleanMethodInvertedTest.java
index ea09612..0fa73d2 100644
--- a/plugins/InspectionGadgets/testsrc/com/intellij/codeInspection/BooleanMethodInvertedTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/intellij/codeInspection/BooleanMethodInvertedTest.java
@@ -21,6 +21,14 @@
doTest();
}
+ public void testAlwaysInvertedDelegation() throws Exception {
+ doTest();
+ }
+
+ public void testAlwaysInvertedOneUsage() throws Exception {
+ doTest();
+ }
+
public void testAlwaysInvertedByRange() throws Exception {
doTest(true);
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
index 20ce1a9..7a3bad5 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/LightInspectionTestCase.java
@@ -40,6 +40,7 @@
protected abstract InspectionProfileEntry getInspection();
@NonNls
+ @Language("JAVA")
protected String[] getEnvironmentClasses() {
return ArrayUtil.EMPTY_STRING_ARRAY;
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/CyclicClassDependencyInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/CyclicClassDependencyInspectionTest.java
deleted file mode 100644
index 08e2faa..0000000
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/CyclicClassDependencyInspectionTest.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.siyeh.ig.abstraction;
-
-import com.siyeh.ig.IGInspectionTestCase;
-import com.siyeh.ig.dependency.CyclicClassDependencyInspection;
-
-/**
- * @author Bas Leijdekkers
- */
-public class CyclicClassDependencyInspectionTest extends IGInspectionTestCase {
-
- public void test() {
- doTest("com/siyeh/igtest/abstraction/cyclic_class_dependency", new CyclicClassDependencyInspection());
- }
-}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/MagicNumberInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/MagicNumberInspectionTest.java
index d1423b1..3696d70 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/MagicNumberInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/abstraction/MagicNumberInspectionTest.java
@@ -8,6 +8,7 @@
final MagicNumberInspection tool = new MagicNumberInspection();
tool.ignoreInHashCode = true;
tool.ignoreInAnnotations = true;
+ tool.ignoreInitialCapacity = true;
doTest("com/siyeh/igtest/abstraction/magic_number", tool);
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ArrayEqualityInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ArrayEqualityInspectionTest.java
new file mode 100644
index 0000000..c8493a2
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/ArrayEqualityInspectionTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.bugs;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ArrayEqualityInspectionTest extends LightInspectionTestCase {
+
+ public void testArrayEquality() {
+ doTest();
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ArrayEqualityInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/NumberEqualityInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/NumberEqualityInspectionTest.java
new file mode 100644
index 0000000..5036d9c
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/NumberEqualityInspectionTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.bugs;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class NumberEqualityInspectionTest extends LightInspectionTestCase {
+
+ public void testNumberEquality() {
+ doTest();
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new NumberEqualityInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspectionTest.java
new file mode 100644
index 0000000..33c74e4
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/bugs/StaticFieldReferenceOnSubclassInspectionTest.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.siyeh.ig.bugs;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class StaticFieldReferenceOnSubclassInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new StaticFieldReferenceOnSubclassInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package a;" +
+ "public class A {" +
+ " private static class AA {\n" +
+ " public static final int VALUE = 5;\n" +
+ " }" +
+ " public static class AB extends AA {\n" +
+ " }" +
+ " public static final String S = \"\";" +
+ "}",
+ "package a;" +
+ "public class B extends A {}"
+ };
+ }
+
+ public void testSimple() {
+ doStatementTest("System.out.println(a.B./*Static field 'S' declared in class 'a.A' but referenced via subclass 'a.B'*/S/**/);");
+ }
+
+ public void testNoWarn() {
+ doStatementTest("System.out.println(a.A.AB.VALUE);");
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassInitializerInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassInitializerInspectionTest.java
new file mode 100644
index 0000000..f950d3e
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/ClassInitializerInspectionTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.siyeh.ig.classlayout;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ClassInitializerInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() { doTest(); }
+ public void testAnonymous() { doTest(); }
+
+ public void testNoConstructor() {
+ final ClassInitializerInspection inspection = new ClassInitializerInspection();
+ inspection.onlyWarnWhenConstructor = true;
+ myFixture.enableInspections(inspection);
+ doTest();
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ClassInitializerInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspectionTest.java
new file mode 100644
index 0000000..ab4e3e8
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/classlayout/InterfaceMayBeAnnotatedFunctionalInspectionTest.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.siyeh.ig.classlayout;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class InterfaceMayBeAnnotatedFunctionalInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() {
+ doTest("interface /*Interface 'Simple' may be annotated with @FunctionalInterface*/Simple/**/ {" +
+ " void f();" +
+ "}");
+ }
+
+ public void testLessSimple() {
+ doTest("interface /*Interface 'F' may be annotated with @FunctionalInterface*/F/**/ {" +
+ " boolean equals(Object o);" +
+ " static void f00() {}\n" +
+ " default void g() {}\n" +
+ " void f();\n" +
+ "}");
+ }
+
+ public void testNotFunctional() {
+ doTest("interface G {" +
+ "<T> void f();" +
+ "}");
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new InterfaceMayBeAnnotatedFunctionalInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneCallsConstructorsInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneCallsConstructorsInspectionTest.java
new file mode 100644
index 0000000..db06e4e
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/cloneable/CloneCallsConstructorsInspectionTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.cloneable;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class CloneCallsConstructorsInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new CloneCallsConstructorsInspection();
+ }
+
+ public void testCloneCallsConstructors() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspectionTest.java
new file mode 100644
index 0000000..927db2f
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ConstantConditionalExpressionInspectionTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.controlflow;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ConstantConditionalExpressionInspectionTest extends LightInspectionTestCase {
+
+ public void testParentheses() {
+ doStatementTest("int i = /*'((true)) ? 1 : 2' can be simplified to '1'*/((true)) ? 1 : 2/**/;");
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ConstantConditionalExpressionInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ConstantIfStatementInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ConstantIfStatementInspectionTest.java
new file mode 100644
index 0000000..2e08d02
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/controlflow/ConstantIfStatementInspectionTest.java
@@ -0,0 +1,38 @@
+/*
+ * 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.siyeh.ig.controlflow;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ConstantIfStatementInspectionTest extends LightInspectionTestCase {
+
+ public void testParentheses() {
+ doStatementTest("/*'if' statement can be simplified*/if/**/ (((false))) {\n" +
+ " System.out.println(1);\n" +
+ " } else {\n" +
+ " System.out.println(2);\n" +
+ " }");
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ConstantIfStatementInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/CyclicClassDependencyInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/CyclicClassDependencyInspectionTest.java
new file mode 100644
index 0000000..2f3d024
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/CyclicClassDependencyInspectionTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.siyeh.ig.dependency;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class CyclicClassDependencyInspectionTest extends IGInspectionTestCase {
+
+ public void test() {
+ doTest("com/siyeh/igtest/dependency/cyclic_class_dependency", new CyclicClassDependencyInspection());
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/CyclicPackageDependencyInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/CyclicPackageDependencyInspectionTest.java
new file mode 100644
index 0000000..47da4a7
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/dependency/CyclicPackageDependencyInspectionTest.java
@@ -0,0 +1,28 @@
+/*
+ * 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.siyeh.ig.dependency;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class CyclicPackageDependencyInspectionTest extends IGInspectionTestCase {
+
+ public void test() {
+ doTest("com/siyeh/igtest/dependency/cyclic_package_dependency", new CyclicPackageDependencyInspection());
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionTest.java
index 5648d57..72529ce 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/errorhandling/EmptyCatchBlockInspectionTest.java
@@ -66,15 +66,4 @@
" }\n" +
"}\n");
}
-
- public void testTest() {
- doTest("import junit.framework.TestCase;\n" +
- "class C extends TestCase {\n" +
- " void m() {\n" +
- " try {\n" +
- " throw new Exception();\n" +
- " } catch (Exception e) {}\n" +
- " }\n" +
- "}\n");
- }
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassInitializerFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassInitializerFixTest.java
new file mode 100644
index 0000000..a414593
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/classlayout/ClassInitializerFixTest.java
@@ -0,0 +1,22 @@
+package com.siyeh.ig.fixes.classlayout;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.classlayout.ClassInitializerInspection;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ClassInitializerFixTest extends IGQuickFixesTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new ClassInitializerInspection());
+ myRelativePath = "classlayout/class_initializer";
+ myDefaultHint = InspectionGadgetsBundle.message("class.initializer.move.code.to.constructor.quickfix");
+ }
+
+ public void testNoConstructor() { doTest(); }
+ public void testChainedConstructor() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/TrivialIfFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/TrivialIfFixTest.java
new file mode 100644
index 0000000..ee6dc83
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/TrivialIfFixTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.siyeh.ig.fixes.controlflow;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.controlflow.TrivialIfInspection;
+
+import java.util.List;
+
+public class TrivialIfFixTest extends IGQuickFixesTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new TrivialIfInspection());
+ myRelativePath = "controlflow/trivialIf";
+ }
+
+ public void testComments() {
+ doTestByName(getTestName(false));
+ }
+
+ public void testCommentsInAssignment() {
+ doTestByName(getTestName(false));
+ }
+
+ public void doTestByName(String testName) {
+ myFixture.configureByFile(getRelativePath() + "/" + testName + ".java");
+ final String message = InspectionGadgetsBundle.message("constant.conditional.expression.simplify.quickfix");
+ final List<IntentionAction> actions =
+ myFixture.filterAvailableIntentions(message);
+ assertFalse("No actions available", actions.isEmpty());
+ for (IntentionAction action : actions) {
+ if (action.getText().equals(message)) {
+ myFixture.launchAction(action);
+ myFixture.checkResultByFile(getRelativePath() + "/" + testName + ".after.java");
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/TrivialIfInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/TrivialIfInspectionTest.java
deleted file mode 100644
index 013c1e8..0000000
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/controlflow/TrivialIfInspectionTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.siyeh.ig.fixes.controlflow;
-
-import com.intellij.codeInsight.intention.IntentionAction;
-import com.siyeh.InspectionGadgetsBundle;
-import com.siyeh.ig.IGQuickFixesTestCase;
-import com.siyeh.ig.controlflow.TrivialIfInspection;
-
-import java.util.List;
-
-public class TrivialIfInspectionTest extends IGQuickFixesTestCase {
-
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- myFixture.enableInspections(new TrivialIfInspection());
- myRelativePath = "controlflow/trivialIf";
- }
-
- public void testComments() {
- final String testName = getTestName(false);
- myFixture.configureByFile(getRelativePath() + "/" + testName + ".java");
- final String message = InspectionGadgetsBundle.message("constant.conditional.expression.simplify.quickfix");
- final List<IntentionAction> actions =
- myFixture.filterAvailableIntentions(message);
- assertFalse("No actions available", actions.isEmpty());
- for (IntentionAction action : actions) {
- if (action.getText().equals(message)) {
- myFixture.launchAction(action);
- myFixture.checkResultByFile(getRelativePath() + "/" + testName + ".after.java");
- break;
- }
- }
- }
-}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/UnqualifiedInnerClassAccessFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/UnqualifiedInnerClassAccessFixTest.java
new file mode 100644
index 0000000..61a2612
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/style/UnqualifiedInnerClassAccessFixTest.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 com.siyeh.ig.fixes.style;
+
+import com.siyeh.InspectionGadgetsBundle;
+import com.siyeh.ig.IGQuickFixesTestCase;
+import com.siyeh.ig.style.UnqualifiedInnerClassAccessInspection;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class UnqualifiedInnerClassAccessFixTest extends IGQuickFixesTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.enableInspections(new UnqualifiedInnerClassAccessInspection());
+ myRelativePath = "style/unqualified_inner_class_access";
+ myDefaultHint = InspectionGadgetsBundle.message("unqualified.inner.class.access.quickfix");
+ }
+
+ public void testDeep() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
new file mode 100644
index 0000000..99c6a24
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ExtendsConcreteCollectionInspectionTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.inheritance;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ExtendsConcreteCollectionInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ExtendsConcreteCollectionInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package java.util;" +
+ "public class LinkedHashMap<K, V> {" +
+ " protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {\n" +
+ " return false;\n" +
+ " }" +
+ "}",
+ "package java.util;" +
+ "public class ArrayDeque<E> extends AbstractCollection<E> {" +
+ " public Iterator<E> iterator() { return null; }" +
+ " public int size() { return 0; }" +
+ "}"
+ };
+ }
+
+ public void testExtendsConcreteCollection() { doTest(); }
+
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspectionTest.java
index 46ec84b..036feda 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/ProblematicVarargsMethodOverrideInspectionTest.java
@@ -34,6 +34,17 @@
"}");
}
+ public void testVarargsOverriding() {
+ doTest("class One {" +
+ " void m(String... ss) {" +
+ " }" +
+ "}" +
+ "class Two extends One {" +
+ " void m(String... ss) {" +
+ " }" +
+ "}");
+ }
+
@Override
protected InspectionProfileEntry getInspection() {
return new ProblematicVarargsMethodOverrideInspection();
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/RedundantMethodOverrideInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/RedundantMethodOverrideInspectionTest.java
new file mode 100644
index 0000000..47b1d9f
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/RedundantMethodOverrideInspectionTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.inheritance;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class RedundantMethodOverrideInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new RedundantMethodOverrideInspection();
+ }
+
+ public void testRedundantMethodOverride() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/StaticInheritanceTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/StaticInheritanceTest.java
index 146e2c0..ecdb832 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/StaticInheritanceTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/inheritance/StaticInheritanceTest.java
@@ -15,7 +15,7 @@
*/
package com.siyeh.ig.inheritance;
-import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.application.PluginPathManager;
import org.jetbrains.annotations.NotNull;
@@ -23,7 +23,7 @@
/**
* User: cdr
*/
-public class StaticInheritanceTest extends LightQuickFixTestCase {
+public class StaticInheritanceTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspectionTest.java
new file mode 100644
index 0000000..eca323b
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/initialization/OverriddenMethodCallDuringObjectConstructionInspectionTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.siyeh.ig.initialization;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class OverriddenMethodCallDuringObjectConstructionInspectionTest extends LightInspectionTestCase {
+
+ public void testOverriddenMethodCallDuringObjectConstruction() {
+ doTest();
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new OverriddenMethodCallDuringObjectConstructionInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.java
new file mode 100644
index 0000000..7882249
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/ImplicitDefaultCharsetUsageInspectionTest.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 com.siyeh.ig.internationalization;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ImplicitDefaultCharsetUsageInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ImplicitDefaultCharsetUsageInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package java.io;" +
+ "import java.io.File;" +
+ "import java.io.Writer;" +
+ "public class PrintWriter {" +
+ " public PrintWriter(String fileName, String csn) {}" +
+ " public PrintWriter(String fileName) {}" +
+ " public PrintWriter(Writer writer) {}" +
+ "}",
+ "package java.util;" +
+ "import java.io.*;" +
+ "public class Formatter {" +
+ " public Formatter(OutputStream os) {}" +
+ " public Formatter(OutputStream os, String csn) {}" +
+ " public Formatter(OutputStream os, String csn, Locale l) {}" +
+ " public Formatter(PrintStream ps) {}" +
+ "}",
+ "package java.util;" +
+ "import java.io.*;" +
+ "public class Scanner {" +
+ " public Scanner(InputStream source) {}" +
+ " public Scanner(InputStream source, String charsetName) {}" +
+ " public Scanner(String source) {}" +
+ "}"
+ };
+
+ }
+
+ public void testImplicitDefaultCharsetUsage() {
+ doTest();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspectionTest.java
new file mode 100644
index 0000000..3c05139
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/internationalization/SimpleDateFormatWithoutLocaleInspectionTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.internationalization;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class SimpleDateFormatWithoutLocaleInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new SimpleDateFormatWithoutLocaleInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package java.text;" +
+ "import java.util.Locale;" +
+ "public class SimpleDateFormat {" +
+ " public SimpleDateFormat(String pattern) {}" +
+ " public SimpleDateFormat(String pattern, Locale locale) {}" +
+ "}"
+ };
+ }
+
+ public void testSimpleDateFormatWithoutLocale() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspectionTest.java
new file mode 100644
index 0000000..4c74726
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/j2me/PrivateMemberAccessBetweenOuterAndInnerClassInspectionTest.java
@@ -0,0 +1,33 @@
+/*
+ * 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.siyeh.ig.j2me;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class PrivateMemberAccessBetweenOuterAndInnerClassInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() { doTest(); }
+ public void testPrivateMemberAccessBetweenOuterAndInnerClass() { doTest(); }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new PrivateMemberAccessBetweenOuterAndInnerClassInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspectionTest.java
new file mode 100644
index 0000000..dfe13ca
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/junit/MisorderedAssertEqualsParametersInspectionTest.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.siyeh.ig.junit;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class MisorderedAssertEqualsParametersInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() { doTest(); }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package org.junit;" +
+ "public class Assert {" +
+ " static public void assertEquals(long expected, long actual) {}" +
+ " static public void assertSame(Object expected, Object actual) {}" +
+ "}",
+ "package junit.framework;" +
+ "public class Assert {" +
+ " static public void failNotEquals(String message, Object expected, Object actual) {}" +
+ "}"
+ };
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new MisorderedAssertEqualsParametersInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/junit/UseOfObsoleteAssertInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/junit/UseOfObsoleteAssertInspectionTest.java
new file mode 100644
index 0000000..19826e2
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/junit/UseOfObsoleteAssertInspectionTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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.siyeh.ig.junit;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class UseOfObsoleteAssertInspectionTest extends LightInspectionTestCase {
+
+ public void testObsoleteAssert() { doTest(); }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package junit.framework;" +
+ "public class Assert {" +
+ " static public void assertEquals(String message, int expected, int actual) {}" +
+ "}",
+ "package org.junit;" +
+ "public class Assert {}"
+ };
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new UseOfObsoleteAssertInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/SystemOutErrInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/SystemOutErrInspectionTest.java
index 382f76d..149525b 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/SystemOutErrInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/SystemOutErrInspectionTest.java
@@ -27,16 +27,6 @@
doStatementTest("/*Uses of 'System.out' should probably be replaced with more robust logging*/System.out/**/.println(\"debugging\");");
}
- public void testInTest() {
- addEnvironmentClass("package org.junit;" +
- "@Retention(RetentionPolicy.RUNTIME) " +
- "@Target({ElementType.METHOD}) " +
- "public @interface Test {}");
- doMemberTest("@org.junit.Test public void testSomething() {" +
- " System.out.println(\"debugger\");" +
- "}");
- }
-
public void testMultiple() {
doMemberTest("public void foo() {" +
" /*Uses of 'System.out' should probably be replaced with more robust logging*/System.out/**/.println(0);" +
@@ -48,8 +38,6 @@
@Override
protected InspectionProfileEntry getInspection() {
- final SystemOutErrInspection inspection = new SystemOutErrInspection();
- inspection.ignoreInTestCode = true;
- return inspection;
+ return new SystemOutErrInspection();
}
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionTest.java
index 7970516..5928bb4 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/maturity/ThrowablePrintStackTraceInspectionTest.java
@@ -33,14 +33,12 @@
"@Target({ElementType.METHOD}) " +
"public @interface Test {}");
doMemberTest("@org.junit.Test public void testSomething() {" +
- " new RuntimeException().printStackTrace();" +
+ " new RuntimeException()./*Call to 'printStackTrace()' should probably be replaced with more robust logging*/printStackTrace/**/();" +
"}");
}
@Override
protected InspectionProfileEntry getInspection() {
- final ThrowablePrintStackTraceInspection inspection = new ThrowablePrintStackTraceInspection();
- inspection.ignoreInTestCode = true;
- return inspection;
+ return new ThrowablePrintStackTraceInspection();
}
}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java
index a54bd64..9d5faec 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/migration/MethodCanBeVariableArityMethodInspectionTest.java
@@ -8,6 +8,7 @@
final MethodCanBeVariableArityMethodInspection tool = new MethodCanBeVariableArityMethodInspection();
tool.ignoreByteAndShortArrayParameters = true;
tool.ignoreOverridingMethods = true;
+ tool.onlyReportPublicMethods = true;
doTest("com/siyeh/igtest/migration/method_can_be_variable_arity_method", tool);
}
}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/AbstractClassNamingConventionInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/AbstractClassNamingConventionInspectionTest.java
new file mode 100644
index 0000000..efa576c
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/naming/AbstractClassNamingConventionInspectionTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.siyeh.ig.naming;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class AbstractClassNamingConventionInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() { doTest(); }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new AbstractClassNamingConventionInspection();
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspectionTest.java
new file mode 100644
index 0000000..20460ad
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/CollectionsMustHaveInitialCapacityInspectionTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.performance;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class CollectionsMustHaveInitialCapacityInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new CollectionsMustHaveInitialCapacityInspection();
+ }
+
+ @Override
+ protected String[] getEnvironmentClasses() {
+ return new String[] {
+ "package java.util.concurrent;" +
+ "public class ConcurrentHashMap {}",
+ "package java.util;" +
+ "public class WeakHashMap {" +
+ " public WeakHashMap() {}" +
+ " public WeakHashMap(int c) {}" +
+ "}",
+ "package java.util;" +
+ "public class HashSet {" +
+ " public HashSet() {}" +
+ " public HashSet(int c) {}" +
+ "}",
+ "package java.util;" +
+ "public class BitSet {" +
+ " public BitSet() {}" +
+ " public BitSet(int c) {}" +
+ "}",
+ "package java.util;" +
+ "public class Vector {" +
+ " public Vector() {}" +
+ " public Vector(int c) {}" +
+ "}"
+ };
+ }
+
+ public void testSimple() {
+ doStatementTest("new /*'new java.util.concurrent.ConcurrentHashMap()' without initial capacity*/java.util.concurrent.ConcurrentHashMap/**/();");
+ }
+
+ public void testMore() {
+ doTest("import java.util.*;" +
+ "class X {" +
+ " void m() {" +
+ " new /*'new HashMap<String, String>()' without initial capacity*/HashMap<String, String>/**/();" +
+ " new HashMap<String, String>(3);" +
+ " new /*'new HashMap()' without initial capacity*/HashMap/**/();" +
+ " new HashMap(3);" +
+ " new /*'new WeakHashMap()' without initial capacity*/WeakHashMap/**/();" +
+ " new WeakHashMap(3);" +
+ " new /*'new HashSet()' without initial capacity*/HashSet/**/();" +
+ " new HashSet(3);" +
+ " new /*'new Hashtable()' without initial capacity*/Hashtable/**/();" +
+ " new Hashtable(3);" +
+ " new /*'new BitSet()' without initial capacity*/BitSet/**/();" +
+ " new BitSet(3);" +
+ " new /*'new Vector()' without initial capacity*/Vector/**/();" +
+ " new Vector(3);" +
+ " new /*'new ArrayList()' without initial capacity*/ArrayList/**/();" +
+ " new ArrayList(3);" +
+ " }" +
+ "}");
+ }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/ObjectAllocationInLoopInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/ObjectAllocationInLoopInspectionTest.java
new file mode 100644
index 0000000..0fcd297
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/ObjectAllocationInLoopInspectionTest.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.performance;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ObjectAllocationInLoopInspectionTest extends LightInspectionTestCase {
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new ObjectAllocationInLoopInspection();
+ }
+
+ public void testObjectAllocationInLoop() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspectionTest.java
new file mode 100644
index 0000000..54c1488
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/performance/StringBufferMustHaveInitialCapacityInspectionTest.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.performance;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class StringBufferMustHaveInitialCapacityInspectionTest extends LightInspectionTestCase {
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new StringBufferMustHaveInitialCapacityInspection();
+ }
+
+ public void testStringBufferMustHaveInitialCapacity() { doTest(); }
+}
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java
index 258c821..df7f28b 100644
--- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/style/UnnecessarilyQualifiedStaticallyImportedElementInspectionTest.java
@@ -29,6 +29,10 @@
doTest(getTestName(true));
}
+ public void testMethodRef() throws Exception {
+ doTest(getTestName(true));
+ }
+
private void doTest(String testName) throws Exception {
doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/" + testName,
new UnnecessarilyQualifiedStaticallyImportedElementInspection());
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/ThreadWithDefaultRunInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/ThreadWithDefaultRunInspectionTest.java
new file mode 100644
index 0000000..5160c98
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/threading/ThreadWithDefaultRunInspectionTest.java
@@ -0,0 +1,25 @@
+/*
+ * 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.siyeh.ig.threading;
+
+import com.siyeh.ig.IGInspectionTestCase;
+
+public class ThreadWithDefaultRunInspectionTest extends IGInspectionTestCase {
+
+ public void test() throws Exception {
+ doTest("com/siyeh/igtest/threading/defaultRun", new ThreadWithDefaultRunMethodInspection());
+ }
+}
\ No newline at end of file
diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionTest.java
new file mode 100644
index 0000000..bc9194a
--- /dev/null
+++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/visibility/TypeParameterHidesVisibleTypeInspectionTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.siyeh.ig.visibility;
+
+import com.intellij.codeInspection.InspectionProfileEntry;
+import com.siyeh.ig.LightInspectionTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class TypeParameterHidesVisibleTypeInspectionTest extends LightInspectionTestCase {
+
+ public void testSimple() {
+ doTest("import java.util.*;\n" +
+ "public abstract class TypeParameterHidesVisibleTypeInspection<List> {\n" +
+ " private Map map = new HashMap();\n" +
+ " public abstract List foo();\n" +
+ " public abstract </*Type parameter 'Set' hides visible type 'java.util.Set'*/Set/**/> Set bar();\n" +
+ " public abstract </*Type parameter 'TypeParameterHidesVisibleTypeInspection' hides visible type 'TypeParameterHidesVisibleTypeInspection'*/TypeParameterHidesVisibleTypeInspection/**/> TypeParameterHidesVisibleTypeInspection baz();\n" +
+ " public abstract <InputStream> InputStream baz3();\n" +
+ " public abstract <A> A baz2();\n" +
+ "}\n");
+ }
+
+ public void testHiddenTypeParameter() {
+ doTest("import java.util.*;\n" +
+ "public abstract class MyList<T> extends AbstractList<T> {\n" +
+ " private List<T> elements;\n" +
+ " public </*Type parameter 'T' hides type parameter 'T'*/T/**/> T[] toArray( T[] array ) {\n" +
+ " return elements.toArray( array );\n" +
+ " }\n" +
+ "}\n");
+ }
+
+ public void testCanNotHideFromStaticContext() {
+ doTest("class Y<T> {\n" +
+ " static class X<T> {\n" +
+ " T t;\n" +
+ " }\n" +
+ " static <T> T go() {\n" +
+ " return null;\n" +
+ " }\n" +
+ "}");
+ }
+
+ public void testCannotHideFromImplicitStaticContext() {
+ doTest("interface G<T> {\n" +
+ " class I {\n" +
+ " class H<T> {\n" +
+ " T t;\n" +
+ " }\n" +
+ " }\n" +
+ "}");
+ }
+
+ @Override
+ protected InspectionProfileEntry getInspection() {
+ return new TypeParameterHidesVisibleTypeInspection();
+ }
+}
diff --git a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java
index 14c7535..c597fc8 100644
--- a/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java
+++ b/plugins/IntelliLang/java-support/org/intellij/plugins/intelliLang/inject/java/JavaLanguageInjectionSupport.java
@@ -178,7 +178,7 @@
}
private static boolean doInjectInJava(final Project project,
- final PsiElement psiElement,
+ @NotNull final PsiElement psiElement,
PsiLanguageInjectionHost host,
final String languageId) {
final PsiElement target = ContextComputationProcessor.getTopLevelInjectionTarget(psiElement);
@@ -245,7 +245,7 @@
return false;
}
new WriteCommandAction(modifierListOwner.getProject(), modifierListOwner.getContainingFile()) {
- protected void run(final Result result) throws Throwable {
+ protected void run(@NotNull final Result result) throws Throwable {
JVMElementFactory factory = JVMElementFactories.getFactory(modifierListOwner.getLanguage(), modifierListOwner.getProject());
if (factory == null) {
factory = JavaPsiFacade.getElementFactory(modifierListOwner.getProject());
@@ -484,7 +484,7 @@
}
}
}
- else {
+// else {
// todo tbd
//for (InjectionPlace place : injection.getInjectionPlaces()) {
// final Matcher matcher = pattern.matcher(place.getText());
@@ -492,7 +492,7 @@
//
// }
//}
- }
+// }
result.setMethodInfos(infos);
result.generatePlaces();
return result;
diff --git a/plugins/IntelliLang/src/META-INF/plugin.xml b/plugins/IntelliLang/src/META-INF/plugin.xml
index 975422e..3473135 100644
--- a/plugins/IntelliLang/src/META-INF/plugin.xml
+++ b/plugins/IntelliLang/src/META-INF/plugin.xml
@@ -11,7 +11,6 @@
<depends optional="true" config-file="intellilang-xml-support.xml">com.intellij.modules.xml</depends>
<depends optional="true" config-file="intellilang-js-support.xml">JavaScript</depends>
<depends optional="true" config-file="intellilang-python-support.xml">com.intellij.modules.python</depends>
- <depends optional="true" config-file="intellilang-python-support.xml">Pythonid</depends>
<extensionPoints>
<extensionPoint name="languageSupport" interface="org.intellij.plugins.intelliLang.inject.LanguageInjectionSupport"/>
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java
index a042093..2febf94 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/InjectionsSettingsUI.java
@@ -525,7 +525,7 @@
setShowGrid(false);
setShowVerticalLines(false);
setGridColor(getForeground());
- getColumnModel().getColumn(0).setMaxWidth(new JCheckBox().getPreferredSize().width);
+ TableUtil.setupCheckboxColumn(getColumnModel().getColumn(0));
new DoubleClickListener() {
@Override
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
index b03a07d..0e19690 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectLanguageAction.java
@@ -27,6 +27,7 @@
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
@@ -50,6 +51,7 @@
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Processor;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.ui.EmptyIcon;
import org.intellij.plugins.intelliLang.Configuration;
import org.intellij.plugins.intelliLang.references.InjectedReferencesContributor;
import org.jetbrains.annotations.NonNls;
@@ -57,6 +59,7 @@
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
+import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -188,6 +191,9 @@
}
}
});
+ Dimension minSize = new JLabel(PlainTextLanguage.INSTANCE.getDisplayName(), EmptyIcon.ICON_16, SwingConstants.LEFT).getMinimumSize();
+ minSize.height *= 4;
+ list.setMinimumSize(minSize);
JBPopup popup = new PopupChooserBuilder(list).setItemChoosenCallback(new Runnable() {
public void run() {
Injectable value = (Injectable)list.getSelectedValue();
@@ -201,7 +207,7 @@
public String fun(Object language) {
return ((Injectable)language).getDisplayName();
}
- }).createPopup();
+ }).setMinSize(minSize).createPopup();
final String lastInjected = PropertiesComponent.getInstance().getValue(LAST_INJECTED_LANGUAGE);
if (lastInjected != null) {
Injectable injectable = ContainerUtil.find(injectables, new Condition<Injectable>() {
diff --git a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
index 01a7629..4211fdf 100644
--- a/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.java
+++ b/plugins/IntelliLang/src/org/intellij/plugins/intelliLang/inject/InjectorUtils.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 @@
InjectedLanguage.create(injection.getInjectedLanguageId(), injection.getPrefix(), injection.getSuffix(), false);
List<TextRange> ranges = injection.getInjectedArea(host);
- List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list = ContainerUtil.newArrayListWithExpectedSize(ranges.size());
+ List<Trinity<PsiLanguageInjectionHost, InjectedLanguage, TextRange>> list = ContainerUtil.newArrayListWithCapacity(ranges.size());
for (TextRange range : ranges) {
list.add(Trinity.create(host, injectedLanguage, range));
diff --git a/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml b/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml
index 4ebdc25..bf03d7b 100644
--- a/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml
+++ b/plugins/IntentionPowerPak/src/META-INF/IntentionPowerPack.xml
@@ -606,5 +606,10 @@
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
<categoryKey>intention.category.other</categoryKey>
</intentionAction>
+ <intentionAction>
+ <className>com.siyeh.ipp.asserttoif.ObjectsRequireNonNullIntention</className>
+ <bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
+ <categoryKey>intention.category.other</categoryKey>
+ </intentionAction>
</extensions>
</idea-plugin>
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.java b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.java
index 4c930f8..44732e1 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,24 +28,23 @@
* @author max
*/
public class IntentionPowerPackBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "com.siyeh.IntentionPowerPackBundle";
private IntentionPowerPackBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
public static String defaultableMessage(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
return CommonBundle.messageOrDefault(getBundle(), key, "default", true, (Object[])params);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
index 0564761..dc1b4c6 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
+++ b/plugins/IntentionPowerPak/src/com/siyeh/IntentionPowerPackBundle.properties
@@ -182,6 +182,8 @@
replace.octal.escape.with.unicode.escape.intention.family.name=Replace Octal Escape with Unicode Escape
negate.conditional.intention.name=Negate '?:'
negate.conditional.intention.family.name=Negate Conditional
+objects.require.non.null.intention.name=Use 'java.util.Objects.requireNonNull()' expression
+objects.require.non.null.intention.family.name=Use 'java.util.Objects.requireNonNull()' Expression
#hand made
demorgans.intention.name1=Replace '\\&\\&' with '||'
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/AssertToIfIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/AssertToIfIntention.java
index 7d050c5..5a25314 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/AssertToIfIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/AssertToIfIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.PsiAssertStatement;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -43,6 +44,6 @@
newStatement.append(description.getText());
}
newStatement.append(");");
- replaceStatement(newStatement.toString(), assertStatement);
+ PsiReplacementUtil.replaceStatement(assertStatement, newStatement.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfStatementPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfStatementPredicate.java
index 22554aa..7a2470c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfStatementPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfStatementPredicate.java
@@ -16,7 +16,6 @@
package com.siyeh.ipp.asserttoif;
import com.intellij.psi.*;
-import com.siyeh.ig.psiutils.TypeUtils;
import com.siyeh.ipp.base.PsiElementPredicate;
class IfStatementPredicate implements PsiElementPredicate {
@@ -39,18 +38,12 @@
return false;
}
final PsiStatement thenBranch = statement.getThenBranch();
- return throwsException(thenBranch);
+ return isSimpleThrowStatement(thenBranch);
}
- private static boolean throwsException(PsiElement element) {
+ public static boolean isSimpleThrowStatement(PsiStatement element) {
if (element instanceof PsiThrowStatement) {
- final PsiThrowStatement throwStatement = (PsiThrowStatement)element;
- final PsiExpression exception = throwStatement.getException();
- if (!(exception instanceof PsiNewExpression)) {
- return false;
- }
- final PsiNewExpression newExpression = (PsiNewExpression)exception;
- return TypeUtils.expressionHasTypeOrSubtype(newExpression, CommonClassNames.JAVA_LANG_THROWABLE);
+ return true;
}
else if (element instanceof PsiBlockStatement) {
final PsiBlockStatement blockStatement = (PsiBlockStatement)element;
@@ -60,7 +53,7 @@
return false;
}
final PsiStatement statement = statements[0];
- return throwsException(statement);
+ return isSimpleThrowStatement(statement);
}
return false;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfToAssertionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfToAssertionIntention.java
index c64152a..427359c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfToAssertionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/IfToAssertionIntention.java
@@ -16,7 +16,9 @@
package com.siyeh.ipp.asserttoif;
import com.intellij.psi.*;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
+import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NonNls;
@@ -46,7 +48,7 @@
newStatementText.append(':').append(message);
}
newStatementText.append(';');
- replaceStatement(newStatementText.toString(), ifStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, newStatementText.toString());
}
private static String getMessage(PsiElement element) {
@@ -57,18 +59,16 @@
if (statements.length != 1) {
return null;
}
- final PsiStatement statement = statements[0];
- return getMessage(statement);
+ return getMessage(statements[0]);
}
else if (element instanceof PsiThrowStatement) {
final PsiThrowStatement throwStatement = (PsiThrowStatement)element;
- final PsiExpression exception = throwStatement.getException();
+ final PsiExpression exception = ParenthesesUtils.stripParentheses(throwStatement.getException());
if (!(exception instanceof PsiNewExpression)) {
return null;
}
final PsiNewExpression newExpression = (PsiNewExpression)exception;
- final PsiExpressionList argumentList =
- newExpression.getArgumentList();
+ final PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) {
return null;
}
@@ -76,8 +76,7 @@
if (arguments.length != 1) {
return null;
}
- final PsiExpression argument = arguments[0];
- return argument.getText();
+ return arguments[0].getText();
}
return null;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
new file mode 100644
index 0000000..10caec2
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntention.java
@@ -0,0 +1,179 @@
+/*
+ * 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.siyeh.ipp.asserttoif;
+
+import com.intellij.codeInsight.AnnotationUtil;
+import com.intellij.codeInsight.NullableNotNullManager;
+import com.intellij.psi.*;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.psi.util.PsiUtil;
+import com.siyeh.ig.PsiReplacementUtil;
+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 org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class ObjectsRequireNonNullIntention extends Intention {
+
+ @NotNull
+ @Override
+ protected PsiElementPredicate getElementPredicate() {
+ return new NullCheckedAssignmentPredicate();
+ }
+
+ @Override
+ protected void processIntention(@NotNull PsiElement element) {
+ if (!(element instanceof PsiReferenceExpression)) {
+ return;
+ }
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
+ final PsiElement target = referenceExpression.resolve();
+ if (!(target instanceof PsiVariable)) {
+ return;
+ }
+ final PsiVariable variable = (PsiVariable)target;
+ final List<String> notNulls = NullableNotNullManager.getInstance(element.getProject()).getNotNulls();
+ final PsiAnnotation annotation = AnnotationUtil.findAnnotation(variable, notNulls);
+ if (annotation != null) {
+ annotation.delete();
+ } else {
+ final PsiStatement referenceStatement = PsiTreeUtil.getParentOfType(referenceExpression, PsiStatement.class);
+ final PsiElement parent = referenceStatement.getParent();
+ if (!(parent instanceof PsiCodeBlock)) {
+ return;
+ }
+ final PsiCodeBlock codeBlock = (PsiCodeBlock)parent;
+ final PsiStatement[] statements = codeBlock.getStatements();
+ PsiStatement statementToDelete = null;
+ for (PsiStatement statement : statements) {
+ if (statement == referenceStatement) {
+ break;
+ }
+ if (NullCheckedAssignmentPredicate.isNotNullAssertion(statement, variable) ||
+ NullCheckedAssignmentPredicate.isIfStatementNullCheck(statement, variable)) {
+ statementToDelete = statement;
+ break;
+ }
+ }
+ if (statementToDelete == null) {
+ return;
+ }
+ statementToDelete.delete();
+ }
+ PsiReplacementUtil
+ .replaceExpressionAndShorten(referenceExpression, "java.util.Objects.requireNonNull(" + referenceExpression.getText() + ")");
+ }
+
+ private static class NullCheckedAssignmentPredicate implements PsiElementPredicate {
+
+ @Override
+ public boolean satisfiedBy(PsiElement element) {
+ if (!PsiUtil.isLanguageLevel7OrHigher(element)) {
+ return false;
+ }
+ if (!(element instanceof PsiReferenceExpression)) {
+ return false;
+ }
+ final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)element;
+ if (PsiUtil.isAccessedForWriting(referenceExpression)) {
+ return false;
+ }
+ final PsiElement target = referenceExpression.resolve();
+ if (!(target instanceof PsiVariable)) {
+ return false;
+ }
+ final PsiVariable variable = (PsiVariable)target;
+ if (NullableNotNullManager.isNotNull(variable)) {
+ return true;
+ }
+ final PsiStatement referenceStatement = PsiTreeUtil.getParentOfType(referenceExpression, PsiStatement.class);
+ final PsiElement parent = referenceStatement != null ? referenceStatement.getParent() : null;
+ if (!(parent instanceof PsiCodeBlock)) {
+ return false;
+ }
+ final PsiCodeBlock codeBlock = (PsiCodeBlock)parent;
+ final PsiStatement[] statements = codeBlock.getStatements();
+ for (PsiStatement statement : statements) {
+ if (statement == referenceStatement) {
+ return false;
+ }
+ if (isNotNullAssertion(statement, variable) || isIfStatementNullCheck(statement, variable)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static boolean isIfStatementNullCheck(PsiStatement statement, @NotNull PsiVariable variable) {
+ if (!(statement instanceof PsiIfStatement)) {
+ return false;
+ }
+ final PsiIfStatement ifStatement = (PsiIfStatement)statement;
+ final PsiStatement elseBranch = ifStatement.getElseBranch();
+ if (elseBranch != null) {
+ return false;
+ }
+ final PsiStatement thenBranch = ifStatement.getThenBranch();
+ if (!IfStatementPredicate.isSimpleThrowStatement(thenBranch)) {
+ return false;
+ }
+ final PsiExpression condition = ifStatement.getCondition();
+ return isNullComparison(condition, variable, true);
+ }
+
+ private static boolean isNotNullAssertion(PsiStatement statement, @NotNull PsiVariable variable) {
+ if (!(statement instanceof PsiAssertStatement)) {
+ return false;
+ }
+ final PsiAssertStatement assertStatement = (PsiAssertStatement)statement;
+ final PsiExpression condition = assertStatement.getAssertCondition();
+ return isNullComparison(condition, variable, false);
+ }
+
+ private static boolean isNullComparison(PsiExpression expression, @NotNull PsiVariable variable, boolean equal) {
+ expression = ParenthesesUtils.stripParentheses(expression);
+ if (!(expression instanceof PsiBinaryExpression)) {
+ return false;
+ }
+ final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
+ final IElementType tokenType = binaryExpression.getOperationTokenType();
+ if (equal) {
+ if (!JavaTokenType.EQEQ.equals(tokenType)) {
+ return false;
+ }
+ }
+ else {
+ if (!JavaTokenType.NE.equals(tokenType)) {
+ return false;
+ }
+ }
+ final PsiExpression lhs = binaryExpression.getLOperand();
+ final PsiExpression rhs = binaryExpression.getROperand();
+ if (rhs == null) {
+ return false;
+ }
+ return PsiType.NULL.equals(rhs.getType()) && VariableAccessUtils.evaluatesToVariable(lhs, variable) ||
+ PsiType.NULL.equals(lhs.getType()) && VariableAccessUtils.evaluatesToVariable(rhs, variable);
+ }
+ }
+}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java
index a0d83d2..9e1ef7f 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/base/Intention.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.
@@ -22,12 +22,10 @@
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.psiutils.BoolUtils;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -67,15 +65,6 @@
@NotNull
protected abstract PsiElementPredicate getElementPredicate();
- protected static void replaceExpression(@NotNull String newExpression, @NotNull PsiExpression expression){
- final Project project = expression.getProject();
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
- final PsiExpression newCall = factory.createExpressionFromText(newExpression, expression);
- final PsiElement insertedElement = expression.replace(newCall);
- final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
- codeStyleManager.reformat(insertedElement);
- }
-
protected static void replaceExpressionWithNegatedExpression(@NotNull PsiExpression newExpression, @NotNull PsiExpression expression){
final Project project = expression.getProject();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
@@ -134,27 +123,6 @@
codeStyleManager.reformat(insertedElement);
}
- protected static void replaceStatement(@NonNls @NotNull String newStatementText, @NonNls @NotNull PsiStatement statement) {
- final Project project = statement.getProject();
- final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
- final PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
- final PsiElement insertedElement = statement.replace(newStatement);
- final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
- codeStyleManager.reformat(insertedElement);
- }
-
- protected static void replaceStatementAndShorten(@NonNls @NotNull String newStatementText, @NonNls @NotNull PsiStatement statement) {
- final Project project = statement.getProject();
- final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project);
- final PsiElementFactory factory = psiFacade.getElementFactory();
- final PsiStatement newStatement = factory.createStatementFromText(newStatementText, statement);
- final PsiElement insertedElement = statement.replace(newStatement);
- final JavaCodeStyleManager javaCodeStyleManager = JavaCodeStyleManager.getInstance(project);
- final PsiElement shortenedElement = javaCodeStyleManager.shortenClassReferences(insertedElement);
- final CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(project);
- codeStyleManager.reformat(shortenedElement);
- }
-
protected static void addStatementBefore(String newStatementText, PsiReturnStatement anchor) {
final Project project = anchor.getProject();
final PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/ComparisonPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/ComparisonPredicate.java
index f8e3913..1712ea4 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/ComparisonPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/ComparisonPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2005 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.
@@ -18,8 +18,8 @@
import com.intellij.psi.PsiBinaryExpression;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
import com.siyeh.ipp.psiutils.ErrorUtil;
class ComparisonPredicate implements PsiElementPredicate {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/DemorgansIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/DemorgansIntention.java
index 6d74875..eb27f3e 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/DemorgansIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/DemorgansIntention.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,11 +19,11 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.BoolUtils;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
import org.jetbrains.annotations.NotNull;
public class DemorgansIntention extends MutablyNamedIntention {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipComparisonIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipComparisonIntention.java
index 18ef406..97ea780 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipComparisonIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipComparisonIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2003-2009 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.
@@ -22,9 +22,10 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
import org.jetbrains.annotations.NotNull;
public class FlipComparisonIntention extends MutablyNamedIntention {
@@ -37,7 +38,7 @@
final PsiJavaToken sign = expression.getOperationSign();
operatorText = sign.getText();
flippedOperatorText =
- ComparisonUtils.getFlippedComparison(sign);
+ ComparisonUtils.getFlippedComparison(sign.getTokenType());
}
if (operatorText.equals(flippedOperatorText)) {
return IntentionPowerPackBundle.message("flip.smth.intention.name",
@@ -66,6 +67,6 @@
final String expString = rhs.getText() +
ComparisonUtils.getFlippedComparison(tokenType) +
lhs.getText();
- replaceExpression(expString, expression);
+ PsiReplacementUtil.replaceExpression(expression, expString);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipConjunctionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipConjunctionIntention.java
index 401b154..7bef3bf 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipConjunctionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/FlipConjunctionIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -51,7 +52,7 @@
parent = exp.getParent();
}
final String newExpression = flipExpression(exp, conjunctionType);
- replaceExpression(newExpression, exp);
+ PsiReplacementUtil.replaceExpression(exp, newExpression);
}
private static String flipExpression(PsiExpression expression,
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/NegateComparisonIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/NegateComparisonIntention.java
index 2a5c9c4..7844157 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/NegateComparisonIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/NegateComparisonIntention.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.
@@ -20,10 +20,10 @@
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiJavaToken;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
-import com.siyeh.IntentionPowerPackBundle;
import org.jetbrains.annotations.NotNull;
public class NegateComparisonIntention extends MutablyNamedIntention {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/RemoveBooleanEqualityIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/RemoveBooleanEqualityIntention.java
index 65e67de..c0f496c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/RemoveBooleanEqualityIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/bool/RemoveBooleanEqualityIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.IntentionPowerPackBundle;
@@ -53,7 +54,7 @@
@NonNls final String rhsText = rhs.getText();
if (PsiKeyword.TRUE.equals(lhsText)) {
if (isEquals) {
- replaceExpression(rhsText, exp);
+ PsiReplacementUtil.replaceExpression(exp, rhsText);
}
else {
replaceExpressionWithNegatedExpression(rhs, exp);
@@ -64,12 +65,12 @@
replaceExpressionWithNegatedExpression(rhs, exp);
}
else {
- replaceExpression(rhsText, exp);
+ PsiReplacementUtil.replaceExpression(exp, rhsText);
}
}
else if (PsiKeyword.TRUE.equals(rhsText)) {
if (isEquals) {
- replaceExpression(lhsText, exp);
+ PsiReplacementUtil.replaceExpression(exp, lhsText);
}
else {
replaceExpressionWithNegatedExpression(lhs, exp);
@@ -80,7 +81,7 @@
replaceExpressionWithNegatedExpression(lhs, exp);
}
else {
- replaceExpression(lhsText, exp);
+ PsiReplacementUtil.replaceExpression(exp, lhsText);
}
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddArrayCreationExpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddArrayCreationExpressionIntention.java
index 0815174..8a08420 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddArrayCreationExpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddArrayCreationExpressionIntention.java
@@ -19,9 +19,9 @@
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public class AddArrayCreationExpressionIntention extends MutablyNamedIntention {
@@ -47,7 +47,8 @@
if (type == null) {
return;
}
- replaceExpression("new " + TypeConversionUtil.erasure(type).getCanonicalText() + arrayInitializerExpression.getText(),
- arrayInitializerExpression);
+ PsiReplacementUtil.replaceExpression(arrayInitializerExpression, "new " +
+ TypeConversionUtil.erasure(type).getCanonicalText() +
+ arrayInitializerExpression.getText());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddBracesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddBracesIntention.java
index ac643a7..f51759f 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddBracesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/AddBracesIntention.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -45,6 +46,6 @@
return;
}
final String newStatement = "{\n" + statement.getText() + "\n}";
- replaceStatement(newStatement, statement);
+ PsiReplacementUtil.replaceStatement(statement, newStatement);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java
index e07e0df..f7ff592 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/braces/RemoveBracesIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.intellij.psi.util.FileTypeUtils;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -64,7 +65,7 @@
handleComments(blockStatement, codeBlock);
final String text = statement.getText();
- replaceStatement(text, blockStatement);
+ PsiReplacementUtil.replaceStatement(blockStatement, text);
}
private static void handleComments(PsiBlockStatement blockStatement, PsiCodeBlock codeBlock) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/CharToStringIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/CharToStringIntention.java
index 6828378..edb8e7c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/CharToStringIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/CharToStringIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -37,7 +38,7 @@
(PsiLiteralExpression)element;
final String charLiteralText = charLiteral.getText();
final String stringLiteral = stringForCharLiteral(charLiteralText);
- replaceExpression(stringLiteral, charLiteral);
+ PsiReplacementUtil.replaceExpression(charLiteral, stringLiteral);
}
private static String stringForCharLiteral(String charLiteral) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/StringToCharIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/StringToCharIntention.java
index 4627c59..67e0146 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/StringToCharIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/chartostring/StringToCharIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -37,7 +38,7 @@
(PsiLiteralExpression)element;
final String stringLiteralText = stringLiteral.getText();
final String charLiteral = charForStringLiteral(stringLiteralText);
- replaceExpression(charLiteral, stringLiteral);
+ PsiReplacementUtil.replaceExpression(stringLiteral, charLiteral);
}
private static String charForStringLiteral(String stringLiteral) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/FlipCommutativeMethodCallIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/FlipCommutativeMethodCallIntention.java
index d560d08..c96e9cc 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/FlipCommutativeMethodCallIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/FlipCommutativeMethodCallIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -81,6 +82,6 @@
callString = strippedArg.getText() + '.' + methodName + '(' +
strippedTarget.getText() + ')';
}
- replaceExpression(callString, call);
+ PsiReplacementUtil.replaceExpression(call, callString);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/SwapMethodCallArgumentsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/SwapMethodCallArgumentsIntention.java
index 7770f4d..4fd24a9 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/SwapMethodCallArgumentsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/commutative/SwapMethodCallArgumentsIntention.java
@@ -15,6 +15,7 @@
*/
package com.siyeh.ipp.commutative;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.IntentionPowerPackBundle;
@@ -72,6 +73,6 @@
}
final String newExpression = callText + '(' + secondArgumentText +
", " + firstArgumentText + ')';
- replaceExpression(newExpression, callExpression);
+ PsiReplacementUtil.replaceExpression(callExpression, newExpression);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/JoinConcatenatedStringLiteralsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/JoinConcatenatedStringLiteralsIntention.java
index 5b5dcd5..9f8fc03 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/JoinConcatenatedStringLiteralsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/JoinConcatenatedStringLiteralsIntention.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -86,6 +87,6 @@
for (PsiElement bufferedElement : buffer) {
newExpression.append(bufferedElement.getText());
}
- replaceExpression(newExpression.toString(), polyadicExpression);
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpression.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MergeCallSequenceToChainIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MergeCallSequenceToChainIntention.java
index 6f314dc..5e9170d 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MergeCallSequenceToChainIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/MergeCallSequenceToChainIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -62,7 +63,7 @@
}
methodCallExpression = (PsiMethodCallExpression)grandParent;
}
- replaceExpression(newMethodCallExpression.toString(), expression);
+ PsiReplacementUtil.replaceExpression(expression, newMethodCallExpression.toString());
nextSibling.delete();
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithFormatStringIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithFormatStringIntention.java
index a81f8e4..8da78eb 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithFormatStringIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithFormatStringIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiConcatenationUtil;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ConcatenationUtils;
@@ -57,7 +58,7 @@
newExpression.append(formatParameter.getText());
}
newExpression.append(')');
- replaceExpression(newExpression.toString(), expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression.toString());
}
private static boolean replaceWithPrintfExpression(PsiExpression expression, CharSequence formatString,
@@ -113,7 +114,7 @@
newExpression.append(formatParameter.getText());
}
newExpression.append(')');
- replaceExpression(newExpression.toString(), methodCallExpression);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression.toString());
return true;
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithStringBufferIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithStringBufferIntention.java
index 8ac9745..6cdfdeb 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithStringBufferIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/concatenation/ReplaceConcatenationWithStringBufferIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -65,7 +66,7 @@
newExpression.append(qualifierText);
}
turnExpressionIntoChainedAppends(expression, newExpression);
- replaceExpression(newExpression.toString(), methodCallExpression);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression.toString());
}
else {
if (!PsiUtil.isLanguageLevel5OrHigher(expression)) {
@@ -76,7 +77,7 @@
}
turnExpressionIntoChainedAppends(expression, newExpression);
newExpression.append(".toString()");
- replaceExpression(newExpression.toString(), expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/FlipConditionalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/FlipConditionalIntention.java
index 6e1b5bd..5c8960d 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/FlipConditionalIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/FlipConditionalIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.BoolUtils;
@@ -47,6 +48,6 @@
elseExpression.getText() +
':' +
thenExpression.getText();
- replaceExpression(newExpression, exp);
+ PsiReplacementUtil.replaceExpression(exp, newExpression);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/RemoveConditionalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/RemoveConditionalIntention.java
index dff37b4..24eea41 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/RemoveConditionalIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/RemoveConditionalIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiExpression;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.BoolUtils;
@@ -42,12 +43,12 @@
@NonNls final String thenExpressionText = thenExpression.getText();
if ("true".equals(thenExpressionText)) {
final String newExpression = condition.getText();
- replaceExpression(newExpression, expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
else {
final String newExpression =
BoolUtils.getNegatedExpressionText(condition);
- replaceExpression(newExpression, expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfIntention.java
index 6d22d8e..ba88524 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/conditional/ReplaceConditionalWithIfIntention.java
@@ -24,6 +24,7 @@
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -126,7 +127,7 @@
if (addBraces || elseExpression == null) {
newStatement.append('}');
}
- replaceStatement(newStatement.toString(), statement);
+ PsiReplacementUtil.replaceStatement(statement, newStatement.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantExpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantExpressionIntention.java
index 3a9dd30..e774be8 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantExpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantExpressionIntention.java
@@ -20,6 +20,7 @@
import com.intellij.psi.PsiExpression;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -96,6 +97,6 @@
else {
newExpression = String.valueOf(value);
}
- replaceExpression(newExpression, expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantSubexpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantSubexpressionIntention.java
index 79698f3..5bec1b6 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantSubexpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/constant/ConstantSubexpressionIntention.java
@@ -21,6 +21,7 @@
import com.intellij.psi.PsiPolyadicExpression;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -144,6 +145,6 @@
if (prevOperand != null) {
newExpressionText.append(prevOperand.getText());
}
- replaceExpression(newExpressionText.toString(), polyadicExpression);
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpressionText.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java
index 59d1f36..9f2078c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/enumswitch/CreateEnumSwitchBranchesIntention.java
@@ -16,6 +16,7 @@
package com.siyeh.ipp.enumswitch;
import com.intellij.psi.*;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NonNls;
@@ -69,7 +70,7 @@
newStatementText.append("case ").append(missingEnumElement.getName()).append(": break;");
}
newStatementText.append('}');
- replaceStatement(newStatementText.toString(), switchStatement);
+ PsiReplacementUtil.replaceStatement(switchStatement, newStatementText.toString());
return;
}
final Map<PsiEnumConstant, PsiEnumConstant> nextEnumConstants = new HashMap<PsiEnumConstant, PsiEnumConstant>(fields.length);
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java
index a9afb48..9c0119a 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithEqualsIntention.java
@@ -21,6 +21,7 @@
import com.intellij.psi.PsiExpression;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -77,6 +78,6 @@
strippedRhs.getText() + ')';
}
}
- replaceExpression(expString, exp);
+ PsiReplacementUtil.replaceExpression(exp, expString);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithSafeEqualsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithSafeEqualsIntention.java
index d5d14f7..d14804a 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithSafeEqualsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualityWithSafeEqualsIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -75,6 +76,6 @@
buffer.append(".equals(");
buffer.append(rhsText);
buffer.append(')');
- replaceExpression(buffer.toString(), exp);
+ PsiReplacementUtil.replaceExpression(exp, buffer.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualsWithEqualityIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualsWithEqualityIntention.java
index 5faa4d7..66d8615 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualsWithEqualityIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/equality/ReplaceEqualsWithEqualityIntention.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -70,6 +71,6 @@
else {
strippedTargetText = strippedTarget.getText();
}
- replaceExpression(strippedTargetText + "==" + strippedArgText, call);
+ PsiReplacementUtil.replaceExpression(call, strippedTargetText + "==" + strippedArgText);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java
index 092ff01..2fe672f 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/DetailExceptionsIntention.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -86,6 +87,6 @@
newTryStatement.append("finally").append(finallyBlock.getText());
}
final String newStatement = newTryStatement.toString();
- replaceStatementAndShorten(newStatement, tryStatement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(tryStatement, newStatement);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java
index 2683504..9c73792 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/exceptions/SplitTryWithMultipleResourcesIntention.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NonNls;
@@ -65,6 +66,6 @@
for (PsiCatchSection catchSection : catchSections) {
newTryStatementText.append(catchSection.getText());
}
- replaceStatement(newTryStatementText.toString(), tryStatement);
+ PsiReplacementUtil.replaceStatement(tryStatement, newTryStatementText.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java
index 7055f69..b22f285 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/ExpressionPredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2007-2013 Dave Griffith, Bas Leijdekkers
+ * Copyright 2007-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.
@@ -15,9 +15,12 @@
*/
package com.siyeh.ipp.expression;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiExpression;
+import com.intellij.psi.PsiJavaToken;
+import com.intellij.psi.PsiPolyadicExpression;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
class ExpressionPredicate implements PsiElementPredicate {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java
index fe4e862..3c84786 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/expression/FlipExpressionIntention.java
@@ -23,6 +23,7 @@
import com.intellij.psi.PsiPolyadicExpression;
import com.intellij.psi.tree.IElementType;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ConcatenationUtils;
@@ -77,7 +78,7 @@
prevOperand = operand.getText();
}
newExpression.append(prevOperand);
- replaceExpression(newExpression.toString(), polyadicExpression);
+ PsiReplacementUtil.replaceExpression(polyadicExpression, newExpression.toString());
}
@Override
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java
index 61a25f3..7ee3e0f 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIndexedForLoopIntention.java
@@ -20,6 +20,7 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NonNls;
@@ -100,7 +101,7 @@
newStatement.append(body.getText());
}
newStatement.append('}');
- replaceStatementAndShorten(newStatement.toString(), statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newStatement.toString());
}
protected void createForLoopDeclaration(PsiForeachStatement statement,
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java
index f99fdd3..272cbfb 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReplaceForEachLoopWithIteratorForLoopIntention.java
@@ -21,6 +21,7 @@
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -94,6 +95,6 @@
newStatement.append(body.getText());
}
newStatement.append('}');
- replaceStatementAndShorten(newStatement.toString(), statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newStatement.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java
index 92a3df4..35404ae 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/forloop/ReverseForLoopDirectionIntention.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.
@@ -19,11 +19,11 @@
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.psiutils.ComparisonUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ComparisonUtils;
import com.siyeh.ipp.psiutils.VariableAccessUtils;
import org.jetbrains.annotations.NotNull;
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/increment/ExtractIncrementIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/increment/ExtractIncrementIntention.java
index a60901e..dc7cca4 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/increment/ExtractIncrementIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/increment/ExtractIncrementIntention.java
@@ -23,6 +23,7 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -253,7 +254,7 @@
}
}
}
- replaceExpression(operandText, (PsiExpression)element);
+ PsiReplacementUtil.replaceExpression((PsiExpression)element, operandText);
}
private static String getElementText(@NotNull PsiElement element,
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java
index b9e67ad..371e69b 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/integer/ConvertNumberIntentionBase.java
@@ -19,6 +19,7 @@
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiType;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ipp.base.Intention;
import org.jetbrains.annotations.NotNull;
@@ -37,10 +38,10 @@
if (resultString == null) return;
if (negated) {
- replaceExpression(resultString, (PsiExpression)expression.getParent());
+ PsiReplacementUtil.replaceExpression((PsiExpression)expression.getParent(), resultString);
}
else {
- replaceExpression(resultString, expression);
+ PsiReplacementUtil.replaceExpression(expression, resultString);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/CreateAssertIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/CreateAssertIntention.java
index 328f29f..55ae45e 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/CreateAssertIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/CreateAssertIntention.java
@@ -20,6 +20,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.intellij.codeInsight.AnnotationUtil;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.BoolUtils;
@@ -54,8 +55,7 @@
@NonNls final String newExpression =
specifierString + "assertFalse(" +
BoolUtils.getNegatedExpressionText(expression) + ");";
- replaceStatementAndShorten(newExpression,
- statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newExpression);
}
else if (isNullComparison(expression)) {
final PsiBinaryExpression binaryExpression =
@@ -72,8 +72,7 @@
assert comparedExpression != null;
@NonNls final String newExpression = specifierString +
"assertNull(" + comparedExpression.getText() + ");";
- replaceStatementAndShorten(newExpression,
- statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newExpression);
}
else if (isEqualityComparison(expression)) {
final PsiBinaryExpression binaryExpression =
@@ -108,8 +107,7 @@
comparedExpression.getText() + ", " +
comparingExpression.getText() + ");";
}
- replaceStatementAndShorten(newExpression,
- statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newExpression);
}
else if (isEqualsExpression(expression)) {
final PsiMethodCallExpression call =
@@ -133,14 +131,12 @@
comparedExpression.getText() + ", " +
comparingExpression.getText() + ");";
}
- replaceStatementAndShorten(newExpression,
- statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newExpression);
}
else {
@NonNls final String newExpression =
specifierString + "assertTrue(" + expression.getText() + ");";
- replaceStatementAndShorten(newExpression,
- statement);
+ PsiReplacementUtil.replaceStatementAndShortenClassNames(statement, newExpression);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/FlipAssertLiteralIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/FlipAssertLiteralIntention.java
index ac90d38..d3a8d4c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/FlipAssertLiteralIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/FlipAssertLiteralIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ImportUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -87,6 +88,6 @@
newCall.append(BoolUtils.getNegatedExpressionText(arguments[1]));
}
newCall.append(')');
- replaceExpression(newCall.toString(), call);
+ PsiReplacementUtil.replaceExpression(call, newCall.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertEqualsWithAssertLiteralIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertEqualsWithAssertLiteralIntention.java
index 43d318a..cb27659 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertEqualsWithAssertLiteralIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertEqualsWithAssertLiteralIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ImportUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -96,7 +97,7 @@
newExpression.append(qualifier.getText()).append('.');
}
newExpression.append(assertString).append('(').append(actualArgumentText).append(')');
- replaceExpression(newExpression.toString(), call);
+ PsiReplacementUtil.replaceExpression(call, newExpression.toString());
}
@NonNls
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertLiteralWithAssertEqualsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertLiteralWithAssertEqualsIntention.java
index 08dc488..7bc8b2b 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertLiteralWithAssertEqualsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/junit/ReplaceAssertLiteralWithAssertEqualsIntention.java
@@ -20,6 +20,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ImportUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -112,6 +113,6 @@
newExpression.append(literal).append(", ").append(lastArgument.getText());
}
newExpression.append(')');
- replaceExpression(newExpression.toString(), call);
+ PsiReplacementUtil.replaceExpression(call, newExpression.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierPredicate.java
index d1c2781..47a39f6 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierPredicate.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.
@@ -35,7 +35,7 @@
@Override
public boolean satisfiedBy(PsiElement element) {
final PsiElement parent = element.getParent();
- if (!(parent instanceof PsiClass || parent instanceof PsiField || parent instanceof PsiMethod)) {
+ if (!(parent instanceof PsiClass || parent instanceof PsiField || parent instanceof PsiMethod) || parent instanceof PsiEnumConstant) {
return false;
}
if (element instanceof PsiDocComment || element instanceof PsiCodeBlock) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionIntention.java
index 2edca43..3e03d55 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceAssignmentWithPostfixExpressionIntention.java
@@ -15,6 +15,7 @@
*/
package com.siyeh.ipp.opassign;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.IntentionPowerPackBundle;
@@ -73,10 +74,10 @@
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)rhs;
final IElementType tokenType = binaryExpression.getOperationTokenType();
if (JavaTokenType.PLUS.equals(tokenType)) {
- replaceExpression(lhsText + "++", assignmentExpression);
+ PsiReplacementUtil.replaceExpression(assignmentExpression, lhsText + "++");
}
else if (JavaTokenType.MINUS.equals(tokenType)) {
- replaceExpression(lhsText + "--", assignmentExpression);
+ PsiReplacementUtil.replaceExpression(assignmentExpression, lhsText + "--");
}
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java
index c94b02d..35b1470 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithAssignmentIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.TypeConversionUtil;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -97,7 +98,7 @@
if (!cast.isEmpty()) {
newExpression.append(')');
}
- replaceExpression(newExpression.toString(), assignmentExpression);
+ PsiReplacementUtil.replaceExpression(assignmentExpression, newExpression.toString());
}
private static String getCastString(PsiExpression lhs, PsiExpression rhs) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithPostfixExpressionIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithPostfixExpressionIntention.java
index b43d3dd..a220cdf 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithPostfixExpressionIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceOperatorAssignmentWithPostfixExpressionIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -69,6 +70,6 @@
else {
return;
}
- replaceExpression(newExpressionText, assignment);
+ PsiReplacementUtil.replaceExpression(assignment, newExpressionText);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithAssignmentIntention.java
index 63a6568..5817535 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithAssignmentIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithAssignmentIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -54,12 +55,10 @@
final IElementType tokenType =
postfixExpression.getOperationTokenType();
if (JavaTokenType.PLUSPLUS.equals(tokenType)) {
- replaceExpression(operandText + '=' + operandText + "+1",
- postfixExpression);
+ PsiReplacementUtil.replaceExpression(postfixExpression, operandText + '=' + operandText + "+1");
}
else if (JavaTokenType.MINUSMINUS.equals(tokenType)) {
- replaceExpression(operandText + '=' + operandText + "-1",
- postfixExpression);
+ PsiReplacementUtil.replaceExpression(postfixExpression, operandText + '=' + operandText + "-1");
}
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithOperatorAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithOperatorAssignmentIntention.java
index 3a60e3f..56fec08 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithOperatorAssignmentIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplacePostfixExpressionWithOperatorAssignmentIntention.java
@@ -15,6 +15,7 @@
*/
package com.siyeh.ipp.opassign;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.IntentionPowerPackBundle;
@@ -61,10 +62,10 @@
final IElementType tokenType =
postfixExpression.getOperationTokenType();
if (JavaTokenType.PLUSPLUS.equals(tokenType)) {
- replaceExpression(operandText + "+=1", postfixExpression);
+ PsiReplacementUtil.replaceExpression(postfixExpression, operandText + "+=1");
}
else if (JavaTokenType.MINUSMINUS.equals(tokenType)) {
- replaceExpression(operandText + "-=1", postfixExpression);
+ PsiReplacementUtil.replaceExpression(postfixExpression, operandText + "-=1");
}
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java
index f4d0397..2e81373 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/opassign/ReplaceWithOperatorAssignmentIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -64,6 +65,6 @@
}
newExpression.append(operand.getText());
}
- replaceExpression(newExpression.toString(), expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/parenthesis/AddClarifyingParenthesesIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/parenthesis/AddClarifyingParenthesesIntention.java
index 3780225..37068de 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/parenthesis/AddClarifyingParenthesesIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/parenthesis/AddClarifyingParenthesesIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -45,11 +46,11 @@
final PsiConditionalExpression conditionalExpression = (PsiConditionalExpression)parent;
final PsiExpression condition = conditionalExpression.getCondition();
if (expression == condition) {
- replaceExpression('(' + newExpression.toString() + ')', expression);
+ PsiReplacementUtil.replaceExpression(expression, '(' + newExpression.toString() + ')');
return;
}
}
- replaceExpression(newExpression.toString(), expression);
+ PsiReplacementUtil.replaceExpression(expression, newExpression.toString());
}
@Nullable
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/BoolUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/BoolUtils.java
index b5e0194..295ca9a 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/BoolUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/BoolUtils.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.
@@ -17,6 +17,7 @@
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.NonNls;
import org.jetbrains.annotations.Nullable;
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ComparisonUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ComparisonUtils.java
deleted file mode 100644
index f2ffeda..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ComparisonUtils.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2003-2009 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.JavaTokenType;
-import com.intellij.psi.PsiBinaryExpression;
-import com.intellij.psi.PsiExpression;
-import com.intellij.psi.PsiJavaToken;
-import com.intellij.psi.tree.IElementType;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-
-public class ComparisonUtils {
-
- private static final Set<IElementType> comparisons =
- new HashSet<IElementType>(6);
- private static final Map<IElementType, String> flippedComparisons =
- new HashMap<IElementType, String>(6);
- private static final Map<IElementType, String> negatedComparisons =
- new HashMap<IElementType, String>(6);
-
- private ComparisonUtils() {
- }
-
- static {
- comparisons.add(JavaTokenType.EQEQ);
- comparisons.add(JavaTokenType.NE);
- comparisons.add(JavaTokenType.GT);
- comparisons.add(JavaTokenType.LT);
- comparisons.add(JavaTokenType.GE);
- comparisons.add(JavaTokenType.LE);
-
- flippedComparisons.put(JavaTokenType.EQEQ, "==");
- flippedComparisons.put(JavaTokenType.NE, "!=");
- flippedComparisons.put(JavaTokenType.GT, "<");
- flippedComparisons.put(JavaTokenType.LT, ">");
- flippedComparisons.put(JavaTokenType.GE, "<=");
- flippedComparisons.put(JavaTokenType.LE, ">=");
-
- negatedComparisons.put(JavaTokenType.EQEQ, "!=");
- negatedComparisons.put(JavaTokenType.NE, "==");
- negatedComparisons.put(JavaTokenType.GT, "<=");
- negatedComparisons.put(JavaTokenType.LT, ">=");
- negatedComparisons.put(JavaTokenType.GE, "<");
- negatedComparisons.put(JavaTokenType.LE, ">");
- }
-
- public static boolean isComparison(@Nullable PsiExpression expression) {
- if (!(expression instanceof PsiBinaryExpression)) {
- return false;
- }
- final PsiBinaryExpression binaryExpression =
- (PsiBinaryExpression)expression;
- final IElementType tokenType = binaryExpression.getOperationTokenType();
- return isComparison(tokenType);
- }
-
- public static boolean isComparison(@NotNull IElementType tokenType) {
- return comparisons.contains(tokenType);
- }
-
- public static String getFlippedComparison(@NotNull PsiJavaToken sign) {
- final IElementType text = sign.getTokenType();
- return getFlippedComparison(text);
- }
-
- public static String getFlippedComparison(IElementType text) {
- return flippedComparisons.get(text);
- }
-
- public static String getNegatedComparison(IElementType tokenType) {
- return negatedComparisons.get(tokenType);
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java
index dd9d5b1..8d13fe2 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/ConditionalUtils.java
@@ -22,23 +22,6 @@
private ConditionalUtils() {}
- public static PsiStatement stripBraces(PsiStatement branch) {
- if (branch instanceof PsiBlockStatement) {
- final PsiBlockStatement block = (PsiBlockStatement)branch;
- final PsiCodeBlock codeBlock = block.getCodeBlock();
- final PsiStatement[] statements = codeBlock.getStatements();
- if (statements.length == 1) {
- return statements[0];
- }
- else {
- return block;
- }
- }
- else {
- return branch;
- }
- }
-
public static boolean isReturn(PsiStatement statement,
@NonNls String value) {
if (statement == null) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.java
index 46e2214..2ac8500 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/psiutils/VariableAccessUtils.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.
@@ -17,6 +17,7 @@
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;
@@ -39,7 +40,7 @@
final PsiBinaryExpression binaryExpression =
(PsiBinaryExpression)expression;
final IElementType tokenType = binaryExpression.getOperationTokenType();
- if (!ComparisonUtils.isComparison(tokenType)) {
+ if (!ComparisonUtils.isComparisonOperation(tokenType)) {
return false;
}
final PsiExpression lhs = binaryExpression.getLOperand();
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceMultiplyWithShiftIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceMultiplyWithShiftIntention.java
index 713f81a..f4d411d 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceMultiplyWithShiftIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceMultiplyWithShiftIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -91,7 +92,7 @@
}
final String expString =
lhs.getText() + assignString + ShiftUtils.getLogBase2(rhs);
- replaceExpression(expString, expression);
+ PsiReplacementUtil.replaceExpression(expression, expString);
}
private static void replaceMultiplyOrDivideWithShift(
@@ -125,6 +126,6 @@
expString = '(' + expString + ')';
}
}
- replaceExpression(expString, expression);
+ PsiReplacementUtil.replaceExpression(expression, expString);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceShiftWithMultiplyIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceShiftWithMultiplyIntention.java
index f23ad11..76b5a12 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceShiftWithMultiplyIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/shift/ReplaceShiftWithMultiplyIntention.java
@@ -19,6 +19,7 @@
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.MutablyNamedIntention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -95,7 +96,7 @@
}
final String expString =
lhs.getText() + assignString + ShiftUtils.getExpBase2(rhs);
- replaceExpression(expString, exp);
+ PsiReplacementUtil.replaceExpression(exp, expString);
}
private static void replaceShiftWithMultiplyOrDivide(PsiElement element)
@@ -130,6 +131,6 @@
expString = '(' + expString + ')';
}
}
- replaceExpression(expString, exp);
+ PsiReplacementUtil.replaceExpression(exp, expString);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchStatementBranch.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchStatementBranch.java
deleted file mode 100644
index f500513..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/switchtoif/SwitchStatementBranch.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright 2003-2009 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.switchtoif;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLocalVariable;
-
-import java.util.*;
-
-class SwitchStatementBranch {
-
- private final Set<PsiLocalVariable> m_pendingVariableDeclarations =
- new HashSet<PsiLocalVariable>(5);
- private final List<String> m_caseValues =
- new ArrayList<String>(2);
- private final List<PsiElement> m_bodyElements =
- new ArrayList<PsiElement>(5);
- private final List<PsiElement> m_pendingWhiteSpace =
- new ArrayList<PsiElement>(2);
- private boolean m_default = false;
- private boolean m_hasStatements = false;
-
- public void addCaseValue(String labelString) {
- m_caseValues.add(labelString);
- }
-
- public void addStatement(PsiElement statement) {
- m_hasStatements = true;
- addElement(statement);
- }
-
- public void addComment(PsiElement comment) {
- addElement(comment);
- }
-
- private void addElement(PsiElement element) {
- m_bodyElements.addAll(m_pendingWhiteSpace);
- m_pendingWhiteSpace.clear();
- m_bodyElements.add(element);
- }
-
- public void addWhiteSpace(PsiElement statement) {
- if (!m_bodyElements.isEmpty()) {
- m_pendingWhiteSpace.add(statement);
- }
- }
-
- public List<String> getCaseValues() {
- return Collections.unmodifiableList(m_caseValues);
- }
-
- public List<PsiElement> getBodyElements() {
- return Collections.unmodifiableList(m_bodyElements);
- }
-
- public boolean isDefault() {
- return m_default;
- }
-
- public void setDefault() {
- m_default = true;
- }
-
- public boolean hasStatements() {
- return m_hasStatements;
- }
-
- public void addPendingVariableDeclarations(Set<PsiLocalVariable> vars) {
- m_pendingVariableDeclarations.addAll(vars);
- }
-
- public Set<PsiLocalVariable> getPendingVariableDeclarations() {
- return Collections.unmodifiableSet(m_pendingVariableDeclarations);
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ConvertToNestedIfIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ConvertToNestedIfIntention.java
index a768bab..c73febe 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ConvertToNestedIfIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ConvertToNestedIfIntention.java
@@ -20,6 +20,7 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.tree.IElementType;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -69,7 +70,7 @@
for (PsiStatement st : blockStatement.getCodeBlock().getStatements()) {
CodeStyleManager.getInstance(project).reformat(parent.addBefore(st, returnStatement));
}
- replaceStatement("return false;", returnStatement);
+ PsiReplacementUtil.replaceStatement(returnStatement, "return false;");
}
private static StringBuilder buildIf(@Nullable PsiExpression expression, StringBuilder out) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ExpandBooleanIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ExpandBooleanIntention.java
index 5985b57..b372a45 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ExpandBooleanIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ExpandBooleanIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import com.siyeh.ipp.psiutils.ErrorUtil;
@@ -61,7 +62,7 @@
conditionText = rhsText;
}
@NonNls final String statement = "if(" + conditionText + ") " + lhsText + " = true; else " + lhsText + " = false;";
- replaceStatement(statement, containingStatement);
+ PsiReplacementUtil.replaceStatement(containingStatement, statement);
}
else if (ExpandBooleanPredicate.isBooleanReturn(containingStatement)) {
final PsiReturnStatement returnStatement = (PsiReturnStatement)containingStatement;
@@ -74,7 +75,7 @@
}
final String valueText = returnValue.getText();
@NonNls final String statement = "if(" + valueText + ") return true; else return false;";
- replaceStatement(statement, containingStatement);
+ PsiReplacementUtil.replaceStatement(containingStatement, statement);
}
else if (ExpandBooleanPredicate.isBooleanDeclaration(containingStatement)) {
final PsiDeclarationStatement declarationStatement = (PsiDeclarationStatement)containingStatement;
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeElseIfIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeElseIfIntention.java
index 75baaa0..ab81f4c 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeElseIfIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeElseIfIntention.java
@@ -17,6 +17,7 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -40,6 +41,6 @@
final PsiCodeBlock elseBranchBlock = elseBranch.getCodeBlock();
final PsiStatement elseBranchContents =
elseBranchBlock.getStatements()[0];
- replaceStatement(elseBranchContents.getText(), elseBranch);
+ PsiReplacementUtil.replaceStatement(elseBranch, elseBranchContents.getText());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndIntention.java
index eb9984c..7482909 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndIntention.java
@@ -17,10 +17,10 @@
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ConditionalUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -42,7 +42,7 @@
}
final PsiStatement parentThenBranch = parentStatement.getThenBranch();
final PsiIfStatement childStatement =
- (PsiIfStatement)ConditionalUtils.stripBraces(parentThenBranch);
+ (PsiIfStatement)com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(parentThenBranch);
final PsiExpression childCondition = childStatement.getCondition();
if (childCondition == null) {
return;
@@ -74,6 +74,6 @@
}
@NonNls final String statement = "if(" + parentConditionText + "&&" +
childConditionText + ')' + childThenBranch.getText();
- replaceStatement(statement, parentStatement);
+ PsiReplacementUtil.replaceStatement(parentStatement, statement);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndPredicate.java
index 67fd13d..4a02dd6 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfAndPredicate.java
@@ -20,7 +20,6 @@
import com.intellij.psi.PsiJavaToken;
import com.intellij.psi.PsiStatement;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ConditionalUtils;
import com.siyeh.ipp.psiutils.ErrorUtil;
class MergeIfAndPredicate implements PsiElementPredicate {
@@ -40,9 +39,9 @@
return false;
}
PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
+ thenBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(thenBranch);
PsiStatement elseBranch = ifStatement.getElseBranch();
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
+ elseBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(elseBranch);
if (thenBranch == null) {
return false;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrIntention.java
index 5998796..440ce37 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeIfOrIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -95,7 +96,7 @@
statement.append(childElseBranchText);
}
final String newStatement = statement.toString();
- replaceStatement(newStatement, parentStatement);
+ PsiReplacementUtil.replaceStatement(parentStatement, newStatement);
}
private static void replaceMergeableImplicitIf(PsiJavaToken token)
@@ -147,7 +148,7 @@
newStatement.append("else ");
newStatement.append(childElseBranch.getText());
}
- replaceStatement(newStatement.toString(), parentStatement);
+ PsiReplacementUtil.replaceStatement(parentStatement, newStatement.toString());
childStatement.delete();
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsIntention.java
index 77d7c6a..65b028b 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/MergeParallelIfsIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -42,7 +43,7 @@
final String statement =
mergeIfStatements(firstStatement, secondStatement);
assert firstStatement != null;
- replaceStatement(statement, firstStatement);
+ PsiReplacementUtil.replaceStatement(firstStatement, statement);
assert secondStatement != null;
secondStatement.delete();
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java
index c30df47..ee18b81 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalIntention.java
@@ -18,11 +18,11 @@
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiDiamondTypeUtil;
import com.intellij.psi.util.PsiTreeUtil;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ConditionalUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -46,9 +46,11 @@
return;
}
final PsiStatement thenBranch = ifStatement.getThenBranch();
- final PsiExpressionStatement strippedThenBranch = (PsiExpressionStatement)ConditionalUtils.stripBraces(thenBranch);
+ final PsiExpressionStatement strippedThenBranch = (PsiExpressionStatement)com.siyeh.ig.psiutils.ControlFlowUtils
+ .stripBraces(thenBranch);
final PsiStatement elseBranch = ifStatement.getElseBranch();
- final PsiExpressionStatement strippedElseBranch = (PsiExpressionStatement)ConditionalUtils.stripBraces(elseBranch);
+ final PsiExpressionStatement strippedElseBranch = (PsiExpressionStatement)com.siyeh.ig.psiutils.ControlFlowUtils
+ .stripBraces(elseBranch);
final PsiAssignmentExpression thenAssign = (PsiAssignmentExpression)strippedThenBranch.getExpression();
final PsiAssignmentExpression elseAssign = (PsiAssignmentExpression)strippedElseBranch.getExpression();
final PsiExpression lhs = thenAssign.getLExpression();
@@ -64,7 +66,7 @@
return;
}
final String conditional = getConditionalText(condition, thenRhs, elseRhs, thenAssign.getType());
- replaceStatement(lhsText + operator + conditional + ';', ifStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, lhsText + operator + conditional + ';');
}
else if (ReplaceIfWithConditionalPredicate.isReplaceableReturn(ifStatement)) {
final PsiExpression condition = ifStatement.getCondition();
@@ -72,9 +74,9 @@
return;
}
final PsiStatement thenBranch = ifStatement.getThenBranch();
- final PsiReturnStatement thenReturn = (PsiReturnStatement)ConditionalUtils.stripBraces(thenBranch);
+ final PsiReturnStatement thenReturn = (PsiReturnStatement)com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(thenBranch);
final PsiStatement elseBranch = ifStatement.getElseBranch();
- final PsiReturnStatement elseReturn = (PsiReturnStatement)ConditionalUtils.stripBraces(elseBranch);
+ final PsiReturnStatement elseReturn = (PsiReturnStatement)com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(elseBranch);
final PsiExpression thenReturnValue = thenReturn.getReturnValue();
if (thenReturnValue == null) {
return;
@@ -89,15 +91,17 @@
}
final PsiType returnType = method.getReturnType();
final String conditional = getConditionalText(condition, thenReturnValue, elseReturnValue, returnType);
- replaceStatement("return " + conditional + ';', ifStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, "return " + conditional + ';');
}
else if (ReplaceIfWithConditionalPredicate.isReplaceableMethodCall(ifStatement)) {
final PsiExpression condition = ifStatement.getCondition();
if (condition == null) {
return;
}
- final PsiExpressionStatement thenBranch = (PsiExpressionStatement)ConditionalUtils.stripBraces(ifStatement.getThenBranch());
- final PsiExpressionStatement elseBranch = (PsiExpressionStatement)ConditionalUtils.stripBraces(ifStatement.getElseBranch());
+ final PsiExpressionStatement thenBranch = (PsiExpressionStatement)com.siyeh.ig.psiutils.ControlFlowUtils
+ .stripBraces(ifStatement.getThenBranch());
+ final PsiExpressionStatement elseBranch = (PsiExpressionStatement)com.siyeh.ig.psiutils.ControlFlowUtils
+ .stripBraces(ifStatement.getElseBranch());
final PsiMethodCallExpression thenMethodCallExpression = (PsiMethodCallExpression)thenBranch.getExpression();
final PsiMethodCallExpression elseMethodCallExpression = (PsiMethodCallExpression)elseBranch.getExpression();
final StringBuilder replacementText = new StringBuilder(thenMethodCallExpression.getMethodExpression().getText());
@@ -130,14 +134,15 @@
}
}
replacementText.append(");");
- replaceStatement(replacementText.toString(), ifStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, replacementText.toString());
}
else if (ReplaceIfWithConditionalPredicate.isReplaceableImplicitReturn(ifStatement)) {
final PsiExpression condition = ifStatement.getCondition();
if (condition == null) {
return;
}
- final PsiReturnStatement thenBranch = (PsiReturnStatement)ConditionalUtils.stripBraces(ifStatement.getThenBranch());
+ final PsiReturnStatement thenBranch = (PsiReturnStatement)com.siyeh.ig.psiutils.ControlFlowUtils
+ .stripBraces(ifStatement.getThenBranch());
final PsiExpression thenReturnValue = thenBranch.getReturnValue();
if (thenReturnValue == null) {
return;
@@ -159,7 +164,7 @@
if (conditional == null) {
return;
}
- replaceStatement("return " + conditional + ';', ifStatement);
+ PsiReplacementUtil.replaceStatement(ifStatement, "return " + conditional + ';');
elseBranch.delete();
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalPredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalPredicate.java
index 47ab770..d6cf5d7 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalPredicate.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/ReplaceIfWithConditionalPredicate.java
@@ -20,7 +20,6 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ConditionalUtils;
import com.siyeh.ipp.psiutils.ErrorUtil;
class ReplaceIfWithConditionalPredicate implements PsiElementPredicate {
@@ -57,11 +56,11 @@
public static boolean isReplaceableMethodCall(PsiIfStatement ifStatement) {
final PsiStatement thenBranch = ifStatement.getThenBranch();
final PsiStatement elseBranch = ifStatement.getElseBranch();
- final PsiStatement thenStatement = ConditionalUtils.stripBraces(thenBranch);
+ final PsiStatement thenStatement = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(thenBranch);
if (thenStatement == null) {
return false;
}
- final PsiStatement elseStatement = ConditionalUtils.stripBraces(elseBranch);
+ final PsiStatement elseStatement = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(elseBranch);
if (elseStatement == null) {
return false;
}
@@ -105,7 +104,7 @@
return false;
}
PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
+ thenBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(thenBranch);
if (!(thenBranch instanceof PsiReturnStatement)) {
return false;
}
@@ -136,9 +135,9 @@
public static boolean isReplaceableReturn(PsiIfStatement ifStatement) {
PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
+ thenBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(thenBranch);
PsiStatement elseBranch = ifStatement.getElseBranch();
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
+ elseBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(elseBranch);
if (!(thenBranch instanceof PsiReturnStatement) || !(elseBranch instanceof PsiReturnStatement)) {
return false;
}
@@ -159,8 +158,8 @@
}
public static boolean isReplaceableAssignment(PsiIfStatement ifStatement) {
- final PsiStatement thenBranch = ConditionalUtils.stripBraces(ifStatement.getThenBranch());
- final PsiStatement elseBranch = ConditionalUtils.stripBraces(ifStatement.getElseBranch());
+ final PsiStatement thenBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
+ final PsiStatement elseBranch = com.siyeh.ig.psiutils.ControlFlowUtils.stripBraces(ifStatement.getElseBranch());
if (thenBranch == null || elseBranch == null) {
return false;
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElseIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElseIntention.java
index f2804ae..3cedc2a 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElseIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElseIntention.java
@@ -15,198 +15,34 @@
*/
package com.siyeh.ipp.trivialif;
-import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.util.IncorrectOperationException;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiIfStatement;
+import com.intellij.psi.PsiJavaToken;
+import com.siyeh.ig.controlflow.TrivialIfInspection;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.BoolUtils;
-import com.siyeh.ipp.psiutils.ConditionalUtils;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.NonNls;
public class SimplifyIfElseIntention extends Intention {
@NotNull
public PsiElementPredicate getElementPredicate() {
- return new SimplifyIfElsePredicate();
+ return new PsiElementPredicate() {
+ public boolean satisfiedBy(PsiElement element) {
+ if (!(element instanceof PsiJavaToken)) {
+ return false;
+ }
+ final PsiJavaToken token = (PsiJavaToken)element;
+ final PsiElement parent = token.getParent();
+ if (!(parent instanceof PsiIfStatement)) {
+ return false;
+ }
+ return TrivialIfInspection.isTrivial((PsiIfStatement)parent);
+ }
+ };
}
- public void processIntention(@NotNull PsiElement element)
- throws IncorrectOperationException {
- final PsiIfStatement statement = (PsiIfStatement)element.getParent();
- if (SimplifyIfElsePredicate.isSimplifiableAssignment(statement)) {
- replaceSimplifiableAssignment(statement);
- }
- else if (SimplifyIfElsePredicate.isSimplifiableReturn(statement)) {
- replaceSimplifiableReturn(statement);
- }
- else if (SimplifyIfElsePredicate.isSimplifiableImplicitReturn(
- statement)) {
- replaceSimplifiableImplicitReturn(statement);
- }
- else if (SimplifyIfElsePredicate.isSimplifiableAssignmentNegated(
- statement)) {
- replaceSimplifiableAssignmentNegated(statement);
- }
- else if (SimplifyIfElsePredicate.isSimplifiableReturnNegated(
- statement)) {
- replaceSimplifiableReturnNegated(statement);
- }
- else if (SimplifyIfElsePredicate.isSimplifiableImplicitReturnNegated(
- statement)) {
- replaceSimplifiableImplicitReturnNegated(statement);
- }
- else if (SimplifyIfElsePredicate.isSimplifiableImplicitAssignment(
- statement)) {
- replaceSimplifiableImplicitAssignment(statement);
- }
- else if (
- SimplifyIfElsePredicate.isSimplifiableImplicitAssignmentNegated(
- statement)) {
- replaceSimplifiableImplicitAssignmentNegated(statement);
- }
- }
-
- private static void replaceSimplifiableImplicitReturn(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(statement,
- PsiWhiteSpace.class);
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(newStatement, statement);
- assert nextStatement != null;
- nextStatement.delete();
- }
-
- private static void replaceSimplifiableReturn(PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(newStatement, statement);
- }
-
- private static void replaceSimplifiableAssignment(PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)ConditionalUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)assignmentStatement.getExpression();
- final PsiJavaToken operator = assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(lhsText + operand + conditionText + ';',
- statement);
- }
-
- private static void replaceSimplifiableImplicitAssignment(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiElement prevStatement =
- PsiTreeUtil.skipSiblingsBackward(statement,
- PsiWhiteSpace.class);
- final PsiExpression condition = statement.getCondition();
- if (condition == null) {
- return;
- }
- final String conditionText = condition.getText();
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)ConditionalUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)assignmentStatement.getExpression();
- final PsiJavaToken operator = assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(lhsText + operand + conditionText + ';',
- statement);
- assert prevStatement != null;
- prevStatement.delete();
- }
-
- private static void replaceSimplifiableImplicitAssignmentNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiElement prevStatement =
- PsiTreeUtil.skipSiblingsBackward(statement,
- PsiWhiteSpace.class);
- final PsiExpression condition = statement.getCondition();
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)ConditionalUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)assignmentStatement.getExpression();
- final PsiJavaToken operator = assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(lhsText + operand + conditionText + ';',
- statement);
- assert prevStatement != null;
- prevStatement.delete();
- }
-
- private static void replaceSimplifiableImplicitReturnNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(statement,
- PsiWhiteSpace.class);
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(newStatement, statement);
- assert nextStatement != null;
- nextStatement.delete();
- }
-
- private static void replaceSimplifiableReturnNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- @NonNls final String newStatement = "return " + conditionText + ';';
- replaceStatement(newStatement, statement);
- }
-
- private static void replaceSimplifiableAssignmentNegated(
- PsiIfStatement statement)
- throws IncorrectOperationException {
- final PsiExpression condition = statement.getCondition();
- final String conditionText =
- BoolUtils.getNegatedExpressionText(condition);
- final PsiStatement thenBranch = statement.getThenBranch();
- final PsiExpressionStatement assignmentStatement =
- (PsiExpressionStatement)ConditionalUtils.stripBraces(thenBranch);
- final PsiAssignmentExpression assignmentExpression =
- (PsiAssignmentExpression)assignmentStatement.getExpression();
- final PsiJavaToken operator = assignmentExpression.getOperationSign();
- final String operand = operator.getText();
- final PsiExpression lhs = assignmentExpression.getLExpression();
- final String lhsText = lhs.getText();
- replaceStatement(lhsText + operand + conditionText + ';',
- statement);
+ public void processIntention(@NotNull PsiElement element) {
+ TrivialIfInspection.simplify((PsiIfStatement)element.getParent());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElsePredicate.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElsePredicate.java
deleted file mode 100644
index 3513c9e..0000000
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SimplifyIfElsePredicate.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * Copyright 2003-2007 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.trivialif;
-
-import com.intellij.psi.*;
-import com.intellij.psi.tree.IElementType;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.siyeh.ipp.base.PsiElementPredicate;
-import com.siyeh.ipp.psiutils.ConditionalUtils;
-import com.siyeh.ig.psiutils.EquivalenceChecker;
-import com.siyeh.ipp.psiutils.ErrorUtil;
-
-class SimplifyIfElsePredicate implements PsiElementPredicate {
-
- public boolean satisfiedBy(PsiElement element) {
- if (!(element instanceof PsiJavaToken)) {
- return false;
- }
- final PsiJavaToken token = (PsiJavaToken)element;
- final PsiElement parent = token.getParent();
- if (!(parent instanceof PsiIfStatement)) {
- return false;
- }
- final PsiIfStatement ifStatement = (PsiIfStatement)parent;
- if (ErrorUtil.containsError(ifStatement)) {
- return false;
- }
- final PsiExpression condition = ifStatement.getCondition();
- if (condition == null) {
- return false;
- }
- if (isSimplifiableAssignment(ifStatement)) {
- return true;
- }
- if (isSimplifiableReturn(ifStatement)) {
- return true;
- }
- if (isSimplifiableImplicitReturn(ifStatement)) {
- return true;
- }
- if (isSimplifiableAssignmentNegated(ifStatement)) {
- return true;
- }
- if (isSimplifiableReturnNegated(ifStatement)) {
- return true;
- }
- if (isSimplifiableImplicitReturnNegated(ifStatement)) {
- return true;
- }
- if (isSimplifiableImplicitAssignment(ifStatement)) {
- return true;
- }
- return isSimplifiableImplicitAssignmentNegated(ifStatement);
- }
-
- public static boolean isSimplifiableImplicitReturn(
- PsiIfStatement ifStatement) {
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- if (ifStatement.getElseBranch() != null) {
- return false;
- }
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(ifStatement,
- PsiWhiteSpace.class);
- if (!(nextStatement instanceof PsiStatement)) {
- return false;
- }
- final PsiStatement elseBranch = (PsiStatement)nextStatement;
- return ConditionalUtils.isReturn(thenBranch, "true")
- && ConditionalUtils.isReturn(elseBranch, "false");
- }
-
- public static boolean isSimplifiableImplicitReturnNegated(
- PsiIfStatement ifStatement) {
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- if (ifStatement.getElseBranch() != null) {
- return false;
- }
- final PsiElement nextStatement =
- PsiTreeUtil.skipSiblingsForward(ifStatement,
- PsiWhiteSpace.class);
- if (!(nextStatement instanceof PsiStatement)) {
- return false;
- }
- final PsiStatement elseBranch = (PsiStatement)nextStatement;
- return ConditionalUtils.isReturn(thenBranch, "false")
- && ConditionalUtils.isReturn(elseBranch, "true");
- }
-
- public static boolean isSimplifiableReturn(PsiIfStatement ifStatement) {
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- PsiStatement elseBranch = ifStatement.getElseBranch();
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
- return ConditionalUtils.isReturn(thenBranch, "true")
- && ConditionalUtils.isReturn(elseBranch, "false");
- }
-
- public static boolean isSimplifiableReturnNegated(
- PsiIfStatement ifStatement) {
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- PsiStatement elseBranch = ifStatement.getElseBranch();
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
- return ConditionalUtils.isReturn(thenBranch, "false")
- && ConditionalUtils.isReturn(elseBranch, "true");
- }
-
- public static boolean isSimplifiableAssignment(PsiIfStatement ifStatement) {
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- PsiStatement elseBranch = ifStatement.getElseBranch();
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
- if (!(ConditionalUtils.isAssignment(thenBranch, "true") &&
- ConditionalUtils.isAssignment(elseBranch, "false"))) {
- return false;
- }
- final PsiExpressionStatement thenExpressionStatement =
- (PsiExpressionStatement)thenBranch;
- final PsiAssignmentExpression thenExpression =
- (PsiAssignmentExpression)
- thenExpressionStatement.getExpression();
- final PsiExpressionStatement elseExpressionStatement =
- (PsiExpressionStatement)elseBranch;
- final PsiAssignmentExpression elseExpression =
- (PsiAssignmentExpression)
- elseExpressionStatement.getExpression();
- final IElementType thenTokenType = thenExpression.getOperationTokenType();
- if (!thenTokenType.equals(elseExpression.getOperationTokenType())) {
- return false;
- }
- final PsiExpression thenLhs = thenExpression.getLExpression();
- final PsiExpression elseLhs = elseExpression.getLExpression();
- return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs);
- }
-
- public static boolean isSimplifiableAssignmentNegated(
- PsiIfStatement ifStatement) {
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- PsiStatement elseBranch = ifStatement.getElseBranch();
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
- if (!ConditionalUtils.isAssignment(thenBranch, "false") ||
- !ConditionalUtils.isAssignment(elseBranch, "true")) {
- return false;
- }
- final PsiExpressionStatement thenExpressionStatement =
- (PsiExpressionStatement)thenBranch;
- final PsiAssignmentExpression thenExpression =
- (PsiAssignmentExpression)
- thenExpressionStatement.getExpression();
- final PsiExpressionStatement elseExpressionStatement =
- (PsiExpressionStatement)elseBranch;
- final PsiAssignmentExpression elseExpression =
- (PsiAssignmentExpression)
- elseExpressionStatement.getExpression();
- final IElementType thenTokenType = thenExpression.getOperationTokenType();
- if (!thenTokenType.equals(elseExpression.getOperationTokenType())) {
- return false;
- }
- final PsiExpression thenLhs = thenExpression.getLExpression();
- final PsiExpression elseLhs = elseExpression.getLExpression();
- return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs);
- }
-
- public static boolean isSimplifiableImplicitAssignment(
- PsiIfStatement ifStatement) {
- if (ifStatement.getElseBranch() != null) {
- return false;
- }
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- final PsiElement previousStatement =
- PsiTreeUtil.skipSiblingsBackward(ifStatement,
- PsiWhiteSpace.class);
- if (!(previousStatement instanceof PsiStatement)) {
- return false;
- }
- PsiStatement elseBranch = (PsiStatement)previousStatement;
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
- if (!ConditionalUtils.isAssignment(thenBranch, "true") ||
- !ConditionalUtils.isAssignment(elseBranch, "false")) {
- return false;
- }
- final PsiAssignmentExpression thenExpression =
- (PsiAssignmentExpression)
- ((PsiExpressionStatement)thenBranch).getExpression();
- final PsiAssignmentExpression elseExpression =
- (PsiAssignmentExpression)
- ((PsiExpressionStatement)elseBranch).getExpression();
- final IElementType thenTokenType = thenExpression.getOperationTokenType();
- if (!thenTokenType.equals(elseExpression.getOperationTokenType())) {
- return false;
- }
- final PsiExpression thenLhs = thenExpression.getLExpression();
- final PsiExpression elseLhs = elseExpression.getLExpression();
- return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs);
- }
-
- public static boolean isSimplifiableImplicitAssignmentNegated(
- PsiIfStatement ifStatement) {
- if (ifStatement.getElseBranch() != null) {
- return false;
- }
- PsiStatement thenBranch = ifStatement.getThenBranch();
- thenBranch = ConditionalUtils.stripBraces(thenBranch);
- final PsiElement previousStatement =
- PsiTreeUtil.skipSiblingsBackward(ifStatement,
- PsiWhiteSpace.class);
- if (!(previousStatement instanceof PsiStatement)) {
- return false;
- }
- PsiStatement elseBranch = (PsiStatement)previousStatement;
- elseBranch = ConditionalUtils.stripBraces(elseBranch);
- if (!ConditionalUtils.isAssignment(thenBranch, "false") ||
- !ConditionalUtils.isAssignment(elseBranch, "true")) {
- return false;
- }
- final PsiExpressionStatement thenExpressionStatement =
- (PsiExpressionStatement)thenBranch;
- final PsiAssignmentExpression thenExpression =
- (PsiAssignmentExpression)
- thenExpressionStatement.getExpression();
- final PsiExpressionStatement elseExpressionStatement =
- (PsiExpressionStatement)elseBranch;
- final PsiAssignmentExpression elseExpression =
- (PsiAssignmentExpression)
- elseExpressionStatement.getExpression();
- final IElementType thenTokenType = thenExpression.getOperationTokenType();
- if (!thenTokenType.equals(elseExpression.getOperationTokenType())) {
- return false;
- }
- final PsiExpression thenLhs = thenExpression.getLExpression();
- final PsiExpression elseLhs = elseExpression.getLExpression();
- return EquivalenceChecker.expressionsAreEquivalent(thenLhs, elseLhs);
- }
-}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SplitElseIfIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SplitElseIfIntention.java
index 9c94506..2de6d9d 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SplitElseIfIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/trivialif/SplitElseIfIntention.java
@@ -20,6 +20,7 @@
import com.intellij.psi.PsiJavaToken;
import com.intellij.psi.PsiStatement;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -44,6 +45,6 @@
return;
}
final String newStatement = '{' + elseBranch.getText() + '}';
- replaceStatement(newStatement, elseBranch);
+ PsiReplacementUtil.replaceStatement(elseBranch, newStatement);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java
index bd63923..7a31564 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntention.java
@@ -74,6 +74,9 @@
final Map<PsiElement, PsiElement> replacements = new HashMap<PsiElement, PsiElement>();
blockFromText.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
+ public void visitClass(PsiClass aClass) {}
+
+ @Override
public void visitSuperExpression(PsiSuperExpression expression) {
super.visitSuperExpression(expression);
if (expression.getQualifier() == null) {
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java
index 1d479be..fc57ba3 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/unicode/ReplaceOctalEscapeWithUnicodeEscapeIntention.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiLiteralExpression;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementEditorPredicate;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -72,7 +73,7 @@
newLiteralText.append(text.substring(0, escapeStart));
final int escapeEnd = appendUnicodeEscape(text, escapeStart, newLiteralText);
newLiteralText.append(text.substring(escapeEnd, text.length()));
- replaceExpression(newLiteralText.toString(), literalExpression);
+ PsiReplacementUtil.replaceExpression(literalExpression, newLiteralText.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/varargs/WrapVarargArgumentsWithExplicitArrayIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/varargs/WrapVarargArgumentsWithExplicitArrayIntention.java
index 3769ebd..8408bb7 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/varargs/WrapVarargArgumentsWithExplicitArrayIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/varargs/WrapVarargArgumentsWithExplicitArrayIntention.java
@@ -18,6 +18,7 @@
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
@@ -78,6 +79,6 @@
}
}
newExpression.append("})");
- replaceExpression(newExpression.toString(), methodCallExpression);
+ PsiReplacementUtil.replaceExpression(methodCallExpression, newExpression.toString());
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceDoWhileLoopWithWhileLoopIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceDoWhileLoopWithWhileLoopIntention.java
index 050fdcb..6647b0a 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceDoWhileLoopWithWhileLoopIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceDoWhileLoopWithWhileLoopIntention.java
@@ -16,6 +16,7 @@
package com.siyeh.ipp.whileloop;
import com.intellij.psi.*;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -44,7 +45,7 @@
if (body != null) {
replacementText.append(body.getText());
}
- replaceStatement(replacementText.toString(), doWhileStatement);
+ PsiReplacementUtil.replaceStatement(doWhileStatement, replacementText.toString());
return;
}
final boolean noBraces = !(parent instanceof PsiCodeBlock);
@@ -136,10 +137,10 @@
replacementText.append('}');
}
if (noBraces) {
- replaceStatement(replacementText.toString(), (PsiStatement)parent);
+ PsiReplacementUtil.replaceStatement((PsiStatement)parent, replacementText.toString());
}
else {
- replaceStatement(replacementText.toString(), doWhileStatement);
+ PsiReplacementUtil.replaceStatement(doWhileStatement, replacementText.toString());
}
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceWhileLoopWithDoWhileLoopIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceWhileLoopWithDoWhileLoopIntention.java
index ee308bd..5a2d3fb 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceWhileLoopWithDoWhileLoopIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/whileloop/ReplaceWhileLoopWithDoWhileLoopIntention.java
@@ -16,6 +16,7 @@
package com.siyeh.ipp.whileloop;
import com.intellij.psi.*;
+import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.BoolUtils;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementPredicate;
@@ -69,6 +70,6 @@
if (!infiniteLoop) {
doWhileStatementText.append("\n}");
}
- replaceStatement(doWhileStatementText.toString(), whileStatement);
+ PsiReplacementUtil.replaceStatement(whileStatement, doWhileStatementText.toString());
}
}
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/after.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/after.java.template
index b34986a..3fcfe9f 100644
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/after.java.template
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/after.java.template
@@ -1,6 +1,6 @@
public class X {
void f(Object foo) {
- if (foo==null) {
+ if (foo == null) {
throw new AssertionError("Argument is null");
}
}
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/description.html b/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/description.html
index 322b2b4..5890f7a 100644
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/description.html
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/AssertToIfIntention/description.html
@@ -1,6 +1,6 @@
<html>
<body>
-This intention replaces an <b>assert</b> statement with an
-<b>if</b> statement which throws an AssertionError if the asserted condition is false.
+This intention replaces an <b>assert</b> statement with an equivalent
+<b>if</b> statement which throws an <b>java.lang.AssertionError</b> if the asserted condition is <b>false</b>.
</body>
</html>
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/before.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/before.java.template
index b6dad71..7bb74ea 100644
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/before.java.template
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/before.java.template
@@ -1,6 +1,6 @@
public class X {
void f(Object foo) {
- <spot>if</spot> (foo==null) {
+ <spot>if</spot> (foo == null) {
throw new AssertionError("Argument is null");
}
}
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/description.html b/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/description.html
index a58e126..2175860 100644
--- a/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/description.html
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/IfToAssertionIntention/description.html
@@ -1,7 +1,7 @@
<html>
<body>
This intention replaces an <b>if</b> statement
-which throws an AssertionError if the condition is false, with an <b>assert</b> statement.
+which throws any <b>java.lang.Throwable</b> when the condition is <b>true</b> and does not have an <b>else</b> branch, with an <b>assert</b> statement.
<br><br>
<small>New in 10</small>
</body>
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/after.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/after.java.template
new file mode 100644
index 0000000..93acdd6
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/after.java.template
@@ -0,0 +1,9 @@
+import java.util.Objects;
+
+public class X {
+ private String s;
+
+ public X(String s) {
+ this.s = Objects.requireNonNull(s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/before.java.template b/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/before.java.template
new file mode 100644
index 0000000..5dc33a1
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/before.java.template
@@ -0,0 +1,8 @@
+public class X {
+ private String s;
+
+ public X(String s) {
+ if (s == null) throw new NullPointerException();
+ this.s = <spot>s</spot>;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/description.html b/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/description.html
new file mode 100644
index 0000000..848c8c0
--- /dev/null
+++ b/plugins/IntentionPowerPak/src/intentionDescriptions/ObjectsRequireNonNullIntention/description.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+Converts a variable read access where the variable is first checked for <b>null</b> using either a @NonNull annotation,
+an <b>if</b> statement which throws an exception or an <b>assert</b> statement to an expression using a call to
+<b>java.util.Objects.requireNonNull()</b>.
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/if_to_assert/Parentheses.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/if_to_assert/Parentheses.java
new file mode 100644
index 0000000..e9c591b
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/if_to_assert/Parentheses.java
@@ -0,0 +1,9 @@
+package com.siyeh.ipp.asserttoif.if_to_assert;
+
+class Parentheses {
+ void s(String s) {
+ if<caret> (s == null) {
+ throw (new NullPointerException(("s")));
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/if_to_assert/Parentheses_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/if_to_assert/Parentheses_after.java
new file mode 100644
index 0000000..e479d9a
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/if_to_assert/Parentheses_after.java
@@ -0,0 +1,7 @@
+package com.siyeh.ipp.asserttoif.if_to_assert;
+
+class Parentheses {
+ void s(String s) {
+ assert s != null : ("s");
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/One.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/One.java
new file mode 100644
index 0000000..628ed07
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/One.java
@@ -0,0 +1,10 @@
+package objects_require_non_null;
+
+import org.jetbrains.annotations.NotNull;
+
+class One {
+ private String s;
+ One(@NotNull String s) {
+ this.s = <caret>s;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/One_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/One_after.java
new file mode 100644
index 0000000..06d9524
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/One_after.java
@@ -0,0 +1,12 @@
+package objects_require_non_null;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Objects;
+
+class One {
+ private String s;
+ One(String s) {
+ this.s = Objects.requireNonNull(s);
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Three.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Three.java
new file mode 100644
index 0000000..339e9ee
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Three.java
@@ -0,0 +1,8 @@
+package objects_require_non_null;
+
+class Three {
+ void a(Integer i) {
+ assert ((i) != (null));
+ System.out.println(i<caret>);
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Three_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Three_after.java
new file mode 100644
index 0000000..86c63b9
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Three_after.java
@@ -0,0 +1,9 @@
+package objects_require_non_null;
+
+import java.util.Objects;
+
+class Three {
+ void a(Integer i) {
+ System.out.println(Objects.requireNonNull(i));
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Two.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Two.java
new file mode 100644
index 0000000..a89df76
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Two.java
@@ -0,0 +1,12 @@
+package objects_require_non_null;
+
+class Two {
+ private Object o;
+
+ Two(Object o) {
+ if (o == null) {
+ throw new NullPointerException();
+ }
+ this.o = <caret>o;
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Two_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Two_after.java
new file mode 100644
index 0000000..6e630bf
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/asserttoif/objects_require_non_null/Two_after.java
@@ -0,0 +1,11 @@
+package objects_require_non_null;
+
+import java.util.Objects;
+
+class Two {
+ private Object o;
+
+ Two(Object o) {
+ this.o = Objects.requireNonNull(o);
+ }
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/Method.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/Method.java
new file mode 100644
index 0000000..f9039da
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/Method.java
@@ -0,0 +1,4 @@
+class Method {
+
+ <caret>void m() {}
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/Method_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/Method_after.java
new file mode 100644
index 0000000..e03c018
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/Method_after.java
@@ -0,0 +1,4 @@
+class Method {
+
+ private void m() {}
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyClass.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyClass.java
new file mode 100644
index 0000000..6ecfed8
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyClass.java
@@ -0,0 +1,5 @@
+package com.siyeh.ipp.modifiers.make_public;
+
+class<caret> MyClass {
+
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyEnum.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyEnum.java
new file mode 100644
index 0000000..424cfe5
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyEnum.java
@@ -0,0 +1,5 @@
+package com.siyeh.ipp.modifiers.make_public;
+
+enum MyEnum {
+ A, B<caret>, C
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyInterface.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyInterface.java
new file mode 100644
index 0000000..121a6a8
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/modifiers/make_public/MyInterface.java
@@ -0,0 +1,6 @@
+package com.siyeh.ipp.modifiers.make_public;
+
+public interface MyInterface {
+
+ void <caret>m();
+}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ComparisonParentheses.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ComparisonParentheses.java
index 7c5dde2..8eda383 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ComparisonParentheses.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/parentheses/ComparisonParentheses.java
@@ -1,9 +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.siyeh.ipp.parentheses;
class ComparisonParenthese {
void foo(Object a, boolean b) {
final boolean c = b == (a <caret>!= null);
- boolean d = c == (1 < 3<caret>);
+ boolean d = c == (1 < 3);
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/LocalClasses.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/LocalClasses.java
new file mode 100644
index 0000000..79b5ba4
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/LocalClasses.java
@@ -0,0 +1,23 @@
+class Test2 {
+
+ class A {
+ void foo(){}
+ }
+
+ interface I<X> {
+ X foo();
+ }
+
+ static <T> I<T> bar(I<T> i){return i;}
+
+ {
+ bar((<caret>)->{
+ A a = new A() {
+ void foo() {
+ super.foo();
+ }
+ }
+ return "sss";
+ });
+ }
+}
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/LocalClasses_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/LocalClasses_after.java
new file mode 100644
index 0000000..9130d92
--- /dev/null
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/types/lambda2anonymous/LocalClasses_after.java
@@ -0,0 +1,26 @@
+class Test2 {
+
+ class A {
+ void foo(){}
+ }
+
+ interface I<X> {
+ X foo();
+ }
+
+ static <T> I<T> bar(I<T> i){return i;}
+
+ {
+ bar(new I<String>() {
+ @Override
+ public String foo() {
+ <selection>A a = new A() {
+ void foo() {
+ super.foo();
+ }
+ }
+ return "sss";</selection>
+ }
+ });
+ }
+}
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop.java
index 245c853..0061e9c 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop.java
@@ -5,6 +5,6 @@
do<caret> {
int i = 10;
System.out.println(i);
- } while (true);
+ } while ((true));
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop_after.java
index d8469c7..e075bef 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop_after.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_do_while_with_while_loop/InfiniteLoop_after.java
@@ -2,7 +2,7 @@
class InfiniteLoop {
void m() {
- while (true) {
+ while ((true)) {
int i = 10;
System.out.println(i);
}
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop.java
index ca54d07..ccba421 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop.java
@@ -3,7 +3,7 @@
class InfiniteLoop {
void m() {
- while<caret>(true) {
+ while<caret>((true)) {
System.out.println(1);
}
}
diff --git a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop_after.java b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop_after.java
index ec64399..efe03a6 100644
--- a/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop_after.java
+++ b/plugins/IntentionPowerPak/test/com/siyeh/ipp/whileloop/replace_while_with_do_while_loop/InfiniteLoop_after.java
@@ -5,6 +5,6 @@
void m() {
do {
System.out.println(1);
- } while (true);
+ } while ((true));
}
}
\ No newline at end of file
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/IfToAssertionIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/IfToAssertionIntentionTest.java
index 919325d..df70b56 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/IfToAssertionIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/IfToAssertionIntentionTest.java
@@ -19,11 +19,13 @@
import com.siyeh.ipp.IPPTestCase;
/**
+ * @see IfToAssertionIntention
* @author Bas Leijdekkers
*/
public class IfToAssertionIntentionTest extends IPPTestCase {
public void testRandomThrowable() { doTest(); }
+ public void testParentheses() { doTest(); }
@Override
protected String getRelativePath() {
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntentionTest.java
new file mode 100644
index 0000000..9b22a7f
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/asserttoif/ObjectsRequireNonNullIntentionTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.siyeh.ipp.asserttoif;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @see com.siyeh.ipp.asserttoif.ObjectsRequireNonNullIntention
+ * @author Bas Leijdekkers
+ */
+public class ObjectsRequireNonNullIntentionTest extends IPPTestCase {
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ myFixture.addClass("package java.util;\n" +
+ "public class Objects {\n" +
+ " public static <T> T requireNonNull(T obj) {\n" +
+ " if (obj == null)\n" +
+ " throw new NullPointerException();\n" +
+ " return obj;\n" +
+ " }\n" +
+ "}");
+ }
+
+ public void testOne() { doTest(); }
+ public void testTwo() { doTest(); }
+ public void testThree() { doTest(); }
+
+ @Override
+ protected String getRelativePath() {
+ return "asserttoif/objects_require_non_null";
+ }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("objects.require.non.null.intention.name");
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java
new file mode 100644
index 0000000..e7e3911
--- /dev/null
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/modifiers/MakePrivateIntentionTest.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.modifiers;
+
+import com.siyeh.IntentionPowerPackBundle;
+import com.siyeh.ipp.IPPTestCase;
+
+/**
+ * @author Bas Leijdekkers
+ */
+public class MakePrivateIntentionTest extends IPPTestCase {
+
+ public void testMyEnum() { assertIntentionNotAvailable(); }
+ public void testMyClass() { assertIntentionNotAvailable(); }
+ public void testMyInterface() { assertIntentionNotAvailable(); }
+ public void testMethod() { doTest(); }
+
+ @Override
+ protected String getRelativePath() {
+ return "modifiers/make_public";
+ }
+
+ @Override
+ protected String getIntentionName() {
+ return IntentionPowerPackBundle.message("make.private.intention.name");
+ }
+}
diff --git a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java
index 21841d1..dfcdca5 100644
--- a/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java
+++ b/plugins/IntentionPowerPak/testSrc/com/siyeh/ipp/types/ReplaceLambdaWithAnonymousIntentionTest.java
@@ -47,6 +47,10 @@
doTest();
}
+ public void testLocalClasses() {
+ doTest();
+ }
+
public void testNoFunctionalInterfaceFound() {
assertIntentionNotAvailable();
}
diff --git a/plugins/ant/src/META-INF/plugin.xml b/plugins/ant/src/META-INF/plugin.xml
index 89dbf88..6917238 100644
--- a/plugins/ant/src/META-INF/plugin.xml
+++ b/plugins/ant/src/META-INF/plugin.xml
@@ -14,6 +14,8 @@
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
+ <tipAndTrick file="CreateTargetTag.html" />
+
<projectService serviceInterface="com.intellij.lang.ant.config.AntConfiguration" serviceImplementation="com.intellij.lang.ant.config.impl.AntConfigurationImpl"/>
<projectService serviceInterface="com.intellij.lang.ant.config.impl.AntWorkspaceConfiguration" serviceImplementation="com.intellij.lang.ant.config.impl.AntWorkspaceConfiguration"/>
diff --git a/plugins/ant/src/com/intellij/lang/ant/AntBundle.java b/plugins/ant/src/com/intellij/lang/ant/AntBundle.java
index 552e517..2abb224 100644
--- a/plugins/ant/src/com/intellij/lang/ant/AntBundle.java
+++ b/plugins/ant/src/com/intellij/lang/ant/AntBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,21 +25,19 @@
import java.util.ResourceBundle;
public class AntBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
protected static final String PATH_TO_BUNDLE = "messages.AntBundle";
private AntBundle() {
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java
index 76baab1..e718b8f 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/execution/AntBuildMessageView.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -265,11 +265,11 @@
AntBundle.message("starting.ant.build.dialog.title"), Messages.getQuestionIcon());
switch (result) {
- case 0: // yes
+ case Messages.YES: // yes
buildMessageView.stopProcess();
ijMessageView.getContentManager().removeContent(content, true);
continue;
- case 1: // no
+ case Messages.NO: // no
continue;
default: // cancel
return null;
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntExplorer.java b/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntExplorer.java
index f058ce9..2976c03 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntExplorer.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/explorer/AntExplorer.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.
@@ -263,7 +263,7 @@
final String fileName = buildFile.getPresentableUrl();
final int result = Messages.showYesNoDialog(myProject, AntBundle.message("remove.the.reference.to.file.confirmation.text", fileName),
AntBundle.message("confirm.remove.dialog.title"), Messages.getQuestionIcon());
- if (result != 0) {
+ if (result != Messages.YES) {
return;
}
myConfig.removeBuildFile(buildFile);
@@ -854,7 +854,7 @@
@Override
public boolean canImport(final TransferSupport support) {
- return FileCopyPasteUtil.isFileListFlavorSupported(support.getDataFlavors());
+ return FileCopyPasteUtil.isFileListFlavorAvailable(support.getDataFlavors());
}
private VirtualFile[] getAntFiles(final TransferSupport support) {
diff --git a/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AnActionListEditor.java b/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AnActionListEditor.java
index aba3779..8b64f01 100644
--- a/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AnActionListEditor.java
+++ b/plugins/ant/src/com/intellij/lang/ant/config/impl/configuration/AnActionListEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -76,12 +76,12 @@
return Messages.showOkCancelDialog(description.getList(),
AntBundle.message("delete.selected.ant.configuration.confirmation.text"),
ExecutionBundle.message("delete.confirmation.dialog.title"),
- Messages.getQuestionIcon()) == 0;
+ Messages.getQuestionIcon()) == Messages.OK;
} else {
return Messages.showOkCancelDialog(description.getList(),
AntBundle.message("delete.selected.ant.configurations.confirmation.text"),
ExecutionBundle.message("delete.confirmation.dialog.title"),
- Messages.getQuestionIcon()) == 0;
+ Messages.getQuestionIcon()) == Messages.OK;
}
}
});
diff --git a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomFileReferenceSet.java b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomFileReferenceSet.java
index bd6225c..6587164 100644
--- a/plugins/ant/src/com/intellij/lang/ant/dom/AntDomFileReferenceSet.java
+++ b/plugins/ant/src/com/intellij/lang/ant/dom/AntDomFileReferenceSet.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,22 +20,20 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.psi.ElementManipulators;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.xml.XmlAttributeValue;
-import com.intellij.psi.xml.XmlElement;
import com.intellij.util.xml.GenericAttributeValue;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
-import java.util.Collections;
public class AntDomFileReferenceSet extends FileReferenceSet {
-
private final GenericAttributeValue myValue;
public AntDomFileReferenceSet(final GenericAttributeValue attribValue, boolean validateFileRefs) {
@@ -67,11 +65,13 @@
}
return path;
}
-
+
+ @Override
protected boolean isSoft() {
return true;
}
+ @Override
public FileReference createFileReference(final TextRange range, final int index, final String text) {
return new AntDomFileReference(this, range, index, text);
}
@@ -82,28 +82,34 @@
}
@Nullable
+ @Override
public String getPathString() {
return myValue.getStringValue();
}
+ @Override
public boolean isAbsolutePathReference() {
if (super.isAbsolutePathReference()) {
return true;
}
- return FileUtil.isAbsolute(getPathString());
+
+ String path = getPathString();
+ return path != null && FileUtil.isAbsolute(path);
}
@NotNull
+ @Override
public Collection<PsiFileSystemItem> computeDefaultContexts() {
final AntDomElement element = myValue.getParentOfType(AntDomElement.class, false);
final AntDomProject containingProject = element != null? element.getAntProject() : null;
+
if (containingProject != null) {
- VirtualFile root = null;
if (isAbsolutePathReference()) {
- root = LocalFileSystem.getInstance().getRoot();
+ return toFileSystemItems(ManagingFS.getInstance().getLocalRoots());
}
else {
-
+ VirtualFile root = null;
+
if (element instanceof AntDomAnt) {
final PsiFileSystemItem dirValue = ((AntDomAnt)element).getAntFileDir().getValue();
if (dirValue instanceof PsiDirectory) {
@@ -123,18 +129,13 @@
root = LocalFileSystem.getInstance().findFileByPath(basedir);
}
}
- }
- if (root != null) {
- final XmlElement xmlElement = containingProject.getXmlElement();
- if (xmlElement != null) {
- final PsiDirectory directory = xmlElement.getManager().findDirectory(root);
- if (directory != null) {
- return Collections.<PsiFileSystemItem>singleton(directory);
- }
+ if (root != null) {
+ return toFileSystemItems(root);
}
}
}
+
return super.computeDefaultContexts();
}
}
diff --git a/plugins/ant/src/com/intellij/lang/ant/resources/AntActionsBundle.java b/plugins/ant/src/com/intellij/lang/ant/resources/AntActionsBundle.java
index 33872e1..3a6c9fe 100644
--- a/plugins/ant/src/com/intellij/lang/ant/resources/AntActionsBundle.java
+++ b/plugins/ant/src/com/intellij/lang/ant/resources/AntActionsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,8 +25,12 @@
import java.util.ResourceBundle;
public final class AntActionsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = IDEA_ACTIONS_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String IDEA_ACTIONS_BUNDLE = "com.intellij.lang.ant.resources.AntActionsBundle";
private AntActionsBundle() {
@@ -41,13 +46,8 @@
return message("action." + actionId + ".description");
}
- public static String message(@PropertyKey(resourceBundle = IDEA_ACTIONS_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(IDEA_ACTIONS_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/copyright/src/META-INF/plugin.xml b/plugins/copyright/src/META-INF/plugin.xml
index a064ee9..bc39143 100644
--- a/plugins/copyright/src/META-INF/plugin.xml
+++ b/plugins/copyright/src/META-INF/plugin.xml
@@ -33,7 +33,9 @@
<updater filetype="HTML" implementationClass="com.maddyhome.idea.copyright.psi.UpdateXmlCopyrightsProvider"/>
</extensions>
<extensionPoints>
- <extensionPoint name="updater" beanClass="com.intellij.openapi.fileTypes.FileTypeExtensionPoint"/>
+ <extensionPoint name="updater" beanClass="com.intellij.openapi.fileTypes.FileTypeExtensionPoint">
+ <with attribute="implementationClass" implements="com.maddyhome.idea.copyright.psi.UpdateCopyrightsProvider"/>
+ </extensionPoint>
</extensionPoints>
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java
index 09d19f9..0b36db8 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/CopyrightManager.java
@@ -33,6 +33,7 @@
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packageDependencies.DependencyValidationManager;
import com.intellij.psi.PsiFile;
@@ -58,11 +59,11 @@
storages = {@Storage(file = StoragePathMacros.PROJECT_FILE),
@Storage(file = StoragePathMacros.PROJECT_CONFIG_DIR + "/copyright/", scheme = StorageScheme.DIRECTORY_BASED,
stateSplitter = CopyrightManager.CopyrightStateSplitter.class)})
-public class CopyrightManager extends AbstractProjectComponent implements JDOMExternalizable, PersistentStateComponent<Element> {
+public class CopyrightManager extends AbstractProjectComponent implements PersistentStateComponent<Element> {
private static final Logger LOG = Logger.getInstance("#" + CopyrightManager.class.getName());
@Nullable
private CopyrightProfile myDefaultCopyright = null;
- private final LinkedHashMap<String, String> myModule2Copyrights = new LinkedHashMap<String, String>();
+ private final LinkedHashMap<String, String> myModuleToCopyrights = new LinkedHashMap<String, String>();
private final Map<String, CopyrightProfile> myCopyrights = new HashMap<String, CopyrightProfile>();
private final Options myOptions = new Options();
@@ -141,63 +142,67 @@
}
@Override
- public void readExternal(Element element) throws InvalidDataException {
- clearCopyrights();
- final Element module2copyright = element.getChild(MODULE2COPYRIGHT);
- if (module2copyright != null) {
- for (Object o : module2copyright.getChildren(ELEMENT)) {
- final Element el = (Element)o;
- final String moduleName = el.getAttributeValue(MODULE);
- final String copyrightName = el.getAttributeValue(COPYRIGHT);
- myModule2Copyrights.put(moduleName, copyrightName);
- }
- }
- for (Object o : element.getChildren(COPYRIGHT)) {
- final CopyrightProfile copyrightProfile = new CopyrightProfile();
- copyrightProfile.readExternal((Element)o);
- myCopyrights.put(copyrightProfile.getName(), copyrightProfile);
- }
- myDefaultCopyright = myCopyrights.get(element.getAttributeValue(DEFAULT));
- myOptions.readExternal(element);
- }
-
- @Override
- public void writeExternal(Element element) throws WriteExternalException {
- for (CopyrightProfile copyright : myCopyrights.values()) {
- final Element copyrightElement = new Element(COPYRIGHT);
- copyright.writeExternal(copyrightElement);
- element.addContent(copyrightElement);
- }
- final Element map = new Element(MODULE2COPYRIGHT);
- for (String moduleName : myModule2Copyrights.keySet()) {
- final Element setting = new Element(ELEMENT);
- setting.setAttribute(MODULE, moduleName);
- setting.setAttribute(COPYRIGHT, myModule2Copyrights.get(moduleName));
- map.addContent(setting);
- }
- element.addContent(map);
- element.setAttribute(DEFAULT, myDefaultCopyright != null ? myDefaultCopyright.getName() : "");
- myOptions.writeExternal(element);
- }
-
-
- @Override
public Element getState() {
+ Element state = new Element("settings");
+
try {
- final Element e = new Element("settings");
- writeExternal(e);
- return e;
+ if (!myCopyrights.isEmpty()) {
+ for (CopyrightProfile copyright : myCopyrights.values()) {
+ final Element copyrightElement = new Element(COPYRIGHT);
+ copyright.writeExternal(copyrightElement);
+ state.addContent(copyrightElement);
+ }
+ }
+
+ if (!myModuleToCopyrights.isEmpty()) {
+ final Element map = new Element(MODULE2COPYRIGHT);
+ for (String moduleName : myModuleToCopyrights.keySet()) {
+ final Element setting = new Element(ELEMENT);
+ setting.setAttribute(MODULE, moduleName);
+ setting.setAttribute(COPYRIGHT, myModuleToCopyrights.get(moduleName));
+ map.addContent(setting);
+ }
+ state.addContent(map);
+ }
+
+ myOptions.writeExternal(state);
}
- catch (WriteExternalException e1) {
- LOG.error(e1);
+ catch (WriteExternalException e) {
+ LOG.error(e);
return null;
}
+
+ if (myDefaultCopyright != null) {
+ state.setAttribute(DEFAULT, myDefaultCopyright.getName());
+ }
+ else {
+ // todo we still add empty attribute to avoid annoying change (idea 12 - attribute exists, idea 13 - attribute doesn't exists)
+ // CR-IC-3403#CFR-62470, idea <= 12 compatibility
+ state.setAttribute(DEFAULT, "");
+ }
+
+ return state;
}
@Override
public void loadState(Element state) {
+ clearCopyrights();
+
+ final Element moduleToCopyright = state.getChild(MODULE2COPYRIGHT);
+ if (moduleToCopyright != null) {
+ for (Element element : moduleToCopyright.getChildren(ELEMENT)) {
+ myModuleToCopyrights.put(element.getAttributeValue(MODULE), element.getAttributeValue(COPYRIGHT));
+ }
+ }
+
try {
- readExternal(state);
+ for (Element element : state.getChildren(COPYRIGHT)) {
+ final CopyrightProfile copyrightProfile = new CopyrightProfile();
+ copyrightProfile.readExternal(element);
+ myCopyrights.put(copyrightProfile.getName(), copyrightProfile);
+ }
+ myDefaultCopyright = myCopyrights.get(StringUtil.notNullize(state.getAttributeValue(DEFAULT)));
+ myOptions.readExternal(state);
}
catch (InvalidDataException e) {
LOG.error(e);
@@ -205,7 +210,7 @@
}
public Map<String, String> getCopyrightsMapping() {
- return myModule2Copyrights;
+ return myModuleToCopyrights;
}
public void setDefaultCopyright(@Nullable CopyrightProfile copyright) {
@@ -223,8 +228,8 @@
public void removeCopyright(CopyrightProfile copyrightProfile) {
myCopyrights.values().remove(copyrightProfile);
- for (Iterator<String> it = myModule2Copyrights.keySet().iterator(); it.hasNext();) {
- final String profileName = myModule2Copyrights.get(it.next());
+ for (Iterator<String> it = myModuleToCopyrights.keySet().iterator(); it.hasNext();) {
+ final String profileName = myModuleToCopyrights.get(it.next());
if (profileName.equals(copyrightProfile.getName())) {
it.remove();
}
@@ -234,15 +239,15 @@
public void clearCopyrights() {
myDefaultCopyright = null;
myCopyrights.clear();
- myModule2Copyrights.clear();
+ myModuleToCopyrights.clear();
}
public void mapCopyright(String scopeName, String copyrightProfileName) {
- myModule2Copyrights.put(scopeName, copyrightProfileName);
+ myModuleToCopyrights.put(scopeName, copyrightProfileName);
}
public void unmapCopyright(String scopeName) {
- myModule2Copyrights.remove(scopeName);
+ myModuleToCopyrights.remove(scopeName);
}
public Collection<CopyrightProfile> getCopyrights() {
@@ -250,7 +255,7 @@
}
public boolean hasAnyCopyrights() {
- return myDefaultCopyright != null || !myModule2Copyrights.isEmpty();
+ return myDefaultCopyright != null || !myModuleToCopyrights.isEmpty();
}
@Nullable
@@ -258,13 +263,13 @@
final VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null || myOptions.getOptions(virtualFile.getFileType().getName()).getFileTypeOverride() == LanguageOptions.NO_COPYRIGHT) return null;
final DependencyValidationManager validationManager = DependencyValidationManager.getInstance(myProject);
- for (String scopeName : myModule2Copyrights.keySet()) {
+ for (String scopeName : myModuleToCopyrights.keySet()) {
final NamedScope namedScope = validationManager.getScope(scopeName);
if (namedScope != null) {
final PackageSet packageSet = namedScope.getValue();
if (packageSet != null) {
if (packageSet.contains(file, validationManager)) {
- final CopyrightProfile profile = myCopyrights.get(myModule2Copyrights.get(scopeName));
+ final CopyrightProfile profile = myCopyrights.get(myModuleToCopyrights.get(scopeName));
if (profile != null) {
return profile;
}
@@ -330,7 +335,7 @@
target.addContent(state);
}
for (Object attr : element.getAttributes()) {
- target.setAttribute((Attribute)((Attribute)attr).clone());
+ target.setAttribute(((Attribute)attr).clone());
}
}
}
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java
index 1c7c6ce..c6d274f 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/GenerateCopyrightAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -21,7 +21,6 @@
import com.intellij.openapi.module.Module;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
@@ -73,7 +72,7 @@
PsiFile file = getFile(context, project);
assert file != null;
if (CopyrightManager.getInstance(project).getCopyrightOptions(file) == null) {
- if (Messages.showOkCancelDialog(project, "No copyright configured for current file. Would you like to edit copyright settings?", "No Copyright Available", Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ if (Messages.showOkCancelDialog(project, "No copyright configured for current file. Would you like to edit copyright settings?", "No Copyright Available", Messages.getQuestionIcon()) == Messages.OK) {
ShowSettingsUtil.getInstance().showSettingsDialog(project, new CopyrightProjectConfigurable(project).getDisplayName());
} else {
return;
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/RecursionDlg.form b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/RecursionDlg.form
deleted file mode 100644
index c5d6d7a..0000000
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/RecursionDlg.form
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.maddyhome.idea.copyright.actions.RecursionDlg">
- <grid id="a340a" binding="mainPanel" row-count="3" column-count="2" hgap="-1" vgap="-1">
- <margin top="0" left="0" bottom="0" right="0"/>
- <constraints>
- <xy x="73" y="46" width="193" height="79"/>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="d3f2" class="javax.swing.JRadioButton" binding="rbFile">
- <constraints>
- <xy x="0" y="0" width="44" height="23"/>
- <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0"/>
- </constraints>
- <properties>
- <text value="File"/>
- </properties>
- </component>
- <component id="a6545" class="javax.swing.JRadioButton" binding="rbAll">
- <constraints>
- <xy x="0" y="28" width="39" height="23"/>
- <grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0"/>
- </constraints>
- <properties>
- <text value="All"/>
- </properties>
- </component>
- <component id="6e042" class="javax.swing.JCheckBox" binding="cbSubdirs">
- <constraints>
- <xy x="30" y="56" width="152" height="23"/>
- <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0"/>
- </constraints>
- <properties>
- <text value="Include subdirectories"/>
- </properties>
- </component>
- <component id="95da6" class="javax.swing.JLabel">
- <constraints>
- <xy x="0" y="60" width="4" height="15"/>
- <grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0"/>
- </constraints>
- <properties>
- <text value=" "/>
- </properties>
- </component>
- </children>
- </grid>
-</form>
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/RecursionDlg.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/RecursionDlg.java
deleted file mode 100644
index 3898c90..0000000
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/RecursionDlg.java
+++ /dev/null
@@ -1,190 +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.maddyhome.idea.copyright.actions;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectFileIndex;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.uiDesigner.core.GridConstraints;
-import com.intellij.uiDesigner.core.GridLayoutManager;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-
-public class RecursionDlg extends DialogWrapper
-{
- public RecursionDlg(Project project, VirtualFile file)
- {
- super(project, false);
-
- logger.debug("file=" + file);
-
- this.project = project;
- this.file = file;
-
- setupControls();
-
- init();
- }
-
- public boolean isAll()
- {
- return rbAll.isSelected();
- }
-
- public boolean includeSubdirs()
- {
- return cbSubdirs.isSelected();
- }
-
- private void setupControls()
- {
- setTitle("Update Copyright");
-
- setOKButtonText("Run");
-
- ButtonGroup group = new ButtonGroup();
- group.add(rbFile);
- group.add(rbAll);
-
- rbFile.setMnemonic('F');
- rbAll.setMnemonic('A');
- cbSubdirs.setMnemonic('I');
-
- if (file.isDirectory())
- {
- rbFile.setText("File");
- rbFile.setEnabled(false);
- rbAll.setText("All files in " + file.getPresentableUrl());
- rbAll.setSelected(true);
- cbSubdirs.setSelected(true);
- cbSubdirs.setEnabled(true);
- }
- else
- {
- VirtualFile parent = file.getParent();
- rbFile.setText("File '" + file.getPresentableUrl() + '\'');
- rbFile.setSelected(true);
- if (parent != null)
- {
- rbAll.setText("All files in " + parent.getPresentableUrl());
- cbSubdirs.setSelected(true);
- cbSubdirs.setEnabled(false);
- }
- else
- {
- rbAll.setVisible(false);
- cbSubdirs.setVisible(false);
- }
- }
-
- VirtualFile check = file;
- if (!file.isDirectory())
- {
- check = file.getParent();
- }
- ProjectRootManager prm = ProjectRootManager.getInstance(project);
- ProjectFileIndex pfi = prm.getFileIndex();
-
- VirtualFile[] children = check != null ? check.getChildren() : VirtualFile.EMPTY_ARRAY;
- boolean hasSubdirs = false;
- for (int i = 0; i < children.length && !hasSubdirs; i++)
- {
- if (children[i].isDirectory() && !pfi.isIgnored(children[i]))
- {
- hasSubdirs = true;
- }
- }
-
- cbSubdirs.setVisible(hasSubdirs);
- if (!hasSubdirs)
- {
- cbSubdirs.setEnabled(false);
- mainPanel.remove(cbSubdirs);
- }
-
- ActionListener listener = new ActionListener()
- {
- public void actionPerformed(ActionEvent e)
- {
- if (cbSubdirs.isVisible())
- {
- cbSubdirs.setEnabled(rbAll.isSelected());
- }
- }
- };
-
- rbFile.addActionListener(listener);
- rbAll.addActionListener(listener);
- }
-
- protected JComponent createCenterPanel()
- {
- return mainPanel;
- }
-
- {
-// GUI initializer generated by IntelliJ IDEA GUI Designer
-// >>> IMPORTANT!! <<<
-// DO NOT EDIT OR ADD ANY CODE HERE!
- $$$setupUI$$$();
- }
-
- /**
- * Method generated by IntelliJ IDEA GUI Designer >>> IMPORTANT!! <<< DO NOT edit this method OR call it in your
- * code!
- */
- private void $$$setupUI$$$()
- {
- mainPanel = new JPanel();
- mainPanel.setLayout(new GridLayoutManager(3, 2, new Insets(0, 0, 0, 0), -1, -1));
- rbFile = new JRadioButton();
- rbFile.setText("File");
- mainPanel.add(rbFile, new GridConstraints(0, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
- GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
- GridConstraints.SIZEPOLICY_FIXED, null, null, null));
- rbAll = new JRadioButton();
- rbAll.setText("All");
- mainPanel.add(rbAll, new GridConstraints(1, 0, 1, 2, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
- GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
- GridConstraints.SIZEPOLICY_FIXED, null, null, null));
- cbSubdirs = new JCheckBox();
- cbSubdirs.setText("Include subdirectories");
- mainPanel.add(cbSubdirs, new GridConstraints(2, 1, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
- GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
- GridConstraints.SIZEPOLICY_FIXED, null, null, null));
- final JLabel label1 = new JLabel();
- label1.setText(" ");
- mainPanel.add(label1, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
- GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null));
- }
-
- private final VirtualFile file;
- private JPanel mainPanel;
- private JRadioButton rbFile;
- private JRadioButton rbAll;
- private JCheckBox cbSubdirs;
- private final Project project;
-
- private static final Logger logger = Logger.getInstance(RecursionDlg.class.getName());
-
-}
\ No newline at end of file
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java
index db01018..a372331 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightAction.java
@@ -16,21 +16,24 @@
package com.maddyhome.idea.copyright.actions;
+import com.intellij.analysis.AnalysisScope;
+import com.intellij.analysis.BaseAnalysisAction;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
-import com.intellij.psi.util.PsiUtilCore;
import com.maddyhome.idea.copyright.CopyrightManager;
import com.maddyhome.idea.copyright.pattern.FileUtil;
import com.maddyhome.idea.copyright.util.FileTypeUtil;
+import org.jetbrains.annotations.NotNull;
-import java.util.ArrayList;
-import java.util.List;
+public class UpdateCopyrightAction extends BaseAnalysisAction {
+ protected UpdateCopyrightAction() {
+ super(UpdateCopyrightProcessor.TITLE, UpdateCopyrightProcessor.TITLE);
+ }
-public class UpdateCopyrightAction extends AnAction {
public void update(AnActionEvent event) {
final boolean enabled = isEnabled(event);
event.getPresentation().setEnabled(enabled);
@@ -94,79 +97,14 @@
return true;
}
- public void actionPerformed(AnActionEvent event) {
- final DataContext context = event.getDataContext();
- final Project project = CommonDataKeys.PROJECT.getData(context);
- assert project != null;
-
- final Module module = LangDataKeys.MODULE.getData(context);
- PsiDocumentManager.getInstance(project).commitAllDocuments();
-
- final VirtualFile[] files = CommonDataKeys.VIRTUAL_FILE_ARRAY.getData(context);
- final Editor editor = CommonDataKeys.EDITOR.getData(context);
-
- PsiFile file = null;
- PsiDirectory dir;
- if (editor != null) {
- file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
- if (file == null) {
- return;
+ @Override
+ protected void analyze(@NotNull final Project project, @NotNull AnalysisScope scope) {
+ if (scope.checkScopeWritable(project)) return;
+ scope.accept(new PsiElementVisitor() {
+ @Override
+ public void visitFile(PsiFile file) {
+ new UpdateCopyrightProcessor(project, ModuleUtilCore.findModuleForPsiElement(file), file).run();
}
- dir = file.getContainingDirectory();
- }
- else {
- if (FileUtil.areFiles(files)) {
- new UpdateCopyrightProcessor(project, null, FileUtil.convertToPsiFiles(files, project)).run();
- return;
- }
- final Module modCtx = LangDataKeys.MODULE_CONTEXT.getData(context);
- if (modCtx != null) {
- new UpdateCopyrightProcessor(project, module).run();
- return;
- }
-
- final Module[] modules = LangDataKeys.MODULE_CONTEXT_ARRAY.getData(context);
- if (modules != null && modules.length > 0) {
- List<PsiFile> psiFiles = new ArrayList<PsiFile>();
- for (Module mod : modules) {
- AbstractFileProcessor.findFiles(mod, psiFiles);
- }
- new UpdateCopyrightProcessor(project, null, PsiUtilCore.toPsiFileArray(psiFiles)).run();
- return;
- }
-
- final PsiElement psielement = CommonDataKeys.PSI_ELEMENT.getData(context);
- if (psielement == null) {
- return;
- }
-
- if (psielement instanceof PsiDirectoryContainer) {
- dir = ((PsiDirectoryContainer)psielement).getDirectories()[0];
- }
- else if (psielement instanceof PsiDirectory) {
- dir = (PsiDirectory)psielement;
- }
- else {
- file = psielement.getContainingFile();
- if (file == null) {
- return;
- }
- dir = file.getContainingDirectory();
- }
- }
-
- final RecursionDlg recDlg = new RecursionDlg(project, file != null ? file.getVirtualFile() : dir.getVirtualFile());
- recDlg.show();
- if (!recDlg.isOK()) {
- return;
- }
-
- if (recDlg.isAll()) {
- new UpdateCopyrightProcessor(project, module, dir, recDlg.includeSubdirs()).run();
- }
- else {
- new UpdateCopyrightProcessor(project, module, file).run();
- }
+ });
}
-
}
\ No newline at end of file
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java
index 513b862..dceefc6 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/actions/UpdateCopyrightProcessor.java
@@ -35,6 +35,9 @@
public class UpdateCopyrightProcessor extends AbstractFileProcessor
{
+ public static final String TITLE = "Update Copyright";
+ public static final String MESSAGE = "Updating copyrights...";
+
public UpdateCopyrightProcessor(Project project, Module module)
{
super(project, module, TITLE, MESSAGE);
@@ -115,8 +118,5 @@
private Project project;
private Module module;
- private static final String TITLE = "Update Copyright";
- private static final String MESSAGE = "Updating copyrights...";
-
private static final Logger logger = Logger.getInstance(UpdateCopyrightProcessor.class.getName());
}
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java b/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java
index 501fa0b..5df860e 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/options/LanguageOptions.java
@@ -16,10 +16,13 @@
package com.maddyhome.idea.copyright.options;
-import com.intellij.openapi.util.*;
+import com.intellij.openapi.util.DefaultJDOMExternalizer;
+import com.intellij.openapi.util.DifferenceFilter;
+import com.intellij.openapi.util.InvalidDataException;
+import com.intellij.openapi.util.WriteExternalException;
import org.jdom.Element;
-public class LanguageOptions implements JDOMExternalizable, Cloneable {
+public class LanguageOptions implements Cloneable {
public static final int NO_COPYRIGHT = 1;
public static final int USE_TEMPLATE = 2;
public static final int USE_TEXT = 3;
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/options/Options.java b/plugins/copyright/src/com/maddyhome/idea/copyright/options/Options.java
index 35722e9..8ca3c76 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/options/Options.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/options/Options.java
@@ -20,7 +20,6 @@
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.util.InvalidDataException;
-import com.intellij.openapi.util.JDOMExternalizable;
import com.intellij.openapi.util.WriteExternalException;
import com.maddyhome.idea.copyright.CopyrightUpdaters;
import com.maddyhome.idea.copyright.psi.UpdateCopyrightsProvider;
@@ -34,196 +33,161 @@
/**
*/
-public class Options implements JDOMExternalizable, Cloneable
-{
- public LanguageOptions getOptions(String name)
- {
- String lang = FileTypeUtil.getInstance().getFileTypeNameByName(name);
- LanguageOptions res = options.get(lang);
- if (res == null)
- {
- // NOTE: If any change is made here you need to update ConfigTabFactory and UpdateCopyrightFactory too.
- final FileType fileType = FileTypeUtil.getInstance().getFileTypeByName(name);
- if (fileType != null) {
- final UpdateCopyrightsProvider provider = CopyrightUpdaters.INSTANCE.forFileType(fileType);
- if (provider != null) return provider.getDefaultOptions();
+public class Options implements Cloneable {
+ public LanguageOptions getOptions(String name) {
+ String lang = FileTypeUtil.getInstance().getFileTypeNameByName(name);
+ LanguageOptions res = options.get(lang);
+ if (res == null) {
+ // NOTE: If any change is made here you need to update ConfigTabFactory and UpdateCopyrightFactory too.
+ final FileType fileType = FileTypeUtil.getInstance().getFileTypeByName(name);
+ if (fileType != null) {
+ final UpdateCopyrightsProvider provider = CopyrightUpdaters.INSTANCE.forFileType(fileType);
+ if (provider != null) return provider.getDefaultOptions();
+ }
+ res = new LanguageOptions();
+ }
+
+ return res;
+ }
+
+ public LanguageOptions getTemplateOptions() {
+ return getOptions(LANG_TEMPLATE);
+ }
+
+ public void setOptions(String name, LanguageOptions options) {
+ String lang = FileTypeUtil.getInstance().getFileTypeNameByName(name);
+ this.options.put(lang, options);
+ }
+
+ public void setTemplateOptions(LanguageOptions options) {
+ setOptions(LANG_TEMPLATE, options);
+ }
+
+ @Nullable
+ public LanguageOptions getMergedOptions(String name) {
+ try {
+ LanguageOptions lang = getOptions(name).clone();
+ LanguageOptions temp = getTemplateOptions().clone();
+ switch (lang.getFileTypeOverride()) {
+ case LanguageOptions.USE_TEMPLATE:
+ temp.setFileLocation(lang.getFileLocation());
+ temp.setFileTypeOverride(lang.getFileTypeOverride());
+ lang = temp;
+ break;
+ case LanguageOptions.USE_TEXT:
+ break;
+ }
+
+ return lang;
+ }
+ catch (CloneNotSupportedException e) {
+ // This shouldn't happen
+ }
+
+ return null;
+ }
+
+
+ public void readExternal(Element element) throws InvalidDataException {
+ logger.debug("readExternal()");
+ List<Element> languageOptions = element.getChildren("LanguageOptions");
+ if (languageOptions != null && !languageOptions.isEmpty()) {
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0; i < languageOptions.size(); i++) {
+ Element languageOption = languageOptions.get(i);
+ // NOTE: If any change is made here you need to update ConfigTabFactory and UpdateCopyrightFactory too.
+ LanguageOptions opts = new LanguageOptions();
+ opts.readExternal(languageOption);
+ setOptions(languageOption.getAttributeValue("name"), opts);
+ }
+ }
+ else {
+ Element root = null;
+ Element jOpts = element.getChild("JavaOptions");
+ if (jOpts != null) // version 2.1.x
+ {
+ root = jOpts;
+ }
+ else // versions 0.0.1 - 2.0.x
+ {
+ Element child = element.getChild("option");
+ if (child != null && child.getAttribute("name") != null) {
+ root = element;
+ }
+ }
+ if (root != null) {
+ String languageName = StdFileTypes.JAVA.getName();
+ // NOTE: If any change is made here you need to update ConfigTabFactory and UpdateCopyrightFactory too.
+ LanguageOptions opts = new LanguageOptions();
+ opts.setFileTypeOverride(LanguageOptions.USE_TEMPLATE);
+ for (Object option : root.getChildren("option")) {
+ String name = ((Element)option).getAttributeValue("name");
+ String val = ((Element)option).getAttributeValue("value");
+ if ("body".equals(name)) {
+ //todo opts.setNotice(val);
}
- res = new LanguageOptions();
+ else if ("location".equals(name)) {
+ opts.setFileLocation(Integer.parseInt(val));
+ }
}
- return res;
+ setOptions(languageName, opts);
+ }
}
- public LanguageOptions getTemplateOptions()
- {
- return getOptions(LANG_TEMPLATE);
+ logger.debug("options=" + this);
+ }
+
+ public void writeExternal(Element element) throws WriteExternalException {
+ logger.debug("writeExternal()");
+
+ for (String lang : options.keySet()) {
+ Element elem = new Element("LanguageOptions");
+ elem.setAttribute("name", lang);
+ element.addContent(elem);
+ options.get(lang).writeExternal(elem);
}
- public void setOptions(String name, LanguageOptions options)
- {
- String lang = FileTypeUtil.getInstance().getFileTypeNameByName(name);
- this.options.put(lang, options);
+ logger.debug("options=" + this);
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
}
- public void setTemplateOptions(LanguageOptions options)
- {
- setOptions(LANG_TEMPLATE, options);
+ final Options options1 = (Options)o;
+
+ return options.equals(options1.options);
+ }
+
+ public int hashCode() {
+ int result;
+ result = options.hashCode();
+ return result;
+ }
+
+ public String toString() {
+ return "Options" + "{options=" + options + '}';
+ }
+
+ @Override
+ public Options clone() throws CloneNotSupportedException {
+ Options res = (Options)super.clone();
+ res.options = new TreeMap<String, LanguageOptions>();
+ for (String lang : options.keySet()) {
+ LanguageOptions opts = options.get(lang);
+ res.options.put(lang, opts.clone());
}
- @Nullable
- public LanguageOptions getMergedOptions(String name)
- {
- try
- {
- LanguageOptions lang = getOptions(name).clone();
- LanguageOptions temp = getTemplateOptions().clone();
- switch (lang.getFileTypeOverride()){
- case LanguageOptions.USE_TEMPLATE:
- temp.setFileLocation(lang.getFileLocation());
- temp.setFileTypeOverride(lang.getFileTypeOverride());
- lang = temp;
- break;
- case LanguageOptions.USE_TEXT:
- break;
- }
+ return res;
+ }
- return lang;
- }
- catch (CloneNotSupportedException e)
- {
- // This shouldn't happen
- }
+ private Map<String, LanguageOptions> options = new TreeMap<String, LanguageOptions>();
+ private static final String LANG_TEMPLATE = "__TEMPLATE__";
- return null;
- }
-
-
- public void readExternal(Element element) throws InvalidDataException
- {
- logger.debug("readExternal()");
- List langs = element.getChildren("LanguageOptions");
- if (langs != null && langs.size() > 0)
- {
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0; i < langs.size(); i++)
- {
- Element lang = (Element)langs.get(i);
- String name = lang.getAttributeValue("name");
- // NOTE: If any change is made here you need to update ConfigTabFactory and UpdateCopyrightFactory too.
- LanguageOptions opts = new LanguageOptions();
- opts.readExternal(lang);
-
- setOptions(name, opts);
- }
- }
- else
- {
- Element root = null;
- Element jOpts = element.getChild("JavaOptions");
- if (jOpts != null) // version 2.1.x
- {
- root = jOpts;
- }
- else // versions 0.0.1 - 2.0.x
- {
- Element child = element.getChild("option");
- if (child != null && child.getAttribute("name") != null)
- {
- root = element;
- }
- }
- if (root != null)
- {
- String lname = StdFileTypes.JAVA.getName();
- // NOTE: If any change is made here you need to update ConfigTabFactory and UpdateCopyrightFactory too.
- LanguageOptions opts = new LanguageOptions();
- opts.setFileTypeOverride(LanguageOptions.USE_TEMPLATE);
- List children = root.getChildren("option");
- for (Object option : children)
- {
- String name = ((Element)option).getAttributeValue("name");
- String val = ((Element)option).getAttributeValue("value");
- if ("body".equals(name))
- {
- //todo opts.setNotice(val);
- }
- else if ("location".equals(name))
- {
- opts.setFileLocation(Integer.parseInt(val));
- }
- }
-
- setOptions(lname, opts);
- }
- }
-
- logger.debug("options=" + this);
- }
-
- public void writeExternal(Element element) throws WriteExternalException
- {
- logger.debug("writeExternal()");
-
- for (String lang : options.keySet())
- {
- LanguageOptions opts = options.get(lang);
-
- Element elem = new Element("LanguageOptions");
- elem.setAttribute("name", lang);
- element.addContent(elem);
- opts.writeExternal(elem);
- }
-
- logger.debug("options=" + this);
- }
-
- public boolean equals(Object o)
- {
- if (this == o)
- {
- return true;
- }
- if (o == null || getClass() != o.getClass())
- {
- return false;
- }
-
- final Options options1 = (Options)o;
-
- return options.equals(options1.options);
- }
-
- public int hashCode()
- {
- int result;
- result = options.hashCode();
- return result;
- }
-
- public String toString()
- {
- final StringBuffer sb = new StringBuffer();
- sb.append("Options");
- sb.append("{options=").append(options);
- sb.append('}');
- return sb.toString();
- }
-
- public Options clone() throws CloneNotSupportedException
- {
- Options res = (Options)super.clone();
- res.options = new TreeMap<String, LanguageOptions>();
- for (String lang : options.keySet())
- {
- LanguageOptions opts = options.get(lang);
- res.options.put(lang, opts.clone());
- }
-
- return res;
- }
-
- private Map<String, LanguageOptions> options = new TreeMap<String, LanguageOptions>();
- private static final String LANG_TEMPLATE = "__TEMPLATE__";
-
- private static final Logger logger = Logger.getInstance(Options.class.getName());
+ private static final Logger logger = Logger.getInstance(Options.class.getName());
}
\ No newline at end of file
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdateJavaScriptFileCopyright.java b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdateJavaScriptFileCopyright.java
index ce66457..1990bd0 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdateJavaScriptFileCopyright.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdateJavaScriptFileCopyright.java
@@ -34,6 +34,12 @@
protected void scanFile()
{
PsiElement first = getFile().getFirstChild();
+ if (first != null) {
+ final PsiElement child = first.getFirstChild();
+ if (child instanceof PsiComment) {
+ first = child;
+ }
+ }
PsiElement last = first;
PsiElement next = first;
while (next != null)
diff --git a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java
index 66ea6e3..fa7f346 100644
--- a/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java
+++ b/plugins/copyright/src/com/maddyhome/idea/copyright/psi/UpdatePsiFileCopyright.java
@@ -18,8 +18,7 @@
import com.intellij.lang.Commenter;
import com.intellij.lang.LanguageCommenters;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -317,10 +316,9 @@
}
protected void processActions() throws IncorrectOperationException {
- Application app = ApplicationManager.getApplication();
- app.runWriteAction(new Runnable() {
+ new WriteCommandAction.Simple(file.getProject(), "Update copyright") {
@Override
- public void run() {
+ protected void run() throws Throwable {
Document doc = FileDocumentManager.getInstance().getDocument(getRoot());
if (doc != null) {
PsiDocumentManager.getInstance(file.getProject()).doPostponedOperationsAndUnblockDocument(doc);
@@ -343,10 +341,10 @@
break;
}
}
- PsiDocumentManager.getInstance(file.getProject()).commitDocument(doc);
+ PsiDocumentManager.getInstance(getProject()).commitDocument(doc);
}
}
- });
+ }.execute();
}
private static class CommentRange {
diff --git a/plugins/cvs/cvs-core/src/com/intellij/CvsBundle.java b/plugins/cvs/cvs-core/src/com/intellij/CvsBundle.java
index 21ada03..f5a71b7 100644
--- a/plugins/cvs/cvs-core/src/com/intellij/CvsBundle.java
+++ b/plugins/cvs/cvs-core/src/com/intellij/CvsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -13,7 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package com.intellij;import org.jetbrains.annotations.NonNls;
+package com.intellij;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -21,8 +24,12 @@
import java.util.ResourceBundle;
public class CvsBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE_NAME) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE_NAME = "com.intellij.cvsSupport2.CvsBundle";
private CvsBundle() {
@@ -64,13 +71,8 @@
return message("operation.name.annotate");
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE_NAME)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE_NAME);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/UneditAction.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/UneditAction.java
index cddaa1e..f88f18b 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/UneditAction.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/actions/UneditAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -51,7 +51,7 @@
else {
message = CvsBundle.message("unedit.confirmation.multiple", modifiedFiles);
}
- if (Messages.showOkCancelDialog(context.getProject(), message, CvsBundle.message("unedit.confirmation.title"), Messages.getQuestionIcon()) != 0) {
+ if (Messages.showOkCancelDialog(context.getProject(), message, CvsBundle.message("unedit.confirmation.title"), Messages.getQuestionIcon()) != Messages.OK) {
return;
}
}
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsConfigurationPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsConfigurationPanel.java
index 3b473e7..62c1037 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsConfigurationPanel.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/config/ui/CvsConfigurationPanel.java
@@ -25,6 +25,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -79,7 +80,7 @@
return text;
}
- public void setText(JTextField textField, String text) {
+ public void setText(JTextField textField, @NotNull String text) {
textField.setText(text);
}
});
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/ui/PServerSettingsPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/ui/PServerSettingsPanel.java
index fdc57c3..fc6900d 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/ui/PServerSettingsPanel.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/connections/pserver/ui/PServerSettingsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -61,7 +61,7 @@
if (!passwordFile.exists()) {
final int result = Messages.showYesNoDialog(myPanel, CvsBundle.message("message.password.file.does.not.exist", pathToPasswordFile),
CvsBundle.message("title.password.file.does.not.exist"), Messages.getQuestionIcon());
- if (result == 1) {
+ if (result == Messages.NO) {
throw new InputException(myPathToPasswordFile);
}
try {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CheckoutHelper.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CheckoutHelper.java
index 4724478..0acfc09 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CheckoutHelper.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsBrowser/CheckoutHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -62,7 +62,7 @@
File checkoutDirectory = new File(myCheckoutLocation, myElement.getCheckoutPath());
if (checkoutDirectory.isDirectory()) return true;
return Messages.showYesNoDialog(CvsBundle.message("confirmation.text.directory.will.be.created", checkoutDirectory),
- CvsBundle.message("operation.name.check.out.project"), Messages.getQuestionIcon()) == 0;
+ CvsBundle.message("operation.name.check.out.project"), Messages.getQuestionIcon()) == Messages.YES;
}
private boolean shouldCreateDirectoryOfTheSameName() {
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsAdd/ui/AddMultipleFilesOptionsDialog.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsAdd/ui/AddMultipleFilesOptionsDialog.java
index 6433b58..c60efc4 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsAdd/ui/AddMultipleFilesOptionsDialog.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsAdd/ui/AddMultipleFilesOptionsDialog.java
@@ -33,8 +33,8 @@
import com.intellij.ui.treeStructure.treetable.TreeTableModel;
import com.intellij.ui.treeStructure.treetable.TreeTableTree;
import com.intellij.util.ui.ColumnInfo;
-import com.intellij.util.ui.ComboBoxTableCellEditor;
import com.intellij.util.ui.ComboBoxTableCellRenderer;
+import com.intellij.util.ui.table.ComboBoxTableCellEditor;
import com.intellij.util.ui.tree.TreeUtil;
import org.netbeans.lib.cvsclient.command.KeywordSubstitution;
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/TagsPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/TagsPanel.java
index c01e1eb..0b91db6 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/TagsPanel.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsTagOrBranch/ui/TagsPanel.java
@@ -20,6 +20,7 @@
import com.intellij.ui.ClickListener;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.table.TableCellRenderer;
@@ -56,7 +57,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
showTags();
return true;
}
diff --git a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java
index 508eaf9..d8030c2 100644
--- a/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java
+++ b/plugins/cvs/cvs-plugin/src/com/intellij/cvsSupport2/cvsoperations/cvsUpdate/ui/UpdateOptionsPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -24,7 +24,6 @@
import com.intellij.openapi.options.CancelledConfigurationException;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vcs.FilePath;
@@ -135,7 +134,7 @@
if (myCleanCopy.isSelected()) {
if (Messages.showYesNoDialog(
CvsBundle.message("confirmation.clean.copy"),
- CvsBundle.message("confirmation.title.clean.copy"), Messages.getWarningIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ CvsBundle.message("confirmation.title.clean.copy"), Messages.getWarningIcon()) == Messages.YES) {
configuration.CLEAN_COPY = true;
} else {
throw new CancelledConfigurationException();
diff --git a/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/JavaCvsSrcBundle.java b/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/JavaCvsSrcBundle.java
index 69a9292..e983756 100644
--- a/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/JavaCvsSrcBundle.java
+++ b/plugins/cvs/javacvs-src/org/netbeans/lib/cvsclient/JavaCvsSrcBundle.java
@@ -1,10 +1,23 @@
/*
- * Copyright (c) 2005 JetBrains s.r.o. All Rights Reserved.
+ * 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.netbeans.lib.cvsclient;
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -15,20 +28,19 @@
* @author lesya
*/
public class JavaCvsSrcBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "org.netbeans.lib.cvsclient.JavaCvsSrcBundle";
private JavaCvsSrcBundle() {
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/cvs/smartcvs-src/org/netbeans/lib/cvsclient/SmartCvsSrcBundle.java b/plugins/cvs/smartcvs-src/org/netbeans/lib/cvsclient/SmartCvsSrcBundle.java
index f0c28fe..637a6f2 100644
--- a/plugins/cvs/smartcvs-src/org/netbeans/lib/cvsclient/SmartCvsSrcBundle.java
+++ b/plugins/cvs/smartcvs-src/org/netbeans/lib/cvsclient/SmartCvsSrcBundle.java
@@ -1,10 +1,23 @@
/*
- * Copyright (c) 2005 JetBrains s.r.o. All Rights Reserved.
+ * 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.netbeans.lib.cvsclient;
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -15,20 +28,19 @@
* @author lesya
*/
public class SmartCvsSrcBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "org.netbeans.lib.cvsclient.SmartCvsSrcBundle";
private SmartCvsSrcBundle() {
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/devkit/resources/META-INF/plugin.xml b/plugins/devkit/resources/META-INF/plugin.xml
index 8e26284..f9d1048 100644
--- a/plugins/devkit/resources/META-INF/plugin.xml
+++ b/plugins/devkit/resources/META-INF/plugin.xml
@@ -59,10 +59,6 @@
bundle="org.jetbrains.idea.devkit.DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.UseGrayInspection"/>
- <localInspection language="JAVA" shortName="UseJBColor" displayName="Use Darcula aware JBColor"
- bundle="org.jetbrains.idea.devkit.DevKitBundle"
- groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
- implementationClass="org.jetbrains.idea.devkit.inspections.UseJBColorInspection"/>
<localInspection language="JAVA" shortName="IntentionDescriptionNotFoundInspection" displayName="Intention Description Checker"
bundle="org.jetbrains.idea.devkit.DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
@@ -94,6 +90,32 @@
level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.ExtensionPointBeanClassInspection"/>
+ <localInspection language="JAVA" shortName="UndesirableClassUsage" displayName="Undesirable class usage"
+ bundle="org.jetbrains.idea.devkit.DevKitBundle"
+ groupKey="inspections.group.name"
+ enabledByDefault="true" level="WARNING"
+ implementationClass="org.jetbrains.idea.devkit.inspections.internal.UndesirableClassUsageInspection"/>
+ <localInspection language="JAVA" shortName="FileEqualsUsage" displayName="File.equals() usage"
+ bundle="org.jetbrains.idea.devkit.DevKitBundle"
+ groupKey="inspections.group.name"
+ enabledByDefault="true" level="WARNING"
+ implementationClass="org.jetbrains.idea.devkit.inspections.internal.FileEqualsUsageInspection"/>
+ <localInspection language="JAVA" shortName="GtkPreferredJComboBoxRenderer" displayName="Preferred JComboBox renderer"
+ bundle="org.jetbrains.idea.devkit.DevKitBundle"
+ groupKey="inspections.group.name"
+ enabledByDefault="true" level="WARNING"
+ implementationClass="org.jetbrains.idea.devkit.inspections.internal.GtkPreferredJComboBoxRendererInspection"/>
+ <localInspection language="JAVA" shortName="UnsafeVfsRecursion" displayName="Unsafe VFS recursion"
+ bundle="org.jetbrains.idea.devkit.DevKitBundle"
+ groupKey="inspections.group.name"
+ enabledByDefault="true" level="WARNING"
+ implementationClass="org.jetbrains.idea.devkit.inspections.internal.UnsafeVfsRecursionInspection"/>
+ <localInspection language="JAVA" shortName="UseJBColor" displayName="Use Darcula aware JBColor"
+ bundle="org.jetbrains.idea.devkit.DevKitBundle"
+ groupKey="inspections.group.name"
+ enabledByDefault="true" level="WARNING"
+ implementationClass="org.jetbrains.idea.devkit.inspections.internal.UseJBColorInspection"/>
+
<moduleConfigurationEditorProvider implementation="org.jetbrains.idea.devkit.module.PluginModuleEditorsProvider"/>
<implicitUsageProvider implementation="org.jetbrains.idea.devkit.inspections.DevKitImplicitUsageProvider"/>
<psi.referenceContributor implementation="org.jetbrains.idea.devkit.dom.impl.I18nReferenceContributor"/>
@@ -102,7 +124,6 @@
<unusedDeclarationFixProvider implementation="org.jetbrains.idea.devkit.inspections.quickfix.RegisterExtensionFixProvider"/>
<stacktrace.fold substring="at com.intellij.testFramework."/>
-
</extensions>
<module-components>
diff --git a/plugins/devkit/resources/add_sdk.png b/plugins/devkit/resources/add_sdk.png
index c73a93f..c04e559 100644
--- a/plugins/devkit/resources/add_sdk.png
+++ b/plugins/devkit/resources/add_sdk.png
Binary files differ
diff --git a/plugins/devkit/resources/add_sdk@2x.png b/plugins/devkit/resources/add_sdk@2x.png
index c717f66..c08b453 100644
--- a/plugins/devkit/resources/add_sdk@2x.png
+++ b/plugins/devkit/resources/add_sdk@2x.png
Binary files differ
diff --git a/plugins/devkit/resources/icons/DevkitIcons.java b/plugins/devkit/resources/icons/DevkitIcons.java
index 4cd009d..28437ac 100644
--- a/plugins/devkit/resources/icons/DevkitIcons.java
+++ b/plugins/devkit/resources/icons/DevkitIcons.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,5 @@
}
public static final Icon Add_sdk = load("/add_sdk.png"); // 16x16
- public static final Icon New_html = load("/new_html.png"); // 16x16
public static final Icon Sdk_closed = load("/sdk_closed.png"); // 16x16
- public static final Icon Sdk_open = load("/sdk_open.png"); // 16x16
}
diff --git a/plugins/devkit/resources/inspectionDescriptions/FileEqualsUsage.html b/plugins/devkit/resources/inspectionDescriptions/FileEqualsUsage.html
new file mode 100644
index 0000000..11e81ca
--- /dev/null
+++ b/plugins/devkit/resources/inspectionDescriptions/FileEqualsUsage.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+This inspection detects usages of File.equals/hashCode/compareTo methods - which do not honor case-insensitivity on Mac OS X.
+Please use FileUtil.filesEquals/fileHashCode/compareFiles methods instead.
+</body>
+</html>
diff --git a/plugins/devkit/resources/inspectionDescriptions/GtkPreferredJComboBoxRenderer.html b/plugins/devkit/resources/inspectionDescriptions/GtkPreferredJComboBoxRenderer.html
new file mode 100644
index 0000000..d3b71cf
--- /dev/null
+++ b/plugins/devkit/resources/inspectionDescriptions/GtkPreferredJComboBoxRenderer.html
@@ -0,0 +1,6 @@
+<html>
+<body>
+This inspection detects usages of DefaultListCellRenderer - which causes ugly UI under GTK+ L&F.
+Please use ListCellRendererWrapper (or its inheritors) instead.
+</body>
+</html>
diff --git a/plugins/devkit/resources/inspectionDescriptions/UndesirableClassUsage.html b/plugins/devkit/resources/inspectionDescriptions/UndesirableClassUsage.html
new file mode 100644
index 0000000..8523d3e
--- /dev/null
+++ b/plugins/devkit/resources/inspectionDescriptions/UndesirableClassUsage.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+This inspection detects usages of internally deprecated classes.
+</body>
+</html>
diff --git a/plugins/devkit/resources/inspectionDescriptions/UnsafeVfsRecursion.html b/plugins/devkit/resources/inspectionDescriptions/UnsafeVfsRecursion.html
new file mode 100644
index 0000000..89816f2
--- /dev/null
+++ b/plugins/devkit/resources/inspectionDescriptions/UnsafeVfsRecursion.html
@@ -0,0 +1,7 @@
+<html>
+<body>
+This inspection detects calls of VirtualFile.getChildren() inside recursive methods.
+Such code may cause dead loops when iterating over cyclic symlinks -
+so please use VfsUtilCore.visitChildrenRecursively() instead.
+</body>
+</html>
diff --git a/plugins/devkit/resources/new_html.png b/plugins/devkit/resources/new_html.png
deleted file mode 100644
index 12e6376..0000000
--- a/plugins/devkit/resources/new_html.png
+++ /dev/null
Binary files differ
diff --git a/plugins/devkit/resources/sdk_closed.png b/plugins/devkit/resources/sdk_closed.png
index 56dd0bd..7fa83e3 100644
--- a/plugins/devkit/resources/sdk_closed.png
+++ b/plugins/devkit/resources/sdk_closed.png
Binary files differ
diff --git a/plugins/devkit/resources/sdk_closed@2x.png b/plugins/devkit/resources/sdk_closed@2x.png
new file mode 100644
index 0000000..c056611
--- /dev/null
+++ b/plugins/devkit/resources/sdk_closed@2x.png
Binary files differ
diff --git a/plugins/devkit/resources/sdk_open.png b/plugins/devkit/resources/sdk_open.png
deleted file mode 100644
index 0e72923..0000000
--- a/plugins/devkit/resources/sdk_open.png
+++ /dev/null
Binary files differ
diff --git a/plugins/devkit/src/DevKitBundle.java b/plugins/devkit/src/DevKitBundle.java
index d507273..8dfec4b 100644
--- a/plugins/devkit/src/DevKitBundle.java
+++ b/plugins/devkit/src/DevKitBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* Date: Aug 11, 2005
*/
public class DevKitBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "org.jetbrains.idea.devkit.DevKitBundle";
private DevKitBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/devkit/src/DevKitBundle.properties b/plugins/devkit/src/DevKitBundle.properties
index 2085019..07d3b29 100644
--- a/plugins/devkit/src/DevKitBundle.properties
+++ b/plugins/devkit/src/DevKitBundle.properties
@@ -34,17 +34,17 @@
sandbox.specification=Please configure the sandbox
sandbox.home=Sandbox Home
sandbox.home.label=Sandbox Home:
-sandbox.no.configured=No sandbox specified for idea jdk
-sandbox.purpose=Browse folder to put config, system and plugins for target IDEA
+sandbox.no.configured=No sandbox specified for IntelliJ Platform Plugin SDK
+sandbox.purpose=Browse folder to put config, system and plugins for target IDE
#errors
error.occurred=Error Occurred
-jdk.no.specified=No jdk specified for plugin module ''{0}''
-jdk.type.incorrect=Wrong jdk type for plugin module ''{0}''.
-jdk.type.incorrect.common=Wrong jdk type for plugin module
+sdk.no.specified=No SDK specified for plugin module ''{0}''
+sdk.type.incorrect=Wrong SDK type for plugin module ''{0}''.
+sdk.type.incorrect.common=Wrong SDK type for plugin module
incorrect.dependency.non-plugin-module=The non-plugin module ''{0}'' cannot depend on plugin module ''{1}''.
incorrect.dependency.not-declared=The plugin module ''{0}'' doesn''t declare the dependency on ''{1}'' in its plugin.xml.
-error.file.not.found=File not found
+error.file.not.found=File not Found
error.file.not.found.message=File ''{0}'' not found
error.no.plugin.xml=No plugin.xml file found
error.plugin.xml.readonly=The plugin.xml file is read-only
@@ -65,7 +65,7 @@
action.MakeJarAction.text=Prepare To Deploy
action.MakeAllJarsAction.text=Prepare All Plugins To Deploy
-dont.add.idea.libs.to.classpath=IDEA-related libraries ({0}) must not be added to the module classpath. Please add them to the IDEA-JDK instead.
+dont.add.idea.libs.to.classpath=IDE-related libraries ({0}) must not be added to the module classpath. Please add them to the IntelliJ Platform Plugin SDK instead.
new.action.id=&Action ID:
new.action.description=&Description:
new.action.class.name=&Class Name:
@@ -151,8 +151,8 @@
ant.build.jar.comment=Build archive for plugin ''{0}''
ant.build.jar.description=Build plugin archive for module ''{0}''
project.title=Plugin Project
-no.java.sdk.for.idea.sdk.found=No Java SDK of appropriate version found. In addition to the IDEA Plugin SDK, you need to define a JDK with the same Java version ({0}).
-no.idea.sdk.version.found=Failed to detect JDK version required for IDEA Plugin SDK.
+no.java.sdk.for.idea.sdk.found=No Java SDK of appropriate version found. In addition to the IntelliJ Platform Plugin SDK, you need to define a JDK with the same Java version ({0}).
+no.idea.sdk.version.found=Failed to detect JDK version required for IntelliJ Platform Plugin SDK.
group.PluginDeployActions.text=Plugin Deployment Actions
error.cannot.resolve.plugin=Cannot resolve plugin {0}
diff --git a/plugins/devkit/src/actions/GeneratePluginClassAction.java b/plugins/devkit/src/actions/GeneratePluginClassAction.java
index 0853cc3..3fd6b69 100644
--- a/plugins/devkit/src/actions/GeneratePluginClassAction.java
+++ b/plugins/devkit/src/actions/GeneratePluginClassAction.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.
@@ -76,29 +76,29 @@
public void update(final AnActionEvent e) {
super.update(e);
+
final Presentation presentation = e.getPresentation();
if (presentation.isEnabled()) {
final DataContext context = e.getDataContext();
- Module module = LangDataKeys.MODULE.getData(context);
- if (module == null || !PluginModuleType.isPluginModuleOrDependency(module)) {
- presentation.setEnabled(false);
- presentation.setVisible(false);
- }
- final IdeView view = LangDataKeys.IDE_VIEW.getData(e.getDataContext());
- final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
- if (view != null && project != null) {
- // from com.intellij.ide.actions.CreateClassAction.update()
- ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
- PsiDirectory[] dirs = view.getDirectories();
- for (PsiDirectory dir : dirs) {
- if (projectFileIndex.isUnderSourceRootOfType(dir.getVirtualFile(), JavaModuleSourceRootTypes.SOURCES) && JavaDirectoryService.getInstance().getPackage(dir) != null) {
- return;
+ final Module module = LangDataKeys.MODULE.getData(context);
+ if (PluginModuleType.isPluginModuleOrDependency(module)) {
+ final IdeView view = LangDataKeys.IDE_VIEW.getData(e.getDataContext());
+ final Project project = CommonDataKeys.PROJECT.getData(e.getDataContext());
+ if (view != null && project != null) {
+ // from com.intellij.ide.actions.CreateClassAction.update()
+ ProjectFileIndex projectFileIndex = ProjectRootManager.getInstance(project).getFileIndex();
+ PsiDirectory[] dirs = view.getDirectories();
+ for (PsiDirectory dir : dirs) {
+ if (projectFileIndex.isUnderSourceRootOfType(dir.getVirtualFile(), JavaModuleSourceRootTypes.SOURCES) &&
+ JavaDirectoryService.getInstance().getPackage(dir) != null) {
+ return;
+ }
}
}
-
- presentation.setEnabled(false);
- presentation.setVisible(false);
}
+
+ presentation.setEnabled(false);
+ presentation.setVisible(false);
}
}
diff --git a/plugins/devkit/src/actions/ShowSerializedXmlAction.java b/plugins/devkit/src/actions/ShowSerializedXmlAction.java
index 9c53cac..8880424 100644
--- a/plugins/devkit/src/actions/ShowSerializedXmlAction.java
+++ b/plugins/devkit/src/actions/ShowSerializedXmlAction.java
@@ -19,8 +19,6 @@
import com.intellij.compiler.impl.FileSetCompileScope;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileStatusNotification;
import com.intellij.openapi.compiler.CompilerManager;
@@ -184,7 +182,7 @@
}
public Object createObject(Class<?> aClass, FList<Type> processedTypes) throws Exception {
- final Object o = aClass.newInstance();
+ final Object o = aClass.getDeclaredConstructor().newInstance();
for (Accessor accessor : XmlSerializerUtil.getAccessors(aClass)) {
final Type type = accessor.getGenericType();
Object value = createValue(type, processedTypes);
diff --git a/plugins/devkit/src/build/PluginBuildConfiguration.java b/plugins/devkit/src/build/PluginBuildConfiguration.java
index 5a34c45..5b5dc7b 100644
--- a/plugins/devkit/src/build/PluginBuildConfiguration.java
+++ b/plugins/devkit/src/build/PluginBuildConfiguration.java
@@ -27,7 +27,7 @@
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
@@ -91,12 +91,15 @@
}
url = element.getAttributeValue(MANIFEST_ATTR);
if (url != null) {
- setManifestPath(VfsUtil.urlToPath(url));
+ setManifestPath(VfsUtilCore.urlToPath(url));
}
}
public void writeExternal(Element element) throws WriteExternalException {
- element.setAttribute(URL_ATTR, getPluginXmlUrl());
+ final String url = getPluginXmlUrl();
+ if (url != null) {
+ element.setAttribute(URL_ATTR, url);
+ }
if (myManifestFilePointer != null){
element.setAttribute(MANIFEST_ATTR, myManifestFilePointer.getUrl());
}
@@ -135,14 +138,14 @@
if (url == null) {
return getDefaultLocation();
}
- return FileUtil.toSystemDependentName(VfsUtil.urlToPath(url));
+ return FileUtil.toSystemDependentName(VfsUtilCore.urlToPath(url));
}
public void setPluginXmlPathAndCreateDescriptorIfDoesntExist(final String pluginXmlPath) {
myPluginXmlContainer.getConfiguration().removeConfigFiles(PluginDescriptorConstants.META_DATA);
new WriteAction() {
protected void run(final Result result) throws Throwable {
- createDescriptor(VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(pluginXmlPath)));
+ createDescriptor(VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(pluginXmlPath)));
}
}.execute();
}
@@ -157,7 +160,8 @@
Messages.showErrorDialog(myModule.getProject(), DevKitBundle.message("error.file.not.found.message", manifestPath), DevKitBundle.message("error.file.not.found"));
ApplicationManager.getApplication().runReadAction(new Runnable() {
public void run() {
- myManifestFilePointer = VirtualFilePointerManager.getInstance().create(VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(manifestPath)), myModule, null);
+ myManifestFilePointer = VirtualFilePointerManager.getInstance().create(
+ VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(manifestPath)), myModule, null);
}
});
} else {
diff --git a/plugins/devkit/src/build/PluginBuildParticipant.java b/plugins/devkit/src/build/PluginBuildParticipant.java
index 174dd17..a599896 100644
--- a/plugins/devkit/src/build/PluginBuildParticipant.java
+++ b/plugins/devkit/src/build/PluginBuildParticipant.java
@@ -71,13 +71,13 @@
@Override
public Artifact createArtifact(CompileContext context) {
- Sdk jdk = IdeaJdk.findIdeaJdk(ModuleRootManager.getInstance(myModule).getSdk());
- if (jdk != null && IdeaJdk.isFromIDEAProject(jdk.getHomePath())) {
+ Sdk sdk = IdeaJdk.findIdeaJdk(ModuleRootManager.getInstance(myModule).getSdk());
+ if (sdk != null && IdeaJdk.isFromIDEAProject(sdk.getHomePath())) {
return null;
}
- if (jdk == null) {
- context.addMessage(CompilerMessageCategory.ERROR, DevKitBundle.message("jdk.type.incorrect", myModule.getName()), null, -1, -1);
+ if (sdk == null) {
+ context.addMessage(CompilerMessageCategory.ERROR, DevKitBundle.message("sdk.type.incorrect", myModule.getName()), null, -1, -1);
return null;
}
@@ -138,7 +138,7 @@
// libraries
- final VirtualFile libDir = jdk.getHomeDirectory().findFileByRelativePath(LIB_DIRECTORY);
+ final VirtualFile libDir = sdk.getHomeDirectory().findFileByRelativePath(LIB_DIRECTORY);
for (Library library : libs) {
boolean hasDirsOnly = true;
VirtualFile[] files = library.getFiles(OrderRootType.CLASSES);
diff --git a/plugins/devkit/src/build/PluginModuleBuildConfEditor.java b/plugins/devkit/src/build/PluginModuleBuildConfEditor.java
index 3e5a614..8ac3b4c 100644
--- a/plugins/devkit/src/build/PluginModuleBuildConfEditor.java
+++ b/plugins/devkit/src/build/PluginModuleBuildConfEditor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -21,7 +21,6 @@
import com.intellij.openapi.module.ModuleConfigurationEditor;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.roots.ui.configuration.ModuleConfigurationState;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
@@ -106,7 +105,7 @@
final String newPluginPath = myPluginXML.getText() + File.separator + META_INF + File.separator + PLUGIN_XML;
if (plugin.exists() && !plugin.getPath().equals(newPluginPath) &&
Messages.showYesNoDialog(myModule.getProject(), DevKitBundle.message("deployment.view.delete", plugin.getPath()),
- DevKitBundle.message("deployment.cleanup", META_INF), null) == DialogWrapper.OK_EXIT_CODE) {
+ DevKitBundle.message("deployment.cleanup", META_INF), null) == Messages.YES) {
CommandProcessor.getInstance().executeCommand(myModule.getProject(),
new Runnable() {
diff --git a/plugins/devkit/src/build/PrepareAllToDeployAction.java b/plugins/devkit/src/build/PrepareAllToDeployAction.java
index 9d26f3b..022123c 100644
--- a/plugins/devkit/src/build/PrepareAllToDeployAction.java
+++ b/plugins/devkit/src/build/PrepareAllToDeployAction.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,7 +20,6 @@
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ui.configuration.ChooseModulesDialog;
import org.jetbrains.idea.devkit.DevKitBundle;
@@ -37,7 +36,7 @@
List<Module> pluginModules = new ArrayList<Module>();
for (Module aModule : ModuleManager.getInstance(project).getModules()) {
- if (ModuleType.get(aModule) instanceof PluginModuleType) {
+ if (PluginModuleType.isOfType(aModule)) {
pluginModules.add(aModule);
}
}
@@ -57,7 +56,7 @@
final Project project = e.getData(CommonDataKeys.PROJECT);
if (project != null) {
for (Module aModule : (ModuleManager.getInstance(project).getModules())) {
- if (ModuleType.get(aModule) instanceof PluginModuleType) {
+ if (PluginModuleType.isOfType(aModule)) {
moduleCount++;
}
}
@@ -68,7 +67,7 @@
}
else if (moduleCount > 0) {
final Module module = e.getData(LangDataKeys.MODULE);
- if (module == null || !(ModuleType.get(module) instanceof PluginModuleType)) {
+ if (module == null || !(PluginModuleType.isOfType(module))) {
enabled = true;
}
}
diff --git a/plugins/devkit/src/build/PrepareToDeployAction.java b/plugins/devkit/src/build/PrepareToDeployAction.java
index 19399fd..b501331 100644
--- a/plugins/devkit/src/build/PrepareToDeployAction.java
+++ b/plugins/devkit/src/build/PrepareToDeployAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,6 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileStatusNotification;
@@ -29,14 +28,12 @@
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.CompilerModuleExtension;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -77,7 +74,7 @@
public void actionPerformed(final AnActionEvent e) {
final Module module = LangDataKeys.MODULE.getData(e.getDataContext());
- if (module != null && ModuleType.get(module) instanceof PluginModuleType) {
+ if (module != null && PluginModuleType.isOfType(module)) {
doPrepare(Arrays.asList(module), CommonDataKeys.PROJECT.getData(e.getDataContext()));
}
}
@@ -144,7 +141,7 @@
if (oldFile.exists()) {
if (Messages
.showYesNoDialog(module.getProject(), DevKitBundle.message("suggest.to.delete", oldPath), DevKitBundle.message("info.message"),
- Messages.getInformationIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getInformationIcon()) == Messages.YES) {
FileUtil.delete(oldFile);
}
}
@@ -400,7 +397,7 @@
public void update(AnActionEvent e) {
final Module module = LangDataKeys.MODULE.getData(e.getDataContext());
- boolean enabled = module != null && ModuleType.get(module) instanceof PluginModuleType;
+ boolean enabled = module != null && PluginModuleType.isOfType(module);
e.getPresentation().setVisible(enabled);
e.getPresentation().setEnabled(enabled);
if (enabled) {
diff --git a/plugins/devkit/src/dom/Action.java b/plugins/devkit/src/dom/Action.java
index be3d595..ac87914 100644
--- a/plugins/devkit/src/dom/Action.java
+++ b/plugins/devkit/src/dom/Action.java
@@ -80,7 +80,6 @@
@NotNull
GenericAttributeValue<String> getText();
-
/**
* Returns the value of the id child.
* Attribute id
@@ -90,6 +89,13 @@
@Required
GenericAttributeValue<String> getId();
+ ///**
+ // * Returns the value of the overrides child.
+ // * Attribute overrides
+ // * @return the value of the overrides child.
+ // */
+ //@NotNull
+ //GenericAttributeValue<Boolean> getOverrides();
/**
* Returns the list of keyboard-shortcut children.
diff --git a/plugins/devkit/src/dom/Group.java b/plugins/devkit/src/dom/Group.java
index c35c31f..5cf7a54 100644
--- a/plugins/devkit/src/dom/Group.java
+++ b/plugins/devkit/src/dom/Group.java
@@ -87,10 +87,22 @@
@NotNull
GenericAttributeValue<String> getText();
-
+ /**
+ * Returns the value of the id child.
+ * Attribute id
+ * @return the value of the id child.
+ */
@NotNull
GenericAttributeValue<String> getId();
+ ///**
+ // * Returns the value of the overrides child.
+ // * Attribute overrides
+ // * @return the value of the overrides child.
+ // */
+ //@NotNull
+ //GenericAttributeValue<Boolean> getOverrides();
+
/**
* Returns the list of reference children.
* @return the list of reference children.
diff --git a/plugins/devkit/src/dom/IdeaPlugin.java b/plugins/devkit/src/dom/IdeaPlugin.java
index d624be7..f1dae2f 100644
--- a/plugins/devkit/src/dom/IdeaPlugin.java
+++ b/plugins/devkit/src/dom/IdeaPlugin.java
@@ -117,10 +117,16 @@
@NotNull
- ApplicationComponents getApplicationComponents();
+ @SubTagList("application-components")
+ List<ApplicationComponents> getApplicationComponents();
+
+ ApplicationComponents addApplicationComponent();
@NotNull
- ProjectComponents getProjectComponents();
+ @SubTagList("project-components")
+ List<ProjectComponents> getProjectComponents();
+
+ ProjectComponents addProjectComponent();
@NotNull
ModuleComponents getModuleComponents();
diff --git a/plugins/devkit/src/dom/impl/ExtensionDomExtender.java b/plugins/devkit/src/dom/impl/ExtensionDomExtender.java
index a76c166..cbd6215 100644
--- a/plugins/devkit/src/dom/impl/ExtensionDomExtender.java
+++ b/plugins/devkit/src/dom/impl/ExtensionDomExtender.java
@@ -49,6 +49,7 @@
*/
public class ExtensionDomExtender extends DomExtender<Extensions> {
private static final PsiClassConverter CLASS_CONVERTER = new PluginPsiClassConverter();
+ private static final Converter LANGUAGE_CONVERTER = new LanguageResolvingConverter();
private static class MyRequired implements Required {
@Override
@@ -236,6 +237,9 @@
final DomExtension extension =
registrar.registerGenericAttributeValueChildExtension(new XmlName(attrName), clazz).setDeclaringElement(field);
markAsClass(extension, fieldName, withElement);
+ if (clazz.equals(String.class)) {
+ markAsLanguage(extension, fieldName);
+ }
}
return;
}
@@ -265,6 +269,12 @@
}
}
+ private static void markAsLanguage(DomExtension extension, String fieldName) {
+ if ("language".equals(fieldName)) {
+ extension.setConverter(LANGUAGE_CONVERTER);
+ }
+ }
+
private static void markAsClass(DomExtension extension, String fieldName, @Nullable With withElement) {
if (withElement != null) {
final String withClassName = withElement.getImplements().getStringValue();
@@ -275,7 +285,7 @@
}
});
}
- if (isClassField(fieldName) || withElement != null) {
+ if (withElement != null || isClassField(fieldName)) {
extension.setConverter(CLASS_CONVERTER);
}
}
diff --git a/plugins/devkit/src/dom/impl/IdeaPluginConverter.java b/plugins/devkit/src/dom/impl/IdeaPluginConverter.java
index 60f72ac..82b6b0d 100644
--- a/plugins/devkit/src/dom/impl/IdeaPluginConverter.java
+++ b/plugins/devkit/src/dom/impl/IdeaPluginConverter.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,7 +22,6 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.search.GlobalSearchScopesCore;
import com.intellij.util.Function;
-import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.ConvertContext;
import com.intellij.util.xml.DomFileElement;
@@ -35,6 +34,7 @@
import org.jetbrains.idea.devkit.DevKitBundle;
import org.jetbrains.idea.devkit.dom.IdeaPlugin;
import org.jetbrains.idea.devkit.dom.PluginModule;
+import org.jetbrains.idea.devkit.util.PsiUtil;
import java.util.Collection;
import java.util.Collections;
@@ -108,7 +108,7 @@
public static Collection<IdeaPlugin> getAllPlugins(final Project project) {
if (DumbService.isDumb(project)) return Collections.emptyList();
- GlobalSearchScope scope = PlatformUtils.isIdeaProject(project) ?
+ GlobalSearchScope scope = PsiUtil.isIdeaProject(project) ?
GlobalSearchScopesCore.projectProductionScope(project) : GlobalSearchScope.allScope(project);
List<DomFileElement<IdeaPlugin>> files = DomService.getInstance().getFileElements(IdeaPlugin.class, project, scope);
return ContainerUtil.map(files, new Function<DomFileElement<IdeaPlugin>, IdeaPlugin>() {
diff --git a/plugins/devkit/src/dom/impl/InternalDomExtender.java b/plugins/devkit/src/dom/impl/InternalDomExtender.java
index a41dd53..d982390 100644
--- a/plugins/devkit/src/dom/impl/InternalDomExtender.java
+++ b/plugins/devkit/src/dom/impl/InternalDomExtender.java
@@ -36,6 +36,8 @@
registrar.registerGenericAttributeValueChildExtension(new XmlName("internal"), clazz)
.setConverter(BooleanValueConverter.getInstance(false));
+ registrar.registerGenericAttributeValueChildExtension(new XmlName("overrides"), clazz)
+ .setConverter(BooleanValueConverter.getInstance(false));
}
public static class ForAction extends DomExtender<Action> {
@@ -49,6 +51,8 @@
@Override
public void registerExtensions(@NotNull Group group, @NotNull DomExtensionsRegistrar registrar) {
addInternalAttribute(registrar, Group.class);
+ registrar.registerGenericAttributeValueChildExtension(new XmlName("keep-content"), Group.class)
+ .setConverter(BooleanValueConverter.getInstance(false));
}
}
}
diff --git a/plugins/devkit/src/dom/impl/LanguageResolvingConverter.java b/plugins/devkit/src/dom/impl/LanguageResolvingConverter.java
new file mode 100644
index 0000000..da1fb72
--- /dev/null
+++ b/plugins/devkit/src/dom/impl/LanguageResolvingConverter.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.devkit.dom.impl;
+
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.openapi.util.Condition;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xml.ConvertContext;
+import com.intellij.util.xml.ResolvingConverter;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+class LanguageResolvingConverter extends ResolvingConverter<LanguageResolvingUtil.LanguageDefinition> {
+
+ @NotNull
+ @Override
+ public Collection<LanguageResolvingUtil.LanguageDefinition> getVariants(final ConvertContext context) {
+ return LanguageResolvingUtil.getAllLanguageDefinitions(context);
+ }
+
+ @Nullable
+ @Override
+ public LookupElement createLookupElement(LanguageResolvingUtil.LanguageDefinition o) {
+ return LookupElementBuilder.create(o.clazz, o.id)
+ .withIcon(o.icon)
+ .withTailText(o.displayName == null ? null : " (" + o.displayName + ")")
+ .withTypeText(o.clazz.getQualifiedName(), true);
+ }
+
+ @Nullable
+ @Override
+ public LanguageResolvingUtil.LanguageDefinition fromString(@Nullable @NonNls final String s, ConvertContext context) {
+ return ContainerUtil.find(getVariants(context), new Condition<LanguageResolvingUtil.LanguageDefinition>() {
+ @Override
+ public boolean value(LanguageResolvingUtil.LanguageDefinition definition) {
+ return definition.id.equals(s);
+ }
+ });
+ }
+
+ @Nullable
+ @Override
+ public String toString(@Nullable LanguageResolvingUtil.LanguageDefinition o, ConvertContext context) {
+ return o != null ? o.id : null;
+ }
+
+ @Override
+ public String getErrorMessage(@Nullable String s, ConvertContext context) {
+ return "Cannot resolve language with id ''" + s + "''";
+ }
+}
diff --git a/plugins/devkit/src/dom/impl/LanguageResolvingUtil.java b/plugins/devkit/src/dom/impl/LanguageResolvingUtil.java
new file mode 100644
index 0000000..acb0dbf
--- /dev/null
+++ b/plugins/devkit/src/dom/impl/LanguageResolvingUtil.java
@@ -0,0 +1,265 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.devkit.dom.impl;
+
+import com.intellij.codeInsight.completion.CompletionContributorEP;
+import com.intellij.icons.AllIcons;
+import com.intellij.lang.DependentLanguage;
+import com.intellij.lang.Language;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScopesCore;
+import com.intellij.psi.search.ProjectScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xml.ConvertContext;
+import com.intellij.util.xml.DomJavaUtil;
+import com.intellij.util.xml.GenericAttributeValue;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.devkit.dom.Extension;
+import org.jetbrains.idea.devkit.dom.ExtensionPoint;
+
+import javax.swing.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+class LanguageResolvingUtil {
+
+ private static final String ANY_LANGUAGE_DEFAULT_ID = Language.ANY.getID();
+
+ static Collection<LanguageDefinition> getAllLanguageDefinitions(ConvertContext context) {
+ List<LanguageDefinition> languageDefinitions = collectLanguageDefinitions(context);
+ ContainerUtil.addIfNotNull(languageDefinitions, createAnyLanguageDefinition(context));
+ return languageDefinitions;
+ }
+
+ private static List<LanguageDefinition> collectLanguageDefinitions(final ConvertContext context) {
+ final PsiClass languageClass = DomJavaUtil.findClass(Language.class.getName(), context.getInvocationElement());
+ if (languageClass == null) {
+ return Collections.emptyList();
+ }
+
+ final Project project = context.getProject();
+ final GlobalSearchScope projectProductionScope = GlobalSearchScopesCore.projectProductionScope(project);
+ GlobalSearchScope allScope = projectProductionScope.union(ProjectScope.getLibrariesScope(project));
+ final Collection<PsiClass> allLanguages = ClassInheritorsSearch.search(languageClass,
+ allScope, true).findAll();
+ final List<LanguageDefinition> libraryDefinitions = collectLibraryLanguages(context, allLanguages);
+
+ final Collection<PsiClass> projectLanguages = ClassInheritorsSearch.search(languageClass,
+ projectProductionScope, true).findAll();
+ final List<LanguageDefinition> projectDefinitions = collectProjectLanguages(projectLanguages, libraryDefinitions);
+
+ final List<LanguageDefinition> all = new ArrayList<LanguageDefinition>(libraryDefinitions);
+ all.addAll(projectDefinitions);
+ return all;
+ }
+
+ private static List<LanguageDefinition> collectLibraryLanguages(final ConvertContext context,
+ final Collection<PsiClass> allLanguages) {
+ return ContainerUtil.mapNotNull(Language.getRegisteredLanguages(), new NullableFunction<Language, LanguageDefinition>() {
+ @Override
+ public LanguageDefinition fun(Language language) {
+ if (language.getID().isEmpty() ||
+ language instanceof DependentLanguage) {
+ return null;
+ }
+ final PsiClass psiClass = DomJavaUtil.findClass(language.getClass().getName(), context.getInvocationElement());
+ if (psiClass == null) {
+ return null;
+ }
+
+ if (!allLanguages.contains(psiClass)) {
+ return null;
+ }
+
+ final LanguageFileType type = language.getAssociatedFileType();
+ final Icon icon = type != null ? type.getIcon() : null;
+ return new LanguageDefinition(language.getID(),
+ psiClass,
+ icon, language.getDisplayName());
+ }
+ });
+ }
+
+ private static List<LanguageDefinition> collectProjectLanguages(final Collection<PsiClass> projectLanguages,
+ final List<LanguageDefinition> libraryLanguages) {
+ return ContainerUtil.mapNotNull(projectLanguages, new NullableFunction<PsiClass, LanguageDefinition>() {
+ @Nullable
+ @Override
+ public LanguageDefinition fun(final PsiClass language) {
+ if (language.hasModifierProperty(PsiModifier.ABSTRACT)) {
+ return null;
+ }
+
+ if (ContainerUtil.exists(libraryLanguages, new Condition<LanguageDefinition>() {
+ @Override
+ public boolean value(LanguageDefinition definition) {
+ return definition.clazz.equals(language);
+ }
+ })) {
+ return null;
+ }
+
+ String id = computeConstantSuperCtorCallParameter(language, 0);
+ if (id == null) {
+ id = computeConstantSuperCtorCallParameter(language, 1);
+ }
+ if (id == null) {
+ id = computeConstantReturnValue(language, "getID");
+ }
+ if (id == null) {
+ return null;
+ }
+
+ return new LanguageDefinition(id,
+ language,
+ null,
+ computeConstantReturnValue(language, "getDisplayName"));
+ }
+ });
+ }
+
+ @Nullable
+ private static String computeConstantReturnValue(PsiClass languagePsiClass,
+ String methodName) {
+ final PsiMethod[] methods = languagePsiClass.findMethodsByName(methodName, false);
+ if (methods.length != 1) {
+ return null;
+ }
+
+ final PsiMethod method = methods[0];
+ final PsiCodeBlock body = method.getBody();
+
+ if (body == null) {
+ return null;
+ }
+ final PsiStatement[] statements = body.getStatements();
+ if (statements.length != 1) {
+ return null;
+ }
+
+
+ final PsiStatement statement = statements[0];
+ if (!(statement instanceof PsiReturnStatement)) {
+ return null;
+ }
+ final PsiReturnStatement returnStatement =
+ (PsiReturnStatement)statement;
+ final PsiExpression returnValue = returnStatement.getReturnValue();
+ if (returnValue == null ||
+ !PsiUtil.isConstantExpression(returnValue)) {
+ return null;
+ }
+
+ return computeConstant(languagePsiClass, returnValue);
+ }
+
+ private static String computeConstantSuperCtorCallParameter(PsiClass languagePsiClass, int index) {
+ PsiMethod defaultConstructor = null;
+ for (PsiMethod constructor : languagePsiClass.getConstructors()) {
+ if (constructor.getParameterList().getParametersCount() == 0) {
+ defaultConstructor = constructor;
+ break;
+ }
+ }
+ if (defaultConstructor == null) {
+ return null;
+ }
+
+ final PsiCodeBlock body = defaultConstructor.getBody();
+ if (body == null) {
+ return null;
+ }
+ final PsiStatement[] statements = body.getStatements();
+ if (statements.length < 1) {
+ return null;
+ }
+
+ // super() must be first
+ PsiStatement statement = statements[0];
+ if (!(statement instanceof PsiExpressionStatement)) {
+ return null;
+ }
+ PsiExpression expression = ((PsiExpressionStatement)statement).getExpression();
+ if (!(expression instanceof PsiMethodCallExpression)) {
+ return null;
+ }
+ PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
+ final PsiExpression[] argumentExpressions = methodCallExpression.getArgumentList().getExpressions();
+ if (argumentExpressions.length < index + 1) {
+ return null;
+ }
+ return computeConstant(languagePsiClass, argumentExpressions[index]);
+ }
+
+ private static String computeConstant(PsiClass languagePsiClass, PsiExpression returnValue) {
+ final PsiConstantEvaluationHelper constantEvaluationHelper =
+ JavaPsiFacade.getInstance(languagePsiClass.getProject()).getConstantEvaluationHelper();
+
+ final Object constant = constantEvaluationHelper.computeConstantExpression(returnValue);
+ return constant instanceof String ? ((String)constant) : null;
+ }
+
+ @Nullable
+ private static LanguageDefinition createAnyLanguageDefinition(ConvertContext context) {
+ final PsiClass languageClass = DomJavaUtil.findClass(Language.class.getName(), context.getInvocationElement());
+ if (languageClass == null) return null;
+
+ String anyLanguageId = calculateAnyLanguageId(context);
+ return new LanguageDefinition(anyLanguageId, languageClass, AllIcons.FileTypes.Any_type, "<any language>");
+ }
+
+ private static String calculateAnyLanguageId(ConvertContext context) {
+ final Extension extension = context.getInvocationElement().getParentOfType(Extension.class, true);
+ if (extension == null) {
+ return ANY_LANGUAGE_DEFAULT_ID;
+ }
+ final ExtensionPoint extensionPoint = extension.getExtensionPoint();
+ if (extensionPoint == null) {
+ return ANY_LANGUAGE_DEFAULT_ID;
+ }
+
+ final GenericAttributeValue<PsiClass> epBeanClass = extensionPoint.getBeanClass();
+ if (CompletionContributorEP.class.getName().equals(epBeanClass.getStringValue())) {
+ return "any";
+ }
+
+ return ANY_LANGUAGE_DEFAULT_ID;
+ }
+
+ static class LanguageDefinition {
+
+ final String id;
+ final PsiClass clazz;
+ final Icon icon;
+ final String displayName;
+
+ LanguageDefinition(String id, PsiClass clazz, Icon icon, String displayName) {
+ this.id = id;
+ this.clazz = clazz;
+ this.icon = icon;
+ this.displayName = displayName;
+ }
+ }
+}
diff --git a/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java b/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java
index aca8a5d..efa0062 100644
--- a/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.java
+++ b/plugins/devkit/src/inspections/ComponentNotRegisteredInspection.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.
@@ -22,7 +22,7 @@
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtil;
+import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
@@ -165,7 +165,7 @@
final Project project = psiClass.getProject();
final PsiFile psiFile = psiClass.getContainingFile();
LOG.assertTrue(psiFile != null);
- final Module module = ModuleUtil.findModuleForFile(psiFile.getVirtualFile(), project);
- return module != null && PluginModuleType.isPluginModuleOrDependency(module);
+ final Module module = ModuleUtilCore.findModuleForFile(psiFile.getVirtualFile(), project);
+ return PluginModuleType.isPluginModuleOrDependency(module);
}
}
diff --git a/plugins/devkit/src/inspections/DevKitInspectionBase.java b/plugins/devkit/src/inspections/DevKitInspectionBase.java
index c2e77ba..9ded8e2 100644
--- a/plugins/devkit/src/inspections/DevKitInspectionBase.java
+++ b/plugins/devkit/src/inspections/DevKitInspectionBase.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.
@@ -75,7 +75,7 @@
@Nullable
private static Set<PsiClass> checkModule(Module module, PsiClass psiClass, @Nullable Set<PsiClass> types, boolean includeActions) {
final XmlFile pluginXml = PluginModuleType.getPluginXml(module);
- if (!isPluginXml(pluginXml)) return types;
+ if (!DescriptorUtil.isPluginXml(pluginXml)) return types;
assert pluginXml != null;
final XmlDocument document = pluginXml.getDocument();
@@ -100,17 +100,6 @@
return types;
}
- public static boolean isPluginXml(PsiFile file) {
- if (!(file instanceof XmlFile)) return false;
- final XmlFile pluginXml = (XmlFile)file;
-
- final XmlDocument document = pluginXml.getDocument();
- if (document == null) return false;
- final XmlTag rootTag = document.getRootTag();
- return rootTag != null && "idea-plugin".equals(rootTag.getLocalName());
-
- }
-
@Nullable
protected static PsiElement getAttValueToken(@NotNull XmlAttribute attribute) {
final XmlAttributeValue valueElement = attribute.getValueElement();
diff --git a/plugins/devkit/src/inspections/InspectionDescriptionNotFoundInspection.java b/plugins/devkit/src/inspections/InspectionDescriptionNotFoundInspection.java
index 155274e..fb8b520 100644
--- a/plugins/devkit/src/inspections/InspectionDescriptionNotFoundInspection.java
+++ b/plugins/devkit/src/inspections/InspectionDescriptionNotFoundInspection.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,8 +30,6 @@
import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix;
import org.jetbrains.idea.devkit.util.PsiUtil;
-import java.util.List;
-
/**
* @author Konstantin Bulenkov
*/
@@ -41,11 +39,11 @@
@Override
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
- final Project project = aClass.getProject();
+ final Project project = aClass.getProject();
final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
final Module module = ModuleUtil.findModuleForPsiElement(aClass);
- if (nameIdentifier == null || module == null || !PsiUtil.isInstantiatable(aClass)) return null;
+ if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null;
final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INSPECTION_PROFILE_ENTRY, GlobalSearchScope.allScope(project));
@@ -75,7 +73,7 @@
.createProblemDescriptor(problem == null ? nameIdentifier : problem,
"Inspection does not have a description", isOnTheFly, new LocalQuickFix[]{new CreateHtmlDescriptionFix(filename, module, false)},
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
- return new ProblemDescriptor[]{problemDescriptor};
+ return new ProblemDescriptor[]{problemDescriptor};
}
@Nullable
diff --git a/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java b/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java
index e5f02f2..e424c70 100644
--- a/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.java
+++ b/plugins/devkit/src/inspections/IntentionDescriptionNotFoundInspection.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.
@@ -46,7 +46,7 @@
final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
final Module module = ModuleUtil.findModuleForPsiElement(aClass);
- if (nameIdentifier == null || module == null || !PsiUtil.isInstantiatable(aClass)) return null;
+ if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null;
final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INTENTION, GlobalSearchScope.allScope(project));
diff --git a/plugins/devkit/src/inspections/RegistrationProblemsInspection.java b/plugins/devkit/src/inspections/RegistrationProblemsInspection.java
index 8473dc0..d73c7b2 100644
--- a/plugins/devkit/src/inspections/RegistrationProblemsInspection.java
+++ b/plugins/devkit/src/inspections/RegistrationProblemsInspection.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.
@@ -116,7 +116,7 @@
@Nullable
public ProblemDescriptor[] checkFile(@NotNull PsiFile file, @NotNull InspectionManager manager, boolean isOnTheFly) {
- if (CHECK_PLUGIN_XML && isPluginXml(file)) {
+ if (CHECK_PLUGIN_XML && DescriptorUtil.isPluginXml(file)) {
return checkPluginXml((XmlFile)file, manager, isOnTheFly);
}
return null;
diff --git a/plugins/devkit/src/inspections/UseJBColorInspection.java b/plugins/devkit/src/inspections/UseJBColorInspection.java
deleted file mode 100644
index 833b774..0000000
--- a/plugins/devkit/src/inspections/UseJBColorInspection.java
+++ /dev/null
@@ -1,125 +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 org.jetbrains.idea.devkit.inspections;
-
-import com.intellij.codeInspection.InspectionManager;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ProblemHighlightType;
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtilCore;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.ui.JBColor;
-import com.intellij.util.PlatformUtils;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToJBColorConstantQuickFix;
-import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToJBColorQuickFix;
-import org.jetbrains.idea.devkit.module.PluginModuleType;
-
-import java.awt.*;
-
-/**
- * @author Konstantin Bulenkov
- */
-public class UseJBColorInspection extends DevKitInspectionBase {
- @NotNull
- @Override
- public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
- final Module module = ModuleUtilCore.findModuleForPsiElement(holder.getFile());
- if (module == null
- || !(PlatformUtils.isIdeaProject(holder.getProject()) || PluginModuleType.isPluginModuleOrDependency(module))) {
- return new JavaElementVisitor(){};
- }
- return new JavaElementVisitor() {
- @Override
- public void visitNewExpression(PsiNewExpression expression) {
- final ProblemDescriptor descriptor = checkNewExpression(expression, holder.getManager(), isOnTheFly);
- if (descriptor != null) {
- holder.registerProblem(descriptor);
- }
- super.visitNewExpression(expression);
- }
-
- @Override
- public void visitReferenceExpression(PsiReferenceExpression expression) {
- super.visitReferenceExpression(expression);
- final PsiElement colorField = expression.resolve();
- if (colorField != null && colorField instanceof PsiField && ((PsiField)colorField).hasModifierProperty(PsiModifier.STATIC)) {
- final PsiClass colorClass = ((PsiField)colorField).getContainingClass();
- if (colorClass != null && Color.class.getName().equals(colorClass.getQualifiedName())) {
- String text = expression.getText();
- if (text.contains(".")) {
- text = text.substring(text.lastIndexOf('.'));
- }
- if (text.startsWith(".")) {
- text = text.substring(1);
- }
- if (text.equalsIgnoreCase("lightGray")) {
- text = "LIGHT_GRAY";
- } else if (text.equalsIgnoreCase("darkGray")) {
- text = "DARK_GRAY";
- }
- final ProblemDescriptor descriptor = holder.getManager()
- .createProblemDescriptor(expression, "Change to JBColor." + text.toUpperCase(), new ConvertToJBColorConstantQuickFix(text.toUpperCase()),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
- holder.registerProblem(descriptor);
- }
- }
- }
- };
- }
-
- @Nullable
- private static ProblemDescriptor checkNewExpression(PsiNewExpression expression, InspectionManager manager, boolean isOnTheFly) {
- final Project project = manager.getProject();
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
- final PsiClass jbColorClass = facade.findClass(JBColor.class.getName(), GlobalSearchScope.allScope(project));
- final PsiType type = expression.getType();
- if (type != null && jbColorClass != null) {
- if (!facade.getResolveHelper().isAccessible(jbColorClass, expression, jbColorClass)) return null;
- final PsiExpressionList arguments = expression.getArgumentList();
- if (arguments != null) {
- if ("java.awt.Color".equals(type.getCanonicalText())) {
- final PsiElement parent = expression.getParent();
- if (parent instanceof PsiExpressionList && parent.getParent() instanceof PsiNewExpression) {
- final PsiType parentType = ((PsiNewExpression)parent.getParent()).getType();
- if (parentType == null || JBColor.class.getName().equals(parentType.getCanonicalText())) return null;
- }
- return manager.createProblemDescriptor(expression, "Replace with JBColor", new ConvertToJBColorQuickFix(),
- ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
- }
- }
- }
- return null;
- }
-
- @Nls
- @NotNull
- @Override
- public String getDisplayName() {
- return "Use Darcula aware JBColor";
- }
-
- @NotNull
- @Override
- public String getShortName() {
- return "UseJBColor";
- }
-}
diff --git a/plugins/devkit/src/inspections/internal/FileEqualsUsageInspection.java b/plugins/devkit/src/inspections/internal/FileEqualsUsageInspection.java
new file mode 100644
index 0000000..f066b1d
--- /dev/null
+++ b/plugins/devkit/src/inspections/internal/FileEqualsUsageInspection.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 org.jetbrains.idea.devkit.inspections.internal;
+
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.psi.*;
+import org.jetbrains.annotations.NotNull;
+
+public class FileEqualsUsageInspection extends InternalInspection {
+ private static final String MESSAGE =
+ "Do not use File.equals/hashCode/compareTo as they don't honor case-sensitivity on MacOS. " +
+ "Please use FileUtil.filesEquals/fileHashCode/compareFiles instead";
+
+ @Override
+ @NotNull
+ public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+ return new JavaElementVisitor() {
+ @Override
+ public void visitMethodCallExpression(PsiMethodCallExpression expression) {
+ PsiReferenceExpression methodExpression = expression.getMethodExpression();
+ PsiElement resolved = methodExpression.resolve();
+ if (!(resolved instanceof PsiMethod)) return;
+
+ PsiMethod method = (PsiMethod)resolved;
+
+ PsiClass clazz = method.getContainingClass();
+ if (clazz == null) return;
+
+ String methodName = method.getName();
+ if (CommonClassNames.JAVA_IO_FILE.equals(clazz.getQualifiedName()) &&
+ ("equals".equals(methodName) || "compareTo".equals(methodName) || "hashCode".equals(methodName))) {
+ holder.registerProblem(methodExpression, MESSAGE, ProblemHighlightType.LIKE_DEPRECATED);
+ }
+ }
+ };
+ }
+}
diff --git a/plugins/devkit/src/inspections/internal/GtkPreferredJComboBoxRendererInspection.java b/plugins/devkit/src/inspections/internal/GtkPreferredJComboBoxRendererInspection.java
new file mode 100644
index 0000000..b4e2e77
--- /dev/null
+++ b/plugins/devkit/src/inspections/internal/GtkPreferredJComboBoxRendererInspection.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.devkit.inspections.internal;
+
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.ListCellRendererWrapper;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class GtkPreferredJComboBoxRendererInspection extends InternalInspection {
+ private static final String COMBO_BOX_CLASS_NAME = JComboBox.class.getName();
+ private static final String[] RIGHT_RENDERER_CLASS_NAMES =
+ {ListCellRendererWrapper.class.getName(), ColoredListCellRenderer.class.getName()};
+ private static final String SETTER_METHOD_NAME = "setRenderer";
+
+ private static final String MESSAGE =
+ "Default ListCellRenderer implementations are known to cause UI artifacts under GTK+ look&feel, " +
+ "so please use ListCellRendererWrapper or ColoredListCellRenderer instead.";
+
+ @Override
+ @NotNull
+ public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+ return new JavaElementVisitor() {
+ @Override
+ public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
+ super.visitMethodCallExpression(expression);
+
+ final Project project = expression.getProject();
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+
+ final PsiElement target = expression.getMethodExpression().resolve();
+ if (!(target instanceof PsiMethod)) return;
+ final PsiMethod method = (PsiMethod)target;
+ if (!SETTER_METHOD_NAME.equals(method.getName())) return;
+ final PsiClass aClass = ((PsiMethod)target).getContainingClass();
+ final PsiClass comboClass = facade.findClass(COMBO_BOX_CLASS_NAME, GlobalSearchScope.allScope(project));
+ if (!InheritanceUtil.isInheritorOrSelf(aClass, comboClass, true)) return;
+
+ final PsiExpression[] arguments = expression.getArgumentList().getExpressions();
+ if (arguments.length != 1) return;
+ final PsiType type = arguments[0].getType();
+ if (!(type instanceof PsiClassType)) return;
+ final PsiClass rendererClass = ((PsiClassType)type).resolve();
+ for (String rightClassName : RIGHT_RENDERER_CLASS_NAMES) {
+ final PsiClass rightClass = facade.findClass(rightClassName, GlobalSearchScope.allScope(project));
+ if (InheritanceUtil.isInheritorOrSelf(rendererClass, rightClass, true)) return;
+ }
+
+ holder.registerProblem(expression, MESSAGE);
+ }
+ };
+ }
+}
diff --git a/plugins/devkit/src/inspections/internal/InternalInspection.java b/plugins/devkit/src/inspections/internal/InternalInspection.java
new file mode 100644
index 0000000..54251a0
--- /dev/null
+++ b/plugins/devkit/src/inspections/internal/InternalInspection.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.idea.devkit.inspections.internal;
+
+import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
+import com.intellij.codeInspection.LocalInspectionToolSession;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.psi.PsiElementVisitor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.devkit.module.PluginModuleType;
+import org.jetbrains.idea.devkit.util.PsiUtil;
+
+public abstract class InternalInspection extends BaseJavaLocalInspectionTool {
+ @NotNull
+ @Override
+ public final PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
+ return isAllowed(holder) ? buildInternalVisitor(holder, isOnTheFly) : PsiUtil.EMPTY_VISITOR;
+ }
+
+ @NotNull
+ @Override
+ public final PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder,
+ boolean isOnTheFly,
+ @NotNull LocalInspectionToolSession session) {
+ return isAllowed(holder) ? buildInternalVisitor(holder, isOnTheFly) : PsiUtil.EMPTY_VISITOR;
+ }
+
+ private static boolean isAllowed(ProblemsHolder holder) {
+ if (PsiUtil.isIdeaProject(holder.getProject())) {
+ return true;
+ }
+
+ Module module = ModuleUtilCore.findModuleForPsiElement(holder.getFile());
+ if (PluginModuleType.isPluginModuleOrDependency(module)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ public abstract PsiElementVisitor buildInternalVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly);
+}
diff --git a/plugins/devkit/src/inspections/internal/UndesirableClassUsageInspection.java b/plugins/devkit/src/inspections/internal/UndesirableClassUsageInspection.java
new file mode 100644
index 0000000..18cbbd3
--- /dev/null
+++ b/plugins/devkit/src/inspections/internal/UndesirableClassUsageInspection.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.devkit.inspections.internal;
+
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.application.QueryExecutorBase;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.psi.*;
+import com.intellij.ui.components.JBList;
+import com.intellij.ui.components.JBScrollPane;
+import com.intellij.ui.table.JBTable;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.QueryExecutor;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.image.BufferedImage;
+import java.util.Map;
+
+public class UndesirableClassUsageInspection extends InternalInspection {
+ private static final Map<String, String> CLASSES = new THashMap<String, String>();
+ static {
+ CLASSES.put(JList.class.getName(), JBList.class.getName());
+ CLASSES.put(JTable.class.getName(), JBTable.class.getName());
+ CLASSES.put(JTree.class.getName(), Tree.class.getName());
+ CLASSES.put(JScrollPane.class.getName(), JBScrollPane.class.getName());
+ CLASSES.put(JComboBox.class.getName(), ComboBox.class.getName());
+ CLASSES.put(QueryExecutor.class.getName(), QueryExecutorBase.class.getName());
+ CLASSES.put(BufferedImage.class.getName(), "UIUtil.createImage()");
+ }
+
+ @Override
+ @NotNull
+ public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
+ return new JavaElementVisitor() {
+ @Override
+ public void visitNewExpression(PsiNewExpression expression) {
+ PsiJavaCodeReferenceElement ref = expression.getClassReference();
+ if (ref == null) return;
+
+ PsiElement res = ref.resolve();
+ if (res == null) return;
+
+ String name = ((PsiClass)res).getQualifiedName();
+ if (name == null) return;
+
+ String replacement = CLASSES.get(name);
+ if (replacement == null) return;
+
+ holder.registerProblem(expression, "Please use '" + replacement + "' instead", ProblemHighlightType.LIKE_DEPRECATED);
+ }
+ };
+ }
+}
diff --git a/plugins/devkit/src/inspections/internal/UnsafeVfsRecursionInspection.java b/plugins/devkit/src/inspections/internal/UnsafeVfsRecursionInspection.java
new file mode 100644
index 0000000..97201d8
--- /dev/null
+++ b/plugins/devkit/src/inspections/internal/UnsafeVfsRecursionInspection.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.devkit.inspections.internal;
+
+import com.intellij.codeInspection.ProblemsHolder;
+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.search.GlobalSearchScope;
+import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiTreeUtil;
+import org.jetbrains.annotations.NotNull;
+
+public class UnsafeVfsRecursionInspection extends InternalInspection {
+ private static final String VIRTUAL_FILE_CLASS_NAME = VirtualFile.class.getName();
+ private static final String GET_CHILDREN_METHOD_NAME = "getChildren";
+
+ private static final String MESSAGE =
+ "VirtualFile.getChildren() is called from a recursive method. " +
+ "This may cause an endless loop on cyclic symlinks. " +
+ "Please use VfsUtilCore.visitChildrenRecursively() instead.";
+
+ @NotNull
+ @Override
+ public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+ return new JavaElementVisitor() {
+ @Override
+ public void visitMethodCallExpression(final PsiMethodCallExpression expression) {
+ final Project project = expression.getProject();
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+
+ final PsiReferenceExpression methodRef = expression.getMethodExpression();
+ if (!GET_CHILDREN_METHOD_NAME.equals(methodRef.getReferenceName())) return;
+ final PsiElement methodElement = methodRef.resolve();
+ if (!(methodElement instanceof PsiMethod)) return;
+ final PsiMethod method = (PsiMethod)methodElement;
+ final PsiClass aClass = method.getContainingClass();
+ final PsiClass virtualFileClass = facade.findClass(VIRTUAL_FILE_CLASS_NAME, GlobalSearchScope.allScope(project));
+ if (!InheritanceUtil.isInheritorOrSelf(aClass, virtualFileClass, true)) return;
+
+ final PsiMethod containingMethod = PsiTreeUtil.getParentOfType(expression, PsiMethod.class);
+ if (containingMethod == null) return;
+ final String containingMethodName = containingMethod.getName();
+ final Ref<Boolean> result = Ref.create();
+ containingMethod.accept(new JavaRecursiveElementVisitor() {
+ @Override
+ public void visitMethodCallExpression(final PsiMethodCallExpression expression2) {
+ if (expression2 != expression &&
+ containingMethodName.equals(expression2.getMethodExpression().getReferenceName()) &&
+ expression2.resolveMethod() == containingMethod) {
+ result.set(Boolean.TRUE);
+ }
+ }
+ });
+
+ if (!result.isNull()) {
+ holder.registerProblem(expression, MESSAGE);
+ }
+ }
+ };
+ }
+}
diff --git a/plugins/devkit/src/inspections/internal/UseJBColorInspection.java b/plugins/devkit/src/inspections/internal/UseJBColorInspection.java
new file mode 100644
index 0000000..aa4fe02
--- /dev/null
+++ b/plugins/devkit/src/inspections/internal/UseJBColorInspection.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.devkit.inspections.internal;
+
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ProblemsHolder;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.ui.JBColor;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToJBColorConstantQuickFix;
+import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToJBColorQuickFix;
+
+import java.awt.*;
+
+/**
+ * @author Konstantin Bulenkov
+ */
+public class UseJBColorInspection extends InternalInspection {
+ @Override
+ public PsiElementVisitor buildInternalVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
+ return new JavaElementVisitor() {
+ @Override
+ public void visitNewExpression(PsiNewExpression expression) {
+ final ProblemDescriptor descriptor = checkNewExpression(expression, holder.getManager(), isOnTheFly);
+ if (descriptor != null) {
+ holder.registerProblem(descriptor);
+ }
+ super.visitNewExpression(expression);
+ }
+
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ super.visitReferenceExpression(expression);
+ final PsiElement colorField = expression.resolve();
+ if (colorField != null && colorField instanceof PsiField && ((PsiField)colorField).hasModifierProperty(PsiModifier.STATIC)) {
+ final PsiClass colorClass = ((PsiField)colorField).getContainingClass();
+ if (colorClass != null && Color.class.getName().equals(colorClass.getQualifiedName())) {
+ String text = expression.getText();
+ if (text.contains(".")) {
+ text = text.substring(text.lastIndexOf('.'));
+ }
+ if (text.startsWith(".")) {
+ text = text.substring(1);
+ }
+ if (text.equalsIgnoreCase("lightGray")) {
+ text = "LIGHT_GRAY";
+ } else if (text.equalsIgnoreCase("darkGray")) {
+ text = "DARK_GRAY";
+ }
+ final ProblemDescriptor descriptor = holder.getManager()
+ .createProblemDescriptor(expression, "Change to JBColor." + text.toUpperCase(), new ConvertToJBColorConstantQuickFix(text.toUpperCase()),
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
+ holder.registerProblem(descriptor);
+ }
+ }
+ }
+ };
+ }
+
+ @Nullable
+ private static ProblemDescriptor checkNewExpression(PsiNewExpression expression, InspectionManager manager, boolean isOnTheFly) {
+ final Project project = manager.getProject();
+ final JavaPsiFacade facade = JavaPsiFacade.getInstance(project);
+ final PsiClass jbColorClass = facade.findClass(JBColor.class.getName(), GlobalSearchScope.allScope(project));
+ final PsiType type = expression.getType();
+ if (type != null && jbColorClass != null) {
+ if (!facade.getResolveHelper().isAccessible(jbColorClass, expression, jbColorClass)) return null;
+ final PsiExpressionList arguments = expression.getArgumentList();
+ if (arguments != null) {
+ if ("java.awt.Color".equals(type.getCanonicalText())) {
+ final PsiElement parent = expression.getParent();
+ if (parent instanceof PsiExpressionList && parent.getParent() instanceof PsiNewExpression) {
+ final PsiType parentType = ((PsiNewExpression)parent.getParent()).getType();
+ if (parentType == null || JBColor.class.getName().equals(parentType.getCanonicalText())) return null;
+ }
+ return manager.createProblemDescriptor(expression, "Replace with JBColor", new ConvertToJBColorQuickFix(),
+ ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
+ }
+ }
+ }
+ return null;
+ }
+
+ @Nls
+ @NotNull
+ @Override
+ public String getDisplayName() {
+ return "Use Darcula aware JBColor";
+ }
+
+ @NotNull
+ @Override
+ public String getShortName() {
+ return "UseJBColor";
+ }
+}
diff --git a/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java b/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java
index fe5f538..11890a1 100644
--- a/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.java
+++ b/plugins/devkit/src/inspections/quickfix/AbstractRegisterFix.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.
@@ -72,6 +72,7 @@
final PsiFile psiFile = myClass.getContainingFile();
LOG.assertTrue(psiFile != null);
final Module module = ModuleUtil.findModuleForFile(psiFile.getVirtualFile(), project);
+ assert module != null;
Runnable command = new Runnable() {
public void run() {
diff --git a/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java b/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java
index 879f010..e8f498d 100644
--- a/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.java
+++ b/plugins/devkit/src/inspections/quickfix/CreateHtmlDescriptionFix.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,7 @@
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
+import com.intellij.icons.AllIcons;
import com.intellij.ide.fileTemplates.FileTemplate;
import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.fileTemplates.FileTemplateUtil;
@@ -36,9 +37,9 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
+import com.intellij.ui.LayeredIcon;
import com.intellij.ui.components.JBList;
import com.intellij.util.ArrayUtil;
-import icons.DevkitIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.devkit.DevKitBundle;
@@ -181,7 +182,7 @@
}
public Icon getIcon(int flags) {
- return DevkitIcons.New_html;
+ return new LayeredIcon(AllIcons.FileTypes.Html, AllIcons.Actions.New);
}
private VirtualFile[] prepare(VirtualFile[] roots) {
diff --git a/plugins/devkit/src/module/PluginModuleBuilder.java b/plugins/devkit/src/module/PluginModuleBuilder.java
index 2552b2b..fde2a63 100644
--- a/plugins/devkit/src/module/PluginModuleBuilder.java
+++ b/plugins/devkit/src/module/PluginModuleBuilder.java
@@ -56,7 +56,7 @@
}
@Override
- public String getGroupName() {
+ public String getParentGroup() {
return JavaModuleType.JAVA_GROUP;
}
}
diff --git a/plugins/devkit/src/module/PluginModuleType.java b/plugins/devkit/src/module/PluginModuleType.java
index b97ec1b..e0cb37b 100644
--- a/plugins/devkit/src/module/PluginModuleType.java
+++ b/plugins/devkit/src/module/PluginModuleType.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.
@@ -19,7 +19,6 @@
import com.intellij.openapi.module.*;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.util.IconLoader;
import com.intellij.psi.xml.XmlFile;
import com.intellij.util.containers.HashSet;
import com.intellij.util.descriptors.ConfigFile;
@@ -38,7 +37,7 @@
import java.util.Set;
public class PluginModuleType extends ModuleType<PluginModuleBuilder> {
- private static final Icon ADD_PLUGIN_MODULE_ICON = IconLoader.getIcon("/add_plugin_modulewizard.png");
+
@NonNls private static final String ID = "PLUGIN_MODULE";
public PluginModuleType() {
@@ -49,7 +48,7 @@
return (PluginModuleType) ModuleTypeManager.getInstance().findByID(ID);
}
- public static boolean isOfType(Module module) {
+ public static boolean isOfType(@NotNull Module module) {
return get(module) instanceof PluginModuleType;
}
@@ -79,7 +78,7 @@
@Nullable
public static XmlFile getPluginXml(Module module) {
if (module == null) return null;
- if (!(get(module) instanceof PluginModuleType)) return null;
+ if (!isOfType(module)) return null;
final PluginBuildConfiguration buildConfiguration = PluginBuildConfiguration.getInstance(module);
if (buildConfiguration == null) return null;
@@ -87,9 +86,9 @@
return configFile != null ? configFile.getXmlFile() : null;
}
- public static boolean isPluginModuleOrDependency(@NotNull Module module) {
+ public static boolean isPluginModuleOrDependency(@Nullable Module module) {
+ if (module == null) return false;
if (isOfType(module)) return true;
-
return getCandidateModules(module).size() > 0;
}
diff --git a/plugins/devkit/src/projectRoots/IdeaJdk.java b/plugins/devkit/src/projectRoots/IdeaJdk.java
index a958af1..cd484b1 100644
--- a/plugins/devkit/src/projectRoots/IdeaJdk.java
+++ b/plugins/devkit/src/projectRoots/IdeaJdk.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,6 +177,8 @@
appendIdeaLibrary(plugins + "DatabaseSupport", result, "database-impl.jar", "jdbc-console.jar");
appendIdeaLibrary(plugins + "css", result, "css.jar");
appendIdeaLibrary(plugins + "uml", result, "uml-support.jar");
+ appendIdeaLibrary(plugins + "Spring", result,
+ "spring-el.jar", "spring-jsf.jar", "spring-persistence-integration.jar", "spring-web.jar");
return VfsUtilCore.toVirtualFileArray(result);
}
@@ -227,7 +229,10 @@
}
final int choice = Messages
- .showChooseDialog("Select Java SDK to be used as IDEA internal platform", "Select Internal Java Platform", ArrayUtil.toStringArray(javaSdks), javaSdks.get(0), Messages.getQuestionIcon());
+ .showChooseDialog("Select Java SDK to be used for " + DevKitBundle.message("sdk.title"),
+ "Select Internal Java Platform",
+ ArrayUtil.toStringArray(javaSdks), javaSdks.get(0),
+ Messages.getQuestionIcon());
if (choice != -1) {
final String name = javaSdks.get(choice);
diff --git a/plugins/devkit/src/references/IconsReferencesContributor.java b/plugins/devkit/src/references/IconsReferencesContributor.java
index dba2102..74d2587 100644
--- a/plugins/devkit/src/references/IconsReferencesContributor.java
+++ b/plugins/devkit/src/references/IconsReferencesContributor.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.
@@ -43,9 +43,11 @@
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.FindUsagesProcessPresentation;
+import com.intellij.usages.UsageViewPresentation;
import com.intellij.util.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.devkit.util.PsiUtil;
import java.util.ArrayList;
import java.util.Collection;
@@ -73,7 +75,7 @@
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
- if (!PlatformUtils.isIdeaProject(element.getProject())) return PsiReference.EMPTY_ARRAY;
+ if (!PsiUtil.isIdeaProject(element.getProject())) return PsiReference.EMPTY_ARRAY;
return new PsiReference[] {
new PsiReferenceBase<PsiElement>(element, true) {
@Override
@@ -157,7 +159,7 @@
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
- if (!PlatformUtils.isIdeaProject(element.getProject())) return PsiReference.EMPTY_ARRAY;
+ if (!PsiUtil.isIdeaProject(element.getProject())) return PsiReference.EMPTY_ARRAY;
return new FileReferenceSet(element) {
@Override
protected Collection<PsiFileSystemItem> getExtraContexts() {
@@ -325,7 +327,7 @@
});
return true;
}
- }, new FindUsagesProcessPresentation());
+ }, new FindUsagesProcessPresentation(new UsageViewPresentation()));
}
}
return true;
diff --git a/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java b/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java
index 9e5ce03..02d6107 100644
--- a/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.java
+++ b/plugins/devkit/src/references/extensions/ExtensionPointQuickDocProvider.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.
@@ -29,7 +29,7 @@
import com.intellij.psi.xml.XmlToken;
import com.intellij.psi.xml.XmlTokenType;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.devkit.inspections.DevKitInspectionBase;
+import org.jetbrains.idea.devkit.util.DescriptorUtil;
import java.util.List;
@@ -50,7 +50,7 @@
@Override
public String generateDoc(PsiElement element, @Nullable PsiElement originalElement) {
if (originalElement == null) return null;
- if (originalElement.getLanguage() == XMLLanguage.INSTANCE || DevKitInspectionBase.isPluginXml(originalElement.getContainingFile())) {
+ if (originalElement.getLanguage() == XMLLanguage.INSTANCE || DescriptorUtil.isPluginXml(originalElement.getContainingFile())) {
final PsiElement context = element.getContext();
String fqn = null;
if (originalElement instanceof XmlToken && ((XmlToken)originalElement).getTokenType() == XmlTokenType.XML_NAME) {
diff --git a/plugins/devkit/src/run/PluginRunConfiguration.java b/plugins/devkit/src/run/PluginRunConfiguration.java
index c477c0d..51eb8f5 100644
--- a/plugins/devkit/src/run/PluginRunConfiguration.java
+++ b/plugins/devkit/src/run/PluginRunConfiguration.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.
@@ -80,7 +80,7 @@
final Sdk ideaJdk = IdeaJdk.findIdeaJdk(jdk);
if (ideaJdk == null) {
- throw new ExecutionException(DevKitBundle.message("jdk.type.incorrect.common"));
+ throw new ExecutionException(DevKitBundle.message("sdk.type.incorrect.common"));
}
String sandboxHome = ((Sandbox)ideaJdk.getSdkAdditionalData()).getSandboxHome();
@@ -145,11 +145,14 @@
String prefix = null;
if (buildNumber.startsWith("IC")) {
- prefix = PlatformUtils.COMMUNITY_PREFIX;
+ prefix = PlatformUtils.IDEA_CE_PREFIX;
}
else if (buildNumber.startsWith("PY")) {
prefix = PlatformUtils.PYCHARM_PREFIX;
}
+ else if (buildNumber.startsWith("PC")) {
+ prefix = PlatformUtils.PYCHARM_CE_PREFIX;
+ }
else if (buildNumber.startsWith("RM")) {
prefix = PlatformUtils.RUBY_PREFIX;
}
@@ -162,7 +165,13 @@
else if (buildNumber.startsWith("OC")) {
prefix = buildNumber.contains("121") ? "CIDR" : PlatformUtils.APPCODE_PREFIX;
}
- if (prefix != null) vm.defineProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
+ else if (buildNumber.startsWith("CP")) {
+ prefix = PlatformUtils.CPP_PREFIX;
+ }
+
+ if (prefix != null) {
+ vm.defineProperty(PlatformUtils.PLATFORM_PREFIX_KEY, prefix);
+ }
}
}
@@ -231,12 +240,12 @@
throw new RuntimeConfigurationException(DevKitBundle.message("run.configuration.no.module.specified"));
}
final ModuleRootManager rootManager = ModuleRootManager.getInstance(getModule());
- final Sdk jdk = rootManager.getSdk();
- if (jdk == null) {
- throw new RuntimeConfigurationException(DevKitBundle.message("jdk.no.specified", moduleName));
+ final Sdk sdk = rootManager.getSdk();
+ if (sdk == null) {
+ throw new RuntimeConfigurationException(DevKitBundle.message("sdk.no.specified", moduleName));
}
- if (IdeaJdk.findIdeaJdk(jdk) == null) {
- throw new RuntimeConfigurationException(DevKitBundle.message("jdk.type.incorrect", moduleName));
+ if (IdeaJdk.findIdeaJdk(sdk) == null) {
+ throw new RuntimeConfigurationException(DevKitBundle.message("sdk.type.incorrect", moduleName));
}
}
diff --git a/plugins/devkit/src/util/ChooseModulesDialog.java b/plugins/devkit/src/util/ChooseModulesDialog.java
index 28eabdb..dcc43c1 100644
--- a/plugins/devkit/src/util/ChooseModulesDialog.java
+++ b/plugins/devkit/src/util/ChooseModulesDialog.java
@@ -27,6 +27,7 @@
import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SimpleTextAttributes;
+import com.intellij.ui.TableUtil;
import com.intellij.ui.components.JBList;
import com.intellij.ui.table.JBTable;
import org.jetbrains.annotations.NonNls;
@@ -98,7 +99,7 @@
myView.setShowGrid(false);
myView.setTableHeader(null);
myView.setIntercellSpacing(new Dimension(0, 0));
- myView.getColumnModel().getColumn(0).setMaxWidth(new JCheckBox().getPreferredSize().width);
+ TableUtil.setupCheckboxColumn(myView, 0);
myView.getModel().addTableModelListener(new TableModelListener() {
public void tableChanged(TableModelEvent e) {
getOKAction().setEnabled(getSelectedModules().size() > 0);
diff --git a/plugins/devkit/src/util/DescriptorUtil.java b/plugins/devkit/src/util/DescriptorUtil.java
index 4fca895..3a773e9 100644
--- a/plugins/devkit/src/util/DescriptorUtil.java
+++ b/plugins/devkit/src/util/DescriptorUtil.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,16 +15,20 @@
*/
package org.jetbrains.idea.devkit.util;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.vfs.ReadonlyStatusHandler;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
-import com.intellij.psi.PsiClass;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.ReadonlyStatusHandler;
-import com.intellij.openapi.module.Module;
-import org.jetbrains.idea.devkit.DevKitBundle;
-import org.jetbrains.idea.devkit.module.PluginModuleType;
+import com.intellij.util.xml.DomFileElement;
+import com.intellij.util.xml.DomManager;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.devkit.DevKitBundle;
+import org.jetbrains.idea.devkit.dom.IdeaPlugin;
+import org.jetbrains.idea.devkit.module.PluginModuleType;
/**
* @author swr
@@ -72,16 +76,18 @@
assert PluginModuleType.isOfType(plugin);
final XmlFile pluginXml = PluginModuleType.getPluginXml(plugin);
- if (pluginXml != null) {
- final XmlTag rootTag = pluginXml.getDocument().getRootTag();
- if (rootTag != null) {
- final XmlTag idTag = rootTag.findFirstSubTag("id");
- if (idTag != null) return idTag.getValue().getTrimmedText();
-
- final XmlTag nameTag = rootTag.findFirstSubTag("name");
- if (nameTag != null) return nameTag.getValue().getTrimmedText();
- }
+ if (pluginXml == null) {
+ return null;
}
- return null;
+ return getIdeaPlugin(pluginXml).getRootElement().getPluginId();
+ }
+
+ public static boolean isPluginXml(PsiFile file) {
+ if (!(file instanceof XmlFile)) return false;
+ return getIdeaPlugin((XmlFile)file) != null;
+ }
+
+ private static DomFileElement<IdeaPlugin> getIdeaPlugin(XmlFile file) {
+ return DomManager.getDomManager(file.getProject()).getFileElement(file, IdeaPlugin.class);
}
}
diff --git a/plugins/devkit/src/util/PsiUtil.java b/plugins/devkit/src/util/PsiUtil.java
index 490f94f..58b6e8c 100644
--- a/plugins/devkit/src/util/PsiUtil.java
+++ b/plugins/devkit/src/util/PsiUtil.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,10 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.jetbrains.idea.devkit.util;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.GlobalSearchScopesCore;
+import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,21 +29,19 @@
* @author Konstantin Bulenkov
*/
public class PsiUtil {
- private PsiUtil() {
- }
+ private static final Key<Boolean> IDEA_PROJECT = Key.create("idea.internal.inspections.enabled");
+ private static final String IDE_PROJECT_MARKER_CLASS = JBList.class.getName();
+ public static final PsiElementVisitor EMPTY_VISITOR = new PsiElementVisitor() { };
- public static boolean isInstantiatable(@NotNull PsiClass cls) {
- final PsiModifierList modifiers = cls.getModifierList();
+ private PsiUtil() { }
- if (modifiers == null
- || cls.isInterface()
- || modifiers.hasModifierProperty(PsiModifier.ABSTRACT)
- || !isPublicOrStaticInnerClass(cls)) {
+ public static boolean isInstantiable(@NotNull PsiClass cls) {
+ final PsiModifierList modList = cls.getModifierList();
+ if (modList == null || cls.isInterface() || modList.hasModifierProperty(PsiModifier.ABSTRACT) || !isPublicOrStaticInnerClass(cls)) {
return false;
}
final PsiMethod[] constructors = cls.getConstructors();
-
if (constructors.length == 0) return true;
for (PsiMethod constructor : constructors) {
@@ -58,24 +61,16 @@
(cls.getParent() instanceof PsiFile || modifiers.hasModifierProperty(PsiModifier.STATIC));
}
- public static boolean isOneStatementMethod(@NotNull PsiMethod method) {
- final PsiCodeBlock body = method.getBody();
- return body != null
- && body.getStatements().length == 1
- && body.getStatements()[0] instanceof PsiReturnStatement;
- }
-
@Nullable
public static String getReturnedLiteral(PsiMethod method, PsiClass cls) {
- if (isOneStatementMethod(method)) {
- final PsiExpression value = ((PsiReturnStatement)method.getBody().getStatements()[0]).getReturnValue();
- if (value instanceof PsiLiteralExpression) {
- final Object str = ((PsiLiteralExpression)value).getValue();
- return str == null ? null : str.toString();
- } else if (value instanceof PsiMethodCallExpression) {
- if (isSimpleClassNameExpression((PsiMethodCallExpression)value)) {
- return cls.getName();
- }
+ final PsiExpression value = getReturnedExpression(method);
+ if (value instanceof PsiLiteralExpression) {
+ final Object str = ((PsiLiteralExpression)value).getValue();
+ return str == null ? null : str.toString();
+ }
+ else if (value instanceof PsiMethodCallExpression) {
+ if (isSimpleClassNameExpression((PsiMethodCallExpression)value)) {
+ return cls.getName();
}
}
return null;
@@ -88,15 +83,45 @@
.replaceAll("\n", "")
.replaceAll("\t", "")
.replaceAll("\r", "");
- return "getClass().getSimpleName()".equals(text) || "this.getClass().getSimpleName()".equals(text);
+ return "getClass().getSimpleName()".equals(text) || "this.getClass().getSimpleName()".equals(text);
}
@Nullable
public static PsiExpression getReturnedExpression(PsiMethod method) {
- if (isOneStatementMethod(method)) {
- return ((PsiReturnStatement)method.getBody().getStatements()[0]).getReturnValue();
- } else {
- return null;
+ PsiCodeBlock body = method.getBody();
+ if (body != null) {
+ PsiStatement[] statements = body.getStatements();
+ if (statements.length == 1 && statements[0] instanceof PsiReturnStatement) {
+ return ((PsiReturnStatement)statements[0]).getReturnValue();
+ }
}
+
+ return null;
+ }
+
+ public static boolean isIdeaProject(@Nullable Project project) {
+ if (project == null) return false;
+
+ Boolean flag = project.getUserData(IDEA_PROJECT);
+ if (flag == null) {
+ flag = checkIdeaProject(project);
+ project.putUserData(IDEA_PROJECT, flag);
+ }
+
+ return flag;
+ }
+
+ private static boolean checkIdeaProject(@NotNull Project project) {
+ VirtualFile baseDir = project.getBaseDir();
+ if (baseDir == null || baseDir.findChild("idea.iml") == null && baseDir.findChild("community-main.iml") == null) {
+ return false;
+ }
+
+ GlobalSearchScope scope = GlobalSearchScopesCore.projectProductionScope(project);
+ if (JavaPsiFacade.getInstance(project).findClass(IDE_PROJECT_MARKER_CLASS, scope) == null) {
+ return false;
+ }
+
+ return true;
}
}
diff --git a/plugins/devkit/testData/codeInsight/MyLanguage.java b/plugins/devkit/testData/codeInsight/MyLanguage.java
new file mode 100644
index 0000000..7a582c4
--- /dev/null
+++ b/plugins/devkit/testData/codeInsight/MyLanguage.java
@@ -0,0 +1,6 @@
+public class MyLanguage extends com.intellij.lang.Language {
+
+ public MyLanguage() {
+ super("MyLanguageID");
+ }
+}
\ No newline at end of file
diff --git a/plugins/devkit/testData/codeInsight/MyLanguageAttributeEPBean.java b/plugins/devkit/testData/codeInsight/MyLanguageAttributeEPBean.java
new file mode 100644
index 0000000..7e64385
--- /dev/null
+++ b/plugins/devkit/testData/codeInsight/MyLanguageAttributeEPBean.java
@@ -0,0 +1,5 @@
+public class MyLanguageAttributeEPBean {
+
+ @com.intellij.util.xmlb.annotations.Attribute("language")
+ public String language;
+}
\ No newline at end of file
diff --git a/plugins/devkit/testData/codeInsight/languageAttribute.xml b/plugins/devkit/testData/codeInsight/languageAttribute.xml
new file mode 100644
index 0000000..bdd24fa
--- /dev/null
+++ b/plugins/devkit/testData/codeInsight/languageAttribute.xml
@@ -0,0 +1,16 @@
+<idea-plugin>
+ <id>com.intellij.myPlugin</id>
+
+ <extensionPoints>
+ <extensionPoint name="myLanguageEP" beanClass="MyLanguageAttributeEPBean"/>
+ </extensionPoints>
+
+ <extensions defaultExtensionNs="com.intellij.myPlugin">
+
+ <myLanguageEP language="MyLanguageID"/>
+
+ <myLanguageEP language="<error descr="Cannot resolve language with id ''INVALID_VALUE''">INVALID_VALUE</error>"/>
+
+ </extensions>
+
+</idea-plugin>
\ No newline at end of file
diff --git a/plugins/devkit/testSources/PluginProjectWizardTest.java b/plugins/devkit/testSources/PluginProjectWizardTest.java
index 603110a..1b6dd25 100644
--- a/plugins/devkit/testSources/PluginProjectWizardTest.java
+++ b/plugins/devkit/testSources/PluginProjectWizardTest.java
@@ -16,8 +16,7 @@
package org.jetbrains.idea.devkit;
import com.intellij.ide.IdeBundle;
-import com.intellij.ide.projectWizard.ProjectWizardTestCase;
-import com.intellij.openapi.module.JavaModuleType;
+import com.intellij.ide.projectWizard.NewProjectWizardTestCase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
@@ -26,13 +25,12 @@
/**
* @author Dmitry Avdeev
- * Date: 11/8/12
*/
-public class PluginProjectWizardTest extends ProjectWizardTestCase {
+public class PluginProjectWizardTest extends NewProjectWizardTestCase {
public void testPluginProject() throws Exception {
createSdk("devkit", IdeaJdk.getInstance());
- Project project = createProjectFromTemplate(JavaModuleType.JAVA_GROUP, PluginModuleType.getInstance().getName(), null);
+ Project project = createProjectFromTemplate(PluginModuleType.getInstance().getName(), null, null);
VirtualFile baseDir = project.getBaseDir();
VirtualFile virtualFile = VfsUtilCore.findRelativeFile("META-INF/plugin.xml", baseDir);
assertNotNull(virtualFile);
@@ -40,7 +38,7 @@
public void testProjectWithoutSdk() throws Exception {
try {
- createProjectFromTemplate(JavaModuleType.JAVA_GROUP, PluginModuleType.getInstance().getName(), null);
+ createProjectFromTemplate(PluginModuleType.getInstance().getName(), null, null);
fail("Exception should be thrown");
}
catch (Exception e) {
diff --git a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
index e6e588f..90bcb4f 100644
--- a/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.groovy
+++ b/plugins/devkit/testSources/codeInsight/PluginXmlFunctionalTest.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.
@@ -20,8 +20,10 @@
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection
import com.intellij.codeInspection.htmlInspections.RequiredAttributesInspection
import com.intellij.codeInspection.unusedSymbol.UnusedSymbolLocalInspection
+import com.intellij.codeInspection.xml.DeprecatedClassUsageInspection
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PluginPathManager
+import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.ElementDescriptionUtil
import com.intellij.psi.PsiElement
import com.intellij.testFramework.PsiTestUtil
@@ -30,7 +32,6 @@
import com.intellij.testFramework.fixtures.TempDirTestFixture
import com.intellij.usageView.UsageViewNodeTextLocation
import com.intellij.usageView.UsageViewTypeLocation
-import com.intellij.codeInspection.xml.DeprecatedClassUsageInspection
import org.jetbrains.idea.devkit.inspections.*
/**
@@ -204,6 +205,18 @@
myFixture.testHighlighting("extensionAttributeWithAccessors.xml", "ExtBeanWithAccessors.java");
}
+ public void testLanguageAttribute() {
+ myFixture.addClass("package com.intellij.lang; " +
+ "public class Language { " +
+ " protected Language(String id) {}" +
+ "}")
+ VirtualFile myLanguageVirtualFile = myFixture.copyFileToProject("MyLanguage.java");
+ myFixture.allowTreeAccessForFile(myLanguageVirtualFile)
+
+ myFixture.testHighlighting("languageAttribute.xml",
+ "MyLanguageAttributeEPBean.java")
+ }
+
public void testPluginModule() throws Throwable {
myFixture.testHighlighting("pluginWithModules.xml");
}
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/EclipseBundle.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/EclipseBundle.java
index d3c9174..c00e15b 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/EclipseBundle.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/EclipseBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,21 +25,20 @@
import java.util.ResourceBundle;
public class EclipseBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "EclipseBundle";
private EclipseBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/export/ExportEclipseProjectsAction.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/export/ExportEclipseProjectsAction.java
index f0c6750..38a9f8a 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/export/ExportEclipseProjectsAction.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/export/ExportEclipseProjectsAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,7 +18,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.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -29,7 +28,6 @@
import com.intellij.openapi.roots.ModuleRootModel;
import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil;
import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.io.FileUtil;
@@ -43,7 +41,10 @@
import org.jetbrains.idea.eclipse.EclipseBundle;
import org.jetbrains.idea.eclipse.EclipseXml;
import org.jetbrains.idea.eclipse.IdeaXml;
-import org.jetbrains.idea.eclipse.conversion.*;
+import org.jetbrains.idea.eclipse.conversion.DotProjectFileHelper;
+import org.jetbrains.idea.eclipse.conversion.EclipseClasspathWriter;
+import org.jetbrains.idea.eclipse.conversion.EclipseUserLibrariesHelper;
+import org.jetbrains.idea.eclipse.conversion.IdeaSpecificSettings;
import org.jetbrains.jps.eclipse.model.JpsEclipseClasspathSerializer;
import java.io.File;
@@ -87,7 +88,7 @@
}
}, "<br><li>") +
"</ul><br>Would you like to proceed and possibly lose your configurations?</body></html>",
- "Eclipse Incompatible Modules Found", Messages.getWarningIcon()) != DialogWrapper.OK_EXIT_CODE) {
+ "Eclipse Incompatible Modules Found", Messages.getWarningIcon()) != Messages.OK) {
return;
}
}
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
index a640a13..f1157a1 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importWizard/EclipseImportBuilder.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -43,7 +43,6 @@
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
import com.intellij.openapi.startup.StartupManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMUtil;
@@ -275,8 +274,8 @@
}, "\n") +
".\n Would you like to reuse them?", "Module files found",
Messages.getQuestionIcon());
- if (resultCode != DialogWrapper.OK_EXIT_CODE) {
- if (resultCode == DialogWrapper.CANCEL_EXIT_CODE) {
+ if (resultCode != Messages.YES) {
+ if (resultCode == Messages.NO) {
final LocalFileSystem localFileSystem = LocalFileSystem.getInstance();
for (File file : files) {
final VirtualFile virtualFile = localFileSystem.findFileByIoFile(file);
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java
index e1e432d..b3cc7ec 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseCodeStyleSchemeImporter.java
@@ -154,9 +154,6 @@
VALUE_TRUE.equals(value)) {
return true;
}
- if (key.contains("alignment") && value.matches("\\d*")) {
- return isAlignmentOn(value);
- }
if (!(VALUE_DO_NOT_INSERT.equals(value) ||
VALUE_FALSE.equals(value))) {
throw new SchemeImportException("Unrecognized boolean value: " + value + ", key: " + key);
@@ -172,12 +169,57 @@
return Integer.parseInt(value);
}
- private static boolean isAlignmentOn(@NotNull String value) {
- int packed = valueToInt(value);
- return (packed & 2) != 0;
+ private static class AlignmentAndWrapValueDecoder {
+ int myEncodedValue;
+
+ public AlignmentAndWrapValueDecoder(int encodedValue) {
+ myEncodedValue = encodedValue;
+ }
+
+ public int getWrapType() {
+ switch (getEclipseWrap()) {
+ case WRAP_WHERE_NECESSARY:
+ case WRAP_FIRST_OTHERS_WHERE_NECESSARY:
+ return CommonCodeStyleSettings.WRAP_AS_NEEDED;
+ case WRAP_ALL_EXCEPT_FIRST:
+ case WRAP_ALL_INDENT_EXCEPT_FIRST:
+ case WRAP_ALL_ON_NEW_LINE_EACH:
+ return CommonCodeStyleSettings.WRAP_AS_NEEDED | CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM;
+ }
+ return CommonCodeStyleSettings.DO_NOT_WRAP;
+ }
+
+ public int getFirstElementWrapType() {
+ return isNewLineBeforeFirst() ? CommonCodeStyleSettings.WRAP_ALWAYS :
+ getEclipseWrap() == WRAP_ALL_EXCEPT_FIRST ? CommonCodeStyleSettings.DO_NOT_WRAP :
+ CommonCodeStyleSettings.WRAP_AS_NEEDED;
+ }
+
+ public boolean isFirstElementWrapped() {
+ int eclipseWrapValue = getEclipseWrap();
+ return eclipseWrapValue == WRAP_FIRST_OTHERS_WHERE_NECESSARY ||
+ eclipseWrapValue == WRAP_ALL_INDENT_EXCEPT_FIRST ||
+ eclipseWrapValue == WRAP_ALL_ON_NEW_LINE_EACH ||
+ isNewLineBeforeFirst();
+ }
+
+ public boolean isNewLineBeforeFirst() {
+ return (myEncodedValue & 1) != 0;
+ }
+
+ public boolean isAlignmentOn() {
+ return (myEncodedValue & 2) != 0;
+ }
+
+ public int getEclipseWrap() {
+ return myEncodedValue & WRAP_MASK;
+ }
}
private static void setProgrammatically(@NotNull Object object, @NotNull String key, @NotNull String value) throws SchemeImportException {
+ if (key.contains("alignment") && value.matches("\\d*") && object instanceof CommonCodeStyleSettings) {
+ if (setAlignmentAndWrappingOptions((CommonCodeStyleSettings)object, key, value)) return;
+ }
if (object instanceof CodeStyleSettings) {
CodeStyleSettings settings = (CodeStyleSettings)object;
if (OPTION_REMOVE_JAVADOC_BLANK_LINES.equals(key)) {
@@ -204,6 +246,17 @@
else if (OPTION_INDENT_CLASS_BODY_DECL.equals(key)) {
commonSettings.DO_NOT_INDENT_TOP_LEVEL_CLASS_MEMBERS = !valueToBoolean(key, value);
}
+ else if (OPTION_BLANK_LINES_BEFORE_FIRST_DECLARATION_IN_CLASS.equals(key)) {
+ int intValue = valueToInt(value);
+ commonSettings.BLANK_LINES_AFTER_CLASS_HEADER = intValue;
+ commonSettings.BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER = intValue;
+ }
+ else if (OPTION_EMPTY_LINES_TO_PRESERVE.equals(key)) {
+ int intValue = valueToInt(value);
+ commonSettings.KEEP_BLANK_LINES_IN_CODE = intValue;
+ commonSettings.KEEP_BLANK_LINES_IN_DECLARATIONS = intValue;
+ commonSettings.KEEP_BLANK_LINES_BEFORE_RBRACE = intValue;
+ }
}
else if (object instanceof CommonCodeStyleSettings.IndentOptions) {
CommonCodeStyleSettings.IndentOptions indentOptions = (CommonCodeStyleSettings.IndentOptions)object;
@@ -228,4 +281,74 @@
}
}
}
+
+ private static boolean setAlignmentAndWrappingOptions(@NotNull CommonCodeStyleSettings settings,
+ @NotNull String key,
+ @NotNull String value) {
+ int encodedValue = Integer.parseInt(value);
+ AlignmentAndWrapValueDecoder decoder = new AlignmentAndWrapValueDecoder(encodedValue);
+ if (OPTION_ALIGN_ARGS_IN_ANNOTATION.equals(key)) {
+ settings.FIELD_ANNOTATION_WRAP =
+ settings.METHOD_ANNOTATION_WRAP =
+ settings.PARAMETER_ANNOTATION_WRAP =
+ settings.VARIABLE_ANNOTATION_WRAP =
+ settings.CLASS_ANNOTATION_WRAP = decoder.getWrapType();
+ return true;
+ }
+ else if (OPTION_ALIGN_EXPR_IN_ARRAY_INITIALIZER.equals(key)) {
+ settings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION = decoder.isAlignmentOn();
+ settings.ARRAY_INITIALIZER_WRAP = decoder.getWrapType();
+ settings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = decoder.isFirstElementWrapped();
+ return true;
+ }
+ else if (OPTION_ALIGN_ARGS_IN_METHOD_INVOCATION.equals(key)) {
+ settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = decoder.isAlignmentOn();
+ settings.CALL_PARAMETERS_WRAP = decoder.getWrapType();
+ settings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = decoder.isFirstElementWrapped();
+ return true;
+ }
+ else if (OPTION_ALIGN_INTERFACES_IN_TYPE_DECL.equals(key)) {
+ settings.ALIGN_MULTILINE_EXTENDS_LIST = decoder.isAlignmentOn();
+ settings.EXTENDS_KEYWORD_WRAP = decoder.getFirstElementWrapType();
+ settings.EXTENDS_LIST_WRAP = decoder.getWrapType();
+ return true;
+ }
+ else if (OPTION_ALIGN_ASSIGNMENT.equals(key)) {
+ settings.ALIGN_MULTILINE_ASSIGNMENT = decoder.isAlignmentOn();
+ settings.ASSIGNMENT_WRAP = decoder.getWrapType();
+ return true;
+ }
+ else if (OPTION_ALIGN_METHOD_DECL_PARAMETERS.equals(key)) {
+ settings.ALIGN_MULTILINE_PARAMETERS = decoder.isAlignmentOn();
+ settings.METHOD_PARAMETERS_WRAP = decoder.getWrapType();
+ settings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE = decoder.isFirstElementWrapped();
+ return true;
+ }
+ else if (OPTION_ALIGN_BINARY_EXPR.equals(key)) {
+ settings.ALIGN_MULTILINE_BINARY_OPERATION = decoder.isAlignmentOn();
+ settings.BINARY_OPERATION_WRAP = decoder.getWrapType();
+ return true;
+ }
+ else if (OPTION_ALIGN_THROWS_IN_METHOD_DECL.equals(key)) {
+ settings.ALIGN_MULTILINE_THROWS_LIST = decoder.isAlignmentOn();
+ settings.THROWS_KEYWORD_WRAP = decoder.getFirstElementWrapType();
+ settings.THROWS_LIST_WRAP = decoder.getWrapType();
+ return true;
+ }
+ else if (OPTION_ALIGN_RESOURCES_IN_TRY.equals(key)) {
+ settings.ALIGN_MULTILINE_RESOURCES = decoder.isAlignmentOn();
+ settings.RESOURCE_LIST_WRAP = decoder.getWrapType();
+ settings.RESOURCE_LIST_LPAREN_ON_NEXT_LINE = decoder.isFirstElementWrapped();
+ return true;
+ }
+ else if (OPTION_ALIGN_CHAINED_CALLS.equals(key)) {
+ settings.METHOD_CALL_CHAIN_WRAP = decoder.getWrapType();
+ settings.ALIGN_MULTILINE_CHAINED_METHODS = decoder.isAlignmentOn();
+ }
+ else if (OPTION_ALIGN_CONDITIONALS.equals(key)) {
+ settings.TERNARY_OPERATION_WRAP = decoder.getWrapType();
+ settings.ALIGN_MULTILINE_TERNARY_OPERATION = decoder.isAlignmentOn();
+ }
+ return false;
+ }
}
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties
index b68e279..9bc5f9b 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseImportMap.properties
@@ -34,8 +34,8 @@
#org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=
#org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=
#org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=
-org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=Java:ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION
-#org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=Java:<Programmatic>
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=Java:<Programmatic>
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=Java:SPACE_BEFORE_FOR_PARENTHESES
org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=Java:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=
@@ -49,7 +49,7 @@
#org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=
org.eclipse.jdt.core.formatter.continuation_indentation=Java:IndentOptions:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=
-org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=Java:ALIGN_MULTILINE_PARAMETERS_IN_CALLS
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=Java:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=
#org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=
#org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=
@@ -69,7 +69,7 @@
#org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=Java:SPACE_WITHIN_FOR_PARENTHESES
org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=Java:SPACE_BEFORE_METHOD_PARENTHESES
-#org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=Java:<Programmatic>
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=Java:SPACE_WITHIN_SWITCH_PARENTHESES
org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=Java:SPACE_AROUND_UNARY_OPERATOR
#org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=
@@ -86,13 +86,13 @@
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=Java:SPACE_WITHIN_PARENTHESES
#org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=
#org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaratio n=
-#org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=Java:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=
org.eclipse.jdt.core.formatter.indentation.size=Java:IndentOptions:INDENT_SIZE
org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=Java:SPACE_WITHIN_EMPTY_METHOD_PARENTHESES
#org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=
-org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=Java:ALIGN_MULTILINE_EXTENDS_LIST
-org.eclipse.jdt.core.formatter.alignment_for_assignment=Java:ALIGN_MULTILINE_ASSIGNMENT
+#org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=Java:ALIGN_MULTILINE_EXTENDS_LIST
+org.eclipse.jdt.core.formatter.alignment_for_assignment=Java:<Programmatic>
org.eclipse.jdt.core.formatter.tabulation.char=Java:IndentOptions:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=
#org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=
@@ -107,7 +107,7 @@
#org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=
#org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=
#org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=
-org.eclipse.jdt.core.formatter.alignment_for_method_declaration=Java:ALIGN_MULTILINE_PARAMETERS_IN_CALLS
+#org.eclipse.jdt.core.formatter.alignment_for_method_declaration=
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=Java:SPACE_WITHIN_METHOD_CALL_PARENTHESES
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=Java:SPACE_WITHIN_TRY_PARENTHESES
#org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=
@@ -150,7 +150,7 @@
#org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=
org.eclipse.jdt.core.formatter.tabulation.size=Java:IndentOptions:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=
-org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE
+#org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=Java:ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE
#org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=
#org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=
#org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=
@@ -167,7 +167,7 @@
org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=Java:SPACE_AFTER_TYPE_CAST
org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=Java:SPACE_AFTER_COMMA
#org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=
-org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=Java:KEEP_BLANK_LINES_IN_CODE
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=Java:<Programmatic>
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=Java:SPACE_BEFORE_METHOD_PARENTHESES
org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=Java:SPACE_WITHIN_CATCH_PARENTHESES
#org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=
@@ -193,8 +193,8 @@
#org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=
#org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=
#org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=
-#org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=
-org.eclipse.jdt.core.formatter.alignment_for_binary_expression=Java:ALIGN_MULTILINE_BINARY_OPERATION
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=Java:<Programmatic>
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=Java:<Programmatic>
#org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=
#org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=Java:SPACE_WITHIN_WHILE_PARENTHESES
@@ -219,7 +219,7 @@
#org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=
org.eclipse.jdt.core.formatter.wrap_before_binary_operator=Java:BINARY_OPERATION_SIGN_ON_NEXT_LINE
#org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=
-#org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=Java:BLANK_LINES_AROUND_CLASS
org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=Java:SPACE_WITHIN_SYNCHRONIZED_PARENTHESES
#org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=
#org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=
@@ -236,7 +236,7 @@
org.eclipse.jdt.core.formatter.blank_lines_before_imports=Java:BLANK_LINES_BEFORE_IMPORTS
#org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=
#org.eclipse.jdt.core.formatter.comment.format_html=
-org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=Java:ALIGN_MULTILINE_THROWS_LIST
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=Java:<Programmatic>
#org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=
#org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=
#org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=
@@ -248,11 +248,11 @@
org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=Java:SPACE_BEFORE_SYNCHRONIZED_PARENTHESES
#org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=
#org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=
-org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=Java:ALIGN_MULTILINE_PARAMETERS
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=Java:<Programmatic>
org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=Java:SPACE_WITHIN_ARRAY_INITIALIZER_BRACES
-org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=Java:ALIGN_MULTILINE_RESOURCES
+org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=Java:<Programmatic>
org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=Java:IndentOptions:SMART_TABS
-#org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=Java:<Programmatic>
#org.eclipse.jdt.core.formatter.comment.format_header=
#org.eclipse.jdt.core.formatter.comment.format_block_comments=
#org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=
diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java
index 85158fe..b1b805c 100644
--- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java
+++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/importer/EclipseXmlProfileElements.java
@@ -48,4 +48,30 @@
String OPTION_TAB_CHAR = "org.eclipse.jdt.core.formatter.tabulation.char";
String OPTION_CONTINUATION_INDENT = "org.eclipse.jdt.core.formatter.continuation_indentation";
String OPTION_TAB_SIZE = "org.eclipse.jdt.core.formatter.tabulation.size";
+
+ String OPTION_ALIGN_EXPR_IN_ARRAY_INITIALIZER = "org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer";
+ String OPTION_ALIGN_ARGS_IN_ANNOTATION = "org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation";
+ String OPTION_ALIGN_ARGS_IN_METHOD_INVOCATION = "org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation";
+ String OPTION_ALIGN_SUPERCLASS_IN_TYPE_DECL = "org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration";
+ String OPTION_ALIGN_INTERFACES_IN_TYPE_DECL = "org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration";
+ String OPTION_ALIGN_ASSIGNMENT = "org.eclipse.jdt.core.formatter.alignment_for_assignment";
+ String OPTION_ALIGN_METHOD_DECL_PARAMETERS = "org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration";
+ String OPTION_ALIGN_BINARY_EXPR = "org.eclipse.jdt.core.formatter.alignment_for_binary_expression";
+ String OPTION_ALIGN_THROWS_IN_METHOD_DECL = "org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration";
+ String OPTION_ALIGN_RESOURCES_IN_TRY = "org.eclipse.jdt.core.formatter.alignment_for_resources_in_try";
+ String OPTION_ALIGN_METHOD_DECL = "org.eclipse.jdt.core.formatter.alignment_for_method_declaration";
+ String OPTION_ALIGN_CHAINED_CALLS = "org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation";
+ String OPTION_ALIGN_CONDITIONALS = "org.eclipse.jdt.core.formatter.alignment_for_conditional_expression";
+
+ String OPTION_BLANK_LINES_BEFORE_FIRST_DECLARATION_IN_CLASS = "org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration";
+ String OPTION_EMPTY_LINES_TO_PRESERVE = "org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve";
+
+ int WRAP_MASK = 0x70;
+
+ int DO_NOT_WRAP = 0x00;
+ int WRAP_WHERE_NECESSARY = 0x10;
+ int WRAP_FIRST_OTHERS_WHERE_NECESSARY = 0x20;
+ int WRAP_ALL_ON_NEW_LINE_EACH = 0x30;
+ int WRAP_ALL_INDENT_EXCEPT_FIRST = 0x40;
+ int WRAP_ALL_EXCEPT_FIRST = 0x50;
}
diff --git a/plugins/eclipse/testData/iml/allProps/expected/expected.iml b/plugins/eclipse/testData/iml/allProps/expected/expected.iml
index 73bb462..142bc10 100644
--- a/plugins/eclipse/testData/iml/allProps/expected/expected.iml
+++ b/plugins/eclipse/testData/iml/allProps/expected/expected.iml
@@ -101,7 +101,7 @@
<orderEntry type="module-library">
<library name="junit4">
<CLASSES>
- <root url="jar://$JUNIT$/lib/junit-4.10.jar!/" />
+ <root url="jar://$JUNIT$/lib/junit-4.11.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
diff --git a/plugins/eclipse/testData/import/settings/eclipse_exported.xml b/plugins/eclipse/testData/import/settings/eclipse_exported.xml
index 37dd465..7d3f951 100644
--- a/plugins/eclipse/testData/import/settings/eclipse_exported.xml
+++ b/plugins/eclipse/testData/import/settings/eclipse_exported.xml
@@ -27,8 +27,8 @@
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="34"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="18"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
@@ -42,7 +42,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
@@ -63,7 +63,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="50"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
@@ -80,14 +80,14 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@on_tag"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="18"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
@@ -164,7 +164,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
-<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="5"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
@@ -190,8 +190,8 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="50"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="50"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
@@ -217,7 +217,7 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
+<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="3"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
@@ -234,7 +234,7 @@
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="18"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
@@ -246,12 +246,12 @@
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="36"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.7"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="20"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="true"/>
-<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
+<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="50"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/Eclipse2ModulesTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/Eclipse2ModulesTest.java
index 7d56617..76924df 100644
--- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/Eclipse2ModulesTest.java
+++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/Eclipse2ModulesTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -20,8 +20,8 @@
*/
package org.jetbrains.idea.eclipse;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.io.FileUtil;
@@ -69,18 +69,16 @@
protected void doTest(final String workspaceRoot, final String projectRoot) throws Exception {
final VirtualFile file =
- ApplicationManager.getApplication().runWriteAction(
- new Computable<VirtualFile>() {
- @Override
- @Nullable
- public VirtualFile compute() {
- final VirtualFile baseDir = getProject().getBaseDir();
- assert baseDir != null;
- return LocalFileSystem.getInstance()
- .refreshAndFindFileByPath(baseDir.getPath() + "/" + workspaceRoot + "/" + myDependantModulePath);
- }
+ WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
+ @Override
+ @Nullable
+ public VirtualFile compute() {
+ final VirtualFile baseDir = getProject().getBaseDir();
+ assert baseDir != null;
+ return LocalFileSystem.getInstance()
+ .refreshAndFindFileByPath(baseDir.getPath() + "/" + workspaceRoot + "/" + myDependantModulePath);
}
- );
+ });
if (file != null) {
PsiTestUtil.addContentRoot(getModule(), file);
}
diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseClasspathTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseClasspathTest.java
index 9339d9e..ddfdbb7 100644
--- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseClasspathTest.java
+++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseClasspathTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
@@ -80,7 +81,7 @@
fileText = fileText.replaceAll(EclipseXml.FILE_PROTOCOL + "/", EclipseXml.FILE_PROTOCOL);
}
final Element classpathElement = JDOMUtil.loadDocument(fileText).getRootElement();
- final Module module = ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
+ final Module module = WriteCommandAction.runWriteCommandAction(null, new Computable<Module>() {
@Override
public Module compute() {
return ModuleManager.getInstance(project)
diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseEmlTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseEmlTest.java
index 8c80bf7..cfd6a62 100644
--- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseEmlTest.java
+++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseEmlTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -22,6 +22,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
@@ -67,7 +68,7 @@
}
private static Module doLoadModule(final String path, final Project project) throws IOException, JDOMException, InvalidDataException {
- final Module module = ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
+ final Module module = WriteCommandAction.runWriteCommandAction(null, new Computable<Module>() {
@Override
public Module compute() {
return ModuleManager.getInstance(project)
diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseImlTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseImlTest.java
index 7569fdd..5e1cc3f 100644
--- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseImlTest.java
+++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseImlTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -24,6 +24,7 @@
import com.intellij.openapi.application.PathMacros;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -80,7 +81,7 @@
}
fileText = fileText.replaceAll("\\$" + JUNIT + "\\$", communityAppDir);
final Element classpathElement = JDOMUtil.loadDocument(fileText).getRootElement();
- final Module module = ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
+ final Module module = WriteCommandAction.runWriteCommandAction(null, new Computable<Module>() {
@Override
public Module compute() {
return ModuleManager.getInstance(project)
diff --git a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java
index 3fcbfa7..acca9e1 100644
--- a/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java
+++ b/plugins/eclipse/testSources/org/jetbrains/idea/eclipse/EclipseSettingsImportTest.java
@@ -63,7 +63,6 @@
EditorSettingsExternalizable editorSettings = EditorSettingsExternalizable.getInstance();
boolean currAddLineFeed = editorSettings.isEnsureNewLineAtEOF();
editorSettings.setEnsureNewLineAtEOF(true);
- javaSettings.ALIGN_MULTILINE_BINARY_OPERATION = true;
javaSettings.SPACE_WITHIN_TRY_PARENTHESES = true;
javaSettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES = true;
javaSettings.WHILE_ON_NEW_LINE = true;
@@ -76,12 +75,9 @@
javaSettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES = true;
javaSettings.SPACE_BEFORE_QUEST = false;
javaSettings.BLANK_LINES_BEFORE_IMPORTS = 0;
- javaSettings.ALIGN_MULTILINE_THROWS_LIST = true;
javaSettings.SPACE_AFTER_COLON = false;
javaSettings.SPACE_WITHIN_FOR_PARENTHESES = true;
javaSettings.SPACE_BEFORE_SYNCHRONIZED_PARENTHESES = false;
- javaSettings.ALIGN_MULTILINE_PARAMETERS = true;
- javaSettings.ALIGN_MULTILINE_RESOURCES = true;
javaSettings.SPACE_BEFORE_SWITCH_PARENTHESES = false;
javaSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES = true;
javaSettings.CLASS_BRACE_STYLE = CommonCodeStyleSettings.NEXT_LINE;
@@ -92,6 +88,43 @@
javaSettings.BLANK_LINES_AFTER_IMPORTS = -1;
javaSettings.KEEP_FIRST_COLUMN_COMMENT = true;
javaSettings.KEEP_CONTROL_STATEMENT_IN_ONE_LINE = true;
+ javaSettings.FIELD_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.METHOD_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.PARAMETER_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.VARIABLE_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.CLASS_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION = false;
+ javaSettings.ARRAY_INITIALIZER_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS;
+ javaSettings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE = false;
+ javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
+ javaSettings.CALL_PARAMETERS_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE = true;
+ javaSettings.ALIGN_MULTILINE_EXTENDS_LIST = false;
+ javaSettings.EXTENDS_KEYWORD_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.EXTENDS_LIST_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_ASSIGNMENT = false;
+ javaSettings.ASSIGNMENT_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_PARAMETERS = true;
+ javaSettings.METHOD_PARAMETERS_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE = false;
+ javaSettings.ALIGN_MULTILINE_BINARY_OPERATION = false;
+ javaSettings.BINARY_OPERATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_THROWS_LIST = false;
+ javaSettings.THROWS_KEYWORD_WRAP = CommonCodeStyleSettings.WRAP_ALWAYS;
+ javaSettings.THROWS_LIST_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_RESOURCES = true;
+ javaSettings.RESOURCE_LIST_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.RESOURCE_LIST_LPAREN_ON_NEXT_LINE = true;
+ javaSettings.METHOD_CALL_CHAIN_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_CHAINED_METHODS = false;
+ javaSettings.TERNARY_OPERATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
+ javaSettings.ALIGN_MULTILINE_TERNARY_OPERATION = false;
+ javaSettings.BLANK_LINES_AFTER_CLASS_HEADER = -1;
+ javaSettings.BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER = -1;
+ javaSettings.BLANK_LINES_AROUND_CLASS = -1;
+ javaSettings.KEEP_BLANK_LINES_IN_CODE = -1;
+ javaSettings.KEEP_BLANK_LINES_BEFORE_RBRACE = -1;
+ javaSettings.KEEP_BLANK_LINES_IN_DECLARATIONS = -1;
indentOptions.USE_TAB_CHARACTER = false;
indentOptions.SMART_TABS = false;
indentOptions.TAB_SIZE = 3;
@@ -122,7 +155,6 @@
assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS);
assertEquals(0, javaSettings.BLANK_LINES_BEFORE_PACKAGE);
assertFalse(javaSettings.SPACE_WITHIN_FOR_PARENTHESES);
- assertFalse(javaSettings.ALIGN_MULTILINE_ASSIGNMENT);
assertFalse(javaSettings.SPACE_BEFORE_METHOD_PARENTHESES);
assertFalse(javaSettings.SPACE_WITHIN_CATCH_PARENTHESES);
assertFalse(javaSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES);
@@ -130,7 +162,6 @@
assertFalse(javaSettings.SPACE_AROUND_UNARY_OPERATOR);
assertTrue(javaSettings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE);
assertFalse(editorSettings.isEnsureNewLineAtEOF());
- assertFalse(javaSettings.ALIGN_MULTILINE_BINARY_OPERATION);
assertFalse(javaSettings.SPACE_WITHIN_TRY_PARENTHESES);
assertFalse(javaSettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES);
assertFalse(javaSettings.WHILE_ON_NEW_LINE);
@@ -143,12 +174,9 @@
assertFalse(javaSettings.SPACE_WITHIN_SYNCHRONIZED_PARENTHESES);
assertTrue(javaSettings.SPACE_BEFORE_QUEST);
assertEquals(1, javaSettings.BLANK_LINES_BEFORE_IMPORTS);
- assertFalse(javaSettings.ALIGN_MULTILINE_THROWS_LIST);
assertTrue(javaSettings.SPACE_AFTER_COLON);
assertFalse(javaSettings.SPACE_WITHIN_FOR_PARENTHESES);
assertTrue(javaSettings.SPACE_BEFORE_SYNCHRONIZED_PARENTHESES);
- assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS);
- assertFalse(javaSettings.ALIGN_MULTILINE_RESOURCES);
assertTrue(javaSettings.SPACE_BEFORE_SWITCH_PARENTHESES);
assertFalse(javaSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES);
assertEquals(CommonCodeStyleSettings.END_OF_LINE, javaSettings.CLASS_BRACE_STYLE);
@@ -164,6 +192,43 @@
assertTrue(settings.FORMATTER_TAGS_ENABLED);
assertEquals("@off_tag", settings.FORMATTER_OFF_TAG);
assertEquals("@on_tag", settings.FORMATTER_ON_TAG);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.FIELD_ANNOTATION_WRAP);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.METHOD_ANNOTATION_WRAP);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.VARIABLE_ANNOTATION_WRAP);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.PARAMETER_ANNOTATION_WRAP);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.CLASS_ANNOTATION_WRAP);
+ assertTrue(javaSettings.ALIGN_MULTILINE_ARRAY_INITIALIZER_EXPRESSION);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.ARRAY_INITIALIZER_WRAP);
+ assertTrue(javaSettings.ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE);
+ assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.CALL_PARAMETERS_WRAP);
+ assertFalse(javaSettings.CALL_PARAMETERS_LPAREN_ON_NEXT_LINE);
+ assertTrue(javaSettings.ALIGN_MULTILINE_EXTENDS_LIST);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.EXTENDS_KEYWORD_WRAP);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.EXTENDS_LIST_WRAP);
+ assertTrue(javaSettings.ALIGN_MULTILINE_ASSIGNMENT);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.ASSIGNMENT_WRAP);
+ assertFalse(javaSettings.ALIGN_MULTILINE_PARAMETERS);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.METHOD_PARAMETERS_WRAP);
+ assertTrue(javaSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE);
+ assertTrue(javaSettings.ALIGN_MULTILINE_BINARY_OPERATION);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.BINARY_OPERATION_WRAP);
+ assertTrue(javaSettings.ALIGN_MULTILINE_THROWS_LIST);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.THROWS_KEYWORD_WRAP);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.THROWS_LIST_WRAP);
+ assertFalse(javaSettings.ALIGN_MULTILINE_RESOURCES);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.RESOURCE_LIST_WRAP);
+ assertFalse(javaSettings.RESOURCE_LIST_LPAREN_ON_NEXT_LINE);
+ assertEquals(CommonCodeStyleSettings.WRAP_ON_EVERY_ITEM | CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.METHOD_CALL_CHAIN_WRAP);
+ assertTrue(javaSettings.ALIGN_MULTILINE_CHAINED_METHODS);
+ assertEquals(CommonCodeStyleSettings.WRAP_AS_NEEDED, javaSettings.TERNARY_OPERATION_WRAP);
+ assertTrue(javaSettings.ALIGN_MULTILINE_TERNARY_OPERATION);
+ assertEquals(2, javaSettings.BLANK_LINES_AFTER_CLASS_HEADER);
+ assertEquals(2, javaSettings.BLANK_LINES_AFTER_ANONYMOUS_CLASS_HEADER);
+ assertEquals(3, javaSettings.BLANK_LINES_AROUND_CLASS);
+ assertEquals(5, javaSettings.KEEP_BLANK_LINES_IN_CODE);
+ assertEquals(5, javaSettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
+ assertEquals(5, javaSettings.KEEP_BLANK_LINES_BEFORE_RBRACE);
}
finally {
inputStream.close();
diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java
index 76f7233..5a85d72 100644
--- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java
+++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/GenerateToStringWorker.java
@@ -19,6 +19,7 @@
*/
package org.jetbrains.generate.tostring;
+import com.intellij.codeInsight.hint.HintManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
@@ -159,8 +160,18 @@
// create psi newMethod named toString()
final JVMElementFactory topLevelFactory = JVMElementFactories.getFactory(clazz.getLanguage(), clazz.getProject());
- PsiMethod newMethod = topLevelFactory.createMethodFromText(template.getMethodSignature() + " { " + body + " }", clazz);
- CodeStyleManager.getInstance(clazz.getProject()).reformat(newMethod);
+ if (topLevelFactory == null) {
+ return null;
+ }
+ PsiMethod newMethod;
+ try {
+ newMethod = topLevelFactory.createMethodFromText(template.getMethodSignature() + " { " + body + " }", clazz);
+ CodeStyleManager.getInstance(clazz.getProject()).reformat(newMethod);
+ } catch (IncorrectOperationException ignore) {
+ HintManager.getInstance().showErrorHint(editor, "'toString()' method could not be created from template '" +
+ template.getFileName() + '\'');
+ return null;
+ }
// insertNewMethod conflict resolution policy (add/replace, duplicate, cancel)
PsiMethod existingMethod = clazz.findMethodBySignature(newMethod, false);
diff --git a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/view/MethodExistsDialog.java b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/view/MethodExistsDialog.java
index 2bbd997..8547ac5 100644
--- a/plugins/generate-tostring/src/org/jetbrains/generate/tostring/view/MethodExistsDialog.java
+++ b/plugins/generate-tostring/src/org/jetbrains/generate/tostring/view/MethodExistsDialog.java
@@ -21,8 +21,6 @@
import org.jetbrains.generate.tostring.config.DuplicatePolicy;
import org.jetbrains.generate.tostring.config.ReplacePolicy;
-import javax.swing.*;
-
/**
* This is a dialog when the <code>toString()</code> method already exists.
* <p/>
@@ -52,11 +50,13 @@
*/
public static ConflictResolutionPolicy showDialog(String targetMethodName) {
int exit = Messages.showYesNoCancelDialog("Replace existing " + targetMethodName + " method", "Method Already Exists", Messages.getQuestionIcon());
- if (exit == JOptionPane.CLOSED_OPTION || exit == JOptionPane.CANCEL_OPTION) {
+ if (exit == Messages.CANCEL) {
return CancelPolicy.getInstance();
- } else if (exit == JOptionPane.YES_OPTION) {
+ }
+ if (exit == Messages.YES) {
return ReplacePolicy.getInstance();
- } else if (exit == JOptionPane.NO_OPTION) {
+ }
+ if (exit == Messages.NO) {
return DuplicatePolicy.getInstance();
}
diff --git a/plugins/git4idea/remote-servers-git/remote-servers-git.iml b/plugins/git4idea/remote-servers-git/remote-servers-git.iml
index 07e0637..b9f6138 100644
--- a/plugins/git4idea/remote-servers-git/remote-servers-git.iml
+++ b/plugins/git4idea/remote-servers-git/remote-servers-git.iml
@@ -4,7 +4,6 @@
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
- <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudBundle.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudBundle.java
deleted file mode 100644
index b203653..0000000
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudBundle.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.intellij.remoteServer.util;
-
-import com.intellij.CommonBundle;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.PropertyKey;
-
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.util.ResourceBundle;
-
-/**
- * @author michael.golubev
- */
-public class CloudBundle {
-
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls private static final String BUNDLE = "resources.cloud";
-
- private CloudBundle() {
-
- }
-
- public static String getText(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
- if (bundle == null) {
- bundle = ResourceBundle.getBundle(BUNDLE);
- ourBundle = new SoftReference<ResourceBundle>(bundle);
- }
- return bundle;
- }
-}
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
new file mode 100644
index 0000000..155e7e2
--- /dev/null
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentChecker.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.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;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.remoteServer.agent.util.CloudGitApplication;
+import com.intellij.remoteServer.configuration.RemoteServer;
+import com.intellij.remoteServer.configuration.ServerConfigurationBase;
+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;
+
+/**
+ * @author michael.golubev
+ */
+public class CloudGitDeploymentChecker<
+ T extends CloudDeploymentNameConfiguration,
+ SC extends ServerConfigurationBase,
+ SR extends CloudMultiSourceServerRuntimeInstance<T, ?, ?, ?>> {
+
+ private GitRepositoryManager myGitRepositoryManager;
+ private Git myGit;
+
+ private final DeploymentSource myDeploymentSource;
+ private final RemoteServer<SC> myServer;
+ private final CloudDeploymentNameEditor<T> mySettingsEditor;
+
+ public CloudGitDeploymentChecker(DeploymentSource deploymentSource,
+ RemoteServer<SC> server,
+ CloudDeploymentNameEditor<T> settingsEditor) {
+ myDeploymentSource = deploymentSource;
+ myServer = server;
+ mySettingsEditor = settingsEditor;
+ }
+
+ public void checkGitUrl(final T settings, Pattern gitUrlPattern) throws ConfigurationException {
+ if (!(myDeploymentSource instanceof ModuleDeploymentSource)) {
+ return;
+ }
+
+ ModuleDeploymentSource moduleSource = (ModuleDeploymentSource)myDeploymentSource;
+ Module module = moduleSource.getModule();
+ if (module == null) {
+ return;
+ }
+
+ File contentRootFile = myDeploymentSource.getFile();
+ if (contentRootFile == null) {
+ return;
+ }
+
+ final Project project = module.getProject();
+
+ 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) {
+ return;
+ }
+
+ GitRepository repository = myGitRepositoryManager.getRepositoryForRoot(contentRoot);
+ if (repository == null) {
+ return;
+ }
+
+
+ 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) {
+ return;
+ }
+
+
+ RuntimeConfigurationWarning warning =
+ new RuntimeConfigurationWarning("Cloud Git URL found in repository, but it doesn't match the run configuration");
+
+ warning.setQuickFix(new Runnable() {
+
+ @Override
+ public void run() {
+ CloudGitApplication application
+ = new CloudConnectionTask<CloudGitApplication, SC, T, SR>(project, "Searching for application", myServer) {
+
+ @Override
+ protected CloudGitApplication run(SR serverRuntime) throws ServerRuntimeException {
+ CloudGitDeploymentRuntime deploymentRuntime
+ = (CloudGitDeploymentRuntime)serverRuntime.createDeploymentRuntime(myDeploymentSource, settings, project);
+ return deploymentRuntime.findApplication4Repository();
+ }
+ }.performSync();
+
+ if (application == null) {
+ Messages.showErrorDialog(mySettingsEditor.getComponent(), "No application matching repository URL(s) found in account");
+ }
+ else {
+ T fixedSettings = mySettingsEditor.getFactory().create();
+ fixedSettings.setDefaultDeploymentName(false);
+ fixedSettings.setDeploymentName(application.getName());
+ mySettingsEditor.resetFrom(fixedSettings);
+ }
+ }
+ });
+
+ throw warning;
+ }
+}
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
index 41bc988..d308ad1 100644
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitDeploymentRuntime.java
@@ -1,31 +1,20 @@
package com.intellij.remoteServer.util;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.remoteServer.agent.util.CloudGitAgent;
-import com.intellij.remoteServer.agent.util.CloudGitAgentDeployment;
import com.intellij.remoteServer.agent.util.CloudGitApplication;
-import com.intellij.remoteServer.agent.util.CloudLoggingHandler;
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
-import com.intellij.remoteServer.configuration.deployment.ModuleDeploymentSource;
-import com.intellij.remoteServer.runtime.ServerTaskExecutor;
import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
-import com.intellij.remoteServer.runtime.deployment.DeploymentRuntime;
import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
-import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
-import com.intellij.remoteServer.runtime.log.LoggingHandler;
-import com.intellij.util.ThrowableRunnable;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.concurrency.Semaphore;
import git4idea.GitUtil;
import git4idea.actions.GitInit;
@@ -33,203 +22,77 @@
import git4idea.repo.GitRemote;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
+import git4idea.util.GitFileUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
/**
* @author michael.golubev
*/
-public abstract class CloudGitDeploymentRuntime<DC extends CloudDeploymentNameConfiguration,
- AD extends CloudGitAgentDeployment,
- A extends CloudGitAgent<?, AD>> extends DeploymentRuntime {
+public class CloudGitDeploymentRuntime extends CloudDeploymentRuntime {
private static final Logger LOG = Logger.getInstance("#" + CloudGitDeploymentRuntime.class.getName());
- private final String myApplicationName;
- private final CloudConfigurationBase myConfiguration;
- private final Project myProject;
private final GitRepositoryManager myGitRepositoryManager;
private final Git myGit;
private final VirtualFile myContentRoot;
- private final File myContentRootFile;
- private final AgentTaskExecutor myAgentTaskExecutor;
- private final String myPresentableName;
- private final CloudLoggingHandler myLoggingHandler;
- private final ServerTaskExecutor myTasksExecutor;
- private final AD myDeployment;
+ private final File myRepositoryRootFile;
- private final DeploymentLogManager myLogManager;
- private final String myRemoteName;
+ private final String myDefaultRemoteName;
+ private String myRemoteName;
private final String myCloudName;
private GitRepository myRepository;
- public CloudGitDeploymentRuntime(CloudConfigurationBase serverConfiguration,
- A agent,
- ServerTaskExecutor taskExecutor,
- DeploymentTask<DC> task,
- AgentTaskExecutor agentTaskExecutor,
- @Nullable DeploymentLogManager logManager,
- CloudDeploymentNameProvider deploymentNameProvider,
- String remoteName,
+ public CloudGitDeploymentRuntime(CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentSource source,
+ File repositoryRoot,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> task,
+ DeploymentLogManager logManager,
+ String defaultRemoteName,
String cloudName) throws ServerRuntimeException {
- myConfiguration = serverConfiguration;
- myTasksExecutor = taskExecutor;
- myLogManager = logManager;
+ super(serverRuntime, source, task, logManager);
- myRemoteName = remoteName;
+ myDefaultRemoteName = defaultRemoteName;
myCloudName = cloudName;
- DeploymentSource deploymentSource = task.getSource();
- if (!(deploymentSource instanceof ModuleDeploymentSource)) {
- throw new ServerRuntimeException("Module deployment source is the only supported");
- }
+ myRepositoryRootFile = repositoryRoot;
- ModuleDeploymentSource moduleDeploymentSource = (ModuleDeploymentSource)deploymentSource;
- Module module = moduleDeploymentSource.getModule();
- if (module == null) {
- throw new ServerRuntimeException("Module not found: " + moduleDeploymentSource.getModulePointer().getModuleName());
- }
-
- VirtualFile contentRoot = moduleDeploymentSource.getContentRoot();
- LOG.assertTrue(contentRoot != null, "Content root is not found");
+ VirtualFile contentRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(myRepositoryRootFile);
+ LOG.assertTrue(contentRoot != null, "Repository root is not found");
myContentRoot = contentRoot;
- File contentRootFile = moduleDeploymentSource.getFile();
- LOG.assertTrue(contentRootFile != null, "Content root file is not found");
- myContentRootFile = contentRootFile;
-
- myProject = task.getProject();
- myGitRepositoryManager = GitUtil.getRepositoryManager(myProject);
+ myGitRepositoryManager = GitUtil.getRepositoryManager(getProject());
myGit = ServiceManager.getService(Git.class);
if (myGit == null) {
throw new ServerRuntimeException("Can't initialize GIT");
}
-
- myAgentTaskExecutor = agentTaskExecutor;
- myLoggingHandler = logManager == null ? new CloudSilentLoggingHandlerImpl() : new CloudLoggingHandlerImpl(logManager);
-
- myPresentableName = deploymentSource.getPresentableName();
-
- DC deploymentConfiguration = task.getConfiguration();
- myApplicationName = deploymentConfiguration.isDefaultDeploymentName()
- ? deploymentNameProvider.getDeploymentName(deploymentSource)
- : deploymentConfiguration.getDeploymentName();
-
- myDeployment = agent.createDeployment(getApplicationName(), myLoggingHandler);
- }
-
- public AgentTaskExecutor getAgentTaskExecutor() {
- return myAgentTaskExecutor;
- }
-
- public AD getDeployment() {
- return myDeployment;
- }
-
- public void deploy(ServerRuntimeInstance.DeploymentOperationCallback callback) {
- try {
- deploy();
- callback.succeeded(this);
- }
- catch (ServerRuntimeException e) {
- callback.errorOccurred(e.getMessage());
- }
- }
-
- public void deploy() throws ServerRuntimeException {
- VirtualFile contentRoot = getContentRoot();
-
- CloudGitApplication application = findApplication();
- if (application == null) {
- application = createApplication();
- }
-
- GitRepository repository = findRepository();
- if (repository == null) {
- myLoggingHandler.println("Initializing git repository...");
- GitCommandResult gitInitResult = getGit().init(getProject(), contentRoot, createGitLineHandlerListener());
- checkGitResult(gitInitResult);
-
- refreshApplicationRepository();
-
- repository = getRepository();
- }
-
- GitRemote gitRemote = GitUtil.findRemoteByName(repository, getRemoteName());
- if (gitRemote == null) {
- addGitRemote(application);
- }
- else if (!gitRemote.getUrls().contains(application.getGitUrl())) {
- resetGitRemote(application);
- }
-
- try {
- GitSimpleHandler handler = new GitSimpleHandler(getProject(), contentRoot, GitCommand.ADD);
- handler.setSilent(false);
- handler.addParameters(".");
- handler.run();
- }
- catch (VcsException e) {
- throw new ServerRuntimeException(e);
- }
-
- try {
- if (GitUtil.hasLocalChanges(true, getProject(), contentRoot)) {
- GitSimpleHandler handler = new GitSimpleHandler(getProject(), contentRoot, GitCommand.COMMIT);
- handler.setSilent(false);
- handler.addParameters("-a");
- handler.addParameters("-m", "Deploy");
- handler.endOptions();
- handler.run();
- }
- }
- catch (VcsException e) {
- throw new ServerRuntimeException(e);
- }
-
- repository.update();
-
- pushApplication(getRemoteName(), application.getGitUrl());
-
- if (myLogManager != null) {
- LoggingHandler loggingHandler = myLogManager.getMainLoggingHandler();
- loggingHandler.print("Application is available at ");
- loggingHandler.printHyperlink(application.getWebUrl());
- loggingHandler.print("\n");
- }
}
@Override
- public void undeploy(final @NotNull UndeploymentTaskCallback callback) {
- myTasksExecutor.submit(new ThrowableRunnable<Exception>() {
-
- @Override
- public void run() throws Exception {
- try {
- undeploy();
- callback.succeeded();
- }
- catch (ServerRuntimeException e) {
- callback.errorOccurred(e.getMessage());
- }
- }
- }, callback);
+ public CloudGitApplication deploy() throws ServerRuntimeException {
+ CloudGitApplication application = findOrCreateApplication();
+ GitRepository repository = findOrCreateRepository();
+ addOrResetGitRemote(application, repository);
+ add();
+ commit();
+ repository.update();
+ pushApplication(application);
+ return application;
}
public void undeploy() throws ServerRuntimeException {
- if (!confirmUndeploy()) {
- throw new ServerRuntimeException("Undeploy cancelled");
- }
- myAgentTaskExecutor.execute(new Computable<Object>() {
+ getAgentTaskExecutor().execute(new Computable<Object>() {
@Override
public Object compute() {
- myDeployment.deleteApplication();
+ getDeployment().deleteApplication();
return null;
}
});
@@ -239,6 +102,47 @@
return findApplication() != null;
}
+ public CloudGitApplication findOrCreateApplication() throws ServerRuntimeException {
+ CloudGitApplication application = findApplication();
+ if (application == null) {
+ application = createApplication();
+ }
+ return application;
+ }
+
+ public void addOrResetGitRemote(CloudGitApplication application, GitRepository repository) throws ServerRuntimeException {
+ String gitUrl = application.getGitUrl();
+ if (myRemoteName == null) {
+ for (GitRemote gitRemote : repository.getRemotes()) {
+ if (gitRemote.getUrls().contains(gitUrl)) {
+ myRemoteName = gitRemote.getName();
+ return;
+ }
+ }
+ }
+ GitRemote gitRemote = GitUtil.findRemoteByName(repository, getRemoteName());
+ if (gitRemote == null) {
+ addGitRemote(application);
+ }
+ else if (!gitRemote.getUrls().contains(gitUrl)) {
+ resetGitRemote(application);
+ }
+ }
+
+ public GitRepository findOrCreateRepository() throws ServerRuntimeException {
+ GitRepository repository = findRepository();
+ if (repository == null) {
+ getLoggingHandler().println("Initializing git repository...");
+ GitCommandResult gitInitResult = getGit().init(getProject(), getRepositoryRoot(), createGitLineHandlerListener());
+ checkGitResult(gitInitResult);
+
+ refreshApplicationRepository();
+
+ repository = getRepository();
+ }
+ return repository;
+ }
+
public void downloadExistingApplication() throws ServerRuntimeException {
CloudGitApplication application = findApplication();
if (application == null) {
@@ -251,24 +155,16 @@
refreshContentRoot();
}
- protected Project getProject() {
- return myProject;
- }
-
- private String getApplicationName() {
- return myApplicationName;
- }
-
- private Git getGit() {
+ protected Git getGit() {
return myGit;
}
- protected VirtualFile getContentRoot() {
+ protected VirtualFile getRepositoryRoot() {
return myContentRoot;
}
- private File getContentRootFile() {
- return myContentRootFile;
+ protected File getRepositoryRootFile() {
+ return myRepositoryRootFile;
}
protected static void checkGitResult(GitCommandResult commandResult) throws ServerRuntimeException {
@@ -289,7 +185,7 @@
@Override
public void onLineAvailable(String line, Key outputType) {
- myLoggingHandler.println(line);
+ getLoggingHandler().println(line);
}
};
}
@@ -308,7 +204,7 @@
String failMessage)
throws ServerRuntimeException {
try {
- final GitSimpleHandler handler = new GitSimpleHandler(myProject, myContentRoot, GitCommand.REMOTE);
+ final GitSimpleHandler handler = new GitSimpleHandler(getProject(), myContentRoot, GitCommand.REMOTE);
handler.setSilent(false);
handler.addParameters(subCommand, remoteName, application.getGitUrl());
handler.run();
@@ -332,12 +228,12 @@
}
protected void refreshApplicationRepository() {
- GitInit.refreshAndConfigureVcsMappings(myProject, getContentRoot(), getContentRootFile().getAbsolutePath());
+ GitInit.refreshAndConfigureVcsMappings(getProject(), getRepositoryRoot(), getRepositoryRootFile().getAbsolutePath());
}
- protected void pushApplication(String remoteName, String gitUrl) throws ServerRuntimeException {
+ protected void pushApplication(@NotNull CloudGitApplication application) throws ServerRuntimeException {
GitCommandResult gitPushResult
- = getGit().push(getRepository(), remoteName, gitUrl, "master:master", createGitLineHandlerListener());
+ = getGit().push(getRepository(), getRemoteName(), application.getGitUrl(), "master:master", createGitLineHandlerListener());
checkGitResult(gitPushResult);
}
@@ -351,7 +247,7 @@
}
protected void fetch() throws ServerRuntimeException {
- final VirtualFile contentRoot = getContentRoot();
+ final VirtualFile contentRoot = getRepositoryRoot();
GitRepository repository = getRepository();
final GitLineHandler fetchHandler = new GitLineHandler(getProject(), contentRoot, GitCommand.FETCH);
fetchHandler.setSilent(false);
@@ -362,8 +258,32 @@
repository.update();
}
+ protected void add() throws ServerRuntimeException {
+ try {
+ GitFileUtils.addFiles(getProject(), myContentRoot, myContentRoot);
+ }
+ catch (VcsException e) {
+ throw new ServerRuntimeException(e);
+ }
+ }
+
+ protected void commit() throws ServerRuntimeException {
+ try {
+ if (GitUtil.hasLocalChanges(true, getProject(), myContentRoot)) {
+ GitSimpleHandler handler = new GitSimpleHandler(getProject(), myContentRoot, GitCommand.COMMIT);
+ handler.setSilent(false);
+ handler.addParameters("-m", "Deploy");
+ handler.endOptions();
+ handler.run();
+ }
+ }
+ catch (VcsException e) {
+ throw new ServerRuntimeException(e);
+ }
+ }
+
protected void performRemoteGitTask(final GitLineHandler handler, String title) throws ServerRuntimeException {
- final GitTask task = new GitTask(myProject, handler, title);
+ final GitTask task = new GitTask(getProject(), handler, title);
task.setProgressAnalyzer(new GitStandardProgressAnalyzer());
final Semaphore semaphore = new Semaphore();
@@ -386,7 +306,7 @@
@Override
protected void onFailure() {
for (VcsException error : handler.errors()) {
- myLoggingHandler.println(error.toString());
+ getLoggingHandler().println(error.toString());
if (errorRef.isNull()) {
errorRef.set(new ServerRuntimeException(error));
}
@@ -407,35 +327,15 @@
@Override
public void run() {
- getContentRoot().refresh(false, true);
+ getRepositoryRoot().refresh(false, true);
}
});
}
- protected boolean confirmUndeploy() {
- final Ref<Boolean> confirmed = new Ref<Boolean>(false);
- ApplicationManager.getApplication().invokeAndWait(new Runnable() {
-
- @Override
- public void run() {
- String title = CloudBundle.getText("cloud.undeploy.confirm.title");
- while (true) {
- String password = Messages.showPasswordDialog(CloudBundle.getText("cloud.undeploy.confirm.message", myPresentableName), title);
- if (password == null) {
- return;
- }
- if (password.equals(myConfiguration.getPassword())) {
- confirmed.set(true);
- return;
- }
- Messages.showErrorDialog(CloudBundle.getText("cloud.undeploy.confirm.password.incorrect"), title);
- }
- }
- }, ModalityState.defaultModalityState());
- return confirmed.get();
- }
-
private String getRemoteName() {
+ if (myRemoteName == null) {
+ myRemoteName = myDefaultRemoteName;
+ }
return myRemoteName;
}
@@ -444,21 +344,38 @@
}
protected CloudGitApplication findApplication() throws ServerRuntimeException {
- return myAgentTaskExecutor.execute(new Computable<CloudGitApplication>() {
+ return getAgentTaskExecutor().execute(new Computable<CloudGitApplication>() {
@Override
public CloudGitApplication compute() {
- return myDeployment.findApplication();
+ return getDeployment().findApplication();
}
});
}
protected CloudGitApplication createApplication() throws ServerRuntimeException {
- return myAgentTaskExecutor.execute(new Computable<CloudGitApplication>() {
+ return getAgentTaskExecutor().execute(new Computable<CloudGitApplication>() {
@Override
public CloudGitApplication compute() {
- return myDeployment.createApplication();
+ return getDeployment().createApplication();
+ }
+ });
+ }
+
+ public CloudGitApplication findApplication4Repository() throws ServerRuntimeException {
+ final List<String> repositoryUrls = new ArrayList<String>();
+ for (GitRemote remote : getRepository().getRemotes()) {
+ for (String url : remote.getUrls()) {
+ repositoryUrls.add(url);
+ }
+ }
+
+ return getAgentTaskExecutor().execute(new Computable<CloudGitApplication>() {
+
+ @Override
+ public CloudGitApplication compute() {
+ return getDeployment().findApplication4Repository(ArrayUtil.toStringArray(repositoryUrls));
}
});
}
@@ -485,7 +402,7 @@
File cloneDir = cloneToTemp(gitUrl);
try {
- FileUtil.copyDir(cloneDir, getContentRootFile());
+ FileUtil.copyDir(cloneDir, getRepositoryRootFile());
}
catch (IOException e) {
throw new ServerRuntimeException(e);
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitServerRuntimeInstanceBase.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitServerRuntimeInstanceBase.java
deleted file mode 100644
index 8423be8..0000000
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudGitServerRuntimeInstanceBase.java
+++ /dev/null
@@ -1,218 +0,0 @@
-package com.intellij.remoteServer.util;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Computable;
-import com.intellij.remoteServer.agent.RemoteAgentManager;
-import com.intellij.remoteServer.agent.util.CloudAgentConfigBase;
-import com.intellij.remoteServer.agent.util.CloudAgentLogger;
-import com.intellij.remoteServer.agent.util.CloudGitAgent;
-import com.intellij.remoteServer.agent.util.DeploymentData;
-import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
-import com.intellij.remoteServer.impl.configuration.deployment.DeployToServerRunConfiguration;
-import com.intellij.remoteServer.runtime.ServerConnector;
-import com.intellij.remoteServer.runtime.ServerTaskExecutor;
-import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
-import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
-import com.intellij.remoteServer.runtime.deployment.ServerRuntimeInstance;
-import com.intellij.util.ThrowableRunnable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * @author michael.golubev
- */
-
-public abstract class CloudGitServerRuntimeInstanceBase<
- DC extends CloudDeploymentNameConfiguration,
- AC extends CloudAgentConfigBase,
- A extends CloudGitAgent<AC, ?>,
- SC extends AC,
- DR extends CloudGitDeploymentRuntime>
- extends CloudServerRuntimeInstance<DC>
- implements CloudDeploymentNameProvider {
-
- private static final Logger LOG = Logger.getInstance("#" + CloudGitServerRuntimeInstanceBase.class.getName());
-
- private final A myAgent;
- private final AgentTaskExecutor myAgentTaskExecutor;
-
- private final SC myConfiguration;
- private final ServerTaskExecutor myTasksExecutor;
-
- public CloudGitServerRuntimeInstanceBase(SC configuration,
- ServerTaskExecutor tasksExecutor,
- List<File> libraries,
- List<Class<?>> commonJarClasses,
- String specificsModuleName,
- String specificJarPath,
- Class<A> agentInterface,
- String agentClassName) throws Exception {
- myConfiguration = configuration;
- myTasksExecutor = tasksExecutor;
-
- RemoteAgentManager agentManager = RemoteAgentManager.getInstance();
- myAgent = agentManager.createAgent(agentManager.createReflectiveThreadProxyFactory(getClass().getClassLoader()),
- libraries,
- commonJarClasses,
- specificsModuleName,
- specificJarPath,
- agentInterface,
- agentClassName,
- getClass());
- myAgentTaskExecutor = new AgentTaskExecutor();
- }
-
- @NotNull
- @Override
- public String getDeploymentName(@NotNull DeploymentSource source) {
- return CloudDeploymentNameProvider.DEFAULT_NAME_PROVIDER.getDeploymentName(source);
- }
-
- public void connect(final ServerConnector.ConnectionCallback<DC> callback) {
- myAgentTaskExecutor.execute(new Computable() {
-
- @Override
- public Object compute() {
- doConnect(myConfiguration,
- new CloudAgentLogger() {
-
- @Override
- public void debugEx(Exception e) {
- LOG.debug(e);
- }
-
- @Override
- public void debug(String message) {
- LOG.debug(message);
- }
- });
- return null;
- }
- }, new CallbackWrapper() {
-
- @Override
- public void onSuccess(Object result) {
- callback.connected(CloudGitServerRuntimeInstanceBase.this);
- }
-
- @Override
- public void onError(String message) {
- callback.errorOccurred(message);
- }
- }
- );
- }
-
- @Override
- public void deploy(@NotNull final DeploymentTask<DC> task,
- @NotNull final DeploymentLogManager logManager,
- @NotNull final ServerRuntimeInstance.DeploymentOperationCallback callback) {
- myTasksExecutor.submit(new ThrowableRunnable<Exception>() {
-
- @Override
- public void run() throws Exception {
- createDeploymentRuntime(myConfiguration, myTasksExecutor, task, logManager).deploy(callback);
- }
- }, callback);
- }
-
- @Override
- public void computeDeployments(@NotNull final ServerRuntimeInstance.ComputeDeploymentsCallback callback) {
- myTasksExecutor.submit(new ThrowableRunnable<Exception>() {
- @Override
- public void run() throws Exception {
- myAgentTaskExecutor.execute(new Computable<DeploymentData[]>() {
-
- @Override
- public DeploymentData[] compute() {
- return myAgent.getDeployments();
- }
- },
- new CallbackWrapper<DeploymentData[]>() {
-
- @Override
- public void onSuccess(DeploymentData[] deployments) {
- for (DeploymentData deployment : deployments) {
- callback.addDeployment(deployment.getName());
- }
- callback.succeeded();
- }
-
- @Override
- public void onError(String message) {
- callback.errorOccurred(message);
- }
- }
- );
- }
- }, callback);
- }
-
- @Override
- public void disconnect() {
- myTasksExecutor.submit(new Runnable() {
-
- @Override
- public void run() {
- myAgent.disconnect();
- }
- });
- }
-
- @Override
- public ServerTaskExecutor getTaskExecutor() {
- return myTasksExecutor;
- }
-
- protected final A getAgent() {
- return myAgent;
- }
-
- protected final AgentTaskExecutor getAgentTaskExecutor() {
- return myAgentTaskExecutor;
- }
-
- public DR createDeploymentRuntime(final DeployToServerRunConfiguration<?, DC> runConfiguration)
- throws ServerRuntimeException {
- return createDeploymentRuntime(myConfiguration,
- myTasksExecutor,
- new DeploymentTask<DC>() {
-
- @NotNull
- @Override
- public DeploymentSource getSource() {
- return runConfiguration.getDeploymentSource();
- }
-
- @NotNull
- @Override
- public DC getConfiguration() {
- return runConfiguration.getDeploymentConfiguration();
- }
-
- @NotNull
- @Override
- public Project getProject() {
- return runConfiguration.getProject();
- }
-
- @Override
- public boolean isDebugMode() {
- return false;
- }
- },
- null
- );
- }
-
- protected abstract DR createDeploymentRuntime(SC configuration,
- ServerTaskExecutor serverTaskExecutor,
- DeploymentTask<DC> deploymentTask,
- @Nullable DeploymentLogManager logManager) throws ServerRuntimeException;
-
- protected abstract void doConnect(SC configuration, CloudAgentLogger logger);
-}
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudModuleDeploymentRuntimeProviderBase.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudModuleDeploymentRuntimeProviderBase.java
new file mode 100644
index 0000000..748866a
--- /dev/null
+++ b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudModuleDeploymentRuntimeProviderBase.java
@@ -0,0 +1,78 @@
+/*
+ * 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.remoteServer.util;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.module.ModulePointerManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
+import com.intellij.remoteServer.configuration.deployment.ModuleDeploymentSource;
+import com.intellij.remoteServer.impl.configuration.deployment.ModuleDeploymentSourceImpl;
+import com.intellij.remoteServer.runtime.deployment.DeploymentLogManager;
+import com.intellij.remoteServer.runtime.deployment.DeploymentTask;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author michael.golubev
+ */
+public abstract class CloudModuleDeploymentRuntimeProviderBase implements CloudDeploymentRuntimeProvider {
+
+ private static final Logger LOG = Logger.getInstance("#" + CloudModuleDeploymentRuntimeProviderBase.class.getName());
+
+ @Override
+ public Collection<DeploymentSource> getDeploymentSources(Project project) {
+ List<DeploymentSource> result = new ArrayList<DeploymentSource>();
+ ModulePointerManager pointerManager = ModulePointerManager.getInstance(project);
+ for (Module module : ModuleManager.getInstance(project).getModules()) {
+ result.add(new ModuleDeploymentSourceImpl(pointerManager.create(module)));
+ }
+ return result;
+ }
+
+ @Override
+ public CloudDeploymentRuntime createDeploymentRuntime(DeploymentSource source,
+ CloudMultiSourceServerRuntimeInstance serverRuntime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager)
+ throws ServerRuntimeException {
+ if (!(source instanceof ModuleDeploymentSource)) {
+ return null;
+ }
+
+ ModuleDeploymentSource moduleSource = (ModuleDeploymentSource)source;
+ Module module = moduleSource.getModule();
+ if (module == null) {
+ throw new ServerRuntimeException("Module not found: " + moduleSource.getModulePointer().getModuleName());
+ }
+
+ File contentRootFile = source.getFile();
+ LOG.assertTrue(contentRootFile != null, "Content root file is not found");
+
+ return doCreateDeploymentRuntime(moduleSource, contentRootFile, serverRuntime, deploymentTask, logManager);
+ }
+
+ protected abstract CloudDeploymentRuntime doCreateDeploymentRuntime(ModuleDeploymentSource moduleSource,
+ File contentRootFile,
+ CloudMultiSourceServerRuntimeInstance runtime,
+ DeploymentTask<? extends CloudDeploymentNameConfiguration> deploymentTask,
+ DeploymentLogManager logManager) throws ServerRuntimeException;
+}
diff --git a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java b/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java
deleted file mode 100644
index 468a471..0000000
--- a/plugins/git4idea/remote-servers-git/src/com/intellij/remoteServer/util/CloudSupportConfigurableBase.java
+++ /dev/null
@@ -1,302 +0,0 @@
-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.notification.Notification;
-import com.intellij.notification.NotificationGroup;
-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.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;
-
-/**
- * @author michael.golubev
- */
-public abstract class CloudSupportConfigurableBase<
- SC extends CloudConfigurationBase,
- DC extends CloudDeploymentNameConfiguration,
- ST extends ServerType<SC>,
- SR extends CloudGitServerRuntimeInstanceBase<DC, ?, ?, ?, ?>>
- extends FrameworkSupportConfigurable {
-
- private final String myNotificationDisplayId;
- 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, String notificationDisplayId) {
- myModelProject = frameworkSupportModel.getProject();
- myCloudType = cloudType;
- myNotificationDisplayId = notificationDisplayId;
- }
-
- @Override
- public void dispose() {
- myServerConfigurable.disposeUIResources();
- }
-
- 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));
- }
-
- protected void reloadExistingApplications() {
- Collection<Deployment> deployments = new ConnectionTask<Collection<Deployment>>("Loading existing applications list", true, true) {
-
- @Override
- protected void run(final ServerConnection<DC> connection,
- final Semaphore semaphore,
- final AtomicReference<Collection<Deployment>> result) {
- connection.connectIfNeeded(new ServerConnector.ConnectionCallback<DC>() {
-
- @Override
- public void connected(@NotNull ServerRuntimeInstance<DC> serverRuntimeInstance) {
- connection.computeDeployments(new Runnable() {
-
- @Override
- public void run() {
- result.set(connection.getDeployments());
- semaphore.up();
- }
- });
- }
-
- @Override
- public void errorOccurred(@NotNull String errorMessage) {
- runtimeErrorOccurred(errorMessage);
- semaphore.up();
- }
- });
- }
-
- @Override
- protected Collection<Deployment> run(SR serverRuntimeInstance) throws ServerRuntimeException {
- return null;
- }
- }.perform();
-
- if (deployments == null) {
- return;
- }
-
- JComboBox existingComboBox = getExistingComboBox();
- existingComboBox.removeAllItems();
- for (Deployment deployment : deployments) {
- existingComboBox.addItem(deployment.getName());
- }
- }
-
- @Override
- public void onFrameworkSelectionChanged(boolean selected) {
- if (selected && !myInitialized) {
- myInitialized = true;
- initUI();
- updateApplicationUI();
- }
- }
-
- 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) {
- NotificationGroup notificationGroup = NotificationGroup.balloonGroup(myNotificationDisplayId);
- Notification notification = notificationGroup.createNotification(message, messageType);
- notification.notify(null);
- }
-
- protected void showErrorMessage(String errorMessage) {
- showMessage(errorMessage, MessageType.ERROR);
- }
-
- 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) {
- showErrorMessage(e.getMessage());
- 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;
- }
-
- protected void runOnModuleAdded(final Module module, final Runnable runnable) {
- if (myModelProject == null) {
- StartupManager.getInstance(module.getProject()).runWhenProjectIsInitialized(runnable);
- }
- else {
- MessageBusConnection connection = myModelProject.getMessageBus().connect(myModelProject);
- connection.subscribe(ProjectTopics.MODULES, new ModuleAdapter() {
-
- public void moduleAdded(Project project, Module addedModule) {
- if (addedModule == module) {
- runnable.run();
- }
- }
- });
- }
- }
-
- protected abstract JComboBox getExistingComboBox();
-
- protected abstract JComboBox getServerComboBox();
-
- protected abstract void updateApplicationUI();
-
- 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, boolean modal, boolean cancellable) {
- super(myModelProject, title, modal, cancellable);
- }
-
- public ConnectionTask(Module module, String title, boolean modal, boolean cancellable) {
- super(module.getProject(), title, modal, cancellable);
- }
-
- @Override
- protected RemoteServer<SC> getServer() {
- return CloudSupportConfigurableBase.this.getServer();
- }
- }
-}
diff --git a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java
index 507d1fc..f94cd29 100644
--- a/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java
+++ b/plugins/git4idea/rt/src/org/jetbrains/git4idea/ssh/SSHMainBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.BundleBase;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,20 @@
* The bundle for SSH messages
*/
public class SSHMainBundle {
- private static Reference<ResourceBundle> ourBundle;
- @NonNls
- private static final String BUNDLE = "org.jetbrains.git4idea.ssh.SSHMainBundle";
-
- private SSHMainBundle() { }
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return BundleBase.message(getBundle(), key, params);
}
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.git4idea.ssh.SSHMainBundle";
+
+ private SSHMainBundle() {
+ }
+
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/git4idea/src/META-INF/plugin.xml b/plugins/git4idea/src/META-INF/plugin.xml
index 62640bf..5bd07d3 100644
--- a/plugins/git4idea/src/META-INF/plugin.xml
+++ b/plugins/git4idea/src/META-INF/plugin.xml
@@ -45,7 +45,9 @@
<separator/>
<action id="Git.Fetch" class="git4idea.actions.GitFetch" text="Fetch"/>
<action id="Git.Pull" class="git4idea.actions.GitPull" text="Pull..." icon="AllIcons.Actions.CheckOut"/>
- <action id="Git.Push" class="git4idea.actions.GitPushAction" icon="AllIcons.Actions.Commit" text="Push..."/>
+ <action id="Git.Push" class="git4idea.actions.GitPushAction" icon="AllIcons.Actions.Commit" text="Push...">
+ <keyboard-shortcut first-keystroke="control shift K" keymap="$default"/>
+ </action>
<separator/>
<action id="Git.Rebase" class="git4idea.actions.GitRebase" text="Rebase..."/>
<action id="Git.Rebase.Abort" class="git4idea.actions.GitRebaseAbort" text="Abort Rebasing"/>
@@ -192,5 +194,4 @@
<extensionPoints>
<extensionPoint qualifiedName="Git4Idea.GitHttpAuthDataProvider" interface="git4idea.jgit.GitHttpAuthDataProvider"/>
</extensionPoints>
-
</idea-plugin>
diff --git a/plugins/git4idea/src/git4idea/GitTaskHandler.java b/plugins/git4idea/src/git4idea/GitTaskHandler.java
index c5269a2..7dac465 100644
--- a/plugins/git4idea/src/git4idea/GitTaskHandler.java
+++ b/plugins/git4idea/src/git4idea/GitTaskHandler.java
@@ -22,9 +22,11 @@
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsTaskHandler;
+import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
+import git4idea.branch.GitBranchUtil;
import git4idea.branch.GitBrancher;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
@@ -88,7 +90,7 @@
}
@Override
- public void switchToTask(TaskInfo taskInfo) {
+ public void switchToTask(TaskInfo taskInfo, Runnable invokeAfter) {
for (final String branchName : taskInfo.branches.keySet()) {
List<GitRepository> repositories = getRepositories(taskInfo.branches.get(branchName));
List<GitRepository> notFound = ContainerUtil.filter(repositories, new Condition<GitRepository>() {
@@ -102,7 +104,7 @@
}
repositories.removeAll(notFound);
if (!repositories.isEmpty()) {
- myBrancher.checkout(branchName, repositories, null);
+ myBrancher.checkout(branchName, repositories, invokeAfter);
}
}
}
@@ -144,6 +146,26 @@
return new TaskInfo(branches);
}
+ @Override
+ public TaskInfo[] getCurrentTasks() {
+ List<GitRepository> repositories = myRepositoryManager.getRepositories();
+ final List<String> names = ContainerUtil.map(repositories, new Function<GitRepository, String>() {
+ @Override
+ public String fun(GitRepository repository) {
+ return repository.getPresentableUrl();
+ }
+ });
+ Collection<String> branches = GitBranchUtil.getCommonBranches(repositories, true);
+ return ContainerUtil.map2Array(branches, TaskInfo.class, new Function<String, TaskInfo>() {
+ @Override
+ public TaskInfo fun(String branchName) {
+ MultiMap<String, String> map = new MultiMap<String, String>();
+ map.put(branchName, names);
+ return new TaskInfo(map);
+ }
+ });
+ }
+
private List<GitRepository> getRepositories(Collection<String> urls) {
final List<GitRepository> repositories = myRepositoryManager.getRepositories();
return ContainerUtil.mapNotNull(urls, new NullableFunction<String, GitRepository>() {
diff --git a/plugins/git4idea/src/git4idea/GitUtil.java b/plugins/git4idea/src/git4idea/GitUtil.java
index b507e4a..7204f61 100644
--- a/plugins/git4idea/src/git4idea/GitUtil.java
+++ b/plugins/git4idea/src/git4idea/GitUtil.java
@@ -23,7 +23,6 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -38,10 +37,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.UIUtil;
-import com.intellij.vcs.log.VcsLog;
-import com.intellij.vcs.log.VcsLogProvider;
import com.intellij.vcsUtil.VcsFileUtil;
import com.intellij.vcsUtil.VcsUtil;
import git4idea.branch.GitBranchUtil;
@@ -83,12 +79,6 @@
if (o2 == null) {
return 1;
}
- if (o1.getPresentableUrl() == null) {
- return -1;
- }
- if (o2.getPresentableUrl() == null) {
- return 1;
- }
return o1.getPresentableUrl().compareTo(o2.getPresentableUrl());
}
};
@@ -944,27 +934,4 @@
return !output.trim().isEmpty();
}
- /**
- * Report a warning that the given root has no associated GitRepositories.
- */
- public static void noRepositoryForRoot(@NotNull Logger log, @NotNull VirtualFile root, @NotNull Project project) {
- GitRepositoryManager repositoryManager = getRepositoryManager(project);
- ProjectLevelVcsManager vcsManager = ProjectLevelVcsManager.getInstance(project);
- List<VirtualFile> roots = Arrays.asList(vcsManager.getRootsUnderVcs(GitVcs.getInstance(project)));
- log.warn(String.format("Repository not found for root: %s. All roots: %s, all repositories: %s", root, roots,
- repositoryManager.getRepositories()));
- }
-
- /**
- * Checks if there are Git roots in the VCS log.
- */
- public static boolean logHasGitRoot(@NotNull VcsLog log) {
- return ContainerUtil.find(log.getLogProviders(), new Condition<VcsLogProvider>() {
- @Override
- public boolean value(VcsLogProvider logProvider) {
- return logProvider.getSupportedVcs().equals(GitVcs.getKey());
- }
- }) != null;
- }
-
}
diff --git a/plugins/git4idea/src/git4idea/MessageManager.java b/plugins/git4idea/src/git4idea/MessageManager.java
index 02d9f4b..28c28f3 100644
--- a/plugins/git4idea/src/git4idea/MessageManager.java
+++ b/plugins/git4idea/src/git4idea/MessageManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -32,11 +32,13 @@
return ServiceManager.getService(project, MessageManager.class);
}
+ @Messages.YesNoResult
public static int showYesNoDialog(Project project, String description, String title, String yesText, String noText, @Nullable Icon icon) {
return getInstance(project).doShowYesNoDialog(project, description, title, yesText, noText, icon);
}
@SuppressWarnings("MethodMayBeStatic")
+ @Messages.YesNoResult
protected int doShowYesNoDialog(Project project, String description, String title, String yesText, String noText, @Nullable Icon icon) {
return Messages.showYesNoDialog(project, description, title, yesText, noText, icon);
}
diff --git a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
index 16f5a41..39cfb2a 100644
--- a/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
+++ b/plugins/git4idea/src/git4idea/actions/GitLogSingleCommitAction.java
@@ -15,6 +15,7 @@
*/
package git4idea.actions;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.components.ServiceManager;
@@ -24,7 +25,7 @@
import com.intellij.vcs.log.VcsFullCommitDetails;
import com.intellij.vcs.log.VcsLog;
import com.intellij.vcs.log.VcsLogDataKeys;
-import git4idea.GitUtil;
+import git4idea.GitVcs;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import org.jetbrains.annotations.NotNull;
@@ -56,10 +57,10 @@
GitRepositoryManager repositoryManager = ServiceManager.getService(data.project, GitRepositoryManager.class);
final GitRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
if (repository == null) {
- GitUtil.noRepositoryForRoot(LOG, commit.getRoot(), data.project);
+ DvcsUtil.noVcsRepositoryForRoot(LOG, commit.getRoot(), data.project, repositoryManager, GitVcs.getInstance(data.project));
return;
}
-
+
actionPerformed(repository, commit);
}
@@ -83,7 +84,7 @@
}
boolean isValid() {
- return project != null && log != null && GitUtil.logHasGitRoot(log);
+ return project != null && log != null && DvcsUtil.logHasRootForVcs(log, GitVcs.getKey());
}
}
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
index 7c74823..0defd88 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUiHandlerImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -95,7 +95,7 @@
description.append(message).append("<br/>");
}
description.append(rollbackProposal);
- ok.set(Messages.OK == MessageManager.showYesNoDialog(myProject, XmlStringUtil.wrapInHtml(description), title,
+ ok.set(Messages.YES == MessageManager.showYesNoDialog(myProject, XmlStringUtil.wrapInHtml(description), title,
"Rollback", "Don't rollback", Messages.getErrorIcon()));
}
});
@@ -133,7 +133,7 @@
operationName, rollbackProposal);
// suppressing: this message looks ugly if capitalized by words
//noinspection DialogTitleCapitalization
- ok.set(Messages.OK == MessageManager.showYesNoDialog(myProject, description, unmergedFilesErrorTitle(operationName),
+ ok.set(Messages.YES == MessageManager.showYesNoDialog(myProject, description, unmergedFilesErrorTitle(operationName),
"Rollback", "Don't rollback", Messages.getErrorIcon()));
}
});
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java
index c1832f6..a41a172 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchUtil.java
@@ -20,13 +20,8 @@
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.diagnostic.Logger;
-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.fileEditor.FileEditorManager;
-import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.ui.Messages;
@@ -36,9 +31,6 @@
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.wm.StatusBar;
-import com.intellij.openapi.wm.WindowManager;
-import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.Hash;
import com.intellij.vcsUtil.VcsUtil;
@@ -50,7 +42,6 @@
import git4idea.repo.*;
import git4idea.ui.branch.GitMultiRootBranchConfig;
import git4idea.validators.GitNewBranchNameValidator;
-import org.intellij.images.editor.ImageFileEditor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -373,40 +364,10 @@
}
/**
- * Returns the currently selected file, based on which GitBranch components ({@link git4idea.ui.branch.GitBranchPopup}, {@link git4idea.ui.branch.GitBranchWidget})
- * will identify the current repository root.
- */
- @Nullable
- static VirtualFile getSelectedFile(@NotNull Project project) {
- StatusBar statusBar = WindowManager.getInstance().getStatusBar(project);
- final FileEditor fileEditor = StatusBarUtil.getCurrentFileEditor(project, statusBar);
- VirtualFile result = null;
- if (fileEditor != null) {
- if (fileEditor instanceof TextEditor) {
- Document document = ((TextEditor)fileEditor).getEditor().getDocument();
- result = FileDocumentManager.getInstance().getFile(document);
- } else if (fileEditor instanceof ImageFileEditor) {
- result = ((ImageFileEditor)fileEditor).getImageEditor().getFile();
- }
- }
-
- if (result == null) {
- final FileEditorManager manager = FileEditorManager.getInstance(project);
- if (manager != null) {
- Editor editor = manager.getSelectedTextEditor();
- if (editor != null) {
- result = FileDocumentManager.getInstance().getFile(editor.getDocument());
- }
- }
- }
- return result;
- }
-
- /**
* Guesses the Git root on which a Git action is to be invoked.
* <ol>
* <li>
- * Returns the root for the selected file. Selected file is determined by {@link #getSelectedFile(com.intellij.openapi.project.Project)}.
+ * Returns the root for the selected file. Selected file is determined by {@link DvcsUtil#getSelectedFile(com.intellij.openapi.project.Project)}.
* If selected file is unknown (for example, no file is selected in the Project View or Changes View and no file is open in the editor),
* continues guessing. Otherwise returns the Git root for the selected file. If the file is not under a known Git root,
* <code>null</code> will be returned - the file is definitely determined, but it is not under Git.
@@ -431,7 +392,7 @@
@Nullable
public static GitRepository getCurrentRepository(@NotNull Project project) {
GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
- VirtualFile file = getSelectedFile(project);
+ VirtualFile file = DvcsUtil.getSelectedFile(project);
VirtualFile root = getVcsRootOrGuess(project, file);
return manager.getRepositoryForRoot(root);
}
diff --git a/plugins/git4idea/src/git4idea/branch/GitBranchesCollection.java b/plugins/git4idea/src/git4idea/branch/GitBranchesCollection.java
index e3081f9..4f40fc6 100644
--- a/plugins/git4idea/src/git4idea/branch/GitBranchesCollection.java
+++ b/plugins/git4idea/src/git4idea/branch/GitBranchesCollection.java
@@ -17,9 +17,11 @@
import com.intellij.openapi.util.Condition;
import com.intellij.util.containers.ContainerUtil;
+import git4idea.GitBranch;
import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.Collection;
import java.util.Collections;
@@ -58,12 +60,25 @@
return Collections.unmodifiableCollection(myRemoteBranches);
}
- public GitLocalBranch findLocalBranch(@NotNull final String name) {
- return ContainerUtil.find(myLocalBranches, new Condition<GitLocalBranch>() {
+ @Nullable
+ public GitLocalBranch findLocalBranch(@NotNull String name) {
+ return findByName(myLocalBranches, name);
+ }
+
+ @Nullable
+ public GitBranch findBranchByName(@NotNull String name) {
+ GitLocalBranch branch = findByName(myLocalBranches, name);
+ return branch != null ? branch : findByName(myRemoteBranches, name);
+ }
+
+ @Nullable
+ private static <T extends GitBranch> T findByName(Collection<T> branches, @NotNull final String name) {
+ return ContainerUtil.find(branches, new Condition<T>() {
@Override
- public boolean value(GitLocalBranch branch) {
+ public boolean value(T branch) {
return name.equals(branch.getName());
}
});
}
+
}
diff --git a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java
index 1d63456..29f7bd7 100644
--- a/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java
+++ b/plugins/git4idea/src/git4idea/branch/GitDeleteRemoteBranchOperation.java
@@ -1,8 +1,16 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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 permissions and
+ * 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 git4idea.branch;
diff --git a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
index 7331fd7..d5c4b3f 100644
--- a/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
+++ b/plugins/git4idea/src/git4idea/checkin/GitCheckinEnvironment.java
@@ -16,13 +16,13 @@
package git4idea.checkin;
import com.intellij.CommonBundle;
+import com.intellij.dvcs.DvcsCommitAdditionalComponent;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.*;
@@ -33,7 +33,6 @@
import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.GuiUtils;
-import com.intellij.ui.NonFocusableCheckBox;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
@@ -61,8 +60,6 @@
import javax.swing.*;
import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;
@@ -131,7 +128,7 @@
}
}
}
- return joinOrNull(messages);
+ return DvcsUtil.joinMessagesOrNull(messages);
}
private static String loadMessage(@NotNull VirtualFile messageFile, @NotNull String encoding) throws IOException {
@@ -595,36 +592,18 @@
/**
* Checkin options for git
*/
- private class GitCheckinOptions implements CheckinChangeListSpecificComponent {
+ private class GitCheckinOptions extends DvcsCommitAdditionalComponent implements CheckinChangeListSpecificComponent {
private final GitVcs myVcs;
/**
- * A container panel
- */
- private final JPanel myPanel;
- /**
* The author ComboBox, the combobox contains previously selected authors.
*/
private final JComboBox myAuthor;
- /**
- * The amend checkbox
- */
- private final JCheckBox myAmend;
+
private Date myAuthorDate;
- @Nullable private String myPreviousMessage;
- @Nullable private String myAmendedMessage;
- @NotNull private final CheckinProjectPanel myCheckinPanel;
-
- /**
- * A constructor
- *
- * @param project
- * @param panel
- */
GitCheckinOptions(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
+ super(project, panel);
myVcs = GitVcs.getInstance(project);
- myCheckinPanel = panel;
- myPanel = new JPanel(new GridBagLayout());
final Insets insets = new Insets(2, 2, 2, 2);
// add authors drop down
GridBagConstraints c = new GridBagConstraints();
@@ -642,7 +621,7 @@
c.gridy = 0;
c.weightx = 1;
c.fill = GridBagConstraints.HORIZONTAL;
- final List<String> usersList = getUsersList(project, myCheckinPanel.getRoots());
+ final List<String> usersList = getUsersList(project);
final Set<String> authors = usersList == null ? new HashSet<String>() : new HashSet<String>(usersList);
ContainerUtil.addAll(authors, mySettings.getCommitAuthors());
List<String> list = new ArrayList<String>(authors);
@@ -653,108 +632,36 @@
return StringUtil.shortenTextWithEllipsis(o, 30, 0);
}
});
- myAuthor = new JComboBox(ArrayUtil.toObjectArray(list));
+ myAuthor = new ComboBox(ArrayUtil.toObjectArray(list));
myAuthor.insertItemAt("", 0);
myAuthor.setSelectedItem("");
myAuthor.setEditable(true);
authorLabel.setLabelFor(myAuthor);
myAuthor.setToolTipText(GitBundle.getString("commit.author.tooltip"));
myPanel.add(myAuthor, c);
- // add amend checkbox
- c = new GridBagConstraints();
- c.gridx = 0;
- c.gridy = 1;
- c.gridwidth = 2;
- c.anchor = GridBagConstraints.CENTER;
- c.insets = insets;
- c.weightx = 1;
- c.fill = GridBagConstraints.HORIZONTAL;
- myAmend = new NonFocusableCheckBox(GitBundle.getString("commit.amend"));
- myAmend.setMnemonic('m');
- myAmend.setSelected(false);
- myAmend.setToolTipText(GitBundle.getString("commit.amend.tooltip"));
- myPanel.add(myAmend, c);
-
- myPreviousMessage = myCheckinPanel.getCommitMessage();
-
- myAmend.addActionListener(new ActionListener() {
- @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);
- }
- else { // checkbox is selected not the first time
- substituteCommitMessage(myAmendedMessage);
- }
- }
- }
- else {
- // there was the amended message, but user has changed it => not reverting
- if (myCheckinPanel.getCommitMessage().equals(myAmendedMessage)) {
- myCheckinPanel.setCommitMessage(myPreviousMessage);
- }
- }
- }
- });
}
- private void loadMessageInModalTask(@NotNull Project project) {
- try {
- String messageFromGit =
- ProgressManager.getInstance().runProcessWithProgressSynchronously(new ThrowableComputable<String, VcsException>() {
- @Override
- public String compute() throws VcsException {
- return getLastCommitMessage();
- }
- }, "Reading commit message...", false, project);
- if (!StringUtil.isEmptyOrSpaces(messageFromGit)) {
- substituteCommitMessage(messageFromGit);
- myAmendedMessage = messageFromGit;
- }
- }
- catch (VcsException e) {
- Messages.showErrorDialog(getComponent(), "Couldn't load commit message of the commit to amend.\n" + e.getMessage(),
- "Commit Message not Loaded");
- log.info(e);
- }
- }
-
- private void substituteCommitMessage(@NotNull String newMessage) {
- myPreviousMessage = myCheckinPanel.getCommitMessage();
- myCheckinPanel.setCommitMessage(newMessage);
+ @Override
+ @NotNull
+ protected Set<VirtualFile> getRoots() {
+ return GitUtil.gitRoots(getSelectedFilePaths());
}
@Nullable
- private String getLastCommitMessage() throws VcsException {
- Set<VirtualFile> roots = GitUtil.gitRoots(getSelectedFilePaths());
- 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);
- }
- }
- if (!exception.isNull()) {
- throw exception.get();
- }
- return joinOrNull(messages);
- }
-
- @Nullable
- private String getLastCommitMessage(@NotNull VirtualFile root) throws VcsException {
+ @Override
+ protected String getLastCommitMessage(@NotNull VirtualFile root) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(myProject, root, GitCommand.LOG);
h.addParameters("--max-count=1");
+ String formatPattern;
if (GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(myVcs.getVersion())) {
- h.addParameters("--pretty=%B");
+ formatPattern = "%B";
}
else {
// only message: subject + body; "%-b" means that preceding line-feeds will be deleted if the body is empty
// %s strips newlines from subject; there is no way to work around it before 1.7.2 with %B (unless parsing some fixed format)
- h.addParameters("--pretty=%s%n%n%-b");
+ formatPattern = "%s%n%n%-b";
}
+ h.addParameters("--pretty=format:" + formatPattern);
return h.run();
}
@@ -768,29 +675,16 @@
});
}
- private List<String> getUsersList(final Project project, final Collection<VirtualFile> roots) {
+ private List<String> getUsersList(final Project project) {
return NewGitUsersComponent.getInstance(project).get();
}
- /**
- * {@inheritDoc}
- */
- public JComponent getComponent() {
- return myPanel;
- }
-
- /**
- * {@inheritDoc}
- */
public void refresh() {
+ super.refresh();
myAuthor.setSelectedItem("");
- myAmend.setSelected(false);
reset();
}
- /**
- * {@inheritDoc}
- */
public void saveState() {
String author = (String)myAuthor.getEditor().getItem();
myNextCommitAuthor = author.length() == 0 ? null : author;
@@ -805,9 +699,6 @@
myNextCommitAuthorDate = myAuthorDate;
}
- /**
- * {@inheritDoc}
- */
public void restoreState() {
refresh();
}
@@ -824,12 +715,6 @@
}
}
- @Nullable
- private static String joinOrNull(@NotNull Collection<String> messages) {
- String joined = StringUtil.join(messages, "\n");
- return StringUtil.isEmptyOrSpaces(joined) ? null : joined;
- }
-
public void setNextCommitIsPushed(Boolean nextCommitIsPushed) {
myNextCommitIsPushed = nextCommitIsPushed;
}
diff --git a/plugins/git4idea/src/git4idea/checkin/UnresolvedMergeCheckFactory.java b/plugins/git4idea/src/git4idea/checkin/UnresolvedMergeCheckFactory.java
index 1388ee0..ca9b394 100644
--- a/plugins/git4idea/src/git4idea/checkin/UnresolvedMergeCheckFactory.java
+++ b/plugins/git4idea/src/git4idea/checkin/UnresolvedMergeCheckFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -39,7 +39,7 @@
if (containsUnresolvedConflicts(panel)) {
int answer = Messages.showYesNoDialog(panel.getComponent(), "Are you sure you want to commit changes with unresolved conflicts?",
"Unresolved Conflicts", Messages.getWarningIcon());
- return answer == Messages.OK ? ReturnResult.COMMIT : ReturnResult.CANCEL;
+ return answer == Messages.YES ? ReturnResult.COMMIT : ReturnResult.CANCEL;
}
return ReturnResult.COMMIT;
}
diff --git a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
index 57305c4..9b3e587 100644
--- a/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
+++ b/plugins/git4idea/src/git4idea/checkout/GitCheckoutProvider.java
@@ -15,6 +15,7 @@
*/
package git4idea.checkout;
+import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
@@ -29,7 +30,6 @@
import git4idea.commands.GitCommandResult;
import git4idea.commands.GitLineHandlerListener;
import git4idea.commands.GitStandardProgressAnalyzer;
-import git4idea.i18n.GitBundle;
import git4idea.jgit.GitHttpAdapter;
import git4idea.update.GitFetchResult;
import git4idea.update.GitFetcher;
@@ -81,7 +81,7 @@
final String sourceRepositoryURL, final String directoryName, final String parentDirectory) {
final AtomicBoolean cloneResult = new AtomicBoolean();
- new Task.Backgroundable(project, GitBundle.message("cloning.repository", sourceRepositoryURL)) {
+ new Task.Backgroundable(project, DvcsBundle.message("cloning.repository", sourceRepositoryURL)) {
@Override
public void run(@NotNull ProgressIndicator indicator) {
cloneResult.set(doClone(project, indicator, git, directoryName, parentDirectory, sourceRepositoryURL));
diff --git a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.form b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.form
deleted file mode 100644
index 9bffc1a..0000000
--- a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.form
+++ /dev/null
@@ -1,84 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="git4idea.checkout.GitCloneDialog">
- <grid id="27dc6" binding="myRootPanel" layout-manager="GridLayoutManager" row-count="4" column-count="4" 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="567" height="119"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="7e816" class="javax.swing.JLabel">
- <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="b8c8e"/>
- <text resource-bundle="git4idea/i18n/GitBundle" key="clone.repository.url"/>
- </properties>
- </component>
- <vspacer id="86a0f">
- <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"/>
- </constraints>
- </vspacer>
- <hspacer id="a0290">
- <constraints>
- <grid row="3" column="1" row-span="1" col-span="3" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- </hspacer>
- <component id="b8c8e" class="com.intellij.ui.EditorComboBox" binding="myRepositoryURL" custom-create="true">
- <constraints>
- <grid row="0" column="1" row-span="1" col-span="2" 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="1422b" class="javax.swing.JLabel">
- <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 resource-bundle="git4idea/i18n/GitBundle" key="clone.parent.dir"/>
- </properties>
- </component>
- <component id="876a6" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myParentDirectory">
- <constraints>
- <grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- </component>
- <component id="2002c" 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>
- <labelFor value="4e988"/>
- <text resource-bundle="git4idea/i18n/GitBundle" key="clone.dir.name"/>
- </properties>
- </component>
- <component id="fbda8" class="javax.swing.JButton" binding="myTestButton">
- <constraints>
- <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="git4idea/i18n/GitBundle" key="clone.test"/>
- </properties>
- </component>
- <component id="4e988" class="javax.swing.JTextField" binding="myDirectoryName">
- <constraints>
- <grid row="2" 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>
- <hspacer id="e781a">
- <constraints>
- <grid row="2" column="2" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- </hspacer>
- </children>
- </grid>
-</form>
diff --git a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
index 33bc8d0..4358a1f 100644
--- a/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
+++ b/plugins/git4idea/src/git4idea/checkout/GitCloneDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,146 +15,27 @@
*/
package git4idea.checkout;
-import com.intellij.ide.impl.ProjectUtil;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.dvcs.DvcsRememberedInputs;
+import com.intellij.dvcs.ui.CloneDvcsDialog;
+import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.*;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.DocumentAdapter;
-import com.intellij.ui.EditorComboBox;
-import com.intellij.util.ArrayUtil;
import git4idea.GitUtil;
-import git4idea.commands.*;
-import git4idea.i18n.GitBundle;
+import git4idea.commands.GitCommand;
+import git4idea.commands.GitLineHandlerPasswordRequestAware;
+import git4idea.commands.GitTask;
+import git4idea.commands.GitTaskResult;
import git4idea.remote.GitRememberedInputs;
-import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
-import javax.swing.*;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.util.regex.Pattern;
/**
- * A dialog for the git clone options
- *
- * @author Constantine.Plotnikov
+ * @author Nadya Zabrodina
*/
-public class GitCloneDialog extends DialogWrapper {
- /**
- * The pattern for SSH URL-s in form [user@]host:path
- */
- private static final Pattern SSH_URL_PATTERN;
+public class GitCloneDialog extends CloneDvcsDialog {
- static {
- // TODO make real URL pattern
- @NonNls final String ch = "[\\p{ASCII}&&[\\p{Graph}]&&[^@:/]]";
- @NonNls final String host = ch + "+(?:\\." + ch + "+)*";
- @NonNls final String path = "/?" + ch + "+(?:/" + ch + "+)*/?";
- @NonNls final String all = "(?:" + ch + "+@)?" + host + ":" + path;
- SSH_URL_PATTERN = Pattern.compile(all);
- }
-
- private JPanel myRootPanel;
- private EditorComboBox myRepositoryURL;
- private TextFieldWithBrowseButton myParentDirectory;
- private JButton myTestButton; // test repository
- private JTextField myDirectoryName;
-
- private String myTestURL; // the repository URL at the time of the last test
- private Boolean myTestResult; // the test result of the last test or null if not tested
- private String myDefaultDirectoryName = "";
- private final Project myProject;
-
- public GitCloneDialog(Project project) {
- super(project, true);
- myProject = project;
- init();
- initListeners();
- setTitle(GitBundle.getString("clone.title"));
- setOKButtonText(GitBundle.getString("clone.button"));
- }
-
- public String getSourceRepositoryURL() {
- return getCurrentUrlText();
- }
-
- public String getParentDirectory() {
- return myParentDirectory.getText();
- }
-
- public String getDirectoryName() {
- return myDirectoryName.getText();
- }
-
- /**
- * Init components
- */
- private void initListeners() {
- FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor();
- fcd.setShowFileSystemRoots(true);
- fcd.setTitle(GitBundle.getString("clone.destination.directory.title"));
- fcd.setDescription(GitBundle.getString("clone.destination.directory.description"));
- fcd.setHideIgnored(false);
- myParentDirectory.addActionListener(
- new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>(fcd.getTitle(), fcd.getDescription(), myParentDirectory,
- myProject, fcd, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
- @Override
- protected VirtualFile getInitialFile() {
- // suggest project base directory only if nothing is typed in the component.
- String text = getComponentText();
- if (text.length() == 0) {
- VirtualFile file = myProject.getBaseDir();
- if (file != null) {
- return file;
- }
- }
- return super.getInitialFile();
- }
- });
-
- final DocumentListener updateOkButtonListener = new DocumentAdapter() {
- @Override protected void textChanged(DocumentEvent e) {
- updateButtons();
- }
- };
- myParentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener);
- String parentDir = GitRememberedInputs.getInstance().getCloneParentDir();
- if (StringUtil.isEmptyOrSpaces(parentDir)) {
- parentDir = ProjectUtil.getBaseDir();
- }
- myParentDirectory.setText(parentDir);
-
- myDirectoryName.getDocument().addDocumentListener(updateOkButtonListener);
-
- myTestButton.addActionListener(new ActionListener() {
- public void actionPerformed(final ActionEvent e) {
- test();
- }
- });
-
- setOKActionEnabled(false);
- myTestButton.setEnabled(false);
- }
-
- private void test() {
- myTestURL = getCurrentUrlText();
- boolean testResult = test(myTestURL);
-
- if (testResult) {
- Messages.showInfoMessage(myTestButton, GitBundle.message("clone.test.success.message", myTestURL),
- GitBundle.getString("clone.test.connection.title"));
- myTestResult = Boolean.TRUE;
- } else {
- myTestResult = Boolean.FALSE;
- }
- updateButtons();
+ public GitCloneDialog(@NotNull Project project) {
+ super(project, GitUtil.DOT_GIT);
}
/*
@@ -162,169 +43,21 @@
* That way, we have a hack here: if http response asked for a password, then the url is at least valid and existant, and we consider
* that the test passed.
*/
- private boolean test(String url) {
- final GitLineHandlerPasswordRequestAware handler = new GitLineHandlerPasswordRequestAware(myProject, new File("."), GitCommand.LS_REMOTE);
+ protected boolean test(@NotNull String url) {
+ final GitLineHandlerPasswordRequestAware handler =
+ new GitLineHandlerPasswordRequestAware(myProject, new File("."), GitCommand.LS_REMOTE);
handler.setUrl(url);
handler.addParameters(url, "master");
- GitTask task = new GitTask(myProject, handler, GitBundle.message("clone.testing", url));
+ GitTask task = new GitTask(myProject, handler, DvcsBundle.message("clone.testing", url));
GitTaskResult result = task.executeModal();
boolean authFailed = handler.hadAuthRequest();
return result.isOK() || authFailed;
}
- /**
- * Check fields and display error in the wrapper if there is a problem
- */
- private void updateButtons() {
- if (!checkRepositoryURL()) {
- return;
- }
- if (!checkDestination()) {
- return;
- }
- setErrorText(null);
- setOKActionEnabled(true);
- }
-
- /**
- * Check destination directory and set appropriate error text if there are problems
- *
- * @return true if destination components are OK.
- */
- private boolean checkDestination() {
- if (myParentDirectory.getText().length() == 0 || myDirectoryName.getText().length() == 0) {
- setErrorText(null);
- setOKActionEnabled(false);
- return false;
- }
- File file = new File(myParentDirectory.getText(), myDirectoryName.getText());
- if (file.exists()) {
- setErrorText(GitBundle.message("clone.destination.exists.error", file));
- setOKActionEnabled(false);
- return false;
- }
- else if (!file.getParentFile().exists()) {
- setErrorText(GitBundle.message("clone.parent.missing.error", file.getParent()));
- setOKActionEnabled(false);
- return false;
- }
- return true;
- }
-
- /**
- * Check repository URL and set appropriate error text if there are problems
- *
- * @return true if repository URL is OK.
- */
- private boolean checkRepositoryURL() {
- String repository = getCurrentUrlText();
- if (repository.length() == 0) {
- setErrorText(null);
- setOKActionEnabled(false);
- return false;
- }
- if (myTestResult != null && repository.equals(myTestURL)) {
- if (!myTestResult.booleanValue()) {
- setErrorText(GitBundle.getString("clone.test.failed.error"));
- setOKActionEnabled(false);
- return false;
- }
- else {
- return true;
- }
- }
- try {
- if (new URI(repository).isAbsolute()) {
- return true;
- }
- }
- catch (URISyntaxException urlExp) {
- // do nothing
- }
- // check if ssh url pattern
- if (SSH_URL_PATTERN.matcher(repository).matches()) {
- return true;
- }
- try {
- File file = new File(repository);
- if (file.exists()) {
- if (!file.isDirectory()) {
- setErrorText(GitBundle.getString("clone.url.is.not.directory.error"));
- setOKActionEnabled(false);
- }
- return true;
- }
- }
- catch (Exception fileExp) {
- // do nothing
- }
- setErrorText(GitBundle.getString("clone.invalid.url"));
- setOKActionEnabled(false);
- return false;
- }
-
- private String getCurrentUrlText() {
- return myRepositoryURL.getText().trim();
- }
-
- private void createUIComponents() {
- myRepositoryURL = new EditorComboBox("");
- final GitRememberedInputs rememberedInputs = GitRememberedInputs.getInstance();
- myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getVisitedUrls(), String.class));
- myRepositoryURL.addDocumentListener(new com.intellij.openapi.editor.event.DocumentAdapter() {
- @Override
- public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
- // enable test button only if something is entered in repository URL
- final String url = getCurrentUrlText();
- myTestButton.setEnabled(url.length() != 0);
- if (myDefaultDirectoryName.equals(myDirectoryName.getText()) || myDirectoryName.getText().length() == 0) {
- // modify field if it was unmodified or blank
- myDefaultDirectoryName = defaultDirectoryName(url);
- myDirectoryName.setText(myDefaultDirectoryName);
- }
- updateButtons();
- }
- });
- }
-
- public void prependToHistory(final String item) {
- myRepositoryURL.prependItem(item);
- }
-
- public void rememberSettings() {
- final GitRememberedInputs rememberedInputs = GitRememberedInputs.getInstance();
- rememberedInputs.addUrl(getSourceRepositoryURL());
- rememberedInputs.setCloneParentDir(getParentDirectory());
- }
-
- /**
- * Get default name for checked out directory
- *
- * @param url an URL to checkout
- * @return a default repository name
- */
- private static String defaultDirectoryName(final String url) {
- String nonSystemName;
- if (url.endsWith("/" + GitUtil.DOT_GIT) || url.endsWith(File.separator + GitUtil.DOT_GIT)) {
- nonSystemName = url.substring(0, url.length() - 5);
- }
- else {
- if (url.endsWith(GitUtil.DOT_GIT)) {
- nonSystemName = url.substring(0, url.length() - 4);
- }
- else {
- nonSystemName = url;
- }
- }
- int i = nonSystemName.lastIndexOf('/');
- if (i == -1 && File.separatorChar != '/') {
- i = nonSystemName.lastIndexOf(File.separatorChar);
- }
- return i >= 0 ? nonSystemName.substring(i + 1) : "";
- }
-
- protected JComponent createCenterPanel() {
- return myRootPanel;
+ @NotNull
+ @Override
+ protected DvcsRememberedInputs getRememberedInputs() {
+ return GitRememberedInputs.getInstance();
}
@Override
@@ -333,13 +66,7 @@
}
@Override
- public JComponent getPreferredFocusedComponent() {
- return myRepositoryURL;
- }
-
- @Override
protected String getHelpId() {
return "reference.VersionControl.Git.CloneRepository";
}
-
-}
+}
\ No newline at end of file
diff --git a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
index 7d24caf..8547848 100644
--- a/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
+++ b/plugins/git4idea/src/git4idea/cherrypick/GitCherryPickAction.java
@@ -15,6 +15,7 @@
*/
package git4idea.cherrypick;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
@@ -29,7 +30,6 @@
import com.intellij.vcs.log.*;
import git4idea.GitLocalBranch;
import git4idea.GitPlatformFacade;
-import git4idea.GitUtil;
import git4idea.GitVcs;
import git4idea.commands.Git;
import git4idea.config.GitVcsSettings;
@@ -133,7 +133,7 @@
public void update(AnActionEvent e) {
super.update(e);
final VcsLog log = getVcsLog(e);
- if (log != null && !GitUtil.logHasGitRoot(log)) {
+ if (log != null && !DvcsUtil.logHasRootForVcs(log, GitVcs.getKey())) {
e.getPresentation().setEnabledAndVisible(false);
}
else {
diff --git a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
index c27fb0d..9822704 100644
--- a/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitSSHGUIHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -67,7 +67,7 @@
final AtomicBoolean rc = new AtomicBoolean();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
public void run() {
- rc.set(0 == Messages.showYesNoDialog(myProject, message, GitBundle.getString("ssh.confirm.key.titile"), null));
+ rc.set(Messages.YES == Messages.showYesNoDialog(myProject, message, GitBundle.getString("ssh.confirm.key.titile"), null));
}
});
return rc.get();
diff --git a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java
index 821a1d3..7dd759f 100644
--- a/plugins/git4idea/src/git4idea/commands/GitTextHandler.java
+++ b/plugins/git4idea/src/git4idea/commands/GitTextHandler.java
@@ -61,6 +61,9 @@
}
protected void startHandlingStreams() {
+ if (myHandler == null) {
+ return;
+ }
myHandler.addProcessListener(new ProcessListener() {
public void startNotified(final ProcessEvent event) {
// do nothing
diff --git a/plugins/git4idea/src/git4idea/config/GitVersionSpecialty.java b/plugins/git4idea/src/git4idea/config/GitVersionSpecialty.java
index 22e1167..1ce90bb 100644
--- a/plugins/git4idea/src/git4idea/config/GitVersionSpecialty.java
+++ b/plugins/git4idea/src/git4idea/config/GitVersionSpecialty.java
@@ -101,6 +101,17 @@
public boolean existsIn(@NotNull GitVersion version) {
return SystemInfo.isWindows && version.isOlderOrEqual(new GitVersion(1, 7, 0, 2));
}
+ },
+
+ /**
+ * {@code --no-walk=unsorted} <br/>
+ * Before this version {@code --no-walk} didn't take any parameters.
+ */
+ NO_WALK_UNSORTED {
+ @Override
+ public boolean existsIn(@NotNull GitVersion version) {
+ return version.isLaterOrEqual(new GitVersion(1, 7, 12, 1));
+ }
};
public abstract boolean existsIn(@NotNull GitVersion version);
diff --git a/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java b/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java
index aeb7f94..229d8b0 100644
--- a/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java
+++ b/plugins/git4idea/src/git4idea/crlf/GitCrlfDialog.java
@@ -79,7 +79,7 @@
JLabel readMore = new LinkLabel("Read more", null, new LinkListener() {
@Override
public void linkSelected(LinkLabel aSource, Object aLinkData) {
- BrowserUtil.launchBrowser("https://help.github.com/articles/dealing-with-line-endings");
+ BrowserUtil.browse("https://help.github.com/articles/dealing-with-line-endings");
}
});
diff --git a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
index c1353e7..f4cc163 100644
--- a/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
+++ b/plugins/git4idea/src/git4idea/history/GitHistoryUtils.java
@@ -46,6 +46,7 @@
import git4idea.branch.GitBranchUtil;
import git4idea.commands.*;
import git4idea.config.GitConfigUtil;
+import git4idea.config.GitVersionSpecialty;
import git4idea.history.browser.GitHeavyCommit;
import git4idea.history.browser.SHAHash;
import git4idea.history.browser.SymbolicRefs;
@@ -484,39 +485,11 @@
return null;
}
- public static List<? extends VcsShortCommitDetails> readAllMiniDetails(final Project project, final VirtualFile root) throws VcsException {
- GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
- GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, AUTHOR_NAME,
- AUTHOR_EMAIL, AUTHOR_TIME, SUBJECT);
- h.setStdoutSuppressed(true);
- h.addParameters(parser.getPretty(), "--encoding=UTF-8");
- h.addParameters(LOG_ALL);
- h.addParameters("--full-history", "--sparse");
- h.endOptions();
-
- String output = h.run();
-
- List<GitLogRecord> records = parser.parse(output);
-
- return ContainerUtil.mapNotNull(records, new Function<GitLogRecord, VcsShortCommitDetails>() {
- @Override
- public VcsShortCommitDetails fun(GitLogRecord record) {
- List<Hash> parents = new SmartList<Hash>();
- for (String parent : record.getParentsHashes()) {
- parents.add(HashImpl.build(parent));
- }
-
- return vcsObjectsFactory(project).createShortDetails(HashImpl.build(record.getHash()), parents, record.getAuthorTimeStamp(), root,
- record.getSubject(), record.getAuthorName(), record.getAuthorEmail());
- }
- });
- }
-
public static List<? extends VcsShortCommitDetails> readMiniDetails(final Project project, final VirtualFile root, List<String> hashes) throws VcsException {
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.NONE, HASH, PARENTS, AUTHOR_NAME,
AUTHOR_EMAIL, COMMIT_TIME, SUBJECT);
- h.setStdoutSuppressed(true);
+ h.setSilent(true);
// git show can show either -p, or --name-status, or --name-only, but we need nothing, just details => using git log --no-walk
h.addParameters("--no-walk");
h.addParameters(parser.getPretty(), "--encoding=UTF-8");
@@ -1032,7 +1005,7 @@
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS,
HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME,
COMMITTER_EMAIL, PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY);
- h.setStdoutSuppressed(true);
+ h.setSilent(true);
h.addParameters("--name-status", "-M", parser.getPretty(), "--encoding=UTF-8");
h.addParameters(new ArrayList<String>(commitsIds));
@@ -1048,20 +1021,11 @@
@NotNull
public static List<GitCommit> commitsDetails(@NotNull Project project, @NotNull VirtualFile root,
@NotNull final Collection<String> hashes) throws VcsException {
- GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.SHOW);
- GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS,
- HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME,
- COMMITTER_EMAIL, PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY);
- h.setStdoutSuppressed(true);
- h.addParameters("--name-status", "-M", parser.getPretty(), "--encoding=UTF-8");
- h.addParameters(new ArrayList<String>(hashes));
-
- String output = h.run();
- final List<GitCommit> rc = new ArrayList<GitCommit>();
- for (GitLogRecord record : parser.parse(output)) {
- rc.add(createCommit(project, root, record));
- }
- return rc;
+ List<String> params = new ArrayList<String>(hashes);
+ GitVcs vcs = GitVcs.getInstance(project);
+ String noWalk = vcs != null && GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(vcs.getVersion()) ? "--no-walk=unsorted" : "--no-walk";
+ params.add(0, noWalk);
+ return getAllDetails(project, root, params);
}
@NotNull
@@ -1071,7 +1035,7 @@
GitLogParser parser = new GitLogParser(project, GitLogParser.NameStatus.STATUS,
HASH, HASH, COMMIT_TIME, AUTHOR_NAME, AUTHOR_TIME, AUTHOR_EMAIL, COMMITTER_NAME,
COMMITTER_EMAIL, PARENTS, REF_NAMES, SUBJECT, BODY, RAW_BODY);
- h.setStdoutSuppressed(true);
+ h.setSilent(true);
h.addParameters("--name-status", "-M", parser.getPretty(), "--encoding=UTF-8");
h.addParameters(parameters);
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/BasePopupAction.java b/plugins/git4idea/src/git4idea/history/wholeTree/BasePopupAction.java
index f4f5054..95a981c 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/BasePopupAction.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/BasePopupAction.java
@@ -28,6 +28,7 @@
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.Consumer;
import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -64,7 +65,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
doAction(e);
return true;
}
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/ContainedInBranchesConfigDialog.java b/plugins/git4idea/src/git4idea/history/wholeTree/ContainedInBranchesConfigDialog.java
index 2afeca8..a9a2dfa 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/ContainedInBranchesConfigDialog.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/ContainedInBranchesConfigDialog.java
@@ -37,12 +37,11 @@
*/
public class ContainedInBranchesConfigDialog extends DialogWrapper {
private JPanel myPanel;
- private CheckBoxList myLocalBranches;
- private CheckBoxList myRemoteBranches;
+ private CheckBoxList<String> myLocalBranches;
+ private CheckBoxList<String> myRemoteBranches;
private final Project myProject;
private boolean myChanged;
private JRadioButton myHighlight;
- private JRadioButton myFilter;
public ContainedInBranchesConfigDialog(final Project project, final Collection<String> localBranches,
Collection<String> remoteBranches, final String currentLocal, final String currentRemote) {
@@ -74,15 +73,15 @@
final ButtonGroup bg = new ButtonGroup();
myHighlight = new JRadioButton("Highlight them");
- myFilter = new JRadioButton("Filter others out");
+ JRadioButton filter = new JRadioButton("Filter others out");
bg.add(myHighlight);
- bg.add(myFilter);
+ bg.add(filter);
gb.gridwidth = 1;
gb.gridx = 0;
++ gb.gridy;
myPanel.add(myHighlight, gb);
++ gb.gridy;
- myPanel.add(myFilter, gb);
+ myPanel.add(filter, gb);
gb.insets.top = 10;
gb.gridwidth = 1;
@@ -108,7 +107,7 @@
setItems(remoteBranches, gitLogSettings.getRemoteBranchesCopy(), myRemoteBranches);
myHighlight.setSelected(gitLogSettings.isHighlight());
- myFilter.setSelected(! gitLogSettings.isHighlight());
+ filter.setSelected(!gitLogSettings.isHighlight());
new ListSpeedSearch(myLocalBranches);
new ListSpeedSearch(myRemoteBranches);
@@ -134,7 +133,7 @@
return myChanged;
}
- private static void setItems(Collection<String> localBranches, Set<String> localBranchesCopy, final CheckBoxList list) {
+ private static void setItems(Collection<String> localBranches, Set<String> localBranchesCopy, final CheckBoxList<String> list) {
// order
final Map<String, Boolean> localBranchesState = new TreeMap<String, Boolean>();
for (String localBranch : localBranches) {
@@ -163,9 +162,9 @@
final GitLogSettings gitLogSettings = GitLogSettings.getInstance(myProject);
final ArrayList<String> local = gatherSelected((DefaultListModel)myLocalBranches.getModel());
final ArrayList<String> remote = gatherSelected((DefaultListModel)myRemoteBranches.getModel());
- boolean hightlightChanged = gitLogSettings.isHighlight() != myHighlight.isSelected();
+ boolean highlightChanged = gitLogSettings.isHighlight() != myHighlight.isSelected();
gitLogSettings.setHighlight(myHighlight.isSelected());
- if (gitLogSettings.setIfChanged(local, remote) || hightlightChanged) {
+ if (gitLogSettings.setIfChanged(local, remote) || highlightChanged) {
myChanged = true;
}
super.doOKAction();
@@ -183,7 +182,7 @@
return selected;
}
- private static class MyCheckBoxList extends CheckBoxList {
+ private static class MyCheckBoxList extends CheckBoxList<String> {
private final String myBold;
private final static Border FOCUSED_BORDER = UIManager.getBorder("List.focusCellHighlightBorder");
private final EmptyBorder myEmptyBorder;
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
index 02b2445..209d2ad 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/GitLogUI.java
@@ -117,7 +117,7 @@
private boolean myStarted;
private String myPreviousFilter;
private final CommentSearchContext myCommentSearchContext;
- private List<String> myUsersSearchContext;
+ private final List<String> myUsersSearchContext;
private String mySelectedBranch;
private BranchSelectorAction myBranchSelectorAction;
private final DescriptionRenderer myDescriptionRenderer;
@@ -159,7 +159,7 @@
private JScrollPane myTableScrollPane;
private GitLogUI.MyTextFieldAction myTextFieldAction;
private DatesFilterI myDatesFilter;
- private GitLogSettings mySettings;
+ private final GitLogSettings mySettings;
public GitLogUI(Project project, final Mediator mediator) {
myProject = project;
@@ -481,7 +481,7 @@
});
myBranchesLoaderImpl = new Consumer<CommitI>() {
- private Processor<AbstractHash> myRecheck;
+ private final Processor<AbstractHash> myRecheck;
{
myRecheck = new Processor<AbstractHash>() {
@@ -685,11 +685,7 @@
protected Object tryGetTag(MouseEvent e, JTable table, int row, int column) {
myDescriptionRenderer.getTableCellRendererComponent(table, table.getValueAt(row, column), false, false, row, column);
final Rectangle rc = table.getCellRect(row, column, false);
- int index = myDescriptionRenderer.myInner.findFragmentAt(e.getPoint().x - rc.x - myDescriptionRenderer.getCurrentWidth());
- if (index >= 0) {
- return myDescriptionRenderer.myInner.getFragmentTag(index);
- }
- return null;
+ return myDescriptionRenderer.myInner.getFragmentTag(e.getPoint().x - rc.x - myDescriptionRenderer.getCurrentWidth());
}
};
final ActionToolbar actionToolbar = createToolbar();
@@ -1043,7 +1039,7 @@
private class DataProviderPanel extends JPanel implements TypeSafeDataProvider {
- private GitCommitDetailsProvider myCommitDetailsProvider;
+ private final GitCommitDetailsProvider myCommitDetailsProvider;
private DataProviderPanel(LayoutManager layout) {
super(layout);
@@ -1989,7 +1985,7 @@
private final DumbAwareAction myMultiColorAction;
private final DumbAwareAction myCalmAction;
private final Icon myIcon;
- private JLabel myLabel;
+ private final JLabel myLabel;
private final GitLogUI.MySelectRootsForTreeAction myRootsForTreeAction;
private final DumbAwareAction myDateOrder;
private final DumbAwareAction myTopoOrder;
@@ -2102,7 +2098,7 @@
@Override
public void actionPerformed(AnActionEvent e) {
- final CheckBoxList checkBoxList = new CheckBoxList();
+ final CheckBoxList<String> checkBoxList = new CheckBoxList<String>();
final List<VirtualFile> order = myTableModel.getOrder();
final Set<VirtualFile> activeRoots = myTableModel.getActiveRoots();
diff --git a/plugins/git4idea/src/git4idea/history/wholeTree/SelectRepositoryAndShowLogAction.java b/plugins/git4idea/src/git4idea/history/wholeTree/SelectRepositoryAndShowLogAction.java
index 8029408..9257f1f 100644
--- a/plugins/git4idea/src/git4idea/history/wholeTree/SelectRepositoryAndShowLogAction.java
+++ b/plugins/git4idea/src/git4idea/history/wholeTree/SelectRepositoryAndShowLogAction.java
@@ -18,7 +18,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.application.ModalityState;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.fileChooser.FileChooser;
@@ -63,7 +62,7 @@
* @author irengrig
*/
public class SelectRepositoryAndShowLogAction extends AnAction {
- public static final String ourTitle = "Show Git repository log";
+ public static final String ourTitle = "Show Git Repository Log";
public static final int MAX_REPOS = 10;
public SelectRepositoryAndShowLogAction() {
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.java b/plugins/git4idea/src/git4idea/i18n/GitBundle.java
index eb9d419..da0fe7c 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.java
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -29,6 +29,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -39,21 +40,20 @@
* Git4Idea package I18N localization bundle helper
*/
public class GitBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "git4idea.i18n.GitBundle";
private GitBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
index 56061ca..79e7f70 100644
--- a/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
+++ b/plugins/git4idea/src/git4idea/i18n/GitBundle.properties
@@ -37,25 +37,6 @@
checkout.validate.tooltip=Use this button to validate reference expression if entered manually.
checkout.validate=&Validate
checkout.validation.failed=Source revision validation failed
-clone.button=Clone
-clone.destination.directory.description=Select a parent directory destination directory for clone
-clone.destination.directory.title=Parent Directory
-clone.destination.exists.error=The path {0} exists. Git cannot clone to an existing directory.
-clone.dir.name=Directory &Name:
-clone.invalid.origin=The origin name is in invalid format.
-clone.invalid.url=Repository URL is a malformed URL or non-existent directory.
-clone.origin=&Origin Name
-clone.parent.dir=&Parent Directory:
-clone.parent.missing.error=The parent path {0} must exist.
-clone.repository.url=Git &Repository URL:
-clone.test.failed.error=Repository test has failed.
-clone.test.success.message=<html>Connection to repository {0} has been successful.</html>
-clone.test.connection.title=Test Connection
-clone.test=&Test
-clone.testing=Testing repository {0}
-clone.title=Clone Repository
-clone.url.is.not.directory.error=Repository URL is not a directory.
-cloning.repository=Cloning source repository {0}
command.cancelled=The command was cancelled.
commit.action.name=Comm&it
commit.author.tooltip=<html>Specify a commit author here if it is different from committer. The author should be in the format: Author Name <author@ema.il></html>
diff --git a/plugins/git4idea/src/git4idea/log/GitLogProvider.java b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
index 672e4eb..88aae2a 100644
--- a/plugins/git4idea/src/git4idea/log/GitLogProvider.java
+++ b/plugins/git4idea/src/git4idea/log/GitLogProvider.java
@@ -15,7 +15,6 @@
*/
package git4idea.log;
-import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
@@ -26,7 +25,6 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ExceptionUtil;
-import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
import com.intellij.vcs.log.impl.HashImpl;
@@ -50,9 +48,6 @@
import java.util.Collections;
import java.util.List;
-/**
- * @author Kirill Likhodedov
- */
public class GitLogProvider implements VcsLogProvider {
private static final Logger LOG = Logger.getInstance(GitLogProvider.class);
@@ -62,11 +57,11 @@
@NotNull private final VcsLogRefManager myRefSorter;
@NotNull private final VcsLogObjectsFactory myVcsObjectsFactory;
- public GitLogProvider(@NotNull Project project, @NotNull GitRepositoryManager repositoryManager) {
+ public GitLogProvider(@NotNull Project project, @NotNull GitRepositoryManager repositoryManager, @NotNull VcsLogObjectsFactory factory) {
myProject = project;
myRepositoryManager = repositoryManager;
myRefSorter = new GitRefManager(myRepositoryManager);
- myVcsObjectsFactory = ServiceManager.getService(myProject, VcsLogObjectsFactory.class);
+ myVcsObjectsFactory = factory;
}
@NotNull
@@ -184,11 +179,7 @@
@NotNull
@Override
public List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull final VirtualFile root,
- @NotNull Collection<VcsLogBranchFilter> branchFilters,
- @NotNull Collection<VcsLogUserFilter> userFilters,
- @NotNull Collection<VcsLogDateFilter> dateFilters,
- @NotNull Collection<VcsLogTextFilter> textFilters,
- @NotNull Collection<VcsLogStructureFilter> structureFilters,
+ @NotNull VcsLogFilterCollection filterCollection,
int maxCount) throws VcsException {
if (!isRepositoryReady(root)) {
return Collections.emptyList();
@@ -196,61 +187,56 @@
List<String> filterParameters = ContainerUtil.newArrayList();
- if (!branchFilters.isEmpty()) {
+ if (filterCollection.getBranchFilter() != null) {
// git doesn't support filtering by several branches very well (--branches parameter give a weak pattern capabilities)
// => by now assuming there is only one branch filter.
- if (branchFilters.size() > 1) {
+ if (filterCollection.getBranchFilter().getBranchNames().size() > 1) {
LOG.warn("More than one branch filter was passed. Using only the first one.");
}
- VcsLogBranchFilter branchFilter = branchFilters.iterator().next();
- filterParameters.add(branchFilter.getBranchName());
+ String branch = filterCollection.getBranchFilter().getBranchNames().iterator().next();
+ GitRepository repository = getRepository(root);
+ assert repository != null : "repository is null for root " + root + " but was previously reported as 'ready'";
+ if (repository.getBranches().findBranchByName(branch) == null) {
+ return Collections.emptyList();
+ }
+ filterParameters.add(branch);
}
else {
filterParameters.addAll(GitHistoryUtils.LOG_ALL);
}
- if (!userFilters.isEmpty()) {
- String authorFilter = joinFilters(userFilters, new Function<VcsLogUserFilter, String>() {
- @Override
- public String fun(VcsLogUserFilter filter) {
- return filter.getUserName(root);
- }
- });
- filterParameters.add(prepareParameter("author", authorFilter));
+ if (filterCollection.getUserFilter() != null) {
+ String authorFilter = StringUtil.join(filterCollection.getUserFilter().getUserNames(root), "|");
+ filterParameters.add(prepareParameter("author", StringUtil.escapeChar(StringUtil.escapeBackSlashes(authorFilter), '|')));
}
- if (!dateFilters.isEmpty()) {
+ if (filterCollection.getDateFilter() != null) {
// assuming there is only one date filter, until filter expressions are defined
- VcsLogDateFilter filter = dateFilters.iterator().next();
+ VcsLogDateFilter filter = filterCollection.getDateFilter();
if (filter.getAfter() != null) {
- filterParameters.add("--after=" + filter.getAfter().toString());
+ filterParameters.add(prepareParameter("after", filter.getAfter().toString()));
}
if (filter.getBefore() != null) {
- filterParameters.add("--before=" + filter.getBefore().toString());
+ filterParameters.add(prepareParameter("before", filter.getBefore().toString()));
}
}
- if (textFilters.size() > 1) {
- LOG.warn("Expected only one text filter: " + textFilters);
- }
- else if (!textFilters.isEmpty()) {
- String textFilter = textFilters.iterator().next().getText();
+ if (filterCollection.getTextFilter() != null) {
+ String textFilter = StringUtil.escapeBackSlashes(filterCollection.getTextFilter().getText());
filterParameters.add(prepareParameter("grep", textFilter));
}
filterParameters.add("--regexp-ignore-case"); // affects case sensitivity of any filter (except file filter)
if (maxCount > 0) {
- filterParameters.add("--max-count=" + maxCount);
+ filterParameters.add(prepareParameter("max-count", String.valueOf(maxCount)));
}
filterParameters.add("--date-order");
// note: structure filter must be the last parameter, because it uses "--" which separates parameters from paths
- if (!structureFilters.isEmpty()) {
+ if (filterCollection.getStructureFilter() != null) {
filterParameters.add("--");
- for (VcsLogStructureFilter filter : structureFilters) {
- for (VirtualFile file : filter.getFiles(root)) {
- filterParameters.add(file.getPath());
- }
+ for (VirtualFile file : filterCollection.getStructureFilter().getFiles(root)) {
+ filterParameters.add(file.getPath());
}
}
@@ -272,11 +258,7 @@
}
private static String prepareParameter(String paramName, String value) {
- return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
- }
-
- private static <T> String joinFilters(Collection<T> filters, Function<T, String> toString) {
- return StringUtil.join(filters, toString, "\\|");
+ return "--" + paramName + "=" + value; // no value quoting needed, because the parameter itself will be quoted by GeneralCommandLine
}
@Nullable
diff --git a/plugins/git4idea/src/git4idea/push/GitPushResult.java b/plugins/git4idea/src/git4idea/push/GitPushResult.java
index c82b5ea..995a3a4 100644
--- a/plugins/git4idea/src/git4idea/push/GitPushResult.java
+++ b/plugins/git4idea/src/git4idea/push/GitPushResult.java
@@ -378,7 +378,7 @@
tree.setAfter(LocalHistory.getInstance().putSystemLabel(myProject, "After push"));
}
else {
- BrowserUtil.launchBrowser(event.getDescription());
+ BrowserUtil.browse(event.getDescription());
}
}
}
diff --git a/plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java b/plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java
index aaf2de9..0124f24 100644
--- a/plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java
+++ b/plugins/git4idea/src/git4idea/remote/GitRememberedInputs.java
@@ -15,12 +15,9 @@
*/
package git4idea.remote;
+import com.intellij.dvcs.DvcsRememberedInputs;
import com.intellij.openapi.components.*;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.ArrayList;
-import java.util.List;
/**
* @author Kirill Likhodedov
@@ -29,79 +26,10 @@
name = "GitRememberedInputs",
storages = @Storage( file = StoragePathMacros.APP_CONFIG + "/vcs.xml")
)
-public class GitRememberedInputs implements PersistentStateComponent<GitRememberedInputs.State> {
-
- private State myState = new State();
-
- public static class State {
- public List<UrlAndUserName> visitedUrls = new ArrayList<UrlAndUserName>();
- public String cloneParentDir = "";
- }
-
- public static class UrlAndUserName {
- public String url;
- public String userName;
- }
-
- public static GitRememberedInputs getInstance() {
- return ServiceManager.getService(GitRememberedInputs.class);
- }
-
- @Override
- public State getState() {
- return myState;
- }
-
- @Override
- public void loadState(State state) {
- myState = state;
- }
-
- public void addUrl(@NotNull String url) {
- addUrl(url, "");
- }
-
- public void addUrl(@NotNull String url, @NotNull String userName) {
- for (UrlAndUserName visitedUrl : myState.visitedUrls) {
- if (visitedUrl.url.equalsIgnoreCase(url)) { // don't add multiple entries for a single url
- if (!userName.isEmpty()) { // rewrite username, unless no username is specified
- visitedUrl.userName = userName;
- }
- return;
- }
- }
-
- UrlAndUserName urlAndUserName = new UrlAndUserName();
- urlAndUserName.url = url;
- urlAndUserName.userName = userName;
- myState.visitedUrls.add(urlAndUserName);
- }
-
- @Nullable
- public String getUserNameForUrl(String url) {
- for (UrlAndUserName urlAndUserName : myState.visitedUrls) {
- if (urlAndUserName.url.equalsIgnoreCase(url)) {
- return urlAndUserName.userName;
- }
- }
- return null;
- }
+public class GitRememberedInputs extends DvcsRememberedInputs implements PersistentStateComponent<DvcsRememberedInputs.State> {
@NotNull
- public List<String> getVisitedUrls() {
- List<String> urls = new ArrayList<String>(myState.visitedUrls.size());
- for (UrlAndUserName urlAndUserName : myState.visitedUrls) {
- urls.add(urlAndUserName.url);
- }
- return urls;
+ public static DvcsRememberedInputs getInstance() {
+ return ServiceManager.getService(GitRememberedInputs.class);
}
-
- public String getCloneParentDir() {
- return myState.cloneParentDir;
- }
-
- public void setCloneParentDir(String cloneParentDir) {
- myState.cloneParentDir = cloneParentDir;
- }
-
}
diff --git a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java
index 4e9533a..c06a0ae 100644
--- a/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java
+++ b/plugins/git4idea/src/git4idea/roots/GitIntegrationEnabler.java
@@ -61,8 +61,8 @@
Collection<VcsRoot> gitRoots = ContainerUtil.filter(vcsRoots, new Condition<VcsRoot>() {
@Override
public boolean value(VcsRoot root) {
- AbstractVcs gitVcs = root.getVcs();
- return gitVcs != null && gitVcs.getName().equals(GitVcs.NAME);
+ AbstractVcs vcs = root.getVcs();
+ return vcs != null && vcs.getName().equals(GitVcs.NAME);
}
});
Collection<VirtualFile> roots = VcsRootErrorsFinder.vcsRootsToVirtualFiles(gitRoots);
diff --git a/plugins/git4idea/src/git4idea/update/GitUpdater.java b/plugins/git4idea/src/git4idea/update/GitUpdater.java
index 6d3b448..ccc3fd6 100644
--- a/plugins/git4idea/src/git4idea/update/GitUpdater.java
+++ b/plugins/git4idea/src/git4idea/update/GitUpdater.java
@@ -22,10 +22,7 @@
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
-import git4idea.GitBranch;
-import git4idea.GitRevisionNumber;
-import git4idea.GitUtil;
-import git4idea.GitVcs;
+import git4idea.*;
import git4idea.branch.GitBranchPair;
import git4idea.branch.GitBranchUtil;
import git4idea.commands.Git;
@@ -103,9 +100,13 @@
@NotNull Map<VirtualFile, GitBranchPair> trackedBranches,
@NotNull ProgressIndicator progressIndicator, @NotNull UpdatedFiles updatedFiles) {
try {
- final GitBranch branchName = GitBranchUtil.getCurrentBranch(project, root);
- final String rebase = GitConfigUtil.getValue(project, root, "branch." + branchName + ".rebase");
- if (rebase != null && rebase.equalsIgnoreCase("true")) {
+ GitLocalBranch branch = GitBranchUtil.getCurrentBranch(project, root);
+ boolean rebase = false;
+ if (branch != null) {
+ String rebaseValue = GitConfigUtil.getValue(project, root, "branch." + branch.getName() + ".rebase");
+ rebase = rebaseValue != null && rebaseValue.equalsIgnoreCase("true");
+ }
+ if (rebase) {
return new GitRebaseUpdater(project, git, root, trackedBranches, progressIndicator, updatedFiles);
}
} catch (VcsException e) {
diff --git a/plugins/git4idea/src/git4idea/util/GitUIUtil.java b/plugins/git4idea/src/git4idea/util/GitUIUtil.java
index 1f9c3ff..ae44f75 100644
--- a/plugins/git4idea/src/git4idea/util/GitUIUtil.java
+++ b/plugins/git4idea/src/git4idea/util/GitUIUtil.java
@@ -155,7 +155,7 @@
return new ListCellRendererWrapper<VirtualFile>() {
@Override
public void customize(final JList list, final VirtualFile file, final int index, final boolean selected, final boolean hasFocus) {
- setText(file == null || !file.isValid() ? "(invalid)" : file.getPresentableUrl());
+ setText(file == null ? "(invalid)" : file.getPresentableUrl());
}
};
}
diff --git a/plugins/git4idea/tests/git4idea/config/GitExecutableDetectorWindowsTest.groovy b/plugins/git4idea/tests/git4idea/config/GitExecutableDetectorWindowsTest.groovy
index e6a97f3..4061b4e 100644
--- a/plugins/git4idea/tests/git4idea/config/GitExecutableDetectorWindowsTest.groovy
+++ b/plugins/git4idea/tests/git4idea/config/GitExecutableDetectorWindowsTest.groovy
@@ -207,7 +207,7 @@
file.createNewFile()
}
- private String convertPath(String path) {
+ private String convertPath(@NotNull String path) {
path = FileUtil.toSystemDependentName(replaceDiskColon(path))
return testRoot.getPath() + File.separator + path
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
index 995c224..878b9b8 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreateGistAction.java
@@ -38,7 +38,7 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubGist;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
+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.GithubNotifications;
@@ -115,7 +115,7 @@
try {
auth = getValidAuthData(project);
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return;
}
catch (IOException e) {
@@ -140,7 +140,7 @@
return;
}
if (dialog.isOpenInBrowser()) {
- BrowserUtil.launchBrowser(url.get());
+ BrowserUtil.browse(url.get());
}
else {
GithubNotifications.showInfoURL(project, "Gist Created Successfully", "Your gist url", url.get());
@@ -153,11 +153,13 @@
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);
}
- });
+ }
+ );
}
@NotNull
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java b/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
index 6e074ff..ee357b1 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubCreatePullRequestWorker.java
@@ -15,7 +15,8 @@
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.ThrowableConvertor;
-import com.intellij.util.containers.*;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.HashMap;
import git4idea.DialogManager;
import git4idea.GitCommit;
@@ -34,7 +35,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.*;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
+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;
@@ -43,8 +44,6 @@
import java.io.IOException;
import java.util.*;
-import java.util.HashSet;
-import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -139,13 +138,14 @@
try {
auth = 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);
}
});
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return null;
}
catch (IOException e) {
@@ -161,6 +161,7 @@
try {
GithubInfo info =
GithubUtil.computeValueInModal(myProject, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubInfo, IOException>() {
+ @NotNull
@Override
public GithubInfo convert(ProgressIndicator indicator) throws IOException {
// configure remote
@@ -209,6 +210,7 @@
if (canShowDiff()) {
for (final String branch : info.getBranches()) {
myDiffInfos.put(branch, new FutureTask<DiffInfo>(new Callable<DiffInfo>() {
+ @Nullable
@Override
public DiffInfo call() throws Exception {
return loadDiffInfo(myProject, myGitRepository, myCurrentBranch, myTargetRemote + "/" + branch);
@@ -219,7 +221,7 @@
return new GithubTargetInfo(info.getBranches());
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return null;
}
catch (IOException e) {
@@ -244,11 +246,34 @@
@Nullable
public GithubFullPath showTargetDialog() {
+ return showTargetDialog(false);
+ }
+
+ @Nullable
+ public GithubFullPath showTargetDialog(boolean firstTime) {
final GithubInfo2 info = getAvailableForksInModal(myProject, myGitRepository, myAuth, myPath);
if (info == null) {
return null;
}
+ if (firstTime) {
+ if (info.getForks().size() == 1) {
+ return info.getForks().iterator().next();
+ }
+ if (info.getForks().size() == 2) {
+ Iterator<GithubFullPath> it = info.getForks().iterator();
+ GithubFullPath path1 = it.next();
+ GithubFullPath path2 = it.next();
+
+ if (myPath.equals(path1)) {
+ return path2;
+ }
+ if (myPath.equals(path2)) {
+ return path1;
+ }
+ }
+ }
+
Convertor<String, GithubFullPath> getForkPath = new Convertor<String, GithubFullPath>() {
@Nullable
@Override
@@ -431,6 +456,7 @@
try {
return GithubUtil
.computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubInfo2, IOException>() {
+ @NotNull
@Override
public GithubInfo2 convert(ProgressIndicator indicator) throws IOException {
final Set<GithubFullPath> forks = new HashSet<GithubFullPath>();
@@ -453,7 +479,7 @@
}
});
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return null;
}
catch (IOException e) {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java
index 3763e5f..f587d44 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubOpenInBrowserAction.java
@@ -99,7 +99,7 @@
String urlToOpen = getGithubUrl(project, virtualFile, editor);
if (urlToOpen != null) {
- BrowserUtil.launchBrowser(urlToOpen);
+ BrowserUtil.browse(urlToOpen);
}
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
index 42c3479..d3f9125 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubRebaseAction.java
@@ -43,7 +43,7 @@
import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubFullPath;
import org.jetbrains.plugins.github.api.GithubRepoDetailed;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
+import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
import org.jetbrains.plugins.github.util.*;
import java.io.IOException;
@@ -105,7 +105,6 @@
GithubNotifications.showError(project, CANNOT_PERFORM_GITHUB_REBASE, "Can't find git repository");
return;
}
- final VirtualFile root = gitRepository.getRoot();
BasicAction.saveAll();
@@ -118,7 +117,7 @@
if (upstreamRemoteUrl == null) {
LOG.info("Configuring upstream remote");
indicator.setText("Configuring upstream remote...");
- upstreamRemoteUrl = configureUpstreamRemote(project, root, gitRepository, indicator);
+ upstreamRemoteUrl = configureUpstreamRemote(project, gitRepository, indicator);
if (upstreamRemoteUrl == null) {
return;
}
@@ -149,14 +148,13 @@
LOG.info("Rebasing current branch");
indicator.setText("Rebasing current branch...");
- rebaseCurrentBranch(project, root, gitRepository, indicator);
+ rebaseCurrentBranch(project, gitRepository, indicator);
}
}.queue();
}
@Nullable
static String configureUpstreamRemote(@NotNull Project project,
- @NotNull VirtualFile root,
@NotNull GitRepository gitRepository,
@NotNull ProgressIndicator indicator) {
GithubRepoDetailed repositoryInfo = loadRepositoryInfo(project, gitRepository, indicator);
@@ -199,14 +197,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());
- }
- });
+ @Override
+ @NotNull
+ public GithubRepoDetailed convert(GithubAuthData authData) throws IOException {
+ return GithubApiUtil.getDetailedRepoInfo(authData, userAndRepo.getUser(), userAndRepo.getRepository());
+ }
+ });
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return null;
}
catch (IOException e) {
@@ -227,7 +225,6 @@
}
private static void rebaseCurrentBranch(@NotNull final Project project,
- @NotNull final VirtualFile root,
@NotNull final GitRepository gitRepository,
@NotNull final ProgressIndicator indicator) {
final Git git = ServiceManager.getService(project, Git.class);
@@ -237,7 +234,7 @@
new Runnable() {
@Override
public void run() {
- doRebaseCurrentBranch(project, root, indicator);
+ 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 4d70975..d3e72a2 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShareAction.java
@@ -52,7 +52,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.*;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
+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;
@@ -73,7 +73,7 @@
private static final Logger LOG = GithubUtil.LOG;
public GithubShareAction() {
- super("Share project on GitHub", "Easily share project on GitHub", GithubIcons.Github_icon);
+ super("Share Project on GitHub", "Easily share project on GitHub", GithubIcons.Github_icon);
}
public void update(AnActionEvent e) {
@@ -228,7 +228,7 @@
}
});
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return null;
}
catch (IOException e) {
@@ -288,6 +288,8 @@
final List<VirtualFile> trackedFiles = ChangeListManager.getInstance(project).getAffectedFiles();
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);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java
index 70bc450..36e5bc4 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/GithubShowCommitInBrowserAction.java
@@ -51,7 +51,7 @@
String githubUrl = GithubUrlUtil.getGithubHost() + '/' + userAndRepository.getUser() + '/'
+ userAndRepository.getRepository() + "/commit/" + revisionHash;
- BrowserUtil.launchBrowser(githubUrl);
+ BrowserUtil.browse(githubUrl);
}
}
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 885f252..f444e95 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubApiUtil.java
@@ -18,7 +18,6 @@
import com.google.gson.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ThrowableConvertor;
import com.intellij.util.net.HttpConfigurable;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.auth.AuthScope;
@@ -27,8 +26,13 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.exceptions.*;
-import org.jetbrains.plugins.github.util.*;
+import org.jetbrains.plugins.github.util.GithubAuthData;
+import org.jetbrains.plugins.github.util.GithubSettings;
+import org.jetbrains.plugins.github.util.GithubUrlUtil;
+import org.jetbrains.plugins.github.util.GithubUtil;
+import sun.security.validator.ValidatorException;
+import javax.net.ssl.SSLHandshakeException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -133,40 +137,46 @@
@NotNull final Collection<Header> headers,
@NotNull final HttpVerb verb) throws IOException {
HttpClient client = getHttpClient(auth.getBasicAuth(), auth.isUseProxy());
- return GithubSslSupport.getInstance()
- .executeSelfSignedCertificateAwareRequest(client, uri, new ThrowableConvertor<String, HttpMethod, IOException>() {
- @Override
- public HttpMethod convert(String uri) throws IOException {
- HttpMethod method;
- switch (verb) {
- case POST:
- method = new PostMethod(uri);
- if (requestBody != null) {
- ((PostMethod)method).setRequestEntity(new StringRequestEntity(requestBody, "application/json", "UTF-8"));
- }
- break;
- case GET:
- method = new GetMethod(uri);
- break;
- case DELETE:
- method = new DeleteMethod(uri);
- break;
- case HEAD:
- method = new HeadMethod(uri);
- break;
- default:
- throw new IllegalStateException("Wrong HttpVerb: unknown method: " + verb.toString());
- }
- GithubAuthData.TokenAuth tokenAuth = auth.getTokenAuth();
- if (tokenAuth != null) {
- method.addRequestHeader("Authorization", "token " + tokenAuth.getToken());
- }
- for (Header header : headers) {
- method.addRequestHeader(header);
- }
- return method;
+ HttpMethod method;
+ switch (verb) {
+ case POST:
+ method = new PostMethod(uri);
+ if (requestBody != null) {
+ ((PostMethod)method).setRequestEntity(new StringRequestEntity(requestBody, "application/json", "UTF-8"));
}
- });
+ break;
+ case GET:
+ method = new GetMethod(uri);
+ break;
+ case DELETE:
+ method = new DeleteMethod(uri);
+ break;
+ case HEAD:
+ method = new HeadMethod(uri);
+ break;
+ default:
+ throw new IllegalStateException("Wrong HttpVerb: unknown method: " + verb.toString());
+ }
+
+ GithubAuthData.TokenAuth tokenAuth = auth.getTokenAuth();
+ if (tokenAuth != null) {
+ method.addRequestHeader("Authorization", "token " + tokenAuth.getToken());
+ }
+ for (Header header : headers) {
+ method.addRequestHeader(header);
+ }
+
+ try {
+ client.executeMethod(method);
+ }
+ catch (SSLHandshakeException e) { // User canceled operation from CertificatesManager
+ if (e.getCause() instanceof ValidatorException) {
+ LOG.info("Host SSL certificate is not trusted", e);
+ throw new GithubOperationCanceledException("Host SSL certificate is not trusted", e);
+ }
+ throw e;
+ }
+ return method;
}
@NotNull
@@ -208,9 +218,18 @@
case HttpStatus.SC_PAYMENT_REQUIRED:
case HttpStatus.SC_FORBIDDEN:
String message = getErrorMessage(method);
+
+ Header headerOTP = method.getResponseHeader("X-GitHub-OTP");
+ if (headerOTP != null) {
+ if (headerOTP.getValue().startsWith("required")) {
+ throw new GithubTwoFactorAuthenticationException(message);
+ }
+ }
+
if (message.contains("API rate limit exceeded")) {
throw new GithubRateLimitExceededException(message);
}
+
throw new GithubAuthenticationException("Request response: " + message);
default:
throw new GithubStatusCodeException(code + ": " + getErrorMessage(method), code);
@@ -421,10 +440,21 @@
}
@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
+
+ return getScopedToken(auth, scopes, note);
+ }
+
+ @NotNull
public static String getReadOnlyToken(@NotNull GithubAuthData auth, @NotNull String user, @NotNull String repo, @Nullable String note)
throws IOException {
GithubRepo repository = getDetailedRepoInfo(auth, user, repo);
+ // TODO: use read-only token for private repos when it will be available
List<String> scopes = repository.isPrivate() ? Collections.singletonList("repo") : Collections.<String>emptyList();
return getScopedToken(auth, scopes, note);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java
index c56bb44..2c82c07 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserDetailed.java
@@ -25,10 +25,10 @@
@Nullable private final String myName;
@Nullable private final String myEmail;
- private final int myOwnedPrivateRepos;
+ @Nullable private final Integer myOwnedPrivateRepos;
- @NotNull private final String myType;
- @NotNull private final UserPlan myPlan;
+ @Nullable private final String myType;
+ @Nullable private final UserPlan myPlan;
public static class UserPlan {
@NotNull private final String myName;
@@ -50,7 +50,7 @@
}
public boolean canCreatePrivateRepo() {
- return getPlan().getPrivateRepos() > getOwnedPrivateRepos();
+ return getPlan() == null || getOwnedPrivateRepos() == null || getPlan().getPrivateRepos() > getOwnedPrivateRepos();
}
public GithubUserDetailed(@NotNull String login,
@@ -58,9 +58,9 @@
@Nullable String gravatarId,
@Nullable String name,
@Nullable String email,
- int ownedPrivateRepos,
- @NotNull String type,
- @NotNull UserPlan plan) {
+ @Nullable Integer ownedPrivateRepos,
+ @Nullable String type,
+ @Nullable UserPlan plan) {
super(login, htmlUrl, gravatarId);
myName = name;
myEmail = email;
@@ -79,16 +79,17 @@
return myEmail;
}
- @NotNull
+ @Nullable
public String getType() {
return myType;
}
- public int getOwnedPrivateRepos() {
+ @Nullable
+ public Integer getOwnedPrivateRepos() {
return myOwnedPrivateRepos;
}
- @NotNull
+ @Nullable
public UserPlan getPlan() {
return myPlan;
}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java
index 22bed5d..04d642f 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/api/GithubUserRaw.java
@@ -80,7 +80,8 @@
@SuppressWarnings("ConstantConditions")
@NotNull
public GithubUserDetailed createUserDetailed() {
- return new GithubUserDetailed(login, htmlUrl, gravatarId, name, email, ownedPrivateRepos, type, plan.create());
+ GithubUserDetailed.UserPlan plan = this.plan == null ? null : this.plan.create();
+ return new GithubUserDetailed(login, htmlUrl, gravatarId, name, email, ownedPrivateRepos, type, plan);
}
@SuppressWarnings("unchecked")
diff --git a/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubAuthenticationCanceledException.java b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubAuthenticationCanceledException.java
deleted file mode 100644
index 69ccfbc..0000000
--- a/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubAuthenticationCanceledException.java
+++ /dev/null
@@ -1,37 +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.github.exceptions;
-
-/**
- * @author Aleksey Pivovarov
- */
-public class GithubAuthenticationCanceledException extends GithubAuthenticationException {
- public GithubAuthenticationCanceledException() {
- super();
- }
-
- public GithubAuthenticationCanceledException(String message) {
- super(message);
- }
-
- public GithubAuthenticationCanceledException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public GithubAuthenticationCanceledException(Throwable cause) {
- super(cause);
- }
-}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubJsonException.java b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubJsonException.java
index 7bc102a..3afe12d 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubJsonException.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubJsonException.java
@@ -15,8 +15,6 @@
*/
package org.jetbrains.plugins.github.exceptions;
-import java.io.IOException;
-
/**
* @author Aleksey Pivovarov
*/
diff --git a/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubOperationCanceledException.java b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubOperationCanceledException.java
new file mode 100644
index 0000000..4868d00
--- /dev/null
+++ b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubOperationCanceledException.java
@@ -0,0 +1,39 @@
+/*
+ * 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.exceptions;
+
+import java.io.IOException;
+
+/**
+ * @author Aleksey Pivovarov
+ */
+public class GithubOperationCanceledException extends IOException {
+ public GithubOperationCanceledException() {
+ super();
+ }
+
+ public GithubOperationCanceledException(String message) {
+ super(message);
+ }
+
+ public GithubOperationCanceledException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public GithubOperationCanceledException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubTwoFactorAuthenticationException.java b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubTwoFactorAuthenticationException.java
new file mode 100644
index 0000000..20210a1
--- /dev/null
+++ b/plugins/github/src/org/jetbrains/plugins/github/exceptions/GithubTwoFactorAuthenticationException.java
@@ -0,0 +1,34 @@
+/*
+ * 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.exceptions;
+
+public class GithubTwoFactorAuthenticationException extends GithubAuthenticationException {
+ public GithubTwoFactorAuthenticationException() {
+ super();
+ }
+
+ public GithubTwoFactorAuthenticationException(String message) {
+ super(message);
+ }
+
+ public GithubTwoFactorAuthenticationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public GithubTwoFactorAuthenticationException(Throwable cause) {
+ super(cause);
+ }
+}
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 5858a65..6689138 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/extensions/GithubCheckoutProvider.java
@@ -30,7 +30,7 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubRepo;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
+import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
import org.jetbrains.plugins.github.util.GithubAuthData;
import org.jetbrains.plugins.github.util.GithubNotifications;
import org.jetbrains.plugins.github.util.GithubUtil;
@@ -57,6 +57,7 @@
try {
availableRepos = GithubUtil
.computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, List<GithubRepo>, IOException>() {
+ @NotNull
@Override
public List<GithubRepo> convert(ProgressIndicator indicator) throws IOException {
return GithubUtil.runWithValidAuth(project, indicator, new ThrowableConvertor<GithubAuthData, List<GithubRepo>, IOException>() {
@@ -68,7 +69,7 @@
}
});
}
- catch (GithubAuthenticationCanceledException e) {
+ catch (GithubOperationCanceledException e) {
return;
}
catch (IOException e) {
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 bbb94ca..8af4136 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/tasks/GithubRepositoryEditor.java
@@ -13,8 +13,8 @@
import com.intellij.util.ui.GridBag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
import org.jetbrains.plugins.github.util.GithubAuthData;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
import org.jetbrains.plugins.github.util.GithubNotifications;
import org.jetbrains.plugins.github.util.GithubUtil;
import org.jetbrains.plugins.github.api.GithubApiUtil;
@@ -120,6 +120,7 @@
try {
myToken.setText(
GithubUtil.computeValueInModal(myProject, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, String, IOException>() {
+ @NotNull
@Override
public String convert(ProgressIndicator indicator) throws IOException {
return GithubUtil
@@ -133,7 +134,7 @@
}
}));
}
- catch (GithubAuthenticationCanceledException ignore) {
+ catch (GithubOperationCanceledException ignore) {
}
catch (IOException e) {
GithubNotifications.showErrorDialog(myProject, "Can't get access token", e);
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCreatePullRequestDialog.java b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCreatePullRequestDialog.java
index 338003e..f062742 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCreatePullRequestDialog.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubCreatePullRequestDialog.java
@@ -106,7 +106,7 @@
setTarget(defaultForkPath);
}
else {
- if (!showTargetDialog()) {
+ if (!showTargetDialog(true)) {
close(CANCEL_EXIT_CODE);
return;
}
@@ -115,7 +115,11 @@
}
private boolean showTargetDialog() {
- GithubFullPath forkPath = myWorker.showTargetDialog();
+ return showTargetDialog(false);
+ }
+
+ private boolean showTargetDialog(boolean firstTime) {
+ GithubFullPath forkPath = myWorker.showTargetDialog(firstTime);
if (forkPath == null) {
return false;
}
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 26bc40c..7660fb5 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubLoginDialog.java
@@ -1,10 +1,13 @@
package org.jetbrains.plugins.github.ui;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
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.GithubSettings;
import org.jetbrains.plugins.github.util.GithubUtil;
@@ -22,9 +25,11 @@
protected final GithubLoginPanel myGithubLoginPanel;
protected final GithubSettings mySettings;
+ protected final Project myProject;
public GithubLoginDialog(@Nullable final Project project) {
super(project, true);
+ myProject = project;
myGithubLoginPanel = new GithubLoginPanel(this);
mySettings = GithubSettings.getInstance();
@@ -68,7 +73,13 @@
protected void doOKAction() {
final GithubAuthData auth = myGithubLoginPanel.getAuthData();
try {
- GithubUtil.checkAuthData(auth);
+ GithubUtil.computeValueInModal(myProject, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubUser, IOException>() {
+ @NotNull
+ @Override
+ public GithubUser convert(ProgressIndicator indicator) throws IOException {
+ return GithubUtil.checkAuthData(auth);
+ }
+ });
saveCredentials(auth);
if (mySettings.isSavePasswordMakesSense()) {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
index 747f0ec..a3549a4 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.form
@@ -7,7 +7,6 @@
</constraints>
<properties/>
<clientProperties>
- <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
<html.disable class="java.lang.Boolean" value="false"/>
</clientProperties>
<border type="none"/>
@@ -107,7 +106,7 @@
</component>
</children>
</grid>
- <grid id="6d9fb" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="6d9fb" layout-manager="GridLayoutManager" row-count="2" 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>
<card name="Token"/>
@@ -137,6 +136,14 @@
<grid row="1" 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="1b2df" class="javax.swing.JButton" binding="myCreateTokenButton">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Create API Token"/>
+ </properties>
+ </component>
</children>
</grid>
</children>
@@ -164,7 +171,6 @@
</constraints>
<properties/>
<clientProperties>
- <BorderFactoryClass class="java.lang.String" value="com.intellij.ui.IdeBorderFactory$PlainSmallWithIndent"/>
<html.disable class="java.lang.Boolean" value="false"/>
</clientProperties>
<border type="etched" title="Other Settings:"/>
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 72315eb..9e8f9ab 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/ui/GithubSettingsPanel.java
@@ -17,20 +17,23 @@
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.DocumentAdapter;
import com.intellij.ui.HyperlinkAdapter;
import com.intellij.ui.components.JBLabel;
+import com.intellij.util.ThrowableConvertor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.github.util.GithubAuthData;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
-import org.jetbrains.plugins.github.util.GithubNotifications;
-import org.jetbrains.plugins.github.util.GithubSettings;
-import org.jetbrains.plugins.github.util.GithubUtil;
+import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubUser;
+import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
+import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
+import org.jetbrains.plugins.github.util.*;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -57,7 +60,7 @@
private JTextField myLoginTextField;
private JPasswordField myPasswordField;
- private JPasswordField myTokenField;
+ private JPasswordField myTokenField; // look at createUIComponents() to understand
private JTextPane mySignupTextField;
private JPanel myPane;
private JButton myTestButton;
@@ -66,6 +69,7 @@
private JPanel myCardPanel;
private JBLabel myAuthTypeLabel;
private JSpinner myTimeoutSpinner;
+ private JButton myCreateTokenButton;
private boolean myCredentialsModified;
@@ -84,11 +88,22 @@
myAuthTypeComboBox.addItem(AUTH_PASSWORD);
myAuthTypeComboBox.addItem(AUTH_TOKEN);
+ final Project project = ProjectManager.getInstance().getDefaultProject();
+
myTestButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
try {
- GithubUser user = GithubUtil.checkAuthData(getAuthData());
+ final GithubAuthData auth = getAuthData();
+ GithubUser user = GithubUtil
+ .computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, GithubUser, IOException>() {
+ @NotNull
+ @Override
+ public GithubUser convert(ProgressIndicator indicator) throws IOException {
+ return GithubUtil.checkAuthData(auth);
+ }
+ });
+
if (GithubAuthData.AuthType.TOKEN.equals(getAuthType())) {
GithubNotifications.showInfoDialog(myPane, "Success", "Connection successful for user " + user.getLogin());
}
@@ -96,6 +111,8 @@
GithubNotifications.showInfoDialog(myPane, "Success", "Connection successful");
}
}
+ catch (GithubOperationCanceledException ignore) {
+ }
catch (GithubAuthenticationException ex) {
GithubNotifications.showErrorDialog(myPane, "Login Failure", "Can't login using given credentials: " + ex.getMessage());
}
@@ -106,6 +123,36 @@
}
});
+ myCreateTokenButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ try {
+ myPasswordField.setText(
+ GithubUtil.computeValueInModal(project, "Access to GitHub", new ThrowableConvertor<ProgressIndicator, String, IOException>() {
+ @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");
+ }
+ }
+ );
+ }
+ })
+ );
+ }
+ catch (GithubOperationCanceledException ignore) {
+ }
+ catch (IOException ex) {
+ LOG.info(ex);
+ GithubNotifications.showErrorDialog(myPane, "Can't create API token", ex);
+ }
+ }
+ });
+
myPasswordField.getDocument().addDocumentListener(new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java
index 4b3b6e3..a6f8584 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubNotifications.java
@@ -141,6 +141,7 @@
Messages.showInfoMessage(component, getErrorTextFromException(e), title);
}
+ @Messages.YesNoResult
public static int showYesNoDialog(final @Nullable Project project, final @NotNull String title, final @NotNull String message) {
return Messages.showYesNoDialog(project, message, title, Messages.getQuestionIcon());
}
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 deb9e9e..49199c0 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSettings.java
@@ -26,9 +26,6 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.github.api.GithubApiUtil;
-import java.util.ArrayList;
-import java.util.Collection;
-
import static org.jetbrains.plugins.github.util.GithubAuthData.AuthType;
/**
@@ -61,7 +58,6 @@
public boolean OPEN_IN_BROWSER_GIST = true;
public boolean PRIVATE_GIST = true;
public boolean SAVE_PASSWORD = true;
- @NotNull public Collection<String> TRUSTED_HOSTS = new ArrayList<String>();
public int CONNECTION_TIMEOUT = 5000;
}
@@ -146,17 +142,6 @@
}
@NotNull
- public Collection<String> getTrustedHosts() {
- return myState.TRUSTED_HOSTS;
- }
-
- public void addTrustedHost(String host) {
- if (!myState.TRUSTED_HOSTS.contains(host)) {
- myState.TRUSTED_HOSTS.add(host);
- }
- }
-
- @NotNull
private String getPassword() {
String password;
try {
diff --git a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSslSupport.java b/plugins/github/src/org/jetbrains/plugins/github/util/GithubSslSupport.java
deleted file mode 100644
index 35a861e..0000000
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubSslSupport.java
+++ /dev/null
@@ -1,129 +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.github.util;
-
-import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.vcs.CalledInAwt;
-import com.intellij.util.ThrowableConvertor;
-import org.apache.commons.httpclient.HostConfiguration;
-import org.apache.commons.httpclient.HttpClient;
-import org.apache.commons.httpclient.HttpMethod;
-import org.apache.commons.httpclient.URI;
-import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
-import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import sun.security.validator.ValidatorException;
-
-import java.io.IOException;
-
-/**
- * Provides various methods to work with SSL certificate protected HTTPS connections.
- *
- * @author Kirill Likhodedov
- */
-public class GithubSslSupport {
-
- public static GithubSslSupport getInstance() {
- return ServiceManager.getService(GithubSslSupport.class);
- }
-
- /**
- * Tries to execute the {@link HttpMethod} and captures the {@link ValidatorException exception} which is thrown if user connects
- * to an HTTPS server with a non-trusted (probably, self-signed) SSL certificate. In which case proposes to cancel the connection
- * or to proceed without certificate check.
- *
- * @param methodCreator a function to create the HttpMethod. This is required instead of just {@link HttpMethod} instance, because the
- * implementation requires the HttpMethod to be recreated in certain circumstances.
- * @return the HttpMethod instance which was actually executed
- * and which can be {@link HttpMethod#getResponseBodyAsString() asked for the response}.
- * @throws IOException in case of other errors or if user declines the proposal of non-trusted connection.
- */
- @NotNull
- public HttpMethod executeSelfSignedCertificateAwareRequest(@NotNull HttpClient client,
- @NotNull String uri,
- @NotNull ThrowableConvertor<String, HttpMethod, IOException> methodCreator)
- throws IOException {
- HttpMethod method = methodCreator.convert(uri);
- try {
- client.executeMethod(method);
- return method;
- }
- catch (IOException e) {
- HttpMethod m = handleCertificateExceptionAndRetry(e, method.getURI().getHost(), client, method.getURI(), methodCreator);
- if (m == null) {
- throw e;
- }
- return m;
- }
- }
-
- @Nullable
- private static HttpMethod handleCertificateExceptionAndRetry(@NotNull IOException e,
- @NotNull String host,
- @NotNull HttpClient client,
- @NotNull URI uri,
- @NotNull ThrowableConvertor<String, HttpMethod, IOException> methodCreator)
- throws IOException {
- if (!isCertificateException(e)) {
- throw e;
- }
-
- if (isTrusted(host)) {
- // creating a special configuration that allows connections to non-trusted HTTPS hosts
- // see the javadoc to EasySSLProtocolSocketFactory for details
- Protocol easyHttps = new Protocol("https", (ProtocolSocketFactory)new EasySSLProtocolSocketFactory(), 443);
- HostConfiguration hc = new HostConfiguration();
- hc.setHost(host, 443, easyHttps);
- String relativeUri = new URI(uri.getPathQuery(), false).getURI();
- // it is important to use relative URI here, otherwise our custom protocol won't work.
- // we have to recreate the method, because HttpMethod#setUri won't overwrite the host,
- // and changing host by hands (HttpMethodBase#setHostConfiguration) is deprecated.
- HttpMethod method = methodCreator.convert(relativeUri);
- client.executeMethod(hc, method);
- return method;
- }
- throw e;
- }
-
- public static boolean isCertificateException(IOException e) {
- return e.getCause() instanceof ValidatorException;
- }
-
- private static boolean isTrusted(@NotNull String host) {
- return GithubSettings.getInstance().getTrustedHosts().contains(host.toLowerCase());
- }
-
- private static void saveToTrusted(@NotNull String host) {
- GithubSettings.getInstance().addTrustedHost(host.toLowerCase());
- }
-
- @CalledInAwt
- public boolean askIfShouldProceed(final String url) {
- String host = GithubUrlUtil.getHostFromUrl(url);
-
- int choice = Messages.showYesNoDialog("The security certificate of " + host + " is not trusted. Do you want to proceed anyway?",
- "Not Trusted Certificate", "Proceed anyway", "No, I don't trust", Messages.getErrorIcon());
- boolean trust = (choice == Messages.YES);
- if (trust) {
- saveToTrusted(host);
- }
- return trust;
- }
-
-}
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 804d3a1..a3eb6c4 100644
--- a/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
+++ b/plugins/github/src/org/jetbrains/plugins/github/util/GithubUtil.java
@@ -29,6 +29,7 @@
import com.intellij.util.ThrowableConsumer;
import com.intellij.util.ThrowableConvertor;
import com.intellij.util.containers.Convertor;
+import git4idea.DialogManager;
import git4idea.GitUtil;
import git4idea.commands.GitCommand;
import git4idea.commands.GitSimpleHandler;
@@ -43,8 +44,8 @@
import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubFullPath;
import org.jetbrains.plugins.github.api.GithubUserDetailed;
-import org.jetbrains.plugins.github.exceptions.GithubAuthenticationCanceledException;
import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
+import org.jetbrains.plugins.github.exceptions.GithubOperationCanceledException;
import org.jetbrains.plugins.github.ui.GithubBasicLoginDialog;
import org.jetbrains.plugins.github.ui.GithubLoginDialog;
@@ -82,12 +83,6 @@
task.consume(auth);
return auth;
}
- catch (IOException e) {
- if (checkSSLCertificate(e, auth.getHost(), indicator)) {
- return runAndGetValidAuth(project, indicator, task);
- }
- throw e;
- }
}
@NotNull
@@ -105,12 +100,6 @@
auth = getValidAuthData(project, indicator);
return task.convert(auth);
}
- catch (IOException e) {
- if (checkSSLCertificate(e, auth.getHost(), indicator)) {
- return runWithValidAuth(project, indicator, task);
- }
- throw e;
- }
}
@NotNull
@@ -132,27 +121,6 @@
auth = getValidBasicAuthDataForHost(project, indicator, host);
return task.convert(auth);
}
- catch (IOException e) {
- if (checkSSLCertificate(e, auth.getHost(), indicator)) {
- return runWithValidBasicAuthForHost(project, indicator, host, task);
- }
- throw e;
- }
- }
-
- private static boolean checkSSLCertificate(IOException e, final String host, ProgressIndicator indicator) {
- final GithubSslSupport sslSupport = GithubSslSupport.getInstance();
- if (GithubSslSupport.isCertificateException(e)) {
- final AtomicReference<Boolean> result = new AtomicReference<Boolean>();
- ApplicationManager.getApplication().invokeAndWait(new Runnable() {
- @Override
- public void run() {
- result.set(sslSupport.askIfShouldProceed(host));
- }
- }, indicator.getModalityState());
- return result.get();
- }
- return false;
}
/**
@@ -160,16 +128,16 @@
*/
@NotNull
public static GithubAuthData getValidAuthData(@Nullable Project project, @NotNull ProgressIndicator indicator)
- throws GithubAuthenticationCanceledException {
+ throws GithubOperationCanceledException {
final GithubLoginDialog dialog = new GithubLoginDialog(project);
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
- dialog.show();
+ DialogManager.show(dialog);
}
}, indicator.getModalityState());
if (!dialog.isOK()) {
- throw new GithubAuthenticationCanceledException("Can't get valid credentials");
+ throw new GithubOperationCanceledException("Can't get valid credentials");
}
return dialog.getAuthData();
}
@@ -179,18 +147,18 @@
*/
@NotNull
public static GithubAuthData getValidBasicAuthDataForHost(@Nullable Project project,
- @NotNull ProgressIndicator indicator, @NotNull String host)
- throws GithubAuthenticationCanceledException {
+ @NotNull ProgressIndicator indicator,
+ @NotNull String host) throws GithubOperationCanceledException {
final GithubLoginDialog dialog = new GithubBasicLoginDialog(project);
dialog.lockHost(host);
ApplicationManager.getApplication().invokeAndWait(new Runnable() {
@Override
public void run() {
- dialog.show();
+ DialogManager.show(dialog);
}
}, indicator.getModalityState());
if (!dialog.isOK()) {
- throw new GithubAuthenticationCanceledException("Can't get valid credentials");
+ throw new GithubOperationCanceledException("Can't get valid credentials");
}
return dialog.getAuthData();
}
@@ -233,17 +201,7 @@
throw new GithubAuthenticationException("Anonymous connection not allowed");
}
- try {
- return testConnection(auth);
- }
- catch (IOException e) {
- if (GithubSslSupport.isCertificateException(e)) {
- if (GithubSslSupport.getInstance().askIfShouldProceed(auth.getHost())) {
- return testConnection(auth);
- }
- }
- throw e;
- }
+ return testConnection(auth);
}
@NotNull
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
index 7968008..0d394d5 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTest.java
@@ -112,6 +112,8 @@
}
public void testWrongLogin() throws Throwable {
+ registerDefaultLoginDialogHandler();
+
List<FileContent> expected = createContent();
GithubAuthData auth = myGitHubSettings.getAuthData();
@@ -123,6 +125,8 @@
}
public void testWrongPassword() throws Throwable {
+ registerDefaultLoginDialogHandler();
+
List<FileContent> expected = createContent();
GithubAuthData auth = myGitHubSettings.getAuthData();
diff --git a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
index 150e7e8..5e785fa 100644
--- a/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
+++ b/plugins/github/test/org/jetbrains/plugins/github/GithubCreateGistTestBase.java
@@ -15,13 +15,16 @@
*/
package org.jetbrains.plugins.github;
+import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Clock;
import com.intellij.openapi.util.Comparing;
import com.intellij.util.text.DateFormatUtil;
+import git4idea.test.TestDialogHandler;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.github.api.GithubApiUtil;
import org.jetbrains.plugins.github.api.GithubGist;
import org.jetbrains.plugins.github.test.GithubTest;
+import org.jetbrains.plugins.github.ui.GithubLoginDialog;
import java.io.IOException;
import java.util.ArrayList;
@@ -129,4 +132,13 @@
protected void checkEquals(@NotNull List<FileContent> expected, @NotNull List<FileContent> actual) {
assertTrue("Gist content differs from sample", Comparing.haveEqualElements(expected, actual));
}
+
+ protected void registerDefaultLoginDialogHandler() {
+ myDialogManager.registerDialogHandler(GithubLoginDialog.class, new TestDialogHandler<GithubLoginDialog>() {
+ @Override
+ public int handleDialog(GithubLoginDialog dialog) {
+ return DialogWrapper.CANCEL_EXIT_CODE;
+ }
+ });
+ }
}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacet.java b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacet.java
index 541e524..4e9fbc1 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacet.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineFacet.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 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.xml.XmlFile;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomFileElement;
import com.intellij.util.xml.DomManager;
@@ -84,7 +84,7 @@
final DomFileElement<DomElement> element = domManager.getFileElement((XmlFile)file, DomElement.class);
if (element == null) return null;
final DomElement root = element.getRootElement();
- if (!ReflectionCache.isAssignable(domClass, root.getClass())) return null;
+ if (!ReflectionUtil.isAssignable(domClass, root.getClass())) return null;
return (T)root;
}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineSupportProvider.java b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineSupportProvider.java
index 39d2f24..0fb96f2 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineSupportProvider.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/facet/AppEngineSupportProvider.java
@@ -37,7 +37,9 @@
import com.intellij.openapi.ui.LabeledComponent;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactManager;
import com.intellij.packaging.artifacts.ArtifactType;
@@ -56,6 +58,8 @@
import java.awt.*;
import java.io.IOException;
import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
/**
* @author nik
@@ -120,7 +124,7 @@
webIntegration.setupRunConfiguration(sdk, artifact, project);
webIntegration.addDevServerToModuleDependencies(rootModel, sdk);
- final Library apiJar = addProjectLibrary(module, "AppEngine API", sdk.getLibUserDirectoryPath(), VirtualFile.EMPTY_ARRAY);
+ final Library apiJar = addProjectLibrary(module, "AppEngine API", sdk.getUserLibraryPaths(), VirtualFile.EMPTY_ARRAY);
rootModel.addLibraryEntry(apiJar);
webIntegration.addLibraryToArtifact(apiJar, artifact, project);
@@ -151,7 +155,7 @@
catch (IOException e) {
LOG.error(e);
}
- final Library library = addProjectLibrary(module, "AppEngine ORM", sdk.getOrmLibDirectoryPath(), sdk.getOrmLibSources());
+ final Library library = addProjectLibrary(module, "AppEngine ORM", Collections.singletonList(sdk.getOrmLibDirectoryPath()), sdk.getOrmLibSources());
rootModel.addLibraryEntry(library);
webIntegration.addLibraryToArtifact(library, artifact, project);
}
@@ -174,7 +178,7 @@
return artifactManager.addArtifact(module.getName(), artifactType, root);
}
- private static Library addProjectLibrary(final Module module, final String name, final String path, final VirtualFile[] sources) {
+ private static Library addProjectLibrary(final Module module, final String name, final List<String> jarDirectories, final VirtualFile[] sources) {
return new WriteAction<Library>() {
protected void run(final Result<Library> result) {
final LibraryTable libraryTable = LibraryTablesRegistrar.getInstance().getLibraryTable(module.getProject());
@@ -182,7 +186,11 @@
if (library == null) {
library = libraryTable.createLibrary(name);
final Library.ModifiableModel model = library.getModifiableModel();
- model.addJarDirectory(VfsUtil.pathToUrl(path), false);
+ for (String path : jarDirectories) {
+ String url = VfsUtilCore.pathToUrl(path);
+ VirtualFileManager.getInstance().refreshAndFindFileByUrl(url);
+ model.addJarDirectory(url, false);
+ }
for (VirtualFile sourceRoot : sources) {
model.addRoot(sourceRoot, OrderRootType.SOURCES);
}
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/sdk/AppEngineSdk.java b/plugins/google-app-engine/source/com/intellij/appengine/sdk/AppEngineSdk.java
index 1da2cff..318c950 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/sdk/AppEngineSdk.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/sdk/AppEngineSdk.java
@@ -21,6 +21,7 @@
import org.jetbrains.annotations.Nullable;
import java.io.File;
+import java.util.List;
/**
* @author nik
@@ -47,7 +48,7 @@
String getOrmLibDirectoryPath();
- String getLibUserDirectoryPath();
+ List<String> getUserLibraryPaths();
VirtualFile[] getOrmLibSources();
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkImpl.java b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkImpl.java
index 5c60ab0..c8aeced 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkImpl.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkImpl.java
@@ -27,6 +27,7 @@
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
+import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -120,9 +121,16 @@
}
else {
myClassesWhiteList = AppEngineSdkUtil.computeWhiteList(getToolsApiJarFile());
- AppEngineSdkUtil.saveWhiteList(cachedWhiteList, myClassesWhiteList);
+ if (!myClassesWhiteList.isEmpty()) {
+ AppEngineSdkUtil.saveWhiteList(cachedWhiteList, myClassesWhiteList);
+ }
}
}
+ if (myClassesWhiteList.isEmpty()) {
+ //don't report errors if white-list wasn't properly loaded
+ return true;
+ }
+
final String packageName = StringUtil.getPackageName(className);
final String name = StringUtil.getShortName(className);
final Set<String> classes = myClassesWhiteList.get(packageName);
@@ -167,6 +175,25 @@
return getLibUserDirectoryPath() + "/orm";
}
+ @Override
+ public List<String> getUserLibraryPaths() {
+ List<String> result = new ArrayList<String>();
+ result.add(getLibUserDirectoryPath());
+ File opt = new File(myHomePath, "lib/opt/user");
+ ContainerUtil.addIfNotNull(result, findLatestVersion(new File(opt, "appengine-endpoints")));
+ ContainerUtil.addIfNotNull(result, findLatestVersion(new File(opt, "jsr107")));
+ return result;
+ }
+
+ private static String findLatestVersion(File dir) {
+ String[] names = dir.list();
+ if (names != null && names.length > 0) {
+ String max = Collections.max(Arrays.asList(names));
+ return FileUtil.toSystemIndependentName(new File(dir, max).getAbsolutePath());
+ }
+ return null;
+ }
+
public VirtualFile[] getOrmLibSources() {
final File libsDir = new File(FileUtil.toSystemDependentName(myHomePath + "/src/orm"));
final File[] files = libsDir.listFiles();
diff --git a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java
index 645c6f7..9edece0 100644
--- a/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java
+++ b/plugins/google-app-engine/source/com/intellij/appengine/sdk/impl/AppEngineSdkUtil.java
@@ -42,7 +42,7 @@
private static final FacetConfigurationQuickFix DOWNLOAD_SDK_QUICK_FIX = new FacetConfigurationQuickFix("Download...") {
@Override
public void run(JComponent place) {
- BrowserUtil.launchBrowser(APP_ENGINE_DOWNLOAD_URL);
+ BrowserUtil.browse(APP_ENGINE_DOWNLOAD_URL);
}
};
@@ -101,7 +101,7 @@
final ClassLoader loader = UrlClassLoader.build().urls(toolsApiJarFile.toURI().toURL()).parent(
AppEngineSdkUtil.class.getClassLoader()).get();
final Class<?> whiteListClass = Class.forName("com.google.apphosting.runtime.security.WhiteList", true, loader);
- final Set<String> classes = (Set<String>) whiteListClass.getMethod("getWhiteList").invoke(null);
+ final Set<String> classes = (Set<String>)whiteListClass.getMethod("getWhiteList").invoke(null);
for (String qualifiedName : classes) {
final String packageName = StringUtil.getPackageName(qualifiedName);
Set<String> classNames = map.get(packageName);
@@ -113,6 +113,10 @@
}
return map;
}
+ catch (UnsupportedClassVersionError e) {
+ LOG.warn(e);
+ return Collections.emptyMap();
+ }
catch (Exception e) {
LOG.error(e);
return Collections.emptyMap();
diff --git a/plugins/gradle/gradle.iml b/plugins/gradle/gradle.iml
index 6f6de26..4f67303 100644
--- a/plugins/gradle/gradle.iml
+++ b/plugins/gradle/gradle.iml
@@ -9,8 +9,10 @@
<sourceFolder url="file://$MODULE_DIR$/testData" isTestSource="true" />
</content>
<orderEntry type="inheritedJdk" />
- <orderEntry type="library" scope="TEST" name="Mocks" level="project" />
<orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="external-system-api" exported="" />
+ <orderEntry type="module" module-name="external-system-impl" exported="" />
+ <orderEntry type="module" module-name="gradle-tooling-extension" exported="" />
<orderEntry type="module" module-name="idea-ui" />
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="compiler-openapi" />
@@ -20,107 +22,32 @@
<orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="java-impl" />
- <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
- <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="module" module-name="maven" />
<orderEntry type="library" name="swingx" level="project" />
<orderEntry type="module-library" exported="">
<library name="Gradle">
<CLASSES>
- <root url="jar://$MODULE_DIR$/lib/gradle-base-services-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-tooling-api-1.9.jar!/" />
<root url="jar://$MODULE_DIR$/lib/gradle-core-1.9.jar!/" />
<root url="jar://$MODULE_DIR$/lib/gradle-messaging-1.9.jar!/" />
- <root url="jar://$MODULE_DIR$/lib/gradle-tooling-api-1.9.jar!/" />
<root url="jar://$MODULE_DIR$/lib/gradle-wrapper-1.9.jar!/" />
- <root url="jar://$MODULE_DIR$/lib/gradle-plugins-1.9.jar!/" />
- <root url="jar://$MODULE_DIR$/lib/gradle-build-init-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-base-services-1.9.jar!/" />
<root url="jar://$MODULE_DIR$/lib/gradle-native-1.9.jar!/" />
- <root url="jar://$MODULE_DIR$/lib/gradle-ide-1.9.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/buildSrc/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/buildSrc/src/test/resources" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/integTest/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cli/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cpp/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cpp/src/integTest/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ear/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ide/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ide/src/main/resources" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/main/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/integTest/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/testFixtures/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/osgi/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/osgi/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/antlr/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/jetty/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/maven/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/maven/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/scala/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/scala/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/jacoco/src/main/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/native/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/testFixtures/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/publish/src/main/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/wrapper/src/main/java" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/wrapper/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/announce/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/integTest/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/open-api/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/open-api/src/integTest/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core-impl/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core-impl/src/test/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/messaging/src/main/java" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/messaging/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/reporting/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/resources/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/javascript/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/integTest/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/performance/src/configPlugin" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/performance/src/testFixtures/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/main/java" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/integTest/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/testFixtures/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/code-quality/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services/src/main/java" />
<root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services/src/test/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-base/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/source/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/target/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/internal-testing/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services-groovy/src/main/groovy" />
- <root url="jar://$MODULE_DIR$/lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services-groovy/src/test/groovy" />
</SOURCES>
</library>
</orderEntry>
@@ -163,9 +90,7 @@
<SOURCES />
</library>
</orderEntry>
- <orderEntry type="module" module-name="external-system-impl" />
- <orderEntry type="module" module-name="external-system-api" />
- <orderEntry type="module-library" exported="">
+ <orderEntry type="module-library">
<library name="GradleJnaPosix">
<CLASSES>
<root url="jar://$MODULE_DIR$/lib/jna-3.2.7.jar!/" />
@@ -186,8 +111,10 @@
<jarDirectory url="jar://$MODULE_DIR$/lib/native-platform-windows-i386-0.3-rc-2.jar!/" recursive="false" />
</library>
</orderEntry>
+ <orderEntry type="library" scope="TEST" name="Mocks" level="project" />
+ <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
- <orderEntry type="module" module-name="maven" />
</component>
</module>
diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft
index 6199e79..170d1ac 100644
--- a/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft
+++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Build Script with wrapper.gradle.ft
@@ -4,8 +4,8 @@
version = '1.0'
task wrapper(type: Wrapper) {
- gradleVersion = '1.8'
- distributionUrl = 'http://services.gradle.org/distributions/gradle-1.8-all.zip'
+ gradleVersion = '1.9'
+ distributionUrl = 'http://services.gradle.org/distributions/gradle-1.9-all.zip'
}
repositories {
diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft
new file mode 100644
index 0000000..73f1b4e
--- /dev/null
+++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings merge.gradle.ft
@@ -0,0 +1,6 @@
+#if (${CONTENT} && ${CONTENT} != "")${CONTENT}#end
+#if (${MODULE_DIR_NAME} && ${MODULE_DIR_NAME} != "")include '${MODULE_DIR_NAME}'
+#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_DIR_NAME} != ${MODULE_NAME})rootProject.children.find { it.name == '${MODULE_DIR_NAME}' }.name = '${MODULE_NAME}'
+#end
+#end
+
diff --git a/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft
new file mode 100644
index 0000000..9fbc0de
--- /dev/null
+++ b/plugins/gradle/resources/fileTemplates/internal/Gradle Settings.gradle.ft
@@ -0,0 +1,11 @@
+#if (${PROJECT_NAME} && ${PROJECT_NAME} != "")
+#if (((!${MODULE_DIR_NAME} || ${MODULE_DIR_NAME} == "")) && (${MODULE_NAME} && ${MODULE_NAME} != ""))rootProject.name = '${MODULE_NAME}'
+#elseif(true)rootProject.name = '${PROJECT_NAME}'
+#end
+#end
+#if (${MODULE_DIR_NAME} && ${MODULE_DIR_NAME} != "")
+include '${MODULE_DIR_NAME}'
+#if (${MODULE_NAME} && ${MODULE_NAME} != "" && ${MODULE_DIR_NAME} != ${MODULE_NAME})rootProject.children.find { it.name == '${MODULE_DIR_NAME}' }.name = '${MODULE_NAME}'
+#end
+#end
+
diff --git a/plugins/gradle/resources/i18n/GradleBundle.properties b/plugins/gradle/resources/i18n/GradleBundle.properties
index 254b5a9..fddd058 100644
--- a/plugins/gradle/resources/i18n/GradleBundle.properties
+++ b/plugins/gradle/resources/i18n/GradleBundle.properties
@@ -10,6 +10,7 @@
gradle.settings.text.home.path=Gradle home:
gradle.settings.text.service.dir.path=Service directory path:
gradle.settings.text.vm.options=Gradle VM options:
+gradle.settings.text.offline_work=Offline work
gradle.settings.title.service.dir.path=Select gradle service directory to use
gradle.generic.text.error.jar.not.found=Gradle jars location is unknown
@@ -25,7 +26,7 @@
gradle.notifications.apply.suggestion=Ok, apply suggestion!
gradle.notifications.unlinked.project.found.title=Unlinked Gradle project?
gradle.notifications.unlinked.project.found.msg=<a href="{0}">Import Gradle project</a>, this will also enable Gradle Tool Window.
-gradle.notifications.do.not.show=Don't want to see the message for the project again: <a href="{0}">press here</a>.
+gradle.notifications.do.not.show=Don't want to see the message for the project again: <a href="do.not.show">press here</a>.
gradle.codeInsight.action.apply_plugin.text=Add gradle plugin
gradle.codeInsight.action.apply_plugin.description=Add selected gradle plugin to the project
diff --git a/plugins/gradle/src/META-INF/gradle-javaee-plugin.xml b/plugins/gradle/src/META-INF/gradle-javaee-plugin.xml
index 2a8b4d5..1bb578f 100644
--- a/plugins/gradle/src/META-INF/gradle-javaee-plugin.xml
+++ b/plugins/gradle/src/META-INF/gradle-javaee-plugin.xml
@@ -1,6 +1,7 @@
<idea-plugin>
<extensions defaultExtensionNs="com.intellij">
<externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.javaee.WebModuleGradleDataService"/>
+ <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.javaee.WebDetectionExclusionModuleDataService"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
<projectResolve implementation="org.jetbrains.plugins.gradle.integrations.javaee.JavaEEGradleProjectResolverExtension"/>
diff --git a/plugins/gradle/src/META-INF/gradle-scala-integration.xml b/plugins/gradle/src/META-INF/gradle-scala-integration.xml
new file mode 100644
index 0000000..707d616
--- /dev/null
+++ b/plugins/gradle/src/META-INF/gradle-scala-integration.xml
@@ -0,0 +1,5 @@
+<idea-plugin>
+ <extensions defaultExtensionNs="org.jetbrains.plugins.gradle">
+ <projectResolve implementation="org.jetbrains.plugins.gradle.integrations.scala.ScalaGradleProjectResolverExtension"/>
+ </extensions>
+</idea-plugin>
diff --git a/plugins/gradle/src/META-INF/plugin.xml b/plugins/gradle/src/META-INF/plugin.xml
index 034ef35..2870911 100644
--- a/plugins/gradle/src/META-INF/plugin.xml
+++ b/plugins/gradle/src/META-INF/plugin.xml
@@ -24,6 +24,7 @@
<depends>org.intellij.groovy</depends>
<depends optional="true" config-file="gradle-javaee-plugin.xml">com.intellij.javaee</depends>
<depends optional="true" config-file="gradle-maven-integration.xml">org.jetbrains.idea.maven</depends>
+ <depends optional="true" config-file="gradle-scala-integration.xml">org.intellij.scala</depends>
<extensionPoints>
<extensionPoint name="projectResolve" interface="org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtension"/>
@@ -62,6 +63,7 @@
key="gradle.name" bundle="i18n.GradleBundle"/>
<library.presentationProvider implementation="org.jetbrains.plugins.gradle.config.GradleLibraryPresentationProvider" order="last"/>
<java.elementFinder implementation="org.jetbrains.plugins.gradle.config.GradleClassFinder"/>
+ <editorTabTitleProvider implementation="org.jetbrains.plugins.gradle.util.GradleEditorTabTitleProvider"/>
<projectOpenProcessor implementation="org.jetbrains.plugins.gradle.service.project.wizard.GradleProjectOpenProcessor"/>
<configurationType implementation="org.jetbrains.plugins.gradle.service.execution.GradleExternalTaskConfigurationType"/>
diff --git a/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService b/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService
deleted file mode 100644
index 430ac6f..0000000
--- a/plugins/gradle/src/META-INF/services/org.jetbrains.plugins.gradle.model.ModelBuilderService
+++ /dev/null
@@ -1,19 +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.
-#
-org.jetbrains.plugins.gradle.model.builder.WarModelBuilderImpl
-org.jetbrains.plugins.gradle.model.builder.ModelDependenciesBuilderImpl
-org.jetbrains.plugins.gradle.model.builder.ModuleExtendedModelBuilderImpl
-org.jetbrains.plugins.gradle.model.builder.ModelBuildScriptClasspathBuilderImpl
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java
index c888569..b011f2d 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java
@@ -30,7 +30,9 @@
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
+import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskType;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
+import com.intellij.openapi.externalSystem.service.internal.ExternalSystemProcessingManager;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.ExternalSystemProjectResolver;
import com.intellij.openapi.externalSystem.service.project.autoimport.CachingExternalSystemAutoImportAware;
@@ -76,6 +78,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.locks.ReentrantLock;
/**
* @author Denis Zhdanov
@@ -177,7 +180,8 @@
GradleExecutionSettings result = new GradleExecutionSettings(localGradlePath,
settings.getServiceDirectoryPath(),
distributionType,
- settings.getGradleVmOptions());
+ settings.getGradleVmOptions(),
+ settings.isOfflineWork());
for (GradleProjectResolverExtension extension : RESOLVER_EXTENSIONS.getValue()) {
result.addResolverExtensionClass(ClassHolder.from(extension.getClass()));
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInspection/GradleInspectionBundle.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInspection/GradleInspectionBundle.java
index 9602b1d..af55b24 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInspection/GradleInspectionBundle.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/codeInspection/GradleInspectionBundle.java
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -29,25 +30,21 @@
*/
public class GradleInspectionBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.gradle.codeInspection.GradleInspectionBundle";
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.gradle.codeInspection.GradleInspectionBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
- ourBundle = new SoftReference<ResourceBundle >(bundle);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
}
return bundle;
}
-
}
\ No newline at end of file
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
index d598490..e05284a 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/config/GradleScriptType.java
@@ -58,7 +58,6 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrShiftExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.runner.GroovyScriptRunConfiguration;
import org.jetbrains.plugins.groovy.runner.GroovyScriptRunner;
@@ -137,7 +136,7 @@
}
else if (parent instanceof GrApplicationStatement) {
PsiElement shiftExpression = parent.getChildren()[1].getChildren()[0];
- if (shiftExpression instanceof GrShiftExpressionImpl) {
+ if (GradleResolverUtil.isLShiftElement(shiftExpression)) {
PsiElement shiftiesChild = shiftExpression.getChildren()[0];
if (shiftiesChild instanceof GrReferenceExpression) {
return Collections.singletonList(shiftiesChild.getText());
@@ -314,6 +313,9 @@
GlobalSearchScope result = GlobalSearchScope.EMPTY_SCOPE;
final Module module = ModuleUtilCore.findModuleForPsiElement(file);
if (module != null) {
+ String externalSystemId = module.getOptionValue(ExternalSystemConstants.EXTERNAL_SYSTEM_ID_KEY);
+ if(!GradleConstants.SYSTEM_ID.toString().equals(externalSystemId)) return baseScope;
+
for (OrderEntry entry : ModuleRootManager.getInstance(module).getOrderEntries()) {
if (entry instanceof JdkOrderEntry) {
GlobalSearchScope scopeForSdk = LibraryScopeCache.getInstance(module.getProject()).getScopeForSdk((JdkOrderEntry)entry);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/javaee/JavaEEGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/javaee/JavaEEGradleProjectResolverExtension.java
index f95c8a0..9779d6e 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/javaee/JavaEEGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/javaee/JavaEEGradleProjectResolverExtension.java
@@ -20,14 +20,20 @@
import com.intellij.openapi.externalSystem.model.project.ModuleData;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.Order;
+import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import org.gradle.tooling.model.idea.IdeaModule;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.model.WarModel;
-import org.jetbrains.plugins.gradle.model.data.WarModelData;
+import org.jetbrains.plugins.gradle.model.WebConfiguration;
+import org.jetbrains.plugins.gradle.model.data.War;
+import org.jetbrains.plugins.gradle.model.data.WarDirectory;
+import org.jetbrains.plugins.gradle.model.data.WebConfigurationModelData;
+import org.jetbrains.plugins.gradle.model.data.WebResource;
import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension;
import org.jetbrains.plugins.gradle.util.GradleConstants;
+import java.util.Collections;
+import java.util.List;
import java.util.Set;
/**
@@ -42,14 +48,23 @@
@Override
public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
- WarModel warModel = resolverCtx.getExtraProject(gradleModule, WarModel.class);
- if (warModel != null) {
- WarModelData warModelData = new WarModelData(GradleConstants.SYSTEM_ID, warModel.getWebAppDirName(), warModel.getWebAppDir());
- warModelData.setWebXml(warModel.getWebXml());
- warModelData.setWebRoots(warModel.getWebRoots());
- warModelData.setClasspath(warModel.getClasspath());
- warModelData.setManifestContent(warModel.getManifestContent());
- ideModule.createChild(WarModelData.KEY, warModelData);
+ final WebConfiguration webConfiguration = resolverCtx.getExtraProject(gradleModule, WebConfiguration.class);
+ if (webConfiguration != null) {
+ List<War> warModels =
+ ContainerUtil.map(webConfiguration.getWarModels(), new Function<WebConfiguration.WarModel, War>() {
+ @Override
+ public War fun(WebConfiguration.WarModel model) {
+ War war =
+ new War(model.getWarName(), model.getWebAppDirName(), model.getWebAppDir());
+ war.setWebXml(model.getWebXml());
+ war.setWebResources(map(model.getWebResources()));
+ war.setClasspath(model.getClasspath());
+ war.setManifestContent(model.getManifestContent());
+ return war;
+ }
+ });
+
+ ideModule.createChild(WebConfigurationModelData.KEY, new WebConfigurationModelData(GradleConstants.SYSTEM_ID, warModels));
}
nextResolver.populateModuleExtraModels(gradleModule, ideModule);
@@ -58,6 +73,20 @@
@NotNull
@Override
public Set<Class> getExtraProjectModelClasses() {
- return ContainerUtil.<Class>set(WarModel.class);
+ return Collections.<Class>singleton(WebConfiguration.class);
+ }
+
+ private static List<WebResource> map(List<WebConfiguration.WebResource> webResources) {
+ return ContainerUtil.mapNotNull(webResources, new Function<WebConfiguration.WebResource, WebResource>() {
+ @Override
+ public WebResource fun(WebConfiguration.WebResource resource) {
+ if (resource == null) return null;
+
+ final WarDirectory warDirectory =
+ WarDirectory.fromPath(resource.getWarDirectory());
+ if (warDirectory == null) return null;
+ return new WebResource(warDirectory, resource.getRelativePath(), resource.getFile());
+ }
+ });
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java
index d14125e..5250d28 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/maven/ImportMavenRepositoriesTask.java
@@ -42,6 +42,7 @@
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.GrApplicationStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
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.literals.GrLiteral;
@@ -174,11 +175,11 @@
}
}
}
- else if ("maven".equals(expressionText)) {
- List<GrApplicationStatement> list =
+ else if ("maven".equals(expressionText) && repo.getClosureArguments().length > 0) {
+ List<GrApplicationStatement> applicationStatementList =
PsiTreeUtil.getChildrenOfTypeAsList(repo.getClosureArguments()[0], GrApplicationStatement.class);
- if (!list.isEmpty()) {
- GrApplicationStatement statement = list.get(0);
+ if (!applicationStatementList.isEmpty()) {
+ GrApplicationStatement statement = applicationStatementList.get(0);
if (statement == null) continue;
GrExpression expression = statement.getInvokedExpression();
if (expression == null) continue;
@@ -191,6 +192,22 @@
}
}
}
+
+ List<GrAssignmentExpression> assignmentExpressionList =
+ PsiTreeUtil.getChildrenOfTypeAsList(repo.getClosureArguments()[0], GrAssignmentExpression.class);
+ if (!assignmentExpressionList.isEmpty()) {
+ GrAssignmentExpression statement = assignmentExpressionList.get(0);
+ if (statement == null) continue;
+ GrExpression expression = statement.getLValue();
+
+ if ("url".equals(expression.getText())) {
+ URI urlArgumentValue = resolveUriFromSimpleExpression(statement.getRValue());
+ if (urlArgumentValue != null) {
+ String textUri = urlArgumentValue.toString();
+ myRemoteRepositories.add(new MavenRemoteRepository(textUri, null, textUri, null, null, null));
+ }
+ }
+ }
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/scala/ScalaGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/scala/ScalaGradleProjectResolverExtension.java
new file mode 100644
index 0000000..657d064
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/integrations/scala/ScalaGradleProjectResolverExtension.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.integrations.scala;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.externalSystem.model.DataNode;
+import com.intellij.openapi.externalSystem.model.project.ModuleData;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.externalSystem.util.Order;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ScalaCompileOptions;
+import org.jetbrains.plugins.gradle.model.ScalaForkOptions;
+import org.jetbrains.plugins.gradle.model.ScalaModel;
+import org.jetbrains.plugins.gradle.model.data.ScalaCompileOptionsData;
+import org.jetbrains.plugins.gradle.model.data.ScalaModelData;
+import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+@Order(ExternalSystemConstants.UNORDERED)
+public class ScalaGradleProjectResolverExtension extends AbstractProjectResolverExtension {
+ private static final Logger LOG = Logger.getInstance(ScalaGradleProjectResolverExtension.class);
+
+ @Override
+ public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
+ ScalaModel scalaModel = resolverCtx.getExtraProject(gradleModule, ScalaModel.class);
+ if (scalaModel != null) {
+ ScalaModelData scalaModelData = create(scalaModel);
+ ideModule.createChild(ScalaModelData.KEY, scalaModelData);
+ }
+
+ nextResolver.populateModuleExtraModels(gradleModule, ideModule);
+ }
+
+ @NotNull
+ @Override
+ public Set<Class> getExtraProjectModelClasses() {
+ return Collections.<Class>singleton(ScalaModel.class);
+ }
+
+
+ @NotNull
+ private static ScalaModelData create(@NotNull ScalaModel scalaModel) {
+ ScalaModelData scalaModelData = new ScalaModelData(GradleConstants.SYSTEM_ID);
+ scalaModelData.setZincClasspath(scalaModel.getZincClasspath());
+ scalaModelData.setScalaClasspath(scalaModel.getScalaClasspath());
+ scalaModelData.setScalaCompileOptions(create((scalaModel.getScalaCompileOptions())));
+ scalaModelData.setSourceCompatibility(scalaModel.getSourceCompatibility());
+ scalaModelData.setTargetCompatibility(scalaModel.getTargetCompatibility());
+ return scalaModelData;
+ }
+
+ @Nullable
+ @Contract("null -> null")
+ private static ScalaCompileOptionsData create(@Nullable ScalaCompileOptions options) {
+ if (options == null) return null;
+
+ ScalaCompileOptionsData result = new ScalaCompileOptionsData();
+
+ result.setAdditionalParameters(options.getAdditionalParameters());
+ result.setDaemonServer(options.getDaemonServer());
+ result.setDebugLevel(options.getDebugLevel());
+ result.setDeprecation(options.isDeprecation());
+ result.setEncoding(options.getEncoding());
+ result.setFailOnError(options.isFailOnError());
+ result.setForce(options.getForce());
+ result.setFork(options.isFork());
+ result.setListFiles(options.isListFiles());
+ result.setLoggingLevel(options.getLoggingLevel());
+ result.setDebugLevel(options.getDebugLevel());
+ result.setLoggingPhases(options.getLoggingPhases());
+ result.setOptimize(options.isOptimize());
+ result.setUnchecked(options.isUnchecked());
+ result.setUseAnt(options.isUseAnt());
+ result.setUseCompileDaemon(options.isUseCompileDaemon());
+ result.setForkOptions(create(options.getForkOptions()));
+ return result;
+ }
+
+ @Nullable
+ @Contract("null -> null")
+ private static ScalaCompileOptionsData.ScalaForkOptions create(@Nullable ScalaForkOptions options) {
+ if (options == null) return null;
+
+ ScalaCompileOptionsData.ScalaForkOptions result = new ScalaCompileOptionsData.ScalaForkOptions();
+ result.setJvmArgs(options.getJvmArgs());
+ result.setMemoryInitialSize(options.getMemoryInitialSize());
+ result.setMemoryMaximumSize(options.getMemoryMaximumSize());
+ return result;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ModelBuilderService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ModelBuilderService.java
deleted file mode 100644
index 3a76dbe..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ModelBuilderService.java
+++ /dev/null
@@ -1,28 +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.gradle.model;
-
-import org.gradle.api.Project;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-public interface ModelBuilderService {
- boolean canBuild(String modelName);
-
- Object buildAll(String modelName, Project project);
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/WarModel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/WarModel.java
deleted file mode 100644
index 48636dd..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/WarModel.java
+++ /dev/null
@@ -1,39 +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.gradle.model;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-public interface WarModel extends Serializable {
- String getWebAppDirName();
-
- File getWebAppDir();
-
- File getWebXml();
-
- Map<String, Set<String>> getWebRoots();
-
- Set<File> getClasspath();
-
- String getManifestContent();
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java
deleted file mode 100644
index 5572290..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImpl.java
+++ /dev/null
@@ -1,107 +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 org.jetbrains.plugins.gradle.model.builder;
-
-import org.gradle.api.Project;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.plugins.ide.idea.IdeaPlugin;
-import org.gradle.plugins.ide.idea.model.IdeaModel;
-import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
-import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
-import org.jetbrains.plugins.gradle.model.ModelBuilderService;
-import org.jetbrains.plugins.gradle.model.internal.BuildScriptClasspathModelImpl;
-import org.jetbrains.plugins.gradle.model.internal.ClasspathEntryModelImpl;
-
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * @author Vladislav.Soroka
- * @since 12/20/13
- */
-public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService {
-
- private final Map<String, BuildScriptClasspathModelImpl> cache = new ConcurrentHashMap<String, BuildScriptClasspathModelImpl>();
-
- @Override
- public boolean canBuild(String modelName) {
- return BuildScriptClasspathModel.class.getName().equals(modelName);
- }
-
- @Nullable
- @Override
- public Object buildAll(final String modelName, final Project project) {
- BuildScriptClasspathModelImpl buildScriptClasspath = cache.get(project.getPath());
- if (buildScriptClasspath != null) return buildScriptClasspath;
-
- boolean offline = false;
- boolean downloadJavadoc = false;
- boolean downloadSources = true;
-
- final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
-
- if (ideaPlugin != null) {
- IdeaModel ideaModel = ideaPlugin.getModel();
- if (ideaModel != null && ideaModel.getModule() != null) {
- offline = ideaModel.getModule().isOffline();
- downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
- downloadSources = ideaModel.getModule().isDownloadSources();
- }
- }
-
- buildScriptClasspath = new BuildScriptClasspathModelImpl();
- Project parent = project.getParent();
- if (parent != null) {
- BuildScriptClasspathModelImpl parentBuildScriptClasspath = (BuildScriptClasspathModelImpl)buildAll(modelName, parent);
- if (parentBuildScriptClasspath != null) {
- for (ClasspathEntryModel classpathEntryModel : parentBuildScriptClasspath.getClasspath()) {
- buildScriptClasspath.add(classpathEntryModel);
- }
- }
- }
-
- final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
-
- final Configuration configuration = project.getBuildscript().getConfigurations().findByName("classpath");
- Collection<Configuration> plusConfigurations = Collections.singletonList(configuration);
-
- if (!offline) {
- // download sources and/or javadoc
- List<IdeDependenciesExtractor.IdeRepoFileDependency> repoFileDependencies = dependenciesExtractor.extractRepoFileDependencies(
- project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
-
- for (IdeDependenciesExtractor.IdeRepoFileDependency dependency : repoFileDependencies) {
- if (dependency.getFile() == null) continue;
-
- buildScriptClasspath.add(
- new ClasspathEntryModelImpl(dependency.getFile(), dependency.getSourceFile(), dependency.getJavadocFile()));
- }
- }
-
- final List<IdeDependenciesExtractor.IdeLocalFileDependency> localFileDependencies =
- dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
-
- for (IdeDependenciesExtractor.IdeLocalFileDependency dependency : localFileDependencies) {
- if (dependency.getFile() == null) continue;
- buildScriptClasspath.add(new ClasspathEntryModelImpl(dependency.getFile(), null, null));
- }
-
- cache.put(project.getPath(), buildScriptClasspath);
- return buildScriptClasspath;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java
deleted file mode 100644
index 4c0e391..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImpl.java
+++ /dev/null
@@ -1,334 +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.gradle.model.builder;
-
-import org.gradle.api.Project;
-import org.gradle.api.artifacts.Configuration;
-import org.gradle.api.artifacts.ModuleIdentifier;
-import org.gradle.api.artifacts.ModuleVersionIdentifier;
-import org.gradle.plugins.ide.idea.GenerateIdeaModule;
-import org.gradle.plugins.ide.idea.IdeaPlugin;
-import org.gradle.plugins.ide.idea.model.IdeaModel;
-import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
-import org.gradle.tooling.model.idea.IdeaDependency;
-import org.gradle.util.GradleVersion;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
-import org.jetbrains.plugins.gradle.model.ModelBuilderService;
-import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
-import org.jetbrains.plugins.gradle.model.internal.*;
-
-import java.io.File;
-import java.io.Serializable;
-import java.util.*;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-public class ModelDependenciesBuilderImpl implements ModelBuilderService {
-
- private static final String MODULE_PROPERTY = "ideaModule";
- private static final String VERSION_PROPERTY = "version";
- private static final String GROUP_PROPERTY = "group";
-
- @Override
- public boolean canBuild(String modelName) {
- return ProjectDependenciesModel.class.getName().equals(modelName);
- }
-
- @Nullable
- @Override
- public Object buildAll(final String modelName, final Project project) {
- final List<IdeaDependency> dependencies = new ArrayList<IdeaDependency>();
-
- final Map<DependencyVersionId, Scopes> scopesMap = new LinkedHashMap<DependencyVersionId, Scopes>();
- final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
-
- boolean offline = false;
- boolean downloadJavadoc = false;
- boolean downloadSources = true;
-
- final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
- Map<String, Map<String, Collection<Configuration>>> userScopes = Collections.emptyMap();
- if (ideaPlugin != null) {
- IdeaModel ideaModel = ideaPlugin.getModel();
- if (ideaModel != null && ideaModel.getModule() != null) {
- offline = ideaModel.getModule().isOffline();
- downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
- downloadSources = ideaModel.getModule().isDownloadSources();
- userScopes = ideaModel.getModule().getScopes();
- }
- }
-
- for (final Configuration configuration : project.getConfigurations()) {
- Collection<Configuration> plusConfigurations = new ArrayList<Configuration>();
- plusConfigurations.add(configuration);
-
- final List<IdeDependenciesExtractor.IdeProjectDependency> ideProjectDependencies =
- dependenciesExtractor.extractProjectDependencies(plusConfigurations, new ArrayList<Configuration>());
-
- for (IdeDependenciesExtractor.IdeProjectDependency ideProjectDependency : ideProjectDependencies) {
- merge(scopesMap, ideProjectDependency, userScopes);
- }
-
- if (!offline) {
- final Collection<IdeDependenciesExtractor.IdeRepoFileDependency> ideRepoFileDependencies =
- dependenciesExtractor.extractRepoFileDependencies(
- project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
- for (IdeDependenciesExtractor.IdeRepoFileDependency repoFileDependency : ideRepoFileDependencies) {
- merge(scopesMap, repoFileDependency, userScopes);
- }
- }
-
- final List<IdeDependenciesExtractor.IdeLocalFileDependency> ideLocalFileDependencies =
- dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
- for (IdeDependenciesExtractor.IdeLocalFileDependency fileDependency : ideLocalFileDependencies) {
- merge(scopesMap, fileDependency, userScopes);
- }
- }
-
- for (Map.Entry<DependencyVersionId, Scopes> entry : scopesMap.entrySet()) {
- DependencyVersionId versionId = entry.getKey();
- for (GradleDependencyScope scope : entry.getValue().getScopes()) {
- if (versionId.getIdeDependency() instanceof IdeDependenciesExtractor.IdeRepoFileDependency) {
- IdeDependenciesExtractor.IdeRepoFileDependency repoFileDependency =
- (IdeDependenciesExtractor.IdeRepoFileDependency)versionId.getIdeDependency();
- IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
- new IdeaDependencyScopeImpl(scope),
- versionId.getName(),
- versionId.getGroup(),
- versionId.getVersion(),
- versionId.getClassifier()
- );
- libraryDependency.setFile(repoFileDependency.getFile());
- libraryDependency.setSource(repoFileDependency.getSourceFile());
- libraryDependency.setJavadoc(repoFileDependency.getJavadocFile());
- dependencies.add(libraryDependency);
- }
- else if (versionId.getIdeDependency() instanceof IdeDependenciesExtractor.IdeProjectDependency) {
- IdeDependenciesExtractor.IdeProjectDependency projectDependency =
- (IdeDependenciesExtractor.IdeProjectDependency)versionId.getIdeDependency();
-
- String ideaModuleName = findDeDuplicatedModuleName(projectDependency.getProject());
- if (ideaModuleName == null) {
- ideaModuleName = versionId.getName();
- }
-
- IdeaModuleDependencyImpl moduleDependency = new IdeaModuleDependencyImpl(
- new IdeaDependencyScopeImpl(scope),
- ideaModuleName,
- versionId.getGroup(),
- versionId.getVersion(),
- versionId.getClassifier()
- );
- moduleDependency.setIdeaModule(new StubIdeaModule(ideaModuleName));
- dependencies.add(moduleDependency);
- }
- else if (versionId.getIdeDependency() instanceof IdeDependenciesExtractor.IdeLocalFileDependency) {
- IdeDependenciesExtractor.IdeLocalFileDependency fileDependency =
- (IdeDependenciesExtractor.IdeLocalFileDependency)versionId.getIdeDependency();
- IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
- new IdeaDependencyScopeImpl(scope),
- versionId.getName(),
- versionId.getGroup(),
- versionId.getVersion(),
- versionId.getClassifier()
- );
- libraryDependency.setFile(fileDependency.getFile());
- attachGradleSdkSources(libraryDependency, fileDependency);
- dependencies.add(libraryDependency);
- }
- }
- }
-
- return new ProjectDependenciesModelImpl(project.getPath(), dependencies);
- }
-
- private static void attachGradleSdkSources(IdeaSingleEntryLibraryDependencyImpl libraryDependency,
- IdeDependenciesExtractor.IdeLocalFileDependency localFileDependency) {
- final String libName = localFileDependency.getFile().getName();
- if (localFileDependency.getFile() == null || !libName.startsWith("gradle-")) return;
-
- File libOrPluginsFile = localFileDependency.getFile().getParentFile();
- if (libOrPluginsFile != null && ("plugins".equals(libOrPluginsFile.getName()))) {
- libOrPluginsFile = libOrPluginsFile.getParentFile();
- }
-
- if (libOrPluginsFile != null && "lib".equals(libOrPluginsFile.getName()) && libOrPluginsFile.getParentFile() != null) {
- File srcDir = new File(libOrPluginsFile.getParentFile(), "src");
- if (GradleVersion.current().compareTo(GradleVersion.version("1.9")) >= 0) {
- int endIndex = libName.indexOf(GradleVersion.current().getVersion() + ".jar");
- if (endIndex != -1) {
- String srcDirChild = libName.substring("gradle-".length(), endIndex - 1);
- srcDir = new File(srcDir, srcDirChild);
- }
- }
-
- if (srcDir.isDirectory()) {
- libraryDependency.setSource(srcDir);
- }
- }
- }
-
- @Nullable
- private static String findDeDuplicatedModuleName(Project project) {
- if (project.hasProperty(MODULE_PROPERTY)) {
- Object ideaModule = project.property(MODULE_PROPERTY);
- if (ideaModule instanceof GenerateIdeaModule) {
- GenerateIdeaModule generateIdeaModule = (GenerateIdeaModule)ideaModule;
- return generateIdeaModule.getModule().getName();
- }
- }
- return null;
- }
-
- private static void merge(Map<DependencyVersionId, Scopes> map,
- IdeDependenciesExtractor.IdeProjectDependency dependency,
- Map<String, Map<String, Collection<Configuration>>> userScopes) {
- final String configurationName = dependency.getDeclaredConfiguration().getName();
- final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
- if (scope == null) return;
-
- final Project project = dependency.getProject();
- final String version = project.hasProperty(VERSION_PROPERTY) ? str(project.property(VERSION_PROPERTY)) : "";
- final String group = project.hasProperty(GROUP_PROPERTY) ? str(project.property(GROUP_PROPERTY)) : "";
-
- DependencyVersionId versionId =
- new DependencyVersionId(dependency, project.getName(), group, version, null);
- Scopes scopes = map.get(versionId);
- if (scopes == null) {
- map.put(versionId, new Scopes(scope));
- }
- else {
- scopes.add(scope);
- }
- }
-
- private static String str(Object o) {
- return String.valueOf(o == null ? "" : o);
- }
-
- private static void merge(Map<DependencyVersionId, Scopes> map,
- IdeDependenciesExtractor.IdeRepoFileDependency dependency,
- Map<String, Map<String, Collection<Configuration>>> userScopes) {
- final String configurationName = dependency.getDeclaredConfiguration().getName();
- final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
- if (scope == null) return;
-
- final ModuleVersionIdentifier dependencyId;
- if (dependency instanceof IdeDependenciesExtractor.UnresolvedIdeRepoFileDependency) {
- IdeDependenciesExtractor.UnresolvedIdeRepoFileDependency unresolvedDependency =
- (IdeDependenciesExtractor.UnresolvedIdeRepoFileDependency)dependency;
- dependencyId = new MyModuleVersionIdentifier(unresolvedDependency.getFile().getName());
- }
- else {
- dependencyId = dependency.getId();
- }
-
- String classifier = parseClassifier(dependencyId, dependency.getFile());
- DependencyVersionId versionId =
- new DependencyVersionId(dependency, dependencyId.getName(), dependencyId.getGroup(), dependencyId.getVersion(), classifier);
- Scopes scopes = map.get(versionId);
- if (scopes == null) {
- map.put(versionId, new Scopes(scope));
- }
- else {
- scopes.add(scope);
- }
- }
-
- private static String parseClassifier(ModuleVersionIdentifier dependencyId, File dependencyFile) {
- if (dependencyFile == null) return null;
- String dependencyFileName = dependencyFile.getName();
- int i = dependencyFileName.indexOf(dependencyId.getName() + '-' + dependencyId.getVersion() + '-');
- return i != -1 ? dependencyFileName.substring(i, dependencyFileName.length()) : null;
- }
-
- private static void merge(Map<DependencyVersionId, Scopes> map,
- IdeDependenciesExtractor.IdeLocalFileDependency dependency,
- Map<String, Map<String, Collection<Configuration>>> userScopes) {
-
- final String configurationName = dependency.getDeclaredConfiguration().getName();
- final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
- if (scope == null) return;
-
- String path = dependency.getFile().getPath();
- DependencyVersionId versionId =
- new DependencyVersionId(dependency, path, "", "", null);
- Scopes scopes = map.get(versionId);
- if (scopes == null) {
- map.put(versionId, new Scopes(scope));
- }
- else {
- scopes.add(scope);
- }
- }
-
- /**
- * Deduce configuration scope based on configuration name using gradle conventions.
- * IDEA gradle plugin only 'plus' configuration used to support configuration based on a custom configuration (not conventional)
- *
- * @param configurationName gradle configuration name
- * @param userScopes gradle IDEA plugin scopes map
- * @return deduced scope
- */
- private static GradleDependencyScope deduceScope(String configurationName,
- Map<String, Map<String, Collection<Configuration>>> userScopes) {
- GradleDependencyScope scope = GradleDependencyScope.fromName(configurationName);
- for (Map.Entry<String, Map<String, Collection<Configuration>>> entry : userScopes.entrySet()) {
- Collection<Configuration> plusConfigurations = entry.getValue().get("plus");
- if (plusConfigurations == null) continue;
-
- for (Configuration plus : plusConfigurations) {
- if (plus.getName().equals(configurationName)) {
- return GradleDependencyScope.fromIdeaMappingName(entry.getKey().toLowerCase());
- }
- }
- }
-
- return scope;
- }
-
- private static class MyModuleVersionIdentifier implements ModuleVersionIdentifier, Serializable {
- private final String myName;
-
- public MyModuleVersionIdentifier(String name) {
-
- myName = name;
- }
-
- @Override
- public String getVersion() {
- return null;
- }
-
- @Override
- public String getGroup() {
- return null;
- }
-
- @Override
- public String getName() {
- return myName;
- }
-
- @Override
- public ModuleIdentifier getModule() {
- return null;
- }
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java
deleted file mode 100644
index 44eb6cf..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImpl.java
+++ /dev/null
@@ -1,234 +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.gradle.model.builder;
-
-import groovy.lang.GroovyObject;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.tasks.SourceSet;
-import org.gradle.api.tasks.SourceSetContainer;
-import org.gradle.api.tasks.bundling.Jar;
-import org.gradle.api.tasks.testing.Test;
-import org.gradle.plugins.ide.idea.IdeaPlugin;
-import org.gradle.plugins.ide.idea.model.IdeaModel;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
-import org.jetbrains.plugins.gradle.model.ModelBuilderService;
-import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
-import org.jetbrains.plugins.gradle.model.internal.IdeaContentRootImpl;
-import org.jetbrains.plugins.gradle.model.internal.IdeaSourceDirectoryImpl;
-import org.jetbrains.plugins.gradle.model.internal.ModuleExtendedModelImpl;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
-
- private static final String SOURCE_SETS_PROPERTY = "sourceSets";
- private static final String TEST_SRC_DIRS_PROPERTY = "testSrcDirs";
-
- @Override
- public boolean canBuild(String modelName) {
- return ModuleExtendedModel.class.getName().equals(modelName);
- }
-
- @Nullable
- @Override
- public Object buildAll(String modelName, Project project) {
-
- final String moduleName = project.getName();
- final String moduleGroup = project.getGroup().toString();
- final String moduleVersion = project.getVersion().toString();
-
- final ModuleExtendedModelImpl moduleVersionModel = new ModuleExtendedModelImpl(moduleName, moduleGroup, moduleVersion);
-
- final List<File> artifacts = new ArrayList<File>();
- for (Task task : project.getTasks()) {
- if (task instanceof Jar) {
- Jar jar = (Jar)task;
- artifacts.add(jar.getArchivePath());
- }
- }
-
- moduleVersionModel.setArtifacts(artifacts);
-
- final Set<String> sourceDirectories = new HashSet<String>();
- final Set<String> testDirectories = new HashSet<String>();
- final Set<String> resourceDirectories = new HashSet<String>();
- final Set<String> testResourceDirectories = new HashSet<String>();
-
- final List<File> testClassesDirs = new ArrayList<File>();
- for (Task task : project.getTasks()) {
- if (task instanceof Test) {
- Test test = (Test)task;
- testClassesDirs.add(test.getTestClassesDir());
-
- if (test.hasProperty(TEST_SRC_DIRS_PROPERTY)) {
- Object testSrcDirs = test.property(TEST_SRC_DIRS_PROPERTY);
- if (testSrcDirs instanceof Iterable) {
- for (Object dir : Iterable.class.cast(testSrcDirs)) {
- addFilePath(testDirectories, dir);
- }
- }
- }
- }
- }
-
- if (project.hasProperty(SOURCE_SETS_PROPERTY)) {
- Object sourceSets = project.property(SOURCE_SETS_PROPERTY);
- if (sourceSets instanceof SourceSetContainer) {
- SourceSetContainer sourceSetContainer = (SourceSetContainer)sourceSets;
- for (SourceSet sourceSet : sourceSetContainer) {
- for (File javaSrcDir : sourceSet.getJava().getSrcDirs()) {
- boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
- addFilePath(isTestDir ? testDirectories : sourceDirectories, javaSrcDir);
- }
- for (File resourcesSrcDir : sourceSet.getResources().getSrcDirs()) {
- boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
- addFilePath(isTestDir ? testResourceDirectories : resourceDirectories, resourcesSrcDir);
- }
- }
- }
- }
-
- File projectDir = project.getProjectDir();
- IdeaContentRootImpl contentRoot = new IdeaContentRootImpl(projectDir);
-
- final Set<String> ideaSourceDirectories = new HashSet<String>();
- final Set<String> ideaTestDirectories = new HashSet<String>();
- final Set<String> ideaExtResourceDirectories = new HashSet<String>();
- final Set<String> ideaExtTestResourceDirectories = new HashSet<String>();
- final Set<File> excludeDirectories = new HashSet<File>();
-
- enrichDataFromIdeaPlugin(project, excludeDirectories, ideaSourceDirectories, ideaTestDirectories,
- ideaExtResourceDirectories, ideaExtTestResourceDirectories);
-
- if (ideaSourceDirectories.isEmpty()) {
- sourceDirectories.clear();
- resourceDirectories.clear();
- }
- if (ideaTestDirectories.isEmpty()) {
- testDirectories.clear();
- testResourceDirectories.clear();
- }
-
- ideaSourceDirectories.removeAll(resourceDirectories);
- sourceDirectories.addAll(ideaSourceDirectories);
- ideaTestDirectories.removeAll(testResourceDirectories);
- testDirectories.addAll(ideaTestDirectories);
-
- resourceDirectories.addAll(ideaExtResourceDirectories);
- testResourceDirectories.addAll(ideaExtTestResourceDirectories);
-
- // ensure disjoint directories with different type
- resourceDirectories.removeAll(sourceDirectories);
- testDirectories.removeAll(sourceDirectories);
- testResourceDirectories.removeAll(testDirectories);
-
- for (String javaDir : sourceDirectories) {
- contentRoot.addSourceDirectory(new IdeaSourceDirectoryImpl(new File(javaDir)));
- }
- for (String testDir : testDirectories) {
- contentRoot.addTestDirectory(new IdeaSourceDirectoryImpl(new File(testDir)));
- }
- for (String resourceDir : resourceDirectories) {
- contentRoot.addResourceDirectory(new IdeaSourceDirectoryImpl(new File(resourceDir)));
- }
- for (String testResourceDir : testResourceDirectories) {
- contentRoot.addTestResourceDirectory(new IdeaSourceDirectoryImpl(new File(testResourceDir)));
- }
- for (File excludeDir : excludeDirectories) {
- contentRoot.addExcludeDirectory(excludeDir);
- }
-
- moduleVersionModel.setContentRoots(Collections.<ExtIdeaContentRoot>singleton(contentRoot));
- return moduleVersionModel;
- }
-
- private static boolean isTestDir(SourceSet sourceSet, List<File> testClassesDirs) {
- if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.getName())) return true;
- if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) return false;
-
- File sourceSetClassesDir = sourceSet.getOutput().getClassesDir();
- for (File testClassesDir : testClassesDirs) {
- do {
- if (sourceSetClassesDir.getPath().equals(testClassesDir.getPath())) return true;
- }
- while ((testClassesDir = testClassesDir.getParentFile()) != null);
- }
-
- return false;
- }
-
- private static void addFilePath(Set<String> filePathSet, Object file) {
- if (file instanceof File) {
- try {
- filePathSet.add(((File)file).getCanonicalPath());
- }
- catch (IOException ignore) {
- }
- }
- }
-
- private static void enrichDataFromIdeaPlugin(Project project,
- Set<File> excludeDirectories,
- Set<String> javaDirectories,
- Set<String> testDirectories,
- Set<String> ideaExtResourceDirectories,
- Set<String> ideaExtTestResourceDirectories) {
-
- IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
- if (ideaPlugin == null) return;
-
- IdeaModel ideaModel = ideaPlugin.getModel();
- if (ideaModel == null || ideaModel.getModule() == null) return;
-
- for (File excludeDir : ideaModel.getModule().getExcludeDirs()) {
- excludeDirectories.add(excludeDir);
- }
- for (File file : ideaModel.getModule().getSourceDirs()) {
- javaDirectories.add(file.getPath());
- }
- for (File file : ideaModel.getModule().getTestSourceDirs()) {
- testDirectories.add(file.getPath());
- }
-
- ideaExtResourceDirectories.addAll(getExtDirs("resourceDirs", ideaModel.getModule()));
- ideaExtTestResourceDirectories.addAll(getExtDirs("testResourceDirs", ideaModel.getModule()));
- }
-
- private static List<String> getExtDirs(String propertyName, GroovyObject ideaModule) {
- List<String> directories = new ArrayList<String>();
- Object resourceDirs = ideaModule.getProperty(propertyName);
- if (resourceDirs instanceof Iterable) {
- for (Object o : Iterable.class.cast(resourceDirs)) {
- if (o instanceof File) {
- directories.add(File.class.cast(o).getPath());
- }
- else if (o instanceof String) {
- directories.add((String)o);
- }
- }
- }
-
- return directories;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/WarModelBuilderImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/WarModelBuilderImpl.java
deleted file mode 100644
index 8a1d2a1..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/builder/WarModelBuilderImpl.java
+++ /dev/null
@@ -1,130 +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.gradle.model.builder;
-
-import org.gradle.api.Action;
-import org.gradle.api.Project;
-import org.gradle.api.Task;
-import org.gradle.api.file.FileVisitDetails;
-import org.gradle.api.file.FileVisitor;
-import org.gradle.api.internal.file.copy.CopySpecInternal;
-import org.gradle.api.java.archives.Manifest;
-import org.gradle.api.plugins.WarPlugin;
-import org.gradle.api.tasks.bundling.War;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.ModelBuilderService;
-import org.jetbrains.plugins.gradle.model.WarModel;
-import org.jetbrains.plugins.gradle.model.internal.WarModelImpl;
-
-import java.io.File;
-import java.io.StringWriter;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-public class WarModelBuilderImpl implements ModelBuilderService {
-
- private static final String WEB_APP_DIR_PROPERTY = "webAppDir";
- private static final String WEB_APP_DIR_NAME_PROPERTY = "webAppDirName";
-
- @Override
- public boolean canBuild(String modelName) {
- return WarModel.class.getName().equals(modelName);
- }
-
- @Nullable
- @Override
- public Object buildAll(String modelName, Project project) {
- final WarPlugin warPlugin = project.getPlugins().findPlugin(WarPlugin.class);
- if (warPlugin == null) return null;
-
- final String webAppDirName = !project.hasProperty(WEB_APP_DIR_NAME_PROPERTY) ?
- "src/main/webapp" : String.valueOf(project.property(WEB_APP_DIR_NAME_PROPERTY));
-
- final File webAppDir = !project.hasProperty(WEB_APP_DIR_PROPERTY)
- ? new File(project.getProjectDir(), webAppDirName)
- : (File)project.property(WEB_APP_DIR_PROPERTY);
-
- WarModelImpl warModel = new WarModelImpl(webAppDirName, webAppDir);
-
- for (Task task : project.getTasks()) {
- if (task instanceof War) {
- final War warTask = (War)task;
- warModel.setWebXml(warTask.getWebXml());
-
- final Map<String, Set<String>> webRoots = new HashMap<String, Set<String>>();
- addPath(webRoots, "", webAppDir.getPath());
-
- warTask.getRootSpec().walk(new Action<CopySpecInternal>() {
- @Override
- public void execute(CopySpecInternal internal) {
- final String relativePath = internal.getDestPath().getPathString();
- internal.getSource().visit(new FileVisitor() {
- @Override
- public void visitDir(FileVisitDetails dirDetails) {
- try {
- addPath(webRoots, relativePath, dirDetails.getFile().getPath());
- }
- catch (Exception ignore) {
- }
- }
-
- @Override
- public void visitFile(FileVisitDetails fileDetails) {
- try {
- if (warTask.getWebXml() == null ||
- !fileDetails.getFile().getCanonicalPath().equals(warTask.getWebXml().getCanonicalPath())) {
- addPath(webRoots, relativePath, fileDetails.getFile().getParent());
- }
- }
- catch (Exception ignore) {
- }
- }
- });
- }
- });
-
- warModel.setWebRoots(webRoots);
- warModel.setClasspath(warTask.getClasspath().getFiles());
-
- Manifest manifest = warTask.getManifest();
- if(manifest != null) {
- StringWriter writer = new StringWriter();
- manifest.writeTo(writer);
- warModel.setManifestContent(writer.toString());
- }
- break;
- }
- }
-
- return warModel;
- }
-
- private static void addPath(Map<String, Set<String>> webRoots, String relativePath, String path) {
- relativePath = relativePath == null ? "" : relativePath;
- Set<String> paths = webRoots.get(relativePath);
- if (paths == null) {
- paths = new LinkedHashSet<String>();
- webRoots.put(relativePath, paths);
- }
- paths.add(path);
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java
index cc252a9..0f52cd8 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/BuildScriptClasspathData.java
@@ -19,8 +19,12 @@
import com.intellij.openapi.externalSystem.model.ProjectKeys;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
+import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.io.File;
+import java.io.Serializable;
import java.util.List;
/**
@@ -46,4 +50,61 @@
public List<ClasspathEntry> getClasspathEntries() {
return myClasspathEntries;
}
+
+ public static class ClasspathEntry implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private final File myClassesFile;
+
+ @Nullable
+ private final File mySourcesFile;
+
+ @Nullable
+ private final File myJavadocFile;
+
+ public ClasspathEntry(@NotNull File classesFile, @Nullable File sourcesFile, @Nullable File javadocFile) {
+ myClassesFile = classesFile;
+ mySourcesFile = sourcesFile;
+ myJavadocFile = javadocFile;
+ }
+
+ @NotNull
+ public File getClassesFile() {
+ return myClassesFile;
+ }
+
+ @Nullable
+ public File getSourcesFile() {
+ return mySourcesFile;
+ }
+
+ @Nullable
+ public File getJavadocFile() {
+ return myJavadocFile;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ClasspathEntry)) return false;
+
+ ClasspathEntry entry = (ClasspathEntry)o;
+
+ if (!FileUtil.filesEqual(myClassesFile, entry.myClassesFile)) return false;
+ if (!FileUtil.filesEqual(myJavadocFile, entry.myJavadocFile)) return false;
+ if (!FileUtil.filesEqual(mySourcesFile, entry.mySourcesFile)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = FileUtil.fileHashCode(myClassesFile);
+ result = 31 * result + FileUtil.fileHashCode(mySourcesFile);
+ result = 31 * result + FileUtil.fileHashCode(myJavadocFile);
+ return result;
+ }
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java
deleted file mode 100644
index fa0959f..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ClasspathEntry.java
+++ /dev/null
@@ -1,84 +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 org.jetbrains.plugins.gradle.model.data;
-
-import com.intellij.openapi.util.io.FileUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 12/23/13
- */
-public class ClasspathEntry implements Serializable {
-
- private static final long serialVersionUID = 1L;
-
- @NotNull
- private final File myClassesFile;
-
- @Nullable
- private final File mySourcesFile;
-
- @Nullable
- private final File myJavadocFile;
-
- public ClasspathEntry(@NotNull File classesFile, @Nullable File sourcesFile, @Nullable File javadocFile) {
- myClassesFile = classesFile;
- mySourcesFile = sourcesFile;
- myJavadocFile = javadocFile;
- }
-
- @NotNull
- public File getClassesFile() {
- return myClassesFile;
- }
-
- @Nullable
- public File getSourcesFile() {
- return mySourcesFile;
- }
-
- @Nullable
- public File getJavadocFile() {
- return myJavadocFile;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof ClasspathEntry)) return false;
-
- ClasspathEntry entry = (ClasspathEntry)o;
-
- if (!FileUtil.filesEqual(myClassesFile, entry.myClassesFile)) return false;
- if (!FileUtil.filesEqual(myJavadocFile, entry.myJavadocFile)) return false;
- if (!FileUtil.filesEqual(mySourcesFile, entry.mySourcesFile)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = FileUtil.fileHashCode(myClassesFile);
- result = 31 * result + FileUtil.fileHashCode(mySourcesFile);
- result = 31 * result + FileUtil.fileHashCode(myJavadocFile);
- return result;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ScalaCompileOptionsData.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ScalaCompileOptionsData.java
new file mode 100644
index 0000000..14f8bdc
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ScalaCompileOptionsData.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.model.data;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public class ScalaCompileOptionsData implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private boolean useCompileDaemon;
+ private String daemonServer;
+ private boolean failOnError;
+ private boolean deprecation;
+ private boolean unchecked;
+ private String debugLevel;
+ private boolean optimize;
+ private String encoding;
+ private String force;
+ private String targetCompatibility;
+ private List<String> additionalParameters;
+ private boolean listFiles;
+ private String loggingLevel;
+ private List<String> loggingPhases;
+ private boolean fork;
+ private ScalaForkOptions forkOptions;
+ private boolean useAnt;
+
+ public boolean isUseCompileDaemon() {
+ return useCompileDaemon;
+ }
+
+ public void setUseCompileDaemon(boolean useCompileDaemon) {
+ this.useCompileDaemon = useCompileDaemon;
+ }
+
+ public String getDaemonServer() {
+ return daemonServer;
+ }
+
+ public void setDaemonServer(String daemonServer) {
+ this.daemonServer = daemonServer;
+ }
+
+ public boolean isFailOnError() {
+ return failOnError;
+ }
+
+ public void setFailOnError(boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+ public boolean isDeprecation() {
+ return deprecation;
+ }
+
+ public void setDeprecation(boolean deprecation) {
+ this.deprecation = deprecation;
+ }
+
+ public boolean isUnchecked() {
+ return unchecked;
+ }
+
+ public void setUnchecked(boolean unchecked) {
+ this.unchecked = unchecked;
+ }
+
+ public String getDebugLevel() {
+ return debugLevel;
+ }
+
+ public void setDebugLevel(String debugLevel) {
+ this.debugLevel = debugLevel;
+ }
+
+ public boolean isOptimize() {
+ return optimize;
+ }
+
+ public void setOptimize(boolean optimize) {
+ this.optimize = optimize;
+ }
+
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public String getForce() {
+ return force;
+ }
+
+ public void setForce(String force) {
+ this.force = force;
+ }
+
+ public String getTargetCompatibility() {
+ return targetCompatibility;
+ }
+
+ public void setTargetCompatibility(String targetCompatibility) {
+ this.targetCompatibility = targetCompatibility;
+ }
+
+ public List<String> getAdditionalParameters() {
+ return additionalParameters;
+ }
+
+ public void setAdditionalParameters(List<String> additionalParameters) {
+ this.additionalParameters = additionalParameters;
+ }
+
+ public boolean isListFiles() {
+ return listFiles;
+ }
+
+ public void setListFiles(boolean listFiles) {
+ this.listFiles = listFiles;
+ }
+
+ public String getLoggingLevel() {
+ return loggingLevel;
+ }
+
+ public void setLoggingLevel(String loggingLevel) {
+ this.loggingLevel = loggingLevel;
+ }
+
+ public List<String> getLoggingPhases() {
+ return loggingPhases;
+ }
+
+ public void setLoggingPhases(List<String> loggingPhases) {
+ this.loggingPhases = loggingPhases;
+ }
+
+ public boolean isFork() {
+ return fork;
+ }
+
+ public void setFork(boolean fork) {
+ this.fork = fork;
+ }
+
+ public boolean isUseAnt() {
+ return useAnt;
+ }
+
+ public void setUseAnt(boolean useAnt) {
+ this.useAnt = useAnt;
+ }
+
+ public ScalaForkOptions getForkOptions() {
+ return forkOptions;
+ }
+
+ public void setForkOptions(ScalaForkOptions forkOptions) {
+ this.forkOptions = forkOptions;
+ }
+
+ public static class ScalaForkOptions implements Serializable {
+ private static final long serialVersionUID = 1L;
+ private String memoryInitialSize;
+ private String memoryMaximumSize;
+ private List<String> jvmArgs;
+
+ public String getMemoryInitialSize() {
+ return memoryInitialSize;
+ }
+
+ public void setMemoryInitialSize(String memoryInitialSize) {
+ this.memoryInitialSize = memoryInitialSize;
+ }
+
+ public String getMemoryMaximumSize() {
+ return memoryMaximumSize;
+ }
+
+ public void setMemoryMaximumSize(String memoryMaximumSize) {
+ this.memoryMaximumSize = memoryMaximumSize;
+ }
+
+ public List<String> getJvmArgs() {
+ return jvmArgs;
+ }
+
+ public void setJvmArgs(List<String> jvmArgs) {
+ this.jvmArgs = jvmArgs;
+ }
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ScalaModelData.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ScalaModelData.java
new file mode 100644
index 0000000..3e9d62c
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/ScalaModelData.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.model.data;
+
+import com.intellij.openapi.externalSystem.model.Key;
+import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.ProjectSystemId;
+import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public class ScalaModelData extends AbstractExternalEntityData {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ public static final Key<ScalaModelData> KEY = Key.create(ScalaModelData.class, ProjectKeys.LIBRARY_DEPENDENCY.getProcessingWeight() + 1);
+ private Set<File> scalaClasspath;
+ private Set<File> zincClasspath;
+ private ScalaCompileOptionsData scalaCompileOptions;
+ private String sourceCompatibility;
+ private String targetCompatibility;
+
+
+ public ScalaModelData(@NotNull ProjectSystemId owner) {
+ super(owner);
+ }
+
+ public Set<File> getScalaClasspath() {
+ return scalaClasspath;
+ }
+
+ public void setScalaClasspath(Set<File> scalaClasspath) {
+ this.scalaClasspath = scalaClasspath;
+ }
+
+ public Set<File> getZincClasspath() {
+ return zincClasspath;
+ }
+
+ public void setZincClasspath(Set<File> zincClasspath) {
+ this.zincClasspath = zincClasspath;
+ }
+
+ public ScalaCompileOptionsData getScalaCompileOptions() {
+ return scalaCompileOptions;
+ }
+
+ public void setScalaCompileOptions(ScalaCompileOptionsData scalaCompileOptions) {
+ this.scalaCompileOptions = scalaCompileOptions;
+ }
+
+ public String getSourceCompatibility() {
+ return sourceCompatibility;
+ }
+
+ public void setSourceCompatibility(String sourceCompatibility) {
+ this.sourceCompatibility = sourceCompatibility;
+ }
+
+ public String getTargetCompatibility() {
+ return targetCompatibility;
+ }
+
+ public void setTargetCompatibility(String targetCompatibility) {
+ this.targetCompatibility = targetCompatibility;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof ScalaModelData)) return false;
+ if (!super.equals(o)) return false;
+
+ ScalaModelData data = (ScalaModelData)o;
+
+ if (scalaClasspath != null ? !scalaClasspath.equals(data.scalaClasspath) : data.scalaClasspath != null) return false;
+ if (scalaCompileOptions != null ? !scalaCompileOptions.equals(data.scalaCompileOptions) : data.scalaCompileOptions != null) {
+ return false;
+ }
+ if (sourceCompatibility != null ? !sourceCompatibility.equals(data.sourceCompatibility) : data.sourceCompatibility != null) {
+ return false;
+ }
+ if (targetCompatibility != null ? !targetCompatibility.equals(data.targetCompatibility) : data.targetCompatibility != null) {
+ return false;
+ }
+ if (zincClasspath != null ? !zincClasspath.equals(data.zincClasspath) : data.zincClasspath != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (scalaClasspath != null ? scalaClasspath.hashCode() : 0);
+ result = 31 * result + (zincClasspath != null ? zincClasspath.hashCode() : 0);
+ result = 31 * result + (scalaCompileOptions != null ? scalaCompileOptions.hashCode() : 0);
+ result = 31 * result + (sourceCompatibility != null ? sourceCompatibility.hashCode() : 0);
+ result = 31 * result + (targetCompatibility != null ? targetCompatibility.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/War.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/War.java
new file mode 100644
index 0000000..b183324
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/War.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.gradle.model.data;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/10/14
+ */
+public class War implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private final String myName;
+
+ @NotNull
+ private final String myWebAppDirName;
+ @NotNull
+ private final File myWebAppDir;
+ @Nullable
+ private File myWebXml;
+ @NotNull
+ private List<WebResource> myWebResources;
+ @NotNull
+ private Set<File> myClasspath;
+ @Nullable
+ private String myManifestContent;
+
+
+ public War(@NotNull String name, @NotNull String webAppDirName, @NotNull File webAppDir) {
+ myName = name;
+ myWebAppDirName = webAppDirName;
+ myWebAppDir = webAppDir;
+ myWebResources = Collections.emptyList();
+ myClasspath = Collections.emptySet();
+ }
+
+ @NotNull
+ public String getName() {
+ return myName;
+ }
+
+ @NotNull
+ public String getWebAppDirName() {
+ return myWebAppDirName;
+ }
+
+ @NotNull
+ public File getWebAppDir() {
+ return myWebAppDir;
+ }
+
+ public void setWebXml(@Nullable File webXml) {
+ myWebXml = webXml;
+ }
+
+ @Nullable
+ public File getWebXml() {
+ return myWebXml;
+ }
+
+ public void setWebResources(@Nullable List<WebResource> webResources) {
+ myWebResources = webResources == null ? Collections.<WebResource>emptyList() : webResources;
+ }
+
+ @NotNull
+ public List<WebResource> getWebResources() {
+ return myWebResources;
+ }
+
+ public void setClasspath(@Nullable Set<File> classpath) {
+ myClasspath = classpath == null ? Collections.<File>emptySet() : classpath;
+ }
+
+ @NotNull
+ public Set<File> getClasspath() {
+ return myClasspath;
+ }
+
+ public void setManifestContent(@Nullable String manifestContent) {
+ myManifestContent = manifestContent;
+ }
+
+ @Nullable
+ public String getManifestContent() {
+ return myManifestContent;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ if (!super.equals(o)) return false;
+
+ War that = (War)o;
+
+ if (!myName.equals(that.myName)) return false;
+ if (!myWebAppDirName.equals(that.myWebAppDirName)) return false;
+ if (!myWebResources.equals(that.myWebResources)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + myName.hashCode();
+ result = 31 * result + myWebAppDirName.hashCode();
+ result = 31 * result + myWebResources.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "War{" +
+ "myName='" + myName + '\'' +
+ ", myWebAppDirName='" + myWebAppDirName + '\'' +
+ ", myWebAppDir=" + myWebAppDir +
+ ", myWebXml=" + myWebXml +
+ ", myWebResources=" + myWebResources +
+ '}';
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WarDirectory.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WarDirectory.java
new file mode 100644
index 0000000..b59dcbb
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WarDirectory.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 org.jetbrains.plugins.gradle.model.data;
+
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/10/14
+ */
+public enum WarDirectory {
+ /**
+ * Public files typically include the following:
+ * HTML files.
+ * JSP files.
+ * Image files and other multimedia files -- it is a common convention to store image files in an images subdirectory.
+ */
+ WAR_ROOT("/"),
+ /**
+ * directory can contain the following file:
+ * META-INF/MANIFEST.MF -- an optional file that can be used to specify additional meta-information for the WAR.
+ */
+ META_INF("/META-INF"),
+ /**
+ * Directory contains a Web archive's private files and directories.
+ * That is, when the Web archive is deployed, the files and directories under the WEB-INF/ directory cannot be accessed directly by Web clients.
+ */
+ WEB_INF("/WEB-INF"),
+ /**
+ * Subdirectory can store JAR files used by the Web module.
+ * The JAR files in this directory are automatically accessible to the Web module without needing to be added to the class path.
+ */
+ WEB_INF_LIB("/WEB-INF/lib"),
+ /**
+ * Subdirectory contains the compiled Java code for the Web module.
+ */
+ WEB_INF_CLASSES("/WEB-INF/classes");
+ @NotNull
+ private final String myRelativePath;
+
+ WarDirectory(@NotNull final String relativePath) {
+ myRelativePath = relativePath;
+ }
+
+ @NotNull
+ public String getRelativePath() {
+ return myRelativePath;
+ }
+
+ @Nullable
+ public static WarDirectory fromPath(final @NotNull String path) {
+ if (StringUtil.isEmpty(path)) return WAR_ROOT;
+
+ final String adjustedPath = path.charAt(0) != '/' ? '/' + path : path;
+ for (WarDirectory warDirectory : values()) {
+ if (warDirectory.myRelativePath.equals(adjustedPath)) return warDirectory;
+ }
+ return null;
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WarModelData.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WarModelData.java
deleted file mode 100644
index f22ab8f..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WarModelData.java
+++ /dev/null
@@ -1,138 +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.gradle.model.data;
-
-import com.intellij.openapi.externalSystem.model.Key;
-import com.intellij.openapi.externalSystem.model.ProjectKeys;
-import com.intellij.openapi.externalSystem.model.ProjectSystemId;
-import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/6/13
- */
-public class WarModelData extends AbstractExternalEntityData {
- private static final long serialVersionUID = 1L;
-
- @NotNull
- public static final Key<WarModelData> KEY = Key.create(WarModelData.class, ProjectKeys.LIBRARY_DEPENDENCY.getProcessingWeight() + 1);
- @NotNull
- private final String myWebAppDirName;
- @NotNull
- private final File myWebAppDir;
- @Nullable
- private File myWebXml;
- @NotNull
- private Map<String, Set<String>> myWebRoots;
- @NotNull
- private Set<File> myClasspath;
- @Nullable
- private String myManifestContent;
-
-
- public WarModelData(@NotNull ProjectSystemId owner, @NotNull String webAppDirName, @NotNull File webAppDir) {
- super(owner);
- myWebAppDirName = webAppDirName;
- myWebAppDir = webAppDir;
- myWebRoots = Collections.emptyMap();
- myClasspath = Collections.emptySet();
- }
-
- @NotNull
- public String getWebAppDirName() {
- return myWebAppDirName;
- }
-
- @NotNull
- public File getWebAppDir() {
- return myWebAppDir;
- }
-
- public void setWebXml(@Nullable File webXml) {
- myWebXml = webXml;
- }
-
- @Nullable
- public File getWebXml() {
- return myWebXml;
- }
-
- public void setWebRoots(@Nullable Map<String, Set<String>> webRoots) {
- myWebRoots = webRoots == null ? Collections.<String, Set<String>>emptyMap() : webRoots;
- }
-
- @NotNull
- public Map<String, Set<String>> getWebRoots() {
- return myWebRoots;
- }
-
- public void setClasspath(@Nullable Set<File> classpath) {
- myClasspath = classpath == null ? Collections.<File>emptySet() : classpath;
- }
-
- @NotNull
- public Set<File> getClasspath() {
- return myClasspath;
- }
-
- public void setManifestContent(@Nullable String manifestContent) {
- myManifestContent = manifestContent;
- }
-
- @Nullable
- public String getManifestContent() {
- return myManifestContent;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
- if (!super.equals(o)) return false;
-
- WarModelData that = (WarModelData)o;
-
- if (!myWebAppDirName.equals(that.myWebAppDirName)) return false;
- if (!myWebRoots.equals(that.myWebRoots)) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = super.hashCode();
- result = 31 * result + myWebAppDirName.hashCode();
- result = 31 * result + myWebRoots.hashCode();
- return result;
- }
-
- @Override
- public String toString() {
- return "WarModelData{" +
- "myWebAppDirName='" + myWebAppDirName + '\'' +
- ", myWebAppDir=" + myWebAppDir +
- ", myWebXml=" + myWebXml +
- ", myWebRoots=" + myWebRoots +
- '}';
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WebConfigurationModelData.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WebConfigurationModelData.java
new file mode 100644
index 0000000..6874703
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WebConfigurationModelData.java
@@ -0,0 +1,76 @@
+/*
+ * 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.gradle.model.data;
+
+import com.intellij.openapi.externalSystem.model.Key;
+import com.intellij.openapi.externalSystem.model.ProjectKeys;
+import com.intellij.openapi.externalSystem.model.ProjectSystemId;
+import com.intellij.openapi.externalSystem.model.project.AbstractExternalEntityData;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/6/13
+ */
+public class WebConfigurationModelData extends AbstractExternalEntityData {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ public static final Key<WebConfigurationModelData> KEY =
+ Key.create(WebConfigurationModelData.class, ProjectKeys.LIBRARY_DEPENDENCY.getProcessingWeight() + 1);
+
+ @NotNull
+ private final List<War> myWars;
+
+ public WebConfigurationModelData(@NotNull ProjectSystemId owner, @NotNull List<War> warModels) {
+ super(owner);
+ myWars = warModels;
+ }
+
+ @NotNull
+ public List<War> getWars() {
+ return myWars;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof WebConfigurationModelData)) return false;
+ if (!super.equals(o)) return false;
+
+ WebConfigurationModelData data = (WebConfigurationModelData)o;
+
+ if (!myWars.equals(data.myWars)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + myWars.hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "WebConfigurationModelData{" +
+ "myWars=" + myWars +
+ '}';
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WebResource.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WebResource.java
new file mode 100644
index 0000000..a33bb7e
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/data/WebResource.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.model.data;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/10/14
+ */
+public class WebResource implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @NotNull
+ private final WarDirectory myWarDirectory;
+ @NotNull
+ private final String warRelativePath;
+ @NotNull
+ private final File file;
+
+ public WebResource(@NotNull WarDirectory warDirectory, @NotNull String warRelativePath, @NotNull File file) {
+ myWarDirectory = warDirectory;
+ this.warRelativePath = warRelativePath;
+ this.file = file;
+ }
+
+ @NotNull
+ public WarDirectory getWarDirectory() {
+ return myWarDirectory;
+ }
+
+ @NotNull
+ public String getWarRelativePath() {
+ return warRelativePath;
+ }
+
+ @NotNull
+ public File getFile() {
+ return file;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof WebResource)) return false;
+
+ WebResource resource = (WebResource)o;
+ if (!file.getPath().equals(resource.file.getPath())) return false;
+ if (myWarDirectory != resource.myWarDirectory) return false;
+ if (!warRelativePath.equals(resource.warRelativePath)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myWarDirectory.hashCode();
+ result = 31 * result + warRelativePath.hashCode();
+ result = 31 * result + file.getPath().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "WebResource{" +
+ "myWarDirectory=" + myWarDirectory +
+ ", warRelativePath='" + warRelativePath + '\'' +
+ ", file=" + file +
+ '}';
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/AbstractGradleDependency.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/AbstractGradleDependency.java
deleted file mode 100644
index 948081a..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/AbstractGradleDependency.java
+++ /dev/null
@@ -1,105 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/8/13
- */
-public abstract class AbstractGradleDependency implements Serializable {
- private final IdeaDependencyScope myScope;
- private final String myDependencyName;
- private final String myDependencyGroup;
- private final String myDependencyVersion;
- private final String myClassifier;
-
- public AbstractGradleDependency(IdeaDependencyScope scope, String dependencyName,
- String dependencyGroup, String dependencyVersion, String classifier) {
- myScope = scope;
- myDependencyName = dependencyName;
- myDependencyGroup = dependencyGroup;
- myDependencyVersion = dependencyVersion;
- myClassifier = classifier;
- }
-
- public IdeaDependencyScope getScope() {
- return myScope;
- }
-
- public boolean getExported() {
- return "compile".equals(myScope.getScope()) || "runtime".equals(myScope.getScope());
- }
-
- public String getDependencyName() {
- return myDependencyName;
- }
-
- public String getDependencyGroup() {
- return myDependencyGroup;
- }
-
- public String getDependencyVersion() {
- return myDependencyVersion;
- }
-
- public String getClassifier() {
- return myClassifier;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof AbstractGradleDependency)) return false;
-
- AbstractGradleDependency that = (AbstractGradleDependency)o;
-
- if (myDependencyGroup != null ? !myDependencyGroup.equals(that.myDependencyGroup) : that.myDependencyGroup != null) return false;
- if (myDependencyName != null ? !myDependencyName.equals(that.myDependencyName) : that.myDependencyName != null) return false;
- if (myDependencyVersion != null ? !myDependencyVersion.equals(that.myDependencyVersion) : that.myDependencyVersion != null) {
- return false;
- }
- if (myScope != null ? !myScope.equals(that.myScope) : that.myScope != null) return false;
- if (myClassifier != null ? !myClassifier.equals(that.myClassifier) : that.myClassifier != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = myScope != null ? myScope.hashCode() : 0;
- result = 31 * result + (myDependencyName != null ? myDependencyName.hashCode() : 0);
- result = 31 * result + (myDependencyGroup != null ? myDependencyGroup.hashCode() : 0);
- result = 31 * result + (myDependencyVersion != null ? myDependencyVersion.hashCode() : 0);
- result = 31 * result + (myClassifier != null ? myClassifier.hashCode() : 0);
- return result;
- }
-
- @Override
- public String toString() {
- return "GradleDependency{" +
- "myScope=" + myScope +
- ", dependencyName='" + myDependencyName + '\'' +
- ", dependencyGroup='" + myDependencyGroup + '\'' +
- ", dependencyVersion='" + myDependencyVersion + '\'' +
- ", classifier='" + myClassifier + '\'' +
- ", exported=" + getExported() +
- '}';
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java
deleted file mode 100644
index b592411..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/BuildScriptClasspathModelImpl.java
+++ /dev/null
@@ -1,47 +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 org.jetbrains.plugins.gradle.model.internal;
-
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
-import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Vladislav.Soroka
- * @since 12/20/13
- */
-public class BuildScriptClasspathModelImpl implements BuildScriptClasspathModel {
-
- private final List<ClasspathEntryModel> myClasspathEntries;
-
- public BuildScriptClasspathModelImpl() {
- myClasspathEntries = new ArrayList<ClasspathEntryModel>();
- }
-
- @Override
- public DomainObjectSet<? extends ClasspathEntryModel> getClasspath() {
- return ImmutableDomainObjectSet.of(myClasspathEntries);
- }
-
- public void add(@NotNull ClasspathEntryModel classpathEntryModel) {
- myClasspathEntries.add(classpathEntryModel);
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java
deleted file mode 100644
index 0618810..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ClasspathEntryModelImpl.java
+++ /dev/null
@@ -1,60 +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 org.jetbrains.plugins.gradle.model.internal;
-
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 12/20/13
- */
-public class ClasspathEntryModelImpl implements ClasspathEntryModel, Serializable {
- @NotNull
- private final File classesFile;
- @Nullable
- private final File sourcesFile;
- @Nullable
- private final File javadocFile;
-
- public ClasspathEntryModelImpl(@NotNull File classesFile, @Nullable File sourcesFile, @Nullable File javadocFile) {
- this.classesFile = classesFile;
- this.sourcesFile = sourcesFile;
- this.javadocFile = javadocFile;
- }
-
- @NotNull
- @Override
- public File getClassesFile() {
- return classesFile;
- }
-
- @Nullable
- @Override
- public File getSourcesFile() {
- return sourcesFile;
- }
-
- @Nullable
- @Override
- public File getJavadocFile() {
- return javadocFile;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/DependencyVersionId.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/DependencyVersionId.java
deleted file mode 100644
index e8658cf..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/DependencyVersionId.java
+++ /dev/null
@@ -1,96 +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.gradle.model.internal;
-
-import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/25/13
- */
-public class DependencyVersionId {
- private final IdeDependenciesExtractor.IdeDependency myIdeDependency;
- private final String myName;
- private final String myGroup;
- private final String myVersion;
- private final String myClassifier;
-
- public DependencyVersionId(IdeDependenciesExtractor.IdeDependency dependency,
- String name,
- String group,
- String version,
- String classifier) {
- myIdeDependency = dependency;
- myName = name;
- myGroup = group;
- myVersion = version;
- myClassifier = classifier;
- }
-
- public String getName() {
- return myName;
- }
-
- public String getGroup() {
- return myGroup;
- }
-
- public String getVersion() {
- return myVersion;
- }
-
- public String getClassifier() {
- return myClassifier;
- }
-
- public IdeDependenciesExtractor.IdeDependency getIdeDependency() {
- return myIdeDependency;
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof DependencyVersionId)) return false;
-
- DependencyVersionId id = (DependencyVersionId)o;
-
- if (myGroup != null ? !myGroup.equals(id.myGroup) : id.myGroup != null) return false;
- if (myName != null ? !myName.equals(id.myName) : id.myName != null) return false;
- if (myVersion != null ? !myVersion.equals(id.myVersion) : id.myVersion != null) return false;
- if (myClassifier != null ? !myClassifier.equals(id.myClassifier) : id.myClassifier != null) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- int result = myName != null ? myName.hashCode() : 0;
- result = 31 * result + (myGroup != null ? myGroup.hashCode() : 0);
- result = 31 * result + (myVersion != null ? myVersion.hashCode() : 0);
- result = 31 * result + (myClassifier != null ? myClassifier.hashCode() : 0);
- return result;
- }
-
- @Override
- public String toString() {
- return "DependencyVersionId{" +
- "name='" + myName + '\'' +
- ", group='" + myGroup + '\'' +
- ", version='" + myVersion + '\'' +
- ", classifier='" + myClassifier + '\'' +
- '}';
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ExtraModelBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ExtraModelBuilder.java
deleted file mode 100644
index 2619557..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ExtraModelBuilder.java
+++ /dev/null
@@ -1,50 +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.gradle.model.internal;
-
-import org.gradle.api.Project;
-import org.gradle.tooling.provider.model.ToolingModelBuilder;
-import org.jetbrains.plugins.gradle.model.ModelBuilderService;
-
-import java.util.ServiceLoader;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-@SuppressWarnings("UnusedDeclaration")
-public class ExtraModelBuilder implements ToolingModelBuilder {
- private static ServiceLoader<ModelBuilderService> buildersLoader =
- ServiceLoader.load(ModelBuilderService.class, ExtraModelBuilder.class.getClassLoader());
-
- @Override
- public boolean canBuild(String modelName) {
- for (ModelBuilderService service : buildersLoader) {
- if (service.canBuild(modelName)) return true;
- }
- return false;
- }
-
- @Override
- public Object buildAll(String modelName, Project project) {
- for (ModelBuilderService service : buildersLoader) {
- if (service.canBuild(modelName)) {
- return service.buildAll(modelName, project);
- }
- }
- throw new IllegalArgumentException("Unsupported model: " + modelName);
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaContentRootImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaContentRootImpl.java
deleted file mode 100644
index 86a3741..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaContentRootImpl.java
+++ /dev/null
@@ -1,100 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.idea.IdeaSourceDirectory;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/13/13
- */
-public class IdeaContentRootImpl implements ExtIdeaContentRoot {
-
- private final File myRootDirectory;
- private final List<IdeaSourceDirectory> mySourceDirectories;
- private final List<IdeaSourceDirectory> myTestDirectories;
- private final List<IdeaSourceDirectory> myResourceDirectories;
- private final List<IdeaSourceDirectory> myTestResourceDirectories;
- private final Set<File> myExcludeDirectories;
-
- public IdeaContentRootImpl(File rootDirectory) {
- myRootDirectory = rootDirectory;
- mySourceDirectories = new ArrayList<IdeaSourceDirectory>();
- myTestDirectories = new ArrayList<IdeaSourceDirectory>();
- myResourceDirectories = new ArrayList<IdeaSourceDirectory>();
- myTestResourceDirectories = new ArrayList<IdeaSourceDirectory>();
- myExcludeDirectories = new HashSet<File>();
- }
-
- @Override
- public File getRootDirectory() {
- return myRootDirectory;
- }
-
- @Override
- public DomainObjectSet<? extends IdeaSourceDirectory> getSourceDirectories() {
- return ImmutableDomainObjectSet.of(mySourceDirectories);
- }
-
- public void addSourceDirectory(IdeaSourceDirectory sourceDirectory) {
- mySourceDirectories.add(sourceDirectory);
- }
-
- public void addTestDirectory(IdeaSourceDirectory testDirectory) {
- myTestDirectories.add(testDirectory);
- }
-
- public void addResourceDirectory(IdeaSourceDirectory resourceDirectory) {
- myResourceDirectories.add(resourceDirectory);
- }
-
- public void addTestResourceDirectory(IdeaSourceDirectory resourceDirectory) {
- myTestResourceDirectories.add(resourceDirectory);
- }
-
- public void addExcludeDirectory(File excludeDirectory) {
- myExcludeDirectories.add(excludeDirectory);
- }
-
- @Override
- public DomainObjectSet<? extends IdeaSourceDirectory> getTestDirectories() {
- return ImmutableDomainObjectSet.of(myTestDirectories);
- }
-
- @Override
- public DomainObjectSet<? extends IdeaSourceDirectory> getResourceDirectories() {
- return ImmutableDomainObjectSet.of(myResourceDirectories);
- }
-
- @Override
- public DomainObjectSet<? extends IdeaSourceDirectory> getTestResourceDirectories() {
- return ImmutableDomainObjectSet.of(myTestResourceDirectories);
- }
-
- @Override
- public Set<File> getExcludeDirectories() {
- return myExcludeDirectories;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaDependencyScopeImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaDependencyScopeImpl.java
deleted file mode 100644
index aa7f5af..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaDependencyScopeImpl.java
+++ /dev/null
@@ -1,61 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
-
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/25/13
- */
-public class IdeaDependencyScopeImpl implements IdeaDependencyScope, Serializable {
-
- private final GradleDependencyScope myDependencyScope;
-
- public IdeaDependencyScopeImpl(GradleDependencyScope scope) {
- myDependencyScope = scope;
- }
-
- @Override
- public String getScope() {
- return myDependencyScope.getIdeaMappingName();
- }
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof IdeaDependencyScopeImpl)) return false;
-
- IdeaDependencyScopeImpl scope = (IdeaDependencyScopeImpl)o;
-
- if (myDependencyScope != scope.myDependencyScope) return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return myDependencyScope != null ? myDependencyScope.hashCode() : 0;
- }
-
- @Override
- public String toString() {
- return "IdeaDependencyScope{" + myDependencyScope + '}';
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaModuleDependencyImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaModuleDependencyImpl.java
deleted file mode 100644
index 6890ebd..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaModuleDependencyImpl.java
+++ /dev/null
@@ -1,48 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaModuleDependency;
-
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/25/13
- */
-public class IdeaModuleDependencyImpl extends AbstractGradleDependency
- implements IdeaModuleDependency, Serializable {
- private IdeaModule myIdeaModule;
-
- public IdeaModuleDependencyImpl(IdeaDependencyScope myScope,
- String dependencyName,
- String dependencyGroup,
- String dependencyVersion,
- String classifier) {
- super(myScope, dependencyName, dependencyGroup, dependencyVersion, classifier);
- }
-
- @Override
- public IdeaModule getDependencyModule() {
- return myIdeaModule;
- }
-
- public void setIdeaModule(IdeaModule ideaModule) {
- myIdeaModule = ideaModule;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaSingleEntryLibraryDependencyImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaSingleEntryLibraryDependencyImpl.java
deleted file mode 100644
index 7012a36..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaSingleEntryLibraryDependencyImpl.java
+++ /dev/null
@@ -1,75 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.GradleModuleVersion;
-import org.gradle.tooling.model.idea.IdeaDependencyScope;
-import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/25/13
- */
-public class IdeaSingleEntryLibraryDependencyImpl extends AbstractGradleDependency
- implements IdeaSingleEntryLibraryDependency, Serializable {
-
- private File myFile;
- private File mySource;
- private File myJavadoc;
-
- public IdeaSingleEntryLibraryDependencyImpl(IdeaDependencyScope myScope,
- String dependencyName,
- String dependencyGroup,
- String dependencyVersion,
- String classifier) {
- super(myScope, dependencyName, dependencyGroup, dependencyVersion, classifier);
- }
-
- @Override
- public File getFile() {
- return myFile;
- }
-
- @Override
- public File getSource() {
- return mySource;
- }
-
- @Override
- public File getJavadoc() {
- return myJavadoc;
- }
-
- public void setFile(File file) {
- myFile = file;
- }
-
- public void setSource(File source) {
- mySource = source;
- }
-
- public void setJavadoc(File javadoc) {
- myJavadoc = javadoc;
- }
-
- @Override
- public GradleModuleVersion getGradleModuleVersion() {
- return null;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaSourceDirectoryImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaSourceDirectoryImpl.java
deleted file mode 100644
index bcc37bd..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/IdeaSourceDirectoryImpl.java
+++ /dev/null
@@ -1,39 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.idea.IdeaSourceDirectory;
-
-import java.io.File;
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/15/13
- */
-public class IdeaSourceDirectoryImpl implements IdeaSourceDirectory, Serializable {
-
- private final File myDirectory;
-
- public IdeaSourceDirectoryImpl(File directory) {
- myDirectory = directory;
- }
-
- @Override
- public File getDirectory() {
- return myDirectory;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ModuleExtendedModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ModuleExtendedModelImpl.java
deleted file mode 100644
index b8bce40..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ModuleExtendedModelImpl.java
+++ /dev/null
@@ -1,79 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
-import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
-import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
-
-import java.io.File;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/8/13
- */
-public class ModuleExtendedModelImpl implements ModuleExtendedModel {
- private final String myName;
- private final String myGroup;
- private final String myVersion;
- private List<File> myArtifacts;
- private Set<ExtIdeaContentRoot> myContentRoots;
-
- public ModuleExtendedModelImpl(String name, String group, String version) {
- myName = name;
- myGroup = group;
- myVersion = version;
- myArtifacts = Collections.emptyList();
- myContentRoots = Collections.emptySet();
- }
-
- @Override
- public String getName() {
- return myName;
- }
-
- @Override
- public String getGroup() {
- return myGroup;
- }
-
- @Override
- public String getVersion() {
- return myVersion;
- }
-
- @Override
- public List<File> getArtifacts() {
- return myArtifacts;
- }
-
- public void setArtifacts(List<File> artifacts) {
- this.myArtifacts = artifacts == null ? Collections.<File>emptyList() : artifacts;
- }
-
- @Override
- public DomainObjectSet<? extends ExtIdeaContentRoot> getContentRoots() {
- return ImmutableDomainObjectSet.of(myContentRoots);
- }
-
- public void setContentRoots(Set<ExtIdeaContentRoot> contentRoots) {
- myContentRoots = contentRoots == null ? Collections.<ExtIdeaContentRoot>emptySet() : contentRoots;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ProjectDependenciesModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ProjectDependenciesModelImpl.java
deleted file mode 100644
index 533c350..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/ProjectDependenciesModelImpl.java
+++ /dev/null
@@ -1,52 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.idea.IdeaDependency;
-import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
-
-import java.util.List;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/8/13
- */
-public class ProjectDependenciesModelImpl implements ProjectDependenciesModel {
- private final String projectName;
- private final List<IdeaDependency> myDependencies;
-
- public ProjectDependenciesModelImpl(String projectName, List<IdeaDependency> dependencies) {
- this.projectName = projectName;
- myDependencies = dependencies;
- }
-
- @Override
- public String getProjectName() {
- return projectName;
- }
-
- @Override
- public List<IdeaDependency> getDependencies() {
- return myDependencies;
- }
-
- @Override
- public String toString() {
- return "ProjectDependenciesModelImpl{" +
- "projectName='" + projectName + '\'' +
- '}';
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/Scopes.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/Scopes.java
deleted file mode 100644
index cc0155e..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/Scopes.java
+++ /dev/null
@@ -1,84 +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.gradle.model.internal;
-
-import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/25/13
- */
-public class Scopes {
- private boolean myForProductionCompile;
- private boolean myForProductionRuntime;
- private boolean myForTestCompile;
- private boolean myForTestRuntime;
- private boolean myIsProvided;
-
- public Scopes(GradleDependencyScope scope) {
- myForProductionCompile = scope.isForProductionCompile();
- myForProductionRuntime = scope.isForProductionRuntime();
- myForTestCompile = scope.isForTestCompile();
- myForTestRuntime = scope.isForTestRuntime();
- myIsProvided = scope == GradleDependencyScope.PROVIDED_COMPILE ||
- scope == GradleDependencyScope.PROVIDED_RUNTIME ||
- scope == GradleDependencyScope.PROVIDED;
- }
-
- public GradleDependencyScope[] getScopes() {
- if (myIsProvided) {
- if (myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.PROVIDED_COMPILE};
- }
- else if (!myForProductionCompile && myForProductionRuntime && !myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.PROVIDED_RUNTIME};
- }
- else if (!myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.TEST_COMPILE, GradleDependencyScope.PROVIDED_RUNTIME};
- }
- }
-
- if (myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.COMPILE};
- }
- else if (!myForProductionCompile && myForProductionRuntime && !myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.RUNTIME};
- }
- else if (!myForProductionCompile && !myForProductionRuntime && myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.TEST_COMPILE};
- }
- else if (!myForProductionCompile && !myForProductionRuntime && !myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.TEST_RUNTIME};
- }
- else if (!myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
- return new GradleDependencyScope[]{GradleDependencyScope.TEST_COMPILE, GradleDependencyScope.RUNTIME};
- }
- else {
- return new GradleDependencyScope[]{GradleDependencyScope.COMPILE};
- }
- }
-
- public void add(GradleDependencyScope scope) {
- myForProductionCompile = myForProductionCompile || scope.isForProductionCompile();
- myForProductionRuntime = myForProductionRuntime || scope.isForProductionRuntime();
- myForTestCompile = myForTestCompile || scope.isForTestCompile();
- myForTestRuntime = myForTestRuntime || scope.isForTestRuntime();
- myIsProvided = myIsProvided ||
- scope == GradleDependencyScope.PROVIDED_COMPILE ||
- scope == GradleDependencyScope.PROVIDED_RUNTIME ||
- scope == GradleDependencyScope.PROVIDED;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/StubIdeaModule.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/StubIdeaModule.java
deleted file mode 100644
index 0e8d2bc..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/StubIdeaModule.java
+++ /dev/null
@@ -1,81 +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.gradle.model.internal;
-
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.GradleProject;
-import org.gradle.tooling.model.HierarchicalElement;
-import org.gradle.tooling.model.idea.*;
-
-import java.io.Serializable;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/25/13
- */
-public class StubIdeaModule implements IdeaModule, Serializable {
-
- private final String name;
-
- public StubIdeaModule(String name) {
- this.name = name;
- }
-
- @Override
- public DomainObjectSet<? extends IdeaContentRoot> getContentRoots() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public GradleProject getGradleProject() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public IdeaProject getParent() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DomainObjectSet<? extends HierarchicalElement> getChildren() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public IdeaProject getProject() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public IdeaCompilerOutput getCompilerOutput() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public DomainObjectSet<? extends IdeaDependency> getDependencies() {
- throw new UnsupportedOperationException();
- }
-
- @Override
- public String getName() {
- return name;
- }
-
- @Override
- public String getDescription() {
- throw new UnsupportedOperationException();
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/WarModelImpl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/WarModelImpl.java
deleted file mode 100644
index 6ebe710..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/WarModelImpl.java
+++ /dev/null
@@ -1,86 +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.gradle.model.internal;
-
-import org.jetbrains.plugins.gradle.model.WarModel;
-
-import java.io.File;
-import java.util.Map;
-import java.util.Set;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/5/13
- */
-public class WarModelImpl implements WarModel {
- private final String myWebAppDirName;
- private final File myWebAppDir;
- private File myWebXml;
- private Map<String, Set<String>> myWebRoots;
- private Set<File> myClasspath;
- private String myManifestContent;
-
- public WarModelImpl(String webAppDirName, File webAppDir) {
- myWebAppDirName = webAppDirName;
- myWebAppDir = webAppDir;
- }
-
- @Override
- public String getWebAppDirName() {
- return myWebAppDirName;
- }
-
- @Override
- public File getWebAppDir() {
- return myWebAppDir;
- }
-
- public void setWebXml(File webXml) {
- myWebXml = webXml;
- }
-
- @Override
- public File getWebXml() {
- return myWebXml;
- }
-
- @Override
- public Map<String, Set<String>> getWebRoots() {
- return myWebRoots;
- }
-
- public void setWebRoots(Map<String, Set<String>> webRoots) {
- myWebRoots = webRoots;
- }
-
- public void setClasspath(Set<File> classpath) {
- myClasspath = classpath;
- }
-
- @Override
- public Set<File> getClasspath() {
- return myClasspath;
- }
-
- public void setManifestContent(String manifestContent) {
- myManifestContent = manifestContent;
- }
-
- @Override
- public String getManifestContent() {
- return myManifestContent;
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle
deleted file mode 100644
index 4f382fd..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/init.gradle
+++ /dev/null
@@ -1,46 +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.
- */
-import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
-
-@SuppressWarnings("GrPackage")
-class JetGradlePlugin implements Plugin<Project> {
- private final ToolingModelBuilderRegistry registry
-
- @javax.inject.Inject
- public JetGradlePlugin(ToolingModelBuilderRegistry registry) {
- this.registry = registry
- }
-
- public void apply(Project project) {
- registry.register(project.jetExtraModelBuilderClass.newInstance())
- }
-}
-
-try {
- URL[] urls = [new File("${JAR_PATH}").toURI().toURL()]
- URLClassLoader classLoader = new URLClassLoader(urls, getClass().classLoader)
- Class modelClass = classLoader.loadClass('org.jetbrains.plugins.gradle.model.internal.ExtraModelBuilder')
- allprojects {
- apply plugin: 'idea'
- idea.module.ext.set('resourceDirs', [])
- idea.module.ext.set('testResourceDirs', [])
-
- ext.jetExtraModelBuilderClass = modelClass
- apply plugin: JetGradlePlugin
- }
-}
-catch (all) {
-}
\ No newline at end of file
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java
index 95fdb0a..07521be 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/GradleInstallationManager.java
@@ -14,7 +14,6 @@
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.gradle.StartParameter;
-import org.gradle.api.tasks.wrapper.Wrapper;
import org.gradle.util.DistributionLocator;
import org.gradle.util.GradleVersion;
import org.gradle.wrapper.PathAssembler;
@@ -420,6 +419,15 @@
return result;
}
+ File src = new File(gradleHome, "src");
+ if (src.isDirectory()) {
+ if(new File(src, "org").isDirectory()) {
+ addRoots(result, src);
+ } else {
+ addRoots(result, src.listFiles());
+ }
+ }
+
final Collection<File> libraries = getAllLibraries(gradleHome);
if (libraries == null) {
return result;
@@ -431,15 +439,6 @@
}
}
- File src = new File(gradleHome, "src");
- if (src.isDirectory()) {
- if(new File(src, "org").isDirectory()) {
- addRoots(result, src);
- } else {
- addRoots(result, src.listFiles());
- }
- }
-
return result;
}
@@ -455,7 +454,7 @@
if (files == null) return;
for (File file : files) {
if (file == null || !file.isDirectory()) continue;
- result.add(0, file);
+ result.add(file);
}
}
@@ -465,7 +464,7 @@
}
File gradleSystemDir;
- if (Wrapper.PathBase.PROJECT.name().equals(wrapperConfiguration.getDistributionBase())) {
+ if ("PROJECT".equals(wrapperConfiguration.getDistributionBase())) {
gradleSystemDir = new File(linkedProjectPath, ".gradle");
}
else {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectImportErrorHandler.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectImportErrorHandler.java
index 35bfdeb..3281724 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectImportErrorHandler.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectImportErrorHandler.java
@@ -15,10 +15,9 @@
*/
package org.jetbrains.plugins.gradle.service.project;
-import com.google.common.base.Splitter;
-import com.google.common.base.Strings;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
import org.gradle.api.internal.LocationAwareException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -81,8 +80,8 @@
String location = error.getMessage();
if (location != null && location.startsWith("Build file '")) {
// Only the first line contains the location of the error. Discard the rest.
- Iterable<String> lines = Splitter.on('\n').split(location);
- return lines.iterator().next();
+ String[] lines = StringUtil.splitByLines(location);
+ return lines.length > 0 ? lines[0] : null;
}
}
return null;
@@ -96,8 +95,7 @@
newMsg = "Cause: " + newMsg;
}
- if (!Strings.isNullOrEmpty(location)) {
- assert location != null;
+ if (!StringUtil.isEmpty(location)) {
Matcher matcher = ERROR_LOCATION_PATTERN.matcher(location);
if(matcher.find()) {
String href = "error in file: " + matcher.group(1) + " at line: " + matcher.group(2);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
index cde2278..2c51b29 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/AbstractProjectResolverExtension.java
@@ -152,4 +152,8 @@
@Override
public void enhanceLocalProcessing(@NotNull List<URL> urls) {
}
+
+ @Override
+ public void preImportCheck() {
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
index b2eb6a0..d74524b 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseGradleProjectResolverExtension.java
@@ -55,7 +55,6 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.*;
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
-import org.jetbrains.plugins.gradle.model.data.ClasspathEntry;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import org.jetbrains.plugins.gradle.util.GradleUtil;
@@ -156,11 +155,11 @@
public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
BuildScriptClasspathModel buildScriptClasspathModel = resolverCtx.getExtraProject(gradleModule, BuildScriptClasspathModel.class);
if (buildScriptClasspathModel != null) {
- List<ClasspathEntry> classpathEntries =
- ContainerUtil.map(buildScriptClasspathModel.getClasspath(), new Function<ClasspathEntryModel, ClasspathEntry>() {
+ List<BuildScriptClasspathData.ClasspathEntry> classpathEntries =
+ ContainerUtil.map(buildScriptClasspathModel.getClasspath(), new Function<ClasspathEntryModel, BuildScriptClasspathData.ClasspathEntry>() {
@Override
- public ClasspathEntry fun(ClasspathEntryModel model) {
- return new ClasspathEntry(model.getClassesFile(), model.getSourcesFile(), model.getJavadocFile());
+ public BuildScriptClasspathData.ClasspathEntry fun(ClasspathEntryModel model) {
+ return new BuildScriptClasspathData.ClasspathEntry(model.getClassesFile(), model.getSourcesFile(), model.getJavadocFile());
}
});
BuildScriptClasspathData buildScriptClasspathData =
@@ -313,7 +312,16 @@
@Override
public List<KeyValue<String, String>> getExtraJvmArgs() {
if (ExternalSystemApiUtil.isInProcessMode(GradleConstants.SYSTEM_ID)) {
- return HttpConfigurable.getJvmPropertiesList(false, null);
+ final List<KeyValue<String, String>> extraJvmArgs = ContainerUtil.newArrayList();
+ final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance();
+ if (!StringUtil.isEmpty(httpConfigurable.PROXY_EXCEPTIONS)) {
+ List<String> hosts = StringUtil.split(httpConfigurable.PROXY_EXCEPTIONS, ",");
+ if (!hosts.isEmpty()) {
+ extraJvmArgs.add(KeyValue.create("http.nonProxyHosts", StringUtil.join(hosts, StringUtil.TRIMMER, "|")));
+ }
+ }
+ extraJvmArgs.addAll(HttpConfigurable.getJvmPropertiesList(false, null));
+ return extraJvmArgs;
}
return Collections.emptyList();
}
@@ -327,6 +335,10 @@
}
@Override
+ public void preImportCheck() {
+ }
+
+ @Override
public void enhanceRemoteProcessing(@NotNull SimpleJavaParameters parameters) throws ExecutionException {
PathsList classPath = parameters.getClassPath();
@@ -362,6 +374,7 @@
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(JavaModuleType.class));
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(ModuleType.class));
ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(EmptyModuleType.class));
+ ContainerUtilRt.addIfNotNull(additionalEntries, PathUtil.getJarPathForClass(ProjectImportAction.class));
for (String entry : additionalEntries) {
classPath.add(entry);
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseProjectImportErrorHandler.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseProjectImportErrorHandler.java
index aa60940..71f77f5 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseProjectImportErrorHandler.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/BaseProjectImportErrorHandler.java
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.gradle.service.project;
-import com.google.common.base.Strings;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import com.intellij.openapi.util.Pair;
@@ -54,7 +53,7 @@
Throwable rootCause = rootCauseAndLocation.getFirst();
String location = rootCauseAndLocation.getSecond();
- if (location == null && !Strings.isNullOrEmpty(buildFilePath)) {
+ if (location == null && !StringUtil.isEmpty(buildFilePath)) {
location = String.format("Build file: '%1$s'", buildFilePath);
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java
index 39dfe9a..af0a7e3 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleExecutionHelper.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationEvent;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListener;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.*;
import com.intellij.util.containers.ContainerUtil;
@@ -34,6 +35,7 @@
import org.gradle.tooling.model.build.BuildEnvironment;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ProjectImportAction;
import org.jetbrains.plugins.gradle.settings.DistributionType;
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
@@ -44,9 +46,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
-import java.util.Collection;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.TimeUnit;
/**
@@ -66,7 +66,7 @@
@NotNull ExternalSystemTaskNotificationListener listener,
@NotNull List<String> extraJvmArgs) {
ModelBuilder<T> result = connection.model(modelType);
- prepare(result, id, settings, listener, extraJvmArgs, connection);
+ prepare(result, id, settings, listener, extraJvmArgs, ContainerUtil.<String>newArrayList(), connection);
return result;
}
@@ -76,9 +76,10 @@
@NotNull ProjectConnection connection,
@Nullable GradleExecutionSettings settings,
@NotNull ExternalSystemTaskNotificationListener listener,
- @NotNull final List<String> vmOptions) {
+ @NotNull final List<String> vmOptions,
+ @NotNull final List<String> commandLineArgs) {
BuildLauncher result = connection.newBuild();
- prepare(result, id, settings, listener, vmOptions, connection);
+ prepare(result, id, settings, listener, vmOptions, commandLineArgs, connection);
return result;
}
@@ -88,8 +89,9 @@
@Nullable GradleExecutionSettings settings,
@NotNull final ExternalSystemTaskNotificationListener listener,
@NotNull List<String> extraJvmArgs,
+ @NotNull List<String> commandLineArgs,
@NotNull ProjectConnection connection) {
- prepare(operation, id, settings, listener, extraJvmArgs, connection,
+ prepare(operation, id, settings, listener, extraJvmArgs, commandLineArgs, connection,
new OutputWrapper(listener, id, true), new OutputWrapper(listener, id, false));
}
@@ -100,6 +102,7 @@
@Nullable GradleExecutionSettings settings,
@NotNull final ExternalSystemTaskNotificationListener listener,
@NotNull List<String> extraJvmArgs,
+ @NotNull List<String> commandLineArgs,
@NotNull ProjectConnection connection,
@NotNull final OutputStream standardOutput,
@NotNull final OutputStream standardError) {
@@ -138,6 +141,22 @@
operation.setJvmArguments(ArrayUtil.toStringArray(filteredArgs));
}
+ if(settings.isOfflineWork()) {
+ commandLineArgs.add(GradleConstants.OFFLINE_MODE_CMD_OPTION);
+ }
+
+ if (!commandLineArgs.isEmpty()) {
+ LOG.info("Passing command-line args to Gradle Tooling API: " + commandLineArgs);
+ // filter nulls and empty strings
+ List<String> filteredArgs = ContainerUtil.mapNotNull(commandLineArgs, new Function<String, String>() {
+ @Override
+ public String fun(String s) {
+ return StringUtil.isEmpty(s) ? null : s;
+ }
+ });
+ operation.withArguments(ArrayUtil.toStringArray(filteredArgs));
+ }
+
listener.onStart(id);
final String javaHome = settings.getJavaHome();
if (javaHome != null && new File(javaHome).isDirectory()) {
@@ -182,7 +201,9 @@
return f.fun(connection);
}
catch (Throwable e) {
- throw new ExternalSystemException(ExceptionUtil.getMessage(e));
+ LOG.debug("Gradle execution error", e);
+ Throwable rootCause = ExceptionUtil.getRootCause(e);
+ throw new ExternalSystemException(ExceptionUtil.getMessage(rootCause));
}
finally {
try {
@@ -212,7 +233,6 @@
ProjectConnection connection = getConnection(projectPath, settings);
try {
- BuildLauncher launcher = getBuildLauncher(id, connection, settings, listener, ContainerUtil.<String>newArrayList());
try {
final File tempFile = FileUtil.createTempFile("wrap", ".gradle");
tempFile.deleteOnExit();
@@ -228,18 +248,20 @@
"}}",
};
FileUtil.writeToFile(tempFile, StringUtil.join(lines, SystemProperties.getLineSeparator()));
- launcher.withArguments("--init-script", tempFile.getAbsolutePath());
+
+ BuildLauncher launcher = getBuildLauncher(id, connection, settings, listener, ContainerUtil.<String>newArrayList(),
+ ContainerUtil.newArrayList(GradleConstants.INIT_SCRIPT_CMD_OPTION, tempFile.getAbsolutePath()));
launcher.forTasks("wrapper");
launcher.run();
String wrapperPropertyFile = FileUtil.loadFile(wrapperPropertyFileLocation);
settings.setWrapperPropertyFile(wrapperPropertyFile);
}
catch (IOException e) {
- throw new ExternalSystemException(e);
+ LOG.warn("Can't update wrapper", e);
}
}
catch (Throwable e) {
- throw new ExternalSystemException(e);
+ LOG.warn("Can't update wrapper", e);
}
finally {
try {
@@ -354,48 +376,49 @@
field.setAccessible(isAccessible);
}
- @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
- public static boolean setInitScript(@NotNull LongRunningOperation longRunningOperation, boolean isBuildSrcProject) {
+ @Nullable
+ public static File generateInitScript(boolean isBuildSrcProject) {
+ InputStream stream = ProjectImportAction.class.getResourceAsStream("/org/jetbrains/plugins/gradle/tooling/internal/init.gradle");
try {
- InputStream stream = GradleProjectResolver.class.getResourceAsStream("/org/jetbrains/plugins/gradle/model/internal/init.gradle");
- if (stream == null) return isBuildSrcProject;
-
- String jarPath = PathUtil.getCanonicalPath(PathUtil.getJarPathForClass(GradleProjectResolver.class));
- String s = FileUtil.loadTextAndClose(stream).replace("${JAR_PATH}", jarPath);
-
- if(isBuildSrcProject) {
+ if (stream == null) {
+ LOG.warn("Can't get init script template");
+ return null;
+ }
+ String s = FileUtil.loadTextAndClose(stream).replace("${EXTENSIONS_JARS_PATH}", getToolingExtensionsJarPaths());
+ if (isBuildSrcProject) {
String buildSrcDefaultInitScript = getBuildSrcDefaultInitScript();
- if(buildSrcDefaultInitScript == null) return false;
+ if (buildSrcDefaultInitScript == null) return null;
s += buildSrcDefaultInitScript;
}
final File tempFile = FileUtil.createTempFile("ijinit", '.' + GradleConstants.EXTENSION, true);
FileUtil.writeToFile(tempFile, s);
-
- String[] buildExecutorArgs = new String[]{"--init-script", tempFile.getAbsolutePath()};
- longRunningOperation.withArguments(buildExecutorArgs);
-
- return true;
+ return tempFile;
}
catch (Exception e) {
- LOG.warn("Can't use IJ gradle init script", e);
- return false;
+ LOG.warn("Can't generate IJ gradle init script", e);
+ return null;
+ }
+ finally {
+ StreamUtil.closeStream(stream);
}
}
@Nullable
- @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
public static String getBuildSrcDefaultInitScript() {
+ InputStream stream =
+ ProjectImportAction.class.getResourceAsStream("/org/jetbrains/plugins/gradle/tooling/internal/buildSrcInit.gradle");
try {
- InputStream stream = GradleProjectResolver.class.getResourceAsStream("/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle");
if (stream == null) return null;
-
return FileUtil.loadTextAndClose(stream);
}
catch (Exception e) {
LOG.warn("Can't use IJ gradle init script", e);
return null;
}
+ finally {
+ StreamUtil.closeStream(stream);
+ }
}
@Nullable
@@ -408,4 +431,31 @@
return null;
}
}
+
+ @NotNull
+ private static String getToolingExtensionsJarPaths() throws ClassNotFoundException {
+ final ArrayList<Class<?>> list = ContainerUtil.newArrayList(
+ // add gradle-tooling-extension jar
+ Class.forName("org.jetbrains.plugins.gradle.model.ProjectImportAction"),
+ // add gradle-tooling-extension-v1.9 jar
+ Class.forName("org.jetbrains.plugins.gradle.tooling.v1_9.builder.ModelBuildScriptClasspathBuilderImpl"),
+ // add gradle-tooling-extension-v1.11 jar
+ Class.forName("org.jetbrains.plugins.gradle.tooling.v1_11.builder.ModelBuildScriptClasspathBuilderImpl"),
+ // add gradle-tooling-extension-v1.12 jar
+ Class.forName("org.jetbrains.plugins.gradle.tooling.v1_12.builder.ModelBuildScriptClasspathBuilderImpl")
+ );
+
+ StringBuilder buf = new StringBuilder();
+ buf.append('[');
+ for (Iterator<Class<?>> it = list.iterator(); it.hasNext(); ) {
+ Class<?> aClass = it.next();
+ String jarPath = PathUtil.getCanonicalPath(PathUtil.getJarPathForClass(aClass));
+ buf.append('\"').append(jarPath).append('\"');
+ if (it.hasNext()) {
+ buf.append(',');
+ }
+ }
+ buf.append(']');
+ return buf.toString();
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleNotification.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleNotification.java
index 32f37d1..ce251bc 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleNotification.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleNotification.java
@@ -15,7 +15,6 @@
*/
package org.jetbrains.plugins.gradle.service.project;
-import com.intellij.notification.Notification;
import com.intellij.notification.NotificationGroup;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
@@ -32,7 +31,6 @@
public class GradleNotification {
private static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.balloonGroup("Gradle Notification Group");
- @Nullable private Notification myNotification;
@NotNull private final Project myProject;
@NotNull
@@ -48,22 +46,12 @@
@NotNull final String message,
@NotNull final NotificationType type,
@Nullable final NotificationListener listener) {
- Runnable notificationTask = new Runnable() {
+ AppUIUtil.invokeLaterIfProjectAlive(myProject, new Runnable() {
@Override
public void run() {
- if (!myProject.isDisposed() && myProject.isOpen()) {
- Notification notification = NOTIFICATION_GROUP.createNotification(title, message, type, listener);
- Notification old = myNotification;
- if (old != null && old.getContent().equals(notification.getContent())) {
- old.expire();
- }
- myNotification = notification;
- notification.notify(myProject);
- }
+ NOTIFICATION_GROUP.createNotification(title, message, type, listener).notify(myProject);
}
- };
-
- AppUIUtil.invokeLaterIfProjectAlive(myProject, notificationTask);
+ });
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
index 29a27ba..ffc0b74 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.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.
@@ -47,6 +47,7 @@
import org.gradle.tooling.model.idea.IdeaProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ProjectImportAction;
import org.jetbrains.plugins.gradle.remote.impl.GradleLibraryNamesMixer;
import org.jetbrains.plugins.gradle.settings.ClassHolder;
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
@@ -141,32 +142,41 @@
final ProjectImportAction projectImportAction = new ProjectImportAction(resolverCtx.isPreviewMode());
- // inject ProjectResolverContext into gradle project resolver extensions
- // collect extra JVM arguments provided by gradle project resolver extensions
- // and register classes of extra gradle project models required for extensions (e.g. com.android.builder.model.AndroidProject)
final List<KeyValue<String, String>> extraJvmArgs = new ArrayList<KeyValue<String, String>>();
for (GradleProjectResolverExtension resolverExtension = projectResolverChain;
resolverExtension != null;
resolverExtension = resolverExtension.getNext()) {
+ // inject ProjectResolverContext into gradle project resolver extensions
resolverExtension.setProjectResolverContext(resolverCtx);
+ // pre-import checks
+ resolverExtension.preImportCheck();
+ // register classes of extra gradle project models required for extensions (e.g. com.android.builder.model.AndroidProject)
projectImportAction.addExtraProjectModelClasses(resolverExtension.getExtraProjectModelClasses());
+ // collect extra JVM arguments provided by gradle project resolver extensions
extraJvmArgs.addAll(resolverExtension.getExtraJvmArgs());
}
+
final ParametersList parametersList = new ParametersList();
for (KeyValue<String, String> jvmArg : extraJvmArgs) {
parametersList.addProperty(jvmArg.getKey(), jvmArg.getValue());
}
+
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = resolverCtx.getConnection().action(projectImportAction);
+
+ final List<String> commandLineArgs = ContainerUtil.newArrayList();
+ // TODO [vlad] remove the check
+ if (!GradleEnvironment.DISABLE_ENHANCED_TOOLING_API) {
+ File initScript = GradleExecutionHelper.generateInitScript(isBuildSrcProject);
+ if (initScript != null) {
+ ContainerUtil.addAll(commandLineArgs, GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
+ }
+ }
+
GradleExecutionHelper.prepare(
buildActionExecutor, resolverCtx.getExternalSystemTaskId(),
resolverCtx.getSettings(), resolverCtx.getListener(),
- parametersList.getParameters(), resolverCtx.getConnection());
-
- // TODO [vlad] remove the check
- if (!GradleEnvironment.DISABLE_ENHANCED_TOOLING_API) {
- GradleExecutionHelper.setInitScript(buildActionExecutor, isBuildSrcProject);
- }
+ parametersList.getParameters(), commandLineArgs, resolverCtx.getConnection());
ProjectImportAction.AllModels allModels;
try {
@@ -178,8 +188,9 @@
catch (UnsupportedVersionException unsupportedVersionException) {
// Old gradle distribution version used (before ver. 1.8)
// fallback to use ModelBuilder gradle tooling API
+ Class<? extends IdeaProject> aClass = resolverCtx.isPreviewMode() ? BasicIdeaProject.class : IdeaProject.class;
ModelBuilder<? extends IdeaProject> modelBuilder = myHelper.getModelBuilder(
- resolverCtx.isPreviewMode() ? BasicIdeaProject.class : IdeaProject.class,
+ aClass,
resolverCtx.getExternalSystemTaskId(),
resolverCtx.getSettings(),
resolverCtx.getConnection(),
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
index b663dbc..1b0af68 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolverExtension.java
@@ -26,12 +26,10 @@
import com.intellij.openapi.externalSystem.service.ParametersEnhancer;
import com.intellij.openapi.util.KeyValue;
import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaProject;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.GradleManager;
-import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@@ -67,7 +65,7 @@
ModuleData createModule(@NotNull IdeaModule gradleModule, @NotNull ProjectData projectData);
/**
- * Populates extra models of the given ide module on the basis of the information provided by {@link org.jetbrains.plugins.gradle.model.ModelBuilderService}
+ * Populates extra models of the given ide module on the basis of the information provided by {@link org.jetbrains.plugins.gradle.tooling.ModelBuilderService}
*
* @param ideModule corresponding module from intellij gradle plugin domain
*/
@@ -105,4 +103,9 @@
@NotNull
ExternalSystemException getUserFriendlyError(@NotNull Throwable error, @NotNull String projectPath, @Nullable String buildFilePath);
+
+ /**
+ * Performs project configuration and other checks before the actual project import (before invocation of gradle tooling API).
+ */
+ void preImportCheck();
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
index fc4805e..81ceaa3 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleStartupActivity.java
@@ -64,7 +64,8 @@
private static void showNotificationForUnlinkedGradleProject(@NotNull final Project project) {
if (!PropertiesComponent.getInstance(project).getBoolean(SHOW_UNLINKED_GRADLE_POPUP, true)
|| !GradleSettings.getInstance(project).getLinkedProjectsSettings().isEmpty()
- || project.getUserData(ExternalSystemDataKeys.NEWLY_IMPORTED_PROJECT) == Boolean.TRUE) {
+ || project.getUserData(ExternalSystemDataKeys.NEWLY_IMPORTED_PROJECT) == Boolean.TRUE
+ || project.getBaseDir() == null) {
return;
}
@@ -79,13 +80,14 @@
if (files != null && files.length != 0) {
String message = String.format("%s<br>\n%s",
GradleBundle.message("gradle.notifications.unlinked.project.found.msg", IMPORT_EVENT_DESCRIPTION),
- GradleBundle.message("gradle.notifications.do.not.show", DO_NOT_SHOW_EVENT_DESCRIPTION));
+ GradleBundle.message("gradle.notifications.do.not.show"));
GradleNotification.getInstance(project).showBalloon(
GradleBundle.message("gradle.notifications.unlinked.project.found.title"),
message, NotificationType.INFORMATION, new NotificationListener.Adapter() {
@Override
protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
+ notification.expire();
if (IMPORT_EVENT_DESCRIPTION.equals(e.getDescription())) {
final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class);
GradleProjectImportBuilder gradleProjectImportBuilder = new GradleProjectImportBuilder(projectDataManager);
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java
deleted file mode 100644
index 2d201e5..0000000
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectImportAction.java
+++ /dev/null
@@ -1,152 +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.gradle.service.project;
-
-import com.intellij.openapi.externalSystem.model.ExternalSystemException;
-import org.gradle.tooling.BuildAction;
-import org.gradle.tooling.BuildController;
-import org.gradle.tooling.model.build.BuildEnvironment;
-import org.gradle.tooling.model.idea.BasicIdeaProject;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaProject;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.Serializable;
-import java.util.*;
-
-/**
- * @author Vladislav.Soroka
- * @since 10/14/13
- */
-public class ProjectImportAction implements BuildAction<ProjectImportAction.AllModels>, Serializable {
-
- private final Set<Class> myExtraProjectModelClasses = new HashSet<Class>();
- private final boolean myIsPreviewMode;
-
- public ProjectImportAction(boolean isPreviewMode) {
- myIsPreviewMode = isPreviewMode;
- }
-
- public void addExtraProjectModelClasses(@NotNull Set<Class> projectModelClasses) {
- myExtraProjectModelClasses.addAll(projectModelClasses);
- }
-
- @Nullable
- @Override
- public AllModels execute(final BuildController controller) {
- final IdeaProject ideaProject = controller.getModel(myIsPreviewMode ? BasicIdeaProject.class : IdeaProject.class);
- if (ideaProject == null || ideaProject.getModules().isEmpty()) {
- return null;
- }
-
- AllModels allModels = new AllModels(ideaProject);
-
- // TODO ask gradle guys why there is always null got for BuildEnvironment model
- //allModels.setBuildEnvironment(controller.findModel(BuildEnvironment.class));
-
- for (IdeaModule module : ideaProject.getModules()) {
- for (Class aClass : myExtraProjectModelClasses) {
- try {
- Object extraProject = controller.findModel(module, aClass);
- if (extraProject == null) continue;
- allModels.addExtraProject(extraProject, aClass, module);
- }
- catch (Exception e) {
- // do not fail project import in a preview mode
- if (!myIsPreviewMode) {
- throw new ExternalSystemException(e);
- }
- }
- }
- }
-
- return allModels;
- }
-
- public static class AllModels implements Serializable {
- @NotNull private final Map<String, Object> projectsByPath = new HashMap<String, Object>();
- @NotNull private final IdeaProject myIdeaProject;
- @Nullable private BuildEnvironment myBuildEnvironment;
-
- public AllModels(@NotNull IdeaProject project) {
- myIdeaProject = project;
- }
-
- @NotNull
- public IdeaProject getIdeaProject() {
- return myIdeaProject;
- }
-
- @Nullable
- public BuildEnvironment getBuildEnvironment() {
- return myBuildEnvironment;
- }
-
- public void setBuildEnvironment(@Nullable BuildEnvironment buildEnvironment) {
- myBuildEnvironment = buildEnvironment;
- }
-
-
- @Nullable
- public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) {
- Object extraProject = projectsByPath.get(extractMapKey(modelClazz, module));
- if (modelClazz.isInstance(extraProject)) {
- //noinspection unchecked
- return (T)extraProject;
- }
- return null;
- }
-
- /**
- * Return collection path of modules provides the model
- * @param modelClazz extra project model
- * @return modules path collection
- */
- @NotNull
- public Collection<String> findModulesWithModel(@NotNull Class modelClazz) {
- List<String> modules = new ArrayList<String>();
- for (Map.Entry<String, Object> set : projectsByPath.entrySet()) {
- if (modelClazz.isInstance(set.getValue())) {
- modules.add(extractModulePath(modelClazz, set.getKey()));
- }
- }
- return modules;
- }
-
- public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @NotNull IdeaModule module) {
- projectsByPath.put(extractMapKey(modelClazz, module), project);
- }
-
- @NotNull
- private static String extractMapKey(Class modelClazz, @NotNull IdeaModule module) {
- return modelClazz.getName() + '@' + module.getGradleProject().getPath();
- }
-
- @NotNull
- private static String extractModulePath(Class modelClazz, String key) {
- return key.replaceFirst(modelClazz.getName() + '@', "");
- }
-
- @Override
- public String toString() {
- return "AllModels{" +
- "projectsByPath=" + projectsByPath +
- ", myIdeaProject=" + myIdeaProject +
- '}';
- }
- }
-}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
index 0f9bc39..b7f94dd 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/ProjectResolverContext.java
@@ -21,6 +21,7 @@
import org.gradle.tooling.model.idea.IdeaModule;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ProjectImportAction;
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
import java.util.Collection;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java
index 907f290..928a8f9 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/BuildClasspathModuleGradleDataService.java
@@ -37,7 +37,6 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData;
-import org.jetbrains.plugins.gradle.model.data.ClasspathEntry;
import org.jetbrains.plugins.gradle.service.GradleBuildClasspathManager;
import org.jetbrains.plugins.gradle.service.GradleInstallationManager;
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings;
@@ -88,7 +87,7 @@
GradleProjectSettings settings = GradleSettings.getInstance(project).getLinkedProjectSettings(externalProjectPath);
if (settings == null || settings.getDistributionType() == null) return null;
- final Set<String> gradleSdkLibraries = ContainerUtil.newHashSet();
+ final Set<String> gradleSdkLibraries = ContainerUtil.newLinkedHashSet();
File gradleHome =
gradleInstallationManager.getGradleHome(settings.getDistributionType(), externalProjectPath, settings.getGradleHome());
if (gradleHome != null && gradleHome.isDirectory()) {
@@ -119,15 +118,13 @@
GradleProjectSettings settings = GradleSettings.getInstance(project).getLinkedProjectSettings(linkedExternalProjectPath);
if (settings == null || settings.getDistributionType() == null) continue;
- final Set<String> buildClasspath = ContainerUtil.newHashSet();
+ final Set<String> buildClasspath = ContainerUtil.newLinkedHashSet();
BuildScriptClasspathData buildScriptClasspathData = node.getData();
- for (ClasspathEntry classpathEntry : buildScriptClasspathData.getClasspathEntries()) {
+ for (BuildScriptClasspathData.ClasspathEntry classpathEntry : buildScriptClasspathData.getClasspathEntries()) {
if (classpathEntry.getSourcesFile() != null) {
buildClasspath.add(FileUtil.toCanonicalPath(classpathEntry.getSourcesFile().getPath()));
}
- else {
- buildClasspath.add(FileUtil.toCanonicalPath(classpathEntry.getClassesFile().getPath()));
- }
+ buildClasspath.add(FileUtil.toCanonicalPath(classpathEntry.getClassesFile().getPath()));
}
ExternalProjectBuildClasspathPojo projectBuildClasspathPojo =
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java
index 36922d3..4f19cb7 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/wizard/GradleModuleBuilder.java
@@ -15,19 +15,35 @@
*/
package org.jetbrains.plugins.gradle.service.project.wizard;
+import com.intellij.ide.fileTemplates.FileTemplate;
+import com.intellij.ide.fileTemplates.FileTemplateManager;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.WizardContext;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.service.project.wizard.AbstractExternalModuleBuilder;
import com.intellij.openapi.externalSystem.service.project.wizard.ExternalModuleSettingsStep;
-import com.intellij.openapi.module.JavaModuleType;
-import com.intellij.openapi.module.ModuleType;
-import com.intellij.openapi.module.StdModuleTypes;
+import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
+import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
+import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
+import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
+import com.intellij.openapi.module.*;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.SdkTypeId;
+import com.intellij.openapi.roots.ContentEntry;
+import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.service.settings.GradleProjectSettingsControl;
@@ -36,6 +52,8 @@
import org.jetbrains.plugins.gradle.util.GradleConstants;
import java.io.File;
+import java.io.IOException;
+import java.util.Map;
/**
* @author Denis Zhdanov
@@ -43,35 +61,70 @@
*/
public class GradleModuleBuilder extends AbstractExternalModuleBuilder<GradleProjectSettings> {
+ private static final Logger LOG = Logger.getInstance(GradleModuleBuilder.class);
+
+ private static final String TEMPLATE_GRADLE_SETTINGS = "Gradle Settings.gradle";
+ private static final String TEMPLATE_GRADLE_SETTINGS_MERGE = "Gradle Settings merge.gradle";
+ private static final String TEMPLATE_GRADLE_BUILD_WITH_WRAPPER = "Gradle Build Script with wrapper.gradle";
+ private static final String DEFAULT_TEMPLATE_GRADLE_BUILD = "Gradle Build Script.gradle";
+
+ private static final String TEMPLATE_ATTRIBUTE_PROJECT_NAME = "PROJECT_NAME";
+ private static final String TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME = "MODULE_DIR_NAME";
+ private static final String TEMPLATE_ATTRIBUTE_MODULE_NAME = "MODULE_NAME";
+
+ private @NotNull WizardContext myWizardContext;
+
public GradleModuleBuilder() {
super(GradleConstants.SYSTEM_ID, new GradleProjectSettings());
}
- @Nullable
@Override
- protected VirtualFile getExternalProjectConfigFile(@NotNull VirtualFile contentRootDir) {
- File gradleScript = new File(contentRootDir.getPath(), GradleConstants.DEFAULT_SCRIPT_NAME);
- FileUtilRt.createIfNotExists(gradleScript);
- return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(gradleScript);
- }
+ public void setupRootModel(final ModifiableRootModel modifiableRootModel) throws ConfigurationException {
+ String contentEntryPath = getContentEntryPath();
+ if (StringUtil.isEmpty(contentEntryPath)) {
+ return;
+ }
+ File contentRootDir = new File(contentEntryPath);
+ FileUtilRt.createDirectory(contentRootDir);
+ LocalFileSystem fileSystem = LocalFileSystem.getInstance();
+ VirtualFile modelContentRootDir = fileSystem.refreshAndFindFileByIoFile(contentRootDir);
+ if (modelContentRootDir == null) {
+ return;
+ }
- @Nullable
- @Override
- protected String getTemplateConfigName(@NotNull GradleProjectSettings settings) {
- final String templateName;
- if (settings.getDistributionType() == DistributionType.WRAPPED) {
- templateName = "Gradle Build Script with wrapper.gradle";
+ modifiableRootModel.addContentEntry(modelContentRootDir);
+ modifiableRootModel.inheritSdk();
+
+ final Project project = modifiableRootModel.getProject();
+
+ setupGradleBuildFile(modelContentRootDir);
+ setupGradleSettingsFile(modelContentRootDir, modifiableRootModel);
+
+ if (myWizardContext.isCreatingNewProject()) {
+ String externalProjectPath = FileUtil.toCanonicalPath(project.getBasePath());
+ getExternalProjectSettings().setExternalProjectPath(externalProjectPath);
+ AbstractExternalSystemSettings settings = ExternalSystemApiUtil.getSettings(project, GradleConstants.SYSTEM_ID);
+ //noinspection unchecked
+ settings.linkProject(getExternalProjectSettings());
}
else {
- templateName = "Gradle Build Script.gradle";
+ FileDocumentManager.getInstance().saveAllDocuments();
+ ExternalSystemUtil.refreshProjects(project, GradleConstants.SYSTEM_ID, false);
}
- return templateName;
}
@Override
public ModuleWizardStep[] createWizardSteps(@NotNull WizardContext wizardContext, @NotNull ModulesProvider modulesProvider) {
+ myWizardContext = wizardContext;
+ return super.createWizardSteps(wizardContext, modulesProvider);
+ }
+
+ @Nullable
+ @Override
+ public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
+ if (!myWizardContext.isCreatingNewProject()) return null;
final GradleProjectSettingsControl settingsControl = new GradleProjectSettingsControl(getExternalProjectSettings());
- return new ModuleWizardStep[]{new ExternalModuleSettingsStep<GradleProjectSettings>(this, settingsControl)};
+ return new ExternalModuleSettingsStep<GradleProjectSettings>(this, settingsControl);
}
@Override
@@ -80,7 +133,7 @@
}
@Override
- public String getGroupName() {
+ public String getParentGroup() {
return JavaModuleType.JAVA_GROUP;
}
@@ -88,4 +141,111 @@
public ModuleType getModuleType() {
return StdModuleTypes.JAVA;
}
+
+ @Nullable
+ private VirtualFile setupGradleBuildFile(@NotNull VirtualFile modelContentRootDir) throws ConfigurationException {
+ final VirtualFile file = getExternalProjectConfigFile(modelContentRootDir.getPath(), GradleConstants.DEFAULT_SCRIPT_NAME);
+ final String templateName = getExternalProjectSettings().getDistributionType() == DistributionType.WRAPPED
+ ? TEMPLATE_GRADLE_BUILD_WITH_WRAPPER
+ : DEFAULT_TEMPLATE_GRADLE_BUILD;
+
+ Map attributes = ContainerUtil.newHashMap();
+ if (file != null) {
+ saveFile(file, templateName, attributes);
+ }
+ return file;
+ }
+
+ @Nullable
+ private VirtualFile setupGradleSettingsFile(@NotNull VirtualFile modelContentRootDir, @NotNull ModifiableRootModel model)
+ throws ConfigurationException {
+ VirtualFile file = null;
+ if (myWizardContext.isCreatingNewProject()) {
+ final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, model.getProject().getBaseDir(), '/');
+ file = getExternalProjectConfigFile(model.getProject().getBasePath(), GradleConstants.SETTINGS_FILE_NAME);
+ if (file == null) return null;
+
+ Map<String, String> attributes = ContainerUtil.newHashMap();
+ final String projectName = model.getProject().getName();
+ attributes.put(TEMPLATE_ATTRIBUTE_PROJECT_NAME, projectName);
+ attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
+ attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
+ saveFile(file, TEMPLATE_GRADLE_SETTINGS, attributes);
+ }
+ else {
+ Map<String, Module> moduleMap = ContainerUtil.newHashMap();
+ for (Module module : ModuleManager.getInstance(model.getProject()).getModules()) {
+ for (ContentEntry contentEntry : model.getContentEntries()) {
+ if (contentEntry.getFile() != null) {
+ moduleMap.put(contentEntry.getFile().getPath(), module);
+ }
+ }
+ }
+
+ VirtualFile virtualFile = modelContentRootDir;
+ Module module = null;
+ while (virtualFile != null && module == null) {
+ module = moduleMap.get(virtualFile.getPath());
+ virtualFile = virtualFile.getParent();
+ }
+
+ if (module != null) {
+ String rootProjectPath = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
+
+ if (!StringUtil.isEmpty(rootProjectPath)) {
+ VirtualFile rootProjectFile = VfsUtil.findFileByIoFile(new File(rootProjectPath), true);
+ if (rootProjectFile == null) return null;
+
+ final String moduleDirName = VfsUtilCore.getRelativePath(modelContentRootDir, rootProjectFile, '/');
+ file = getExternalProjectConfigFile(rootProjectPath, GradleConstants.SETTINGS_FILE_NAME);
+ if (file == null) return null;
+
+ Map<String, String> attributes = ContainerUtil.newHashMap();
+ attributes.put(TEMPLATE_ATTRIBUTE_MODULE_DIR_NAME, moduleDirName);
+ attributes.put(TEMPLATE_ATTRIBUTE_MODULE_NAME, model.getModule().getName());
+ appendToFile(file, TEMPLATE_GRADLE_SETTINGS_MERGE, attributes);
+ }
+ }
+ }
+ return file;
+ }
+
+ private static void saveFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
+ throws ConfigurationException {
+ FileTemplateManager manager = FileTemplateManager.getInstance();
+ FileTemplate template = manager.getInternalTemplate(templateName);
+ try {
+ VfsUtil.saveText(file, templateAttributes != null ? template.getText(templateAttributes) : template.getText());
+ }
+ catch (IOException e) {
+ LOG.warn(String.format("Unexpected exception on applying template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
+ throw new ConfigurationException(
+ e.getMessage(), String.format("Can't apply %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
+ );
+ }
+ }
+
+ private static void appendToFile(@NotNull VirtualFile file, @NotNull String templateName, @Nullable Map templateAttributes)
+ throws ConfigurationException {
+ FileTemplateManager manager = FileTemplateManager.getInstance();
+ FileTemplate template = manager.getInternalTemplate(templateName);
+ try {
+ VfsUtil.saveText(file, VfsUtilCore.loadText(file) +
+ (templateAttributes != null ? template.getText(templateAttributes) : template.getText()));
+ }
+ catch (IOException e) {
+ LOG.warn(String.format("Unexpected exception on appending template %s config", GradleConstants.SYSTEM_ID.getReadableName()), e);
+ throw new ConfigurationException(
+ e.getMessage(), String.format("Can't append %s template config text", GradleConstants.SYSTEM_ID.getReadableName())
+ );
+ }
+ }
+
+
+ @Nullable
+ private static VirtualFile getExternalProjectConfigFile(@NotNull String parent, @NotNull String fileName) {
+ File file = new File(parent, fileName);
+ FileUtilRt.createIfNotExists(file);
+ return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file);
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
index 535565c..cf7474b 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleResolverUtil.java
@@ -23,10 +23,12 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleLog;
+import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
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.expressions.GrBinaryExpression;
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.impl.GroovyPsiManager;
@@ -244,4 +246,9 @@
}
});
}
+
+ public static boolean isLShiftElement(@Nullable PsiElement psiElement) {
+ return (psiElement instanceof GrBinaryExpression &&
+ GroovyElementTypes.COMPOSITE_LSHIFT_SIGN.equals(GrBinaryExpression.class.cast(psiElement).getOperationTokenType()));
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java
index 908ad38..f0c4e74 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/resolve/GradleTaskContributor.java
@@ -21,15 +21,16 @@
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
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.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrCommandArgumentList;
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.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrShiftExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightParameter;
@@ -49,8 +50,8 @@
if (methodCallInfo.isEmpty()) return;
if (methodCallInfo.size() == 1) {
- if (place.getParent() instanceof GrShiftExpressionImpl) {
- GradleResolverUtil.addImplicitVariable(processor, state, place, CommonClassNames.JAVA_LANG_VOID);
+ if(GradleResolverUtil.isLShiftElement(place.getParent())) {
+ GradleResolverUtil.addImplicitVariable(processor, state, place, GradleCommonClassNames.GRADLE_API_TASK);
}
}
else if (methodCallInfo.size() == 2) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleConfigLocator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleConfigLocator.java
index 60c387d..4455931 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleConfigLocator.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleConfigLocator.java
@@ -2,13 +2,17 @@
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.service.settings.ExternalSystemConfigLocator;
+import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
+import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
import org.gradle.tooling.GradleConnector;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.util.GradleConstants;
import java.io.File;
+import java.util.List;
/**
* We store not gradle config file but its parent dir path instead. That is implied by gradle design
@@ -50,4 +54,22 @@
}
return null;
}
+
+ @NotNull
+ @Override
+ public List<VirtualFile> findAll(@NotNull ExternalProjectSettings externalProjectSettings) {
+ List<VirtualFile> list = ContainerUtil.newArrayList();
+ for (String path : externalProjectSettings.getModules()) {
+ VirtualFile vFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path));
+ if (vFile != null) {
+ for (VirtualFile child : vFile.getChildren()) {
+ String name = child.getName();
+ if (!child.isDirectory() && name.endsWith(GradleConstants.EXTENSION)) {
+ list.add(child);
+ }
+ }
+ }
+ }
+ return list;
+ }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
index ee527f6..ffdf37c 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/GradleSystemSettingsControl.java
@@ -26,6 +26,7 @@
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.intellij.ui.components.JBTextField;
import org.jetbrains.annotations.NotNull;
@@ -56,6 +57,7 @@
private JBLabel myGradleVmOptionsLabel;
private JBTextField myGradleVmOptionsField;
private boolean myServiceDirectoryPathModifiedByUser;
+ private JBCheckBox myOfflineModeBox;
public GradleSystemSettingsControl(@NotNull GradleSettings settings) {
myInitialSettings = settings;
@@ -63,6 +65,9 @@
@Override
public void fillUi(@NotNull PaintAwarePanel canvas, int indentLevel) {
+ myOfflineModeBox = new JBCheckBox(GradleBundle.message("gradle.settings.text.offline_work"));
+ canvas.add(myOfflineModeBox, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
+
myServiceDirectoryLabel = new JBLabel(GradleBundle.message("gradle.settings.text.service.dir.path"));
preparePathControl();
canvas.add(myServiceDirectoryLabel, ExternalSystemUiUtil.getLabelConstraints(indentLevel));
@@ -119,6 +124,7 @@
}
myGradleVmOptionsField.setText(trimIfPossible(myInitialSettings.getGradleVmOptions()));
+ myOfflineModeBox.setSelected(myInitialSettings.isOfflineWork());
}
private void deduceServiceDirectoryIfPossible() {
@@ -136,7 +142,8 @@
return (myServiceDirectoryPathModifiedByUser
&& !Comparing.equal(ExternalSystemApiUtil.normalizePath(myServiceDirectoryPathField.getText()),
ExternalSystemApiUtil.normalizePath(myInitialSettings.getServiceDirectoryPath())))
- || !Comparing.equal(trimIfPossible(myGradleVmOptionsField.getText()), trimIfPossible(myInitialSettings.getGradleVmOptions()));
+ || !Comparing.equal(trimIfPossible(myGradleVmOptionsField.getText()), trimIfPossible(myInitialSettings.getGradleVmOptions()))
+ || myOfflineModeBox.isSelected() != myInitialSettings.isOfflineWork();
}
@Nullable
@@ -154,6 +161,7 @@
settings.setServiceDirectoryPath(ExternalSystemApiUtil.normalizePath(myServiceDirectoryPathField.getText()));
}
settings.setGradleVmOptions(trimIfPossible(myGradleVmOptionsField.getText()));
+ settings.setOfflineWork(myOfflineModeBox.isSelected());
}
@Override
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java
index 5d54bee..e309bd8 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/settings/ImportFromGradleControl.java
@@ -35,7 +35,7 @@
extends AbstractImportFromExternalSystemControl<GradleProjectSettings, GradleSettingsListener, GradleSettings>
{
public ImportFromGradleControl() {
- super(GradleConstants.SYSTEM_ID, new GradleSettings(ProjectManager.getInstance().getDefaultProject()), getInitialProjectSettings());
+ super(GradleConstants.SYSTEM_ID, new GradleSettings(ProjectManager.getInstance().getDefaultProject()), getInitialProjectSettings(), true);
}
@NotNull
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
index 67cb359..f0fc48b 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
@@ -27,6 +27,7 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.SystemProperties;
+import com.intellij.util.containers.ContainerUtil;
import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.ProjectConnection;
import org.jetbrains.annotations.NotNull;
@@ -89,7 +90,6 @@
Function<ProjectConnection, Void> f = new Function<ProjectConnection, Void>() {
@Override
public Void fun(ProjectConnection connection) {
- BuildLauncher launcher = myHelper.getBuildLauncher(id, connection, settings, listener, vmOptions);
if (!StringUtil.isEmpty(debuggerSetup)) {
try {
final File tempFile = FileUtil.createTempFile("init", ".gradle");
@@ -102,17 +102,14 @@
};
FileUtil.writeToFile(tempFile, StringUtil.join(lines, SystemProperties.getLineSeparator()));
- scriptParameters.add("--init-script");
- scriptParameters.add(tempFile.getAbsolutePath());
+ ContainerUtil.addAll(scriptParameters, GradleConstants.INIT_SCRIPT_CMD_OPTION, tempFile.getAbsolutePath());
}
catch (IOException e) {
throw new ExternalSystemException(e);
}
}
- if (!scriptParameters.isEmpty()) {
- launcher.withArguments(ArrayUtil.toStringArray(scriptParameters));
- }
+ BuildLauncher launcher = myHelper.getBuildLauncher(id, connection, settings, listener, vmOptions, scriptParameters);
launcher.forTasks(ArrayUtil.toStringArray(taskNames));
launcher.run();
return null;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java
index badb42d..3f08b97 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleExecutionSettings.java
@@ -37,11 +37,12 @@
@NotNull private final List<ClassHolder<? extends GradleProjectResolverExtension>> myResolverExtensions = ContainerUtilRt.newArrayList();
@Nullable private final String myGradleHome;
+
@Nullable private final String myServiceDirectory;
-
@Nullable private final String myDaemonVmOptions;
+ private final boolean myIsOfflineWork;
- @NotNull final DistributionType myDistributionType;
+ @NotNull private final DistributionType myDistributionType;
@Nullable private String wrapperPropertyFile;
@Nullable private String myJavaHome;
@@ -49,12 +50,14 @@
public GradleExecutionSettings(@Nullable String gradleHome,
@Nullable String serviceDirectory,
@NotNull DistributionType distributionType,
- @Nullable String daemonVmOptions)
+ @Nullable String daemonVmOptions,
+ boolean isOfflineWork)
{
myGradleHome = gradleHome;
myServiceDirectory = serviceDirectory;
myDistributionType = distributionType;
myDaemonVmOptions = daemonVmOptions;
+ myIsOfflineWork = isOfflineWork;
setVerboseProcessing(USE_VERBOSE_GRADLE_API_BY_DEFAULT);
}
@@ -77,6 +80,10 @@
myJavaHome = javaHome;
}
+ public boolean isOfflineWork() {
+ return myIsOfflineWork;
+ }
+
@NotNull
public List<ClassHolder<? extends GradleProjectResolverExtension>> getResolverExtensions() {
return myResolverExtensions;
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java
index 8599392..d85e6cf 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleSettings.java
@@ -46,6 +46,7 @@
@Nullable private String myServiceDirectoryPath;
@Nullable private String myGradleVmOptions;
+ private boolean myIsOfflineWork;
public GradleSettings(@NotNull Project project) {
super(GradleSettingsListener.TOPIC, project);
@@ -66,6 +67,7 @@
protected void copyExtraSettingsFrom(@NotNull GradleSettings settings) {
myServiceDirectoryPath = settings.getServiceDirectoryPath();
myGradleVmOptions = settings.getGradleVmOptions();
+ myIsOfflineWork = settings.isOfflineWork();
}
@SuppressWarnings("unchecked")
@@ -76,6 +78,7 @@
fillState(state);
state.serviceDirectoryPath = myServiceDirectoryPath;
state.gradleVmOptions = myGradleVmOptions;
+ state.offlineWork = myIsOfflineWork;
return state;
}
@@ -84,6 +87,7 @@
super.loadState(state);
myServiceDirectoryPath = state.serviceDirectoryPath;
myGradleVmOptions = state.gradleVmOptions;
+ myIsOfflineWork = state.offlineWork;
}
/**
@@ -118,6 +122,14 @@
}
}
+ public boolean isOfflineWork() {
+ return myIsOfflineWork;
+ }
+
+ public void setOfflineWork(boolean isOfflineWork) {
+ myIsOfflineWork = isOfflineWork;
+ }
+
@Override
protected void checkSettings(@NotNull GradleProjectSettings old, @NotNull GradleProjectSettings current) {
if (!Comparing.equal(old.getGradleHome(), current.getGradleHome())) {
@@ -133,6 +145,7 @@
private Set<GradleProjectSettings> myProjectSettings = ContainerUtilRt.newTreeSet();
public String serviceDirectoryPath;
public String gradleVmOptions;
+ public boolean offlineWork;
@AbstractCollection(surroundWithTag = false, elementTypes = {GradleProjectSettings.class})
public Set<GradleProjectSettings> getLinkedExternalProjectsSettings() {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java
index 0742e4d..46b6ff4 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/RichTextActionProcessor.java
@@ -58,7 +58,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
final AsyncResult<DataContext> callback = DataManager.getInstance().getDataContextFromFocus();
final DataContext context = callback.getResult();
if (context == null) {
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleBundle.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleBundle.java
index 066a07c..9dd3fc4 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleBundle.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleBundle.java
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.gradle.util;
import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
/**
@@ -24,14 +25,14 @@
*/
public class GradleBundle extends AbstractBundle {
- public static final String PATH_TO_BUNDLE = "i18n.GradleBundle";
- private static final GradleBundle BUNDLE = new GradleBundle();
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return BUNDLE.getMessage(key, params);
+ }
+
+ public static final String PATH_TO_BUNDLE = "i18n.GradleBundle";
+ private static final GradleBundle BUNDLE = new GradleBundle();
public GradleBundle() {
super(PATH_TO_BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
- return BUNDLE.getMessage(key, params);
- }
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
index 9ed33e9..df51e51 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleConstants.java
@@ -26,6 +26,9 @@
@NotNull @NonNls public static final String HELP_TOPIC_TOOL_WINDOW = "reference.toolwindows.gradle";
+ @NotNull @NonNls public static final String OFFLINE_MODE_CMD_OPTION = "--offline";
+ @NotNull @NonNls public static final String INIT_SCRIPT_CMD_OPTION = "--init-script";
+
private GradleConstants() {
}
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleDocumentationBundle.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleDocumentationBundle.java
index 4751d60..e3bb3c0 100644
--- a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleDocumentationBundle.java
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleDocumentationBundle.java
@@ -18,6 +18,7 @@
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.reference.SoftReference;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -29,30 +30,29 @@
*/
public class GradleDocumentationBundle extends AbstractBundle {
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return BUNDLE.getMessage(key, params);
+ }
+
public static final String PATH_TO_BUNDLE = "i18n.GradleDocumentationBundle";
private static final GradleDocumentationBundle BUNDLE = new GradleDocumentationBundle();
- private static Reference<ResourceBundle> myBundle;
+ private static Reference<ResourceBundle> ourBundle;
public GradleDocumentationBundle() {
super(PATH_TO_BUNDLE);
}
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
- return BUNDLE.getMessage(key, params);
- }
-
- public static String messageOrDefault(String key, String defaultValue, Object... params) {
+ public static String messageOrDefault(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key,
+ String defaultValue,
+ @NotNull Object... params) {
return CommonBundle.messageOrDefault(getBundle(), key, defaultValue, params);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (myBundle != null) {
- bundle = myBundle.get();
- }
+ ResourceBundle bundle = SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
- myBundle = new SoftReference<ResourceBundle>(bundle);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
}
return bundle;
}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEditorTabTitleProvider.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEditorTabTitleProvider.java
new file mode 100644
index 0000000..635d437
--- /dev/null
+++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/util/GradleEditorTabTitleProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.util;
+
+import com.intellij.openapi.fileEditor.impl.EditorTabTitleProvider;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.vfs.VirtualFile;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/5/14
+ */
+public class GradleEditorTabTitleProvider implements EditorTabTitleProvider {
+ public String getEditorTabTitle(Project project, VirtualFile file) {
+ if (GradleConstants.EXTENSION.equals(file.getExtension()) && GradleConstants.DEFAULT_SCRIPT_NAME.equals(file.getName())) {
+ for (Module module : ModuleManager.getInstance(project).getModules()) {
+ if (module.isDisposed()) return null;
+
+ final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
+ for (VirtualFile virtualFile : moduleRootManager.getContentRoots()) {
+ if (virtualFile == file.getParent()) return module.getName();
+ }
+ }
+ }
+ return null;
+ }
+}
diff --git a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle b/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
deleted file mode 100644
index 73cb6a1..0000000
--- a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
+++ /dev/null
@@ -1,55 +0,0 @@
-//noinspection GrPackage
-
-allprojects {
- apply plugin: 'java'
- apply plugin: 'idea'
-
- version = '1.0'
-
- sourceCompatibility = 1.6
-
- configurations {
- provided
- }
-
- sourceSets {
- main {
- compileClasspath += configurations.provided
- }
- }
-
- idea {
- module {
- scopes.PROVIDED.plus += configurations.provided
- }
- }
-}
-
-project(":service") {
- dependencies {
- compile(project(':api'))
- }
-}
-
-project(":api") {
- dependencies {
- provided(project(':lib'))
- }
-}
-
-project(":withIdeaModelCustomisations") {
- dependencies {
- //compile 'org.slf4j:slf4j-api:1.7.5'
- //testCompile 'junit:junit:4.11'
-
- compile files("lib/someDep.jar")
- testCompile files("lib/someTestDep.jar")
- }
-
- idea {
- module {
- scopes.COMPILE.plus += scopes.TEST.plus
- scopes.TEST.plus = []
- }
- }
-}
diff --git a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle b/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
deleted file mode 100644
index 26ee835..0000000
--- a/plugins/gradle/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
+++ /dev/null
@@ -1,5 +0,0 @@
-//noinspection GrPackage
-include "lib"
-include "api"
-include "service"
-include "withIdeaModelCustomisations"
\ No newline at end of file
diff --git a/plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle b/plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle
deleted file mode 100644
index 8c75849..0000000
--- a/plugins/gradle/testData/testGradleSourcesSetsInterpretation/build.gradle
+++ /dev/null
@@ -1,74 +0,0 @@
-//noinspection GrPackage
-
-project("defaultJavaModule") {
- apply plugin: "java"
-}
-
-project("moduleWithSourceSetDirBothAsResourceAndJava") {
- apply plugin: "java"
-
- sourceSets.main.resources.srcDir 'src/main/java'
- sourceSets.test.resources.srcDir 'src/test/java'
-}
-
-project("moduleWithCustomSourceSet") {
- apply plugin: "java"
-
- sourceSets {
- custom
- }
-
- sourceSets.custom.java.srcDir 'src/custom/java'
-}
-
-project("withIntegrationTests") {
- apply plugin: 'java'
-
- sourceSets {
- integrationTest {
- java.srcDir file('src/integration-test/java')
- resources.srcDir file('src/integration-test/resources')
- }
- }
-
- dependencies {
- integrationTestCompile sourceSets.main.output
- integrationTestCompile configurations.testCompile
- integrationTestCompile sourceSets.test.output
- integrationTestRuntime configurations.testRuntime
- }
-
- //noinspection GrUnresolvedAccess
- task integrationTest(type: Test, dependsOn: jar) {
- testClassesDir = sourceSets.integrationTest.output.classesDir
- classpath = sourceSets.integrationTest.runtimeClasspath
- }
-
- check.dependsOn integrationTest
-}
-
-project("withIdeaPluginCustomization1") {
- apply plugin: 'java'
-
- idea {
- module {
- testSourceDirs += file('src/intTest/java')
- testSourceDirs += file('src/intTest/resources')
- excludeDirs += file('some-extra-exclude-folder')
- }
- }
-}
-
-// see http://youtrack.jetbrains.com/issue/IDEA-119365
-project("withIdeaPluginCustomization2") {
- apply plugin: 'java'
-
- idea {
- module {
- sourceDirs += testSourceDirs
- testSourceDirs = []
- ext.resourceDirs += file('some-extra-resource-folder')
- ext.testResourceDirs += file('some-extra-test-resource-folder')
- }
- }
-}
diff --git a/plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle b/plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle
deleted file mode 100644
index 4f7ab78..0000000
--- a/plugins/gradle/testData/testGradleSourcesSetsInterpretation/settings.gradle
+++ /dev/null
@@ -1,8 +0,0 @@
-//noinspection GrPackage
-
-include 'defaultJavaModule'
-include 'moduleWithSourceSetDirBothAsResourceAndJava'
-include 'moduleWithCustomSourceSet'
-include 'withIntegrationTests'
-include 'withIdeaPluginCustomization1'
-include 'withIdeaPluginCustomization2'
\ No newline at end of file
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/GradleProjectWizardTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/GradleProjectWizardTest.java
index bda7890..b8ff35f 100644
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/GradleProjectWizardTest.java
+++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/GradleProjectWizardTest.java
@@ -17,13 +17,15 @@
import com.intellij.ide.projectWizard.NewProjectWizardTestCase;
import com.intellij.ide.projectWizard.ProjectTypeStep;
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.wizard.Step;
import com.intellij.openapi.project.Project;
import com.intellij.util.Consumer;
+import java.util.List;
+
/**
* @author Dmitry Avdeev
- * Date: 18.10.13
*/
public class GradleProjectWizardTest extends NewProjectWizardTestCase {
@@ -32,7 +34,9 @@
@Override
public void consume(Step step) {
if (step instanceof ProjectTypeStep) {
- assertTrue(((ProjectTypeStep)step).setSelectedProjectType("Java", "Gradle"));
+ assertTrue(((ProjectTypeStep)step).setSelectedTemplate("Gradle", null));
+ List<ModuleWizardStep> steps = myWizard.getSequence().getSelectedSteps();
+ assertEquals(3, steps.size());
}
}
});
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/GradleContentRootTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/GradleContentRootTest.java
deleted file mode 100644
index e060b7f..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/GradleContentRootTest.java
+++ /dev/null
@@ -1,21 +0,0 @@
-package org.jetbrains.plugins.gradle.model;
-
-import com.intellij.openapi.externalSystem.model.project.ContentRootData;
-import com.intellij.openapi.externalSystem.model.project.ModuleData;
-import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
-import org.junit.Test;
-
-/**
- * @author Denis Zhdanov
- * @since 8/31/11 1:33 PM
- */
-public class GradleContentRootTest {
-
- @Test(expected = IllegalArgumentException.class)
- public void pathOutOfContentRoot() {
- throw new IllegalArgumentException();
- // TODO den implement
-// ContentRootData contentRoot = new ContentRootData(new ModuleData("module", "."), "./my-content-root");
-// contentRoot.storePath(ExternalSystemSourceType.SOURCE, "./my-dir-out-of-content-root");
- }
-}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/GradleProjectTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/GradleProjectTest.java
deleted file mode 100644
index 77e92bd..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/GradleProjectTest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-package org.jetbrains.plugins.gradle.model;
-
-import com.intellij.openapi.externalSystem.model.project.ProjectData;
-import com.intellij.openapi.projectRoots.JavaSdkVersion;
-import org.jetbrains.annotations.NotNull;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.io.File;
-
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Denis Zhdanov
- * @since 8/29/11 1:28 PM
- */
-public class GradleProjectTest {
-
- private ProjectData myProject;
-
- @Before
- public void setUp() {
- String path = new File(".").getPath();
- // TODO den implement
-// myProject = new ProjectData(path, path, id);
- }
-
- @Test
- public void jdkVersion() {
- doTestJdkVersion("4", JavaSdkVersion.JDK_1_4);
- doTestJdkVersion(" 5", JavaSdkVersion.JDK_1_5);
- doTestJdkVersion("6 ", JavaSdkVersion.JDK_1_6);
- doTestJdkVersion(" 7 ", JavaSdkVersion.JDK_1_7);
- doTestJdkVersion(" 1.4 ", JavaSdkVersion.JDK_1_4);
- doTestJdkVersion("this is version 1.5.1_0b12 ", JavaSdkVersion.JDK_1_5);
- }
-
- private void doTestJdkVersion(@NotNull String version, @NotNull JavaSdkVersion expected) {
- // TODO den implement
-// myProject.setJdkVersion(version);
-// assertEquals(expected, myProject.getJdkVersion());
- }
-}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java
deleted file mode 100644
index 0cdd2f0..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/AbstractModelBuilderTest.java
+++ /dev/null
@@ -1,96 +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.gradle.model.builder;
-
-import com.intellij.openapi.util.io.FileUtil;
-import org.gradle.tooling.BuildActionExecuter;
-import org.gradle.tooling.GradleConnector;
-import org.gradle.tooling.ProjectConnection;
-import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
-import org.jetbrains.plugins.gradle.service.project.GradleExecutionHelper;
-import org.jetbrains.plugins.gradle.service.project.ProjectImportAction;
-import org.jetbrains.plugins.gradle.util.GradleConstants;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.rules.TestName;
-
-import java.io.File;
-import java.util.Set;
-
-import static org.junit.Assert.assertNotNull;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/29/13
- */
-public abstract class AbstractModelBuilderTest {
- private static File ourTempDir;
- protected File testDir;
- protected ProjectImportAction.AllModels allModels;
-
- @Rule public TestName name = new TestName();
-
- @Before
- public void setUp() throws Exception {
- ensureTempDirCreated();
- testDir = new File(ourTempDir, name.getMethodName());
- testDir.mkdirs();
-
- FileUtil.writeToFile(
- new File(testDir, GradleConstants.DEFAULT_SCRIPT_NAME),
- FileUtil.loadTextAndClose(getClass().getResourceAsStream(
- String.format("/%s/%s", name.getMethodName(), GradleConstants.DEFAULT_SCRIPT_NAME))
- )
- );
-
- FileUtil.writeToFile(
- new File(testDir, GradleConstants.SETTINGS_FILE_NAME),
- FileUtil.loadTextAndClose(getClass().getResourceAsStream(
- String.format("/%s/%s", name.getMethodName(), GradleConstants.SETTINGS_FILE_NAME))
- )
- );
-
- GradleConnector connector = GradleConnector.newConnector();
-
- DefaultGradleConnector gradleConnector = (DefaultGradleConnector)connector;
- gradleConnector.forProjectDirectory(testDir);
- ProjectConnection connection = gradleConnector.connect();
-
- final ProjectImportAction projectImportAction = new ProjectImportAction(true);
- projectImportAction.addExtraProjectModelClasses(getModels());
- BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
- GradleExecutionHelper.setInitScript(buildActionExecutor, false);
-
- allModels = buildActionExecutor.run();
- assertNotNull(allModels);
- }
-
- @After
- public void tearDown() throws Exception {
- FileUtil.delete(testDir);
- }
-
- protected abstract Set<Class> getModels();
-
- private static void ensureTempDirCreated() {
- if (ourTempDir != null) return;
-
- ourTempDir = new File(FileUtil.getTempDirectory(), "gradleTests");
- FileUtil.delete(ourTempDir);
- ourTempDir.mkdirs();
- }
-}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java
deleted file mode 100644
index d802d08..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelBuildScriptClasspathBuilderImplTest.java
+++ /dev/null
@@ -1,86 +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 org.jetbrains.plugins.gradle.model.builder;
-
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
-import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.Set;
-
-import static junit.framework.Assert.*;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Vladislav.Soroka
- * @since 1/16/14
- */
-public class ModelBuildScriptClasspathBuilderImplTest extends AbstractModelBuilderTest {
-
- @Test
- public void testModelBuildScriptClasspathBuilder() throws Exception {
- ModelBuildScriptClasspathBuilderImpl buildScriptClasspathBuilder = new ModelBuildScriptClasspathBuilderImpl();
- assertTrue(buildScriptClasspathBuilder.canBuild("org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel"));
-
- DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
-
- List<BuildScriptClasspathModel> ideaModule =
- ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, BuildScriptClasspathModel>() {
- @Override
- public BuildScriptClasspathModel fun(IdeaModule module) {
- BuildScriptClasspathModel classpathModel = allModels.getExtraProject(module, BuildScriptClasspathModel.class);
-
- if (module.getName().equals("moduleWithAdditionalClasspath")) {
- assertNotNull(classpathModel);
- assertEquals(1, classpathModel.getClasspath().size());
-
- ClasspathEntryModel classpathEntry = classpathModel.getClasspath().getAt(0);
- assertEquals("someDep.jar", classpathEntry.getClassesFile().getName());
- }
- else if (module.getName().equals("baseModule") ||
- module.getName().equals("moduleWithInheritedClasspath")) {
- assertNotNull("Null build classpath for module: " + module.getName(), classpathModel);
- assertEquals("Wrong build classpath for module: " + module.getName(), 1, classpathModel.getClasspath().size());
-
- ClasspathEntryModel classpathEntry = classpathModel.getClasspath().getAt(0);
- assertEquals("Wrong build classpath for module: " + module.getName(), "inheritedDep.jar", classpathEntry.getClassesFile().getName());
- }
- else if (module.getName().equals("moduleWithoutAdditionalClasspath") ||
- module.getName().equals("testModelBuildScriptClasspathBuilder")) {
- assertNotNull("Wrong build classpath for module: " + module.getName(), classpathModel);
- assertTrue("Wrong build classpath for module: " + module.getName(), classpathModel.getClasspath().isEmpty());
- }
- else {
- fail("Unexpected module found: " + module.getName());
- }
-
- return classpathModel;
- }
- });
-
- assertEquals(5, ideaModule.size());
- }
-
- @Override
- protected Set<Class> getModels() {
- return ContainerUtil.<Class>set(BuildScriptClasspathModel.class);
- }
-}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java
deleted file mode 100644
index 8cf50ef..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModelDependenciesBuilderImplTest.java
+++ /dev/null
@@ -1,155 +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.gradle.model.builder;
-
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.idea.IdeaDependency;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaModuleDependency;
-import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
-import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.Set;
-
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/29/13
- */
-public class ModelDependenciesBuilderImplTest extends AbstractModelBuilderTest {
-
- @Test
- public void testDefaultDependenciesModel() throws Exception {
- ModelDependenciesBuilderImpl dependenciesBuilder = new ModelDependenciesBuilderImpl();
- assertTrue(dependenciesBuilder.canBuild("org.jetbrains.plugins.gradle.model.ProjectDependenciesModel"));
-
- DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
-
- final int modulesSize = 3;
- assertEquals(modulesSize, ideaModules.size());
-
- for (IdeaModule ideaModule : ideaModules) {
- if (ideaModule.getName().equals("dependencyProject") ||
- ideaModule.getName().equals("testDefaultDependenciesModel")) {
- DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
- assertTrue((dependencies.isEmpty()));
- }
- else if (ideaModule.getName().equals("dependentProject")) {
- DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
- assertEquals(1, dependencies.size());
- assertTrue(dependencies.getAt(0) instanceof IdeaModuleDependency);
- IdeaModuleDependency moduleDependency = (IdeaModuleDependency)dependencies.getAt(0);
-
- assertEquals("dependencyProject", moduleDependency.getDependencyModule().getName());
- assertEquals("COMPILE", moduleDependency.getScope().getScope());
- assertTrue(moduleDependency.getExported());
- }
- else {
- fail();
- }
- }
- }
-
- @Test
- public void testGradleIdeaPluginPlusScopesDependenciesModel() throws Exception {
- ModelDependenciesBuilderImpl dependenciesBuilder = new ModelDependenciesBuilderImpl();
- assertTrue(dependenciesBuilder.canBuild("org.jetbrains.plugins.gradle.model.ProjectDependenciesModel"));
-
- DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
-
- final int modulesSize = 5;
- assertEquals(modulesSize, ideaModules.size());
-
- for (IdeaModule ideaModule : ideaModules) {
- DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
- if (ideaModule.getName().equals("lib") ||
- ideaModule.getName().equals("testGradleIdeaPluginPlusScopesDependenciesModel")) {
- assertTrue((dependencies.isEmpty()));
- }
- else if (ideaModule.getName().equals("api")) {
- assertEquals(1, dependencies.size());
- IdeaDependency libDependency = dependencies.getAt(0);
- assertEquals(GradleDependencyScope.PROVIDED.getIdeaMappingName(), libDependency.getScope().getScope().toLowerCase());
- assertTrue(libDependency instanceof IdeaModuleDependency);
-
- IdeaModuleDependency libModuleDependency = (IdeaModuleDependency)libDependency;
- assertNotNull(libModuleDependency.getDependencyModule());
- assertEquals("lib", libModuleDependency.getDependencyModule().getName());
- }
- else if (ideaModule.getName().equals("service")) {
- assertEquals(1, dependencies.size());
- IdeaDependency apiDependency = dependencies.getAt(0);
- assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), apiDependency.getScope().getScope().toLowerCase());
- assertTrue(apiDependency instanceof IdeaModuleDependency);
-
- IdeaModuleDependency apiModuleDependency = (IdeaModuleDependency)apiDependency;
- assertNotNull(apiModuleDependency.getDependencyModule());
- assertEquals("api", apiModuleDependency.getDependencyModule().getName());
- }
- else if (ideaModule.getName().equals("withIdeaModelCustomisations")) {
-
- assertTrue(findLocalLibraries(dependencies, GradleDependencyScope.TEST_COMPILE.getIdeaMappingName()).isEmpty());
-
- List<IdeaSingleEntryLibraryDependency> libraryDependencies =
- findLocalLibraries(dependencies, GradleDependencyScope.COMPILE.getIdeaMappingName());
- assertEquals(2, libraryDependencies.size());
-
- IdeaSingleEntryLibraryDependency someDep = libraryDependencies.get(0);
- assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), someDep.getScope().getScope().toLowerCase());
- assertEquals("someDep.jar", someDep.getFile().getName());
-
- IdeaSingleEntryLibraryDependency someTestDep = libraryDependencies.get(1);
- assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), someTestDep.getScope().getScope().toLowerCase());
- assertEquals("someTestDep.jar", someTestDep.getFile().getName());
- }
- else {
- fail();
- }
- }
- }
-
- @NotNull
- private static List<IdeaSingleEntryLibraryDependency> findLocalLibraries(
- @NotNull final DomainObjectSet<? extends IdeaDependency> dependencies, @NotNull final String scope) {
- return ContainerUtil.mapNotNull(
- dependencies,
- new Function<IdeaDependency, IdeaSingleEntryLibraryDependency>() {
- @Override
- public IdeaSingleEntryLibraryDependency fun(IdeaDependency dependency) {
- return dependency instanceof IdeaSingleEntryLibraryDependency && scope.equals(dependency.getScope().getScope().toLowerCase())
- ? (IdeaSingleEntryLibraryDependency)dependency
- : null;
- }
- }
- );
- }
-
- @Override
- protected Set<Class> getModels() {
- return ContainerUtil.<Class>set(ProjectDependenciesModel.class);
- }
-}
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java
deleted file mode 100644
index 9694c9d..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/ModuleExtendedModelBuilderImplTest.java
+++ /dev/null
@@ -1,177 +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 org.jetbrains.plugins.gradle.model.builder;
-
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.gradle.tooling.model.idea.IdeaSourceDirectory;
-import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
-import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.io.File;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Set;
-
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.fail;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Vladislav.Soroka
- * @since 1/16/14
- */
-public class ModuleExtendedModelBuilderImplTest extends AbstractModelBuilderTest {
-
- @Test
- public void testGradleSourcesSetsInterpretation() throws Exception {
- final int modulesSize = 7;
-
- ModuleExtendedModelBuilderImpl moduleExtendedModelBuilder = new ModuleExtendedModelBuilderImpl();
- assertTrue(moduleExtendedModelBuilder.canBuild("org.jetbrains.plugins.gradle.model.ModuleExtendedModel"));
-
- DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
-
- List<ModuleExtendedModel> models =
- ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, ModuleExtendedModel>() {
- @Override
- public ModuleExtendedModel fun(IdeaModule module) {
- ModuleExtendedModel moduleExtendedModel = allModels.getExtraProject(module, ModuleExtendedModel.class);
-
- assertNotNull(moduleExtendedModel);
-
- List<String> sourceDirectories = ContainerUtil.newArrayList();
- List<String> resourceDirectories = ContainerUtil.newArrayList();
- List<String> testResourceDirectories = ContainerUtil.newArrayList();
- List<String> testDirectories = ContainerUtil.newArrayList();
- List<String> excludeDirectories = ContainerUtil.newArrayList();
-
- fillDirectories(moduleExtendedModel,
- sourceDirectories, resourceDirectories,
- testDirectories, testResourceDirectories,
- excludeDirectories);
-
- if (module.getName().equals("defaultJavaModule") || module.getName().equals("moduleWithSourceSetDirBothAsResourceAndJava")) {
- assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/test/java"), testDirectories);
- assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
- assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
- }
- else if (module.getName().equals("moduleWithCustomSourceSet")) {
- assertEquals(ContainerUtil.newArrayList("src/custom/java", "src/main/java"), sourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/custom/resources", "src/main/resources"), resourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/test/java"), testDirectories);
- assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
- assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
- }
- else if (module.getName().equals("withIntegrationTests")) {
- assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
- assertEquals(ContainerUtil.newArrayList(
- "src/integration-test/java", "src/integrationTest/java", "src/test/java"), testDirectories);
- assertEquals(ContainerUtil.newArrayList(
- "src/integration-test/resources",
- "src/integrationTest/resources",
- "src/test/resources"), testResourceDirectories);
- assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
- }
- else if (module.getName().equals("testGradleSourcesSetsInterpretation")) {
- assertTrue(sourceDirectories.isEmpty());
- assertTrue(resourceDirectories.isEmpty());
- assertTrue(testDirectories.isEmpty());
- assertTrue(testResourceDirectories.isEmpty());
- assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
- }
- else if (module.getName().equals("withIdeaPluginCustomization1")) {
- assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
- assertEquals(ContainerUtil.newArrayList("src/intTest/java", "src/intTest/resources", "src/test/java"), testDirectories);
- assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
- assertEquals(ContainerUtil.newArrayList(".gradle", "build", "some-extra-exclude-folder"), excludeDirectories);
- }
- else if (module.getName().equals("withIdeaPluginCustomization2")) {
- assertEquals(ContainerUtil.newArrayList("src/main/java", "src/test/java", "src/test/resources"), sourceDirectories);
- assertEquals(ContainerUtil.newArrayList("some-extra-resource-folder", "src/main/resources"), resourceDirectories);
- assertTrue(testDirectories.isEmpty());
- assertEquals(ContainerUtil.newArrayList("some-extra-test-resource-folder"), testResourceDirectories);
- assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
- }
- else {
- fail();
- }
-
- return moduleExtendedModel;
- }
- });
-
- assertEquals(modulesSize, models.size());
- }
-
- private void fillDirectories(final ModuleExtendedModel model,
- List<String> sourceDirectories, List<String> resourceDirectories,
- List<String> testDirectories, List<String> resourceTestDirectories,
- List<String> excludeDirectories) {
- for (ExtIdeaContentRoot contentRoot : model.getContentRoots()) {
- sourceDirectories.addAll(getAllPaths(contentRoot.getSourceDirectories(), model.getName()));
- resourceDirectories.addAll(getAllPaths(contentRoot.getResourceDirectories(), model.getName()));
- testDirectories.addAll(getAllPaths(contentRoot.getTestDirectories(), model.getName()));
- resourceTestDirectories.addAll(getAllPaths(contentRoot.getTestResourceDirectories(), model.getName()));
- excludeDirectories.addAll(getAllPaths(contentRoot.getExcludeDirectories(), model.getName()));
- }
- }
-
- private Collection<? extends String> getAllPaths(Collection<? extends File> directories, final String moduleName) {
- List<String> list = ContainerUtil.map2List(directories, new Function<File, String>() {
- @Override
- public String fun(File sourceDirectory) {
- String path =
- FileUtil.toCanonicalPath(FileUtil.getRelativePath(new File(testDir, moduleName), sourceDirectory));
- Assert.assertNotNull(path);
- return path.substring(path.indexOf("/") + 1);
- }
- });
- Collections.sort(list);
- return list;
- }
-
- private Collection<? extends String> getAllPaths(DomainObjectSet<? extends IdeaSourceDirectory> directories, final String moduleName) {
- List<String> list = ContainerUtil.map2List(directories, new Function<IdeaSourceDirectory, String>() {
- @Override
- public String fun(IdeaSourceDirectory sourceDirectory) {
- String path =
- FileUtil.toCanonicalPath(FileUtil.getRelativePath(new File(testDir, moduleName), sourceDirectory.getDirectory()));
- Assert.assertNotNull(path);
- return path.substring(path.indexOf("/") + 1);
- }
- });
- Collections.sort(list);
- return list;
- }
-
- @Override
- protected Set<Class> getModels() {
- return ContainerUtil.<Class>set(ModuleExtendedModel.class);
- }
-}
-
diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/WarModelBuilderImplTest.java b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/WarModelBuilderImplTest.java
deleted file mode 100644
index e0aff59..0000000
--- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/model/builder/WarModelBuilderImplTest.java
+++ /dev/null
@@ -1,61 +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.gradle.model.builder;
-
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
-import org.gradle.tooling.model.DomainObjectSet;
-import org.gradle.tooling.model.idea.IdeaModule;
-import org.jetbrains.plugins.gradle.model.WarModel;
-import org.junit.Test;
-
-import java.util.List;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-/**
- * @author Vladislav.Soroka
- * @since 11/29/13
- */
-public class WarModelBuilderImplTest extends AbstractModelBuilderTest {
-
- @Test
- public void testDefaultWarModel() throws Exception {
- WarModelBuilderImpl warModelBuilder = new WarModelBuilderImpl();
- assertTrue(warModelBuilder.canBuild("org.jetbrains.plugins.gradle.model.WarModel"));
-
- DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
-
- List<WarModel> ideaModule = ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, WarModel>() {
- @Override
- public WarModel fun(IdeaModule module) {
- return allModels.getExtraProject(module, WarModel.class);
- }
- });
-
- assertEquals(1, ideaModule.size());
- WarModel warModel = ideaModule.get(0);
-
- assertEquals("src/main/webapp", warModel.getWebAppDirName());
- }
-
- @Override
- protected Set<Class> getModels() {
- return ContainerUtil.<Class>set(WarModel.class);
- }
-}
diff --git a/plugins/gradle/tooling-extension-v1.11/gradle-tooling-extension-v1.11.iml b/plugins/gradle/tooling-extension-v1.11/gradle-tooling-extension-v1.11.iml
new file mode 100644
index 0000000..921ff34
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/gradle-tooling-extension-v1.11.iml
@@ -0,0 +1,124 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="annotations" />
+ <orderEntry type="module" module-name="external-system-api" />
+ <orderEntry type="module" module-name="gradle-tooling-extension" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module" module-name="gradle" scope="TEST" />
+ <orderEntry type="module-library">
+ <library name="Gradle">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/gradle-tooling-api-1.11-rc-1.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-core-1.11-rc-1.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-base-services-1.11-rc-1.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-ide-1.11-rc-1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/buildSrc/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/buildSrc/src/test/resources" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ui/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ui/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ui/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/cli/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/cpp/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/cpp/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ear/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ide/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ide/src/main/resources" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/ivy/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/core/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/core/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/core/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/core/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/osgi/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/osgi/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/antlr/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/jetty/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/maven/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/maven/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/scala/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/scala/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/jacoco/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/native/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/plugins/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/plugins/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/plugins/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/publish/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/wrapper/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/wrapper/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/announce/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/launcher/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/launcher/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/launcher/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/open-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/open-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/core-impl/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/core-impl/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/messaging/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/messaging/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/reporting/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/resources/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/javascript/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/diagnostics/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/diagnostics/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/diagnostics/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/performance/src/configPlugin" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/performance/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/tooling-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/tooling-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/tooling-api/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/code-quality/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/language-jvm/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/base-services/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/base-services/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/language-base/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-comparison/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/source/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/target/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/internal-testing/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/base-services-groovy/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.11-rc-1-src.zip!/gradle-1.11-rc-1/subprojects/base-services-groovy/src/test/groovy" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library name="GradleGuava">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/guava-jdk5-14.0.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="Groovy" level="project" />
+ </component>
+</module>
+
diff --git a/plugins/gradle/tooling-extension-v1.11/lib/gradle-1.11-rc-1-src.zip b/plugins/gradle/tooling-extension-v1.11/lib/gradle-1.11-rc-1-src.zip
new file mode 100644
index 0000000..355aee4
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/lib/gradle-1.11-rc-1-src.zip
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.11/lib/gradle-base-services-1.11-rc-1.jar b/plugins/gradle/tooling-extension-v1.11/lib/gradle-base-services-1.11-rc-1.jar
new file mode 100644
index 0000000..27283d8
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/lib/gradle-base-services-1.11-rc-1.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.11/lib/gradle-core-1.11-rc-1.jar b/plugins/gradle/tooling-extension-v1.11/lib/gradle-core-1.11-rc-1.jar
new file mode 100644
index 0000000..19d2356
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/lib/gradle-core-1.11-rc-1.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.11/lib/gradle-ide-1.11-rc-1.jar b/plugins/gradle/tooling-extension-v1.11/lib/gradle-ide-1.11-rc-1.jar
new file mode 100644
index 0000000..881d355
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/lib/gradle-ide-1.11-rc-1.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.11/lib/gradle-tooling-api-1.11-rc-1.jar b/plugins/gradle/tooling-extension-v1.11/lib/gradle-tooling-api-1.11-rc-1.jar
new file mode 100644
index 0000000..25557d7
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/lib/gradle-tooling-api-1.11-rc-1.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.11/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension-v1.11/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
new file mode 100644
index 0000000..b8b70b0
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -0,0 +1,17 @@
+#
+# Copyright 2000-2014 JetBrains s.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.
+#
+org.jetbrains.plugins.gradle.tooling.v1_11.builder.ModelDependenciesBuilderImpl
+org.jetbrains.plugins.gradle.tooling.v1_11.builder.ModelBuildScriptClasspathBuilderImpl
diff --git a/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/builder/ModelBuildScriptClasspathBuilderImpl.java b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/builder/ModelBuildScriptClasspathBuilderImpl.java
new file mode 100644
index 0000000..a0d3c3e
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/builder/ModelBuildScriptClasspathBuilderImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_11.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.gradle.plugins.ide.internal.resolver.model.IdeLocalFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeRepoFileDependency;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.jetbrains.plugins.gradle.tooling.internal.BuildScriptClasspathModelImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.ClasspathEntryModelImpl;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+@TargetVersions("1.11")
+public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService {
+
+ private final Map<String, BuildScriptClasspathModelImpl> cache = new ConcurrentHashMap<String, BuildScriptClasspathModelImpl>();
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return BuildScriptClasspathModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ BuildScriptClasspathModelImpl buildScriptClasspath = cache.get(project.getPath());
+ if (buildScriptClasspath != null) return buildScriptClasspath;
+
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ }
+ }
+
+ buildScriptClasspath = new BuildScriptClasspathModelImpl();
+ Project parent = project.getParent();
+ if (parent != null) {
+ BuildScriptClasspathModelImpl parentBuildScriptClasspath = (BuildScriptClasspathModelImpl)buildAll(modelName, parent);
+ if (parentBuildScriptClasspath != null) {
+ for (ClasspathEntryModel classpathEntryModel : parentBuildScriptClasspath.getClasspath()) {
+ buildScriptClasspath.add(classpathEntryModel);
+ }
+ }
+ }
+
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ final Configuration configuration = project.getBuildscript().getConfigurations().findByName("classpath");
+ Collection<Configuration> plusConfigurations = Collections.singletonList(configuration);
+
+ if (!offline) {
+ // download sources and/or javadoc
+ List<IdeRepoFileDependency> repoFileDependencies = dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+
+ for (IdeRepoFileDependency dependency : repoFileDependencies) {
+ if (dependency.getFile() == null) continue;
+
+ buildScriptClasspath.add(
+ new ClasspathEntryModelImpl(dependency.getFile(), dependency.getSourceFile(), dependency.getJavadocFile()));
+ }
+ }
+
+ final Collection<IdeLocalFileDependency> localFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeLocalFileDependency dependency : localFileDependencies) {
+ if (dependency.getFile() == null) continue;
+ buildScriptClasspath.add(new ClasspathEntryModelImpl(dependency.getFile(), null, null));
+ }
+
+ cache.put(project.getPath(), buildScriptClasspath);
+ return buildScriptClasspath;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/builder/ModelDependenciesBuilderImpl.java b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/builder/ModelDependenciesBuilderImpl.java
new file mode 100644
index 0000000..caaae15
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/builder/ModelDependenciesBuilderImpl.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_11.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.gradle.plugins.ide.internal.resolver.model.IdeLocalFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeProjectDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeRepoFileDependency;
+import org.gradle.tooling.model.idea.IdeaDependency;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.jetbrains.plugins.gradle.tooling.internal.*;
+import org.jetbrains.plugins.gradle.tooling.v1_11.internal.InternalDependencyVersionId;
+
+import java.util.*;
+
+import static org.jetbrains.plugins.gradle.tooling.v1_11.internal.ModelDependenciesBuilderImplHelper.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+@TargetVersions("1.11")
+public class ModelDependenciesBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return ProjectDependenciesModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ final List<IdeaDependency> dependencies = new ArrayList<IdeaDependency>();
+
+ final Map<InternalDependencyVersionId, Scopes> scopesMap = new LinkedHashMap<InternalDependencyVersionId, Scopes>();
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+ Map<String, Map<String, Collection<Configuration>>> userScopes = Collections.emptyMap();
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ userScopes = ideaModel.getModule().getScopes();
+ }
+ }
+
+ for (final Configuration configuration : project.getConfigurations()) {
+ Collection<Configuration> plusConfigurations = new ArrayList<Configuration>();
+ plusConfigurations.add(configuration);
+
+ final Collection<IdeProjectDependency> ideProjectDependencies =
+ dependenciesExtractor.extractProjectDependencies(project, plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeProjectDependency ideProjectDependency : ideProjectDependencies) {
+ merge(scopesMap, ideProjectDependency, userScopes);
+ }
+
+ if (!offline) {
+ final Collection<IdeRepoFileDependency> ideRepoFileDependencies =
+ dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+ for (IdeRepoFileDependency repoFileDependency : ideRepoFileDependencies) {
+ merge(scopesMap, repoFileDependency, userScopes);
+ }
+ }
+
+ final Collection<IdeLocalFileDependency> ideLocalFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+ for (IdeLocalFileDependency fileDependency : ideLocalFileDependencies) {
+ merge(scopesMap, fileDependency, userScopes);
+ }
+ }
+
+ for (Map.Entry<InternalDependencyVersionId, Scopes> entry : scopesMap.entrySet()) {
+ InternalDependencyVersionId versionId = entry.getKey();
+ for (GradleDependencyScope scope : entry.getValue().getScopes()) {
+ if (versionId.getIdeDependency() instanceof IdeRepoFileDependency) {
+ IdeRepoFileDependency repoFileDependency =
+ (IdeRepoFileDependency)versionId.getIdeDependency();
+ IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ versionId.getName(),
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ libraryDependency.setFile(repoFileDependency.getFile());
+ libraryDependency.setSource(repoFileDependency.getSourceFile());
+ libraryDependency.setJavadoc(repoFileDependency.getJavadocFile());
+ dependencies.add(libraryDependency);
+ }
+ else if (versionId.getIdeDependency() instanceof IdeProjectDependency) {
+ IdeProjectDependency projectDependency =
+ (IdeProjectDependency)versionId.getIdeDependency();
+
+ String ideaModuleName = findDeDuplicatedModuleName(projectDependency.getProject());
+ if (ideaModuleName == null) {
+ ideaModuleName = versionId.getName();
+ }
+
+ IdeaModuleDependencyImpl moduleDependency = new IdeaModuleDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ ideaModuleName,
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ moduleDependency.setIdeaModule(new StubIdeaModule(ideaModuleName));
+ dependencies.add(moduleDependency);
+ }
+ else if (versionId.getIdeDependency() instanceof IdeLocalFileDependency) {
+ IdeLocalFileDependency fileDependency =
+ (IdeLocalFileDependency)versionId.getIdeDependency();
+ IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ versionId.getName(),
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ libraryDependency.setFile(fileDependency.getFile());
+ attachGradleSdkSources(libraryDependency, fileDependency);
+ dependencies.add(libraryDependency);
+ }
+ }
+ }
+
+ return new ProjectDependenciesModelImpl(project.getPath(), dependencies);
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/internal/InternalDependencyVersionId.java b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/internal/InternalDependencyVersionId.java
new file mode 100644
index 0000000..f94c1ab
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/internal/InternalDependencyVersionId.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_11.internal;
+
+import org.gradle.plugins.ide.internal.resolver.model.IdeDependency;
+import org.jetbrains.plugins.gradle.tooling.internal.DependencyVersionId;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class InternalDependencyVersionId extends DependencyVersionId {
+ private final IdeDependency myIdeDependency;
+
+ public InternalDependencyVersionId(IdeDependency dependency,
+ String name,
+ String artifactName,
+ String group,
+ String version,
+ String classifier) {
+ super(name, artifactName, group, version, classifier);
+ myIdeDependency = dependency;
+ }
+
+ public IdeDependency getIdeDependency() {
+ return myIdeDependency;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/internal/ModelDependenciesBuilderImplHelper.java b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/internal/ModelDependenciesBuilderImplHelper.java
new file mode 100644
index 0000000..7a241bc
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.11/src/org/jetbrains/plugins/gradle/tooling/v1_11/internal/ModelDependenciesBuilderImplHelper.java
@@ -0,0 +1,228 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_11.internal;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ModuleIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.plugins.ide.idea.GenerateIdeaModule;
+import org.gradle.plugins.ide.internal.resolver.model.IdeLocalFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeProjectDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeRepoFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.UnresolvedIdeRepoFileDependency;
+import org.gradle.util.GradleVersion;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.tooling.internal.IdeaSingleEntryLibraryDependencyImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.Scopes;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/3/14
+ */
+public class ModelDependenciesBuilderImplHelper {
+
+ private static final String MODULE_PROPERTY = "ideaModule";
+ private static final String VERSION_PROPERTY = "version";
+ private static final String GROUP_PROPERTY = "group";
+
+
+ public static void attachGradleSdkSources(IdeaSingleEntryLibraryDependencyImpl libraryDependency,
+ IdeLocalFileDependency localFileDependency) {
+ final String libName = localFileDependency.getFile().getName();
+ if (localFileDependency.getFile() == null || !libName.startsWith("gradle-")) return;
+
+ File libOrPluginsFile = localFileDependency.getFile().getParentFile();
+ if (libOrPluginsFile != null && ("plugins".equals(libOrPluginsFile.getName()))) {
+ libOrPluginsFile = libOrPluginsFile.getParentFile();
+ }
+
+ if (libOrPluginsFile != null && "lib".equals(libOrPluginsFile.getName()) && libOrPluginsFile.getParentFile() != null) {
+ File srcDir = new File(libOrPluginsFile.getParentFile(), "src");
+ if (GradleVersion.current().compareTo(GradleVersion.version("1.9")) >= 0) {
+ int endIndex = libName.indexOf(GradleVersion.current().getVersion() + ".jar");
+ if (endIndex != -1) {
+ String srcDirChild = libName.substring("gradle-".length(), endIndex - 1);
+ srcDir = new File(srcDir, srcDirChild);
+ }
+ }
+
+ if (srcDir.isDirectory()) {
+ libraryDependency.setSource(srcDir);
+ }
+ }
+ }
+
+ @Nullable
+ public static String findDeDuplicatedModuleName(Project project) {
+ if (project.hasProperty(MODULE_PROPERTY)) {
+ Object ideaModule = project.property(MODULE_PROPERTY);
+ if (ideaModule instanceof GenerateIdeaModule) {
+ GenerateIdeaModule generateIdeaModule = (GenerateIdeaModule)ideaModule;
+ return generateIdeaModule.getModule().getName();
+ }
+ }
+ return null;
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeProjectDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ final Project project = dependency.getProject();
+ final String version = project.hasProperty(VERSION_PROPERTY) ? str(project.property(VERSION_PROPERTY)) : "";
+ final String group = project.hasProperty(GROUP_PROPERTY) ? str(project.property(GROUP_PROPERTY)) : "";
+
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, project.getName(), null, group, version, null);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ public static String str(Object o) {
+ return String.valueOf(o == null ? "" : o);
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeRepoFileDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ final ModuleVersionIdentifier dependencyId;
+ if (dependency instanceof UnresolvedIdeRepoFileDependency) {
+ UnresolvedIdeRepoFileDependency unresolvedDependency =
+ (UnresolvedIdeRepoFileDependency)dependency;
+ dependencyId = new MyModuleVersionIdentifier(unresolvedDependency.getFile().getName());
+ }
+ else {
+ dependencyId = dependency.getId();
+ }
+
+ String classifier = parseClassifier(dependencyId, dependency.getFile());
+ String dependencyFileName = null;
+ if (dependency.getFile() != null) {
+ dependencyFileName = dependency.getFile().getName();
+ }
+
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, dependencyId.getName(), dependencyFileName, dependencyId.getGroup(), dependencyId.getVersion(),
+ classifier);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ public static String parseClassifier(ModuleVersionIdentifier dependencyId, File dependencyFile) {
+ if (dependencyFile == null) return null;
+ String dependencyFileName = dependencyFile.getName();
+ int i = dependencyFileName.indexOf(dependencyId.getName() + '-' + dependencyId.getVersion() + '-');
+ return i != -1 ? dependencyFileName.substring(i, dependencyFileName.length()) : null;
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeLocalFileDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ String path = dependency.getFile().getPath();
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, path, dependency.getFile().getName(), "", "", null);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ /**
+ * Deduce configuration scope based on configuration name using gradle conventions.
+ * IDEA gradle plugin only 'plus' configuration used to support configuration based on a custom configuration (not conventional)
+ *
+ * @param configurationName gradle configuration name
+ * @param userScopes gradle IDEA plugin scopes map
+ * @return deduced scope
+ */
+ public static GradleDependencyScope deduceScope(String configurationName,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ GradleDependencyScope scope = GradleDependencyScope.fromName(configurationName);
+ for (Map.Entry<String, Map<String, Collection<Configuration>>> entry : userScopes.entrySet()) {
+ Collection<Configuration> plusConfigurations = entry.getValue().get("plus");
+ if (plusConfigurations == null) continue;
+
+ for (Configuration plus : plusConfigurations) {
+ if (plus.getName().equals(configurationName)) {
+ return GradleDependencyScope.fromIdeaMappingName(entry.getKey().toLowerCase());
+ }
+ }
+ }
+
+ return scope;
+ }
+
+ public static class MyModuleVersionIdentifier implements ModuleVersionIdentifier, Serializable {
+ private final String myName;
+
+ public MyModuleVersionIdentifier(String name) {
+
+ myName = name;
+ }
+
+ @Override
+ public String getVersion() {
+ return null;
+ }
+
+ @Override
+ public String getGroup() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public ModuleIdentifier getModule() {
+ return null;
+ }
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.12/gradle-tooling-extension-v1.12.iml b/plugins/gradle/tooling-extension-v1.12/gradle-tooling-extension-v1.12.iml
new file mode 100644
index 0000000..5100975
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/gradle-tooling-extension-v1.12.iml
@@ -0,0 +1,124 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="annotations" />
+ <orderEntry type="module" module-name="external-system-api" />
+ <orderEntry type="module" module-name="gradle-tooling-extension" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module" module-name="gradle" scope="TEST" />
+ <orderEntry type="module-library">
+ <library name="Gradle">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/gradle-tooling-api-1.12-20140210235036+0000.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-core-1.12-20140210235036+0000.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-base-services-1.12-20140210235036+0000.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-ide-1.12-20140210235036+0000.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/buildSrc/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/buildSrc/src/test/resources" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ui/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ui/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ui/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/cli/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/cpp/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/cpp/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ear/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ide/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ide/src/main/resources" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/ivy/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/core/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/core/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/core/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/core/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/osgi/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/osgi/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/antlr/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/jetty/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/maven/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/maven/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/scala/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/scala/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/jacoco/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/native/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/plugins/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/plugins/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/plugins/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/publish/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/wrapper/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/wrapper/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/announce/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/launcher/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/launcher/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/launcher/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/open-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/open-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/core-impl/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/core-impl/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/messaging/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/messaging/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/reporting/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/resources/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/javascript/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/diagnostics/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/diagnostics/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/diagnostics/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/performance/src/configPlugin" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/performance/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/tooling-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/tooling-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/tooling-api/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/code-quality/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/language-jvm/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/base-services/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/base-services/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/language-base/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-comparison/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/source/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/target/src/main/java" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/internal-testing/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/base-services-groovy/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-1.12-20140210235036+0000-src.zip!/gradle-1.12-20140210235036+0000/subprojects/base-services-groovy/src/test/groovy" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library name="GradleGuava">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/guava-jdk5-14.0.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="Groovy" level="project" />
+ </component>
+</module>
+
diff --git a/plugins/gradle/tooling-extension-v1.12/lib/gradle-1.12-20140210235036+0000-src.zip b/plugins/gradle/tooling-extension-v1.12/lib/gradle-1.12-20140210235036+0000-src.zip
new file mode 100644
index 0000000..afcf00f
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/lib/gradle-1.12-20140210235036+0000-src.zip
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.12/lib/gradle-base-services-1.12-20140210235036+0000.jar b/plugins/gradle/tooling-extension-v1.12/lib/gradle-base-services-1.12-20140210235036+0000.jar
new file mode 100644
index 0000000..5d03e15
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/lib/gradle-base-services-1.12-20140210235036+0000.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.12/lib/gradle-core-1.12-20140210235036+0000.jar b/plugins/gradle/tooling-extension-v1.12/lib/gradle-core-1.12-20140210235036+0000.jar
new file mode 100644
index 0000000..5fb4be6
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/lib/gradle-core-1.12-20140210235036+0000.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.12/lib/gradle-ide-1.12-20140210235036+0000.jar b/plugins/gradle/tooling-extension-v1.12/lib/gradle-ide-1.12-20140210235036+0000.jar
new file mode 100644
index 0000000..7e7d39f
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/lib/gradle-ide-1.12-20140210235036+0000.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.12/lib/gradle-tooling-api-1.12-20140210235036+0000.jar b/plugins/gradle/tooling-extension-v1.12/lib/gradle-tooling-api-1.12-20140210235036+0000.jar
new file mode 100644
index 0000000..ce2cf12
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/lib/gradle-tooling-api-1.12-20140210235036+0000.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.12/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension-v1.12/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
new file mode 100644
index 0000000..8af48ec
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -0,0 +1,17 @@
+#
+# Copyright 2000-2014 JetBrains s.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.
+#
+org.jetbrains.plugins.gradle.tooling.v1_12.builder.ModelDependenciesBuilderImpl
+org.jetbrains.plugins.gradle.tooling.v1_12.builder.ModelBuildScriptClasspathBuilderImpl
diff --git a/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/builder/ModelBuildScriptClasspathBuilderImpl.java b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/builder/ModelBuildScriptClasspathBuilderImpl.java
new file mode 100644
index 0000000..adaf5cb
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/builder/ModelBuildScriptClasspathBuilderImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_12.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.gradle.plugins.ide.internal.resolver.model.IdeExtendedRepoFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeLocalFileDependency;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.jetbrains.plugins.gradle.tooling.internal.BuildScriptClasspathModelImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.ClasspathEntryModelImpl;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+@TargetVersions("1.12+")
+public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService {
+
+ private final Map<String, BuildScriptClasspathModelImpl> cache = new ConcurrentHashMap<String, BuildScriptClasspathModelImpl>();
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return BuildScriptClasspathModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ BuildScriptClasspathModelImpl buildScriptClasspath = cache.get(project.getPath());
+ if (buildScriptClasspath != null) return buildScriptClasspath;
+
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ }
+ }
+
+ buildScriptClasspath = new BuildScriptClasspathModelImpl();
+ Project parent = project.getParent();
+ if (parent != null) {
+ BuildScriptClasspathModelImpl parentBuildScriptClasspath = (BuildScriptClasspathModelImpl)buildAll(modelName, parent);
+ if (parentBuildScriptClasspath != null) {
+ for (ClasspathEntryModel classpathEntryModel : parentBuildScriptClasspath.getClasspath()) {
+ buildScriptClasspath.add(classpathEntryModel);
+ }
+ }
+ }
+
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ final Configuration configuration = project.getBuildscript().getConfigurations().findByName("classpath");
+ Collection<Configuration> plusConfigurations = Collections.singletonList(configuration);
+
+ if (!offline) {
+ // download sources and/or javadoc
+ List<IdeExtendedRepoFileDependency> repoFileDependencies = dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+
+ for (IdeExtendedRepoFileDependency dependency : repoFileDependencies) {
+ if (dependency.getFile() == null) continue;
+
+ buildScriptClasspath.add(
+ new ClasspathEntryModelImpl(dependency.getFile(), dependency.getSourceFile(), dependency.getJavadocFile()));
+ }
+ }
+
+ final Collection<IdeLocalFileDependency> localFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeLocalFileDependency dependency : localFileDependencies) {
+ if (dependency.getFile() == null) continue;
+ buildScriptClasspath.add(new ClasspathEntryModelImpl(dependency.getFile(), null, null));
+ }
+
+ cache.put(project.getPath(), buildScriptClasspath);
+ return buildScriptClasspath;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/builder/ModelDependenciesBuilderImpl.java b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/builder/ModelDependenciesBuilderImpl.java
new file mode 100644
index 0000000..f21cda3
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/builder/ModelDependenciesBuilderImpl.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_12.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.gradle.plugins.ide.internal.resolver.model.IdeExtendedRepoFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeLocalFileDependency;
+import org.gradle.plugins.ide.internal.resolver.model.IdeProjectDependency;
+import org.gradle.tooling.model.idea.IdeaDependency;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.jetbrains.plugins.gradle.tooling.internal.*;
+import org.jetbrains.plugins.gradle.tooling.v1_12.internal.InternalDependencyVersionId;
+
+import java.util.*;
+
+import static org.jetbrains.plugins.gradle.tooling.v1_12.internal.ModelDependenciesBuilderImplHelper.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+@TargetVersions("1.12+")
+public class ModelDependenciesBuilderImpl implements ModelBuilderService {
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return ProjectDependenciesModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ final List<IdeaDependency> dependencies = new ArrayList<IdeaDependency>();
+
+ final Map<InternalDependencyVersionId, Scopes> scopesMap = new LinkedHashMap<InternalDependencyVersionId, Scopes>();
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+ Map<String, Map<String, Collection<Configuration>>> userScopes = Collections.emptyMap();
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ userScopes = ideaModel.getModule().getScopes();
+ }
+ }
+
+ for (final Configuration configuration : project.getConfigurations()) {
+ Collection<Configuration> plusConfigurations = new ArrayList<Configuration>();
+ plusConfigurations.add(configuration);
+
+ final Collection<IdeProjectDependency> ideProjectDependencies =
+ dependenciesExtractor.extractProjectDependencies(project, plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeProjectDependency ideProjectDependency : ideProjectDependencies) {
+ merge(scopesMap, ideProjectDependency, userScopes);
+ }
+
+ if (!offline) {
+ final Collection<IdeExtendedRepoFileDependency> ideRepoFileDependencies =
+ dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+ for (IdeExtendedRepoFileDependency repoFileDependency : ideRepoFileDependencies) {
+ merge(scopesMap, repoFileDependency, userScopes);
+ }
+ }
+
+ final Collection<IdeLocalFileDependency> ideLocalFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+ for (IdeLocalFileDependency fileDependency : ideLocalFileDependencies) {
+ merge(scopesMap, fileDependency, userScopes);
+ }
+ }
+
+ for (Map.Entry<InternalDependencyVersionId, Scopes> entry : scopesMap.entrySet()) {
+ InternalDependencyVersionId versionId = entry.getKey();
+ for (GradleDependencyScope scope : entry.getValue().getScopes()) {
+ if (versionId.getIdeDependency() instanceof IdeExtendedRepoFileDependency) {
+ IdeExtendedRepoFileDependency repoFileDependency =
+ (IdeExtendedRepoFileDependency)versionId.getIdeDependency();
+ IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ versionId.getName(),
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ libraryDependency.setFile(repoFileDependency.getFile());
+ libraryDependency.setSource(repoFileDependency.getSourceFile());
+ libraryDependency.setJavadoc(repoFileDependency.getJavadocFile());
+ dependencies.add(libraryDependency);
+ }
+ else if (versionId.getIdeDependency() instanceof IdeProjectDependency) {
+ IdeProjectDependency projectDependency =
+ (IdeProjectDependency)versionId.getIdeDependency();
+
+ String ideaModuleName = findDeDuplicatedModuleName(projectDependency.getProject());
+ if (ideaModuleName == null) {
+ ideaModuleName = versionId.getName();
+ }
+
+ IdeaModuleDependencyImpl moduleDependency = new IdeaModuleDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ ideaModuleName,
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ moduleDependency.setIdeaModule(new StubIdeaModule(ideaModuleName));
+ dependencies.add(moduleDependency);
+ }
+ else if (versionId.getIdeDependency() instanceof IdeLocalFileDependency) {
+ IdeLocalFileDependency fileDependency =
+ (IdeLocalFileDependency)versionId.getIdeDependency();
+ IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ versionId.getName(),
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ libraryDependency.setFile(fileDependency.getFile());
+ attachGradleSdkSources(libraryDependency, fileDependency);
+ dependencies.add(libraryDependency);
+ }
+ }
+ }
+
+ return new ProjectDependenciesModelImpl(project.getPath(), dependencies);
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/internal/InternalDependencyVersionId.java b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/internal/InternalDependencyVersionId.java
new file mode 100644
index 0000000..d37ebd5
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/internal/InternalDependencyVersionId.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_12.internal;
+
+import org.gradle.plugins.ide.internal.resolver.model.IdeDependency;
+import org.jetbrains.plugins.gradle.tooling.internal.DependencyVersionId;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class InternalDependencyVersionId extends DependencyVersionId {
+ private final IdeDependency myIdeDependency;
+
+ public InternalDependencyVersionId(IdeDependency dependency,
+ String name,
+ String artifactName,
+ String group,
+ String version,
+ String classifier) {
+ super(name, artifactName, group, version, classifier);
+ myIdeDependency = dependency;
+ }
+
+ public IdeDependency getIdeDependency() {
+ return myIdeDependency;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/internal/ModelDependenciesBuilderImplHelper.java b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/internal/ModelDependenciesBuilderImplHelper.java
new file mode 100644
index 0000000..7cf08c4
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.12/src/org/jetbrains/plugins/gradle/tooling/v1_12/internal/ModelDependenciesBuilderImplHelper.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_12.internal;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ModuleIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.plugins.ide.idea.GenerateIdeaModule;
+import org.gradle.plugins.ide.internal.resolver.model.*;
+import org.gradle.util.GradleVersion;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.tooling.internal.IdeaSingleEntryLibraryDependencyImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.Scopes;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/3/14
+ */
+public class ModelDependenciesBuilderImplHelper {
+
+ private static final String MODULE_PROPERTY = "ideaModule";
+ private static final String VERSION_PROPERTY = "version";
+ private static final String GROUP_PROPERTY = "group";
+
+
+ public static void attachGradleSdkSources(IdeaSingleEntryLibraryDependencyImpl libraryDependency,
+ IdeLocalFileDependency localFileDependency) {
+ final String libName = localFileDependency.getFile().getName();
+ if (localFileDependency.getFile() == null || !libName.startsWith("gradle-")) return;
+
+ File libOrPluginsFile = localFileDependency.getFile().getParentFile();
+ if (libOrPluginsFile != null && ("plugins".equals(libOrPluginsFile.getName()))) {
+ libOrPluginsFile = libOrPluginsFile.getParentFile();
+ }
+
+ if (libOrPluginsFile != null && "lib".equals(libOrPluginsFile.getName()) && libOrPluginsFile.getParentFile() != null) {
+ File srcDir = new File(libOrPluginsFile.getParentFile(), "src");
+ if (GradleVersion.current().compareTo(GradleVersion.version("1.9")) >= 0) {
+ int endIndex = libName.indexOf(GradleVersion.current().getVersion() + ".jar");
+ if (endIndex != -1) {
+ String srcDirChild = libName.substring("gradle-".length(), endIndex - 1);
+ srcDir = new File(srcDir, srcDirChild);
+ }
+ }
+
+ if (srcDir.isDirectory()) {
+ libraryDependency.setSource(srcDir);
+ }
+ }
+ }
+
+ @Nullable
+ public static String findDeDuplicatedModuleName(Project project) {
+ if (project.hasProperty(MODULE_PROPERTY)) {
+ Object ideaModule = project.property(MODULE_PROPERTY);
+ if (ideaModule instanceof GenerateIdeaModule) {
+ GenerateIdeaModule generateIdeaModule = (GenerateIdeaModule)ideaModule;
+ return generateIdeaModule.getModule().getName();
+ }
+ }
+ return null;
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeProjectDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ final Project project = dependency.getProject();
+ final String version = project.hasProperty(VERSION_PROPERTY) ? str(project.property(VERSION_PROPERTY)) : "";
+ final String group = project.hasProperty(GROUP_PROPERTY) ? str(project.property(GROUP_PROPERTY)) : "";
+
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, project.getName(), null, group, version, null);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ public static String str(Object o) {
+ return String.valueOf(o == null ? "" : o);
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeExtendedRepoFileDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ final ModuleVersionIdentifier dependencyId;
+ if (dependency instanceof UnresolvedIdeRepoFileDependency) {
+ UnresolvedIdeRepoFileDependency unresolvedDependency =
+ (UnresolvedIdeRepoFileDependency)dependency;
+ dependencyId = new MyModuleVersionIdentifier(unresolvedDependency.getFile().getName());
+ }
+ else {
+ dependencyId = dependency.getId();
+ }
+
+ String classifier = parseClassifier(dependencyId, dependency.getFile());
+ String dependencyFileName = null;
+ if (dependency.getFile() != null) {
+ dependencyFileName = dependency.getFile().getName();
+ }
+
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, dependencyId.getName(), dependencyFileName, dependencyId.getGroup(), dependencyId.getVersion(),
+ classifier);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ public static String parseClassifier(ModuleVersionIdentifier dependencyId, File dependencyFile) {
+ if (dependencyFile == null) return null;
+ String dependencyFileName = dependencyFile.getName();
+ int i = dependencyFileName.indexOf(dependencyId.getName() + '-' + dependencyId.getVersion() + '-');
+ return i != -1 ? dependencyFileName.substring(i, dependencyFileName.length()) : null;
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeLocalFileDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ String path = dependency.getFile().getPath();
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, path, dependency.getFile().getName(), "", "", null);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ /**
+ * Deduce configuration scope based on configuration name using gradle conventions.
+ * IDEA gradle plugin only 'plus' configuration used to support configuration based on a custom configuration (not conventional)
+ *
+ * @param configurationName gradle configuration name
+ * @param userScopes gradle IDEA plugin scopes map
+ * @return deduced scope
+ */
+ public static GradleDependencyScope deduceScope(String configurationName,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ GradleDependencyScope scope = GradleDependencyScope.fromName(configurationName);
+ for (Map.Entry<String, Map<String, Collection<Configuration>>> entry : userScopes.entrySet()) {
+ Collection<Configuration> plusConfigurations = entry.getValue().get("plus");
+ if (plusConfigurations == null) continue;
+
+ for (Configuration plus : plusConfigurations) {
+ if (plus.getName().equals(configurationName)) {
+ return GradleDependencyScope.fromIdeaMappingName(entry.getKey().toLowerCase());
+ }
+ }
+ }
+
+ return scope;
+ }
+
+ public static class MyModuleVersionIdentifier implements ModuleVersionIdentifier, Serializable {
+ private final String myName;
+
+ public MyModuleVersionIdentifier(String name) {
+
+ myName = name;
+ }
+
+ @Override
+ public String getVersion() {
+ return null;
+ }
+
+ @Override
+ public String getGroup() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public ModuleIdentifier getModule() {
+ return null;
+ }
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/gradle-tooling-extension-v1.9.iml b/plugins/gradle/tooling-extension-v1.9/gradle-tooling-extension-v1.9.iml
new file mode 100644
index 0000000..ab382ff
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/gradle-tooling-extension-v1.9.iml
@@ -0,0 +1,131 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="annotations" />
+ <orderEntry type="module" module-name="external-system-api" />
+ <orderEntry type="module" module-name="gradle" />
+ <orderEntry type="module" module-name="gradle-tooling-extension" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module-library">
+ <library name="Gradle">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/gradle-tooling-api-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-core-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-messaging-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-wrapper-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-base-services-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-native-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-build-init-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-plugins-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-ide-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-scala-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/lib/gradle-reporting-1.9.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/buildSrc/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/buildSrc/src/test/resources" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cli/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cpp/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cpp/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ear/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ide/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ide/src/main/resources" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/osgi/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/osgi/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/antlr/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/jetty/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/maven/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/maven/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/scala/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/scala/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/jacoco/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/native/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/publish/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/wrapper/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/wrapper/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/announce/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/open-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/open-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core-impl/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core-impl/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/messaging/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/messaging/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/reporting/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/resources/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/javascript/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/performance/src/configPlugin" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/performance/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/code-quality/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-base/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/source/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/target/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/internal-testing/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services-groovy/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services-groovy/src/test/groovy" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library name="GradleGuava">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/guava-jdk5-14.0.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="Groovy" level="project" />
+ </component>
+</module>
+
diff --git a/plugins/gradle/lib/gradle-build-init-1.9.jar b/plugins/gradle/tooling-extension-v1.9/lib/gradle-build-init-1.9.jar
similarity index 100%
copy from plugins/gradle/lib/gradle-build-init-1.9.jar
copy to plugins/gradle/tooling-extension-v1.9/lib/gradle-build-init-1.9.jar
Binary files differ
diff --git a/plugins/gradle/lib/gradle-ide-1.9.jar b/plugins/gradle/tooling-extension-v1.9/lib/gradle-ide-1.9.jar
similarity index 100%
copy from plugins/gradle/lib/gradle-ide-1.9.jar
copy to plugins/gradle/tooling-extension-v1.9/lib/gradle-ide-1.9.jar
Binary files differ
diff --git a/plugins/gradle/lib/gradle-plugins-1.9.jar b/plugins/gradle/tooling-extension-v1.9/lib/gradle-plugins-1.9.jar
similarity index 100%
copy from plugins/gradle/lib/gradle-plugins-1.9.jar
copy to plugins/gradle/tooling-extension-v1.9/lib/gradle-plugins-1.9.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.9/lib/gradle-reporting-1.9.jar b/plugins/gradle/tooling-extension-v1.9/lib/gradle-reporting-1.9.jar
new file mode 100644
index 0000000..5315525
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/lib/gradle-reporting-1.9.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.9/lib/gradle-scala-1.9.jar b/plugins/gradle/tooling-extension-v1.9/lib/gradle-scala-1.9.jar
new file mode 100644
index 0000000..aa6a20a
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/lib/gradle-scala-1.9.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension-v1.9/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension-v1.9/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
new file mode 100644
index 0000000..88d8207
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -0,0 +1,20 @@
+#
+# Copyright 2000-2014 JetBrains s.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.
+#
+org.jetbrains.plugins.gradle.tooling.v1_9.builder.WarModelBuilderImpl
+org.jetbrains.plugins.gradle.tooling.v1_9.builder.ModelDependenciesBuilderImpl
+org.jetbrains.plugins.gradle.tooling.v1_9.builder.ModuleExtendedModelBuilderImpl
+org.jetbrains.plugins.gradle.tooling.v1_9.builder.ModelBuildScriptClasspathBuilderImpl
+org.jetbrains.plugins.gradle.tooling.v1_9.builder.ScalaModelBuilderImpl
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModelBuildScriptClasspathBuilderImpl.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModelBuildScriptClasspathBuilderImpl.java
new file mode 100644
index 0000000..b4de8ba
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModelBuildScriptClasspathBuilderImpl.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_9.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.jetbrains.plugins.gradle.tooling.internal.BuildScriptClasspathModelImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.ClasspathEntryModelImpl;
+
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+@TargetVersions("1.8 <=> 1.10")
+public class ModelBuildScriptClasspathBuilderImpl implements ModelBuilderService {
+
+ private final Map<String, BuildScriptClasspathModelImpl> cache = new ConcurrentHashMap<String, BuildScriptClasspathModelImpl>();
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return BuildScriptClasspathModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+ BuildScriptClasspathModelImpl buildScriptClasspath = cache.get(project.getPath());
+ if (buildScriptClasspath != null) return buildScriptClasspath;
+
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ }
+ }
+
+ buildScriptClasspath = new BuildScriptClasspathModelImpl();
+ Project parent = project.getParent();
+ if (parent != null) {
+ BuildScriptClasspathModelImpl parentBuildScriptClasspath = (BuildScriptClasspathModelImpl)buildAll(modelName, parent);
+ if (parentBuildScriptClasspath != null) {
+ for (ClasspathEntryModel classpathEntryModel : parentBuildScriptClasspath.getClasspath()) {
+ buildScriptClasspath.add(classpathEntryModel);
+ }
+ }
+ }
+
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ final Configuration configuration = project.getBuildscript().getConfigurations().findByName("classpath");
+ Collection<Configuration> plusConfigurations = Collections.singletonList(configuration);
+
+ if (!offline) {
+ // download sources and/or javadoc
+ List<IdeDependenciesExtractor.IdeRepoFileDependency> repoFileDependencies = dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+
+ for (IdeDependenciesExtractor.IdeRepoFileDependency dependency : repoFileDependencies) {
+ if (dependency.getFile() == null) continue;
+
+ buildScriptClasspath.add(
+ new ClasspathEntryModelImpl(dependency.getFile(), dependency.getSourceFile(), dependency.getJavadocFile()));
+ }
+ }
+
+ final List<IdeDependenciesExtractor.IdeLocalFileDependency> localFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeDependenciesExtractor.IdeLocalFileDependency dependency : localFileDependencies) {
+ if (dependency.getFile() == null) continue;
+ buildScriptClasspath.add(new ClasspathEntryModelImpl(dependency.getFile(), null, null));
+ }
+
+ cache.put(project.getPath(), buildScriptClasspath);
+ return buildScriptClasspath;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModelDependenciesBuilderImpl.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModelDependenciesBuilderImpl.java
new file mode 100644
index 0000000..72c3ddb
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModelDependenciesBuilderImpl.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_9.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.gradle.tooling.model.idea.IdeaDependency;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.jetbrains.plugins.gradle.tooling.internal.*;
+import org.jetbrains.plugins.gradle.tooling.v1_9.internal.InternalDependencyVersionId;
+import org.jetbrains.plugins.gradle.tooling.v1_9.internal.ModelDependenciesBuilderImplHelper;
+
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+@TargetVersions("1.8 <=> 1.10")
+public class ModelDependenciesBuilderImpl implements ModelBuilderService {
+ @Override
+ public boolean canBuild(String modelName) {
+ return ProjectDependenciesModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(final String modelName, final Project project) {
+
+ final List<IdeaDependency> dependencies = new ArrayList<IdeaDependency>();
+
+ final Map<InternalDependencyVersionId, Scopes> scopesMap = new LinkedHashMap<InternalDependencyVersionId, Scopes>();
+ final IdeDependenciesExtractor dependenciesExtractor = new IdeDependenciesExtractor();
+
+ boolean offline = false;
+ boolean downloadJavadoc = false;
+ boolean downloadSources = true;
+
+ final IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+ Map<String, Map<String, Collection<Configuration>>> userScopes = Collections.emptyMap();
+ if (ideaPlugin != null) {
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel != null && ideaModel.getModule() != null) {
+ offline = ideaModel.getModule().isOffline();
+ downloadJavadoc = ideaModel.getModule().isDownloadJavadoc();
+ downloadSources = ideaModel.getModule().isDownloadSources();
+ userScopes = ideaModel.getModule().getScopes();
+ }
+ }
+
+ for (final Configuration configuration : project.getConfigurations()) {
+ Collection<Configuration> plusConfigurations = new ArrayList<Configuration>();
+ plusConfigurations.add(configuration);
+
+ final List<IdeDependenciesExtractor.IdeProjectDependency> ideProjectDependencies =
+ dependenciesExtractor.extractProjectDependencies(plusConfigurations, new ArrayList<Configuration>());
+
+ for (IdeDependenciesExtractor.IdeProjectDependency ideProjectDependency : ideProjectDependencies) {
+ ModelDependenciesBuilderImplHelper.merge(scopesMap, ideProjectDependency, userScopes);
+ }
+
+ if (!offline) {
+ final Collection<IdeDependenciesExtractor.IdeRepoFileDependency> ideRepoFileDependencies =
+ dependenciesExtractor.extractRepoFileDependencies(
+ project.getConfigurations(), plusConfigurations, new ArrayList<Configuration>(), downloadSources, downloadJavadoc);
+ for (IdeDependenciesExtractor.IdeRepoFileDependency repoFileDependency : ideRepoFileDependencies) {
+ ModelDependenciesBuilderImplHelper.merge(scopesMap, repoFileDependency, userScopes);
+ }
+ }
+
+ final List<IdeDependenciesExtractor.IdeLocalFileDependency> ideLocalFileDependencies =
+ dependenciesExtractor.extractLocalFileDependencies(plusConfigurations, new ArrayList<Configuration>());
+ for (IdeDependenciesExtractor.IdeLocalFileDependency fileDependency : ideLocalFileDependencies) {
+ ModelDependenciesBuilderImplHelper.merge(scopesMap, fileDependency, userScopes);
+ }
+ }
+
+ for (Map.Entry<InternalDependencyVersionId, Scopes> entry : scopesMap.entrySet()) {
+ InternalDependencyVersionId versionId = entry.getKey();
+ for (GradleDependencyScope scope : entry.getValue().getScopes()) {
+ if (versionId.getIdeDependency() instanceof IdeDependenciesExtractor.IdeRepoFileDependency) {
+ IdeDependenciesExtractor.IdeRepoFileDependency repoFileDependency =
+ (IdeDependenciesExtractor.IdeRepoFileDependency)versionId.getIdeDependency();
+ IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ versionId.getName(),
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ libraryDependency.setFile(repoFileDependency.getFile());
+ libraryDependency.setSource(repoFileDependency.getSourceFile());
+ libraryDependency.setJavadoc(repoFileDependency.getJavadocFile());
+ dependencies.add(libraryDependency);
+ }
+ else if (versionId.getIdeDependency() instanceof IdeDependenciesExtractor.IdeProjectDependency) {
+ IdeDependenciesExtractor.IdeProjectDependency projectDependency =
+ (IdeDependenciesExtractor.IdeProjectDependency)versionId.getIdeDependency();
+
+ String ideaModuleName = ModelDependenciesBuilderImplHelper.findDeDuplicatedModuleName(projectDependency.getProject());
+ if (ideaModuleName == null) {
+ ideaModuleName = versionId.getName();
+ }
+
+ IdeaModuleDependencyImpl moduleDependency = new IdeaModuleDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ ideaModuleName,
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ moduleDependency.setIdeaModule(new StubIdeaModule(ideaModuleName));
+ dependencies.add(moduleDependency);
+ }
+ else if (versionId.getIdeDependency() instanceof IdeDependenciesExtractor.IdeLocalFileDependency) {
+ IdeDependenciesExtractor.IdeLocalFileDependency fileDependency =
+ (IdeDependenciesExtractor.IdeLocalFileDependency)versionId.getIdeDependency();
+ IdeaSingleEntryLibraryDependencyImpl libraryDependency = new IdeaSingleEntryLibraryDependencyImpl(
+ new IdeaDependencyScopeImpl(scope),
+ versionId.getName(),
+ versionId.getGroup(),
+ versionId.getVersion(),
+ versionId.getClassifier()
+ );
+ libraryDependency.setFile(fileDependency.getFile());
+ ModelDependenciesBuilderImplHelper.attachGradleSdkSources(libraryDependency, fileDependency);
+ dependencies.add(libraryDependency);
+ }
+ }
+ }
+
+ return new ProjectDependenciesModelImpl(project.getPath(), dependencies);
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModuleExtendedModelBuilderImpl.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModuleExtendedModelBuilderImpl.java
new file mode 100644
index 0000000..42d20e9
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ModuleExtendedModelBuilderImpl.java
@@ -0,0 +1,237 @@
+/*
+ * 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.gradle.tooling.v1_9.builder;
+
+import groovy.lang.GroovyObject;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.tasks.SourceSet;
+import org.gradle.api.tasks.SourceSetContainer;
+import org.gradle.api.tasks.bundling.Jar;
+import org.gradle.api.tasks.testing.Test;
+import org.gradle.plugins.ide.idea.IdeaPlugin;
+import org.gradle.plugins.ide.idea.model.IdeaModel;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
+import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.internal.IdeaContentRootImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.IdeaSourceDirectoryImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.ModuleExtendedModelImpl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+public class ModuleExtendedModelBuilderImpl implements ModelBuilderService {
+
+ private static final String SOURCE_SETS_PROPERTY = "sourceSets";
+ private static final String TEST_SRC_DIRS_PROPERTY = "testSrcDirs";
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return ModuleExtendedModel.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(String modelName, Project project) {
+
+ final String moduleName = project.getName();
+ final String moduleGroup = project.getGroup().toString();
+ final String moduleVersion = project.getVersion().toString();
+
+ final ModuleExtendedModelImpl moduleVersionModel = new ModuleExtendedModelImpl(moduleName, moduleGroup, moduleVersion);
+
+ final List<File> artifacts = new ArrayList<File>();
+ for (Task task : project.getTasks()) {
+ if (task instanceof Jar) {
+ Jar jar = (Jar)task;
+ artifacts.add(jar.getArchivePath());
+ }
+ }
+
+ moduleVersionModel.setArtifacts(artifacts);
+
+ final Set<String> sourceDirectories = new HashSet<String>();
+ final Set<String> testDirectories = new HashSet<String>();
+ final Set<String> resourceDirectories = new HashSet<String>();
+ final Set<String> testResourceDirectories = new HashSet<String>();
+
+ final List<File> testClassesDirs = new ArrayList<File>();
+ for (Task task : project.getTasks()) {
+ if (task instanceof Test) {
+ Test test = (Test)task;
+ testClassesDirs.add(test.getTestClassesDir());
+
+ if (test.hasProperty(TEST_SRC_DIRS_PROPERTY)) {
+ Object testSrcDirs = test.property(TEST_SRC_DIRS_PROPERTY);
+ if (testSrcDirs instanceof Iterable) {
+ for (Object dir : Iterable.class.cast(testSrcDirs)) {
+ addFilePath(testDirectories, dir);
+ }
+ }
+ }
+ }
+ }
+
+ if (project.hasProperty(SOURCE_SETS_PROPERTY)) {
+ Object sourceSets = project.property(SOURCE_SETS_PROPERTY);
+ if (sourceSets instanceof SourceSetContainer) {
+ SourceSetContainer sourceSetContainer = (SourceSetContainer)sourceSets;
+ for (SourceSet sourceSet : sourceSetContainer) {
+ for (File javaSrcDir : sourceSet.getJava().getSrcDirs()) {
+ boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
+ addFilePath(isTestDir ? testDirectories : sourceDirectories, javaSrcDir);
+ }
+ for (File resourcesSrcDir : sourceSet.getResources().getSrcDirs()) {
+ boolean isTestDir = isTestDir(sourceSet, testClassesDirs);
+ addFilePath(isTestDir ? testResourceDirectories : resourceDirectories, resourcesSrcDir);
+ }
+ }
+ }
+ }
+
+ File projectDir = project.getProjectDir();
+ IdeaContentRootImpl contentRoot = new IdeaContentRootImpl(projectDir);
+
+ final Set<String> ideaSourceDirectories = new HashSet<String>();
+ final Set<String> ideaTestDirectories = new HashSet<String>();
+ final Set<String> ideaExtResourceDirectories = new HashSet<String>();
+ final Set<String> ideaExtTestResourceDirectories = new HashSet<String>();
+ final Set<File> excludeDirectories = new HashSet<File>();
+
+ enrichDataFromIdeaPlugin(project, excludeDirectories, ideaSourceDirectories, ideaTestDirectories,
+ ideaExtResourceDirectories, ideaExtTestResourceDirectories);
+
+ if (ideaSourceDirectories.isEmpty()) {
+ sourceDirectories.clear();
+ resourceDirectories.clear();
+ }
+ if (ideaTestDirectories.isEmpty()) {
+ testDirectories.clear();
+ testResourceDirectories.clear();
+ }
+
+ ideaSourceDirectories.removeAll(resourceDirectories);
+ sourceDirectories.removeAll(ideaTestDirectories);
+ sourceDirectories.addAll(ideaSourceDirectories);
+ ideaTestDirectories.removeAll(testResourceDirectories);
+ testDirectories.addAll(ideaTestDirectories);
+
+ resourceDirectories.removeAll(ideaExtTestResourceDirectories);
+ resourceDirectories.addAll(ideaExtResourceDirectories);
+ testResourceDirectories.removeAll(ideaExtResourceDirectories);
+ testResourceDirectories.addAll(ideaExtTestResourceDirectories);
+
+ // ensure disjoint directories with different type
+ resourceDirectories.removeAll(sourceDirectories);
+ testDirectories.removeAll(sourceDirectories);
+ testResourceDirectories.removeAll(testDirectories);
+
+ for (String javaDir : sourceDirectories) {
+ contentRoot.addSourceDirectory(new IdeaSourceDirectoryImpl(new File(javaDir)));
+ }
+ for (String testDir : testDirectories) {
+ contentRoot.addTestDirectory(new IdeaSourceDirectoryImpl(new File(testDir)));
+ }
+ for (String resourceDir : resourceDirectories) {
+ contentRoot.addResourceDirectory(new IdeaSourceDirectoryImpl(new File(resourceDir)));
+ }
+ for (String testResourceDir : testResourceDirectories) {
+ contentRoot.addTestResourceDirectory(new IdeaSourceDirectoryImpl(new File(testResourceDir)));
+ }
+ for (File excludeDir : excludeDirectories) {
+ contentRoot.addExcludeDirectory(excludeDir);
+ }
+
+ moduleVersionModel.setContentRoots(Collections.<ExtIdeaContentRoot>singleton(contentRoot));
+ return moduleVersionModel;
+ }
+
+ private static boolean isTestDir(SourceSet sourceSet, List<File> testClassesDirs) {
+ if (SourceSet.TEST_SOURCE_SET_NAME.equals(sourceSet.getName())) return true;
+ if (SourceSet.MAIN_SOURCE_SET_NAME.equals(sourceSet.getName())) return false;
+
+ File sourceSetClassesDir = sourceSet.getOutput().getClassesDir();
+ for (File testClassesDir : testClassesDirs) {
+ do {
+ if (sourceSetClassesDir.getPath().equals(testClassesDir.getPath())) return true;
+ }
+ while ((testClassesDir = testClassesDir.getParentFile()) != null);
+ }
+
+ return false;
+ }
+
+ private static void addFilePath(Set<String> filePathSet, Object file) {
+ if (file instanceof File) {
+ try {
+ filePathSet.add(((File)file).getCanonicalPath());
+ }
+ catch (IOException ignore) {
+ }
+ }
+ }
+
+ private static void enrichDataFromIdeaPlugin(Project project,
+ Set<File> excludeDirectories,
+ Set<String> javaDirectories,
+ Set<String> testDirectories,
+ Set<String> ideaExtResourceDirectories,
+ Set<String> ideaExtTestResourceDirectories) {
+
+ IdeaPlugin ideaPlugin = project.getPlugins().getPlugin(IdeaPlugin.class);
+ if (ideaPlugin == null) return;
+
+ IdeaModel ideaModel = ideaPlugin.getModel();
+ if (ideaModel == null || ideaModel.getModule() == null) return;
+
+ for (File excludeDir : ideaModel.getModule().getExcludeDirs()) {
+ excludeDirectories.add(excludeDir);
+ }
+ for (File file : ideaModel.getModule().getSourceDirs()) {
+ javaDirectories.add(file.getPath());
+ }
+ for (File file : ideaModel.getModule().getTestSourceDirs()) {
+ testDirectories.add(file.getPath());
+ }
+
+ ideaExtResourceDirectories.addAll(getExtDirs("resourceDirs", ideaModel.getModule()));
+ ideaExtTestResourceDirectories.addAll(getExtDirs("testResourceDirs", ideaModel.getModule()));
+ }
+
+ private static List<String> getExtDirs(String propertyName, GroovyObject ideaModule) {
+ List<String> directories = new ArrayList<String>();
+ Object resourceDirs = ideaModule.getProperty(propertyName);
+ if (resourceDirs instanceof Iterable) {
+ for (Object o : Iterable.class.cast(resourceDirs)) {
+ if (o instanceof File) {
+ directories.add(File.class.cast(o).getPath());
+ }
+ else if (o instanceof String) {
+ directories.add((String)o);
+ }
+ }
+ }
+
+ return directories;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ScalaModelBuilderImpl.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ScalaModelBuilderImpl.java
new file mode 100644
index 0000000..b885b7f
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/ScalaModelBuilderImpl.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_9.builder;
+
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.plugins.scala.ScalaPlugin;
+import org.gradle.api.tasks.scala.ScalaCompile;
+import org.gradle.api.tasks.scala.ScalaCompileOptions;
+import org.gradle.api.tasks.scala.ScalaForkOptions;
+import org.jetbrains.annotations.Contract;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ScalaModel;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.internal.scala.ScalaCompileOptionsImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.scala.ScalaForkOptionsImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.scala.ScalaModelImpl;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public class ScalaModelBuilderImpl implements ModelBuilderService {
+
+ private static final String COMPILE_SCALA_TASK = "compileScala";
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return ScalaModel.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ final ScalaPlugin scalaPlugin = project.getPlugins().findPlugin(ScalaPlugin.class);
+ if (scalaPlugin == null) return null;
+
+ final ScalaModelImpl scalaModel = new ScalaModelImpl();
+
+ for (Task task : project.getTasks()) {
+ if (task instanceof ScalaCompile && COMPILE_SCALA_TASK.equals(task.getName())) {
+ ScalaCompile scalaCompile = (ScalaCompile)task;
+ scalaModel.setScalaClasspath(scalaCompile.getScalaClasspath().getFiles());
+ scalaModel.setZincClasspath(scalaCompile.getZincClasspath().getFiles());
+ scalaModel.setScalaCompileOptions(create(scalaCompile.getScalaCompileOptions()));
+ scalaModel.setTargetCompatibility(scalaCompile.getTargetCompatibility());
+ scalaModel.setSourceCompatibility(scalaCompile.getSourceCompatibility());
+ break;
+ }
+ }
+
+ return scalaModel;
+ }
+
+ @Nullable
+ @Contract("null -> null")
+ private static ScalaCompileOptionsImpl create(@Nullable ScalaCompileOptions options) {
+ if (options == null) return null;
+
+ ScalaCompileOptionsImpl result = new ScalaCompileOptionsImpl();
+ result.setAdditionalParameters(options.getAdditionalParameters());
+ result.setDaemonServer(options.getDaemonServer());
+ result.setDebugLevel(options.getDebugLevel());
+ result.setDeprecation(options.isDeprecation());
+ result.setEncoding(options.getEncoding());
+ result.setFailOnError(options.isFailOnError());
+ result.setForce(options.getForce());
+ result.setFork(options.isFork());
+ result.setForkOptions(create(options.getForkOptions()));
+ result.setListFiles(options.isListFiles());
+ result.setLoggingLevel(options.getLoggingLevel());
+ result.setDebugLevel(options.getDebugLevel());
+ result.setLoggingPhases(options.getLoggingPhases());
+ result.setOptimize(options.isOptimize());
+ result.setUnchecked(options.isUnchecked());
+ result.setUseAnt(options.isUseAnt());
+ result.setUseCompileDaemon(options.isUseCompileDaemon());
+
+ return result;
+ }
+
+ @Nullable
+ @Contract("null -> null")
+ private static ScalaForkOptionsImpl create(@Nullable ScalaForkOptions forkOptions) {
+ if (forkOptions == null) return null;
+
+ ScalaForkOptionsImpl result = new ScalaForkOptionsImpl();
+ result.setJvmArgs(forkOptions.getJvmArgs());
+ result.setMemoryInitialSize(forkOptions.getMemoryInitialSize());
+ result.setMemoryMaximumSize(forkOptions.getMemoryMaximumSize());
+ return result;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/WarModelBuilderImpl.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/WarModelBuilderImpl.java
new file mode 100644
index 0000000..2060653
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/builder/WarModelBuilderImpl.java
@@ -0,0 +1,130 @@
+/*
+ * 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.gradle.tooling.v1_9.builder;
+
+import org.gradle.api.Action;
+import org.gradle.api.Project;
+import org.gradle.api.Task;
+import org.gradle.api.file.FileVisitDetails;
+import org.gradle.api.file.FileVisitor;
+import org.gradle.api.internal.file.copy.CopySpecInternal;
+import org.gradle.api.java.archives.Manifest;
+import org.gradle.api.plugins.WarPlugin;
+import org.gradle.api.tasks.bundling.War;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.WebConfiguration;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.internal.WarModelImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.WebConfigurationImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.WebResourceImpl;
+
+import java.io.File;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+public class WarModelBuilderImpl implements ModelBuilderService {
+
+ private static final String WEB_APP_DIR_PROPERTY = "webAppDir";
+ private static final String WEB_APP_DIR_NAME_PROPERTY = "webAppDirName";
+
+ @Override
+ public boolean canBuild(String modelName) {
+ return WebConfiguration.class.getName().equals(modelName);
+ }
+
+ @Nullable
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ final WarPlugin warPlugin = project.getPlugins().findPlugin(WarPlugin.class);
+ if (warPlugin == null) return null;
+
+ final String webAppDirName = !project.hasProperty(WEB_APP_DIR_NAME_PROPERTY) ?
+ "src/main/webapp" : String.valueOf(project.property(WEB_APP_DIR_NAME_PROPERTY));
+
+ final File webAppDir = !project.hasProperty(WEB_APP_DIR_PROPERTY)
+ ? new File(project.getProjectDir(), webAppDirName)
+ : (File)project.property(WEB_APP_DIR_PROPERTY);
+
+
+ List<WebConfiguration.WarModel> warModels = new ArrayList<WebConfiguration.WarModel>();
+
+
+ for (Task task : project.getTasks()) {
+ if (task instanceof War) {
+ final WarModelImpl warModel =
+ new WarModelImpl(((War)task).getArchiveName(), webAppDirName, webAppDir);
+ final List<WebConfiguration.WebResource> webResources = new ArrayList<WebConfiguration.WebResource>();
+
+ final War warTask = (War)task;
+ warModel.setWebXml(warTask.getWebXml());
+
+ warTask.getRootSpec().walk(new Action<CopySpecInternal>() {
+ @Override
+ public void execute(CopySpecInternal internal) {
+ final String relativePath = internal.getDestPath().getPathString();
+ internal.getSource().visit(new FileVisitor() {
+ @Override
+ public void visitDir(FileVisitDetails dirDetails) {
+ try {
+ addPath(webResources, relativePath, dirDetails.getPath(), dirDetails.getFile());
+ }
+ catch (Exception ignore) {
+ }
+ }
+
+ @Override
+ public void visitFile(FileVisitDetails fileDetails) {
+ try {
+ if (warTask.getWebXml() == null ||
+ !fileDetails.getFile().getCanonicalPath().equals(warTask.getWebXml().getCanonicalPath())) {
+ addPath(webResources, relativePath, fileDetails.getPath(), fileDetails.getFile());
+ }
+ }
+ catch (Exception ignore) {
+ }
+ }
+ });
+ }
+ });
+
+ warModel.setWebResources(webResources);
+ warModel.setClasspath(warTask.getClasspath().getFiles());
+
+ Manifest manifest = warTask.getManifest();
+ if (manifest != null) {
+ StringWriter writer = new StringWriter();
+ manifest.writeTo(writer);
+ warModel.setManifestContent(writer.toString());
+ }
+ warModels.add(warModel);
+ }
+ }
+
+ return new WebConfigurationImpl(warModels);
+ }
+
+ private static void addPath(List<WebConfiguration.WebResource> webResources, String warRelativePath, String fileRelativePath, File file) {
+ warRelativePath = warRelativePath == null ? "" : warRelativePath;
+
+ WebConfiguration.WebResource webResource = new WebResourceImpl(warRelativePath, fileRelativePath, file);
+ webResources.add(webResource);
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/internal/InternalDependencyVersionId.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/internal/InternalDependencyVersionId.java
new file mode 100644
index 0000000..5d5fda7
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/internal/InternalDependencyVersionId.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_9.internal;
+
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.jetbrains.plugins.gradle.tooling.internal.DependencyVersionId;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class InternalDependencyVersionId extends DependencyVersionId {
+ private final IdeDependenciesExtractor.IdeDependency myIdeDependency;
+
+ public InternalDependencyVersionId(IdeDependenciesExtractor.IdeDependency dependency,
+ String name,
+ String artifactName,
+ String group,
+ String version,
+ String classifier) {
+ super(name, artifactName, group, version, classifier);
+ myIdeDependency = dependency;
+ }
+
+ public IdeDependenciesExtractor.IdeDependency getIdeDependency() {
+ return myIdeDependency;
+ }
+}
diff --git a/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/internal/ModelDependenciesBuilderImplHelper.java b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/internal/ModelDependenciesBuilderImplHelper.java
new file mode 100644
index 0000000..183938a
--- /dev/null
+++ b/plugins/gradle/tooling-extension-v1.9/src/org/jetbrains/plugins/gradle/tooling/v1_9/internal/ModelDependenciesBuilderImplHelper.java
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.v1_9.internal;
+
+import org.gradle.api.Project;
+import org.gradle.api.artifacts.Configuration;
+import org.gradle.api.artifacts.ModuleIdentifier;
+import org.gradle.api.artifacts.ModuleVersionIdentifier;
+import org.gradle.plugins.ide.idea.GenerateIdeaModule;
+import org.gradle.plugins.ide.internal.IdeDependenciesExtractor;
+import org.gradle.util.GradleVersion;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.tooling.internal.IdeaSingleEntryLibraryDependencyImpl;
+import org.jetbrains.plugins.gradle.tooling.internal.Scopes;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/3/14
+ */
+public class ModelDependenciesBuilderImplHelper {
+
+ private static final String MODULE_PROPERTY = "ideaModule";
+ private static final String VERSION_PROPERTY = "version";
+ private static final String GROUP_PROPERTY = "group";
+
+
+ public static void attachGradleSdkSources(IdeaSingleEntryLibraryDependencyImpl libraryDependency,
+ IdeDependenciesExtractor.IdeLocalFileDependency localFileDependency) {
+ final String libName = localFileDependency.getFile().getName();
+ if (localFileDependency.getFile() == null || !libName.startsWith("gradle-")) return;
+
+ File libOrPluginsFile = localFileDependency.getFile().getParentFile();
+ if (libOrPluginsFile != null && ("plugins".equals(libOrPluginsFile.getName()))) {
+ libOrPluginsFile = libOrPluginsFile.getParentFile();
+ }
+
+ if (libOrPluginsFile != null && "lib".equals(libOrPluginsFile.getName()) && libOrPluginsFile.getParentFile() != null) {
+ File srcDir = new File(libOrPluginsFile.getParentFile(), "src");
+ if (GradleVersion.current().compareTo(GradleVersion.version("1.9")) >= 0) {
+ int endIndex = libName.indexOf(GradleVersion.current().getVersion() + ".jar");
+ if (endIndex != -1) {
+ String srcDirChild = libName.substring("gradle-".length(), endIndex - 1);
+ srcDir = new File(srcDir, srcDirChild);
+ }
+ }
+
+ if (srcDir.isDirectory()) {
+ libraryDependency.setSource(srcDir);
+ }
+ }
+ }
+
+ @Nullable
+ public static String findDeDuplicatedModuleName(Project project) {
+ if (project.hasProperty(MODULE_PROPERTY)) {
+ Object ideaModule = project.property(MODULE_PROPERTY);
+ if (ideaModule instanceof GenerateIdeaModule) {
+ GenerateIdeaModule generateIdeaModule = (GenerateIdeaModule)ideaModule;
+ return generateIdeaModule.getModule().getName();
+ }
+ }
+ return null;
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeDependenciesExtractor.IdeProjectDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ final Project project = dependency.getProject();
+ final String version = project.hasProperty(VERSION_PROPERTY) ? str(project.property(VERSION_PROPERTY)) : "";
+ final String group = project.hasProperty(GROUP_PROPERTY) ? str(project.property(GROUP_PROPERTY)) : "";
+
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, project.getName(), null, group, version, null);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ public static String str(Object o) {
+ return String.valueOf(o == null ? "" : o);
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeDependenciesExtractor.IdeRepoFileDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ final ModuleVersionIdentifier dependencyId;
+ if (dependency instanceof IdeDependenciesExtractor.UnresolvedIdeRepoFileDependency) {
+ IdeDependenciesExtractor.UnresolvedIdeRepoFileDependency unresolvedDependency =
+ (IdeDependenciesExtractor.UnresolvedIdeRepoFileDependency)dependency;
+ dependencyId = new MyModuleVersionIdentifier(unresolvedDependency.getFile().getName());
+ }
+ else {
+ dependencyId = dependency.getId();
+ }
+
+ String classifier = parseClassifier(dependencyId, dependency.getFile());
+ String dependencyFileName = null;
+ if (dependency.getFile() != null) {
+ dependencyFileName = dependency.getFile().getName();
+ }
+
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, dependencyId.getName(), dependencyFileName, dependencyId.getGroup(), dependencyId.getVersion(),
+ classifier);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ public static String parseClassifier(ModuleVersionIdentifier dependencyId, File dependencyFile) {
+ if (dependencyFile == null) return null;
+ String dependencyFileName = dependencyFile.getName();
+ int i = dependencyFileName.indexOf(dependencyId.getName() + '-' + dependencyId.getVersion() + '-');
+ return i != -1 ? dependencyFileName.substring(i, dependencyFileName.length()) : null;
+ }
+
+ public static void merge(Map<InternalDependencyVersionId, Scopes> map,
+ IdeDependenciesExtractor.IdeLocalFileDependency dependency,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+
+ final String configurationName = dependency.getDeclaredConfiguration().getName();
+ final GradleDependencyScope scope = deduceScope(configurationName, userScopes);
+ if (scope == null) return;
+
+ String path = dependency.getFile().getPath();
+ InternalDependencyVersionId versionId =
+ new InternalDependencyVersionId(dependency, path, dependency.getFile().getName(), "", "", null);
+ Scopes scopes = map.get(versionId);
+ if (scopes == null) {
+ map.put(versionId, new Scopes(scope));
+ }
+ else {
+ scopes.add(scope);
+ }
+ }
+
+ /**
+ * Deduce configuration scope based on configuration name using gradle conventions.
+ * IDEA gradle plugin only 'plus' configuration used to support configuration based on a custom configuration (not conventional)
+ *
+ * @param configurationName gradle configuration name
+ * @param userScopes gradle IDEA plugin scopes map
+ * @return deduced scope
+ */
+ public static GradleDependencyScope deduceScope(String configurationName,
+ Map<String, Map<String, Collection<Configuration>>> userScopes) {
+ GradleDependencyScope scope = GradleDependencyScope.fromName(configurationName);
+ for (Map.Entry<String, Map<String, Collection<Configuration>>> entry : userScopes.entrySet()) {
+ Collection<Configuration> plusConfigurations = entry.getValue().get("plus");
+ if (plusConfigurations == null) continue;
+
+ for (Configuration plus : plusConfigurations) {
+ if (plus.getName().equals(configurationName)) {
+ return GradleDependencyScope.fromIdeaMappingName(entry.getKey().toLowerCase());
+ }
+ }
+ }
+
+ return scope;
+ }
+
+ public static class MyModuleVersionIdentifier implements ModuleVersionIdentifier, Serializable {
+ private final String myName;
+
+ public MyModuleVersionIdentifier(String name) {
+
+ myName = name;
+ }
+
+ @Override
+ public String getVersion() {
+ return null;
+ }
+
+ @Override
+ public String getGroup() {
+ return null;
+ }
+
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public ModuleIdentifier getModule() {
+ return null;
+ }
+ }
+}
diff --git a/plugins/gradle/tooling-extension/gradle-tooling-extension.iml b/plugins/gradle/tooling-extension/gradle-tooling-extension.iml
new file mode 100644
index 0000000..d6300f1
--- /dev/null
+++ b/plugins/gradle/tooling-extension/gradle-tooling-extension.iml
@@ -0,0 +1,130 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/testSources" isTestSource="true" />
+ <sourceFolder url="file://$MODULE_DIR$/testData" type="java-test-resource" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="external-system-api" />
+ <orderEntry type="module" module-name="annotations" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module-library">
+ <library name="Gradle">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/gradle-tooling-api-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-core-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-messaging-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-wrapper-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-base-services-1.9.jar!/" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-native-1.9.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES>
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/buildSrc/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/buildSrc/src/test/resources" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ui/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cli/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cpp/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/cpp/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ear/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ide/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ide/src/main/resources" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/tasks" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java/org/gradle/api/publish/ivy/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/ivy/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/osgi/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/osgi/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/antlr/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/jetty/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/maven/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/maven/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/scala/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/scala/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/jacoco/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/native/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/plugins/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/publish/src/main/groovy/org/gradle/api/publish/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/publish/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/wrapper/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/wrapper/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/announce/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/launcher/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/open-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/open-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core-impl/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/core-impl/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/messaging/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/messaging/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/reporting/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/resources/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/javascript/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/testjar/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/multiModule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/singleModule/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/enforcerplugin/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-init/src/integTest/resources/org/gradle/buildinit/plugins/MavenConversionIntegrationTest/flatmultimodule/webinar-impl/src/test/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/diagnostics/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/performance/src/configPlugin" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/performance/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/integTest/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/tooling-api/src/testFixtures/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/code-quality/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/tasks" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy/org/gradle/language/jvm/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-jvm/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services/src/test/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-base/src/main/groovy/org/gradle/language/base/plugins" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/language-base/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/source/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/build-comparison/src/integTest/resources/org/gradle/api/plugins/buildcomparison/gradle/BuildComparisonIntegrationSpec/compareArchives/target/src/main/java" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/internal-testing/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services-groovy/src/main/groovy" />
+ <root url="jar://$MODULE_DIR$/../lib/gradle-1.9-src.zip!/gradle-1.9/subprojects/base-services-groovy/src/test/groovy" />
+ </SOURCES>
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library" scope="PROVIDED">
+ <library name="GradleGuava">
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/../lib/guava-jdk5-14.0.1.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" scope="PROVIDED" name="Groovy" level="project" />
+ <orderEntry type="module" module-name="gradle" scope="TEST" />
+ <orderEntry type="module" module-name="gradle-tooling-extension-v1.9" scope="RUNTIME" />
+ <orderEntry type="module" module-name="gradle-tooling-extension-v1.11" scope="RUNTIME" />
+ <orderEntry type="module" module-name="gradle-tooling-extension-v1.12" scope="RUNTIME" />
+ </component>
+</module>
+
diff --git a/plugins/gradle/lib/gradle-build-init-1.9.jar b/plugins/gradle/tooling-extension/lib/gradle-build-init-1.9.jar
similarity index 100%
rename from plugins/gradle/lib/gradle-build-init-1.9.jar
rename to plugins/gradle/tooling-extension/lib/gradle-build-init-1.9.jar
Binary files differ
diff --git a/plugins/gradle/lib/gradle-ide-1.9.jar b/plugins/gradle/tooling-extension/lib/gradle-ide-1.9.jar
similarity index 100%
rename from plugins/gradle/lib/gradle-ide-1.9.jar
rename to plugins/gradle/tooling-extension/lib/gradle-ide-1.9.jar
Binary files differ
diff --git a/plugins/gradle/lib/gradle-plugins-1.9.jar b/plugins/gradle/tooling-extension/lib/gradle-plugins-1.9.jar
similarity index 100%
rename from plugins/gradle/lib/gradle-plugins-1.9.jar
rename to plugins/gradle/tooling-extension/lib/gradle-plugins-1.9.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension/lib/gradle-scala-1.9.jar b/plugins/gradle/tooling-extension/lib/gradle-scala-1.9.jar
new file mode 100644
index 0000000..aa6a20a
--- /dev/null
+++ b/plugins/gradle/tooling-extension/lib/gradle-scala-1.9.jar
Binary files differ
diff --git a/plugins/gradle/tooling-extension/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
new file mode 100644
index 0000000..8a3203c
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -0,0 +1,15 @@
+#
+# Copyright 2000-2014 JetBrains s.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.
+#
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/BuildScriptClasspathModel.java
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ClasspathEntryModel.java
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ExtIdeaContentRoot.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ExtIdeaContentRoot.java
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/ExtIdeaContentRoot.java
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ExtIdeaContentRoot.java
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/GradleDependencyScope.java
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ModuleExtendedModel.java
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/ProjectDependenciesModel.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ProjectDependenciesModel.java
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/ProjectDependenciesModel.java
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ProjectDependenciesModel.java
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
new file mode 100644
index 0000000..af6f4fe
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ProjectImportAction.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.model;
+
+import com.intellij.openapi.externalSystem.model.ExternalSystemException;
+import org.gradle.tooling.BuildAction;
+import org.gradle.tooling.BuildController;
+import org.gradle.tooling.model.build.BuildEnvironment;
+import org.gradle.tooling.model.idea.BasicIdeaProject;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaProject;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 10/14/13
+ */
+public class ProjectImportAction implements BuildAction<ProjectImportAction.AllModels>, Serializable {
+
+ private final Set<Class> myExtraProjectModelClasses = new HashSet<Class>();
+ private final boolean myIsPreviewMode;
+
+ public ProjectImportAction(boolean isPreviewMode) {
+ myIsPreviewMode = isPreviewMode;
+ }
+
+ public void addExtraProjectModelClasses(@NotNull Set<Class> projectModelClasses) {
+ myExtraProjectModelClasses.addAll(projectModelClasses);
+ }
+
+ @Nullable
+ @Override
+ public AllModels execute(final BuildController controller) {
+ Class<? extends IdeaProject> aClass1 = myIsPreviewMode ? BasicIdeaProject.class : IdeaProject.class;
+ final IdeaProject ideaProject = controller.getModel(aClass1);
+ if (ideaProject == null || ideaProject.getModules().isEmpty()) {
+ return null;
+ }
+
+ AllModels allModels = new AllModels(ideaProject);
+
+ // TODO ask gradle guys why there is always null got for BuildEnvironment model
+ //allModels.setBuildEnvironment(controller.findModel(BuildEnvironment.class));
+
+ for (IdeaModule module : ideaProject.getModules()) {
+ for (Class aClass : myExtraProjectModelClasses) {
+ try {
+ Object extraProject = controller.findModel(module, aClass);
+ if (extraProject == null) continue;
+ allModels.addExtraProject(extraProject, aClass, module);
+ }
+ catch (Exception e) {
+ // do not fail project import in a preview mode
+ if (!myIsPreviewMode) {
+ throw new ExternalSystemException(e);
+ }
+ }
+ }
+ }
+
+ return allModels;
+ }
+
+ public static class AllModels implements Serializable {
+ @NotNull private final Map<String, Object> projectsByPath = new HashMap<String, Object>();
+ @NotNull private final IdeaProject myIdeaProject;
+ @Nullable private BuildEnvironment myBuildEnvironment;
+
+ public AllModels(@NotNull IdeaProject project) {
+ myIdeaProject = project;
+ }
+
+ @NotNull
+ public IdeaProject getIdeaProject() {
+ return myIdeaProject;
+ }
+
+ @Nullable
+ public BuildEnvironment getBuildEnvironment() {
+ return myBuildEnvironment;
+ }
+
+ public void setBuildEnvironment(@Nullable BuildEnvironment buildEnvironment) {
+ myBuildEnvironment = buildEnvironment;
+ }
+
+
+ @Nullable
+ public <T> T getExtraProject(@NotNull IdeaModule module, Class<T> modelClazz) {
+ Object extraProject = projectsByPath.get(extractMapKey(modelClazz, module));
+ if (modelClazz.isInstance(extraProject)) {
+ //noinspection unchecked
+ return (T)extraProject;
+ }
+ return null;
+ }
+
+ /**
+ * Return collection path of modules provides the model
+ *
+ * @param modelClazz extra project model
+ * @return modules path collection
+ */
+ @NotNull
+ public Collection<String> findModulesWithModel(@NotNull Class modelClazz) {
+ List<String> modules = new ArrayList<String>();
+ for (Map.Entry<String, Object> set : projectsByPath.entrySet()) {
+ if (modelClazz.isInstance(set.getValue())) {
+ modules.add(extractModulePath(modelClazz, set.getKey()));
+ }
+ }
+ return modules;
+ }
+
+ public void addExtraProject(@NotNull Object project, @NotNull Class modelClazz, @NotNull IdeaModule module) {
+ projectsByPath.put(extractMapKey(modelClazz, module), project);
+ }
+
+ @NotNull
+ private static String extractMapKey(Class modelClazz, @NotNull IdeaModule module) {
+ return modelClazz.getName() + '@' + module.getGradleProject().getPath();
+ }
+
+ @NotNull
+ private static String extractModulePath(Class modelClazz, String key) {
+ return key.replaceFirst(modelClazz.getName() + '@', "");
+ }
+
+ @Override
+ public String toString() {
+ return "AllModels{" +
+ "projectsByPath=" + projectsByPath +
+ ", myIdeaProject=" + myIdeaProject +
+ '}';
+ }
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaCompileOptions.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaCompileOptions.java
new file mode 100644
index 0000000..596659a
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaCompileOptions.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.gradle.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public interface ScalaCompileOptions extends Serializable {
+ boolean isUseCompileDaemon();
+
+ String getDaemonServer();
+
+ boolean isFailOnError();
+
+ boolean isDeprecation();
+
+ boolean isUnchecked();
+
+ String getDebugLevel();
+
+ boolean isOptimize();
+
+ String getEncoding();
+
+ String getForce();
+
+ List<String> getAdditionalParameters();
+
+ boolean isListFiles();
+
+ String getLoggingLevel();
+
+ List<String> getLoggingPhases();
+
+ boolean isFork();
+
+ boolean isUseAnt();
+
+ ScalaForkOptions getForkOptions();
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaForkOptions.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaForkOptions.java
new file mode 100644
index 0000000..9dd0cef
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaForkOptions.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.model;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public interface ScalaForkOptions extends Serializable {
+ String getMemoryInitialSize();
+
+ String getMemoryMaximumSize();
+
+ List<String> getJvmArgs();
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaModel.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaModel.java
new file mode 100644
index 0000000..7e72400
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/ScalaModel.java
@@ -0,0 +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 org.jetbrains.plugins.gradle.model;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public interface ScalaModel extends Serializable {
+
+ Set<File> getScalaClasspath();
+
+ Set<File> getZincClasspath();
+
+ ScalaCompileOptions getScalaCompileOptions();
+
+ String getSourceCompatibility();
+
+ String getTargetCompatibility();
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/WebConfiguration.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/WebConfiguration.java
new file mode 100644
index 0000000..c2ed1eb
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/model/WebConfiguration.java
@@ -0,0 +1,61 @@
+/*
+ * 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.gradle.model;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+public interface WebConfiguration extends Serializable {
+
+ List<? extends WarModel> getWarModels();
+
+ interface WarModel extends Serializable {
+ @NotNull
+ String getWarName();
+
+ String getWebAppDirName();
+
+ File getWebAppDir();
+
+ File getWebXml();
+
+ List<WebResource> getWebResources();
+
+ Set<File> getClasspath();
+
+ String getManifestContent();
+ }
+
+ interface WebResource extends Serializable {
+
+ @NotNull
+ String getWarDirectory();
+
+ @NotNull
+ String getRelativePath();
+
+ @NotNull
+ File getFile();
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/ModelBuilderService.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/ModelBuilderService.java
new file mode 100644
index 0000000..4b972fa
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/ModelBuilderService.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling;
+
+import org.gradle.api.Project;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+public interface ModelBuilderService {
+ boolean canBuild(String modelName);
+
+ Object buildAll(String modelName, Project project);
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/annotation/TargetVersions.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/annotation/TargetVersions.java
new file mode 100644
index 0000000..a5d81fb
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/annotation/TargetVersions.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2012 the original author or authors.
+ *
+ * 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.gradle.tooling.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface TargetVersions {
+ String value();
+ boolean checkBaseVersions() default true;
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/AbstractGradleDependency.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/AbstractGradleDependency.java
new file mode 100644
index 0000000..16cef89
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/AbstractGradleDependency.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/8/13
+ */
+public abstract class AbstractGradleDependency implements Serializable {
+ private final IdeaDependencyScope myScope;
+ private final String myDependencyName;
+ private final String myDependencyGroup;
+ private final String myDependencyVersion;
+ private final String myClassifier;
+
+ public AbstractGradleDependency(IdeaDependencyScope scope, String dependencyName,
+ String dependencyGroup, String dependencyVersion, String classifier) {
+ myScope = scope;
+ myDependencyName = dependencyName;
+ myDependencyGroup = dependencyGroup;
+ myDependencyVersion = dependencyVersion;
+ myClassifier = classifier;
+ }
+
+ public IdeaDependencyScope getScope() {
+ return myScope;
+ }
+
+ public boolean getExported() {
+ return "compile".equals(myScope.getScope()) || "runtime".equals(myScope.getScope());
+ }
+
+ public String getDependencyName() {
+ return myDependencyName;
+ }
+
+ public String getDependencyGroup() {
+ return myDependencyGroup;
+ }
+
+ public String getDependencyVersion() {
+ return myDependencyVersion;
+ }
+
+ public String getClassifier() {
+ return myClassifier;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AbstractGradleDependency)) return false;
+
+ AbstractGradleDependency that = (AbstractGradleDependency)o;
+
+ if (myDependencyGroup != null ? !myDependencyGroup.equals(that.myDependencyGroup) : that.myDependencyGroup != null) return false;
+ if (myDependencyName != null ? !myDependencyName.equals(that.myDependencyName) : that.myDependencyName != null) return false;
+ if (myDependencyVersion != null ? !myDependencyVersion.equals(that.myDependencyVersion) : that.myDependencyVersion != null) {
+ return false;
+ }
+ if (myScope != null ? !myScope.equals(that.myScope) : that.myScope != null) return false;
+ if (myClassifier != null ? !myClassifier.equals(that.myClassifier) : that.myClassifier != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myScope != null ? myScope.hashCode() : 0;
+ result = 31 * result + (myDependencyName != null ? myDependencyName.hashCode() : 0);
+ result = 31 * result + (myDependencyGroup != null ? myDependencyGroup.hashCode() : 0);
+ result = 31 * result + (myDependencyVersion != null ? myDependencyVersion.hashCode() : 0);
+ result = 31 * result + (myClassifier != null ? myClassifier.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "GradleDependency{" +
+ "myScope=" + myScope +
+ ", dependencyName='" + myDependencyName + '\'' +
+ ", dependencyGroup='" + myDependencyGroup + '\'' +
+ ", dependencyVersion='" + myDependencyVersion + '\'' +
+ ", classifier='" + myClassifier + '\'' +
+ ", exported=" + getExported() +
+ '}';
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/BuildScriptClasspathModelImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/BuildScriptClasspathModelImpl.java
new file mode 100644
index 0000000..608df19
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/BuildScriptClasspathModelImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public class BuildScriptClasspathModelImpl implements BuildScriptClasspathModel {
+
+ private final List<ClasspathEntryModel> myClasspathEntries;
+
+ public BuildScriptClasspathModelImpl() {
+ myClasspathEntries = new ArrayList<ClasspathEntryModel>();
+ }
+
+ @Override
+ public DomainObjectSet<? extends ClasspathEntryModel> getClasspath() {
+ return ImmutableDomainObjectSet.of(myClasspathEntries);
+ }
+
+ public void add(@NotNull ClasspathEntryModel classpathEntryModel) {
+ myClasspathEntries.add(classpathEntryModel);
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ClasspathEntryModelImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ClasspathEntryModelImpl.java
new file mode 100644
index 0000000..2a9783c
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ClasspathEntryModelImpl.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 12/20/13
+ */
+public class ClasspathEntryModelImpl implements ClasspathEntryModel, Serializable {
+ @NotNull
+ private final File classesFile;
+ @Nullable
+ private final File sourcesFile;
+ @Nullable
+ private final File javadocFile;
+
+ public ClasspathEntryModelImpl(@NotNull File classesFile, @Nullable File sourcesFile, @Nullable File javadocFile) {
+ this.classesFile = classesFile;
+ this.sourcesFile = sourcesFile;
+ this.javadocFile = javadocFile;
+ }
+
+ @NotNull
+ @Override
+ public File getClassesFile() {
+ return classesFile;
+ }
+
+ @Nullable
+ @Override
+ public File getSourcesFile() {
+ return sourcesFile;
+ }
+
+ @Nullable
+ @Override
+ public File getJavadocFile() {
+ return javadocFile;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/DependencyVersionId.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/DependencyVersionId.java
new file mode 100644
index 0000000..3c49f8f
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/DependencyVersionId.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class DependencyVersionId {
+ private final String myName;
+ private final String myArtifactName;
+ private final String myGroup;
+ private final String myVersion;
+ private final String myClassifier;
+
+ public DependencyVersionId(String name,
+ String artifactName,
+ String group,
+ String version,
+ String classifier) {
+ myName = name;
+ myArtifactName = artifactName;
+ myGroup = group;
+ myVersion = version;
+ myClassifier = classifier;
+ }
+
+ public String getName() {
+ return myName;
+ }
+
+ public String getArtifactName() {
+ return myArtifactName;
+ }
+
+ public String getGroup() {
+ return myGroup;
+ }
+
+ public String getVersion() {
+ return myVersion;
+ }
+
+ public String getClassifier() {
+ return myClassifier;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DependencyVersionId)) return false;
+
+ DependencyVersionId id = (DependencyVersionId)o;
+
+ if (myGroup != null ? !myGroup.equals(id.myGroup) : id.myGroup != null) return false;
+ if (myName != null ? !myName.equals(id.myName) : id.myName != null) return false;
+ if (myArtifactName != null ? !myArtifactName.equals(id.myArtifactName) : id.myArtifactName != null) return false;
+ if (myVersion != null ? !myVersion.equals(id.myVersion) : id.myVersion != null) return false;
+ if (myClassifier != null ? !myClassifier.equals(id.myClassifier) : id.myClassifier != null) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myName != null ? myName.hashCode() : 0;
+ result = 31 * result + (myArtifactName != null ? myArtifactName.hashCode() : 0);
+ result = 31 * result + (myGroup != null ? myGroup.hashCode() : 0);
+ result = 31 * result + (myVersion != null ? myVersion.hashCode() : 0);
+ result = 31 * result + (myClassifier != null ? myClassifier.hashCode() : 0);
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "DependencyVersionId{" +
+ "name='" + myName + '\'' +
+ ", artifactName='" + myArtifactName + '\'' +
+ ", group='" + myGroup + '\'' +
+ ", version='" + myVersion + '\'' +
+ ", classifier='" + myClassifier + '\'' +
+ '}';
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ExtraModelBuilder.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ExtraModelBuilder.java
new file mode 100644
index 0000000..cdcb8a5
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ExtraModelBuilder.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.api.Project;
+import org.gradle.tooling.provider.model.ToolingModelBuilder;
+import org.gradle.util.GradleVersion;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+
+import java.util.ServiceLoader;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+@SuppressWarnings("UnusedDeclaration")
+public class ExtraModelBuilder implements ToolingModelBuilder {
+ private static final String RANGE_TOKEN = " <=> ";
+ private static ServiceLoader<ModelBuilderService> buildersLoader =
+ ServiceLoader.load(ModelBuilderService.class, ExtraModelBuilder.class.getClassLoader());
+
+ @NotNull
+ private final GradleVersion myCurrentGradleVersion;
+
+ public ExtraModelBuilder() {
+ this.myCurrentGradleVersion = GradleVersion.current();
+ }
+
+ @TestOnly
+ public ExtraModelBuilder(@NotNull GradleVersion gradleVersion) {
+ this.myCurrentGradleVersion = gradleVersion;
+ }
+
+ @Override
+ public boolean canBuild(String modelName) {
+ for (ModelBuilderService service : buildersLoader) {
+ if (service.canBuild(modelName) && isVersionMatch(service)) return true;
+ }
+ return false;
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ for (ModelBuilderService service : buildersLoader) {
+ if (service.canBuild(modelName) && isVersionMatch(service)) {
+ return service.buildAll(modelName, project);
+ }
+ }
+ throw new IllegalArgumentException("Unsupported model: " + modelName);
+ }
+
+ private boolean isVersionMatch(@NotNull ModelBuilderService builderService) {
+ TargetVersions targetVersions = builderService.getClass().getAnnotation(TargetVersions.class);
+ if (targetVersions == null || targetVersions.value() == null || targetVersions.value().isEmpty()) return true;
+
+ final GradleVersion current = adjust(myCurrentGradleVersion, targetVersions.checkBaseVersions());
+
+ if (targetVersions.value().endsWith("+")) {
+ String minVersion = targetVersions.value().substring(0, targetVersions.value().length() - 1);
+ return compare(current, minVersion, targetVersions.checkBaseVersions()) >= 0;
+ }
+ else {
+ final int rangeIndex = targetVersions.value().indexOf(RANGE_TOKEN);
+ if (rangeIndex != -1) {
+ String minVersion = targetVersions.value().substring(0, rangeIndex);
+ String maxVersion = targetVersions.value().substring(rangeIndex + RANGE_TOKEN.length());
+ return compare(current, minVersion, targetVersions.checkBaseVersions()) >= 0 &&
+ compare(current, maxVersion, targetVersions.checkBaseVersions()) <= 0;
+ }
+ else {
+ return compare(current, targetVersions.value(), targetVersions.checkBaseVersions()) == 0;
+ }
+ }
+ }
+
+ private static int compare(@NotNull GradleVersion gradleVersion, @NotNull String otherGradleVersion, boolean checkBaseVersions) {
+ return gradleVersion.compareTo(adjust(GradleVersion.version(otherGradleVersion), checkBaseVersions));
+ }
+
+ private static GradleVersion adjust(@NotNull GradleVersion version, boolean checkBaseVersions) {
+ return checkBaseVersions ? version.getBaseVersion() : version;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaContentRootImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaContentRootImpl.java
new file mode 100644
index 0000000..a2dbfe8
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaContentRootImpl.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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/13/13
+ */
+public class IdeaContentRootImpl implements ExtIdeaContentRoot {
+
+ private final File myRootDirectory;
+ private final List<IdeaSourceDirectory> mySourceDirectories;
+ private final List<IdeaSourceDirectory> myTestDirectories;
+ private final List<IdeaSourceDirectory> myResourceDirectories;
+ private final List<IdeaSourceDirectory> myTestResourceDirectories;
+ private final Set<File> myExcludeDirectories;
+
+ public IdeaContentRootImpl(File rootDirectory) {
+ myRootDirectory = rootDirectory;
+ mySourceDirectories = new ArrayList<IdeaSourceDirectory>();
+ myTestDirectories = new ArrayList<IdeaSourceDirectory>();
+ myResourceDirectories = new ArrayList<IdeaSourceDirectory>();
+ myTestResourceDirectories = new ArrayList<IdeaSourceDirectory>();
+ myExcludeDirectories = new HashSet<File>();
+ }
+
+ @Override
+ public File getRootDirectory() {
+ return myRootDirectory;
+ }
+
+ @Override
+ public DomainObjectSet<? extends IdeaSourceDirectory> getSourceDirectories() {
+ return ImmutableDomainObjectSet.of(mySourceDirectories);
+ }
+
+ public void addSourceDirectory(IdeaSourceDirectory sourceDirectory) {
+ mySourceDirectories.add(sourceDirectory);
+ }
+
+ public void addTestDirectory(IdeaSourceDirectory testDirectory) {
+ myTestDirectories.add(testDirectory);
+ }
+
+ public void addResourceDirectory(IdeaSourceDirectory resourceDirectory) {
+ myResourceDirectories.add(resourceDirectory);
+ }
+
+ public void addTestResourceDirectory(IdeaSourceDirectory resourceDirectory) {
+ myTestResourceDirectories.add(resourceDirectory);
+ }
+
+ public void addExcludeDirectory(File excludeDirectory) {
+ myExcludeDirectories.add(excludeDirectory);
+ }
+
+ @Override
+ public DomainObjectSet<? extends IdeaSourceDirectory> getTestDirectories() {
+ return ImmutableDomainObjectSet.of(myTestDirectories);
+ }
+
+ @Override
+ public DomainObjectSet<? extends IdeaSourceDirectory> getResourceDirectories() {
+ return ImmutableDomainObjectSet.of(myResourceDirectories);
+ }
+
+ @Override
+ public DomainObjectSet<? extends IdeaSourceDirectory> getTestResourceDirectories() {
+ return ImmutableDomainObjectSet.of(myTestResourceDirectories);
+ }
+
+ @Override
+ public Set<File> getExcludeDirectories() {
+ return myExcludeDirectories;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaDependencyScopeImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaDependencyScopeImpl.java
new file mode 100644
index 0000000..6e10e56
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaDependencyScopeImpl.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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class IdeaDependencyScopeImpl implements IdeaDependencyScope, Serializable {
+
+ private final GradleDependencyScope myDependencyScope;
+
+ public IdeaDependencyScopeImpl(GradleDependencyScope scope) {
+ myDependencyScope = scope;
+ }
+
+ @Override
+ public String getScope() {
+ return myDependencyScope.getIdeaMappingName();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof IdeaDependencyScopeImpl)) return false;
+
+ IdeaDependencyScopeImpl scope = (IdeaDependencyScopeImpl)o;
+
+ if (myDependencyScope != scope.myDependencyScope) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return myDependencyScope != null ? myDependencyScope.hashCode() : 0;
+ }
+
+ @Override
+ public String toString() {
+ return "IdeaDependencyScope{" + myDependencyScope + '}';
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaModuleDependencyImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaModuleDependencyImpl.java
new file mode 100644
index 0000000..5b5d0df
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaModuleDependencyImpl.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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaModuleDependency;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class IdeaModuleDependencyImpl extends AbstractGradleDependency
+ implements IdeaModuleDependency, Serializable {
+ private IdeaModule myIdeaModule;
+
+ public IdeaModuleDependencyImpl(IdeaDependencyScope myScope,
+ String dependencyName,
+ String dependencyGroup,
+ String dependencyVersion,
+ String classifier) {
+ super(myScope, dependencyName, dependencyGroup, dependencyVersion, classifier);
+ }
+
+ @Override
+ public IdeaModule getDependencyModule() {
+ return myIdeaModule;
+ }
+
+ public void setIdeaModule(IdeaModule ideaModule) {
+ myIdeaModule = ideaModule;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaSingleEntryLibraryDependencyImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaSingleEntryLibraryDependencyImpl.java
new file mode 100644
index 0000000..13025c9
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaSingleEntryLibraryDependencyImpl.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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.gradle.tooling.model.GradleModuleVersion;
+import org.gradle.tooling.model.idea.IdeaDependencyScope;
+import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class IdeaSingleEntryLibraryDependencyImpl extends AbstractGradleDependency
+ implements IdeaSingleEntryLibraryDependency, Serializable {
+
+ private File myFile;
+ private File mySource;
+ private File myJavadoc;
+
+ public IdeaSingleEntryLibraryDependencyImpl(IdeaDependencyScope myScope,
+ String dependencyName,
+ String dependencyGroup,
+ String dependencyVersion,
+ String classifier) {
+ super(myScope, dependencyName, dependencyGroup, dependencyVersion, classifier);
+ }
+
+ @Override
+ public File getFile() {
+ return myFile;
+ }
+
+ @Override
+ public File getSource() {
+ return mySource;
+ }
+
+ @Override
+ public File getJavadoc() {
+ return myJavadoc;
+ }
+
+ public void setFile(File file) {
+ myFile = file;
+ }
+
+ public void setSource(File source) {
+ mySource = source;
+ }
+
+ public void setJavadoc(File javadoc) {
+ myJavadoc = javadoc;
+ }
+
+ @Override
+ public GradleModuleVersion getGradleModuleVersion() {
+ return null;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaSourceDirectoryImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaSourceDirectoryImpl.java
new file mode 100644
index 0000000..f038fb8
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/IdeaSourceDirectoryImpl.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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+
+import java.io.File;
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/15/13
+ */
+public class IdeaSourceDirectoryImpl implements IdeaSourceDirectory, Serializable {
+
+ private final File myDirectory;
+
+ public IdeaSourceDirectoryImpl(File directory) {
+ myDirectory = directory;
+ }
+
+ @Override
+ public File getDirectory() {
+ return myDirectory;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java
new file mode 100644
index 0000000..46ecbf1
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ModuleExtendedModelImpl.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.internal.ImmutableDomainObjectSet;
+import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
+import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/8/13
+ */
+public class ModuleExtendedModelImpl implements ModuleExtendedModel {
+ private final String myName;
+ private final String myGroup;
+ private final String myVersion;
+ private List<File> myArtifacts;
+ private Set<ExtIdeaContentRoot> myContentRoots;
+
+ public ModuleExtendedModelImpl(String name, String group, String version) {
+ myName = name;
+ myGroup = group;
+ myVersion = version;
+ myArtifacts = Collections.emptyList();
+ myContentRoots = Collections.emptySet();
+ }
+
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public String getGroup() {
+ return myGroup;
+ }
+
+ @Override
+ public String getVersion() {
+ return myVersion;
+ }
+
+ @Override
+ public List<File> getArtifacts() {
+ return myArtifacts;
+ }
+
+ public void setArtifacts(List<File> artifacts) {
+ this.myArtifacts = artifacts == null ? Collections.<File>emptyList() : artifacts;
+ }
+
+ @Override
+ public DomainObjectSet<? extends ExtIdeaContentRoot> getContentRoots() {
+ return ImmutableDomainObjectSet.of(myContentRoots);
+ }
+
+ public void setContentRoots(Set<ExtIdeaContentRoot> contentRoots) {
+ myContentRoots = contentRoots == null ? Collections.<ExtIdeaContentRoot>emptySet() : contentRoots;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ProjectDependenciesModelImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ProjectDependenciesModelImpl.java
new file mode 100644
index 0000000..1a57dc5
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/ProjectDependenciesModelImpl.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.tooling.model.idea.IdeaDependency;
+import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/8/13
+ */
+public class ProjectDependenciesModelImpl implements ProjectDependenciesModel {
+ private final String projectName;
+ private final List<IdeaDependency> myDependencies;
+
+ public ProjectDependenciesModelImpl(String projectName, List<IdeaDependency> dependencies) {
+ this.projectName = projectName;
+ myDependencies = dependencies;
+ }
+
+ @Override
+ public String getProjectName() {
+ return projectName;
+ }
+
+ @Override
+ public List<IdeaDependency> getDependencies() {
+ return myDependencies;
+ }
+
+ @Override
+ public String toString() {
+ return "ProjectDependenciesModelImpl{" +
+ "projectName='" + projectName + '\'' +
+ '}';
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/Scopes.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/Scopes.java
new file mode 100644
index 0000000..3f47723
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/Scopes.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.gradle.tooling.internal;
+
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class Scopes {
+ private boolean myForProductionCompile;
+ private boolean myForProductionRuntime;
+ private boolean myForTestCompile;
+ private boolean myForTestRuntime;
+ private boolean myIsProvided;
+
+ public Scopes(GradleDependencyScope scope) {
+ myForProductionCompile = scope.isForProductionCompile();
+ myForProductionRuntime = scope.isForProductionRuntime();
+ myForTestCompile = scope.isForTestCompile();
+ myForTestRuntime = scope.isForTestRuntime();
+ myIsProvided = scope == GradleDependencyScope.PROVIDED_COMPILE ||
+ scope == GradleDependencyScope.PROVIDED_RUNTIME ||
+ scope == GradleDependencyScope.PROVIDED;
+ }
+
+ public GradleDependencyScope[] getScopes() {
+ if (myIsProvided) {
+ if (myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.PROVIDED_COMPILE};
+ }
+ else if (!myForProductionCompile && myForProductionRuntime && !myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.PROVIDED_RUNTIME};
+ }
+ else if (!myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.TEST_COMPILE, GradleDependencyScope.PROVIDED_RUNTIME};
+ }
+ }
+
+ if (myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.COMPILE};
+ }
+ else if (!myForProductionCompile && myForProductionRuntime && !myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.RUNTIME};
+ }
+ else if (!myForProductionCompile && !myForProductionRuntime && myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.TEST_COMPILE};
+ }
+ else if (!myForProductionCompile && !myForProductionRuntime && !myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.TEST_RUNTIME};
+ }
+ else if (!myForProductionCompile && myForProductionRuntime && myForTestCompile && myForTestRuntime) {
+ return new GradleDependencyScope[]{GradleDependencyScope.TEST_COMPILE, GradleDependencyScope.RUNTIME};
+ }
+ else {
+ return new GradleDependencyScope[]{GradleDependencyScope.COMPILE};
+ }
+ }
+
+ public void add(GradleDependencyScope scope) {
+ myForProductionCompile = myForProductionCompile || scope.isForProductionCompile();
+ myForProductionRuntime = myForProductionRuntime || scope.isForProductionRuntime();
+ myForTestCompile = myForTestCompile || scope.isForTestCompile();
+ myForTestRuntime = myForTestRuntime || scope.isForTestRuntime();
+ myIsProvided = myIsProvided ||
+ scope == GradleDependencyScope.PROVIDED_COMPILE ||
+ scope == GradleDependencyScope.PROVIDED_RUNTIME ||
+ scope == GradleDependencyScope.PROVIDED;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/StubIdeaModule.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/StubIdeaModule.java
new file mode 100644
index 0000000..1662240
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/StubIdeaModule.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.GradleProject;
+import org.gradle.tooling.model.HierarchicalElement;
+import org.gradle.tooling.model.idea.*;
+
+import java.io.Serializable;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/25/13
+ */
+public class StubIdeaModule implements IdeaModule, Serializable {
+
+ private final String name;
+
+ public StubIdeaModule(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public DomainObjectSet<? extends IdeaContentRoot> getContentRoots() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public GradleProject getGradleProject() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public IdeaProject getParent() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DomainObjectSet<? extends HierarchicalElement> getChildren() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public IdeaProject getProject() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public IdeaCompilerOutput getCompilerOutput() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DomainObjectSet<? extends IdeaDependency> getDependencies() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String getDescription() {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WarModelImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WarModelImpl.java
new file mode 100644
index 0000000..67d492d
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WarModelImpl.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.WebConfiguration;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+/**
+* @author Vladislav.Soroka
+* @since 2/10/14
+*/
+public class WarModelImpl implements WebConfiguration.WarModel {
+ @NotNull
+ private final String warName;
+ private final String myWebAppDirName;
+ private final File myWebAppDir;
+ private File myWebXml;
+ private List<WebConfiguration.WebResource> myWebResources;
+ private Set<File> myClasspath;
+ private String myManifestContent;
+
+ public WarModelImpl(@NotNull String name, String webAppDirName, File webAppDir) {
+ warName = name;
+ myWebAppDirName = webAppDirName;
+ myWebAppDir = webAppDir;
+ }
+
+ @NotNull
+ @Override
+ public String getWarName() {
+ return warName;
+ }
+
+ @Override
+ public String getWebAppDirName() {
+ return myWebAppDirName;
+ }
+
+ @Override
+ public File getWebAppDir() {
+ return myWebAppDir;
+ }
+
+ public void setWebXml(File webXml) {
+ myWebXml = webXml;
+ }
+
+ @Override
+ public File getWebXml() {
+ return myWebXml;
+ }
+
+ @Override
+ public List<WebConfiguration.WebResource> getWebResources() {
+ return myWebResources;
+ }
+
+ public void setWebResources(List<WebConfiguration.WebResource> webResources) {
+ myWebResources = webResources;
+ }
+
+ public void setClasspath(Set<File> classpath) {
+ myClasspath = classpath;
+ }
+
+ @Override
+ public Set<File> getClasspath() {
+ return myClasspath;
+ }
+
+ public void setManifestContent(String manifestContent) {
+ myManifestContent = manifestContent;
+ }
+
+ @Override
+ public String getManifestContent() {
+ return myManifestContent;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WebConfigurationImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WebConfigurationImpl.java
new file mode 100644
index 0000000..8c0c9a5
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WebConfigurationImpl.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.WebConfiguration;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/5/13
+ */
+public class WebConfigurationImpl implements WebConfiguration {
+
+ @NotNull
+ private final List<WarModel> myWarModels;
+
+ public WebConfigurationImpl(@NotNull List<WarModel> warModels) {
+ myWarModels = warModels;
+ }
+
+ @Override
+ public List<? extends WarModel> getWarModels() {
+ return myWarModels;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WebResourceImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WebResourceImpl.java
new file mode 100644
index 0000000..e449f06
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/WebResourceImpl.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 org.jetbrains.plugins.gradle.tooling.internal;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.WebConfiguration;
+
+import java.io.File;
+
+/**
+* @author Vladislav.Soroka
+* @since 2/10/14
+*/
+public class WebResourceImpl implements WebConfiguration.WebResource {
+ @NotNull
+ private final String myWarDirectory;
+ @NotNull
+ private final String myRelativePath;
+ @NotNull
+ private final File file;
+
+ public WebResourceImpl(@NotNull String warDirectory, @NotNull String relativePath, @NotNull File file) {
+ myWarDirectory = warDirectory;
+ this.myRelativePath = relativePath;
+ this.file = file;
+ }
+
+ @NotNull
+ @Override
+ public String getWarDirectory() {
+ return myWarDirectory;
+ }
+
+ @NotNull
+ @Override
+ public String getRelativePath() {
+ return myRelativePath;
+ }
+
+ @NotNull
+ @Override
+ public File getFile() {
+ return file;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof WebResourceImpl)) return false;
+
+ WebResourceImpl resource = (WebResourceImpl)o;
+ if (!file.getPath().equals(resource.file.getPath())) return false;
+ if (myWarDirectory != resource.myWarDirectory) return false;
+ if (!myRelativePath.equals(resource.myRelativePath)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myWarDirectory.hashCode();
+ result = 31 * result + myRelativePath.hashCode();
+ result = 31 * result + file.getPath().hashCode();
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ return "WebResourceImpl{" +
+ "myWarDirectory=" + myWarDirectory +
+ ", warRelativePath='" + myRelativePath + '\'' +
+ ", file=" + file +
+ '}';
+ }
+}
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/buildSrcInit.gradle
similarity index 100%
rename from plugins/gradle/src/org/jetbrains/plugins/gradle/model/internal/buildSrcInit.gradle
rename to plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/buildSrcInit.gradle
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/init.gradle b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/init.gradle
new file mode 100644
index 0000000..d9c1e3b
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/init.gradle
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.
+ */
+import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
+
+@SuppressWarnings("GrPackage")
+class JetGradlePlugin implements Plugin<Project> {
+ private final ToolingModelBuilderRegistry registry
+
+ @javax.inject.Inject
+ public JetGradlePlugin(ToolingModelBuilderRegistry registry) {
+ this.registry = registry
+ }
+
+ public void apply(Project project) {
+ registry.register(project.jetExtraModelBuilderClass.newInstance())
+ }
+}
+
+try {
+ String[] paths = ${EXTENSIONS_JARS_PATH}
+ URL[] urls = paths.collect{ new File(it).toURI().toURL() }
+ URLClassLoader classLoader = new URLClassLoader(urls, getClass().classLoader)
+ Class modelClass = classLoader.loadClass('org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilder')
+ allprojects {
+ apply plugin: 'idea'
+ idea.module.ext.set('resourceDirs', [])
+ idea.module.ext.set('testResourceDirs', [])
+
+ ext.jetExtraModelBuilderClass = modelClass
+ apply plugin: JetGradlePlugin
+ }
+}
+catch (all) {
+}
\ No newline at end of file
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaCompileOptionsImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaCompileOptionsImpl.java
new file mode 100644
index 0000000..b40d0cb
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaCompileOptionsImpl.java
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal.scala;
+
+import org.jetbrains.plugins.gradle.model.ScalaCompileOptions;
+import org.jetbrains.plugins.gradle.model.ScalaForkOptions;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public class ScalaCompileOptionsImpl implements ScalaCompileOptions {
+ private boolean useCompileDaemon;
+ private String daemonServer;
+ private boolean failOnError;
+ private boolean deprecation;
+ private boolean unchecked;
+ private String debugLevel;
+ private boolean optimize;
+ private String encoding;
+ private String force;
+ private List<String> additionalParameters;
+ private boolean listFiles;
+ private String loggingLevel;
+ private List<String> loggingPhases;
+ private boolean fork;
+ private ScalaForkOptionsImpl forkOptions;
+ private boolean useAnt;
+
+ @Override
+ public boolean isUseCompileDaemon() {
+ return useCompileDaemon;
+ }
+
+ public void setUseCompileDaemon(boolean useCompileDaemon) {
+ this.useCompileDaemon = useCompileDaemon;
+ }
+
+ @Override
+ public String getDaemonServer() {
+ return daemonServer;
+ }
+
+ public void setDaemonServer(String daemonServer) {
+ this.daemonServer = daemonServer;
+ }
+
+ @Override
+ public boolean isFailOnError() {
+ return failOnError;
+ }
+
+ public void setFailOnError(boolean failOnError) {
+ this.failOnError = failOnError;
+ }
+
+ @Override
+ public boolean isDeprecation() {
+ return deprecation;
+ }
+
+ public void setDeprecation(boolean deprecation) {
+ this.deprecation = deprecation;
+ }
+
+ @Override
+ public boolean isUnchecked() {
+ return unchecked;
+ }
+
+ public void setUnchecked(boolean unchecked) {
+ this.unchecked = unchecked;
+ }
+
+ @Override
+ public String getDebugLevel() {
+ return debugLevel;
+ }
+
+ public void setDebugLevel(String debugLevel) {
+ this.debugLevel = debugLevel;
+ }
+
+ @Override
+ public boolean isOptimize() {
+ return optimize;
+ }
+
+ public void setOptimize(boolean optimize) {
+ this.optimize = optimize;
+ }
+
+ @Override
+ public String getEncoding() {
+ return encoding;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ @Override
+ public String getForce() {
+ return force;
+ }
+
+ public void setForce(String force) {
+ this.force = force;
+ }
+
+ @Override
+ public List<String> getAdditionalParameters() {
+ return additionalParameters;
+ }
+
+ public void setAdditionalParameters(List<String> additionalParameters) {
+ this.additionalParameters = additionalParameters;
+ }
+
+ @Override
+ public boolean isListFiles() {
+ return listFiles;
+ }
+
+ public void setListFiles(boolean listFiles) {
+ this.listFiles = listFiles;
+ }
+
+ @Override
+ public String getLoggingLevel() {
+ return loggingLevel;
+ }
+
+ public void setLoggingLevel(String loggingLevel) {
+ this.loggingLevel = loggingLevel;
+ }
+
+ @Override
+ public List<String> getLoggingPhases() {
+ return loggingPhases;
+ }
+
+ public void setLoggingPhases(List<String> loggingPhases) {
+ this.loggingPhases = loggingPhases;
+ }
+
+ @Override
+ public boolean isFork() {
+ return fork;
+ }
+
+ public void setFork(boolean fork) {
+ this.fork = fork;
+ }
+
+ @Override
+ public boolean isUseAnt() {
+ return useAnt;
+ }
+
+ public void setUseAnt(boolean useAnt) {
+ this.useAnt = useAnt;
+ }
+
+ @Override
+ public ScalaForkOptions getForkOptions() {
+ return forkOptions;
+ }
+
+ public void setForkOptions(ScalaForkOptionsImpl forkOptions) {
+ this.forkOptions = forkOptions;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaForkOptionsImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaForkOptionsImpl.java
new file mode 100644
index 0000000..cd5612d
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaForkOptionsImpl.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.gradle.tooling.internal.scala;
+
+import org.jetbrains.plugins.gradle.model.ScalaForkOptions;
+
+import java.util.List;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public class ScalaForkOptionsImpl implements ScalaForkOptions {
+ private String memoryInitialSize;
+ private String memoryMaximumSize;
+ private List<String> jvmArgs;
+
+ @Override
+ public String getMemoryInitialSize() {
+ return memoryInitialSize;
+ }
+
+ public void setMemoryInitialSize(String memoryInitialSize) {
+ this.memoryInitialSize = memoryInitialSize;
+ }
+
+ @Override
+ public String getMemoryMaximumSize() {
+ return memoryMaximumSize;
+ }
+
+ public void setMemoryMaximumSize(String memoryMaximumSize) {
+ this.memoryMaximumSize = memoryMaximumSize;
+ }
+
+ @Override
+ public List<String> getJvmArgs() {
+ return jvmArgs;
+ }
+
+ public void setJvmArgs(List<String> jvmArgs) {
+ this.jvmArgs = jvmArgs;
+ }
+}
diff --git a/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaModelImpl.java b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaModelImpl.java
new file mode 100644
index 0000000..e019ca5
--- /dev/null
+++ b/plugins/gradle/tooling-extension/src/org/jetbrains/plugins/gradle/tooling/internal/scala/ScalaModelImpl.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal.scala;
+
+import org.jetbrains.plugins.gradle.model.ScalaCompileOptions;
+import org.jetbrains.plugins.gradle.model.ScalaModel;
+
+import java.io.File;
+import java.util.Set;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/31/14
+ */
+public class ScalaModelImpl implements ScalaModel {
+ private Set<File> scalaClasspath;
+ private Set<File> zincClasspath;
+ private String sourceCompatibility;
+ private String targetCompatibility;
+ private ScalaCompileOptionsImpl scalaCompileOptions;
+
+ @Override
+ public Set<File> getScalaClasspath() {
+ return scalaClasspath;
+ }
+
+ public void setScalaClasspath(Set<File> scalaClasspath) {
+ this.scalaClasspath = scalaClasspath;
+ }
+
+ @Override
+ public Set<File> getZincClasspath() {
+ return zincClasspath;
+ }
+
+ public void setZincClasspath(Set<File> zincClasspath) {
+ this.zincClasspath = zincClasspath;
+ }
+
+ @Override
+ public ScalaCompileOptions getScalaCompileOptions() {
+ return scalaCompileOptions;
+ }
+
+ public void setScalaCompileOptions(ScalaCompileOptionsImpl scalaCompileOptions) {
+ this.scalaCompileOptions = scalaCompileOptions;
+ }
+
+ @Override
+ public String getSourceCompatibility() {
+ return sourceCompatibility;
+ }
+
+ public void setSourceCompatibility(String sourceCompatibility) {
+ this.sourceCompatibility = sourceCompatibility;
+ }
+
+ @Override
+ public String getTargetCompatibility() {
+ return targetCompatibility;
+ }
+
+ public void setTargetCompatibility(String targetCompatibility) {
+ this.targetCompatibility = targetCompatibility;
+ }
+}
diff --git a/plugins/gradle/testData/testDefaultDependenciesModel/build.gradle b/plugins/gradle/tooling-extension/testData/testDefaultDependenciesModel/build.gradle
similarity index 100%
rename from plugins/gradle/testData/testDefaultDependenciesModel/build.gradle
rename to plugins/gradle/tooling-extension/testData/testDefaultDependenciesModel/build.gradle
diff --git a/plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle b/plugins/gradle/tooling-extension/testData/testDefaultDependenciesModel/settings.gradle
similarity index 100%
rename from plugins/gradle/testData/testDefaultDependenciesModel/settings.gradle
rename to plugins/gradle/tooling-extension/testData/testDefaultDependenciesModel/settings.gradle
diff --git a/plugins/gradle/testData/testDefaultWarModel/build.gradle b/plugins/gradle/tooling-extension/testData/testDefaultWarModel/build.gradle
similarity index 100%
rename from plugins/gradle/testData/testDefaultWarModel/build.gradle
rename to plugins/gradle/tooling-extension/testData/testDefaultWarModel/build.gradle
diff --git a/plugins/gradle/testData/testDefaultWarModel/settings.gradle b/plugins/gradle/tooling-extension/testData/testDefaultWarModel/settings.gradle
similarity index 100%
rename from plugins/gradle/testData/testDefaultWarModel/settings.gradle
rename to plugins/gradle/tooling-extension/testData/testDefaultWarModel/settings.gradle
diff --git a/plugins/gradle/tooling-extension/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle b/plugins/gradle/tooling-extension/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
new file mode 100644
index 0000000..d4157ea
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testData/testGradleIdeaPluginPlusScopesDependenciesModel/build.gradle
@@ -0,0 +1,61 @@
+//noinspection GrPackage
+
+allprojects {
+ apply plugin: 'java'
+ apply plugin: 'idea'
+
+ version = '1.0'
+
+ sourceCompatibility = 1.6
+
+ configurations {
+ provided
+ }
+
+ sourceSets {
+ main {
+ compileClasspath += configurations.provided
+ }
+ }
+
+ idea {
+ module {
+ scopes.PROVIDED.plus += configurations.provided
+ }
+ }
+}
+
+project(":service") {
+ dependencies {
+ compile(project(':api'))
+ }
+}
+
+project(":api") {
+ dependencies {
+ provided(project(':lib'))
+ }
+}
+
+project(":withIdeaModelCustomisations") {
+ dependencies {
+ compile files("lib/someDep.jar")
+ testCompile files("lib/someTestDep.jar")
+ }
+
+ idea {
+ module {
+ scopes.COMPILE.plus += scopes.TEST.plus
+ scopes.TEST.plus = []
+ }
+ }
+}
+
+project(":withIdeRepoFileDependency") {
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ testCompile 'junit:junit:4.11'
+ }
+}
diff --git a/plugins/gradle/tooling-extension/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle b/plugins/gradle/tooling-extension/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
new file mode 100644
index 0000000..93a9186
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testData/testGradleIdeaPluginPlusScopesDependenciesModel/settings.gradle
@@ -0,0 +1,6 @@
+//noinspection GrPackage
+include "lib"
+include "api"
+include "service"
+include "withIdeaModelCustomisations"
+include "withIdeRepoFileDependency"
\ No newline at end of file
diff --git a/plugins/gradle/tooling-extension/testData/testGradleSourcesSetsInterpretation/build.gradle b/plugins/gradle/tooling-extension/testData/testGradleSourcesSetsInterpretation/build.gradle
new file mode 100644
index 0000000..eb35c27
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testData/testGradleSourcesSetsInterpretation/build.gradle
@@ -0,0 +1,103 @@
+//noinspection GrPackage
+
+project("defaultJavaModule") {
+ apply plugin: "java"
+}
+
+project("moduleWithSourceSetDirBothAsResourceAndJava") {
+ apply plugin: "java"
+
+ sourceSets.main.resources.srcDir 'src/main/java'
+ sourceSets.test.resources.srcDir 'src/test/java'
+}
+
+project("moduleWithCustomSourceSet") {
+ apply plugin: "java"
+
+ sourceSets {
+ custom
+ }
+
+ sourceSets.custom.java.srcDir 'src/custom/java'
+}
+
+project("withIntegrationTests") {
+ apply plugin: 'java'
+
+ sourceSets {
+ integrationTest {
+ java.srcDir file('src/integration-test/java')
+ resources.srcDir file('src/integration-test/resources')
+ }
+ }
+
+ dependencies {
+ integrationTestCompile sourceSets.main.output
+ integrationTestCompile configurations.testCompile
+ integrationTestCompile sourceSets.test.output
+ integrationTestRuntime configurations.testRuntime
+ }
+
+ //noinspection GrUnresolvedAccess
+ task integrationTest(type: Test, dependsOn: jar) {
+ testClassesDir = sourceSets.integrationTest.output.classesDir
+ classpath = sourceSets.integrationTest.runtimeClasspath
+ }
+
+ check.dependsOn integrationTest
+}
+
+project("withIdeaPluginCustomization1") {
+ apply plugin: 'java'
+
+ idea {
+ module {
+ testSourceDirs += file('src/intTest/java')
+ testSourceDirs += file('src/intTest/resources')
+ excludeDirs += file('some-extra-exclude-folder')
+ }
+ }
+}
+
+// see http://youtrack.jetbrains.com/issue/IDEA-119365
+project("withIdeaPluginCustomization2") {
+ apply plugin: 'java'
+
+ idea {
+ module {
+ sourceDirs += testSourceDirs
+ testSourceDirs = []
+ ext.resourceDirs += file('some-extra-resource-folder')
+ ext.testResourceDirs += file('some-extra-test-resource-folder')
+ }
+ }
+}
+
+// see http://youtrack.jetbrains.com/issue/IDEA-120562
+project("withIdeaPluginCustomization3") {
+ apply plugin: 'java'
+ apply plugin: 'idea'
+
+ idea {
+ module {
+ sourceDirs += file('src/main/java')
+ testSourceDirs += file('src/awesome-test/java')
+ testSourceDirs += file('src/awesome-with-resource-test/java')
+ ext.testResourceDirs += file('src/awesome-with-resource-test/resources')
+ }
+ }
+
+ sourceSets {
+ 'awesome-test' {
+ java {
+ srcDir 'src/awesome-test/java'
+ }
+ compileClasspath += sourceSets.main.runtimeClasspath
+ }
+ 'awesome-with-resource-test' {
+ java {
+ srcDir 'src/awesome-with-resource-test/java'
+ }
+ }
+ }
+}
diff --git a/plugins/gradle/tooling-extension/testData/testGradleSourcesSetsInterpretation/settings.gradle b/plugins/gradle/tooling-extension/testData/testGradleSourcesSetsInterpretation/settings.gradle
new file mode 100644
index 0000000..5e84e50
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testData/testGradleSourcesSetsInterpretation/settings.gradle
@@ -0,0 +1,9 @@
+//noinspection GrPackage
+
+include 'defaultJavaModule'
+include 'moduleWithSourceSetDirBothAsResourceAndJava'
+include 'moduleWithCustomSourceSet'
+include 'withIntegrationTests'
+include 'withIdeaPluginCustomization1'
+include 'withIdeaPluginCustomization2'
+include 'withIdeaPluginCustomization3'
\ No newline at end of file
diff --git a/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/build.gradle b/plugins/gradle/tooling-extension/testData/testModelBuildScriptClasspathBuilder/build.gradle
similarity index 100%
rename from plugins/gradle/testData/testModelBuildScriptClasspathBuilder/build.gradle
rename to plugins/gradle/tooling-extension/testData/testModelBuildScriptClasspathBuilder/build.gradle
diff --git a/plugins/gradle/testData/testModelBuildScriptClasspathBuilder/settings.gradle b/plugins/gradle/tooling-extension/testData/testModelBuildScriptClasspathBuilder/settings.gradle
similarity index 100%
rename from plugins/gradle/testData/testModelBuildScriptClasspathBuilder/settings.gradle
rename to plugins/gradle/tooling-extension/testData/testModelBuildScriptClasspathBuilder/settings.gradle
diff --git a/plugins/gradle/tooling-extension/testSources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/tooling-extension/testSources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
new file mode 100644
index 0000000..1ef2a6e
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
@@ -0,0 +1,19 @@
+#
+# Copyright 2000-2014 JetBrains s.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.
+#
+org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilderTest$TestModelBuilderService_v_1_8
+org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilderTest$TestModelBuilderService_v_1_8_or_Above
+org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilderTest$TestModelBuilderService_between_v_1_8_and_1_9
+org.jetbrains.plugins.gradle.tooling.internal.ExtraModelBuilderTest$TestModelBuilderService_between_v_1_8_and_1_9_NotBase
diff --git a/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
new file mode 100644
index 0000000..f5a5dfb
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/AbstractModelBuilderTest.java
@@ -0,0 +1,143 @@
+/*
+ * 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.gradle.tooling.builder;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.gradle.tooling.BuildActionExecuter;
+import org.gradle.tooling.GradleConnector;
+import org.gradle.tooling.ProjectConnection;
+import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.ProjectImportAction;
+import org.jetbrains.plugins.gradle.service.project.GradleExecutionHelper;
+import org.jetbrains.plugins.gradle.util.GradleConstants;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.rules.TestName;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/29/13
+ */
+@RunWith(value = Parameterized.class)
+public abstract class AbstractModelBuilderTest {
+
+ public static final String GRADLE_v1_9 = "1.9";
+ public static final String GRADLE_v1_10 = "1.10";
+ public static final String GRADLE_v1_11 = "1.11-rc-1";
+ public static final String GRADLE_v1_12 = "1.12-20140210235036+0000";
+
+ public static final Pattern TEST_METHOD_NAME_PATTERN;
+
+ static {
+ TEST_METHOD_NAME_PATTERN = Pattern.compile("(.*)\\[(\\d*)\\]");
+ }
+
+ private static File ourTempDir;
+
+ @NotNull
+ private final String gradleVersion;
+ protected File testDir;
+ protected ProjectImportAction.AllModels allModels;
+
+ @Rule public TestName name = new TestName();
+
+ public AbstractModelBuilderTest(@NotNull String gradleVersion) {
+ this.gradleVersion = gradleVersion;
+ }
+
+ @Parameterized.Parameters
+ public static Collection<Object[]> data() {
+ Object[][] data = new Object[][]{
+ {AbstractModelBuilderTest.GRADLE_v1_9},
+ {AbstractModelBuilderTest.GRADLE_v1_10},
+ {AbstractModelBuilderTest.GRADLE_v1_11},
+ {AbstractModelBuilderTest.GRADLE_v1_12}};
+ return Arrays.asList(data);
+ }
+
+
+ @Before
+ public void setUp() throws Exception {
+ ensureTempDirCreated();
+
+ String methodName = name.getMethodName();
+ Matcher m = TEST_METHOD_NAME_PATTERN.matcher(methodName);
+ if (m.matches()) {
+ methodName = m.group(1);
+ }
+
+ testDir = new File(ourTempDir, methodName);
+ testDir.mkdirs();
+
+ FileUtil.writeToFile(
+ new File(testDir, GradleConstants.DEFAULT_SCRIPT_NAME),
+ FileUtil.loadTextAndClose(getClass().getResourceAsStream(
+ String.format("/%s/%s", methodName, GradleConstants.DEFAULT_SCRIPT_NAME))
+ )
+ );
+
+ FileUtil.writeToFile(
+ new File(testDir, GradleConstants.SETTINGS_FILE_NAME),
+ FileUtil.loadTextAndClose(getClass().getResourceAsStream(
+ String.format("/%s/%s", methodName, GradleConstants.SETTINGS_FILE_NAME))
+ )
+ );
+
+ GradleConnector connector = GradleConnector.newConnector();
+
+ DefaultGradleConnector gradleConnector = (DefaultGradleConnector)connector;
+ gradleConnector.useGradleVersion(gradleVersion);
+ gradleConnector.forProjectDirectory(testDir);
+ ProjectConnection connection = gradleConnector.connect();
+
+ final ProjectImportAction projectImportAction = new ProjectImportAction(false);
+ projectImportAction.addExtraProjectModelClasses(getModels());
+ BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = connection.action(projectImportAction);
+ File initScript = GradleExecutionHelper.generateInitScript(false);
+ assertNotNull(initScript);
+ buildActionExecutor.withArguments(GradleConstants.INIT_SCRIPT_CMD_OPTION, initScript.getAbsolutePath());
+ allModels = buildActionExecutor.run();
+ assertNotNull(allModels);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ FileUtil.delete(testDir);
+ }
+
+ protected abstract Set<Class> getModels();
+
+ private static void ensureTempDirCreated() {
+ if (ourTempDir != null) return;
+
+ ourTempDir = new File(FileUtil.getTempDirectory(), "gradleTests");
+ FileUtil.delete(ourTempDir);
+ ourTempDir.mkdirs();
+ }
+}
diff --git a/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImplTest.java b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImplTest.java
new file mode 100644
index 0000000..c624b59
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModelBuildScriptClasspathBuilderImplTest.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.builder;
+
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.BuildScriptClasspathModel;
+import org.jetbrains.plugins.gradle.model.ClasspathEntryModel;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.*;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/16/14
+ */
+public class ModelBuildScriptClasspathBuilderImplTest extends AbstractModelBuilderTest {
+
+ public ModelBuildScriptClasspathBuilderImplTest(@NotNull String gradleVersion) {
+ super(gradleVersion);
+ }
+
+ @Test
+ public void testModelBuildScriptClasspathBuilder() throws Exception {
+
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ List<BuildScriptClasspathModel> ideaModule =
+ ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, BuildScriptClasspathModel>() {
+ @Override
+ public BuildScriptClasspathModel fun(IdeaModule module) {
+ BuildScriptClasspathModel classpathModel = allModels.getExtraProject(module, BuildScriptClasspathModel.class);
+
+ if (module.getName().equals("moduleWithAdditionalClasspath")) {
+ assertNotNull(classpathModel);
+ assertEquals(1, classpathModel.getClasspath().size());
+
+ ClasspathEntryModel classpathEntry = classpathModel.getClasspath().getAt(0);
+ assertEquals("someDep.jar", classpathEntry.getClassesFile().getName());
+ }
+ else if (module.getName().equals("baseModule") ||
+ module.getName().equals("moduleWithInheritedClasspath")) {
+ assertNotNull("Null build classpath for module: " + module.getName(), classpathModel);
+ assertEquals("Wrong build classpath for module: " + module.getName(), 1, classpathModel.getClasspath().size());
+
+ ClasspathEntryModel classpathEntry = classpathModel.getClasspath().getAt(0);
+ assertEquals("Wrong build classpath for module: " + module.getName(), "inheritedDep.jar",
+ classpathEntry.getClassesFile().getName());
+ }
+ else if (module.getName().equals("moduleWithoutAdditionalClasspath") ||
+ module.getName().equals("testModelBuildScriptClasspathBuilder")) {
+ assertNotNull("Wrong build classpath for module: " + module.getName(), classpathModel);
+ assertTrue("Wrong build classpath for module: " + module.getName(), classpathModel.getClasspath().isEmpty());
+ }
+ else {
+ fail("Unexpected module found: " + module.getName());
+ }
+
+ return classpathModel;
+ }
+ });
+
+ assertEquals(5, ideaModule.size());
+ }
+
+ @Override
+ protected Set<Class> getModels() {
+ return ContainerUtil.<Class>set(BuildScriptClasspathModel.class);
+ }
+}
diff --git a/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModelDependenciesBuilderImplTest.java b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModelDependenciesBuilderImplTest.java
new file mode 100644
index 0000000..decc2eb
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModelDependenciesBuilderImplTest.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.builder;
+
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaDependency;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaModuleDependency;
+import org.gradle.tooling.model.idea.IdeaSingleEntryLibraryDependency;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.GradleDependencyScope;
+import org.jetbrains.plugins.gradle.model.ProjectDependenciesModel;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.*;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/29/13
+ */
+public class ModelDependenciesBuilderImplTest extends AbstractModelBuilderTest {
+
+ public ModelDependenciesBuilderImplTest(@NotNull String gradleVersion) {
+ super(gradleVersion);
+ }
+
+ @Test
+ public void testDefaultDependenciesModel() throws Exception {
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ final int modulesSize = 3;
+ assertEquals(modulesSize, ideaModules.size());
+
+ for (IdeaModule ideaModule : ideaModules) {
+ if (ideaModule.getName().equals("dependencyProject") ||
+ ideaModule.getName().equals("testDefaultDependenciesModel")) {
+ DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
+ assertTrue((dependencies.isEmpty()));
+ }
+ else if (ideaModule.getName().equals("dependentProject")) {
+ DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
+ assertEquals(1, dependencies.size());
+ assertTrue(dependencies.getAt(0) instanceof IdeaModuleDependency);
+ IdeaModuleDependency moduleDependency = (IdeaModuleDependency)dependencies.getAt(0);
+
+ assertEquals("dependencyProject", moduleDependency.getDependencyModule().getName());
+ assertEquals("COMPILE", moduleDependency.getScope().getScope());
+ assertTrue(moduleDependency.getExported());
+ }
+ else {
+ fail();
+ }
+ }
+ }
+
+ @Test
+ public void testGradleIdeaPluginPlusScopesDependenciesModel() throws Exception {
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ final int modulesSize = 6;
+ assertEquals(modulesSize, ideaModules.size());
+
+ for (IdeaModule ideaModule : ideaModules) {
+ DomainObjectSet<? extends IdeaDependency> dependencies = ideaModule.getDependencies();
+ if (ideaModule.getName().equals("lib") ||
+ ideaModule.getName().equals("testGradleIdeaPluginPlusScopesDependenciesModel")) {
+ assertTrue((dependencies.isEmpty()));
+ }
+ else if (ideaModule.getName().equals("api")) {
+ assertEquals(1, dependencies.size());
+ IdeaDependency libDependency = dependencies.getAt(0);
+ assertEquals(GradleDependencyScope.PROVIDED.getIdeaMappingName(), libDependency.getScope().getScope().toLowerCase());
+ assertTrue(libDependency instanceof IdeaModuleDependency);
+
+ IdeaModuleDependency libModuleDependency = (IdeaModuleDependency)libDependency;
+ assertNotNull(libModuleDependency.getDependencyModule());
+ assertEquals("lib", libModuleDependency.getDependencyModule().getName());
+ }
+ else if (ideaModule.getName().equals("service")) {
+ assertEquals(1, dependencies.size());
+ IdeaDependency apiDependency = dependencies.getAt(0);
+ assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), apiDependency.getScope().getScope().toLowerCase());
+ assertTrue(apiDependency instanceof IdeaModuleDependency);
+
+ IdeaModuleDependency apiModuleDependency = (IdeaModuleDependency)apiDependency;
+ assertNotNull(apiModuleDependency.getDependencyModule());
+ assertEquals("api", apiModuleDependency.getDependencyModule().getName());
+ }
+ else if (ideaModule.getName().equals("withIdeaModelCustomisations")) {
+
+ assertTrue(findLocalLibraries(dependencies, GradleDependencyScope.TEST_COMPILE.getIdeaMappingName()).isEmpty());
+
+ List<IdeaSingleEntryLibraryDependency> libraryDependencies =
+ findLocalLibraries(dependencies, GradleDependencyScope.COMPILE.getIdeaMappingName());
+ assertEquals(2, libraryDependencies.size());
+
+ IdeaSingleEntryLibraryDependency someDep = libraryDependencies.get(0);
+ assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), someDep.getScope().getScope().toLowerCase());
+ assertEquals("someDep.jar", someDep.getFile().getName());
+
+ IdeaSingleEntryLibraryDependency someTestDep = libraryDependencies.get(1);
+ assertEquals(GradleDependencyScope.COMPILE.getIdeaMappingName(), someTestDep.getScope().getScope().toLowerCase());
+ assertEquals("someTestDep.jar", someTestDep.getFile().getName());
+ }
+ else if (ideaModule.getName().equals("withIdeRepoFileDependency")) {
+ assertEquals(2, dependencies.size());
+ assertTrue(dependencies.getAt(0) instanceof IdeaSingleEntryLibraryDependency);
+ IdeaSingleEntryLibraryDependency libraryDependency = (IdeaSingleEntryLibraryDependency)dependencies.getAt(0);
+
+ assertNotNull(libraryDependency.getGradleModuleVersion());
+ assertEquals("junit", libraryDependency.getGradleModuleVersion().getName());
+ assertEquals("junit", libraryDependency.getGradleModuleVersion().getGroup());
+ assertEquals("4.11", libraryDependency.getGradleModuleVersion().getVersion());
+ assertEquals("TEST", libraryDependency.getScope().getScope());
+ assertFalse(libraryDependency.getExported());
+ }
+ else {
+ fail();
+ }
+ }
+ }
+
+ @NotNull
+ private static List<IdeaSingleEntryLibraryDependency> findLocalLibraries(
+ @NotNull final DomainObjectSet<? extends IdeaDependency> dependencies, @NotNull final String scope) {
+ return ContainerUtil.mapNotNull(
+ dependencies,
+ new Function<IdeaDependency, IdeaSingleEntryLibraryDependency>() {
+ @Override
+ public IdeaSingleEntryLibraryDependency fun(IdeaDependency dependency) {
+ return dependency instanceof IdeaSingleEntryLibraryDependency && scope.equals(dependency.getScope().getScope().toLowerCase())
+ ? (IdeaSingleEntryLibraryDependency)dependency
+ : null;
+ }
+ }
+ );
+ }
+
+ @Override
+ protected Set<Class> getModels() {
+ return ContainerUtil.<Class>set(ProjectDependenciesModel.class);
+ }
+}
diff --git a/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImplTest.java b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImplTest.java
new file mode 100644
index 0000000..2187331
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/ModuleExtendedModelBuilderImplTest.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.builder;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.gradle.tooling.model.idea.IdeaSourceDirectory;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.ExtIdeaContentRoot;
+import org.jetbrains.plugins.gradle.model.ModuleExtendedModel;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 1/16/14
+ */
+public class ModuleExtendedModelBuilderImplTest extends AbstractModelBuilderTest {
+
+ public ModuleExtendedModelBuilderImplTest(@NotNull String gradleVersion) {
+ super(gradleVersion);
+ }
+
+ @Test
+ public void testGradleSourcesSetsInterpretation() throws Exception {
+ final int modulesSize = 8;
+
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ List<ModuleExtendedModel> models =
+ ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, ModuleExtendedModel>() {
+ @Override
+ public ModuleExtendedModel fun(IdeaModule module) {
+ ModuleExtendedModel moduleExtendedModel = allModels.getExtraProject(module, ModuleExtendedModel.class);
+
+ assertNotNull(moduleExtendedModel);
+
+ List<String> sourceDirectories = ContainerUtil.newArrayList();
+ List<String> resourceDirectories = ContainerUtil.newArrayList();
+ List<String> testResourceDirectories = ContainerUtil.newArrayList();
+ List<String> testDirectories = ContainerUtil.newArrayList();
+ List<String> excludeDirectories = ContainerUtil.newArrayList();
+
+ fillDirectories(moduleExtendedModel,
+ sourceDirectories, resourceDirectories,
+ testDirectories, testResourceDirectories,
+ excludeDirectories);
+
+ if (module.getName().equals("defaultJavaModule") || module.getName().equals("moduleWithSourceSetDirBothAsResourceAndJava")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("moduleWithCustomSourceSet")) {
+ assertEquals(ContainerUtil.newArrayList("src/custom/java", "src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/custom/resources", "src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIntegrationTests")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/integration-test/java", "src/integrationTest/java", "src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/integration-test/resources",
+ "src/integrationTest/resources",
+ "src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("testGradleSourcesSetsInterpretation")) {
+ assertTrue(sourceDirectories.isEmpty());
+ assertTrue(resourceDirectories.isEmpty());
+ assertTrue(testDirectories.isEmpty());
+ assertTrue(testResourceDirectories.isEmpty());
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIdeaPluginCustomization1")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/intTest/java", "src/intTest/resources", "src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList("src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build", "some-extra-exclude-folder"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIdeaPluginCustomization2")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java", "src/test/java", "src/test/resources"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList("some-extra-resource-folder", "src/main/resources"), resourceDirectories);
+ assertTrue(testDirectories.isEmpty());
+ assertEquals(ContainerUtil.newArrayList("some-extra-test-resource-folder"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else if (module.getName().equals("withIdeaPluginCustomization3")) {
+ assertEquals(ContainerUtil.newArrayList("src/main/java"), sourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/awesome-test/resources", "src/main/resources"), resourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/awesome-test/java", "src/awesome-with-resource-test/java", "src/test/java"), testDirectories);
+ assertEquals(ContainerUtil.newArrayList(
+ "src/awesome-with-resource-test/resources", "src/test/resources"), testResourceDirectories);
+ assertEquals(ContainerUtil.newArrayList(".gradle", "build"), excludeDirectories);
+ }
+ else {
+ fail();
+ }
+
+ return moduleExtendedModel;
+ }
+ });
+
+ assertEquals(modulesSize, models.size());
+ }
+
+ private void fillDirectories(final ModuleExtendedModel model,
+ List<String> sourceDirectories, List<String> resourceDirectories,
+ List<String> testDirectories, List<String> resourceTestDirectories,
+ List<String> excludeDirectories) {
+ for (ExtIdeaContentRoot contentRoot : model.getContentRoots()) {
+ sourceDirectories.addAll(getAllPaths(contentRoot.getSourceDirectories(), model.getName()));
+ resourceDirectories.addAll(getAllPaths(contentRoot.getResourceDirectories(), model.getName()));
+ testDirectories.addAll(getAllPaths(contentRoot.getTestDirectories(), model.getName()));
+ resourceTestDirectories.addAll(getAllPaths(contentRoot.getTestResourceDirectories(), model.getName()));
+ excludeDirectories.addAll(getAllPaths(contentRoot.getExcludeDirectories(), model.getName()));
+ }
+ }
+
+ private Collection<? extends String> getAllPaths(Collection<? extends File> directories, final String moduleName) {
+ List<String> list = ContainerUtil.map2List(directories, new Function<File, String>() {
+ @Override
+ public String fun(File sourceDirectory) {
+ String path =
+ FileUtil.toCanonicalPath(FileUtil.getRelativePath(new File(testDir, moduleName), sourceDirectory));
+ Assert.assertNotNull(path);
+ return path.substring(path.indexOf("/") + 1);
+ }
+ });
+ Collections.sort(list);
+ return list;
+ }
+
+ private Collection<? extends String> getAllPaths(DomainObjectSet<? extends IdeaSourceDirectory> directories, final String moduleName) {
+ List<String> list = ContainerUtil.map2List(directories, new Function<IdeaSourceDirectory, String>() {
+ @Override
+ public String fun(IdeaSourceDirectory sourceDirectory) {
+ String path =
+ FileUtil.toCanonicalPath(FileUtil.getRelativePath(new File(testDir, moduleName), sourceDirectory.getDirectory()));
+ Assert.assertNotNull(path);
+ return path.substring(path.indexOf("/") + 1);
+ }
+ });
+ Collections.sort(list);
+ return list;
+ }
+
+ @Override
+ protected Set<Class> getModels() {
+ return ContainerUtil.<Class>set(ModuleExtendedModel.class);
+ }
+}
+
diff --git a/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/WebConfigurationBuilderImplTest.java b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/WebConfigurationBuilderImplTest.java
new file mode 100644
index 0000000..55e6280
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/builder/WebConfigurationBuilderImplTest.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.gradle.tooling.builder;
+
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.gradle.tooling.model.DomainObjectSet;
+import org.gradle.tooling.model.idea.IdeaModule;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.gradle.model.WebConfiguration;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 11/29/13
+ */
+public class WebConfigurationBuilderImplTest extends AbstractModelBuilderTest {
+
+ public WebConfigurationBuilderImplTest(@NotNull String gradleVersion) {
+ super(gradleVersion);
+ }
+
+ @Test
+ public void testDefaultWarModel() throws Exception {
+ DomainObjectSet<? extends IdeaModule> ideaModules = allModels.getIdeaProject().getModules();
+
+ List<WebConfiguration> ideaModule = ContainerUtil.mapNotNull(ideaModules, new Function<IdeaModule, WebConfiguration>() {
+ @Override
+ public WebConfiguration fun(IdeaModule module) {
+ return allModels.getExtraProject(module, WebConfiguration.class);
+ }
+ });
+
+ assertEquals(1, ideaModule.size());
+ WebConfiguration webConfiguration = ideaModule.get(0);
+ assertEquals(1, webConfiguration.getWarModels().size());
+
+ final WebConfiguration.WarModel warModel = webConfiguration.getWarModels().iterator().next();
+ assertEquals("src/main/webapp", warModel.getWebAppDirName());
+ }
+
+ @Override
+ protected Set<Class> getModels() {
+ return ContainerUtil.<Class>set(WebConfiguration.class);
+ }
+}
diff --git a/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/internal/ExtraModelBuilderTest.java b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/internal/ExtraModelBuilderTest.java
new file mode 100644
index 0000000..a4b8d2f
--- /dev/null
+++ b/plugins/gradle/tooling-extension/testSources/org/jetbrains/plugins/gradle/tooling/internal/ExtraModelBuilderTest.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.gradle.tooling.internal;
+
+import org.gradle.api.Project;
+import org.gradle.util.GradleVersion;
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService;
+import org.jetbrains.plugins.gradle.tooling.annotation.TargetVersions;
+import org.junit.Test;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * @author Vladislav.Soroka
+ * @since 2/3/14
+ */
+public class ExtraModelBuilderTest {
+
+ @Test
+ public void testVersionMatching() throws Exception {
+
+ assertTrue(isMatching("1.8", TestModelBuilderService_v_1_8.class));
+ assertTrue(isMatching("1.8-rc-1", TestModelBuilderService_v_1_8.class));
+ assertFalse(isMatching("1.7", TestModelBuilderService_v_1_8.class));
+ assertFalse(isMatching("1.7-rc-1", TestModelBuilderService_v_1_8.class));
+ assertFalse(isMatching("1.9", TestModelBuilderService_v_1_8.class));
+
+ assertTrue(isMatching("1.8", TestModelBuilderService_v_1_8_or_Above.class));
+ assertTrue(isMatching("1.8-rc-1", TestModelBuilderService_v_1_8_or_Above.class));
+ assertFalse(isMatching("1.7", TestModelBuilderService_v_1_8_or_Above.class));
+ assertTrue(isMatching("1.9", TestModelBuilderService_v_1_8_or_Above.class));
+ assertTrue(isMatching("1.10", TestModelBuilderService_v_1_8_or_Above.class));
+
+ assertTrue(isMatching("1.8", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertTrue(isMatching("1.8-20130903233633+0000", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertFalse(isMatching("1.7", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertFalse(isMatching("1.7-20130903233633+0000", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertTrue(isMatching("1.9", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertTrue(isMatching("1.9-20131007220022+0000", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertFalse(isMatching("1.10", TestModelBuilderService_between_v_1_8_and_1_9.class));
+ assertFalse(isMatching("1.10-20131007220022+0000", TestModelBuilderService_between_v_1_8_and_1_9.class));
+
+ assertTrue(isMatching("1.8", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertFalse(isMatching("1.8-20130903233633+0000", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertFalse(isMatching("1.7", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertFalse(isMatching("1.7-20130903233633+0000", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertTrue(isMatching("1.9", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertTrue(isMatching("1.9-20131007220022+0000", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertFalse(isMatching("1.10", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ assertFalse(isMatching("1.10-20131007220022+0000", TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class));
+ }
+
+ @TargetVersions("1.8")
+ public static class TestModelBuilderService_v_1_8 implements ModelBuilderService {
+ @Override
+ public boolean canBuild(String modelName) {
+ return TestModelBuilderService_v_1_8.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ return null;
+ }
+ }
+
+ @TargetVersions("1.8+")
+ public static class TestModelBuilderService_v_1_8_or_Above implements ModelBuilderService {
+ @Override
+ public boolean canBuild(String modelName) {
+ return TestModelBuilderService_v_1_8_or_Above.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ return null;
+ }
+ }
+
+ @TargetVersions("1.8 <=> 1.9")
+ public static class TestModelBuilderService_between_v_1_8_and_1_9 implements ModelBuilderService {
+ @Override
+ public boolean canBuild(String modelName) {
+ return TestModelBuilderService_between_v_1_8_and_1_9.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ return null;
+ }
+ }
+
+ @TargetVersions(value = "1.8 <=> 1.9", checkBaseVersions = false)
+ public static class TestModelBuilderService_between_v_1_8_and_1_9_NotBase implements ModelBuilderService {
+ @Override
+ public boolean canBuild(String modelName) {
+ return TestModelBuilderService_between_v_1_8_and_1_9_NotBase.class.getName().equals(modelName);
+ }
+
+ @Override
+ public Object buildAll(String modelName, Project project) {
+ return null;
+ }
+ }
+
+
+ private static boolean isMatching(String version, Class<?> aClass) {
+ return new ExtraModelBuilder(GradleVersion.version(version)).canBuild(aClass.getName());
+ }
+}
diff --git a/plugins/groovy/jetgroovy.iml b/plugins/groovy/jetgroovy.iml
index bd8506c..c8bb19d 100644
--- a/plugins/groovy/jetgroovy.iml
+++ b/plugins/groovy/jetgroovy.iml
@@ -35,6 +35,7 @@
<orderEntry type="module" module-name="java-indexing-api" />
<orderEntry type="module" module-name="groovy-jps-plugin" />
<orderEntry type="module" module-name="ByteCodeViewer" />
+ <orderEntry type="module" module-name="properties-psi-api" />
</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 d2efa81..d8d3297 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
@@ -328,12 +328,18 @@
GroovycOSProcessHandler.OutputItem item,
Map<ModuleBuildTarget, String> generationOutputs,
String compilerOutput,
- ModuleBuildTarget srcTarget) throws IOException {
+ @NotNull ModuleBuildTarget srcTarget) throws IOException {
if (chunk.getModules().size() > 1 && !srcTarget.equals(chunk.representativeTarget())) {
File output = new File(item.outputPath);
+ String srcTargetOutput = generationOutputs.get(srcTarget);
+ if (srcTargetOutput == null) {
+ LOG.info("No output for " + srcTarget + "; outputs=" + generationOutputs + "; targets = " + chunk.getTargets());
+ return item.outputPath;
+ }
+
//todo honor package prefixes
- File correctRoot = new File(generationOutputs.get(srcTarget));
+ File correctRoot = new File(srcTargetOutput);
File correctOutput = new File(correctRoot, FileUtil.getRelativePath(new File(compilerOutput), output));
FileUtil.rename(output, correctOutput);
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 47b7fe5..9a5a3d0 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
@@ -58,14 +58,14 @@
super.notifyTextAvailable(text, outputType);
if (LOG.isDebugEnabled()) {
- LOG.debug("Received from groovyc: " + text);
+ LOG.debug("Received from groovyc " + outputType + ": " + text);
}
if (outputType == ProcessOutputTypes.SYSTEM) {
return;
}
- if (outputType == ProcessOutputTypes.STDERR) {
+ if (outputType == ProcessOutputTypes.STDERR && !text.startsWith("Picked up JAVA_TOOL_OPTIONS")) {
stdErr.append(StringUtil.convertLineSeparators(text));
return;
}
@@ -197,14 +197,17 @@
public boolean shouldRetry() {
if (getProcess().exitValue() != 0) {
+ LOG.debug("Non-zero exit code");
return true;
}
for (CompilerMessage message : compilerMessages) {
if (message.getKind() == BuildMessage.Kind.ERROR) {
+ LOG.debug("Error message: " + message);
return true;
}
}
if (getStdErr().length() > 0) {
+ LOG.debug("Non-empty stderr: '" + getStdErr() + "'");
return true;
}
return false;
diff --git a/plugins/groovy/resources/icons/JetgroovyIcons.java b/plugins/groovy/resources/icons/JetgroovyIcons.java
index 2781405..d7beb42 100644
--- a/plugins/groovy/resources/icons/JetgroovyIcons.java
+++ b/plugins/groovy/resources/icons/JetgroovyIcons.java
@@ -53,6 +53,7 @@
public static final Icon Groovy_16x16 = load("/icons/groovy/groovy_16x16.png"); // 16x16
public static final Icon Groovy_32x32 = load("/icons/groovy/groovy_32x32.png"); // 32x32
public static final Icon GroovyDoc = load("/icons/groovy/GroovyDoc.png"); // 16x16
+ public static final Icon GroovyModule = load("/icons/groovy/groovyModule.png"); // 24x24
public static final Icon Interface = load("/icons/groovy/interface.png"); // 16x16
public static final Icon Method = load("/icons/groovy/method.png"); // 16x16
public static final Icon Property = load("/icons/groovy/property.png"); // 16x16
diff --git a/plugins/groovy/resources/icons/groovy/groovyModule.png b/plugins/groovy/resources/icons/groovy/groovyModule.png
new file mode 100644
index 0000000..278c0d8
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/groovyModule.png
Binary files differ
diff --git a/plugins/groovy/resources/icons/groovy/groovyModule@2x.png b/plugins/groovy/resources/icons/groovy/groovyModule@2x.png
new file mode 100644
index 0000000..b421a44
--- /dev/null
+++ b/plugins/groovy/resources/icons/groovy/groovyModule@2x.png
Binary files differ
diff --git a/plugins/groovy/resources/intentionDescriptions/GrRedundantElseIntention/description.html b/plugins/groovy/resources/intentionDescriptions/GrRedundantElseIntention/description.html
index 416ec7a..d819b88 100644
--- a/plugins/groovy/resources/intentionDescriptions/GrRedundantElseIntention/description.html
+++ b/plugins/groovy/resources/intentionDescriptions/GrRedundantElseIntention/description.html
@@ -1,7 +1,5 @@
<html>
<body>
This intention detaches <b>else</b> clause from the <b>if</b> statement, if corresponding <b>then</b> clause never completes normally.
-<!-- tooltip end -->
-Text after this comment will not be shown in tooltips.
</body>
</html>
\ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/after.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/after.groovy.template
new file mode 100644
index 0000000..3aac7db
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/after.groovy.template
@@ -0,0 +1,3 @@
+def phones = [Ann : 23467,
+ Max : 78564,
+ Peter: 45678]
\ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/before.groovy.template b/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/before.groovy.template
new file mode 100644
index 0000000..eb77284
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/before.groovy.template
@@ -0,0 +1 @@
+def phones = [Peter: 45678, Max : 78564, Ann : 23467]
\ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/description.html b/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/description.html
new file mode 100644
index 0000000..eb90b0c
--- /dev/null
+++ b/plugins/groovy/resources/intentionDescriptions/GrSortMapKeysIntention/description.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+This intention sorts map entries alphabetically.
+</body>
+</html>
\ No newline at end of file
diff --git a/plugins/groovy/resources/intentionDescriptions/ReplaceIfWithTernaryIntention/description.html b/plugins/groovy/resources/intentionDescriptions/ReplaceIfWithTernaryIntention/description.html
index e7e00ed..6311f24 100644
--- a/plugins/groovy/resources/intentionDescriptions/ReplaceIfWithTernaryIntention/description.html
+++ b/plugins/groovy/resources/intentionDescriptions/ReplaceIfWithTernaryIntention/description.html
@@ -1,7 +1,5 @@
<html>
<body>
This intention replaces if-statement with equivalent ternary operator
-<!-- tooltip end -->
-Text after this comment will not be shown in tooltips.
</body>
</html>
\ No newline at end of file
diff --git a/plugins/groovy/resources/standardDsls/defaultMethods.gdsl b/plugins/groovy/resources/standardDsls/defaultMethods.gdsl
index 8464717..e9f72c8 100644
--- a/plugins/groovy/resources/standardDsls/defaultMethods.gdsl
+++ b/plugins/groovy/resources/standardDsls/defaultMethods.gdsl
@@ -18,7 +18,6 @@
import com.intellij.psi.PsiType
import com.intellij.psi.util.PsiUtil
-import static standardDsls.Constants.STRING
/**
* @author Maxim.Medvedev
*/
@@ -61,27 +60,6 @@
delegatesTo(findClass("java.lang.String"))
}
-[Integer, Double, Float, Byte, Long, Short, Number].each {
- def className = it.canonicalName
- contributor(ctype: className) {
- method name: "plus", type: className, params: [arg: className]
- method name: "minus", type: className, params: [arg: className]
- method name: "multiply", type: className, params: [arg: className]
- method name: "power", type: className, params: [arg: className]
- method name: "div", type: className, params: [arg: className]
- method name: "mod", type: className, params: [arg: className]
- method name: "or", type: className, params: [arg: className]
- method name: "and", type: className, params: [arg: className]
- method name: "xor", type: className, params: [arg: className]
- method name: "next", type: className
- method name: "previous", type: className
- method name: "negative", type: className
- method name: "positive", type: className
-
- method name: "plus", type: STRING, params: [arg: STRING]
- }
-}
-
contributor(ctype: 'groovy.lang.MetaClass') {
property name: 'static'
}
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 d340342..835c91d 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
@@ -188,13 +188,7 @@
continue;
}
- unit.addSource(new SourceUnit(file, unit.getConfiguration(), unit.getClassLoader(), unit.getErrorCollector()) {
- public void parse() throws CompilationFailedException {
- System.out.println(GroovyRtConstants.PRESENTABLE_MESSAGE + "Parsing " + file.getName() + "...");
- super.parse();
- System.out.println(GroovyRtConstants.CLEAR_PRESENTABLE);
- }
- });
+ unit.addSource(new SourceUnit(file, unit.getConfiguration(), unit.getClassLoader(), unit.getErrorCollector()));
}
}
diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml
index da7ed7e..f069024 100644
--- a/plugins/groovy/src/META-INF/plugin.xml
+++ b/plugins/groovy/src/META-INF/plugin.xml
@@ -105,6 +105,8 @@
<membersContributor implementation="org.jetbrains.plugins.groovy.markup.XmlMarkupBuilderNonCodeMemberContributor"/>
+ <closureMissingMethodContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.PluginXmlClosureMemberContributor"/>
+
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.DelegatedMethodsContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.AutoExternalizeContributor"/>
<astTransformContributor implementation="org.jetbrains.plugins.groovy.lang.resolve.ast.AutoCloneContributor"/>
@@ -189,7 +191,7 @@
</extensions>
<extensions defaultExtensionNs="com.intellij">
- <navbar implementation="org.jetbrains.plugins.groovy.navbar.GrNavBarModelExtension"/>
+ <navbar implementation="org.jetbrains.plugins.groovy.navbar.GrNavBarModelExtension" order="after defaultNavbar"/>
<declarationRangeHandler key="org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod"
implementationClass="org.jetbrains.plugins.groovy.codeInsight.hint.GrMethodDeclarationRangeHandler"/>
@@ -1408,6 +1410,13 @@
<categoryKey>intention.category.groovy.other</categoryKey>
<className>org.jetbrains.plugins.groovy.intentions.other.GrCopyStringConcatenationContentIntention</className>
</intentionAction>
+
+ <intentionAction>
+ <bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
+ <categoryKey>intention.category.groovy.other</categoryKey>
+ <className>org.jetbrains.plugins.groovy.intentions.other.GrSortMapKeysIntention</className>
+ </intentionAction>
+
<intentionAction>
<bundleName>org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle</bundleName>
<categoryKey>intention.category.groovy.declaration</categoryKey>
@@ -1555,14 +1564,12 @@
icon="JetgroovyIcons.Groovy.GroovyDoc">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</action>
-<!--
<action id="Groovy.Shell"
class="org.jetbrains.plugins.groovy.console.GroovyShellAction"
text="Groovy Shell..." description="Launch Groovy Shell"
icon="JetgroovyIcons.Groovy.Groovy_16x16">
<add-to-group group-id="ToolsMenu" anchor="last"/>
</action>
--->
<action id="Groovy.Console"
class="org.jetbrains.plugins.groovy.console.GroovyConsoleAction"
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.java
index d2f8ba7..9b587e2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -30,20 +30,16 @@
*/
public class GroovyBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.groovy.GroovyBundle";
-
- @NotNull
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.groovy.GroovyBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
@@ -51,5 +47,4 @@
}
return bundle;
}
-
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
index 3bce9ce..c3b8164 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/GroovyBundle.properties
@@ -371,3 +371,4 @@
mixing.private.and.public.protected.methods.of.the.same.name=Mixing private and public/protected methods of the same name
explicit.constructors.are.not.allowed.in.immutable.class=Explicit constructors are not allowed for @Immutable class
repetitive.method.name.0=Repetitive method name ''{0}''
+assign.expected='=' expected
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java
index bcba952..6c34488 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/DumpGroovyControlFlowAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -74,7 +74,7 @@
final List<GrControlFlowOwner> result = new ArrayList<GrControlFlowOwner>();
for (GrControlFlowOwner owner = ControlFlowUtils.findControlFlowOwner(elementAtCaret);
- owner != null;
+ owner != null && !result.contains(owner);
owner = ControlFlowUtils.findControlFlowOwner(owner)) {
result.add(owner);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyCodeInsightBundle.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyCodeInsightBundle.java
index 615e0be..1823fd7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyCodeInsightBundle.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyCodeInsightBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.actions.generate;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.util.ResourceBundle;
@@ -29,23 +30,21 @@
* Date: 02.06.2008
*/
public class GroovyCodeInsightBundle {
- private static Reference<ResourceBundle> ourBundle;
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.groovy.actions.generate.GroovyCodeInsightBundle";
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.groovy.actions.generate.GroovyCodeInsightBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
- ourBundle = new SoftReference<ResourceBundle >(bundle);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
}
return bundle;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyGenerationInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyGenerationInfo.java
index 2ebb3e4..068e96d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyGenerationInfo.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/GroovyGenerationInfo.java
@@ -39,11 +39,10 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.refactoring.GroovyChangeContextUtil;
-import static org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil.isWhiteSpace;
-
/**
* @author peter
*/
@@ -147,12 +146,12 @@
if (body != null) {
PsiElement l = body.getLBrace();
if (l != null) l = l.getNextSibling();
- while (isWhiteSpace(l)) l = l.getNextSibling();
+ while (PsiImplUtil.isWhiteSpaceOrNls(l)) l = l.getNextSibling();
if (l == null) l = body;
PsiElement r = body.getRBrace();
if (r != null) r = r.getPrevSibling();
- while (isWhiteSpace(r)) r = r.getPrevSibling();
+ while (PsiImplUtil.isWhiteSpaceOrNls(r)) r = r.getPrevSibling();
if (r == null) r = body;
int start = l.getTextRange().getStartOffset();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/equals/GroovyGenerateEqualsHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/equals/GroovyGenerateEqualsHandler.java
index d48edee..94545ec 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/equals/GroovyGenerateEqualsHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/equals/GroovyGenerateEqualsHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -77,7 +77,7 @@
if (Messages.showYesNoDialog(project, text,
GroovyCodeInsightBundle.message("generate.equals.and.hashcode.already.defined.title"),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getQuestionIcon()) == Messages.YES) {
if (!ApplicationManager.getApplication().runWriteAction(new Computable<Boolean>() {
public Boolean compute() {
try {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGenerateMethodMissingHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGenerateMethodMissingHandler.java
index fe4cf52..5b11c73 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGenerateMethodMissingHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGenerateMethodMissingHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -25,7 +25,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
@@ -127,7 +126,7 @@
if (Messages.showYesNoDialog(project, text,
GroovyCodeInsightBundle.message("generate.method.missing.already.defined.title"),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getQuestionIcon()) == Messages.YES) {
final PsiMethod finalMethod = method;
if (!ApplicationManager.getApplication().runWriteAction(new Computable<Boolean>() {
public Boolean compute() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGeneratePropertyMissingHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGeneratePropertyMissingHandler.java
index ed21afa..857d1d1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGeneratePropertyMissingHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/actions/generate/missing/GroovyGeneratePropertyMissingHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -25,7 +25,6 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
@@ -158,7 +157,7 @@
if (Messages.showYesNoDialog(project, text,
GroovyCodeInsightBundle.message("generate.property.missing.already.defined.title"),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE) {
+ Messages.getQuestionIcon()) == Messages.YES) {
final PsiMethod finalGetter = getter;
final PsiMethod finalSetter = setter;
if (!ApplicationManager.getApplication().runWriteAction(new Computable<Boolean>() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrRemoveAnnotationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrRemoveAnnotationIntention.java
new file mode 100644
index 0000000..ca371b9
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GrRemoveAnnotationIntention.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.annotator;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.intentions.base.Intention;
+import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
+
+/**
+ * Created by Max Medvedev on 06/02/14
+ */
+public class GrRemoveAnnotationIntention extends Intention {
+ @Override
+ protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
+ element.delete();
+ }
+
+ @NotNull
+ @Override
+ protected PsiElementPredicate getElementPredicate() {
+ return new PsiElementPredicate() {
+ @Override
+ public boolean satisfiedBy(PsiElement element) {
+ return element instanceof GrAnnotation;
+ }
+ };
+ }
+}
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 cea5b5b..e8af932 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/GroovyAnnotator.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,12 +17,16 @@
package org.jetbrains.plugins.groovy.annotator;
import com.intellij.codeInsight.ClassUtil;
+import com.intellij.codeInsight.daemon.impl.analysis.HighlightClassUtil;
import com.intellij.codeInsight.daemon.impl.quickfix.AddMethodBodyFix;
import com.intellij.codeInsight.daemon.impl.quickfix.CreateConstructorMatchingSuperFix;
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteMethodBodyFix;
import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.QuickFixFactory;
+import com.intellij.codeInspection.InspectionManager;
+import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
@@ -50,6 +54,7 @@
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.annotator.intentions.*;
+import org.jetbrains.plugins.groovy.codeInspection.bugs.GrModifierFix;
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.lang.documentation.GroovyPresentationUtil;
@@ -207,7 +212,7 @@
if (typeElement instanceof GrDisjunctionTypeElement) {
final GrTypeElement[] elements = ((GrDisjunctionTypeElement)typeElement).getTypeElements();
- PsiType[] types = new PsiType[elements.length];
+ PsiType[] types = PsiType.createArray(elements.length);
for (int i = 0; i < elements.length; i++) {
types[i] = elements[i].getType();
}
@@ -297,6 +302,7 @@
checkThisOrSuperReferenceExpression(referenceExpression, myHolder);
checkFinalFieldAccess(referenceExpression);
checkFinalParameterAccess(referenceExpression);
+
if (ResolveUtil.isKeyOfMap(referenceExpression)) {
PsiElement nameElement = referenceExpression.getReferenceNameElement();
LOG.assertTrue(nameElement != null);
@@ -586,7 +592,7 @@
checkOverridingMethod(myHolder, method);
}
- private void checkGetterOfImmutable(AnnotationHolder holder, GrMethod method) {
+ private static void checkGetterOfImmutable(AnnotationHolder holder, GrMethod method) {
if (!GroovyPropertyUtils.isSimplePropertyGetter(method)) return;
PsiClass aClass = method.getContainingClass();
@@ -943,8 +949,8 @@
if (modifierList.hasExplicitModifier(VOLATILE) && modifierList.hasExplicitModifier(FINAL)) {
final Annotation annotation =
holder.createErrorAnnotation(modifierList, GroovyBundle.message("illegal.combination.of.modifiers.volatile.and.final"));
- annotation.registerFix(new GrModifierFix(member, modifierList, VOLATILE, true, false));
- annotation.registerFix(new GrModifierFix(member, modifierList, FINAL, true, false));
+ registerFix(annotation, new GrModifierFix(member, VOLATILE, true, false, GrModifierFix.MODIFIER_LIST), modifierList);
+ registerFix(annotation, new GrModifierFix(member, FINAL, true, false, GrModifierFix.MODIFIER_LIST), modifierList);
}
checkModifierIsNotAllowed(modifierList, NATIVE, GroovyBundle.message("variable.cannot.be.native"), holder);
@@ -957,6 +963,16 @@
}
}
+ private static void registerFix(Annotation annotation, LocalQuickFix fix, PsiElement place) {
+ final InspectionManager manager = InspectionManager.getInstance(place.getProject());
+ assert !place.getTextRange().isEmpty();
+
+ final ProblemDescriptor descriptor = manager.createProblemDescriptor(place, place, annotation.getMessage(),
+ annotation.getHighlightType(), true, LocalQuickFix.EMPTY_ARRAY);
+ final TextRange range = TextRange.create(annotation.getStartOffset(), annotation.getEndOffset());
+ annotation.registerFix(fix, range, null, descriptor);
+ }
+
private static void checkModifierIsNotAllowed(@NotNull GrModifierList modifierList,
@NotNull @GrModifier.GrModifierConstant String modifier,
@Nullable String message,
@@ -970,10 +986,9 @@
@NotNull AnnotationHolder holder,
final boolean explicit) {
if (explicit ? modifierList.hasModifierProperty(modifier) : modifierList.hasExplicitModifier(modifier)) {
- PsiElement toHighlight = PsiUtil.findModifierInList(modifierList, modifier);
- if (toHighlight == null) toHighlight = modifierList;
- final Annotation annotation = holder.createErrorAnnotation(toHighlight, message);
- annotation.registerFix(new GrModifierFix((PsiMember)modifierList.getParent(), modifierList, modifier, true, false));
+ PsiElement modifierOrList = getModifierOrList(modifierList, modifier);
+ final Annotation annotation = holder.createErrorAnnotation(modifierOrList, message);
+ registerFix(annotation, new GrModifierFix((PsiMember)modifierList.getParent(), modifier, true, false, GrModifierFix.MODIFIER_LIST), modifierList);
}
}
@@ -1095,9 +1110,8 @@
private void checkTypeArgForPrimitive(@Nullable GrTypeElement element, String message) {
if (element == null || !(element.getType() instanceof PsiPrimitiveType)) return;
- myHolder.
- createErrorAnnotation(element, message).
- registerFix(new GrReplacePrimitiveTypeWithWrapperFix(element));
+ final Annotation annotation = myHolder.createErrorAnnotation(element, message);
+ registerFix(annotation, new GrReplacePrimitiveTypeWithWrapperFix(element), element);
}
@Override
@@ -1426,6 +1440,7 @@
}
+ @Override
public void visitAnnotation(GrAnnotation annotation) {
final GrCodeReferenceElement ref = annotation.getClassReference();
final PsiElement resolved = ref.resolve();
@@ -1448,7 +1463,7 @@
String description = CustomAnnotationChecker.isAnnotationApplicable(annotation, annotation.getParent());
if (description != null) {
- myHolder.createErrorAnnotation(ref, description);
+ myHolder.createErrorAnnotation(ref, description).registerFix(new GrRemoveAnnotationIntention());
}
}
@@ -1464,7 +1479,8 @@
}
Map<PsiElement, String> errors = ContainerUtil.newHashMap();
- CustomAnnotationChecker.checkAnnotationArguments(errors, anno, annotation.getClassReference(), annotationArgumentList.getAttributes(), true);
+ CustomAnnotationChecker.checkAnnotationArguments(errors, anno, annotation.getClassReference(), annotationArgumentList.getAttributes(),
+ true);
for (Map.Entry<PsiElement, String> entry : errors.entrySet()) {
myHolder.createErrorAnnotation(entry.getKey(), entry.getValue());
}
@@ -1500,11 +1516,14 @@
}
final GrAnnotationMemberValue value = nameValuePair.getValue();
-
- checkAnnotationAttributeValue(value, value);
+ if (value != null) {
+ checkAnnotationAttributeValue(value, value);
+ }
}
- private boolean checkAnnotationAttributeValue(GrAnnotationMemberValue value, PsiElement toHighlight) {
+ private boolean checkAnnotationAttributeValue(@Nullable GrAnnotationMemberValue value, @NotNull PsiElement toHighlight) {
+ if (value == null) return false;
+
if (value instanceof GrLiteral) return false;
if (value instanceof GrClosableBlock) return false;
if (value instanceof GrAnnotation) return false;
@@ -1544,6 +1563,12 @@
}
return false;
}
+ if (value instanceof GrUnaryExpression) {
+ final IElementType tokenType = ((GrUnaryExpression)value).getOperationTokenType();
+ if (tokenType == GroovyTokenTypes.mMINUS || tokenType == GroovyTokenTypes.mPLUS) {
+ return checkAnnotationAttributeValue(((GrUnaryExpression)value).getOperand(), toHighlight);
+ }
+ }
myHolder.createErrorAnnotation(toHighlight, GroovyBundle.message("expected.0.to.be.inline.constant", value.getText()));
return true;
@@ -1736,12 +1761,12 @@
}
if (!JavaPsiFacade.getInstance(typeDefinition.getProject()).getResolveHelper().isAccessible(abstractMethod, typeDefinition, null)) {
- annotation.registerFix(new GrModifierFix(abstractMethod, abstractMethod.getModifierList(), PUBLIC, true, true));
- annotation.registerFix(new GrModifierFix(abstractMethod, abstractMethod.getModifierList(), PROTECTED, true, true));
+ registerFix(annotation, new GrModifierFix(abstractMethod, PUBLIC, true, true, GrModifierFix.MODIFIER_LIST_OWNER), abstractMethod);
+ registerFix(annotation, new GrModifierFix(abstractMethod, PROTECTED, true, true, GrModifierFix.MODIFIER_LIST_OWNER), abstractMethod);
}
if (!(typeDefinition instanceof GrAnnotationTypeDefinition) && typeDefinition.getModifierList() != null) {
- annotation.registerFix(new GrModifierFix(typeDefinition, typeDefinition.getModifierList(), ABSTRACT, false, true));
+ registerFix(annotation, new GrModifierFix(typeDefinition, ABSTRACT, false, true, GrModifierFix.MODIFIER_LIST_OWNER), typeDefinition);
}
}
@@ -1759,13 +1784,13 @@
else {
annotation.registerFix(new DeleteMethodBodyFix(method));
}
- annotation.registerFix(new GrModifierFix(method, method.getModifierList(), ABSTRACT, false, false));
+ registerFix(annotation, new GrModifierFix(method, ABSTRACT, false, false, GrModifierFix.MODIFIER_LIST_OWNER), method);
if (makeClassAbstract) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass != null) {
- final GrModifierList list = (GrModifierList)containingClass.getModifierList();
+ final PsiModifierList list = containingClass.getModifierList();
if (list != null && !list.hasModifierProperty(ABSTRACT)) {
- annotation.registerFix(new GrModifierFix(containingClass, list, ABSTRACT, false, true));
+ registerFix(annotation, new GrModifierFix(containingClass, ABSTRACT, false, true, GrModifierFix.MODIFIER_LIST), list);
}
}
}
@@ -1779,12 +1804,7 @@
checkModifierIsNotAllowed(modifiersList, VOLATILE, GroovyBundle.message("method.has.incorrect.modifier.volatile"), holder);
- if (method.hasModifierProperty(FINAL) && method.hasModifierProperty(ABSTRACT)) {
- final Annotation annotation =
- holder.createErrorAnnotation(modifiersList, GroovyBundle.message("illegal.combination.of.modifiers.abstract.and.final"));
- annotation.registerFix(new GrModifierFix(method, modifiersList, FINAL, false, false));
- annotation.registerFix(new GrModifierFix(method, modifiersList, ABSTRACT, false, false));
- }
+ checkForAbstractAndFinalCombination(holder, method, modifiersList);
//script methods
boolean isMethodAbstract = modifiersList.hasExplicitModifier(ABSTRACT);
@@ -1835,11 +1855,19 @@
if (method.hasModifierProperty(NATIVE) && method.getBlock() != null) {
final Annotation annotation = holder.createErrorAnnotation(getModifierOrList(modifiersList, NATIVE),
GroovyBundle.message("native.methods.cannot.have.body"));
- annotation.registerFix(new GrModifierFix((PsiMember)modifiersList.getParent(), modifiersList, NATIVE, true, false));
+ registerFix(annotation, new GrModifierFix((PsiMember)modifiersList.getParent(), NATIVE, true, false, GrModifierFix.MODIFIER_LIST), modifiersList);
annotation.registerFix(new DeleteMethodBodyFix(method));
}
}
+ private static void checkForAbstractAndFinalCombination(AnnotationHolder holder, GrMember member, GrModifierList modifiersList) {
+ if (member.hasModifierProperty(FINAL) && member.hasModifierProperty(ABSTRACT)) {
+ final Annotation annotation = holder.createErrorAnnotation(modifiersList, GroovyBundle.message("illegal.combination.of.modifiers.abstract.and.final"));
+ registerFix(annotation, new GrModifierFix(member, FINAL, false, false, GrModifierFix.MODIFIER_LIST), modifiersList);
+ registerFix(annotation, new GrModifierFix(member, ABSTRACT, false, false, GrModifierFix.MODIFIER_LIST), modifiersList);
+ }
+ }
+
@NotNull
private static PsiElement getModifierOrList(@NotNull GrModifierList modifiersList, @GrModifier.GrModifierConstant final String modifier) {
PsiElement m = PsiUtil.findModifierInList(modifiersList, modifier);
@@ -1877,17 +1905,13 @@
PsiClass psiClass = classType.resolve();
if (psiClass != null && psiClass.hasModifierProperty(FINAL)) {
- final Annotation annotation =
- holder.createErrorAnnotation(typeDefinition.getNameIdentifierGroovy(), GroovyBundle.message("final.class.cannot.be.extended"));
- annotation.registerFix(new GrModifierFix(typeDefinition, modifiersList, FINAL, false, false));
+ final Annotation annotation = holder.createErrorAnnotation(typeDefinition.getNameIdentifierGroovy(), GroovyBundle.message("final.class.cannot.be.extended"));
+ registerFix(annotation, new GrModifierFix(typeDefinition, FINAL, false, false, GrModifierFix.MODIFIER_LIST_OWNER), typeDefinition);
}
}
- if (!typeDefinition.isEnum() && modifiersList.hasModifierProperty(ABSTRACT) && modifiersList.hasModifierProperty(FINAL)) {
- final Annotation annotation =
- holder.createErrorAnnotation(modifiersList, GroovyBundle.message("illegal.combination.of.modifiers.abstract.and.final"));
- annotation.registerFix(new GrModifierFix(typeDefinition, modifiersList, FINAL, false, false));
- annotation.registerFix(new GrModifierFix(typeDefinition, modifiersList, ABSTRACT, false, false));
+ if (!typeDefinition.isEnum()) {
+ checkForAbstractAndFinalCombination(holder, typeDefinition, modifiersList);
}
checkModifierIsNotAllowed(modifiersList, TRANSIENT, GroovyBundle.message("modifier.transient.not.allowed.here"), holder);
@@ -1907,7 +1931,7 @@
@GrModifier.GrModifierConstant String name = modifier.getText();
if (set.contains(name)) {
final Annotation annotation = holder.createErrorAnnotation(list, GroovyBundle.message("duplicate.modifier", name));
- annotation.registerFix(new GrModifierFix(member, list, name, false, false));
+ registerFix(annotation, new GrModifierFix(member, name, false, false, GrModifierFix.MODIFIER_LIST), list);
}
else {
set.add(name);
@@ -1923,13 +1947,13 @@
if (hasPrivate && hasPublic || hasPrivate && hasProtected || hasPublic && hasProtected) {
final Annotation annotation = holder.createErrorAnnotation(modifierList, GroovyBundle.message("illegal.combination.of.modifiers"));
if (hasPrivate) {
- annotation.registerFix(new GrModifierFix(member, modifierList, PRIVATE, false, false));
+ registerFix(annotation, new GrModifierFix(member, PRIVATE, false, false, GrModifierFix.MODIFIER_LIST), modifierList);
}
if (hasProtected) {
- annotation.registerFix(new GrModifierFix(member, modifierList, PROTECTED, false, false));
+ registerFix(annotation, new GrModifierFix(member, PROTECTED, false, false, GrModifierFix.MODIFIER_LIST), modifierList);
}
if (hasPublic) {
- annotation.registerFix(new GrModifierFix(member, modifierList, PUBLIC, false, false));
+ registerFix(annotation, new GrModifierFix(member, PUBLIC, false, false, GrModifierFix.MODIFIER_LIST), modifierList);
}
}
else if (member instanceof PsiMethod &&
@@ -1937,8 +1961,8 @@
hasPublic &&
!GroovyConfigUtils.getInstance().isVersionAtLeast(member, "1.8.4")) {
final PsiElement publicModifier = ObjectUtils.assertNotNull(PsiUtil.findModifierInList(modifierList, PUBLIC));
- holder.createErrorAnnotation(publicModifier, GroovyBundle.message("public.modifier.is.not.allowed.in.interfaces"))
- .registerFix(new GrModifierFix(member, modifierList, PUBLIC, false, false));
+ final Annotation annotation = holder.createErrorAnnotation(publicModifier, GroovyBundle.message("public.modifier.is.not.allowed.in.interfaces"));
+ registerFix(annotation, new GrModifierFix(member, PUBLIC, false, false, GrModifierFix.MODIFIER_LIST), modifierList);
}
else if (member instanceof PsiClass &&
member.getContainingClass() == null &&
@@ -2000,7 +2024,7 @@
private static void checkCyclicInheritance(AnnotationHolder holder,
GrTypeDefinition typeDefinition) {
- final PsiClass psiClass = getCircularClass(typeDefinition, new HashSet<PsiClass>());
+ final PsiClass psiClass = HighlightClassUtil.getCircularClass(typeDefinition, new HashSet<PsiClass>());
if (psiClass != null) {
String qname = psiClass.getQualifiedName();
assert qname != null;
@@ -2009,31 +2033,6 @@
}
}
- @Nullable
- private static PsiClass getCircularClass(PsiClass aClass, Collection<PsiClass> usedClasses) {
- if (usedClasses.contains(aClass)) {
- return aClass;
- }
- try {
- usedClasses.add(aClass);
- PsiClass[] superTypes = aClass.getSupers();
- for (PsiElement superType : superTypes) {
- while (superType instanceof PsiClass) {
- if (!CommonClassNames.JAVA_LANG_OBJECT.equals(((PsiClass)superType).getQualifiedName())) {
- PsiClass circularClass = getCircularClass((PsiClass)superType, usedClasses);
- if (circularClass != null) return circularClass;
- }
- // check class qualifier
- superType = superType.getParent();
- }
- }
- }
- finally {
- usedClasses.remove(aClass);
- }
- return null;
- }
-
private static void checkForWildCards(AnnotationHolder holder, @Nullable GrReferenceList clause) {
if (clause == null) return;
final GrCodeReferenceElement[] elements = clause.getReferenceElementsGroovy();
@@ -2083,7 +2082,7 @@
String packageName = "<default package>";
if (file instanceof GroovyFile) {
final String name = ((GroovyFile)file).getPackageName();
- if (name.length() > 0) packageName = name;
+ if (!name.isEmpty()) packageName = name;
}
return packageName;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.java
index da0689b..2b98f5c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/CreateSetterFromUsageFix.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.
@@ -43,7 +43,7 @@
protected PsiType[] getArgumentTypes() {
final GrReferenceExpression ref = getRefExpr();
assert PsiUtil.isLValue(ref);
- PsiType initializer = TypeInferenceHelper.getInitializerFor(ref);
+ PsiType initializer = TypeInferenceHelper.getInitializerTypeFor(ref);
if (initializer == null || initializer == PsiType.NULL) {
initializer = TypesUtil.getJavaLangObject(ref);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrModifierFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrModifierFix.java
deleted file mode 100644
index 6d8c6ac..0000000
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrModifierFix.java
+++ /dev/null
@@ -1,79 +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.annotator.intentions;
-
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiMember;
-import com.intellij.psi.PsiModifierList;
-import com.intellij.psi.PsiModifierListOwner;
-import com.intellij.util.IncorrectOperationException;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.GroovyBundle;
-import org.jetbrains.plugins.groovy.intentions.base.Intention;
-import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
-import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
-
-/**
- * @author Maxim.Medvedev
- */
-public class GrModifierFix extends Intention {
- private final String myModifier;
- private final String myText;
- private final boolean myDoSet;
- private final PsiModifierList myModifierList;
-
- public GrModifierFix(@NotNull PsiMember member,
- @NotNull PsiModifierList modifierList,
- @GrModifier.GrModifierConstant String modifier,
- boolean showContainingClass,
- boolean doSet) {
- myModifierList = modifierList;
- myModifier = modifier;
- myDoSet = doSet;
-
- myText = org.jetbrains.plugins.groovy.codeInspection.bugs.GrModifierFix.initText(member, showContainingClass, modifier, doSet);
- }
-
- @NotNull
- @Override
- public String getText() {
- return myText;
- }
-
- @Override
- protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
- assert myModifierList.isValid();
- myModifierList.setModifierProperty(myModifier, myDoSet);
- }
-
- @NotNull
- @Override
- protected PsiElementPredicate getElementPredicate() {
- return new PsiElementPredicate() {
- @Override
- public boolean satisfiedBy(PsiElement element) {
- return element instanceof PsiModifierList || element instanceof PsiModifierListOwner;
- }
- };
- }
-
- @NotNull
- public String getFamilyName() {
- return GroovyBundle.message("change.modifier.family.name");
- }
-}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrReplacePrimitiveTypeWithWrapperFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrReplacePrimitiveTypeWithWrapperFix.java
index 5793ce5..626ae5c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrReplacePrimitiveTypeWithWrapperFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/GrReplacePrimitiveTypeWithWrapperFix.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,31 @@
*/
package org.jetbrains.plugins.groovy.annotator.intentions;
+import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiClassType;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiPrimitiveType;
+import com.intellij.psi.PsiType;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.codeInspection.GroovyFix;
import org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle;
-import org.jetbrains.plugins.groovy.intentions.base.Intention;
-import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
/**
* @author Max Medvedev
*/
-public class GrReplacePrimitiveTypeWithWrapperFix extends Intention {
+public class GrReplacePrimitiveTypeWithWrapperFix extends GroovyFix {
private static final Logger LOG = Logger.getInstance(GrReplacePrimitiveTypeWithWrapperFix.class);
- private final GrTypeElement myTypeElement;
private final String myBoxedName;
public GrReplacePrimitiveTypeWithWrapperFix(GrTypeElement typeElement) {
LOG.assertTrue(typeElement.isValid());
- myTypeElement = typeElement;
final PsiType type = typeElement.getType();
LOG.assertTrue(type instanceof PsiPrimitiveType);
@@ -49,7 +49,7 @@
@NotNull
@Override
- public String getText() {
+ public String getName() {
return GroovyIntentionsBundle.message("replace.with.wrapper", myBoxedName);
}
@@ -60,35 +60,18 @@
}
@Override
- public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
- return myTypeElement.isValid() && myTypeElement.getType() instanceof PsiPrimitiveType;
- }
+ protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
+ final PsiElement element = descriptor.getPsiElement();
+ assert element instanceof GrTypeElement : element;
- @Override
- protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
- final PsiType type = myTypeElement.getType();
+ GrTypeElement typeElement = (GrTypeElement)element;
+ final PsiType type = typeElement.getType();
if (!(type instanceof PsiPrimitiveType)) return;
- final PsiClassType boxed = ((PsiPrimitiveType)type).getBoxedType(myTypeElement);
+ final PsiClassType boxed = ((PsiPrimitiveType)type).getBoxedType(typeElement);
final GrTypeElement newTypeElement = GroovyPsiElementFactory.getInstance(project).createTypeElement(boxed);
- final PsiElement replaced = myTypeElement.replace(newTypeElement);
+ final PsiElement replaced = typeElement.replace(newTypeElement);
JavaCodeStyleManager.getInstance(project).shortenClassReferences(replaced);
}
-
- @NotNull
- @Override
- protected PsiElementPredicate getElementPredicate() {
- return new PsiElementPredicate() {
- @Override
- public boolean satisfiedBy(PsiElement element) {
- return myTypeElement.isValid();
- }
- };
- }
-
- @Override
- public boolean startInWriteAction() {
- return true;
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java
index 604ac2f..a6319d8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/QuickfixUtil.java
@@ -197,7 +197,7 @@
for (PsiType type : PsiUtil.getArgumentTypes(referenceExpression, false)) {
unboxedTypes.add(TypesUtil.unboxPrimitiveTypeWrapperAndEraseGenerics(type));
}
- final PsiType[] types = unboxedTypes.toArray(new PsiType[unboxedTypes.size()]);
+ final PsiType[] types = unboxedTypes.toArray(PsiType.createArray(unboxedTypes.size()));
final String[] names = getMethodArgumentsNames(referenceExpression.getProject(), types);
final List<ParamInfo> infos = swapArgumentsAndTypes(names, types);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicToolWindowWrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicToolWindowWrapper.java
index 002c2d6..2670bca 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicToolWindowWrapper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/annotator/intentions/dynamic/DynamicToolWindowWrapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.SimpleToolWindowPanel;
import com.intellij.openapi.wm.IdeFocusManager;
@@ -456,7 +455,7 @@
GroovyBundle.message("dynamic.property.deletion"), Messages.getQuestionIcon());
}
- if (result != DialogWrapper.OK_EXIT_CODE) return false;
+ if (result != Messages.OK) return false;
}
removeNamedElement(((DNamedElement)namedElement));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GrReassignedLocalVarsChecker.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GrReassignedLocalVarsChecker.java
index 313347d..eaeee5b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GrReassignedLocalVarsChecker.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInsight/GrReassignedLocalVarsChecker.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,7 +37,6 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
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.dataFlow.types.TypeInferenceHelper;
@@ -57,7 +56,7 @@
private static final Key<CachedValue<Boolean>> REASSIGNED_VAR = Key.create("least upper bound type");
@Nullable
- public static Boolean isReassignedVar(final GrReferenceExpression refExpr) {
+ public static Boolean isReassignedVar(@NotNull final GrReferenceExpression refExpr) {
if (!PsiUtil.isCompileStatic(refExpr)) {
return false;
}
@@ -86,7 +85,7 @@
return data.getValue();
}
- private static boolean isReassignedVarImpl(final GrVariable resolved) {
+ private static boolean isReassignedVarImpl(@NotNull final GrVariable resolved) {
final GrControlFlowOwner variableScope = PsiTreeUtil.getParentOfType(resolved, GrCodeBlock.class, GroovyFile.class);
if (variableScope == null) return false;
@@ -97,7 +96,7 @@
((GroovyPsiElement)scope).accept(new GroovyRecursiveElementVisitor() {
@Override
public void visitClosure(GrClosableBlock closure) {
- if (getAssignedVarsInsideBlock(closure).contains(name)) {
+ if (getUsedVarsInsideBlock(closure).contains(name)) {
isReassigned.set(true);
}
}
@@ -133,7 +132,7 @@
}
@Nullable
- private static PsiType getLeastUpperBoundByVar(final GrVariable resolved) {
+ private static PsiType getLeastUpperBoundByVar(@NotNull final GrVariable resolved) {
CachedValue<PsiType> data = resolved.getUserData(LEAST_UPPER_BOUND_TYPE);
if (data == null) {
data = CachedValuesManager.getManager(resolved.getProject()).createCachedValue(new CachedValueProvider<PsiType>() {
@@ -148,11 +147,11 @@
}
@Nullable
- private static PsiType getLeastUpperBoundByVarImpl(final GrVariable resolved) {
+ private static PsiType getLeastUpperBoundByVarImpl(@NotNull final GrVariable resolved) {
return RecursionManager.doPreventingRecursion(resolved, false, new NullableComputable<PsiType>() {
@Override
public PsiType compute() {
- final Collection<PsiReference> all = ReferencesSearch.search(resolved, resolved.getResolveScope()).findAll();
+ final Collection<PsiReference> all = ReferencesSearch.search(resolved).findAll();
final GrExpression initializer = resolved.getInitializerGroovy();
PsiType result = initializer != null ? initializer.getType() : null;
@@ -161,7 +160,7 @@
for (PsiReference reference : all) {
final PsiElement ref = reference.getElement();
if (ref instanceof GrReferenceExpression && PsiUtil.isLValue(((GrReferenceExpression)ref))) {
- result = TypesUtil.getLeastUpperBoundNullable(result, TypeInferenceHelper.getInitializerFor(ref), manager);
+ result = TypesUtil.getLeastUpperBoundNullable(result, TypeInferenceHelper.getInitializerTypeFor(ref), manager);
}
}
return result;
@@ -170,7 +169,7 @@
}
@NotNull
- private static Set<String> getAssignedVarsInsideBlock(@NotNull final GrCodeBlock block) {
+ private static Set<String> getUsedVarsInsideBlock(@NotNull final GrCodeBlock block) {
CachedValue<Set<String>> data = block.getUserData(ASSIGNED_VARS);
if (data == null) {
@@ -181,27 +180,24 @@
final Set<String> result = ContainerUtil.newHashSet();
block.acceptChildren(new GroovyRecursiveElementVisitor() {
- @Override
- public void visitAssignmentExpression(GrAssignmentExpression expression) {
- super.visitAssignmentExpression(expression);
-
- GrExpression lValue = expression.getLValue();
- if (lValue instanceof GrReferenceExpression && !((GrReferenceExpression)lValue).isQualified()) {
- result.add(((GrReferenceExpression)lValue).getReferenceName());
- }
- }
@Override
public void visitOpenBlock(GrOpenBlock openBlock) {
- result.addAll(getAssignedVarsInsideBlock(openBlock));
+ result.addAll(getUsedVarsInsideBlock(openBlock));
}
@Override
public void visitClosure(GrClosableBlock closure) {
- result.addAll(getAssignedVarsInsideBlock(closure));
+ result.addAll(getUsedVarsInsideBlock(closure));
+ }
+
+ @Override
+ public void visitReferenceExpression(GrReferenceExpression referenceExpression) {
+ if (referenceExpression.getQualifier() == null && referenceExpression.getReferenceName() != null) {
+ result.add(referenceExpression.getReferenceName());
+ }
}
});
-
return Result.create(result, block);
}
}, false);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.java
index 552c291..8c4a204 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.codeInspection;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.util.ResourceBundle;
@@ -29,25 +30,21 @@
*/
public class GroovyInspectionBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle";
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
- ourBundle = new SoftReference<ResourceBundle >(bundle);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
}
return bundle;
}
-
}
\ No newline at end of file
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 5ccb19b..3d658f0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/GroovyInspectionBundle.properties
@@ -85,7 +85,7 @@
replace.0.with.1=Replace {0} with binary {1}
gr.deprecated.api.usage=Deprecated API inspection
category.method.0.cannot.be.applied.to.1=Category method ''{0}'' cannot be applied to ''{1}''
-local.var.0.is.reassigned.in.closure=Local variable {0} is reassigned in {1} with other type
+local.var.0.is.reassigned=Local variable ''{0}'' is reassigned
anonymous.class=anonymous class
closure=closure
other.scope=Other scope
@@ -106,4 +106,7 @@
target.0.does.not.exist=Target ''{0}'' does not exist
target.annotation.is.unused=@Target is unused
change.lvalue.type=Change variable ''{0}'' type to ''{1}''
-replace.qualified.name.with.import=Replace qualified name with import
\ No newline at end of file
+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
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/CallInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/CallInfo.java
new file mode 100644
index 0000000..1dea914
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/CallInfo.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+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.arguments.GrNamedArgument;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public interface CallInfo<Call extends GroovyPsiElement> {
+ @Nullable
+ GrArgumentList getArgumentList();
+
+ @Nullable
+ PsiType[] getArgumentTypes();
+
+ @Nullable
+ GrExpression getInvokedExpression();
+
+ @Nullable
+ PsiType getQualifierInstanceType();
+
+ @NotNull
+ PsiElement getHighlightElementForCategoryQualifier() throws UnsupportedOperationException;
+
+ @NotNull
+ PsiElement getElementToHighlight();
+
+ @NotNull
+ GroovyResolveResult advancedResolve();
+
+ @NotNull
+ GroovyResolveResult[] multiResolve();
+
+ @NotNull
+ Call getCall();
+
+ @NotNull
+ GrExpression[] getExpressionArguments();
+
+ @NotNull
+ GrClosableBlock[] getClosureArguments();
+
+ @NotNull
+ GrNamedArgument[] getNamedArguments();
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/CallInfoBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/CallInfoBase.java
new file mode 100644
index 0000000..1d4e938
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/CallInfoBase.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+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.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;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public abstract class CallInfoBase<T extends GrCall> implements CallInfo<T> {
+ private final T myCall;
+ private final PsiType[] myArgTypes;
+
+ protected CallInfoBase(T call) {
+ myCall = call;
+ myArgTypes = inferArgTypes();
+ }
+
+ @Nullable
+ protected abstract PsiType[] inferArgTypes();
+
+ @Nullable
+ @Override
+ public GrArgumentList getArgumentList() {
+ return myCall.getArgumentList();
+ }
+
+ @Nullable
+ @Override
+ public PsiType[] getArgumentTypes() {
+ return myArgTypes;
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult advancedResolve() {
+ return myCall.advancedResolve();
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult[] multiResolve() {
+ return myCall.multiResolve(false);
+ }
+
+ @NotNull
+ @Override
+ public T getCall() {
+ return myCall;
+ }
+
+ @NotNull
+ public GrExpression[] getExpressionArguments() {
+ return myCall.getExpressionArguments();
+ }
+
+ @NotNull
+ public GrClosableBlock[] getClosureArguments() {
+ return myCall.getClosureArguments();
+ }
+
+ @NotNull
+ public GrNamedArgument[] getNamedArguments() {
+ return myCall.getNamedArguments();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ConstructorCallInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ConstructorCallInfo.java
new file mode 100644
index 0000000..238d885
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ConstructorCallInfo.java
@@ -0,0 +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 org.jetbrains.plugins.groovy.codeInspection.assignment;
+
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public interface ConstructorCallInfo<T extends GroovyPsiElement> extends CallInfo<T> {
+ GroovyResolveResult[] multiResolveClass();
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ConstructorCallInfoBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ConstructorCallInfoBase.java
new file mode 100644
index 0000000..90d5ea3
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ConstructorCallInfoBase.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConstructorCall;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public abstract class ConstructorCallInfoBase<T extends GrConstructorCall> extends CallInfoBase<T> implements ConstructorCallInfo<T> {
+ public ConstructorCallInfoBase(T call) {
+ super(call);
+ }
+
+ public GroovyResolveResult[] multiResolveClass() {
+ return getCall().multiResolveClass();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/DelegatingCallInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/DelegatingCallInfo.java
new file mode 100644
index 0000000..f5bb288
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/DelegatingCallInfo.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
+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.arguments.GrNamedArgument;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class DelegatingCallInfo<T extends GroovyPsiElement> implements CallInfo<T> {
+ private final CallInfo<T> myDelegate;
+
+ public DelegatingCallInfo(CallInfo<T> delegate) {
+ myDelegate = delegate;
+ }
+
+ @Nullable
+ @Override
+ public GrArgumentList getArgumentList() {
+ return myDelegate.getArgumentList();
+ }
+
+ @Nullable
+ @Override
+ public PsiType[] getArgumentTypes() {
+ return myDelegate.getArgumentTypes();
+ }
+
+ @Nullable
+ @Override
+ public GrExpression getInvokedExpression() {
+ return myDelegate.getInvokedExpression();
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return myDelegate.getQualifierInstanceType();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() throws UnsupportedOperationException {
+ return myDelegate.getHighlightElementForCategoryQualifier();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ return myDelegate.getElementToHighlight();
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult advancedResolve() {
+ return myDelegate.advancedResolve();
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult[] multiResolve() {
+ return myDelegate.multiResolve();
+ }
+
+ @NotNull
+ @Override
+ public T getCall() {
+ return myDelegate.getCall();
+ }
+
+ @NotNull
+ @Override
+ public GrExpression[] getExpressionArguments() {
+ return myDelegate.getExpressionArguments();
+ }
+
+ @NotNull
+ @Override
+ public GrClosableBlock[] getClosureArguments() {
+ return myDelegate.getClosureArguments();
+ }
+
+ @NotNull
+ @Override
+ public GrNamedArgument[] getNamedArguments() {
+ return myDelegate.getNamedArguments();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrBinaryExprInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrBinaryExprInfo.java
new file mode 100644
index 0000000..54750a9
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrBinaryExprInfo.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+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.arguments.GrNamedArgument;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrBinaryExprInfo implements CallInfo<GrBinaryExpression> {
+ private final GrBinaryExpression myExpr;
+
+ public GrBinaryExprInfo(GrBinaryExpression expr) {
+ myExpr = expr;
+ }
+
+ @Nullable
+ @Override
+ public GrArgumentList getArgumentList() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PsiType[] getArgumentTypes() {
+ GrExpression operand = myExpr.getRightOperand();
+
+ return new PsiType[]{operand != null ? operand.getType() : null};
+ }
+
+ @Nullable
+ @Override
+ public GrExpression getInvokedExpression() {
+ return myExpr.getLeftOperand();
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return myExpr.getLeftOperand().getType();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() {
+ return myExpr.getOperationToken();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ return myExpr.getOperationToken();
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult advancedResolve() {
+ return PsiImplUtil.extractUniqueResult(multiResolve());
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult[] multiResolve() {
+ return myExpr.multiResolve(false);
+ }
+
+ @NotNull
+ @Override
+ public GrBinaryExpression getCall() {
+ return myExpr;
+ }
+
+ @NotNull
+ @Override
+ public GrExpression[] getExpressionArguments() {
+ GrExpression right = myExpr.getRightOperand();
+ if (right != null) {
+ return new GrExpression[]{right};
+ }
+ else {
+ return GrExpression.EMPTY_ARRAY;
+ }
+ }
+
+ @NotNull
+ @Override
+ public GrClosableBlock[] getClosureArguments() {
+ return GrClosableBlock.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ @Override
+ public GrNamedArgument[] getNamedArguments() {
+ return GrNamedArgument.EMPTY_ARRAY;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrCastFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrCastFix.java
index 44109f9..d5a3467 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrCastFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrCastFix.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.
@@ -34,6 +34,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
/**
* @author Maxim.Medvedev
@@ -42,8 +43,8 @@
private static final Logger LOG = Logger.getInstance(GrCastFix.class);
private PsiType myExpectedType;
- public GrCastFix(PsiType expectedType) {
- myExpectedType = expectedType;
+ public GrCastFix(PsiType expectedType, GrExpression expression) {
+ myExpectedType = PsiImplUtil.normalizeWildcardTypeByPosition(expectedType, expression);
}
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrConstructorInvocationInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrConstructorInvocationInfo.java
new file mode 100644
index 0000000..cdc00ce
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrConstructorInvocationInfo.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrConstructorInvocationInfo extends ConstructorCallInfoBase<GrConstructorInvocation>
+ implements ConstructorCallInfo<GrConstructorInvocation> {
+ protected GrConstructorInvocationInfo(GrConstructorInvocation call) {
+ super(call);
+ }
+
+ @Nullable
+ @Override
+ protected PsiType[] inferArgTypes() {
+ return PsiUtil.getArgumentTypes(getArgumentList());
+ }
+
+ @NotNull
+ @Override
+ public GrExpression getInvokedExpression() {
+ return getCall().getInvokedExpression();
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return getInvokedExpression().getType();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() {
+ throw new UnsupportedOperationException("not applicable");
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ return getCall().getArgumentList();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrEnumConstantInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrEnumConstantInfo.java
new file mode 100644
index 0000000..436ded4
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrEnumConstantInfo.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 org.jetbrains.plugins.groovy.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrEnumConstant;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrEnumConstantInfo extends ConstructorCallInfoBase<GrEnumConstant> implements ConstructorCallInfo<GrEnumConstant> {
+ public GrEnumConstantInfo(GrEnumConstant constant) {
+ super(constant);
+ }
+
+ @Nullable
+ @Override
+ protected PsiType[] inferArgTypes() {
+ GrEnumConstant call = getCall();
+ GrArgumentList argList = call.getArgumentList();
+ if (argList != null) {
+ return PsiUtil.getArgumentTypes(argList);
+ }
+ else {
+ return PsiType.EMPTY_ARRAY;
+ }
+ }
+
+ @Nullable
+ @Override
+ public GrExpression getInvokedExpression() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() {
+ throw new UnsupportedOperationException("not applicable");
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ GrEnumConstant constant = getCall();
+ GrArgumentList argList = constant.getArgumentList();
+ if (argList != null) return argList;
+
+ return constant.getNameIdentifierGroovy();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrIndexPropertyInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrIndexPropertyInfo.java
new file mode 100644
index 0000000..1efd015
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrIndexPropertyInfo.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+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;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrIndexPropertyInfo extends CallInfoBase<GrIndexProperty> {
+ protected GrIndexPropertyInfo(GrIndexProperty call) {
+ super(call);
+ }
+
+ @Nullable
+ @Override
+ protected PsiType[] inferArgTypes() {
+ return PsiUtil.getArgumentTypes(getCall().getInvokedExpression(), true);
+ }
+
+ @NotNull
+ @Override
+ public GrExpression getInvokedExpression() {
+ return getCall().getInvokedExpression();
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return getInvokedExpression().getType();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() {
+ GrExpression invoked = getInvokedExpression();
+ if (invoked instanceof GrReferenceExpression) {
+ PsiElement refNameElement = ((GrReferenceExpression)invoked).getReferenceNameElement();
+ if (refNameElement != null) {
+ return refNameElement;
+ }
+ }
+
+ return invoked;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ return getCall().getArgumentList();
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrListOrMapInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrListOrMapInfo.java
new file mode 100644
index 0000000..1a09254
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrListOrMapInfo.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiClass;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.findUsages.LiteralConstructorReference;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
+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.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyResolveResultImpl;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrListOrMapInfo implements ConstructorCallInfo<GrListOrMap> {
+ private final GrListOrMap myListOrMap;
+ private final LiteralConstructorReference myReference;
+
+ public GrListOrMapInfo(GrListOrMap listOrMap) {
+ myListOrMap = listOrMap;
+
+ assert listOrMap.getReference() instanceof LiteralConstructorReference;
+ myReference = ((LiteralConstructorReference)listOrMap.getReference());
+ }
+
+ @Nullable
+ @Override
+ public GrArgumentList getArgumentList() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PsiType[] getArgumentTypes() {
+ if (myListOrMap.isMap()) {
+ GrNamedArgument[] args = myListOrMap.getNamedArguments();
+ if (args.length == 0) return new PsiType[]{myListOrMap.getType()};
+
+ return PsiUtil.getArgumentTypes(args, GrExpression.EMPTY_ARRAY, GrClosableBlock.EMPTY_ARRAY, true, null, false);
+ }
+ else {
+ GrExpression[] args = myListOrMap.getInitializers();
+ return PsiUtil.getArgumentTypes(GrNamedArgument.EMPTY_ARRAY, args, GrClosableBlock.EMPTY_ARRAY, true, null, false);
+ }
+ }
+
+ @Nullable
+ @Override
+ public GrExpression getInvokedExpression() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("not applicable");
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ return myListOrMap;
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult advancedResolve() {
+ return PsiImplUtil.extractUniqueResult(multiResolve());
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult[] multiResolve() {
+ GroovyResolveResult[] results = myReference.multiResolve(false);
+ if (results.length == 1 && results[0].getElement() instanceof PsiClass) {
+ return GroovyResolveResult.EMPTY_ARRAY; //the same behaviour as constructor calls
+ }
+ return results;
+ }
+
+ @NotNull
+ @Override
+ public GrListOrMap getCall() {
+ return myListOrMap;
+ }
+
+ @Override
+ public GroovyResolveResult[] multiResolveClass() {
+ return new GroovyResolveResult[]{new GroovyResolveResultImpl(myReference.getConstructedClassType().resolveGenerics())};
+ }
+
+ @NotNull
+ @Override
+ public GrExpression[] getExpressionArguments() {
+ return myListOrMap.isMap() ? GrExpression.EMPTY_ARRAY : myListOrMap.getInitializers();
+ }
+
+ @NotNull
+ @Override
+ public GrClosableBlock[] getClosureArguments() {
+ return GrClosableBlock.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ @Override
+ public GrNamedArgument[] getNamedArguments() {
+ return myListOrMap.isMap() ? myListOrMap.getNamedArguments() : GrNamedArgument.EMPTY_ARRAY;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrMethodCallInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrMethodCallInfo.java
new file mode 100644
index 0000000..721a6eb
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrMethodCallInfo.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+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;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrMethodCallInfo extends CallInfoBase<GrMethodCall> implements CallInfo<GrMethodCall> {
+ public GrMethodCallInfo(GrMethodCall call) {
+ super(call);
+ }
+
+ @Nullable
+ @Override
+ protected PsiType[] inferArgTypes() {
+ return PsiUtil.getArgumentTypes(getCall().getInvokedExpression(), true);
+ }
+
+ @Override
+ public GrExpression getInvokedExpression() {
+ return getCall().getInvokedExpression();
+ }
+
+ @Override
+ public PsiType getQualifierInstanceType() {
+ GrExpression invoked = getCall().getInvokedExpression();
+ return invoked instanceof GrReferenceExpression ? GrReferenceResolveUtil.getQualifierType((GrReferenceExpression)invoked) : null;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() {
+ GrExpression invoked = getCall().getInvokedExpression();
+ if (invoked instanceof GrReferenceExpression) {
+ PsiElement nameElement = ((GrReferenceExpression)invoked).getReferenceNameElement();
+ if (nameElement != null) {
+ return nameElement;
+ }
+ }
+ return invoked;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ GrArgumentList argList = getCall().getArgumentList();
+ if (argList.getTextLength() == 0) {
+ return getCall();
+ }
+ return argList;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrNewExpressionInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrNewExpressionInfo.java
new file mode 100644
index 0000000..3634455
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GrNewExpressionInfo.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 org.jetbrains.plugins.groovy.codeInspection.assignment;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiType;
+import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+/**
+ * Created by Max Medvedev on 05/02/14
+ */
+public class GrNewExpressionInfo extends ConstructorCallInfoBase<GrNewExpression> {
+
+ public GrNewExpressionInfo(GrNewExpression expr) {
+ super(expr);
+ }
+
+ @Nullable
+ @Override
+ protected PsiType[] inferArgTypes() {
+ return PsiUtil.getArgumentTypes(getCall().getReferenceElement(), true);
+ }
+
+ @Nullable
+ @Override
+ public GrExpression getInvokedExpression() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public PsiType getQualifierInstanceType() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getHighlightElementForCategoryQualifier() {
+ throw new UnsupportedOperationException("no categories are applicable to new expression");
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElementToHighlight() {
+ GrNewExpression call = getCall();
+
+ GrArgumentList argList = call.getArgumentList();
+ if (argList != null) return argList;
+
+ GrCodeReferenceElement ref = call.getReferenceElement();
+ if (ref != null) return ref;
+
+ throw new IncorrectOperationException("reference of new expression should exist if it is a constructor call");
+ }
+}
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 fff8538..33ad9e2 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
@@ -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,12 +18,14 @@
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.*;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSubstitutorImpl;
import com.intellij.psi.tree.IElementType;
@@ -58,6 +60,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
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.arguments.GrSpreadArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrThrowStatement;
@@ -69,18 +72,20 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
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.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.GrClosureType;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
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.GrReferenceResolveUtil;
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.util.*;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
+import javax.swing.*;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -90,6 +95,10 @@
public class GroovyAssignabilityCheckInspection extends BaseInspection {
private static final Logger LOG = Logger.getInstance(GroovyAssignabilityCheckInspection.class);
+ private static final String SHORT_NAME = "GroovyAssignabilityCheck";
+
+ public boolean myHighlightAssignmentsFromVoid = true;
+
@Nls
@NotNull
@Override
@@ -102,6 +111,14 @@
return true;
}
+ @Nullable
+ @Override
+ public JComponent createOptionsPanel() {
+ final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this);
+ optionsPanel.addCheckbox(GroovyInspectionBundle.message("highlight.assignments.from.void"), "myHighlightAssignmentsFromVoid");
+ return optionsPanel;
+ }
+
@Nls
@NotNull
@Override
@@ -127,9 +144,17 @@
final PsiType rType = expression.getType();
if (rType == null) return;
+ if (PsiUtil.isVoidMethodCall(expression)) {
+ if (isHighlightAssignmentsFromVoid(expression)) {
+ registerError(toHighlight, GroovyBundle.message("cannot.assign", PsiType.VOID.getPresentableText(),
+ expectedType.getPresentableText()));
+ }
+ return;
+ }
+
if (!TypesUtil.isAssignable(expectedType, rType, expression)) {
final List<LocalQuickFix> fixes = ContainerUtil.newArrayList();
- fixes.add(new GrCastFix(expectedType));
+ fixes.add(new GrCastFix(expectedType, expression));
String varName = getLValueVarName(toHighlight);
if (varName != null) {
@@ -141,6 +166,21 @@
}
}
+ private static boolean isHighlightAssignmentsFromVoid(PsiElement place) {
+ final GroovyAssignabilityCheckInspection instance = getInspectionInstance(place.getContainingFile(), place.getProject());
+ if (instance != null) {
+ return instance.myHighlightAssignmentsFromVoid;
+ }
+
+ return false;
+ }
+
+ private static GroovyAssignabilityCheckInspection getInspectionInstance(PsiFile file, Project project) {
+ final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
+ return (GroovyAssignabilityCheckInspection)profile.getUnwrappedTool(SHORT_NAME, file);
+ }
+
+
@Nullable
private static String getLValueVarName(PsiElement highlight) {
final PsiElement parent = highlight.getParent();
@@ -221,7 +261,7 @@
if (flowOwner != null && returnType != null && returnType != PsiType.VOID) {
if (ControlFlowUtils.isReturnValue(expression, flowOwner) &&
!isNewInstanceInitialingByTuple(expression) &&
- expression.getType() != PsiType.VOID) {
+ !PsiUtil.isVoidMethodCall(expression)) {
checkAssignability(returnType, expression, getExpressionPartToHighlight(expression));
}
}
@@ -272,14 +312,10 @@
for (GrExpression lValue : lValues) {
PsiType lType = lValue.getNominalType();
// For assignments with spread dot
- if (isListAssignment(lValue) && lType != null && lType instanceof PsiClassType) {
- final PsiClassType pct = (PsiClassType)lType;
- final PsiClass clazz = pct.resolve();
- if (clazz != null && CommonClassNames.JAVA_UTIL_LIST.equals(clazz.getQualifiedName())) {
- final PsiType[] types = pct.getParameters();
- if (types.length == 1 && types[0] != null && rType != null) {
- checkAssignability(types[0], rType, tupleExpression, getExpressionPartToHighlight(lValue));
- }
+ if (GroovyRefactoringUtil.isSpreadAssignment(lValue)) {
+ final PsiType argType = extractIterableArg(lType);
+ if (argType != null && rType != null) {
+ checkAssignability(argType, rType, tupleExpression, getExpressionPartToHighlight(lValue));
}
return;
}
@@ -298,15 +334,10 @@
private void checkAssignment(GrExpression lValue, GrExpression rValue) {
PsiType lType = lValue.getNominalType();
PsiType rType = rValue.getType();
- // For assignments with spread dot
- if (isListAssignment(lValue) && lType != null && lType instanceof PsiClassType) {
- final PsiClassType pct = (PsiClassType)lType;
- final PsiClass clazz = pct.resolve();
- if (clazz != null && CommonClassNames.JAVA_UTIL_LIST.equals(clazz.getQualifiedName())) {
- final PsiType[] types = pct.getParameters();
- if (types.length == 1 && types[0] != null && rType != null) {
- checkAssignability(types[0], rValue, getExpressionPartToHighlight(lValue));
- }
+ if (GroovyRefactoringUtil.isSpreadAssignment(lValue)) {
+ final PsiType argType = extractIterableArg(lType);
+ if (argType != null && rValue != null) {
+ checkAssignability(argType, rValue, getExpressionPartToHighlight(lValue));
}
return;
}
@@ -325,6 +356,11 @@
}
}
+ @Nullable
+ private static PsiType extractIterableArg(@Nullable PsiType type) {
+ return com.intellij.psi.util.PsiUtil.extractIterableTypeParameter(type, false);
+ }
+
@Override
public void visitVariable(GrVariable variable) {
super.visitVariable(variable);
@@ -400,43 +436,43 @@
GrCodeReferenceElement refElement = newExpression.getReferenceElement();
if (refElement == null) return;
- checkConstructorCall(newExpression, refElement);
+ GrNewExpressionInfo info = new GrNewExpressionInfo(newExpression);
+ checkConstructorCall(info);
}
- private void checkConstructorCall(GrConstructorCall constructorCall, GroovyPsiElement refElement) {
- final GrArgumentList argList = constructorCall.getArgumentList();
- if (hasErrorElements(argList)) return;
+ private void checkConstructorCall(ConstructorCallInfo<?> info) {
+ if (hasErrorElements(info.getArgumentList())) return;
- if (!checkCannotInferArgumentTypes(refElement)) return;
- final GroovyResolveResult constructorResolveResult = constructorCall.advancedResolve();
+ if (!checkCannotInferArgumentTypes(info)) return;
+ final GroovyResolveResult constructorResolveResult = info.advancedResolve();
final PsiElement constructor = constructorResolveResult.getElement();
if (constructor != null) {
- if (!checkConstructorApplicability(constructorResolveResult, refElement, true)) return;
+ if (!checkConstructorApplicability(constructorResolveResult, info, true)) return;
}
else {
- final GroovyResolveResult[] results = constructorCall.multiResolve(false);
+ final GroovyResolveResult[] results = info.multiResolve();
if (results.length > 0) {
for (GroovyResolveResult result : results) {
PsiElement resolved = result.getElement();
if (resolved instanceof PsiMethod) {
- if (!checkConstructorApplicability(result, refElement, false)) return;
+ if (!checkConstructorApplicability(result, info, false)) return;
}
}
- registerError(getElementToHighlight(refElement, argList), GroovyBundle.message("constructor.call.is.ambiguous"));
+ registerError(info.getElementToHighlight(), GroovyBundle.message("constructor.call.is.ambiguous"));
}
else {
- final GrExpression[] expressionArguments = constructorCall.getExpressionArguments();
- final boolean hasClosureArgs = PsiImplUtil.hasClosureArguments(constructorCall);
- final boolean hasNamedArgs = PsiImplUtil.hasNamedArguments(constructorCall.getArgumentList());
+ final GrExpression[] expressionArguments = info.getExpressionArguments();
+ final boolean hasClosureArgs = info.getClosureArguments().length > 0;
+ final boolean hasNamedArgs = info.getNamedArguments().length > 0;
if (hasClosureArgs ||
hasNamedArgs && expressionArguments.length > 0 ||
!hasNamedArgs && expressionArguments.length > 0 && !isOnlyOneMapParam(expressionArguments)) {
- final GroovyResolveResult[] resolveResults = constructorCall.multiResolveClass();
+ final GroovyResolveResult[] resolveResults = info.multiResolveClass();
if (resolveResults.length == 1) {
final PsiElement element = resolveResults[0].getElement();
if (element instanceof PsiClass) {
- registerError(getElementToHighlight(refElement, argList),
+ registerError(info.getElementToHighlight(),
GroovyBundle.message("cannot.apply.default.constructor", ((PsiClass)element).getName()));
return;
}
@@ -445,22 +481,14 @@
}
}
- checkNamedArgumentsType(constructorCall);
+ checkNamedArgumentsType(info);
}
private static boolean isOnlyOneMapParam(GrExpression[] exprs) {
if (!(exprs.length == 1)) return false;
final GrExpression e = exprs[0];
- return TypesUtil.isAssignableByMethodCallConversion(TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_UTIL_MAP, e), e.getType(),
- e);
- }
-
- @NotNull
- private static PsiElement getElementToHighlight(@NotNull PsiElement refElement, @Nullable GrArgumentList argList) {
- PsiElement elementToHighlight = argList;
- if (elementToHighlight == null || elementToHighlight.getTextLength() == 0) elementToHighlight = refElement;
- return elementToHighlight;
+ return TypesUtil.isAssignableByMethodCallConversion(TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_UTIL_MAP, e), e.getType(), e);
}
@NotNull
@@ -482,27 +510,7 @@
final GroovyResolveResult[] results = ((LiteralConstructorReference)reference).multiResolve(false);
if (results.length == 0) return;
- if (results.length == 1) {
- final GroovyResolveResult result = results[0];
- final PsiElement element = result.getElement();
- if (element instanceof PsiClass) {
- if (!listOrMap.isMap()) {
- registerError(listOrMap, GroovyBundle.message("cannot.apply.default.constructor", ((PsiClass)element).getName()));
- }
- }
- else if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) {
- checkLiteralConstructorApplicability(result, listOrMap, true);
- }
- }
- else {
- for (GroovyResolveResult result : results) {
- PsiElement resolved = result.getElement();
- if (resolved instanceof PsiMethod) {
- if (!checkLiteralConstructorApplicability(result, listOrMap, false)) return;
- }
- registerError(listOrMap, GroovyBundle.message("constructor.call.is.ambiguous"));
- }
- }
+ checkConstructorCall(new GrListOrMapInfo(listOrMap));
}
@Override
@@ -516,146 +524,127 @@
}
}
- private boolean checkLiteralConstructorApplicability(GroovyResolveResult result, GrListOrMap listOrMap, boolean checkUnknownArgs) {
- final PsiElement element = result.getElement();
- LOG.assertTrue(element instanceof PsiMethod && ((PsiMethod)element).isConstructor());
- final PsiMethod constructor = (PsiMethod)element;
-
- final GrExpression[] exprArgs;
- final GrNamedArgument[] namedArgs;
- if (listOrMap.isMap()) {
- exprArgs = GrExpression.EMPTY_ARRAY;
- namedArgs = listOrMap.getNamedArguments();
- }
- else {
- exprArgs = listOrMap.getInitializers();
- namedArgs = GrNamedArgument.EMPTY_ARRAY;
- }
-
- if (exprArgs.length == 0 && !PsiUtil.isConstructorHasRequiredParameters(constructor)) return true;
-
- PsiType[] argumentTypes = PsiUtil.getArgumentTypes(namedArgs, exprArgs, GrClosableBlock.EMPTY_ARRAY, false, null, false);
- if (listOrMap.isMap() && namedArgs.length == 0) {
- argumentTypes = new PsiType[]{listOrMap.getType()};
- }
-
- GrClosureSignatureUtil.ApplicabilityResult applicable =
- PsiUtil.isApplicableConcrete(argumentTypes, constructor, result.getSubstitutor(), listOrMap, false);
- switch (applicable) {
- case inapplicable:
- highlightInapplicableMethodUsage(result, listOrMap, constructor, argumentTypes);
- return false;
- case canBeApplicable:
- if (checkUnknownArgs) {
- highlightUnknownArgs(listOrMap);
- }
- return !checkUnknownArgs;
- default:
- return true;
- }
- }
-
private boolean checkConstructorApplicability(GroovyResolveResult constructorResolveResult,
- GroovyPsiElement place,
+ CallInfo<?> info,
boolean checkUnknownArgs) {
final PsiElement element = constructorResolveResult.getElement();
- LOG.assertTrue(element instanceof PsiMethod && ((PsiMethod)element).isConstructor());
+ LOG.assertTrue(element instanceof PsiMethod && ((PsiMethod)element).isConstructor(), element);
final PsiMethod constructor = (PsiMethod)element;
- final GrArgumentList argList = PsiUtil.getArgumentsList(place);
+ final GrArgumentList argList = info.getArgumentList();
if (argList != null) {
final GrExpression[] exprArgs = argList.getExpressionArguments();
-
if (exprArgs.length == 0 && !PsiUtil.isConstructorHasRequiredParameters(constructor)) return true;
}
- PsiType[] types = PsiUtil.getArgumentTypes(place, true);
+ PsiType[] types = info.getArgumentTypes();
PsiClass containingClass = constructor.getContainingClass();
if (types != null && containingClass != null) {
- types = GrInnerClassConstructorUtil.addEnclosingArgIfNeeded(types, place, containingClass);
+ final PsiType[] newTypes = GrInnerClassConstructorUtil.addEnclosingArgIfNeeded(types, info.getCall(), containingClass);
+ if (newTypes.length != types.length) {
+ return checkMethodApplicability(constructorResolveResult, checkUnknownArgs, new DelegatingCallInfo(info) {
+ @Nullable
+ @Override
+ public PsiType[] getArgumentTypes() {
+ return newTypes;
+ }
+ });
+ }
}
- return checkMethodApplicability(constructorResolveResult, place, checkUnknownArgs, types);
+
+ return checkMethodApplicability(constructorResolveResult, checkUnknownArgs, info);
}
@Override
public void visitConstructorInvocation(GrConstructorInvocation invocation) {
super.visitConstructorInvocation(invocation);
- checkConstructorCall(invocation, invocation.getInvokedExpression());
+ GrConstructorInvocationInfo info = new GrConstructorInvocationInfo(invocation);
+ checkConstructorCall(info);
+ checkNamedArgumentsType(info);
}
@Override
public void visitIndexProperty(GrIndexProperty expression) {
super.visitIndexProperty(expression);
- if (!checkCannotInferArgumentTypes(expression.getInvokedExpression())) return;
+ checkIndexProperty(new GrIndexPropertyInfo(expression));
+ }
- final GrExpression invoked = expression.getInvokedExpression();
+ private void checkIndexProperty(CallInfo<? extends GrIndexProperty> info) {
+ if (hasErrorElements(info.getArgumentList())) return;
- if (hasErrorElements(expression.getArgumentList())) return;
+ if (!checkCannotInferArgumentTypes(info)) return;
- final PsiType type = invoked.getType();
- final PsiType[] types = PsiUtil.getArgumentTypes(expression.getArgumentList(), true);
- if (type instanceof PsiArrayType) {
- assert types != null;
+ final PsiType type = info.getQualifierInstanceType();
+ final PsiType[] types = info.getArgumentTypes();
- if (PsiUtil.isLValue(expression)) {
- if (types.length == 2 &&
- TypesUtil.isAssignable(PsiType.INT, types[0], expression) &&
- TypesUtil.isAssignable(((PsiArrayType)type).getComponentType(), types[1], expression)) {
- return;
- }
- }
- else {
- if (types.length == 1 && TypesUtil.isAssignable(PsiType.INT, types[0], expression)) {
- return;
- }
- }
- }
+ if (checkSimpleArrayAccess(info, type, types)) return;
- final GroovyResolveResult[] results = expression.multiResolve(false);
+ final GroovyResolveResult[] results = info.multiResolve();
+ final GroovyResolveResult resolveResult = info.advancedResolve();
- if (results.length == 1) {
- final GroovyResolveResult resolveResult = results[0];
+ if (resolveResult.getElement() != null) {
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof PsiMethod && !resolveResult.isInvokedOnProperty()) {
- checkMethodApplicability(resolveResult, invoked, true);
+ checkMethodApplicability(resolveResult, true, info);
}
else if (resolved instanceof GrField) {
- checkCallApplicability(((GrField)resolved).getTypeGroovy(), invoked, true);
+ checkCallApplicability(((GrField)resolved).getTypeGroovy(), true, info);
}
else if (resolved instanceof PsiField) {
- checkCallApplicability(((PsiField)resolved).getType(), invoked, true);
+ checkCallApplicability(((PsiField)resolved).getType(), true, info);
}
}
else if (results.length > 0) {
- for (GroovyResolveResult resolveResult : results) {
- PsiElement resolved = resolveResult.getElement();
- if (resolved instanceof PsiMethod && !resolveResult.isInvokedOnProperty()) {
- if (!checkMethodApplicability(resolveResult, invoked, false)) return;
+ for (GroovyResolveResult result : results) {
+ PsiElement resolved = result.getElement();
+ if (resolved instanceof PsiMethod && !result.isInvokedOnProperty()) {
+ if (!checkMethodApplicability(result, false, info)) return;
}
else if (resolved instanceof GrField) {
- if (!checkCallApplicability(((GrField)resolved).getTypeGroovy(), invoked, false)) return;
+ if (!checkCallApplicability(((GrField)resolved).getTypeGroovy(), false, info)) return;
}
else if (resolved instanceof PsiField) {
- if (!checkCallApplicability(((PsiField)resolved).getType(), invoked, false)) return;
+ if (!checkCallApplicability(((PsiField)resolved).getType(), false, info)) return;
}
}
- registerError(getElementToHighlight(invoked, PsiUtil.getArgumentsList(invoked)), GroovyBundle.message("method.call.is.ambiguous"));
+ registerError(info.getElementToHighlight(), GroovyBundle.message("method.call.is.ambiguous"));
}
else {
final String typesString = buildArgTypesList(types);
- registerError(PsiUtil.getArgumentsList(invoked), GroovyBundle.message("cannot.find.operator.overload.method", typesString));
+ registerError(info.getElementToHighlight(), GroovyBundle.message("cannot.find.operator.overload.method", typesString));
}
}
- private boolean checkCannotInferArgumentTypes(PsiElement place) {
- if (PsiUtil.getArgumentTypes(place, true) != null) {
+ private static boolean checkSimpleArrayAccess(CallInfo<? extends GrIndexProperty> info, PsiType type, PsiType[] types) {
+ if (!(type instanceof PsiArrayType)) return false;
+
+ assert types != null;
+
+ if (PsiUtil.isLValue(info.getCall())) {
+ if (types.length == 2 &&
+ TypesUtil.isAssignable(PsiType.INT, types[0], info.getCall()) &&
+ TypesUtil.isAssignable(((PsiArrayType)type).getComponentType(), types[1], info.getCall())) {
+ return true;
+ }
+ }
+ else {
+ if (types.length == 1 && TypesUtil.isAssignable(PsiType.INT, types[0], info.getCall())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private boolean checkCannotInferArgumentTypes(CallInfo info) {
+ if (info.getArgumentTypes() != null) {
return true;
}
else {
- highlightUnknownArgs(place);
+ highlightUnknownArgs(info);
return false;
}
}
@@ -663,22 +652,34 @@
@Override
public void visitMethodCallExpression(GrMethodCallExpression methodCallExpression) {
super.visitMethodCallExpression(methodCallExpression);
- checkMethodCall(methodCallExpression, methodCallExpression.getInvokedExpression());
+ checkMethodCall(new GrMethodCallInfo(methodCallExpression));
}
@Override
public void visitApplicationStatement(GrApplicationStatement applicationStatement) {
super.visitApplicationStatement(applicationStatement);
- checkMethodCall(applicationStatement, applicationStatement.getInvokedExpression());
+ 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);
- checkConstructorCall(enumConstant, enumConstant);
+ GrEnumConstantInfo info = new GrEnumConstantInfo(enumConstant);
+ checkConstructorCall(info);
+ checkNamedArgumentsType(info);
}
- private void checkNamedArgumentsType(GrCall call) {
+ private void checkNamedArgumentsType(CallInfo<?> info) {
+ GroovyPsiElement rawCall = info.getCall();
+ if (!(rawCall instanceof GrCall)) return;
+ GrCall call = (GrCall)rawCall;
+
GrNamedArgument[] namedArguments = PsiUtil.getFirstMapNamedArguments(call);
if (namedArguments.length == 0) return;
@@ -700,14 +701,11 @@
if (PsiUtil.isRawClassMemberAccess(namedArgumentExpression)) continue;
- PsiType expressionType = namedArgumentExpression.getType();
+ PsiType expressionType = TypesUtil.boxPrimitiveType(namedArgumentExpression.getType(), call.getManager(), call.getResolveScope());
if (expressionType == null) continue;
- expressionType = TypesUtil.boxPrimitiveType(expressionType, call.getManager(), call.getResolveScope());
-
if (!descriptor.checkType(expressionType, call)) {
- registerError(namedArgumentExpression,
- "Type of argument '" + labelName + "' can not be '" + expressionType.getPresentableText() + "'");
+ registerError(namedArgumentExpression, "Type of argument '" + labelName + "' can not be '" + expressionType.getPresentableText() + "'");
}
}
}
@@ -724,13 +722,49 @@
return false;
}
- private void checkMethodCall(GrCall call, GrExpression invoked) {
- if (hasErrorElements(call.getArgumentList())) return;
+ private void checkOperator(CallInfo<? extends GrBinaryExpression> info) {
+ if (hasErrorElements(info.getCall())) return;
- if (invoked instanceof GrReferenceExpression) {
- final GrReferenceExpression referenceExpression = (GrReferenceExpression)invoked;
- GroovyResolveResult resolveResult = call.advancedResolve();
- GroovyResolveResult[] results = call.multiResolve(false); //cached
+ GroovyResolveResult[] results = info.multiResolve();
+ GroovyResolveResult resolveResult = info.advancedResolve();
+
+ if (isOperatorWithSimpleTypes(info.getCall(), resolveResult)) return;
+
+ if (!checkCannotInferArgumentTypes(info)) return;
+
+ if (resolveResult.getElement() != null) {
+ checkMethodApplicability(resolveResult, true, info);
+ }
+ else if (results.length > 0) {
+ for (GroovyResolveResult result : results) {
+ if (!checkMethodApplicability(result, false, info)) return;
+ }
+
+ registerError(info.getElementToHighlight(), GroovyBundle.message("method.call.is.ambiguous"));
+ }
+ }
+
+ private static boolean isOperatorWithSimpleTypes(GrBinaryExpression binary, GroovyResolveResult result) {
+ if (result.getElement() != null && result.isApplicable()) {
+ return false;
+ }
+
+ GrExpression left = binary.getLeftOperand();
+ GrExpression right = binary.getRightOperand();
+
+ PsiType ltype = left.getType();
+ PsiType rtype = right != null ? right.getType() : null;
+
+ return TypesUtil.isNumericType(ltype) && (rtype == null || TypesUtil.isNumericType(rtype));
+ }
+
+ private void checkMethodCall(CallInfo<? extends GrMethodCall> info) {
+ if (hasErrorElements(info.getArgumentList())) return;
+
+ if (info.getInvokedExpression() instanceof GrReferenceExpression) {
+ final GrReferenceExpression referenceExpression = (GrReferenceExpression)info.getInvokedExpression();
+ GroovyResolveResult resolveResult = info.advancedResolve();
+ GroovyResolveResult[] results = info.multiResolve();
PsiElement resolved = resolveResult.getElement();
if (resolved == null) {
@@ -738,71 +772,69 @@
if (qualifier == null && GrHighlightUtil.isDeclarationAssignment(referenceExpression)) return;
}
- if (!checkCannotInferArgumentTypes(referenceExpression)) return;
+ if (!checkCannotInferArgumentTypes(info)) return;
final PsiType type = referenceExpression.getType();
if (resolved != null) {
if (resolved instanceof PsiMethod && !resolveResult.isInvokedOnProperty()) {
- checkMethodApplicability(resolveResult, referenceExpression, true);
+ checkMethodApplicability(resolveResult, true, info);
}
else {
- checkCallApplicability(type, referenceExpression, true);
+ checkCallApplicability(type, true, info);
}
}
else if (results.length > 0) {
for (GroovyResolveResult result : results) {
- resolved = result.getElement();
- if (resolved instanceof PsiMethod && !result.isInvokedOnProperty()) {
- if (!checkMethodApplicability(result, referenceExpression, false)) return;
+ PsiElement current = result.getElement();
+ if (current instanceof PsiMethod && !result.isInvokedOnProperty()) {
+ if (!checkMethodApplicability(result, false, info)) return;
}
else {
- if (!checkCallApplicability(type, referenceExpression, false)) return;
+ if (!checkCallApplicability(type, false, info)) return;
}
}
- registerError(getElementToHighlight(referenceExpression, PsiUtil.getArgumentsList(referenceExpression)),
- GroovyBundle.message("method.call.is.ambiguous"));
+ registerError(info.getElementToHighlight(), GroovyBundle.message("method.call.is.ambiguous"));
}
}
- else if (invoked != null) { //it checks in visitRefExpr(...)
- final PsiType type = invoked.getType();
- checkCallApplicability(type, invoked, true);
+ else if (info.getInvokedExpression() != null) { //it checks in visitRefExpr(...)
+ final PsiType type = info.getInvokedExpression().getType();
+ checkCallApplicability(type, true, info);
}
- checkNamedArgumentsType(call);
+ checkNamedArgumentsType(info);
}
- private void highlightInapplicableMethodUsage(GroovyResolveResult methodResolveResult,
- GroovyPsiElement place,
- PsiMethod method,
- PsiType[] argumentTypes) {
+ private void highlightInapplicableMethodUsage(@NotNull GroovyResolveResult methodResolveResult,
+ @NotNull CallInfo info,
+ @NotNull PsiMethod method) {
final PsiClass containingClass =
method instanceof GrGdkMethod ? ((GrGdkMethod)method).getStaticMethod().getContainingClass() : method.getContainingClass();
+ PsiType[] argumentTypes = info.getArgumentTypes();
if (containingClass == null) {
- registerCannotApplyError(place, argumentTypes, method.getName());
+ registerCannotApplyError(method.getName(), info);
return;
}
final String typesString = buildArgTypesList(argumentTypes);
- final PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
+ final PsiElementFactory factory = JavaPsiFacade.getElementFactory(method.getProject());
final PsiClassType containingType = factory.createType(containingClass, methodResolveResult.getSubstitutor());
final String canonicalText = containingType.getInternalCanonicalText();
- String message;
- if (method.isConstructor()) {
- message = GroovyBundle.message("cannot.apply.constructor", method.getName(), canonicalText, typesString);
- }
- else {
- message = GroovyBundle.message("cannot.apply.method1", method.getName(), canonicalText, typesString);
- }
+ String message = method.isConstructor() ? GroovyBundle.message("cannot.apply.constructor", method.getName(), canonicalText, typesString)
+ : GroovyBundle.message("cannot.apply.method1", method.getName(), canonicalText, typesString);
- final GrArgumentList argumentsList = PsiUtil.getArgumentsList(place);
- registerError(getElementToHighlight(place, argumentsList), message,
- genCastFixes(GrClosureSignatureUtil.createSignature(methodResolveResult), argumentTypes, argumentsList),
+ registerError(info.getElementToHighlight(), message,
+ genCastFixes(GrClosureSignatureUtil.createSignature(methodResolveResult), argumentTypes, info.getArgumentList()),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
private static LocalQuickFix[] genCastFixes(GrSignature signature, PsiType[] argumentTypes, @Nullable GrArgumentList argumentList) {
if (argumentList == null) return LocalQuickFix.EMPTY_ARRAY;
+ final List<GrExpression> args = getExpressionArgumentsOfCall(argumentList);
+
+ if (args == null) {
+ return LocalQuickFix.EMPTY_ARRAY;
+ }
final List<GrClosureSignature> signatures = GrClosureSignatureUtil.generateSimpleSignature(signature);
@@ -822,26 +854,29 @@
final ArrayList<LocalQuickFix> fixes = new ArrayList<LocalQuickFix>();
for (Pair<Integer, PsiType> error : allErrors) {
- fixes.add(new ParameterCastFix(error.first, error.second));
+ fixes.add(new ParameterCastFix(error.first, error.second, args.get(error.first)));
}
return fixes.toArray(new LocalQuickFix[fixes.size()]);
}
- private boolean checkCallApplicability(PsiType type, GroovyPsiElement invokedExpr, boolean checkUnknownArgs) {
+ private boolean checkCallApplicability(PsiType type, boolean checkUnknownArgs, CallInfo info) {
- PsiType[] argumentTypes = PsiUtil.getArgumentTypes(invokedExpr, true);
+ PsiType[] argumentTypes = info.getArgumentTypes();
+ GrExpression invoked = info.getInvokedExpression();
+ if (invoked == null) return true;
+
if (type instanceof GrClosureType) {
if (argumentTypes == null) return true;
- GrClosureSignatureUtil.ApplicabilityResult result = PsiUtil.isApplicableConcrete(argumentTypes, (GrClosureType)type, invokedExpr);
+ GrClosureSignatureUtil.ApplicabilityResult result = PsiUtil.isApplicableConcrete(argumentTypes, (GrClosureType)type, info.getCall());
switch (result) {
case inapplicable:
- registerCannotApplyError(invokedExpr, argumentTypes, invokedExpr.getText());
+ registerCannotApplyError(invoked.getText(), info);
return false;
case canBeApplicable:
if (checkUnknownArgs) {
- highlightUnknownArgs(invokedExpr);
+ highlightUnknownArgs(info);
}
return !checkUnknownArgs;
default:
@@ -849,30 +884,27 @@
}
}
else if (type != null) {
- final GroovyResolveResult[] calls = ResolveUtil.getMethodCandidates(type, "call", invokedExpr, argumentTypes);
+ final GroovyResolveResult[] calls = ResolveUtil.getMethodCandidates(type, "call", invoked, argumentTypes);
for (GroovyResolveResult result : calls) {
PsiElement resolved = result.getElement();
if (resolved instanceof PsiMethod && !result.isInvokedOnProperty()) {
- if (!checkMethodApplicability(result, invokedExpr, checkUnknownArgs && calls.length == 1)) return false;
+ if (!checkMethodApplicability(result, checkUnknownArgs, info)) return false;
}
else if (resolved instanceof PsiField) {
- if (!checkCallApplicability(((PsiField)resolved).getType(), invokedExpr, checkUnknownArgs && calls.length == 1)) return false;
+ if (!checkCallApplicability(((PsiField)resolved).getType(), checkUnknownArgs && calls.length == 1, info)) return false;
}
}
- if (calls.length == 0 && !(invokedExpr instanceof GrString)) {
- registerCannotApplyError(invokedExpr, argumentTypes, invokedExpr.getText());
+ if (calls.length == 0 && !(invoked instanceof GrString)) {
+ registerCannotApplyError(invoked.getText(), info);
}
return true;
}
return true;
}
- private void registerCannotApplyError(PsiElement place, PsiType[] argumentTypes, String invokedText) {
- final String typesString = buildArgTypesList(argumentTypes);
- String message = GroovyBundle.message("cannot.apply.method.or.closure", invokedText, typesString);
- PsiElement elementToHighlight = PsiUtil.getArgumentsList(place);
- if (elementToHighlight == null || elementToHighlight.getTextRange().getLength() == 0) elementToHighlight = place;
- registerError(elementToHighlight, message);
+ private void registerCannotApplyError(String invokedText, CallInfo info) {
+ final String typesString = buildArgTypesList(info.getArgumentTypes());
+ registerError(info.getElementToHighlight(), GroovyBundle.message("cannot.apply.method.or.closure", invokedText, typesString));
}
private static String buildArgTypesList(PsiType[] argTypes) {
@@ -890,33 +922,26 @@
}
private boolean checkMethodApplicability(@NotNull GroovyResolveResult methodResolveResult,
- @NotNull GroovyPsiElement place,
- boolean checkUnknownArgs) {
- return checkMethodApplicability(methodResolveResult, place, checkUnknownArgs, PsiUtil.getArgumentTypes(place, true));
- }
-
- private boolean checkMethodApplicability(@NotNull GroovyResolveResult methodResolveResult,
- @NotNull GroovyPsiElement place,
boolean checkUnknownArgs,
- @Nullable PsiType[] argumentTypes) {
+ @NotNull CallInfo info) {
final PsiElement element = methodResolveResult.getElement();
if (!(element instanceof PsiMethod)) return true;
if (element instanceof GrBuilderMethod) return true;
final PsiMethod method = (PsiMethod)element;
- if ("call".equals(method.getName()) && place instanceof GrReferenceExpression) {
- final GrExpression qualifierExpression = ((GrReferenceExpression)place).getQualifierExpression();
+ if ("call".equals(method.getName()) && info.getInvokedExpression() instanceof GrReferenceExpression) {
+ final GrExpression qualifierExpression = ((GrReferenceExpression)info.getInvokedExpression()).getQualifierExpression();
if (qualifierExpression != null) {
final PsiType type = qualifierExpression.getType();
if (type instanceof GrClosureType) {
- GrClosureSignatureUtil.ApplicabilityResult result = PsiUtil.isApplicableConcrete(argumentTypes, (GrClosureType)type, place);
+ GrClosureSignatureUtil.ApplicabilityResult result = PsiUtil.isApplicableConcrete(info.getArgumentTypes(), (GrClosureType)type, info.getInvokedExpression());
switch (result) {
case inapplicable:
- highlightInapplicableMethodUsage(methodResolveResult, place, method, argumentTypes);
+ highlightInapplicableMethodUsage(methodResolveResult, info, method);
return false;
case canBeApplicable:
if (checkUnknownArgs) {
- highlightUnknownArgs(place);
+ highlightUnknownArgs(info);
}
return !checkUnknownArgs;
default:
@@ -926,32 +951,33 @@
}
}
- if (method instanceof GrGdkMethod && place instanceof GrReferenceExpression) {
+ if (method instanceof GrGdkMethod && info.getInvokedExpression() instanceof GrReferenceExpression) {
final PsiMethod staticMethod = ((GrGdkMethod)method).getStaticMethod();
- final PsiType qualifierType = inferQualifierTypeByPlace((GrReferenceExpression)place);
+ final PsiType qualifierType = info.getQualifierInstanceType();
- final GrExpression qualifier = PsiImplUtil.getRuntimeQualifier((GrReferenceExpression)place);
+ GrReferenceExpression invoked = (GrReferenceExpression)info.getInvokedExpression();
+ final GrExpression qualifier = PsiImplUtil.getRuntimeQualifier(invoked);
//check methods processed by @Category(ClassWhichProcessMethod) annotation
if (qualifierType != null &&
!GdkMethodUtil.isCategoryMethod(staticMethod, qualifierType, qualifier, methodResolveResult.getSubstitutor()) &&
- !checkCategoryQualifier((GrReferenceExpression)place, qualifier, staticMethod, methodResolveResult.getSubstitutor())) {
- registerError(((GrReferenceExpression)place).getReferenceNameElement(), GroovyInspectionBundle
+ !checkCategoryQualifier(invoked, qualifier, staticMethod, methodResolveResult.getSubstitutor())) {
+ registerError(info.getHighlightElementForCategoryQualifier(), GroovyInspectionBundle
.message("category.method.0.cannot.be.applied.to.1", method.getName(), qualifierType.getCanonicalText()));
return false;
}
}
- if (argumentTypes == null) return true;
+ if (info.getArgumentTypes() == null) return true;
- GrClosureSignatureUtil.ApplicabilityResult applicable = PsiUtil.isApplicableConcrete(argumentTypes, method, methodResolveResult.getSubstitutor(), place, false);
+ GrClosureSignatureUtil.ApplicabilityResult applicable = PsiUtil.isApplicableConcrete(info.getArgumentTypes(), method, methodResolveResult.getSubstitutor(), info.getCall(), false);
switch (applicable) {
case inapplicable:
- highlightInapplicableMethodUsage(methodResolveResult, place, method, argumentTypes);
+ highlightInapplicableMethodUsage(methodResolveResult, info, method);
return false;
case canBeApplicable:
if (checkUnknownArgs) {
- highlightUnknownArgs(place);
+ highlightUnknownArgs(info);
}
return !checkUnknownArgs;
default:
@@ -991,34 +1017,39 @@
return null;
}
- private void highlightUnknownArgs(@NotNull PsiElement place) {
- final PsiElement toHighlight = getElementToHighlight(place, PsiUtil.getArgumentsList(place));
- registerError(toHighlight, GroovyBundle.message("cannot.infer.argument.types"), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.WEAK_WARNING);
+ private void highlightUnknownArgs(@NotNull CallInfo info) {
+ registerError(info.getElementToHighlight(), GroovyBundle.message("cannot.infer.argument.types"), LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.WEAK_WARNING);
}
}
- private static boolean isListAssignment(GrExpression lValue) {
- if (lValue instanceof GrReferenceExpression) {
- GrReferenceExpression expression = (GrReferenceExpression)lValue;
- final PsiElement dot = expression.getDotToken();
- //noinspection ConstantConditions
- if (dot != null && dot.getNode().getElementType() == GroovyTokenTypes.mSPREAD_DOT) {
- return true;
- }
- else {
- final GrExpression qualifier = expression.getQualifierExpression();
- if (qualifier != null) return isListAssignment(qualifier);
- }
- }
- return false;
- }
-
@Nullable
- private static PsiType inferQualifierTypeByPlace(GrReferenceExpression place) {
- if (place.getParent() instanceof GrIndexProperty) {
- return place.getType();
+ private static List<GrExpression> getExpressionArgumentsOfCall(@NotNull GrArgumentList argumentList) {
+ final GrExpression[] argArray = argumentList.getExpressionArguments();
+ final ArrayList<GrExpression> args = ContainerUtil.newArrayList();
+
+ for (GrExpression arg : argArray) {
+ if (arg instanceof GrSpreadArgument) {
+ GrExpression spreaded = ((GrSpreadArgument)arg).getArgument();
+ if (spreaded instanceof GrListOrMap && !((GrListOrMap)spreaded).isMap()) {
+ Collections.addAll(args, ((GrListOrMap)spreaded).getInitializers());
+ }
+ else {
+ return null;
+ }
+ }
+ else {
+ args.add(arg);
+ }
}
- return GrReferenceResolveUtil.getQualifierType(place);
+
+ final PsiElement parent = argumentList.getParent();
+ if (parent instanceof GrIndexProperty && PsiUtil.isLValue((GroovyPsiElement)parent)) {
+ args.add(TypeInferenceHelper.getInitializerFor((GrExpression)parent));
+ }
+ else if (parent instanceof GrMethodCallExpression) {
+ ContainerUtil.addAll(args, ((GrMethodCallExpression)parent).getClosureArguments());
+ }
+ return args;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovySillyAssignmentInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovySillyAssignmentInspection.java
index d32f298..9c33e5a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovySillyAssignmentInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovySillyAssignmentInspection.java
@@ -52,12 +52,12 @@
return true;
}
+ @NotNull
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
- private static class Visitor
- extends BaseInspectionVisitor {
+ private static class Visitor extends BaseInspectionVisitor {
public void visitAssignmentExpression(@NotNull GrAssignmentExpression assignment) {
super.visitAssignmentExpression(assignment);
@@ -71,8 +71,7 @@
if (rhs == null) {
return;
}
- if (!(rhs instanceof GrReferenceExpression) ||
- !(lhs instanceof GrReferenceExpression)) {
+ if (!(rhs instanceof GrReferenceExpression) || !(lhs instanceof GrReferenceExpression)) {
return;
}
final GrReferenceExpression rhsReference = (GrReferenceExpression) rhs;
@@ -94,8 +93,7 @@
}
final PsiElement rhsReferent = rhsReference.resolve();
final PsiElement lhsReferent = lhsReference.resolve();
- if (rhsReferent != null && lhsReferent != null &&
- !rhsReferent.equals(lhsReferent)) {
+ if (rhsReferent == null || lhsReferent == null || !rhsReferent.equals(lhsReferent)) {
return;
}
registerError(assignment);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyUncheckedAssignmentOfMemberOfRawTypeInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyUncheckedAssignmentOfMemberOfRawTypeInspection.java
index 52b091a..d69140c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyUncheckedAssignmentOfMemberOfRawTypeInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/GroovyUncheckedAssignmentOfMemberOfRawTypeInspection.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,6 +40,8 @@
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+import static org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil.isSpreadAssignment;
+
/**
* @author Maxim.Medvedev
*/
@@ -62,6 +64,7 @@
return true;
}
+ @NotNull
protected BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
@@ -149,7 +152,7 @@
PsiType rType = rValue.getType();
// For assignments with spread dot
- if (isListAssignment(lValue) && lType != null && lType instanceof PsiClassType) {
+ if (isSpreadAssignment(lValue) && lType != null && lType instanceof PsiClassType) {
final PsiClassType pct = (PsiClassType)lType;
final PsiClass clazz = pct.resolve();
if (clazz != null && CommonClassNames.JAVA_UTIL_LIST.equals(clazz.getQualifiedName())) {
@@ -178,20 +181,5 @@
}
}
- private static boolean isListAssignment(GrExpression lValue) {
- if (lValue instanceof GrReferenceExpression) {
- GrReferenceExpression expression = (GrReferenceExpression)lValue;
- final PsiElement dot = expression.getDotToken();
- //noinspection ConstantConditions
- if (dot != null && dot.getNode().getElementType() == GroovyTokenTypes.mSPREAD_DOT) {
- return true;
- }
- else {
- final GrExpression qual = expression.getQualifierExpression();
- if (qual != null) return isListAssignment(qual);
- }
- }
- return false;
- }
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ParameterCastFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ParameterCastFix.java
index 1e11751..4ee984e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ParameterCastFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/assignment/ParameterCastFix.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,13 +31,13 @@
* @author Max Medvedev
*/
public class ParameterCastFix extends GroovyFix {
- private final int myParam;
+ private final GrExpression myArgument;
private final PsiType myType;
private String myName;
- public ParameterCastFix(int param, PsiType type) {
- myParam = param;
- myType = type;
+ public ParameterCastFix(int param, @NotNull PsiType type, @NotNull GrExpression argument) {
+ myArgument = argument;
+ myType = PsiImplUtil.normalizeWildcardTypeByPosition(type, argument);
StringBuilder builder = new StringBuilder();
builder.append("Cast ");
@@ -57,7 +57,7 @@
builder.append("th");
break;
}
- builder.append(" parameter to ").append(type.getCanonicalText());
+ builder.append(" parameter to ").append(myType.getPresentableText());
myName = builder.toString();
@@ -69,12 +69,7 @@
final GrArgumentList list = element instanceof GrArgumentList ? (GrArgumentList)element :PsiUtil.getArgumentsList(element);
if (list == null) return;
- final GrExpression[] arguments = list.getExpressionArguments();
-
- final int p = PsiImplUtil.hasNamedArguments(list) ? myParam - 1 : myParam;
- if (arguments.length <= p) return;
-
- GrCastFix.doCast(project, myType, arguments[p]);
+ GrCastFix.doCast(project, myType, myArgument);
}
@NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GrModifierFix.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GrModifierFix.java
index 28b8f54..15cf050 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GrModifierFix.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GrModifierFix.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,9 +17,8 @@
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiMember;
-import com.intellij.psi.PsiModifierList;
+import com.intellij.psi.*;
+import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyBundle;
@@ -30,40 +29,44 @@
* @author Max Medvedev
*/
public class GrModifierFix extends GroovyFix {
- @NotNull private final PsiModifierList myModifierList;
+ public static final Function<ProblemDescriptor, PsiModifierList> MODIFIER_LIST = new Function<ProblemDescriptor, PsiModifierList>() {
+ @Override
+ public PsiModifierList fun(ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ assert element instanceof PsiImportList : element;
+ return (PsiModifierList)element;
+ }
+ };
+
+ public static final Function<ProblemDescriptor, PsiModifierList> MODIFIER_LIST_OWNER = new Function<ProblemDescriptor, PsiModifierList>() {
+ @Override
+ public PsiModifierList fun(ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ assert element instanceof PsiModifierListOwner : element;
+ return ((PsiModifierListOwner)element).getModifierList();
+ }
+ };
+
+
private final String myModifier;
private final String myText;
private final boolean myDoSet;
+ private final Function<ProblemDescriptor, PsiModifierList> myModifierListProvider;
public GrModifierFix(@NotNull PsiMember member,
- @NotNull PsiModifierList modifierList,
@GrModifier.GrModifierConstant String modifier,
boolean showContainingClass,
- boolean doSet) {
- myModifierList = modifierList;
+ boolean doSet,
+ Function<ProblemDescriptor, PsiModifierList> modifierListProvider) {
myModifier = modifier;
myDoSet = doSet;
+ myModifierListProvider = modifierListProvider;
myText = initText(member, showContainingClass, myModifier, myDoSet);
}
public static String initText(final PsiMember member, final boolean showContainingClass, final String modifier, final boolean doSet) {
- String name;
- if (showContainingClass) {
- final PsiClass containingClass = member.getContainingClass();
- String containingClassName;
- if (containingClass != null) {
- containingClassName = containingClass.getName() + ".";
- }
- else {
- containingClassName = "";
- }
-
- name = containingClassName + member.getName();
- }
- else {
- name = member.getName();
- }
+ String name = getMemberName(member, showContainingClass);
String modifierText = toPresentableText(modifier);
if (doSet) {
@@ -74,6 +77,17 @@
}
}
+ private static String getMemberName(PsiMember member, boolean showContainingClass) {
+ if (showContainingClass) {
+ final PsiClass containingClass = member.getContainingClass();
+ String containingClassName = containingClass != null ? containingClass.getName() + "." : "";
+ return containingClassName + member.getName();
+ }
+ else {
+ return member.getName();
+ }
+ }
+
public static String toPresentableText(String modifier) {
return GroovyBundle.message(modifier + ".visibility.presentation");
}
@@ -91,7 +105,11 @@
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) throws IncorrectOperationException {
- assert myModifierList.isValid();
- myModifierList.setModifierProperty(myModifier, myDoSet);
+ final PsiModifierList modifierList = getModifierList(descriptor);
+ modifierList.setModifierProperty(myModifier, myDoSet);
+ }
+
+ private PsiModifierList getModifierList(ProblemDescriptor descriptor) {
+ return myModifierListProvider.fun(descriptor);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
index 634d32e..5532217 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyAccessibilityInspection.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 org.jetbrains.plugins.groovy.codeInspection.bugs;
+import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
@@ -22,6 +23,7 @@
import com.intellij.psi.util.PsiFormatUtilBase;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
@@ -135,7 +137,16 @@
String modifier = modifiers[i];
modifierListCopy.setModifierProperty(modifier, true);
if (facade.getResolveHelper().isAccessible(refElement, modifierListCopy, location, accessObjectClass, null)) {
- fixes.add(new GrModifierFix(refElement, refElement.getModifierList(), modifier, true, true));
+ fixes.add(new GrModifierFix(refElement, modifier, true, true, new Function<ProblemDescriptor, PsiModifierList>() {
+ @Override
+ public PsiModifierList fun(ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ assert element instanceof GrReferenceElement : element;
+ final PsiElement resolved = ((GrReferenceElement)element).resolve();
+ assert resolved instanceof PsiModifierListOwner : resolved;
+ return ((PsiModifierListOwner)resolved).getModifierList();
+ }
+ }));
}
}
}
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 6f16535..82a688f 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
@@ -21,16 +21,12 @@
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.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
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;
@@ -70,38 +66,18 @@
final PsiElement resolved = referenceExpression.resolve();
if (!GroovyRefactoringUtil.isLocalVariable(resolved)) return;
- 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.in.closure", ((GrNamedElement)resolved).getName(), flowDescription);
+ if (isOtherTypeOrDifferent(referenceExpression, (GrVariable)resolved) ) {
+ final String message = message("local.var.0.is.reassigned", ((GrNamedElement)resolved).getName());
registerError(referenceExpression, message, LocalQuickFix.EMPTY_ARRAY, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}
};
}
- private static boolean isOtherScopeAndType(GrReferenceExpression referenceExpression,
- PsiType checked,
- GrControlFlowOwner varFlowOwner,
- GrControlFlowOwner refFlorOwner) {
- return varFlowOwner != refFlorOwner && !TypesUtil.isAssignable(referenceExpression.getType(), checked, referenceExpression);
- }
+ private static boolean isOtherTypeOrDifferent(@NotNull GrReferenceExpression referenceExpression, GrVariable resolved) {
+ if (ControlFlowUtils.findControlFlowOwner(referenceExpression) != ControlFlowUtils.findControlFlowOwner(resolved)) return true;
- 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;
+ final PsiType currentType = referenceExpression.getType();
+ return currentType != null && currentType != PsiType.NULL && !ControlFlowUtils.findAccess(resolved, referenceExpression, false, true).isEmpty();
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java
index 2eed53a..20b43d3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/control/GroovyUnnecessaryContinueInspection.java
@@ -94,23 +94,14 @@
return;
}
- if (!(continuedStatement instanceof GrLoopStatement)) {
- return;
- }
- final GrCondition body = ((GrLoopStatement) continuedStatement).getBody();
- if (body == null) {
- return;
- }
- if (body instanceof GrBlockStatement) {
- if (ControlFlowUtils.blockCompletesWithStatement((GrBlockStatement) body,
- continueStatement)) {
- registerStatementError(continueStatement);
- }
- } else if (body instanceof GrStatement) {
- if (ControlFlowUtils.statementCompletesWithStatement((GrStatement) body,
- continueStatement)) {
- registerStatementError(continueStatement);
- }
+ if (!(continuedStatement instanceof GrLoopStatement)) return;
+ final GrStatement body = ((GrLoopStatement)continuedStatement).getBody();
+ if (body == null) return;
+
+
+ if (body instanceof GrBlockStatement && ControlFlowUtils.blockCompletesWithStatement((GrBlockStatement)body, continueStatement) ||
+ !(body instanceof GrBlockStatement) && ControlFlowUtils.statementCompletesWithStatement(body, continueStatement)){
+ registerStatementError(continueStatement);
}
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java
index 3c912d7..386c830 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/declaration/GrMethodMayBeStaticInspection.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,12 +17,14 @@
import com.intellij.codeInspection.InspectionManager;
import com.intellij.codeInspection.LocalQuickFix;
+import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.OverridingMethodsSearch;
import com.intellij.psi.search.searches.SuperMethodsSearch;
+import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
@@ -63,8 +65,16 @@
@Override
public void visitMethod(GrMethod method) {
if (checkMethod(method)) {
- LocalQuickFix[] fixes = new LocalQuickFix[]{new GrModifierFix(method, method.getModifierList(), PsiModifier.STATIC, false, true)};
- registerError(method.getNameIdentifierGroovy(), GroovyInspectionBundle.message("method.may.be.static"), fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
+ final GrModifierFix modifierFix = new GrModifierFix(method, PsiModifier.STATIC, false, true, new Function<ProblemDescriptor, PsiModifierList>() {
+ @Override
+ public PsiModifierList fun(ProblemDescriptor descriptor) {
+ final PsiElement element = descriptor.getPsiElement();
+ final PsiElement parent = element.getParent();
+ assert parent instanceof GrMethod : "element: " + element + ", parent:" + parent;
+ return ((GrMethod)parent).getModifierList();
+ }
+ });
+ registerError(method.getNameIdentifierGroovy(), GroovyInspectionBundle.message("method.may.be.static"), new LocalQuickFix[]{modifierFix}, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
}
};
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyCatchBlockInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyCatchBlockInspection.java
index 231bc90..50ff0bc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyCatchBlockInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/exception/GroovyEmptyCatchBlockInspection.java
@@ -18,16 +18,26 @@
import com.intellij.codeInsight.daemon.impl.quickfix.RenameElementFix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
+import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspection;
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor;
+import org.jetbrains.plugins.groovy.codeInspection.GroovyInspectionBundle;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrCatchClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import javax.swing.*;
public class GroovyEmptyCatchBlockInspection extends BaseInspection {
+ public boolean myIgnore = true;
+ public boolean myCountCommentsAsContent = true;
@Nls
@NotNull
@@ -41,11 +51,21 @@
return "Empty 'catch' block";
}
+ @NotNull
public BaseInspectionVisitor buildVisitor() {
return new Visitor();
}
- private static class Visitor extends BaseInspectionVisitor {
+ @Nullable
+ @Override
+ public JComponent createOptionsPanel() {
+ MultipleCheckboxOptionsPanel panel = new MultipleCheckboxOptionsPanel(this);
+ panel.addCheckbox(GroovyInspectionBundle.message("comments.count.as.content"), "myCountCommentsAsContent");
+ panel.addCheckbox(GroovyInspectionBundle.message("ignore.when.catch.parameter.is.named.ignore.or.ignored"), "myIgnore");
+ return panel;
+ }
+
+ private class Visitor extends BaseInspectionVisitor {
public void visitCatchClause(GrCatchClause catchClause) {
super.visitCatchClause(catchClause);
@@ -56,15 +76,29 @@
final GrParameter parameter = catchClause.getParameter();
if (parameter == null) return;
- if (GrExceptionUtil.ignore(parameter)) return;
+ if (myIgnore && GrExceptionUtil.ignore(parameter)) return;
- final LocalQuickFix[] fixes = {new RenameElementFix(parameter, "ignored")};
+ final LocalQuickFix[] fixes = myIgnore
+ ? new RenameElementFix[]{new RenameElementFix(parameter, "ignored")}
+ : LocalQuickFix.EMPTY_ARRAY;
registerError(catchClause.getFirstChild(), "Empty '#ref' block #loc", fixes, ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
}
- private static boolean isEmpty(@NotNull GrOpenBlock body) {
+ private boolean isEmpty(@NotNull GrOpenBlock body) {
final GrStatement[] statements = body.getStatements();
- return statements.length == 0;
+ if (statements.length != 0) return false;
+
+ if (myCountCommentsAsContent) {
+ final PsiElement brace = body.getLBrace();
+ if (brace != null) {
+ final PsiElement next = PsiUtil.skipWhitespaces(brace.getNextSibling(), true);
+ if (next instanceof PsiComment) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
}
}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java
index 107b593..95d9bab 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/local/GroovyPostHighlightingPass.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,22 @@
import com.intellij.codeInspection.InspectionProfile;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.deadCode.UnusedDeclarationInspection;
+import com.intellij.diagnostic.AttachmentFactory;
+import com.intellij.diagnostic.LogMessageEx;
import com.intellij.lang.annotation.Annotation;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.AnnotationSession;
import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.undo.UndoManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -75,6 +81,8 @@
* @author ilyas
*/
public class GroovyPostHighlightingPass extends TextEditorHighlightingPass {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.codeInspection.local.GroovyPostHighlightingPass");
+
private final GroovyFile myFile;
private final Editor myEditor;
private volatile Set<GrImportStatement> myUnusedImports;
@@ -133,19 +141,21 @@
if (deadCodeEnabled &&
element instanceof GrNamedElement && element instanceof PsiModifierListOwner &&
- !PostHighlightingPass.isImplicitUsage((PsiModifierListOwner)element, progress) &&
+ !PostHighlightingPass.isImplicitUsage(((PsiModifierListOwner)element).getProject(), (PsiModifierListOwner)element, progress) &&
!GroovySuppressableInspectionTool.isElementToolSuppressedIn(element, GroovyUnusedDeclarationInspection.SHORT_NAME)) {
PsiElement nameId = ((GrNamedElement)element).getNameIdentifierGroovy();
if (nameId.getNode().getElementType() == GroovyTokenTypes.mIDENT) {
String name = ((GrNamedElement)element).getName();
- if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed((GrTypeDefinition)element, progress, usageHelper)) {
+ if (element instanceof GrTypeDefinition && !PostHighlightingPass.isClassUsed(myProject,
+ ((GrTypeDefinition)element).getContainingFile(), (GrTypeDefinition)element, progress, usageHelper
+ )) {
HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, "Class " + name + " is unused", HighlightInfoType.UNUSED_SYMBOL);
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(element), unusedDefKey);
ContainerUtil.addIfNotNull(unusedDeclarations, highlightInfo);
}
else if (element instanceof GrMethod) {
GrMethod method = (GrMethod)element;
- if (!PostHighlightingPass.isMethodReferenced(method, progress, usageHelper)) {
+ if (!PostHighlightingPass.isMethodReferenced(method.getProject(), method.getContainingFile(), method, progress, usageHelper)) {
String message = (method.isConstructor() ? "Constructor" : "Method") + " " + name + " is unused";
HighlightInfo highlightInfo = PostHighlightingPass.createUnusedSymbolInfo(nameId, message, HighlightInfoType.UNUSED_SYMBOL);
QuickFixAction.registerQuickFixAction(highlightInfo, new SafeDeleteFix(method), unusedDefKey);
@@ -222,7 +232,7 @@
}
private static boolean isFieldUnused(GrField field, ProgressIndicator progress, GlobalUsageHelper usageHelper) {
- if (!PostHighlightingPass.isFieldUnused(field, progress, usageHelper)) return false;
+ if (!PostHighlightingPass.isFieldUnused(field.getProject(), field.getContainingFile(), field, progress, usageHelper)) return false;
final GrAccessorMethod[] getters = field.getGetters();
final GrAccessorMethod setter = field.getSetter();
@@ -300,7 +310,7 @@
final Runnable optimize = myOptimizeRunnable;
if (optimize != null && timeToOptimizeImports()) {
- PostHighlightingPass.invokeOnTheFlyImportOptimizer(new Runnable() {
+ invokeOnTheFlyImportOptimizer(new Runnable() {
@Override
public void run() {
optimize.run();
@@ -309,6 +319,39 @@
}
}
+ public static void invokeOnTheFlyImportOptimizer(@NotNull final Runnable runnable,
+ @NotNull final PsiFile file,
+ @NotNull final Editor editor) {
+ final long stamp = editor.getDocument().getModificationStamp();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (file.getProject().isDisposed() || editor.isDisposed() || editor.getDocument().getModificationStamp() != stamp) return;
+ //no need to optimize imports on the fly during undo/redo
+ final UndoManager undoManager = UndoManager.getInstance(editor.getProject());
+ if (undoManager.isUndoInProgress() || undoManager.isRedoInProgress()) return;
+ PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
+ String beforeText = file.getText();
+ final long oldStamp = editor.getDocument().getModificationStamp();
+ CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(runnable);
+ }
+ });
+ if (oldStamp != editor.getDocument().getModificationStamp()) {
+ String afterText = file.getText();
+ if (Comparing.strEqual(beforeText, afterText)) {
+ LOG.error(
+ LogMessageEx.createEvent("Import optimizer hasn't optimized any imports", file.getViewProvider().getVirtualFile().getPath(),
+ AttachmentFactory.createAttachment(file.getViewProvider().getVirtualFile())));
+ }
+ }
+ }
+ });
+ }
+
+
private static TextRange calculateRangeToUse(GrImportStatement unusedImport) {
final TextRange range = unusedImport.getTextRange();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unassignedVariable/UnassignedVariableAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unassignedVariable/UnassignedVariableAccessInspection.java
index 511c19d..d84e99b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unassignedVariable/UnassignedVariableAccessInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unassignedVariable/UnassignedVariableAccessInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -35,6 +35,7 @@
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrTraditionalForClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
@@ -87,7 +88,7 @@
ReadWriteVariableInstruction[] reads = ControlFlowBuilderUtil.getReadsWithoutPriorWrites(flow, true);
for (ReadWriteVariableInstruction read : reads) {
PsiElement element = read.getElement();
- if (element instanceof GroovyPsiElement) {
+ if (element instanceof GroovyPsiElement && !(element instanceof GrClosableBlock)) {
String name = read.getVariableName();
GroovyPsiElement property = ResolveUtil.resolveProperty((GroovyPsiElement)element, name);
if (property != null &&
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
index 3bc8412..7259fa7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/untypedUnresolvedAccess/GrUnresolvedAccessInspection.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.
@@ -81,6 +81,7 @@
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrReferenceResolveUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -224,6 +225,7 @@
final PsiClass outerClass = clazz.getContainingClass();
if (com.intellij.psi.util.PsiUtil.isInnerClass(clazz) &&
outerClass != null &&
+ newExpression.getArgumentList() != null &&
!PsiUtil.hasEnclosingInstanceInScope(outerClass, newExpression, true) &&
!hasEnclosingInstanceInArgList(newExpression.getArgumentList(), outerClass)) {
String qname = clazz.getQualifiedName();
@@ -237,7 +239,7 @@
return null;
}
- private static boolean hasEnclosingInstanceInArgList(GrArgumentList list, PsiClass enclosingClass) {
+ private static boolean hasEnclosingInstanceInArgList(@NotNull GrArgumentList list, @NotNull PsiClass enclosingClass) {
if (PsiImplUtil.hasNamedArguments(list)) return false;
GrExpression[] args = list.getExpressionArguments();
@@ -546,24 +548,26 @@
HighlightInfo info,
boolean compileStatic,
final HighlightDisplayKey key) {
- PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic);
+ PsiClass targetClass = QuickfixUtil.findTargetClass(refExpr, compileStatic);
if (targetClass == null) return;
- if (!compileStatic) {
- addDynamicAnnotation(info, refExpr, key);
- }
+ if (!(targetClass instanceof SyntheticElement) || (targetClass instanceof GroovyScriptClass)) {
+ if (!compileStatic) {
+ addDynamicAnnotation(info, refExpr, key);
+ }
- QuickFixAction.registerQuickFixAction(info, new CreateFieldFromUsageFix(refExpr), key);
+ QuickFixAction.registerQuickFixAction(info, new CreateFieldFromUsageFix(refExpr), key);
- if (PsiUtil.isAccessedForReading(refExpr)) {
- QuickFixAction.registerQuickFixAction(info, new CreateGetterFromUsageFix(refExpr, targetClass), key);
- }
- if (PsiUtil.isLValue(refExpr)) {
- QuickFixAction.registerQuickFixAction(info, new CreateSetterFromUsageFix(refExpr), key);
- }
+ if (PsiUtil.isAccessedForReading(refExpr)) {
+ QuickFixAction.registerQuickFixAction(info, new CreateGetterFromUsageFix(refExpr, targetClass), key);
+ }
+ if (PsiUtil.isLValue(refExpr)) {
+ QuickFixAction.registerQuickFixAction(info, new CreateSetterFromUsageFix(refExpr), key);
+ }
- if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) {
- QuickFixAction.registerQuickFixAction(info, new CreateMethodFromUsageFix(refExpr), key);
+ if (refExpr.getParent() instanceof GrCall && refExpr.getParent() instanceof GrExpression) {
+ QuickFixAction.registerQuickFixAction(info, new CreateMethodFromUsageFix(refExpr), key);
+ }
}
if (!refExpr.isQualified()) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java
index 3cf0b38..0386ab5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/unusedDef/UnusedDefInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -23,7 +23,6 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
-import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.Processor;
@@ -208,7 +207,7 @@
}
}
- return ReferencesSearch.search(var, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
+ return ReferencesSearch.search(var, var.getUseScope()).forEach(new Processor<PsiReference>() {
public boolean process(PsiReference ref) {
return ControlFlowUtils.findControlFlowOwner(ref.getElement()) == scope;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java
index b1a497d..999d2bd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/utils/ControlFlowUtils.java
@@ -23,6 +23,7 @@
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import org.jetbrains.annotations.NotNull;
@@ -43,6 +44,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrUnaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.AfterCallInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.ReadWriteVariableInstruction;
@@ -117,21 +119,18 @@
if (statementIsBreakTarget(switchStatement)) {
return true;
}
+
final GrCaseSection[] caseClauses = switchStatement.getCaseSections();
- if (caseClauses.length == 0) {
- return true;
- }
- boolean hasDefaultCase = false;
- for (GrCaseSection clause : caseClauses) {
- if (clause.isDefault()) {
- hasDefaultCase = true;
+ if (ContainerUtil.find(caseClauses, new Condition<GrCaseSection>() {
+ @Override
+ public boolean value(GrCaseSection section) {
+ return section.isDefault();
}
+ }) == null) {
+ return true;
}
- if (!hasDefaultCase) {
- return true;
- }
final GrCaseSection lastClause = caseClauses[caseClauses.length - 1];
final GrStatement[] statements = lastClause.getStatements();
if (statements.length == 0) {
@@ -296,25 +295,44 @@
if (statementToCheck == null) {
return false;
}
- final GrStatement container = getContainingStatement(statementToCheck);
+
+ final PsiElement container = statementToCheck.getParent();
if (container == null) {
return false;
}
- if (isLoop(container)) {
+
+ if (container instanceof GrLoopStatement) {
return false;
}
- if (container instanceof GrBlockStatement) {
- if (!statementIsLastInBlock((GrBlockStatement)container, statementToCheck)) {
+ else if (container instanceof GrCaseSection) {
+ final GrCaseSection caseSection = (GrCaseSection)container;
+
+ if (!statementIsLastInBlock(caseSection, statementToCheck)) return false;
+
+ final PsiElement parent = container.getParent();
+ assert parent instanceof GrSwitchStatement;
+ final GrSwitchStatement switchStatement = (GrSwitchStatement)parent;
+
+ final GrCaseSection[] sections = switchStatement.getCaseSections();
+ if (ArrayUtil.getLastElement(sections) != caseSection) {
return false;
}
- if (container.equals(body)) {
- return true;
+ }
+ else if (container instanceof GrOpenBlock) {
+ final GrOpenBlock block = (GrOpenBlock)container;
+
+ if (!statementIsLastInBlock(block, statementToCheck)) return false;
+ final PsiElement parent = block.getParent();
+ if (parent instanceof GrBlockStatement) {
+ final GrBlockStatement blockStatement = (GrBlockStatement)parent;
+ if (blockStatement == body) return true;
}
- statementToCheck = PsiTreeUtil.getParentOfType(container, GrStatement.class);
}
- else {
- statementToCheck = container;
+ else if (container instanceof GrClosableBlock) {
+ return false;
}
+
+ statementToCheck = getContainingStatement(statementToCheck);
}
}
@@ -338,7 +356,7 @@
if (container instanceof GrCodeBlock) {
if (elementToCheck instanceof GrStatement) {
final GrCodeBlock codeBlock = (GrCodeBlock)container;
- if (!statementIsLastInCodeBlock(codeBlock, (GrStatement)elementToCheck)) {
+ if (!statementIsLastInBlock(codeBlock, (GrStatement)elementToCheck)) {
return false;
}
}
@@ -372,7 +390,7 @@
return false;
}
if (container instanceof GrCodeBlock) {
- if (!statementIsLastInCodeBlock((GrCodeBlock)container, (GrStatement)statementToCheck)) {
+ if (!statementIsLastInBlock((GrCodeBlock)container, (GrStatement)statementToCheck)) {
return false;
}
if (container.equals(body)) {
@@ -386,7 +404,7 @@
}
}
- private static boolean isLoop(@NotNull GroovyPsiElement element) {
+ private static boolean isLoop(@NotNull PsiElement element) {
return element instanceof GrLoopStatement;
}
@@ -401,20 +419,10 @@
}
private static boolean statementIsLastInBlock(@NotNull GrBlockStatement block, @NotNull GrStatement statement) {
- final GrStatement[] statements = block.getBlock().getStatements();
- for (int i = statements.length - 1; i >= 0; i--) {
- final GrStatement childStatement = statements[i];
- if (statement.equals(childStatement)) {
- return true;
- }
- if (!(childStatement instanceof GrReturnStatement)) {
- return false;
- }
- }
- return false;
+ return statementIsLastInBlock(block.getBlock(), statement);
}
- private static boolean statementIsLastInCodeBlock(@NotNull GrCodeBlock block, @NotNull GrStatement statement) {
+ private static boolean statementIsLastInBlock(@NotNull GrStatementOwner block, @NotNull GrStatement statement) {
final GrStatement[] statements = block.getStatements();
for (int i = statements.length - 1; i >= 0; i--) {
final GrStatement childStatement = statements[i];
@@ -709,15 +717,10 @@
* @param ahead if true search for next write. if false searches for previous write
* @return all write instructions leading to (or preceding) the place
*/
- public static ReadWriteVariableInstruction[] findWriteAccess(GrVariable local, final PsiElement place, boolean ahead) {
- List<ReadWriteVariableInstruction> res = findAccess(local, place, ahead, true);
- return res.toArray(new ReadWriteVariableInstruction[res.size()]);
- }
-
public static List<ReadWriteVariableInstruction> findAccess(GrVariable local, final PsiElement place, boolean ahead, boolean writeAccessOnly) {
LOG.assertTrue(!(local instanceof GrField), local.getClass());
- final GrControlFlowOwner owner = findControlFlowOwner(local);
+ final GrControlFlowOwner owner = findControlFlowOwner(place);
assert owner != null;
final Instruction cur = findInstruction(place, owner.getControlFlow());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyCodeStyleSettings.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyCodeStyleSettings.java
index 06aff70..ef1024a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyCodeStyleSettings.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyCodeStyleSettings.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.
@@ -41,9 +41,9 @@
public boolean USE_FLYING_GEESE_BRACES = false;
public boolean SPACE_IN_NAMED_ARGUMENT = true;
- public boolean ALIGN_MULTILINE_LIST_OR_MAP = false;
+ public boolean ALIGN_MULTILINE_LIST_OR_MAP = true;
public boolean SPACE_WITHIN_LIST_OR_MAP = false;
- public boolean ALIGN_NAMED_ARGS_IN_MAP = false;
+ public boolean ALIGN_NAMED_ARGS_IN_MAP = true;
public boolean SPACE_BEFORE_CLOSURE_LBRACE = true;
public boolean SPACE_WITHIN_GSTRING_INJECTION_BRACES = false;
public boolean SPACE_WITHIN_TUPLE_EXPRESSION = false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java
index bbeb15b..0aecf6c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeStyle/GroovyLanguageCodeStyleSettingsProvider.java
@@ -166,7 +166,7 @@
"SPACE_AROUND_ADDITIVE_OPERATORS",
"SPACE_AROUND_MULTIPLICATIVE_OPERATORS",
"SPACE_AROUND_SHIFT_OPERATORS",
- "SPACE_AROUND_UNARY_OPERATOR",
+ //"SPACE_AROUND_UNARY_OPERATOR",
"SPACE_AFTER_COMMA",
"SPACE_AFTER_COMMA_IN_TYPE_ARGUMENTS",
"SPACE_BEFORE_COMMA",
@@ -224,6 +224,7 @@
"SPACE_WITHIN_ANNOTATION_PARENTHESES"
);
consumer.renameStandardOption("SPACE_AROUND_RELATIONAL_OPERATORS", "Relational operators (<, >, <=, >=, <=>)");
+ consumer.renameStandardOption("SPACE_AROUND_UNARY_OPERATOR", "Unary operators (!, -, +, ++, --, *)");
consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_IN_NAMED_ARGUMENT", "In named argument after ':'", CodeStyleSettingsCustomizable.SPACES_OTHER);
consumer.showCustomOption(GroovyCodeStyleSettings.class, "SPACE_WITHIN_LIST_OR_MAP", "List and maps literals", CodeStyleSettingsCustomizable.SPACES_WITHIN);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompiler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompiler.java
index b01fbb7..2a62258 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompiler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/compiler/GroovyCompiler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -141,7 +141,7 @@
"(you can do it yourself later in Settings | Compiler | Resource patterns)",
"AST Transformations Found",
JetgroovyIcons.Groovy.Groovy_32x32);
- if (result == 0) {
+ if (result == Messages.YES) {
CompilerConfiguration.getInstance(myProject).addResourceFilePattern(AST_TRANSFORM_FILE_NAME);
} else {
configuration.transformsOk = true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyAwareModuleBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyAwareModuleBuilder.java
index d163b28..db51e01 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyAwareModuleBuilder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyAwareModuleBuilder.java
@@ -39,7 +39,7 @@
@SuppressWarnings("UnusedDeclaration")
public GroovyAwareModuleBuilder() {
- this("groovy", "Groovy", "Simple module with attached Groovy library", null);
+ this("groovy", "Groovy", "Simple module with attached Groovy library", JetgroovyIcons.Groovy.GroovyModule);
}
protected GroovyAwareModuleBuilder(String builderId, String presentableName, String description, Icon bigIcon) {
@@ -90,6 +90,16 @@
return "Groovy";
}
+ @Override
+ public String getParentGroup() {
+ return getModuleTypeName();
+ }
+
+ @Override
+ public boolean isTemplateBased() {
+ return true;
+ }
+
@Nullable
protected MvcFramework getFramework() {
return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java
index 015102a..ff05249 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/config/GroovyConfigUtils.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,17 +46,19 @@
* @author ilyas
*/
public abstract class GroovyConfigUtils extends AbstractConfigUtils {
- @NonNls private static final Pattern GROOVY_ALL_JAR_PATTERN = Pattern.compile("groovy-all-(.*)\\.jar");
- private static GroovyConfigUtils myGroovyConfigUtils;
+ @NonNls public static final Pattern GROOVY_ALL_JAR_PATTERN = Pattern.compile("groovy-all(-(.*))?\\.jar");
+ @NonNls public static final Pattern GROOVY_JAR_PATTERN = Pattern.compile("groovy(-(\\d.*))?\\.jar");
- @NonNls public static final String GROOVY_JAR_PATTERN_NOVERSION = "groovy\\.jar";
- @NonNls public static final String GROOVY_JAR_PATTERN = "groovy-(\\d.*)\\.jar";
public static final String NO_VERSION = "<no version>";
public static final String GROOVY1_7 = "1.7";
public static final String GROOVY1_8 = "1.8";
public static final String GROOVY2_0 = "2.0";
public static final String GROOVY2_1 = "2.1";
public static final String GROOVY2_2 = "2.2";
+ public static final String GROOVY2_2_2 = "2.2.2";
+ public static final String GROOVY2_3 = "2.3";
+
+ private static GroovyConfigUtils myGroovyConfigUtils;
private GroovyConfigUtils() {
}
@@ -84,9 +86,6 @@
public String getSDKVersion(@NotNull final String path) {
String groovyJarVersion = getSDKJarVersion(path + "/lib", GROOVY_JAR_PATTERN, MANIFEST_PATH);
if (groovyJarVersion == null) {
- groovyJarVersion = getSDKJarVersion(path + "/lib", GROOVY_JAR_PATTERN_NOVERSION, MANIFEST_PATH);
- }
- if (groovyJarVersion == null) {
groovyJarVersion = getSDKJarVersion(path + "/lib", GROOVY_ALL_JAR_PATTERN, MANIFEST_PATH);
}
if (groovyJarVersion == null) {
@@ -143,7 +142,6 @@
if (file != null && file.isDirectory()) {
final String path = file.getPath();
if (GroovyUtils.getFilesInDirectoryByPattern(path + "/lib", GROOVY_JAR_PATTERN).length > 0 ||
- GroovyUtils.getFilesInDirectoryByPattern(path + "/lib", GROOVY_JAR_PATTERN_NOVERSION).length > 0 ||
GroovyUtils.getFilesInDirectoryByPattern(path + "/embeddable", GROOVY_ALL_JAR_PATTERN).length > 0 ||
GroovyUtils.getFilesInDirectoryByPattern(path, GROOVY_JAR_PATTERN).length > 0) {
return true;
@@ -160,7 +158,7 @@
int result = Messages
.showOkCancelDialog(GroovyBundle.message("groovy.like.library.found.text", module.getName(), library.getName(), getSDKLibVersion(library)),
GroovyBundle.message("groovy.like.library.found"), JetgroovyIcons.Groovy.Groovy_32x32);
- if (result == 0) {
+ if (result == Messages.OK) {
AccessToken accessToken = WriteAction.start();
try {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/DefaultGroovyShellRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/DefaultGroovyShellRunner.java
index db046d1..26e5cad 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/DefaultGroovyShellRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/DefaultGroovyShellRunner.java
@@ -19,7 +19,6 @@
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.search.GlobalSearchScope;
@@ -28,12 +27,8 @@
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.runner.DefaultGroovyScriptRunner;
import org.jetbrains.plugins.groovy.runner.GroovyScriptRunConfiguration;
-import org.jetbrains.plugins.groovy.runner.GroovyScriptRunner;
-import org.jetbrains.plugins.groovy.util.GroovyUtils;
import org.jetbrains.plugins.groovy.util.LibrariesUtil;
-import java.io.File;
-
/**
* @author Sergey Evdokimov
*/
@@ -49,58 +44,32 @@
@Override
public JavaParameters createJavaParameters(@NotNull Module module) throws ExecutionException {
JavaParameters res = GroovyScriptRunConfiguration.createJavaParametersWithSdk(module);
- boolean useBundled = !hasGroovyWithNeededJars(module);
DefaultGroovyScriptRunner.configureGenericGroovyRunner(res, module, "org.codehaus.groovy.tools.shell.Main", false, true);
- if (useBundled) {
- String libRoot = GroovyUtils.getBundledGroovyJar().getParent();
- File libDir = new File(libRoot + "/groovy/lib");
- assert libDir.isDirectory();
- for (File file : libDir.listFiles()) {
- res.getClassPath().add(file);
- }
-
- GroovyScriptRunner.setGroovyHome(res, FileUtil.toCanonicalPath(libRoot + "/groovy"));
- }
res.setWorkingDirectory(getWorkingDirectory(module));
-
return res;
}
@Override
public boolean canRun(@NotNull Module module) {
VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
- return contentRoots.length > 0;
+ return contentRoots.length > 0 && hasGroovyWithNeededJars(module);
}
@NotNull
@Override
public String getTitle(@NotNull Module module) {
String homePath = LibrariesUtil.getGroovyHomePath(module);
- boolean bundled = !hasGroovyWithNeededJars(module);
- if (bundled) {
- homePath = GroovyUtils.getBundledGroovyJar().getParentFile().getParent();
- }
- else {
- assert homePath != null;
- }
+ assert homePath != null;
String version = GroovyConfigUtils.getInstance().getSDKVersion(homePath);
- return version == AbstractConfigUtils.UNDEFINED_VERSION ? "" : " (" + (bundled ? "Bundled " : "") + "Groovy " + version + ")";
+ return version == AbstractConfigUtils.UNDEFINED_VERSION ? "" : " (Groovy " + version + ")";
}
- private static boolean hasGroovyWithNeededJars(Module module) {
+ static boolean hasGroovyWithNeededJars(Module module) {
GlobalSearchScope scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module);
JavaPsiFacade facade = JavaPsiFacade.getInstance(module.getProject());
- return (facade.findClass("org.apache.commons.cli.CommandLineParser", scope) != null ||
- facade.findClass("groovyjarjarcommonscli.CommandLineParser", scope) != null) &&
+ return (facade.findClass("org.apache.commons.cli.CommandLineParser", scope) != null || facade.findClass("groovyjarjarcommonscli.CommandLineParser", scope) != null) &&
facade.findClass("groovy.ui.GroovyMain", scope) != null &&
facade.findClass("org.fusesource.jansi.AnsiConsole", scope) != null;
}
-
- @NotNull
- @Override
- public String transformUserInput(@NotNull String userInput) {
- //return StringUtil.replace(userInput, "\n", "###\\n");
- return userInput;
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyConsoleRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyConsoleRunner.java
index bf46a21..1932da4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyConsoleRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyConsoleRunner.java
@@ -69,13 +69,11 @@
@NotNull
@Override
public String getTitle(@NotNull Module module) {
- String homePath = LibrariesUtil.getGroovyHomePath(module);
- boolean bundled = false;
- if (homePath == null || !hasGroovyAll(module)) {
- homePath = GroovyUtils.getBundledGroovyJar().getParentFile().getParent();
- bundled = true;
- }
- String version = GroovyConfigUtils.getInstance().getSDKVersion(homePath);
+ String moduleGroovyHomePath = LibrariesUtil.getGroovyHomePath(module);
+ boolean bundled = moduleGroovyHomePath == null || !hasGroovyAll(module);
+ String homePathToUse = bundled ? GroovyUtils.getBundledGroovyJar().getParentFile().getParent() : moduleGroovyHomePath;
+
+ String version = GroovyConfigUtils.getInstance().getSDKVersion(homePathToUse);
return version == AbstractConfigUtils.UNDEFINED_VERSION ? "" : " (" + (bundled ? "Bundled " : "") + "Groovy " + version + ")";
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellAction.java
index 835687a..085cce5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellAction.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellAction.java
@@ -22,6 +22,11 @@
* @author peter
*/
public class GroovyShellAction extends GroovyShellActionBase {
+ @Override
+ protected boolean isSuitableModule(Module module) {
+ return super.isSuitableModule(module) && DefaultGroovyShellRunner.hasGroovyWithNeededJars(module);
+ }
+
protected GroovyShellRunner getRunner(Module module) {
return new DefaultGroovyShellRunner();
}
@@ -33,31 +38,6 @@
@Override
protected GroovyShellConsoleImpl createConsole(Project project, String title) {
- final GroovyShellConsoleImpl console = new GroovyShellConsoleImpl(project, title);
-
- /*UiNotifyConnector.doWhenFirstShown(console.getComponent(), new Runnable() {
- @Override
- public void run() {
- final String key = "groovy.shell.is.really.groovy.shell";
- if (!PropertiesComponent.getInstance().isTrueValue(key)) {
- final Alarm alarm = new Alarm();
- alarm.addRequest(new Runnable() {
- @Override
- public void run() {
- GotItMessage.createMessage("Groovy Shell & Groovy Console", "<html><div align='left'>Use 'Groovy Console' action (Tools | Groovy Console...) to run <a href='http://'>Groovy Console</a><br>Use 'Groovy Shell' action (Tools | Groovy Shell...) to invoke <a href=\"http://groovy.codehaus.org/Groovy+Shell\">Groovy Shell</a></div></html>")
- .setDisposable(console)
- .show(new RelativePoint(console.getComponent(), new Point(10, 0)), Balloon.Position.above);
-
- PropertiesComponent.getInstance().setValue(key, String.valueOf(true));
- Disposer.dispose(alarm);
- }
- }, 2000);
- }
-
- }
- })*/;
-
-
- return console;
+ return new GroovyShellConsoleImpl(project, title);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java
index 90087a8..e9d5151 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/console/GroovyShellActionBase.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.
@@ -45,8 +45,10 @@
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.openapi.util.Condition;
import com.intellij.openapi.util.Key;
import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.ContainerUtil;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl;
@@ -64,10 +66,10 @@
public static final Key<Boolean> GROOVY_SHELL_FILE = Key.create("GROOVY_SHELL_FILE");
private static final String GROOVY_SHELL_LAST_MODULE = "Groovy.Shell.LastModule";
- private static List<Module> getGroovyCompatibleModules(Project project) {
+ private List<Module> getGroovyCompatibleModules(Project project) {
ArrayList<Module> result = new ArrayList<Module>();
for (Module module : ModuleManager.getInstance(project).getModules()) {
- if (GroovyUtils.isSuitableModule(module)) {
+ if (isSuitableModule(module)) {
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
if (sdk != null && sdk.getSdkType() instanceof JavaSdkType) {
result.add(module);
@@ -77,6 +79,10 @@
return result;
}
+ protected boolean isSuitableModule(Module module) {
+ return GroovyUtils.isSuitableModule(module);
+ }
+
@Override
public void update(AnActionEvent e) {
final Project project = e.getData(CommonDataKeys.PROJECT);
@@ -153,13 +159,19 @@
}
};
- for (int i = 0; i < modules.size(); i++) {
- Module module = modules.get(i);
- if (module.getName().equals(PropertiesComponent.getInstance(project).getValue(GROOVY_SHELL_LAST_MODULE))) {
- step.setDefaultOptionIndex(i);
- break;
+ final String lastModuleName = PropertiesComponent.getInstance(project).getValue(GROOVY_SHELL_LAST_MODULE);
+ if (lastModuleName != null) {
+ int defaultOption = ContainerUtil.indexOf(modules, new Condition<Module>() {
+ @Override
+ public boolean value(Module module) {
+ return module.getName().equals(lastModuleName);
+ }
+ });
+ if (defaultOption >= 0) {
+ step.setDefaultOptionIndex(defaultOption);
}
}
+
JBPopupFactory.getInstance().createListPopup(step).showCenteredInCurrentWindow(project);
}
@@ -231,7 +243,7 @@
protected ConsoleExecuteActionHandler createConsoleExecuteActionHandler() {
ConsoleExecuteActionHandler handler = new ConsoleExecuteActionHandler(getProcessHandler(), false) {
@Override
- public void processLine(String line) {
+ public void processLine(@NotNull String line) {
super.processLine(myShellRunner.transformUserInput(line));
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java
index 81d24d3..4e88625 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/GroovyCodeFragmentFactory.java
@@ -97,41 +97,32 @@
if (!isStatic) {
javaText.append("java.lang.Object |thiz0;\n");
- String fileName;
+ PsiFile containingFile = context.getContainingFile();
- PsiElement originalContext = context.getContainingFile().getContext();
- if (originalContext == null) {
- fileName = null; // The class is not reloaded by springloaded if context is in physical file.
- }
- else {
- fileName = originalContext.getContainingFile().getOriginalFile().getName();
+ if (containingFile.getContext() != null) {
+ containingFile = containingFile.getContext().getContainingFile();
}
- if (fileName == null) {
- // The class could not be reloaded by springloaded
- javaText.append("|thiz0 = this;\n");
- }
- else {
- // Class could be reloaded by springloaded
+ String fileName = containingFile.getOriginalFile().getName();
- String s = StringUtil.escapeStringCharacters(Pattern.quote(fileName));
- // We believe what class is reloaded if stacktrace matches one of two patterns:
- // 1.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), com.package.Foo$$DNLbVXwm.methodName(Unknown Source), *
- // 2.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), * com.springsource.loaded. *
- // Pattern below test this.
+ String s = StringUtil.escapeStringCharacters(Pattern.quote(fileName));
+ // We believe what class is reloaded if stacktrace matches one of two patterns:
+ // 1.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), com.package.Foo$$DNLbVXwm.methodName(Unknown Source), *
+ // 2.) [com.package.Foo$$ENLbVXwm.methodName(FileName.groovy:12), * com.springsource.loaded. *
+ // Pattern below test this.
- //javaText.append("System.out.println(java.util.Arrays.toString(new Exception().getStackTrace()));\n");
- //javaText.append("System.out.println(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(" + s + ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), |.+(?:com|org)\\\\.springsource\\\\.loaded\\\\.).+\")\n");
+ //javaText.append("System.out.println(java.util.Arrays.toString(new Exception().getStackTrace()));\n");
+ //javaText.append("System.out.println(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(" + s + ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), |.+(?:com|org)\\\\.springsource\\\\.loaded\\\\.).+\")\n");
- javaText.append(
- "if (java.util.Arrays.toString(new Exception().getStackTrace()).matches(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(")
- .append(s)
- .append(":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), $OR$.+(?:com$OR$org)\\\\.springsource\\\\.loaded\\\\.).+\")) {\n");
- javaText.append(" |thiz0 = thiz;\n");
- javaText.append(" } else {\n");
- javaText.append(" |thiz0 = this;\n");
- javaText.append(" }\n");
- }
+ javaText.append(
+ "if (java.util.Arrays.toString(new Exception().getStackTrace()).matches(\"\\\\[([^,()]+\\\\$\\\\$)[A-Za-z0-9]{8}(\\\\.[^,()]+)\\\\(")
+ .append(s)
+ .append(
+ ":\\\\d+\\\\), (\\\\1[A-Za-z0-9]{8}\\\\2\\\\(Unknown Source\\\\), $OR$.+(?:com$OR$org)\\\\.springsource\\\\.loaded\\\\.).+\")) {\n");
+ javaText.append(" |thiz0 = thiz;\n");
+ javaText.append(" } else {\n");
+ javaText.append(" |thiz0 = this;\n");
+ javaText.append(" }\n");
}
if (!isStatic) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/filters/GroovyDebuggerClassFilterProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/filters/GroovyDebuggerClassFilterProvider.java
index f8ae680..77cbbb1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/filters/GroovyDebuggerClassFilterProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/filters/GroovyDebuggerClassFilterProvider.java
@@ -17,7 +17,6 @@
import com.intellij.ui.classFilter.ClassFilter;
import com.intellij.ui.classFilter.DebuggerClassFilterProvider;
-import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.Arrays;
import java.util.Collections;
@@ -38,18 +37,4 @@
return Collections.emptyList();
}
- public boolean isAuxiliaryFrame(String className, String methodName) {
- if (className.equals(GroovyCommonClassNames.DEFAULT_GROOVY_METHODS) ||
- className.equals("org.codehaus.groovy.runtime.DefaultGroovyMethodsSupport")) {
- return false;
- }
-
- for (ClassFilter filter : FILTERS) {
- final String pattern = filter.getPattern();
- if (className.startsWith(pattern.substring(0, pattern.length() - 1))) {
- return true;
- }
- }
- return false;
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/fragments/GroovyCodeFragment.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/fragments/GroovyCodeFragment.java
index 45d37ed..5818cd9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/fragments/GroovyCodeFragment.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/debugger/fragments/GroovyCodeFragment.java
@@ -151,7 +151,7 @@
return myExceptionChecker;
}
- public void setIntentionActionsFilter(IntentionActionsFilter filter) {
+ public void setIntentionActionsFilter(@NotNull IntentionActionsFilter filter) {
myFilter = filter;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GenerateGroovyDocDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GenerateGroovyDocDialog.java
index cf71abd..2d87f0a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GenerateGroovyDocDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GenerateGroovyDocDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -54,12 +54,6 @@
}
}
- @Override
- protected void dispose() {
- super.dispose();
- //Disposer.dispose(myPanel);
- }
-
@Nullable
@Override
protected String getHelpId() {
@@ -84,7 +78,7 @@
int choice = Messages.showOkCancelDialog(myProject,
GroovyDocBundle.message("groovydoc.generate.directory.not.exists", dirName),
GroovyDocBundle.message("groovydoc.generate.message.title"), Messages.getWarningIcon());
- if (choice != 0) return false;
+ if (choice != Messages.OK) return false;
if (!dir.mkdirs()) {
showError(GroovyDocBundle.message("groovydoc.generate.directory.creation.failed", dirName));
return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocBundle.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocBundle.java
index b0d8df1..4a403bc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocBundle.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -26,19 +27,16 @@
public class GroovyDocBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.groovy.doc.GroovyDocBundle";
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.groovy.doc.GroovyDocBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
@@ -46,6 +44,5 @@
}
return bundle;
}
-
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocGenerationPanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocGenerationPanel.java
index 5f9cec8..3973a8d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocGenerationPanel.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/doc/GroovyDocGenerationPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -36,7 +36,7 @@
import java.util.HashSet;
import java.util.Set;
-public final class GroovyDocGenerationPanel extends JPanel/* implements Disposable*/ {
+public final class GroovyDocGenerationPanel extends JPanel {
JPanel myPanel;
TextFieldWithBrowseButton myOutputDir;
NonFocusableCheckBox myIsUse;
@@ -54,9 +54,6 @@
private final DefaultListModel myDataModel;
GroovyDocGenerationPanel() {
- //Disposer.register(this, myInputDir);
- //Disposer.register(this, myOutputDir);
-
myInputDir.addBrowseFolderListener(GroovyDocBundle.message("groovydoc.generate.directory.browse"), null, null,
FileChooserDescriptorFactory.createSingleFolderDescriptor());
@@ -161,8 +158,4 @@
public JPanel getPanel() {
return myPanel;
}
-
- //@Override
- public void dispose() {
- }
}
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 57c7d30..25c3646 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/dsl/GroovyDslFileIndex.java
@@ -343,8 +343,7 @@
@Nullable
private static List<Pair<File, GroovyDslExecutor>> derefStandardScripts() {
- SoftReference<List<Pair<File, GroovyDslExecutor>>> ref = ourStandardScripts;
- return ref == null ? null : ref.get();
+ return SoftReference.dereference(ourStandardScripts);
}
private static List<Pair<File, GroovyDslExecutor>> getStandardScripts() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportHelper.java
index 2b0dc1f..d6a3214 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportHelper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportHelper.java
@@ -23,6 +23,7 @@
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
+import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.resolve.DefaultImportContributor;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
@@ -106,8 +107,9 @@
}
}
+ GroovyPsiManager groovyPsiManager = GroovyPsiManager.getInstance(file.getProject());
for (String implicitlyImportedClass : GroovyFileBase.IMPLICITLY_IMPORTED_CLASSES) {
- PsiClass clazz = facade.findClass(implicitlyImportedClass, file.getResolveScope());
+ PsiClass clazz = groovyPsiManager.findClassWithCache(implicitlyImportedClass, file.getResolveScope());
if (clazz != null && !ResolveUtil.processElement(processor, clazz, state)) return false;
}
return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportOptimizer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportOptimizer.java
index fc7bbff..a909733 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportOptimizer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/GroovyImportOptimizer.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.
@@ -21,6 +21,7 @@
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashSet;
import gnu.trove.TObjectIntHashMap;
@@ -56,7 +57,7 @@
public static Set<GrImportStatement> findUsedImports(GroovyFile file) {
Set<GrImportStatement> usedImports = new HashSet<GrImportStatement>();
- processFile(file, null, null, usedImports, null, null, null, null);
+ processFile(file, null, null, usedImports, null, null, null, null, null);
return usedImports;
}
@@ -68,12 +69,15 @@
@Nullable final Set<String> importedClasses,
@Nullable final Set<String> staticallyImportedMembers,
@Nullable final Set<GrImportStatement> usedImports,
+ @Nullable final Set<GrImportStatement> unresolvedOnDemandImports,
@Nullable final Set<String> implicitlyImported,
@Nullable final Set<String> innerClasses,
@Nullable final Map<String, String> aliased,
@Nullable final Map<String, String> annotations) {
if (!(file instanceof GroovyFile)) return;
+ final Set<String> unresolvedReferenceNames = ContainerUtil.newLinkedHashSet();
+
file.accept(new PsiRecursiveElementWalkingVisitor() {
@Override
public void visitElement(PsiElement element) {
@@ -84,22 +88,30 @@
}
private void visitRefElement(GrReferenceElement refElement) {
- if ("super".equals(refElement.getReferenceName())) return;
+ final String refName = refElement.getReferenceName();
+
+ if ("super".equals(refName)) return;
final GroovyResolveResult[] resolveResults = refElement.multiResolve(false);
+ if (resolveResults.length == 0 && refName != null) {
+ if (PsiTreeUtil.getParentOfType(refElement, GrImportStatement.class) == null) {
+ unresolvedReferenceNames.add(refName);
+ }
+ }
+
for (GroovyResolveResult resolveResult : resolveResults) {
final PsiElement context = resolveResult.getCurrentFileResolveContext();
- final PsiElement element = resolveResult.getElement();
- if (element == null) return;
+ final PsiElement resolved = resolveResult.getElement();
+ if (resolved == null) return;
if (context instanceof GrImportStatement) {
final GrImportStatement importStatement = (GrImportStatement)context;
- if (usedImports != null && isImportUsed(refElement, element)) {
+ if (usedImports != null && isImportUsed(refElement, resolved)) {
usedImports.add(importStatement);
}
- if (isImplicitlyImported(element, refElement.getReferenceName(), (GroovyFile)file)) {
- addImplicitClass(element);
+ if (isImplicitlyImported(resolved, refName, (GroovyFile)file)) {
+ addImplicitClass(resolved);
}
if (!importStatement.isAliasedImport() && !isAnnotatedImport(importStatement)) {
@@ -107,8 +119,8 @@
if (importStatement.isOnDemand()) {
if (importStatement.isStatic()) {
- if (element instanceof PsiMember) {
- final PsiMember member = (PsiMember)element;
+ if (resolved instanceof PsiMember) {
+ final PsiMember member = (PsiMember)resolved;
final PsiClass clazz = member.getContainingClass();
if (clazz != null) {
final String classQName = clazz.getQualifiedName();
@@ -122,7 +134,7 @@
}
}
else {
- importedName = getTargetQualifiedName(element);
+ importedName = getTargetQualifiedName(resolved);
}
}
else {
@@ -152,14 +164,14 @@
if (importedClasses != null) {
importedClasses.add(importedName);
}
- if (element instanceof PsiClass && ((PsiClass)element).getContainingClass() != null && innerClasses != null) {
+ if (resolved instanceof PsiClass && ((PsiClass)resolved).getContainingClass() != null && innerClasses != null) {
innerClasses.add(importedName);
}
}
}
}
else if (context == null && !(refElement.getParent() instanceof GrImportStatement) && refElement.getQualifier() == null) {
- addImplicitClass(element);
+ addImplicitClass(resolved);
}
}
}
@@ -179,8 +191,8 @@
/**
* checks if import for implicitly imported class is needed
*/
- private boolean isImportUsed(GrReferenceElement refElement, PsiElement element) {
- if (isImplicitlyImported(element, refElement.getReferenceName(), (GroovyFile)file)) {
+ private boolean isImportUsed(GrReferenceElement refElement, PsiElement resolved) {
+ if (isImplicitlyImported(resolved, refElement.getReferenceName(), (GroovyFile)file)) {
final ClassResolverProcessor processor =
new ClassResolverProcessor(refElement.getReferenceName(), refElement, ResolverProcessor.RESOLVE_KINDS_CLASS);
processImports(ResolveState.initial(), null, refElement, processor, ((GroovyFile)file).getImportStatements(), true);
@@ -192,6 +204,53 @@
}
});
+ final Set<GrImportStatement> importsToCheck = ContainerUtil.newLinkedHashSet(PsiUtil.getValidImportStatements((GroovyFile)file));
+ for (GrImportStatement anImport : importsToCheck) {
+ if (usedImports != null && usedImports.contains(anImport)) continue;
+
+ final GrCodeReferenceElement ref = anImport.getImportReference();
+ assert ref != null : "invalid import!";
+
+ if (ref.resolve() == null) {
+ if (anImport.isOnDemand()) {
+ if (usedImports != null) {
+ usedImports.add(anImport);
+ }
+ if (unresolvedOnDemandImports != null) {
+ unresolvedOnDemandImports.add(anImport);
+ }
+ }
+ else {
+ String importedName = anImport.getImportedName();
+ if (importedName != null && unresolvedReferenceNames.contains(importedName)) {
+ if (usedImports != null) {
+ usedImports.add(anImport);
+ }
+
+ final String symbolName = getImportReferenceText(anImport);
+
+ if (anImport.isAliasedImport()) {
+ if (aliased != null) {
+ aliased.put(symbolName, importedName);
+ }
+ }
+ else {
+ if (anImport.isStatic()) {
+ if (staticallyImportedMembers != null) {
+ staticallyImportedMembers.add(symbolName);
+ }
+ }
+ else {
+ if (importedClasses != null) {
+ importedClasses.add(symbolName);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
if (annotations != null) {
((GroovyFile)file).acceptChildren(new GroovyElementVisitor() {
@Override
@@ -238,12 +297,13 @@
final Set<String> simplyImportedClasses = new LinkedHashSet<String>();
final Set<String> staticallyImportedMembers = new LinkedHashSet<String>();
final Set<GrImportStatement> usedImports = new HashSet<GrImportStatement>();
+ final Set<GrImportStatement> unresolvedOnDemandImports = new HashSet<GrImportStatement>();
final Set<String> implicitlyImportedClasses = new LinkedHashSet<String>();
final Set<String> innerClasses = new HashSet<String>();
Map<String, String> aliasImported = ContainerUtil.newHashMap();
Map<String, String> annotatedImports = ContainerUtil.newHashMap();
- processFile(myFile, simplyImportedClasses, staticallyImportedMembers, usedImports, implicitlyImportedClasses, innerClasses,
+ processFile(myFile, simplyImportedClasses, staticallyImportedMembers, usedImports, unresolvedOnDemandImports ,implicitlyImportedClasses, innerClasses,
aliasImported, annotatedImports);
final List<GrImportStatement> oldImports = PsiUtil.getValidImportStatements(file);
if (myRemoveUnusedOnly) {
@@ -258,7 +318,7 @@
// Add new import statements
GrImportStatement[] newImports =
prepare(usedImports, simplyImportedClasses, staticallyImportedMembers, implicitlyImportedClasses, innerClasses, aliasImported,
- annotatedImports);
+ annotatedImports, unresolvedOnDemandImports);
if (oldImports.isEmpty() && newImports.length == 0 && aliasImported.isEmpty()) {
return;
}
@@ -295,7 +355,8 @@
Set<String> implicitlyImported,
Set<String> innerClasses,
Map<String, String> aliased,
- final Map<String, String> annotations) {
+ final Map<String, String> annotations,
+ Set<GrImportStatement> unresolvedOnDemandImports) {
final Project project = myFile.getProject();
final GroovyCodeStyleSettings settings =
CodeStyleSettingsManager.getSettings(project).getCustomSettings(GroovyCodeStyleSettings.class);
@@ -432,6 +493,10 @@
first.getAnnotationList().replace(factory.createModifierList(allSkippedAnnotations));
}
+ for (GrImportStatement anImport : unresolvedOnDemandImports) {
+ explicated.add(anImport);
+ }
+
return explicated.toArray(new GrImportStatement[explicated.size()]);
}
}
@@ -463,7 +528,7 @@
private static String getImportReferenceText(GrImportStatement statement) {
GrCodeReferenceElement importReference = statement.getImportReference();
if (importReference != null) {
- return statement.getText().substring(importReference.getStartOffsetInParent());
+ return importReference.getClassNameText();
}
return null;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/GroovyEnterHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/GroovyEnterHandler.java
index c31b59b..aecc2dd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/GroovyEnterHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/actions/GroovyEnterHandler.java
@@ -21,7 +21,6 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -130,18 +129,18 @@
Project project = file.getProject();
CaretModel caretModel = editor.getCaretModel();
- String text = document.getText();
- if (StringUtil.isEmpty(text)) {
+ if (!(file instanceof GroovyFileBase)) {
return Result.Continue;
}
- if (!(file instanceof GroovyFileBase)) {
+ int docLength = document.getTextLength();
+ if (docLength == 0) {
return Result.Continue;
}
final int caret = caretModel.getOffset();
final EditorHighlighter highlighter = ((EditorEx)editor).getHighlighter();
- if (caret >= 1 && caret < text.length() && CodeInsightSettings.getInstance().SMART_INDENT_ON_ENTER) {
+ if (caret >= 1 && caret < docLength && CodeInsightSettings.getInstance().SMART_INDENT_ON_ENTER) {
HighlighterIterator iterator = highlighter.createIterator(caret);
iterator.retreat();
while (!iterator.atEnd() && TokenType.WHITE_SPACE == iterator.getTokenType()) {
@@ -164,7 +163,7 @@
if (element != null &&
element.getNode().getElementType() == mRCURLY &&
element.getParent() instanceof GrClosableBlock &&
- text.length() > caret && afterArrow) {
+ docLength > caret && afterArrow) {
return Result.DefaultForceIndent;
}
}
@@ -298,7 +297,7 @@
boolean isInsertIndent = isInsertIndent(caretOffset, stringElement.getTextRange().getStartOffset(), fileText);
- // For simple String literals like 'abcdef'
+ // For simple String literals like 'abc'
CaretModel caretModel = editor.getCaretModel();
if (nodeElementType == mSTRING_LITERAL) {
if (isSingleQuoteString(stringElement)) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyBlockStatementsSelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyBlockStatementsSelectioner.java
index eb023ac..545e0ec 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyBlockStatementsSelectioner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyBlockStatementsSelectioner.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -51,7 +51,7 @@
PsiElement lbrace = block.getLBrace();
if (lbrace == null) return block.getTextRange().getStartOffset();
- while (PsiImplUtil.isWhiteSpace(lbrace.getNextSibling())) {
+ while (PsiImplUtil.isWhiteSpaceOrNls(lbrace.getNextSibling())) {
lbrace = lbrace.getNextSibling();
}
return lbrace.getTextRange().getEndOffset();
@@ -61,7 +61,7 @@
PsiElement rbrace = block.getRBrace();
if (rbrace == null) return block.getTextRange().getEndOffset();
- while (PsiImplUtil.isWhiteSpace(rbrace.getPrevSibling()) && rbrace.getPrevSibling().getTextRange().getStartOffset() > startOffset) {
+ while (PsiImplUtil.isWhiteSpaceOrNls(rbrace.getPrevSibling()) && rbrace.getPrevSibling().getTextRange().getStartOffset() > startOffset) {
rbrace = rbrace.getPrevSibling();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java
index 12df73c..257ac99 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyStatementSelectioner.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -21,9 +21,9 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiWhiteSpace;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.List;
@@ -130,7 +130,7 @@
private static boolean isOneLineFeed(PsiElement e) {
if (e == null) return false;
- if (!TokenSets.WHITE_SPACES_SET.contains(e.getNode().getElementType())) return false;
+ if (!PsiImplUtil.isWhiteSpaceOrNls(e)) return false;
final String text = e.getText();
final int i = text.indexOf('\n');
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.java
index 3125606..ba5d061 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/editor/selection/GroovyTypeDefinitionBodySelectioner.java
@@ -49,7 +49,7 @@
PsiElement lbrace = block.getLBrace();
if (lbrace == null) return block.getTextRange().getStartOffset();
- while (PsiImplUtil.isWhiteSpace(lbrace.getNextSibling())) {
+ while (PsiImplUtil.isWhiteSpaceOrNls(lbrace.getNextSibling())) {
lbrace = lbrace.getNextSibling();
}
return lbrace.getTextRange().getEndOffset();
@@ -59,7 +59,7 @@
PsiElement rbrace = block.getRBrace();
if (rbrace == null) return block.getTextRange().getEndOffset();
- while (PsiImplUtil.isWhiteSpace(rbrace.getPrevSibling()) && rbrace.getPrevSibling().getTextRange().getStartOffset() > startOffset) {
+ while (PsiImplUtil.isWhiteSpaceOrNls(rbrace.getPrevSibling()) && rbrace.getPrevSibling().getTextRange().getStartOffset() > startOffset) {
rbrace = rbrace.getPrevSibling();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java
index 4f06c15..64767e0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodDescriptor.java
@@ -80,6 +80,19 @@
}
}
+ @Property(surroundWithTag = false)
+ @AbstractCollection(surroundWithTag = false)
+ public ClosureArgument[] myClosureArguments;
+
+ @Tag("closureArgument")
+ public static class ClosureArgument {
+ @Attribute("index")
+ public int index;
+
+ @Attribute("methodContributor")
+ public String methodContributor;
+ }
+
@Nullable
public List<String> getParams() {
if (params != null) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java
index 7730c6f..8365a38 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/GroovyMethodInfo.java
@@ -11,6 +11,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightMethodBuilder;
+import org.jetbrains.plugins.groovy.lang.resolve.ClosureMissingMethodContributor;
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import org.jetbrains.plugins.groovy.util.FixedValuesReferenceProvider;
@@ -40,6 +41,8 @@
private Map<String, NamedArgumentReference> myNamedArgReferenceProviders;
+ private final GroovyMethodDescriptor myDescriptor;
+
private static void ensureInit() {
if (METHOD_INFOS != null) return;
@@ -131,6 +134,8 @@
private GroovyMethodInfo(GroovyMethodDescriptor method, @NotNull ClassLoader classLoader) {
myClassLoader = classLoader;
+ myDescriptor = method;
+
myParams = method.getParams();
myReturnType = method.returnType;
myReturnTypeCalculatorClassName = method.returnTypeCalculator;
@@ -153,6 +158,12 @@
for (NamedArgumentReference r : myNamedArgReferenceProviders.values()) {
assertClassExists(r.myProviderClassName, PsiReferenceProvider.class, GroovyNamedArgumentReferenceProvider.class);
}
+
+ if (method.myClosureArguments != null) {
+ for (GroovyMethodDescriptor.ClosureArgument argument : method.myClosureArguments) {
+ assertClassExists(argument.methodContributor, ClosureMissingMethodContributor.class);
+ }
+ }
}
}
@@ -174,6 +185,10 @@
}
}
+ public GroovyMethodDescriptor getDescriptor() {
+ return myDescriptor;
+ }
+
private static Map<String, NamedArgumentReference> getNamedArgumentsReferenceProviders(GroovyMethodDescriptor methodDescriptor) {
if (methodDescriptor.myArguments == null) return Collections.emptyMap();
@@ -293,6 +308,10 @@
return myNamedArgProviderInstance;
}
+ public ClassLoader getPluginClassLoader() {
+ return myClassLoader;
+ }
+
public boolean isApplicable(@NotNull PsiMethod method) {
if (myParams == null) {
return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/NamedArgumentDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/NamedArgumentDescriptor.java
index c870de6..910a3a9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/NamedArgumentDescriptor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/extensions/NamedArgumentDescriptor.java
@@ -142,7 +142,7 @@
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
- return new GroovyResolveResult[]{new GroovyResolveResultImpl(myNavigationElement, null, null, mySubstitutor, true, true, false)};
+ return new GroovyResolveResult[]{new GroovyResolveResultImpl(myNavigationElement, null, null, mySubstitutor, true, true)};
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AnnotatedMembersSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AnnotatedMembersSearcher.java
index 86aec32..b8fe585 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AnnotatedMembersSearcher.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/AnnotatedMembersSearcher.java
@@ -53,7 +53,7 @@
final Collection<PsiElement> members = ApplicationManager.getApplication().runReadAction(new Computable<Collection<PsiElement>>() {
@Override
public Collection<PsiElement> compute() {
- return StubIndex.getInstance().get(GrAnnotatedMemberIndex.KEY, name, clazz.getProject(), scope);
+ return StubIndex.getElements(GrAnnotatedMemberIndex.KEY, name, clazz.getProject(), scope, PsiElement.class);
}
});
if (members.isEmpty()) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyFieldFindUsagesHandlerFactory.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyFieldFindUsagesHandlerFactory.java
index ed95d06..676770c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyFieldFindUsagesHandlerFactory.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/findUsages/GroovyFieldFindUsagesHandlerFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
@@ -70,7 +69,7 @@
if (ApplicationManager.getApplication().isUnitTestMode()) return PsiElement.EMPTY_ARRAY;
doSearch = Messages.showYesNoDialog(FindBundle.message("find.field.accessors.prompt", field.getName()),
FindBundle.message("find.field.accessors.title"),
- Messages.getQuestionIcon()) == DialogWrapper.OK_EXIT_CODE;
+ Messages.getQuestionIcon()) == Messages.YES;
}
else {
doSearch = true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java
index 8159008..5c052f4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/AlignmentProvider.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,40 +58,18 @@
}
if (myAlignments.containsKey(set2)) {
- for (Iterator<PsiElement> iterator = set1.iterator(); iterator.hasNext(); ) {
- PsiElement element = iterator.next();
- iterator.remove();
-
- addInternal(set2, element);
- }
+ addSet(set1, set2);
}
else {
set1.addAll(set2);
- for (Iterator<PsiElement> iterator = set2.iterator(); iterator.hasNext(); ) {
- PsiElement element = iterator.next();
- iterator.remove();
-
- addInternal(set1, element);
- }
+ addSet(set2, set1);
}
}
else if (set1 != null) {
- if (allowBackwardShift != null) {
- assert myAllowBackwardShift.get(set1).booleanValue() == allowBackwardShift.booleanValue();
- }
- if (anchor != null) {
- assert myAnchor.get(set1) == anchor;
- }
- addInternal(set1, e2);
+ addElement(e2, allowBackwardShift, anchor, set1);
}
else if (set2 != null) {
- if (allowBackwardShift != null) {
- assert(myAllowBackwardShift.get(set2).booleanValue() == allowBackwardShift.booleanValue());
- }
- if (anchor != null) {
- assert(myAnchor.get(set2) == anchor);
- }
- addInternal(set2, e1);
+ addElement(e1, allowBackwardShift, anchor, set2);
}
else {
final HashSet<PsiElement> set = createHashSet();
@@ -102,6 +80,25 @@
}
}
+ private void addElement(PsiElement e, Boolean allowBackwardShift, Alignment.Anchor anchor, Set<PsiElement> set) {
+ if (allowBackwardShift != null) {
+ assert myAllowBackwardShift.get(set).booleanValue() == allowBackwardShift.booleanValue();
+ }
+ if (anchor != null) {
+ assert myAnchor.get(set) == anchor;
+ }
+ addInternal(set, e);
+ }
+
+ private void addSet(Set<PsiElement> set1, Set<PsiElement> set2) {
+ for (Iterator<PsiElement> iterator = set1.iterator(); iterator.hasNext(); ) {
+ PsiElement element = iterator.next();
+ iterator.remove();
+
+ addInternal(set2, element);
+ }
+ }
+
private void addInternal(@NotNull Set<PsiElement> set, @NotNull PsiElement element) {
myTree.put(element, set);
set.add(element);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GeeseUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GeeseUtil.java
index 30115c2..667be21 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GeeseUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GeeseUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -26,10 +26,10 @@
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;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mRCURLY;
-import static org.jetbrains.plugins.groovy.lang.lexer.TokenSets.WHITE_SPACES_SET;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.CLOSABLE_BLOCK;
/**
@@ -50,7 +50,7 @@
}
ASTNode lastChild = node.getLastChildNode();
- while (lastChild != null && WHITE_SPACES_SET.contains(lastChild.getElementType())) {
+ while (lastChild != null && PsiImplUtil.isWhiteSpaceOrNls(lastChild)) {
lastChild = lastChild.getTreePrev();
}
if (lastChild == null) return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyFormattingModelBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyFormattingModelBuilder.java
index 226e23d..a095273 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyFormattingModelBuilder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/GroovyFormattingModelBuilder.java
@@ -39,7 +39,7 @@
import org.jetbrains.plugins.groovy.codeStyle.GroovyCodeStyleSettings;
import org.jetbrains.plugins.groovy.formatter.blocks.GroovyBlock;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
/**
@@ -94,12 +94,12 @@
@Override
protected String replaceWithPsiInLeaf(TextRange textRange, String whiteSpace, ASTNode leafElement) {
if (!myCanModifyAllWhiteSpaces) {
- if (TokenSets.WHITE_SPACES_SET.contains(leafElement.getElementType())) return null;
+ if (PsiImplUtil.isWhiteSpaceOrNls(leafElement)) return null;
}
IElementType elementTypeToUse = TokenType.WHITE_SPACE;
ASTNode prevNode = TreeUtil.prevLeaf(leafElement);
- if (prevNode != null && TokenSets.WHITE_SPACES_SET.contains(prevNode.getElementType())) {
+ if (prevNode != null && PsiImplUtil.isWhiteSpaceOrNls(prevNode)) {
elementTypeToUse = prevNode.getElementType();
}
FormatterUtil.replaceWhiteSpace(whiteSpace, leafElement, elementTypeToUse, textRange);
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 c2ac05a..337f162 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
@@ -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.
@@ -31,6 +31,7 @@
import com.intellij.psi.tree.TokenSet;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.formatter.AlignmentProvider;
@@ -301,12 +302,20 @@
if (myContext.getSettings().ALIGN_MULTILINE_TERNARY_OPERATION) {
final GrConditionalExpression conditional = (GrConditionalExpression)blockPsi;
- final AlignmentProvider.Aligner aligner = myAlignmentProvider.createAligner(false);
- aligner.append(conditional.getCondition());
+ final AlignmentProvider.Aligner exprAligner = myAlignmentProvider.createAligner(false);
+ exprAligner.append(conditional.getCondition());
if (!(conditional instanceof GrElvisExpression)) {
- aligner.append(conditional.getThenBranch());
+ exprAligner.append(conditional.getThenBranch());
}
- aligner.append(conditional.getElseBranch());
+ exprAligner.append(conditional.getElseBranch());
+
+ ASTNode question = conditional.getNode().findChildByType(GroovyTokenTypes.mQUESTION);
+ ASTNode colon = conditional.getNode().findChildByType(GroovyTokenTypes.mCOLON);
+ if (question != null && colon != null) {
+ AlignmentProvider.Aligner questionColonAligner = myAlignmentProvider.createAligner(false);
+ questionColonAligner.append(question.getPsi());
+ questionColonAligner.append(colon.getPsi());
+ }
}
}
@@ -323,21 +332,25 @@
return wrap;
}
+ @NotNull
public List<Block> generateSubBlockForCodeBlocks(boolean classLevel, final List<ASTNode> children, boolean indentLabelBlocks) {
- calculateAlignments(children, classLevel);
final ArrayList<Block> subBlocks = new ArrayList<Block>();
- if (indentLabelBlocks) {
- for (int i = 0; i < children.size(); i++) {
- ASTNode childNode = children.get(i);
+ if (indentLabelBlocks && (myNode.getElementType() == OPEN_BLOCK || myNode.getElementType() == CLOSABLE_BLOCK || myNode.getElementType() == CONSTRUCTOR_BODY)) {
+ List<ASTNode> flattenChildren = flattenChildren(children);
+ calculateAlignments(flattenChildren, classLevel);
+ for (int i = 0; i < flattenChildren.size(); i++) {
+ ASTNode childNode = flattenChildren.get(i);
if (childNode.getElementType() == LABELED_STATEMENT) {
- int j = i;
+ int start = i;
do {
i++;
}
- while (i < children.size() && children.get(i).getElementType() != LABELED_STATEMENT && children.get(i).getElementType() != mRCURLY);
- subBlocks.add(new GrLabelBlock(childNode, children.subList(j, i), classLevel, getIndent(childNode), getChildWrap(childNode), myContext));
+ while (i < flattenChildren.size() &&
+ flattenChildren.get(i).getElementType() != LABELED_STATEMENT &&
+ flattenChildren.get(i).getElementType() != mRCURLY);
+ subBlocks.add(new GrLabelBlock(childNode, flattenChildren.subList(start + 1, i), classLevel, getIndent(childNode), getChildWrap(childNode), myContext));
i--;
}
else {
@@ -346,6 +359,8 @@
}
}
else {
+ calculateAlignments(children, classLevel);
+
for (ASTNode childNode : children) {
subBlocks.add(new GroovyBlock(childNode, getIndent(childNode), getChildWrap(childNode), myContext));
}
@@ -353,6 +368,23 @@
return subBlocks;
}
+ private static List<ASTNode> flattenChildren(List<ASTNode> children) {
+ ArrayList<ASTNode> result = ContainerUtil.newArrayList();
+ for (ASTNode child : children) {
+ processNodeFlattening(result, child);
+ }
+ return result;
+ }
+
+ private static void processNodeFlattening(ArrayList<ASTNode> result, ASTNode child) {
+ result.add(child);
+ if (child.getElementType() == LABELED_STATEMENT) {
+ for (ASTNode node : visibleChildren(child)) {
+ processNodeFlattening(result, node);
+ }
+ }
+ }
+
private Indent getIndent(ASTNode childNode) {
return new GroovyIndentProcessor().getChildIndent(myBlock, childNode);
}
@@ -365,7 +397,7 @@
PsiElement psi = child.getPsi();
if (psi instanceof GrLabeledStatement) {
alignGroup(currentGroup, spock, classLevel);
- currentGroup = ContainerUtil.newArrayList((GrStatement)psi);
+ currentGroup = ContainerUtil.newArrayList(/*(GrStatement)psi*/);
spock = true;
}
else if (currentGroup != null && spock && isTablePart(psi)) {
@@ -383,18 +415,26 @@
}
}
else {
- if (psi instanceof PsiComment) {
- PsiElement prev = psi.getPrevSibling();
- if (prev != null && prev.getNode().getElementType() != mNLS || classLevel && !fieldGroupEnded(psi)) {
- continue;
- }
- }
+ if (shouldSkip(classLevel, psi)) continue;
alignGroup(currentGroup, spock, classLevel);
currentGroup = null;
}
}
}
+ private boolean shouldSkip(boolean classLevel, PsiElement psi) {
+ if (psi instanceof PsiComment) {
+ PsiElement prev = psi.getPrevSibling();
+ if (prev != null && prev.getNode().getElementType() != mNLS || classLevel && !fieldGroupEnded(psi)) {
+ return true;
+ }
+ }
+ if (psi.getParent() instanceof GrLabeledStatement && !(psi instanceof GrStatement)) {
+ return true;
+ }
+ return false;
+ }
+
private void alignGroup(@Nullable List<GrStatement> group, boolean spock, boolean classLevel) {
if (group == null) {
return;
@@ -432,7 +472,7 @@
if (group.size() < 2) {
return;
}
- GrStatement inner = ((GrLabeledStatement)group.get(0)).getStatement();
+ GrStatement inner = group.get(0);
boolean embedded = inner != null && isTablePart(inner);
GrStatement first = embedded ? inner : group.get(1);
@@ -508,7 +548,6 @@
return blockPsi instanceof GrParameterList && myContext.getSettings().ALIGN_MULTILINE_PARAMETERS ||
blockPsi instanceof GrExtendsClause && myContext.getSettings().ALIGN_MULTILINE_EXTENDS_LIST ||
blockPsi instanceof GrThrowsClause && myContext.getSettings().ALIGN_MULTILINE_THROWS_LIST ||
- blockPsi instanceof GrConditionalExpression && myContext.getSettings().ALIGN_MULTILINE_TERNARY_OPERATION ||
blockPsi instanceof GrListOrMap && myContext.getGroovySettings().ALIGN_MULTILINE_LIST_OR_MAP;
}
@@ -516,7 +555,6 @@
return blockPsi instanceof GrParameterList ||
blockPsi instanceof GrArgumentList ||
blockPsi instanceof GrAssignmentExpression ||
- blockPsi instanceof GrConditionalExpression ||
blockPsi instanceof GrExtendsClause ||
blockPsi instanceof GrThrowsClause ||
blockPsi instanceof GrListOrMap;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java
index 2cc72c3..c81df59 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovyIndentProcessor.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.
@@ -38,6 +38,8 @@
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrThrowsClause;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationArrayInitializer;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationNameValuePair;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
@@ -45,15 +47,19 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrAssertStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrConditionalExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrParenthesizedExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForClause;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameterList;
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.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrWildcardTypeArgument;
import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*;
@@ -89,7 +95,8 @@
}
}
if (parentBlock instanceof GrLabelBlock) {
- return myChildType == LABELED_STATEMENT
+ ASTNode first = parentBlock.getNode().getFirstChildNode();
+ return child == first
? Indent.getNoneIndent()
: Indent.getLabelIndent();
@@ -118,6 +125,13 @@
}
@Override
+ public void visitAnnotationArrayInitializer(GrAnnotationArrayInitializer arrayInitializer) {
+ if (myChildType != mLBRACK && myChildType != mRBRACK) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+ }
+
+ @Override
public void visitListOrMap(GrListOrMap listOrMap) {
if (myChildType != mLBRACK && myChildType != mRBRACK) {
myResult = Indent.getContinuationWithoutFirstIndent();
@@ -212,9 +226,7 @@
@Override
public void visitVariable(GrVariable variable) {
- if (myChild == variable.getInitializerGroovy()) {
- myResult = Indent.getContinuationIndent();
- }
+ myResult = Indent.getContinuationWithoutFirstIndent();
}
@Override
@@ -369,5 +381,67 @@
myResult = Indent.getContinuationWithoutFirstIndent();
}
+ @Override
+ public void visitArrayDeclaration(GrArrayDeclaration arrayDeclaration) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitExpression(GrExpression expression) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitTypeArgumentList(GrTypeArgumentList typeArgumentList) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitCodeReferenceElement(GrCodeReferenceElement refElement) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitWildcardTypeArgument(GrWildcardTypeArgument wildcardTypeArgument) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitDefaultAnnotationValue(GrDefaultAnnotationValue defaultAnnotationValue) {
+ myResult = Indent.getContinuationIndent();
+ }
+
+ @Override
+ public void visitAnnotationNameValuePair(GrAnnotationNameValuePair nameValuePair) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitForInClause(GrForInClause forInClause) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitForClause(GrForClause forClause) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+ @Override
+ public void visitCatchClause(GrCatchClause catchClause) {
+ if (myChild == catchClause.getBody()) {
+ myResult = Indent.getNoneIndent();
+ }
+ else {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+ }
+
+ @Override
+ public void visitTypeParameterList(GrTypeParameterList list) {
+ myResult = Indent.getContinuationWithoutFirstIndent();
+ }
+
+
+
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java
index a6251ea..e64154c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/formatter/processors/GroovySpacingProcessor.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.
@@ -45,6 +45,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.*;
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.arguments.GrSpreadArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
@@ -63,6 +64,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrArrayTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import static org.jetbrains.plugins.groovy.GroovyFileType.GROOVY_LANGUAGE;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.*;
@@ -75,6 +77,7 @@
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mGDOC_COMMENT_START;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mQUESTION;
import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mSEMI;
+import static org.jetbrains.plugins.groovy.formatter.models.spacing.SpacingTokens.mSTAR;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_ASTERISKS;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_INLINE_TAG_END;
import static org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes.mGDOC_INLINE_TAG_START;
@@ -358,29 +361,36 @@
}
@Override
+ public void visitSpreadArgument(GrSpreadArgument spreadArgument) {
+ if (myType1 == mSTAR) {
+ createSpaceInCode(mySettings.SPACE_AROUND_UNARY_OPERATOR);
+ }
+ }
+
+ @Override
public void visitFile(GroovyFileBase file) {
if (isAfterElementOrSemi(PACKAGE_DEFINITION)) {
- myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
+ myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
else if (myType2 == PACKAGE_DEFINITION) {
- myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
+ myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_PACKAGE + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
else if (isLeftOrRight(TYPE_DEFINITION_TYPES)) {
if (myType1 == GROOVY_DOC_COMMENT) {
createLF(true);
}
else {
- myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AROUND_CLASS + 1, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_DECLARATIONS);
+ myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AROUND_CLASS + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
}
else if (isAfterElementOrSemi(IMPORT_STATEMENT) && myType2 != IMPORT_STATEMENT) { //after imports
- myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_IMPORTS + 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
+ myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_AFTER_IMPORTS + 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
else if (myType1 != IMPORT_STATEMENT && !isSemiAfter(IMPORT_STATEMENT) && myType2 == IMPORT_STATEMENT) { //before imports
- myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_IMPORTS, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
+ myResult = Spacing.createSpacing(0, 0, mySettings.BLANK_LINES_BEFORE_IMPORTS, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
else if (isAfterElementOrSemi(IMPORT_STATEMENT) && myType2 == IMPORT_STATEMENT) {
- myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, Integer.MAX_VALUE / 2);
+ myResult = Spacing.createSpacing(0, 0, 1, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
else {
processClassMembers(null);
@@ -572,7 +582,7 @@
@Override
public void visitTypeArgumentList(GrTypeArgumentList typeArgumentList) {
if (myType1 == mLT || myType2 == mGT) {
- createSpaceProperty(false, true, 1);
+ createSpaceInCode(false);
}
}
@@ -848,7 +858,7 @@
}
private void createLazySpace() {
- myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 0, mySettings.KEEP_LINE_BREAKS, mySettings.KEEP_BLANK_LINES_IN_CODE);
+ myResult = Spacing.createSpacing(0, Integer.MAX_VALUE, 0, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
public void visitDocTag(GrDocTag docTag) {
@@ -1011,11 +1021,7 @@
}
private void createSpaceInCode(final boolean space) {
- createSpaceProperty(space, keepBlankLines());
- }
-
- private void createSpaceProperty(boolean space, int keepBlankLines) {
- createSpaceProperty(space, mySettings.KEEP_LINE_BREAKS, keepBlankLines);
+ createSpaceProperty(space, mySettings.KEEP_LINE_BREAKS, keepBlankLines());
}
private void createSpaceProperty(boolean space, boolean keepLineBreaks, final int keepBlankLines) {
@@ -1074,7 +1080,7 @@
}
static boolean isWhiteSpace(final ASTNode node) {
- return node != null && (TokenSets.WHITE_SPACES_SET.contains(node.getElementType()) || node.getTextLength() == 0);
+ return node != null && (PsiImplUtil.isWhiteSpaceOrNls(node) || node.getTextLength() == 0);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantRunner.java
index fedbecb..98dbd90 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gant/GantRunner.java
@@ -61,7 +61,7 @@
int result = Messages
.showOkCancelDialog("Gant is not configured. Do you want to configure it?", "Configure Gant SDK",
JetgroovyIcons.Groovy.Gant_16x16);
- if (result == 0) {
+ if (result == Messages.OK) {
ShowSettingsUtil.getInstance().editConfigurable(project, new GantConfigurable(project));
}
if (!(GantUtils.getSDKInstallPath(module, project).length() > 0)) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/gotoclass/GroovyGoToSymbolContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/gotoclass/GroovyGoToSymbolContributor.java
index ee517e9..b8b4e06 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/gotoclass/GroovyGoToSymbolContributor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/gotoclass/GroovyGoToSymbolContributor.java
@@ -22,6 +22,9 @@
import com.intellij.psi.stubs.StubIndex;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAnnotationMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrAnnotationMethodNameIndex;
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrFieldNameIndex;
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.GrMethodNameIndex;
@@ -49,9 +52,9 @@
GlobalSearchScope scope = includeNonProjectItems ? GlobalSearchScope.allScope(project) : GlobalSearchScope.projectScope(project);
List<NavigationItem> symbols = new ArrayList<NavigationItem>();
- symbols.addAll(StubIndex.getInstance().get(GrFieldNameIndex.KEY, name, project, scope));
- symbols.addAll(StubIndex.getInstance().get(GrMethodNameIndex.KEY, name, project, scope));
- symbols.addAll(StubIndex.getInstance().get(GrAnnotationMethodNameIndex.KEY, name, project, scope));
+ symbols.addAll(StubIndex.getElements(GrFieldNameIndex.KEY, name, project, scope, GrField.class));
+ symbols.addAll(StubIndex.getElements(GrMethodNameIndex.KEY, name, project, scope, GrMethod.class));
+ symbols.addAll(StubIndex.getElements(GrAnnotationMethodNameIndex.KEY, name, project, scope, GrAnnotationMethod.class));
return symbols.toArray(new NavigationItem[symbols.size()]);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.java
index 64b47c7..74bcfea 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -29,19 +30,16 @@
*/
public class GroovyIntentionsBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle";
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
@@ -49,5 +47,4 @@
}
return bundle;
}
-
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
index 17a44c8..846eea7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/GroovyIntentionsBundle.properties
@@ -208,4 +208,9 @@
convert.to.dollar.slash.regex.intention.name=Convert to Dollar-Slashy String
convert.to.dollar.slash.regex.intention.family.name=Convert string literal to dollar-slashy string
gr.remove.explicit.type.declaration.intention.name=Remove explicit type
-gr.remove.explicit.type.declaration.intention.family.name=Remove explicit type declaration
\ No newline at end of file
+gr.remove.explicit.type.declaration.intention.family.name=Remove explicit type declaration
+rename.file.to.0=Rename file to ''{0}''
+gr.sort.map.keys.intention.name=Sort alphabetically
+gr.sort.map.keys.intention.family.name=Sort map entries alphabetically
+gr.remove.annotation.intention.name=Remove
+gr.remove.annotation.intention.family.name=Remove annotation
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java
index c1df8e1..103546f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/base/Intention.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.
@@ -89,13 +89,17 @@
}
SelectionModel selectionModel = editor.getSelectionModel();
- if (selectionModel.hasSelection()) {
- TextRange selectionRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
- PsiElement element = GroovyRefactoringUtil
- .findElementInRange(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), PsiElement.class);
- while (element != null && element.getTextRange() != null && selectionRange.contains(element.getTextRange())) {
- if (predicate.satisfiedBy(element)) return element;
- element = element.getParent();
+ if (selectionModel.hasSelection() && !selectionModel.hasBlockSelection()) {
+ int start = selectionModel.getSelectionStart();
+ int end = selectionModel.getSelectionEnd();
+
+ if (0 <= start && start <= end) {
+ TextRange selectionRange = new TextRange(start, end);
+ PsiElement element = GroovyRefactoringUtil.findElementInRange(file, start, end, PsiElement.class);
+ while (element != null && element.getTextRange() != null && selectionRange.contains(element.getTextRange())) {
+ if (predicate.satisfiedBy(element)) return element;
+ element = element.getParent();
+ }
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java
index a108c93..41454ce 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ClassNameDiffersFromFileNamePredicate.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,8 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.util.Consumer;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
@@ -26,14 +28,16 @@
* @author Maxim.Medvedev
*/
class ClassNameDiffersFromFileNamePredicate implements PsiElementPredicate {
+ private final Consumer<GrTypeDefinition> myClassConsumer;
private final boolean mySearchForClassInMultiClassFile;
- ClassNameDiffersFromFileNamePredicate(boolean searchForClassInMultiClassFile) {
+ ClassNameDiffersFromFileNamePredicate(@Nullable Consumer<GrTypeDefinition> classConsumer, boolean searchForClassInMultiClassFile) {
+ myClassConsumer = classConsumer;
mySearchForClassInMultiClassFile = searchForClassInMultiClassFile;
}
- ClassNameDiffersFromFileNamePredicate() {
- this(false);
+ ClassNameDiffersFromFileNamePredicate(@Nullable Consumer<GrTypeDefinition> classConsumer) {
+ this(classConsumer, false);
}
@Override
@@ -44,6 +48,7 @@
final String name = ((GrTypeDefinition)parent).getName();
if (name == null || name.length() == 0) return false;
+ if (myClassConsumer != null) myClassConsumer.consume(((GrTypeDefinition)parent));
final PsiFile file = element.getContainingFile();
if (!(file instanceof GroovyFile)) return false;
if (!file.isPhysical()) return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java
index 0cdb467..a69bc7c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/ConvertMapToClassIntention.java
@@ -154,7 +154,7 @@
GroovyIntentionsBundle
.message(
"convert.map.to.class.intention.name"),
- Messages.getQuestionIcon()) != 0);
+ Messages.getQuestionIcon()) != Messages.YES);
}
public static boolean checkForVariableDeclaration(GrExpression replacedNewExpression) {
@@ -171,7 +171,7 @@
GroovyIntentionsBundle.message(
"convert.map.to.class.intention.name"),
Messages.getQuestionIcon()) ==
- 0) {
+ Messages.YES) {
return true;
}
}
@@ -215,7 +215,7 @@
if (ApplicationManager.getApplication().isUnitTestMode() ||
Messages.showYesNoDialog(map.getProject(), GroovyIntentionsBundle
.message("do.you.want.to.change.type.of.parameter.in.method", parameter.getName(), method.getName()),
- GroovyIntentionsBundle.message("convert.map.to.class.intention.name"), Messages.getQuestionIcon()) == 0) {
+ GroovyIntentionsBundle.message("convert.map.to.class.intention.name"), Messages.getQuestionIcon()) == Messages.YES) {
return parameter;
}
return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java
index e84f216..ff8dbf8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/MoveClassToNewFileIntention.java
@@ -23,6 +23,7 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.util.CommonRefactoringUtil;
+import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.actions.GroovyTemplates;
@@ -84,6 +85,6 @@
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
- return new ClassNameDiffersFromFileNamePredicate(true);
+ return new ClassNameDiffersFromFileNamePredicate(null, true);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameFileWithClassIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameFileWithClassIntention.java
index 8a3f5ee..2d93149 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameFileWithClassIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/RenameFileWithClassIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -21,8 +21,10 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.openapi.impl.RenameRefactoringImpl;
+import com.intellij.util.Consumer;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.intentions.GroovyIntentionsBundle;
import org.jetbrains.plugins.groovy.intentions.base.Intention;
import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
@@ -30,21 +32,32 @@
/**
* @author Maxim.Medvedev
*/
-public class RenameFileWithClassIntention extends Intention {
+public class RenameFileWithClassIntention extends Intention implements Consumer<GrTypeDefinition> {
+
+ private String myNewFileName = null;
@Override
protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
- final GrTypeDefinition psiClass = (GrTypeDefinition)element.getParent();
- final String name = psiClass.getName();
+ final PsiFile file = element.getContainingFile();
+ new RenameRefactoringImpl(project, file, myNewFileName, true, true).run();
+ }
- final PsiFile file = psiClass.getContainingFile();
- final String newFileName = name + "." + FileUtilRt.getExtension(file.getName());
- new RenameRefactoringImpl(project, file, newFileName, true, true).run();
+ @NotNull
+ @Override
+ public String getText() {
+ return GroovyIntentionsBundle.message("rename.file.to.0", myNewFileName);
}
@NotNull
@Override
protected PsiElementPredicate getElementPredicate() {
- return new ClassNameDiffersFromFileNamePredicate();
+ return new ClassNameDiffersFromFileNamePredicate(this);
+ }
+
+ @Override
+ public void consume(GrTypeDefinition def) {
+ final String name = def.getName();
+ final PsiFile file = def.getContainingFile();
+ myNewFileName = name + "." + FileUtilRt.getExtension(file.getName());
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java
index 6e98bad..1d33099 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/conversions/strings/ConvertConcatenationToGstringIntention.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.
@@ -196,13 +196,12 @@
private static void getOperandText(@Nullable GrExpression operand, StringBuilder builder, boolean multiline) {
if (operand instanceof GrRegex) {
- boolean isDollarSlashy = GrStringUtil.isDollarSlashyString((GrLiteral)operand);
for (GroovyPsiElement element : ((GrRegex)operand).getAllContentParts()) {
if (element instanceof GrStringInjection) {
builder.append(element.getText());
}
else if (element instanceof GrStringContent) {
- if (isDollarSlashy) {
+ if (GrStringUtil.isDollarSlashyString((GrLiteral)operand)) {
processDollarSlashyContent(builder, multiline, element.getText());
}
else {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateFieldForParameterIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateFieldForParameterIntention.java
index c8b8731..6c56814 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateFieldForParameterIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateFieldForParameterIntention.java
@@ -59,7 +59,7 @@
}
private static boolean checkAssignmentToFieldExists(PsiParameter parameter) {
- for (PsiReference reference : ReferencesSearch.search(parameter)) {
+ for (PsiReference reference : ReferencesSearch.search(parameter).findAll()) {
PsiElement element = reference.getElement();
if (element instanceof GrReferenceExpression &&
element.getParent() instanceof GrAssignmentExpression &&
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateSubclassAction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateSubclassAction.java
index 1d152a2..a4cc490 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateSubclassAction.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrCreateSubclassAction.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,24 +29,26 @@
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.fileEditor.ex.IdeDocumentHistory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
-import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.actions.GroovyTemplates;
import org.jetbrains.plugins.groovy.annotator.intentions.CreateClassActionBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
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.GrReferenceList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
/**
@@ -75,14 +77,13 @@
new WriteCommandAction(project, getTitle(psiClass), getTitle(psiClass)) {
@Override
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
IdeDocumentHistory.getInstance(project).includeCurrentPlaceAsChangePlace();
final GrTypeParameterList oldTypeParameterList = psiClass.getTypeParameterList();
try {
- targetClass.set(CreateClassActionBase.createClassByType(targetDirectory, className, PsiManager.getInstance(project), psiClass,
- GroovyTemplates.GROOVY_CLASS, true));
+ targetClass.set(CreateClassActionBase.createClassByType(targetDirectory, className, PsiManager.getInstance(project), psiClass, GroovyTemplates.GROOVY_CLASS, true));
}
catch (final IncorrectOperationException e) {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@@ -96,10 +97,9 @@
return;
}
startTemplate(oldTypeParameterList, project, psiClass, targetClass.get(), false);
- PsiElement element = targetClass.get();
- JavaCodeStyleManager.getInstance(project).shortenClassReferences(element);
}
}.execute();
+
if (targetClass.get() == null) return null;
if (!ApplicationManager.getApplication().isUnitTestMode() && !psiClass.hasTypeParameters()) {
@@ -118,22 +118,15 @@
boolean includeClassName) {
PsiElementFactory jfactory = JavaPsiFacade.getElementFactory(project);
final GroovyPsiElementFactory elementFactory = GroovyPsiElementFactory.getInstance(project);
- GrCodeReferenceElement ref = elementFactory.createCodeReferenceElementFromClass(psiClass);
+ GrCodeReferenceElement stubRef = elementFactory.createCodeReferenceElementFromClass(psiClass);
try {
- if (psiClass.isInterface()) {
- GrImplementsClause clause = targetClass.getImplementsClause();
- if (clause == null) {
- clause = (GrImplementsClause)targetClass.addAfter(elementFactory.createImplementsClause(), targetClass.getNameIdentifierGroovy());
- }
- ref = (GrCodeReferenceElement)clause.add(ref);
+ GrReferenceList clause = psiClass.isInterface() ? targetClass.getImplementsClause() : targetClass.getExtendsClause();
+ if (clause == null) {
+ GrReferenceList stubRefList = psiClass.isInterface() ? elementFactory.createImplementsClause() : elementFactory.createExtendsClause();
+ clause = (GrExtendsClause)targetClass.addAfter(stubRefList, targetClass.getNameIdentifierGroovy());
}
- else {
- GrExtendsClause clause = targetClass.getExtendsClause();
- if (clause == null) {
- clause = (GrExtendsClause)targetClass.addAfter(elementFactory.createExtendsClause(), targetClass.getNameIdentifierGroovy());
- }
- ref = (GrCodeReferenceElement)clause.add(ref);
- }
+ GrCodeReferenceElement ref = (GrCodeReferenceElement)clause.add(stubRef);
+
if (psiClass.hasTypeParameters() || includeClassName) {
final Editor editor = CodeInsightUtil.positionCursor(project, targetClass.getContainingFile(), targetClass.getLBrace());
final TemplateBuilderImpl templateBuilder = editor == null || ApplicationManager.getApplication().isUnitTestMode() ? null
@@ -143,19 +136,31 @@
templateBuilder.replaceElement(targetClass.getNameIdentifier(), targetClass.getName());
}
- if (oldTypeParameterList != null) {
+ if (oldTypeParameterList != null && oldTypeParameterList.getTypeParameters().length > 0) {
+ GrTypeArgumentList existingList = ref.getTypeArgumentList();
+ final GrTypeParameterList typeParameterList =
+ (GrTypeParameterList)targetClass.addAfter(elementFactory.createTypeParameterList(), targetClass.getNameIdentifierGroovy());
+
+ GrTypeArgumentList argList;
+ if (existingList == null) {
+ GrCodeReferenceElement codeRef = elementFactory.createCodeReferenceElementFromText("A<T>");
+ argList = ((GrTypeArgumentList)ref.add(codeRef.getTypeArgumentList()));
+ argList.getTypeArgumentElements()[0].delete();
+ }
+ else {
+ argList = existingList;
+ }
+
for (PsiTypeParameter parameter : oldTypeParameterList.getTypeParameters()) {
- final PsiElement param = ref.getTypeArgumentList().add(elementFactory.createTypeElement(jfactory.createType(parameter)));
+ final PsiElement param = argList.add(elementFactory.createTypeElement(jfactory.createType(parameter)));
if (templateBuilder != null) {
templateBuilder.replaceElement(param, param.getText());
}
+
+ typeParameterList.add(elementFactory.createTypeParameter(parameter.getName(), parameter.getExtendsListTypes()));
}
}
- final GrTypeParameterList typeParameterList = targetClass.getTypeParameterList();
- assert typeParameterList != null;
- typeParameterList.replace(oldTypeParameterList);
-
if (templateBuilder != null) {
templateBuilder.setEndVariableBefore(ref);
final Template template = templateBuilder.buildTemplate();
@@ -166,12 +171,14 @@
PsiDocumentManager.getInstance(project).doPostponedOperationsAndUnblockDocument(editor.getDocument());
final TextRange textRange = targetClass.getTextRange();
- final int startClassOffset = textRange.getStartOffset();
+ final RangeMarker startClassOffset = editor.getDocument().createRangeMarker(textRange.getStartOffset(), textRange.getEndOffset());
+ startClassOffset.setGreedyToLeft(true);
+ startClassOffset.setGreedyToRight(true);
editor.getDocument().deleteString(textRange.getStartOffset(), textRange.getEndOffset());
CreateFromUsageBaseFix.startTemplate(editor, template, project, new TemplateEditingAdapter() {
@Override
public void templateFinished(Template template, boolean brokenOff) {
- chooseAndImplement(psiClass, project,PsiTreeUtil.getParentOfType(containingFile.findElementAt(startClassOffset), GrTypeDefinition.class),editor);
+ chooseAndImplement(psiClass, project,PsiTreeUtil.getParentOfType(containingFile.findElementAt(startClassOffset.getStartOffset()), GrTypeDefinition.class),editor);
}
}, getTitle(psiClass));
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrIntroduceLocalVariableIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrIntroduceLocalVariableIntention.java
index a099692..d4e3c2d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrIntroduceLocalVariableIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrIntroduceLocalVariableIntention.java
@@ -1,8 +1,25 @@
+/*
+ * 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.intentions.declaration;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
@@ -46,16 +63,16 @@
editor.getSelectionModel().setSelection(offset, offset + length);
}
-
@Override
- public boolean startInWriteAction() {
- return false;
- }
-
- @Override
- protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
+ protected void processIntention(@NotNull final PsiElement element, final Project project, final Editor editor) throws IncorrectOperationException {
setSelection(editor, getTargetExpression(element));
- new GrIntroduceVariableHandler().invoke(project, editor, element.getContainingFile(), null);
+ final PsiFile file = element.getContainingFile();
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ new GrIntroduceVariableHandler().invoke(project, editor, file, null);
+ }
+ });
}
@NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java
index 5f53070..74bdd87 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/declaration/GrRemoveExplicitTypeDeclarationIntention.java
@@ -65,7 +65,7 @@
return ((GrVariable)parent).getTypeElementGroovy() != null;
}
- if (parent instanceof GrMethod) {
+ if (parent instanceof GrMethod && ((GrMethod)parent).findSuperMethods().length == 0 ) {
return ((GrMethod)parent).getReturnTypeElementGroovy() != null;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/other/GrSortMapKeysIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/other/GrSortMapKeysIntention.java
new file mode 100644
index 0000000..ce1a8fb
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/other/GrSortMapKeysIntention.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 org.jetbrains.plugins.groovy.intentions.other;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.util.IncorrectOperationException;
+import groovy.lang.Closure;
+import org.codehaus.groovy.runtime.DefaultGroovyMethods;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.intentions.base.ErrorUtil;
+import org.jetbrains.plugins.groovy.intentions.base.Intention;
+import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+/**
+ * Created by Max Medvedev on 10/01/14
+ */
+public class GrSortMapKeysIntention extends Intention {
+
+ @Override
+ protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
+ PsiElement parent = element.getParent();
+
+ if (parent instanceof GrArgumentLabel) {
+ PsiElement pparent = parent.getParent().getParent();
+ if (pparent instanceof GrListOrMap && !ErrorUtil.containsError(pparent)) {
+ GrListOrMap map = (GrListOrMap)pparent;
+ if (map.getInitializers().length == 0) {
+ GrNamedArgument[] namedArgs = map.getNamedArguments();
+ if (isLiteralKeys(namedArgs)) {
+ GrListOrMap newMap = constructNewMap(namedArgs, project);
+ map.replace(newMap);
+ }
+ }
+ }
+ }
+ }
+
+ @NotNull
+ private static GrListOrMap constructNewMap(@NotNull GrNamedArgument[] args, Project project) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append("[");
+
+ Arrays.sort(args, new Comparator<GrNamedArgument>() {
+ @Override
+ public int compare(GrNamedArgument o1, GrNamedArgument o2) {
+ final String l1 = o1.getLabelName();
+ final String l2 = o2.getLabelName();
+ assert l1 != null && l2 != null;
+
+ return l1.compareTo(l2);
+ }
+ });
+
+ for (GrNamedArgument arg : args) {
+ builder.append(arg.getText()).append(",\n");
+ }
+
+
+ builder.replace(builder.length() - 2, builder.length(), "]");
+
+ return (GrListOrMap)GroovyPsiElementFactory.getInstance(project).createExpressionFromText(builder);
+ }
+
+ @NotNull
+ @Override
+ protected PsiElementPredicate getElementPredicate() {
+ return new PsiElementPredicate() {
+ @Override
+ public boolean satisfiedBy(PsiElement element) {
+ PsiElement parent = element.getParent();
+ if (parent instanceof GrArgumentLabel &&
+ ((GrArgumentLabel)parent).getNameElement().equals(element) &&
+ parent.getParent() != null &&
+ parent.getParent().getParent() instanceof GrListOrMap) {
+ GrListOrMap map = DefaultGroovyMethods.asType(parent.getParent().getParent(), GrListOrMap.class);
+ if (!ErrorUtil.containsError(map) && map.getInitializers().length == 0 && isLiteralKeys(map.getNamedArguments())) {
+ return true;
+ }
+ }
+
+
+ return false;
+ }
+ };
+ }
+
+ private static boolean isLiteralKeys(GrNamedArgument[] args) {
+ return DefaultGroovyMethods.find(args, new Closure<Boolean>(null, null) {
+ public Boolean doCall(GrNamedArgument it) {
+ return it.getLabel().getNameElement() == null;
+ }
+
+ public Boolean doCall() {
+ return doCall(null);
+ }
+ }) == null;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertFromGeeseBracesIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertFromGeeseBracesIntention.java
index 1f9417f..ce1b552 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertFromGeeseBracesIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertFromGeeseBracesIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -26,7 +26,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -37,7 +36,7 @@
import org.jetbrains.plugins.groovy.intentions.base.Intention;
import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
/**
* @author Max Medvedev
@@ -54,8 +53,7 @@
return false;
}
- IElementType elementType = element.getNode().getElementType();
- if (TokenSets.WHITE_SPACES_SET.contains(elementType)) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(element)) {
element = PsiTreeUtil.prevLeaf(element);
}
@@ -97,8 +95,7 @@
@Override
protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
- IElementType elementType = element.getNode().getElementType();
- if (TokenSets.WHITE_SPACES_SET.contains(elementType)) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(element)) {
element = PsiTreeUtil.prevLeaf(element);
}
LOG.assertTrue(GeeseUtil.isClosureRBrace(element));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertToGeeseBracesIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertToGeeseBracesIntention.java
index 81d9f33..963e9d9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertToGeeseBracesIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/ConvertToGeeseBracesIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -27,7 +27,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
-import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
@@ -37,7 +36,7 @@
import org.jetbrains.plugins.groovy.intentions.base.Intention;
import org.jetbrains.plugins.groovy.intentions.base.PsiElementPredicate;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import static org.jetbrains.plugins.groovy.formatter.GeeseUtil.*;
@@ -56,8 +55,7 @@
return false;
}
- IElementType elementType = element.getNode().getElementType();
- if (TokenSets.WHITE_SPACES_SET.contains(elementType)) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(element)) {
element = PsiTreeUtil.prevLeaf(element);
}
@@ -87,8 +85,7 @@
@Override
protected void processIntention(@NotNull PsiElement element, Project project, Editor editor) throws IncorrectOperationException {
- IElementType elementType = element.getNode().getElementType();
- if (TokenSets.WHITE_SPACES_SET.contains(elementType)) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(element)) {
element = PsiTreeUtil.prevLeaf(element);
}
LOG.assertTrue(isClosureRBrace(element) && isClosureContainLF(element));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java
index 48e774c..79eb885 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/intentions/style/parameterToEntry/ConvertParameterToMapEntryIntention.java
@@ -445,7 +445,6 @@
final Task task = new Task.Modal(project, GroovyIntentionsBundle
.message("find.method.ro.closure.usages.0", owner instanceof GrClosableBlock ? CLOSURE_CAPTION : METHOD_CAPTION), true) {
public void run(@NotNull final ProgressIndicator indicator) {
- final GlobalSearchScope projectScope = GlobalSearchScope.projectScope(getProject());
final Collection<PsiReference> references = Collections.synchronizedSet(new HashSet<PsiReference>());
final Processor<PsiReference> consumer = new Processor<PsiReference>() {
@Override
@@ -454,7 +453,7 @@
return true;
}
};
- ReferencesSearch.search(namedElem, projectScope).forEach(consumer);
+ ReferencesSearch.search(namedElem).forEach(consumer);
if (namedElem instanceof GrField && ((GrField)namedElem).isProperty()) {
final GrAccessorMethod[] getters = ((GrField)namedElem).getGetters();
for (GrAccessorMethod getter : getters) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java
index aa24e61..eba80bc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionData.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.
@@ -239,8 +239,11 @@
elem = PsiUtil.skipWhitespacesAndComments(context.getPrevSibling(), false);
}
else {
- if (elem.getParent() != null) {
- elem = elem.getParent().getPrevSibling();
+ if (elem instanceof GrReferenceExpression && PsiUtil.skipWhitespacesAndComments(elem.getPrevSibling(), false) instanceof GrTypeDefinition) {
+ elem = PsiUtil.skipWhitespacesAndComments(elem.getPrevSibling(), false);
+ }
+ else if (elem.getParent() != null) {
+ elem = PsiUtil.skipWhitespacesAndComments(elem.getParent().getPrevSibling(), false);
}
}
@@ -591,7 +594,7 @@
candidate = PsiUtil.skipWhitespacesAndComments(run.getPrevSibling(), false, skipNLs);
}
else {
- candidate = PsiTreeUtil.prevLeaf(context);
+ candidate = PsiUtil.skipWhitespacesAndComments(PsiTreeUtil.prevLeaf(context), false);
}
if (candidate instanceof PsiErrorElement) candidate = candidate.getPrevSibling();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
index d841cc8..e3b6fc6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.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.
@@ -263,9 +263,9 @@
}
- public static List<? extends LookupElement> createLookupElements(GroovyResolveResult candidate,
+ public static List<? extends LookupElement> createLookupElements(@NotNull GroovyResolveResult candidate,
boolean afterNew,
- PrefixMatcher matcher,
+ @NotNull PrefixMatcher matcher,
@Nullable PsiElement position) {
final PsiElement element = candidate.getElement();
final PsiElement context = candidate.getCurrentFileResolveContext();
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 7392520..4d1f239 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
@@ -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.
@@ -411,7 +411,9 @@
}
final LookupItem item = PsiTypeLookupItem.createLookupItem(GenericsUtil.eliminateWildcards(type), place, isDiamond, ChooseTypeExpression.IMPORT_FIXER);
- JavaCompletionUtil.setShowFQN(item);
+ if (item.getObject() instanceof PsiClass) {
+ JavaCompletionUtil.setShowFQN(item);
+ }
item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, true));
return item;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java
index 8ed7f39..53e941d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/closureParameters/ClosureDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -87,12 +87,12 @@
}
final boolean isConstructor = Boolean.TRUE.equals(myMethod.get("constructor"));
final MethodSignature signature = MethodSignatureUtil
- .createMethodSignature(name, types.toArray(new PsiType[types.size()]), method.getTypeParameters(), PsiSubstitutor.EMPTY, isConstructor);
+ .createMethodSignature(name, types.toArray(PsiType.createArray(types.size())), method.getTypeParameters(), PsiSubstitutor.EMPTY, isConstructor);
final GrClosureSignature closureSignature = GrClosureSignatureUtil.createSignature(signature);
if (method instanceof ClsMethodImpl) method = ((ClsMethodImpl)method).getSourceMirrorMethod();
final PsiParameter[] parameters = method.getParameterList().getParameters();
- final PsiType[] typeArray = new PsiType[parameters.length];
+ final PsiType[] typeArray = PsiType.createArray(parameters.length);
ContainerUtil.map(parameters, new Function<PsiParameter, PsiType>() {
@Override
public PsiType fun(PsiParameter parameter) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java
index d56722d..f24d182 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.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.
@@ -48,7 +48,6 @@
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocCommentOwner;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.impl.GrDocCommentUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
@@ -60,6 +59,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrPropertyForCompletion;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrImplicitVariable;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrLightVariable;
@@ -195,7 +195,7 @@
private static void appendInferredType(PsiElement originalElement, GrVariable variable, StringBuilder buffer) {
PsiType inferredType = null;
- if (TokenSets.WHITE_SPACES_SET.contains(originalElement.getNode().getElementType())) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(originalElement)) {
originalElement = PsiTreeUtil.prevLeaf(originalElement);
}
if (originalElement != null && originalElement.getNode().getElementType() == GroovyTokenTypes.mIDENT) {
@@ -455,7 +455,7 @@
PsiFormatUtilBase.SHOW_TYPE);
createElementLink(sb, element, str);
}
- return CodeInsightBundle.message("javadoc.candiates", text, sb);
+ return CodeInsightBundle.message("javadoc.candidates", text, sb);
}
return CodeInsightBundle.message("javadoc.candidates.not.found", text);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java
index 4965af3..25b2e48 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/folding/GroovyFoldingBuilder.java
@@ -21,6 +21,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.lang.folding.CustomFoldingBuilder;
import com.intellij.lang.folding.FoldingDescriptor;
+import com.intellij.lang.folding.NamedFoldingDescriptor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.FoldingGroup;
import com.intellij.openapi.project.DumbAware;
@@ -41,6 +42,7 @@
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.toplevel.imports.GrImportStatement;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
import java.util.List;
@@ -82,15 +84,14 @@
usedComments.add(element);
PsiElement end = null;
for (PsiElement current = element.getNextSibling(); current != null; current = current.getNextSibling()) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(current)) continue;
+
IElementType elementType = current.getNode().getElementType();
if (elementType == mSL_COMMENT) {
end = current;
usedComments.add(current);
continue;
}
- if (WHITE_SPACES_SET.contains(elementType)) {
- continue;
- }
break;
}
if (end != null) {
@@ -121,11 +122,11 @@
if (lbrace != null && rbrace != null) {
final PsiElement next = lbrace.getNextSibling();
final PsiElement prev = rbrace.getPrevSibling();
- if (next != null && WHITE_SPACES_SET.contains(next.getNode().getElementType()) &&
- prev != null && WHITE_SPACES_SET.contains(prev.getNode().getElementType())) {
+ if (next != null && PsiImplUtil.isWhiteSpaceOrNls(next) &&
+ prev != null && PsiImplUtil.isWhiteSpaceOrNls(prev)) {
final FoldingGroup group = FoldingGroup.newGroup("block_group");
- descriptors.add(new NamedFoldingDescriptor(psi.getNode(), lbrace.getTextRange().getStartOffset(), next.getTextRange().getEndOffset(), group, "{"));
- descriptors.add(new NamedFoldingDescriptor(psi.getNode(), prev.getTextRange().getStartOffset(), rbrace.getTextRange().getEndOffset(), group, "}"));
+ descriptors.add(new NamedFoldingDescriptor(psi, lbrace.getTextRange().getStartOffset(), next.getTextRange().getEndOffset(), group, "{"));
+ descriptors.add(new NamedFoldingDescriptor(psi, prev.getTextRange().getStartOffset(), rbrace.getTextRange().getEndOffset(), group, "}"));
return;
}
}
@@ -191,24 +192,6 @@
}
}
- private static class NamedFoldingDescriptor extends FoldingDescriptor {
- private final String myPlaceholderText;
-
- private NamedFoldingDescriptor(@NotNull ASTNode node, int start, int end, @Nullable FoldingGroup group, @NotNull String placeholderText) {
- this(node, new TextRange(start, end), group, placeholderText);
- }
-
- private NamedFoldingDescriptor(@NotNull ASTNode node, @NotNull final TextRange range, @Nullable FoldingGroup group, @NotNull String placeholderText) {
- super(node, range, group);
- myPlaceholderText = placeholderText;
- }
-
- @Override
- public String getPlaceholderText() {
- return myPlaceholderText;
- }
- }
-
private static void processImports(final List<FoldingDescriptor> descriptors, GrImportStatement[] imports) {
if (imports.length < 2) return;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/parser/elements/GroovyDocTagValueTokenType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/parser/elements/GroovyDocTagValueTokenType.java
index a372cef..9bd58f2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/parser/elements/GroovyDocTagValueTokenType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/parser/elements/GroovyDocTagValueTokenType.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.
@@ -120,7 +120,7 @@
return builder.getTreeBuilt().getFirstChildNode();
}
- public static enum TagValueTokenType {
+ public enum TagValueTokenType {
REFERENCE_ELEMENT, VALUE_TOKEN
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodParamsImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodParamsImpl.java
index 5051f08..fcc9d6d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodParamsImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/groovydoc/psi/impl/GrDocMethodParamsImpl.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,7 +25,6 @@
import com.intellij.psi.impl.PsiManagerEx;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.groovydoc.lexer.GroovyDocTokenTypes;
@@ -53,10 +52,12 @@
return "GrDocMethodParameterList";
}
+ @Override
public void accept(GroovyElementVisitor visitor) {
visitor.visitDocMethodParameterList(this);
}
+ @Override
public PsiType[] getParameterTypes() {
ArrayList<PsiType> types = new ArrayList<PsiType>();
PsiManagerEx manager = getManager();
@@ -73,17 +74,19 @@
types.add(null);
}
}
- return types.toArray(new PsiType[types.size()]);
+ return types.toArray(PsiType.createArray(types.size()));
}
+ @Override
public GrDocMethodParameter[] getParameters() {
List<GrDocMethodParameter> result = new ArrayList<GrDocMethodParameter>();
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, GrDocMethodParameter.class)) result.add((GrDocMethodParameter)cur);
+ if (GrDocMethodParameter.class.isInstance(cur)) result.add((GrDocMethodParameter)cur);
}
return result.toArray(new GrDocMethodParameter[result.size()]);
}
+ @Override
@NotNull
public PsiElement getLeftParen() {
ASTNode paren = getNode().findChildByType(GroovyDocTokenTypes.mGDOC_TAG_VALUE_LPAREN);
@@ -91,6 +94,7 @@
return paren.getPsi();
}
+ @Override
@Nullable
public PsiElement getRightParen() {
ASTNode paren = getNode().findChildByType(GroovyDocTokenTypes.mGDOC_TAG_VALUE_RPAREN);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyElementType.java
index 923bbc7..d6dfc73 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyElementType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyElementType.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,11 +16,11 @@
package org.jetbrains.plugins.groovy.lang.lexer;
-import com.intellij.psi.tree.IElementType;
import com.intellij.lang.ASTNode;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
-import org.jetbrains.annotations.NotNull;
/**
* Main classdef for Groovy element types, such as lexems or AST nodes
@@ -29,15 +29,26 @@
*/
public class GroovyElementType extends IElementType {
- private String debugName = null;
+ private final String myDebugName;
+ private final boolean myLeftBound;
public GroovyElementType(String debugName) {
+ this(debugName, false);
+ }
+
+ public GroovyElementType(String debugName, boolean boundToLeft) {
super(debugName, GroovyFileType.GROOVY_LANGUAGE);
- this.debugName = debugName;
+ myDebugName = debugName;
+ myLeftBound = boundToLeft;
}
public String toString() {
- return debugName;
+ return myDebugName;
+ }
+
+ @Override
+ public boolean isLeftBound() {
+ return myLeftBound;
}
public static abstract class PsiCreator extends GroovyElementType {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyLexer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyLexer.java
index 7812039..726fbb2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyLexer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/GroovyLexer.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,9 +33,7 @@
mREGEX_CONTENT,
mDOLLAR_SLASH_REGEX_CONTENT,
WHITE_SPACE,
- mGSTRING_CONTENT,
- mDOLLAR_SLASH_REGEX_CONTENT,
- mREGEX_CONTENT
+ mGSTRING_CONTENT
);
public GroovyLexer() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java
index 72930dc..3fa6965 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/lexer/TokenSets.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.
@@ -100,6 +100,8 @@
public static final TokenSet REFERENCE_NAMES = TokenSet.orSet(KEYWORDS, PROPERTY_NAMES, NUMBERS);
public static final TokenSet REFERENCE_NAMES_WITHOUT_NUMBERS = TokenSet.orSet(KEYWORDS, PROPERTY_NAMES);
+ public static final TokenSet REFERENCE_NAME_PREFIXES = TokenSet.orSet(NUMBERS, KEYWORDS, TokenSet.create(mIDENT, mSTRING_LITERAL, mGSTRING_LITERAL, mGSTRING_BEGIN, mREGEX_BEGIN, mDOLLAR_SLASH_REGEX_BEGIN, mAT));
+
public static final TokenSet VISIBILITY_MODIFIERS = TokenSet.create(
kPRIVATE,
@@ -172,6 +174,9 @@
COMPOSITE_LSHIFT_SIGN, COMPOSITE_RSHIFT_SIGN, COMPOSITE_TRIPLE_SHIFT_SIGN,
mREGEX_FIND, mREGEX_MATCH, mRANGE_INCLUSIVE, mRANGE_EXCLUSIVE);
+ public static final TokenSet ASSOCIATIVE_BINARY_OP_SET = TokenSet.create(mBAND, mBOR, mBXOR, mEQUAL, mLOR, mPLUS, mSTAR, mNOT_EQUAL, mLAND);
+
+
public static final TokenSet BINARY_EXPRESSIONS = TokenSet.create(ADDITIVE_EXPRESSION, MULTIPLICATIVE_EXPRESSION, POWER_EXPRESSION,
POWER_EXPRESSION_SIMPLE, LOGICAL_OR_EXPRESSION, LOGICAL_AND_EXPRESSION,
INCLUSIVE_OR_EXPRESSION, EXCLUSIVE_OR_EXPRESSION, AND_EXPRESSION,
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java
index 7a58e0d..8d67050 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyAnnotationAttributeInfoHandler.java
@@ -154,7 +154,7 @@
}
@Override
- public void updateParameterInfo(@NotNull GrAnnotationArgumentList o, @NotNull UpdateParameterInfoContext context) {
+ public void updateParameterInfo(@NotNull GrAnnotationArgumentList parameterOwner, @NotNull UpdateParameterInfoContext context) {
context.setHighlightedParameter(findAnnotationMethod(context.getFile(), context.getEditor()));
}
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 0df8cf1..10e5c0b 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
@@ -62,6 +62,7 @@
public class GroovyParameterInfoHandler implements ParameterInfoHandlerWithTabActionSupport<GroovyPsiElement, Object, GroovyPsiElement> {
private static final Logger LOG = Logger.getInstance(GroovyParameterInfoHandler.class);
+ @Override
public boolean couldShowInLookup() {
return true;
}
@@ -75,6 +76,7 @@
}
+ @Override
public Object[] getParametersForLookup(LookupElement item, ParameterInfoContext context) {
List<? extends PsiElement> elements = JavaCompletionUtil.getAllPsiElements(item);
@@ -91,6 +93,7 @@
return null;
}
+ @Override
public Object[] getParametersForDocumentation(Object resolveResult, ParameterInfoContext context) {
if (resolveResult instanceof GroovyResolveResult) {
final PsiElement element = ((GroovyResolveResult)resolveResult).getElement();
@@ -102,11 +105,13 @@
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
- public GroovyPsiElement findElementForParameterInfo(CreateParameterInfoContext context) {
+ @Override
+ public GroovyPsiElement findElementForParameterInfo(@NotNull CreateParameterInfoContext context) {
return findAnchorElement(context.getEditor().getCaretModel().getOffset(), context.getFile());
}
- public GroovyPsiElement findElementForUpdatingParameterInfo(UpdateParameterInfoContext context) {
+ @Override
+ public GroovyPsiElement findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context) {
return findAnchorElement(context.getEditor().getCaretModel().getOffset(), context.getFile());
}
@@ -131,6 +136,7 @@
return null;
}
+ @Override
@SuppressWarnings("unchecked")
public void showParameterInfo(@NotNull GroovyPsiElement place, @NotNull CreateParameterInfoContext context) {
GroovyResolveResult[] variants = ResolveUtil.getCallVariants(place);
@@ -210,7 +216,8 @@
return resolveResult.isInvokedOnProperty() || resolveResult.getElement() instanceof PsiVariable;
}
- public void updateParameterInfo(@NotNull GroovyPsiElement place, UpdateParameterInfoContext context) {
+ @Override
+ public void updateParameterInfo(@NotNull GroovyPsiElement place, @NotNull UpdateParameterInfoContext context) {
final PsiElement parameterOwner = context.getParameterOwner();
if (parameterOwner != place) {
context.removeHint();
@@ -243,7 +250,7 @@
final PsiMethod method = (PsiMethod)namedElement;
PsiParameter[] parameters = method.getParameterList().getParameters();
parameters = updateConstructorParams(method, parameters, context.getParameterOwner());
- parameterTypes = new PsiType[parameters.length];
+ parameterTypes = PsiType.createArray(parameters.length);
for (int j = 0; j < parameters.length; j++) {
parameterTypes[j] = parameters[j].getType();
}
@@ -254,7 +261,7 @@
else if (objects[i] instanceof GrClosureSignature) {
final GrClosureSignature signature = (GrClosureSignature)objects[i];
argTypes = PsiUtil.getArgumentTypes(place, false);
- parameterTypes = new PsiType[signature.getParameterCount()];
+ parameterTypes = PsiType.createArray(signature.getParameterCount());
int j = 0;
for (GrClosureParameter parameter : signature.getParameters()) {
parameterTypes[j++] = parameter.getType();
@@ -310,15 +317,18 @@
return element != null && element.getNode().getElementType() == GroovyTokenTypes.mCOMMA;
}
+ @Override
public String getParameterCloseChars() {
return ",){}";
}
+ @Override
public boolean tracksParameterIndex() {
return true;
}
- public void updateUI(Object o, ParameterInfoUIContext context) {
+ @Override
+ public void updateUI(Object o, @NotNull ParameterInfoUIContext context) {
CodeInsightSettings settings = CodeInsightSettings.getInstance();
if (o == null) return;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java
index 63560d2..4924d01 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parameterInfo/GroovyTypeParameterInfoHandler.java
@@ -100,7 +100,7 @@
@Nullable
@Override
- public GrTypeArgumentList findElementForParameterInfo(CreateParameterInfoContext context) {
+ public GrTypeArgumentList findElementForParameterInfo(@NotNull CreateParameterInfoContext context) {
final GrTypeArgumentList parameterList = ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), GrTypeArgumentList.class);
if (parameterList != null) {
@@ -121,19 +121,19 @@
}
@Override
- public void showParameterInfo(@NotNull GrTypeArgumentList element, CreateParameterInfoContext context) {
+ public void showParameterInfo(@NotNull GrTypeArgumentList element, @NotNull CreateParameterInfoContext context) {
context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
}
@Nullable
@Override
- public GrTypeArgumentList findElementForUpdatingParameterInfo(UpdateParameterInfoContext context) {
+ public GrTypeArgumentList findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context) {
return ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), GrTypeArgumentList.class);
}
@Override
- public void updateParameterInfo(@NotNull GrTypeArgumentList o, UpdateParameterInfoContext context) {
- int index = ParameterInfoUtils.getCurrentParameterIndex(o.getNode(), context.getOffset(), getActualParameterDelimiterType());
+ public void updateParameterInfo(@NotNull GrTypeArgumentList parameterOwner, @NotNull UpdateParameterInfoContext context) {
+ int index = ParameterInfoUtils.getCurrentParameterIndex(parameterOwner.getNode(), context.getOffset(), getActualParameterDelimiterType());
context.setCurrentParameter(index);
final Object[] objectsToView = context.getObjectsToView();
context.setHighlightedParameter(index < objectsToView.length && index >= 0 ? (PsiElement)objectsToView[index] : null);
@@ -151,7 +151,7 @@
}
@Override
- public void updateUI(PsiTypeParameter p, ParameterInfoUIContext context) {
+ public void updateUI(PsiTypeParameter p, @NotNull ParameterInfoUIContext context) {
@NonNls StringBuilder buffer = new StringBuilder();
buffer.append(p.getName());
int highlightEndOffset = buffer.length();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java
index bc96a54..af5085f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/GroovyElementTypes.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,7 +37,6 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeParameterList;
-import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.GrVariableDeclarationImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrBlockImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.blocks.GrClosableBlockImpl;
@@ -257,7 +256,7 @@
GroovyElementType REFERENCE_ELEMENT = new GroovyElementType("reference element");
GroovyElementType ARRAY_DECLARATOR = new GroovyElementType("array declarator");
- GroovyElementType TYPE_ARGUMENTS = new GroovyElementType("type arguments");
+ GroovyElementType TYPE_ARGUMENTS = new GroovyElementType("type arguments", true);
GroovyElementType TYPE_ARGUMENT = new GroovyElementType("type argument");
EmptyStubElementType<GrTypeParameterList> TYPE_PARAMETER_LIST = new EmptyStubElementType<GrTypeParameterList>("type parameter list", GroovyFileType.GROOVY_LANGUAGE) {
@Override
@@ -302,35 +301,13 @@
GroovyElementType EXPLICIT_CONSTRUCTOR = new GroovyElementType("explicit constructor invokation");
//throws
- GroovyElementType THROW_CLAUSE = new GroovyElementType("throw clause");
+ GroovyElementType THROW_CLAUSE = new GroovyElementType("throw clause", true);
//annotation
GroovyElementType ANNOTATION_ARRAY_INITIALIZER = new GroovyElementType("annotation array initializer");
- GroovyElementType ANNOTATION_ARGUMENTS = new GroovyElementType("annotation arguments");
+ GroovyElementType ANNOTATION_ARGUMENTS = new GroovyElementType("annotation arguments", true);
GroovyElementType ANNOTATION_MEMBER_VALUE_PAIR = new GroovyElementType("annotation member value pair");
- GrStubElementType<GrAnnotationStub, GrAnnotation> ANNOTATION = new GrStubElementType<GrAnnotationStub, GrAnnotation>("annotation") {
-
- @Override
- public GrAnnotation createPsi(@NotNull GrAnnotationStub stub) {
- return new GrAnnotationImpl(stub);
- }
-
- @Override
- public GrAnnotationStub createStub(@NotNull GrAnnotation psi, StubElement parentStub) {
- return new GrAnnotationStub(parentStub, psi);
- }
-
- @Override
- public void serialize(@NotNull GrAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException {
- dataStream.writeName(stub.getAnnotationName());
- }
-
- @NotNull
- @Override
- public GrAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
- return new GrAnnotationStub(parentStub, dataStream.readName());
- }
- };
+ GrStubElementType<GrAnnotationStub, GrAnnotation> ANNOTATION = new GrAnnotationElementType("annotation");
//parameters
EmptyStubElementType<GrParameterList> PARAMETERS_LIST = new EmptyStubElementType<GrParameterList>("parameters list", GroovyFileType.GROOVY_LANGUAGE) {
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java
index e348966..13f99db 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/ThrowClause.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,16 +39,16 @@
ParserUtils.getToken(builder, mNLS);
- if (ReferenceElement.parseReferenceElement(builder) == FAIL) {
- throwClauseMarker.done(THROW_CLAUSE);
+ if (ReferenceElement.parse(builder, false, true, true, false, false) == FAIL) {
builder.error(GroovyBundle.message("identifier.expected"));
+ throwClauseMarker.done(THROW_CLAUSE);
return;
}
while (ParserUtils.getToken(builder, mCOMMA)) {
ParserUtils.getToken(builder, mNLS);
- if (ReferenceElement.parseReferenceElement(builder) == FAIL) {
+ if (ReferenceElement.parse(builder, false, true, true, false, false) == FAIL) {
break;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java
index 313fb60..c6b15d9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/annotations/Annotation.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.
@@ -48,7 +48,7 @@
return false;
}
- if (ReferenceElement.parseReferenceElement(builder) == FAIL) {
+ if (ReferenceElement.parse(builder, false, true, true, false, false) == FAIL) {
builder.error("Annotation name expected");
annMarker.drop();
return false;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java
index 8ffd2bb..2d4e4d4 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/auxiliary/parameters/ParameterDeclaration.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,6 +32,8 @@
import java.util.HashSet;
import java.util.Set;
+import static org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.ReferenceElement.ReferenceElementResult.*;
+
/**
* @author: Dmitry.Krasilschikov, ilyas
*/
@@ -47,7 +49,7 @@
final ReferenceElement.ReferenceElementResult result = TypeSpec.parseStrict(builder, true);
- if (result == ReferenceElement.ReferenceElementResult.FAIL && !hasModifiers) {
+ if (result == FAIL && !hasModifiers) {
rb.drop();
pdMarker.rollbackTo();
return false;
@@ -90,9 +92,10 @@
if (mIDENT.equals(builder.getTokenType()) || (mTRIPLE_DOT.equals(builder.getTokenType()))) {
rb.drop();
}
- else if (result == ReferenceElement.ReferenceElementResult.REF_WITH_TYPE_PARAMS) {
+ else if (result == REF_WITH_TYPE_PARAMS || result == PATH_REF) {
rb.drop();
- pdMarker.error(GroovyBundle.message("identifier.expected"));
+ pdMarker.drop();
+ builder.error(GroovyBundle.message("identifier.expected"));
return true;
}
else {
@@ -135,7 +138,7 @@
rb.drop();
rb = builder.mark();
final ReferenceElement.ReferenceElementResult result = TypeSpec.parseStrict(builder, false);
- if (result == ReferenceElement.ReferenceElementResult.FAIL && ParserUtils.lookAhead(builder, mBOR)) {
+ if (result == FAIL && ParserUtils.lookAhead(builder, mBOR)) {
builder.error(GroovyBundle.message("type.expected"));
}
else {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java
index b986090..ce73328 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/AssignmentExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -47,6 +47,9 @@
marker.done(ASSIGNMENT_EXPRESSION);
}
else {
+ if (isTuple) {
+ builder.error(GroovyBundle.message("assign.expected"));
+ }
marker.drop();
}
return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.java
index 65061b0..2a514c6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/arithmetic/PathExpression.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 @@
import com.intellij.lang.PsiBuilder;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyElementType;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
@@ -38,73 +39,65 @@
*/
public class PathExpression implements GroovyElementTypes {
- public static boolean parse(PsiBuilder builder, GroovyParser parser) {
+ public enum Result {INVOKED_EXPR, METHOD_CALL, WRONG_WAY, LITERAL}
+
+ private static final TokenSet DOTS = TokenSet.create(mSPREAD_DOT, mOPTIONAL_DOT, mMEMBER_POINTER, mDOT);
+ private static final TokenSet PATH_ELEMENT_START = TokenSet.create(mSPREAD_DOT, mOPTIONAL_DOT, mMEMBER_POINTER, mLBRACK, mLPAREN, mLCURLY, mDOT);
+
+ public static boolean parse(@NotNull PsiBuilder builder, @NotNull GroovyParser parser) {
return parsePathExprQualifierForExprStatement(builder, parser) != WRONG_WAY;
}
- public enum Result {INVOKED_EXPR, METHOD_CALL, WRONG_WAY, LITERAL}
-
/**
* parses method calls with parentheses, property index access, etc
*/
- public static Result parsePathExprQualifierForExprStatement(PsiBuilder builder, GroovyParser parser) {
+ @NotNull
+ public static Result parsePathExprQualifierForExprStatement(@NotNull PsiBuilder builder, @NotNull GroovyParser parser) {
PsiBuilder.Marker marker = builder.mark();
- final PsiBuilder.Marker marker1 = builder.mark();
IElementType qualifierType = PrimaryExpression.parsePrimaryExpression(builder, parser);
if (qualifierType != WRONGWAY) {
- Result result;
- if (isPathElementStart(builder)) {
- if ((builder.getTokenType() == mLPAREN || builder.getTokenType() == mLCURLY) && qualifierType == LITERAL) {
- marker1.rollbackTo();
- qualifierType = PrimaryExpression.parsePrimaryExpression(builder, parser, true);
- assert qualifierType != WRONGWAY;
- }
- else {
- marker1.drop();
- }
- PsiBuilder.Marker newMarker = marker.precede();
- marker.drop();
- if (checkForLCurly(builder)) {
- PsiBuilder.Marker argsMarker = builder.mark();
- argsMarker.done(ARGUMENTS);
- ParserUtils.getToken(builder, mNLS);
- result = pathElementParse(builder, newMarker, parser, METHOD_CALL);
- }
- else {
- result = pathElementParse(builder, newMarker, parser, INVOKED_EXPR);
- }
- }
- else {
- marker1.drop();
- marker.drop();
- if (qualifierType == LITERAL) return Result.LITERAL;
- return INVOKED_EXPR;
- }
- return result;
+ return parseAfterQualifier(builder, parser, marker, qualifierType);
}
else {
- marker1.drop();
marker.drop();
return WRONG_WAY;
}
}
- /**
- * Any path element parsing
- *
- * @param builder
- * @param marker
- * @return
- */
+ @NotNull
+ private static Result parseAfterQualifier(@NotNull PsiBuilder builder,
+ @NotNull GroovyParser parser,
+ @NotNull PsiBuilder.Marker marker,
+ @NotNull IElementType qualifierType) {
+ if (isPathElementStart(builder)) {
+ if (isLParenthOrLCurlyAfterLiteral(builder, qualifierType)) {
+ marker.rollbackTo();
+ PsiBuilder.Marker newMarker = builder.mark();
+ IElementType newQualifierType = PrimaryExpression.parsePrimaryExpression(builder, parser, true);
+ assert newQualifierType != WRONGWAY;
+ return parseAfterReference(builder, parser, newMarker);
+ }
+ else {
+ return parseAfterReference(builder, parser, marker);
+ }
+ }
+ else {
+ marker.drop();
+ if (qualifierType == LITERAL) return Result.LITERAL;
+ return INVOKED_EXPR;
+ }
+ }
- private static final TokenSet DOTS = TokenSet.create(mSPREAD_DOT, mOPTIONAL_DOT, mMEMBER_POINTER, mDOT);
+ private static boolean isLParenthOrLCurlyAfterLiteral(@NotNull PsiBuilder builder, @NotNull IElementType qualifierType) {
+ return qualifierType == LITERAL && (checkForLParenth(builder) || checkForLCurly(builder));
+ }
- private static Result pathElementParse(PsiBuilder builder,
- PsiBuilder.Marker marker,
- GroovyParser parser,
- Result result) {
+ @NotNull
+ private static Result pathElementParse(@NotNull PsiBuilder builder,
+ @NotNull PsiBuilder.Marker marker,
+ @NotNull GroovyParser parser,
+ @NotNull Result result) {
- GroovyElementType res;
// Property reference
if (DOTS.contains(builder.getTokenType()) || ParserUtils.lookAhead(builder, mNLS, mDOT)) {
@@ -114,76 +107,75 @@
ParserUtils.getToken(builder, DOTS);
ParserUtils.getToken(builder, mNLS);
TypeArguments.parseTypeArguments(builder, true);
- res = namePartParse(builder, parser);
- if (!res.equals(WRONGWAY)) {
+ GroovyElementType res = namePartParse(builder, parser);
+ if (res != WRONGWAY) {
PsiBuilder.Marker newMarker = marker.precede();
marker.done(res);
- if (checkForLCurly(builder)) {
- PsiBuilder.Marker argsMarker = builder.mark();
- argsMarker.done(ARGUMENTS);
- ParserUtils.getToken(builder, mNLS);
- result = pathElementParse(builder, newMarker, parser, METHOD_CALL);
- }
- else {
- result = pathElementParse(builder, newMarker, parser, INVOKED_EXPR);
- }
+ return parseAfterReference(builder, parser, newMarker);
}
else {
builder.error(GroovyBundle.message("path.selector.expected"));
marker.drop();
+ return result;
}
}
- else if (mLPAREN.equals(builder.getTokenType())) {
+ else if (checkForLParenth(builder)) {
PrimaryExpression.methodCallArgsParse(builder, parser);
- if (checkForLCurly(builder)) {
- ParserUtils.getToken(builder, mNLS);
- result = pathElementParse(builder, marker, parser, METHOD_CALL);
- }
- else {
- PsiBuilder.Marker newMarker = marker.precede();
- marker.done(PATH_METHOD_CALL);
- result = pathElementParse(builder, newMarker, parser, METHOD_CALL);
- }
+ return parseAfterArguments(builder, marker, parser);
}
else if (checkForLCurly(builder)) {
ParserUtils.getToken(builder, mNLS);
appendedBlockParse(builder, parser);
- if (checkForLCurly(builder)) {
- ParserUtils.getToken(builder, mNLS);
- result = pathElementParse(builder, marker, parser, METHOD_CALL);
- }
- else {
- PsiBuilder.Marker newMarker = marker.precede();
- marker.done(PATH_METHOD_CALL);
- result = pathElementParse(builder, newMarker, parser, METHOD_CALL);
- }
+ return parseAfterArguments(builder, marker, parser);
}
else if (checkForArrayAccess(builder)) {
indexPropertyArgsParse(builder, parser);
PsiBuilder.Marker newMarker = marker.precede();
marker.done(PATH_INDEX_PROPERTY);
- if (checkForLCurly(builder)) {
- PsiBuilder.Marker argsMarker = builder.mark();
- argsMarker.done(ARGUMENTS);
- ParserUtils.getToken(builder, mNLS);
- result = pathElementParse(builder, newMarker, parser, METHOD_CALL);
- }
- else {
- result = pathElementParse(builder, newMarker, parser, INVOKED_EXPR);
- }
+ return parseAfterReference(builder, parser, newMarker);
}
else {
marker.drop();
+ return result;
}
- return result;
}
- private static boolean checkForLCurly(PsiBuilder builder) {
+ @NotNull
+ private static Result parseAfterReference(@NotNull PsiBuilder builder, @NotNull GroovyParser parser, @NotNull PsiBuilder.Marker newMarker) {
+ if (checkForLCurly(builder)) {
+ PsiBuilder.Marker argsMarker = builder.mark();
+ argsMarker.done(ARGUMENTS);
+ ParserUtils.getToken(builder, mNLS);
+ return pathElementParse(builder, newMarker, parser, METHOD_CALL);
+ }
+ else {
+ return pathElementParse(builder, newMarker, parser, INVOKED_EXPR);
+ }
+ }
+
+ @NotNull
+ private static Result parseAfterArguments(@NotNull PsiBuilder builder, @NotNull PsiBuilder.Marker marker, @NotNull GroovyParser parser) {
+ if (checkForLCurly(builder)) {
+ ParserUtils.getToken(builder, mNLS);
+ return pathElementParse(builder, marker, parser, METHOD_CALL);
+ }
+ else {
+ PsiBuilder.Marker newMarker = marker.precede();
+ marker.done(PATH_METHOD_CALL);
+ return pathElementParse(builder, newMarker, parser, METHOD_CALL);
+ }
+ }
+
+ private static boolean checkForLCurly(@NotNull PsiBuilder builder) {
return ParserUtils.lookAhead(builder, mLCURLY) || ParserUtils.lookAhead(builder, mNLS, mLCURLY);
}
- public static boolean checkForArrayAccess(PsiBuilder builder) {
- return mLBRACK.equals(builder.getTokenType()) &&
+ private static boolean checkForLParenth(@NotNull PsiBuilder builder) {
+ return builder.getTokenType() == mLPAREN;
+ }
+
+ public static boolean checkForArrayAccess(@NotNull PsiBuilder builder) {
+ return builder.getTokenType() == mLBRACK &&
!ParserUtils.lookAhead(builder, mLBRACK, mCOLON) &&
!ParserUtils.lookAhead(builder, mLBRACK, mNLS, mCOLON);
}
@@ -194,7 +186,8 @@
* @param builder
* @return
*/
- public static GroovyElementType namePartParse(PsiBuilder builder, GroovyParser parser) {
+ @NotNull
+ public static GroovyElementType namePartParse(@NotNull PsiBuilder builder, @NotNull GroovyParser parser) {
ParserUtils.getToken(builder, mAT);
if (ParserUtils.getToken(builder, mIDENT) ||
ParserUtils.getToken(builder, mSTRING_LITERAL) ||
@@ -203,29 +196,29 @@
}
final IElementType tokenType = builder.getTokenType();
- if (mGSTRING_BEGIN.equals(tokenType)) {
+ if (tokenType == mGSTRING_BEGIN) {
final boolean result = CompoundStringExpression.parse(builder, parser, true, mGSTRING_BEGIN, mGSTRING_CONTENT, mGSTRING_END, null,
GSTRING, GroovyBundle.message("string.end.expected"));
return result ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
- if (mREGEX_BEGIN.equals(tokenType)) {
+ if (tokenType == mREGEX_BEGIN) {
final boolean result = CompoundStringExpression.parse(builder, parser, true,
mREGEX_BEGIN, mREGEX_CONTENT, mREGEX_END, mREGEX_LITERAL,
REGEX, GroovyBundle.message("regex.end.expected"));
return result ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
- if (mDOLLAR_SLASH_REGEX_BEGIN.equals(tokenType)) {
+ if (tokenType == mDOLLAR_SLASH_REGEX_BEGIN) {
final boolean result = CompoundStringExpression.parse(builder, parser, true,
mDOLLAR_SLASH_REGEX_BEGIN, mDOLLAR_SLASH_REGEX_CONTENT, mDOLLAR_SLASH_REGEX_END,
mDOLLAR_SLASH_REGEX_LITERAL,
REGEX, GroovyBundle.message("dollar.slash.end.expected"));
return result ? PATH_PROPERTY_REFERENCE : REFERENCE_EXPRESSION;
}
- if (mLCURLY.equals(tokenType)) {
+ if (tokenType == mLCURLY) {
OpenOrClosableBlock.parseOpenBlock(builder, parser);
return PATH_PROPERTY_REFERENCE;
}
- if (mLPAREN.equals(tokenType)) {
+ if (tokenType == mLPAREN) {
PrimaryExpression.parenthesizedExprParse(builder, parser);
return PATH_PROPERTY_REFERENCE;
}
@@ -242,8 +235,9 @@
* @param builder
* @return
*/
- public static GroovyElementType indexPropertyArgsParse(PsiBuilder builder, GroovyParser parser) {
- assert mLBRACK.equals(builder.getTokenType());
+ @NotNull
+ public static GroovyElementType indexPropertyArgsParse(@NotNull PsiBuilder builder, @NotNull GroovyParser parser) {
+ assert builder.getTokenType() == mLBRACK;
PsiBuilder.Marker marker = builder.mark();
ParserUtils.getToken(builder, mLBRACK);
@@ -261,7 +255,8 @@
* @param builder
* @return
*/
- private static IElementType appendedBlockParse(PsiBuilder builder, GroovyParser parser) {
+ @NotNull
+ private static IElementType appendedBlockParse(@NotNull PsiBuilder builder, @NotNull GroovyParser parser) {
return OpenOrClosableBlock.parseClosableBlock(builder, parser);
}
@@ -272,17 +267,10 @@
* @param builder
* @return
*/
- private static boolean isPathElementStart(PsiBuilder builder) {
+ private static boolean isPathElementStart(@NotNull PsiBuilder builder) {
return (PATH_ELEMENT_START.contains(builder.getTokenType()) ||
ParserUtils.lookAhead(builder, mNLS, mDOT) ||
ParserUtils.lookAhead(builder, mNLS, mLCURLY));
}
- /**
- * FIRST(1) of PathElement
- */
- private static final TokenSet PATH_ELEMENT_START =
- TokenSet.create(mSPREAD_DOT, mOPTIONAL_DOT, mMEMBER_POINTER, mLBRACK, mLPAREN, mLCURLY, mDOT);
-
-
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.java
index f785fe6..e2fc55c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/expressions/primary/PrimaryExpression.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.
@@ -118,9 +118,10 @@
}
PsiBuilder.Marker anonymousMarker = builder.mark();
- String name = null;
+ String name;
if (TokenSets.BUILT_IN_TYPES.contains(builder.getTokenType())) {
ParserUtils.eatElement(builder, BUILT_IN_TYPE);
+ name = null;
}
else if (TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS.contains(builder.getTokenType())) {
name = builder.getTokenText();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java
index 62381a5..6bb48b3b9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/imports/ImportReference.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.
@@ -36,7 +36,9 @@
return false;
}
- ReferenceElement.parseForImport(builder);
+ if (ReferenceElement.parseForImport(builder) == ReferenceElement.ReferenceElementResult.FAIL) {
+ return false;
+ }
if (ParserUtils.getToken(builder, mDOT)) {
ParserUtils.getToken(builder, mNLS);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java
index 79763df..3d13f1e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/statements/typeDefinitions/ReferenceElement.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,6 +21,7 @@
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.parsing.types.TypeArguments;
@@ -98,10 +99,9 @@
}
public static ReferenceElementResult parseForPackage(@NotNull PsiBuilder builder) {
- return parse(builder, false, false, false, false, false);
+ return parse(builder, false, false, true, false, false);
}
-
//it doesn't important first letter of identifier of ThrowClause, of Annotation, of new Expression, of implements, extends, superclass clauses
public static ReferenceElementResult parseReferenceElement(@NotNull PsiBuilder builder) {
return parseReferenceElement(builder, false, true);
@@ -114,7 +114,7 @@
public static ReferenceElementResult parse(@NotNull PsiBuilder builder,
boolean checkUpperCase,
boolean parseTypeArgs,
- boolean forImport,
+ boolean lineFeedAllowed,
boolean allowDiamond,
boolean expressionPossible) {
PsiBuilder.Marker internalTypeMarker = builder.mark();
@@ -127,8 +127,8 @@
}
boolean hasTypeArguments = false;
- if (parseTypeArgs) {
- hasTypeArguments = TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond);
+ if (parseTypeArgs && TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond)) {
+ hasTypeArguments = true;
}
internalTypeMarker.done(REFERENCE_ELEMENT);
@@ -138,26 +138,31 @@
while (builder.getTokenType() == mDOT) {
- if ((ParserUtils.lookAhead(builder, mDOT, mSTAR) || ParserUtils.lookAhead(builder, mDOT, mNLS, mSTAR)) && forImport) {
+ if ((ParserUtils.lookAhead(builder, mDOT, mSTAR) || ParserUtils.lookAhead(builder, mDOT, mNLS, mSTAR)) && lineFeedAllowed) {
internalTypeMarker.drop();
return PATH_REF;
}
ParserUtils.getToken(builder, mDOT);
- if (forImport) {
+ if (lineFeedAllowed) {
ParserUtils.getToken(builder, mNLS);
}
lastIdentifier = builder.getTokenText();
if (!ParserUtils.getToken(builder, TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS)) {
- internalTypeMarker.rollbackTo();
- return FAIL;
+ if (TokenSets.REFERENCE_NAME_PREFIXES.contains(builder.getTokenType())) {
+ internalTypeMarker.rollbackTo();
+ return FAIL;
+ }
+ builder.error(GroovyBundle.message("identifier.expected"));
+ internalTypeMarker.done(REFERENCE_ELEMENT);
+ return PATH_REF;
}
- if (parseTypeArgs) {
- hasTypeArguments = TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond) || hasTypeArguments;
+ if (parseTypeArgs && TypeArguments.parseTypeArguments(builder, expressionPossible, allowDiamond)) {
+ hasTypeArguments = true;
}
internalTypeMarker.done(REFERENCE_ELEMENT);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java
index f0e5a4a..fa432a8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/parser/parsing/toplevel/packaging/PackageDefinition.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,13 +19,13 @@
import com.intellij.lang.PsiBuilder;
import com.intellij.lang.PsiBuilder.Marker;
import org.jetbrains.plugins.groovy.GroovyBundle;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyParser;
import org.jetbrains.plugins.groovy.lang.parser.parsing.auxiliary.modifiers.Modifiers;
import org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.ReferenceElement;
import org.jetbrains.plugins.groovy.lang.parser.parsing.util.ParserUtils;
+import static org.jetbrains.plugins.groovy.lang.parser.parsing.statements.typeDefinitions.ReferenceElement.ReferenceElementResult.FAIL;
/**
* @author ilyas
@@ -42,8 +42,7 @@
return false;
}
- if (!TokenSets.CODE_REFERENCE_ELEMENT_NAME_TOKENS.contains(builder.getTokenType()) ||
- ReferenceElement.parseForPackage(builder) == ReferenceElement.ReferenceElementResult.FAIL) {
+ if (ReferenceElement.parseForPackage(builder) == FAIL) {
builder.error(GroovyBundle.message("identifier.expected"));
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java
index 06b53a4..c548b56 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/GroovyElementVisitor.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.
@@ -27,6 +27,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
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.arguments.GrSpreadArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.*;
@@ -462,4 +463,8 @@
public void visitTupleExpression(GrTupleExpression tupleExpression) {
visitExpression(tupleExpression);
}
+
+ public void visitSpreadArgument(GrSpreadArgument spreadArgument) {
+ visitExpression(spreadArgument);
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/GroovyResolveResult.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/GroovyResolveResult.java
index d725cb6..e3ce5dd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/GroovyResolveResult.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/GroovyResolveResult.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -31,6 +31,8 @@
boolean isStaticsOK();
+ boolean isApplicable();
+
@Nullable
PsiElement getCurrentFileResolveContext();
@@ -55,6 +57,11 @@
return true;
}
+ @Override
+ public boolean isApplicable() {
+ return false;
+ }
+
@NotNull
public PsiSubstitutor getSubstitutor() {
return PsiSubstitutor.EMPTY;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrConstructorInvocation.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrConstructorInvocation.java
index 922f5bb..e212db7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrConstructorInvocation.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrConstructorInvocation.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.
@@ -31,6 +31,7 @@
boolean isThisCall();
+ @NotNull
GrReferenceExpression getInvokedExpression();
@Nullable
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrWhileStatement.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrWhileStatement.java
index 527c7d2..824b039 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrWhileStatement.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/GrWhileStatement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,6 +20,7 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition;
import org.jetbrains.plugins.groovy.lang.psi.api.formatter.GrControlStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
/**
* @autor: Dmitry.Krasilschikov
@@ -28,7 +29,7 @@
public interface GrWhileStatement extends GrStatement, GrControlStatement, GrLoopStatement {
@Nullable
- GrCondition getCondition();
+ GrExpression getCondition();
@Nullable
GrStatement getBody();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrAssignmentExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrAssignmentExpression.java
index b76ede2..9e90485 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrAssignmentExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrAssignmentExpression.java
@@ -34,10 +34,12 @@
@Nullable
GrExpression getRValue();
+ @NotNull
IElementType getOperationTokenType();
@NotNull
GroovyResolveResult[] multiResolve(boolean incompleteCode);
+ @NotNull
PsiElement getOperationToken();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrMethodCall.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrMethodCall.java
index 1e718ac..1d558bc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrMethodCall.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrMethodCall.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,15 +16,20 @@
package org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions;
import com.intellij.navigation.NavigationItem;
-import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
/**
* @author peter
*/
public interface GrMethodCall extends GrCallExpression, NavigationItem {
- @Nullable
+ @NotNull
GrExpression getInvokedExpression();
+ @Override
+ @NotNull
+ GrArgumentList getArgumentList();
+
boolean isCommandExpression();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java
index 03900c9..ab33b08 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/api/statements/expressions/GrUnaryExpression.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -27,10 +27,14 @@
* @author ilyas
*/
public interface GrUnaryExpression extends GrExpression, PsiPolyVariantReference {
+ @NotNull
IElementType getOperationTokenType();
+
+ @NotNull
PsiElement getOperationToken();
- @Nullable GrExpression getOperand();
+ @Nullable
+ GrExpression getOperand();
@NotNull
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java
index cd6e3fc..2934d09 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/ControlFlowBuilder.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.
@@ -60,9 +60,10 @@
*/
public class ControlFlowBuilder extends GroovyRecursiveElementVisitor {
private static final Logger LOG = Logger.getInstance(ControlFlowBuilder.class);
- private List<InstructionImpl> myInstructions;
- private Deque<InstructionImpl> myProcessingStack;
+ private final List<InstructionImpl> myInstructions = new ArrayList<InstructionImpl>();
+
+ private final Deque<InstructionImpl> myProcessingStack = new ArrayDeque<InstructionImpl>();
private final PsiConstantEvaluationHelper myConstantEvaluator;
private GroovyPsiElement myScope;
@@ -70,12 +71,12 @@
/**
* stack of current catch blocks
*/
- private Deque<ExceptionInfo> myCaughtExceptionInfos;
+ private final Deque<ExceptionInfo> myCaughtExceptionInfos = new ArrayDeque<ExceptionInfo>();
/**
* stack of current conditions
*/
- private Deque<ConditionInstruction> myConditions;
+ private final Deque<ConditionInstruction> myConditions = new ArrayDeque<ConditionInstruction>();
/**
@@ -91,7 +92,7 @@
/**
* list of pending nodes and corresponding scopes sorted by scopes from the biggest to smallest.
*/
- private List<Pair<InstructionImpl, GroovyPsiElement>> myPending;
+ private List<Pair<InstructionImpl, GroovyPsiElement>> myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
private int myInstructionNumber;
private final GrControlFlowPolicy myPolicy;
@@ -135,20 +136,16 @@
}
- private void handlePossibleReturn(@NotNull GrStatement possibleReturn) {
+ @Nullable
+ private InstructionImpl handlePossibleReturn(@NotNull GrStatement possibleReturn) {
if (possibleReturn instanceof GrExpression && ControlFlowBuilderUtil.isCertainlyReturnStatement(possibleReturn)) {
- addNodeAndCheckPending(new MaybeReturnInstruction((GrExpression)possibleReturn));
+ return addNodeAndCheckPending(new MaybeReturnInstruction((GrExpression)possibleReturn));
}
+ return null;
}
public Instruction[] buildControlFlow(GroovyPsiElement scope) {
- myInstructions = new ArrayList<InstructionImpl>();
- myProcessingStack = new ArrayDeque<InstructionImpl>();
- myCaughtExceptionInfos = new ArrayDeque<ExceptionInfo>();
- myConditions = new ArrayDeque<ConditionInstruction>();
-
myFinallyCount = 0;
- myPending = new ArrayList<Pair<InstructionImpl, GroovyPsiElement>>();
myInstructionNumber = 0;
myScope = scope;
@@ -411,8 +408,8 @@
GrExpression rValue = expression.getRValue();
if (rValue != null) {
rValue.accept(this);
- lValue.accept(this);
}
+ lValue.accept(this);
}
@Override
@@ -617,12 +614,12 @@
addNode(new InstanceOfInstruction(expression, cond));
NegatingGotoInstruction negation = new NegatingGotoInstruction(expression, cond);
addNode(negation);
- handlePossibleReturn(expression);
- addPendingEdge(expression, negation);
+ InstructionImpl possibleReturn = handlePossibleReturn(expression);
+ addPendingEdge(expression, possibleReturn != null ? possibleReturn : negation);
myHead = cond;
addNode(new InstanceOfInstruction(expression, cond));
- handlePossibleReturn(expression);
+ //handlePossibleReturn(expression);
myConditions.removeFirstOccurrence(cond);
}
@@ -1123,7 +1120,9 @@
private void finishNode(InstructionImpl instruction) {
final InstructionImpl popped = myProcessingStack.pop();
if (!instruction.equals(popped)) {
- String description = "popped: " + popped.toString() + " : " + popped.hashCode() + " , expected: " + instruction.toString() + " : " + instruction.hashCode();
+ String description = "popped: " + popped.toString() + " : " + popped.hashCode() +
+ " , expected: " + instruction.toString() + " : " + instruction.hashCode() +
+ "same objects:" + (popped == instruction);
error(description);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/MaybeReturnInstruction.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/MaybeReturnInstruction.java
index 7720041..bfb4a82 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/MaybeReturnInstruction.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/controlFlow/impl/MaybeReturnInstruction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,8 @@
import com.intellij.psi.PsiType;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
/**
* @author peter
@@ -35,7 +37,7 @@
GrExpression expression = (GrExpression) getElement();
assert expression != null;
final PsiType type = expression.getType();
- return type != PsiType.VOID;
+ return type != PsiType.VOID && !PsiUtil.isVoidMethodCall(expression);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAType.java
index fe97437..6f512c3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/DFAType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -132,7 +132,7 @@
@Nullable
public PsiType getResultType() {
- if (mixins.size() == 0) return primary;
+ if (mixins.isEmpty()) return primary;
List<PsiType> types = new ArrayList<PsiType>();
if (primary != null) {
@@ -143,8 +143,8 @@
types.add(mixin.myType);
}
}
- if (types.size() == 0) return null;
- return PsiIntersectionType.createIntersection(types.toArray(new PsiType[types.size()]));
+ if (types.isEmpty()) return null;
+ return PsiIntersectionType.createIntersection(types.toArray(PsiType.createArray(types.size())));
}
public static DFAType create(@Nullable PsiType type) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java
index b4d8d61..a113fd8 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/dataFlow/types/TypeInferenceHelper.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.
@@ -31,8 +31,10 @@
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.InstanceOfInstruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.MixinTypeInstruction;
@@ -224,7 +226,7 @@
@Nullable
public static PsiType getInitializerType(final PsiElement element) {
if (element instanceof GrReferenceExpression && ((GrReferenceExpression) element).getQualifierExpression() == null) {
- return getInitializerFor(element);
+ return getInitializerTypeFor(element);
}
if (element instanceof GrVariable) {
@@ -235,9 +237,13 @@
}
@Nullable
- public static PsiType getInitializerFor(PsiElement element) {
+ public static PsiType getInitializerTypeFor(PsiElement element) {
final PsiElement parent = element.getParent();
if (parent instanceof GrAssignmentExpression) {
+ if (element instanceof GrIndexProperty) {
+ final GrExpression rvalue = ((GrAssignmentExpression)parent).getRValue();
+ return rvalue != null ? rvalue.getType() : null; //don't try to infer assignment type in case of index property because of infinite recursion (example: a[2]+=4)
+ }
return ((GrAssignmentExpression)parent).getType();
}
@@ -265,6 +271,25 @@
return null;
}
+ @Nullable
+ public static GrExpression getInitializerFor(GrExpression lValue) {
+ final PsiElement parent = lValue.getParent();
+ if (parent instanceof GrAssignmentExpression) return ((GrAssignmentExpression)parent).getRValue();
+ if (parent instanceof GrTupleExpression) {
+ final int i = ((GrTupleExpression)parent).indexOf(lValue);
+ final PsiElement pparent = parent.getParent();
+ org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.LOG.assertTrue(pparent instanceof GrAssignmentExpression);
+
+ final GrExpression rValue = ((GrAssignmentExpression)pparent).getRValue();
+ if (rValue instanceof GrListOrMap && !((GrListOrMap)rValue).isMap()) {
+ final GrExpression[] initializers = ((GrListOrMap)rValue).getInitializers();
+ if (initializers.length < i) return initializers[i];
+ }
+ }
+
+ return null;
+ }
+
static class TypeDfaInstance implements DfaInstance<TypeDfaState> {
private final GrControlFlowOwner myScope;
private final Instruction[] myFlow;
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 152ceb5..09ce7cc 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
@@ -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,12 +15,14 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.expectedTypes;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
+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.codeInspection.utils.ControlFlowUtils;
@@ -66,8 +68,6 @@
*/
public class GroovyExpectedTypesProvider {
- private static final Logger LOG = Logger.getInstance(GroovyExpectedTypesProvider.class);
-
public static TypeConstraint[] calculateTypeConstraints(@NotNull final GrExpression expression) {
return TypeInferenceHelper.getCurrentContext().getCachedValue(expression, new Computable<TypeConstraint[]>() {
@Override
@@ -82,7 +82,7 @@
}
final TypeConstraint[] result = calculator.getResult();
- List<TypeConstraint> custom = new ArrayList<TypeConstraint>();
+ List<TypeConstraint> custom = ContainerUtil.newArrayList();
for (GroovyExpectedTypesContributor contributor : GroovyExpectedTypesContributor.EP_NAME.getExtensions()) {
custom.addAll(contributor.calculateTypeConstraints(expression));
}
@@ -140,19 +140,15 @@
if (pparent instanceof GrCall && resolvesToDefaultConstructor(((GrCall)pparent))) {
final GroovyResolveResult resolveResult = label.advancedResolve();
PsiElement resolved = resolveResult.getElement();
- PsiType type;
- if (resolved instanceof PsiField) {
- type = ((PsiField)resolved).getType();
- }
- else if (resolved instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertySetter((PsiMethod)resolved)) {
- type = ((PsiMethod)resolved).getParameterList().getParameters()[0].getType();
- }
- else {
- type = null;
- }
- type = resolveResult.getSubstitutor().substitute(type);
- if (type != null) {
- myResult = createSimpleSubTypeResult(type);
+ PsiType type = resolved instanceof PsiField ?
+ ((PsiField)resolved).getType() :
+ resolved instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertySetter((PsiMethod)resolved) ?
+ ((PsiMethod)resolved).getParameterList().getParameters()[0].getType()
+ : null;
+
+ PsiType substituted = resolveResult.getSubstitutor().substitute(type);
+ if (substituted != null) {
+ myResult = createSimpleSubTypeResult(substituted);
}
}
}
@@ -178,27 +174,12 @@
}
final GrClosableBlock[] closureArgs = methodCall.getClosureArguments();
- //noinspection SuspiciousMethodCalls
- final int closureIndex = Arrays.asList(closureArgs).indexOf(myExpression);
- if (closureIndex >= 0) {
- List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
- for (GroovyResolveResult variant : ResolveUtil.getCallVariants(myExpression)) {
- 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();
- try {
- final Map<GrExpression, Pair<PsiParameter, PsiType>> map =
- GrClosureSignatureUtil.mapArgumentsToParameters(variant, methodCall, true, false, namedArgs, expressionArgs, closureArgs);
- addConstraintsFromMap(constraints, map);
- }
- catch (RuntimeException e) {
- LOG.error("call: " + methodCall.getText() + "\nsymbol: " + variant.getElement().getText(), e);
- }
- }
- if (!constraints.isEmpty()) {
- myResult = constraints.toArray(new TypeConstraint[constraints.size()]);
- }
-
+ 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 GroovyResolveResult[] callVariants = ResolveUtil.getCallVariants(myExpression);
+ processCallVariants(methodCall, callVariants, namedArgs, expressionArgs, closureArgs);
}
}
@@ -240,14 +221,7 @@
final String name = nameValuePair.getName();
if (name == null) return;
- final PsiMethod[] attrs = annot.findMethodsByName(name, false);
- if (attrs.length > 0) {
- PsiType type = attrs[0].getReturnType();
- while (type instanceof PsiArrayType) type = ((PsiArrayType)type).getComponentType();
- if (type != null && isAcceptableAnnotationValueType(type)) {
- myResult = createSimpleSubTypeResult(type);
- }
- }
+ createResultFromAttrName(annot, name);
}
else {
final GrAnnotationMethod method = PsiTreeUtil.getParentOfType(arrayInitializer, GrAnnotationMethod.class);
@@ -279,30 +253,21 @@
if (annot != null) {
final String name = nameValuePair.getName();
if (name != null) {
- final PsiMethod[] attrs = annot.findMethodsByName(name, false);
- if (attrs.length > 0) {
- PsiType type = attrs[0].getReturnType();
- while (type instanceof PsiArrayType) type = ((PsiArrayType)type).getComponentType();
- if (type != null && isAcceptableAnnotationValueType(type)) {
- myResult = createSimpleSubTypeResult(type);
- }
- }
+ createResultFromAttrName(annot, name);
}
else {
final PsiMethod[] valueAttr = annot.findMethodsByName("value", false);
- boolean canHaveSimpleExpr = valueAttr.length > 0;
- final PsiMethod[] methods = annot.getMethods();
- for (PsiMethod method : methods) {
- if (!("value".equals(method.getName()) || method instanceof PsiAnnotationMethod && ((PsiAnnotationMethod)method).getDefaultValue() != null)) {
- canHaveSimpleExpr = false;
- }
- }
+ if (valueAttr.length > 0) {
+ boolean canHaveSimpleExpr = ContainerUtil.find(annot.getMethods(), new Condition<PsiMethod>() {
+ @Override
+ public boolean value(PsiMethod method) {
+ return !("value".equals(method.getName()) || method instanceof PsiAnnotationMethod && ((PsiAnnotationMethod)method).getDefaultValue() != null);
+ }
+ }) == null;
- if (canHaveSimpleExpr) {
- PsiType type = valueAttr[0].getReturnType();
- while (type instanceof PsiArrayType) type = ((PsiArrayType)type).getComponentType();
- if (type != null && isAcceptableAnnotationValueType(type)) {
- myResult = createSimpleSubTypeResult(type);
+
+ if (canHaveSimpleExpr) {
+ createResultFromAnnotationAttribute(valueAttr[0]);
}
}
}
@@ -310,6 +275,21 @@
}
}
+ private void createResultFromAttrName(PsiClass annotation, String attrName) {
+ final PsiMethod[] attrs = annotation.findMethodsByName(attrName, false);
+ if (attrs.length > 0) {
+ createResultFromAnnotationAttribute(attrs[0]);
+ }
+ }
+
+ private void createResultFromAnnotationAttribute(PsiMethod attr) {
+ PsiType type = attr.getReturnType();
+ while (type instanceof PsiArrayType) type = ((PsiArrayType)type).getComponentType();
+ if (type != null && isAcceptableAnnotationValueType(type)) {
+ myResult = createSimpleSubTypeResult(type);
+ }
+ }
+
private static boolean isAcceptableAnnotationValueType(PsiType type) {
//noinspection ConstantConditions
return type instanceof PsiPrimitiveType ||
@@ -356,10 +336,18 @@
}
public void visitArgumentList(GrArgumentList list) {
- List<TypeConstraint> constraints = new ArrayList<TypeConstraint>();
- for (GroovyResolveResult variant : ResolveUtil.getCallVariants(list)) {
+ processCallVariants(list, ResolveUtil.getCallVariants(list), list.getNamedArguments(), list.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY);
+ }
+
+ private void processCallVariants(@NotNull PsiElement place,
+ @NotNull GroovyResolveResult[] variants,
+ @NotNull GrNamedArgument[] namedArguments,
+ @NotNull GrExpression[] expressionArguments,
+ @NotNull GrClosableBlock[] closureArguments) {
+ List<TypeConstraint> constraints = ContainerUtil.newArrayList();
+ for (GroovyResolveResult variant : variants) {
final Map<GrExpression, Pair<PsiParameter, PsiType>> map = GrClosureSignatureUtil.mapArgumentsToParameters(
- variant, list, true, true, list.getNamedArguments(), list.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY
+ variant, place, true, true, namedArguments, expressionArguments, closureArguments
);
addConstraintsFromMap(constraints, map);
}
@@ -374,25 +362,28 @@
final GrExpression left = expression.getLeftOperand();
final GrExpression right = expression.getRightOperand();
-
- if (type == mREGEX_FIND || type == mREGEX_MATCH) {
- final PsiClassType string = TypesUtil.createType(CommonClassNames.JAVA_LANG_STRING, expression);
- myResult = createSimpleSubTypeResult(string);
- return;
- }
-
final GrExpression other = myExpression == left ? right : left;
final PsiType otherType = other != null ? other.getType() : null;
if (otherType == null) return;
- if (type== mPLUS && otherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
- final PsiClassType obj = TypesUtil.getJavaLangObject(expression);
- myResult = createSimpleSubTypeResult(obj);
- return;
+ final GroovyResolveResult[] callVariants = expression.multiResolve(true);
+ if (myExpression == left || callVariants.length == 0) {
+ if (type == mPLUS && otherType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
+ final PsiClassType obj = TypesUtil.getJavaLangObject(expression);
+ myResult = createSimpleSubTypeResult(obj);
+ }
+ else if (type == mREGEX_FIND || type == mREGEX_MATCH) {
+ final PsiClassType string = TypesUtil.createType(CommonClassNames.JAVA_LANG_STRING, expression);
+ myResult = createSimpleSubTypeResult(string);
+ }
+ else {
+ myResult = createSimpleSubTypeResult(otherType);
+ }
}
-
- myResult = createSimpleSubTypeResult(otherType);
+ else { //myExpression == right
+ processCallVariants(expression, callVariants, GrNamedArgument.EMPTY_ARRAY, new GrExpression[]{myExpression}, GrClosableBlock.EMPTY_ARRAY);
+ }
}
@Override
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 eb1f818..387db84 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
@@ -44,4 +44,14 @@
}
return null;
}
+
+ @Nullable
+ public static Boolean inferBooleanAttribute(@NotNull PsiAnnotation annotation, @NotNull String attributeName) {
+ final PsiAnnotationMemberValue targetValue = annotation.findAttributeValue(attributeName);
+ if (targetValue instanceof PsiLiteral) {
+ final Object value = ((PsiLiteral)targetValue).getValue();
+ if (value instanceof Boolean) return (Boolean)value;
+ }
+ return null;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnonymousClassType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnonymousClassType.java
index fd6ee28..529b060 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnonymousClassType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrAnonymousClassType.java
@@ -74,6 +74,7 @@
return new GrAnonymousClassType(languageLevel, myScope, myFacade, myAnonymous);
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return getCanonicalText();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClassReferenceType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClassReferenceType.java
index 4c02980..aa74648 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClassReferenceType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrClassReferenceType.java
@@ -40,6 +40,7 @@
myReferenceElement = referenceElement;
}
+ @Override
@Nullable
public PsiClass resolve() {
ResolveResult[] results = multiResolve();
@@ -56,6 +57,7 @@
return myReferenceElement.multiResolve(false);
}
+ @Override
@Nullable
public String getClassName() {
final PsiClass resolved = resolve();
@@ -63,47 +65,58 @@
return myReferenceElement.getReferenceName();
}
+ @Override
@NotNull
public PsiType[] getParameters() {
return myReferenceElement.getTypeArguments();
}
+ @Override
@NotNull
public ClassResolveResult resolveGenerics() {
final GroovyResolveResult resolveResult = myReferenceElement.advancedResolve();
return new ClassResolveResult() {
+ @Override
public PsiClass getElement() {
final PsiElement resolved = resolveResult.getElement();
return resolved instanceof PsiClass ? (PsiClass)resolved : null;
}
+ @Override
+ @NotNull
public PsiSubstitutor getSubstitutor() {
return resolveResult.getSubstitutor();
}
+ @Override
public boolean isPackagePrefixPackageReference() {
return false;
}
+ @Override
public boolean isAccessible() {
return resolveResult.isAccessible();
}
+ @Override
public boolean isStaticsScopeCorrect() {
return resolveResult.isStaticsOK();
}
+ @Override
@Nullable
public PsiElement getCurrentFileResolveScope() {
return resolveResult.getCurrentFileResolveContext();
}
+ @Override
public boolean isValidResult() {
return isStaticsScopeCorrect() && isAccessible();
}
};
}
+ @Override
@NotNull
public PsiClassType rawType() {
final PsiClass clazz = resolve();
@@ -115,38 +128,48 @@
return this;
}
+ @NotNull
+ @Override
public String getPresentableText() {
return PsiNameHelper.getPresentableText(myReferenceElement.getReferenceName(), PsiAnnotation.EMPTY_ARRAY, myReferenceElement.getTypeArguments());
}
+ @Override
@NotNull
public String getCanonicalText() {
return myReferenceElement.getCanonicalText();
}
+ @NotNull
+ @Override
public String getInternalCanonicalText() {
return getCanonicalText();
}
+ @Override
public boolean isValid() {
return myReferenceElement.isValid();
}
- public boolean equalsToText(@NonNls String text) {
+ @Override
+ public boolean equalsToText(@NotNull @NonNls String text) {
return text.endsWith(getPresentableText()) && //optimization
text.equals(getCanonicalText());
}
+ @Override
@NotNull
public GlobalSearchScope getResolveScope() {
return myReferenceElement.getResolveScope();
}
+ @Override
@NotNull
public LanguageLevel getLanguageLevel() {
return myLanguageLevel;
}
+ @Override
@NotNull
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
return new GrClassReferenceType(myReferenceElement,languageLevel);
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 6d59dd8..7689a6c 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
@@ -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,7 @@
*/
public class GrClosureType extends GrLiteralClassType {
private final GrSignature mySignature;
- private PsiType[] myTypeArgs = null;
+ private volatile PsiType[] myTypeArgs = null;
private GrClosureType(@NotNull LanguageLevel languageLevel,
@NotNull GlobalSearchScope scope,
@@ -63,11 +63,13 @@
myTypeArgs = typeArgs;
}
+ @Override
@NotNull
public String getClassName() {
return "Closure";
}
+ @Override
@NotNull
public PsiType[] getParameters() {
if (myTypeArgs == null) {
@@ -76,6 +78,7 @@
return myTypeArgs;
}
+ @NotNull
private PsiType[] inferParameters() {
final PsiClass psiClass = resolve();
if (psiClass != null && psiClass.getTypeParameters().length == 1) {
@@ -98,6 +101,7 @@
return GroovyCommonClassNames.GROOVY_LANG_CLOSURE;
}
+ @Override
@NotNull
public PsiClassType rawType() {
if (myTypeArgs != null && myTypeArgs.length == 0) {
@@ -107,11 +111,13 @@
return new GrClosureType(getLanguageLevel(), getResolveScope(), myFacade, mySignature, false);
}
- @Nullable
+ @Override
+ @NotNull
public String getInternalCanonicalText() {
return getCanonicalText();
}
+ @Override
public boolean isValid() {
return mySignature.isValid();
}
@@ -124,10 +130,12 @@
return super.equals(obj);
}
- public boolean equalsToText(@NonNls String text) {
+ @Override
+ public boolean equalsToText(@NotNull @NonNls String text) {
return text != null && text.equals(GroovyCommonClassNames.GROOVY_LANG_CLOSURE);
}
+ @Override
@NotNull
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
return new GrClosureType(languageLevel, myScope, myFacade, mySignature, myTypeArgs);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java
index 3595f8d..738ac06 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrLiteralClassType.java
@@ -43,6 +43,7 @@
@NotNull
protected abstract String getJavaClassName();
+ @Override
@NotNull
public ClassResolveResult resolveGenerics() {
final PsiClass myBaseClass = resolve();
@@ -50,31 +51,39 @@
return new ClassResolveResult() {
+ @Override
public PsiClass getElement() {
return myBaseClass;
}
+ @Override
+ @NotNull
public PsiSubstitutor getSubstitutor() {
return substitutor;
}
+ @Override
public boolean isPackagePrefixPackageReference() {
return false;
}
+ @Override
public boolean isAccessible() {
return true;
}
+ @Override
public boolean isStaticsScopeCorrect() {
return true;
}
+ @Override
@Nullable
public PsiElement getCurrentFileResolveScope() {
return null;
}
+ @Override
public boolean isValidResult() {
return isStaticsScopeCorrect() && isAccessible();
}
@@ -90,7 +99,7 @@
return PsiSubstitutor.EMPTY.putAll(myBaseClass, typeArgs);
}
else {
- return PsiSubstitutor.EMPTY.putAll(myBaseClass, new PsiType[typeParams.length]);
+ return PsiSubstitutor.EMPTY.putAll(myBaseClass, createArray(typeParams.length));
}
}
else {
@@ -102,6 +111,7 @@
@NotNull
public abstract String getClassName() ;
+ @Override
@NotNull
public String getPresentableText() {
String name = getClassName();
@@ -116,6 +126,7 @@
}, ", ") + ">";
}
+ @Override
@NotNull
public String getCanonicalText() {
String name = getJavaClassName();
@@ -131,6 +142,7 @@
return name + "<" + StringUtil.join(params, f, ", ") + ">";
}
+ @Override
@NotNull
public LanguageLevel getLanguageLevel() {
return myLanguageLevel;
@@ -141,20 +153,24 @@
return myScope;
}
+ @Override
@Nullable
public PsiClass resolve() {
return myGroovyPsiManager.findClassWithCache(getJavaClassName(), getResolveScope());
}
+ @Override
@NotNull
public PsiClassType rawType() {
return myGroovyPsiManager.createTypeByFQClassName(getJavaClassName(), myScope);
}
- public boolean equalsToText(@NonNls String text) {
+ @Override
+ public boolean equalsToText(@NotNull @NonNls String text) {
return text != null && text.equals(getJavaClassName());
}
+ @Override
@NotNull
public GlobalSearchScope getResolveScope() {
return myScope;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java
index 3387f98..1142db2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrMapType.java
@@ -87,6 +87,7 @@
return myJavaClassName;
}
+ @Override
@NotNull
public String getClassName() {
return StringUtil.getShortName(myJavaClassName);
@@ -110,7 +111,7 @@
result.add(entry.first);
}
result.remove(null);
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(createArray(result.size()));
}
public PsiType[] getAllValueTypes() {
@@ -120,9 +121,10 @@
result.add(entry.second);
}
result.remove(null);
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(createArray(result.size()));
}
+ @Override
@NotNull
public PsiType[] getParameters() {
final PsiType[] keyTypes = getAllKeyTypes();
@@ -134,9 +136,11 @@
return new PsiType[]{getLeastUpperBound(keyTypes), getLeastUpperBound(valueTypes)};
}
+ @Override
+ @NotNull
public String getInternalCanonicalText() {
- if (myStringEntries.size() == 0) {
- if (myOtherEntries.size() == 0) return "[:]";
+ if (myStringEntries.isEmpty()) {
+ if (myOtherEntries.isEmpty()) return "[:]";
String name = getJavaClassName();
final PsiType[] params = getParameters();
return name + "<" + getInternalText(params[0]) + ", " + getInternalText(params[1]) + ">";
@@ -159,6 +163,7 @@
return param == null ? "null" : param.getInternalCanonicalText();
}
+ @Override
public boolean isValid() {
for (PsiType type : myStringEntries.values()) {
if (type != null && !type.isValid()) {
@@ -177,6 +182,7 @@
return true;
}
+ @Override
@NotNull
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
return new GrMapType(myFacade, getResolveScope(), myStringEntries, myOtherEntries, languageLevel);
@@ -189,6 +195,7 @@
return super.equals(obj);
}
+ @Override
public boolean isAssignableFrom(@NotNull PsiType type) {
return type instanceof GrMapType || super.isAssignableFrom(type);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java
index ed887ff..9abcedf 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrRangeType.java
@@ -34,8 +34,8 @@
* @author Maxim.Medvedev
*/
public class GrRangeType extends GrLiteralClassType {
- private final @Nullable PsiType myLeft;
- private final @Nullable PsiType myRight;
+ @Nullable private final PsiType myLeft;
+ @Nullable private final PsiType myRight;
private final PsiType myIterationType;
private final String myQualifiedName;
@@ -97,6 +97,7 @@
return new GrRangeType(languageLevel, myScope, myFacade, myLeft, myRight);
}
+ @NotNull
@Override
public String getInternalCanonicalText() {
return "[" +
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrReferenceElementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrReferenceElementImpl.java
index ada7e75..05e634b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrReferenceElementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrReferenceElementImpl.java
@@ -41,6 +41,7 @@
super(node);
}
+ @Override
public PsiReference getReference() {
return this;
}
@@ -52,6 +53,7 @@
super.subtreeChanged();
}
+ @Override
public String getReferenceName() {
PsiElement nameElement = getReferenceNameElement();
if (nameElement != null) {
@@ -60,10 +62,12 @@
return null;
}
+ @Override
public PsiElement getElement() {
return this;
}
+ @Override
public TextRange getRangeInElement() {
final PsiElement refNameElement = getReferenceNameElement();
if (refNameElement != null) {
@@ -73,6 +77,7 @@
return new TextRange(0, getTextLength());
}
+ @Override
public PsiElement handleElementRenameSimple(String newElementName) throws IncorrectOperationException {
PsiElement nameElement = getReferenceNameElement();
if (nameElement != null) {
@@ -92,10 +97,12 @@
return this;
}
+ @Override
public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
return handleElementRenameSimple(newElementName);
}
+ @Override
public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
if (isReferenceTo(element)) return this;
final boolean fullyQualified = isFullyQualified();
@@ -151,6 +158,7 @@
public abstract boolean isFullyQualified();
+ @Override
@NotNull
public PsiType[] getTypeArguments() {
final GrTypeArgumentList typeArgsList = getTypeArgumentList();
@@ -158,7 +166,7 @@
final GrTypeElement[] args = typeArgsList.getTypeArgumentElements();
if (args.length == 0) return PsiType.EMPTY_ARRAY;
- PsiType[] result = new PsiType[args.length];
+ PsiType[] result = PsiType.createArray(args.length);
for (int i = 0; i < result.length; i++) {
result[i] = args[i].getType();
}
@@ -166,15 +174,18 @@
return result;
}
+ @Override
@Nullable
public GrTypeArgumentList getTypeArgumentList() {
return (GrTypeArgumentList)findChildByType(GroovyElementTypes.TYPE_ARGUMENTS);
}
+ @Override
public void setQualifier(@Nullable Q newQualifier) {
PsiImplUtil.setQualifier(this, newQualifier);
}
+ @Override
public String getClassNameText() {
String cachedQName = myCachedQName;
if (cachedQName == null) {
@@ -191,6 +202,7 @@
return whiteSpaceAndComments;
}
+ @Override
public boolean isQualified() {
return getQualifier() != null;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java
index 9d1b305..1b444cd 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrTupleType.java
@@ -50,11 +50,13 @@
return CommonClassNames.JAVA_UTIL_ARRAY_LIST;
}
+ @Override
@NotNull
public String getClassName() {
return StringUtil.getShortName(getJavaClassName());
}
+ @Override
@NotNull
public PsiType[] getParameters() {
return myParameters;
@@ -67,6 +69,8 @@
return new PsiType[]{leastUpperBound};
}
+ @Override
+ @NotNull
public String getInternalCanonicalText() {
StringBuilder builder = new StringBuilder();
builder.append("[");
@@ -83,6 +87,7 @@
return builder.toString();
}
+ @Override
public boolean isValid() {
for (PsiType initializer : myComponentTypes) {
if (initializer != null && !initializer.isValid()) return false;
@@ -90,6 +95,7 @@
return true;
}
+ @Override
@NotNull
public PsiClassType setLanguageLevel(@NotNull final LanguageLevel languageLevel) {
return new GrTupleType(myComponentTypes, myFacade, myScope,languageLevel);
@@ -106,6 +112,7 @@
return super.equals(obj);
}
+ @Override
public boolean isAssignableFrom(@NotNull PsiType type) {
if (type instanceof GrTupleType) {
PsiType[] otherComponents = ((GrTupleType) type).myComponentTypes;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java
index cc03c9a..0b54659 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyDirectInheritorsSearcher.java
@@ -51,7 +51,7 @@
final String name = clazz.getName();
if (name == null) return Collections.emptyList();
final ArrayList<PsiClass> inheritors = new ArrayList<PsiClass>();
- for (GrReferenceList list : StubIndex.getInstance().safeGet(GrDirectInheritorsIndex.KEY, name, clazz.getProject(), scope,
+ for (GrReferenceList list : StubIndex.getElements(GrDirectInheritorsIndex.KEY, name, clazz.getProject(), scope,
GrReferenceList.class)) {
final PsiElement parent = list.getParent();
if (parent instanceof GrTypeDefinition) {
@@ -59,7 +59,7 @@
}
}
final Collection<GrAnonymousClassDefinition> classes =
- StubIndex.getInstance().get(GrAnonymousClassIndex.KEY, name, clazz.getProject(), scope);
+ StubIndex.getElements(GrAnonymousClassIndex.KEY, name, clazz.getProject(), scope, GrAnonymousClassDefinition.class);
for (GrAnonymousClassDefinition aClass : classes) {
inheritors.add(aClass);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
index 9641abf..764e321 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileBaseImpl.java
@@ -144,17 +144,17 @@
public void removeImport(GrImportStatement importStatement) throws IncorrectOperationException {
PsiElement before = importStatement;
- while (isWhiteSpace(before.getPrevSibling())) {
+ while (isWhiteSpaceOrNls(before.getPrevSibling())) {
before = before.getPrevSibling();
}
if (hasElementType(before.getPrevSibling(), GroovyTokenTypes.mSEMI)) before = before.getPrevSibling();
- if (isWhiteSpace(before.getPrevSibling())) before = before.getPrevSibling();
+ if (isWhiteSpaceOrNls(before.getPrevSibling())) before = before.getPrevSibling();
PsiElement after = importStatement;
- if (isWhiteSpace(after.getNextSibling())) after = after.getNextSibling();
+ if (isWhiteSpaceOrNls(after.getNextSibling())) after = after.getNextSibling();
if (hasElementType(after.getNextSibling(), GroovyTokenTypes.mSEMI)) after = after.getNextSibling();
- while (isWhiteSpace(after.getNextSibling())) after = after.getNextSibling();
+ while (isWhiteSpaceOrNls(after.getNextSibling())) after = after.getNextSibling();
if (before == null) before = importStatement;
@@ -243,8 +243,7 @@
public Instruction[] getControlFlow() {
assert isValid();
- SoftReference<Instruction[]> flow = myControlFlow;
- Instruction[] result = flow != null ? flow.get() : null;
+ Instruction[] result = SoftReference.dereference(myControlFlow);
if (result == null) {
result = new ControlFlowBuilder(getProject()).buildControlFlow(this);
myControlFlow = new SoftReference<Instruction[]>(result);
@@ -272,11 +271,11 @@
final PackageEntry[] entries = layoutTable.getEntries();
PsiElement prev = result.getPrevSibling();
- while (isWhiteSpace(prev)) {
+ while (isWhiteSpaceOrNls(prev)) {
prev = prev.getPrevSibling();
}
if (hasElementType(prev, GroovyTokenTypes.mSEMI)) prev = prev.getPrevSibling();
- if (isWhiteSpace(prev)) prev = prev.getPrevSibling();
+ if (isWhiteSpaceOrNls(prev)) prev = prev.getPrevSibling();
if (prev instanceof GrImportStatement) {
final int idx_before = getPackageEntryIdx(entries, (GrImportStatement)prev);
@@ -284,9 +283,9 @@
final int spaceCount = getMaxSpaceCount(entries, idx_before, idx);
//skip space and semicolon after import
- if (isWhiteSpace(prev.getNextSibling()) && hasElementType(prev.getNextSibling().getNextSibling(), GroovyTokenTypes.mSEMI)) prev = prev.getNextSibling().getNextSibling();
+ if (isWhiteSpaceOrNls(prev.getNextSibling()) && hasElementType(prev.getNextSibling().getNextSibling(), GroovyTokenTypes.mSEMI)) prev = prev.getNextSibling().getNextSibling();
final FileASTNode node = getNode();
- while (isWhiteSpace(prev.getNextSibling())) {
+ while (isWhiteSpaceOrNls(prev.getNextSibling())) {
node.removeChild(prev.getNextSibling().getNode());
}
node.addLeaf(GroovyTokenTypes.mNLS, StringUtil.repeat("\n", spaceCount + 1), result.getNode());
@@ -299,9 +298,9 @@
final PackageEntry[] entries = layoutTable.getEntries();
PsiElement next = result.getNextSibling();
- if (isWhiteSpace(next)) next = next.getNextSibling();
+ if (isWhiteSpaceOrNls(next)) next = next.getNextSibling();
if (hasElementType(next, GroovyTokenTypes.mSEMI)) next = next.getNextSibling();
- while (isWhiteSpace(next)) {
+ while (isWhiteSpaceOrNls(next)) {
next = next.getNextSibling();
}
if (next instanceof GrImportStatement) {
@@ -311,7 +310,7 @@
final FileASTNode node = getNode();
- while (isWhiteSpace(next.getPrevSibling())) {
+ while (isWhiteSpaceOrNls(next.getPrevSibling())) {
node.removeChild(next.getPrevSibling().getNode());
}
node.addLeaf(GroovyTokenTypes.mNLS, StringUtil.repeat("\n", spaceCount + 1), next.getNode());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java
index e4da17d..9728c54 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java
@@ -17,6 +17,7 @@
package org.jetbrains.plugins.groovy.lang.psi.impl;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
@@ -563,5 +564,13 @@
}
return this;
}
+
+ @Override
+ public String toString() {
+ if (ApplicationManager.getApplication().isUnitTestMode()){
+ return super.toString();
+ }
+ return "GroovyFileImpl:" + getName();
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java
index d60892b..ec3def9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiElementFactoryImpl.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,6 +86,7 @@
myProject = project;
}
+ @Override
@NotNull
public PsiElement createReferenceNameFromText(String refName) {
PsiFile file = createGroovyFileChecked("a." + refName);
@@ -100,12 +101,14 @@
return element;
}
+ @Override
public PsiElement createDocMemberReferenceNameFromText(String idText) {
GrDocMemberReference reference = createDocMemberReferenceFromText("Foo", idText);
LOG.assertTrue(reference != null, idText);
return reference.getReferenceNameElement();
}
+ @Override
public GrDocMemberReference createDocMemberReferenceFromText(String className, String text) {
PsiFile file = createGroovyFileChecked("/** @see " + className + "#" + text + " */");
PsiElement element = file.getFirstChild();
@@ -115,6 +118,7 @@
return PsiTreeUtil.getChildOfType(tag, GrDocMemberReference.class);
}
+ @Override
public GrDocReferenceElement createDocReferenceElementFromFQN(String qName) {
PsiFile file = createGroovyFileChecked("/** @see " + qName + " */");
PsiElement element = file.getFirstChild();
@@ -124,12 +128,14 @@
return PsiTreeUtil.getChildOfType(tag, GrDocReferenceElement.class);
}
+ @Override
public GrCodeReferenceElement createReferenceElementFromText(String refName, final PsiElement context) {
GroovyFile file = createGroovyFileChecked("(" + refName + ")foo", false, context);
GrTypeElement typeElement = ((GrTypeCastExpression) file.getTopStatements()[0]).getCastTypeElement();
return ((GrClassTypeElement) typeElement).getReferenceElement();
}
+ @Override
public GrReferenceExpression createReferenceExpressionFromText(String idText) {
PsiFile file = createGroovyFileChecked(idText);
final GrTopStatement[] statements = ((GroovyFileBase)file).getTopStatements();
@@ -137,6 +143,7 @@
return (GrReferenceExpression) statements[0];
}
+ @Override
public GrReferenceExpression createReferenceExpressionFromText(String idText, PsiElement context) {
GroovyFile file = createGroovyFileChecked(idText, false, context);
GrTopStatement[] statements = file.getTopStatements();
@@ -159,6 +166,7 @@
return createReferenceExpressionFromText(text);
}
+ @Override
@NotNull
public GrExpression createExpressionFromText(@NotNull String text, PsiElement context) {
GroovyFile file = createGroovyFile(text, false, context);
@@ -182,7 +190,7 @@
final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
final PsiClass refClass = resolveResult.getElement();
assert refClass != null : type;
- return createCodeReferenceElementFromText(type.getPresentableText());
+ return createCodeReferenceElementFromText(type.getCanonicalText());
}
@NotNull
@@ -215,6 +223,7 @@
}
}
+ @Override
public GrVariableDeclaration createVariableDeclaration(@Nullable String[] modifiers,
@Nullable GrExpression initializer,
@Nullable PsiType type,
@@ -289,6 +298,7 @@
return enumClass.getEnumConstants()[0];
}
+ @Override
public GrVariableDeclaration createFieldDeclaration(String[] modifiers,
String identifier,
@Nullable GrExpression initializer,
@@ -336,6 +346,7 @@
}
}
+ @Override
@Nullable
public GrTopStatement createTopElementFromText(String text) {
GroovyFile dummyFile = createGroovyFileChecked(text);
@@ -344,6 +355,7 @@
return topStatements[0];
}
+ @Override
public GrClosableBlock createClosureFromText(String closureText, PsiElement context) throws IncorrectOperationException {
GroovyFile psiFile = createGroovyFileChecked("def __hdsjfghk_sdhjfshglk_foo = " + closureText, false, context);
final GrStatement st = psiFile.getStatements()[0];
@@ -360,6 +372,7 @@
return (GroovyFileImpl) factory.createFileFromText(fileName, GroovyFileType.GROOVY_FILE_TYPE, text, stamp, physical);
}
+ @Override
public GrParameter createParameter(String name,
@Nullable String typeText,
@Nullable String initializer,
@@ -375,7 +388,7 @@
fileText.append(typeText).append(' ');
}
fileText.append(name);
- if (initializer != null && initializer.length() > 0) {
+ if (initializer != null && !initializer.isEmpty()) {
fileText.append(" = ").append(initializer);
}
fileText.append("){}");
@@ -389,6 +402,7 @@
}
}
+ @Override
public GrCodeReferenceElement createTypeOrPackageReference(String qName) {
try {
final GroovyFileBase file = createGroovyFileChecked("def i = new " + qName + "()");
@@ -403,6 +417,7 @@
}
}
+ @Override
public GrTypeDefinition createTypeDefinition(String text) throws IncorrectOperationException {
final GroovyFileBase file = createGroovyFileChecked(text);
final GrTypeDefinition[] classes = file.getTypeDefinitions();
@@ -410,6 +425,7 @@
return classes[0];
}
+ @Override
@NotNull
public GrTypeElement createTypeElement(String typeText, final PsiElement context) throws IncorrectOperationException {
final GroovyFile file = createGroovyFileChecked("def " + typeText + " someVar", false, context);
@@ -427,6 +443,7 @@
return element;
}
+ @Override
public GrTypeElement createTypeElement(PsiType type) throws IncorrectOperationException {
final String typeText = getTypeText(type);
if (typeText == null)
@@ -440,14 +457,17 @@
return JavaPsiFacade.getElementFactory(myProject).createType(aClass);
}
+ @Override
public GrParenthesizedExpression createParenthesizedExpr(GrExpression expression) {
return ((GrParenthesizedExpression) createExpressionFromText("(" + expression.getText() + ")"));
}
+ @Override
public PsiElement createStringLiteralForReference(String text) {
return createLiteralFromValue(text).getFirstChild();
}
+ @Override
public PsiElement createModifierFromText(String name) {
final GroovyFileBase file = createGroovyFileChecked(name + " foo() {}");
final GrTopLevelDefinition[] definitions = file.getTopLevelDefinitions();
@@ -455,12 +475,14 @@
return definitions[0].getFirstChild().getFirstChild();
}
+ @Override
public GrCodeBlock createMethodBodyFromText(String text) {
final GroovyFileBase file = createGroovyFileChecked("def foo () {" + text + "}");
final GrMethod method = (GrMethod) file.getTopLevelDefinitions()[0];
return method.getBlock();
}
+ @Override
public GrVariableDeclaration createSimpleVariableDeclaration(String name, String typeText) {
String classText;
if (Character.isLowerCase(typeText.charAt(0))) {
@@ -474,14 +496,17 @@
return (GrVariableDeclaration) body.getMemberDeclarations()[0];
}
+ @Override
public GrReferenceElement createPackageReferenceElementFromText(String newPackageName) {
return ((GrPackageDefinition) createGroovyFileChecked("package " + newPackageName).getTopStatements()[0]).getPackageReference();
}
+ @Override
public PsiElement createDotToken(String newDot) {
return createReferenceExpressionFromText("a" + newDot + "b").getDotToken();
}
+ @Override
public GrMethod createConstructorFromText(@NotNull String constructorName,
@Nullable String[] paramTypes,
String[] paramNames,
@@ -491,6 +516,7 @@
return createConstructorFromText(constructorName, text, context);
}
+ @Override
public GrMethod createConstructorFromText(String constructorName, CharSequence constructorText, @Nullable PsiElement context) {
GroovyFile file = createGroovyFileChecked("class " + constructorName + "{" + constructorText + "}", false, context);
GrTopLevelDefinition definition = file.getTopLevelDefinitions()[0];
@@ -505,6 +531,7 @@
return methods[0];
}
+ @Override
@NotNull
public GrMethod createMethodFromText(@NotNull String methodText, @Nullable PsiElement context) {
GroovyFile file = createGroovyFile(methodText, false, context);
@@ -523,14 +550,14 @@
@NotNull
@Override
public GrAnnotation createAnnotationFromText(@NotNull @NonNls String annotationText, @Nullable PsiElement context) throws IncorrectOperationException {
- return createMethodFromText(annotationText + " void ___shdjklf_pqweirupncp_foo() {}", context).getModifierList().getAnnotations()[0];
+ return createMethodFromText(annotationText + " void ___shdjklf_pqweirupncp_foo() {}", context).getModifierList().getRawAnnotations()[0];
}
@Override
public GrMethod createMethodFromSignature(String name, GrClosureSignature signature) {
StringBuilder builder = new StringBuilder("public");
final PsiType returnType = signature.getReturnType();
- if (returnType != null) {
+ if (returnType != null && returnType != PsiType.NULL) {
builder.append(' ');
builder.append(returnType.getCanonicalText());
}
@@ -579,17 +606,20 @@
/**
* use createGroovyFileChecked() inside GroovyPsiElementFactoryImpl instead of this method
*/
+ @Override
public GroovyFile createGroovyFile(CharSequence idText, boolean isPhysical, @Nullable PsiElement context) {
GroovyFileImpl file = createDummyFile(idText, isPhysical);
file.setContext(context);
return file;
}
+ @Override
public PsiElement createWhiteSpace() {
PsiFile dummyFile = createDummyFile(" ", false);
return dummyFile.getFirstChild();
}
+ @Override
@NotNull
public PsiElement createLineTerminator(int length) {
@@ -601,6 +631,7 @@
return createLineTerminator(text);
}
+ @Override
@NotNull
public PsiElement createLineTerminator(String text) {
PsiFile dummyFile = createGroovyFileChecked(text);
@@ -609,6 +640,7 @@
return child;
}
+ @Override
public GrArgumentList createExpressionArgumentList(GrExpression... expressions) {
StringBuilder text = new StringBuilder();
text.append("ven (");
@@ -624,6 +656,7 @@
return (((GrMethodCallExpression) file.getChildren()[0])).getArgumentList();
}
+ @Override
public GrNamedArgument createNamedArgument(@NotNull final String name, final GrExpression expression) {
PsiFile file = createGroovyFileChecked("foo (" + name + ":" + expression.getText() + ")");
assert file.getChildren()[0] != null;
@@ -631,6 +664,7 @@
return call.getArgumentList().getNamedArguments()[0];
}
+ @Override
public GrStatement createStatementFromText(CharSequence text) {
return createStatementFromText(text, null);
}
@@ -648,6 +682,7 @@
return (GrStatement)statements[0];
}
+ @Override
public GrBlockStatement createBlockStatement(@NonNls GrStatement... statements) {
StringBuilder text = new StringBuilder();
text.append("while (true) { \n");
@@ -660,6 +695,7 @@
return (GrBlockStatement) ((GrWhileStatement) file.getChildren()[0]).getBody();
}
+ @Override
public GrMethodCallExpression createMethodCallByAppCall(GrApplicationStatement callExpr) {
StringBuilder text = new StringBuilder();
text.append(callExpr.getInvokedExpression().getText());
@@ -741,10 +777,12 @@
return sections[0];
}
+ @Override
public GrImportStatement createImportStatementFromText(@NotNull String qName, boolean isStatic, boolean isOnDemand, String alias) {
return createImportStatement(qName, isStatic, isOnDemand, alias, null);
}
+ @Override
public GrImportStatement createImportStatementFromText(@NotNull String text) {
PsiFile dummyFile = createGroovyFileChecked(text);
return ((GrImportStatement) dummyFile.getFirstChild());
@@ -825,6 +863,7 @@
return builder;
}
+ @Override
public GrMethod createMethodFromText(String modifier, String name, @Nullable String type, String[] paramTypes, PsiElement context) {
PsiType psiType;
List<PsiType> res = new ArrayList<PsiType>();
@@ -840,11 +879,12 @@
res.add(psiType);
}
- String[] paramNames = QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(new PsiType[res.size()]));
+ String[] paramNames = QuickfixUtil.getMethodArgumentsNames(myProject, res.toArray(PsiType.createArray(res.size())));
final CharSequence text = generateMethodText(modifier, name, type, paramTypes, paramNames, null, false);
return createMethodFromText(text.toString(), context);
}
+ @Override
@NotNull
public GrDocComment createDocCommentFromText(@NotNull String text) {
return (GrDocComment)createGroovyFileChecked(text).getFirstChild();
@@ -899,6 +939,7 @@
return ((GrCall)createExpressionFromText("foo()")).getArgumentList();
}
+ @Override
public GrArgumentList createArgumentListFromText(String argListText) {
try {
return ((GrCall)createExpressionFromText("foo " + argListText)).getArgumentList();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java
index d1822bb..c31399e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyPsiManager.java
@@ -36,6 +36,7 @@
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.*;
import com.intellij.util.messages.MessageBusConnection;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
@@ -77,11 +78,13 @@
myProject = project;
((PsiManagerEx)PsiManager.getInstance(myProject)).registerRunnableToRunOnAnyChange(new Runnable() {
+ @Override
public void run() {
dropTypesCache();
}
});
((PsiManagerEx)PsiManager.getInstance(myProject)).registerRunnableToRunOnChange(new Runnable() {
+ @Override
public void run() {
myClassCache.clear();
}
@@ -89,6 +92,7 @@
final MessageBusConnection connection = myProject.getMessageBus().connect();
connection.subscribe(ProjectTopics.PROJECT_ROOTS, new ModuleRootAdapter() {
+ @Override
public void rootsChanged(ModuleRootEvent event) {
dropTypesCache();
myClassCache.clear();
@@ -186,7 +190,52 @@
}
- private static final PsiType UNKNOWN_TYPE = new PsiPrimitiveType("unknown type", PsiAnnotation.EMPTY_ARRAY);
+ private static final PsiType UNKNOWN_TYPE = new PsiType(PsiAnnotation.EMPTY_ARRAY) {
+ @NotNull
+ @Override
+ public String getPresentableText() {
+ return "?";
+ }
+
+ @NotNull
+ @Override
+ public String getCanonicalText() {
+ return "?";
+ }
+
+ @NotNull
+ @Override
+ public String getInternalCanonicalText() {
+ return "?";
+ }
+
+ @Override
+ public boolean isValid() {
+ return true;
+ }
+
+ @Override
+ public boolean equalsToText(@NotNull @NonNls String text) {
+ return false;
+ }
+
+ @Override
+ public <A> A accept(@NotNull PsiTypeVisitor<A> visitor) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public GlobalSearchScope getResolveScope() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public PsiType[] getSuperTypes() {
+ return PsiType.EMPTY_ARRAY;
+ }
+ };
@Nullable
public <T extends GroovyPsiElement> PsiType getType(@NotNull T element, @NotNull Function<T, PsiType> calculator) {
PsiType type = myCalculatedTypes.get(element);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java
index ee45530..a50d882 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyResolveResultImpl.java
@@ -31,6 +31,8 @@
private final PsiElement myElement;
private final boolean myIsAccessible;
private final boolean myIsStaticsOK;
+ private final boolean myIsApplicable;
+
private final PsiSubstitutor mySubstitutor;
private final boolean myIsInvokedOnProperty;
@@ -38,7 +40,7 @@
private final SpreadState mySpreadState;
public GroovyResolveResultImpl(@NotNull PsiElement element, boolean isAccessible) {
- this(element, null, null, PsiSubstitutor.EMPTY, isAccessible, true, false);
+ this(element, null, null, PsiSubstitutor.EMPTY, isAccessible, true, false, true);
}
public GroovyResolveResultImpl(@NotNull PsiElement element,
@@ -47,11 +49,11 @@
@NotNull PsiSubstitutor substitutor,
boolean isAccessible,
boolean staticsOK) {
- this(element, resolveContext, spreadState, substitutor, isAccessible, staticsOK, false);
+ this(element, resolveContext, spreadState, substitutor, isAccessible, staticsOK, false, true);
}
public GroovyResolveResultImpl(PsiClassType.ClassResolveResult classResolveResult) {
- this(classResolveResult.getElement(), null, null, classResolveResult.getSubstitutor(), classResolveResult.isAccessible(), classResolveResult.isStaticsScopeCorrect(), false);
+ this(classResolveResult.getElement(), null, null, classResolveResult.getSubstitutor(), classResolveResult.isAccessible(), classResolveResult.isStaticsScopeCorrect(), false, classResolveResult.isValidResult());
}
public GroovyResolveResultImpl(@NotNull PsiElement element,
@@ -60,7 +62,8 @@
@NotNull PsiSubstitutor substitutor,
boolean isAccessible,
boolean staticsOK,
- boolean isInvokedOnProperty) {
+ boolean isInvokedOnProperty,
+ boolean isApplicable) {
myCurrentFileResolveContext = resolveContext;
myElement = element;
myIsAccessible = isAccessible;
@@ -68,6 +71,7 @@
myIsStaticsOK = staticsOK;
myIsInvokedOnProperty = isInvokedOnProperty;
mySpreadState = spreadState;
+ myIsApplicable = isApplicable;
}
@NotNull
@@ -83,13 +87,18 @@
return myIsStaticsOK;
}
+ @Override
+ public boolean isApplicable() {
+ return myIsApplicable;
+ }
+
@Nullable
public PsiElement getElement() {
return myElement;
}
public boolean isValidResult() {
- return isAccessible();
+ return isAccessible() && isApplicable() && isStaticsOK();
}
public boolean equals(Object o) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java
index 3f8eb9c..1dd57fc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/InferenceContext.java
@@ -141,8 +141,7 @@
return _getCachedValue(element, new Computable<PsiType>() {
@Override
public PsiType compute() {
- PsiType type = calculator.fun(element);
- return type == PsiType.NULL ? null : type;
+ return calculator.fun(element);
}
}, "type");
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java
index 1fe5e6f..5eaa8f2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/PsiImplUtil.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,8 @@
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrListOrMap;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifier;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.GrModifierList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrConstructorInvocation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
@@ -74,9 +76,6 @@
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrNamedArgumentsOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrAdditiveExpressionImpl;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrMultiplicativeExpressionImpl;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrRangeExpressionImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.literals.GrLiteralImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrSyntheticExpression;
@@ -273,20 +272,11 @@
private static boolean isNotAssociative(GrBinaryExpression binaryExpression) {
final IElementType opToken = binaryExpression.getOperationTokenType();
- if (binaryExpression instanceof GrMultiplicativeExpressionImpl) {
- return opToken != mSTAR;
- }
- if (binaryExpression instanceof GrAdditiveExpressionImpl) {
- return opToken == mMINUS;
- }
- return RELATIONS.contains(opToken) || opToken == mCOMPARE_TO
- || opToken == mREGEX_FIND || opToken == mREGEX_MATCH
- || SHIFT_SIGNS.contains(opToken)
- || opToken==mSTAR;
+ return !TokenSets.ASSOCIATIVE_BINARY_OP_SET.contains(opToken);
}
@Nullable
- public static GrExpression getRuntimeQualifier(GrReferenceExpression refExpr) {
+ public static GrExpression getRuntimeQualifier(@NotNull GrReferenceExpression refExpr) {
GrExpression qualifier = refExpr.getQualifierExpression();
if (qualifier != null) return qualifier;
@@ -362,12 +352,11 @@
}
private static int getExprPriorityLevel(GrExpression expr) {
- int priority = 0;
+ int priority;
//if (expr instanceof GrNewExpression) priority = 1;
if (expr instanceof GrUnaryExpression) priority = ((GrUnaryExpression)expr).isPostfix() ? 5 : 6;
else if (expr instanceof GrTypeCastExpression) priority = 6;
- else if (expr instanceof GrRangeExpressionImpl) priority = 11;
else if (expr instanceof GrBinaryExpression) {
final IElementType opToken = ((GrBinaryExpression)expr).getOperationTokenType();
@@ -376,6 +365,7 @@
else if (opToken == mSTAR || opToken == mDIV) priority = 8;
else if (opToken == mPLUS || opToken == mMINUS) priority = 9;
else if (SHIFT_SIGNS.contains(opToken)) priority = 10;
+ else if (opToken == mRANGE_EXCLUSIVE || opToken == mRANGE_INCLUSIVE) priority = 11;
else if (RELATIONS.contains(opToken)) priority = 12;
else if (opToken == mEQUAL || opToken == mNOT_EQUAL || opToken == mCOMPARE_TO) priority = 13;
else if (opToken == mREGEX_FIND || opToken == mREGEX_MATCH) priority = 14;
@@ -384,11 +374,16 @@
else if (opToken == mBOR) priority = 17;
else if (opToken == mLAND) priority = 18;
else if (opToken == mLOR) priority = 19;
+ else {
+ assert false :"unknown operation:"+opToken;
+ priority = 0;
+ }
}
else if (expr instanceof GrConditionalExpression) priority = 20;
else if (expr instanceof GrSafeCastExpression) priority = 21;
else if (expr instanceof GrAssignmentExpression) priority = 22;
else if (expr instanceof GrApplicationStatement) priority = 23;
+ else priority = 0;
return -priority;
}
@@ -582,7 +577,7 @@
if (block == null) return null;
final SoftReference<PsiCodeBlock> ref = block.getUserData(PSI_CODE_BLOCK);
- final PsiCodeBlock body = ref == null ? null : ref.get();
+ final PsiCodeBlock body = SoftReference.dereference(ref);
if (body != null) return body;
final GrSyntheticCodeBlock newBody = new GrSyntheticCodeBlock(block);
block.putUserData(PSI_CODE_BLOCK, new SoftReference<PsiCodeBlock>(newBody));
@@ -593,7 +588,7 @@
if (typeElement == null) return null;
final SoftReference<PsiTypeElement> ref = typeElement.getUserData(PSI_TYPE_ELEMENT);
- final PsiTypeElement element = ref == null ? null : ref.get();
+ final PsiTypeElement element = SoftReference.dereference(ref);
if (element != null) return element;
final GrSyntheticTypeElement newTypeElement = new GrSyntheticTypeElement(typeElement);
typeElement.putUserData(PSI_TYPE_ELEMENT, new SoftReference<PsiTypeElement>(newTypeElement));
@@ -604,7 +599,7 @@
if (expr == null) return null;
final SoftReference<PsiExpression> ref = expr.getUserData(PSI_EXPRESSION);
- final PsiExpression element = ref == null ? null : ref.get();
+ final PsiExpression element = SoftReference.dereference(ref);
if (element != null) return element;
final GrSyntheticExpression newExpr = new GrSyntheticExpression(expr);
expr.putUserData(PSI_EXPRESSION, new SoftReference<PsiExpression>(newExpr));
@@ -615,7 +610,7 @@
if (list == null) return null;
final SoftReference<PsiReferenceList> ref = list.getUserData(PSI_REFERENCE_LIST);
- final PsiReferenceList element = ref == null ? null : ref.get();
+ final PsiReferenceList element = SoftReference.dereference(ref);
if (element != null) return element;
final GrSyntheticReferenceList newList = new GrSyntheticReferenceList(list, role);
list.putUserData(PSI_REFERENCE_LIST, new SoftReference<PsiReferenceList>(newList));
@@ -756,10 +751,6 @@
return type;
}
- public static boolean isWhiteSpace(@Nullable PsiElement element) {
- return hasElementType(element, TokenSets.WHITE_SPACES_SET);
- }
-
public static boolean hasElementType(@Nullable PsiElement next, @NotNull final IElementType type) {
if (next == null) return false;
final ASTNode astNode = next.getNode();
@@ -849,4 +840,44 @@
return modifierList.findAnnotation(GROOVY_LANG_IMMUTABLE) != null ||
modifierList.findAnnotation(GROOVY_TRANSFORM_IMMUTABLE) != null;
}
+
+ public static boolean isWhiteSpaceOrNls(@Nullable PsiElement sibling) {
+ return sibling != null && isWhiteSpaceOrNls(sibling.getNode());
+ }
+
+ public static boolean isWhiteSpaceOrNls(@Nullable ASTNode node) {
+ return node != null && TokenSets.WHITE_SPACES_SET.contains(node.getElementType());
+ }
+
+ public static void insertPlaceHolderToModifierListAtEndIfNeeded(GrModifierList modifierList) {
+ PsiElement newLineAfterModifierList = findNewLineAfterElement(modifierList);
+ if (newLineAfterModifierList != null) {
+ modifierList.setModifierProperty(GrModifier.DEF, false);
+
+ if (modifierList.getModifiers().length > 0) {
+ modifierList.getNode().addLeaf(mNLS, newLineAfterModifierList.getText(), null);
+ }
+ modifierList.getNode().addLeaf(kDEF, "def", null);
+ final PsiElement newLineUpdated = findNewLineAfterElement(modifierList);
+ if (newLineUpdated != null) newLineUpdated.delete();
+ if (!isWhiteSpaceOrNls(modifierList.getNextSibling())) {
+ modifierList.getParent().getNode().addLeaf(TokenType.WHITE_SPACE, " ", modifierList.getNextSibling().getNode());
+ }
+ }
+ else if (modifierList.getModifiers().length == 0) {
+ modifierList.setModifierProperty(GrModifier.DEF, true);
+ }
+ }
+
+ @Nullable
+ private static PsiElement findNewLineAfterElement(PsiElement element) {
+ PsiElement sibling = element.getNextSibling();
+ while (sibling != null && isWhiteSpaceOrNls(sibling)) {
+ if (PsiUtil.isNewLine(sibling)) {
+ return sibling;
+ }
+ sibling = sibling.getNextSibling();
+ }
+ return null;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java
index 15791c2..bea29ef 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/GrListOrMapImpl.java
@@ -22,9 +22,12 @@
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.CachedValueProvider;
+import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.util.Function;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.findUsages.LiteralConstructorReference;
@@ -46,7 +49,6 @@
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
-import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -64,6 +66,7 @@
super(node);
}
+ @Override
public void accept(GroovyElementVisitor visitor) {
visitor.visitListOrMap(this);
}
@@ -98,10 +101,12 @@
super.deleteChildInternal(child);
}
+ @Override
public PsiType getType() {
return TypeInferenceHelper.getCurrentContext().getExpressionType(this, TYPES_CALCULATOR);
}
+ @Override
public boolean isMap() {
return findChildByType(MAP_LITERAL_TOKEN_SET) != null;
}
@@ -116,15 +121,19 @@
return findChildByType(GroovyTokenTypes.mRBRACK);
}
+ @Override
@NotNull
public GrExpression[] getInitializers() {
- List<GrExpression> result = new ArrayList<GrExpression>();
+ List<GrExpression> result = ContainerUtil.newArrayList();
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, GrExpression.class)) result.add((GrExpression)cur);
+ if (cur instanceof GrExpression) {
+ result.add((GrExpression)cur);
+ }
}
- return result.toArray((GrExpression[]) Array.newInstance(GrExpression.class, result.size()));
+ return result.toArray(new GrExpression[result.size()]);
}
+ @Override
@NotNull
public GrNamedArgument[] getNamedArguments() {
List<GrNamedArgument> result = new ArrayList<GrNamedArgument>();
@@ -141,13 +150,21 @@
@Override
public PsiReference getReference() {
+ return CachedValuesManager.getCachedValue(this, new CachedValueProvider<PsiReference>() {
+ @Nullable
+ @Override
+ public Result<PsiReference> compute() {
+ return Result.create(getReferenceImpl(), PsiModificationTracker.MODIFICATION_COUNT);
+ }
+ });
+ }
+
+ @Nullable
+ private PsiReference getReferenceImpl() {
final PsiClassType conversionType = LiteralConstructorReference.getTargetConversionType(this);
if (conversionType == null) return null;
- PsiType ownType = getType();
- if (ownType instanceof PsiClassType) {
- ownType = ((PsiClassType)ownType).rawType();
- }
+ PsiType ownType = getTypeWithoutGenerics();
if (ownType != null && TypesUtil.isAssignableWithoutConversions(conversionType.rawType(), ownType, this)) return null;
final PsiClass resolved = conversionType.resolve();
@@ -159,7 +176,19 @@
return new LiteralConstructorReference(this, conversionType);
}
+ @Nullable
+ private PsiType getTypeWithoutGenerics() {
+ PsiType ownType = getType();
+ if (ownType instanceof PsiClassType) {
+ return ((PsiClassType)ownType).rawType();
+ }
+ else {
+ return ownType;
+ }
+ }
+
private static class MyTypesCalculator implements Function<GrListOrMapImpl, PsiType> {
+ @Override
@Nullable
public PsiType fun(GrListOrMapImpl listOrMap) {
final GlobalSearchScope scope = listOrMap.getResolveScope();
@@ -238,7 +267,7 @@
}
}
- PsiType[] result = new PsiType[initializers.length];
+ PsiType[] result = PsiType.createArray(initializers.length);
for (int i = 0; i < result.length; i++) {
result[i] = initializers[i].getType();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java
index 674bfe6..c672ca1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/annotation/GrAnnotationImpl.java
@@ -23,6 +23,7 @@
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.light.LightClassReference;
import com.intellij.psi.meta.PsiMetaData;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.PairFunction;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -88,35 +89,61 @@
@Nullable
@NonNls
public String getQualifiedName() {
+ final GrAnnotationStub stub = getStub();
+ if (stub != null) {
+ return stub.getPsiElement().getQualifiedName();
+ }
+
final GrCodeReferenceElement nameRef = getClassReference();
final PsiElement resolved = nameRef.resolve();
- if (resolved instanceof PsiClass) return ((PsiClass) resolved).getQualifiedName();
+ if (resolved instanceof PsiClass) return ((PsiClass)resolved).getQualifiedName();
return null;
}
@Nullable
public PsiJavaCodeReferenceElement getNameReferenceElement() {
- final GroovyResolveResult resolveResult = getClassReference().advancedResolve();
- final PsiElement resolved = resolveResult.getElement();
+ final GroovyResolveResult resolveResult = resolveWithStub();
- if (resolved instanceof PsiClass) {
- return new LightClassReference(getManager(), getClassReference().getText(), (PsiClass)resolved, resolveResult.getSubstitutor());
- }
- else {
- return null;
- }
+ final PsiElement resolved = resolveResult.getElement();
+ if (!(resolved instanceof PsiClass)) return null;
+
+ return new LightClassReference(getManager(), getClassReference().getText(), (PsiClass)resolved, resolveResult.getSubstitutor());
}
+ @NotNull
+ private GroovyResolveResult resolveWithStub() {
+ final GrAnnotationStub stub = getStub();
+ final GrCodeReferenceElement reference = stub != null ? stub.getPsiElement().getClassReference() : getClassReference();
+ return reference.advancedResolve();
+ }
+
+ @Nullable
public PsiAnnotationMemberValue findAttributeValue(@Nullable String attributeName) {
+ final GrAnnotationStub stub = getStub();
+ if (stub != null) {
+ final GrAnnotation stubbedPsi = stub.getPsiElement();
+ final PsiAnnotationMemberValue value = PsiImplUtil.findAttributeValue(stubbedPsi, attributeName);
+ if (value == null || !PsiTreeUtil.isAncestor(stubbedPsi, value, true)) { // if value is a default value we can use it
+ return value;
+ }
+ }
return PsiImplUtil.findAttributeValue(this, attributeName);
}
@Nullable
public PsiAnnotationMemberValue findDeclaredAttributeValue(@NonNls final String attributeName) {
+ final GrAnnotationStub stub = getStub();
+ if (stub != null) {
+ final GrAnnotation stubbedPsi = stub.getPsiElement();
+ final PsiAnnotationMemberValue value = PsiImplUtil.findDeclaredAttributeValue(stubbedPsi, attributeName);
+ if (value == null) {
+ return null;
+ }
+ }
return PsiImplUtil.findDeclaredAttributeValue(this, attributeName);
}
- public <T extends PsiAnnotationMemberValue> T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, T value) {
+ public <T extends PsiAnnotationMemberValue> T setDeclaredAttributeValue(@Nullable @NonNls String attributeName, T value) {
return (T)PsiImplUtil.setDeclaredAttributeValue(this, attributeName, value, ANNOTATION_CREATOR);
}
@@ -127,6 +154,11 @@
@NotNull
public GrCodeReferenceElement getClassReference() {
+ final GrAnnotationStub stub = getStub();
+ if (stub != null) {
+ return stub.getPsiElement().getClassReference();
+ }
+
return findNotNullChildByClass(GrCodeReferenceElement.class);
}
@@ -134,13 +166,15 @@
public String getShortName() {
final GrAnnotationStub stub = getStub();
if (stub != null) {
- return stub.getAnnotationName();
+ return stub.getPsiElement().getShortName();
}
- else {
- return getClassReference().getReferenceName();
- }
+
+ final String referenceName = getClassReference().getReferenceName();
+ assert referenceName != null;
+ return referenceName;
}
+ @Nullable
public PsiAnnotationOwner getOwner() {
return (PsiAnnotationOwner)getParent();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java
index 1bd4bf9..9415e88 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/auxiliary/modifiers/GrModifierListImpl.java
@@ -297,7 +297,7 @@
if (doSet) {
if (isEmptyModifierList()) {
final PsiElement nextSibling = getNextSibling();
- if (nextSibling != null && !TokenSets.WHITE_SPACES_SET.contains(nextSibling.getNode().getElementType())) {
+ if (nextSibling != null && !PsiImplUtil.isWhiteSpaceOrNls(nextSibling)) {
getNode().getTreeParent().addLeaf(TokenType.WHITE_SPACE, " ", nextSibling.getNode());
}
}
@@ -317,7 +317,7 @@
if (isEmptyModifierList()) {
final PsiElement nextSibling = getNextSibling();
- if (nextSibling != null && TokenSets.WHITE_SPACES_SET.contains(nextSibling.getNode().getElementType())) {
+ if (nextSibling != null && PsiImplUtil.isWhiteSpaceOrNls(nextSibling)) {
nextSibling.delete();
}
}
@@ -360,13 +360,13 @@
@NotNull
public GrAnnotation[] getAnnotations() {
- return CachedValuesManager.getManager(getProject()).createCachedValue(new CachedValueProvider<GrAnnotation[]>() {
+ return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAnnotation[]>() {
@Nullable
@Override
public Result<GrAnnotation[]> compute() {
return Result.create(GrAnnotationCollector.getResolvedAnnotations(GrModifierListImpl.this), PsiModificationTracker.JAVA_STRUCTURE_MODIFICATION_COUNT);
}
- }).getValue();
+ });
}
@NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java
index 83c5696..48121cf 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/signatures/GrClosureSignatureUtil.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.
@@ -368,7 +368,7 @@
PsiType type;
@Nullable Arg arg;
- private ArgWrapper(PsiType type, Arg arg) {
+ private ArgWrapper(PsiType type, @Nullable Arg arg) {
this.type = type;
this.arg = arg;
}
@@ -515,7 +515,7 @@
this.context = context;
this.params = params;
this.args = args;
- this.types = new PsiType[args.length];
+ this.types = PsiType.createArray(args.length);
for (int i = 0; i < args.length; i++) {
types[i] = typeComputer.fun(args[i]);
}
@@ -819,7 +819,7 @@
List<PsiType> paramTypes,
PsiTypeParameter[] typeParameters,
PsiSubstitutor substitutor) {
- return MethodSignatureUtil.createMethodSignature(name, paramTypes.toArray(new PsiType[paramTypes.size()]), typeParameters, substitutor);
+ return MethodSignatureUtil.createMethodSignature(name, paramTypes.toArray(PsiType.createArray(paramTypes.size())), typeParameters, substitutor);
}
public static void generateAllMethodSignaturesByClosureSignature(@NotNull String name,
@@ -866,7 +866,7 @@
@Nullable
public static PsiType getTypeByArg(ArgInfo<PsiElement> arg, PsiManager manager, GlobalSearchScope resolveScope) {
if (arg.isMultiArg) {
- if (arg.args.size() == 0) return PsiType.getJavaLangObject(manager, resolveScope).createArrayType();
+ if (arg.args.isEmpty()) return PsiType.getJavaLangObject(manager, resolveScope).createArrayType();
PsiType leastUpperBound = null;
PsiElement first = arg.args.get(0);
if (first instanceof GrNamedArgument) {
@@ -887,7 +887,7 @@
}
}
else {
- if (arg.args.size() == 0) return null;
+ if (arg.args.isEmpty()) return null;
PsiElement elem = arg.args.get(0);
if (elem instanceof GrExpression) {
return ((GrExpression)elem).getType();
@@ -990,7 +990,7 @@
return new MapResultWithError<Arg>(map, errors);
}
- public static List<GrClosureSignature> generateSimpleSignature(GrSignature signature) {
+ public static List<GrClosureSignature> generateSimpleSignature(@NotNull GrSignature signature) {
final List<GrClosureSignature> result = new ArrayList<GrClosureSignature>();
signature.accept(new GrRecursiveSignatureVisitor() {
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java
index a591ed5..98763e5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrConstructorInvocationImpl.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.
@@ -69,6 +69,7 @@
}
+ @NotNull
public GrReferenceExpression getInvokedExpression() {
return findNotNullChildByClass(GrReferenceExpression.class);
}
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 38439f1..a9e25ea 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
@@ -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.
@@ -57,10 +57,8 @@
* Date: 25.05.2007
*/
public class GrFieldImpl extends GrVariableBaseImpl<GrFieldStub> implements GrField, StubBasedPsiElement<GrFieldStub> {
- private GrAccessorMethod mySetter;
- private GrAccessorMethod[] myGetters;
-
- private boolean mySetterInitialized = false;
+ private volatile GrAccessorMethod mySetter;
+ private volatile GrAccessorMethod[] myGetters;
public GrFieldImpl(@NotNull ASTNode node) {
super(node);
@@ -177,16 +175,13 @@
}
public GrAccessorMethod getSetter() {
- if (mySetterInitialized) return mySetter;
-
- mySetter = GrAccessorMethodImpl.createSetterMethod(this);
- mySetterInitialized = true;
-
+ if (mySetter == null) {
+ mySetter = GrAccessorMethodImpl.createSetterMethod(this);
+ }
return mySetter;
}
public void clearCaches() {
- mySetterInitialized = false;
mySetter = null;
myGetters = null;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java
index 0c2789a..ce98c9c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrIfStatementImpl.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,7 +19,6 @@
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
@@ -66,7 +65,7 @@
public GrStatement getThenBranch() {
List<GrStatement> statements = new ArrayList<GrStatement>();
for (PsiElement cur = getFirstChild(); cur != null; cur = cur.getNextSibling()) {
- if (ReflectionCache.isInstance(cur, GrStatement.class)) statements.add((GrStatement)cur);
+ if (GrStatement.class.isInstance(cur)) statements.add((GrStatement)cur);
}
if (getCondition() == null && statements.size() > 0) return statements.get(0);
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 1ab1a1a..990876d 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
@@ -42,6 +42,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
@@ -85,7 +86,7 @@
@NotNull
public GrModifierList getModifierList() {
- return (GrModifierList)findNotNullChildByType(GroovyElementTypes.MODIFIERS);
+ return getRequiredStubOrPsiChild(GroovyElementTypes.MODIFIERS);
}
@Override
@@ -192,7 +193,7 @@
@NotNull ResolveState state,
PsiElement lastParent,
@NotNull PsiElement place) {
- if (lastParent != null && lastParent == getTupleInitializer()) {
+ if (lastParent != null && !(getParent() instanceof GrTypeDefinitionBody) && lastParent == getTupleInitializer()) {
return true;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrWhileStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrWhileStatementImpl.java
index 1a36d72..696e94d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrWhileStatementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/GrWhileStatementImpl.java
@@ -26,6 +26,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.GrCondition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrWhileStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
@@ -50,13 +51,13 @@
}
@Nullable
- public GrCondition getCondition() {
+ public GrExpression getCondition() {
PsiElement lParenth = getLParenth();
if (lParenth == null) return null;
PsiElement afterLParenth = PsiUtil.skipWhitespacesAndComments(lParenth.getNextSibling(), true);
- if (afterLParenth instanceof GrCondition) return ((GrCondition) afterLParenth);
+ if (afterLParenth instanceof GrExpression) return ((GrExpression) afterLParenth);
return null;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java
index 3f09e10..79e6457 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrArgumentListImpl.java
@@ -209,7 +209,7 @@
ASTNode prev = TreeUtil.skipElementsBack(child.getTreePrev(), TokenSets.WHITE_SPACES_OR_COMMENTS);
if (prev != null && prev.getElementType() == mCOMMA) {
final ASTNode pprev = prev.getTreePrev();
- if (pprev != null && TokenSets.WHITE_SPACES_SET.contains(pprev.getElementType())) {
+ if (pprev != null && PsiImplUtil.isWhiteSpaceOrNls(pprev)) {
super.deleteChildInternal(pprev);
}
super.deleteChildInternal(prev);
@@ -218,7 +218,7 @@
ASTNode next = TreeUtil.skipElements(child.getTreeNext(), TokenSets.WHITE_SPACES_OR_COMMENTS);
if (next != null && next.getElementType() == mCOMMA) {
final ASTNode nnext = next.getTreeNext();
- if (nnext != null && TokenSets.WHITE_SPACES_SET.contains(nnext.getElementType())) {
+ if (nnext != null && PsiImplUtil.isWhiteSpaceOrNls(nnext)) {
super.deleteChildInternal(nnext);
}
super.deleteChildInternal(next);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrSpreadArgumentImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrSpreadArgumentImpl.java
index 3cf36fa..2e675d3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrSpreadArgumentImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/arguments/GrSpreadArgumentImpl.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.lang.ASTNode;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrSpreadArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiElementImpl;
@@ -56,4 +57,9 @@
public String toString() {
return "Spread argument";
}
+
+ @Override
+ public void accept(GroovyElementVisitor visitor) {
+ visitor.visitSpreadArgument(this);
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java
index 4b7efe4..9bc485e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/CompleteReferenceExpression.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.
@@ -75,10 +75,10 @@
private CompleteReferenceExpression() {
}
- public static void processVariants(PrefixMatcher matcher,
- final Consumer<LookupElement> consumer,
- GrReferenceExpressionImpl refExpr,
- CompletionParameters parameters) {
+ public static void processVariants(@NotNull PrefixMatcher matcher,
+ @NotNull final Consumer<LookupElement> consumer,
+ @NotNull GrReferenceExpressionImpl refExpr,
+ @NotNull CompletionParameters parameters) {
processRefInAnnotation(refExpr, matcher, consumer);
final int[] count = new int[]{0};
@@ -105,8 +105,9 @@
}
}
- public static void processRefInAnnotation(GrReferenceExpression refExpr,
- PrefixMatcher matcher, Consumer<LookupElement> consumer) {
+ public static void processRefInAnnotation(@NotNull GrReferenceExpression refExpr,
+ @NotNull PrefixMatcher matcher,
+ @NotNull Consumer<LookupElement> consumer) {
if (refExpr.getParent() instanceof GrAnnotationNameValuePair &&
((GrAnnotationNameValuePair)refExpr.getParent()).getNameIdentifierGroovy() == null) {
PsiElement parent = refExpr.getParent().getParent();
@@ -121,7 +122,9 @@
}
}
- private static void processIfJavaLangClass(GrReferenceExpression refExpr, ResolverProcessor consumer, PsiType type) {
+ private static void processIfJavaLangClass(@NotNull GrReferenceExpression refExpr,
+ @NotNull ResolverProcessor consumer,
+ @Nullable PsiType type) {
if (!(type instanceof PsiClassType)) return;
final PsiClass psiClass = ((PsiClassType)type).resolve();
@@ -133,23 +136,24 @@
getVariantsFromQualifierType(refExpr, consumer, params[0], refExpr.getProject());
}
- private static void getVariantsImpl(GrReferenceExpression refExpr, CompleteReferenceProcessor processor) {
+ private static void getVariantsImpl(@NotNull GrReferenceExpression refExpr,
+ @NotNull CompleteReferenceProcessor processor) {
GrExpression qualifier = refExpr.getQualifierExpression();
if (qualifier == null) {
ResolveUtil.treeWalkUp(refExpr, processor, true);
for (PsiElement e = refExpr.getParent(); e != null; e = e.getParent()) {
if (e instanceof GrClosableBlock) {
- ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, (GrClosableBlock)e);
+ ResolveState state = ResolveState.initial().put(ResolverProcessor.RESOLVE_CONTEXT, e);
for (ClosureMissingMethodContributor contributor : ClosureMissingMethodContributor.EP_NAME.getExtensions()) {
contributor.processMembers((GrClosableBlock)e, processor, refExpr, state);
}
}
}
- qualifier = PsiImplUtil.getRuntimeQualifier(refExpr);
- if (qualifier != null) {
- getVariantsFromQualifier(refExpr, processor, qualifier);
+ GrExpression runtimeQualifier = PsiImplUtil.getRuntimeQualifier(refExpr);
+ if (runtimeQualifier != null) {
+ getVariantsFromQualifier(refExpr, processor, runtimeQualifier);
}
getBindings(refExpr, processor);
@@ -170,7 +174,8 @@
ResolveUtil.processCategoryMembers(refExpr, processor, ResolveState.initial());
}
- private static void getBindings(final GrReferenceExpression refExpr, final CompleteReferenceProcessor processor) {
+ private static void getBindings(@NotNull final GrReferenceExpression refExpr,
+ @NotNull final CompleteReferenceProcessor processor) {
final PsiClass containingClass = PsiTreeUtil.getParentOfType(refExpr, PsiClass.class);
if (containingClass != null) return;
@@ -202,11 +207,13 @@
}
}
- private static void getVariantsFromQualifierForSpreadOperator(GrReferenceExpression refExpr,
- ResolverProcessor processor,
- GrExpression qualifier) {
+ private static void getVariantsFromQualifierForSpreadOperator(@NotNull GrReferenceExpression refExpr,
+ @NotNull ResolverProcessor processor,
+ @NotNull GrExpression qualifier) {
final PsiType spreadType = ClosureParameterEnhancer.findTypeForIteration(qualifier, refExpr);
- getVariantsFromQualifierType(refExpr, processor, spreadType, refExpr.getProject());
+ if (spreadType != null) {
+ getVariantsFromQualifierType(refExpr, processor, spreadType, refExpr.getProject());
+ }
}
@NotNull
@@ -219,7 +226,8 @@
}
@Nullable
- public static LookupElementBuilder createPropertyLookupElement(@NotNull PsiMethod accessor, @Nullable GroovyResolveResult resolveResult,
+ public static LookupElementBuilder createPropertyLookupElement(@NotNull PsiMethod accessor,
+ @Nullable GroovyResolveResult resolveResult,
@Nullable PrefixMatcher matcher) {
String propName;
PsiType propType;
@@ -259,25 +267,26 @@
return builder;
}
+ @NotNull
private static GroovyResolveResult generatePropertyResolveResult(@NotNull String name,
@NotNull PsiMethod method,
@Nullable PsiType type,
@Nullable GroovyResolveResult resolveResult) {
- if (type == null) {
- type = TypesUtil.getJavaLangObject(method);
- }
+ PsiType nonNullType = type != null ? type : TypesUtil.getJavaLangObject(method);
- final GrPropertyForCompletion field = new GrPropertyForCompletion(method, name, type);
+ final GrPropertyForCompletion field = new GrPropertyForCompletion(method, name, nonNullType);
if (resolveResult != null) {
return new GroovyResolveResultImpl(field, resolveResult.getCurrentFileResolveContext(), resolveResult.getSpreadState(),
- resolveResult.getSubstitutor(), resolveResult.isAccessible(), resolveResult.isStaticsOK(), false);
+ resolveResult.getSubstitutor(), resolveResult.isAccessible(), resolveResult.isStaticsOK());
}
else {
return new GroovyResolveResultImpl(field, true);
}
}
- private static void getVariantsFromQualifier(GrReferenceExpression refExpr, ResolverProcessor processor, GrExpression qualifier) {
+ private static void getVariantsFromQualifier(@NotNull GrReferenceExpression refExpr,
+ @NotNull ResolverProcessor processor,
+ @NotNull GrExpression qualifier) {
Project project = qualifier.getProject();
PsiType qualifierType = qualifier.getType();
final ResolveState state = ResolveState.initial();
@@ -318,19 +327,25 @@
}
}
- public static Set<String> getVariantsWithSameQualifier(PrefixMatcher matcher, @Nullable GrExpression qualifier, GrReferenceExpression refExpr) {
+ @NotNull
+ public static Set<String> getVariantsWithSameQualifier(@NotNull PrefixMatcher matcher,
+ @Nullable GrExpression qualifier,
+ @NotNull GrReferenceExpression refExpr) {
if (qualifier != null && qualifier.getType() != null) return Collections.emptySet();
final PsiElement scope = PsiTreeUtil.getParentOfType(refExpr, GrMember.class, PsiFile.class);
Set<String> result = new LinkedHashSet<String>();
- addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result);
+ if (scope != null) {
+ addVariantsWithSameQualifier(matcher, scope, refExpr, qualifier, result);
+ }
return result;
}
- private static void addVariantsWithSameQualifier(PrefixMatcher matcher, PsiElement element,
- GrReferenceExpression patternExpression,
+ private static void addVariantsWithSameQualifier(@NotNull PrefixMatcher matcher,
+ @NotNull PsiElement element,
+ @NotNull GrReferenceExpression patternExpression,
@Nullable GrExpression patternQualifier,
- Set<String> result) {
+ @NotNull Set<String> result) {
if (element instanceof GrReferenceExpression && element != patternExpression && !PsiUtil.isLValue((GroovyPsiElement)element)) {
final GrReferenceExpression refExpr = (GrReferenceExpression)element;
final String refName = refExpr.getReferenceName();
@@ -356,10 +371,10 @@
}
}
- private static void getVariantsFromQualifierType(GrReferenceExpression refExpr,
- ResolverProcessor processor,
- PsiType qualifierType,
- Project project) {
+ private static void getVariantsFromQualifierType(@NotNull GrReferenceExpression refExpr,
+ @NotNull ResolverProcessor processor,
+ @NotNull PsiType qualifierType,
+ @NotNull Project project) {
final ResolveState state = ResolveState.initial();
if (qualifierType instanceof PsiClassType) {
PsiClassType.ClassResolveResult result = ((PsiClassType)qualifierType).resolveGenerics();
@@ -370,7 +385,9 @@
}
else if (qualifierType instanceof PsiArrayType) {
final GrTypeDefinition arrayClass = GroovyPsiManager.getInstance(project).getArrayClass(((PsiArrayType)qualifierType).getComponentType());
- if (!arrayClass.processDeclarations(processor, state, null, refExpr)) return;
+ if (arrayClass != null) {
+ if (!arrayClass.processDeclarations(processor, state, null, refExpr)) return;
+ }
}
else if (qualifierType instanceof PsiIntersectionType) {
for (PsiType conjunct : ((PsiIntersectionType)qualifierType).getConjuncts()) {
@@ -381,7 +398,8 @@
ResolveUtil.processNonCodeMembers(qualifierType, processor, refExpr, state);
}
- private static Set<String> addAllRestrictedProperties(GrReferenceExpression place) {
+ @NotNull
+ private static Set<String> addAllRestrictedProperties(@NotNull GrReferenceExpression place) {
if (place.getQualifier() != null) {
return Collections.emptySet();
}
@@ -397,7 +415,7 @@
return propertyNames;
}
- private static boolean isMap(GrReferenceExpression place) {
+ private static boolean isMap(@NotNull GrReferenceExpression place) {
final PsiType qType = GrReferenceResolveUtil.getQualifierType(place);
return InheritanceUtil.isInheritor(qType, CommonClassNames.JAVA_UTIL_MAP);
}
@@ -425,7 +443,10 @@
private List<GroovyResolveResult> myInapplicable;
private GroovyResolveResult[] myInapplicableResults;
- protected CompleteReferenceProcessor(GrReferenceExpression place, Consumer<LookupElement> consumer, @NotNull PrefixMatcher matcher, CompletionParameters parameters) {
+ protected CompleteReferenceProcessor(@NotNull GrReferenceExpression place,
+ @NotNull Consumer<LookupElement> consumer,
+ @NotNull PrefixMatcher matcher,
+ @NotNull CompletionParameters parameters) {
super(null, EnumSet.allOf(ResolveKind.class), place, PsiType.EMPTY_ARRAY);
myConsumer = consumer;
myMatcher = matcher;
@@ -442,7 +463,7 @@
mySubstitutorComputer = new SubstitutorComputer(thisType, PsiType.EMPTY_ARRAY, PsiType.EMPTY_ARRAY, true, place, place.getParent());
}
- private static boolean shouldSkipPackages(GrReferenceExpression place) {
+ private static boolean shouldSkipPackages(@NotNull GrReferenceExpression place) {
if (PsiImplUtil.getRuntimeQualifier(place) != null) {
return false;
}
@@ -501,7 +522,7 @@
result = new GroovyResolveResultImpl(element, result.getCurrentFileResolveContext(), result.getSpreadState(),
result.getSubstitutor(), result.isAccessible(), result.isStaticsOK(),
- result.isInvokedOnProperty());
+ result.isInvokedOnProperty(), result.isValidResult());
}
if (myFieldPointerOperator && !(element instanceof PsiVariable)) {
@@ -527,7 +548,7 @@
}
}
- private void processPropertyFromField(GrField field, GroovyResolveResult resolveResult) {
+ private void processPropertyFromField(@NotNull GrField field, @NotNull GroovyResolveResult resolveResult) {
if (field.getGetters().length != 0 || field.getSetter() != null || !myPropertyNames.add(field.getName()) || myIsMap) return;
for (LookupElement element : GroovyCompletionUtil.createLookupElements(resolveResult, false, myMatcher, null)) {
@@ -536,7 +557,7 @@
}
- private void processProperty(PsiMethod method, GroovyResolveResult resolveResult) {
+ private void processProperty(@NotNull PsiMethod method, @NotNull GroovyResolveResult resolveResult) {
if (myIsMap) return;
final LookupElementBuilder lookup = createPropertyLookupElement(method, resolveResult, myMatcher);
if (lookup != null) {
@@ -549,7 +570,7 @@
}
}
- private void processListenerProperties(PsiMethod method) {
+ private void processListenerProperties(@NotNull PsiMethod method) {
if (!method.getName().startsWith("add") || method.getParameterList().getParametersCount() != 1) return;
final PsiParameter parameter = method.getParameterList().getParameters()[0];
@@ -602,6 +623,7 @@
return list.toArray(new GroovyResolveResult[list.size()]);
}
+ @NotNull
private List<GroovyResolveResult> getInapplicableResults() {
if (myInapplicable == null) return Collections.emptyList();
return myInapplicable;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java
index 0f4b844..5382801 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrAssignmentExpressionImpl.java
@@ -19,7 +19,6 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiType;
import com.intellij.psi.impl.source.resolve.ResolveCache;
@@ -27,7 +26,6 @@
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.NullableFunction;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
@@ -39,34 +37,19 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrIndexProperty;
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.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryExpressionTypeCalculators;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryExpressionUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryFacade;
/**
* @author ilyas
*/
public class GrAssignmentExpressionImpl extends GrExpressionImpl implements GrAssignmentExpression {
- private static final Function<GrAssignmentExpressionImpl, PsiType> TYPE_CALCULATOR =
- new NullableFunction<GrAssignmentExpressionImpl, PsiType>() {
- @Override
- public PsiType fun(GrAssignmentExpressionImpl assignment) {
- final GroovyResolveResult[] results = assignment.multiResolve(false);
+ private GrBinaryFacade getFacade() {
+ return myFacade;
+ }
- if (results.length == 0) {
- final GrExpression rValue = assignment.getRValue();
- return rValue == null ? null : rValue.getType();
- }
-
-
- PsiType returnType = null;
- final PsiManager manager = assignment.getManager();
- for (GroovyResolveResult result : results) {
- final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(result, assignment, new PsiType[]{getRValueType(assignment)});
- returnType = TypesUtil.getLeastUpperBoundNullable(returnType, substituted, manager);
- }
- return returnType;
- }
- };
public GrAssignmentExpressionImpl(@NotNull ASTNode node) {
super(node);
}
@@ -89,10 +72,12 @@
return null;
}
+ @NotNull
public IElementType getOperationTokenType() {
return getOperationToken().getNode().getElementType();
}
+ @NotNull
public PsiElement getOperationToken() {
return findNotNullChildByType(TokenSets.ASSIGN_OP_SET);
}
@@ -119,7 +104,6 @@
@Override
public TextRange getRangeInElement() {
final PsiElement token = getOperationToken();
- assert token != null;
final int offset = token.getStartOffsetInParent();
return new TextRange(offset, offset + token.getTextLength());
}
@@ -169,38 +153,78 @@
return this;
}
- private static final ResolveCache.PolyVariantResolver<GrAssignmentExpressionImpl> RESOLVER =
- new ResolveCache.PolyVariantResolver<GrAssignmentExpressionImpl>() {
- @NotNull
- @Override
- public GroovyResolveResult[] resolve(@NotNull GrAssignmentExpressionImpl assignmentExpression, boolean incompleteCode) {
- final IElementType opType = assignmentExpression.getOperationTokenType();
- if (opType == null || opType == GroovyTokenTypes.mASSIGN) return GroovyResolveResult.EMPTY_ARRAY;
+ private final GrBinaryFacade myFacade = new GrBinaryFacade() {
+ @NotNull
+ @Override
+ public GrExpression getLeftOperand() {
+ return getLValue();
+ }
- final GrExpression lValue = assignmentExpression.getLValue();
- final PsiType lType;
- if (lValue instanceof GrIndexProperty) {
+ @Nullable
+ @Override
+ public GrExpression getRightOperand() {
+ return getRValue();
+ }
+
+ @NotNull
+ @Override
+ public IElementType getOperationTokenType() {
+ return GrAssignmentExpressionImpl.this.getOperationTokenType();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getOperationToken() {
+ return GrAssignmentExpressionImpl.this.getOperationToken();
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
+ return GrAssignmentExpressionImpl.this.multiResolve(false);
+ }
+
+ @NotNull
+ @Override
+ public GrExpression getPsiElement() {
+ return GrAssignmentExpressionImpl.this;
+ }
+ };
+
+
+ private static final ResolveCache.PolyVariantResolver<GrAssignmentExpressionImpl> RESOLVER = new ResolveCache.PolyVariantResolver<GrAssignmentExpressionImpl>() {
+ @NotNull
+ @Override
+ public GroovyResolveResult[] resolve(@NotNull GrAssignmentExpressionImpl assignmentExpression, boolean incompleteCode) {
+ final IElementType opType = assignmentExpression.getOperationTokenType();
+ if (opType == GroovyTokenTypes.mASSIGN) return GroovyResolveResult.EMPTY_ARRAY;
+
+ final GrExpression lValue = assignmentExpression.getLValue();
+ final PsiType lType;
+ if (lValue instanceof GrIndexProperty) {
/*
now we have something like map[i] += 2. It equals to map.putAt(i, map.getAt(i).plus(2))
by default map[i] resolves to putAt, but we need getAt(). so this hack is for it =)
*/
- lType = ((GrIndexProperty)lValue).getGetterType();
- }
- else {
- lType = lValue.getType();
- }
- if (lType == null) return GroovyResolveResult.EMPTY_ARRAY;
-
- PsiType rType = getRValueType(assignmentExpression);
-
- final IElementType operatorToken = TokenSets.ASSIGNMENTS_TO_OPERATORS.get(opType);
- return TypesUtil.getOverloadedOperatorCandidates(lType, operatorToken, lValue, new PsiType[]{rType});
+ lType = ((GrIndexProperty)lValue).getGetterType();
}
- };
+ else {
+ lType = lValue.getType();
+ }
+ if (lType == null) return GroovyResolveResult.EMPTY_ARRAY;
- @Nullable
- private static PsiType getRValueType(GrAssignmentExpressionImpl assignmentExpression) {
- final GrExpression rightOperand = assignmentExpression.getRValue();
- return rightOperand == null ? null : rightOperand.getType();
- }
+ PsiType rType = GrBinaryExpressionUtil.getRightType(assignmentExpression.getFacade());
+
+ final IElementType operatorToken = TokenSets.ASSIGNMENTS_TO_OPERATORS.get(opType);
+ return TypesUtil.getOverloadedOperatorCandidates(lType, operatorToken, lValue, new PsiType[]{rType});
+ }
+ };
+
+ private static final Function<GrAssignmentExpressionImpl, PsiType> TYPE_CALCULATOR = new Function<GrAssignmentExpressionImpl, PsiType>() {
+ @Override
+ public PsiType fun(GrAssignmentExpressionImpl expression) {
+ final Function<GrBinaryFacade, PsiType> calculator = GrBinaryExpressionTypeCalculators.getTypeCalculator(expression.getFacade());
+ return calculator.fun(expression.getFacade());
+ }
+ };
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrBinaryExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrBinaryExpressionImpl.java
index bce762c..4f6487d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrBinaryExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrBinaryExpressionImpl.java
@@ -35,42 +35,83 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
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.resolve.ResolveUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryExpressionTypeCalculators;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryFacade;
/**
* @author ilyas
*/
public abstract class GrBinaryExpressionImpl extends GrExpressionImpl implements GrBinaryExpression {
- private static final ResolveCache.PolyVariantResolver<GrBinaryExpressionImpl> RESOLVER =
- new ResolveCache.PolyVariantResolver<GrBinaryExpressionImpl>() {
- @NotNull
- @Override
- public GroovyResolveResult[] resolve(@NotNull GrBinaryExpressionImpl binary, boolean incompleteCode) {
- final IElementType opType = binary.getOperationTokenType();
+ private static final ResolveCache.PolyVariantResolver<GrBinaryExpressionImpl> RESOLVER = new ResolveCache.PolyVariantResolver<GrBinaryExpressionImpl>() {
+ @NotNull
+ @Override
+ public GroovyResolveResult[] resolve(@NotNull GrBinaryExpressionImpl binary, boolean incompleteCode) {
+ final IElementType opType = binary.getOperationTokenType();
- final GrExpression left = binary.getLeftOperand();
- final PsiType lType = left.getType();
- if (lType == null) return GroovyResolveResult.EMPTY_ARRAY;
+ final PsiType lType = binary.getLeftType();
+ if (lType == null) return GroovyResolveResult.EMPTY_ARRAY;
- PsiType rType = getRightType(binary);
- return TypesUtil.getOverloadedOperatorCandidates(lType, opType, binary, new PsiType[]{rType}, incompleteCode);
- }
- };
+ PsiType rType = binary.getRightType();
+ return TypesUtil.getOverloadedOperatorCandidates(lType, opType, binary, new PsiType[]{rType}, incompleteCode);
+ }
+ };
+
+ private static final Function<GrBinaryExpressionImpl, PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
+ @Override
+ public PsiType fun(GrBinaryExpressionImpl expression) {
+ return GrBinaryExpressionTypeCalculators.getTypeCalculator(expression.getFacade()).fun(expression.getFacade());
+ }
+ };
+
+ private final GrBinaryFacade myFacade = new GrBinaryFacade() {
+ @NotNull
+ @Override
+ public GrExpression getLeftOperand() {
+ return GrBinaryExpressionImpl.this.getLeftOperand();
+ }
+
+ @Nullable
+ @Override
+ public GrExpression getRightOperand() {
+ return GrBinaryExpressionImpl.this.getRightOperand();
+ }
+
+ @NotNull
+ @Override
+ public IElementType getOperationTokenType() {
+ return GrBinaryExpressionImpl.this.getOperationTokenType();
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getOperationToken() {
+ return GrBinaryExpressionImpl.this.getOperationToken();
+ }
+
+ @NotNull
+ @Override
+ public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
+ return GrBinaryExpressionImpl.this.multiResolve(incompleteCode);
+ }
+
+ @NotNull
+ @Override
+ public GrExpression getPsiElement() {
+ return GrBinaryExpressionImpl.this;
+ }
+ };
@Nullable
- private static PsiType getRightType(GrBinaryExpressionImpl binary) {
- final GrExpression rightOperand = binary.getRightOperand();
+ protected PsiType getRightType() {
+ final GrExpression rightOperand = getRightOperand();
return rightOperand == null ? null : rightOperand.getType();
}
- private static final Function<GrBinaryExpressionImpl,PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
- @Nullable
- @Override
- public PsiType fun(GrBinaryExpressionImpl binary) {
- return binary.calcType();
- }
- };
+ @Nullable
+ protected PsiType getLeftType() {
+ return getLeftOperand().getType();
+ }
public GrBinaryExpressionImpl(@NotNull ASTNode node) {
super(node);
@@ -82,20 +123,6 @@
}
@Nullable
- public PsiType getLeftOperandType() {
- GrExpression leftOperand = getLeftOperand();
- return leftOperand instanceof GrBinaryExpressionImpl ? ((GrBinaryExpressionImpl)leftOperand).calcType() : leftOperand.getType();
- }
-
- @Nullable
- public PsiType getRightOperandType() {
- GrExpression rightOperand = getRightOperand();
- if (rightOperand == null) return null;
- if (rightOperand instanceof GrBinaryExpressionImpl) return ((GrBinaryExpressionImpl)rightOperand).calcType();
- return rightOperand.getType();
- }
-
- @Nullable
public GrExpression getRightOperand() {
final PsiElement last = getLastChild();
return last instanceof GrExpression ? (GrExpression)last : null;
@@ -129,23 +156,6 @@
return TypeInferenceHelper.getCurrentContext().getExpressionType(this, TYPE_CALCULATOR);
}
- @Nullable
- protected Function<GrBinaryExpressionImpl,PsiType> getTypeCalculator() {
- return null;
- }
-
- protected PsiType calcType() {
- final Function<GrBinaryExpressionImpl, PsiType> typeCalculator = getTypeCalculator();
- if (typeCalculator != null) {
- final PsiType result = typeCalculator.fun(this);
- if (result != null) return result;
- }
-
- final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(multiResolve(false));
- final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, this, new PsiType[]{getRightType(this)});
- return TypesUtil.boxPrimitiveType(substituted, getManager(), getResolveScope());
- }
-
@Override
public PsiElement getElement() {
return this;
@@ -200,4 +210,8 @@
return this;
}
+ private GrBinaryFacade getFacade() {
+ return myFacade;
+ }
+
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrMethodCallImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrMethodCallImpl.java
index 194bc7e..b85d3a6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrMethodCallImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrMethodCallImpl.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.
@@ -22,6 +22,7 @@
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.util.Function;
+import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
@@ -72,12 +73,12 @@
return ((GrReferenceExpressionImpl)invoked).getCallVariants(upToArgument);
}
- @Nullable
+ @NotNull
public GrExpression getInvokedExpression() {
for (PsiElement cur = this.getFirstChild(); cur != null; cur = cur.getNextSibling()) {
if (cur instanceof GrExpression) return (GrExpression)cur;
}
- return null;
+ throw new IncorrectOperationException("invoked expression must not be null");
}
public PsiMethod resolveMethod() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java
index cfc1db1..c6c3b0a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrNewExpressionImpl.java
@@ -17,9 +17,12 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions;
import com.intellij.lang.ASTNode;
+import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
+import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.util.InheritanceUtil;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.NullableFunction;
@@ -86,6 +89,16 @@
}
};
+ private static final ResolveCache.PolyVariantResolver<MyFakeReference> RESOLVER = new ResolveCache.PolyVariantResolver<MyFakeReference>() {
+ @NotNull
+ @Override
+ public GroovyResolveResult[] resolve(@NotNull MyFakeReference reference, boolean incompleteCode) {
+ return reference.getElement().resolveImpl(incompleteCode);
+ }
+ };
+
+ private final MyFakeReference myFakeReference = new MyFakeReference();
+
public GrNewExpressionImpl(@NotNull ASTNode node) {
super(node);
}
@@ -208,6 +221,14 @@
@NotNull
@Override
public GroovyResolveResult[] multiResolve(boolean incompleteCode) {
+ if (getArrayCount() > 0 || getReferenceElement() == null) {
+ return GroovyResolveResult.EMPTY_ARRAY;
+ }
+
+ return TypeInferenceHelper.getCurrentContext().multiResolve(myFakeReference, incompleteCode, RESOLVER);
+ }
+
+ private GroovyResolveResult[] resolveImpl(boolean incompleteCode) {
GrCodeReferenceElement ref = getReferenceElement();
if (ref == null) return GroovyResolveResult.EMPTY_ARRAY;
@@ -259,4 +280,60 @@
}
return null;
}
+
+ private class MyFakeReference implements PsiPolyVariantReference {
+ @NotNull
+ @Override
+ public ResolveResult[] multiResolve(boolean incompleteCode) {
+ return GrNewExpressionImpl.this.multiResolve(incompleteCode);
+ }
+
+ @Override
+ public GrNewExpressionImpl getElement() {
+ return GrNewExpressionImpl.this;
+ }
+
+ @Override
+ public TextRange getRangeInElement() {
+ return TextRange.EMPTY_RANGE;
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ return resolveMethod();
+ }
+
+ @NotNull
+ @Override
+ public String getCanonicalText() {
+ return "new expression";
+ }
+
+ @Override
+ public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
+ throw new UnsupportedOperationException("unsupported!");
+ }
+
+ @Override
+ public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
+ throw new UnsupportedOperationException("unsupported!");
+ }
+
+ @Override
+ public boolean isReferenceTo(PsiElement element) {
+ return getManager().areElementsEquivalent(element, resolve());
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+ return ArrayUtil.EMPTY_OBJECT_ARRAY;
+ }
+
+ @Override
+ public boolean isSoft() {
+ return false;
+ }
+ }
}
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 268f080..3b19a68 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
@@ -711,7 +711,7 @@
}
final PsiType inferred = getInferredTypes(refExpr, resolved);
- if (inferred == null || PsiType.NULL.equals(inferred)) {
+ if (inferred == null) {
if (nominal == null) {
//inside nested closure we could still try to infer from variable initializer. Not sound, but makes sense
if (resolved instanceof GrVariable) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveUtil.java
index 44e3990..acdd899 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/GrReferenceResolveUtil.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,6 +21,7 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.untypedUnresolvedAccess.GrUnresolvedAccessInspection;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
@@ -225,7 +226,7 @@
}
@Nullable
- public static PsiType getQualifierType(GrReferenceExpression ref) {
+ public static PsiType getQualifierType(@NotNull GrReferenceExpression ref) {
final GrExpression rtQualifier = PsiImplUtil.getRuntimeQualifier(ref);
if (rtQualifier != null) {
return rtQualifier.getType();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
index ad3219c..e1d565a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/TypesUtil.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.
@@ -36,6 +36,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.SpreadState;
@@ -44,7 +45,6 @@
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotationMemberValue;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrSignature;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureImpl;
@@ -88,27 +88,6 @@
private TypesUtil() {
}
- @Nullable
- public static PsiType getNumericResultType(GrBinaryExpression binaryExpression) {
- PsiType lType = binaryExpression.getLeftOperand().getType();
- final GrExpression rop = binaryExpression.getRightOperand();
- PsiType rType = rop == null ? null : rop.getType();
- if (lType == null || rType == null) return null;
- return getLeastUpperBoundForNumericType(lType, rType);
- }
-
- @Nullable
- private static PsiType getLeastUpperBoundForNumericType(@NotNull PsiType lType, @NotNull PsiType rType) {
- String lCanonical = lType.getCanonicalText();
- String rCanonical = rType.getCanonicalText();
- if (JAVA_LANG_FLOAT.equals(lCanonical)) lCanonical = JAVA_LANG_DOUBLE;
- if (JAVA_LANG_FLOAT.equals(rCanonical)) rCanonical = JAVA_LANG_DOUBLE;
- if (TYPE_TO_RANK.containsKey(lCanonical) && TYPE_TO_RANK.containsKey(rCanonical)) {
- return TYPE_TO_RANK.get(lCanonical) > TYPE_TO_RANK.get(rCanonical) ? lType : rType;
- }
- return null;
- }
-
@NotNull
public static GroovyResolveResult[] getOverloadedOperatorCandidates(@NotNull PsiType thisType,
IElementType tokenType,
@@ -182,6 +161,7 @@
ourOperationsToOperatorNames.put(mSTAR_STAR, "power");
ourOperationsToOperatorNames.put(COMPOSITE_LSHIFT_SIGN, "leftShift");
ourOperationsToOperatorNames.put(COMPOSITE_RSHIFT_SIGN, "rightShift");
+ ourOperationsToOperatorNames.put(GroovyElementTypes.COMPOSITE_TRIPLE_SHIFT_SIGN, "rightShiftUnsigned");
ourOperationsToOperatorNames.put(mEQUAL, "equals");
ourOperationsToOperatorNames.put(mNOT_EQUAL, "equals");
@@ -380,6 +360,12 @@
if (result != null && result.booleanValue()) return true;
}
+ if (rType instanceof GrClosureType) {
+ if (canMakeClosureRaw(lType)) {
+ rType = ((GrClosureType)rType).rawType();
+ }
+ }
+
if (TypeConversionUtil.isAssignable(lType, rType)) {
return true;
}
@@ -387,6 +373,19 @@
return false;
}
+ private static boolean canMakeClosureRaw(PsiType type) {
+ if (!(type instanceof PsiClassType)) return true;
+
+ final PsiType[] parameters = ((PsiClassType)type).getParameters();
+
+ if (parameters.length != 1) return true;
+
+ final PsiType parameter = parameters[0];
+ if (parameter instanceof PsiWildcardType) return true;
+
+ return false;
+ }
+
@Nullable
private static Boolean isAssignableForNativeTypes(@NotNull PsiType lType,
@NotNull PsiClassType rType,
@@ -509,7 +508,7 @@
if (components1.length == 0) return genNewListBy(type2, manager);
if (components2.length == 0) return genNewListBy(type1, manager);
- PsiType[] components3 = new PsiType[Math.min(components1.length, components2.length)];
+ PsiType[] components3 = PsiType.createArray(Math.min(components1.length, components2.length));
for (int i = 0; i < components3.length; i++) {
PsiType c1 = components1[i];
PsiType c2 = components2[i];
@@ -564,8 +563,6 @@
CommonClassNames.JAVA_LANG_STRING.equals(type1.getInternalCanonicalText())) {
return type1;
}
- final PsiType result = getLeastUpperBoundForNumericType(type1, type2);
- if (result != null) return result;
return GenericsUtil.getLeastUpperBound(type1, type2, manager);
}
@@ -852,7 +849,7 @@
public PsiType fun(GrAnnotationMemberValue value) {
return inferAnnotationMemberValueType(value);
}
- }, new PsiType[initializers.length]);
+ }, PsiType.createArray(initializers.length));
return new GrTupleType(types, JavaPsiFacade.getInstance(value.getProject()), value.getResolveScope());
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java
index 542f682..22f124b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrAdditiveExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,14 +17,8 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
-import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
/**
* @author ilyas
@@ -35,24 +29,8 @@
super(node);
}
- private static boolean isStringType(@Nullable PsiType type) {
- return type != null && (type.equalsToText(CommonClassNames.JAVA_LANG_STRING) || type.equalsToText(GroovyCommonClassNames.GROOVY_LANG_GSTRING));
- }
-
public String toString() {
return "Additive expression";
}
- protected PsiType calcType() {
- final PsiType numeric = TypesUtil.getNumericResultType(this);
- if (numeric != null) return numeric;
-
- if (getOperationTokenType() == GroovyTokenTypes.mPLUS) {
- if (isStringType(getLeftOperandType()) || isStringType(getRightOperandType())) {
- return getTypeByFQName(CommonClassNames.JAVA_LANG_STRING);
- }
- }
-
- return super.calcType();
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrMultiplicativeExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrMultiplicativeExpressionImpl.java
index 82e5218..127eaf2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrMultiplicativeExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrMultiplicativeExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,43 +17,13 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.PsiType;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
-import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
-
-import static com.intellij.psi.CommonClassNames.JAVA_LANG_DOUBLE;
-import static com.intellij.psi.CommonClassNames.JAVA_LANG_FLOAT;
/**
* @author ilyas
*/
public class GrMultiplicativeExpressionImpl extends GrBinaryExpressionImpl {
- private static final Function<GrBinaryExpressionImpl,PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
- @Nullable
- @Override
- public PsiType fun(GrBinaryExpressionImpl binary) {
- PsiType lType = binary.getLeftOperand().getType();
- GrExpression right = binary.getRightOperand();
- PsiType rType = right == null ? null : right.getType();
-
- if (binary.getOperationTokenType() == GroovyTokenTypes.mDIV) {
- if (isDoubleOrFloat(lType) || isDoubleOrFloat(rType)) {
- return binary.getTypeByFQName(JAVA_LANG_DOUBLE);
- }
- if (TypesUtil.isNumericType(lType) && TypesUtil.isNumericType(rType)) {
- return binary.getTypeByFQName(GroovyCommonClassNames.JAVA_MATH_BIG_DECIMAL);
- }
- }
-
- return TypesUtil.getNumericResultType(binary);
- }
- };
public GrMultiplicativeExpressionImpl(@NotNull ASTNode node) {
super(node);
@@ -62,13 +32,4 @@
public String toString() {
return "Multiplicative expression";
}
-
- @Override
- protected Function<GrBinaryExpressionImpl, PsiType> getTypeCalculator() {
- return TYPE_CALCULATOR;
- }
-
- private static boolean isDoubleOrFloat(PsiType type) {
- return type != null && (type.equalsToText(JAVA_LANG_DOUBLE) || type.equalsToText(JAVA_LANG_FLOAT));
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPowerExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPowerExpressionImpl.java
index 0056670..a005ea1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPowerExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrPowerExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrRangeExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrRangeExpressionImpl.java
index 0acf180..5e05974 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrRangeExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrRangeExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,16 +16,12 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.PsiType;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.arithmetic.GrRangeExpression;
-import org.jetbrains.plugins.groovy.lang.psi.impl.GrRangeType;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
+
/**
* @author ilyas
*/
@@ -35,11 +31,6 @@
super(node);
}
- @Override
- protected Function<GrBinaryExpressionImpl, PsiType> getTypeCalculator() {
- return TYPES_CALCULATOR;
- }
-
public String toString() {
return "Range expression";
}
@@ -49,16 +40,4 @@
visitor.visitRangeExpression(this);
}
- private static final Function<GrBinaryExpressionImpl, PsiType> TYPES_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
- @Override
- public PsiType fun(GrBinaryExpressionImpl range) {
- final JavaPsiFacade facade = JavaPsiFacade.getInstance(range.getProject());
-
- final GrExpression right = range.getRightOperand();
- final PsiType rtype = right == null ? null : right.getType();
- final PsiType ltype = range.getLeftOperand().getType();
-
- return new GrRangeType(range.getResolveScope(), facade, ltype, rtype);
- }
- };
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrShiftExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrShiftExpressionImpl.java
index 0c28edd..e0230ce 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrShiftExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrShiftExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,11 +17,7 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiType;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
/**
@@ -29,24 +25,6 @@
*/
public class GrShiftExpressionImpl extends GrBinaryExpressionImpl {
- private static class MyTypeCalculator implements Function<GrBinaryExpressionImpl, PsiType> {
- private static final Function<GrBinaryExpressionImpl, PsiType> INSTANCE = new MyTypeCalculator();
-
- @Nullable
- @Override
- public PsiType fun(GrBinaryExpressionImpl binary) {
- PsiType lopType = binary.getLeftOperand().getType();
- if (lopType == null) return null;
- if (lopType.equalsToText(CommonClassNames.JAVA_LANG_BYTE) ||
- lopType.equalsToText(CommonClassNames.JAVA_LANG_CHARACTER) ||
- lopType.equalsToText(CommonClassNames.JAVA_LANG_SHORT) ||
- lopType.equalsToText(CommonClassNames.JAVA_LANG_INTEGER)) {
- return binary.getTypeByFQName(CommonClassNames.JAVA_LANG_INTEGER);
- }
- return null;
- }
- }
-
public GrShiftExpressionImpl(@NotNull ASTNode node) {
super(node);
}
@@ -55,8 +33,4 @@
return "Shift expression";
}
- @Override
- protected Function<GrBinaryExpressionImpl, PsiType> getTypeCalculator() {
- return MyTypeCalculator.INSTANCE;
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java
index 3fd53f4..25038b6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/arithmetic/GrUnaryExpressionImpl.java
@@ -18,10 +18,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.PsiType;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.ResolveCache;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.ArrayUtil;
@@ -29,17 +26,17 @@
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
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.GrUnaryExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
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.statements.expressions.GrExpressionImpl;
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.PsiUtil;
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
/**
@@ -51,41 +48,63 @@
@Nullable
@Override
public PsiType fun(GrUnaryExpressionImpl unary) {
+ final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(unary.multiResolve(false));
+
+ if (isIncDecNumber(resolveResult)) {
+ return unary.getOperand().getType();
+ }
+
+ final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, unary, PsiType.EMPTY_ARRAY);
+ if (substituted != null) {
+ return substituted;
+ }
+
GrExpression operand = unary.getOperand();
if (operand == null) return null;
- PsiType opType = operand.getType();
- if (opType == null) return null;
-
- final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(unary.multiResolve(false));
- final PsiType substituted = ResolveUtil.extractReturnTypeFromCandidate(resolveResult, unary, PsiType.EMPTY_ARRAY);
- if (substituted != null) {
- return TypesUtil.boxPrimitiveType(substituted, unary.getManager(), unary.getResolveScope());
+ final PsiType type = operand.getType();
+ if (TypesUtil.isNumericType(type)) {
+ return type;
}
- IElementType opToken = unary.getOperationTokenType();
- if (opToken == GroovyTokenTypes.mBNOT && opType.equalsToText(CommonClassNames.JAVA_LANG_STRING)) {
- return unary.getTypeByFQName(GroovyCommonClassNames.JAVA_UTIL_REGEX_PATTERN);
- }
+ return null;
+ }
- return opType;
+ //hack for DGM.next(Number):Number
+ private boolean isIncDecNumber(GroovyResolveResult result) {
+ PsiElement element = result.getElement();
+
+ if (!(element instanceof PsiMethod)) return false;
+
+ final PsiMethod method = element instanceof GrGdkMethod ? ((GrGdkMethod)element).getStaticMethod() : (PsiMethod)element;
+
+ final String name = method.getName();
+ if (!"next".equals(name) && !"previous".equals(name)) return false;
+
+ if (!PsiUtil.isDGMMethod(method)) return false;
+
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ if (parameters.length != 1) return false;
+
+ if (!parameters[0].getType().equalsToText(CommonClassNames.JAVA_LANG_NUMBER)) return false;
+
+ return true;
}
};
- private static final ResolveCache.PolyVariantResolver<GrUnaryExpressionImpl> OUR_RESOLVER =
- new ResolveCache.PolyVariantResolver<GrUnaryExpressionImpl>() {
- @NotNull
- @Override
- public GroovyResolveResult[] resolve(@NotNull GrUnaryExpressionImpl unary, boolean incompleteCode) {
- final GrExpression operand = unary.getOperand();
- if (operand == null) return GroovyResolveResult.EMPTY_ARRAY;
+ private static final ResolveCache.PolyVariantResolver<GrUnaryExpressionImpl> OUR_RESOLVER = new ResolveCache.PolyVariantResolver<GrUnaryExpressionImpl>() {
+ @NotNull
+ @Override
+ public GroovyResolveResult[] resolve(@NotNull GrUnaryExpressionImpl unary, boolean incompleteCode) {
+ final GrExpression operand = unary.getOperand();
+ if (operand == null) return GroovyResolveResult.EMPTY_ARRAY;
- final PsiType type = operand.getType();
- if (type == null) return GroovyResolveResult.EMPTY_ARRAY;
+ final PsiType type = operand.getType();
+ if (type == null) return GroovyResolveResult.EMPTY_ARRAY;
- return TypesUtil.getOverloadedUnaryOperatorCandidates(type, unary.getOperationTokenType(), operand, PsiType.EMPTY_ARRAY);
- }
- };
+ return TypesUtil.getOverloadedUnaryOperatorCandidates(type, unary.getOperationTokenType(), operand, PsiType.EMPTY_ARRAY);
+ }
+ };
public GrUnaryExpressionImpl(@NotNull ASTNode node) {
super(node);
@@ -99,6 +118,7 @@
return TypeInferenceHelper.getCurrentContext().getExpressionType(this, TYPE_CALCULATOR);
}
+ @NotNull
public IElementType getOperationTokenType() {
PsiElement opElement = getOperationToken();
ASTNode node = opElement.getNode();
@@ -106,6 +126,7 @@
return node.getElementType();
}
+ @NotNull
public PsiElement getOperationToken() {
PsiElement opElement = findChildByType(TokenSets.UNARY_OP_SET);
assert opElement != null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrAssignTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrAssignTypeCalculator.java
new file mode 100644
index 0000000..3264948
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrAssignTypeCalculator.java
@@ -0,0 +1,31 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrAssignTypeCalculator implements Function<GrBinaryFacade, PsiType> {
+ public static final GrAssignTypeCalculator INSTANCE = new GrAssignTypeCalculator();
+
+ @Override
+ public PsiType fun(GrBinaryFacade expression) {
+ return GrBinaryExpressionUtil.getRightType(expression);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionTypeCalculator.java
new file mode 100644
index 0000000..87b70d2
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionTypeCalculator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+import com.intellij.util.NullableFunction;
+import org.jetbrains.annotations.Nullable;
+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.impl.PsiImplUtil;
+import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrBinaryExpressionTypeCalculator implements NullableFunction<GrBinaryFacade, PsiType> {
+ public static final Function<GrBinaryFacade, PsiType> INSTANCE = new GrBinaryExpressionTypeCalculator();
+
+ @Override
+ @Nullable
+ public PsiType fun(GrBinaryFacade e) {
+ final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(e.multiResolve(false));
+ if (resolveResult.getElement() != null) {
+ return ResolveUtil.extractReturnTypeFromCandidate(resolveResult, e.getPsiElement(), new PsiType[]{getRightType(e)});
+ }
+ return null;
+ }
+
+ @Nullable
+ protected static PsiType getRightType(GrBinaryFacade e) {
+ final GrExpression rightOperand = e.getRightOperand();
+ return rightOperand == null ? null : rightOperand.getType();
+ }
+
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionTypeCalculators.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionTypeCalculators.java
new file mode 100644
index 0000000..09b834e
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionTypeCalculators.java
@@ -0,0 +1,92 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import com.intellij.psi.tree.IElementType;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+import static org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes.*;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrBinaryExpressionTypeCalculators {
+ private static final Map<IElementType, Function<GrBinaryFacade, PsiType>> MAP = ContainerUtil.newLinkedHashMap();
+
+ static {
+
+ MAP.put(mPLUS, GrNumericBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mPLUS_ASSIGN, GrNumericBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mMINUS, GrNumericBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mMINUS_ASSIGN, GrNumericBinaryExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(mSTAR, GrMultiplicativeExpressionTypeCalculator.INSTANCE);
+ MAP.put(mSTAR_ASSIGN, GrMultiplicativeExpressionTypeCalculator.INSTANCE);
+ MAP.put(mDIV, GrDivExpressionTypeCalculator.INSTANCE);
+ MAP.put(mDIV_ASSIGN, GrDivExpressionTypeCalculator.INSTANCE);
+ MAP.put(mMOD, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mMOD_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(mSTAR_STAR, GrNumericBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mSTAR_STAR_ASSIGN, GrNumericBinaryExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(COMPOSITE_RSHIFT_SIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mSR_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(COMPOSITE_LSHIFT_SIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mSL_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(COMPOSITE_TRIPLE_SHIFT_SIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBSR_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(mRANGE_EXCLUSIVE, GrRangeExpressionTypeCalculator.INSTANCE);
+ MAP.put(mRANGE_INCLUSIVE, GrRangeExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(mBAND, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBAND_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBOR, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBOR_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBXOR, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBXOR_ASSIGN, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mBAND, GrDecimalBinaryExpressionTypeCalculator.INSTANCE);
+ MAP.put(mCOMPARE_TO, GrIntegerTypeCalculator.INSTANCE);
+
+ MAP.put(mLOR, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mLAND, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mEQUAL, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mNOT_EQUAL, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mGT, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mGE, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mLT, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(mLE, GrBooleanExpressionTypeCalculator.INSTANCE);
+ MAP.put(kIN, GrBooleanExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(mREGEX_FIND, GrMatcherTypeCalculator.INSTANCE);
+ MAP.put(mREGEX_MATCH, GrBooleanExpressionTypeCalculator.INSTANCE);
+
+ MAP.put(mASSIGN, GrAssignTypeCalculator.INSTANCE);
+ }
+
+ @NotNull
+ public static Function<GrBinaryFacade, PsiType> getTypeCalculator(GrBinaryFacade e) {
+ final Function<GrBinaryFacade, PsiType> function = MAP.get(e.getOperationTokenType());
+ assert function != null : e.getOperationTokenType();
+ return function;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionUtil.java
new file mode 100644
index 0000000..839e260
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryExpressionUtil.java
@@ -0,0 +1,79 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrBinaryExpressionUtil {
+ @Nullable
+ public static PsiType getRightType(GrBinaryFacade e) {
+ final GrExpression rightOperand = e.getRightOperand();
+ return rightOperand == null ? null : rightOperand.getType();
+ }
+
+ @Nullable
+ public static PsiType getLeftType(GrBinaryFacade e) {
+ return e.getLeftOperand().getType();
+ }
+
+ public static PsiType getDefaultNumericResultType(PsiType ltype, PsiType rtype, GrBinaryFacade e) {
+ if (isBigDecimal(ltype, rtype)) return createBigDecimal(e);
+ if (isFloatOrDouble(ltype, rtype)) return createDouble(e);
+ if (isLong(ltype, rtype)) return createLong(e);
+ return createInteger(e);
+ }
+
+ public static PsiType createDouble(GrBinaryFacade e) {
+ return getTypeByFQName(CommonClassNames.JAVA_LANG_DOUBLE, e);
+ }
+
+ public static PsiType createLong(GrBinaryFacade e) {
+ return getTypeByFQName(CommonClassNames.JAVA_LANG_LONG, e);
+ }
+
+ public static PsiType createInteger(GrBinaryFacade e) {
+ return getTypeByFQName(CommonClassNames.JAVA_LANG_INTEGER, e);
+ }
+
+ public static PsiType createBigDecimal(GrBinaryFacade e) {
+ return getTypeByFQName(GroovyCommonClassNames.JAVA_MATH_BIG_DECIMAL, e);
+ }
+
+ public static boolean isBigDecimal(PsiType lType, PsiType rType) {
+ return lType.equalsToText(GroovyCommonClassNames.JAVA_MATH_BIG_DECIMAL) || rType.equalsToText(GroovyCommonClassNames.JAVA_MATH_BIG_DECIMAL);
+ }
+
+ public static boolean isFloatOrDouble(PsiType ltype, PsiType rtype) {
+ return ltype.equalsToText(CommonClassNames.JAVA_LANG_DOUBLE) || rtype.equalsToText(CommonClassNames.JAVA_LANG_DOUBLE) ||
+ ltype.equalsToText(CommonClassNames.JAVA_LANG_FLOAT) || rtype.equalsToText(CommonClassNames.JAVA_LANG_FLOAT);
+ }
+
+ public static boolean isLong(PsiType ltype, PsiType rtype) {
+ return ltype.equalsToText(CommonClassNames.JAVA_LANG_LONG) || rtype.equalsToText(CommonClassNames.JAVA_LANG_LONG);
+ }
+
+ public static PsiType getTypeByFQName(String fqn, GrBinaryFacade e) {
+ return TypesUtil.createTypeByFQClassName(fqn, e.getPsiElement());
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryFacade.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryFacade.java
new file mode 100644
index 0000000..6d52e60
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBinaryFacade.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 org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public interface GrBinaryFacade {
+
+ @NotNull
+ GrExpression getLeftOperand();
+
+ @Nullable
+ GrExpression getRightOperand();
+
+ @NotNull
+ IElementType getOperationTokenType();
+
+ @NotNull
+ PsiElement getOperationToken();
+
+ @NotNull
+ GroovyResolveResult[] multiResolve(final boolean incompleteCode);
+
+ @NotNull
+ GrExpression getPsiElement();
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBooleanExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBooleanExpressionTypeCalculator.java
new file mode 100644
index 0000000..863bba5
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrBooleanExpressionTypeCalculator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrBooleanExpressionTypeCalculator implements Function<GrBinaryFacade, PsiType>{
+ public static final GrBooleanExpressionTypeCalculator INSTANCE = new GrBooleanExpressionTypeCalculator();
+
+ @Override
+ public PsiType fun(GrBinaryFacade expression) {
+ return GrBinaryExpressionUtil.getTypeByFQName(CommonClassNames.JAVA_LANG_BOOLEAN, expression);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrDecimalBinaryExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrDecimalBinaryExpressionTypeCalculator.java
new file mode 100644
index 0000000..0cf9b53
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrDecimalBinaryExpressionTypeCalculator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryExpressionUtil.*;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrDecimalBinaryExpressionTypeCalculator extends GrNumericBinaryExpressionTypeCalculator {
+ public static final GrDecimalBinaryExpressionTypeCalculator INSTANCE = new GrDecimalBinaryExpressionTypeCalculator();
+
+ @Nullable
+ @Override
+ protected PsiType inferNumericType(@NotNull PsiType ltype, @NotNull PsiType rtype, GrBinaryFacade e) {
+ if (isBigDecimal(ltype, rtype)) return null;
+ if (isFloatOrDouble(ltype, rtype)) return null;
+ if (isLong(ltype, rtype)) return createLong(e);
+ return createInteger(e);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrDivExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrDivExpressionTypeCalculator.java
new file mode 100644
index 0000000..9a1cf29
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrDivExpressionTypeCalculator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrDivExpressionTypeCalculator extends GrNumericBinaryExpressionTypeCalculator {
+ public static final GrDivExpressionTypeCalculator INSTANCE = new GrDivExpressionTypeCalculator();
+
+ @Nullable
+ @Override
+ protected PsiType inferNumericType(@NotNull PsiType ltype, @NotNull PsiType rtype, GrBinaryFacade e) {
+ if (GrBinaryExpressionUtil.isFloatOrDouble(ltype, rtype)) {
+ return GrBinaryExpressionUtil.createDouble(e);
+ }
+
+ return GrBinaryExpressionUtil.createBigDecimal(e);
+ }
+
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrIntegerTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrIntegerTypeCalculator.java
new file mode 100644
index 0000000..1298f7b
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrIntegerTypeCalculator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.CommonClassNames;
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrIntegerTypeCalculator implements Function<GrBinaryFacade,PsiType> {
+ public static final GrIntegerTypeCalculator INSTANCE = new GrIntegerTypeCalculator();
+
+ @Override
+ public PsiType fun(GrBinaryFacade expression) {
+ return GrBinaryExpressionUtil.getTypeByFQName(CommonClassNames.JAVA_LANG_INTEGER, expression);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrMatcherTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrMatcherTypeCalculator.java
new file mode 100644
index 0000000..1d5d8af
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrMatcherTypeCalculator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import com.intellij.util.Function;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrMatcherTypeCalculator implements Function<GrBinaryFacade, PsiType> {
+ public static final GrMatcherTypeCalculator INSTANCE = new GrMatcherTypeCalculator();
+
+ @Override
+ public PsiType fun(GrBinaryFacade expression) {
+ return GrBinaryExpressionUtil.getTypeByFQName(GroovyCommonClassNames.JAVA_UTIL_REGEX_MATCHER, expression);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrMultiplicativeExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrMultiplicativeExpressionTypeCalculator.java
new file mode 100644
index 0000000..9455f71
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrMultiplicativeExpressionTypeCalculator.java
@@ -0,0 +1,33 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrMultiplicativeExpressionTypeCalculator extends GrNumericBinaryExpressionTypeCalculator {
+ public static final GrMultiplicativeExpressionTypeCalculator INSTANCE = new GrMultiplicativeExpressionTypeCalculator();
+
+ @Nullable
+ @Override
+ protected PsiType inferNumericType(@NotNull PsiType ltype, @NotNull PsiType rtype, GrBinaryFacade e) {
+ return GrBinaryExpressionUtil.getDefaultNumericResultType(ltype, rtype, e);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrNumericBinaryExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrNumericBinaryExpressionTypeCalculator.java
new file mode 100644
index 0000000..88c7fda
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrNumericBinaryExpressionTypeCalculator.java
@@ -0,0 +1,60 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.PsiType;
+import com.intellij.util.NullableFunction;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+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.lang.resolve.ResolveUtil;
+
+import static org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.binaryCalculators.GrBinaryExpressionUtil.*;
+
+/**
+ * Created by Max Medvedev on 12/20/13
+ */
+public class GrNumericBinaryExpressionTypeCalculator implements NullableFunction<GrBinaryFacade, PsiType> {
+ public static final GrNumericBinaryExpressionTypeCalculator INSTANCE = new GrNumericBinaryExpressionTypeCalculator();
+
+ @Nullable
+ @Override
+ public PsiType fun(GrBinaryFacade e) {
+
+ final GroovyResolveResult resolveResult = PsiImplUtil.extractUniqueResult(e.multiResolve(false));
+ if (resolveResult.isApplicable() && !PsiUtil.isDGMMethod(resolveResult.getElement())) {
+ return ResolveUtil.extractReturnTypeFromCandidate(resolveResult, e.getPsiElement(), new PsiType[]{getRightType(e)});
+ }
+
+ PsiType lType = getLeftType(e);
+ PsiType rType = getRightType(e);
+ if (TypesUtil.isNumericType(lType) && TypesUtil.isNumericType(rType)) {
+ assert lType != null;
+ assert rType != null;
+ return inferNumericType(lType, rType, e);
+ }
+
+ return ResolveUtil.extractReturnTypeFromCandidate(resolveResult, e.getPsiElement(), new PsiType[]{rType});
+ }
+
+ @Nullable
+ protected PsiType inferNumericType(@NotNull PsiType ltype, @NotNull PsiType rtype, GrBinaryFacade e) {
+ return getDefaultNumericResultType(ltype, rtype, e);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrRangeExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrRangeExpressionTypeCalculator.java
new file mode 100644
index 0000000..e1b79a5
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/binaryCalculators/GrRangeExpressionTypeCalculator.java
@@ -0,0 +1,38 @@
+/*
+ * 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.lang.psi.impl.statements.expressions.binaryCalculators;
+
+import com.intellij.psi.JavaPsiFacade;
+import com.intellij.psi.PsiType;
+import org.jetbrains.plugins.groovy.lang.psi.impl.GrRangeType;
+
+/**
+* Created by Max Medvedev on 12/20/13
+*/
+public class GrRangeExpressionTypeCalculator extends GrBinaryExpressionTypeCalculator {
+ public static final GrBinaryExpressionTypeCalculator INSTANCE = new GrRangeExpressionTypeCalculator();
+
+ @Override
+ public PsiType fun(GrBinaryFacade e) {
+ final PsiType type = super.fun(e);
+ if (type != null) return type;
+
+ final PsiType ltype = GrBinaryExpressionUtil.getLeftType(e);
+ final PsiType rtype = GrBinaryExpressionUtil.getRightType(e);
+
+ return new GrRangeType(e.getPsiElement().getResolveScope(), JavaPsiFacade.getInstance(e.getPsiElement().getProject()), ltype, rtype);
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/bitwise/GrBitwiseExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/bitwise/GrBitwiseExpressionImpl.java
index 9c00f4b..831c96e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/bitwise/GrBitwiseExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/bitwise/GrBitwiseExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java
index 4da4d13..cf69b23 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/literals/GrLiteralImpl.java
@@ -54,7 +54,7 @@
public PsiType getType() {
IElementType elemType = getLiteralType(this);
- return elemType == kNULL ? PsiType.NULL : TypesUtil.getPsiType(this, elemType);
+ return TypesUtil.getPsiType(this, elemType);
}
public void accept(GroovyElementVisitor visitor) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/logical/GrLogicalExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/logical/GrLogicalExpressionImpl.java
index b8d8855..f837b14 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/logical/GrLogicalExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/logical/GrLogicalExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,9 +16,6 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.logical;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiType;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
@@ -26,23 +23,12 @@
* author ven
*/
public class GrLogicalExpressionImpl extends GrBinaryExpressionImpl {
- private static final Function<GrBinaryExpressionImpl,PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
- @Override
- public PsiType fun(GrBinaryExpressionImpl binary) {
- return binary.getTypeByFQName(CommonClassNames.JAVA_LANG_BOOLEAN);
- }
- };
public GrLogicalExpressionImpl(@NotNull ASTNode node) {
super(node);
}
@Override
- protected Function<GrBinaryExpressionImpl, PsiType> getTypeCalculator() {
- return TYPE_CALCULATOR;
- }
-
- @Override
public String toString() {
return "Logical expression";
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java
index b8d1ded..410fb89 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/DefaultCallExpressionTypeCalculator.java
@@ -54,18 +54,21 @@
PsiType result = null;
for (GroovyResolveResult resolveResult : resolveResults) {
PsiType returnType = calculateReturnTypeInner(callExpression, refExpr, resolveResult);
-
if (returnType == null) return null;
- if (!(returnType instanceof GrLiteralClassType)) {
- returnType = TypesUtil.substituteBoxAndNormalizeType(returnType, resolveResult.getSubstitutor(), resolveResult.getSpreadState(), callExpression);
- LOG.assertTrue(returnType != null);
- }
- if (result == null || returnType.isAssignableFrom(result)) {
- result = returnType;
+ PsiType nonVoid = PsiType.VOID.equals(returnType) ? PsiType.NULL : returnType;
+
+ PsiType normalized = nonVoid instanceof GrLiteralClassType
+ ? nonVoid
+ : TypesUtil.substituteBoxAndNormalizeType(nonVoid, resolveResult.getSubstitutor(), resolveResult.getSpreadState(), callExpression);
+
+ LOG.assertTrue(normalized != null, "return type: " + returnType + "; substitutor: " + resolveResult.getSubstitutor());
+
+ if (result == null || normalized.isAssignableFrom(result)) {
+ result = normalized;
}
- else if (!result.isAssignableFrom(returnType)) {
- result = TypesUtil.getLeastUpperBound(result, returnType, manager);
+ else if (!result.isAssignableFrom(normalized)) {
+ result = TypesUtil.getLeastUpperBound(result, normalized, manager);
}
}
@@ -81,26 +84,29 @@
GrReferenceExpression refExpr,
GroovyResolveResult resolveResult) {
PsiElement resolved = resolveResult.getElement();
- PsiType returnType = null;
if (resolved instanceof PsiMethod) {
PsiMethod method = (PsiMethod)resolved;
if (resolveResult.isInvokedOnProperty()) {
final PsiType propertyType = PsiUtil.getSmartReturnType(method);
- returnType = extractReturnTypeFromType(propertyType, true, callExpression);
+ return extractReturnTypeFromType(propertyType, true, callExpression);
}
else {
- returnType = getClosureMethodsReturnType(callExpression, refExpr, method);
- if (returnType == null) {
- returnType = PsiUtil.getSmartReturnType(method);
+ PsiType closureReturnType = getClosureMethodsReturnType(callExpression, refExpr, method);
+ if (closureReturnType != null) {
+ return closureReturnType;
+ }
+ else {
+ final PsiType smartReturnType = PsiUtil.getSmartReturnType(method);
+ return smartReturnType;
}
}
}
else if (resolved instanceof GrVariable) {
PsiType refType = refExpr.getType();
final PsiType type = refType == null ? ((GrVariable)resolved).getTypeGroovy() : refType;
- returnType = extractReturnTypeFromType(type, false, callExpression);
+ return extractReturnTypeFromType(type, false, callExpression);
}
- return returnType;
+ return null;
}
@Nullable
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java
index a50f7ae..bc81626 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/path/GrIndexPropertyImpl.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.
@@ -128,7 +128,7 @@
if (element instanceof PsiNamedElement) {
final String name = ((PsiNamedElement)element).getName();
if ("putAt".equals(name) && args != null) {
- args = ArrayUtil.append(args, TypeInferenceHelper.getInitializerFor(this), PsiType.class);
+ args = ArrayUtil.append(args, TypeInferenceHelper.getInitializerTypeFor(this), PsiType.class);
}
}
PsiType overloadedOperatorType = ResolveUtil.extractReturnTypeFromCandidate(candidate, this, args);
@@ -192,7 +192,7 @@
GroovyResolveResult[] candidates;
final String name = isSetter ? "putAt" : "getAt";
if (isSetter && !incompleteCode) {
- argTypes = ArrayUtil.append(argTypes, TypeInferenceHelper.getInitializerFor(this), PsiType.class);
+ argTypes = ArrayUtil.append(argTypes, TypeInferenceHelper.getInitializerTypeFor(this), PsiType.class);
}
if (PsiImplUtil.isSimpleArrayAccess(thisType, argTypes, this, isSetter)) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/regex/GrRegexFindExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/regex/GrRegexFindExpressionImpl.java
index b563bbd..525d7d1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/regex/GrRegexFindExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/regex/GrRegexFindExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,49 +17,18 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.regex;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiType;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrParenthesizedExpression;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
-import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
/**
* @author ilyas
*/
public class GrRegexFindExpressionImpl extends GrBinaryExpressionImpl {
- private static final Function<GrBinaryExpressionImpl, PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
- @Override
- public PsiType fun(GrBinaryExpressionImpl binary) {
- PsiElement parent = binary.getParent();
-
- while (parent instanceof GrParenthesizedExpression) {
- parent = parent.getParent();
- }
-
- if (parent instanceof GrVariable) {
- PsiType declaredType = ((GrVariable)parent).getDeclaredType();
- if (declaredType == PsiType.BOOLEAN || (declaredType != null && declaredType.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN))) {
- return PsiType.BOOLEAN;
- }
- }
-
- return binary.getTypeByFQName(GroovyCommonClassNames.JAVA_UTIL_REGEX_MATCHER);
- }
- };
public GrRegexFindExpressionImpl(@NotNull ASTNode node) {
super(node);
}
- @Override
- protected Function<GrBinaryExpressionImpl, PsiType> getTypeCalculator() {
- return TYPE_CALCULATOR;
- }
-
public String toString() {
return "RegexFindExpression";
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/relational/GrRelationalExpressionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/relational/GrRelationalExpressionImpl.java
index 971778c..4a3eac6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/relational/GrRelationalExpressionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/expressions/relational/GrRelationalExpressionImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,28 +17,14 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.relational;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.PsiType;
-import com.intellij.util.Function;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.GrBinaryExpressionImpl;
-import static com.intellij.psi.CommonClassNames.JAVA_LANG_BOOLEAN;
-import static com.intellij.psi.CommonClassNames.JAVA_LANG_INTEGER;
-import static org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes.mCOMPARE_TO;
-
/**
* @author ilyas
*/
public class GrRelationalExpressionImpl extends GrBinaryExpressionImpl {
- private static final Function<GrBinaryExpressionImpl,PsiType> TYPE_CALCULATOR = new Function<GrBinaryExpressionImpl, PsiType>() {
- @Override
- public PsiType fun(GrBinaryExpressionImpl binary) {
- final String typeName = mCOMPARE_TO == binary.getOperationTokenType() ? JAVA_LANG_INTEGER : JAVA_LANG_BOOLEAN;
- return binary.getTypeByFQName(typeName);
- }
- };
-
public GrRelationalExpressionImpl(@NotNull ASTNode node) {
super(node);
}
@@ -46,9 +32,4 @@
public String toString() {
return "Relational expression";
}
-
- @Override
- protected Function<GrBinaryExpressionImpl, PsiType> getTypeCalculator() {
- return TYPE_CALCULATOR;
- }
}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java
index aa7876a..2ff2a00 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrAnonymousClassDefinitionImpl.java
@@ -106,8 +106,7 @@
return createClassType();
}
- PsiClassType type = null;
- if (myCachedBaseType != null) type = myCachedBaseType.get();
+ PsiClassType type = SoftReference.dereference(myCachedBaseType);
if (type != null && type.isValid()) return type;
type = createClassType();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrReferenceListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrReferenceListImpl.java
index 339e67d..548bf70 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrReferenceListImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/statements/typedef/GrReferenceListImpl.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,10 +17,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.psi.PsiClassType;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiJavaCodeReferenceElement;
-import com.intellij.psi.StubBasedPsiElement;
+import com.intellij.psi.*;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
@@ -135,6 +132,7 @@
//hack for inserting references from java code
if (element instanceof GrCodeReferenceElement || element instanceof PsiJavaCodeReferenceElement) {
if (findChildByType(getKeywordType()) == null) {
+ getNode().getTreeParent().addLeaf(TokenType.WHITE_SPACE, " ", getNode());
getNode().addLeaf(getKeywordType(), getKeywordType().toString(), null);
}
else if (findChildByClass(GrCodeReferenceElement.class) != null) {
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 471a5e3..b608f29 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
@@ -38,6 +38,7 @@
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
import org.jetbrains.plugins.groovy.gpp.GppTypeConverter;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
@@ -260,30 +261,37 @@
@Nullable
public GrTypeElement setReturnType(@Nullable PsiType newReturnType) {
GrTypeElement typeElement = getReturnTypeElementGroovy();
- if (newReturnType == null) {
+ if (newReturnType == null || newReturnType == PsiType.NULL) {
if (typeElement != null) typeElement.delete();
+ insertPlaceHolderToModifierList();
return null;
}
- GrTypeElement newTypeElement = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(newReturnType);
+ final GrTypeElement stub = GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(newReturnType);
+ GrTypeElement newTypeElement;
if (typeElement == null) {
- PsiElement anchor = getTypeParameterList();
- if (anchor == null) anchor = getModifierList();
- newTypeElement = (GrTypeElement)addAfter(newTypeElement, anchor);
+ final GrTypeParameterList typeParemeterList = getTypeParameterList();
+ PsiElement anchor = typeParemeterList != null ? typeParemeterList : getModifierList();
+ newTypeElement = (GrTypeElement)addAfter(stub, anchor);
}
else {
- newTypeElement = (GrTypeElement)typeElement.replace(newTypeElement);
+ newTypeElement = (GrTypeElement)typeElement.replace(stub);
}
newTypeElement.accept(new GroovyRecursiveElementVisitor() {
@Override
public void visitCodeReferenceElement(GrCodeReferenceElement refElement) {
super.visitCodeReferenceElement(refElement);
- org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster.shortenReference(refElement);
+ GrReferenceAdjuster.shortenReference(refElement);
}
});
return newTypeElement;
}
+ private void insertPlaceHolderToModifierList() {
+ final GrModifierList list = getModifierList();
+ PsiImplUtil.insertPlaceHolderToModifierListAtEndIfNeeded(list);
+ }
+
@Override
protected boolean isVisibilitySupported() {
return true;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrMethodWrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrMethodWrapper.java
index 20b18ad..ac57f1e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrMethodWrapper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrMethodWrapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -16,17 +16,63 @@
package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
import com.intellij.codeInsight.completion.originInfo.OriginInfoAwareElement;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
+import com.intellij.psi.search.GlobalSearchScope;
+import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
+import org.jetbrains.annotations.Nullable;
/**
* @author Sergey Evdokimov
*/
public class GrMethodWrapper extends GrLightMethodBuilder {
- private static PsiType TYPE_MARKER = new PsiPrimitiveType("xxx", PsiAnnotation.EMPTY_ARRAY);
+ private static final PsiType TYPE_MARKER = new PsiType(PsiAnnotation.EMPTY_ARRAY) {
+ @NotNull
+ @Override
+ public String getPresentableText() {
+ return "?";
+ }
+
+ @NotNull
+ @Override
+ public String getCanonicalText() {
+ return "?";
+ }
+
+ @NotNull
+ @Override
+ public String getInternalCanonicalText() {
+ return "?";
+ }
+
+ @Override
+ public boolean isValid() {
+ return false;
+ }
+
+ @Override
+ public boolean equalsToText(@NotNull @NonNls String text) {
+ return false;
+ }
+
+ @Override
+ public <A> A accept(@NotNull PsiTypeVisitor<A> visitor) {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public GlobalSearchScope getResolveScope() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public PsiType[] getSuperTypes() {
+ return EMPTY_ARRAY;
+ }
+ };
private volatile boolean myNavigationElementInit;
@@ -41,15 +87,7 @@
getModifierList().copyModifiers(method);
- for (PsiParameter parameter : method.getParameterList().getParameters()) {
- GrLightParameter p = new GrLightParameter(StringUtil.notNullize(parameter.getName()), parameter.getType(), this);
-
- if (parameter instanceof GrParameter) {
- p.setOptional(((GrParameter)parameter).isOptional());
- }
-
- addParameter(p);
- }
+ getParameterList().copyParameters(method);
if (method instanceof OriginInfoAwareElement) {
setOriginInfo(((OriginInfoAwareElement)method).getOriginInfo());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java
index e0344e8..2b925cf 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/synthetic/GrSyntheticCodeBlock.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -84,7 +84,7 @@
if (element == null) return null;
final SoftReference<PsiJavaToken> ref = element.getUserData(PSI_JAVA_TOKEN);
- final PsiJavaToken token = ref == null ? null : ref.get();
+ final PsiJavaToken token = SoftReference.dereference(ref);
if (token != null) return token;
final LightJavaToken newToken = new LightJavaToken(element, type);
element.putUserData(PSI_JAVA_TOKEN, new SoftReference<PsiJavaToken>(newToken));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java
index 6e51ce6..761cbeb 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/toplevel/imports/GrImportStatementImpl.java
@@ -99,14 +99,13 @@
NameHint nameHint = processor.getHint(NameHint.KEY);
- GrCodeReferenceElement ref = getImportReference();
- if (ref == null) return true;
-
if (isStatic()) {
- return processSingleStaticImport(processor, state, name, nameHint, ref);
+ GrCodeReferenceElement ref = getImportReference();
+ return ref == null || processSingleStaticImport(processor, state, name, nameHint, ref);
}
if (nameHint == null || name.equals(nameHint.getName(state))) {
- return processSingleClassImport(processor, state, ref);
+ GrCodeReferenceElement ref = getImportReference();
+ return ref == null || processSingleClassImport(processor, state, ref);
}
return true;
}
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 159c92b..498a6ea 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
@@ -40,6 +40,7 @@
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
@@ -142,7 +143,7 @@
return CLASS_OR_PACKAGE;
}
else if (parentKind == STATIC_MEMBER_FQ) {
- return CLASS;
+ return isQualified() ? CLASS_FQ : CLASS;
}
else if (parentKind == CLASS_FQ) return CLASS_OR_PACKAGE_FQ;
return parentKind;
@@ -163,12 +164,9 @@
}
}
else if (parent instanceof GrNewExpression || parent instanceof GrAnonymousClassDefinition) {
- if (parent instanceof GrAnonymousClassDefinition) {
- parent = parent.getParent();
- }
- assert parent instanceof GrNewExpression;
- final GrNewExpression newExpression = (GrNewExpression)parent;
- if (newExpression.getQualifier() != null) return CLASS_IN_QUALIFIED_NEW;
+ PsiElement newExpr = parent instanceof GrAnonymousClassDefinition ? parent.getParent() : parent;
+ assert newExpr instanceof GrNewExpression;
+ if (((GrNewExpression)newExpr).getQualifier() != null) return CLASS_IN_QUALIFIED_NEW;
}
return CLASS;
@@ -500,47 +498,29 @@
break;
- case CLASS:
- case CLASS_OR_PACKAGE: {
+ case CLASS: {
+ EnumSet<ClassHint.ResolveKind> kinds = kind == CLASS ? ResolverProcessor.RESOLVE_KINDS_CLASS : ResolverProcessor.RESOLVE_KINDS_CLASS_PACKAGE;
+ ResolverProcessor processor = new ClassResolverProcessor(refName, ref, kinds);
GrCodeReferenceElement qualifier = ref.getQualifier();
if (qualifier != null) {
PsiElement qualifierResolved = qualifier.resolve();
- if (qualifierResolved instanceof PsiPackage) {
- for (final PsiClass aClass : ((PsiPackage)qualifierResolved).getClasses(ref.getResolveScope())) {
- if (refName.equals(aClass.getName())) {
- boolean isAccessible = PsiUtil.isAccessible(ref, aClass);
- return new GroovyResolveResult[]{new GroovyResolveResultImpl(aClass, isAccessible)};
- }
- }
-
- if (kind == CLASS_OR_PACKAGE) {
- final String fqName = ((PsiPackage)qualifierResolved).getQualifiedName() + "." + refName;
- final PsiPackage aPackage = JavaPsiFacade.getInstance(ref.getProject()).findPackage(fqName);
- if (aPackage != null) return new GroovyResolveResult[]{new GroovyResolveResultImpl(aPackage, true)};
- }
- }
- else if ((kind == CLASS || kind == CLASS_OR_PACKAGE) && qualifierResolved instanceof PsiClass) {
- final ClassResolverProcessor processor = new ClassResolverProcessor(refName, ref);
+ if (qualifierResolved instanceof PsiPackage || qualifierResolved instanceof PsiClass) {
qualifierResolved.processDeclarations(processor, ResolveState.initial(), null, ref);
return processor.getCandidates();
}
}
else {
- EnumSet<ClassHint.ResolveKind> kinds = kind == CLASS ? ResolverProcessor.RESOLVE_KINDS_CLASS :
- ResolverProcessor.RESOLVE_KINDS_CLASS_PACKAGE;
- ResolverProcessor processor = new ClassResolverProcessor(refName, ref, kinds);
- ResolveUtil.treeWalkUp(ref, processor, false);
+ // if ref is an annotation name reference we should not process declarations of annotated elements
+ // because inner annotations are not permitted and it can cause infinite recursion
+ PsiElement placeToStartWalking = isAnnotationRef(ref) ? getContextFile(ref) : ref;
+ ResolveUtil.treeWalkUp(placeToStartWalking, processor, false);
GroovyResolveResult[] candidates = processor.getCandidates();
if (candidates.length > 0) return candidates;
if (kind == CLASS_OR_PACKAGE) {
- PsiPackage defaultPackage = JavaPsiFacade.getInstance(ref.getProject()).findPackage("");
- if (defaultPackage != null) {
- for (final PsiPackage subpackage : defaultPackage.getSubPackages(ref.getResolveScope())) {
- if (refName.equals(subpackage.getName())) {
- return new GroovyResolveResult[]{new GroovyResolveResultImpl(subpackage, true)};
- }
- }
+ PsiPackage pkg = JavaPsiFacade.getInstance(ref.getProject()).findPackage(refName);
+ if (pkg != null) {
+ return new GroovyResolveResult[]{new GroovyResolveResultImpl(pkg, true)};
}
}
}
@@ -548,6 +528,21 @@
break;
}
+ case CLASS_OR_PACKAGE: {
+ GroovyResolveResult[] classResult = _resolve(ref, manager, CLASS);
+
+ if (classResult.length == 1 && !classResult[0].isAccessible()) {
+ GroovyResolveResult[] packageResult = _resolve(ref, manager, PACKAGE_FQ);
+ if (packageResult.length != 0) {
+ return packageResult;
+ }
+ }
+ else if (classResult.length == 0) {
+ return _resolve(ref, manager, PACKAGE_FQ);
+ }
+
+ return classResult;
+ }
case STATIC_MEMBER_FQ: {
final GrCodeReferenceElement qualifier = ref.getQualifier();
if (qualifier != null) {
@@ -600,6 +595,21 @@
return GroovyResolveResult.EMPTY_ARRAY;
}
+ private static boolean isAnnotationRef(GrCodeReferenceElement ref) {
+ final PsiElement parent = ref.getParent();
+ return parent instanceof GrAnnotation || parent instanceof GrCodeReferenceElement && isAnnotationRef((GrCodeReferenceElement)parent);
+ }
+
+ private static PsiFile getContextFile(@NotNull PsiElement ref) {
+ final PsiFile file = ref.getContainingFile();
+ if (file.isPhysical() || file.getContext() == null) {
+ return file;
+ }
+ else {
+ return getContextFile(file.getContext());
+ }
+ }
+
private static void processAccessors(GrCodeReferenceElementImpl ref,
String refName,
PsiClass clazz,
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeArgumentListImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeArgumentListImpl.java
index a9fce13..fc22dda 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeArgumentListImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/impl/types/GrTypeArgumentListImpl.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.
@@ -19,6 +19,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
@@ -33,6 +34,7 @@
super(node);
}
+ @Override
public void accept(GroovyElementVisitor visitor) {
visitor.visitTypeArgumentList(this);
}
@@ -41,6 +43,7 @@
return "Type arguments";
}
+ @Override
public GrTypeElement[] getTypeArgumentElements() {
return findChildrenByClass(GrTypeElement.class);
}
@@ -50,14 +53,39 @@
final GrTypeElement[] elements = getTypeArgumentElements();
if (elements.length == 0) return PsiType.EMPTY_ARRAY;
- PsiType[] result = new PsiType[elements.length];
+ PsiType[] result = PsiType.createArray(elements.length);
for (int i = 0; i < elements.length; i++) {
result[i] = elements[i].getType();
}
return result;
}
+ @Override
public boolean isDiamond() {
return getTypeArgumentElements().length == 0;
}
+
+ @Override
+ public ASTNode addInternal(ASTNode first, ASTNode last, ASTNode anchor, Boolean before) {
+ if (first == last && first.getPsi() instanceof GrTypeElement) {
+ if (anchor == null) {
+ anchor = getLastChild().getNode();
+ before = true;
+ }
+ if (getTypeArgumentElements().length > 0) {
+ if (before == null || before.booleanValue()) {
+ getNode().addLeaf(GroovyTokenTypes.mCOMMA, ",", anchor);
+ }
+ else {
+ getNode().addLeaf(GroovyTokenTypes.mCOMMA, ",", anchor.getTreeNext());
+ }
+ }
+
+ return super.addInternal(first, last, anchor, before);
+ }
+
+ else {
+ return super.addInternal(first, last, anchor, before);
+ }
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java
index 450a7bd..d87020b 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/patterns/GroovyMethodCallPattern.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.
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java
index f78b7f3..811384c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/GrAnnotationStub.java
@@ -1,28 +1,65 @@
+/*
+ * 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.lang.psi.stubs;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.stubs.StubBase;
import com.intellij.psi.stubs.StubElement;
-import com.intellij.util.io.StringRef;
+import com.intellij.reference.SoftReference;
+import com.intellij.util.IncorrectOperationException;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
/**
* @author peter
*/
public class GrAnnotationStub extends StubBase<GrAnnotation> {
- private final StringRef myReference;
+ private static final Logger LOG = Logger.getInstance(GrAnnotationStub.class);
- public GrAnnotationStub(StubElement parent, StringRef reference) {
+ private final String myText;
+ private SoftReference<GrAnnotation> myPsiRef;
+
+ public GrAnnotationStub(StubElement parent, String text) {
super(parent, GroovyElementTypes.ANNOTATION);
- myReference = reference;
+ myText = text;
}
public GrAnnotationStub(StubElement parent, GrAnnotation from) {
super(parent, GroovyElementTypes.ANNOTATION);
- myReference = StringRef.fromString(from.getClassReference().getReferenceName());
+ myText = from.getText();
}
- public String getAnnotationName() {
- return myReference.getString();
+ public GrAnnotation getPsiElement() {
+ GrAnnotation annotation = SoftReference.dereference(myPsiRef);
+ if (annotation != null) {
+ return annotation;
+ }
+ try {
+ annotation = GroovyPsiElementFactory.getInstance(getProject()).createAnnotationFromText(myText, getPsi());
+ myPsiRef = new SoftReference<GrAnnotation>(annotation);
+ return annotation;
+ }
+ catch (IncorrectOperationException e) {
+ LOG.error("Bad annotation in repository!", e);
+ return null;
+ }
+ }
+
+ public String getText() {
+ return myText;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java
new file mode 100644
index 0000000..9dc51c8
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrAnnotationElementType.java
@@ -0,0 +1,56 @@
+/*
+ * 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.lang.psi.stubs.elements;
+
+import com.intellij.psi.stubs.StubElement;
+import com.intellij.psi.stubs.StubInputStream;
+import com.intellij.psi.stubs.StubOutputStream;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
+import org.jetbrains.plugins.groovy.lang.psi.impl.auxiliary.annotation.GrAnnotationImpl;
+import org.jetbrains.plugins.groovy.lang.psi.stubs.GrAnnotationStub;
+
+import java.io.IOException;
+
+/**
+ * Created by Max Medvedev on 12/6/13
+ */
+public class GrAnnotationElementType extends GrStubElementType<GrAnnotationStub, GrAnnotation> {
+ public GrAnnotationElementType(@NotNull String name) {
+ super(name);
+ }
+
+ @Override
+ public GrAnnotation createPsi(@NotNull GrAnnotationStub stub) {
+ return new GrAnnotationImpl(stub);
+ }
+
+ @Override
+ public GrAnnotationStub createStub(@NotNull GrAnnotation psi, StubElement parentStub) {
+ return new GrAnnotationStub(parentStub, psi);
+ }
+
+ @Override
+ public void serialize(@NotNull GrAnnotationStub stub, @NotNull StubOutputStream dataStream) throws IOException {
+ dataStream.writeUTFFast(stub.getText());
+ }
+
+ @NotNull
+ @Override
+ public GrAnnotationStub deserialize(@NotNull StubInputStream dataStream, StubElement parentStub) throws IOException {
+ return new GrAnnotationStub(parentStub, dataStream.readUTFFast());
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrReferenceListElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrReferenceListElementType.java
index 3deae8d..71dab4f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrReferenceListElementType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrReferenceListElementType.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.
@@ -70,5 +70,10 @@
}
}
}
+
+ @Override
+ public boolean isLeftBound() {
+ return true;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java
index 10e803e..c54cc96 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/elements/GrStubFileElementType.java
@@ -55,7 +55,7 @@
@Override
public int getStubVersion() {
- return super.getStubVersion() + 19;
+ return super.getStubVersion() + 20;
}
@NotNull
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/index/GrFullClassNameIndex.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/index/GrFullClassNameIndex.java
index 696ea8e..eb00004 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/index/GrFullClassNameIndex.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/stubs/index/GrFullClassNameIndex.java
@@ -43,6 +43,6 @@
}
public Collection<PsiClass> get(final Integer integer, final Project project, final GlobalSearchScope scope) {
- return StubIndex.getInstance().safeGet(getKey(), integer, project, new GrSourceFilterScope(scope), PsiClass.class);
+ return StubIndex.getElements(getKey(), integer, project, new GrSourceFilterScope(scope), PsiClass.class);
}
}
\ No newline at end of file
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 7290d52..165b5f7 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
@@ -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,12 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.typeEnhancers;
+import com.intellij.psi.PsiSubstitutor;
import com.intellij.psi.PsiType;
+import com.intellij.psi.PsiWildcardType;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.gpp.GppClosureParameterTypeProvider;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrSafeCastExpression;
@@ -63,7 +66,13 @@
for (PsiType constraint : expectedTypes) {
final PsiType suggestion = GppClosureParameterTypeProvider.getSingleMethodParameterType(constraint, index, closure);
if (suggestion != null) {
- return suggestion;
+ if (GroovyConfigUtils.getInstance().isVersionAtLeast(closure, GroovyConfigUtils.GROOVY2_3)) {
+ if (suggestion instanceof PsiWildcardType && ((PsiWildcardType)suggestion).isSuper()) {
+ return ((PsiWildcardType)suggestion).getBound();
+ }
+ }
+
+ return TypesUtil.substituteBoxAndNormalizeType(suggestion, PsiSubstitutor.EMPTY, null, closure);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureToSamConverter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureToSamConverter.java
index 8c574fe..7516dec 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureToSamConverter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/typeEnhancers/ClosureToSamConverter.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.
@@ -45,18 +45,13 @@
@Override
public Boolean isConvertible(@NotNull PsiType ltype, @NotNull PsiType rtype, @NotNull final GroovyPsiElement context) {
if (rtype instanceof GrClosureType && ltype instanceof PsiClassType && GroovyConfigUtils.getInstance().isVersionAtLeast(context, GroovyConfigUtils.GROOVY2_2)) {
- PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)ltype).resolveGenerics();
- final PsiClass resolved = resolveResult.getElement();
- if (resolved != null) {
- final MethodSignature signature = findSingleAbstractMethodClass(resolved, resolveResult.getSubstitutor());
- if (signature != null) {
+ MethodSignature signature = findSAMSignature(ltype);
+ if (signature != null) {
+ final PsiType[] samParameterTypes = signature.getParameterTypes();
- final PsiType[] samParameterTypes = signature.getParameterTypes();
-
- GrSignature closureSignature = ((GrClosureType)rtype).getSignature();
- if (GrClosureSignatureUtil.isSignatureApplicable(closureSignature, samParameterTypes, context)) {
- return true;
- }
+ GrSignature closureSignature = ((GrClosureType)rtype).getSignature();
+ if (GrClosureSignatureUtil.isSignatureApplicable(closureSignature, samParameterTypes, context)) {
+ return true;
}
}
}
@@ -65,16 +60,15 @@
}
@Nullable
- private static MethodSignature findSingleAbstractMethodClass(@NotNull PsiClass aClass,
- @NotNull PsiSubstitutor substitutor) {
+ public static MethodSignature findSingleAbstractMethod(@NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor) {
MethodSignature signature;
Ref<MethodSignature> cached = SAM_SIGNATURE_LIGHT_CACHE_KEY.getCachedValue(aClass);
if (cached != null) {
signature = cached.get();
}
else {
- cached = Ref.create(doFindSingleAbstractMethodClass(aClass));
- signature = SAM_SIGNATURE_LIGHT_CACHE_KEY.putCachedValue(aClass, cached).get();
+ Ref<MethodSignature> newCached = Ref.create(doFindSingleAbstractMethodClass(aClass));
+ signature = SAM_SIGNATURE_LIGHT_CACHE_KEY.putCachedValue(aClass, newCached).get();
}
return signature != null ? substitute(signature, substitutor): null;
@@ -100,4 +94,18 @@
private static MethodSignature substitute(@NotNull MethodSignature signature, @NotNull PsiSubstitutor substitutor) {
return MethodSignatureUtil.createMethodSignature(signature.getName(), signature.getParameterTypes(), PsiTypeParameter.EMPTY_ARRAY, substitutor, false);
}
+
+ @Nullable
+ public static MethodSignature findSAMSignature(@Nullable PsiType type) {
+ if (type instanceof PsiClassType) {
+ PsiClassType.ClassResolveResult result = ((PsiClassType)type).resolveGenerics();
+ PsiClass aClass = result.getElement();
+
+ if (aClass != null) {
+ return findSingleAbstractMethod(aClass, result.getSubstitutor());
+ }
+ }
+
+ return null;
+ }
}
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 27e42e2..dc08b53 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
@@ -40,7 +40,6 @@
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrEnumConstantInitializer;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrReferenceList;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition;
@@ -50,6 +49,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrReflectedMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.impl.GrAnnotationUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyPsiManager;
import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
@@ -616,21 +616,8 @@
}
private static boolean shouldImplementDelegatedInterfaces(PsiAnnotation delegate) {
- final PsiAnnotationParameterList parameterList = delegate.getParameterList();
- final PsiNameValuePair[] attributes = parameterList.getAttributes();
- for (PsiNameValuePair attribute : attributes) {
- final String name = attribute.getName();
- if ("interfaces".equals(name)) {
- final PsiAnnotationMemberValue value = attribute.getValue();
- if (value instanceof GrLiteral) {
- final Object innerValue = ((GrLiteral)value).getValue();
- if (innerValue instanceof Boolean) {
- return (Boolean)innerValue;
- }
- }
- }
- }
- return true;
+ final Boolean result = GrAnnotationUtil.inferBooleanAttribute(delegate, "interfaces");
+ return result != null ? result.booleanValue() : true;
}
public static void addExpandingReflectedMethods(List<PsiMethod> result, PsiMethod method) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java
index 96e02cf..2c8196a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrImportUtil.java
@@ -16,7 +16,7 @@
package org.jetbrains.plugins.groovy.lang.psi.util;
import com.intellij.psi.PsiFile;
-import com.intellij.util.containers.MultiMapBasedOnSet;
+import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
@@ -30,7 +30,7 @@
* @author Max Medvedev
*/
public class GrImportUtil {
- private static final LightCacheKey<MultiMapBasedOnSet<String, String>> KEY = LightCacheKey.createByFileModificationCount();
+ private static final LightCacheKey<MultiMap<String, String>> KEY = LightCacheKey.createByFileModificationCount();
public static boolean acceptName(GrReferenceElement ref, String expected) {
final String actual = ref.getReferenceName();
@@ -40,7 +40,7 @@
final PsiFile file = ref.getContainingFile();
if (file instanceof GroovyFile) {
- MultiMapBasedOnSet<String, String> data = KEY.getCachedValue(file);
+ MultiMap<String, String> data = KEY.getCachedValue(file);
if (data == null) {
data = collectAliases((GroovyFile)file);
KEY.putCachedValue(file, data);
@@ -55,8 +55,8 @@
}
@NotNull
- private static MultiMapBasedOnSet<String, String> collectAliases(@NotNull GroovyFile file) {
- MultiMapBasedOnSet<String, String> aliases = new MultiMapBasedOnSet<String, String>();
+ private static MultiMap<String, String> collectAliases(@NotNull GroovyFile file) {
+ MultiMap<String, String> aliases = MultiMap.createSet();
for (GrImportStatement anImport : file.getImportStatements()) {
if (anImport.isAliasedImport()) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrInnerClassConstructorUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrInnerClassConstructorUtil.java
index 2a9b081..e233d78 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrInnerClassConstructorUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrInnerClassConstructorUtil.java
@@ -68,13 +68,13 @@
PsiElementFactory factory = JavaPsiFacade.getElementFactory(place.getProject());
PsiClass scopeClass = PsiUtil.findEnclosingInstanceClassInScope(containingClass, place, true);
if (scopeClass != null) {
- PsiType[] newTypes = new PsiType[types.length + 1];
+ PsiType[] newTypes = PsiType.createArray(types.length + 1);
newTypes[0] = factory.createType(scopeClass);
System.arraycopy(types, 0, newTypes, 1, types.length);
types = newTypes;
}
else if (types.length == 0 || !TypesUtil.isAssignableByMethodCallConversion(factory.createType(containingClass), types[0], place)) {
- PsiType[] newTypes = new PsiType[types.length + 1];
+ PsiType[] newTypes = PsiType.createArray(types.length + 1);
newTypes[0] = PsiType.NULL;
System.arraycopy(types, 0, newTypes, 1, types.length);
types = newTypes;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java
index 4cc4db1..e3f1da5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/GrStringUtil.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.
@@ -602,12 +602,12 @@
}
public static String getEndQuote(String text) {
- if (text.startsWith(TRIPLE_QUOTES)) return TRIPLE_QUOTES;
- if (text.startsWith(QUOTE)) return QUOTE;
- if (text.startsWith(TRIPLE_DOUBLE_QUOTES)) return TRIPLE_DOUBLE_QUOTES;
- if (text.startsWith(DOUBLE_QUOTES)) return DOUBLE_QUOTES;
- if (text.startsWith(SLASH)) return SLASH;
- if (text.startsWith(SLASH_DOLLAR)) return SLASH_DOLLAR;
+ if (text.endsWith(TRIPLE_QUOTES)) return TRIPLE_QUOTES;
+ if (text.endsWith(QUOTE)) return QUOTE;
+ if (text.endsWith(TRIPLE_DOUBLE_QUOTES)) return TRIPLE_DOUBLE_QUOTES;
+ if (text.endsWith(DOUBLE_QUOTES)) return DOUBLE_QUOTES;
+ if (text.endsWith(SLASH)) return SLASH;
+ if (text.endsWith(SLASH_DOLLAR)) return SLASH_DOLLAR;
return "";
}
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 27f597b..cfd5a26 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
@@ -15,8 +15,12 @@
*/
package org.jetbrains.plugins.groovy.lang.psi.util;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
+import java.util.Collections;
+import java.util.Set;
+
/**
* @author Maxim.Medvedev
*/
@@ -66,6 +70,22 @@
@NonNls public static final String GROOVY_TRANSFORM_COMPILE_DYNAMIC = "groovy.transform.CompileDynamic";
+ public static final Set<String> GROOVY_EXTENSION_CLASSES = Collections.unmodifiableSet(ContainerUtil.newLinkedHashSet(
+ "org.codehaus.groovy.runtime.DateGroovyMethods",
+ "org.codehaus.groovy.runtime.DefaultGroovyMethods",
+ "org.codehaus.groovy.runtime.DefaultGroovyStaticMethods",
+ "org.codehaus.groovy.runtime.EncodingGroovyMethods",
+ "org.codehaus.groovy.runtime.IOGroovyMethods",
+ "org.codehaus.groovy.runtime.ProcessGroovyMethods",
+ "org.codehaus.groovy.runtime.ResourceGroovyMethods",
+ "org.codehaus.groovy.runtime.SocketGroovyMethods",
+ "org.codehaus.groovy.runtime.SqlGroovyMethods",
+ "org.codehaus.groovy.runtime.StringGroovyMethods",
+ "org.codehaus.groovy.runtime.SwingGroovyMethods",
+ "org.codehaus.groovy.runtime.XmlGroovyMethods",
+ "org.codehaus.groovy.vmplugin.v5.PluginDefaultGroovyMethods"
+ ));
+
private GroovyCommonClassNames() {
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
index 0577681..bbdd353 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/psi/util/PsiUtil.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,18 +28,18 @@
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
-import com.intellij.psi.util.InheritanceUtil;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.VisibilityUtil;
import com.intellij.util.containers.HashSet;
import gnu.trove.TIntStack;
+import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
+import org.jetbrains.plugins.groovy.intentions.base.ErrorUtil;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyLexer;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
@@ -56,6 +56,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrNamedArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrSpreadArgument;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrOpenBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrAssertStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
@@ -63,6 +64,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrForInClause;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
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.expressions.path.GrPropertySelection;
@@ -73,6 +75,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrNamedArgumentsOwner;
+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.*;
import org.jetbrains.plugins.groovy.lang.psi.impl.signatures.GrClosureSignatureUtil;
@@ -249,10 +252,9 @@
GrIndexProperty index = (GrIndexProperty)parent;
PsiType[] argTypes = getArgumentTypes(index.getNamedArguments(), index.getExpressionArguments(), index.getClosureArguments(), nullAsBottom, stopAt, byShape);
if (isLValue(index) && argTypes != null) {
- PsiType initializer = TypeInferenceHelper.getInitializerFor(index);
- if (initializer == null && !nullAsBottom) {
- initializer = TypesUtil.getJavaLangObject(index);
- }
+ PsiType rawInitializer = TypeInferenceHelper.getInitializerTypeFor(index);
+
+ PsiType initializer = notNullizeType(rawInitializer, nullAsBottom, index);
return ArrayUtil.append(argTypes, initializer);
}
else {
@@ -270,18 +272,26 @@
else if (parent instanceof GrAnonymousClassDefinition) {
final GrArgumentList argList = ((GrAnonymousClassDefinition)parent).getArgumentListGroovy();
if (argList == null) {
- return getArgumentTypes(GrNamedArgument.EMPTY_ARRAY, GrExpression.EMPTY_ARRAY, GrClosableBlock.EMPTY_ARRAY, nullAsBottom, stopAt,
- byShape);
+ return getArgumentTypes(GrNamedArgument.EMPTY_ARRAY, GrExpression.EMPTY_ARRAY, GrClosableBlock.EMPTY_ARRAY, nullAsBottom, stopAt, byShape);
}
else {
- return getArgumentTypes(argList.getNamedArguments(), argList.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY, nullAsBottom,
- stopAt, byShape);
+ return getArgumentTypes(argList.getNamedArguments(), argList.getExpressionArguments(), GrClosableBlock.EMPTY_ARRAY, nullAsBottom, stopAt, byShape);
}
}
+ else if (parent instanceof GrBinaryExpression) {
+ GrExpression right = ((GrBinaryExpression)parent).getRightOperand();
+ PsiType type = right != null ? right.getType() : null;
+ return new PsiType[] {notNullizeType(type, nullAsBottom, parent)};
+ }
return null;
}
+ @Contract("_, false, _ -> !null; !null, _, _ -> !null; null, true, _ -> null")
+ private static PsiType notNullizeType(PsiType type, boolean acceptNull, PsiElement context) {
+ return type != null || acceptNull ? type : TypesUtil.getJavaLangObject(context);
+ }
+
@Nullable
public static PsiType[] getArgumentTypes(GrArgumentList argList) {
return getArgumentTypes(argList, false, null, false);
@@ -323,7 +333,7 @@
}
if (stopAt == expression) {
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(PsiType.createArray(result.size()));
}
}
@@ -333,14 +343,14 @@
if (stopAt == closure) {
closureType = TypeConversionUtil.erasure(closureType);
}
- result.add(closureType == null && !nullAsBottom ? TypesUtil.getJavaLangObject(closure) : closureType);
+ result.add(notNullizeType(closureType, nullAsBottom, closure));
}
if (stopAt == closure) {
break;
}
}
- return result.toArray(new PsiType[result.size()]);
+ return result.toArray(PsiType.createArray(result.size()));
}
@Nullable
@@ -390,8 +400,9 @@
}
}
- public static Iterable<PsiClass> iterateSupers(final @NotNull PsiClass psiClass, final boolean includeSelf) {
+ public static Iterable<PsiClass> iterateSupers(@NotNull final PsiClass psiClass, final boolean includeSelf) {
return new Iterable<PsiClass>() {
+ @Override
public Iterator<PsiClass> iterator() {
return new Iterator<PsiClass>() {
TIntStack indices = new TIntStack();
@@ -413,6 +424,7 @@
pushSuper(psiClass);
}
+ @Override
public boolean hasNext() {
nextElement();
return current != null;
@@ -450,6 +462,7 @@
indices.push(0);
}
+ @Override
@NotNull
public PsiClass next() {
nextElement();
@@ -458,6 +471,7 @@
return current;
}
+ @Override
public void remove() {
throw new IllegalStateException("should not be called");
}
@@ -600,7 +614,7 @@
PsiClassType classType = (PsiClassType)qualifierType;
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
GrExpression[] arguments = expr.getArgumentList().getExpressionArguments();
- PsiType[] argTypes = new PsiType[arguments.length];
+ PsiType[] argTypes = PsiType.createArray(arguments.length);
for (int i = 0; i < arguments.length; i++) {
PsiType argType = arguments[i].getType();
if (argType == null) argType = TypesUtil.getJavaLangObject(expr);
@@ -968,6 +982,44 @@
}
}
+ public static int getArgumentIndex(@NotNull GrCall call, @NotNull PsiElement argument) {
+ GrArgumentList argumentList = call.getArgumentList();
+ if (argumentList == null) return -1;
+
+ GrExpression[] expressionArguments = argumentList.getExpressionArguments();
+
+ for (int i = 0; i < expressionArguments.length; i++) {
+ if (argument.equals(expressionArguments[i])) {
+ int res = i;
+
+ if (argumentList.getNamedArguments().length > 0) {
+ res++; // first argument is map defined by named arguments
+ }
+
+ return res;
+ }
+ }
+
+ if (argument instanceof GrClosableBlock) {
+ GrClosableBlock[] closureArgs = call.getClosureArguments();
+
+ for (int i = 0; i < closureArgs.length; i++) {
+ if (argument.equals(closureArgs[i])) {
+ int res = i + expressionArguments.length;
+
+ if (argumentList.getNamedArguments().length > 0) {
+ res++; // first argument is map defined by named arguments
+ }
+
+ return res;
+ }
+ }
+
+ }
+
+ return -1;
+ }
+
/**
* Returns all arguments passed to method. First argument is null if Named Arguments is present.
*/
@@ -1159,27 +1211,6 @@
return !ref.isQualified() && name.equals(ref.getReferenceName());
}
- @Nullable
- public static GrExpression getInitializerFor(GrReferenceExpression lValue) {
- if (!isLValue(lValue)) throw new IllegalArgumentException("arg is not lValue");
-
- final PsiElement parent = lValue.getParent();
- if (parent instanceof GrAssignmentExpression) return ((GrAssignmentExpression)parent).getRValue();
- if (parent instanceof GrTupleExpression) {
- final int i = ((GrTupleExpression)parent).indexOf(lValue);
- final PsiElement pparent = parent.getParent();
- LOG.assertTrue(pparent instanceof GrAssignmentExpression);
-
- final GrExpression rValue = ((GrAssignmentExpression)pparent).getRValue();
- if (rValue instanceof GrListOrMap && !((GrListOrMap)rValue).isMap()) {
- final GrExpression[] initializers = ((GrListOrMap)rValue).getInitializers();
- if (initializers.length < i) return initializers[i];
- }
- }
-
- return null;
- }
-
public static boolean isProperty(GrField field) {
final PsiClass clazz = field.getContainingClass();
if (clazz == null) return false;
@@ -1205,8 +1236,7 @@
public static List<GrImportStatement> getValidImportStatements(final GroovyFile file) {
final List<GrImportStatement> oldImports = new ArrayList<GrImportStatement>();
for (GrImportStatement statement : file.getImportStatements()) {
- final GrCodeReferenceElement reference = statement.getImportReference();
- if (reference != null && reference.multiResolve(false).length > 0) {
+ if (!ErrorUtil.containsError(statement)) {
oldImports.add(statement);
}
}
@@ -1271,7 +1301,7 @@
public static boolean isLineFeed(@Nullable PsiElement e) {
return e != null &&
- TokenSets.WHITE_SPACES_SET.contains(e.getNode().getElementType()) &&
+ PsiImplUtil.isWhiteSpaceOrNls(e) &&
(e.getText().indexOf('\n') >= 0 || e.getText().indexOf('\r') >= 0);
}
@@ -1294,4 +1324,49 @@
return null;
}
}
+
+ public static boolean isDGMMethod(@Nullable PsiElement element) {
+ if (!(element instanceof PsiMethod)) return false;
+
+ final PsiMethod method = element instanceof GrGdkMethod ? ((GrGdkMethod)element).getStaticMethod() : (PsiMethod)element;
+ final PsiClass aClass = method.getContainingClass();
+ if (aClass == null) return false;
+
+ final String qname = aClass.getQualifiedName();
+ return GroovyCommonClassNames.GROOVY_EXTENSION_CLASSES.contains(qname);
+ }
+
+ public static boolean isVoidMethodCall(@Nullable GrExpression expression) {
+ if (expression instanceof GrMethodCall && PsiType.NULL.equals(expression.getType())) {
+ final GroovyResolveResult resolveResult = ((GrMethodCall)expression).advancedResolve();
+ final PsiType[] args = getArgumentTypes(((GrMethodCall)expression).getInvokedExpression(), true);
+ return PsiType.VOID.equals(ResolveUtil.extractReturnTypeFromCandidate(resolveResult, expression, args));
+ }
+
+ return false;
+ }
+
+ public static boolean isVoidMethod(@NotNull PsiMethod method) {
+ return PsiType.VOID.equals(method.getReturnType()) ||
+
+ method instanceof GrMethod &&
+ ((GrMethod)method).getReturnTypeElementGroovy() == null &&
+ ((GrMethod)method).getBlock() != null &&
+ isBlockReturnVoid(((GrMethod)method).getBlock());
+ }
+
+ public static boolean isBlockReturnVoid(@NotNull final GrCodeBlock block) {
+ return CachedValuesManager.getCachedValue(block, new CachedValueProvider<Boolean>() {
+ @Nullable
+ @Override
+ public Result<Boolean> compute() {
+ return Result.create(ControlFlowUtils.visitAllExitPoints(block, new ControlFlowUtils.ExitPointVisitor() {
+ @Override
+ public boolean visitExitPoint(Instruction instruction, @Nullable GrExpression returnValue) {
+ return returnValue == null || !(returnValue instanceof GrLiteral);
+ }
+ }), PsiModificationTracker.MODIFICATION_COUNT);
+ }
+ });
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java
index 5d7e5bc..8e1382e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/CollectClassMembersUtil.java
@@ -85,7 +85,7 @@
@NotNull
private static ClassMembers getCachedMembers(@NotNull PsiClass aClass, boolean includeSynthetic) {
- LOG.assertTrue(aClass.isValid());
+ PsiUtilCore.ensureValid(aClass);
Key<CachedValue<ClassMembers>> key = includeSynthetic ? CACHED_MEMBERS_INCLUDING_SYNTHETIC : CACHED_MEMBERS;
CachedValue<ClassMembers> cachedValue = aClass.getUserData(key);
if (isCyclicDependence(aClass)) {
@@ -150,7 +150,7 @@
@NotNull Set<PsiClass> visitedClasses,
@NotNull PsiSubstitutor substitutor,
boolean includeSynthetic) {
- LOG.assertTrue(aClass.isValid());
+ PsiUtilCore.ensureValid(aClass);
if (!visitedClasses.add(aClass)) return;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/PluginXmlClosureMemberContributor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/PluginXmlClosureMemberContributor.java
new file mode 100644
index 0000000..b2a1f6a
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/PluginXmlClosureMemberContributor.java
@@ -0,0 +1,67 @@
+/*
+ * 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.lang.resolve;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiMethod;
+import com.intellij.psi.ResolveState;
+import com.intellij.psi.scope.PsiScopeProcessor;
+import com.intellij.util.SingletonInstancesCache;
+import org.jetbrains.plugins.groovy.extensions.GroovyMethodDescriptor;
+import org.jetbrains.plugins.groovy.extensions.GroovyMethodInfo;
+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.GrMethodCall;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class PluginXmlClosureMemberContributor extends ClosureMissingMethodContributor {
+ @Override
+ public boolean processMembers(GrClosableBlock closure, PsiScopeProcessor processor, GrReferenceExpression refExpr, ResolveState state) {
+ PsiElement parent = closure.getParent();
+ if (parent instanceof GrArgumentList) parent = parent.getParent();
+
+ if (!(parent instanceof GrMethodCall)) return true;
+
+ PsiMethod psiMethod = ((GrMethodCall)parent).resolveMethod();
+ if (psiMethod == null) return true;
+
+ List<GroovyMethodInfo> infos = GroovyMethodInfo.getInfos(psiMethod);
+ if (infos.isEmpty()) return true;
+
+ int index = PsiUtil.getArgumentIndex((GrMethodCall)parent, closure);
+ if (index == -1) return true;
+
+ for (GroovyMethodInfo info : infos) {
+ GroovyMethodDescriptor.ClosureArgument[] closureArguments = info.getDescriptor().myClosureArguments;
+ if (closureArguments != null) {
+ for (GroovyMethodDescriptor.ClosureArgument argument : closureArguments) {
+ if (argument.index == index && argument.methodContributor != null) {
+ ClosureMissingMethodContributor instance = SingletonInstancesCache.getInstance(argument.methodContributor, info.getPluginClassLoader());
+ if (!instance.processMembers(closure, processor, refExpr, state)) return false;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+}
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 b78d2c8..98bd1d9 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
@@ -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.
@@ -640,7 +640,7 @@
return variants;
}
- public static GroovyResolveResult[] getConstructorResolveResult(PsiMethod[] constructors, PsiElement place) {
+ private static GroovyResolveResult[] getConstructorResolveResult(PsiMethod[] constructors, PsiElement place) {
GroovyResolveResult[] variants = new GroovyResolveResult[constructors.length];
for (int i = 0; i < constructors.length; i++) {
final boolean isAccessible = PsiUtil.isAccessible(constructors[i], place, null);
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 3c584a6..2aa286e 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
@@ -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,10 +15,13 @@
*/
package org.jetbrains.plugins.groovy.lang.resolve.ast;
+import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.impl.light.LightMethodBuilder;
+import com.intellij.psi.impl.light.LightParameter;
+import com.intellij.psi.impl.source.tree.java.PsiCompositeModifierList;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureUtil;
import com.intellij.psi.util.PsiUtil;
@@ -31,11 +34,11 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
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;
import org.jetbrains.plugins.groovy.lang.psi.util.GrClassImplUtil;
@@ -57,7 +60,7 @@
initializeSignatures(clazz, PsiSubstitutor.EMPTY, signatures, processed);
List<PsiMethod> methods = new ArrayList<PsiMethod>();
- process(clazz, PsiSubstitutor.EMPTY, true, new HashSet<PsiClass>(), processed, methods, clazz);
+ process(clazz, PsiSubstitutor.EMPTY, true, new HashSet<PsiClass>(), processed, methods, clazz, false);
final Set<PsiMethod> result = new LinkedHashSet<PsiMethod>();
for (PsiMethod method : methods) {
@@ -151,12 +154,14 @@
Set<PsiClass> processedWithoutDeprecated,
Set<PsiClass> processedAll,
List<PsiMethod> collector,
- GrTypeDefinition classToDelegateTo) {
+ GrTypeDefinition classToDelegateTo,
+ boolean keepParameterAnnotations) {
final List<PsiMethod> result = new ArrayList<PsiMethod>();
//process super methods before delegated methods
for (PsiClassType superType : getSuperTypes(clazz)) {
- processClassInner(superType, superClassSubstitutor, shouldProcessDeprecated, result, classToDelegateTo, processedWithoutDeprecated, processedAll);
+ processClassInner(superType, superClassSubstitutor, shouldProcessDeprecated, result, classToDelegateTo, processedWithoutDeprecated,
+ processedAll, keepParameterAnnotations);
}
if (clazz instanceof GrTypeDefinition) {
@@ -168,7 +173,8 @@
final PsiType type = field.getDeclaredType();
if (!(type instanceof PsiClassType)) continue;
- processClassInner((PsiClassType)type, superClassSubstitutor, shouldDelegateDeprecated(delegate), result, classToDelegateTo, processedWithoutDeprecated, processedAll);
+ processClassInner((PsiClassType)type, superClassSubstitutor, shouldDelegateDeprecated(delegate), result, classToDelegateTo,
+ processedWithoutDeprecated, processedAll, shouldKeepParameterAnnotations(delegate));
}
}
@@ -206,7 +212,7 @@
List<PsiMethod> result,
GrTypeDefinition classToDelegateTo,
Set<PsiClass> processedWithoutDeprecated,
- Set<PsiClass> processedAll) {
+ Set<PsiClass> processedAll, boolean keepParameterAnnotationsNew) {
final PsiClassType.ClassResolveResult resolveResult = type.resolveGenerics();
final PsiClass psiClass = resolveResult.getElement();
if (psiClass == null) return;
@@ -228,15 +234,16 @@
processedWithoutDeprecated.add(psiClass);
}
- collectMethods(psiClass, substitutor, shouldProcessDeprecated, classToDelegateTo, result);
- process(psiClass, substitutor, shouldProcessDeprecated, processedWithoutDeprecated, processedAll, result, classToDelegateTo);
+ collectMethods(psiClass, substitutor, shouldProcessDeprecated, classToDelegateTo, result, keepParameterAnnotationsNew);
+ process(psiClass, substitutor, shouldProcessDeprecated, processedWithoutDeprecated, processedAll, result, classToDelegateTo, keepParameterAnnotationsNew);
}
private static void collectMethods(PsiClass currentClass,
PsiSubstitutor currentClassSubstitutor,
boolean shouldProcessDeprecated,
GrTypeDefinition classToDelegateTo,
- Collection<PsiMethod> collector) {
+ Collection<PsiMethod> collector,
+ boolean keepParameterAnnotations) {
final List<PsiMethod> methods;
if (currentClass instanceof GrTypeDefinition) {
methods = new ArrayList<PsiMethod>();
@@ -253,7 +260,7 @@
if (method.isConstructor() || method.hasModifierProperty(PsiModifier.STATIC)) continue;
if (overridesObjectOrGroovyObject(method)) continue;
if (!shouldProcessDeprecated && PsiImplUtil.getAnnotation(method, CommonClassNames.JAVA_LANG_DEPRECATED) != null) continue;
- collector.add(generateDelegateMethod(method, classToDelegateTo, currentClassSubstitutor));
+ collector.add(generateDelegateMethod(method, classToDelegateTo, currentClassSubstitutor, keepParameterAnnotations));
}
}
@@ -272,24 +279,20 @@
}
private static boolean shouldDelegateDeprecated(PsiAnnotation delegate) {
- final PsiAnnotationParameterList parameterList = delegate.getParameterList();
- final PsiNameValuePair[] attributes = parameterList.getAttributes();
- for (PsiNameValuePair attribute : attributes) {
- final String name = attribute.getName();
- if ("deprecated".equals(name)) {
- final PsiAnnotationMemberValue value = attribute.getValue();
- if (value instanceof GrLiteral) {
- final Object innerValue = ((GrLiteral)value).getValue();
- if (innerValue instanceof Boolean) {
- return (Boolean)innerValue;
- }
- }
- }
- }
- return false;
+ final Boolean result = GrAnnotationUtil.inferBooleanAttribute(delegate, "deprecated");
+ return result != null && result.booleanValue();
}
- private static PsiMethod generateDelegateMethod(PsiMethod method, PsiClass superClass, PsiSubstitutor substitutor) {
+ private static boolean shouldKeepParameterAnnotations(PsiAnnotation delegate) {
+ final Boolean keepParameterAnnotations = GrAnnotationUtil.inferBooleanAttribute(delegate, "parameterAnnotations");
+ return keepParameterAnnotations != null && keepParameterAnnotations.booleanValue();
+ }
+
+
+ private static PsiMethod generateDelegateMethod(PsiMethod method,
+ PsiClass superClass,
+ PsiSubstitutor substitutor,
+ boolean keepParameterAnnotations) {
final LightMethodBuilder builder = new LightMethodBuilder(superClass.getManager(), GroovyFileType.GROOVY_LANGUAGE, method.getName());
builder.setContainingClass(superClass);
builder.setMethodReturnType(substitutor.substitute(method.getReturnType()));
@@ -324,7 +327,12 @@
if (type == null) {
type = PsiType.getJavaLangObject(superClass.getManager(), superClass.getResolveScope());
}
- builder.addParameter(StringUtil.notNullize(originalParameter.getName(), "p" + i), type);
+ final LightParameter lightParameter = new LightParameter(StringUtil.notNullize(originalParameter.getName(), "p" + i), type, builder, JavaLanguage.INSTANCE);
+ if (keepParameterAnnotations) {
+ final PsiCompositeModifierList delegatingModifierList = new PsiCompositeModifierList(method.getManager(), Collections.singletonList(originalParameter.getModifierList()));
+ lightParameter.setModifierList(delegatingModifierList);
+ }
+ builder.addParameter(lightParameter);
}
builder.setBaseIcon(JetgroovyIcons.Groovy.Method);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java
index 1fcda2d..879f839 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/AccessorResolverProcessor.java
@@ -111,8 +111,7 @@
final PsiElement resolveContext = state.get(RESOLVE_CONTEXT);
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
boolean isStaticsOK = isStaticsOK(method, resolveContext, true);
- final GroovyResolveResultImpl candidate =
- new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK, true);
+ final GroovyResolveResultImpl candidate = new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK, true, true);
if (isAccessible && isStaticsOK) {
addCandidate(candidate);
return method instanceof GrGdkMethod; //don't stop searching if we found only gdk method
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
index 2a78565..c929a20 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/MethodResolverProcessor.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.
@@ -59,7 +59,7 @@
private boolean myStopExecuting = false;
private final boolean myByShape;
-
+
private final SubstitutorComputer mySubstitutorComputer;
private final boolean myTypedContext;
@@ -88,45 +88,55 @@
myAllVariants = allVariants;
myByShape = byShape;
- mySubstitutorComputer = new SubstitutorComputer(thisType, argumentTypes, typeArguments, allVariants, place, myPlace.getParent());
+ mySubstitutorComputer = new SubstitutorComputer(myThisType, myArgumentTypes, typeArguments, myAllVariants, myPlace, myPlace.getParent());
myTypedContext = GppTypeConverter.hasTypedContext(myPlace);
}
+ @Override
public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) {
if (myStopExecuting) {
return false;
}
- PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
if (element instanceof PsiMethod) {
PsiMethod method = (PsiMethod) element;
if (method.isConstructor() != myIsConstructor) return true;
- if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
- if (!myByShape) {
- substitutor = mySubstitutorComputer.obtainSubstitutor(substitutor, method, state);
- }
+
+ PsiSubstitutor substitutor = inferSubstitutor(method, state);
PsiElement resolveContext = state.get(RESOLVE_CONTEXT);
final SpreadState spreadState = state.get(SpreadState.SPREAD_STATE);
boolean isAccessible = isAccessible(method);
boolean isStaticsOK = isStaticsOK(method, resolveContext, true);
+ boolean isApplicable = PsiUtil.isApplicable(myArgumentTypes, method, substitutor, myPlace, myByShape);
+ boolean isValidResult = isStaticsOK && isAccessible && isApplicable;
- if (!myAllVariants && isStaticsOK && isAccessible && PsiUtil.isApplicable(myArgumentTypes, method, substitutor, myPlace, myByShape)) {
- addCandidate(new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
+ GroovyResolveResultImpl candidate = new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK, false, isValidResult);
+
+ if (!myAllVariants && isValidResult) {
+ addCandidate(candidate);
}
else {
- myInapplicableCandidates.add(new GroovyResolveResultImpl(method, resolveContext, spreadState, substitutor, isAccessible, isStaticsOK));
+ myInapplicableCandidates.add(candidate);
}
-
- return true;
}
return true;
}
@NotNull
+ private PsiSubstitutor inferSubstitutor(@NotNull PsiMethod method, @NotNull ResolveState state) {
+ PsiSubstitutor substitutor = state.get(PsiSubstitutor.KEY);
+ if (substitutor == null) substitutor = PsiSubstitutor.EMPTY;
+
+ return myByShape ? substitutor
+ : mySubstitutorComputer.obtainSubstitutor(substitutor, method, state);
+ }
+
+ @Override
+ @NotNull
public GroovyResolveResult[] getCandidates() {
if (!myAllVariants && super.hasCandidates()) {
return filterCandidates();
@@ -148,7 +158,7 @@
result.add(candidate);
}
}
- if (result.size() > 0) return result;
+ if (!result.isEmpty()) return result;
return candidates;
}
@@ -220,7 +230,7 @@
return 0;
}
-
+
private static boolean isMoreConcreteThan(@NotNull PsiMethod method,
@NotNull final PsiSubstitutor substitutor,
@NotNull PsiMethod another,
@@ -230,7 +240,7 @@
final PsiParameter[] plusParameters = method.getParameterList().getParameters();
final PsiParameter[] defParameters = another.getParameterList().getParameters();
- final PsiType[] paramTypes = new PsiType[plusParameters.length];
+ final PsiType[] paramTypes = PsiType.createArray(plusParameters.length);
for (int i = 0; i < paramTypes.length; i++) {
paramTypes[i] = eliminateOneMethodInterfaces(plusParameters[i], defParameters, i);
@@ -270,7 +280,7 @@
method1 = ((GrGdkMethod)method1).getStaticMethod();
method2 = ((GrGdkMethod)method2).getStaticMethod();
if (myArgumentTypes != null) {
- argTypes = new PsiType[argTypes.length + 1];
+ argTypes = PsiType.createArray(argTypes.length + 1);
System.arraycopy(myArgumentTypes, 0, argTypes, 1, myArgumentTypes.length);
argTypes[0] = myThisType;
}
@@ -345,6 +355,7 @@
}
+ @Override
public boolean hasCandidates() {
return super.hasCandidates() || !myInapplicableCandidates.isEmpty();
}
@@ -353,6 +364,7 @@
return super.hasCandidates();
}
+ @Override
@Nullable
public PsiType[] getArgumentTypes() {
return myArgumentTypes;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/SubstitutorComputer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/SubstitutorComputer.java
index fcefca0..01242d5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/SubstitutorComputer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/resolve/processors/SubstitutorComputer.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,11 +18,12 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
-import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.psi.util.*;
import com.intellij.util.containers.hash.HashSet;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
+import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
@@ -39,7 +40,9 @@
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrClosureParameter;
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.ClosureToSamConverter;
import org.jetbrains.plugins.groovy.lang.psi.util.GdkMethodUtil;
+import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import java.util.Set;
@@ -60,6 +63,7 @@
private final GrControlFlowOwner myFlowOwner;
private final PsiElement myPlaceToInferContext;
+ private PsiResolveHelper myHelper;
public SubstitutorComputer(PsiType thisType,
@@ -81,6 +85,9 @@
else {
myFlowOwner = null;
}
+
+ myHelper = JavaPsiFacade.getInstance(myPlace.getProject()).getResolveHelper();
+
}
@Nullable
@@ -126,7 +133,7 @@
final PsiElement resolveContext = state.get(ResolverProcessor.RESOLVE_CONTEXT);
if (method instanceof GrGdkMethod) {
//type inference should be performed from static method
- PsiType[] newArgTypes = new PsiType[argTypes.length + 1];
+ PsiType[] newArgTypes = PsiType.createArray(argTypes.length + 1);
if (GdkMethodUtil.isInWithContext(resolveContext)) {
newArgTypes[0] = ((GrExpression)resolveContext).getType();
}
@@ -146,10 +153,10 @@
return substitutor;
}
- private PsiSubstitutor inferMethodTypeParameters(PsiMethod method,
- PsiSubstitutor partialSubstitutor,
- final PsiTypeParameter[] typeParameters,
- final PsiType[] argTypes) {
+ private PsiSubstitutor inferMethodTypeParameters(@NotNull PsiMethod method,
+ @NotNull PsiSubstitutor partialSubstitutor,
+ @NotNull PsiTypeParameter[] typeParameters,
+ @NotNull PsiType[] argTypes) {
if (typeParameters.length == 0 || myArgumentTypes == null) return partialSubstitutor;
final GrClosureSignature erasedSignature = GrClosureSignatureUtil.createSignatureWithErasedParameterTypes(method);
@@ -163,8 +170,8 @@
int max = Math.max(params.length, argTypes.length);
- PsiType[] parameterTypes = new PsiType[max];
- PsiType[] argumentTypes = new PsiType[max];
+ PsiType[] parameterTypes = PsiType.createArray(max);
+ PsiType[] argumentTypes = PsiType.createArray(max);
int i = 0;
for (int paramIndex = 0; paramIndex < argInfos.length; paramIndex++) {
PsiType paramType = params[paramIndex].getType();
@@ -186,11 +193,10 @@
i++;
}
}
- final PsiResolveHelper helper = JavaPsiFacade.getInstance(method.getProject()).getResolveHelper();
- PsiSubstitutor substitutor = helper.inferTypeArguments(typeParameters, parameterTypes, argumentTypes, LanguageLevel.JDK_1_7);
+ PsiSubstitutor substitutor = myHelper.inferTypeArguments(typeParameters, parameterTypes, argumentTypes, LanguageLevel.JDK_1_7);
for (PsiTypeParameter typeParameter : typeParameters) {
if (!substitutor.getSubstitutionMap().containsKey(typeParameter)) {
- substitutor = inferFromContext(typeParameter, PsiUtil.getSmartReturnType(method), substitutor, helper);
+ substitutor = inferFromContext(typeParameter, PsiUtil.getSmartReturnType(method), substitutor);
if (!substitutor.getSubstitutionMap().containsKey(typeParameter)) {
substitutor = substitutor.put(typeParameter, null);
}
@@ -200,7 +206,16 @@
return partialSubstitutor.putAll(substitutor);
}
- private PsiType handleConversion(PsiType paramType, PsiType argType) {
+ @Nullable
+ private PsiType handleConversion(@Nullable PsiType paramType, @Nullable PsiType argType) {
+ if (GroovyConfigUtils.getInstance().isVersionAtLeast(myPlace, GroovyConfigUtils.GROOVY2_2_2) &&
+ InheritanceUtil.isInheritor(argType, GroovyCommonClassNames.GROOVY_LANG_CLOSURE)) {
+ PsiType converted = handleConversionOfSAMType(paramType, (PsiClassType)argType);
+ if (converted != null) {
+ return converted;
+ }
+ }
+
if (!TypesUtil.isAssignable(TypeConversionUtil.erasure(paramType), argType, myPlace) &&
TypesUtil.isAssignableByMethodCallConversion(paramType, argType, myPlace)) {
return paramType;
@@ -208,13 +223,42 @@
return argType;
}
- private PsiSubstitutor inferFromContext(PsiTypeParameter typeParameter,
- PsiType lType,
- PsiSubstitutor substitutor,
- PsiResolveHelper helper) {
+ @Nullable
+ private PsiType handleConversionOfSAMType(@Nullable PsiType samType, @NotNull PsiClassType closure) {
+ if (samType instanceof PsiClassType) {
+ PsiClassType.ClassResolveResult resolveResult = ((PsiClassType)samType).resolveGenerics();
+ PsiClass samClass = resolveResult.getElement();
+
+ if (samClass != null && samClass.getTypeParameters().length != 0) {
+ MethodSignature samSignature = ClosureToSamConverter.findSingleAbstractMethod(samClass, PsiSubstitutor.EMPTY);
+ if (samSignature != null) {
+
+ PsiMethod samMethod = MethodSignatureUtil.findMethodBySignature(samClass, samSignature, true);
+ if (samMethod != null) {
+ PsiType[] closureArgs = closure.getParameters();
+ if (closureArgs.length == 1 && samMethod.getReturnType() != null) {
+ PsiSubstitutor substitutor = myHelper.inferTypeArguments(samClass.getTypeParameters(),
+ new PsiType[]{samMethod.getReturnType()},
+ closureArgs,
+ LanguageLevel.JDK_1_7);
+
+ return JavaPsiFacade.getElementFactory(myPlace.getProject()).createType(samClass, substitutor);
+ }
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+ private PsiSubstitutor inferFromContext(@NotNull PsiTypeParameter typeParameter,
+ @Nullable PsiType lType,
+ @NotNull PsiSubstitutor substitutor) {
if (myPlace == null) return substitutor;
- final PsiType inferred = helper.getSubstitutionForTypeParameter(typeParameter, lType, inferContextType(), false, LanguageLevel.JDK_1_7);
+ final PsiType inferred = myHelper.getSubstitutionForTypeParameter(typeParameter, lType, inferContextType(), false, LanguageLevel.JDK_1_7);
if (inferred != PsiType.NULL) {
return substitutor.put(typeParameter, inferred);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java
index 918fa27..7a51955 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/stubs/GroovyShortNamesCache.java
@@ -32,6 +32,9 @@
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.api.statements.GrField;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAnnotationMethod;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.lang.psi.impl.search.GrSourceFilterScope;
import org.jetbrains.plugins.groovy.lang.psi.stubs.index.*;
@@ -65,7 +68,8 @@
public List<PsiClass> getScriptClassesByFQName(final String name, final GlobalSearchScope scope, final boolean srcOnly) {
GlobalSearchScope actualScope = srcOnly ? new GrSourceFilterScope(scope) : scope;
- final Collection<GroovyFile> files = StubIndex.getInstance().get(GrFullScriptNameIndex.KEY, name.hashCode(), myProject, actualScope);
+ final Collection<GroovyFile> files = StubIndex.getElements(GrFullScriptNameIndex.KEY, name.hashCode(), myProject, actualScope,
+ GroovyFile.class);
if (files.isEmpty()) {
return Collections.emptyList();
}
@@ -97,8 +101,8 @@
private List<PsiClass> addClasses(String name, GlobalSearchScope scope, boolean inSource) {
final List<PsiClass> result = new ArrayList<PsiClass>(getScriptClassesByFQName(name, scope, inSource));
- for (PsiElement psiClass : StubIndex.getInstance().safeGet(GrFullClassNameIndex.KEY, name.hashCode(), myProject,
- inSource ? new GrSourceFilterScope(scope) : scope, PsiClass.class)) {
+ for (PsiElement psiClass : StubIndex.getElements(GrFullClassNameIndex.KEY, name.hashCode(), myProject,
+ inSource ? new GrSourceFilterScope(scope) : scope, PsiClass.class)) {
//hashcode doesn't guarantee equals
if (name.equals(((PsiClass)psiClass).getQualifiedName())) {
result.add((PsiClass)psiClass);
@@ -122,8 +126,11 @@
@Override
@NotNull
public PsiMethod[] getMethodsByName(@NonNls @NotNull String name, @NotNull GlobalSearchScope scope) {
- final Collection<? extends PsiMethod> methods = StubIndex.getInstance().get(GrMethodNameIndex.KEY, name, myProject, new GrSourceFilterScope(scope));
- final Collection<? extends PsiMethod> annMethods = StubIndex.getInstance().get(GrAnnotationMethodNameIndex.KEY, name, myProject, new GrSourceFilterScope(scope));
+ final Collection<? extends PsiMethod> methods = StubIndex.getElements(GrMethodNameIndex.KEY, name, myProject,
+ new GrSourceFilterScope(scope), GrMethod.class);
+ final Collection<? extends PsiMethod> annMethods = StubIndex.getElements(GrAnnotationMethodNameIndex.KEY, name, myProject,
+ new GrSourceFilterScope(scope),
+ GrAnnotationMethod.class);
if (methods.isEmpty() && annMethods.isEmpty()) return PsiMethod.EMPTY_ARRAY;
return ArrayUtil.mergeCollections(annMethods, methods, PsiMethod.ARRAY_FACTORY);
}
@@ -173,7 +180,8 @@
@Override
@NotNull
public PsiField[] getFieldsByName(@NotNull @NonNls String name, @NotNull GlobalSearchScope scope) {
- final Collection<? extends PsiField> fields = StubIndex.getInstance().get(GrFieldNameIndex.KEY, name, myProject, new GrSourceFilterScope(scope));
+ final Collection<? extends PsiField> fields = StubIndex.getElements(GrFieldNameIndex.KEY, name, myProject,
+ new GrSourceFilterScope(scope), GrField.class);
if (fields.isEmpty()) return PsiField.EMPTY_ARRAY;
return fields.toArray(new PsiField[fields.size()]);
}
@@ -203,7 +211,8 @@
@NotNull Processor<? super PsiClass> processor,
@NotNull GlobalSearchScope scope,
@Nullable IdFilter filter) {
- for (GroovyFile file : StubIndex.getInstance().get(GrScriptClassNameIndex.KEY, name, myProject, new GrSourceFilterScope(scope), filter)) {
+ for (GroovyFile file : StubIndex.getElements(GrScriptClassNameIndex.KEY, name, myProject, new GrSourceFilterScope(scope), filter,
+ GroovyFile.class)) {
PsiClass aClass = file.getScriptClass();
if (aClass != null && !processor.process(aClass)) return true;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java
index 83cd58f..55f0129 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/GroovySdkForProjectFromSourcesStep.java
@@ -18,6 +18,7 @@
import com.intellij.ide.util.importProject.ModuleDescriptor;
import com.intellij.ide.util.importProject.ProjectDescriptor;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
+import com.intellij.ide.util.projectWizard.importSources.DetectedSourceRoot;
import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder;
import com.intellij.openapi.module.StdModuleTypes;
@@ -47,7 +48,7 @@
super.updateDataModel();
List<ModuleDescriptor> modules = new ArrayList<ModuleDescriptor>();
for (DetectedProjectRoot root : myBuilder.getProjectRoots(myDetector)) {
- final ModuleDescriptor descriptor = new ModuleDescriptor(root.getDirectory(), StdModuleTypes.JAVA, Collections.<DetectedProjectRoot>emptyList());
+ final ModuleDescriptor descriptor = new ModuleDescriptor(root.getDirectory(), StdModuleTypes.JAVA, Collections.<DetectedSourceRoot>emptyList());
descriptor.addConfigurationUpdater(createModuleConfigurationUpdater());
modules.add(descriptor);
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
index 992b078..3617ad1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
@@ -131,7 +131,7 @@
if (Messages.showYesNoDialog(module.getProject(), "Cannot generate " + getDisplayName() + " project structure because JDK is not specified for module \"" +
module.getName() + "\".\n" +
getDisplayName() + " project will not be created if you don't specify JDK.\nDo you want to specify JDK?",
- "Error", Messages.getErrorIcon()) == 1) {
+ "Error", Messages.getErrorIcon()) == Messages.NO) {
return;
}
ProjectSettingsService.getInstance(module.getProject()).showModuleConfigurationDialog(module.getName(), ClasspathEditor.NAME);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleBuilder.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleBuilder.java
index 399a99d..5bfa4c6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleBuilder.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleBuilder.java
@@ -35,4 +35,9 @@
protected MvcFramework getFramework() {
return myFramework;
}
+
+ @Override
+ public boolean isTemplate() {
+ return true;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java
index b2d0257..8c9eed5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcModuleStructureSynchronizer.java
@@ -24,6 +24,9 @@
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleUtilCore;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
+import com.intellij.openapi.progress.util.ReadTask;
import com.intellij.openapi.project.DumbAwareRunnable;
import com.intellij.openapi.project.ModuleAdapter;
import com.intellij.openapi.project.Project;
@@ -54,7 +57,7 @@
* @author peter
*/
public class MvcModuleStructureSynchronizer extends AbstractProjectComponent {
- private final Set<Pair<Object, SyncAction>> myActions = new LinkedHashSet<Pair<Object, SyncAction>>();
+ private final Set<Pair<Object, SyncAction>> myOrders = new LinkedHashSet<Pair<Object, SyncAction>>();
private Set<VirtualFile> myPluginRoots = Collections.emptySet();
@@ -240,29 +243,77 @@
private void queue(SyncAction action, Object on) {
ApplicationManager.getApplication().assertIsDispatchThread();
+ if (myProject.isDisposed()) return;
- if (myActions.isEmpty()) {
- if (myProject.isDisposed()) return;
+ boolean shouldSchedule;
+ synchronized (myOrders) {
+ shouldSchedule = myOrders.isEmpty();
+ myOrders.add(new Pair<Object, SyncAction>(on, action));
+ }
+ if (shouldSchedule) {
StartupManager.getInstance(myProject).runWhenProjectIsInitialized(new DumbAwareRunnable() {
@Override
public void run() {
- Application app = ApplicationManager.getApplication();
- if (!app.isUnitTestMode()) {
- app.invokeLater(new Runnable() {
- @Override
- public void run() {
- runActions();
- }
- }, ModalityState.NON_MODAL);
- }
- else {
- runActions();
- }
+ scheduleRunActions();
}
});
}
+ }
- myActions.add(new Pair<Object, SyncAction>(on, action));
+ private void scheduleRunActions() {
+ if (myProject.isDisposed()) return;
+
+ final Application app = ApplicationManager.getApplication();
+ if (app.isUnitTestMode()) {
+ if (ourGrailsTestFlag && !myProject.isInitialized()) {
+ runActions(computeRawActions(takeOrderSnapshot()));
+ }
+ return;
+ }
+
+ app.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ final Set<Pair<Object, SyncAction>> orderSnapshot = takeOrderSnapshot();
+ ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ReadTask() {
+ @Override
+ public void computeInReadAction(@NotNull ProgressIndicator indicator) {
+ if (!isUpToDate()) {
+ indicator.cancel();
+ return;
+ }
+
+ final Set<Trinity<Module, SyncAction, MvcFramework>> actions = computeRawActions(orderSnapshot);
+ app.invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (!isUpToDate()) {
+ scheduleRunActions();
+ }
+ else {
+ runActions(actions);
+ }
+ }
+ }, ModalityState.NON_MODAL);
+ }
+
+ @Override
+ public void onCanceled(@NotNull ProgressIndicator indicator) {
+ scheduleRunActions();
+ }
+
+ private boolean isUpToDate() {
+ return !myProject.isDisposed() && orderSnapshot.equals(takeOrderSnapshot());
+ }
+ });
+ }
+ });
+ }
+
+ private LinkedHashSet<Pair<Object, SyncAction>> takeOrderSnapshot() {
+ synchronized (myOrders) {
+ return new LinkedHashSet<Pair<Object, SyncAction>>(myOrders);
+ }
}
@NotNull
@@ -289,41 +340,15 @@
@TestOnly
public static void forceUpdateProject(Project project) {
- project.getComponent(MvcModuleStructureSynchronizer.class).runActions();
+ MvcModuleStructureSynchronizer instance = project.getComponent(MvcModuleStructureSynchronizer.class);
+ instance.runActions(instance.computeRawActions(instance.takeOrderSnapshot()));
}
- private void runActions() {
+ private void runActions(Set<Trinity<Module, SyncAction, MvcFramework>> actions) {
try {
- if (myProject.isDisposed()) {
- return;
- }
-
- if (ApplicationManager.getApplication().isUnitTestMode() && !ourGrailsTestFlag) {
- return;
- }
-
- @SuppressWarnings("unchecked") Pair<Object, SyncAction>[] actions = myActions.toArray(new Pair[myActions.size()]);
- //get module by object and kill duplicates
-
- final Set<Trinity<Module, SyncAction, MvcFramework>> rawActions = new LinkedHashSet<Trinity<Module, SyncAction, MvcFramework>>();
-
- for (final Pair<Object, SyncAction> pair : actions) {
- for (Module module : determineModuleBySyncActionObject(pair.first)) {
- if (!module.isDisposed()) {
- final MvcFramework framework = (pair.second == SyncAction.CreateAppStructureIfNeeded)
- ? MvcFramework.getInstanceBySdk(module)
- : MvcFramework.getInstance(module);
-
- if (framework != null && !framework.isAuxModule(module)) {
- rawActions.add(Trinity.create(module, pair.second, framework));
- }
- }
- }
- }
-
boolean isProjectStructureUpdated = false;
- for (final Trinity<Module, SyncAction, MvcFramework> rawAction : rawActions) {
+ for (final Trinity<Module, SyncAction, MvcFramework> rawAction : actions) {
final Module module = rawAction.first;
if (module.isDisposed()) {
continue;
@@ -341,10 +366,31 @@
// if there were any actions added during performSyncAction, clear them too
// all needed actions are already added to buffer and have thus been performed
// otherwise you may get repetitive 'run create-app?' questions
- myActions.clear();
+ synchronized (myOrders) {
+ myOrders.clear();
+ }
}
}
+ private Set<Trinity<Module, SyncAction, MvcFramework>> computeRawActions(Set<Pair<Object, SyncAction>> actions) {
+ //get module by object and kill duplicates
+ final Set<Trinity<Module, SyncAction, MvcFramework>> rawActions = new LinkedHashSet<Trinity<Module, SyncAction, MvcFramework>>();
+ for (final Pair<Object, SyncAction> pair : actions) {
+ for (Module module : determineModuleBySyncActionObject(pair.first)) {
+ if (!module.isDisposed()) {
+ final MvcFramework framework = (pair.second == SyncAction.CreateAppStructureIfNeeded)
+ ? MvcFramework.getInstanceBySdk(module)
+ : MvcFramework.getInstance(module);
+
+ if (framework != null && !framework.isAuxModule(module)) {
+ rawActions.add(Trinity.create(module, pair.second, framework));
+ }
+ }
+ }
+ }
+ return rawActions;
+ }
+
private enum SyncAction {
SyncLibrariesInPluginsModule {
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcProjectWithoutLibraryNotificator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcProjectWithoutLibraryNotificator.java
index 7445188..8871a43 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcProjectWithoutLibraryNotificator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcProjectWithoutLibraryNotificator.java
@@ -1,20 +1,33 @@
+/*
+ * 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.mvc;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
-import com.intellij.openapi.application.AccessToken;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
+import com.intellij.openapi.progress.util.ReadTask;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.CommonClassNames;
-import com.intellij.psi.JavaPsiFacade;
-import com.intellij.psi.search.GlobalSearchScope;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -24,44 +37,41 @@
* @author Sergey Evdokimov
*/
public class MvcProjectWithoutLibraryNotificator implements StartupActivity, DumbAware {
-
@Override
public void runActivity(@NotNull final Project project) {
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ ProgressIndicatorUtils.scheduleWithWriteActionPriority(new ReadTask() {
@Override
- public void run() {
- AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
+ public void computeInReadAction(@NotNull ProgressIndicator indicator) {
+ if (project.isDisposed()) {
+ return;
+ }
- try {
- if (JavaPsiFacade.getInstance(project).findClass(CommonClassNames.JAVA_LANG_OBJECT, GlobalSearchScope.allScope(project)) == null) {
- return; // If indexes is corrupted JavaPsiFacade.findClass() can't find classes during StartupActivity (may be it's a bug).
- // So we can't determine whether exists Grails library or not.
- }
+ Pair<Module, MvcFramework> pair = findModuleWithoutLibrary(project);
- Pair<Module, MvcFramework> pair = findModuleWithoutLibrary(project);
+ if (pair != null) {
+ final MvcFramework framework = pair.second;
+ final Module module = pair.first;
- if (pair != null) {
- final MvcFramework framework = pair.second;
- final Module module = pair.first;
-
- new Notification(framework.getFrameworkName() + ".Configure",
- framework.getFrameworkName() + " SDK not found.",
- "<html><body>Module '" +
- module.getName() +
- "' has no " +
- framework.getFrameworkName() +
- " SDK. <a href='create'>Configure SDK</a></body></html>", NotificationType.INFORMATION,
- new NotificationListener.Adapter() {
- @Override
- protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
+ String name = framework.getFrameworkName();
+ String content = "<html><body>Module '" + module.getName() + "' has no " + name + " SDK. <a href='create'>Configure SDK</a></body></html>";
+ new Notification(name + ".Configure",
+ name + " SDK not found",
+ content, NotificationType.INFORMATION,
+ new NotificationListener.Adapter() {
+ @Override
+ protected void hyperlinkActivated(@NotNull Notification notification, @NotNull HyperlinkEvent e) {
+ if (!module.isDisposed()) {
MvcConfigureNotification.configure(framework, module);
}
- }).notify(project);
- }
+ }
+ }
+ ).notify(project);
}
- finally {
- accessToken.finish();
- }
+ }
+
+ @Override
+ public void onCanceled(@NotNull ProgressIndicator indicator) {
+ ProgressIndicatorUtils.scheduleWithWriteActionPriority(this);
}
});
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java
index 9be41eb..30e158c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java
@@ -168,7 +168,7 @@
}
private void createUIComponents() {
- myTargetField = new ComboBox(MvcRunTargetHistoryService.getInstance().getHistory(), -1);
+ myTargetField = new ComboBox(MvcRunTargetHistoryService.getInstance().getHistory());
myTargetField.setLightWeightPopupEnabled(false);
EditorComboBoxEditor editor = new StringComboboxEditor(myModule.getProject(), PlainTextFileType.INSTANCE, myTargetField);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java
index dab3cfe..c2a23fa 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideImplementUtil.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.
@@ -94,18 +94,19 @@
GrParameter[] parameters = result.getParameters();
for (int i = 0; i < parameters.length; i++) {
GrParameter parameter = parameters[i];
- final PsiParameter original = originalParams[i];
+ PsiParameter original = originalParams[i];
for (PsiAnnotation annotation : original.getModifierList().getAnnotations()) {
final GrModifierList modifierList = parameter.getModifierList();
String qname = annotation.getQualifiedName();
-
- if (annotation instanceof GrAnnotation) {
- modifierList.add(annotation);
- }
- else {
- modifierList.add(factory.createAnnotationFromText(annotation.getText()));
+ if (qname != null && modifierList.findAnnotation(qname) == null) {
+ if (annotation instanceof GrAnnotation) {
+ modifierList.add(annotation);
+ }
+ else {
+ modifierList.add(factory.createAnnotationFromText(annotation.getText()));
+ }
}
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java
index 364107f..324cf28 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/overrideImplement/GroovyOverrideMethodsHandler.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,7 @@
package org.jetbrains.plugins.groovy.overrideImplement;
import com.intellij.codeInsight.CodeInsightUtilBase;
+import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.codeInsight.hint.HintManager;
import com.intellij.lang.LanguageCodeInsightActionHandler;
@@ -40,7 +41,7 @@
PsiClass aClass = OverrideImplementUtil.getContextClass(project, editor, file, true);
if (aClass == null) return;
- if (OverrideImplementUtil.getMethodSignaturesToOverride(aClass).isEmpty()) {
+ if (OverrideImplementExploreUtil.getMethodSignaturesToOverride(aClass).isEmpty()) {
HintManager.getInstance().showErrorHint(editor, "No methods to override have been found");
return;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.java
index ab4d587..8a6fc6f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,6 +16,7 @@
package org.jetbrains.plugins.groovy.refactoring;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.GroovyBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.PropertyKey;
@@ -31,19 +32,16 @@
*/
public class GroovyRefactoringBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls
- private static final String BUNDLE = "org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle";
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls
+ private static final String BUNDLE = "org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle";
- if (ourBundle != null) bundle = ourBundle.get();
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
@@ -51,5 +49,4 @@
}
return bundle;
}
-
}
\ No newline at end of file
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java
index feca69e..961cd88 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringUtil.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.
@@ -36,7 +36,7 @@
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.IncorrectOperationException;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -53,6 +53,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
@@ -64,6 +65,8 @@
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeArgumentList;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrStatementOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrVariableDeclarationOwner;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
+import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import java.util.*;
@@ -91,11 +94,11 @@
PsiElement element2 = file.getViewProvider().findElementAt(endOffset - 1, file.getLanguage());
if (element1 == null || element2 == null) return null;
- if (TokenSets.WHITE_SPACES_SET.contains(element1.getNode().getElementType())) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(element1)) {
startOffset = element1.getTextRange().getEndOffset();
element1 = file.getViewProvider().findElementAt(startOffset, file.getLanguage());
}
- if (TokenSets.WHITE_SPACES_SET.contains(element2.getNode().getElementType())) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(element2)) {
endOffset = element2.getTextRange().getStartOffset();
element2 = file.getViewProvider().findElementAt(endOffset - 1, file.getLanguage());
}
@@ -103,13 +106,30 @@
if (element2 == null || element1 == null) return null;
final PsiElement commonParent = PsiTreeUtil.findCommonParent(element1, element2);
assert commonParent != null;
- final T element = ReflectionCache.isAssignable(klass, commonParent.getClass()) ? (T) commonParent : PsiTreeUtil.getParentOfType(commonParent, klass);
- if (element == null || element.getTextRange().getStartOffset() != startOffset) {
+ final T element = ReflectionUtil.isAssignable(klass, commonParent.getClass()) ? (T) commonParent : PsiTreeUtil.getParentOfType(commonParent, klass);
+ if (element == null) {
return null;
}
+
+ if (!checkRanges(element, startOffset, endOffset)) {
+ return null;
+ }
+
return element;
}
+ private static boolean checkRanges(@NotNull PsiElement element, int startOffset, int endOffset) {
+ if (element instanceof GrLiteral && StringPartInfo.isWholeLiteralContentSelected((GrLiteral)element, startOffset, endOffset)) {
+ return true;
+ }
+
+ if (element.getTextRange().getStartOffset() == startOffset) {
+ return true;
+ }
+
+ return false;
+ }
+
public static PsiElement[] getExpressionOccurrences(@NotNull PsiElement expr, @NotNull PsiElement scope) {
ArrayList<PsiElement> occurrences = new ArrayList<PsiElement>();
Comparator<PsiElement> comparator = new Comparator<PsiElement>() {
@@ -772,4 +792,20 @@
}
});
}
+
+ public static boolean isSpreadAssignment(GrExpression lValue) {
+ if (lValue instanceof GrReferenceExpression) {
+ GrReferenceExpression expression = (GrReferenceExpression)lValue;
+ final PsiElement dot = expression.getDotToken();
+ //noinspection ConstantConditions
+ if (dot != null && dot.getNode().getElementType() == GroovyTokenTypes.mSPREAD_DOT) {
+ return true;
+ }
+ else {
+ final GrExpression qualifier = expression.getQualifierExpression();
+ if (qualifier != null) return isSpreadAssignment(qualifier);
+ }
+ }
+ return false;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java
index 0cd6775..0b78e3c 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/changeSignature/GrChageSignatureUsageSearcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -267,9 +267,7 @@
private static void addParameterUsages(PsiParameter parameter, ArrayList<UsageInfo> results, ParameterInfo info) {
- PsiManager manager = parameter.getManager();
- GlobalSearchScope projectScope = GlobalSearchScope.projectScope(manager.getProject());
- for (PsiReference psiReference : ReferencesSearch.search(parameter, projectScope, false)) {
+ for (PsiReference psiReference : ReferencesSearch.search(parameter)) {
PsiElement parmRef = psiReference.getElement();
UsageInfo usageInfo = new ChangeSignatureParameterUsageInfo(parmRef, parameter.getName(), info.getName());
results.add(usageInfo);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java
index 156e1d8..03290f5 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/AnonymousFromMapGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -68,9 +68,10 @@
final GrExpression expression = arg.getExpression();
if (name == null || expression == null || !(expression instanceof GrClosableBlock)) continue;
- final GrParameter[] allParameters = ((GrClosableBlock)expression).getAllParameters();
+ final GrClosableBlock closure = (GrClosableBlock)expression;
+ final GrParameter[] allParameters = closure.getAllParameters();
List<GrParameter> actual = new ArrayList<GrParameter>(Arrays.asList(allParameters));
- final PsiType clReturnType = ((GrClosableBlock)expression).getReturnType();
+ final PsiType clReturnType = context.typeProvider.getReturnType(closure);
GrExpression[] args = new GrExpression[allParameters.length];
for (int i = 0; i < allParameters.length; i++) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java
index 7f04df7..17d2892 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ClosureGenerator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -34,6 +34,7 @@
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl;
import java.util.Collection;
+import java.util.Collections;
import static org.jetbrains.plugins.groovy.refactoring.convertToJava.TypeWriter.writeType;
import static org.jetbrains.plugins.groovy.refactoring.convertToJava.TypeWriter.writeTypeForNew;
@@ -85,15 +86,15 @@
private void generateClosureMainMethod(@NotNull GrClosableBlock block) {
builder.append("public ");
- final PsiType returnType = block.getReturnType();
+ final PsiType returnType = context.typeProvider.getReturnType(block);
writeType(builder, returnType, block);
builder.append(" doCall");
final GrParameter[] parameters = block.getAllParameters();
GenerationUtil.writeParameterList(builder, parameters, new GeneratorClassNameProvider(), context);
- Collection<GrStatement> myExitPoints = ControlFlowUtils.collectReturns(block);
- boolean shouldInsertReturnNull =
- !(returnType instanceof PsiPrimitiveType) && MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.shouldNotReturnValue);
+ Collection<GrStatement> myExitPoints = returnType != PsiType.VOID ? ControlFlowUtils.collectReturns(block) : Collections.<GrStatement>emptySet();
+ boolean shouldInsertReturnNull = !(returnType instanceof PsiPrimitiveType) &&
+ MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.shouldNotReturnValue);
new CodeBlockGenerator(builder, context.extend(), myExitPoints).generateCodeBlock(block, shouldInsertReturnNull);
builder.append('\n');
@@ -104,7 +105,7 @@
final GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(context.project);
final GrMethod method = factory.createMethodFromText("def doCall(){}", block);
- method.setReturnType(block.getReturnType());
+ method.setReturnType(context.typeProvider.getReturnType(block));
if (block.hasParametersSection()) {
method.getParameterList().replace(block.getParameterList());
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java
index 739c6a9..51d39ae 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerator.java
@@ -101,14 +101,18 @@
public void generateMethodBody(GrMethod method) {
final GrOpenBlock block = method.getBlock();
- boolean shouldInsertReturnNull = false;
+ boolean shouldInsertReturnNull;
myExitPoints.clear();
PsiType returnType = context.typeProvider.getReturnType(method);
if (!method.isConstructor() && returnType != PsiType.VOID) {
myExitPoints.addAll(ControlFlowUtils.collectReturns(block));
- shouldInsertReturnNull = block != null && !(returnType instanceof PsiPrimitiveType) &&
- MissingReturnInspection.methodMissesSomeReturns(block,
- MissingReturnInspection.ReturnStatus.getReturnStatus(method));
+ shouldInsertReturnNull = block != null &&
+ !(returnType instanceof PsiPrimitiveType) &&
+ MissingReturnInspection.methodMissesSomeReturns(block, MissingReturnInspection.ReturnStatus.getReturnStatus(
+ method));
+ }
+ else {
+ shouldInsertReturnNull = false;
}
if (block != null) {
@@ -186,9 +190,18 @@
return StringUtil.repeatSymbol('\n', count);
}
+
+ private void writeStatement(@Nullable GrStatement statement, @NotNull StatementWriter writer) {
+ GenerationUtil.writeStatement(builder, context, statement, writer);
+ }
+
+ private static void writeExpression(@NotNull GrExpression expression, @NotNull StringBuilder builder, @NotNull ExpressionContext context) {
+ expression.accept(new ExpressionGenerator(builder, context));
+ }
+
@Override
public void visitConstructorInvocation(final GrConstructorInvocation invocation) {
- GenerationUtil.writeStatement(builder, context, invocation, new StatementWriter() {
+ writeStatement(invocation, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
final GrReferenceExpression thisOrSuperKeyword = invocation.getInvokedExpression();
@@ -198,7 +211,7 @@
builder.append(thisOrSuperKeyword.getReferenceName());
}
else {
- thisOrSuperKeyword.accept(new ExpressionGenerator(builder, context));
+ writeExpression(thisOrSuperKeyword, builder, context);
}
new ArgumentListGenerator(builder, context).generate(
GrClosureSignatureUtil.createSignature(resolveResult),
@@ -236,7 +249,7 @@
return;
}
- GenerationUtil.writeStatement(builder, context, returnStatement, new StatementWriter() {
+ writeStatement(returnStatement, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
writeReturn(builder, context, returnValue);
@@ -244,36 +257,30 @@
});
}
- private void writeStatement(StringBuilder statementBuilder,
- GrStatement statement,
- @Nullable ExpressionContext context) {
- GenerationUtil.writeStatement(builder, statementBuilder, statement, context);
- }
-
@Override
public void visitAssertStatement(final GrAssertStatement assertStatement) {
final GrExpression assertion = assertStatement.getAssertion();
final GrExpression message = assertStatement.getErrorMessage();
if (assertion != null) {
- GenerationUtil.writeStatement(builder, context, assertStatement, new StatementWriter() {
+ writeStatement(assertStatement, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
builder.append("assert ");
- assertion.accept(new ExpressionGenerator(builder, context));
+ writeExpression(assertion, builder, context);
if (message != null) {
builder.append(" : ");
- message.accept(new ExpressionGenerator(builder, context));
+ writeExpression(message, builder, context);
}
builder.append(';');
}
});
}
else if (message != null) {
- GenerationUtil.writeStatement(builder, context, assertStatement, new StatementWriter() {
+ writeStatement(assertStatement, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
builder.append("assert : ");
- message.accept(new ExpressionGenerator(builder, context));
+ writeExpression(message, builder, context);
builder.append(';');
}
});
@@ -290,11 +297,11 @@
builder.append("throw ;");
return;
}
- GenerationUtil.writeStatement(builder, context, throwStatement, new StatementWriter() {
+ writeStatement(throwStatement, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
builder.append("throw ");
- exception.accept(new ExpressionGenerator(builder, context)); //todo add exception to method 'throws' list
+ writeExpression(exception, builder, context); //todo add exception to method 'throws' list
builder.append(';');
}
});
@@ -302,7 +309,7 @@
@Override
public void visitLabeledStatement(final GrLabeledStatement labeledStatement) {
- GenerationUtil.writeStatement(builder, context, labeledStatement, new StatementWriter() {
+ writeStatement(labeledStatement, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
final String label = labeledStatement.getName();
@@ -318,17 +325,27 @@
@Override
public void visitExpression(final GrExpression expression) {
- GenerationUtil.writeStatement(builder, context, expression, new StatementWriter() {
+ writeStatement(expression, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
- if (myExitPoints.contains(expression) && expression.getType() != PsiType.VOID) {
+ if (myExitPoints.contains(expression) && isRealExpression(expression)) {
writeReturn(builder, context, expression);
}
else {
- expression.accept(new ExpressionGenerator(builder, context));
+ writeExpression(expression, builder, context);
builder.append(';');
}
}
+
+ private boolean isRealExpression(GrExpression expression) {
+ final PsiType type = expression.getType();
+
+ if (type == PsiType.VOID) return false; //statement
+
+ if (type == PsiType.NULL) return !org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.isVoidMethodCall(expression);
+
+ return true;
+ }
});
}
@@ -336,12 +353,11 @@
builder.append("return ");
final PsiType expectedReturnType = PsiImplUtil.inferReturnType(expression);
- final PsiType nnReturnType =
- expectedReturnType == null || expectedReturnType == PsiType.VOID ? TypesUtil.getJavaLangObject(expression) : expectedReturnType;
+ final PsiType nnReturnType = expectedReturnType == null || expectedReturnType == PsiType.VOID ? TypesUtil.getJavaLangObject(expression) : expectedReturnType;
wrapInCastIfNeeded(builder, nnReturnType, expression.getNominalType(), expression, context, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
- expression.accept(new ExpressionGenerator(builder, context));
+ writeExpression(expression, builder, context);
}
});
builder.append(';');
@@ -359,7 +375,7 @@
@Override
public void visitIfStatement(final GrIfStatement ifStatement) {
- GenerationUtil.writeStatement(builder, context, ifStatement, new StatementWriter() {
+ writeStatement(ifStatement, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
final GrExpression condition = ifStatement.getCondition();
@@ -369,7 +385,7 @@
if (condition != null) {
final PsiType type = condition.getType();
if (TypesUtil.unboxPrimitiveTypeWrapper(type) == PsiType.BOOLEAN) {
- condition.accept(new ExpressionGenerator(builder, context));
+ writeExpression(condition, builder, context);
}
else {
invokeMethodByName(
@@ -403,7 +419,7 @@
builder.append(" : ");
if (expression != null) {
final ExpressionContext context = forContext.copy();
- expression.accept(new ExpressionGenerator(builder, context));
+ writeExpression(expression, builder, context);
}
}
else if (clause instanceof GrTraditionalForClause) {
@@ -419,19 +435,17 @@
if (initializer != null) {
final ExpressionContext partContext = forContext.copy();
partBuilder.append(" = ");
- initializer.accept(new ExpressionGenerator(partBuilder, partContext));
+ writeExpression(initializer, partBuilder, partContext);
for (String statement : partContext.myStatements) {
builder.append(statement).append(", ");
}
builder.append(partBuilder);
}
}
- else {
- if (initialization != null) {
- StringBuilder partBuilder = new StringBuilder();
- final ExpressionContext partContext = forContext.copy();
- genForPart(builder, initialization, new CodeBlockGenerator(partBuilder, partContext, null));
- }
+ else if (initialization != null) {
+ StringBuilder partBuilder = new StringBuilder();
+ final ExpressionContext partContext = forContext.copy();
+ genForPart(builder, initialization, new CodeBlockGenerator(partBuilder, partContext, null));
}
builder.append(';');
@@ -471,29 +485,33 @@
}
@Override
- public void visitWhileStatement(GrWhileStatement whileStatement) {
- final GrCondition condition = whileStatement.getCondition();
- final GrStatement body = whileStatement.getBody();
+ public void visitWhileStatement(final GrWhileStatement whileStatement) {
+ writeStatement(whileStatement, new StatementWriter() {
+ @Override
+ public void writeStatement(StringBuilder builder, ExpressionContext context) {
+ final GrExpression condition = whileStatement.getCondition();
+ final GrStatement body = whileStatement.getBody();
- StringBuilder builder = new StringBuilder();
- builder.append("while (");
- final ExpressionContext copy = context.copy();
- if (condition != null) {
- condition.accept(new ExpressionGenerator(builder, copy)); //todo update???
- }
- builder.append(" )");
- if (body != null) {
- body.accept(new CodeBlockGenerator(builder, copy.extend(), null));
- }
- writeStatement(builder, whileStatement, copy);
+ builder.append("while (");
+ if (condition != null) {
+ writeExpression(condition, builder, context);
+ }
+ builder.append(" )");
+ if (body != null) {
+ body.accept(new CodeBlockGenerator(builder, context.extend(), null));
+ }
+ }
+ });
}
@Override
- public void visitSwitchStatement(GrSwitchStatement switchStatement) {
- final StringBuilder builder = new StringBuilder();
- final ExpressionContext copy = context.copy();
- SwitchStatementGenerator.generate(builder, copy, switchStatement);
- writeStatement(builder, switchStatement, copy);
+ public void visitSwitchStatement(final GrSwitchStatement switchStatement) {
+ writeStatement(switchStatement, new StatementWriter() {
+ @Override
+ public void writeStatement(StringBuilder builder, ExpressionContext context) {
+ SwitchStatementGenerator.generate(builder, context, switchStatement);
+ }
+ });
}
@Override
@@ -538,23 +556,28 @@
}
@Override
- public void visitSynchronizedStatement(GrSynchronizedStatement synchronizedStatement) {
- final GrExpression monitor = synchronizedStatement.getMonitor();
- final GrOpenBlock body = synchronizedStatement.getBody();
+ public void visitSynchronizedStatement(final GrSynchronizedStatement statement) {
+ writeStatement(statement, new StatementWriter() {
+ @Override
+ public void writeStatement(StringBuilder builder, ExpressionContext context) {
+ final GrExpression monitor = statement.getMonitor();
+ final GrOpenBlock body = statement.getBody();
- StringBuilder statementBuilder = new StringBuilder();
- final ExpressionContext expressionContext = context.copy();
-
- statementBuilder.append("synchronized(");
- monitor.accept(new ExpressionGenerator(statementBuilder, expressionContext));
- statementBuilder.append(')');
- body.accept(new CodeBlockGenerator(statementBuilder, context.extend(), myExitPoints));
- writeStatement(statementBuilder, synchronizedStatement, expressionContext);
+ builder.append("synchronized(");
+ if (monitor != null ) {
+ writeExpression(monitor, builder, context);
+ }
+ builder.append(')');
+ if (body != null) {
+ body.accept(new CodeBlockGenerator(builder, context.extend(), myExitPoints));
+ }
+ }
+ });
}
@Override
public void visitVariableDeclaration(final GrVariableDeclaration variableDeclaration) {
- GenerationUtil.writeStatement(builder, context, variableDeclaration, new StatementWriter() {
+ writeStatement(variableDeclaration, new StatementWriter() {
@Override
public void writeStatement(StringBuilder builder, ExpressionContext context) {
if (variableDeclaration.isTuple()) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java
index 657f558..fb783b9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/ExpressionGenerator.java
@@ -55,6 +55,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
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.expressions.path.GrPropertySelection;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrAnonymousClassDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrGdkMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
@@ -1271,6 +1272,13 @@
}
@Override
+ public void visitPropertySelection(GrPropertySelection expression) {
+ expression.getQualifier().accept(this);
+ builder.append('.');
+ builder.append(expression.getReferenceNameElement().getText());
+ }
+
+ @Override
public void visitIndexProperty(GrIndexProperty expression) {
final GrExpression selectedExpression = expression.getInvokedExpression();
final PsiType thisType = selectedExpression.getType();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java
index 7b0769c..8af18d6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/GenerationUtil.java
@@ -248,7 +248,7 @@
}
}
- public static void writeStatement(final StringBuilder builder, ExpressionContext context, @Nullable GrStatement statement, StatementWriter writer) {
+ public static void writeStatement(@NotNull StringBuilder builder, @NotNull ExpressionContext context, @Nullable GrStatement statement, @NotNull StatementWriter writer) {
StringBuilder statementBuilder = new StringBuilder();
ExpressionContext statementContext = context.copy();
writer.writeStatement(statementBuilder, statementContext);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SwitchStatementGenerator.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SwitchStatementGenerator.java
index e88868b..b973288 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SwitchStatementGenerator.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/SwitchStatementGenerator.java
@@ -17,8 +17,10 @@
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
import com.intellij.psi.PsiType;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrSwitchStatement;
@@ -94,46 +96,11 @@
final boolean isCase = labels.length > 1 || !labels[0].isDefault();
if (isCase) {
- builder.append("if (");
- for (GrCaseLabel label : labels) {
- if (label.isDefault()) {
- builder.append("true");
- }
- else {
- GenerationUtil.invokeMethodByName(
- label.getValue(),
- "isCase",
- args,
- GrNamedArgument.EMPTY_ARRAY,
- GrClosableBlock.EMPTY_ARRAY,
- new ExpressionGenerator(builder, context),
- section
- );
- }
- builder.append("||");
- }
- builder.delete(builder.length() - 2, builder.length());
- builder.append(") ");
+ writeCondition(builder, context, section, labels, args);
}
- builder.append("{\n");
- final ExpressionContext extended = context.extend();
- CodeBlockGenerator generator = new CodeBlockGenerator(builder, extended);
+ writeCaseBody(builder, context, i, caseSections);
- Outer:
- for (int j = i; j < caseSections.length; j++) {
- section = caseSections[j];
- final GrStatement[] statements = section.getStatements();
- for (GrStatement statement : statements) {
- if (statement instanceof GrBreakStatement && ((GrBreakStatement)statement).getLabelIdentifier() == null) {
- break Outer;
- }
- statement.accept(generator);
- builder.append("\n");
- }
- }
-
- builder.append('}');
- if (isCase && i + 1 < caseSections.length) {
+ if (isCase && i != caseSections.length - 1) {
builder.append("\nelse ");
StringBuilder elseBuilder = new StringBuilder();
final ExpressionContext elseContext = context.extend();
@@ -149,6 +116,64 @@
});
}
+ private static void writeCaseBody(@NotNull StringBuilder builder,
+ @NotNull ExpressionContext context,
+ int i,
+ @NotNull GrCaseSection[] caseSections) {
+ builder.append("{\n");
+
+ final ExpressionContext extended = context.extend();
+ CodeBlockGenerator generator = new CodeBlockGenerator(builder, extended);
+
+ Outer:
+ for (int j = i; j < caseSections.length; j++) {
+ GrCaseSection curSection = caseSections[j];
+ final GrStatement[] statements = curSection.getStatements();
+ for (GrStatement statement : statements) {
+ if (statement instanceof GrBreakStatement && ((GrBreakStatement)statement).getLabelIdentifier() == null) {
+ break Outer;
+ }
+ statement.accept(generator);
+ builder.append("\n");
+ }
+ if (brakesFlow(curSection)) break;
+ }
+
+ builder.append('}');
+ }
+
+ private static boolean brakesFlow(GrCaseSection section) {
+ final GrStatement[] statements = section.getStatements();
+ return statements.length > 0 && !ControlFlowUtils.statementMayCompleteNormally(ArrayUtil.getLastElement(statements));
+ }
+
+ private static void writeCondition(StringBuilder builder,
+ ExpressionContext context,
+ GrCaseSection section,
+ GrCaseLabel[] labels,
+ GrExpression[] args) {
+ builder.append("if (");
+ for (GrCaseLabel label : labels) {
+ if (label.isDefault()) {
+ builder.append("true");
+ }
+ else {
+ GenerationUtil.invokeMethodByName(
+ label.getValue(),
+ "isCase",
+ args,
+ GrNamedArgument.EMPTY_ARRAY,
+ GrClosableBlock.EMPTY_ARRAY,
+ new ExpressionGenerator(builder, context),
+ section
+ );
+ }
+ builder.append("||");
+ }
+ builder.delete(builder.length() - 2, builder.length());
+ builder.append(") ");
+ }
+
private static String generateConditionVar(@NotNull StringBuilder builder,
@NotNull ExpressionContext context,
@NotNull GrExpression condition) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java
index 9870962..55df1da 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeProvider.java
@@ -25,6 +25,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
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.GrCall;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
@@ -55,7 +56,9 @@
if (typeElement != null) return typeElement.getType();
}
final PsiType smartReturnType = PsiUtil.getSmartReturnType(method);
- if (smartReturnType != null) return smartReturnType;
+ if (smartReturnType != null && !PsiType.NULL.equals(smartReturnType)) return smartReturnType;
+
+ if (PsiType.NULL.equals(smartReturnType) && PsiUtil.isVoidMethod(method)) return PsiType.VOID;
//todo make smarter. search for usages and infer type from them
return TypesUtil.getJavaLangObject(method);
@@ -113,7 +116,7 @@
final GrParameter[] parameters = method.getParameters();
final TIntArrayList paramInds = new TIntArrayList(parameters.length);
- final PsiType[] types = new PsiType[parameters.length];
+ final PsiType[] types = PsiType.createArray(parameters.length);
for (int i = 0; i < parameters.length; i++) {
if (parameters[i].getTypeElementGroovy() == null) {
paramInds.add(i);
@@ -122,7 +125,7 @@
}
}
- if (paramInds.size() > 0) {
+ if (!paramInds.isEmpty()) {
final GrClosureSignature signature = GrClosureSignatureUtil.createSignature(method, PsiSubstitutor.EMPTY);
MethodReferencesSearch.search(method, true).forEach(new Processor<PsiReference>() {
@Override
@@ -161,4 +164,18 @@
inferredTypes.put(method, types);
return types;
}
+
+ @NotNull
+ public PsiType getReturnType(GrClosableBlock closure) {
+ final PsiType returnType = closure.getReturnType();
+ if (PsiType.NULL.equals(returnType) && PsiUtil.isBlockReturnVoid(closure)) {
+ return PsiType.VOID;
+ }
+
+ if (returnType == null) {
+ return TypesUtil.getJavaLangObject(closure);
+ }
+
+ return returnType;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeWriter.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeWriter.java
index 4f0aade..4080f2f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeWriter.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/convertToJava/TypeWriter.java
@@ -53,13 +53,13 @@
@Nullable PsiType type,
@NotNull final PsiElement context,
@NotNull final ClassNameProvider classNameProvider) {
- if (type instanceof PsiPrimitiveType) {
- builder.append(type.getCanonicalText());
+ if (type == null || PsiType.NULL.equals(type)) {
+ builder.append(CommonClassNames.JAVA_LANG_OBJECT);
return;
}
- if (type == null) {
- builder.append(CommonClassNames.JAVA_LANG_OBJECT);
+ if (type instanceof PsiPrimitiveType) {
+ builder.append(type.getCanonicalText());
return;
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java
index fde920e..85c4008 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelper.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,6 +21,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
@@ -52,6 +53,9 @@
@Nullable
StringPartInfo getStringPartInfo();
+ @Nullable
+ GrVariable getVar();
+
boolean hasReturnValue();
String getName();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java
index 24a8cd8..67f5487 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractInfoHelperBase.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,6 +21,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
@@ -113,6 +114,12 @@
return myInitialInfo.getStringPartInfo();
}
+ @Nullable
+ @Override
+ public GrVariable getVar() {
+ return myInitialInfo.getVar();
+ }
+
public boolean hasReturnValue() {
return myInitialInfo.hasReturnValue();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java
index 07ec5c4..190d5ba 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ExtractUtil.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,6 @@
import org.jetbrains.plugins.groovy.refactoring.GroovyNamesUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import org.jetbrains.plugins.groovy.refactoring.extract.method.ExtractMethodInfoHelper;
-import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import java.util.*;
@@ -89,7 +88,7 @@
else {
GrExpression oldExpr;
if (helper.getStringPartInfo() != null) {
- oldExpr = GrIntroduceHandlerBase.processLiteral(helper.getName(), helper.getStringPartInfo(), helper.getProject());
+ oldExpr = helper.getStringPartInfo().replaceLiteralWithConcatenation("xyz");
}
else {
oldExpr = (GrExpression)helper.getStatements()[0];
@@ -405,13 +404,13 @@
}
else {
GrExpression expr = stringPartInfo != null
- ? GrIntroduceHandlerBase.generateExpressionFromStringPart(stringPartInfo, helper.getProject())
+ ? stringPartInfo.createLiteralFromSelected()
: (GrExpression)PsiUtil.skipParentheses(helper.getStatements()[0], false);
- boolean addReturn = !isVoid && forceReturn;
+ boolean addReturn = !isVoid && forceReturn && !PsiUtil.isVoidMethodCall(expr);
if (addReturn) {
buffer.append("return ");
- expr = ApplicationStatementUtil.convertToMethodCallExpression(expr);
- buffer.append(expr.getText());
+ final GrExpression methodCall = ApplicationStatementUtil.convertToMethodCallExpression(expr);
+ buffer.append(methodCall.getText());
}
else {
buffer.append(expr != null ? expr.getText() : "");
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java
index 6e61c36..9132991 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/GroovyExtractChooser.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,18 +19,22 @@
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.HashSet;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+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.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression;
@@ -78,18 +82,37 @@
SelectionModel selectionModel = editor.getSelectionModel();
PsiDocumentManager.getInstance(project).commitAllDocuments();
- final StringPartInfo stringPart =
- StringPartInfo.findStringPart(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
-
+ final StringPartInfo stringPart = StringPartInfo.findStringPart(file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
if (stringPart != null) {
- return new InitialInfo(new VariableInfo[0], new VariableInfo[0], PsiElement.EMPTY_ARRAY, GrStatement.EMPTY_ARRAY, new ArrayList<GrStatement>(), stringPart, project);
+ return new InitialInfo(new VariableInfo[0], new VariableInfo[0], PsiElement.EMPTY_ARRAY, GrStatement.EMPTY_ARRAY, new ArrayList<GrStatement>(), stringPart, project, null);
}
+ if (!forceStatements) {
+ GrVariable variable = GrIntroduceHandlerBase.findVariable(file, start, end);
+ if (variable != null) {
+ GrExpression initializer = variable.getInitializerGroovy();
+ if (initializer != null) {
+ TextRange range = initializer.getTextRange();
+ return buildInfo(project, file, range.getStartOffset(), range.getEndOffset(), forceStatements, selectionModel, variable);
+ }
+ }
+ }
+ return buildInfo(project, file, start, end, forceStatements, selectionModel, null);
+ }
+
+ @NotNull
+ private static InitialInfo buildInfo(@NotNull Project project,
+ @NotNull PsiFile file,
+ int start,
+ int end,
+ boolean forceStatements,
+ @NotNull SelectionModel selectionModel,
+ @Nullable GrVariable variable) throws GrRefactoringError {
PsiElement[] elements = getElementsInOffset(file, start, end, forceStatements);
- if (elements.length == 1 && elements[0] instanceof GrExpression) {
- selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset());
- }
+ //if (elements.length == 1 && elements[0] instanceof GrExpression) {
+ // selectionModel.setSelection(start, elements[0].getTextRange().getEndOffset());
+ //}
GrStatement[] statements = getStatementsByElements(elements);
@@ -171,7 +194,7 @@
GroovyRefactoringBundle.message("refactoring.is.not.supported.when.return.statement.interrupts.the.execution.flow"));
}
- return new InitialInfo(inputInfos, outputInfos, elements, statements, returnStatements, null, project);
+ return new InitialInfo(inputInfos, outputInfos, elements, statements, returnStatements, null, project, variable);
}
private static boolean isLastStatementOfMethodOrClosure(GrStatement[] statements) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java
index e50e6d5..896f1e2 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/InitialInfo.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,6 +25,7 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.branch.GrReturnStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.reachingDefs.VariableInfo;
@@ -47,6 +48,7 @@
private final boolean myHasReturnValue;
private final String[] myArgumentNames;
private final StringPartInfo myStringPartInfo;
+ private final GrVariable myVariable;
public InitialInfo(VariableInfo[] inputInfos,
VariableInfo[] outputInfos,
@@ -54,11 +56,12 @@
GrStatement[] statements,
ArrayList<GrStatement> returnStatements,
StringPartInfo stringPartInfo,
- Project project) {
+ Project project, GrVariable variable) {
myInnerElements = innerElements;
myStatements = statements;
myOutputNames = outputInfos;
myStringPartInfo = stringPartInfo;
+ myVariable = variable;
myHasReturnValue = ContainerUtil.find(returnStatements, new Condition<GrStatement>() {
@Override
@@ -194,4 +197,10 @@
public StringPartInfo getStringPartInfo() {
return myStringPartInfo;
}
+
+ @Nullable
+ @Override
+ public GrVariable getVar() {
+ return myVariable;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java
index cccdaa3..3125f08 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/ParameterTablePanel.java
@@ -16,17 +16,13 @@
package org.jetbrains.plugins.groovy.refactoring.extract;
-import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiPrimitiveType;
import com.intellij.psi.PsiType;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.refactoring.ui.TypeSelector;
-import com.intellij.ui.BooleanTableCellRenderer;
-import com.intellij.ui.IdeBorderFactory;
-import com.intellij.ui.TableUtil;
-import com.intellij.ui.ToolbarDecorator;
+import com.intellij.ui.*;
import com.intellij.ui.table.JBTable;
import com.intellij.util.ui.AbstractTableCellEditor;
import com.intellij.util.ui.EditableModel;
@@ -38,6 +34,7 @@
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableColumn;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
@@ -71,9 +68,13 @@
myTable.setTableHeader(null);
myTable.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
- myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN).setCellRenderer(new CheckBoxTableCellRenderer());
- myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN).setMaxWidth(new JCheckBox().getPreferredSize().width);
+
+ TableColumn checkBoxColumn = myTable.getColumnModel().getColumn(MyTableModel.CHECKMARK_COLUMN);
+ TableUtil.setupCheckboxColumn(checkBoxColumn);
+ checkBoxColumn.setCellRenderer(new CheckBoxTableCellRenderer());
+
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_NAME_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
+ @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
ParameterInfo info = myParameterInfos[row];
@@ -111,10 +112,12 @@
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN).setCellEditor(new AbstractTableCellEditor() {
TypeSelector myCurrentSelector;
+ @Override
public Object getCellEditorValue() {
return myCurrentSelector.getSelectedType();
}
+ @Override
public Component getTableCellEditorComponent(final JTable table,
final Object value,
final boolean isSelected,
@@ -126,6 +129,7 @@
});
myTable.getColumnModel().getColumn(MyTableModel.PARAMETER_TYPE_COLUMN).setCellRenderer(new DefaultTableCellRenderer() {
+ @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (myParameterTypeSelectors[row].getComponent() instanceof JComboBox) {
myTypeRendererCombo.setSelectedIndex(row);
@@ -149,6 +153,7 @@
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, 0), "enable_disable");
@NonNls final ActionMap actionMap = myTable.getActionMap();
actionMap.put("enable_disable", new AbstractAction() {
+ @Override
public void actionPerformed(ActionEvent e) {
if (myTable.isEditing()) return;
int[] rows = myTable.getSelectedRows();
@@ -171,6 +176,7 @@
// F2 should edit the name
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0), "edit_parameter_name");
actionMap.put("edit_parameter_name", new AbstractAction() {
+ @Override
public void actionPerformed(ActionEvent e) {
if (!myTable.isEditing()) {
int row = myTable.getSelectedRow();
@@ -184,6 +190,7 @@
// make ENTER work when the table has focus
inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "invokeImpl");
actionMap.put("invokeImpl", new AbstractAction() {
+ @Override
public void actionPerformed(ActionEvent e) {
TableCellEditor editor = myTable.getCellEditor();
if (editor != null) {
@@ -197,6 +204,7 @@
// make ESCAPE work when the table has focus
actionMap.put("doCancel", new AbstractAction() {
+ @Override
public void actionPerformed(ActionEvent e) {
TableCellEditor editor = myTable.getCellEditor();
if (editor != null) {
@@ -256,14 +264,17 @@
return true;
}
+ @Override
public int getRowCount() {
return myParameterInfos.length;
}
+ @Override
public int getColumnCount() {
return 3;
}
+ @Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case CHECKMARK_COLUMN: {
@@ -281,6 +292,7 @@
return null;
}
+ @Override
public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
switch (columnIndex) {
case CHECKMARK_COLUMN: {
@@ -308,6 +320,7 @@
}
}
+ @Override
public boolean isCellEditable(int rowIndex, int columnIndex) {
switch (columnIndex) {
case CHECKMARK_COLUMN:
@@ -323,6 +336,7 @@
}
}
+ @Override
public Class getColumnClass(int columnIndex) {
if (columnIndex == CHECKMARK_COLUMN) {
return Boolean.class;
@@ -332,6 +346,7 @@
}
private class CheckBoxTableCellRenderer extends BooleanTableCellRenderer {
+ @Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component rendererComponent = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
rendererComponent.setEnabled(ParameterTablePanel.this.isEnabled());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java
index baa5dbd..7b7f9ea 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureHelperImpl.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.
@@ -21,6 +21,7 @@
import com.intellij.psi.PsiType;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock;
@@ -42,6 +43,7 @@
private final boolean myGenerateDelegate;
private final int myReplaceFieldsWithGetters;
private final boolean myForceReturn;
+ private final boolean myReplaceAllOccurrences;
private PsiType myType = null;
private boolean myForceDef;
@@ -52,9 +54,12 @@
TIntArrayList toRemove,
boolean generateDelegate,
int replaceFieldsWithGetters,
- boolean forceReturn, boolean forceDef) {
+ boolean forceReturn,
+ boolean replaceAllOccurrences,
+ boolean forceDef) {
super(info);
myForceReturn = forceReturn;
+ myReplaceAllOccurrences = replaceAllOccurrences;
myForceDef = forceDef;
myOwner = info.getToReplaceIn();
myToSearchFor = info.getToSearchFor();
@@ -99,7 +104,7 @@
@Override
public boolean replaceAllOccurrences() {
- return false;
+ return myReplaceAllOccurrences;
}
@Override
@@ -131,6 +136,7 @@
return myForceReturn;
}
+ @Nullable
@Override
public GrVariable getVar() {
return null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java
index 7359fc0..07ed028 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/extract/closure/ExtractClosureProcessorBase.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.
@@ -60,7 +60,8 @@
return EXTRACT_CLOSURE;
}
- public static GrClosableBlock generateClosure(GrIntroduceParameterSettings helper) {
+ @NotNull
+ public static GrClosableBlock generateClosure(@NotNull GrIntroduceParameterSettings helper) {
StringBuilder buffer = new StringBuilder();
buffer.append("{ ");
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java
index 2f0c6ce..3facacb 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineLocalHandler.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.
@@ -40,7 +40,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMember;
import org.jetbrains.plugins.groovy.lang.psi.controlFlow.Instruction;
-import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
+import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
@@ -129,7 +129,7 @@
initializer = ((GrVariable)element).getInitializerGroovy();
}
else if (element instanceof GrReferenceExpression) {
- initializer = PsiUtil.getInitializerFor((GrReferenceExpression)element);
+ initializer = TypeInferenceHelper.getInitializerFor((GrReferenceExpression)element);
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java
index 70b6807..4f64084 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyInlineMethodUtil.java
@@ -600,7 +600,7 @@
final boolean isFinal = ((GrVariable)resolved).hasModifierProperty(PsiModifier.FINAL);
if (!isFinal) {
final PsiReference lastRef =
- Collections.max(ReferencesSearch.search(resolved, resolved.getResolveScope()).findAll(), new Comparator<PsiReference>() {
+ Collections.max(ReferencesSearch.search(resolved).findAll(), new Comparator<PsiReference>() {
public int compare(PsiReference o1, PsiReference o2) {
return o1.getElement().getTextRange().getStartOffset() - o2.getElement().getTextRange().getStartOffset();
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java
index 5d43719..cbae27d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/inline/GroovyMethodInliner.java
@@ -28,7 +28,6 @@
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
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;
import com.intellij.refactoring.util.CommonRefactoringUtil;
@@ -373,7 +372,7 @@
InlineMethodConflictSolver.suggestNewName(name, method, call, ((GrReferenceExpression)qualifier).getReferenceName()) :
InlineMethodConflictSolver.suggestNewName(name, method, call);
if (!newName.equals(namedElement.getName())) {
- final Collection<PsiReference> refs = ReferencesSearch.search(namedElement, GlobalSearchScope.projectScope(namedElement.getProject()), false).findAll();
+ final Collection<PsiReference> refs = ReferencesSearch.search(namedElement).findAll();
for (PsiReference ref : refs) {
PsiElement element = ref.getElement();
if (element instanceof GrReferenceExpression) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java
index 9d9fe9e..92b0368 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/GrAbstractInplaceIntroducer.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.
@@ -262,7 +262,7 @@
@Override
public boolean isReplaceAllOccurrences() {
- return myReplaceChoice != OccurrencesChooser.ReplaceChoice.NO || myContext.getOccurrences().length == 1;
+ return myReplaceChoice != OccurrencesChooser.ReplaceChoice.NO;
}
protected abstract Settings getSettings();
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 5235c0a..10e93ac 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
@@ -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.
@@ -43,7 +43,9 @@
import com.intellij.refactoring.IntroduceTargetChooser;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.introduce.inplace.AbstractInplaceIntroducer;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
+import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
@@ -61,12 +63,11 @@
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseLabel;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.*;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.util.GrDeclarationHolder;
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil;
-import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil;
+import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
@@ -185,6 +186,11 @@
}
else if (context.getStringPart() != null) {
map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.<Object>singletonList(context.getStringPart()));
+ return map;
+ }
+ else if (context.getVar() != null) {
+ map.put(OccurrencesChooser.ReplaceChoice.ALL, Collections.<Object>singletonList(context.getVar()));
+ return map;
}
PsiElement[] occurrences = context.getOccurrences();
@@ -273,14 +279,7 @@
final List<GrExpression> expressions = collectExpressions(file, editor, offset, false);
if (expressions.isEmpty()) {
- final GrVariable variable = findVariableAtCaret(file, editor, offset);
- if (variable == null || variable instanceof GrField || variable instanceof GrParameter) {
- selectionModel.selectLineAtCaret();
- }
- else {
- final TextRange textRange = variable.getTextRange();
- selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset());
- }
+ updateSelectionForVariable(editor, file, selectionModel, offset);
}
else if (expressions.size() == 1) {
final TextRange textRange = expressions.get(0).getTextRange();
@@ -298,6 +297,17 @@
invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
}
+ public static void updateSelectionForVariable(Editor editor, PsiFile file, SelectionModel selectionModel, int offset) {
+ final GrVariable variable = findVariableAtCaret(file, editor, offset);
+ if (variable == null || variable instanceof GrField || variable instanceof GrParameter) {
+ selectionModel.selectLineAtCaret();
+ }
+ else {
+ final TextRange textRange = variable.getTextRange();
+ selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset());
+ }
+ }
+
@Override
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
// Does nothing
@@ -340,7 +350,10 @@
public void run() {
GrIntroduceContext context = ref.get();
- GrExpression expression = cutLiteral(context.getStringPart(), context.getProject());
+ StringPartInfo stringPart = context.getStringPart();
+ assert stringPart != null;
+
+ GrExpression expression = stringPart.replaceLiteralWithConcatenation(null);
ref.set(new GrIntroduceContextImpl(context.getProject(), context.getEditor(), expression, null, null, new PsiElement[]{expression}, context.getScope()));
}
@@ -427,19 +440,8 @@
@Nullable StringPartInfo stringPart,
@NotNull PsiElement scope) {
if (variable != null) {
- final List<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
- ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
- @Override
- public boolean process(PsiReference psiReference) {
- final PsiElement element = psiReference.getElement();
- if (element != null) {
- list.add(element);
- }
- return true;
- }
- });
- final PsiElement[] occurrences = list.toArray(new PsiElement[list.size()]);
- return new GrIntroduceContextImpl(project, editor, variable.getInitializerGroovy(), variable, stringPart, occurrences, scope);
+ final PsiElement[] occurrences = collectVariableUsages(variable, scope);
+ return new GrIntroduceContextImpl(project, editor, null, variable, stringPart, occurrences, scope);
}
else if (expression != null ) {
final PsiElement[] occurrences = findOccurrences(expression, scope);
@@ -451,6 +453,24 @@
}
}
+ public static PsiElement[] collectVariableUsages(GrVariable variable, PsiElement scope) {
+ final List<PsiElement> list = Collections.synchronizedList(new ArrayList<PsiElement>());
+ if (scope instanceof GroovyScriptClass) {
+ scope = scope.getContainingFile();
+ }
+ ReferencesSearch.search(variable, new LocalSearchScope(scope)).forEach(new Processor<PsiReference>() {
+ @Override
+ public boolean process(PsiReference psiReference) {
+ final PsiElement element = psiReference.getElement();
+ if (element != null) {
+ list.add(element);
+ }
+ return true;
+ }
+ });
+ return list.toArray(new PsiElement[list.size()]);
+ }
+
private boolean invokeImpl(final Project project, final GrIntroduceContext context, final Editor editor) {
try {
if (!CommonRefactoringUtil.checkReadOnlyStatus(project, context.getOccurrences())) {
@@ -460,21 +480,8 @@
if (isInplace(context.getEditor(), context.getPlace())) {
- Map<OccurrencesChooser.ReplaceChoice, List<Object>> occurrencesMap = fillChoice(context);
- new OccurrencesChooser<Object>(editor) {
- @Override
- protected TextRange getOccurrenceRange(Object occurrence) {
- if (occurrence instanceof PsiElement) {
- return ((PsiElement)occurrence).getTextRange();
- }
- else if (occurrence instanceof StringPartInfo) {
- return ((StringPartInfo)occurrence).getRange();
- }
- else {
- return null;
- }
- }
- }.showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
+ Map<OccurrencesChooser.ReplaceChoice, List<Object>> occurrencesMap = getOccurrenceOptions(context);
+ new IntroduceOccurrencesChooser(editor).showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
@Override
public void pass(final OccurrencesChooser.ReplaceChoice choice) {
getIntroducer(context, choice).startInplaceIntroduceTemplate();
@@ -507,6 +514,11 @@
}
@NotNull
+ protected Map<OccurrencesChooser.ReplaceChoice, List<Object>> getOccurrenceOptions(@NotNull GrIntroduceContext context) {
+ return fillChoice(context);
+ }
+
+ @NotNull
protected PsiElement[] findOccurrences(@NotNull GrExpression expression, @NotNull PsiElement scope) {
final PsiElement[] occurrences = GroovyRefactoringUtil.getExpressionOccurrences(skipParentheses(expression, false), scope);
if (occurrences == null || occurrences.length == 0) {
@@ -574,6 +586,8 @@
public static boolean isInplace(@NotNull Editor editor, @NotNull PsiElement place) {
final RefactoringSupportProvider supportProvider = LanguageRefactoringSupport.INSTANCE.forLanguage(place.getLanguage());
return supportProvider != null &&
+ (editor.getUserData(InplaceRefactoring.INTRODUCE_RESTART) == null || !editor.getUserData(InplaceRefactoring.INTRODUCE_RESTART)) &&
+ editor.getUserData(AbstractInplaceIntroducer.ACTIVE_INTRODUCE) == null &&
editor.getSettings().isVariableInplaceRenameEnabled() &&
supportProvider.isInplaceIntroduceAvailable(place, place) &&
!ApplicationManager.getApplication().isUnitTestMode();
@@ -743,19 +757,29 @@
}
}
- @NotNull
+ @Nullable
public static GrVariable resolveLocalVar(@NotNull GrIntroduceContext context) {
final GrVariable var = context.getVar();
if (var != null) {
return var;
}
- final GrReferenceExpression expression = (GrReferenceExpression)context.getExpression();
- assert expression != null;
+ return resolveLocalVar(context.getExpression());
+ }
- final PsiElement resolved = expression.resolve();
- assert resolved instanceof GrVariable;
- return (GrVariable)resolved;
+ @Nullable
+ public static GrVariable resolveLocalVar(@Nullable GrExpression expression) {
+ if (expression instanceof GrReferenceExpression) {
+ final GrReferenceExpression ref = (GrReferenceExpression)expression;
+
+ final PsiElement resolved = ref.resolve();
+ if (GroovyRefactoringUtil.isLocalVariable(resolved)) {
+ return (GrVariable)resolved;
+ }
+ return null;
+ }
+
+ return null;
}
public static boolean hasLhs(@NotNull final PsiElement[] occurrences) {
@@ -779,141 +803,7 @@
throw new IncorrectOperationException();
}
- @NotNull
- public static GrExpression generateExpressionFromStringPart(final StringPartInfo stringPart, final Project project) {
- Data data = new Data(stringPart);
- String startQuote = data.getStartQuote();
- TextRange range = data.getRange();
- String literalText = data.getText();
- String endQuote = data.getEndQuote();
-
- final String substringLiteral = startQuote + range.substring(literalText) + endQuote;
- return GroovyPsiElementFactory.getInstance(project).createExpressionFromText(substringLiteral);
- }
-
- @NotNull
- public static GrExpression processLiteral(final String varName, final StringPartInfo stringPart, final Project project) {
- Data data = new Data(stringPart);
- String startQuote = data.getStartQuote();
- TextRange range = data.getRange();
- String literalText = data.getText();
- String endQuote = data.getEndQuote();
-
- String prefix = literalText.substring(0, range.getStartOffset()) ;
- String suffix = literalText.substring(range.getEndOffset());
-
- StringBuilder buffer = new StringBuilder();
- if (!prefix.equals(startQuote)) {
- buffer.append(prefix).append(endQuote).append('+');
- }
- buffer.append(varName);
- if (!suffix.equals(endQuote)) {
- buffer.append('+').append(startQuote).append(suffix);
- }
-
- final GrExpression concatenation = GroovyPsiElementFactory.getInstance(project).createExpressionFromText(buffer);
-
- final GrExpression concat = stringPart.getLiteral().replaceWithExpression(concatenation, false);
- if (concat instanceof GrReferenceExpression) {
- return concat;
- }
- else {
- assert concat instanceof GrBinaryExpression;
- final GrExpression left = ((GrBinaryExpression)concat).getLeftOperand();
- if (left instanceof GrReferenceExpression) {
- return left;
- }
- else {
- assert left instanceof GrBinaryExpression;
- final GrExpression right = ((GrBinaryExpression)left).getRightOperand();
- assert right != null;
- return right;
- }
- }
- }
-
- @NotNull
- public static GrExpression cutLiteral(final StringPartInfo stringPart, final Project project) {
- Data data = new Data(stringPart);
- String startQuote = data.getStartQuote();
- TextRange range = data.getRange();
- String literalText = data.getText();
- String endQuote = data.getEndQuote();
-
- String prefix = literalText.substring(0, range.getStartOffset()) ;
- String suffix = literalText.substring(range.getEndOffset());
- String selected = literalText.substring(range.getStartOffset(), range.getEndOffset());
-
- StringBuilder buffer = new StringBuilder();
- if (!prefix.equals(startQuote)) {
- buffer.append(prefix).append(endQuote).append('+');
- }
- buffer.append(startQuote).append(selected).append(endQuote);
-
- if (!suffix.equals(endQuote)) {
- buffer.append('+').append(startQuote).append(suffix);
- }
-
- final GrExpression concatenation = GroovyPsiElementFactory.getInstance(project).createExpressionFromText(buffer);
-
- final GrExpression concat = stringPart.getLiteral().replaceWithExpression(concatenation, false);
- if (concat instanceof GrReferenceExpression) {
- return concat;
- }
- else {
- assert concat instanceof GrBinaryExpression;
- final GrExpression left = ((GrBinaryExpression)concat).getLeftOperand();
- if (left instanceof GrReferenceExpression) {
- return left;
- }
- else {
- assert left instanceof GrBinaryExpression;
- final GrExpression right = ((GrBinaryExpression)left).getRightOperand();
- assert right != null;
- return right;
- }
- }
- }
-
-
public interface Validator extends NameValidator {
boolean isOK(GrIntroduceDialog dialog);
}
-
- private static class Data {
- private String myText;
- private String myStartQuote;
- private String myEndQuote;
- private TextRange myRange;
-
- public Data(final StringPartInfo stringPartInfo) {
- assert stringPartInfo != null;
-
- final GrLiteral literal = stringPartInfo.getLiteral();
-
- myText = literal.getText();
-
- myStartQuote = GrStringUtil.getStartQuote(myText);
- myEndQuote = GrStringUtil.getEndQuote(myText);
- final TextRange dataRange = new TextRange(myStartQuote.length(), myText.length() - myEndQuote.length());
-
- myRange = stringPartInfo.getRange().intersection(dataRange);
- }
-
- public String getText() {
- return myText;
- }
-
- public String getStartQuote() {
- return myStartQuote;
- }
-
- public String getEndQuote() {
- return myEndQuote;
- }
-
- public TextRange getRange() {
- return myRange;
- }
- }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceOccurrencesChooser.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceOccurrencesChooser.java
new file mode 100644
index 0000000..78cb717
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceOccurrencesChooser.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.introduce;
+
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
+
+/**
+* Created by Max Medvedev on 29/01/14
+*/
+public class IntroduceOccurrencesChooser extends OccurrencesChooser<Object> {
+ public IntroduceOccurrencesChooser(Editor editor) {
+ super(editor);
+ }
+
+ @Override
+ protected TextRange getOccurrenceRange(Object occurrence) {
+ if (occurrence instanceof PsiElement) {
+ return ((PsiElement)occurrence).getTextRange();
+ }
+ else if (occurrence instanceof StringPartInfo) {
+ return ((StringPartInfo)occurrence).getRange();
+ }
+ else {
+ return null;
+ }
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java
index de72a79..d37f5ba 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/StringPartInfo.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,10 +20,15 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
+import com.intellij.util.ArrayUtil;
+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.TokenSets;
+import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrBinaryExpression;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrString;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrStringInjection;
@@ -32,6 +37,8 @@
import java.util.Collections;
import java.util.List;
+import static org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil.*;
+
/**
* @author Max Medvedev
*/
@@ -40,30 +47,29 @@
private final TextRange myRange;
private final List<GrStringInjection> myInjections;
+ private final String myText;
+ private final String myStartQuote;
+ private final String myEndQuote;
+
@Nullable
public static StringPartInfo findStringPart(@NotNull PsiFile file, int startOffset, int endOffset) {
final PsiElement start = file.findElementAt(startOffset);
final PsiElement fin = file.findElementAt(endOffset - 1);
if (start == null || fin == null) return null;
- final PsiElement parent = PsiTreeUtil.findCommonParent(start, fin);
+ final PsiElement psi = PsiTreeUtil.findCommonParent(start, fin);
+ if (psi == null) return null;
- if (parent != null && isStringLiteral(parent.getParent()) && !parent.getParent().getTextRange().equalsToRange(startOffset, endOffset)) {
- return new StringPartInfo((GrLiteral)parent.getParent(), new TextRange(startOffset, endOffset));
+ GrLiteral literal = findLiteral(psi);
+ if (literal != null && checkSelectedRange(startOffset, endOffset, literal)) {
+ return new StringPartInfo(literal, new TextRange(startOffset, endOffset));
}
- if (parent instanceof GrString && !parent.getTextRange().equalsToRange(startOffset, endOffset)) {
- return new StringPartInfo((GrLiteral)parent, new TextRange(startOffset, endOffset));
- }
+
return null;
}
- private static boolean isStringLiteral(final PsiElement psi) {
- return psi instanceof GrLiteral && TokenSets.STRING_LITERAL_SET.contains(GrLiteralImpl.getLiteralType((GrLiteral)psi));
- }
-
public StringPartInfo(@NotNull GrLiteral literal, @NotNull final TextRange range) {
myLiteral = literal;
- myRange = range.shiftRight(-literal.getTextRange().getStartOffset());
if (literal instanceof GrString) {
final GrStringInjection[] injections = ((GrString)literal).getInjections();
@@ -77,6 +83,188 @@
else {
myInjections = Collections.emptyList();
}
+
+ myText = myLiteral.getText();
+
+ myStartQuote = getStartQuote(myText);
+ myEndQuote = getEndQuote(myText);
+
+ TextRange dataRange = new TextRange(myStartQuote.length(), myText.length() - myEndQuote.length());
+ myRange = range.shiftRight(-literal.getTextRange().getStartOffset()).intersection(dataRange);
+ }
+
+ private static boolean checkSelectedRange(int startOffset, int endOffset, GrLiteral literal) {
+ if (isWholeLiteralContentSelected(literal, startOffset, endOffset)) {
+ return false;
+ }
+
+ if (literal instanceof GrString) {
+ if (areInjectionsCut((GrString)literal, startOffset, endOffset)) {
+ return false;
+ }
+ }
+
+ if (isEscapesCut(literal, startOffset, endOffset)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ private static boolean isEscapesCut(GrLiteral literal, int startOffset, int endOffset) {
+ String rawContent = removeQuotes(literal.getText());
+ int[] offsets = new int[rawContent.length() + 1];
+
+ if (isSingleQuoteString(literal) || isDoubleQuoteString(literal)) {
+ parseStringCharacters(rawContent, new StringBuilder(), offsets);
+ }
+ else if (isSlashyString(literal)) {
+ parseRegexCharacters(rawContent, new StringBuilder(), offsets, true);
+ }
+ else if (isDollarSlashyString(literal)) {
+ parseRegexCharacters(rawContent, new StringBuilder(), offsets, false);
+ }
+
+ int contentStart = literal.getTextRange().getStartOffset() + getStartQuote(literal.getText()).length();
+
+ int relativeStart = startOffset - contentStart;
+ int relativeEnd = endOffset - contentStart;
+
+ return ArrayUtil.find(offsets, relativeStart) < 0 ||
+ ArrayUtil.find(offsets, relativeEnd) < 0;
+ }
+
+ public static boolean isWholeLiteralContentSelected(GrLiteral literal, int startOffset, int endOffset) {
+ TextRange literalRange = literal.getTextRange();
+ String literalText = literal.getText();
+ String startQuote = getStartQuote(literalText);
+ String endQuote = getEndQuote(literalText);
+
+ return literalRange.getStartOffset() <= startOffset && startOffset <= literalRange.getStartOffset() + startQuote.length() &&
+ literalRange.getEndOffset() - endQuote.length() <= endOffset && endOffset <= literalRange.getEndOffset();
+ }
+
+ private static boolean areInjectionsCut(GrString literal, int startOffset, int endOffset) {
+ TextRange selectionRange = new TextRange(startOffset, endOffset);
+
+ GrStringInjection[] injections = literal.getInjections();
+ for (GrStringInjection injection : injections) {
+ TextRange range = injection.getTextRange();
+ if (!selectionRange.contains(range) && !range.contains(selectionRange) && range.intersects(selectionRange)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Nullable
+ private static GrLiteral findLiteral(@NotNull PsiElement psi) {
+ if (isStringLiteral(psi.getParent())) {
+ return (GrLiteral)psi.getParent();
+ }
+
+ if (isStringLiteral(psi.getParent().getParent())) {
+ return (GrLiteral)psi.getParent().getParent();
+ }
+
+ if (psi instanceof GrString) {
+ return (GrLiteral)psi;
+ }
+
+ return null;
+ }
+
+ private static boolean isStringLiteral(final PsiElement psi) {
+ return psi instanceof GrLiteral && TokenSets.STRING_LITERAL_SET.contains(GrLiteralImpl.getLiteralType((GrLiteral)psi)) || psi instanceof GrString;
+ }
+
+ @NotNull
+ public GrExpression replaceLiteralWithConcatenation(@Nullable String varName) {
+
+ String prefix = preparePrefix();
+ String suffix = prepareSuffix();
+
+ StringBuilder buffer = new StringBuilder();
+ boolean prefixExists = !removeQuotes(prefix).isEmpty();
+ if (prefixExists) {
+ buffer.append(prefix).append('+');
+ }
+
+ buffer.append(varName != null ? varName : prepareSelected());
+
+ boolean suffixExists = !removeQuotes(suffix).isEmpty();
+ if (suffixExists) {
+ buffer.append('+').append(suffix);
+ }
+
+ final GrExpression concatenation = GroovyPsiElementFactory.getInstance(myLiteral.getProject()).createExpressionFromText(buffer);
+
+ final GrExpression replaced = getLiteral().replaceWithExpression(concatenation, false);
+
+ try {
+ if (prefixExists && suffixExists) {
+ return ((GrBinaryExpression)((GrBinaryExpression)replaced).getLeftOperand()).getRightOperand();
+ }
+ if (!prefixExists && suffixExists) {
+ return ((GrBinaryExpression)replaced).getLeftOperand();
+ }
+ if (prefixExists && !suffixExists) {
+ return ((GrBinaryExpression)replaced).getRightOperand();
+ }
+ if (!prefixExists && !suffixExists) {
+ return replaced;
+ }
+ }
+ catch (ClassCastException c) {
+ throw new IncorrectOperationException(buffer.toString());
+ }
+
+ throw new IncorrectOperationException(buffer.toString());
+ }
+
+ private String prepareSelected() {
+ String content = myRange.substring(myLiteral.getText());
+ return prepareLiteral(content);
+ }
+
+ private String prepareSuffix() {
+ return myStartQuote + myText.substring(myRange.getEndOffset());
+ }
+
+ private String preparePrefix() {
+ String prefix = myText.substring(0, myRange.getStartOffset());
+ String content = removeQuotes(prefix);
+
+ return prepareLiteral(content);
+ }
+
+ private String prepareLiteral(String content) {
+
+ if (isSlashyString(myLiteral)) {
+ if (content.endsWith("\\")) {
+ String unescaped = unescapeSlashyString(content);
+ return prepareGString(unescaped);
+ }
+ }
+ else if (isDollarSlashyString(myLiteral)) {
+ if (content.endsWith("$")) {
+ String unescaped = unescapeDollarSlashyString(content);
+ return prepareGString(unescaped);
+ }
+ }
+
+ return myStartQuote + content + myEndQuote;
+ }
+
+ @NotNull
+ private static String prepareGString(@NotNull String content) {
+ StringBuilder buffer = new StringBuilder();
+ boolean multiline = content.contains("\n");
+ buffer.append(multiline ? TRIPLE_DOUBLE_QUOTES : DOUBLE_QUOTES);
+ escapeSymbolsForGString(content, multiline, false, buffer);
+ buffer.append(multiline ? TRIPLE_DOUBLE_QUOTES : DOUBLE_QUOTES);
+
+ return buffer.toString();
}
@NotNull
@@ -93,4 +281,9 @@
public List<GrStringInjection> getInjections() {
return myInjections;
}
+
+ @NotNull
+ public GrLiteral createLiteralFromSelected() {
+ return (GrLiteral)GroovyPsiElementFactory.getInstance(myLiteral.getProject()).createExpressionFromText(prepareSelected());
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java
index a23723a..7f7ef7e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrInplaceConstantIntroducer.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,8 @@
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.introduceField.IntroduceConstantHandler;
import com.intellij.ui.components.JBCheckBox;
+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.lang.psi.GroovyFileBase;
@@ -28,10 +30,12 @@
import org.jetbrains.plugins.groovy.refactoring.GroovyNameSuggestionUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GroovyInplaceFieldValidator;
import javax.swing.*;
+import java.util.ArrayList;
/**
* Created by Max Medvedev on 8/29/13
@@ -48,13 +52,26 @@
myPanel = new GrInplaceIntroduceConstantPanel();
- mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(context),
- true);
+ GrVariable localVar = GrIntroduceHandlerBase.resolveLocalVar(context);
+ if (localVar != null) {
+ ArrayList<String> result = ContainerUtil.newArrayList(localVar.getName());
+
+ GrExpression initializer = localVar.getInitializerGroovy();
+ if (initializer != null) {
+ ContainerUtil.addAll(result, GroovyNameSuggestionUtil.suggestVariableNames(initializer, new GroovyInplaceFieldValidator(context), true));
+ }
+ mySuggestedNames = ArrayUtil.toStringArray(result);
+ }
+ else {
+ GrExpression expression = context.getExpression();
+ assert expression != null;
+ mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(expression, new GroovyInplaceFieldValidator(context), true);
+ }
}
@Override
protected String getActionName() {
- return null;
+ return GrIntroduceConstantHandler.REFACTORING_NAME;
}
@Override
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java
index 9e525bf..954c966 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantDialog.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,6 +58,7 @@
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceDialog;
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import org.jetbrains.plugins.groovy.refactoring.introduce.field.GrFieldNameSuggester;
import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyVariableValidator;
@@ -135,7 +136,7 @@
initializeName();
initializeTargetClassEditor();
- if (myContext.getVar() != null) {
+ if (GrIntroduceHandlerBase.resolveLocalVar(myContext) != null) {
myReplaceAllOccurrences.setEnabled(false);
myReplaceAllOccurrences.setSelected(true);
}
@@ -368,7 +369,7 @@
if (newClass == null &&
Messages.showOkCancelDialog(myContext.getProject(), GroovyRefactoringBundle.message("class.does.not.exist.in.the.module"),
- IntroduceConstantHandler.REFACTORING_NAME, Messages.getErrorIcon()) != OK_EXIT_CODE) {
+ IntroduceConstantHandler.REFACTORING_NAME, Messages.getErrorIcon()) != Messages.OK) {
return;
}
myTargetClassInfo = new TargetClassInfo(targetClassName, myContext.getPlace().getContainingFile().getContainingDirectory(), module, myContext.getProject());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java
index 95db618..f7320b9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantHandler.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,6 +21,7 @@
import com.intellij.refactoring.HelpID;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyRecursiveElementVisitor;
@@ -33,6 +34,8 @@
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.introduce.*;
+import java.util.*;
+
/**
* @author Maxim.Medvedev
*/
@@ -53,7 +56,13 @@
@Override
protected void checkExpression(@NotNull GrExpression selectedExpr) {
- selectedExpr.accept(new ConstantChecker(selectedExpr, selectedExpr));
+ GrVariable variable = GrIntroduceHandlerBase.resolveLocalVar(selectedExpr);
+ if (variable != null) {
+ checkVariable(variable);
+ }
+ else {
+ selectedExpr.accept(new ConstantChecker(selectedExpr, selectedExpr));
+ }
}
@Override
@@ -104,6 +113,31 @@
return new GrInplaceConstantIntroducer(contextRef.get(), choice);
}
+ @NotNull
+ @Override
+ protected Map<OccurrencesChooser.ReplaceChoice, List<Object>> getOccurrenceOptions(@NotNull GrIntroduceContext context) {
+ HashMap<OccurrencesChooser.ReplaceChoice, List<Object>> map = ContainerUtil.newLinkedHashMap();
+
+ GrVariable localVar = resolveLocalVar(context);
+ if (localVar != null) {
+ map.put(OccurrencesChooser.ReplaceChoice.ALL, Arrays.<Object>asList(context.getOccurrences()));
+ return map;
+ }
+
+ if (context.getExpression() != null) {
+ map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.<Object>singletonList(context.getExpression()));
+ }
+ else if (context.getStringPart() != null) {
+ map.put(OccurrencesChooser.ReplaceChoice.NO, Collections.<Object>singletonList(context.getStringPart()));
+ }
+
+ PsiElement[] occurrences = context.getOccurrences();
+ if (occurrences.length > 1) {
+ map.put(OccurrencesChooser.ReplaceChoice.ALL, Arrays.<Object>asList(occurrences));
+ }
+ return map;
+ }
+
private static class ConstantChecker extends GroovyRecursiveElementVisitor {
private final PsiElement scope;
private final GrExpression expr;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java
index 24e33f6..64c3e28 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/constant/GrIntroduceConstantProcessor.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,6 +30,7 @@
import org.jetbrains.plugins.groovy.codeStyle.GrReferenceAdjuster;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
@@ -45,7 +46,6 @@
import java.util.ArrayList;
import static org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase.deleteLocalVar;
-import static org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase.processLiteral;
/**
* @author Max Medvedev
@@ -72,22 +72,26 @@
final GrVariableDeclaration declaration = addDeclaration(targetClass);
final GrField field = (GrField)declaration.getVariables()[0];
- if (context.getVar() != null) {
- deleteLocalVar(context.getVar());
- }
+ GrVariable localVar = GrIntroduceHandlerBase.resolveLocalVar(context);
+ if (localVar != null) {
+ assert localVar.getInitializerGroovy() != null : "initializer should exist: " + localVar.getText();
+ deleteLocalVar(localVar);
- if (context.getStringPart() != null) {
- final GrExpression ref = processLiteral(field.getName(), context.getStringPart(), context.getProject());
+ if (settings.replaceAllOccurrences()) {
+ processOccurrences(field);
+ }
+ else {
+ replaceOccurrence(field, localVar.getInitializerGroovy(), isEscalateVisibility());
+ }
+ }
+ else if (context.getStringPart() != null) {
+ final GrExpression ref = context.getStringPart().replaceLiteralWithConcatenation(field.getName());
final PsiElement element = replaceOccurrence(field, ref, isEscalateVisibility());
updateCaretPosition(element);
}
- else {
+ else if (context.getExpression() != null) {
if (settings.replaceAllOccurrences()) {
- final PsiElement[] occurrences = context.getOccurrences();
- GroovyRefactoringUtil.sortOccurrences(occurrences);
- for (PsiElement occurrence : occurrences) {
- replaceOccurrence(field, occurrence, isEscalateVisibility());
- }
+ processOccurrences(field);
}
else {
replaceOccurrence(field, context.getExpression(), isEscalateVisibility());
@@ -96,6 +100,14 @@
return field;
}
+ private void processOccurrences(GrField field) {
+ final PsiElement[] occurrences = context.getOccurrences();
+ GroovyRefactoringUtil.sortOccurrences(occurrences);
+ for (PsiElement occurrence : occurrences) {
+ replaceOccurrence(field, occurrence, isEscalateVisibility());
+ }
+ }
+
private void updateCaretPosition(PsiElement element) {
context.getEditor().getCaretModel().moveToOffset(element.getTextRange().getEndOffset());
context.getEditor().getSelectionModel().removeSelection();
@@ -132,7 +144,7 @@
String message = RefactoringBundle.message("field.exists", fieldName, oldField.getContainingClass().getQualifiedName());
int answer = Messages
.showYesNoDialog(context.getProject(), message, GrIntroduceConstantHandler.REFACTORING_NAME, Messages.getWarningIcon());
- if (answer != 0) {
+ if (answer != Messages.YES) {
return true;
}
}
@@ -185,7 +197,9 @@
private static GrReferenceExpression createRefExpression(@NotNull GrField field, @NotNull PsiElement place) {
final PsiClass containingClass = field.getContainingClass();
assert containingClass != null;
- final String refText = containingClass.getQualifiedName() != null ? containingClass.getQualifiedName() + "." + field.getName() : field.getName();
+ final String qname = containingClass.getQualifiedName();
+ final String fieldName = field.getName();
+ final String refText = qname != null && !qname.equals(fieldName) ? qname + "." + fieldName : fieldName;
return GroovyPsiElementFactory.getInstance(place.getProject()).createReferenceExpressionFromText(refText, place);
}
@@ -202,12 +216,17 @@
@NotNull
protected GrExpression getInitializer() {
- final GrExpression expression = context.getExpression();
- if (expression != null) {
+ GrVariable var = GrIntroduceHandlerBase.resolveLocalVar(context);
+ GrExpression expression = context.getExpression();
+
+ if (var != null) {
+ return var.getInitializerGroovy();
+ }
+ else if (expression != null) {
return expression;
}
else {
- return GrIntroduceHandlerBase.generateExpressionFromStringPart(context.getStringPart(), context.getProject());
+ return context.getStringPart().createLiteralFromSelected();
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java
index 43c41f4..ebc1228 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrInplaceFieldIntroducer.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.
@@ -24,8 +24,11 @@
import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.introduceField.IntroduceFieldHandler;
import com.intellij.ui.NonFocusableCheckBox;
+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.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
@@ -38,6 +41,7 @@
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.util.ArrayList;
import java.util.EnumSet;
/**
@@ -49,22 +53,48 @@
private final GrFinalListener finalListener;
private String[] mySuggestedNames;
private boolean myIsStatic;
-
- @Nullable
- @Override
- protected PsiElement checkLocalScope() {
- return ((PsiField)getVariable()).getContainingClass();
- }
+ private final GrVariable myLocalVar;
public GrInplaceFieldIntroducer(GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
super(IntroduceFieldHandler.REFACTORING_NAME, choice, context);
finalListener = new GrFinalListener(myEditor);
- mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false);
+ myLocalVar = GrIntroduceHandlerBase.resolveLocalVar(context);
+ if (myLocalVar != null) {
+ //myLocalVariable = myLocalVar;
+ ArrayList<String> result = ContainerUtil.newArrayList(myLocalVar.getName());
+
+ GrExpression initializer = myLocalVar.getInitializerGroovy();
+ if (initializer != null) {
+ ContainerUtil.addAll(result, GroovyNameSuggestionUtil.suggestVariableNames(initializer, new GroovyInplaceFieldValidator(getContext()), false));
+ }
+ mySuggestedNames = ArrayUtil.toStringArray(result);
+ }
+ else {
+ mySuggestedNames = GroovyNameSuggestionUtil.suggestVariableNames(context.getExpression(), new GroovyInplaceFieldValidator(getContext()), false);
+ }
myApplicablePlaces = getApplicableInitPlaces();
}
+ @Nullable
+ @Override
+ protected PsiElement checkLocalScope() {
+ final GrVariable variable = getVariable();
+ if (variable instanceof PsiField) {
+ return ((PsiField)getVariable()).getContainingClass();
+ }
+ else {
+ final PsiFile file = variable.getContainingFile();
+ if (file instanceof GroovyFile) {
+ return ((GroovyFile)file).getScriptClass();
+ }
+ else {
+ return null;
+ }
+ }
+ }
+
@Override
protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceFieldSettings settings, boolean processUsages) {
GrIntroduceFieldProcessor processor = new GrIntroduceFieldProcessor(context, settings);
@@ -117,7 +147,7 @@
@Override
public boolean removeLocalVar() {
- return context.getVar() != null;
+ return myLocalVar != null;
}
@Nullable
@@ -170,7 +200,7 @@
@Override
public boolean removeLocalVar() {
- return false;
+ return myLocalVar != null;
}
@Nullable
@@ -224,7 +254,13 @@
private EnumSet<GrIntroduceFieldSettings.Init> getApplicableInitPlaces() {
GrIntroduceContext context = getContext();
PsiElement[] occurrences = getOccurrences();
- EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.of(GrIntroduceFieldSettings.Init.FIELD_DECLARATION);
+ EnumSet<GrIntroduceFieldSettings.Init> result = EnumSet.noneOf(GrIntroduceFieldSettings.Init.class);
+
+ if (context.getExpression() != null ||
+ context.getVar() != null && context.getVar().getInitializerGroovy() != null ||
+ context.getStringPart() != null) {
+ result.add(GrIntroduceFieldSettings.Init.FIELD_DECLARATION);
+ }
if (!(context.getScope() instanceof GroovyScriptClass || context.getScope() instanceof GroovyFileBase)) {
result.add(GrIntroduceFieldSettings.Init.CONSTRUCTOR);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java
index 48bb596..631b25e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldDialog.java
@@ -17,6 +17,7 @@
import com.intellij.codeInsight.TestFrameworks;
import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
@@ -463,7 +464,7 @@
final String name = getName();
String message = RefactoringBundle.message("field.exists", name, clazz.getQualifiedName());
if (clazz.findFieldByName(name, true) != null &&
- showYesNoDialog(myContext.getProject(), message, REFACTORING_NAME, getWarningIcon()) != 0) {
+ showYesNoDialog(myContext.getProject(), message, REFACTORING_NAME, getWarningIcon()) != Messages.YES) {
return;
}
super.doOKAction();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java
index f100448..849cac3 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldHandler.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.
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java
index 50f07d5..bd57810 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldProcessor.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.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -52,6 +53,7 @@
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
+import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import java.util.ArrayList;
import java.util.Collections;
@@ -65,8 +67,9 @@
private final GrIntroduceContext myContext;
private final GrIntroduceFieldSettings mySettings;
- private GrExpression myInitializer;
- private GrVariable myLocalVariable;
+
+ @Nullable private GrExpression myInitializer;
+ @Nullable private GrVariable myLocalVariable;
public GrIntroduceFieldProcessor(@NotNull GrIntroduceContext context,
@NotNull GrIntroduceFieldSettings settings) {
@@ -85,6 +88,7 @@
if (mySettings.removeLocalVar()) {
myLocalVariable = GrIntroduceHandlerBase.resolveLocalVar(myContext);
+ assert myLocalVariable != null : myContext.getExpression() + ", " + myContext.getVar() + ", " + myContext.getStringPart();
}
myInitializer = (GrExpression)getInitializer().copy();
@@ -117,31 +121,40 @@
@NotNull
private List<PsiElement> processOccurrences(@NotNull PsiClass targetClass, @NotNull GrVariable field) {
if (myContext.getStringPart() != null) {
- final GrExpression expr = GrIntroduceHandlerBase.processLiteral(field.getName(), myContext.getStringPart(), myContext.getProject());
+ final GrExpression expr = myContext.getStringPart().replaceLiteralWithConcatenation(field.getName());
final PsiElement occurrence = replaceOccurrence(field, expr, targetClass);
updateCaretPosition(occurrence);
return Collections.singletonList(occurrence);
}
- else {
- if (mySettings.replaceAllOccurrences()) {
- GroovyRefactoringUtil.sortOccurrences(myContext.getOccurrences());
- ArrayList<PsiElement> result = ContainerUtil.newArrayList();
- for (PsiElement occurrence : myContext.getOccurrences()) {
- result.add(replaceOccurrence(field, occurrence, targetClass));
- }
- return result;
+
+ if (mySettings.replaceAllOccurrences()) {
+ GroovyRefactoringUtil.sortOccurrences(myContext.getOccurrences());
+ ArrayList<PsiElement> result = ContainerUtil.newArrayList();
+ for (PsiElement occurrence : myContext.getOccurrences()) {
+ result.add(replaceOccurrence(field, occurrence, targetClass));
+ }
+ return result;
+ }
+
+ GrVariable var = myContext.getVar();
+ if (var != null) {
+ GrExpression initializer = var.getInitializerGroovy();
+ if (initializer != null) {
+ return Collections.singletonList(replaceOccurrence(field, initializer, targetClass));
}
else {
- final GrExpression expression = myContext.getExpression();
- assert expression != null;
- if (PsiUtil.isExpressionStatement(expression)) {
- return Collections.<PsiElement>singletonList(expression);
- }
- else {
- return Collections.singletonList(replaceOccurrence(field, expression, targetClass));
- }
+ return Collections.emptyList();
}
}
+
+ final GrExpression expression = myContext.getExpression();
+ assert expression != null;
+ if (PsiUtil.isExpressionStatement(expression)) {
+ return Collections.<PsiElement>singletonList(expression);
+ }
+ else {
+ return Collections.singletonList(replaceOccurrence(field, expression, targetClass));
+ }
}
private void updateCaretPosition(@NotNull PsiElement occurrence) {
@@ -282,9 +295,10 @@
@Nullable GrStatement anchor,
@NotNull GrStatementOwner defaultContainer,
@Nullable PsiElement occurrenceToDelete) {
- final GrExpression initializer = myInitializer;
+ if (myInitializer == null) return;
+
GrAssignmentExpression init = (GrAssignmentExpression)GroovyPsiElementFactory.getInstance(myContext.getProject())
- .createExpressionFromText(mySettings.getName() + " = " + initializer.getText());
+ .createExpressionFromText(mySettings.getName() + " = " + myInitializer.getText());
GrStatementOwner block;
if (anchor != null) {
@@ -304,12 +318,10 @@
}
}
- @NotNull
+ @Nullable
private GrExpression extractVarInitializer() {
assert myLocalVariable != null;
- GrExpression initializer = myLocalVariable.getInitializerGroovy();
- LOG.assertTrue(initializer != null);
- return initializer;
+ return myLocalVariable.getInitializerGroovy();
}
@Nullable
@@ -386,19 +398,21 @@
}
}
- @NotNull
+ @Nullable
protected GrExpression getInitializer() {
if (mySettings.removeLocalVar()) {
return extractVarInitializer();
}
-
- final GrExpression expression = myContext.getExpression();
+ GrExpression expression = myContext.getExpression();
+ StringPartInfo stringPart = myContext.getStringPart();
if (expression != null) {
return expression;
}
+ else if (stringPart != null) {
+ return stringPart.createLiteralFromSelected();
+ }
-
- return GrIntroduceHandlerBase.generateExpressionFromStringPart(myContext.getStringPart(), myContext.getProject());
+ throw new IncorrectOperationException("cannot be here!");
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java
index 4bb4ee8..99ea5a7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrExpressionWrapper.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.
@@ -34,7 +34,7 @@
private final RangeMarker myMarker;
private final PsiFile myFile;
- public GrExpressionWrapper(GrExpression expression) {
+ public GrExpressionWrapper(@NotNull GrExpression expression) {
assert expression.isValid();
myExpression = expression;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java
index 759b788..5a841f9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrInplaceParameterIntroducer.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,132 +18,85 @@
import com.intellij.codeInsight.template.TextResult;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.EditorFactory;
-import com.intellij.openapi.editor.EditorSettings;
-import com.intellij.openapi.editor.RangeMarker;
-import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
-import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.editor.impl.DocumentMarkupModel;
import com.intellij.openapi.editor.markup.EffectType;
import com.intellij.openapi.editor.markup.HighlighterTargetArea;
import com.intellij.openapi.editor.markup.MarkupModel;
import com.intellij.openapi.editor.markup.TextAttributes;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiParameter;
-import com.intellij.psi.PsiVariable;
+import com.intellij.psi.PsiType;
import com.intellij.refactoring.IntroduceParameterRefactoring;
+import com.intellij.refactoring.introduce.inplace.OccurrencesChooser;
import com.intellij.refactoring.rename.inplace.InplaceRefactoring;
-import com.intellij.ui.DottedBorder;
import com.intellij.ui.JBColor;
import com.intellij.ui.components.JBCheckBox;
+import com.intellij.usageView.UsageInfo;
import com.intellij.util.ArrayUtil;
import gnu.trove.TIntArrayList;
-import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
-import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrAbstractInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
-import javax.swing.border.LineBorder;
import java.awt.*;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
+import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.findParametersToRemove;
+
/**
* Created by Max Medvedev on 9/1/13
*/
-public class GrInplaceParameterIntroducer extends GrInplaceIntroducer {
- private final JPanel myPanel;
- private EditorEx myPreview;
+public class GrInplaceParameterIntroducer extends GrAbstractInplaceIntroducer<GrIntroduceParameterSettings> {
+ private final IntroduceParameterInfo myInfo;
+ private final TIntArrayList myParametersToRemove;
- private JComponent myPreviewComponent;
private JBCheckBox myDelegateCB;
- private GrIntroduceParameterSettings mySettings;
- private final GrExpressionWrapper myExpr;
+ private LinkedHashSet<String> mySuggestedNames;
- public GrInplaceParameterIntroducer(@NotNull GrVariable elementToRename,
- @NotNull Editor editor,
- @NotNull Project project,
- @NotNull String title,
- @NotNull List<RangeMarker> occurrences,
- @Nullable PsiElement elementToIntroduce,
- GrIntroduceParameterSettings settings,
- GrExpressionWrapper expr) {
- super(elementToRename, editor, project, title, occurrences, elementToIntroduce);
+ public GrInplaceParameterIntroducer(IntroduceParameterInfo info, GrIntroduceContext context, OccurrencesChooser.ReplaceChoice choice) {
+ super(GrIntroduceParameterHandler.REFACTORING_NAME, choice, context);
+ myInfo = info;
- mySettings = settings;
+ GrVariable localVar = GrIntroduceHandlerBase.resolveLocalVar(context);
+ mySuggestedNames = GroovyIntroduceParameterUtil.suggestNames(localVar, context.getExpression(), context.getStringPart(), info.getToReplaceIn(), context.getProject());
- initPreview(project);
-
- myDelegateCB = new JBCheckBox("Delegate via overloading method");
- myDelegateCB.setMnemonic('l');
- myDelegateCB.setFocusable(false);
-
- myPanel = new JPanel(new BorderLayout());
- myPanel.add(myPreviewComponent, BorderLayout.CENTER);
- myPanel.add(myDelegateCB, BorderLayout.SOUTH);
-
- myExpr = expr;
-
+ myParametersToRemove = new TIntArrayList(findParametersToRemove(info).getValues());
}
- protected final void setPreviewText(final String text) {
- if (myPreview == null) return; //already disposed
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- myPreview.getDocument().replaceString(0, myPreview.getDocument().getTextLength(), text);
- }
- });
+ @Override
+ protected String getActionName() {
+ return GrIntroduceParameterHandler.REFACTORING_NAME;
}
+ @Override
+ protected String[] suggestNames(boolean replaceAll, @Nullable GrVariable variable) {
+ return ArrayUtil.toStringArray(mySuggestedNames);
+ }
- private void initPreview(Project project) {
- myPreview = (EditorEx)EditorFactory.getInstance()
- .createEditor(EditorFactory.getInstance().createDocument(""), project, GroovyFileType.GROOVY_FILE_TYPE, true);
- myPreview.setOneLineMode(true);
- final EditorSettings settings = myPreview.getSettings();
- settings.setAdditionalLinesCount(0);
- settings.setAdditionalColumnsCount(1);
- settings.setRightMarginShown(false);
- settings.setFoldingOutlineShown(false);
- settings.setLineNumbersShown(false);
- settings.setLineMarkerAreaShown(false);
- settings.setIndentGuidesShown(false);
- settings.setVirtualSpace(false);
- myPreview.setHorizontalScrollbarVisible(false);
- myPreview.setVerticalScrollbarVisible(false);
- myPreview.setCaretEnabled(false);
- settings.setLineCursorWidth(1);
+ @Override
+ protected JComponent getComponent() {
- final Color bg = myPreview.getColorsScheme().getColor(EditorColors.CARET_ROW_COLOR);
- myPreview.setBackgroundColor(bg);
- myPreview.setBorder(BorderFactory.createCompoundBorder(new DottedBorder(JBColor.GRAY), new LineBorder(bg, 2)));
-
- myPreviewComponent = new JPanel(new BorderLayout());
- myPreviewComponent.add(myPreview.getComponent(), BorderLayout.CENTER);
- myPreviewComponent.setBorder(new EmptyBorder(2, 2, 6, 2));
+ JPanel previewPanel = new JPanel(new BorderLayout());
+ previewPanel.add(getPreviewEditor().getComponent(), BorderLayout.CENTER);
+ previewPanel.setBorder(new EmptyBorder(2, 2, 6, 2));
DocumentAdapter documentAdapter = new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
- if (myPreview == null) return;
final TemplateState templateState = TemplateManagerImpl.getTemplateState(myEditor);
if (templateState != null) {
final TextResult value = templateState.getVariableValue(InplaceRefactoring.PRIMARY_VARIABLE_NAME);
@@ -155,59 +108,29 @@
};
myEditor.getDocument().addDocumentListener(documentAdapter);
- updateTitle(getVariable(), getVariable().getName());
+ myDelegateCB = new JBCheckBox("Delegate via overloading method");
+ myDelegateCB.setMnemonic('l');
+ myDelegateCB.setFocusable(false);
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(previewPanel, BorderLayout.CENTER);
+ panel.add(myDelegateCB, BorderLayout.SOUTH);
+ return panel;
}
@Override
- public LinkedHashSet<String> suggestNames(GrIntroduceContext context) {
- return GroovyIntroduceParameterUtil.suggestNames(null, myExpr.getExpression(), null, (GrParametersOwner)context.getScope(), context.getProject());
+ protected void saveSettings(@NotNull GrVariable variable) {
+
}
- static LinkedHashSet<String> suggestNames(GrIntroduceContext context, GrParametersOwner scope) {
- return GroovyIntroduceParameterUtil.suggestNames(context.getVar(), context.getExpression(), context.getStringPart(), scope, context.getProject());
- }
-
- @Override
- protected void moveOffsetAfter(boolean success) {
- if (success) {
- final GrVariable parameter = getVariable();
- GrIntroduceParameterSettings settings = generateSettings((GrParameter)parameter, mySettings, myDelegateCB.isSelected());
- assert parameter != null;
- parameter.delete();
- GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(settings, myExpr);
- processor.run();
- }
-
-
- super.moveOffsetAfter(success);
- }
-
- public GrIntroduceParameterSettings generateSettings(GrParameter parameter, IntroduceParameterInfo info, boolean delegate) {
-
- TObjectIntHashMap<GrParameter> toRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info);
- TIntArrayList removeList = new TIntArrayList(delegate ? ArrayUtil.EMPTY_INT_ARRAY: toRemove.getValues());
-
- GrExpression _expr = myExpr.getExpression();
- GrVariable _var = GroovyIntroduceParameterUtil.findVar(info);
- return new GrIntroduceExpressionSettingsImpl(info, parameter.getName(), false, removeList, myDelegateCB.isSelected(),
- IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, _expr, _var,
- parameter.getType(), false);
- }
-
- @Override
- protected JComponent getComponent() {
- updateTitle(getVariable());
- return myPanel;
- }
-
-
- protected void updateTitle(@Nullable PsiVariable variable) {
+ protected void updateTitle(@Nullable GrVariable variable) {
if (variable == null) return;
updateTitle(variable, variable.getName());
}
- protected void updateTitle(@Nullable final PsiVariable variable, final String value) {
- final PsiElement declarationScope = variable != null ? ((PsiParameter)variable).getDeclarationScope() : null;
+ protected void updateTitle(@Nullable GrVariable variable, String value) {
+ if (getPreviewEditor() == null || variable == null) return;
+ final PsiElement declarationScope = ((PsiParameter)variable).getDeclarationScope();
if (declarationScope instanceof PsiMethod) {
final PsiMethod psiMethod = (PsiMethod)declarationScope;
final StringBuilder buf = new StringBuilder();
@@ -233,15 +156,17 @@
if (variable == parameter) {
addedRange = new TextRange(startOffset, endOffset);
}
- else if (mySettings.parametersToRemove().contains(i)) {
+ else if (myParametersToRemove.contains(i)) {
ranges2Remove.add(new TextRange(startOffset, endOffset));
}
i++;
}
+ assert addedRange != null;
+
buf.append(")");
setPreviewText(buf.toString());
- final MarkupModel markupModel = DocumentMarkupModel.forDocument(myPreview.getDocument(), myProject, true);
+ final MarkupModel markupModel = DocumentMarkupModel.forDocument(getPreviewEditor().getDocument(), myProject, true);
markupModel.removeAllHighlighters();
for (TextRange textRange : ranges2Remove) {
markupModel.addRangeHighlighter(textRange.getStartOffset(), textRange.getEndOffset(), 0, getTestAttributesForRemoval(), HighlighterTargetArea.EXACT_RANGE);
@@ -261,7 +186,61 @@
private static TextAttributes getTestAttributesForRemoval() {
final TextAttributes textAttributes = new TextAttributes();
textAttributes.setEffectType(EffectType.STRIKEOUT);
- textAttributes.setEffectColor(Color.BLACK);
+ textAttributes.setEffectColor(JBColor.BLACK);
return textAttributes;
}
+
+ @Override
+ protected GrVariable runRefactoring(GrIntroduceContext context, GrIntroduceParameterSettings settings, boolean processUsages) {
+ GrExpressionWrapper wrapper = createExpressionWrapper(context);
+ if (processUsages) {
+ GrIntroduceExpressionSettingsImpl patchedSettings =
+ new GrIntroduceExpressionSettingsImpl(settings, settings.getName(), settings.declareFinal(), settings.parametersToRemove(),
+ settings.generateDelegate(), settings.replaceFieldsWithGetters(), context.getExpression(),
+ context.getVar(), settings.getSelectedType(), context.getVar() != null || settings.replaceAllOccurrences(),
+ context.getVar() != null, settings.isForceReturn());
+ GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(patchedSettings, wrapper);
+ processor.run();
+ }
+ else {
+ GrIntroduceParameterProcessor processor = new GrIntroduceParameterProcessor(settings, wrapper);
+ processor.performRefactoring(UsageInfo.EMPTY_ARRAY);
+ }
+ GrParametersOwner owner = settings.getToReplaceIn();
+ return ArrayUtil.getLastElement(owner.getParameters());
+ }
+
+ @NotNull
+ private static GrExpressionWrapper createExpressionWrapper(@NotNull GrIntroduceContext context) {
+ GrExpression expression = context.getExpression();
+ GrVariable var = context.getVar();
+ assert expression != null || var != null ;
+
+ GrExpression initializer = expression != null ? expression : var.getInitializerGroovy();
+ return new GrExpressionWrapper(initializer);
+ }
+
+ @Nullable
+ @Override
+ protected GrIntroduceParameterSettings getInitialSettingsForInplace(@NotNull GrIntroduceContext context,
+ @NotNull OccurrencesChooser.ReplaceChoice choice,
+ String[] names) {
+ GrExpression expression = context.getExpression();
+ GrVariable var = context.getVar();
+ PsiType type = var != null ? var.getDeclaredType() :
+ expression != null ? expression.getType() :
+ null;
+
+ return new GrIntroduceExpressionSettingsImpl(myInfo, names[0], false, new TIntArrayList(), false,
+ IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, expression,
+ var, type, false, false, false);
+
+ }
+
+ @Override
+ protected GrIntroduceParameterSettings getSettings() {
+ return new GrIntroduceExpressionSettingsImpl(myInfo, getInputName(), false, myParametersToRemove, myDelegateCB.isSelected(),
+ IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, null,
+ null, getSelectedType(), isReplaceAllOccurrences(), false, false);
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java
index babc957..84389a6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceClosureParameterProcessor.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 org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
import org.jetbrains.plugins.groovy.codeInspection.utils.ControlFlowUtils;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.signatures.GrClosureSignature;
@@ -71,7 +70,6 @@
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringUtil;
-import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.java2groovy.FieldConflictsResolver;
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.java2groovy.OldReferencesResolver;
@@ -94,7 +92,7 @@
private GrExpressionWrapper myParameterInitializer;
private GroovyPsiElementFactory myFactory = GroovyPsiElementFactory.getInstance(myProject);
- public GrIntroduceClosureParameterProcessor(GrIntroduceParameterSettings settings) {
+ public GrIntroduceClosureParameterProcessor(@NotNull GrIntroduceParameterSettings settings) {
super(settings.getProject(), null);
mySettings = settings;
@@ -103,7 +101,7 @@
final StringPartInfo info = settings.getStringPartInfo();
final GrExpression expression = info != null ?
- GrIntroduceHandlerBase.generateExpressionFromStringPart(info, settings.getProject()) :
+ info.createLiteralFromSelected() :
mySettings.getExpression();
myParameterInitializer = new GrExpressionWrapper(expression);
}
@@ -178,7 +176,7 @@
if (!mySettings.generateDelegate() && toSearchFor != null) {
Collection<PsiReference> refs;
if (toSearchFor instanceof GrField) {
- refs = ReferencesSearch.search(toSearchFor, toSearchFor.getResolveScope()).findAll();
+ refs = ReferencesSearch.search(toSearchFor).findAll();
final GrAccessorMethod[] getters = ((GrField)toSearchFor).getGetters();
for (GrAccessorMethod getter : getters) {
refs.addAll(MethodReferencesSearch.search(getter, getter.getResolveScope(), true).findAll());
@@ -188,7 +186,7 @@
refs = findUsagesForLocal(toReplaceIn, ((GrVariable)toSearchFor));
}
else {
- refs = ReferencesSearch.search(toSearchFor, toSearchFor.getResolveScope()).findAll();
+ refs = ReferencesSearch.search(toSearchFor).findAll();
}
for (PsiReference ref1 : refs) {
@@ -316,7 +314,7 @@
final StringPartInfo info = settings.getStringPartInfo();
if (info != null) {
- final GrExpression expr = GrIntroduceHandlerBase.processLiteral(settings.getName(), info, settings.getProject());
+ final GrExpression expr = info.replaceLiteralWithConcatenation(settings.getName());
final Editor editor = PsiUtilBase.findEditor(expr);
if (editor != null) {
editor.getSelectionModel().removeSelection();
@@ -364,7 +362,7 @@
if (block.getArrow() == null) {
final PsiElement arrow = block.addAfter(factory.createClosureFromText("{->}").getArrow().copy(), parameterList);
final PsiElement child = block.getFirstChild().getNextSibling();
- if (TokenSets.WHITE_SPACES_SET.contains(child.getNode().getElementType())) {
+ if (PsiImplUtil.isWhiteSpaceOrNls(child)) {
final String text = child.getText();
child.delete();
block.addAfter(factory.createLineTerminator(text), arrow);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java
index aafce74..3113473 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceExpressionSettingsImpl.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.
@@ -31,21 +31,27 @@
private final GrExpression myExpr;
private final GrVariable myVar;
private final PsiType mySelectedType;
+ private final boolean myRemoveLocalVar;
public GrIntroduceExpressionSettingsImpl(IntroduceParameterInfo info,
String name,
boolean declareFinal,
TIntArrayList toRemove,
boolean generateDelegate,
- @MagicConstant(intValues = {REPLACE_FIELDS_WITH_GETTERS_ALL, REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, REPLACE_FIELDS_WITH_GETTERS_NONE}) int replaceFieldsWithGetters,
+ @MagicConstant(
+ intValues = {REPLACE_FIELDS_WITH_GETTERS_ALL, REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE,
+ REPLACE_FIELDS_WITH_GETTERS_NONE}) int replaceFieldsWithGetters,
GrExpression expr,
GrVariable var,
PsiType selectedType,
+ boolean replaceAllOccurrences,
+ boolean removeLocalVar,
boolean forceReturn) {
- super(info, name, declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, forceReturn, false);
+ super(info, name, declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters, forceReturn, replaceAllOccurrences, false);
myExpr = expr;
myVar = var;
mySelectedType = selectedType;
+ myRemoveLocalVar = removeLocalVar;
}
@Override
@@ -64,4 +70,8 @@
}
+ @Override
+ public boolean removeLocalVariable() {
+ return myRemoveLocalVar;
+ }
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java
index 0ee6ba2..bd63f95 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterDialog.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.
@@ -75,6 +75,7 @@
import java.util.List;
import static com.intellij.refactoring.IntroduceParameterRefactoring.*;
+import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.*;
public class GrIntroduceParameterDialog extends DialogWrapper {
private GrTypeComboBox myTypeComboBox;
@@ -100,9 +101,11 @@
super(info.getProject(), true);
myInfo = info;
myProject = info.getProject();
- myCanIntroduceSimpleParameter = GroovyIntroduceParameterUtil.findExpr(myInfo) != null || GroovyIntroduceParameterUtil.findVar(myInfo) != null || findStringPart() != null;
+ myCanIntroduceSimpleParameter = findExpr(myInfo) != null ||
+ findVar(myInfo) != null ||
+ findStringPart() != null;
- TObjectIntHashMap<GrParameter> parametersToRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info);
+ TObjectIntHashMap<GrParameter> parametersToRemove = findParametersToRemove(info);
toRemoveCBs = new TObjectIntHashMap<JCheckBox>(parametersToRemove.size());
for (Object p : parametersToRemove.keys()) {
JCheckBox cb = new JCheckBox(GroovyRefactoringBundle.message("remove.parameter.0.no.longer.used", ((GrParameter)p).getName()));
@@ -274,7 +277,7 @@
c.nextLine().next().weightx(0).fillCellNone();
namePanel.add(typeLabel, c);
- myTypeComboBox = createTypeComboBox(GroovyIntroduceParameterUtil.findVar(myInfo), GroovyIntroduceParameterUtil.findExpr(myInfo), findStringPart());
+ myTypeComboBox = createTypeComboBox(findVar(myInfo), findExpr(myInfo), findStringPart());
c.next().weightx(1).fillCellHorizontally();
namePanel.add(myTypeComboBox, c);
typeLabel.setLabelFor(myTypeComboBox);
@@ -283,7 +286,7 @@
c.nextLine().next().weightx(0).fillCellNone();
namePanel.add(nameLabel, c);
- myNameSuggestionsField = createNameField(GroovyIntroduceParameterUtil.findVar(myInfo));
+ myNameSuggestionsField = createNameField(findVar(myInfo));
c.next().weightx(1).fillCellHorizontally();
namePanel.add(myNameSuggestionsField, c);
nameLabel.setLabelFor(myNameSuggestionsField);
@@ -335,7 +338,7 @@
@Nullable
private PsiType inferClosureReturnType() {
final ExtractClosureHelperImpl mockHelper =
- new ExtractClosureHelperImpl(myInfo, "__test___n_", false, new TIntArrayList(), false, 0, false, false);
+ new ExtractClosureHelperImpl(myInfo, "__test___n_", false, new TIntArrayList(), false, 0, false, false, false);
final PsiType returnType;
final AccessToken token = WriteAction.start();
try {
@@ -358,7 +361,7 @@
}
private void initReplaceFieldsWithGetters(JavaRefactoringSettings settings) {
- final PsiField[] usedFields = GroovyIntroduceParameterUtil.findUsedFieldsWithGetters(myInfo.getStatements(), getContainingClass());
+ final PsiField[] usedFields = findUsedFieldsWithGetters(myInfo.getStatements(), getContainingClass());
myGetterPanel.setVisible(usedFields.length > 0);
switch (settings.INTRODUCE_PARAMETER_REPLACE_FIELDS_WITH_GETTERS) {
case REPLACE_FIELDS_WITH_GETTERS_ALL:
@@ -452,8 +455,8 @@
final GrParametersOwner toReplaceIn = myInfo.getToReplaceIn();
- final GrExpression expr = GroovyIntroduceParameterUtil.findExpr(myInfo);
- final GrVariable var = GroovyIntroduceParameterUtil.findVar(myInfo);
+ final GrExpression expr = findExpr(myInfo);
+ final GrVariable var = findVar(myInfo);
final StringPartInfo stringPart = findStringPart();
if (myTypeComboBox.isClosureSelected() || expr == null && var == null && stringPart == null) {
@@ -464,6 +467,7 @@
myDelegateViaOverloadingMethodCheckBox.isSelected(),
getReplaceFieldsWithGetter(),
myForceReturnCheckBox.isSelected(),
+ false,
myTypeComboBox.getSelectedType() == null);
if (toReplaceIn instanceof GrMethod) {
invokeRefactoring(new ExtractClosureFromMethodProcessor(settings));
@@ -483,7 +487,7 @@
expr,
var,
myTypeComboBox.getSelectedType(),
- myForceReturnCheckBox.isSelected());
+ var != null, true, myForceReturnCheckBox.isSelected());
if (toReplaceIn instanceof GrMethod) {
invokeRefactoring(new GrIntroduceParameterProcessor(settings));
}
@@ -521,8 +525,8 @@
@NotNull
public LinkedHashSet<String> suggestNames() {
- GrVariable var = GroovyIntroduceParameterUtil.findVar(myInfo);
- GrExpression expr = GroovyIntroduceParameterUtil.findExpr(myInfo);
+ GrVariable var = findVar(myInfo);
+ GrExpression expr = findExpr(myInfo);
StringPartInfo stringPart = findStringPart();
return GroovyIntroduceParameterUtil.suggestNames(var, expr, stringPart, myInfo.getToReplaceIn(), myProject);
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 50667f1..9f1a984 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
@@ -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,19 +18,16 @@
import com.intellij.ide.util.SuperMethodWarningUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.JBPopup;
-import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pass;
import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.*;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiMethod;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.refactoring.IntroduceParameterRefactoring;
import com.intellij.refactoring.IntroduceTargetChooser;
import com.intellij.refactoring.RefactoringActionHandler;
import com.intellij.refactoring.RefactoringBundle;
@@ -38,38 +35,31 @@
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.Function;
import com.intellij.util.PairFunction;
-import com.intellij.util.containers.ContainerUtil;
-import gnu.trove.TIntArrayList;
-import gnu.trove.TObjectIntHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrParametersOwner;
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.GrExpression;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.params.GrParameter;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod;
import org.jetbrains.plugins.groovy.refactoring.GrRefactoringError;
import org.jetbrains.plugins.groovy.refactoring.GroovyRefactoringBundle;
import org.jetbrains.plugins.groovy.refactoring.extract.GroovyExtractChooser;
import org.jetbrains.plugins.groovy.refactoring.extract.InitialInfo;
-import org.jetbrains.plugins.groovy.refactoring.introduce.GrInplaceIntroducer;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase;
+import org.jetbrains.plugins.groovy.refactoring.introduce.IntroduceOccurrencesChooser;
import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo;
-import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.java2groovy.GroovyIntroduceParameterMethodUsagesProcessor;
import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GrIntroduceVariableHandler;
import org.jetbrains.plugins.groovy.refactoring.ui.MethodOrClosureScopeChooser;
import java.util.ArrayList;
-import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import static org.jetbrains.plugins.groovy.refactoring.HelpID.GROOVY_INTRODUCE_PARAMETER;
-import static org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase.createRange;
+import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.findExpr;
+import static org.jetbrains.plugins.groovy.refactoring.introduce.parameter.GroovyIntroduceParameterUtil.findVar;
/**
* @author Maxim.Medvedev
@@ -78,21 +68,14 @@
static final String REFACTORING_NAME = RefactoringBundle.message("introduce.parameter.title");
private JBPopup myEnclosingMethodsPopup;
- public void invoke(final @NotNull Project project, final Editor editor, final PsiFile file, final @Nullable DataContext dataContext) {
+ public void invoke(final @NotNull Project project, @NotNull final Editor editor, @NotNull final PsiFile file, final @Nullable DataContext dataContext) {
final SelectionModel selectionModel = editor.getSelectionModel();
if (!selectionModel.hasSelection()) {
final int offset = editor.getCaretModel().getOffset();
final List<GrExpression> expressions = GrIntroduceHandlerBase.collectExpressions(file, editor, offset, false);
if (expressions.isEmpty()) {
- final GrVariable variable = GrIntroduceHandlerBase.findVariableAtCaret(file, editor, offset);
- if (variable == null || variable instanceof GrField || variable instanceof GrParameter) {
- selectionModel.selectLineAtCaret();
- }
- else {
- final TextRange textRange = variable.getTextRange();
- selectionModel.setSelection(textRange.getStartOffset(), textRange.getEndOffset());
- }
+ GrIntroduceHandlerBase.updateSelectionForVariable(editor, file, selectionModel, offset);
}
else if (expressions.size() == 1) {
final TextRange textRange = expressions.get(0).getTextRange();
@@ -116,7 +99,7 @@
invoke(project, editor, file, selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
}
- private void invoke(final Project project, final Editor editor, PsiFile file, int startOffset, int endOffset) {
+ private void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file, int startOffset, int endOffset) {
try {
final InitialInfo initialInfo = GroovyExtractChooser.invoke(project, editor, file, startOffset, endOffset, false);
chooseScopeAndRun(initialInfo, editor);
@@ -157,7 +140,8 @@
}
}
- private List<GrParametersOwner> findScopes(InitialInfo initialInfo) {
+ @NotNull
+ private static List<GrParametersOwner> findScopes(@NotNull InitialInfo initialInfo) {
PsiElement place = initialInfo.getContext();
final List<GrParametersOwner> scopes = new ArrayList<GrParametersOwner>();
while (true) {
@@ -176,27 +160,14 @@
//method to hack in tests
- protected void showDialogOrStartInplace(final IntroduceParameterInfo info, final Editor editor) {
+ protected void showDialogOrStartInplace(@NotNull final IntroduceParameterInfo info, @NotNull final Editor editor) {
if (isInplace(info, editor)) {
final GrIntroduceContext context = createContext(info, editor);
Map<OccurrencesChooser.ReplaceChoice, List<Object>> occurrencesMap = GrIntroduceHandlerBase.fillChoice(context);
- new OccurrencesChooser<Object>(editor) {
- @Override
- protected TextRange getOccurrenceRange(Object occurrence) {
- if (occurrence instanceof PsiElement) {
- return ((PsiElement)occurrence).getTextRange();
- }
- else if (occurrence instanceof StringPartInfo) {
- return ((StringPartInfo)occurrence).getRange();
- }
- else {
- return null;
- }
- }
- }.showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
+ new IntroduceOccurrencesChooser(editor).showChooser(new Pass<OccurrencesChooser.ReplaceChoice>() {
@Override
public void pass(OccurrencesChooser.ReplaceChoice choice) {
- startInplace(info, context);
+ startInplace(info, context, choice);
}
}, occurrencesMap);
}
@@ -209,115 +180,27 @@
new GrIntroduceParameterDialog(info).show();
}
- private void startInplace(final IntroduceParameterInfo info, final GrIntroduceContext context) {
- final GrIntroduceParameterSettings settings = getSettingsForInplace(info, context);
- if (settings == null) return;
-
- CommandProcessor.getInstance().executeCommand(info.getProject(), new Runnable() {
- public void run() {
- Document document = context.getEditor().getDocument();
-
- List<RangeMarker> occurrences = ContainerUtil.newArrayList();
- if (settings.replaceAllOccurrences()) {
- for (PsiElement element : context.getOccurrences()) {
- occurrences.add(createRange(document, element));
- }
- }
- else if (context.getExpression() != null) {
- occurrences.add(createRange(document, context.getExpression()));
- }
-
- GrExpressionWrapper expr = new GrExpressionWrapper(GroovyIntroduceParameterUtil.findExpr(settings));
-
- SmartPsiElementPointer<GrParameter> pointer =
- ApplicationManager.getApplication().runWriteAction(new Computable<SmartPsiElementPointer<GrParameter>>() {
- @Override
- public SmartPsiElementPointer<GrParameter> compute() {
- Project project = context.getProject();
- GrParametersOwner toReplaceIn = info.getToReplaceIn();
- String name = GrInplaceParameterIntroducer.suggestNames(context, toReplaceIn).iterator().next();
- PsiType type = getType(context.getExpression(), context.getVar(), context.getStringPart());
- GrParameter parameter = GroovyIntroduceParameterMethodUsagesProcessor.addParameter(
- toReplaceIn, null,
- type != null ? type : PsiType.getJavaLangObject(PsiManager.getInstance(project), toReplaceIn.getResolveScope()), name,
- false, project);
- GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
-
- if (settings.replaceAllOccurrences()) {
- for (PsiElement element : context.getOccurrences()) {
- element.replace(factory.createReferenceExpressionFromText(name));
- }
- }
- else {
- context.getExpression().replace(factory.createReferenceExpressionFromText(name));
- }
- return SmartPointerManager.getInstance(project).createSmartPsiElementPointer(parameter);
- }
- });
- GrVariable parameter = pointer != null ? pointer.getElement() : null;
-
- if (parameter != null) {
- GrInplaceIntroducer introducer = getIntroducer(parameter, context, settings, occurrences, expr);
- PsiDocumentManager.getInstance(info.getProject()).doPostponedOperationsAndUnblockDocument(context.getEditor().getDocument());
- introducer.performInplaceRefactoring(introducer.suggestNames(context));
- }
- }
- }, REFACTORING_NAME, REFACTORING_NAME);
-
+ private static void startInplace(@NotNull final IntroduceParameterInfo info,
+ @NotNull final GrIntroduceContext context,
+ OccurrencesChooser.ReplaceChoice replaceChoice) {
+ new GrInplaceParameterIntroducer(info, context, replaceChoice).startInplaceIntroduceTemplate();
}
- private static GrInplaceIntroducer getIntroducer(GrVariable parameter,
- GrIntroduceContext context,
- GrIntroduceParameterSettings settings,
- List<RangeMarker> occurrences,
- GrExpressionWrapper expr) {
- //return new GrInplaceVariableIntroducer(parameter, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrences, parameter);
- return new GrInplaceParameterIntroducer(parameter, context.getEditor(), context.getProject(), REFACTORING_NAME, occurrences, context.getPlace(), settings, expr);
+ private static boolean isInplace(@NotNull IntroduceParameterInfo info,
+ @NotNull Editor editor) {
+ return findExpr(info) != null && GrIntroduceHandlerBase.isInplace(editor, info.getContext());
}
- private static GrIntroduceParameterSettings getSettingsForInplace(@NotNull IntroduceParameterInfo info, @NotNull GrIntroduceContext context) {
- GrExpression expr = context.getExpression();
- GrVariable var = context.getVar();
-
- TObjectIntHashMap<GrParameter> toRemove = GroovyIntroduceParameterUtil.findParametersToRemove(info);
- LinkedHashSet<String> names =
- GroovyIntroduceParameterUtil.suggestNames(var, expr, info.getStringPartInfo(), info.getToReplaceIn(), info.getProject());
- return new GrIntroduceExpressionSettingsImpl(info, names.iterator().next(), false, new TIntArrayList(toRemove.getValues()), false,
- IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, expr, var,
- getType(expr, var, info.getStringPartInfo()), false);
- }
-
- @Nullable
- private static PsiType getType(GrExpression expr, GrVariable var, StringPartInfo info) {
- if (expr != null) {
- return expr.getType();
- }
- else if (var != null) {
- return var.getDeclaredType();
- }
- else if (info != null) {
- return info.getLiteral().getType();
- }
- return null;
- }
-
- private static boolean isInplace(IntroduceParameterInfo info, Editor editor) {
- GrExpression expr = GroovyIntroduceParameterUtil.findExpr(info);
- GrVariable var = GroovyIntroduceParameterUtil.findVar(info);
- StringPartInfo stringPart = info.getStringPartInfo();
-
- return (expr != null || var != null || stringPart != null) && GrIntroduceHandlerBase.isInplace(editor, info.getContext());
- }
-
-
@Override
public void invoke(@NotNull Project project, @NotNull PsiElement[] elements, DataContext dataContext) {
// Does nothing
}
- private static GrIntroduceContext createContext(IntroduceParameterInfo info, Editor editor) {
- GrExpression expr = GroovyIntroduceParameterUtil.findExpr(info);
- GrVariable var = GroovyIntroduceParameterUtil.findVar(info);
- return new GrIntroduceVariableHandler().getContext(info.getProject(), editor, expr, var, info.getStringPartInfo(), info.getToReplaceIn());
+ private static GrIntroduceContext createContext(@NotNull IntroduceParameterInfo info,
+ @NotNull Editor editor) {
+ GrExpression expr = findExpr(info);
+ GrVariable var = findVar(info);
+ StringPartInfo stringPart = info.getStringPartInfo();
+ return new GrIntroduceVariableHandler().getContext(info.getProject(), editor, expr, var, stringPart, info.getToReplaceIn());
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java
index 86961a1..9a5ccb0 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GrIntroduceParameterProcessor.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.
@@ -78,9 +78,10 @@
LOG.assertTrue(settings.getToSearchFor() instanceof PsiMethod);
final StringPartInfo stringPartInfo = settings.getStringPartInfo();
- final GrExpression expression = stringPartInfo != null
- ? GrIntroduceHandlerBase.generateExpressionFromStringPart(stringPartInfo, settings.getProject())
- : settings.getExpression();
+ GrVariable var = settings.getVar();
+ final GrExpression expression = stringPartInfo != null ? stringPartInfo.createLiteralFromSelected() :
+ var != null ? var.getInitializerGroovy()
+ : settings.getExpression();
return new GrExpressionWrapper(expression);
}
@@ -177,9 +178,16 @@
}
if (mySettings.replaceAllOccurrences()) {
- PsiElement[] exprs = GroovyIntroduceParameterUtil.getOccurrences(mySettings);
- for (PsiElement expr : exprs) {
- result.add(new InternalUsageInfo(expr));
+ if (mySettings.getVar() != null) {
+ for (PsiElement element : GrIntroduceHandlerBase.collectVariableUsages(mySettings.getVar(), mySettings.getToReplaceIn())) {
+ result.add(new InternalUsageInfo(element));
+ }
+ }
+ else {
+ PsiElement[] exprs = GroovyIntroduceParameterUtil.getOccurrences(mySettings);
+ for (PsiElement expr : exprs) {
+ result.add(new InternalUsageInfo(expr));
+ }
}
}
else {
@@ -241,7 +249,7 @@
final StringPartInfo stringPartInfo = mySettings.getStringPartInfo();
if (stringPartInfo != null) {
final GrExpression
- expr = GrIntroduceHandlerBase.processLiteral(mySettings.getName(), mySettings.getStringPartInfo(), mySettings.getProject());
+ expr = mySettings.getStringPartInfo().replaceLiteralWithConcatenation(mySettings.getName());
final Editor editor = PsiUtilBase.findEditor(expr);
if (editor != null) {
editor.getSelectionModel().removeSelection();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java
index 5391a68..ef1e8f7 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/GroovyIntroduceParameterUtil.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.
@@ -379,6 +379,9 @@
@Nullable
static GrVariable findVar(IntroduceParameterInfo info) {
+ GrVariable variable = info.getVar();
+ if (variable != null) return variable;
+
final GrStatement[] statements = info.getStatements();
if (statements.length != 1) return null;
return GrIntroduceHandlerBase.findVariable(statements[0]);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java
index 2e1b0f8..a5383af 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/parameter/java2groovy/GroovyIntroduceParameterMethodUsagesProcessor.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.
@@ -270,7 +270,7 @@
@NotNull Project project) {
GroovyPsiElementFactory factory = GroovyPsiElementFactory.getInstance(project);
- final String typeText = forcedType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) ? null : forcedType.getCanonicalText();
+ final String typeText = forcedType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT) || forcedType == PsiType.NULL ? null : forcedType.getCanonicalText();
GrParameter parameter = factory.createParameter(parameterName, typeText, parametersOwner);
parameter.getModifierList().setModifierProperty(PsiModifier.FINAL, isFinal);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java
index a873298..ea1b272 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrInplaceVariableIntroducer.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.
@@ -133,7 +133,7 @@
var != null ? var.getType() :
stringPart != null ? stringPart.getLiteral().getType() :
null;
- myType = type != null ? CanonicalTypes.createTypeWrapper(type) : null;
+ myType = type != null && !PsiType.NULL.equals(type)? CanonicalTypes.createTypeWrapper(type) : null;
}
@@ -164,8 +164,10 @@
@Override
protected void addAdditionalVariables(TemplateBuilderImpl builder) {
GrVariable variable = getVariable();
- assert variable != null;
- TypeConstraint[] constraints = {SupertypeConstraint.create(variable.getInitializerGroovy().getType())};
+ assert variable != null && variable.getInitializerGroovy() != null;
+ final PsiType initializerType = variable.getInitializerGroovy().getType();
+ TypeConstraint[] constraints = initializerType != null && !initializerType.equals(PsiType.NULL) ? new SupertypeConstraint[]{SupertypeConstraint.create(initializerType)}
+ : TypeConstraint.EMPTY_ARRAY;
ChooseTypeExpression typeExpression = new ChooseTypeExpression(constraints, variable.getManager(), variable.getResolveScope(), true, GroovyApplicationSettings.getInstance().INTRODUCE_LOCAL_SELECT_DEF);
PsiElement element = variable.getTypeElementGroovy() != null ? variable.getTypeElementGroovy()
: PsiUtil.findModifierInList(variable.getModifierList(), GrModifier.DEF);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java
index 6b01652..849d2ca 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/introduce/variable/GrIntroduceVariableHandler.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.
@@ -195,7 +195,7 @@
GrVariableDeclaration varDecl = generateDeclaration(context, settings);
if (context.getStringPart() != null) {
- final GrExpression ref = processLiteral(DUMMY_NAME, context.getStringPart(), context.getProject());
+ final GrExpression ref = context.getStringPart().replaceLiteralWithConcatenation(DUMMY_NAME);
return doProcessExpression(context, settings, varDecl, new PsiElement[]{ref}, ref, true);
}
else {
@@ -222,7 +222,7 @@
private static GrExpression generateInitializer(@NotNull GrIntroduceContext context,
@NotNull GrVariable variable) {
final GrExpression initializer = context.getStringPart() != null
- ? GrIntroduceHandlerBase.generateExpressionFromStringPart(context.getStringPart(), context.getProject())
+ ? context.getStringPart().createLiteralFromSelected()
: context.getExpression();
final GrExpression dummyInitializer = variable.getInitializerGroovy();
assert dummyInitializer != null;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHelper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHelper.java
index 6e98ba8..7b37a83 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHelper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/memberPullUp/GrPullUpHelper.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.
@@ -330,26 +330,27 @@
final Map<PsiElement, PsiElement> replacement = new LinkedHashMap<PsiElement, PsiElement>();
for (PsiTypeParameter parameter : parametersIterable) {
PsiType substitutedType = substitutor.substitute(parameter);
- if (substitutedType == null) {
- substitutedType = TypeConversionUtil.erasure(factory.createType(parameter));
- }
+
+ PsiType type = substitutedType != null ? substitutedType : TypeConversionUtil.erasure(factory.createType(parameter));
PsiElement scopeElement = member instanceof GrField ? member.getParent() : member;
for (PsiReference reference : ReferencesSearch.search(parameter, new LocalSearchScope(scopeElement))) {
final PsiElement element = reference.getElement();
final PsiElement parent = element.getParent();
if (parent instanceof PsiTypeElement) {
- replacement.put(parent, factory.createTypeElement(substitutedType));
+ replacement.put(parent, factory.createTypeElement(type));
}
- else if (element instanceof GrCodeReferenceElement && substitutedType instanceof PsiClassType) {
- replacement.put(element, factory.createReferenceElementByType((PsiClassType)substitutedType));
+ else if (element instanceof GrCodeReferenceElement && type instanceof PsiClassType) {
+ replacement.put(element, factory.createReferenceElementByType((PsiClassType)type));
}
}
}
+ final JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(member.getProject());
for (PsiElement element : replacement.keySet()) {
if (element.isValid()) {
- element.replace(replacement.get(element));
+ final PsiElement replaced = element.replace(replacement.get(element));
+ codeStyleManager.shortenClassReferences(replaced);
}
}
}
@@ -593,12 +594,12 @@
private static void addSpacesAround(@NotNull GrReferenceList list) {
PsiElement prev = list.getPrevSibling();
- if (!PsiImplUtil.isWhiteSpace(prev)) {
+ if (!PsiImplUtil.isWhiteSpaceOrNls(prev)) {
list.getParent().getNode().addLeaf(TokenType.WHITE_SPACE, " ", list.getNode());
}
PsiElement next = list.getNextSibling();
- if (!PsiImplUtil.isWhiteSpace(next)) {
+ if (!PsiImplUtil.isWhiteSpaceOrNls(next)) {
list.getParent().getNode().addLeaf(TokenType.WHITE_SPACE, " ", list.getNode().getTreeNext());
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyClassHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyClassHandler.java
index ff36475..0bf6acc 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyClassHandler.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/move/MoveGroovyClassHandler.java
@@ -37,7 +37,6 @@
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocCommentOwner;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.impl.GrDocCommentUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
@@ -48,6 +47,7 @@
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.imports.GrImportStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.toplevel.packaging.GrPackageDefinition;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrCodeReferenceElement;
+import org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass;
import org.jetbrains.plugins.groovy.refactoring.GroovyChangeContextUtil;
@@ -186,7 +186,7 @@
if (packageDefinition != null) packageDefinition.delete();
PsiElement cur = newFile.getFirstChild();
- while (cur != null && TokenSets.WHITE_SPACES_SET.contains(cur.getNode().getElementType())) {
+ while (cur != null && PsiImplUtil.isWhiteSpaceOrNls(cur)) {
cur = cur.getNextSibling();
}
if (cur != null && cur != newFile.getFirstChild()) {
@@ -195,7 +195,7 @@
}
cur = newFile.getLastChild();
- while (cur != null && TokenSets.WHITE_SPACES_SET.contains(cur.getNode().getElementType())) {
+ while (cur != null && PsiImplUtil.isWhiteSpaceOrNls(cur)) {
cur = cur.getPrevSibling();
}
if (cur != null && cur != newFile.getLastChild()) {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGrFieldProcessor.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGrFieldProcessor.java
index 8ec7ce6..89cfd5d 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGrFieldProcessor.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenameGrFieldProcessor.java
@@ -32,7 +32,6 @@
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.containers.hash.HashMap;
-import com.intellij.util.containers.hash.LinkedHashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
@@ -99,18 +98,8 @@
renames.put(setter, GroovyPropertyUtils.getSetterName(newName));
}
- MultiMap<PsiNamedElement, UsageInfo> propertyUsages = new MultiMap<PsiNamedElement, UsageInfo>() {
- @Override
- protected Map<PsiNamedElement, Collection<UsageInfo>> createMap() {
- return new LinkedHashMap<PsiNamedElement, Collection<UsageInfo>>();
- }
- };
- MultiMap<PsiNamedElement, UsageInfo> simpleUsages = new MultiMap<PsiNamedElement, UsageInfo>() {
- @Override
- protected Map<PsiNamedElement, Collection<UsageInfo>> createMap() {
- return new LinkedHashMap<PsiNamedElement, Collection<UsageInfo>>();
- }
- };
+ MultiMap<PsiNamedElement, UsageInfo> propertyUsages = MultiMap.createLinked();
+ MultiMap<PsiNamedElement, UsageInfo> simpleUsages = MultiMap.createLinked();
List<PsiReference> unknownUsages = new ArrayList<PsiReference>();
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java
index fa12c81..38e495e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/DefaultGroovyScriptRunner.java
@@ -100,14 +100,13 @@
setToolsJar(params);
String groovyHome = useBundled ? FileUtil.toCanonicalPath(GroovyUtils.getBundledGroovyJar().getParentFile().getParent()) : LibrariesUtil.getGroovyHomePath(module);
- if (groovyHome != null) {
- groovyHome = FileUtil.toSystemDependentName(groovyHome);
- }
- if (groovyHome != null) {
- setGroovyHome(params, groovyHome);
+ String groovyHomeDependentName = groovyHome != null ? FileUtil.toSystemDependentName(groovyHome) : null;
+
+ if (groovyHomeDependentName != null) {
+ setGroovyHome(params, groovyHomeDependentName);
}
- final String confPath = getConfPath(groovyHome);
+ final String confPath = getConfPath(groovyHomeDependentName);
params.getVMParametersList().add("-Dgroovy.starter.conf=" + confPath);
params.getVMParametersList().addAll(HttpConfigurable.convertArguments(HttpConfigurable.getJvmPropertiesList(false, null)));
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java
index 33e3224..f4457d9 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/runner/GroovyScriptRunner.java
@@ -103,9 +103,7 @@
protected static VirtualFile findGroovyJar(@NotNull Module module) {
final VirtualFile[] files = OrderEnumerator.orderEntries(module).getAllLibrariesAndSdkClassesRoots();
for (VirtualFile root : files) {
- if (root.getName().matches(GroovyConfigUtils.GROOVY_JAR_PATTERN)
- || GroovyConfigUtils.matchesGroovyAll(root.getName()))
- {
+ if (GroovyConfigUtils.GROOVY_JAR_PATTERN.matcher(root.getName()).matches() || GroovyConfigUtils.matchesGroovyAll(root.getName())) {
return root;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java
index 8d99ae1..3ce8cb1 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/spock/SpockUtils.java
@@ -34,7 +34,6 @@
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.api.statements.typedef.members.GrMethod;
-import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.arithmetic.GrShiftExpressionImpl;
import org.jetbrains.plugins.groovy.util.LightCacheKey;
import java.util.*;
@@ -57,9 +56,10 @@
PsiFile containingFile = method.getContainingFile();
if (containingFile != containingFile.getOriginalFile()) {
- PsiElement originalPlace = containingFile.getOriginalFile().findElementAt(method.getTextOffset());
+ int methodOffset = method.getTextOffset();
+ PsiElement originalPlace = containingFile.getOriginalFile().findElementAt(methodOffset);
originalMethod = PsiTreeUtil.getParentOfType(originalPlace, GrMethod.class);
- assert originalMethod != null;
+ assert originalMethod != null : containingFile.getOriginalFile().getText().substring(Math.max(0, methodOffset - 50), Math.min(methodOffset + 50, containingFile.getOriginalFile().getText().length()));
}
else {
originalMethod = method;
@@ -115,36 +115,33 @@
PsiElement e = elementUnderLabel;
while (e != null) {
- if (e instanceof GrShiftExpressionImpl) {
- GrShiftExpressionImpl shift = (GrShiftExpressionImpl)e;
+ if (e instanceof GrBinaryExpression && ((GrBinaryExpression)e).getOperationTokenType() == GroovyElementTypes.COMPOSITE_LSHIFT_SIGN) {
+ GrBinaryExpression shift = (GrBinaryExpression)e;
+ GrExpression leftOperand = shift.getLeftOperand();
+ GrExpression rightOperand = shift.getRightOperand();
- if (shift.getOperationTokenType() == GroovyElementTypes.COMPOSITE_LSHIFT_SIGN) {
- GrExpression leftOperand = shift.getLeftOperand();
- GrExpression rightOperand = shift.getRightOperand();
-
- if (leftOperand instanceof GrReferenceExpression) {
- String name = getNameByReference(leftOperand);
- if (name != null) {
- SpockVariableDescriptor descriptor = new SpockVariableDescriptor(leftOperand, name);
- descriptor.addExpressionOfCollection(rightOperand);
- res.put(name, descriptor);
- }
+ if (leftOperand instanceof GrReferenceExpression) {
+ String name = getNameByReference(leftOperand);
+ if (name != null) {
+ SpockVariableDescriptor descriptor = new SpockVariableDescriptor(leftOperand, name);
+ descriptor.addExpressionOfCollection(rightOperand);
+ res.put(name, descriptor);
}
- else if (leftOperand instanceof GrListOrMap) {
- GrExpression[] variableDefinitions = ((GrListOrMap)leftOperand).getInitializers();
+ }
+ else if (leftOperand instanceof GrListOrMap) {
+ GrExpression[] variableDefinitions = ((GrListOrMap)leftOperand).getInitializers();
- SpockVariableDescriptor[] variables = createVariables(res, Arrays.asList(variableDefinitions));
+ SpockVariableDescriptor[] variables = createVariables(res, Arrays.asList(variableDefinitions));
- if (rightOperand instanceof GrListOrMap) {
- for (GrExpression expression : ((GrListOrMap)rightOperand).getInitializers()) {
- if (expression instanceof GrListOrMap) {
- add(variables, Arrays.asList(((GrListOrMap)expression).getInitializers()));
- }
- else {
- for (SpockVariableDescriptor variable : variables) {
- if (variable != null) {
- variable.addExpressionOfCollection(expression);
- }
+ if (rightOperand instanceof GrListOrMap) {
+ for (GrExpression expression : ((GrListOrMap)rightOperand).getInitializers()) {
+ if (expression instanceof GrListOrMap) {
+ add(variables, Arrays.asList(((GrListOrMap)expression).getInitializers()));
+ }
+ else {
+ for (SpockVariableDescriptor variable : variables) {
+ if (variable != null) {
+ variable.addExpressionOfCollection(expression);
}
}
}
@@ -169,14 +166,14 @@
List<GrExpression> row = new ArrayList<GrExpression>();
- PsiElement rowElement = getNext(e, elementUnderLabel,elementAfterLabel);
+ PsiElement rowElement = getNext(e, elementUnderLabel, elementAfterLabel);
while (isOrStatement(rowElement)) {
row.clear();
splitOr(row, (GrExpression)rowElement);
add(variables, row);
- rowElement = getNext(rowElement, elementUnderLabel,elementAfterLabel);
+ rowElement = getNext(rowElement, elementUnderLabel, elementAfterLabel);
}
e = rowElement;
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java
index ee62e88..d41c691 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/unwrap/GroovyUnwrapper.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -23,7 +23,6 @@
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
-import org.jetbrains.plugins.groovy.lang.lexer.TokenSets;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrBlockStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrIfStatement;
@@ -104,7 +103,7 @@
}
protected boolean isWhiteSpace(PsiElement element) {
- return PsiImplUtil.isLeafElementOfType(element, TokenSets.WHITE_SPACES_SET);
+ return org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil.isWhiteSpaceOrNls(element);
}
public void setElseBranch(GrIfStatement ifStatement, GrStatement elseBranch) throws IncorrectOperationException {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java
index 3b05608..723f53a 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/util/LibrariesUtil.java
@@ -143,7 +143,7 @@
private static String getGroovySdkHome(VirtualFile[] classRoots) {
for (VirtualFile file : classRoots) {
final String name = file.getName();
- if (name.matches(GroovyConfigUtils.GROOVY_JAR_PATTERN_NOVERSION) || name.matches(GroovyConfigUtils.GROOVY_JAR_PATTERN)) {
+ if (GroovyConfigUtils.GROOVY_JAR_PATTERN.matcher(name).matches()) {
String jarPath = file.getPresentableUrl();
File realFile = new File(jarPath);
if (realFile.exists()) {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy
index 3a2d988..1063666 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/GroovyLightProjectDescriptor.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.
@@ -24,8 +24,7 @@
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.fixtures.DefaultLightProjectDescriptor
-import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy2_1LibraryName
-import static org.jetbrains.plugins.groovy.util.TestUtils.getMockGroovy2_2LibraryName
+import static org.jetbrains.plugins.groovy.util.TestUtils.*
/**
* @author Max Medvedev
@@ -33,6 +32,7 @@
class GroovyLightProjectDescriptor extends DefaultLightProjectDescriptor {
public static final GroovyLightProjectDescriptor GROOVY_2_1 = new GroovyLightProjectDescriptor(mockGroovy2_1LibraryName)
public static final GroovyLightProjectDescriptor GROOVY_2_2 = new GroovyLightProjectDescriptor(mockGroovy2_2LibraryName)
+ public static final GroovyLightProjectDescriptor GROOVY_2_3 = new GroovyLightProjectDescriptor(mockGroovy2_3LibraryName)
private final String myLibPath
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy
index 388cf1d..29518e9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/LightGroovyTestCase.groovy
@@ -16,6 +16,8 @@
package org.jetbrains.plugins.groovy
+import com.intellij.psi.PsiIntersectionType
+import com.intellij.psi.PsiType
import com.intellij.testFramework.LightProjectDescriptor
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.annotations.NonNls
@@ -245,4 +247,30 @@
''')
}
+ public static void assertType(String expected, PsiType actual) {
+ if (expected == null) {
+ assertNull(actual)
+ return
+ }
+
+ assertNotNull(actual)
+ if (actual instanceof PsiIntersectionType) {
+ assertEquals(expected, genIntersectionTypeText(actual))
+ }
+ else {
+ assertEquals(expected, actual.canonicalText)
+ }
+ }
+
+ private static String genIntersectionTypeText(PsiIntersectionType t) {
+ StringBuilder b = new StringBuilder('[')
+ for (PsiType c : t.conjuncts) {
+ b << c.canonicalText << ','
+ }
+ if (t.conjuncts) {
+ b.replace(b.length() - 1, b.length(), ']')
+ }
+ return b
+ }
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyRangeTypeCheckTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyRangeTypeCheckTest.java
index 924b5e0..406a4b0 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyRangeTypeCheckTest.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/codeInspection/bugs/GroovyRangeTypeCheckTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -19,7 +19,7 @@
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.util.PsiTreeUtil;
@@ -49,7 +49,7 @@
LocalQuickFix[] fixes = {fix};
final ProblemDescriptor descriptor = InspectionManager.getInstance(getProject()).createProblemDescriptor(range, "bla-bla", false, fixes, ProblemHighlightType.WEAK_WARNING);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
fix.applyFix(myFixture.getProject(), descriptor);
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
index 205d3fc..4d25da3 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTestCase.java
@@ -240,7 +240,9 @@
semaphore.up();
}
});
- semaphore.waitFor();
+ if (!semaphore.waitFor(20000)) {
+ fail("Process took too long");
+ }
return processHandler.get();
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy
index a4b3fda..5904e75 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy
@@ -56,7 +56,7 @@
*/
class GroovyDebuggerTest extends GroovyCompilerTestCase {
@Override
- protected boolean useJps() { false }
+ protected boolean useJps() { true }
@Override
protected void setUp() {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy
index 7516575..f0a4f1a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GrCompletionWithLibraryTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -227,4 +227,8 @@
void testListCompletionVariantsFromDGM() {
doVariantableTest('drop', 'dropWhile')
}
+
+ public void testGStringConcatenationCompletion() {
+ myFixture.testCompletionVariants(getTestName(false) + ".groovy", "substring", "substring", "subSequence");
+ }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy
index 151a779..724cf40 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyAutoPopupTest.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.
@@ -114,10 +114,10 @@
}
public void testClassesAndPackagesInUnqualifiedImports() {
- myFixture.addClass("package xxxxx; public class xxxxxxxxx {}")
+ myFixture.addClass("package Xxxxx; public class Xxxxxxxxx {}")
myFixture.configureByText 'a.groovy', 'package foo; import <caret>'
- type 'xxx'
- assert myFixture.lookupElementStrings == ['xxxxxxxxx', 'xxxxx']
+ type 'Xxx'
+ assert myFixture.lookupElementStrings == ['Xxxxxxxxx', 'Xxxxx']
}
@@ -139,14 +139,18 @@
myFixture.addClass("class Foo { static class Bar {} }")
myFixture.configureByText "a.groovy", "void foo(Foo<caret>[] a) { }"
type '.'
- assert !lookup
+ assert lookup
+ type '.'
+ myFixture.checkResult('void foo(Foo..<caret>[] a) { }')
}
public void testTypingFirstVarargDot2() {
myFixture.addClass("class Foo { static class Bar {} }")
myFixture.configureByText "a.groovy", "void foo(Foo<caret>) { }"
type '.'
- assert !lookup
+ assert lookup
+ type '.'
+ myFixture.checkResult('void foo(Foo..<caret>) { }')
}
public void testDotDot() {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy
index 43fcda2..5f186b7 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyClassNameCompletionTest.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.
@@ -88,7 +88,7 @@
addClassToProject("a", "FooBarGooDoo");
myFixture.configureByText("a.groovy", "FBGD<caret>a")
myFixture.complete(CompletionType.BASIC, 2)
- myFixture.type '.'.charAt(0)
+ myFixture.type '.'
myFixture.checkResult "a.FooBarGooDoo.<caret>a"
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
index 7ab9a5c..946aae9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
@@ -238,10 +238,6 @@
doBasicTest();
}
- public void testGStringConcatenationCompletion() {
- myFixture.testCompletionVariants(getTestName(false) + ".groovy", "substring", "substring", "subSequence");
- }
-
public void testPropertyWithSecondUpperLetter() {
myFixture.testCompletionVariants(getTestName(false) + ".groovy", "geteMail", "getePost");
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy
index 315a534..017f399 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovySmartCompletionTest.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.
@@ -197,4 +197,21 @@
a(new foo.User<String>()<caret>)
''')
}
+
+ void testBinaryExpr() {
+ doSmartTest('''
+class A {
+ def plus(String s) {}
+}
+
+print new A() + new <caret>
+''', '''
+class A {
+ def plus(String s) {}
+}
+
+print new A() + new String(<caret>)
+'''
+)
+ }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy
index 127f8d1..bb0a4cb 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/KeywordCompletionTest.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.
@@ -104,6 +104,8 @@
void testElse2() { doTest() }
void testClassAfterAnnotation(){ doTest() }
void testClassAfterAnno2() { doTest() }
+ void testExtends() { doTest() }
+ void testImplements() { doTest() }
String basePath = TestUtils.testDataPath + 'groovy/oldCompletion/keyword'
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertMapToClassTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertMapToClassTest.java
index 89edcef..14d064e 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertMapToClassTest.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ConvertMapToClassTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -16,7 +16,7 @@
package org.jetbrains.plugins.groovy.intentions;
import com.intellij.codeInsight.intention.IntentionAction;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
@@ -79,7 +79,7 @@
final GrTypeDefinition foo = ConvertMapToClassIntention.createClass(getProject(), map.getNamedArguments(), "", "Foo");
myFixture.addFileToProject(getTestName(true) + "/Foo.groovy", foo.getContainingFile().getText());
final PsiClass psiClass = myFixture.findClass("Foo");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
ConvertMapToClassIntention
.replaceMapWithClass(getProject(), map, psiClass, ConvertMapToClassIntention.checkForReturnFromMethod(map),
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy
index 8156066..88f2e0e 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/CreateFieldFromParameterTest.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -14,12 +14,11 @@
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.intentions
-
import com.intellij.codeInsight.intention.impl.config.IntentionActionWrapper
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.plugins.groovy.intentions.declaration.GrCreateFieldForParameterIntention
import org.jetbrains.plugins.groovy.util.TestUtils
-
/**
* @author Max Medvedev
*/
@@ -56,8 +55,12 @@
for (intention in intentions) {
if (intention instanceof IntentionActionWrapper) intention = intention.delegate
if (intention instanceof GrCreateFieldForParameterIntention) {
- intention.invoke(myFixture.project, myFixture.editor, myFixture.file)
- doPostponedFormatting(project)
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ void run() {
+ intention.invoke(myFixture.project, myFixture.editor, myFixture.file)
+ doPostponedFormatting(myFixture.project)
+ }
+ })
break
}
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrIntentionTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrIntentionTestCase.groovy
index ef44b48..99143c2 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrIntentionTestCase.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrIntentionTestCase.groovy
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -25,6 +25,7 @@
import com.intellij.util.Function
import org.jetbrains.annotations.NotNull
import org.jetbrains.annotations.Nullable
+import org.jetbrains.plugins.groovy.intentions.base.Intention
/**
* @author Maxim.Medvedev
@@ -39,6 +40,11 @@
myHint = hint
}
+ GrIntentionTestCase(@NotNull Class<? extends IntentionAction> intention) {
+ myInspections = []
+ myHint = intention.newInstance().text
+ }
+
protected void doTest(@NotNull String hint = myHint, boolean intentionExists) {
assertNotNull(hint)
myFixture.configureByFile(getTestName(false) + ".groovy");
@@ -48,8 +54,8 @@
PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
myFixture.checkResultByFile(getTestName(false) + "_after.groovy");
}
- else if (list.size() > 0) {
- fail StringUtil.join(list, {it.familyName} as Function<IntentionAction, String>, ',')
+ else if (!list.empty) {
+ fail StringUtil.join(list, {IntentionAction it -> it.familyName}, ',')
}
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrSortMapTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrSortMapTest.groovy
new file mode 100644
index 0000000..86b0769
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/GrSortMapTest.groovy
@@ -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 org.jetbrains.plugins.groovy.intentions
+
+import org.jetbrains.plugins.groovy.intentions.other.GrSortMapKeysIntention
+import org.jetbrains.plugins.groovy.util.TestUtils
+
+/**
+ * Created by Max Medvedev on 11/01/14
+ */
+class GrSortMapTest extends GrIntentionTestCase {
+ GrSortMapTest() {
+ super(GrSortMapKeysIntention)
+ }
+
+ @Override
+ protected String getBasePath() {
+ TestUtils.testDataPath + 'intentions/sortMap/'
+ }
+
+ public void testBasicMapSort() throws Exception {
+ doTest(true)
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/RemoveExplicitTypeDeclarationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/RemoveExplicitTypeDeclarationTest.groovy
new file mode 100644
index 0000000..6eeea4f
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/RemoveExplicitTypeDeclarationTest.groovy
@@ -0,0 +1,38 @@
+/*
+ * 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.intentions
+
+import org.jetbrains.plugins.groovy.intentions.declaration.GrRemoveExplicitTypeDeclarationIntention
+import org.jetbrains.plugins.groovy.util.TestUtils
+
+/**
+ * Created by Max Medvedev on 27/12/13
+ */
+class RemoveExplicitTypeDeclarationTest extends GrIntentionTestCase {
+ def RemoveExplicitTypeDeclarationTest() {
+ super(GrRemoveExplicitTypeDeclarationIntention)
+ }
+
+ final String basePath = TestUtils.testDataPath + 'intentions/removeExplicitTypeDeclaration/'
+
+ void testMethod1() { doTest(true) }
+ void testMethod2() { doTest(true) }
+ void testMethod3() { doTest(true) }
+ void testMethod4() { doTest(true) }
+ void testMethod5() { doTest(true) }
+
+
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy
index b5fa168..ac83d7d 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyFixesTest.groovy
@@ -14,7 +14,8 @@
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang
-import com.intellij.openapi.application.ApplicationManager
+
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.plugins.groovy.codeInspection.control.GroovyConstantIfStatementInspection
import org.jetbrains.plugins.groovy.codeInspection.style.JavaStylePropertiesInvocationInspection
@@ -99,7 +100,7 @@
class Foo {}
''')
- ApplicationManager.application.runWriteAction { ((GroovyFile) myFixture.file).packageName = 'foo' }
+ WriteCommandAction.runWriteCommandAction project, { ((GroovyFile)myFixture.file).packageName = 'foo' }
myFixture.checkResult '''\
#!/usr/bin/groovy
package foo
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.groovy
index 789e35e..e67b07c 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovyLiveTemplatesTest.groovy
@@ -1,9 +1,19 @@
/*
- * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
- * Use is subject to license terms.
+ * 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.lang;
-
+package org.jetbrains.plugins.groovy.lang
import com.intellij.codeInsight.lookup.Lookup
import com.intellij.codeInsight.lookup.LookupManager
@@ -12,10 +22,10 @@
import com.intellij.codeInsight.template.impl.TemplateManagerImpl
import com.intellij.codeInsight.template.impl.TemplateSettings
import com.intellij.codeInsight.template.impl.actions.ListTemplatesAction
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.editor.Editor
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.plugins.groovy.util.TestUtils
-
/**
* @author peter
*/
@@ -58,8 +68,13 @@
}
public static void expandTemplate(final Editor editor) {
- new ListTemplatesAction().actionPerformedImpl(editor.getProject(), editor);
- ((LookupImpl)LookupManager.getActiveLookup(editor)).finishLookup(Lookup.NORMAL_SELECT_CHAR);
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ @Override
+ void run() {
+ new ListTemplatesAction().actionPerformedImpl(editor.getProject(), editor);
+ ((LookupImpl)LookupManager.getActiveLookup(editor)).finishLookup(Lookup.NORMAL_SELECT_CHAR);
+ }
+ })
}
public void testGroovyStatementContext() throws Exception {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy
index f90d2c5..859b81a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/controlFlow/ControlFlowTest.groovy
@@ -81,6 +81,7 @@
public void testBinaryExpressionInReturn() { doTest() }
public void testPendingFromIf() { doTest() }
public void testSwitchWithEmptyCaseBeforeDefault() { doTest() }
+ public void testUnfinishedAssignment() { doTest() }
public void doTest() {
final List<String> input = TestUtils.readInput(testDataPath + getTestName(true) + ".test");
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy
index a7ded29..01cb0f7 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/formatter/FormatterTest.groovy
@@ -713,6 +713,15 @@
'''
}
+ void testConditional2() {
+ groovySettings.ALIGN_MULTILINE_TERNARY_OPERATION = true
+ checkFormatting('''\
+print abc ? cde
+:xyz''', '''\
+print abc ? cde
+ : xyz''')
+ }
+
void testLabelsInBasicMode() {
groovySettings.indentOptions.INDENT_SIZE = 4
groovySettings.indentOptions.LABEL_INDENT_SIZE = -2
@@ -768,6 +777,10 @@
void testRegexExpressions() { doTest() }
+ void testSpreadArg() { doTest() }
+
+ void testExtraLines() { doTest() }
+
void testLabelWithDescription() {
GroovyCodeStyleSettings customSettings = myTempSettings.getCustomSettings(GroovyCodeStyleSettings.class)
CommonCodeStyleSettings commonSettings = myTempSettings.getCommonSettings(GroovyFileType.GROOVY_LANGUAGE)
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy
index 0709db7..03ac29a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GrAssignabilityTest.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.
@@ -368,7 +368,7 @@
foo<warning descr="'foo' in '_' cannot be applied to '(Function<java.lang.Double,java.lang.Double>)'">({println it.byteValue()} as Function<Double, Double>)</warning>
foo({println it.substring(1)} as Function)
foo({println it.substring(1)} as Function<String, String>)
-foo<warning descr="'foo' in '_' cannot be applied to '(groovy.lang.Closure<java.lang.Void>)'">({println it})</warning>
+foo<warning descr="'foo' in '_' cannot be applied to '(groovy.lang.Closure)'">({println it})</warning>
''')
}
@@ -799,4 +799,20 @@
}
''')
}
+
+ void testBinaryOperatorApplicability() {
+ testHighlighting('''\
+void bug(Collection<String> foo, Collection<String> bar) {
+ foo <warning descr="'leftShift' in 'org.codehaus.groovy.runtime.DefaultGroovyMethods' cannot be applied to '(java.util.Collection<java.lang.String>)'"><<</warning> bar // warning missed
+ foo << "a"
+}''')
+ }
+
+ void testPlusIsApplicable() {
+ testHighlighting('''\
+print 1 + 2
+
+print 4 <warning descr="'plus' in 'org.codehaus.groovy.runtime.StringGroovyMethods' cannot be applied to '(java.util.ArrayList)'">+</warning> new ArrayList()
+''')
+ }
}
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 efed43e..2b9ecad 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
@@ -20,10 +20,13 @@
import org.jetbrains.plugins.groovy.codeInspection.confusing.*
import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialConditionalInspection
import org.jetbrains.plugins.groovy.codeInspection.control.GroovyTrivialIfInspection
+import org.jetbrains.plugins.groovy.codeInspection.control.GroovyUnnecessaryContinueInspection
import org.jetbrains.plugins.groovy.codeInspection.control.GroovyUnnecessaryReturnInspection
import org.jetbrains.plugins.groovy.codeInspection.declaration.GrMethodMayBeStaticInspection
+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
/**
@@ -149,7 +152,7 @@
test() {
def var = "abc"
def cl = {
- <warning descr="Local variable var is reassigned in closure with other type">var</warning> = new Date()
+ <warning descr="Local variable 'var' is reassigned">var</warning> = new Date()
}
cl()
var.toUpperCase()
@@ -158,7 +161,7 @@
test2() {
def var = "abc"
def cl = {
- var = 'cde'
+ <warning descr="Local variable 'var' is reassigned">var</warning> = 'cde'
}
cl()
var.toUpperCase()
@@ -277,4 +280,71 @@
''', DelegatesToInspection)
}
+
+ void testUnnecessaryContinue() {
+ testHighlighting('''
+for(i in []) {
+ print 2
+ <warning descr="continue is unnecessary as the last statement in a loop">continue</warning>
+}
+
+for(i in []) {
+ print 2
+ continue
+ print 3
+}
+
+for(i in []) {
+ print 2
+ switch(i) {
+ case not_last:
+ continue
+ case last:
+ <warning descr="continue is unnecessary as the last statement in a loop">continue</warning>
+ }
+}
+
+for(i in []) {
+ if (cond) {
+ print 2
+ <warning descr="continue is unnecessary as the last statement in a loop">continue</warning>
+ }
+ else {
+ continue
+ print 4
+ }
+}
+''', GroovyUnnecessaryContinueInspection)
+ }
+
+ void testEmptyCatchBlock1() {
+ testHighlighting('''
+try{} <warning descr="Empty 'catch' block">catch</warning>(IOException e) {}
+try{} catch(IOException ignored) {}
+try{} catch(IOException ignore) {}
+try{} catch(IOException e) {/*comment*/}
+''', GroovyEmptyCatchBlockInspection)
+ }
+
+ void testEmptyCatchBlock2() {
+ GroovyEmptyCatchBlockInspection inspection = new GroovyEmptyCatchBlockInspection()
+ inspection.myIgnore = false
+ myFixture.enableInspections(inspection)
+ testHighlighting('try{} <warning descr="Empty \'catch\' block">catch</warning>(IOException ignored) {}')
+ }
+
+ void testEmptyCatchBlock3() {
+ GroovyEmptyCatchBlockInspection inspection = new GroovyEmptyCatchBlockInspection()
+ inspection.myIgnore = false
+ myFixture.enableInspections(inspection)
+ testHighlighting('try{} <warning descr="Empty \'catch\' block">catch</warning>(IOException ignored) {}')
+ }
+
+ void testEmptyCatchBlock4() {
+ GroovyEmptyCatchBlockInspection inspection = new GroovyEmptyCatchBlockInspection()
+ inspection.myCountCommentsAsContent = false
+ myFixture.enableInspections(inspection)
+ testHighlighting('try{} <warning descr="Empty \'catch\' block">catch</warning>(IOException e) {/*comment*/}')
+ }
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
index 87f7ba7..0405449 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/highlighting/GroovyHighlightingTest.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.
@@ -1472,15 +1472,15 @@
void testSOEIfExtendsItself() {
testHighlighting('''\
-<error descr="Cyclic inheritance involving 'A'"><error descr="Method 'invokeMethod' is not implemented">class A extends A </error></error>{
+<error descr="Cyclic inheritance involving 'A'"><error descr="Method 'invokeMethod' is not implemented">class A extends A</error></error> {
def foo
}
-<error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class B extends C </error></error>{
+<error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class B extends C</error></error> {
def foo
}
-<error descr="Cyclic inheritance involving 'C'"><error descr="Method 'invokeMethod' is not implemented">class C extends B </error></error>{
+<error descr="Cyclic inheritance involving 'C'"><error descr="Method 'invokeMethod' is not implemented">class C extends B</error></error> {
}
''')
}
@@ -1643,7 +1643,7 @@
}
''')
testHighlighting('''\
-<error>class Foo extends p.Base </error>{
+<error>class Foo extends p.Base</error> {
}
''')
}
@@ -1772,4 +1772,21 @@
''')
}
+ void testMinusInAnnotationArg() {
+ testHighlighting('''\
+@interface Xx {
+ int value()
+}
+
+@Xx(-1)
+public class Bar1 { }
+
+@Xx(+1)
+public class Bar2 { }
+
+@Xx(<error descr="Expected '++1' to be an inline constant">++1</error>)
+public class Bar3 { }
+''')
+ }
+
}
\ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy
index 4dba591..f31a6e3 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/overriding/GroovyOverrideImplementTest.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,7 +15,7 @@
*/
package org.jetbrains.plugins.groovy.lang.overriding
import com.intellij.codeInsight.generation.OverrideImplementUtil
-import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.PsiClassOwner
import com.intellij.psi.PsiMethod
@@ -99,8 +99,8 @@
"""
}
- void testTrhowsList() {
- myFixture.configureByText('a.groovy', '''\
+ void testThrowsList() {
+ assertImplement('''\
class X implements I {
<caret>
}
@@ -108,11 +108,7 @@
interface I {
void foo() throws RuntimeException
}
-''')
-
- generateImplementation(findMethod('I', 'foo'))
-
- myFixture.checkResult('''\
+''', 'I', 'foo', '''\
class X implements I {
@Override
@@ -127,6 +123,80 @@
''')
}
+ private void assertImplement(String textBefore, String clazz, String name, String textAfter) {
+ myFixture.configureByText('a.groovy', textBefore)
+ generateImplementation(findMethod(clazz, name))
+ myFixture.checkResult(textAfter)
+ }
+
+ void testThrowsListWithImport() {
+ myFixture.addClass('''\
+package pack;
+public class Exc extends RuntimeException {}
+''')
+
+ myFixture.addClass('''\
+import pack.Exc;
+
+interface I {
+ void foo() throws Exc;
+}
+''')
+
+ myFixture.configureByText('a.groovy', '''\
+class X implements I {
+ <caret>
+}
+''')
+
+ generateImplementation(findMethod('I', 'foo'))
+
+ myFixture.checkResult('''\
+import pack.Exc
+
+class X implements I {
+
+ @Override
+ void foo() throws Exc {
+
+ }
+}
+''')
+ }
+
+ void testNullableParameter() {
+ myFixture.addClass('''
+package org.jetbrains.annotations;
+public @interface Nullable{}
+''')
+
+ assertImplement('''
+import org.jetbrains.annotations.Nullable
+
+class Inheritor implements I {
+ <caret>
+}
+
+interface I {
+ def foo(@Nullable p)
+}
+''', 'I', 'foo', '''
+import org.jetbrains.annotations.Nullable
+
+class Inheritor implements I {
+
+ @Override
+ def foo(@Nullable Object p) {
+ <caret>return null
+ }
+}
+
+interface I {
+ def foo(@Nullable p)
+}
+''')
+ }
+
public void _testImplementIntention() {
myFixture.configureByText('a.groovy', '''
class Base<E> {
@@ -145,7 +215,7 @@
}
private def generateImplementation(PsiMethod method) {
- ApplicationManager.application.runWriteAction {
+ WriteCommandAction.runWriteCommandAction project, {
GrTypeDefinition clazz = (myFixture.file as PsiClassOwner).classes[0] as GrTypeDefinition
OverrideImplementUtil.overrideOrImplement(clazz, method);
PostprocessReformattingAspect.getInstance(myFixture.project).doPostponedFormatting()
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy
index ea365fd..5d933e7 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/ExpressionsParsingTest.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.
@@ -254,6 +254,7 @@
public void testreferences$ref5() throws Throwable { doTest(); }
public void testreferences$ref6() throws Throwable { doTest(); }
public void testreferences$ref7() throws Throwable { doTest(); }
+ public void testreferences$ref8() throws Throwable { doTest(); }
public void testreferences$emptyTypeArgs() { doTest() }
public void testregex$chen() throws Throwable { doTest(); }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy
index e15f174..98a5cf5 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/StatementsParsingTest.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.
@@ -95,6 +95,7 @@
public void testImports$imp5() throws Throwable { doTest(); }
public void testImports$imp6() throws Throwable { doTest(); }
public void testImports$imp7() throws Throwable { doTest(); }
+ public void testImports$imp8() throws Throwable { doTest(); }
public void testKing_regex$king1() throws Throwable { doTest(); }
public void testKing_regex$king2() throws Throwable { doTest(); }
public void testKing_regex$king3() throws Throwable { doTest(); }
@@ -116,6 +117,7 @@
public void testMultiple_assign$grvy2086() throws Throwable { doTest("multiple_assign/grvy-2086.test"); }
public void testMultiple_assign$mult_assign() throws Throwable { doTest(); }
public void testMultiple_assign$mult_def() throws Throwable { doTest(); }
+ public void testMultiple_assign$without_assign() throws Throwable { doTest(); }
public void testSwitch$laforge1() throws Throwable { doTest(); }
public void testSwitch$swit1() throws Throwable { doTest(); }
public void testSwitch$swit2() throws Throwable { doTest(); }
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy
index 489a2fe..fd91208 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/parser/TypesParsingTest.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.
@@ -34,6 +34,8 @@
public void testType11() throws Throwable { doTest(); }
public void testType12() throws Throwable { doTest(); }
public void testType13() throws Throwable { doTest(); }
+ public void testType14() throws Throwable { doTest(); }
+ public void testType15() throws Throwable { doTest(); }
public void testType2() throws Throwable { doTest(); }
public void testType3() throws Throwable { doTest(); }
public void testType4() throws Throwable { doTest(); }
@@ -49,5 +51,9 @@
public void testStaticInitializer() throws Throwable { doTest(); }
public void testInterfaceWithGroovyDoc() throws Throwable { doTest(); }
+ public void testIncorrectParam1() { doTest() }
+ public void testIncorrectParameter2() { doTest() }
+ public void testIncorrectParam3() { doTest() }
+
public void testEmptyTypeArgs() {doTest()}
}
\ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy
index 30030f2..2fba622 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/psi/GrStubAstSwitchTest.groovy
@@ -15,14 +15,19 @@
*/
package org.jetbrains.plugins.groovy.lang.psi
-import com.intellij.psi.PsiClass
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
+import com.intellij.psi.*
+import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.lang.psi.impl.GroovyFileImpl
/**
* Created by Max Medvedev on 12/4/13
*/
-class GrStubAstSwitchTest extends LightCodeInsightFixtureTestCase {
+class GrStubAstSwitchTest extends LightGroovyTestCase {
+ @Override
+ protected String getBasePath() {
+ null
+ }
+
void testDontLoadContentWhenProcessingImports() {
GroovyFileImpl file = (GroovyFileImpl) myFixture.addFileToProject("A.groovy", """
import java.util.concurrent.ConcurrentHashMap
@@ -44,4 +49,175 @@
fooMethod.findDeepestSuperMethods()
assert !file.contentsLoaded
}
+
+ void testDontLoadAstForAnnotation() {
+ GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\
+class A {
+ def foo(){}
+}
+
+class B {
+ @Delegate
+ A a = new A()
+}
+''') as GroovyFileImpl
+
+ assert !file.contentsLoaded
+ PsiClass clazzB = file.classes[1]
+ assert !file.contentsLoaded
+
+ PsiField field = clazzB.fields[0]
+ assert !file.contentsLoaded
+
+
+ PsiModifierList modifierList = field.modifierList
+ assert !file.contentsLoaded
+
+ PsiAnnotation[] annotations = modifierList.annotations
+ PsiAnnotation annotation = annotations[0]
+ assert !file.contentsLoaded
+
+ assert annotation.qualifiedName == 'groovy.lang.Delegate'
+ assert !file.contentsLoaded
+ }
+
+ void testDontLoadAstForAnnotation2() {
+ GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\
+class A {
+ def foo(){}
+}
+
+class B extends A {
+ @Override
+ def foo() {}
+}
+''') as GroovyFileImpl
+
+ assert !file.contentsLoaded
+ PsiClass clazzB = file.classes[1]
+ assert !file.contentsLoaded
+
+ PsiMethod method = clazzB.methods[0]
+ assert !file.contentsLoaded
+
+
+ PsiModifierList modifierList = method.modifierList
+ assert !file.contentsLoaded
+
+ PsiAnnotation[] annotations = modifierList.annotations
+ PsiAnnotation annotation = annotations[0]
+ assert !file.contentsLoaded
+
+ assert annotation.qualifiedName == "java.lang.Override"
+ assert !file.contentsLoaded
+ }
+
+
+ void testDelegateExists() {
+ GroovyFileImpl file = myFixture.addFileToProject('a.groovy', '''\
+class A {
+ def foo(){}
+}
+
+class B {
+ @Delegate
+ A a = new A()
+}
+''') as GroovyFileImpl
+
+ assert !file.contentsLoaded
+ PsiClass clazzB = file.classes[1]
+ assert !file.contentsLoaded
+
+ assert clazzB.methods.find {it.name =='foo'}
+ assert !file.contentsLoaded
+ }
+
+ void testDefaultValueForAnnotation() {
+ myFixture.addFileToProject('pack/Ann.groovy', '''\
+package pack
+
+@interface Ann {
+ String foo() default 'def'
+}
+''')
+
+ GroovyFileImpl file = myFixture.addFileToProject('usage.groovy', '''\
+import pack.Ann
+
+class X {
+ @Ann()
+ String bar() {}
+}
+''') as GroovyFileImpl
+
+ assert !file.contentsLoaded
+ PsiClass clazz = file.classes[0]
+ assert !file.contentsLoaded
+ PsiMethod method = clazz.methods[0]
+ assert !file.contentsLoaded
+ PsiAnnotation annotation = method.modifierList.findAnnotation('pack.Ann')
+ assert !file.contentsLoaded
+ assert annotation.findAttributeValue('foo') != null
+ assert !file.contentsLoaded
+ }
+
+ void testDefaultValueForAnnotationWithAliases() {
+ myFixture.addFileToProject('pack/Ann.groovy', '''\
+package pack
+
+@interface Ann {
+ String foo() default 'def'
+}
+''')
+
+ GroovyFileImpl file = myFixture.addFileToProject('usage.groovy', '''\
+import pack.Ann as A
+
+class X {
+ @A()
+ String bar() {}
+}
+''') as GroovyFileImpl
+
+ assert !file.contentsLoaded
+ PsiClass clazz = file.classes[0]
+ assert !file.contentsLoaded
+ PsiMethod method = clazz.methods[0]
+ assert !file.contentsLoaded
+ PsiAnnotation annotation = method.modifierList.findAnnotation('pack.Ann')
+ assert !file.contentsLoaded
+ assert annotation.findAttributeValue('foo') != null
+ assert !file.contentsLoaded
+ }
+
+ void testValueForAnnotationWithAliases() {
+ myFixture.addFileToProject('pack/Ann.groovy', '''\
+package pack
+
+@interface Ann {
+ String foo() default 'def'
+}
+''')
+
+ GroovyFileImpl file = myFixture.addFileToProject('usage.groovy', '''\
+import pack.Ann as A
+
+class X {
+ @A(foo='non_def')
+ String bar() {}
+}
+''') as GroovyFileImpl
+
+ assert !file.contentsLoaded
+ PsiClass clazz = file.classes[0]
+ assert !file.contentsLoaded
+ PsiMethod method = clazz.methods[0]
+ assert !file.contentsLoaded
+ PsiAnnotation annotation = method.modifierList.findAnnotation('pack.Ann')
+ assert !file.contentsLoaded
+ assert annotation.findAttributeValue('foo') != null
+ assert file.contentsLoaded
+ }
+
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy
index 2092272..485f91e 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveClassTest.groovy
@@ -306,5 +306,93 @@
''', PsiClass)
}
+ void testCollisionOfClassAndPackage() {
+ myFixture.addFileToProject('foo/Bar.groovy', '''\
+package foo
+
+class Bar {
+ static void xyz(){}
+}
+''')
+ def ref = configureByText('foo.groovy', '''\
+import foo.B<caret>ar
+
+print new Bar()
+''')
+
+ assertNotNull(ref.resolve())
+ }
+
+ void testCollisionOfClassAndPackage2() {
+ myFixture.addFileToProject('foo/Bar.groovy', '''\
+package foo
+
+class Bar {
+ static void xyz(){}
+}
+''')
+ def ref = configureByText('foo.groovy', '''\
+import static foo.Bar.xyz
+
+class foo {
+ public static void main(args) {
+ x<caret>yz() //should resolve to inner class
+ }
+
+ static class Bar {
+ static void xyz() {}
+ }
+}
+''')
+
+ PsiElement resolved = ref.resolve()
+ assertInstanceOf(resolved, PsiMethod)
+
+ PsiClass clazz = resolved.containingClass
+ assertNotNull(clazz.containingClass)
+ }
+
+
+ void testCollisionOfClassAndPackage3() {
+ myFixture.addFileToProject('foo/Bar.groovy', '''\
+package foo
+
+class Bar {
+ static void xyz(){}
+}
+''')
+ def ref = configureByText('foo.groovy', '''\
+import static foo.Bar.xyz
+
+x<caret>yz()
+''')
+
+ assertNotNull(ref.resolve())
+ }
+
+ void testCollisionOfClassAndPackage4() {
+ myFixture.addFileToProject('foo/Bar.groovy', '''\
+package foo
+
+class Bar {
+ static void xyz(){}
+}
+''')
+
+ def ref = configureByText('foo.groovy', '''\
+import static foo.Bar.xyz
+
+class foo {
+ public static void main(String[] args) {
+ x<caret>yz()
+ }
+}
+''')
+
+ PsiElement resolved = ref.resolve()
+ assertInstanceOf(resolved, PsiMethod)
+ }
+
+
private void doTest(String fileName = getTestName(false) + ".groovy") { resolve(fileName, PsiClass) }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
index 7b8296c..343e6d9 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveMethodTest.groovy
@@ -1872,11 +1872,11 @@
void testBinaryWithQualifiedRefsInArgs() {
GrBinaryExpression expr = configureByText('_.groovy', '''\
class Base {
- public static final int SHOW_NAME = 0x0001; // variable, method, class
- public static final int SHOW_TYPE = 0x0002; // variable, method
- public static final int TYPE_AFTER = 0x0004; // variable, method
- public static final int SHOW_MODIFIERS = 0x0008; // variable, method, class
- public static final int MODIFIERS_AFTER = 0x0010; // variable, method, class
+ def or(String s) {}
+ def or(Base b) {}
+
+ public static Base SHOW_NAME = new Base()
+ public static Base SHOW_TYPE = new Base()
}
class GrTypeDefinition {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy
index 6237f92..9762f67 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/ResolveWithDelegatesToTest.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.
@@ -653,6 +653,34 @@
''', 'String')
}
+ void testDelegateAndDelegatesTo() {
+ assertScript('''
+import groovy.transform.CompileStatic
+
+class Subject {
+ List list = []
+
+ void withList(@DelegatesTo(List) Closure<?> closure) {
+ list.with(closure)
+ }
+}
+
+class Wrapper {
+ @Delegate(parameterAnnotations = true)
+ Subject subject = new Subject()
+}
+
+@CompileStatic
+def staticOnWrapper() {
+ def wrapper = new Wrapper()
+ wrapper.withList {
+ ad<caret>d(1)
+ }
+ assert wrapper.list == [1]
+}
+''', 'List')
+ }
+
void assertScript(String text, String resolvedClass) {
myFixture.configureByText('_a.groovy', text)
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInference2_3Test.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInference2_3Test.groovy
new file mode 100644
index 0000000..731023d
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInference2_3Test.groovy
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.resolve
+
+import com.intellij.testFramework.LightProjectDescriptor
+import org.jetbrains.plugins.groovy.GroovyLightProjectDescriptor
+
+/**
+ * Created by Max Medvedev on 10/02/14
+ */
+class TypeInference2_3Test extends TypeInferenceTestBase {
+ @Override
+ protected LightProjectDescriptor getProjectDescriptor() {
+ return GroovyLightProjectDescriptor.GROOVY_2_3
+ }
+
+ public void testContravariantType() throws Exception {
+ doTest('''\
+import groovy.transform.CompileStatic
+import java.util.concurrent.Callable
+
+@CompileStatic
+class TestCase {
+
+ interface Action<T> {
+ void execute(T thing)
+ }
+
+ static class Wrapper<T> {
+
+ private final T thing
+
+ Wrapper(T thing) {
+ this.thing = thing
+ }
+
+ void contravariantTake(Action<? super T> action) {
+ action.execute(thing)
+ }
+
+ }
+
+ static <T> Wrapper<T> wrap(Callable<T> callable) {
+ new Wrapper(callable.call())
+ }
+
+ static Integer dub(Integer integer) {
+ integer * 2
+ }
+
+ static void main(String[] args) {
+ wrap {
+ 1
+ } contravariantTake {
+ dub(i<caret>t) // fails static compile, 'it' is not known to be Integer
+ }
+ }
+
+}
+''', 'java.lang.Integer')
+ }
+
+ void testSAMInference() {
+ doTest('''\
+import groovy.transform.CompileStatic
+
+interface CustomCallable<T> {
+ T call()
+}
+
+class Thing {
+ static <T> T customType(CustomCallable<T> callable) {
+ callable.call()
+ }
+
+ @CompileStatic
+ static void run() {
+ customType { [] }.ad<caret>d(1) // return type is not inferred - fails compile
+ }
+}
+''', "java.lang.Boolean")
+ }
+
+ void testSAMInference2() {
+ doTest('''\
+import groovy.transform.CompileStatic
+
+interface CustomCallable<T> {
+ List<T> call()
+}
+
+class Thing {
+ static <T> T first(CustomCallable<T> callable) {
+ callable.call().iterator().next()
+ }
+
+ @CompileStatic
+ static void run() {
+ first { [[]] }.ad<caret>d(1) // return type is not inferred - fails compile
+ }
+}
+''', "java.lang.Boolean")
+ }
+
+ void testSAMInference3() {
+ doTest('''\
+import groovy.transform.CompileStatic
+
+interface CustomCallable<K, V> {
+ Map<K, V> call()
+}
+
+class Thing {
+ static <K, V> Map<K, V> customType(CustomCallable<K, V> callable) {
+ callable.call()
+ }
+
+ @CompileStatic
+ static void run() {
+ customType { [(1):3] }.pu<caret>t(1, 5) // return type is not inferred - fails compile
+ }
+}
+
+''', 'java.lang.Integer')
+ }
+
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy
index e3dfe63..f02b940 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTest.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.
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.plugins.groovy.lang.resolve;
-
+package org.jetbrains.plugins.groovy.lang.resolve
import com.intellij.psi.PsiIntersectionType
import com.intellij.psi.PsiReference
@@ -26,15 +25,13 @@
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.impl.GrClosureType
-import org.jetbrains.plugins.groovy.util.TestUtils
import static com.intellij.psi.CommonClassNames.*
/**
* @author ven
*/
-public class TypeInferenceTest extends GroovyResolveTestCase {
- final String basePath = TestUtils.testDataPath + "resolve/inference/"
+public class TypeInferenceTest extends TypeInferenceTestBase {
public void testTryFinallyFlow() {
GrReferenceExpression ref = (GrReferenceExpression)configureByFile("tryFinallyFlow/A.groovy").element;
@@ -168,7 +165,7 @@
}
public void testConditionalExpressionWithNumericTypes() {
- assertTypeEquals("java.math.BigDecimal", "A.groovy");
+ assertTypeEquals("java.lang.Number", "A.groovy");
}
public void testImplicitCallMethod() {
@@ -223,7 +220,7 @@
final PsiReference ref = configureByFile(getTestName(true) + "/A.groovy");
assertInstanceOf(ref, GrReferenceExpression.class);
final PsiType type = ((GrReferenceExpression)ref).type;
- assertNull(type);
+ assertTrue(true); //test just should not fail with SOF exception
}
public void testTraditionalForVar() {
@@ -257,7 +254,7 @@
def getAt(String s) {new X()}
- def plus(X x, int i) {x}
+ def plus(int i) {this}
}
map = new X()
@@ -265,7 +262,7 @@
map['i'] += 2
''') as GroovyFile
GrAssignmentExpression assignment = file.topStatements[2] as GrAssignmentExpression
- assertTrue(assignment.LValue.type.equalsToText(JAVA_UTIL_DATE))
+ assertType("X", assignment.type)
}
void testAllTypeParamsAreSubstituted() {
@@ -605,33 +602,98 @@
''', 'java.lang.Object')
}
- private void doTest(String text, String type) {
- def file = myFixture.configureByText('_.groovy', text)
- def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
- def actual = ref.type
- if (type == null) {
- assertNull(actual)
- return
- }
-
- assertNotNull(actual)
- if (actual instanceof PsiIntersectionType) {
- assertEquals(type, genIntersectionTypeText(actual))
- }
- else {
- assertEquals(type, actual.canonicalText)
- }
+ void testUnary() {
+ doExprTest('~/abc/', 'java.util.regex.Pattern')
}
- private static String genIntersectionTypeText(PsiIntersectionType t) {
- StringBuilder b = new StringBuilder('[')
- for (PsiType c : t.conjuncts) {
- b.append(c.canonicalText).append(',')
- }
- if (t.conjuncts) {
- b.replace(b.length() - 1, b.length(), ']')
- }
- return b.toString()
+ void testUnary2() {
+ doExprTest('-/abc/', null)
+ }
+
+ void testUnary3() {
+ doExprTest('''
+ class A {
+ def bitwiseNegate() {'abc'}
+ }
+ ~new A()
+''', 'java.lang.String')
+ }
+
+ void testPlus1() {
+ doExprTest('2+2', 'java.lang.Integer')
+ }
+
+ void testPlus2() {
+ doExprTest('2f+2', 'java.lang.Double')
+ }
+
+ void testPlus3() {
+ doExprTest('2f+2f', 'java.lang.Double')
+ }
+
+ void testPlus4() {
+ doExprTest('2.5+2', 'java.math.BigDecimal')
+ }
+
+ void testMultiply1() {
+ doExprTest('2*2', 'java.lang.Integer')
+ }
+
+ void testMultiply2() {
+ doExprTest('2f*2f', 'java.lang.Double')
+ }
+
+ void testMultiply3() {
+ doExprTest('2d*2d', 'java.lang.Double')
+ }
+
+ void testMultiply4() {
+ doExprTest('2.4*2', 'java.math.BigDecimal')
+ }
+
+ void testMultiply5() {
+ doExprTest('((byte)2)*((byte)2)', 'java.lang.Integer')
+ }
+
+ void testMultiply6() {
+ doExprTest('"abc"*"cde"', 'java.lang.String') //expected number as a right operand
+ }
+
+ void testMultiply7() {
+ doExprTest('''
+ class A {
+ def multiply(A a) {new B()}
+ }
+ class B{}
+ new A()*new A()
+''', 'B')
+ }
+
+ void testMultiply8() {
+ doExprTest('''
+ class A { }
+ new A()*new A()
+''', null)
+ }
+
+ void testDiv1() {
+ doExprTest('1/2', 'java.math.BigDecimal')
+ }
+
+ void testDiv2() {
+ doExprTest('1/2.4', 'java.math.BigDecimal')
+ }
+
+ void testDiv3() {
+ doExprTest('1d/2', 'java.lang.Double')
+ }
+
+ void testDiv4() {
+ doExprTest('1f/2', 'java.lang.Double')
+ }
+
+ void testDiv5() {
+ doExprTest('1f/2.4', 'java.lang.Double')
}
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTestBase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTestBase.groovy
new file mode 100644
index 0000000..52c1e14
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/resolve/TypeInferenceTestBase.groovy
@@ -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 org.jetbrains.plugins.groovy.lang.resolve
+
+import org.intellij.lang.annotations.Language
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement
+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.util.TestUtils
+
+/**
+ * Created by Max Medvedev on 10/02/14
+ */
+abstract class TypeInferenceTestBase extends GroovyResolveTestCase {
+ final String basePath = TestUtils.testDataPath + "resolve/inference/"
+
+ @Override
+ protected void setUp() {
+ super.setUp()
+
+ myFixture.addClass("package java.math; public class BigDecimal extends Number implements Comparable<BigDecimal> {}");
+ }
+
+ protected void doTest(@Language("Groovy") String text, String type) {
+ def file = myFixture.configureByText('_.groovy', text)
+ def ref = file.findReferenceAt(myFixture.editor.caretModel.offset) as GrReferenceExpression
+ def actual = ref.type
+ assertType(type, actual)
+ }
+
+ protected void doExprTest(@Language("Groovy") String text, String expectedType) {
+ GroovyFile file = myFixture.configureByText('_.groovy', text) as GroovyFile
+ GrStatement lastStatement = file.statements.last()
+ assertInstanceOf lastStatement, GrExpression
+ assertType(expectedType, (lastStatement as GrExpression).type)
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/surroundWith/SurroundTestCase.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/surroundWith/SurroundTestCase.groovy
index 297a17c..ff86ea4 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/surroundWith/SurroundTestCase.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/surroundWith/SurroundTestCase.groovy
@@ -14,13 +14,11 @@
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.surroundWith
-
import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler
import com.intellij.lang.surroundWith.Surrounder
-import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.command.WriteCommandAction
import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.util.TestUtils
-
/**
* @author peter
*/
@@ -33,7 +31,7 @@
protected void doTest(final Surrounder surrounder, String textBefore, String textAfter) {
myFixture.configureByText("a.groovy", textBefore)
- ApplicationManager.application.runWriteAction {
+ WriteCommandAction.runWriteCommandAction project, {
SurroundWithHandler.invoke(project, myFixture.editor, myFixture.file, surrounder)
doPostponedFormatting(project)
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy
index ab2af7e..f6e5275 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/convertToJava/CodeBlockGenerationTest.groovy
@@ -196,4 +196,8 @@
void testStringConverting() { doTest() }
void testInWitchClassCheck() { doTest() }
+
+ void testSwitch() { doTest() }
+
+ void testPropSelection() { doTest() }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy
index d17fea8..baa7026 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/extract/method/ExtractMethodTest.groovy
@@ -239,4 +239,15 @@
''')
}
+ void testExtractMethodFromStringPart() {
+ doTest('-', '''\
+print 'a<begin>b<end>c'
+''', '''\
+print 'a' + '-'() + 'c'
+
+private String '-'() {
+ return 'b'
+}
+''')
+ }
}
\ No newline at end of file
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/implExtQuickFix/ImplementsExtendsQuickFixTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/implExtQuickFix/ImplementsExtendsQuickFixTest.groovy
index c1f689b..214d41f 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/implExtQuickFix/ImplementsExtendsQuickFixTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/implExtQuickFix/ImplementsExtendsQuickFixTest.groovy
@@ -1,6 +1,21 @@
+/*
+ * 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.refactoring.implExtQuickFix
-import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.psi.PsiFile
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.jetbrains.plugins.groovy.annotator.intentions.ChangeExtendsImplementsQuickFix
@@ -38,7 +53,7 @@
}
else {
- ApplicationManager.application.runWriteAction {
+ WriteCommandAction.runWriteCommandAction project, {
ChangeExtendsImplementsQuickFix fix = new ChangeExtendsImplementsQuickFix(typeDefinition)
fix.invoke(project, null, psiFile)
doPostponedFormatting(project)
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceConstantTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceConstantTest.groovy
new file mode 100644
index 0000000..99c5476
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceConstantTest.groovy
@@ -0,0 +1,190 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.introduce
+
+import com.intellij.openapi.command.WriteCommandAction
+import com.intellij.openapi.editor.Editor
+import com.intellij.psi.PsiClass
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiModifier
+import com.intellij.psi.PsiType
+import com.intellij.psi.impl.source.PostprocessReformattingAspect
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
+import com.intellij.util.VisibilityUtil
+import org.jetbrains.annotations.NotNull
+import org.jetbrains.annotations.Nullable
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
+import org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrIntroduceConstantHandler
+import org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrIntroduceConstantSettings
+import org.jetbrains.plugins.groovy.util.TestUtils
+
+/**
+ * @author Maxim.Medvedev
+ */
+public class IntroduceConstantTest extends LightCodeInsightFixtureTestCase {
+ @Override
+ protected String getBasePath() {
+ TestUtils.testDataPath + "refactoring/introduceConstant/"
+ }
+
+ public void testSimple() {
+ doTest();
+ }
+
+ public void testReplaceAllOccurences() {
+ doTest();
+ }
+
+ public void testEscalateVisibility() {
+ doTest("Other", true, false, VisibilityUtil.ESCALATE_VISIBILITY);
+ }
+
+ public void testInsertInEnum() {
+ doTest("Planet", false, false, PsiModifier.PROTECTED);
+ }
+
+ public void testInsertInInterface() {
+ doTest("MyInterface", false, false, PsiModifier.PROTECTED);
+ }
+
+ public void testTupleDeclaration() {
+ doTest("Test", true, false, PsiModifier.PUBLIC);
+ }
+
+ public void testStringPart() {
+ doTest();
+ }
+
+ public void testAnonymousClass() {
+ doTest();
+ }
+
+ public void testFieldWithClassName() {
+ doTest();
+ }
+
+ void testLocalVarRef() {
+ doTest()
+ }
+
+ private void doTest() {
+ doTest(null, true, true, PsiModifier.PUBLIC);
+ }
+
+ private void doTest(@Nullable String targetClassName, boolean replaceAllOccurrences, boolean useExplicitType, String modifier) {
+ myFixture.configureByFile(getTestName(false) + ".groovy");
+
+
+
+ final GrIntroduceConstantHandler handler = new GrIntroduceConstantHandler();
+ final Editor editor = myFixture.getEditor();
+
+ final GrExpression expression = findExpression();
+ final GrVariable variable = findVariable();
+ final StringPartInfo stringPart = findStringPart();
+ PsiElement[] scopes = handler.findPossibleScopes(expression, variable, stringPart, editor);
+ final GrIntroduceContext context = handler.getContext(getProject(), editor, expression, variable, stringPart, scopes[0]);
+
+ PsiClass targetClass = targetClassName == null ? GrIntroduceConstantHandler.findContainingClass(context)
+ : myFixture.findClass(targetClassName);
+ assertNotNull("target class is null", targetClass);
+
+ def type = getType(useExplicitType, expression, variable, stringPart)
+ final GrIntroduceConstantSettings settings = new MockIntroduceConstantSettings(targetClass, replaceAllOccurrences, type, modifier);
+
+ WriteCommandAction.runWriteCommandAction(null) {
+ handler.runRefactoring(context, settings);
+ PostprocessReformattingAspect.getInstance(project).doPostponedFormatting();
+ }
+ myFixture.checkResultByFile(getTestName(false) + "_after.groovy", true);
+ }
+
+ private static PsiType getType(boolean useExplicitType, GrExpression expression, GrVariable variable, StringPartInfo stringPart) {
+ if (!useExplicitType) {
+ return null;
+ }
+ return expression != null ? expression.getType() :
+ variable != null ? variable.getType() :
+ stringPart.getLiteral().getType();
+ }
+
+ @Nullable
+ private GrVariable findVariable() {
+ final Editor editor = myFixture.getEditor();
+ final int start = editor.getSelectionModel().getSelectionStart();
+ final int end = editor.getSelectionModel().getSelectionEnd();
+ return GrIntroduceHandlerBase.findVariable(myFixture.getFile(), start, end);
+ }
+
+ @Nullable
+ private GrExpression findExpression() {
+ final Editor editor = myFixture.getEditor();
+ final int start = editor.getSelectionModel().getSelectionStart();
+ final int end = editor.getSelectionModel().getSelectionEnd();
+ return GrIntroduceHandlerBase.findExpression(myFixture.getFile(), start, end);
+ }
+
+ @Nullable
+ private StringPartInfo findStringPart() {
+ final Editor editor = myFixture.getEditor();
+ final int start = editor.getSelectionModel().getSelectionStart();
+ final int end = editor.getSelectionModel().getSelectionEnd();
+ return StringPartInfo.findStringPart(myFixture.getFile(), start, end);
+ }
+
+ private static class MockIntroduceConstantSettings implements GrIntroduceConstantSettings {
+ private final PsiClass myTargetClass;
+ private final boolean myReplaceAllOccurrences;
+ private final PsiType mySelectedType;
+ private final String myModifier;
+
+ private MockIntroduceConstantSettings(@NotNull PsiClass targetClass,
+ boolean replaceAllOccurrences,
+ @Nullable PsiType selectedType,
+ String modifier) {
+ myTargetClass = targetClass;
+ myReplaceAllOccurrences = replaceAllOccurrences;
+ mySelectedType = selectedType;
+ myModifier = modifier;
+ }
+
+ @Override
+ public String getVisibilityModifier() {
+ return myModifier;
+ }
+
+ @Override
+ public PsiClass getTargetClass() {
+ return myTargetClass;
+ }
+
+ @Override
+ public String getName() {
+ return "CONST";
+ }
+
+ @Override
+ public boolean replaceAllOccurrences() {
+ return myReplaceAllOccurrences;
+ }
+
+ @Override
+ public PsiType getSelectedType() {
+ return mySelectedType;
+ }
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceConstantTest.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceConstantTest.java
deleted file mode 100644
index 81317cc..0000000
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/IntroduceConstantTest.java
+++ /dev/null
@@ -1,191 +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.refactoring.introduce;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiModifier;
-import com.intellij.psi.PsiType;
-import com.intellij.psi.impl.source.PostprocessReformattingAspect;
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
-import com.intellij.util.VisibilityUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
-import org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrIntroduceConstantHandler;
-import org.jetbrains.plugins.groovy.refactoring.introduce.constant.GrIntroduceConstantSettings;
-import org.jetbrains.plugins.groovy.util.TestUtils;
-
-/**
- * @author Maxim.Medvedev
- */
-public class IntroduceConstantTest extends LightCodeInsightFixtureTestCase {
- @Override
- protected String getBasePath() {
- return TestUtils.getTestDataPath() + "refactoring/introduceConstant/";
- }
-
- public void testSimple() {
- doTest();
- }
-
- public void testReplaceAllOccurences() {
- doTest();
- }
-
- public void testEscalateVisibility() {
- doTest("Other", true, false, VisibilityUtil.ESCALATE_VISIBILITY);
- }
-
- public void testInsertInEnum() {
- doTest("Planet", false, false, PsiModifier.PROTECTED);
- }
-
- public void testInsertInInterface() {
- doTest("MyInterface", false, false, PsiModifier.PROTECTED);
- }
-
- public void testTupleDeclaration() {
- doTest("Test", false, false, PsiModifier.PUBLIC);
- }
-
- public void testStringPart() {
- doTest();
- }
-
- public void testAnonymousClass() {
- doTest();
- }
-
- private void doTest() {
- doTest(null, true, true, PsiModifier.PUBLIC);
- }
-
- private void doTest(@Nullable String targetClassName, boolean replaceAllOccurences, boolean useExplicitType, String modifier) {
- myFixture.configureByFile(getTestName(false) + ".groovy");
-
-
-
- final GrIntroduceConstantHandler handler = new GrIntroduceConstantHandler();
- final Editor editor = myFixture.getEditor();
-
- final GrExpression expression = findExpression();
- final GrVariable variable = findVariable();
- final StringPartInfo stringPart = findStringPart();
- PsiElement[] scopes = handler.findPossibleScopes(expression, variable, stringPart, editor);
- final GrIntroduceContext context = handler.getContext(getProject(), editor, expression, variable, stringPart, scopes[0]);
-
- PsiClass targetClass;
- if (targetClassName == null) {
- targetClass = GrIntroduceConstantHandler.findContainingClass(context);
- }
- else {
- targetClass = myFixture.findClass(targetClassName);
- }
- assertNotNull("target class is null", targetClass);
-
- final GrIntroduceConstantSettings settings =
- new MockIntroduceConstantSettings(targetClass, replaceAllOccurences, getType(useExplicitType, expression, variable, stringPart), modifier);
-
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- handler.runRefactoring(context, settings);
- PostprocessReformattingAspect.getInstance(getProject()).doPostponedFormatting();
- }
- });
- myFixture.checkResultByFile(getTestName(false) + "_after.groovy", true);
- }
-
- private static PsiType getType(boolean useExplicitType, GrExpression expression, GrVariable variable, StringPartInfo stringPart) {
- if (!useExplicitType) {
- return null;
- }
- return expression != null ? expression.getType() :
- variable != null ? variable.getType() :
- stringPart.getLiteral().getType();
- }
-
- @Nullable
- private GrVariable findVariable() {
- final Editor editor = myFixture.getEditor();
- final int start = editor.getSelectionModel().getSelectionStart();
- final int end = editor.getSelectionModel().getSelectionEnd();
- return GrIntroduceHandlerBase.findVariable(myFixture.getFile(), start, end);
- }
-
- @Nullable
- private GrExpression findExpression() {
- final Editor editor = myFixture.getEditor();
- final int start = editor.getSelectionModel().getSelectionStart();
- final int end = editor.getSelectionModel().getSelectionEnd();
- return GrIntroduceHandlerBase.findExpression(myFixture.getFile(), start, end);
- }
-
- @Nullable
- private StringPartInfo findStringPart() {
- final Editor editor = myFixture.getEditor();
- final int start = editor.getSelectionModel().getSelectionStart();
- final int end = editor.getSelectionModel().getSelectionEnd();
- return StringPartInfo.findStringPart(myFixture.getFile(), start, end);
- }
-
- private static class MockIntroduceConstantSettings implements GrIntroduceConstantSettings {
- private PsiClass myTargetClass;
- private boolean myReplaceAllOccurrences;
- private PsiType mySelectedType;
- private String myModifier;
-
- private MockIntroduceConstantSettings(@NotNull PsiClass targetClass,
- boolean replaceAllOccurrences,
- @Nullable PsiType selectedType,
- String modifier) {
- myTargetClass = targetClass;
- myReplaceAllOccurrences = replaceAllOccurrences;
- mySelectedType = selectedType;
- myModifier = modifier;
- }
-
- @Override
- public String getVisibilityModifier() {
-
- return myModifier;
- }
-
- @Override
- public PsiClass getTargetClass() {
- return myTargetClass;
- }
-
- @Override
- public String getName() {
- return "CONST";
- }
-
- @Override
- public boolean replaceAllOccurrences() {
- return myReplaceAllOccurrences;
- }
-
- @Override
- public PsiType getSelectedType() {
- return mySelectedType;
- }
- }
-}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy
index 911f3a4..945eb1f 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduce/field/GrIntroduceFieldTest.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.
@@ -328,6 +328,23 @@
''', false, false, false, CUR_METHOD, false, null)
}
+ void testFromVar() {
+ doTest('''\
+class A {
+ def foo() {
+ def <selection>a = 5</selection>
+ print a
+ }
+}''', '''\
+class A {
+ def f = 5
+
+ def foo() {
+ print f
+ }
+}''', false, true, false, FIELD_DECLARATION, true, null)
+ }
+
private void doTest(final boolean isStatic,
final boolean removeLocal,
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy
index dcc405e..2f6b96a 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/ExtractClosureTest.groovy
@@ -13,9 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.plugins.groovy.refactoring.introduceParameter;
+package org.jetbrains.plugins.groovy.refactoring.introduceParameter
-
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.refactoring.IntroduceParameterRefactoring
import gnu.trove.TIntArrayList
import org.jetbrains.plugins.groovy.LightGroovyTestCase
@@ -47,7 +47,7 @@
GrIntroduceParameterSettings helper = new ExtractClosureHelperImpl(info, "closure", false,
new TIntArrayList(toRemove as int[]), false,
IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE,
- forceReturn, false)
+ forceReturn, false, false)
for (p in notToUseAsParams) {
helper.parameterInfos[p].passAsParameter = false
}
@@ -60,8 +60,10 @@
}
}
- handler.invoke myFixture.project, myFixture.editor, myFixture.file, null
- doPostponedFormatting(myFixture.project)
+ WriteCommandAction.runWriteCommandAction project, {
+ handler.invoke myFixture.project, myFixture.editor, myFixture.file, null
+ doPostponedFormatting(myFixture.project)
+ }
myFixture.checkResult after
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy
index 6c7f1b5..550c5a1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceParameter/GrIntroduceParameterTest.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.
@@ -23,11 +23,10 @@
import com.intellij.psi.PsiType
import com.intellij.psi.impl.source.PostprocessReformattingAspect
import com.intellij.refactoring.IntroduceParameterRefactoring
-import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import gnu.trove.TIntArrayList
import gnu.trove.TObjectIntHashMap
-import junit.framework.Assert
import org.jetbrains.annotations.Nullable
+import org.jetbrains.plugins.groovy.LightGroovyTestCase
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression
@@ -37,10 +36,12 @@
import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceHandlerBase
import org.jetbrains.plugins.groovy.refactoring.introduce.parameter.*
import org.jetbrains.plugins.groovy.util.TestUtils
+import org.junit.Assert
+
/**
* @author Maxim.Medvedev
*/
-public class GrIntroduceParameterTest extends LightCodeInsightFixtureTestCase {
+public class GrIntroduceParameterTest extends LightGroovyTestCase {
protected String getBasePath() {
return TestUtils.getTestDataPath() + "refactoring/introduceParameterGroovy/" + getTestName(true) + '/';
@@ -122,37 +123,32 @@
final Project project,
final Editor editor,
final PsiFile file) {
- CommandProcessor.getInstance().executeCommand(project, new Runnable() {
- @Override
- public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- try {
- final GrIntroduceParameterHandler hackedHandler = new GrIntroduceParameterHandler() {
- @Override
- protected void showDialog(IntroduceParameterInfo info) {
- final GrIntroduceParameterSettings hackedSettings = GrIntroduceParameterTest.getSettings(info, removeUnusedParameters, replaceFieldsWithGetters, declareFinal, generateDelegate);
- if (info.getToReplaceIn() instanceof GrMethod) {
- new GrIntroduceParameterProcessor(hackedSettings).run();
- }
- else {
- new GrIntroduceClosureParameterProcessor(hackedSettings).run();
- }
- }
- };
- hackedHandler.invoke(project, editor, file, null);
- if (conflicts != null) fail("Conflicts were expected");
- }
- catch (Exception e) {
- if (conflicts == null) {
- e.printStackTrace();
- fail("Conflicts were not expected");
+ CommandProcessor.instance.executeCommand(project, {
+ ApplicationManager.application.runWriteAction {
+ try {
+ final GrIntroduceParameterHandler hackedHandler = new GrIntroduceParameterHandler() {
+ @Override
+ protected void showDialog(IntroduceParameterInfo info) {
+ final GrIntroduceParameterSettings hackedSettings =
+ getSettings(info, removeUnusedParameters, replaceFieldsWithGetters, declareFinal, generateDelegate);
+ if (info.getToReplaceIn() instanceof GrMethod) {
+ new GrIntroduceParameterProcessor(hackedSettings).run();
}
- Assert.assertEquals(conflicts, e.getMessage());
+ else {
+ new GrIntroduceClosureParameterProcessor(hackedSettings).run();
+ }
}
+ };
+ hackedHandler.invoke(project, editor, file, null);
+ if (conflicts != null) fail("Conflicts were expected");
+ }
+ catch (Exception e) {
+ if (conflicts == null) {
+ e.printStackTrace();
+ fail("Conflicts were not expected");
}
- });
+ Assert.assertEquals(conflicts, e.getMessage());
+ }
}
}, "introduce Parameter", null);
}
@@ -173,11 +169,10 @@
final GrStatement[] statements = context.getStatements()
GrExpression expr = statements.length == 1 ? GrIntroduceHandlerBase.findExpression(statements[0]) : null;
- GrVariable var = statements.length == 1 ? GrIntroduceHandlerBase.findVariable(context.getStatements()[0]) : null;
- final PsiType type = TypesUtil.
- unboxPrimitiveTypeWrapper(var != null ? var.getType() : expr != null ? expr.getType() : context.stringPartInfo.literal.type);
+ GrVariable var = context.var
+ final PsiType type = TypesUtil.unboxPrimitiveTypeWrapper(var != null ? var.getType() : expr != null ? expr.getType() : context.stringPartInfo.literal.type);
return new GrIntroduceExpressionSettingsImpl(context, "anObject", declareFinal, toRemove, generateDelegate, replaceFieldsWithGetters,
- expr, var, type, true);
+ expr, var, type, var !=null, var != null, true);
}
@@ -357,4 +352,42 @@
}
''')
}
+
+
+ void testNullType() {
+ doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, null, false, '''\
+def foo() {
+ def a = '4'
+ <selection>print a</selection>
+}
+
+foo()
+''', '''\
+def foo(anObject) {
+ def a = '4'
+ anObject
+}
+
+foo(print(a))
+''')
+ }
+
+ void testIntroduceFromLocalVar() {
+ doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, null, false, '''\
+def foo() {
+ def <selection>var = 5</selection>
+
+ print var + var
+}
+
+foo()
+''', '''\
+def foo(anObject) {
+
+ print anObject + anObject
+}
+
+foo(5)
+''')
+ }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceLocalVariableTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceLocalVariableTest.groovy
index 63e5a75..4d4c838 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceLocalVariableTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceLocalVariableTest.groovy
@@ -14,21 +14,17 @@
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.refactoring.introduceVariable
+
import com.intellij.codeInsight.intention.impl.config.IntentionActionWrapper
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
-import com.intellij.psi.PsiType
import com.intellij.util.IncorrectOperationException
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.groovy.intentions.GrIntentionTestCase
import org.jetbrains.plugins.groovy.intentions.declaration.GrIntroduceLocalVariableIntention
-import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext
-import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GrIntroduceVariableHandler
-import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyIntroduceVariableDialog
-import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyIntroduceVariableSettings
-import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyVariableValidator
import org.jetbrains.plugins.groovy.util.TestUtils
+
/**
* @author siosio
*/
@@ -68,74 +64,4 @@
new MockGrIntroduceVariableHandler(settings).invoke(project, editor, element.containingFile, null);
}
}
-
- static class MockGrIntroduceVariableHandler extends GrIntroduceVariableHandler {
- private final MockSettings mySettings
-
- MockGrIntroduceVariableHandler(MockSettings settings) {
- mySettings = settings
- }
-
- @NotNull
- @Override
- protected GroovyIntroduceVariableDialog getDialog(@NotNull GrIntroduceContext context) {
- new MockGrIntroduceVariableDialog(context, new GroovyVariableValidator(context), mySettings)
- }
- }
-
- static class MockGrIntroduceVariableDialog extends GroovyIntroduceVariableDialog {
- private final MockSettings mySettings
-
- MockGrIntroduceVariableDialog(GrIntroduceContext context, GroovyVariableValidator validator, MockSettings settings) {
- super(context, validator)
- mySettings = settings
- }
-
- @Override
- void show() {
- close(0)
- }
-
- @Override
- MockSettings getSettings() { mySettings }
-
- @Override
- boolean isOK() {
- true
- }
- }
-
- static class MockSettings implements GroovyIntroduceVariableSettings {
- private final boolean myFinal
- private final String myName
- private final boolean myAllOccurrences
- private final PsiType myType
-
- MockSettings(final boolean isFinal, final String name, PsiType type, boolean allOccurrences) {
- myFinal = isFinal
- myName = name
- myType = type
- myAllOccurrences = allOccurrences
- }
-
- @Override
- boolean isDeclareFinal() {
- return myFinal
- }
-
- @Override
- String getName() {
- myName
- }
-
- @Override
- boolean replaceAllOccurrences() {
- return myAllOccurrences
- }
-
- @Override
- PsiType getSelectedType() {
- return myType
- }
- }
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.groovy
index 60a96ef..6d06726 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/IntroduceVariableTest.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.
@@ -119,6 +119,15 @@
''')
}
+ void testDollarSlashyString() {
+ doTest('''\
+print($/a<begin>b<end>c/$)
+''', '''\
+def preved = $/b/$
+print($/a/$ + preved + $/c/$)
+''')
+ }
+
protected static final String ALL_MARKER = "<all>"
private void processFile(String fileText, boolean explicitType) {
@@ -126,8 +135,8 @@
PsiType type = inferType(explicitType)
- final IntroduceLocalVariableTest.MockSettings settings = new IntroduceLocalVariableTest.MockSettings(false, "preved", type, replaceAllOccurrences)
- final GrIntroduceVariableHandler introduceVariableHandler = new IntroduceLocalVariableTest.MockGrIntroduceVariableHandler(settings)
+ final MockSettings settings = new MockSettings(false, "preved", type, replaceAllOccurrences)
+ final GrIntroduceVariableHandler introduceVariableHandler = new MockGrIntroduceVariableHandler(settings)
introduceVariableHandler.invoke(myFixture.project, myFixture.editor, myFixture.file, null)
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockGrIntroduceVariableDialog.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockGrIntroduceVariableDialog.java
new file mode 100644
index 0000000..a6113b7
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockGrIntroduceVariableDialog.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 org.jetbrains.plugins.groovy.refactoring.introduceVariable;
+
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
+import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyIntroduceVariableDialog;
+import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyVariableValidator;
+
+/**
+ * Created by Max Medvedev on 12/1/13
+ */
+public class MockGrIntroduceVariableDialog extends GroovyIntroduceVariableDialog {
+ private final MockSettings mySettings;
+
+ public MockGrIntroduceVariableDialog(GrIntroduceContext context, GroovyVariableValidator validator, MockSettings settings) {
+ super(context, validator);
+ mySettings = settings;
+ }
+
+ @Override
+ public void show() {
+ close(0);
+ }
+
+ @Override
+ public MockSettings getSettings() {
+ return mySettings;
+ }
+
+ @Override
+ public boolean isOK() {
+ return true;
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockGrIntroduceVariableHandler.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockGrIntroduceVariableHandler.java
new file mode 100644
index 0000000..64166c5
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockGrIntroduceVariableHandler.java
@@ -0,0 +1,40 @@
+/*
+ * 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.refactoring.introduceVariable;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.groovy.refactoring.introduce.GrIntroduceContext;
+import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GrIntroduceVariableHandler;
+import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyIntroduceVariableDialog;
+import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyVariableValidator;
+
+/**
+ * Created by Max Medvedev on 12/1/13
+ */
+public class MockGrIntroduceVariableHandler extends GrIntroduceVariableHandler {
+ private final MockSettings mySettings;
+
+ public MockGrIntroduceVariableHandler(MockSettings settings) {
+ mySettings = settings;
+ }
+
+ @NotNull
+ @Override
+ protected GroovyIntroduceVariableDialog getDialog(@NotNull GrIntroduceContext context) {
+ return new MockGrIntroduceVariableDialog(context, new GroovyVariableValidator(context), mySettings);
+ }
+
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockSettings.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockSettings.java
new file mode 100644
index 0000000..36d32ed
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/MockSettings.java
@@ -0,0 +1,56 @@
+/*
+ * 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.refactoring.introduceVariable;
+
+import com.intellij.psi.PsiType;
+import org.jetbrains.plugins.groovy.refactoring.introduce.variable.GroovyIntroduceVariableSettings;
+
+/**
+ * Created by Max Medvedev on 12/1/13
+ */
+public class MockSettings implements GroovyIntroduceVariableSettings {
+ private final boolean myFinal;
+ private final String myName;
+ private final boolean myAllOccurrences;
+ private final PsiType myType;
+
+ public MockSettings(final boolean isFinal, final String name, PsiType type, boolean allOccurrences) {
+ myFinal = isFinal;
+ myName = name;
+ myType = type;
+ myAllOccurrences = allOccurrences;
+ }
+
+ @Override
+ public boolean isDeclareFinal() {
+ return myFinal;
+ }
+
+ @Override
+ public String getName() {
+ return myName;
+ }
+
+ @Override
+ public boolean replaceAllOccurrences() {
+ return myAllOccurrences;
+ }
+
+ @Override
+ public PsiType getSelectedType() {
+ return myType;
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/StringExtractingTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/StringExtractingTest.groovy
new file mode 100644
index 0000000..3a06da0
--- /dev/null
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/introduceVariable/StringExtractingTest.groovy
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.introduceVariable
+
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.command.CommandProcessor
+import com.intellij.openapi.util.TextRange
+import org.jetbrains.plugins.groovy.LightGroovyTestCase
+import org.jetbrains.plugins.groovy.lang.psi.GroovyFile
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.literals.GrLiteral
+import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil
+import org.jetbrains.plugins.groovy.refactoring.introduce.StringPartInfo
+import org.jetbrains.plugins.groovy.util.TestUtils
+
+/**
+ * Created by Max Medvedev on 04/02/14
+ */
+class StringExtractingTest extends LightGroovyTestCase {
+
+ @Override
+ protected String getBasePath() {
+ return TestUtils.testDataPath + "refactoring/stringExtracting/"
+ }
+
+ public void testStringExtractingFromQuote() { doTest() }
+
+ public void testStringExtractingFromDoubleQuotes() { doTest() }
+
+ public void testStringExtractingFromSlashyString() { doTest() }
+
+ public void testStringExtractingFromDollarSlashyString() { doTest() }
+
+ public void testSlashyWithSlash() { doTest() }
+
+ public void testDollarSlashyWithDollar() { doTest() }
+
+ public void testSlashyWithSlashInsideExtractedPart() { doTest() }
+
+ private void doTest() {
+ GroovyFile file = myFixture.configureByFile(getTestName(true) + '.groovy') as GroovyFile
+
+ TextRange range = new TextRange(*myFixture.editor.selectionModel.with { [selectionStart, selectionEnd] })
+
+ CommandProcessor.instance.executeCommand(myFixture.project, {
+ ApplicationManager.application.runWriteAction {
+ new StringPartInfo(PsiUtil.skipParentheses(file.statements[0], false) as GrLiteral, range).replaceLiteralWithConcatenation(null)
+ myFixture.editor.selectionModel.removeSelection()
+ }
+ }, null, null)
+
+ myFixture.checkResultByFile(getTestName(true) + '_after.groovy')
+ }
+}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
index 6d2105a..2239271 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/optimizeImports/OptimizeImportsTest.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.
@@ -125,8 +125,6 @@
doTest();
}
- public void testJavaUtilString() { doTest(); }
-
public void testSamePackage() {
myFixture.addClass("package foo; public class Bar {}");
myFixture.configureFromExistingVirtualFile(myFixture.copyFileToProject(getTestName(false) + ".groovy", "foo/Foo.groovy"));
@@ -146,6 +144,14 @@
public void testRemoveImplicitlyImported() { doTest(); }
public void testRemoveImplicitlyDemandImported() { doTest(); }
public void testDontRemoveRedImports() { doTest(); }
+ public void testDontRemoveRedImports2() { doTest(); }
+ public void testDontRemoveRedImports3() { doTest(); }
+ public void testDontRemoveRedImports4() { doTest(); }
+ public void testDontRemoveRedImports5() { doTest(); }
+ public void testDontRemoveRedImports6() { doTest(); }
+ public void testDontRemoveRedImports7() { doTest(); }
+ public void testDontRemoveRedImports8() { doTest(); }
+ public void testDontRemoveRedImports9() { doTest(); }
public void testRemoveSamePackaged() {
myFixture.addClass("package foo.bar; public class Aaaa {}");
@@ -157,9 +163,9 @@
}
public void testJustWrongImport() throws Exception {
- myFixture.configureByText("a.groovy", "import a.b.c.d");
+ myFixture.configureByText("a.groovy", "import a.b.c.d; final d c;");
doOptimizeImports();
- myFixture.checkResult("import a.b.c.d");
+ myFixture.checkResult("import a.b.c.d; final d c;");
}
public void testCleanBeforeJavadoc() throws Exception {
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy
index 38d3b39..e1a39a1 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/refactoring/rename/RenameTest.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,6 +15,7 @@
*/
package org.jetbrains.plugins.groovy.refactoring.rename
+import com.intellij.openapi.command.WriteCommandAction
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.*
import com.intellij.psi.impl.source.PostprocessReformattingAspect
@@ -76,11 +77,13 @@
myFixture.configureByText(GroovyFileType.GROOVY_FILE_TYPE, """
import foo.bar.Zoo
SomeClass c = new SomeClass()
+Zoo zoo
""")
myFixture.renameElement(someClass, "NewClass")
myFixture.checkResult """
import foo.bar.Zoo
NewClass c = new NewClass()
+Zoo zoo
"""
}
@@ -523,7 +526,9 @@
private def doInplaceRenameTest() {
String prefix = "/${getTestName(false)}"
myFixture.configureByFile prefix + ".groovy";
- CodeInsightTestUtil.doInlineRename(new GrVariableInplaceRenameHandler(), "foo", myFixture);
+ WriteCommandAction.runWriteCommandAction project, {
+ CodeInsightTestUtil.doInlineRename(new GrVariableInplaceRenameHandler(), "foo", myFixture);
+ }
myFixture.checkResultByFile prefix + "_after.groovy"
}
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
index b709431..e534333 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.java
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/util/TestUtils.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.
@@ -59,6 +59,7 @@
public static final String GROOVY_JAR_18 = "groovy-1.8.0-beta-2.jar";
public static final String GROOVY_JAR_21 = "groovy-all-2.1.3.jar";
public static final String GROOVY_JAR_22 = "groovy-all-2.2.0-beta-1.jar";
+ public static final String GROOVY_JAR_23 = "groovy-all-2.3.0.jar";
public static String getMockJdkHome() {
return getAbsoluteTestDataPath() + "/mockJDK";
@@ -92,6 +93,10 @@
return getAbsoluteTestDataPath() + "/mockGroovyLib2.2";
}
+ private static String getMockGroovy2_3LibraryHome() {
+ return getAbsoluteTestDataPath() + "/mockGroovyLib2.3";
+ }
+
public static String getMockGroovy1_8LibraryName() {
return getMockGroovy1_8LibraryHome()+"/"+GROOVY_JAR_18;
}
@@ -104,6 +109,10 @@
return getMockGroovy2_2LibraryHome() + "/" + GROOVY_JAR_22;
}
+ public static String getMockGroovy2_3LibraryName() {
+ return getMockGroovy2_3LibraryHome() + "/" + GROOVY_JAR_23;
+ }
+
public static PsiFile createPseudoPhysicalGroovyFile(final Project project, final String text) throws IncorrectOperationException {
return createPseudoPhysicalFile(project, TEMP_FILE, text);
}
diff --git a/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine.test b/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine.test
index 56aeaea..2d542f2 100644
--- a/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine.test
+++ b/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine.test
@@ -3,11 +3,11 @@
}
pri<caret>ntln 'b'
-pri<caret>ntln 'c'
+println 'c'
-----
if (true) {
println 'a'
pri<caret>ntln 'b'
}
-pri<caret>ntln 'c'
\ No newline at end of file
+println 'c'
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine2.test b/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine2.test
index b144854..2d8ab23 100644
--- a/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine2.test
+++ b/plugins/groovy/testdata/groovy/actions/moveStatement/moveIntoEmptyLine2.test
@@ -2,10 +2,10 @@
}
pri<caret>ntln 'b'
-pri<caret>ntln 'c'
+println 'c'
-----
if (true) {
pri<caret>ntln 'b'
}
-pri<caret>ntln 'c'
\ No newline at end of file
+println 'c'
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/completion/GroovyDocParameter.groovy b/plugins/groovy/testdata/groovy/completion/GroovyDocParameter.groovy
index 69eb9e6..a14f4b7 100644
--- a/plugins/groovy/testdata/groovy/completion/GroovyDocParameter.groovy
+++ b/plugins/groovy/testdata/groovy/completion/GroovyDocParameter.groovy
@@ -3,7 +3,7 @@
* @param x<caret> abc
* dfgdsfgdjkg
* @param y sdgfhjsd
- * @param <caret>
+ * @param
*/
def abc(def xx, def xy) {
diff --git a/plugins/groovy/testdata/groovy/controlFlow/mayBeStaticWithCondition.test b/plugins/groovy/testdata/groovy/controlFlow/mayBeStaticWithCondition.test
index bd37862..362d0ea 100644
--- a/plugins/groovy/testdata/groovy/controlFlow/mayBeStaticWithCondition.test
+++ b/plugins/groovy/testdata/groovy/controlFlow/mayBeStaticWithCondition.test
@@ -4,9 +4,8 @@
1(2) READ a
2(3,6) Condition Instanceof expression
3(4) instanceof: a instanceof String
-4(5,9) Negating goto instruction, condition=2Instanceof expression
-5() element: Instanceof expression MAYBE_RETURN
+4(5) Negating goto instruction, condition=2Instanceof expression
+5(8) element: Instanceof expression MAYBE_RETURN
6(7) instanceof: a instanceof String
7(8) element: Instanceof expression MAYBE_RETURN
-8(9) element: Instanceof expression MAYBE_RETURN
-9() element: null
\ No newline at end of file
+8() element: null
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/controlFlow/unfinishedAssignment.test b/plugins/groovy/testdata/groovy/controlFlow/unfinishedAssignment.test
new file mode 100644
index 0000000..3fc4b3b
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/controlFlow/unfinishedAssignment.test
@@ -0,0 +1,9 @@
+def a = 5
+
+a =
+-----
+0(1) element: null
+1(2) WRITE a
+2(3) WRITE a
+3(4) element: Assignment expression MAYBE_RETURN
+4() element: null
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/formatter/extraLines.test b/plugins/groovy/testdata/groovy/formatter/extraLines.test
new file mode 100644
index 0000000..1fa2e57
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/formatter/extraLines.test
@@ -0,0 +1,14 @@
+package abc
+
+
+
+
+
+
+
+print 1
+-----
+package abc
+
+
+print 1
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/formatter/mapInArgumentList.test b/plugins/groovy/testdata/groovy/formatter/mapInArgumentList.test
index ea87e82..8101230 100644
--- a/plugins/groovy/testdata/groovy/formatter/mapInArgumentList.test
+++ b/plugins/groovy/testdata/groovy/formatter/mapInArgumentList.test
@@ -7,7 +7,7 @@
-----
test(
changesSorter: [
- (GradleMismatchedLibraryPathChange): 2,
+ (GradleMismatchedLibraryPathChange) : 2,
(GradleLibraryDependencyPresenceChange): 1
]
)
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/formatter/spreadArg.test b/plugins/groovy/testdata/groovy/formatter/spreadArg.test
new file mode 100644
index 0000000..e259549
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/formatter/spreadArg.test
@@ -0,0 +1,7 @@
+def foo(x, y) {}
+
+foo(* [1, 3])
+-----
+def foo(x, y) {}
+
+foo(*[1, 3])
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test b/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test
index 65af467..c602447 100644
--- a/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test
+++ b/plugins/groovy/testdata/groovy/formatter/stuffAfterLineComments.test
@@ -23,9 +23,9 @@
// comment for this formal parameter
, b) {
[a + b
- // comment for this formula
- , a * b
- , a / b
+ // comment for this formula
+ , a * b
+ , a / b
].collect { it * 2 }
}
diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/extends.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/extends.test
new file mode 100644
index 0000000..0bea567
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/extends.test
@@ -0,0 +1,3 @@
+class A ext<caret>
+-----
+extends
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/oldCompletion/keyword/implements.test b/plugins/groovy/testdata/groovy/oldCompletion/keyword/implements.test
new file mode 100644
index 0000000..388b59d
--- /dev/null
+++ b/plugins/groovy/testdata/groovy/oldCompletion/keyword/implements.test
@@ -0,0 +1,3 @@
+class Y im<caret>
+-----
+implements
\ No newline at end of file
diff --git a/plugins/groovy/testdata/groovy/refactoring/extractMethod/noContextConflicts.test b/plugins/groovy/testdata/groovy/refactoring/extractMethod/noContextConflicts.test
index 23964f5..6d59ee9 100644
--- a/plugins/groovy/testdata/groovy/refactoring/extractMethod/noContextConflicts.test
+++ b/plugins/groovy/testdata/groovy/refactoring/extractMethod/noContextConflicts.test
@@ -19,8 +19,8 @@
testMethod()
}
- private void testMethod() {
- use(StringCategory) {
+ private testMethod() {
+ return use(StringCategory) {
println "TeSt".lower()
}
}
diff --git a/plugins/groovy/testdata/highlighting/CircularInheritance.groovy b/plugins/groovy/testdata/highlighting/CircularInheritance.groovy
index b7d0c57..d0e3ad2 100644
--- a/plugins/groovy/testdata/highlighting/CircularInheritance.groovy
+++ b/plugins/groovy/testdata/highlighting/CircularInheritance.groovy
@@ -1,4 +1,4 @@
-<error descr="Cyclic inheritance involving 'Foo'"><error descr="Method 'invokeMethod' is not implemented">class Foo extends Bar </error></error>{}
-<error descr="Cyclic inheritance involving 'Bar'"><error descr="Method 'invokeMethod' is not implemented">class Bar extends Foo </error></error>{}
+<error descr="Cyclic inheritance involving 'Foo'"><error descr="Method 'invokeMethod' is not implemented">class Foo extends Bar</error></error> {}
+<error descr="Cyclic inheritance involving 'Bar'"><error descr="Method 'invokeMethod' is not implemented">class Bar extends Foo</error></error> {}
println(new Foo())
\ No newline at end of file
diff --git a/plugins/groovy/testdata/highlighting/ConstructorWithAllParametersOptional.groovy b/plugins/groovy/testdata/highlighting/ConstructorWithAllParametersOptional.groovy
index 889f437..f3af609 100644
--- a/plugins/groovy/testdata/highlighting/ConstructorWithAllParametersOptional.groovy
+++ b/plugins/groovy/testdata/highlighting/ConstructorWithAllParametersOptional.groovy
@@ -9,6 +9,6 @@
def Base2(int x){}
}
-<error descr="There is no default constructor available in class 'Base2'">class Inheritor2 extends Base2 </error>{
+<error descr="There is no default constructor available in class 'Base2'">class Inheritor2 extends Base2</error> {
}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy b/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy
index 1b48c6e..43f9fc4 100644
--- a/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy
+++ b/plugins/groovy/testdata/highlighting/CyclicInheritance.groovy
@@ -1,15 +1,15 @@
-<error descr="Cyclic inheritance involving 'A'"><error descr="Method 'invokeMethod' is not implemented">class A extends C </error></error>{
+<error descr="Cyclic inheritance involving 'A'"><error descr="Method 'invokeMethod' is not implemented">class A extends C</error></error> {
}
-<error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class B extends A </error></error>{
+<error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class B extends A</error></error> {
}
-<error descr="Cyclic inheritance involving 'C'"><error descr="Method 'invokeMethod' is not implemented">class C extends B </error></error>{
+<error descr="Cyclic inheritance involving 'C'"><error descr="Method 'invokeMethod' is not implemented">class C extends B</error></error> {
}
-<error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class D extends B </error></error>{
+<error descr="Cyclic inheritance involving 'B'"><error descr="Method 'invokeMethod' is not implemented">class D extends B</error></error> {
}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot.groovy b/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot.groovy
index b40c523..df90ca2 100644
--- a/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot.groovy
+++ b/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot.groovy
@@ -1 +1,2 @@
+def test = 1
print test<caret>+".test"
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot_after.groovy b/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot_after.groovy
index a8b09fd..38210c2 100644
--- a/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot_after.groovy
+++ b/plugins/groovy/testdata/intentions/convertConcatenationToGstring/Dot_after.groovy
@@ -1 +1,2 @@
+def test = 1
print "${test}.test"
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method1.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method1.groovy
new file mode 100644
index 0000000..458f95b
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method1.groovy
@@ -0,0 +1 @@
+int f<caret>oo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method1_after.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method1_after.groovy
new file mode 100644
index 0000000..20c0509
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method1_after.groovy
@@ -0,0 +1 @@
+def foo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method2.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method2.groovy
new file mode 100644
index 0000000..5f9b349
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method2.groovy
@@ -0,0 +1,2 @@
+@Nullable
+int f<caret>oo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method2_after.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method2_after.groovy
new file mode 100644
index 0000000..9976ebc
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method2_after.groovy
@@ -0,0 +1,2 @@
+@Nullable
+def foo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method3.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method3.groovy
new file mode 100644
index 0000000..9bbe853
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method3.groovy
@@ -0,0 +1,2 @@
+@Abnc public
+int f<caret>oo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method3_after.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method3_after.groovy
new file mode 100644
index 0000000..a3cce56
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method3_after.groovy
@@ -0,0 +1,2 @@
+@Abnc public
+def f<caret>oo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method4.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method4.groovy
new file mode 100644
index 0000000..70e3ce9
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method4.groovy
@@ -0,0 +1 @@
+@Abc def public int f<caret>oo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method4_after.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method4_after.groovy
new file mode 100644
index 0000000..69b230a
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method4_after.groovy
@@ -0,0 +1 @@
+@Abc def public f<caret>oo() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method5.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method5.groovy
new file mode 100644
index 0000000..b88295e
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method5.groovy
@@ -0,0 +1,2 @@
+public def
+int fo<caret>o() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method5_after.groovy b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method5_after.groovy
new file mode 100644
index 0000000..b8f85c7
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/removeExplicitTypeDeclaration/Method5_after.groovy
@@ -0,0 +1,2 @@
+public
+def fo<caret>o() {}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/sortMap/BasicMapSort.groovy b/plugins/groovy/testdata/intentions/sortMap/BasicMapSort.groovy
new file mode 100644
index 0000000..f39fa4f
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/sortMap/BasicMapSort.groovy
@@ -0,0 +1 @@
+def phones = [Pet<caret>er: 45678, Max : 78564, Ann : 23467]
\ No newline at end of file
diff --git a/plugins/groovy/testdata/intentions/sortMap/BasicMapSort_after.groovy b/plugins/groovy/testdata/intentions/sortMap/BasicMapSort_after.groovy
new file mode 100644
index 0000000..3aac7db
--- /dev/null
+++ b/plugins/groovy/testdata/intentions/sortMap/BasicMapSort_after.groovy
@@ -0,0 +1,3 @@
+def phones = [Ann : 23467,
+ Max : 78564,
+ Peter: 45678]
\ No newline at end of file
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
new file mode 100644
index 0000000..3b5173f
--- /dev/null
+++ b/plugins/groovy/testdata/mockGroovyLib2.3/groovy-all-2.3.0.jar
Binary files differ
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports.groovy
index 71eb1fe..cdbbb60 100644
--- a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports.groovy
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports.groovy
@@ -4,4 +4,5 @@
class ScriptRunnerProxyy {
private static ClassLoader scriptLoader
+ Abc f;
}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports2.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports2.groovy
new file mode 100644
index 0000000..62b8e2a
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports2.groovy
@@ -0,0 +1,8 @@
+import java.zzz
+import java.yyy.*
+import java.lang.ClassLoader
+
+class ScriptRunnerProxyy {
+ private static ClassLoader scriptLoader
+ private zzz f;
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports2_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports2_after.groovy
new file mode 100644
index 0000000..1194d38
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports2_after.groovy
@@ -0,0 +1,7 @@
+import java.yyy.*
+import java.zzz
+
+class ScriptRunnerProxyy {
+ private static ClassLoader scriptLoader
+ private zzz f;
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports3.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports3.groovy
new file mode 100644
index 0000000..6d9ff60
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports3.groovy
@@ -0,0 +1,8 @@
+import java.zzzz
+import java.yyy.*
+import java.lang.ClassLoader
+
+class ScriptRunnerProxyy {
+ private static ClassLoader scriptLoader
+ private zzz f;
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports3_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports3_after.groovy
new file mode 100644
index 0000000..38f1f99
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports3_after.groovy
@@ -0,0 +1,6 @@
+import java.yyy.*
+
+class ScriptRunnerProxyy {
+ private static ClassLoader scriptLoader
+ private zzz f;
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports4.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports4.groovy
new file mode 100644
index 0000000..f6913f4
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports4.groovy
@@ -0,0 +1,8 @@
+import java.zzz as Abc
+import java.yyy.*
+import java.lang.ClassLoader
+
+class ScriptRunnerProxyy {
+ private static ClassLoader scriptLoader
+ private Abc f;
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports4_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports4_after.groovy
new file mode 100644
index 0000000..b36474f
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports4_after.groovy
@@ -0,0 +1,7 @@
+import java.yyy.*
+import java.zzz as Abc
+
+class ScriptRunnerProxyy {
+ private static ClassLoader scriptLoader
+ private Abc f;
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports5.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports5.groovy
new file mode 100644
index 0000000..dcb9c90
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports5.groovy
@@ -0,0 +1,6 @@
+import java.x.Cde as Abc
+import java.x.Cde
+
+class ScriptRunnerProxyy {
+ private static Cde x
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports5_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports5_after.groovy
new file mode 100644
index 0000000..293f042
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports5_after.groovy
@@ -0,0 +1,5 @@
+import java.x.Cde
+
+class ScriptRunnerProxyy {
+ private static Cde x
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports6.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports6.groovy
new file mode 100644
index 0000000..416cbc1
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports6.groovy
@@ -0,0 +1,6 @@
+import java.x.Cde as Abc
+import java.x.Cde
+
+class ScriptRunnerProxyy {
+ private static Abc x
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports6_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports6_after.groovy
new file mode 100644
index 0000000..5c94d50
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports6_after.groovy
@@ -0,0 +1,5 @@
+import java.x.Cde as Abc
+
+class ScriptRunnerProxyy {
+ private static Abc x
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports7.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports7.groovy
new file mode 100644
index 0000000..6cbf4a2
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports7.groovy
@@ -0,0 +1,7 @@
+import java.x.Cde as Abc
+import java.x.Cde
+
+class ScriptRunnerProxyy {
+ private static Cde x
+ private static Abc y
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports7_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports7_after.groovy
new file mode 100644
index 0000000..6cbf4a2
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports7_after.groovy
@@ -0,0 +1,7 @@
+import java.x.Cde as Abc
+import java.x.Cde
+
+class ScriptRunnerProxyy {
+ private static Cde x
+ private static Abc y
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports8.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports8.groovy
new file mode 100644
index 0000000..dd0b3f6
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports8.groovy
@@ -0,0 +1,4 @@
+import static abc.X.foo
+import static abc.X.bar
+
+print foo()
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports8_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports8_after.groovy
new file mode 100644
index 0000000..b3eafc4
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports8_after.groovy
@@ -0,0 +1,3 @@
+import static abc.X.foo
+
+print foo()
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports9.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports9.groovy
new file mode 100644
index 0000000..1fb427b
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports9.groovy
@@ -0,0 +1,4 @@
+import static abc.X.foo as bar
+import static abc.X.baz as xyz
+
+print bar()
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports9_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports9_after.groovy
new file mode 100644
index 0000000..0549ca7
--- /dev/null
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports9_after.groovy
@@ -0,0 +1,3 @@
+import static abc.X.foo as bar
+
+print bar()
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports_after.groovy b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports_after.groovy
index 3521213..2fcf294 100644
--- a/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports_after.groovy
+++ b/plugins/groovy/testdata/optimizeImports/DontRemoveRedImports_after.groovy
@@ -1,6 +1,6 @@
-import java.zzz
import java.yyy.*
class ScriptRunnerProxyy {
private static ClassLoader scriptLoader
+ Abc f;
}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/JavaUtilString.groovy b/plugins/groovy/testdata/optimizeImports/JavaUtilString.groovy
deleted file mode 100644
index 82a136d..0000000
--- a/plugins/groovy/testdata/optimizeImports/JavaUtilString.groovy
+++ /dev/null
@@ -1,9 +0,0 @@
-import java.util.String
-
-class GrEnum {
-
- {
- new AntBuilder().delete(dir: workdir.absolutePath)
- }
-
-}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/optimizeImports/JavaUtilString_after.groovy b/plugins/groovy/testdata/optimizeImports/JavaUtilString_after.groovy
deleted file mode 100644
index 82a136d..0000000
--- a/plugins/groovy/testdata/optimizeImports/JavaUtilString_after.groovy
+++ /dev/null
@@ -1,9 +0,0 @@
-import java.util.String
-
-class GrEnum {
-
- {
- new AntBuilder().delete(dir: workdir.absolutePath)
- }
-
-}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/ann1.test b/plugins/groovy/testdata/parsing/groovy/annotations/ann1.test
index 7896c70..803951b 100644
--- a/plugins/groovy/testdata/parsing/groovy/annotations/ann1.test
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/ann1.test
@@ -29,11 +29,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/ann2.test b/plugins/groovy/testdata/parsing/groovy/annotations/ann2.test
index 564bd35..b0fae49 100644
--- a/plugins/groovy/testdata/parsing/groovy/annotations/ann2.test
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/ann2.test
@@ -40,9 +40,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/ann3.test b/plugins/groovy/testdata/parsing/groovy/annotations/ann3.test
index 9b42636..f7645a0 100644
--- a/plugins/groovy/testdata/parsing/groovy/annotations/ann3.test
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/ann3.test
@@ -9,9 +9,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -21,9 +21,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Nullable')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(def)('def')
PsiWhiteSpace(' ')
Type element
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/ann4.test b/plugins/groovy/testdata/parsing/groovy/annotations/ann4.test
index df85630..2718b61 100644
--- a/plugins/groovy/testdata/parsing/groovy/annotations/ann4.test
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/ann4.test
@@ -26,11 +26,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/ann7.test b/plugins/groovy/testdata/parsing/groovy/annotations/ann7.test
index fb003a0..b48fc30 100644
--- a/plugins/groovy/testdata/parsing/groovy/annotations/ann7.test
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/ann7.test
@@ -30,11 +30,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('GroovyClass')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/annotations/classLiteral.test b/plugins/groovy/testdata/parsing/groovy/annotations/classLiteral.test
index a9cdf2d..f7692a1 100644
--- a/plugins/groovy/testdata/parsing/groovy/annotations/classLiteral.test
+++ b/plugins/groovy/testdata/parsing/groovy/annotations/classLiteral.test
@@ -24,11 +24,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/comments/error1205.test b/plugins/groovy/testdata/parsing/groovy/comments/error1205.test
index 8035ba6..5206e22 100644
--- a/plugins/groovy/testdata/parsing/groovy/comments/error1205.test
+++ b/plugins/groovy/testdata/parsing/groovy/comments/error1205.test
@@ -10,11 +10,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/closures/param6.test b/plugins/groovy/testdata/parsing/groovy/expressions/closures/param6.test
index 075c6b3..37bed96 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/closures/param6.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/closures/param6.test
@@ -32,9 +32,9 @@
Literal
PsiElement(Integer)('3')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/closures/param7.test b/plugins/groovy/testdata/parsing/groovy/expressions/closures/param7.test
index 9f0ec7b..a918012 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/closures/param7.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/closures/param7.test
@@ -11,9 +11,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/path/method/method13.test b/plugins/groovy/testdata/parsing/groovy/expressions/path/method/method13.test
index 19e07d1..86db5c7 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/path/method/method13.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/path/method/method13.test
@@ -12,9 +12,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/path/typeVsExpr.test b/plugins/groovy/testdata/parsing/groovy/expressions/path/typeVsExpr.test
index 9a94767..c498a14 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/path/typeVsExpr.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/path/typeVsExpr.test
@@ -13,9 +13,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/references/ref8.test b/plugins/groovy/testdata/parsing/groovy/expressions/references/ref8.test
new file mode 100644
index 0000000..d2d4cc4
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/references/ref8.test
@@ -0,0 +1,26 @@
+'abc'
+ {
+ print 2
+ }
+-----
+Groovy script
+ Method call
+ Reference expression
+ PsiElement(string)(''abc'')
+ Arguments
+ <empty list>
+ PsiElement(new line)('\n ')
+ Closable block
+ PsiElement({)('{')
+ PsiWhiteSpace('\n ')
+ Parameter list
+ <empty list>
+ Call expression
+ Reference expression
+ PsiElement(identifier)('print')
+ PsiWhiteSpace(' ')
+ Command arguments
+ Literal
+ PsiElement(Integer)('2')
+ PsiElement(new line)('\n ')
+ PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/super/qualifiedSuper.test b/plugins/groovy/testdata/parsing/groovy/expressions/super/qualifiedSuper.test
index df0c2b6..1749c57 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/super/qualifiedSuper.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/super/qualifiedSuper.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('X')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -28,9 +28,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/super/super.test b/plugins/groovy/testdata/parsing/groovy/expressions/super/super.test
index e6dcf1e..9038561 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/super/super.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/super/super.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('X')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -28,9 +28,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/this/qualifiedThis.test b/plugins/groovy/testdata/parsing/groovy/expressions/this/qualifiedThis.test
index bdf617e..a16ce31 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/this/qualifiedThis.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/this/qualifiedThis.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('X')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -28,9 +28,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/expressions/this/this.test b/plugins/groovy/testdata/parsing/groovy/expressions/this/this.test
index 068199e..8a07aed 100644
--- a/plugins/groovy/testdata/parsing/groovy/expressions/this/this.test
+++ b/plugins/groovy/testdata/parsing/groovy/expressions/this/this.test
@@ -30,9 +30,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/err1.test b/plugins/groovy/testdata/parsing/groovy/generics/err1.test
index 9fa0c15..5d5bbc0 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/err1.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/err1.test
@@ -36,11 +36,11 @@
Type extends bounds list
<empty list>
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/err2.test b/plugins/groovy/testdata/parsing/groovy/generics/err2.test
index d9abd0e..7d97b4d 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/err2.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/err2.test
@@ -29,11 +29,11 @@
Type extends bounds list
<empty list>
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/err3.test b/plugins/groovy/testdata/parsing/groovy/generics/err3.test
index 0356c86..274b2b8 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/err3.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/err3.test
@@ -10,11 +10,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/err4.test b/plugins/groovy/testdata/parsing/groovy/generics/err4.test
index 67281e6..572d106 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/err4.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/err4.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/genmethod1.test b/plugins/groovy/testdata/parsing/groovy/generics/genmethod1.test
index 353896f..3b9fb06 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/genmethod1.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/genmethod1.test
@@ -18,9 +18,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/genmethod2.test b/plugins/groovy/testdata/parsing/groovy/generics/genmethod2.test
index d96d79f..21224e5 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/genmethod2.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/genmethod2.test
@@ -16,11 +16,11 @@
Type extends bounds list
<empty list>
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n')
@@ -45,9 +45,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/genmethod3.test b/plugins/groovy/testdata/parsing/groovy/generics/genmethod3.test
index ea2dce1..5798bb1 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/genmethod3.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/genmethod3.test
@@ -16,9 +16,9 @@
Type extends bounds list
<empty list>
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n')
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/genmethod4.test b/plugins/groovy/testdata/parsing/groovy/generics/genmethod4.test
index bc6e2c1..9a4c6f8 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/genmethod4.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/genmethod4.test
@@ -22,9 +22,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/genmethod5.test b/plugins/groovy/testdata/parsing/groovy/generics/genmethod5.test
index 3b08b5c..6f43c2e 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/genmethod5.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/genmethod5.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -40,9 +40,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/typeargs1.test b/plugins/groovy/testdata/parsing/groovy/generics/typeargs1.test
index 83bf489..58e8901 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/typeargs1.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/typeargs1.test
@@ -25,11 +25,11 @@
PsiElement(identifier)('S')
PsiElement(>)('>')
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/typeparam1.test b/plugins/groovy/testdata/parsing/groovy/generics/typeparam1.test
index 2d31e1e..0b8013c 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/typeparam1.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/typeparam1.test
@@ -15,11 +15,11 @@
Type extends bounds list
<empty list>
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/typeparam2.test b/plugins/groovy/testdata/parsing/groovy/generics/typeparam2.test
index 7da8c21..771cfb8 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/typeparam2.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/typeparam2.test
@@ -23,11 +23,11 @@
Reference element
PsiElement(identifier)('U')
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/generics/typeparam3.test b/plugins/groovy/testdata/parsing/groovy/generics/typeparam3.test
index 75dbf33..91c1578 100644
--- a/plugins/groovy/testdata/parsing/groovy/generics/typeparam3.test
+++ b/plugins/groovy/testdata/parsing/groovy/generics/typeparam3.test
@@ -48,11 +48,11 @@
PsiErrorElement:Type expected
<empty list>
PsiElement(>)('>')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test b/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test
index bd24b1f..179df1e 100644
--- a/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test
+++ b/plugins/groovy/testdata/parsing/groovy/packaging/pack3.test
@@ -7,16 +7,14 @@
Modifiers
<empty list>
PsiElement(package)('package')
- PsiErrorElement:Identifier expected
- <empty list>
- PsiWhiteSpace(' ')
- Reference expression
- Reference expression
- Reference expression
- PsiElement(identifier)('a')
+ PsiWhiteSpace(' ')
+ Reference element
+ Reference element
+ Reference element
+ PsiElement(identifier)('a')
+ PsiElement(.)('.')
+ PsiElement(new line)('\n')
+ PsiElement(identifier)('b')
PsiElement(.)('.')
PsiElement(new line)('\n')
- PsiElement(identifier)('b')
- PsiElement(.)('.')
- PsiElement(new line)('\n')
- PsiElement(identifier)('c')
\ No newline at end of file
+ PsiElement(identifier)('c')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/branch/ret1.test b/plugins/groovy/testdata/parsing/groovy/statements/branch/ret1.test
index 6cd59bd..82f5112 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/branch/ret1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/branch/ret1.test
@@ -12,11 +12,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('MyMath')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/class_init1.test b/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/class_init1.test
index 801c54e..f81d7a7 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/class_init1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/class_init1.test
@@ -14,11 +14,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/stat_block.test b/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/stat_block.test
index f49c328..ff07ff1 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/stat_block.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/class_initializers/stat_block.test
@@ -15,11 +15,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/GRVY-1451.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/GRVY-1451.test
index ff33007..86430f4 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/declaration/GRVY-1451.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/GRVY-1451.test
@@ -7,11 +7,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('BacklogItem')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace(' ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/decl11.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/decl11.test
index 84f7138..08db040 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/declaration/decl11.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/decl11.test
@@ -30,11 +30,9 @@
PsiElement(identifier)('gory')
PsiErrorElement:')' expected
<empty list>
- PsiWhiteSpace(' ')
Throw clause
<empty list>
- PsiErrorElement:';' or new line expected
- <empty list>
+ PsiWhiteSpace(' ')
Reference expression
PsiElement(identifier)('other')
PsiErrorElement:';' or new line expected
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/declaration/nl_trows.test b/plugins/groovy/testdata/parsing/groovy/statements/declaration/nl_trows.test
index b7d3cac..591de4e 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/declaration/nl_trows.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/declaration/nl_trows.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('Foos')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n\t')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/ifRecovery.test b/plugins/groovy/testdata/parsing/groovy/statements/ifRecovery.test
index 4214ae1..fe03750 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/ifRecovery.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/ifRecovery.test
@@ -12,9 +12,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/imports/imp8.test b/plugins/groovy/testdata/parsing/groovy/statements/imports/imp8.test
new file mode 100644
index 0000000..f20b09b
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/statements/imports/imp8.test
@@ -0,0 +1,56 @@
+import a.;
+import a.b.;
+import;
+import a.b.c
+-----
+Groovy script
+ Import statement
+ Modifiers
+ <empty list>
+ PsiElement(import)('import')
+ PsiWhiteSpace(' ')
+ Reference element
+ Reference element
+ PsiElement(identifier)('a')
+ PsiElement(.)('.')
+ PsiErrorElement:Identifier expected
+ <empty list>
+ PsiElement(;)(';')
+ PsiElement(new line)('\n')
+ Import statement
+ Modifiers
+ <empty list>
+ PsiElement(import)('import')
+ PsiWhiteSpace(' ')
+ Reference element
+ Reference element
+ Reference element
+ PsiElement(identifier)('a')
+ PsiElement(.)('.')
+ PsiElement(identifier)('b')
+ PsiElement(.)('.')
+ PsiErrorElement:Identifier expected
+ <empty list>
+ PsiElement(;)(';')
+ PsiElement(new line)('\n')
+ Import statement
+ Modifiers
+ <empty list>
+ PsiElement(import)('import')
+ PsiErrorElement:package or class name expected
+ <empty list>
+ PsiElement(;)(';')
+ PsiElement(new line)('\n')
+ Import statement
+ Modifiers
+ <empty list>
+ PsiElement(import)('import')
+ PsiWhiteSpace(' ')
+ Reference element
+ Reference element
+ Reference element
+ PsiElement(identifier)('a')
+ PsiElement(.)('.')
+ PsiElement(identifier)('b')
+ PsiElement(.)('.')
+ PsiElement(identifier)('c')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/methods/method3.test b/plugins/groovy/testdata/parsing/groovy/statements/methods/method3.test
index 4dd51bd..959149e 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/methods/method3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/methods/method3.test
@@ -14,9 +14,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/methods/method4.test b/plugins/groovy/testdata/parsing/groovy/statements/methods/method4.test
index 49d0241..67945eb 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/methods/method4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/methods/method4.test
@@ -31,9 +31,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -44,11 +44,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/multiple_assign/without_assign.test b/plugins/groovy/testdata/parsing/groovy/statements/multiple_assign/without_assign.test
new file mode 100644
index 0000000..4402e22
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/statements/multiple_assign/without_assign.test
@@ -0,0 +1,47 @@
+def a = 5
+def b = 5
+print ((a, b))
+-----
+Groovy script
+ Variable definitions
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ Variable
+ PsiElement(identifier)('a')
+ PsiWhiteSpace(' ')
+ PsiElement(=)('=')
+ PsiWhiteSpace(' ')
+ Literal
+ PsiElement(Integer)('5')
+ PsiElement(new line)('\n')
+ Variable definitions
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ Variable
+ PsiElement(identifier)('b')
+ PsiWhiteSpace(' ')
+ PsiElement(=)('=')
+ PsiWhiteSpace(' ')
+ Literal
+ PsiElement(Integer)('5')
+ PsiElement(new line)('\n')
+ Method call
+ Reference expression
+ PsiElement(identifier)('print')
+ PsiWhiteSpace(' ')
+ Arguments
+ PsiElement(()('(')
+ Tuple Assignment Expression
+ PsiElement(()('(')
+ Reference expression
+ PsiElement(identifier)('a')
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Reference expression
+ PsiElement(identifier)('b')
+ PsiElement())(')')
+ PsiErrorElement:'=' expected
+ <empty list>
+ PsiElement())(')')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/semicolonsOnDifferentLines.test b/plugins/groovy/testdata/parsing/groovy/statements/semicolonsOnDifferentLines.test
index 69e04e6..c33ffe2 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/semicolonsOnDifferentLines.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/semicolonsOnDifferentLines.test
@@ -15,9 +15,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method3.test b/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method3.test
index 4dd51bd..959149e 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method3.test
@@ -14,9 +14,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method4.test b/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method4.test
index 49d0241..67945eb 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/top_methods/method4.test
@@ -31,9 +31,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -44,11 +44,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/try_catch/try5.test b/plugins/groovy/testdata/parsing/groovy/statements/try_catch/try5.test
index be148f4..cf90904 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/try_catch/try5.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/try_catch/try5.test
@@ -16,9 +16,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/tuples/nestedTupleUnsupp.test b/plugins/groovy/testdata/parsing/groovy/statements/tuples/nestedTupleUnsupp.test
index cc3ac6d..a304e07 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/tuples/nestedTupleUnsupp.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/tuples/nestedTupleUnsupp.test
@@ -16,7 +16,7 @@
Reference expression
PsiElement(identifier)('b')
PsiElement())(')')
- PsiErrorElement:')' expected
+ PsiErrorElement:'=' expected
<empty list>
PsiErrorElement:Unexpected symbol
PsiElement(,)(',')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/tuples/tupleInClass.test b/plugins/groovy/testdata/parsing/groovy/statements/tuples/tupleInClass.test
index f3918a9..236ffde 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/tuples/tupleInClass.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/tuples/tupleInClass.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/abstr.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/abstr.test
index 9add238..52f0f94 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/abstr.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/abstr.test
@@ -8,11 +8,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('C')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class1.test
index e8c7394..5dce63e 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class1.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -24,9 +24,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class2.test
index 004be1e..e07e639 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class2.test
@@ -7,11 +7,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class3.test
index 2673c07..695866e 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class3.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -27,9 +27,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class4.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class4.test
index 0cf7fc1..169a31a 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class4.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -41,9 +41,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class5.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class5.test
index ffcbfcd..63188eb 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class5.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class5.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -40,9 +40,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -52,9 +52,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class6.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class6.test
index 10cd522..86f034b 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class6.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class6.test
@@ -14,9 +14,9 @@
PsiWhiteSpace(' ')
Reference element
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class7.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class7.test
index 8742568..53b54b8 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class7.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/class7.test
@@ -8,9 +8,9 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Implements clause
PsiElement(implements)('implements')
PsiWhiteSpace(' ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr1.test
index 21da981..ccc6e03 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr1.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr2.test
index 95f6273..9fc4b4d 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr2.test
@@ -14,11 +14,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('d')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -72,9 +72,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Property')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(def)('def')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
@@ -83,9 +83,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr3.test
index b3c8931..56e42d8 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/classes/errors/classerr3.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/construct12.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/construct12.test
index ca80a43..a9ed2a9 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/construct12.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/construct12.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('Greet')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -28,9 +28,9 @@
<empty list>
PsiElement(identifier)('who')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace(' ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor1.test
index 71dbd1b..1725b16 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor1.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -29,9 +29,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor11.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor11.test
index 69d5f59..981c353 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor11.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor11.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('map')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -27,9 +27,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor13.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor13.test
index a7f629f..0d0f94a 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor13.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor13.test
@@ -10,11 +10,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -49,9 +49,9 @@
<empty list>
PsiElement(identifier)('p')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace(' ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor14.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor14.test
index 977db0d..9a953b9 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor14.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor14.test
@@ -17,11 +17,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('ComparableFoo')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -49,9 +49,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('theValue')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -81,9 +81,9 @@
<empty list>
PsiElement(identifier)('anotherFoo')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor15.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor15.test
index 028ebfa..7f9b5b4 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor15.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor15.test
@@ -10,11 +10,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('LogPipeBuilder')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor2.test
index 9cffe8e..e733643 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor2.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('w')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -31,9 +31,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor3.test
index 833dd7e..eab2d95 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor3.test
@@ -11,9 +11,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -27,9 +27,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor4.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor4.test
index 4e0b6c2..7163673 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor4.test
@@ -10,11 +10,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -44,9 +44,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('B')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
@@ -61,9 +61,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
Method call
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor5.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor5.test
index 9576bb3..26be7fa 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor5.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor5.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -36,9 +36,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor6.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor6.test
index c3a9c0d..af748b4 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor6.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor6.test
@@ -12,11 +12,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -30,9 +30,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor7.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor7.test
index f0d9c26..890437f 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor7.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor7.test
@@ -35,9 +35,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor8.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor8.test
index c984b68..b26eeab 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor8.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor8.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor9.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor9.test
index 488c59c..edd3d1a 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor9.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/constructors/constructor9.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum1.test
index a02dd73..af05977 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum1.test
@@ -9,9 +9,9 @@
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum3.test
index 2d23952..13ed41c 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum3.test
@@ -42,16 +42,16 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('NotNull')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
Annotation
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Property')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(identifier)('item1')
PsiWhiteSpace(' ')
Arguments
@@ -75,11 +75,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
@@ -135,9 +135,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum4.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum4.test
index 13cf12a..dde30e3 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum4.test
@@ -33,9 +33,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Nullable')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(identifier)('foo')
PsiWhiteSpace(' ')
Arguments
@@ -74,9 +74,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Nullable')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(identifier)('bar')
PsiWhiteSpace(' ')
Arguments
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test
index ae66289..1f2d2e8 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum5.test
@@ -11,9 +11,9 @@
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test
index 9f031af..2ed2a21 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum6.test
@@ -9,9 +9,9 @@
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(identifier)('B')
- PsiWhiteSpace(' ')
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum7.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum7.test
index 6d2db33..af31a42 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum7.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/enums/enum7.test
@@ -9,9 +9,9 @@
PsiElement(enum)('enum')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -22,9 +22,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Property')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(identifier)('a')
PsiElement(new line)('\n')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr1.test
index fb84a2e..21d7f1c 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr1.test
@@ -13,9 +13,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('q')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -29,9 +29,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace(' ')
@@ -47,9 +47,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr2.test
index 98ef391..c1387ce 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr2.test
@@ -11,9 +11,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr3.test
index 7422d06..d4c1bf7 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/errors/interfaceerr3.test
@@ -11,9 +11,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface1.test
index 1ca010d..dd0568a 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface1.test
@@ -7,9 +7,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface2.test
index 4c7d332..860d520 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface2.test
@@ -8,9 +8,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface3.test
index ed1baf7..75c29ad 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface3.test
@@ -9,9 +9,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -22,9 +22,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface4.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface4.test
index 3a7fcdc..03b91bf 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface4.test
@@ -9,9 +9,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -22,9 +22,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('d')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface5.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface5.test
index ab946b6..2a6fdaa 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface5.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/interface5.test
@@ -10,9 +10,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/member3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/member3.test
index 5571293..0712061 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/member3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/member3.test
@@ -10,9 +10,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member1.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member1.test
index b9862c7..feb71f0 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member1.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member1.test
@@ -9,9 +9,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -25,9 +25,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member2.test
index f19dbaf..6760b82 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member2.test
@@ -9,9 +9,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member3.test
index 7c6111e..89f9e7e 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member3.test
@@ -10,9 +10,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member4.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member4.test
index 923ed09..54f4e75 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member4.test
@@ -13,9 +13,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -57,9 +57,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('s')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n\n ')
@@ -71,11 +71,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('B')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member5.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member5.test
index 741f16a..baeac2b 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member5.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member5.test
@@ -10,9 +10,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -23,9 +23,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member6.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member6.test
index 0122399..323c0a3 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member6.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/member6.test
@@ -9,9 +9,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/memeber7.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/memeber7.test
index 7cb721c..26caf6b 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/memeber7.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/interfaces/members/memeber7.test
@@ -12,9 +12,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -58,9 +58,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method2.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method2.test
index c8b1836..e1098b7 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method2.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method2.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -29,9 +29,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method3.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method3.test
index b73c64c..55b423d 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method3.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method3.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -40,9 +40,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('y')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -53,9 +53,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('d')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method4.test b/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method4.test
index 83b0d01..4b023ab 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method4.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/typedef/methods/method4.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/statements/unnamedField.test b/plugins/groovy/testdata/parsing/groovy/statements/unnamedField.test
index e50e140..4ce246a 100644
--- a/plugins/groovy/testdata/parsing/groovy/statements/unnamedField.test
+++ b/plugins/groovy/testdata/parsing/groovy/statements/unnamedField.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('Steps')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/ann_def1.test b/plugins/groovy/testdata/parsing/groovy/types/ann_def1.test
index 3c87ee3..932deee 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/ann_def1.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/ann_def1.test
@@ -24,11 +24,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('foo')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/ann_def2.test b/plugins/groovy/testdata/parsing/groovy/types/ann_def2.test
index 5a8b687..ff2f4de 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/ann_def2.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/ann_def2.test
@@ -23,11 +23,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('foo')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/default1.test b/plugins/groovy/testdata/parsing/groovy/types/default1.test
index 275ba92..94cc6ec 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/default1.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/default1.test
@@ -22,9 +22,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('ann')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
Built in type
PsiElement(int)('int')
PsiWhiteSpace(' ')
@@ -41,10 +41,10 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('Bar')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
PsiElement(new line)('\n')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/default2.test b/plugins/groovy/testdata/parsing/groovy/types/default2.test
index abfc413..05a31b6 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/default2.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/default2.test
@@ -22,9 +22,9 @@
PsiElement(@)('@')
Reference element
PsiElement(identifier)('ann')
- PsiWhiteSpace(' ')
Annotation arguments
<empty list>
+ PsiWhiteSpace(' ')
Built in type
PsiElement(int)('int')
PsiWhiteSpace(' ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/incorrectParam1.test b/plugins/groovy/testdata/parsing/groovy/types/incorrectParam1.test
new file mode 100644
index 0000000..b3f0b8a
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/types/incorrectParam1.test
@@ -0,0 +1,28 @@
+def foo(A. B) {}
+-----
+Groovy script
+ Method
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('foo')
+ PsiElement(()('(')
+ Parameter list
+ Modifiers
+ <empty list>
+ Type element
+ Reference element
+ Reference element
+ PsiElement(identifier)('A')
+ PsiElement(.)('.')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('B')
+ PsiErrorElement:Identifier expected
+ <empty list>
+ PsiElement())(')')
+ Throw clause
+ <empty list>
+ PsiWhiteSpace(' ')
+ Open block
+ PsiElement({)('{')
+ PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/incorrectParam3.test b/plugins/groovy/testdata/parsing/groovy/types/incorrectParam3.test
new file mode 100644
index 0000000..ccfc130
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/types/incorrectParam3.test
@@ -0,0 +1,38 @@
+def foo(A. b, A c) {}
+-----
+Groovy script
+ Method
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('foo')
+ PsiElement(()('(')
+ Parameter list
+ Modifiers
+ <empty list>
+ Type element
+ Reference element
+ Reference element
+ PsiElement(identifier)('A')
+ PsiElement(.)('.')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('b')
+ PsiErrorElement:Identifier expected
+ <empty list>
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Parameter
+ Modifiers
+ <empty list>
+ Type element
+ Reference element
+ PsiElement(identifier)('A')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('c')
+ PsiElement())(')')
+ Throw clause
+ <empty list>
+ PsiWhiteSpace(' ')
+ Open block
+ PsiElement({)('{')
+ PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/incorrectParameter2.test b/plugins/groovy/testdata/parsing/groovy/types/incorrectParameter2.test
new file mode 100644
index 0000000..19f23eb
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/types/incorrectParameter2.test
@@ -0,0 +1,38 @@
+def foo(A a, A. b) {}
+-----
+Groovy script
+ Method
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('foo')
+ PsiElement(()('(')
+ Parameter list
+ Parameter
+ Modifiers
+ <empty list>
+ Type element
+ Reference element
+ PsiElement(identifier)('A')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('a')
+ PsiElement(,)(',')
+ PsiWhiteSpace(' ')
+ Modifiers
+ <empty list>
+ Type element
+ Reference element
+ Reference element
+ PsiElement(identifier)('A')
+ PsiElement(.)('.')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('b')
+ PsiErrorElement:Identifier expected
+ <empty list>
+ PsiElement())(')')
+ Throw clause
+ <empty list>
+ PsiWhiteSpace(' ')
+ Open block
+ PsiElement({)('{')
+ PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/interfaceWithGroovyDoc.test b/plugins/groovy/testdata/parsing/groovy/types/interfaceWithGroovyDoc.test
index 5f78881..4d0bb50 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/interfaceWithGroovyDoc.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/interfaceWithGroovyDoc.test
@@ -12,9 +12,9 @@
PsiElement(interface)('interface')
PsiWhiteSpace(' ')
PsiElement(identifier)('Usage')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/newlineBeforeExtends.test b/plugins/groovy/testdata/parsing/groovy/types/newlineBeforeExtends.test
index 9c9b9ab..93ded07 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/newlineBeforeExtends.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/newlineBeforeExtends.test
@@ -9,11 +9,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('Super')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
@@ -37,9 +37,9 @@
PsiWhiteSpace(' ')
Reference element
PsiElement(identifier)('Super')
- PsiWhiteSpace(' ')
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/staticInitializer.test b/plugins/groovy/testdata/parsing/groovy/types/staticInitializer.test
index a39f75e..cbeb25f 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/staticInitializer.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/staticInitializer.test
@@ -17,11 +17,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('StaticDemo')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type1.test b/plugins/groovy/testdata/parsing/groovy/types/type1.test
index 5d8bcab..38f63bd 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type1.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type1.test
@@ -24,9 +24,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('x')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type10.test b/plugins/groovy/testdata/parsing/groovy/types/type10.test
index 614873b..8c0f7e2 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type10.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type10.test
@@ -51,9 +51,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type11.test b/plugins/groovy/testdata/parsing/groovy/types/type11.test
index 1796e18..e529b66 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type11.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type11.test
@@ -51,9 +51,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -67,9 +67,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type13.test b/plugins/groovy/testdata/parsing/groovy/types/type13.test
index cfd0c2d..d472d34 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type13.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type13.test
@@ -11,11 +11,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('A')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -32,9 +32,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n\n ')
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type14.test b/plugins/groovy/testdata/parsing/groovy/types/type14.test
new file mode 100644
index 0000000..2f2bcba
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/types/type14.test
@@ -0,0 +1,32 @@
+def foo() throws java.
+lang.RuntimeException {
+}
+-----
+Groovy script
+ Method
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('foo')
+ PsiElement(()('(')
+ Parameter list
+ <empty list>
+ PsiElement())(')')
+ PsiWhiteSpace(' ')
+ Throw clause
+ PsiElement(throws)('throws')
+ PsiWhiteSpace(' ')
+ Reference element
+ Reference element
+ Reference element
+ PsiElement(identifier)('java')
+ PsiElement(.)('.')
+ PsiElement(new line)('\n')
+ PsiElement(identifier)('lang')
+ PsiElement(.)('.')
+ PsiElement(identifier)('RuntimeException')
+ PsiWhiteSpace(' ')
+ Open block
+ PsiElement({)('{')
+ PsiWhiteSpace('\n')
+ PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type15.test b/plugins/groovy/testdata/parsing/groovy/types/type15.test
new file mode 100644
index 0000000..387614b
--- /dev/null
+++ b/plugins/groovy/testdata/parsing/groovy/types/type15.test
@@ -0,0 +1,40 @@
+def foo() throws java
+.lang.RuntimeException {
+}
+-----
+Groovy script
+ Method
+ Modifiers
+ PsiElement(def)('def')
+ PsiWhiteSpace(' ')
+ PsiElement(identifier)('foo')
+ PsiElement(()('(')
+ Parameter list
+ <empty list>
+ PsiElement())(')')
+ PsiWhiteSpace(' ')
+ Throw clause
+ PsiElement(throws)('throws')
+ PsiWhiteSpace(' ')
+ Reference element
+ PsiElement(identifier)('java')
+ PsiElement(new line)('\n')
+ PsiErrorElement:Unexpected symbol
+ PsiElement(.)('.')
+ PsiErrorElement:';' or new line expected
+ <empty list>
+ Method call
+ Reference expression
+ Reference expression
+ PsiElement(identifier)('lang')
+ PsiElement(.)('.')
+ PsiElement(identifier)('RuntimeException')
+ PsiWhiteSpace(' ')
+ Arguments
+ <empty list>
+ Closable block
+ PsiElement({)('{')
+ PsiWhiteSpace('\n')
+ Parameter list
+ <empty list>
+ PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type5.test b/plugins/groovy/testdata/parsing/groovy/types/type5.test
index 4ba5da4..bb5938e 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type5.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type5.test
@@ -32,9 +32,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('f')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type6.test b/plugins/groovy/testdata/parsing/groovy/types/type6.test
index a143aed..5abf351 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type6.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type6.test
@@ -37,9 +37,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('f')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type7.test b/plugins/groovy/testdata/parsing/groovy/types/type7.test
index 5baedd2..39ac712 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type7.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type7.test
@@ -40,9 +40,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('f')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type8.test b/plugins/groovy/testdata/parsing/groovy/types/type8.test
index 4d3dd04..75fc7cb 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type8.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type8.test
@@ -31,9 +31,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('b')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/parsing/groovy/types/type9.test b/plugins/groovy/testdata/parsing/groovy/types/type9.test
index 800e749..b070bca 100644
--- a/plugins/groovy/testdata/parsing/groovy/types/type9.test
+++ b/plugins/groovy/testdata/parsing/groovy/types/type9.test
@@ -26,9 +26,9 @@
PsiWhiteSpace(' ')
PsiElement(identifier)('args')
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiElement(})('}')
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/closure.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/closure.java
index 79aa62b..769c8bd 100644
--- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/closure.java
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/closure.java
@@ -1,5 +1,5 @@
java.util.ArrayList<java.lang.Integer> list = new java.util.ArrayList<java.lang.Integer>(java.util.Arrays.asList(1, 2, 3));
-org.codehaus.groovy.runtime.DefaultGroovyMethods.each(list, new groovy.lang.Closure<java.lang.Void>(this, this) {
+org.codehaus.groovy.runtime.DefaultGroovyMethods.each(list, new groovy.lang.Closure<java.lang.Object>(this, this) {
public void doCall(java.lang.Integer it) {
print(it);
}
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/propSelection.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/propSelection.groovy
new file mode 100644
index 0000000..0073667
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/propSelection.groovy
@@ -0,0 +1 @@
+print p."a$c"
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/propSelection.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/propSelection.java
new file mode 100644
index 0000000..0347871
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/propSelection.java
@@ -0,0 +1 @@
+print(this.getBinding().getProperty("p")."a$c");
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/switch.groovy b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/switch.groovy
new file mode 100644
index 0000000..c5e703c
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/switch.groovy
@@ -0,0 +1,13 @@
+String[] commands = ['abc']
+for (String command : commands) {
+ switch (command) {
+ case "abc":
+ print 1
+ case "start":
+ return 4
+ case "next":
+ continue;
+ default:
+ return 0;
+ }
+}
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/switch.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/switch.java
new file mode 100644
index 0000000..dafdae9
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/codeBlock/switch.java
@@ -0,0 +1,17 @@
+java.lang.String[] commands = new java.lang.String[]{"abc"};
+for(java.lang.String command : commands){
+if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase("abc", command)) {
+print(1);
+return 4;
+}
+else if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase("start", command)) {
+return 4;
+}
+else if (org.codehaus.groovy.runtime.DefaultGroovyMethods.isCase("next", command)) {
+continue;
+}
+else {
+return 0;
+}
+}
+
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/closureInUse.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/closureInUse.java
index 93ca27e..4812e82 100644
--- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/closureInUse.java
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/closureInUse.java
@@ -12,7 +12,7 @@
public java.lang.Object run() {
-return org.codehaus.groovy.runtime.DefaultGroovyMethods.use(this, IntCat.class, new groovy.lang.Closure<java.lang.Void>(this, this) {
+return org.codehaus.groovy.runtime.DefaultGroovyMethods.use(this, IntCat.class, new groovy.lang.Closure<java.lang.Object>(this, this) {
public void doCall(java.lang.Object it) {
IntCat.call(2);
IntCat.call(2, "a");
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java
index 5b94cbc..92d6fb7 100644
--- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/hash.java
@@ -42,7 +42,7 @@
long start = java.lang.System.currentTimeMillis();
-org.codehaus.groovy.runtime.DefaultGroovyMethods.eachByte(f, MB, new groovy.lang.Closure<java.lang.Void>(this, this) {
+org.codehaus.groovy.runtime.DefaultGroovyMethods.eachByte(f, MB, new groovy.lang.Closure<java.lang.Object>(this, this) {
public void doCall(java.lang.Byte[] buf, int bytesRead) {
messageDigest.update(buf, 0, bytesRead);
}
diff --git a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/refInClosureInScript.java b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/refInClosureInScript.java
index 0c17a66..3956fee 100644
--- a/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/refInClosureInScript.java
+++ b/plugins/groovy/testdata/refactoring/convertGroovyToJava/file/refInClosureInScript.java
@@ -6,7 +6,7 @@
public java.lang.Object run() {
final groovy.lang.Reference<java.lang.Integer> foo = new groovy.lang.Reference<java.lang.Integer>(2);
-org.codehaus.groovy.runtime.DefaultGroovyMethods.times(3, new groovy.lang.Closure<java.lang.Void>(this, this) {
+org.codehaus.groovy.runtime.DefaultGroovyMethods.times(3, new groovy.lang.Closure<java.lang.Object>(this, this) {
public void doCall(java.lang.Integer it) {
foo.set(foo.get()++);
foo.set(foo.get() + 2);
diff --git a/plugins/groovy/testdata/refactoring/introduceConstant/FieldWithClassName.groovy b/plugins/groovy/testdata/refactoring/introduceConstant/FieldWithClassName.groovy
new file mode 100644
index 0000000..bbb493f
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/introduceConstant/FieldWithClassName.groovy
@@ -0,0 +1,5 @@
+class CONST {
+ def foo() {
+ print <selection>2</selection>
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/introduceConstant/FieldWithClassName_after.groovy b/plugins/groovy/testdata/refactoring/introduceConstant/FieldWithClassName_after.groovy
new file mode 100644
index 0000000..d9c0210
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/introduceConstant/FieldWithClassName_after.groovy
@@ -0,0 +1,7 @@
+class CONST {
+ public static final int CONST = 2
+
+ def foo() {
+ print CONST
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/introduceConstant/LocalVarRef.groovy b/plugins/groovy/testdata/refactoring/introduceConstant/LocalVarRef.groovy
new file mode 100644
index 0000000..f024417
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/introduceConstant/LocalVarRef.groovy
@@ -0,0 +1,11 @@
+class X {
+ def foo() {
+ def ad = 6
+
+ print <selection>ad</selection>
+ print ad
+ print "abc"
+
+ print 5
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/introduceConstant/LocalVarRef_after.groovy b/plugins/groovy/testdata/refactoring/introduceConstant/LocalVarRef_after.groovy
new file mode 100644
index 0000000..02032b3
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/introduceConstant/LocalVarRef_after.groovy
@@ -0,0 +1,12 @@
+class X {
+ public static final int CONST = 6
+
+ def foo() {
+
+ print CONST
+ print CONST
+ print "abc"
+
+ print 5
+ }
+}
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/move/moveClass/staticImport/after/p2/C1.groovy b/plugins/groovy/testdata/refactoring/move/moveClass/staticImport/after/p2/C1.groovy
index 6edb229..c07883e 100644
--- a/plugins/groovy/testdata/refactoring/move/moveClass/staticImport/after/p2/C1.groovy
+++ b/plugins/groovy/testdata/refactoring/move/moveClass/staticImport/after/p2/C1.groovy
@@ -1,6 +1,6 @@
package p2
-import static C1.E.e
+import static p2.C1.E.e
class C1 {
def foo() {
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/dollarSlashyWithDollar.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/dollarSlashyWithDollar.groovy
new file mode 100644
index 0000000..b8cc532
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/dollarSlashyWithDollar.groovy
@@ -0,0 +1 @@
+$/abc$<selection> </selection>cde/$
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/dollarSlashyWithDollar_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/dollarSlashyWithDollar_after.groovy
new file mode 100644
index 0000000..cd02c98
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/dollarSlashyWithDollar_after.groovy
@@ -0,0 +1 @@
+"abc\$" + $/ /$ + $/cde/$
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlash.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlash.groovy
new file mode 100644
index 0000000..3ede018
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlash.groovy
@@ -0,0 +1 @@
+/ab\<selection>c</selection>/
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlashInsideExtractedPart.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlashInsideExtractedPart.groovy
new file mode 100644
index 0000000..3063235
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlashInsideExtractedPart.groovy
@@ -0,0 +1 @@
+/a<selection>b\</selection>cd/
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlashInsideExtractedPart_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlashInsideExtractedPart_after.groovy
new file mode 100644
index 0000000..c07f6f4
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlashInsideExtractedPart_after.groovy
@@ -0,0 +1 @@
+/a/ + "b\\" + /cd/
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlash_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlash_after.groovy
new file mode 100644
index 0000000..6466fb1
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/slashyWithSlash_after.groovy
@@ -0,0 +1 @@
+"ab\\" + /c/
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDollarSlashyString.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDollarSlashyString.groovy
new file mode 100644
index 0000000..c223f7e
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDollarSlashyString.groovy
@@ -0,0 +1 @@
+($/a<selection>b</selection>c/$)
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDollarSlashyString_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDollarSlashyString_after.groovy
new file mode 100644
index 0000000..190c4e5
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDollarSlashyString_after.groovy
@@ -0,0 +1 @@
+($/a/$ + $/b/$ + $/c/$)
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDoubleQuotes.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDoubleQuotes.groovy
new file mode 100644
index 0000000..b6f2ecf
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDoubleQuotes.groovy
@@ -0,0 +1 @@
+"a<selection>b</selection>c"
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDoubleQuotes_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDoubleQuotes_after.groovy
new file mode 100644
index 0000000..3cbc0c6
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromDoubleQuotes_after.groovy
@@ -0,0 +1 @@
+"a" + "b" + "c"
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromQuote.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromQuote.groovy
new file mode 100644
index 0000000..47f8c77
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromQuote.groovy
@@ -0,0 +1 @@
+'a<selection>b</selection>c'
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromQuote_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromQuote_after.groovy
new file mode 100644
index 0000000..db53737
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromQuote_after.groovy
@@ -0,0 +1 @@
+'a' + 'b' + 'c'
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromSlashyString.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromSlashyString.groovy
new file mode 100644
index 0000000..554cd15
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromSlashyString.groovy
@@ -0,0 +1 @@
+(/a<selection>b</selection>c/)
\ No newline at end of file
diff --git a/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromSlashyString_after.groovy b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromSlashyString_after.groovy
new file mode 100644
index 0000000..6da090b
--- /dev/null
+++ b/plugins/groovy/testdata/refactoring/stringExtracting/stringExtractingFromSlashyString_after.groovy
@@ -0,0 +1 @@
+(/a/ + /b/ + /c/)
\ No newline at end of file
diff --git a/plugins/groovy/testdata/reparse/MultilineToNormalString.txt b/plugins/groovy/testdata/reparse/MultilineToNormalString.txt
index 5f0d6d9..cacf4d0 100644
--- a/plugins/groovy/testdata/reparse/MultilineToNormalString.txt
+++ b/plugins/groovy/testdata/reparse/MultilineToNormalString.txt
@@ -6,11 +6,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -23,9 +23,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -62,9 +62,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -88,11 +88,11 @@
PsiElement(class)('class')
PsiWhiteSpace(' ')
PsiElement(identifier)('a')
- PsiWhiteSpace(' ')
Extends clause
<empty list>
Implements clause
<empty list>
+ PsiWhiteSpace(' ')
Type definition body
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -105,9 +105,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -131,9 +131,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/NoVariableName.txt b/plugins/groovy/testdata/reparse/NoVariableName.txt
index bb56d59..6f25d60 100644
--- a/plugins/groovy/testdata/reparse/NoVariableName.txt
+++ b/plugins/groovy/testdata/reparse/NoVariableName.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -87,9 +87,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/OpeningParenthesisAtBlockStart.txt b/plugins/groovy/testdata/reparse/OpeningParenthesisAtBlockStart.txt
index 43602fd..74b0541 100644
--- a/plugins/groovy/testdata/reparse/OpeningParenthesisAtBlockStart.txt
+++ b/plugins/groovy/testdata/reparse/OpeningParenthesisAtBlockStart.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -65,9 +65,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseDef.txt b/plugins/groovy/testdata/reparse/SwitchCaseDef.txt
index 41bf992..5271429 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseDef.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseDef.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -54,9 +54,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseDo.txt b/plugins/groovy/testdata/reparse/SwitchCaseDo.txt
index 04a40ba..8da1cbb 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseDo.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseDo.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -54,9 +54,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseDot.txt b/plugins/groovy/testdata/reparse/SwitchCaseDot.txt
index aff0d03..3234681 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseDot.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseDot.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -80,9 +80,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseFor.txt b/plugins/groovy/testdata/reparse/SwitchCaseFor.txt
index ad25f48..8bdf684 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseFor.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseFor.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -54,9 +54,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseIf.txt b/plugins/groovy/testdata/reparse/SwitchCaseIf.txt
index 7bcdcd5..51a023e 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseIf.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseIf.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -54,9 +54,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseSwitch.txt b/plugins/groovy/testdata/reparse/SwitchCaseSwitch.txt
index ee9d4f2..2f55349 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseSwitch.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseSwitch.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -54,9 +54,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchCaseWhile.txt b/plugins/groovy/testdata/reparse/SwitchCaseWhile.txt
index 3d5863f..dadec26 100644
--- a/plugins/groovy/testdata/reparse/SwitchCaseWhile.txt
+++ b/plugins/groovy/testdata/reparse/SwitchCaseWhile.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -54,9 +54,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SwitchRParen.txt b/plugins/groovy/testdata/reparse/SwitchRParen.txt
index 7401dde..732ccb2 100644
--- a/plugins/groovy/testdata/reparse/SwitchRParen.txt
+++ b/plugins/groovy/testdata/reparse/SwitchRParen.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -79,9 +79,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/SynchronizedRParen.txt b/plugins/groovy/testdata/reparse/SynchronizedRParen.txt
index 80a5095..200ce23 100644
--- a/plugins/groovy/testdata/reparse/SynchronizedRParen.txt
+++ b/plugins/groovy/testdata/reparse/SynchronizedRParen.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -65,9 +65,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/groovy/testdata/reparse/WhileRParen.txt b/plugins/groovy/testdata/reparse/WhileRParen.txt
index 5df4d40..04c21f5 100644
--- a/plugins/groovy/testdata/reparse/WhileRParen.txt
+++ b/plugins/groovy/testdata/reparse/WhileRParen.txt
@@ -9,9 +9,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
@@ -65,9 +65,9 @@
Parameter list
<empty list>
PsiElement())(')')
- PsiWhiteSpace(' ')
Throw clause
<empty list>
+ PsiWhiteSpace(' ')
Open block
PsiElement({)('{')
PsiWhiteSpace('\n ')
diff --git a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
index 1283e65..1531965 100644
--- a/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
+++ b/plugins/hg4idea/resources/org/zmlx/hg4idea/HgVcsMessages.properties
@@ -3,7 +3,7 @@
action.hg4idea.tag.text=Tag Repository...
action.hg4idea.tag.description=Create a tag for current revision
action.hg4idea.updateTo.text=Update to...
-action.hg4idea.updateTo.description=Updating to {0}...
+action.hg4idea.updateTo.description=Update the repository's working directory to the specified changeset.
action.hg4idea.push.text=Push...
action.hg4idea.push.description=Push outgoing commits
action.hg4idea.pull.text=Pull...
@@ -49,7 +49,11 @@
hg4idea.configuration.executable.title=Mercurial executable
hg4idea.configuration.description=Specify the full path to hg executable
hg4idea.configuration.executable.error=\"{0}\" doesn''t appear to be a valid hg executable
+hg4idea.configuration.test.label=Test
+hg4idea.configuration.test=&Test
hg4idea.unable.to.run.hg=Unable to run hg: {0}
+hg4idea.run.success.title=Hg Executed Successfully
+hg4idea.run.failed.title=Hg Execution Failed
hg4idea.command.executable.error=Error executing \"{0}\". Make sure you have setup the right executable in Mercurial configuration
@@ -102,13 +106,12 @@
hg4idea.progress.integrating=Integrating {0} ...
hg4idea.progress.merging=Performing merge...
hg4idea.progress.updating=Updating {0} ...
+hg4idea.progress.updatingTo=Updating to {0}...
hg4idea.progress.countingHeads=Checking number of heads...
hg4idea.progress.pull.with.rebase=Rebasing patches
hg4idea.progress.pull.with.update=Updating repository
hg4idea.error.invalidTarget=Invalid integration target
-hg4idea.status.currentSituationText={0} ({1})
-hg4idea.status.currentSituation.description=Branch: {0} Parent: {1}
hg4idea.progress.checking.ignored=Checking for ignoring files
hg4idea.warning.no-default-update-path=Skipped \"{0}\". No default update path.
hg4idea.merge.please-commit=Merged heads, please commit repository \"{0}\"
diff --git a/plugins/hg4idea/src/META-INF/plugin.xml b/plugins/hg4idea/src/META-INF/plugin.xml
index 8eb193b..ba40408 100644
--- a/plugins/hg4idea/src/META-INF/plugin.xml
+++ b/plugins/hg4idea/src/META-INF/plugin.xml
@@ -17,13 +17,12 @@
<applicationService serviceInterface="org.zmlx.hg4idea.HgGlobalSettings"
serviceImplementation="org.zmlx.hg4idea.HgGlobalSettings"/>
+ <applicationService serviceInterface="org.zmlx.hg4idea.HgRememberedInputs"
+ serviceImplementation="org.zmlx.hg4idea.HgRememberedInputs"/>
<projectService serviceInterface="org.zmlx.hg4idea.HgProjectSettings"
serviceImplementation="org.zmlx.hg4idea.HgProjectSettings"/>
<projectService serviceInterface="org.zmlx.hg4idea.HgRootsHandler"
serviceImplementation="org.zmlx.hg4idea.HgRootsHandler" />
- <projectService serviceInterface="org.zmlx.hg4idea.HgRememberedInputs"
- serviceImplementation="org.zmlx.hg4idea.HgRememberedInputs"/>
-
<projectService serviceImplementation="org.zmlx.hg4idea.log.HgContentRevisionFactory"/>
</extensions>
@@ -56,7 +55,9 @@
<separator/>
<action id="hg4idea.pull" class="org.zmlx.hg4idea.action.HgPullAction" />
- <action id="hg4idea.push" class="org.zmlx.hg4idea.action.HgPushAction" />
+ <action id="hg4idea.push" class="org.zmlx.hg4idea.action.HgPushAction">
+ <keyboard-shortcut first-keystroke="control shift K" keymap="$default"/>
+ </action>
<separator/>
<action id="hg4idea.run.conflict.resolver" class="org.zmlx.hg4idea.action.HgRunConflictResolverAction"/>
<action id="hg4idea.merge.files" class="org.zmlx.hg4idea.action.HgMerge" icon="AllIcons.Vcs.MergeSourcesTree"/>
@@ -75,6 +76,20 @@
<add-to-group group-id="VcsGlobalGroup" anchor="after" relative-to-action="Vcs.Specific"/>
</group>
+ <group id="Hg.LogContextMenu">
+ <separator/>
+ </group>
+
+ <action class="org.zmlx.hg4idea.action.HgUpdateToFromLogAction" id="hg4idea.UpdateToRevision" text="Update to Revision"/>
+ <action class="org.zmlx.hg4idea.action.HgCreateTagFromLogAction" id="hg4idea.CreateNewTag" text="New Tag"
+ description="Create new tag pointing to this commit"/>
+
+ <group id="Hg.Log.ContextMenu">
+ <reference id="hg4idea.UpdateToRevision"/>
+ <reference id="hg4idea.CreateNewTag"/>
+ <add-to-group group-id="Vcs.Log.ContextMenu"/>
+ </group>
+
</actions>
<resource-bundle>org.zmlx.hg4idea.HgVcsMessages</resource-bundle>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgNameWithHashInfo.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgNameWithHashInfo.java
index d7e09ba..ccc87f6 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgNameWithHashInfo.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgNameWithHashInfo.java
@@ -38,11 +38,11 @@
}
/**
- * <p>Returns the hash on which this branch or bookmark or tag is reference to.</p>
+ * <p>Returns the hash on which this bookmark or tag is reference to.</p>
*/
@NotNull
- public String getHash() {
- return myHash.asString();
+ public Hash getHash() {
+ return myHash;
}
@NotNull
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRememberedInputs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRememberedInputs.java
index f269403..5ad7c71 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRememberedInputs.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRememberedInputs.java
@@ -15,50 +15,18 @@
*/
package org.zmlx.hg4idea;
+import com.intellij.dvcs.DvcsRememberedInputs;
import com.intellij.openapi.components.*;
-import com.intellij.openapi.project.Project;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.ArrayList;
-import java.util.List;
/**
* @author Nadya Zabrodina
*/
@State(
name = "HgRememberedInputs",
- storages = @Storage(file = StoragePathMacros.WORKSPACE_FILE)
+ storages = @Storage(file = StoragePathMacros.APP_CONFIG + "/vcs.xml")
)
-public class HgRememberedInputs implements PersistentStateComponent<HgRememberedInputs.State> {
- private State myState = new State();
-
- public static class State {
- public List<String> repositoryUrls = new ArrayList<String>();
- }
-
-
- public static HgRememberedInputs getInstance(@NotNull Project project) {
- return ServiceManager.getService(project, HgRememberedInputs.class);
- }
-
- @Override
- public State getState() {
- return myState;
- }
-
- @Override
- public void loadState(State state) {
- myState = state;
- }
-
- public void addRepositoryUrl(@NotNull String url) {
- if (!myState.repositoryUrls.contains(url)) { // don't add multiple entries for a single path
- myState.repositoryUrls.add(url);
- }
- }
-
- @NotNull
- public List<String> getRepositoryUrls() {
- return myState.repositoryUrls;
+public class HgRememberedInputs extends DvcsRememberedInputs implements PersistentStateComponent<DvcsRememberedInputs.State> {
+ public static DvcsRememberedInputs getInstance() {
+ return ServiceManager.getService(HgRememberedInputs.class);
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java
index 8f7431e..0815e47 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRevisionNumber.java
@@ -13,7 +13,9 @@
package org.zmlx.hg4idea;
import com.google.common.base.Objects;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
+import org.jetbrains.annotations.NotNull;
import org.zmlx.hg4idea.util.HgUtil;
import java.util.Collections;
@@ -21,13 +23,13 @@
public class HgRevisionNumber implements VcsRevisionNumber {
- private final String revision;
- private final String changeset;
- private final String commitMessage;
- private final String author;
- private final String email;
- private final List<HgRevisionNumber> parents;
- private final String mySubject;
+ @NotNull private final String revision;
+ @NotNull private final String changeset;
+ @NotNull private final String commitMessage;
+ @NotNull private final String author;
+ @NotNull private final String email;
+ @NotNull private final List<HgRevisionNumber> parents;
+ @NotNull private final String mySubject;
private final boolean isWorkingVersion;
@@ -44,31 +46,31 @@
}
};
- public static HgRevisionNumber getInstance(String revision, String changeset, String author, String commitMessage) {
+ public static HgRevisionNumber getInstance(@NotNull String revision,@NotNull String changeset,@NotNull String author,@NotNull String commitMessage) {
return new HgRevisionNumber(revision, changeset, author, commitMessage, Collections.<HgRevisionNumber>emptyList());
}
- public static HgRevisionNumber getInstance(String revision, String changeset) {
+ public static HgRevisionNumber getInstance(@NotNull String revision,@NotNull String changeset) {
return new HgRevisionNumber(revision, changeset, "", "", Collections.<HgRevisionNumber>emptyList());
}
- public static HgRevisionNumber getInstance(String revision, String changeset, List<HgRevisionNumber> parents) {
+ public static HgRevisionNumber getInstance(@NotNull String revision,@NotNull String changeset,@NotNull List<HgRevisionNumber> parents) {
return new HgRevisionNumber(revision, changeset, "", "", parents);
}
- public static HgRevisionNumber getLocalInstance(String revision) {
+ public static HgRevisionNumber getLocalInstance(@NotNull String revision) {
return new HgRevisionNumber(revision, "", "", "", Collections.<HgRevisionNumber>emptyList());
}
- public HgRevisionNumber(String revision,
- String changeset,
- String authorInfo,
- String commitMessage,
- List<HgRevisionNumber> parents) {
+ public HgRevisionNumber(@NotNull String revision,
+ @NotNull String changeset,
+ @NotNull String authorInfo,
+ @NotNull String commitMessage,
+ @NotNull List<HgRevisionNumber> parents) {
this.commitMessage = commitMessage;
- List<String> authorArgs = HgUtil.parseUserNameAndEmail(authorInfo);
- this.author = authorArgs.get(0);
- this.email = authorArgs.get(1);
+ Pair<String, String> authorArgs = HgUtil.parseUserNameAndEmail(authorInfo);
+ this.author = authorArgs.getFirst();
+ this.email = authorArgs.getSecond();
this.parents = parents;
this.revision = revision.trim();
this.changeset = changeset.trim();
@@ -77,10 +79,12 @@
mySubject = subjectIndex == -1 ? commitMessage : commitMessage.substring(0, subjectIndex);
}
+ @NotNull
public String getChangeset() {
return changeset;
}
+ @NotNull
public String getRevision() {
return revision;
}
@@ -89,10 +93,12 @@
return java.lang.Long.parseLong(revision);
}
+ @NotNull
public String getCommitMessage() {
return commitMessage;
}
+ @NotNull
public String getAuthor() {
return author;
}
@@ -108,6 +114,7 @@
return revision + ":" + changeset;
}
+ @NotNull
public List<HgRevisionNumber> getParents() {
return parents;
}
@@ -178,10 +185,12 @@
return asString();
}
+ @NotNull
public String getSubject() {
return mySubject;
}
+ @NotNull
public String getEmail() {
return email;
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java
index 7594b13..0c6ac2a 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcs.java
@@ -29,7 +29,6 @@
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vcs.*;
import com.intellij.openapi.vcs.annotate.AnnotationProvider;
import com.intellij.openapi.vcs.changes.ChangeProvider;
@@ -41,7 +40,7 @@
import com.intellij.openapi.vcs.rollback.RollbackEnvironment;
import com.intellij.openapi.vcs.update.UpdateEnvironment;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ComparatorDelegate;
import com.intellij.util.containers.Convertor;
@@ -56,7 +55,6 @@
import org.zmlx.hg4idea.provider.commit.HgCommitAndPushExecutor;
import org.zmlx.hg4idea.provider.update.HgUpdateEnvironment;
import org.zmlx.hg4idea.status.HgRemoteStatusUpdater;
-import org.zmlx.hg4idea.status.ui.HgCurrentBranchStatusUpdater;
import org.zmlx.hg4idea.status.ui.HgHideableWidget;
import org.zmlx.hg4idea.status.ui.HgIncomingOutgoingWidget;
import org.zmlx.hg4idea.status.ui.HgStatusWidget;
@@ -78,7 +76,6 @@
private static final Logger LOG = Logger.getInstance(HgVcs.class);
public static final String VCS_NAME = "hg4idea";
- public static final String HG_EXECUTABLE_FILE_NAME = (SystemInfo.isWindows ? "hg.exe" : "hg");
private final static VcsKey ourKey = createKey(VCS_NAME);
private static final int MAX_CONSOLE_OUTPUT_SIZE = 10000;
@@ -106,7 +103,6 @@
private CommitExecutor myCommitAndPushExecutor;
private HgRemoteStatusUpdater myHgRemoteStatusUpdater;
- private HgCurrentBranchStatusUpdater myHgCurrentBranchStatusUpdater;
private HgStatusWidget myStatusWidget;
private HgIncomingOutgoingWidget myIncomingWidget;
private HgIncomingOutgoingWidget myOutgoingWidget;
@@ -228,7 +224,7 @@
final S sParent = in.get(j);
final VirtualFile parent = convertor.convert(sParent);
// if the parent is an ancestor of the child and that they share common root, the child is removed
- if (VfsUtil.isAncestor(parent, child, false) && VfsUtil.isAncestor(childRoot, parent, false)) {
+ if (VfsUtilCore.isAncestor(parent, child, false) && VfsUtilCore.isAncestor(childRoot, parent, false)) {
in.remove(i);
//noinspection AssignmentToForLoopParameter
--i;
@@ -239,7 +235,6 @@
return in;
}
-
@Override
public RootsConvertor getCustomConvertor() {
return HgRootsHandler.getInstance(myProject);
@@ -292,9 +287,6 @@
projectSettings);
myHgRemoteStatusUpdater.activate();
- myHgCurrentBranchStatusUpdater = new HgCurrentBranchStatusUpdater(this, myStatusWidget.getCurrentBranchStatus());
- myHgCurrentBranchStatusUpdater.activate();
-
messageBusConnection = myProject.getMessageBus().connect();
messageBusConnection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, new FileEditorManagerAdapter() {
@Override
@@ -329,23 +321,19 @@
@Override
public void deactivate() {
- if (null != myHgRemoteStatusUpdater) {
+ if (myHgRemoteStatusUpdater != null) {
myHgRemoteStatusUpdater.deactivate();
myHgRemoteStatusUpdater = null;
}
- if (null != myHgCurrentBranchStatusUpdater) {
- myHgCurrentBranchStatusUpdater.deactivate();
- myHgCurrentBranchStatusUpdater = null;
- }
- if (null != myStatusWidget) {
+ if (myStatusWidget != null) {
myStatusWidget.deactivate();
myStatusWidget = null;
}
- if (null != myIncomingWidget) {
+ if (myIncomingWidget != null) {
myIncomingWidget.deactivate();
myIncomingWidget = null;
}
- if (null != myOutgoingWidget) {
+ if (myOutgoingWidget != null) {
myOutgoingWidget.deactivate();
myOutgoingWidget = null;
}
@@ -373,15 +361,6 @@
return (HgVcs)vcsManager.findVcsByName(VCS_NAME);
}
- private static String ourTestHgExecutablePath; // path to hg in test mode
-
- /**
- * Sets the path to hg executable used in the test mode.
- */
- public static void setTestHgExecutablePath(String path) {
- ourTestHgExecutablePath = path;
- }
-
@NotNull
public HgGlobalSettings getGlobalSettings() {
return globalSettings;
@@ -434,7 +413,6 @@
public void checkVersion() {
final String executable = getGlobalSettings().getHgExecutable();
HgCommandResultNotifier errorNotification = new HgCommandResultNotifier(myProject);
- String message;
final String SETTINGS_LINK = "settings";
final String UPDATE_LINK = "update";
NotificationListener linkAdapter = new NotificationListener.Adapter() {
@@ -455,11 +433,17 @@
//if version is not supported, but have valid hg executable
if (!myVersion.isSupported()) {
LOG.info("Unsupported Hg version: " + myVersion);
- message = String.format("The <a href='" + SETTINGS_LINK + "'>configured</a> version of Hg is not supported: %s.<br/> " +
- "The minimal supported version is %s. Please <a href='" + UPDATE_LINK + "'>update</a>.",
- myVersion, HgVersion.MIN);
+ String message = String.format("The <a href='" + SETTINGS_LINK + "'>configured</a> version of Hg is not supported: %s.<br/> " +
+ "The minimal supported version is %s. Please <a href='" + UPDATE_LINK + "'>update</a>.",
+ myVersion, HgVersion.MIN);
errorNotification.notifyError(null, "Unsupported Hg version", message, linkAdapter);
-
+ }
+ else if (myVersion.hasUnsupportedExtensions()) {
+ String unsupportedExtensionsAsString = myVersion.getUnsupportedExtensions().toString();
+ LOG.warn("Unsupported Hg extensions: " + unsupportedExtensionsAsString);
+ String message = String.format("Some hg extensions %s are not found or not supported by your hg version and will be ignored.\n" +
+ "Please, update your hgrc or Mercurial.ini file", unsupportedExtensionsAsString);
+ errorNotification.notifyWarning("Unsupported Hg version", message);
}
}
catch (Exception e) {
@@ -467,10 +451,13 @@
//sometimes not hg application has version command, but we couldn't parse an answer as valid hg,
// so parse(output) throw ParseException, but hg and git executable seems to be valid in this case
final String reason = (e.getCause() != null ? e.getCause() : e).getMessage();
- message = HgVcsMessages.message("hg4idea.unable.to.run.hg", executable);
+ String message = HgVcsMessages.message("hg4idea.unable.to.run.hg", executable);
errorNotification.notifyError(null, message,
String.format(
- reason + "<br/> Please check your hg executable path in <a href='" + SETTINGS_LINK + "'> settings </a>"),
+ reason +
+ "<br/> Please check your hg executable path in <a href='" +
+ SETTINGS_LINK +
+ "'> settings </a>"),
linkAdapter);
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcsMessages.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcsMessages.java
index 2ad3893..9937db3 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcsMessages.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgVcsMessages.java
@@ -12,6 +12,7 @@
// limitations under the License.
package org.zmlx.hg4idea;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;
@@ -23,26 +24,22 @@
public final class HgVcsMessages {
- private static Reference<ResourceBundle> ourBundle;
-
- private static final String BUNDLE = "org.zmlx.hg4idea.HgVcsMessages";
-
- private HgVcsMessages() { }
-
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, @Nullable Object... params) {
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull @Nullable Object... params) {
return CommonBundle.message(getBundle(), key, params);
}
+ private static Reference<ResourceBundle> ourBundle;
+ private static final String BUNDLE = "org.zmlx.hg4idea.HgVcsMessages";
+
+ private HgVcsMessages() {
+ }
+
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) {
- bundle = ourBundle.get();
- }
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
}
return bundle;
}
-
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
index 5f75011..3db5f19 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgAbstractGlobalAction.java
@@ -16,7 +16,6 @@
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.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
@@ -75,7 +74,7 @@
new HgCommandResultNotifier(project).notifyError(null, title, e.getMessage());
}
- protected void markDirtyAndHandleErrors(Project project, VirtualFile repository) {
+ static void markDirtyAndHandleErrors(Project project, VirtualFile repository) {
try {
HgUtil.markDirectoryDirty(project, repository);
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java
index f272547..c31e14e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopup.java
@@ -87,7 +87,8 @@
private void setCurrentBranchInfo() {
String branchText = "Current branch : ";
- myPopup.setAdText(branchText + HgUtil.getDisplayableBranchText(myCurrentRepository), SwingConstants.CENTER);
+ //always display heavy branch name for additional info //
+ myPopup.setAdText(branchText + myCurrentRepository.getCurrentBranch(), SwingConstants.CENTER);
}
@@ -113,7 +114,7 @@
if (repo != null) {
popupGroup.add(new RootAction<HgRepository>(repo, isMultiRepoConfig ? myCurrentRepository : null,
new HgBranchPopupActions(repo.getProject(), repo).createActions(null),
- HgUtil.getDisplayableBranchText(repo)));
+ HgUtil.getDisplayableBranchOrBookmarkText(repo)));
}
}
return popupGroup;
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java
index 0e31428..b2b4f99 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgBranchPopupActions.java
@@ -16,11 +16,13 @@
package org.zmlx.hg4idea.action;
import com.intellij.dvcs.DvcsUtil;
+import com.intellij.dvcs.repo.Repository;
import com.intellij.dvcs.ui.NewBranchAction;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.AnAction;
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;
@@ -28,16 +30,18 @@
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.UpdatedFiles;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.Function;
import com.intellij.util.PlatformIcons;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.vcs.log.Hash;
+import com.intellij.vcs.log.impl.HashImpl;
import org.jetbrains.annotations.NotNull;
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.HgBookmarkCreateCommand;
-import org.zmlx.hg4idea.command.HgBranchCreateCommand;
-import org.zmlx.hg4idea.command.HgMergeCommand;
-import org.zmlx.hg4idea.command.HgUpdateCommand;
+import org.zmlx.hg4idea.command.*;
import org.zmlx.hg4idea.execution.HgCommandException;
import org.zmlx.hg4idea.execution.HgCommandResult;
import org.zmlx.hg4idea.execution.HgCommandResultHandler;
@@ -46,10 +50,10 @@
import org.zmlx.hg4idea.repo.HgRepository;
import org.zmlx.hg4idea.ui.HgBookmarkDialog;
import org.zmlx.hg4idea.util.HgErrorUtil;
-import org.zmlx.hg4idea.util.HgUtil;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
+
+import static org.zmlx.hg4idea.util.HgUtil.*;
/**
* @author Nadya Zabrodina
@@ -68,13 +72,13 @@
DefaultActionGroup popupGroup = new DefaultActionGroup(null, false);
popupGroup.addAction(new HgNewBranchAction(myProject, Collections.singletonList(myRepository), myRepository.getRoot()));
popupGroup.addAction(new HgNewBookmarkAction(myProject, Collections.singletonList(myRepository), myRepository.getRoot()));
-
+ popupGroup.addAction(new HgShowUnnamedHeadsForCurrentBranchAction(myProject, myRepository));
if (toInsert != null) {
popupGroup.addAll(toInsert);
}
popupGroup.addSeparator("Bookmarks");
- List<String> bookmarkNames = HgUtil.getNamesWithoutHashes(myRepository.getBookmarks());
+ List<String> bookmarkNames = getNamesWithoutHashes(myRepository.getBookmarks());
String currentBookmark = myRepository.getCurrentBookmark();
Collections.sort(bookmarkNames);
for (String bookmark : bookmarkNames) {
@@ -86,9 +90,9 @@
}
popupGroup.addSeparator("Branches");
- List<String> branchNames = HgUtil.getNamesWithoutHashes(myRepository.getBranches());
- Collections.sort(branchNames);
- for (String branch : branchNames) {
+ List<String> branchNamesList = new ArrayList<String>(myRepository.getOpenedBranches());//only opened branches have to be shown
+ 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));
}
@@ -106,7 +110,7 @@
@Override
public void actionPerformed(AnActionEvent e) {
- final String name = HgUtil.getNewBranchNameFromUser(myProject, "Create New Branch");
+ final String name = getNewBranchNameFromUser(myProject, "Create New Branch");
if (name == null) {
return;
}
@@ -114,7 +118,7 @@
new HgBranchCreateCommand(myProject, myPreselectedRepo, name).execute(new HgCommandResultHandler() {
@Override
public void process(@Nullable HgCommandResult result) {
- myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null);
+ getRepositoryManager(myProject).updateRepository(myPreselectedRepo);
if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
new HgCommandResultNotifier(myProject)
.notifyError(result, "Creation failed", "Branch creation [" + name + "] failed");
@@ -160,7 +164,7 @@
bookmarkDialog.isActive()).execute(new HgCommandResultHandler() {
@Override
public void process(@Nullable HgCommandResult result) {
- myProject.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(myProject, null);
+ getRepositoryManager(myProject).updateRepository(myPreselectedRepo);
if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
new HgCommandResultNotifier(myProject)
.notifyError(result, "Creation failed", "Bookmark creation [" + name + "] failed");
@@ -175,6 +179,73 @@
}
}
+ static private class HgShowUnnamedHeadsForCurrentBranchAction extends ActionGroup {
+ @NotNull final Project myProject;
+ @NotNull final HgRepository myRepository;
+ @NotNull final String myCurrentBranchName;
+ @NotNull Collection<Hash> myHeads = new HashSet<Hash>();
+
+ public HgShowUnnamedHeadsForCurrentBranchAction(@NotNull Project project,
+ @NotNull HgRepository repository) {
+ super(null, true);
+ myProject = project;
+ myRepository = repository;
+ myCurrentBranchName = repository.getCurrentBranch();
+ getTemplatePresentation().setText(String.format("Unnamed heads for %s", myCurrentBranchName));
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ myHeads = filterUnnamedHeads();
+ }
+ });
+ }
+
+ @NotNull
+ private Collection<Hash> filterUnnamedHeads() {
+ Collection<Hash> branchWithHashes = myRepository.getBranches().get(myCurrentBranchName);
+ if (branchWithHashes == null) {
+ // repository is fresh or branch is fresh.
+ return Collections.emptySet();
+ }
+ else {
+ List<HgRevisionNumber> parents = new HgWorkingCopyRevisionsCommand(myProject).parents(myRepository.getRoot());
+ if (parents.size() == 1) {
+ Collection<Hash> bookmarkHashes = ContainerUtil.map(myRepository.getBookmarks(), new Function<HgNameWithHashInfo, Hash>() {
+
+ @Override
+ public Hash fun(HgNameWithHashInfo info) {
+ return info.getHash();
+ }
+ });
+ branchWithHashes.removeAll(bookmarkHashes);
+ branchWithHashes.remove(HashImpl.build(parents.get(0).getChangeset()));
+ }
+ }
+ return branchWithHashes;
+ }
+
+ @NotNull
+ @Override
+ public AnAction[] getChildren(@Nullable AnActionEvent e) {
+ List<AnAction> branchHeadActions = new ArrayList<AnAction>();
+ for (Hash hash : myHeads) {
+ branchHeadActions.add(new BranchActions(myProject, hash.toShortString(), myRepository));
+ }
+ return ContainerUtil.toArray(branchHeadActions, new AnAction[branchHeadActions.size()]);
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ if (myRepository.isFresh()) {
+ e.getPresentation().setEnabled(false);
+ e.getPresentation().setDescription("Checkout of a new branch is not possible before the first commit.");
+ }
+ else if (Repository.State.MERGING.equals(myRepository.getState())) {
+ e.getPresentation().setEnabled(false);
+ }
+ }
+ }
+
/**
* Actions available for branches.
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
index f5635cd..1aec1a0 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagAction.java
@@ -27,13 +27,16 @@
public class HgCreateTagAction extends HgAbstractGlobalAction {
- protected void execute(@NotNull final Project project, @NotNull Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
+ public void execute(@NotNull final Project project,
+ @NotNull Collection<VirtualFile> repos,
+ @Nullable VirtualFile selectedRepo,
+ @Nullable final String reference) {
final HgTagDialog dialog = new HgTagDialog(project);
dialog.setRoots(repos, selectedRepo);
dialog.show();
if (dialog.isOK()) {
try {
- new HgTagCreateCommand(project, dialog.getRepository(), dialog.getTagName()).execute(new HgCommandResultHandler() {
+ new HgTagCreateCommand(project, dialog.getRepository(), dialog.getTagName(), reference).execute(new HgCommandResultHandler() {
@Override
public void process(@Nullable HgCommandResult result) {
if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
@@ -48,4 +51,8 @@
}
}
}
+
+ protected void execute(@NotNull final Project project, @NotNull Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo) {
+ execute(project, repos, selectedRepo, null);
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java
new file mode 100644
index 0000000..18a42d7
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgCreateTagFromLogAction.java
@@ -0,0 +1,33 @@
+/*
+ * 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.action;
+
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.repo.HgRepository;
+
+import java.util.Arrays;
+
+/**
+ * @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);
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
new file mode 100644
index 0000000..7410b0e
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgLogSingleCommitAction.java
@@ -0,0 +1,91 @@
+/*
+ * 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.action;
+
+import com.intellij.dvcs.DvcsUtil;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.components.ServiceManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import com.intellij.vcs.log.VcsLog;
+import com.intellij.vcs.log.VcsLogDataKeys;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.repo.HgRepositoryManager;
+
+import java.util.List;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public abstract class HgLogSingleCommitAction extends DumbAwareAction {
+
+ private static final Logger LOG = Logger.getInstance(HgLogSingleCommitAction.class);
+
+ protected abstract void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit);
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ Data data = Data.collect(e);
+ if (!data.isValid()) {
+ return;
+ }
+
+ List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
+ if (details.size() != 1) {
+ return;
+ }
+ VcsFullCommitDetails commit = details.get(0);
+
+ HgRepositoryManager repositoryManager = ServiceManager.getService(data.project, HgRepositoryManager.class);
+ final HgRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
+ if (repository == null) {
+ DvcsUtil.noVcsRepositoryForRoot(LOG, commit.getRoot(), data.project, repositoryManager, HgVcs.getInstance(data.project));
+ return;
+ }
+
+ actionPerformed(repository, commit);
+ }
+
+ @Override
+ public void update(AnActionEvent e) {
+ Data data = Data.collect(e);
+ boolean enabled = data.isValid() && data.log.getSelectedCommits().size() == 1;
+ e.getPresentation().setVisible(data.isValid());
+ e.getPresentation().setEnabled(enabled);
+ }
+
+ private static class Data {
+ Project project;
+ VcsLog log;
+
+ static Data collect(AnActionEvent e) {
+ Data data = new Data();
+ data.project = e.getData(CommonDataKeys.PROJECT);
+ data.log = e.getData(VcsLogDataKeys.VSC_LOG);
+ return data;
+ }
+
+ boolean isValid() {
+ return project != null && log != null && DvcsUtil.logHasRootForVcs(log, HgVcs.getKey());
+ }
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
index f7a3b8a..1a2cdea 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToAction.java
@@ -12,7 +12,6 @@
// limitations under the License.
package org.zmlx.hg4idea.action;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
@@ -21,7 +20,6 @@
import com.intellij.util.Consumer;
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.HgUpdateCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
@@ -46,54 +44,42 @@
});
}
- private void showUpdateDialogAndExecute(final Project project,
- Collection<VirtualFile> repos, @Nullable VirtualFile selectedRepo,
- HgBranchesAndTags branchesAndTags) {
+ 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);
dialog.show();
if (dialog.isOK()) {
FileDocumentManager.getInstance().saveAllDocuments();
- String updateToValue = dialog.isBranchSelected()
- ? dialog.getBranch().getName()
- : dialog.isTagSelected() ? dialog.getTag().getName() : dialog.getRevision();
- new Task.Backgroundable(project, HgVcsMessages.message("action.hg4idea.updateTo.description", updateToValue)) {
-
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- updateTo(dialog, project);
- markDirtyAndHandleErrors(project, dialog.getRepository());
- }
- }.queue();
+ final String updateToValue = dialog.isBranchSelected()
+ ? dialog.getBranch().getName()
+ : dialog.isBookmarkSelected()
+ ? dialog.getBookmark().getName()
+ : dialog.isTagSelected() ? dialog.getTag().getName() : dialog.getRevision();
+ String title = HgVcsMessages.message("hg4idea.progress.updatingTo", updateToValue);
+ runUpdateToInBackground(project, title, dialog.getRepository(), updateToValue, dialog.isRemoveLocalChanges());
}
}
- public void updateTo(HgUpdateToDialog dialog, final Project project) {
- final VirtualFile repository = dialog.getRepository();
- final HgUpdateCommand command = new HgUpdateCommand(project, repository);
- command.setClean(dialog.isRemoveLocalChanges());
- if (dialog.isRevisionSelected()) {
- command.setRevision(dialog.getRevision());
- }
- if (dialog.isBranchSelected()) {
- command.setBranch(dialog.getBranch().getName());
- }
- if (dialog.isTagSelected()) {
- command.setRevision(dialog.getTag().getName());
- }
- if (dialog.isBookmarkSelected()) {
- command.setRevision(dialog.getBookmark().getName());
- }
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ public static void runUpdateToInBackground(@NotNull final Project project,
+ @NotNull String title,
+ @NotNull final VirtualFile root,
+ @NotNull final String updateToNameOrRevision,
+ final boolean clean) {
+ new Task.Backgroundable(project, title) {
@Override
- public void run() {
+ public void run(@NotNull ProgressIndicator indicator) {
+ final HgUpdateCommand command = new HgUpdateCommand(project, root);
+ command.setRevision(updateToNameOrRevision);
+ command.setClean(clean);
HgCommandResult result = command.execute();
- new HgConflictResolver(project).resolve(repository);
+ new HgConflictResolver(project).resolve(root);
if (HgErrorUtil.hasErrorsInCommandExecution(result)) {
new HgCommandResultNotifier(project).notifyError(result, "", "Update failed");
}
- project.getMessageBus().syncPublisher(HgVcs.BRANCH_TOPIC).update(project, null);
+ markDirtyAndHandleErrors(project, root);
}
- });
+ }.queue();
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java
new file mode 100644
index 0000000..506298e
--- /dev/null
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/action/HgUpdateToFromLogAction.java
@@ -0,0 +1,34 @@
+/*
+ * 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.action;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.vcs.log.VcsFullCommitDetails;
+import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.HgVcsMessages;
+import org.zmlx.hg4idea.repo.HgRepository;
+
+public class HgUpdateToFromLogAction extends HgLogSingleCommitAction {
+ @Override
+ protected void actionPerformed(@NotNull HgRepository repository, @NotNull VcsFullCommitDetails commit) {
+ String revisionHash = commit.getHash().asString();
+ Project project = repository.getProject();
+ VirtualFile rootFile = repository.getRoot();
+ String title = HgVcsMessages.message("hg4idea.progress.updatingTo", revisionHash);
+ HgUpdateToAction.runUpdateToInBackground(project, title, rootFile, revisionHash, false);
+ }
+}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java
index bcad185..5aa632e 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgCommitCommand.java
@@ -50,14 +50,20 @@
private final VirtualFile myRoot;
private final String myMessage;
@NotNull private final Charset myCharset;
+ private final boolean myAmend;
private Set<HgFile> myFiles = Collections.emptySet();
- public HgCommitCommand(Project project, @NotNull VirtualFile root, String message) {
+ public HgCommitCommand(Project project, @NotNull VirtualFile root, String message, boolean amend) {
myProject = project;
myRoot = root;
myMessage = message;
myCharset = HgEncodingUtil.getDefaultCharset(myProject);
+ myAmend = amend;
+ }
+
+ public HgCommitCommand(Project project, @NotNull VirtualFile root, String message) {
+ this(project, root, message, false);
}
public void setFiles(@NotNull Set<HgFile> files) {
@@ -71,7 +77,7 @@
//if it's merge commit, so myFiles is Empty. Need to commit all files in changeList.
// see HgCheckinEnviroment->commit() method
if (myFiles.isEmpty()) {
- commitChunkFiles(Collections.<String>emptyList(), false);
+ commitChunkFiles(Collections.<String>emptyList(), myAmend);
}
else {
List<String> relativePaths = ContainerUtil.map2List(myFiles, new Function<HgFile, String>() {
@@ -82,7 +88,7 @@
});
List<List<String>> chunkedCommits = VcsFileUtil.chunkRelativePaths(relativePaths);
int size = chunkedCommits.size();
- commitChunkFiles(chunkedCommits.get(0), false);
+ commitChunkFiles(chunkedCommits.get(0), myAmend);
HgVcs vcs = HgVcs.getInstance(myProject);
boolean amendCommit = vcs != null && vcs.getVersion().isAmendSupported();
for (int i = 1; i < size; i++) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java
index 373dd12..ed93bee 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgLogCommand.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgFile;
@@ -38,16 +39,6 @@
public class HgLogCommand {
private static final Logger LOG = Logger.getInstance(HgLogCommand.class.getName());
- private static final String[] SHORT_TEMPLATE_ITEMS =
- {"{rev}", "{node}", "{parents}", "{date|isodatesec}", "{author}", "{branch}", "{desc}"};
- private static final String[] LONG_TEMPLATE_ITEMS =
- {"{rev}", "{node}", "{parents}", "{date|isodatesec}", "{author}", "{branch}", "{desc}", "{file_adds}",
- "{file_mods}",
- "{file_dels}", "{join(file_copies,'" + HgChangesetUtil.FILE_SEPARATOR + "')}"};
- private static final String[] LONG_TEMPLATE_FOR_OLD_VERSIONS =
- {"{rev}", "{node}", "{parents}", "{date|isodatesec}", "{author}", "{branch}", "{desc}", "{file_adds}",
- "{file_mods}",
- "{file_dels}", "{file_copies}"};
private static final int REVISION_INDEX = 0;
private static final int CHANGESET_INDEX = 1;
private static final int PARENTS_INDEX = 2;
@@ -64,11 +55,10 @@
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z");
@NotNull private final Project myProject;
-
+ @NotNull private HgVersion myVersion;
private boolean myIncludeRemoved;
private boolean myFollowCopies;
private boolean myLogFile = true;
- private boolean myBuiltInSupported = false;
private boolean myLargeFilesWithFollowSupported = false;
public void setIncludeRemoved(boolean includeRemoved) {
@@ -90,9 +80,8 @@
LOG.info("Vcs couldn't be null for project");
return;
}
- HgVersion version = vcs.getVersion();
- myBuiltInSupported = version.isBuiltInFunctionSupported();
- myLargeFilesWithFollowSupported = version.isLargeFilesWithFollowSupported();
+ myVersion = vcs.getVersion();
+ myLargeFilesWithFollowSupported = myVersion.isLargeFilesWithFollowSupported();
}
/**
@@ -107,27 +96,14 @@
*/
public final List<HgFileRevision> execute(final HgFile hgFile, int limit, boolean includeFiles, @Nullable List<String> argsForCmd)
throws HgCommandException {
- if ((limit <= 0 && limit != -1) || hgFile == null || hgFile.getRepo() == null) {
+ if ((limit <= 0 && limit != -1) || hgFile == null) {
return Collections.emptyList();
}
- String template;
- boolean shouldParseOldTemplate = false;
-
- if (!includeFiles) {
- template = HgChangesetUtil.makeTemplate(SHORT_TEMPLATE_ITEMS);
- }
- else {
- if (!myBuiltInSupported) {
- template = HgChangesetUtil.makeTemplate(LONG_TEMPLATE_FOR_OLD_VERSIONS);
- shouldParseOldTemplate = true;
- }
- else {
- template = HgChangesetUtil.makeTemplate(LONG_TEMPLATE_ITEMS);
- }
- }
-
- int expectedItemCount = includeFiles ? LONG_TEMPLATE_ITEMS.length : SHORT_TEMPLATE_ITEMS.length;
+ String[] templates = constructTemplateArgument(includeFiles, myVersion);
+ String template = HgChangesetUtil.makeTemplate(templates);
+ int expectedItemCount = templates.length;
+ boolean shouldParseOldTemplate = !myVersion.isBuiltInFunctionSupported();
FilePath originalFileName = HgUtil.getOriginalFileName(hgFile.toFilePath(), ChangeListManager.getInstance(myProject));
HgFile originalHgFile = new HgFile(hgFile.getRepo(), originalFileName);
@@ -140,7 +116,10 @@
List<String> errors = result.getErrorLines();
if (errors != null && !errors.isEmpty()) {
- throw new HgCommandException(errors.toString());
+ if (result.getExitValue() != 0) {
+ throw new HgCommandException(errors.toString());
+ }
+ LOG.warn(errors.toString());
}
String output = result.getRawOutput();
String[] changeSets = output.split(HgChangesetUtil.CHANGESET_SEPARATOR);
@@ -163,23 +142,7 @@
String changeset = attributes[CHANGESET_INDEX];
String parentsString = attributes[PARENTS_INDEX];
- List<HgRevisionNumber> parents = new ArrayList<HgRevisionNumber>(2);
- if (StringUtil.isEmpty(parentsString)) {
- Long revision = Long.valueOf(revisionString);
- HgRevisionNumber parentRevision = HgRevisionNumber.getLocalInstance(String.valueOf(revision - 1));
- parents.add(parentRevision);
- }
- else {
- //hg returns parents in the format 'rev:node rev:node ' (note the trailing space)
- String[] parentStrings = parentsString.trim().split(" ");
- for (String parentString : parentStrings) {
- String[] parentParts = parentString.split(":");
- //if revision has only 1 parent and "--debug" argument were added, its second parent has revision number -1
- if (Integer.valueOf(parentParts[0]) >= 0) {
- parents.add(HgRevisionNumber.getInstance(parentParts[0], parentParts[1]));
- }
- }
- }
+ List<HgRevisionNumber> parents = parseParentRevisions(parentsString, revisionString);
Date revisionDate = DATE_FORMAT.parse(attributes[DATE_INDEX]);
String author = attributes[AUTHOR_INDEX];
@@ -240,7 +203,7 @@
}
@Nullable
- public HgCommandResult execute(@NotNull VirtualFile repo, @NotNull String template, int limit, HgFile hgFile,
+ public HgCommandResult execute(@NotNull VirtualFile repo, @NotNull String template, int limit, @Nullable HgFile hgFile,
@Nullable List<String> argsForCmd) {
List<String> arguments = new LinkedList<String>();
if (myIncludeRemoved) {
@@ -268,8 +231,9 @@
}
if (argsForCmd != null) {
arguments.addAll(argsForCmd);
- }
- if (myLogFile) {
+ } //to do double check the same condition should be simplified
+
+ if (myLogFile && hgFile != null) {
arguments.add(hgFile.getRelativePath());
}
HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject);
@@ -356,4 +320,46 @@
return -1;
}
+ @NotNull
+ private static String[] constructTemplateArgument(boolean includeFiles, @NotNull HgVersion currentVersion) {
+ List<String> templates = new ArrayList<String>();
+ templates.add("{rev}");
+ templates.add("{node}");
+ if (currentVersion.isParentRevisionTemplateSupported()) {
+ templates.add("{p1rev}:{p1node} {p2rev}:{p2node}");
+ }
+ else {
+ templates.add("{parents}");
+ }
+ templates.addAll(Arrays.asList("{date|isodatesec}", "{author}", "{branch}", "{desc}"));
+ if (!includeFiles) {
+ return ArrayUtil.toStringArray(templates);
+ }
+ templates.addAll(Arrays.asList("{file_adds}", "{file_mods}", "{file_dels}"));
+ templates
+ .add(currentVersion.isBuiltInFunctionSupported() ? "{join(file_copies,'" + HgChangesetUtil.FILE_SEPARATOR + "')}" : "{file_copies}");
+ return ArrayUtil.toStringArray(templates);
+ }
+
+ @NotNull
+ private static List<HgRevisionNumber> parseParentRevisions(@NotNull String parentsString, @NotNull String currentRevisionString) {
+ List<HgRevisionNumber> parents = new ArrayList<HgRevisionNumber>(2);
+ if (StringUtil.isEmptyOrSpaces(parentsString)) {
+ // parents shouldn't be empty only if not supported
+ Long revision = Long.valueOf(currentRevisionString);
+ HgRevisionNumber parentRevision = HgRevisionNumber.getLocalInstance(String.valueOf(revision - 1));
+ parents.add(parentRevision);
+ return parents;
+ }
+ //hg returns parents in the format 'rev:node rev:node ' (note the trailing space)
+ String[] parentStrings = parentsString.trim().split(" ");
+ for (String parentString : parentStrings) {
+ String[] parentParts = parentString.split(":");
+ //if revision has only 1 parent and "--debug" argument were added or if appropriate parent template were used, its second parent has revision number -1
+ if (Integer.valueOf(parentParts[0]) >= 0) {
+ parents.add(HgRevisionNumber.getInstance(parentParts[0], parentParts[1]));
+ }
+ }
+ return parents;
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
index d7dd9ec..decdbd9 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
@@ -188,6 +188,14 @@
if (result == null) {
return changes;
}
+ List<String> errors = result.getErrorLines();
+ if (errors != null && !errors.isEmpty()) {
+ if (result.getExitValue() != 0) {
+ LOG.error("Mercurial error: Could not execute hg status command ", errors.toString());
+ return changes;
+ }
+ LOG.warn(errors.toString());
+ }
for (String line : result.getOutputLines()) {
if (StringUtil.isEmptyOrSpaces(line) || line.length() < ITEM_COUNT) {
LOG.warn("Unexpected line in status '" + line + '\'');
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java
index 11dae66..7c1aa06 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagBranchCommand.java
@@ -14,6 +14,7 @@
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;
@@ -22,6 +23,7 @@
import java.util.LinkedList;
import java.util.List;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -67,7 +69,7 @@
return new HgCommandExecutor(project).executeInCurrentThread(repo, "bookmarks", null);
}
- public static List<HgTagBranch> parseResult(HgCommandResult result) {
+ 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);
@@ -81,4 +83,15 @@
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/command/HgTagCreateCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagCreateCommand.java
index 5c36d7d..ba1934b 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagCreateCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/command/HgTagCreateCommand.java
@@ -19,26 +19,40 @@
import org.zmlx.hg4idea.execution.HgCommandException;
import org.zmlx.hg4idea.execution.HgCommandExecutor;
import org.zmlx.hg4idea.execution.HgCommandResultHandler;
+import org.zmlx.hg4idea.repo.HgRepositoryManager;
+import org.zmlx.hg4idea.util.HgUtil;
-import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.List;
public class HgTagCreateCommand {
private final Project project;
private final VirtualFile repo;
private final String tagName;
+ private final String revisionNumberOrHash;
- public HgTagCreateCommand(Project project, @NotNull VirtualFile repo, String tagName) {
+ public HgTagCreateCommand(Project project, @NotNull VirtualFile repo, String tagName, String revisionNumberOrHash) {
this.project = project;
this.repo = repo;
this.tagName = tagName;
+ this.revisionNumberOrHash = revisionNumberOrHash;
}
public void execute(HgCommandResultHandler resultHandler) throws HgCommandException {
if (StringUtil.isEmptyOrSpaces(tagName)) {
throw new HgCommandException("tag name is empty");
}
- new HgCommandExecutor(project).execute(repo, "tag", Arrays.asList(tagName), resultHandler);
+ List<String> arguments = new ArrayList<String>();
+ arguments.add(tagName);
+ if (!StringUtil.isEmptyOrSpaces(revisionNumberOrHash)) {
+ arguments.add("--rev");
+ arguments.add(revisionNumberOrHash);
+ }
+ new HgCommandExecutor(project).execute(repo, "tag", arguments, resultHandler);
+ if (!project.isDisposed()) {
+ HgRepositoryManager manager = HgUtil.getRepositoryManager(project);
+ manager.updateRepository(repo);
+ }
}
-
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
index 35a7077..bcf2747 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/HgCommandExecutor.java
@@ -214,7 +214,7 @@
ShellCommand shellCommand = new ShellCommand(cmdLine, workingDir, myCharset);
long startTime = System.currentTimeMillis();
LOG.debug(String.format("hg %s started", operation));
- result = shellCommand.execute();
+ result = shellCommand.execute(myShowOutput);
LOG.debug(String.format("hg %s finished. Took %s ms", operation, System.currentTimeMillis() - startTime));
if (!HgErrorUtil.isAuthorizationError(result)) {
passReceiver.saveCredentials();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java
index f999649..ccfc562 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/execution/ShellCommand.java
@@ -14,19 +14,24 @@
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.process.CapturingProcessHandler;
-import com.intellij.execution.process.ProcessOutput;
+import com.intellij.execution.process.*;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.util.Key;
+import com.intellij.openapi.vcs.LineHandlerHelper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.StringWriter;
import java.nio.charset.Charset;
+import java.util.Iterator;
import java.util.List;
public final class ShellCommand {
private final GeneralCommandLine myCommandLine;
+ private int myExitCode;
public ShellCommand(@Nullable List<String> commandLine, @Nullable String dir, @Nullable Charset charset) {
if (commandLine == null || commandLine.isEmpty()) {
@@ -42,19 +47,55 @@
}
@NotNull
- public HgCommandResult execute() throws ShellCommandException, InterruptedException {
- StringWriter out = new StringWriter();
- StringWriter err = new StringWriter();
+ public HgCommandResult execute(final boolean showTextOnIndicator) throws ShellCommandException, InterruptedException {
+ final StringWriter out = new StringWriter();
+ final StringWriter err = new StringWriter();
+ final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
try {
- Process process = myCommandLine.createProcess();
+ final Process process = myCommandLine.createProcess();
+ final OSProcessHandler processHandler = new OSProcessHandler(process, myCommandLine.toString(), myCommandLine.getCharset());
- CapturingProcessHandler processHandler = new CapturingProcessHandler(process, myCommandLine.getCharset());
- final ProcessOutput processOutput = processHandler.runProcess();
+ processHandler.addProcessListener(new ProcessListener() {
+ public void startNotified(final ProcessEvent event) {
+ }
- int exitValue = processOutput.getExitCode();
- out.write(processOutput.getStdout());
- err.write(processOutput.getStderr());
- return new HgCommandResult(out, err, exitValue);
+ public void processTerminated(final ProcessEvent event) {
+ myExitCode = event.getExitCode();
+ }
+
+ @Override
+ public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
+ }
+
+ @Override
+ public void onTextAvailable(ProcessEvent event, Key outputType) {
+ Iterator<String> lines = LineHandlerHelper.splitText(event.getText()).iterator();
+ if (ProcessOutputTypes.STDOUT == outputType) {
+ while (lines.hasNext()) {
+ String line = lines.next();
+ if (indicator != null && showTextOnIndicator) {
+ indicator.setText2(line);
+ }
+ out.write(line);
+ }
+ }
+ else if (ProcessOutputTypes.STDERR == outputType) {
+ while (lines.hasNext()) {
+ err.write(lines.next());
+ }
+ }
+ }
+ });
+
+ processHandler.startNotify();
+ while (!processHandler.waitFor(300)) {
+ if (indicator != null && indicator.isCanceled()) {
+ processHandler.destroyProcess();
+ myExitCode = 255;
+ break;
+ }
+ }
+ return new HgCommandResult(out, err, myExitCode);
}
catch (ExecutionException e) {
throw new ShellCommandException(e);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
index c538825..9c90f5f 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgLogProvider.java
@@ -16,17 +16,15 @@
package org.zmlx.hg4idea.log;
-import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcs.log.*;
-import com.intellij.vcs.log.VcsLogTextFilter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgNameWithHashInfo;
@@ -39,10 +37,7 @@
import org.zmlx.hg4idea.util.HgUtil;
import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
/**
* @author Nadya Zabrodina
@@ -56,19 +51,18 @@
@NotNull private final VcsLogRefManager myRefSorter;
@NotNull private final VcsLogObjectsFactory myVcsObjectsFactory;
- public HgLogProvider(@NotNull Project project, @NotNull HgRepositoryManager repositoryManager) {
+ public HgLogProvider(@NotNull Project project, @NotNull HgRepositoryManager repositoryManager, @NotNull VcsLogObjectsFactory factory) {
myProject = project;
myRepositoryManager = repositoryManager;
myRefSorter = new HgRefManager();
- myVcsObjectsFactory = ServiceManager.getService(project, VcsLogObjectsFactory.class);
+ myVcsObjectsFactory = factory;
}
@NotNull
@Override
public List<? extends VcsFullCommitDetails> readFirstBlock(@NotNull VirtualFile root,
boolean ordered, int commitCount) throws VcsException {
- String[] params = ordered ? ArrayUtil.EMPTY_STRING_ARRAY : new String[]{"-r", "0:tip"};
- return HgHistoryUtil.history(myProject, root, commitCount, params);
+ return HgHistoryUtil.history(myProject, root, commitCount, ordered ? Collections.<String>emptyList() : Arrays.asList("-r", "0:tip"));
}
@NotNull
@@ -101,18 +95,24 @@
}
repository.update();
- Collection<HgNameWithHashInfo> branches = repository.getBranches();
+ Map<String, Set<Hash>> branches = repository.getBranches();
+ Set<String> openedBranchNames = repository.getOpenedBranches();
Collection<HgNameWithHashInfo> bookmarks = repository.getBookmarks();
Collection<HgNameWithHashInfo> tags = repository.getTags();
Collection<HgNameWithHashInfo> localTags = repository.getLocalTags();
Collection<VcsRef> refs = new ArrayList<VcsRef>(branches.size() + bookmarks.size());
- for (HgNameWithHashInfo branchInfo : branches) {
- refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(branchInfo.getHash()), branchInfo.getName(), HgRefManager.BRANCH, root));
+ for (Map.Entry<String, Set<Hash>> entry : branches.entrySet()) {
+ String branchName = entry.getKey();
+ boolean opened = openedBranchNames.contains(branchName);
+ for (Hash hash : entry.getValue()) {
+ refs.add(myVcsObjectsFactory.createRef(hash, branchName, opened ? HgRefManager.BRANCH : HgRefManager.CLOSED_BRANCH, root));
+ }
}
+
for (HgNameWithHashInfo bookmarkInfo : bookmarks) {
- refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(bookmarkInfo.getHash()), bookmarkInfo.getName(),
+ refs.add(myVcsObjectsFactory.createRef(bookmarkInfo.getHash(), bookmarkInfo.getName(),
HgRefManager.BOOKMARK, root));
}
String currentRevision = repository.getCurrentRevision();
@@ -120,10 +120,10 @@
refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(currentRevision), "tip", HgRefManager.HEAD, root));
}
for (HgNameWithHashInfo tagInfo : tags) {
- refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(tagInfo.getHash()), tagInfo.getName(), HgRefManager.TAG, root));
+ refs.add(myVcsObjectsFactory.createRef(tagInfo.getHash(), tagInfo.getName(), HgRefManager.TAG, root));
}
for (HgNameWithHashInfo localTagInfo : localTags) {
- refs.add(myVcsObjectsFactory.createRef(myVcsObjectsFactory.createHash(localTagInfo.getHash()), localTagInfo.getName(),
+ refs.add(myVcsObjectsFactory.createRef(localTagInfo.getHash(), localTagInfo.getName(),
HgRefManager.LOCAL_TAG, root));
}
return refs;
@@ -156,32 +156,41 @@
@NotNull
@Override
public List<? extends VcsFullCommitDetails> getFilteredDetails(@NotNull final VirtualFile root,
- @NotNull Collection<VcsLogBranchFilter> branchFilters,
- @NotNull Collection<VcsLogUserFilter> userFilters,
- @NotNull Collection<VcsLogDateFilter> dateFilters,
- @NotNull Collection<VcsLogTextFilter> textFilters,
- @NotNull Collection<VcsLogStructureFilter> structureFilters,
+ @NotNull VcsLogFilterCollection filterCollection,
int maxCount) throws VcsException {
List<String> filterParameters = ContainerUtil.newArrayList();
// branch filter and user filter may be used several times without delimiter
- if (!branchFilters.isEmpty()) {
- for (VcsLogBranchFilter branchFilter : branchFilters) {
- filterParameters.add(prepareParameter("branch", branchFilter.getBranchName()));
+ if (filterCollection.getBranchFilter() != null) {
+ HgRepository repository = myRepositoryManager.getRepositoryForRoot(root);
+ if (repository == null) {
+ LOG.error("Repository not found for root " + root);
+ return Collections.emptyList();
+ }
+
+ boolean atLeastOneBranchExists = false;
+ for (String branchName : filterCollection.getBranchFilter().getBranchNames()) {
+ if (branchExists(repository, branchName)) {
+ filterParameters.add(prepareParameter("branch", branchName));
+ atLeastOneBranchExists = true;
+ }
+ }
+ if (!atLeastOneBranchExists) { // no such branches => filter matches nothing
+ return Collections.emptyList();
}
}
- if (!userFilters.isEmpty()) {
- for (VcsLogUserFilter authorFilter : userFilters) {
- filterParameters.add(prepareParameter("user", authorFilter.getUserName(root)));
+ if (filterCollection.getUserFilter() != null) {
+ for (String authorName : filterCollection.getUserFilter().getUserNames(root)) {
+ filterParameters.add(prepareParameter("user", authorName));
}
}
- if (!dateFilters.isEmpty()) {
+ if (filterCollection.getDateFilter() != null) {
StringBuilder args = new StringBuilder();
final SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
filterParameters.add("-r");
- VcsLogDateFilter filter = dateFilters.iterator().next();
+ VcsLogDateFilter filter = filterCollection.getDateFilter();
if (filter.getAfter() != null) {
args.append("date('>").append(dateFormatter.format(filter.getAfter())).append("')");
}
@@ -196,34 +205,39 @@
filterParameters.add(args.toString());
}
- if (textFilters.size() > 1) {
- LOG.warn("Expected only one text filter: " + textFilters);
- }
- else if (!textFilters.isEmpty()) {
- String textFilter = textFilters.iterator().next().getText();
+ if (filterCollection.getTextFilter() != null) {
+ String textFilter = filterCollection.getTextFilter().getText();
filterParameters.add(prepareParameter("keyword", textFilter));
}
- if (!structureFilters.isEmpty()) {
- for (VcsLogStructureFilter filter : structureFilters) {
- for (VirtualFile file : filter.getFiles(root)) {
- filterParameters.add(file.getPath());
- }
+ if (filterCollection.getStructureFilter() != null) {
+ for (VirtualFile file : filterCollection.getStructureFilter().getFiles(root)) {
+ filterParameters.add(file.getPath());
}
}
- return HgHistoryUtil.history(myProject, root, maxCount, ArrayUtil.toStringArray(filterParameters));
+ return HgHistoryUtil.history(myProject, root, maxCount, filterParameters);
}
@Nullable
@Override
public VcsUser getCurrentUser(@NotNull VirtualFile root) throws VcsException {
String userName = HgConfig.getInstance(myProject, root).getNamedConfig("ui", "username");
+ //order of variables to identify hg username see at mercurial/ui.py
if (userName == null) {
userName = System.getenv("HGUSER");
+ if (userName == null) {
+ userName = System.getenv("USER");
+ if (userName == null) {
+ userName = System.getenv("LOGNAME");
+ if (userName == null) {
+ return null;
+ }
+ }
+ }
}
- List<String> userArgs = HgUtil.parseUserNameAndEmail(userName);
- return userName == null ? null : myVcsObjectsFactory.createUser(userArgs.get(0), userArgs.get(1));
+ Pair<String, String> userArgs = HgUtil.parseUserNameAndEmail(userName);
+ return myVcsObjectsFactory.createUser(userArgs.getFirst(), userArgs.getSecond());
}
@NotNull
@@ -235,4 +249,10 @@
private static String prepareParameter(String paramName, String value) {
return "--" + paramName + "=" + value; // no value escaping needed, because the parameter itself will be quoted by GeneralCommandLine
}
+
+ private static boolean branchExists(@NotNull HgRepository repository, @NotNull String branchName) {
+ return repository.getBranches().keySet().contains(branchName) ||
+ HgUtil.getNamesWithoutHashes(repository.getBookmarks()).contains(branchName);
+ }
+
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgRefManager.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgRefManager.java
index 1a52c2b4..f1df227 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgRefManager.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgRefManager.java
@@ -36,12 +36,14 @@
private static final Color HEAD_COLOR = new JBColor(new Color(0xf1ef9e), new Color(113, 111, 64));
private static final Color BRANCH_COLOR = new JBColor(new Color(0x75eec7), new Color(0x0D6D4F));
+ private static final Color CLOSED_BRANCH_COLOR = new JBColor(new Color(0xee7f8a), new Color(0xee7f8a).darker());
private static final Color BOOKMARK_COLOR = new JBColor(new Color(0xbcbcfc), new Color(0xbcbcfc).darker().darker());
private static final Color TAG_COLOR = JBColor.WHITE;
private static final Color LOCAL_TAG_COLOR = JBColor.CYAN;
public static final VcsRefType HEAD = new SimpleRefType(true, HEAD_COLOR);
public static final VcsRefType BRANCH = new SimpleRefType(true, BRANCH_COLOR);
+ public static final VcsRefType CLOSED_BRANCH = new SimpleRefType(false, CLOSED_BRANCH_COLOR);
public static final VcsRefType BOOKMARK = new SimpleRefType(true, BOOKMARK_COLOR);
public static final VcsRefType TAG = new SimpleRefType(false, TAG_COLOR);
public static final VcsRefType LOCAL_TAG = new SimpleRefType(false, LOCAL_TAG_COLOR);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java
index 71c4993..46b2f46 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCheckoutProvider.java
@@ -52,6 +52,7 @@
if (!dialog.isOK()) {
return;
}
+ dialog.rememberSettings();
final VirtualFile destinationParent = LocalFileSystem.getInstance().findFileByIoFile(new File(dialog.getParentDirectory()));
if (destinationParent == null) {
return;
@@ -68,13 +69,12 @@
// handle result
HgCommandResult myCloneResult = clone.execute();
- if (myCloneResult == null) {
- new HgCommandResultNotifier(project).notifyError(myCloneResult, "Clone failed", "Clone failed due to unknown error");
- } else if (HgErrorUtil.hasErrorsInCommandExecution(myCloneResult)) {
+ if (myCloneResult == null || HgErrorUtil.hasErrorsInCommandExecution(myCloneResult)) {
new HgCommandResultNotifier(project).notifyError(myCloneResult, "Clone failed", "Clone from " +
sourceRepositoryURL +
" failed.");
- } else {
+ }
+ else {
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
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 7df032e..aaf9e9d 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCheckinEnvironment.java
@@ -12,6 +12,7 @@
// limitations under the License.
package org.zmlx.hg4idea.provider.commit;
+import com.intellij.dvcs.DvcsCommitAdditionalComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.progress.ProgressIndicator;
@@ -33,9 +34,13 @@
import com.intellij.util.ui.UIUtil;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.*;
import org.zmlx.hg4idea.command.*;
import org.zmlx.hg4idea.execution.HgCommandException;
+import org.zmlx.hg4idea.execution.HgCommandExecutor;
+import org.zmlx.hg4idea.execution.HgCommandResult;
+import org.zmlx.hg4idea.util.HgUtil;
import java.util.*;
@@ -43,6 +48,7 @@
private final Project myProject;
private boolean myNextCommitIsPushed;
+ private boolean myNextCommitAmend; // If true, the next commit is amended
public HgCheckinEnvironment(Project project) {
myProject = project;
@@ -51,7 +57,7 @@
public RefreshableOnComponent createAdditionalOptionsPanel(CheckinProjectPanel panel,
PairConsumer<Object, Object> additionalDataConsumer) {
myNextCommitIsPushed = false;
- return null;
+ return new HgCommitAdditionalComponent(myProject,panel);
}
public String getDefaultMessageFor(FilePath[] filesToCheckin) {
@@ -78,7 +84,7 @@
VirtualFile repo = entry.getKey();
Set<HgFile> selectedFiles = entry.getValue();
- HgCommitCommand command = new HgCommitCommand(myProject, repo, preparedComment);
+ HgCommitCommand command = new HgCommitCommand(myProject, repo, preparedComment, myNextCommitAmend);
if (isMergeCommit(repo)) {
//partial commits are not allowed during merges
@@ -170,11 +176,11 @@
} else {
runnable.run();
}
- return choice[0] == 0;
+ return choice[0] == Messages.OK;
}
public List<VcsException> commit(List<Change> changes, String preparedComment) {
- return commit(changes, preparedComment, FunctionUtil.<Object, Object>nullConstant(), null);
+ return commit(changes, preparedComment, FunctionUtil.nullConstant(), null);
}
public List<VcsException> scheduleMissingFileForDeletion(List<FilePath> files) {
@@ -246,7 +252,52 @@
hgFiles.add(new HgFile(repo, filePath));
}
- public void setNextCommitIsPushed(boolean pushed) {
+ public void setNextCommitIsPushed() {
myNextCommitIsPushed = true;
}
+
+ /**
+ * Commit options for hg
+ */
+ private class HgCommitAdditionalComponent extends DvcsCommitAdditionalComponent {
+
+ 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);
+ }
+ }
+
+ public void refresh() {
+ super.refresh();
+ myNextCommitAmend = false;
+ }
+
+ public void saveState() {
+ myNextCommitAmend = myAmend.isSelected();
+ }
+
+ public void restoreState() {
+ myNextCommitAmend = false;
+ }
+
+ @NotNull
+ @Override
+ protected Collection<VirtualFile> getRoots() {
+ return HgUtil.getHgRepositories(myProject);
+ }
+
+ @Nullable
+ protected String getLastCommitMessage(@NotNull VirtualFile repo) throws VcsException {
+ HgCommandExecutor commandExecutor = new HgCommandExecutor(myProject);
+ List<String> args = new ArrayList<String>();
+ args.add("-r");
+ args.add(".");
+ args.add("--template");
+ args.add("{desc}");
+ HgCommandResult result = commandExecutor.executeInCurrentThread(repo, "log", args, null);
+ return result == null ? "" : result.getRawOutput();
+ }
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitAndPushExecutor.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitAndPushExecutor.java
index e240b9d..15fb6f1 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitAndPushExecutor.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/commit/HgCommitAndPushExecutor.java
@@ -37,7 +37,7 @@
@NotNull
public CommitSession createCommitSession() {
- myCheckinEnvironment.setNextCommitIsPushed(true);
+ myCheckinEnvironment.setNextCommitIsPushed();
return CommitSession.VCS_COMMIT;
}
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java
index 90c5937..133bfc7 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepoInfo.java
@@ -17,14 +17,12 @@
import com.google.common.base.Objects;
import com.intellij.dvcs.repo.Repository;
+import com.intellij.vcs.log.Hash;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgNameWithHashInfo;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
+import java.util.*;
/**
* @author Nadya Zabrodina
@@ -34,7 +32,7 @@
@Nullable private final String myCurrentRevision;
@NotNull private final Repository.State myState;
@Nullable private String myCurrentBookmark = null;
- @NotNull private Set<HgNameWithHashInfo> myBranches = Collections.emptySet();
+ @NotNull private Map<String, Set<Hash>> myBranches = Collections.emptyMap();
@NotNull private Set<HgNameWithHashInfo> myBookmarks = Collections.emptySet();
@NotNull private Set<HgNameWithHashInfo> myTags = Collections.emptySet();
@NotNull private Set<HgNameWithHashInfo> myLocalTags = Collections.emptySet();
@@ -42,7 +40,7 @@
public HgRepoInfo(@NotNull String currentBranch,
@Nullable String currentRevision,
@NotNull Repository.State state,
- @NotNull Collection<HgNameWithHashInfo> branches,
+ @NotNull Map<String,Set<Hash>> branches,
@NotNull Collection<HgNameWithHashInfo> bookmarks,
@Nullable String currentBookmark,
@NotNull Collection<HgNameWithHashInfo> tags,
@@ -50,7 +48,7 @@
myCurrentBranch = currentBranch;
myCurrentRevision = currentRevision;
myState = state;
- myBranches = new LinkedHashSet<HgNameWithHashInfo>(branches);
+ myBranches = branches;
myBookmarks = new LinkedHashSet<HgNameWithHashInfo>(bookmarks);
myCurrentBookmark = currentBookmark;
myTags = new LinkedHashSet<HgNameWithHashInfo>(tags);
@@ -63,7 +61,7 @@
}
@NotNull
- public Collection<HgNameWithHashInfo> getBranches() {
+ public Map<String, Set<Hash>> getBranches() {
return myBranches;
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java
index fbaaa4f..5b96879 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepository.java
@@ -18,11 +18,14 @@
import com.intellij.dvcs.repo.Repository;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.vcs.log.Hash;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgNameWithHashInfo;
import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
public interface HgRepository extends Repository {
@@ -38,8 +41,17 @@
@NotNull
String getCurrentBranch();
+ /**
+ * @return map with heavy branch names and appropriate set of head hashes
+ */
@NotNull
- Collection<HgNameWithHashInfo> getBranches();
+ Map<String, Set<Hash>> getBranches();
+
+ /**
+ * @return names of opened heavy branches
+ */
+ @NotNull
+ Set<String> getOpenedBranches();
@NotNull
Collection<HgNameWithHashInfo> getBookmarks();
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryFiles.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryFiles.java
index 57870f1..d6ee739 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryFiles.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryFiles.java
@@ -30,8 +30,8 @@
*/
public class HgRepositoryFiles {
- public static final String BRANCHHEADS = "cache/branchheads"; // can be branchheads or branchheads-served after approx 2.5,
- // so check for starting branchheads
+ public static final String BRANCHHEADS = "cache/branch";//branchheads <2.5; branchheads-served >= 2.5 and <2.9; branch2-served >=2.9
+ // so check for starting branch
public static final String BRANCHEADSDIR = "cache";
public static final String MERGE = "merge";
public static final String BRANCH = "branch";
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
index c95eb59..898dbfa 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryImpl.java
@@ -22,13 +22,19 @@
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.vcs.log.Hash;
import org.jetbrains.annotations.NotNull;
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.execution.HgCommandResult;
import org.zmlx.hg4idea.util.HgUtil;
import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
/**
@@ -40,26 +46,31 @@
@NotNull private final HgRepositoryReader myReader;
@NotNull private final VirtualFile myHgDir;
@NotNull private volatile HgRepoInfo myInfo;
+ @NotNull private Set<String> myOpenedBranches = Collections.emptySet();
@NotNull private volatile HgConfig myConfig;
private boolean myIsFresh = true;
@SuppressWarnings("ConstantConditions")
- private HgRepositoryImpl(@NotNull VirtualFile rootDir, @NotNull Project project,
+ private HgRepositoryImpl(@NotNull VirtualFile rootDir, @NotNull HgVcs vcs,
@NotNull Disposable parentDisposable) {
- super(project, rootDir, parentDisposable);
+ super(vcs.getProject(), rootDir, parentDisposable);
myHgDir = rootDir.findChild(HgUtil.DOT_HG);
assert myHgDir != null : ".hg directory wasn't found under " + rootDir.getPresentableUrl();
- myReader = new HgRepositoryReader(project, VfsUtilCore.virtualToIoFile(myHgDir));
- myConfig = HgConfig.getInstance(project, rootDir);
+ myReader = new HgRepositoryReader(vcs, VfsUtilCore.virtualToIoFile(myHgDir));
+ myConfig = HgConfig.getInstance(getProject(), rootDir);
update();
}
@NotNull
public static HgRepository getInstance(@NotNull VirtualFile root, @NotNull Project project,
@NotNull Disposable parentDisposable) {
- HgRepositoryImpl repository = new HgRepositoryImpl(root, project, parentDisposable);
+ HgVcs vcs = HgVcs.getInstance(project);
+ if (vcs == null) {
+ throw new IllegalArgumentException("Vcs not found for project " + project);
+ }
+ HgRepositoryImpl repository = new HgRepositoryImpl(root, vcs, parentDisposable);
repository.setupUpdater();
return repository;
}
@@ -96,10 +107,16 @@
@Override
@NotNull
- public Collection<HgNameWithHashInfo> getBranches() {
+ public Map<String, Set<Hash>> getBranches() {
return myInfo.getBranches();
}
+ @Override
+ @NotNull
+ public Set<String> getOpenedBranches() {
+ return myOpenedBranches;
+ }
+
@NotNull
@Override
public Collection<HgNameWithHashInfo> getBookmarks() {
@@ -142,11 +159,18 @@
// Then blinking and do not work properly;
if (!Disposer.isDisposed(getProject()) && !currentInfo.equals(myInfo)) {
myInfo = currentInfo;
+ myOpenedBranches = updateOpenedBranches();
getProject().getMessageBus().syncPublisher(HgVcs.STATUS_TOPIC).update(getProject(), getRoot());
}
}
@NotNull
+ private Set<String> updateOpenedBranches() {
+ HgCommandResult branchCommandResult = new HgTagBranchCommand(getProject(), getRoot()).collectBranches();
+ return HgTagBranchCommand.collectNames(branchCommandResult);
+ }
+
+ @NotNull
@Override
public String toLogString() {
return String.format("HgRepository " + getRoot() + " : " + myInfo);
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java
index bed7480..e35d789 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/repo/HgRepositoryReader.java
@@ -19,12 +19,13 @@
import com.intellij.dvcs.repo.Repository;
import com.intellij.dvcs.repo.RepositoryUtil;
import com.intellij.openapi.components.ServiceManager;
-import com.intellij.openapi.project.Project;
+import com.intellij.vcs.log.Hash;
import com.intellij.vcs.log.VcsLogObjectsFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgNameWithHashInfo;
import org.zmlx.hg4idea.HgVcs;
+import org.zmlx.hg4idea.util.HgVersion;
import java.io.File;
import java.util.*;
@@ -41,9 +42,11 @@
public class HgRepositoryReader {
private static Pattern HASH_NAME = Pattern.compile("\\s*([0-9a-fA-F]+)\\s+(.+)");
+ private static Pattern HASH_STATUS_NAME = Pattern.compile("\\s*([0-9a-fA-F]+)\\s+\\w\\s+(.+)");
+ //hash + name_or_revision_num; hash + status_character + name_or_revision_num
@NotNull private final File myHgDir; // .hg
- @NotNull private final File myBranchHeadsFile; // .hg/cache/branchheads
+ @NotNull private final File myBranchHeadsFile; // .hg/cache/branch* + part depends on version
@NotNull private final File myCacheDir; // .hg/cache (does not exist before first commit)
@NotNull private final File myCurrentBranch; // .hg/branch
@NotNull private final File myBookmarksFile; //.hg/bookmarks
@@ -51,33 +54,33 @@
@NotNull private final File myTagsFile; //.hgtags - not in .hg directory!!!
@NotNull private final File myLocalTagsFile; // .hg/localtags
@NotNull private final VcsLogObjectsFactory myVcsObjectsFactory;
+ private final boolean myStatusInBranchFile;
- public HgRepositoryReader(@NotNull Project project, @NotNull File hgDir) {
+ public HgRepositoryReader(@NotNull HgVcs vcs, @NotNull File hgDir) {
myHgDir = hgDir;
RepositoryUtil.assertFileExists(myHgDir, ".hg directory not found in " + myHgDir);
+ HgVersion version = vcs.getVersion();
+ myStatusInBranchFile = version.hasBranch2Served();
myCacheDir = new File(myHgDir, "cache");
- myBranchHeadsFile = identifyBranchHeadFile(project, myCacheDir);
+ myBranchHeadsFile = identifyBranchHeadFile(version, myCacheDir);
myCurrentBranch = new File(myHgDir, "branch");
myBookmarksFile = new File(myHgDir, "bookmarks");
myCurrentBookmark = new File(myHgDir, "bookmarks.current");
myLocalTagsFile = new File(myHgDir, "localtags");
myTagsFile = new File(myHgDir.getParentFile(), ".hgtags");
- myVcsObjectsFactory = ServiceManager.getService(project, VcsLogObjectsFactory.class);
+ myVcsObjectsFactory = ServiceManager.getService(vcs.getProject(), VcsLogObjectsFactory.class);
}
/**
* Identify file with branches and heads information depends on hg version;
- *
- * @param project
- * @param parentCacheFile
- * @return
*/
@NotNull
- private static File identifyBranchHeadFile(@NotNull Project project, @NotNull File parentCacheFile) {
- File branchesFile = new File(parentCacheFile, "branchheads-served"); //branchheads-served exist after mercurial 2.5,
- //before 2.5 only branchheads exist
- HgVcs vcs = HgVcs.getInstance(project);
- return vcs != null && vcs.getVersion().hasBranchHeadsServed() ? branchesFile : new File(parentCacheFile, "branchheads");
+ private static File identifyBranchHeadFile(@NotNull HgVersion version, @NotNull File parentCacheFile) {
+ //before 2.5 only branchheads exist; branchheads-served after mercurial 2.5; branch2-served after 2.9;
+ String branchFileName = version.hasBranch2Served()
+ ? "branch2-served"
+ : version.hasBranchHeadsServed() ? "branchheads-served" : "branchheads";
+ return new File(parentCacheFile, branchFileName);
}
/**
@@ -110,23 +113,29 @@
}
@NotNull
- public Collection<HgNameWithHashInfo> readBranches() {
- List<HgNameWithHashInfo> branches = new ArrayList<HgNameWithHashInfo>();
+ public Map<String, Set<Hash>> readBranches() {
+ Map<String, Set<Hash>> branchesWithHashes = new HashMap<String, Set<Hash>>();
// Set<String> branchNames = new HashSet<String>();
if (isBranchInfoAvailable()) {
+ Pattern activeBranchPattern = myStatusInBranchFile ? HASH_STATUS_NAME : HASH_NAME;
String[] branchesWithHeads = RepositoryUtil.tryLoadFile(myBranchHeadsFile).split("\n");
// first one - is a head revision: head hash + head number;
for (int i = 1; i < branchesWithHeads.length; ++i) {
- Matcher matcher = HASH_NAME.matcher(branchesWithHeads[i]);
+ Matcher matcher = activeBranchPattern.matcher(branchesWithHeads[i]);
if (matcher.matches()) {
String name = matcher.group(2);
- // if (branchNames.add(name)) {
- branches.add(new HgNameWithHashInfo(name, myVcsObjectsFactory.createHash(matcher.group(1))));
- //}
+ if (branchesWithHashes.containsKey(name)) {
+ branchesWithHashes.get(name).add(myVcsObjectsFactory.createHash(matcher.group(1)));
+ }
+ else {
+ Set<Hash> hashes = new HashSet<Hash>();
+ hashes.add(myVcsObjectsFactory.createHash(matcher.group(1)));
+ branchesWithHashes.put(name, hashes);
+ }
}
}
}
- return branches;
+ return branchesWithHashes;
}
public boolean isMergeInProgress() {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/HgCurrentBranchStatus.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/HgCurrentBranchStatus.java
deleted file mode 100644
index 7de106d..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/HgCurrentBranchStatus.java
+++ /dev/null
@@ -1,58 +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.status;
-
-import com.intellij.openapi.util.text.StringUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.HgVcsMessages;
-
-import java.util.List;
-
-public class HgCurrentBranchStatus {
-
- private String text;
- private String toolTip;
-
- public HgCurrentBranchStatus() {
- }
-
- public void updateFor(@Nullable String branch, @NotNull List<HgRevisionNumber> parents) {
- StringBuilder parentsBuffer = new StringBuilder();
- String delimiter = "";
- for (HgRevisionNumber parent : parents) {
- String rev = parent.getRevision();
- parentsBuffer.append(delimiter).append(rev);
- delimiter = ", ";
- }
- String parent = parentsBuffer.toString();
- String statusText =
- !StringUtil.isEmptyOrSpaces(branch) ? HgVcsMessages.message("hg4idea.status.currentSituationText", branch, parent) : "";
-
- String toolTipText =
- !StringUtil.isEmptyOrSpaces(statusText) ? HgVcsMessages.message("hg4idea.status.currentSituation.description", branch, parent) : "";
-
- text = statusText;
- toolTip = toolTipText;
- }
-
- public String getStatusText() {
- return text;
- }
-
- public String getToolTipText() {
- return toolTip;
- }
-
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgCurrentBranchStatusUpdater.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgCurrentBranchStatusUpdater.java
deleted file mode 100644
index d0a49aa..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgCurrentBranchStatusUpdater.java
+++ /dev/null
@@ -1,114 +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.status.ui;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.editor.Document;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.fileEditor.FileDocumentManager;
-import com.intellij.openapi.fileEditor.FileEditorManager;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.messages.MessageBusConnection;
-import com.intellij.util.ui.UIUtil;
-import com.intellij.vcsUtil.VcsUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.HgUpdater;
-import org.zmlx.hg4idea.HgVcs;
-import org.zmlx.hg4idea.command.HgTagBranchCommand;
-import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
-import org.zmlx.hg4idea.status.HgCurrentBranchStatus;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicReference;
-
-public class HgCurrentBranchStatusUpdater implements HgUpdater {
-
- private final HgVcs vcs;
- private final HgCurrentBranchStatus currentBranchStatus;
-
- private MessageBusConnection busConnection;
-
- public HgCurrentBranchStatusUpdater(HgVcs vcs, HgCurrentBranchStatus currentBranchStatus) {
- this.vcs = vcs;
- this.currentBranchStatus = currentBranchStatus;
- }
-
- @Override
- public void update(final Project project, @Nullable VirtualFile root) {
- update(project);
- }
-
- public void update(final Project project) {
- final AtomicReference<Editor> textEditor = new AtomicReference<Editor>();
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- public void run() {
- textEditor.set(FileEditorManager.getInstance(project).getSelectedTextEditor());
- }
- });
- }
- });
-
- if (textEditor.get() == null) {
- handleUpdate(project, null, Collections.<HgRevisionNumber>emptyList());
- }
- else {
- if (project.isDisposed()) {
- return;
- }
- Document document = textEditor.get().getDocument();
- VirtualFile file = FileDocumentManager.getInstance().getFile(document);
-
- final VirtualFile repo = VcsUtil.getVcsRootFor(project, file);
- if (repo != null) {
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
- @Override
- public void run() {
- HgTagBranchCommand hgTagBranchCommand = new HgTagBranchCommand(project, repo);
- final String branch = hgTagBranchCommand.getCurrentBranch();
- final List<HgRevisionNumber> parents = new HgWorkingCopyRevisionsCommand(project).parents(repo);
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- handleUpdate(project, branch, parents);
- }
- });
- }
- });
- }
- }
- }
-
- private void handleUpdate(@NotNull Project project, @Nullable String branch, @NotNull List<HgRevisionNumber> parents) {
- currentBranchStatus.updateFor(branch, parents);
- if (!project.isDisposed()) {
- project.getMessageBus().syncPublisher(HgVcs.STATUS_TOPIC).update(project, null);
- }
- }
-
- public void activate() {
- busConnection = vcs.getProject().getMessageBus().connect();
- busConnection.subscribe(HgVcs.BRANCH_TOPIC, this);
- }
-
- public void deactivate() {
- busConnection.disconnect();
- }
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
index dad66a0..05a6233 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/status/ui/HgStatusWidget.java
@@ -16,7 +16,6 @@
package org.zmlx.hg4idea.status.ui;
import com.intellij.dvcs.DvcsUtil;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.FileEditorManagerEvent;
import com.intellij.openapi.project.Project;
@@ -27,14 +26,14 @@
import com.intellij.openapi.wm.impl.status.EditorBasedWidget;
import com.intellij.util.Consumer;
import com.intellij.util.messages.MessageBusConnection;
+import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgProjectSettings;
import org.zmlx.hg4idea.HgUpdater;
import org.zmlx.hg4idea.HgVcs;
import org.zmlx.hg4idea.action.HgBranchPopup;
-import org.zmlx.hg4idea.repo.HgRepositoryImpl;
-import org.zmlx.hg4idea.status.HgCurrentBranchStatus;
+import org.zmlx.hg4idea.repo.HgRepository;
import org.zmlx.hg4idea.util.HgUtil;
import java.awt.event.MouseEvent;
@@ -46,11 +45,10 @@
implements StatusBarWidget.MultipleTextValuesPresentation,
StatusBarWidget.Multiframe, HgUpdater {
- private static final String MAX_STRING = "hg: default branch (128)";
+ private static final String MAX_STRING = "Hg: Merging default ";
@NotNull private final HgVcs myVcs;
@NotNull private final HgProjectSettings myProjectSettings;
- @NotNull private final HgCurrentBranchStatus myCurrentBranchStatus;
private volatile String myText = "";
private volatile String myTooltip = "";
@@ -59,8 +57,6 @@
super(project);
myVcs = vcs;
myProjectSettings = projectSettings;
-
- myCurrentBranchStatus = new HgCurrentBranchStatus();
}
@Override
@@ -101,8 +97,9 @@
return null;
}
VirtualFile root = HgUtil.getRootForSelectedFile(project);
- if (root != null) {
- return HgBranchPopup.getInstance(project, HgRepositoryImpl.getInstance(root, project, project)).asListPopup();
+ HgRepository repository = HgUtil.getRepositoryManager(project).getRepositoryForRoot(root);
+ if (repository != null) {
+ return HgBranchPopup.getInstance(project, repository).asListPopup();
}
return null;
}
@@ -143,7 +140,7 @@
}
public void update(final Project project) {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
if ((project == null) || project.isDisposed()) {
@@ -151,15 +148,13 @@
return;
}
- emptyTextAndTooltip();
-
- if (null != myCurrentBranchStatus.getStatusText()) {
- myText = myCurrentBranchStatus.getStatusText();
- myTooltip = myCurrentBranchStatus.getToolTipText();
+ final HgRepository repo = HgUtil.getCurrentRepository(project);
+ if (repo == null) { // the file is not under version control => display nothing
+ emptyTextAndTooltip();
+ return;
}
-
- int maxLength = MAX_STRING.length();
- myText = StringUtil.shortenTextWithEllipsis(myText, maxLength, 5);
+ myTooltip = HgUtil.getDisplayableBranchOrBookmarkText(repo);
+ myText = StringUtil.shortenTextWithEllipsis(myTooltip, MAX_STRING.length(), 5);
if (!isDisposed() && myStatusBar != null) {
myStatusBar.updateWidget(ID());
}
@@ -176,6 +171,7 @@
MessageBusConnection busConnection = project.getMessageBus().connect();
busConnection.subscribe(HgVcs.STATUS_TOPIC, this);
+ busConnection.subscribe(HgVcs.BRANCH_TOPIC,this);
DvcsUtil.installStatusBarWidget(myProject, this);
}
@@ -198,9 +194,4 @@
myText = "";
myTooltip = "";
}
-
- @NotNull
- public HgCurrentBranchStatus getCurrentBranchStatus() {
- return myCurrentBranchStatus;
- }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form
deleted file mode 100644
index a06a928..0000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.form
+++ /dev/null
@@ -1,84 +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.HgCloneDialog">
- <grid id="27dc6" binding="clonePanel" layout-manager="GridLayoutManager" row-count="4" column-count="4" 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="644" height="99"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="7e816" class="javax.swing.JLabel">
- <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="9bab4"/>
- <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.clone.repository.url"/>
- </properties>
- </component>
- <vspacer id="86a0f">
- <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"/>
- </constraints>
- </vspacer>
- <hspacer id="a0290">
- <constraints>
- <grid row="3" column="1" row-span="1" col-span="3" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- </hspacer>
- <component id="9bab4" class="javax.swing.JTextField" binding="repositoryURL">
- <constraints>
- <grid row="0" column="1" row-span="1" col-span="2" 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="1422b" class="javax.swing.JLabel">
- <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 resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.clone.parent.directory"/>
- </properties>
- </component>
- <component id="876a6" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="parentDirectory">
- <constraints>
- <grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- </component>
- <component id="2002c" 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>
- <labelFor value="4e988"/>
- <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.clone.directory.name"/>
- </properties>
- </component>
- <component id="fbda8" class="javax.swing.JButton" binding="testButton">
- <constraints>
- <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.clone.button.test"/>
- </properties>
- </component>
- <component id="4e988" class="javax.swing.JTextField" binding="directoryName">
- <constraints>
- <grid row="2" 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>
- <hspacer id="e781a">
- <constraints>
- <grid row="2" column="2" row-span="1" col-span="2" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- </hspacer>
- </children>
- </grid>
-</form>
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java
index e5c0d49..57033d0 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgCloneDialog.java
@@ -15,337 +15,58 @@
*/
package org.zmlx.hg4idea.ui;
+import com.intellij.dvcs.DvcsRememberedInputs;
+import com.intellij.dvcs.ui.CloneDvcsDialog;
+import com.intellij.dvcs.ui.DvcsBundle;
import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.*;
-import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.HgVcsMessages;
+import org.zmlx.hg4idea.HgRememberedInputs;
import org.zmlx.hg4idea.command.HgIdentifyCommand;
import org.zmlx.hg4idea.execution.HgCommandResult;
-
-import javax.swing.*;
-import javax.swing.event.DocumentEvent;
-import javax.swing.event.DocumentListener;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.net.URI;
-import java.net.URISyntaxException;
+import org.zmlx.hg4idea.util.HgUtil;
/**
* A dialog for the mercurial clone options
*/
-public class HgCloneDialog extends DialogWrapper {
+public class HgCloneDialog extends CloneDvcsDialog {
- /**
- * repository URL
- */
- private JTextField repositoryURL;
- /**
- * parent directory
- */
- private TextFieldWithBrowseButton parentDirectory;
- /**
- * test repository URL button
- */
- private JButton testButton;
- /**
- * the repository URL at the time of the last test
- */
- private String testURL;
- /**
- * the test result of the last test or null if not tested
- */
- private Boolean testResult;
- /**
- * directory name button
- */
- private JTextField directoryName;
- /**
- * current default directory name
- */
- private String defaultDirectoryName = "";
- /**
- * panel that wraps it all
- */
- private JPanel clonePanel;
- /**
- * the project for checkout
- */
- private final Project project;
-
- /**
- * A constructor
- *
- * @param project a project for checkout action
- */
- public HgCloneDialog(Project project) {
- super(project, true);
- this.project = project;
- init();
- initListeners();
- setTitle(HgVcsMessages.message("hg4idea.clone.title"));
- setOKButtonText(HgVcsMessages.message("hg4idea.clone.button.clone"));
+ public HgCloneDialog(@NotNull Project project) {
+ super(project, HgUtil.DOT_HG);
}
- /**
- * @return the URL of the source repository
- */
- public String getSourceRepositoryURL() {
- return repositoryURL.getText();
- }
-
- /**
- * @return the parent directory for checkout
- */
- public String getParentDirectory() {
- return parentDirectory.getText();
- }
-
- /**
- * @return the directory name to checkout to
- */
- public String getDirectoryName() {
- return directoryName.getText();
- }
-
- /**
- * Init components
- */
- private void initListeners() {
- FileChooserDescriptor fcd = FileChooserDescriptorFactory.createSingleFolderDescriptor();
- fcd.setShowFileSystemRoots(true);
- fcd.setTitle(HgVcsMessages.message("hg4idea.clone.parent.directory.title"));
- fcd.setDescription(HgVcsMessages.message("hg4idea.clone.parent.directory.description"));
- fcd.setHideIgnored(false);
- parentDirectory.addActionListener(
- new ComponentWithBrowseButton.BrowseFolderActionListener<JTextField>(fcd.getTitle(), fcd.getDescription(), parentDirectory,
- project, fcd, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT) {
- @Override
- protected VirtualFile getInitialFile() {
- // suggest project base directory only if nothing is typed in the component.
- String text = getComponentText();
- if (text.length() == 0) {
- VirtualFile file = project.getBaseDir();
- if (file != null) {
- return file;
- }
- }
- return super.getInitialFile();
- }
- });
- final DocumentListener updateOkButtonListener = new DocumentListener() {
- // update Ok button state depending on the current state of the fields
- public void insertUpdate(final DocumentEvent e) {
- updateCloneButton();
- }
-
- public void removeUpdate(final DocumentEvent e) {
- updateCloneButton();
- }
-
- public void changedUpdate(final DocumentEvent e) {
- updateCloneButton();
- }
- };
- parentDirectory.getChildComponent().getDocument().addDocumentListener(updateOkButtonListener);
- directoryName.getDocument().addDocumentListener(updateOkButtonListener);
- repositoryURL.getDocument().addDocumentListener(new DocumentListener() {
- // enable test button only if something is entered in repository URL
- public void insertUpdate(final DocumentEvent e) {
- changed();
- }
-
- public void removeUpdate(final DocumentEvent e) {
- changed();
- }
-
- public void changedUpdate(final DocumentEvent e) {
- changed();
- }
-
- private void changed() {
- final String url = repositoryURL.getText();
- testButton.setEnabled(url.length() != 0);
- if (defaultDirectoryName.equals(directoryName.getText()) || directoryName.getText().length() == 0) {
- // modify field if it was unmodified or blank
- defaultDirectoryName = defaultDirectoryName(url);
- directoryName.setText(defaultDirectoryName);
- }
- updateCloneButton();
- }
- });
-
- testButton.addActionListener(new ActionListener() {
- public void actionPerformed(final ActionEvent e) {
- testURL = repositoryURL.getText();
- ProgressManager.getInstance().run(new Task.Modal(project, HgVcsMessages.message("hg4idea.clone.test.progress", testURL), true) {
- @Override
- public void run(@NotNull ProgressIndicator indicator) {
- testResult = testRepository(project, testURL, indicator.getModalityState());
- }
- });
- if (testResult) {
- Messages.showInfoMessage(testButton, HgVcsMessages.message("hg4idea.clone.test.success.message", testURL),
- HgVcsMessages.message("hg4idea.clone.test.success"));
- }
- updateCloneButton();
- }
- });
-
- setOKActionEnabled(false);
- }
-
- /**
- * Check fields and display error in the wrapper if there is a problem
- */
- private void updateCloneButton() {
- if (!checkRepositoryURL()) {
- return;
- }
- if (!checkDestination()) {
- return;
- }
- setErrorText(null);
- setOKActionEnabled(true);
- }
-
- /**
- * Check destination directory and set appropriate error text if there are problems
- *
- * @return true if destination components are OK.
- */
- private boolean checkDestination() {
- if (parentDirectory.getText().length() == 0 || directoryName.getText().length() == 0) {
- setErrorText(null);
- setOKActionEnabled(false);
- return false;
- }
- File file = new File(parentDirectory.getText(), directoryName.getText());
- if (file.exists()) {
- setErrorText(HgVcsMessages.message("hg4idea.clone.error.destination.directory.exists", file));
- setOKActionEnabled(false);
- return false;
- } else if (!file.getParentFile().exists()) {
- setErrorText(HgVcsMessages.message("hg4idea.clone.error.parent.directory.missing", file.getParent()));
- setOKActionEnabled(false);
- return false;
- }
- return true;
- }
-
- /**
- * Check repository URL and set appropriate error text if there are problems
- *
- * @return true if repository URL is OK.
- */
- private boolean checkRepositoryURL() {
- String repository = repositoryURL.getText();
- if (repository.length() == 0) {
- setErrorText(null);
- setOKActionEnabled(false);
- return false;
- }
- if (testResult != null && repository.equals(testURL)) {
- if (!testResult) {
- setErrorText(HgVcsMessages.message("hg4idea.clone.error.test.failed"));
- setOKActionEnabled(false);
- return false;
- } else {
- return true;
- }
- }
- try {
- if (new URI(repository).isAbsolute()) {
- return true;
- }
- }
- catch (URISyntaxException urlExp) {
- // do nothing
- }
- try {
- File file = new File(repository);
- if (file.exists()) {
- if (!file.isDirectory()) {
- setErrorText(HgVcsMessages.message("hg4idea.clone.error.repository.url.is.not.directory"));
- setOKActionEnabled(false);
- }
- return true;
- }
- }
- catch (Exception fileExp) {
- // do nothing
- }
- setErrorText(HgVcsMessages.message("hg4idea.clone.error.repository.url"));
- setOKActionEnabled(false);
- return false;
- }
-
- /**
- * Get default name for checked out directory
- *
- * @param url an URL to checkout
- * @return a default repository name
- */
- private static String defaultDirectoryName(final String url) {
- String nonSystemName;
- //noinspection HardCodedStringLiteral
- if (url.endsWith("/.hg") || url.endsWith(File.separator + ".hg")) {
- nonSystemName = url.substring(0, url.length() - 5);
- } else {
- //noinspection HardCodedStringLiteral
- if (url.endsWith(".hg")) {
- nonSystemName = url.substring(0, url.length() - 4);
- } else {
- nonSystemName = url;
- }
- }
- int i = nonSystemName.lastIndexOf('/');
- if (i == -1 && File.separatorChar != '/') {
- i = nonSystemName.lastIndexOf(File.separatorChar);
- }
- return i >= 0 ? nonSystemName.substring(i + 1) : "";
- }
-
- /**
- * {@inheritDoc}
- */
- protected JComponent createCenterPanel() {
- return clonePanel;
- }
-
- /**
- * {@inheritDoc}
- */
@Override
protected String getDimensionServiceKey() {
return "HgCloneDialog";
}
@Override
- public JComponent getPreferredFocusedComponent() {
- return repositoryURL;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
protected String getHelpId() {
return "reference.mercurial.clone.mercurial.repository";
}
- private static boolean testRepository(Project project, final String repositoryUrl, @NotNull ModalityState state) {
- final HgIdentifyCommand identifyCommand = new HgIdentifyCommand(project);
- identifyCommand.setSource(repositoryUrl);
- final HgCommandResult result = identifyCommand.execute(state);
- return result != null && result.getExitValue() == 0;
+ @NotNull
+ @Override
+ protected DvcsRememberedInputs getRememberedInputs() {
+ return ServiceManager.getService(HgRememberedInputs.class);
}
+ @Override
+ protected boolean test(@NotNull final String url) {
+ final boolean[] testResult = new boolean[1];
+ ProgressManager.getInstance().run(new Task.Modal(myProject, DvcsBundle.message("clone.testing", url), true) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ final HgIdentifyCommand identifyCommand = new HgIdentifyCommand(myProject);
+ identifyCommand.setSource(url);
+ final HgCommandResult result = identifyCommand.execute(ModalityState.stateForComponent(getRootPane()));
+ testResult[0] = result != null && result.getExitValue() == 0;
+ }
+ });
+ return testResult[0];
+ }
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form
index 206d010..a9fbc33 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.form
@@ -3,7 +3,7 @@
<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="339" height="228"/>
+ <xy x="20" y="20" width="623" height="228"/>
</constraints>
<properties/>
<border type="none"/>
@@ -30,7 +30,7 @@
</component>
</children>
</grid>
- <grid id="4e3f3" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="4e3f3" layout-manager="GridLayoutManager" row-count="1" 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="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -59,6 +59,16 @@
<text value="&Specify executable path"/>
</properties>
</component>
+ <component id="61549" class="javax.swing.JButton" binding="myTestButton">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="2" hsize-policy="0" anchor="4" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <horizontalAlignment value="0"/>
+ <label resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.configuration.test.label"/>
+ <text resource-bundle="org/zmlx/hg4idea/HgVcsMessages" key="hg4idea.configuration.test"/>
+ </properties>
+ </component>
</children>
</grid>
<vspacer id="4088f">
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java
index 3398aa9..d906808 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgConfigurationProjectPanel.java
@@ -14,15 +14,18 @@
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgProjectSettings;
import org.zmlx.hg4idea.HgVcs;
import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.util.HgUtil;
+import org.zmlx.hg4idea.util.HgVersion;
import javax.swing.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
public class HgConfigurationProjectPanel {
@@ -31,12 +34,29 @@
private JPanel myMainPanel;
private JCheckBox myCheckIncomingOutgoingCbx;
private TextFieldWithBrowseButton myPathSelector;
+ private JButton myTestButton;
private final HgVcs myVcs;
- public HgConfigurationProjectPanel(@NotNull HgProjectSettings projectSettings, @Nullable Project project) {
+ public HgConfigurationProjectPanel(@NotNull HgProjectSettings projectSettings, @NotNull Project project) {
myProjectSettings = projectSettings;
myVcs = HgVcs.getInstance(project);
loadSettings();
+ myTestButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ String executable = getCurrentPath();
+ HgVersion version;
+ try {
+ version = HgVersion.identifyVersion(executable);
+ }
+ catch (Exception exception) {
+ Messages.showErrorDialog(myMainPanel, exception.getMessage(), HgVcsMessages.message("hg4idea.run.failed.title"));
+ return;
+ }
+ Messages.showInfoMessage(myMainPanel, String.format("Mercurial version is %s", version.toString()),
+ HgVcsMessages.message("hg4idea.run.success.title")
+ );
+ }
+ });
}
public boolean isModified() {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form
index feca813..5a9411c 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.form
@@ -84,7 +84,7 @@
</constraints>
<properties>
<selected value="false"/>
- <text value="&Other head"/>
+ <text value="&Other head:"/>
<toolTipText value="There is exactly one other head on this branch"/>
</properties>
</component>
@@ -93,7 +93,7 @@
<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="Other head: "/>
+ <text value=""/>
</properties>
</component>
<component id="dc07f" class="javax.swing.JRadioButton" binding="bookmarkOption">
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
index fa6114c..f41972a 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgMergeDialog.java
@@ -19,7 +19,6 @@
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;
import org.zmlx.hg4idea.HgRevisionNumber;
-import org.zmlx.hg4idea.HgVcsMessages;
import org.zmlx.hg4idea.command.HgHeadsCommand;
import org.zmlx.hg4idea.command.HgTagBranch;
import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
@@ -158,7 +157,7 @@
otherHeadRadioButton.setVisible(true);
otherHeadLabel.setVisible(true);
otherHead = heads.get(0);
- otherHeadLabel.setText(HgVcsMessages.message("hg4idea.integrate.other.head", otherHead.asString()));
+ otherHeadLabel.setText(" " + otherHead.asString());
}
});
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
index 6705058..5b4af4a 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPullDialog.java
@@ -12,6 +12,7 @@
// limitations under the License.
package org.zmlx.hg4idea.ui;
+import com.intellij.dvcs.DvcsRememberedInputs;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.event.DocumentAdapter;
import com.intellij.openapi.editor.event.DocumentEvent;
@@ -56,8 +57,8 @@
public void createUIComponents() {
myRepositoryURL = new EditorComboBox("");
- final HgRememberedInputs rememberedInputs = HgRememberedInputs.getInstance(project);
- myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getRepositoryUrls(), String.class));
+ final DvcsRememberedInputs rememberedInputs = HgRememberedInputs.getInstance();
+ myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getVisitedUrls(), String.class));
myRepositoryURL.addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(DocumentEvent e) {
@@ -74,11 +75,10 @@
}
public void rememberSettings() {
- final HgRememberedInputs rememberedInputs = HgRememberedInputs.getInstance(project);
- rememberedInputs.addRepositoryUrl(HgUtil.removePasswordIfNeeded(getSource()));
+ final DvcsRememberedInputs rememberedInputs = HgRememberedInputs.getInstance();
+ rememberedInputs.addUrl(HgUtil.removePasswordIfNeeded(getSource()));
}
-
public VirtualFile getRepository() {
return hgRepositorySelector.getRepository();
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
index d9974b2..7660494 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/ui/HgPushDialog.java
@@ -12,6 +12,7 @@
// limitations under the License.
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;
@@ -82,8 +83,8 @@
public void createUIComponents() {
myRepositoryURL = new EditorComboBox("");
- final HgRememberedInputs rememberedInputs = HgRememberedInputs.getInstance(myProject);
- myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getRepositoryUrls(), String.class));
+ final DvcsRememberedInputs rememberedInputs = HgRememberedInputs.getInstance();
+ myRepositoryURL.setHistory(ArrayUtil.toObjectArray(rememberedInputs.getVisitedUrls(), String.class));
myRepositoryURL.addDocumentListener(new DocumentAdapter() {
@Override
public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent e) {
@@ -187,8 +188,8 @@
}
public void rememberSettings() {
- final HgRememberedInputs rememberedInputs = HgRememberedInputs.getInstance(myProject);
- rememberedInputs.addRepositoryUrl(HgUtil.removePasswordIfNeeded(myRepositoryURL.getText()));
+ final DvcsRememberedInputs rememberedInputs = HgRememberedInputs.getInstance();
+ rememberedInputs.addUrl(HgUtil.removePasswordIfNeeded(myRepositoryURL.getText()));
}
/**
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java
index af7d0c2..5afd008 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgEncodingUtil.java
@@ -18,13 +18,11 @@
if (HGENCODING != null && HGENCODING.length() > 0 && Charset.isSupported(HGENCODING)) {
return Charset.forName(HGENCODING);
}
- else {
- Charset defaultCharset = EncodingProjectManager.getInstance(project).getDefaultCharset();
- if (defaultCharset != null) {
- return defaultCharset;
- }
+ Charset defaultCharset = null;
+ if (!project.isDisposed()) {
+ defaultCharset = EncodingProjectManager.getInstance(project).getDefaultCharset();
}
- return Charset.defaultCharset();
+ return defaultCharset != null ? defaultCharset : Charset.defaultCharset();
}
@NotNull
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java
index 7deafd2..2847323 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgHistoryUtil.java
@@ -17,11 +17,11 @@
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FileStatus;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.SmartList;
@@ -58,7 +58,7 @@
@NotNull
public static List<VcsFullCommitDetails> history(@NotNull final Project project,
@NotNull final VirtualFile root, int limit,
- String... parameters)
+ List<String> parameters)
throws VcsException {
List<HgCommittedChangeList> result = getCommittedChangeList(project, root, limit, true, parameters);
return ContainerUtil.mapNotNull(result, new Function<HgCommittedChangeList, VcsFullCommitDetails>() {
@@ -72,18 +72,19 @@
@NotNull
private static List<HgCommittedChangeList> getCommittedChangeList(@NotNull final Project project,
@NotNull final VirtualFile root, int limit, boolean withFiles,
- String... parameters) {
+ List<String> parameters) {
HgFile hgFile = new HgFile(root, VcsUtil.getFilePath(root.getPath()));
- List<String> args = ContainerUtil.newArrayList(parameters);
- args.add("--debug");
List<HgCommittedChangeList> result = new LinkedList<HgCommittedChangeList>();
final List<HgFileRevision> localRevisions;
HgLogCommand hgLogCommand = new HgLogCommand(project);
-
+ List<String> args = new ArrayList<String>(parameters);
hgLogCommand.setLogFile(false);
HgVcs hgvcs = HgVcs.getInstance(project);
assert hgvcs != null;
try {
+ if (!hgvcs.getVersion().isParentRevisionTemplateSupported()) {
+ args.add("--debug");
+ }
localRevisions = hgLogCommand.execute(hgFile, limit, withFiles, args);
}
catch (HgCommandException e) {
@@ -144,7 +145,7 @@
@NotNull final Consumer<VcsUser> userRegistry) throws VcsException {
final VcsLogObjectsFactory factory = ServiceManager.getService(project, VcsLogObjectsFactory.class);
- return ContainerUtil.map(getCommittedChangeList(project, root, -1, false, ""), new Function<HgCommittedChangeList, TimedVcsCommit>() {
+ return ContainerUtil.map(getCommittedChangeList(project, root, -1, false, Collections.<String>emptyList()), new Function<HgCommittedChangeList, TimedVcsCommit>() {
@Override
public TimedVcsCommit fun(HgCommittedChangeList record) {
HgRevisionNumber revNumber = (HgRevisionNumber)record.getRevisionNumber();
@@ -195,40 +196,35 @@
}
@Nullable
- public static String[] prepareHashes(@NotNull List<String> hashes) {
- if (hashes.isEmpty()) {
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
- StringBuilder builder = new StringBuilder();
+ public static List<String> prepareHashes(@NotNull List<String> hashes) {
+ List<String> hashArgs = new ArrayList<String>();
for (String hash : hashes) {
- builder.append(hash).append('+');
+ hashArgs.add("-r");
+ hashArgs.add(hash);
}
- builder.deleteCharAt(builder.length() - 1);
- //todo change ugly style
- return new String[]{"--rev", builder.toString()};
+ return hashArgs;
}
@NotNull
public static Collection<String> getDescendingHeadsOfBranches(@NotNull Project project, @NotNull VirtualFile root, @NotNull Hash hash)
throws VcsException {
- //hg log -r "descendants(659db54c1b6865c97c4497fa867194bcd759ca76) and head() " --template "{branch} {bookmarks}\n"
+ //hg log -r "descendants(659db54c1b6865c97c4497fa867194bcd759ca76) and head()" --template "{branch}{bookmarks}"
Set<String> branchHeads = new HashSet<String>();
List<String> params = new ArrayList<String>();
params.add("-r");
params.add("descendants(" + hash.asString() + ") and head()");
- HgFile hgFile = new HgFile(root, VcsUtil.getFilePath(root.getPath()));
HgLogCommand hgLogCommand = new HgLogCommand(project);
hgLogCommand.setLogFile(false);
String template = HgChangesetUtil.makeTemplate("{branch}", "{bookmarks}");
- HgCommandResult logResult = hgLogCommand.execute(root, template, -1, hgFile, params);
+ HgCommandResult logResult = hgLogCommand.execute(root, template, -1, null, params);
if (logResult == null || logResult.getExitValue() != 0) {
throw new VcsException("Couldn't get commit details: log command execution error.");
}
String output = logResult.getRawOutput();
- String[] changeSets = output.split(HgChangesetUtil.CHANGESET_SEPARATOR);
+ List<String> changeSets = StringUtil.split(output, HgChangesetUtil.CHANGESET_SEPARATOR);
for (String line : changeSets) {
- String[] attributes = line.split(HgChangesetUtil.ITEM_SEPARATOR);
- branchHeads.addAll(Arrays.asList(attributes));
+ List<String> attributes = StringUtil.split(line, HgChangesetUtil.ITEM_SEPARATOR);
+ branchHeads.addAll(attributes);
}
return branchHeads;
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
index 61dd6a7..fd0fc50 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgUtil.java
@@ -12,6 +12,7 @@
// limitations under the License.
package org.zmlx.hg4idea.util;
+import com.intellij.dvcs.DvcsUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
@@ -23,6 +24,7 @@
import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -38,8 +40,6 @@
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.status.StatusBarUtil;
import com.intellij.ui.GuiUtils;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -551,13 +551,18 @@
return path;
}
- public static String getDisplayableBranchText(HgRepository repository) {
+ @NotNull
+ public static String getDisplayableBranchOrBookmarkText(@NotNull HgRepository repository) {
HgRepository.State state = repository.getState();
String branchText = "";
if (state == HgRepository.State.MERGING) {
branchText += state.toString() + " ";
}
- return branchText + repository.getCurrentBranch();
+ String branchOrBookMarkName = repository.getCurrentBookmark();
+ if (StringUtil.isEmptyOrSpaces(branchOrBookMarkName)) {
+ branchOrBookMarkName = repository.getCurrentBranch();
+ }
+ return branchText + branchOrBookMarkName;
}
@NotNull
@@ -566,6 +571,17 @@
}
@Nullable
+ public static HgRepository getCurrentRepository(@NotNull Project project) {
+ HgRepositoryManager repositoryManager = getRepositoryManager(project);
+ VirtualFile file = DvcsUtil.getSelectedFile(project);
+ if (file == null) {
+ return null;
+ }
+ VirtualFile root = getHgRootOrNull(project, file);
+ return repositoryManager.getRepositoryForRoot(root);
+ }
+
+ @Nullable
public static String getRepositoryDefaultPath(@NotNull Project project, @NotNull VirtualFile root) {
HgRepository hgRepository = getRepositoryManager(project).getRepositoryForRoot(root);
assert hgRepository != null : "Repository can't be null for root " + root.getName();
@@ -603,7 +619,7 @@
return false;
}
HgCommandResult result = getVersionOutput(executable);
- return result.getRawError().isEmpty();
+ return result.getExitValue() == 0 && !result.getRawOutput().isEmpty();
}
catch (Throwable e) {
LOG.info("Error during hg executable validation: ", e);
@@ -619,7 +635,7 @@
cmdArgs.add("version");
cmdArgs.add("-q");
ShellCommand shellCommand = new ShellCommand(cmdArgs, null, CharsetToolkit.getDefaultSystemCharset());
- return shellCommand.execute();
+ return shellCommand.execute(false);
}
public static List<String> getNamesWithoutHashes(Collection<HgNameWithHashInfo> namesWithHashes) {
@@ -634,33 +650,29 @@
}
@NotNull
- public static List<String> parseUserNameAndEmail(String authorString) {
- //maybe return value should be a pair of String not an array
- List<String> userInfoList = new ArrayList<String>(2);
- if (authorString == null) {
- return Arrays.asList("", "");
- }
-
+ public static Pair<String, String> parseUserNameAndEmail(@NotNull String authorString) {
// Vasya Pupkin <vasya.pupkin@jetbrains.com> -> Vasya Pupkin , vasya.pupkin@jetbrains.com
- final int[] ind = {authorString.indexOf('<'), authorString.indexOf('@'), authorString.indexOf('>')};
- if (0 < ind[0] && ind[0] < ind[1] && ind[1] < ind[2]) {
- String email = authorString.substring(ind[0] + 1, ind[2]).trim();
- userInfoList.add(convertUserName(authorString.substring(0, ind[0])));
- userInfoList.add(email);
+ int startEmailIndex = authorString.indexOf('<');
+ int startDomainIndex = authorString.indexOf('@');
+ int endEmailIndex = authorString.indexOf('>');
+ String userName;
+ String email;
+ if (0 < startEmailIndex && startEmailIndex < startDomainIndex && startDomainIndex < endEmailIndex) {
+ email = authorString.substring(startEmailIndex + 1, endEmailIndex);
+ userName = convertUserName(authorString.substring(0, startEmailIndex));
}
// vasya.pupkin@email.com --> vasya pupkin, vasya.pupkin@email.com
- else if (!authorString.contains(" ") && authorString.contains("@")) { //simple e-mail check. john@localhost
- final String firstPart = convertUserName(authorString.substring(0, authorString.indexOf('@')));
- userInfoList.add(firstPart); //user name
- userInfoList.add(authorString);// email
+ else if (!authorString.contains(" ") && startDomainIndex > 0) { //simple e-mail check. john@localhost
+ userName = convertUserName(authorString.substring(0, startDomainIndex));
+ email = authorString;
}
else {
- userInfoList.add(convertUserName(authorString));
- userInfoList.add("");
+ userName = convertUserName(authorString);
+ email = "";
}
- return userInfoList;
+ return Pair.create(userName, email);
}
private static String convertUserName(@NotNull String userNameInfo) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java
index c869ffd..910a1a7 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/util/HgVersion.java
@@ -24,6 +24,10 @@
import org.zmlx.hg4idea.execution.ShellCommandException;
import java.text.ParseException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -37,7 +41,8 @@
private static final Pattern HG_VERSION_PATTERN =
Pattern.compile(".+\\(\\s*\\S+\\s+(\\d+)\\.(\\d+)[\\.]?(\\d)?.*\\s*\\)\\s*.*\\s*", Pattern.CASE_INSENSITIVE);
//f.e. Mercurial Distributed SCM (version 2.6+20130507) or Mercurial Distributed SCM (version 2.6.2), 2.7-rc+5-ca2dfc2f63eb
-
+ private static final Pattern HG_UNSUPPORTED_EXTENSION =
+ Pattern.compile("\\*\\*\\*\\s*failed to import\\s+extension\\s+([a-zA-z0-9\\.-]+).*", Pattern.CASE_INSENSITIVE);
/**
* The minimal supported version
*/
@@ -48,7 +53,9 @@
// since 2.3 - 2.5.3 hg has bug with join function with file_copies
// see http://mercurial.808500.n3.nabble.com/Bug-3887-New-hg-log-template-quot-rev-join-file-copies-n-quot-prints-literal-quot-sourcename-quot-fos-td4000129.html
public static final HgVersion BUILT_IN_FUNCTION_SUPPORTED = new HgVersion(2, 6, 0);
+ public static final HgVersion PARENT_REVISION_TEMPLATES_SUPPORTED = new HgVersion(2, 4, 0);
public static final HgVersion BRANCH_HEADS_SERVED_FILE_EXIST = new HgVersion(2, 5, 0);
+ public static final HgVersion BRANCH2_SERVED_FILE_EXIST = new HgVersion(2, 9, 0);
//see http://selenic.com/pipermail/mercurial-devel/2013-May/051209.html fixed since 2.7
private static final HgVersion LARGEFILES_WITH_FOLLOW_SUPPORTED = new HgVersion(2, 7, 0);
@@ -61,30 +68,57 @@
private final int myMajor;
private final int myMiddle;
private final int myMinor; //use only first digit after second dot
+ @NotNull private final Set<String> myUnsupportedExtensions;
public HgVersion(int major, int middle, int minor) {
+ this(major, middle, minor, Collections.<String>emptySet());
+ }
+
+ public HgVersion(int major, int middle, int minor, @NotNull Set<String> unsupportedExtensions) {
myMajor = major;
myMiddle = middle;
myMinor = minor;
+ myUnsupportedExtensions = unsupportedExtensions;
}
/**
* Parses output of "Hg version" command.
*/
-
@NotNull
- public static HgVersion parseVersion(@Nullable String output) throws ParseException {
+ public static HgVersion parseVersionAndExtensionInfo(@Nullable String output,
+ @NotNull List<String> errorLines)
+ throws ParseException {
if (StringUtil.isEmptyOrSpaces(output)) {
throw new ParseException("Empty hg version output: " + output, 0);
}
Matcher matcher = HG_VERSION_PATTERN.matcher(output);
if (matcher.matches()) {
- return new HgVersion(getIntGroup(matcher, 1), getIntGroup(matcher, 2), getIntGroup(matcher, 3));
+ return new HgVersion(getIntGroup(matcher, 1), getIntGroup(matcher, 2), getIntGroup(matcher, 3),
+ parseUnsupportedExtensions(errorLines));
}
LOGGER.error("Couldn't identify hg version: " + output);
throw new ParseException("Unsupported format of hg version output: " + output, 0);
}
+ @NotNull
+ public static Set<String> parseUnsupportedExtensions(@NotNull List<String> errorLines) {
+ // hg version command execute with null start directory,
+ // but hgrc configuration file may be related to one of repository then extension may be failed to import too
+ //before fixed use command exit value instead if errors.isEmpty
+ //todo store all unsupported extensions for all repository and notify once
+ Set<String> extensions = new HashSet<String>();
+ if (errorLines.isEmpty()) {
+ return extensions;
+ }
+ for (String line : errorLines) {
+ Matcher matcher = HG_UNSUPPORTED_EXTENSION.matcher(line);
+ if (matcher.matches()) {
+ extensions.add(matcher.group(1));
+ }
+ }
+ return extensions;
+ }
+
// Utility method used in parsing - checks that the given capture group exists and captured something - then returns the captured value,
// otherwise returns 0.
private static int getIntGroup(@NotNull Matcher matcher, int group) {
@@ -103,30 +137,47 @@
public static HgVersion identifyVersion(@NotNull String executable)
throws ShellCommandException, InterruptedException, ParseException {
HgCommandResult versionResult = HgUtil.getVersionOutput(executable);
- return parseVersion(versionResult.getRawOutput());
+ return parseVersionAndExtensionInfo(versionResult.getRawOutput(), versionResult.getErrorLines());
}
/**
* @return true if the version is supported by the plugin
*/
public boolean isSupported() {
- return !isNull() && compareTo(MIN) >= 0;
+ return compareTo(MIN) >= 0;
}
public boolean isAmendSupported() {
- return !isNull() && compareTo(AMEND_SUPPORTED) >= 0;
+ return compareTo(AMEND_SUPPORTED) >= 0;
}
public boolean isBuiltInFunctionSupported() {
- return !isNull() && compareTo(BUILT_IN_FUNCTION_SUPPORTED) >= 0;
+ return compareTo(BUILT_IN_FUNCTION_SUPPORTED) >= 0;
}
public boolean isLargeFilesWithFollowSupported() {
- return !isNull() && compareTo(LARGEFILES_WITH_FOLLOW_SUPPORTED) >= 0;
+ return compareTo(LARGEFILES_WITH_FOLLOW_SUPPORTED) >= 0;
}
-
+
+ public boolean isParentRevisionTemplateSupported() {
+ return compareTo(PARENT_REVISION_TEMPLATES_SUPPORTED) >= 0;
+ }
+
public boolean hasBranchHeadsServed() {
- return !isNull() && compareTo(BRANCH_HEADS_SERVED_FILE_EXIST) >= 0;
+ return compareTo(BRANCH_HEADS_SERVED_FILE_EXIST) >= 0 && compareTo(BRANCH2_SERVED_FILE_EXIST) < 0;
+ }
+
+ public boolean hasBranch2Served() {
+ return compareTo(BRANCH2_SERVED_FILE_EXIST) >= 0;
+ }
+
+ public boolean hasUnsupportedExtensions() {
+ return !myUnsupportedExtensions.isEmpty();
+ }
+
+ @NotNull
+ public Set<String> getUnsupportedExtensions() {
+ return myUnsupportedExtensions;
}
/**
@@ -170,8 +221,4 @@
public String toString() {
return myMajor + "." + myMiddle + "." + myMinor;
}
-
- public boolean isNull() {
- return myMajor == 0 && myMiddle == 0 && myMinor == 0;
- }
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
index db23fda..5d3ef1e 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
@@ -38,7 +38,7 @@
final String programName = "hg";
final String unixExec = "hg";
final String winExec = "hg.exe";
- String exec = findInPathEnvs(programName, Arrays.asList(HG_EXECUTABLE_ENV));
+ String exec = findEnvValue(programName, Arrays.asList(HG_EXECUTABLE_ENV));
if (exec != null) {
return exec;
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
index 1b4519a..ac64812 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgPlatformTest.java
@@ -109,6 +109,7 @@
File hgrc = new File(new File(repositoryRoot.getPath(), ".hg"), "hgrc");
FileUtil.appendToFile(hgrc, text);
assertTrue(hgrc.exists());
+ repositoryRoot.refresh(false,true);
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java b/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java
new file mode 100644
index 0000000..81387d1
--- /dev/null
+++ b/plugins/hg4idea/testSrc/hg4idea/test/commit/HgCommitTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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 hg4idea.test.commit;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import hg4idea.test.HgPlatformTest;
+import org.zmlx.hg4idea.HgFile;
+import org.zmlx.hg4idea.HgFileRevision;
+import org.zmlx.hg4idea.command.HgCommitCommand;
+import org.zmlx.hg4idea.command.HgLogCommand;
+import org.zmlx.hg4idea.execution.HgCommandException;
+
+import java.util.List;
+
+import static com.intellij.openapi.vcs.Executor.*;
+import static hg4idea.test.HgExecutor.hg;
+
+/**
+ * @author Nadya Zabrodina
+ */
+public class HgCommitTest extends HgPlatformTest {
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ cd(myRepository);
+ String abFile = "AB.txt";
+ touch(abFile, "base");
+ hg("add " + abFile);
+ hg("commit -m amend");
+ echo(abFile, "text for amend");
+ }
+
+ public void testAmendCommit() throws HgCommandException, VcsException {
+ String changedCommit = "anotherCommit";
+ HgLogCommand logCommand = new HgLogCommand(myProject);
+ logCommand.setLogFile(false);
+ HgFile hgFile = new HgFile(myRepository, VfsUtilCore.virtualToIoFile(myRepository));
+ List<HgFileRevision> revisions = logCommand.execute(hgFile, -1, false);
+ HgCommitCommand commit = new HgCommitCommand(myProject, myRepository, changedCommit, true);
+ commit.execute();
+ List<HgFileRevision> revisionsAfterAmendCommit = logCommand.execute(hgFile, -1, false);
+ assertTrue(revisions.size() == revisionsAfterAmendCommit.size());
+ assertEquals(revisionsAfterAmendCommit.get(0).getCommitMessage(), changedCommit);
+ }
+}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java b/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java
index 5b57827..ea7850e 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/history/HgBrowseChangesTest.java
@@ -30,6 +30,7 @@
import static com.intellij.openapi.vcs.Executor.cd;
import static com.intellij.openapi.vcs.Executor.touch;
import static hg4idea.test.HgExecutor.hg;
+import static java.util.Calendar.YEAR;
/**
* @author Nadya Zabrodina
@@ -52,8 +53,9 @@
hg("add");
hg("commit -m add");
java.util.Calendar now = java.util.Calendar.getInstance();
+ now.add(YEAR, 1);
dateBefore = ChangeBrowserSettings.DATE_FORMAT.format(now.getTime());
- now.set(java.util.Calendar.YEAR, 1970);
+ now.set(YEAR, 1970);
dateAfter = ChangeBrowserSettings.DATE_FORMAT.format(now.getTime());
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogHistoryTest.java b/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogHistoryTest.java
index 3c215ae..f5d8c04 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogHistoryTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogHistoryTest.java
@@ -26,6 +26,7 @@
import java.util.Arrays;
import java.util.Collection;
+import java.util.List;
import static com.intellij.openapi.vcs.Executor.cd;
import static com.intellij.openapi.vcs.Executor.echo;
@@ -40,10 +41,10 @@
@Override
public void setUp() throws Exception {
super.setUp();
- createBookmarksAndBranches(myRepository);
}
public void testContainedInBranchesInLogInfos() throws VcsException {
+ createBookmarksAndBranches(myRepository);
Hash testHashForFirstCommit = HashImpl.build("0");
Collection<String> branches = HgHistoryUtil.getDescendingHeadsOfBranches(myProject, myRepository, testHashForFirstCommit);
//B_Bookmark should not be listed - it is inactive and not head//
@@ -53,13 +54,11 @@
private static void createBookmarksAndBranches(@NotNull VirtualFile repositoryRoot) {
cd(repositoryRoot);
hg("bookmark A_BookMark");
- hg("tag tag1");
String aFile = "A.txt";
touch(aFile, "base");
hg("add " + aFile);
hg("commit -m 'create file'");
hg("branch branchA");
- hg("tag tag2");
echo(aFile, " modify with a");
hg("commit -m 'create branchA'");
hg("bookmark B_BookMark --inactive");
@@ -67,7 +66,6 @@
hg("commit -m 'modify branchA'");
hg("up default");
hg("branch branchB");
- hg("tag -l localTag");
echo(aFile, " modify with b");
hg("commit -m 'modify file in branchB'");
hg("bookmark C_BookMark");
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogParseTest.java b/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogParseTest.java
index b568e70..f209d6c 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogParseTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/history/HgLogParseTest.java
@@ -15,15 +15,14 @@
*/
package hg4idea.test.history;
-import com.intellij.openapi.vcs.VcsTestUtil;
-import com.intellij.openapi.vcs.actions.ShortNameType;
+import com.intellij.openapi.util.Pair;
import org.junit.Test;
import org.zmlx.hg4idea.command.HgLogCommand;
import org.zmlx.hg4idea.util.HgUtil;
-import java.util.Arrays;
import java.util.Map;
+import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
/**
@@ -52,10 +51,10 @@
@Test
public void testParseUserNameAndEmail() {
- VcsTestUtil.assertEqualCollections(HgUtil.parseUserNameAndEmail("Vasya Pavlovich Pupkin <asdasd@localhost>"),
- Arrays.asList("Vasya Pavlovich Pupkin", "asdasd@localhost"));
- VcsTestUtil.assertEqualCollections(HgUtil.parseUserNameAndEmail("Vasya Pavlovich Pupkin"), Arrays.asList("Vasya Pavlovich Pupkin", ""));
- VcsTestUtil.assertEqualCollections(HgUtil.parseUserNameAndEmail("vasya.pupkin@localhost.com"),
- Arrays.asList("vasya pupkin", "vasya.pupkin@localhost.com"));
+ assertEquals(HgUtil.parseUserNameAndEmail("Vasya Pavlovich Pupkin <asdasd@localhost>"),
+ new Pair<String, String>("Vasya Pavlovich Pupkin", "asdasd@localhost"));
+ assertEquals(HgUtil.parseUserNameAndEmail("Vasya Pavlovich Pupkin"), new Pair<String, String>("Vasya Pavlovich Pupkin", ""));
+ assertEquals(HgUtil.parseUserNameAndEmail("vasya.pupkin@localhost.com"),
+ new Pair<String, String>("vasya pupkin", "vasya.pupkin@localhost.com"));
}
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java b/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java
index 079a6d2..0702f44 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRealRepositoryReaderTest.java
@@ -19,6 +19,8 @@
import com.intellij.openapi.vcs.VcsTestUtil;
import hg4idea.test.HgPlatformTest;
import org.jetbrains.annotations.NotNull;
+import org.zmlx.hg4idea.repo.HgRepository;
+import org.zmlx.hg4idea.repo.HgRepositoryImpl;
import org.zmlx.hg4idea.repo.HgRepositoryReader;
import org.zmlx.hg4idea.util.HgUtil;
@@ -41,7 +43,7 @@
File hgDir = new File(myRepository.getPath(), ".hg");
assertTrue(hgDir.exists());
createBranchesAndTags();
- myRepositoryReader = new HgRepositoryReader(myProject, hgDir);
+ myRepositoryReader = new HgRepositoryReader(myVcs, hgDir);
}
public void testMergeState() {
@@ -58,10 +60,20 @@
}
public void testBranches() {
- VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readBranches()),
+ VcsTestUtil.assertEqualCollections(myRepositoryReader.readBranches().keySet(),
Arrays.asList("default", "branchA", "branchB"));
}
+ public void testOpenedBranches() {
+ cd(myRepository);
+ HgRepository hgRepository = HgRepositoryImpl.getInstance(myRepository, myProject, myProject);
+ hg("up branchA");
+ hg("commit -m 'close branch' --close-branch");
+ hgRepository.update();
+ VcsTestUtil.assertEqualCollections(hgRepository.getOpenedBranches(),
+ Arrays.asList("default", "branchB"));
+ }
+
public void testTags() {
VcsTestUtil.assertEqualCollections(HgUtil.getNamesWithoutHashes(myRepositoryReader.readTags()),
Arrays.asList("tag1", "tag2"));
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRepositoryReaderTest.java b/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRepositoryReaderTest.java
index bb94270..9aeda2b 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRepositoryReaderTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/repo/HgRepositoryReaderTest.java
@@ -63,7 +63,7 @@
FileUtil.copy(testTagFile, new File(myHgDir.getParentFile(), ".hgtags"));
FileUtil.copy(testLocalTagFile, new File(myHgDir, "localtags"));
- myRepositoryReader = new HgRepositoryReader(myProject, myHgDir);
+ myRepositoryReader = new HgRepositoryReader(myVcs, myHgDir);
myBranches = readBranches();
myBookmarks = readRefs(testBookmarkFile);
myTags = readRefs(testTagFile);
@@ -80,7 +80,7 @@
}
public void testBranches() {
- Collection<String> branches = HgUtil.getNamesWithoutHashes(myRepositoryReader.readBranches());
+ Collection<String> branches = myRepositoryReader.readBranches().keySet();
VcsTestUtil.assertEqualCollections(branches, myBranches);
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java
index 6a0e21a..04dcbc3 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/version/HgVersionTest.java
@@ -15,10 +15,14 @@
*/
package hg4idea.test.version;
+import com.intellij.openapi.vcs.VcsTestUtil;
import hg4idea.test.HgPlatformTest;
import org.zmlx.hg4idea.util.HgVersion;
import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
/**
* @author Nadya Zabrodina
@@ -37,12 +41,13 @@
new TestHgVersion("Распределенная SCM Mercurial (версия 2.6.1)", 2, 6, 1),
new TestHgVersion("[Mercurial Distributed SCM (version 2.6.2+20130606)]", 2, 6, 2),
new TestHgVersion("[Mercurial Distributed SCM (version 2.4.2+20130203)]\n", 2, 4, 2),
- new TestHgVersion("Mercurial Distributed SCM (version 2.6.2)\n", 2, 6, 2)
+ new TestHgVersion("Mercurial Distributed SCM (version 2.6.2)\n", 2, 6, 2),
+ new TestHgVersion("Mercurial Distributed SCM (version 2.7+93-f959b60e3025)", 2, 7, 0)
};
public void testParseSupported() throws Exception {
for (TestHgVersion test : commonTests) {
- HgVersion version = HgVersion.parseVersion(test.output);
+ HgVersion version = HgVersion.parseVersionAndExtensionInfo(test.output, Collections.<String>emptyList());
assertEqualVersions(version, test);
assertTrue(version.isSupported());
}
@@ -50,11 +55,26 @@
public void testParseUnsupported() throws Exception {
TestHgVersion unsupportedVersion = new TestHgVersion("Mercurial Distributed SCM (version 1.5.1)", 1, 5, 1);
- HgVersion parsedVersion = HgVersion.parseVersion(unsupportedVersion.output);
+ HgVersion parsedVersion =
+ HgVersion.parseVersionAndExtensionInfo(unsupportedVersion.output, Collections.<String>emptyList());
assertEqualVersions(parsedVersion, unsupportedVersion);
assertFalse(parsedVersion.isSupported());
}
+ public void testParseImportExtensionsError() {
+ List<String> errorLines = Arrays.asList("*** failed to import extension hgcr-gui: No module named hgcr-gui",
+ "*** failed to import extension hgcr-gui-qt: No module named hgcr-gui-qt");
+ VcsTestUtil.assertEqualCollections(HgVersion.parseUnsupportedExtensions(errorLines), Arrays.asList("hgcr-gui", "hgcr-gui-qt"));
+ }
+
+ public void testParseImportDeprecatedExtensionsError() {
+ List<String> errorLines = Arrays.asList("*** failed to import extension kilnpath from" +
+ " C:\\Users\\Developer\\AppData\\Local\\KilnExtensions\\kilnpath.py:" +
+ " kilnpath is deprecated, and does not work in Mercurial 2.3 or higher." +
+ " Use the official schemes extension instead");
+ VcsTestUtil.assertEqualCollections(HgVersion.parseUnsupportedExtensions(errorLines), Arrays.asList("kilnpath"));
+ }
+
private static void assertEqualVersions(HgVersion actual, TestHgVersion expected) throws Exception {
Field field = HgVersion.class.getDeclaredField("myMajor");
field.setAccessible(true);
diff --git a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTest.java b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTest.java
index 633e78c..43bb2121a 100644
--- a/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTest.java
+++ b/plugins/hg4idea/testSrc/org/zmlx/hg4idea/test/HgTest.java
@@ -74,7 +74,6 @@
final File pluginRoot = new File(PluginPathManager.getPluginHomePath(HgVcs.VCS_NAME));
myClientBinaryPath = new File(pluginRoot, "testData/bin");
}
- HgVcs.setTestHgExecutablePath(myClientBinaryPath.getPath());
myMainRepo = initRepositories();
myProjectDir = new File(myMainRepo.getDirFixture().getTempDirPath());
diff --git a/plugins/java-i18n/java-i18n.iml b/plugins/java-i18n/java-i18n.iml
index eed7b0a..b15f5c1 100644
--- a/plugins/java-i18n/java-i18n.iml
+++ b/plugins/java-i18n/java-i18n.iml
@@ -19,6 +19,7 @@
<orderEntry type="module" module-name="jsp-base-openapi" />
<orderEntry type="module" module-name="jsp-openapi" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module" module-name="properties-psi-api" />
</component>
</module>
diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java b/plugins/java-i18n/src/com/intellij/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java
index eae515b..ce11ac7 100644
--- a/plugins/java-i18n/src/com/intellij/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java
+++ b/plugins/java-i18n/src/com/intellij/codeInspection/duplicateStringLiteral/DuplicateStringLiteralInspection.java
@@ -200,8 +200,10 @@
String msg = InspectionsBundle.message("inspection.duplicates.message", classList);
Collection<LocalQuickFix> fixes = new SmartList<LocalQuickFix>();
- final LocalQuickFix introduceConstFix = createIntroduceConstFix(foundExpr, originalExpression);
- fixes.add(introduceConstFix);
+ if (isOnTheFly) {
+ final LocalQuickFix introduceConstFix = createIntroduceConstFix(foundExpr, originalExpression);
+ fixes.add(introduceConstFix);
+ }
createReplaceFixes(foundExpr, originalExpression, fixes);
LocalQuickFix[] array = fixes.toArray(new LocalQuickFix[fixes.size()]);
holder.registerProblem(originalExpression, msg, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, array);
diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java
index af459ac..4b01041 100644
--- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java
+++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/I18nizeAction.java
@@ -18,6 +18,7 @@
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.lang.properties.psi.ResourceBundleManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
@@ -108,6 +109,17 @@
return;
}
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ JavaI18nizeQuickFixDialog.isAvailable(psiFile);
+ }
+
+ try {
+ ResourceBundleManager.getManager(psiFile);
+ }
+ catch (ResourceBundleManager.ResourceBundleNotFoundException e) {
+ return;
+ }
+
final JavaI18nizeQuickFixDialog dialog = handler.createDialog(project, editor, psiFile);
if (dialog == null) return;
dialog.show();
diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nizeQuickFixDialog.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nizeQuickFixDialog.java
index f7040be..27bc39e 100644
--- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nizeQuickFixDialog.java
+++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/JavaI18nizeQuickFixDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -52,8 +52,9 @@
import javax.swing.event.HyperlinkListener;
import java.awt.*;
import java.io.IOException;
-import java.util.*;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
public class JavaI18nizeQuickFixDialog extends I18nizeQuickFixDialog {
private final PsiLiteralExpression myLiteralExpression;
@@ -177,7 +178,7 @@
catch (ResourceBundleManager.ResourceBundleNotFoundException e) {
final IntentionAction fix = e.getFix();
if (fix != null) {
- if (Messages.showOkCancelDialog(project, e.getMessage(), title, Messages.getErrorIcon()) == OK_EXIT_CODE) {
+ if (Messages.showOkCancelDialog(project, e.getMessage(), title, Messages.getErrorIcon()) == Messages.OK) {
try {
fix.invoke(project, null, file);
return false;
diff --git a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
index b704663..592bfbc 100644
--- a/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
+++ b/plugins/java-i18n/src/com/intellij/codeInspection/i18n/folding/I18nMessageGotoDeclarationHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.lang.folding.FoldingBuilder;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.FoldRegion;
-import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.util.Key;
import com.intellij.psi.*;
import org.jetbrains.annotations.Nullable;
@@ -34,7 +33,7 @@
private static final Key<FoldingBuilder> KEY = CompositeFoldingBuilder.FOLDING_BUILDER;
@Override
- public PsiElement getGotoDeclarationTarget(PsiElement element, Editor editor) {
+ public PsiElement getGotoDeclarationTarget(@Nullable PsiElement element, Editor editor) {
if (!(element instanceof PsiJavaToken)) return null;
int i = 4; //some street magic
diff --git a/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerSuppressionTest.java b/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerSuppressionTest.java
index 7634d11..2936964 100644
--- a/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerSuppressionTest.java
+++ b/plugins/java-i18n/testSrc/com/intellij/spellchecker/inspection/JavaSpellcheckerSuppressionTest.java
@@ -16,6 +16,7 @@
package com.intellij.spellchecker.inspection;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.openapi.application.PluginPathManager;
import org.jetbrains.annotations.NotNull;
@@ -29,8 +30,13 @@
public void testClassName() { doTest(); }
public void testStringLiteral() { doTest(); }
+ @NotNull
+ @Override
+ protected LocalInspectionTool[] configureLocalInspectionTools() {
+ return SpellcheckerInspectionTestCase.getInspectionTools();
+ }
+
private void doTest() {
- enableInspectionTools(SpellcheckerInspectionTestCase.getInspectionTools());
doSingleTest(getTestName(false) + ".java");
}
}
diff --git a/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml b/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml
new file mode 100644
index 0000000..94b91b5
--- /dev/null
+++ b/plugins/javaFX/FxBuilderEmbedder/FxBuilderEmbedder.iml
@@ -0,0 +1,22 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="module-library" scope="PROVIDED">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/SceneBuilderKit.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ </component>
+</module>
+
diff --git a/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar b/plugins/javaFX/FxBuilderEmbedder/lib/embedder.jar
new file mode 100644
index 0000000..10561a4
--- /dev/null
+++ 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
new file mode 100644
index 0000000..6748c07
--- /dev/null
+++ b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderImpl.java
@@ -0,0 +1,124 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.oracle.javafx.scenebuilder.kit.editor.EditorController;
+import com.oracle.javafx.scenebuilder.kit.editor.panel.content.ContentPanelController;
+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 javafx.application.Platform;
+import javafx.beans.value.ChangeListener;
+import javafx.beans.value.ObservableValue;
+import javafx.embed.swing.JFXPanel;
+import javafx.geometry.Orientation;
+import javafx.scene.Scene;
+import javafx.scene.SceneAntialiasing;
+import javafx.scene.control.SplitPane;
+
+import javax.swing.*;
+import java.net.URL;
+
+/**
+ * @author Alexander Lobas
+ */
+public class SceneBuilderImpl implements SceneBuilder {
+ private final URL myFileURL;
+ private final EditorCallback myEditorCallback;
+ private final JFXPanel myPanel = new JFXPanel();
+ private EditorController myEditorController;
+ private ChangeListener<Number> myListener;
+ private volatile boolean mySkipChanges;
+
+ public SceneBuilderImpl(URL url, EditorCallback editorCallback) {
+ myFileURL = url;
+ myEditorCallback = editorCallback;
+
+ Platform.setImplicitExit(false);
+
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ create();
+ }
+ });
+ }
+
+ private void create() {
+ myEditorController = new EditorController();
+ HierarchyTreeViewController componentTree = new HierarchyTreeViewController(myEditorController);
+ ContentPanelController canvas = new ContentPanelController(myEditorController);
+ InspectorPanelController propertyTable = new InspectorPanelController(myEditorController);
+ LibraryPanelController palette = new LibraryPanelController(myEditorController);
+
+ loadFile();
+ startChangeListener();
+
+ SplitPane leftPane = new SplitPane();
+ leftPane.setOrientation(Orientation.VERTICAL);
+ leftPane.getItems().addAll(palette.getPanelRoot(), componentTree.getPanelRoot());
+ leftPane.setDividerPositions(0.5, 0.5);
+
+ SplitPane.setResizableWithParent(leftPane, Boolean.FALSE);
+ SplitPane.setResizableWithParent(propertyTable.getPanelRoot(), Boolean.FALSE);
+
+ SplitPane mainPane = new SplitPane();
+
+ mainPane.getItems().addAll(leftPane, canvas.getPanelRoot(), propertyTable.getPanelRoot());
+ mainPane.setDividerPositions(0.11036789297658862, 0.8963210702341137);
+
+ myPanel.setScene(new Scene(mainPane, -1, -1, true, SceneAntialiasing.BALANCED));
+ }
+
+ @Override
+ public JComponent getPanel() {
+ return myPanel;
+ }
+
+ @Override
+ public void reloadFile() {
+ if (myEditorController != null) {
+ Platform.runLater(new Runnable() {
+ @Override
+ public void run() {
+ // TODO: restore state
+ loadFile();
+ }
+ });
+ }
+ }
+
+ private void startChangeListener() {
+ myListener = new ChangeListener<Number>() {
+ @Override
+ public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
+ if (!mySkipChanges) {
+ myEditorCallback.saveChanges(myEditorController.getFxmlText());
+ }
+ }
+ };
+
+ myEditorController.getJobManager().revisionProperty().addListener(myListener);
+ }
+
+ @Override
+ public void close() {
+ if (myEditorController != null) {
+ myEditorController.getJobManager().revisionProperty().removeListener(myListener);
+ }
+ }
+
+ private void loadFile() {
+ mySkipChanges = true;
+
+ try {
+ String fxmlText = FXOMDocument.readContentFromURL(myFileURL);
+ myEditorController.setFxmlTextAndLocation(fxmlText, myFileURL);
+ }
+ catch (Throwable e) {
+ myEditorCallback.handleError(e);
+ }
+ finally {
+ mySkipChanges = false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderKitWrapper.java b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderKitWrapper.java
new file mode 100644
index 0000000..592401c
--- /dev/null
+++ b/plugins/javaFX/FxBuilderEmbedder/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderKitWrapper.java
@@ -0,0 +1,29 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.oracle.javafx.scenebuilder.kit.editor.drag.source.AbstractDragSource;
+import javafx.fxml.FXMLLoader;
+import javafx.scene.input.DataFormat;
+
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+
+/**
+ * @author Alexander Lobas
+ */
+public class SceneBuilderKitWrapper {
+ public static SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception {
+ // JavaFX -> Swing drag&drop fix
+ Field identifier = DataFormat.class.getDeclaredField("identifier");
+ identifier.setAccessible(true);
+ identifier.set(AbstractDragSource.INTERNAL_DATA_FORMAT, Collections
+ .unmodifiableSet(new HashSet<String>(Arrays.asList("application/scene.builder.internal"))));
+
+ // JavaFX class loading fix
+ FXMLLoader.setDefaultClassLoader(SceneBuilderKitWrapper.class.getClassLoader());
+
+ return new SceneBuilderImpl(url, editorCallback);
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java
index e95087b..8be55ab 100644
--- a/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java
+++ b/plugins/javaFX/javaFX-CE/testSrc/org/jetbrains/plugins/javaFX/GenerateGetterSetterTest.java
@@ -21,10 +21,12 @@
import com.intellij.openapi.application.PluginPathManager;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
+import com.intellij.testFramework.PlatformTestCase;
import com.intellij.testFramework.PsiTestUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+@PlatformTestCase.WrapInCommand
public class GenerateGetterSetterTest extends DaemonAnalyzerTestCase {
public void testDouble() throws Exception {
doTest();
diff --git a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
index 2d953b7..cdc1397 100644
--- a/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
+++ b/plugins/javaFX/src/META-INF/common-javaFX-plugin.xml
@@ -3,6 +3,7 @@
<extensions defaultExtensionNs="com.intellij">
<errorHandler implementation="com.intellij.diagnostic.ITNReporter"/>
<fileTypeFactory implementation="org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory"/>
+ <fileEditorProvider implementation="org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderEditorProvider"/>
<xml.xmlExtension implementation="org.jetbrains.plugins.javaFX.fxml.JavaFxXmlExtension"/>
<xml.fileNSInfoProvider implementation="org.jetbrains.plugins.javaFX.fxml.JavaFXNamespaceProvider"/>
<metaDataContributor implementation="org.jetbrains.plugins.javaFX.fxml.JavaFXMetaDataContributor"/>
@@ -50,12 +51,13 @@
<renamePsiElementProcessor implementation="org.jetbrains.plugins.javaFX.JavaFxRenameAttributeProcessor" order="before xmlAttribute"/>
<completion.contributor implementationClass="org.jetbrains.plugins.javaFX.fxml.refs.JavaFxCompletionContributor" language="XML" order="before xmlNonFirst"/>
<manifest.parser.provider implementation="org.jetbrains.plugins.javaFX.manifest.JavaFxManifestHeaderParsers"/>
- <projectWizard.projectCategory implementation="org.jetbrains.plugins.javaFX.JavaFxProjectType"/>
+ <projectTemplate projectType="Java FX" templatePath="resources/projectTemplates/Java/JavaFX Application.zip" category="true"/>
</extensions>
<actions>
<action class="org.jetbrains.plugins.javaFX.actions.OpenInSceneBuilderAction" id="OpenInSceneBuilder" text="Open In SceneBuilder">
<add-to-group group-id="EditorPopupMenu" anchor="last"/>
+ <add-to-group group-id="EditorTabPopupMenu" anchor="last"/>
<add-to-group group-id="ProjectViewPopupMenu" anchor="last"/>
</action>
</actions>
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxProjectType.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxProjectType.java
deleted file mode 100644
index 653c573..0000000
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/JavaFxProjectType.java
+++ /dev/null
@@ -1,19 +0,0 @@
-package org.jetbrains.plugins.javaFX;
-
-import com.intellij.ide.projectWizard.TemplateBasedProjectType;
-
-/**
- * @author Dmitry Avdeev
- * Date: 20.09.13
- */
-public class JavaFxProjectType extends TemplateBasedProjectType {
-
- public JavaFxProjectType() {
- super("/resources/projectTemplates/Java/JavaFX Application.zip");
- }
-
- @Override
- public String getId() {
- return "JavaFX";
- }
-}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java
index f41b9be..6a56d6b 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/actions/OpenInSceneBuilderAction.java
@@ -17,35 +17,18 @@
import com.intellij.CommonBundle;
import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.configurations.JavaParameters;
-import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
-import com.intellij.execution.process.OSProcessHandler;
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.diagnostic.Logger;
-import com.intellij.openapi.fileChooser.FileChooser;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.registry.Registry;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.ArrayUtil;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.javaFX.JavaFxSettings;
-import org.jetbrains.plugins.javaFX.JavaFxSettingsConfigurable;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
+import org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderInfo;
/**
* User: anna
@@ -53,84 +36,21 @@
*/
public class OpenInSceneBuilderAction extends AnAction {
private static final Logger LOG = Logger.getInstance("#" + OpenInSceneBuilderAction.class.getName());
- public static final String ORACLE = "Oracle";
@Override
public void actionPerformed(AnActionEvent e) {
final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
LOG.assertTrue(virtualFile != null);
final String path = virtualFile.getPath();
-
- final JavaFxSettings settings = JavaFxSettings.getInstance();
- String pathToSceneBuilder = settings.getPathToSceneBuilder();
- if (StringUtil.isEmptyOrSpaces(settings.getPathToSceneBuilder())){
- final VirtualFile sceneBuilderFile = FileChooser.chooseFile(JavaFxSettingsConfigurable.createSceneBuilderDescriptor(), e.getProject(), getPredefinedPath());
- if (sceneBuilderFile == null) return;
-
- pathToSceneBuilder = sceneBuilderFile.getPath();
- settings.setPathToSceneBuilder(FileUtil.toSystemIndependentName(pathToSceneBuilder));
- }
-
final Project project = getEventProject(e);
- if (project != null && !Registry.is("scene.builder.start.executable", true)) {
- final Module module = ModuleUtilCore.findModuleForFile(virtualFile, project);
- if (module != null) {
- try {
- final JavaParameters javaParameters = new JavaParameters();
- javaParameters.configureByModule(module, JavaParameters.JDK_AND_CLASSES);
- final File sceneBuilderLibsFile;
- if (SystemInfo.isMac) {
- sceneBuilderLibsFile = new File(new File(pathToSceneBuilder, "Contents"), "Java");
- } else if (SystemInfo.isWindows) {
- File sceneBuilderRoot = new File(pathToSceneBuilder);
- File sceneBuilderRootDir = sceneBuilderRoot.getParentFile();
- if (sceneBuilderRootDir == null) {
- final File foundInPath = PathEnvironmentVariableUtil.findInPath(pathToSceneBuilder);
- if (foundInPath != null) {
- sceneBuilderRootDir = foundInPath.getParentFile();
- }
- }
- sceneBuilderRoot = sceneBuilderRootDir != null ? sceneBuilderRootDir.getParentFile() : null;
- if (sceneBuilderRoot != null) {
- final File libFile = new File(sceneBuilderRoot, "lib");
- if (libFile.isDirectory()) {
- sceneBuilderLibsFile = libFile;
- }
- else {
- final File appFile = new File(sceneBuilderRootDir, "app");
- sceneBuilderLibsFile = appFile.isDirectory() ? appFile : null;
- }
- }
- else {
- sceneBuilderLibsFile = null;
- }
- } else {
- sceneBuilderLibsFile = new File(new File(pathToSceneBuilder).getParent(), "app");
- }
- if (sceneBuilderLibsFile != null) {
- final File[] sceneBuilderLibs = sceneBuilderLibsFile.listFiles();
- if (sceneBuilderLibs != null) {
- for (File jarFile : sceneBuilderLibs) {
- javaParameters.getClassPath().add(jarFile.getPath());
- }
- javaParameters.setMainClass("com.oracle.javafx.authoring.Main");
- javaParameters.getProgramParametersList().add(path);
-
- final OSProcessHandler processHandler = javaParameters.createOSProcessHandler();
- final String commandLine = processHandler.getCommandLine();
- LOG.info("scene builder command line: " + commandLine);
- processHandler.startNotify();
- return;
- }
- }
- }
- catch (Throwable ex) {
- LOG.info(ex);
- }
- }
+ final SceneBuilderInfo info = SceneBuilderInfo.get(project, true);
+ if (info == SceneBuilderInfo.EMPTY) {
+ return;
}
+ String pathToSceneBuilder = info.path;
+
if (SystemInfo.isMac) {
pathToSceneBuilder += "/Contents/MacOS/scenebuilder-launcher.sh";
}
@@ -152,45 +72,11 @@
presentation.setEnabled(false);
presentation.setVisible(false);
final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
- if (virtualFile != null &&
+ if (virtualFile != null &&
JavaFxFileTypeFactory.isFxml(virtualFile) &&
e.getProject() != null) {
presentation.setEnabled(true);
presentation.setVisible(true);
}
}
-
- @Nullable
- private static VirtualFile getPredefinedPath() {
- String path = null;
- if (SystemInfo.isWindows) {
- final String sb11 = File.separator + "JavaFX Scene Builder 1.1" + File.separator + "JavaFX Scene Builder 1.1.exe";
- final String sb10 = File.separator + "JavaFX Scene Builder 1.0" + File.separator + "bin" + File.separator + "scenebuilder.exe";
- final List<String> suspiciousPaths = new ArrayList<String>();
- final String programFiles = "C:\\Program Files";
- fillPaths(programFiles, sb11, sb10, suspiciousPaths);
- fillPaths(programFiles + " (x86)", sb11, sb10, suspiciousPaths);
- final File sb = FileUtil.findFirstThatExist(ArrayUtil.toStringArray(suspiciousPaths));
- if (sb != null) {
- path = sb.getPath();
- }
- }
- else if (SystemInfo.isMac) {
- final File sb = FileUtil.findFirstThatExist("/Applications/JavaFX Scene Builder 1.1.app",
- "/Applications/JavaFX Scene Builder 1.0.app");
- if (sb != null) {
- path = sb.getPath();
- }
- }
- else if (SystemInfo.isUnix) {
- path = "/opt/JavaFXSceneBuilder1.1/JavaFXSceneBuilder1.1";
- }
-
- return path != null ? LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(path)) : null;
- }
-
- private static void fillPaths(String programFilesPath, String sb11, String sb10, List<String> suspiciousPaths) {
- suspiciousPaths.add(new File(programFilesPath, ORACLE).getPath() + sb11);
- suspiciousPaths.add(new File(programFilesPath, ORACLE).getPath() + sb10);
- }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
index 0261bd8..9efc302 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
@@ -24,7 +24,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.editor.Editor;
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.util.text.StringUtil;
@@ -34,7 +33,7 @@
import com.intellij.ui.ColorUtil;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ui.ColorIcon;
-import com.intellij.xml.util.ColorSampleLookupValue;
+import com.intellij.xml.util.ColorMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
@@ -124,7 +123,7 @@
if (attributeValueText.startsWith("#")) {
color = ColorUtil.fromHex(attributeValueText.substring(1));
} else {
- final String hexCode = ColorSampleLookupValue.getHexCodeForColorName(StringUtil.toLowerCase(attributeValueText));
+ final String hexCode = ColorMap.getHexCodeForColorName(StringUtil.toLowerCase(attributeValueText));
if (hexCode != null) {
color = ColorUtil.fromHex(hexCode);
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/EditorCallback.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/EditorCallback.java
new file mode 100644
index 0000000..8d019dc
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/EditorCallback.java
@@ -0,0 +1,10 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+/**
+ * @author Alexander Lobas
+ */
+public interface EditorCallback {
+ void saveChanges(String content);
+
+ void handleError(Throwable e);
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/ErrorSceneBuilderCreator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/ErrorSceneBuilderCreator.java
new file mode 100644
index 0000000..e1f989d
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/ErrorSceneBuilderCreator.java
@@ -0,0 +1,24 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import java.net.URL;
+
+/**
+ * @author Alexander Lobas
+ */
+public class ErrorSceneBuilderCreator implements SceneBuilderCreator {
+ private final State myState;
+
+ public ErrorSceneBuilderCreator(State state) {
+ myState = state;
+ }
+
+ @Override
+ public State getState() {
+ return myState;
+ }
+
+ @Override
+ public SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilder.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilder.java
new file mode 100644
index 0000000..4891d6b
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilder.java
@@ -0,0 +1,14 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import javax.swing.*;
+
+/**
+ * @author Alexander Lobas
+ */
+public interface SceneBuilder {
+ JComponent getPanel();
+
+ void reloadFile();
+
+ void close();
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderCreator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderCreator.java
new file mode 100644
index 0000000..4a81bac
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderCreator.java
@@ -0,0 +1,12 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import java.net.URL;
+
+/**
+ * @author Alexander Lobas
+ */
+public interface SceneBuilderCreator {
+ State getState();
+
+ SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception;
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderCreatorImpl.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderCreatorImpl.java
new file mode 100644
index 0000000..97832c4
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderCreatorImpl.java
@@ -0,0 +1,101 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.intellij.ide.plugins.cl.PluginClassLoader;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.PathUtil;
+
+import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarFile;
+
+/**
+ * @author Alexander Lobas
+ */
+public class SceneBuilderCreatorImpl implements SceneBuilderCreator {
+ private final SceneBuilderInfo myInfo;
+ private final ClassLoader myClassLoader;
+
+ public SceneBuilderCreatorImpl(SceneBuilderInfo info) throws Exception {
+ myInfo = info;
+ myClassLoader = createSceneLoader(info);
+ }
+
+ @Override
+ public State getState() {
+ return State.OK;
+ }
+
+ @Override
+ public SceneBuilder create(URL url, EditorCallback editorCallback) throws Exception {
+ Class<?> wrapperClass = Class.forName("org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderKitWrapper", false, myClassLoader);
+ return (SceneBuilder)wrapperClass.getMethod("create", URL.class, EditorCallback.class).invoke(null, url, editorCallback);
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof SceneBuilderCreatorImpl) {
+ SceneBuilderCreatorImpl impl = (SceneBuilderCreatorImpl)object;
+ return getState() == impl.getState() && myInfo.equals(impl.myInfo);
+ }
+ return false;
+ }
+
+ private static ClassLoader createSceneLoader(SceneBuilderInfo info) throws Exception {
+ List<URL> urls = new ArrayList<URL>();
+
+ File[] files = new File(info.libPath).listFiles();
+ if (files == null) {
+ throw new Exception(info.libPath + " wrong path");
+ }
+
+ for (File libFile : files) {
+ if (libFile.isFile() && libFile.getName().endsWith(".jar")) {
+ if (libFile.getName().equalsIgnoreCase("SceneBuilderApp.jar")) {
+ JarFile appJar = new JarFile(libFile);
+ String version = appJar.getManifest().getMainAttributes().getValue("Implementation-Version");
+ appJar.close();
+
+ if (version != null) {
+ int index = version.indexOf(" ");
+ if (index != -1) {
+ version = version.substring(0, index);
+ }
+ }
+
+ if (StringUtil.compareVersionNumbers(version, "2.0") < 0) {
+ throw new Exception(info.path + " wrong version: " + version);
+ }
+ }
+
+ urls.add(libFile.toURI().toURL());
+ }
+ }
+
+ if (urls.isEmpty()) {
+ throw new Exception(info.libPath + " no jar found");
+ }
+
+ final String parent = new File(PathUtil.getJarPathForClass(SceneBuilderCreatorImpl.class)).getParent();
+ if (SceneBuilderCreatorImpl.class.getClassLoader() instanceof PluginClassLoader) {
+ urls.add(new File(new File(parent).getParent(), "embedder.jar").toURI().toURL());
+ }
+ else {
+ final File localEmbedder = new File(parent, "FXBuilderEmbedder");
+ if (localEmbedder.exists()) {
+ urls.add(localEmbedder.toURI().toURL());
+ }
+ else {
+ File home = new File(PathManager.getHomePath(), "community");
+ if (!home.exists()) {
+ home = new File(PathManager.getHomePath());
+ }
+ urls.add(new File(home, "plugins/JavaFX/FxBuilderEmbedder/lib/embedder.jar").toURI().toURL());
+ }
+ }
+ return new URLClassLoader(urls.toArray(new URL[urls.size()]), SceneBuilderCreatorImpl.class.getClassLoader());
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java
new file mode 100644
index 0000000..ae36f91
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditor.java
@@ -0,0 +1,332 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.intellij.codeHighlighting.BackgroundEditorHighlighter;
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.editor.event.DocumentAdapter;
+import com.intellij.openapi.editor.event.DocumentEvent;
+import com.intellij.openapi.fileEditor.*;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.VerticalFlowLayout;
+import com.intellij.openapi.util.UserDataHolderBase;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.ui.HyperlinkLabel;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import java.awt.*;
+import java.beans.PropertyChangeListener;
+import java.io.File;
+import java.net.URL;
+
+/**
+ * @author Alexander Lobas
+ */
+public class SceneBuilderEditor extends UserDataHolderBase implements FileEditor, EditorCallback {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderEditor");
+
+ private final static String SCENE_CARD = "scene_builder";
+ private final static String ERROR_CARD = "error";
+
+ private final Project myProject;
+ private final VirtualFile myFile;
+ private final SceneBuilderProvider myCreatorProvider;
+
+ private final CardLayout myLayout = new CardLayout();
+ private final JPanel myPanel = new JPanel(myLayout);
+
+ private final JPanel myErrorPanel = new JPanel(new VerticalFlowLayout(VerticalFlowLayout.TOP, 10, 5, true, false));
+ private final HyperlinkLabel myErrorLabel = new HyperlinkLabel();
+
+ private final Document myDocument;
+ private final ExternalChangeListener myChangeListener;
+
+ private SceneBuilderCreator myBuilderCreator;
+ private URL myFileURL;
+ private SceneBuilder mySceneBuilder;
+
+ public SceneBuilderEditor(@NotNull Project project, @NotNull VirtualFile file, SceneBuilderProvider creatorProvider) {
+ myProject = project;
+ myFile = file;
+ myCreatorProvider = creatorProvider;
+
+ myDocument = FileDocumentManager.getInstance().getDocument(file);
+ myChangeListener = new ExternalChangeListener();
+
+ createErrorPage();
+ }
+
+ private void createErrorPage() {
+ myErrorLabel.setOpaque(false);
+
+ myErrorLabel.addHyperlinkListener(new HyperlinkListener() {
+ @Override
+ public void hyperlinkUpdate(HyperlinkEvent e) {
+ initSceneBuilder(true);
+ }
+ });
+
+ myErrorPanel.add(myErrorLabel);
+ myPanel.add(myErrorPanel);
+ }
+
+ private void showErrorPage(State state, Throwable e) {
+ removeSceneBuilder();
+
+ if (e == null) {
+ if (state == State.CREATE_ERROR) {
+ myErrorLabel.setHyperlinkText("JavaFX Scene Builder initialize error", "", "");
+ myErrorLabel.setIcon(Messages.getErrorIcon());
+ }
+ else {
+ if (state == State.EMPTY_PATH) {
+ myErrorLabel.setHyperlinkText("Please configure JavaFX Scene Builder ", "path", "");
+ }
+ else {
+ myErrorLabel.setHyperlinkText("Please reconfigure JavaFX Scene Builder ", "path", "");
+ }
+ myErrorLabel.setIcon(Messages.getWarningIcon());
+ }
+ }
+ else {
+ myErrorLabel.setHyperlinkText("Error: " + e.getMessage(), "", "");
+ myErrorLabel.setIcon(Messages.getErrorIcon());
+
+ LOG.error(e);
+ }
+ myLayout.show(myPanel, ERROR_CARD);
+ }
+
+ @Override
+ public void saveChanges(final String content) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ public void run() {
+ if (mySceneBuilder != null) {
+ try {
+ myChangeListener.setRunState(false);
+
+ // XXX: strange behavior with undo/redo
+
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ CommandProcessor.getInstance().executeCommand(myProject, new Runnable() {
+ @Override
+ public void run() {
+ myDocument.setText(content);
+ }
+ }, "JavaFX Scene Builder edit operation", null);
+ }
+ });
+ }
+ finally {
+ myChangeListener.setRunState(true);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ public void handleError(Throwable e) {
+ showErrorPage(null, e);
+ }
+
+ private void initSceneBuilder(boolean choosePathIfEmpty) {
+ if (choosePathIfEmpty || myBuilderCreator == null) {
+ myBuilderCreator = myCreatorProvider.get(myProject, choosePathIfEmpty);
+ updateState();
+ }
+ else {
+ SceneBuilderCreator creator = myCreatorProvider.get(null, false);
+ if (myBuilderCreator.equals(creator)) {
+ if (myBuilderCreator.getState() == State.OK) {
+ myChangeListener.checkContent();
+ }
+ }
+ else {
+ updateState();
+ }
+ }
+ }
+
+ private void updateState() {
+ if (myBuilderCreator.getState() == State.OK) {
+ addSceneBuilder();
+ }
+ else {
+ showErrorPage(myBuilderCreator.getState(), null);
+ }
+ }
+
+ private void addSceneBuilder() {
+ removeSceneBuilder();
+
+ try {
+ FileDocumentManager.getInstance().saveDocument(myDocument);
+
+ if (myFileURL == null) {
+ myFileURL = new File(myFile.getPath()).toURI().toURL();
+ }
+
+ mySceneBuilder = myBuilderCreator.create(myFileURL, this);
+
+ myPanel.add(mySceneBuilder.getPanel(), SCENE_CARD);
+ myLayout.show(myPanel, SCENE_CARD);
+
+ myChangeListener.start();
+ }
+ catch (Throwable e) {
+ showErrorPage(null, e);
+ }
+ }
+
+ private void updateSceneBuilder() {
+ if (mySceneBuilder != null) {
+ FileDocumentManager.getInstance().saveDocument(myDocument);
+ mySceneBuilder.reloadFile();
+ }
+ }
+
+ private void removeSceneBuilder() {
+ myChangeListener.stop();
+
+ if (mySceneBuilder != null) {
+ myPanel.remove(mySceneBuilder.getPanel());
+ mySceneBuilder.close();
+ mySceneBuilder = null;
+ }
+ }
+
+ @NotNull
+ @Override
+ public JComponent getComponent() {
+ return myPanel;
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return mySceneBuilder == null ? myErrorPanel : mySceneBuilder.getPanel();
+ }
+
+ @Override
+ public void dispose() {
+ removeSceneBuilder();
+ myChangeListener.dispose();
+ }
+
+ @NotNull
+ @Override
+ public String getName() {
+ return "Scene Builder";
+ }
+
+ @Override
+ public void selectNotify() {
+ initSceneBuilder(false);
+ }
+
+ @Override
+ public void deselectNotify() {
+ myChangeListener.stop();
+ }
+
+ @NotNull
+ @Override
+ public FileEditorState getState(@NotNull FileEditorStateLevel level) {
+ return FileEditorState.INSTANCE;
+ }
+
+ @Override
+ public void setState(@NotNull FileEditorState state) {
+ }
+
+ @Override
+ public boolean isValid() {
+ return myFile.isValid();
+ }
+
+ @Override
+ public boolean isModified() {
+ return true;
+ }
+
+ @Override
+ public void addPropertyChangeListener(@NotNull PropertyChangeListener listener) {
+ }
+
+ @Override
+ public void removePropertyChangeListener(@NotNull PropertyChangeListener listener) {
+ }
+
+ @Nullable
+ @Override
+ public BackgroundEditorHighlighter getBackgroundHighlighter() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public FileEditorLocation getCurrentLocation() {
+ return null;
+ }
+
+ @Nullable
+ @Override
+ public StructureViewBuilder getStructureViewBuilder() {
+ return null;
+ }
+
+ private class ExternalChangeListener extends DocumentAdapter {
+ private volatile boolean myRunState;
+ private String myContent;
+
+ public ExternalChangeListener() {
+ myDocument.addDocumentListener(this);
+ }
+
+ public void start() {
+ if (!myRunState) {
+ myRunState = true;
+ myContent = null;
+ }
+ }
+
+ public void stop() {
+ if (myRunState) {
+ myRunState = false;
+ myContent = myDocument.getText();
+ }
+ }
+
+ public void setRunState(boolean state) {
+ myRunState = state;
+ }
+
+ public void dispose() {
+ myDocument.removeDocumentListener(this);
+ }
+
+ public void checkContent() {
+ if (!myRunState && !myDocument.getText().equals(myContent)) {
+ updateSceneBuilder();
+ start();
+ }
+ }
+
+ @Override
+ public void documentChanged(DocumentEvent e) {
+ if (myRunState) {
+ updateSceneBuilder();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
new file mode 100644
index 0000000..de123d1
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderEditorProvider.java
@@ -0,0 +1,89 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorPolicy;
+import com.intellij.openapi.fileEditor.FileEditorProvider;
+import com.intellij.openapi.fileEditor.FileEditorState;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+
+/**
+ * @author Alexander Lobas
+ */
+public class SceneBuilderEditorProvider implements FileEditorProvider, DumbAware, SceneBuilderProvider {
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.javaFX.sceneBuilder.SceneBuilderEditorProvider");
+
+ private SceneBuilderCreatorImpl mySceneBuilderCreator;
+
+ @Override
+ 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);
+ }
+
+ @NotNull
+ @Override
+ public FileEditor createEditor(@NotNull Project project, @NotNull VirtualFile file) {
+ return new SceneBuilderEditor(project, file, this);
+ }
+
+ @Override
+ public void disposeEditor(@NotNull FileEditor editor) {
+ Disposer.dispose(editor);
+ }
+
+ @NotNull
+ @Override
+ public FileEditorState readState(@NotNull Element sourceElement, @NotNull Project project, @NotNull VirtualFile file) {
+ return FileEditorState.INSTANCE;
+ }
+
+ @Override
+ public void writeState(@NotNull FileEditorState state, @NotNull Project project, @NotNull Element targetElement) {
+ }
+
+ @NotNull
+ @Override
+ public String getEditorTypeId() {
+ return "JavaFX-Scene-Builder";
+ }
+
+ @NotNull
+ @Override
+ public FileEditorPolicy getPolicy() {
+ return FileEditorPolicy.PLACE_AFTER_DEFAULT_EDITOR;
+ }
+
+ @Override
+ public SceneBuilderCreator get(Project project, boolean choosePathIfEmpty) {
+ if (mySceneBuilderCreator == null) {
+ SceneBuilderInfo info = SceneBuilderInfo.get(project, choosePathIfEmpty);
+ if (info == SceneBuilderInfo.EMPTY) {
+ return new ErrorSceneBuilderCreator(State.EMPTY_PATH);
+ }
+ if (info.libPath == null) {
+ return new ErrorSceneBuilderCreator(State.ERROR_PATH);
+ }
+
+ // TODO: handle change configuration
+
+ try {
+ mySceneBuilderCreator = new SceneBuilderCreatorImpl(info);
+ }
+ catch (Throwable e) {
+ LOG.error(e);
+ return new ErrorSceneBuilderCreator(State.CREATE_ERROR);
+ }
+ }
+ return mySceneBuilderCreator;
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderInfo.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderInfo.java
new file mode 100644
index 0000000..209d3bb
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderInfo.java
@@ -0,0 +1,141 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.intellij.execution.configurations.PathEnvironmentVariableUtil;
+import com.intellij.openapi.fileChooser.FileChooser;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.SystemInfo;
+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.util.ArrayUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.JavaFxSettings;
+import org.jetbrains.plugins.javaFX.JavaFxSettingsConfigurable;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Alexander Lobas
+ */
+public class SceneBuilderInfo {
+ public static final SceneBuilderInfo EMPTY = new SceneBuilderInfo(null, null);
+
+ public final String path;
+ public final String libPath;
+
+ private SceneBuilderInfo(String path, String libPath) {
+ this.path = path;
+ this.libPath = libPath;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (object instanceof SceneBuilderInfo) {
+ SceneBuilderInfo info = (SceneBuilderInfo)object;
+ return Comparing.equal(path, info.path) && Comparing.equal(libPath, info.libPath);
+ }
+ return false;
+ }
+
+ @NotNull
+ public static SceneBuilderInfo get(Project project, boolean choosePathIfEmpty) {
+ JavaFxSettings settings = JavaFxSettings.getInstance();
+ String pathToSceneBuilder = settings.getPathToSceneBuilder();
+
+ if (StringUtil.isEmptyOrSpaces(pathToSceneBuilder)) {
+ VirtualFile sceneBuilderFile = null;
+ if (choosePathIfEmpty) {
+ sceneBuilderFile = FileChooser.chooseFile(JavaFxSettingsConfigurable.createSceneBuilderDescriptor(), project, getPredefinedPath());
+ }
+ if (sceneBuilderFile == null) {
+ return EMPTY;
+ }
+
+ pathToSceneBuilder = FileUtil.toSystemIndependentName(sceneBuilderFile.getPath());
+ settings.setPathToSceneBuilder(pathToSceneBuilder);
+ }
+
+ File sceneBuilderLibsFile;
+
+ if (SystemInfo.isMac) {
+ sceneBuilderLibsFile = new File(new File(pathToSceneBuilder, "Contents"), "Java");
+ }
+ else if (SystemInfo.isWindows) {
+ File sceneBuilderRoot = new File(pathToSceneBuilder);
+ File sceneBuilderRootDir = sceneBuilderRoot.getParentFile();
+ if (sceneBuilderRootDir == null) {
+ final File foundInPath = PathEnvironmentVariableUtil.findInPath(pathToSceneBuilder);
+ if (foundInPath != null) {
+ sceneBuilderRootDir = foundInPath.getParentFile();
+ }
+ }
+ sceneBuilderRoot = sceneBuilderRootDir != null ? sceneBuilderRootDir.getParentFile() : null;
+ if (sceneBuilderRoot != null) {
+ final File libFile = new File(sceneBuilderRoot, "lib");
+ if (libFile.isDirectory()) {
+ sceneBuilderLibsFile = libFile;
+ }
+ else {
+ final File appFile = new File(sceneBuilderRootDir, "app");
+ sceneBuilderLibsFile = appFile.isDirectory() ? appFile : null;
+ }
+ }
+ else {
+ sceneBuilderLibsFile = null;
+ }
+ }
+ else {
+ sceneBuilderLibsFile = new File(new File(pathToSceneBuilder).getParent(), "app");
+ }
+
+ if (sceneBuilderLibsFile != null && (!sceneBuilderLibsFile.exists() || !sceneBuilderLibsFile.isDirectory())) {
+ sceneBuilderLibsFile = null;
+ }
+
+ return new SceneBuilderInfo(pathToSceneBuilder, sceneBuilderLibsFile == null ? null : sceneBuilderLibsFile.getAbsolutePath());
+ }
+
+ @Nullable
+ private static VirtualFile getPredefinedPath() {
+ String path = null;
+ if (SystemInfo.isWindows) {
+ List<String> suspiciousPaths = new ArrayList<String>();
+ String programFiles = "C:\\Program Files";
+
+ String sb20 = "\\JavaFX Scene Builder 2.0\\JavaFX Scene Builder 2.0.exe";
+ String sb11 = "\\JavaFX Scene Builder 1.1\\JavaFX Scene Builder 1.1.exe";
+ String sb10 = "\\JavaFX Scene Builder 1.0\\bin\\scenebuilder.exe";
+
+ fillPaths(programFiles, suspiciousPaths, sb20, sb11, sb10);
+ fillPaths(programFiles + " (x86)", suspiciousPaths, sb20, sb11, sb10);
+
+ path = findFirstThatExist(ArrayUtil.toStringArray(suspiciousPaths));
+ }
+ else if (SystemInfo.isMac) {
+ path = findFirstThatExist("/Applications/JavaFX Scene Builder 2.0.app",
+ "/Applications/JavaFX Scene Builder 1.1.app",
+ "/Applications/JavaFX Scene Builder 1.0.app");
+ }
+ else if (SystemInfo.isUnix) {
+ path = findFirstThatExist("/opt/JavaFXSceneBuilder2.0/JavaFXSceneBuilder2.0", "/opt/JavaFXSceneBuilder1.1/JavaFXSceneBuilder1.1");
+ }
+
+ return path != null ? LocalFileSystem.getInstance().findFileByPath(FileUtil.toSystemIndependentName(path)) : null;
+ }
+
+ private static String findFirstThatExist(String... paths) {
+ File sb = FileUtil.findFirstThatExist(paths);
+ return sb == null ? null : sb.getPath();
+ }
+
+ private static void fillPaths(String programFilesPath, List<String> suspiciousPaths, String... sb) {
+ for (String sbi : sb) {
+ suspiciousPaths.add(new File(programFilesPath, "Oracle").getPath() + sbi);
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderProvider.java
new file mode 100644
index 0000000..eb1e8c7
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/SceneBuilderProvider.java
@@ -0,0 +1,10 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+import com.intellij.openapi.project.Project;
+
+/**
+ * @author Alexander Lobas
+ */
+public interface SceneBuilderProvider {
+ SceneBuilderCreator get(Project project, boolean choosePathIfEmpty);
+}
\ No newline at end of file
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/State.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/State.java
new file mode 100644
index 0000000..3ee0e12
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/sceneBuilder/State.java
@@ -0,0 +1,8 @@
+package org.jetbrains.plugins.javaFX.sceneBuilder;
+
+/**
+ * @author Alexander Lobas
+ */
+public enum State {
+ OK, EMPTY_PATH, ERROR_PATH, CREATE_ERROR
+}
\ No newline at end of file
diff --git a/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java b/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java
index c200d8f..8959088 100644
--- a/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java
+++ b/plugins/junit/src/com/intellij/execution/ConfigurationUtil.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
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.psi.search.PsiElementProcessor;
@@ -96,6 +97,7 @@
}
);
if (testAnnotation != null) {
+ //allScope is used to find all abstract test cases which probably have inheritors in the current 'scope'
AnnotatedMembersSearch.search(testAnnotation, GlobalSearchScope.allScope(manager.getProject())).forEach(new Processor<PsiMember>() {
public boolean process(final PsiMember annotated) {
final PsiClass containingClass = annotated instanceof PsiClass ? (PsiClass)annotated : annotated.getContainingClass();
@@ -104,7 +106,8 @@
new Computable<Boolean>() {
@Override
public Boolean compute() {
- return scope.contains(PsiUtilCore.getVirtualFile(containingClass)) && testClassFilter.isAccepted(containingClass);
+ final VirtualFile file = PsiUtilCore.getVirtualFile(containingClass);
+ return file != null && scope.contains(file) && testClassFilter.isAccepted(containingClass);
}
})) {
found.add(containingClass);
diff --git a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java
index 6ac30d9..df492ca 100644
--- a/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java
+++ b/plugins/junit/src/com/intellij/execution/junit/AddToTestsPatternAction.java
@@ -28,7 +28,6 @@
import com.intellij.openapi.ui.popup.PopupStep;
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiMember;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -41,7 +40,7 @@
public void actionPerformed(AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
- final Set<PsiElement> classes = PatternConfigurationProducer.collectTestMembers(psiElements);
+ final Set<PsiElement> classes = PatternConfigurationProducer.collectTestMembers(psiElements, true);
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
final List<JUnitConfiguration> patternConfigurations = collectPatternConfigurations(classes, project);
@@ -81,7 +80,7 @@
final DataContext dataContext = e.getDataContext();
final PsiElement[] psiElements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
if (psiElements != null) {
- final Set<PsiElement> foundMembers = PatternConfigurationProducer.collectTestMembers(psiElements);
+ final Set<PsiElement> foundMembers = PatternConfigurationProducer.collectTestMembers(psiElements, true);
if (foundMembers.isEmpty()) return;
final Project project = CommonDataKeys.PROJECT.getData(dataContext);
if (project != null) {
diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java b/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java
index bcb3678..1e08521 100644
--- a/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java
+++ b/plugins/junit/src/com/intellij/execution/junit/JUnit4Framework.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -31,7 +30,6 @@
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.junit.Ignore;
import javax.swing.*;
@@ -97,11 +95,11 @@
PsiMethod existingMethod = clazz.findMethodBySignature(method, false);
if (existingMethod != null) {
int exit = ApplicationManager.getApplication().isUnitTestMode() ?
- DialogWrapper.OK_EXIT_CODE :
+ Messages.OK :
Messages.showOkCancelDialog("Method setUp already exist but is not annotated as @Before. Annotate?",
CommonBundle.getWarningTitle(),
Messages.getWarningIcon());
- if (exit == DialogWrapper.OK_EXIT_CODE) {
+ if (exit == Messages.OK) {
new AddAnnotationFix(JUnitUtil.BEFORE_ANNOTATION_NAME, existingMethod).invoke(existingMethod.getProject(), null, existingMethod.getContainingFile());
return existingMethod;
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java
index d70a97f..4806869 100644
--- a/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java
+++ b/plugins/junit/src/com/intellij/execution/junit/JUnitConfigurationProducer.java
@@ -23,6 +23,7 @@
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.ConfigurationFromContext;
import com.intellij.execution.configurations.RunConfiguration;
+import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.*;
@@ -44,7 +45,12 @@
return false;
}
final RunConfiguration predefinedConfiguration = context.getOriginalConfiguration(JUnitConfigurationType.getInstance());
- Location location = JavaExecutionUtil.stepIntoSingleClass(context.getLocation());
+ final Location contextLocation = context.getLocation();
+
+ String paramSetName = contextLocation instanceof PsiMemberParameterizedLocation
+ ? ((PsiMemberParameterizedLocation)contextLocation).getParamSetName() : null;
+ assert contextLocation != null;
+ Location location = JavaExecutionUtil.stepIntoSingleClass(contextLocation);
final PsiElement element = location.getPsiElement();
final PsiClass testClass = JUnitUtil.getTestClass(element);
final PsiMethod testMethod = JUnitUtil.getTestMethod(element, false);
@@ -65,6 +71,7 @@
final String vmParameters = predefinedConfiguration instanceof JUnitConfiguration ? ((JUnitConfiguration)predefinedConfiguration).getVMParameters() : null;
if (vmParameters != null && !Comparing.strEqual(vmParameters, unitConfiguration.getVMParameters())) return false;
+ if (paramSetName != null && !Comparing.strEqual(paramSetName, unitConfiguration.getProgramParameters())) return false;
final TestObject testobject = unitConfiguration.getTestObject();
if (testobject != null) {
if (testobject.isConfiguredByElement(unitConfiguration, testClass, testMethod, testPackage, testDir)) {
diff --git a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
index 633f31a..6f3413c 100644
--- a/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
+++ b/plugins/junit/src/com/intellij/execution/junit/PatternConfigurationProducer.java
@@ -17,8 +17,10 @@
package com.intellij.execution.junit;
import com.intellij.execution.JavaExecutionUtil;
+import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.configurations.ModuleBasedConfiguration;
+import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
@@ -66,7 +68,7 @@
});
}
- static Set<PsiElement> collectTestMembers(PsiElement[] psiElements) {
+ static Set<PsiElement> collectTestMembers(PsiElement[] psiElements, boolean checkAbstract) {
final Set<PsiElement> foundMembers = new LinkedHashSet<PsiElement>();
for (PsiElement psiElement : psiElements) {
if (psiElement instanceof PsiClassOwner) {
@@ -81,7 +83,7 @@
foundMembers.add(psiElement);
}
} else if (psiElement instanceof PsiMethod) {
- if (JUnitUtil.getTestMethod(psiElement) != null) {
+ if (JUnitUtil.getTestMethod(psiElement, checkAbstract) != null) {
foundMembers.add(psiElement);
}
} else if (psiElement instanceof PsiDirectory) {
@@ -97,7 +99,7 @@
public static boolean isMultipleElementsSelected(ConfigurationContext context) {
final LinkedHashSet<String> classes = new LinkedHashSet<String>();
final PsiElement[] elements = collectPatternElements(context, classes);
- if (elements != null && collectTestMembers(elements).size() > 1) {
+ if (elements != null && collectTestMembers(elements, false).size() > 1) {
return true;
}
return false;
@@ -105,9 +107,19 @@
private static PsiElement[] collectPatternElements(ConfigurationContext context, LinkedHashSet<String> classes) {
final DataContext dataContext = context.getDataContext();
+ final Location<?>[] locations = Location.DATA_KEYS.getData(dataContext);
+ if (locations != null) {
+ List<PsiElement> elements = new ArrayList<PsiElement>();
+ for (Location<?> location : locations) {
+ final PsiElement psiElement = location.getPsiElement();
+ classes.add(getQName(psiElement, location));
+ elements.add(psiElement);
+ }
+ return elements.toArray(new PsiElement[elements.size()]);
+ }
PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
if (elements != null) {
- for (PsiElement psiClass : collectTestMembers(elements)) {
+ for (PsiElement psiClass : collectTestMembers(elements, true)) {
classes.add(getQName(psiClass));
}
return elements;
@@ -119,7 +131,7 @@
for (VirtualFile file : files) {
final PsiFile psiFile = psiManager.findFile(file);
if (psiFile instanceof PsiClassOwner) {
- for (PsiElement psiMember : collectTestMembers(((PsiClassOwner)psiFile).getClasses())) {
+ for (PsiElement psiMember : collectTestMembers(((PsiClassOwner)psiFile).getClasses(), true)) {
classes.add(((PsiClass)psiMember).getQualifiedName());
}
psiFiles.add(psiFile);
@@ -132,11 +144,17 @@
}
public static String getQName(PsiElement psiMember) {
+ return getQName(psiMember, null);
+ }
+
+ public static String getQName(PsiElement psiMember, Location location) {
if (psiMember instanceof PsiClass) {
return ((PsiClass)psiMember).getQualifiedName();
}
else if (psiMember instanceof PsiMember) {
- return ((PsiMember)psiMember).getContainingClass().getQualifiedName() + "," + ((PsiMember)psiMember).getName();
+ final PsiClass containingClass = location instanceof MethodLocation ? ((MethodLocation)location).getContainingClass(): ((PsiMember)psiMember).getContainingClass();
+ assert containingClass != null;
+ return containingClass.getQualifiedName() + "," + ((PsiMember)psiMember).getName();
} else if (psiMember instanceof PsiPackage) {
return ((PsiPackage)psiMember).getQualifiedName();
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java
index 3bfa052..a96e794 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestClassConfigurationProducer.java
@@ -20,6 +20,7 @@
import com.intellij.execution.Location;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.ConfigurationFromContext;
+import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiClass;
@@ -33,9 +34,18 @@
protected boolean setupConfigurationFromContext(JUnitConfiguration configuration,
ConfigurationContext context,
Ref<PsiElement> sourceElement) {
- Location location = JavaExecutionUtil.stepIntoSingleClass(context.getLocation());
+ final Location contextLocation = context.getLocation();
+ assert contextLocation != null;
+ final Location location = JavaExecutionUtil.stepIntoSingleClass(contextLocation);
if (location == null) return false;
+ if (contextLocation instanceof PsiMemberParameterizedLocation) {
+ final String paramSetName = ((PsiMemberParameterizedLocation)contextLocation).getParamSetName();
+ if (paramSetName != null) {
+ configuration.setProgramParameters(paramSetName);
+ }
+ }
+
if (PatternConfigurationProducer.isMultipleElementsSelected(context)) {
return false;
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java b/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java
index 99005b1..3eca5b7 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestMethodConfigurationProducer.java
@@ -21,6 +21,7 @@
import com.intellij.execution.PsiLocation;
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.actions.ConfigurationFromContext;
+import com.intellij.execution.junit2.PsiMemberParameterizedLocation;
import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
@@ -40,14 +41,27 @@
if (PatternConfigurationProducer.isMultipleElementsSelected(context)) {
return false;
}
- Location<PsiMethod> methodLocation = getTestMethod(context.getLocation());
+ final Location contextLocation = context.getLocation();
+ assert contextLocation != null;
+ Location<PsiMethod> methodLocation = getTestMethod(contextLocation);
if (methodLocation == null) return false;
+
+ if (contextLocation instanceof PsiMemberParameterizedLocation) {
+ final String paramSetName = ((PsiMemberParameterizedLocation)contextLocation).getParamSetName();
+ if (paramSetName != null) {
+ configuration.setProgramParameters(paramSetName);
+ }
+ PsiClass containingClass = ((PsiMemberParameterizedLocation)contextLocation).getContainingClass();
+ if (containingClass != null) {
+ methodLocation = MethodLocation.elementInClass(methodLocation.getPsiElement(), containingClass);
+ }
+ }
sourceElement.set(methodLocation.getPsiElement());
setupConfigurationModule(context, configuration);
final Module originalModule = configuration.getConfigurationModule().getModule();
configuration.beMethodConfiguration(methodLocation);
configuration.restoreOriginalModule(originalModule);
- JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, context.getLocation());
+ JavaRunConfigurationExtensionManager.getInstance().extendCreatedConfiguration(configuration, contextLocation);
return true;
}
diff --git a/plugins/junit/src/com/intellij/execution/junit/TestObject.java b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
index 39a280c..01832d6 100644
--- a/plugins/junit/src/com/intellij/execution/junit/TestObject.java
+++ b/plugins/junit/src/com/intellij/execution/junit/TestObject.java
@@ -61,6 +61,7 @@
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.psi.*;
import com.intellij.refactoring.listeners.RefactoringElementListener;
@@ -68,6 +69,7 @@
import com.intellij.rt.execution.junit.JUnitStarter;
import com.intellij.util.Function;
import com.intellij.util.PathUtil;
+import com.intellij.util.ui.UIUtil;
import jetbrains.buildServer.messages.serviceMessages.ServiceMessageTypes;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -191,7 +193,14 @@
}
protected void initialize() throws ExecutionException {
- JavaParametersUtil.configureConfiguration(myJavaParameters, myConfiguration);
+ String parameters = myConfiguration.getProgramParameters();
+ myConfiguration.getPersistentData().setProgramParameters(null);
+ try {
+ JavaParametersUtil.configureConfiguration(myJavaParameters, myConfiguration);
+ }
+ finally {
+ myConfiguration.getPersistentData().setProgramParameters(parameters);
+ }
myJavaParameters.setMainClass(JUnitConfiguration.JUNIT_START_CLASS);
final Module module = myConfiguration.getConfigurationModule().getModule();
if (myJavaParameters.getJdk() == null){
@@ -206,6 +215,9 @@
myJavaParameters.getClassPath().add(PathUtil.getJarPathForClass(ServiceMessageTypes.class));
}
myJavaParameters.getProgramParametersList().add(JUnitStarter.IDE_VERSION + JUnitStarter.VERSION);
+ if (!StringUtil.isEmptyOrSpaces(parameters)) {
+ myJavaParameters.getProgramParametersList().add("@name" + parameters);
+ }
for (RunConfigurationExtension ext : Extensions.getExtensions(RunConfigurationExtension.EP_NAME)) {
ext.updateJavaParameters(myConfiguration, myJavaParameters, getRunnerSettings());
}
@@ -421,12 +433,12 @@
private void appendForkInfo(Executor executor) throws ExecutionException {
final String forkMode = myConfiguration.getForkMode();
if (Comparing.strEqual(forkMode, "none")) {
- final String workingDirectory = myConfiguration.getWorkingDirectory();
- if (!JUnitConfiguration.TEST_PACKAGE.equals(myConfiguration.getPersistentData().TEST_OBJECT) ||
- myConfiguration.getPersistentData().getScope() == TestSearchScope.SINGLE_MODULE ||
- !("$" + PathMacroUtil.MODULE_DIR_MACRO_NAME + "$").equals(workingDirectory)) {
- return;
+ if (forkPerModule() && getRunnerSettings() != null) {
+ final String actionName = UIUtil.removeMnemonic(executor.getStartActionText());
+ throw new CantRunException("'" + actionName + "' is disabled when per-module working directory is configured.<br/>" +
+ "Please specify single working directory, or change test scope to single module.");
}
+ return;
}
if (getRunnerSettings() != null) {
diff --git a/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java b/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java
index 9373667..412d0d1 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/TestProxy.java
@@ -18,6 +18,7 @@
import com.intellij.execution.Location;
import com.intellij.execution.junit2.events.*;
+import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.execution.junit2.info.TestInfo;
import com.intellij.execution.junit2.states.IgnoredState;
import com.intellij.execution.junit2.states.Statistics;
@@ -28,6 +29,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.pom.Navigatable;
+import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.rt.execution.junit.states.PoolOfTestStates;
import org.jetbrains.annotations.NotNull;
@@ -131,7 +133,33 @@
}
public Location getLocation(final Project project, GlobalSearchScope searchScope) {
- return getInfo().getLocation(project, searchScope);
+ final Location location = getInfo().getLocation(project, searchScope);
+ if (location == null) {
+ return checkParentParameterized(project, searchScope);
+ } else {
+ Location parentLocation = getParent().getLocation(project, searchScope);
+ if (parentLocation instanceof PsiMemberParameterizedLocation) {
+ return new PsiMemberParameterizedLocation(project,
+ location.getPsiElement(),
+ location instanceof MethodLocation ? ((MethodLocation)location).getContainingClass() : null,
+ ((PsiMemberParameterizedLocation)parentLocation).getParamSetName());
+ }
+ }
+ return location;
+ }
+
+ private Location checkParentParameterized(Project project, GlobalSearchScope searchScope) {
+ final TestProxy parent = getParent();
+ if (parent != null) {
+ final Location parentLocation = parent.getLocation(project, searchScope);
+ if (parentLocation != null) {
+ final PsiElement parentElement = parentLocation.getPsiElement();
+ if (parentElement instanceof PsiClass) {
+ return PsiMemberParameterizedLocation.getParameterizedLocation((PsiClass)parentElement, getInfo().getName());
+ }
+ }
+ }
+ return null;
}
public boolean isLeaf() {
diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java
index d564b54..f50c153 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurable.java
@@ -214,7 +214,7 @@
}
});
- myCommonJavaParameters.getProgramParametersComponent().setVisible(false);
+ //myCommonJavaParameters.getProgramParametersComponent().setVisible(false);
setAnchor(mySearchForTestsLabel);
myModule.setAnchor(myAlternativeJREPanel.getCbEnabled());
diff --git a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
index fa23dd1..7e4745d 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/configuration/JUnitConfigurationModel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -19,7 +19,7 @@
import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.junit.JUnitConfiguration;
import com.intellij.execution.junit.JUnitUtil;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
@@ -174,7 +174,7 @@
setDocumentText(index, text, myJUnitDocuments);
}
- private static void setDocumentText(final int index, final String text, final Object[] documents) {
+ private void setDocumentText(final int index, final String text, final Object[] documents) {
final Object document = documents[index];
if (document instanceof PlainDocument) {
try {
@@ -186,7 +186,7 @@
}
}
else {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(myProject, new Runnable() {
public void run() {
((Document)document).replaceString(0, ((Document)document).getTextLength(), text);
}
diff --git a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java
index 54f0bc6..b59854e 100644
--- a/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.java
+++ b/plugins/junit/src/com/intellij/execution/junit2/inspection/JUnitEntryPoint.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.
@@ -45,12 +45,12 @@
return InspectionsBundle.message("inspection.dead.code.option2");
}
- public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
return isEntryPoint(psiElement);
}
@Override
- public boolean isEntryPoint(PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull PsiElement psiElement) {
if (ADD_JUNIT_TO_ENTRIES) {
if (psiElement instanceof PsiClass) {
final PsiClass aClass = (PsiClass)psiElement;
diff --git a/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java
index 1f027db..dde361c 100644
--- a/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java
+++ b/plugins/junit_rt/src/com/intellij/junit3/JUnit3IdeaTestRunner.java
@@ -37,7 +37,7 @@
super(DeafStream.DEAF_PRINT_STREAM);
}
- public int startRunnerWithArgs(String[] args, ArrayList listeners, boolean sendTree) {
+ public int startRunnerWithArgs(String[] args, ArrayList listeners, String name, boolean sendTree) {
myListeners = listeners;
mySendTree = sendTree;
if (sendTree) {
@@ -74,7 +74,7 @@
myTestsListener = new TestResultsSender(myRegistry);
}
- public Object getTestToStart(String[] args) {
+ public Object getTestToStart(String[] args, String name) {
return TestRunnerUtil.getTestSuite(this, args);
}
diff --git a/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java b/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java
index 77118a0..3da0f09 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/IdeaSuite.java
@@ -52,9 +52,9 @@
try {
final Method getFilteredChildrenMethod = ParentRunner.class.getDeclaredMethod("getFilteredChildren", new Class[0]);
getFilteredChildrenMethod.setAccessible(true);
- List filteredChildren = (List)getFilteredChildrenMethod.invoke(this, new Object[0]);
- for (int i = 0, filteredChildrenSize = filteredChildren.size(); i < filteredChildrenSize; i++) {
- Object child = filteredChildren.get(i);
+ Collection filteredChildren = (Collection)getFilteredChildrenMethod.invoke(this, new Object[0]);
+ for (Iterator iterator = filteredChildren.iterator(); iterator.hasNext();) {
+ Object child = iterator.next();
description.addChild(describeChild((Runner)child));
}
}
@@ -78,7 +78,7 @@
}
protected List getChildren() {
- final List children = super.getChildren();
+ final List children = new ArrayList(super.getChildren());
final Set allNames = new HashSet();
for (Iterator iterator = children.iterator(); iterator.hasNext();) {
final Object child = iterator.next();
@@ -139,4 +139,4 @@
e.printStackTrace();
}
}
-}
+}
\ No newline at end of file
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java
index 42f6767..a1201c6 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4IdeaTestRunner.java
@@ -34,9 +34,9 @@
private RunListener myTestsListener;
private OutputObjectRegistry myRegistry;
- public int startRunnerWithArgs(String[] args, ArrayList listeners, boolean sendTree) {
+ public int startRunnerWithArgs(String[] args, ArrayList listeners, String name, boolean sendTree) {
- final Request request = JUnit4TestRunnerUtil.buildRequest(args, sendTree);
+ final Request request = JUnit4TestRunnerUtil.buildRequest(args, name, sendTree);
if (request == null) return -1;
final Runner testRunner = request.getRunner();
try {
@@ -145,8 +145,8 @@
}
}
- public Object getTestToStart(String[] args) {
- final Request request = JUnit4TestRunnerUtil.buildRequest(args, false);
+ public Object getTestToStart(String[] args, String name) {
+ final Request request = JUnit4TestRunnerUtil.buildRequest(args, name, false);
if (request == null) return null;
final Runner testRunner = request.getRunner();
Description description = null;
diff --git a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java
index 106e0b2..1e3ea5b 100644
--- a/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java
+++ b/plugins/junit_rt/src/com/intellij/junit4/JUnit4TestRunnerUtil.java
@@ -33,6 +33,7 @@
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.MessageFormat;
import java.util.*;
@@ -43,7 +44,7 @@
*/
private static final ResourceBundle ourBundle = ResourceBundle.getBundle("RuntimeBundle");
- public static Request buildRequest(String[] suiteClassNames, boolean notForked) {
+ public static Request buildRequest(String[] suiteClassNames, String name, boolean notForked) {
if (suiteClassNames.length == 0) {
return null;
}
@@ -143,15 +144,9 @@
//return simple method runner
}
} else {
- final Class runnerClass = clazzAnnotation.value();
- if (runnerClass.isAssignableFrom(Parameterized.class)) {
- try {
- Class.forName("org.junit.runners.BlockJUnit4ClassRunner"); //ignore for junit4.4 and <
- return Request.runner(new ParameterizedMethodRunner(clazz, methodName));
- }
- catch (Throwable throwable) {
- //return simple method runner
- }
+ final Request request = getParameterizedRequest(name, clazz, methodName, clazzAnnotation);
+ if (request != null) {
+ return request;
}
}
try {
@@ -163,6 +158,15 @@
//ignore
}
return Request.method(clazz, methodName);
+ } else if (name != null && suiteClassNames.length == 1) {
+ final Class clazz = loadTestClass(suiteClassName);
+ if (clazz != null) {
+ final RunWith clazzAnnotation = (RunWith)clazz.getAnnotation(RunWith.class);
+ final Request request = getParameterizedRequest(name, clazz, null, clazzAnnotation);
+ if (request != null) {
+ return request;
+ }
+ }
}
appendTestClass(result, suiteClassName);
}
@@ -183,6 +187,22 @@
return Request.classes(getArrayOfClasses(result));
}
+ private static Request getParameterizedRequest(String name, Class clazz, String methodName, RunWith clazzAnnotation) {
+ if (clazzAnnotation == null) return null;
+
+ final Class runnerClass = clazzAnnotation.value();
+ if (Parameterized.class.isAssignableFrom(runnerClass)) {
+ try {
+ Class.forName("org.junit.runners.BlockJUnit4ClassRunner"); //ignore for junit4.4 and <
+ return Request.runner(new SelectedParameterizedRunner(clazz, name, methodName, runnerClass));
+ }
+ catch (Throwable throwable) {
+ //return simple method runner
+ }
+ }
+ return null;
+ }
+
private static Request createIgnoreIgnoredClassRequest(final Class clazz, final boolean recursively) throws ClassNotFoundException {
Class.forName("org.junit.runners.BlockJUnit4ClassRunner"); //ignore IgnoreIgnored for junit4.4 and <
return new ClassRequest(clazz) {
@@ -280,31 +300,75 @@
}
}
- private static class ParameterizedMethodRunner extends Parameterized {
+ private static class SelectedParameterizedRunner extends Parameterized {
+ private final String myName;
private final String myMethodName;
+ private Parameterized myRunnerClass;
- public ParameterizedMethodRunner(Class clazz, String methodName) throws Throwable {
+ public SelectedParameterizedRunner(Class clazz, String name, String methodName, Class runnerClass) throws Throwable {
super(clazz);
+ myName = name;
myMethodName = methodName;
+ myRunnerClass = (Parameterized)runnerClass.getConstructor(new Class[] {Class.class}).newInstance(new Object[]{clazz});
}
protected List getChildren() {
- final List children = super.getChildren();
- for (int i = 0; i < children.size(); i++) {
- try {
- final BlockJUnit4ClassRunner child = (BlockJUnit4ClassRunner)children.get(i);
- final Method getChildrenMethod = BlockJUnit4ClassRunner.class.getDeclaredMethod("getChildren", new Class[0]);
- getChildrenMethod.setAccessible(true);
- final List list = (List)getChildrenMethod.invoke(child, new Object[0]);
- for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
- final FrameworkMethod description = (FrameworkMethod)iterator.next();
- if (!description.getName().equals(myMethodName)) {
+ List children;
+ try {
+ Method getChildren = Parameterized.class.getDeclaredMethod("getChildren", new Class[0]);
+ getChildren.setAccessible(true);
+ children = (List)getChildren.invoke(myRunnerClass, new Object[0]);
+ }
+ catch (Throwable e) {
+ children = super.getChildren();
+ }
+
+ //filter by params
+ if (myName != null) {
+ for (Iterator iterator = children.iterator(); iterator.hasNext(); ) {
+ Object child = iterator.next();
+ try {
+ Field f;
+ try {
+ f = child.getClass().getDeclaredField("fName");
+ }
+ catch (NoSuchFieldException e) {
+ continue;
+ }
+ f.setAccessible(true);
+ String fName = (String)f.get(child);
+ if (!myName.equals(fName)) {
iterator.remove();
}
}
+ catch (Exception e) {
+ e.printStackTrace();
+ }
}
- catch (Exception e) {
- e.printStackTrace();
+ if (children.isEmpty()) {
+ System.err.println("No tests were found by passed name: " + myName);
+ System.exit(1);
+ }
+ }
+
+ //filter only selected method
+ if (myMethodName != null) {
+ for (int i = 0; i < children.size(); i++) {
+ try {
+ final BlockJUnit4ClassRunner child = (BlockJUnit4ClassRunner)children.get(i);
+ final Method getChildrenMethod = BlockJUnit4ClassRunner.class.getDeclaredMethod("getChildren", new Class[0]);
+ getChildrenMethod.setAccessible(true);
+ final List list = (List)getChildrenMethod.invoke(child, new Object[0]);
+ for (Iterator iterator = list.iterator(); iterator.hasNext(); ) {
+ final FrameworkMethod description = (FrameworkMethod)iterator.next();
+ if (!description.getName().equals(myMethodName)) {
+ iterator.remove();
+ }
+ }
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
}
}
return children;
diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/IdeaTestRunner.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/IdeaTestRunner.java
index cd1cbb9..7937ee2 100644
--- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/IdeaTestRunner.java
+++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/IdeaTestRunner.java
@@ -28,10 +28,10 @@
public interface IdeaTestRunner {
- int startRunnerWithArgs(String[] args, ArrayList listeners, boolean sendTree);
+ int startRunnerWithArgs(String[] args, ArrayList listeners, String name, boolean sendTree);
void setStreams(SegmentedOutputStream segmentedOut, SegmentedOutputStream segmentedErr, int lastIdx);
- Object getTestToStart(String[] args);
+ Object getTestToStart(String[] args, String name);
List getChildTests(Object description);
String getStartDescription(Object child);
diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java
index 3f3276a..dbb575a 100644
--- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java
+++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitForkedStarter.java
@@ -57,7 +57,7 @@
IdeaTestRunner testRunner = (IdeaTestRunner)JUnitStarter.getAgentClass(isJUnit4).newInstance();
//noinspection IOResourceOpenedButNotSafelyClosed
testRunner.setStreams(new SegmentedOutputStream(out, true), new SegmentedOutputStream(err, true), lastIdx);
- System.exit(testRunner.startRunnerWithArgs(childTestDescription, listeners, false));
+ System.exit(testRunner.startRunnerWithArgs(childTestDescription, listeners, null, false));
}
finally {
System.setOut(oldOut);
@@ -70,7 +70,7 @@
String[] args,
boolean isJUnit4,
List listeners,
- SegmentedOutputStream out,
+ String params, SegmentedOutputStream out,
SegmentedOutputStream err,
String forkMode,
String path) throws Exception {
@@ -88,7 +88,7 @@
IdeaTestRunner testRunner = (IdeaTestRunner)JUnitStarter.getAgentClass(isJUnit4).newInstance();
testRunner.setStreams(out, err, 0);
- final Object description = testRunner.getTestToStart(args);
+ final Object description = testRunner.getTestToStart(args, params);
if (description == null) return -1;
TreeSender.sendTree(testRunner, description, true);
diff --git a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java
index 1ed5c0c..cb398d9 100644
--- a/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java
+++ b/plugins/junit_rt/src/com/intellij/rt/execution/junit/JUnitStarter.java
@@ -49,7 +49,9 @@
}
final ArrayList listeners = new ArrayList();
- boolean isJUnit4 = processParameters(argList, listeners);
+ final String[] name = new String[1];
+
+ boolean isJUnit4 = processParameters(argList, listeners, name);
if (!canWorkWithJUnitVersion(err, isJUnit4)) {
err.flush();
@@ -62,11 +64,11 @@
String[] array = new String[argList.size()];
argList.copyInto(array);
- int exitCode = prepareStreamsAndStart(array, isJUnit4, listeners, out, err);
+ int exitCode = prepareStreamsAndStart(array, isJUnit4, listeners, name[0], out, err);
System.exit(exitCode);
}
- private static boolean processParameters(Vector args, final List listeners) {
+ private static boolean processParameters(Vector args, final List listeners, String[] params) {
boolean isJunit4 = true;
Vector result = new Vector(args.size());
for (int i = 0; i < args.size(); i++) {
@@ -78,7 +80,10 @@
isJunit4 = false;
}
else {
- if (arg.startsWith("@w@")) {
+ if (arg.startsWith("@name")) {
+ params[0] = arg.substring("@name".length());
+ continue;
+ } else if (arg.startsWith("@w@")) {
ourWorkingDirs = arg.substring(3);
continue;
} else if (arg.startsWith("@@@")) {
@@ -185,7 +190,11 @@
new junit.textui.TestRunner().setPrinter(new com.intellij.junit3.JUnit3IdeaTestRunner.MockResultPrinter());
}
- private static int prepareStreamsAndStart(String[] args, final boolean isJUnit4, ArrayList listeners, SegmentedOutputStream out,
+ private static int prepareStreamsAndStart(String[] args,
+ final boolean isJUnit4,
+ ArrayList listeners,
+ String name,
+ SegmentedOutputStream out,
SegmentedOutputStream err) {
PrintStream oldOut = System.out;
PrintStream oldErr = System.err;
@@ -194,12 +203,12 @@
System.setErr(new PrintStream(err));
if (ourCommandFileName != null) {
if (!"none".equals(ourForkMode) || ourWorkingDirs != null && new File(ourWorkingDirs).length() > 0) {
- return JUnitForkedStarter.startForkedVMs(ourWorkingDirs, args, isJUnit4, listeners, out, err, ourForkMode, ourCommandFileName);
+ return JUnitForkedStarter.startForkedVMs(ourWorkingDirs, args, isJUnit4, listeners, name, out, err, ourForkMode, ourCommandFileName);
}
}
IdeaTestRunner testRunner = (IdeaTestRunner)getAgentClass(isJUnit4).newInstance();
testRunner.setStreams(out, err, 0);
- return testRunner.startRunnerWithArgs(args, listeners, !SM_RUNNER);
+ return testRunner.startRunnerWithArgs(args, listeners, name, !SM_RUNNER);
}
catch (Exception e) {
e.printStackTrace(System.err);
diff --git a/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml b/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml
index 527e632..95bee8a 100644
--- a/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml
+++ b/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml
@@ -11,7 +11,7 @@
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/aether-api-1.11.jar!/" />
+ <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/aether-api-1.13.1.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -20,7 +20,7 @@
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/maven-core-3.0.3.jar!/" />
+ <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/maven-core-3.0.5.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
@@ -29,7 +29,7 @@
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.3.jar!/" />
+ <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.5.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
diff --git a/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml b/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml
index 3d45f6b..e859fa2 100644
--- a/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml
+++ b/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml
@@ -10,7 +10,7 @@
<orderEntry type="module-library">
<library>
<CLASSES>
- <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/maven-core-3.0.3.jar!/" />
+ <root url="jar://$MODULE_DIR$/../maven3-server-impl/lib/maven3/lib/maven-core-3.0.5.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
diff --git a/plugins/maven/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.artifacts.instructions.ArtifactRootCopyingHandlerProvider b/plugins/maven/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.artifacts.instructions.ArtifactRootCopyingHandlerProvider
new file mode 100644
index 0000000..40e7c09
--- /dev/null
+++ b/plugins/maven/jps-plugin/src/META-INF/services/org.jetbrains.jps.incremental.artifacts.instructions.ArtifactRootCopyingHandlerProvider
@@ -0,0 +1 @@
+org.jetbrains.jps.maven.compiler.MavenWebArtifactRootCopyingHandlerProvider
\ No newline at end of file
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourceFileProcessor.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourceFileProcessor.java
new file mode 100644
index 0000000..bc405be
--- /dev/null
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourceFileProcessor.java
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.maven.compiler;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.messages.BuildMessage;
+import org.jetbrains.jps.incremental.messages.CompilerMessage;
+import org.jetbrains.jps.maven.model.impl.MavenModuleResourceConfiguration;
+import org.jetbrains.jps.maven.model.impl.MavenProjectConfiguration;
+import org.jetbrains.jps.maven.model.impl.ResourceRootConfiguration;
+import org.jetbrains.jps.model.JpsEncodingConfigurationService;
+import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
+import org.jetbrains.jps.model.JpsProject;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * @author nik
+ */
+public class MavenResourceFileProcessor {
+ private static final int FILTERING_SIZE_LIMIT = 10 * 1024 * 1024 /*10 mb*/;
+ private static final String MAVEN_BUILD_TIMESTAMP_PROPERTY = "maven.build.timestamp";
+ private static final String MAVEN_BUILD_TIMESTAMP_FORMAT_PROPERTY = "maven.build.timestamp.format";
+ protected final Set<String> myFilteringExcludedExtensions;
+ protected final JpsEncodingProjectConfiguration myEncodingConfig;
+ protected final MavenProjectConfiguration myProjectConfig;
+ protected final MavenModuleResourceConfiguration myModuleConfiguration;
+ protected final Date myTimestamp;
+ private Map<String, String> myProperties;
+ private Pattern myDelimitersPattern;
+
+ public MavenResourceFileProcessor(MavenProjectConfiguration projectConfiguration, JpsProject project,
+ MavenModuleResourceConfiguration moduleConfiguration) {
+ myTimestamp = new Date();
+ myProjectConfig = projectConfiguration;
+ myEncodingConfig = JpsEncodingConfigurationService.getInstance().getEncodingConfiguration(project);
+ myModuleConfiguration = moduleConfiguration;
+ myFilteringExcludedExtensions = moduleConfiguration.getFilteringExcludedExtensions();
+ }
+
+ protected void copyFile(File file, File targetFile, ResourceRootConfiguration rootConfiguration, CompileContext context) throws IOException {
+ boolean shouldFilter = rootConfiguration.isFiltered && !myFilteringExcludedExtensions.contains(FileUtilRt.getExtension(file.getName()));
+ if (shouldFilter && file.length() > FILTERING_SIZE_LIMIT) {
+ context.processMessage(new CompilerMessage("MavenResources", BuildMessage.Kind.WARNING,
+ "File is too big to be filtered. Most likely it is a binary file and should be excluded from filtering",
+ file.getPath()));
+ shouldFilter = false;
+ }
+ if (shouldFilter) {
+ copyWithFiltering(file, targetFile);
+ }
+ else {
+ FileUtil.copyContent(file, targetFile);
+ }
+ }
+
+ private void copyWithFiltering(File file, File outputFile) throws IOException {
+ final String encoding = myEncodingConfig != null? myEncodingConfig.getEncoding(file) : null;
+ PrintWriter writer;
+ try {
+ writer = encoding != null ? new PrintWriter(outputFile, encoding) : new PrintWriter(outputFile);
+ }
+ catch (FileNotFoundException e) {
+ FileUtil.createIfDoesntExist(outputFile);
+ writer = encoding != null ? new PrintWriter(outputFile, encoding) : new PrintWriter(outputFile);
+ }
+ try {
+ final byte[] bytes = FileUtil.loadFileBytes(file);
+ final String text = encoding != null? new String(bytes, encoding) : new String(bytes);
+ doFilterText(text, getDelimitersPattern(), getProperties(), null, writer);
+ }
+ finally {
+ writer.close();
+ }
+ }
+
+ private void doFilterText(String text, Pattern delimitersPattern,
+ @NotNull Map<String, String> additionalProperties,
+ @Nullable Map<String, String> resolvedPropertiesParam,
+ final Appendable out) throws IOException {
+ Map<String, String> resolvedProperties = resolvedPropertiesParam;
+
+ final Matcher matcher = delimitersPattern.matcher(text);
+
+ boolean hasEscapeString = !StringUtil.isEmpty(myModuleConfiguration.escapeString);
+
+ final int groupCount = matcher.groupCount();
+ int firstPropertyGroupIndex = hasEscapeString ? 3 : 0;
+
+ int last = 0;
+ while (matcher.find()) {
+ out.append(text, last, matcher.start());
+ last = matcher.end();
+
+ if (hasEscapeString) {
+ if (matcher.group(1) != null) {
+ out.append(myModuleConfiguration.escapeString).append(myModuleConfiguration.escapeString); // double escape string
+ continue;
+ }
+ else if (matcher.group(2) != null) {
+ out.append(matcher.group(3)); // escaped value
+ continue;
+ }
+ }
+
+ String propertyName = null;
+
+ for (int i = firstPropertyGroupIndex; i < groupCount; i++) {
+ propertyName = matcher.group(i + 1);
+ if (propertyName != null) {
+ break;
+ }
+ }
+
+ assert propertyName != null;
+
+ if (resolvedProperties == null) {
+ resolvedProperties = new HashMap<String, String>();
+ }
+
+ String propertyValue = resolvedProperties.get(propertyName);
+ if (propertyValue == null) {
+ if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies
+ out.append(matcher.group());
+ continue;
+ }
+
+ String resolved = myProjectConfig.resolveProperty(propertyName, myModuleConfiguration, additionalProperties);
+ if (resolved == null) {
+ out.append(matcher.group());
+ continue;
+ }
+
+ resolvedProperties.put(propertyName, null);
+
+ StringBuilder sb = new StringBuilder();
+ doFilterText(resolved, delimitersPattern, additionalProperties, resolvedProperties, sb);
+ propertyValue = sb.toString();
+
+ resolvedProperties.put(propertyName, propertyValue);
+ }
+
+ if (myModuleConfiguration.escapeWindowsPaths) {
+ MavenEscapeWindowsCharacterUtils.escapeWindowsPath(out, propertyValue);
+ }
+ else {
+ out.append(propertyValue);
+ }
+ }
+
+ out.append(text, last, text.length());
+ }
+
+ private Pattern getDelimitersPattern() {
+ Pattern pattern = myDelimitersPattern;
+ if (pattern == null) {
+ if (StringUtil.isEmpty(myModuleConfiguration.escapeString)) {
+ pattern = Pattern.compile(myModuleConfiguration.delimitersPattern);
+ }
+ else {
+ String quotedEscapeString = Pattern.quote(myModuleConfiguration.escapeString);
+ pattern = Pattern.compile("(" + quotedEscapeString + quotedEscapeString + ")|(?:(" + quotedEscapeString + ")?(" + myModuleConfiguration.delimitersPattern + "))");
+ }
+ myDelimitersPattern = pattern;
+ }
+ return pattern;
+ }
+
+ private Map<String, String> getProperties() {
+ Map<String, String> props = myProperties;
+ if (props == null) {
+ props = new HashMap<String, String>(myModuleConfiguration.properties);
+ String timestampFormat = props.get(MAVEN_BUILD_TIMESTAMP_FORMAT_PROPERTY);
+ if (timestampFormat == null) {
+ timestampFormat = "yyyyMMdd-HHmm"; // See ModelInterpolator.DEFAULT_BUILD_TIMESTAMP_FORMAT
+ }
+ props.put(MAVEN_BUILD_TIMESTAMP_PROPERTY, new SimpleDateFormat(timestampFormat).format(myTimestamp));
+ myProperties = props;
+ }
+ return props;
+ }
+}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
index 13bf786..749557c 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenResourcesBuilder.java
@@ -1,9 +1,7 @@
package org.jetbrains.jps.maven.compiler;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
@@ -16,14 +14,12 @@
import org.jetbrains.jps.incremental.messages.ProgressMessage;
import org.jetbrains.jps.maven.model.JpsMavenExtensionService;
import org.jetbrains.jps.maven.model.impl.*;
-import org.jetbrains.jps.model.JpsEncodingConfigurationService;
-import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
-import java.io.*;
-import java.text.SimpleDateFormat;
-import java.util.*;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
+import java.io.File;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+import java.util.Collections;
/**
* @author Eugene Zhuravlev
@@ -31,9 +27,6 @@
*/
public class MavenResourcesBuilder extends TargetBuilder<MavenResourceRootDescriptor, MavenResourcesTarget> {
public static final String BUILDER_NAME = "Maven Resources Compiler";
- private static final int FILTERING_SIZE_LIMIT = 10 * 1024 * 1024 /*10 mb*/;
- private static final String MAVEN_BUILD_TIMESTAMP_PROPERTY = "maven.build.timestamp";
- private static final String MAVEN_BUILD_TIMESTAMP_FORMAT_PROPERTY = "maven.build.timestamp.format";
public MavenResourcesBuilder() {
super(Arrays.asList(MavenResourcesTargetType.PRODUCTION, MavenResourcesTargetType.TEST));
@@ -47,15 +40,9 @@
if (config == null) {
return;
}
- final Set<String> filteringExcludedExtensions = config.getFilteringExcludedExtensions();
- final JpsEncodingProjectConfiguration encodingConfig =
- JpsEncodingConfigurationService.getInstance().getEncodingConfiguration(target.getModule().getProject());
- final Date timestamp = new Date();
-
+ final MavenResourceFileProcessor fileProcessor = new MavenResourceFileProcessor(projectConfig, target.getModule().getProject(), config);
holder.processDirtyFiles(new FileProcessor<MavenResourceRootDescriptor, MavenResourcesTarget>() {
- private Map<String, String> myProperties;
- private Pattern myDelimitersPattern;
@Override
public boolean apply(MavenResourcesTarget target, File file, MavenResourceRootDescriptor rd) throws IOException {
@@ -69,80 +56,18 @@
}
final File outputFile = new File(outputDir, relPath);
final String sourcePath = file.getPath();
- boolean shouldFilter = rd.getConfiguration().isFiltered && !filteringExcludedExtensions.contains(getExtension(file));
- if (shouldFilter && file.length() > FILTERING_SIZE_LIMIT) {
- context.processMessage(new CompilerMessage("MavenResources", BuildMessage.Kind.WARNING, "File is too big to be filtered. Most likely it is a binary file and should be excluded from filtering", sourcePath));
- shouldFilter = false;
- }
try {
context.processMessage(new ProgressMessage("Copying resources... [" + target.getModule().getName() + "]"));
- if (shouldFilter) {
- copyWithFiltering(file, outputFile);
- }
- else {
- FileUtil.copyContent(file, outputFile);
- }
+ fileProcessor.copyFile(file, outputFile, rd.getConfiguration(), context);
outputConsumer.registerOutputFile(outputFile, Collections.singleton(sourcePath));
}
catch (UnsupportedEncodingException e) {
- context.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, "Resource was not copied: " + e.getMessage(), sourcePath));
+ context.processMessage(
+ new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, "Resource was not copied: " + e.getMessage(), sourcePath));
}
return !context.getCancelStatus().isCanceled();
}
-
- private void copyWithFiltering(File file, File outputFile) throws IOException {
- final String encoding = encodingConfig != null? encodingConfig.getEncoding(file) : null;
- PrintWriter writer;
- try {
- writer = encoding != null ? new PrintWriter(outputFile, encoding) : new PrintWriter(outputFile);
- }
- catch (FileNotFoundException e) {
- FileUtil.createIfDoesntExist(outputFile);
- writer = encoding != null ? new PrintWriter(outputFile, encoding) : new PrintWriter(outputFile);
- }
- try {
- final byte[] bytes = FileUtil.loadFileBytes(file);
- final String text = encoding != null? new String(bytes, encoding) : new String(bytes);
- doFilterText(
- getDelimitersPattern(), text, projectConfig, config, getProperties(), null,
- writer
- );
- }
- finally {
- writer.close();
- }
- }
-
- private Pattern getDelimitersPattern() {
- Pattern pattern = myDelimitersPattern;
- if (pattern == null) {
- if (StringUtil.isEmpty(config.escapeString)) {
- pattern = Pattern.compile(config.delimitersPattern);
- }
- else {
- String quotedEscapeString = Pattern.quote(config.escapeString);
- pattern = Pattern.compile("(" + quotedEscapeString + quotedEscapeString + ")|(?:(" + quotedEscapeString + ")?(" + config.delimitersPattern + "))");
- }
- myDelimitersPattern = pattern;
- }
- return pattern;
- }
-
- private Map<String, String> getProperties() {
- Map<String, String> props = myProperties;
- if (props == null) {
- props = new HashMap<String, String>(config.properties);
- String timestampFormat = props.get(MAVEN_BUILD_TIMESTAMP_FORMAT_PROPERTY);
- if (timestampFormat == null) {
- timestampFormat = "yyyyMMdd-HHmm"; // See ModelInterpolator.DEFAULT_BUILD_TIMESTAMP_FORMAT
- }
- props.put(MAVEN_BUILD_TIMESTAMP_PROPERTY, new SimpleDateFormat(timestampFormat).format(timestamp));
- myProperties = props;
- }
- return props;
- }
-
});
context.checkCanceled();
@@ -155,94 +80,4 @@
public String getPresentableName() {
return BUILDER_NAME;
}
-
- private static String getExtension(File file) {
- final String name = file.getName();
- final int dotindex = name.lastIndexOf(".");
- if (dotindex < 0) {
- return "";
- }
- return name.substring(dotindex + 1);
- }
-
- private static void doFilterText(Pattern delimitersPattern,
- String text,
- MavenProjectConfiguration projectConfig,
- MavenModuleResourceConfiguration moduleConfig,
- @NotNull Map<String, String> additionalProperties,
- @Nullable Map<String, String> resolvedPropertiesParam,
- final Appendable out) throws IOException {
- Map<String, String> resolvedProperties = resolvedPropertiesParam;
-
- final Matcher matcher = delimitersPattern.matcher(text);
-
- boolean hasEscapeString = !StringUtil.isEmpty(moduleConfig.escapeString);
-
- final int groupCount = matcher.groupCount();
- int firstPropertyGroupIndex = hasEscapeString ? 3 : 0;
-
- int last = 0;
- while (matcher.find()) {
- out.append(text, last, matcher.start());
- last = matcher.end();
-
- if (hasEscapeString) {
- if (matcher.group(1) != null) {
- out.append(moduleConfig.escapeString).append(moduleConfig.escapeString); // double escape string
- continue;
- }
- else if (matcher.group(2) != null) {
- out.append(matcher.group(3)); // escaped value
- continue;
- }
- }
-
- String propertyName = null;
-
- for (int i = firstPropertyGroupIndex; i < groupCount; i++) {
- propertyName = matcher.group(i + 1);
- if (propertyName != null) {
- break;
- }
- }
-
- assert propertyName != null;
-
- if (resolvedProperties == null) {
- resolvedProperties = new HashMap<String, String>();
- }
-
- String propertyValue = resolvedProperties.get(propertyName);
- if (propertyValue == null) {
- if (resolvedProperties.containsKey(propertyName)) { // if cyclic property dependencies
- out.append(matcher.group());
- continue;
- }
-
- String resolved = projectConfig.resolveProperty(propertyName, moduleConfig, additionalProperties);
- if (resolved == null) {
- out.append(matcher.group());
- continue;
- }
-
- resolvedProperties.put(propertyName, null);
-
- StringBuilder sb = new StringBuilder();
- doFilterText(delimitersPattern, resolved, projectConfig, moduleConfig, additionalProperties, resolvedProperties, sb);
- propertyValue = sb.toString();
-
- resolvedProperties.put(propertyName, propertyValue);
- }
-
- if (moduleConfig.escapeWindowsPaths) {
- MavenEscapeWindowsCharacterUtils.escapeWindowsPath(out, propertyValue);
- }
- else {
- out.append(propertyValue);
- }
- }
-
- out.append(text, last, text.length());
- }
-
}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenWebArtifactRootCopyingHandlerProvider.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenWebArtifactRootCopyingHandlerProvider.java
new file mode 100644
index 0000000..b977bb6
--- /dev/null
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/compiler/MavenWebArtifactRootCopyingHandlerProvider.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.maven.compiler;
+
+import com.intellij.openapi.diagnostic.Logger;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.storage.BuildDataPaths;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.artifacts.instructions.ArtifactRootCopyingHandlerProvider;
+import org.jetbrains.jps.incremental.artifacts.instructions.FileCopyingHandler;
+import org.jetbrains.jps.maven.model.JpsMavenExtensionService;
+import org.jetbrains.jps.maven.model.impl.*;
+import org.jetbrains.jps.model.JpsModel;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * @author nik
+ */
+public class MavenWebArtifactRootCopyingHandlerProvider extends ArtifactRootCopyingHandlerProvider {
+ private static final Logger LOG = Logger.getInstance(MavenWebArtifactRootCopyingHandlerProvider.class);
+ @Nullable
+ @Override
+ public FileCopyingHandler createCustomHandler(@NotNull JpsArtifact artifact, @NotNull File root, @NotNull JpsModel model,
+ @NotNull BuildDataPaths buildDataPaths) {
+ JpsMavenExtensionService mavenExtensionService = JpsMavenExtensionService.getInstance();
+ if (!mavenExtensionService.hasMavenProjectConfiguration(buildDataPaths)) return null;
+
+ MavenProjectConfiguration projectConfiguration = mavenExtensionService.getMavenProjectConfiguration(buildDataPaths);
+ MavenArtifactResourceConfiguration artifactResourceConfiguration = projectConfiguration.artifactsResources.get(artifact.getName());
+ if (artifactResourceConfiguration == null) return null;
+
+ ResourceRootConfiguration rootConfiguration = artifactResourceConfiguration.getRootConfiguration(root);
+ if (rootConfiguration == null) return null;
+
+ MavenModuleResourceConfiguration moduleResourceConfiguration = projectConfiguration.moduleConfigurations.get(artifactResourceConfiguration.moduleName);
+ if (moduleResourceConfiguration == null) {
+ LOG.debug("Maven resource configuration not found for module " + artifactResourceConfiguration.moduleName);
+ return null;
+ }
+
+ MavenResourceFileProcessor fileProcessor = new MavenResourceFileProcessor(projectConfiguration, model.getProject(), moduleResourceConfiguration);
+ return new MavenWebRootCopyingHandler(fileProcessor, rootConfiguration, moduleResourceConfiguration, root);
+ }
+
+ private static class MavenWebRootCopyingHandler extends FileCopyingHandler {
+ private final MavenResourceFileProcessor myFileProcessor;
+ @NotNull private final ResourceRootConfiguration myRootConfiguration;
+ @NotNull private final MavenModuleResourceConfiguration myModuleResourceConfiguration;
+ @NotNull private final File myRoot;
+
+ private MavenWebRootCopyingHandler(@NotNull MavenResourceFileProcessor fileProcessor,
+ @NotNull ResourceRootConfiguration rootConfiguration,
+ @NotNull MavenModuleResourceConfiguration moduleResourceConfiguration,
+ @NotNull File root) {
+ myFileProcessor = fileProcessor;
+ myRootConfiguration = rootConfiguration;
+ myModuleResourceConfiguration = moduleResourceConfiguration;
+ myRoot = root;
+ }
+
+ @Override
+ public void copyFile(@NotNull File from, @NotNull File to, @NotNull CompileContext context) throws IOException {
+ myFileProcessor.copyFile(from, to, myRootConfiguration, context);
+ }
+
+ @Override
+ public void writeConfiguration(@NotNull PrintWriter out) {
+ out.print("maven hash:");
+ out.println(myModuleResourceConfiguration.computeModuleConfigurationHash() + 31*myRootConfiguration.computeConfigurationHash());
+ }
+
+ @NotNull
+ @Override
+ public FileFilter createFileFilter() {
+ return new MavenResourceFileFilter(myRoot, myRootConfiguration);
+ }
+ }
+}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/JpsMavenExtensionService.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/JpsMavenExtensionService.java
index b4b6e7d..c5b4b19 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/JpsMavenExtensionService.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/JpsMavenExtensionService.java
@@ -26,6 +26,8 @@
public abstract boolean isProductionOnTestDependency(@NotNull JpsDependencyElement dependency);
+ public abstract boolean hasMavenProjectConfiguration(@NotNull BuildDataPaths paths);
+
@NotNull
public abstract MavenProjectConfiguration getMavenProjectConfiguration(BuildDataPaths paths);
}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
index 6b710ff..8a09cc6 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/JpsMavenExtensionServiceImpl.java
@@ -2,6 +2,9 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.util.containers.ConcurrentFactoryMap;
+import com.intellij.util.containers.FactoryMap;
import com.intellij.util.xmlb.XmlSerializer;
import gnu.trove.THashMap;
import org.jdom.Document;
@@ -28,6 +31,15 @@
public class JpsMavenExtensionServiceImpl extends JpsMavenExtensionService {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.maven.model.impl.JpsMavenExtensionServiceImpl");
private static final JpsElementChildRole<JpsSimpleElement<Boolean>> PRODUCTION_ON_TEST_ROLE = JpsElementChildRoleBase.create("production on test");
+ private final Map<File, MavenProjectConfiguration> myLoadedConfigs =
+ new THashMap<File, MavenProjectConfiguration>(FileUtil.FILE_HASHING_STRATEGY);
+ private final FactoryMap<File, Boolean> myConfigFileExists = new ConcurrentFactoryMap<File, Boolean>() {
+ @Nullable
+ @Override
+ protected Boolean create(File key) {
+ return key.exists();
+ }
+ };
public JpsMavenExtensionServiceImpl() {
ResourcesBuilder.registerEnabler(new StandardResourceBuilderEnabler() {
@@ -73,7 +85,10 @@
return child != null && child.getData();
}
- private final Map<File, MavenProjectConfiguration> myLoadedConfigs = new THashMap<File, MavenProjectConfiguration>();
+ @Override
+ public boolean hasMavenProjectConfiguration(@NotNull BuildDataPaths paths) {
+ return myConfigFileExists.get(new File(paths.getDataStorageRoot(), MavenProjectConfiguration.CONFIGURATION_FILE_RELATIVE_PATH));
+ }
@NotNull
@Override
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenArtifactResourceConfiguration.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenArtifactResourceConfiguration.java
index d0988e3..1a62548 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenArtifactResourceConfiguration.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenArtifactResourceConfiguration.java
@@ -15,21 +15,45 @@
*/
package org.jetbrains.jps.maven.model.impl;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Tag;
+import com.intellij.util.xmlb.annotations.Transient;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import java.io.File;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* @author Sergey Evdokimov
*/
public class MavenArtifactResourceConfiguration {
-
+ @Tag("web-artifact-name")
public String webArtifactName;
+ @Tag("module-name")
+ public String moduleName;
+
@Tag("web-resources")
@AbstractCollection(surroundWithTag = false, elementTag = "resource")
public List<ResourceRootConfiguration> webResources = new ArrayList<ResourceRootConfiguration>();
+ @Transient
+ private volatile Map<File, ResourceRootConfiguration> myResourceRootsMap;
+
+ @Nullable
+ public ResourceRootConfiguration getRootConfiguration(@NotNull File root) {
+ if (myResourceRootsMap == null) {
+ Map<File, ResourceRootConfiguration> map = new THashMap<File, ResourceRootConfiguration>(FileUtil.FILE_HASHING_STRATEGY);
+ for (ResourceRootConfiguration resource : webResources) {
+ map.put(new File(resource.directory), resource);
+ }
+ myResourceRootsMap = map;
+ }
+ return myResourceRootsMap.get(root);
+ }
}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java
index 86340ad..62f8922 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenModuleResourceConfiguration.java
@@ -82,15 +82,7 @@
}
public int computeConfigurationHash(boolean forTestResources) {
- int result = id.hashCode();
- result = 31 * result + (parentId != null ? parentId.hashCode() : 0);
- result = 31 * result + directory.hashCode();
- result = 31 * result + delimitersPattern.hashCode();
- result = 31 * result + modelMap.hashCode();
- result = 31 * result + properties.hashCode();
- result = 31 * result + filteringExclusions.hashCode();
- result = 31 * result + (escapeString != null ? escapeString.hashCode() : 0);
- result = 31 * result + (escapeWindowsPaths ? 1 : 0);
+ int result = computeModuleConfigurationHash();
final List<ResourceRootConfiguration> _resources = forTestResources? testResources : resources;
result = 31 * result;
@@ -100,6 +92,18 @@
return result;
}
+ public int computeModuleConfigurationHash() {
+ int result = id.hashCode();
+ result = 31 * result + (parentId != null ? parentId.hashCode() : 0);
+ result = 31 * result + directory.hashCode();
+ result = 31 * result + delimitersPattern.hashCode();
+ result = 31 * result + modelMap.hashCode();
+ result = 31 * result + properties.hashCode();
+ result = 31 * result + filteringExclusions.hashCode();
+ result = 31 * result + (escapeString != null ? escapeString.hashCode() : 0);
+ result = 31 * result + (escapeWindowsPaths ? 1 : 0);
+ return result;
+ }
}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceFileFilter.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceFileFilter.java
new file mode 100644
index 0000000..e2c3e72
--- /dev/null
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceFileFilter.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.maven.model.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.codehaus.plexus.util.SelectorUtils;
+import org.codehaus.plexus.util.StringUtils;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Collection;
+
+/**
+* @author nik
+*/
+public class MavenResourceFileFilter implements FileFilter {
+ private String[] myNormalizedIncludes;
+ private String[] myNormalizedExcludes;
+ private ResourceRootConfiguration myConfiguration;
+ private File myRoot;
+
+ public MavenResourceFileFilter(@NotNull File rootFile, @NotNull ResourceRootConfiguration configuration) {
+ myConfiguration = configuration;
+ myRoot = rootFile;
+ }
+
+ @Override
+ public boolean accept(@NotNull File file) {
+ final String relPath = FileUtil.getRelativePath(myRoot, file);
+ return relPath != null && isIncluded(relPath);
+ }
+
+ public boolean isIncluded(String relativePath) {
+ if (myNormalizedIncludes == null) {
+ if (myConfiguration.includes.isEmpty()) {
+ myNormalizedIncludes = new String[]{"**" + File.separatorChar + '*'};
+ }
+ else {
+ myNormalizedIncludes = normalizePatterns(myConfiguration.includes);
+ }
+ }
+ if (myNormalizedExcludes == null) {
+ myNormalizedExcludes = normalizePatterns(myConfiguration.excludes);
+ }
+ return isIncluded(relativePath, myNormalizedIncludes, myNormalizedExcludes);
+ }
+
+ private static boolean isIncluded(String relativeName, String[] includes, String[] excludes) {
+ boolean isIncluded = false;
+ for (String each : includes) {
+ if (SelectorUtils.matchPath(each, relativeName)) {
+ isIncluded = true;
+ break;
+ }
+ }
+ if (!isIncluded) {
+ return false;
+ }
+ for (String each : excludes) {
+ if (SelectorUtils.matchPath(each, relativeName)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @NotNull
+ private static String[] normalizePatterns(@NotNull Collection<String> patterns) {
+ String[] res = new String[patterns.size()];
+
+ int i = 0;
+ for (String pattern : patterns) {
+ res[i++] = normalizePattern(pattern);
+ }
+
+ return res;
+ }
+
+ /*
+ * Copy-pasted from org.codehaus.plexus.util.AbstractScanner#normalizePattern()
+ */
+ private static String normalizePattern(String pattern) {
+ pattern = pattern.trim();
+
+ if (pattern.startsWith(SelectorUtils.REGEX_HANDLER_PREFIX)) {
+ if (File.separatorChar == '\\') {
+ pattern = StringUtils.replace(pattern, "/", "\\\\");
+ }
+ else {
+ pattern = StringUtils.replace(pattern, "\\\\", "/");
+ }
+ }
+ else {
+ pattern = pattern.replace(File.separatorChar == '/' ? '\\' : '/', File.separatorChar);
+
+ if (pattern.endsWith(File.separator)) {
+ pattern += "**";
+ }
+ }
+
+ return pattern;
+ }
+}
diff --git a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceRootDescriptor.java b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceRootDescriptor.java
index 746e3a7..1e61c31 100644
--- a/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceRootDescriptor.java
+++ b/plugins/maven/jps-plugin/src/org/jetbrains/jps/maven/model/impl/MavenResourceRootDescriptor.java
@@ -16,14 +16,11 @@
package org.jetbrains.jps.maven.model.impl;
import com.intellij.openapi.util.io.FileUtil;
-import org.codehaus.plexus.util.SelectorUtils;
-import org.codehaus.plexus.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import java.io.File;
import java.io.FileFilter;
-import java.util.Collection;
/**
* @author Eugene Zhuravlev
@@ -34,8 +31,6 @@
private final ResourceRootConfiguration myConfig;
private final File myFile;
private final String myId;
- private String[] myNormalizedIncludes;
- private String[] myNormalizedExcludes;
public MavenResourceRootDescriptor(@NotNull MavenResourcesTarget target, ResourceRootConfiguration config) {
myTarget = target;
@@ -67,84 +62,7 @@
@NotNull
@Override
public FileFilter createFileFilter() {
- return new FileFilter() {
- @Override
- public boolean accept(File file) {
- final String relPath = FileUtil.getRelativePath(getRootFile(), file);
- return relPath != null && isIncluded(relPath);
- }
- };
- }
-
- public boolean isIncluded(String relativePath) {
- if (myNormalizedIncludes == null) {
- if (myConfig.includes.isEmpty()) {
- myNormalizedIncludes = new String[]{"**" + File.separatorChar + '*'};
- }
- else {
- myNormalizedIncludes = normalizePatterns(myConfig.includes);
- }
- }
- if (myNormalizedExcludes == null) {
- myNormalizedExcludes = normalizePatterns(myConfig.excludes);
- }
- return isIncluded(relativePath, myNormalizedIncludes, myNormalizedExcludes);
- }
-
- private static boolean isIncluded(String relativeName, String[] includes, String[] excludes) {
- boolean isIncluded = false;
- for (String each : includes) {
- if (SelectorUtils.matchPath(each, relativeName)) {
- isIncluded = true;
- break;
- }
- }
- if (!isIncluded) {
- return false;
- }
- for (String each : excludes) {
- if (SelectorUtils.matchPath(each, relativeName)) {
- return false;
- }
- }
- return true;
- }
-
- @NotNull
- private static String[] normalizePatterns(@NotNull Collection<String> patterns) {
- String[] res = new String[patterns.size()];
-
- int i = 0;
- for (String pattern : patterns) {
- res[i++] = normalizePattern(pattern);
- }
-
- return res;
- }
-
- /*
- * Copy-pasted from org.codehaus.plexus.util.AbstractScanner#normalizePattern()
- */
- private static String normalizePattern(String pattern) {
- pattern = pattern.trim();
-
- if (pattern.startsWith(SelectorUtils.REGEX_HANDLER_PREFIX)) {
- if (File.separatorChar == '\\') {
- pattern = StringUtils.replace(pattern, "/", "\\\\");
- }
- else {
- pattern = StringUtils.replace(pattern, "\\\\", "/");
- }
- }
- else {
- pattern = pattern.replace(File.separatorChar == '/' ? '\\' : '/', File.separatorChar);
-
- if (pattern.endsWith(File.separator)) {
- pattern += "**";
- }
- }
-
- return pattern;
+ return new MavenResourceFileFilter(myFile, myConfig);
}
@Override
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 dba0c44..8fe4348 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
@@ -36,7 +36,7 @@
@NotNull Collection<String> activeProfiles) throws RemoteException,
MavenServerProcessCanceledException;
- @NotNull
+ @Nullable
String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles) throws RemoteException,
MavenServerProcessCanceledException;
diff --git a/plugins/maven/maven.iml b/plugins/maven/maven.iml
index c15aa89..f644609 100644
--- a/plugins/maven/maven.iml
+++ b/plugins/maven/maven.iml
@@ -62,6 +62,7 @@
<orderEntry type="module" module-name="maven-artifact-resolver-m31" />
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="vcs-api" />
+ <orderEntry type="module" module-name="properties-psi-api" />
</component>
<component name="copyright">
<Base>
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 89f97f5..630e664 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
@@ -198,7 +198,7 @@
return result;
}
- @NotNull
+ @Nullable
public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles) {
throw new UnsupportedOperationException();
}
diff --git a/plugins/maven/maven3-server-impl/lib-src/apache-maven-3.0.3-src.zip b/plugins/maven/maven3-server-impl/lib-src/apache-maven-3.0.3-src.zip
deleted file mode 100644
index ada9c11..0000000
--- a/plugins/maven/maven3-server-impl/lib-src/apache-maven-3.0.3-src.zip
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib-src/maven-dependency-tree-1.2-sources.jar b/plugins/maven/maven3-server-impl/lib-src/maven-dependency-tree-1.2-sources.jar
deleted file mode 100644
index c511da9..0000000
--- a/plugins/maven/maven3-server-impl/lib-src/maven-dependency-tree-1.2-sources.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib-src/nexus-indexer-3.0.4-sources.jar b/plugins/maven/maven3-server-impl/lib-src/nexus-indexer-3.0.4-sources.jar
deleted file mode 100644
index b66631c..0000000
--- a/plugins/maven/maven3-server-impl/lib-src/nexus-indexer-3.0.4-sources.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib-src/wagon-1.0-beta-7-source-release.zip b/plugins/maven/maven3-server-impl/lib-src/wagon-1.0-beta-7-source-release.zip
deleted file mode 100644
index f49dcfc..0000000
--- a/plugins/maven/maven3-server-impl/lib-src/wagon-1.0-beta-7-source-release.zip
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/bin/m2.conf b/plugins/maven/maven3-server-impl/lib/maven3/bin/m2.conf
index 339372a..b942125 100644
--- a/plugins/maven/maven3-server-impl/lib/maven3/bin/m2.conf
+++ b/plugins/maven/maven3-server-impl/lib/maven3/bin/m2.conf
@@ -3,5 +3,5 @@
set maven.home default ${user.home}/m2
[plexus.core]
-load ${maven.home}/lib/ext/*.jar
-load ${maven.home}/lib/*.jar
+optionally ${maven.home}/lib/ext/*.jar
+load ${maven.home}/lib/*.jar
\ No newline at end of file
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-api-1.11.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-api-1.11.jar
deleted file mode 100644
index 5bdade8..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-api-1.11.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-api-1.13.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-api-1.13.1.jar
new file mode 100644
index 0000000..15f2ce8
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-api-1.13.1.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-connector-wagon-1.11.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-connector-wagon-1.11.jar
deleted file mode 100644
index b5bf1b8..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-connector-wagon-1.11.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-connector-wagon-1.13.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-connector-wagon-1.13.1.jar
new file mode 100644
index 0000000..3182bf3
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-connector-wagon-1.13.1.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-impl-1.11.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-impl-1.11.jar
deleted file mode 100644
index 8ce9f13..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-impl-1.11.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-impl-1.13.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-impl-1.13.1.jar
new file mode 100644
index 0000000..a5a0e32
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-impl-1.13.1.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-spi-1.11.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-spi-1.11.jar
deleted file mode 100644
index 8fb6603..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-spi-1.11.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-spi-1.13.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-spi-1.13.1.jar
new file mode 100644
index 0000000..69e0f29
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-spi-1.13.1.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-util-1.11.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-util-1.11.jar
deleted file mode 100644
index 9f517ea..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-util-1.11.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-util-1.13.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-util-1.13.1.jar
new file mode 100644
index 0000000..76749db
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/aether-util-1.13.1.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-aether-provider-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-aether-provider-3.0.3.jar
deleted file mode 100644
index 33389cb..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-aether-provider-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-aether-provider-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-aether-provider-3.0.5.jar
new file mode 100644
index 0000000..b93247f
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-aether-provider-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.3.jar
deleted file mode 100644
index 4434712..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.5.jar
new file mode 100644
index 0000000..4e0600c
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-artifact-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-compat-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-compat-3.0.3.jar
deleted file mode 100644
index 47bb3dd..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-compat-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-compat-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-compat-3.0.5.jar
new file mode 100644
index 0000000..9afcdd1
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-compat-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-core-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-core-3.0.3.jar
deleted file mode 100644
index 2140f62..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-core-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-core-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-core-3.0.5.jar
new file mode 100644
index 0000000..0da4926
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-core-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-embedder-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-embedder-3.0.3.jar
deleted file mode 100644
index 857c286..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-embedder-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-embedder-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-embedder-3.0.5.jar
new file mode 100644
index 0000000..75050f6
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-embedder-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-3.0.3.jar
deleted file mode 100644
index 6fede20..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-3.0.5.jar
new file mode 100644
index 0000000..e7191ec
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-builder-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-builder-3.0.3.jar
deleted file mode 100644
index ca7a09c..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-builder-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-builder-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-builder-3.0.5.jar
new file mode 100644
index 0000000..1ff1421
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-model-builder-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-plugin-api-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-plugin-api-3.0.3.jar
deleted file mode 100644
index e0903e9..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-plugin-api-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-plugin-api-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-plugin-api-3.0.5.jar
new file mode 100644
index 0000000..1570c2d
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-plugin-api-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-repository-metadata-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-repository-metadata-3.0.3.jar
deleted file mode 100644
index 682f1be..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-repository-metadata-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-repository-metadata-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-repository-metadata-3.0.5.jar
new file mode 100644
index 0000000..0b72df6
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-repository-metadata-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-3.0.3.jar
deleted file mode 100644
index 01b26ab..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-3.0.5.jar
new file mode 100644
index 0000000..bd7149d
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-builder-3.0.3.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-builder-3.0.3.jar
deleted file mode 100644
index d5e9e46..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-builder-3.0.3.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-builder-3.0.5.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-builder-3.0.5.jar
new file mode 100644
index 0000000..838e254
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/maven-settings-builder-3.0.5.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/plexus-cipher-1.4.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/plexus-cipher-1.4.jar
deleted file mode 100644
index 9227205..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/plexus-cipher-1.4.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/plexus-cipher-1.7.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/plexus-cipher-1.7.jar
new file mode 100644
index 0000000..21928b9
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/plexus-cipher-1.7.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guava-0.9.9.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guava-0.9.9.jar
new file mode 100644
index 0000000..460abed
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guava-0.9.9.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guice-2.9.4-no_aop.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guice-2.9.4-no_aop.jar
deleted file mode 100644
index 4ccd861..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guice-2.9.4-no_aop.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guice-3.1.0-no_aop.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guice-3.1.0-no_aop.jar
new file mode 100644
index 0000000..4c84b3e
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-guice-3.1.0-no_aop.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-bean-2.1.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-bean-2.1.1.jar
deleted file mode 100644
index f595db9..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-bean-2.1.1.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-bean-2.3.0.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-bean-2.3.0.jar
new file mode 100644
index 0000000..ebf244b
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-bean-2.3.0.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-plexus-2.1.1.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-plexus-2.1.1.jar
deleted file mode 100644
index 94a1183..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-plexus-2.1.1.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-plexus-2.3.0.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-plexus-2.3.0.jar
new file mode 100644
index 0000000..0395047
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/sisu-inject-plexus-2.3.0.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-file-1.0-beta-7.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-file-1.0-beta-7.jar
deleted file mode 100644
index 2e59d4b..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-file-1.0-beta-7.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-file-2.4.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-file-2.4.jar
new file mode 100644
index 0000000..1dfe063
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-file-2.4.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-2.4-shaded.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-2.4-shaded.jar
new file mode 100644
index 0000000..1173a48
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-2.4-shaded.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-lightweight-1.0-beta-7.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-lightweight-1.0-beta-7.jar
deleted file mode 100644
index 2aca330..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-lightweight-1.0-beta-7.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-shared-1.0-beta-7.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-shared-1.0-beta-7.jar
deleted file mode 100644
index 4321708..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-http-shared-1.0-beta-7.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-provider-api-1.0-beta-7.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-provider-api-1.0-beta-7.jar
deleted file mode 100644
index 052b265..0000000
--- a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-provider-api-1.0-beta-7.jar
+++ /dev/null
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-provider-api-2.4.jar b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-provider-api-2.4.jar
new file mode 100644
index 0000000..dc1aeb0
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/lib/maven3/lib/wagon-provider-api-2.4.jar
Binary files differ
diff --git a/plugins/maven/maven3-server-impl/maven3-server-impl.iml b/plugins/maven/maven3-server-impl/maven3-server-impl.iml
index 0c898b2..7a9fd94 100644
--- a/plugins/maven/maven3-server-impl/maven3-server-impl.iml
+++ b/plugins/maven/maven3-server-impl/maven3-server-impl.iml
@@ -18,84 +18,7 @@
<root url="file://$MODULE_DIR$/lib/maven3/lib" />
</CLASSES>
<JAVADOC />
- <SOURCES>
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-core/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/aggregate-mojo-failure/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-artifact/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-model-builder/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/mojo-config-error/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/missing-req-mojo-param/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-dep-ver/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-artifact/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/project-mojo-failure/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/ext-realm-error/ext/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-compat/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/project-dep-missing/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/err-resolving-project-dep/project/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-core/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/projects/isolated-project-getting-parent-pom/project/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-model/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/missing-module-pom/child1/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/projects/isolated-project-getting-parent-pom/project/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-settings/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/project-dep-missing/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/missing-module-pom/child1/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-plugin-api/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-core/src/test/projects/lifecycle-executor/project-with-additional-lifecycle-elements/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/bad-build-plan/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/err-resolving-project-dep/project/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/duplicated-attachments/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-core/src/test/projects/lifecycle-executor/project-with-additional-lifecycle-elements/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-aether-provider/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/missing-direct-invoke-mojo/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/embedder-test-project/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-aether-provider/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/profile-activator-lookup-err/ext/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-model-builder/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-settings-builder/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/mojo-lookup-err/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/ext-plugin-version-err/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-model/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/ext-plugin-realm-error/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-plugin-api/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/project-mojo-failure/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/embedder-test-project/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-settings-builder/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-compat/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/examples/simple-project/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/mojo-exec-err/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/bad-ext-plugin-maven-ver/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/test/error-reporting-projects/config-rdonly-mojo-param/plugin/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/apache-maven/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/apache-maven-3.0.3-src.zip!/apache-maven-3.0.3/maven-embedder/src/examples/simple-project/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-http/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-scm/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-tcks/wagon-tck-http/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-webdav-jackrabbit/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ftp/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh-common/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-scm/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-http/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh-common/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-provider-api/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-webdav-jackrabbit/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ftp/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-tcks/wagon-tck-http/sample-tck-consumer/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-http-shared/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-http-lightweight/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-provider-test/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-file/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh-external/src/test/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh-common-test/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-http-shared/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-file/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-ssh-external/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-provider-api/src/main/java" />
- <root url="jar://$MODULE_DIR$/lib-src/wagon-1.0-beta-7-source-release.zip!/wagon-1.0-beta-7/wagon-providers/wagon-http-lightweight/src/test/java" />
- </SOURCES>
+ <SOURCES />
<jarDirectory url="file://$MODULE_DIR$/lib/maven3/lib" recursive="false" />
</library>
</orderEntry>
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 77f9950..ae45421 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
@@ -19,9 +19,7 @@
import com.intellij.util.SystemProperties;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
-import org.apache.maven.DefaultMaven;
-import org.apache.maven.Maven;
-import org.apache.maven.RepositoryUtils;
+import org.apache.maven.*;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.InvalidRepositoryException;
import org.apache.maven.artifact.factory.ArtifactFactory;
@@ -36,6 +34,7 @@
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.Profile;
+import org.apache.maven.model.interpolation.ModelInterpolator;
import org.apache.maven.model.profile.DefaultProfileInjector;
import org.apache.maven.plugin.LegacySupport;
import org.apache.maven.plugin.internal.PluginDependenciesResolver;
@@ -82,6 +81,21 @@
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
+/**
+ * Overridden maven components:
+
+ maven-compat:
+ org.jetbrains.idea.maven.server.embedder.CustomMaven3RepositoryMetadataManager <-> org.apache.maven.artifact.repository.metadata.DefaultRepositoryMetadataManager
+ org.jetbrains.idea.maven.server.embedder.CustomMaven3ArtifactResolver <-> org.apache.maven.artifact.resolver.DefaultArtifactResolver
+ org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator <-> org.apache.maven.project.interpolation.StringSearchModelInterpolator
+
+ maven-core:
+ org.jetbrains.idea.maven.server.embedder.CustomMaven3ArtifactFactory <-> org.apache.maven.artifact.factory.DefaultArtifactFactory
+ org.jetbrains.idea.maven.server.embedder.CustomPluginDescriptorCache <-> org.apache.maven.plugin.DefaultPluginDescriptorCache
+
+ maven-model-builder:
+ org.jetbrains.idea.maven.server.embedder.CustomMaven3ModelInterpolator2 <-> org.apache.maven.model.interpolation.StringSearchModelInterpolator
+*/
public class Maven3ServerEmbedderImpl extends MavenRemoteObject implements MavenServerEmbedder {
@NotNull private final DefaultPlexusContainer myContainer;
@NotNull private final Settings myMavenSettings;
@@ -168,10 +182,9 @@
mySystemProperties.setProperty("java.home", settings.getProjectJdk());
}
- myMavenSettings = buildSettings(FieldAccessor.<SettingsBuilder>get(MavenCli.class, cli, "settingsBuilder"),
- settings,
- mySystemProperties,
- FieldAccessor.<Properties>get(cliRequestClass, cliRequest, "userProperties"));
+ myMavenSettings =
+ buildSettings(FieldAccessor.<SettingsBuilder>get(MavenCli.class, cli, "settingsBuilder"), settings, mySystemProperties,
+ FieldAccessor.<Properties>get(cliRequestClass, cliRequest, "userProperties"));
myLocalRepository = createLocalRepository();
}
@@ -179,8 +192,7 @@
private static Settings buildSettings(SettingsBuilder builder,
MavenServerSettings settings,
Properties systemProperties,
- Properties userProperties)
- throws RemoteException {
+ Properties userProperties) throws RemoteException {
SettingsBuildingRequest settingsRequest = new DefaultSettingsBuildingRequest();
settingsRequest.setGlobalSettingsFile(settings.getGlobalSettingsFile());
settingsRequest.setUserSettingsFile(settings.getUserSettingsFile());
@@ -210,20 +222,22 @@
@SuppressWarnings({"unchecked"})
public <T> T getComponent(Class<T> clazz, String roleHint) {
- try {
- return (T) myContainer.lookup(clazz.getName(), roleHint);
- } catch (ComponentLookupException e) {
- throw new RuntimeException(e);
- }
+ try {
+ return (T)myContainer.lookup(clazz.getName(), roleHint);
+ }
+ catch (ComponentLookupException e) {
+ throw new RuntimeException(e);
+ }
}
@SuppressWarnings({"unchecked"})
public <T> T getComponent(Class<T> clazz) {
- try {
- return (T) myContainer.lookup(clazz.getName());
- } catch (ComponentLookupException e) {
- throw new RuntimeException(e);
- }
+ try {
+ return (T)myContainer.lookup(clazz.getName());
+ }
+ catch (ComponentLookupException e) {
+ throw new RuntimeException(e);
+ }
}
private ArtifactRepository createLocalRepository() {
@@ -285,13 +299,12 @@
throws RemoteException, MavenServerProcessCanceledException {
DependencyTreeResolutionListener listener = new DependencyTreeResolutionListener(myConsoleWrapper);
- MavenExecutionResult result = doResolveProject(file,
- new ArrayList<String>(activeProfiles),
- Arrays.<ResolutionListener>asList(listener));
+ MavenExecutionResult result =
+ doResolveProject(file, new ArrayList<String>(activeProfiles), Arrays.<ResolutionListener>asList(listener));
return createExecutionResult(file, result, listener.getRootNode());
}
- @NotNull
+ @Nullable
@Override
public String evaluateEffectivePom(@NotNull File file, @NotNull List<String> activeProfiles)
throws RemoteException, MavenServerProcessCanceledException {
@@ -310,6 +323,17 @@
MavenSession oldSession = legacySupport.getSession();
legacySupport.setSession(mavenSession);
+
+ /** adapted from {@link org.apache.maven.DefaultMaven#doExecute(org.apache.maven.execution.MavenExecutionRequest)} */
+ try {
+ for (AbstractMavenLifecycleParticipant listener : getLifecycleParticipants(Collections.<MavenProject>emptyList())) {
+ listener.afterSessionStart(mavenSession);
+ }
+ }
+ catch (MavenExecutionException e) {
+ throw new RuntimeException(e);
+ }
+
try {
runnable.run();
}
@@ -322,7 +346,8 @@
public MavenExecutionResult doResolveProject(@NotNull final File file,
@NotNull final List<String> activeProfiles,
final List<ResolutionListener> listeners) throws RemoteException {
- final MavenExecutionRequest request = createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
+ final MavenExecutionRequest request =
+ createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
final AtomicReference<MavenExecutionResult> ref = new AtomicReference<MavenExecutionResult>();
@@ -333,24 +358,41 @@
// copied from DefaultMavenProjectBuilder.buildWithDependencies
ProjectBuilder builder = getComponent(ProjectBuilder.class);
- // Don't use build(File projectFile, ProjectBuildingRequest request) , because it don't use cache !!!!!!!! (see http://devnet.jetbrains.com/message/5500218)
- List<ProjectBuildingResult> results =
- builder.build(Collections.singletonList(new File(file.getPath())), false, request.getProjectBuildingRequest());
+ CustomMaven3ModelInterpolator2 modelInterpolator = (CustomMaven3ModelInterpolator2)getComponent(ModelInterpolator.class);
+
+ String savedLocalRepository = modelInterpolator.getLocalRepository();
+ modelInterpolator.setLocalRepository(request.getLocalRepositoryPath().getAbsolutePath());
+ List<ProjectBuildingResult> results;
+
+ try {
+ // Don't use build(File projectFile, ProjectBuildingRequest request) , because it don't use cache !!!!!!!! (see http://devnet.jetbrains.com/message/5500218)
+ results = builder.build(Collections.singletonList(new File(file.getPath())), false, request.getProjectBuildingRequest());
+ }
+ finally {
+ modelInterpolator.setLocalRepository(savedLocalRepository);
+ }
ProjectBuildingResult buildingResult = results.get(0);
MavenProject project = buildingResult.getProject();
- // copied from DefaultLifecycleExecutor.execute
- //findExtensions(project);
- // end copied from DefaultLifecycleExecutor.execute
+ RepositorySystemSession repositorySession = getComponent(LegacySupport.class).getRepositorySession();
+ if (repositorySession instanceof DefaultRepositorySystemSession) {
+ ((DefaultRepositorySystemSession)repositorySession).setTransferListener(new TransferListenerAdapter(myCurrentIndicator));
+
+ if (myWorkspaceMap != null) {
+ ((DefaultRepositorySystemSession)repositorySession).setWorkspaceReader(new Maven3WorkspaceReader(myWorkspaceMap));
+ }
+ }
+
+ List<Exception> exceptions = new ArrayList<Exception>();
+ loadExtensions(project, exceptions);
//Artifact projectArtifact = project.getArtifact();
//Map managedVersions = project.getManagedVersionMap();
//ArtifactMetadataSource metadataSource = getComponent(ArtifactMetadataSource.class);
project.setDependencyArtifacts(project.createArtifacts(getComponent(ArtifactFactory.class), null, null));
//
- ArtifactResolver resolver = getComponent(ArtifactResolver.class);
ArtifactResolutionRequest resolutionRequest = new ArtifactResolutionRequest();
resolutionRequest.setArtifactDependencies(project.getDependencyArtifacts());
@@ -363,20 +405,12 @@
resolutionRequest.setResolveRoot(false);
resolutionRequest.setResolveTransitively(true);
- RepositorySystemSession repositorySession = getComponent(LegacySupport.class).getRepositorySession();
- if (repositorySession instanceof DefaultRepositorySystemSession) {
- ((DefaultRepositorySystemSession)repositorySession).setTransferListener(new TransferListenerAdapter(myCurrentIndicator));
-
- if (myWorkspaceMap != null) {
- ((DefaultRepositorySystemSession)repositorySession).setWorkspaceReader(new Maven3WorkspaceReader(myWorkspaceMap));
- }
- }
-
+ ArtifactResolver resolver = getComponent(ArtifactResolver.class);
ArtifactResolutionResult result = resolver.resolve(resolutionRequest);
project.setArtifacts(result.getArtifacts());
// end copied from DefaultMavenProjectBuilder.buildWithDependencies
- ref.set(new MavenExecutionResult(project, new ArrayList<Exception>()));
+ ref.set(new MavenExecutionResult(project, exceptions));
}
catch (Exception e) {
ref.set(handleException(e));
@@ -387,6 +421,83 @@
return ref.get();
}
+ /**
+ * adapted from {@link org.apache.maven.DefaultMaven#doExecute(org.apache.maven.execution.MavenExecutionRequest)}
+ */
+ private void loadExtensions(MavenProject project, List<Exception> exceptions) {
+ ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+ Collection<AbstractMavenLifecycleParticipant> lifecycleParticipants = getLifecycleParticipants(Arrays.asList(project));
+ if (!lifecycleParticipants.isEmpty()) {
+ LegacySupport legacySupport = getComponent(LegacySupport.class);
+ MavenSession session = legacySupport.getSession();
+ session.setCurrentProject(project);
+ session.setProjects(Arrays.asList(project));
+
+ for (AbstractMavenLifecycleParticipant listener : lifecycleParticipants) {
+ Thread.currentThread().setContextClassLoader(listener.getClass().getClassLoader());
+ try {
+ listener.afterProjectsRead(session);
+ }
+ catch (MavenExecutionException e) {
+ exceptions.add(e);
+ }
+ finally {
+ Thread.currentThread().setContextClassLoader(originalClassLoader);
+ }
+ }
+ }
+ }
+
+ /**
+ * adapted from {@link org.apache.maven.DefaultMaven#getLifecycleParticipants(java.util.Collection)}
+ */
+ private Collection<AbstractMavenLifecycleParticipant> getLifecycleParticipants(Collection<MavenProject> projects) {
+ Collection<AbstractMavenLifecycleParticipant> lifecycleListeners = new LinkedHashSet<AbstractMavenLifecycleParticipant>();
+
+ ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
+ try {
+ try {
+ lifecycleListeners.addAll(myContainer.lookupList(AbstractMavenLifecycleParticipant.class));
+ }
+ catch (ComponentLookupException e) {
+ // this is just silly, lookupList should return an empty list!
+ warn("Failed to lookup lifecycle participants", e);
+ }
+
+ Collection<ClassLoader> scannedRealms = new HashSet<ClassLoader>();
+
+ for (MavenProject project : projects) {
+ ClassLoader projectRealm = project.getClassRealm();
+
+ if (projectRealm != null && scannedRealms.add(projectRealm)) {
+ Thread.currentThread().setContextClassLoader(projectRealm);
+
+ try {
+ lifecycleListeners.addAll(myContainer.lookupList(AbstractMavenLifecycleParticipant.class));
+ }
+ catch (ComponentLookupException e) {
+ // this is just silly, lookupList should return an empty list!
+ warn("Failed to lookup lifecycle participants", e);
+ }
+ }
+ }
+ }
+ finally {
+ Thread.currentThread().setContextClassLoader(originalClassLoader);
+ }
+
+ return lifecycleListeners;
+ }
+
+ private static void warn(String message, Throwable e) {
+ try {
+ Maven3ServerGlobals.getLogger().warn(new RuntimeException(message, e));
+ }
+ catch (RemoteException e1) {
+ throw new RuntimeException(e1);
+ }
+ }
+
public MavenExecutionRequest createRequest(File file, List<String> activeProfiles, List<String> inactiveProfiles, List<String> goals)
throws RemoteException {
//Properties executionProperties = myMavenSettings.getProperties();
@@ -420,14 +531,14 @@
}
private static MavenExecutionResult handleException(Throwable e) {
- if (e instanceof Error) throw (Error) e;
+ if (e instanceof Error) throw (Error)e;
- return new MavenExecutionResult(null, Collections.singletonList((Exception) e));
+ return new MavenExecutionResult(null, Collections.singletonList((Exception)e));
}
@NotNull
public File getLocalRepositoryFile() {
- return new File(myLocalRepository.getBasedir());
+ return new File(myLocalRepository.getBasedir());
}
@NotNull
@@ -441,13 +552,10 @@
MavenProject mavenProject = result.getMavenProject();
if (mavenProject == null) return new MavenServerExecutionResult(null, problems, unresolvedArtifacts);
- MavenModel model = MavenModelConverter.convertModel(mavenProject.getModel(),
- mavenProject.getCompileSourceRoots(),
- mavenProject.getTestCompileSourceRoots(),
- mavenProject.getArtifacts(),
- (rootNode == null ? Collections.emptyList() : rootNode.getChildren()),
- mavenProject.getExtensionArtifacts(),
- getLocalRepositoryFile());
+ MavenModel model = MavenModelConverter
+ .convertModel(mavenProject.getModel(), mavenProject.getCompileSourceRoots(), mavenProject.getTestCompileSourceRoots(),
+ mavenProject.getArtifacts(), (rootNode == null ? Collections.emptyList() : rootNode.getChildren()),
+ mavenProject.getExtensionArtifacts(), getLocalRepositoryFile());
RemoteNativeMavenProjectHolder holder = new RemoteNativeMavenProjectHolder(mavenProject);
try {
@@ -459,8 +567,9 @@
Collection<String> activatedProfiles = collectActivatedProfiles(mavenProject);
- MavenServerExecutionResult.ProjectData data = new MavenServerExecutionResult.ProjectData(
- model, MavenModelConverter.convertToMap(mavenProject.getModel()), holder, activatedProfiles);
+ MavenServerExecutionResult.ProjectData data =
+ new MavenServerExecutionResult.ProjectData(model, MavenModelConverter.convertToMap(mavenProject.getModel()), holder,
+ activatedProfiles);
return new MavenServerExecutionResult(data, problems, unresolvedArtifacts);
}
@@ -537,8 +646,7 @@
Set<Artifact> res = getComponent(ArtifactResolver.class)
.resolveTransitively(toResolve, project, Collections.EMPTY_MAP, myLocalRepository, convertRepositories(remoteRepositories),
- getComponent(ArtifactMetadataSource.class))
- .getArtifacts();
+ getComponent(ArtifactMetadataSource.class)).getArtifacts();
return MavenModelConverter.convertArtifacts(res, new THashMap<Artifact, MavenArtifact>(), getLocalRepositoryFile());
}
@@ -572,7 +680,8 @@
mavenPlugin.setDependencies(pluginFromProject.getDependencies());
}
- final MavenExecutionRequest request = createRequest(null, Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList());
+ final MavenExecutionRequest request =
+ createRequest(null, Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList());
DefaultMaven maven = (DefaultMaven)getComponent(Maven.class);
RepositorySystemSession repositorySystemSession = maven.newRepositorySession(request);
@@ -591,8 +700,8 @@
List<MavenArtifact> res = new ArrayList<MavenArtifact>();
for (org.sonatype.aether.artifact.Artifact artifact : nlg.getArtifacts(true)) {
- if (!Comparing.equal(artifact.getArtifactId(), plugin.getArtifactId())
- || !Comparing.equal(artifact.getGroupId(), plugin.getGroupId())) {
+ if (!Comparing.equal(artifact.getArtifactId(), plugin.getArtifactId()) ||
+ !Comparing.equal(artifact.getGroupId(), plugin.getGroupId())) {
res.add(MavenModelConverter.convertArtifact(RepositoryUtils.toArtifact(artifact), getLocalRepositoryFile()));
}
}
@@ -622,7 +731,7 @@
}
public void resolve(@NotNull final Artifact artifact, @NotNull final List<ArtifactRepository> repos)
- throws ArtifactResolutionException, ArtifactNotFoundException {
+ throws ArtifactResolutionException, ArtifactNotFoundException {
MavenExecutionRequest request = new DefaultMavenExecutionRequest();
request.setRemoteRepositories(repos);
@@ -652,11 +761,8 @@
}
private Artifact createArtifact(MavenArtifactInfo info) {
- return getComponent(ArtifactFactory.class).createArtifactWithClassifier(info.getGroupId(),
- info.getArtifactId(),
- info.getVersion(),
- info.getPackaging(),
- info.getClassifier());
+ return getComponent(ArtifactFactory.class)
+ .createArtifactWithClassifier(info.getGroupId(), info.getArtifactId(), info.getVersion(), info.getPackaging(), info.getClassifier());
}
@NotNull
@@ -668,8 +774,9 @@
@NotNull List<String> selectedProjects,
boolean alsoMake,
boolean alsoMakeDependents) throws RemoteException, MavenServerProcessCanceledException {
- MavenExecutionResult result = doExecute(file, new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles), goals,
- selectedProjects, alsoMake, alsoMakeDependents);
+ MavenExecutionResult result =
+ doExecute(file, new ArrayList<String>(activeProfiles), new ArrayList<String>(inactiveProfiles), goals, selectedProjects, alsoMake,
+ alsoMakeDependents);
return createExecutionResult(file, result, null);
}
@@ -697,12 +804,18 @@
}
}
- Maven maven = getComponent(Maven.class);
- org.apache.maven.execution.MavenExecutionResult executionResult = maven.execute(request);
+ org.apache.maven.execution.MavenExecutionResult executionResult = safeExecute(request, getComponent(Maven.class));
return new MavenExecutionResult(executionResult.getProject(), filterExceptions(executionResult.getExceptions()));
}
+ private org.apache.maven.execution.MavenExecutionResult safeExecute(MavenExecutionRequest request, Maven maven) throws RemoteException {
+ MavenLeakDetector detector = new MavenLeakDetector().mark();
+ org.apache.maven.execution.MavenExecutionResult result = maven.execute(request);
+ detector.check();
+ return result;
+ }
+
private static List<Exception> filterExceptions(List<Throwable> list) {
for (Throwable throwable : list) {
if (!(throwable instanceof Exception)) {
@@ -816,8 +929,7 @@
new DefaultProfileInjector().injectProfile(nativeModel, each, null, null);
}
- return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null),
- collectProfilesIds(activatedProfiles));
+ return new ProfileApplicationResult(MavenModelConverter.convertModel(nativeModel, null), collectProfilesIds(activatedProfiles));
}
private static Model doInterpolate(Model result, File basedir) throws RemoteException {
@@ -862,9 +974,7 @@
return new ProfileActivator[0];
}
- return new ProfileActivator[]{new MyFileProfileActivator(basedir),
- sysPropertyActivator,
- new JdkPrefixProfileActivator(),
+ return new ProfileActivator[]{new MyFileProfileActivator(basedir), sysPropertyActivator, new JdkPrefixProfileActivator(),
new OperatingSystemProfileActivator()};
}
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
index 180fc05..2d0c90d 100644
--- a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenEffectivePomDumper.java
@@ -17,6 +17,7 @@
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
@@ -43,38 +44,43 @@
private static final String SETTINGS_XSD_URL = "http://maven.apache.org/xsd/settings-1.0.0.xsd";
// See org.apache.maven.plugins.help.EffectivePomMojo#execute from maven-help-plugin
-
+ @Nullable
public static String evaluateEffectivePom(final Maven3ServerEmbedderImpl embedder,
@NotNull final File file,
@NotNull List<String> activeProfiles)
throws RemoteException, MavenServerProcessCanceledException {
- final MavenExecutionRequest
- request = embedder.createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
-
final StringWriter w = new StringWriter();
- embedder.executeWithMavenSession(request, new Runnable() {
- @Override
- public void run() {
- try {
- // copied from DefaultMavenProjectBuilder.buildWithDependencies
- ProjectBuilder builder = embedder.getComponent(ProjectBuilder.class);
- ProjectBuildingResult buildingResult = builder.build(new File(file.getPath()), request.getProjectBuildingRequest());
+ try {
+ final MavenExecutionRequest
+ request = embedder.createRequest(file, activeProfiles, Collections.<String>emptyList(), Collections.<String>emptyList());
- MavenProject project = buildingResult.getProject();
+ embedder.executeWithMavenSession(request, new Runnable() {
+ @Override
+ public void run() {
+ try {
+ // copied from DefaultMavenProjectBuilder.buildWithDependencies
+ ProjectBuilder builder = embedder.getComponent(ProjectBuilder.class);
+ ProjectBuildingResult buildingResult = builder.build(new File(file.getPath()), request.getProjectBuildingRequest());
- XMLWriter writer = new PrettyPrintXMLWriter(w, StringUtils.repeat(" ", XmlWriterUtil.DEFAULT_INDENTATION_SIZE));
+ MavenProject project = buildingResult.getProject();
- writeHeader(writer);
+ XMLWriter writer = new PrettyPrintXMLWriter(w, StringUtils.repeat(" ", XmlWriterUtil.DEFAULT_INDENTATION_SIZE));
- writeEffectivePom(project, writer);
+ writeHeader(writer);
+
+ writeEffectivePom(project, writer);
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
}
- catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- });
+ });
+ }
+ catch (Exception e) {
+ return null;
+ }
return w.toString();
}
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
new file mode 100644
index 0000000..15899e7
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/MavenLeakDetector.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.maven.server;
+
+import com.intellij.util.ReflectionUtil;
+
+import java.rmi.RemoteException;
+import java.util.IdentityHashMap;
+import java.util.Map;
+
+public class MavenLeakDetector {
+
+ private IdentityHashMap<Thread, Thread> markedHooks = new IdentityHashMap<Thread, Thread>();
+
+ public MavenLeakDetector mark() {
+ markShutdownHooks();
+ return this;
+ }
+
+ private void markShutdownHooks() {
+ markedHooks.putAll(getShutdownHooks());
+ }
+
+ public void check() throws RemoteException {
+ checkShutdownHooks();
+ }
+
+ private void checkShutdownHooks() throws RemoteException {
+ IdentityHashMap<Thread, Thread> checkedHooks = new IdentityHashMap<Thread, Thread>(getShutdownHooks());
+ for (Thread t : markedHooks.values()) {
+ checkedHooks.remove(t);
+ }
+ for (Thread t : checkedHooks.values()) {
+ removeHook(t);
+ }
+ }
+
+ private void removeHook(Thread thread) throws RemoteException {
+ Runtime.getRuntime().removeShutdownHook(thread);
+ Maven3ServerGlobals.getLogger().print(String.format("ShutdownHook[%s] was removed to avoid memory leak", thread));
+ }
+
+ private Map<Thread, Thread> getShutdownHooks() {
+ Class clazz = null;
+ try {
+ clazz = Class.forName("java.lang.ApplicationShutdownHooks");
+ }
+ catch (ClassNotFoundException e) {
+ // we can ignore this one
+ }
+ return ReflectionUtil.getField(clazz, null, Map.class, "hooks");
+ }
+
+}
diff --git a/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/CustomMaven3ModelInterpolator2.java b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/CustomMaven3ModelInterpolator2.java
new file mode 100644
index 0000000..534ed3d
--- /dev/null
+++ b/plugins/maven/maven3-server-impl/src/org/jetbrains/idea/maven/server/embedder/CustomMaven3ModelInterpolator2.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 org.jetbrains.idea.maven.server.embedder;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.building.ModelBuildingRequest;
+import org.apache.maven.model.building.ModelProblemCollector;
+import org.apache.maven.model.interpolation.ModelInterpolator;
+import org.apache.maven.model.interpolation.StringSearchModelInterpolator;
+import org.codehaus.plexus.component.annotations.Component;
+import org.codehaus.plexus.interpolation.SingleResponseValueSource;
+import org.codehaus.plexus.interpolation.ValueSource;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ * @author Sergey Evdokimov
+ */
+@Component( role = ModelInterpolator.class )
+public class CustomMaven3ModelInterpolator2 extends StringSearchModelInterpolator {
+
+ private String localRepository;
+
+ @Override
+ protected List<ValueSource> createValueSources(Model model,
+ File projectDir,
+ ModelBuildingRequest config,
+ ModelProblemCollector problems) {
+ List<ValueSource> res = super.createValueSources(model, projectDir, config, problems);
+
+ if (localRepository != null) {
+ res.add(new SingleResponseValueSource("settings.localRepository", localRepository));
+ }
+
+ return res;
+ }
+
+ public String getLocalRepository() {
+ return localRepository;
+ }
+
+ public void setLocalRepository(String localRepository) {
+ this.localRepository = localRepository;
+ }
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomBundle.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomBundle.java
index 52849f6..b5c68f4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomBundle.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenDomBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,21 +25,20 @@
import java.util.ResourceBundle;
public class MavenDomBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "MavenDomBundle";
private MavenDomBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java
index 2d7e40b..fc54abc 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPluginDomUtil.java
@@ -33,15 +33,24 @@
public class MavenPluginDomUtil {
@Nullable
public static MavenDomPluginModel getMavenPluginModel(DomElement element) {
- Project p = element.getXmlElement().getProject();
+ Project project = element.getManager().getProject();
MavenDomPlugin pluginElement = element.getParentOfType(MavenDomPlugin.class, false);
if (pluginElement == null) return null;
- VirtualFile pluginXmlFile = getPluginXmlFile(p, pluginElement);
+ String groupId = pluginElement.getGroupId().getStringValue();
+ String artifactId = pluginElement.getArtifactId().getStringValue();
+ String version = pluginElement.getVersion().getStringValue();
+
+ return getMavenPluginModel(project, groupId, artifactId, version);
+ }
+
+ @Nullable
+ public static MavenDomPluginModel getMavenPluginModel(Project project, String groupId, String artifactId, String version) {
+ VirtualFile pluginXmlFile = getPluginXmlFile(project, groupId, artifactId, version);
if (pluginXmlFile == null) return null;
- return MavenDomUtil.getMavenDomModel(p, pluginXmlFile, MavenDomPluginModel.class);
+ return MavenDomUtil.getMavenDomModel(project, pluginXmlFile, MavenDomPluginModel.class);
}
public static boolean isPlugin(@NotNull MavenDomConfiguration configuration, @Nullable String groupId, @NotNull String artifactId) {
@@ -68,12 +77,8 @@
}
@Nullable
- private static VirtualFile getPluginXmlFile(Project p, MavenDomPlugin pluginElement) {
- String groupId = pluginElement.getGroupId().getStringValue();
- String artifactId = pluginElement.getArtifactId().getStringValue();
- String version = pluginElement.getVersion().getStringValue();
-
- File file = MavenArtifactUtil.getArtifactFile(MavenProjectsManager.getInstance(p).getLocalRepository(),
+ private static VirtualFile getPluginXmlFile(Project project, String groupId, String artifactId, String version) {
+ File file = MavenArtifactUtil.getArtifactFile(MavenProjectsManager.getInstance(project).getLocalRepository(),
groupId, artifactId, version, "jar");
VirtualFile pluginFile = LocalFileSystem.getInstance().findFileByIoFile(file);
if (pluginFile == null) return null;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java
index cd37e99..63d3106 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicateDependenciesInspection.java
@@ -23,11 +23,10 @@
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Processor;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.MultiMapBasedOnSet;
import com.intellij.util.containers.hash.HashSet;
import com.intellij.util.xml.DomFileElement;
-import com.intellij.util.xml.highlighting.BasicDomElementsInspection;
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
+import com.intellij.util.xml.highlighting.DomElementsInspection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.DependencyConflictId;
import org.jetbrains.idea.maven.dom.MavenDomBundle;
@@ -40,7 +39,7 @@
import java.util.*;
-public class MavenDuplicateDependenciesInspection extends BasicDomElementsInspection<MavenDomProjectModel> {
+public class MavenDuplicateDependenciesInspection extends DomElementsInspection<MavenDomProjectModel> {
public MavenDuplicateDependenciesInspection() {
super(MavenDomProjectModel.class);
}
@@ -142,7 +141,7 @@
@NotNull
private static MultiMap<DependencyConflictId, MavenDomDependency> getDuplicateDependenciesMap(MavenDomProjectModel projectModel) {
- final MultiMap<DependencyConflictId, MavenDomDependency> allDependencies = new MultiMapBasedOnSet<DependencyConflictId, MavenDomDependency>();
+ final MultiMap<DependencyConflictId, MavenDomDependency> allDependencies = MultiMap.createSet();
Processor<MavenDomProjectModel> collectProcessor = new Processor<MavenDomProjectModel>() {
public boolean process(MavenDomProjectModel model) {
@@ -168,7 +167,7 @@
private static void checkManagedDependencies(@NotNull MavenDomProjectModel projectModel,
@NotNull DomElementAnnotationHolder holder) {
- MultiMap<DependencyConflictId, MavenDomDependency> duplicates = new MultiMapBasedOnSet<DependencyConflictId, MavenDomDependency>();
+ MultiMap<DependencyConflictId, MavenDomDependency> duplicates = MultiMap.createSet();
collect(duplicates, projectModel.getDependencyManagement().getDependencies());
for (Map.Entry<DependencyConflictId, Collection<MavenDomDependency>> entry : duplicates.entrySet()) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicatePluginInspection.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicatePluginInspection.java
index 7e7f510..68a42e6 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicatePluginInspection.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenDuplicatePluginInspection.java
@@ -20,10 +20,9 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.containers.MultiMap;
-import com.intellij.util.containers.MultiMapBasedOnSet;
import com.intellij.util.xml.DomFileElement;
-import com.intellij.util.xml.highlighting.BasicDomElementsInspection;
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
+import com.intellij.util.xml.highlighting.DomElementsInspection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.MavenDomBundle;
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin;
@@ -32,7 +31,7 @@
import java.util.Collection;
import java.util.Map;
-public class MavenDuplicatePluginInspection extends BasicDomElementsInspection<MavenDomProjectModel> {
+public class MavenDuplicatePluginInspection extends DomElementsInspection<MavenDomProjectModel> {
public MavenDuplicatePluginInspection() {
super(MavenDomProjectModel.class);
}
@@ -42,7 +41,7 @@
DomElementAnnotationHolder holder) {
MavenDomProjectModel projectModel = domFileElement.getRootElement();
- MultiMap<Pair<String,String>, MavenDomPlugin> duplicates = new MultiMapBasedOnSet<Pair<String, String>, MavenDomPlugin>();
+ MultiMap<Pair<String,String>, MavenDomPlugin> duplicates = MultiMap.createSet();
for (MavenDomPlugin plugin : projectModel.getBuild().getPlugins().getPlugins()) {
String groupId = plugin.getGroupId().getStringValue();
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/refactorings/introduce/IntroducePropertyAction.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/refactorings/introduce/IntroducePropertyAction.java
index 16d9de0..e595e1f 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/refactorings/introduce/IntroducePropertyAction.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/refactorings/introduce/IntroducePropertyAction.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.jetbrains.idea.maven.dom.refactorings.introduce;
import com.intellij.find.FindManager;
@@ -43,8 +58,8 @@
import java.util.*;
public class IntroducePropertyAction extends BaseRefactoringAction {
- private static String PREFIX = "${";
- private static String SUFFIX = "}";
+ private static final String PREFIX = "${";
+ private static final String SUFFIX = "}";
public IntroducePropertyAction() {
setInjectedContext(true);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenEditGoalDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenEditGoalDialog.java
index 4f0b999..148edeb 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenEditGoalDialog.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenEditGoalDialog.java
@@ -25,6 +25,7 @@
import com.intellij.ui.EditorComboBoxRenderer;
import com.intellij.ui.EditorTextField;
import com.intellij.ui.StringComboboxEditor;
+import com.intellij.util.ArrayUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.MavenConstants;
@@ -74,8 +75,7 @@
goalsLabel.setLabelFor(goalsEditor);
}
else {
- //noinspection SSBasedInspection
- goalsComboBox = new ComboBox(myHistory.toArray(new String[myHistory.size()]), -1);
+ goalsComboBox = new ComboBox(ArrayUtilRt.toStringArray(myHistory));
goalComponent = goalsComboBox;
goalsLabel.setLabelFor(goalsComboBox);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
index 4ba837b..0e68403 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenExternalParameters.java
@@ -118,6 +118,8 @@
final String mavenHome = resolveMavenHome(coreSettings, project, runConfiguration);
+ params.getProgramParametersList().add("-Didea.version=" + MavenUtil.getIdeaVersionToPassToMavenProcess());
+
addVMParameters(params.getVMParametersList(), mavenHome, runnerSettings);
File confFile = MavenUtil.getMavenConfFile(new File(mavenHome));
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcher.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcher.java
index 7d8bd8c..0dbfc4f 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcher.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcher.java
@@ -16,8 +16,10 @@
package org.jetbrains.idea.maven.execution;
import com.intellij.execution.JUnitPatcher;
+import com.intellij.execution.configurations.CommandLineTokenizer;
import com.intellij.execution.configurations.JavaParameters;
import com.intellij.openapi.module.Module;
+import com.intellij.openapi.util.text.StringUtil;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
@@ -59,7 +61,7 @@
}
Element systemPropertyVariables = config.getChild("systemPropertyVariables");
- if (systemPropertyVariables != null) {
+ if (systemPropertyVariables != null && isEnabled("systemPropertyVariables")) {
for (Element element : systemPropertyVariables.getChildren()) {
String propertyName = element.getName();
@@ -70,7 +72,7 @@
}
Element environmentVariables = config.getChild("environmentVariables");
- if (environmentVariables != null) {
+ if (environmentVariables != null && isEnabled("environmentVariables")) {
for (Element element : environmentVariables.getChildren()) {
String variableName = element.getName();
@@ -79,5 +81,17 @@
}
}
}
+
+ Element argLine = config.getChild("argLine");
+ if (argLine != null && isEnabled("argLine")) {
+ String value = argLine.getTextTrim();
+ if (StringUtil.isNotEmpty(value)) {
+ javaParameters.getVMParametersList().addParametersString(value);
+ }
+ }
+ }
+
+ private static boolean isEnabled(String s) {
+ return !Boolean.valueOf(System.getProperty("idea.maven.surefire.disable." + s));
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/RunnerBundle.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/RunnerBundle.java
index 73bf517..342a5e0 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/RunnerBundle.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/execution/RunnerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -16,17 +16,19 @@
package org.jetbrains.idea.maven.execution;
import com.intellij.AbstractBundle;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
public class RunnerBundle extends AbstractBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return ourInstance.getMessage(key, params);
+ }
+
private static final String PATH_TO_BUNDLE = "RunnerBundle";
private static final AbstractBundle ourInstance = new RunnerBundle();
private RunnerBundle() {
super(PATH_TO_BUNDLE);
}
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return ourInstance.getMessage(key, params);
- }
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java
deleted file mode 100644
index d4c4628..0000000
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/GroovyImporter.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package org.jetbrains.idea.maven.importing;
-
-import com.intellij.openapi.module.Module;
-import com.intellij.util.PairConsumer;
-import org.jdom.Element;
-import org.jetbrains.idea.maven.project.MavenProject;
-import org.jetbrains.idea.maven.project.MavenProjectChanges;
-import org.jetbrains.idea.maven.project.MavenProjectsProcessorTask;
-import org.jetbrains.idea.maven.project.MavenProjectsTree;
-import org.jetbrains.idea.maven.utils.MavenJDOMUtil;
-import org.jetbrains.jps.model.java.JavaSourceRootType;
-import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
-
-import java.util.List;
-import java.util.Map;
-
-public abstract class GroovyImporter extends MavenImporter {
- public GroovyImporter(String pluginGroupID, String pluginArtifactID) {
- super(pluginGroupID, pluginArtifactID);
- }
-
- @Override
- public void preProcess(Module module,
- MavenProject mavenProject,
- MavenProjectChanges changes,
- MavenModifiableModelsProvider modifiableModelsProvider) {
- }
-
- @Override
- public void process(MavenModifiableModelsProvider modifiableModelsProvider, Module module, MavenRootModelAdapter rootModel,
- MavenProjectsTree mavenModel,
- MavenProject mavenProject,
- MavenProjectChanges changes,
- Map<MavenProject, String> mavenProjectToModuleName,
- List<MavenProjectsProcessorTask> postTasks) {
- }
-
- @Override
- public void collectSourceRoots(MavenProject mavenProject, PairConsumer<String, JpsModuleSourceRootType<?>> result) {
- collectSourceOrTestFolders(mavenProject, "compile", "src/main/groovy", JavaSourceRootType.SOURCE, result);
- collectSourceOrTestFolders(mavenProject, "testCompile", "src/test/groovy", JavaSourceRootType.TEST_SOURCE, result);
- }
-
- private void collectSourceOrTestFolders(MavenProject mavenProject, String goal, String defaultDir, JavaSourceRootType type,
- PairConsumer<String, JpsModuleSourceRootType<?>> result) {
- Element sourcesElement = getGoalConfig(mavenProject, goal);
- List<String> dirs = MavenJDOMUtil.findChildrenValuesByPath(sourcesElement, "sources", "fileset.directory");
- if (dirs.isEmpty()) {
- result.consume(mavenProject.getDirectory() + "/" + defaultDir, type);
- return;
- }
- for (String dir : dirs) {
- result.consume(dir, type);
- }
- }
-
- @Override
- public void collectExcludedFolders(MavenProject mavenProject, List<String> result) {
- String stubsDir = findGoalConfigValue(mavenProject, "generateStubs", "outputDirectory");
- String testStubsDir = findGoalConfigValue(mavenProject, "generateTestStubs", "outputDirectory");
-
- // exclude common parent of /groovy-stubs/main and /groovy-stubs/test
- String defaultStubsDir = mavenProject.getGeneratedSourcesDirectory(false) + "/groovy-stubs";
-
- result.add(stubsDir == null ? defaultStubsDir : stubsDir);
- result.add(testStubsDir == null ? defaultStubsDir : testStubsDir);
- }
-}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/Groovy_1_0_Importer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/Groovy_1_0_Importer.java
deleted file mode 100644
index d80e994..0000000
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/Groovy_1_0_Importer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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 org.jetbrains.idea.maven.importing;
-
-public class Groovy_1_0_Importer extends GroovyImporter {
- public Groovy_1_0_Importer() {
- super("org.codehaus.groovy.maven", "gmaven-plugin");
- }
-}
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/Groovy_1_1_plus_Importer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/Groovy_1_1_plus_Importer.java
deleted file mode 100644
index 9b50a7b..0000000
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/Groovy_1_1_plus_Importer.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * 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 org.jetbrains.idea.maven.importing;
-
-public class Groovy_1_1_plus_Importer extends GroovyImporter {
- public Groovy_1_1_plus_Importer() {
- super("org.codehaus.gmaven", "gmaven-plugin");
- }
-}
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
index 0d4b06b..acae99f 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenModuleImporter.java
@@ -328,6 +328,8 @@
}
private void configLanguageLevel() {
+ if ("false".equalsIgnoreCase(System.getProperty("idea.maven.configure.language.level"))) return;
+
LanguageLevel level = null;
Element cfg = myMavenProject.getPluginConfiguration("com.googlecode", "maven-idea-plugin");
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java
index 10b4ac6..2fb6d9c 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/importing/MavenProjectImporter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -240,7 +240,7 @@
}
});
- if (result[0] == 0) {
+ if (result[0] == Messages.OK) {
for (Pair<MavenProject, Module> each : incompatibleNotMavenized) {
myFileToModuleMapping.remove(each.first.getFile());
myModuleModel.disposeModule(each.second);
@@ -305,7 +305,7 @@
}
});
- if (result[0] == 1) return false;// NO
+ if (result[0] == Messages.NO) return false;// NO
for (Module each : obsoleteModules) {
if (!each.isDisposed()) {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndicesBundle.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndicesBundle.java
index 524e18d..f557c66 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndicesBundle.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/IndicesBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,21 +25,20 @@
import java.util.ResourceBundle;
public class IndicesBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "IndicesBundle";
private IndicesBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java
index d4926d6..c028a25 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenArtifactSearchDialog.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.indices;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.Pair;
@@ -35,6 +36,8 @@
public class MavenArtifactSearchDialog extends DialogWrapper {
private List<MavenId> myResult = Collections.emptyList();
+ public static List<MavenId> ourResultForTest;
+
private TabbedPaneWrapper myTabbedPane;
private MavenArtifactSearchPanel myArtifactsPanel;
private MavenArtifactSearchPanel myClassesPanel;
@@ -45,6 +48,14 @@
@NotNull
public static List<MavenId> searchForClass(Project project, String className) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ assert ourResultForTest != null;
+
+ List<MavenId> res = ourResultForTest;
+ ourResultForTest = null;
+ return res;
+ }
+
MavenArtifactSearchDialog d = new MavenArtifactSearchDialog(project, className, true);
d.show();
if (!d.isOK()) return Collections.emptyList();
@@ -54,6 +65,14 @@
@NotNull
public static List<MavenId> searchForArtifact(Project project, Collection<MavenDomDependency> managedDependencies) {
+ if (ApplicationManager.getApplication().isUnitTestMode()) {
+ assert ourResultForTest != null;
+
+ List<MavenId> res = ourResultForTest;
+ ourResultForTest = null;
+ return res;
+ }
+
MavenArtifactSearchDialog d = new MavenArtifactSearchDialog(project, "", false);
d.setManagedDependencies(managedDependencies);
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 9fbefb0..614332f 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
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.indices;
+import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.io.*;
import gnu.trove.THashMap;
@@ -619,7 +620,7 @@
}
}
- private PersistentHashMap<String, Set<String>> createPersistentMap(File f) throws IOException {
+ private PersistentHashMap<String, Set<String>> createPersistentMap(final File f) throws IOException {
return new PersistentHashMap<String, Set<String>>(f, new EnumeratorStringDescriptor(), new SetDescriptor());
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java
index 945a4a7..d2db31c 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/indices/MavenProjectIndicesManager.java
@@ -15,7 +15,9 @@
*/
package org.jetbrains.idea.maven.indices;
+import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
@@ -100,8 +102,22 @@
public void scheduleUpdateIndicesList(@Nullable final Consumer<List<MavenIndex>> consumer) {
myUpdateQueue.queue(new Update(MavenProjectIndicesManager.this) {
public void run() {
- myProjectIndices = MavenIndicesManager.getInstance().ensureIndicesExist(
- myProject, getLocalRepository(), collectRemoteRepositoriesIdsAndUrls());
+ Set<Pair<String, String>> remoteRepositoriesIdsAndUrls;
+ File localRepository;
+
+ AccessToken accessToken = ReadAction.start();
+
+ try {
+ if (myProject.isDisposed()) return;
+
+ remoteRepositoriesIdsAndUrls = collectRemoteRepositoriesIdsAndUrls();
+ localRepository = getLocalRepository();
+ }
+ finally {
+ accessToken.finish();
+ }
+
+ myProjectIndices = MavenIndicesManager.getInstance().ensureIndicesExist(myProject, localRepository, remoteRepositoriesIdsAndUrls);
if(consumer != null) {
consumer.consume(myProjectIndices);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
index 525f0e7..8676153 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsNavigatorPanel.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.
@@ -318,7 +318,7 @@
@Override
public boolean canImport(final TransferSupport support) {
- return FileCopyPasteUtil.isFileListFlavorSupported(support.getDataFlavors());
+ return FileCopyPasteUtil.isFileListFlavorAvailable(support.getDataFlavors());
}
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java
index 68974c5..e6e574b 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/navigator/MavenProjectsStructure.java
@@ -22,22 +22,29 @@
import com.intellij.icons.AllIcons;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
+import com.intellij.pom.NavigatableAdapter;
+import com.intellij.psi.xml.XmlElement;
import com.intellij.ui.JBColor;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.treeStructure.*;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
+import gnu.trove.THashSet;
import icons.MavenIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
+import org.jetbrains.idea.maven.dom.MavenPluginDomUtil;
+import org.jetbrains.idea.maven.dom.plugin.MavenDomMojo;
+import org.jetbrains.idea.maven.dom.plugin.MavenDomPluginModel;
import org.jetbrains.idea.maven.execution.MavenRunConfiguration;
import org.jetbrains.idea.maven.execution.MavenRunConfigurationType;
import org.jetbrains.idea.maven.execution.MavenRunner;
@@ -64,6 +71,7 @@
private static final Collection<String> PHASES = MavenConstants.PHASES;
private static final Comparator<MavenSimpleNode> NODE_COMPARATOR = new Comparator<MavenSimpleNode>() {
+ @Override
public int compare(MavenSimpleNode o1, MavenSimpleNode o2) {
return StringUtil.compare(o1.getName(), o2.getName(), true);
}
@@ -106,6 +114,7 @@
tree.setShowsRootHandles(true);
MavenUIUtil.installCheckboxRenderer(tree, new MavenUIUtil.CheckboxHandler() {
+ @Override
public void toggle(TreePath treePath, InputEvent e) {
SimpleNode node = tree.getNodeFor(treePath);
if (node != null) {
@@ -113,10 +122,12 @@
}
}
+ @Override
public boolean isVisible(Object userObject) {
return userObject instanceof ProfileNode;
}
+ @Override
public MavenUIUtil.CheckBoxState getState(Object userObject) {
MavenProfileKind state = ((ProfileNode)userObject).getState();
switch (state) {
@@ -133,6 +144,7 @@
});
}
+ @Override
public RootNode getRootElement() {
return myRoot;
}
@@ -449,13 +461,13 @@
}
}
- protected void setNameAndTooltip(String name, @Nullable String tooltip, SimpleTextAttributes attribs) {
+ protected void setNameAndTooltip(String name, @Nullable String tooltip, SimpleTextAttributes attributes) {
clearColoredText();
- addColoredFragment(name, prepareAttribs(attribs));
+ addColoredFragment(name, prepareAttributes(attributes));
getTemplatePresentation().setTooltip(tooltip);
}
- private SimpleTextAttributes prepareAttribs(SimpleTextAttributes from) {
+ private SimpleTextAttributes prepareAttributes(SimpleTextAttributes from) {
ErrorLevel level = getTotalErrorLevel();
Color waveColor = level == ErrorLevel.NONE ? null : JBColor.RED;
int style = from.getStyle();
@@ -485,6 +497,7 @@
return MavenNavigationUtil.createNavigatableForPom(getProject(), getVirtualFile());
}
+ @Override
public void handleDoubleClickOrEnter(SimpleTree tree, InputEvent inputEvent) {
String actionId = getActionId();
if (actionId != null) {
@@ -587,6 +600,7 @@
setUniformIcon(MavenIcons.ProfilesClosed);
}
+ @Override
protected List<? extends MavenSimpleNode> doGetChildren() {
return myProfileNodes;
}
@@ -645,6 +659,7 @@
myState = state;
}
+ @Override
@Nullable
@NonNls
protected String getActionId() {
@@ -839,13 +854,14 @@
}
@Override
- protected void setNameAndTooltip(String name, @Nullable String tooltip, SimpleTextAttributes attribs) {
- super.setNameAndTooltip(name, tooltip, attribs);
+ protected void setNameAndTooltip(String name, @Nullable String tooltip, SimpleTextAttributes attributes) {
+ super.setNameAndTooltip(name, tooltip, attributes);
if (myProjectsNavigator.getShowVersions()) {
addColoredFragment(":" + myMavenProject.getMavenId().getVersion(), new SimpleTextAttributes(SimpleTextAttributes.STYLE_PLAIN, JBColor.GRAY));
}
}
+ @Override
@Nullable
@NonNls
protected String getMenuId() {
@@ -872,6 +888,7 @@
super(parent);
}
+ @Override
protected List<? extends MavenSimpleNode> doGetChildren() {
return myGoalNodes;
}
@@ -943,12 +960,14 @@
return original;
}
+ @Override
@Nullable
@NonNls
protected String getActionId() {
return "Maven.RunBuild";
}
+ @Override
@Nullable
@NonNls
protected String getMenuId() {
@@ -1001,6 +1020,7 @@
return message("view.node.plugins");
}
+ @Override
protected List<? extends MavenSimpleNode> doGetChildren() {
return myPluginNodes;
}
@@ -1078,7 +1098,7 @@
myGoalNodes.clear();
if (myPluginInfo != null) {
for (MavenPluginInfo.Mojo mojo : myPluginInfo.getMojos()) {
- myGoalNodes.add(new PluginGoalNode(this, mojo.getQualifiedGoal(), mojo.getDisplayName()));
+ myGoalNodes.add(new PluginGoalNode(this, mojo.getQualifiedGoal(), mojo.getGoal(), mojo.getDisplayName()));
}
}
@@ -1095,9 +1115,41 @@
}
public class PluginGoalNode extends GoalNode {
- public PluginGoalNode(PluginNode parent, String goal, String displayName) {
+
+ private final String myUnqualifiedGoal;
+
+ public PluginGoalNode(PluginNode parent, String goal, String unqualifiedGoal, String displayName) {
super(parent, goal, displayName);
setUniformIcon(MavenIcons.PluginGoal);
+ myUnqualifiedGoal = unqualifiedGoal;
+ }
+
+ @Nullable
+ @Override
+ public Navigatable getNavigatable() {
+ PluginNode pluginNode = (PluginNode)getParent();
+
+ MavenDomPluginModel pluginModel = MavenPluginDomUtil.getMavenPluginModel(myProject,
+ pluginNode.getPlugin().getGroupId(),
+ pluginNode.getPlugin().getArtifactId(),
+ pluginNode.getPlugin().getVersion());
+
+ if (pluginModel == null) return null;
+
+ for (MavenDomMojo mojo : pluginModel.getMojos().getMojos()) {
+ final XmlElement xmlElement = mojo.getGoal().getXmlElement();
+
+ if (xmlElement instanceof Navigatable && Comparing.equal(myUnqualifiedGoal, mojo.getGoal().getStringValue())) {
+ return new NavigatableAdapter() {
+ @Override
+ public void navigate(boolean requestFocus) {
+ ((Navigatable)xmlElement).navigate(requestFocus);
+ }
+ };
+ }
+ }
+
+ return null;
}
}
@@ -1269,15 +1321,13 @@
public void updateRunConfigurations(MavenProject mavenProject) {
boolean childChanged = false;
- List<RunnerAndConfigurationSettings>
- list = RunManager.getInstance(myProject).getConfigurationSettingsList(MavenRunConfigurationType.getInstance());
-
- Set<RunnerAndConfigurationSettings> cfgs = new HashSet<RunnerAndConfigurationSettings>(((Collection<RunnerAndConfigurationSettings>)((Collection)list)));
+ Set<RunnerAndConfigurationSettings> settings = new THashSet<RunnerAndConfigurationSettings>(
+ RunManager.getInstance(myProject).getConfigurationSettingsList(MavenRunConfigurationType.getInstance()));
for (Iterator<RunConfigurationNode> itr = myChildren.iterator(); itr.hasNext(); ) {
RunConfigurationNode node = itr.next();
- if (cfgs.remove(node.getSettings())) {
+ if (settings.remove(node.getSettings())) {
node.updateRunConfiguration();
}
else {
@@ -1290,7 +1340,7 @@
int oldSize = myChildren.size();
- for (RunnerAndConfigurationSettings cfg : cfgs) {
+ for (RunnerAndConfigurationSettings cfg : settings) {
MavenRunConfiguration mavenRunConfiguration = (MavenRunConfiguration)cfg.getConfiguration();
if (directory.equals(PathUtil.getCanonicalPath(mavenRunConfiguration.getRunnerParameters().getWorkingDirPath()))) {
@@ -1310,8 +1360,7 @@
}
public class RunConfigurationNode extends MavenSimpleNode {
-
- private RunnerAndConfigurationSettings mySettings;
+ private final RunnerAndConfigurationSettings mySettings;
public RunConfigurationNode(RunConfigurationsNode parent, RunnerAndConfigurationSettings settings) {
super(parent);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/GroovyGmavenImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/GroovyGmavenImporter.java
new file mode 100644
index 0000000..133515e
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/GroovyGmavenImporter.java
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.maven.plugins.groovy;
+
+public class GroovyGmavenImporter extends GroovyImporter {
+ public GroovyGmavenImporter() {
+ super("org.codehaus.gmaven", "groovy-maven-plugin");
+ }
+}
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/GroovyImporter.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/GroovyImporter.java
new file mode 100644
index 0000000..1608932
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/GroovyImporter.java
@@ -0,0 +1,71 @@
+package org.jetbrains.idea.maven.plugins.groovy;
+
+import com.intellij.openapi.module.Module;
+import com.intellij.util.PairConsumer;
+import org.jdom.Element;
+import org.jetbrains.idea.maven.importing.MavenImporter;
+import org.jetbrains.idea.maven.importing.MavenModifiableModelsProvider;
+import org.jetbrains.idea.maven.importing.MavenRootModelAdapter;
+import org.jetbrains.idea.maven.project.MavenProject;
+import org.jetbrains.idea.maven.project.MavenProjectChanges;
+import org.jetbrains.idea.maven.project.MavenProjectsProcessorTask;
+import org.jetbrains.idea.maven.project.MavenProjectsTree;
+import org.jetbrains.idea.maven.utils.MavenJDOMUtil;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+import java.util.List;
+import java.util.Map;
+
+public abstract class GroovyImporter extends MavenImporter {
+ public GroovyImporter(String pluginGroupID, String pluginArtifactID) {
+ super(pluginGroupID, pluginArtifactID);
+ }
+
+ @Override
+ public void preProcess(Module module,
+ MavenProject mavenProject,
+ MavenProjectChanges changes,
+ MavenModifiableModelsProvider modifiableModelsProvider) {
+ }
+
+ @Override
+ public void process(MavenModifiableModelsProvider modifiableModelsProvider, Module module, MavenRootModelAdapter rootModel,
+ MavenProjectsTree mavenModel,
+ MavenProject mavenProject,
+ MavenProjectChanges changes,
+ Map<MavenProject, String> mavenProjectToModuleName,
+ List<MavenProjectsProcessorTask> postTasks) {
+ }
+
+ @Override
+ public void collectSourceRoots(MavenProject mavenProject, PairConsumer<String, JpsModuleSourceRootType<?>> result) {
+ collectSourceOrTestFolders(mavenProject, "compile", "src/main/groovy", JavaSourceRootType.SOURCE, result);
+ collectSourceOrTestFolders(mavenProject, "testCompile", "src/test/groovy", JavaSourceRootType.TEST_SOURCE, result);
+ }
+
+ private void collectSourceOrTestFolders(MavenProject mavenProject, String goal, String defaultDir, JavaSourceRootType type,
+ PairConsumer<String, JpsModuleSourceRootType<?>> result) {
+ Element sourcesElement = getGoalConfig(mavenProject, goal);
+ List<String> dirs = MavenJDOMUtil.findChildrenValuesByPath(sourcesElement, "sources", "fileset.directory");
+ if (dirs.isEmpty()) {
+ result.consume(mavenProject.getDirectory() + "/" + defaultDir, type);
+ return;
+ }
+ for (String dir : dirs) {
+ result.consume(dir, type);
+ }
+ }
+
+ @Override
+ public void collectExcludedFolders(MavenProject mavenProject, List<String> result) {
+ String stubsDir = findGoalConfigValue(mavenProject, "generateStubs", "outputDirectory");
+ String testStubsDir = findGoalConfigValue(mavenProject, "generateTestStubs", "outputDirectory");
+
+ // exclude common parent of /groovy-stubs/main and /groovy-stubs/test
+ String defaultStubsDir = mavenProject.getGeneratedSourcesDirectory(false) + "/groovy-stubs";
+
+ result.add(stubsDir == null ? defaultStubsDir : stubsDir);
+ result.add(testStubsDir == null ? defaultStubsDir : testStubsDir);
+ }
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/Groovy_1_0_Importer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/Groovy_1_0_Importer.java
new file mode 100644
index 0000000..b92f016
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/Groovy_1_0_Importer.java
@@ -0,0 +1,22 @@
+/*
+ * 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 org.jetbrains.idea.maven.plugins.groovy;
+
+public class Groovy_1_0_Importer extends GroovyImporter {
+ public Groovy_1_0_Importer() {
+ super("org.codehaus.groovy.maven", "gmaven-plugin");
+ }
+}
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/Groovy_1_1_plus_Importer.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/Groovy_1_1_plus_Importer.java
new file mode 100644
index 0000000..cb8fb92
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/plugins/groovy/Groovy_1_1_plus_Importer.java
@@ -0,0 +1,22 @@
+/*
+ * 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 org.jetbrains.idea.maven.plugins.groovy;
+
+public class Groovy_1_1_plus_Importer extends GroovyImporter {
+ public Groovy_1_1_plus_Importer() {
+ super("org.codehaus.gmaven", "gmaven-plugin");
+ }
+}
\ No newline at end of file
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
index ed52f6a..6df92c4 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProject.java
@@ -61,7 +61,10 @@
.put("5", "1.5")
.put("1.6", "1.6")
.put("1.7", "1.7")
- .put("7", "1.7").build();
+ .put("7", "1.7")
+ .put("1.8", "1.8")
+ .put("8", "1.8")
+ .build();
public enum ProcMode {BOTH, ONLY, NONE}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
index a2863c4..0b3a8b5 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectReader.java
@@ -356,7 +356,7 @@
for (Element each : xmlProperties.getChildren()) {
String name = each.getName();
String value = each.getTextTrim();
- if (!props.containsKey(name) && !isEmptyOrSpaces(value)) {
+ if (!props.containsKey(name) && !isEmptyOrSpaces(name)) {
props.setProperty(name, value);
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
index c9df10b..2df814f 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenProjectsManager.java
@@ -457,6 +457,14 @@
if (mavenized) {
m.setOption(getMavenizedModuleOptionName(), "true");
+
+ // clear external system API options
+ // see com.intellij.openapi.externalSystem.service.project.manage.ModuleDataService#setModuleOptions
+ m.clearOption("external.system.id");
+ m.clearOption("external.linked.project.path");
+ m.clearOption("external.root.project.path");
+ m.clearOption("external.system.module.group");
+ m.clearOption("external.system.module.version");
}
else {
m.clearOption(getMavenizedModuleOptionName());
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java
index c2b0aa9..600c9f5 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/MavenResourceCompilerConfigurationGenerator.java
@@ -238,6 +238,7 @@
if (artifactResourceCfg == null) {
artifactResourceCfg = new MavenArtifactResourceConfiguration();
artifactResourceCfg.webArtifactName = webArtifactName;
+ artifactResourceCfg.moduleName = module.getName();
projectCfg.artifactsResources.put(webArtifactName, artifactResourceCfg);
}
else {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/ProjectBundle.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/ProjectBundle.java
index c4f5241..fe974ed 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/ProjectBundle.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/ProjectBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,21 +25,20 @@
import java.util.ResourceBundle;
public class ProjectBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "ProjectBundle";
private ProjectBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/MavenShowEffectivePom.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/MavenShowEffectivePom.java
index 7e1bd64..b938230 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/MavenShowEffectivePom.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/project/actions/MavenShowEffectivePom.java
@@ -66,7 +66,10 @@
if (project.isDisposed()) return;
if (s == null) { // null means UnsupportedOperationException
- showUnsupportedNotification(project, file);
+ new Notification(MavenUtil.MAVEN_NOTIFICATION_GROUP,
+ "Error",
+ "Failed to evaluate effective pom.",
+ NotificationType.ERROR).notify(project);
return;
}
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 17eadb6..12cdead 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,6 +20,7 @@
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;
@@ -33,7 +34,20 @@
protected boolean isAvailable(AnActionEvent e) {
if (!super.isAvailable(e)) return false;
- return MavenActionUtil.getMavenProjectsFiles(e.getDataContext()).size() == 1;
+ 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;
}
@Override
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 fad0d0e..c5ac93c 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
@@ -101,7 +101,7 @@
});
}
- @NotNull
+ @Nullable
public String evaluateEffectivePom(@NotNull final VirtualFile file, @NotNull final Collection<String> activeProfiles)
throws MavenProcessCanceledException {
return perform(new RetriableCancelable<String>() {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
index b4c440b..5777e24 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/server/MavenServerManager.java
@@ -228,6 +228,8 @@
params.getVMParametersList().defineProperty(each.getKey(), each.getValue());
}
+ params.getVMParametersList().addProperty("idea.version=", MavenUtil.getIdeaVersionToPassToMavenProcess());
+
boolean xmxSet = false;
if (mavenEmbedderVMOptions != null) {
@@ -258,6 +260,11 @@
params.getVMParametersList().addParametersString("-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=" + mavenEmbedderDebugPort);
}
+ String mavenEmbedderParameters = System.getProperty("idea.maven.embedder.parameters");
+ if (mavenEmbedderParameters != null) {
+ params.getProgramParametersList().addParametersString(mavenEmbedderParameters);
+ }
+
return params;
}
@@ -507,6 +514,7 @@
final Element element = new Element("maven-version");
element.setAttribute("version", useMaven2 ? "2.x" : "3.x");
element.setAttribute("vmOptions", mavenEmbedderVMOptions);
+ element.setAttribute("embedderJdk", embedderJdk);
return element;
}
@@ -517,6 +525,9 @@
String vmOptions = state.getAttributeValue("vmOptions");
mavenEmbedderVMOptions = vmOptions == null ? DEFAULT_VM_OPTIONS : vmOptions;
+
+ String embedderJdk = state.getAttributeValue("embedderJdk");
+ this.embedderJdk = embedderJdk == null ? MavenRunnerSettings.USE_INTERNAL_JAVA : embedderJdk;
}
private static class RemoteMavenServerLogger extends MavenRemoteObject implements MavenServerLogger {
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/TasksBundle.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/TasksBundle.java
index 3fbe422..965bb11 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/TasksBundle.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/tasks/TasksBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,21 +25,20 @@
import java.util.ResourceBundle;
public class TasksBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "TasksBundle";
private TasksBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java
index b76a9f1..83b7077 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenAttachSourcesProvider.java
@@ -44,6 +44,7 @@
import java.util.List;
public class MavenAttachSourcesProvider implements AttachSourcesProvider {
+ @Override
@NotNull
public Collection<AttachSourcesAction> getActions(final List<LibraryOrderEntry> orderEntries, final PsiFile psiFile) {
Collection<MavenProject> projects = getMavenProjects(psiFile);
@@ -51,14 +52,17 @@
if (findArtifacts(projects, orderEntries).isEmpty()) return Collections.emptyList();
return Collections.<AttachSourcesAction>singleton(new AttachSourcesAction() {
+ @Override
public String getName() {
return ProjectBundle.message("maven.action.download.sources");
}
+ @Override
public String getBusyText() {
return ProjectBundle.message("maven.action.download.sources.busy.text");
}
+ @Override
public ActionCallback perform(List<LibraryOrderEntry> orderEntries) {
// may have been changed by this time...
Collection<MavenProject> mavenProjects = getMavenProjects(psiFile);
@@ -75,6 +79,7 @@
final ActionCallback resultWrapper = new ActionCallback();
result.doWhenDone(new Consumer<MavenArtifactDownloader.DownloadResult>() {
+ @Override
public void consume(MavenArtifactDownloader.DownloadResult downloadResult) {
if (!downloadResult.unresolvedSources.isEmpty()) {
final StringBuilder message = new StringBuilder();
@@ -92,6 +97,7 @@
message.append("</html>");
SwingUtilities.invokeLater(new Runnable() {
+ @Override
public void run() {
Notifications.Bus.notify(new Notification(MavenUtil.MAVEN_NOTIFICATION_GROUP,
"Cannot download sources",
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java
index 71f22ec..15e7c9a 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/MavenUtil.java
@@ -29,6 +29,7 @@
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.impl.ApplicationInfoImpl;
import com.intellij.openapi.application.impl.LaterInvocator;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -932,4 +933,7 @@
return exploded ? baseName + " exploded" : baseName;
}
+ public static String getIdeaVersionToPassToMavenProcess() {
+ return ApplicationInfoImpl.getShadowInstance().getMajorVersion() + "." + ApplicationInfoImpl.getShadowInstance().getMinorVersion();
+ }
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/Strings.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/Strings.java
index c2cad56..1506f1d 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/Strings.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/utils/Strings.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.idea.maven.utils;
+import com.intellij.util.PatternUtil;
import org.jetbrains.annotations.NonNls;
import java.util.ArrayList;
@@ -53,12 +54,9 @@
if (patterns.length() != 0) {
patterns.append('|');
}
- patterns.append(translateToRegex(mask));
+ patterns.append(PatternUtil.convertToRegex(mask));
}
return patterns.toString();
}
- private static String translateToRegex(final String mask) {
- return mask.replaceAll("\\.", "\\.").replaceAll("\\*", ".*").replaceAll("\\?", ".");
- }
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.form b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.form
deleted file mode 100644
index d7bddc1..0000000
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.form
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.maven.wizards.MavenArchetypesPanel">
- <grid id="27dc6" binding="myMainPanel" 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>
- <xy x="20" y="20" width="500" height="400"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="15313" class="javax.swing.JCheckBox" binding="myUseArchetypeCheckBox" default-binding="true">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="Create from &archetype"/>
- </properties>
- </component>
- <hspacer id="15e41">
- <constraints>
- <grid row="0" 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="f63a2" class="javax.swing.JButton" binding="myAddArchetypeButton">
- <constraints>
- <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="A&dd Archetype..."/>
- </properties>
- </component>
- <grid id="d872d" binding="myArchetypesPanel" layout-manager="CardLayout" hgap="0" vgap="0">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="7" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children/>
- </grid>
- <scrollpane id="88686" class="com.intellij.ui.components.JBScrollPane" binding="myArchetypeDescriptionScrollPane">
- <constraints>
- <grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <component id="fb4a8" class="javax.swing.JTextArea" binding="myArchetypeDescriptionField">
- <constraints/>
- <properties/>
- </component>
- </children>
- </scrollpane>
- </children>
- </grid>
-</form>
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java
deleted file mode 100644
index cd00ccb..0000000
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesPanel.java
+++ /dev/null
@@ -1,325 +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.idea.maven.wizards;
-
-import com.intellij.ide.wizard.StepAdapter;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.ui.*;
-import com.intellij.ui.treeStructure.Tree;
-import com.intellij.util.containers.Convertor;
-import com.intellij.util.ui.AsyncProcessIcon;
-import com.intellij.util.ui.UIUtil;
-import com.intellij.util.ui.tree.TreeUtil;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.maven.indices.MavenIndicesManager;
-import org.jetbrains.idea.maven.model.MavenArchetype;
-
-import javax.swing.*;
-import javax.swing.event.TreeSelectionEvent;
-import javax.swing.event.TreeSelectionListener;
-import javax.swing.tree.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.*;
-import java.util.List;
-
-/**
- * @author Dmitry Avdeev
- * Date: 24.09.13
- */
-public class MavenArchetypesPanel implements Disposable {
-
- private JCheckBox myUseArchetypeCheckBox;
- private JButton myAddArchetypeButton;
- private JPanel myArchetypesPanel;
- private final Tree myArchetypesTree;
- private JScrollPane myArchetypeDescriptionScrollPane;
- private JPanel myMainPanel;
- private JTextArea myArchetypeDescriptionField;
-
- private Object myCurrentUpdaterMarker;
- private final AsyncProcessIcon myLoadingIcon = new AsyncProcessIcon.Big(getClass() + ".loading");
-
- private boolean skipUpdateUI;
- private final MavenModuleBuilder myBuilder;
- @Nullable private final StepAdapter myStep;
-
- public MavenArchetypesPanel(MavenModuleBuilder builder, @Nullable StepAdapter step) {
- myBuilder = builder;
- myStep = step;
- Disposer.register(this, myLoadingIcon);
-
- myArchetypesTree = new Tree();
- myArchetypesTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
- JScrollPane archetypesScrollPane = ScrollPaneFactory.createScrollPane(myArchetypesTree);
-
- myArchetypesPanel.add(archetypesScrollPane, "archetypes");
-
- JPanel loadingPanel = new JPanel(new GridBagLayout());
- JPanel bp = new JPanel(new BorderLayout(10, 10));
- bp.add(new JLabel("Loading archetype list..."), BorderLayout.NORTH);
- bp.add(myLoadingIcon, BorderLayout.CENTER);
-
- loadingPanel.add(bp, new GridBagConstraints());
-
- myArchetypesPanel.add(ScrollPaneFactory.createScrollPane(loadingPanel), "loading");
- ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes");
-
-
- myUseArchetypeCheckBox.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- updateComponents();
- archetypeMayBeChanged();
- }
- });
-
- myAddArchetypeButton.addActionListener(new ActionListener() {
- public void actionPerformed(ActionEvent e) {
- doAddArchetype();
- }
- });
-
- myArchetypesTree.setRootVisible(false);
- myArchetypesTree.setShowsRootHandles(true);
- myArchetypesTree.setCellRenderer(new MyRenderer());
- myArchetypesTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
-
- myArchetypesTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
- public void valueChanged(TreeSelectionEvent e) {
- updateArchetypeDescription();
- archetypeMayBeChanged();
- }
- });
-
- new TreeSpeedSearch(myArchetypesTree, new Convertor<TreePath, String>() {
- public String convert(TreePath path) {
- MavenArchetype info = getArchetypeInfoFromPathComponent(path.getLastPathComponent());
- return info.groupId + ":" + info.artifactId + ":" + info.version;
- }
- }).setComparator(new SpeedSearchComparator(false));
-
- myArchetypeDescriptionField.setEditable(false);
- myArchetypeDescriptionField.setBackground(UIUtil.getPanelBackground());
-
- requestUpdate();
- updateComponents();
- }
-
- public JPanel getMainPanel() {
- return myMainPanel;
- }
-
- private void updateComponents() {
- boolean archetypesEnabled = myUseArchetypeCheckBox.isSelected();
- myAddArchetypeButton.setEnabled(archetypesEnabled);
- myArchetypesTree.setEnabled(archetypesEnabled);
- myArchetypesTree.setBackground(archetypesEnabled ? UIUtil.getListBackground() : UIUtil.getPanelBackground());
-
- }
-
- @Nullable
- public MavenArchetype getSelectedArchetype() {
- if (!myUseArchetypeCheckBox.isSelected() || myArchetypesTree.isSelectionEmpty()) return null;
- return getArchetypeInfoFromPathComponent(myArchetypesTree.getLastSelectedPathComponent());
- }
-
- private static MavenArchetype getArchetypeInfoFromPathComponent(Object sel) {
- return (MavenArchetype)((DefaultMutableTreeNode)sel).getUserObject();
- }
-
- private void updateArchetypeDescription() {
- MavenArchetype sel = getSelectedArchetype();
- String desc = sel == null ? null : sel.description;
- if (StringUtil.isEmptyOrSpaces(desc)) {
- myArchetypeDescriptionScrollPane.setVisible(false);
- }
- else {
- myArchetypeDescriptionScrollPane.setVisible(true);
- myArchetypeDescriptionField.setText(desc);
- }
- }
-
- @Nullable
- private static TreePath findNodePath(MavenArchetype object, TreeModel model, Object parent) {
- for (int i = 0; i < model.getChildCount(parent); i++) {
- DefaultMutableTreeNode each = (DefaultMutableTreeNode)model.getChild(parent, i);
- if (each.getUserObject().equals(object)) return new TreePath(each.getPath());
-
- TreePath result = findNodePath(object, model, each);
- if (result != null) return result;
- }
- return null;
- }
-
- private static TreeNode groupAndSortArchetypes(Set<MavenArchetype> archetypes) {
- List<MavenArchetype> list = new ArrayList<MavenArchetype>(archetypes);
-
- Collections.sort(list, new Comparator<MavenArchetype>() {
- public int compare(MavenArchetype o1, MavenArchetype o2) {
- String key1 = o1.groupId + ":" + o1.artifactId;
- String key2 = o2.groupId + ":" + o2.artifactId;
-
- int result = key1.compareToIgnoreCase(key2);
- if (result != 0) return result;
-
- return o2.version.compareToIgnoreCase(o1.version);
- }
- });
-
- Map<String, List<MavenArchetype>> map = new TreeMap<String, List<MavenArchetype>>();
-
- for (MavenArchetype each : list) {
- String key = each.groupId + ":" + each.artifactId;
- List<MavenArchetype> versions = map.get(key);
- if (versions == null) {
- versions = new ArrayList<MavenArchetype>();
- map.put(key, versions);
- }
- versions.add(each);
- }
-
- DefaultMutableTreeNode result = new DefaultMutableTreeNode("root", true);
- for (List<MavenArchetype> each : map.values()) {
- MavenArchetype eachArchetype = each.get(0);
- DefaultMutableTreeNode node = new DefaultMutableTreeNode(eachArchetype, true);
- for (MavenArchetype eachVersion : each) {
- DefaultMutableTreeNode versionNode = new DefaultMutableTreeNode(eachVersion, false);
- node.add(versionNode);
- }
- result.add(node);
- }
-
- return result;
- }
-
- public void requestUpdate() {
-
- MavenArchetype selectedArch = getSelectedArchetype();
- if (selectedArch == null) {
- selectedArch = myBuilder.getArchetype();
- }
- if (selectedArch != null) myUseArchetypeCheckBox.setSelected(true);
-
- if (myArchetypesTree.getRowCount() == 0) updateArchetypesList(selectedArch);
- }
-
- public void updateArchetypesList(final MavenArchetype selected) {
- ApplicationManager.getApplication().assertIsDispatchThread();
-
- myLoadingIcon.setBackground(myArchetypesTree.getBackground());
-
- ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "loading");
-
- final Object currentUpdaterMarker = new Object();
- myCurrentUpdaterMarker = currentUpdaterMarker;
-
- ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
- public void run() {
- final Set<MavenArchetype> archetypes = MavenIndicesManager.getInstance().getArchetypes();
-
- //noinspection SSBasedInspection
- SwingUtilities.invokeLater(new Runnable() {
- public void run() {
- if (currentUpdaterMarker != myCurrentUpdaterMarker) return; // Other updater has been run.
-
- ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes");
-
- TreeNode root = groupAndSortArchetypes(archetypes);
- TreeModel model = new DefaultTreeModel(root);
- myArchetypesTree.setModel(model);
-
- if (selected != null) {
- TreePath path = findNodePath(selected, model, model.getRoot());
- if (path != null) {
- myArchetypesTree.expandPath(path.getParentPath());
- TreeUtil.selectPath(myArchetypesTree, path, true);
- }
- }
-
- updateArchetypeDescription();
- }
- });
- }
- });
- }
-
- public boolean isSkipUpdateUI() {
- return skipUpdateUI;
- }
-
- private void archetypeMayBeChanged() {
- MavenArchetype selectedArchetype = getSelectedArchetype();
- if (((myBuilder.getArchetype() == null) != (selectedArchetype == null))) {
- myBuilder.setArchetype(selectedArchetype);
- skipUpdateUI = true;
- try {
- if (myStep != null) {
- myStep.fireStateChanged();
- }
- }
- finally {
- skipUpdateUI = false;
- }
- }
- }
-
-
- private void doAddArchetype() {
- MavenAddArchetypeDialog dialog = new MavenAddArchetypeDialog(myMainPanel);
- dialog.show();
- if (!dialog.isOK()) return;
-
- MavenArchetype archetype = dialog.getArchetype();
- MavenIndicesManager.getInstance().addArchetype(archetype);
- updateArchetypesList(archetype);
- }
-
- @Override
- public void dispose() {
- }
-
- private static class MyRenderer extends ColoredTreeCellRenderer {
- public void customizeCellRenderer(JTree tree,
- Object value,
- boolean selected,
- boolean expanded,
- boolean leaf,
- int row,
- boolean hasFocus) {
- Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
- if (!(userObject instanceof MavenArchetype)) return;
-
- MavenArchetype info = (MavenArchetype)userObject;
-
- if (leaf) {
- append(info.artifactId, SimpleTextAttributes.GRAY_ATTRIBUTES);
- append(":" + info.version, SimpleTextAttributes.REGULAR_ATTRIBUTES);
- }
- else {
- append(info.groupId + ":", SimpleTextAttributes.GRAY_ATTRIBUTES);
- append(info.artifactId, SimpleTextAttributes.REGULAR_ATTRIBUTES);
- }
- }
- }
-
-}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesStep.form b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesStep.form
new file mode 100644
index 0000000..b6dbd8d
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesStep.form
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="org.jetbrains.idea.maven.wizards.MavenArchetypesStep">
+ <grid id="27dc6" binding="myMainPanel" 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>
+ <xy x="20" y="20" width="500" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="15313" class="javax.swing.JCheckBox" binding="myUseArchetypeCheckBox" default-binding="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="Create from &archetype"/>
+ </properties>
+ </component>
+ <hspacer id="15e41">
+ <constraints>
+ <grid row="0" 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="f63a2" class="javax.swing.JButton" binding="myAddArchetypeButton">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <text value="A&dd Archetype..."/>
+ </properties>
+ </component>
+ <grid id="d872d" binding="myArchetypesPanel" layout-manager="CardLayout" hgap="0" vgap="0">
+ <constraints>
+ <grid row="1" column="0" row-span="1" col-span="3" vsize-policy="7" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children/>
+ </grid>
+ <scrollpane id="88686" class="com.intellij.ui.components.JBScrollPane" binding="myArchetypeDescriptionScrollPane">
+ <constraints>
+ <grid row="2" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="fb4a8" class="javax.swing.JTextArea" binding="myArchetypeDescriptionField">
+ <constraints/>
+ <properties/>
+ </component>
+ </children>
+ </scrollpane>
+ </children>
+ </grid>
+</form>
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesStep.java
new file mode 100644
index 0000000..e9cb627
--- /dev/null
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenArchetypesStep.java
@@ -0,0 +1,337 @@
+/*
+ * 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.idea.maven.wizards;
+
+import com.intellij.ide.util.projectWizard.ModuleWizardStep;
+import com.intellij.ide.wizard.StepAdapter;
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.*;
+import com.intellij.ui.treeStructure.Tree;
+import com.intellij.util.containers.Convertor;
+import com.intellij.util.ui.AsyncProcessIcon;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.tree.TreeUtil;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.indices.MavenIndicesManager;
+import org.jetbrains.idea.maven.model.MavenArchetype;
+
+import javax.swing.*;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.*;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.*;
+import java.util.List;
+
+/**
+ * @author Dmitry Avdeev
+ * Date: 24.09.13
+ */
+public class MavenArchetypesStep extends ModuleWizardStep implements Disposable {
+
+ private JCheckBox myUseArchetypeCheckBox;
+ private JButton myAddArchetypeButton;
+ private JPanel myArchetypesPanel;
+ private final Tree myArchetypesTree;
+ private JScrollPane myArchetypeDescriptionScrollPane;
+ private JPanel myMainPanel;
+ private JTextArea myArchetypeDescriptionField;
+
+ private Object myCurrentUpdaterMarker;
+ private final AsyncProcessIcon myLoadingIcon = new AsyncProcessIcon.Big(getClass() + ".loading");
+
+ private boolean skipUpdateUI;
+ private final MavenModuleBuilder myBuilder;
+ @Nullable private final StepAdapter myStep;
+
+ public MavenArchetypesStep(MavenModuleBuilder builder, @Nullable StepAdapter step) {
+ myBuilder = builder;
+ myStep = step;
+ Disposer.register(this, myLoadingIcon);
+
+ myArchetypesTree = new Tree();
+ myArchetypesTree.setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
+ JScrollPane archetypesScrollPane = ScrollPaneFactory.createScrollPane(myArchetypesTree);
+
+ myArchetypesPanel.add(archetypesScrollPane, "archetypes");
+
+ JPanel loadingPanel = new JPanel(new GridBagLayout());
+ JPanel bp = new JPanel(new BorderLayout(10, 10));
+ bp.add(new JLabel("Loading archetype list..."), BorderLayout.NORTH);
+ bp.add(myLoadingIcon, BorderLayout.CENTER);
+
+ loadingPanel.add(bp, new GridBagConstraints());
+
+ myArchetypesPanel.add(ScrollPaneFactory.createScrollPane(loadingPanel), "loading");
+ ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes");
+
+
+ myUseArchetypeCheckBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ updateComponents();
+ archetypeMayBeChanged();
+ }
+ });
+
+ myAddArchetypeButton.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ doAddArchetype();
+ }
+ });
+
+ myArchetypesTree.setRootVisible(false);
+ myArchetypesTree.setShowsRootHandles(true);
+ myArchetypesTree.setCellRenderer(new MyRenderer());
+ myArchetypesTree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+
+ myArchetypesTree.getSelectionModel().addTreeSelectionListener(new TreeSelectionListener() {
+ public void valueChanged(TreeSelectionEvent e) {
+ updateArchetypeDescription();
+ archetypeMayBeChanged();
+ }
+ });
+
+ new TreeSpeedSearch(myArchetypesTree, new Convertor<TreePath, String>() {
+ public String convert(TreePath path) {
+ MavenArchetype info = getArchetypeInfoFromPathComponent(path.getLastPathComponent());
+ return info.groupId + ":" + info.artifactId + ":" + info.version;
+ }
+ }).setComparator(new SpeedSearchComparator(false));
+
+ myArchetypeDescriptionField.setEditable(false);
+ myArchetypeDescriptionField.setBackground(UIUtil.getPanelBackground());
+
+ requestUpdate();
+ updateComponents();
+ }
+
+ public JPanel getMainPanel() {
+ return myMainPanel;
+ }
+
+ private void updateComponents() {
+ boolean archetypesEnabled = myUseArchetypeCheckBox.isSelected();
+ myAddArchetypeButton.setEnabled(archetypesEnabled);
+ myArchetypesTree.setEnabled(archetypesEnabled);
+ myArchetypesTree.setBackground(archetypesEnabled ? UIUtil.getListBackground() : UIUtil.getPanelBackground());
+
+ }
+
+ @Nullable
+ public MavenArchetype getSelectedArchetype() {
+ if (!myUseArchetypeCheckBox.isSelected() || myArchetypesTree.isSelectionEmpty()) return null;
+ return getArchetypeInfoFromPathComponent(myArchetypesTree.getLastSelectedPathComponent());
+ }
+
+ private static MavenArchetype getArchetypeInfoFromPathComponent(Object sel) {
+ return (MavenArchetype)((DefaultMutableTreeNode)sel).getUserObject();
+ }
+
+ private void updateArchetypeDescription() {
+ MavenArchetype sel = getSelectedArchetype();
+ String desc = sel == null ? null : sel.description;
+ if (StringUtil.isEmptyOrSpaces(desc)) {
+ myArchetypeDescriptionScrollPane.setVisible(false);
+ }
+ else {
+ myArchetypeDescriptionScrollPane.setVisible(true);
+ myArchetypeDescriptionField.setText(desc);
+ }
+ }
+
+ @Nullable
+ private static TreePath findNodePath(MavenArchetype object, TreeModel model, Object parent) {
+ for (int i = 0; i < model.getChildCount(parent); i++) {
+ DefaultMutableTreeNode each = (DefaultMutableTreeNode)model.getChild(parent, i);
+ if (each.getUserObject().equals(object)) return new TreePath(each.getPath());
+
+ TreePath result = findNodePath(object, model, each);
+ if (result != null) return result;
+ }
+ return null;
+ }
+
+ private static TreeNode groupAndSortArchetypes(Set<MavenArchetype> archetypes) {
+ List<MavenArchetype> list = new ArrayList<MavenArchetype>(archetypes);
+
+ Collections.sort(list, new Comparator<MavenArchetype>() {
+ public int compare(MavenArchetype o1, MavenArchetype o2) {
+ String key1 = o1.groupId + ":" + o1.artifactId;
+ String key2 = o2.groupId + ":" + o2.artifactId;
+
+ int result = key1.compareToIgnoreCase(key2);
+ if (result != 0) return result;
+
+ return o2.version.compareToIgnoreCase(o1.version);
+ }
+ });
+
+ Map<String, List<MavenArchetype>> map = new TreeMap<String, List<MavenArchetype>>();
+
+ for (MavenArchetype each : list) {
+ String key = each.groupId + ":" + each.artifactId;
+ List<MavenArchetype> versions = map.get(key);
+ if (versions == null) {
+ versions = new ArrayList<MavenArchetype>();
+ map.put(key, versions);
+ }
+ versions.add(each);
+ }
+
+ DefaultMutableTreeNode result = new DefaultMutableTreeNode("root", true);
+ for (List<MavenArchetype> each : map.values()) {
+ MavenArchetype eachArchetype = each.get(0);
+ DefaultMutableTreeNode node = new DefaultMutableTreeNode(eachArchetype, true);
+ for (MavenArchetype eachVersion : each) {
+ DefaultMutableTreeNode versionNode = new DefaultMutableTreeNode(eachVersion, false);
+ node.add(versionNode);
+ }
+ result.add(node);
+ }
+
+ return result;
+ }
+
+ public void requestUpdate() {
+
+ MavenArchetype selectedArch = getSelectedArchetype();
+ if (selectedArch == null) {
+ selectedArch = myBuilder.getArchetype();
+ }
+ if (selectedArch != null) myUseArchetypeCheckBox.setSelected(true);
+
+ if (myArchetypesTree.getRowCount() == 0) updateArchetypesList(selectedArch);
+ }
+
+ public void updateArchetypesList(final MavenArchetype selected) {
+ ApplicationManager.getApplication().assertIsDispatchThread();
+
+ myLoadingIcon.setBackground(myArchetypesTree.getBackground());
+
+ ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "loading");
+
+ final Object currentUpdaterMarker = new Object();
+ myCurrentUpdaterMarker = currentUpdaterMarker;
+
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ public void run() {
+ final Set<MavenArchetype> archetypes = MavenIndicesManager.getInstance().getArchetypes();
+
+ //noinspection SSBasedInspection
+ SwingUtilities.invokeLater(new Runnable() {
+ public void run() {
+ if (currentUpdaterMarker != myCurrentUpdaterMarker) return; // Other updater has been run.
+
+ ((CardLayout)myArchetypesPanel.getLayout()).show(myArchetypesPanel, "archetypes");
+
+ TreeNode root = groupAndSortArchetypes(archetypes);
+ TreeModel model = new DefaultTreeModel(root);
+ myArchetypesTree.setModel(model);
+
+ if (selected != null) {
+ TreePath path = findNodePath(selected, model, model.getRoot());
+ if (path != null) {
+ myArchetypesTree.expandPath(path.getParentPath());
+ TreeUtil.selectPath(myArchetypesTree, path, true);
+ }
+ }
+
+ updateArchetypeDescription();
+ }
+ });
+ }
+ });
+ }
+
+ public boolean isSkipUpdateUI() {
+ return skipUpdateUI;
+ }
+
+ private void archetypeMayBeChanged() {
+ MavenArchetype selectedArchetype = getSelectedArchetype();
+ if (((myBuilder.getArchetype() == null) != (selectedArchetype == null))) {
+ myBuilder.setArchetype(selectedArchetype);
+ skipUpdateUI = true;
+ try {
+ if (myStep != null) {
+ myStep.fireStateChanged();
+ }
+ }
+ finally {
+ skipUpdateUI = false;
+ }
+ }
+ }
+
+
+ private void doAddArchetype() {
+ MavenAddArchetypeDialog dialog = new MavenAddArchetypeDialog(myMainPanel);
+ dialog.show();
+ if (!dialog.isOK()) return;
+
+ MavenArchetype archetype = dialog.getArchetype();
+ MavenIndicesManager.getInstance().addArchetype(archetype);
+ updateArchetypesList(archetype);
+ }
+
+ @Override
+ public void dispose() {
+ }
+
+ @Override
+ public JComponent getComponent() {
+ return getMainPanel();
+ }
+
+ @Override
+ public void updateDataModel() {
+ MavenArchetype selectedArchetype = getSelectedArchetype();
+ myBuilder.setArchetype(selectedArchetype);
+ }
+
+ private static class MyRenderer extends ColoredTreeCellRenderer {
+ public void customizeCellRenderer(JTree tree,
+ Object value,
+ boolean selected,
+ boolean expanded,
+ boolean leaf,
+ int row,
+ boolean hasFocus) {
+ Object userObject = ((DefaultMutableTreeNode)value).getUserObject();
+ if (!(userObject instanceof MavenArchetype)) return;
+
+ MavenArchetype info = (MavenArchetype)userObject;
+
+ if (leaf) {
+ append(info.artifactId, SimpleTextAttributes.GRAY_ATTRIBUTES);
+ append(":" + info.version, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ }
+ else {
+ append(info.groupId + ":", SimpleTextAttributes.GRAY_ATTRIBUTES);
+ append(info.artifactId, SimpleTextAttributes.REGULAR_ATTRIBUTES);
+ }
+ }
+ }
+
+}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java
index db1e1a6..1561223 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilder.java
@@ -21,7 +21,6 @@
import com.intellij.ide.util.projectWizard.SourcePathsBuilder;
import com.intellij.ide.util.projectWizard.WizardContext;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.module.JavaModuleType;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.options.ConfigurationException;
@@ -98,6 +97,11 @@
}
@Override
+ public String getParentGroup() {
+ return getModuleTypeName();
+ }
+
+ @Override
public String getDescription() {
return "Maven modules are used for developing <b>JVM-based</b> applications with dependencies managed by <b>Maven</b>. " +
"You can create either a blank Maven module or a module based on a <b>Maven archetype</b>.";
@@ -130,17 +134,6 @@
};
}
- public MavenProject findPotentialParentProject(Project project) {
- if (!MavenProjectsManager.getInstance(project).isMavenizedProject()) return null;
-
- File parentDir = new File(getContentEntryPath()).getParentFile();
- if (parentDir == null) return null;
- VirtualFile parentPom = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(parentDir, "pom.xml"));
- if (parentPom == null) return null;
-
- return MavenProjectsManager.getInstance(project).findProject(parentPom);
- }
-
private VirtualFile createAndGetContentEntry() {
String path = FileUtil.toSystemIndependentName(getContentEntryPath());
new File(path).mkdirs();
@@ -220,18 +213,14 @@
@Override
public String getGroupName() {
- return JavaModuleType.JAVA_GROUP;
+ return "Maven";
}
- private MavenArchetypesPanel myPanel;
-
@Nullable
@Override
- public JComponent getCustomOptionsPanel(Disposable parentDisposable) {
- if (myPanel == null) {
- myPanel = new MavenArchetypesPanel(this, null);
- Disposer.register(parentDisposable, myPanel);
- }
- return myPanel.getMainPanel();
+ public ModuleWizardStep getCustomOptionsStep(WizardContext context, Disposable parentDisposable) {
+ MavenArchetypesStep step = new MavenArchetypesStep(this, null);
+ Disposer.register(parentDisposable, step);
+ return step;
}
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java
index ec99bd5..d3da701 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/wizards/MavenModuleWizardStep.java
@@ -23,6 +23,8 @@
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.IconLoader;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.MavenArchetype;
@@ -35,6 +37,7 @@
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
+import java.io.File;
public class MavenModuleWizardStep extends ModuleWizardStep {
private static final Icon WIZARD_ICON = IconLoader.getIcon("/addmodulewizard.png");
@@ -71,14 +74,14 @@
private JPanel myAddToPanel;
@Nullable
- private final MavenArchetypesPanel myArchetypes;
+ private final MavenArchetypesStep myArchetypes;
public MavenModuleWizardStep(MavenModuleBuilder builder, WizardContext context, boolean includeArtifacts) {
myProjectOrNull = context.getProject();
myBuilder = builder;
myContext = context;
if (includeArtifacts) {
- myArchetypes = new MavenArchetypesPanel(builder, this);
+ myArchetypes = new MavenArchetypesStep(builder, this);
myArchetypesPanel.add(myArchetypes.getMainPanel(), BorderLayout.CENTER);
}
else {
@@ -198,18 +201,27 @@
return true;
}
+ public MavenProject findPotentialParentProject(Project project) {
+ if (!MavenProjectsManager.getInstance(project).isMavenizedProject()) return null;
+
+ VirtualFile parentPom = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myContext.getProjectFileDirectory(), "pom.xml"));
+ if (parentPom == null) return null;
+
+ return MavenProjectsManager.getInstance(project).findProject(parentPom);
+ }
+
private static void setTestIfEmpty(@NotNull JTextField artifactIdField, @Nullable String text) {
if (StringUtil.isEmpty(artifactIdField.getText())) {
artifactIdField.setText(StringUtil.notNullize(text));
}
}
-
+
@Override
public void updateStep() {
if (myArchetypes != null && myArchetypes.isSkipUpdateUI()) return;
if (isMavenizedProject()) {
- MavenProject parent = myBuilder.findPotentialParentProject(myProjectOrNull);
+ MavenProject parent = findPotentialParentProject(myProjectOrNull);
myAggregator = parent;
myParent = parent;
}
@@ -288,6 +300,10 @@
myBuilder.setInheritedOptions(myInheritGroupIdCheckBox.isSelected(),
myInheritVersionCheckBox.isSelected());
+ if (myContext.getProjectName() == null) {
+ myContext.setProjectName(myBuilder.getProjectId().getArtifactId());
+ }
+
if (myArchetypes != null) {
myBuilder.setArchetype(myArchetypes.getSelectedArchetype());
}
diff --git a/plugins/maven/src/main/resources/META-INF/groovy-support.xml b/plugins/maven/src/main/resources/META-INF/groovy-support.xml
index a3b21c1..3dc7ba1 100644
--- a/plugins/maven/src/main/resources/META-INF/groovy-support.xml
+++ b/plugins/maven/src/main/resources/META-INF/groovy-support.xml
@@ -1,7 +1,8 @@
<idea-plugin url="http://www.jetbrains.com/idea">
<extensions defaultExtensionNs="org.jetbrains.idea.maven">
- <importer implementation="org.jetbrains.idea.maven.importing.Groovy_1_0_Importer"/>
- <importer implementation="org.jetbrains.idea.maven.importing.Groovy_1_1_plus_Importer"/>
+ <importer implementation="org.jetbrains.idea.maven.plugins.groovy.Groovy_1_0_Importer"/>
+ <importer implementation="org.jetbrains.idea.maven.plugins.groovy.Groovy_1_1_plus_Importer"/>
+ <importer implementation="org.jetbrains.idea.maven.plugins.groovy.GroovyGmavenImporter"/>
<pluginDescriptor mavenId="org.codehaus.groovy.maven:gmaven-plugin">
<param name="source" languageProvider="org.jetbrains.idea.maven.plugins.groovy.MavenGroovyLanguageProvider"/>
@@ -10,6 +11,10 @@
<pluginDescriptor mavenId="org.codehaus.gmaven:gmaven-plugin">
<param name="source" languageProvider="org.jetbrains.idea.maven.plugins.groovy.MavenGroovyLanguageProvider"/>
</pluginDescriptor>
+
+ <pluginDescriptor mavenId="org.codehaus.gmaven:groovy-maven-plugin">
+ <param name="source" languageProvider="org.jetbrains.idea.maven.plugins.groovy.MavenGroovyLanguageProvider"/>
+ </pluginDescriptor>
</extensions>
<extensions defaultExtensionNs="org.intellij.groovy">
diff --git a/plugins/maven/src/main/resources/META-INF/plugin.xml b/plugins/maven/src/main/resources/META-INF/plugin.xml
index 0ff8c82..337fe0c 100644
--- a/plugins/maven/src/main/resources/META-INF/plugin.xml
+++ b/plugins/maven/src/main/resources/META-INF/plugin.xml
@@ -437,9 +437,6 @@
icon="AllIcons.Nodes.ExceptionClass">
</action>
- <action id="Maven.Help"
- class="com.intellij.ide.actions.ContextHelpAction" text="Help"/>
-
<action id="Maven.ExpandAll" class="org.jetbrains.idea.maven.navigator.actions.MavenTreeAction$ExpandAll" text="Expand All"
icon="AllIcons.Actions.Expandall"
use-shortcut-of="ExpandAll"/>
@@ -527,7 +524,6 @@
<reference id="Maven.CollapseAll"/>
<separator/>
<reference id="Maven.ShowSettings"/>
- <reference id="Maven.Help"/>
</group>
<group id="Maven.DependencyMenu">
diff --git a/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0-sources.jar b/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0-sources.jar
new file mode 100644
index 0000000..15b3b6c
--- /dev/null
+++ b/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0-sources.jar
Binary files differ
diff --git a/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0.jar b/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0.jar
new file mode 100644
index 0000000..f9c570b
--- /dev/null
+++ b/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0.jar
Binary files differ
diff --git a/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0.pom b/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0.pom
new file mode 100644
index 0000000..510cdec
--- /dev/null
+++ b/plugins/maven/src/test/data/plugins/intellij/test/maven-extension/1.0/maven-extension-1.0.pom
@@ -0,0 +1,40 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>intellij.test</groupId>
+ <artifactId>maven-extension</artifactId>
+ <version>1.0</version>
+ <packaging>jar</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-metadata</artifactId>
+ <version>1.5.5</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>generate-metadata</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-core</artifactId>
+ <version>3.0.3</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-component-annotations</artifactId>
+ <version>1.5.5</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/maven/src/test/data/plugins/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar b/plugins/maven/src/test/data/plugins/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar
new file mode 100644
index 0000000..5c50e17
--- /dev/null
+++ b/plugins/maven/src/test/data/plugins/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar
Binary files differ
diff --git a/plugins/maven/src/test/data/plugins/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom b/plugins/maven/src/test/data/plugins/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom
new file mode 100644
index 0000000..6cf9079
--- /dev/null
+++ b/plugins/maven/src/test/data/plugins/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?><project>
+ <parent>
+ <artifactId>plexus</artifactId>
+ <groupId>org.codehaus.plexus</groupId>
+ <version>1.0.4</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>plexus-utils</artifactId>
+ <name>Plexus Common Utilities</name>
+ <version>1.1</version>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <excludes>
+ <exclude>org/codehaus/plexus/util/FileBasedTestCase.java</exclude>
+ <exclude>**/Test*.java</exclude>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <distributionManagement>
+ <status>deployed</status>
+ </distributionManagement>
+</project>
\ No newline at end of file
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
index 1f7a404..9de33c5 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenImportingTestCase.java
@@ -546,58 +546,6 @@
return IdeaTestUtil.getMockJdk17(versionName);
}
- protected void compileModules(final String... moduleNames) throws Exception {
- final List<Module> modules = new ArrayList<Module>();
-
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- for (String each : moduleNames) {
- setupJdkForModule(each);
- modules.add(getModule(each));
- }
- if (useJps()) {
- new MavenResourceCompilerConfigurationGenerator(myProject, MavenProjectsManager.getInstance(myProject).getProjectsTreeForTests())
- .generateBuildConfiguration(false);
- }
- }
- });
-
- CompilerWorkspaceConfiguration.getInstance(myProject).CLEAR_OUTPUT_DIRECTORY = true;
- CompilerManagerImpl.testSetup();
-
- List<VirtualFile> roots = Arrays.asList(ProjectRootManager.getInstance(myProject).getContentRoots());
- TranslatingCompilerFilesMonitor.getInstance()
- .scanSourceContent(new TranslatingCompilerFilesMonitor.ProjectRef(myProject), roots, roots.size(), true);
-
- final CompileScope scope = new ModuleCompileScope(myProject, modules.toArray(new Module[modules.size()]), false);
-
- final Semaphore semaphore = new Semaphore();
- semaphore.down();
- UIUtil.invokeAndWaitIfNeeded(new Runnable() {
- @Override
- public void run() {
- CompilerManager.getInstance(myProject).make(scope, new CompileStatusNotification() {
- @Override
- public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
- //assertFalse(aborted);
- //assertEquals(collectMessages(compileContext, CompilerMessageCategory.ERROR), 0, errors);
- //assertEquals(collectMessages(compileContext, CompilerMessageCategory.WARNING), 0, warnings);
- semaphore.up();
- }
- });
- }
- });
- while (!semaphore.waitFor(100)) {
- if (SwingUtilities.isEventDispatchThread()) {
- UIUtil.dispatchAllInvocationEvents();
- }
- }
- if (SwingUtilities.isEventDispatchThread()) {
- UIUtil.dispatchAllInvocationEvents();
- }
- }
-
protected static AtomicInteger configConfirmationForYesAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
index ed54389..0b1c369 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/MavenTestCase.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.
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/AddMavenDependencyQuickFixTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/AddMavenDependencyQuickFixTest.java
new file mode 100644
index 0000000..c934e6c
--- /dev/null
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/actions/AddMavenDependencyQuickFixTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.idea.maven.actions;
+
+import com.intellij.codeInsight.intention.IntentionAction;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiManager;
+import org.jetbrains.idea.maven.dom.MavenDomWithIndicesTestCase;
+import org.jetbrains.idea.maven.indices.MavenArtifactSearchDialog;
+import org.jetbrains.idea.maven.model.MavenId;
+
+import java.io.IOException;
+import java.util.Collections;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class AddMavenDependencyQuickFixTest extends MavenDomWithIndicesTestCase {
+
+ private IntentionAction findAddMavenIntention() {
+ for (IntentionAction intention : myFixture.getAvailableIntentions()) {
+ if (intention.getText().contains("Add Maven")) {
+ return intention;
+ }
+ }
+
+ return null;
+ }
+
+ public void testAddDependency() throws IOException {
+ VirtualFile f = createProjectSubFile("src/main/java/A.java", "import org.apache.commons.io.IOUtils;\n" +
+ "\n" +
+ "public class Aaa {\n" +
+ "\n" +
+ " public void xxx() {\n" +
+ " IOUtil<caret>s u;\n" +
+ " }\n" +
+ "\n" +
+ "}");
+
+ importProject("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>");
+
+ myFixture.configureFromExistingVirtualFile(f);
+
+ IntentionAction intentionAction = findAddMavenIntention();
+
+ MavenArtifactSearchDialog.ourResultForTest = Collections.singletonList(new MavenId("commons-io", "commons-io", "2.4"));
+
+ intentionAction.invoke(myProject, myFixture.getEditor(), myFixture.getFile());
+
+ String pomText = PsiManager.getInstance(myProject).findFile(myProjectPom).getText();
+ assert pomText.matches(
+ "(?s).*<dependency>\\s*<groupId>commons-io</groupId>\\s*<artifactId>commons-io</artifactId>\\s*<version>2.4</version>\\s*</dependency>.*");
+ }
+
+ public void testAddDependencyInTest() throws IOException {
+ VirtualFile f = createProjectSubFile("src/test/java/A.java", "import org.apache.commons.io.IOUtils;\n" +
+ "\n" +
+ "public class Aaa {\n" +
+ "\n" +
+ " public void xxx() {\n" +
+ " IOUtil<caret>s u;\n" +
+ " }\n" +
+ "\n" +
+ "}");
+
+ importProject("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>");
+
+ myFixture.configureFromExistingVirtualFile(f);
+
+ IntentionAction intentionAction = findAddMavenIntention();
+
+ MavenArtifactSearchDialog.ourResultForTest = Collections.singletonList(new MavenId("commons-io", "commons-io", "2.4"));
+
+ intentionAction.invoke(myProject, myFixture.getEditor(), myFixture.getFile());
+
+ String pomText = PsiManager.getInstance(myProject).findFile(myProjectPom).getText();
+ assert pomText.matches(
+ "(?s).*<dependency>\\s*<groupId>commons-io</groupId>\\s*<artifactId>commons-io</artifactId>\\s*<version>2.4</version>\\s*<scope>test</scope>\\s*</dependency>.*");
+ }
+
+// public void testAddDependencyStatic() throws IOException {
+// VirtualFile f = createProjectSubFile("src/main/java/A.java", "import org.apache.commons.io.IOUtils;\n" +
+// "\n" +
+// "public class Aaa {\n" +
+// "\n" +
+// " public void xxx() {\n" +
+// " IOUtil<caret>s.closeQuietly(null);\n" +
+// " }\n" +
+// "\n" +
+// "}");
+//
+// importProject("<groupId>test</groupId>" +
+// "<artifactId>project</artifactId>" +
+// "<version>1</version>");
+//
+// myFixture.configureFromExistingVirtualFile(f);
+//
+// getIntentionAtCaret("Add Maven");
+// }
+
+}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/MavenCompilingTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/MavenCompilingTestCase.java
new file mode 100644
index 0000000..3f3d4b2
--- /dev/null
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/MavenCompilingTestCase.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.maven.compiler;
+
+import com.intellij.compiler.CompilerManagerImpl;
+import com.intellij.compiler.CompilerWorkspaceConfiguration;
+import com.intellij.compiler.artifacts.ArtifactsTestUtil;
+import com.intellij.compiler.impl.ModuleCompileScope;
+import com.intellij.compiler.impl.TranslatingCompilerFilesMonitor;
+import com.intellij.openapi.compiler.CompileContext;
+import com.intellij.openapi.compiler.CompileScope;
+import com.intellij.openapi.compiler.CompileStatusNotification;
+import com.intellij.openapi.compiler.CompilerManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.packaging.artifacts.Artifact;
+import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
+import com.intellij.util.concurrency.Semaphore;
+import com.intellij.util.io.TestFileSystemBuilder;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.project.MavenProjectsManager;
+import org.jetbrains.idea.maven.project.MavenResourceCompilerConfigurationGenerator;
+
+import javax.swing.*;
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author nik
+ */
+public abstract class MavenCompilingTestCase extends MavenImportingTestCase {
+ protected void compileModules(final String... moduleNames) {
+ compile(createModulesCompileScope(moduleNames));
+ }
+
+ protected void buildArtifacts(String... artifactNames) {
+ compile(createArtifactsScope(artifactNames));
+ }
+
+ private void compile(final CompileScope scope) {
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ for (Module module : scope.getAffectedModules()) {
+ setupJdkForModule(module.getName());
+ }
+ if (useJps()) {
+ new MavenResourceCompilerConfigurationGenerator(myProject, MavenProjectsManager.getInstance(myProject).getProjectsTreeForTests())
+ .generateBuildConfiguration(false);
+ }
+ }
+ });
+
+ CompilerWorkspaceConfiguration.getInstance(myProject).CLEAR_OUTPUT_DIRECTORY = true;
+ CompilerManagerImpl.testSetup();
+
+ List<VirtualFile> roots = Arrays.asList(ProjectRootManager.getInstance(myProject).getContentRoots());
+ TranslatingCompilerFilesMonitor.getInstance()
+ .scanSourceContent(new TranslatingCompilerFilesMonitor.ProjectRef(myProject), roots, roots.size(), true);
+
+
+ final Semaphore semaphore = new Semaphore();
+ semaphore.down();
+ UIUtil.invokeAndWaitIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ CompilerManager.getInstance(myProject).make(scope, new CompileStatusNotification() {
+ @Override
+ public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
+ //assertFalse(aborted);
+ //assertEquals(collectMessages(compileContext, CompilerMessageCategory.ERROR), 0, errors);
+ //assertEquals(collectMessages(compileContext, CompilerMessageCategory.WARNING), 0, warnings);
+ semaphore.up();
+ }
+ });
+ }
+ });
+ while (!semaphore.waitFor(100)) {
+ if (SwingUtilities.isEventDispatchThread()) {
+ UIUtil.dispatchAllInvocationEvents();
+ }
+ }
+ if (SwingUtilities.isEventDispatchThread()) {
+ UIUtil.dispatchAllInvocationEvents();
+ }
+ }
+
+ private CompileScope createArtifactsScope(String[] artifactNames) {
+ List<Artifact> artifacts = new ArrayList<Artifact>();
+ for (String name : artifactNames) {
+ artifacts.add(ArtifactsTestUtil.findArtifact(myProject, name));
+ }
+ return ArtifactCompileScope.createArtifactsScope(myProject, artifacts);
+ }
+
+ private CompileScope createModulesCompileScope(final String[] moduleNames) {
+ final List<Module> modules = new ArrayList<Module>();
+ for (String name : moduleNames) {
+ modules.add(getModule(name));
+ }
+ return new ModuleCompileScope(myProject, modules.toArray(new Module[modules.size()]), false);
+ }
+
+ protected static void assertResult(VirtualFile pomFile, String relativePath, String content) throws IOException {
+ assertEquals(content, loadResult(pomFile, relativePath));
+ }
+
+ protected static String loadResult(VirtualFile pomFile, String relativePath) throws IOException {
+ File file = new File(pomFile.getParent().getPath(), relativePath);
+ assertTrue("file not found: " + relativePath, file.exists());
+ return new String(FileUtil.loadFileText(file));
+ }
+
+ protected void assertResult(String relativePath, String content) throws IOException {
+ assertResult(myProjectPom, relativePath, content);
+ }
+
+ protected void assertDirectory(String relativePath, TestFileSystemBuilder fileSystemBuilder) {
+ fileSystemBuilder.build().assertDirectoryEqual(new File(myProjectPom.getParent().getPath(), relativePath));
+ }
+}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java
index 7ef085a..97f7d07 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceCopyingTest.java
@@ -25,11 +25,10 @@
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PsiTestUtil;
-import org.jetbrains.idea.maven.MavenImportingTestCase;
import java.io.File;
-public class ResourceCopyingTest extends MavenImportingTestCase {
+public class ResourceCopyingTest extends MavenCompilingTestCase {
@Override
protected boolean useJps() {
return true;
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
index 80e738f..1a27f94 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/compiler/ResourceFilteringTest.java
@@ -17,16 +17,12 @@
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.FileTypes;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.idea.maven.MavenImportingTestCase;
-import java.io.File;
-import java.io.IOException;
import java.util.Arrays;
-public abstract class ResourceFilteringTest extends MavenImportingTestCase {
+public abstract class ResourceFilteringTest extends MavenCompilingTestCase {
public static class IdeaModeTest extends ResourceFilteringTest {
@Override
@@ -1002,18 +998,4 @@
assertNotNull(myProjectPom.getParent().findFileByRelativePath("target/classes/file.xyz"));
}
-
- private void assertResult(String relativePath, String content) throws IOException {
- assertResult(myProjectPom, relativePath, content);
- }
-
- private static void assertResult(VirtualFile pomFile, String relativePath, String content) throws IOException {
- assertEquals(content, loadResult(pomFile, relativePath));
- }
-
- private static String loadResult(VirtualFile pomFile, String relativePath) throws IOException {
- File file = new File(pomFile.getParent().getPath(), relativePath);
- assertTrue("file not found: " + relativePath, file.exists());
- return new String(FileUtil.loadFileText(file));
- }
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
index 506815f..f667e1e 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
@@ -20,7 +20,11 @@
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.psi.PsiReference;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
import com.intellij.psi.formatter.xml.XmlCodeStyleSettings;
@@ -32,6 +36,7 @@
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -1073,7 +1078,6 @@
"</properties>");
importProject();
-
checkHighlighting(m, true, false, true);
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java
index 17f4591..8b3d41e 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenExtensionCompletionAndResolutionTest.java
@@ -54,7 +54,7 @@
" </extensions>" +
"</build>");
- assertCompletionVariants(myProjectPom, "test", "org.apache.maven.plugins", "org.codehaus.mojo");
+ assertCompletionVariants(myProjectPom, "org.codehaus.plexus", "test", "org.apache.maven.plugins", "org.codehaus.mojo", "intellij.test");
}
public void testArtifactIdCompletion() throws Exception {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java
index 11c3fce..827f5ac 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPluginCompletionAndResolutionTest.java
@@ -43,7 +43,7 @@
"<version>1</version>");
}
- @Bombed(year = 2013, month = Calendar.APRIL, day = 25, user = "sergey.evdokimov")
+ @Bombed(year = 2014, month = Calendar.APRIL, day = 25, user = "sergey.evdokimov")
public void testGroupIdCompletion() throws Exception {
createProjectPom("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
@@ -57,7 +57,7 @@
" </plugins>" +
"</build>");
- assertCompletionVariants(myProjectPom, "test", "org.apache.maven.plugins", "org.codehaus.mojo");
+ assertCompletionVariants(myProjectPom, "org.codehaus.plexus", "intellij.test", "test", "org.apache.maven.plugins", "org.codehaus.mojo");
}
@Bombed(year = 2013, month = Calendar.APRIL, day = 25, user = "sergey.evdokimov")
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java
index 2b2aa3a..9d31be4 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenPropertyResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,7 +15,7 @@
*/
package org.jetbrains.idea.maven.dom;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.module.Module;
@@ -259,7 +259,7 @@
"<version>1</version>");
final Document doc = FileDocumentManager.getInstance().getDocument(myProjectPom);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
doc.setText(createPomXml("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcherTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcherTest.java
new file mode 100644
index 0000000..f8ce021
--- /dev/null
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/execution/MavenJUnitPatcherTest.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.idea.maven.execution;
+
+import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.idea.maven.MavenImportingTestCase;
+
+import static java.util.Arrays.asList;
+
+public class MavenJUnitPatcherTest extends MavenImportingTestCase {
+ public void testArgList() throws Exception {
+ VirtualFile m1 = createModulePom("m1", "<groupId>test</groupId>" +
+ "<artifactId>m1</artifactId>" +
+ "<version>1</version>" +
+ "<dependencies>" +
+ " <dependency>" +
+ " <groupId>test</groupId>" +
+ " <artifactId>m2</artifactId>" +
+ " <version>1</version>" +
+ " </dependency>" +
+ "</dependencies>" +
+ "<build><plugins>" +
+ " <plugin>" +
+ " <groupId>org.apache.maven.plugins</groupId>" +
+ " <artifactId>maven-surefire-plugin</artifactId>" +
+ " <version>2.16</version>" +
+ " <configuration>" +
+ " <argLine>-Xmx2048M -XX:MaxPermSize=512M \"-Dargs=can have spaces\"</argLine>" +
+ " </configuration>" +
+ " </plugin>" +
+ "</plugins></build>");
+
+ importProjects(m1);
+ Module module = getModule("m1");
+
+ MavenJUnitPatcher mavenJUnitPatcher = new MavenJUnitPatcher();
+ JavaParameters javaParameters = new JavaParameters();
+ mavenJUnitPatcher.patchJavaParameters(module, javaParameters);
+ assertEquals(asList("-Xmx2048M", "-XX:MaxPermSize=512M", "-Dargs=can have spaces"),
+ javaParameters.getVMParametersList().getList());
+ }
+}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/GroovyImporterTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/GroovyImporterTest.java
index 53941f9..a846132 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/GroovyImporterTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/GroovyImporterTest.java
@@ -101,6 +101,36 @@
assertTestResources("project", "src/test/resources");
}
+ public void testAddingGroovySpecificSources2() throws Exception {
+ createStdProjectFolders();
+ createProjectSubDirs("src/main/groovy",
+ "src/test/groovy");
+
+ importProject("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>" +
+
+ "<build>" +
+ " <plugins>" +
+ " <plugin>" +
+ " <groupId>org.codehaus.gmaven</groupId>" +
+ " <artifactId>groovy-maven-plugin</artifactId>" +
+ " </plugin>" +
+ " </plugins>" +
+ "</build>");
+
+ assertModules("project");
+
+ assertSources("project",
+ "src/main/java",
+ "src/main/groovy");
+ assertResources("project", "src/main/resources");
+ assertTestSources("project",
+ "src/test/java",
+ "src/test/groovy");
+ assertTestResources("project", "src/test/resources");
+ }
+
public void testAddingCustomGroovySpecificSources() throws Exception {
createStdProjectFolders();
createProjectSubDirs("src/main/groovy",
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java
index bb842ba..0d99e39 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/MiscImportingTest.java
@@ -16,6 +16,7 @@
package org.jetbrains.idea.maven.importing;
import com.intellij.ProjectTopics;
+import com.intellij.idea.Bombed;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
@@ -24,9 +25,12 @@
import org.jetbrains.idea.maven.MavenCustomRepositoryHelper;
import org.jetbrains.idea.maven.MavenImportingTestCase;
import org.jetbrains.idea.maven.model.MavenProjectProblem;
+import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.server.MavenServerManager;
+import org.jetbrains.idea.maven.server.MavenServerManagerHelper;
import java.io.File;
+import java.util.Calendar;
import java.util.List;
public class MiscImportingTest extends MavenImportingTestCase {
@@ -262,14 +266,74 @@
"</build>");
List<MavenProjectProblem> problems = myProjectsTree.getRootProjects().get(0).getProblems();
- assertEquals(1, problems.size());
- assertTrue(problems.get(0).getDescription(), problems.get(0).getDescription().contains("Unresolved plugin"));
+ assertTrue(problems.size() > 0);
+
+ for (MavenProjectProblem problem : problems) {
+ assertTrue(problem.getDescription(), problem.getDescription().contains("Unresolved plugin"));
+ }
resolvePlugins();
assertEquals(0, myProjectsTree.getRootProjects().get(0).getProblems().size());
}
+ @Bombed(year = 2014, month = Calendar.JUNE, day = 25, user = "sergey.evdokimov")
+ public void testMavenExtensionsAreLoadedAndAfterProjectsReadIsCalled() throws Exception {
+ MavenCustomRepositoryHelper helper = new MavenCustomRepositoryHelper(myDir, "plugins");
+ setRepositoryPath(helper.getTestDataPath("plugins"));
+ getMavenGeneralSettings().setWorkOffline(true);
+ MavenServerManagerHelper.connectToMaven3Server();
+
+ importProjectWithMaven3("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>" +
+ "" +
+ "<build>" +
+ " <extensions>" +
+ " <extension>" +
+ " <groupId>intellij.test</groupId>" +
+ " <artifactId>maven-extension</artifactId>" +
+ " <version>1.0</version>" +
+ " </extension>" +
+ " </extensions>" +
+ "</build>");
+
+ List<MavenProject> projects = myProjectsTree.getProjects();
+ assertEquals(1, projects.size());
+ MavenProject mavenProject = projects.get(0);
+ assertEquals("Name for test:project generated by MyMavenExtension.", mavenProject.getFinalName());
+
+ assertEquals(myProjectPom.getPath().replace('\\', '/'), mavenProject.getProperties().getProperty("workspace-info"));
+ }
+
+ @Bombed(year = 2014, month = Calendar.JUNE, day = 25, user = "sergey.evdokimov")
+ public void testExceptionsFromMavenExtensionsAreReportedAsProblems() throws Exception {
+ MavenCustomRepositoryHelper helper = new MavenCustomRepositoryHelper(myDir, "plugins");
+ setRepositoryPath(helper.getTestDataPath("plugins"));
+ getMavenGeneralSettings().setWorkOffline(true);
+
+ importProjectWithMaven3("<groupId>test</groupId>" +
+ "<artifactId>project</artifactId>" +
+ "<version>1</version>" +
+ "<description>throw!</description>" +
+ "" +
+ "<build>" +
+ " <extensions>" +
+ " <extension>" +
+ " <groupId>intellij.test</groupId>" +
+ " <artifactId>maven-extension</artifactId>" +
+ " <version>1.0</version>" +
+ " </extension>" +
+ " </extensions>" +
+ "</build>");
+
+ List<MavenProject> projects = myProjectsTree.getProjects();
+ assertEquals(1, projects.size());
+ MavenProject mavenProject = projects.get(0);
+ assertEquals(mavenProject.getProblems().toString(), 1, mavenProject.getProblems().size());
+ assertEquals("throw!", mavenProject.getProblems().get(0).getDescription());
+ }
+
public void testCheckingIfModuleIsNotDisposedBeforeCommitOnImport() throws Exception {
if (ignore()) return;
@@ -312,4 +376,14 @@
assertEquals(count, rootsChangedCount);
assertEquals(rootsChangedCount, beforeRootsChangedCount);
}
+
+ private void importProjectWithMaven3(String xml) throws Exception {
+ MavenServerManagerHelper.connectToMaven3Server();
+ try {
+ importProject(xml);
+ }
+ finally {
+ MavenServerManagerHelper.disconnectFromServer();
+ }
+ }
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/WorkingWithOpenProjectTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/WorkingWithOpenProjectTest.java
index 0658320..e7ac9ca 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/WorkingWithOpenProjectTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/importing/WorkingWithOpenProjectTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,7 +15,7 @@
*/
package org.jetbrains.idea.maven.importing;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.vfs.LocalFileSystem;
@@ -61,7 +61,7 @@
myProjectsManager.listenForExternalChanges();
final Document d = FileDocumentManager.getInstance().getDocument(myProjectPom);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
d.setText(createPomXml("<groupId>test</groupId>" +
"<artifactId>project</artifactId>" +
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/groovy/MavenGroovyInjectionTest.groovy b/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/groovy/MavenGroovyInjectionTest.groovy
index 31693eb..ec4f5f5 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/groovy/MavenGroovyInjectionTest.groovy
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/plugins/groovy/MavenGroovyInjectionTest.groovy
@@ -116,6 +116,45 @@
assert lookups.containsAll(["String", "StringBuffer", "StringBuilder"])
}
+ public void testCompletion3() {
+ myFixture.configureByText("pom.xml", """
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>simpleMaven</groupId>
+ <artifactId>simpleMaven</artifactId>
+ <version>1.0</version>
+
+ <packaging>jar</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.gmaven</groupId>
+ <artifactId>groovy-maven-plugin</artifactId>
+ <version>1.3</version>
+ <configuration>
+ <!-- http://groovy.codehaus.org/The+groovydoc+Ant+task -->
+ <source>
+ String<caret>
+ </source>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
+""")
+
+ myFixture.completeBasic()
+
+ def lookups = myFixture.lookupElementStrings
+ assert lookups.containsAll(["String", "StringBuffer", "StringBuilder"])
+ }
+
public void testInjectionVariables() {
myFixture.configureByText("pom.xml", """
<?xml version="1.0" encoding="UTF-8"?>
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
index c500650..770196b 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/project/MavenProjectReaderTest.java
@@ -414,6 +414,7 @@
public void testPathsWithProperties() throws Exception {
createProjectPom("<properties>" +
" <foo>subDir</foo>" +
+ " <emptyProperty />" +
"</properties>" +
"<build>" +
" <sourceDirectory>${foo}/mySrc</sourceDirectory>" +
@@ -423,6 +424,9 @@
" <resource>" +
" <directory>${foo}/myRes</directory>" +
" </resource>" +
+ " <resource>" +
+ " <directory>aaa/${emptyProperty}/${unexistingProperty}</directory>" +
+ " </resource>" +
" </resources>" +
" <testResources>" +
" <testResource>" +
@@ -440,9 +444,11 @@
PlatformTestUtil.assertPathsEqual(pathFromBasedir("subDir/mySrc"), p.getBuild().getSources().get(0));
assertSize(1, p.getBuild().getTestSources());
PlatformTestUtil.assertPathsEqual(pathFromBasedir("subDir/myTestSrc"), p.getBuild().getTestSources().get(0));
- assertEquals(1, p.getBuild().getResources().size());
+ assertEquals(2, p.getBuild().getResources().size());
assertResource(p.getBuild().getResources().get(0), pathFromBasedir("subDir/myRes"),
false, null, Collections.<String>emptyList(), Collections.<String>emptyList());
+ assertResource(p.getBuild().getResources().get(1), pathFromBasedir("aaa/${unexistingProperty}"),
+ false, null, Collections.<String>emptyList(), Collections.<String>emptyList());
assertEquals(1, p.getBuild().getTestResources().size());
assertResource(p.getBuild().getTestResources().get(0), pathFromBasedir("subDir/myTestRes"),
false, null, Collections.<String>emptyList(), Collections.<String>emptyList());
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/server/MavenServerManagerHelper.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/server/MavenServerManagerHelper.java
new file mode 100644
index 0000000..07478ea
--- /dev/null
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/server/MavenServerManagerHelper.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.maven.server;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.impl.ApplicationImpl;
+
+import java.rmi.RemoteException;
+
+public class MavenServerManagerHelper {
+ /** {@link MavenServerManager#collectClassPathAndLibsFolder()} forces maven2 in test mode; we want maven3. */
+ public static MavenServer connectToMaven3Server() throws RemoteException {
+ ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
+ MavenServerManager msm = MavenServerManager.getInstance(); // do this first, it won't work outside of unit test mode
+
+ msm.cleanup(); // in case we were previously connected to maven2
+
+ boolean oldUnitTestMode = application.isUnitTestMode();
+ application.setUnitTestMode(false);
+ try {
+ return msm.getOrCreateWrappee();
+ }
+ finally {
+ application.setUnitTestMode(oldUnitTestMode);
+ }
+ }
+
+ public static void disconnectFromServer() {
+ MavenServerManager msm = MavenServerManager.getInstance();
+ msm.cleanup();
+ }
+}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java
index 7a684df..f041769 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/wizards/MavenModuleBuilderTest.java
@@ -288,26 +288,6 @@
VfsUtil.loadText(myProjectRoot.findFileByRelativePath("subDir/module/pom.xml")));
}
- public void testFindingPotentialParentInNotMavenizedProject() throws Exception {
- if (!hasMavenInstallation()) return;
-
- Module module = createModule("project");
- final VirtualFile dir = module.getModuleFile().getParent();
- new WriteCommandAction.Simple(myProject) {
- @Override
- protected void run() throws Throwable {
- dir.createChildData(this, "pom.xml");
- }
- }.execute().throwException();
-
-
- setModuleNameAndRoot("module", dir.getPath() + "/module");
-
- // should not throw
- MavenProject project = myBuilder.findPotentialParentProject(myProject);
- assertNull(project);
- }
-
private void setModuleNameAndRoot(String name, String root) {
myBuilder.setName(name);
myBuilder.setModuleFilePath(root + "/" + name + ".iml");
diff --git a/plugins/properties/properties-psi-api/properties-psi-api.iml b/plugins/properties/properties-psi-api/properties-psi-api.iml
new file mode 100644
index 0000000..d62c145
--- /dev/null
+++ b/plugins/properties/properties-psi-api/properties-psi-api.iml
@@ -0,0 +1,16 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="core-api" />
+ <orderEntry type="module" module-name="editor-ui-api" />
+ <orderEntry type="module" module-name="analysis-api" />
+ </component>
+</module>
+
diff --git a/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
new file mode 100644
index 0000000..0864d1e
--- /dev/null
+++ b/plugins/properties/properties-psi-api/resources/messages/PropertiesBundle.properties
@@ -0,0 +1,43 @@
+duplicate.property.key.error.message=Duplicate property key
+rename.prefix.based.property.key.error.message=Could not rename property key ''{1}'' based on prefix ''{0}'' by name ''{2}'', change prefix first
+properties.files.file.type.description=Properties files
+remove.property.intention.text=Remove property
+rename.bundle.enter.new.resource.bundle.base.name.prompt.text=Enter new resource bundle base name
+rename.bundle.enter.new.resource.bundle.key.name.prompt.text=Enter new resource bundle key name
+rename.resource.bundle.dialog.title=Rename Resource Bundle
+rename.resource.bundle.key.dialog.title=Rename Resource Bundle Key
+properties.files.inspection.group.display.name=Properties Files
+unused.property.inspection.display.name=Unused Property
+searching.for.property.key.progress.text=Searching for {0}
+unused.property.problem.descriptor.name=Unused property
+remove.property.quick.fix.name=Remove Property
+no.property.selected.panel.label=<html><body><center><b>Please select property name on the left to edit its values</body></html>
+properties.structure.view.group.by.label=Group by:
+select.property.separator.dialog.text=Select separator
+select.property.separator.dialog.title=Property Keys Separator
+select.separator.action.with.empty.separator.name=other...
+resourcebundle.fake.file.type.description=ResourceBundle fake file type
+property.key.expected.parsing.error.message=property key expected
+project.view.resource.bundle.tree.node.text=Resource Bundle ''{0}''
+structure.view.group.by.prefixes.action.name=Group by Prefixes
+structure.view.group.by.prefixes.action.description=Groups properties by common key prefixes
+unused.message.format.parameter.display.name=Missing message format parameter
+#{0},{1} used and unused parameter numbers
+unused.message.format.parameter.problem.descriptor=Using parameter {0} without using parameter {1} in <code>#ref<code> #loc
+unresolved.property.key=Cannot resolve property key
+unused.property.suppress.for.property=Suppress for this property
+unused.property.suppress.for.file=Suppress for whole file
+# suppress inspection "UnusedProperty"
+action.I18nize.text=Internationali_ze...
+# suppress inspection "UnusedProperty"
+action.I18nize.description=Replace Java string literal or JSP text with internationalized expression
+create.property.quickfix.text=Create Property
+unescape=Unescape
+trail.spaces.property.inspection.display.name=Trailing Spaces in Property
+
+options.properties.attribute.descriptor.property.key=Property key
+options.properties.attribute.descriptor.property.value=Property value
+options.properties.attribute.descriptor.key.value.separator=Key/value separator
+options.properties.attribute.descriptor.comment=Comment
+options.properties.attribute.descriptor.valid.string.escape=Valid string escape
+options.properties.attribute.descriptor.invalid.string.escape=Invalid string escape
\ No newline at end of file
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesBundle.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesBundle.java
new file mode 100644
index 0000000..290f5a4
--- /dev/null
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesBundle.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.lang.properties;
+
+import com.intellij.CommonBundle;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.PropertyKey;
+
+import java.lang.ref.Reference;
+import java.lang.ref.SoftReference;
+import java.util.ResourceBundle;
+
+public class PropertiesBundle {
+
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
+ @NonNls protected static final String PATH_TO_BUNDLE = "messages.PropertiesBundle";
+
+ private PropertiesBundle() {
+ }
+
+ private static ResourceBundle getBundle() {
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
+ if (bundle == null) {
+ bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
+ ourBundle = new SoftReference<ResourceBundle>(bundle);
+ }
+ return bundle;
+ }
+}
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
new file mode 100644
index 0000000..6d9d3ee
--- /dev/null
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesFileType.java
@@ -0,0 +1,74 @@
+/*
+ * 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.lang.properties;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.fileTypes.LanguageFileType;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.encoding.EncodingRegistry;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.nio.charset.Charset;
+
+/**
+ * @author max
+ */
+public class PropertiesFileType extends LanguageFileType {
+ public static final LanguageFileType INSTANCE = new PropertiesFileType();
+ @NonNls public static final String DEFAULT_EXTENSION = "properties";
+ @NonNls public static final String DOT_DEFAULT_EXTENSION = "."+DEFAULT_EXTENSION;
+
+ private PropertiesFileType() {
+ super(PropertiesLanguage.INSTANCE);
+ }
+
+ @Override
+ @NotNull
+ public String getName() {
+ return "Properties";
+ }
+
+ @Override
+ @NotNull
+ public String getDescription() {
+ return PropertiesBundle.message("properties.files.file.type.description");
+ }
+
+ @Override
+ @NotNull
+ public String getDefaultExtension() {
+ return DEFAULT_EXTENSION;
+ }
+
+ @Override
+ public Icon getIcon() {
+ return AllIcons.FileTypes.Properties;
+ }
+
+ @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();
+ }
+ final Charset charset = CharsetToolkit.getDefaultSystemCharset();
+ return charset != null ? charset.toString() : null;
+ }
+}
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java
new file mode 100644
index 0000000..cb198d6
--- /dev/null
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlighter.java
@@ -0,0 +1,101 @@
+/*
+ * 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.lang.properties;
+
+import com.intellij.lang.annotation.HighlightSeverity;
+import com.intellij.lang.properties.parsing.PropertiesTokenTypes;
+import com.intellij.lexer.Lexer;
+import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
+import com.intellij.openapi.editor.colors.TextAttributesKey;
+import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.StringEscapesTokenTypes;
+import com.intellij.psi.tree.IElementType;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Map;
+
+/**
+ * @author max
+ */
+public class PropertiesHighlighter extends SyntaxHighlighterBase {
+ private static final Map<IElementType, TextAttributesKey> keys1;
+ private static final Map<IElementType, TextAttributesKey> keys2;
+
+ @NotNull
+ public Lexer getHighlightingLexer() {
+ return new PropertiesHighlightingLexer();
+ }
+
+ public static final TextAttributesKey PROPERTY_KEY = TextAttributesKey.createTextAttributesKey(
+ "PROPERTIES.KEY",
+ DefaultLanguageHighlighterColors.KEYWORD
+ );
+
+ public static final TextAttributesKey PROPERTY_VALUE = TextAttributesKey.createTextAttributesKey(
+ "PROPERTIES.VALUE",
+ DefaultLanguageHighlighterColors.STRING
+ );
+
+ public static final TextAttributesKey PROPERTY_COMMENT = TextAttributesKey.createTextAttributesKey(
+ "PROPERTIES.LINE_COMMENT",
+ DefaultLanguageHighlighterColors.LINE_COMMENT
+ );
+
+ public static final TextAttributesKey PROPERTY_KEY_VALUE_SEPARATOR = TextAttributesKey.createTextAttributesKey(
+ "PROPERTIES.KEY_VALUE_SEPARATOR",
+ DefaultLanguageHighlighterColors.OPERATION_SIGN
+ );
+ public static final TextAttributesKey PROPERTIES_VALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey(
+ "PROPERTIES.VALID_STRING_ESCAPE",
+ DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE
+ );
+ public static final TextAttributesKey PROPERTIES_INVALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey(
+ "PROPERTIES.INVALID_STRING_ESCAPE",
+ DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE
+ );
+
+ static {
+ keys1 = new THashMap<IElementType, TextAttributesKey>();
+ keys2 = new THashMap<IElementType, TextAttributesKey>();
+
+ keys1.put(PropertiesTokenTypes.VALUE_CHARACTERS, PROPERTY_VALUE);
+ keys1.put(PropertiesTokenTypes.END_OF_LINE_COMMENT, PROPERTY_COMMENT);
+ keys1.put(PropertiesTokenTypes.KEY_CHARACTERS, PROPERTY_KEY);
+ keys1.put(PropertiesTokenTypes.KEY_VALUE_SEPARATOR, PROPERTY_KEY_VALUE_SEPARATOR);
+
+ keys1.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, PROPERTIES_VALID_STRING_ESCAPE);
+ // in fact all back-slashed escapes are allowed
+ keys1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, PROPERTIES_INVALID_STRING_ESCAPE);
+ keys1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, PROPERTIES_INVALID_STRING_ESCAPE);
+ }
+
+ @NotNull
+ public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
+ return SyntaxHighlighterBase.pack(keys1.get(tokenType), keys2.get(tokenType));
+ }
+
+ public static final Map<TextAttributesKey, Pair<String, HighlightSeverity>> DISPLAY_NAMES = new THashMap<TextAttributesKey, Pair<String, HighlightSeverity>>(6);
+ static {
+ DISPLAY_NAMES.put(PROPERTY_KEY, new Pair<String, HighlightSeverity>(PropertiesBundle.message("options.properties.attribute.descriptor.property.key"),null));
+ DISPLAY_NAMES.put(PROPERTY_VALUE, new Pair<String, HighlightSeverity>(PropertiesBundle.message("options.properties.attribute.descriptor.property.value"), null));
+ DISPLAY_NAMES.put(PROPERTY_KEY_VALUE_SEPARATOR, new Pair<String, HighlightSeverity>(PropertiesBundle.message("options.properties.attribute.descriptor.key.value.separator"), null));
+ DISPLAY_NAMES.put(PROPERTY_COMMENT, new Pair<String, HighlightSeverity>(PropertiesBundle.message("options.properties.attribute.descriptor.comment"), null));
+ DISPLAY_NAMES.put(PROPERTIES_VALID_STRING_ESCAPE, new Pair<String, HighlightSeverity>(PropertiesBundle.message("options.properties.attribute.descriptor.valid.string.escape"), null));
+ DISPLAY_NAMES.put(PROPERTIES_INVALID_STRING_ESCAPE, new Pair<String, HighlightSeverity>(PropertiesBundle.message("options.properties.attribute.descriptor.invalid.string.escape"), HighlightSeverity.WARNING));
+ }
+}
diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesHighlightingLexer.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlightingLexer.java
similarity index 100%
rename from plugins/properties/src/com/intellij/lang/properties/PropertiesHighlightingLexer.java
rename to plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesHighlightingLexer.java
diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesLanguage.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesLanguage.java
similarity index 100%
rename from plugins/properties/src/com/intellij/lang/properties/PropertiesLanguage.java
rename to plugins/properties/properties-psi-api/src/com/intellij/lang/properties/PropertiesLanguage.java
diff --git a/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesElementType.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesElementType.java
new file mode 100644
index 0000000..32e8d4a
--- /dev/null
+++ b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesElementType.java
@@ -0,0 +1,34 @@
+/*
+ * 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.lang.properties.parsing;
+
+import com.intellij.lang.properties.PropertiesLanguage;
+import com.intellij.psi.tree.IElementType;
+import org.jetbrains.annotations.NonNls;
+
+/**
+ * @author max
+ */
+public class PropertiesElementType extends IElementType {
+ public PropertiesElementType(@NonNls String debugName) {
+ super(debugName, PropertiesLanguage.INSTANCE);
+ }
+
+ @SuppressWarnings({"HardCodedStringLiteral"})
+ public String toString() {
+ return "Properties:" + super.toString();
+ }
+}
diff --git a/plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesLexer.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesLexer.java
similarity index 100%
rename from plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesLexer.java
rename to plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesLexer.java
diff --git a/plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesTokenTypes.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesTokenTypes.java
similarity index 100%
rename from plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesTokenTypes.java
rename to plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/PropertiesTokenTypes.java
diff --git a/plugins/properties/src/com/intellij/lang/properties/parsing/_PropertiesLexer.java b/plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/_PropertiesLexer.java
similarity index 100%
rename from plugins/properties/src/com/intellij/lang/properties/parsing/_PropertiesLexer.java
rename to plugins/properties/properties-psi-api/src/com/intellij/lang/properties/parsing/_PropertiesLexer.java
diff --git a/plugins/properties/properties-psi-impl/properties-psi-impl.iml b/plugins/properties/properties-psi-impl/properties-psi-impl.iml
new file mode 100644
index 0000000..7878d54
--- /dev/null
+++ b/plugins/properties/properties-psi-impl/properties-psi-impl.iml
@@ -0,0 +1,16 @@
+<?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$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="properties-psi-api" />
+ <orderEntry type="module" module-name="core-impl" />
+ <orderEntry type="module" module-name="editor-ui-api" />
+ <orderEntry type="module" module-name="analysis-api" />
+ </component>
+</module>
+
diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java b/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java
new file mode 100644
index 0000000..6fd3902
--- /dev/null
+++ b/plugins/properties/properties-psi-impl/src/com/intellij/properties/PropertiesCoreEnvironment.java
@@ -0,0 +1,21 @@
+package com.intellij.properties;
+
+import com.intellij.core.CoreApplicationEnvironment;
+import com.intellij.core.CoreProjectEnvironment;
+import com.intellij.lang.properties.PropertiesFileType;
+
+/**
+ * @author Anna Bulenkova
+ */
+public class PropertiesCoreEnvironment {
+ public static class ApplicationEnvironment {
+ public ApplicationEnvironment(CoreApplicationEnvironment appEnvironment) {
+ appEnvironment.registerFileType(PropertiesFileType.INSTANCE, "properties");
+ }
+ }
+
+ public static class ProjectEnvironment {
+ public ProjectEnvironment(CoreProjectEnvironment projectEnvironment) {
+ }
+ }
+}
diff --git a/plugins/properties/properties.iml b/plugins/properties/properties.iml
index 3aa5283..ae5c42e 100644
--- a/plugins/properties/properties.iml
+++ b/plugins/properties/properties.iml
@@ -19,6 +19,8 @@
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="resources" scope="TEST" />
<orderEntry type="module" module-name="xml" />
+ <orderEntry type="module" module-name="properties-psi-api" />
+ <orderEntry type="module" module-name="properties-psi-impl" />
</component>
</module>
diff --git a/plugins/properties/resources/messages/PropertiesBundle.properties b/plugins/properties/resources/messages/PropertiesBundle.properties
deleted file mode 100644
index 237deda..0000000
--- a/plugins/properties/resources/messages/PropertiesBundle.properties
+++ /dev/null
@@ -1,36 +0,0 @@
-duplicate.property.key.error.message=Duplicate property key
-rename.prefix.based.property.key.error.message=Could not rename property key ''{1}'' based on prefix ''{0}'' by name ''{2}'', change prefix first
-properties.files.file.type.description=Properties files
-remove.property.intention.text=Remove property
-rename.bundle.enter.new.resource.bundle.base.name.prompt.text=Enter new resource bundle base name
-rename.bundle.enter.new.resource.bundle.key.name.prompt.text=Enter new resource bundle key name
-rename.resource.bundle.dialog.title=Rename Resource Bundle
-rename.resource.bundle.key.dialog.title=Rename Resource Bundle Key
-properties.files.inspection.group.display.name=Properties Files
-unused.property.inspection.display.name=Unused Property
-searching.for.property.key.progress.text=Searching for {0}
-unused.property.problem.descriptor.name=Unused property
-remove.property.quick.fix.name=Remove Property
-no.property.selected.panel.label=<html><body><center><b>Please select property name on the left to edit its values</body></html>
-properties.structure.view.group.by.label=Group by:
-select.property.separator.dialog.text=Select separator
-select.property.separator.dialog.title=Property Keys Separator
-select.separator.action.with.empty.separator.name=other...
-resourcebundle.fake.file.type.description=ResourceBundle fake file type
-property.key.expected.parsing.error.message=property key expected
-project.view.resource.bundle.tree.node.text=Resource Bundle ''{0}''
-structure.view.group.by.prefixes.action.name=Group by Prefixes
-structure.view.group.by.prefixes.action.description=Groups properties by common key prefixes
-unused.message.format.parameter.display.name=Missing message format parameter
-#{0},{1} used and unused parameter numbers
-unused.message.format.parameter.problem.descriptor=Using parameter {0} without using parameter {1} in <code>#ref<code> #loc
-unresolved.property.key=Cannot resolve property key
-unused.property.suppress.for.property=Suppress for this property
-unused.property.suppress.for.file=Suppress for whole file
-# suppress inspection "UnusedProperty"
-action.I18nize.text=Internationali_ze...
-# suppress inspection "UnusedProperty"
-action.I18nize.description=Replace Java string literal or JSP text with internationalized expression
-create.property.quickfix.text=Create Property
-unescape=Unescape
-trail.spaces.property.inspection.display.name=Trailing Spaces in Property
\ No newline at end of file
diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesBundle.java b/plugins/properties/src/com/intellij/lang/properties/PropertiesBundle.java
deleted file mode 100644
index 56e69d4..0000000
--- a/plugins/properties/src/com/intellij/lang/properties/PropertiesBundle.java
+++ /dev/null
@@ -1,47 +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.lang.properties;
-
-import com.intellij.CommonBundle;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.PropertyKey;
-
-import java.lang.ref.Reference;
-import java.lang.ref.SoftReference;
-import java.util.ResourceBundle;
-
-public class PropertiesBundle {
- private static Reference<ResourceBundle> ourBundle;
-
- @NonNls protected static final String PATH_TO_BUNDLE = "messages.PropertiesBundle";
-
- private PropertiesBundle() {
- }
-
- public static String message(@PropertyKey(resourceBundle = PATH_TO_BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
- private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
- if (bundle == null) {
- bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
- ourBundle = new SoftReference<ResourceBundle>(bundle);
- }
- return bundle;
- }
-}
diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesFileType.java b/plugins/properties/src/com/intellij/lang/properties/PropertiesFileType.java
deleted file mode 100644
index f1bc0f7..0000000
--- a/plugins/properties/src/com/intellij/lang/properties/PropertiesFileType.java
+++ /dev/null
@@ -1,69 +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.lang.properties;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.fileTypes.LanguageFileType;
-import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.encoding.EncodingManager;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.nio.charset.Charset;
-
-/**
- * @author max
- */
-public class PropertiesFileType extends LanguageFileType {
- public static final LanguageFileType INSTANCE = new PropertiesFileType();
- @NonNls public static final String DEFAULT_EXTENSION = "properties";
- @NonNls public static final String DOT_DEFAULT_EXTENSION = "."+DEFAULT_EXTENSION;
-
- private PropertiesFileType() {
- super(PropertiesLanguage.INSTANCE);
- }
-
- @Override
- @NotNull
- public String getName() {
- return "Properties";
- }
-
- @Override
- @NotNull
- public String getDescription() {
- return PropertiesBundle.message("properties.files.file.type.description");
- }
-
- @Override
- @NotNull
- public String getDefaultExtension() {
- return DEFAULT_EXTENSION;
- }
-
- @Override
- public Icon getIcon() {
- return AllIcons.FileTypes.Properties;
- }
-
- @Override
- public String getCharset(@NotNull VirtualFile file, final byte[] content) {
- Charset charset = EncodingManager.getInstance().getDefaultCharsetForPropertiesFiles(file);
- return charset == null ? CharsetToolkit.getDefaultSystemCharset().name() : charset.name();
- }
-}
diff --git a/plugins/properties/src/com/intellij/lang/properties/PropertiesHighlighter.java b/plugins/properties/src/com/intellij/lang/properties/PropertiesHighlighter.java
deleted file mode 100644
index 2d5f6a3..0000000
--- a/plugins/properties/src/com/intellij/lang/properties/PropertiesHighlighter.java
+++ /dev/null
@@ -1,102 +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.lang.properties;
-
-import com.intellij.lang.annotation.HighlightSeverity;
-import com.intellij.lang.properties.parsing.PropertiesTokenTypes;
-import com.intellij.lexer.Lexer;
-import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
-import com.intellij.openapi.editor.colors.TextAttributesKey;
-import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
-import com.intellij.openapi.options.OptionsBundle;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.StringEscapesTokenTypes;
-import com.intellij.psi.tree.IElementType;
-import gnu.trove.THashMap;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.Map;
-
-/**
- * @author max
- */
-public class PropertiesHighlighter extends SyntaxHighlighterBase {
- private static final Map<IElementType, TextAttributesKey> keys1;
- private static final Map<IElementType, TextAttributesKey> keys2;
-
- @NotNull
- public Lexer getHighlightingLexer() {
- return new PropertiesHighlightingLexer();
- }
-
- public static final TextAttributesKey PROPERTY_KEY = TextAttributesKey.createTextAttributesKey(
- "PROPERTIES.KEY",
- DefaultLanguageHighlighterColors.KEYWORD
- );
-
- public static final TextAttributesKey PROPERTY_VALUE = TextAttributesKey.createTextAttributesKey(
- "PROPERTIES.VALUE",
- DefaultLanguageHighlighterColors.STRING
- );
-
- public static final TextAttributesKey PROPERTY_COMMENT = TextAttributesKey.createTextAttributesKey(
- "PROPERTIES.LINE_COMMENT",
- DefaultLanguageHighlighterColors.LINE_COMMENT
- );
-
- public static final TextAttributesKey PROPERTY_KEY_VALUE_SEPARATOR = TextAttributesKey.createTextAttributesKey(
- "PROPERTIES.KEY_VALUE_SEPARATOR",
- DefaultLanguageHighlighterColors.OPERATION_SIGN
- );
- public static final TextAttributesKey PROPERTIES_VALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey(
- "PROPERTIES.VALID_STRING_ESCAPE",
- DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE
- );
- public static final TextAttributesKey PROPERTIES_INVALID_STRING_ESCAPE = TextAttributesKey.createTextAttributesKey(
- "PROPERTIES.INVALID_STRING_ESCAPE",
- DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE
- );
-
- static {
- keys1 = new THashMap<IElementType, TextAttributesKey>();
- keys2 = new THashMap<IElementType, TextAttributesKey>();
-
- keys1.put(PropertiesTokenTypes.VALUE_CHARACTERS, PROPERTY_VALUE);
- keys1.put(PropertiesTokenTypes.END_OF_LINE_COMMENT, PROPERTY_COMMENT);
- keys1.put(PropertiesTokenTypes.KEY_CHARACTERS, PROPERTY_KEY);
- keys1.put(PropertiesTokenTypes.KEY_VALUE_SEPARATOR, PROPERTY_KEY_VALUE_SEPARATOR);
-
- keys1.put(StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN, PROPERTIES_VALID_STRING_ESCAPE);
- // in fact all back-slashed escapes are allowed
- keys1.put(StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN, PROPERTIES_INVALID_STRING_ESCAPE);
- keys1.put(StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN, PROPERTIES_INVALID_STRING_ESCAPE);
- }
-
- @NotNull
- public TextAttributesKey[] getTokenHighlights(IElementType tokenType) {
- return pack(keys1.get(tokenType), keys2.get(tokenType));
- }
-
- public static final Map<TextAttributesKey, Pair<String, HighlightSeverity>> DISPLAY_NAMES = new THashMap<TextAttributesKey, Pair<String, HighlightSeverity>>(6);
- static {
- DISPLAY_NAMES.put(PROPERTY_KEY, new Pair<String, HighlightSeverity>(OptionsBundle.message("options.properties.attribute.descriptor.property.key"),null));
- DISPLAY_NAMES.put(PROPERTY_VALUE, new Pair<String, HighlightSeverity>(OptionsBundle.message("options.properties.attribute.descriptor.property.value"), null));
- DISPLAY_NAMES.put(PROPERTY_KEY_VALUE_SEPARATOR, new Pair<String, HighlightSeverity>(OptionsBundle.message("options.properties.attribute.descriptor.key.value.separator"), null));
- DISPLAY_NAMES.put(PROPERTY_COMMENT, new Pair<String, HighlightSeverity>(OptionsBundle.message("options.properties.attribute.descriptor.comment"), null));
- DISPLAY_NAMES.put(PROPERTIES_VALID_STRING_ESCAPE, new Pair<String, HighlightSeverity>(OptionsBundle.message("options.properties.attribute.descriptor.valid.string.escape"), null));
- DISPLAY_NAMES.put(PROPERTIES_INVALID_STRING_ESCAPE, new Pair<String, HighlightSeverity>(OptionsBundle.message("options.properties.attribute.descriptor.invalid.string.escape"), HighlightSeverity.WARNING));
- }
-}
diff --git a/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java b/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java
index 70713d4..5f708c3 100644
--- a/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.java
+++ b/plugins/properties/src/com/intellij/lang/properties/ResourceBundleReference.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,27 +15,37 @@
*/
package com.intellij.lang.properties;
+import com.intellij.codeInsight.completion.PrioritizedLookupElement;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.icons.AllIcons;
import com.intellij.lang.properties.psi.PropertiesFile;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.util.Function;
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;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
/**
* @author yole
*/
public class ResourceBundleReference extends PsiReferenceBase<PsiElement> implements PsiPolyVariantReference, BundleNameEvaluator {
- private static final Function<PropertiesFile,PsiElement> PROPERTIES_FILE_PSI_ELEMENT_FUNCTION = new Function<PropertiesFile, PsiElement>() {
- @Override
- public PsiElement fun(PropertiesFile propertiesFile) {
- return propertiesFile.getContainingFile();
- }
- };
- private String myBundleName;
+ private static final Function<PropertiesFile, PsiElement> PROPERTIES_FILE_PSI_ELEMENT_FUNCTION =
+ new Function<PropertiesFile, PsiElement>() {
+ @Override
+ public PsiElement fun(PropertiesFile propertiesFile) {
+ return propertiesFile.getContainingFile();
+ }
+ };
+ private final String myBundleName;
public ResourceBundleReference(final PsiElement element) {
this(element, false);
@@ -43,15 +53,17 @@
public ResourceBundleReference(final PsiElement element, boolean soft) {
super(element, soft);
- myBundleName = getValue();
+ myBundleName = StringUtil.replaceChar(getValue(), '/', '.');
}
- @Nullable public PsiElement resolve() {
+ @Nullable
+ public PsiElement resolve() {
ResolveResult[] resolveResults = multiResolve(false);
return resolveResults.length == 1 ? resolveResults[0].getElement() : null;
}
- @NotNull public ResolveResult[] multiResolve(final boolean incompleteCode) {
+ @NotNull
+ public ResolveResult[] multiResolve(final boolean incompleteCode) {
PropertiesReferenceManager referenceManager = PropertiesReferenceManager.getInstance(myElement.getProject());
List<PropertiesFile> propertiesFiles = referenceManager.findPropertiesFiles(myElement.getResolveScope(), myBundleName, this);
return PsiElementResolveResult.createResults(ContainerUtil.map(propertiesFiles, PROPERTIES_FILE_PSI_ELEMENT_FUNCTION));
@@ -67,14 +79,20 @@
newElementName = newElementName.substring(0, newElementName.lastIndexOf(PropertiesFileType.DOT_DEFAULT_EXTENSION));
}
- final int index = myBundleName.lastIndexOf('.');
+ final String currentValue = getValue();
+ final char packageDelimiter = getPackageDelimiter();
+ final int index = currentValue.lastIndexOf(packageDelimiter);
if (index != -1) {
- newElementName = myBundleName.substring(0, index) + "." + newElementName;
+ newElementName = currentValue.substring(0, index) + packageDelimiter + newElementName;
}
return super.handleElementRename(newElementName);
}
+ private char getPackageDelimiter() {
+ return StringUtil.indexOf(getValue(), '/') != -1 ? '/' : '.';
+ }
+
public PsiElement bindToElement(@NotNull final PsiElement element) throws IncorrectOperationException {
if (!(element instanceof PropertiesFile)) {
throw new IncorrectOperationException();
@@ -96,8 +114,27 @@
@NotNull
public Object[] getVariants() {
- PropertiesReferenceManager referenceManager = PropertiesReferenceManager.getInstance(getElement().getProject());
- return referenceManager.getPropertyFileBaseNames(myElement.getResolveScope(), this);
+ final ProjectFileIndex projectFileIndex = ProjectFileIndex.SERVICE.getInstance(getElement().getProject());
+ final PropertiesReferenceManager referenceManager = PropertiesReferenceManager.getInstance(getElement().getProject());
+
+ final Set<String> bundleNames = new HashSet<String>();
+ final List<LookupElement> variants = new SmartList<LookupElement>();
+ PropertiesFileProcessor processor = new PropertiesFileProcessor() {
+ @Override
+ public boolean process(String baseName, PropertiesFile propertiesFile) {
+ if (!bundleNames.add(baseName)) return true;
+
+ final LookupElementBuilder builder =
+ LookupElementBuilder.create(baseName)
+ .withIcon(AllIcons.Nodes.ResourceBundle);
+ boolean isInContent = projectFileIndex.isInContent(propertiesFile.getVirtualFile());
+ variants.add(isInContent ? PrioritizedLookupElement.withPriority(builder, Double.MAX_VALUE) : builder);
+ return true;
+ }
+ };
+
+ referenceManager.processPropertiesFiles(myElement.getResolveScope(), processor, this);
+ return variants.toArray(new LookupElement[variants.size()]);
}
public String evaluateBundleName(final PsiFile psiFile) {
diff --git a/plugins/properties/src/com/intellij/lang/properties/findUsages/PropertiesFindUsagesProvider.java b/plugins/properties/src/com/intellij/lang/properties/findUsages/PropertiesFindUsagesProvider.java
index 50211cd..99e7338 100644
--- a/plugins/properties/src/com/intellij/lang/properties/findUsages/PropertiesFindUsagesProvider.java
+++ b/plugins/properties/src/com/intellij/lang/properties/findUsages/PropertiesFindUsagesProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.lang.LangBundle;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
-import com.intellij.find.impl.HelpID;
import org.jetbrains.annotations.NotNull;
/**
@@ -34,7 +33,7 @@
}
public String getHelpId(@NotNull PsiElement psiElement) {
- return HelpID.FIND_OTHER_USAGES;
+ return com.intellij.lang.HelpID.FIND_OTHER_USAGES;
}
@NotNull
diff --git a/plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesElementType.java b/plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesElementType.java
deleted file mode 100644
index 48c930e..0000000
--- a/plugins/properties/src/com/intellij/lang/properties/parsing/PropertiesElementType.java
+++ /dev/null
@@ -1,34 +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.lang.properties.parsing;
-
-import com.intellij.psi.tree.IElementType;
-import com.intellij.openapi.fileTypes.StdFileTypes;
-import org.jetbrains.annotations.NonNls;
-
-/**
- * @author max
- */
-public class PropertiesElementType extends IElementType {
- public PropertiesElementType(@NonNls String debugName) {
- super(debugName, StdFileTypes.PROPERTIES.getLanguage());
- }
-
- @SuppressWarnings({"HardCodedStringLiteral"})
- public String toString() {
- return "Properties:" + super.toString();
- }
-}
diff --git a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java
index 9a3cd7f..3394011 100644
--- a/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java
+++ b/plugins/properties/src/com/intellij/lang/properties/projectView/ResourceBundleGrouper.java
@@ -22,8 +22,10 @@
import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiFile;
import com.intellij.util.SmartList;
import gnu.trove.THashMap;
@@ -40,49 +42,54 @@
myProject = project;
}
- public Collection<AbstractTreeNode> modify(AbstractTreeNode parent, Collection<AbstractTreeNode> children, ViewSettings settings) {
+ public Collection<AbstractTreeNode> modify(AbstractTreeNode parent, final Collection<AbstractTreeNode> children, final ViewSettings settings) {
if (parent instanceof ResourceBundleNode) return children;
- Map<ResourceBundle,Collection<PropertiesFile>> childBundles = new THashMap<ResourceBundle, Collection<PropertiesFile>>();
- for (AbstractTreeNode child : children) {
- Object f = child.getValue();
- if (f instanceof PsiFile) {
- PropertiesFile propertiesFile = PropertiesUtil.getPropertiesFile((PsiFile)f);
- if (propertiesFile != null) {
- ResourceBundle bundle = propertiesFile.getResourceBundle();
- Collection<PropertiesFile> files = childBundles.get(bundle);
- if (files == null) {
- files = new SmartList<PropertiesFile>();
- childBundles.put(bundle, files);
- }
- files.add(propertiesFile);
- }
- }
- }
-
- List<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
- for (Map.Entry<ResourceBundle, Collection<PropertiesFile>> entry : childBundles.entrySet()) {
- ResourceBundle resourceBundle = entry.getKey();
- Collection<PropertiesFile> files = entry.getValue();
- if (files.size() != 1) {
- result.add(new ResourceBundleNode(myProject, resourceBundle, settings));
- }
- }
- for (AbstractTreeNode child : children) {
- Object f = child.getValue();
- if (f instanceof PsiFile) {
- PropertiesFile propertiesFile = PropertiesUtil.getPropertiesFile((PsiFile)f);
- if (propertiesFile != null) {
- ResourceBundle bundle = propertiesFile.getResourceBundle();
- if (childBundles.get(bundle).size() != 1) {
- continue;
+ return ApplicationManager.getApplication().runReadAction(new Computable<Collection<AbstractTreeNode>>() {
+ @Override
+ public Collection<AbstractTreeNode> compute() {
+ Map<ResourceBundle,Collection<PropertiesFile>> childBundles = new THashMap<ResourceBundle, Collection<PropertiesFile>>();
+ for (AbstractTreeNode child : children) {
+ Object f = child.getValue();
+ if (f instanceof PsiFile) {
+ PropertiesFile propertiesFile = PropertiesUtil.getPropertiesFile((PsiFile)f);
+ if (propertiesFile != null) {
+ ResourceBundle bundle = propertiesFile.getResourceBundle();
+ Collection<PropertiesFile> files = childBundles.get(bundle);
+ if (files == null) {
+ files = new SmartList<PropertiesFile>();
+ childBundles.put(bundle, files);
+ }
+ files.add(propertiesFile);
+ }
}
}
- }
- result.add(child);
- }
- return result;
+ List<AbstractTreeNode> result = new ArrayList<AbstractTreeNode>();
+ for (Map.Entry<ResourceBundle, Collection<PropertiesFile>> entry : childBundles.entrySet()) {
+ ResourceBundle resourceBundle = entry.getKey();
+ Collection<PropertiesFile> files = entry.getValue();
+ if (files.size() != 1) {
+ result.add(new ResourceBundleNode(myProject, resourceBundle, settings));
+ }
+ }
+ for (AbstractTreeNode child : children) {
+ Object f = child.getValue();
+ if (f instanceof PsiFile) {
+ PropertiesFile propertiesFile = PropertiesUtil.getPropertiesFile((PsiFile)f);
+ if (propertiesFile != null) {
+ ResourceBundle bundle = propertiesFile.getResourceBundle();
+ if (childBundles.get(bundle).size() != 1) {
+ continue;
+ }
+ }
+ }
+ result.add(child);
+ }
+
+ return result;
+ }
+ });
}
public Object getData(Collection<AbstractTreeNode> selected, String dataName) {
diff --git a/plugins/properties/src/com/intellij/lang/properties/psi/impl/PropertyImplEscaper.java b/plugins/properties/src/com/intellij/lang/properties/psi/impl/PropertyImplEscaper.java
index cd482af..aba503f 100644
--- a/plugins/properties/src/com/intellij/lang/properties/psi/impl/PropertyImplEscaper.java
+++ b/plugins/properties/src/com/intellij/lang/properties/psi/impl/PropertyImplEscaper.java
@@ -1,6 +1,6 @@
package com.intellij.lang.properties.psi.impl;
-import com.intellij.openapi.util.ProperTextRange;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.LiteralTextEscaper;
import org.jetbrains.annotations.NotNull;
@@ -9,6 +9,8 @@
* @author gregsh
*/
public class PropertyImplEscaper extends LiteralTextEscaper<PropertyImpl> {
+ private static final Logger LOG = Logger.getInstance(PropertyImplEscaper.class);
+
private int[] outSourceOffsets;
public PropertyImplEscaper(PropertyImpl value) {
@@ -17,16 +19,18 @@
@Override
public boolean decode(@NotNull TextRange rangeInsideHost, @NotNull StringBuilder outChars) {
- ProperTextRange.assertProperRange(rangeInsideHost);
+ TextRange.assertProperRange(rangeInsideHost);
String subText = rangeInsideHost.substring(myHost.getText());
outSourceOffsets = new int[subText.length() + 1];
+ int prefixLen = outChars.length();
boolean b = PropertyImpl.parseCharacters(subText, outChars, outSourceOffsets);
if (b) {
- for (int i=0; i<outChars.length(); i++) {
- if (outChars.charAt(i) != subText.charAt(outSourceOffsets[i])) {
- if (subText.charAt(outSourceOffsets[i]) != '\\') {
- throw new IllegalStateException();
- }
+ for (int i = prefixLen, len = outChars.length(); i < len; i++) {
+ char outChar = outChars.charAt(i);
+ char inChar = subText.charAt(outSourceOffsets[i - prefixLen]);
+ if (outChar != inChar && inChar != '\\') {
+ LOG.error("input: " + subText + ";\noutput: " + outChars +
+ "\nat: " + i + "; prefix-length: " + prefixLen);
}
}
}
diff --git a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java
index 89af66a..159dd58 100644
--- a/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java
+++ b/plugins/properties/testSrc/com/intellij/lang/properties/PropertiesFileTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -19,6 +19,7 @@
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.lang.properties.psi.Property;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.testFramework.LightPlatformTestCase;
import com.intellij.testFramework.PlatformTestCase;
import com.intellij.util.IncorrectOperationException;
@@ -63,7 +64,7 @@
public void testAddPropertyAfterProperty() throws Exception {
final PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "xxx=yyy");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
propertiesFile.addProperty(myPropertyToAdd);
}
@@ -83,7 +84,7 @@
assertPropertyEquals(properties.get(0), "xxx", "yyy");
assertPropertyEquals(properties.get(1), "zzz", "ttt");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
properties.get(1).getPsiElement().delete();
}
@@ -98,9 +99,8 @@
PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "xxx=yyy\nxxx2=tyrt\nxxx3=ttt\n\n");
final Property property = (Property)propertiesFile.findPropertyByKey("xxx2");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
- property.delete();
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
+ property.delete();
}
});
@@ -111,8 +111,7 @@
PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "xxx=yyy\nxxx2=tyrt\nxxx3=ttt\n\n");
final Property property = (Property)propertiesFile.findPropertyByKey("xxx");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
property.delete();
}
});
@@ -124,8 +123,7 @@
public void testAddToEnd() throws IncorrectOperationException {
final PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "a=b\\nccc");
assertEquals(1,propertiesFile.getProperties().size());
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
propertiesFile.addProperty(myPropertyToAdd);
}
});
@@ -146,8 +144,7 @@
public void testAddPropertyAfter() throws IncorrectOperationException {
final PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "a=b\nc=d\ne=f");
final Property c = (Property)propertiesFile.findPropertyByKey("c");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
propertiesFile.addPropertyAfter(myPropertyToAdd, c);
}
});
@@ -157,8 +154,7 @@
public void testAddPropertyAfterLast() throws IncorrectOperationException {
final PropertiesFile propertiesFile = PropertiesElementFactory.createPropertiesFile(getProject(), "a=b\nc=d\ne=f");
final Property p = (Property)propertiesFile.findPropertyByKey("e");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
propertiesFile.addPropertyAfter(myPropertyToAdd, p);
}
});
diff --git a/plugins/svn4idea/src/META-INF/plugin.xml b/plugins/svn4idea/src/META-INF/plugin.xml
index e1a1a0b..e831d05 100644
--- a/plugins/svn4idea/src/META-INF/plugin.xml
+++ b/plugins/svn4idea/src/META-INF/plugin.xml
@@ -72,7 +72,7 @@
<reference id="Compare.SameVersion" text="Compare with BASE revision"/>
<reference id="Compare.LastVersion" text="Compare with revision at HEAD"/>
<reference id="Compare.Selected"/>
- <action id="Subversion.CompareWithBranch" class="org.jetbrains.idea.svn.actions.CompareWithBranchAction"/>
+ <action id="Subversion.CompareWithBranch" class="org.jetbrains.idea.svn.diff.CompareWithBranchAction"/>
<reference id="Vcs.ShowTabbedFileHistory"/>
<reference id="Vcs.ShowHistoryForBlock"/>
<reference id="Annotate"/>
@@ -139,5 +139,7 @@
<vcs name="svn" vcsClass="org.jetbrains.idea.svn.SvnVcs" displayName="Subversion" administrativeAreaName=".svn, _svn" crawlUpToCheckUnderVcs="true"/>
<vcsPopupProvider implementation="org.jetbrains.idea.svn.actions.SvnQuickListContentProvider"/>
+
+ <statistics.usagesCollector implementation="org.jetbrains.idea.svn.statistics.SvnWorkingCopyFormatUsagesCollector"/>
</extensions>
</idea-plugin>
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java
deleted file mode 100644
index b46b7a8..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/AuthManagerType.java
+++ /dev/null
@@ -1,26 +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.idea.svn;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 2/28/13
- * Time: 10:14 AM
- */
-public enum AuthManagerType {
- active, passive, usual;
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/CheckJavaHL.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/CheckJavaHL.java
deleted file mode 100644
index 7729902..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/CheckJavaHL.java
+++ /dev/null
@@ -1,94 +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.idea.svn;
-
-import com.intellij.notification.Notification;
-import com.intellij.notification.NotificationType;
-import com.intellij.notification.Notifications;
-import com.intellij.openapi.project.Project;
-import org.apache.subversion.javahl.types.Version;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/24/12
- * Time: 2:20 PM
- */
-public class CheckJavaHL {
- public static final String VERSION_CLASS = "org.apache.subversion.javahl.types.Version";
- public static final String CHECK_JAVAHL_VERSION = "svn.check.javahl.version";
- private static boolean ourIsPresent;
- private static String ourProblemDescription;
-
- static {
- try {
- ClassLoader loader = CheckJavaHL.class.getClassLoader();
- if (loader == null) {
- loader = ClassLoader.getSystemClassLoader();
- }
- ourProblemDescription = "No JavaHL library found.";
- if (loader != null) {
- Class<?> aClass = loader.loadClass(VERSION_CLASS);
- if (aClass != null) {
- if (checkVersion(aClass)) {
- ourIsPresent = true;
- }
- }
- }
- } catch (ClassNotFoundException e) {
- ourIsPresent = false;
- }
- }
-
- private static boolean checkVersion(Class<?> aClass) {
- try {
- Version v = (Version)aClass.newInstance();
- boolean atLeast = true;
- Boolean check = Boolean.getBoolean(CHECK_JAVAHL_VERSION);
- if (Boolean.TRUE.equals(check)) {
- atLeast = v.isAtLeast(1, 7, 0);
- if (! atLeast) {
- ourProblemDescription = "JavaHL library version is old: " + v.toString();
- }
- }
- return atLeast;
- }
- catch (InstantiationException e) {
- return false;
- }
- catch (IllegalAccessException e) {
- return false;
- } catch (Throwable e) {
- return false;
- }
- }
-
- public static boolean isPresent() {
- return ourIsPresent;
- }
-
- public static String getProblemDescription() {
- return ourProblemDescription;
- }
-
- public static void runtimeCheck(final Project project) {
- if (! ourIsPresent) {
- Notifications.Bus.notify(new Notification(SvnVcs.getInstance(project).getDisplayName(), "Subversion: JavaHL problem",
- ourProblemDescription + " Acceleration is not available.",
- NotificationType.ERROR), project);
- }
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java
index f5c27c2..0c0e36f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/IdeaSVNConfigFile.java
@@ -15,16 +15,24 @@
*/
package org.jetbrains.idea.svn;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.config.DefaultProxyGroup;
import org.jetbrains.idea.svn.config.ProxyGroup;
import org.tmatesoft.svn.core.internal.wc.SVNConfigFile;
import java.io.File;
+import java.net.InetSocketAddress;
+import java.net.PasswordAuthentication;
+import java.net.Proxy;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class IdeaSVNConfigFile {
+
+ public final static String SERVERS_FILE_NAME = "servers";
+
private final Map<String, String> myPatternsMap;
private final long myLatestUpdate;
private final File myFile;
@@ -41,6 +49,59 @@
myPatternsMap = new HashMap<String, String>();
}
+ public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) {
+ final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME));
+ configFile.updateGroups();
+
+ String groupName = ensureHostGroup(host, configFile);
+
+ final HashMap<String, String> map = new HashMap<String, String>();
+ final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address());
+ map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName());
+ map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort()));
+ configFile.addGroup(groupName, host + "*", map);
+ configFile.save();
+ }
+
+ @NotNull
+ public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) {
+ String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
+
+ if (StringUtil.isEmptyOrSpaces(groupName)) {
+ groupName = getNewGroupName(host, configFile);
+ }
+
+ return groupName;
+ }
+
+ @NotNull
+ public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) {
+ String groupName = host;
+ final Map<String,ProxyGroup> groups = configFile.getAllGroups();
+ while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) {
+ groupName += "1";
+ }
+ return groupName;
+ }
+
+ public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host,
+ @NotNull final PasswordAuthentication authentication) {
+ final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME));
+ configFile.updateGroups();
+
+ String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
+ // no proxy defined in group -> no sense in password
+ if (StringUtil.isEmptyOrSpaces(groupName)) return false;
+ final Map<String, String> properties = configFile.getAllGroups().get(groupName).getProperties();
+ if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false;
+ if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false;
+
+ configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName());
+ configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword()));
+ configFile.save();
+ return true;
+ }
+
public void updateGroups() {
if (myLatestUpdate != myFile.lastModified()) {
myPatternsMap.clear();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java
index c3932d9..0597ea1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -32,6 +32,7 @@
import com.intellij.openapi.vcs.changes.committed.AbstractCalledLater;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.util.EventDispatcher;
+import com.intellij.util.SystemProperties;
import com.intellij.util.messages.Topic;
import com.intellij.util.net.HttpConfigurable;
import com.intellij.util.proxy.CommonProxy;
@@ -119,6 +120,40 @@
});
}
+ public String getDefaultUsername(String kind, SVNURL url) {
+ String result = SystemProperties.getUserName();
+
+ // USERNAME authentication is also requested in SVNSSHConnector.open()
+ if (ISVNAuthenticationManager.SSH.equals(kind) ||
+ (ISVNAuthenticationManager.USERNAME.equals(kind) && SVN_SSH.equals(url.getProtocol()))) {
+ result = url != null && !StringUtil.isEmpty(url.getUserInfo()) ? url.getUserInfo() : getDefaultOptions().getDefaultSSHUserName();
+ }
+
+ return result;
+ }
+
+ @Override
+ protected SVNSSHAuthentication getDefaultSSHAuthentication(SVNURL url) {
+ String userName = getDefaultUsername(ISVNAuthenticationManager.SSH, url);
+
+ // This is fully copied from base class - DefaultSVNAuthenticationManager - as there are no setters in Authentication classes
+ // and there is no url parameter if overriding getDefaultOptions()
+ String password = getDefaultOptions().getDefaultSSHPassword();
+ String keyFile = getDefaultOptions().getDefaultSSHKeyFile();
+ int port = getDefaultOptions().getDefaultSSHPortNumber();
+ String passphrase = getDefaultOptions().getDefaultSSHPassphrase();
+
+ if (userName != null && password != null) {
+ return new SVNSSHAuthentication(userName, password, port, getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(), url,
+ false);
+ }
+ else if (userName != null && keyFile != null) {
+ return new SVNSSHAuthentication(userName, new File(keyFile), passphrase, port,
+ getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled(), url, false);
+ }
+ return null;
+ }
+
private class AuthenticationProviderProxy implements ISVNAuthenticationProvider {
private final ISVNAuthenticationProvider myDelegate;
@@ -674,7 +709,7 @@
return DEFAULT_READ_TIMEOUT;
}
if (SVN_SSH.equals(protocol)) {
- return (int) getConfig().mySSHReadTimeout;
+ return (int)getConfig().getSshReadTimeout();
}
return 0;
}
@@ -683,7 +718,7 @@
public int getConnectTimeout(SVNRepository repository) {
String protocol = repository.getLocation().getProtocol();
if (SVN_SSH.equals(protocol)) {
- return (int) getConfig().mySSHConnectionTimeout;
+ return (int)getConfig().getSshConnectionTimeout();
}
final int connectTimeout = super.getConnectTimeout(repository);
if ((HTTP.equals(protocol) || HTTPS.equals(protocol)) && (connectTimeout <= 0)) {
@@ -789,7 +824,7 @@
@CalledInAwt
private boolean askToStoreUnencrypted(String title, String message) {
final int answer = Messages.showYesNoDialog(myProject, message, title, Messages.getQuestionIcon());
- return answer == 0;
+ return answer == Messages.YES;
}
public void setInteraction(SvnAuthenticationInteraction interaction) {
@@ -823,7 +858,7 @@
final int answer = Messages.showYesNoDialog(myProject, String.format("Your password for authentication realm:\n" +
"%s\ncan only be stored to disk unencrypted. Would you like to store it in plaintext?", realm),
"Store the password in plaintext?", Messages.getQuestionIcon());
- return answer == 0;
+ return answer == Messages.YES;
}
@Override
@@ -837,7 +872,7 @@
String.format("Your passphrase for " + certificateName + ":\n%s\ncan only be stored to disk unencrypted. Would you like to store it in plaintext?",
certificateFile.getPath()),
"Store the passphrase in plaintext?", Messages.getQuestionIcon());
- return answer == 0;
+ return answer == Messages.YES;
}
@Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java
index 4efcce6..5b84aa2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnAuthenticationNotifier.java
@@ -16,17 +16,21 @@
package org.jetbrains.idea.svn;
import com.intellij.notification.NotificationType;
+import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.application.ex.ApplicationEx;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.MessageType;
+import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.Balloon;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.NamedRunnable;
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.impl.GenericNotifierImpl;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
@@ -45,12 +49,15 @@
import org.tmatesoft.svn.core.SVNCancelException;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import org.tmatesoft.svn.core.wc.SVNRevision;
import javax.swing.*;
import java.awt.*;
+import java.io.File;
+import java.io.FilenameFilter;
import java.net.*;
import java.util.*;
import java.util.List;
@@ -59,6 +66,9 @@
public class SvnAuthenticationNotifier extends GenericNotifierImpl<SvnAuthenticationNotifier.AuthenticationRequest, SVNURL> {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnAuthenticationNotifier");
+ private static final List<String> ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH,
+ ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server");
+
private final SvnVcs myVcs;
private final RootsToWorkingCopies myRootsToWorkingCopies;
private final Map<SVNURL, Boolean> myCopiesPassiveResults;
@@ -414,7 +424,7 @@
SvnBundle.message("confirmation.title.clear.authentication.cache")) {
@Override
public void run() {
- SvnConfigurable.clearAuthenticationCache(project, null, configuration
+ clearAuthenticationCache(project, null, configuration
.getConfigurationDirectory());
}
},
@@ -436,4 +446,58 @@
}
}, ModalityState.NON_MODAL, project.getDisposed());
}
+
+ public static void clearAuthenticationCache(@NotNull final Project project, final Component component, final String configDirPath) {
+ if (configDirPath != null) {
+ int result;
+ if (component == null) {
+ result = Messages.showYesNoDialog(project, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
+ SvnBundle.message("confirmation.title.clear.authentication.cache"),
+ Messages.getWarningIcon());
+ } else {
+ result = Messages.showYesNoDialog(component, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
+ SvnBundle.message("confirmation.title.clear.authentication.cache"),
+ Messages.getWarningIcon());
+ }
+ if (result == Messages.YES) {
+ SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
+ clearAuthenticationDirectory(SvnConfiguration.getInstance(project));
+ }
+ }
+ }
+
+ public static void clearAuthenticationDirectory(@NotNull SvnConfiguration configuration) {
+ final File authDir = new File(configuration.getConfigurationDirectory(), "auth");
+ if (authDir.exists()) {
+ final Runnable process = new Runnable() {
+ public void run() {
+ final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator();
+ if (ind != null) {
+ ind.setIndeterminate(true);
+ ind.setText("Clearing stored credentials in " + authDir.getAbsolutePath());
+ }
+ final File[] files = authDir.listFiles(new FilenameFilter() {
+ public boolean accept(File dir, String name) {
+ return ourAuthKinds.contains(name);
+ }
+ });
+
+ for (File dir : files) {
+ if (ind != null) {
+ ind.setText("Deleting " + dir.getAbsolutePath());
+ }
+ FileUtil.delete(dir);
+ }
+ }
+ };
+ final Application application = ApplicationManager.getApplication();
+ if (application.isUnitTestMode() || !application.isDispatchThread()) {
+ process.run();
+ }
+ else {
+ ProgressManager.getInstance()
+ .runProcessWithProgressSynchronously(process, "button.text.clear.authentication.cache", false, configuration.getProject());
+ }
+ }
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java
index 201a10f..65e9028 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBranchConfigurationManager.java
@@ -295,7 +295,7 @@
return result;
}
- private String serializeUrl(final String url, final Ref<Boolean> withUserInfo) {
+ private static String serializeUrl(final String url, final Ref<Boolean> withUserInfo) {
if (Boolean.FALSE.equals(withUserInfo.get())) {
return url;
}
@@ -306,7 +306,8 @@
withUserInfo.set((userInfo != null) && (userInfo.length() > 0));
}
if (withUserInfo.get()) {
- return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), svnurl.getPort(), svnurl.getURIEncodedPath(), true).toString();
+ return SVNURL.create(svnurl.getProtocol(), null, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(), true)
+ .toString();
}
}
catch (SVNException e) {
@@ -321,10 +322,11 @@
return svnurl != null ? svnurl.getUserInfo() : null;
}
- private String deserializeUrl(final String url, final String userInfo) {
+ private static String deserializeUrl(final String url, final String userInfo) {
try {
final SVNURL svnurl = SVNURL.parseURIEncoded(url);
- return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), svnurl.getPort(), svnurl.getURIEncodedPath(), true).toString();
+ return SVNURL.create(svnurl.getProtocol(), userInfo, svnurl.getHost(), SvnUtil.resolvePort(svnurl), svnurl.getURIEncodedPath(),
+ true).toString();
} catch (SVNException e) {
return url;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.java
index d74e638..c3edbd5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -24,24 +25,23 @@
import java.util.ResourceBundle;
public class SvnBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "org.jetbrains.idea.svn.SvnBundle";
private SvnBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
- public static String getString(@PropertyKey(resourceBundle = BUNDLE)String key) {
+ public static String getString(@PropertyKey(resourceBundle = BUNDLE) String key) {
return getBundle().getString(key);
}
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java
index ac23963..71709f7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -25,7 +25,6 @@
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfo;
@@ -102,7 +101,7 @@
myClearAuthButton.addActionListener(new ActionListener(){
public void actionPerformed(final ActionEvent e) {
- clearAuthenticationCache(myProject, myComponent, myConfigurationDirectoryText.getText());
+ SvnAuthenticationNotifier.clearAuthenticationCache(myProject, myComponent, myConfigurationDirectoryText.getText());
}
});
@@ -180,25 +179,6 @@
dirConsumer.consume(resultPath);
}
- public static void clearAuthenticationCache(@NotNull final Project project, final Component component, final String configDirPath) {
- if (configDirPath != null) {
- int result;
- if (component == null) {
- result = Messages.showYesNoDialog(project, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
- SvnBundle.message("confirmation.title.clear.authentication.cache"),
- Messages.getWarningIcon());
- } else {
- result = Messages.showYesNoDialog(component, SvnBundle.message("confirmation.text.delete.stored.authentication.information"),
- SvnBundle.message("confirmation.title.clear.authentication.cache"),
- Messages.getWarningIcon());
- }
- if (result == 0) {
- SvnConfiguration.RUNTIME_AUTH_CACHE.clear();
- SvnConfiguration.getInstance(project).clearAuthenticationDirectory(project);
- }
- }
- }
-
private static FileChooserDescriptor createFileDescriptor() {
final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
descriptor.setShowFileSystemRoots(true);
@@ -239,19 +219,19 @@
if (configuration.isIsUseDefaultProxy() != myUseCommonProxy.isSelected()) {
return true;
}
- if (configuration.UPDATE_LOCK_ON_DEMAND != myLockOnDemand.isSelected()) {
+ if (configuration.isUpdateLockOnDemand() != myLockOnDemand.isSelected()) {
return true;
}
- if (configuration.CHECK_NESTED_FOR_QUICK_MERGE != myCheckNestedInQuickMerge.isSelected()) {
+ if (configuration.isCheckNestedForQuickMerge() != myCheckNestedInQuickMerge.isSelected()) {
return true;
}
- if (configuration.IGNORE_SPACES_IN_ANNOTATE != myIgnoreWhitespaceDifferenciesInCheckBox.isSelected()) {
+ if (configuration.isIgnoreSpacesInAnnotate() != myIgnoreWhitespaceDifferenciesInCheckBox.isSelected()) {
return true;
}
- if (configuration.SHOW_MERGE_SOURCES_IN_ANNOTATE != myShowMergeSourceInAnnotate.isSelected()) {
+ if (configuration.isShowMergeSourcesInAnnotate() != myShowMergeSourceInAnnotate.isSelected()) {
return true;
}
- if (! configuration.myUseAcceleration.equals(acceleration())) return true;
+ if (! configuration.getUseAcceleration().equals(acceleration())) return true;
final int annotateRevisions = configuration.getMaxAnnotateRevisions();
final boolean useMaxInAnnot = annotateRevisions != -1;
if (useMaxInAnnot != myMaximumNumberOfRevisionsCheckBox.isSelected()) {
@@ -262,16 +242,16 @@
return true;
}
}
- if (configuration.mySSHConnectionTimeout/1000 != ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue()) {
+ if (configuration.getSshConnectionTimeout() /1000 != ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue()) {
return true;
}
- if (configuration.mySSHReadTimeout/1000 != ((SpinnerNumberModel) mySSHReadTimeout.getModel()).getNumber().longValue()) {
+ if (configuration.getSshReadTimeout() /1000 != ((SpinnerNumberModel) mySSHReadTimeout.getModel()).getNumber().longValue()) {
return true;
}
if (configuration.getHttpTimeout()/1000 != ((SpinnerNumberModel) myHttpTimeout.getModel()).getNumber().longValue()) {
return true;
}
- if (! getSelectedSSL().equals(configuration.SSL_PROTOCOLS)) return true;
+ if (! getSelectedSSL().equals(configuration.getSslProtocols())) return true;
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
if (! Comparing.equal(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim())) return true;
return !configuration.getConfigurationDirectory().equals(myConfigurationDirectoryText.getText().trim());
@@ -288,23 +268,23 @@
configuration.setIsUseDefaultProxy(myUseCommonProxy.isSelected());
final SvnVcs vcs17 = SvnVcs.getInstance(myProject);
- configuration.CHECK_NESTED_FOR_QUICK_MERGE = myCheckNestedInQuickMerge.isSelected();
- configuration.UPDATE_LOCK_ON_DEMAND = myLockOnDemand.isSelected();
+ configuration.setCheckNestedForQuickMerge(myCheckNestedInQuickMerge.isSelected());
+ configuration.setUpdateLockOnDemand(myLockOnDemand.isSelected());
configuration.setIgnoreSpacesInAnnotate(myIgnoreWhitespaceDifferenciesInCheckBox.isSelected());
- configuration.SHOW_MERGE_SOURCES_IN_ANNOTATE = myShowMergeSourceInAnnotate.isSelected();
+ configuration.setShowMergeSourcesInAnnotate(myShowMergeSourceInAnnotate.isSelected());
if (! myMaximumNumberOfRevisionsCheckBox.isSelected()) {
configuration.setMaxAnnotateRevisions(-1);
} else {
configuration.setMaxAnnotateRevisions(((SpinnerNumberModel) myNumRevsInAnnotations.getModel()).getNumber().intValue());
}
- configuration.mySSHConnectionTimeout = ((SpinnerNumberModel) mySSHConnectionTimeout.getModel()).getNumber().longValue() * 1000;
- configuration.mySSHReadTimeout = ((SpinnerNumberModel) mySSHReadTimeout.getModel()).getNumber().longValue() * 1000;
+ configuration.setSshConnectionTimeout(((SpinnerNumberModel)mySSHConnectionTimeout.getModel()).getNumber().longValue() * 1000);
+ configuration.setSshReadTimeout(((SpinnerNumberModel)mySSHReadTimeout.getModel()).getNumber().longValue() * 1000);
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
- boolean reloadWorkingCopies = !acceleration().equals(configuration.myUseAcceleration) ||
+ boolean reloadWorkingCopies = !acceleration().equals(configuration.getUseAcceleration()) ||
!StringUtil.equals(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim());
- configuration.myUseAcceleration = acceleration();
- configuration.SSL_PROTOCOLS = getSelectedSSL();
+ configuration.setUseAcceleration(acceleration());
+ configuration.setSslProtocols(getSelectedSSL());
SvnVcs.getInstance(myProject).refreshSSLProperty();
applicationSettings17.setCommandLinePath(myCommandLineClient.getText().trim());
@@ -325,15 +305,15 @@
myConfigurationDirectoryText.setText(path);
myUseDefaultCheckBox.setSelected(configuration.isUseDefaultConfiguation());
myUseCommonProxy.setSelected(configuration.isIsUseDefaultProxy());
- myCheckNestedInQuickMerge.setSelected(configuration.CHECK_NESTED_FOR_QUICK_MERGE);
+ myCheckNestedInQuickMerge.setSelected(configuration.isCheckNestedForQuickMerge());
boolean enabled = !myUseDefaultCheckBox.isSelected();
myConfigurationDirectoryText.setEnabled(enabled);
myConfigurationDirectoryText.setEditable(enabled);
myConfigurationDirectoryLabel.setEnabled(enabled);
- myLockOnDemand.setSelected(configuration.UPDATE_LOCK_ON_DEMAND);
- myIgnoreWhitespaceDifferenciesInCheckBox.setSelected(configuration.IGNORE_SPACES_IN_ANNOTATE);
- myShowMergeSourceInAnnotate.setSelected(configuration.SHOW_MERGE_SOURCES_IN_ANNOTATE);
+ myLockOnDemand.setSelected(configuration.isUpdateLockOnDemand());
+ myIgnoreWhitespaceDifferenciesInCheckBox.setSelected(configuration.isIgnoreSpacesInAnnotate());
+ myShowMergeSourceInAnnotate.setSelected(configuration.isShowMergeSourcesInAnnotate());
final int annotateRevisions = configuration.getMaxAnnotateRevisions();
if (annotateRevisions == -1) {
@@ -344,16 +324,16 @@
myNumRevsInAnnotations.setValue(annotateRevisions);
}
myNumRevsInAnnotations.setEnabled(myMaximumNumberOfRevisionsCheckBox.isSelected());
- mySSHConnectionTimeout.setValue(Long.valueOf(configuration.mySSHConnectionTimeout / 1000));
- mySSHReadTimeout.setValue(Long.valueOf(configuration.mySSHReadTimeout / 1000));
+ mySSHConnectionTimeout.setValue(Long.valueOf(configuration.getSshConnectionTimeout() / 1000));
+ mySSHReadTimeout.setValue(Long.valueOf(configuration.getSshReadTimeout() / 1000));
myHttpTimeout.setValue(Long.valueOf(configuration.getHttpTimeout() / 1000));
myWithCommandLineClient.setSelected(configuration.isCommandLine());
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
myCommandLineClient.setText(applicationSettings17.getCommandLinePath());
- if (SvnConfiguration.SSLProtocols.sslv3.equals(configuration.SSL_PROTOCOLS)) {
+ if (SvnConfiguration.SSLProtocols.sslv3.equals(configuration.getSslProtocols())) {
mySSLv3RadioButton.setSelected(true);
- } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(configuration.SSL_PROTOCOLS)) {
+ } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(configuration.getSslProtocols())) {
myTLSv1RadioButton.setSelected(true);
} else {
myAllRadioButton.setSelected(true);
@@ -381,8 +361,8 @@
myNumRevsInAnnotations = new JSpinner(new SpinnerNumberModel(value, 10, 100000, 100));
final Long maximum = 30 * 60 * 1000L;
- final long connection = configuration.mySSHConnectionTimeout <= maximum ? configuration.mySSHConnectionTimeout : maximum;
- final long read = configuration.mySSHReadTimeout <= maximum ? configuration.mySSHReadTimeout : maximum;
+ final long connection = configuration.getSshConnectionTimeout() <= maximum ? configuration.getSshConnectionTimeout() : maximum;
+ final long read = configuration.getSshReadTimeout() <= maximum ? configuration.getSshReadTimeout() : maximum;
mySSHConnectionTimeout = new JSpinner(new SpinnerNumberModel(Long.valueOf(connection / 1000), Long.valueOf(0L), maximum, Long.valueOf(10L)));
mySSHReadTimeout = new JSpinner(new SpinnerNumberModel(Long.valueOf(read / 1000), Long.valueOf(0L), maximum, Long.valueOf(10L)));
myHttpTimeout = new JSpinner(new SpinnerNumberModel(Long.valueOf(read / 1000), Long.valueOf(0L), maximum, Long.valueOf(10L)));
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
index e4eb988..5e0d86f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfiguration.java
@@ -18,23 +18,14 @@
package org.jetbrains.idea.svn;
import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.Application;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.*;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.VcsAnnotationRefresher;
import org.jdom.Attribute;
import org.jdom.DataConversionException;
import org.jdom.Element;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.config.ProxyGroup;
import org.jetbrains.idea.svn.config.SvnServerFileKeys;
import org.jetbrains.idea.svn.dialogs.SvnAuthenticationProvider;
import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider;
@@ -43,7 +34,6 @@
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationProvider;
import org.tmatesoft.svn.core.auth.SVNAuthentication;
import org.tmatesoft.svn.core.internal.wc.ISVNAuthenticationStorage;
@@ -54,10 +44,6 @@
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import java.io.File;
-import java.io.FilenameFilter;
-import java.net.InetSocketAddress;
-import java.net.PasswordAuthentication;
-import java.net.Proxy;
import java.util.*;
@State(
@@ -73,26 +59,18 @@
private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.SvnConfiguration");
public final static int ourMaxAnnotateRevisionsDefault = 500;
- private final static String SERVERS_FILE_NAME = "servers";
-
public static final String CLEANUP_ON_START_RUN = "cleanupOnStartRun";
private final Project myProject;
- public String USER = "";
- public String PASSWORD = "";
- public String[] ADD_PATHS = null;
-
private String myConfigurationDirectory;
private boolean myIsUseDefaultConfiguration;
private boolean myIsUseDefaultProxy;
private ISVNOptions myOptions;
private boolean myIsKeepLocks;
private boolean myAutoUpdateAfterCommit;
- private boolean myRemoteStatus;
private SvnAuthenticationManager myAuthManager;
private SvnAuthenticationManager myPassiveAuthManager;
private SvnAuthenticationManager myInteractiveManager;
- private String myUpgradeMode;
private SvnSupportOptions mySupportOptions;
private boolean myCleanupRun;
private int myMaxAnnotateRevisions = ourMaxAnnotateRevisionsDefault;
@@ -101,14 +79,14 @@
public long mySSHReadTimeout = DEFAULT_SSH_TIMEOUT;
public static final AuthStorage RUNTIME_AUTH_CACHE = new AuthStorage();
- public String LAST_MERGED_REVISION = null;
+ // TODO: update depth is not stored in configuration as SVNDepth has wrong type for DefaultJDOMExternalizer
+ // TODO: check if it should be stored
public SVNDepth UPDATE_DEPTH = SVNDepth.UNKNOWN;
public boolean MERGE_DRY_RUN = false;
public boolean MERGE_DIFF_USE_ANCESTRY = true;
public boolean UPDATE_LOCK_ON_DEMAND = false;
public boolean IGNORE_SPACES_IN_MERGE = false;
- //public boolean DETECT_NESTED_COPIES = true;
public boolean CHECK_NESTED_FOR_QUICK_MERGE = false;
public boolean IGNORE_SPACES_IN_ANNOTATE = true;
public boolean SHOW_MERGE_SOURCES_IN_ANNOTATE = true;
@@ -126,7 +104,7 @@
private IdeaSVNConfigFile myConfigFile;
public boolean isCommandLine() {
- return UseAcceleration.commandLine.equals(myUseAcceleration);
+ return UseAcceleration.commandLine.equals(getUseAcceleration());
}
@Override
@@ -162,12 +140,12 @@
}
public SVNDiffOptions getMergeOptions() {
- return new SVNDiffOptions(IGNORE_SPACES_IN_MERGE, IGNORE_SPACES_IN_MERGE, IGNORE_SPACES_IN_MERGE);
+ return new SVNDiffOptions(isIgnoreSpacesInMerge(), isIgnoreSpacesInMerge(), isIgnoreSpacesInMerge());
}
private void initServers() {
if (myConfigFile == null) {
- myConfigFile = new IdeaSVNConfigFile(new File(getConfigurationDirectory(), SERVERS_FILE_NAME));
+ myConfigFile = new IdeaSVNConfigFile(new File(getConfigurationDirectory(), IdeaSVNConfigFile.SERVERS_FILE_NAME));
}
myConfigFile.updateGroups();
}
@@ -180,59 +158,6 @@
myConfigFile.save();
}
- public static void putProxyIntoServersFile(final File configDir, final String host, final Proxy proxyInfo) {
- final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME));
- configFile.updateGroups();
-
- String groupName = ensureHostGroup(host, configFile);
-
- final HashMap<String, String> map = new HashMap<String, String>();
- final InetSocketAddress address = ((InetSocketAddress) proxyInfo.address());
- map.put(SvnAuthenticationManager.HTTP_PROXY_HOST, address.getHostName());
- map.put(SvnAuthenticationManager.HTTP_PROXY_PORT, String.valueOf(address.getPort()));
- configFile.addGroup(groupName, host + "*", map);
- configFile.save();
- }
-
- @NotNull
- public static String ensureHostGroup(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) {
- String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
-
- if (StringUtil.isEmptyOrSpaces(groupName)) {
- groupName = getNewGroupName(host, configFile);
- }
-
- return groupName;
- }
-
- @NotNull
- public static String getNewGroupName(@NotNull String host, @NotNull IdeaSVNConfigFile configFile) {
- String groupName = host;
- final Map<String,ProxyGroup> groups = configFile.getAllGroups();
- while (StringUtil.isEmptyOrSpaces(groupName) || groups.containsKey(groupName)) {
- groupName += "1";
- }
- return groupName;
- }
-
- public static boolean putProxyCredentialsIntoServerFile(@NotNull final File configDir, @NotNull final String host,
- @NotNull final PasswordAuthentication authentication) {
- final IdeaSVNConfigFile configFile = new IdeaSVNConfigFile(new File(configDir, SERVERS_FILE_NAME));
- configFile.updateGroups();
-
- String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
- // no proxy defined in group -> no sense in password
- if (StringUtil.isEmptyOrSpaces(groupName)) return false;
- final Map<String, String> properties = configFile.getAllGroups().get(groupName).getProperties();
- if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_HOST))) return false;
- if (StringUtil.isEmptyOrSpaces(properties.get(SvnAuthenticationManager.HTTP_PROXY_PORT))) return false;
-
- configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_USERNAME, authentication.getUserName());
- configFile.setValue(groupName, SvnAuthenticationManager.HTTP_PROXY_PASSWORD, String.valueOf(authentication.getPassword()));
- configFile.save();
- return true;
- }
-
public static SvnConfiguration getInstance(final Project project) {
return ServiceManager.getService(project, SvnConfiguration.class);
}
@@ -245,10 +170,130 @@
final boolean changed = IGNORE_SPACES_IN_ANNOTATE != value;
IGNORE_SPACES_IN_ANNOTATE = value;
if (changed) {
- myProject.getMessageBus().syncPublisher(VcsAnnotationRefresher.LOCAL_CHANGES_CHANGED).configurationChanged(SvnVcs.getKey());
+ getProject().getMessageBus().syncPublisher(VcsAnnotationRefresher.LOCAL_CHANGES_CHANGED).configurationChanged(SvnVcs.getKey());
}
}
+ public long getSshConnectionTimeout() {
+ return mySSHConnectionTimeout;
+ }
+
+ public void setSshConnectionTimeout(long sshConnectionTimeout) {
+ mySSHConnectionTimeout = sshConnectionTimeout;
+ }
+
+ public long getSshReadTimeout() {
+ return mySSHReadTimeout;
+ }
+
+ public void setSshReadTimeout(long sshReadTimeout) {
+ mySSHReadTimeout = sshReadTimeout;
+ }
+
+ public Project getProject() {
+ return myProject;
+ }
+
+ public Boolean isKeepNewFilesAsIsForTreeConflictMerge() {
+ return TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE;
+ }
+
+ public void setKeepNewFilesAsIsForTreeConflictMerge(Boolean keepNewFilesAsIsForTreeConflictMerge) {
+ this.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = keepNewFilesAsIsForTreeConflictMerge;
+ }
+
+ public SSLProtocols getSslProtocols() {
+ return SSL_PROTOCOLS;
+ }
+
+ public void setSslProtocols(SSLProtocols sslProtocols) {
+ this.SSL_PROTOCOLS = sslProtocols;
+ }
+
+ public SVNDepth getUpdateDepth() {
+ return UPDATE_DEPTH;
+ }
+
+ public void setUpdateDepth(SVNDepth updateDepth) {
+ this.UPDATE_DEPTH = updateDepth;
+ }
+
+ public UseAcceleration getUseAcceleration() {
+ return myUseAcceleration;
+ }
+
+ public void setUseAcceleration(UseAcceleration useAcceleration) {
+ myUseAcceleration = useAcceleration;
+ }
+
+ public boolean isIgnoreExternals() {
+ return IGNORE_EXTERNALS;
+ }
+
+ public void setIgnoreExternals(boolean ignoreExternals) {
+ this.IGNORE_EXTERNALS = ignoreExternals;
+ }
+
+ public boolean isMergeDryRun() {
+ return MERGE_DRY_RUN;
+ }
+
+ public void setMergeDryRun(boolean mergeDryRun) {
+ this.MERGE_DRY_RUN = mergeDryRun;
+ }
+
+ public boolean isMergeDiffUseAncestry() {
+ return MERGE_DIFF_USE_ANCESTRY;
+ }
+
+ public void setMergeDiffUseAncestry(boolean mergeDiffUseAncestry) {
+ this.MERGE_DIFF_USE_ANCESTRY = mergeDiffUseAncestry;
+ }
+
+ public boolean isUpdateLockOnDemand() {
+ return UPDATE_LOCK_ON_DEMAND;
+ }
+
+ public void setUpdateLockOnDemand(boolean updateLockOnDemand) {
+ this.UPDATE_LOCK_ON_DEMAND = updateLockOnDemand;
+ }
+
+ public boolean isIgnoreSpacesInMerge() {
+ return IGNORE_SPACES_IN_MERGE;
+ }
+
+ public void setIgnoreSpacesInMerge(boolean ignoreSpacesInMerge) {
+ this.IGNORE_SPACES_IN_MERGE = ignoreSpacesInMerge;
+ }
+
+ public boolean isCheckNestedForQuickMerge() {
+ return CHECK_NESTED_FOR_QUICK_MERGE;
+ }
+
+ public void setCheckNestedForQuickMerge(boolean checkNestedForQuickMerge) {
+ this.CHECK_NESTED_FOR_QUICK_MERGE = checkNestedForQuickMerge;
+ }
+
+ public boolean isIgnoreSpacesInAnnotate() {
+ return IGNORE_SPACES_IN_ANNOTATE;
+ }
+
+ public boolean isShowMergeSourcesInAnnotate() {
+ return SHOW_MERGE_SOURCES_IN_ANNOTATE;
+ }
+
+ public void setShowMergeSourcesInAnnotate(boolean showMergeSourcesInAnnotate) {
+ this.SHOW_MERGE_SOURCES_IN_ANNOTATE = showMergeSourcesInAnnotate;
+ }
+
+ public boolean isForceUpdate() {
+ return FORCE_UPDATE;
+ }
+
+ public void setForceUpdate(boolean forceUpdate) {
+ this.FORCE_UPDATE = forceUpdate;
+ }
+
public class SvnSupportOptions {
/**
* version of "support SVN in IDEA". for features tracking. should grow
@@ -267,10 +312,6 @@
private final static long CHANGELIST_SUPPORT = 124;
private final static long UPGRADE_TO_16_VERSION_ASKED = 125;
- public boolean upgradeTo16Asked() {
- return (myVersion != null) && (UPGRADE_TO_16_VERSION_ASKED <= myVersion);
- }
-
public boolean changeListsSynchronized() {
return (myVersion != null) && (CHANGELIST_SUPPORT <= myVersion);
}
@@ -347,34 +388,6 @@
return myOptions;
}
- public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir) {
- return createForTmpDir(project, dir, null);
- }
-
- public static SvnAuthenticationManager createForTmpDir(final Project project, final File dir,
- @Nullable final SvnInteractiveAuthenticationProvider provider) {
- final SvnVcs vcs = SvnVcs.getInstance(project);
-
- final SvnAuthenticationManager interactive = new SvnAuthenticationManager(project, dir);
- interactive.setRuntimeStorage(RUNTIME_AUTH_CACHE);
- final SvnInteractiveAuthenticationProvider interactiveProvider = provider == null ?
- new SvnInteractiveAuthenticationProvider(vcs, interactive) : provider;
- interactive.setAuthenticationProvider(interactiveProvider);
-
- return interactive;
- }
-
- public SvnAuthenticationManager getManager(final AuthManagerType type, final SvnVcs vcs) {
- if (AuthManagerType.active.equals(type)) {
- return getInteractiveManager(vcs);
- } else if (AuthManagerType.passive.equals(type)) {
- return getPassiveAuthenticationManager(vcs.getProject());
- } else if (AuthManagerType.usual.equals(type)) {
- return getAuthenticationManager(vcs);
- }
- throw new IllegalArgumentException();
- }
-
public SvnAuthenticationManager getAuthenticationManager(final SvnVcs svnVcs) {
if (myAuthManager == null) {
// reloaded when configuration directory changes
@@ -434,29 +447,14 @@
SVNConfigFile.createDefaultConfiguration(dir);
}
- systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), SERVERS_FILE_NAME))));
+ systemManager.set(new SvnServerFileManagerImpl(new IdeaSVNConfigFile(new File(SVNFileUtil.getSystemConfigurationDirectory(), IdeaSVNConfigFile.SERVERS_FILE_NAME))));
initServers();
userManager.set(new SvnServerFileManagerImpl(myConfigFile));
}
- public String getUpgradeMode() {
- return myUpgradeMode;
- }
-
- public void setUpgradeMode(String upgradeMode) {
- myUpgradeMode = upgradeMode;
- }
-
@SuppressWarnings({"HardCodedStringLiteral"})
public void readExternal(Element element) throws InvalidDataException {
DefaultJDOMExternalizer.readExternal(this, element);
- List elems = element.getChildren("addpath");
- LOG.debug(elems.toString());
- ADD_PATHS = new String[elems.size()];
- for (int i = 0; i < elems.size(); i++) {
- Element elem = (Element)elems.get(i);
- ADD_PATHS[i] = elem.getAttributeValue("path");
- }
Element configurationDirectory = element.getChild("configuration");
if (configurationDirectory != null) {
myConfigurationDirectory = configurationDirectory.getText();
@@ -471,18 +469,7 @@
else {
myIsUseDefaultConfiguration = true;
}
- // compatibility: this setting was moved from .iws to global settings
- List urls = element.getChildren("checkoutURL");
- for (Object url1 : urls) {
- Element child = (Element)url1;
- String url = child.getText();
- if (url != null) {
- SvnApplicationSettings.getInstance().addCheckoutURL(url);
- }
- }
myIsKeepLocks = element.getChild("keepLocks") != null;
- myRemoteStatus = element.getChild("remoteStatus") != null;
- myUpgradeMode = element.getChild("upgradeMode") != null ? element.getChild("upgradeMode").getText() : null;
final Element useProxy = element.getChild("myIsUseDefaultProxy");
if (useProxy == null) {
myIsUseDefaultProxy = false;
@@ -508,7 +495,7 @@
final Attribute acceleration = element.getAttribute("myUseAcceleration");
if (acceleration != null) {
try {
- myUseAcceleration = UseAcceleration.valueOf(acceleration.getValue());
+ setUseAcceleration(UseAcceleration.valueOf(acceleration.getValue()));
} catch (IllegalArgumentException e) {
//
}
@@ -526,26 +513,19 @@
final Attribute protocols = element.getAttribute("SSL_PROTOCOLS");
if (protocols != null) {
try {
- SSL_PROTOCOLS = SSLProtocols.valueOf(protocols.getValue());
+ setSslProtocols(SSLProtocols.valueOf(protocols.getValue()));
} catch (IllegalArgumentException e) {
//
}
}
if (treeConflictMergeNewFilesPlace != null) {
- TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = Boolean.parseBoolean(treeConflictMergeNewFilesPlace.getValue());
+ setKeepNewFilesAsIsForTreeConflictMerge(Boolean.parseBoolean(treeConflictMergeNewFilesPlace.getValue()));
}
}
@SuppressWarnings({"HardCodedStringLiteral"})
public void writeExternal(Element element) throws WriteExternalException {
DefaultJDOMExternalizer.writeExternal(this, element);
- if (ADD_PATHS != null) {
- for (String aADD_PATHS : ADD_PATHS) {
- Element elem = new Element("addpath");
- elem.setAttribute("path", aADD_PATHS);
- element.addContent(elem);
- }
- }
if (myConfigurationDirectory != null) {
Element configurationDirectory = new Element("configuration");
configurationDirectory.setText(myConfigurationDirectory);
@@ -555,23 +535,18 @@
if (myIsKeepLocks) {
element.addContent(new Element("keepLocks"));
}
- if (myRemoteStatus) {
- element.addContent(new Element("remoteStatus"));
- }
- if (myUpgradeMode != null) {
- element.addContent(new Element("upgradeMode").setText(myUpgradeMode));
- }
element.addContent(new Element("myIsUseDefaultProxy").setText(myIsUseDefaultProxy ? "true" : "false"));
if (mySupportOptions != null) {
- element.addContent(new Element("supportedVersion").setText("" + mySupportOptions.myVersion));
+ element.addContent(new Element("supportedVersion").setText(String.valueOf(mySupportOptions.myVersion)));
}
- element.setAttribute("maxAnnotateRevisions", "" + myMaxAnnotateRevisions);
- element.setAttribute("myUseAcceleration", "" + myUseAcceleration);
- element.setAttribute("myAutoUpdateAfterCommit", "" + myAutoUpdateAfterCommit);
- element.setAttribute(CLEANUP_ON_START_RUN, "" + myCleanupRun);
- element.setAttribute("SSL_PROTOCOLS", SSL_PROTOCOLS.name());
- if (TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE != null) {
- element.setAttribute("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", "" + TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE);
+ element.setAttribute("maxAnnotateRevisions", String.valueOf(myMaxAnnotateRevisions));
+ element.setAttribute("myUseAcceleration", String.valueOf(getUseAcceleration()));
+ element.setAttribute("myAutoUpdateAfterCommit", String.valueOf(myAutoUpdateAfterCommit));
+ element.setAttribute(CLEANUP_ON_START_RUN, String.valueOf(myCleanupRun));
+ element.setAttribute("SSL_PROTOCOLS", getSslProtocols().name());
+ if (isKeepNewFilesAsIsForTreeConflictMerge() != null) {
+ element.setAttribute("TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE", String.valueOf(
+ isKeepNewFilesAsIsForTreeConflictMerge()));
}
}
@@ -591,14 +566,6 @@
myIsKeepLocks = keepLocks;
}
- public boolean isRemoteStatus() {
- return myRemoteStatus;
- }
-
- public void setRemoteStatus(boolean remote) {
- myRemoteStatus = remote;
- }
-
public boolean isIsUseDefaultProxy() {
return myIsUseDefaultProxy;
}
@@ -643,50 +610,11 @@
return myUpdateRootInfos.get(file);
}
+ // TODO: Check why SvnUpdateEnvironment.validationOptions is fully commented and then remove this method if necessary
public Map<File, UpdateRootInfo> getUpdateInfosMap() {
return Collections.unmodifiableMap(myUpdateRootInfos);
}
- private static final List<String> ourAuthKinds = Arrays.asList(ISVNAuthenticationManager.PASSWORD, ISVNAuthenticationManager.SSH,
- ISVNAuthenticationManager.SSL, ISVNAuthenticationManager.USERNAME, "svn.ssl.server", "svn.ssh.server");
-
- public void clearAuthenticationDirectory(@Nullable Project project) {
- final File authDir = new File(getConfigurationDirectory(), "auth");
- if (authDir.exists()) {
- final Runnable process = new Runnable() {
- public void run() {
- final ProgressIndicator ind = ProgressManager.getInstance().getProgressIndicator();
- if (ind != null) {
- ind.setIndeterminate(true);
- ind.setText("Clearing stored credentials in " + authDir.getAbsolutePath());
- }
- final File[] files = authDir.listFiles(new FilenameFilter() {
- public boolean accept(File dir, String name) {
- return ourAuthKinds.contains(name);
- }
- });
-
- for (File dir : files) {
- if (ind != null) {
- ind.setText("Deleting " + dir.getAbsolutePath());
- }
- FileUtil.delete(dir);
- }
- }
- };
- final Application application = ApplicationManager.getApplication();
- if (application.isUnitTestMode() || ! application.isDispatchThread()) {
- process.run();
- } else {
- ProgressManager.getInstance().runProcessWithProgressSynchronously(process, "button.text.clear.authentication.cache", false, project);
- }
- }
- }
-
- public boolean haveCredentialsFor(final String kind, final String realm) {
- return RUNTIME_AUTH_CACHE.getData(kind, realm) != null;
- }
-
public void acknowledge(final String kind, final String realm, final Object object) {
RUNTIME_AUTH_CACHE.putData(kind, realm, object);
}
@@ -709,7 +637,6 @@
}
public enum UseAcceleration {
- javaHL,
commandLine,
nothing
}
@@ -722,7 +649,7 @@
myCleanupRun = cleanupRun;
}
- public static enum SSLProtocols {
+ public enum SSLProtocols {
sslv3, tlsv1, all
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
index e05bf28..978a52b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnDiffProvider.java
@@ -22,11 +22,16 @@
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.diff.DiffMixin;
import com.intellij.openapi.vcs.diff.DiffProvider;
+import com.intellij.openapi.vcs.diff.DiffProviderEx;
import com.intellij.openapi.vcs.diff.ItemLatestState;
import com.intellij.openapi.vcs.history.VcsRevisionDescription;
import com.intellij.openapi.vcs.history.VcsRevisionDescriptionImpl;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.history.LatestExistentSearcher;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNPropertyValue;
@@ -35,10 +40,14 @@
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
+import java.util.List;
+import java.util.Map;
-public class SvnDiffProvider implements DiffProvider, DiffMixin {
+public class SvnDiffProvider extends DiffProviderEx implements DiffProvider, DiffMixin {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnDiffProvider");
public static final String COMMIT_MESSAGE = "svn:log";
+ private static final int BATCH_INFO_SIZE = 20;
+
private final SvnVcs myVcs;
public SvnDiffProvider(final SvnVcs vcs) {
@@ -47,11 +56,73 @@
public VcsRevisionNumber getCurrentRevision(VirtualFile file) {
final SVNInfo svnInfo = myVcs.getInfo(new File(file.getPresentableUrl()));
- if (svnInfo == null) return null;
- if (SVNRevision.UNDEFINED.equals(svnInfo.getCommittedRevision()) && svnInfo.getCopyFromRevision() != null) {
- return new SvnRevisionNumber(svnInfo.getCopyFromRevision());
+
+ return getRevision(svnInfo);
+ }
+
+ @Nullable
+ private static VcsRevisionNumber getRevision(@Nullable SVNInfo info) {
+ VcsRevisionNumber result = null;
+
+ if (info != null) {
+ SVNRevision revision = SVNRevision.UNDEFINED.equals(info.getCommittedRevision()) && info.getCopyFromRevision() != null
+ ? info.getCopyFromRevision()
+ : info.getRevision();
+
+ result = new SvnRevisionNumber(revision);
}
- return new SvnRevisionNumber(svnInfo.getRevision());
+
+ return result;
+ }
+
+ @Override
+ public Map<VirtualFile, VcsRevisionNumber> getCurrentRevisions(Iterable<VirtualFile> files) {
+ Map<VirtualFile, VcsRevisionNumber> result = ContainerUtil.newHashMap();
+ Map<String, VirtualFile> items = ContainerUtil.newHashMap();
+ List<File> ioFiles = ContainerUtil.newArrayList();
+
+ for (VirtualFile file : files) {
+ File ioFile = VfsUtilCore.virtualToIoFile(file);
+ ioFiles.add(ioFile);
+ items.put(ioFile.getAbsolutePath(), file);
+
+ // process in blocks of BATCH_INFO_SIZE size
+ if (items.size() == BATCH_INFO_SIZE) {
+ collectRevisionsInBatch(result, items, ioFiles);
+ items.clear();
+ ioFiles.clear();
+ }
+ }
+ // process left files
+ collectRevisionsInBatch(result, items, ioFiles);
+
+ return result;
+ }
+
+ private void collectRevisionsInBatch(@NotNull final Map<VirtualFile, VcsRevisionNumber> revisionMap,
+ @NotNull final Map<String, VirtualFile> fileMap,
+ @NotNull List<File> ioFiles) {
+ myVcs.collectInfo(ioFiles, createInfoHandler(revisionMap, fileMap));
+ }
+
+ @NotNull
+ private static ISVNInfoHandler createInfoHandler(@NotNull final Map<VirtualFile, VcsRevisionNumber> revisionMap,
+ @NotNull final Map<String, VirtualFile> fileMap) {
+ return new ISVNInfoHandler() {
+ @Override
+ public void handleInfo(SVNInfo info) throws SVNException {
+ if (info != null) {
+ VirtualFile file = fileMap.get(info.getFile().getAbsolutePath());
+
+ if (file != null) {
+ revisionMap.put(file, getRevision(info));
+ }
+ else {
+ LOG.info("Could not find virtual file for path " + info.getFile().getAbsolutePath());
+ }
+ }
+ }
+ };
}
@Override
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
index 6275f2c..741de4f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnRecursiveStatusWalker.java
@@ -31,7 +31,6 @@
import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
-import org.jetbrains.idea.svn.portable.JavaHLSvnStatusClient;
import org.jetbrains.idea.svn.portable.SvnStatusClientI;
import org.jetbrains.idea.svn.portable.SvnkitSvnStatusClient;
import org.tmatesoft.svn.core.SVNDepth;
@@ -155,15 +154,7 @@
return mySvnClient;
}
- // check format
- if (CheckJavaHL.isPresent() && SvnConfiguration.UseAcceleration.javaHL.equals(myConfiguration17.myUseAcceleration) &&
- Svn17Detector.is17(myProject, file)) {
- return new JavaHLSvnStatusClient(myProject);
- } else if (myConfiguration17.isCommandLine()) {
- // apply command line disregarding working copy format
- return myCommandLineClient;
- }
- return mySvnClient;
+ return myConfiguration17.isCommandLine() ? myCommandLineClient : mySvnClient;
}
public boolean isIsInnerCopyRoot() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java
index 184fbab..3c0d396 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnStatusConvertor.java
@@ -16,7 +16,9 @@
package org.jetbrains.idea.svn;
import com.intellij.openapi.vcs.FileStatus;
-import org.tmatesoft.svn.core.SVNException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.portable.PortableStatus;
import org.tmatesoft.svn.core.wc.SVNStatus;
import org.tmatesoft.svn.core.wc.SVNStatusType;
@@ -24,11 +26,18 @@
private SvnStatusConvertor() {
}
- public static FileStatus convertStatus(final SVNStatus status) throws SVNException {
- return convertStatus(status, true);
+ @NotNull
+ public static FileStatus convertStatus(@Nullable SVNStatusType itemStatus, @Nullable SVNStatusType propertiesStatus) {
+ PortableStatus status = new PortableStatus();
+
+ status.setContentsStatus(itemStatus);
+ status.setPropertiesStatus(propertiesStatus);
+
+ return convertStatus(status);
}
- public static FileStatus convertStatus(final SVNStatus status, final boolean noticeProperties) throws SVNException {
+ @NotNull
+ public static FileStatus convertStatus(@Nullable final SVNStatus status) {
if (status == null) {
return FileStatus.UNKNOWN;
}
@@ -57,17 +66,18 @@
return SvnFileStatus.REPLACED;
}
else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED ||
- noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) {
+ status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) {
if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED &&
- noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) {
+ status.getPropertiesStatus() == SVNStatusType.STATUS_CONFLICTED) {
return FileStatus.MERGED_WITH_BOTH_CONFLICTS;
- } else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) {
+ }
+ else if (status.getContentsStatus() == SVNStatusType.STATUS_CONFLICTED) {
return FileStatus.MERGED_WITH_CONFLICTS;
}
return FileStatus.MERGED_WITH_PROPERTY_CONFLICTS;
}
else if (status.getContentsStatus() == SVNStatusType.STATUS_MODIFIED ||
- noticeProperties && status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) {
+ status.getPropertiesStatus() == SVNStatusType.STATUS_MODIFIED) {
return FileStatus.MODIFIED;
}
else if (status.isSwitched()) {
@@ -79,15 +89,8 @@
return FileStatus.NOT_CHANGED;
}
- public static FileStatus convertPropertyStatus(final SVNStatusType status) throws SVNException {
- return convertSingleStatus(status, FileStatus.MERGED_WITH_PROPERTY_CONFLICTS);
- }
-
- public static FileStatus convertContentsStatus(final SVNStatus status) throws SVNException {
- return convertStatus(status, false);
- }
-
- private static FileStatus convertSingleStatus(final SVNStatusType status, final FileStatus defaultConflictStatus) throws SVNException {
+ @NotNull
+ public static FileStatus convertPropertyStatus(final SVNStatusType status) {
if (status == null) {
return FileStatus.UNKNOWN;
}
@@ -116,7 +119,7 @@
return SvnFileStatus.REPLACED;
}
else if (status == SVNStatusType.STATUS_CONFLICTED) {
- return defaultConflictStatus;
+ return FileStatus.MERGED_WITH_PROPERTY_CONFLICTS;
}
else if (status == SVNStatusType.STATUS_MODIFIED) {
return FileStatus.MODIFIED;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index ce734fd..1e3fd7b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -73,6 +73,7 @@
@NonNls public static final String WC_DB_FILE_NAME = "wc.db";
@NonNls public static final String DIR_PROPS_FILE_NAME = "dir-props";
@NonNls public static final String PATH_TO_LOCK_FILE = SVN_ADMIN_DIR_NAME + "/lock";
+ public static final int DEFAULT_PORT_INDICATOR = -1;
private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnUtil");
public static final Pattern ERROR_PATTERN = Pattern.compile("^svn: (E(\\d+)): (.*)$", Pattern.MULTILINE);
@@ -151,12 +152,6 @@
return info != null && info.getURL() != null ? info.getURL().toString() : null;
}
- public static Map<String, File> getLocationInfoForModule(final SvnVcs vcs, File path, ProgressIndicator progress) {
- final LocationsCrawler crawler = new LocationsCrawler(vcs);
- crawlWCRoots(vcs.getProject(), path, crawler, progress);
- return crawler.getLocationInfos();
- }
-
public static void doLockFiles(Project project, final SvnVcs activeVcs, @NotNull final File[] ioFiles) throws VcsException {
final String lockMessage;
final boolean force;
@@ -348,12 +343,7 @@
public static <T> MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> splitIntoRepositoriesMap(SvnVcs vcs,
List<T> committables, Convertor<T, File> convertor) {
- final MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> result = new MultiMap<Pair<SVNURL, WorkingCopyFormat>, T>() {
- @Override
- protected Collection<T> createCollection() {
- return new ArrayList<T>();
- }
- };
+ final MultiMap<Pair<SVNURL, WorkingCopyFormat>, T> result = MultiMap.create();
for (T committable : committables) {
final RootUrlInfo path = vcs.getSvnFileUrlMapping().getWcRootForFilePath(convertor.convert(committable));
if (path == null) {
@@ -418,35 +408,6 @@
return result;
}
- private static class LocationsCrawler implements SvnWCRootCrawler {
- private final SvnVcs myVcs;
- private final Map<String, File> myLocations;
-
- public LocationsCrawler(SvnVcs vcs) {
- myVcs = vcs;
- myLocations = new HashMap<String, File>();
- }
-
- public Map<String, File> getLocationInfos() {
- return Collections.unmodifiableMap(myLocations);
- }
-
- public void handleWorkingCopyRoot(File root, ProgressIndicator progress) {
- String oldText = null;
- if (progress != null) {
- oldText = progress.getText();
- progress.setText(SvnBundle.message("progress.text.discovering.location", root.getAbsolutePath()));
- }
- SVNInfo info = myVcs.getInfo(root);
- if (info != null && info.getURL() != null) {
- myLocations.put(info.getURL().toString(), info.getFile());
- }
- if (progress != null) {
- progress.setText(oldText);
- }
- }
- }
-
@Nullable
public static String getRepositoryUUID(final SvnVcs vcs, final File file) {
final SVNInfo info = vcs.getInfo(file);
@@ -573,6 +534,7 @@
return repository.hasCapability(SVNCapability.MERGE_INFO);
}
catch (SVNException e) {
+ // TODO: Exception is thrown when url just not exist (was deleted, for instance) => and false is returned which seems not to be correct.
return false;
}
finally {
@@ -743,7 +705,24 @@
}
}
- public static String appendMultiParts(@NotNull final String base, @NotNull final String subPath) throws SVNException {
+ public static String getRelativeUrl(@NotNull String parentUrl, @NotNull String childUrl) {
+ return FileUtilRt.getRelativePath(parentUrl, childUrl, '/', true);
+ }
+
+ public static String getRelativePath(@NotNull String parentPath, @NotNull String childPath) {
+ return FileUtilRt.getRelativePath(FileUtil.toSystemIndependentName(parentPath), FileUtil.toSystemIndependentName(childPath), '/');
+ }
+
+ public static String ensureStartSlash(@NotNull String path) {
+ return StringUtil.startsWithChar(path, '/') ? path : '/' + path;
+ }
+
+ @NotNull
+ public static String join(@NotNull final String... parts) {
+ return StringUtil.join(parts, "/");
+ }
+
+ public static String appendMultiParts(@NotNull final String base, @NotNull final String subPath) {
if (StringUtil.isEmpty(subPath)) return base;
final List<String> parts = StringUtil.split(subPath.replace('\\', '/'), "/", true);
String result = base;
@@ -768,9 +747,32 @@
@Nullable final SVNRevision revision,
@Nullable final SVNRevision pegRevision)
throws VcsException {
- ClientFactory factory = target.isFile() ? vcs.getFactory(target.getFile()) : vcs.getFactory();
+ return vcs.getFactory(target).createContentClient().getContent(target, revision, pegRevision);
+ }
- return factory.createContentClient().getContent(target, revision, pegRevision);
+ public static boolean hasDefaultPort(@NotNull SVNURL result) {
+ return !result.hasPort() || SVNURL.getDefaultPortNumber(result.getProtocol()) == result.getPort();
+ }
+
+ /**
+ * When creating SVNURL with default port, some negative value should be specified as port number, otherwise specified port value (even
+ * if equals to default) will occur in toString() result.
+ */
+ public static int resolvePort(@NotNull SVNURL url) {
+ return !hasDefaultPort(url) ? url.getPort() : DEFAULT_PORT_INDICATOR;
+ }
+
+ @NotNull
+ public static SVNURL createUrl(@NotNull String url) throws SVNException {
+ SVNURL result = SVNURL.parseURIEncoded(url);
+
+ // explicitly check if port corresponds to default port and recreate url specifying default port indicator
+ if (result.hasPort() && hasDefaultPort(result)) {
+ result = SVNURL
+ .create(result.getProtocol(), result.getUserInfo(), result.getHost(), DEFAULT_PORT_INDICATOR, result.getURIEncodedPath(), true);
+ }
+
+ return result;
}
public static SVNURL parseUrl(@NotNull String url) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index f92ad15..96dfea9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -56,6 +56,7 @@
import com.intellij.util.Consumer;
import com.intellij.util.Processor;
import com.intellij.util.ThreeState;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.SoftHashMap;
import com.intellij.util.messages.MessageBus;
@@ -497,11 +498,7 @@
}
}
- final SvnConfiguration.UseAcceleration accelerationType = SvnConfiguration.getInstance(myProject).myUseAcceleration;
- if (SvnConfiguration.UseAcceleration.javaHL.equals(accelerationType)) {
- CheckJavaHL.runtimeCheck(myProject);
- }
- else if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
+ if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
checkCommandLineVersion();
}
@@ -983,6 +980,33 @@
return result;
}
+ public void collectInfo(@NotNull Collection<File> files, @Nullable ISVNInfoHandler handler) {
+ File first = ContainerUtil.getFirstItem(files);
+
+ if (first != null) {
+ ClientFactory factory = getFactory(first);
+
+ try {
+ if (factory instanceof CmdClientFactory) {
+ factory.createInfoClient().doInfo(files, handler);
+ }
+ else {
+ // TODO: Generally this should be moved in SvnKit info client implementation.
+ // TODO: Currently left here to have exception logic as in handleInfoException to be applied for each file separately.
+ for (File file : files) {
+ SVNInfo info = getInfo(file);
+ if (handler != null) {
+ handler.handleInfo(info);
+ }
+ }
+ }
+ }
+ catch (SVNException e) {
+ handleInfoException(e);
+ }
+ }
+ }
+
@Nullable
public SVNInfo getInfo(@NotNull File ioFile, @NotNull SVNRevision revision) {
SVNInfo result = null;
@@ -1031,11 +1055,11 @@
public void refreshSSLProperty() {
if (ourSSLProtocolsExplicitlySet) return;
- if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.SSL_PROTOCOLS)) {
+ if (SvnConfiguration.SSLProtocols.all.equals(myConfiguration.getSslProtocols())) {
System.clearProperty(SVNKIT_HTTP_SSL_PROTOCOLS);
- } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.SSL_PROTOCOLS)) {
+ } else if (SvnConfiguration.SSLProtocols.sslv3.equals(myConfiguration.getSslProtocols())) {
System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "SSLv3");
- } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.SSL_PROTOCOLS)) {
+ } else if (SvnConfiguration.SSLProtocols.tlsv1.equals(myConfiguration.getSslProtocols())) {
System.setProperty(SVNKIT_HTTP_SSL_PROTOCOLS, "TLSv1");
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/Wrapper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/Wrapper.java
deleted file mode 100644
index 877af9f..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/Wrapper.java
+++ /dev/null
@@ -1,28 +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 org.jetbrains.idea.svn;
-
-public class Wrapper<T> {
- private final T myT;
-
- public Wrapper(T t) {
- myT = t;
- }
-
- public T getT() {
- return myT;
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java
deleted file mode 100644
index 544bbc7..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java
+++ /dev/null
@@ -1,367 +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 org.jetbrains.idea.svn.actions;
-
-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.diagnostic.Logger;
-import com.intellij.openapi.diff.DiffManager;
-import com.intellij.openapi.diff.FileContent;
-import com.intellij.openapi.diff.SimpleContent;
-import com.intellij.openapi.diff.SimpleDiffRequest;
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vcs.AbstractVcsHelper;
-import com.intellij.openapi.vcs.FileStatus;
-import com.intellij.openapi.vcs.FileStatusManager;
-import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vfs.CharsetToolkit;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.WaitForProgressToShow;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
-import org.jetbrains.idea.svn.status.SvnDiffEditor;
-import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor;
-import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaInfo;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNReporter;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess;
-import org.tmatesoft.svn.core.internal.wc17.SVNReporter17;
-import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
-import org.tmatesoft.svn.core.io.SVNRepository;
-import org.tmatesoft.svn.core.wc.*;
-import org.tmatesoft.svn.util.SVNDebugLog;
-import org.tmatesoft.svn.util.SVNLogType;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author yole
- */
-public class CompareWithBranchAction extends AnAction implements DumbAware {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.actions.CompareWithBranchAction");
-
- public void actionPerformed(AnActionEvent e) {
- Project project = e.getData(CommonDataKeys.PROJECT);
- assert project != null;
- final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
-
- SelectBranchPopup.show(project, virtualFile, new SelectBranchPopup.BranchSelectedCallback() {
- public void branchSelected(final Project project, final SvnBranchConfigurationNew configuration, final String url, final long revision) {
- new CompareWithBranchOperation(project, virtualFile, configuration).compareWithBranch(url, revision);
- }
- }, SvnBundle.message("compare.with.branch.popup.title"));
- }
-
- @Override
- public void update(final AnActionEvent e) {
- Project project = e.getData(CommonDataKeys.PROJECT);
- VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
- e.getPresentation().setEnabled(isEnabled(project, virtualFile));
- }
-
- private static boolean isEnabled(final Project project, final VirtualFile virtualFile) {
- if (project == null || virtualFile == null) {
- return false;
- }
- final FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(virtualFile);
- if (fileStatus == FileStatus.UNKNOWN || fileStatus == FileStatus.ADDED || fileStatus == FileStatus.IGNORED) {
- return false;
- }
- return true;
- }
-
-
- private class CompareWithBranchOperation {
- private final Project myProject;
- private final VirtualFile myVirtualFile;
- private final SvnBranchConfigurationNew myConfiguration;
-
- public CompareWithBranchOperation(final Project project, final VirtualFile virtualFile, final SvnBranchConfigurationNew config) {
- myProject = project;
- myVirtualFile = virtualFile;
- myConfiguration = config;
- }
-
- public void compareWithBranch(final String baseUrl, final long revision) {
- if (myVirtualFile.isDirectory()) {
- compareDirectoryWithBranch(baseUrl, revision);
- }
- else {
- compareFileWithBranch(baseUrl, revision);
- }
- }
- final StringBuilder titleBuilder = new StringBuilder();
-
- public void compareDirectoryWithBranch(final String baseUrl, final long revision) {
- final List<Change> changes = new ArrayList<Change>();
- ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
- public void run() {
- try {
- final SvnVcs vcs = SvnVcs.getInstance(myProject);
- final SVNURL url = getURLInBranch(vcs, baseUrl);
- if (url == null) return; // todo diagnostics
- titleBuilder.append(SvnBundle.message("repository.browser.compare.title",
- url.toString(),
- FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl())));
-
- final File ioFile = new File(myVirtualFile.getPath());
- if (SvnUtil.is17CopyPart(ioFile)) {
- report17DirDiff(vcs, url);
- } else {
- report16DirDiff(vcs, url);
- }
-
- /* final SVNInfo info1 = vcs.createWCClient().doInfo(new File(myVirtualFile.getPath()), SVNRevision.HEAD);
- if (info1 == null) return;
-
- if (info1 == null) {
- SVNErrorMessage err =
- SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath());
- SVNErrorManager.error(err, SVNLogType.WC);
- }
- else if (info1.getURL() == null) {
- SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath());
- SVNErrorManager.error(err, SVNLogType.WC);
- }
- */
-
- // todo
-
-
- /*final SVNDiffClient diffClient = vcs.createDiffClient();
- diffClient.doDiffStatus(info1.getURL(), info1.getRevision(), url, info1.getRevision(), SVNDepth.INFINITY, false,
- new ISVNDiffStatusHandler() {
- @Override
- public void handleDiffStatus(SVNDiffStatus diffStatus) throws SVNException {
- diffStatus.getModificationType()
- }
- });*/
-
- /*public void doDiffStatus(File path1, SVNRevision rN, File path2, SVNRevision rM, SVNDepth depth, boolean useAncestry, ISVNDiffStatusHandler handler) throws SVNException {*/
- }
- catch(SVNCancelException ex) {
- changes.clear();
- }
- catch (SVNException ex) {
- reportException(ex, baseUrl);
- }
- }
-
- private void report17DirDiff(SvnVcs vcs, SVNURL url) throws SVNException {
- final File ioFile = new File(myVirtualFile.getPath());
- final SVNWCClient wcClient = vcs.createWCClient();
- final SVNInfo info1 = wcClient.doInfo(ioFile, SVNRevision.HEAD);
-
- if (info1 == null) {
- SVNErrorMessage err =
- SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath());
- SVNErrorManager.error(err, SVNLogType.WC);
- }
- else if (info1.getURL() == null) {
- SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath());
- SVNErrorManager.error(err, SVNLogType.WC);
- }
-
- final SVNReporter17 reporter17 =
- new SVNReporter17(ioFile, new SVNWCContext(SvnConfiguration.getInstance(myProject).getOptions(myProject), new ISVNEventHandler() {
- @Override
- public void handleEvent(SVNEvent event, double progress) throws SVNException {
- }
-
- @Override
- public void checkCancelled() throws SVNCancelException {
- }
- }),
- false, true, SVNDepth.INFINITY, false, false, true, false,
- SVNDebugLog.getDefaultLog());
- SVNRepository repository = null;
- SVNRepository repository2 = null;
- try {
- repository = vcs.createRepository(info1.getURL());
- long rev = repository.getLatestRevision();
- repository2 = vcs.createRepository(url.toString());
- SvnDiffEditor diffEditor = new SvnDiffEditor(myVirtualFile, repository2, rev, true);
- repository.diff(url, rev, rev, null, true, SVNDepth.INFINITY, false, reporter17,
- SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null));
- changes.addAll(diffEditor.getChangesMap().values());
- } finally {
- if (repository != null) {
- repository.closeSession();
- }
- if (repository2 != null) {
- repository2.closeSession();
- }
- }
- }
-
- private void report16DirDiff(SvnVcs vcs, SVNURL url) throws SVNException {
- // here there's 1.6 copy so ok to use SVNWCAccess
- final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
- wcAccess.setOptions(vcs.getSvnOptions());
- SVNRepository repository = null;
- SVNRepository repository2 = null;
- try {
- SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH);
- File anchorPath = info.getAnchor().getRoot();
- String target = "".equals(info.getTargetName()) ? null : info.getTargetName();
-
- SVNEntry anchorEntry = info.getAnchor().getEntry("", false);
- if (anchorEntry == null) {
- SVNErrorMessage err =
- SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", anchorPath);
- SVNErrorManager.error(err, SVNLogType.WC);
- }
- else if (anchorEntry.getURL() == null) {
- SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", anchorPath);
- SVNErrorManager.error(err, SVNLogType.WC);
- }
-
- SVNURL anchorURL = anchorEntry.getSVNURL();
- SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY,
- false, false, true, SVNDebugLog.getDefaultLog());
-
- repository = vcs.createRepository(anchorURL.toString());
- long rev = repository.getLatestRevision();
- repository2 = vcs.createRepository((target == null) ? url.toString() : url.removePathTail().toString());
- SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(),
- repository2, rev, true);
- repository.diff(url, rev, rev, target, true, true, false, reporter,
- SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null));
- changes.addAll(diffEditor.getChangesMap().values());
- }
- finally {
- wcAccess.close();
- if (repository != null) {
- repository.closeSession();
- }
- if (repository2 != null) {
- repository2.closeSession();
- }
- }
- }
- }, SvnBundle.message("progress.computing.difference"), true, myProject);
- if (!changes.isEmpty()) {
- AbstractVcsHelper.getInstance(myProject).showWhatDiffersBrowser(null, changes, titleBuilder.toString());
- }
- }
-
- public void compareFileWithBranch(final String baseUrl, final long revision) {
- final ByteArrayOutputStream baos = new ByteArrayOutputStream();
- final StringBuilder remoteTitleBuilder = new StringBuilder();
- final Ref<Boolean> success = new Ref<Boolean>();
- ProgressManager.getInstance().runProcessWithProgressSynchronously(new Runnable() {
- public void run() {
- try {
- final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
- if (indicator != null) {
- indicator.setIndeterminate(true);
- }
- final SvnVcs vcs = SvnVcs.getInstance(myProject);
- SVNURL svnurl = getURLInBranch(vcs, baseUrl);
- if (svnurl == null) {
- reportNotFound(baseUrl);
- return;
- }
- remoteTitleBuilder.append(svnurl.toString());
- SVNWCClient client = vcs.createWCClient();
- client.doGetFileContents(svnurl, SVNRevision.UNDEFINED, SVNRevision.HEAD, true, baos);
- success.set(true);
- }
- catch (SVNException ex) {
- reportException(ex, baseUrl);
- }
- }
- }, SvnBundle.message("compare.with.branch.progress.loading.content"), true, myProject);
- if (success.isNull()) {
- return;
- }
- SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title"));
- req.setContents(new SimpleContent(CharsetToolkit.bytesToString(baos.toByteArray(), myVirtualFile.getCharset())),
- new FileContent(myProject, myVirtualFile));
- req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl());
- DiffManager.getInstance().getDiffTool().show(req);
- }
-
- @Nullable
- private SVNURL getURLInBranch(final SvnVcs vcs, final String baseUrl) throws SVNException {
- final SvnFileUrlMapping urlMapping = vcs.getSvnFileUrlMapping();
- final File file = new File(myVirtualFile.getPath());
- final SVNURL fileUrl = urlMapping.getUrlForFile(file);
- if (fileUrl == null) {
- return null;
- }
-
- final String fileUrlString = fileUrl.toString();
- final RootUrlInfo rootMixed = urlMapping.getWcRootForUrl(fileUrlString);
- if (rootMixed == null) {
- return null;
- }
-
- final SVNURL thisBranchForUrl = SvnUtil.getBranchForUrl(vcs, rootMixed.getVirtualFile(), fileUrlString);
- if (thisBranchForUrl == null) {
- return null;
- }
-
- final String relativePath = SVNPathUtil.getRelativePath(thisBranchForUrl.toString(), fileUrlString);
- return SVNURL.parseURIEncoded(SVNPathUtil.append(baseUrl, relativePath));
- }
-
- private void reportException(final SVNException ex, final String baseUrl) {
- final SVNErrorCode errorCode = ex.getErrorMessage().getErrorCode();
- if (errorCode.equals(SVNErrorCode.RA_ILLEGAL_URL) ||
- errorCode.equals(SVNErrorCode.CLIENT_UNRELATED_RESOURCES) ||
- errorCode.equals(SVNErrorCode.RA_DAV_PATH_NOT_FOUND) ||
- errorCode.equals(SVNErrorCode.FS_NOT_FOUND)) {
- reportNotFound(baseUrl);
- }
- else {
- WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
- public void run() {
- Messages.showMessageDialog(myProject, ex.getMessage(),
- SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon());
- }
- }, null, myProject);
- LOG.info(ex);
- }
- }
-
- private void reportNotFound(final String baseUrl) {
- WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
- public void run() {
- Messages.showMessageDialog(myProject,
- SvnBundle.message("compare.with.branch.location.error", myVirtualFile.getPresentableUrl(), baseUrl),
- SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon());
- }
- }, null, myProject);
- }
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java
index 7135153..d263f1e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CreateBranchOrTagAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -89,7 +89,7 @@
if (!dirExists(activeVcs, project, parentUrl)) {
int rc = Messages.showYesNoDialog(project, "The repository path '" + parentUrl + "' does not exist. Would you like to create it?",
"Branch or Tag", Messages.getQuestionIcon());
- if (rc == 1) {
+ if (rc == Messages.NO) {
return;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkLocallyDeletedTreeConflictResolvedAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkLocallyDeletedTreeConflictResolvedAction.java
index 461c202..1079326 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkLocallyDeletedTreeConflictResolvedAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkLocallyDeletedTreeConflictResolvedAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -19,12 +19,10 @@
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.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.AbstractVcsHelper;
@@ -63,7 +61,7 @@
final int result = Messages.showYesNoDialog(project,
SvnBundle.message("action.mark.tree.conflict.resolved.confirmation.text"), markText,
Messages.getQuestionIcon());
- if (result == DialogWrapper.OK_EXIT_CODE) {
+ if (result == Messages.YES) {
final Ref<VcsException> exception = new Ref<VcsException>();
ProgressManager
.getInstance().run(new Task.Backgroundable(project, markText, true, BackgroundFromStartOption.getInstance()) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkTreeConflictResolvedAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkTreeConflictResolvedAction.java
index a9e372c..73d9c28 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkTreeConflictResolvedAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/MarkTreeConflictResolvedAction.java
@@ -15,13 +15,15 @@
*/
package org.jetbrains.idea.svn.actions;
-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.actionSystem.DataContext;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.AbstractVcsHelper;
@@ -103,7 +105,7 @@
final int result = Messages.showYesNoDialog(checker.getProject(),
SvnBundle.message("action.mark.tree.conflict.resolved.confirmation.text"), markText,
Messages.getQuestionIcon());
- if (result == DialogWrapper.OK_EXIT_CODE) {
+ if (result == Messages.YES) {
final Ref<VcsException> exception = new Ref<VcsException>();
ProgressManager.getInstance().run(new Task.Backgroundable(checker.getProject(), markText, true, BackgroundFromStartOption.getInstance()) {
public void run(@NotNull ProgressIndicator indicator) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/RelocateAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/RelocateAction.java
index 36dc70b..87615a0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/RelocateAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/RelocateAction.java
@@ -28,10 +28,7 @@
import org.jetbrains.idea.svn.SvnStatusUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.dialogs.RelocateDialog;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNInfo;
-import org.tmatesoft.svn.core.wc.SVNUpdateClient;
import java.io.File;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java
index c8779c5..0a81b08 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShareProjectAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,13 +18,11 @@
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.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
@@ -118,7 +116,7 @@
final int promptAnswer =
Messages.showYesNoDialog(project, "Remote folder \"" + parent + "\" is not empty.\nDo you want to continue sharing?",
"Share directory", Messages.getWarningIcon());
- if (DialogWrapper.OK_EXIT_CODE != promptAnswer) return false;
+ if (Messages.YES != promptAnswer) return false;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowAllSubmittedFilesAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowAllSubmittedFilesAction.java
deleted file mode 100644
index 611bff6..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowAllSubmittedFilesAction.java
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- * 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 org.jetbrains.idea.svn.actions;
-
-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.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.io.BufferExposingByteArrayOutputStream;
-import com.intellij.openapi.vcs.AbstractVcsHelper;
-import com.intellij.openapi.vcs.VcsDataKeys;
-import com.intellij.openapi.vcs.VcsException;
-import com.intellij.openapi.vcs.history.VcsFileRevision;
-import com.intellij.openapi.vfs.VirtualFile;
-import icons.SvnIcons;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.history.SvnChangeList;
-import org.jetbrains.idea.svn.history.SvnFileRevision;
-import org.jetbrains.idea.svn.history.SvnRepositoryLocation;
-import org.tmatesoft.svn.core.ISVNLogEntryHandler;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNLogEntry;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.SVNInfo;
-import org.tmatesoft.svn.core.wc.SVNLogClient;
-import org.tmatesoft.svn.core.wc.SVNRevision;
-
-import java.io.File;
-import java.io.PrintStream;
-
-public class ShowAllSubmittedFilesAction extends AnAction implements DumbAware {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.actions.ShowAllSubmittedFilesAction");
-
- public ShowAllSubmittedFilesAction() {
- super(SvnBundle.message("action.name.show.all.paths.affected"), null, SvnIcons.AllRevisions);
- }
-
- public void update(AnActionEvent e) {
- super.update(e);
- final Project project = e.getData(CommonDataKeys.PROJECT);
- if (project == null) {
- e.getPresentation().setEnabled(false);
- return;
- }
- final VirtualFile revisionVirtualFile = e.getData(VcsDataKeys.VCS_VIRTUAL_FILE);
- e.getPresentation().setEnabled((e.getData(VcsDataKeys.VCS_FILE_REVISION) != null) && (revisionVirtualFile != null));
- }
-
- public void actionPerformed(AnActionEvent e) {
- final Project project = e.getData(CommonDataKeys.PROJECT);
- if (project == null) return;
- final VcsFileRevision revision = e.getData(VcsDataKeys.VCS_FILE_REVISION);
- final VirtualFile revisionVirtualFile = e.getData(VcsDataKeys.VCS_VIRTUAL_FILE);
- if ((revision != null) && (revisionVirtualFile != null)) {
- final SvnFileRevision svnRevision = ((SvnFileRevision)revision);
-
- showSubmittedFiles(project, svnRevision, revisionVirtualFile);
- }
- }
-
- public static void showSubmittedFiles(final Project project, final SvnFileRevision svnRevision, final VirtualFile file) {
- final SvnChangeList changeList = loadRevisions(project, svnRevision, file);
-
- if (changeList != null) {
- long revNumber = ((SvnRevisionNumber)svnRevision.getRevisionNumber()).getRevision().getNumber();
- AbstractVcsHelper.getInstance(project).showChangesListBrowser(changeList, getTitle(revNumber));
- }
- }
-
- private static String getTitle(long revisionNumber) {
- return SvnBundle.message("dialog.title.affected.paths", revisionNumber);
- }
-
- @Nullable
- public static SvnChangeList loadRevisions(final Project project, final SvnFileRevision svnRevision, @Nullable final VirtualFile file) {
- return loadRevisions(project, svnRevision, file, true);
- }
-
- @Nullable
- public static SvnChangeList loadRevisions(final Project project, final SvnFileRevision svnRevision, @Nullable final VirtualFile file, boolean underProgress) {
- final Ref<SvnChangeList> result = new Ref<SvnChangeList>();
- final SvnRevisionNumber number = ((SvnRevisionNumber)svnRevision.getRevisionNumber());
-
- final SVNRevision targetRevision = ((SvnRevisionNumber)svnRevision.getRevisionNumber()).getRevision();
- final SvnVcs vcs = SvnVcs.getInstance(project);
-
- try {
- final Exception[] ex = new Exception[1];
- final String url = svnRevision.getURL();
- final SVNLogEntry[] logEntry = new SVNLogEntry[1];
- final SvnRepositoryLocation location = new SvnRepositoryLocation(url);
-
- final SVNLogClient client = vcs.createLogClient();
- final SVNURL repositoryUrl;
- if ((file != null) && file.isInLocalFileSystem()) {
- final SvnFileUrlMapping urlMapping = vcs.getSvnFileUrlMapping();
- final RootUrlInfo wcRoot = urlMapping.getWcRootForFilePath(new File(file.getPath()));
- if (wcRoot == null) {
- return null;
- }
- repositoryUrl = wcRoot.getRepositoryUrlUrl();
- } else {
- final SVNInfo svnInfo = vcs.createWCClient().doInfo(SVNURL.parseURIEncoded(url), SVNRevision.HEAD, SVNRevision.HEAD);
- repositoryUrl = svnInfo.getRepositoryRootURL();
- if (repositoryUrl == null) {
- Messages.showErrorDialog(SvnBundle.message("message.text.cannot.load.version", number, "Cannot get repository url"),
- SvnBundle.message("message.title.error.fetching.affected.paths"));
- return null;
- }
- }
-
- final Runnable process = new Runnable() {
- public void run() {
- try {
-
- ProgressManager.getInstance().getProgressIndicator().setText(SvnBundle.message("progress.text.loading.log"));
- client.doLog(repositoryUrl, null, targetRevision, targetRevision, targetRevision, false, true, 0, new ISVNLogEntryHandler() {
- public void handleLogEntry(final SVNLogEntry currentLogEntry) throws SVNException {
- logEntry[0] = currentLogEntry;
- }
- });
- if (logEntry[0] == null) {
- throw new VcsException(SvnBundle.message("exception.text.cannot.load.version", number));
- }
-
- ProgressManager.getInstance().getProgressIndicator().setText(SvnBundle.message("progress.text.processing.changes"));
- result.set(new SvnChangeList(vcs, location, logEntry[0], repositoryUrl.toString()));
- }
- catch (Exception e) {
- ex[0] = e;
- }
- }
- };
- if (underProgress) {
- ProgressManager.getInstance().runProcessWithProgressSynchronously(process, getTitle(targetRevision.getNumber()), false, project);
- } else {
- process.run();
- }
- if (ex[0] != null) throw ex[0];
- }
- catch (Exception e1) {
- final BufferExposingByteArrayOutputStream baos = new BufferExposingByteArrayOutputStream();
- e1.printStackTrace(new PrintStream(baos));
- LOG.info("For url: " + svnRevision.getURL() + "Exception: " + new String(baos.getInternalBuffer(), 0, baos.size()));
-
- Messages.showErrorDialog(SvnBundle.message("message.text.cannot.load.version", number, e1.getLocalizedMessage()),
- SvnBundle.message("message.title.error.fetching.affected.paths"));
- return null;
- }
-
- return result.get();
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java
index bce6278..d8126a1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/ShowPropertiesDiffAction.java
@@ -20,6 +20,7 @@
import com.intellij.openapi.vcs.VcsDataKeys;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.changes.CurrentContentRevision;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnVcs;
@@ -53,7 +54,10 @@
protected SVNRevision getAfterRevisionValue(final Change change, final SvnVcs vcs) throws SVNException {
final ContentRevision afterRevision = change.getAfterRevision();
if (afterRevision != null) {
- return ((SvnRevisionNumber) afterRevision.getRevisionNumber()).getRevision();
+ // CurrentContentRevision will be here, for instance, if invoked from changes dialog for "Compare with Branch" action
+ return afterRevision instanceof CurrentContentRevision
+ ? SVNRevision.WORKING
+ : ((SvnRevisionNumber)afterRevision.getRevisionNumber()).getRevision();
} else {
return SVNRevision.create(((SvnRevisionNumber) change.getBeforeRevision().getRevisionNumber()).getRevision().getNumber() + 1);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java
index f16bfa4..f4fa9f9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/BaseSvnFileAnnotation.java
@@ -164,7 +164,7 @@
myContents = contents;
myBaseRevision = baseRevision;
myConfiguration = SvnConfiguration.getInstance(vcs.getProject());
- myShowMergeSources = myConfiguration.SHOW_MERGE_SOURCES_IN_ANNOTATE;
+ myShowMergeSources = myConfiguration.isShowMergeSourcesInAnnotate();
myInfos = new MyPartiallyCreatedInfos();
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
index 88adf25..c51f4db 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/annotate/SvnAnnotationProvider.java
@@ -118,7 +118,7 @@
// ignore mime type=true : IDEA-19562
final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(progress, result);
- final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE &&
+ final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() &&
SvnUtil.checkRepositoryVersion15(myVcs, url);
final MySteppedLogGetter logGetter = new MySteppedLogGetter(
myVcs, ioFile, progress,
@@ -248,7 +248,7 @@
pair.getSecond().getPath(), current);
final ISVNAnnotateHandler annotateHandler = createAnnotationHandler(ProgressManager.getInstance().getProgressIndicator(), result);
- final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE &&
+ final boolean calculateMergeinfo = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate() &&
SvnUtil.checkRepositoryVersion15(myVcs, wasUrl.toString());
AnnotateClient client = myVcs.getFactory().createAnnotateClient();
client.annotate(SvnTarget.fromURL(wasUrl), SVNRevision.create(1), svnRevision, svnRevision, calculateMergeinfo,
@@ -451,8 +451,8 @@
}
private void doLog(final boolean includeMerged, final SVNRevision truncateTo, final int max) throws VcsException {
- myClient.doLog(myIoFile, myEndRevision, truncateTo == null ? SVNRevision.create(1L) : truncateTo,
- SVNRevision.UNDEFINED, false, false, includeMerged, max, null,
+ myClient.doLog(SvnTarget.fromFile(myIoFile), myEndRevision, truncateTo == null ? SVNRevision.create(1L) : truncateTo,
+ false, false, includeMerged, max, null,
new ISVNLogEntryHandler() {
public void handleLogEntry(SVNLogEntry logEntry) {
if (SVNRevision.UNDEFINED.getNumber() == logEntry.getRevision()) {
@@ -478,6 +478,6 @@
}
private static SVNDiffOptions getLogClientOptions(@NotNull SvnVcs vcs) {
- return SvnConfiguration.getInstance(vcs.getProject()).IGNORE_SPACES_IN_ANNOTATE ? new SVNDiffOptions(true, true, true) : null;
+ return SvnConfiguration.getInstance(vcs.getProject()).isIgnoreSpacesInAnnotate() ? new SVNDiffOptions(true, true, true) : null;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java
index 4076a72..e140a62 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java
@@ -57,6 +57,13 @@
}
}
+ protected void assertDirectory(@NotNull SvnTarget target) {
+ assertFile(target);
+ if (!target.getFile().isDirectory()) {
+ throw new IllegalArgumentException("Target should be directory " + target);
+ }
+ }
+
protected void validateFormat(@NotNull WorkingCopyFormat format, @NotNull Collection<WorkingCopyFormat> supported) throws VcsException {
if (!supported.contains(format)) {
throw new VcsException(
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java
index 7f16724..9c01217 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/ClientFactory.java
@@ -4,6 +4,7 @@
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.add.AddClient;
import org.jetbrains.idea.svn.annotate.AnnotateClient;
+import org.jetbrains.idea.svn.browse.BrowseClient;
import org.jetbrains.idea.svn.change.ChangeListClient;
import org.jetbrains.idea.svn.checkin.ImportClient;
import org.jetbrains.idea.svn.checkout.CheckoutClient;
@@ -13,6 +14,7 @@
import org.jetbrains.idea.svn.content.ContentClient;
import org.jetbrains.idea.svn.copy.CopyMoveClient;
import org.jetbrains.idea.svn.delete.DeleteClient;
+import org.jetbrains.idea.svn.diff.DiffClient;
import org.jetbrains.idea.svn.history.HistoryClient;
import org.jetbrains.idea.svn.integrate.MergeClient;
import org.jetbrains.idea.svn.lock.LockClient;
@@ -53,6 +55,8 @@
protected ImportClient myImportClient;
protected ExportClient myExportClient;
protected UpgradeClient myUpgradeClient;
+ protected BrowseClient myBrowseClient;
+ protected DiffClient myDiffClient;
protected ClientFactory(@NotNull SvnVcs vcs) {
myVcs = vcs;
@@ -174,6 +178,16 @@
}
@NotNull
+ public BrowseClient createBrowseClient() {
+ return prepare(myBrowseClient);
+ }
+
+ @NotNull
+ public DiffClient createDiffClient() {
+ return prepare(myDiffClient);
+ }
+
+ @NotNull
protected <T extends SvnClient> T prepare(@NotNull T client) {
client.setVcs(myVcs);
client.setFactory(this);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java
index de5c33e..653852c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdClientFactory.java
@@ -4,11 +4,13 @@
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.add.CmdAddClient;
import org.jetbrains.idea.svn.annotate.CmdAnnotateClient;
+import org.jetbrains.idea.svn.browse.CmdBrowseClient;
import org.jetbrains.idea.svn.change.CmdChangeListClient;
import org.jetbrains.idea.svn.checkin.CmdImportClient;
import org.jetbrains.idea.svn.checkout.CmdCheckoutClient;
import org.jetbrains.idea.svn.checkout.CmdExportClient;
import org.jetbrains.idea.svn.cleanup.CmdCleanupClient;
+import org.jetbrains.idea.svn.diff.CmdDiffClient;
import org.jetbrains.idea.svn.update.CmdUpdateClient;
import org.jetbrains.idea.svn.commandLine.SvnCommandLineInfoClient;
import org.jetbrains.idea.svn.commandLine.SvnCommandLineStatusClient;
@@ -55,6 +57,8 @@
myImportClient = new CmdImportClient();
myExportClient = new CmdExportClient();
myUpgradeClient = new CmdUpgradeClient();
+ myBrowseClient = new CmdBrowseClient();
+ myDiffClient = new CmdDiffClient();
statusClient = new SvnCommandLineStatusClient(myVcs);
infoClient = new SvnCommandLineInfoClient(myVcs);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java
index 27e025c..3fb1d83 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/SvnKitClientFactory.java
@@ -4,6 +4,7 @@
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.add.SvnKitAddClient;
import org.jetbrains.idea.svn.annotate.SvnKitAnnotateClient;
+import org.jetbrains.idea.svn.browse.SvnKitBrowseClient;
import org.jetbrains.idea.svn.change.SvnKitChangeListClient;
import org.jetbrains.idea.svn.checkin.SvnKitImportClient;
import org.jetbrains.idea.svn.checkout.SvnKitCheckoutClient;
@@ -13,6 +14,7 @@
import org.jetbrains.idea.svn.content.SvnKitContentClient;
import org.jetbrains.idea.svn.copy.SvnKitCopyMoveClient;
import org.jetbrains.idea.svn.delete.SvnKitDeleteClient;
+import org.jetbrains.idea.svn.diff.SvnKitDiffClient;
import org.jetbrains.idea.svn.history.SvnKitHistoryClient;
import org.jetbrains.idea.svn.integrate.SvnKitMergeClient;
import org.jetbrains.idea.svn.lock.SvnKitLockClient;
@@ -55,6 +57,8 @@
myImportClient = new SvnKitImportClient();
myExportClient = new SvnKitExportClient();
myUpgradeClient = new SvnKitUpgradeClient();
+ myBrowseClient = new SvnKitBrowseClient();
+ myDiffClient = new SvnKitDiffClient();
statusClient = new SvnkitSvnStatusClient(myVcs, null);
infoClient = new SvnkitSvnWcClient(myVcs);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java
index 049326a..2cbbc1c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/BranchesLoader.java
@@ -17,48 +17,56 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.integrate.SvnBranchItem;
import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public class BranchesLoader {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.branchConfig.BranchesLoader");
private BranchesLoader() {
}
- public static List<SvnBranchItem> loadBranches(final Project project, final String url, boolean passive) throws SVNException {
- final List<SvnBranchItem> result = new LinkedList<SvnBranchItem>();
-
+ public static List<SvnBranchItem> loadBranches(final Project project, final String url, boolean passive) throws SVNException,
+ VcsException {
final SvnConfiguration configuration = SvnConfiguration.getInstance(project);
final SvnVcs vcs = SvnVcs.getInstance(project);
- final ISVNAuthenticationManager passiveManager = passive ?
- configuration.getPassiveAuthenticationManager(project) : configuration.getInteractiveManager(vcs);
- final SVNURL branchesUrl = SVNURL.parseURIEncoded(url);
+ SVNURL branchesUrl = SVNURL.parseURIEncoded(url);
+ List<SvnBranchItem> result = new LinkedList<SvnBranchItem>();
+ SvnTarget target = SvnTarget.fromURL(branchesUrl);
+ ISVNDirEntryHandler handler = createHandler(branchesUrl, result);
- // TODO: Currently this method works for 1.8 - but should be updated to command line implementation
- final SVNLogClient logClient = vcs.createLogClient(passiveManager);
- logClient.doList(branchesUrl, SVNRevision.UNDEFINED, SVNRevision.HEAD, false, SVNDepth.IMMEDIATES, SVNDirEntry.DIRENT_ALL, new ISVNDirEntryHandler() {
- public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException {
- final SVNURL currentUrl = dirEntry.getURL();
- if (! branchesUrl.equals(currentUrl)) {
- final String url = currentUrl.toString();
- // if have permissions
- if (dirEntry.getDate() != null) {
- result.add(new SvnBranchItem(url, dirEntry.getDate(), dirEntry.getRevision()));
- }
- }
- }
- });
+ if (!passive) {
+ // TODO: Implement ability to specify interactive/non-interactive auth mode for clients
+ vcs.getFactory(target).createBrowseClient().list(target, SVNRevision.HEAD, SVNDepth.IMMEDIATES, handler);
+ }
+ else {
+ SVNLogClient client = vcs.createLogClient(configuration.getPassiveAuthenticationManager(project));
+ client
+ .doList(target.getURL(), target.getPegRevision(), SVNRevision.HEAD, false, SVNDepth.IMMEDIATES, SVNDirEntry.DIRENT_ALL, handler);
+ }
+
Collections.sort(result);
return result;
}
+
+ @NotNull
+ private static ISVNDirEntryHandler createHandler(@NotNull final SVNURL branchesUrl, @NotNull final List<SvnBranchItem> result) {
+ return new ISVNDirEntryHandler() {
+ public void handleDirEntry(final SVNDirEntry dirEntry) throws SVNException {
+ if (!branchesUrl.equals(dirEntry.getURL()) && dirEntry.getDate() != null) {
+ result.add(new SvnBranchItem(dirEntry.getURL().toDecodedString(), dirEntry.getDate(), dirEntry.getRevision()));
+ }
+ }
+ };
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java
index 11374d8..2c7444e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/branchConfig/NewRootBunch.java
@@ -23,6 +23,7 @@
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vcs.CalledInBackground;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Consumer;
@@ -172,18 +173,26 @@
callbackCalled = true;
}
}
+ catch (VcsException e) {
+ showError(e);
+ }
catch (SVNException e) {
- // already logged inside
- if (InfoReliability.setByUser.equals(myInfoReliability)) {
- VcsBalloonProblemNotifier.showOverChangesView(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR);
- }
- } finally {
+ showError(e);
+ }
+ finally {
// callback must be called by contract
if (myCallback != null && (! callbackCalled)) {
myCallback.consume(null);
}
}
}
+
+ private void showError(Exception e) {
+ // already logged inside
+ if (InfoReliability.setByUser.equals(myInfoReliability)) {
+ VcsBalloonProblemNotifier.showOverChangesView(myProject, "Branches load error: " + e.getMessage(), MessageType.ERROR);
+ }
+ }
}
private static class DefaultBranchConfigInitializer implements Runnable {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java
new file mode 100644
index 0000000..ea59a9a
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/BrowseClient.java
@@ -0,0 +1,34 @@
+/*
+ * 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.idea.svn.browse;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.ISVNDirEntryHandler;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface BrowseClient extends SvnClient {
+
+ void list(@NotNull SvnTarget target, @Nullable SVNRevision revision, @Nullable SVNDepth depth, @Nullable ISVNDirEntryHandler handler)
+ throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java
new file mode 100644
index 0000000..b8fba0c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/CmdBrowseClient.java
@@ -0,0 +1,177 @@
+/*
+ * 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.idea.svn.browse;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.CommandExecutor;
+import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+import org.jetbrains.idea.svn.commandLine.SvnCommandName;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdBrowseClient extends BaseSvnClient implements BrowseClient {
+
+ @Override
+ public void list(@NotNull SvnTarget target,
+ @Nullable SVNRevision revision,
+ @Nullable SVNDepth depth,
+ @Nullable ISVNDirEntryHandler handler) throws VcsException {
+ assertUrl(target);
+
+ List<String> parameters = new ArrayList<String>();
+
+ CommandUtil.put(parameters, target);
+ CommandUtil.put(parameters, revision);
+ CommandUtil.put(parameters, depth);
+ parameters.add("--xml");
+
+ CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.list, parameters, null);
+
+ try {
+ parseOutput(target.getURL(), command, handler);
+ }
+ catch (SVNException e) {
+ throw new SvnBindException(e);
+ }
+ }
+
+ private static void parseOutput(@NotNull SVNURL url, @NotNull CommandExecutor command, @Nullable ISVNDirEntryHandler handler)
+ throws VcsException, SVNException {
+ try {
+ TargetLists lists = CommandUtil.parse(command.getOutput(), TargetLists.class);
+
+ if (handler != null && lists != null) {
+ for (TargetList list : lists.lists) {
+ for (Entry entry : list.entries) {
+ handler.handleDirEntry(entry.toDirEntry(url));
+ }
+ }
+ }
+ }
+ catch (JAXBException e) {
+ throw new SvnBindException(e);
+ }
+ }
+
+
+ @XmlRootElement(name = "lists")
+ public static class TargetLists {
+
+ @XmlElement(name = "list")
+ public List<TargetList> lists = new ArrayList<TargetList>();
+ }
+
+ public static class TargetList {
+
+ @XmlAttribute(name = "path")
+ public String path;
+
+ @XmlElement(name = "entry")
+ public List<Entry> entries = new ArrayList<Entry>();
+ }
+
+ public static class Entry {
+
+ @XmlAttribute(name = "kind")
+ public String kind;
+
+ @XmlElement(name = "name")
+ public String name;
+
+ @XmlElement(name = "size")
+ public long size;
+
+ @XmlElement(name = "commit")
+ public Commit commit;
+
+ @XmlElement(name = "lock")
+ public Lock lock;
+
+ public long revision() {
+ return commit != null ? commit.revision : 0;
+ }
+
+ public String author() {
+ return commit != null ? commit.author : "";
+ }
+
+ public Date date() {
+ return commit != null ? commit.date : null;
+ }
+
+ public SVNDirEntry toDirEntry(@NotNull SVNURL url) throws SVNException {
+ // TODO: repository root and relative path are not used for now
+ SVNDirEntry entry =
+ new SVNDirEntry(url.appendPath(name, false), null, name, SVNNodeKind.parseKind(kind), size, false, revision(), date(),
+ author());
+
+ entry.setRelativePath(null);
+ entry.setLock(lock != null ? lock.toLock(entry.getRelativePath()) : null);
+
+ return entry;
+ }
+ }
+
+ public static class Commit {
+
+ @XmlAttribute(name = "revision")
+ public long revision;
+
+ @XmlElement(name = "author")
+ public String author;
+
+ @XmlElement(name = "date")
+ public Date date;
+ }
+
+ public static class Lock {
+
+ @XmlElement(name = "token")
+ public String token;
+
+ @XmlElement(name = "owner")
+ public String owner;
+
+ @XmlElement(name = "comment")
+ public String comment;
+
+ @XmlElement(name = "created")
+ public Date created;
+
+ @XmlElement(name = "expires")
+ public Date expires;
+
+ public SVNLock toLock(@NotNull String path) {
+ return new SVNLock(path, token, owner, comment, created, expires);
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java
new file mode 100644
index 0000000..29531ab
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/browse/SvnKitBrowseClient.java
@@ -0,0 +1,56 @@
+/*
+ * 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.idea.svn.browse;
+
+import com.intellij.openapi.vcs.VcsException;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+import org.tmatesoft.svn.core.ISVNDirEntryHandler;
+import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNDirEntry;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.SVNLogClient;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitBrowseClient extends BaseSvnClient implements BrowseClient {
+ @Override
+ public void list(@NotNull SvnTarget target,
+ @Nullable SVNRevision revision,
+ @Nullable SVNDepth depth,
+ @Nullable ISVNDirEntryHandler handler) throws VcsException {
+ assertUrl(target);
+
+ SVNLogClient client = myVcs.createLogClient();
+
+ try {
+ if (target.isFile()) {
+ client.doList(target.getFile(), target.getPegRevision(), revision, true, depth, SVNDirEntry.DIRENT_ALL, handler);
+ }
+ else {
+ client.doList(target.getURL(), target.getPegRevision(), revision, true, depth, SVNDirEntry.DIRENT_ALL, handler);
+ }
+ }
+ catch (SVNException e) {
+ throw new SvnBindException(e);
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
index 57daf70..29d5068 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/IdeaSvnkitBasedAuthenticationCallback.java
@@ -33,12 +33,10 @@
import com.intellij.util.proxy.CommonProxy;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.SvnAuthenticationManager;
-import org.jetbrains.idea.svn.SvnBundle;
-import org.jetbrains.idea.svn.SvnConfiguration;
-import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.*;
import org.jetbrains.idea.svn.commandLine.AuthenticationCallback;
import org.jetbrains.idea.svn.dialogs.SimpleCredentialsDialog;
+import org.jetbrains.idea.svn.dialogs.SvnInteractiveAuthenticationProvider;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.*;
import org.tmatesoft.svn.core.internal.util.SVNBase64;
@@ -221,7 +219,7 @@
final Proxy proxy = getIdeaDefinedProxy(repositoryUrl);
if (proxy != null){
- SvnConfiguration.putProxyIntoServersFile(myTempDirectory, repositoryUrl.getHost(), proxy);
+ IdeaSVNConfigFile.putProxyIntoServersFile(myTempDirectory, repositoryUrl.getHost(), proxy);
}
return true;
}
@@ -301,7 +299,7 @@
PopupUtil.showBalloonForActiveComponent("Failed to authenticate to proxy: " + e.getMessage(), MessageType.ERROR);
return false;
}
- return SvnConfiguration.putProxyCredentialsIntoServerFile(myTempDirectory, repositoryUrl.getHost(), authentication);
+ return IdeaSVNConfigFile.putProxyCredentialsIntoServerFile(myTempDirectory, repositoryUrl.getHost(), authentication);
}
return false;
}
@@ -358,7 +356,12 @@
}
protected SvnAuthenticationManager createTmpManager() {
- return SvnConfiguration.createForTmpDir(myVcs.getProject(), myTempDirectory);
+ final SvnAuthenticationManager interactive = new SvnAuthenticationManager(myVcs.getProject(), myTempDirectory);
+
+ interactive.setRuntimeStorage(SvnConfiguration.RUNTIME_AUTH_CACHE);
+ interactive.setAuthenticationProvider(new SvnInteractiveAuthenticationProvider(myVcs, interactive));
+
+ return interactive;
}
protected abstract T getWithPassive(SvnAuthenticationManager passive) throws SVNException;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
index 6125ea4..b38d1c9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java
@@ -25,6 +25,17 @@
*/
public class CommandUtil {
+ @NotNull
+ public static File resolvePath(@NotNull File base, @NotNull String path) {
+ File result = new File(path);
+
+ if (!result.isAbsolute()) {
+ result = ".".equals(path) ? base : new File(base, path);
+ }
+
+ return result;
+ }
+
/**
* Puts given value to parameters if condition is satisfied
*
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java
index 9e28696..421a734 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/ProxyModule.java
@@ -20,7 +20,6 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.IdeaSVNConfigFile;
import org.jetbrains.idea.svn.SvnAuthenticationManager;
-import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.checkin.IdeaSvnkitBasedAuthenticationCallback;
import org.tmatesoft.svn.core.SVNURL;
@@ -73,7 +72,7 @@
String groupName = SvnAuthenticationManager.getGroupForHost(host, configFile);
if (StringUtil.isEmptyOrSpaces(groupName)) {
- groupName = SvnConfiguration.getNewGroupName(host, configFile);
+ groupName = IdeaSVNConfigFile.getNewGroupName(host, configFile);
command.put("--config-option");
command.put(String.format("servers:groups:%s=%s*", groupName, host));
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java
index bcfcba5..1976a31 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnBindException.java
@@ -15,9 +15,11 @@
*/
package org.jetbrains.idea.svn.commandLine;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.util.LineSeparator;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.hash.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -38,6 +40,9 @@
*/
public class SvnBindException extends VcsException {
+ public static final int ERROR_BASE = 120000;
+ public static final int CATEGORY_SIZE = 5000;
+
private Map<Integer, String> errors = new HashMap<Integer, String>();
public SvnBindException(String message) {
@@ -67,6 +72,21 @@
return errors.containsKey(error.getCode());
}
+ public boolean containsCategory(int category) {
+ final int categoryCode = getCategoryCode(category);
+
+ return ContainerUtil.exists(errors.keySet(), new Condition<Integer>() {
+ @Override
+ public boolean value(Integer code) {
+ return getCategoryCode(code) == categoryCode;
+ }
+ });
+ }
+
+ private static int getCategoryCode(int category) {
+ return (category - ERROR_BASE) / CATEGORY_SIZE;
+ }
+
private void parseErrors(@NotNull String message) {
Matcher matcher = SvnUtil.ERROR_PATTERN.matcher(message);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
index 844835d..ef48226 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandLineInfoClient.java
@@ -23,6 +23,7 @@
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.Consumer;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnVcs;
@@ -124,13 +125,15 @@
final String text = e.getMessage();
final boolean notEmpty = !StringUtil.isEmptyOrSpaces(text);
if (notEmpty && text.contains("W155010")) {
- // just null
- return null;
+ // if "svn info" is executed for several files at once, then this warning could be printed only for some files, but info for other
+ // files should be parsed from output
+ return output.getStdout();
}
// not a working copy exception
// "E155007: '' is not a working copy"
if (notEmpty && text.contains("is not a working copy")) {
if (StringUtil.isNotEmpty(output.getStdout())) {
+ // TODO: Seems not reproducible in 1.8.4
// workaround: as in subversion 1.8 "svn info" on a working copy root outputs such error for parent folder,
// if there are files with conflicts.
// but the requested info is still in the output except root closing tag
@@ -152,7 +155,7 @@
}
}
- private void parseResult(@NotNull final ISVNInfoHandler handler, @Nullable File base, @Nullable String result) throws SVNException {
+ private static void parseResult(@NotNull final ISVNInfoHandler handler, @Nullable File base, @Nullable String result) throws SVNException {
if (StringUtil.isEmpty(result)) {
return;
}
@@ -246,4 +249,26 @@
});
return infoArr[0];
}
+
+ @Override
+ public void doInfo(@NotNull Collection<File> paths, @Nullable ISVNInfoHandler handler) throws SVNException {
+ File base = ContainerUtil.getFirstItem(paths);
+
+ if (base != null) {
+ base = CommandUtil.correctUpToExistingParent(base);
+
+ List<String> parameters = ContainerUtil.newArrayList();
+ for (File file : paths) {
+ CommandUtil.put(parameters, file);
+ }
+ CommandUtil.put(parameters, true, "--xml");
+
+ // Currently do not handle exceptions here like in SvnVcs.handleInfoException - just continue with parsing in case of warnings for
+ // some of the requested items
+ String result = execute(parameters, base);
+ if (handler != null) {
+ parseResult(handler, base, result);
+ }
+ }
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
index 1932d04..c31ce23 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommandName.java
@@ -50,7 +50,9 @@
unlock("unlock", true),
importFolder("import", false),
export("export", false),
- upgrade("upgrade", true);
+ upgrade("upgrade", true),
+ list("list", false),
+ diff("diff", false);
private final String myName;
private final boolean myWriteable;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java
index 5e1b4c9..d9b760d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnCommitRunner.java
@@ -20,7 +20,6 @@
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.VcsException;
-import org.apache.subversion.javahl.types.Revision;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnVcs;
@@ -42,6 +41,8 @@
private static final Logger LOG = Logger.getInstance("org.jetbrains.idea.svn.commandLine.SvnCommitRunner");
+ public static final long INVALID_REVISION_NUMBER = -1L;
+
private SvnCommitRunner.CommandListener myCommandListener;
private SvnVcs myVcs;
@@ -57,7 +58,7 @@
boolean keepChangelist,
Collection<String> changelists,
Map revpropTable) throws VcsException {
- if (paths.length == 0) return Revision.SVN_INVALID_REVNUM;
+ if (paths.length == 0) return INVALID_REVISION_NUMBER;
final List<String> parameters = new ArrayList<String>();
CommandUtil.put(parameters, depth);
@@ -106,7 +107,7 @@
@Nullable private final CommitEventHandler myHandler;
private SvnBindException myException;
- private long myCommittedRevision = Revision.SVN_INVALID_REVNUM;
+ private long myCommittedRevision = INVALID_REVISION_NUMBER;
private File myBase;
public CommandListener(@Nullable CommitEventHandler handler) {
@@ -212,13 +213,7 @@
@NotNull
private File toFile(@NotNull String path) {
- File result = new File(path);
-
- if (!result.isAbsolute()) {
- result = new File(myBase, result.getPath());
- }
-
- return result;
+ return CommandUtil.resolvePath(myBase, path);
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java
index f52f120..46372c2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoHandler.java
@@ -887,7 +887,7 @@
if (myBase != null) {
final String path = attributes.getValue("path");
assertSAX(!StringUtil.isEmptyOrSpaces(path));
- structure.myFile = new File(myBase, path);
+ structure.myFile = CommandUtil.resolvePath(myBase, path);
}
final String revision = attributes.getValue("revision");
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java
index c5cb47b..696e366 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnInfoStructure.java
@@ -15,9 +15,9 @@
*/
package org.jetbrains.idea.svn.commandLine;
-import org.apache.subversion.javahl.ConflictDescriptor;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.portable.ConflictActionConvertor;
import org.jetbrains.idea.svn.portable.IdeaSVNInfo;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion;
@@ -26,6 +26,7 @@
import java.io.File;
import java.util.Date;
+import java.util.Map;
/**
* Created with IntelliJ IDEA.
@@ -34,6 +35,25 @@
* Time: 2:11 PM
*/
public class SvnInfoStructure {
+
+ private static final Map<String, SVNConflictAction> ourConflictActions = ContainerUtil.newHashMap();
+ private static final Map<String, SVNConflictReason> ourConflictReasons = ContainerUtil.newHashMap();
+
+ static {
+ ourConflictActions.put("add", SVNConflictAction.ADD);
+ ourConflictActions.put("edit", SVNConflictAction.EDIT);
+ ourConflictActions.put("delete", SVNConflictAction.DELETE);
+ ourConflictActions.put("replace", SVNConflictAction.REPLACE);
+
+ ourConflictReasons.put("edit", SVNConflictReason.EDITED);
+ ourConflictReasons.put("obstruct", SVNConflictReason.OBSTRUCTED);
+ ourConflictReasons.put("delete", SVNConflictReason.DELETED);
+ ourConflictReasons.put("miss", SVNConflictReason.MISSING);
+ ourConflictReasons.put("unversion", SVNConflictReason.UNVERSIONED);
+ ourConflictReasons.put("add", SVNConflictReason.ADDED);
+ ourConflictReasons.put("replace", SVNConflictReason.REPLACED);
+ }
+
@Nullable public File myFile;
public String relativeUrl;
public SVNURL myUrl;
@@ -87,9 +107,8 @@
else {
assert myFile != null;
- final SVNConflictAction action = ConflictActionConvertor.create(ConflictDescriptor.Action.valueOf(myTreeConflict.myAction));
+ final SVNConflictAction action = parseConflictAction(myTreeConflict.myAction);
final SVNConflictReason reason = parseConflictReason(myTreeConflict.myReason);
- //final SVNConflictReason reason = ConflictReasonConvertor.convert(ConflictDescriptor.Reason.valueOf(myTreeConflict.myReason));
SVNOperation operation = SVNOperation.fromString(myTreeConflict.myOperation);
operation = operation == null ? SVNOperation.NONE : operation;
return new SVNTreeConflictDescription(myFile, myKind, action, reason, operation,
@@ -98,38 +117,26 @@
}
}
- private SVNConflictReason parseConflictReason(String reason) throws SAXException {
- if (ConflictDescriptor.Reason.edited.name().equals(reason)) {
- return SVNConflictReason.EDITED;
- } else if (ConflictDescriptor.Reason.obstructed.name().equals(reason)) {
- return SVNConflictReason.OBSTRUCTED;
- } else if (ConflictDescriptor.Reason.deleted.name().equals(reason)) {
- return SVNConflictReason.DELETED;
- } else if (ConflictDescriptor.Reason.missing.name().equals(reason)) {
- return SVNConflictReason.MISSING;
- } else if (ConflictDescriptor.Reason.unversioned.name().equals(reason)) {
- return SVNConflictReason.UNVERSIONED;
- } else if (ConflictDescriptor.Reason.added.name().equals(reason)) {
- return SVNConflictReason.ADDED;
- } else if (ConflictDescriptor.Reason.replaced.name().equals(reason)) {
- return SVNConflictReason.REPLACED;
+ private SVNConflictAction parseConflictAction(@NotNull String actionName) {
+ SVNConflictAction action = SVNConflictAction.fromString(actionName);
+ action = action != null ? action : ourConflictActions.get(actionName);
+
+ if (action == null) {
+ throw new IllegalArgumentException("Unknown conflict action " + actionName);
}
- if ("edit".equals(reason)) {
- return SVNConflictReason.EDITED;
- } else if (reason.contains("obstruct")) {
- return SVNConflictReason.OBSTRUCTED;
- } else if ("delete".equals(reason)) {
- return SVNConflictReason.DELETED;
- } else if (reason.contains("miss")) {
- return SVNConflictReason.MISSING;
- } else if (reason.contains("unversion")) {
- return SVNConflictReason.UNVERSIONED;
- } else if (reason.contains("add")) {
- return SVNConflictReason.ADDED;
- } else if (reason.contains("replace")) {
- return SVNConflictReason.REPLACED;
+
+ return action;
+ }
+
+ private SVNConflictReason parseConflictReason(@NotNull String reasonName) throws SAXException {
+ SVNConflictReason reason = SVNConflictReason.fromString(reasonName);
+ reason = reason != null ? reason : ourConflictReasons.get(reasonName);
+
+ if (reason == null) {
+ throw new SAXException("Can not parse conflict reason: " + reasonName);
}
- throw new SAXException("Can not parse conflict reason: " + reason);
+
+ return reason;
}
private SVNConflictVersion createVersion(final ConflictVersion version) throws SVNException, SAXException {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java
index f78569f..460f7cd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/SvnStatusHandler.java
@@ -15,12 +15,15 @@
*/
package org.jetbrains.idea.svn.commandLine;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Getter;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.portable.PortableStatus;
-import org.jetbrains.idea.svn.portable.StatusCallbackConvertor;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.wc.SVNInfo;
@@ -40,6 +43,40 @@
* Time: 7:59 PM
*/
public class SvnStatusHandler extends DefaultHandler {
+
+ private static final Logger LOG = Logger.getInstance(SvnStatusHandler.class);
+
+ public static final Map<String, SVNStatusType> ourStatusTypes = ContainerUtil.newHashMap();
+
+ static {
+ // TODO: Check STATUS_MERGED as it is marked deprecated
+ put(SVNStatusType.STATUS_ADDED, SVNStatusType.STATUS_CONFLICTED, SVNStatusType.STATUS_DELETED, SVNStatusType.STATUS_EXTERNAL,
+ SVNStatusType.STATUS_IGNORED, SVNStatusType.STATUS_INCOMPLETE, SVNStatusType.STATUS_MERGED, SVNStatusType.STATUS_MISSING,
+ SVNStatusType.STATUS_MODIFIED, SVNStatusType.STATUS_NONE, SVNStatusType.STATUS_NORMAL, SVNStatusType.STATUS_OBSTRUCTED,
+ SVNStatusType.STATUS_REPLACED, SVNStatusType.STATUS_UNVERSIONED);
+ }
+
+ private static void put(@NotNull SVNStatusType... statusTypes) {
+ for (SVNStatusType statusType : statusTypes) {
+ put(statusType);
+ }
+ }
+
+ private static void put(@NotNull SVNStatusType statusType) {
+ ourStatusTypes.put(statusType.toString(), statusType);
+ }
+
+ @Nullable
+ public static SVNStatusType getStatus(@NotNull String code) {
+ SVNStatusType result = ourStatusTypes.get(code);
+
+ if (result == null) {
+ LOG.info("Unknown status type " + code);
+ }
+
+ return result;
+ }
+
private String myChangelistName;
private List<PortableStatus> myDefaultListStatuses;
private MultiMap<String, PortableStatus> myCurrentListChanges;
@@ -330,13 +367,13 @@
private static SVNStatusType parseContentsStatus(Attributes attributes) throws SAXException {
final String item = attributes.getValue("item");
assertSAX(item != null);
- return StatusCallbackConvertor.convert(org.apache.subversion.javahl.types.Status.Kind.valueOf(item));
+ return getStatus(item);
}
private static SVNStatusType parsePropertiesStatus(Attributes attributes) throws SAXException {
final String props = attributes.getValue("props");
assertSAX(props != null);
- return StatusCallbackConvertor.convert(org.apache.subversion.javahl.types.Status.Kind.valueOf(props));
+ return getStatus(props);
}
private static class Fake extends ElementHandlerBase {
@@ -702,16 +739,7 @@
protected void updateStatus(Attributes attributes, PortableStatus status, SVNLockWrapper lock) throws SAXException {
final String path = attributes.getValue("path");
assertSAX(path != null);
- final File file;
- if (new File(path).isAbsolute()) {
- file = new File(path);
- } else {
- if (".".equals(path)) {
- file = myBase;
- } else {
- file = new File(myBase, path);
- }
- }
+ final File file = CommandUtil.resolvePath(myBase, path);
status.setFile(file);
final boolean exists = file.exists();
if (exists) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
index 6520c62..44d9d72 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/UpdateOutputLineConverter.java
@@ -169,7 +169,7 @@
}
private File createFile(String path) {
- return FileUtil.isAbsolute(path) ? new File(path) : new File(myBase, path);
+ return CommandUtil.resolvePath(myBase, path);
}
@Nullable
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
index 221ba2a..32b1dae 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/BranchConfigurationDialog.java
@@ -35,6 +35,9 @@
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigManager;
import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
import org.jetbrains.idea.svn.integrate.SvnBranchItem;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -57,7 +60,11 @@
private final SvnBranchConfigManager mySvnBranchConfigManager;
private final VirtualFile myRoot;
- public BranchConfigurationDialog(@NotNull final Project project, @NotNull final SvnBranchConfigurationNew configuration, final @NotNull String rootUrl, @NotNull final VirtualFile root, @NotNull String url) {
+ public BranchConfigurationDialog(@NotNull final Project project,
+ @NotNull final SvnBranchConfigurationNew configuration,
+ final @NotNull SVNURL rootUrl,
+ @NotNull final VirtualFile root,
+ @NotNull String url) {
super(project, true);
myRoot = root;
init();
@@ -95,7 +102,7 @@
.setAddAction(new AnActionButtonRunnable() {
@Override
public void run(AnActionButton button) {
- final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl);
+ final String selectedUrl = SelectLocationDialog.selectLocation(project, rootUrl.toDecodedString());
if (selectedUrl != null) {
if (!configuration.getBranchUrls().contains(selectedUrl)) {
configuration
@@ -127,27 +134,41 @@
}
private class TrunkUrlValidator extends DocumentAdapter {
- private final String myRootUrl;
- private final String myRootUrlPrefix;
+ private final SVNURL myRootUrl;
private final SvnBranchConfigurationNew myConfiguration;
- private TrunkUrlValidator(final String rootUrl, final SvnBranchConfigurationNew configuration) {
+ private TrunkUrlValidator(final SVNURL rootUrl, final SvnBranchConfigurationNew configuration) {
myRootUrl = rootUrl;
- myRootUrlPrefix = rootUrl + "/";
myConfiguration = configuration;
}
protected void textChanged(final DocumentEvent e) {
- final String currentValue = myTrunkLocationTextField.getText();
- final boolean valueOk = (currentValue != null) && (currentValue.equals(myRootUrl) || currentValue.startsWith(myRootUrlPrefix));
- final boolean prefixOk = (currentValue != null) && (currentValue.startsWith(myRootUrlPrefix)) &&
- (currentValue.length() > myRootUrlPrefix.length());
+ SVNURL url = parseUrl(myTrunkLocationTextField.getText());
- myTrunkLocationTextField.getButton().setEnabled(valueOk);
- if (prefixOk) {
- myConfiguration.setTrunkUrl(currentValue.endsWith("/") ? currentValue.substring(0, currentValue.length() - 1) : currentValue);
+ if (url != null) {
+ boolean isAncestor = SVNURLUtil.isAncestor(myRootUrl, url);
+ boolean areNotSame = isAncestor && !url.equals(myRootUrl);
+
+ myTrunkLocationTextField.getButton().setEnabled(isAncestor);
+ if (areNotSame) {
+ myConfiguration.setTrunkUrl(url.toDecodedString());
+ }
+ myErrorPrompt.setText(areNotSame ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl));
}
- myErrorPrompt.setText(prefixOk ? "" : SvnBundle.message("configure.branches.error.wrong.url", myRootUrl));
+ }
+
+ @Nullable
+ private SVNURL parseUrl(@NotNull String url) {
+ SVNURL result = null;
+
+ try {
+ result = SvnUtil.createUrl(url);
+ }
+ catch (SVNException e) {
+ myErrorPrompt.setText(e.getMessage());
+ }
+
+ return result;
}
}
@@ -180,7 +201,7 @@
if (wcRoot == null) {
return;
}
- final String rootUrl = wcRoot.getRepositoryUrl();
+ final SVNURL rootUrl = wcRoot.getRepositoryUrlUrl();
if (rootUrl == null) {
Messages.showErrorDialog(project, SvnBundle.message("configure.branches.error.no.connection.title"),
SvnBundle.message("configure.branches.title"));
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
index 046a134..e010105 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/CopiesPanel.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -225,7 +225,7 @@
"This will update your working copy to HEAD revision as well.",
"Set Working Copy Infinity Depth",
Messages.getWarningIcon());
- if (result == 0) {
+ if (result == Messages.OK) {
// update of view will be triggered by roots changed event
SvnCheckoutProvider.checkout(myVcs.getProject(), new File(wcInfo.getPath()), wcInfo.getRootUrl(), SVNRevision.HEAD,
SVNDepth.INFINITY, false, null, wcInfo.getFormat());
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java
index ed1f219..6591d98 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/LoadRecentBranchRevisions.java
@@ -115,9 +115,11 @@
for (Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>> pair : list) {
// do not take first since it's equal
if (myFirst > 0 && myFirst == pair.getFirst().getNumber()) continue;
- if (! QuickMerge.checkListForPaths(relativeLocal, relativeBranch, pair)) {
+ // TODO: Currently path filtering with QuickMerge.checkListForPaths is not applied as it removes some necessary revisions
+ // TODO: (merge revisions) from list. Check if that filtering was really necessary here - in "Quick merge".
+// if (! QuickMerge.checkListForPaths(relativeLocal, relativeBranch, pair)) {
myCommittedChangeLists.add(pair.getFirst());
- }
+// }
}
try {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java
index d515b04..20077fc 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/QuickMerge.java
@@ -60,6 +60,7 @@
import org.tmatesoft.svn.core.SVNLogEntryPath;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import java.io.File;
import java.io.IOException;
@@ -115,7 +116,12 @@
@Override
public void run(ContinuationContext continuationContext) {
- if (SVNPathUtil.isAncestor(mySourceUrl, myWcInfo.getRootUrl()) || SVNPathUtil.isAncestor(myWcInfo.getRootUrl(), mySourceUrl)) {
+ SVNURL url = parseUrl(continuationContext);
+ if (url == null) {
+ return;
+ }
+
+ if (SVNURLUtil.isAncestor(url, myWcInfo.getUrl()) || SVNURLUtil.isAncestor(myWcInfo.getUrl(), url)) {
finishWithError(continuationContext, "Cannot merge from self", true);
return;
}
@@ -124,6 +130,20 @@
continuationContext.cancelEverything();
}
}
+
+ @Nullable
+ private SVNURL parseUrl(ContinuationContext continuationContext) {
+ SVNURL url = null;
+
+ try {
+ url = SvnUtil.createUrl(mySourceUrl);
+ }
+ catch (SVNException e) {
+ finishWithError(continuationContext, e.getMessage(), true);
+ }
+
+ return url;
+ }
}
private class CheckRepositorySupportsMergeinfo extends TaskDescriptor {
@@ -465,6 +485,13 @@
// true if errors found
static boolean checkListForPaths(String relativeLocal,
String relativeBranch, Pair<SvnChangeList, TreeStructureNode<SVNLogEntry>> pair) {
+ // TODO: Such filtering logic is not clear enough so far (and probably not correct for all cases - for instance when we perform merge
+ // TODO: from branch1 to branch2 and have revision which contain merge changes from branch3 to branch1.
+ // TODO: In this case paths of child log entries will not contain neither urls from branch1 nor from branch2 - and checkEntry() method
+ // TODO: will return true => so such revision will not be used (and displayed) further.
+
+ // TODO: Why do we check entries recursively - we have a revision - set of changes in the "merge from" branch? Why do we need to check
+ // TODO: where they came from - we want avoid some circular merges or what? Does subversion itself perform such checks or not?
final List<TreeStructureNode<SVNLogEntry>> children = pair.getSecond().getChildren();
boolean localChange = false;
for (TreeStructureNode<SVNLogEntry> child : children) {
@@ -497,6 +524,10 @@
}
// true if errors found
+ // checks if either some changed path is in current branch => treat as local change
+ // or if no changed paths in current branch, checks if at least one path in "merge from" branch
+ // NOTE: this fails for "merge-source" log entries from other branches - when all changed paths are from some
+ // third branch - this logic treats such log entry as local.
private static boolean checkForEntry(final SVNLogEntry entry, final String localURL, String relativeBranch) {
boolean atLeastOneUnderBranch = false;
final Map map = entry.getChangedPaths();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
index 9856d30..ae9fd51 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/RepositoryBrowserDialog.java
@@ -35,7 +35,6 @@
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vcs.*;
-import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangesUtil;
import com.intellij.openapi.vcs.changes.ContentRevision;
@@ -47,6 +46,7 @@
import com.intellij.util.IconUtil;
import com.intellij.util.NotNullFunction;
import com.intellij.util.WaitForProgressToShow;
+import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -57,7 +57,6 @@
import org.jetbrains.idea.svn.dialogs.browserCache.Expander;
import org.jetbrains.idea.svn.dialogs.browserCache.KeepingExpandedExpander;
import org.jetbrains.idea.svn.dialogs.browserCache.SyntheticWorker;
-import org.jetbrains.idea.svn.history.SvnHistoryProvider;
import org.jetbrains.idea.svn.history.SvnRepositoryLocation;
import org.jetbrains.idea.svn.status.SvnDiffEditor;
import org.tmatesoft.svn.core.*;
@@ -355,9 +354,10 @@
}
boolean isDirectory = node.getUserObject() instanceof SVNURL ||
(node.getSVNDirEntry() != null && node.getSVNDirEntry().getKind() == SVNNodeKind.DIR);
- AbstractVcsHelper.getInstance(myProject).showFileHistory(new SvnHistoryProvider(myVCS),
- VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(node.getURL().toString(), isDirectory),
- myVCS, node.getURL().toString());
+ String url = node.getURL().toDecodedString();
+
+ AbstractVcsHelper.getInstance(myProject)
+ .showFileHistory(myVCS.getVcsHistoryProvider(), VcsUtil.getFilePathOnNonLocal(url, isDirectory), myVCS, url);
node.reload(false);
}
}
@@ -489,7 +489,7 @@
if (url != null) {
int rc = Messages.showYesNoDialog(myBrowserComponent.getProject(), SvnBundle.message("repository.browser.discard.location.prompt", url.toString()),
SvnBundle.message("repository.browser.discard.location.title"), Messages.getQuestionIcon());
- if (rc != 0) {
+ if (rc != Messages.YES) {
return;
}
SvnApplicationSettings.getInstance().removeCheckoutURL(url.toString());
@@ -661,7 +661,7 @@
final int result =
Messages.showOkCancelDialog(myProject, "You are about to move folder named '" + lastFolder +
"'. Are you sure?", SvnBundle.message(myDialogTitleKey), Messages.getWarningIcon());
- if (DialogWrapper.CANCEL_EXIT_CODE == result) return;
+ if (Messages.OK == result) return;
}
}
String message = dialog.getCommitMessage();
@@ -1062,7 +1062,7 @@
if (dirEntry != null) {
if (dirEntry.getRepositoryRoot() != null) {
if (! dirEntry.getRepositoryRoot().equals(url)) {
- relativePath = SVNPathUtil.getRelativePath(dirEntry.getRepositoryRoot().toString(), url.toString());
+ relativePath = SVNPathUtil.getRelativePath(dirEntry.getRepositoryRoot().toString(), url.toDecodedString());
}
} else {
relativePath = dirEntry.getRelativePath();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java
index dd22ac5..bee4101 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnFormatWorker.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,8 +20,6 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.AbstractVcsHelper;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.VcsException;
@@ -44,7 +42,6 @@
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Iterator;
import java.util.List;
public class SvnFormatWorker extends Task.Backgroundable {
@@ -71,30 +68,6 @@
this(project, newFormat, Collections.singletonList(wcInfo));
}
- public void checkForOutsideCopies() {
- boolean canceled = false;
- for (Iterator<WCInfo> iterator = myWcInfos.iterator(); iterator.hasNext();) {
- final WCInfo wcInfo = iterator.next();
- if (! wcInfo.isIsWcRoot()) {
- File path = new File(wcInfo.getPath());
- path = SvnUtil.getWorkingCopyRoot(path);
- int result = Messages.showYesNoCancelDialog(SvnBundle.message("upgrade.format.clarify.for.outside.copies.text", path),
- SvnBundle.message("action.change.wcopy.format.task.title"),
- Messages.getWarningIcon());
- if (DialogWrapper.CANCEL_EXIT_CODE == result) {
- canceled = true;
- break;
- } else if (DialogWrapper.OK_EXIT_CODE != result) {
- // no - for this copy only. maybe other
- iterator.remove();
- }
- }
- }
- if (canceled) {
- myWcInfos.clear();
- }
- }
-
public boolean haveStuffToConvert() {
return ! myWcInfos.isEmpty();
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java
index 37b4f9d..5be10cf 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/SvnInteractiveAuthenticationProvider.java
@@ -20,11 +20,13 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.MessageType;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.ui.VcsBalloonProblemNotifier;
-import com.intellij.util.SystemProperties;
import com.intellij.util.WaitForProgressToShow;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnAuthenticationManager;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnConfiguration;
@@ -81,18 +83,13 @@
final boolean authCredsOn = authMayBeStored && myManager.getHostOptionsProvider().getHostOptions(url).isAuthStorageEnabled();
final String userName =
- previousAuth != null && previousAuth.getUserName() != null ? previousAuth.getUserName() : SystemProperties.getUserName();
+ previousAuth != null && previousAuth.getUserName() != null ? previousAuth.getUserName() : myManager.getDefaultUsername(kind, url);
if (ISVNAuthenticationManager.PASSWORD.equals(kind)) {// || ISVNAuthenticationManager.USERNAME.equals(kind)) {
command = new Runnable() {
public void run() {
SimpleCredentialsDialog dialog = new SimpleCredentialsDialog(myProject);
dialog.setup(realm, userName, authCredsOn);
- if (errorMessage == null) {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
- }
- else {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed"));
- }
+ setTitle(dialog, errorMessage);
dialog.show();
if (dialog.isOK()) {
result[0] = new SVNPasswordAuthentication(dialog.getUserName(), dialog.getPassword(), dialog.isSaveAllowed(), url, false);
@@ -108,12 +105,7 @@
public void run() {
UserNameCredentialsDialog dialog = new UserNameCredentialsDialog(myProject);
dialog.setup(realm, userName, authCredsOn);
- if (errorMessage == null) {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
- }
- else {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed"));
- }
+ setTitle(dialog, errorMessage);
dialog.show();
if (dialog.isOK()) {
result[0] = new SVNUserNameAuthentication(dialog.getUserName(), dialog.isSaveAllowed(), url, false);
@@ -125,12 +117,7 @@
command = new Runnable() {
public void run() {
SSHCredentialsDialog dialog = new SSHCredentialsDialog(myProject, realm, userName, authCredsOn, url.getPort());
- if (errorMessage == null) {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
- }
- else {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed"));
- }
+ setTitle(dialog, errorMessage);
dialog.show();
if (dialog.isOK()) {
int port = dialog.getPortNumber();
@@ -158,12 +145,7 @@
if (!StringUtil.isEmptyOrSpaces(file)) {
dialog.setFile(file);
}
- if (errorMessage == null) {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required"));
- }
- else {
- dialog.setTitle(SvnBundle.message("dialog.title.authentication.required.was.failed"));
- }
+ setTitle(dialog, errorMessage);
dialog.show();
if (dialog.isOK()) {
result[0] = new SVNSSLAuthentication(new File(dialog.getCertificatePath()), String.valueOf(dialog.getCertificatePassword()),
@@ -184,6 +166,12 @@
return result[0];
}
+ private static void setTitle(@NotNull DialogWrapper dialog, @Nullable SVNErrorMessage errorMessage) {
+ dialog.setTitle(errorMessage == null
+ ? SvnBundle.message("dialog.title.authentication.required")
+ : SvnBundle.message("dialog.title.authentication.required.was.failed"));
+ }
+
public int acceptServerAuthentication(final SVNURL url, String realm, final Object certificate, final boolean resultMayBeStored) {
final int[] result = new int[1];
Runnable command;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java
index 19a8832..f77f33d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/ToBeMergedDialog.java
@@ -235,13 +235,15 @@
private void initUI() {
final ListSelectionListener selectionListener = new ListSelectionListener() {
+ @Override
public void valueChanged(ListSelectionEvent e) {
final List objects = myRevisionsList.getSelectedObjects();
myRepositoryChangesBrowser.setChangesToDisplay(Collections.<Change>emptyList());
myAlreadyMerged.clear();
- if (objects != null && (!objects.isEmpty())) {
+ if ((!objects.isEmpty())) {
final List<CommittedChangeList> lists =
ObjectsConvertor.convert(objects, new Convertor<Object, CommittedChangeList>() {
+ @Override
public CommittedChangeList convert(Object o) {
if (o instanceof CommittedChangeList) {
final CommittedChangeList cl = (CommittedChangeList)o;
@@ -296,33 +298,29 @@
myRevisionsList.setShowGrid(false);
final AbstractBaseTagMouseListener mouseListener = new AbstractBaseTagMouseListener() {
@Override
- public Object getTagAt(MouseEvent e) {
- Object tag = null;
+ public Object getTagAt(@NotNull MouseEvent e) {
JTable table = (JTable)e.getSource();
int row = table.rowAtPoint(e.getPoint());
int column = table.columnAtPoint(e.getPoint());
if (row == -1 || column == -1) return null;
listCellRenderer.customizeCellRenderer(table, table.getValueAt(row, column), table.isRowSelected(row), false, row, column);
- final ColoredTreeCellRenderer renderer = listCellRenderer.myRenderer;
- final Rectangle rc = table.getCellRect(row, column, false);
- int index = renderer.findFragmentAt(e.getPoint().x - rc.x);
- if (index >= 0) {
- tag = renderer.getFragmentTag(index);
- }
- return tag;
+ return listCellRenderer.myRenderer.getFragmentTagAt(e.getPoint().x - table.getCellRect(row, column, false).x);
}
};
mouseListener.installOn(myRevisionsList);
final PagedListWithActions.InnerComponentManager<CommittedChangeList> listsManager =
new PagedListWithActions.InnerComponentManager<CommittedChangeList>() {
+ @Override
public Component getComponent() {
return myRevisionsList;
}
+ @Override
public void setData(List<CommittedChangeList> committedChangeLists) {
flatModel.setItems(committedChangeLists);
flatModel.fireTableDataChanged();
}
+ @Override
public void refresh() {
myRevisionsList.revalidate();
myRevisionsList.repaint();
@@ -353,11 +351,14 @@
private void setChangesDecorator() {
myRepositoryChangesBrowser.setDecorator(new ChangeNodeDecorator() {
+ @Override
public void decorate(Change change, SimpleColoredComponent component, boolean isShowFlatten) {
}
+ @Override
public List<Pair<String, Stress>> stressPartsOfFileName(Change change, String parentPath) {
return null;
}
+ @Override
public void preDecorate(Change change, ChangesBrowserNodeRenderer renderer, boolean showFlatten) {
if (myAlreadyMerged.contains(change)) {
renderer.append(" [already merged] ", SimpleTextAttributes.REGULAR_BOLD_ATTRIBUTES);
@@ -370,7 +371,7 @@
final int checkboxWidth = new JCheckBox().getPreferredSize().width;
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
final int idx = myRevisionsList.rowAtPoint(e.getPoint());
if (idx >= 0) {
final Rectangle baseRect = myRevisionsList.getCellRect(idx, 0, false);
@@ -391,7 +392,9 @@
public void keyReleased(KeyEvent e) {
if (KeyEvent.VK_SPACE == e.getKeyCode()) {
final List selected = myRevisionsList.getSelectedObjects();
- if (selected == null || selected.isEmpty()) return;
+ if (selected.isEmpty()) {
+ return;
+ }
for (Object o : selected) {
if (o instanceof SvnChangeList) {
@@ -512,6 +515,7 @@
}
}
+ @Override
public final Component getTableCellRendererComponent(
JTable table,
Object value,
@@ -525,8 +529,6 @@
}
}
- private final static int ourPageSize = 30;
-
private static final ColumnInfo FAKE_COLUMN = new ColumnInfo<CommittedChangeList, CommittedChangeList>("fake column"){
@Override
public CommittedChangeList valueOf(CommittedChangeList committedChangeList) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/CheckoutOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/CheckoutOptionsDialog.java
index 1f68c99..b5c3782 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/CheckoutOptionsDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/dialogs/browser/CheckoutOptionsDialog.java
@@ -62,7 +62,7 @@
public CheckoutOptionsDialog(final Project project, SVNURL url, File target, final VirtualFile root, final String relativePath) {
super(project, true);
myRelativePath = relativePath;
- final String urlText = url.toString();
+ final String urlText = url.toDecodedString();
myUrlLabel.setText(urlText);
fillTargetList(target);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
new file mode 100644
index 0000000..b774fe6
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CmdDiffClient.java
@@ -0,0 +1,179 @@
+/*
+ * 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.idea.svn.diff;
+
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.changes.CurrentContentRevision;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.vcsUtil.VcsUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnStatusConvertor;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.*;
+import org.jetbrains.idea.svn.history.SvnRepositoryContentRevision;
+import org.tmatesoft.svn.core.SVNNodeKind;
+import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.annotation.XmlAttribute;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlValue;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class CmdDiffClient extends BaseSvnClient implements DiffClient {
+
+ @Override
+ public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
+ // TODO: Currently implemented only for "Compare with Branch" action - target1 is assumed to be file, target2 - repository url
+ // Such combination (file and url) with "--summarize" option is supported only in svn 1.8.
+ // For svn 1.7 "--summarize" is only supported when both targets are repository urls.
+ assertDirectory(target1);
+ assertUrl(target2);
+
+ List<String> parameters = new ArrayList<String>();
+ CommandUtil.put(parameters, target1);
+ CommandUtil.put(parameters, target2);
+ parameters.add("--xml");
+ parameters.add("--summarize");
+
+ CommandExecutor executor = CommandUtil.execute(myVcs, target1, SvnCommandName.diff, parameters, null);
+ return parseOutput(target1, target2, executor);
+ }
+
+ private List<Change> parseOutput(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull CommandExecutor executor)
+ throws SvnBindException {
+ try {
+ DiffInfo diffInfo = CommandUtil.parse(executor.getOutput(), DiffInfo.class);
+ List<Change> result = ContainerUtil.newArrayList();
+
+ if (diffInfo != null && diffInfo.paths != null) {
+ for (DiffPath path : diffInfo.paths.diffPaths) {
+ result.add(createChange(target1, target2, path));
+ }
+ }
+
+ return result;
+ }
+ catch (JAXBException e) {
+ throw new SvnBindException(e);
+ }
+ }
+
+ private ContentRevision createRemoteRevision(@NotNull FilePath remotePath, @NotNull FilePath localPath, @NotNull FileStatus status) {
+ // explicitly use local path for deleted items - so these items will be correctly displayed as deleted under local working copy node
+ // and not as deleted under remote branch node (in ChangesBrowser)
+ // NOTE, that content is still retrieved using remotePath.
+ return SvnRepositoryContentRevision
+ .create(myVcs, remotePath, status == FileStatus.DELETED ? localPath : null, SVNRevision.HEAD.getNumber());
+ }
+
+ private static ContentRevision createLocalRevision(@NotNull FilePath path) {
+ return CurrentContentRevision.create(path);
+ }
+
+ @NotNull
+ private Change createChange(@NotNull SvnTarget target1, @NotNull SvnTarget target2, @NotNull DiffPath diffPath) throws SvnBindException {
+ // TODO: 1) Unify logic of creating Change instance with SvnDiffEditor and SvnChangeProviderContext
+ // TODO: 2) If some directory is switched, files inside it are returned as modified in "svn diff --summarize", even if they are equal
+ // TODO: to branch files by content - possibly add separate processing of all switched files
+ // TODO: 3) Properties change is currently not added as part of result change like in SvnChangeProviderContext.patchWithPropertyChange
+
+ File oldTarget = CommandUtil.resolvePath(target1.getFile(), diffPath.path);
+ String relativePath = FileUtil.getRelativePath(target1.getFile(), oldTarget);
+
+ if (relativePath == null) {
+ throw new SvnBindException("Could not get relative path for " + target1.getFile() + " and " + oldTarget);
+ }
+
+ FilePath localPath = VcsUtil.getFilePath(oldTarget, diffPath.isDirectory());
+ FilePath remotePath = VcsUtil
+ .getFilePathOnNonLocal(SVNPathUtil.append(target2.getPathOrUrlDecodedString(), FileUtil.toSystemIndependentName(relativePath)),
+ diffPath.isDirectory());
+
+ FileStatus status = SvnStatusConvertor
+ .convertStatus(SvnStatusHandler.getStatus(diffPath.itemStatus), SvnStatusHandler.getStatus(diffPath.propertiesStatus));
+
+ ContentRevision beforeRevision = status == FileStatus.ADDED ? null : createRemoteRevision(remotePath, localPath, status);
+ ContentRevision afterRevision = status == FileStatus.DELETED ? null : createLocalRevision(localPath);
+
+ return createChange(status, beforeRevision, afterRevision);
+ }
+
+ @NotNull
+ private static Change createChange(@NotNull final FileStatus status,
+ @Nullable final ContentRevision beforeRevision,
+ @Nullable final ContentRevision afterRevision) {
+ // isRenamed() and isMoved() are always false here not to have text like "moved from ..." in changes window - by default different
+ // paths in before and after revisions are treated as move, but this is not the case for "Compare with Branch"
+ return new Change(beforeRevision, afterRevision, status) {
+ @Override
+ public boolean isRenamed() {
+ return false;
+ }
+
+ @Override
+ public boolean isMoved() {
+ return false;
+ }
+ };
+ }
+
+ @XmlRootElement(name = "diff")
+ public static class DiffInfo {
+
+ @XmlElement(name = "paths")
+ public DiffPaths paths;
+ }
+
+ public static class DiffPaths {
+
+ @XmlElement(name = "path")
+ public List<DiffPath> diffPaths = new ArrayList<DiffPath>();
+ }
+
+ public static class DiffPath {
+
+ @XmlAttribute(name = "kind")
+ public String kind;
+
+ @XmlAttribute(name = "props")
+ public String propertiesStatus;
+
+ @XmlAttribute(name = "item")
+ public String itemStatus;
+
+ @XmlValue
+ public String path;
+
+ public boolean isDirectory() {
+ return SVNNodeKind.DIR.equals(SVNNodeKind.parseKind(kind));
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java
new file mode 100644
index 0000000..a8e0ca9
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/CompareWithBranchAction.java
@@ -0,0 +1,81 @@
+/*
+ * 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 org.jetbrains.idea.svn.diff;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.CommonDataKeys;
+import com.intellij.openapi.project.DumbAware;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.FileStatus;
+import com.intellij.openapi.vcs.FileStatusManager;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.actions.SelectBranchPopup;
+import org.jetbrains.idea.svn.branchConfig.SvnBranchConfigurationNew;
+
+/**
+ * @author yole
+ */
+public class CompareWithBranchAction extends AnAction implements DumbAware {
+
+ public void actionPerformed(AnActionEvent e) {
+ Project project = e.getData(CommonDataKeys.PROJECT);
+ assert project != null;
+ final VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
+
+ SelectBranchPopup
+ .show(project, virtualFile, new MyBranchSelectedCallback(virtualFile), SvnBundle.message("compare.with.branch.popup.title"));
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ Project project = e.getData(CommonDataKeys.PROJECT);
+ VirtualFile virtualFile = e.getData(CommonDataKeys.VIRTUAL_FILE);
+ e.getPresentation().setEnabled(isEnabled(project, virtualFile));
+ }
+
+ private static boolean isEnabled(final Project project, final VirtualFile virtualFile) {
+ if (project == null || virtualFile == null) {
+ return false;
+ }
+ final FileStatus fileStatus = FileStatusManager.getInstance(project).getStatus(virtualFile);
+ if (fileStatus == FileStatus.UNKNOWN || fileStatus == FileStatus.ADDED || fileStatus == FileStatus.IGNORED) {
+ return false;
+ }
+ return true;
+ }
+
+ private static class MyBranchSelectedCallback implements SelectBranchPopup.BranchSelectedCallback {
+
+ @NotNull private final VirtualFile myVirtualFile;
+
+ public MyBranchSelectedCallback(@NotNull VirtualFile virtualFile) {
+ myVirtualFile = virtualFile;
+ }
+
+ public void branchSelected(Project project, SvnBranchConfigurationNew configuration, String url, long revision) {
+ ElementWithBranchComparer comparer =
+ myVirtualFile.isDirectory()
+ ? new DirectoryWithBranchComparer(project, myVirtualFile, url, revision)
+ : new FileWithBranchComparer(project, myVirtualFile, url, revision);
+
+ comparer.run();
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
new file mode 100644
index 0000000..a9678be
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DiffClient.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.diff;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.SvnClient;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public interface DiffClient extends SvnClient {
+
+ List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException;
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
new file mode 100644
index 0000000..48ba029
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/DirectoryWithBranchComparer.java
@@ -0,0 +1,204 @@
+/*
+ * 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.idea.svn.diff;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.AbstractVcsHelper;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnConfiguration;
+import org.jetbrains.idea.svn.SvnProgressCanceller;
+import org.jetbrains.idea.svn.WorkingCopyFormat;
+import org.jetbrains.idea.svn.status.SvnDiffEditor;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor;
+import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
+import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaInfo;
+import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry;
+import org.tmatesoft.svn.core.internal.wc.admin.SVNReporter;
+import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess;
+import org.tmatesoft.svn.core.internal.wc17.SVNReporter17;
+import org.tmatesoft.svn.core.internal.wc17.SVNWCContext;
+import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.wc.ISVNEventHandler;
+import org.tmatesoft.svn.core.wc.SVNEvent;
+import org.tmatesoft.svn.core.wc.SVNInfo;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+import org.tmatesoft.svn.util.SVNDebugLog;
+import org.tmatesoft.svn.util.SVNLogType;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class DirectoryWithBranchComparer extends ElementWithBranchComparer {
+
+ @NotNull private final StringBuilder titleBuilder = new StringBuilder();
+ @NotNull private final List<Change> changes = new ArrayList<Change>();
+
+ public DirectoryWithBranchComparer(@NotNull Project project,
+ @NotNull VirtualFile virtualFile,
+ @NotNull String branchUrl,
+ long branchRevision) {
+ super(project, virtualFile, branchUrl, branchRevision);
+ }
+
+ @Override
+ protected void compare() throws SVNException, VcsException {
+ titleBuilder.append(SvnBundle.message("repository.browser.compare.title", myElementUrl,
+ FileUtil.toSystemDependentName(myVirtualFile.getPresentableUrl())));
+
+ final File ioFile = new File(myVirtualFile.getPath());
+ WorkingCopyFormat format = myVcs.getWorkingCopyFormat(ioFile);
+
+ if (WorkingCopyFormat.ONE_DOT_EIGHT.equals(format)) {
+ // svn 1.7 command line "--summarize" option for "diff" command does not support comparing working copy directories with repository
+ // directories - that is why command line is only used explicitly for svn 1.8
+ compareWithCommandLine();
+ }
+ else if (WorkingCopyFormat.ONE_DOT_SEVEN.equals(format)) {
+ report17DirDiff();
+ }
+ else {
+ report16DirDiff();
+ }
+ }
+
+ private void compareWithCommandLine() throws VcsException {
+ SvnTarget target1 = SvnTarget.fromFile(new File(myVirtualFile.getPath()));
+ SvnTarget target2 = SvnTarget.fromURL(myElementUrl);
+
+ changes.addAll(myVcs.getFactory(target1).createDiffClient().compare(target1, target2));
+ }
+
+ private void report17DirDiff() throws SVNException {
+ final File ioFile = new File(myVirtualFile.getPath());
+ final SVNInfo info1 = myVcs.getInfo(ioFile, SVNRevision.HEAD);
+
+ if (info1 == null) {
+ SVNErrorMessage err =
+ SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", myVirtualFile.getPath());
+ SVNErrorManager.error(err, SVNLogType.WC);
+ }
+ else if (info1.getURL() == null) {
+ SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", myVirtualFile.getPath());
+ SVNErrorManager.error(err, SVNLogType.WC);
+ }
+
+ final SVNReporter17 reporter17 =
+ new SVNReporter17(ioFile, new SVNWCContext(SvnConfiguration.getInstance(myProject).getOptions(myProject), new ISVNEventHandler() {
+ @Override
+ public void handleEvent(SVNEvent event, double progress) throws SVNException {
+ }
+
+ @Override
+ public void checkCancelled() throws SVNCancelException {
+ }
+ }),
+ false, true, SVNDepth.INFINITY, false, false, true, false,
+ SVNDebugLog.getDefaultLog());
+ SVNRepository repository = null;
+ SVNRepository repository2 = null;
+ try {
+ repository = myVcs.createRepository(info1.getURL());
+ long rev = repository.getLatestRevision();
+ repository2 = myVcs.createRepository(myElementUrl.toString());
+ SvnDiffEditor diffEditor = new SvnDiffEditor(myVirtualFile, repository2, rev, true);
+ repository.diff(myElementUrl, rev, rev, null, true, SVNDepth.INFINITY, false, reporter17,
+ SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null));
+ changes.addAll(diffEditor.getChangesMap().values());
+ }
+ finally {
+ if (repository != null) {
+ repository.closeSession();
+ }
+ if (repository2 != null) {
+ repository2.closeSession();
+ }
+ }
+ }
+
+ private void report16DirDiff() throws SVNException {
+ // here there's 1.6 copy so ok to use SVNWCAccess
+ final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
+ wcAccess.setOptions(myVcs.getSvnOptions());
+ SVNRepository repository = null;
+ SVNRepository repository2 = null;
+ try {
+ SVNAdminAreaInfo info = wcAccess.openAnchor(new File(myVirtualFile.getPath()), false, SVNWCAccess.INFINITE_DEPTH);
+ File anchorPath = info.getAnchor().getRoot();
+ String target = "".equals(info.getTargetName()) ? null : info.getTargetName();
+
+ SVNEntry anchorEntry = info.getAnchor().getEntry("", false);
+ if (anchorEntry == null) {
+ SVNErrorMessage err =
+ SVNErrorMessage.create(SVNErrorCode.ENTRY_NOT_FOUND, "''{0}'' is not under version control", anchorPath);
+ SVNErrorManager.error(err, SVNLogType.WC);
+ }
+ else if (anchorEntry.getURL() == null) {
+ SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.ENTRY_MISSING_URL, "''{0}'' has no URL", anchorPath);
+ SVNErrorManager.error(err, SVNLogType.WC);
+ }
+
+ SVNURL anchorURL = anchorEntry.getSVNURL();
+ SVNReporter reporter = new SVNReporter(info, info.getAnchor().getFile(info.getTargetName()), false, true, SVNDepth.INFINITY,
+ false, false, true, SVNDebugLog.getDefaultLog());
+
+ repository = myVcs.createRepository(anchorURL.toString());
+ long rev = repository.getLatestRevision();
+ repository2 = myVcs.createRepository((target == null) ? myElementUrl.toString() : myElementUrl.removePathTail().toString());
+ SvnDiffEditor diffEditor = new SvnDiffEditor((target == null) ? myVirtualFile : myVirtualFile.getParent(),
+ repository2, rev, true);
+ repository.diff(myElementUrl, rev, rev, target, true, true, false, reporter,
+ SVNCancellableEditor.newInstance(diffEditor, new SvnProgressCanceller(), null));
+ changes.addAll(diffEditor.getChangesMap().values());
+ }
+ finally {
+ wcAccess.close();
+ if (repository != null) {
+ repository.closeSession();
+ }
+ if (repository2 != null) {
+ repository2.closeSession();
+ }
+ }
+ }
+
+ @Override
+ protected void onCancel() {
+ changes.clear();
+ }
+
+ @Override
+ protected void showResult() {
+ if (!changes.isEmpty()) {
+ AbstractVcsHelper.getInstance(myProject).showWhatDiffersBrowser(null, changes, titleBuilder.toString());
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return SvnBundle.message("progress.computing.difference");
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java
new file mode 100644
index 0000000..2d67ce7
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/ElementWithBranchComparer.java
@@ -0,0 +1,163 @@
+/*
+ * 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.idea.svn.diff;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.util.WaitForProgressToShow;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+import org.tmatesoft.svn.core.SVNCancelException;
+import org.tmatesoft.svn.core.SVNErrorCode;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+
+import java.io.File;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public abstract class ElementWithBranchComparer {
+
+ private static final Logger LOG = Logger.getInstance(ElementWithBranchComparer.class);
+
+ @NotNull protected final Project myProject;
+ @NotNull protected final SvnVcs myVcs;
+ @NotNull protected final VirtualFile myVirtualFile;
+ @NotNull protected final String myBranchUrl;
+ protected final long myBranchRevision;
+ protected SVNURL myElementUrl;
+
+ ElementWithBranchComparer(@NotNull Project project,
+ @NotNull VirtualFile virtualFile,
+ @NotNull String branchUrl,
+ long branchRevision) {
+ myProject = project;
+ myVcs = SvnVcs.getInstance(myProject);
+ myVirtualFile = virtualFile;
+ myBranchUrl = branchUrl;
+ myBranchRevision = branchRevision;
+ }
+
+ public void run() {
+ new Task.Modal(myProject, getTitle(), true) {
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ try {
+ beforeCompare();
+ myElementUrl = resolveElementUrl();
+ if (myElementUrl == null) {
+ reportNotFound();
+ }
+ else {
+ compare();
+ }
+ }
+ catch (SVNCancelException ex) {
+ ElementWithBranchComparer.this.onCancel();
+ }
+ catch (SVNException ex) {
+ reportException(new SvnBindException(ex));
+ }
+ catch (SvnBindException ex) {
+ reportException(ex);
+ }
+ catch (VcsException ex) {
+ reportGeneralException(ex);
+ }
+ }
+ }.queue();
+ showResult();
+ }
+
+ protected void beforeCompare() {
+ }
+
+ protected abstract void compare() throws SVNException, VcsException;
+
+ protected abstract void showResult();
+
+ protected void onCancel() {
+ }
+
+ public abstract String getTitle();
+
+ @Nullable
+ protected SVNURL resolveElementUrl() throws SVNException {
+ final SvnFileUrlMapping urlMapping = myVcs.getSvnFileUrlMapping();
+ final File file = new File(myVirtualFile.getPath());
+ final SVNURL fileUrl = urlMapping.getUrlForFile(file);
+ if (fileUrl == null) {
+ return null;
+ }
+
+ final String fileUrlString = fileUrl.toString();
+ final RootUrlInfo rootMixed = urlMapping.getWcRootForUrl(fileUrlString);
+ if (rootMixed == null) {
+ return null;
+ }
+
+ final SVNURL thisBranchForUrl = SvnUtil.getBranchForUrl(myVcs, rootMixed.getVirtualFile(), fileUrlString);
+ if (thisBranchForUrl == null) {
+ return null;
+ }
+
+ final String relativePath = SVNPathUtil.getRelativePath(thisBranchForUrl.toString(), fileUrlString);
+ return SVNURL.parseURIEncoded(SVNPathUtil.append(myBranchUrl, relativePath));
+ }
+
+ private void reportException(final SvnBindException e) {
+ if (e.contains(SVNErrorCode.RA_ILLEGAL_URL) ||
+ e.contains(SVNErrorCode.CLIENT_UNRELATED_RESOURCES) ||
+ e.contains(SVNErrorCode.RA_DAV_PATH_NOT_FOUND) ||
+ e.contains(SVNErrorCode.FS_NOT_FOUND) ||
+ e.contains(SVNErrorCode.ILLEGAL_TARGET)) {
+ reportNotFound();
+ }
+ else {
+ reportGeneralException(e);
+ }
+ }
+
+ private void reportGeneralException(final Exception e) {
+ WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
+ public void run() {
+ Messages.showMessageDialog(myProject, e.getMessage(),
+ SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon());
+ }
+ }, null, myProject);
+ LOG.info(e);
+ }
+
+ private void reportNotFound() {
+ WaitForProgressToShow.runOrInvokeLaterAboveProgress(new Runnable() {
+ public void run() {
+ Messages.showMessageDialog(myProject,
+ SvnBundle
+ .message("compare.with.branch.location.error", myVirtualFile.getPresentableUrl(), myBranchUrl),
+ SvnBundle.message("compare.with.branch.error.title"), Messages.getErrorIcon());
+ }
+ }, null, myProject);
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java
new file mode 100644
index 0000000..b4b4e3c
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/FileWithBranchComparer.java
@@ -0,0 +1,82 @@
+/*
+ * 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.idea.svn.diff;
+
+import com.intellij.openapi.diff.DiffManager;
+import com.intellij.openapi.diff.FileContent;
+import com.intellij.openapi.diff.SimpleContent;
+import com.intellij.openapi.diff.SimpleDiffRequest;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.ProgressManager;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.openapi.vfs.VirtualFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class FileWithBranchComparer extends ElementWithBranchComparer {
+
+ @NotNull private final Ref<byte[]> content = new Ref<byte[]>();
+ @NotNull private final StringBuilder remoteTitleBuilder = new StringBuilder();
+ @NotNull private final Ref<Boolean> success = new Ref<Boolean>();
+
+ public FileWithBranchComparer(@NotNull Project project,
+ @NotNull VirtualFile virtualFile,
+ @NotNull String branchUrl,
+ long branchRevision) {
+ super(project, virtualFile, branchUrl, branchRevision);
+ }
+
+ @Override
+ protected void beforeCompare() {
+ final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
+ if (indicator != null) {
+ indicator.setIndeterminate(true);
+ }
+ }
+
+ @Override
+ protected void compare() throws SVNException, VcsException {
+ remoteTitleBuilder.append(myElementUrl);
+ content.set(SvnUtil.getFileContents(myVcs, SvnTarget.fromURL(myElementUrl), SVNRevision.HEAD, SVNRevision.UNDEFINED));
+ success.set(true);
+ }
+
+ @Override
+ protected void showResult() {
+ if (!success.isNull()) {
+ SimpleDiffRequest req = new SimpleDiffRequest(myProject, SvnBundle.message("compare.with.branch.diff.title"));
+ req.setContents(new SimpleContent(CharsetToolkit.bytesToString(content.get(), myVirtualFile.getCharset())),
+ new FileContent(myProject, myVirtualFile));
+ req.setContentTitles(remoteTitleBuilder.toString(), myVirtualFile.getPresentableUrl());
+ DiffManager.getInstance().getDiffTool().show(req);
+ }
+ }
+
+ @Override
+ public String getTitle() {
+ return SvnBundle.message("compare.with.branch.progress.loading.content");
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
new file mode 100644
index 0000000..07bf6ec
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/diff/SvnKitDiffClient.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2000-2013 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jetbrains.idea.svn.diff;
+
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.util.List;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnKitDiffClient extends BaseSvnClient implements DiffClient {
+
+ @Override
+ public List<Change> compare(@NotNull SvnTarget target1, @NotNull SvnTarget target2) throws VcsException {
+ throw new UnsupportedOperationException("Diff client is not implemented for SVNKit");
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchFactory.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchFactory.java
index 1e4760b..426c760 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchFactory.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchFactory.java
@@ -17,8 +17,8 @@
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
-import org.tmatesoft.svn.core.SVNException;
import java.util.ArrayList;
import java.util.Iterator;
@@ -57,7 +57,7 @@
myYoungest = -1;
}
- public List<Fragment> goBack(final int bunchSize, final Ref<Boolean> myYoungestRead) throws SVNException {
+ public List<Fragment> goBack(final int bunchSize, final Ref<Boolean> myYoungestRead) throws VcsException {
execute(bunchSize);
myYoungestRead.set(myLiveProvider.isEarliestRevisionWasAccessed());
return new ArrayList<Fragment>(myResult);
@@ -78,7 +78,7 @@
myYoungest = subList.get(subList.size() - 1).getNumber();
}
- private void execute(final int bunchSize) throws SVNException {
+ private void execute(final int bunchSize) throws VcsException {
myBunchSize = bunchSize;
myResult.clear();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchProvider.java
index 482cce9..6094474 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/BunchProvider.java
@@ -15,8 +15,8 @@
*/
package org.jetbrains.idea.svn.history;
+import com.intellij.openapi.vcs.VcsException;
import org.jetbrains.annotations.Nullable;
-import org.tmatesoft.svn.core.SVNException;
public interface BunchProvider {
long getEarliestRevision();
@@ -29,6 +29,6 @@
*/
@Nullable
Fragment getEarliestBunchInInterval(final long earliestRevision, final long oldestRevision, final int desirableSize,
- final boolean includeYoungest, final boolean includeOldest) throws SVNException;
+ final boolean includeYoungest, final boolean includeOldest) throws VcsException;
boolean isEmpty();
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CachedProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CachedProvider.java
index 294a2cd..b261ff1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CachedProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CachedProvider.java
@@ -15,10 +15,10 @@
*/
package org.jetbrains.idea.svn.history;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.committed.ChangesBunch;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import org.jetbrains.annotations.Nullable;
-import org.tmatesoft.svn.core.SVNException;
import java.util.ArrayList;
import java.util.Iterator;
@@ -86,7 +86,7 @@
@Nullable
public Fragment getEarliestBunchInInterval(final long earliestRevision, final long oldestRevision, final int desirableSize,
- final boolean includeYoungest, final boolean includeOldest) throws SVNException {
+ final boolean includeYoungest, final boolean includeOldest) throws VcsException {
if ((earliestRevision > getEarliestRevision()) || (earliestRevision == -1)) {
if (myAlreadyReaded == null) {
return null;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java
index c973061..567c21f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/CmdHistoryClient.java
@@ -7,11 +7,9 @@
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.commandLine.CommandExecutor;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
-import org.tmatesoft.svn.core.ISVNLogEntryHandler;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNLogEntry;
-import org.tmatesoft.svn.core.SVNLogEntryPath;
+import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -20,7 +18,6 @@
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlValue;
-import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -32,10 +29,9 @@
public class CmdHistoryClient extends BaseSvnClient implements HistoryClient {
@Override
- public void doLog(@NotNull File path,
+ public void doLog(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
- @Nullable SVNRevision pegRevision,
boolean stopOnCopy,
boolean discoverChangedPaths,
boolean includeMergedRevisions,
@@ -45,16 +41,16 @@
// TODO: add revision properties parameter if necessary
List<String> parameters =
- prepareCommand(path, startRevision, endRevision, pegRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions, limit);
+ prepareCommand(target, startRevision, endRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions, limit);
try {
- CommandExecutor command = CommandUtil.execute(myVcs, SvnTarget.fromFile(path, pegRevision), SvnCommandName.log, parameters, null);
+ CommandExecutor command = CommandUtil.execute(myVcs, target, SvnCommandName.log, parameters, null);
// TODO: handler should be called in parallel with command execution, but this will be in other thread
// TODO: check if that is ok for current handler implementation
parseOutput(command, handler);
}
catch (SVNException e) {
- throw new VcsException(e);
+ throw new SvnBindException(e);
}
}
@@ -87,14 +83,13 @@
}
}
- private static List<String> prepareCommand(@NotNull File path,
+ private static List<String> prepareCommand(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
- @Nullable SVNRevision pegRevision,
boolean stopOnCopy, boolean discoverChangedPaths, boolean includeMergedRevisions, long limit) {
List<String> parameters = new ArrayList<String>();
- CommandUtil.put(parameters, path, pegRevision);
+ CommandUtil.put(parameters, target);
parameters.add("--revision");
parameters.add(startRevision + ":" + endRevision);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java
index d19ed02..7fb35d1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/FirstInBranch.java
@@ -30,6 +30,9 @@
import java.util.Map;
import java.util.Set;
+// TODO: This one seem to determine revision in which branch was created - copied from trunk.
+// TODO: This could be done in one command "svn log <folder> -r 0:HEAD --stop-on-copy --limit 1".
+// TODO: Check for 1.7 and rewrite using this approach.
public class FirstInBranch implements Runnable {
private final SvnVcs myVcs;
private final String myBranchUrl;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java
index 87e5e76..d719e75 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/HistoryClient.java
@@ -6,19 +6,16 @@
import org.jetbrains.idea.svn.api.SvnClient;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.wc.SVNRevision;
-
-import java.io.File;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
/**
* @author Konstantin Kolosovsky.
*/
public interface HistoryClient extends SvnClient {
- // TODO: Url is also supported as parameter in cmd - use Target class
- void doLog(@NotNull File path,
+ void doLog(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
- @Nullable SVNRevision pegRevision,
boolean stopOnCopy,
boolean discoverChangedPaths,
boolean includeMergedRevisions,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LiveProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LiveProvider.java
index 573a226..b50a6de 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LiveProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LiveProvider.java
@@ -20,12 +20,13 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.SVNErrorCode;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.wc.SVNRevision;
import java.util.Iterator;
@@ -54,7 +55,7 @@
}
public Fragment getEarliestBunchInInterval(final long earliestRevision, final long oldestRevision, final int desirableSize,
- final boolean includeYoungest, final boolean includeOldest) throws SVNException {
+ final boolean includeYoungest, final boolean includeOldest) throws VcsException {
return getEarliestBunchInIntervalImpl(earliestRevision, oldestRevision, desirableSize, includeYoungest, includeOldest, earliestRevision);
}
@@ -62,14 +63,14 @@
final long oldestRevision,
final int desirableSize,
final boolean includeYoungest,
- final boolean includeOldest, final long earliestToTake) throws SVNException {
+ final boolean includeOldest, final long earliestToTake) throws VcsException {
if ((myEarliestRevisionWasAccessed) || ((oldestRevision == myYoungestRevision) && ((! includeYoungest) || (! includeOldest)))) {
return null;
}
final SVNRevision youngRevision = (earliestRevision == -1) ? SVNRevision.HEAD : SVNRevision.create(earliestRevision);
final Ref<List<CommittedChangeList>> refToList = new Ref<List<CommittedChangeList>>();
- final Ref<SVNException> exceptionRef = new Ref<SVNException>();
+ final Ref<VcsException> exceptionRef = new Ref<VcsException>();
final Runnable loader = new Runnable() {
public void run() {
@@ -77,7 +78,7 @@
refToList.set(
myLoader.loadInterval(youngRevision, SVNRevision.create(oldestRevision), desirableSize, includeYoungest, includeOldest));
}
- catch (SVNException e) {
+ catch (VcsException e) {
exceptionRef.set(e);
}
}
@@ -98,13 +99,13 @@
}, SvnBundle.message("progress.live.provider.loading.revisions.text"), false, myVcs.getProject());
}
- if (exceptionRef.get() != null) {
- final SVNException e = exceptionRef.get();
- if (SVNErrorCode.FS_NOT_FOUND.equals(e.getErrorMessage().getErrorCode())) {
+ if (!exceptionRef.isNull()) {
+ final VcsException e = exceptionRef.get();
+ if (isElementNotFound(e)) {
// occurs when target URL is deleted in repository
// try to find latest existent revision. expensive ...
final LatestExistentSearcher searcher = new LatestExistentSearcher(oldestRevision, myYoungestRevision, (oldestRevision != 0),
- myVcs, SVNURL.parseURIEncoded(myLocation.getURL()));
+ myVcs, myLocation.toSvnUrl());
final long existent = searcher.getLatestExistent();
if ((existent == -1) || (existent == earliestRevision)) {
myEarliestRevisionWasAccessed = true;
@@ -132,6 +133,10 @@
return new Fragment(Origin.LIVE, list, true, true, null);
}
+ private static boolean isElementNotFound(@NotNull VcsException e) {
+ return e instanceof SvnBindException && ((SvnBindException)e).contains(SVNErrorCode.FS_NOT_FOUND);
+ }
+
public boolean isEarliestRevisionWasAccessed() {
return myEarliestRevisionWasAccessed;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LocationDetector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LocationDetector.java
deleted file mode 100644
index 55cc740..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/LocationDetector.java
+++ /dev/null
@@ -1,64 +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 org.jetbrains.idea.svn.history;
-
-import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.progress.ProgressManager;
-import com.intellij.openapi.vcs.FilePath;
-import com.intellij.openapi.vcs.ProjectLevelVcsManager;
-import com.intellij.openapi.vcs.actions.VcsContextFactory;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.util.NotNullFunction;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.SvnUtil;
-import org.jetbrains.idea.svn.SvnVcs;
-import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
-
-import java.io.File;
-import java.util.HashMap;
-import java.util.Map;
-
-public class LocationDetector {
- private final Map<String, File> myMap;
-
- public LocationDetector(final SvnVcs vcs) {
- myMap = new HashMap<String, File>();
-
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
- final VirtualFile[] roots = ProjectLevelVcsManager.getInstance(vcs.getProject()).getRootsUnderVcs(vcs);
-
- for (VirtualFile root : roots) {
- myMap.putAll(SvnUtil.getLocationInfoForModule(vcs, new File(root.getPath()), progress));
- }
- }
-
- @Nullable
- public FilePath crawlForPath(final String fullPath, final NotNullFunction<File, Boolean> detector) {
- for (Map.Entry<String, File> entry : myMap.entrySet()) {
- final String url = entry.getKey();
- if (SVNPathUtil.isAncestor(url, fullPath)) {
- return filePathByUrlAndPath(fullPath, url, entry.getValue().getAbsolutePath(), detector);
- }
- }
- return null;
- }
-
- static FilePath filePathByUrlAndPath(final String longPath, final String parentUrl, final String parentPath, final NotNullFunction<File, Boolean> detector) {
- final String relPath = longPath.substring(parentUrl.length());
- final File localFile = new File(parentPath, relPath);
- return VcsContextFactory.SERVICE.getInstance().createFilePathOn(localFile, detector);
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.java
new file mode 100644
index 0000000..f0a7719
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/MergeSourceHierarchyBuilder.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 org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.util.Pair;
+import com.intellij.util.Consumer;
+import com.intellij.util.ThrowableConsumer;
+import org.jetbrains.annotations.NotNull;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNLogEntry;
+
+import java.util.List;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class MergeSourceHierarchyBuilder implements ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException> {
+
+ private TreeStructureNode<SVNLogEntry> myCurrentHierarchy;
+ @NotNull private final Consumer<TreeStructureNode<SVNLogEntry>> myConsumer;
+
+ public MergeSourceHierarchyBuilder(@NotNull Consumer<TreeStructureNode<SVNLogEntry>> consumer) {
+ myConsumer = consumer;
+ }
+
+ public void consume(Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException {
+ final SVNLogEntry logEntry = svnLogEntryIntegerPair.getFirst();
+ final Integer mergeLevel = svnLogEntryIntegerPair.getSecond();
+
+ if (mergeLevel < 0) {
+ if (myCurrentHierarchy != null) {
+ myConsumer.consume(myCurrentHierarchy);
+ }
+ if (logEntry.hasChildren()) {
+ myCurrentHierarchy = new TreeStructureNode<SVNLogEntry>(logEntry);
+ } else {
+ // just pass
+ myCurrentHierarchy = null;
+ myConsumer.consume(new TreeStructureNode<SVNLogEntry>(logEntry));
+ }
+ } else {
+ addToLevel(myCurrentHierarchy, logEntry, mergeLevel);
+ }
+ }
+
+ public void finish() {
+ if (myCurrentHierarchy != null) {
+ myConsumer.consume(myCurrentHierarchy);
+ }
+ }
+
+ private static void addToLevel(final TreeStructureNode<SVNLogEntry> tree, final SVNLogEntry entry, final int left) {
+ assert tree != null;
+ if (left == 0) {
+ tree.add(entry);
+ } else {
+ final List<TreeStructureNode<SVNLogEntry>> children = tree.getChildren();
+ assert ! children.isEmpty();
+ addToLevel(children.get(children.size() - 1), entry, left - 1);
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/ShowHideMergePanelAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/ShowHideMergePanelAction.java
new file mode 100644
index 0000000..570167f
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/ShowHideMergePanelAction.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 org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.actionSystem.ToggleAction;
+import com.intellij.openapi.vcs.changes.committed.ChangeListFilteringStrategy;
+import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
+import icons.SvnIcons;
+import org.jetbrains.idea.svn.SvnBundle;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class ShowHideMergePanelAction extends ToggleAction {
+
+ private final DecoratorManager myManager;
+ private final ChangeListFilteringStrategy myStrategy;
+ private boolean myIsSelected;
+
+ public ShowHideMergePanelAction(final DecoratorManager manager, final ChangeListFilteringStrategy strategy) {
+ myManager = manager;
+ myStrategy = strategy;
+ }
+
+ @Override
+ public void update(final AnActionEvent e) {
+ super.update(e);
+ final Presentation presentation = e.getPresentation();
+ presentation.setIcon(SvnIcons.ShowIntegratedFrom);
+ presentation.setText(SvnBundle.message("committed.changes.action.enable.merge.highlighting"));
+ presentation.setDescription(SvnBundle.message("committed.changes.action.enable.merge.highlighting.description.text"));
+ }
+
+ public boolean isSelected(final AnActionEvent e) {
+ return myIsSelected;
+ }
+
+ public void setSelected(final AnActionEvent e, final boolean state) {
+ myIsSelected = state;
+ if (state) {
+ myManager.setFilteringStrategy(myStrategy);
+ } else {
+ myManager.removeFilteringStrategy(myStrategy.getKey());
+ }
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java
new file mode 100644
index 0000000..e62b8e0
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SingleCommittedListProvider.java
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.svn.history;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProcessCanceledException;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.changes.Change;
+import com.intellij.openapi.vcs.changes.ContentRevision;
+import com.intellij.openapi.vcs.history.VcsRevisionNumber;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.vcsUtil.VcsUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.*;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
+
+import java.io.File;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class SingleCommittedListProvider {
+
+ private static final Logger LOG = Logger.getInstance(SingleCommittedListProvider.class);
+
+ @NotNull private final SvnVcs myVcs;
+ @NotNull private final Project myProject;
+ @NotNull private final VirtualFile file;
+ @NotNull private final VcsRevisionNumber number;
+ private SvnChangeList[] changeList;
+ private SVNRevision revisionBefore;
+ private SVNURL repositoryUrl;
+ private SVNURL svnRootUrl;
+ private SvnRepositoryLocation svnRootLocation;
+ private String repositoryRelativeUrl;
+ private FilePath filePath;
+
+ public SingleCommittedListProvider(@NotNull SvnVcs vcs, @NotNull VirtualFile file, @NotNull VcsRevisionNumber number) {
+ myVcs = vcs;
+ myProject = vcs.getProject();
+ this.file = file;
+ this.number = number;
+ }
+
+ public Pair<SvnChangeList, FilePath> run() throws VcsException {
+ Pair<SvnChangeList, FilePath> result = null;
+
+ if (setup()) {
+ calculate();
+ result = Pair.create(changeList[0], filePath);
+ }
+
+ return result;
+ }
+
+ private boolean setup() {
+ boolean result = false;
+
+ RootUrlInfo rootUrlInfo = myVcs.getSvnFileUrlMapping().getWcRootForFilePath(new File(file.getPath()));
+ if (rootUrlInfo != null) {
+ changeList = new SvnChangeList[1];
+ revisionBefore = ((SvnRevisionNumber)number).getRevision();
+ repositoryUrl = rootUrlInfo.getRepositoryUrlUrl();
+ svnRootUrl = rootUrlInfo.getAbsoluteUrlAsUrl();
+ svnRootLocation = new SvnRepositoryLocation(rootUrlInfo.getAbsoluteUrl());
+ repositoryRelativeUrl = SvnUtil.ensureStartSlash(SvnUtil.join(
+ SvnUtil.getRelativeUrl(repositoryUrl.toDecodedString(), svnRootUrl.toDecodedString()),
+ SvnUtil.getRelativePath(rootUrlInfo.getPath(), file.getPath())));
+
+ filePath = VcsUtil.getFilePath(file);
+
+ result = true;
+ }
+
+ return result;
+ }
+
+ private void calculate() throws VcsException {
+ // TODO: Seems that filePath detection could be replaced with "svn info -r <revisionBefore>" - and not call
+ // TODO: "svn log -r HEAD:<revisionBefore>" and track copies manually (which also is not correct for all cases).
+ if (!searchForUrl(svnRootUrl) && !(hasAccess(repositoryUrl) && searchForUrl(repositoryUrl))) {
+ filePath = searchFromHead(svnRootUrl);
+ }
+ else {
+ if (changeList[0].getChanges().size() == 1) {
+ final ContentRevision afterRevision = changeList[0].getChanges().iterator().next().getAfterRevision();
+
+ filePath = afterRevision != null ? afterRevision.getFile() : filePath;
+ }
+ else {
+ final Change targetChange = changeList[0].getByPath(repositoryRelativeUrl);
+
+ filePath = targetChange == null ? searchFromHead(svnRootUrl) : filePath;
+ }
+ }
+ }
+
+ private boolean hasAccess(@NotNull SVNURL url) {
+ return SvnAuthenticationNotifier.passiveValidation(myProject, url);
+ }
+
+ // return changed path, if any
+ private FilePath searchFromHead(@NotNull SVNURL url) throws VcsException {
+ final SvnCopyPathTracker pathTracker = new SvnCopyPathTracker(repositoryUrl.toDecodedString(), repositoryRelativeUrl);
+ SvnTarget target = SvnTarget.fromURL(url);
+
+ myVcs.getFactory(target).createHistoryClient().doLog(target, SVNRevision.HEAD, revisionBefore, false, true, false, 0, null,
+ new ISVNLogEntryHandler() {
+ public void handleLogEntry(SVNLogEntry logEntry) {
+ checkDisposed();
+ // date could be null for lists where there are paths that user has no rights to observe
+ if (logEntry.getDate() != null) {
+ pathTracker.accept(logEntry);
+ if (logEntry.getRevision() == revisionBefore.getNumber()) {
+ changeList[0] = createChangeList(logEntry);
+ }
+ }
+ }
+ }
+ );
+
+ FilePath path = pathTracker.getFilePath(myVcs);
+ return path == null ? filePath : path;
+ }
+
+ @NotNull
+ private SvnChangeList createChangeList(@NotNull SVNLogEntry logEntry) {
+ return new SvnChangeList(myVcs, svnRootLocation, logEntry, repositoryUrl.toDecodedString());
+ }
+
+ private void checkDisposed() {
+ if (myProject.isDisposed()) {
+ throw new ProcessCanceledException();
+ }
+ }
+
+ private boolean searchForUrl(@NotNull SVNURL url) throws VcsException {
+ ISVNLogEntryHandler handler = new ISVNLogEntryHandler() {
+ public void handleLogEntry(SVNLogEntry logEntry) {
+ checkDisposed();
+ // date could be null for lists where there are paths that user has no rights to observe
+ if (logEntry.getDate() != null) {
+ changeList[0] = createChangeList(logEntry);
+ }
+ }
+ };
+
+ SvnTarget target = SvnTarget.fromURL(url);
+ try {
+ myVcs.getFactory(target).createHistoryClient().doLog(target, revisionBefore, revisionBefore, false, true, false, 1, null, handler);
+ }
+ catch (SvnBindException e) {
+ LOG.info(e);
+ if (!e.containsCategory(SVNErrorCode.FS_CATEGORY)) {
+ throw e;
+ }
+ }
+ return changeList[0] != null;
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
index fc91dc3..f8b0717 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedChangesProvider.java
@@ -16,19 +16,20 @@
package org.jetbrains.idea.svn.history;
-import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
-import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.ThrowableComputable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.*;
-import com.intellij.openapi.vcs.changes.Change;
-import com.intellij.openapi.vcs.changes.ContentRevision;
-import com.intellij.openapi.vcs.changes.committed.*;
+import com.intellij.openapi.vcs.changes.committed.DecoratorManager;
+import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper;
+import com.intellij.openapi.vcs.changes.committed.VcsCommittedViewAuxiliary;
+import com.intellij.openapi.vcs.changes.committed.VcsConfigurationChangeListener;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.versionBrowser.ChangeBrowserSettings;
import com.intellij.openapi.vcs.versionBrowser.ChangesBrowserSettingsEditor;
@@ -38,23 +39,19 @@
import com.intellij.util.Consumer;
import com.intellij.util.PairConsumer;
import com.intellij.util.ThrowableConsumer;
-import com.intellij.util.containers.MultiMap;
import com.intellij.util.messages.MessageBusConnection;
-import icons.SvnIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
import org.jetbrains.idea.svn.actions.ConfigureBranchesAction;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.*;
-import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.io.SVNRepository;
-import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
import java.io.DataInput;
import java.io.DataOutput;
-import java.io.File;
import java.io.IOException;
import java.util.*;
@@ -66,17 +63,15 @@
private final SvnVcs myVcs;
private final MessageBusConnection myConnection;
private MergeInfoUpdatesListener myMergeInfoUpdatesListener;
- private final MyZipper myZipper;
+ private final SvnCommittedListsZipper myZipper;
public final static int VERSION_WITH_COPY_PATHS_ADDED = 2;
public final static int VERSION_WITH_REPLACED_PATHS = 3;
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.history.SvnCommittedChangesProvider");
-
public SvnCommittedChangesProvider(final Project project) {
myProject = project;
myVcs = SvnVcs.getInstance(myProject);
- myZipper = new MyZipper();
+ myZipper = new SvnCommittedListsZipper(myVcs);
myConnection = myProject.getMessageBus().connect();
@@ -110,17 +105,12 @@
@Nullable
public RepositoryLocation getLocationFor(final FilePath root) {
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
final String url = SvnUtil.getExactLocation(myVcs, root.getIOFile());
return url == null ? null : new SvnRepositoryLocation(url);
}
public RepositoryLocation getLocationFor(final FilePath root, final String repositoryPath) {
- if (repositoryPath == null) {
- return getLocationFor(root);
- }
-
- return new SvnLoadingRepositoryLocation(repositoryPath, myVcs);
+ return repositoryPath == null ? getLocationFor(root) : new SvnRepositoryLocation(repositoryPath);
}
@Nullable
@@ -128,49 +118,6 @@
return myZipper;
}
- private class MyZipper implements VcsCommittedListsZipper {
- public Pair<List<RepositoryLocationGroup>, List<RepositoryLocation>> groupLocations(final List<RepositoryLocation> in) {
- final List<RepositoryLocationGroup> groups = new ArrayList<RepositoryLocationGroup>();
- final List<RepositoryLocation> singles = new ArrayList<RepositoryLocation>();
-
- final MultiMap<SVNURL, RepositoryLocation> map = new MultiMap<SVNURL, RepositoryLocation>();
-
- for (RepositoryLocation location : in) {
- final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
- final String url = svnLocation.getURL();
-
- final SVNURL root = SvnUtil.getRepositoryRoot(myVcs, url);
- if (root == null) {
- // should not occur
- LOG.info("repository root not found for location:"+ location.toPresentableString());
- singles.add(location);
- } else {
- map.putValue(root, svnLocation);
- }
- }
-
- final Set<SVNURL> keys = map.keySet();
- for (SVNURL key : keys) {
- final Collection<RepositoryLocation> repositoryLocations = map.get(key);
- if (repositoryLocations.size() == 1) {
- singles.add(repositoryLocations.iterator().next());
- } else {
- final SvnRepositoryLocationGroup group = new SvnRepositoryLocationGroup(key, repositoryLocations);
- groups.add(group);
- }
- }
- return new Pair<List<RepositoryLocationGroup>, List<RepositoryLocation>>(groups, singles);
- }
-
- public CommittedChangeList zip(final RepositoryLocationGroup group, final List<CommittedChangeList> lists) {
- return new SvnChangeList(lists, new SvnRepositoryLocation(group.toPresentableString()));
- }
-
- public long getNumber(final CommittedChangeList list) {
- return list.getNumber();
- }
- }
-
public void loadCommittedChanges(ChangeBrowserSettings settings,
RepositoryLocation location,
int maxCount,
@@ -178,30 +125,10 @@
throws VcsException {
try {
final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
- if (progress != null) {
- progress.setText(SvnBundle.message("progress.text.changes.collecting.changes"));
- progress.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", location));
- }
-
- // TODO: Implement this with command line
- final String repositoryRoot;
- SVNRepository repository = null;
- try {
- repository = myVcs.createRepository(svnLocation.getURL());
- repositoryRoot = repository.getRepositoryRoot(true).toString();
- }
- catch (SVNException e) {
- throw new VcsException(e);
- } finally {
- if (repository != null) {
- repository.closeSession();
- }
- }
-
+ final String repositoryRoot = getRepositoryRoot(svnLocation);
final ChangeBrowserSettings.Filter filter = settings.createFilter();
- getCommittedChangesImpl(settings, svnLocation.getURL(), new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
+ getCommittedChangesImpl(settings, svnLocation, new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
public void consume(final SVNLogEntry svnLogEntry) {
final SvnChangeList cl = new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot);
if (filter.accepts(cl)) {
@@ -218,29 +145,9 @@
public List<SvnChangeList> getCommittedChanges(ChangeBrowserSettings settings, final RepositoryLocation location, final int maxCount) throws VcsException {
final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
final ArrayList<SvnChangeList> result = new ArrayList<SvnChangeList>();
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
- if (progress != null) {
- progress.setText(SvnBundle.message("progress.text.changes.collecting.changes"));
- progress.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", location));
- }
+ final String repositoryRoot = getRepositoryRoot(svnLocation);
- final String repositoryRoot;
- // TODO: Implement this with command line
- SVNRepository repository = null;
- try {
- repository = myVcs.createRepository(svnLocation.getURL());
- repositoryRoot = repository.getRepositoryRoot(true).toString();
- repository.closeSession();
- }
- catch (SVNException e) {
- throw new VcsException(e);
- } finally {
- if (repository != null) {
- repository.closeSession();
- }
- }
-
- getCommittedChangesImpl(settings, svnLocation.getURL(), new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
+ getCommittedChangesImpl(settings, svnLocation, new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
public void consume(final SVNLogEntry svnLogEntry) {
result.add(new SvnChangeList(myVcs, svnLocation, svnLogEntry, repositoryRoot));
}
@@ -254,14 +161,40 @@
final PairConsumer<SvnChangeList, TreeStructureNode<SVNLogEntry>> finalConsumer)
throws VcsException {
final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
- if (progress != null) {
- progress.setText(SvnBundle.message("progress.text.changes.collecting.changes"));
- progress.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", location));
- }
- // TODO: Rewrite this without using SVNKit
+ final String repositoryRoot = getRepositoryRoot(svnLocation);
+
+ final MergeSourceHierarchyBuilder builder = new MergeSourceHierarchyBuilder(new Consumer<TreeStructureNode<SVNLogEntry>>() {
+ public void consume(TreeStructureNode<SVNLogEntry> node) {
+ finalConsumer.consume(new SvnChangeList(myVcs, svnLocation, node.getMe(), repositoryRoot), node);
+ }
+ });
+ final SvnMergeSourceTracker mergeSourceTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException>() {
+ public void consume(Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException {
+ builder.consume(svnLogEntryIntegerPair);
+ }
+ });
+
+ getCommittedChangesImpl(settings, svnLocation, new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
+ public void consume(final SVNLogEntry svnLogEntry) {
+ try {
+ mergeSourceTracker.consume(svnLogEntry);
+ }
+ catch (SVNException e) {
+ throw new RuntimeException(e);
+ // will not occur actually but anyway never eat them
+ }
+ }
+ }, true, false);
+
+ builder.finish();
+ }
+
+ private String getRepositoryRoot(@NotNull SvnRepositoryLocation svnLocation) throws VcsException {
+ // TODO: Implement this with command line
+
final String repositoryRoot;
SVNRepository repository = null;
+
try {
repository = myVcs.createRepository(svnLocation.getURL());
repositoryRoot = repository.getRepositoryRoot(true).toString();
@@ -273,154 +206,124 @@
repository.closeSession();
}
}
-
- final MergeTrackerProxy proxy = new MergeTrackerProxy(new Consumer<TreeStructureNode<SVNLogEntry>>() {
- public void consume(TreeStructureNode<SVNLogEntry> node) {
- finalConsumer.consume(new SvnChangeList(myVcs, svnLocation, node.getMe(), repositoryRoot), node);
- }
- });
- final SvnMergeSourceTracker mergeSourceTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException>() {
- public void consume(Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException {
- proxy.consume(svnLogEntryIntegerPair);
- }
- });
-
- getCommittedChangesImpl(settings, svnLocation.getURL(), new String[]{""}, maxCount, new Consumer<SVNLogEntry>() {
- public void consume(final SVNLogEntry svnLogEntry) {
- try {
- mergeSourceTracker.consume(svnLogEntry);
- }
- catch (SVNException e) {
- throw new RuntimeException(e);
- // will not occur actually but anyway never eat them
- }
- }
- }, true, false);
-
- proxy.finish();
+ return repositoryRoot;
}
-
- private static class MergeTrackerProxy implements ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException> {
- private TreeStructureNode<SVNLogEntry> myCurrentHierarchy;
- private final Consumer<TreeStructureNode<SVNLogEntry>> myConsumer;
-
- private MergeTrackerProxy(Consumer<TreeStructureNode<SVNLogEntry>> consumer) {
- myConsumer = consumer;
- }
-
- public void consume(Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException {
- final SVNLogEntry logEntry = svnLogEntryIntegerPair.getFirst();
- final Integer mergeLevel = svnLogEntryIntegerPair.getSecond();
-
- if (mergeLevel < 0) {
- if (myCurrentHierarchy != null) {
- myConsumer.consume(myCurrentHierarchy);
- }
- if (logEntry.hasChildren()) {
- myCurrentHierarchy = new TreeStructureNode<SVNLogEntry>(logEntry);
- } else {
- // just pass
- myCurrentHierarchy = null;
- myConsumer.consume(new TreeStructureNode<SVNLogEntry>(logEntry));
- }
- } else {
- addToLevel(myCurrentHierarchy, logEntry, mergeLevel);
- }
- }
-
- public void finish() {
- if (myCurrentHierarchy != null) {
- myConsumer.consume(myCurrentHierarchy);
- }
- }
-
- private static void addToLevel(final TreeStructureNode<SVNLogEntry> tree, final SVNLogEntry entry, final int left) {
- assert tree != null;
- if (left == 0) {
- tree.add(entry);
- } else {
- final List<TreeStructureNode<SVNLogEntry>> children = tree.getChildren();
- assert ! children.isEmpty();
- addToLevel(children.get(children.size() - 1), entry, left - 1);
- }
- }
- }
-
- private void getCommittedChangesImpl(ChangeBrowserSettings settings, final String url, final String[] filterUrls,
+ private void getCommittedChangesImpl(ChangeBrowserSettings settings, final SvnRepositoryLocation location, final String[] filterUrls,
final int maxCount, final Consumer<SVNLogEntry> resultConsumer, final boolean includeMergedRevisions,
final boolean filterOutByDate) throws VcsException {
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
- if (progress != null) {
- progress.setText(SvnBundle.message("progress.text.changes.collecting.changes"));
- progress.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", url));
- }
- try {
- SVNLogClient logger = myVcs.createLogClient();
+ setCollectingChangesProgress(location);
+ try {
final String author = settings.getUserFilter();
final Date dateFrom = settings.getDateAfterFilter();
final Long changeFrom = settings.getChangeAfterFilter();
final Date dateTo = settings.getDateBeforeFilter();
final Long changeTo = settings.getChangeBeforeFilter();
- final SVNRevision revisionBefore;
- if (dateTo != null) {
- revisionBefore = SVNRevision.create(dateTo);
- }
- else if (changeTo != null) {
- revisionBefore = SVNRevision.create(changeTo.longValue());
- }
- else {
- // TODO: Implement this with command line
- SVNRepository repository = null;
- final long revision;
- try {
- repository = myVcs.createRepository(url);
- revision = repository.getLatestRevision();
- } finally {
- if (repository != null) {
- repository.closeSession();
- }
- }
- revisionBefore = SVNRevision.create(revision);
- }
- final SVNRevision revisionAfter;
- if (dateFrom != null) {
- revisionAfter = SVNRevision.create(dateFrom);
- }
- else if (changeFrom != null) {
- revisionAfter = SVNRevision.create(changeFrom.longValue());
- }
- else {
- revisionAfter = SVNRevision.create(1);
- }
+ final SVNRevision revisionBefore = createRevisionBefore(location, dateTo, changeTo);
+ final SVNRevision revisionAfter = createRevisionAfter(dateFrom, changeFrom);
// TODO: Implement this with command line
- logger.doLog(SVNURL.parseURIEncoded(url), filterUrls, revisionBefore, revisionBefore, revisionAfter,
- settings.STOP_ON_COPY, true, includeMergedRevisions, maxCount, null,
- new ISVNLogEntryHandler() {
- public void handleLogEntry(SVNLogEntry logEntry) {
- if (myProject.isDisposed()) throw new ProcessCanceledException();
- if (progress != null) {
- progress.setText2(SvnBundle.message("progress.text2.processing.revision", logEntry.getRevision()));
- progress.checkCanceled();
- }
- if (filterOutByDate && logEntry.getDate() == null) {
- // do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe
- return;
- }
- if (author == null || author.equalsIgnoreCase(logEntry.getAuthor())) {
- resultConsumer.consume(logEntry);
- }
- }
- });
+ SVNLogClient logger = myVcs.createLogClient();
+ logger.doLog(location.toSvnUrl(), filterUrls, revisionBefore, revisionBefore, revisionAfter, settings.STOP_ON_COPY, true,
+ includeMergedRevisions, maxCount, null, createLogHandler(resultConsumer, filterOutByDate, author));
}
catch (SVNException e) {
throw new VcsException(e);
}
}
+ @NotNull
+ private static SVNRevision createRevisionAfter(@Nullable Date date, @Nullable Long change) throws VcsException {
+ return createRevision(date, change, new ThrowableComputable<SVNRevision, VcsException>() {
+ @Override
+ public SVNRevision compute() throws VcsException {
+ return SVNRevision.create(1);
+ }
+ });
+ }
+
+ @NotNull
+ private SVNRevision createRevisionBefore(@NotNull final SvnRepositoryLocation location, @Nullable Date date, @Nullable Long change)
+ throws VcsException {
+ return createRevision(date, change, new ThrowableComputable<SVNRevision, VcsException>() {
+ @Override
+ public SVNRevision compute() throws VcsException {
+ return getLatestRevision(location);
+ }
+ });
+ }
+
+ @NotNull
+ private SVNRevision getLatestRevision(@NotNull SvnRepositoryLocation location) throws VcsException {
+ // TODO: Implement this with command line - issue is that if url does not exist, SVNRepository will be created and asked correctly
+ // TODO: But "svn info -r HEAD" will fail - check if non-existing location could be passed or inteface should be expanded to use
+ // TODO: peg revisions.
+ SVNRepository repository = null;
+ long revision;
+
+ try {
+ repository = myVcs.createRepository(location.getURL());
+ revision = repository.getLatestRevision();
+ }
+ catch (SVNException e) {
+ throw new SvnBindException(e);
+ }
+ finally {
+ if (repository != null) {
+ repository.closeSession();
+ }
+ }
+
+ return SVNRevision.create(revision);
+ }
+
+ @NotNull
+ private static SVNRevision createRevision(@Nullable Date date,
+ @Nullable Long change,
+ @NotNull ThrowableComputable<SVNRevision, VcsException> defaultValue)
+ throws VcsException {
+ final SVNRevision result;
+
+ if (date != null) {
+ result = SVNRevision.create(date);
+ }
+ else if (change != null) {
+ result = SVNRevision.create(change.longValue());
+ }
+ else {
+ result = defaultValue.compute();
+ }
+
+ return result;
+ }
+
+ @NotNull
+ private ISVNLogEntryHandler createLogHandler(final Consumer<SVNLogEntry> resultConsumer,
+ final boolean filterOutByDate,
+ final String author) {
+ return new ISVNLogEntryHandler() {
+ public void handleLogEntry(SVNLogEntry logEntry) {
+ if (myProject.isDisposed()) throw new ProcessCanceledException();
+
+ ProgressManager.progress2(SvnBundle.message("progress.text2.processing.revision", logEntry.getRevision()));
+ if (filterOutByDate && logEntry.getDate() == null) {
+ // do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe
+ return;
+ }
+ if (author == null || author.equalsIgnoreCase(logEntry.getAuthor())) {
+ resultConsumer.consume(logEntry);
+ }
+ }
+ };
+ }
+
+ private static void setCollectingChangesProgress(@Nullable Object location) {
+ ProgressManager.progress(SvnBundle.message("progress.text.changes.collecting.changes"),
+ SvnBundle.message("progress.text2.changes.establishing.connection", location));
+ }
+
public ChangeListColumn[] getColumns() {
return new ChangeListColumn[] {
new ChangeListColumn.ChangeListNumberColumn(SvnBundle.message("revision.title")),
@@ -435,39 +338,6 @@
myMergeInfoUpdatesListener.addPanel(action);
}
- private static class ShowHideMergePanel extends ToggleAction {
- private final DecoratorManager myManager;
- private final ChangeListFilteringStrategy myStrategy;
- private boolean myIsSelected;
-
- public ShowHideMergePanel(final DecoratorManager manager, final ChangeListFilteringStrategy strategy) {
- myManager = manager;
- myStrategy = strategy;
- }
-
- @Override
- public void update(final AnActionEvent e) {
- super.update(e);
- final Presentation presentation = e.getPresentation();
- presentation.setIcon(SvnIcons.ShowIntegratedFrom);
- presentation.setText(SvnBundle.message("committed.changes.action.enable.merge.highlighting"));
- presentation.setDescription(SvnBundle.message("committed.changes.action.enable.merge.highlighting.description.text"));
- }
-
- public boolean isSelected(final AnActionEvent e) {
- return myIsSelected;
- }
-
- public void setSelected(final AnActionEvent e, final boolean state) {
- myIsSelected = state;
- if (state) {
- myManager.setFilteringStrategy(myStrategy);
- } else {
- myManager.removeFilteringStrategy(myStrategy.getKey());
- }
- }
- }
-
@Nullable
public VcsCommittedViewAuxiliary createActions(final DecoratorManager manager, @Nullable final RepositoryLocation location) {
final RootsAndBranches rootsAndBranches = new RootsAndBranches(myProject, manager, location);
@@ -478,7 +348,7 @@
popup.add(rootsAndBranches.getUndoIntegrateAction());
popup.add(new ConfigureBranchesAction());
- final ShowHideMergePanel action = new ShowHideMergePanel(manager, rootsAndBranches.getStrategy());
+ final ShowHideMergePanelAction action = new ShowHideMergePanelAction(manager, rootsAndBranches.getStrategy());
return new VcsCommittedViewAuxiliary(Collections.<AnAction>singletonList(popup), new Runnable() {
public void run() {
@@ -496,73 +366,7 @@
@Override
public Pair<SvnChangeList, FilePath> getOneList(final VirtualFile file, VcsRevisionNumber number) throws VcsException {
- final RootUrlInfo rootUrlInfo = myVcs.getSvnFileUrlMapping().getWcRootForFilePath(new File(file.getPath()));
- if (rootUrlInfo == null) return null;
- final VirtualFile root = rootUrlInfo.getVirtualFile();
- if (root == null) return null;
- final SvnRepositoryLocation svnRootLocation = (SvnRepositoryLocation)getLocationFor(new FilePathImpl(root));
- if (svnRootLocation == null) return null;
- final String url = svnRootLocation.getURL();
- final long revision;
- try {
- revision = Long.parseLong(number.asString());
- } catch (NumberFormatException e) {
- throw new VcsException(e);
- }
-
- final SvnChangeList[] result = new SvnChangeList[1];
- final SVNLogClient logger;
- final SVNRevision revisionBefore;
- final SVNURL repositoryUrl;
- final SVNURL svnurl;
- final SVNInfo targetInfo;
- try {
- logger = myVcs.createLogClient();
- revisionBefore = SVNRevision.create(revision);
-
- svnurl = SVNURL.parseURIEncoded(url);
- final SVNInfo info = myVcs.getInfo(svnurl, SVNRevision.HEAD);
- targetInfo = myVcs.getInfo(new File(file.getPath()));
- if (info == null) {
- throw new VcsException("Can not get repository URL");
- }
- repositoryUrl = info.getRepositoryRootURL();
- }
- catch (SVNException e) {
- LOG.info(e);
- throw new VcsException(e);
- }
-
- tryExactHit(svnRootLocation, result, logger, revisionBefore, repositoryUrl, svnurl);
- if (result[0] == null) {
- tryByRoot(result, logger, revisionBefore, repositoryUrl);
- if (result[0] == null) {
- FilePath path = tryStepByStep(svnRootLocation, result, logger, revisionBefore, targetInfo, svnurl);
- path = path == null ? new FilePathImpl(file) : path;
- // and pass & take rename context there
- return new Pair<SvnChangeList, FilePath>(result[0], path);
- }
- }
- if (result[0].getChanges().size() == 1) {
- final Collection<Change> changes = result[0].getChanges();
- final Change change = changes.iterator().next();
- final ContentRevision afterRevision = change.getAfterRevision();
- if (afterRevision != null) {
- return new Pair<SvnChangeList, FilePath>(result[0], afterRevision.getFile());
- } else {
- return new Pair<SvnChangeList, FilePath>(result[0], new FilePathImpl(file));
- }
- }
- String relativePath = SVNPathUtil.getRelativePath(targetInfo.getRepositoryRootURL().toString(), targetInfo.getURL().toString());
- relativePath = relativePath.startsWith("/") ? relativePath : "/" + relativePath;
- final Change targetChange = result[0].getByPath(relativePath);
- if (targetChange == null) {
- FilePath path = tryStepByStep(svnRootLocation, result, logger, revisionBefore, targetInfo, svnurl);
- path = path == null ? new FilePathImpl(file) : path;
- // and pass & take rename context there
- return new Pair<SvnChangeList, FilePath>(result[0], path);
- }
- return new Pair<SvnChangeList, FilePath>(result[0], new FilePathImpl(file));
+ return new SingleCommittedListProvider(myVcs, file, number).run();
}
@Override
@@ -576,121 +380,6 @@
return true;
}
- private static class RenameContext {
- @NotNull
- private String myCurrentPath;
- private String myRepositoryRoot;
- private boolean myHadChanged;
-
- private RenameContext(final SVNInfo info) {
- myRepositoryRoot = info.getRepositoryRootURL().toString();
- myCurrentPath = SVNPathUtil.getRelativePath(myRepositoryRoot, info.getURL().toString());
- myCurrentPath = myCurrentPath.startsWith("/") ? myCurrentPath : ("/" + myCurrentPath);
- }
-
- public void accept(final SVNLogEntry entry) {
- final Map changedPaths = entry.getChangedPaths();
- if (changedPaths == null) return;
-
- for (Object o : changedPaths.values()) {
- final SVNLogEntryPath entryPath = (SVNLogEntryPath) o;
- if (entryPath != null && 'A' == entryPath.getType() && entryPath.getCopyPath() != null) {
- if (myCurrentPath.equals(entryPath.getPath())) {
- myHadChanged = true;
- myCurrentPath = entryPath.getCopyPath();
- return;
- } else if (SVNPathUtil.isAncestor(entryPath.getPath(), myCurrentPath)) {
- final String relativePath = SVNPathUtil.getRelativePath(entryPath.getPath(), myCurrentPath);
- myCurrentPath = SVNPathUtil.append(entryPath.getCopyPath(), relativePath);
- myHadChanged = true;
- return;
- }
- }
- }
- }
-
- @Nullable
- public FilePath getFilePath(final SvnVcs vcs) {
- if (! myHadChanged) return null;
- final SvnFileUrlMapping svnFileUrlMapping = vcs.getSvnFileUrlMapping();
- final String absolutePath = SVNPathUtil.append(myRepositoryRoot, myCurrentPath);
- final String localPath = svnFileUrlMapping.getLocalPath(absolutePath);
- if (localPath == null) {
- LOG.info("Cannot find local path for url: " + absolutePath);
- return null;
- }
- return new FilePathImpl(new File(localPath), false);
- }
- }
-
- private void tryByRoot(SvnChangeList[] result, SVNLogClient logger, SVNRevision revisionBefore, SVNURL repositoryUrl) throws VcsException {
- final boolean authorized = SvnAuthenticationNotifier.passiveValidation(myProject, repositoryUrl);
- if (! authorized) return;
- tryExactHit(new SvnRepositoryLocation(repositoryUrl.toString()), result, logger, revisionBefore, repositoryUrl, repositoryUrl);
- }
-
- // return changed path, if any
- private FilePath tryStepByStep(final SvnRepositoryLocation svnRepositoryLocation,
- final SvnChangeList[] result,
- SVNLogClient logger,
- final SVNRevision revisionBefore, final SVNInfo info, SVNURL svnurl) throws VcsException {
- final String repositoryRoot = info.getRepositoryRootURL().toString();
- try {
- final RenameContext renameContext = new RenameContext(info);
- // TODO: Implement this with command line
- logger.doLog(svnurl, null, SVNRevision.UNDEFINED, SVNRevision.HEAD, revisionBefore,
- false, true, false, 0, null,
- new ISVNLogEntryHandler() {
- public void handleLogEntry(SVNLogEntry logEntry) {
- if (myProject.isDisposed()) throw new ProcessCanceledException();
- if (logEntry.getDate() == null) {
- // do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe
- return;
- }
- renameContext.accept(logEntry);
- if (logEntry.getRevision() == revisionBefore.getNumber()) {
- result[0] = new SvnChangeList(myVcs, svnRepositoryLocation, logEntry, repositoryRoot);
- }
- }
- });
- return renameContext.getFilePath(myVcs);
- }
- catch (SVNException e) {
- LOG.info(e);
- throw new VcsException(e);
- }
- }
-
- private void tryExactHit(final SvnRepositoryLocation location,
- final SvnChangeList[] result,
- SVNLogClient logger,
- SVNRevision revisionBefore,
- final SVNURL repositoryUrl, SVNURL svnurl) throws VcsException {
- try {
- // TODO: Implement this with command line
- logger.doLog(svnurl, null, SVNRevision.UNDEFINED, revisionBefore, revisionBefore,
- false, true, false, 1, null,
- new ISVNLogEntryHandler() {
- public void handleLogEntry(SVNLogEntry logEntry) {
- if (myProject.isDisposed()) throw new ProcessCanceledException();
- if (logEntry.getDate() == null) {
- // do not add lists without info - this situation is possible for lists where there are paths that user has no rights to observe
- return;
- }
- result[0] = new SvnChangeList(myVcs, location, logEntry, repositoryUrl.toString());
- }
- });
- }
- catch (SVNException e) {
- LOG.info(e);
- if (SVNErrorCode.FS_CATEGORY == e.getErrorMessage().getErrorCode().getCategory()) {
- // pass to step by step looking for revision
- return;
- }
- throw new VcsException(e);
- }
- }
-
public int getFormatVersion() {
return VERSION_WITH_REPLACED_PATHS;
}
@@ -710,6 +399,10 @@
}
public Collection<FilePath> getIncomingFiles(final RepositoryLocation location) {
+ // TODO: Implement this using "svn status -u" or probably use this command in other part of cache logic
+ // TODO: How to map RepositoryLocation to concrete working copy ???
+ // TODO: Seems that another parameter identifying local copy with for which we're detecting if repository location contains
+ // TODO: incoming files.
return null;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.java
new file mode 100644
index 0000000..13359c4
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCommittedListsZipper.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 org.jetbrains.idea.svn.history;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vcs.RepositoryLocation;
+import com.intellij.openapi.vcs.changes.committed.RepositoryLocationGroup;
+import com.intellij.openapi.vcs.changes.committed.VcsCommittedListsZipper;
+import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import com.intellij.util.containers.MultiMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.tmatesoft.svn.core.SVNURL;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class SvnCommittedListsZipper implements VcsCommittedListsZipper {
+
+ private static final Logger LOG = Logger.getInstance(SvnCommittedListsZipper.class);
+
+ @NotNull private final SvnVcs myVcs;
+
+ public SvnCommittedListsZipper(@NotNull SvnVcs vcs) {
+ myVcs = vcs;
+ }
+
+ public Pair<List<RepositoryLocationGroup>, List<RepositoryLocation>> groupLocations(final List<RepositoryLocation> in) {
+ final List<RepositoryLocationGroup> groups = new ArrayList<RepositoryLocationGroup>();
+ final List<RepositoryLocation> singles = new ArrayList<RepositoryLocation>();
+
+ final MultiMap<SVNURL, RepositoryLocation> map = new MultiMap<SVNURL, RepositoryLocation>();
+
+ for (RepositoryLocation location : in) {
+ final SvnRepositoryLocation svnLocation = (SvnRepositoryLocation) location;
+ final String url = svnLocation.getURL();
+
+ final SVNURL root = SvnUtil.getRepositoryRoot(myVcs, url);
+ if (root == null) {
+ // should not occur
+ LOG.info("repository root not found for location:"+ location.toPresentableString());
+ singles.add(location);
+ } else {
+ map.putValue(root, svnLocation);
+ }
+ }
+
+ final Set<SVNURL> keys = map.keySet();
+ for (SVNURL key : keys) {
+ final Collection<RepositoryLocation> repositoryLocations = map.get(key);
+ if (repositoryLocations.size() == 1) {
+ singles.add(repositoryLocations.iterator().next());
+ } else {
+ final SvnRepositoryLocationGroup group = new SvnRepositoryLocationGroup(key, repositoryLocations);
+ groups.add(group);
+ }
+ }
+ return new Pair<List<RepositoryLocationGroup>, List<RepositoryLocation>>(groups, singles);
+ }
+
+ public CommittedChangeList zip(final RepositoryLocationGroup group, final List<CommittedChangeList> lists) {
+ return new SvnChangeList(lists, new SvnRepositoryLocation(group.toPresentableString()));
+ }
+
+ public long getNumber(final CommittedChangeList list) {
+ return list.getNumber();
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java
new file mode 100644
index 0000000..70e982a
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnCopyPathTracker.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.idea.svn.history;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.FilePathImpl;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.svn.SvnFileUrlMapping;
+import org.jetbrains.idea.svn.SvnVcs;
+import org.tmatesoft.svn.core.SVNLogEntry;
+import org.tmatesoft.svn.core.SVNLogEntryPath;
+import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
+
+import java.io.File;
+import java.util.Map;
+
+/**
+* @author Konstantin Kolosovsky.
+*/
+public class SvnCopyPathTracker {
+
+ private static final Logger LOG = Logger.getInstance(SvnCopyPathTracker.class);
+
+ @NotNull private String myCurrentPath;
+ private String myRepositoryRoot;
+ private boolean myHadChanged;
+
+ public SvnCopyPathTracker(@NotNull String repositoryUrl, @NotNull String relativeUrl) {
+ myRepositoryRoot = repositoryUrl;
+ myCurrentPath = relativeUrl;
+ }
+
+ public void accept(@NotNull final SVNLogEntry entry) {
+ final Map changedPaths = entry.getChangedPaths();
+ if (changedPaths == null) return;
+
+ for (Object o : changedPaths.values()) {
+ final SVNLogEntryPath entryPath = (SVNLogEntryPath) o;
+ if (entryPath != null && 'A' == entryPath.getType() && entryPath.getCopyPath() != null) {
+ if (myCurrentPath.equals(entryPath.getPath())) {
+ myHadChanged = true;
+ myCurrentPath = entryPath.getCopyPath();
+ return;
+ } else if (SVNPathUtil.isAncestor(entryPath.getPath(), myCurrentPath)) {
+ final String relativePath = SVNPathUtil.getRelativePath(entryPath.getPath(), myCurrentPath);
+ myCurrentPath = SVNPathUtil.append(entryPath.getCopyPath(), relativePath);
+ myHadChanged = true;
+ return;
+ }
+ }
+ }
+ }
+
+ @Nullable
+ public FilePath getFilePath(final SvnVcs vcs) {
+ if (! myHadChanged) return null;
+ final SvnFileUrlMapping svnFileUrlMapping = vcs.getSvnFileUrlMapping();
+ final String absolutePath = SVNPathUtil.append(myRepositoryRoot, myCurrentPath);
+ final String localPath = svnFileUrlMapping.getLocalPath(absolutePath);
+ if (localPath == null) {
+ LOG.info("Cannot find local path for url: " + absolutePath);
+ return null;
+ }
+ return new FilePathImpl(new File(localPath), false);
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
index a429999..92b619a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnHistoryProvider.java
@@ -44,8 +44,8 @@
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.wc.SVNInfo;
-import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
import org.tmatesoft.svn.util.SVNLogType;
import javax.swing.*;
@@ -65,6 +65,7 @@
myVcs = vcs;
}
+ @Override
public boolean supportsHistoryForDirectories() {
return true;
}
@@ -79,6 +80,7 @@
return true;
}
+ @Override
public VcsDependentHistoryComponents getUICustomization(final VcsHistorySession session, JComponent forShortcutRegistration) {
final ColumnInfo[] columns;
final Consumer<VcsFileRevision> listener;
@@ -94,6 +96,7 @@
field.setBackground(UIUtil.getComboBoxDisabledBackground());
field.setWrapStyleWord(true);
listener = new Consumer<VcsFileRevision>() {
+ @Override
public void consume(VcsFileRevision vcsFileRevision) {
field.setText(mergeSourceColumn.getText(vcsFileRevision));
}
@@ -155,6 +158,7 @@
return new SvnHistorySession(myVcs, revisions, filePath, aBoolean, currentRevision, false, ! filePath.isNonLocal());
}
+ @Override
@Nullable
public VcsHistorySession createSessionFor(final FilePath filePath) throws VcsException {
final VcsAppendableHistoryPartnerAdapter adapter = new VcsAppendableHistoryPartnerAdapter();
@@ -164,6 +168,7 @@
return adapter.getSession();
}
+ @Override
public void reportAppendableHistory(FilePath path, final VcsAppendableHistorySessionPartner partner) throws VcsException {
// we need + 1 rows to be reported to further detect that number of rows exceeded the limit
reportAppendableHistory(path, partner, null, null, VcsConfiguration.getInstance(myVcs.getProject()).MAXIMUM_HISTORY_ROWS + 1, null, false);
@@ -187,7 +192,7 @@
}
}
- final boolean showMergeSources = SvnConfiguration.getInstance(myVcs.getProject()).SHOW_MERGE_SOURCES_IN_ANNOTATE;
+ final boolean showMergeSources = SvnConfiguration.getInstance(myVcs.getProject()).isShowMergeSourcesInAnnotate();
final LogLoader logLoader;
if (path.isNonLocal()) {
logLoader = new RepositoryLoader(myVcs, committedPath, from, to, limit, peg, forceBackwards, showMergeSources);
@@ -220,6 +225,7 @@
indicator.setText(SvnBundle.message("progress.text2.collecting.history", path.getName()));
}
final Consumer<VcsFileRevision> consumer = new Consumer<VcsFileRevision>() {
+ @Override
public void consume(VcsFileRevision vcsFileRevision) {
if (!Boolean.TRUE.equals(sessionReported.get())) {
partner.reportCreatedEmptySession(historySession);
@@ -311,11 +317,12 @@
myPI.setText2(SvnBundle.message("progress.text2.changes.establishing.connection", myUrl));
}
final SVNRevision pegRevision = myInfo.getRevision();
+ final SvnTarget target = SvnTarget.fromFile(myFile.getIOFile(), myPeg);
try {
- myVcs.getFactory(myFile.getIOFile()).createHistoryClient().doLog(
- myFile.getIOFile(),
+ myVcs.getFactory(target).createHistoryClient().doLog(
+ target,
myFrom == null ? SVNRevision.HEAD : myFrom,
- myTo == null ? SVNRevision.create(1) : myTo, myPeg,
+ myTo == null ? SVNRevision.create(1) : myTo,
false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
new MyLogEntryHandler(myVcs, myUrl, pegRevision, relativeUrl,
createConsumerAdapter(myConsumer),
@@ -378,7 +385,10 @@
final SVNURL svnurl = SVNURL.parseURIEncoded(myUrl);
SVNRevision operationalFrom = myFrom == null ? SVNRevision.HEAD : myFrom;
- final SVNURL rootURL = getRepositoryRoot(svnurl, myFrom);
+ // TODO: try to rewrite without separately retrieving repository url by item url - as this command could require authentication
+ // TODO: and it is not "clear enough/easy to implement" with current design (for some cases) how to cache credentials (if in
+ // TODO: non-interactive mode)
+ final SVNURL rootURL = SvnUtil.getRepositoryRoot(myVcs, svnurl);
if (rootURL == null) {
throw new VcsException("Could not find repository root for URL: " + myUrl);
}
@@ -387,12 +397,13 @@
if (myUrl.startsWith(root)) {
relativeUrl = myUrl.substring(root.length());
}
- // TODO: Update this call to myVcs.getFactory.createHistoryClient
- SVNLogClient client = myVcs.createLogClient();
- // a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
- client.doLog(svnurl, new String[]{}, myPeg == null ? myFrom : myPeg,
- operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15, myLimit + 1, null,
- new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, createConsumerAdapter(myConsumer), rootURL));
+ SvnTarget target = SvnTarget.fromURL(svnurl, myPeg == null ? myFrom : myPeg);
+ RepositoryLogEntryHandler handler =
+ new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl, createConsumerAdapter(myConsumer), rootURL);
+
+ myVcs.getFactory(target).createHistoryClient()
+ .doLog(target, operationalFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15,
+ myLimit + 1, null, handler);
}
catch (SVNCancelException e) {
//
@@ -406,34 +417,30 @@
}
private void loadBackwards(SVNURL svnurl) throws SVNException, VcsException {
- final SVNURL rootURL = getRepositoryRoot(svnurl, myFrom);
- final String root = rootURL.toString();
- String relativeUrl = myUrl;
- if (myUrl.startsWith(root)) {
- relativeUrl = myUrl.substring(root.length());
- }
+ // this method is called when svnurl does not exist in latest repository revision - thus concrete old revision is used for "info"
+ // command to get repository url
+ SVNInfo info = myVcs.getInfo(svnurl, myPeg, myPeg);
+ final SVNURL rootURL = info != null ? info.getRepositoryRootURL() : null;
+ final String root = rootURL != null ? rootURL.toString() : "";
+ String relativeUrl = myUrl;
+ if (myUrl.startsWith(root)) {
+ relativeUrl = myUrl.substring(root.length());
+ }
- // TODO: Update this call to myVcs.getFactory.createHistoryClient
- SVNLogClient client = myVcs.createLogClient();
-
- final RepositoryLogEntryHandler repositoryLogEntryHandler =
+ final RepositoryLogEntryHandler repositoryLogEntryHandler =
new RepositoryLogEntryHandler(myVcs, myUrl, SVNRevision.UNDEFINED, relativeUrl,
new ThrowableConsumer<VcsFileRevision, SVNException>() {
@Override
public void consume(VcsFileRevision revision) throws SVNException {
myConsumer.consume(revision);
- throw new SVNCancelException(); // load only one revision
}
}, rootURL);
- repositoryLogEntryHandler.setThrowCancelOnMeetPathCreation(true);
+ repositoryLogEntryHandler.setThrowCancelOnMeetPathCreation(true);
- client.doLog(rootURL, new String[]{}, myFrom, myFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15, 0, null, repositoryLogEntryHandler);
- }
-
- private SVNURL getRepositoryRoot(SVNURL svnurl, SVNRevision operationalFrom) throws SVNException {
- SVNInfo info = myVcs.getInfo(svnurl, SVNRevision.HEAD);
-
- return info != null ? info.getRepositoryRootURL() : null;
+ SvnTarget target = SvnTarget.fromURL(rootURL, myFrom);
+ myVcs.getFactory(target).createHistoryClient()
+ .doLog(target, myFrom, myTo == null ? SVNRevision.create(1) : myTo, false, true, myShowMergeSources && mySupport15, 1, null,
+ repositoryLogEntryHandler);
}
private boolean existsNow(SVNURL svnurl) {
@@ -448,14 +455,17 @@
}
}
+ @Override
public String getHelpId() {
return null;
}
+ @Override
public AnAction[] getAdditionalActions(final Runnable refresher) {
return new AnAction[]{ ShowAllAffectedGenericAction.getInstance(), new MergeSourceDetailsAction(), new SvnEditCommitMessageFromFileHistoryAction()};
}
+ @Override
public boolean isDateOmittable() {
return false;
}
@@ -494,6 +504,7 @@
myUrl = url;
myRepositoryRoot = repoRootURL;
myTracker = new SvnMergeSourceTracker(new ThrowableConsumer<Pair<SVNLogEntry, Integer>, SVNException>() {
+ @Override
public void consume(final Pair<SVNLogEntry, Integer> svnLogEntryIntegerPair) throws SVNException {
final SVNLogEntry logEntry = svnLogEntryIntegerPair.getFirst();
@@ -522,7 +533,10 @@
// mergeLevel >= 0 indicates that we are currently processing some "merge source" revision. This "merge source" revision
// contains changes from some other branch - so checkForChildChanges() and checkForParentChanges() return "false".
// Because of this case we apply these methods only for non-"merge source" revisions - this means mergeLevel < 0.
- if (mergeLevel < 0 && !checkForChildChanges(logEntry) && !checkForParentChanges(logEntry)) return;
+ // TODO: Do not apply path filtering even for log entries on the first level => just output of 'svn log' should be returned.
+ // TODO: Looks like there is no cases when we issue 'svn log' for some parent paths or some other cases where we need such
+ // TODO: filtering. Check user feedback on this.
+// if (mergeLevel < 0 && !checkForChildChanges(logEntry) && !checkForParentChanges(logEntry)) return;
}
}
@@ -548,6 +562,7 @@
while (path.length() > 0) {
final SVNLogEntryPath entryPath = logEntry.getChangedPaths().get(path);
// A & D are checked since we are not interested in parent folders property changes, only in structure changes
+ // TODO: seems that R (replaced) should also be checked here
if (entryPath != null && (entryPath.getType() == 'A' || entryPath.getType() == 'D')) {
if (entryPath.getCopyPath() != null) {
return true;
@@ -559,6 +574,8 @@
return false;
}
+ // TODO: this makes sense only for directories, but should always return true if something under the directory was changed in revision
+ // TODO: as svn will provide child changes in history for directory
private boolean checkForChildChanges(SVNLogEntry logEntry) {
final String lastPathBefore = myLastPathCorrector.getBefore();
for (String key : logEntry.getChangedPaths().keySet()) {
@@ -569,11 +586,12 @@
return false;
}
+ @Override
public void handleLogEntry(SVNLogEntry logEntry) throws SVNException {
myTracker.consume(logEntry);
}
- private void addToListByLevel(final SvnFileRevision revision, final SvnFileRevision revisionToAdd, final int level) {
+ private static void addToListByLevel(final SvnFileRevision revision, final SvnFileRevision revisionToAdd, final int level) {
if (level < 0) {
return;
}
@@ -671,6 +689,7 @@
return myRenderer;
}
+ @Override
public RevisionMergeSourceInfo valueOf(final VcsFileRevision vcsFileRevision) {
return vcsFileRevision != null ? new RevisionMergeSourceInfo(vcsFileRevision) : null;
}
@@ -702,7 +721,7 @@
}
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (e.getButton() == 1 && !e.isPopupTrigger()) {
Object tag = getTagAt(e);
if (tag == myTag) {
@@ -729,6 +748,7 @@
return null;
}
+ @Override
public void mouseMoved(MouseEvent e) {
JTable table = (JTable)e.getSource();
Object tag = getTagAt(e);
@@ -753,6 +773,7 @@
return RevisionMergeSourceInfo.toString(value);
}
+ @Override
protected void customizeCellRenderer(final JTable table,
final Object value,
final boolean selected,
@@ -801,6 +822,7 @@
private static class CopyFromColumnInfo extends ColumnInfo<VcsFileRevision, String> {
private final Icon myIcon = PlatformIcons.COPY_ICON;
private final ColoredTableCellRenderer myRenderer = new ColoredTableCellRenderer() {
+ @Override
protected void customizeCellRenderer(final JTable table,
final Object value,
final boolean selected,
@@ -821,6 +843,7 @@
super(SvnBundle.message("copy.column.title"));
}
+ @Override
public String valueOf(final VcsFileRevision o) {
return o instanceof SvnFileRevision ? ((SvnFileRevision)o).getCopyFromPath() : "";
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java
index 6d41285..f58e6c8 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnKitHistoryClient.java
@@ -1,13 +1,16 @@
package org.jetbrains.idea.svn.history;
import com.intellij.openapi.vcs.VcsException;
+import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.BaseSvnClient;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
@@ -15,11 +18,11 @@
* @author Konstantin Kolosovsky.
*/
public class SvnKitHistoryClient extends BaseSvnClient implements HistoryClient {
+
@Override
- public void doLog(@NotNull File path,
+ public void doLog(@NotNull SvnTarget target,
@NotNull SVNRevision startRevision,
@NotNull SVNRevision endRevision,
- @Nullable SVNRevision pegRevision,
boolean stopOnCopy,
boolean discoverChangedPaths,
boolean includeMergedRevisions,
@@ -30,11 +33,17 @@
// TODO: a bug noticed when testing: we should pass "limit + 1" to get "limit" rows
SVNLogClient client = myVcs.createLogClient();
- client.doLog(new File[]{path}, startRevision, endRevision, pegRevision, stopOnCopy, discoverChangedPaths, includeMergedRevisions,
- limit, revisionProperties, handler);
+ if (target.isFile()) {
+ client.doLog(new File[]{target.getFile()}, startRevision, endRevision, target.getPegRevision(), stopOnCopy, discoverChangedPaths,
+ includeMergedRevisions, limit, revisionProperties, handler);
+ }
+ else {
+ client.doLog(target.getURL(), ArrayUtil.EMPTY_STRING_ARRAY, target.getPegRevision(), startRevision, endRevision, stopOnCopy,
+ discoverChangedPaths, includeMergedRevisions, limit, revisionProperties, handler);
+ }
}
catch (SVNException e) {
- throw new VcsException(e);
+ throw new SvnBindException(e);
}
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLoadingRepositoryLocation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLoadingRepositoryLocation.java
deleted file mode 100644
index 3fcc5c3..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLoadingRepositoryLocation.java
+++ /dev/null
@@ -1,35 +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 org.jetbrains.idea.svn.history;
-
-import com.intellij.openapi.vcs.FilePath;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.idea.svn.SvnVcs;
-
-public class SvnLoadingRepositoryLocation extends SvnRepositoryLocation {
- private final LocationDetector locationDetector;
-
- public SvnLoadingRepositoryLocation(final FilePath rootFile, @NotNull final String URL, @NotNull final SvnVcs vcs) {
- super(URL);
- locationDetector = new LocationDetector(vcs);
- }
-
- public SvnLoadingRepositoryLocation(@NotNull final String URL, @NotNull final SvnVcs vcs) {
- super(URL);
- locationDetector = new LocationDetector(vcs);
- }
-
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogLoader.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogLoader.java
index 4ed82c6..0ff2e3b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogLoader.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogLoader.java
@@ -15,13 +15,14 @@
*/
package org.jetbrains.idea.svn.history;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
-import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.wc.SVNRevision;
import java.util.List;
public interface SvnLogLoader {
List<CommittedChangeList> loadInterval(final SVNRevision fromIncluding, final SVNRevision toIncluding,
- final int maxCount, final boolean includingYoungest, final boolean includeOldest) throws SVNException;
+ final int maxCount, final boolean includingYoungest, final boolean includeOldest)
+ throws VcsException;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java
index db22955..7f4f25f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnLogUtil.java
@@ -19,15 +19,16 @@
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.ISVNLogEntryHandler;
-import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.SVNLogClient;
import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.util.ArrayList;
import java.util.List;
@@ -37,48 +38,47 @@
private final SvnVcs myVcs;
private final SvnRepositoryLocation myLocation;
private final SVNURL myRepositoryRoot;
- private final String myRelative;
public SvnLogUtil(final Project project, final SvnVcs vcs, final SvnRepositoryLocation location, final SVNURL repositoryRoot) {
myProject = project;
myVcs = vcs;
myLocation = location;
myRepositoryRoot = repositoryRoot;
-
- final String repositoryRootPath = repositoryRoot.toString();
- myRelative = myLocation.getURL().substring(repositoryRootPath.length());
}
public List<CommittedChangeList> loadInterval(final SVNRevision fromIncluding, final SVNRevision toIncluding,
- final int maxCount, final boolean includingYoungest, final boolean includeOldest) throws SVNException {
+ final int maxCount, final boolean includingYoungest, final boolean includeOldest)
+ throws VcsException {
final List<CommittedChangeList> result = new ArrayList<CommittedChangeList>();
- loadRevisions(fromIncluding, toIncluding, null, maxCount, result, includingYoungest, includeOldest);
+ ISVNLogEntryHandler handler = createLogHandler(fromIncluding, toIncluding, includingYoungest, includeOldest, result);
+ SvnTarget target = SvnTarget.fromURL(myLocation.toSvnUrl());
+
+ myVcs.getFactory(target).createHistoryClient().doLog(target, fromIncluding, toIncluding, true, true, false, maxCount, null, handler);
+
return result;
}
- private void loadRevisions(final SVNRevision fromIncluding, final SVNRevision toIncluding, final String author, final int maxCount,
- final List<CommittedChangeList> result,
- final boolean includingYoungest, final boolean includeOldest) throws SVNException {
- SVNLogClient logger = myVcs.createLogClient();
- logger.doLog(myRepositoryRoot, new String[]{myRelative}, SVNRevision.UNDEFINED, fromIncluding, toIncluding, true, true, maxCount,
- new ISVNLogEntryHandler() {
- public void handleLogEntry(SVNLogEntry logEntry) {
- if (myProject.isDisposed()) throw new ProcessCanceledException();
- final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
- if (progress != null) {
- progress.setText2(SvnBundle.message("progress.text2.processing.revision", logEntry.getRevision()));
- progress.checkCanceled();
- }
- if ((! includingYoungest) && (logEntry.getRevision() == fromIncluding.getNumber())) {
- return;
- }
- if ((! includeOldest) && (logEntry.getRevision() == toIncluding.getNumber())) {
- return;
- }
- if (author == null || author.equalsIgnoreCase(logEntry.getAuthor())) {
- result.add(new SvnChangeList(myVcs, myLocation, logEntry, myRepositoryRoot.toString()));
- }
- }
- });
+ @NotNull
+ private ISVNLogEntryHandler createLogHandler(final SVNRevision fromIncluding,
+ final SVNRevision toIncluding,
+ final boolean includingYoungest,
+ final boolean includeOldest, final List<CommittedChangeList> result) {
+ return new ISVNLogEntryHandler() {
+ public void handleLogEntry(SVNLogEntry logEntry) {
+ if (myProject.isDisposed()) throw new ProcessCanceledException();
+ final ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
+ if (progress != null) {
+ progress.setText2(SvnBundle.message("progress.text2.processing.revision", logEntry.getRevision()));
+ progress.checkCanceled();
+ }
+ if ((!includingYoungest) && (logEntry.getRevision() == fromIncluding.getNumber())) {
+ return;
+ }
+ if ((!includeOldest) && (logEntry.getRevision() == toIncluding.getNumber())) {
+ return;
+ }
+ result.add(new SvnChangeList(myVcs, myLocation, logEntry, myRepositoryRoot.toString()));
+ }
+ };
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java
index 35b7b4d..8ecb8a3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnPathThroughHistoryCorrection.java
@@ -64,6 +64,8 @@
}
for (SVNLogEntryPath path : paths.values()) {
// "the origin path *from where* the item, ..."
+ // TODO: this could incorrectly handle case when parent folder was replaced - see IDEA-103042
+ // TODO: or several parent folder renames occur IDEA-96825
final String copyPath = path.getCopyPath();
if (copyPath != null) {
final String thisEntryPath = path.getPath();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java
index 49e8c1d..fb7499c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryBinaryContentRevision.java
@@ -18,6 +18,7 @@
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.BinaryContentRevision;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnVcs;
@@ -27,9 +28,9 @@
public class SvnRepositoryBinaryContentRevision extends SvnRepositoryContentRevision implements BinaryContentRevision {
private byte[] myBinaryContent;
- public SvnRepositoryBinaryContentRevision(final SvnVcs vcs, final String repositoryRoot, final String path,
+ public SvnRepositoryBinaryContentRevision(final SvnVcs vcs, @NotNull final FilePath remotePath,
@Nullable final FilePath localPath, final long revision) {
- super(vcs, repositoryRoot, path, localPath, revision);
+ super(vcs, remotePath, localPath, revision);
}
@Nullable
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
index b7a0bb9..36c80b1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
@@ -23,23 +23,24 @@
package org.jetbrains.idea.svn.history;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.fileTypes.FileType;
-import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.util.Throwable2Computable;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.VcsKey;
-import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.openapi.vcs.changes.ContentRevision;
import com.intellij.openapi.vcs.changes.MarkerVcsContentRevision;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.impl.ContentRevisionCache;
+import com.intellij.vcsUtil.VcsUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.idea.svn.*;
-import org.tmatesoft.svn.core.SVNException;
+import org.jetbrains.idea.svn.SvnBundle;
+import org.jetbrains.idea.svn.SvnRevisionNumber;
+import org.jetbrains.idea.svn.SvnUtil;
+import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -48,32 +49,16 @@
import java.io.OutputStream;
public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsContentRevision {
- private final String myRepositoryRoot;
private final SvnVcs myVcs;
private final String myPath;
@NotNull private final FilePath myFilePath;
private final long myRevision;
- SvnRepositoryContentRevision(final SvnVcs vcs, final String repositoryRoot, final String path, @Nullable final FilePath localPath,
+ public SvnRepositoryContentRevision(final SvnVcs vcs, @NotNull final FilePath remotePath, @Nullable final FilePath localPath,
final long revision) {
myVcs = vcs;
- myPath = path;
- myRepositoryRoot = repositoryRoot;
- if (localPath != null) {
- myFilePath = localPath;
- }
- else {
- FilePath local;
- try {
- final String fullPath = SvnUtil.appendMultiParts(repositoryRoot, myPath);
- local = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, false);
- }
- catch (SVNException e) {
- // todo what to do safely?
- local = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(repositoryRoot, false);
- }
- myFilePath = local;
- }
+ myPath = FileUtil.toSystemIndependentName(remotePath.getPath());
+ myFilePath = localPath != null ? localPath : remotePath;
myRevision = revision;
}
@@ -125,15 +110,19 @@
public static SvnRepositoryContentRevision create(final SvnVcs vcs, final String repositoryRoot, final String path,
@Nullable final FilePath localPath, final long revision) {
- int fileNamePos = path.lastIndexOf('/');
- if (fileNamePos >= 0) {
- String fileName = path.substring(fileNamePos);
- final FileType fileType = FileTypeManager.getInstance().getFileTypeByFileName(fileName);
- if (fileType.isBinary()) {
- return new SvnRepositoryBinaryContentRevision(vcs, repositoryRoot, path, localPath, revision);
- }
- }
- return new SvnRepositoryContentRevision(vcs, repositoryRoot, path, localPath, revision);
+ // TODO: Check if isDirectory = false always true for this method calls
+ FilePath remotePath = VcsUtil.getFilePathOnNonLocal(SvnUtil.appendMultiParts(repositoryRoot, path), false);
+
+ return create(vcs, remotePath, localPath, revision);
+ }
+
+ public static SvnRepositoryContentRevision create(@NotNull SvnVcs vcs,
+ @NotNull FilePath remotePath,
+ @Nullable FilePath localPath,
+ long revision) {
+ return remotePath.getFileType().isBinary()
+ ? new SvnRepositoryBinaryContentRevision(vcs, remotePath, localPath, revision)
+ : new SvnRepositoryContentRevision(vcs, remotePath, localPath, revision);
}
@Override
@@ -180,12 +169,7 @@
}
public String getFullPath() {
- String fullPath = myRepositoryRoot;
- if (!fullPath.endsWith("/") && !myPath.startsWith("/")) {
- fullPath += "/";
- }
- fullPath += myPath;
- return fullPath;
+ return myPath;
}
public String getPath() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
index 3d5bcaf..5dc605b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
@@ -18,10 +18,15 @@
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.RepositoryLocation;
import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vcs.actions.VcsContextFactory;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.RootUrlInfo;
+import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
+import org.jetbrains.idea.svn.commandLine.SvnBindException;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
import java.io.File;
@@ -63,10 +68,24 @@
public static FilePath getLocalPath(final String fullPath, final NotNullFunction<File, Boolean> detector, final SvnVcs vcs) {
if (vcs.getProject().isDefault()) return null;
final RootUrlInfo rootForUrl = vcs.getSvnFileUrlMapping().getWcRootForUrl(fullPath);
+ FilePath result = null;
+
if (rootForUrl != null) {
- return LocationDetector.filePathByUrlAndPath(fullPath, rootForUrl.getUrl().toString(), rootForUrl.getIoFile().getAbsolutePath(), detector);
+ String relativePath = SvnUtil.getRelativeUrl(rootForUrl.getUrl(), fullPath);
+ File file = new File(rootForUrl.getPath(), relativePath);
+
+ result = VcsContextFactory.SERVICE.getInstance().createFilePathOn(file, detector);
}
- return null;
+ return result;
+ }
+
+ public SVNURL toSvnUrl() throws VcsException {
+ try {
+ return SvnUtil.createUrl(myURL);
+ }
+ catch (SVNException e) {
+ throw new SvnBindException(e);
+ }
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java
index 26e5152..8f29e01 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRevisionsNavigationMediator.java
@@ -29,8 +29,8 @@
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.io.SVNRepository;
+import org.tmatesoft.svn.core.wc.SVNInfo;
+import org.tmatesoft.svn.core.wc.SVNRevision;
import java.util.*;
@@ -55,31 +55,30 @@
myChunks = new LinkedList<List<Fragment>>();
- final SVNURL[] repositoryRoot = new SVNURL[1];
- final long[] youngRevision = new long[1];
final VcsException[] exception = new VcsException[1];
+ final Ref<SVNInfo> infoRef = new Ref<SVNInfo>();
Runnable process = new Runnable() {
@Override
public void run() {
- SVNRepository repository = null;
try {
- repository = vcs.createRepository(location.getURL());
- youngRevision[0] = repository.getLatestRevision();
- repositoryRoot[0] = repository.getRepositoryRoot(false);
+ infoRef.set(vcs.getInfo(location.toSvnUrl(), SVNRevision.HEAD));
+ }
+ catch (VcsException e) {
+ exception[0] = e;
}
catch (SVNException e) {
exception[0] = new VcsException(e);
}
- finally {
- if (repository != null) {
- repository.closeSession();
- }
- }
}
};
underProgress(exception, process);
+ SVNInfo info = infoRef.get();
+ if (info == null || info.getRevision() == null || info.getRepositoryRootURL() == null) {
+ throw new VcsException("Could not get head info for " + location);
+ }
+
final Iterator<ChangesBunch> visualIterator = project.isDefault() ? null :
CommittedChangesCache.getInstance(project).getBackBunchedIterator(vcs, vcsRoot, location, CHUNK_SIZE);
final Iterator<ChangesBunch> internalIterator = project.isDefault() ? null : LoadedRevisionsCache.getInstance(project).iterator(location.getURL());
@@ -87,8 +86,9 @@
myInternallyCached = (internalIterator == null) ? null : new InternallyCachedProvider(internalIterator, myProject);
myVisuallyCached = (visualIterator == null) ? null : new VisuallyCachedProvider(visualIterator, myProject, location);
- myChunkFactory = new BunchFactory(myInternallyCached, myVisuallyCached,
- new LiveProvider(vcs, location, youngRevision[0], new SvnLogUtil(myProject, vcs, location, repositoryRoot[0])));
+ myChunkFactory = new BunchFactory(myInternallyCached, myVisuallyCached, new LiveProvider(vcs, location, info.getRevision().getNumber(),
+ new SvnLogUtil(myProject, vcs, location,
+ info.getRepositoryRootURL())));
myCurrentIdx = -1;
@@ -133,13 +133,7 @@
}
final Ref<Boolean> canNotGoBackRef = new Ref<Boolean>();
- final List<Fragment> fragments;
- try {
- fragments = myChunkFactory.goBack(CHUNK_SIZE, canNotGoBackRef);
- }
- catch (SVNException e) {
- throw new VcsException(e);
- }
+ final List<Fragment> fragments = myChunkFactory.goBack(CHUNK_SIZE, canNotGoBackRef);
myCanNotGoBack = canNotGoBackRef.get().booleanValue();
if (! fragments.isEmpty()) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java
index 3c4c17e..cb62668 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/GroupMerger.java
@@ -31,7 +31,6 @@
import org.tmatesoft.svn.core.SVNDepth;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.SVNDiffOptions;
import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc.SVNRevisionRange;
import org.tmatesoft.svn.core.wc2.SvnTarget;
@@ -132,7 +131,7 @@
SvnTarget source = SvnTarget.fromURL(myCurrentBranchUrl);
MergeClient client = myVcs.getFactory(myTarget).createMergeClient();
- client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.MERGE_DRY_RUN, myDryRun, true,
+ client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.isMergeDryRun(), myDryRun, true,
mySvnConfig.getMergeOptions(), myHandler);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
index 8ceba6e..47d2633 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/IntegratedSelectedOptionsDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -97,8 +97,8 @@
}
SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject());
- myDryRunCheckbox.setSelected(svnConfig.MERGE_DRY_RUN);
- myIgnoreWhitespacesCheckBox.setSelected(svnConfig.IGNORE_SPACES_IN_MERGE);
+ myDryRunCheckbox.setSelected(svnConfig.isMergeDryRun());
+ myIgnoreWhitespacesCheckBox.setSelected(svnConfig.isIgnoreSpacesInMerge());
mySourceInfoLabel.setText(SvnBundle.message("action.Subversion.integrate.changes.branch.info.source.label.text", currentBranch));
myTargetInfoLabel.setText(SvnBundle.message("action.Subversion.integrate.changes.branch.info.target.label.text", selectedBranchUrl));
@@ -121,7 +121,7 @@
// local not consistent copy can not prevent us from integration: only remote local copy is really involved
if ((mySelectedRepositoryUUID != null) && (! mySelectedRepositoryUUID.equals(repositoryUUID))) {
- if (OK_EXIT_CODE == Messages.showOkCancelDialog((repositoryUUID == null) ? SvnBundle.message("action.Subversion.integrate.changes.message.not.under.control.text")
+ if (Messages.OK == Messages.showOkCancelDialog((repositoryUUID == null) ? SvnBundle.message("action.Subversion.integrate.changes.message.not.under.control.text")
: SvnBundle.message("action.Subversion.integrate.changes.message.another.wc.text"),
getTitle(), UIUtil.getWarningIcon())) {
onOkToAdd(file);
@@ -223,8 +223,8 @@
public void saveOptions() {
SvnConfiguration svnConfig = SvnConfiguration.getInstance(myVcs.getProject());
- svnConfig.MERGE_DRY_RUN = myDryRunCheckbox.isSelected();
- svnConfig.IGNORE_SPACES_IN_MERGE = myIgnoreWhitespacesCheckBox.isSelected();
+ svnConfig.setMergeDryRun(myDryRunCheckbox.isSelected());
+ svnConfig.setIgnoreSpacesInMerge(myIgnoreWhitespacesCheckBox.isSelected());
}
protected JComponent createCenterPanel() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java
index 1c50dde..8f534b9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/Merger.java
@@ -128,7 +128,7 @@
SvnTarget source = SvnTarget.fromURL(myCurrentBranchUrl);
MergeClient client = myVcs.getFactory(myTarget).createMergeClient();
- client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.MERGE_DRY_RUN, isRecordOnly(), true,
+ client.merge(source, createRange(), myTarget, SVNDepth.INFINITY, mySvnConfig.isMergeDryRun(), isRecordOnly(), true,
mySvnConfig.getMergeOptions(), myHandler);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java
index 78b8e86..1a58a3c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/PointMerger.java
@@ -18,7 +18,6 @@
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnRevisionNumber;
import org.jetbrains.idea.svn.SvnUtil;
@@ -88,7 +87,7 @@
SvnTarget source1 = SvnTarget.fromURL(SVNURL.parseURIEncoded(beforeUrl), ((SvnRevisionNumber)before.getRevisionNumber()).getRevision());
SvnTarget source2 = SvnTarget.fromURL(SVNURL.parseURIEncoded(afterUrl), ((SvnRevisionNumber) after.getRevisionNumber()).getRevision());
- client.merge(source1, source2, afterPath, SVNDepth.FILES, true, mySvnConfig.MERGE_DRY_RUN, false, false, mySvnConfig.getMergeOptions(),
+ client.merge(source1, source2, afterPath, SVNDepth.FILES, true, mySvnConfig.isMergeDryRun(), false, false, mySvnConfig.getMergeOptions(),
myHandler);
}
@@ -99,7 +98,7 @@
final File beforePath = SvnUtil.fileFromUrl(myTarget, path, beforeUrl);
DeleteClient client = myVcs.getFactory(myTarget).createDeleteClient();
- client.delete(beforePath, false, mySvnConfig.MERGE_DRY_RUN, myHandler);
+ client.delete(beforePath, false, mySvnConfig.isMergeDryRun(), myHandler);
}
private void add(final Change change) throws SVNException, VcsException {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java
index 93790e9..1348cd0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/QuickMergeInteractionImpl.java
@@ -159,6 +159,6 @@
}
private boolean prompt(final String question) {
- return Messages.showOkCancelDialog(myProject, question, myTitle, Messages.getQuestionIcon()) == 0;
+ return Messages.showOkCancelDialog(myProject, question, myTitle, Messages.getQuestionIcon()) == Messages.OK;
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java
index 45558e4..f283afa 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ResolveWorker.java
@@ -75,7 +75,7 @@
}
return ((! myConflictedVirtualFiles.isEmpty()) || (! haveUnresolvedConflicts(updatedFiles))) &&
- (! SvnConfiguration.getInstance(myProject).MERGE_DRY_RUN);
+ (!SvnConfiguration.getInstance(myProject).isMergeDryRun());
}
public static boolean haveUnresolvedConflicts(final UpdatedFiles updatedFiles) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java
index a793aae..e07fac0 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/SvnIntegrateChangesActionPerformer.java
@@ -69,7 +69,7 @@
return;
}
final SvnIntegrateChangesTask task = new SvnIntegrateChangesTask(myVcs, info, myMergerFactory, sourceUrl, SvnBundle.message("action.Subversion.integrate.changes.messages.title"),
- SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN, name);
+ SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun(), name);
ProgressManager.getInstance().run(task);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
index 20b8144..ead9b7d 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/BranchInfo.java
@@ -27,7 +27,6 @@
import org.tmatesoft.svn.core.wc.SVNInfo;
import org.tmatesoft.svn.core.wc.SVNPropertyData;
import org.tmatesoft.svn.core.wc.SVNRevision;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
@@ -55,7 +54,7 @@
private final MultiMap<Long, String> myPartlyMerged;
public BranchInfo(final SvnVcs vcs, final String repositoryRoot, final String branchUrl, final String trunkUrl,
- final String trunkCorrected, final SVNWCClient client) {
+ final String trunkCorrected) {
myVcs = vcs;
myRepositoryRoot = repositoryRoot;
myBranchUrl = branchUrl;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
index 39d72f5..f492a43 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneRecursiveShotMergeInfoWorker.java
@@ -63,7 +63,7 @@
}
public void prepare() throws VcsException {
- final SVNDepth depth = SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE ? SVNDepth.INFINITY : SVNDepth.EMPTY;
+ final SVNDepth depth = SvnConfiguration.getInstance(myProject).isCheckNestedForQuickMerge() ? SVNDepth.INFINITY : SVNDepth.EMPTY;
ISVNPropertyHandler handler = new ISVNPropertyHandler() {
public void handleProperty(File path, SVNPropertyData property) throws SVNException {
final String key = keyFromFile(path);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java
index 724ce95..d9ad5a3 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/SvnMergeInfoCache.java
@@ -33,8 +33,6 @@
import org.jetbrains.idea.svn.history.FirstInBranch;
import org.jetbrains.idea.svn.history.SvnChangeList;
import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
import java.util.HashMap;
import java.util.Map;
@@ -44,7 +42,6 @@
private final Project myProject;
private final MyState myState;
- private final SVNWCClient myClient;
public static Topic<SvnMergeInfoCacheListener> SVN_MERGE_INFO_CACHE = new Topic<SvnMergeInfoCacheListener>("SVN_MERGE_INFO_CACHE",
SvnMergeInfoCacheListener.class);
@@ -52,14 +49,6 @@
private SvnMergeInfoCache(final Project project) {
myProject = project;
myState = new MyState();
- final SvnVcs vcs = SvnVcs.getInstance(myProject);
- myClient = vcs.createWCClient();
- myClient.setOptions(new DefaultSVNOptions() {
- @Override
- public byte[] getNativeEOL() {
- return new byte[]{'\n'};
- }
- });
}
public static SvnMergeInfoCache getInstance(final Project project) {
@@ -112,7 +101,7 @@
mergeChecker = rootMapping.getBranchInfo(branchPath);
}
if (mergeChecker == null) {
- mergeChecker = new BranchInfo(SvnVcs.getInstance(myProject), info.getRepoUrl(), branchUrl, currentUrl, info.getTrunkRoot(), myClient);
+ mergeChecker = new BranchInfo(SvnVcs.getInstance(myProject), info.getRepoUrl(), branchUrl, currentUrl, info.getTrunkRoot());
rootMapping.addBranchInfo(branchPath, mergeChecker);
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ConflictActionConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ConflictActionConvertor.java
deleted file mode 100644
index 7a9329a..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ConflictActionConvertor.java
+++ /dev/null
@@ -1,42 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.ConflictDescriptor;
-import org.tmatesoft.svn.core.wc.SVNConflictAction;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/23/12
- * Time: 7:09 PM
- */
-public class ConflictActionConvertor {
- public static SVNConflictAction create(final ConflictDescriptor conflict) {
- return create(conflict.getAction());
- }
-
- public static SVNConflictAction create(ConflictDescriptor.Action action) {
- if (ConflictDescriptor.Action.add.equals(action)) {
- return SVNConflictAction.ADD;
- } else if (ConflictDescriptor.Action.delete.equals(action)) {
- return SVNConflictAction.DELETE;
- } else if (ConflictDescriptor.Action.edit.equals(action)) {
- return SVNConflictAction.EDIT;
- }
- throw new IllegalStateException();
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ConflictReasonConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ConflictReasonConvertor.java
deleted file mode 100644
index acfb490..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ConflictReasonConvertor.java
+++ /dev/null
@@ -1,44 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.ConflictDescriptor;
-import org.tmatesoft.svn.core.wc.SVNConflictReason;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/23/12
- * Time: 7:26 PM
- */
-public class ConflictReasonConvertor {
- public static SVNConflictReason convert(ConflictDescriptor.Reason reason) {
- if (ConflictDescriptor.Reason.added.equals(reason)) {
- return SVNConflictReason.ADDED;
- } else if (ConflictDescriptor.Reason.deleted.equals(reason)) {
- return SVNConflictReason.DELETED;
- } else if (ConflictDescriptor.Reason.edited.equals(reason)) {
- return SVNConflictReason.EDITED;
- } else if (ConflictDescriptor.Reason.missing.equals(reason)) {
- return SVNConflictReason.MISSING;
- } else if (ConflictDescriptor.Reason.obstructed.equals(reason)) {
- return SVNConflictReason.OBSTRUCTED;
- } else if (ConflictDescriptor.Reason.unversioned.equals(reason)) {
- return SVNConflictReason.UNVERSIONED;
- }
- throw new IllegalStateException();
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/DepthConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/DepthConvertor.java
deleted file mode 100644
index d2b4d03..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/DepthConvertor.java
+++ /dev/null
@@ -1,61 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.types.Depth;
-import org.tmatesoft.svn.core.SVNDepth;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/21/12
- * Time: 7:09 PM
- */
-public class DepthConvertor {
- public static SVNDepth convert(Depth depth) {
- if (Depth.infinity.equals(depth)) {
- return SVNDepth.INFINITY;
- } else if (Depth.unknown.equals(depth)) {
- return SVNDepth.UNKNOWN;
- } else if (Depth.empty.equals(depth)) {
- return SVNDepth.EMPTY;
- } else if (Depth.exclude.equals(depth)) {
- return SVNDepth.EXCLUDE;
- } else if (Depth.files.equals(depth)) {
- return SVNDepth.FILES;
- } else if (Depth.immediates.equals(depth)) {
- return SVNDepth.IMMEDIATES;
- }
- throw new UnsupportedOperationException();
- }
-
- public static Depth convert(SVNDepth depth) {
- if (SVNDepth.INFINITY.equals(depth)) {
- return Depth.infinity;
- } else if (SVNDepth.UNKNOWN.equals(depth)) {
- return Depth.unknown;
- } else if (SVNDepth.EMPTY.equals(depth)) {
- return Depth.empty;
- } else if (SVNDepth.EXCLUDE.equals(depth)) {
- return Depth.exclude;
- } else if (SVNDepth.FILES.equals(depth)) {
- return Depth.files;
- } else if (SVNDepth.IMMEDIATES.equals(depth)) {
- return Depth.immediates;
- }
- throw new UnsupportedOperationException();
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ExceptionConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ExceptionConvertor.java
deleted file mode 100644
index 5d2d9c8..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/ExceptionConvertor.java
+++ /dev/null
@@ -1,33 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.ClientException;
-import org.tmatesoft.svn.core.SVNErrorCode;
-import org.tmatesoft.svn.core.SVNErrorMessage;
-import org.tmatesoft.svn.core.SVNException;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/24/12
- * Time: 11:54 AM
- */
-public class ExceptionConvertor {
- public static SVNException convert(final ClientException exception) {
- return new SVNException(SVNErrorMessage.create(SVNErrorCode.getErrorCode(exception.getAprError())));
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoCallbackConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoCallbackConvertor.java
deleted file mode 100644
index fa26a94..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoCallbackConvertor.java
+++ /dev/null
@@ -1,45 +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 org.jetbrains.idea.svn.portable;
-
-import com.intellij.util.Consumer;
-import org.apache.subversion.javahl.callback.InfoCallback;
-import org.apache.subversion.javahl.types.Info;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.wc.ISVNInfoHandler;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/21/12
- * Time: 7:18 PM
- */
-public class InfoCallbackConvertor {
- public static InfoCallback create(final ISVNInfoHandler callback, final Consumer<SVNException> exceptionConsumer) {
- return new InfoCallback() {
- @Override
- public void singleInfo(Info info) {
- if (callback == null) return;
- try {
- callback.handleInfo(InfoConvertor.convert(info));
- }
- catch (SVNException e) {
- exceptionConsumer.consume(e);
- }
- }
- };
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoConvertor.java
deleted file mode 100644
index faea19e..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/InfoConvertor.java
+++ /dev/null
@@ -1,112 +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 org.jetbrains.idea.svn.portable;
-
-import com.intellij.openapi.diagnostic.Logger;
-import org.apache.subversion.javahl.ConflictDescriptor;
-import org.apache.subversion.javahl.types.ConflictVersion;
-import org.apache.subversion.javahl.types.Info;
-import org.jetbrains.annotations.Nullable;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNProperty;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.internal.wc.SVNConflictVersion;
-import org.tmatesoft.svn.core.wc.SVNInfo;
-import org.tmatesoft.svn.core.wc.SVNTreeConflictDescription;
-
-import java.io.File;
-import java.util.Set;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/21/12
- * Time: 7:21 PM
- */
-public class InfoConvertor {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.portable.InfoConvertor");
-
- public static Info convert(SVNInfo info) {
- throw new UnsupportedOperationException();
- }
-
- public static SVNInfo convert(Info info) throws SVNException {
- // !! prop time is NOT filled
- final Set<ConflictDescriptor> conflicts = info.getConflicts();
- String oldConflict = null;
- String newConflict = null;
- String wrkConflict = null;
- String propConflict = null;
- SVNTreeConflictDescription description = null;
- if (conflicts != null && ! conflicts.isEmpty()) {
- for (ConflictDescriptor conflict : conflicts) {
- if (ConflictDescriptor.Kind.property.equals(conflict.getKind())) {
- propConflict = conflict.getPropertyName();
- } else if (ConflictDescriptor.Kind.tree.equals(conflict.getKind())) {
- description = createTreeConflict(conflict);
- } else {
- oldConflict = conflict.getBasePath();
- newConflict = conflict.getTheirPath();
- wrkConflict = conflict.getMyPath();
- }
- }
- }
-
- return new IdeaSVNInfo(new File(info.getPath()), url(info.getUrl()), url(info.getReposRootUrl()),
- info.getRev(), NodeKindConvertor.convert(info.getKind()), info.getReposUUID(), info.getLastChangedRev(),
- info.getLastChangedDate(), info.getLastChangedAuthor(), convertSchedule(info.getSchedule()),
- url(info.getCopyFromUrl()), info.getCopyFromRev(), info.getTextTime(), null,
- checksum(info), oldConflict, newConflict, wrkConflict, propConflict, null,
- DepthConvertor.convert(info.getDepth()), info.getChangelistName(), info.getWorkingSize(), description);
- }
-
- @Nullable
- private static SVNURL url(String url) throws SVNException {
- return url == null ? null : SVNURL.parseURIEncoded(url);
- }
-
- @Nullable
- private static String checksum(Info info) {
- return info.getChecksum() == null ? null : new String(info.getChecksum().getDigest());
- }
-
- private static SVNTreeConflictDescription createTreeConflict(final ConflictDescriptor conflict) throws SVNException {
- return new SVNTreeConflictDescription(new File(conflict.getPath()), NodeKindConvertor.convert(conflict.getNodeKind()),
- ConflictActionConvertor.create(conflict), ConflictReasonConvertor.convert(conflict.getReason()),
- OperationConvertor.convert(conflict.getOperation()),
- createConflictVersion(conflict.getSrcLeftVersion()),
- createConflictVersion(conflict.getSrcRightVersion()));
- }
-
- @Nullable
- private static SVNConflictVersion createConflictVersion(ConflictVersion version) throws SVNException {
- return version == null ? null : new SVNConflictVersion(url(version.getReposURL()), version.getPathInRepos(), version.getPegRevision(),
- NodeKindConvertor.convert(version.getNodeKind()));
- }
-
- public static String convertSchedule(Info.ScheduleKind schedule) {
- if (Info.ScheduleKind.normal.equals(schedule)) {
- return "normal";
- } else if (Info.ScheduleKind.add.equals(schedule)) {
- return SVNProperty.SCHEDULE_ADD;
- } else if (Info.ScheduleKind.delete.equals(schedule)) {
- return SVNProperty.SCHEDULE_DELETE;
- } else if (Info.ScheduleKind.replace.equals(schedule)) {
- return SVNProperty.SCHEDULE_REPLACE;
- }
- return "normal";
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/JavaHLSvnStatusClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/JavaHLSvnStatusClient.java
deleted file mode 100644
index a864954..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/JavaHLSvnStatusClient.java
+++ /dev/null
@@ -1,149 +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 org.jetbrains.idea.svn.portable;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.util.Consumer;
-import com.intellij.util.containers.Convertor;
-import org.apache.subversion.javahl.ClientException;
-import org.apache.subversion.javahl.SVNClient;
-import org.apache.subversion.javahl.callback.InfoCallback;
-import org.apache.subversion.javahl.types.Depth;
-import org.apache.subversion.javahl.types.Info;
-import org.apache.subversion.javahl.types.Revision;
-import org.tmatesoft.svn.core.SVNDepth;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.wc.*;
-
-import java.io.File;
-import java.util.Collection;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/24/12
- * Time: 9:51 AM
- */
-public class JavaHLSvnStatusClient implements SvnStatusClientI {
- private final Project myProject;
-
- public JavaHLSvnStatusClient(final Project project) {
- myProject = project;
- }
-
- @Override
- public long doStatus(File path, boolean recursive, boolean remote, boolean reportAll, boolean includeIgnored, ISVNStatusHandler handler)
- throws SVNException {
- return doStatus(path, SVNRevision.UNDEFINED, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, remote, reportAll, includeIgnored,
- false, handler, null);
- }
-
- @Override
- public long doStatus(File path,
- boolean recursive,
- boolean remote,
- boolean reportAll,
- boolean includeIgnored,
- boolean collectParentExternals,
- ISVNStatusHandler handler) throws SVNException {
- return doStatus(path, SVNRevision.UNDEFINED, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, remote, reportAll, includeIgnored,
- collectParentExternals, handler, null);
- }
-
- @Override
- public long doStatus(File path,
- SVNRevision revision,
- boolean recursive,
- boolean remote,
- boolean reportAll,
- boolean includeIgnored,
- boolean collectParentExternals,
- ISVNStatusHandler handler) throws SVNException {
- return doStatus(path, revision, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, remote, reportAll, includeIgnored,
- collectParentExternals, handler, null);
- }
-
- @Override
- public long doStatus(File path,
- SVNRevision revision,
- SVNDepth depth,
- boolean remote,
- boolean reportAll,
- boolean includeIgnored,
- boolean collectParentExternals,
- ISVNStatusHandler handler,
- Collection changeLists) throws SVNException {
- final SVNException[] exc = new SVNException[1];
- SVNClient client = new SVNClient();
- try {
- client.status(path.getPath(), DepthConvertor.convert(depth), remote, reportAll, !includeIgnored, !collectParentExternals,
- changeLists, StatusCallbackConvertor.create(handler, new Convertor<String, SVNInfo>() {
- @Override
- public SVNInfo convert(String o) {
- final SVNInfo[] infoArr = new SVNInfo[1];
- try {
- new SVNClient().info2(o, Revision.START, Revision.START, Depth.empty, null, new InfoCallback() {
- @Override
- public void singleInfo(Info info) {
- try {
- infoArr[0] = InfoConvertor.convert(info);
- }
- catch (SVNException e) {
- throw new SvnExceptionWrapper(e);
- }
- }
- });
- }
- catch (ClientException e) {
- throw new SvnExceptionWrapper(ExceptionConvertor.convert(e));
- }
- return infoArr[0];
- }
- }, new Consumer<SVNException>() {
- @Override
- public void consume(SVNException e) {
- exc[0] = e;
- }
- }));
- }
- catch (ClientException e) {
- throw ExceptionConvertor.convert(e);
- }
- if (exc[0] != null) {
- throw exc[0];
- }
- // isn't used
- return -1;
- }
-
- @Override
- public SVNStatus doStatus(File path, boolean remote) throws SVNException {
- return doStatus(path, remote, false);
- }
-
- @Override
- public SVNStatus doStatus(File path, boolean remote, boolean collectParentExternals) throws SVNException {
- final SVNStatus[] statusArr = new SVNStatus[0];
- doStatus(path, SVNRevision.UNDEFINED, SVNDepth.EMPTY, remote, false, false, collectParentExternals,
- new ISVNStatusHandler() {
- @Override
- public void handleStatus(SVNStatus status) throws SVNException {
- statusArr[0] = status;
- }
- }, null);
- return statusArr[0];
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/NodeKindConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/NodeKindConvertor.java
deleted file mode 100644
index f888e36..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/NodeKindConvertor.java
+++ /dev/null
@@ -1,43 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.types.NodeKind;
-import org.tigris.subversion.javahl.JavaHLObjectFactory;
-import org.tmatesoft.svn.core.SVNNodeKind;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/21/12
- * Time: 7:45 PM
- */
-public class NodeKindConvertor {
- public static int convert(SVNNodeKind kind) {
- return JavaHLObjectFactory.getNodeKind(kind);
- }
-
- public static SVNNodeKind convert(NodeKind kind) {
- if (NodeKind.dir == kind) {
- return SVNNodeKind.DIR;
- } else if (NodeKind.none == kind) {
- return SVNNodeKind.NONE;
- } else if (NodeKind.file == kind) {
- return SVNNodeKind.FILE;
- }
- return SVNNodeKind.UNKNOWN;
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/OperationConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/OperationConvertor.java
deleted file mode 100644
index 4ec3d44..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/OperationConvertor.java
+++ /dev/null
@@ -1,38 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.ConflictDescriptor;
-import org.tmatesoft.svn.core.wc.SVNOperation;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/23/12
- * Time: 7:30 PM
- */
-public class OperationConvertor {
- public static SVNOperation convert(ConflictDescriptor.Operation operation) {
- if (ConflictDescriptor.Operation.merge.equals(operation)) {
- return SVNOperation.MERGE;
- } else if (ConflictDescriptor.Operation.switched.equals(operation)) {
- return SVNOperation.SWITCH;
- } else if (ConflictDescriptor.Operation.update.equals(operation)) {
- return SVNOperation.UPDATE;
- }
- return SVNOperation.NONE;
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/RevisionConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/RevisionConvertor.java
deleted file mode 100644
index 0b1ead4..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/RevisionConvertor.java
+++ /dev/null
@@ -1,70 +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 org.jetbrains.idea.svn.portable;
-
-import org.apache.subversion.javahl.types.Revision;
-import org.jetbrains.annotations.NotNull;
-import org.tmatesoft.svn.core.wc.SVNRevision;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/21/12
- * Time: 6:59 PM
- */
-public class RevisionConvertor {
- public static Revision convert(@NotNull SVNRevision r) {
- if (SVNRevision.BASE.equals(r)) {
- return Revision.BASE;
- } else if (SVNRevision.COMMITTED.equals(r)) {
- return Revision.COMMITTED;
- } else if (SVNRevision.HEAD.equals(r)) {
- return Revision.HEAD;
- } else if (SVNRevision.PREVIOUS.equals(r)) {
- return Revision.PREVIOUS;
- } else if (SVNRevision.UNDEFINED.equals(r)) {
- return Revision.START;
- } else if (SVNRevision.WORKING.equals(r)) {
- return Revision.WORKING;
- } else {
- return new Revision.Number(r.getNumber());
- }
- }
-
- public static SVNRevision convert(Revision r) {
- if (r == null) return null;
- if (Revision.BASE.equals(r)) {
- return SVNRevision.BASE;
- } else if (Revision.COMMITTED.equals(r)) {
- return SVNRevision.COMMITTED;
- } else if (Revision.HEAD.equals(r)) {
- return SVNRevision.HEAD;
- } else if (Revision.PREVIOUS.equals(r)) {
- return SVNRevision.PREVIOUS;
- } else if (Revision.START.equals(r)) {
- return SVNRevision.UNDEFINED;
- } else if (Revision.WORKING.equals(r)) {
- return SVNRevision.WORKING;
- } else {
- if (Revision.Kind.number.equals(r.getKind())) {
- return SVNRevision.create(((Revision.Number)r).getNumber());
- }
- else {
- return SVNRevision.create(((Revision.DateSpec)r).getDate());
- }
- }
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SVNChangelistClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SVNChangelistClientI.java
deleted file mode 100644
index 58ee569..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SVNChangelistClientI.java
+++ /dev/null
@@ -1,47 +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 org.jetbrains.idea.svn.portable;
-
-import org.tmatesoft.svn.core.SVNDepth;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.wc.ISVNChangelistHandler;
-
-import java.io.File;
-import java.util.Collection;
-
-/**
- * Created with IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 10/19/12
- * Time: 3:50 PM
- */
-public interface SVNChangelistClientI extends SvnMarkerInterface {
- void getChangeLists(File path, Collection<String> changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
-
- void getChangeListPaths(Collection<String> changeLists, Collection<File> targets, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
-
- void addToChangelist(File[] paths, SVNDepth depth, String changelist, String[] changelists) throws SVNException;
-
- void removeFromChangelist(File[] paths, SVNDepth depth, String[] changelists) throws SVNException;
-
- void doAddToChangelist(File[] paths, SVNDepth depth, String changelist, String[] changelists) throws SVNException;
-
- void doRemoveFromChangelist(File[] paths, SVNDepth depth, String[] changelists) throws SVNException;
-
- void doGetChangeListPaths(Collection<String> changeLists, Collection<File> targets, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
-
- void doGetChangeLists(File path, Collection<String> changeLists, SVNDepth depth, ISVNChangelistHandler handler) throws SVNException;
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusCallbackConvertor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusCallbackConvertor.java
deleted file mode 100644
index a570fbf..0000000
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/StatusCallbackConvertor.java
+++ /dev/null
@@ -1,113 +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 org.jetbrains.idea.svn.portable;
-
-import com.intellij.openapi.util.Getter;
-import com.intellij.util.Consumer;
-import com.intellij.util.containers.Convertor;
-import org.apache.subversion.javahl.callback.StatusCallback;
-import org.apache.subversion.javahl.types.Status;
-import org.jetbrains.idea.svn.WorkingCopyFormat;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.ISVNStatusHandler;
-import org.tmatesoft.svn.core.wc.SVNInfo;
-import org.tmatesoft.svn.core.wc.SVNStatus;
-import org.tmatesoft.svn.core.wc.SVNStatusType;
-
-import java.io.File;
-
-/**
- * Created by IntelliJ IDEA.
- * User: Irina.Chernushina
- * Date: 1/24/12
- * Time: 9:55 AM
- */
-public class StatusCallbackConvertor {
- public static StatusCallback create(final ISVNStatusHandler handler, final Convertor<String, SVNInfo> infoGetter,
- final Consumer<SVNException> exceptionConsumer) {
- return new StatusCallback() {
- @Override
- public void doStatus(String path, Status status) {
- if (handler == null) return;
- try {
- handler.handleStatus(convert(path, status, infoGetter));
- }
- catch (SVNException e) {
- exceptionConsumer.consume(e);
- }
- }
- };
- }
-
- public static SVNStatus convert(final String path, Status status, final Convertor<String, SVNInfo> infoGetter) throws SVNException {
- // no locks
- return new PortableStatus(createUrl(status.getUrl()), new File(path), NodeKindConvertor.convert(status.getNodeKind()),
- RevisionConvertor.convert(status.getRevision()), RevisionConvertor.convert(status.getLastChangedRevision()),
- status.getLastChangedDate(), status.getLastCommitAuthor(), convert(status.getTextStatus()),
- convert(status.getPropStatus()), convert(status.getRepositoryTextStatus()),
- convert(status.getRepositoryPropStatus()), status.isLocked(), status.isCopied(), status.isSwitched(),
- status.isFileExternal(), null, null, null, status.getChangelist(), WorkingCopyFormat.ONE_DOT_SEVEN.getFormat(),
- status.isConflicted(),
- new Getter<SVNInfo>() {
- @Override
- public SVNInfo get() {
- return infoGetter.convert(path);
- }
- });
- }
-
- private static SVNURL createUrl(final String url) throws SVNException {
- if (url == null) return null;
- return SVNURL.parseURIEncoded(url);
- }
-
- public static SVNStatusType convert(Status.Kind kind) {
- if (kind == null) return null;
- if (Status.Kind.added.equals(kind)) {
- return SVNStatusType.STATUS_ADDED;
- } else if (Status.Kind.conflicted.equals(kind)) {
- return SVNStatusType.STATUS_CONFLICTED;
- } else if (Status.Kind.deleted.equals(kind)) {
- return SVNStatusType.STATUS_DELETED;
- } else if (Status.Kind.external.equals(kind)) {
- return SVNStatusType.STATUS_EXTERNAL;
- } else if (Status.Kind.ignored.equals(kind)) {
- // 5
- return SVNStatusType.STATUS_IGNORED;
- } else if (Status.Kind.incomplete.equals(kind)) {
- return SVNStatusType.STATUS_INCOMPLETE;
- } else if (Status.Kind.merged.equals(kind)) {
- return SVNStatusType.STATUS_MERGED;
- } else if (Status.Kind.missing.equals(kind)) {
- return SVNStatusType.STATUS_MISSING;
- } else if (Status.Kind.modified.equals(kind)) {
- return SVNStatusType.STATUS_MODIFIED;
- } else if (Status.Kind.none.equals(kind)) {
- //10
- return SVNStatusType.STATUS_NONE;
- } else if (Status.Kind.normal.equals(kind)) {
- return SVNStatusType.STATUS_NORMAL;
- } else if (Status.Kind.obstructed.equals(kind)) {
- return SVNStatusType.STATUS_OBSTRUCTED;
- } else if (Status.Kind.replaced.equals(kind)) {
- return SVNStatusType.STATUS_REPLACED;
- } else if (Status.Kind.unversioned.equals(kind)) {
- return SVNStatusType.STATUS_UNVERSIONED;
- }
- return SVNStatusType.STATUS_NONE;
- }
-}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java
index 036de6b..48ba32e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnWcClientI.java
@@ -15,6 +15,8 @@
*/
package org.jetbrains.idea.svn.portable;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
@@ -38,4 +40,6 @@
ISVNInfoHandler handler) throws SVNException;
SVNInfo doInfo(File path, SVNRevision revision) throws SVNException;
SVNInfo doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision) throws SVNException;
+
+ void doInfo(@NotNull Collection<File> paths, @Nullable ISVNInfoHandler handler) throws SVNException;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java
index faee8ec..44cca7f 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/portable/SvnkitSvnWcClient.java
@@ -16,6 +16,7 @@
package org.jetbrains.idea.svn.portable;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
@@ -83,4 +84,9 @@
public SVNInfo doInfo(SVNURL url, SVNRevision pegRevision, SVNRevision revision) throws SVNException {
return getClient().doInfo(url, pegRevision, revision);
}
+
+ @Override
+ public void doInfo(@NotNull Collection<File> paths, @Nullable ISVNInfoHandler handler) throws SVNException {
+ throw new UnsupportedOperationException();
+ }
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
index 29ff70e..ce6d2b2 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/CmdPropertyClient.java
@@ -8,14 +8,8 @@
import org.jetbrains.idea.svn.commandLine.CommandExecutor;
import org.jetbrains.idea.svn.commandLine.CommandUtil;
import org.jetbrains.idea.svn.commandLine.SvnCommandName;
-import org.tmatesoft.svn.core.SVNDepth;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNInfo;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
-import org.tmatesoft.svn.core.wc.SVNRevision;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import javax.xml.bind.JAXBException;
@@ -99,6 +93,39 @@
}
@Override
+ public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException {
+ SVNProperties currentProperties = collectPropertiesToDelete(file);
+ currentProperties.putAll(properties);
+
+ for (String propertyName : currentProperties.nameSet()) {
+ setProperty(file, propertyName, currentProperties.getSVNPropertyValue(propertyName), SVNDepth.EMPTY, true);
+ }
+ }
+
+ @NotNull
+ private SVNProperties collectPropertiesToDelete(@NotNull File file) throws VcsException {
+ final SVNProperties result = new SVNProperties();
+
+ list(SvnTarget.fromFile(file), null, SVNDepth.EMPTY, new ISVNPropertyHandler() {
+ @Override
+ public void handleProperty(File path, SVNPropertyData property) throws SVNException {
+ // null indicates property will be deleted
+ result.put(property.getName(), (SVNPropertyValue)null);
+ }
+
+ @Override
+ public void handleProperty(SVNURL url, SVNPropertyData property) throws SVNException {
+ }
+
+ @Override
+ public void handleProperty(long revision, SVNPropertyData property) throws SVNException {
+ }
+ });
+
+ return result;
+ }
+
+ @Override
public void setRevisionProperty(@NotNull SvnTarget target,
@NotNull String property,
@NotNull SVNRevision revision,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
index 12bc0e9..b44f7ea 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/PropertyClient.java
@@ -7,6 +7,7 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.SvnClient;
import org.tmatesoft.svn.core.SVNDepth;
+import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;
import org.tmatesoft.svn.core.wc.ISVNOptions;
@@ -51,6 +52,8 @@
@Nullable SVNDepth depth,
boolean force) throws VcsException;
+ void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException;
+
void setRevisionProperty(@NotNull SvnTarget target,
@NotNull String property,
@NotNull SVNRevision revision,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
index d55eb68..c745c42 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/properties/SvnKitPropertyClient.java
@@ -5,14 +5,8 @@
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.api.BaseSvnClient;
import org.jetbrains.idea.svn.commandLine.SvnBindException;
-import org.tmatesoft.svn.core.SVNDepth;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNPropertyValue;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.wc.ISVNPropertyHandler;
-import org.tmatesoft.svn.core.wc.SVNPropertyData;
-import org.tmatesoft.svn.core.wc.SVNRevision;
-import org.tmatesoft.svn.core.wc.SVNWCClient;
+import org.tmatesoft.svn.core.*;
+import org.tmatesoft.svn.core.wc.*;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
@@ -84,6 +78,21 @@
}
@Override
+ public void setProperties(@NotNull File file, @NotNull SVNProperties properties) throws VcsException {
+ try {
+ createClient().doSetProperty(file, new ISVNPropertyValueProvider() {
+ @Override
+ public SVNProperties providePropertyValues(File path, SVNProperties properties) throws SVNException {
+ return properties;
+ }
+ }, true, SVNDepth.EMPTY, null, null);
+ }
+ catch (SVNException e) {
+ throw new SvnBindException(e);
+ }
+ }
+
+ @Override
public void setRevisionProperty(@NotNull SvnTarget target,
@NotNull String property,
@NotNull SVNRevision revision,
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java
index 87f0e23..02992c9 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java
@@ -39,7 +39,8 @@
// TODO: handler should be called in parallel with command execution, but this will be in other thread
// TODO: check if that is ok for current handler implementation
// TODO: add possibility to invoke "handler.checkCancelled" - process should be killed
- CommandExecutor command = CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.revert, parameters, null);
+ CommandExecutor command =
+ CommandUtil.execute(myVcs, SvnTarget.fromFile(paths[0]), CommandUtil.getHomeDirectory(), SvnCommandName.revert, parameters, null);
FileStatusResultParser parser = new FileStatusResultParser(CHANGED_PATH, handler, new RevertStatusConvertor());
parser.parse(command.getOutput());
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
index ed097b4..38f15dd 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java
@@ -24,13 +24,13 @@
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Processor;
-import com.intellij.util.containers.MultiMap;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.*;
-import org.jetbrains.idea.svn.revert.RevertClient;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.wc.*;
+import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
import java.io.IOException;
@@ -94,12 +94,12 @@
};
final List<CopiedAsideInfo> fromToModified = new ArrayList<CopiedAsideInfo>();
- final MultiMap<File, SVNPropertyData> properties = new MultiMap<File, SVNPropertyData>();
+ final Map<File, SVNProperties> properties = ContainerUtil.newHashMap();
moveRenamesToTmp(exceptions, fromToModified, properties, collector);
// adds (deletes)
// deletes (adds)
// modifications
- final Reverter reverter = new Reverter(mySvnVcs.getFactory().createRevertClient(), revertHandler, exceptions);
+ final Reverter reverter = new Reverter(mySvnVcs, revertHandler, exceptions);
reverter.revert(checker.getForAdds(), true);
reverter.revert(checker.getForDeletes(), true);
final List<File> edits = checker.getForEdits();
@@ -117,18 +117,20 @@
private void moveRenamesToTmp(List<VcsException> exceptions,
List<CopiedAsideInfo> fromToModified,
- final MultiMap<File, SVNPropertyData> properties,
+ final Map<File, SVNProperties> properties,
final UnversionedAndNotTouchedFilesGroupCollector collector) {
final Map<File, ThroughRenameInfo> fromTo = collector.getFromTo();
try {
final File tmp = FileUtil.createTempDirectory("forRename", "");
- final SVNWCClient client = mySvnVcs.createWCClient();
final ISVNPropertyHandler handler = new ISVNPropertyHandler() {
@Override
public void handleProperty(File path, SVNPropertyData property) throws SVNException {
final ThroughRenameInfo info = collector.findToFile(new FilePathImpl(path, path.isDirectory()), null);
if (info != null) {
- properties.putValue(info.getTo(), property);
+ if (!properties.containsKey(info.getTo())) {
+ properties.put(info.getTo(), new SVNProperties());
+ }
+ properties.get(info.getTo()).put(property.getName(), property.getValue());
}
}
@@ -148,7 +150,7 @@
final File source = entry.getKey();
final ThroughRenameInfo info = entry.getValue();
if (info.isVersioned()) {
- client.doGetProperty(source, null, SVNRevision.UNDEFINED, SVNRevision.WORKING, SVNDepth.EMPTY, handler, null);
+ mySvnVcs.getFactory(source).createPropertyClient().list(SvnTarget.fromFile(source), SVNRevision.WORKING, SVNDepth.EMPTY, handler);
}
if (source.isDirectory()) {
if (! FileUtil.filesEqual(info.getTo(), info.getFirstTo())) {
@@ -166,14 +168,14 @@
catch (IOException e) {
exceptions.add(new VcsException(e));
}
- catch (SVNException e) {
- exceptions.add(new VcsException(e));
+ catch(VcsException e) {
+ exceptions.add(e);
}
}
private void moveGroup(final List<VcsException> exceptions,
List<CopiedAsideInfo> fromTo,
- MultiMap<File, SVNPropertyData> properties) {
+ Map<File, SVNProperties> properties) {
Collections.sort(fromTo, new Comparator<CopiedAsideInfo>() {
@Override
public int compare(CopiedAsideInfo o1, CopiedAsideInfo o2) {
@@ -232,36 +234,25 @@
applyProperties(properties, exceptions);
}
- private void applyProperties(MultiMap<File, SVNPropertyData> propertiesMap, final List<VcsException> exceptions) {
- final SVNWCClient client = mySvnVcs.createWCClient();
- for (Map.Entry<File, Collection<SVNPropertyData>> entry : propertiesMap.entrySet()) {
- final File file = entry.getKey();
- final Collection<SVNPropertyData> propertyDatas = entry.getValue();
- try {
- client.doSetProperty(file, new ISVNPropertyValueProvider() {
- @Override
- public SVNProperties providePropertyValues(File path, SVNProperties properties) throws SVNException {
- final SVNProperties result = new SVNProperties();
- for (SVNPropertyData data : propertyDatas) {
- result.put(data.getName(), data.getValue());
- }
- return result;
- }
- }, true, SVNDepth.EMPTY, null, null);
- }
- catch (SVNException e) {
- exceptions.add(new VcsException(e));
- }
+ private void applyProperties(Map<File, SVNProperties> propertiesMap, final List<VcsException> exceptions) {
+ for (Map.Entry<File, SVNProperties> entry : propertiesMap.entrySet()) {
+ File file = entry.getKey();
+ try {
+ mySvnVcs.getFactory(file).createPropertyClient().setProperties(file, entry.getValue());
+ }
+ catch (VcsException e) {
+ exceptions.add(e);
+ }
}
}
private static class Reverter {
- private final RevertClient myClient;
+ @NotNull private final SvnVcs myVcs;
private ISVNEventHandler myHandler;
private final List<VcsException> myExceptions;
- private Reverter(RevertClient client, ISVNEventHandler handler, List<VcsException> exceptions) {
- myClient = client;
+ private Reverter(@NotNull SvnVcs vcs, ISVNEventHandler handler, List<VcsException> exceptions) {
+ myVcs = vcs;
myHandler = handler;
myExceptions = exceptions;
}
@@ -269,7 +260,8 @@
public void revert(final File[] files, final boolean recursive) {
if (files.length == 0) return;
try {
- myClient.revert(files, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, myHandler);
+ // Files passed here are split into groups by root and working copy format - thus we could determine factory based on first file
+ myVcs.getFactory(files[0]).createRevertClient().revert(files, recursive ? SVNDepth.INFINITY : SVNDepth.EMPTY, myHandler);
}
catch (VcsException e) {
processRevertError(e);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java
new file mode 100644
index 0000000..72558d4
--- /dev/null
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/statistics/SvnWorkingCopyFormatUsagesCollector.java
@@ -0,0 +1,65 @@
+/*
+ * 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.idea.svn.statistics;
+
+import com.intellij.internal.statistic.beans.GroupDescriptor;
+import com.intellij.internal.statistic.beans.UsageDescriptor;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.vcs.statistics.VcsUsagesCollector;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.svn.NestedCopyType;
+import org.jetbrains.idea.svn.RootUrlInfo;
+import org.jetbrains.idea.svn.SvnVcs;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Konstantin Kolosovsky.
+ */
+public class SvnWorkingCopyFormatUsagesCollector extends VcsUsagesCollector {
+
+ private static final String GROUP_ID = "svn working copy format";
+
+ @NotNull
+ public GroupDescriptor getGroupId() {
+ return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY);
+ }
+
+ @NotNull
+ public Set<UsageDescriptor> getProjectUsages(@NotNull Project project) {
+ SvnVcs vcs = SvnVcs.getInstance(project);
+
+ // do not track roots with errors (SvnFileUrlMapping.getErrorRoots()) as they are "not usable" until errors are resolved
+ // skip externals and switched directories as they will have the same format
+ List<RootUrlInfo> roots = ContainerUtil.filter(vcs.getSvnFileUrlMapping().getAllWcInfos(), new Condition<RootUrlInfo>() {
+ @Override
+ public boolean value(RootUrlInfo info) {
+ return info.getType() == null || NestedCopyType.inner.equals(info.getType());
+ }
+ });
+
+ return ContainerUtil.map2Set(roots, new Function<RootUrlInfo, UsageDescriptor>() {
+ @Override
+ public UsageDescriptor fun(RootUrlInfo info) {
+ return new UsageDescriptor(info.getFormat().toString(), 1);
+ }
+ });
+ }
+}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java
index cfafc65..31b040c 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java
@@ -587,8 +587,8 @@
private boolean getAddedFilesPlaceOption() {
final SvnConfiguration configuration = SvnConfiguration.getInstance(myVcs.getProject());
- boolean add = Boolean.TRUE.equals(configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE);
- if (configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE != null) {
+ boolean add = Boolean.TRUE.equals(configuration.isKeepNewFilesAsIsForTreeConflictMerge());
+ if (configuration.isKeepNewFilesAsIsForTreeConflictMerge() != null) {
return add;
}
if (!containAdditions(myTheirsChanges) && !containAdditions(myTheirsBinaryChanges)) {
@@ -606,10 +606,10 @@
if (!value) {
if (exitCode == 0) {
// yes
- configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = true;
+ configuration.setKeepNewFilesAsIsForTreeConflictMerge(true);
}
else {
- configuration.TREE_CONFLICT_MERGE_THEIRS_NEW_INTO_OLD_PLACE = false;
+ configuration.setKeepNewFilesAsIsForTreeConflictMerge(false);
}
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java
index 57a7e21..da0b1e7 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java
@@ -193,12 +193,6 @@
return EmptyConflictSide.getInstance();
}
}
- // todo temporally
- /*if (SVNNodeKind.DIR.equals(version.getKind())) {
- return new HistoryAsBrowseChangesConflictSide(myVcs.getProject(), version);
- } else {
- return new HistoryConflictSide(myVcs, version);
- }*/
HistoryConflictSide side = new HistoryConflictSide(myVcs, version, untilThisOther);
if (untilThisOther != null && ! isLeft) {
side.setListToReportLoaded(myRightRevisionsList);
@@ -314,11 +308,7 @@
additionalPath = myChange.getAfterRevision().getFile();
}
} else {
- if (myChange.getBeforeRevision() != null) {
- mainPath = myChange.getBeforeRevision().getFile();
- } else {
- mainPath = myChange.getAfterRevision().getFile();
- }
+ mainPath = myChange.getBeforeRevision() != null ? myChange.getBeforeRevision().getFile() : myChange.getAfterRevision().getFile();
}
return new Paths(mainPath, additionalPath);
}
@@ -368,15 +358,6 @@
return null;
}
// my edit, theirs move or delete
- /*if (SVNConflictAction.DELETE.equals(description.getConflictAction()) && description.getSourceLeftVersion() != null) {
- //todo
- return new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- mergeMyEditTheirsDelete();
- }
- };
- } */
if (SVNConflictAction.EDIT.equals(description.getConflictAction()) && description.getSourceLeftVersion() != null &&
SVNConflictReason.DELETED.equals(description.getConflictReason()) && (myChange.isMoved() || myChange.isRenamed()) &&
myCommittedRevision != null) {
@@ -397,10 +378,7 @@
}
public static String filePath(FilePath newFilePath) {
- return newFilePath.getName() +
- " (" +
- newFilePath.getParentPath().getPath() +
- ")";
+ return newFilePath.getName() + " (" + newFilePath.getParentPath().getPath() + ")";
}
private static ActionListener createBoth(SVNTreeConflictDescription description) {
@@ -524,12 +502,7 @@
@Override
public void load() throws SVNException, VcsException {
SVNRevision from = SVNRevision.create(myVersion.getPegRevision());
- if (myPeg == null) {
- // just a portion of history
- myProvider.reportAppendableHistory(myPath, mySessionAdapter, from, myPeg, LIMIT, myPeg, true);
- } else {
- myProvider.reportAppendableHistory(myPath, mySessionAdapter, from, myPeg, 0, myPeg, true);
- }
+ myProvider.reportAppendableHistory(myPath, mySessionAdapter, from, myPeg, myPeg == null ? LIMIT : 0, myPeg, true);
VcsAbstractHistorySession session = mySessionAdapter.getSession();
if (myListToReportLoaded != null && session != null) {
List<VcsFileRevision> list = session.getRevisionList();
@@ -576,15 +549,4 @@
return myFileHistoryPanel;
}
}
-
- /*private static class HistoryAsBrowseChangesConflictSide implements AbstractConflictSide<Object> {
- public HistoryAsBrowseChangesConflictSide(Project project, SVNConflictVersion version) {
- //To change body of created methods use File | Settings | File Templates.
- }
-
- @Override
- public JPanel createPanel() {
- return null;
- }
- }*/
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java
index 4c24d69..0cea23e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AbstractSvnUpdatePanel.java
@@ -85,7 +85,7 @@
}
public void reset(final SvnConfiguration configuration) {
- getDepthBox().setSelectedItem(configuration.UPDATE_DEPTH);
+ getDepthBox().setSelectedItem(configuration.getUpdateDepth());
for (FilePath filePath : myRootToPanel.keySet()) {
myRootToPanel.get(filePath).reset(configuration);
@@ -94,7 +94,7 @@
}
public void apply(final SvnConfiguration configuration) throws ConfigurationException {
- configuration.UPDATE_DEPTH = getDepthBox().getDepth();
+ configuration.setUpdateDepth(getDepthBox().getDepth());
for (FilePath filePath : myRootToPanel.keySet()) {
final SvnPanel svnPanel = myRootToPanel.get(filePath);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java
index 0c0e836..cf424af 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/AutoSvnUpdater.java
@@ -47,9 +47,9 @@
@Override
protected void actionPerformed(VcsContext context) {
final SvnConfiguration configuration17 = SvnConfiguration.getInstance(myProject);
- configuration17.FORCE_UPDATE = false;
- configuration17.UPDATE_LOCK_ON_DEMAND = false;
- configuration17.UPDATE_DEPTH = SVNDepth.INFINITY;
+ configuration17.setForceUpdate(false);
+ configuration17.setUpdateLockOnDemand(false);
+ configuration17.setUpdateDepth(SVNDepth.INFINITY);
final SvnVcs vcs = SvnVcs.getInstance(myProject);
for (FilePath root : myRoots) {
final UpdateRootInfo info = configuration17.getUpdateRootInfo(root.getIOFile(), vcs);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java
index 7627b1e..c8a77f6 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegrateEnvironment.java
@@ -20,15 +20,10 @@
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.update.UpdatedFiles;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.integrate.MergeClient;
-import org.tmatesoft.svn.core.SVNException;
-import org.tmatesoft.svn.core.SVNURL;
-import org.tmatesoft.svn.core.io.SVNRepository;
-import org.tmatesoft.svn.core.wc.SVNRevision;
import org.tmatesoft.svn.core.wc2.SvnTarget;
import java.io.File;
@@ -66,10 +61,10 @@
@Override
protected boolean isDryRun() {
- return SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN;
+ return SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun();
}
- private class IntegrateCrawler extends AbstractUpdateIntegrateCrawler {
+ private static class IntegrateCrawler extends AbstractUpdateIntegrateCrawler {
public IntegrateCrawler(SvnVcs vcs,
UpdateEventHandler handler,
@@ -83,7 +78,7 @@
}
protected void showProgressMessage(final ProgressIndicator progress, final File root) {
- if (SvnConfiguration.getInstance(myVcs.getProject()).MERGE_DRY_RUN) {
+ if (SvnConfiguration.getInstance(myVcs.getProject()).isMergeDryRun()) {
progress.setText(SvnBundle.message("progress.text.merging.dry.run.changes", root.getAbsolutePath()));
}
else {
@@ -104,9 +99,8 @@
SvnTarget source1 = SvnTarget.fromURL(info.getUrl1(), info.getRevision1());
SvnTarget source2 = SvnTarget.fromURL(info.getUrl2(), info.getRevision2());
- client.merge(source1, source2, root, svnConfig.UPDATE_DEPTH, svnConfig.MERGE_DIFF_USE_ANCESTRY, svnConfig.MERGE_DRY_RUN, false, false,
+ client.merge(source1, source2, root, svnConfig.getUpdateDepth(), svnConfig.isMergeDiffUseAncestry(), svnConfig.isMergeDryRun(), false, false,
svnConfig.getMergeOptions(), myHandler);
- svnConfig.LAST_MERGED_REVISION = getLastMergedRevision(info.getRevision2(), info.getUrl2());
return info.getResultRevision();
}
@@ -115,36 +109,6 @@
}
}
- @Nullable
- private String getLastMergedRevision(final SVNRevision rev2, final SVNURL svnURL2) {
- if (!rev2.isValid() || rev2.isLocal()) {
- return null;
- }
- else {
- final long number = rev2.getNumber();
- if (number > 0) {
- return String.valueOf(number);
- }
- else {
-
- // TODO: Rewrite with command line implementation
- SVNRepository repos = null;
- try {
- repos = myVcs.createRepository(svnURL2.toString());
- final long latestRev = repos.getLatestRevision();
- return String.valueOf(latestRev);
- }
- catch (SVNException e) {
- return null;
- } finally {
- if (repos != null) {
- repos.closeSession();
- }
- }
- }
- }
- }
-
public boolean validateOptions(final Collection<FilePath> roots) {
return true;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java
index b01b379..b7f5012 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnIntegratePanel.java
@@ -65,13 +65,13 @@
public void reset(final SvnConfiguration configuration) {
super.reset(configuration);
- myDryRunCheckbox.setSelected(configuration.MERGE_DRY_RUN);
- myUseAncestry.setSelected(configuration.MERGE_DIFF_USE_ANCESTRY);
+ myDryRunCheckbox.setSelected(configuration.isMergeDryRun());
+ myUseAncestry.setSelected(configuration.isMergeDiffUseAncestry());
}
public void apply(final SvnConfiguration configuration) throws ConfigurationException {
super.apply(configuration);
- configuration.MERGE_DRY_RUN = myDryRunCheckbox.isSelected();
- configuration.MERGE_DIFF_USE_ANCESTRY = myUseAncestry.isSelected();
+ configuration.setMergeDryRun(myDryRunCheckbox.isSelected());
+ configuration.setMergeDiffUseAncestry(myUseAncestry.isSelected());
}
protected JComponent getPanel() {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java
index 3da7e90..42ba2b5 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateContext.java
@@ -67,7 +67,7 @@
result = false;
}
else if (NestedCopyType.external.equals(info.getType())) {
- result = !myVcs.getSvnConfiguration().IGNORE_EXTERNALS;
+ result = !myVcs.getSvnConfiguration().isIgnoreExternals();
}
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
index af9ef2e..d0ad292 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdateEnvironment.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,7 +17,6 @@
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.progress.ProgressIndicator;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.VcsException;
@@ -84,10 +83,11 @@
if (isSwitch) {
final UpdateClient updateClient = createUpdateClient(configuration, root, true, sourceUrl);
myHandler.addToSwitch(root, sourceUrl);
- rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, updateTo, configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false);
+ rev = updateClient.doSwitch(root, rootInfo.getUrl(), SVNRevision.UNDEFINED, updateTo, configuration.getUpdateDepth(),
+ configuration.isForceUpdate(), false);
} else {
final UpdateClient updateClient = createUpdateClient(configuration, root, false, sourceUrl);
- rev = updateClient.doUpdate(root, updateTo, configuration.UPDATE_DEPTH, configuration.FORCE_UPDATE, false);
+ rev = updateClient.doUpdate(root, updateTo, configuration.getUpdateDepth(), configuration.isForceUpdate(), false);
}
myPostUpdateFiles.setRevisions(root.getAbsolutePath(), myVcs, new SvnRevisionNumber(SVNRevision.create(rev)));
@@ -96,19 +96,13 @@
}
private UpdateClient createUpdateClient(SvnConfiguration configuration, File root, boolean isSwitch, SVNURL sourceUrl) {
- boolean is17 = WorkingCopyFormat.ONE_DOT_SEVEN.equals(myVcs.getWorkingCopyFormat(root));
- boolean isSupportedProtocol =
- SvnAuthenticationManager.HTTP.equals(sourceUrl.getProtocol()) || SvnAuthenticationManager.HTTPS.equals(sourceUrl.getProtocol());
-
- // TODO: Update this with just myVcs.getFactory(root) when switch and authentication protocols are implemented for command line
- ClientFactory factory = is17 && (isSwitch || !isSupportedProtocol) ? myVcs.getSvnKitFactory() : myVcs.getFactory(root);
- final UpdateClient updateClient = factory.createUpdateClient();
+ final UpdateClient updateClient = myVcs.getFactory(root).createUpdateClient();
if (! isSwitch) {
- updateClient.setIgnoreExternals(configuration.IGNORE_EXTERNALS);
+ updateClient.setIgnoreExternals(configuration.isIgnoreExternals());
}
updateClient.setEventHandler(myHandler);
- updateClient.setUpdateLocksOnDemand(configuration.UPDATE_LOCK_ON_DEMAND);
+ updateClient.setUpdateLocksOnDemand(configuration.isUpdateLockOnDemand());
return updateClient;
}
@@ -193,6 +187,6 @@
final int result = Messages.showYesNoDialog(myVcs.getProject(), SvnBundle.message("switch.target.not.copy.current"),
SvnBundle.message("switch.target.problem.title"), Messages.getWarningIcon());
- return (DialogWrapper.OK_EXIT_CODE == result);
+ return (Messages.YES == result);
}
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java
index ab66664..1aef057 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/update/SvnUpdatePanel.java
@@ -52,24 +52,24 @@
myDepthLabel.setLabelFor(myDepthCombo);
final SvnConfiguration svnConfiguration = SvnConfiguration.getInstance(myVCS.getProject());
- myLockOnDemand.setSelected(svnConfiguration.UPDATE_LOCK_ON_DEMAND);
+ myLockOnDemand.setSelected(svnConfiguration.isUpdateLockOnDemand());
myLockOnDemand.addActionListener(new ActionListener() {
public void actionPerformed(final ActionEvent e) {
- svnConfiguration.UPDATE_LOCK_ON_DEMAND = myLockOnDemand.isSelected();
+ svnConfiguration.setUpdateLockOnDemand(myLockOnDemand.isSelected());
}
});
- myForceBox.setSelected(svnConfiguration.FORCE_UPDATE);
- myIgnoreExternalsCheckBox.setSelected(svnConfiguration.IGNORE_EXTERNALS);
+ myForceBox.setSelected(svnConfiguration.isForceUpdate());
+ myIgnoreExternalsCheckBox.setSelected(svnConfiguration.isIgnoreExternals());
myForceBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- svnConfiguration.FORCE_UPDATE = myForceBox.isSelected();
+ svnConfiguration.setForceUpdate(myForceBox.isSelected());
}
});
myIgnoreExternalsCheckBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- svnConfiguration.IGNORE_EXTERNALS = myIgnoreExternalsCheckBox.isSelected();
+ svnConfiguration.setIgnoreExternals(myIgnoreExternalsCheckBox.isSelected());
}
});
}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
index 00d96b8..17ae6b5 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/SvnTestCase.java
@@ -20,7 +20,6 @@
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.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
@@ -71,9 +70,7 @@
import java.io.IOException;
import java.util.*;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
/**
* @author yole
@@ -219,7 +216,7 @@
@Override
protected void projectCreated() {
if (isUseNativeAcceleration()) {
- SvnConfiguration.getInstance(myProject).myUseAcceleration = SvnConfiguration.UseAcceleration.commandLine;
+ SvnConfiguration.getInstance(myProject).setUseAcceleration(SvnConfiguration.UseAcceleration.commandLine);
SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn");
}
}
@@ -618,8 +615,8 @@
protected void setNativeAcceleration(final boolean value) {
System.out.println("Set native acceleration to " + value);
- SvnConfiguration.getInstance(myProject).myUseAcceleration =
- value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing;
+ SvnConfiguration.getInstance(myProject).setUseAcceleration(
+ value ? SvnConfiguration.UseAcceleration.commandLine : SvnConfiguration.UseAcceleration.nothing);
SvnApplicationSettings.getInstance().setCommandLinePath(myClientBinaryPath + File.separator + "svn");
}
}
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java
index de27369..3700343 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnAuthenticationTest.java
@@ -730,7 +730,7 @@
@Override
public void run() {
try {
- myConfiguration.clearAuthenticationDirectory(getProject());
+ clearAuthCache();
}
catch (Exception e) {
throw new RuntimeException(e);
@@ -780,6 +780,10 @@
SVNJNAUtil.setJNAEnabled(true);
}
+ private void clearAuthCache() {
+ SvnAuthenticationNotifier.clearAuthenticationDirectory(myConfiguration);
+ }
+
public void testPlaintextPromptAndSecondPrompt() throws Exception {
SVNJNAUtil.setJNAEnabled(false);
@@ -875,7 +879,7 @@
@Override
public void run() {
try {
- myConfiguration.clearAuthenticationDirectory(getProject());
+ clearAuthCache();
}
catch (Exception e) {
throw new RuntimeException(e);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRevisionsTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRevisionsTest.java
index ef80964..1f0f7f8 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRevisionsTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnCachingRevisionsTest.java
@@ -3,11 +3,11 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.committed.ChangesBunch;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import org.jetbrains.idea.svn.history.*;
-import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -48,7 +48,8 @@
@Override
public List<CommittedChangeList> loadInterval(final SVNRevision fromIncluding, final SVNRevision toIncluding, final int maxCount,
- final boolean includingYoungest, final boolean includeOldest) throws SVNException {
+ final boolean includingYoungest, final boolean includeOldest)
+ throws VcsException {
long young = fromIncluding.getNumber();
young = (young == -1) ? myRevisions.get(myRevisions.size() - 1) : young;
final long old = toIncluding.getNumber();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalCommitNoticedTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalCommitNoticedTest.java
index 965ea63..673743c 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalCommitNoticedTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnExternalCommitNoticedTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.impl.local.FileWatcher;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -44,7 +43,7 @@
@Override
@Before
public void setUp() throws Exception {
- System.setProperty(FileWatcher.PROPERTY_WATCHER_DISABLED, "false");
+ //System.setProperty(FileWatcher.PROPERTY_WATCHER_DISABLED, "false");
super.setUp();
clManager = (ChangeListManagerImpl) ChangeListManager.getInstance(myProject);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java
index 4eec823..528ea0f 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnMergeInfoTest.java
@@ -64,7 +64,7 @@
myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY);
myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk");
- SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE = true;
+ SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true);
// AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME);
// Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length);
}
@@ -107,7 +107,7 @@
final SvnChangeList changeList = changeListList.get(0);
final BranchInfo mergeChecker =
- new BranchInfo(vcs, myRepoUrl, myRepoUrl + "/branch", myRepoUrl + "/trunk", myRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, myRepoUrl, myRepoUrl + "/branch", myRepoUrl + "/trunk", myRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -166,7 +166,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result);
@@ -235,7 +235,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -294,7 +294,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -369,7 +369,7 @@
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result);
result = mergeChecker.checkList(changeList4, myBranchVcsRoot.getAbsolutePath());
@@ -447,7 +447,7 @@
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -513,7 +513,7 @@
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result);
}
@@ -571,7 +571,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
index b6d6ae1..1328b94 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeClientAuthTest.java
@@ -29,6 +29,7 @@
import com.intellij.util.Processor;
import com.intellij.util.containers.Convertor;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.svn.checkout.SvnCheckoutProvider;
import org.junit.Before;
import org.tmatesoft.svn.core.*;
@@ -143,10 +144,9 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
updateSimple(wc1);
@@ -166,10 +166,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
updateSimple(wc1);
@@ -191,10 +190,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = true;
updateSimple(wc1);
@@ -215,10 +213,9 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = true;
updateSimple(wc1);
@@ -237,10 +234,9 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
testCommitImpl(wc1);
@@ -260,10 +256,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
testCommitImpl(wc1);
@@ -285,10 +280,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = true;
testCommitImpl(wc1);
@@ -310,10 +304,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = true;
myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED;
@@ -329,6 +322,11 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
}
+ private static void clearAuthCache(@NotNull SvnConfiguration instance) {
+ SvnAuthenticationNotifier.clearAuthenticationDirectory(instance);
+ instance.clearRuntimeStorage();
+ }
+
@Test
public void testMixedSSLCommit() throws Exception {
final File wc1 = testCheckoutImpl(ourHTTPS_URL);
@@ -336,10 +334,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED;
@@ -354,8 +351,7 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
//------------
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
mySaveCredentials = true;
myCertificateAnswer = ISVNAuthenticationProvider.ACCEPTED_TEMPORARY;
@@ -373,10 +369,9 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = true;
testCommitImpl(wc1);
@@ -395,10 +390,9 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
myCredentialsCorrect = false;
@@ -419,10 +413,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
myCredentialsCorrect = false;
@@ -446,10 +439,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
myCertificateAnswer = ISVNAuthenticationProvider.REJECTED;
@@ -480,10 +472,9 @@
//Assert.assertEquals(myExpectedCreds, myCredentialsAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
myCredentialsCorrect = false;
myCancelAuth = true;
@@ -507,10 +498,9 @@
//Assert.assertEquals(myExpectedCert, myCertificateAskedInteractivelyCount);
final SvnConfiguration instance = SvnConfiguration.getInstance(myProject);
- instance.clearAuthenticationDirectory(myProject);
- instance.clearRuntimeStorage();
+ clearAuthCache(instance);
- Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.myUseAcceleration);
+ Assert.assertEquals(SvnConfiguration.UseAcceleration.commandLine, instance.getUseAcceleration());
mySaveCredentials = false;
myCredentialsCorrect = false;
myCancelAuth = true;
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java
index b430210..624cfbb 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnAuthenticationTest.java
@@ -25,6 +25,7 @@
import com.intellij.util.ui.UIUtil;
import junit.framework.Assert;
import org.jetbrains.idea.svn.SvnAuthenticationManager;
+import org.jetbrains.idea.svn.SvnAuthenticationNotifier;
import org.jetbrains.idea.svn.SvnConfiguration;
import org.jetbrains.idea.svn.SvnVcs;
import org.jetbrains.idea.svn.auth.ProviderType;
@@ -733,7 +734,7 @@
@Override
public void run() {
try {
- myConfiguration.clearAuthenticationDirectory(getProject());
+ clearAuthCache();
}
catch (Exception e) {
throw new RuntimeException(e);
@@ -783,6 +784,10 @@
SVNJNAUtil.setJNAEnabled(true);
}
+ private void clearAuthCache() {
+ SvnAuthenticationNotifier.clearAuthenticationDirectory(myConfiguration);
+ }
+
public void testPlaintextPromptAndSecondPrompt() throws Exception {
SVNJNAUtil.setJNAEnabled(false);
@@ -878,7 +883,7 @@
@Override
public void run() {
try {
- myConfiguration.clearAuthenticationDirectory(getProject());
+ clearAuthCache();
}
catch (Exception e) {
throw new RuntimeException(e);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCachingRevisionsTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCachingRevisionsTest.java
index b065028..dca29f0 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCachingRevisionsTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnCachingRevisionsTest.java
@@ -3,12 +3,12 @@
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.committed.ChangesBunch;
import com.intellij.openapi.vcs.versionBrowser.CommittedChangeList;
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
import org.jetbrains.idea.svn.SvnApplicationSettings;
import org.jetbrains.idea.svn.history.*;
-import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.wc.SVNRevision;
@@ -49,7 +49,8 @@
@Override
public List<CommittedChangeList> loadInterval(final SVNRevision fromIncluding, final SVNRevision toIncluding, final int maxCount,
- final boolean includingYoungest, final boolean includeOldest) throws SVNException {
+ final boolean includingYoungest, final boolean includeOldest)
+ throws VcsException {
long young = fromIncluding.getNumber();
young = (young == -1) ? myRevisions.get(myRevisions.size() - 1) : young;
final long old = toIncluding.getNumber();
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java
index b686c94..a41f117 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnExternalCommitNoticedTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -22,7 +22,6 @@
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.openapi.vfs.impl.local.FileWatcher;
import org.jetbrains.idea.svn.RootUrlInfo;
import org.jetbrains.idea.svn.Svn17TestCase;
import org.jetbrains.idea.svn.SvnFileUrlMapping;
@@ -48,7 +47,7 @@
@Override
@Before
public void setUp() throws Exception {
- System.setProperty(FileWatcher.PROPERTY_WATCHER_DISABLED, "false");
+ //System.setProperty(FileWatcher.PROPERTY_WATCHER_DISABLED, "false");
super.setUp();
clManager = (ChangeListManagerImpl) ChangeListManager.getInstance(myProject);
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java
index b66371a..efbb6b9 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn16/SvnMergeInfoTest.java
@@ -64,7 +64,7 @@
myWCInfo = new WCInfo(root, true, SVNDepth.INFINITY);
myOneShotMergeInfoHelper = new OneShotMergeInfoHelper(myProject, myWCInfo, myRepoUrl + "/trunk");
- SvnConfiguration.getInstance(myProject).CHECK_NESTED_FOR_QUICK_MERGE = true;
+ SvnConfiguration.getInstance(myProject).setCheckNestedForQuickMerge(true);
// AbstractVcs vcsFound = myProjectLevelVcsManager.findVcsByName(SvnVcs.VCS_NAME);
// Assert.assertEquals(1, myProjectLevelVcsManager.getRootsUnderVcs(vcsFound).length);
}
@@ -107,7 +107,7 @@
final SvnChangeList changeList = changeListList.get(0);
final BranchInfo mergeChecker =
- new BranchInfo(vcs, myRepoUrl, myRepoUrl + "/branch", myRepoUrl + "/trunk", myRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, myRepoUrl, myRepoUrl + "/branch", myRepoUrl + "/trunk", myRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -166,7 +166,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result);
@@ -235,7 +235,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -294,7 +294,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
final SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -369,7 +369,7 @@
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result);
result = mergeChecker.checkList(changeList4, myBranchVcsRoot.getAbsolutePath());
@@ -447,7 +447,7 @@
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
@@ -513,7 +513,7 @@
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList3, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.MERGED.equals(result);
}
@@ -571,7 +571,7 @@
final SvnChangeList changeList = changeListList.get(0);
final String encodedRepoUrl = SVNURL.parseURIDecoded(myRepoUrl).toString();
final BranchInfo mergeChecker =
- new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk", vcs.createWCClient());
+ new BranchInfo(vcs, encodedRepoUrl, encodedRepoUrl + "/branch", encodedRepoUrl + "/trunk", encodedRepoUrl + "/trunk");
SvnMergeInfoCache.MergeCheckResult result = mergeChecker.checkList(changeList, myBranchVcsRoot.getAbsolutePath());
assert SvnMergeInfoCache.MergeCheckResult.NOT_MERGED.equals(result);
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
index 8d2e756..09f9081 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/TaskRepository.java
@@ -217,7 +217,7 @@
return "{id} (e.g. FOO-001), {summary}, {number} (e.g. 001), {project} (e.g. FOO)";
}
- public void updateTimeSpent(final LocalTask task, final String timeSpent, final String comment) throws Exception {
+ public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception {
throw new UnsupportedOperationException();
}
diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java
index 65c2a21..bedd3d3 100644
--- a/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java
+++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/impl/BaseRepositoryImpl.java
@@ -3,17 +3,12 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.tasks.TaskRepositoryType;
import com.intellij.tasks.config.TaskSettings;
-import com.intellij.util.net.CertificatesManager;
import com.intellij.util.net.HttpConfigurable;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.auth.AuthScope;
-import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
-import org.apache.commons.httpclient.protocol.Protocol;
-import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import javax.net.ssl.SSLContext;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
@@ -23,23 +18,8 @@
* @author Dmitry Avdeev
*/
public abstract class BaseRepositoryImpl extends BaseRepository {
- public static final String EASY_HTTPS = "easyhttps";
-
private static final Logger LOG = Logger.getInstance(BaseRepositoryImpl.class);
- static {
- try {
- SSLContext context = CertificatesManager.createDefault().createSslContext();
- SSLContext.setDefault(context);
- }
- catch (Exception e) {
- LOG.error(e);
- }
- // Don't do this: protocol created this way will ignore SSL tunnels. See IDEA-115708.
- // Protocol.registerProtocol("https", CertificatesManager.createDefault().createProtocol());
- Protocol.registerProtocol(EASY_HTTPS, new Protocol(EASY_HTTPS, (ProtocolSocketFactory)new EasySSLProtocolSocketFactory(), 443));
- }
-
protected BaseRepositoryImpl() {
}
diff --git a/plugins/tasks/tasks-core/src/META-INF/plugin.xml b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
index b558f4e..c204166 100644
--- a/plugins/tasks/tasks-core/src/META-INF/plugin.xml
+++ b/plugins/tasks/tasks-core/src/META-INF/plugin.xml
@@ -54,10 +54,16 @@
</action>
</group>
+ <group id="tasks.internal" text="_Tasks" internal="true" popup="true">
+ <action id="show.certificate" class="com.intellij.tasks.actions.ShowCertificateInfoAction" text="_Show certificate dialog"/>
+ <add-to-group group-id="Internal"/>
+ </group>
+
<group id="tasks.and.contexts" text="_Tasks & Contexts" popup="true">
<reference ref="task.actions"/>
<separator/>
<reference ref="working.context"/>
+ <!-- <reference ref="tasks.util"/> -->
</group>
<group id="tasks.group">
@@ -123,6 +129,7 @@
<tasks.repositoryType implementation="com.intellij.tasks.mantis.MantisRepositoryType"/>
<tasks.repositoryType implementation="com.intellij.tasks.generic.GenericRepositoryType"/>
<tasks.repositoryType implementation="com.intellij.tasks.trello.TrelloRepositoryType"/>
+ <tasks.repositoryType implementation="com.intellij.tasks.gitlab.GitlabRepositoryType"/>
<!-- JQL support -->
<fileTypeFactory implementation="com.intellij.tasks.jira.jql.JqlFileTypeFactory"/>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form
index 1061bc9..fb7ab62 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.form
@@ -73,7 +73,7 @@
</component>
</children>
</grid>
- <grid id="637f6" binding="myVcsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="637f6" binding="myVcsPanel" layout-manager="GridLayoutManager" row-count="2" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -96,7 +96,7 @@
</component>
<component id="3b431" class="javax.swing.JTextField" binding="myChangelistName">
<constraints>
- <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
+ <grid row="1" column="1" row-span="1" col-span="3" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
@@ -120,6 +120,21 @@
<text value="Create change&list"/>
</properties>
</component>
+ <component id="e6ce7" class="com.intellij.openapi.ui.ComboBox" binding="myBranchFrom">
+ <constraints>
+ <grid row="0" column="3" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="2cb41" class="com.intellij.ui.components.JBLabel" binding="myFromLabel">
+ <constraints>
+ <grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties>
+ <labelFor value="e6ce7"/>
+ <text value="&from"/>
+ </properties>
+ </component>
</children>
</grid>
</children>
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java
index 564c806..54d1e8a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java
@@ -16,19 +16,26 @@
package com.intellij.tasks.actions;
+import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.options.binding.BindControl;
import com.intellij.openapi.options.binding.ControlBinder;
import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.ValidationInfo;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vcs.AbstractVcs;
+import com.intellij.openapi.vcs.VcsTaskHandler;
import com.intellij.openapi.vcs.VcsType;
import com.intellij.tasks.*;
import com.intellij.tasks.impl.TaskManagerImpl;
import com.intellij.tasks.impl.TaskUtil;
+import com.intellij.ui.ColoredListCellRenderer;
import com.intellij.ui.components.JBCheckBox;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -42,6 +49,7 @@
*/
public class OpenTaskDialog extends DialogWrapper {
private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.actions.SimpleOpenTaskDialog");
+ public static final String START_FROM_BRANCH = "start.from.branch";
private JPanel myPanel;
@BindControl(value = "clearContext", instant = true)
@@ -53,9 +61,12 @@
private JTextField myChangelistName;
private JBCheckBox myCreateBranch;
private JBCheckBox myCreateChangelist;
+ private JBLabel myFromLabel;
+ private ComboBox myBranchFrom;
private final Project myProject;
private final Task myTask;
+ private VcsTaskHandler myVcsTaskHandler;
public OpenTaskDialog(@NotNull final Project project, @NotNull final Task task) {
super(project, false);
@@ -96,10 +107,54 @@
myCreateChangelist.setSelected(manager.getState().createChangelist);
myCreateBranch.setSelected(manager.getState().createBranch);
- if (vcs.getType() != VcsType.distributed) {
+ // In git 'master' branch appears (in .git/refs/heads/master) only after at least one commit was made in it.
+ // Before that feature branches can't be created normally.
+ if (vcs.getType() != VcsType.distributed || !branchesExist(project)) {
myCreateBranch.setSelected(false);
myCreateBranch.setVisible(false);
myBranchName.setVisible(false);
+ myFromLabel.setVisible(false);
+ myBranchFrom.setVisible(false);
+ }
+ else {
+ VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(project);
+ for (VcsTaskHandler handler : handlers) {
+ VcsTaskHandler.TaskInfo[] tasks = handler.getCurrentTasks();
+ if (tasks.length > 0) {
+ myVcsTaskHandler = handler;
+ myBranchFrom.setModel(new DefaultComboBoxModel(tasks));
+ final String startFrom = PropertiesComponent.getInstance(project).getValue(START_FROM_BRANCH);
+ VcsTaskHandler.TaskInfo info = null;
+ if (startFrom != null) {
+ info = ContainerUtil.find(tasks, new Condition<VcsTaskHandler.TaskInfo>() {
+ @Override
+ public boolean value(VcsTaskHandler.TaskInfo taskInfo) {
+ return startFrom.equals(taskInfo.getName());
+ }
+ });
+ }
+ if (info == null) {
+ info = handler.getActiveTask();
+ }
+ myBranchFrom.setSelectedItem(info);
+ myBranchFrom.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ VcsTaskHandler.TaskInfo item = (VcsTaskHandler.TaskInfo)myBranchFrom.getSelectedItem();
+ if (item != null) {
+ PropertiesComponent.getInstance(project).setValue(START_FROM_BRANCH, item.getName());
+ }
+ }
+ });
+ break;
+ }
+ }
+ myBranchFrom.setRenderer(new ColoredListCellRenderer<VcsTaskHandler.TaskInfo>() {
+ @Override
+ protected void customizeCellRenderer(JList list, VcsTaskHandler.TaskInfo value, int index, boolean selected, boolean hasFocus) {
+ append(value.getName());
+ }
+ });
}
myBranchName.setText(taskManager.suggestBranchName(task));
@@ -109,6 +164,15 @@
init();
}
+ private static boolean branchesExist(Project project) {
+ for (VcsTaskHandler handler : VcsTaskHandler.getAllHandlers(project)) {
+ if (handler.getCurrentTasks().length != 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private void updateFields() {
myBranchName.setEnabled(myCreateBranch.isSelected());
myChangelistName.setEnabled(myCreateChangelist.isSelected());
@@ -122,7 +186,7 @@
}
public void createTask() {
- TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
+ final TaskManagerImpl taskManager = (TaskManagerImpl)TaskManager.getManager(myProject);
taskManager.getState().markAsInProgress = isMarkAsInProgress();
taskManager.getState().createChangelist = myCreateChangelist.isSelected();
@@ -138,13 +202,25 @@
LOG.warn(ex);
}
}
- LocalTask activeTask = taskManager.getActiveTask();
- LocalTask localTask = taskManager.activateTask(myTask, isClearContext());
+ final LocalTask activeTask = taskManager.getActiveTask();
+ final LocalTask localTask = taskManager.activateTask(myTask, isClearContext());
if (myCreateChangelist.isSelected()) {
taskManager.createChangeList(localTask, myChangelistName.getText());
}
if (myCreateBranch.isSelected()) {
- taskManager.createBranch(localTask, activeTask, myBranchName.getText());
+ VcsTaskHandler.TaskInfo item = (VcsTaskHandler.TaskInfo)myBranchFrom.getSelectedItem();
+ Runnable createBranch = new Runnable() {
+ @Override
+ public void run() {
+ taskManager.createBranch(localTask, activeTask, myBranchName.getText());
+ }
+ };
+ if (item != null && !item.equals(myVcsTaskHandler.getActiveTask())) {
+ myVcsTaskHandler.switchToTask(item, createBranch);
+ }
+ else {
+ createBranch.run();
+ }
}
if (myTask.getType() == TaskType.EXCEPTION && AnalyzeTaskStacktraceAction.hasTexts(myTask)) {
AnalyzeTaskStacktraceAction.analyzeStacktrace(myTask, myProject);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java
index 9ec2012..670f651 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskInBrowserAction.java
@@ -19,7 +19,6 @@
import com.intellij.ide.BrowserUtil;
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.project.Project;
import com.intellij.tasks.TaskManager;
@@ -33,7 +32,7 @@
public void actionPerformed(AnActionEvent e) {
String url = getIssueUrl(e);
if (url != null) {
- BrowserUtil.launchBrowser(url);
+ BrowserUtil.browse(url);
}
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowCertificateInfoAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowCertificateInfoAction.java
new file mode 100644
index 0000000..7c5e352
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/ShowCertificateInfoAction.java
@@ -0,0 +1,40 @@
+package com.intellij.tasks.actions;
+
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.util.net.ssl.CertificateWarningDialog;
+import com.intellij.util.net.ssl.CertificatesManager;
+
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class ShowCertificateInfoAction extends AnAction {
+ private static final Logger LOG = Logger.getInstance(ShowCertificateInfoAction.class);
+
+ public ShowCertificateInfoAction() {
+ super("Show certificate information dialog");
+ }
+
+ @Override
+ public void actionPerformed(final AnActionEvent e) {
+ try {
+ CertificatesManager manager = CertificatesManager.getInstance();
+ List<X509Certificate> certificates = manager.getCustomTrustManager().getCertificates();
+ if (certificates.isEmpty()) {
+ Messages.showInfoMessage(String.format("Key store '%s' is empty", manager.getCacertsPath()), "No Certificates Available");
+ } else {
+ CertificateWarningDialog dialog = CertificateWarningDialog.createUntrustedCertificateWarning(certificates.get(0));
+ LOG.debug("Accepted: " + dialog.showAndGet());
+ }
+ }
+ catch (Exception logged) {
+ LOG.error(logged);
+ }
+ }
+}
+
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java
index cf8b257..84bc2bb 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/SwitchTaskAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2011 JetBrains s.r.o.
+ * 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.
@@ -243,9 +243,9 @@
"Do you want to remove it and move the changes to the active changelist?",
"Changelist Not Empty", Messages.getWarningIcon());
switch (result) {
- case 0:
+ case Messages.YES:
break l;
- case 1:
+ case Messages.NO:
removeIt = false;
break;
default:
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
index f437897..2fc0573 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/context/WorkingContextManager.java
@@ -169,7 +169,7 @@
File tasksFolder = new File(PathManager.getConfigPath(), TASKS_FOLDER);
if (!tasksFolder.exists()) {
//noinspection ResultOfMethodCallIgnored
- tasksFolder.mkdir();
+ tasksFolder.mkdirs();
}
String projectName = FileUtil.sanitizeFileName(myProject.getName());
return new File(tasksFolder, projectName + postfix);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java
index 3b8a640..b4e2a0e 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryType.java
@@ -3,8 +3,8 @@
import com.intellij.icons.AllIcons;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.JDOMUtil;
-import com.intellij.tasks.TaskRepositorySubtype;
import com.intellij.tasks.TaskRepository;
+import com.intellij.tasks.TaskRepositorySubtype;
import com.intellij.tasks.config.TaskRepositoryEditor;
import com.intellij.tasks.impl.BaseRepositoryType;
import com.intellij.util.Consumer;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java
index 2a899d6..7880170 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/GenericRepositoryUtil.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.tasks.generic;
import com.intellij.openapi.util.text.StringUtil;
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml
index da466a6..744d80a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/generic/connectors/assembla.xml
@@ -1,5 +1,5 @@
<Assembla shared="false" url="http://www.assembla.com">
- <commitMessageFormat>{id} {summary}</commitMessageFormat>
+ <commitMessageFormat>#{id} {summary}</commitMessageFormat>
<option name="downloadTasksInSeparateRequests" value="false" />
<password/>
<option name="loginAnonymously" value="false" />
@@ -9,7 +9,7 @@
<XPathResponseHandler>
<selectors>
<selector name="tasks" path="/tickets/ticket" />
- <selector name="id" path="id" />
+ <selector name="id" path="number" />
<selector name="summary" path="summary" />
<selector name="description" path="description" />
<selector name="updated" path="updated-at" />
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java
new file mode 100644
index 0000000..7a07878
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java
@@ -0,0 +1,198 @@
+package com.intellij.tasks.gitlab;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.reflect.TypeToken;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskRepositoryType;
+import com.intellij.tasks.gitlab.model.GitlabIssue;
+import com.intellij.tasks.gitlab.model.GitlabProject;
+import com.intellij.tasks.httpclient.NewBaseRepositoryImpl;
+import com.intellij.tasks.impl.TaskUtil;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.apache.http.*;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.protocol.HttpContext;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.IOException;
+import java.util.List;
+
+import static com.intellij.tasks.httpclient.ResponseUtil.GsonMultipleObjectsDeserializer;
+import static com.intellij.tasks.httpclient.ResponseUtil.GsonSingleObjectDeserializer;
+
+/**
+ * @author Mikhail Golubev
+ */
+@Tag("Gitlab")
+public class GitlabRepository extends NewBaseRepositoryImpl {
+
+ @NonNls public static final String REST_API_PATH_PREFIX = "/api/v3/";
+ public static final Gson GSON = TaskUtil.installDateDeserializer(new GsonBuilder()).create();
+ public static final TypeToken<List<GitlabProject>> LIST_OF_PROJECTS_TYPE = new TypeToken<List<GitlabProject>>() {};
+ public static final TypeToken<List<GitlabIssue>> LIST_OF_ISSUES_TYPE = new TypeToken<List<GitlabIssue>>() {};
+ public static final GitlabProject UNSPECIFIED_PROJECT = new GitlabProject() {
+ @Override
+ public String getName() {
+ return "-- from all projects --";
+ }
+
+ @Override
+ public int getId() {
+ return -1;
+ }
+ };
+
+
+ private GitlabProject myCurrentProject;
+
+ /**
+ * Serialization constructor
+ */
+ @SuppressWarnings("UnusedDeclaration")
+ public GitlabRepository() {
+ }
+
+ /**
+ * Normal instantiation constructor
+ */
+ public GitlabRepository(TaskRepositoryType type) {
+ super(type);
+ }
+
+ /**
+ * Cloning constructor
+ */
+ public GitlabRepository(GitlabRepository other) {
+ super(other);
+ myCurrentProject = other.myCurrentProject;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!super.equals(o)) return false;
+ GitlabRepository repository = (GitlabRepository)o;
+ if (!Comparing.equal(myCurrentProject, repository.myCurrentProject)) return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return myCurrentProject != null ? myCurrentProject.hashCode() : 0;
+ }
+
+ @Override
+ public GitlabRepository clone() {
+ return new GitlabRepository(this);
+ }
+
+ @Override
+ public Task[] getIssues(@Nullable String query, int max, long since) throws Exception {
+ return ContainerUtil.map2Array(fetchIssues(), GitlabTask.class, new Function<GitlabIssue, GitlabTask>() {
+ @Override
+ public GitlabTask fun(GitlabIssue issue) {
+ return new GitlabTask(GitlabRepository.this, myCurrentProject, issue);
+ }
+ });
+ }
+
+ @Nullable
+ @Override
+ public Task findTask(String id) throws Exception {
+ return new GitlabTask(this, myCurrentProject, fetchIssue(Integer.parseInt(id)));
+ }
+
+ @Nullable
+ @Override
+ public CancellableConnection createCancellableConnection() {
+ return new CancellableConnection() {
+ private HttpGet myRequest = new HttpGet(getIssuesUrl());
+
+ @Override
+ protected void doTest() throws Exception {
+ HttpResponse response = getHttpClient().execute(myRequest);
+ StatusLine statusLine = response.getStatusLine();
+ if (statusLine != null && statusLine.getStatusCode() != HttpStatus.SC_OK) {
+ throw new Exception(statusLine.getReasonPhrase());
+ }
+ }
+
+ // TODO: find more about proper request aborting in HttpClient4.x
+ @Override
+ public void cancel() {
+ myRequest.abort();
+ }
+ };
+ }
+
+ @NotNull
+ List<GitlabProject> fetchProjects() throws Exception {
+ HttpGet request = new HttpGet(getRestApiUrl("projects"));
+ ResponseHandler<List<GitlabProject>> handler = new GsonMultipleObjectsDeserializer<GitlabProject>(GSON, LIST_OF_PROJECTS_TYPE);
+ return getHttpClient().execute(request, handler);
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ @NotNull
+ GitlabProject fetchProject(int id) throws Exception {
+ HttpGet request = new HttpGet(getRestApiUrl("project", id));
+ return getHttpClient().execute(request, new GsonSingleObjectDeserializer<GitlabProject>(GSON, GitlabProject.class));
+ }
+
+ @NotNull
+ List<GitlabIssue> fetchIssues() throws Exception {
+ ResponseHandler<List<GitlabIssue>> handler = new GsonMultipleObjectsDeserializer<GitlabIssue>(GSON, LIST_OF_ISSUES_TYPE);
+ return getHttpClient().execute(new HttpGet(getIssuesUrl()), handler);
+ }
+
+ private String getIssuesUrl() {
+ if (myCurrentProject != null && myCurrentProject != UNSPECIFIED_PROJECT) {
+ return getRestApiUrl("projects", myCurrentProject.getId(), "issues");
+ }
+ return getRestApiUrl("issues");
+ }
+
+ @NotNull
+ GitlabIssue fetchIssue(int id) throws Exception {
+ HttpGet request = new HttpGet(getRestApiUrl("issues", id));
+ ResponseHandler<GitlabIssue> handler = new GsonSingleObjectDeserializer<GitlabIssue>(GSON, GitlabIssue.class);
+ return getHttpClient().execute(request, handler);
+ }
+
+ @Override
+ public boolean isConfigured() {
+ return super.isConfigured() && !myPassword.isEmpty();
+ }
+
+ @NotNull
+ @Override
+ public String getRestApiPathPrefix() {
+ return REST_API_PATH_PREFIX;
+ }
+
+ @Nullable
+ @Override
+ protected HttpRequestInterceptor createRequestInterceptor() {
+ return new HttpRequestInterceptor() {
+ @Override
+ public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
+ request.addHeader(new BasicHeader("PRIVATE-TOKEN", myPassword));
+ }
+ };
+ }
+
+ public void setCurrentProject(GitlabProject currentProject) {
+ myCurrentProject = currentProject.getId() == -1 ? UNSPECIFIED_PROJECT : currentProject;
+ }
+
+ public GitlabProject getCurrentProject() {
+ return myCurrentProject;
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepositoryEditor.java
new file mode 100644
index 0000000..4a47459
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepositoryEditor.java
@@ -0,0 +1,175 @@
+package com.intellij.tasks.gitlab;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.tasks.config.BaseRepositoryEditor;
+import com.intellij.tasks.gitlab.model.GitlabProject;
+import com.intellij.ui.DocumentAdapter;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.ui.components.JBLabel;
+import com.intellij.util.Consumer;
+import com.intellij.util.ui.FormBuilder;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.event.DocumentEvent;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.List;
+
+import static com.intellij.tasks.gitlab.GitlabRepository.UNSPECIFIED_PROJECT;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class GitlabRepositoryEditor extends BaseRepositoryEditor<GitlabRepository> {
+ private static final Logger LOG = Logger.getInstance(GitlabRepositoryEditor.class);
+
+ private JBLabel myProjectLabel;
+ private ComboBox myProjectComboBox;
+
+
+ public GitlabRepositoryEditor(Project project, GitlabRepository repository, Consumer<GitlabRepository> changeListener) {
+ super(project, repository, changeListener);
+ myPasswordLabel.setText("Token:");
+
+ // Hide unused login field
+ myUsernameLabel.setVisible(false);
+ myUserNameText.setVisible(false);
+
+ myTestButton.setEnabled(myRepository.isConfigured());
+
+ myProjectComboBox.setRenderer(new ListCellRendererWrapper<GitlabProject>() {
+ @Override
+ public void customize(JList list, GitlabProject project, int index, boolean selected, boolean hasFocus) {
+ setText(project == null ? "Set server URL and token first" : project.getName());
+ }
+ });
+
+ // Listeners
+ myPasswordText.getDocument().addDocumentListener(new DocumentAdapter() {
+ @Override
+ protected void textChanged(DocumentEvent e) {
+ if (myPasswordText.getPassword().length != 0) {
+ new FetchProjectsTask().queue();
+ }
+ }
+ });
+ installListener(myProjectComboBox);
+ myProjectComboBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ myRepository.setCurrentProject((GitlabProject)e.getItem());
+ }
+ }
+ });
+ // Combo box initialization
+ UIUtil.invokeLaterIfNeeded(new Runnable() {
+ @Override
+ public void run() {
+ initialize();
+ }
+ });
+ }
+
+ private void initialize() {
+ final GitlabProject currentProject = myRepository.getCurrentProject();
+ if (currentProject != null && myRepository.isConfigured()) {
+ new FetchProjectsTask() {
+ @Override
+ public void updateUI() {
+ super.updateUI();
+ for (int i = 0; i < myProjectComboBox.getItemCount(); i++) {
+ GitlabProject project = (GitlabProject)myProjectComboBox.getItemAt(i);
+ if (project.getId() == currentProject.getId()) {
+ // update project with full info
+ myRepository.setCurrentProject(project);
+ myProjectComboBox.setSelectedItem(project);
+ return;
+ }
+ }
+ myRepository.setCurrentProject(UNSPECIFIED_PROJECT);
+ }
+ }.queue();
+ }
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCustomPanel() {
+ myProjectLabel = new JBLabel("Project:", SwingConstants.RIGHT);
+ myProjectComboBox = new ComboBox(300);
+ myProjectLabel.setLabelFor(myProjectComboBox);
+ return new FormBuilder().addLabeledComponent(myProjectLabel, myProjectComboBox).getPanel();
+ }
+
+ @Override
+ public void setAnchor(@Nullable JComponent anchor) {
+ super.setAnchor(anchor);
+ myProjectLabel.setAnchor(anchor);
+ }
+
+ @Override
+ protected void afterTestConnection(boolean connectionSuccessful) {
+ if (connectionSuccessful) {
+ new FetchProjectsTask().queue();
+ }
+ }
+
+ @Override
+ public void apply() {
+ super.apply();
+ myTestButton.setEnabled(myRepository.isConfigured());
+ }
+
+ private class FetchProjectsTask extends Task.Modal {
+ @NonNls public static final String TITLE = "Downloading Gitlab projects...";
+ private List<GitlabProject> myProjects;
+
+ private FetchProjectsTask() {
+ //super(GitlabRepositoryEditor.this.myProject, TITLE);
+ super(GitlabRepositoryEditor.this.myProject, TITLE, false);
+ }
+
+ @Override
+ public void run(@NotNull ProgressIndicator indicator) {
+ try {
+ myProjects = myRepository.fetchProjects();
+ }
+ catch (Exception e) {
+ LOG.warn(e);
+ myProjectComboBox.removeAllItems();
+ }
+ }
+
+ @Nullable
+ @Override
+ public final NotificationInfo notifyFinished() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ updateUI();
+ }
+ }, ModalityState.current());
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void updateUI() {
+ if (myProjects != null) {
+ myProjectComboBox.setModel(new DefaultComboBoxModel(myProjects.toArray(new GitlabProject[myProjects.size()])));
+ myProjectComboBox.insertItemAt(UNSPECIFIED_PROJECT, 0);
+ myProjectComboBox.setSelectedItem(UNSPECIFIED_PROJECT);
+ }
+ }
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepositoryType.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepositoryType.java
new file mode 100644
index 0000000..25315c6
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepositoryType.java
@@ -0,0 +1,47 @@
+package com.intellij.tasks.gitlab;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.tasks.TaskRepository;
+import com.intellij.tasks.config.TaskRepositoryEditor;
+import com.intellij.tasks.impl.BaseRepositoryType;
+import com.intellij.util.Consumer;
+import icons.TasksIcons;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class GitlabRepositoryType extends BaseRepositoryType<GitlabRepository>{
+ @NotNull
+ @Override
+ public String getName() {
+ return "Gitlab";
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ return TasksIcons.Gitlab;
+ }
+
+ @NotNull
+ @Override
+ public TaskRepository createRepository() {
+ return new GitlabRepository(this);
+ }
+
+ @NotNull
+ @Override
+ public TaskRepositoryEditor createEditor(GitlabRepository repository,
+ Project project,
+ Consumer<GitlabRepository> changeListener) {
+ return new GitlabRepositoryEditor(project, repository, changeListener);
+ }
+
+ @Override
+ public Class<GitlabRepository> getRepositoryClass() {
+ return GitlabRepository.class;
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabTask.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabTask.java
new file mode 100644
index 0000000..6c17a6a
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabTask.java
@@ -0,0 +1,94 @@
+package com.intellij.tasks.gitlab;
+
+import com.intellij.tasks.Comment;
+import com.intellij.tasks.Task;
+import com.intellij.tasks.TaskType;
+import com.intellij.tasks.gitlab.model.GitlabIssue;
+import com.intellij.tasks.gitlab.model.GitlabProject;
+import icons.TasksIcons;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.Date;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class GitlabTask extends Task {
+ private final GitlabIssue myIssue;
+ private final GitlabRepository myRepository;
+ private final GitlabProject myProject;
+
+ public GitlabTask(@NotNull GitlabRepository respository,
+ @NotNull GitlabProject project,
+ @NotNull GitlabIssue issue) {
+ myRepository = respository;
+ myIssue = issue;
+ myProject = project;
+ }
+
+ @NotNull
+ @Override
+ public String getId() {
+ return String.valueOf(myIssue.getId());
+ }
+
+ @NotNull
+ @Override
+ public String getSummary() {
+ return myIssue.getTitle();
+ }
+
+ @Nullable
+ @Override
+ public String getDescription() {
+ return null;
+ }
+
+ @NotNull
+ @Override
+ public Comment[] getComments() {
+ return Comment.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ return TasksIcons.Gitlab;
+ }
+
+ @NotNull
+ @Override
+ public TaskType getType() {
+ return TaskType.BUG;
+ }
+
+ @Nullable
+ @Override
+ public Date getUpdated() {
+ return myIssue.getUpdatedAt();
+ }
+
+ @Nullable
+ @Override
+ public Date getCreated() {
+ return myIssue.getCreatedAt();
+ }
+
+ @Override
+ public boolean isClosed() {
+ return myIssue.getState().equals("closed");
+ }
+
+ @Override
+ public boolean isIssue() {
+ return true;
+ }
+
+ @Nullable
+ @Override
+ public String getIssueUrl() {
+ return myProject.getWebUrl() + "/issues/" + myIssue.getLocalId();
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/model/GitlabIssue.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/model/GitlabIssue.java
new file mode 100644
index 0000000..6961493
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/model/GitlabIssue.java
@@ -0,0 +1,62 @@
+package com.intellij.tasks.gitlab.model;
+
+import com.google.gson.annotations.SerializedName;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Date;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class GitlabIssue {
+ private int id;
+ @SerializedName("iid")
+ private int localId;
+ private String title;
+ private String description;
+ @SerializedName("project_id")
+ private int projectId;
+ @SerializedName("updated_at")
+ private Date updatedAt;
+ @SerializedName("created_at")
+ private Date createdAt;
+ private String state;
+
+
+ public int getId() {
+ return id;
+ }
+
+ @NotNull
+ public String getTitle() {
+ return title;
+ }
+
+ @NotNull
+ public String getDescription() {
+ return description;
+ }
+
+ public int getProjectId() {
+ return projectId;
+ }
+
+ @NotNull
+ public Date getUpdatedAt() {
+ return updatedAt;
+ }
+
+ @NotNull
+ public Date getCreatedAt() {
+ return createdAt;
+ }
+
+ @NotNull
+ public String getState() {
+ return state;
+ }
+
+ public int getLocalId() {
+ return localId;
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/model/GitlabProject.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/model/GitlabProject.java
new file mode 100644
index 0000000..1213ecb
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/model/GitlabProject.java
@@ -0,0 +1,54 @@
+package com.intellij.tasks.gitlab.model;
+
+import com.google.gson.annotations.SerializedName;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Only required fields are declared.
+ * Field {@code name} and {@code webUrl} may be null because only {@code id} is serialized.
+ *
+ * @author Mikhail Golubev
+ */
+@Tag("GitlabProject")
+public class GitlabProject {
+ private int id;
+ private String name;
+ @SerializedName("web_url")
+ private String webUrl;
+
+ @Override
+ public final boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GitlabProject)) return false;
+ return id == ((GitlabProject)o).id;
+ }
+
+ @Override
+ public final int hashCode() {
+ return id;
+ }
+
+ @Attribute("id")
+ public int getId() {
+ return id;
+ }
+
+ /**
+ * For serialization purposed only
+ */
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ @Nullable
+ public String getName() {
+ return name;
+ }
+
+ @Nullable
+ public String getWebUrl() {
+ return webUrl;
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/httpclient/NewBaseRepositoryImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/httpclient/NewBaseRepositoryImpl.java
new file mode 100644
index 0000000..e47b8f8
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/httpclient/NewBaseRepositoryImpl.java
@@ -0,0 +1,139 @@
+package com.intellij.tasks.httpclient;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.tasks.TaskRepositoryType;
+import com.intellij.tasks.config.TaskSettings;
+import com.intellij.tasks.impl.BaseRepository;
+import com.intellij.tasks.impl.TaskUtil;
+import com.intellij.util.net.HttpConfigurable;
+import com.intellij.util.net.ssl.CertificatesManager;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpRequestInterceptor;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.conn.ssl.X509HostnameVerifier;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.impl.client.HttpClients;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * This alternative base implementation of {@link com.intellij.tasks.impl.BaseRepository} should be used
+ * for new connectors that use httpclient-4.x instead of legacy httpclient-3.1.
+ *
+ * @author Mikhail Golubev
+ */
+public abstract class NewBaseRepositoryImpl extends BaseRepository {
+ private static final Logger LOG = Logger.getInstance(NewBaseRepositoryImpl.class);
+
+ /**
+ * Serialization constructor
+ */
+ protected NewBaseRepositoryImpl() {
+ // empty
+ }
+
+ protected NewBaseRepositoryImpl(TaskRepositoryType type) {
+ super(type);
+ }
+
+ protected NewBaseRepositoryImpl(BaseRepository other) {
+ super(other);
+ }
+
+ @NotNull
+ protected HttpClient getHttpClient() {
+ HttpClientBuilder builder = HttpClients.custom()
+ .setDefaultRequestConfig(createRequestConfig())
+ .setSslcontext(CertificatesManager.getInstance().getSslContext())
+ // TODO: use custom one for additional certificate check
+ //.setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
+ .setHostnameVerifier((X509HostnameVerifier)CertificatesManager.HOSTNAME_VERIFIER)
+ .setDefaultCredentialsProvider(createCredentialsProvider());
+ HttpRequestInterceptor interceptor = createRequestInterceptor();
+ if (interceptor != null) {
+ builder = builder.addInterceptorLast(interceptor);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Custom request interceptor can be used for modifying outgoing requests. One possible usage is to
+ * add specific header to each request according to authentication scheme used.
+ *
+ * @return specific request interceptor or null by default
+ */
+ @Nullable
+ protected HttpRequestInterceptor createRequestInterceptor() {
+ return null;
+ }
+
+ @NotNull
+ private CredentialsProvider createCredentialsProvider() {
+ CredentialsProvider provider = new BasicCredentialsProvider();
+ HttpConfigurable proxySettings = HttpConfigurable.getInstance();
+ if (isUseHttpAuthentication()) {
+ provider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(getUsername(), getPassword()));
+ }
+ if (isUseProxy() && proxySettings.PROXY_AUTHENTICATION) {
+ provider.setCredentials(new AuthScope(new HttpHost(proxySettings.PROXY_HOST)),
+ new UsernamePasswordCredentials(proxySettings.PROXY_LOGIN,
+ proxySettings.getPlainProxyPassword()));
+ }
+ return provider;
+ }
+
+ @NotNull
+ protected RequestConfig createRequestConfig() {
+ TaskSettings tasksSettings = TaskSettings.getInstance();
+ HttpConfigurable proxySettings = HttpConfigurable.getInstance();
+ RequestConfig.Builder builder = RequestConfig.custom()
+ .setConnectTimeout(3000)
+ .setSocketTimeout(tasksSettings.CONNECTION_TIMEOUT);
+ if (isUseProxy()) {
+ HttpHost proxy = new HttpHost(proxySettings.PROXY_HOST, proxySettings.PROXY_PORT);
+ builder = builder.setProxy(proxy);
+ }
+ return builder.build();
+ }
+
+ /**
+ * Return server's REST API path prefix, e.g. {@code /rest/api/latest} for JIRA or {@code /api/v3/} for Gitlab.
+ * This value will be used in {@link #getRestApiUrl(Object...)}
+ *
+ * @return server's REST API path prefix
+ */
+ @NotNull
+ public String getRestApiPathPrefix() {
+ return "";
+ }
+
+ /**
+ * Build URL using {@link #getUrl()}, {@link #getRestApiPathPrefix()}} and specified path components.
+ * <p/>
+ * Individual path components will should not contain leading or trailing slashes. Empty or null components
+ * will be omitted. Each components is converted to string using its {@link Object#toString()} method and url encoded, so
+ * numeric IDs can be used as well. Returned URL doesn't contain trailing '/', because it's not compatible with some services.
+ *
+ * @return described URL
+ */
+ @NotNull
+ public String getRestApiUrl(@NotNull Object... parts) {
+ StringBuilder builder = new StringBuilder(getUrl());
+ builder.append(getRestApiPathPrefix());
+ if (builder.charAt(builder.length() - 1) == '/') {
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ for (Object part : parts) {
+ if (part == null || part.equals("")) {
+ continue;
+ }
+ builder.append('/').append(TaskUtil.encodeUrl(String.valueOf(part)));
+ }
+ return builder.toString();
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/httpclient/ResponseUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/httpclient/ResponseUtil.java
new file mode 100644
index 0000000..581de8e
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/httpclient/ResponseUtil.java
@@ -0,0 +1,82 @@
+package com.intellij.tasks.httpclient;
+
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.tasks.impl.TaskUtil;
+import org.apache.http.Header;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.ResponseHandler;
+import org.apache.http.util.EntityUtils;
+
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.util.List;
+
+/**
+ * @author Mikhail Golubev
+ */
+public class ResponseUtil {
+ public static final Logger LOG = Logger.getInstance(ResponseUtil.class);
+ // TODO: in JDK7 see StandardCharsets
+ public final static Charset DEFAULT_CHARSET = Charset.forName(CharsetToolkit.UTF8);
+
+ /**
+ * Utility class
+ */
+ private ResponseUtil() {
+ }
+
+ public static Reader getResponseContentAsReader(HttpResponse response) throws IOException {
+ Header header = response.getEntity().getContentEncoding();
+ Charset charset = header == null ? DEFAULT_CHARSET : Charset.forName(header.getValue());
+ return new InputStreamReader(response.getEntity().getContent(), charset);
+ }
+
+ public static String getResponseContentAsString(HttpResponse response) throws IOException {
+ return EntityUtils.toString(response.getEntity(), DEFAULT_CHARSET);
+ }
+
+
+ public static final class GsonSingleObjectDeserializer<T> implements ResponseHandler<T> {
+ private final Gson myGson;
+ private final Class<T> myClass;
+ public GsonSingleObjectDeserializer(Gson gson, Class<T> cls) {
+ myGson = gson;
+ myClass = cls;
+ }
+
+ @Override
+ public T handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
+ if (LOG.isDebugEnabled()) {
+ String content = getResponseContentAsString(response);
+ TaskUtil.prettyFormatJsonToLog(LOG, content);
+ return myGson.fromJson(content, myClass);
+ }
+ return myGson.fromJson(getResponseContentAsReader(response), myClass);
+ }
+ }
+
+ public static final class GsonMultipleObjectsDeserializer<T> implements ResponseHandler<List<T>> {
+ private final Gson myGson;
+ private final TypeToken<List<T>> myTypeToken;
+ public GsonMultipleObjectsDeserializer(Gson gson, TypeToken<List<T>> token) {
+ myGson = gson;
+ myTypeToken = token;
+ }
+
+ @Override
+ public List<T> handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
+ if (LOG.isDebugEnabled()) {
+ String content = getResponseContentAsString(response);
+ TaskUtil.prettyFormatJsonToLog(LOG, content);
+ return myGson.fromJson(content, myTypeToken.getType());
+ }
+ return myGson.fromJson(getResponseContentAsReader(response), myTypeToken.getType());
+ }
+ }
+}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
index 1dd06d9..f1f275f 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskManagerImpl.java
@@ -379,11 +379,15 @@
List<BranchInfo> branches = task.getBranches(false);
VcsTaskHandler.TaskInfo info = fromBranches(branches);
+ switchBranch(info);
+ return task;
+ }
+
+ public void switchBranch(VcsTaskHandler.TaskInfo info) {
VcsTaskHandler[] handlers = VcsTaskHandler.getAllHandlers(myProject);
for (VcsTaskHandler handler : handlers) {
- handler.switchToTask(info);
+ handler.switchToTask(info, null);
}
- return task;
}
private static VcsTaskHandler.TaskInfo fromBranches(List<BranchInfo> branches) {
@@ -921,10 +925,10 @@
}
public String getChangelistName(Task task) {
- if (task.isIssue() && myConfig.changelistNameFormat != null) {
- return TaskUtil.formatTask(task, myConfig.changelistNameFormat);
- }
- return task.getSummary();
+ String name = task.isIssue() && myConfig.changelistNameFormat != null
+ ? TaskUtil.formatTask(task, myConfig.changelistNameFormat)
+ : task.getSummary();
+ return StringUtil.shortenTextWithEllipsis(name, 100, 0);
}
public String suggestBranchName(Task task) {
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java
index a94f9e8..87dbd62 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java
@@ -16,13 +16,12 @@
package com.intellij.tasks.impl;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
+import com.google.gson.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskRepository;
import org.jdom.Element;
@@ -30,11 +29,15 @@
import org.jetbrains.annotations.Nullable;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Type;
+import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
+import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -43,6 +46,10 @@
*/
public class TaskUtil {
private static SimpleDateFormat ISO8601_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
+ static {
+ // Use UTC time zone by default (for formatting)
+ ISO8601_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
+ }
// Almost ISO-8601 strict except date parts may be separated by '/'
// and date only also allowed just in case
private static Pattern ISO8601_DATE_PATTERN = Pattern.compile(
@@ -50,6 +57,14 @@
"(?:[ T](\\d{2}:\\d{2}:\\d{2})(.\\d{3,})?" + // optional time and milliseconds
"([+-]\\d{2}:\\d{2}|[+-]\\d{4}|[+-]\\d{2}|Z)?)?");// optional timezone info
+ private static final JsonDeserializer<Date> DATE_DESERIALIZER = new JsonDeserializer<Date>() {
+ @Override
+ public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+ return parseDate(json.getAsString());
+ }
+ };
+
+
public static String formatTask(@NotNull Task task, String format) {
return format.replace("{id}", task.getId()).replace("{number}", task.getNumber())
.replace("{project}", task.getProject() == null ? "" : task.getProject()).replace("{summary}", task.getSummary());
@@ -112,8 +127,12 @@
}
}
+ public static String formatDate(@NotNull Date date) {
+ return ISO8601_DATE_FORMAT.format(date);
+ }
+
/**
- * {@link Task#equals(Object)} implementation compares tasks by they unique IDs only.
+ * {@link Task#equals(Object)} implementation compares tasks by their unique IDs only.
* This method should be used when full comparison is necessary.
*/
public static boolean tasksEqual(@NotNull Task t1, @NotNull Task t2) {
@@ -191,8 +210,32 @@
*/
public static void prettyFormatJsonToLog(@NotNull Logger logger, @NotNull String json) {
if (logger.isDebugEnabled()) {
- Gson gson = new GsonBuilder().setPrettyPrinting().create();
- logger.debug("\n" + gson.toJson(gson.fromJson(json, JsonElement.class)));
+ try {
+ Gson gson = new GsonBuilder().setPrettyPrinting().create();
+ logger.debug("\n" + gson.toJson(gson.fromJson(json, JsonElement.class)));
+ }
+ catch (JsonSyntaxException e) {
+ logger.debug("Malformed JSON\n" + json);
+ }
+ }
+ }
+
+ public static GsonBuilder installDateDeserializer(GsonBuilder builder) {
+ return builder.registerTypeAdapter(Date.class, DATE_DESERIALIZER);
+ }
+
+ /**
+ * Perform standard {@code application/x-www-urlencoded} translation for string {@code s}.
+ *
+ * @return urlencoded string
+ */
+ @NotNull
+ public static String encodeUrl(@NotNull String s) {
+ try {
+ return URLEncoder.encode(s, CharsetToolkit.UTF8);
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new AssertionError("UTF-8 is not supported");
}
}
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java
index 4270254..d070ff1 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRepository.java
@@ -1,13 +1,18 @@
package com.intellij.tasks.jira;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.tasks.LocalTask;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskState;
import com.intellij.tasks.impl.BaseRepositoryImpl;
+import com.intellij.tasks.impl.TaskUtil;
import com.intellij.tasks.jira.model.JiraIssue;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
@@ -28,9 +33,10 @@
@Tag("JIRA")
public class JiraRepository extends BaseRepositoryImpl {
+ public static final Gson GSON = TaskUtil.installDateDeserializer(new GsonBuilder()).create();
private final static Logger LOG = Logger.getInstance("#com.intellij.tasks.jira.JiraRepository");
public static final String LOGIN_FAILED_CHECK_YOUR_PERMISSIONS = "Login failed. Check your permissions.";
- public static final String REST_API_PATH_SUFFIX = "/rest/api/latest";
+ public static final String REST_API_PATH = "/rest/api/latest";
/**
* Default JQL query
@@ -105,7 +111,7 @@
@Nullable
@Override
public CancellableConnection createCancellableConnection() {
- String uri = getUrl() + REST_API_PATH_SUFFIX + "/search?maxResults=1&jql=" + encodeUrl(mySearchQuery);
+ String uri = getUrl() + REST_API_PATH + "/search?maxResults=1&jql=" + encodeUrl(mySearchQuery);
return new HttpTestConnection<GetMethod>(new GetMethod(uri)) {
@Override
public void doTest(GetMethod method) throws Exception {
@@ -135,16 +141,20 @@
public JiraRestApi discoverRestApiVersion() throws Exception {
String responseBody;
try {
- responseBody = executeMethod(new GetMethod(getUrl() + REST_API_PATH_SUFFIX + "/serverInfo"));
+ responseBody = executeMethod(new GetMethod(getRestUrl("serverInfo")));
}
catch (Exception e) {
LOG.warn("Can't find out JIRA REST API version");
throw e;
}
- JsonObject object = JiraUtil.GSON.fromJson(responseBody, JsonObject.class);
+ JsonObject object = GSON.fromJson(responseBody, JsonObject.class);
// when JIRA 4.x support will be dropped 'versionNumber' array in response
// may be used instead version string parsing
- return JiraRestApi.fromJiraVersion(object.get("version").getAsString(), this);
+ JiraRestApi version = JiraRestApi.fromJiraVersion(object.get("version").getAsString(), this);
+ if (version == null) {
+ throw new Exception("JIRA below 4.2.0 doesn't have REST API and is no longer supported.");
+ }
+ return version;
}
@Override
@@ -152,32 +162,37 @@
myRestApiVersion.setTaskState(task, state);
}
+ @Override
+ public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception {
+ myRestApiVersion.updateTimeSpend(task, timeSpent, comment);
+ }
+
@NotNull
- public String executeMethod(HttpMethod method) throws Exception {
- LOG.debug("URI is " + method.getURI());
+ public String executeMethod(@NotNull HttpMethod method) throws Exception {
+ LOG.debug("URI: " + method.getURI());
int statusCode;
String entityContent;
try {
statusCode = getHttpClient().executeMethod(method);
- LOG.debug("Status code is " + statusCode);
+ LOG.debug("Status code: " + statusCode);
// may be null if 204 No Content received
final InputStream stream = method.getResponseBodyAsStream();
- entityContent = stream == null ? "" : StreamUtil.readText(stream, "utf-8");
- LOG.debug(entityContent);
+ entityContent = stream == null ? "" : StreamUtil.readText(stream, CharsetToolkit.UTF8);
+ TaskUtil.prettyFormatJsonToLog(LOG, entityContent);
}
finally {
method.releaseConnection();
}
// besides SC_OK, can also be SC_NO_CONTENT in issue transition requests
// see: JiraRestApi#setTaskStatus
- if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
- //if (statusCode >= 200 && statusCode < 300) {
+ //if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
+ if (statusCode >= 200 && statusCode < 300) {
return entityContent;
}
else if (method.getResponseHeader("Content-Type") != null) {
Header header = method.getResponseHeader("Content-Type");
if (header.getValue().startsWith("application/json")) {
- JsonObject object = JiraUtil.GSON.fromJson(entityContent, JsonObject.class);
+ JsonObject object = GSON.fromJson(entityContent, JsonObject.class);
if (object.has("errorMessages")) {
String reason = StringUtil.join(object.getAsJsonArray("errorMessages"), " ");
// something meaningful to user, e.g. invalid field name in JQL query
@@ -196,7 +211,8 @@
if (statusCode == HttpStatus.SC_UNAUTHORIZED) {
throw new Exception(LOGIN_FAILED_CHECK_YOUR_PERMISSIONS);
}
- throw new Exception("Request failed with HTTP error: " + HttpStatus.getStatusText(method.getStatusCode()));
+ String statusText = HttpStatus.getStatusText(method.getStatusCode());
+ throw new Exception(String.format("Request failed with HTTP error: %d %s", statusCode, statusText));
}
@Override
@@ -204,4 +220,8 @@
myRestApiVersion = null;
super.setUrl(url);
}
-}
+
+ public String getRestUrl(String... parts) {
+ return getUrl() + REST_API_PATH + "/" + StringUtil.join(parts, "/");
+ }
+}
\ No newline at end of file
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRestApi.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRestApi.java
index c056128..7856fc4 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRestApi.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraRestApi.java
@@ -1,6 +1,8 @@
package com.intellij.tasks.jira;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.tasks.LocalTask;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskState;
import com.intellij.tasks.jira.model.JiraIssue;
@@ -9,14 +11,14 @@
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import java.io.UnsupportedEncodingException;
import java.util.List;
-import static com.intellij.tasks.jira.JiraRepository.REST_API_PATH_SUFFIX;
-
/**
* @author Mikhail Golubev
*/
@@ -26,14 +28,14 @@
public static JiraRestApi fromJiraVersion(@NotNull JiraVersion jiraVersion, @NotNull JiraRepository repository) {
LOG.debug("JIRA version is " + jiraVersion);
- if (jiraVersion.getMajorNumber() == 4) {
+ if (jiraVersion.getMajorNumber() == 4 && jiraVersion.getMinorNumber() >= 2) {
return new JiraRestApi20Alpha1(repository);
}
else if (jiraVersion.getMajorNumber() >= 5) {
return new JiraRestApi2(repository);
}
else {
- LOG.warn("JIRA below 4.0.0 doesn't support REST API (" + jiraVersion + " used)");
+ LOG.warn("JIRA below 4.2.0 doesn't support REST API (" + jiraVersion + " used)");
return null;
}
}
@@ -63,12 +65,12 @@
@NotNull
protected GetMethod getSingleIssueSearchMethod(String key) {
- return new GetMethod(myRepository.getUrl() + REST_API_PATH_SUFFIX + "/issue/" + key);
+ return new GetMethod(myRepository.getRestUrl("issue", key));
}
@NotNull
protected GetMethod getMultipleIssuesSearchMethod(String jql, int max) {
- GetMethod method = new GetMethod(myRepository.getUrl() + REST_API_PATH_SUFFIX + "/search");
+ GetMethod method = new GetMethod(myRepository.getRestUrl("search"));
method.setQueryString(new NameValuePair[]{
new NameValuePair("jql", jql),
new NameValuePair("maxResults", String.valueOf(max))
@@ -92,22 +94,26 @@
public void setTaskState(Task task, TaskState state) throws Exception {
String requestBody = getRequestForStateTransition(state);
+ LOG.debug(String.format("Transition: %s -> %s, request: %s", task.getState(), state, requestBody));
if (requestBody == null) {
return;
}
- final String transitionsUrl = myRepository.getUrl() + REST_API_PATH_SUFFIX + "/issue/" + task.getId() + "/transitions";
- LOG.debug(String.format("Transition destination: %s, request: %s", state, requestBody));
- final PostMethod method = new PostMethod(transitionsUrl);
- method.setRequestEntity(new StringRequestEntity(requestBody, "application/json", "utf-8"));
- try {
- myRepository.executeMethod(method);
- }
- catch (Exception e) {
- LOG.warn(String.format("Transition destination: %s, server URL: %s", state, myRepository.getUrl()), e);
- throw e;
- }
+ PostMethod method = new PostMethod(myRepository.getRestUrl("issue", task.getId(), "transitions"));
+ method.setRequestEntity(createJsonEntity(requestBody));
+ myRepository.executeMethod(method);
}
@Nullable
protected abstract String getRequestForStateTransition(@NotNull TaskState state);
+
+ public abstract void updateTimeSpend(LocalTask task, String timeSpent, String comment) throws Exception;
+
+ protected static RequestEntity createJsonEntity(String requestBody) {
+ try {
+ return new StringRequestEntity(requestBody, "application/json", CharsetToolkit.UTF8);
+ }
+ catch (UnsupportedEncodingException e) {
+ throw new AssertionError("UTF-8 encoding is not supported");
+ }
+ }
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java
deleted file mode 100644
index af300e0..0000000
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/JiraUtil.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.tasks.jira;
-
-import com.google.gson.*;
-import com.intellij.tasks.impl.TaskUtil;
-
-import java.lang.reflect.Type;
-import java.util.Date;
-
-/**
- * @author Mikhail Golubev
- */
-public class JiraUtil {
- public static final Gson GSON = buildGson();
-
- private static Gson buildGson() {
- GsonBuilder gson = new GsonBuilder();
- gson.registerTypeAdapter(Date.class, new DateDeserializer());
- return gson.create();
- }
-
- private static class DateDeserializer implements JsonDeserializer<Date> {
- @Override
- public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
- return TaskUtil.parseDate(json.getAsString());
- }
- }
-}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/JiraStatus.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/JiraStatus.java
index ab3935f..ee8a09d 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/JiraStatus.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/JiraStatus.java
@@ -17,14 +17,10 @@
import org.jetbrains.annotations.NotNull;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
/**
* @author Mikhail Golubev
*/
public class JiraStatus {
- private static final Pattern ID_PATTERN = Pattern.compile(".*/(\\d+)/?$");
private String id;
private String self;
private String name;
@@ -38,15 +34,14 @@
/**
* Status id is necessary to determine issue status regardless of the language
* used in JIRA installation. However it omitted in case of REST API version 2.0.alpha1.
- * Anyway it still may be extracted from status URL which always presents.
+ * Anyway it still may be extracted from status URL which is always available.
*/
@NotNull
public String getId() {
if (id == null) {
- Matcher m = ID_PATTERN.matcher(self);
- if (m.matches()) {
- return m.group(1);
- }
+ String[] parts = self.split("/");
+ assert parts.length > 0;
+ id = parts[parts.length - 1];
}
return id;
}
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api2/JiraRestApi2.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api2/JiraRestApi2.java
index a8a88ea..2e65882 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api2/JiraRestApi2.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api2/JiraRestApi2.java
@@ -2,13 +2,15 @@
import com.google.gson.reflect.TypeToken;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.tasks.LocalTask;
import com.intellij.tasks.TaskState;
import com.intellij.tasks.jira.JiraRepository;
import com.intellij.tasks.jira.JiraRestApi;
-import com.intellij.tasks.jira.JiraUtil;
import com.intellij.tasks.jira.model.JiraIssue;
import com.intellij.tasks.jira.model.JiraResponseWrapper;
import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.methods.PostMethod;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -41,7 +43,7 @@
@NotNull
@Override
protected List<JiraIssue> parseIssues(String response) {
- JiraResponseWrapper.Issues<JiraIssueApi2> wrapper = JiraUtil.GSON.fromJson(response, ISSUES_WRAPPER_TYPE);
+ JiraResponseWrapper.Issues<JiraIssueApi2> wrapper = JiraRepository.GSON.fromJson(response, ISSUES_WRAPPER_TYPE);
return new ArrayList<JiraIssue>(wrapper.getIssues());
}
@@ -57,7 +59,7 @@
@Nullable
@Override
protected JiraIssue parseIssue(String response) {
- return JiraUtil.GSON.fromJson(response, JiraIssueApi2.class);
+ return JiraRepository.GSON.fromJson(response, JiraIssueApi2.class);
}
@Nullable
@@ -77,6 +79,20 @@
}
}
+ @Override
+ public void updateTimeSpend(LocalTask task, String timeSpent, String comment) throws Exception {
+ LOG.debug(String.format("Time spend: %s, comment: %s", timeSpent, comment));
+ PostMethod method = new PostMethod(myRepository.getRestUrl("issue", task.getId(), "worklog"));
+ String request;
+ if (StringUtil.isEmpty(comment)) {
+ request = String.format("{\"timeSpent\" : \"" + timeSpent + "\"}", timeSpent);
+ } else {
+ request = String.format("{\"timeSpent\": \"%s\", \"comment\": \"%s\"}", timeSpent, StringUtil.escapeQuotes(comment));
+ }
+ method.setRequestEntity(createJsonEntity(request));
+ myRepository.executeMethod(method);
+ }
+
@NotNull
@Override
public String getVersionName() {
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api20alpha1/JiraRestApi20Alpha1.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api20alpha1/JiraRestApi20Alpha1.java
index df0ff53f..453147a 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api20alpha1/JiraRestApi20Alpha1.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/jira/model/api20alpha1/JiraRestApi20Alpha1.java
@@ -2,10 +2,10 @@
import com.google.gson.reflect.TypeToken;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.tasks.LocalTask;
import com.intellij.tasks.TaskState;
import com.intellij.tasks.jira.JiraRepository;
import com.intellij.tasks.jira.JiraRestApi;
-import com.intellij.tasks.jira.JiraUtil;
import com.intellij.tasks.jira.model.JiraIssue;
import com.intellij.tasks.jira.model.JiraResponseWrapper;
import org.jetbrains.annotations.NotNull;
@@ -29,13 +29,13 @@
@Override
protected JiraIssue parseIssue(String response) {
- return JiraUtil.GSON.fromJson(response, JiraIssueApi20Alpha1.class);
+ return JiraRepository.GSON.fromJson(response, JiraIssueApi20Alpha1.class);
}
@NotNull
@Override
protected List<JiraIssue> parseIssues(String response) {
- JiraResponseWrapper.Issues<JiraIssueApi20Alpha1> wrapper = JiraUtil.GSON.fromJson(response, ISSUES_WRAPPER_TYPE);
+ JiraResponseWrapper.Issues<JiraIssueApi20Alpha1> wrapper = JiraRepository.GSON.fromJson(response, ISSUES_WRAPPER_TYPE);
List<JiraIssueApi20Alpha1> incompleteIssues = wrapper.getIssues();
List<JiraIssue> updatedIssues = new ArrayList<JiraIssue>();
for (JiraIssueApi20Alpha1 issue : incompleteIssues) {
@@ -65,6 +65,11 @@
}
}
+ @Override
+ public void updateTimeSpend(LocalTask task, String timeSpent, String comment) throws Exception {
+ throw new Exception(String.format("This version of JIRA REST API (%s) doesn't support updating worklog items.", getVersionName()));
+ }
+
@NotNull
@Override
public String getVersionName() {
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java
index 4678b46..f01c46e 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java
@@ -244,7 +244,7 @@
private HttpMethod doREST(String request, boolean post) throws Exception {
final HttpClient client = getHttpClient();
client.getParams().setContentCharset("UTF-8");
- String uri = getUrl().replace("https://", EASY_HTTPS + "://") + request;
+ String uri = getUrl() + request;
HttpMethod method = post ? new PostMethod(uri) : new GetMethod(uri);
configureHttpMethod(method);
client.executeMethod(method);
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java
index 9389e8f..164af3e 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepositoryEditor.java
@@ -73,7 +73,7 @@
myURLText.setVisible(false);
myUsernameLabel.setVisible(false);
myUserNameText.setVisible(false);
- myPasswordLabel.setText("Token");
+ myPasswordLabel.setText("Token:");
//setAnchor(myPasswordText);
myPasswordText.getDocument().addDocumentListener(new DocumentAdapter() {
diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
index 413c9b8..c0299a7 100644
--- a/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
+++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/youtrack/YouTrackRepository.java
@@ -76,7 +76,7 @@
public Task[] getIssues(@Nullable String request, int max, long since) throws Exception {
String query = getDefaultSearch();
- if (request != null) {
+ if (StringUtil.isNotEmpty(request)) {
query += " " + request;
}
String requestUrl = "/rest/project/issues/?filter=" + encodeUrl(query) + "&max=" + max + "&updatedAfter" + since;
@@ -214,6 +214,7 @@
final Date updated = new Date(Long.parseLong(element.getAttributeValue("updated")));
final Date created = new Date(Long.parseLong(element.getAttributeValue("created")));
+ final boolean resolved = element.getAttribute("resolved") != null;
return new Task() {
@Override
@@ -274,7 +275,8 @@
@Override
public boolean isClosed() {
- return false;
+ // IDEA-118605
+ return resolved;
}
@Override
@@ -307,7 +309,7 @@
private static final Logger LOG = Logger.getInstance("#com.intellij.tasks.youtrack.YouTrackRepository");
@Override
- public void updateTimeSpent(final LocalTask task, final String timeSpent, final String comment) throws Exception {
+ public void updateTimeSpent(@NotNull LocalTask task, @NotNull String timeSpent, @NotNull String comment) throws Exception {
checkVersion();
final HttpMethod method = doREST("/rest/issue/execute/" + task.getId() + "?command=work+Today+" + timeSpent.replaceAll(" ", "+") + "+" + comment, true);
if (method.getStatusCode() != 200) {
diff --git a/plugins/tasks/tasks-core/src/icons/TasksIcons.java b/plugins/tasks/tasks-core/src/icons/TasksIcons.java
index 904cddb..64d63c1 100644
--- a/plugins/tasks/tasks-core/src/icons/TasksIcons.java
+++ b/plugins/tasks/tasks-core/src/icons/TasksIcons.java
@@ -37,6 +37,7 @@
public static final Icon Feature = load("/icons/feature.png"); // 16x16
public static final Icon Fogbugz = load("/icons/fogbugz.png"); // 16x16
public static final Icon Github = load("/icons/github.png"); // 16x16
+ public static final Icon Gitlab = load("/icons/gitlab.png"); // 16x16
public static final Icon Jira = load("/icons/jira.png"); // 16x16
public static final Icon Lighthouse = load("/icons/lighthouse.gif"); // 16x16
public static final Icon Mantis = load("/icons/mantis.png"); // 16x16
diff --git a/plugins/tasks/tasks-core/src/icons/gitlab.png b/plugins/tasks/tasks-core/src/icons/gitlab.png
new file mode 100644
index 0000000..c904236
--- /dev/null
+++ b/plugins/tasks/tasks-core/src/icons/gitlab.png
Binary files differ
diff --git a/plugins/tasks/tasks-core/tasks-core.iml b/plugins/tasks/tasks-core/tasks-core.iml
index 7094b91..9a1624e 100644
--- a/plugins/tasks/tasks-core/tasks-core.iml
+++ b/plugins/tasks/tasks-core/tasks-core.iml
@@ -61,6 +61,7 @@
<orderEntry type="module" module-name="xdebugger-api" />
<orderEntry type="module" module-name="xdebugger-impl" />
<orderEntry type="library" exported="" name="markdownj" level="project" />
+ <orderEntry type="library" name="http-client" level="project" />
</component>
</module>
diff --git a/plugins/tasks/tasks-tests/tasks-tests.iml b/plugins/tasks/tasks-tests/tasks-tests.iml
index deeddcc..327823a 100644
--- a/plugins/tasks/tasks-tests/tasks-tests.iml
+++ b/plugins/tasks/tasks-tests/tasks-tests.iml
@@ -18,6 +18,7 @@
<orderEntry type="module" module-name="xslt-debugger" />
<orderEntry type="module" module-name="xdebugger-impl" scope="TEST" />
<orderEntry type="module" module-name="git4idea" scope="TEST" />
+ <orderEntry type="library" name="gson" level="project" />
</component>
</module>
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
index a21e37c..3bce7ff 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/AssemblaIntegrationTest.java
@@ -74,7 +74,7 @@
Task[] tasks = myRepository.getActiveResponseHandler().parseIssues(TASK_LIST_RESPONSE, 50);
assertTasksEqual(
new Task[]{
- new TaskBuilder("50351983", "\u041F\u0440\u0438\u0432\u0435\u0442", myRepository)
+ new TaskBuilder("1", "\u041F\u0440\u0438\u0432\u0435\u0442", myRepository)
.withDescription("")
.withUpdated("2013-04-01T10:48:19+03:00")
.withCreated("2013-04-01T10:45:06+03:00")
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java
index fc5ed55..5eca626 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/JiraIntegrationTest.java
@@ -15,14 +15,23 @@
*/
package com.intellij.tasks.integration;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
import com.intellij.tasks.Task;
import com.intellij.tasks.TaskManagerTestCase;
import com.intellij.tasks.TaskState;
+import com.intellij.tasks.config.TaskSettings;
+import com.intellij.tasks.impl.LocalTaskImpl;
+import com.intellij.tasks.impl.TaskUtil;
import com.intellij.tasks.jira.JiraRepository;
import com.intellij.tasks.jira.JiraRepositoryType;
import com.intellij.tasks.jira.JiraVersion;
+import org.apache.commons.httpclient.methods.GetMethod;
import org.jetbrains.annotations.NonNls;
+import java.util.Date;
+
/**
* @author Dmitry Avdeev
* Date: 1/15/13
@@ -89,32 +98,51 @@
changeStateAndCheck(JIRA_5_TEST_SERVER_URL, "UT-8");
}
- @SuppressWarnings("ConstantConditions")
+ public void testSetTimeSpend() throws Exception {
+ // only REST API 2.0 supports this feature
+ myRepository.setUrl(JIRA_5_TEST_SERVER_URL);
+ Task task = myRepository.findTask("UT-9");
+ assertNotNull("Test task not found", task);
+
+ // timestamp as comment
+ String comment = "Timestamp: " + TaskUtil.formatDate(new Date());
+
+ // semi-unique duration as timeSpend
+ // should be no longer than 8 hours in total, because it's considered as one full day
+ int minutes = (int)(System.currentTimeMillis() % 240) + 1;
+ String duration = String.format("%dh %dm", minutes / 60, minutes % 60);
+ myRepository.updateTimeSpent(new LocalTaskImpl(task), duration, comment);
+
+ // possible race conditions?
+ GetMethod request = new GetMethod(myRepository.getRestUrl("issue", task.getId(), "worklog"));
+ String response = myRepository.executeMethod(request);
+ JsonObject object = new Gson().fromJson(response, JsonObject.class);
+ JsonArray worklogs = object.get("worklogs").getAsJsonArray();
+ JsonObject last = worklogs.get(worklogs.size() - 1).getAsJsonObject();
+
+ assertEquals(comment, last.get("comment").getAsString());
+ // don't depend on concrete response format: zero hours stripping, zero padding and so on
+ assertEquals(minutes * 60, last.get("timeSpentSeconds").getAsInt());
+ }
+
private void changeStateAndCheck(String url, String key) throws Exception {
myRepository.setUrl(url);
Task task = myRepository.findTask(key);
+ assertNotNull("Test task not found", task);
+ assertEquals(String.format("Initial state of test task '%s' should be 'Reopened'", key),
+ TaskState.REOPENED, task.getState());
try {
- myRepository.setTaskState(task, TaskState.IN_PROGRESS);
- assertEquals(myRepository.findTask(key).getState(), TaskState.IN_PROGRESS);
myRepository.setTaskState(task, TaskState.RESOLVED);
- assertEquals(myRepository.findTask(key).getState(), TaskState.RESOLVED);
- myRepository.setTaskState(task, TaskState.REOPENED);
- assertEquals(myRepository.findTask(key).getState(), TaskState.REOPENED);
- }
- catch (Exception e) {
- // always attempt to restore original state of the issue
+ task = myRepository.findTask(key);
+ assertEquals(task.getState(), TaskState.RESOLVED);
+ } finally {
try {
- // transition to Resolved state usually is possible from any other
- myRepository.setTaskState(task, TaskState.RESOLVED);
- }
- catch (Exception ignored) {
- }
- try {
+ // always attempt to restore original state of the issue
myRepository.setTaskState(task, TaskState.REOPENED);
}
catch (Exception ignored) {
+ // empty
}
- throw e;
}
}
@@ -122,12 +150,12 @@
assertEquals(new JiraVersion("6.1-OD-09-WN").toString(), "6.1.9");
assertEquals(new JiraVersion("5.0.6").toString(), "5.0.6");
assertEquals(new JiraVersion("4.4.5").toString(), "4.4.5");
-
}
@Override
public void setUp() throws Exception {
super.setUp();
+ TaskSettings.getInstance().CONNECTION_TIMEOUT = 10000;
myRepository = new JiraRepository(new JiraRepositoryType());
myRepository.setUrl(JIRA_5_TEST_SERVER_URL);
myRepository.setUsername("buildtest");
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java
index 36cc584..dab5b99 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskBranchesTest.java
@@ -69,7 +69,7 @@
assertEquals(2, repository.getBranches().getLocalBranches().size());
assertEquals(first, repository.getCurrentBranch().getName());
- handler.switchToTask(defaultInfo);
+ handler.switchToTask(defaultInfo, null);
assertEquals("master", repository.getCurrentBranch().getName());
final String second = "second";
diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskVcsTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskVcsTest.java
index 428521d..d78c5c0 100644
--- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskVcsTest.java
+++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/vcs/TaskVcsTest.java
@@ -107,6 +107,7 @@
assertEquals(anotherChangeList.getName(), LocalChangeList.DEFAULT_NAME);
myTaskManager.activateTask(defaultTask, false);
+ myChangeListManager.waitUntilRefreshed();
assertEquals(1, localTask.getChangeLists().size());
assertEquals(1, defaultTask.getChangeLists().size());
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
index 259d93c..0c34444 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalPanel.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.
@@ -44,7 +44,6 @@
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
-import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
@@ -74,7 +73,7 @@
registerKeymapActions(this);
addFocusListener(this);
-
+
mySettingsProvider.addListener(this);
}
@@ -170,11 +169,7 @@
@Override
protected String getClipboardContent() throws IOException, UnsupportedFlavorException {
- Transferable contents = CopyPasteManager.getInstance().getContents();
- if (contents == null) {
- return null;
- }
- return (String)contents.getTransferData(DataFlavor.stringFlavor);
+ return CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
}
@Override
@@ -185,7 +180,7 @@
@Override
public void focusGained(FocusEvent event) {
- if (GeneralSettings.getInstance().isAutoSaveIfInactive()) {
+ if (GeneralSettings.getInstance().isSaveOnFrameDeactivation()) {
FileDocumentManager.getInstance().saveAllDocuments();
}
}
diff --git a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java
index 94479c9..1578b04 100644
--- a/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java
+++ b/plugins/terminal/src/org/jetbrains/plugins/terminal/JBTerminalSystemSettingsProvider.java
@@ -100,7 +100,7 @@
@Override
public boolean shouldCloseTabOnLogout(TtyConnector ttyConnector) {
- return ttyConnector instanceof PtyProcessTtyConnector; //close tab only on logout of local pty, not remote
+ return TerminalOptionsProvider.getInstance().closeSessionOnLogout();
}
@Override
diff --git a/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java b/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java
index b7fdb70..f23e4f4 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/TestNGFramework.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,6 @@
import com.intellij.codeInsight.intention.AddAnnotationFix;
import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
@@ -103,16 +102,16 @@
PsiMethod inClass = clazz.findMethodBySignature(patternMethod, false);
if (inClass != null) {
int exit = ApplicationManager.getApplication().isUnitTestMode() ?
- DialogWrapper.OK_EXIT_CODE :
- Messages.showYesNoDialog("Method \'" + setUpName + "\' already exist but is not annotated as @BeforeMethod.",
+ Messages.YES :
+ Messages.showYesNoDialog(manager.getProject(), "Method \'" + setUpName + "\' already exist but is not annotated as @BeforeMethod.",
CommonBundle.getWarningTitle(),
"Annotate",
"Create new method",
Messages.getWarningIcon());
- if (exit == DialogWrapper.OK_EXIT_CODE) {
+ if (exit == Messages.YES) {
new AddAnnotationFix(BeforeMethod.class.getName(), inClass).invoke(inClass.getProject(), null, inClass.getContainingFile());
return inClass;
- } else if (exit == DialogWrapper.CANCEL_EXIT_CODE) {
+ } else if (exit == Messages.NO) {
inClass = null;
int i = 0;
while (clazz.findMethodBySignature(patternMethod, false) != null) {
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java
index 524d311..551bf34 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGConfigurationEditor.java
@@ -110,7 +110,7 @@
private JPanel myListenersPanel;
TextFieldWithBrowseButton myPatternTextField;
private final CommonJavaParametersPanel commonJavaParameters = new CommonJavaParametersPanel();
- private ArrayList<Map.Entry> propertiesList;
+ private final ArrayList<Map.Entry> propertiesList = new ArrayList<Map.Entry>();
private TestNGListenersTableModel listenerModel;
private TestNGConfiguration config;
@@ -200,6 +200,7 @@
else if (field instanceof EditorTextFieldWithBrowseButton) {
final com.intellij.openapi.editor.Document componentDocument =
((EditorTextFieldWithBrowseButton)field).getChildComponent().getDocument();
+
model.setDocument(i, componentDocument);
}
else {
@@ -303,7 +304,7 @@
packagesInProject.setSelected(true);
}
alternateJDK.init(config.ALTERNATIVE_JRE_PATH, config.ALTERNATIVE_JRE_PATH_ENABLED);
- propertiesList = new ArrayList<Map.Entry>();
+ propertiesList.clear();
propertiesList.addAll(data.TEST_PROPERTIES.entrySet());
propertiesTableModel.setParameterList(propertiesList);
diff --git a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
index ff5adf1..a438177 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/configuration/TestNGPatternConfigurationProducer.java
@@ -27,6 +27,7 @@
import com.intellij.execution.actions.ConfigurationContext;
import com.intellij.execution.configurations.ModuleBasedConfiguration;
import com.intellij.execution.junit.JUnitUtil;
+import com.intellij.execution.junit2.info.MethodLocation;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
@@ -41,6 +42,7 @@
import com.theoryinpractice.testng.util.TestNGUtil;
import org.jetbrains.annotations.NotNull;
+import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@@ -88,14 +90,20 @@
private static PsiElement[] collectPatternElements(ConfigurationContext context, LinkedHashSet<String> classes) {
final DataContext dataContext = context.getDataContext();
+ final Location<?>[] locations = Location.DATA_KEYS.getData(dataContext);
+ if (locations != null) {
+ List<PsiElement> elements = new ArrayList<PsiElement>();
+ for (Location<?> location : locations) {
+ final PsiElement psiElement = location.getPsiElement();
+ classes.add(getQName(psiElement, location));
+ elements.add(psiElement);
+ }
+ return elements.toArray(new PsiElement[elements.size()]);
+ }
PsiElement[] elements = LangDataKeys.PSI_ELEMENT_ARRAY.getData(dataContext);
if (elements != null) {
for (PsiMember psiMember : collectTestMembers(elements)) {
- if (psiMember instanceof PsiClass) {
- classes.add(((PsiClass)psiMember).getQualifiedName());
- } else {
- classes.add(psiMember.getContainingClass().getQualifiedName() + "," + psiMember.getName());
- }
+ classes.add(getQName(psiMember, null));
}
return elements;
} else {
@@ -110,6 +118,22 @@
return null;
}
+ public static String getQName(PsiElement psiMember, Location location) {
+ if (psiMember instanceof PsiClass) {
+ return ((PsiClass)psiMember).getQualifiedName();
+ }
+ else if (psiMember instanceof PsiMember) {
+ final PsiClass containingClass = location instanceof MethodLocation
+ ? ((MethodLocation)location).getContainingClass(): ((PsiMember)psiMember).getContainingClass();
+ assert containingClass != null;
+ return containingClass.getQualifiedName() + "," + ((PsiMember)psiMember).getName();
+ } else if (psiMember instanceof PsiPackage) {
+ return ((PsiPackage)psiMember).getQualifiedName();
+ }
+ assert false;
+ return null;
+ }
+
@Override
protected Module findModule(TestNGConfiguration configuration, Module contextModule) {
final Set<String> patterns = configuration.data.getPatterns();
diff --git a/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java b/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java
index 35aa88a..16bd5dd 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/inspection/DependsOnGroupsInspection.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.
@@ -48,7 +48,7 @@
private static final Pattern PATTERN = Pattern.compile("\"([a-zA-Z0-9_\\-\\(\\)]*)\"");
public JDOMExternalizableStringList groups = new JDOMExternalizableStringList();
- @NonNls public static String SHORT_NAME = "groupsTestNG";
+ @NonNls public static final String SHORT_NAME = "groupsTestNG";
@NotNull
@Override
@@ -114,7 +114,7 @@
if (dep != null) {
final PsiAnnotationMemberValue value = dep.getValue();
if (value != null) {
- LOGGER.info("Found " + dep.getName() + " with: " + value.getText());
+ LOGGER.debug("Found " + dep.getName() + " with: " + value.getText());
String text = value.getText();
if (value instanceof PsiReferenceExpression) {
final PsiElement resolve = ((PsiReferenceExpression)value).resolve();
@@ -131,7 +131,7 @@
while (matcher.find()) {
String methodName = matcher.group(1);
if (!groups.contains(methodName)) {
- LOGGER.info("group doesn't exist:" + methodName);
+ LOGGER.debug("group doesn't exist:" + methodName);
ProblemDescriptor descriptor = manager.createProblemDescriptor(annotation, "Group '" + methodName + "' is undefined.",
new GroupNameQuickFix(methodName),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
diff --git a/plugins/testng/src/com/theoryinpractice/testng/inspection/MisorderedAssertEqualsArgumentsTestNGInspection.java b/plugins/testng/src/com/theoryinpractice/testng/inspection/MisorderedAssertEqualsArgumentsTestNGInspection.java
index 1304646..e683e7c 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/inspection/MisorderedAssertEqualsArgumentsTestNGInspection.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/inspection/MisorderedAssertEqualsArgumentsTestNGInspection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -15,195 +15,15 @@
*/
package com.theoryinpractice.testng.inspection;
-import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
-import com.intellij.codeInspection.LocalQuickFix;
-import com.intellij.codeInspection.ProblemDescriptor;
-import com.intellij.codeInspection.ProblemsHolder;
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.*;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.InheritanceUtil;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
+import com.siyeh.ig.junit.MisorderedAssertEqualsArgumentsInspectionBase;
/**
* @author Bas Leijdekkers
*/
-public class MisorderedAssertEqualsArgumentsTestNGInspection extends BaseJavaLocalInspectionTool {
+public class MisorderedAssertEqualsArgumentsTestNGInspection extends MisorderedAssertEqualsArgumentsInspectionBase {
- private static class FlipParametersFix implements LocalQuickFix {
-
- @Override
- @NotNull
- public String getName() {
- return "Flip compared arguments";
- }
-
- @NotNull
- @Override
- public String getFamilyName() {
- return getName();
- }
-
- @Override
- public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
- final PsiElement methodNameIdentifier = descriptor.getPsiElement();
- final PsiElement parent = methodNameIdentifier.getParent();
- if (parent == null) {
- return;
- }
- final PsiMethodCallExpression callExpression = (PsiMethodCallExpression)parent.getParent();
- if (callExpression == null) {
- return;
- }
- final PsiReferenceExpression methodExpression = callExpression.getMethodExpression();
- final PsiMethod method = (PsiMethod)methodExpression.resolve();
- if (method == null) {
- return;
- }
- final PsiClass containingClass = method.getContainingClass();
- final boolean junit;
- if (InheritanceUtil.isInheritor(containingClass, "org.testng.Assert")) {
- junit = false;
- }
- else if (InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit")) {
- junit = true;
- }
- else {
- return;
- }
- final PsiParameterList parameterList = method.getParameterList();
- final PsiParameter[] parameters = parameterList.getParameters();
- final PsiManager psiManager = callExpression.getManager();
- final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
- final PsiType stringType = PsiType.getJavaLangString(psiManager, scope);
- final PsiType parameterType1 = parameters[0].getType();
- final PsiExpressionList argumentList = callExpression.getArgumentList();
- final PsiExpression[] arguments = argumentList.getExpressions();
- final PsiExpression expectedArgument;
- final PsiExpression actualArgument;
- if (junit) {
- if (parameterType1.equals(stringType) && parameters.length > 2) {
- expectedArgument = arguments[1];
- actualArgument = arguments[2];
- }
- else {
- expectedArgument = arguments[0];
- actualArgument = arguments[1];
- }
- }
- else {
- actualArgument = arguments[0];
- expectedArgument = arguments[1];
- }
- final PsiElement copy = expectedArgument.copy();
- expectedArgument.replace(actualArgument);
- actualArgument.replace(copy);
- }
- }
-
- @NotNull
@Override
- public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
- return new MisorderedAssertEqualsParametersVisitor(holder);
- }
-
- private static class MisorderedAssertEqualsParametersVisitor extends JavaElementVisitor {
-
- private final ProblemsHolder myProblemsHolder;
-
- public MisorderedAssertEqualsParametersVisitor(ProblemsHolder problemsHolder) {
- myProblemsHolder = problemsHolder;
- }
-
- @Override
- public void visitMethodCallExpression(@NotNull PsiMethodCallExpression expression) {
- super.visitMethodCallExpression(expression);
- final PsiReferenceExpression methodExpression = expression.getMethodExpression();
- @NonNls final String methodName = methodExpression.getReferenceName();
- if (!"assertEquals".equals(methodName) && !"assertEqualsNoOrder".equals(methodName) &&
- !"assertNotEquals".equals(methodName) && !"assertArrayEquals".equals(methodName)) {
- return;
- }
- final PsiMethod method = expression.resolveMethod();
- if (method == null) {
- return;
- }
- final PsiManager manager = expression.getManager();
- final Project project = manager.getProject();
- final GlobalSearchScope scope = GlobalSearchScope.allScope(project);
- final PsiType stringType = PsiType.getJavaLangString(manager, scope);
- final PsiExpressionList argumentList = expression.getArgumentList();
- final PsiExpression[] arguments = argumentList.getExpressions();
- if (arguments.length < 2) {
- return;
- }
- final PsiClass containingClass = method.getContainingClass();
- final PsiExpression expectedArgument;
- final PsiExpression actualArgument;
- if (InheritanceUtil.isInheritor(containingClass, "org.testng.AssertJUnit")) {
- final PsiType firstArgumentType = arguments[0].getType();
- if (stringType.equals(firstArgumentType) && arguments.length > 2) {
- expectedArgument = arguments[1];
- actualArgument = arguments[2];
- }
- else {
- expectedArgument = arguments[0];
- actualArgument = arguments[1];
- }
- } else if (InheritanceUtil.isInheritor(containingClass, "org.testng.Assert")){
- actualArgument = arguments[0];
- expectedArgument = arguments[1];
- } else {
- return;
- }
- if (expectedArgument == null || actualArgument == null) {
- return;
- }
- if (isLiteralOrConstant(expectedArgument)) {
- return;
- }
- if (!isLiteralOrConstant(actualArgument)) {
- return;
- }
- final PsiElement referenceNameElement = methodExpression.getReferenceNameElement();
- if (referenceNameElement != null) {
- myProblemsHolder.registerProblem(referenceNameElement, "Arguments to <code>#ref()</code> in wrong order #loc",
- new FlipParametersFix());
- }
- else {
- myProblemsHolder.registerProblem(methodExpression, "Arguments to <code>#ref()</code> in wrong order #loc",
- new FlipParametersFix());
- }
- }
-
- private static boolean isLiteralOrConstant(PsiExpression expression) {
- if (expression instanceof PsiLiteralExpression) {
- return true;
- }
- else if (expression instanceof PsiNewExpression) {
- final PsiNewExpression newExpression = (PsiNewExpression)expression;
- final PsiExpressionList argumentList = newExpression.getArgumentList();
- if (argumentList == null) {
- return true;
- }
- for (PsiExpression argument : argumentList.getExpressions()) {
- if (!isLiteralOrConstant(argument)) {
- return false;
- }
- }
- return true;
- }
- if (!(expression instanceof PsiReferenceExpression)) {
- return false;
- }
- final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
- final PsiElement target = referenceExpression.resolve();
- if (!(target instanceof PsiField)) {
- return false;
- }
- final PsiField field = (PsiField)target;
- return field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL);
- }
+ public boolean checkTestNG() {
+ return true;
}
}
\ No newline at end of file
diff --git a/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java b/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java
index 36395bc..784da48 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/inspection/TestNGEntryPoint.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.
@@ -48,12 +48,12 @@
return "Automatically add all TestNG classes/methods/etc. to entry points";
}
- public boolean isEntryPoint(RefElement refElement, PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull RefElement refElement, @NotNull PsiElement psiElement) {
return isEntryPoint(psiElement);
}
@Override
- public boolean isEntryPoint(PsiElement psiElement) {
+ public boolean isEntryPoint(@NotNull PsiElement psiElement) {
if (ADD_TESTNG_TO_ENTRIES) {
if (psiElement instanceof PsiModifierListOwner) {
if (TestNGUtil.hasTest((PsiModifierListOwner)psiElement, false, false, TestNGUtil.hasDocTagsSupport)) return true;
diff --git a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGConfigurationModel.java b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGConfigurationModel.java
index e891db65..53f403a 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/model/TestNGConfigurationModel.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/model/TestNGConfigurationModel.java
@@ -18,6 +18,7 @@
import com.intellij.execution.JavaExecutionUtil;
import com.intellij.execution.junit.JUnitUtil;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
@@ -204,9 +205,10 @@
throw new RuntimeException(e);
}
} else {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(project, new Runnable() {
public void run() {
- ((com.intellij.openapi.editor.Document)document).replaceString(0, ((com.intellij.openapi.editor.Document)document).getTextLength(), value);
+ ((com.intellij.openapi.editor.Document)document)
+ .replaceString(0, ((com.intellij.openapi.editor.Document)document).getTextLength(), value);
}
});
}
diff --git a/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java b/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java
index 7958cc3..2f77911 100644
--- a/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java
+++ b/plugins/testng/src/com/theoryinpractice/testng/util/TestNGUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,7 +25,6 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.libraries.JarVersionDetectionUtil;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.vfs.*;
@@ -478,7 +477,7 @@
if (JavaPsiFacade.getInstance(manager.getProject()).findClass(TestNG.class.getName(), psiElement.getResolveScope()) == null) {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
if (Messages.showOkCancelDialog(psiElement.getProject(), "TestNG will be added to module classpath", "Unable to convert.", Messages.getWarningIcon()) !=
- DialogWrapper.OK_EXIT_CODE) {
+ Messages.OK) {
return false;
}
}
diff --git a/plugins/testng/src/inspectionDescriptions/MisorderedAssertEqualsArgumentsTestNG.html b/plugins/testng/src/inspectionDescriptions/MisorderedAssertEqualsArgumentsTestNG.html
index 06e6d3f..484099e 100644
--- a/plugins/testng/src/inspectionDescriptions/MisorderedAssertEqualsArgumentsTestNG.html
+++ b/plugins/testng/src/inspectionDescriptions/MisorderedAssertEqualsArgumentsTestNG.html
@@ -6,6 +6,6 @@
arguments differ.
<!-- tooltip end -->
<p>
- <small>New in 12, Powered TestNG-J</small>
+ <small>New in 12, Powered by TestNG-J</small>
</body>
</html>
\ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/DesignerBundle.java b/plugins/ui-designer-core/src/com/intellij/designer/DesignerBundle.java
index fe7f687..18f6319 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/DesignerBundle.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/DesignerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,22 +28,19 @@
* @author yole
*/
public class DesignerBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.DesignerBundle";
private DesignerBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) {
- bundle = ourBundle.get();
- }
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java
index 04021bd..6361ac2 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/CommonEditActionsProvider.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.
@@ -40,7 +40,6 @@
import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
import java.util.List;
import java.util.Map;
@@ -50,6 +49,8 @@
public class CommonEditActionsProvider implements DeleteProvider, CopyProvider, PasteProvider, CutProvider {
private static final DataFlavor DATA_FLAVOR = FileCopyPasteUtil.createJvmDataFlavor(SerializedComponentData.class);
+ public static boolean isDeleting;
+
private final DesignerEditorPanel myDesigner;
public CommonEditActionsProvider(DesignerEditorPanel designer) {
@@ -141,12 +142,19 @@
}
public static void updateSelectionBeforeDelete(EditableArea area, RadComponent component, List<RadComponent> excludes) {
- RadComponent newSelection = getNewSelection(component, excludes);
- if (newSelection == null) {
- area.deselectAll();
+ try {
+ isDeleting = true;
+
+ RadComponent newSelection = getNewSelection(component, excludes);
+ if (newSelection == null) {
+ area.deselectAll();
+ }
+ else {
+ area.select(newSelection);
+ }
}
- else {
- area.select(newSelection);
+ finally {
+ isDeleting = false;
}
}
@@ -251,17 +259,7 @@
@Nullable
private String getSerializedComponentData() {
try {
- CopyPasteManager copyPasteManager = CopyPasteManager.getInstance();
- if (!copyPasteManager.isDataFlavorAvailable(DATA_FLAVOR)) {
- return null;
- }
-
- Transferable content = copyPasteManager.getContents();
- if (content == null) {
- return null;
- }
-
- Object transferData = content.getTransferData(DATA_FLAVOR);
+ Object transferData = CopyPasteManager.getInstance().getContents(DATA_FLAVOR);
if (transferData instanceof SerializedComponentData) {
SerializedComponentData data = (SerializedComponentData)transferData;
String xmlComponents = data.getSerializedComponents();
@@ -270,8 +268,7 @@
}
}
}
- catch (Throwable e) {
- }
+ catch (Throwable ignored) { }
return null;
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java
index 825a443..526c2b6 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/DesignerActionPanel.java
@@ -116,7 +116,7 @@
AnAction selectSameType = new SelectSameTypeAction(area);
AnAction deselectAllAction = new DeselectAllAction(area);
- SelectAllAction selectAllAction = new SelectAllAction(area);
+ AnAction selectAllAction = createSelectAllAction(area);
registerAction(selectAllAction, "$SelectAll");
group.add(selectParent);
@@ -129,6 +129,10 @@
return group;
}
+ public AnAction createSelectAllAction(EditableArea area) {
+ return new SelectAllAction(area);
+ }
+
public static StartInplaceEditing createInplaceEditingAction(JComponent shortcuts) {
StartInplaceEditing action = new StartInplaceEditing();
action.registerCustomShortcutSet(new CustomShortcutSet(KeyStroke.getKeyStroke(KeyEvent.VK_F2, 0)), shortcuts);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java
index eb915b1..fc7e4f3 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/actions/SelectAllAction.java
@@ -28,7 +28,7 @@
* @author Alexander Lobas
*/
public class SelectAllAction extends AnAction {
- private final EditableArea myArea;
+ protected final EditableArea myArea;
public SelectAllAction(EditableArea area) {
super("Select All", "Select All", null);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/AttributeWrapper.java b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/AttributeWrapper.java
index 7214a6d..34bb3aa 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/AttributeWrapper.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/AttributeWrapper.java
@@ -28,5 +28,12 @@
}
};
+ AttributeWrapper REGULAR = new AttributeWrapper() {
+ @Override
+ public SimpleTextAttributes getAttribute(SimpleTextAttributes attributes) {
+ return SimpleTextAttributes.REGULAR_ATTRIBUTES;
+ }
+ };
+
SimpleTextAttributes getAttribute(SimpleTextAttributes attributes);
}
\ No newline at end of file
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTree.java b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTree.java
index f7735c5..c128c81 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTree.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/ComponentTree.java
@@ -39,10 +39,12 @@
import javax.swing.*;
import javax.swing.border.LineBorder;
+import javax.swing.plaf.TreeUI;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import java.awt.*;
+import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.util.List;
@@ -75,6 +77,19 @@
myInplaceEditingAction = DesignerActionPanel.createInplaceEditingAction(this);
}
+ @Override
+ public void setUI(TreeUI ui) {
+ super.setUI(ui);
+ getActionMap().put("selectAll", new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (myDesigner != null) {
+ myDesigner.getActionPanel().createSelectAllAction(myDesigner.getSurfaceArea()).actionPerformed(null);
+ }
+ }
+ });
+ }
+
public void newModel() {
setModel(new DefaultTreeModel(new DefaultMutableTreeNode()));
}
@@ -173,7 +188,8 @@
if (level != null) {
TextAttributesKey attributesKey =
- SeverityRegistrar.getSeverityRegistrar(myDesigner.getProject()).getHighlightInfoTypeBySeverity(level.getSeverity()).getAttributesKey();
+ SeverityRegistrar.getSeverityRegistrar(myDesigner.getProject()).getHighlightInfoTypeBySeverity(level.getSeverity())
+ .getAttributesKey();
final TextAttributes textAttributes = EditorColorsManager.getInstance().getGlobalScheme().getAttributes(attributesKey);
wrapper = new AttributeWrapper() {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditOperation.java b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditOperation.java
index b624831..8faa068 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditOperation.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditOperation.java
@@ -76,7 +76,7 @@
@Override
public void eraseFeedback() {
- myContext.getArea().getFeedbackTreeLayer().mark(null, FeedbackTreeLayer.INSERT_AFTER);
+ myContext.getArea().getFeedbackTreeLayer().unmark();
}
@Override
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditableArea.java b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditableArea.java
index bce7b2f..4e51ab5 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditableArea.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/componentTree/TreeEditableArea.java
@@ -179,7 +179,7 @@
myCanvasSelection = canvasSelection;
}
-//////////////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////////////////
//
// Visual
//
@@ -297,6 +297,11 @@
}
@Override
+ public void unmark() {
+ myTree.mark(null, -1);
+ }
+
+ @Override
public boolean isBeforeLocation(RadComponent component, int x, int y) {
Rectangle bounds = myTree.getPathBounds(getPath(component));
return bounds != null && y - bounds.y < myTree.getEdgeSize();
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
index dc12a18..235cdf2 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
@@ -17,6 +17,7 @@
import com.intellij.designer.*;
import com.intellij.designer.actions.AbstractComboBoxAction;
+import com.intellij.designer.actions.CommonEditActionsProvider;
import com.intellij.designer.actions.DesignerActionPanel;
import com.intellij.designer.componentTree.TreeComponentDecorator;
import com.intellij.designer.componentTree.TreeEditableArea;
@@ -33,6 +34,7 @@
import com.intellij.icons.AllIcons;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Attachment;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
@@ -129,7 +131,7 @@
private FixableMessageAction myWarnAction;
private JPanel myErrorPanel;
- private JPanel myErrorMessages;
+ protected JPanel myErrorMessages;
private JPanel myErrorStackPanel;
private CardLayout myErrorStackLayout;
private JTextArea myErrorStack;
@@ -344,10 +346,14 @@
if (info.myShowLog) {
LOG.error(LogMessageEx.createEvent(info.myDisplayMessage,
info.myMessage + "\n" + ExceptionUtil.getThrowableText(info.myThrowable),
- AttachmentFactory.createAttachment(myFile)));
+ getErrorAttachments(info)));
}
}
+ protected Attachment[] getErrorAttachments(ErrorInfo info) {
+ return new Attachment[]{AttachmentFactory.createAttachment(myFile)};
+ }
+
protected abstract void configureError(final @NotNull ErrorInfo info);
protected void showErrorPage(final ErrorInfo info) {
@@ -380,7 +386,7 @@
repaint();
}
- private void addErrorMessage(final FixableMessageInfo message, Icon icon) {
+ protected void addErrorMessage(final FixableMessageInfo message, Icon icon) {
if (message.myLinkText.length() > 0 || message.myAfterLinkText.length() > 0) {
HyperlinkLabel warnLabel = new HyperlinkLabel();
warnLabel.setOpaque(false);
@@ -499,6 +505,10 @@
return myEditor;
}
+ public VirtualFile getFile() {
+ return myFile;
+ }
+
@Override
public final Project getProject() {
return myProject;
@@ -574,7 +584,9 @@
}
private void storeSourceSelectionState() {
- mySourceSelectionState.put(getEditorText(), getSelectionState());
+ if (!CommonEditActionsProvider.isDeleting) {
+ mySourceSelectionState.put(getEditorText(), getSelectionState());
+ }
}
private int[][] getSelectionState() {
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/FeedbackTreeLayer.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/FeedbackTreeLayer.java
index ed7dc86..84598fc 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/FeedbackTreeLayer.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/FeedbackTreeLayer.java
@@ -27,6 +27,8 @@
void mark(RadComponent component, int feedback);
+ void unmark();
+
boolean isBeforeLocation(RadComponent component, int x, int y);
boolean isAfterLocation(RadComponent component, int x, int y);
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java
index b3a423d..f2e7d9a 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/OperationContext.java
@@ -34,6 +34,7 @@
private Object myType;
private EditableArea myArea;
+ private RadComponent myContainer;
private List<RadComponent> myComponents;
private InputEvent myInputEvent;
private int myModifiers;
@@ -102,6 +103,14 @@
myArea = area;
}
+ public RadComponent getContainer() {
+ return myContainer;
+ }
+
+ public void setContainer(RadComponent container) {
+ myContainer = container;
+ }
+
public List<RadComponent> getComponents() {
return myComponents;
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java
index 2da90b4..27e8593 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/selection/NonResizeSelectionDecorator.java
@@ -27,7 +27,7 @@
* @author Alexander Lobas
*/
public class NonResizeSelectionDecorator extends ComponentDecorator {
- private final Color myColor;
+ protected final Color myColor;
private final int myLineWidth;
private final BasicStroke myStroke;
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java
index f66b5b0..900fe27 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/designSurface/tools/TargetingTool.java
@@ -155,7 +155,9 @@
RadLayout layout = target.getLayout();
if (layout != null) {
+ myContext.setContainer(target);
myOperation = layout.processChildOperation(myContext);
+ myContext.setContainer(null);
}
return myOperation != null;
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/inspection/AbstractQuickFixManager.java b/plugins/ui-designer-core/src/com/intellij/designer/inspection/AbstractQuickFixManager.java
index bf8e071..7692d54 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/inspection/AbstractQuickFixManager.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/inspection/AbstractQuickFixManager.java
@@ -377,7 +377,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent event, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent event, int clickCount) {
showPopup();
return true;
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteGroupComponent.java b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteGroupComponent.java
index 70da0ff..5290150 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteGroupComponent.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/palette/PaletteGroupComponent.java
@@ -16,6 +16,7 @@
package com.intellij.designer.palette;
import com.intellij.icons.AllIcons;
+import com.intellij.ui.Gray;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
@@ -54,6 +55,9 @@
if (isFocusOwner()) {
return UIUtil.getListSelectionBackground();
}
+ if (UIUtil.isUnderDarcula()) {
+ return Gray._100;
+ }
return super.getBackground();
}
diff --git a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/renderers/AbstractResourceRenderer.java b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/renderers/AbstractResourceRenderer.java
index f630380..fa59359 100644
--- a/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/renderers/AbstractResourceRenderer.java
+++ b/plugins/ui-designer-core/src/com/intellij/designer/propertyTable/renderers/AbstractResourceRenderer.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * 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.
@@ -34,7 +34,7 @@
protected final ColorIcon myColorIcon = new ColorIcon(10, 9);
protected final SimpleColoredComponent myColoredComponent = new SimpleColoredComponent() {
@Override
- protected void doPaintIcon(Graphics2D g, Icon icon, int offset) {
+ protected void doPaintIcon(@NotNull Graphics2D g, @NotNull Icon icon, int offset) {
g.setColor(getBackground());
g.fillRect(offset, 0, icon.getIconWidth() + getIpad().left + myIconTextGap, getHeight());
paintIcon(g, icon, offset + getIpad().left);
diff --git a/plugins/ui-designer-core/ui-designer-core.iml b/plugins/ui-designer-core/ui-designer-core.iml
index a4fc33f..6645b82 100644
--- a/plugins/ui-designer-core/ui-designer-core.iml
+++ b/plugins/ui-designer-core/ui-designer-core.iml
@@ -9,16 +9,11 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="openapi" />
<orderEntry type="module" module-name="util" />
- <orderEntry type="module" module-name="compiler-impl" />
- <orderEntry type="module" module-name="compiler-openapi" />
- <orderEntry type="module" module-name="execution-impl" />
- <orderEntry type="module" module-name="execution-openapi" />
<orderEntry type="module" module-name="icons" />
- <orderEntry type="module" module-name="idea-ui" />
- <orderEntry type="module" module-name="java-impl" />
<orderEntry type="module" module-name="platform-api" />
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="spellchecker" />
+ <orderEntry type="module" module-name="lang-impl" exported="" />
</component>
</module>
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java b/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java
index 4fef2c8..a4ecbfb 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/CutCopyPasteSupport.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,7 +39,6 @@
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.DataFlavor;
-import java.awt.datatransfer.Transferable;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
@@ -165,7 +164,7 @@
if (parentLayout != null) {
container.setLayoutManager(parentLayout);
}
-
+
final int x = Integer.parseInt(e.getAttributeValue(ATTRIBUTE_X));
final int y = Integer.parseInt(e.getAttributeValue(ATTRIBUTE_Y));
@@ -204,17 +203,7 @@
@Nullable
private static String getSerializedComponents() {
try {
- final CopyPasteManager copyPasteManager = CopyPasteManager.getInstance();
- if (!copyPasteManager.isDataFlavorAvailable(ourDataFlavor)) {
- return null;
- }
-
- final Transferable content = copyPasteManager.getContents();
- if (content == null) {
- return null;
- }
-
- final Object transferData = content.getTransferData(ourDataFlavor);
+ final Object transferData = CopyPasteManager.getInstance().getContents(ourDataFlavor);
if (!(transferData instanceof SerializedComponentData)) {
return null;
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java b/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java
index 3d83737..6f98660 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/FormEditingUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -25,7 +25,6 @@
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.util.Ref;
@@ -551,7 +550,7 @@
final int rc = Messages.showYesNoDialog(editor, message,
isRow ? UIDesignerBundle.message("delete.row.title")
: UIDesignerBundle.message("delete.column.title"), Messages.getQuestionIcon());
- if (rc != DialogWrapper.OK_EXIT_CODE) {
+ if (rc != Messages.YES) {
return;
}
@@ -630,6 +629,9 @@
if (directory != null) {
PsiPackage pkg = JavaDirectoryService.getInstance().getPackage(directory);
String packageName = pkg != null ? pkg.getQualifiedName() : "";
+ if (packageName.length() == 0) {
+ return file.getName();
+ }
return packageName.replace('.', '/') + '/' + file.getName();
}
return null;
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/UIDesignerBundle.java b/plugins/ui-designer/src/com/intellij/uiDesigner/UIDesignerBundle.java
index 4afcef3..98c951f 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/UIDesignerBundle.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/UIDesignerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author yole
*/
public class UIDesignerBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.UIDesignerBundle";
private UIDesignerBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateListenerAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateListenerAction.java
index 20a3c3c..e5bff19 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateListenerAction.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/CreateListenerAction.java
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import com.intellij.codeInsight.FileModificationService;
+import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
import com.intellij.codeInsight.generation.OverrideImplementUtil;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
@@ -25,16 +26,22 @@
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.fileEditor.FileEditor;
+import com.intellij.openapi.fileEditor.FileEditorManager;
+import com.intellij.openapi.fileEditor.TextEditor;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtil;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.PsiUtilCore;
import com.intellij.uiDesigner.FormEditingUtil;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.uiDesigner.designSurface.GuiEditor;
@@ -226,15 +233,17 @@
});
final PsiClass newClass = newClassRef.get();
final SmartPsiElementPointer ptr = SmartPointerManager.getInstance(myClass.getProject()).createSmartPsiElementPointer(newClass);
- newClass.navigate(true);
+ final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(newClass);
+ final FileEditor[] fileEditors =
+ virtualFile != null ? FileEditorManager.getInstance(newClass.getProject()).openFile(virtualFile, true, true) : null;
IdeFocusManager.findInstance().doWhenFocusSettlesDown(new Runnable() {
public void run() {
final PsiClass newClass = (PsiClass)ptr.getElement();
- final Editor editor = CommonDataKeys.EDITOR.getData(DataManager.getInstance().getDataContext());
+ final Editor editor = getEditor();
if (editor != null && newClass != null) {
CommandProcessor.getInstance().executeCommand(myClass.getProject(), new Runnable() {
public void run() {
- if (!OverrideImplementUtil.getMethodSignaturesToImplement(newClass).isEmpty()) {
+ if (!OverrideImplementExploreUtil.getMethodSignaturesToImplement(newClass).isEmpty()) {
OverrideImplementUtil.chooseAndImplementMethods(newClass.getProject(), editor, newClass);
}
else {
@@ -244,6 +253,17 @@
}, "", null);
}
}
+
+ private Editor getEditor() {
+ if (fileEditors != null) {
+ for (FileEditor fileEditor : fileEditors) {
+ if (fileEditor instanceof TextEditor) {
+ return ((TextEditor)fileEditor).getEditor();
+ }
+ }
+ }
+ return null;
+ }
});
}
catch (IncorrectOperationException ex) {
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/DataBindingWizardAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/DataBindingWizardAction.java
index a57149f..b5bbd64 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/actions/DataBindingWizardAction.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/actions/DataBindingWizardAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -100,10 +100,10 @@
variants[0], variants[1], variants[2],
Messages.getQuestionIcon()
);
- if (result == 0) {
+ if (result == Messages.YES) {
// do nothing here
}
- else if (result == 1) {
+ else if (result == Messages.NO) {
wizardData.myBindToNewBean = true;
}
else {
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/CachedGridImage.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/CachedGridImage.java
index e570bdb..a298278 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/CachedGridImage.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/CachedGridImage.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -188,12 +188,9 @@
}
public static Image getGridImage(final RadContainer container) {
- CachedGridImage gridImage = null;
//noinspection unchecked
SoftReference<CachedGridImage> imageRef = (SoftReference<CachedGridImage>) container.getDelegee().getClientProperty(CACHED_GRID_IMAGE_KEY);
- if (imageRef != null) {
- gridImage = imageRef.get();
- }
+ CachedGridImage gridImage = SoftReference.dereference(imageRef);
if (gridImage != null && gridImage.sizeEquals(container)) {
gridImage.update(container);
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java
index 9319304..b088447 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/designSurface/InsertComponentProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -369,8 +369,8 @@
UIDesignerBundle.message("add.module.dependency.prompt", item.getClassName(), ownerModule.getName(), myEditor.getModule().getName()),
UIDesignerBundle.message("add.module.dependency.title"),
Messages.getQuestionIcon());
- if (rc == 2) return false;
- if (rc == 0) {
+ if (rc == Messages.CANCEL) return false;
+ if (rc == Messages.YES) {
ModuleRootModificationUtil.addDependency(myEditor.getModule(), ownerModule);
}
return true;
@@ -383,8 +383,8 @@
myEditor.getModule().getName()),
UIDesignerBundle.message("add.library.dependency.title"),
Messages.getQuestionIcon());
- if (rc == 2) return false;
- if (rc == 0) {
+ if (rc == Messages.CANCEL) return false;
+ if (rc == Messages.YES) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
public void run() {
final ModifiableRootModel model = ModuleRootManager.getInstance(myEditor.getModule()).getModifiableModel();
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/DeleteComponentAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/DeleteComponentAction.java
index cd1fa5a..4055c3f 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/DeleteComponentAction.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/DeleteComponentAction.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -20,7 +20,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.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.uiDesigner.UIDesignerBundle;
@@ -46,7 +45,7 @@
int rc = Messages.showYesNoDialog(project, UIDesignerBundle.message("delete.component.prompt", selectedItem.getClassShortName()),
UIDesignerBundle.message("delete.component.title"), Messages.getQuestionIcon());
- if (rc != 0) return;
+ if (rc != Messages.YES) return;
final Palette palette = Palette.getInstance(project);
palette.removeItem(groupItem, selectedItem);
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java
index 3673ec9..abe7445 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/palette/Palette.java
@@ -120,7 +120,7 @@
/** Invoked by reflection */
public Palette(Project project) {
myProject = project;
- myLafManagerListener = new MyLafManagerListener();
+ myLafManagerListener = project == null ? null : new MyLafManagerListener();
myClass2Properties = new HashMap<Class, IntrospectedProperty[]>();
myClassName2Item = new HashMap<String, ComponentItem>();
myGroups = new ArrayList<GroupItem>();
@@ -130,7 +130,9 @@
mySpecialGroup.addItem(ComponentItem.createAnyComponentItem(project));
}
- LafManager.getInstance().addLafManagerListener(myLafManagerListener);
+ if (myLafManagerListener != null) {
+ LafManager.getInstance().addLafManagerListener(myLafManagerListener);
+ }
}
public Element getState() {
@@ -164,7 +166,9 @@
@Override
public void dispose() {
- LafManager.getInstance().removeLafManagerListener(myLafManagerListener);
+ if (myLafManagerListener != null) {
+ LafManager.getInstance().removeLafManagerListener(myLafManagerListener);
+ }
}
public void readExternal(@NotNull final Element element) {
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditorDialog.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditorDialog.java
index 73e9edf..655da43 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditorDialog.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/editors/string/StringEditorDialog.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -155,10 +155,10 @@
UIDesignerBundle.message("edit.text.make.unique"),
CommonBundle.getCancelButtonText(),
Messages.getWarningIcon());
- if (rc == 2) {
+ if (rc == Messages.CANCEL) {
return null;
}
- if (rc == 1) {
+ if (rc == Messages.NO) {
newKeyName = promptNewKeyName(module.getProject(), propFile, descriptor.getKey());
if (newKeyName == null) return null;
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java
index 6ea8ac1..d4ef253 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/propertyInspector/properties/BindingProperty.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -171,7 +171,7 @@
Messages.getQuestionIcon()
);
- if(option != 0/*Yes*/){
+ if(option != Messages.YES/*Yes*/){
return;
}
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/LightBulbComponentImpl.java b/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/LightBulbComponentImpl.java
index 25d2b1f..bc94b00 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/LightBulbComponentImpl.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/quickFixes/LightBulbComponentImpl.java
@@ -50,7 +50,7 @@
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
myManager.showIntentionPopup();
return true;
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java
index 4400cd0..284ce42 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/CreateSnapShotAction.java
@@ -30,7 +30,6 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
@@ -147,7 +146,7 @@
if (!connected) {
int rc = Messages.showYesNoDialog(project, UIDesignerBundle.message("snapshot.run.prompt"),
UIDesignerBundle.message("snapshot.title"), Messages.getQuestionIcon());
- if (rc == 1) return;
+ if (rc == Messages.NO) return;
final ApplicationConfiguration appConfig = (ApplicationConfiguration) snapshotConfiguration.getConfiguration();
final SnapShooterConfigurationSettings settings = SnapShooterConfigurationSettings.get(appConfig);
settings.setNotifyRunnable(new Runnable() {
@@ -289,7 +288,7 @@
UIDesignerBundle.message("snapshot.confirm.configuration.prompt", configurations.get(0).getConfiguration().getName()),
UIDesignerBundle.message("snapshot.title"),
Messages.getQuestionIcon());
- if (rc == 1) {
+ if (rc == Messages.NO) {
return null;
}
snapshotConfiguration = configurations.get(0);
@@ -512,7 +511,7 @@
}
builder.append(UIDesignerBundle.message("snapshot.unknown.layout.prompt"));
return Messages.showYesNoDialog(myProject, builder.toString(),
- UIDesignerBundle.message("snapshot.title"), Messages.getQuestionIcon()) == 0;
+ UIDesignerBundle.message("snapshot.title"), Messages.getQuestionIcon()) == Messages.YES;
}
return true;
}
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java
index a4b0f84..fa77193 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/snapShooter/SnapShooterConfigurationExtension.java
@@ -26,6 +26,7 @@
import com.intellij.execution.process.ProcessAdapter;
import com.intellij.execution.process.ProcessEvent;
import com.intellij.execution.process.ProcessHandler;
+import com.intellij.ide.palette.PaletteGroup;
import com.intellij.ide.ui.LafManagerListener;
import com.intellij.openapi.actionSystem.DataProvider;
import com.intellij.openapi.application.PathManager;
@@ -78,6 +79,7 @@
paths.add(PathUtil.getJarPathForClass(ProjectComponent.class)); // openapi
paths.add(PathUtil.getJarPathForClass(LwComponent.class)); // UIDesignerCore
paths.add(PathUtil.getJarPathForClass(GridConstraints.class)); // forms_rt
+ paths.add(PathUtil.getJarPathForClass(PaletteGroup.class)); // openapi
paths.add(PathUtil.getJarPathForClass(LafManagerListener.class)); // ui-impl
paths.add(PathUtil.getJarPathForClass(DataProvider.class)); // action-system-openapi
paths.add(PathUtil.getJarPathForClass(XmlStringUtil.class)); // idea
diff --git a/plugins/ui-designer/src/com/intellij/uiDesigner/wizard/BindToExistingBeanStep.java b/plugins/ui-designer/src/com/intellij/uiDesigner/wizard/BindToExistingBeanStep.java
index 4f6c519..5209c51 100644
--- a/plugins/ui-designer/src/com/intellij/uiDesigner/wizard/BindToExistingBeanStep.java
+++ b/plugins/ui-designer/src/com/intellij/uiDesigner/wizard/BindToExistingBeanStep.java
@@ -161,8 +161,7 @@
myCbx = new ComboBox();
myCbx.setEditable(true);
myCbx.setRenderer(new BeanPropertyListCellRenderer());
- myCbx.putClientProperty("tableCellEditor", this);
- myCbx.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
+ myCbx.registerTableCellEditor(this);
final JComponent editorComponent = (JComponent)myCbx.getEditor().getEditorComponent();
editorComponent.setBorder(null);
diff --git a/plugins/ui-designer/src/messages/UIDesignerBundle.properties b/plugins/ui-designer/src/messages/UIDesignerBundle.properties
index c330d3e..9fabc53 100644
--- a/plugins/ui-designer/src/messages/UIDesignerBundle.properties
+++ b/plugins/ui-designer/src/messages/UIDesignerBundle.properties
@@ -478,7 +478,7 @@
command.paste=Paste
add.component.error.qualified.name.required=Please enter a qualified class name
add.component.error.component.required=Please select a class derived from JComponent
-form.usage.type=Usage in GUI form
+form.usage.type={0} in GUI form
unsupported.component.class.version=Unsupported component class version
field.is.overwritten.by.generated.code=Field ''{0}'' is overwritten by generated code
bound.field.type.mismatch=Types of GUI component (''{0}'') and bound field (''{1}'') do not match
diff --git a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/binding/RenameUIRelatedTest.java b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/binding/RenameUIRelatedTest.java
index 7a8f9ff..f91457e 100644
--- a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/binding/RenameUIRelatedTest.java
+++ b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/binding/RenameUIRelatedTest.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.
@@ -24,11 +24,13 @@
import com.intellij.refactoring.MultiFileTestCase;
import com.intellij.refactoring.rename.RenameProcessor;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
/**
* @author ven
*/
public class RenameUIRelatedTest extends MultiFileTestCase {
+ @NotNull
@Override
protected String getTestRoot() {
return "/renameUIRelated/";
diff --git a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/refactoring/MoveFileTest.java b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/refactoring/MoveFileTest.java
index e2f9003..24f63e7 100644
--- a/plugins/ui-designer/testSrc/com/intellij/uiDesigner/refactoring/MoveFileTest.java
+++ b/plugins/ui-designer/testSrc/com/intellij/uiDesigner/refactoring/MoveFileTest.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.uiDesigner.refactoring;
import com.intellij.openapi.application.PluginPathManager;
@@ -10,6 +25,7 @@
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.MultiFileTestCase;
import com.intellij.refactoring.move.moveFilesOrDirectories.MoveFilesOrDirectoriesProcessor;
+import org.jetbrains.annotations.NotNull;
public class MoveFileTest extends MultiFileTestCase {
@Override
@@ -17,6 +33,7 @@
return PluginPathManager.getPluginHomePath("ui-designer") + "/testData";
}
+ @NotNull
@Override
protected String getTestRoot() {
return "/move/";
diff --git a/plugins/ui-designer/ui-designer.iml b/plugins/ui-designer/ui-designer.iml
index bf40bb2..49c1987 100644
--- a/plugins/ui-designer/ui-designer.iml
+++ b/plugins/ui-designer/ui-designer.iml
@@ -28,6 +28,7 @@
<orderEntry type="module" module-name="spellchecker" />
<orderEntry type="module" module-name="jps-builders" />
<orderEntry type="module" module-name="xml" />
+ <orderEntry type="module" module-name="properties-psi-api" />
</component>
<component name="copyright">
<Base>
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathParameterInfoHandler.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathParameterInfoHandler.java
index 7eb1e91..59df332 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathParameterInfoHandler.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/XPathParameterInfoHandler.java
@@ -43,7 +43,7 @@
return ArrayUtil.EMPTY_OBJECT_ARRAY;
}
- public XPathFunctionCall findElementForParameterInfo(CreateParameterInfoContext context) {
+ public XPathFunctionCall findElementForParameterInfo(@NotNull CreateParameterInfoContext context) {
final XPathFunctionCall call = findFunctionCall(context.getFile(), context.getOffset());
if (call != null) {
final XPathFunction function = call.resolve();
@@ -72,15 +72,15 @@
return null;
}
- public void showParameterInfo(@NotNull XPathFunctionCall call, CreateParameterInfoContext context) {
+ public void showParameterInfo(@NotNull XPathFunctionCall call, @NotNull CreateParameterInfoContext context) {
context.showHint(call, call.getTextOffset() + 1, this);
}
- public XPathFunctionCall findElementForUpdatingParameterInfo(UpdateParameterInfoContext context) {
+ public XPathFunctionCall findElementForUpdatingParameterInfo(@NotNull UpdateParameterInfoContext context) {
return findFunctionCall(context.getFile(), context.getOffset());
}
- public void updateParameterInfo(@NotNull XPathFunctionCall call, UpdateParameterInfoContext context) {
+ public void updateParameterInfo(@NotNull XPathFunctionCall call, @NotNull UpdateParameterInfoContext context) {
int currentParameterIndex = ParameterInfoUtils.getCurrentParameterIndex(call.getNode(), context.getOffset(), XPathTokenTypes.COMMA);
context.setCurrentParameter(currentParameterIndex);
}
@@ -93,7 +93,7 @@
return true;
}
- public void updateUI(XPathFunction function, ParameterInfoUIContext context) {
+ public void updateUI(XPathFunction function, @NotNull ParameterInfoUIContext context) {
final Function declaration = function.getDeclaration();
if (declaration != null) {
if (declaration.getParameters().length > 0) {
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltDocumentationProvider.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltDocumentationProvider.java
index 6158699..9a7493e 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltDocumentationProvider.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/impl/XsltDocumentationProvider.java
@@ -169,8 +169,8 @@
}
private Document getDocumentationDocument() throws IOException, JDOMException {
- Document d;
- if (myDocument == null || ((d = myDocument.get()) == null)) {
+ Document d = com.intellij.reference.SoftReference.dereference(myDocument);
+ if (d == null) {
d = new SAXBuilder().build(XsltSupport.class.getResource("resources/documentation.xml"));
myDocument = new SoftReference<Document>(d);
}
@@ -178,8 +178,8 @@
}
private Templates getTemplate() throws TransformerConfigurationException, IOException {
- Templates t;
- if (myTemplates == null || (t = myTemplates.get()) == null) {
+ Templates t = com.intellij.reference.SoftReference.dereference(myTemplates);
+ if (t == null) {
t = TransformerFactory.newInstance().newTemplates(makeSource("resources/documentation.xsl"));
myTemplates = new SoftReference<Templates>(t);
}
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/VariableInlineHandler.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/VariableInlineHandler.java
index 8c8d5fc..ca8f0cf 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/VariableInlineHandler.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/refactoring/VariableInlineHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2010 JetBrains s.r.o.
+ * 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.
@@ -180,7 +180,7 @@
variable.getName(),
String.valueOf(references.size()),
references.size() > 1 ? "s" : ""),
- TITLE, Messages.getQuestionIcon()) != 0) {
+ TITLE, Messages.getQuestionIcon()) != Messages.YES) {
return;
}
} else {
@@ -191,7 +191,7 @@
variable.getName(),
String.valueOf(references.size()),
references.size() > 1 ? "s" : ""),
- TITLE, Messages.getWarningIcon()) != 0) {
+ TITLE, Messages.getWarningIcon()) != Messages.YES) {
return;
}
}
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java
index e2886b3..6406db9 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltCommandLineState.java
@@ -213,7 +213,7 @@
public void run() {
if (event.getExitCode() == 0) {
if (myXsltRunConfiguration.myOpenInBrowser) {
- BrowserUtil.launchBrowser(myXsltRunConfiguration.myOutputFile);
+ BrowserUtil.browse(myXsltRunConfiguration.myOutputFile);
}
if (myXsltRunConfiguration.myOpenOutputFile) {
final String url = VfsUtilCore.pathToUrl(myXsltRunConfiguration.myOutputFile);
diff --git a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunSettingsEditor.java b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunSettingsEditor.java
index e431146..fc261ca 100644
--- a/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunSettingsEditor.java
+++ b/plugins/xpath/xpath-lang/src/org/intellij/lang/xpath/xslt/run/XsltRunSettingsEditor.java
@@ -135,7 +135,7 @@
return text.length() > 0 ? text : (baseDir != null ? baseDir.getPresentableUrl() : "");
}
- public void setText(JTextField component, String text) {
+ public void setText(JTextField component, @NotNull String text) {
component.setText(text);
}
};
@@ -199,7 +199,7 @@
return item.toString();
}
- public void setText(JComboBox comboBox, String text) {
+ public void setText(JComboBox comboBox, @NotNull String text) {
comboBox.getEditor().setItem(text);
}
});
@@ -218,7 +218,7 @@
myClasspathAndJDKPanel.setVisible(ALLOW_CHOOSING_SDK);
updateOutputState();
- myFileType.setRenderer(new FileTypeRenderer(myFileType.getRenderer()) {
+ myFileType.setRenderer(new FileTypeRenderer() {
@Override
public void customize(JList list, FileType type, int index, boolean selected, boolean hasFocus) {
if (type == null) {
diff --git a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathEvalAction.java b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathEvalAction.java
index 3bbc8b8..dd14694 100644
--- a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathEvalAction.java
+++ b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/XPathEvalAction.java
@@ -255,7 +255,7 @@
} catch (XPathSyntaxException e) {
LOG.debug(e);
// TODO: Better layout of the error message with non-fixed size fonts
- return Messages.showOkCancelDialog(project, e.getMultilineMessage(), "XPath syntax error", "Edit Expression", "Cancel", Messages.getErrorIcon()) == 0;
+ return Messages.showOkCancelDialog(project, e.getMultilineMessage(), "XPath syntax error", "Edit Expression", "Cancel", Messages.getErrorIcon()) == Messages.OK;
} catch (SAXPathException e) {
LOG.debug(e);
Messages.showMessageDialog(project, e.getMessage(), "XPath error", Messages.getErrorIcon());
@@ -310,7 +310,7 @@
presentation.setOpenInNewTab(XPathAppComponent.getInstance().getConfig().OPEN_NEW_TAB);
- final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation();
+ final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation(presentation);
processPresentation.setProgressIndicatorFactory(new Factory<ProgressIndicator>() {
@Override
public ProgressIndicator create() {
diff --git a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/search/FindByXPathAction.java b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/search/FindByXPathAction.java
index 109e267..4231f2c 100644
--- a/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/search/FindByXPathAction.java
+++ b/plugins/xpath/xpath-view/src/org/intellij/plugins/xpathView/search/FindByXPathAction.java
@@ -89,7 +89,7 @@
presentation.setOpenInNewTab(settings.OPEN_NEW_TAB);
- final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation();
+ final FindUsagesProcessPresentation processPresentation = new FindUsagesProcessPresentation(presentation);
processPresentation.setProgressIndicatorFactory(new Factory<ProgressIndicator>() {
public ProgressIndicator create() {
return new FindProgressIndicator(project, scope.getName());
diff --git a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java
index 7e72316..f573f94 100644
--- a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java
+++ b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/XsltDebuggerRunner.java
@@ -2,7 +2,6 @@
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
-import com.intellij.execution.Executor;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.runners.DefaultProgramRunner;
@@ -44,10 +43,10 @@
}
@Override
- protected RunContentDescriptor doExecute(Project project,
- RunProfileState state,
+ protected RunContentDescriptor doExecute(@NotNull Project project,
+ @NotNull RunProfileState state,
RunContentDescriptor contentToReuse,
- ExecutionEnvironment env) throws ExecutionException {
+ @NotNull ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
return createContentDescriptor(project, state, contentToReuse, env);
}
diff --git a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltDebugProcess.java b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltDebugProcess.java
index 99ffea5..b87939b 100644
--- a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltDebugProcess.java
+++ b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/impl/XsltDebugProcess.java
@@ -21,7 +21,10 @@
import org.intellij.plugins.xsltDebugger.VMPausedException;
import org.intellij.plugins.xsltDebugger.XsltBreakpointType;
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
-import org.intellij.plugins.xsltDebugger.rt.engine.*;
+import org.intellij.plugins.xsltDebugger.rt.engine.Breakpoint;
+import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManager;
+import org.intellij.plugins.xsltDebugger.rt.engine.BreakpointManagerImpl;
+import org.intellij.plugins.xsltDebugger.rt.engine.Debugger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -50,6 +53,7 @@
Disposer.register(myExecutionConsole, this);
}
+ @NotNull
@Override
public XBreakpointHandler<?>[] getBreakpointHandlers() {
return myXBreakpointHandlers;
@@ -65,9 +69,8 @@
myDebuggerSession.addListener(new XsltDebuggerSession.Listener() {
@Override
public void debuggerSuspended() {
- final XDebugSession session = XsltDebugProcess.this.getSession();
final Debugger c = myDebuggerSession.getClient();
- session.positionReached(new MySuspendContext(myDebuggerSession, c.getCurrentFrame(), c.getSourceFrame()));
+ getSession().positionReached(new MySuspendContext(myDebuggerSession, c.getCurrentFrame(), c.getSourceFrame()));
}
@Override
diff --git a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/ui/GeneratedStructureModel.java b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/ui/GeneratedStructureModel.java
index 20f1942..195ad1b 100644
--- a/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/ui/GeneratedStructureModel.java
+++ b/plugins/xslt-debugger/src/org/intellij/plugins/xsltDebugger/ui/GeneratedStructureModel.java
@@ -18,10 +18,10 @@
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.pom.Navigatable;
+import com.intellij.reference.SoftReference;
import com.intellij.util.SmartList;
import com.intellij.util.containers.StringInterner;
import org.intellij.plugins.xsltDebugger.XsltDebuggerSession;
@@ -59,8 +59,8 @@
// all instances (and their toolwindow contents) are gone. This should minimize the memory usage of the generated
// structure tree.
private static StringInterner getInterner() {
- StringInterner interner;
- if (ourSharedInterner == null || (interner = ourSharedInterner.get()) == null) {
+ StringInterner interner = SoftReference.dereference(ourSharedInterner);
+ if (interner == null) {
interner = new StringInterner();
ourSharedInterner = new WeakReference<StringInterner>(interner);
}
diff --git a/python/build.xml b/python/build.xml
index aa5176f..22f9990 100644
--- a/python/build.xml
+++ b/python/build.xml
@@ -17,8 +17,8 @@
<attribute name="script" />
<sequential>
<java failonerror="true" jar="${project.home}/lib/ant/lib/ant-launcher.jar" fork="true">
- <jvmarg line="-Xmx612m -XX:MaxPermSize=152m -Didea.build.number=${idea.build.number} -DideaPath=${idea.path}"/>
-
+ <jvmarg line="-Xmx612m -XX:MaxPermSize=152m -Didea.build.number=${idea.build.number} "-DideaPath=${idea.path}""/>
+ <sysproperty key="java.awt.headless" value="true"/>
<arg line=""-Dgant.script=@{script}""/>
<arg line=""-Dteamcity.build.tempDir=${tmp.dir}""/>
<arg line=""-Didea.build.number=${idea.build.number}""/>
diff --git a/python/build/pycharm_community_build.gant b/python/build/pycharm_community_build.gant
index 4701545..dfb9b05 100644
--- a/python/build/pycharm_community_build.gant
+++ b/python/build/pycharm_community_build.gant
@@ -216,12 +216,6 @@
module("util-rt")
}
- dir("libpty") {
- fileset(dir: "$home/community/lib/libpty") {
- exclude(name: "*.txt")
- }
- }
-
jar("openapi.jar") {
openapiModules.each { module it }
}
@@ -272,6 +266,12 @@
fileset(file: it)
}
+ dir("libpty") {
+ fileset(dir: "$ch/lib/libpty") {
+ exclude(name: "*.txt")
+ }
+ }
+
dir("ext") {
fileset(dir: "$ch/lib") {
include(name: "cglib*.jar")
diff --git a/python/build/python_plugin_build.gant b/python/build/python_plugin_build.gant
index 0383e3e..261313a 100644
--- a/python/build/python_plugin_build.gant
+++ b/python/build/python_plugin_build.gant
@@ -149,6 +149,10 @@
fileset(file: "${pluginHome}/pluginResources/META-INF/*.xml")
}
+ ant.replace(file: "${classesDir}/META-INF/plugin.xml") {
+ replacefilter(token: "@@BUILD_NUMBER@@", value: "${buildNumber}")
+ }
+
ant.replaceregexp(file: "${classesDir}/META-INF/plugin.xml",
match: "since-build=\"\\d+\\.\\d+\"",
replace: "since-build=\"${ideaBuildNumber}\"")
diff --git a/python/helpers/pycharm/django_test_runner.py b/python/helpers/pycharm/django_test_runner.py
index ed5fd09..f3f20a0 100644
--- a/python/helpers/pycharm/django_test_runner.py
+++ b/python/helpers/pycharm/django_test_runner.py
@@ -2,6 +2,7 @@
from tcmessages import TeamcityServiceMessages
import sys
from pycharm_run_utils import adjust_django_sys_path
+
adjust_django_sys_path()
from django.conf import settings
diff --git a/python/helpers/pycharm/nose_utils.py b/python/helpers/pycharm/nose_utils.py
index 9a6d682..a7efa08 100644
--- a/python/helpers/pycharm/nose_utils.py
+++ b/python/helpers/pycharm/nose_utils.py
@@ -116,7 +116,7 @@
suite = strclass(test.__class__)
suite_location = "python_nosetestid://" + suite
try:
- from nose_helper.util import func_lineno
+ from nose.util import func_lineno
if hasattr(test.test, "descriptor") and test.test.descriptor:
suite_location = "file://" + self.test_address(
diff --git a/python/helpers/pycharm/pycharm_run_utils.py b/python/helpers/pycharm/pycharm_run_utils.py
index 5fbc35c..d905d05 100644
--- a/python/helpers/pycharm/pycharm_run_utils.py
+++ b/python/helpers/pycharm/pycharm_run_utils.py
@@ -20,9 +20,10 @@
insert_to_sys_path(script_path)
def adjust_django_sys_path():
- sys.path.pop(0)
+ pycharm_path = sys.path.pop(0)
script_path = sys.argv[-1]
insert_to_sys_path(script_path)
+ sys.path.append(pycharm_path)
def import_system_module(name):
f, filename, desc = imp.find_module(name)
diff --git a/python/helpers/pydev/pydev_monkey.py b/python/helpers/pydev/pydev_monkey.py
index 8dd94ab..ed6fea5 100644
--- a/python/helpers/pydev/pydev_monkey.py
+++ b/python/helpers/pydev/pydev_monkey.py
@@ -4,7 +4,7 @@
import pydev_log
import traceback
-helpers = os.path.dirname(__file__)
+helpers = os.path.dirname(__file__).replace('\\', '/')
def is_python(path):
if path.endswith("'") or path.endswith('"'):
diff --git a/python/ide/src/com/jetbrains/python/PyCharmInitialConfigurator.java b/python/ide/src/com/jetbrains/python/PyCharmInitialConfigurator.java
index e87d821..091a670 100644
--- a/python/ide/src/com/jetbrains/python/PyCharmInitialConfigurator.java
+++ b/python/ide/src/com/jetbrains/python/PyCharmInitialConfigurator.java
@@ -55,10 +55,15 @@
propertiesComponent.setValue("PyCharm.InitialConfiguration.V3", "true");
UISettings.getInstance().SHOW_MEMORY_INDICATOR = false;
final String ignoredFilesList = fileTypeManager.getIgnoredFilesList();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- FileTypeManager.getInstance().setIgnoredFilesList(ignoredFilesList + ";*$py.class");
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ FileTypeManager.getInstance().setIgnoredFilesList(ignoredFilesList + ";*$py.class");
+ }
+ });
}
});
}
diff --git a/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java b/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java
index 2636aa5..94e9912 100644
--- a/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java
+++ b/python/ide/src/com/jetbrains/python/PyIdeCommonOptionsForm.java
@@ -224,7 +224,7 @@
}
public void updateSdkList(boolean preserveSelection, PyConfigurableInterpreterList myInterpreterList) {
- myPythonSdks = myInterpreterList.getAllPythonSdks();
+ myPythonSdks = myInterpreterList.getAllPythonSdks(myProject);
Sdk selection = preserveSelection ? (Sdk)myInterpreterComboBox.getSelectedItem() : null;
if (!myPythonSdks.contains(selection)) {
selection = null;
@@ -266,7 +266,7 @@
return myPathMappingsComponent.getMappingSettings();
}
else {
- return null;
+ return new PathMappingSettings();
}
}
diff --git a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
index a0d2fd0..b079014 100644
--- a/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
+++ b/python/ide/src/com/jetbrains/python/PythonSdkChooserCombo.java
@@ -15,18 +15,21 @@
*/
package com.jetbrains.python;
-import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkType;
import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer;
import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.ComboboxWithBrowseButton;
+import com.intellij.util.NullableConsumer;
import com.intellij.util.containers.ContainerUtil;
-import com.jetbrains.python.configuration.PythonSdkConfigurable;
-import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import com.jetbrains.python.configuration.PythonSdkDetailsDialog;
+import com.jetbrains.python.sdk.PyDetectedSdk;
import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -39,10 +42,7 @@
public class PythonSdkChooserCombo extends ComboboxWithBrowseButton {
private final List<ActionListener> myChangedListeners = ContainerUtil.createLockFreeCopyOnWriteList();
- //public PythonSdkChooserCombo(final Condition<Sdk> acceptableSdkCondition) {
- // this(PythonSdkType.getAllSdks(), acceptableSdkCondition);
- //}
-
+ @SuppressWarnings("unchecked")
public PythonSdkChooserCombo(final Project project, List<Sdk> sdks, final Condition<Sdk> acceptableSdkCondition) {
Sdk initialSelection = null;
for (Sdk sdk : sdks) {
@@ -51,26 +51,30 @@
break;
}
}
- getComboBox().setModel(new CollectionComboBoxModel(sdks, initialSelection));
- getComboBox().setRenderer(new SdkListCellRenderer("<no interpreter>") {
+ final JComboBox comboBox = getComboBox();
+ comboBox.setModel(new CollectionComboBoxModel(sdks, initialSelection));
+ comboBox.setRenderer(new SdkListCellRenderer("<no interpreter>") {
@Override
protected Icon getSdkIcon(Sdk sdk) {
final PythonSdkFlavor flavor = PythonSdkFlavor.getFlavor(sdk);
- return flavor != null ? flavor.getIcon() : ((SdkType)sdk.getSdkType()).getIcon();
+ final Icon icon = flavor != null ? flavor.getIcon() : ((SdkType)sdk.getSdkType()).getIcon();
+ return sdk instanceof PyDetectedSdk ? IconLoader.getTransparentIcon(icon) : icon;
}
});
addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
- final PythonSdkConfigurable configurable = new PythonSdkConfigurable(project);
- configurable.setNewProject(true);
- ShowSettingsUtil.getInstance().editConfigurable(PythonSdkChooserCombo.this, configurable);
- Sdk selection = configurable.getRealSelectedSdk();
final List<Sdk> sdks = PythonSdkType.getAllSdks();
- getComboBox().setModel(new CollectionComboBoxModel(sdks, selection));
+ PythonSdkDetailsDialog dialog = new PythonSdkDetailsDialog(project, new NullableConsumer<Sdk>() {
+ @Override
+ public void consume(@Nullable Sdk sdk) {
+ comboBox.setModel(new CollectionComboBoxModel(sdks, sdk));
+ }
+ });
+ dialog.show();
notifyChanged(e);
}
});
- getComboBox().addActionListener(new ActionListener() {
+ comboBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
notifyChanged(e);
}
@@ -83,6 +87,7 @@
}
}
+ @SuppressWarnings("UnusedDeclaration")
public void addChangedListener(ActionListener listener) {
myChangedListeners.add(listener);
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.form b/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.form
index 78c5657..5d2cd59 100644
--- a/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.form
+++ b/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.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.AddVEnvOptionsDialog">
- <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">
+ <grid id="27dc6" binding="myMainPanel" 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>
<xy x="20" y="20" width="500" height="400"/>
@@ -8,23 +8,14 @@
<properties/>
<border type="none"/>
<children>
- <component id="6ea43" class="com.intellij.ui.components.JBCheckBox" binding="myUseForThisProjectJBCheckBox" default-binding="true">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <selected value="true"/>
- <text value="Set as project interpreter for &this project"/>
- </properties>
- </component>
<vspacer id="46c2b">
<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"/>
+ <grid row="1" 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>
<component id="b3884" class="com.intellij.ui.components.JBCheckBox" binding="myMakeAvailableToAllJBCheckBox" default-binding="true">
<constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Make available to &all projects"/>
diff --git a/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.java b/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.java
index b4e5b8e..d894191 100644
--- a/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.java
+++ b/python/ide/src/com/jetbrains/python/configuration/AddVEnvOptionsDialog.java
@@ -25,7 +25,6 @@
* @author yole
*/
public class AddVEnvOptionsDialog extends DialogWrapper {
- private JBCheckBox myUseForThisProjectJBCheckBox;
private JBCheckBox myMakeAvailableToAllJBCheckBox;
private JPanel myMainPanel;
@@ -40,10 +39,6 @@
return myMainPanel;
}
- public boolean useForThisProject() {
- return myUseForThisProjectJBCheckBox.isSelected();
- }
-
public boolean makeAvailableToAll() {
return myMakeAvailableToAllJBCheckBox.isSelected();
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/EditSdkDialog.java b/python/ide/src/com/jetbrains/python/configuration/EditSdkDialog.java
index 988b5e9..2ad22fd 100644
--- a/python/ide/src/com/jetbrains/python/configuration/EditSdkDialog.java
+++ b/python/ide/src/com/jetbrains/python/configuration/EditSdkDialog.java
@@ -27,6 +27,7 @@
import com.intellij.util.NullableFunction;
import com.jetbrains.python.sdk.PythonSdkAdditionalData;
import com.jetbrains.python.sdk.PythonSdkType;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
@@ -82,7 +83,7 @@
init();
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
myAssociateCheckbox.setSelected(false);
myAssociateCheckbox.setEnabled(true);
myAssociateCheckbox.setText("Associate this environment with current project");
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.form b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.form
deleted file mode 100644
index 79a648b..0000000
--- a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.form
+++ /dev/null
@@ -1,40 +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.configuration.PyActiveSdkConfigurable">
- <grid id="27dc6" binding="myPanel" 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>
- <component id="70598" 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="0" fill="1" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties>
- <text value="Project Interpreter:"/>
- </properties>
- </component>
- <vspacer id="3aae9">
- <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>
- <component id="7421c" class="javax.swing.JComboBox" binding="mySdkCombo">
- <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"/>
- </constraints>
- <properties/>
- </component>
- <grid id="19f49" binding="myConfigureInterpretersPanel" layout-manager="BorderLayout" hgap="0" vgap="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/>
- <border type="none"/>
- <children/>
- </grid>
- </children>
- </grid>
-</form>
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java
index e4f22dd..b68df03 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkConfigurable.java
@@ -16,6 +16,7 @@
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;
@@ -27,68 +28,218 @@
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModel;
+import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.projectRoots.impl.SdkListCellRenderer;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
+import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CollectionComboBoxModel;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.NullableConsumer;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.webcore.packaging.PackagesNotificationPanel;
+import com.jetbrains.python.packaging.ui.PyInstalledPackagesPanel;
+import com.jetbrains.python.packaging.ui.PyPackageManagementService;
import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.sdk.PyDetectedSdk;
import com.jetbrains.python.sdk.PySdkListCellRenderer;
+import com.jetbrains.python.sdk.PythonSdkDetailsStep;
+import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import icons.PythonIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
import java.util.List;
-/**
- * @author yole
- */
public class PyActiveSdkConfigurable implements UnnamedConfigurable {
- private JPanel myPanel;
+ private JPanel myMainPanel;
private final Project myProject;
@Nullable private final Module myModule;
- private JComboBox mySdkCombo;
- private JPanel myConfigureInterpretersPanel;
+ private MySdkModelListener mySdkModelListener;
+ private Sdk myAddedSdk = null;
+
private PyConfigurableInterpreterList myInterpreterList;
private ProjectSdksModel myProjectSdksModel;
- private MyListener myListener;
+ private ComboBox mySdkCombo;
+ private PyInstalledPackagesPanel myPackagesPanel;
+ private JButton myDetailsButton;
+ private static final String SHOW_ALL = "Show All";
+ private NullableConsumer<Sdk> myDetailsCallback;
- public PyActiveSdkConfigurable(Project project) {
+ public PyActiveSdkConfigurable(@NotNull Project project) {
myModule = null;
myProject = project;
- init();
+ layoutPanel();
+ initContent();
}
public PyActiveSdkConfigurable(@NotNull Module module) {
myModule = module;
myProject = module.getProject();
- init();
+ layoutPanel();
+ initContent();
}
- private void init() {
+ private void initContent() {
+ myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
+ myInterpreterList.setSdkCombo(mySdkCombo);
+
+ myProjectSdksModel = myInterpreterList.getModel();
+ mySdkModelListener = new MySdkModelListener(this);
+ myProjectSdksModel.addListener(mySdkModelListener);
+
+ mySdkCombo.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ final Sdk selectedSdk = (Sdk)mySdkCombo.getSelectedItem();
+ myPackagesPanel.updatePackages(selectedSdk != null ? new PyPackageManagementService(myProject, selectedSdk) : null);
+ }
+ });
+ myDetailsCallback = new NullableConsumer<Sdk>() {
+
+ @Override
+ public void consume(@Nullable Sdk sdk) {
+ if (sdk instanceof PyDetectedSdk) {
+ final Sdk addedSdk = SdkConfigurationUtil.setupSdk(myProjectSdksModel.getSdks(), sdk.getHomeDirectory(),
+ PythonSdkType.getInstance(), true,
+ null, null);
+ myAddedSdk = addedSdk;
+ myProjectSdksModel.addSdk(addedSdk);
+ myProjectSdksModel.removeSdk(sdk);
+ mySdkCombo.setSelectedItem(addedSdk);
+ }
+ else if (getSdk() != sdk) {
+ mySdkCombo.setSelectedItem(sdk);
+ }
+ }
+ };
+
+ 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),
+ RelativePoint.fromScreen(myDetailsButton.getLocationOnScreen()), true,
+ new NullableConsumer<Sdk>() {
+ @Override
+ public void consume(Sdk sdk) {
+ if (sdk == null) return;
+ if (myProjectSdksModel.findSdk(sdk) == null) {
+ myProjectSdksModel.addSdk(sdk);
+ myAddedSdk = sdk;
+ }
+ updateSdkList(false);
+ mySdkCombo.getModel().setSelectedItem(sdk);
+ myPackagesPanel.updatePackages(new PyPackageManagementService(myProject, sdk));
+ }
+ }
+ );
+ }
+ }
+ );
+
+ }
+
+ private void layoutPanel() {
+ final GridBagLayout layout = new GridBagLayout();
+ myMainPanel = new JPanel(layout);
+ final JLabel interpreterLabel = new JLabel("Project Interpreter:");
+ final JLabel emptyLabel = new JLabel(" ");
+ mySdkCombo = new ComboBox() {
+ @Override
+ public void setSelectedItem(Object item) {
+ if (SHOW_ALL.equals(item)) {
+ PythonSdkDetailsDialog options = myModule == null ? new PythonSdkDetailsDialog(myProject, myDetailsCallback) :
+ new PythonSdkDetailsDialog(myModule, myDetailsCallback);
+ options.show();
+ return;
+ }
+ if (!PySdkListCellRenderer.SEPARATOR.equals(item))
+ super.setSelectedItem(item);
+ }
+ };
+ mySdkCombo.putClientProperty("JComboBox.isTableCellEditor", Boolean.TRUE);
mySdkCombo.setRenderer(new SdkListCellRenderer("<None>"));
- myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
- myProjectSdksModel = myInterpreterList.getModel();
- myListener = new MyListener(this);
- myProjectSdksModel.addListener(myListener);
- myConfigureInterpretersPanel.add(new PyConfigureInterpretersLinkPanel(myPanel), BorderLayout.CENTER);
- myInterpreterList.setSdkCombo(mySdkCombo);
+ final PackagesNotificationPanel notificationsArea = new PackagesNotificationPanel(myProject);
+ final JComponent notificationsComponent = notificationsArea.getComponent();
+ notificationsComponent.setPreferredSize(new Dimension(500, 29));
+
+ myDetailsButton = new JButton();
+ myDetailsButton.setIcon(PythonIcons.Python.InterpreterGear);
+ myDetailsButton.setIconTextGap(0);
+ myDetailsButton.setPreferredSize(new Dimension(29, 29));
+ if (((UIUtil.isUnderAquaLookAndFeel())) || UIUtil.isUnderIntelliJLaF() || UIUtil.isUnderDarcula()) {
+ myDetailsButton.putClientProperty("JButton.buttonType", "square");
+ }
+
+ myPackagesPanel = new PyInstalledPackagesPanel(myProject, notificationsArea);
+ mySdkCombo.setPreferredSize(new Dimension(250, 29));
+ final GridBagConstraints c = new GridBagConstraints();
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.insets = new Insets(2,2,2,2);
+
+ c.gridx = 0;
+ c.gridy = 0;
+ myMainPanel.add(interpreterLabel, c);
+
+ c.gridx = 1;
+ c.gridy = 0;
+ c.weightx = 0.1;
+ myMainPanel.add(mySdkCombo, c);
+
+ c.insets = new Insets(0,5,0,2);
+ c.gridx = 2;
+ c.gridy = 0;
+ c.weightx = 0.0;
+ myMainPanel.add(myDetailsButton, c);
+
+ c.insets = new Insets(2,2,2,2);
+ c.gridx = 0;
+ c.gridy = 1;
+ c.gridwidth = 3;
+ myMainPanel.add(emptyLabel, c);
+
+ c.gridx = 0;
+ c.gridy = 2;
+ c.weighty = 0.5;
+ c.gridwidth = 3;
+ c.gridheight = GridBagConstraints.RELATIVE;
+ c.fill = GridBagConstraints.BOTH;
+ myMainPanel.add(myPackagesPanel, c);
+
+ c.gridheight = GridBagConstraints.REMAINDER;
+ c.gridx = 0;
+ c.gridy = 3;
+ c.gridwidth = 3;
+
+ c.fill = GridBagConstraints.HORIZONTAL;
+ c.anchor = GridBagConstraints.SOUTH;
+
+ myMainPanel.add(notificationsComponent, c);
}
@Override
public JComponent createComponent() {
- return myPanel;
+ return myMainPanel;
}
@Override
public boolean isModified() {
final Sdk sdk = getSdk();
- return sdk != myProjectSdksModel.findSdk((Sdk)mySdkCombo.getSelectedItem());
+ final Sdk selectedItem = (Sdk)mySdkCombo.getSelectedItem();
+ return myAddedSdk != null || selectedItem instanceof PyDetectedSdk || sdk != myProjectSdksModel.findSdk(selectedItem);
}
@Nullable
@@ -102,28 +253,34 @@
@Override
public void apply() throws ConfigurationException {
- final Sdk selectedSdk = myProjectSdksModel.findSdk((Sdk)mySdkCombo.getSelectedItem());
- if (myModule == null) {
- final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ final Sdk item = (Sdk)mySdkCombo.getSelectedItem();
+ if (item instanceof PyDetectedSdk) {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
- rootManager.setProjectSdk(selectedSdk);
+ final Sdk sdk = SdkConfigurationUtil.createAndAddSDK(item.getName(), PythonSdkType.getInstance());
+ myProjectSdksModel.removeSdk(item);
+ myProjectSdksModel.addSdk(sdk);
+ updateSdkList(true);
+ mySdkCombo.setSelectedItem(sdk);
+ setSdk(sdk);
}
- });
+ }, ModalityState.any());
}
else {
- ModuleRootModificationUtil.setModuleSdk(myModule, selectedSdk);
- }
- final Sdk prevSdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
- ProjectRootManager.getInstance(myProject).setProjectSdk(selectedSdk);
+ final Sdk sdk = myProjectSdksModel.findSdk(item);
+ if (item != null && sdk == null) {
+ myProjectSdksModel.addSdk(item);
+ myProjectSdksModel.apply(null, true);
+ mySdkCombo.setSelectedItem(item);
}
- });
+ else if (myAddedSdk != null) {
+ myProjectSdksModel.apply(null, true);
+ }
+ }
- myProjectSdksModel.setProjectSdk(selectedSdk);
+ final Sdk prevSdk = ProjectRootManager.getInstance(myProject).getProjectSdk();
+ final Sdk selectedSdk = setSdk(item);
// update string literals if different LanguageLevel was selected
if (prevSdk != null && selectedSdk != null) {
@@ -141,6 +298,24 @@
rehighlightStrings(myProject);
}
+ private Sdk setSdk(Sdk item) {
+ myAddedSdk = null;
+ final Sdk selectedSdk = myProjectSdksModel.findSdk(item);
+ if (myModule == null) {
+ final ProjectRootManager rootManager = ProjectRootManager.getInstance(myProject);
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ rootManager.setProjectSdk(selectedSdk);
+ }
+ });
+ }
+ else {
+ ModuleRootModificationUtil.setModuleSdk(myModule, selectedSdk);
+ }
+ return selectedSdk;
+ }
+
public static void rehighlightStrings(final @NotNull Project project) {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
@@ -161,6 +336,14 @@
@Override
public void reset() {
+ if (myAddedSdk != null) {
+ myProjectSdksModel.removeSdk(myAddedSdk);
+ myAddedSdk = null;
+ }
+ resetSdkList();
+ }
+
+ private void resetSdkList() {
updateSdkList(false);
final Sdk sdk = getSdk();
@@ -168,37 +351,64 @@
}
private void updateSdkList(boolean preserveSelection) {
- final List<Sdk> sdkList = myInterpreterList.getAllPythonSdks();
+ final List<Sdk> sdkList = myInterpreterList.getAllPythonSdks(myProject);
Sdk selection = preserveSelection ? (Sdk)mySdkCombo.getSelectedItem() : null;
if (!sdkList.contains(selection)) {
selection = null;
}
- VirtualEnvProjectFilter.removeNotMatching(myProject, sdkList);
+ final boolean showAll = VirtualEnvProjectFilter.removeNotMatching(myProject, sdkList);
// if the selection is a non-matching virtualenv, show it anyway
if (selection != null && !sdkList.contains(selection)) {
sdkList.add(0, selection);
}
- sdkList.add(0, null);
+ List<Object> items = new ArrayList<Object>();
+ items.add(null);
+
+ boolean remoteSeparator = true;
+ boolean separator = true;
+ boolean detectedSeparator = true;
+ for (Sdk sdk : sdkList) {
+ if (!PythonSdkType.isVirtualEnv(sdk) && !PythonSdkType.isRemote(sdk) && !(sdk instanceof PyDetectedSdk) && separator) {
+ items.add(PySdkListCellRenderer.SEPARATOR);
+ separator = false;
+ }
+ if (PythonSdkType.isRemote(sdk) && remoteSeparator) {
+ items.add(PySdkListCellRenderer.SEPARATOR);
+ remoteSeparator = false;
+ }
+ if (sdk instanceof PyDetectedSdk && detectedSeparator) {
+ items.add(PySdkListCellRenderer.SEPARATOR);
+ detectedSeparator = false;
+ }
+ items.add(sdk);
+ }
+
+ if (showAll) {
+ items.add(PySdkListCellRenderer.SEPARATOR);
+ items.add(SHOW_ALL);
+ }
+
mySdkCombo.setRenderer(new PySdkListCellRenderer());
- mySdkCombo.setModel(new CollectionComboBoxModel(sdkList, selection));
+ //noinspection unchecked
+ mySdkCombo.setModel(new CollectionComboBoxModel(items, selection));
}
@Override
public void disposeUIResources() {
- myProjectSdksModel.removeListener(myListener);
+ myProjectSdksModel.removeListener(mySdkModelListener);
myInterpreterList.disposeModel();
}
- private static class MyListener implements SdkModel.Listener {
+ private static class MySdkModelListener implements SdkModel.Listener {
private final PyActiveSdkConfigurable myConfigurable;
- public MyListener(PyActiveSdkConfigurable configurable) {
+ public MySdkModelListener(PyActiveSdkConfigurable configurable) {
myConfigurable = configurable;
}
@Override
public void sdkAdded(Sdk sdk) {
- myConfigurable.reset();
+ myConfigurable.resetSdkList();
}
@Override
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkModuleConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkModuleConfigurable.java
index c3c299e..304424f 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkModuleConfigurable.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PyActiveSdkModuleConfigurable.java
@@ -18,7 +18,6 @@
import com.intellij.application.options.ModuleAwareProjectConfigurable;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.UnnamedConfigurable;
import com.intellij.openapi.project.Project;
@@ -28,17 +27,12 @@
import com.jetbrains.python.testing.VFSTestFrameworkListener;
import org.jetbrains.annotations.NotNull;
-/**
- * @author yole
- */
-public class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurable implements Configurable.Composite {
+public class PyActiveSdkModuleConfigurable extends ModuleAwareProjectConfigurable {
private final Project myProject;
- private final Configurable mySdkConfigurable;
public PyActiveSdkModuleConfigurable(Project project) {
super(project, "Project Interpreter", "reference.settings.project.interpreter");
myProject = project;
- mySdkConfigurable = new PythonSdkConfigurable(project);
}
@NotNull
@@ -67,9 +61,4 @@
}
PythonSdkUpdater.getInstance().updateActiveSdks(myProject, 0);
}
-
- @Override
- public Configurable[] getConfigurables() {
- return new Configurable[] { mySdkConfigurable };
- }
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java b/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java
index fbe1d0d..87b9163 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PyConfigurableInterpreterList.java
@@ -18,15 +18,20 @@
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
import com.intellij.openapi.util.Comparing;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.sdk.PyDetectedSdk;
+import com.jetbrains.python.sdk.PySdkUtil;
+import com.jetbrains.python.sdk.PythonSdkAdditionalData;
import com.jetbrains.python.sdk.PythonSdkType;
+import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import com.jetbrains.python.sdk.flavors.VirtualEnvSdkFlavor;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
+import java.util.*;
/**
* Manages the SDK model shared between PythonSdkConfigurable and PyActiveSdkConfigurable.
@@ -65,19 +70,77 @@
}
}
- public List<Sdk> getAllPythonSdks() {
+ public List<Sdk> getAllPythonSdks(@Nullable final Project project) {
List<Sdk> result = new ArrayList<Sdk>();
for (Sdk sdk : getModel().getSdks()) {
if (sdk.getSdkType() instanceof PythonSdkType) {
result.add(sdk);
}
}
+
Collections.sort(result, new Comparator<Sdk>() {
@Override
public int compare(Sdk o1, Sdk o2) {
+ if (!(o1.getSdkType() instanceof PythonSdkType) ||
+ !(o2.getSdkType() instanceof PythonSdkType))
+ return -Comparing.compare(o1.getName(), o2.getName());
+
+ final boolean isVEnv1 = PythonSdkType.isVirtualEnv(o1);
+ final boolean isVEnv2 = PythonSdkType.isVirtualEnv(o2);
+ final boolean isRemote1 = PySdkUtil.isRemote(o1);
+ final boolean isRemote2 = PySdkUtil.isRemote(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>();
+ sdkHomes.addAll(VirtualEnvSdkFlavor.INSTANCE.suggestHomePaths());
+ for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) {
+ if (flavor instanceof VirtualEnvSdkFlavor) continue;
+ sdkHomes.addAll(flavor.suggestHomePaths());
+ }
+
+ for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, getModel().getSdks())) {
+ result.add(new PyDetectedSdk(sdkHome));
+ }
return result;
}
+
+ private static boolean associatedWithCurrent(Sdk o1, Project project) {
+ final PythonSdkAdditionalData data = (PythonSdkAdditionalData)o1.getSdkAdditionalData();
+ if (data != null) {
+ final String path = data.getAssociatedProjectPath();
+ final String projectBasePath = project.getBasePath();
+ if (path != null && path.equals(projectBasePath)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public List<Sdk> getAllPythonSdks() {
+ return getAllPythonSdks(null);
+ }
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PyConfigureInterpretersLinkPanel.java b/python/ide/src/com/jetbrains/python/configuration/PyConfigureInterpretersLinkPanel.java
index 41c2ebe..23aa6c4 100644
--- a/python/ide/src/com/jetbrains/python/configuration/PyConfigureInterpretersLinkPanel.java
+++ b/python/ide/src/com/jetbrains/python/configuration/PyConfigureInterpretersLinkPanel.java
@@ -16,9 +16,11 @@
package com.jetbrains.python.configuration;
import com.intellij.ide.DataManager;
+import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.options.newEditor.OptionsEditor;
import com.intellij.ui.ClickListener;
import com.intellij.ui.components.JBLabel;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
@@ -36,11 +38,11 @@
myConfigureLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
new ClickListener() {
@Override
- public boolean onClick(MouseEvent e, int clickCount) {
+ public boolean onClick(@NotNull MouseEvent e, int clickCount) {
if (clickCount == 1) {
final OptionsEditor optionsEditor = OptionsEditor.KEY.getData(DataManager.getInstance().getDataContext(parentPanel));
if (optionsEditor != null) {
- PythonSdkConfigurable configurable = optionsEditor.findConfigurable(PythonSdkConfigurable.class);
+ SearchableConfigurable configurable = optionsEditor.findConfigurableById(PyActiveSdkModuleConfigurable.class.getName());
if (configurable != null) {
optionsEditor.clearSearchAndSelect(configurable);
}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonSdkConfigurable.form b/python/ide/src/com/jetbrains/python/configuration/PythonSdkConfigurable.form
deleted file mode 100644
index b1a81e8..0000000
--- a/python/ide/src/com/jetbrains/python/configuration/PythonSdkConfigurable.form
+++ /dev/null
@@ -1,32 +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.configuration.PythonSdkConfigurable">
- <grid id="27dc6" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" 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="611" height="400"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <grid id="feff7" binding="mySplitterHolder" layout-manager="BorderLayout" hgap="0" vgap="0">
- <constraints>
- <grid row="0" column="0" row-span="1" col-span="2" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <grid id="6feb9" binding="myNotificationsPlaceholder" layout-manager="BorderLayout" hgap="0" vgap="0">
- <constraints border-constraint="South"/>
- <properties>
- <background swing-color="ArrowButton.background"/>
- <minimumSize width="6" height="6"/>
- <preferredSize width="6" height="23"/>
- </properties>
- <border type="none"/>
- <children/>
- </grid>
- </children>
- </grid>
- </children>
- </grid>
-</form>
diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonSdkConfigurable.java b/python/ide/src/com/jetbrains/python/configuration/PythonSdkConfigurable.java
deleted file mode 100644
index abdfd47..0000000
--- a/python/ide/src/com/jetbrains/python/configuration/PythonSdkConfigurable.java
+++ /dev/null
@@ -1,591 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.configuration;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Sets;
-import com.intellij.CommonBundle;
-import com.intellij.icons.AllIcons;
-import com.intellij.openapi.actionSystem.AnActionEvent;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
-import com.intellij.openapi.module.Module;
-import com.intellij.openapi.module.ModuleManager;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.project.DumbAware;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.*;
-import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
-import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
-import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.roots.OrderRootType;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.Splitter;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.remotesdk.RemoteCredentials;
-import com.intellij.ui.*;
-import com.intellij.ui.components.JBList;
-import com.intellij.ui.components.JBTabbedPane;
-import com.intellij.util.Consumer;
-import com.intellij.util.NullableConsumer;
-import com.intellij.util.NullableFunction;
-import com.intellij.util.containers.FactoryMap;
-import com.intellij.webcore.packaging.PackagesNotificationPanel;
-import com.jetbrains.python.packaging.ui.PyInstalledPackagesPanel;
-import com.jetbrains.python.packaging.ui.PyPackageManagementService;
-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.*;
-import javax.swing.event.ListSelectionEvent;
-import javax.swing.event.ListSelectionListener;
-import java.awt.*;
-import java.util.*;
-import java.util.List;
-
-public class PythonSdkConfigurable implements Configurable, Configurable.NoScroll {
- private JPanel myPanel;
- private JList mySdkList;
- private JPanel mySplitterHolder;
- private PackagesNotificationPanel myNotificationsArea;
- private JPanel myNotificationsPlaceholder;
- private PythonPathEditor myPathEditor;
- private boolean mySdkListChanged = false;
- private boolean myMakeActiveAdded = false;
- private Sdk myAddedSdk;
- private final PyConfigurableInterpreterList myInterpreterList;
- private final ProjectSdksModel myProjectSdksModel;
- private final PyInstalledPackagesPanel myPackagesPanel;
-
- private Map<Sdk, SdkModificator> myModificators = new FactoryMap<Sdk, SdkModificator>() {
- @Override
- protected SdkModificator create(Sdk sdk) {
- return sdk.getSdkModificator();
- }
- };
- private Set<SdkModificator> myModifiedModificators = new HashSet<SdkModificator>();
- private Sdk myPreviousSelection;
- private boolean myFirstReset;
- private final Project myProject;
-
- private boolean myNewProject = false;
- private boolean myShowOtherProjectVirtualenvs = false;
-
- public void setNewProject(final boolean newProject) {
- myNewProject = newProject;
- }
-
- public PythonSdkConfigurable(Project project) {
- myProject = project;
- myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
- myProjectSdksModel = myInterpreterList.getModel();
- myFirstReset = true;
-
-
- mySdkList = new JBList();
- mySdkList.setCellRenderer(new PySdkListCellRenderer("", myModificators));
- mySdkList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
-
- ToolbarDecorator decorator = ToolbarDecorator.createDecorator(mySdkList).disableUpDownActions()
- .setAddAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- addSdk(button);
- }
- })
- .setEditAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- editSdk();
- }
- })
- .setRemoveAction(new AnActionButtonRunnable() {
- @Override
- public void run(AnActionButton button) {
- removeSdk();
- }
- })
- .addExtraAction(new CreateVirtualEnvButton())
- .addExtraAction(new ToggleVirtualEnvFilterButton());
-
-
- final Splitter splitter = new Splitter(true);
- /*
- final JScrollPane sdkListPane = ScrollPaneFactory.createScrollPane(mySdkList,
- ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
- ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- sdkListPane.setPreferredSize(new Dimension(10, 10));
- */
- splitter.setFirstComponent(decorator.createPanel());
-
- myPathEditor =
- new PythonPathEditor("Classes", OrderRootType.CLASSES, FileChooserDescriptorFactory.createAllButJarContentsDescriptor()) {
- @Override
- protected void onReloadButtonClicked() {
- reloadSdk();
- }
- };
-
- myNotificationsArea = new PackagesNotificationPanel(project);
- myNotificationsPlaceholder.add(myNotificationsArea.getComponent(), BorderLayout.CENTER);
-
- final JBTabbedPane tabbedPane = new JBTabbedPane(SwingConstants.TOP);
- myPackagesPanel = new PyInstalledPackagesPanel(project, myNotificationsArea);
- tabbedPane.addTab("Packages", myPackagesPanel);
-
- JPanel panel1 = new JPanel(new GridBagLayout());
- Insets anInsets1 = new Insets(2, 2, 2, 2);
- JScrollPane scrollPane1 = ScrollPaneFactory.createScrollPane(myPathEditor.createComponent(),
- ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
- ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
- scrollPane1.setPreferredSize(new Dimension(500, 500));
- panel1.add(scrollPane1, new GridBagConstraints(0, 0, 1, 8, 1.0, 1.0,
- GridBagConstraints.CENTER,
- GridBagConstraints.BOTH,
- anInsets1, 0, 0));
-
- tabbedPane.addTab("Paths", panel1);
-
- splitter.setSecondComponent(tabbedPane);
- mySplitterHolder.add(splitter, BorderLayout.CENTER);
-
- addListeners();
- }
-
- private void addListeners() {
- myProjectSdksModel.addListener(new SdkModel.Listener() {
- @Override
- public void sdkAdded(Sdk sdk) {
- }
-
- @Override
- public void beforeSdkRemove(Sdk sdk) {
- }
-
- @Override
- public void sdkChanged(Sdk sdk, String previousName) {
- refreshSdkList();
- }
-
- @Override
- public void sdkHomeSelected(Sdk sdk, String newSdkHome) {
- }
- });
- myPackagesPanel.addPathChangedListener(new Consumer<Sdk>() {
- @Override
- public void consume(Sdk sdk) {
- updateSdkPaths(sdk);
- }
- });
-
- myNotificationsArea.addLinkHandler(PyInstalledPackagesPanel.CREATE_VENV, new Runnable() {
- @Override
- public void run() {
- createVirtualEnv(getSelectedSdk());
- }
- });
- mySdkList.addListSelectionListener(new ListSelectionListener() {
- public void valueChanged(ListSelectionEvent event) {
- updateUI(getSelectedSdk());
- }
- });
- }
-
- private void updateUI(final Sdk selectedSdk) {
- if (myPreviousSelection != null) {
- saveSdkPaths(myPreviousSelection);
- }
- myProjectSdksModel.setProjectSdk(selectedSdk);
- updateSdkPaths(selectedSdk);
- myPreviousSelection = selectedSdk;
- myPackagesPanel.updatePackages(selectedSdk == null ? null : new PyPackageManagementService(myProject, selectedSdk));
-
- if (selectedSdk != null) {
- myPackagesPanel.updateNotifications(selectedSdk);
- }
- }
-
- private void createVirtualEnv(Sdk sdk) {
- CreateVirtualEnvDialog.VirtualEnvCallback callback = new CreateVirtualEnvDialog.VirtualEnvCallback() {
- @Override
- public void virtualEnvCreated(Sdk sdk, boolean associateWithProject, boolean setAsProjectInterpreter) {
- PythonSdkType.setupSdkPaths(sdk, myProject, null);
- if (associateWithProject) {
- SdkAdditionalData additionalData = sdk.getSdkAdditionalData();
- if (additionalData == null) {
- additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(sdk.getHomePath()));
- ((ProjectJdkImpl)sdk).setSdkAdditionalData(additionalData);
- }
- if (myNewProject) {
- ((PythonSdkAdditionalData)additionalData).associateWithNewProject();
- }
- else {
- ((PythonSdkAdditionalData)additionalData).associateWithProject(myProject);
- }
- }
- myMakeActiveAdded = setAsProjectInterpreter;
- addCreatedSdk(sdk, true);
- }
- };
- final List<Sdk> allSdks = PyConfigurableInterpreterList.getInstance(myProject).getAllPythonSdks();
- final CreateVirtualEnvDialog dialog = new CreateVirtualEnvDialog(myProject, myNewProject, allSdks, sdk);
- dialog.show();
- if (dialog.isOK()) {
- dialog.createVirtualEnv(allSdks, callback);
- }
- }
-
- public String getDisplayName() {
- return "Python Interpreters";
- }
-
- public String getHelpTopic() {
- return "python_interpreter";
- }
-
- public JComponent createComponent() {
- return myPanel;
- }
-
- public boolean isModified() {
- return mySdkListChanged ||
- myProjectSdksModel.isModified() ||
- myPathEditor.isModified() ||
- !myModifiedModificators.isEmpty();
- }
-
- @Nullable
- private String getSelectedSdkName() {
- final Sdk selectedSdk = (Sdk)mySdkList.getSelectedValue();
- return selectedSdk == null ? null : selectedSdk.getName();
- }
-
- public void apply() throws ConfigurationException {
- if (myPreviousSelection != null) {
- saveSdkPaths(myPreviousSelection);
- }
- for (SdkModificator modificator : myModifiedModificators) {
- modificator.commitChanges();
- }
- myModificators.clear();
- myModifiedModificators.clear();
- myProjectSdksModel.apply();
- mySdkListChanged = false;
- if (myMakeActiveAdded) {
- SdkConfigurationUtil.setDirectoryProjectSdk(myProject, myAddedSdk);
- myProjectSdksModel.setProjectSdk(myAddedSdk);
- myInterpreterList.setSelectedSdk(myAddedSdk);
- }
- }
-
- /**
- * Returns the stable copy of the SDK currently selected in the SDK table.
- *
- * @return the selected SDK, or null if there's no selection
- */
- @Nullable
- public Sdk getRealSelectedSdk() {
- return ProjectJdkTable.getInstance().findJdk(getSelectedSdkName());
- }
-
- @Nullable
- public Sdk getSelectedSdk() {
- return (Sdk)mySdkList.getSelectedValue();
- }
-
- public void reset() {
- clearModificators();
- if (myFirstReset) {
- myFirstReset = false;
- }
- else {
- myProjectSdksModel.reset(null);
- }
- refreshSdkList();
- final Sdk selectedSdk = getRealSelectedSdk();
- if (selectedSdk != null) {
- myPackagesPanel.updateNotifications(selectedSdk);
- }
- }
-
- private void clearModificators() {
- myModificators.clear();
- myModifiedModificators.clear();
- myPreviousSelection = null;
- }
-
- private void refreshSdkList() {
- final List<Sdk> pythonSdks = myInterpreterList.getAllPythonSdks();
- Sdk projectSdk = myProjectSdksModel.getProjectSdk();
- if (!myShowOtherProjectVirtualenvs) {
- VirtualEnvProjectFilter.removeNotMatching(myProject, pythonSdks);
- }
- Collections.sort(pythonSdks, new PreferredSdkComparator());
- mySdkList.setModel(new CollectionListModel<Sdk>(pythonSdks));
-
- mySdkListChanged = false;
- if (projectSdk == null) projectSdk = getSdk();
- if (projectSdk != null) {
- projectSdk = myProjectSdksModel.findSdk(projectSdk.getName());
- mySdkList.clearSelection();
- mySdkList.setSelectedValue(projectSdk, true);
- mySdkList.updateUI();
- }
- }
-
- @Nullable
- private Sdk getSdk() {
- final Module[] modules = ModuleManager.getInstance(myProject).getModules();
- if (modules.length > 0) {
- final Module module = modules[0];
- final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
- return rootManager.getSdk();
- }
- return ProjectRootManager.getInstance(myProject).getProjectSdk();
- }
-
- private void addSdk(AnActionButton button) {
- InterpreterPathChooser
- .show(myProject, myProjectSdksModel.getSdks(), button.getPreferredPopupPoint(), false, new NullableConsumer<Sdk>() {
- @Override
- public void consume(Sdk sdk) {
- myMakeActiveAdded = false;
- addCreatedSdk(sdk, false);
- }
- });
- }
-
- private void addCreatedSdk(@Nullable final Sdk sdk, boolean newVirtualEnv) {
- if (sdk != null) {
- myAddedSdk = sdk;
- boolean isVirtualEnv = PythonSdkType.isVirtualEnv(sdk);
- boolean askSetAsProjectInterpreter = !myProject.isDefault() && !myNewProject;
- if (askSetAsProjectInterpreter && isVirtualEnv && !newVirtualEnv) {
- AddVEnvOptionsDialog dialog = new AddVEnvOptionsDialog(myPanel);
- dialog.show();
- if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
- return;
- }
- SdkModificator modificator = myModificators.get(sdk);
- setSdkAssociated(modificator, !dialog.makeAvailableToAll());
- myModifiedModificators.add(modificator);
- myMakeActiveAdded = dialog.useForThisProject();
- }
- myProjectSdksModel.addSdk(sdk);
- refreshSdkList();
- mySdkList.setSelectedValue(sdk, true);
- mySdkListChanged = true;
- if (askSetAsProjectInterpreter && !isVirtualEnv && !PythonSdkType.isInvalid(sdk) && !PythonSdkType.isIncompleteRemote(sdk)) {
- //TODO: make native mac dialog work
- myMakeActiveAdded = Messages.showIdeaMessageDialog(myProject, "Do you want to set this interpreter as Project Interpreter?",
- "Project Interpreter",
- new String[]{CommonBundle.getYesButtonText(), CommonBundle.getNoButtonText()}, 0, null,
- null
- ) == Messages.YES;
- }
- }
- }
-
- private void editSdk() {
- final Sdk currentSdk = getSelectedSdk();
- if (currentSdk != null) {
- if (currentSdk.getSdkAdditionalData() instanceof RemoteCredentials) {
- editRemoteSdk(currentSdk);
- }
- else {
- editSdk(currentSdk);
- }
- updateUI(currentSdk);
- }
- }
-
- private void editRemoteSdk(Sdk currentSdk) {
- PythonRemoteInterpreterManager remoteInterpreterManager = PythonRemoteInterpreterManager.getInstance();
- if (remoteInterpreterManager != null) {
- final SdkModificator modificator = myModificators.get(currentSdk);
- Set<Sdk> existingSdks = Sets.newHashSet(myProjectSdksModel.getSdks());
- existingSdks.remove(currentSdk);
- if (remoteInterpreterManager.editSdk(myProject, modificator, existingSdks)) {
- myModifiedModificators.add(modificator);
- }
- }
- }
-
- private void editSdk(final Sdk currentSdk) {
- final SdkModificator modificator = myModificators.get(currentSdk);
- final EditSdkDialog dialog = new EditSdkDialog(myProject, modificator, new NullableFunction<String, String>() {
- @Override
- public String fun(String s) {
- if (isDuplicateSdkName(s, currentSdk)) {
- return "Please specify a unique name for the interpreter";
- }
- return null;
- }
- });
- dialog.show();
- if (dialog.isOK()) {
- final boolean pathChanged = !Comparing.equal(currentSdk.getHomePath(), dialog.getHomePath());
- if (!currentSdk.getName().equals(dialog.getName()) || pathChanged || dialog.isAssociateChanged()) {
- myModifiedModificators.add(modificator);
- modificator.setName(dialog.getName());
- modificator.setHomePath(dialog.getHomePath());
-
- if (dialog.isAssociateChanged()) {
- setSdkAssociated(modificator, dialog.associateWithProject());
- }
- if (pathChanged) {
- reloadSdk(currentSdk);
- }
- }
- }
- }
-
- private void setSdkAssociated(SdkModificator modificator, boolean isAssociated) {
- PythonSdkAdditionalData additionalData = (PythonSdkAdditionalData)modificator.getSdkAdditionalData();
- if (additionalData == null) {
- additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(modificator.getHomePath()));
- modificator.setSdkAdditionalData(additionalData);
- }
- if (isAssociated) {
- additionalData.associateWithProject(myProject);
- }
- else {
- additionalData.setAssociatedProjectPath(null);
- }
- }
-
- private boolean isDuplicateSdkName(String s, Sdk sdk) {
- for (Sdk existingSdk : myProjectSdksModel.getSdks()) {
- if (existingSdk == sdk) {
- continue;
- }
- String existingName;
- if (myModificators.containsKey(existingSdk)) {
- existingName = myModificators.get(existingSdk).getName();
- }
- else {
- existingName = existingSdk.getName();
- }
- if (existingName.equals(s)) {
- return true;
- }
- }
- return false;
- }
-
- 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);
- myModifiedModificators.remove(modificator);
- myModificators.remove(current_sdk);
- }
- refreshSdkList();
- mySdkListChanged = true;
- // TODO select initially selected SDK
- if (mySdkList.getSelectedIndex() < 0) {
- mySdkList.setSelectedIndex(0);
- }
- }
- }
-
- private void reloadSdk() {
- final Sdk currentSdk = getSelectedSdk();
- if (currentSdk != null) {
- myModifiedModificators.add(myModificators.get(currentSdk));
- reloadSdk(currentSdk);
- }
- }
-
- private void reloadSdk(Sdk currentSdk) {
- PythonSdkType.setupSdkPaths(myProject, null, currentSdk, myModificators.get(currentSdk)); // or must it be a RunWriteAction?
- reloadSdkPaths(currentSdk);
- }
-
- public void disposeUIResources() {
- myInterpreterList.disposeModel();
- clearModificators();
- myFirstReset = true;
- }
-
- private void saveSdkPaths(Sdk selection) {
- SdkModificator modificator = myModificators.get(selection);
- if (myPathEditor.isModified()) {
- myPathEditor.apply(modificator);
- myModifiedModificators.add(modificator);
- }
- }
-
- private void reloadSdkPaths(Sdk selection) {
- List<VirtualFile> rootPaths = Lists.newArrayList();
- if (selection != null) {
- Collections.addAll(rootPaths, selection.getRootProvider().getFiles(OrderRootType.CLASSES));
- myPathEditor.reload(myModificators.get(selection));
- }
- else {
- myPathEditor.reload(null);
- }
- }
-
- private void updateSdkPaths(final Sdk selection) {
- final List<VirtualFile> rootPaths = Lists.newArrayList();
- if (selection != null) {
- Collections.addAll(rootPaths, selection.getRootProvider().getFiles(OrderRootType.CLASSES));
- myPathEditor.reset(myModificators.get(selection));
- }
- else {
- myPathEditor.reset(null);
- }
- }
-
- private class CreateVirtualEnvButton extends AnActionButton implements DumbAware {
- public CreateVirtualEnvButton() {
- super("Create Virtual Environment", PythonIcons.Python.Virtualenv);
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- Sdk selectedSdk = getSelectedSdk();
- createVirtualEnv(selectedSdk);
- }
- }
-
- private class ToggleVirtualEnvFilterButton extends ToggleActionButton implements DumbAware {
- public ToggleVirtualEnvFilterButton() {
- super("Show virtual environments associated with other projects", AllIcons.General.Filter);
- }
-
- @Override
- public boolean isSelected(AnActionEvent e) {
- return myShowOtherProjectVirtualenvs;
- }
-
- @Override
- public void setSelected(AnActionEvent e, boolean state) {
- myShowOtherProjectVirtualenvs = state;
- refreshSdkList();
- }
- }
-}
diff --git a/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java
new file mode 100644
index 0000000..96d6000
--- /dev/null
+++ b/python/ide/src/com/jetbrains/python/configuration/PythonSdkDetailsDialog.java
@@ -0,0 +1,479 @@
+/*
+ * 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.google.common.collect.Sets;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+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.Sdk;
+import com.intellij.openapi.projectRoots.SdkModel;
+import com.intellij.openapi.projectRoots.SdkModificator;
+import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
+import com.intellij.openapi.roots.ModuleRootManager;
+import com.intellij.openapi.roots.OrderRootType;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel;
+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.ui.*;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.NullableConsumer;
+import com.intellij.util.NullableFunction;
+import com.intellij.util.containers.FactoryMap;
+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.*;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class PythonSdkDetailsDialog extends DialogWrapper {
+ private JPanel myMainPanel;
+ private JList mySdkList;
+ private boolean mySdkListChanged = false;
+ private final PyConfigurableInterpreterList myInterpreterList;
+ private final ProjectSdksModel myProjectSdksModel;
+
+ private Map<Sdk, SdkModificator> myModificators = new FactoryMap<Sdk, SdkModificator>() {
+ @Override
+ protected SdkModificator create(Sdk sdk) {
+ return sdk.getSdkModificator();
+ }
+ };
+ private Set<SdkModificator> myModifiedModificators = new HashSet<SdkModificator>();
+ private final Project myProject;
+
+ private boolean myShowOtherProjectVirtualenvs = true;
+ private final Module myModule;
+ private NullableConsumer<Sdk> myShowMoreCallback;
+
+ public PythonSdkDetailsDialog(Project project, NullableConsumer<Sdk> showMoreCallback) {
+ super(project);
+ myModule = null;
+
+ setTitle("Project Interpreters");
+ myShowMoreCallback = showMoreCallback;
+ myProject = project;
+ myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
+ myProjectSdksModel = myInterpreterList.getModel();
+ init();
+ updateOkButton();
+ }
+
+ public PythonSdkDetailsDialog(Module module, NullableConsumer<Sdk> showMoreCallback) {
+ super(module.getProject());
+ myModule = module;
+
+ setTitle("Project Interpreters");
+ myShowMoreCallback = showMoreCallback;
+ myProject = module.getProject();
+ myInterpreterList = PyConfigurableInterpreterList.getInstance(myProject);
+ myProjectSdksModel = myInterpreterList.getModel();
+ init();
+ updateOkButton();
+ }
+
+ @Nullable
+ @Override
+ protected JComponent createCenterPanel() {
+ mySdkList = new JBList();
+ //noinspection unchecked
+ mySdkList.setCellRenderer(new PySdkListCellRenderer("", myModificators));
+ mySdkList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+
+ ToolbarDecorator decorator = ToolbarDecorator.createDecorator(mySdkList).disableUpDownActions()
+ .setAddAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ addSdk(button);
+ updateOkButton();
+ }
+ })
+ .setEditAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ editSdk();
+ updateOkButton();
+ }
+ })
+ .setRemoveAction(new AnActionButtonRunnable() {
+ @Override
+ public void run(AnActionButton button) {
+ removeSdk();
+ updateOkButton();
+ }
+ })
+ .addExtraAction(new ToggleVirtualEnvFilterButton())
+ .addExtraAction(new ShowPathButton())
+ .addExtraAction(new GenerateSkeletonsButton());
+
+ decorator.setPreferredSize(new Dimension(600, 500));
+ myMainPanel = decorator.createPanel();
+ refreshSdkList();
+ addListeners();
+ return myMainPanel;
+ }
+
+ private void addListeners() {
+ myProjectSdksModel.addListener(new SdkModel.Listener() {
+ @Override
+ public void sdkAdded(Sdk sdk) {
+ }
+
+ @Override
+ public void beforeSdkRemove(Sdk sdk) {
+ }
+
+ @Override
+ public void sdkChanged(Sdk sdk, String previousName) {
+ refreshSdkList();
+ }
+
+ @Override
+ public void sdkHomeSelected(Sdk sdk, String newSdkHome) {
+ }
+ });
+ mySdkList.addListSelectionListener(new ListSelectionListener() {
+ public void valueChanged(ListSelectionEvent event) {
+ updateOkButton();
+ updateUI(getSelectedSdk());
+ }
+ });
+ }
+
+ private void updateUI(final Sdk selectedSdk) {
+ myProjectSdksModel.setProjectSdk(selectedSdk);
+ }
+
+ @Nullable
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return mySdkList;
+ }
+
+ public boolean isModified() {
+ Sdk projectSdk = getSdk();
+ if (projectSdk != null) {
+ projectSdk = myProjectSdksModel.findSdk(projectSdk.getName());
+ }
+ return getSelectedSdk() != projectSdk || mySdkListChanged ||
+ myProjectSdksModel.isModified() ||
+ !myModifiedModificators.isEmpty();
+ }
+
+ protected void updateOkButton() {
+ super.setOKActionEnabled(isModified());
+ }
+
+ @Override
+ protected void doOKAction() {
+ try {
+ apply();
+ }
+ catch (ConfigurationException ignored) {
+ }
+ super.doOKAction();
+ }
+
+ public void apply() throws ConfigurationException {
+ for (SdkModificator modificator : myModifiedModificators) {
+ modificator.commitChanges();
+ }
+ myModificators.clear();
+ myModifiedModificators.clear();
+ myProjectSdksModel.apply();
+ mySdkListChanged = false;
+ myShowMoreCallback.consume(getSelectedSdk());
+ }
+
+ @Nullable
+ public Sdk getSelectedSdk() {
+ return (Sdk)mySdkList.getSelectedValue();
+ }
+
+ private void refreshSdkList() {
+ final List<Sdk> pythonSdks = myInterpreterList.getAllPythonSdks(myProject);
+ Sdk projectSdk = getSdk();
+ if (!myShowOtherProjectVirtualenvs) {
+ VirtualEnvProjectFilter.removeNotMatching(myProject, pythonSdks);
+ }
+ Collections.sort(pythonSdks, new PreferredSdkComparator());
+ //noinspection unchecked
+ mySdkList.setModel(new CollectionListModel<Sdk>(pythonSdks));
+
+ mySdkListChanged = false;
+ if (projectSdk != null) {
+ projectSdk = myProjectSdksModel.findSdk(projectSdk.getName());
+ mySdkList.clearSelection();
+ mySdkList.setSelectedValue(projectSdk, true);
+ mySdkList.updateUI();
+ }
+ }
+ @Nullable
+ private Sdk getSdk() {
+ if (myModule == null) {
+ return ProjectRootManager.getInstance(myProject).getProjectSdk();
+ }
+ final ModuleRootManager rootManager = ModuleRootManager.getInstance(myModule);
+ return rootManager.getSdk();
+ }
+
+ private void addSdk(AnActionButton button) {
+ PythonSdkDetailsStep
+ .show(myProject, myProjectSdksModel.getSdks(), this, button.getPreferredPopupPoint(), false, new NullableConsumer<Sdk>() {
+ @Override
+ public void consume(Sdk sdk) {
+ addCreatedSdk(sdk, false);
+ }
+ });
+ }
+
+ private void addCreatedSdk(@Nullable final Sdk sdk, boolean newVirtualEnv) {
+ if (sdk != null) {
+ boolean isVirtualEnv = PythonSdkType.isVirtualEnv(sdk);
+ if (isVirtualEnv && !newVirtualEnv) {
+ AddVEnvOptionsDialog dialog = new AddVEnvOptionsDialog(myMainPanel);
+ dialog.show();
+ if (dialog.getExitCode() != DialogWrapper.OK_EXIT_CODE) {
+ return;
+ }
+ SdkModificator modificator = myModificators.get(sdk);
+ setSdkAssociated(modificator, !dialog.makeAvailableToAll());
+ myModifiedModificators.add(modificator);
+ }
+ final Sdk oldSdk = myProjectSdksModel.findSdk(sdk);
+ if (oldSdk == null)
+ myProjectSdksModel.addSdk(sdk);
+ refreshSdkList();
+ mySdkList.setSelectedValue(sdk, true);
+ mySdkListChanged = true;
+ }
+ }
+
+ private void editSdk() {
+ final Sdk currentSdk = getSelectedSdk();
+ if (currentSdk != null) {
+ if (currentSdk.getSdkAdditionalData() instanceof RemoteCredentials) {
+ editRemoteSdk(currentSdk);
+ }
+ else {
+ editSdk(currentSdk);
+ }
+ updateUI(currentSdk);
+ }
+ }
+
+ private void editRemoteSdk(Sdk currentSdk) {
+ PythonRemoteInterpreterManager remoteInterpreterManager = PythonRemoteInterpreterManager.getInstance();
+ if (remoteInterpreterManager != null) {
+ final SdkModificator modificator = myModificators.get(currentSdk);
+ Set<Sdk> existingSdks = Sets.newHashSet(myProjectSdksModel.getSdks());
+ existingSdks.remove(currentSdk);
+ if (remoteInterpreterManager.editSdk(myProject, modificator, existingSdks)) {
+ myModifiedModificators.add(modificator);
+ }
+ }
+ }
+
+ private void editSdk(final Sdk currentSdk) {
+ final SdkModificator modificator = myModificators.get(currentSdk);
+ final EditSdkDialog dialog = new EditSdkDialog(myProject, modificator, new NullableFunction<String, String>() {
+ @Override
+ public String fun(String s) {
+ if (isDuplicateSdkName(s, currentSdk)) {
+ return "Please specify a unique name for the interpreter";
+ }
+ return null;
+ }
+ });
+ dialog.show();
+ if (dialog.isOK()) {
+ final boolean pathChanged = !Comparing.equal(currentSdk.getHomePath(), dialog.getHomePath());
+ if (!currentSdk.getName().equals(dialog.getName()) || pathChanged || dialog.isAssociateChanged()) {
+ myModifiedModificators.add(modificator);
+ modificator.setName(dialog.getName());
+ modificator.setHomePath(dialog.getHomePath());
+
+ if (dialog.isAssociateChanged()) {
+ setSdkAssociated(modificator, dialog.associateWithProject());
+ }
+ if (pathChanged) {
+ reloadSdk(currentSdk);
+ }
+ }
+ }
+ }
+
+ private void setSdkAssociated(SdkModificator modificator, boolean isAssociated) {
+ PythonSdkAdditionalData additionalData = (PythonSdkAdditionalData)modificator.getSdkAdditionalData();
+ if (additionalData == null) {
+ additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(modificator.getHomePath()));
+ modificator.setSdkAdditionalData(additionalData);
+ }
+ if (isAssociated) {
+ additionalData.associateWithProject(myProject);
+ }
+ else {
+ additionalData.setAssociatedProjectPath(null);
+ }
+ }
+
+ private boolean isDuplicateSdkName(String s, Sdk sdk) {
+ for (Sdk existingSdk : myProjectSdksModel.getSdks()) {
+ if (existingSdk == sdk) {
+ continue;
+ }
+ String existingName;
+ if (myModificators.containsKey(existingSdk)) {
+ existingName = myModificators.get(existingSdk).getName();
+ }
+ else {
+ existingName = existingSdk.getName();
+ }
+ if (existingName.equals(s)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ 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);
+ myModifiedModificators.remove(modificator);
+ myModificators.remove(current_sdk);
+ }
+ refreshSdkList();
+ mySdkListChanged = true;
+ // TODO select initially selected SDK
+ if (mySdkList.getSelectedIndex() < 0) {
+ mySdkList.setSelectedIndex(0);
+ }
+ }
+ }
+
+ private void reloadSdk() {
+ final Sdk currentSdk = getSelectedSdk();
+ if (currentSdk != null) {
+ myModifiedModificators.add(myModificators.get(currentSdk));
+ reloadSdk(currentSdk);
+ }
+ }
+
+ private void reloadSdk(Sdk currentSdk) {
+ PythonSdkType.setupSdkPaths(myProject, null, currentSdk, myModificators.get(currentSdk)); // or must it be a RunWriteAction?
+ }
+
+ private class ToggleVirtualEnvFilterButton extends ToggleActionButton implements DumbAware {
+ public ToggleVirtualEnvFilterButton() {
+ super("Show virtual environments associated with other projects", AllIcons.General.Filter);
+ }
+
+ @Override
+ public boolean isSelected(AnActionEvent e) {
+ return myShowOtherProjectVirtualenvs;
+ }
+
+ @Override
+ public void setSelected(AnActionEvent e, boolean state) {
+ myShowOtherProjectVirtualenvs = state;
+ refreshSdkList();
+ updateOkButton();
+ }
+ }
+
+ private class ShowPathButton extends AnActionButton implements DumbAware {
+ public ShowPathButton() {
+ super("Show path for the selected interpreter", AllIcons.Actions.ShowAsTree);
+ }
+
+ @Override
+ public boolean isEnabled() {
+ return !(getSelectedSdk() instanceof PyDetectedSdk);
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ DialogBuilder dialog = new DialogBuilder(myProject);
+
+ final PythonPathEditor editor =
+ new PythonPathEditor("Classes", OrderRootType.CLASSES, FileChooserDescriptorFactory.createAllButJarContentsDescriptor()) {
+ @Override
+ protected void onReloadButtonClicked() {
+ reloadSdk();
+ }
+ };
+ final JComponent component = editor.createComponent();
+ component.setPreferredSize(new Dimension(600, 400));
+ component.setBorder(IdeBorderFactory.createBorder(SideBorder.ALL));
+ dialog.setCenterPanel(component);
+ final Sdk sdk = getSelectedSdk();
+ editor.reload(sdk != null ? sdk.getSdkModificator(): null);
+
+ dialog.setTitle("Interpreter Paths");
+ dialog.show();
+ 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/configuration/VirtualEnvProjectFilter.java b/python/ide/src/com/jetbrains/python/configuration/VirtualEnvProjectFilter.java
index 1caf4c3..c8dc610 100644
--- a/python/ide/src/com/jetbrains/python/configuration/VirtualEnvProjectFilter.java
+++ b/python/ide/src/com/jetbrains/python/configuration/VirtualEnvProjectFilter.java
@@ -50,13 +50,14 @@
return false;
}
- public static void removeNotMatching(Project project, List<Sdk> sdks) {
+ public static boolean removeNotMatching(Project project, List<Sdk> sdks) {
if (project != null) {
final String basePath = project.getBasePath();
if (basePath != null) {
- Iterables.removeIf(sdks, new VirtualEnvProjectFilter(FileUtil.toSystemIndependentName(basePath)));
+ return Iterables.removeIf(sdks, new VirtualEnvProjectFilter(FileUtil.toSystemIndependentName(basePath)));
}
}
+ return false;
}
public static void removeAllAssociated(List<Sdk> sdks) {
diff --git a/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectAction.java b/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectAction.java
index 4496b6d..4d638ee 100644
--- a/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectAction.java
+++ b/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectAction.java
@@ -27,6 +27,7 @@
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.platform.DirectoryProjectGenerator;
import com.intellij.platform.NewDirectoryProjectAction;
+import com.jetbrains.python.sdk.PyDetectedSdk;
import com.jetbrains.python.sdk.PythonSdkAdditionalData;
import com.jetbrains.python.sdk.PythonSdkType;
@@ -48,6 +49,9 @@
dlg.show();
if (dlg.getExitCode() != DialogWrapper.OK_EXIT_CODE) return;
mySdk = dlg.getSdk();
+ if (mySdk instanceof PyDetectedSdk) {
+ mySdk = SdkConfigurationUtil.createAndAddSDK(mySdk.getName(), PythonSdkType.getInstance());
+ }
myInstallFramework = dlg.installFramework();
Project newProject = generateProject(project, dlg);
if (newProject != null) {
diff --git a/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java b/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java
index 4b05b73..8db6add 100644
--- a/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java
+++ b/python/ide/src/com/jetbrains/python/newProject/PythonNewDirectoryProjectDialog.java
@@ -31,6 +31,7 @@
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBLabel;
import com.jetbrains.python.PythonSdkChooserCombo;
+import com.jetbrains.python.configuration.PyConfigurableInterpreterList;
import com.jetbrains.python.configuration.VirtualEnvProjectFilter;
import com.jetbrains.python.packaging.PyExternalProcessException;
import com.jetbrains.python.packaging.PyPackage;
@@ -38,7 +39,6 @@
import com.jetbrains.python.packaging.PyPackageManagerImpl;
import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
import com.jetbrains.python.remote.RemoteProjectSettings;
-import com.jetbrains.python.sdk.PreferredSdkComparator;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.flavors.JythonSdkFlavor;
import com.jetbrains.python.sdk.flavors.PyPySdkFlavor;
@@ -53,7 +53,6 @@
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
-import java.util.Collections;
import java.util.List;
/**
@@ -69,9 +68,8 @@
super(project);
myProject = project;
- final List<Sdk> sdks = PythonSdkType.getAllSdks();
+ final List<Sdk> sdks = PyConfigurableInterpreterList.getInstance(myProject).getAllPythonSdks();
VirtualEnvProjectFilter.removeAllAssociated(sdks);
- Collections.sort(sdks, PreferredSdkComparator.INSTANCE);
final Sdk preferred = sdks.isEmpty() ? null : sdks.iterator().next();
mySdkCombo = new PythonSdkChooserCombo(project, sdks, new Condition<Sdk>() {
@Override
diff --git a/python/openapi/python-openapi.iml b/python/openapi/python-openapi.iml
index 690468a..9ac91c1 100644
--- a/python/openapi/python-openapi.iml
+++ b/python/openapi/python-openapi.iml
@@ -12,7 +12,6 @@
<orderEntry type="module" module-name="lang-api" />
<orderEntry type="module" module-name="lang-impl" />
<orderEntry type="library" name="Guava" level="project" />
- <orderEntry type="module" module-name="webide-impl" exported="" />
</component>
</module>
diff --git a/python/openapi/src/com/jetbrains/python/psi/RootFileReferenceSet.java b/python/openapi/src/com/jetbrains/python/psi/RootFileReferenceSet.java
index 36cf4d2..8fd92a3 100644
--- a/python/openapi/src/com/jetbrains/python/psi/RootFileReferenceSet.java
+++ b/python/openapi/src/com/jetbrains/python/psi/RootFileReferenceSet.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,20 +15,20 @@
*/
package com.jetbrains.python.psi;
-import com.google.common.collect.Lists;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.*;
+import com.intellij.openapi.vfs.newvfs.ManagingFS;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiFileSystemItem;
+import com.intellij.psi.PsiReferenceProvider;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
-import com.jetbrains.python.psi.PyStringLiteralExpression;
+import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collection;
-import java.util.Collections;
/**
* Resolves absolute paths from FS root, not content roots
@@ -41,7 +41,8 @@
int startInElement,
PsiReferenceProvider provider,
boolean caseSensitive,
- boolean endingSlashNotAllowed, @Nullable FileType[] suitableFileTypes) {
+ boolean endingSlashNotAllowed,
+ @Nullable FileType[] suitableFileTypes) {
super(str, element, startInElement, provider, caseSensitive, endingSlashNotAllowed, suitableFileTypes);
}
@@ -49,6 +50,7 @@
super(s, element, offset, provider, sensitive);
}
+ @Override
public boolean isAbsolutePathReference() {
if (!ApplicationManager.getApplication().isUnitTestMode()) {
return FileUtil.isAbsolute(getPathString());
@@ -61,26 +63,13 @@
@NotNull
@Override
public Collection<PsiFileSystemItem> computeDefaultContexts() {
- final PsiFile file = getContainingFile();
- if (file != null) {
+ PsiFile file = getContainingFile();
+ if (file == null) return ContainerUtil.emptyList();
- if (isAbsolutePathReference()) {
- if (!ApplicationManager.getApplication().isUnitTestMode()) {
- VirtualFile root = LocalFileSystem.getInstance().getRoot();
- PsiDirectory directory = file.getManager().findDirectory(root);
- if (directory != null) {
- return Lists.<PsiFileSystemItem>newArrayList(directory);
- }
- }
- else {
- return super.computeDefaultContexts();
- }
- }
- else {
- return super.computeDefaultContexts();
- }
+ if (isAbsolutePathReference() && !ApplicationManager.getApplication().isUnitTestMode()) {
+ return toFileSystemItems(ManagingFS.getInstance().getLocalRoots());
}
- return Collections.emptyList();
+ return super.computeDefaultContexts();
}
}
diff --git a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java
index a7ea147..84760d8 100644
--- a/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java
+++ b/python/openapi/src/com/jetbrains/python/templateLanguages/TemplateFileReference.java
@@ -16,7 +16,6 @@
package com.jetbrains.python.templateLanguages;
import com.intellij.lang.injection.InjectedLanguageManager;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
@@ -26,7 +25,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceHelper;
-import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceHelperRegistrar;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.PsiFileSystemItemUtil;
import com.intellij.util.IncorrectOperationException;
@@ -66,17 +64,13 @@
final VirtualFile curVFile = file.getVirtualFile();
if (curVFile == null) throw new IncorrectOperationException("Cannot bind from non-physical element:" + file);
- final Project project = element.getProject();
-
String newName;
PsiFileSystemItem curItem = null;
PsiFileSystemItem dstItem = null;
- final FileReferenceHelper helper = FileReferenceHelperRegistrar.getNotNullHelper(file);
-
- PsiFileSystemItem _dstItem = helper.getPsiFileSystemItem(project, dstVFile);
- PsiFileSystemItem _curItem = helper.getPsiFileSystemItem(project, curVFile);
+ PsiFileSystemItem _dstItem = FileReferenceHelper.getPsiFileSystemItem(file.getManager(), dstVFile);
+ PsiFileSystemItem _curItem = FileReferenceHelper.getPsiFileSystemItem(file.getManager(), curVFile);
if (_dstItem != null && _curItem != null) {
curItem = _curItem;
dstItem = _dstItem;
diff --git a/python/pluginResources/META-INF/plugin.xml b/python/pluginResources/META-INF/plugin.xml
index f65099c..e3aa06f 100644
--- a/python/pluginResources/META-INF/plugin.xml
+++ b/python/pluginResources/META-INF/plugin.xml
@@ -4,9 +4,9 @@
<id>PythonCore</id>
<name>Python Community Edition</name>
- <idea-version since-build="133.471" until-build="133.*"/>
+ <idea-version since-build="134.1007" until-build="134.*"/>
<description>Smart editing for Python scripts</description>
- <version>3.1 Beta 3</version>
+ <version>3.1.1.134.@@BUILD_NUMBER@@</version>
<depends>com.intellij.modules.java</depends>
diff --git a/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java b/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java
index 45dd7cd..35898c7 100644
--- a/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java
+++ b/python/pluginSrc/com/jetbrains/python/module/PyProjectStructureDetector.java
@@ -15,20 +15,21 @@
*/
package com.jetbrains.python.module;
-import com.intellij.ide.util.importProject.ModuleDescriptor;
import com.intellij.ide.util.importProject.ProjectDescriptor;
import com.intellij.ide.util.projectWizard.ModuleWizardStep;
import com.intellij.ide.util.projectWizard.ProjectWizardStepFactory;
+import com.intellij.ide.util.projectWizard.importSources.DetectedContentRoot;
import com.intellij.ide.util.projectWizard.importSources.DetectedProjectRoot;
import com.intellij.ide.util.projectWizard.importSources.ProjectFromSourcesBuilder;
import com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.WebModuleType;
import com.intellij.openapi.util.io.FileUtilRt;
+import com.jetbrains.python.PythonModuleTypeBase;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.io.File;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -50,13 +51,7 @@
for (File child : children) {
if (FileUtilRt.extensionEquals(child.getName(), "py")) {
LOG.info("Found Python file " + child.getPath());
- result.add(new DetectedProjectRoot(dir) {
- @NotNull
- @Override
- public String getRootTypeName() {
- return "Python";
- }
- });
+ result.add(new DetectedContentRoot(dir, "Python", PythonModuleTypeBase.getInstance(), WebModuleType.getInstance()));
return DirectoryProcessingResult.SKIP_CHILDREN;
}
}
@@ -67,16 +62,7 @@
public void setupProjectStructure(@NotNull Collection<DetectedProjectRoot> roots,
@NotNull ProjectDescriptor projectDescriptor,
@NotNull ProjectFromSourcesBuilder builder) {
- if (!roots.isEmpty() && !builder.hasRootsFromOtherDetectors(this)) {
- List<ModuleDescriptor> modules = projectDescriptor.getModules();
- if (modules.isEmpty()) {
- modules = new ArrayList<ModuleDescriptor>();
- for (DetectedProjectRoot root : roots) {
- modules.add(new ModuleDescriptor(root.getDirectory(), PythonModuleType.getInstance(), root));
- }
- projectDescriptor.setModules(modules);
- }
- }
+ builder.setupModulesByContentRoots(projectDescriptor, roots);
}
@Override
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 55a6506..5ba21bf 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyArgumentList.java
@@ -27,12 +27,25 @@
*/
public interface PyArgumentList extends PyElement {
- @NotNull PyExpression[] getArguments();
+ @NotNull
+ PyExpression[] getArguments();
- @Nullable PyKeywordArgument getKeywordArgument(String name);
+ @Nullable
+ PyKeywordArgument getKeywordArgument(String name);
- void addArgument(PyExpression arg);
+ /**
+ * TODO: Copy/Paste with {@link com.jetbrains.python.psi.PyCallExpression#addArgument(PyExpression)} ?
+ * Adds argument to the appropriate place:
+ * {@link com.jetbrains.python.psi.PyKeywordArgument} goes to the end.
+ * All other go before key arguments (if any) but after last non-key arguments.
+ * Commas should be set correctly as well.
+ *
+ * @param arg argument to add
+ */
+ void addArgument(@NotNull PyExpression arg);
+
void addArgumentFirst(PyExpression arg);
+
void addArgumentAfter(PyExpression argument, PyExpression afterThis);
/**
@@ -43,9 +56,10 @@
/**
* Tries to map the argument list to callee's idea of parameters.
- * @return a result object with mappings and diagnostic flags.
+ *
* @param resolveContext the reference resolution context
* @param implicitOffset known from the context implicit offset
+ * @return a result object with mappings and diagnostic flags.
*/
@NotNull
CallArgumentsMapping analyzeCall(PyResolveContext resolveContext, int implicitOffset);
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java b/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java
index 41d93bf..71e31dd 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyCallExpression.java
@@ -68,6 +68,10 @@
@Nullable
PyExpression getKeywordArgument(String keyword);
+ /**
+ * TODO: Copy/Paste with {@link com.jetbrains.python.psi.PyArgumentList#addArgument(PyExpression)}
+ * @param expression
+ */
void addArgument(PyExpression expression);
/**
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 53dd81a..389b0f2 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyClass.java
@@ -36,7 +36,7 @@
* Represents a class declaration in source.
*/
public interface PyClass extends PsiNameIdentifierOwner, PyStatement, NameDefiner, PyDocStringOwner, StubBasedPsiElement<PyClassStub>,
- ScopeOwner, PyDecoratable, PyTypedElement, PyQualifiedNameOwner {
+ ScopeOwner, PyDecoratable, PyTypedElement, PyQualifiedNameOwner, PyStatementListContainer {
ArrayFactory<PyClass> ARRAY_FACTORY = new ArrayFactory<PyClass>() {
@NotNull
@Override
@@ -48,8 +48,6 @@
@Nullable
ASTNode getNameNode();
- @NotNull
- PyStatementList getStatementList();
/**
* Returns types of all ancestors from the hierarchy.
@@ -155,6 +153,7 @@
List<PyTargetExpression> getClassAttributes();
+ @Nullable
PyTargetExpression findClassAttribute(@NotNull String name, boolean inherited);
List<PyTargetExpression> getInstanceAttributes();
@@ -219,6 +218,7 @@
boolean processClassLevelDeclarations(@NotNull PsiScopeProcessor processor);
boolean processInstanceLevelDeclarations(@NotNull PsiScopeProcessor processor, @Nullable PsiElement location);
+ //TODO: Add "addMetaClass" or move methods out of here
/**
* Returns the type representing the metaclass of the class if it is explicitly set, null otherwise.
*/
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
index 75a0bbc..568cb95 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyElementGenerator.java
@@ -67,6 +67,21 @@
public abstract PyExpression createExpressionFromText(final LanguageLevel languageLevel, String text);
+ /**
+ * Adds elements to list inserting required commas.
+ * Method is like {@link #insertItemIntoList(PyElement, PyExpression, PyExpression)} but does not add unneeded commas.
+ *
+ * @param list where to add
+ * @param afterThis after which element it should be added (null for add to the head)
+ * @param toInsert what to insert
+ * @return newly inserted element
+ */
+ @NotNull
+ public abstract PsiElement insertItemIntoListRemoveRedundantCommas(
+ @NotNull PyElement list,
+ @Nullable PyExpression afterThis,
+ @NotNull PyExpression toInsert);
+
public abstract PsiElement insertItemIntoList(PyElement list, @Nullable PyExpression afterThis, PyExpression toInsert)
throws IncorrectOperationException;
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java b/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java
index cb43d38..e70a7ad 100644
--- a/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyFunction.java
@@ -34,7 +34,8 @@
public interface PyFunction
extends
PsiNamedElement, StubBasedPsiElement<PyFunctionStub>,
- PsiNameIdentifierOwner, PyStatement, Callable, NameDefiner, PyDocStringOwner, ScopeOwner, PyDecoratable, PyTypedElement {
+ PsiNameIdentifierOwner, PyStatement, Callable, NameDefiner, PyDocStringOwner, ScopeOwner, PyDecoratable, PyTypedElement,
+ PyStatementListContainer{
PyFunction[] EMPTY_ARRAY = new PyFunction[0];
ArrayFactory<PyFunction> ARRAY_FACTORY = new ArrayFactory<PyFunction>() {
@@ -55,9 +56,6 @@
ASTNode getNameNode();
@Nullable
- PyStatementList getStatementList();
-
- @Nullable
PyClass getContainingClass();
@Nullable
diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java b/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java
new file mode 100644
index 0000000..3c4cd2c
--- /dev/null
+++ b/python/psi-api/src/com/jetbrains/python/psi/PyStatementListContainer.java
@@ -0,0 +1,11 @@
+package com.jetbrains.python.psi;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public interface PyStatementListContainer {
+ @NotNull
+ PyStatementList getStatementList();
+}
diff --git a/python/pydevSrc/com/jetbrains/python/console/pydev/PydevXmlRpcClient.java b/python/pydevSrc/com/jetbrains/python/console/pydev/PydevXmlRpcClient.java
index 695704f..ad9991f 100644
--- a/python/pydevSrc/com/jetbrains/python/console/pydev/PydevXmlRpcClient.java
+++ b/python/pydevSrc/com/jetbrains/python/console/pydev/PydevXmlRpcClient.java
@@ -1,17 +1,12 @@
package com.jetbrains.python.console.pydev;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.SystemInfo;
import com.intellij.util.net.NetUtils;
import org.apache.xmlrpc.*;
-import java.io.IOException;
-import java.io.PrintWriter;
import java.net.MalformedURLException;
-import java.net.Socket;
import java.net.URL;
import java.util.Arrays;
-import java.util.Scanner;
import java.util.Vector;
/**
@@ -25,12 +20,12 @@
/**
* Internal xml-rpc client (responsible for the actual communication with the server)
*/
- private XmlRpcClient impl;
+ private final XmlRpcClient impl;
/**
* The process where the server is being executed.
*/
- private Process process;
+ private final Process process;
/**
* ItelliJ Logging
@@ -43,15 +38,9 @@
/**
* Constructor (see fields description)
*/
- public PydevXmlRpcClient(Process process, int port)
- throws MalformedURLException {
-
- String hostname = NetUtils.getLocalHostString();
-
- URL url = new URL("http://" + hostname + ':' + port + "/RPC2");
-
- XmlRpc.setDefaultInputEncoding("UTF8"); //eventhough it uses UTF anyway
- this.impl = new XmlRpcClientLite(url);
+ public PydevXmlRpcClient(Process process, int port) throws MalformedURLException {
+ XmlRpc.setDefaultInputEncoding("UTF8"); //even though it uses UTF anyway
+ impl = new XmlRpcClientLite(NetUtils.getLocalHostString(), port);
//this.impl = new XmlRpcClient(url, new CommonsXmlRpcTransportFactory(url));
this.process = process;
}
@@ -64,16 +53,19 @@
*
* @return the result from executing the given command in the server.
*/
+ @Override
public Object execute(String command, Object[] args) throws XmlRpcException {
final Object[] result = new Object[]{null};
//make an async call so that we can keep track of not actually having an answer.
- this.impl.executeAsync(command, new Vector(Arrays.asList(args)), new AsyncCallback() {
+ impl.executeAsync(command, new Vector(Arrays.asList(args)), new AsyncCallback() {
+ @Override
public void handleError(Exception error, URL url, String method) {
result[0] = new Object[]{error.getMessage()};
}
+ @Override
public void handleResult(Object recievedResult, URL url, String method) {
result[0] = recievedResult;
}
diff --git a/python/python-plugin-tests.iml b/python/python-plugin-tests.iml
index 3269555..8045894 100644
--- a/python/python-plugin-tests.iml
+++ b/python/python-plugin-tests.iml
@@ -13,7 +13,6 @@
<orderEntry type="module" module-name="testFramework-java" />
<orderEntry type="library" scope="TEST" name="JUnit3" level="project" />
<orderEntry type="module" module-name="java-impl" />
- <orderEntry type="module" module-name="jam-support-impl" scope="RUNTIME" />
<orderEntry type="module" module-name="IntelliLang-java" scope="RUNTIME" />
<orderEntry type="module" module-name="python-community-tests" />
<orderEntry type="module" module-name="python-community-plugin" />
diff --git a/python/resources/icon-robots.txt b/python/resources/icon-robots.txt
index e1ca585..e9cf8c7 100644
--- a/python/resources/icon-robots.txt
+++ b/python/resources/icon-robots.txt
@@ -1,2 +1,3 @@
# Only has artwork and tips stuff
-skip: *
+skip: *.png
+skip: tips
diff --git a/python/resources/icons/com/jetbrains/python/interpreterGear.png b/python/resources/icons/com/jetbrains/python/interpreterGear.png
new file mode 100644
index 0000000..448474a
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/interpreterGear.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/interpreterGear@2x.png b/python/resources/icons/com/jetbrains/python/interpreterGear@2x.png
new file mode 100644
index 0000000..fe190f2
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/interpreterGear@2x.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/interpreterGear@2x_dark.png b/python/resources/icons/com/jetbrains/python/interpreterGear@2x_dark.png
new file mode 100644
index 0000000..2d77aac
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/interpreterGear@2x_dark.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/interpreterGear_dark.png b/python/resources/icons/com/jetbrains/python/interpreterGear_dark.png
new file mode 100644
index 0000000..44e79af
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/interpreterGear_dark.png
Binary files differ
diff --git a/python/resources/icons/com/jetbrains/python/skeleton.png b/python/resources/icons/com/jetbrains/python/skeleton.png
new file mode 100644
index 0000000..5b50602
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/skeleton.png
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
new file mode 100644
index 0000000..313b024
--- /dev/null
+++ b/python/resources/icons/com/jetbrains/python/skeleton@2x.png
Binary files differ
diff --git a/python/resources/idea/PyCharmCoreApplicationInfo.xml b/python/resources/idea/PyCharmCoreApplicationInfo.xml
index 3e6d9a6..ef906b0 100644
--- a/python/resources/idea/PyCharmCoreApplicationInfo.xml
+++ b/python/resources/idea/PyCharmCoreApplicationInfo.xml
@@ -1,6 +1,6 @@
<component>
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
- <version major="3" minor="1" eap="false"/>
+ <version major="3" minor="0" eap="true"/>
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
<logo url="/pycharm_core_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
<about url="/pycharm_core_about.png" logoX="300" logoY="265" logoW="75" logoH="30" foreground="ffffff" linkColor="fca11a"/>
diff --git a/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html b/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html
index 96be990..63818e3 100644
--- a/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html
+++ b/python/resources/intentionDescriptions/ImportFromToImportIntention/description.html
@@ -1,7 +1,7 @@
<html>
<body>
<span style="font-family: verdana,sans-serif;">
-This instenton transforms <code>from module_name import ...</code> into <code>import module_name</code>
+This intention transforms <code>from module_name import ...</code> into <code>import module_name</code>
and qualifies any names imported from that module by module name.
</span>
</body>
diff --git a/python/resources/tips/ShowHideSideBars.html b/python/resources/tips/ShowHideSideBars.html
index b745098..d39e28f 100644
--- a/python/resources/tips/ShowHideSideBars.html
+++ b/python/resources/tips/ShowHideSideBars.html
Binary files differ
diff --git a/python/resources/tips/Terminal.html b/python/resources/tips/Terminal.html
index 0946f5b..fcebc65 100644
--- a/python/resources/tips/Terminal.html
+++ b/python/resources/tips/Terminal.html
@@ -5,7 +5,7 @@
<body>
- <p>You don't need to leave PyCharm to work with your favorite shell. Just choose
+ <p>You don't need to leave <span class="product">&productName;</span> to work with your favorite shell. Just choose
<span class="control">Tools | Open Terminal</span> on the main menu,
and enjoy using the embedded local terminal. </p>
<p class="image"><img src="images/terminal.png"></p>
diff --git a/python/resources/tips/images/reopen.png b/python/resources/tips/images/reopen.png
new file mode 100644
index 0000000..3cdb2df
--- /dev/null
+++ b/python/resources/tips/images/reopen.png
Binary files differ
diff --git a/python/resources/tips/images/reopen@2x.png b/python/resources/tips/images/reopen@2x.png
new file mode 100644
index 0000000..a0b61f5
--- /dev/null
+++ b/python/resources/tips/images/reopen@2x.png
Binary files differ
diff --git a/python/resources/tips/images/reopen@2x_dark.png b/python/resources/tips/images/reopen@2x_dark.png
new file mode 100644
index 0000000..ed33d6e
--- /dev/null
+++ b/python/resources/tips/images/reopen@2x_dark.png
Binary files differ
diff --git a/python/resources/tips/images/reopen_dark.png b/python/resources/tips/images/reopen_dark.png
new file mode 100644
index 0000000..af7ba67
--- /dev/null
+++ b/python/resources/tips/images/reopen_dark.png
Binary files differ
diff --git a/python/resources/tips/tips.xml b/python/resources/tips/tips.xml
deleted file mode 100644
index 5ef9341..0000000
--- a/python/resources/tips/tips.xml
+++ /dev/null
@@ -1,112 +0,0 @@
-<tips>
- <tip file="Welcome.html"/>
- <tip file="MultipleProjects.html"/>
- <tip file="GoToClass.html"/>
- <tip file="CodeCompletion.html"/>
- <tip file="ClassNameCompletion.html"/>
- <tip file="FindUsages.html"/>
- <tip file="QuickJavaDoc.html"/>
- <tip file="GoToDeclaration.html"/>
- <tip file="FileStructurePopup.html"/>
- <tip file="Rename.html"/>
- <tip file="TabInLookups.html"/>
- <tip file="TabInEditorClose.html"/>
- <tip file="SelectIn.html"/>
- <tip file="SpeedSearch.html"/>
- <tip file="Escape.html"/>
- <tip file="CtrlW.html"/>
- <tip file="ExtractVariable.html"/>
- <tip file="CtrlD.html"/>
- <tip file="MoveUpDown.html"/>
- <tip file="JoinLines.html"/>
- <tip file="ParameterInfo.html"/>
- <tip file="JumpToLastEdit.html"/>
- <tip file="HighlightUsagesInFile.html"/>
- <tip file="LocalVCS.html"/>
- <tip file="RecentFiles.html"/>
- <tip file="MethodSeparators.html"/>
- <tip file="CodeCompletionMiddle.html"/>
- <tip file="MethodUpDown.html"/>
- <tip file="ClipboardStack.html"/>
- <tip file="QuickJavaDocInLookups.html"/>
- <tip file="OverrideImplementMethods.html"/>
- <tip file="MenuItemsDescriptions.html"/>
- <tip file="GoToSymbol.html"/>
- <tip file="RecentChanges.html"/>
- <tip file="ImageFileCompletion.html"/>
- <tip file="QuickSwitchScheme.html"/>
- <tip file="CamelPrefixesInNavigationPopups.html"/>
- <tip file="ColumnSelection.html"/>
- <tip file="PyColorFiles.html"/>
- <tip file="CopyWithNoSelection.html"/>
- <tip file="MoveToChangelist.html"/>
- <tip file="moveFileToChangelist.html"/>
- <tip file="ShowUsages.html"/>
- <tip file="GoToAction.html"/>
- <tip file="GoToInspection.html"/>
- <tip file="SearchInSettings.html"/>
- <tip file="SelectRunDebugConfiguration.html"/>
- <tip file="ShowAppliedStyles.html"/>
- <tip file="ImagesLookup.html"/>
- <tip file="RenameCssSelector.html"/>
- <tip file="ColorEditingInCss.html"/>
- <tip file="Spellchecker.html"/>
- <tip file="SpellcheckerDictionaries.html"/>
- <tip file="TagNameCompletion.html"/>
- <tip file="WildcardsInNavigationPopups.html"/>
- <tip file="VcsQuickList.html"/>
- <tip file="Comment.html"/>
- <tip file="NavBar.html"/>
- <tip file="ChangesView.html"/>
- <tip file="Surround.html"/>
- <tip file="Consoles.html"/>
- <tip file="ConsolesCodeCompletion.html"/>
- <tip file="ConsolesHistory.html"/>
- <tip file="QuickFixRightArrow.html"/>
- <tip file="NavigateToFilePath.html"/>
- <tip file="IssueNavigation.html"/>
- <tip file="Managepy.html"/>
- <tip file="Templates.html"/>
- <tip file="Switcher.html"/>
- <tip file="DragToOpen.html"/>
- <tip file="CloseOthers.html"/>
- <tip file="EnterDirectoryInGotoFile.html"/>
- <tip file="GotoLineInFile.html"/>
- <tip file="LineEndings.html"/>
- <tip file="LineEndingsFolder.html"/>
- <tip file="HierarchyBrowser.html"/>
- <tip file="ShowHideSideBars.html"/>
- <tip file="ExcludeFromProject.html"/>
- <tip file="CodeCompletionNoShift.html"/>
- <tip file="CommitCtrlK.html"/>
- <tip file="FindReplaceToggle.html"/>
- <tip file="ScopesInTODO.html"/>
- <tip file="PreviewTODO.html"/>
- <tip file="SelectTasks.html"/>
- <tip file="RunConfigFolders.html"/>
- <tip file="LiveTemplatesDjango.html"/>
- <tip file="LiveTemplates.html"/>
- <tip file="SpeedSearchinLiveTemplates.html"/>
- <tip file="LaunchConsole.html"/>
- <tip file="Interpreter.html"/>
- <tip file="RemoteInterpreter.html"/>
- <tip file="BreakpointSpeedmenu.html"/>
- <tip file="BuiltInServer.html"/>
- <tip file="ConfiguringTerminal.html"/>
- <tip file="Terminal.html"/>
- <tip file="SearchEverywhere.html"/>
- <tip file="WideScreen.html"/>
- <tip file="WordCompletion.html"/>
- <tip file="Reopen.html"/>
- <tip file="Emmet.html"/>
- <tip file="RefactorThis.html"/>
- <tip file="ToolWindowsQuickAccess.html"/>
- <tip file="CamelHumpsInCodeCompletion.html"/>
- <tip file="CancelByControlArrows.html"/>
- <tip file="ChangeSorting.html"/>
- <tip file="CheckRegExp.html"/>
- <tip file="CtrlDotInLookups.html"/>
- <tip file="FinishByControlEnter.html"/>
- <tip file="HorizontalScrolling.html"/>
-</tips>
-
diff --git a/python/rest/src/com/jetbrains/rest/RestBundle.java b/python/rest/src/com/jetbrains/rest/RestBundle.java
index ed1b663..5884d2c 100644
--- a/python/rest/src/com/jetbrains/rest/RestBundle.java
+++ b/python/rest/src/com/jetbrains/rest/RestBundle.java
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -29,22 +30,21 @@
* User : catherine
*/
public class RestBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "com.jetbrains.rest.RestBundle";
private RestBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
// Cached loading
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/python/rest/src/com/jetbrains/rest/RestGotoProvider.java b/python/rest/src/com/jetbrains/rest/RestGotoProvider.java
index 6526202..f032851 100644
--- a/python/rest/src/com/jetbrains/rest/RestGotoProvider.java
+++ b/python/rest/src/com/jetbrains/rest/RestGotoProvider.java
@@ -20,19 +20,21 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import com.jetbrains.rest.psi.RestReference;
+import org.jetbrains.annotations.Nullable;
/**
- * User : catherine
+ * @author catherine
*/
public class RestGotoProvider extends GotoDeclarationHandlerBase {
-
- public PsiElement getGotoDeclarationTarget(PsiElement source, Editor editor) {
+ @Override
+ public PsiElement getGotoDeclarationTarget(@Nullable PsiElement source, Editor editor) {
if (source != null && source.getLanguage() instanceof RestLanguage) {
RestReference ref = PsiTreeUtil.getParentOfType(source, RestReference.class);
if (ref != null) {
return ref.resolve();
}
}
+
return null;
}
}
diff --git a/python/src/META-INF/IdeTipsAndTricks.xml b/python/src/META-INF/IdeTipsAndTricks.xml
new file mode 100644
index 0000000..41a5feb
--- /dev/null
+++ b/python/src/META-INF/IdeTipsAndTricks.xml
@@ -0,0 +1,113 @@
+<idea-plugin version="2">
+ <extensions defaultExtensionNs="com.intellij">
+ <tipAndTrick file="Welcome.html"/>
+ <tipAndTrick file="MultipleProjects.html"/>
+ <tipAndTrick file="GoToClass.html"/>
+ <tipAndTrick file="CodeCompletion.html"/>
+ <tipAndTrick file="ClassNameCompletion.html"/>
+ <tipAndTrick file="FindUsages.html"/>
+ <tipAndTrick file="QuickJavaDoc.html"/>
+ <tipAndTrick file="GoToDeclaration.html"/>
+ <tipAndTrick file="FileStructurePopup.html"/>
+ <tipAndTrick file="Rename.html"/>
+ <tipAndTrick file="TabInLookups.html"/>
+ <tipAndTrick file="TabInEditorClose.html"/>
+ <tipAndTrick file="SelectIn.html"/>
+ <tipAndTrick file="SpeedSearch.html"/>
+ <tipAndTrick file="Escape.html"/>
+ <tipAndTrick file="CtrlW.html"/>
+ <tipAndTrick file="ExtractVariable.html"/>
+ <tipAndTrick file="CtrlD.html"/>
+ <tipAndTrick file="MoveUpDown.html"/>
+ <tipAndTrick file="JoinLines.html"/>
+ <tipAndTrick file="ParameterInfo.html"/>
+ <tipAndTrick file="JumpToLastEdit.html"/>
+ <tipAndTrick file="HighlightUsagesInFile.html"/>
+ <tipAndTrick file="LocalVCS.html"/>
+ <tipAndTrick file="RecentFiles.html"/>
+ <tipAndTrick file="MethodSeparators.html"/>
+ <tipAndTrick file="CodeCompletionMiddle.html"/>
+ <tipAndTrick file="MethodUpDown.html"/>
+ <tipAndTrick file="ClipboardStack.html"/>
+ <tipAndTrick file="QuickJavaDocInLookups.html"/>
+ <tipAndTrick file="OverrideImplementMethods.html"/>
+ <tipAndTrick file="MenuItemsDescriptions.html"/>
+ <tipAndTrick file="GoToSymbol.html"/>
+ <tipAndTrick file="RecentChanges.html"/>
+ <tipAndTrick file="ImageFileCompletion.html"/>
+ <tipAndTrick file="QuickSwitchScheme.html"/>
+ <tipAndTrick file="CamelPrefixesInNavigationPopups.html"/>
+ <tipAndTrick file="ColumnSelection.html"/>
+ <tipAndTrick file="PyColorFiles.html"/>
+ <tipAndTrick file="CopyWithNoSelection.html"/>
+ <tipAndTrick file="MoveToChangelist.html"/>
+ <tipAndTrick file="moveFileToChangelist.html"/>
+ <tipAndTrick file="ShowUsages.html"/>
+ <tipAndTrick file="GoToAction.html"/>
+ <tipAndTrick file="GoToInspection.html"/>
+ <tipAndTrick file="SearchInSettings.html"/>
+ <tipAndTrick file="SelectRunDebugConfiguration.html"/>
+ <tipAndTrick file="ShowAppliedStyles.html"/>
+ <tipAndTrick file="ImagesLookup.html"/>
+ <tipAndTrick file="RenameCssSelector.html"/>
+ <tipAndTrick file="ColorEditingInCss.html"/>
+ <tipAndTrick file="Spellchecker.html"/>
+ <tipAndTrick file="SpellcheckerDictionaries.html"/>
+ <tipAndTrick file="TagNameCompletion.html"/>
+ <tipAndTrick file="WildcardsInNavigationPopups.html"/>
+ <tipAndTrick file="VcsQuickList.html"/>
+ <tipAndTrick file="Comment.html"/>
+ <tipAndTrick file="NavBar.html"/>
+ <tipAndTrick file="ChangesView.html"/>
+ <tipAndTrick file="Surround.html"/>
+ <tipAndTrick file="Consoles.html"/>
+ <tipAndTrick file="ConsolesCodeCompletion.html"/>
+ <tipAndTrick file="ConsolesHistory.html"/>
+ <tipAndTrick file="QuickFixRightArrow.html"/>
+ <tipAndTrick file="NavigateToFilePath.html"/>
+ <tipAndTrick file="IssueNavigation.html"/>
+ <tipAndTrick file="Managepy.html"/>
+ <tipAndTrick file="Templates.html"/>
+ <tipAndTrick file="Switcher.html"/>
+ <tipAndTrick file="DragToOpen.html"/>
+ <tipAndTrick file="CloseOthers.html"/>
+ <tipAndTrick file="EnterDirectoryInGotoFile.html"/>
+ <tipAndTrick file="GotoLineInFile.html"/>
+ <tipAndTrick file="LineEndings.html"/>
+ <tipAndTrick file="LineEndingsFolder.html"/>
+ <tipAndTrick file="HierarchyBrowser.html"/>
+ <tipAndTrick file="ShowHideSideBars.html"/>
+ <tipAndTrick file="ExcludeFromProject.html"/>
+ <tipAndTrick file="CodeCompletionNoShift.html"/>
+ <tipAndTrick file="CommitCtrlK.html"/>
+ <tipAndTrick file="FindReplaceToggle.html"/>
+ <tipAndTrick file="ScopesInTODO.html"/>
+ <tipAndTrick file="PreviewTODO.html"/>
+ <tipAndTrick file="SelectTasks.html"/>
+ <tipAndTrick file="RunConfigFolders.html"/>
+ <tipAndTrick file="LiveTemplatesDjango.html"/>
+ <tipAndTrick file="LiveTemplates.html"/>
+ <tipAndTrick file="SpeedSearchinLiveTemplates.html"/>
+ <tipAndTrick file="LaunchConsole.html"/>
+ <tipAndTrick file="Interpreter.html"/>
+ <tipAndTrick file="RemoteInterpreter.html"/>
+ <tipAndTrick file="BreakpointSpeedmenu.html"/>
+ <tipAndTrick file="BuiltInServer.html"/>
+ <tipAndTrick file="ConfiguringTerminal.html"/>
+ <tipAndTrick file="Terminal.html"/>
+ <tipAndTrick file="SearchEverywhere.html"/>
+ <tipAndTrick file="WideScreen.html"/>
+ <tipAndTrick file="WordCompletion.html"/>
+ <tipAndTrick file="Reopen.html"/>
+ <tipAndTrick file="Emmet.html"/>
+ <tipAndTrick file="RefactorThis.html"/>
+ <tipAndTrick file="ToolWindowsQuickAccess.html"/>
+ <tipAndTrick file="CamelHumpsInCodeCompletion.html"/>
+ <tipAndTrick file="CancelByControlArrows.html"/>
+ <tipAndTrick file="ChangeSorting.html"/>
+ <tipAndTrick file="CheckRegExp.html"/>
+ <tipAndTrick file="CtrlDotInLookups.html"/>
+ <tipAndTrick file="FinishByControlEnter.html"/>
+ <tipAndTrick file="HorizontalScrolling.html"/>
+ </extensions>
+</idea-plugin>
\ No newline at end of file
diff --git a/python/src/META-INF/pycharm-core.xml b/python/src/META-INF/pycharm-core.xml
index 7a4a9c6..dc95bd0 100644
--- a/python/src/META-INF/pycharm-core.xml
+++ b/python/src/META-INF/pycharm-core.xml
@@ -1,5 +1,6 @@
<idea-plugin version="2" xmlns:xi="http://www.w3.org/2001/XInclude">
<!-- Components and extensions declared in this file work ONLY in PyCharm, not in Python plugin. -->
+ <xi:include href="/META-INF/IdeTipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/PlatformLangPlugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/XmlPlugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/META-INF/ImagesPlugin.xml" xpointer="xpointer(/idea-plugin/*)">
@@ -24,14 +25,12 @@
</project-components>
<module value="com.intellij.modules.xml"/>
- <module value="com.intellij.modules.python"/>
<extensions defaultExtensionNs="com.intellij">
<projectViewPane implementation="com.intellij.ide.projectView.impl.ProjectViewPane"/>
<projectAttachProcessor implementation="com.intellij.platform.ModuleAttachProcessor"/>
- <!--<applicationConfigurable instance="com.jetbrains.python.configuration.PythonSdkConfigurable"/>-->
<projectConfigurable instance="com.jetbrains.python.configuration.PythonContentEntriesConfigurable"/>
<projectConfigurable instance="com.jetbrains.python.buildout.BuildoutModulesConfigurable"/>
<projectConfigurable instance="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable"/>
diff --git a/python/src/META-INF/python-core.xml b/python/src/META-INF/python-core.xml
index 6c4665d..f97820d 100644
--- a/python/src/META-INF/python-core.xml
+++ b/python/src/META-INF/python-core.xml
@@ -3,6 +3,8 @@
<resource-bundle>com.jetbrains.python.PyBundle</resource-bundle>
+ <module value="com.intellij.modules.python"/>
+
<extensions defaultExtensionNs="com.intellij">
<nameSuggestionProvider implementation="com.jetbrains.python.refactoring.PyNameSuggestionProvider"/>
<methodNavigationOffsetProvider implementation="com.jetbrains.python.codeInsight.PyMethodNavigationOffsetProvider"/>
@@ -18,6 +20,7 @@
<lang.foldingBuilder language="Python" implementationClass="com.jetbrains.python.PythonFoldingBuilder"/>
<lang.findUsagesProvider language="Python" implementationClass="com.jetbrains.python.findUsages.PythonFindUsagesProvider"/>
<lang.formatter language="Python" implementationClass="com.jetbrains.python.formatter.PythonFormattingModelBuilder"/>
+ <preFormatProcessor implementation="com.jetbrains.python.formatter.PyPreFormatProcessor"/>
<lang.whiteSpaceFormattingStrategy language="Python"
implementationClass="com.jetbrains.python.formatter.PyWhiteSpaceFormattingStrategy"/>
<lang.lineWrapStrategy language="Python" implementationClass="com.jetbrains.python.formatter.PyLineWrapPositionStrategy"/>
@@ -114,7 +117,7 @@
<runConfigurationProducer implementation="com.jetbrains.python.testing.unittest.PythonUnitTestConfigurationProducer"/>
<testSrcLocator implementation="com.jetbrains.python.testing.PythonUnitTestTestIdUrlProvider"/>
- <testSrcLocator implementation="com.jetbrains.django.testRunner.DjangoTestTestIdUrlProvider"/>
+
<testSrcLocator implementation="com.jetbrains.python.testing.nosetest.PythonNoseTestUrlProvider"/>
<runConfigurationProducer implementation="com.jetbrains.python.testing.pytest.PyTestConfigurationProducer"/>
@@ -131,7 +134,6 @@
<highlightUsagesHandlerFactory implementation="com.jetbrains.python.codeInsight.highlighting.PyHighlightExitPointsHandlerFactory"/>
<joinLinesHandler implementation="com.jetbrains.python.editor.PyJoinLinesHandler"/>
- <duplicates.profile implementation="com.jetbrains.python.duplocator.PyDuplicatesProfile"/>
<intentionAction>
<className>com.jetbrains.python.codeInsight.intentions.PyConvertMethodToPropertyIntention</className>
diff --git a/python/src/com/jetbrains/NotNullPredicate.java b/python/src/com/jetbrains/NotNullPredicate.java
new file mode 100644
index 0000000..b34ab62
--- /dev/null
+++ b/python/src/com/jetbrains/NotNullPredicate.java
@@ -0,0 +1,29 @@
+package com.jetbrains;
+
+import com.google.common.base.Predicate;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Filters out nullable elements allowing children to filter not-null elements
+ *
+ * @author Ilya.Kazakevich
+ */
+public class NotNullPredicate<T> implements Predicate<T> {
+ /**
+ * Simply filters nulls
+ */
+ public static final Predicate<Object> INSTANCE = new NotNullPredicate<Object>();
+
+ @Override
+ public final boolean apply(@Nullable final T input) {
+ if (input == null) {
+ return false;
+ }
+ return applyNotNull(input);
+ }
+
+ protected boolean applyNotNull(@NotNull final T input) {
+ return true;
+ }
+}
diff --git a/python/src/com/jetbrains/python/PyBundle.java b/python/src/com/jetbrains/python/PyBundle.java
index 3cb565d..28b853e 100644
--- a/python/src/com/jetbrains/python/PyBundle.java
+++ b/python/src/com/jetbrains/python/PyBundle.java
@@ -18,33 +18,34 @@
import com.intellij.CommonBundle;
import com.intellij.reference.SoftReference;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
import java.util.ResourceBundle;
// A copy of Ruby's.
+
/**
* Resource bundle access.
* Date: Nov 25, 2008 2:36:10 AM
*/
public class PyBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls
private static final String BUNDLE = "com.jetbrains.python.PyBundle";
private PyBundle() {
}
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
// Cached loading
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/python/src/com/jetbrains/python/PyBundle.properties b/python/src/com/jetbrains/python/PyBundle.properties
index c8755a0..7bc5469 100644
--- a/python/src/com/jetbrains/python/PyBundle.properties
+++ b/python/src/com/jetbrains/python/PyBundle.properties
@@ -533,9 +533,11 @@
# pull up
refactoring.pull.up.dialog.title=Pull members up to
+refactoring.pull.up.dialog.move.members.to.class=Move members to class
+refactoring.pull.up.dialog.members.to.be.moved=Following members would be moved
refactoring.pull.up.error.cannot.perform.refactoring.using.selected.elements=Cannot perform pull member up using selected element(s)
refactoring.pull.up.error.cannot.perform.refactoring.not.inside.class=Cannot perform pull member up: not inside the class
-refactoring.pull.up.error.cannot.perform.refactoring.no.base.classes=Class {0} has no super classes
+refactoring.pull.up.error.cannot.perform.refactoring.no.base.classes=Class {0} has no super classes or none of them could be used for refactoring
# push down
refactoring.push.down.dialog.title=Push members down from
@@ -558,7 +560,8 @@
# extract superclass
refactoring.extract.super.target.path.outside.roots=Target directory is outside the project.<br>Must be within content roots
-refactoring.extract.super.name.0.must.be.ident=Name ''{0}'' is invalid.<br/>Must be a valid Python identifier
+refactoring.extract.super.name.0.must.be.ident=Name ''{0}'' is invalid. Must be a valid Python identifier
+refactoring.extract.super.class.no.members.allowed=None of members could be extracted
# move
refactoring.move.class.or.function=Move class or function
diff --git a/python/src/com/jetbrains/python/PyParameterInfoHandler.java b/python/src/com/jetbrains/python/PyParameterInfoHandler.java
index b3f99f2..5aec444 100644
--- a/python/src/com/jetbrains/python/PyParameterInfoHandler.java
+++ b/python/src/com/jetbrains/python/PyParameterInfoHandler.java
@@ -51,7 +51,7 @@
return ArrayUtil.EMPTY_OBJECT_ARRAY; // we don't
}
- public PyArgumentList findElementForParameterInfo(final CreateParameterInfoContext context) {
+ public PyArgumentList findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
PyArgumentList arglist = findArgumentList(context);
if (arglist != null) {
final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(arglist.getContainingFile());
@@ -69,11 +69,11 @@
return ParameterInfoUtils.findParentOfType(context.getFile(), context.getOffset(), PyArgumentList.class);
}
- public void showParameterInfo(@NotNull final PyArgumentList element, final CreateParameterInfoContext context) {
+ public void showParameterInfo(@NotNull final PyArgumentList element, @NotNull final CreateParameterInfoContext context) {
context.showHint(element, element.getTextOffset(), this);
}
- public PyArgumentList findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) {
+ public PyArgumentList findElementForUpdatingParameterInfo(@NotNull final UpdateParameterInfoContext context) {
return findArgumentList(context);
}
@@ -82,7 +82,7 @@
We cannot store an index since we cannot determine what is an argument until we actually map arguments to parameters.
This is because a tuple in arguments may be a whole argument or map to a tuple parameter.
*/
- public void updateParameterInfo(@NotNull final PyArgumentList arglist, final UpdateParameterInfoContext context) {
+ public void updateParameterInfo(@NotNull final PyArgumentList arglist, @NotNull final UpdateParameterInfoContext context) {
if (context.getParameterOwner() != arglist) {
context.removeHint();
return;
@@ -125,7 +125,7 @@
}
@Override
- public void updateUI(final CallArgumentsMapping prevResult, final ParameterInfoUIContext context) {
+ public void updateUI(final CallArgumentsMapping prevResult, @NotNull final ParameterInfoUIContext context) {
if (prevResult == null) return;
final PyArgumentList argList = prevResult.getArgumentList();
if (!argList.isValid()) return;
diff --git a/python/src/com/jetbrains/python/codeInsight/PyBreakContinueGotoProvider.java b/python/src/com/jetbrains/python/codeInsight/PyBreakContinueGotoProvider.java
index 51ff238..778999a 100644
--- a/python/src/com/jetbrains/python/codeInsight/PyBreakContinueGotoProvider.java
+++ b/python/src/com/jetbrains/python/codeInsight/PyBreakContinueGotoProvider.java
@@ -26,15 +26,15 @@
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonLanguage;
import com.jetbrains.python.psi.*;
+import org.jetbrains.annotations.Nullable;
/**
* Provides reaction on ctrl+click for {@code break} and {@code continue} statements.
- * User: dcheryasov
- * Date: Nov 5, 2009 4:58:54 AM
+ * @author dcheryasov
*/
public class PyBreakContinueGotoProvider extends GotoDeclarationHandlerBase {
-
- public PsiElement getGotoDeclarationTarget(PsiElement source, Editor editor) {
+ @Override
+ public PsiElement getGotoDeclarationTarget(@Nullable PsiElement source, Editor editor) {
if (source != null && source.getLanguage() instanceof PythonLanguage) {
final PyLoopStatement loop = PsiTreeUtil.getParentOfType(source, PyLoopStatement.class, false, PyFunction.class, PyClass.class);
if (loop != null) {
@@ -66,6 +66,7 @@
}
}
}
+
return null;
}
}
diff --git a/python/src/com/jetbrains/python/codeInsight/completion/PyClassNameCompletionContributor.java b/python/src/com/jetbrains/python/codeInsight/completion/PyClassNameCompletionContributor.java
index 2b466d9..24318f8 100644
--- a/python/src/com/jetbrains/python/codeInsight/completion/PyClassNameCompletionContributor.java
+++ b/python/src/com/jetbrains/python/codeInsight/completion/PyClassNameCompletionContributor.java
@@ -71,12 +71,12 @@
final PsiFile originalFile = parameters.getOriginalFile();
addVariantsFromIndex(result, originalFile, PyClassNameIndex.KEY,
parent instanceof PyStringLiteralExpression ? STRING_LITERAL_INSERT_HANDLER : IMPORTING_INSERT_HANDLER,
- Conditions.<PyClass>alwaysTrue());
+ Conditions.<PyClass>alwaysTrue(), PyClass.class);
addVariantsFromIndex(result, originalFile, PyFunctionNameIndex.KEY,
- getFunctionInsertHandler(parent), IS_TOPLEVEL);
+ getFunctionInsertHandler(parent), IS_TOPLEVEL, PyFunction.class);
addVariantsFromIndex(result, originalFile, PyVariableNameIndex.KEY,
parent instanceof PyStringLiteralExpression ? STRING_LITERAL_INSERT_HANDLER : IMPORTING_INSERT_HANDLER,
- IS_TOPLEVEL);
+ IS_TOPLEVEL, PyTargetExpression.class);
addVariantsFromModules(result, originalFile, parent instanceof PyStringLiteralExpression);
}
}
@@ -117,13 +117,13 @@
final PsiFile targetFile,
final StubIndexKey<String, T> key,
final InsertHandler<LookupElement> insertHandler,
- final Condition<? super T> condition) {
+ final Condition<? super T> condition, Class<T> elementClass) {
final Project project = targetFile.getProject();
GlobalSearchScope scope = PyProjectScopeBuilder.excludeSdkTestsScope(targetFile);
Collection<String> keys = StubIndex.getInstance().getAllKeys(key, project);
for (final String elementName : CompletionUtil.sortMatching(resultSet.getPrefixMatcher(), keys)) {
- for (T element : StubIndex.getInstance().get(key, elementName, project, scope)) {
+ for (T element : StubIndex.getElements(key, elementName, project, scope, elementClass)) {
if (condition.value(element)) {
resultSet.addElement(LookupElementBuilder.createWithIcon(element)
.withTailText(" " + ((NavigationItem)element).getPresentation().getLocationString(), true)
diff --git a/python/src/com/jetbrains/python/codeInsight/controlflow/ControlFlowCache.java b/python/src/com/jetbrains/python/codeInsight/controlflow/ControlFlowCache.java
index 02b7040..a8db9b6 100644
--- a/python/src/com/jetbrains/python/codeInsight/controlflow/ControlFlowCache.java
+++ b/python/src/com/jetbrains/python/codeInsight/controlflow/ControlFlowCache.java
@@ -39,7 +39,7 @@
public static ControlFlow getControlFlow(@NotNull ScopeOwner element) {
SoftReference<ControlFlow> ref = element.getUserData(CONTROL_FLOW_KEY);
- ControlFlow flow = ref != null ? ref.get() : null;
+ ControlFlow flow = SoftReference.dereference(ref);
if (flow == null) {
flow = new PyControlFlowBuilder().buildControlFlow(element);
element.putUserData(CONTROL_FLOW_KEY, new SoftReference<ControlFlow>(flow));
@@ -50,7 +50,7 @@
@NotNull
public static Scope getScope(@NotNull ScopeOwner element) {
SoftReference<Scope> ref = element.getUserData(SCOPE_KEY);
- Scope scope = ref != null ? ref.get() : null;
+ Scope scope = SoftReference.dereference(ref);
if (scope == null) {
scope = new ScopeImpl(element);
element.putUserData(SCOPE_KEY, new SoftReference<Scope>(scope));
diff --git a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java
index aa6563f..1c09ee2 100644
--- a/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java
+++ b/python/src/com/jetbrains/python/codeInsight/imports/AddImportHelper.java
@@ -21,6 +21,7 @@
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.util.IncorrectOperationException;
@@ -179,7 +180,6 @@
}
return true;
}
-
/**
* Adds an "import ... from ..." statement below other top-level imports.
*
diff --git a/python/src/com/jetbrains/python/codeInsight/testIntegration/CreateTestDialog.java b/python/src/com/jetbrains/python/codeInsight/testIntegration/CreateTestDialog.java
index 08f3d19..c01a1b2 100644
--- a/python/src/com/jetbrains/python/codeInsight/testIntegration/CreateTestDialog.java
+++ b/python/src/com/jetbrains/python/codeInsight/testIntegration/CreateTestDialog.java
@@ -22,6 +22,7 @@
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.BooleanTableCellRenderer;
+import com.intellij.ui.TableUtil;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -29,7 +30,6 @@
import javax.swing.event.DocumentListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumn;
-import javax.swing.table.TableColumnModel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
@@ -72,14 +72,12 @@
myTableModel = new DefaultTableModel(methods, 2);
myMethodsTable.setModel(myTableModel);
- TableColumnModel model = myMethodsTable.getColumnModel();
- model.getColumn(0).setMaxWidth(new JCheckBox().getPreferredSize().width);
-
TableColumn checkColumn = myMethodsTable.getColumnModel().getColumn(0);
+ TableUtil.setupCheckboxColumn(checkColumn);
checkColumn.setCellRenderer(new BooleanTableCellRenderer());
checkColumn.setCellEditor(new DefaultCellEditor(new JCheckBox()));
- model.getColumn(1).setHeaderValue("Test method");
+ myMethodsTable.getColumnModel().getColumn(1).setHeaderValue("Test method");
checkColumn.setHeaderValue("");
getOKAction().setEnabled(true);
}
diff --git a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java
index 5ee041c..ea6db07 100644
--- a/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java
+++ b/python/src/com/jetbrains/python/codeInsight/userSkeletons/PyUserSkeletonsUtil.java
@@ -83,7 +83,7 @@
}
if (!ourNoSkeletonsErrorReported && ourUserSkeletonsDirectory == null) {
ourNoSkeletonsErrorReported = true;
- LOG.error("python-skeletons directory not found in paths: " + getPossibleUserSkeletonsPaths());
+ LOG.warn("python-skeletons directory not found in paths: " + getPossibleUserSkeletonsPaths());
}
return ourUserSkeletonsDirectory;
}
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
index 3dd6187..809d957 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleExecuteActionHandler.java
@@ -22,7 +22,6 @@
import com.intellij.execution.runners.ConsoleExecuteActionHandler;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
@@ -64,7 +63,7 @@
}
@Override
- public void processLine(final String text) {
+ public void processLine(@NotNull final String text) {
processLine(text, false);
}
@@ -202,6 +201,7 @@
executingPrompt(console);
}
myConsoleCommunication.execInterpreter(code, new Function<InterpreterResponse, Object>() {
+ @Override
public Object fun(final InterpreterResponse interpreterResponse) {
// clear
myInputBuffer = null;
@@ -335,7 +335,7 @@
private void indentEditor(final Editor editor, final int indentSize) {
new WriteCommandAction(getProject()) {
@Override
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
EditorModificationUtil.insertStringAtCaret(editor, IndentHelperImpl.fillIndent(getProject(), PythonFileType.INSTANCE, indentSize));
}
}.execute();
@@ -344,7 +344,7 @@
private void cleanEditor(final Editor editor) {
new WriteCommandAction(getProject()) {
@Override
- protected void run(Result result) throws Throwable {
+ protected void run(@NotNull Result result) throws Throwable {
editor.getDocument().setText("");
}
}.execute();
@@ -367,27 +367,26 @@
}
@Override
- public void runExecuteAction(@NotNull LanguageConsoleImpl languageConsole) {
+ public void runExecuteAction(@NotNull LanguageConsoleView console) {
if (isEnabled()) {
if (!canExecuteNow()) {
- HintManager.getInstance().showErrorHint(languageConsole.getConsoleEditor(), getPrevCommandRunningMessage());
+ HintManager.getInstance().showErrorHint(console.getConsole().getConsoleEditor(), getPrevCommandRunningMessage());
}
else {
- doRunExecuteAction(languageConsole);
+ doRunExecuteAction(console);
}
}
else {
- HintManager.getInstance().showErrorHint(languageConsole.getConsoleEditor(), getConsoleIsNotEnabledMessage());
+ HintManager.getInstance().showErrorHint(console.getConsole().getConsoleEditor(), getConsoleIsNotEnabledMessage());
}
}
- private void doRunExecuteAction(LanguageConsoleImpl languageConsole) {
- if (shouldCopyToHistory(languageConsole)) {
- copyToHistoryAndExecute(languageConsole);
+ private void doRunExecuteAction(LanguageConsoleView console) {
+ if (shouldCopyToHistory(console.getConsole())) {
+ copyToHistoryAndExecute(console);
}
else {
- final Document document = languageConsole.getConsoleEditor().getDocument();
- processLine(document.getText());
+ processLine(console.getConsole().getConsoleEditor().getDocument().getText());
}
}
@@ -395,8 +394,8 @@
return !PyConsoleUtil.isPagingPrompt(console.getPrompt());
}
- private void copyToHistoryAndExecute(LanguageConsoleImpl languageConsole) {
- super.runExecuteAction(languageConsole);
+ private void copyToHistoryAndExecute(LanguageConsoleView console) {
+ super.runExecuteAction(console);
}
public boolean canExecuteNow() {
diff --git a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
index c7b9ceb..e7952a3 100644
--- a/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
+++ b/python/src/com/jetbrains/python/console/PydevConsoleRunner.java
@@ -134,7 +134,7 @@
final String encoding = defaultCharset != null ? defaultCharset.name() : "utf-8";
setPythonIOEncoding(setPythonUnbuffered(envs), encoding);
-
+
PythonSdkFlavor.initPythonPath(envs, true, PythonCommandLineState.getAddedPaths(sdk));
return envs;
}
@@ -296,8 +296,11 @@
private Process createRemoteConsoleProcess(PythonRemoteInterpreterManager manager, String[] command, Map<String, String> env)
throws ExecutionException {
RemoteSdkData data = (RemoteSdkData)mySdk.getSdkAdditionalData();
+ assert data != null;
GeneralCommandLine commandLine = new GeneralCommandLine(command);
+
+
commandLine.getEnvironment().putAll(env);
commandLine.getParametersList().set(1, PythonRemoteInterpreterManager.toSystemDependent(new File(data.getHelpersPath(),
@@ -311,7 +314,6 @@
myCommandLine = commandLine.getCommandLineString();
-
RemoteSshProcess remoteProcess =
manager.createRemoteProcess(getProject(), data, commandLine, true);
diff --git a/python/src/com/jetbrains/python/console/PythonConsoleView.java b/python/src/com/jetbrains/python/console/PythonConsoleView.java
index 27d964a..a815e68 100644
--- a/python/src/com/jetbrains/python/console/PythonConsoleView.java
+++ b/python/src/com/jetbrains/python/console/PythonConsoleView.java
@@ -67,12 +67,12 @@
private static final Logger LOG = Logger.getInstance(PythonConsoleView.class);
- private Project myProject;
+ private final Project myProject;
private PydevConsoleExecuteActionHandler myExecuteActionHandler;
private PyConsoleSourceHighlighter mySourceHighlighter;
private boolean myIsIPythonOutput = false;
- private PyHighlighter myPyHighlighter;
- private EditorColorsScheme myScheme;
+ private final PyHighlighter myPyHighlighter;
+ private final EditorColorsScheme myScheme;
private boolean myHyperlink;
private final LanguageConsoleViewImpl myLanguageConsoleView;
@@ -103,6 +103,7 @@
myExecuteActionHandler = consoleExecuteActionHandler;
}
+ @Override
public void requestFocus() {
IdeFocusManager.findInstance().requestFocus(getPythonLanguageConsole().getConsoleEditor().getContentComponent(), true);
myLanguageConsoleView.updateUI();
@@ -120,6 +121,7 @@
@Override
public void executeCode(final @NotNull String code, @Nullable final Editor editor) {
ProgressManager.getInstance().run(new Task.Backgroundable(null, "Executing code in console...", false) {
+ @Override
public void run(@NotNull final ProgressIndicator indicator) {
long time = System.currentTimeMillis();
while (!myExecuteActionHandler.isEnabled() || !myExecuteActionHandler.canExecuteNow()) {
@@ -140,7 +142,7 @@
try {
Thread.sleep(300);
}
- catch (InterruptedException e) {
+ catch (InterruptedException ignored) {
}
}
if (!indicator.isCanceled()) {
@@ -164,7 +166,7 @@
String text = getPythonLanguageConsole().getConsoleEditor().getDocument().getText();
getPythonLanguageConsole().setTextToEditor(code);
- myExecuteActionHandler.runExecuteAction(getPythonLanguageConsole());
+ myExecuteActionHandler.runExecuteAction(myLanguageConsoleView);
if (!StringUtil.isEmpty(text)) {
getPythonLanguageConsole().setTextToEditor(text);
@@ -186,7 +188,8 @@
myLanguageConsoleView.print(text, outputType);
}
- public void print(String text, final ConsoleViewContentType outputType) {
+ @Override
+ public void print(@NotNull String text, @NotNull final ConsoleViewContentType outputType) {
detectIPython(text, outputType);
if (PyConsoleUtil.detectIPythonEnd(text)) {
myIsIPythonOutput = false;
diff --git a/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java b/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java
index 71b4e21..b807b3c 100644
--- a/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java
+++ b/python/src/com/jetbrains/python/console/PythonDebugLanguageConsoleView.java
@@ -141,7 +141,7 @@
}
@Override
- public void print(String s, ConsoleViewContentType contentType) {
+ public void print(@NotNull String s, @NotNull ConsoleViewContentType contentType) {
myPydevConsoleView.print(s, contentType);
myTextConsole.print(s, contentType);
}
@@ -242,19 +242,23 @@
myConsole = console;
}
+ @Override
public boolean isSelected(final AnActionEvent event) {
return myConsole.isDebugConsole();
}
+ @Override
public void setSelected(final AnActionEvent event, final boolean flag) {
myConsole.showDebugConsole(flag);
ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
public void run() {
update(event);
}
});
}
+ @Override
public void update(final AnActionEvent event) {
super.update(event);
final Presentation presentation = event.getPresentation();
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
index 1c1b814..312db25 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugProcess.java
@@ -186,6 +186,7 @@
return myPositionConverter;
}
+ @NotNull
@Override
public XBreakpointHandler<?>[] getBreakpointHandlers() {
return myBreakpointHandlers;
@@ -672,7 +673,7 @@
}
public PyStackFrame createStackFrame(PyStackFrameInfo frameInfo) {
- return new PyStackFrame(this.getSession().getProject(), this, frameInfo,
+ return new PyStackFrame(getSession().getProject(), this, frameInfo,
getPositionConverter().convertFromPython(frameInfo.getPosition()));
}
diff --git a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java
index 7ca044b..c6db6ba 100644
--- a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java
+++ b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java
@@ -19,11 +19,11 @@
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.configurations.*;
+import com.intellij.execution.console.LanguageConsoleBuilder;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.process.ProcessHandler;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.GenericProgramRunner;
-import com.intellij.execution.runners.LanguageConsoleBuilder;
import com.intellij.execution.ui.ExecutionConsole;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.application.ApplicationManager;
@@ -76,9 +76,9 @@
((AbstractPythonRunConfiguration)profile).canRunWithCoverage();
}
- protected RunContentDescriptor doExecute(final Project project, RunProfileState profileState,
+ protected RunContentDescriptor doExecute(@NotNull final Project project, @NotNull RunProfileState profileState,
RunContentDescriptor contentToReuse,
- ExecutionEnvironment env) throws ExecutionException {
+ @NotNull ExecutionEnvironment env) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
final PythonCommandLineState pyState = (PythonCommandLineState)profileState;
@@ -133,7 +133,7 @@
pythonConsoleView.setExecutionHandler(consoleExecuteActionHandler);
debugProcess.getSession().addSessionListener(consoleExecuteActionHandler);
- new LanguageConsoleBuilder().console(pythonConsoleView).processHandler(processHandler).initActions(consoleExecuteActionHandler, "py");
+ new LanguageConsoleBuilder(pythonConsoleView).processHandler(processHandler).initActions(consoleExecuteActionHandler, "py");
}
}
diff --git a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
index edde7f2..6ea6540 100644
--- a/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
+++ b/python/src/com/jetbrains/python/documentation/PyDocumentationSettings.java
@@ -37,7 +37,7 @@
storages = {@Storage(file = "$MODULE_FILE$")}
)
public class PyDocumentationSettings implements PersistentStateComponent<PyDocumentationSettings> {
- public String myDocStringFormat = "";
+ public String myDocStringFormat = DocStringFormat.REST;
public boolean analyzeDoctest = true;
public boolean isEpydocFormat(PsiFile file) {
diff --git a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
index 3a504aa..55bc1e4 100644
--- a/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
+++ b/python/src/com/jetbrains/python/documentation/PythonDocumentationProvider.java
@@ -487,7 +487,7 @@
".\nWould you like to configure it now?",
"Python External Documentation",
Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.OK) {
ShowSettingsUtilImpl.showSettingsDialog(project, PythonDocumentationConfigurable.ID, "");
}
}
diff --git a/python/src/com/jetbrains/python/editor/PythonEnterHandler.java b/python/src/com/jetbrains/python/editor/PythonEnterHandler.java
index 16bf3c7..c055606 100644
--- a/python/src/com/jetbrains/python/editor/PythonEnterHandler.java
+++ b/python/src/com/jetbrains/python/editor/PythonEnterHandler.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.
diff --git a/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java b/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
index efc1e68..78d9d65 100644
--- a/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
+++ b/python/src/com/jetbrains/python/findUsages/PyFindUsagesHandlerFactory.java
@@ -71,13 +71,13 @@
" overrides method of class " +
((PyFunction)next).getContainingClass().getName() +
".\nDo you want to find usages of the base method?", "Find Usages", Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
List<PsiElement> allMethods = new ArrayList<PsiElement>();
allMethods.add(element);
allMethods.addAll(superMethods);
return new PyFunctionFindUsagesHandler(element, allMethods);
}
- if (rc == 1) {
+ if (rc == Messages.NO) {
return new PyFunctionFindUsagesHandler(element);
}
return FindUsagesHandler.NULL_HANDLER;
diff --git a/python/src/com/jetbrains/python/formatter/PyBlock.java b/python/src/com/jetbrains/python/formatter/PyBlock.java
index d160749..0c535c1 100644
--- a/python/src/com/jetbrains/python/formatter/PyBlock.java
+++ b/python/src/com/jetbrains/python/formatter/PyBlock.java
@@ -141,6 +141,33 @@
Wrap wrap = null;
Indent childIndent = Indent.getNoneIndent();
Alignment childAlignment = null;
+
+ if (parentType == PyElementTypes.BINARY_EXPRESSION && !isInControlStatement()) {
+ //Setup alignments for binary expression
+ childAlignment = getAlignmentForChildren();
+
+ PyBlock p = myParent; //Check grandparents
+ while (p != null) {
+ ASTNode pNode = p.getNode();
+ if (ourListElementTypes.contains(pNode.getElementType())) {
+ if (needListAlignment(child) && !isEmptyList(_node.getPsi())) {
+
+ childAlignment = p.getChildAlignment();
+ break;
+ }
+ }
+ else if (pNode == PyElementTypes.BINARY_EXPRESSION) {
+ childAlignment = p.getChildAlignment();
+ }
+ if (!breaksAlignment(pNode.getElementType())) {
+ p = p.myParent;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
if (childType == PyElementTypes.STATEMENT_LIST) {
if (hasLineBreaksBefore(child, 1) || needLineBreakInStatement()) {
childIndent = Indent.getNormalIndent();
@@ -173,14 +200,6 @@
PyStatementPart.class);
childIndent = parens != null ? Indent.getNormalIndent() : Indent.getContinuationIndent();
}
- else {
- if (grandparentType == PyElementTypes.BINARY_EXPRESSION && myParent != null) {
- childAlignment = myParent.getAlignmentForChildren();
- }
- else {
- childAlignment = getAlignmentForChildren();
- }
- }
}
if (parentType == PyElementTypes.LIST_LITERAL_EXPRESSION || parentType == PyElementTypes.LIST_COMP_EXPRESSION) {
@@ -309,6 +328,10 @@
return new PyBlock(this, child, childAlignment, childIndent, wrap, myContext);
}
+ private static boolean breaksAlignment(IElementType type) {
+ return type != PyElementTypes.BINARY_EXPRESSION;
+ }
+
private static Alignment getAlignmentOfChild(PyBlock b, int childNum) {
if (b.getSubBlocks().size() > childNum) {
ChildAttributes attributes = b.getChildAttributes(childNum);
@@ -516,7 +539,7 @@
}
}
- if (psi2 instanceof PsiComment && !hasLineBreaksBefore(psi2.getNode(), 1)) {
+ if (psi2 instanceof PsiComment && !hasLineBreaksBefore(psi2.getNode(), 1) && myContext.getPySettings().SPACE_BEFORE_NUMBER_SIGN) {
return Spacing.createSpacing(2, 0, 0, false, 0);
}
}
diff --git a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
index 961ca72..88ddd41 100644
--- a/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
+++ b/python/src/com/jetbrains/python/formatter/PyCodeStyleSettings.java
@@ -38,6 +38,9 @@
public boolean NEW_LINE_AFTER_COLON = false;
public boolean NEW_LINE_AFTER_COLON_MULTI_CLAUSE = true;
+ public boolean SPACE_AFTER_NUMBER_SIGN = true;
+ public boolean SPACE_BEFORE_NUMBER_SIGN = true;
+
public PyCodeStyleSettings(CodeStyleSettings container) {
super("Python", container);
}
diff --git a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
index c26a1a1..9e7f97d 100644
--- a/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
+++ b/python/src/com/jetbrains/python/formatter/PyLanguageCodeStyleSettingsProvider.java
@@ -72,9 +72,12 @@
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_AROUND_EQ_IN_KEYWORD_ARGUMENT", "Around = in keyword argument",
SPACES_AROUND_OPERATORS);
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_WITHIN_BRACES", "Braces", SPACES_WITHIN);
- consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_PY_COLON", ApplicationBundle.message("checkbox.spaces.before.colon"), SPACES_OTHER);
+ consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_PY_COLON",
+ ApplicationBundle.message("checkbox.spaces.before.colon"), SPACES_OTHER);
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_AFTER_PY_COLON", ApplicationBundle.message("checkbox.spaces.after.colon"), SPACES_OTHER);
consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_BACKSLASH", "Before '\\'", SPACES_OTHER);
+ consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_BEFORE_NUMBER_SIGN", "Before '#'", SPACES_OTHER);
+ consumer.showCustomOption(PyCodeStyleSettings.class, "SPACE_AFTER_NUMBER_SIGN", "After '#'", SPACES_OTHER);
}
else if (settingsType == SettingsType.BLANK_LINES_SETTINGS) {
consumer.showStandardOptions("BLANK_LINES_AROUND_CLASS",
@@ -112,7 +115,7 @@
CommonCodeStyleSettings.IndentOptions indentOptions = defaultSettings.initIndentOptions();
indentOptions.INDENT_SIZE = 4;
defaultSettings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true;
- return defaultSettings;
+ return defaultSettings;
}
@Override
diff --git a/python/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java b/python/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java
index d7fa5f0..47b6b7c 100644
--- a/python/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java
+++ b/python/src/com/jetbrains/python/formatter/PyLineWrapPositionStrategy.java
@@ -24,6 +24,7 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.text.CharArrayUtil;
+import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.psi.StringLiteralExpression;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -44,9 +45,6 @@
addRule(new Rule('(', WrapCondition.AFTER));
addRule(new Rule('[', WrapCondition.AFTER));
addRule(new Rule('{', WrapCondition.AFTER));
-
- // Symbols to wrap before
- addRule(new Rule('.', WrapCondition.BEFORE));
}
@Override
@@ -75,11 +73,20 @@
int maxPreferredOffset,
boolean allowToBeyondMaxPreferredOffset,
boolean virtual) {
+
int wrapPosition =
super.calculateWrapPosition(document, project, startOffset, endOffset, maxPreferredOffset, allowToBeyondMaxPreferredOffset, virtual);
if (wrapPosition < 0) return wrapPosition;
final CharSequence text = document.getCharsSequence();
+ if (wrapPosition > 0) {
+ char charBefore = text.charAt(wrapPosition - 1);
+ if (charBefore == '\'' || charBefore == '"') {
+ //don't wrap the first char of string literal
+ return wrapPosition + 1;
+ }
+ }
+
char c = text.charAt(wrapPosition);
if (!StringUtil.isWhiteSpace(c) || project == null) {
return wrapPosition;
diff --git a/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java b/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java
new file mode 100644
index 0000000..ee56016
--- /dev/null
+++ b/python/src/com/jetbrains/python/formatter/PyPreFormatProcessor.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.formatter;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.impl.source.codeStyle.PreFormatProcessor;
+import com.jetbrains.python.PythonLanguage;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyElementGenerator;
+import com.jetbrains.python.psi.PyRecursiveElementVisitor;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author traff
+ */
+public class PyPreFormatProcessor implements PreFormatProcessor {
+ @NotNull
+ @Override
+ public TextRange process(@NotNull ASTNode element, @NotNull TextRange range) {
+ PsiElement psiElement = element.getPsi();
+ if (psiElement == null) return range;
+
+ if (!psiElement.getLanguage().is(PythonLanguage.getInstance())) return range;
+
+ PsiFile file = psiElement.isValid() ? psiElement.getContainingFile() : null;
+ if (file == null) return range;
+
+ Project project = psiElement.getProject();
+
+ return new PyCommentFormatter(project).process(psiElement, range);
+ }
+
+ /**
+ * @author traff
+ */
+ public static class PyCommentFormatter extends PyRecursiveElementVisitor {
+ private final Project myProject;
+ private final CodeStyleSettings mySettings;
+ private final PyCodeStyleSettings myPyCodeStyleSettings;
+ private TextRange myRange;
+ private int myDelta = 0;
+
+ public PyCommentFormatter(Project project) {
+ myProject = project;
+ mySettings = CodeStyleSettingsManager.getSettings(project);
+ myPyCodeStyleSettings = mySettings.getCustomSettings(PyCodeStyleSettings.class);
+ }
+
+ public TextRange process(PsiElement element, TextRange range) {
+ if (!myPyCodeStyleSettings.SPACE_AFTER_NUMBER_SIGN) {
+ return range;
+ }
+ myRange = range;
+ element.accept(this);
+ return TextRange.create(range.getStartOffset(), range.getEndOffset() + myDelta);
+ }
+
+ @Override
+ public void visitComment(PsiComment element) {
+ if (!myRange.contains(element.getTextRange())) {
+ return;
+ }
+ String text = element.getText();
+ int commentStart = text.indexOf('#');
+ if (commentStart != -1 && (commentStart + 1) < text.length()) {
+ String commentText = StringUtil.trimLeading(text.substring(commentStart + 1));
+
+ String newText = "# " + commentText;
+ if (!newText.equals(text)) {
+ myDelta += newText.length() - text.length();
+ element.replace(
+ PyElementGenerator.getInstance(myProject).createFromText(LanguageLevel.getDefault(), PsiComment.class, newText));
+ }
+ }
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/inspections/PyAssignmentToLoopOrWithParameterInspection.java b/python/src/com/jetbrains/python/inspections/PyAssignmentToLoopOrWithParameterInspection.java
index aefbc34..2efaf98 100644
--- a/python/src/com/jetbrains/python/inspections/PyAssignmentToLoopOrWithParameterInspection.java
+++ b/python/src/com/jetbrains/python/inspections/PyAssignmentToLoopOrWithParameterInspection.java
@@ -132,17 +132,7 @@
if (element instanceof PySubscriptionExpression) {
element = ((PySubscriptionExpression)element).getRootOperand();
}
- while (true) {
- PsiReference reference = element.getReference();
- if (reference == null) {
- break;
- }
- PsiElement resolve = reference.resolve();
- if (resolve == null || resolve.equals(element) || !PyUtil.inSameFile(resolve, element)) {
- break;
- }
- element = resolve;
- }
+ element = PyUtil.resolveToTheTop(element);
return element;
}
diff --git a/python/src/com/jetbrains/python/lexer/PythonEditorHighlighter.java b/python/src/com/jetbrains/python/lexer/PythonEditorHighlighter.java
index d0e3de6..9893d4f 100644
--- a/python/src/com/jetbrains/python/lexer/PythonEditorHighlighter.java
+++ b/python/src/com/jetbrains/python/lexer/PythonEditorHighlighter.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 @@
}
@Override
- public void setEditor(HighlighterClient editor) {
+ public void setEditor(@NotNull HighlighterClient editor) {
Lexer l = getLexer();
if (l instanceof LayeredLexer) {
editor.getDocument().putUserData(KEY, editor.getDocument().getText().indexOf(PyNames.UNICODE_LITERALS) == -1);
diff --git a/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java b/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java
index 546724f..29fb657 100644
--- a/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java
+++ b/python/src/com/jetbrains/python/lexer/PythonIndentingProcessor.java
@@ -194,9 +194,6 @@
if (DUMP_TOKENS) {
System.out.println("\n--- LEXER START---");
}
- if (startOffset != 0 || initialState != 0) {
- throw new RuntimeException("Indenting lexer does not support incremental lexing");
- }
}
private void setStartState() {
diff --git a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
index fecce4f..3118157 100644
--- a/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.java
+++ b/python/src/com/jetbrains/python/packaging/PyPackageManagerImpl.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.
@@ -261,7 +261,7 @@
}
}, ModalityState.current());
}
- if (warning[0] != 0) return true;
+ if (warning[0] != Messages.YES) return true;
}
catch (PyExternalProcessException e) {
LOG.info("Error loading packages dependents: " + e.getMessage(), e);
diff --git a/python/src/com/jetbrains/python/parsing/FunctionParsing.java b/python/src/com/jetbrains/python/parsing/FunctionParsing.java
index 768fa0a..cd61f6e 100644
--- a/python/src/com/jetbrains/python/parsing/FunctionParsing.java
+++ b/python/src/com/jetbrains/python/parsing/FunctionParsing.java
@@ -16,6 +16,7 @@
package com.jetbrains.python.parsing;
import com.intellij.lang.PsiBuilder;
+import com.intellij.lang.WhitespacesBinders;
import com.intellij.psi.tree.IElementType;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyTokenTypes;
@@ -81,7 +82,7 @@
}
else { // empty arglist node, so we always have it
PsiBuilder.Marker argListMarker = myBuilder.mark();
- argListMarker.setCustomEdgeTokenBinders(LeftBiasedWhitespaceBinder.INSTANCE, null);
+ argListMarker.setCustomEdgeTokenBinders(WhitespacesBinders.GREEDY_LEFT_BINDER, null);
argListMarker.done(PyElementTypes.ARGUMENT_LIST);
}
if (atToken(PyTokenTypes.STATEMENT_BREAK)) {
@@ -110,6 +111,7 @@
myBuilder.error(message("PARSE.expected.@.or.def"));
PsiBuilder.Marker parameterList = myBuilder.mark(); // To have non-empty parameters list at all the time.
parameterList.done(PyElementTypes.PARAMETER_LIST);
+ myBuilder.mark().done(PyElementTypes.STATEMENT_LIST); // To have non-empty empty statement list
endMarker.done(getFunctionType());
}
}
diff --git a/python/src/com/jetbrains/python/parsing/LeftBiasedWhitespaceBinder.java b/python/src/com/jetbrains/python/parsing/LeftBiasedWhitespaceBinder.java
deleted file mode 100644
index 38bd079..0000000
--- a/python/src/com/jetbrains/python/parsing/LeftBiasedWhitespaceBinder.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.parsing;
-
-import com.intellij.lang.WhitespacesAndCommentsBinder;
-import com.intellij.psi.tree.IElementType;
-
-import java.util.List;
-
-/**
- * @author yole
- */
-public class LeftBiasedWhitespaceBinder implements WhitespacesAndCommentsBinder {
- public static LeftBiasedWhitespaceBinder INSTANCE = new LeftBiasedWhitespaceBinder();
-
- @Override
- public int getEdgePosition(List<IElementType> tokens, boolean atStreamEdge, TokenTextGetter getter) {
- return 0;
- }
-}
diff --git a/python/src/com/jetbrains/python/psi/PyUtil.java b/python/src/com/jetbrains/python/psi/PyUtil.java
index bcaf70d..8af009b 100644
--- a/python/src/com/jetbrains/python/psi/PyUtil.java
+++ b/python/src/com/jetbrains/python/psi/PyUtil.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.jetbrains.python.psi;
+import com.google.common.collect.Collections2;
import com.google.common.collect.Maps;
import com.intellij.codeInsight.FileModificationService;
import com.intellij.codeInsight.completion.PrioritizedLookupElement;
@@ -51,7 +52,7 @@
import com.intellij.util.PlatformIcons;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ContainerUtil;
-import com.intellij.util.containers.HashSet;
+import com.jetbrains.NotNullPredicate;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PyTokenTypes;
@@ -63,6 +64,7 @@
import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.refactoring.classes.extractSuperclass.PyExtractSuperclassHelper;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -104,21 +106,6 @@
return node != null && node.getElementType().equals(TokenType.WHITE_SPACE);
}
-
- @NotNull
- public static Set<PsiElement> getComments(PsiElement start) {
- final Set<PsiElement> comments = new HashSet<PsiElement>();
- PsiElement seeker = start.getPrevSibling();
- if (seeker == null) seeker = start.getParent().getPrevSibling();
- while (seeker instanceof PsiWhiteSpace || seeker instanceof PsiComment) {
- if (seeker instanceof PsiComment) {
- comments.add(seeker);
- }
- seeker = seeker.getPrevSibling();
- }
- return comments;
- }
-
@Nullable
public static PsiElement getFirstNonCommentAfter(PsiElement start) {
PsiElement seeker = start;
@@ -713,6 +700,38 @@
return PyElementGenerator.getInstance(element.getProject()).createNameIdentifier(name, LanguageLevel.forElement(element));
}
+ /**
+ * Finds element declaration by resolving its references top the top but not further than file (to prevent unstubing)
+ * @param element element to resolve
+ * @return its declaration
+ */
+ @NotNull
+ public static PsiElement resolveToTheTop(@NotNull final PsiElement elementToResolve) {
+ PsiElement currentElement = elementToResolve;
+ while (true) {
+ final PsiReference reference = currentElement.getReference();
+ if (reference == null) {
+ break;
+ }
+ final PsiElement resolve = reference.resolve();
+ if ((resolve == null) || resolve.equals(currentElement) || !inSameFile(resolve, currentElement)) {
+ break;
+ }
+ currentElement = resolve;
+ }
+ return currentElement;
+ }
+
+ /**
+ * Gets class init method
+ * @param pyClass class where to find init
+ * @return class init method if any
+ */
+ @Nullable
+ public static PyFunction getInitMethod(@NotNull final PyClass pyClass) {
+ return pyClass.findMethodByName(PyNames.INIT, false);
+ }
+
public static class KnownDecoratorProviderHolder {
public static PyKnownDecoratorProvider[] KNOWN_DECORATOR_PROVIDERS = Extensions.getExtensions(PyKnownDecoratorProvider.EP_NAME);
@@ -915,6 +934,10 @@
return selfName;
}
+ /**
+ *
+ * @return Source roots <strong>and</strong> content roots for element's project
+ */
@NotNull
public static Collection<VirtualFile> getSourceRoots(@NotNull PsiElement foothold) {
final Module module = ModuleUtilCore.findModuleForPsiElement(foothold);
@@ -924,6 +947,10 @@
return Collections.emptyList();
}
+ /**
+ *
+ * @return Source roots <strong>and</strong> content roots for module
+ */
@NotNull
public static Collection<VirtualFile> getSourceRoots(@NotNull Module module) {
final Set<VirtualFile> result = new LinkedHashSet<VirtualFile>();
@@ -1092,6 +1119,11 @@
}
return null;
}
+
+ //TODO: Doc
+ public boolean isInstanceMethod() {
+ return ! (myIsClassMethod || myIsStaticMethod);
+ }
}
public static boolean isSuperCall(@NotNull PyCallExpression node) {
@@ -1398,4 +1430,57 @@
}
return false;
}
+
+ public static boolean isInit(@NotNull final PyFunction function) {
+ return PyNames.INIT.equals(function.getName());
+ }
+
+
+ private static boolean isObject(@NotNull final PyMemberInfo<PyElement> classMemberInfo) {
+ final PyElement element = classMemberInfo.getMember();
+ if ((element instanceof PyClass) && PyNames.OBJECT.equals(element.getName())) {
+ return true;
+ }
+ return false;
+
+ }
+
+ /**
+ * Filters out {@link com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo}
+ * that should not be displayed in this refactoring (like object)
+ *
+ * @param pyMemberInfos collection to sort
+ * @return sorted collection
+ */
+ @NotNull
+ public static Collection<PyMemberInfo<PyElement>> filterOutObject(@NotNull final Collection<PyMemberInfo<PyElement>> pyMemberInfos) {
+ return Collections2.filter(pyMemberInfos, new ObjectPredicate(false));
+ }
+
+ /**
+ * Filters only pyclass object (new class)
+ */
+ public static class ObjectPredicate extends NotNullPredicate<PyMemberInfo<PyElement>> {
+ private final boolean myAllowObjects;
+
+ /**
+ * @param allowObjects allows only objects if true. Allows all but objects otherwise.
+ */
+ public ObjectPredicate(final boolean allowObjects) {
+ myAllowObjects = allowObjects;
+ }
+
+ @Override
+ public boolean applyNotNull(@NotNull final PyMemberInfo<PyElement> input) {
+ return myAllowObjects == isObject(input);
+ }
+
+ private static boolean isObject(@NotNull final PyMemberInfo<PyElement> classMemberInfo) {
+ final PyElement element = classMemberInfo.getMember();
+ if ((element instanceof PyClass) && PyNames.OBJECT.equals(element.getName())) {
+ return true;
+ }
+ return false;
+ }
+ }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
index 50ba541..dfe12ca 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyArgumentListImpl.java
@@ -15,13 +15,15 @@
*/
package com.jetbrains.python.psi.impl;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Queues;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
+import com.jetbrains.NotNullPredicate;
import com.jetbrains.python.PyElementTypes;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonDialectsTokenSetProvider;
@@ -30,9 +32,13 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Arrays;
+import java.util.*;
public class PyArgumentListImpl extends PyElementImpl implements PyArgumentList {
+
+ // Filters all expressions but keyword arguments
+ private static final NoKeyArguments NO_KEY_ARGUMENTS = new NoKeyArguments();
+
public PyArgumentListImpl(ASTNode astNode) {
super(astNode);
}
@@ -61,47 +67,64 @@
return null;
}
- public void addArgument(PyExpression arg) {
- // it should find the comma after the argument to add after, and add after
- // that. otherwise it won't deal with comments nicely
+ @Override
+ public void addArgument(@NotNull final PyExpression arg) {
+ final PyElementGenerator generator = new PyElementGeneratorImpl(getProject());
+
+ // Adds param to appropriate place
+ final Deque<PyKeywordArgument> keywordArguments = getKeyWordArguments();
+ final Deque<PyExpression> parameters = getParameters();
+
+ if (keywordArguments.isEmpty() && parameters.isEmpty()) {
+ generator.insertItemIntoListRemoveRedundantCommas(this, null, arg);
+ return;
+ }
+
+
if (arg instanceof PyKeywordArgument) {
- PyKeywordArgument keywordArgument = (PyKeywordArgument)arg;
- PyKeywordArgument lastKeyArg = null;
- PyExpression firstNonKeyArg = null;
- for (PsiElement element : getChildren()) {
- if (element instanceof PyKeywordArgument) {
- lastKeyArg = (PyKeywordArgument)element;
- }
- else if (element instanceof PyExpression && firstNonKeyArg == null) {
- firstNonKeyArg = (PyExpression)element;
- }
- }
- if (lastKeyArg != null) {
- // add after last key arg
- addArgumentNode(keywordArgument, lastKeyArg.getNode().getTreeNext(), true);
-
- }
- else if (firstNonKeyArg != null) {
- // add before first non key arg
- addArgumentNode(keywordArgument, firstNonKeyArg.getNode(), true);
-
+ if (parameters.isEmpty()) {
+ generator.insertItemIntoListRemoveRedundantCommas(this, keywordArguments.getLast(), arg);
}
else {
- // add as only argument
- addArgumentLastWithoutComma(arg);
+ if (keywordArguments.isEmpty()) {
+ generator.insertItemIntoListRemoveRedundantCommas(this, parameters.getLast(), arg);
+ }
+ else {
+ generator.insertItemIntoListRemoveRedundantCommas(this, keywordArguments.getLast(), arg);
+ }
}
}
else {
- final PyExpression[] args = getArguments();
- if (args.length > 0) {
- addArgumentAfter(arg, args [args.length-1]);
+ if (parameters.isEmpty()) {
+ generator.insertItemIntoListRemoveRedundantCommas(this, null, arg);
}
else {
- addArgumentLastWithoutComma(arg);
+ generator.insertItemIntoListRemoveRedundantCommas(this, parameters.getLast(), arg);
}
}
}
+
+ /**
+ * @return parameters (as opposite to keyword arguments)
+ */
+ @NotNull
+ private Deque<PyExpression> getParameters() {
+ final PyExpression[] childrenOfType = PsiTreeUtil.getChildrenOfType(this, PyExpression.class);
+ if (childrenOfType == null) {
+ return new ArrayDeque<PyExpression>(0);
+ }
+ return Queues.newArrayDeque(Collections2.filter(Arrays.asList(childrenOfType), NO_KEY_ARGUMENTS));
+ }
+
+ /**
+ * @return keyword arguments (as opposite to parameters)
+ */
+ @NotNull
+ private Deque<PyKeywordArgument> getKeyWordArguments() {
+ return Queues.newArrayDeque(PsiTreeUtil.findChildrenOfType(this, PyKeywordArgument.class));
+ }
+
public void addArgumentFirst(PyExpression arg) {
ASTNode node = getNode();
ASTNode[] pars = node.getChildren(TokenSet.create(PyTokenTypes.LPAR));
@@ -113,13 +136,12 @@
catch (IncorrectOperationException e1) {
throw new IllegalStateException(e1);
}
-
}
else {
ASTNode before = PyUtil.getNextNonWhitespace(pars[0]);
ASTNode anchorBefore;
if (before != null && elementPrecedesElementsOfType(before, PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens())) {
- ASTNode comma = PyElementGenerator.getInstance(getProject()).createComma();
+ ASTNode comma = createComma();
node.addChild(comma, before);
node.addChild(ASTFactory.whitespace(" "), before);
anchorBefore = comma;
@@ -137,6 +159,14 @@
}
}
+ /**
+ * @return newly created comma
+ */
+ @NotNull
+ private ASTNode createComma() {
+ return PyElementGenerator.getInstance(getProject()).createComma();
+ }
+
private static boolean elementPrecedesElementsOfType(ASTNode before, TokenSet expressions) {
ASTNode node = before;
while (node != null) {
@@ -279,4 +309,11 @@
}
return ret;
}
+
+ private static class NoKeyArguments extends NotNullPredicate<PyExpression> {
+ @Override
+ protected boolean applyNotNull(@NotNull final PyExpression input) {
+ return (PsiTreeUtil.getParentOfType(input, PyKeywordArgument.class) == null) && !(input instanceof PyKeywordArgument);
+ }
+ }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
index bd33be4..781dc28 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyCallExpressionHelper.java
@@ -43,6 +43,7 @@
}
/**
+ * TODO: Copy/Paste with {@link com.jetbrains.python.psi.PyArgumentList#addArgument(com.jetbrains.python.psi.PyExpression)}
* Adds an argument to the end of argument list.
* @param us the arg list
* @param expression what to add
@@ -507,7 +508,9 @@
}
}
}
- else if (((PyFile)call.getContainingFile()).getLanguageLevel().isPy3K() && containingClass != null) {
+ else if ((call.getContainingFile() instanceof PyFile) &&
+ ((PyFile)call.getContainingFile()).getLanguageLevel().isPy3K() &&
+ (containingClass != null)) {
return new Maybe<PyType>(getSuperClassUnionType(containingClass));
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
index 877e5fb..afca292 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyClassImpl.java
@@ -148,6 +148,7 @@
pyVisitor.visitPyClass(this);
}
+ @Override
@NotNull
public PyStatementList getStatementList() {
final PyStatementList statementList = childToPsi(PyElementTypes.STATEMENT_LIST);
diff --git a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
index 1a8f123..c306116 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyElementGeneratorImpl.java
@@ -15,6 +15,8 @@
*/
package com.jetbrains.python.psi.impl;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Queues;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -23,9 +25,12 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileFactory;
import com.intellij.psi.impl.PsiFileFactoryImpl;
+import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.IncorrectOperationException;
+import com.jetbrains.NotNullPredicate;
import com.jetbrains.python.PyTokenTypes;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.PythonLanguage;
@@ -37,12 +42,15 @@
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.util.Arrays;
+import java.util.Collection;
+import java.util.Deque;
import java.util.Formatter;
/**
* @author yole
*/
public class PyElementGeneratorImpl extends PyElementGenerator {
+ private static final CommasOnly COMMAS_ONLY = new CommasOnly();
private final Project myProject;
public PyElementGeneratorImpl(Project project) {
@@ -173,6 +181,30 @@
return dot.copyElement();
}
+ @Override
+ @NotNull
+ public PsiElement insertItemIntoListRemoveRedundantCommas(
+ @NotNull final PyElement list,
+ @Nullable final PyExpression afterThis,
+ @NotNull final PyExpression toInsert) {
+ // TODO: #insertItemIntoList is probably buggy. In such case, fix it and get rid of this method
+ final PsiElement result = insertItemIntoList(list, afterThis, toInsert);
+ final LeafPsiElement[] leafs = PsiTreeUtil.getChildrenOfType(list, LeafPsiElement.class);
+ if (leafs != null) {
+ final Deque<LeafPsiElement> commas = Queues.newArrayDeque(Collections2.filter(Arrays.asList(leafs), COMMAS_ONLY));
+ if (! commas.isEmpty()) {
+ final LeafPsiElement lastComma = commas.getLast();
+ if (PsiTreeUtil.getNextSiblingOfType(lastComma, PyExpression.class) == null) { //Comma has no expression after it
+ lastComma.delete();
+ }
+ }
+ }
+
+ return result;
+ }
+
+ // TODO: Adds comma to empty list: adding "foo" to () will create (foo,). That is why "insertItemIntoListRemoveRedundantCommas" was created.
+ // We probably need to fix this method and delete insertItemIntoListRemoveRedundantCommas
public PsiElement insertItemIntoList(PyElement list, @Nullable PyExpression afterThis, PyExpression toInsert)
throws IncorrectOperationException {
ASTNode add = toInsert.getNode().copyElement();
@@ -225,6 +257,7 @@
return createExpressionFromText(LanguageLevel.getDefault(), text);
}
+ @NotNull
public PyExpression createExpressionFromText(final LanguageLevel languageLevel, final String text) {
final PsiFile dummyFile = createDummyFile(languageLevel, text);
final PsiElement element = dummyFile.getFirstChild();
@@ -364,4 +397,11 @@
return createFromText(LanguageLevel.getDefault(),
PyExpressionStatement.class, content + "\n");
}
+
+ private static class CommasOnly extends NotNullPredicate<LeafPsiElement> {
+ @Override
+ protected boolean applyNotNull(@NotNull final LeafPsiElement input) {
+ return input.getNode().getElementType().equals(PyTokenTypes.COMMA);
+ }
+ }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
index 68aaa79..1fa4b21 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFileImpl.java
@@ -59,8 +59,7 @@
private final Map<FutureFeature, Boolean> myFutureFeatures;
private List<String> myDunderAll;
private boolean myDunderAllCalculated;
- private SoftReference<ExportedNameCache> myExportedNameCache = new SoftReference<ExportedNameCache>(null);
- private final Object myENCLock = new Object();
+ private volatile SoftReference<ExportedNameCache> myExportedNameCache = new SoftReference<ExportedNameCache>(null);
private final PsiModificationTracker myModificationTracker;
private class ExportedNameCache {
@@ -305,19 +304,12 @@
}
public boolean isAcceptedFor(@NotNull Class visitorClass) {
- final FileViewProvider viewProvider = getViewProvider();
- final Language lang;
- if (viewProvider instanceof TemplateLanguageFileViewProvider) {
- lang = viewProvider.getBaseLanguage();
- }
- else {
- lang = getLanguage();
- }
- final List<PythonVisitorFilter> filters = PythonVisitorFilter.INSTANCE.allForLanguage(lang);
- if (filters.isEmpty()) return true;
- for (PythonVisitorFilter filter : filters) {
- if (!filter.isSupported(visitorClass, this))
- return false;
+ for (Language lang : getViewProvider().getLanguages()) {
+ final List<PythonVisitorFilter> filters = PythonVisitorFilter.INSTANCE.allForLanguage(lang);
+ for (PythonVisitorFilter filter : filters) {
+ if (!filter.isSupported(visitorClass, this))
+ return false;
+ }
}
return true;
}
@@ -441,17 +433,15 @@
private ExportedNameCache getExportedNameCache() {
ExportedNameCache cache;
- synchronized (myENCLock) {
- cache = myExportedNameCache != null ? myExportedNameCache.get() : null;
- final long modificationStamp = getModificationStamp();
- if (myExportedNameCache != null && cache != null && modificationStamp != cache.getModificationStamp()) {
- myExportedNameCache.clear();
- cache = null;
- }
- if (cache == null) {
- cache = new ExportedNameCache(modificationStamp);
- myExportedNameCache = new SoftReference<ExportedNameCache>(cache);
- }
+ cache = myExportedNameCache != null ? myExportedNameCache.get() : null;
+ final long modificationStamp = getModificationStamp();
+ if (myExportedNameCache != null && cache != null && modificationStamp != cache.getModificationStamp()) {
+ myExportedNameCache.clear();
+ cache = null;
+ }
+ if (cache == null) {
+ cache = new ExportedNameCache(modificationStamp);
+ myExportedNameCache = new SoftReference<ExportedNameCache>(cache);
}
return cache;
}
@@ -747,9 +737,7 @@
ControlFlowCache.clear(this);
myDunderAllCalculated = false;
myFutureFeatures.clear(); // probably no need to synchronize
- synchronized (myENCLock) {
- myExportedNameCache.clear();
- }
+ myExportedNameCache.clear();
}
@Override
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
index 82b21ad..53dea09 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionBuilder.java
@@ -20,25 +20,78 @@
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.util.ArrayUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
-import com.jetbrains.python.psi.LanguageLevel;
-import com.jetbrains.python.psi.PyElementGenerator;
-import com.jetbrains.python.psi.PyFunction;
+import com.jetbrains.python.psi.*;
+
+import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.regex.Pattern;
/**
* @author yole
*/
public class PyFunctionBuilder {
+ private static final String COMMENTS_BOUNDARY = "\"\"\"";
+ private static final Pattern INDENT_REMOVE_PATTERN = Pattern.compile("^\\s+", Pattern.MULTILINE);
private final String myName;
private final List<String> myParameters = new ArrayList<String>();
private final List<String> myStatements = new ArrayList<String>();
private final List<String> myDecorators = new ArrayList<String>();
private String myAnnotation = null;
+ private String[] myDocStringLines = null;
+
+ /**
+ * Creates builder copying signature and doc from another one.
+ * @param source what to copy
+ * @param decoratorsToCopyIfExist list of decorator names to be copied to new function.
+ * @return builder configured by this function
+ */
+ @NotNull
+ public static PyFunctionBuilder copySignature(@NotNull final PyFunction source, @NotNull final String... decoratorsToCopyIfExist) {
+ final String name = source.getName();
+ final PyFunctionBuilder functionBuilder = new PyFunctionBuilder((name != null) ? name : "");
+ for (final PyParameter parameter : source.getParameterList().getParameters()) {
+ final String parameterName = parameter.getName();
+ if (parameterName != null) {
+ functionBuilder.parameter(parameterName);
+ }
+ }
+ final PyDecoratorList decoratorList = source.getDecoratorList();
+ if (decoratorList != null) {
+ for (final PyDecorator decorator : decoratorList.getDecorators()) {
+ final String decoratorName = decorator.getName();
+ if (decoratorName != null) {
+ if (ArrayUtil.contains(decoratorName, decoratorsToCopyIfExist)) {
+ functionBuilder.decorate(decoratorName);
+ }
+ }
+ }
+ }
+ final String docString = source.getDocStringValue();
+ if (docString != null) {
+ functionBuilder.docString(docString);
+ }
+ return functionBuilder;
+ }
+
+ /**
+ * Adds docstring to function. Provide doc with out of comment blocks.
+ * @param docString doc
+ */
+ public void docString(@NotNull final String docString) {
+ myDocStringLines = StringUtil.splitByLines(removeIndent(docString));
+ }
+
+ @NotNull
+ private String removeIndent(@NotNull final String string) {
+ return INDENT_REMOVE_PATTERN.matcher(string).replaceAll("");
+ }
public PyFunctionBuilder(String name) {
myName = name;
@@ -47,7 +100,7 @@
public PyFunctionBuilder parameter(String baseName) {
String name = baseName;
int uniqueIndex = 0;
- while(myParameters.contains(name)) {
+ while (myParameters.contains(name)) {
uniqueIndex++;
name = baseName + uniqueIndex;
}
@@ -66,11 +119,11 @@
}
public PyFunction addFunction(PsiElement target, final LanguageLevel languageLevel) {
- return (PyFunction) target.add(buildFunction(target.getProject(), languageLevel));
+ return (PyFunction)target.add(buildFunction(target.getProject(), languageLevel));
}
public PyFunction addFunctionAfter(PsiElement target, PsiElement anchor, final LanguageLevel languageLevel) {
- return (PyFunction) target.addAfter(buildFunction(target.getProject(), languageLevel), anchor);
+ return (PyFunction)target.addAfter(buildFunction(target.getProject(), languageLevel), anchor);
}
public PyFunction buildFunction(Project project, final LanguageLevel languageLevel) {
@@ -93,6 +146,16 @@
}
builder.append(":");
List<String> statements = myStatements.isEmpty() ? Collections.singletonList(PyNames.PASS) : myStatements;
+
+ if (myDocStringLines != null) {
+ final List<String> comments = new ArrayList<String>(myDocStringLines.length + 2);
+ comments.add(COMMENTS_BOUNDARY);
+ comments.addAll(Arrays.asList(myDocStringLines));
+ comments.add(COMMENTS_BOUNDARY);
+ statements = new ArrayList<String>(statements);
+ statements.addAll(0, comments);
+ }
+
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings();
int indentSize = codeStyleSettings.getIndentOptions(PythonFileType.INSTANCE).INDENT_SIZE;
String indent = StringUtil.repeatSymbol(' ', indentSize);
@@ -105,4 +168,11 @@
public void decorate(String decoratorName) {
myDecorators.add("@" + decoratorName);
}
+
+ @NotNull
+ private static String getIndent(@NotNull final Project project) {
+ final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings();
+ final int indentSize = codeStyleSettings.getIndentOptions(PythonFileType.INSTANCE).INDENT_SIZE;
+ return StringUtil.repeatSymbol(' ', indentSize);
+ }
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
index 8c71346..2ffc8e6 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyFunctionImpl.java
@@ -143,9 +143,12 @@
return getRequiredStubOrPsiChild(PyElementTypes.PARAMETER_LIST);
}
- @Nullable
+ @Override
+ @NotNull
public PyStatementList getStatementList() {
- return childToPsi(PyElementTypes.STATEMENT_LIST);
+ final PyStatementList statementList = childToPsi(PyElementTypes.STATEMENT_LIST);
+ assert statementList != null : "Statement list missing for function " + getText();
+ return statementList;
}
public PyClass getContainingClass() {
diff --git a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
index 9c34062..6ad33d6 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyNamedParameterImpl.java
@@ -238,6 +238,9 @@
if (defaultValue != null) {
final PyType type = context.getType(defaultValue);
if (type != null && !(type instanceof PyNoneType)) {
+ if (type instanceof PyTupleType) {
+ return PyTypeParser.getTypeByName(this, "collections.Iterable");
+ }
return type;
}
}
@@ -249,15 +252,18 @@
@Override
public boolean process(@NotNull PyCallExpression call) {
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(context);
- final CallArgumentsMapping mapping = call.getArgumentList().analyzeCall(resolveContext);
- for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.getPlainMappedParams().entrySet()) {
- if (entry.getValue() == PyNamedParameterImpl.this) {
- final PyExpression argument = entry.getKey();
- if (argument != null) {
- final PyType type = context.getType(argument);
- if (type != null) {
- types.add(type);
- return true;
+ final PyArgumentList argumentList = call.getArgumentList();
+ if (argumentList != null) {
+ final CallArgumentsMapping mapping = argumentList.analyzeCall(resolveContext);
+ for (Map.Entry<PyExpression, PyNamedParameter> entry : mapping.getPlainMappedParams().entrySet()) {
+ if (entry.getValue() == PyNamedParameterImpl.this) {
+ final PyExpression argument = entry.getKey();
+ if (argument != null) {
+ final PyType type = context.getType(argument);
+ if (type != null) {
+ types.add(type);
+ return true;
+ }
}
}
}
diff --git a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
index c5e60eb..47ae589 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyReferenceExpressionImpl.java
@@ -17,6 +17,7 @@
import com.intellij.lang.ASTNode;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.extensions.ExtensionException;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.*;
@@ -309,7 +310,7 @@
}
}
catch (AbstractMethodError e) {
- LOG.info(e);
+ LOG.info(new ExtensionException(provider.getClass()));
}
}
return null;
diff --git a/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
index 340ae09..bf51973 100644
--- a/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
+++ b/python/src/com/jetbrains/python/psi/impl/PyStringLiteralExpressionImpl.java
@@ -218,7 +218,15 @@
str = unicode ? new String(new char[]{(char)Integer.parseInt(unicode16, 16)}) : wholeMatch;
}
else if (escapedUnicode && unicode32 != null) {
- str = unicode ? new String(Character.toChars((int)Long.parseLong(unicode32, 16))) : wholeMatch;
+ String s = wholeMatch;
+ if (unicode) {
+ try {
+ s = new String(Character.toChars((int)Long.parseLong(unicode32, 16)));
+ }
+ catch (IllegalArgumentException ignored) {
+ }
+ }
+ str = s;
}
else if (raw) {
str = wholeMatch;
diff --git a/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java b/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java
index 4a7f084..bb29b7a 100644
--- a/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java
+++ b/python/src/com/jetbrains/python/psi/search/PyClassInheritorsSearchExecutor.java
@@ -56,8 +56,8 @@
if (processed.contains(superClass)) return true;
processed.add(superClass);
Project project = superClass.getProject();
- final Collection<PyClass> candidates = StubIndex.getInstance().get(PySuperClassIndex.KEY, superClassName, project,
- ProjectScope.getAllScope(project));
+ final Collection<PyClass> candidates = StubIndex.getElements(PySuperClassIndex.KEY, superClassName, project,
+ ProjectScope.getAllScope(project), PyClass.class);
for (PyClass candidate : candidates) {
final PyClass[] classes = candidate.getSuperClasses();
for (PyClass superClassCandidate : classes) {
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndex.java
index 8aed157..814f450 100644
--- a/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndex.java
+++ b/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndex.java
@@ -41,7 +41,7 @@
}
public static Collection<PyClass> find(String name, Project project, GlobalSearchScope scope) {
- return StubIndex.getInstance().get(KEY, name, project, scope);
+ return StubIndex.getElements(KEY, name, project, scope, PyClass.class);
}
public static Collection<PyClass> find(String name, Project project, boolean includeNonProjectItems) {
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java b/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java
index e65ba65..a275426 100644
--- a/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java
+++ b/python/src/com/jetbrains/python/psi/stubs/PyClassNameIndexInsensitive.java
@@ -38,6 +38,6 @@
}
public static Collection<PyClass> find(String name, Project project) {
- return StubIndex.getInstance().get(KEY, name.toLowerCase(), project, ProjectScope.getProjectScope(project));
+ return StubIndex.getElements(KEY, name.toLowerCase(), project, ProjectScope.getProjectScope(project), PyClass.class);
}
}
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java
index 8b01c2b..ba87608 100644
--- a/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java
+++ b/python/src/com/jetbrains/python/psi/stubs/PyFunctionNameIndex.java
@@ -39,11 +39,11 @@
}
public static Collection<PyFunction> find(String name, Project project, GlobalSearchScope scope) {
- return StubIndex.getInstance().get(KEY, name, project, scope);
+ return StubIndex.getElements(KEY, name, project, scope, PyFunction.class);
}
public static Collection<PyFunction> find(String name, Project project) {
- return StubIndex.getInstance().get(KEY, name, project, ProjectScope.getAllScope(project));
+ return StubIndex.getElements(KEY, name, project, ProjectScope.getAllScope(project), PyFunction.class);
}
public static Collection<String> allKeys(Project project) {
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java
index 94b196f..58ea933 100644
--- a/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java
+++ b/python/src/com/jetbrains/python/psi/stubs/PyInstanceAttributeIndex.java
@@ -43,6 +43,6 @@
}
public static Collection<PyTargetExpression> find(String name, Project project, GlobalSearchScope scope) {
- return StubIndex.getInstance().get(KEY, name, project, scope);
+ return StubIndex.getElements(KEY, name, project, scope, PyTargetExpression.class);
}
}
diff --git a/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java b/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java
index ca7b420..1fce6df 100644
--- a/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java
+++ b/python/src/com/jetbrains/python/psi/stubs/PyVariableNameIndex.java
@@ -42,6 +42,6 @@
}
public static Collection<PyTargetExpression> find(String name, Project project, GlobalSearchScope scope) {
- return StubIndex.getInstance().get(KEY, name, project, scope);
+ return StubIndex.getElements(KEY, name, project, scope, PyTargetExpression.class);
}
}
diff --git a/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java b/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java
index bde4559..6d33b68 100644
--- a/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java
+++ b/python/src/com/jetbrains/python/psi/types/functionalParser/FunctionalParserBase.java
@@ -203,11 +203,9 @@
myCache.clear();
}
final SoftReference<Pair<R, State>> ref = myCache.get(state.getPos());
- if (ref != null) {
- final Pair<R, State> cached = ref.get();
- if (cached != null) {
- return cached;
- }
+ final Pair<R, State> cached = SoftReference.dereference(ref);
+ if (cached != null) {
+ return cached;
}
final Pair<R, State> result = myParser.parse(tokens, state);
myCache.put(state.getPos(), new SoftReference<Pair<R, State>>(result));
diff --git a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java
index 200c11e..719bc83 100644
--- a/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/changeSignature/PyChangeSignatureHandler.java
@@ -17,8 +17,6 @@
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.actionSystem.LangDataKeys;
-import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -171,9 +169,9 @@
REFACTORING_NAME, Messages.getQuestionIcon());
}
switch (choice) {
- case 0:
+ case Messages.YES:
return deepestSuperMethod;
- case 1:
+ case Messages.NO:
return function;
default:
return null;
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java
index 71f920c..d2a0b0a 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassMembersRefactoringSupport.java
@@ -22,6 +22,7 @@
import com.intellij.refactoring.classMembers.MemberInfoBase;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
/**
* @author Dennis.Ushakov
@@ -30,7 +31,7 @@
public static PyMemberInfoStorage getSelectedMemberInfos(PyClass clazz, PsiElement element1, PsiElement element2) {
final PyMemberInfoStorage infoStorage = new PyMemberInfoStorage(clazz);
- for (PyMemberInfo member : infoStorage.getClassMemberInfos(clazz)) {
+ for (PyMemberInfo<PyElement> member : infoStorage.getClassMemberInfos(clazz)) {
final PyElement function = member.getMember();
member.setChecked(PsiTreeUtil.isAncestor(function, element1, false) ||
PsiTreeUtil.isAncestor(function, element2, false));
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringHandler.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringHandler.java
index ebb20ff..54c5dd1 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringHandler.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.LangDataKeys;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
+import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
@@ -31,6 +32,7 @@
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyUtil;
import org.jetbrains.annotations.NotNull;
/**
@@ -68,7 +70,27 @@
doRefactor(project, elements[0], elements[elements.length - 1], editor, file, dataContext);
}
- protected abstract void doRefactor(Project project, PsiElement element1, PsiElement element2, Editor editor, PsiFile file, DataContext dataContext);
+ private void doRefactor(Project project, PsiElement element1, PsiElement element2, Editor editor, PsiFile file, DataContext dataContext) {
+ if (ApplicationManagerEx.getApplicationEx().isUnitTestMode()) return;
+
+ CommonRefactoringUtil.checkReadOnlyStatus(project, file);
+
+ final PyClass clazz = PyUtil.getContainingClassOrSelf(element1);
+ if (!inClass(clazz, project, editor, "refactoring.pull.up.error.cannot.perform.refactoring.not.inside.class")) return;
+ assert clazz != null;
+
+ final PyMemberInfoStorage infoStorage = PyClassMembersRefactoringSupport.getSelectedMemberInfos(clazz, element1, element2);
+
+ doRefactorImpl(project, clazz, infoStorage, editor);
+ }
+
+
+ protected abstract void doRefactorImpl(@NotNull final Project project,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage,
+ @NotNull final Editor editor);
+
+
protected boolean inClass(PyClass clazz, Project project, Editor editor, String errorMessageId) {
if (clazz == null) {
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
index 9b11d15..1033661 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyClassRefactoringUtil.java
@@ -15,21 +15,24 @@
*/
package com.jetbrains.python.refactoring.classes;
+import com.google.common.collect.Collections2;
+import com.intellij.lang.ASTNode;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtilBase;
-import com.intellij.psi.util.PsiUtilCore;
import com.intellij.psi.util.QualifiedName;
+import com.intellij.util.ArrayUtil;
+import com.jetbrains.NotNullPredicate;
import com.jetbrains.python.PyNames;
-import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.codeInsight.PyCodeInsightSettings;
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
+import com.jetbrains.python.codeInsight.imports.PyImportOptimizer;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyImportedModule;
@@ -43,137 +46,124 @@
/**
* @author Dennis.Ushakov
*/
-public class PyClassRefactoringUtil {
+public final class PyClassRefactoringUtil {
private static final Logger LOG = Logger.getInstance(PyClassRefactoringUtil.class.getName());
private static final Key<PsiNamedElement> ENCODED_IMPORT = Key.create("PyEncodedImport");
private static final Key<Boolean> ENCODED_USE_FROM_IMPORT = Key.create("PyEncodedUseFromImport");
private static final Key<String> ENCODED_IMPORT_AS = Key.create("PyEncodedImportAs");
- private PyClassRefactoringUtil() {}
- public static void moveSuperclasses(PyClass clazz, Set<String> superClasses, PyClass superClass) {
- if (superClasses.size() == 0) return;
- final Project project = clazz.getProject();
- final List<PyExpression> toAdd = removeAndGetSuperClasses(clazz, superClasses);
- addSuperclasses(project, superClass, toAdd, superClasses);
+ private PyClassRefactoringUtil() {
}
- public static void addSuperclasses(Project project, PyClass superClass,
- @Nullable Collection<PyExpression> superClassesAsPsi,
- Collection<String> superClassesAsStrings) {
- if (superClassesAsStrings.size() == 0) return;
- PyArgumentList argList = superClass.getSuperClassExpressionList();
- if (argList != null) {
- if (superClassesAsPsi != null) {
- for (PyExpression element : superClassesAsPsi) {
- argList.addArgument(element);
- }
- }
- else {
- for (String s : superClassesAsStrings) {
- argList.addArgument(PyElementGenerator.getInstance(project).createExpressionFromText(s));
- }
- }
- } else {
- addSuperclasses(project, superClass, superClassesAsStrings);
+
+ /**
+ * Copies class field declarations to some other place
+ *
+ * @param assignmentStatement list of class fields
+ * @return new (copied) fields
+ */
+ @NotNull
+ public static List<PyAssignmentStatement> copyFieldDeclarationToStatement(@NotNull final Collection<PyAssignmentStatement> assignmentStatement,
+ @NotNull final PyStatementList superClassStatement) {
+ final List<PyAssignmentStatement> declations = new ArrayList<PyAssignmentStatement>(assignmentStatement.size());
+ for (final PyAssignmentStatement expression : assignmentStatement) {
+ final PyAssignmentStatement newDeclaration = (PyAssignmentStatement)expression.copy();
+ declations.add((PyAssignmentStatement)PyUtil.addElementToStatementList(newDeclaration, superClassStatement, true));
+ PyPsiUtils.removeRedundantPass(superClassStatement);
}
+ return declations;
}
- public static List<PyExpression> removeAndGetSuperClasses(PyClass clazz, Set<String> superClasses) {
- if (superClasses.size() == 0) return Collections.emptyList();
- final List<PyExpression> toAdd = new ArrayList<PyExpression>();
- final PyExpression[] elements = clazz.getSuperClassExpressions();
- for (PyExpression element : elements) {
- if (superClasses.contains(element.getText())) {
- toAdd.add(element);
- PyUtil.removeListNode(element);
- }
+ @NotNull
+ public static List<PyFunction> copyMethods(Collection<PyFunction> methods, PyClass superClass) {
+ if (methods.isEmpty()) {
+ return Collections.emptyList();
}
- return toAdd;
- }
-
- public static void addSuperclasses(Project project, PyClass superClass, Collection<String> superClasses) {
- if (superClasses.size() == 0) return;
- final StringBuilder builder = new StringBuilder("(");
- boolean hasChanges = false;
- for (String element : superClasses) {
- if (builder.length() > 1) builder.append(",");
- if (!alreadyHasSuperClass(superClass, element)) {
- builder.append(element);
- hasChanges = true;
- }
- }
- builder.append(")");
- if (!hasChanges) return;
-
- final PsiFile file = PsiFileFactory.getInstance(project).createFileFromText(superClass.getName() + "temp", PythonFileType.INSTANCE, builder.toString());
- final PsiElement expression = file.getFirstChild().getFirstChild();
- PsiElement colon = superClass.getFirstChild();
- while (colon != null && !colon.getText().equals(":")) {
- colon = colon.getNextSibling();
- }
- LOG.assertTrue(colon != null && expression != null);
- PyPsiUtils.addBeforeInParent(colon, expression);
- }
-
- private static boolean alreadyHasSuperClass(PyClass superClass, String className) {
- for (PyClass aClass : superClass.getSuperClasses()) {
- if (Comparing.strEqual(aClass.getName(), className)) {
- return true;
- }
- }
- return false;
- }
-
- public static void moveMethods(Collection<PyFunction> methods, PyClass superClass) {
- if (methods.size() == 0) return;
for (PsiElement e : methods) {
rememberNamedReferences(e);
}
- final PyElement[] elements = methods.toArray(new PyElement[methods.size()]);
- addMethods(superClass, elements, true);
- removeMethodsWithComments(elements);
+ final PyFunction[] elements = methods.toArray(new PyFunction[methods.size()]);
+ return addMethods(superClass, elements);
}
- private static void removeMethodsWithComments(PyElement[] elements) {
- for (PyElement element : elements) {
- final Set<PsiElement> comments = PyUtil.getComments(element);
- if (comments.size() > 0) {
- PyPsiUtils.removeElements(PsiUtilCore.toPsiElementArray(comments));
+ /**
+ * Adds methods to class.
+ *
+ * @param destination where to add methods
+ * @param methods methods
+ * @return newly added methods
+ */
+ @NotNull
+ public static List<PyFunction> addMethods(@NotNull final PyClass destination, @NotNull final PyFunction... methods) {
+
+ final PyStatementList destStatementList = destination.getStatementList();
+ final List<PyFunction> newlyCreatedMethods = new ArrayList<PyFunction>(methods.length);
+
+ for (final PyFunction method : methods) {
+
+ if (destination.findMethodByName(method.getName(), false) != null) {
+ continue; //We skip adding if class already has this method. I am not sure if this behaviour is correct, but it was here, so I left if for backward compatibility
+ }
+
+
+ final PyFunction newMethod = insertMethodInProperPlace(destStatementList, method);
+ newlyCreatedMethods.add(newMethod);
+ restoreNamedReferences(newMethod);
+ }
+
+ PyPsiUtils.removeRedundantPass(destStatementList);
+ return newlyCreatedMethods;
+ }
+
+ /**
+ * Adds init methods before all other methods (but after class vars and docs).
+ * Adds all other methods to the bottom
+ *
+ * @param destStatementList where to add methods
+ * @param method method to add
+ * @return newlty added method
+ */
+ @NotNull
+ private static PyFunction insertMethodInProperPlace(
+ @NotNull final PyStatementList destStatementList,
+ @NotNull final PyFunction method) {
+ boolean methodIsInit = PyUtil.isInit(method);
+ if (!methodIsInit) {
+ //Not init method could be inserted in the bottom
+ return (PyFunction)destStatementList.add(method);
+ }
+
+ //We should find appropriate place for init
+ for (final PsiElement element : destStatementList.getChildren()) {
+ final boolean elementComment = element instanceof PyExpressionStatement;
+ final boolean elementClassField = element instanceof PyAssignmentStatement;
+
+ if (!(elementComment || elementClassField)) {
+ return (PyFunction)destStatementList.addBefore(method, element);
}
}
- PyPsiUtils.removeElements(elements);
+ return (PyFunction)destStatementList.add(method);
}
- public static void insertPassIfNeeded(PyClass clazz) {
- final PyStatementList statements = clazz.getStatementList();
+
+ public static <T extends PyElement & PyStatementListContainer> void insertPassIfNeeded(@NotNull T element) {
+ final PyStatementList statements = element.getStatementList();
if (statements.getStatements().length == 0) {
- statements.add(PyElementGenerator.getInstance(clazz.getProject()).createFromText(LanguageLevel.getDefault(), PyPassStatement.class, PyNames.PASS));
+ statements.add(
+ PyElementGenerator.getInstance(element.getProject())
+ .createFromText(LanguageLevel.getDefault(), PyPassStatement.class, PyNames.PASS)
+ );
}
}
- public static void addMethods(final PyClass superClass, final PyElement[] elements, final boolean up) {
- if (elements.length == 0) return;
- final PyStatementList statements = superClass.getStatementList();
- for (PyElement newStatement : elements) {
- if (up && newStatement instanceof PyFunction) {
- final String name = newStatement.getName();
- if (name != null && superClass.findMethodByName(name, false) != null) {
- continue;
- }
- }
- if (newStatement instanceof PyExpressionStatement && newStatement.getFirstChild() instanceof PyStringLiteralExpression) continue;
- final PsiElement anchor = statements.add(newStatement);
- restoreNamedReferences(anchor);
- final Set<PsiElement> comments = PyUtil.getComments(newStatement);
- for (PsiElement comment : comments) {
- statements.addBefore(comment, anchor);
- }
- }
- PyPsiUtils.removeRedundantPass(statements);
- }
-
- public static void restoreNamedReferences(@NotNull PsiElement element) {
+ /**
+ * Restores references saved by {@link #rememberNamedReferences(com.intellij.psi.PsiElement, String...)}.
+ *
+ * @param element newly created element to restore references
+ * @see #rememberNamedReferences(com.intellij.psi.PsiElement, String...)
+ */
+ public static void restoreNamedReferences(@NotNull final PsiElement element) {
restoreNamedReferences(element, null);
}
@@ -197,6 +187,7 @@
});
}
+
private static void restoreReference(final PyReferenceExpression node) {
PsiNamedElement target = node.getCopyableUserData(ENCODED_IMPORT);
final String asName = node.getCopyableUserData(ENCODED_IMPORT_AS);
@@ -238,7 +229,7 @@
if (components.isEmpty()) {
return false;
}
- for (String s: components) {
+ for (String s : components) {
if (!PyNames.isIdentifier(s) || PyNames.isReserved(s)) {
return false;
}
@@ -282,7 +273,16 @@
}
}
- public static void rememberNamedReferences(@NotNull final PsiElement element) {
+ /**
+ * Searches for references inside some element (like {@link com.jetbrains.python.psi.PyAssignmentStatement}, {@link com.jetbrains.python.psi.PyFunction} etc
+ * and stored them.
+ * After that you can add element to some new parent. Newly created element then should be processed via {@link #restoreNamedReferences(com.intellij.psi.PsiElement)}
+ * and all references would be restored.
+ *
+ * @param element element to store references for
+ * @param namesToSkip if reference inside of element has one of this names, it will not be saved.
+ */
+ public static void rememberNamedReferences(@NotNull final PsiElement element, @NotNull final String... namesToSkip) {
element.acceptChildren(new PyRecursiveElementVisitor() {
@Override
public void visitPyReferenceExpression(PyReferenceExpression node) {
@@ -294,7 +294,9 @@
if (importElement != null && PsiTreeUtil.isAncestor(element, importElement, false)) {
return;
}
- rememberReference(node, element);
+ if (!ArrayUtil.contains(node.getText(), namesToSkip)) { //Do not remember name if it should be skipped
+ rememberReference(node, element);
+ }
}
});
}
@@ -346,7 +348,7 @@
final String name = getOriginalName(element);
if (name != null) {
PyImportElement importElement = null;
- for (PyImportElement e: importStatement.getImportElements()) {
+ for (PyImportElement e : importStatement.getImportElements()) {
if (name.equals(getOriginalName(e))) {
importElement = e;
}
@@ -363,11 +365,14 @@
}
if (deleteImportElement) {
if (importStatement.getImportElements().length == 1) {
- final boolean isInjected = InjectedLanguageManager.getInstance(importElement.getProject()).isInjectedFragment(importElement.getContainingFile());
- if (!isInjected)
+ final boolean isInjected =
+ InjectedLanguageManager.getInstance(importElement.getProject()).isInjectedFragment(importElement.getContainingFile());
+ if (!isInjected) {
importStatement.delete();
- else
+ }
+ else {
deleteImportStatementFromInjected(importStatement);
+ }
}
else {
importElement.delete();
@@ -380,8 +385,7 @@
private static void deleteImportStatementFromInjected(@NotNull final PyImportStatementBase importStatement) {
final PsiElement sibling = importStatement.getPrevSibling();
importStatement.delete();
- if (sibling instanceof PsiWhiteSpace)
- sibling.delete();
+ if (sibling instanceof PsiWhiteSpace) sibling.delete();
}
@Nullable
@@ -404,4 +408,108 @@
}
return null;
}
+
+ /**
+ * Adds super classes to certain class.
+ *
+ * @param project project where refactoring takes place
+ * @param clazz destination
+ * @param superClasses classes to add
+ */
+ public static void addSuperclasses(@NotNull final Project project,
+ @NotNull final PyClass clazz,
+ @NotNull final PyClass... superClasses) {
+
+ final Collection<String> superClassNames = new ArrayList<String>();
+
+
+ for (final PyClass superClass : Collections2.filter(Arrays.asList(superClasses), NotNullPredicate.INSTANCE)) {
+ if (superClass.getName() != null) {
+ superClassNames.add(superClass.getName());
+ insertImport(clazz, superClass);
+ }
+ }
+
+ addSuperClassExpressions(project, clazz, superClassNames, null);
+ }
+
+
+ /**
+ * Adds expressions to superclass list
+ *
+ * @param project project
+ * @param clazz class to add expressions to superclass list
+ * @param paramExpressions param expressions. Like "object" or "MySuperClass". Will not add any param exp. if null.
+ * @param keywordArguments keyword args like "metaclass=ABCMeta". key-value pairs. Will not add any keyword arg. if null.
+ */
+ public static void addSuperClassExpressions(@NotNull final Project project,
+ @NotNull final PyClass clazz,
+ @Nullable final Collection<String> paramExpressions,
+ @Nullable final Collection<Pair<String, String>> keywordArguments) {
+ final PyElementGenerator generator = PyElementGenerator.getInstance(project);
+ final LanguageLevel languageLevel = LanguageLevel.forElement(clazz);
+
+ PyArgumentList superClassExpressionList = clazz.getSuperClassExpressionList();
+ boolean addExpression = false;
+ if (superClassExpressionList == null) {
+ superClassExpressionList = generator.createFromText(languageLevel, PyClass.class, "class foo():pass").getSuperClassExpressionList();
+ assert superClassExpressionList != null : "expression not created";
+ addExpression = true;
+ }
+
+
+ generator.createFromText(LanguageLevel.PYTHON34, PyClass.class, "class foo(object, metaclass=Foo): pass").getSuperClassExpressionList();
+ if (paramExpressions != null) {
+ for (final String paramExpression : paramExpressions) {
+ superClassExpressionList.addArgument(generator.createParameter(paramExpression));
+ }
+ }
+
+ if (keywordArguments != null) {
+ for (final Pair<String, String> keywordArgument : keywordArguments) {
+ superClassExpressionList.addArgument(generator.createKeywordArgument(languageLevel, keywordArgument.first, keywordArgument.second));
+ }
+ }
+
+ // If class has no expression list, then we need to add it manually.
+ if (addExpression) {
+ final ASTNode classNameNode = clazz.getNameNode(); // For nameless classes we simply add expression list directly to them
+ final PsiElement elementToAddAfter = (classNameNode == null) ? clazz.getFirstChild() : classNameNode.getPsi();
+ clazz.addAfter(superClassExpressionList, elementToAddAfter);
+ }
+ }
+
+ /**
+ * Optimizes imports resorting them and removing unneeded
+ *
+ * @param file file to optimize imports
+ */
+ public static void optimizeImports(@NotNull final PsiFile file) {
+ new PyImportOptimizer().processFile(file).run();
+ }
+
+ /**
+ * Adds class attributeName (field) if it does not exist. like __metaclass__ = ABCMeta. Or CLASS_FIELD = 42.
+ *
+ * @param aClass where to add
+ * @param attributeName attribute's name. Like __metaclass__ or CLASS_FIELD
+ * @param value it's value. Like ABCMeta or 42.
+ * @return newly inserted attribute
+ */
+ @Nullable
+ public static PsiElement addClassAttributeIfNotExist(
+ @NotNull final PyClass aClass,
+ @NotNull final String attributeName,
+ @NotNull final String value) {
+ if (aClass.findClassAttribute(attributeName, false) != null) {
+ return null; //Do not add any if exist already
+ }
+ final PyElementGenerator generator = PyElementGenerator.getInstance(aClass.getProject());
+ final String text = String.format("%s = %s", attributeName, value);
+ final LanguageLevel level = LanguageLevel.forElement(aClass);
+
+ final PyAssignmentStatement assignmentStatement = generator.createFromText(level, PyAssignmentStatement.class, text);
+ //TODO: Add metaclass to the top. Add others between last attributeName and first method
+ return PyUtil.addElementToStatementList(assignmentStatement, aClass.getStatementList(), true);
+ }
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java b/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java
index 5c51118..5efb352 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyDependentMembersCollector.java
@@ -29,6 +29,7 @@
@Override
public void collect(PyElement member) {
+ //TODO: Move to MembersManager as well
final PyRecursiveElementVisitor visitor = new PyRecursiveElementVisitor() {
@Override
public void visitPyCallExpression(PyCallExpression node) {
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfo.java b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfo.java
deleted file mode 100644
index 405e6e5..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfo.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes;
-
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.classMembers.MemberInfoBase;
-import com.jetbrains.python.psi.*;
-import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyMemberInfo extends MemberInfoBase<PyElement> {
- public PyMemberInfo(PyElement member) {
- super(member);
- final PyClass clazz = PyUtil.getContainingClassOrSelf(member);
- assert clazz != null;
-
- if (member instanceof PyFunction) {
- PyFunction function = (PyFunction)member;
- displayName = buildDisplayMethodName(function);
- for (PyClass aClass : clazz.getSuperClasses()) {
- final PyFunction parentMethod = aClass.findMethodByName(function.getName(), true);
- if (parentMethod != null) {
- overrides = true;
- }
- }
- } else if (member instanceof PyClass) {
- displayName = RefactoringBundle.message("member.info.extends.0", PyClassCellRenderer.getClassText((PyClass)member));
- }
- }
-
- private static String buildDisplayMethodName(PyFunction method) {
- final StringBuilder builder = new StringBuilder(method.getName());
- builder.append("(");
- final PyParameter[] arguments = method.getParameterList().getParameters();
- for (PyParameter parameter : arguments) {
- builder.append(parameter.getName());
- if (arguments.length > 1 && parameter != arguments[arguments.length - 1]) {
- builder.append(", ");
- }
- }
- builder.append(")");
- return builder.toString();
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof PyMemberInfo) {
- return getMember().equals(((PyMemberInfo)obj).getMember());
- }
- return false;
- }
-
- @Override
- public int hashCode() {
- return getMember().hashCode();
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java
index e5c050a..91d9093 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/PyMemberInfoStorage.java
@@ -15,23 +15,22 @@
*/
package com.jetbrains.python.refactoring.classes;
-import com.intellij.psi.PsiElement;
import com.intellij.refactoring.classMembers.AbstractMemberInfoStorage;
import com.intellij.refactoring.classMembers.MemberInfoBase;
+import com.intellij.util.containers.HashSet;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyFunction;
import com.jetbrains.python.refactoring.PyRefactoringUtil;
+import com.jetbrains.python.refactoring.classes.membersManager.MembersManager;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
/**
* @author Dennis.Ushakov
*/
-public class PyMemberInfoStorage extends AbstractMemberInfoStorage<PyElement, PyClass, PyMemberInfo> {
- private Collection<PyClass> myClasses;
+public class PyMemberInfoStorage extends AbstractMemberInfoStorage<PyElement, PyClass, PyMemberInfo<PyElement>> {
public PyMemberInfoStorage(PyClass aClass) {
this(aClass, new MemberInfoBase.EmptyFilter<PyElement>());
@@ -53,12 +52,8 @@
private void buildSubClassesMapImpl(PyClass aClass, HashSet<PyClass> visited) {
visited.add(aClass);
- if (myClasses == null) {
- myClasses = new HashSet<PyClass>();
- }
for (PyClass clazz : aClass.getSuperClasses()) {
getSubclasses(clazz).add(aClass);
- myClasses.add(clazz);
if (!visited.contains(clazz)) {
buildSubClassesMapImpl(clazz, visited);
}
@@ -66,13 +61,8 @@
}
@Override
- protected void extractClassMembers(PyClass aClass, ArrayList<PyMemberInfo> temp) {
- for (PyFunction function : aClass.getMethods()) {
- temp.add(new PyMemberInfo(function));
- }
- for (PyClass pyClass : aClass.getSuperClasses()) {
- temp.add(new PyMemberInfo(pyClass));
- }
+ protected void extractClassMembers(PyClass aClass, ArrayList<PyMemberInfo<PyElement>> temp) {
+ temp.addAll(MembersManager.getAllMembersCouldBeMoved(aClass));
}
@Override
@@ -80,8 +70,4 @@
return member1 instanceof PyFunction && member instanceof PyFunction &&
PyRefactoringUtil.areConflictingMethods((PyFunction)member, (PyFunction)member1);
}
-
- public Collection<PyClass> getClasses() {
- return myClasses;
- }
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java
deleted file mode 100644
index c0bc437..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassDialog.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.extractSuperclass;
-
-import com.intellij.lang.LanguageNamesValidation;
-import com.intellij.lang.refactoring.NamesValidator;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectRootManager;
-import com.intellij.openapi.ui.TextComponentAccessor;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.classMembers.AbstractUsesDependencyMemberInfoModel;
-import com.intellij.refactoring.classMembers.DependencyMemberInfoModel;
-import com.intellij.refactoring.ui.ConflictsDialog;
-import com.jetbrains.python.PyBundle;
-import com.jetbrains.python.PythonLanguage;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
-import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
-import com.jetbrains.python.refactoring.classes.ui.UpDirectedMembersMovingDialog;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyExtractSuperclassDialog extends UpDirectedMembersMovingDialog {
- private final NamesValidator myNamesValidator = LanguageNamesValidation.INSTANCE.forLanguage(PythonLanguage.getInstance());
- protected JTextField mySourceClassField;
- protected JLabel mySuperNameLabel;
- protected JTextField myExtractedSuperNameField;
- protected TextFieldWithBrowseButton myTargetDirField;
- protected JLabel myDirLabel;
- private static final String FILE_BROWSER_TITLE = "Extract superclass to file or directory:";
-
- public PyExtractSuperclassDialog(Project project, PyClass clazz, PyMemberInfoStorage infoStorage) {
- super(project, clazz);
- myMemberInfos = infoStorage.getClassMemberInfos(myClass);
-
- myExtractedSuperNameField = new JTextField();
- myTargetDirField = new TextFieldWithBrowseButton();
- initSourceClassField();
-
- setTitle(PyExtractSuperclassHandler.REFACTORING_NAME);
-
- init();
- }
-
- protected void initSourceClassField() {
- mySourceClassField = new JTextField();
- mySourceClassField.setEditable(false);
- mySourceClassField.setText(myClass.getName());
- }
-
- @Override
- protected void doOKAction() {
- final String name = getSuperBaseName();
- if (!myNamesValidator.isIdentifier(name, myClass.getProject())) {
- setErrorText(PyBundle.message("refactoring.extract.super.name.0.must.be.ident", name));
- return;
- }
- boolean found_root = false;
- try {
- String target_dir = FileUtil.toSystemIndependentName(new File(myTargetDirField.getText()).getCanonicalPath());
- for (VirtualFile file : ProjectRootManager.getInstance(myClass.getProject()).getContentRoots()) {
- if (StringUtil.startsWithIgnoreCase(target_dir, file.getPath())) {
- found_root = true;
- break;
- }
- }
- }
- catch (IOException ignore) {
- }
- if (! found_root) {
- setErrorText(PyBundle.message("refactoring.extract.super.target.path.outside.roots"));
- return;
- }
- super.doOKAction();
- }
-
- @Override
- public JComponent getPreferredFocusedComponent() {
- return myExtractedSuperNameField;
- }
-
- protected JPanel createNorthPanel() {
- Box box = createBox();
- box.add(Box.createVerticalStrut(10));
-
- JPanel panel = new JPanel(new BorderLayout());
- panel.add(box, BorderLayout.CENTER);
- return panel;
- }
-
- protected Box createBox() {
- Box box = Box.createVerticalBox();
-
- JPanel _panel = new JPanel(new BorderLayout());
- _panel.add(new JLabel(RefactoringBundle.message("extract.superclass.from")), BorderLayout.NORTH);
- _panel.add(mySourceClassField, BorderLayout.CENTER);
- box.add(_panel);
-
- box.add(Box.createVerticalStrut(10));
-
- mySuperNameLabel = new JLabel();
- mySuperNameLabel.setText(RefactoringBundle.message("superclass.name"));
-
- _panel = new JPanel(new BorderLayout());
- _panel.add(mySuperNameLabel, BorderLayout.NORTH);
- _panel.add(myExtractedSuperNameField, BorderLayout.CENTER);
- box.add(_panel);
- box.add(Box.createVerticalStrut(5));
-
- final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileOrFolderDescriptor();
- final VirtualFile root = getRoot();
- assert root != null;
-
- final Project project = myClass.getProject();
- descriptor.setRoots(ProjectRootManager.getInstance(project).getContentRoots());
- descriptor.setIsTreeRootVisible(true);
- myTargetDirField.setText(FileUtil.toSystemDependentName(root.getPath()));
- myTargetDirField.addBrowseFolderListener(FILE_BROWSER_TITLE,
- null, project, descriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT);
-
- _panel = new JPanel(new BorderLayout());
- myDirLabel = new JLabel();
- myDirLabel.setText(FILE_BROWSER_TITLE);
-
- _panel.add(myDirLabel, BorderLayout.NORTH);
- _panel.add(myTargetDirField, BorderLayout.CENTER);
- box.add(_panel);
- return box;
- }
-
- @Nullable
- protected VirtualFile getRoot() {
- return myClass.getContainingFile().getVirtualFile();
- }
-
- @Override
- protected String getMembersBorderTitle() {
- return RefactoringBundle.message("members.to.form.superclass");
- }
-
- @Override
- protected String getHelpId() {
- return "python.reference.extractSuperclass";
- }
-
- @Override
- protected DependencyMemberInfoModel<PyElement, PyMemberInfo> createMemberInfoModel() {
- return new MyMemberInfoModel(myClass);
- }
-
- @Override
- public boolean checkConflicts() {
- final Collection<PyMemberInfo> infos = getSelectedMemberInfos();
- if (!checkWritable(myClass, infos)) return false;
- if (infos.size() == 0) {
- ConflictsDialog conflictsDialog = new ConflictsDialog(myClass.getProject(), RefactoringBundle.message("no.members.selected"));
- conflictsDialog.show();
- return conflictsDialog.isOK();
- }
- return true;
- }
-
- public String getSuperBaseName() {
- return myExtractedSuperNameField.getText();
- }
-
- public String getTargetFile() {
- return myTargetDirField.getText();
- }
-
- private static class MyMemberInfoModel extends AbstractUsesDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo> {
- public MyMemberInfoModel(PyClass clazz) {
- super(clazz, null, false);
- }
-
- public boolean isAbstractEnabled(PyMemberInfo member) {
- return false;
- }
-
- public int checkForProblems(@NotNull PyMemberInfo member) {
- return member.isChecked() ? OK : super.checkForProblems(member);
- }
-
- @Override
- protected int doCheck(@NotNull PyMemberInfo memberInfo, int problem) {
- return problem;
- }
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java
index a68860d..747d9bf 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHandler.java
@@ -15,23 +15,18 @@
*/
package com.jetbrains.python.refactoring.classes.extractSuperclass;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
-import com.intellij.util.PsiNavigateUtil;
+import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyUtil;
-import com.jetbrains.python.refactoring.classes.PyClassMembersRefactoringSupport;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringHandler;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
-
-import java.util.Collection;
+import com.jetbrains.python.vp.Creator;
+import com.jetbrains.python.vp.ViewPresenterUtils;
+import org.jetbrains.annotations.NotNull;
/**
* @author Dennis.Ushakov
@@ -39,27 +34,39 @@
public class PyExtractSuperclassHandler extends PyClassRefactoringHandler {
public static final String REFACTORING_NAME = RefactoringBundle.message("extract.superclass.title");
+
@Override
- protected void doRefactor(Project project, PsiElement element1, PsiElement element2, Editor editor, PsiFile file, DataContext dataContext) {
- CommonRefactoringUtil.checkReadOnlyStatus(project, file);
-
- final PyClass clazz = PyUtil.getContainingClassOrSelf(element1);
- if (!inClass(clazz, project, editor, "refactoring.pull.up.error.cannot.perform.refactoring.not.inside.class")) return;
-
- final PyMemberInfoStorage infoStorage = PyClassMembersRefactoringSupport.getSelectedMemberInfos(clazz, element1, element2);
-
- if (ApplicationManagerEx.getApplicationEx().isUnitTestMode()) return;
-
- final PyExtractSuperclassDialog dialog = new PyExtractSuperclassDialog(project, clazz, infoStorage);
- dialog.show();
- if(dialog.isOK()) {
- extractWithHelper(clazz, dialog.getSelectedMemberInfos(), dialog.getSuperBaseName(), dialog.getTargetFile());
+ protected void doRefactorImpl(@NotNull final Project project,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage,
+ @NotNull final Editor editor) {
+ //TODO: Move to presenter
+ if (PyUtil.filterOutObject(infoStorage.getClassMemberInfos(classUnderRefactoring)).isEmpty()) {
+ CommonRefactoringUtil.showErrorHint(project, editor, PyBundle
+ .message("refactoring.extract.super.class.no.members.allowed"), RefactoringBundle.message("extract.superclass.elements.header"),
+ null);
+ return;
}
+
+ ViewPresenterUtils.linkViewWithPresenterAndLaunch(PyExtractSuperclassPresenter.class, PyExtractSuperclassView.class,
+ new Creator<PyExtractSuperclassView, PyExtractSuperclassPresenter>() {
+ @NotNull
+ @Override
+ public PyExtractSuperclassPresenter createPresenter(@NotNull final PyExtractSuperclassView view) {
+ return new PyExtractSuperclassPresenterImpl(view, classUnderRefactoring,
+ infoStorage);
+ }
+
+ @NotNull
+ @Override
+ public PyExtractSuperclassView createView(@NotNull final PyExtractSuperclassPresenter presenter) {
+ return new PyExtractSuperclassViewSwingImpl(classUnderRefactoring, project,
+ presenter);
+ }
+ }
+ );
}
- private static void extractWithHelper(PyClass clazz, Collection<PyMemberInfo> selectedMemberInfos, String superBaseName, String targetFile) {
- PsiNavigateUtil.navigate(PyExtractSuperclassHelper.extractSuperclass(clazz, selectedMemberInfos, superBaseName, targetFile));
- }
@Override
protected String getTitle() {
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java
index 0d80337..52657c6 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassHelper.java
@@ -15,95 +15,89 @@
*/
package com.jetbrains.python.refactoring.classes.extractSuperclass;
-import com.intellij.openapi.application.ApplicationManager;
+import com.google.common.base.Predicate;
import com.intellij.openapi.application.ex.ApplicationManagerEx;
-import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
-import com.intellij.refactoring.RefactoringBundle;
import com.intellij.util.PathUtil;
import com.jetbrains.python.PyNames;
import com.jetbrains.python.PythonFileType;
import com.jetbrains.python.psi.*;
-import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.MembersManager;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
/**
* @author Dennis.Ushakov
*/
-public class PyExtractSuperclassHelper {
+public final class PyExtractSuperclassHelper {
private static final Logger LOG = Logger.getInstance(PyExtractSuperclassHelper.class.getName());
+ /**
+ * Accepts only those members whose element is PyClass object (new classes)
+ */
+ private static final Predicate<PyMemberInfo<PyElement>> ALLOW_OBJECT = new PyUtil.ObjectPredicate(true);
- private PyExtractSuperclassHelper() {}
+ private PyExtractSuperclassHelper() {
+ }
- public static PsiElement extractSuperclass(final PyClass clazz,
- final Collection<PyMemberInfo> selectedMemberInfos,
- final String superBaseName,
- final String targetFile) {
- final Set<String> superClasses = new HashSet<String>();
- final Set<PsiNamedElement> extractedClasses = new HashSet<PsiNamedElement>();
- final List<PyFunction> methods = new ArrayList<PyFunction>();
- for (PyMemberInfo member : selectedMemberInfos) {
- final PyElement element = member.getMember();
- if (element instanceof PyFunction) methods.add((PyFunction)element);
- else if (element instanceof PyClass) {
- extractedClasses.add((PyClass)element);
- superClasses.add(element.getName());
+ static void extractSuperclass(final PyClass clazz,
+ @NotNull Collection<PyMemberInfo<PyElement>> selectedMemberInfos,
+ final String superBaseName,
+ final String targetFile) {
+ //We will need to change it probably while param may be read-only
+ //noinspection AssignmentToMethodParameter
+ selectedMemberInfos = new ArrayList<PyMemberInfo<PyElement>>(selectedMemberInfos);
+
+ // PY-12171
+ final PyMemberInfo<PyElement> objectMember = MembersManager.findMember(selectedMemberInfos, ALLOW_OBJECT);
+ if (LanguageLevel.forElement(clazz).isPy3K()) {
+ // Remove object from list if Py3
+ if (objectMember != null) {
+ selectedMemberInfos.remove(objectMember);
}
- else LOG.error("unmatched member class " + element.getClass());
- }
-
- // 'object' superclass is always pulled up, even if not selected explicitly
- for (PyExpression expr : clazz.getSuperClassExpressions()) {
- if (PyNames.OBJECT.equals(expr.getText()) && !superClasses.contains(PyNames.OBJECT)) {
- superClasses.add(PyNames.OBJECT);
+ } else {
+ // Always add object if < Py3
+ if (objectMember == null) {
+ final PyMemberInfo<PyElement> object = MembersManager.findMember(clazz, ALLOW_OBJECT);
+ if (object != null) {
+ selectedMemberInfos.add(object);
+ }
}
}
final Project project = clazz.getProject();
- final Ref<PyClass> newClassRef = new Ref<PyClass>();
- CommandProcessor.getInstance().executeCommand(project, new Runnable() {
- public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
- final PyElement[] elements = methods.toArray(new PyElement[methods.size()]);
- final String text = "class " + superBaseName + ":\n pass" + "\n";
- PyClass newClass = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyClass.class, text);
- newClass = placeNewClass(project, newClass, clazz, targetFile);
- newClassRef.set(newClass);
- PyClassRefactoringUtil.moveMethods(methods, newClass);
- PyClassRefactoringUtil.moveSuperclasses(clazz, superClasses, newClass);
- PyClassRefactoringUtil.addSuperclasses(project, clazz, null, Collections.singleton(superBaseName));
- PyClassRefactoringUtil.insertImport(newClass, extractedClasses);
- if (elements.length > 0) {
- PyPsiUtils.removeElements(elements);
- }
- PyClassRefactoringUtil.insertPassIfNeeded(clazz);
- }
- });
- }
- }, RefactoringBundle.message("extract.superclass.command.name", superBaseName, clazz.getName()), null);
- return newClassRef.get();
+
+ final String text = "class " + superBaseName + ":\n pass" + "\n";
+ PyClass newClass = PyElementGenerator.getInstance(project).createFromText(LanguageLevel.getDefault(), PyClass.class, text);
+
+ newClass = placeNewClass(project, newClass, clazz, targetFile);
+ MembersManager.moveAllMembers(selectedMemberInfos, clazz, newClass);
+ if (! newClass.getContainingFile().equals(clazz.getContainingFile())) {
+ PyClassRefactoringUtil.optimizeImports(clazz.getContainingFile()); // To remove unneeded imports only if user used different file
+ }
+ PyClassRefactoringUtil.addSuperclasses(project, clazz, null, newClass);
+
}
- private static PyClass placeNewClass(Project project, PyClass newClass, @NotNull PyClass clazz, String targetFile) {
- VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(ApplicationManagerEx.getApplicationEx().isUnitTestMode() ? targetFile : VfsUtil.pathToUrl(targetFile));
+ private static PyClass placeNewClass(final Project project, PyClass newClass, @NotNull final PyClass clazz, final String targetFile) {
+ VirtualFile file = VirtualFileManager.getInstance()
+ .findFileByUrl(ApplicationManagerEx.getApplicationEx().isUnitTestMode() ? targetFile : VfsUtilCore.pathToUrl(targetFile));
// file is the same as the source
if (Comparing.equal(file, clazz.getContainingFile().getVirtualFile())) {
return (PyClass)clazz.getParent().addBefore(newClass, clazz);
@@ -131,7 +125,8 @@
else { // existing file
psiFile = PsiManager.getInstance(project).findFile(file);
}
- } catch (IOException e) {
+ }
+ catch (IOException e) {
LOG.error(e);
}
@@ -147,6 +142,7 @@
/**
* Places a file at the end of given path, creating intermediate dirs and inits.
+ *
* @param project
* @param path
* @param filename
@@ -157,6 +153,7 @@
return placeFile(project, path, filename, null);
}
+ //TODO: Mover to the other class? That is not good to dependent PyUtils on this class
public static PsiFile placeFile(Project project, String path, String filename, @Nullable String content) throws IOException {
PsiDirectory psiDir = createDirectories(project, path);
LOG.assertTrue(psiDir != null);
@@ -177,8 +174,9 @@
/**
* Create all intermediate dirs with inits from one of roots up to target dir.
+ *
* @param project
- * @param target a full path to target dir
+ * @param target a full path to target dir
* @return deepest child directory, or null if target is not in roots or process fails at some point.
*/
@Nullable
@@ -198,7 +196,7 @@
}
}
if (the_root == null) {
- throw new IOException("Can't find '"+ target +"' among roots");
+ throw new IOException("Can't find '" + target + "' among roots");
}
if (the_rest != null) {
final LocalFileSystem lfs = LocalFileSystem.getInstance();
@@ -213,7 +211,9 @@
throw new IOException("Expected dir, but got non-dir: " + subdir.getPath());
}
}
- else subdir = the_root.createChildDirectory(lfs, dirs[i]);
+ else {
+ subdir = the_root.createChildDirectory(lfs, dirs[i]);
+ }
VirtualFile init_vfile = subdir.findChild(PyNames.INIT_DOT_PY);
if (init_vfile == null) init_vfile = subdir.createChildData(lfs, PyNames.INIT_DOT_PY);
/*
@@ -235,5 +235,4 @@
}
return ret;
}
-
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassInfoModel.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassInfoModel.java
new file mode 100644
index 0000000..2bae38a
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassInfoModel.java
@@ -0,0 +1,31 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.intellij.refactoring.classMembers.AbstractUsesDependencyMemberInfoModel;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+class PyExtractSuperclassInfoModel extends AbstractUsesDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo<PyElement>> {
+ PyExtractSuperclassInfoModel(@NotNull final PyClass clazz) {
+ super(clazz, null, false);
+ }
+
+ @Override
+ public boolean isAbstractEnabled(final PyMemberInfo<PyElement> member) {
+ return member.isCouldBeAbstract() && isMemberEnabled(member);
+ }
+
+ @Override
+ public int checkForProblems(@NotNull final PyMemberInfo<PyElement> member) {
+ return member.isChecked() ? OK : super.checkForProblems(member);
+ }
+
+ @Override
+ protected int doCheck(@NotNull final PyMemberInfo<PyElement> memberInfo, final int problem) {
+ return problem;
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassInitializationInfo.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassInitializationInfo.java
new file mode 100644
index 0000000..9ba93c2
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassInitializationInfo.java
@@ -0,0 +1,46 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.refactoring.classMembers.MemberInfoModel;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+/**
+ * View configuration for "extract superclass"
+ *
+ * @author Ilya.Kazakevich
+ */
+class PyExtractSuperclassInitializationInfo extends MembersViewInitializationInfo {
+
+ @NotNull
+ private final String myDefaultFilePath;
+ @NotNull
+ private final VirtualFile[] myRoots;
+
+ /**
+ * @param defaultFilePath module file path to display. User will be able to change it later.
+ * @param roots virtual files where user may add new module
+ */
+ PyExtractSuperclassInitializationInfo(@NotNull final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> memberInfoModel,
+ @NotNull final Collection<PyMemberInfo<PyElement>> memberInfos,
+ @NotNull final String defaultFilePath,
+ @NotNull final VirtualFile... roots) {
+ super(memberInfoModel, memberInfos);
+ myDefaultFilePath = defaultFilePath;
+ myRoots = roots.clone();
+ }
+
+ @NotNull
+ public String getDefaultFilePath() {
+ return myDefaultFilePath;
+ }
+
+ @NotNull
+ public VirtualFile[] getRoots() {
+ return myRoots.clone();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenter.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenter.java
new file mode 100644
index 0000000..4e5edf7
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenter.java
@@ -0,0 +1,10 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenter;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public interface PyExtractSuperclassPresenter extends MembersBasedPresenter {
+ //TODO: Remove?
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenterImpl.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenterImpl.java
new file mode 100644
index 0000000..4d2190a
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenterImpl.java
@@ -0,0 +1,99 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.intellij.lang.LanguageNamesValidation;
+import com.intellij.lang.refactoring.NamesValidator;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.PythonLanguage;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.BadDataException;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenterNoPreviewImpl;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+class PyExtractSuperclassPresenterImpl extends MembersBasedPresenterNoPreviewImpl<PyExtractSuperclassView>
+ implements PyExtractSuperclassPresenter {
+ private final NamesValidator myNamesValidator = LanguageNamesValidation.INSTANCE.forLanguage(PythonLanguage.getInstance());
+
+
+ @NotNull
+ private static final MultiMap<PsiElement, String> EMPTY_MAP = MultiMap.create();
+
+ PyExtractSuperclassPresenterImpl(@NotNull final PyExtractSuperclassView view,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage) {
+ super(view, classUnderRefactoring, infoStorage);
+ }
+
+ @NotNull
+ @Override
+ protected MultiMap<PsiElement, String> getConflicts() {
+ return EMPTY_MAP; //There are no conflicts for extracting
+ }
+
+ @Override
+ protected void validateView() throws BadDataException {
+ super.validateView();
+ final Project project = myClassUnderRefactoring.getProject();
+ if (!myNamesValidator.isIdentifier(myView.getSuperClassName(), project)) {
+ throw new BadDataException(PyBundle.message("refactoring.extract.super.name.0.must.be.ident", myView.getSuperClassName()));
+ }
+ boolean rootFound = false;
+ try {
+ final String targetDir = FileUtil.toSystemIndependentName(new File(myView.getModuleFile()).getCanonicalPath());
+ for (final VirtualFile file : ProjectRootManager.getInstance(project).getContentRoots()) {
+ if (StringUtil.startsWithIgnoreCase(targetDir, file.getPath())) {
+ rootFound = true;
+ break;
+ }
+ }
+ }
+ catch (final IOException ignore) {
+ }
+ if (!rootFound) {
+ throw new BadDataException(PyBundle.message("refactoring.extract.super.target.path.outside.roots"));
+ }
+ }
+
+ @Override
+ public void launch() {
+ final String defaultFilePath = FileUtil.toSystemDependentName(myClassUnderRefactoring.getContainingFile().getVirtualFile().getPath());
+ final VirtualFile[] roots = ProjectRootManager.getInstance(myClassUnderRefactoring.getProject()).getContentRoots();
+ final Collection<PyMemberInfo<PyElement>> pyMemberInfos =
+ PyUtil.filterOutObject(myStorage.getClassMemberInfos(myClassUnderRefactoring));
+ myView.configure(
+ new PyExtractSuperclassInitializationInfo(new PyExtractSuperclassInfoModel(myClassUnderRefactoring), pyMemberInfos, defaultFilePath,
+ roots));
+ myView.initAndShow();
+
+ }
+
+ @NotNull
+ @Override
+ protected String getCommandName() {
+ return RefactoringBundle.message("extract.superclass.command.name", myView.getSuperClassName(), myClassUnderRefactoring.getName());
+ }
+
+ @Override
+ protected void refactorNoPreview() {
+ PyExtractSuperclassHelper
+ .extractSuperclass(myClassUnderRefactoring, myView.getSelectedMemberInfos(), myView.getSuperClassName(), myView.getModuleFile());
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassView.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassView.java
new file mode 100644
index 0000000..d4dd249
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassView.java
@@ -0,0 +1,25 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public interface PyExtractSuperclassView extends MembersBasedView<PyExtractSuperclassInitializationInfo> {
+
+ /**
+ *
+ * @return path to destination file (module) where user wants to create new class
+ */
+ @NotNull
+ String getModuleFile();
+
+ /**
+ *
+ * @return name user wants to give to new class
+ */
+ @NotNull
+ String getSuperClassName();
+
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassViewSwingImpl.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassViewSwingImpl.java
new file mode 100644
index 0000000..aed7301
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassViewSwingImpl.java
@@ -0,0 +1,108 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.ui.TextComponentAccessor;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.refactoring.RefactoringBundle;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedViewSwingImpl;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+class PyExtractSuperclassViewSwingImpl
+ extends MembersBasedViewSwingImpl<PyExtractSuperclassPresenter, PyExtractSuperclassInitializationInfo>
+ implements PyExtractSuperclassView {
+
+ private static final String FILE_OR_DIRECTORY = RefactoringBundle.message("extract.superclass.elements.header");
+ @NotNull
+ private final JTextArea myExtractedSuperNameField = new JTextArea();
+ @NotNull
+ private final FileChooserDescriptor myFileChooserDescriptor;
+ @NotNull
+ private final TextFieldWithBrowseButton myTargetDirField;
+
+ PyExtractSuperclassViewSwingImpl(@NotNull final PyClass classUnderRefactoring,
+ @NotNull final Project project,
+ @NotNull final PyExtractSuperclassPresenter presenter) {
+ super(project, presenter, RefactoringBundle.message("extract.superclass.from"), true);
+ setTitle(PyExtractSuperclassHandler.REFACTORING_NAME);
+
+
+ final Box box = Box.createVerticalBox();
+
+ JPanel panel = new JPanel(new BorderLayout());
+ panel.add(new JLabel(RefactoringBundle.message("extract.superclass.from")), BorderLayout.NORTH);
+ final JTextField sourceClassField = new JTextField();
+ sourceClassField.setEditable(false);
+ sourceClassField.setText(classUnderRefactoring.getName());
+ panel.add(sourceClassField, BorderLayout.CENTER);
+ box.add(panel);
+
+ box.add(Box.createVerticalStrut(10));
+
+ final JLabel superNameLabel = new JLabel();
+ superNameLabel.setText(RefactoringBundle.message("superclass.name"));
+
+ panel = new JPanel(new BorderLayout());
+ panel.add(superNameLabel, BorderLayout.NORTH);
+ panel.add(myExtractedSuperNameField, BorderLayout.CENTER);
+ box.add(panel);
+ box.add(Box.createVerticalStrut(5));
+
+ myFileChooserDescriptor = FileChooserDescriptorFactory.createSingleFileOrFolderDescriptor();
+
+
+ myFileChooserDescriptor.setRoots(ProjectRootManager.getInstance(project).getContentRoots());
+ myFileChooserDescriptor.setIsTreeRootVisible(true);
+ myTargetDirField = new TextFieldWithBrowseButton();
+ myTargetDirField
+ .addBrowseFolderListener(FILE_OR_DIRECTORY, null, project, myFileChooserDescriptor, TextComponentAccessor.TEXT_FIELD_WHOLE_TEXT);
+
+ panel = new JPanel(new BorderLayout());
+ final JLabel dirLabel = new JLabel();
+ dirLabel.setText(FILE_OR_DIRECTORY); //u18n
+
+ panel.add(dirLabel, BorderLayout.NORTH);
+ panel.add(myTargetDirField, BorderLayout.CENTER);
+ box.add(panel);
+
+ box.add(Box.createVerticalStrut(10));
+
+
+ myTopPanel.add(box, BorderLayout.CENTER);
+ myCenterPanel.add(myPyMemberSelectionPanel, BorderLayout.CENTER);
+ setPreviewResults(false);
+ }
+
+ @Override
+ public JComponent getPreferredFocusedComponent() {
+ return myExtractedSuperNameField;
+ }
+
+ @Override
+ public void configure(@NotNull final PyExtractSuperclassInitializationInfo configInfo) {
+ super.configure(configInfo);
+ myFileChooserDescriptor.setRoots(configInfo.getRoots());
+ myTargetDirField.setText(configInfo.getDefaultFilePath());
+ }
+
+ @NotNull
+ @Override
+ public String getModuleFile() {
+ return myTargetDirField.getText();
+ }
+
+ @NotNull
+ @Override
+ public String getSuperClassName() {
+ return myExtractedSuperNameField.getText();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/package-info.java b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/package-info.java
new file mode 100644
index 0000000..32852cb
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/extractSuperclass/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * "Extract superclass" refactoring
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java
new file mode 100644
index 0000000..b6faa3a
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/ClassFieldsManager.java
@@ -0,0 +1,50 @@
+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.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Moves class attributes up
+ *
+ * @author Ilya.Kazakevich
+ */
+class ClassFieldsManager extends FieldsManager {
+
+ ClassFieldsManager() {
+ super(true);
+ }
+
+
+ @Override
+ protected Collection<PyElement> moveAssignments(@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>();
+ for (final PyClass destClass : to) {
+ result.addAll(PyClassRefactoringUtil.copyFieldDeclarationToStatement(statements, destClass.getStatementList()));
+ }
+ deleteElements(statements);
+ PyClassRefactoringUtil.insertPassIfNeeded(from);
+ return result;
+ }
+
+ @Override
+ protected boolean classHasField(@NotNull final PyClass pyClass, @NotNull final String fieldName) {
+ return pyClass.findClassAttribute(fieldName, true) != null;
+ }
+
+ @NotNull
+ @Override
+ protected List<PyTargetExpression> getFieldsByClass(@NotNull final PyClass pyClass) {
+ return pyClass.getClassAttributes();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java
new file mode 100644
index 0000000..d27ec8e
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/FieldsManager.java
@@ -0,0 +1,119 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.jetbrains.NotNullPredicate;
+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 org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Parent of all field-based plugins (like class fields, instance fields and so on)
+ *
+ * @author Ilya.Kazakevich
+ */
+abstract class FieldsManager extends MembersManager<PyTargetExpression> {
+ private static final SimpleAssignmentsOnly SIMPLE_ASSIGNMENTS_ONLY = new SimpleAssignmentsOnly();
+ private static final AssignmentTransform ASSIGNMENT_TRANSFORM = new AssignmentTransform();
+ private final boolean myStatic;
+
+ /**
+ * @param isStatic is field static or not?
+ */
+ protected FieldsManager(final boolean isStatic) {
+ super(PyTargetExpression.class);
+ myStatic = isStatic;
+ }
+
+ @Override
+ protected Collection<? extends PyElement> getElementsToStoreReferences(@NotNull final Collection<PyTargetExpression> elements) {
+ // We need to save references from assignments
+ return Collections2.transform(elements, ASSIGNMENT_TRANSFORM);
+ }
+
+ @NotNull
+ @Override
+ protected List<PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
+ return Lists.<PyElement>newArrayList(Collections2.filter(getFieldsByClass(pyClass), SIMPLE_ASSIGNMENTS_ONLY));
+ }
+
+ @Override
+ protected Collection<PyElement> moveMembers(@NotNull final PyClass from,
+ @NotNull final Collection<PyMemberInfo<PyTargetExpression>> members,
+ @NotNull final PyClass... to) {
+ return moveAssignments(from, Collections2.filter(Collections2.transform(fetchElements(members), ASSIGNMENT_TRANSFORM), NotNullPredicate.INSTANCE),
+ to);
+ }
+
+ protected abstract Collection<PyElement> moveAssignments(@NotNull PyClass from,
+ @NotNull Collection<PyAssignmentStatement> statements,
+ @NotNull PyClass... to);
+
+ /**
+ * Checks if class has fields. Only child may know how to obtain field
+ *
+ * @param pyClass class to check
+ * @param fieldName field name
+ * @return true if has one
+ */
+ protected abstract boolean classHasField(@NotNull PyClass pyClass, @NotNull String fieldName);
+
+ /**
+ * Returns all fields by class. Only child may know how to obtain fields
+ *
+ * @param pyClass class to check
+ * @return list of fields in target expression (declaration) form
+ */
+ @NotNull
+ protected abstract List<PyTargetExpression> getFieldsByClass(@NotNull PyClass pyClass);
+
+
+ @NotNull
+ @Override
+ public PyMemberInfo<PyTargetExpression> apply(@NotNull final PyTargetExpression input) {
+ return new PyMemberInfo<PyTargetExpression>(input, myStatic, input.getText(), isOverrides(input), this, false);
+ }
+
+ @Nullable
+ private Boolean isOverrides(@NotNull final PyTargetExpression input) {
+ final PyClass aClass = input.getContainingClass();
+ final String name = input.getName();
+ if (name == null) {
+ return null; //Field with out of name can't override something
+ }
+
+ assert aClass != null : "Target expression declared outside of class:" + input;
+
+ return classHasField(aClass, name) ? true : null;
+ }
+
+
+ private static class SimpleAssignmentsOnly extends NotNullPredicate<PyTargetExpression> {
+ //Support only simplest cases like CLASS_VAR = 42.
+ //Tuples (CLASS_VAR_1, CLASS_VAR_2) = "spam", "eggs" are not supported by now
+ @Override
+ public boolean applyNotNull(@NotNull final PyTargetExpression input) {
+ final PsiElement parent = input.getParent();
+ return (parent != null) && PyAssignmentStatement.class.isAssignableFrom(parent.getClass());
+ }
+ }
+
+
+ //Transforms expressions to its assignment step
+ private static class AssignmentTransform implements Function<PyTargetExpression, PyAssignmentStatement> {
+ @Nullable
+ @Override
+ public PyAssignmentStatement apply(@NotNull final PyTargetExpression input) {
+ return PsiTreeUtil.getParentOfType(input, PyAssignmentStatement.class);
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java
new file mode 100644
index 0000000..ba6cb0c
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/InstanceFieldsManager.java
@@ -0,0 +1,113 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.google.common.collect.Collections2;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.impl.PyFunctionBuilder;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+class InstanceFieldsManager extends FieldsManager {
+
+ // PY-12170
+
+ InstanceFieldsManager() {
+ super(false);
+ }
+
+
+ @Override
+ protected Collection<PyElement> moveAssignments(@NotNull final PyClass from,
+ @NotNull final Collection<PyAssignmentStatement> statements,
+ @NotNull final PyClass... to) {
+ //TODO: Copy/paste with ClassFieldsManager. Move to parent?
+
+ final List<PyElement> result = new ArrayList<PyElement>();
+ for (final PyClass destClass : to) {
+ result.addAll(copyInstanceFields(statements, destClass));
+ }
+ // Delete only declarations made in __init__ to prevent PY-12170
+ final PyFunction fromInitMethod = PyUtil.getInitMethod(from);
+ if (fromInitMethod != null) { // If class has no init method that means all its fields declared in other methods, so nothing to remove
+ deleteElements(Collections2.filter(statements, new InitsOnly(fromInitMethod)));
+ //We can't leave class constructor with empty body
+ PyClassRefactoringUtil.insertPassIfNeeded(fromInitMethod);
+ }
+ return result;
+ }
+
+ /**
+ * Copies class' fields in form of assignments (instance fields) to another class.
+ * Creates init method if there is no any
+ *
+ * @param members assignments to copy
+ * @param to destination
+ * @return newly created fields
+ */
+ @NotNull
+ private static List<PyAssignmentStatement> copyInstanceFields(@NotNull final Collection<PyAssignmentStatement> members,
+ @NotNull final PyClass to) {
+ //We need __init__ method, and if there is no any -- we need to create it
+ PyFunction toInitMethod = PyUtil.getInitMethod(to);
+ if (toInitMethod == null) {
+ toInitMethod = createInitMethod(to);
+ }
+ final PyStatementList statementList = toInitMethod.getStatementList();
+ return PyClassRefactoringUtil.copyFieldDeclarationToStatement(members, statementList);
+ }
+
+ /**
+ * Creates init method and adds it to certain class.
+ *
+ * @param to Class where method should be added
+ * @return newly created method
+ */
+ //TODO: Move to utils?
+ @NotNull
+ private static PyFunction createInitMethod(@NotNull final PyClass to) {
+ final PyFunctionBuilder functionBuilder = new PyFunctionBuilder(PyNames.INIT);
+ functionBuilder.parameter(PyNames.CANONICAL_SELF); //TODO: Take param from codestyle?
+ final PyFunction function = functionBuilder.buildFunction(to.getProject(), LanguageLevel.forElement(to));
+ return PyClassRefactoringUtil.addMethods(to, function).get(0);
+ }
+
+ @Override
+ protected boolean classHasField(@NotNull final PyClass pyClass, @NotNull final String fieldName) {
+ return pyClass.findInstanceAttribute(fieldName, true) != null;
+ }
+
+ @NotNull
+ @Override
+ protected List<PyTargetExpression> getFieldsByClass(@NotNull final PyClass pyClass) {
+ return pyClass.getInstanceAttributes();
+ }
+
+ private static class InitsOnly extends NotNullPredicate<PyAssignmentStatement> {
+ @NotNull
+ private final PyFunction myInitMethod;
+
+ private InitsOnly(@NotNull final PyFunction initMethod) {
+ myInitMethod = initMethod;
+ }
+
+ @Override
+ protected boolean applyNotNull(@NotNull final PyAssignmentStatement input) {
+ final PyExpression expression = input.getLeftHandSideExpression();
+ if (expression == null) {
+ return false;
+ }
+
+ final PyFunction functionWhereDeclared = PsiTreeUtil.getParentOfType(PyUtil.resolveToTheTop(expression), PyFunction.class);
+ return myInitMethod.equals(functionWhereDeclared);
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java
new file mode 100644
index 0000000..6be3f9d
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MembersManager.java
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.classes.membersManager;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Multimap;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiNamedElement;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
+
+import java.util.*;
+
+/**
+ * Moves members between classes via its plugins (managers).
+ * To move members use {@link #getAllMembersCouldBeMoved(com.jetbrains.python.psi.PyClass)} and {@link #moveAllMembers(java.util.Collection, com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyClass...)}
+ * To add new manager, extend this class and add it to {@link #MANAGERS}
+ *
+ * @author Ilya.Kazakevich
+ */
+public abstract class MembersManager<T extends PyElement> implements Function<T, PyMemberInfo<T>> {
+ /**
+ * 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());
+
+ @NotNull
+ private final Class<T> myExpectedClass;
+
+ protected MembersManager(@NotNull final Class<T> expectedClass) {
+ myExpectedClass = expectedClass;
+ }
+
+ /**
+ * Get all members that could be moved out of certain class
+ *
+ * @param pyClass class to find members
+ * @return list of members could be moved
+ */
+ @NotNull
+ public static List<PyMemberInfo<PyElement>> getAllMembersCouldBeMoved(@NotNull final PyClass pyClass) {
+ final List<PyMemberInfo<PyElement>> result = new ArrayList<PyMemberInfo<PyElement>>();
+
+ for (final MembersManager<? extends PyElement> manager : MANAGERS) {
+ result.addAll(transformSafely(pyClass, manager));
+ }
+ return result;
+ }
+
+
+ /**
+ * Transforms elements, manager says it could move to appropriate {@link com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo}.
+ * Types are checked at runtime.
+ * @param pyClass class whose members we want to move
+ * @param manager manager that should check class and report list of memebers
+ * @return member infos
+ */
+ //TODO: Move to TypeSafeMovingStrategy
+ @NotNull
+ @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);
+ manager.checkElementTypes((Collection)membersCouldBeMoved);
+ return (Collection<PyMemberInfo<PyElement>>)Collections2.transform(membersCouldBeMoved, (Function)manager);
+ }
+
+
+ /**
+ * Moves members from one class to another
+ *
+ * @param memberInfos members to move
+ * @param from source
+ * @param to destination
+ */
+ public static void moveAllMembers(
+ @NotNull final Collection<PyMemberInfo<PyElement>> memberInfos,
+ @NotNull final PyClass from,
+ @NotNull final PyClass... to
+ ) {
+ final Multimap<MembersManager<PyElement>, PyMemberInfo<PyElement>> managerToMember = ArrayListMultimap.create();
+ //Collect map (manager)->(list_of_memebers)
+ for (final PyMemberInfo<PyElement> memberInfo : memberInfos) {
+ managerToMember.put(memberInfo.getMembersManager(), memberInfo);
+ }
+ //Move members via manager
+ for (final MembersManager<PyElement> membersManager : managerToMember.keySet()) {
+ final Collection<PyMemberInfo<PyElement>> members = managerToMember.get(membersManager);
+ TypeSafeMovingStrategy.moveCheckingTypesAtRunTime(from, membersManager, members, to);
+ }
+ PyClassRefactoringUtil.insertPassIfNeeded(from);
+ }
+
+
+
+ /**
+ * Checks that all elements has allowed type for manager
+ *
+ * @param members elements to check against manager
+ */
+ void checkElementTypes(@NotNull final Collection<T> elements) {
+ for (final PyElement pyElement : elements) {
+ Preconditions.checkArgument(myExpectedClass.isAssignableFrom(pyElement.getClass()),
+ String.format("Manager %s expected %s but got %s", this, myExpectedClass, pyElement));
+ }
+ }
+
+ /**
+ * Finds member by predicate
+ *
+ * @param members where to find
+ * @param predicate what to find
+ * @return member or null if not found
+ */
+ @Nullable
+ public static PyMemberInfo<PyElement> findMember(@NotNull final Collection<PyMemberInfo<PyElement>> members,
+ @NotNull final Predicate<PyMemberInfo<PyElement>> predicate) {
+ for (final PyMemberInfo<PyElement> pyMemberInfo : members) {
+ if (predicate.apply(pyMemberInfo)) {
+ return pyMemberInfo;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds member of class by predicate
+ *
+ * @param predicate what to find
+ * @param pyClass class to find members
+ * @return member or null if not found
+ */
+ @Nullable
+ public static PyMemberInfo<PyElement> findMember(@NotNull final PyClass pyClass,
+ @NotNull final Predicate<PyMemberInfo<PyElement>> predicate) {
+ return findMember(getAllMembersCouldBeMoved(pyClass), predicate);
+ }
+
+ /**
+ * Finds member in class. It is here only for backward compatibility with some tests.
+ */
+ //TODO: mark deprecated?
+ @TestOnly
+ @NotNull
+ public static PyMemberInfo<PyElement> findMember(@NotNull final PyClass pyClass, @NotNull final PyElement pyElement) {
+ final PyMemberInfo<PyElement> result = findMember(pyClass, new FindByElement(pyElement));
+ if (result != null) {
+ return result;
+ }
+ throw new IllegalArgumentException(String.format("Element %s not found in class %s or can't be moved", pyElement, pyClass));
+ }
+
+ /**
+ * Get list of elements certain plugin could move out of the class
+ *
+ * @param pyClass class with members
+ * @return list of members
+ */
+ @NotNull
+ protected abstract List<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
+ * @return elements to store
+ * @see #moveAllMembers(java.util.Collection, com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyClass...)
+ */
+ protected Collection<? extends PyElement> getElementsToStoreReferences(@NotNull final Collection<T> elements) {
+ return elements;
+ }
+
+ /**
+ * 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)})
+ *
+ * @see #getElementsToStoreReferences(java.util.Collection)
+ */
+ protected abstract Collection<PyElement> moveMembers(
+ @NotNull PyClass from,
+ @NotNull Collection<PyMemberInfo<T>> members,
+ @NotNull PyClass... to);
+
+
+ /**
+ * Creates {@link com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo} from {@link com.jetbrains.python.psi.PyElement}
+ * This process is plugin-specific and should be implemented in each plugin
+ *
+ * @param input element
+ * @return member info
+ */
+ @SuppressWarnings("NullableProblems") //IDEA-120100
+ @NotNull
+ @Override
+ public abstract PyMemberInfo<T> apply(@NotNull T input);
+
+ /**
+ * Deletes all elements
+ *
+ * @param pyElementsToDelete elements to delete
+ */
+ protected static void deleteElements(@NotNull final Collection<? extends PsiElement> pyElementsToDelete) {
+ for (final PsiElement element : pyElementsToDelete) {
+ element.delete();
+ }
+ }
+
+ /**
+ * Fetches elements from member info.
+ * @param memberInfos member info to fetch elements from
+ * @param <T> type of element
+ * @return list of elements
+ */
+ @NotNull
+ protected static <T extends PyElement> Collection<T> fetchElements(@NotNull final Collection<PyMemberInfo<T>> memberInfos) {
+ return Collections2.transform(memberInfos, new PyMemberExtractor<T>());
+ }
+
+ private static class PyMemberExtractor<T extends PyElement> implements Function<PyMemberInfo<T>, T> {
+ @SuppressWarnings("NullableProblems") //IDEA-120100
+ @Override
+ public T apply(@NotNull final PyMemberInfo<T> input) {
+ return input.getMember();
+ }
+ }
+
+ 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;
+
+ private FindByElement(final PyElement pyElement) {
+ myPyElement = pyElement;
+ }
+
+ @Override
+ public boolean applyNotNull(@NotNull final PyMemberInfo<PyElement> input) {
+ return input.getMember().equals(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
new file mode 100644
index 0000000..264261e
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/MethodsManager.java
@@ -0,0 +1,230 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.intellij.openapi.util.Pair;
+import com.intellij.psi.PsiFile;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.codeInsight.imports.AddImportHelper;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.psi.impl.PyFunctionBuilder;
+import com.jetbrains.python.psi.types.PyClassLikeType;
+import com.jetbrains.python.psi.types.TypeEvalContext;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * Plugin that moves class methods
+ *
+ * @author Ilya.Kazakevich
+ */
+class MethodsManager extends MembersManager<PyFunction> {
+ private static final String ABC_META_CLASS = "ABCMeta";
+
+ /**
+ * Some decorators should be copied with methods if method is marked abstract. Here is list.
+ */
+ private static final String[] DECORATORS_MAY_BE_COPIED_TO_ABSTRACT =
+ {PyNames.PROPERTY, PyNames.CLASSMETHOD, PyNames.STATICMETHOD};
+
+ public static final String ABC_META_PACKAGE = "abc";
+
+ MethodsManager() {
+ super(PyFunction.class);
+ }
+
+ @NotNull
+ @Override
+ protected List<PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
+ return Lists.<PyElement>newArrayList(filterNameless(Arrays.asList(pyClass.getMethods())));
+ }
+
+ @Override
+ protected Collection<PyElement> moveMembers(@NotNull final PyClass from,
+ @NotNull final Collection<PyMemberInfo<PyFunction>> members,
+ @NotNull final PyClass... to) {
+ final Collection<PyFunction> methodsToMove = fetchElements(Collections2.filter(members, new AbstractFilter(false)));
+ final Collection<PyFunction> methodsToAbstract = fetchElements(Collections2.filter(members, new AbstractFilter(true)));
+
+ makeMethodsAbstract(methodsToAbstract, to);
+ return moveMethods(from, methodsToMove, to);
+ }
+
+ /**
+ * Creates abstract version of each method in each class (does not touch method itself as opposite to {@link #moveMethods(com.jetbrains.python.psi.PyClass, java.util.Collection, com.jetbrains.python.psi.PyClass...)})
+ *
+ * @param currentFunctions functions to make them abstract
+ * @param to classes where abstract method should be created
+ */
+ private static void makeMethodsAbstract(final Collection<PyFunction> currentFunctions, final PyClass... to) {
+ final Set<PsiFile> filesToCheckImport = new HashSet<PsiFile>();
+ final Set<PyClass> classesToAddMetaAbc = new HashSet<PyClass>();
+
+ for (final PyFunction function : currentFunctions) {
+ for (final PyClass destClass : to) {
+ final PyFunctionBuilder functionBuilder = PyFunctionBuilder.copySignature(function, DECORATORS_MAY_BE_COPIED_TO_ABSTRACT);
+ functionBuilder.decorate(PyNames.ABSTRACTMETHOD);
+ final LanguageLevel level = LanguageLevel.forElement(destClass);
+ PyClassRefactoringUtil.addMethods(destClass, functionBuilder.buildFunction(destClass.getProject(), level));
+ classesToAddMetaAbc.add(destClass);
+ }
+ }
+
+ // Add ABCMeta to new classes if needed
+ for (final PyClass aClass : classesToAddMetaAbc) {
+ if (addMetaAbcIfNeeded(aClass)) {
+ filesToCheckImport.add(aClass.getContainingFile());
+ }
+ }
+
+ // Add imports for ABC if needed
+ for (final PsiFile file : filesToCheckImport) {
+ addImportFromAbc(file, PyNames.ABSTRACTMETHOD);
+ addImportFromAbc(file, ABC_META_CLASS);
+ PyClassRefactoringUtil.optimizeImports(file); //To remove redundant imports
+ }
+ }
+
+ /**
+ * Adds metaclass = ABCMeta for class if has no.
+ *
+ * @param aClass class where it should be added
+ * @return true if added. False if class already has metaclass so we did not touch it.
+ */
+ // TODO: Copy/Paste with PyClass.getMeta..
+ private static boolean addMetaAbcIfNeeded(@NotNull final PyClass aClass) {
+ final PsiFile file = aClass.getContainingFile();
+ final PyClassLikeType type = aClass.getMetaClassType(TypeEvalContext.userInitiated(file));
+ if (type != null) {
+ return false; //User already has metaclass. He probably knows about metaclasses, so we should not add ABCMeta
+ }
+ final LanguageLevel languageLevel = LanguageLevel.forElement(aClass);
+ if (languageLevel.isPy3K()) { //TODO: Copy/paste, use strategy because we already has the same check in #couldBeAbstract
+ // Add (metaclass= for Py3K
+ PyClassRefactoringUtil
+ .addSuperClassExpressions(aClass.getProject(), aClass, null, Collections.singletonList(Pair.create(PyNames.METACLASS,
+ ABC_META_CLASS)));
+ }
+ else {
+ // Add __metaclass__ for Py2
+ PyClassRefactoringUtil.addClassAttributeIfNotExist(aClass, PyNames.DUNDER_METACLASS, ABC_META_CLASS);
+ }
+ return true;
+ }
+
+ /**
+ * Adds import from ABC module
+ *
+ * @param file where to add import
+ * @param nameToImport what to import
+ */
+ private static void addImportFromAbc(@NotNull final PsiFile file, @NotNull final String nameToImport) {
+ AddImportHelper.addImportFromStatement(file, ABC_META_PACKAGE, nameToImport, null,
+ AddImportHelper.ImportPriority.BUILTIN);
+ }
+
+ /**
+ * Moves methods (as opposite to {@link #makeMethodsAbstract(java.util.Collection, com.jetbrains.python.psi.PyClass...)})
+ *
+ * @param from source
+ * @param methodsToMove what to move
+ * @param to where
+ * @return newly added methods
+ */
+ private static List<PyElement> moveMethods(final PyClass from, final Collection<PyFunction> methodsToMove, 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
+ final List<PyFunction> copies = new ArrayList<PyFunction>(methodsToMove.size());
+ for (final PyFunction element : methodsToMove) {
+ final PyFunction newMethod = (PyFunction)element.copy();
+ copies.add(newMethod);
+ }
+
+ result.addAll(PyClassRefactoringUtil.copyMethods(copies, destClass));
+ }
+ deleteElements(methodsToMove);
+
+ PyClassRefactoringUtil.insertPassIfNeeded(from);
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public PyMemberInfo<PyFunction> apply(@NotNull final PyFunction pyFunction) {
+ final PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(pyFunction);
+ assert flags != null : "No flags return while element is function " + pyFunction;
+ final boolean isStatic = flags.isStaticMethod() || flags.isClassMethod();
+ return new PyMemberInfo<PyFunction>(pyFunction, isStatic, buildDisplayMethodName(pyFunction), isOverrides(pyFunction), this,
+ couldBeAbstract(pyFunction));
+ }
+
+ /**
+ * @return if method could be made abstract? (that means "create abstract version if method in parent class")
+ */
+ private static boolean couldBeAbstract(@NotNull final PyFunction function) {
+ if (PyUtil.isInit(function)) {
+ return false; // Who wants to make __init__ abstract?!
+ }
+ final PyUtil.MethodFlags flags = PyUtil.MethodFlags.of(function);
+ assert flags != null : "Function should be called on method!";
+
+ final boolean py3K = LanguageLevel.forElement(function).isPy3K();
+
+ //TODO: use strategy because we already has the same check in #addMetaAbcIfNeeded
+ return flags.isInstanceMethod() || py3K; //Any method could be made abstract in py3
+ }
+
+
+ @Nullable
+ private static Boolean isOverrides(final PyFunction pyFunction) {
+ final PyClass clazz = PyUtil.getContainingClassOrSelf(pyFunction);
+ assert clazz != null : "Refactoring called on function, not method: " + pyFunction;
+ for (final PyClass parentClass : clazz.getSuperClasses()) {
+ final PyFunction parentMethod = parentClass.findMethodByName(pyFunction.getName(), true);
+ if (parentMethod != null) {
+ return true;
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ private static String buildDisplayMethodName(@NotNull final PyFunction pyFunction) {
+ final StringBuilder builder = new StringBuilder(pyFunction.getName());
+ builder.append('(');
+ final PyParameter[] arguments = pyFunction.getParameterList().getParameters();
+ for (final PyParameter parameter : arguments) {
+ builder.append(parameter.getName());
+ if (arguments.length > 1 && parameter != arguments[arguments.length - 1]) {
+ builder.append(", ");
+ }
+ }
+ builder.append(')');
+ return builder.toString();
+ }
+
+
+ /**
+ * Filters member infos to find if they should be abstracted
+ */
+ private static class AbstractFilter extends NotNullPredicate<PyMemberInfo<PyFunction>> {
+ private final boolean myAllowAbstractOnly;
+
+ /**
+ * @param allowAbstractOnly returns only methods to be abstracted. Returns only methods to be moved otherwise.
+ */
+ private AbstractFilter(final boolean allowAbstractOnly) {
+ myAllowAbstractOnly = allowAbstractOnly;
+ }
+
+ @Override
+ protected boolean applyNotNull(@NotNull final PyMemberInfo<PyFunction> input) {
+ return input.isToAbstract() == myAllowAbstractOnly;
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMemberInfo.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMemberInfo.java
new file mode 100644
index 0000000..650350b
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMemberInfo.java
@@ -0,0 +1,75 @@
+/*
+ * 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.refactoring.classes.membersManager;
+
+import com.intellij.refactoring.classMembers.MemberInfoBase;
+import com.jetbrains.python.psi.PyElement;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class PyMemberInfo<T extends PyElement> extends MemberInfoBase<T> {
+ @NotNull
+ private final MembersManager<T> myMembersManager;
+ private final boolean myCouldBeAbstract;
+
+ /**
+ * TODO: Doc new param
+ * @param member element itself
+ * @param isStatic is it static or not?
+ * @param displayName element display name
+ * @param overrides does it overrides something? TRUE if is overriden, FALSE if implemented, null if not implemented or overriden
+ * TODO: use primitive instead? "Implemeneted" has nothing to do with python duck-typing
+ * @param membersManager manager that knows how to handle this member
+ */
+ PyMemberInfo(@NotNull final T member,
+ final boolean isStatic,
+ @NotNull final String displayName,
+ @Nullable final Boolean overrides,
+ @NotNull final MembersManager<T> membersManager,
+ final boolean couldBeAbstract) {
+ super(member);
+ this.isStatic = isStatic;
+ this.displayName = displayName;
+ this.overrides = overrides;
+ myMembersManager = membersManager;
+ myCouldBeAbstract = couldBeAbstract;
+ }
+
+ @NotNull
+ MembersManager<T> getMembersManager() {
+ return myMembersManager;
+ }
+
+ public boolean isCouldBeAbstract() {
+ return myCouldBeAbstract;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj instanceof PyMemberInfo) {
+ return getMember().equals(((PyMemberInfo<?>)obj).getMember());
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return getMember().hashCode();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java
new file mode 100644
index 0000000..983deb6
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyMembersRefactoringBaseProcessor.java
@@ -0,0 +1,86 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.usageView.UsageInfo;
+import com.intellij.usageView.UsageViewDescriptor;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Processor for member-based refactorings. It moves members from one place to another using {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager}.
+ * Inheritors only need to implement {@link com.intellij.usageView.UsageViewDescriptor} methods (while this interface is also implemented by this class)
+ *
+ * @author Ilya.Kazakevich
+ */
+public abstract class PyMembersRefactoringBaseProcessor extends BaseRefactoringProcessor implements UsageViewDescriptor {
+
+ @NotNull
+ protected final Collection<PyMemberInfo<PyElement>> myMembersToMove;
+ @NotNull
+ protected final PyClass myFrom;
+ @NotNull
+ private final PyClass[] myTo;
+
+ /**
+ * @param membersToMove what to move
+ * @param from source
+ * @param to where to move
+ */
+ protected PyMembersRefactoringBaseProcessor(
+ @NotNull final Project project,
+ @NotNull final Collection<PyMemberInfo<PyElement>> membersToMove,
+ @NotNull final PyClass from,
+ @NotNull final PyClass... to) {
+ super(project);
+ myFrom = from;
+ myMembersToMove = new ArrayList<PyMemberInfo<PyElement>>(membersToMove);
+ myTo = to.clone();
+ }
+
+ @NotNull
+ @Override
+ protected UsageViewDescriptor createUsageViewDescriptor(final UsageInfo[] usages) {
+ return this;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement[] getElements() {
+ return myTo.clone();
+ }
+
+ /**
+ * @return destinations (so user would be able to choose if she wants to move member to certain place or not)
+ */
+ @NotNull
+ @Override
+ protected final PyUsageInfo[] findUsages() {
+ final List<PyUsageInfo> result = new ArrayList<PyUsageInfo>(myTo.length);
+ for (final PyClass pyDestinationClass : myTo) {
+ result.add(new PyUsageInfo(pyDestinationClass));
+ }
+ return result.toArray(new PyUsageInfo[result.size()]);
+ }
+
+ @Override
+ protected final void performRefactoring(final UsageInfo[] usages) {
+ final Collection<PyClass> destinations = new ArrayList<PyClass>(usages.length);
+ for (final UsageInfo usage : usages) {
+ if (!(usage instanceof PyUsageInfo)) {
+ throw new IllegalArgumentException("Only PyUsageInfo is accepted here");
+ }
+ //We collect destination info to pass it to members manager
+ destinations.add(((PyUsageInfo)usage).getTo());
+ }
+ MembersManager.moveAllMembers(myMembersToMove, myFrom, destinations.toArray(new PyClass[destinations.size()]));
+ PyClassRefactoringUtil.optimizeImports(myFrom.getContainingFile()); // To remove unneeded imports
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyUsageInfo.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyUsageInfo.java
new file mode 100644
index 0000000..c8e1f1f
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/PyUsageInfo.java
@@ -0,0 +1,26 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.intellij.usageView.UsageInfo;
+import com.jetbrains.python.psi.PyClass;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * TODO: Make it generic to allow to reuse in another projects?
+ * Usage info that displays destination (where should member be moved)
+ *
+ * @author Ilya.Kazakevich
+ */
+class PyUsageInfo extends UsageInfo {
+ @NotNull
+ private final PyClass myTo;
+
+ PyUsageInfo(@NotNull final PyClass to) {
+ super(to, true); //TODO: Make super generic and get rid of field?
+ myTo = to;
+ }
+
+ @NotNull
+ public PyClass getTo() {
+ return myTo;
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java
new file mode 100644
index 0000000..82ce209
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/SuperClassesManager.java
@@ -0,0 +1,76 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Lists;
+import com.intellij.refactoring.RefactoringBundle;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Plugin that moves superclasses from one class to another
+ *
+ * @author Ilya.Kazakevich
+ */
+class SuperClassesManager extends MembersManager<PyClass> {
+
+ private static final NoFakeSuperClasses NO_FAKE_SUPER_CLASSES = new NoFakeSuperClasses();
+
+ SuperClassesManager() {
+ super(PyClass.class);
+ }
+
+
+ @NotNull
+ @Override
+ protected List<PyElement> getMembersCouldBeMoved(@NotNull final PyClass pyClass) {
+ return Lists.<PyElement>newArrayList(Collections2.filter(Arrays.asList(pyClass.getSuperClasses()), NO_FAKE_SUPER_CLASSES));
+ }
+
+ @Override
+ protected Collection<PyElement> moveMembers(@NotNull final PyClass from,
+ @NotNull final Collection<PyMemberInfo<PyClass>> members,
+ @NotNull final PyClass... to) {
+ final Collection<PyClass> elements = fetchElements(members);
+ for (final PyClass destClass : to) {
+ PyClassRefactoringUtil.addSuperclasses(from.getProject(), destClass, elements.toArray(new PyClass[members.size()]));
+ }
+
+ for (final PyExpression expression : from.getSuperClassExpressions()) {
+ // Remove all superclass expressions that point to class from memberinfo
+ if (!(expression instanceof PyQualifiedExpression)) {
+ continue;
+ }
+ final PyReferenceExpression reference = (PyReferenceExpression)expression;
+ for (final PyClass element : elements) {
+ if (reference.getReference().isReferenceTo(element)) {
+ expression.delete();
+ }
+ }
+ }
+ return Collections.emptyList(); //Hack: we know that "superclass expression" can't have reference
+ }
+
+ @NotNull
+ @Override
+ public PyMemberInfo<PyClass> apply(@NotNull final PyClass input) {
+ final String name = RefactoringBundle.message("member.info.extends.0", PyClassCellRenderer.getClassText(input));
+ //TODO: Check for "overrides"
+ return new PyMemberInfo<PyClass>(input, false, name, false, this, false);
+ }
+
+ private static class NoFakeSuperClasses extends NotNullPredicate<PyClass> {
+ @Override
+ protected boolean applyNotNull(@NotNull final PyClass input) {
+ return !PyNames.FAKE_OLD_BASE.equals(input.getName());
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java
new file mode 100644
index 0000000..2cf9efd
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/TypeSafeMovingStrategy.java
@@ -0,0 +1,70 @@
+package com.jetbrains.python.refactoring.classes.membersManager;
+
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Moves members checking types at runtime.
+ *
+ * @author Ilya.Kazakevich
+ */
+class TypeSafeMovingStrategy<T extends PyElement> {
+ @NotNull private final PyClass myFrom;
+ @NotNull private final MembersManager<T> myManager;
+ @NotNull private final Collection<PyMemberInfo<T>> myMemberInfoCollection;
+ @NotNull private final PyClass[] myTo;
+
+ /**
+ * Move members.
+ * @param from source
+ * @param manager manager to be used
+ * @param memberInfoCollection what to move
+ * @param to where
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"}) //We check types at runtime
+ static void moveCheckingTypesAtRunTime(@NotNull final PyClass from,
+ @NotNull final MembersManager<?> manager,
+ @NotNull final Collection<PyMemberInfo<PyElement>> memberInfoCollection,
+ @NotNull final PyClass... to) {
+ manager.checkElementTypes((Collection)MembersManager.fetchElements(memberInfoCollection));
+ new TypeSafeMovingStrategy(from, manager, memberInfoCollection, to).moveTyped();
+ }
+
+ private TypeSafeMovingStrategy(@NotNull final PyClass from,
+ @NotNull final MembersManager<T> manager,
+ @NotNull final Collection<PyMemberInfo<T>> memberInfoCollection,
+ @NotNull final PyClass[] to) {
+ myFrom = from;
+ myManager = manager;
+ myMemberInfoCollection = new ArrayList<PyMemberInfo<T>>(memberInfoCollection);
+ myTo = to.clone();
+ }
+
+
+ /**
+ * While types are already checked at runtime, this method could move everything in type-safe manner.
+ */
+ private void moveTyped() {
+ final Collection<T> elementsCollection = MembersManager.fetchElements(myMemberInfoCollection);
+ final Collection<? extends PyElement> references = myManager.getElementsToStoreReferences(elementsCollection);
+
+ // Store references to add required imports
+ for (final PyElement element : references) {
+ PyClassRefactoringUtil.rememberNamedReferences(element, PyNames.CANONICAL_SELF); //"self" is not reference we need to move
+ }
+
+ // Move
+ final Collection<PyElement> newElements = myManager.moveMembers(myFrom, myMemberInfoCollection, myTo);
+
+ // Restore references to add appropriate imports
+ for (final PyElement element : newElements) {
+ PyClassRefactoringUtil.restoreNamedReferences(element);
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/package-info.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/package-info.java
new file mode 100644
index 0000000..9fb380a
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/package-info.java
@@ -0,0 +1,12 @@
+/**
+ * Incapsulates knowledge about class members that could be moved to some other class.
+ * To use (get list of members to move or actually move them) use {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager#getAllMembersCouldBeMoved(com.jetbrains.python.psi.PyClass)}
+ * and {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager#moveAllMembers(java.util.Collection, com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyClass)}
+ *
+ * This class delegates its behaviour to its managers (some kind of plugins). There is one for each member type (one for method, one for field etc).
+ * You need to extend {@link com.jetbrains.python.refactoring.classes.membersManager.MembersManager} to add some. See its javadoc for more info.
+ *
+ *
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.python.refactoring.classes.membersManager;
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/BadDataException.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/BadDataException.java
new file mode 100644
index 0000000..684576d
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/BadDataException.java
@@ -0,0 +1,18 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * To be thrown when {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedViewSwingImpl} or its children
+ * assumes that data entered by user in {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView} is invalid.
+ * See {@link MembersBasedPresenterImpl#validateView()} for info why exception user
+ * @author Ilya.Kazakevich
+ */
+public class BadDataException extends Exception {
+ /**
+ * @param message what exactly is wrong with data
+ */
+ public BadDataException(@NotNull final String message) {
+ super(message);
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenter.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenter.java
new file mode 100644
index 0000000..f57f280
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenter.java
@@ -0,0 +1,21 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.jetbrains.python.vp.Presenter;
+
+/**
+ * Presenter for dialogs that display members
+ *
+ * @author Ilya.Kazakevich
+ */
+public interface MembersBasedPresenter extends Presenter {
+ /**
+ * User clicked on "ok" button
+ */
+ void okClicked();
+
+ /**
+ * @return true if dialog button "preview" should be displayed.
+ * Preview uses {@link com.jetbrains.python.refactoring.classes.membersManager.PyMembersRefactoringBaseProcessor}
+ */
+ boolean showPreview();
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterImpl.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterImpl.java
new file mode 100644
index 0000000..118b3d6
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterImpl.java
@@ -0,0 +1,83 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * All presenters that use members inherits this class.
+ * <strong>Warning</strong>: Do not inherit it directly.
+ * Check {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenterNoPreviewImpl}
+ * or {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenterWithPreviewImpl} instead
+ *
+ * @param <T> view for that presenter
+ * @author Ilya.Kazakevich
+ */
+abstract class MembersBasedPresenterImpl<T extends MembersBasedView<?>> implements MembersBasedPresenter {
+ @NotNull
+ protected final T myView;
+ @NotNull
+ protected final PyClass myClassUnderRefactoring;
+ @NotNull
+ protected final PyMemberInfoStorage myStorage;
+
+ /**
+ * @param view View for presenter
+ * @param classUnderRefactoring class to be refactored
+ * @param infoStorage info storage
+ */
+ MembersBasedPresenterImpl(@NotNull final T view,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage) {
+ myView = view;
+ myClassUnderRefactoring = classUnderRefactoring;
+ myStorage = infoStorage;
+ }
+
+ //TODO: Mark Async ?
+ @Override
+ public void okClicked() {
+
+ final MultiMap<PsiElement, String> conflicts = getConflicts();
+ if (conflicts.isEmpty() || myView.showConflictsDialog(conflicts)) {
+ try {
+ validateView();
+ doRefactor();
+ }
+ catch (final BadDataException e) {
+ myView.showError(e.getMessage()); //Show error message if presenter says view in invalid
+ }
+ }
+ }
+
+ /**
+ * Validates view (used by presenter to check if view is valid).
+ * When overwrite, <strong>always</strong> call "super" <strong>first</strong>!
+ * Throw {@link com.jetbrains.python.refactoring.classes.membersManager.vp.BadDataException} in case of error.
+ * Do nothing, otherwise.
+ * Method is designed to be overwritten and exception is used to simplify this process: children do not need parent's result.
+ * They just call super.
+ *
+ * @throws BadDataException
+ */
+ protected void validateView() throws BadDataException {
+ if (myView.getSelectedMemberInfos().isEmpty()) {
+ throw new BadDataException(RefactoringBundle.message("no.members.selected"));
+ }
+ }
+
+ /**
+ * Does refactoring itself
+ */
+ abstract void doRefactor();
+
+ /**
+ * @return map of conflicts (if any)
+ */
+ @NotNull
+ protected abstract MultiMap<PsiElement, String> getConflicts();
+
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterNoPreviewImpl.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterNoPreviewImpl.java
new file mode 100644
index 0000000..199ac7a
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterNoPreviewImpl.java
@@ -0,0 +1,60 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Presenter that has not preview. Children should implement {@link #refactorNoPreview()}.
+ * To "preview" button would be displayed
+ * @param <T> view for this presenter
+ * @author Ilya.Kazakevich
+ */
+
+public abstract class MembersBasedPresenterNoPreviewImpl<T extends MembersBasedView<?>> extends MembersBasedPresenterImpl<T> {
+ /**
+ *
+ * @param view view for this presenter
+ * @param classUnderRefactoring class to refactor
+ * @param infoStorage info storage
+ */
+ protected MembersBasedPresenterNoPreviewImpl(@NotNull final T view,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage) {
+ super(view, classUnderRefactoring, infoStorage);
+ }
+
+ @Override
+ public boolean showPreview() {
+ return false;
+ }
+
+ @Override
+ void doRefactor() {
+ CommandProcessor.getInstance().executeCommand(myClassUnderRefactoring.getProject(), new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ refactorNoPreview();
+ }
+ });
+ }
+ }, getCommandName(), null);
+ myView.close();
+ }
+
+ /**
+ * @return Command name for this preview
+ */
+ @NotNull
+ protected abstract String getCommandName();
+
+ /**
+ * Do refactor with out of preview. Implement this method to do refactoring.
+ */
+ protected abstract void refactorNoPreview();
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterWithPreviewImpl.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterWithPreviewImpl.java
new file mode 100644
index 0000000..ab68548
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedPresenterWithPreviewImpl.java
@@ -0,0 +1,45 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Does refactoring with preview (based on {@link com.intellij.refactoring.BaseRefactoringProcessor}).
+ * Child must implement {@link #createProcessor()} and return appropriate processor.
+ * "Preview" button would be displayed.
+ *
+ * @param <T> view for this presenter
+ * @author Ilya.Kazakevich
+ */
+public abstract class MembersBasedPresenterWithPreviewImpl<T extends MembersBasedView<?>> extends MembersBasedPresenterImpl<T> {
+
+
+ /**
+ * @param view view for this presenter
+ * @param classUnderRefactoring class to refactor
+ * @param infoStorage info storage
+ */
+ protected MembersBasedPresenterWithPreviewImpl(@NotNull final T view,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage) {
+ super(view, classUnderRefactoring, infoStorage);
+ }
+
+ @Override
+ public boolean showPreview() {
+ return true;
+ }
+
+ @Override
+ protected void doRefactor() {
+ myView.invokeRefactoring(createProcessor());
+ }
+
+ /**
+ * @return processor for refactoring
+ */
+ @NotNull
+ public abstract BaseRefactoringProcessor createProcessor();
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedView.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedView.java
new file mode 100644
index 0000000..70496d0
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedView.java
@@ -0,0 +1,69 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+/**
+ * View to display dialog with members.
+ * First, configure it with {@link #configure(MembersViewInitializationInfo)}.
+ * Then, display with {@link #initAndShow()}
+ *
+ * @param <C> initialization info for this view. See {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo}
+ * for more info
+ * @author Ilya.Kazakevich
+ */
+public interface MembersBasedView<C extends MembersViewInitializationInfo> {
+ /**
+ * Display conflict dialogs.
+ *
+ * @param conflicts conflicts.
+ * @return true if user's choice is "continue". False if "cancel"
+ */
+ boolean showConflictsDialog(@NotNull MultiMap<PsiElement, String> conflicts);
+
+ /**
+ * Displays error message
+ *
+ * @param message message to display
+ */
+ void showError(@NotNull String message);
+
+ /**
+ * Configures view and <strong>must</strong> be called once, before {@link #initAndShow()}
+ * It accepts configuration info class
+ * Children may rewrite method to do additional configuration, but they should <strong>always</strong> call "super" first!
+ *
+ * @param configInfo configuration info
+ */
+ void configure(@NotNull C configInfo);
+
+ /**
+ * @return collection of member infos user selected
+ */
+ @NotNull
+ Collection<PyMemberInfo<PyElement>> getSelectedMemberInfos();
+
+ /**
+ * Runs refactoring based on {@link com.intellij.refactoring.BaseRefactoringProcessor}.
+ * It may display "preview" first.
+ *
+ * @param processor refactoring processor
+ */
+ void invokeRefactoring(@NotNull BaseRefactoringProcessor processor);
+
+ /**
+ * Displays dialog. Be sure to run {@link #configure(MembersViewInitializationInfo)} first
+ */
+ void initAndShow();
+
+ /**
+ * Closes dialog
+ */
+ void close();
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedViewSwingImpl.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedViewSwingImpl.java
new file mode 100644
index 0000000..1fc5e53
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersBasedViewSwingImpl.java
@@ -0,0 +1,138 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.google.common.base.Preconditions;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.refactoring.ui.ConflictsDialog;
+import com.intellij.refactoring.ui.RefactoringDialog;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.ui.PyMemberSelectionPanel;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.util.Collection;
+
+/**
+ * {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView} implementation on swing.
+ * Consists of {@link #myTopPanel} and {@link #myCenterPanel}. Children must fill them in constructor.
+ * Presenter is stored in {@link #myPresenter}.
+ * Panel with members in {@link #myPyMemberSelectionPanel}
+ *
+ * @param <P> View presenter class
+ * @param <C> View configuration class
+ */
+public abstract class MembersBasedViewSwingImpl<P extends MembersBasedPresenter, C extends MembersViewInitializationInfo>
+ extends RefactoringDialog implements MembersBasedView<C> {
+
+ /**
+ * Panel to be displayed on the top
+ */
+ @NotNull
+ protected final JPanel myTopPanel;
+ /**
+ * Panel to be displayed at the center
+ */
+ @NotNull
+ protected final JComponent myCenterPanel;
+
+ /**
+ * Presenter
+ */
+ @NotNull
+ protected final P myPresenter;
+
+ /**
+ * Panel with members
+ */
+ @NotNull
+ protected final PyMemberSelectionPanel myPyMemberSelectionPanel;
+
+ private boolean myConfigured;
+
+
+ /**
+ *
+ * @param project project this view runs
+ * @param presenter view's presenter
+ * @param title window title
+ * @param supportAbstract supports "abstract" column?
+ */
+ protected MembersBasedViewSwingImpl(@NotNull final Project project, @NotNull final P presenter, @NotNull final String title,
+ final boolean supportAbstract) {
+ super(project, true);
+ myTopPanel = new JPanel(new BorderLayout());
+ myCenterPanel = new JPanel(new BorderLayout());
+ myPresenter = presenter;
+ myPyMemberSelectionPanel = new PyMemberSelectionPanel(title, supportAbstract);
+ //TODO: Take this from presenter to prevent inconsistence: now it is possible to create view that supports abstract backed by presenter that does not. And vice versa.
+ }
+
+ @Override
+ public boolean showConflictsDialog(@NotNull final MultiMap<PsiElement, String> conflicts) {
+ Preconditions.checkArgument(!conflicts.isEmpty(), "Can't show dialog for empty conflicts");
+ final ConflictsDialog conflictsDialog = new ConflictsDialog(myProject, conflicts);
+ conflictsDialog.show();
+ return conflictsDialog.isOK();
+ }
+
+ @Override
+ public void showError(@NotNull final String message) {
+ Messages.showErrorDialog(getContentPane(), message);
+ }
+
+ @Override
+ protected boolean hasPreviewButton() {
+ return myPresenter.showPreview();
+ }
+
+ @Override
+ protected void doAction() {
+ myPresenter.okClicked();
+ }
+
+ @NotNull
+ @Override
+ protected JComponent createNorthPanel() {
+ return myTopPanel;
+ }
+
+ @Override
+ public void close() {
+ close(OK_EXIT_CODE);
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+ return myCenterPanel;
+ }
+
+ @NotNull
+ @Override
+ public Collection<PyMemberInfo<PyElement>> getSelectedMemberInfos() {
+ return myPyMemberSelectionPanel.getSelectedMemberInfos();
+ }
+
+ @Override
+ public void invokeRefactoring(@NotNull final BaseRefactoringProcessor processor) {
+ super.invokeRefactoring(processor);
+ }
+
+ @Override
+ public void configure(@NotNull final C configInfo) {
+ Preconditions.checkArgument(!myConfigured, "Already configured");
+ myConfigured = true;
+ myPyMemberSelectionPanel.init(configInfo.getMemberInfoModel(), configInfo.getMemberInfos());
+ }
+
+ @Override
+ public void initAndShow() {
+ Preconditions.checkArgument(myConfigured, "Not configured, run 'configure' first!");
+ init();
+ show();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersViewInitializationInfo.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersViewInitializationInfo.java
new file mode 100644
index 0000000..7803105
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/MembersViewInitializationInfo.java
@@ -0,0 +1,49 @@
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
+
+import com.intellij.refactoring.classMembers.MemberInfoModel;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Configuration for {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView}
+ *
+ * @author Ilya.Kazakevich
+ */
+public class MembersViewInitializationInfo {
+
+ @NotNull
+ private final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> myMemberInfoModel;
+ @NotNull
+ private final Collection<PyMemberInfo<PyElement>> myMemberInfos;
+
+ /**
+ * @param memberInfoModel model to be used in members panel
+ * @param memberInfos members to displau
+ */
+ public MembersViewInitializationInfo(@NotNull final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> memberInfoModel,
+ @NotNull final Collection<PyMemberInfo<PyElement>> memberInfos) {
+ myMemberInfos = new ArrayList<PyMemberInfo<PyElement>>(memberInfos);
+ myMemberInfoModel = memberInfoModel;
+ }
+
+ /**
+ * @return model to be used in members panel
+ */
+ @NotNull
+ public MemberInfoModel<PyElement, PyMemberInfo<PyElement>> getMemberInfoModel() {
+ return myMemberInfoModel;
+ }
+
+ /**
+ * @return members to display
+ */
+ @NotNull
+ public Collection<PyMemberInfo<PyElement>> getMemberInfos() {
+ return Collections.unmodifiableCollection(myMemberInfos);
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/package-info.java b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/package-info.java
new file mode 100644
index 0000000..f714797
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/membersManager/vp/package-info.java
@@ -0,0 +1,6 @@
+/**
+ * MVP ({@link com.jetbrains.python.vp}) implementation for refactorings that use members ({@link com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo})
+ * and package {@link com.jetbrains.python.refactoring.classes.membersManager}
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.python.refactoring.classes.membersManager.vp;
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpConflictsUtil.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpConflictsUtil.java
deleted file mode 100644
index ee659c1..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PullUpConflictsUtil.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.pullUp;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.util.RefactoringUIUtil;
-import com.intellij.util.containers.MultiMap;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
-
-import java.util.Collection;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PullUpConflictsUtil {
- private PullUpConflictsUtil() {
- }
-
- public static MultiMap<PsiElement, String> checkConflicts(final Collection<PyMemberInfo> infos, final PyClass superClass) {
- final MultiMap<PsiElement, String> conflictsList = new MultiMap<PsiElement, String>();
- for (PyMemberInfo info : infos) {
- PsiElement member = info.getMember();
- boolean isConflict = false;
- if (member instanceof PyFunction) {
- final String name = ((PyFunction)member).getName();
- if (name == null) continue;
- final PyFunction superClassMethod = superClass.findMethodByName(name, false);
- isConflict = superClassMethod != null;
- } else if (member instanceof PyClass) {
- final PyClass clazz = (PyClass)member;
- for (PyClass aClass : superClass.getSuperClasses()) {
- if (aClass == clazz) {
- conflictsList.putValue(superClass,
- RefactoringUIUtil.getDescription(superClass, false) + " already extends " + RefactoringUIUtil.getDescription(clazz, false));
- }
- }
- }
-
- if (isConflict) {
- final String message = RefactoringBundle.message("0.already.contains.a.1",
- RefactoringUIUtil.getDescription(superClass, false),
- RefactoringUIUtil.getDescription(member, false));
- conflictsList.putValue(superClass, message);
- }
- }
-
- return conflictsList;
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyAncestorsUtils.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyAncestorsUtils.java
new file mode 100644
index 0000000..05c41c4
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyAncestorsUtils.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.classes.pullUp;
+
+
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Sets;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.jetbrains.NotNullPredicate;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.psi.types.TypeEvalContext;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+class PyAncestorsUtils extends NotNullPredicate<PyClass> {
+ @NotNull
+ private final Set<VirtualFile> mySourceRoots;
+
+ /**
+ * Returns list of class parents that are under user control
+ *
+ * @param pyClass class to find parents for
+ * @return list of parents
+ */
+ @NotNull
+ static Collection<PyClass> getAncestorsUnderUserControl(@NotNull final PyClass pyClass) {
+ final List<PyClass> allAncestors = pyClass.getAncestorClasses(TypeEvalContext.userInitiated(pyClass.getContainingFile()));
+ return Collections2.filter(allAncestors, new PyAncestorsUtils(PyUtil.getSourceRoots(pyClass)));
+ }
+
+ private PyAncestorsUtils(@NotNull final Collection<VirtualFile> sourceRoots) {
+ mySourceRoots = Sets.newHashSet(sourceRoots);
+ }
+
+ @Override
+ public boolean applyNotNull(@NotNull final PyClass input) {
+ return VfsUtilCore.isUnder(input.getContainingFile().getVirtualFile(), mySourceRoots);
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java
new file mode 100644
index 0000000..9c63a62
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpConflictsUtil.java
@@ -0,0 +1,69 @@
+/*
+ * 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.refactoring.classes.pullUp;
+
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.RefactoringBundle;
+import com.intellij.refactoring.util.RefactoringUIUtil;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.psi.PyFunction;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+
+/**
+ * @author Dennis.Ushakov
+ */
+final class PyPullUpConflictsUtil {
+ private PyPullUpConflictsUtil() {
+ }
+
+ @NotNull
+ static MultiMap<PsiElement, String> checkConflicts(final Collection<PyMemberInfo<PyElement>> infos, @NotNull final PyClass superClass) {
+ final MultiMap<PsiElement, String> conflictsList = new MultiMap<PsiElement, String>();
+ for (PyMemberInfo<PyElement> info : infos) {
+ PsiElement member = info.getMember();
+ boolean isConflict = false;
+ //TODO: Delegate to MemeberManagers here
+ if (member instanceof PyFunction) {
+ final String name = ((PyFunction)member).getName();
+ if (name == null) continue;
+ final PyFunction superClassMethod = superClass.findMethodByName(name, false);
+ isConflict = superClassMethod != null;
+ } else if (member instanceof PyClass) {
+ final PyClass clazz = (PyClass)member;
+ for (PyClass aClass : superClass.getSuperClasses()) {
+ if (aClass == clazz) {
+ conflictsList.putValue(superClass,
+ RefactoringUIUtil.getDescription(superClass, false) + " already extends " + RefactoringUIUtil.getDescription(clazz, false));
+ }
+ }
+ }
+
+ if (isConflict) {
+ final String message = RefactoringBundle.message("0.already.contains.a.1",
+ RefactoringUIUtil.getDescription(superClass, false),
+ RefactoringUIUtil.getDescription(member, false));
+ conflictsList.putValue(superClass, message);
+ }
+ }
+
+ return conflictsList;
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpDialog.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpDialog.java
deleted file mode 100644
index e9631a8..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpDialog.java
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.pullUp;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiElement;
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.classMembers.AbstractUsesDependencyMemberInfoModel;
-import com.intellij.refactoring.classMembers.DependencyMemberInfoModel;
-import com.intellij.refactoring.ui.ConflictsDialog;
-import com.intellij.util.containers.MultiMap;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
-import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
-import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer;
-import com.jetbrains.python.refactoring.classes.ui.UpDirectedMembersMovingDialog;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.TreeSet;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyPullUpDialog extends UpDirectedMembersMovingDialog {
- private JComboBox myClassCombo;
- private Collection<PyClass> mySuperClasses;
- private final PyMemberInfoStorage myStorage;
-
- public PyPullUpDialog(final Project project, final PyClass clazz, final Collection<PyClass> superClasses, final PyMemberInfoStorage storage) {
- super(project, clazz);
- myStorage = storage;
- mySuperClasses = new TreeSet<PyClass>(new Comparator<PyClass>() {
- public int compare(final PyClass o1, final PyClass o2) {
- final String name1 = PyClassCellRenderer.getClassText(o1);
- final String name2 = PyClassCellRenderer.getClassText(o2);
- return name1 == null ? -1 : name1.compareTo(name2);
- }
- });
- mySuperClasses = superClasses;
- myMemberInfos = myStorage.getClassMemberInfos(myClass);
-
- setTitle(PyPullUpHandler.REFACTORING_NAME);
-
- init();
- }
-
- protected DependencyMemberInfoModel<PyElement, PyMemberInfo> createMemberInfoModel() {
- return new MyMemberInfoModel(myClass);
- }
-
- protected String getHelpId() {
- return "python.reference.pullMembersUp";
- }
-
- protected JComponent createNorthPanel() {
- JPanel panel = new JPanel();
- panel.setLayout(new GridBagLayout());
- GridBagConstraints gbConstraints = new GridBagConstraints();
-
- gbConstraints.insets = new Insets(4, 8, 4, 8);
- gbConstraints.weighty = 1;
- gbConstraints.weightx = 1;
- gbConstraints.gridy = 0;
- gbConstraints.gridwidth = GridBagConstraints.REMAINDER;
- gbConstraints.fill = GridBagConstraints.BOTH;
- gbConstraints.anchor = GridBagConstraints.WEST;
- final JLabel classComboLabel = new JLabel();
- panel.add(classComboLabel, gbConstraints);
-
- myClassCombo = new JComboBox(mySuperClasses.toArray());
- myClassCombo.setRenderer(new PyClassCellRenderer());
- final String fqn = PyClassCellRenderer.getClassText(myClass);
- classComboLabel.setText(RefactoringBundle.message("pull.up.members.to", fqn));
- classComboLabel.setLabelFor(myClassCombo);
- myClassCombo.addItemListener(new ItemListener() {
- public void itemStateChanged(ItemEvent e) {
- if (e.getStateChange() == ItemEvent.SELECTED) {
- updateMembersInfo();
- if (myMemberSelectionPanel != null) {
- ((MyMemberInfoModel)myMemberInfoModel).setSuperClass(getSuperClass());
- myMemberSelectionPanel.getTable().setMemberInfos(myMemberInfos);
- myMemberSelectionPanel.getTable().fireExternalDataChange();
- }
- }
- }
- });
- gbConstraints.gridy++;
- panel.add(myClassCombo, gbConstraints);
- updateMembersInfo();
-
- return panel;
- }
-
- private void updateMembersInfo() {
- final PyClass targetClass = (PyClass)myClassCombo.getSelectedItem();
- myMemberInfos = myStorage.getIntermediateMemberInfosList(targetClass);
- }
-
- @Override
- public boolean checkConflicts() {
- final Collection<PyMemberInfo> infos = getSelectedMemberInfos();
- PyClass superClass = getSuperClass();
- if (!checkWritable(superClass, infos)) return false;
- MultiMap<PsiElement,String> conflicts = PullUpConflictsUtil.checkConflicts(infos, superClass);
- if (!conflicts.isEmpty()) {
- ConflictsDialog conflictsDialog = new ConflictsDialog(myClass.getProject(), conflicts);
- conflictsDialog.show();
- final boolean ok = conflictsDialog.isOK();
- if (!ok && conflictsDialog.isShowConflicts()) close(CANCEL_EXIT_CODE);
- return ok;
- }
- return true;
- }
-
- @Nullable
- public PyClass getSuperClass() {
- return myClassCombo != null ? (PyClass)myClassCombo.getSelectedItem() : null;
- }
-
- protected String getMembersBorderTitle() {
- return RefactoringBundle.message("members.to.be.pulled.up");
- }
-
- private class MyMemberInfoModel extends AbstractUsesDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo> {
- public MyMemberInfoModel(PyClass clazz) {
- super(clazz, getSuperClass(), false);
- }
-
-
- public boolean isMemberEnabled(PyMemberInfo member) {
- PyClass currentSuperClass = getSuperClass();
- return (currentSuperClass == null ||
- !myStorage.getDuplicatedMemberInfos(currentSuperClass).contains(member)) &&
- member.getMember() != currentSuperClass;
- }
-
- public boolean isAbstractEnabled(PyMemberInfo member) {
- return false;
- }
-
- public int checkForProblems(@NotNull PyMemberInfo member) {
- return member.isChecked() ? OK : super.checkForProblems(member);
- }
-
- @Override
- protected int doCheck(@NotNull PyMemberInfo memberInfo, int problem) {
- if (problem == ERROR && memberInfo.isStatic()) {
- return WARNING;
- }
- return problem;
- }
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHandler.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHandler.java
index 0e95700..6dcb3b6 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHandler.java
@@ -15,24 +15,17 @@
*/
package com.jetbrains.python.refactoring.classes.pullUp;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
-import com.intellij.util.PsiNavigateUtil;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyUtil;
-import com.jetbrains.python.refactoring.classes.PyClassMembersRefactoringSupport;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringHandler;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
-
-import java.util.Collection;
+import com.jetbrains.python.vp.Creator;
+import com.jetbrains.python.vp.ViewPresenterUtils;
+import org.jetbrains.annotations.NotNull;
/**
* @author: Dennis.Ushakov
@@ -41,33 +34,39 @@
public static final String REFACTORING_NAME = PyBundle.message("refactoring.pull.up.dialog.title");
@Override
- protected void doRefactor(Project project, PsiElement element1, PsiElement element2, Editor editor, PsiFile file, DataContext dataContext) {
- CommonRefactoringUtil.checkReadOnlyStatus(project, file);
+ protected void doRefactorImpl(@NotNull final Project project,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage,
+ @NotNull final Editor editor) {
+ //TODO: Move to vp (presenter) as well
- final PyClass clazz = PyUtil.getContainingClassOrSelf(element1);
- if (!inClass(clazz, project, editor, "refactoring.pull.up.error.cannot.perform.refactoring.not.inside.class")) return;
-
- final PyMemberInfoStorage infoStorage = PyClassMembersRefactoringSupport.getSelectedMemberInfos(clazz, element1, element2);
- final Collection<PyClass> classes = infoStorage.getClasses();
- if (classes.size() == 0) {
- assert clazz != null;
- CommonRefactoringUtil.showErrorHint(project, editor, PyBundle.message("refactoring.pull.up.error.cannot.perform.refactoring.no.base.classes", clazz.getName()),
- RefactoringBundle.message("pull.members.up.title"),
- "members.pull.up");
+ if (PyAncestorsUtils.getAncestorsUnderUserControl(classUnderRefactoring).isEmpty() ||
+ infoStorage.getClassMemberInfos(classUnderRefactoring).isEmpty()) {
+ CommonRefactoringUtil.showErrorHint(project, editor, PyBundle
+ .message("refactoring.pull.up.error.cannot.perform.refactoring.no.base.classes",
+ classUnderRefactoring.getName()), RefactoringBundle.message("pull.members.up.title"),
+ "members.pull.up"
+ );
return;
}
- if (ApplicationManagerEx.getApplicationEx().isUnitTestMode()) return;
-
- final PyPullUpDialog dialog = new PyPullUpDialog(project, clazz, classes, infoStorage);
- dialog.show();
- if(dialog.isOK()) {
- pullUpWithHelper(clazz, dialog.getSelectedMemberInfos(), dialog.getSuperClass());
- }
- }
- private static void pullUpWithHelper(PyClass clazz, Collection<PyMemberInfo> selectedMemberInfos, PyClass superClass) {
- PsiNavigateUtil.navigate(PyPullUpHelper.pullUp(clazz, selectedMemberInfos, superClass));
+ ViewPresenterUtils
+ .linkViewWithPresenterAndLaunch(PyPullUpPresenter.class, PyPullUpView.class, new Creator<PyPullUpView, PyPullUpPresenter>() {
+ @NotNull
+ @Override
+ public PyPullUpPresenter createPresenter(@NotNull final PyPullUpView view) {
+ return new PyPullUpPresenterImpl(view, infoStorage, classUnderRefactoring);
+ }
+
+ @NotNull
+ @Override
+ public PyPullUpView createView(@NotNull final PyPullUpPresenter presenter) {
+ return new PyPullUpViewSwingImpl(project, presenter, classUnderRefactoring);
+ }
+ }
+ );
+
}
@Override
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java
deleted file mode 100644
index 0046ba2..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpHelper.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.pullUp;
-
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.command.CommandProcessor;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.psi.PsiNamedElement;
-import com.intellij.refactoring.RefactoringBundle;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
-
-import java.util.*;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyPullUpHelper {
- private static final Logger LOG = Logger.getInstance(PyPullUpHelper.class.getName());
- private PyPullUpHelper() {}
-
- public static PyElement pullUp(final PyClass clazz, final Collection<PyMemberInfo> selectedMemberInfos, final PyClass superClass) {
- final Set<String> superClasses = new HashSet<String>();
- final Set<PsiNamedElement> extractedClasses = new HashSet<PsiNamedElement>();
- final List<PyFunction> methods = new ArrayList<PyFunction>();
- for (PyMemberInfo member : selectedMemberInfos) {
- final PyElement element = member.getMember();
- if (element instanceof PyFunction) methods.add((PyFunction)element);
- else if (element instanceof PyClass) {
- superClasses.add(element.getName());
- extractedClasses.add((PyClass)element);
- }
- else LOG.error("unmatched member class " + element.getClass());
- }
-
- CommandProcessor.getInstance().executeCommand(clazz.getProject(), new Runnable() {
- public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
- // move methods
- PyClassRefactoringUtil.moveMethods(methods, superClass);
-
- // move superclasses declarations
- PyClassRefactoringUtil.moveSuperclasses(clazz, superClasses, superClass);
- PyClassRefactoringUtil.insertImport(superClass, extractedClasses);
- PyClassRefactoringUtil.insertPassIfNeeded(clazz);
- }
- });
- }
- }, RefactoringBundle.message("pull.members.up.title"), null);
-
- return superClass;
- }
-
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenter.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenter.java
new file mode 100644
index 0000000..d98433f
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenter.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.classes.pullUp;
+
+
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenter;
+
+/**
+ * Presenter for pull-up refactoring
+ *
+ * TODO: Interface left empty. Remove?
+ *
+ * @author Ilya.Kazakevich
+ */
+public interface PyPullUpPresenter extends MembersBasedPresenter {
+
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java
new file mode 100644
index 0000000..83c2f0b
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterImpl.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.classes.pullUp;
+
+import com.google.common.base.Preconditions;
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.refactoring.classMembers.AbstractUsesDependencyMemberInfoModel;
+import com.intellij.refactoring.util.CommonRefactoringUtil;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenterWithPreviewImpl;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+
+/**
+ * Pull-up presenter implementation
+ *
+ * @author Ilya.Kazakevich
+ */
+class PyPullUpPresenterImpl extends MembersBasedPresenterWithPreviewImpl<PyPullUpView> implements PyPullUpPresenter {
+ @NotNull
+ private final Collection<PyClass> myParents;
+
+ /**
+ * @param view view
+ * @param infoStorage member storage
+ * @param clazz class to refactor
+ */
+ PyPullUpPresenterImpl(@NotNull final PyPullUpView view, @NotNull final PyMemberInfoStorage infoStorage, @NotNull final PyClass clazz) {
+ super(view, clazz, infoStorage);
+ myParents = PyAncestorsUtils.getAncestorsUnderUserControl(clazz);
+ Preconditions.checkArgument(!myParents.isEmpty(), "No parents found");
+ }
+
+
+ @Override
+ public void launch() {
+ myView.configure(
+ new PyPullUpViewInitializationInfo(new PyPullUpInfoModel(), myStorage.getClassMemberInfos(myClassUnderRefactoring), myParents));
+ myView.initAndShow();
+ }
+
+ @Override
+ public void okClicked() {
+ if (!isWritable()) {
+ return; //TODO: Strange behaviour
+ }
+ super.okClicked();
+ }
+
+ @NotNull
+ @Override
+ public BaseRefactoringProcessor createProcessor() {
+ return new PyPullUpProcessor(myClassUnderRefactoring, myView.getSelectedParent(), myView.getSelectedMemberInfos());
+ }
+
+ private boolean isWritable() {
+ final Collection<PyMemberInfo<PyElement>> infos = myView.getSelectedMemberInfos();
+ if (infos.isEmpty()) {
+ return true;
+ }
+ final PyElement element = infos.iterator().next().getMember();
+ final Project project = element.getProject();
+ if (!CommonRefactoringUtil.checkReadOnlyStatus(project, myView.getSelectedParent())) return false;
+ final PyClass container = PyUtil.getContainingClassOrSelf(element);
+ if (container == null || !CommonRefactoringUtil.checkReadOnlyStatus(project, container)) return false;
+ for (final PyMemberInfo<PyElement> info : infos) {
+ final PyElement member = info.getMember();
+ if (!CommonRefactoringUtil.checkReadOnlyStatus(project, member)) return false;
+ }
+ return true;
+ }
+
+
+ @Override
+ @NotNull
+ public MultiMap<PsiElement, String> getConflicts() {
+ final Collection<PyMemberInfo<PyElement>> infos = myView.getSelectedMemberInfos();
+ final PyClass superClass = myView.getSelectedParent();
+ return PyPullUpConflictsUtil.checkConflicts(infos, superClass);
+ }
+
+ private class PyPullUpInfoModel extends AbstractUsesDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo<PyElement>> {
+
+ PyPullUpInfoModel() {
+ super(myClassUnderRefactoring, null, false);
+ }
+
+ @Override
+ public boolean isAbstractEnabled(final PyMemberInfo<PyElement> member) {
+ return member.isCouldBeAbstract() && isMemberEnabled(member); // TODO: copy paste with other models, get rid of
+ }
+
+ @Override
+ public int checkForProblems(@NotNull final PyMemberInfo<PyElement> member) {
+ return member.isChecked() ? OK : super.checkForProblems(member);
+ }
+
+
+ @Override
+ protected int doCheck(@NotNull final PyMemberInfo<PyElement> memberInfo, final int problem) {
+ if (problem == ERROR && memberInfo.isStatic()) {
+ return WARNING;
+ }
+ return problem;
+ }
+
+ @Override
+ public boolean isMemberEnabled(final PyMemberInfo<PyElement> member) {
+ final PyClass currentSuperClass = myView.getSelectedParent();
+ if (member.getMember() instanceof PyClass) {
+ //TODO: Delegate to Memebers Managers
+ final PyClass memberClass = (PyClass)member.getMember();
+ if (memberClass.isSubclass(currentSuperClass) || currentSuperClass.isSubclass(memberClass)) {
+ return false; //Class is already parent of superclass
+ }
+ }
+ if (!PyPullUpConflictsUtil.checkConflicts(Collections.singletonList(member), myView.getSelectedParent()).isEmpty()) {
+ return false; //Member has conflict
+ }
+ return (!myStorage.getDuplicatedMemberInfos(currentSuperClass).contains(member)) && member.getMember() != currentSuperClass;
+ }
+ }
+}
+
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java
new file mode 100644
index 0000000..1eaa742
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpProcessor.java
@@ -0,0 +1,45 @@
+package com.jetbrains.python.refactoring.classes.pullUp;
+
+import com.jetbrains.python.PyBundle;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMembersRefactoringBaseProcessor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+/**
+ *
+ *
+ * @author Ilya.Kazakevich
+ */
+class PyPullUpProcessor extends PyMembersRefactoringBaseProcessor {
+
+ PyPullUpProcessor(@NotNull final PyClass from, @NotNull final PyClass to, @NotNull final Collection<PyMemberInfo<PyElement>> membersToMove) {
+ super(from.getProject(), membersToMove, from, to);
+ }
+
+
+ @Override
+ protected String getCommandName() {
+ return PyPullUpHandler.REFACTORING_NAME;
+ }
+
+ @Override
+ public String getProcessedElementsHeader() {
+ return PyBundle.message("refactoring.pull.up.dialog.move.members.to.class");
+ }
+
+ @Override
+ public String getCodeReferencesText(final int usagesCount, final int filesCount) {
+ return PyBundle.message("refactoring.pull.up.dialog.members.to.be.moved");
+ }
+
+ @Nullable
+ @Override
+ public String getCommentReferencesText(final int usagesCount, final int filesCount) {
+ return getCodeReferencesText(usagesCount, filesCount);
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpView.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpView.java
new file mode 100644
index 0000000..b0a42e0
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpView.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.classes.pullUp;
+
+
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Ilya.Kazakevich
+ * View for pull-up refactoring
+ */
+public interface PyPullUpView extends MembersBasedView<PyPullUpViewInitializationInfo> {
+
+ /**
+ * @return Parent that user selected
+ */
+ @NotNull
+ PyClass getSelectedParent();
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpViewInitializationInfo.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpViewInitializationInfo.java
new file mode 100644
index 0000000..c438e84
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpViewInitializationInfo.java
@@ -0,0 +1,38 @@
+package com.jetbrains.python.refactoring.classes.pullUp;
+
+import com.intellij.refactoring.classMembers.MemberInfoModel;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Configuration for pull-up view
+ *
+ * @author Ilya.Kazakevich
+ */
+class PyPullUpViewInitializationInfo extends MembersViewInitializationInfo {
+ @NotNull
+ private final Collection<PyClass> myParents;
+
+ /**
+ * @param parents list of possible parents to display.
+ */
+ PyPullUpViewInitializationInfo(@NotNull final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> memberInfoModel,
+ @NotNull final List<PyMemberInfo<PyElement>> memberInfos,
+ @NotNull final Collection<PyClass> parents) {
+ super(memberInfoModel, memberInfos);
+ myParents = new ArrayList<PyClass>(parents);
+ }
+
+ @NotNull
+ public Collection<PyClass> getParents() {
+ return Collections.unmodifiableCollection(myParents);
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpViewSwingImpl.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpViewSwingImpl.java
new file mode 100644
index 0000000..2a457f8
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpViewSwingImpl.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.refactoring.classes.pullUp;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.refactoring.RefactoringBundle;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedViewSwingImpl;
+import com.jetbrains.python.refactoring.classes.ui.PyClassCellRenderer;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+
+
+/**
+ * @author Ilya.Kazakevich
+ * Pull up view implementation
+ */
+class PyPullUpViewSwingImpl extends MembersBasedViewSwingImpl<PyPullUpPresenter, PyPullUpViewInitializationInfo> implements PyPullUpView,
+ ItemListener {
+ @NotNull
+ private final ComboBox myParentsCombo;
+ @NotNull
+ private final DefaultComboBoxModel myParentsComboBoxModel;
+
+ /**
+ * @param project project where refactoring takes place
+ * @param presenter presenter for this view
+ * @param clazz class to refactor
+ */
+ PyPullUpViewSwingImpl(@NotNull final Project project, @NotNull final PyPullUpPresenter presenter, @NotNull final PyClass clazz) {
+ super(project, presenter, RefactoringBundle.message("members.to.be.pulled.up"), true);
+ setTitle(PyPullUpHandler.REFACTORING_NAME);
+
+ myParentsComboBoxModel = new DefaultComboBoxModel();
+
+ myParentsCombo = new ComboBox(myParentsComboBoxModel);
+ myParentsCombo.setRenderer(new PyClassCellRenderer());
+
+ final JLabel mainLabel = new JLabel();
+ mainLabel.setText(RefactoringBundle.message("pull.up.members.to", PyClassCellRenderer.getClassText(clazz)));
+ mainLabel.setLabelFor(myParentsCombo);
+
+
+ myTopPanel.setLayout(new GridBagLayout());
+ final GridBagConstraints gbConstraints = new GridBagConstraints();
+
+ gbConstraints.insets = new Insets(4, 8, 4, 8);
+ gbConstraints.weighty = 1;
+ gbConstraints.weightx = 1;
+ gbConstraints.gridy = 0;
+ gbConstraints.gridwidth = GridBagConstraints.REMAINDER;
+ gbConstraints.fill = GridBagConstraints.BOTH;
+ gbConstraints.anchor = GridBagConstraints.WEST;
+ myTopPanel.add(mainLabel, gbConstraints);
+ myTopPanel.add(mainLabel, gbConstraints);
+ gbConstraints.gridy++;
+ myTopPanel.add(myParentsCombo, gbConstraints);
+
+ gbConstraints.gridy++;
+ myCenterPanel.add(myPyMemberSelectionPanel, BorderLayout.CENTER);
+ }
+
+ @Override
+ @NotNull
+ protected String getHelpId() {
+ return "python.reference.pullMembersUp";
+ }
+
+
+ @NotNull
+ @Override
+ public PyClass getSelectedParent() {
+ return (PyClass)myParentsComboBoxModel.getSelectedItem();
+ }
+
+
+
+ @Override
+ public void configure(@NotNull final PyPullUpViewInitializationInfo configInfo) {
+ super.configure(configInfo);
+ for (final PyClass parent : configInfo.getParents()) {
+ myParentsComboBoxModel.addElement(parent);
+ }
+ myParentsCombo.addItemListener(this);
+ }
+
+ @Override
+ public void itemStateChanged(final ItemEvent e) {
+ if (e.getStateChange() == ItemEvent.SELECTED) {
+ myPyMemberSelectionPanel.redraw();
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pullUp/package-info.java b/python/src/com/jetbrains/python/refactoring/classes/pullUp/package-info.java
new file mode 100644
index 0000000..4623236
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pullUp/package-info.java
@@ -0,0 +1,5 @@
+/**
+ * "Pull members up" refactoring
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.python.refactoring.classes.pullUp;
\ No newline at end of file
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownConflicts.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownConflicts.java
index c159b2f..9eee6c9 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownConflicts.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownConflicts.java
@@ -25,7 +25,7 @@
import com.intellij.util.containers.MultiMap;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.resolve.PyResolveContext;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
import java.util.ArrayList;
import java.util.Collection;
@@ -34,29 +34,29 @@
/**
* @author Dennis.Ushakov
*/
-public class PyPushDownConflicts {
+class PyPushDownConflicts {
private static final Logger LOG = Logger.getInstance(PyPushDownProcessor.class.getName());
private final PyClass myClass;
- private final Collection<PyMemberInfo> myMembers;
+ private final Collection<PyMemberInfo<PyElement>> myMembers;
private final MultiMap<PsiElement, String> myConflicts;
- public PyPushDownConflicts(final PyClass clazz, final Collection<PyMemberInfo> members) {
+ public PyPushDownConflicts(final PyClass clazz, final Collection<PyMemberInfo<PyElement>> members) {
myClass = clazz;
myMembers = members;
myConflicts = new MultiMap<PsiElement, String>();
}
- public MultiMap<PsiElement, String> getConflicts() {
+ MultiMap<PsiElement, String> getConflicts() {
return myConflicts;
}
- public void checkTargetClassConflicts(PyClass clazz) {
+ void checkTargetClassConflicts(PyClass clazz) {
checkPlacementConflicts(clazz);
}
private void checkPlacementConflicts(PyClass clazz) {
- for (PyMemberInfo member : myMembers) {
+ for (PyMemberInfo<PyElement> member : myMembers) {
final PyElement element = member.getMember();
if (element instanceof PyFunction) {
for (PyFunction function : clazz.getMethods()) {
@@ -73,8 +73,8 @@
}
public void checkSourceClassConflicts() {
- final List<PyElement> elements = ContainerUtil.map(myMembers, new Function<PyMemberInfo, PyElement>() {
- public PyElement fun(PyMemberInfo pyMemberInfo) {
+ final List<PyElement> elements = ContainerUtil.map(myMembers, new Function<PyMemberInfo<PyElement>, PyElement>() {
+ public PyElement fun(PyMemberInfo<PyElement> pyMemberInfo) {
return pyMemberInfo.getMember();
}
});
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownDialog.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownDialog.java
deleted file mode 100644
index 2235c57..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownDialog.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.pushDown;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.refactoring.classMembers.MemberInfoChange;
-import com.intellij.refactoring.classMembers.MemberInfoModel;
-import com.intellij.refactoring.classMembers.UsedByDependencyMemberInfoModel;
-import com.intellij.refactoring.ui.RefactoringDialog;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
-import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
-import com.jetbrains.python.refactoring.classes.ui.PyMemberSelectionPanel;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyPushDownDialog extends RefactoringDialog {
- private final List<PyMemberInfo> myMemberInfos;
- private final PyClass myClass;
- private MemberInfoModel<PyElement, PyMemberInfo> myMemberInfoModel;
-
- public PyPushDownDialog(Project project, PyClass aClass, PyMemberInfoStorage memberInfos) {
- super(project, true);
- myMemberInfos = memberInfos.getClassMemberInfos(aClass);
- myClass = aClass;
-
- setTitle(PyPushDownHandler.REFACTORING_NAME);
-
- init();
- }
-
- protected String getHelpId() {
- return "python.reference.pushMembersDown";
- }
-
- @Override
- protected void doAction() {
- if(!isOKActionEnabled()) return;
-
- final PyPushDownProcessor processor = new PyPushDownProcessor(getProject(), myClass, getSelectedMemberInfos());
- invokeRefactoring(processor);
- }
-
- protected JComponent createNorthPanel() {
- GridBagConstraints gbConstraints = new GridBagConstraints();
-
- JPanel panel = new JPanel(new GridBagLayout());
-
- gbConstraints.insets = new Insets(4, 0, 4, 8);
- gbConstraints.weighty = 1;
- gbConstraints.weightx = 1;
- gbConstraints.gridy = 0;
- gbConstraints.gridwidth = GridBagConstraints.REMAINDER;
- gbConstraints.fill = GridBagConstraints.BOTH;
- gbConstraints.anchor = GridBagConstraints.WEST;
- final String fqn = myClass.getName();
- panel.add(new JLabel(RefactoringBundle.message("push.members.from.0.down.label", fqn)), gbConstraints);
- return panel;
- }
-
- protected JComponent createCenterPanel() {
- JPanel panel = new JPanel(new BorderLayout());
- final PyMemberSelectionPanel memberSelectionPanel = new PyMemberSelectionPanel(
- RefactoringBundle.message("members.to.be.pushed.down.panel.title"),
- myMemberInfos, null);
- panel.add(memberSelectionPanel, BorderLayout.CENTER);
-
- myMemberInfoModel = new UsedByDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo>(myClass);
- myMemberInfoModel.memberInfoChanged(new MemberInfoChange<PyElement, PyMemberInfo>(myMemberInfos));
- memberSelectionPanel.getTable().setMemberInfoModel(myMemberInfoModel);
- memberSelectionPanel.getTable().addMemberInfoChangeListener(myMemberInfoModel);
-
- return panel;
- }
-
- public Collection<PyMemberInfo> getSelectedMemberInfos() {
- ArrayList<PyMemberInfo> list = new ArrayList<PyMemberInfo>(myMemberInfos.size());
- for (PyMemberInfo info : myMemberInfos) {
- if (info.isChecked() && myMemberInfoModel.isMemberEnabled(info)) {
- list.add(info);
- }
- }
- return list;
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownHandler.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownHandler.java
index 689d508..08fda71 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownHandler.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownHandler.java
@@ -15,21 +15,18 @@
*/
package com.jetbrains.python.refactoring.classes.pushDown;
-import com.intellij.openapi.actionSystem.DataContext;
-import com.intellij.openapi.application.ex.ApplicationManagerEx;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.util.CommonRefactoringUtil;
import com.intellij.util.Query;
import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyUtil;
import com.jetbrains.python.psi.search.PyClassInheritorsSearch;
-import com.jetbrains.python.refactoring.classes.PyClassMembersRefactoringSupport;
import com.jetbrains.python.refactoring.classes.PyClassRefactoringHandler;
import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import com.jetbrains.python.vp.Creator;
+import com.jetbrains.python.vp.ViewPresenterUtils;
+import org.jetbrains.annotations.NotNull;
/**
* @author Dennis.Ushakov
@@ -38,26 +35,33 @@
public static final String REFACTORING_NAME = RefactoringBundle.message("push.members.down.title");
@Override
- protected void doRefactor(Project project, PsiElement element1, PsiElement element2, Editor editor, PsiFile file, DataContext dataContext) {
- CommonRefactoringUtil.checkReadOnlyStatus(project, file);
+ protected void doRefactorImpl(@NotNull final Project project,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage,
+ @NotNull Editor editor) {
- final PyClass clazz = PyUtil.getContainingClassOrSelf(element1);
- if (!inClass(clazz, project, editor, "refactoring.pull.up.error.cannot.perform.refactoring.not.inside.class")) return;
-
- final Query<PyClass> query = PyClassInheritorsSearch.search(clazz, false);
+ //TODO: Move to presenter?
+ final Query<PyClass> query = PyClassInheritorsSearch.search(classUnderRefactoring, false);
if (query.findFirst() == null) {
- assert clazz != null;
- final String message = RefactoringBundle.message("class.0.does.not.have.inheritors", clazz.getName());
+ final String message = RefactoringBundle.message("class.0.does.not.have.inheritors", classUnderRefactoring.getName());
CommonRefactoringUtil.showErrorHint(project, editor, message, getTitle(), getHelpId());
return;
}
- final PyMemberInfoStorage infoStorage = PyClassMembersRefactoringSupport.getSelectedMemberInfos(clazz, element1, element2);
+ ViewPresenterUtils
+ .linkViewWithPresenterAndLaunch(PyPushDownPresenter.class, PyPushDownView.class, new Creator<PyPushDownView, PyPushDownPresenter>() {
+ @NotNull
+ @Override
+ public PyPushDownPresenter createPresenter(@NotNull PyPushDownView view) {
+ return new PyPushDownPresenterImpl(project, view, classUnderRefactoring, infoStorage);
+ }
- if (ApplicationManagerEx.getApplicationEx().isUnitTestMode()) return;
-
- final PyPushDownDialog dialog = new PyPushDownDialog(project, clazz, infoStorage);
- dialog.show();
+ @NotNull
+ @Override
+ public PyPushDownView createView(@NotNull PyPushDownPresenter presenter) {
+ return new PyPushDownViewSwingImpl(classUnderRefactoring, project, presenter);
+ }
+ });
}
@Override
@@ -69,5 +73,4 @@
protected String getHelpId() {
return "members.push.down";
}
-
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownPresenter.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownPresenter.java
new file mode 100644
index 0000000..357aa66
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownPresenter.java
@@ -0,0 +1,9 @@
+package com.jetbrains.python.refactoring.classes.pushDown;
+
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenter;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public interface PyPushDownPresenter extends MembersBasedPresenter {
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownPresenterImpl.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownPresenterImpl.java
new file mode 100644
index 0000000..1e9cabd
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownPresenterImpl.java
@@ -0,0 +1,52 @@
+package com.jetbrains.python.refactoring.classes.pushDown;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.BaseRefactoringProcessor;
+import com.intellij.refactoring.classMembers.UsedByDependencyMemberInfoModel;
+import com.intellij.util.containers.MultiMap;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.psi.PyUtil;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenterWithPreviewImpl;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public class PyPushDownPresenterImpl extends MembersBasedPresenterWithPreviewImpl<PyPushDownView> implements PyPushDownPresenter {
+ @NotNull
+ private final Project myProject;
+
+ public PyPushDownPresenterImpl(@NotNull final Project project,
+ @NotNull final PyPushDownView view,
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final PyMemberInfoStorage infoStorage) {
+ super(view, classUnderRefactoring, infoStorage);
+ myProject = project;
+ }
+
+ @NotNull
+ @Override
+ public BaseRefactoringProcessor createProcessor() {
+ return new PyPushDownProcessor(myProject, myView.getSelectedMemberInfos(), myClassUnderRefactoring);
+ }
+
+ @NotNull
+ @Override
+ protected MultiMap<PsiElement, String> getConflicts() {
+ return new PyPushDownConflicts(myClassUnderRefactoring, myStorage.getClassMemberInfos(myClassUnderRefactoring)).getConflicts();
+ }
+
+ @Override
+ public void launch() {
+ UsedByDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo<PyElement>> model =
+ new UsedByDependencyMemberInfoModel<PyElement, PyClass, PyMemberInfo<PyElement>>(myClassUnderRefactoring);
+ myView
+ .configure(new MembersViewInitializationInfo(model, PyUtil.filterOutObject(myStorage.getClassMemberInfos(myClassUnderRefactoring))));
+ myView.initAndShow();
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java
index e7026aa..a0fcf53 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownProcessor.java
@@ -15,120 +15,51 @@
*/
package com.jetbrains.python.refactoring.classes.pushDown;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.Ref;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiNamedElement;
-import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.usageView.UsageInfo;
-import com.intellij.usageView.UsageViewDescriptor;
-import com.intellij.util.Function;
-import com.intellij.util.containers.ContainerUtil;
+import com.intellij.usageView.UsageViewBundle;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.psi.PyExpression;
-import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.search.PyClassInheritorsSearch;
-import com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMembersRefactoringBaseProcessor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
-import java.util.*;
+import java.util.Collection;
/**
* @author Dennis.Ushakov
*/
-public class PyPushDownProcessor extends BaseRefactoringProcessor {
- private static final Logger LOG = Logger.getInstance(PyPushDownProcessor.class.getName());
+public class PyPushDownProcessor extends PyMembersRefactoringBaseProcessor {
- private PyClass myClass;
- private final Collection<PyMemberInfo> mySelectedMemberInfos;
+ private static final String HEADER = RefactoringBundle.message("push.down.members.elements.header");
- public PyPushDownProcessor(Project project, PyClass clazz, Collection<PyMemberInfo> selectedMemberInfos) {
- super(project);
- myClass = clazz;
- mySelectedMemberInfos = selectedMemberInfos;
+ public PyPushDownProcessor(
+ @NotNull final Project project,
+ @NotNull final Collection<PyMemberInfo<PyElement>> membersToMove,
+ @NotNull final PyClass from) {
+ super(project, membersToMove, from, getChildren(from));
}
@NotNull
- @Override
- protected UsageViewDescriptor createUsageViewDescriptor(UsageInfo[] usages) {
- return new PyPushDownUsageViewDescriptor(myClass);
+ private static PyClass[] getChildren(@NotNull final PyClass from) {
+ Collection<PyClass> all = PyClassInheritorsSearch.search(from, false).findAll();
+ return all.toArray(new PyClass[all.size()]);
}
- @NotNull
- @Override
- protected UsageInfo[] findUsages() {
- final Collection<PyClass> subClasses = PyClassInheritorsSearch.search(myClass, false).findAll();
- final UsageInfo[] result = new UsageInfo[subClasses.size()];
- ContainerUtil.map2Array(subClasses, result, new Function<PyClass, UsageInfo>() {
- public UsageInfo fun(PyClass pyClass) {
- return new UsageInfo(pyClass);
- }
- });
- return result;
+
+ public String getProcessedElementsHeader() {
+ return HEADER;
}
- @Override
- protected void refreshElements(PsiElement[] elements) {
- if (elements.length == 1 && elements[0] instanceof PyClass) {
- myClass = (PyClass)elements[0];
- }
+ public String getCodeReferencesText(int usagesCount, int filesCount) {
+ return RefactoringBundle.message("classes.to.push.down.members.to", UsageViewBundle.getReferencesString(usagesCount, filesCount));
}
- @Override
- protected void performRefactoring(UsageInfo[] usages) {
- final Set<String> superClasses = new HashSet<String>();
- final Set<PsiNamedElement> extractedClasses = new HashSet<PsiNamedElement>();
- final List<PyFunction> methods = new ArrayList<PyFunction>();
- for (PyMemberInfo member : mySelectedMemberInfos) {
- final PyElement element = member.getMember();
- if (element instanceof PyFunction) methods.add((PyFunction)element);
- else if (element instanceof PyClass) {
- superClasses.add(element.getName());
- extractedClasses.add((PyClass)element);
- }
- else LOG.error("unmatched member class " + element.getClass());
- }
- final PyElement[] elements = methods.toArray(new PyElement[methods.size()]);
-
- final List<PyExpression> superClassesElements = PyClassRefactoringUtil.removeAndGetSuperClasses(myClass, superClasses);
-
- for (UsageInfo usage : usages) {
- final PyClass targetClass = (PyClass)usage.getElement();
- PyClassRefactoringUtil.addMethods(targetClass, elements, false);
- PyClassRefactoringUtil.addSuperclasses(myClass.getProject(), targetClass, superClassesElements, superClasses);
- PyClassRefactoringUtil.insertImport(targetClass, extractedClasses);
- }
-
- if (methods.size() != 0) {
- PyPsiUtils.removeElements(elements);
- PyClassRefactoringUtil.insertPassIfNeeded(myClass);
- }
- }
-
- @Override
- protected boolean preprocessUsages(Ref<UsageInfo[]> ref) {
- final UsageInfo[] usages = ref.get();
- final PyPushDownConflicts conflicts = new PyPushDownConflicts(myClass, mySelectedMemberInfos);
- conflicts.checkSourceClassConflicts();
-
- if (usages.length == 0) {
- final String message = RefactoringBundle.message("class.0.does.not.have.inheritors", myClass.getName()) + "\nPushing members down will result in them being deleted";
- final int answer = Messages.showYesNoDialog(message, PyPushDownHandler.REFACTORING_NAME, Messages.getWarningIcon());
- if (answer != 0) {
- return false;
- }
- }
-
- for (UsageInfo usage : usages) {
- conflicts.checkTargetClassConflicts((PyClass)usage.getElement());
- }
- return showConflicts(conflicts.getConflicts(), usages);
+ @Nullable
+ public String getCommentReferencesText(int usagesCount, int filesCount) {
+ return null;
}
@Override
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownUsageViewDescriptor.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownUsageViewDescriptor.java
deleted file mode 100644
index 97f858a..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownUsageViewDescriptor.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.pushDown;
-
-import com.intellij.psi.PsiElement;
-import com.intellij.refactoring.RefactoringBundle;
-import com.intellij.usageView.UsageViewBundle;
-import com.intellij.usageView.UsageViewDescriptor;
-import com.jetbrains.python.psi.PyClass;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyPushDownUsageViewDescriptor implements UsageViewDescriptor {
- private final PyClass myClass;
- private static final String HEADER = RefactoringBundle.message("push.down.members.elements.header");
-
- public PyPushDownUsageViewDescriptor(final PyClass clazz) {
- myClass = clazz;
- }
-
- @NotNull
- public PsiElement[] getElements() {
- return new PsiElement[] {myClass};
- }
-
- public String getProcessedElementsHeader() {
- return HEADER;
- }
-
- public String getCodeReferencesText(int usagesCount, int filesCount) {
- return RefactoringBundle.message("classes.to.push.down.members.to", UsageViewBundle.getReferencesString(usagesCount, filesCount));
- }
-
- @Nullable
- public String getCommentReferencesText(int usagesCount, int filesCount) {
- return null;
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownView.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownView.java
new file mode 100644
index 0000000..5b1848e
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownView.java
@@ -0,0 +1,10 @@
+package com.jetbrains.python.refactoring.classes.pushDown;
+
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public interface PyPushDownView extends MembersBasedView<MembersViewInitializationInfo> {
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownViewSwingImpl.java b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownViewSwingImpl.java
new file mode 100644
index 0000000..9fd0cb5
--- /dev/null
+++ b/python/src/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownViewSwingImpl.java
@@ -0,0 +1,26 @@
+package com.jetbrains.python.refactoring.classes.pushDown;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.refactoring.RefactoringBundle;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedViewSwingImpl;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+
+/**
+ * @author Ilya.Kazakevich
+ */
+public class PyPushDownViewSwingImpl extends MembersBasedViewSwingImpl<PyPushDownPresenter, MembersViewInitializationInfo>
+ implements PyPushDownView {
+ public PyPushDownViewSwingImpl(
+ @NotNull final PyClass classUnderRefactoring,
+ @NotNull final Project project,
+ @NotNull final PyPushDownPresenter presenter) {
+ super(project, presenter, RefactoringBundle.message("push.members.from.0.down.label", classUnderRefactoring.getName()), false);
+
+ myCenterPanel.add(myPyMemberSelectionPanel, BorderLayout.CENTER);
+ setTitle(PyPushDownHandler.REFACTORING_NAME);
+ }
+}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionPanel.java b/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionPanel.java
index cc4357e..6b380b4 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionPanel.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionPanel.java
@@ -15,39 +15,95 @@
*/
package com.jetbrains.python.refactoring.classes.ui;
+import com.google.common.base.Preconditions;
import com.intellij.refactoring.classMembers.MemberInfoModel;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.ui.ScrollPaneFactory;
import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import javax.swing.border.Border;
import java.awt.*;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
/**
+ * Panel that handles table with list of class members with selection checkboxes.
+ *
* @author Dennis.Ushakov
*/
public class PyMemberSelectionPanel extends JPanel {
+ private static final List<PyMemberInfo<PyElement>> EMPTY_MEMBER_INFO = Collections.emptyList();
private final PyMemberSelectionTable myTable;
+ private boolean myInitialized;
- public PyMemberSelectionPanel(String title, List<PyMemberInfo> memberInfo, final MemberInfoModel<PyElement, PyMemberInfo> model) {
- super();
+
+ /**
+ * Creates empty panel to be filled later by {@link #init(com.intellij.refactoring.classMembers.MemberInfoModel, java.util.Collection)}
+ *
+ * @param title
+ */
+ public PyMemberSelectionPanel(@NotNull String title, boolean supportAbstract) {
+ this(title, EMPTY_MEMBER_INFO, null, supportAbstract);
+ }
+
+ /**
+ * Creates panel and fills its table (see {@link #init(com.intellij.refactoring.classMembers.MemberInfoModel, java.util.Collection)} ) with members info
+ *
+ * @param title Title for panel
+ * @param memberInfo list of members
+ * @param model model
+ */
+ public PyMemberSelectionPanel(
+ String title,
+ List<PyMemberInfo<PyElement>> memberInfo,
+ final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> model,
+ final boolean supportAbstract) {
Border titledBorder = IdeBorderFactory.createTitledBorder(title, false);
Border emptyBorder = BorderFactory.createEmptyBorder(0, 5, 5, 5);
Border border = BorderFactory.createCompoundBorder(titledBorder, emptyBorder);
setBorder(border);
setLayout(new BorderLayout());
- myTable = new PyMemberSelectionTable(memberInfo, model);
+ myTable = new PyMemberSelectionTable(memberInfo, model, supportAbstract);
JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(myTable);
add(scrollPane, BorderLayout.CENTER);
}
- public PyMemberSelectionTable getTable() {
- return myTable;
+
+ /**
+ * Inits panel.
+ *
+ * @param memberInfoModel model to display memebers in table
+ * @param members members to display
+ */
+ public void init(@NotNull final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> memberInfoModel,
+ @NotNull final Collection<PyMemberInfo<PyElement>> members) {
+ Preconditions.checkState(!myInitialized, "Already myInitialized");
+ myTable.setMemberInfos(members);
+ myTable.setMemberInfoModel(memberInfoModel);
+ myTable.addMemberInfoChangeListener(memberInfoModel);
+ myInitialized = true;
+ }
+
+ /**
+ * @return list of members, selected by user
+ */
+ @NotNull
+ public Collection<PyMemberInfo<PyElement>> getSelectedMemberInfos() {
+ Preconditions.checkState(myInitialized, "Call #init first");
+ return myTable.getSelectedMemberInfos();
+ }
+
+ /**
+ * Redraws table. Call it when some new data is available.
+ */
+ public void redraw() {
+ myTable.fireExternalDataChange();
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionTable.java b/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionTable.java
index 11d3e42..229b2b5 100644
--- a/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionTable.java
+++ b/python/src/com/jetbrains/python/refactoring/classes/ui/PyMemberSelectionTable.java
@@ -17,12 +17,15 @@
import com.intellij.icons.AllIcons;
import com.intellij.psi.PsiElement;
+import com.intellij.refactoring.RefactoringBundle;
import com.intellij.refactoring.classMembers.MemberInfoModel;
import com.intellij.refactoring.ui.AbstractMemberSelectionTable;
import com.intellij.ui.RowIcon;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyFunction;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
@@ -30,23 +33,37 @@
/**
* @author Dennis.Ushakov
*/
-public class PyMemberSelectionTable extends AbstractMemberSelectionTable<PyElement, PyMemberInfo> {
- public PyMemberSelectionTable(final List<PyMemberInfo> memberInfos,
- final MemberInfoModel<PyElement, PyMemberInfo> model) {
- super(memberInfos, model, null);
+public class PyMemberSelectionTable extends AbstractMemberSelectionTable<PyElement, PyMemberInfo<PyElement>> {
+
+ private static final String ABSTRACT_TITLE = RefactoringBundle.message("make.abstract");
+ private final boolean mySupportAbstract;
+
+ public PyMemberSelectionTable(
+ @NotNull final List<PyMemberInfo<PyElement>> memberInfos,
+ @Nullable final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> model,
+ final boolean supportAbstract) {
+ super(memberInfos, model, (supportAbstract ? ABSTRACT_TITLE : null));
+ mySupportAbstract = supportAbstract;
}
- protected Object getAbstractColumnValue(PyMemberInfo memberInfo) {
- return null;
+ @Nullable
+ @Override
+ protected Object getAbstractColumnValue(final PyMemberInfo<PyElement> memberInfo) {
+ //TODO: Too many logic, move to presenters
+ return (mySupportAbstract && memberInfo.isChecked() && myMemberInfoModel.isAbstractEnabled(memberInfo)) ? memberInfo.isToAbstract() : null;
}
- protected boolean isAbstractColumnEditable(int rowIndex) {
- return false;
+ @Override
+ protected boolean isAbstractColumnEditable(final int rowIndex) {
+ return mySupportAbstract && myMemberInfoModel.isAbstractEnabled(myMemberInfos.get(rowIndex));
}
- protected void setVisibilityIcon(PyMemberInfo memberInfo, RowIcon icon) {}
+ @Override
+ protected void setVisibilityIcon(PyMemberInfo<PyElement> memberInfo, RowIcon icon) {
+ }
- protected Icon getOverrideIcon(PyMemberInfo memberInfo) {
+ @Override
+ protected Icon getOverrideIcon(PyMemberInfo<PyElement> memberInfo) {
final PsiElement member = memberInfo.getMember();
Icon overrideIcon = EMPTY_OVERRIDE_ICON;
if (member instanceof PyFunction && memberInfo.getOverrides() != null && memberInfo.getOverrides()) {
diff --git a/python/src/com/jetbrains/python/refactoring/classes/ui/UpDirectedMembersMovingDialog.java b/python/src/com/jetbrains/python/refactoring/classes/ui/UpDirectedMembersMovingDialog.java
deleted file mode 100644
index 7ac313d..0000000
--- a/python/src/com/jetbrains/python/refactoring/classes/ui/UpDirectedMembersMovingDialog.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes.ui;
-
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.refactoring.classMembers.DependencyMemberInfoModel;
-import com.intellij.refactoring.classMembers.MemberInfoChange;
-import com.intellij.refactoring.util.CommonRefactoringUtil;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.psi.PyUtil;
-import com.jetbrains.python.refactoring.classes.PyMemberInfo;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author Dennis.Ushakov
- */
-public abstract class UpDirectedMembersMovingDialog extends DialogWrapper {
- protected DependencyMemberInfoModel<PyElement, PyMemberInfo> myMemberInfoModel;
- protected PyMemberSelectionPanel myMemberSelectionPanel;
- protected PyClass myClass;
- protected List<PyMemberInfo> myMemberInfos;
-
- public UpDirectedMembersMovingDialog(Project project, final PyClass clazz) {
- super(project, true);
- myClass = clazz;
- }
-
- protected JComponent createCenterPanel() {
- JPanel panel = new JPanel(new BorderLayout());
- myMemberSelectionPanel = new PyMemberSelectionPanel(getMembersBorderTitle(), myMemberInfos, null);
- myMemberInfoModel = createMemberInfoModel();
- myMemberInfoModel.memberInfoChanged(new MemberInfoChange<PyElement, PyMemberInfo>(myMemberInfos));
- myMemberSelectionPanel.getTable().setMemberInfoModel(myMemberInfoModel);
- myMemberSelectionPanel.getTable().addMemberInfoChangeListener(myMemberInfoModel);
- panel.add(myMemberSelectionPanel, BorderLayout.CENTER);
-
- return panel;
- }
-
- protected abstract String getMembersBorderTitle();
-
- protected abstract DependencyMemberInfoModel<PyElement, PyMemberInfo> createMemberInfoModel();
-
- protected void doOKAction() {
- if(!checkConflicts()) return;
- close(OK_EXIT_CODE);
- }
-
- public boolean isOKActionEnabled() {
- return getSelectedMemberInfos().size() > 0 && super.isOKActionEnabled();
- }
-
- public abstract boolean checkConflicts();
-
- protected static boolean checkWritable(final PyClass superClass, final Collection<PyMemberInfo> infos) {
- if (infos.size() ==0) {
- return true;
- }
- final PyElement element = infos.iterator().next().getMember();
- final Project project = element.getProject();
- if (!CommonRefactoringUtil.checkReadOnlyStatus(project, superClass)) return false;
- final PyClass container = PyUtil.getContainingClassOrSelf(element);
- if (container == null || !CommonRefactoringUtil.checkReadOnlyStatus(project, container)) return false;
- for (PyMemberInfo info : infos) {
- final PyElement member = info.getMember();
- if (!CommonRefactoringUtil.checkReadOnlyStatus(project, member)) return false;
- }
- return true;
- }
-
- public Collection<PyMemberInfo> getSelectedMemberInfos() {
- ArrayList<PyMemberInfo> list = new ArrayList<PyMemberInfo>(myMemberInfos.size());
- for (PyMemberInfo info : myMemberInfos) {
- if (info.isChecked() && myMemberInfoModel.isMemberEnabled(info)) {
- list.add(info);
- }
- }
- return list;
- }
-}
diff --git a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
index aeb1efa..d16712d 100644
--- a/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
+++ b/python/src/com/jetbrains/python/refactoring/extractmethod/PyExtractMethodUtil.java
@@ -59,6 +59,7 @@
import java.util.*;
/**
+ * * TODO: Merge with {@link com.jetbrains.python.refactoring.classes.PyClassRefactoringUtil#createMethod(String, com.jetbrains.python.psi.PyClass, com.jetbrains.python.psi.PyFunction.Modifier, java.util.Collection, String...)}
* @author oleg
*/
public class PyExtractMethodUtil {
@@ -564,7 +565,7 @@
throw new CommonRefactoringUtil.RefactoringErrorHintException(error);
}
if (Messages.showOkCancelDialog(error + ". " + RefactoringBundle.message("do.you.wish.to.continue"),
- RefactoringBundle.message("warning.title"), Messages.getWarningIcon()) != 0){
+ RefactoringBundle.message("warning.title"), Messages.getWarningIcon()) != Messages.OK){
throw new CommonRefactoringUtil.RefactoringErrorHintException(error);
}
}
diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java
index 21c2604..e5f5c26 100644
--- a/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java
+++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveClassOrFunctionProcessor.java
@@ -140,7 +140,7 @@
// TODO: Remove extra empty lines after the removed element
element.delete();
if (file != null) {
- optimizeImports(file);
+ PyClassRefactoringUtil.optimizeImports(file);
}
}
@@ -209,15 +209,12 @@
if (resolvesToLocalStarImport(usage)) {
PyClassRefactoringUtil.insertImport(usage, newElement);
if (usageFile != null) {
- optimizeImports(usageFile);
+ PyClassRefactoringUtil.optimizeImports(usageFile);
}
}
}
}
- private static void optimizeImports(@NotNull PsiFile file) {
- new PyImportOptimizer().processFile(file).run();
- }
private static boolean resolvesToLocalStarImport(@NotNull PsiElement element) {
final PsiReference ref = element.getReference();
diff --git a/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java b/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java
index ce91ea6..36e0a00 100644
--- a/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java
+++ b/python/src/com/jetbrains/python/refactoring/rename/RenamePyFunctionProcessor.java
@@ -79,10 +79,10 @@
String message = "Method " + function.getName() + " of class " + containingClass.getQualifiedName() + "\noverrides method of class "
+ deepestSuperMethod.getContainingClass().getQualifiedName() + ".\nDo you want to rename the base method?";
int rc = Messages.showYesNoCancelDialog(element.getProject(), message, "Rename", Messages.getQuestionIcon());
- if (rc == 0) {
+ if (rc == Messages.YES) {
return deepestSuperMethod;
}
- if (rc == 1) {
+ if (rc == Messages.NO) {
return function;
}
return null;
@@ -98,8 +98,8 @@
property.getName(), function.getName());
final int rc = Messages.showYesNoCancelDialog(element.getProject(), message, "Rename", Messages.getQuestionIcon());
switch (rc) {
- case 0: return site;
- case 1: return function;
+ case Messages.YES: return site;
+ case Messages.NO: return function;
default: return null;
}
}
diff --git a/python/src/com/jetbrains/python/run/PythonRunner.java b/python/src/com/jetbrains/python/run/PythonRunner.java
index c2a8937..b95da7c 100644
--- a/python/src/com/jetbrains/python/run/PythonRunner.java
+++ b/python/src/com/jetbrains/python/run/PythonRunner.java
@@ -44,10 +44,10 @@
@Override
protected RunContentDescriptor doExecute(
- Project project,
- RunProfileState state,
+ @NotNull Project project,
+ @NotNull RunProfileState state,
RunContentDescriptor contentToReuse,
- ExecutionEnvironment env
+ @NotNull ExecutionEnvironment env
) throws ExecutionException {
FileDocumentManager.getInstance().saveAllDocuments();
diff --git a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.form b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.form
index bd84b37..ea6172e 100644
--- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.form
+++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.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.sdk.CreateVirtualEnvDialog">
- <grid id="cbd77" binding="myMainPanel" layout-manager="GridLayoutManager" row-count="7" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <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"/>
@@ -16,7 +16,7 @@
</component>
<vspacer id="b277d">
<constraints>
- <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
+ <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">
@@ -60,30 +60,22 @@
</component>
<component id="41e08" class="com.intellij.ui.components.JBCheckBox" binding="myMakeAvailableToAllProjectsCheckbox">
<constraints>
- <grid row="5" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
+ <grid row="4" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<selected value="false"/>
<text value="Make available to &all projects"/>
</properties>
</component>
- <component id="9835d" class="com.intellij.ui.components.JBCheckBox" binding="mySitePackagesCheckBox">
+ <component id="d10a9" class="com.intellij.ui.components.JBCheckBox" binding="mySitePackagesCheckBox">
<constraints>
- <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ <grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="0" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
+ <selected value="false"/>
<text value="&Inherit global site-packages"/>
</properties>
</component>
- <component id="fd5f3" class="com.intellij.ui.components.JBCheckBox" binding="mySetAsProjectInterpreterCheckbox" default-binding="true">
- <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="true"/>
- <text value="&Set as project interpreter for this project"/>
- </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 e86fca4..165d737 100644
--- a/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java
+++ b/python/src/com/jetbrains/python/sdk/CreateVirtualEnvDialog.java
@@ -15,6 +15,8 @@
*/
package com.jetbrains.python.sdk;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
import com.intellij.facet.ui.FacetEditorValidator;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.openapi.application.Application;
@@ -67,18 +69,16 @@
private JTextField myName;
private JBCheckBox mySitePackagesCheckBox;
private JBCheckBox myMakeAvailableToAllProjectsCheckbox;
- private JBCheckBox mySetAsProjectInterpreterCheckbox;
@Nullable private Project myProject;
private String myInitialPath;
public interface VirtualEnvCallback {
- void virtualEnvCreated(Sdk sdk, boolean associateWithProject, boolean setAsProjectInterpreter);
+ void virtualEnvCreated(Sdk sdk, boolean associateWithProject);
}
- private static void setupVirtualEnvSdk(List<Sdk> allSdks,
+ private void setupVirtualEnvSdk(List<Sdk> allSdks,
final String path,
boolean associateWithProject,
- final boolean makeActive,
VirtualEnvCallback callback) {
final VirtualFile sdkHome =
ApplicationManager.getApplication().runWriteAction(new Computable<VirtualFile>() {
@@ -92,46 +92,45 @@
SdkConfigurationUtil.createUniqueSdkName(PythonSdkType.getInstance(), sdkHome.getPath(), allSdks);
final ProjectJdkImpl sdk = new ProjectJdkImpl(name, PythonSdkType.getInstance());
sdk.setHomePath(sdkHome.getPath());
- callback.virtualEnvCreated(sdk, associateWithProject, makeActive);
+ callback.virtualEnvCreated(sdk, associateWithProject);
+ PythonSdkType.setupSdkPaths(sdk, myProject, null);
}
}
public CreateVirtualEnvDialog(Project project,
- boolean isNewProject,
final List<Sdk> allSdks,
@Nullable Sdk suggestedBaseSdk) {
super(project);
- setupDialog(project, isNewProject, allSdks, suggestedBaseSdk);
+ setupDialog(project, allSdks, suggestedBaseSdk);
}
public CreateVirtualEnvDialog(Component owner,
- boolean isNewProject,
final List<Sdk> allSdks,
@Nullable Sdk suggestedBaseSdk) {
super(owner);
- setupDialog(null, isNewProject, allSdks, suggestedBaseSdk);
+ setupDialog(null, allSdks, suggestedBaseSdk);
}
- private void setupDialog(Project project, boolean isNewProject, List<Sdk> allSdks, @Nullable Sdk suggestedBaseSdk) {
+ private void setupDialog(Project project, List<Sdk> allSdks, @Nullable Sdk suggestedBaseSdk) {
myProject = project;
init();
setTitle("Create Virtual Environment");
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) || RemoteSdkDataHolder.isRemoteSdk(s.getHomePath());
+ }
+ });
List<Sdk> sortedSdks = new ArrayList<Sdk>(allSdks);
Collections.sort(sortedSdks, new PreferredSdkComparator());
suggestedBaseSdk = sortedSdks.get(0);
}
updateSdkList(allSdks, suggestedBaseSdk);
- myMakeAvailableToAllProjectsCheckbox.setBorder(BorderFactory.createEmptyBorder(8, 0, 0, 0));
if (project == null || project.isDefault() || !PlatformUtils.isPyCharm()) {
myMakeAvailableToAllProjectsCheckbox.setSelected(true);
myMakeAvailableToAllProjectsCheckbox.setVisible(false);
- mySetAsProjectInterpreterCheckbox.setSelected(false);
- mySetAsProjectInterpreterCheckbox.setVisible(false);
- }
- else if (isNewProject) {
- mySetAsProjectInterpreterCheckbox.setText("Set as project interpreter for the project being created");
}
setOKActionEnabled(false);
@@ -238,17 +237,7 @@
private void updateSdkList(final List<Sdk> allSdks, @Nullable Sdk initialSelection) {
mySdkCombo.setRenderer(new PySdkListCellRenderer());
- List<Sdk> baseSdks = new ArrayList<Sdk>();
- for (Sdk s : allSdks) {
- if (!PythonSdkType.isInvalid(s) && !PythonSdkType.isVirtualEnv(s) && !RemoteSdkDataHolder.isRemoteSdk(s.getHomePath())) {
- baseSdks.add(s);
- }
- else if (s.equals(initialSelection)){
- initialSelection = null;
- }
- }
-
- mySdkCombo.setModel(new CollectionComboBoxModel(baseSdks, initialSelection));
+ mySdkCombo.setModel(new CollectionComboBoxModel(allSdks, initialSelection));
}
@Override
@@ -288,10 +277,6 @@
return !myMakeAvailableToAllProjectsCheckbox.isSelected();
}
- public boolean setAsProjectInterpreter() {
- return mySetAsProjectInterpreterCheckbox.isSelected();
- }
-
@Override
public JComponent getPreferredFocusedComponent() {
return myName;
@@ -326,7 +311,7 @@
application.invokeLater(new Runnable() {
@Override
public void run() {
- setupVirtualEnvSdk(allSdks, myPath, associateWithProject(), setAsProjectInterpreter(), callback);
+ setupVirtualEnvSdk(allSdks, myPath, associateWithProject(), callback);
}
}, ModalityState.any());
}
diff --git a/python/src/com/jetbrains/python/sdk/InterpreterPathChooser.java b/python/src/com/jetbrains/python/sdk/InterpreterPathChooser.java
deleted file mode 100644
index ab57e35..0000000
--- a/python/src/com/jetbrains/python/sdk/InterpreterPathChooser.java
+++ /dev/null
@@ -1,200 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.sdk;
-
-import com.google.common.collect.Lists;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.application.ModalityState;
-import com.intellij.openapi.options.ShowSettingsUtil;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.projectRoots.Sdk;
-import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.ui.popup.ListPopup;
-import com.intellij.openapi.ui.popup.ListPopupStep;
-import com.intellij.openapi.ui.popup.PopupStep;
-import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.ui.awt.RelativePoint;
-import com.intellij.util.NullableConsumer;
-import com.intellij.util.SystemProperties;
-import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
-import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.awt.*;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-/**
-* @author yole
-*/
-public class InterpreterPathChooser extends BaseListPopupStep<String> {
- private final Project myProject;
- private final Component myOwnerComponent;
- private final Sdk[] myExistingSdks;
- private final NullableConsumer<Sdk> myCallback;
-
- private static final String LOCAL = "Local...";
- private static final String REMOTE = "Remote...";
- private static final String VIRTUALENV = "Create VirtualEnv...";
-
- public static void show(final Project project,
- final Sdk[] existingSdks,
- final RelativePoint popupPoint,
- final boolean showVirtualEnv,
- final NullableConsumer<Sdk> callback) {
- ListPopupStep sdkHomesStep = new InterpreterPathChooser(project, popupPoint.getComponent(), existingSdks, showVirtualEnv, callback);
- final ListPopup popup = JBPopupFactory.getInstance().createListPopup(sdkHomesStep);
- popup.show(popupPoint);
- }
-
- public InterpreterPathChooser(Project project,
- Component ownerComponent,
- Sdk[] existingSdks,
- boolean showVirtualEnv,
- NullableConsumer<Sdk> callback) {
- super("Select Interpreter Path", getSuggestedPythonSdkPaths(existingSdks, showVirtualEnv));
- myProject = project;
- myOwnerComponent = ownerComponent;
- myExistingSdks = existingSdks;
- myCallback = callback;
- }
-
- private static List<String> getSuggestedPythonSdkPaths(Sdk[] existingSdks, boolean showVirtualEnv) {
- List<String> paths = new ArrayList<String>();
- Collection<String> sdkHomes = PythonSdkType.getInstance().suggestHomePaths();
- for (String sdkHome : SdkConfigurationUtil.filterExistingPaths(PythonSdkType.getInstance(), sdkHomes, existingSdks)) {
- paths.add(FileUtil.getLocationRelativeToUserHome(sdkHome));
- }
- paths.add(LOCAL);
- if (PythonRemoteInterpreterManager.getInstance() != null) {
- paths.add(REMOTE);
- }
- if (showVirtualEnv) {
- paths.add(VIRTUALENV);
- }
- return paths;
- }
-
- @Nullable
- @Override
- public Icon getIconFor(String aValue) {
- if (LOCAL.equals(aValue) || REMOTE.equals(aValue) || VIRTUALENV.equals(aValue)) return null;
- String filePath = aValue;
- if (StringUtil.startsWithChar(filePath, '~')) {
- String home = SystemProperties.getUserHome();
- filePath = home + filePath.substring(1);
- }
- final PythonSdkFlavor flavor = PythonSdkFlavor.getPlatformIndependentFlavor(filePath);
- return flavor != null ? flavor.getIcon() : PythonSdkType.getInstance().getIcon();
- }
-
- @NotNull
- @Override
- public String getTextFor(String value) {
- return FileUtil.toSystemDependentName(value);
- }
-
- private void sdkSelected(final String selectedValue) {
- if (LOCAL.equals(selectedValue)) {
- createLocalSdk();
- }
- else if (REMOTE.equals(selectedValue)) {
- createRemoteSdk();
- }
- else if (VIRTUALENV.equals(selectedValue)) {
- createVirtualEnvSdk();
- }
- else {
- createSdkFromPath(selectedValue);
- }
- }
-
- private void createLocalSdk() {
- ApplicationManager.getApplication().invokeLater(new Runnable() {
- @Override
- public void run() {
- SdkConfigurationUtil.createSdk(myProject, myExistingSdks, myCallback, PythonSdkType.getInstance());
- }
- }, ModalityState.any());
- }
-
- private void createRemoteSdk() {
- PythonRemoteInterpreterManager remoteInterpreterManager = PythonRemoteInterpreterManager.getInstance();
- if (remoteInterpreterManager != null) {
- remoteInterpreterManager.addRemoteSdk(myProject, myOwnerComponent, Lists.newArrayList(myExistingSdks), myCallback);
- }
- else {
- Messages.showErrorDialog("The Remote Hosts Access plugin is missing. Please enable the plugin in " +
- ShowSettingsUtil.getSettingsMenuName() +
- " | Plugins.", "Add Remote Interpreter");
- }
- }
-
- private void createSdkFromPath(String selectedPath) {
- String filePath = selectedPath;
- if (StringUtil.startsWithChar(filePath, '~')) {
- String home = SystemProperties.getUserHome();
- filePath = home + filePath.substring(1);
- }
- Sdk sdk = SdkConfigurationUtil.setupSdk(myExistingSdks,
- LocalFileSystem.getInstance().findFileByPath(filePath),
- PythonSdkType.getInstance(), false, null, null);
- myCallback.consume(sdk);
- }
-
- private void createVirtualEnvSdk() {
- final CreateVirtualEnvDialog dialog;
- final List<Sdk> allSdks = Arrays.asList(myExistingSdks);
- if (myProject != null) {
- dialog = new CreateVirtualEnvDialog(myProject, false, allSdks, null);
- }
- else {
- dialog = new CreateVirtualEnvDialog(myOwnerComponent, false, allSdks, null);
- }
- dialog.show();
- if (dialog.isOK()) {
- dialog.createVirtualEnv(allSdks, new CreateVirtualEnvDialog.VirtualEnvCallback() {
- @Override
- public void virtualEnvCreated(Sdk sdk, boolean associateWithProject, boolean setAsProjectInterpreter) {
- myCallback.consume(sdk);
- }
- });
- }
- }
-
- @Override
- public boolean canBeHidden(String value) {
- return true;
- }
-
- @Override
- public PopupStep onChosen(final String selectedValue, boolean finalChoice) {
- return doFinalStep(new Runnable() {
- public void run() {
- sdkSelected(selectedValue);
- }
- });
- }
-}
diff --git a/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java b/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java
index 50bc771..ff1cea9 100644
--- a/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java
+++ b/python/src/com/jetbrains/python/sdk/PreferredSdkComparator.java
@@ -37,6 +37,12 @@
if (remote1Weight != remote2Weight) {
return remote2Weight - remote1Weight;
}
+ int detectedWeight1 = o1 instanceof PyDetectedSdk ? 0 : 1;
+ int detectedWeight2 = o2 instanceof PyDetectedSdk ? 0 : 1;
+ if (detectedWeight1 != detectedWeight2) {
+ return detectedWeight2 - detectedWeight1;
+ }
+
int venv1weight = PythonSdkType.isVirtualEnv(o1) ? 0 : 1;
int venv2weight = PythonSdkType.isVirtualEnv(o2) ? 0 : 1;
if (venv1weight != venv2weight) {
@@ -47,6 +53,7 @@
if (flavor1weight != flavor2weight) {
return flavor2weight - flavor1weight;
}
+
return -Comparing.compare(o1.getVersionString(), o2.getVersionString());
}
}
diff --git a/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
new file mode 100644
index 0000000..098462e
--- /dev/null
+++ b/python/src/com/jetbrains/python/sdk/PyDetectedSdk.java
@@ -0,0 +1,11 @@
+package com.jetbrains.python.sdk;
+
+import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
+
+public class PyDetectedSdk extends ProjectJdkImpl {
+ public PyDetectedSdk(String name) {
+ super(name, PythonSdkType.getInstance());
+ setHomePath(name);
+ }
+
+}
diff --git a/python/src/com/jetbrains/python/sdk/PySdkListCellRenderer.java b/python/src/com/jetbrains/python/sdk/PySdkListCellRenderer.java
index 9065d37..9886224 100644
--- a/python/src/com/jetbrains/python/sdk/PySdkListCellRenderer.java
+++ b/python/src/com/jetbrains/python/sdk/PySdkListCellRenderer.java
@@ -19,6 +19,7 @@
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.projectRoots.SdkType;
+import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.ListCellRendererWrapper;
import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
@@ -27,9 +28,10 @@
import javax.swing.*;
import java.util.Map;
-public class PySdkListCellRenderer extends ListCellRendererWrapper<Sdk> {
+public class PySdkListCellRenderer extends ListCellRendererWrapper<Object> {
private final String myNullText;
private final Map<Sdk, SdkModificator> mySdkModifiers;
+ public static final String SEPARATOR = "separator";
public PySdkListCellRenderer() {
myNullText = "";
@@ -42,8 +44,9 @@
}
@Override
- public void customize(JList list, Sdk sdk, int index, boolean selected, boolean hasFocus) {
- if (sdk != null) {
+ public void customize(JList list, Object item, int index, boolean selected, boolean hasFocus) {
+ if (item instanceof Sdk) {
+ Sdk sdk = (Sdk)item;
final PythonSdkFlavor flavor = PythonSdkFlavor.getPlatformIndependentFlavor(sdk.getHomePath());
final Icon icon = flavor != null ? flavor.getIcon() : ((SdkType)sdk.getSdkType()).getIcon();
@@ -54,7 +57,6 @@
else {
name = sdk.getName();
}
-
if (PythonSdkType.isInvalid(sdk)) {
setText("[invalid] " + name);
setIcon(wrapIconWithWarningDecorator(icon));
@@ -63,17 +65,22 @@
setText("[incomplete] " + name);
setIcon(wrapIconWithWarningDecorator(icon));
}
+ else if (sdk instanceof PyDetectedSdk){
+ setText(name);
+ setIcon(IconLoader.getTransparentIcon(icon));
+ }
else {
setText(name);
setIcon(icon);
}
}
- else {
+ else if (SEPARATOR.equals(item))
+ setSeparator();
+ else if (item == null)
setText(myNullText);
- }
}
- private LayeredIcon wrapIconWithWarningDecorator(Icon icon) {
+ private static LayeredIcon wrapIconWithWarningDecorator(Icon icon) {
final LayeredIcon layered = new LayeredIcon(2);
layered.setIcon(icon, 0);
// TODO: Create a separate invalid SDK overlay icon (DSGN-497)
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java
new file mode 100644
index 0000000..8e3f18a
--- /dev/null
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkDetailsStep.java
@@ -0,0 +1,186 @@
+/*
+ * 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.sdk;
+
+import com.google.common.collect.Lists;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.SdkAdditionalData;
+import com.intellij.openapi.projectRoots.impl.ProjectJdkImpl;
+import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.popup.*;
+import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.NullableConsumer;
+import com.jetbrains.python.remote.PythonRemoteInterpreterManager;
+import com.jetbrains.python.sdk.flavors.PythonSdkFlavor;
+import org.jetbrains.annotations.Nullable;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+public class PythonSdkDetailsStep extends BaseListPopupStep<String> {
+ private static DialogWrapper myMore;
+ private final Project myProject;
+ private final Component myOwnerComponent;
+ private final Sdk[] myExistingSdks;
+ private final NullableConsumer<Sdk> myCallback;
+
+ private static final String LOCAL = "Add Local";
+ private static final String REMOTE = "Add Remote";
+ private static final String VIRTUALENV = "Create VirtualEnv";
+ private static final String MORE = "More...";
+
+ public static void show(final Project project,
+ final Sdk[] existingSdks,
+ DialogWrapper component, final RelativePoint popupPoint,
+ final boolean showMore,
+ final NullableConsumer<Sdk> callback) {
+ myMore = component;
+ final ListPopupStep sdkHomesStep = new PythonSdkDetailsStep(project, popupPoint.getComponent(), existingSdks, showMore, callback);
+ final ListPopup popup = JBPopupFactory.getInstance().createListPopup(sdkHomesStep);
+ popup.show(popupPoint);
+ }
+
+ public PythonSdkDetailsStep(Project project,
+ Component ownerComponent,
+ Sdk[] existingSdks,
+ boolean showMore,
+ NullableConsumer<Sdk> callback) {
+ super(null, getAvailableOptions(showMore));
+ myProject = project;
+ myOwnerComponent = ownerComponent;
+ myExistingSdks = existingSdks;
+ myCallback = callback;
+ }
+
+ private static List<String> getAvailableOptions(boolean showMore) {
+ final List<String> options = new ArrayList<String>();
+ options.add(LOCAL);
+ if (PythonRemoteInterpreterManager.getInstance() != null) {
+ options.add(REMOTE);
+ }
+ options.add(VIRTUALENV);
+
+ if (showMore) {
+ options.add(MORE);
+ }
+ return options;
+ }
+
+ @Nullable
+ @Override
+ public ListSeparator getSeparatorAbove(String value) {
+ return MORE.equals(value) ? new ListSeparator() : null;
+ }
+
+ private void optionSelected(final String selectedValue) {
+ if (LOCAL.equals(selectedValue)) {
+ createLocalSdk();
+ }
+ else if (REMOTE.equals(selectedValue)) {
+ createRemoteSdk();
+ }
+ else if (VIRTUALENV.equals(selectedValue)) {
+ createVirtualEnvSdk();
+ }
+ else {
+ myMore.show();
+ }
+ }
+
+ private void createLocalSdk() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ SdkConfigurationUtil.createSdk(myProject, myExistingSdks, myCallback, false, PythonSdkType.getInstance());
+ }
+ }, ModalityState.any());
+ }
+
+ private void createRemoteSdk() {
+ PythonRemoteInterpreterManager remoteInterpreterManager = PythonRemoteInterpreterManager.getInstance();
+ if (remoteInterpreterManager != null) {
+ remoteInterpreterManager.addRemoteSdk(myProject, myOwnerComponent, Lists.newArrayList(myExistingSdks), myCallback);
+ }
+ else {
+ Messages.showErrorDialog("The Remote Hosts Access plugin is missing. Please enable the plugin in " +
+ ShowSettingsUtil.getSettingsMenuName() +
+ " | Plugins.", "Add Remote Interpreter");
+ }
+ }
+
+ private void createVirtualEnvSdk() {
+ CreateVirtualEnvDialog.VirtualEnvCallback callback = new CreateVirtualEnvDialog.VirtualEnvCallback() {
+ @Override
+ public void virtualEnvCreated(Sdk sdk, boolean associateWithProject) {
+ PythonSdkType.setupSdkPaths(sdk, myProject, null);
+ if (associateWithProject) {
+ SdkAdditionalData additionalData = sdk.getSdkAdditionalData();
+ if (additionalData == null) {
+ additionalData = new PythonSdkAdditionalData(PythonSdkFlavor.getFlavor(sdk.getHomePath()));
+ ((ProjectJdkImpl)sdk).setSdkAdditionalData(additionalData);
+ }
+ ((PythonSdkAdditionalData)additionalData).associateWithProject(myProject);
+ }
+ myCallback.consume(sdk);
+ }
+ };
+
+ final CreateVirtualEnvDialog dialog;
+ final List<Sdk> allSdks = Lists.newArrayList(myExistingSdks);
+
+ final List<PythonSdkFlavor> flavors = PythonSdkFlavor.getApplicableFlavors(false);
+ for (PythonSdkFlavor flavor : flavors) {
+ final Collection<String> strings = flavor.suggestHomePaths();
+ for (String string : strings) {
+ allSdks.add(new PyDetectedSdk(string));
+ }
+ }
+
+ if (myProject != null) {
+ dialog = new CreateVirtualEnvDialog(myProject, allSdks, null);
+ }
+ else {
+ dialog = new CreateVirtualEnvDialog(myOwnerComponent, allSdks, null);
+ }
+ dialog.show();
+ if (dialog.isOK()) {
+ dialog.createVirtualEnv(allSdks, callback);
+ }
+ }
+
+ @Override
+ public boolean canBeHidden(String value) {
+ return true;
+ }
+
+ @Override
+ public PopupStep onChosen(final String selectedValue, boolean finalChoice) {
+ return doFinalStep(new Runnable() {
+ public void run() {
+ optionSelected(selectedValue);
+ }
+ });
+ }
+}
diff --git a/python/src/com/jetbrains/python/sdk/PythonSdkType.java b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
index 92654e9..3ad05e0 100644
--- a/python/src/com/jetbrains/python/sdk/PythonSdkType.java
+++ b/python/src/com/jetbrains/python/sdk/PythonSdkType.java
@@ -45,8 +45,12 @@
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.CharFilter;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.*;
+import com.intellij.openapi.vfs.JarFileSystem;
+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.reference.SoftReference;
import com.intellij.remotesdk.RemoteSdkData;
import com.intellij.remotesdk.RemoteSdkDataHolder;
import com.intellij.ui.awt.RelativePoint;
@@ -76,6 +80,7 @@
import java.awt.*;
import java.io.File;
import java.io.FilenameFilter;
+import java.io.IOException;
import java.lang.ref.WeakReference;
import java.util.*;
import java.util.List;
@@ -143,6 +148,10 @@
@NonNls
@Nullable
public String suggestHomePath() {
+ final String pythonFromPath = findPythonInPath();
+ if (pythonFromPath != null) {
+ return pythonFromPath;
+ }
for (PythonSdkFlavor flavor : PythonSdkFlavor.getApplicableFlavors()) {
TreeSet<String> candidates = createVersionSet();
candidates.addAll(flavor.suggestHomePaths());
@@ -155,6 +164,23 @@
return null;
}
+ @Nullable
+ private static String findPythonInPath() {
+ final String defaultCommand = SystemInfo.isWindows ? "python.exe" : "python";
+ final String path = System.getenv("PATH");
+ for (String root : path.split(File.pathSeparator)) {
+ final File file = new File(root, defaultCommand);
+ if (file.exists()) {
+ try {
+ return file.getCanonicalPath();
+ }
+ catch (IOException ignored) {
+ }
+ }
+ }
+ return null;
+ }
+
@Override
public Collection<String> suggestHomePaths() {
List<String> candidates = new ArrayList<String>();
@@ -254,15 +280,16 @@
public void showCustomCreateUI(SdkModel sdkModel, final JComponent parentComponent, final Consumer<Sdk> sdkCreatedCallback) {
Project project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(parentComponent));
- InterpreterPathChooser.show(project, sdkModel.getSdks(), RelativePoint.getCenterOf(parentComponent), true, new NullableConsumer<Sdk>() {
- @Override
- public void consume(@Nullable Sdk sdk) {
- if (sdk != null) {
- sdk.putUserData(SDK_CREATOR_COMPONENT_KEY, new WeakReference<Component>(parentComponent));
- sdkCreatedCallback.consume(sdk);
+ PythonSdkDetailsStep
+ .show(project, sdkModel.getSdks(), null, RelativePoint.getCenterOf(parentComponent), true, new NullableConsumer<Sdk>() {
+ @Override
+ public void consume(@Nullable Sdk sdk) {
+ if (sdk != null) {
+ sdk.putUserData(SDK_CREATOR_COMPONENT_KEY, new WeakReference<Component>(parentComponent));
+ sdkCreatedCallback.consume(sdk);
+ }
}
- }
- });
+ });
}
public static boolean isVirtualEnv(Sdk sdk) {
@@ -460,11 +487,8 @@
public void setupSdkPaths(@NotNull final Sdk sdk) {
final Project project;
- Component ownerComponent = null;
final WeakReference<Component> ownerComponentRef = sdk.getUserData(SDK_CREATOR_COMPONENT_KEY);
- if (ownerComponentRef != null) {
- ownerComponent = ownerComponentRef.get();
- }
+ Component ownerComponent = SoftReference.dereference(ownerComponentRef);
if (ownerComponent != null) {
project = CommonDataKeys.PROJECT.getData(DataManager.getInstance().getDataContext(ownerComponent));
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java
index 780effe..5d241b6 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/MacPythonSdkFlavor.java
@@ -16,6 +16,7 @@
package com.jetbrains.python.sdk.flavors;
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;
@@ -57,7 +58,7 @@
if (binDir != null && binDir.isDirectory()) {
for (String name : POSSIBLE_BINARY_NAMES) {
final VirtualFile child = binDir.findChild(name);
- if (child != null) {
+ if (child != null && !child.is(VFileProperty.SYMLINK)) {
candidates.add(child.getPath());
break;
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java
index 60fa802..07c8e1c 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/PythonSdkFlavor.java
@@ -72,6 +72,10 @@
}
public static List<PythonSdkFlavor> getApplicableFlavors() {
+ return getApplicableFlavors(true);
+ }
+
+ public static List<PythonSdkFlavor> getApplicableFlavors(boolean addPlatformIndependent) {
List<PythonSdkFlavor> result = new ArrayList<PythonSdkFlavor>();
if (SystemInfo.isWindows) {
@@ -84,7 +88,8 @@
result.add(UnixPythonSdkFlavor.INSTANCE);
}
- result.addAll(getPlatformIndependentFlavors());
+ if (addPlatformIndependent)
+ result.addAll(getPlatformIndependentFlavors());
return result;
}
diff --git a/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java
index c28587c..2440661 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/UnixPythonSdkFlavor.java
@@ -16,6 +16,7 @@
package com.jetbrains.python.sdk.flavors;
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;
@@ -47,14 +48,15 @@
if (rootDir instanceof NewVirtualFile) {
((NewVirtualFile)rootDir).markDirty();
}
- rootDir.refresh(false, false);
+ rootDir.refresh(true, false);
VirtualFile[] suspects = rootDir.getChildren();
for (VirtualFile child : suspects) {
if (!child.isDirectory()) {
final String childName = child.getName();
for (String name : NAMES) {
if (childName.startsWith(name)) {
- if (!childName.endsWith("-config") && !childName.startsWith("pythonw")) {
+ if (!childName.endsWith("-config") && !childName.startsWith("pythonw") &&
+ !childName.endsWith("m") && !child.is(VFileProperty.SYMLINK)) {
candidates.add(child.getPath());
}
break;
diff --git a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java
index 5bdecd7..b9de2e2 100644
--- a/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java
+++ b/python/src/com/jetbrains/python/sdk/flavors/VirtualEnvSdkFlavor.java
@@ -83,7 +83,7 @@
public static Collection<String> findInDirectory(VirtualFile rootDir) {
List<String> candidates = new ArrayList<String>();
if (rootDir != null) {
- rootDir.refresh(false, false);
+ rootDir.refresh(true, false);
VirtualFile[] suspects = rootDir.getChildren();
for (VirtualFile child : suspects) {
if (child.isDirectory()) {
diff --git a/python/src/com/jetbrains/python/validation/PyMultiplePsiFilesVisitorFilter.java b/python/src/com/jetbrains/python/validation/PyMultiplePsiFilesVisitorFilter.java
new file mode 100644
index 0000000..9b6e6b7
--- /dev/null
+++ b/python/src/com/jetbrains/python/validation/PyMultiplePsiFilesVisitorFilter.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.jetbrains.python.validation;
+
+import com.intellij.psi.MultiplePsiFilesPerDocumentFileViewProvider;
+import com.intellij.psi.PsiFile;
+import com.jetbrains.python.inspections.PythonVisitorFilter;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author vlan
+ */
+public class PyMultiplePsiFilesVisitorFilter implements PythonVisitorFilter {
+ @Override
+ public boolean isSupported(@NotNull Class visitorClass, @NotNull PsiFile file) {
+ if (visitorClass == StringLiteralQuotesAnnotator.class &&
+ file.getViewProvider() instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/python/src/com/jetbrains/python/vp/Creator.java b/python/src/com/jetbrains/python/vp/Creator.java
new file mode 100644
index 0000000..3d5bffe
--- /dev/null
+++ b/python/src/com/jetbrains/python/vp/Creator.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.vp;
+
+
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Creates view and presenter allowing them to have links to each other.
+ * Implement it and pass to {@link com.jetbrains.python.vp.ViewPresenterUtils#linkViewWithPresenterAndLaunch(Class, Class, Creator)}
+ *
+ * @author Ilya.Kazakevich
+ * @param <V> view interface
+ * @param <P> presenter interface
+ */
+public interface Creator<V, P extends Presenter> {
+
+ /**
+ * Create presenter
+ *
+ * @param view for that presenter
+ * @return presenter
+ */
+ @NotNull
+ P createPresenter(@NotNull V view);
+
+ /**
+ * Creates view
+ *
+ * @param presenter for this view
+ * @return view
+ */
+ @NotNull
+ V createView(@NotNull P presenter);
+
+}
diff --git a/python/src/com/jetbrains/python/vp/Presenter.java b/python/src/com/jetbrains/python/vp/Presenter.java
new file mode 100644
index 0000000..251aff6
--- /dev/null
+++ b/python/src/com/jetbrains/python/vp/Presenter.java
@@ -0,0 +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.jetbrains.python.vp;
+
+
+/**
+ * Interface each presenter should implement
+ * @author Ilya.Kazakevich
+ */
+public interface Presenter {
+ /**
+ * Launches dialog. Presenter should fetch data and start view.
+ * TODO: Say you run initand show and launch
+ */
+ void launch();
+}
diff --git a/python/src/com/jetbrains/python/vp/PresenterHandler.java b/python/src/com/jetbrains/python/vp/PresenterHandler.java
new file mode 100644
index 0000000..e610604
--- /dev/null
+++ b/python/src/com/jetbrains/python/vp/PresenterHandler.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.vp;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
+
+/**
+ * Wrapper for presenter.
+ * @author Ilya.Kazakevich
+ * @param <C> presenter class
+ */
+class PresenterHandler<C> implements InvocationHandler {
+ /**
+ * Presenter, created by user with {@link com.jetbrains.python.vp.Creator#createPresenter(Object)}
+ */
+ private C realPresenter;
+
+ void setRealPresenter(@NotNull C realPresenter) {
+ this.realPresenter = realPresenter;
+ }
+
+ @Override
+ public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
+ /**
+ * TODO: Implement async call.
+ * The idea is void methods marked with @Async should be called in background thread.
+ * That will allow presenter to be agnostic about EDT
+ */
+ return method.invoke(realPresenter, args);
+ }
+}
diff --git a/python/src/com/jetbrains/python/vp/ViewHandler.java b/python/src/com/jetbrains/python/vp/ViewHandler.java
new file mode 100644
index 0000000..84e9963
--- /dev/null
+++ b/python/src/com/jetbrains/python/vp/ViewHandler.java
@@ -0,0 +1,87 @@
+/*
+ * 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.vp;
+
+import com.google.common.base.Preconditions;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.ModalityState;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Wrapper for view.
+ * @author Ilya.Kazakevich
+ * @param <C> view class
+ */
+class ViewHandler<C> implements InvocationHandler {
+ /**
+ * Real view, created by user using {@link com.jetbrains.python.vp.Creator#createView(Presenter)}
+ */
+ private C realView;
+
+ public void setRealView(@NotNull C realView) {
+ this.realView = realView;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ Preconditions.checkState(realView != null, "Real view not set");
+ Invoker invoker = new Invoker(realView, method, args);
+ ApplicationManager.getApplication().invokeAndWait(invoker, ModalityState.defaultModalityState());
+ if (invoker.exception != null) {
+ throw invoker.exception;
+ }
+ return invoker.result;
+ }
+
+ /**
+ * Class that invokes view methods in appropriate thread
+ */
+ private static class Invoker implements Runnable {
+ @NotNull
+ private final Method method;
+ @Nullable
+ private final Object[] args;
+ @NotNull
+ private final Object target;
+
+ private InvocationTargetException exception;
+ private Object result;
+
+ private Invoker(@NotNull Object target, @NotNull Method method, @Nullable Object[] args) {
+ this.target = target;
+ this.method = method;
+ this.args = args;
+ }
+
+ @Override
+ public void run() {
+ try {
+ result = method.invoke(target, args);
+ }
+ catch (IllegalAccessException e) {
+ throw new IllegalStateException("Method is unaccessible: " + method, e);
+ }
+ catch (InvocationTargetException e) {
+ exception = e;
+ }
+ }
+ }
+}
diff --git a/python/src/com/jetbrains/python/vp/ViewPresenterUtils.java b/python/src/com/jetbrains/python/vp/ViewPresenterUtils.java
new file mode 100644
index 0000000..cfd9677
--- /dev/null
+++ b/python/src/com/jetbrains/python/vp/ViewPresenterUtils.java
@@ -0,0 +1,69 @@
+/*
+ * 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.vp;
+
+
+import com.google.common.base.Preconditions;
+import org.jetbrains.annotations.NotNull;
+
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Proxy;
+
+/**
+ * Entry point to package. Use {@link #linkViewWithPresenterAndLaunch(Class, Class, Creator)}
+ * @author Ilya.Kazakevich
+ */
+public final class ViewPresenterUtils {
+ private ViewPresenterUtils() {
+ }
+
+ /**
+ * TODO: Write about do not call anything in constructor
+ * Creates link between view and presenter and launches them using {@link Presenter#launch()}. Be sure to read package info first.
+ *
+ * @param presenterInterface presenter interface
+ * @param viewInterface view interface
+ * @param creator class that handles presenter and view instances actual creation
+ * @param <V> view interface
+ * @param <P> presenter interface
+ */
+ public static <V, P extends Presenter> void linkViewWithPresenterAndLaunch(@NotNull Class<P> presenterInterface,
+ @NotNull Class<V> viewInterface,
+ @NotNull Creator<V, P> creator) {
+ Preconditions.checkArgument(presenterInterface.isInterface(), "Presenter is not interface");
+ Preconditions.checkArgument(viewInterface.isInterface(), "View is not interface");
+
+ //TODO: Use cglib?
+ PresenterHandler<P> presenterHandler = new PresenterHandler<P>();
+ ViewHandler<V> viewHandler = new ViewHandler<V>();
+ V viewProxy = createProxy(viewInterface, viewHandler);
+ P presenterProxy = createProxy(presenterInterface, presenterHandler);
+
+ V realView = creator.createView(presenterProxy);
+ viewHandler.setRealView(realView);
+ P realPresenter = creator.createPresenter(viewProxy);
+ presenterHandler.setRealPresenter(realPresenter);
+ realPresenter.launch();
+ }
+
+
+ @SuppressWarnings("unchecked") //Proxy always returns correct class
+ private static <C> C createProxy(Class<C> clazz, InvocationHandler handler) {
+ assert clazz != null;
+ assert handler != null;
+ return (C)Proxy.newProxyInstance(ViewPresenterUtils.class.getClassLoader(), new Class[]{clazz}, handler);
+ }
+}
diff --git a/python/src/com/jetbrains/python/vp/package-info.java b/python/src/com/jetbrains/python/vp/package-info.java
new file mode 100644
index 0000000..834ca29
--- /dev/null
+++ b/python/src/com/jetbrains/python/vp/package-info.java
@@ -0,0 +1,26 @@
+/**
+ * <h1>Model-view presenter package</h1>
+ * <h2>How to use?</h2>
+ * <p>
+ * <a href="http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter">MVP</a> pattern implementation with only view and presenter for now.
+ * <dl>
+ * <dt>Presenter</dt>
+ * <dd>Handles all business logic and has <strong>no</strong> references to awt/swing, so it is 100% testable</dd>
+ * <dt>View</dt>
+ * <dd>Handles only view: it may import any swing/awt packages but should contain almost no logic, because it is untestable.</dd>
+ * </dl>
+ * One implements <strong>Presenter</strong> and <strong>View</strong>. Both may have links to each other.
+ * You run {@link com.jetbrains.python.vp.ViewPresenterUtils#linkViewWithPresenterAndLaunch(Class, Class, Creator)} to link and launch them.
+ * See its javadoc
+ * </p>
+ * <h2>Threading issues</h2>
+ *
+ * <p>
+ * Presenter and View should be thread-agnostic.
+ * Any call to <strong>view</strong> is invoked in EDT automatically. <br/>
+ * Call to <strong>presenter</strong> may be invoked in background (not implemented yet, see {@link com.jetbrains.python.vp.PresenterHandler})
+ * </p>
+ *
+ * @author Ilya.Kazakevich
+ */
+package com.jetbrains.python.vp;
\ No newline at end of file
diff --git a/python/src/icons/PythonIcons.java b/python/src/icons/PythonIcons.java
index c942e0c..a65d468 100644
--- a/python/src/icons/PythonIcons.java
+++ b/python/src/icons/PythonIcons.java
@@ -32,6 +32,7 @@
}
public static final Icon Dotnet = load("/icons/com/jetbrains/python/dotnet.png"); // 16x16
+ public static final Icon InterpreterGear = load("/icons/com/jetbrains/python/interpreterGear.png"); // 16x16
public static final Icon Jython = load("/icons/com/jetbrains/python/jython.png"); // 16x16
public static class Nodes {
@@ -48,6 +49,7 @@
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 Virtualenv = load("/icons/com/jetbrains/python/virtualenv.png"); // 16x16
}
diff --git a/python/testData/formatter/alignListComprehensionInDict.py b/python/testData/formatter/alignListComprehensionInDict.py
new file mode 100644
index 0000000..7b74279
--- /dev/null
+++ b/python/testData/formatter/alignListComprehensionInDict.py
@@ -0,0 +1,5 @@
+def foo():
+ return {field.key: field for key, field in inspect.getmembers(instance)
+ if isinstance(field, QueryableAttribute)
+ and isinstance(field.property, ColumnProperty)
+ or field.foreign_keys}
\ No newline at end of file
diff --git a/python/testData/formatter/alignListComprehensionInDict_after.py b/python/testData/formatter/alignListComprehensionInDict_after.py
new file mode 100644
index 0000000..bcb4c22
--- /dev/null
+++ b/python/testData/formatter/alignListComprehensionInDict_after.py
@@ -0,0 +1,5 @@
+def foo():
+ return {field.key: field for key, field in inspect.getmembers(instance)
+ if isinstance(field, QueryableAttribute)
+ and isinstance(field.property, ColumnProperty)
+ or field.foreign_keys}
\ No newline at end of file
diff --git a/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py
index a0f5290..c908253 100644
--- a/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py
+++ b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment.py
@@ -1,7 +1,7 @@
class A(object):
pass
-#comment
+# comment
def one():
pass
@@ -9,10 +9,10 @@
def two():
pass
-#comment
+# comment
class B(object):
pass
-#comment
+# comment
class C(object):
pass
\ No newline at end of file
diff --git a/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py
index d582036..ba0e697 100644
--- a/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py
+++ b/python/testData/formatter/twoLinesBetweenTopLevelDeclarationsWithComment_after.py
@@ -2,7 +2,7 @@
pass
-#comment
+# comment
def one():
pass
@@ -12,11 +12,11 @@
pass
-#comment
+# comment
class B(object):
pass
-#comment
+# comment
class C(object):
pass
\ No newline at end of file
diff --git a/python/testData/inspections/PyTypeCheckerInspection/DefaultTupleParameter.py b/python/testData/inspections/PyTypeCheckerInspection/DefaultTupleParameter.py
new file mode 100644
index 0000000..0e082e8
--- /dev/null
+++ b/python/testData/inspections/PyTypeCheckerInspection/DefaultTupleParameter.py
@@ -0,0 +1,5 @@
+def f(x=(), y=('foo', 'bar')):
+ pass
+
+
+f([1, 2, 3], ['foo'])
diff --git a/python/testData/psi/BadDecoratorNotMethod.py b/python/testData/psi/BadDecoratorNotMethod.py
new file mode 100644
index 0000000..1e3b5e6
--- /dev/null
+++ b/python/testData/psi/BadDecoratorNotMethod.py
@@ -0,0 +1,4 @@
+class Foo(object):
+ @staticmethod
+ def bad_method(): #test
+ pass
\ No newline at end of file
diff --git a/python/testData/psi/BadDecoratorNotMethod.txt b/python/testData/psi/BadDecoratorNotMethod.txt
new file mode 100644
index 0000000..b2269d3
--- /dev/null
+++ b/python/testData/psi/BadDecoratorNotMethod.txt
@@ -0,0 +1,44 @@
+PyFile:BadDecoratorNotMethod.py
+ PyClass: Foo
+ PsiElement(Py:CLASS_KEYWORD)('class')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:IDENTIFIER)('Foo')
+ PyArgumentList
+ PsiElement(Py:LPAR)('(')
+ PyReferenceExpression: object
+ PsiElement(Py:IDENTIFIER)('object')
+ PsiElement(Py:RPAR)(')')
+ PsiElement(Py:COLON)(':')
+ PsiWhiteSpace('\n ')
+ PyStatementList
+ PyFunction('null')
+ PyDecoratorList
+ PyDecorator: @staticmethod
+ PsiElement(Py:AT)('@')
+ PyReferenceExpression: staticmethod
+ PsiElement(Py:IDENTIFIER)('staticmethod')
+ PyArgumentList
+ <empty list>
+ PsiErrorElement:'@' or 'def' expected
+ <empty list>
+ PsiWhiteSpace('\n ')
+ PyParameterList
+ <empty list>
+ PyStatementList
+ <empty list>
+ PsiErrorElement:Unexpected indent
+ <empty list>
+ PyFunction('bad_method')
+ PsiElement(Py:DEF_KEYWORD)('def')
+ PsiWhiteSpace(' ')
+ PsiElement(Py:IDENTIFIER)('bad_method')
+ PyParameterList
+ PsiElement(Py:LPAR)('(')
+ PsiElement(Py:RPAR)(')')
+ PsiElement(Py:COLON)(':')
+ PsiWhiteSpace(' ')
+ PsiComment(Py:END_OF_LINE_COMMENT)('#test')
+ PsiWhiteSpace('\n ')
+ PyStatementList
+ PyPassStatement
+ PsiElement(Py:PASS_KEYWORD)('pass')
\ No newline at end of file
diff --git a/python/testData/refactoring/argumentList/addKeyArgument/addArgumentFile.after.py b/python/testData/refactoring/argumentList/addKeyArgument/addArgumentFile.after.py
new file mode 100644
index 0000000..7a9fbe9
--- /dev/null
+++ b/python/testData/refactoring/argumentList/addKeyArgument/addArgumentFile.after.py
@@ -0,0 +1,32 @@
+from stub import *
+import stub
+
+
+class MyOldClass(metaclass=ABCMeta):
+ pass
+
+
+class MyNewClass(object,metaclass=ABCMeta):
+ pass
+
+
+class MyNewClass_2(object, datetime,metaclass=ABCMeta):
+ pass
+
+class NewClass_3(stub.object,metaclass=ABCMeta):
+ pass
+
+class NewClass_4(stub.object, stub.datetime,metaclass=ABCMeta):
+ pass
+
+class NewClass_5(stub.datetime, foo=stub.object,metaclass=ABCMeta):
+ pass
+
+
+spam = "new_param"
+
+my_function(new_param=spam)
+my_function_1("some_param",new_param=spam)
+my_function_2(named_param="ham",new_param=spam)
+my_function_3("some_param", "some_param_2", named_param="ham",new_param=spam)
+my_function_4("some_param", "some_param_2", named_param=stub.object, named_param_2="eggs",new_param=spam)
\ No newline at end of file
diff --git a/python/testData/refactoring/argumentList/addKeyArgument/addArgumentFile.py b/python/testData/refactoring/argumentList/addKeyArgument/addArgumentFile.py
new file mode 100644
index 0000000..32b4fda
--- /dev/null
+++ b/python/testData/refactoring/argumentList/addKeyArgument/addArgumentFile.py
@@ -0,0 +1,32 @@
+from stub import *
+import stub
+
+
+class MyOldClass():
+ pass
+
+
+class MyNewClass(object):
+ pass
+
+
+class MyNewClass_2(object, datetime):
+ pass
+
+class NewClass_3(stub.object):
+ pass
+
+class NewClass_4(stub.object, stub.datetime):
+ pass
+
+class NewClass_5(stub.datetime, foo=stub.object):
+ pass
+
+
+spam = "new_param"
+
+my_function()
+my_function_1("some_param")
+my_function_2(named_param="ham")
+my_function_3("some_param", "some_param_2", named_param="ham")
+my_function_4("some_param", "some_param_2", named_param=stub.object, named_param_2="eggs")
\ No newline at end of file
diff --git a/python/testData/refactoring/argumentList/addKeyArgument/stub.py b/python/testData/refactoring/argumentList/addKeyArgument/stub.py
new file mode 100644
index 0000000..9227a35
--- /dev/null
+++ b/python/testData/refactoring/argumentList/addKeyArgument/stub.py
@@ -0,0 +1,13 @@
+class object: pass
+
+class datetime: pass
+
+
+class ABCMeta: pass
+
+
+def my_function(new_param="spam"): pass
+def my_function_1(first_param,some_param, new_param="spam"): pass
+def my_function_2(first_param,named_param="ham", new_param="spam"): pass
+def my_function_3(first_param,some_param, some_param_2, named_param="ham", new_param="spam"): pass
+def my_function_4(first_param,some_param, some_param_2, named_param="ham", named_param_2="eggs", new_param="spam"): pass
\ No newline at end of file
diff --git a/python/testData/refactoring/argumentList/addParam/addArgumentFile.after.py b/python/testData/refactoring/argumentList/addParam/addArgumentFile.after.py
new file mode 100644
index 0000000..97c18fd
--- /dev/null
+++ b/python/testData/refactoring/argumentList/addParam/addArgumentFile.after.py
@@ -0,0 +1,27 @@
+from stub import *
+import stub
+
+
+class MyOldClass(SuperClass):
+ pass
+
+
+class MyNewClass(object,SuperClass):
+ pass
+
+
+class MyNewClass_2(object, datetime,SuperClass):
+ pass
+
+class NewClass_3(stub.object,SuperClass):
+ pass
+
+class NewClass_4(stub.object, stub.datetime,SuperClass):
+ pass
+
+new_param = "ogg"
+
+my_function(new_param,some_param="spam")
+my_function(new_param)
+my_function_2("some_param",new_param)
+my_function_3(new_param,some_param="spam",some_another_param=stub.object)
\ No newline at end of file
diff --git a/python/testData/refactoring/argumentList/addParam/addArgumentFile.py b/python/testData/refactoring/argumentList/addParam/addArgumentFile.py
new file mode 100644
index 0000000..32d0235
--- /dev/null
+++ b/python/testData/refactoring/argumentList/addParam/addArgumentFile.py
@@ -0,0 +1,27 @@
+from stub import *
+import stub
+
+
+class MyOldClass():
+ pass
+
+
+class MyNewClass(object):
+ pass
+
+
+class MyNewClass_2(object, datetime):
+ pass
+
+class NewClass_3(stub.object):
+ pass
+
+class NewClass_4(stub.object, stub.datetime):
+ pass
+
+new_param = "ogg"
+
+my_function(some_param="spam")
+my_function()
+my_function_2("some_param")
+my_function_3(some_param="spam",some_another_param=stub.object)
\ No newline at end of file
diff --git a/python/testData/refactoring/argumentList/addParam/stub.py b/python/testData/refactoring/argumentList/addParam/stub.py
new file mode 100644
index 0000000..b98bdb0
--- /dev/null
+++ b/python/testData/refactoring/argumentList/addParam/stub.py
@@ -0,0 +1,13 @@
+class object: pass
+
+class datetime: pass
+
+
+class ABCMeta: pass
+
+class SuperClass: pass
+
+
+def my_function(new_param,some_param="spam"): pass
+def my_function_2(new_param,some_param): pass
+def my_function_3(new_param,some_param="spam",some_another_param="eggs"): pass
diff --git a/python/testData/refactoring/extractmethod/Comment2.after.py b/python/testData/refactoring/extractmethod/Comment2.after.py
index 5e5fdc3..c5cc3a7 100644
--- a/python/testData/refactoring/extractmethod/Comment2.after.py
+++ b/python/testData/refactoring/extractmethod/Comment2.after.py
@@ -1,6 +1,6 @@
class Foo():
def baz():
- tmp = "!" #try to extract this assignmet, either with or without this comment
+ tmp = "!" # try to extract this assignment, either with or without this comment
baz()
diff --git a/python/testData/refactoring/extractmethod/Comment2.before.py b/python/testData/refactoring/extractmethod/Comment2.before.py
index d43386a..23ba13d 100644
--- a/python/testData/refactoring/extractmethod/Comment2.before.py
+++ b/python/testData/refactoring/extractmethod/Comment2.before.py
@@ -1,5 +1,5 @@
class Foo():
- <selection>tmp = "!" #try to extract this assignmet, either with or without this comment</selection>
+ <selection>tmp = "!" #try to extract this assignment, either with or without this comment</selection>
def bar(self):
pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractmethod/ElseBody.after.py b/python/testData/refactoring/extractmethod/ElseBody.after.py
index 57b5fa0..24e387d 100644
--- a/python/testData/refactoring/extractmethod/ElseBody.after.py
+++ b/python/testData/refactoring/extractmethod/ElseBody.after.py
@@ -1,5 +1,5 @@
def baz(f_new):
- length = len(f_new.readlines()) #<---extract something from here
+ length = len(f_new.readlines()) # <---extract something from here
print("hi from else")
diff --git a/python/testData/refactoring/extractsuperclass/importMultiFile/dest_module.after.py b/python/testData/refactoring/extractsuperclass/importMultiFile/dest_module.after.py
new file mode 100644
index 0000000..eba5f32
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importMultiFile/dest_module.after.py
@@ -0,0 +1,9 @@
+import shared_module
+from shared_module import module_function as my_function, ModuleClass
+
+
+class NewParent(object):
+ def do_useful_stuff(self):
+ i = shared_module.MODULE_CONTANT
+ my_function()
+ ModuleClass()
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/importMultiFile/dest_module.py
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/test.rnc
rename to python/testData/refactoring/extractsuperclass/importMultiFile/dest_module.py
diff --git a/python/testData/refactoring/extractsuperclass/importMultiFile/shared_module.py b/python/testData/refactoring/extractsuperclass/importMultiFile/shared_module.py
new file mode 100644
index 0000000..13fe833
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importMultiFile/shared_module.py
@@ -0,0 +1,9 @@
+MODULE_CONTANT = 42
+
+
+def module_function():
+ pass
+
+
+class ModuleClass(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importMultiFile/source_module.after.py b/python/testData/refactoring/extractsuperclass/importMultiFile/source_module.after.py
new file mode 100644
index 0000000..b9d7117
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importMultiFile/source_module.after.py
@@ -0,0 +1,5 @@
+from dest_module import NewParent
+
+
+class MyClass(NewParent):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importMultiFile/source_module.py b/python/testData/refactoring/extractsuperclass/importMultiFile/source_module.py
new file mode 100644
index 0000000..aa10bca
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importMultiFile/source_module.py
@@ -0,0 +1,9 @@
+import shared_module
+from shared_module import module_function as my_function
+from shared_module import ModuleClass
+
+class MyClass(object):
+ def do_useful_stuff(self):
+ i = shared_module.MODULE_CONTANT
+ my_function()
+ ModuleClass()
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importNotBroken.after.py b/python/testData/refactoring/extractsuperclass/importNotBroken.after.py
new file mode 100644
index 0000000..897c62a
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importNotBroken.after.py
@@ -0,0 +1,9 @@
+from shared import SharedClass
+
+
+class DestClass(SharedClass):
+ pass
+
+
+class Source(DestClass):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importNotBroken.before.py b/python/testData/refactoring/extractsuperclass/importNotBroken.before.py
new file mode 100644
index 0000000..82d6d5c
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importNotBroken.before.py
@@ -0,0 +1,5 @@
+from shared import SharedClass
+
+
+class Source(SharedClass):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py
new file mode 100644
index 0000000..6189ad4
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.after.py
@@ -0,0 +1,5 @@
+from shared_module import SharedClass
+
+
+class NewParent(SharedClass):
+ pass
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.py
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/test.rnc
copy to python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/dest_module.py
diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py
new file mode 100644
index 0000000..da81c49
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/shared_module.py
@@ -0,0 +1 @@
+class SharedClass(object): pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py
new file mode 100644
index 0000000..b9d7117
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.after.py
@@ -0,0 +1,5 @@
+from dest_module import NewParent
+
+
+class MyClass(NewParent):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py
new file mode 100644
index 0000000..1824aec
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/importNotBrokenManyFiles/source_module.py
@@ -0,0 +1,4 @@
+from shared_module import SharedClass
+
+class MyClass(SharedClass):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/instanceNotDeclaredInInit.after.py b/python/testData/refactoring/extractsuperclass/instanceNotDeclaredInInit.after.py
new file mode 100644
index 0000000..ef3511d
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/instanceNotDeclaredInInit.after.py
@@ -0,0 +1,8 @@
+class Parent(object):
+ def __init__(self):
+ self.eggs = 12
+
+
+class Child(Parent):
+ def foo(self):
+ self.eggs = 12
diff --git a/python/testData/refactoring/extractsuperclass/instanceNotDeclaredInInit.before.py b/python/testData/refactoring/extractsuperclass/instanceNotDeclaredInInit.before.py
new file mode 100644
index 0000000..9c5594a
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/instanceNotDeclaredInInit.before.py
@@ -0,0 +1,3 @@
+class Child(object):
+ def foo(self):
+ self.eggs = 12
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/abc.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/abc.py
new file mode 100644
index 0000000..ef4f2f6
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/abc.py
@@ -0,0 +1,8 @@
+# Stubs
+
+class ABCMeta:
+ pass
+
+
+def abstractmethod(foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py
new file mode 100644
index 0000000..bbf726c
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.after.py
@@ -0,0 +1,13 @@
+from abc import abstractmethod
+from abc import ABCMeta
+
+
+class NewParent(object):
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def foo_method(self):
+ """
+ Foo
+ """
+ pass
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.py
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/test.rnc
copy to python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/dest_module.py
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/shared_module.py
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/test.rnc
copy to python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/shared_module.py
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py
new file mode 100644
index 0000000..6e71752
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.after.py
@@ -0,0 +1,9 @@
+from dest_module import NewParent
+
+
+class MyClass(NewParent):
+ def foo_method(self):
+ """
+ Foo
+ """
+ spam = "eggs"
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py
new file mode 100644
index 0000000..f4a7c42
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstract/source_module.py
@@ -0,0 +1,6 @@
+class MyClass(object):
+ def foo_method(self):
+ """
+ Foo
+ """
+ spam = "eggs"
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/abc.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/abc.py
new file mode 100644
index 0000000..ef4f2f6
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/abc.py
@@ -0,0 +1,8 @@
+# Stubs
+
+class ABCMeta:
+ pass
+
+
+def abstractmethod(foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/dest_module.after.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/dest_module.after.py
new file mode 100644
index 0000000..ddce4a8
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/dest_module.after.py
@@ -0,0 +1,13 @@
+from abc import ABCMeta
+from abc import abstractmethod
+
+
+ABCMeta()
+abstractmethod()
+
+
+class NewParent(metaclass=ABCMeta):
+ @classmethod
+ @abstractmethod
+ def foo_method(cls):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/dest_module.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/dest_module.py
new file mode 100644
index 0000000..81549d3
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/dest_module.py
@@ -0,0 +1,6 @@
+from abc import ABCMeta
+from abc import abstractmethod
+
+
+ABCMeta()
+abstractmethod()
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/shared_module.py
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/test.rnc
copy to python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/shared_module.py
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/source_module.after.py
new file mode 100644
index 0000000..02c129f
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/source_module.after.py
@@ -0,0 +1,7 @@
+from dest_module import NewParent
+
+
+class MyClass(NewParent):
+ @classmethod
+ def foo_method(cls):
+ spam = "eggs"
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/source_module.py b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/source_module.py
new file mode 100644
index 0000000..b197c5f
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveAndMakeAbstractImportExistsPy3/source_module.py
@@ -0,0 +1,4 @@
+class MyClass():
+ @classmethod
+ def foo_method(cls):
+ spam = "eggs"
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveExtends/dest_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtends/dest_module.after.py
new file mode 100644
index 0000000..1171abf
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtends/dest_module.after.py
@@ -0,0 +1,5 @@
+from shared_module import TheParentOfItAll
+
+
+class NewParent(TheParentOfItAll):
+ pass
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/moveExtends/dest_module.py
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/test.rnc
copy to python/testData/refactoring/extractsuperclass/moveExtends/dest_module.py
diff --git a/python/testData/refactoring/extractsuperclass/moveExtends/shared_module.py b/python/testData/refactoring/extractsuperclass/moveExtends/shared_module.py
new file mode 100644
index 0000000..fd3d3fc
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtends/shared_module.py
@@ -0,0 +1,2 @@
+class TheParentOfItAll(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py
new file mode 100644
index 0000000..b9d7117
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtends/source_module.after.py
@@ -0,0 +1,5 @@
+from dest_module import NewParent
+
+
+class MyClass(NewParent):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveExtends/source_module.py b/python/testData/refactoring/extractsuperclass/moveExtends/source_module.py
new file mode 100644
index 0000000..87c753a
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtends/source_module.py
@@ -0,0 +1,4 @@
+import shared_module
+
+class MyClass(shared_module.TheParentOfItAll):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py
new file mode 100644
index 0000000..1171abf
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.after.py
@@ -0,0 +1,5 @@
+from shared_module import TheParentOfItAll
+
+
+class NewParent(TheParentOfItAll):
+ pass
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/test.rnc b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.py
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/test.rnc
copy to python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/dest_module.py
diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py
new file mode 100644
index 0000000..fd3d3fc
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/shared_module.py
@@ -0,0 +1,2 @@
+class TheParentOfItAll(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py
new file mode 100644
index 0000000..b9d7117
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.after.py
@@ -0,0 +1,5 @@
+from dest_module import NewParent
+
+
+class MyClass(NewParent):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py
new file mode 100644
index 0000000..c2ca974
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveExtendsCheckReference/source_module.py
@@ -0,0 +1,4 @@
+from shared_module import TheParentOfItAll
+
+class MyClass(TheParentOfItAll):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveFields.after.py b/python/testData/refactoring/extractsuperclass/moveFields.after.py
new file mode 100644
index 0000000..043e4d3
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveFields.after.py
@@ -0,0 +1,10 @@
+class ToClass(object):
+ CLASS_FIELD = 42
+
+ def __init__(self):
+ self.instance_field = 100500
+
+
+class FromClass(ToClass):
+ def __init__(self):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/moveFields.before.py b/python/testData/refactoring/extractsuperclass/moveFields.before.py
new file mode 100644
index 0000000..54a167f
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/moveFields.before.py
@@ -0,0 +1,4 @@
+class FromClass(object):
+ CLASS_FIELD = 42
+ def __init__(self):
+ self.instance_field = 100500
diff --git a/python/testData/refactoring/extractsuperclass/presenter/file.py b/python/testData/refactoring/extractsuperclass/presenter/file.py
new file mode 100644
index 0000000..9e6af14
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/presenter/file.py
@@ -0,0 +1,20 @@
+from datetime import date
+class Child(object, date):
+ CLASS_VAR = "spam"
+
+ def eggs(self): # May be abstract
+ pass
+
+ def __init__(self):
+ super(Child, self).__init__()
+ self.artur = "king"
+
+class StaticOnly(object):
+ @staticmethod
+ def static_method(): # May be abstract in case of Py3
+ pass
+
+
+class OldClass():
+ def foo(self):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/shared.py b/python/testData/refactoring/extractsuperclass/shared.py
new file mode 100644
index 0000000..71f03ab
--- /dev/null
+++ b/python/testData/refactoring/extractsuperclass/shared.py
@@ -0,0 +1 @@
+class SharedClass: pass
\ No newline at end of file
diff --git a/python/testData/refactoring/extractsuperclass/withImport.after.py b/python/testData/refactoring/extractsuperclass/withImport.after.py
index ccd508b..8601863 100644
--- a/python/testData/refactoring/extractsuperclass/withImport.after.py
+++ b/python/testData/refactoring/extractsuperclass/withImport.after.py
@@ -1,4 +1,3 @@
-import os
from refactoring.extractsuperclass import Suppa
diff --git a/python/testData/refactoring/pullup/abstractMethodHasMeta/Class.after.py b/python/testData/refactoring/pullup/abstractMethodHasMeta/Class.after.py
new file mode 100644
index 0000000..e85e0f2
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodHasMeta/Class.after.py
@@ -0,0 +1,4 @@
+from SuperClass import Parent
+class Child(Parent):
+ def my_method(self, foo):
+ bar = foo
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodHasMeta/Class.py b/python/testData/refactoring/pullup/abstractMethodHasMeta/Class.py
new file mode 100644
index 0000000..e85e0f2
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodHasMeta/Class.py
@@ -0,0 +1,4 @@
+from SuperClass import Parent
+class Child(Parent):
+ def my_method(self, foo):
+ bar = foo
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodHasMeta/SuperClass.after.py b/python/testData/refactoring/pullup/abstractMethodHasMeta/SuperClass.after.py
new file mode 100644
index 0000000..b0004eb
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodHasMeta/SuperClass.after.py
@@ -0,0 +1,13 @@
+from abc import ABCMeta, abstractmethod
+
+
+class Parent(object):
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def my_method2(self):
+ pass
+
+ @abstractmethod
+ def my_method(self, foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodHasMeta/SuperClass.py b/python/testData/refactoring/pullup/abstractMethodHasMeta/SuperClass.py
new file mode 100644
index 0000000..14d85de
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodHasMeta/SuperClass.py
@@ -0,0 +1,9 @@
+from abc import ABCMeta, abstractmethod
+
+
+class Parent(object):
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def my_method2(self):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodHasMeta/abc.py b/python/testData/refactoring/pullup/abstractMethodHasMeta/abc.py
new file mode 100644
index 0000000..ef4f2f6
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodHasMeta/abc.py
@@ -0,0 +1,8 @@
+# Stubs
+
+class ABCMeta:
+ pass
+
+
+def abstractmethod(foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/Class.after.py b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/Class.after.py
new file mode 100644
index 0000000..69998c4
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/Class.after.py
@@ -0,0 +1,7 @@
+from SuperClass import Parent
+class Child(Parent):
+ def my_method(self, foo):
+ bar = foo
+
+ def my_method_2(self, foo):
+ bar = foo
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/Class.py b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/Class.py
new file mode 100644
index 0000000..69998c4
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/Class.py
@@ -0,0 +1,7 @@
+from SuperClass import Parent
+class Child(Parent):
+ def my_method(self, foo):
+ bar = foo
+
+ def my_method_2(self, foo):
+ bar = foo
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/SuperClass.after.py b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/SuperClass.after.py
new file mode 100644
index 0000000..d44a9e4
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/SuperClass.after.py
@@ -0,0 +1,14 @@
+from abc import ABCMeta
+from abc import abstractmethod
+
+
+class Parent(object):
+ __metaclass__ = ABCMeta
+
+ @abstractmethod
+ def my_method(self, foo):
+ pass
+
+ @abstractmethod
+ def my_method_2(self, foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/SuperClass.py b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/SuperClass.py
new file mode 100644
index 0000000..b63dd44
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/SuperClass.py
@@ -0,0 +1,2 @@
+class Parent(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/abc.py b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/abc.py
new file mode 100644
index 0000000..ef4f2f6
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy2AddMeta/abc.py
@@ -0,0 +1,8 @@
+# Stubs
+
+class ABCMeta:
+ pass
+
+
+def abstractmethod(foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py
new file mode 100644
index 0000000..c0e75fa
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.after.py
@@ -0,0 +1,12 @@
+from SuperClass import Parent
+class Child(Parent):
+ def my_method(self, foo):
+ """
+ Eats eggs
+ :param foo: eggs
+ """
+ bar = foo
+
+ @classmethod
+ def my_class_method():
+ print("Q")
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py
new file mode 100644
index 0000000..c0e75fa
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/Class.py
@@ -0,0 +1,12 @@
+from SuperClass import Parent
+class Child(Parent):
+ def my_method(self, foo):
+ """
+ Eats eggs
+ :param foo: eggs
+ """
+ bar = foo
+
+ @classmethod
+ def my_class_method():
+ print("Q")
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py
new file mode 100644
index 0000000..ded9ea6
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.after.py
@@ -0,0 +1,16 @@
+from abc import ABCMeta
+from abc import abstractmethod
+from abc import object
+class Parent(object, metaclass=ABCMeta):
+ @abstractmethod
+ def my_method(self, foo):
+ """
+ Eats eggs
+ :param foo: eggs
+ """
+ pass
+
+ @classmethod
+ @abstractmethod
+ def my_class_method():
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.py
new file mode 100644
index 0000000..33ba9ff
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/SuperClass.py
@@ -0,0 +1,3 @@
+from abc import object
+class Parent(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/abc.py b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/abc.py
new file mode 100644
index 0000000..a63732d
--- /dev/null
+++ b/python/testData/refactoring/pullup/abstractMethodPy3AddMeta/abc.py
@@ -0,0 +1,11 @@
+# Stubs
+
+class object:
+ pass
+
+class ABCMeta:
+ pass
+
+
+def abstractmethod(foo):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/duplicateImport/Class.after.py b/python/testData/refactoring/pullup/duplicateImport/Class.after.py
new file mode 100644
index 0000000..d1946f8
--- /dev/null
+++ b/python/testData/refactoring/pullup/duplicateImport/Class.after.py
@@ -0,0 +1,6 @@
+from SuperClass import SuperClass
+
+
+class AnyClass(SuperClass):
+ pass
+
diff --git a/python/testData/refactoring/pullup/duplicateImport/Class.py b/python/testData/refactoring/pullup/duplicateImport/Class.py
index bd19d07..ca10ac1 100644
--- a/python/testData/refactoring/pullup/duplicateImport/Class.py
+++ b/python/testData/refactoring/pullup/duplicateImport/Class.py
@@ -1,4 +1,6 @@
from SuperClass import SuperClass
+import sys
+
from sys import argv
@@ -7,3 +9,5 @@
if not self.args:
self.args = argv
self.argument = some_argument
+ print(sys.api_version)
+
diff --git a/python/testData/refactoring/pullup/duplicateImport/SuperClass.after.py b/python/testData/refactoring/pullup/duplicateImport/SuperClass.after.py
index 19fa11b..beda7cd 100644
--- a/python/testData/refactoring/pullup/duplicateImport/SuperClass.after.py
+++ b/python/testData/refactoring/pullup/duplicateImport/SuperClass.after.py
@@ -1,4 +1,6 @@
from sys import argv
+import sys
+
class SuperClass(object):
def __init__(self):
@@ -8,3 +10,4 @@
if not self.args:
self.args = argv
self.argument = some_argument
+ print(sys.api_version)
diff --git a/python/testData/refactoring/pullup/fieldMove/Class.after.py b/python/testData/refactoring/pullup/fieldMove/Class.after.py
new file mode 100644
index 0000000..da34ab3
--- /dev/null
+++ b/python/testData/refactoring/pullup/fieldMove/Class.after.py
@@ -0,0 +1,6 @@
+from SuperClass import SuperClass
+
+
+class AnyClass(SuperClass):
+ def __init__(self):
+ super().__init__()
diff --git a/python/testData/refactoring/pullup/fieldMove/Class.py b/python/testData/refactoring/pullup/fieldMove/Class.py
new file mode 100644
index 0000000..99e7fa8
--- /dev/null
+++ b/python/testData/refactoring/pullup/fieldMove/Class.py
@@ -0,0 +1,9 @@
+import sys
+from SuperClass import SuperClass
+
+class AnyClass(SuperClass):
+ COPYRIGHT = sys.copyright
+
+ def __init__(self):
+ super().__init__()
+ self.version = sys.api_version
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/fieldMove/SuperClass.after.py b/python/testData/refactoring/pullup/fieldMove/SuperClass.after.py
new file mode 100644
index 0000000..fc7c5e9
--- /dev/null
+++ b/python/testData/refactoring/pullup/fieldMove/SuperClass.after.py
@@ -0,0 +1,8 @@
+import sys
+
+
+class SuperClass(object):
+ COPYRIGHT = sys.copyright
+
+ def __init__(self):
+ self.version = sys.api_version
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/fieldMove/SuperClass.py b/python/testData/refactoring/pullup/fieldMove/SuperClass.py
new file mode 100644
index 0000000..287177a
--- /dev/null
+++ b/python/testData/refactoring/pullup/fieldMove/SuperClass.py
@@ -0,0 +1,2 @@
+class SuperClass(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/instanceNotDeclaredInInit.after.py b/python/testData/refactoring/pullup/instanceNotDeclaredInInit.after.py
new file mode 100644
index 0000000..812bd9c
--- /dev/null
+++ b/python/testData/refactoring/pullup/instanceNotDeclaredInInit.after.py
@@ -0,0 +1,8 @@
+class Parent(object):
+ def __init__(self):
+ self.foo = 12
+
+
+class Child(Parent):
+ def foo(self):
+ self.foo = 12
diff --git a/python/testData/refactoring/pullup/instanceNotDeclaredInInit.py b/python/testData/refactoring/pullup/instanceNotDeclaredInInit.py
new file mode 100644
index 0000000..9e57575
--- /dev/null
+++ b/python/testData/refactoring/pullup/instanceNotDeclaredInInit.py
@@ -0,0 +1,7 @@
+class Parent(object):
+ pass
+
+
+class Child(Parent):
+ def foo(self):
+ self.foo = 12
diff --git a/python/testData/refactoring/pullup/moveClassAttributesNoPass.after.py b/python/testData/refactoring/pullup/moveClassAttributesNoPass.after.py
new file mode 100644
index 0000000..8732118
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveClassAttributesNoPass.after.py
@@ -0,0 +1,9 @@
+class Parent2:
+ CLASS_VAR = 42
+
+ def doo(self):
+ pass
+
+
+class Child2(Parent2):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/moveClassAttributesNoPass.py b/python/testData/refactoring/pullup/moveClassAttributesNoPass.py
new file mode 100644
index 0000000..2454ab2
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveClassAttributesNoPass.py
@@ -0,0 +1,7 @@
+class Parent2:
+ def doo(self):
+ pass
+
+
+class Child2(Parent2):
+ CLASS_VAR = 42
diff --git a/python/testData/refactoring/pullup/moveClassAttributesSimple.after.py b/python/testData/refactoring/pullup/moveClassAttributesSimple.after.py
new file mode 100644
index 0000000..a770871
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveClassAttributesSimple.after.py
@@ -0,0 +1,6 @@
+class Parent:
+ CLASS_VAR = 42
+
+
+class Child(Parent):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/moveClassAttributesSimple.py b/python/testData/refactoring/pullup/moveClassAttributesSimple.py
new file mode 100644
index 0000000..fbfef9f
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveClassAttributesSimple.py
@@ -0,0 +1,6 @@
+class Parent:
+ pass
+
+
+class Child(Parent):
+ CLASS_VAR = 42
diff --git a/python/testData/refactoring/pullup/moveInstanceAttributesLeaveEmptyInit.after.py b/python/testData/refactoring/pullup/moveInstanceAttributesLeaveEmptyInit.after.py
new file mode 100644
index 0000000..b379333
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveInstanceAttributesLeaveEmptyInit.after.py
@@ -0,0 +1,21 @@
+class Parent(object):
+ C = 12
+
+ def __init__(self):
+ self.foo = 12
+
+ def foo(self):
+ pass
+
+
+class Child(Parent, object):
+ def __init__(self): pass
+
+ AC = 11
+
+ def foo(self):
+ pass
+
+
+class Bar(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/moveInstanceAttributesLeaveEmptyInit.py b/python/testData/refactoring/pullup/moveInstanceAttributesLeaveEmptyInit.py
new file mode 100644
index 0000000..36721bf
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveInstanceAttributesLeaveEmptyInit.py
@@ -0,0 +1,19 @@
+class Parent(object):
+ C = 12
+
+ def foo(self):
+ pass
+
+
+class Child(Parent, object):
+ def __init__(self):
+ self.foo = 12
+
+ AC = 11
+
+ def foo(self):
+ pass
+
+
+class Bar(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/moveInstanceAttributesNoInit.after.py b/python/testData/refactoring/pullup/moveInstanceAttributesNoInit.after.py
new file mode 100644
index 0000000..ec67fd6
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveInstanceAttributesNoInit.after.py
@@ -0,0 +1,9 @@
+class Parent:
+ def __init__(self):
+ self.instance_field = "eggs"
+
+
+class Child(Parent):
+ def __init__(self):
+ Parent2.__init__(self)
+
diff --git a/python/testData/refactoring/pullup/moveInstanceAttributesNoInit.py b/python/testData/refactoring/pullup/moveInstanceAttributesNoInit.py
new file mode 100644
index 0000000..88866c1
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveInstanceAttributesNoInit.py
@@ -0,0 +1,9 @@
+class Parent:
+ pass
+
+
+class Child(Parent):
+ def __init__(self):
+ Parent2.__init__(self)
+ self.instance_field = "eggs"
+
diff --git a/python/testData/refactoring/pullup/moveInstanceAttributesSimple.after.py b/python/testData/refactoring/pullup/moveInstanceAttributesSimple.after.py
new file mode 100644
index 0000000..c1d9a6b
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveInstanceAttributesSimple.after.py
@@ -0,0 +1,9 @@
+class Parent:
+ def __init__(self):
+ self.instance_field = "eggs"
+
+
+class Child(Parent):
+ def __init__(self):
+ Parent2.__init__(self)
+
diff --git a/python/testData/refactoring/pullup/moveInstanceAttributesSimple.py b/python/testData/refactoring/pullup/moveInstanceAttributesSimple.py
new file mode 100644
index 0000000..2cf1c16
--- /dev/null
+++ b/python/testData/refactoring/pullup/moveInstanceAttributesSimple.py
@@ -0,0 +1,10 @@
+class Parent:
+ def __init__(self):
+ pass
+
+
+class Child(Parent):
+ def __init__(self):
+ Parent2.__init__(self)
+ self.instance_field = "eggs"
+
diff --git a/python/testData/refactoring/pullup/multiFile/Class.after.py b/python/testData/refactoring/pullup/multiFile/Class.after.py
new file mode 100644
index 0000000..1def8e5
--- /dev/null
+++ b/python/testData/refactoring/pullup/multiFile/Class.after.py
@@ -0,0 +1,4 @@
+from SuperClass import SuperClass
+
+class AnyClass(SuperClass):
+ pass
diff --git a/python/testData/refactoring/pullup/presenter/file.py b/python/testData/refactoring/pullup/presenter/file.py
new file mode 100644
index 0000000..5caadf0
--- /dev/null
+++ b/python/testData/refactoring/pullup/presenter/file.py
@@ -0,0 +1,62 @@
+from datetime import datetime
+from datetime import date
+
+class MainParent(object):
+ pass
+
+class SubParent1(MainParent):
+ def foo(self):
+ pass
+ pass
+
+class SubParent2(MainParent):
+ pass
+
+class Child(SubParent1, SubParent2):
+ def spam(self):
+ pass
+ pass
+
+class NoParentsAllowed(datetime, object):
+ def foo(self):
+ pass
+ pass
+
+
+class NoMembers(object):
+ pass
+
+class BadMro(MainParent, object, SubParent1, SubParent2):
+ pass
+
+class HugeChild(SubParent1, date): #SubParent1 is disabled
+ 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
+ pass
+ def bar(self):
+ pass
+
+ @classmethod
+ def static_1(cls): # Could be abstract in Py3K
+ pass
+
+ @staticmethod
+ def static_2(): # Could be abstract in Py3K
+ pass
+
+
+ @staticmethod
+ def bad_method(): #Code has errors, so method should be not be marked as static
+ pass
+
+class Bar(object):
+ C = 1
+
+class Foo(Bar):
+ def __init__(self):
+ self.foo = 12
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/severalParents.after.py b/python/testData/refactoring/pullup/severalParents.after.py
new file mode 100644
index 0000000..cd45e22
--- /dev/null
+++ b/python/testData/refactoring/pullup/severalParents.after.py
@@ -0,0 +1,13 @@
+class Spam:
+ pass
+
+class Parent_1(object, Spam):
+ pass
+
+
+class Parent_2():
+ pass
+
+
+class Child(Parent_1, Parent_2):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/severalParents.py b/python/testData/refactoring/pullup/severalParents.py
new file mode 100644
index 0000000..2c5f7a1
--- /dev/null
+++ b/python/testData/refactoring/pullup/severalParents.py
@@ -0,0 +1,13 @@
+class Spam:
+ pass
+
+class Parent_1(object):
+ pass
+
+
+class Parent_2():
+ pass
+
+
+class Child(Parent_1, Parent_2, Spam):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pullup/withComments.after.py b/python/testData/refactoring/pullup/withComments.after.py
index ce91117..d2d920f 100644
--- a/python/testData/refactoring/pullup/withComments.after.py
+++ b/python/testData/refactoring/pullup/withComments.after.py
@@ -2,8 +2,10 @@
def foo(self):
print("a")
- # this is boo
def boo(self):
+ """
+ In python we use multi-line comments inside of method body
+ """
print "rrrrr"
diff --git a/python/testData/refactoring/pullup/withComments.py b/python/testData/refactoring/pullup/withComments.py
index 32edbc3..a044302 100644
--- a/python/testData/refactoring/pullup/withComments.py
+++ b/python/testData/refactoring/pullup/withComments.py
@@ -3,6 +3,8 @@
print("a")
class Boo(Foo):
- # this is boo
def boo(self):
+ """
+ In python we use multi-line comments inside of method body
+ """
print "rrrrr"
\ No newline at end of file
diff --git a/python/testData/refactoring/pushdown/existingmethod.after.py b/python/testData/refactoring/pushdown/existingmethod.after.py
index 25daa38..b396cd5 100644
--- a/python/testData/refactoring/pushdown/existingmethod.after.py
+++ b/python/testData/refactoring/pushdown/existingmethod.after.py
@@ -1,5 +1,7 @@
class Foo:
+ pass
-class Boo():
+
+class Boo(Foo):
def foo(self):
print "rrrrr"
\ No newline at end of file
diff --git a/python/testData/refactoring/pushdown/full.after.py b/python/testData/refactoring/pushdown/full.after.py
new file mode 100644
index 0000000..0845450
--- /dev/null
+++ b/python/testData/refactoring/pushdown/full.after.py
@@ -0,0 +1,48 @@
+class Dummny(object):
+ pass
+
+
+class Parent(object):
+ """
+ This class is usefull.
+ """
+ CLASS_VAR_2 = 2
+
+ def __init__(self): pass
+
+
+ def method_2(self):
+ i = 1
+
+
+class Child_1(Parent, Dummny):
+ CLASS_VAR_1 = 1
+
+ def __init__(self):
+ self.inst_var = 12
+ self.bar = 64
+
+ def method_1(self):
+ """
+ Some text
+ """
+ pass
+
+
+class Child_2(Parent, Dummny):
+ """
+ This class implements most sophisticated algorithm
+ """
+ CLASS_VAR_1 = 1
+
+ def __init__(self):
+ self.inst_var = 12
+
+ def lala(self):
+ pass
+
+ def method_1(self):
+ """
+ Some text
+ """
+ pass
diff --git a/python/testData/refactoring/pushdown/full.before.py b/python/testData/refactoring/pushdown/full.before.py
new file mode 100644
index 0000000..30b205b
--- /dev/null
+++ b/python/testData/refactoring/pushdown/full.before.py
@@ -0,0 +1,37 @@
+class Dummny(object):
+ pass
+
+
+class Parent(object, Dummny):
+ """
+ This class is usefull.
+ """
+ CLASS_VAR_1 = 1
+ CLASS_VAR_2 = 2
+
+ def __init__(self):
+ self.inst_var = 12
+
+
+ def method_1(self):
+ """
+ Some text
+ """
+ pass
+
+ def method_2(self):
+ i = 1
+
+
+class Child_1(Parent):
+ def __init__(self):
+ self.bar = 64
+ pass
+
+
+class Child_2(Parent):
+ """
+ This class implements most sophisticated algorithm
+ """
+ def lala(self):
+ pass
diff --git a/python/testData/refactoring/pushdown/multiFileImports/child_module.after.py b/python/testData/refactoring/pushdown/multiFileImports/child_module.after.py
new file mode 100644
index 0000000..020596c
--- /dev/null
+++ b/python/testData/refactoring/pushdown/multiFileImports/child_module.after.py
@@ -0,0 +1,7 @@
+from parent_module import Parent
+from shared_module import module_function
+
+
+class Child(Parent):
+ def should_be_pushed(self):
+ module_function()
\ No newline at end of file
diff --git a/python/testData/refactoring/pushdown/multiFileImports/child_module.py b/python/testData/refactoring/pushdown/multiFileImports/child_module.py
new file mode 100644
index 0000000..86716f1
--- /dev/null
+++ b/python/testData/refactoring/pushdown/multiFileImports/child_module.py
@@ -0,0 +1,4 @@
+from parent_module import Parent
+
+class Child(Parent):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pushdown/multiFileImports/parent_module.after.py b/python/testData/refactoring/pushdown/multiFileImports/parent_module.after.py
new file mode 100644
index 0000000..b63dd44
--- /dev/null
+++ b/python/testData/refactoring/pushdown/multiFileImports/parent_module.after.py
@@ -0,0 +1,2 @@
+class Parent(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/pushdown/multiFileImports/parent_module.py b/python/testData/refactoring/pushdown/multiFileImports/parent_module.py
new file mode 100644
index 0000000..aeeb449
--- /dev/null
+++ b/python/testData/refactoring/pushdown/multiFileImports/parent_module.py
@@ -0,0 +1,6 @@
+from shared_module import module_function
+
+
+class Parent(object):
+ def should_be_pushed(self):
+ module_function()
\ No newline at end of file
diff --git a/python/testData/refactoring/pushdown/multiFileImports/shared_module.py b/python/testData/refactoring/pushdown/multiFileImports/shared_module.py
new file mode 100644
index 0000000..13fe833
--- /dev/null
+++ b/python/testData/refactoring/pushdown/multiFileImports/shared_module.py
@@ -0,0 +1,9 @@
+MODULE_CONTANT = 42
+
+
+def module_function():
+ pass
+
+
+class ModuleClass(object):
+ pass
\ No newline at end of file
diff --git a/python/testData/refactoring/unwrap/ifInIfUnwrap_after.py b/python/testData/refactoring/unwrap/ifInIfUnwrap_after.py
index 68407fb..1473f8f 100644
--- a/python/testData/refactoring/unwrap/ifInIfUnwrap_after.py
+++ b/python/testData/refactoring/unwrap/ifInIfUnwrap_after.py
@@ -1,4 +1,4 @@
if False:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/ifInIfUnwrap_before.py b/python/testData/refactoring/unwrap/ifInIfUnwrap_before.py
index 2bb897c..4e4fa45 100644
--- a/python/testData/refactoring/unwrap/ifInIfUnwrap_before.py
+++ b/python/testData/refactoring/unwrap/ifInIfUnwrap_before.py
@@ -1,5 +1,5 @@
if False:
if True:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/ifInWhileUnwrap_after.py b/python/testData/refactoring/unwrap/ifInWhileUnwrap_after.py
index a3de7bd..61a8c67 100644
--- a/python/testData/refactoring/unwrap/ifInWhileUnwrap_after.py
+++ b/python/testData/refactoring/unwrap/ifInWhileUnwrap_after.py
@@ -1,4 +1,4 @@
while False:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/ifInWhileUnwrap_before.py b/python/testData/refactoring/unwrap/ifInWhileUnwrap_before.py
index a612cbc..b47a4d5 100644
--- a/python/testData/refactoring/unwrap/ifInWhileUnwrap_before.py
+++ b/python/testData/refactoring/unwrap/ifInWhileUnwrap_before.py
@@ -1,5 +1,5 @@
while False:
if True:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/whileInIfUnwrap_after.py b/python/testData/refactoring/unwrap/whileInIfUnwrap_after.py
index 02d1de0..a855afb 100644
--- a/python/testData/refactoring/unwrap/whileInIfUnwrap_after.py
+++ b/python/testData/refactoring/unwrap/whileInIfUnwrap_after.py
@@ -1,4 +1,4 @@
if True:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/whileInIfUnwrap_before.py b/python/testData/refactoring/unwrap/whileInIfUnwrap_before.py
index 3fb06a2..ddd29ac 100644
--- a/python/testData/refactoring/unwrap/whileInIfUnwrap_before.py
+++ b/python/testData/refactoring/unwrap/whileInIfUnwrap_before.py
@@ -1,5 +1,5 @@
if True:
while False:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/whileInWhileUnwrap_after.py b/python/testData/refactoring/unwrap/whileInWhileUnwrap_after.py
index d5a3c2b..fc23ac4 100644
--- a/python/testData/refactoring/unwrap/whileInWhileUnwrap_after.py
+++ b/python/testData/refactoring/unwrap/whileInWhileUnwrap_after.py
@@ -1,4 +1,4 @@
while True:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/refactoring/unwrap/whileInWhileUnwrap_before.py b/python/testData/refactoring/unwrap/whileInWhileUnwrap_before.py
index 631003f..a7cb503 100644
--- a/python/testData/refactoring/unwrap/whileInWhileUnwrap_before.py
+++ b/python/testData/refactoring/unwrap/whileInWhileUnwrap_before.py
@@ -1,5 +1,5 @@
while True:
while False:
- #comment
+ # comment
x = 1<caret>
y = 2
diff --git a/python/testData/wrap/DontWrapStartOfString.after.py b/python/testData/wrap/DontWrapStartOfString.after.py
new file mode 100644
index 0000000..f3fc48a
--- /dev/null
+++ b/python/testData/wrap/DontWrapStartOfString.after.py
@@ -0,0 +1,2 @@
+call_command(' '
+ 'regressiontests_some_long_text_here_to_test_right_margin_some_long_text_here_to_test_right_margin_some_long_text_here_to_test_right_margin')
\ No newline at end of file
diff --git a/python/testData/wrap/DontWrapStartOfString.py b/python/testData/wrap/DontWrapStartOfString.py
new file mode 100644
index 0000000..06905d2
--- /dev/null
+++ b/python/testData/wrap/DontWrapStartOfString.py
@@ -0,0 +1 @@
+call_command(' regressiontests<caret>')
\ No newline at end of file
diff --git a/python/testData/wrap/wrapRightMargin.after.py b/python/testData/wrap/wrapRightMargin.after.py
index b7ed9d5..1d20b40 100644
--- a/python/testData/wrap/wrapRightMargin.after.py
+++ b/python/testData/wrap/wrapRightMargin.after.py
@@ -1,4 +1,4 @@
def do_stuff():
another_long_variable = a_really_long_function_name_with_parameters(12,
this_is_the_first_param=23,
- this_is_the_second=45).do_more_stuff_to_the_result()
+ this_is_the_second=45).do_more_stuff_to_the_result()
diff --git a/python/testSrc/com/jetbrains/python/PyAutoUnindentTest.java b/python/testSrc/com/jetbrains/python/PyAutoUnindentTest.java
index 18fdeec..995ab6a 100644
--- a/python/testSrc/com/jetbrains/python/PyAutoUnindentTest.java
+++ b/python/testSrc/com/jetbrains/python/PyAutoUnindentTest.java
@@ -17,7 +17,7 @@
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.lookup.LookupElement;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.PsiFile;
import com.jetbrains.python.fixtures.PyTestCase;
@@ -78,7 +78,7 @@
private void doTyping(final char character) {
final int offset = myFixture.getEditor().getCaretModel().getOffset();
- final PsiFile file = ApplicationManager.getApplication().runWriteAction(new Computable<PsiFile>() {
+ final PsiFile file = WriteCommandAction.runWriteCommandAction(null, new Computable<PsiFile>() {
@Override
public PsiFile compute() {
myFixture.getEditor().getCaretModel().moveToOffset(offset);
diff --git a/python/testSrc/com/jetbrains/python/PyDeprecationTest.java b/python/testSrc/com/jetbrains/python/PyDeprecationTest.java
index 450a99b..dffa4bc 100644
--- a/python/testSrc/com/jetbrains/python/PyDeprecationTest.java
+++ b/python/testSrc/com/jetbrains/python/PyDeprecationTest.java
@@ -15,6 +15,7 @@
*/
package com.jetbrains.python;
+import com.intellij.testFramework.PlatformTestUtil;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.inspections.PyDeprecationInspection;
import com.jetbrains.python.psi.PyFile;
@@ -43,9 +44,13 @@
public void testFunctionStub() {
myFixture.configureByFile("deprecation/functionStub.py");
- PyFunction getstatus = ((PyFile) myFixture.getFile()).findTopLevelFunction("getstatus");
- assertEquals("commands.getstatus() is deprecated", getstatus.getDeprecationMessage());
- assertNotParsed((PyFile) myFixture.getFile());
+ PyFile file = (PyFile)myFixture.getFile();
+ assertEquals("commands.getstatus() is deprecated", file.findTopLevelFunction("getstatus").getDeprecationMessage());
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+ assertNotParsed(file);
+
+ assertEquals("commands.getstatus() is deprecated", file.findTopLevelFunction("getstatus").getDeprecationMessage());
+ assertNotParsed(file);
}
public void testDeprecatedAsFallback() {
@@ -68,7 +73,13 @@
public void testFileStub() {
myFixture.configureByFile("deprecation/deprecatedModule.py");
- assertEquals("the deprecated module is deprecated; use a non-deprecated module instead", ((PyFile) myFixture.getFile()).getDeprecationMessage());
- assertNotParsed((PyFile) myFixture.getFile());
+ PyFile file = (PyFile)myFixture.getFile();
+ assertEquals("the deprecated module is deprecated; use a non-deprecated module instead", file.getDeprecationMessage());
+ PlatformTestUtil.tryGcSoftlyReachableObjects();
+ assertNotParsed(file);
+
+ assertEquals("the deprecated module is deprecated; use a non-deprecated module instead", file.getDeprecationMessage());
+ assertNotParsed(file);
+
}
}
diff --git a/python/testSrc/com/jetbrains/python/PyEditingTest.java b/python/testSrc/com/jetbrains/python/PyEditingTest.java
index 5f0e7c2..46a4af9 100644
--- a/python/testSrc/com/jetbrains/python/PyEditingTest.java
+++ b/python/testSrc/com/jetbrains/python/PyEditingTest.java
@@ -20,8 +20,8 @@
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
-import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable;
import com.intellij.openapi.util.Computable;
@@ -332,7 +332,7 @@
}
private String doTestTyping(final String text, final int offset, final char character) {
- final PsiFile file = ApplicationManager.getApplication().runWriteAction(new Computable<PsiFile>() {
+ final PsiFile file = WriteCommandAction.runWriteCommandAction(null, new Computable<PsiFile>() {
@Override
public PsiFile compute() {
final PsiFile file = myFixture.configureByText(PythonFileType.INSTANCE, text);
@@ -353,7 +353,7 @@
private void doTyping(final char character) {
final int offset = myFixture.getEditor().getCaretModel().getOffset();
- final PsiFile file = ApplicationManager.getApplication().runWriteAction(new Computable<PsiFile>() {
+ final PsiFile file = WriteCommandAction.runWriteCommandAction(null, new Computable<PsiFile>() {
@Override
public PsiFile compute() {
myFixture.getEditor().getCaretModel().moveToOffset(offset);
diff --git a/python/testSrc/com/jetbrains/python/PyFormatterTest.java b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
index 2fdd39c..3983689 100644
--- a/python/testSrc/com/jetbrains/python/PyFormatterTest.java
+++ b/python/testSrc/com/jetbrains/python/PyFormatterTest.java
@@ -15,7 +15,7 @@
*/
package com.jetbrains.python;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
@@ -251,7 +251,7 @@
" desired_response_parameters,\n" +
" inverse_filter_length, \n" +
" observed_impulse_response):\n" +
- " # Extract from here to ...\n" +
+ " # Extract from here to ...\n" +
" desired_impulse_response = {'dirac, 'gaussian', logistic_derivative'}\n" +
"return desired, o";
@@ -264,7 +264,7 @@
" desired_response_parameters,\n" +
" inverse_filter_length,\n" +
" observed_impulse_response):\n" +
- " # Extract from here to ...\n" +
+ " # Extract from here to ...\n" +
" desired_impulse_response = {'dirac, '\n" +
" gaussian\n" +
" ', logistic_derivative'}\n" +
@@ -394,13 +394,17 @@
doTest();
}
+ public void testAlignListComprehensionInDict() { //PY-10076
+ doTest();
+ }
+
private void doTest() {
doTest(false);
}
private void doTest(final boolean reformatText) {
myFixture.configureByFile("formatter/" + getTestName(true) + ".py");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
CodeStyleManager codeStyleManager = CodeStyleManager.getInstance(myFixture.getProject());
diff --git a/python/testSrc/com/jetbrains/python/PyJoinLinesTest.java b/python/testSrc/com/jetbrains/python/PyJoinLinesTest.java
index 699e8c7..856ddb7 100644
--- a/python/testSrc/com/jetbrains/python/PyJoinLinesTest.java
+++ b/python/testSrc/com/jetbrains/python/PyJoinLinesTest.java
@@ -16,8 +16,7 @@
package com.jetbrains.python;
import com.intellij.codeInsight.editorActions.JoinRawLinesHandlerDelegate;
-import com.intellij.openapi.application.Result;
-import com.intellij.openapi.application.WriteAction;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.jetbrains.python.editor.PyJoinLinesHandler;
@@ -46,12 +45,12 @@
while (" \n\t".indexOf(text.charAt(i)) >= 0) i += 1;
final int end = i;
final JoinRawLinesHandlerDelegate handler = new PyJoinLinesHandler();
- new WriteAction() {
+ WriteCommandAction.runWriteCommandAction(myFixture.getProject(), new Runnable() {
@Override
- protected void run(Result result) throws Throwable {
+ public void run() {
handler.tryJoinRawLines(doc, myFixture.getFile(), start, end);
}
- }.execute().throwException();
+ });
myFixture.checkResultByFile(path + getTestName(false) + "-after.py");
}
diff --git a/python/testSrc/com/jetbrains/python/PyRequirementTest.java b/python/testSrc/com/jetbrains/python/PyRequirementTest.java
index 18e6bdd..75fb9a5 100644
--- a/python/testSrc/com/jetbrains/python/PyRequirementTest.java
+++ b/python/testSrc/com/jetbrains/python/PyRequirementTest.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.
diff --git a/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java b/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java
index 2be57da..c79b37b 100644
--- a/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java
+++ b/python/testSrc/com/jetbrains/python/PyStringLiteralTest.java
@@ -130,6 +130,10 @@
assertEquals("\\u0041", createLiteralFromText("b'\\u0041'").getStringValue());
}
+ public void testNonUnicodeCodePointValue() {
+ assertEquals("\\U12345678", createLiteralFromText("u'\\U12345678'").getStringValue());
+ }
+
private static String decodeRange(PyStringLiteralExpression expr, TextRange range) {
final StringBuilder builder = new StringBuilder();
expr.createLiteralTextEscaper().decode(range, builder);
diff --git a/python/testSrc/com/jetbrains/python/PyStructureViewTest.java b/python/testSrc/com/jetbrains/python/PyStructureViewTest.java
index 7556d0f..b1ed603 100644
--- a/python/testSrc/com/jetbrains/python/PyStructureViewTest.java
+++ b/python/testSrc/com/jetbrains/python/PyStructureViewTest.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,7 +25,7 @@
* @author vlan
*/
public class PyStructureViewTest extends PyTestCase {
- private static String TEST_DIRECTORY = "structureView/";
+ private static final String TEST_DIRECTORY = "structureView/";
public void testBaseClassNames() {
myFixture.configureByFiles(TEST_DIRECTORY + "baseClassNames.py",
diff --git a/python/testSrc/com/jetbrains/python/PyWrapTest.java b/python/testSrc/com/jetbrains/python/PyWrapTest.java
index 39606c3..05c21b8 100644
--- a/python/testSrc/com/jetbrains/python/PyWrapTest.java
+++ b/python/testSrc/com/jetbrains/python/PyWrapTest.java
@@ -64,6 +64,10 @@
doTest(" AND field");
}
+ public void testDontWrapStartOfString() { // PY-9436
+ doTest("_some_long_text_here_to_test_right_margin_some_long_text_here_to_test_right_margin_some_long_text_here_to_test_right_margin");
+ }
+
public void testWrapRightMargin() {
final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(myFixture.getProject()).getCurrentSettings();
@@ -83,7 +87,6 @@
settings.RIGHT_MARGIN = oldValue;
settings.WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN = oldMarginValue;
}
-
}
private void doTest(final String textToType) {
diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
index 9f612a2..f50257c 100644
--- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java
+++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java
@@ -16,10 +16,15 @@
package com.jetbrains.python;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.testFramework.ParsingTestCase;
import com.intellij.testFramework.TestDataPath;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyFunction;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
/**
* @author yole
@@ -220,7 +225,7 @@
}
public void testTrailingSemicolon() { // PY-363
- doTest();
+ doTest();
}
public void testStarExpression() { // PEP-3132
@@ -251,6 +256,10 @@
doTest();
}
+ public void testBadDecoratorNotMethod() {
+ doTest();
+ }
+
public void testCommentAtEndOfMethod() { // PY-2137
doTest();
}
@@ -318,7 +327,7 @@
public void testIncompleteFor() { // PY-3792
doTest();
}
-
+
public void testCallInAssignment() { // PY-5062
doTest();
}
@@ -447,6 +456,7 @@
finally {
myLanguageLevel = prev;
}
+ ensureEachFunctionHasStatementList(myFile, PyFunction.class);
}
@Override
@@ -455,4 +465,13 @@
file.getVirtualFile().putUserData(LanguageLevel.KEY, myLanguageLevel);
return file;
}
+
+ public static <T extends PyFunction> void ensureEachFunctionHasStatementList(
+ @NotNull PsiFile parentFile,
+ @NotNull Class<T> functionType) {
+ Collection<T> functions = PsiTreeUtil.findChildrenOfType(parentFile, functionType);
+ for (T functionToCheck : functions) {
+ functionToCheck.getStatementList(); //To make sure each function has statement list (does not throw exception)
+ }
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/fixtures/PyMultiFileResolveTestCase.java b/python/testSrc/com/jetbrains/python/fixtures/PyMultiFileResolveTestCase.java
index 431bf28..22b4e54 100644
--- a/python/testSrc/com/jetbrains/python/fixtures/PyMultiFileResolveTestCase.java
+++ b/python/testSrc/com/jetbrains/python/fixtures/PyMultiFileResolveTestCase.java
@@ -44,17 +44,13 @@
FileType fileType = file.getFileType();
return fileType == PythonFileType.INSTANCE;
}
- });
- try {
- final ResolveResult[] resolveResults = ref.multiResolve(false);
- if (resolveResults.length == 0) {
- return null;
- }
- return resolveResults[0].isValidResult() ? resolveResults[0].getElement() : null;
+ }, myTestRootDisposable);
+ final ResolveResult[] resolveResults = ref.multiResolve(false);
+ psiManager.setAssertOnFileLoadingFilter(VirtualFileFilter.NONE, myTestRootDisposable);
+ if (resolveResults.length == 0) {
+ return null;
}
- finally {
- psiManager.setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
- }
+ return resolveResults[0].isValidResult() ? resolveResults[0].getElement() : null;
}
diff --git a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java
index 0e09054..0b15d89 100644
--- a/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java
+++ b/python/testSrc/com/jetbrains/python/inspections/PyTypeCheckerInspectionTest.java
@@ -232,4 +232,9 @@
public void testMetaClassIteration() {
doTest();
}
+
+ // PY-10967
+ public void testDefaultTupleParameter() {
+ doTest();
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/psi/impl/PyArgumentListImplTest.java b/python/testSrc/com/jetbrains/python/psi/impl/PyArgumentListImplTest.java
new file mode 100644
index 0000000..7aa1a5c
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/psi/impl/PyArgumentListImplTest.java
@@ -0,0 +1,89 @@
+package com.jetbrains.python.psi.impl;
+
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.psi.impl.source.PostprocessReformattingAspect;
+import com.intellij.psi.util.PsiTreeUtil;
+import com.jetbrains.python.psi.*;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringTest;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Tests {@link com.jetbrains.python.psi.impl.PyArgumentListImpl#addArgument(com.jetbrains.python.psi.PyExpression)}
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyArgumentListImplTest extends PyClassRefactoringTest {
+ private PyElementGeneratorImpl myGenerator;
+ private LanguageLevel myLanguagelevel;
+
+ public PyArgumentListImplTest() {
+ super("argumentList");
+ }
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myGenerator = new PyElementGeneratorImpl(myFixture.getProject());
+ myLanguagelevel = LanguageLevel.PYTHON34;
+ setLanguageLevel(myLanguagelevel);
+ }
+
+ /**
+ * Ensures new keyword argument is set into appropriate place
+ */
+ public void testAddKeyArgument() throws Exception {
+ final PyKeywordArgument classKeyword = myGenerator.createKeywordArgument(myLanguagelevel, "metaclass", "ABCMeta");
+ final PyKeywordArgument functionKeyword = myGenerator.createKeywordArgument(myLanguagelevel, "new_param", "spam");
+
+
+ doTest(classKeyword, functionKeyword);
+ }
+
+ /**
+ * Ensures new param (NOT keyword argument) is set into appropriate place
+ */
+ public void testAddParam() throws Exception {
+ final PyExpression classParameter = myGenerator.createParameter("SuperClass");
+ final PyExpression functionParameter = myGenerator.createParameter("new_param");
+
+
+ doTest(classParameter, functionParameter);
+ }
+
+ /**
+ * Adds expressions to the superclass list and to the function calls in file
+ *
+ * @param superClassExpression expressions to add to the list of superclasses to any class found on file
+ * @param functionExpression expressions to add to any function call found in file
+ */
+ private void doTest(@NotNull final PyExpression superClassExpression, @NotNull final PyExpression functionExpression) {
+ configureMultiFile("addArgumentFile", "stub");
+ myFixture.configureByFile(getMultiFileBaseName() + "/addArgumentFile.py");
+
+ //TODO: newly created expressions has no indent info, it leads to errors in postprocessing formatting. Need to investigate.
+ PostprocessReformattingAspect.getInstance(myFixture.getProject()).disablePostprocessFormattingInside(new Runnable() {
+ @Override
+ public void run() {
+ WriteCommandAction.runWriteCommandAction(myFixture.getProject(), new Runnable() {
+ @Override
+ public void run() {
+
+
+ for (final PyClass aClass : PsiTreeUtil.findChildrenOfType(myFixture.getFile(), PyClass.class)) {
+ final PyArgumentList superClassExpressionList = aClass.getSuperClassExpressionList();
+ assert superClassExpressionList != null : "Class has no expression list!";
+ superClassExpressionList.addArgument(superClassExpression);
+ }
+
+ for (final PyCallExpression expression : PsiTreeUtil.findChildrenOfType(myFixture.getFile(), PyCallExpression.class)) {
+ final PyArgumentList list = expression.getArgumentList();
+ assert list != null : "Callable statement has no argument list?";
+ list.addArgument(functionExpression);
+ }
+ }
+ });
+ }
+ });
+ myFixture.checkResultByFile(getMultiFileBaseName() + "/addArgumentFile.after.py");
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java
index ac05633..8b6f81b 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyCodeFragmentTest.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.
diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceTestCase.java b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceTestCase.java
index e949656..82efe37 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceTestCase.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/PyIntroduceTestCase.java
@@ -17,6 +17,7 @@
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
@@ -88,9 +89,15 @@
}
handler.performAction(introduceOperation);
- TemplateState state = TemplateManagerImpl.getTemplateState(myFixture.getEditor());
- assert state != null;
- state.gotoEnd(false);
+ WriteCommandAction.runWriteCommandAction(myFixture.getProject(), new Runnable() {
+ @Override
+ public void run() {
+ TemplateState state = TemplateManagerImpl.getTemplateState(myFixture.getEditor());
+ assert state != null;
+ state.gotoEnd(false);
+ }
+ });
+
myFixture.checkResultByFile(name + ".after.py", true);
}
finally {
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/NameAndStatusTransformer.java b/python/testSrc/com/jetbrains/python/refactoring/classes/NameAndStatusTransformer.java
new file mode 100644
index 0000000..8d80445
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/NameAndStatusTransformer.java
@@ -0,0 +1,24 @@
+package com.jetbrains.python.refactoring.classes;
+
+import com.google.common.base.Function;
+import com.intellij.refactoring.classMembers.MemberInfoModel;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+/**
+* @author Ilya.Kazakevich
+*/
+public class NameAndStatusTransformer implements Function<PyMemberInfo<PyElement>, PyPresenterTestMemberEntry> {
+ @NotNull
+ private final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> myMemberInfoModel;
+
+ public NameAndStatusTransformer(@NotNull final MemberInfoModel<PyElement, PyMemberInfo<PyElement>> memberInfoModel) {
+ myMemberInfoModel = memberInfoModel;
+ }
+
+ @Override
+ public PyPresenterTestMemberEntry apply(final PyMemberInfo<PyElement> input) {
+ return new PyPresenterTestMemberEntry(input.getDisplayName(), myMemberInfoModel.isMemberEnabled(input), input.isStatic(), myMemberInfoModel.isAbstractEnabled(input));
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java
index dbdca0d..c47935d 100644
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyClassRefactoringTest.java
@@ -15,12 +15,21 @@
*/
package com.jetbrains.python.refactoring.classes;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.project.Project;
+import com.intellij.refactoring.BaseRefactoringProcessor;
import com.jetbrains.python.fixtures.PyTestCase;
import com.jetbrains.python.psi.PyClass;
import com.jetbrains.python.psi.PyElement;
import com.jetbrains.python.psi.PyFunction;
+import com.jetbrains.python.psi.PyTargetExpression;
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
+import com.jetbrains.python.refactoring.classes.membersManager.MembersManager;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
import java.util.Collection;
@@ -28,22 +37,126 @@
* @author Dennis.Ushakov
*/
public abstract class PyClassRefactoringTest extends PyTestCase {
- protected PyElement findMember(String className, String memberName) {
- if (!memberName.contains(".")) return findClass(memberName);
- return findMethod(className, memberName.substring(1));
+ @NotNull
+ private final String myRefactoringName;
+
+ /**
+ * @param refactoringName name of the refactoring. It will be used as folder name for tests
+ */
+ protected PyClassRefactoringTest(@NotNull final String refactoringName) {
+ myRefactoringName = refactoringName;
+ }
+
+ /**
+ * Finds memberInfo by class name and member name.
+ *
+ * @param clazzName name of class
+ * @param memberName name of member (See {@link #findMember(String, String)} for naming protocol)
+ * @return member info
+ * @see #findMember(String, String)
+ */
+ @NotNull
+ protected PyMemberInfo<PyElement> findMemberInfo(@NotNull final String clazzName, @NotNull final String memberName) {
+ final PyClass clazz = findClass(clazzName);
+ return MembersManager.findMember(clazz, findMember(clazzName, memberName));
+ }
+
+ /**
+ * @param className class where member should be found
+ * @param memberName member that starts with dot (<code>.</code>) is treated as method.
+ * member that starts with dash (<code>#</code>) is treated as attribute.
+ * It is treated parent class otherwise
+ * @return member or null if not found
+ */
+ @NotNull
+ protected PyElement findMember(@NotNull final String className, @NotNull String memberName) {
+ final PyElement result;
+ //TODO: Get rid of this chain of copy pastes
+ if (memberName.contains(".")) {
+ result = findMethod(className, memberName.substring(1));
+ }
+ else if (memberName.contains("#")) {
+ result = findField(className, memberName.substring(1));
+ }
+ else {
+ result = findClass(memberName);
+ }
+ Assert.assertNotNull(String.format("No member %s found in class %s", memberName, className), result);
+ return result;
+ }
+
+ private PyElement findField(final String className, final String memberName) {
+ final PyClass aClass = findClass(className);
+ final PyTargetExpression attribute = aClass.findClassAttribute(memberName, false);
+ if (attribute != null) {
+ return attribute;
+ }
+ return aClass.findInstanceAttribute(memberName, false);
}
private PyFunction findMethod(final String className, final String name) {
final PyClass clazz = findClass(className);
- final PyFunction method = clazz.findMethodByName(name, false);
- assertNotNull(method);
- return method;
+ return clazz.findMethodByName(name, false);
}
protected PyClass findClass(final String name) {
final Project project = myFixture.getProject();
final Collection<PyClass> classes = PyClassNameIndex.find(name, project, false);
- assertEquals(1, classes.size());
+ Assert.assertThat(String.format("Expected one class named %s", name), classes, Matchers.hasSize(1));
return classes.iterator().next();
}
+
+
+ protected void moveViaProcessor(@NotNull Project project, @NotNull final BaseRefactoringProcessor processor) {
+ CommandProcessor.getInstance().executeCommand(project, new Runnable() {
+ @Override
+ public void run() {
+ ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ @Override
+ public void run() {
+ processor.run();
+ }
+ });
+ }
+ }, null, null);
+ }
+
+ /**
+ * Adds several files to project from folder {@link #myRefactoringName} with extension <pre>py</pre>.
+ * Call it <strong>before</strong> refactoring.
+ * After refactoring use {@link #checkMultiFile(String...)} to make sure refactoring is ok.
+ *
+ * @param fileNamesNoExtensions file (module) names to add with out of extensions
+ * @see #checkMultiFile(String...)
+ */
+ protected void configureMultiFile(@NotNull final String... fileNamesNoExtensions) {
+ final String baseName = getMultiFileBaseName() + "/";
+
+ for (final String fileNameNoExtension : fileNamesNoExtensions) {
+ final String fileNameBefore = String.format("%s.py", fileNameNoExtension);
+ myFixture.copyFileToProject(baseName + fileNameBefore, fileNameBefore);
+ }
+ }
+
+ /**
+ * Checks files <strong>after</strong> refactoring. See {@link #configureMultiFile(String...)} for more info.
+ *
+ * @param fileNamesNoExtensions file names to check with out of extension
+ * @see #configureMultiFile(String...)
+ */
+ protected void checkMultiFile(@NotNull final String... fileNamesNoExtensions) {
+ for (final String fileNameNoExtension : fileNamesNoExtensions) {
+ final String fileNameAfter = String.format("%s.after.py", fileNameNoExtension);
+ final String fileNameBefore = String.format("%s.py", fileNameNoExtension);
+ myFixture.checkResultByFile(fileNameBefore, "/" + getMultiFileBaseName() + "/" + fileNameAfter, true);
+ }
+ }
+
+ /**
+ * @return folder name with {@link #myRefactoringName} and test name added
+ */
+ @NotNull
+ protected String getMultiFileBaseName() {
+ return "refactoring/" + myRefactoringName + "/" + getTestName(true);
+ }
}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java
deleted file mode 100644
index cae5550..0000000
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyExtractSuperclassTest.java
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes;
-
-import com.intellij.openapi.command.WriteCommandAction;
-import com.intellij.openapi.vfs.LocalFileSystem;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
-import com.jetbrains.python.PyNames;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.extractSuperclass.PyExtractSuperclassHelper;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyExtractSuperclassTest extends PyClassRefactoringTest {
- public void testSimple() throws Exception {
- doSimpleTest("Foo", "Suppa", null, true, ".foo");
- }
-
- public void testWithSuper() throws Exception {
- doSimpleTest("Foo", "Suppa", null, true, ".foo");
- }
-
- public void testWithImport() throws Exception {
- doSimpleTest("A", "Suppa", null, false, ".foo");
- }
-
- private void doSimpleTest(final String className, final String superclassName, final String expectedError, final boolean sameFile, final String... membersName) throws Exception {
- try {
- String baseName = "/refactoring/extractsuperclass/" + getTestName(true);
- myFixture.configureByFile(baseName + ".before.py");
- final PyClass clazz = findClass(className);
- final List<PyMemberInfo> members = new ArrayList<PyMemberInfo>();
- for (String memberName : membersName) {
- final PyElement member = findMember(className, memberName);
- assertNotNull(member);
- members.add(new PyMemberInfo(member));
- }
-
- new WriteCommandAction.Simple(myFixture.getProject()) {
- @Override
- protected void run() throws Throwable {
- //noinspection ConstantConditions
- final String url = sameFile ? myFixture.getFile().getVirtualFile().getUrl() :
- myFixture.getFile().getVirtualFile().getParent().getUrl();
- PyExtractSuperclassHelper.extractSuperclass(clazz, members, superclassName, url);
- }
- }.execute();
- myFixture.checkResultByFile(baseName + ".after.py");
- } catch (Exception e) {
- if (expectedError == null) throw e;
- assertEquals(expectedError, e.getMessage());
- }
- }
-
-
- public void testMultifileNew() {
- String baseName = "/refactoring/extractsuperclass/multifile/";
- myFixture.configureByFile(baseName + "source.py");
- final String className = "Foo";
- final String superclassName = "Suppa";
- final PyClass clazz = findClass(className);
- final List<PyMemberInfo> members = new ArrayList<PyMemberInfo>();
- final PyElement member = findMember(className, ".foo");
- assertNotNull(member);
- members.add(new PyMemberInfo(member));
- final VirtualFile base_dir = myFixture.getFile().getVirtualFile().getParent();
-
- new WriteCommandAction.Simple(myFixture.getProject()) {
- @Override
- protected void run() throws Throwable {
- //noinspection ConstantConditions
- final String path = base_dir.getPath() + "/a/b";
- PyExtractSuperclassHelper.extractSuperclass(clazz, members, superclassName, path);
- }
- }.execute();
- final PsiManager psi_mgr = PsiManager.getInstance(myFixture.getProject());
- VirtualFile vfile = base_dir.findChild("a");
- assertTrue(vfile.isDirectory());
- vfile = vfile.findChild(PyNames.INIT_DOT_PY);
- assertNotNull(vfile);
-
- vfile = base_dir.findChild("a").findChild("b");
- assertTrue(vfile.isDirectory());
- vfile = vfile.findChild(PyNames.INIT_DOT_PY);
- assertNotNull(vfile);
-
- PsiFile psi_file = psi_mgr.findFile(vfile);
- String result = psi_file.getText().trim();
- File expected_file = new File(getTestDataPath() + baseName, "target.new.py");
- String expected = psi_mgr.findFile(LocalFileSystem.getInstance().findFileByIoFile(expected_file)).getText().trim();
- assertEquals(expected, result);
- }
-
- public void testMultifileAppend() {
- // this is half-copy-paste of testMultifileNew. generalization won't make either easier to follow.
- String baseName = "/refactoring/extractsuperclass/multifile/";
- myFixture.configureByFiles(
- baseName + "source.py",
- baseName + "a/__init__.py",
- baseName + "a/b/__init__.py",
- baseName + "a/b/foo.py"
- );
- final String className = "Foo";
- final String superclassName = "Suppa";
- final PyClass clazz = findClass(className);
- final List<PyMemberInfo> members = new ArrayList<PyMemberInfo>();
- final PyElement member = findMember(className, ".foo");
- assertNotNull(member);
- members.add(new PyMemberInfo(member));
- final VirtualFile base_dir = myFixture.getFile().getVirtualFile().getParent();
-
- new WriteCommandAction.Simple(myFixture.getProject()) {
- @Override
- protected void run() throws Throwable {
- //noinspection ConstantConditions
- final String path = base_dir.getPath() + "/a/b";
- PyExtractSuperclassHelper.extractSuperclass(clazz, members, superclassName, path + "/foo.py");
- }
- }.execute();
- final PsiManager psi_mgr = PsiManager.getInstance(myFixture.getProject());
- VirtualFile vfile = base_dir.findChild("a");
- assertTrue(vfile.isDirectory());
- vfile = vfile.findChild(PyNames.INIT_DOT_PY);
- assertNotNull(vfile);
-
- vfile = base_dir.findChild("a").findChild("b");
- assertTrue(vfile.isDirectory());
- assertNotNull(vfile.findChild(PyNames.INIT_DOT_PY));
- vfile = vfile.findChild("foo.py");
- assertNotNull(vfile);
-
- PsiFile psi_file = psi_mgr.findFile(vfile);
- String result = psi_file.getText().trim();
- File expected_file = new File(getTestDataPath() + baseName, "target.append.py");
- String expected = psi_mgr.findFile(LocalFileSystem.getInstance().findFileByIoFile(expected_file)).getText().trim();
- assertEquals(expected, result);
- }
-
-}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPresenterTestMemberEntry.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPresenterTestMemberEntry.java
new file mode 100644
index 0000000..8518c45
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPresenterTestMemberEntry.java
@@ -0,0 +1,63 @@
+package com.jetbrains.python.refactoring.classes;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * Test only {@link com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo} representation.
+ * @author Ilya.Kazakevich
+ */
+public class PyPresenterTestMemberEntry {
+ @NonNls @NotNull
+ private final String myName;
+ private final boolean myEnabled;
+ private final boolean myStaticEntry;
+ private final boolean myMayBeAbstract;
+
+ /**
+ * @param name name of the member
+ * @param enabled is member enabled or not
+ * @param staticEntry is member static entry
+ * @param mayBeAbstract if element has "abstract" checkbox or not
+ */
+ public PyPresenterTestMemberEntry(@NotNull final String name, final boolean enabled, final boolean staticEntry, final boolean mayBeAbstract) {
+ myName = name;
+ myEnabled = enabled;
+ myStaticEntry = staticEntry;
+ myMayBeAbstract = mayBeAbstract;
+ }
+
+ @Override
+ public String toString() {
+ return "PyPresenterTestMemberEntry{" +
+ "myName='" + myName + '\'' +
+ ", myEnabled=" + myEnabled +
+ ", myStaticEntry=" + myStaticEntry +
+ ", myMayBeAbstract=" + myMayBeAbstract +
+ '}';
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (!(o instanceof PyPresenterTestMemberEntry)) return false;
+
+ final PyPresenterTestMemberEntry entry = (PyPresenterTestMemberEntry)o;
+
+ if (myEnabled != entry.myEnabled) return false;
+ if (myMayBeAbstract != entry.myMayBeAbstract) return false;
+ if (myStaticEntry != entry.myStaticEntry) return false;
+ if (!myName.equals(entry.myName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = myName.hashCode();
+ result = 31 * result + (myEnabled ? 1 : 0);
+ result = 31 * result + (myStaticEntry ? 1 : 0);
+ result = 31 * result + (myMayBeAbstract ? 1 : 0);
+ return result;
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java
deleted file mode 100644
index 80c6b24..0000000
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPullUpTest.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes;
-
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.pullUp.PyPullUpHelper;
-
-import java.util.Collections;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyPullUpTest extends PyClassRefactoringTest {
- public void testSimple() {
- doHelperTest("Boo", ".boo", "Foo");
- }
-
- public void testSuperclass() {
- doHelperTest("Boo", "Foo", "Zope");
- }
-
- public void testExistingsuperclass() {
- doHelperTest("Boo", "Foo", "Zope");
- }
-
- public void testWithComments() {
- doHelperTest("Boo", ".boo", "Foo");
- }
-
- public void testWithMultilineComments() {
- doHelperTest("Boo", ".boo", "Foo");
- }
-
- public void testMultiFile() { // PY-2810
- doMultiFileTest();
- }
-
- public void testDuplicateImport() { // PY-2810
- doMultiFileTest();
- }
-
- private void doMultiFileTest() {
- String baseName = "refactoring/pullup/" + getTestName(true) + "/";
- myFixture.copyFileToProject(baseName + "Class.py", "Class.py");
- myFixture.copyFileToProject(baseName + "SuperClass.py", "SuperClass.py");
- doPullUp("AnyClass", ".this_should_be_in_super", "SuperClass");
- myFixture.checkResultByFile("SuperClass.py", "/" + baseName + "/SuperClass.after.py", true);
- }
-
- private void doHelperTest(final String className, final String memberName, final String superClassName) {
- String baseName = "/refactoring/pullup/" + getTestName(true);
- myFixture.configureByFile(baseName + ".py");
- doPullUp(className, memberName, superClassName);
- myFixture.checkResultByFile(baseName + ".after.py");
- }
-
- private void doPullUp(String className, String memberName, String superClassName) {
- final PyClass clazz = findClass(className);
- final PyElement member = findMember(className, memberName);
- final PyClass superClass = findClass(superClassName);
- PyPullUpHelper.pullUp(clazz, Collections.singleton(new PyMemberInfo(member)), superClass);
- }
-}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java
deleted file mode 100644
index cc4ca07..0000000
--- a/python/testSrc/com/jetbrains/python/refactoring/classes/PyPushDownTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.jetbrains.python.refactoring.classes;
-
-import com.intellij.openapi.command.WriteCommandAction;
-import com.jetbrains.python.psi.PyClass;
-import com.jetbrains.python.psi.PyElement;
-import com.jetbrains.python.refactoring.classes.pushDown.PyPushDownProcessor;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Dennis.Ushakov
- */
-public class PyPushDownTest extends PyClassRefactoringTest {
- public void testSimple() throws Exception {
- doProcessorTest("Foo", null, ".foo");
- }
-
- public void testSuperclass() throws Exception {
- doProcessorTest("Zope", null, "Foo");
- }
-
- public void testMultiple() throws Exception {
- doProcessorTest("Foo", null, ".foo");
- }
-
- public void testPy346() throws Exception {
- doProcessorTest("A", null, ".meth_a1", ".meth_a2");
- }
-
- public void testExistingmethod() throws Exception {
- doProcessorTest("Foo", "method <b><code>foo</code></b> is already overridden in class <b><code>Boo</code></b>. Method will not be pushed down to that class.", ".foo");
- }
-
- private void doProcessorTest(final String className, final String expectedError, final String... membersName) throws Exception {
- try {
- String baseName = "/refactoring/pushdown/" + getTestName(true);
- myFixture.configureByFile(baseName + ".before.py");
- final PyClass clazz = findClass(className);
- final List<PyMemberInfo> members = new ArrayList<PyMemberInfo>();
- for (String memberName : membersName) {
- final PyElement member = findMember(className, memberName);
- assertNotNull(member);
- members.add(new PyMemberInfo(member));
- }
-
- final PyPushDownProcessor processor = new PyPushDownProcessor(myFixture.getProject(), clazz, members);
- new WriteCommandAction.Simple(myFixture.getProject()) {
- @Override
- protected void run() throws Throwable {
- processor.run();
- }
- }.execute().throwException();
- myFixture.checkResultByFile(baseName + ".after.py");
- } catch (Exception e) {
- if (expectedError == null) throw e;
- assertTrue(e.getMessage(), e.getMessage().contains(expectedError));
- }
- }
-}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/PyRefactoringPresenterTestCase.java b/python/testSrc/com/jetbrains/python/refactoring/classes/PyRefactoringPresenterTestCase.java
new file mode 100644
index 0000000..66c478e
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/PyRefactoringPresenterTestCase.java
@@ -0,0 +1,120 @@
+package com.jetbrains.python.refactoring.classes;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.jetbrains.python.fixtures.PyTestCase;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedView;
+import com.jetbrains.python.refactoring.classes.membersManager.vp.MembersViewInitializationInfo;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.internal.MocksControl;
+import org.hamcrest.Matcher;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.util.Collection;
+
+/**
+ * Base class for {@link com.jetbrains.python.refactoring.classes.membersManager.vp.MembersBasedPresenter} tests.
+ * It takes file <pre>file.py</pre> from folder provided as "refactoringName" constructor argument.
+ * It configures {@link #myView}
+ *
+ * @param <C> configuration class for presenter view
+ * @param <V> presenter's view class
+ * @author Ilya.Kazakevich
+ */
+public abstract class PyRefactoringPresenterTestCase<C extends MembersViewInitializationInfo, V extends MembersBasedView<C>>
+ extends PyTestCase {
+ /**
+ * Converts class collection to name collection
+ */
+ protected static final Function<PyClass, String> CLASS_TO_NAME = new ClassToName();
+ /**
+ * Easy mock control
+ */
+ protected MocksControl myMocksControl;
+ /**
+ * View mock
+ */
+ protected V myView;
+ /**
+ * Capture that stores config ({@link MembersViewInitializationInfo} or its children) after {@link com.jetbrains.python.vp.Presenter#launch()} is called
+ */
+ protected Capture<C> myViewConfigCapture;
+
+ @NotNull
+ private final Class<V> myViewClass;
+ @NotNull
+ private final String myRefactoringName;
+
+ /**
+ * @param viewClass view class
+ * @param refactoringName name of the refactoring. Folder with its name would be used to take "file.py" from it.
+ */
+ protected PyRefactoringPresenterTestCase(@NotNull final Class<V> viewClass, @NotNull final String refactoringName) {
+ myViewClass = viewClass;
+ this.myRefactoringName = refactoringName;
+ }
+
+
+ /**
+ * Compares member states (names and other fields) with provided matcher.
+ * @see PyPresenterTestMemberEntry
+ * @param members members to compare
+ * @param matcher to match them against
+ */
+ protected static void compareMembers(@NotNull final Collection<PyPresenterTestMemberEntry> members,
+ @NotNull final Matcher<Iterable<? extends PyPresenterTestMemberEntry>> matcher) {
+ Assert.assertThat("Wrong members or their states", members, matcher);
+ }
+
+ /**
+ * Initializes test. Always run it <strong>first</strong> if overwrite.
+ */
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+
+ myFixture.copyDirectoryToProject("refactoring/" + myRefactoringName + "/presenter/", "");
+ myFixture.configureFromTempProjectFile("file.py");
+ myMocksControl = new MocksControl(MocksControl.MockType.NICE);
+ myView = myMocksControl.createMock(myViewClass);
+
+ myViewConfigCapture = new Capture<C>();
+
+ myView.configure(EasyMock.capture(myViewConfigCapture));
+ EasyMock.expectLastCall().once();
+ }
+
+
+ /**
+ * @param name
+ * @return class by its name from file
+ */
+ @NotNull
+ protected PyClass getClassByName(@NotNull final String name) {
+ return myFixture.findElementByText("class " + name, PyClass.class);
+ }
+
+ /**
+ * @return collection of members displayed by presenter
+ */
+ @NotNull
+ protected Collection<PyPresenterTestMemberEntry> getMembers() {
+ Assert.assertTrue("No members captured", myViewConfigCapture.hasCaptured());
+ final Collection<PyMemberInfo<PyElement>> members = myViewConfigCapture.getValue().getMemberInfos();
+ Assert.assertFalse("No members selected", members.isEmpty());
+ return Collections2.transform(members, new NameAndStatusTransformer(myViewConfigCapture.getValue().getMemberInfoModel()));
+ }
+
+ private static class ClassToName implements Function<PyClass, String> {
+
+ @Override
+ public String apply(@NotNull final PyClass input) {
+ return input.getName();
+ }
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenterTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenterTest.java
new file mode 100644
index 0000000..accfbab
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassPresenterTest.java
@@ -0,0 +1,172 @@
+package com.jetbrains.python.refactoring.classes.extractSuperclass;
+
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import com.jetbrains.python.refactoring.classes.PyPresenterTestMemberEntry;
+import com.jetbrains.python.refactoring.classes.PyRefactoringPresenterTestCase;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Tests presenter for "extract superclass" refactoring
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyExtractSuperclassPresenterTest
+ extends PyRefactoringPresenterTestCase<PyExtractSuperclassInitializationInfo, PyExtractSuperclassView> {
+
+ public PyExtractSuperclassPresenterTest() {
+ super(PyExtractSuperclassView.class, "extractsuperclass");
+ }
+
+ /**
+ * Tests that static methods could be moved, but "extends object" is not in list
+ * Also checks that static method could NOT be made abstract in Py2K
+ */
+ public void testStaticNoObjectPy2() {
+ ensureStaticNoObject(false);
+ }
+
+ /**
+ * Tests that static methods could be moved, but "extends object" is not in list
+ * Also checks that static method COULD be made abstract in Py3K
+ */
+ public void testStaticNoObjectPy3() {
+ setLanguageLevel(LanguageLevel.PYTHON32);
+ ensureStaticNoObject(true);
+ }
+
+ /**
+ * Tests that static methods could be moved, but "extends object" is not in list.
+ * Also checks that static method could be made abstract in Py3K, but not in Py2K
+ *
+ * @param py3k if py 3?
+ */
+ private void ensureStaticNoObject( final boolean py3k) {
+ final Collection<PyPresenterTestMemberEntry> members = launchAndGetMembers("StaticOnly");
+
+ final Matcher<Iterable<? extends PyPresenterTestMemberEntry>> matcher =
+ Matchers.containsInAnyOrder(new PyPresenterTestMemberEntry("static_method()", true, true, py3k));
+ compareMembers(members, matcher);
+ }
+
+ /**
+ * Tests that if no members selected, presenter shows error
+ */
+ public void testNoSelectedMembersLeadsToError() {
+ EasyMock.expect(myView.getSelectedMemberInfos()).andReturn(Collections.<PyMemberInfo<PyElement>>emptyList()).anyTimes();
+
+ final Capture<String> errorMessageCapture = configureViewToCaptureError();
+
+
+ final PyExtractSuperclassPresenterImpl sut = configureByClass("Child");
+ myMocksControl.replay();
+ sut.launch();
+
+ sut.okClicked();
+
+ Assert.assertTrue("No error displayed empty list of selected members", errorMessageCapture.hasCaptured());
+
+ }
+
+ /**
+ * Checks that presenter displays error if user enters invalid name for new class
+ */
+ public void testInvalidSuperClassNameLeadsToError() {
+ final String className = "Child";
+ final PyClass aClass = getClassByName(className);
+ final List<PyMemberInfo<PyElement>> classMemberInfos = new PyMemberInfoStorage(aClass).getClassMemberInfos(aClass);
+ assert !classMemberInfos.isEmpty() : "No member infos for " + className;
+ final PyMemberInfo<PyElement> pyMemberInfo = classMemberInfos.get(0);
+ EasyMock.expect(myView.getSelectedMemberInfos()).andReturn(Collections.singletonList(pyMemberInfo)).anyTimes();
+ EasyMock.expect(myView.getSuperClassName()).andReturn("INVALID CLASS NAME").anyTimes();
+ final Capture<String> errorMessageCapture = configureViewToCaptureError();
+
+
+ final PyExtractSuperclassPresenterImpl sut = configureByClass(className);
+ myMocksControl.replay();
+ sut.launch();
+
+ sut.okClicked();
+
+ Assert.assertTrue("No error displayed for invalid class name", errorMessageCapture.hasCaptured());
+
+ }
+
+ /**
+ * Creates capture ready to capture error message and configures view to return it
+ *
+ * @return
+ */
+ @NotNull
+ private Capture<String> configureViewToCaptureError() {
+ final Capture<String> errorMessageCapture = new Capture<String>();
+ myView.showError(EasyMock.capture(errorMessageCapture));
+ return errorMessageCapture;
+ }
+
+ /**
+ * Old classes could be refactored as well
+ */
+ public void testOldClass() {
+ final Collection<PyPresenterTestMemberEntry> members = launchAndGetMembers("OldClass");
+ final Matcher<Iterable<? extends PyPresenterTestMemberEntry>> matcher = Matchers
+ .containsInAnyOrder(new PyPresenterTestMemberEntry("foo(self)", true, false, true));
+ compareMembers(members, matcher);
+ }
+
+ /**
+ * Checks that class fields could be moved while "extends object" is not in list
+ */
+ public void testFieldsAndNoObject() {
+ final Collection<PyPresenterTestMemberEntry> members = launchAndGetMembers("Child");
+
+ final Matcher<Iterable<? extends PyPresenterTestMemberEntry>> matcher = Matchers
+ .containsInAnyOrder(new PyPresenterTestMemberEntry("CLASS_VAR", true, true, false),
+ new PyPresenterTestMemberEntry("eggs(self)", true, false, true),
+ new PyPresenterTestMemberEntry("__init__(self)", true, false, false),
+ new PyPresenterTestMemberEntry("self.artur", true, false, false),
+ new PyPresenterTestMemberEntry("extends date", true, false, false));
+ compareMembers(members, matcher);
+ }
+
+ /**
+ * launches presenter and returns member it displayed to user
+ *
+ * @param className name of class to configure presenter by
+ * @return displayed members
+ */
+ @NotNull
+ private Collection<PyPresenterTestMemberEntry> launchAndGetMembers(@NotNull final String className) {
+ final PyExtractSuperclassPresenterImpl sut = configureByClass(className);
+ myMocksControl.replay();
+ sut.launch();
+ return getMembers();
+ }
+
+
+ /**
+ * Configures presenter by class
+ *
+ * @param name name of class
+ * @return presenter
+ */
+ @NotNull
+ private PyExtractSuperclassPresenterImpl configureByClass(@NotNull final String name) {
+ final PyClass childClass = getClassByName(name);
+ final PyMemberInfoStorage storage = new PyMemberInfoStorage(childClass);
+ return new PyExtractSuperclassPresenterImpl(myView, childClass, storage);
+ }
+
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java
new file mode 100644
index 0000000..13d5b4d
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/extractSuperclass/PyExtractSuperclassTest.java
@@ -0,0 +1,242 @@
+/*
+ * 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.refactoring.classes.extractSuperclass;
+
+import com.intellij.openapi.command.WriteCommandAction;
+import com.intellij.openapi.vfs.LocalFileSystem;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.util.ArrayUtil;
+import com.jetbrains.python.PyNames;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringTest;
+import com.jetbrains.python.refactoring.classes.membersManager.MembersManager;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class PyExtractSuperclassTest extends PyClassRefactoringTest {
+
+ public PyExtractSuperclassTest() {
+ super("extractsuperclass");
+ }
+
+ // Checks that moving methods between files moves imports as well
+ public void testImportMultiFile() throws Throwable {
+ multiFileTestHelper(".do_useful_stuff", false);
+ }
+
+ // Checks that moving methods between files moves superclass expressions as well
+ public void testMoveExtends() throws Throwable {
+ multiFileTestHelper("TheParentOfItAll", false);
+ }
+
+ // Checks that moving methods between files moves superclass expressions regardless import style (q.name or name)
+ public void testMoveExtendsCheckReference() throws Throwable {
+ multiFileTestHelper("TheParentOfItAll", false);
+ }
+
+ // Extracts method as abstract
+ public void testMoveAndMakeAbstract() throws Throwable {
+ multiFileTestHelper(".foo_method", true);
+ }
+
+ // Extracts method as abstract and ensures that newly created class imports ABC in Py3
+ public void testMoveAndMakeAbstractImportExistsPy3() throws Throwable {
+ setLanguageLevel(LanguageLevel.PYTHON30);
+ configureMultiFile("abc");
+ multiFileTestHelper(".foo_method", true);
+ }
+
+ /**
+ * Moves member from class <pre>MyClass</pre> in module <pre>source_module</pre> to class <pre>NewParent</pre> in module <pre>dest_module</pre>.
+ * Ensures it is moved correctly.
+ *
+ * @param memberToMove name of the member to move
+ */
+ private void multiFileTestHelper(@NotNull final String memberToMove, final boolean toAbstract) {
+ final String[] modules = {"dest_module", "source_module"};
+ configureMultiFile(ArrayUtil.mergeArrays(modules, "shared_module"));
+ myFixture.configureByFile("source_module.py");
+ final String sourceClass = "MyClass";
+ final PyMemberInfo<PyElement> member = findMemberInfo(sourceClass, memberToMove);
+ member.setToAbstract(toAbstract);
+ final String destUrl = myFixture.getFile().getVirtualFile().getParent().findChild("dest_module.py").getUrl();
+ new WriteCommandAction.Simple(myFixture.getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ PyExtractSuperclassHelper.extractSuperclass(findClass(sourceClass), Collections.singleton(member), "NewParent", destUrl);
+ }
+ }.execute();
+ checkMultiFile(modules);
+ }
+
+ public void testSimple() throws Exception {
+ doSimpleTest("Foo", "Suppa", null, true, ".foo");
+ }
+
+ public void testInstanceNotDeclaredInInit() throws Exception {
+ doSimpleTest("Child", "Parent", null, true, "#eggs");
+ }
+
+ public void testWithSuper() throws Exception {
+ doSimpleTest("Foo", "Suppa", null, true, ".foo");
+ }
+
+ public void testWithImport() throws Exception {
+ doSimpleTest("A", "Suppa", null, false, ".foo");
+ }
+
+ // PY-12175
+ public void testImportNotBroken() throws Exception {
+ myFixture.copyFileToProject("/refactoring/extractsuperclass/shared.py", "shared.py");
+ doSimpleTest("Source", "DestClass", null, true, "SharedClass");
+ }
+
+ // PY-12175 but between several files
+ public void testImportNotBrokenManyFiles() throws Exception {
+ multiFileTestHelper("SharedClass", false);
+ }
+
+ public void testMoveFields() throws Exception {
+ doSimpleTest("FromClass", "ToClass", null, true, "#instance_field", "#CLASS_FIELD");
+ }
+
+ private void doSimpleTest(final String className,
+ final String superclassName,
+ final String expectedError,
+ final boolean sameFile,
+ final String... membersName) throws Exception {
+ try {
+ String baseName = "/refactoring/extractsuperclass/" + getTestName(true);
+ myFixture.configureByFile(baseName + ".before.py");
+ final PyClass clazz = findClass(className);
+ final List<PyMemberInfo<PyElement>> members = new ArrayList<PyMemberInfo<PyElement>>();
+ for (String memberName : membersName) {
+ final PyElement member = findMember(className, memberName);
+ members.add(MembersManager.findMember(clazz, member));
+ }
+
+ new WriteCommandAction.Simple(myFixture.getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ //noinspection ConstantConditions
+ final String url = sameFile ? myFixture.getFile().getVirtualFile().getUrl() :
+ myFixture.getFile().getVirtualFile().getParent().getUrl();
+ PyExtractSuperclassHelper.extractSuperclass(clazz, members, superclassName, url);
+ }
+ }.execute();
+ myFixture.checkResultByFile(baseName + ".after.py");
+ }
+ catch (Exception e) {
+ if (expectedError == null) throw e;
+ assertEquals(expectedError, e.getMessage());
+ }
+ }
+
+
+ public void testMultifileNew() {
+ String baseName = "/refactoring/extractsuperclass/multifile/";
+ myFixture.configureByFile(baseName + "source.py");
+ final String className = "Foo";
+ final String superclassName = "Suppa";
+ final PyClass clazz = findClass(className);
+ final List<PyMemberInfo<PyElement>> members = new ArrayList<PyMemberInfo<PyElement>>();
+ final PyElement member = findMember(className, ".foo");
+ members.add(MembersManager.findMember(clazz, member));
+ final VirtualFile base_dir = myFixture.getFile().getVirtualFile().getParent();
+
+ new WriteCommandAction.Simple(myFixture.getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ //noinspection ConstantConditions
+ final String path = base_dir.getPath() + "/a/b";
+ PyExtractSuperclassHelper.extractSuperclass(clazz, members, superclassName, path);
+ }
+ }.execute();
+ final PsiManager psi_mgr = PsiManager.getInstance(myFixture.getProject());
+ VirtualFile vfile = base_dir.findChild("a");
+ assertTrue(vfile.isDirectory());
+ vfile = vfile.findChild(PyNames.INIT_DOT_PY);
+ assertNotNull(vfile);
+
+ vfile = base_dir.findChild("a").findChild("b");
+ assertTrue(vfile.isDirectory());
+ vfile = vfile.findChild(PyNames.INIT_DOT_PY);
+ assertNotNull(vfile);
+
+ PsiFile psi_file = psi_mgr.findFile(vfile);
+ String result = psi_file.getText().trim();
+ File expected_file = new File(getTestDataPath() + baseName, "target.new.py");
+ String expected = psi_mgr.findFile(LocalFileSystem.getInstance().findFileByIoFile(expected_file)).getText().trim();
+ assertEquals(expected, result);
+ }
+
+ public void testMultifileAppend() {
+ // this is half-copy-paste of testMultifileNew. generalization won't make either easier to follow.
+ String baseName = "/refactoring/extractsuperclass/multifile/";
+ myFixture.configureByFiles(
+ baseName + "source.py",
+ baseName + "a/__init__.py",
+ baseName + "a/b/__init__.py",
+ baseName + "a/b/foo.py"
+ );
+ final String className = "Foo";
+ final String superclassName = "Suppa";
+ final PyClass clazz = findClass(className);
+ final List<PyMemberInfo<PyElement>> members = new ArrayList<PyMemberInfo<PyElement>>();
+ final PyElement member = findMember(className, ".foo");
+ members.add(MembersManager.findMember(clazz, member));
+ final VirtualFile base_dir = myFixture.getFile().getVirtualFile().getParent();
+
+ new WriteCommandAction.Simple(myFixture.getProject()) {
+ @Override
+ protected void run() throws Throwable {
+ //TODO: Test via presenter
+ //noinspection ConstantConditions
+ final String path = base_dir.getPath() + "/a/b";
+ PyExtractSuperclassHelper.extractSuperclass(clazz, members, superclassName, path + "/foo.py");
+ }
+ }.execute();
+ final PsiManager psi_mgr = PsiManager.getInstance(myFixture.getProject());
+ VirtualFile vfile = base_dir.findChild("a");
+ assertTrue(vfile.isDirectory());
+ vfile = vfile.findChild(PyNames.INIT_DOT_PY);
+ assertNotNull(vfile);
+
+ vfile = base_dir.findChild("a").findChild("b");
+ assertTrue(vfile.isDirectory());
+ assertNotNull(vfile.findChild(PyNames.INIT_DOT_PY));
+ vfile = vfile.findChild("foo.py");
+ assertNotNull(vfile);
+
+ PsiFile psi_file = psi_mgr.findFile(vfile);
+ String result = psi_file.getText().trim();
+ File expected_file = new File(getTestDataPath() + baseName, "target.append.py");
+ String expected = psi_mgr.findFile(LocalFileSystem.getInstance().findFileByIoFile(expected_file)).getText().trim();
+ assertEquals(expected, result);
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java
new file mode 100644
index 0000000..81833f6
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpPresenterTest.java
@@ -0,0 +1,165 @@
+package com.jetbrains.python.refactoring.classes.pullUp;
+
+import com.google.common.collect.Collections2;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.refactoring.classes.PyMemberInfoStorage;
+import com.jetbrains.python.refactoring.classes.PyPresenterTestMemberEntry;
+import com.jetbrains.python.refactoring.classes.PyRefactoringPresenterTestCase;
+import org.easymock.EasyMock;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.jetbrains.annotations.NotNull;
+import org.junit.Assert;
+
+import java.util.Collection;
+
+
+/**
+ * Test presenter for pull-up refactoring
+ *
+ * @author Ilya.Kazakevich
+ */
+public class PyPullUpPresenterTest extends PyRefactoringPresenterTestCase<PyPullUpViewInitializationInfo, PyPullUpView> {
+
+
+ public PyPullUpPresenterTest() {
+ super(PyPullUpView.class, "pullup");
+ }
+
+ /**
+ * Checks that parents are returned in MRO order and no parents outside of source root are included
+ */
+ public void testParentsOrder() throws Exception {
+ final PyPullUpPresenter sut = configureByClass("Child");
+
+ myMocksControl.replay();
+
+ sut.launch();
+ Assert.assertTrue("Presenter did not show parents", myViewConfigCapture.hasCaptured());
+ final Collection<PyClass> parents = myViewConfigCapture.getValue().getParents();
+ Assert.assertThat("Wrong list of parents or parents are listed in wrong order", Collections2.transform(parents, CLASS_TO_NAME),
+ Matchers.contains("SubParent1", "SubParent2", "MainParent"));
+ }
+
+ /**
+ * Checks that refactoring does not work for classes with out of allowed parents
+ */
+ public void testNoParents() throws Exception {
+ ensureNoMembers("NoParentsAllowed");
+ }
+
+ /**
+ * Checks that refactoring does not work for classes with out of members
+ */
+ public void testNoMembers() throws Exception {
+ ensureNoMembers("NoMembers");
+ }
+
+ /**
+ * Checks that refactoring does not work when C3 MRO can't be calculated
+ */
+ public void testBadMro() throws Exception {
+ ensureNoMembers("BadMro");
+ }
+
+ /**
+ * Checks that parent can't be moved to itself
+ */
+ public void testNoMoveParentToItSelf() throws Exception {
+ final Collection<PyPresenterTestMemberEntry> memberNamesAndStatus = launchAndGetMembers("Foo", "Bar");
+
+ compareMembers(memberNamesAndStatus, Matchers.containsInAnyOrder(new PyPresenterTestMemberEntry("__init__(self)", true, false, false),
+ new PyPresenterTestMemberEntry("self.foo", true, false, false),
+ new PyPresenterTestMemberEntry("extends Bar", false, false, false)));
+ }
+
+ /**
+ * Checks that some members are not allowed (and may nto be abstract), while others are for Py2
+ */
+ public void testMembersPy2() throws Exception {
+ ensureCorrectMembersForHugeChild(false);
+ }
+
+ /**
+ * Checks that some members are not allowed (and may nto be abstract), while others are for Py3
+ */
+ public void testMembersPy3() throws Exception {
+ setLanguageLevel(LanguageLevel.PYTHON30);
+ ensureCorrectMembersForHugeChild(true);
+ }
+
+
+ /**
+ * Checks members for class HugeChild
+ *
+ * @param py3K if python 3
+ */
+ private void ensureCorrectMembersForHugeChild(final boolean py3K) {
+ final Collection<PyPresenterTestMemberEntry> memberNamesAndStatus = launchAndGetMembers("HugeChild", "SubParent1");
+
+ //Pair will return correct type
+ final Matcher<Iterable<? extends PyPresenterTestMemberEntry>> matcher = Matchers
+ .containsInAnyOrder(new PyPresenterTestMemberEntry("extends date", true, false, false),
+ new PyPresenterTestMemberEntry("CLASS_FIELD", true, true, false),
+ new PyPresenterTestMemberEntry("__init__(self)", true, false, false),
+ new PyPresenterTestMemberEntry("extends SubParent1", false, false, false),
+ new PyPresenterTestMemberEntry("foo(self)", false, false, false),
+ new PyPresenterTestMemberEntry("bar(self)", true, false, true),
+ new PyPresenterTestMemberEntry("static_1(cls)", true, true, py3K),
+ 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));
+ compareMembers(memberNamesAndStatus, matcher);
+ }
+
+ /**
+ * Launches presenter and returns members it displayed to user
+ *
+ * @param classUnderRefactoring class to refactor
+ * @param destinationClass where to move it
+ * @return members displayed to user
+ */
+ @NotNull
+ private Collection<PyPresenterTestMemberEntry> launchAndGetMembers(@NotNull final String classUnderRefactoring,
+ @NotNull final String destinationClass) {
+ final PyPullUpPresenterImpl sut = configureByClass(classUnderRefactoring);
+
+ EasyMock.expect(myView.getSelectedParent()).andReturn(getClassByName(destinationClass)).anyTimes();
+
+ myMocksControl.replay();
+ sut.launch();
+
+ return getMembers();
+ }
+
+ /**
+ * Checks that refactoring does not work for classes with out of members
+ */
+ private void ensureNoMembers(@NotNull final String className) throws Exception {
+ try {
+ final PyPullUpPresenter sut = configureByClass(className);
+
+ myMocksControl.replay();
+ sut.launch();
+ }
+ catch (final IllegalArgumentException ignored) {
+ return;
+ }
+ Assert
+ .fail("Presenter should throw exception, but it returned list of parents instead: " + myViewConfigCapture.getValue().getParents());
+ }
+
+ /**
+ * Creates presenter (sut) by class
+ *
+ * @param name name of class
+ * @return presenter
+ */
+ private PyPullUpPresenterImpl configureByClass(@NotNull final String name) {
+ final PyClass childClass = getClassByName(name);
+ final PyMemberInfoStorage storage = new PyMemberInfoStorage(childClass);
+ return new PyPullUpPresenterImpl(myView, storage, childClass);
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java
new file mode 100644
index 0000000..d18f5b7
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pullUp/PyPullUpTest.java
@@ -0,0 +1,166 @@
+/*
+ * 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.refactoring.classes.pullUp;
+
+import com.intellij.util.ArrayUtil;
+import com.jetbrains.python.psi.LanguageLevel;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringTest;
+import com.jetbrains.python.refactoring.classes.membersManager.MembersManager;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class PyPullUpTest extends PyClassRefactoringTest {
+
+ public PyPullUpTest() {
+ super("pullup");
+ }
+
+ public void testSimple() {
+ doHelperTest("Boo", ".boo", "Foo");
+ }
+
+ public void testSuperclass() {
+ doHelperTest("Boo", "Foo", "Zope");
+ }
+
+ public void testExistingsuperclass() {
+ doHelperTest("Boo", "Foo", "Zope");
+ }
+
+ public void testWithComments() {
+ doHelperTest("Boo", ".boo", "Foo");
+ }
+
+ public void testWithMultilineComments() {
+ doHelperTest("Boo", ".boo", "Foo");
+ }
+
+ public void testSeveralParents() {
+ doHelperTest("Child", "Spam", "Parent_1");
+ }
+
+ public void testMoveClassAttributesSimple() {
+ doHelperTest("Child", "#CLASS_VAR", "Parent");
+ }
+
+ public void testInstanceNotDeclaredInInit() {
+ doHelperTest("Child", "#foo", "Parent");
+ }
+
+ public void testMoveClassAttributesNoPass() {
+ doHelperTest("Child2", "#CLASS_VAR", "Parent2");
+ }
+
+ public void testMoveInstanceAttributesSimple() {
+ doHelperTest("Child", "#instance_field", "Parent");
+ }
+
+ public void testMoveInstanceAttributesNoInit() {
+ doHelperTest("Child", "#instance_field", "Parent");
+ }
+
+ public void testMoveInstanceAttributesLeaveEmptyInit() {
+ doHelperTest("Child", "#foo", "Parent");
+ }
+
+ public void testMultiFile() { // PY-2810
+ doMultiFileTest();
+ }
+
+ public void testDuplicateImport() { // PY-2810
+ doMultiFileTest();
+ }
+
+ public void testFieldMove() {
+ final String[] modules = {"Class", "SuperClass"};
+ configureMultiFile(modules);
+ doPullUp("AnyClass", "SuperClass", "#COPYRIGHT");
+ doPullUp("AnyClass", "SuperClass", "#version");
+ checkMultiFile(modules);
+ }
+
+ private void doMultiFileTest() {
+ final String[] modules = {"Class", "SuperClass"};
+ configureMultiFile(modules);
+ doPullUp("AnyClass", "SuperClass", ".this_should_be_in_super");
+ checkMultiFile(modules);
+ }
+
+ /**
+ * Ensures that pulling abstract method up to class that already uses ABCMeta works correctly
+ */
+ public void testAbstractMethodHasMeta() {
+ checkAbstract(".my_method");
+ }
+
+ /**
+ * Ensures that pulling abstract method up to class that has NO ABCMeta works correctly for py2 (__metaclass__ is added)
+ */
+ public void testAbstractMethodPy2AddMeta() {
+ checkAbstract(".my_method", ".my_method_2");
+ }
+
+ /**
+ * Ensures that pulling abstract method up to class that has NO ABCMeta works correctly for py3k (metaclass is added)
+ */
+ public void testAbstractMethodPy3AddMeta() {
+ setLanguageLevel(LanguageLevel.PYTHON34);
+ checkAbstract(".my_method", ".my_class_method");
+ }
+
+ /**
+ * Moves methods fromn Child to Parent and make them abstract
+ * @param methodNames methods to check
+ */
+ private void checkAbstract(@NotNull final String... methodNames) {
+ final String[] modules = {"Class", "SuperClass"};
+ configureMultiFile(ArrayUtil.mergeArrays(modules, "abc"));
+ doPullUp("Child", "Parent", true, methodNames);
+ checkMultiFile(modules);
+ }
+
+
+ private void doHelperTest(final String className, final String memberName, final String superClassName) {
+ myFixture.configureByFile(getMultiFileBaseName() + ".py");
+ doPullUp(className, superClassName, memberName);
+ myFixture.checkResultByFile(getMultiFileBaseName() + ".after.py");
+ }
+
+ private void doPullUp(final String className, final String superClassName, final String memberName) {
+ doPullUp(className, superClassName, false, memberName);
+ }
+ private void doPullUp(final String className, final String superClassName, final boolean toAbstract, final String... memberNames ) {
+ final PyClass clazz = findClass(className);
+ final PyClass superClass = findClass(superClassName);
+ final Collection<PyMemberInfo<PyElement>> membersToMove = new ArrayList<PyMemberInfo<PyElement>>(memberNames.length);
+ for (final String memberName : memberNames) {
+ final PyElement member = findMember(className, memberName);
+ final PyMemberInfo<PyElement> memberInfo = MembersManager.findMember(clazz, member);
+ memberInfo.setToAbstract(toAbstract);
+ membersToMove.add(memberInfo);
+ }
+ moveViaProcessor(clazz.getProject(),
+ new PyPullUpProcessor(clazz, superClass, membersToMove));
+ }
+}
diff --git a/python/testSrc/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownTest.java b/python/testSrc/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownTest.java
new file mode 100644
index 0000000..e2bd778
--- /dev/null
+++ b/python/testSrc/com/jetbrains/python/refactoring/classes/pushDown/PyPushDownTest.java
@@ -0,0 +1,95 @@
+/*
+ * 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.refactoring.classes.pushDown;
+
+import com.intellij.util.ArrayUtil;
+import com.jetbrains.python.psi.PyClass;
+import com.jetbrains.python.psi.PyElement;
+import com.jetbrains.python.refactoring.classes.PyClassRefactoringTest;
+import com.jetbrains.python.refactoring.classes.membersManager.MembersManager;
+import com.jetbrains.python.refactoring.classes.membersManager.PyMemberInfo;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class PyPushDownTest extends PyClassRefactoringTest {
+
+ public PyPushDownTest() {
+ super("pushdown");
+ }
+
+ // Tests that pushing down methods moves imports as well (PY-10963)
+ public void testMultiFileImports() {
+ final String[] modules = {"child_module", "parent_module"};
+ configureMultiFile(ArrayUtil.mergeArrays(modules, "shared_module"));
+ final PyClass parentClass = findClass("Parent");
+ final PyMemberInfo<PyElement> methodToMove = MembersManager.findMember(parentClass, findMember("Parent", ".should_be_pushed"));
+
+ moveViaProcessor(myFixture.getProject(), new PyPushDownProcessor(myFixture.getProject(), Collections.singletonList(methodToMove), parentClass));
+ checkMultiFile(modules);
+ }
+
+ public void testSimple() throws Exception {
+ doProcessorTest("Foo", null, ".foo");
+ }
+
+ public void testSuperclass() throws Exception {
+ doProcessorTest("Zope", null, "Foo");
+ }
+
+ public void testFull() throws Exception {
+ doProcessorTest("Parent", null, "#CLASS_VAR_1", "#inst_var", ".method_1", "Dummny");
+ }
+
+ public void testMultiple() throws Exception {
+ doProcessorTest("Foo", null, ".foo");
+ }
+
+ public void testPy346() throws Exception {
+ doProcessorTest("A", null, ".meth_a1", ".meth_a2");
+ }
+
+ public void testExistingmethod() throws Exception {
+ doProcessorTest("Foo",
+ "method <b><code>foo</code></b> is already overridden in class <b><code>Boo</code></b>. Method will not be pushed down to that class.",
+ ".foo");
+ }
+
+ private void doProcessorTest(final String className, final String expectedError, final String... memberNames) throws Exception {
+ try {
+ String baseName = "/refactoring/pushdown/" + getTestName(true);
+ myFixture.configureByFile(baseName + ".before.py");
+ final PyClass clazz = findClass(className);
+ final List<PyMemberInfo<PyElement>> members = new ArrayList<PyMemberInfo<PyElement>>();
+ for (String memberName : memberNames) {
+ final PyElement member = findMember(className, memberName);
+ members.add(MembersManager.findMember(clazz, member));
+ }
+
+ final PyPushDownProcessor processor = new PyPushDownProcessor(myFixture.getProject(), members, clazz);
+ moveViaProcessor(myFixture.getProject(), processor);
+ myFixture.checkResultByFile(baseName + ".after.py");
+ }
+ catch (Exception e) {
+ if (expectedError == null) throw e;
+ assertTrue(e.getMessage(), e.getMessage().contains(expectedError));
+ }
+ }
+}
diff --git a/python/testSrc/python-community-tests.iml b/python/testSrc/python-community-tests.iml
index b4cc276..6511d88 100644
--- a/python/testSrc/python-community-tests.iml
+++ b/python/testSrc/python-community-tests.iml
@@ -15,6 +15,7 @@
<orderEntry type="module" module-name="spellchecker" scope="TEST" />
<orderEntry type="module" module-name="python-ide-community" />
<orderEntry type="module" module-name="python-helpers" scope="RUNTIME" />
+ <orderEntry type="library" name="Groovy" level="project" />
</component>
</module>
diff --git a/resources-en/src/fileTemplates/code/Catch Statement Body.java.html b/resources-en/src/fileTemplates/code/Catch Statement Body.java.html
index d1c5a3b..0671243 100644
--- a/resources-en/src/fileTemplates/code/Catch Statement Body.java.html
+++ b/resources-en/src/fileTemplates/code/Catch Statement Body.java.html
@@ -19,6 +19,11 @@
<td width="10"> </td>
<td valign="top"><font face="verdana" size="-1">name of the <b>Exception</b> variable specified as a <b>catch</b> parameter</font></td>
</tr>
+ <tr>
+ <td valign="top"><nobr><font face="verdana" size="-2" ><b>${EXCEPTION_TYPE}</b></font></nobr></td>
+ <td width="10"> </td>
+ <td valign="top"><font face="verdana" size="-1">type of the <b>catch</b> parameter</font></td>
+ </tr>
</table>
</body>
</html>
\ No newline at end of file
diff --git a/resources-en/src/inspectionDescriptions/FileEqualsUsage.html b/resources-en/src/inspectionDescriptions/FileEqualsUsage.html
deleted file mode 100644
index 7fc1f93..0000000
--- a/resources-en/src/inspectionDescriptions/FileEqualsUsage.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body>
-This inspection detects usages of File.equals/hashCode/compareTo methods - which do not honor case-insensitivity on Mac OS X.
-Please use FileUtil.filesEquals/fileHashCode/compareFiles methods instead.
-<p><small>Internal inspection - has no effect outside of IntelliJ IDEA project.</small></p>
-</body>
-</html>
diff --git a/resources-en/src/inspectionDescriptions/GtkPreferredJComboBoxRenderer.html b/resources-en/src/inspectionDescriptions/GtkPreferredJComboBoxRenderer.html
deleted file mode 100644
index b28da27..0000000
--- a/resources-en/src/inspectionDescriptions/GtkPreferredJComboBoxRenderer.html
+++ /dev/null
@@ -1,7 +0,0 @@
-<html>
-<body>
-This inspection detects usages of DefaultListCellRenderer - which causes ugly UI under GTK+ L&F.
-Please use ListCellRendererWrapper (or it's inheritors) instead.
-<p><small>Internal inspection - has no effect outside of IntelliJ IDEA project.</small></p>
-</body>
-</html>
diff --git a/resources-en/src/inspectionDescriptions/Since15.html b/resources-en/src/inspectionDescriptions/Since15.html
index 2720bcf..4fd249d 100644
--- a/resources-en/src/inspectionDescriptions/Since15.html
+++ b/resources-en/src/inspectionDescriptions/Since15.html
@@ -1,10 +1,9 @@
<html>
<body>
<font face="verdana" size="-1">
-This inspection finds all usages of methods that have <b><font color="#000080">@since 1.5</font></b> tag in
+This inspection finds all usages of methods that have <b><font color="#000080">@since</font></b> tag in
their documentation.<br><br>
-This may be useful when development is performed under J2SDK 5.0, while the target platform for production is
-still J2SDK 1.4.<br><br>
+This may be useful when development is performed under newer SDK version as the target platform for production.<br><br>
</font>
</body>
</html>
diff --git a/resources-en/src/inspectionDescriptions/UndesirableClassUsage.html b/resources-en/src/inspectionDescriptions/UndesirableClassUsage.html
deleted file mode 100644
index bbbe61d..0000000
--- a/resources-en/src/inspectionDescriptions/UndesirableClassUsage.html
+++ /dev/null
@@ -1,6 +0,0 @@
-<html>
-<body>
-This inspection detects usages of internally deprecated classes.
-<p><small>Internal inspection - has no effect outside of IntelliJ IDEA project.</small></p>
-</body>
-</html>
diff --git a/resources-en/src/inspectionDescriptions/UnsafeVfsRecursion.html b/resources-en/src/inspectionDescriptions/UnsafeVfsRecursion.html
deleted file mode 100644
index 270853f..0000000
--- a/resources-en/src/inspectionDescriptions/UnsafeVfsRecursion.html
+++ /dev/null
@@ -1,8 +0,0 @@
-<html>
-<body>
-This inspection detects calls of VirtualFile.getChildren() inside recursive methods.
-Such a code may cause dead loops when iterating over cyclic symlinks -
-so please use VfsUtilCore.visitChildrenRecursively() instead.
-<p><small>Internal inspection - has no effect outside of IntelliJ IDEA project.</small></p>
-</body>
-</html>
diff --git a/resources-en/src/messages/DebuggerBundle.properties b/resources-en/src/messages/DebuggerBundle.properties
index 01984ee..57e0ec1 100644
--- a/resources-en/src/messages/DebuggerBundle.properties
+++ b/resources-en/src/messages/DebuggerBundle.properties
@@ -132,6 +132,7 @@
evaluation.error.cannot.cast.numeric=Cannot cast numeric value to ''{0}''
evaluation.error.cannot.cast.boolean=Cannot cast boolean value to ''{0}''
evaluation.error.cannot.cast.char=Cannot cast char value to ''{0}''
+evaluation.error.cannot.cast.object=Cannot cast ''{0}'' to ''{1}''
evaluation.error.numeric.expected=Numeric value expected
evaluation.error.integer.expected=Integer value expected
evaluation.error.boolean.expected=Boolean value expected
diff --git a/resources-en/src/tips/EclipseQuickOpen.html b/resources-en/src/tips/EclipseQuickOpen.html
index 1a7a2ba..17b2b32 100644
--- a/resources-en/src/tips/EclipseQuickOpen.html
+++ b/resources-en/src/tips/EclipseQuickOpen.html
@@ -8,7 +8,7 @@
<p>You can quickly open an Eclipse project by selecting a <span class="code_emphasis">.classpath</span> or <span class="code_emphasis">.project</span> file in
- the <span class="control">Open Project</span> dialog.
+ the <span class="control">File | Open</span> dialog.
The corresponding Eclipse project is imported with default settings, without launching the wizard.</p>
diff --git a/resources-en/src/tips/ExternalJavaDoc.html b/resources-en/src/tips/ExternalJavaDoc.html
index e6c9d1c..e1791b4 100644
--- a/resources-en/src/tips/ExternalJavaDoc.html
+++ b/resources-en/src/tips/ExternalJavaDoc.html
@@ -8,10 +8,9 @@
<p>To open your browser with documentation for the element at the editor's caret,
press <span class="shortcut">&shortcut:ExternalJavaDoc;</span>
(<span class="control">View | External Documentation</span>).</p>
- <p>You must have the path to your browser set in the <span class="control">General</span> options
- (<span class="control">File | Settings</span>)
+ <p>You must have the path to your browser set in the <span class="control">File | Settings | Web Browsers</span> options
and paths to documentation files added to your project
- (<span class="control">File | Settings | Project Structure</span>) to use this feature.</p>
+ (<span class="control">File | Project Structure...</span>) to use this feature.</p>
</body>
</html>
diff --git a/resources-en/src/tips/HierarchyBrowser.html b/resources-en/src/tips/HierarchyBrowser.html
index 39ffec5..6f9616a 100644
--- a/resources-en/src/tips/HierarchyBrowser.html
+++ b/resources-en/src/tips/HierarchyBrowser.html
@@ -6,7 +6,7 @@
<p>To see the inheritance hierarchy for a selected class, press <span class="shortcut">&shortcut:TypeHierarchy;</span>
- (<span class="control">View | Type Hierarchy</span>).
+ (<span class="control">Navigate | Type Hierarchy</span>).
You can also invoke the hierarchy view right from the editor to see the hierarchy for the currently edited class.</p>
<p class="image"><img src="images/hierarchy_browser.png"></p>
diff --git a/resources-en/src/tips/HighlightThrows.html b/resources-en/src/tips/HighlightThrows.html
index a6d8468..20a747d 100644
--- a/resources-en/src/tips/HighlightThrows.html
+++ b/resources-en/src/tips/HighlightThrows.html
@@ -6,7 +6,7 @@
- <p>You can view all statements within the method where certain exceptions can be brought.
+ <p>You can view all statements within the method where certain exceptions can be caught.
Just place the caret at the <span class="code_emphasis">throws</span> keyword in a method declaration,
press <span class="shortcut">&shortcut:HighlightUsagesInFile;</span> and select the desired exception class from the list.
This will also work for <span class="code_emphasis">try</span> and <span class="code_emphasis">catch</span>.
diff --git a/resources-en/src/tips/MavenQuickOpen.html b/resources-en/src/tips/MavenQuickOpen.html
index 7fd23c6..c1d1d18 100644
--- a/resources-en/src/tips/MavenQuickOpen.html
+++ b/resources-en/src/tips/MavenQuickOpen.html
@@ -7,7 +7,7 @@
- <p>You can quickly open a Maven project by selecting a <span class="code_emphasis">pom.xml</span> file in the <span class="control">Open Project</span> dialog.
+ <p>You can quickly open a Maven project by selecting a <span class="code_emphasis">pom.xml</span> file in the <span class="control">File | Open</span> dialog.
The corresponding Maven project is imported with default settings, without launching the wizard.</p>
diff --git a/resources-en/src/tips/NextPrevError.html b/resources-en/src/tips/NextPrevError.html
index ff6fa10..5760050 100644
--- a/resources-en/src/tips/NextPrevError.html
+++ b/resources-en/src/tips/NextPrevError.html
@@ -8,6 +8,7 @@
<p>Use <span class="shortcut">&shortcut:GotoNextError;</span>/<span class="shortcut">&shortcut:GotoPreviousError;</span> keys to jump between highlighted syntax errors.</p>
<p>Use <span class="shortcut">&shortcut:PreviousOccurence;</span>/<span class="shortcut">&shortcut:NextOccurence;</span> shortcuts to jump between compiler error messages
or search operation results.</p>
+ <p>To skip warnings right click on the validation side bar / marker bar and choose <span class="control">Go to high priority problems only</span>.</p>
diff --git a/resources-en/src/tips/SurroundWith.html b/resources-en/src/tips/SurroundWith.html
index 4de4f2b..3eeaf92 100644
--- a/resources-en/src/tips/SurroundWith.html
+++ b/resources-en/src/tips/SurroundWith.html
@@ -10,7 +10,7 @@
and choose <span class="control">try / catch</span>. The catch blocks for all the exceptions thrown inside the block will be generated automatically.</p>
<p>You can customize the bodies of the generated catch blocks on the
<span class="control">Code</span> tab of
- <span class="control">File | Settings | File Templates</span>.</p>
+ <span class="control">File | Settings | File and Code Templates</span>.</p>
<p>Use other items in the list to surround with other constructs.</p>
<p class="image"><img src="images/surround_with.png"></p>
diff --git a/resources-en/src/tips/Terminal.html b/resources-en/src/tips/Terminal.html
index 84957c7..fcebc65 100644
--- a/resources-en/src/tips/Terminal.html
+++ b/resources-en/src/tips/Terminal.html
@@ -5,7 +5,7 @@
<body>
- <p>You don't need to leave WebStorm to work with your favorite shell. Just choose
+ <p>You don't need to leave <span class="product">&productName;</span> to work with your favorite shell. Just choose
<span class="control">Tools | Open Terminal</span> on the main menu,
and enjoy using the embedded local terminal. </p>
<p class="image"><img src="images/terminal.png"></p>
diff --git a/resources-en/src/tips/UmlClassDiagram.html b/resources-en/src/tips/UmlClassDiagram.html
deleted file mode 100644
index fba09a6..0000000
--- a/resources-en/src/tips/UmlClassDiagram.html
+++ /dev/null
Binary files differ
diff --git a/resources-en/src/tips/WideScreen.html b/resources-en/src/tips/WideScreen.html
index ee5c16c..506b73f 100644
--- a/resources-en/src/tips/WideScreen.html
+++ b/resources-en/src/tips/WideScreen.html
@@ -7,7 +7,7 @@
<p>Tune the <span class="product">&productName;</span> tool windows layout to make better use of your screen.</p>
<p>Toggle between the vertical and side-by-side placement of the tool windows by
-Ctrl+click/Cmd+Click on the splitter:</p>
+Ctrl+Click/Cmd+Click on the splitter:</p>
<p class="image"><img src="images/sidebyside.png"></p>
diff --git a/resources-en/src/tips/images/umlClassDiagram.png b/resources-en/src/tips/images/umlClassDiagram.png
deleted file mode 100644
index b5d759e..0000000
--- a/resources-en/src/tips/images/umlClassDiagram.png
+++ /dev/null
Binary files differ
diff --git a/resources-en/src/tips/tips.xml b/resources-en/src/tips/tips.xml
deleted file mode 100644
index 503f385..0000000
--- a/resources-en/src/tips/tips.xml
+++ /dev/null
@@ -1,166 +0,0 @@
-<tips> <!--covered items are included to ProductivityFeaturesRegistry.xml -->
- <!--
- <tip file="NotReadyYet.html"/>
- -->
- <tip file="Welcome.html"/>
- <tip file="GoToClass.html"/>
- <!--covered-->
- <tip file="CodeCompletion.html"/>
- <!--covered-->
- <tip file="FindUsages.html"/>
- <tip file="QuickJavaDoc.html"/>
- <!--covered-->
- <tip file="GoToDeclaration.html"/>
- <!--covered-->
- <tip file="FileStructurePopup.html"/>
- <!--covered-->
- <tip file="Rename.html"/>
- <tip file="OverrideImplementMethods.html"/>
- <!--covered-->
- <tip file="SmartTypeCompletion.html"/>
- <!--covered-->
- <tip file="TabInLookups.html"/>
- <!--covered-->
- <tip file="TabInEditorClose.html"/>
- <tip file="AltInsertInEditor.html"/>
- <!--<tip file="ClosingTabsWithMiddleMouse.html"/>-->
- <tip file="SelectIn.html"/>
- <!--covered-->
- <tip file="SpeedSearch.html"/>
- <!--covered-->
- <tip file="Escape.html"/>
- <tip file="SurroundWith.html"/>
- <!--covered-->
- <tip file="SmartTypeAfterNew.html"/>
- <!--covered-->
- <tip file="GoToImplementation.html"/>
- <!--covered-->
- <tip file="CtrlW.html"/>
- <!--covered-->
- <tip file="IntroduceVariable.html"/>
- <!--covered-->
- <tip file="CommentCode.html"/>
- <!--covered-->
- <!--<tip file="DisableBulb.html"/>-->
- <tip file="ExternalJavaDoc.html"/>
- <!--covered-->
- <tip file="SmartTypeCasting.html"/>
- <!--covered-->
- <tip file="CtrlD.html"/>
- <tip file="LiveTemplates.html"/>
- <tip file="VariableNameCompletion.html"/>
- <!--covered-->
- <tip file="ParameterInfo.html"/>
- <tip file="JumpToLastEdit.html"/>
- <tip file="HighlightUsagesInFile.html"/>
- <tip file="LayoutCode.html"/>
- <tip file="LocalVCS.html"/>
- <tip file="ContextInfo.html"/>
- <tip file="RecentFiles.html"/>
- <!--covered-->
- <tip file="NextPrevError.html"/>
- <tip file="InsertLiveTemplate.html"/>
- <tip file="MethodSeparators.html"/>
- <tip file="CodeCompletionMiddle.html"/>
- <!--covered-->
- <tip file="MethodUpDown.html"/>
- <tip file="JoinLines.html"/>
- <tip file="CopyClass.html"/>
- <!--covered-->
- <tip file="ClipboardStack.html"/>
- <tip file="HierarchyBrowser.html"/>
- <tip file="BreakpointSpeedmenu.html"/>
- <tip file="EvaluateExpressionInEditor.html"/>
- <tip file="WordCompletion.html"/>
- <tip file="QuickJavaDocInLookups.html"/>
- <!--covered-->
- <tip file="DotEtcInLookups.html"/>
- <!--covered-->
- <tip file="MenuItemsDescriptions.html"/>
- <tip file="WildcardsInNavigationPopups.html"/>
- <tip file="MoveInnerToUpper.html"/>
- <tip file="IntroduceVariableIncompleteCode.html"/>
- <!--<tip file="CreateTargetTag.html"/>-->
- <tip file="GoToSymbol.html"/>
- <tip file="RecentChanges.html"/>
- <!--covered-->
- <tip file="ImageFileCompletion.html"/>
- <tip file="CreatePropertyTag.html"/>
- <tip file="QuickSwitchScheme.html"/>
- <!--covered-->
- <tip file="CompleteStatement.html"/>
- <tip file="CamelPrefixesInNavigationPopups.html"/>
- <tip file="CtrlShiftI.html"/>
- <!--covered-->
- <tip file="CompletionInHTML.html"/>
- <tip file="CopyPasteReference.html"/>
- <tip file="MoveUpDown.html"/>
- <tip file="SelectRunDebugConfiguration.html"/>
- <tip file="CtrlShiftIForLookup.html"/>
- <!--covered-->
- <tip file="PropertiesCompletion.html"/>
- <tip file="ShowAppliedStyles.html"/>
- <tip file="ImagesLookup.html"/>
- <tip file="RenameCssSelector.html"/>
- <tip file="NavBar.html"/>
- <tip file="ChangesView.html"/>
- <tip file="Antivirus.html"/>
- <tip file="MavenQuickOpen.html"/>
- <tip file="MoveToChangelist.html"/>
- <tip file="EclipseQuickOpen.html"/>
- <tip file="ShowUsages.html"/>
- <tip file="GoToAction.html"/>
- <tip file="GoToInspection.html"/>
- <tip file="SearchInSettings.html"/>
- <tip file="CompleteMethod.html"/>
- <tip file="HighlightImplements.html"/>
- <tip file="RecentSearch.html"/>
- <tip file="CodeCompletionInSearch.html"/>
- <tip file="HighlightMethodExitPoint.html"/>
- <tip file="HighlightThrows.html"/>
- <tip file="QuickFixRightArrow.html"/>
- <tip file="NavigateToFilePath.html"/>
- <tip file="IssueNavigation.html"/>
- <tip file="UmlClassDiagram.html"/>
- <tip file="ColorEditingInCss.html"/>
- <tip file="CreateTestIntentionAction.html"/>
- <tip file="ColumnSelection.html"/>
- <tip file="ColorFiles.html"/>
- <tip file="CopyWithNoSelection.html"/>
- <tip file="moveFileToChangelist.html"/>
- <tip file="Spellchecker.html"/>
- <tip file="SpellcheckerDictionaries.html"/>
- <tip file="VcsQuickList.html"/>
- <tip file="Switcher.html"/>
- <tip file="DragToOpen.html"/>
- <tip file="CloseOthers.html"/>
- <tip file="EnterDirectoryInGotoFile.html"/>
- <tip file="GotoLineInFile.html"/>
- <tip file="AnnotationsAndDiffs.html"/>
- <tip file="DirDiff.html"/>
- <tip file="JarDiff.html"/>
- <tip file="ShowHideSideBars.html"/>
- <tip file="ExcludeFromProject.html"/>
- <tip file="CodeCompletionNoShift.html"/>
- <tip file="CommitCtrlK.html"/>
- <tip file="FindReplaceToggle.html"/>
- <tip file="ScopesInTODO.html"/>
- <tip file="PreviewTODO.html"/>
- <tip file="FixDocComment.html"/>
- <tip file="SelectTasks.html"/>
- <tip file="RunConfigFolders.html"/>
- <tip file="SpeedSearchinLiveTemplates.html"/>
- <tip file="EditRegExp.html"/>
-
- <tip file="Emmet.html"/>
- <tip file="EscapeCharactersInResourceBundle.html"/>
- <tip file="LineEndings.html"/>
- <tip file="LineEndingsFolder.html"/>
- <tip file="RefactorThis.html"/>
- <tip file="FavoritesToolWindow1.html"/>
- <tip file="FavoritesToolWindow2.html"/>
-
- <tip file="WideScreen.html"/>
- <tip file="Terminal.html"/>
- <tip file="ConfiguringTerminal.html"/>
-</tips>
diff --git a/resources/src/META-INF/IdeTipsAndTricks.xml b/resources/src/META-INF/IdeTipsAndTricks.xml
new file mode 100644
index 0000000..fa9847f
--- /dev/null
+++ b/resources/src/META-INF/IdeTipsAndTricks.xml
@@ -0,0 +1,155 @@
+<idea-plugin version="2">
+ <extensions defaultExtensionNs="com.intellij">
+ <!--
+ <tipAndTrick file="NotReadyYet.html"/>
+ -->
+ <tipAndTrick file="Welcome.html"/>
+ <tipAndTrick file="GoToClass.html" feature-id="navigation.popup.class"/>
+ <tipAndTrick file="CodeCompletion.html" feature-id="editing.completion.basic"/>
+ <tipAndTrick file="FindUsages.html"/>
+ <tipAndTrick file="QuickJavaDoc.html" feature-id="codeassists.quickjavadoc"/>
+ <tipAndTrick file="GoToDeclaration.html" feature-id="navigation.goto.declaration"/>
+ <tipAndTrick file="FileStructurePopup.html" feature-id="navigation.popup.file.structure"/>
+ <tipAndTrick file="Rename.html"/>
+ <tipAndTrick file="OverrideImplementMethods.html" feature-id="codeassists.overrideimplement"/>
+ <tipAndTrick file="SmartTypeCompletion.html" feature-id="editing.completion.smarttype.general"/>
+ <tipAndTrick file="TabInLookups.html" feature-id="editing.completion.replace"/>
+ <tipAndTrick file="TabInEditorClose.html"/>
+ <tipAndTrick file="AltInsertInEditor.html"/>
+ <!--<tipAndTrick file="ClosingTabsWithMiddleMouse.html"/>-->
+ <tipAndTrick file="SelectIn.html" feature-id="navigation.select.in"/>
+ <tipAndTrick file="SpeedSearch.html" feature-id="ui.tree.speedsearch"/>
+ <tipAndTrick file="Escape.html"/>
+ <tipAndTrick file="SurroundWith.html" feature-id="codeassists.surroundwith.expression"/>
+ <tipAndTrick file="SmartTypeAfterNew.html" feature-id="editing.completion.smarttype.afternew"/>
+ <tipAndTrick file="GoToImplementation.html" feature-id="navigation.goto.implementation"/>
+ <tipAndTrick file="CtrlW.html" feature-id="editing.select.word"/>
+ <tipAndTrick file="IntroduceVariable.html" feature-id="refactoring.introduceVariable"/>
+ <tipAndTrick file="CommentCode.html" feature-id="codeassists.comment.line"/>
+ <!--<tipAndTrick file="DisableBulb.html"/>-->
+ <tipAndTrick file="ExternalJavaDoc.html" feature-id="codeassists.javadoc.external"/>
+ <tipAndTrick file="SmartTypeCasting.html" feature-id="editing.completion.smarttype.casting"/>
+ <tipAndTrick file="CtrlD.html"/>
+ <tipAndTrick file="LiveTemplates.html"/>
+ <tipAndTrick file="VariableNameCompletion.html" feature-id="editing.completion.variable.name"/>
+ <tipAndTrick file="ParameterInfo.html"/>
+ <tipAndTrick file="JumpToLastEdit.html"/>
+ <tipAndTrick file="HighlightUsagesInFile.html"/>
+ <tipAndTrick file="LayoutCode.html"/>
+ <tipAndTrick file="LocalVCS.html"/>
+ <tipAndTrick file="ContextInfo.html"/>
+ <tipAndTrick file="RecentFiles.html" feature-id="navigation.recent.files"/>
+ <tipAndTrick file="NextPrevError.html"/>
+ <tipAndTrick file="InsertLiveTemplate.html"/>
+ <tipAndTrick file="MethodSeparators.html"/>
+ <tipAndTrick file="CodeCompletionMiddle.html"/>
+ <tipAndTrick file="MethodUpDown.html"/>
+ <tipAndTrick file="JoinLines.html"/>
+ <tipAndTrick file="CopyClass.html" feature-id="refactoring.copyClass"/>
+ <tipAndTrick file="ClipboardStack.html"/>
+ <tipAndTrick file="HierarchyBrowser.html"/>
+ <tipAndTrick file="BreakpointSpeedmenu.html"/>
+ <tipAndTrick file="EvaluateExpressionInEditor.html"/>
+ <tipAndTrick file="WordCompletion.html"/>
+ <tipAndTrick file="QuickJavaDocInLookups.html" feature-id="codeassists.quickjavadoc.lookup"/>
+ <tipAndTrick file="DotEtcInLookups.html" feature-id="editing.completion.finishByDotEtc"/>
+ <tipAndTrick file="MenuItemsDescriptions.html"/>
+ <tipAndTrick file="WildcardsInNavigationPopups.html"/>
+ <tipAndTrick file="MoveInnerToUpper.html"/>
+ <tipAndTrick file="IntroduceVariableIncompleteCode.html"/>
+ <tipAndTrick file="GoToSymbol.html" feature-id="navigation.popup.symbol"/>
+ <tipAndTrick file="RecentChanges.html" feature-id="ui.recentchanges"/>
+ <tipAndTrick file="ImageFileCompletion.html"/>
+ <tipAndTrick file="CreatePropertyTag.html"/>
+ <tipAndTrick file="QuickSwitchScheme.html" feature-id="ui.scheme.quickswitch"/>
+ <tipAndTrick file="CompleteStatement.html"/>
+ <tipAndTrick file="CamelPrefixesInNavigationPopups.html"/>
+ <tipAndTrick file="CtrlShiftI.html" feature-id="codeassists.quickdefinition"/>
+ <tipAndTrick file="CompletionInHTML.html"/>
+ <tipAndTrick file="CopyPasteReference.html"/>
+ <tipAndTrick file="MoveUpDown.html"/>
+ <tipAndTrick file="SelectRunDebugConfiguration.html"/>
+ <tipAndTrick file="CtrlShiftIForLookup.html" feature-id="codeassists.quickdefinition.lookup"/>
+ <tipAndTrick file="PropertiesCompletion.html"/>
+ <tipAndTrick file="ShowAppliedStyles.html"/>
+ <tipAndTrick file="ImagesLookup.html"/>
+ <tipAndTrick file="RenameCssSelector.html"/>
+ <tipAndTrick file="NavBar.html"/>
+ <tipAndTrick file="ChangesView.html"/>
+ <tipAndTrick file="Antivirus.html"/>
+ <tipAndTrick file="MavenQuickOpen.html"/>
+ <tipAndTrick file="MoveToChangelist.html"/>
+ <tipAndTrick file="EclipseQuickOpen.html"/>
+ <tipAndTrick file="ShowUsages.html"/>
+ <tipAndTrick file="GoToAction.html"/>
+ <tipAndTrick file="GoToInspection.html"/>
+ <tipAndTrick file="SearchInSettings.html"/>
+ <tipAndTrick file="CompleteMethod.html"/>
+ <tipAndTrick file="HighlightImplements.html"/>
+ <tipAndTrick file="RecentSearch.html"/>
+ <tipAndTrick file="CodeCompletionInSearch.html"/>
+ <tipAndTrick file="HighlightMethodExitPoint.html"/>
+ <tipAndTrick file="HighlightThrows.html"/>
+ <tipAndTrick file="QuickFixRightArrow.html"/>
+ <tipAndTrick file="NavigateToFilePath.html"/>
+ <tipAndTrick file="IssueNavigation.html"/>
+ <tipAndTrick file="ColorEditingInCss.html"/>
+ <tipAndTrick file="CreateTestIntentionAction.html"/>
+ <tipAndTrick file="ColumnSelection.html"/>
+ <tipAndTrick file="ColorFiles.html"/>
+ <tipAndTrick file="CopyWithNoSelection.html"/>
+ <tipAndTrick file="moveFileToChangelist.html"/>
+ <tipAndTrick file="Spellchecker.html"/>
+ <tipAndTrick file="SpellcheckerDictionaries.html"/>
+ <tipAndTrick file="VcsQuickList.html"/>
+ <tipAndTrick file="Switcher.html"/>
+ <tipAndTrick file="DragToOpen.html"/>
+ <tipAndTrick file="CloseOthers.html"/>
+ <tipAndTrick file="EnterDirectoryInGotoFile.html"/>
+ <tipAndTrick file="GotoLineInFile.html"/>
+ <tipAndTrick file="AnnotationsAndDiffs.html"/>
+ <tipAndTrick file="DirDiff.html"/>
+ <tipAndTrick file="JarDiff.html"/>
+ <tipAndTrick file="ShowHideSideBars.html"/>
+ <tipAndTrick file="ExcludeFromProject.html"/>
+ <tipAndTrick file="CodeCompletionNoShift.html"/>
+ <tipAndTrick file="CommitCtrlK.html"/>
+ <tipAndTrick file="FindReplaceToggle.html"/>
+ <tipAndTrick file="ScopesInTODO.html"/>
+ <tipAndTrick file="PreviewTODO.html"/>
+ <tipAndTrick file="FixDocComment.html"/>
+ <tipAndTrick file="SelectTasks.html"/>
+ <tipAndTrick file="RunConfigFolders.html"/>
+ <tipAndTrick file="SpeedSearchinLiveTemplates.html"/>
+ <tipAndTrick file="EditRegExp.html"/>
+
+ <tipAndTrick file="Emmet.html"/>
+ <tipAndTrick file="EscapeCharactersInResourceBundle.html"/>
+ <tipAndTrick file="LineEndings.html"/>
+ <tipAndTrick file="LineEndingsFolder.html"/>
+ <tipAndTrick file="RefactorThis.html"/>
+ <tipAndTrick file="FavoritesToolWindow1.html"/>
+ <tipAndTrick file="FavoritesToolWindow2.html"/>
+
+ <tipAndTrick file="WideScreen.html"/>
+ <tipAndTrick file="Terminal.html"/>
+ <tipAndTrick file="ConfiguringTerminal.html"/>
+
+ <tipAndTrick file="HorizontalScrolling.html" feature-id="ui.horizontal.scrolling"/>
+ <tipAndTrick file="SearchEverywhere.html" feature-id="SearchEverywhere"/>
+ <tipAndTrick file="CtrlDotInLookups.html" feature-id="editing.completion.finishByCtrlDot"/>
+ <tipAndTrick file="CancelByControlArrows.html" feature-id="editing.completion.cancelByControlArrows"/>
+ <tipAndTrick file="CamelHumpsInCodeCompletion.html" feature-id="editing.completion.camelHumps"/>
+
+ <tipAndTrick file="SecondSmartCompletionArrayMember.html" feature-id="editing.completion.second.smarttype.array.member"/>
+ <tipAndTrick file="SecondSmartCompletionAsList.html" feature-id="editing.completion.second.smarttype.aslist"/>
+ <tipAndTrick file="SecondSmartCompletionChain.html" feature-id="editing.completion.second.smarttype.chain"/>
+ <tipAndTrick file="FinishBySmartEnter.html" feature-id="editing.completion.finishBySmartEnter"/>
+ <tipAndTrick file="FinishByExclamation.html" feature-id="editing.completion.finishByExclamation"/>
+ <tipAndTrick file="CompletionImportStatic.html" feature-id="editing.completion.global.member.name"/>
+ <tipAndTrick file="FinishByControlEnter.html" feature-id="editing.completion.finishByControlEnter"/>
+ <tipAndTrick file="SecondBasicClassNameCompletion.html" feature-id="editing.completion.second.basic"/>
+ <tipAndTrick file="SecondSmartCompletionToar.html" feature-id="editing.completion.second.smarttype.toar"/>
+ <tipAndTrick file="ChangeSorting.html" feature-id="editing.completion.changeSorting"/>
+ </extensions>
+</idea-plugin>
\ No newline at end of file
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index c5e1481..e6d8f98 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -2,6 +2,7 @@
<id>com.intellij</id>
<name>IDEA CORE</name>
+ <xi:include href="/META-INF/IdeTipsAndTricks.xml" xpointer="xpointer(/idea-plugin/*)"/>
<xi:include href="/idea/RichPlatformPlugin.xml" xpointer="xpointer(/idea-plugin/*)"/>
<module value="com.intellij.modules.java"/>
<module value="com.intellij.modules.all"/>
@@ -13,6 +14,7 @@
<xi:include href="/META-INF/ManifestSupport.xml" xpointer="xpointer(/idea-plugin/*)">
<xi:fallback/>
</xi:include>
+ <xi:include href="/META-INF/PostfixTemplates.xml" xpointer="xpointer(/idea-plugin/*)"/>
<application-components>
<component>
@@ -22,29 +24,11 @@
<project-components>
<component>
- <interface-class>com.intellij.psi.JavaPsiFacade</interface-class>
- <implementation-class>com.intellij.psi.impl.JavaPsiFacadeImpl</implementation-class>
- <loadForDefaultProject/>
- </component>
-
- <component>
- <interface-class>com.intellij.pom.java.PomJavaAspect</interface-class>
- <implementation-class>com.intellij.pom.java.impl.PomJavaAspectImpl</implementation-class>
- <loadForDefaultProject/>
- </component>
-
- <component>
- <interface-class>com.intellij.psi.impl.file.impl.JavaFileManager</interface-class>
- <implementation-class>com.intellij.psi.impl.file.impl.JavaFileManagerImpl</implementation-class>
- <loadForDefaultProject/>
- </component>
-
- <component>
<implementation-class>com.intellij.codeInsight.daemon.impl.PostHighlightingPassFactory</implementation-class>
</component>
<component>
- <implementation-class>com.intellij.compilerOutputIndex.api.indexer.CompilerOutputIndexer</implementation-class>
+ <implementation-class>com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexFeaturesHolder</implementation-class>
</component>
</project-components>
@@ -228,13 +212,12 @@
<with attribute="implementationClass" implements="com.intellij.refactoring.encapsulateFields.EncapsulateFieldHelper"/>
</extensionPoint>
- <extensionPoint name="psi.clsCustomNavigationPolicy"
- interface="com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy"/>
- <extensionPoint name="psi.clsDecompiledFileProvider"
- interface="com.intellij.psi.ClsFileDecompiledPsiFileProvider"/>
-
- <extensionPoint name="java.compilerOutputIndex" area="IDEA_PROJECT"
- interface="com.intellij.compilerOutputIndex.api.indexer.CompilerOutputBaseIndex"/>
+ <extensionPoint name="psi.classFileDecompiler" interface="com.intellij.psi.compiled.ClassFileDecompilers$Decompiler"/>
+ <!-- deprecated API -->
+ <!--suppress DeprecatedClassUsageInspection -->
+ <extensionPoint name="psi.clsCustomNavigationPolicy" interface="com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy"/>
+ <!--suppress DeprecatedClassUsageInspection -->
+ <extensionPoint name="psi.clsDecompiledFileProvider" interface="com.intellij.psi.ClsFileDecompiledPsiFileProvider"/>
<extensionPoint name="vetoSPICondition" interface="com.intellij.openapi.util.Condition"/>
@@ -296,19 +279,6 @@
<definitionsScopedSearch implementation="com.intellij.codeInsight.navigation.MethodImplementationsSearch"/>
<definitionsScopedSearch implementation="com.intellij.codeInsight.navigation.ClassImplementationsSearch"/>
- <localInspection language="JAVA" shortName="UndesirableClassUsage" displayName="Undesirable class usage"
- groupName="IntelliJ IDEA Platform Inspections" enabledByDefault="true" level="WARNING"
- implementationClass="com.intellij.codeInspection.internal.UndesirableClassUsageInspection"/>
- <localInspection language="JAVA" shortName="FileEqualsUsage" displayName="File.equals() usage"
- groupName="IntelliJ IDEA Platform Inspections" enabledByDefault="true" level="WARNING"
- implementationClass="com.intellij.codeInspection.internal.FileEqualsUsageInspection"/>
- <localInspection language="JAVA" shortName="GtkPreferredJComboBoxRenderer" displayName="Preferred JComboBox renderer"
- groupName="IntelliJ IDEA Platform Inspections" enabledByDefault="true" level="WARNING"
- implementationClass="com.intellij.codeInspection.internal.GtkPreferredJComboBoxRendererInspection"/>
- <localInspection language="JAVA" shortName="UnsafeVfsRecursion" displayName="Unsafe VFS recursion"
- groupName="IntelliJ IDEA Platform Inspections" enabledByDefault="true" level="WARNING"
- implementationClass="com.intellij.codeInspection.internal.UnsafeVfsRecursionInspection"/>
-
<fileTypeFactory implementation="com.intellij.openapi.fileTypes.impl.JavaFileTypeFactory"/>
<lookup.actionProvider implementation="com.intellij.codeInsight.completion.ImportStaticLookupActionProvider" id="importStatic"/>
@@ -386,6 +356,12 @@
<projectService serviceInterface="com.intellij.ide.util.TreeClassChooserFactory"
serviceImplementation="com.intellij.ide.util.TreeClassChooserFactoryImpl"/>
+ <projectService serviceInterface="com.intellij.psi.JavaPsiFacade"
+ serviceImplementation="com.intellij.psi.impl.JavaPsiFacadeImpl"/>
+ <projectService serviceInterface="com.intellij.psi.PsiNameHelper"
+ serviceImplementation="com.intellij.psi.impl.PsiNameHelperImpl"/>
+ <projectService serviceInterface="com.intellij.psi.impl.file.impl.JavaFileManager"
+ serviceImplementation="com.intellij.psi.impl.file.impl.JavaFileManagerImpl"/>
<projectService serviceInterface="com.intellij.codeInsight.guess.GuessManager"
serviceImplementation="com.intellij.codeInsight.guess.impl.GuessManagerImpl"/>
<projectService serviceInterface="com.intellij.psi.impl.source.resolve.JavaResolveCache"
@@ -493,6 +469,7 @@
<highlightVisitor implementation="com.intellij.codeInsight.daemon.impl.analysis.HighlightVisitorImpl"/>
<lang.foldingBuilder language="JAVA" implementationClass="com.intellij.codeInsight.daemon.impl.actions.SuppressWarningsFoldingBuilder" />
+ <moduleType id="WEB_MODULE" implementationClass="com.intellij.openapi.module.WebModuleType"/>
<moduleConfigurationEditorProvider implementation="com.intellij.openapi.module.WebModuleConfigurationEditorProvider"/>
<externalProjectDataService implementation="com.intellij.externalSystem.JavaProjectDataService"/>
@@ -1031,6 +1008,9 @@
<filetype.decompiler filetype="CLASS" implementationClass="com.intellij.psi.impl.compiled.ClassFileDecompiler"/>
<filetype.stubBuilder filetype="CLASS" implementationClass="com.intellij.psi.impl.compiled.ClassFileStubBuilder"/>
+ <!--suppress DeprecatedClassUsageInspection -->
+ <applicationService serviceInterface="com.intellij.psi.impl.compiled.ClassFileDecompiler$PlatformDecompiler"
+ serviceImplementation="com.intellij.psi.impl.compiled.DeprecatedClassFileDecompiler"/>
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.ReferenceListWeigher" id="referenceList"
order="before samePsiMember"/>
@@ -1262,7 +1242,7 @@
<lang.implementationTextSelectioner language="JAVA"
implementationClass="com.intellij.codeInsight.hint.JavaImplementationTextSelectioner"/>
<gotoDeclarationHandler implementation="com.intellij.codeInsight.navigation.actions.GotoBreakContinueHandler"/>
- <navbar implementation="com.intellij.ide.navigationToolbar.JavaNavBarExtension"/>
+ <navbar implementation="com.intellij.ide.navigationToolbar.JavaNavBarExtension" order="after defaultNavbar"/>
<typeDeclarationProvider implementation="com.intellij.codeInsight.navigation.actions.JavaTypeDeclarationProvider"/>
<gotoTargetRendererProvider implementation="com.intellij.codeInsight.navigation.JavaGotoTargetRendererProvider"/>
@@ -1324,7 +1304,6 @@
<codeInsight.surroundWithRangeAdjuster implementation="com.intellij.codeInsight.generation.surroundWith.XmlSurroundWithRangeAdjuster"/>
-
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaAnnotationIndex"/>
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaAnonymousClassBaseRefOccurenceIndex"/>
<stubIndex implementation="com.intellij.psi.impl.java.stubs.index.JavaFieldNameIndex"/>
@@ -1337,9 +1316,6 @@
<stubElementTypeHolder class="com.intellij.psi.impl.java.stubs.JavaStubElementTypes"/>
- <clsStubBuilderFactory implementation="com.intellij.psi.impl.compiled.DefaultClsStubBuilderFactory" order="last"/>
-
-
<dom.customAnnotationChecker implementation="com.intellij.util.xml.impl.ExtendsClassChecker"/>
<methodNavigationOffsetProvider implementation="com.intellij.codeInsight.navigation.JavaMethodNavigationOffsetProvider"/>
@@ -1462,11 +1438,10 @@
<gotoDeclarationHandler implementation="com.intellij.codeInsight.navigation.actions.GotoLambdaParameterHandler"/>
- <java.compilerOutputIndex implementation="com.intellij.compilerOutputIndex.impl.MethodsUsageIndex"/>
<completion.contributor language="JAVA" id="methodsChainsCompletionContributor" order="first"
- implementationClass="com.intellij.codeInsight.completion.methodChains.completion.MethodsChainsCompletionContributor"/>
+ implementationClass="com.intellij.compiler.classFilesIndex.chainsSearch.completion.MethodsChainsCompletionContributor"/>
<weigher order="first" key="completion" id="methodsChains"
- implementationClass="com.intellij.codeInsight.completion.methodChains.completion.MethodsChainsWeigher"/>
+ implementationClass="com.intellij.compiler.classFilesIndex.chainsSearch.completion.MethodsChainsWeigher"/>
<applicationService serviceInterface="org.jetbrains.generate.tostring.template.TemplatesManager"
serviceImplementation="org.jetbrains.generate.tostring.template.TemplatesManager"/>
@@ -1486,8 +1461,12 @@
<refactoring.pullUpHelperFactory language="JAVA" implementationClass="com.intellij.refactoring.memberPullUp.JavaPullUpHelperFactory"/>
<hierarchy.referenceProcessor implementation="com.intellij.ide.hierarchy.call.JavaCallReferenceProcessor"/>
- <projectTemplate projectType="Java" templatePath="resources/projectTemplates/Java/Command_Line_App.zip"/>
+ <projectTemplate projectType="JAVA_MODULE" templatePath="resources/projectTemplates/Java/Command_Line_App.zip"/>
<generatedSourcesFilter implementation="com.intellij.openapi.roots.JavaGeneratedSourcesFilter"/>
+ <refactoring.elementListenerProvider implementation="com.intellij.codeInspection.ex.AdditionalAnnotationsRefactoringElementListener"/>
+ <projectOpenProcessor implementation="com.intellij.platform.PlatformProjectOpenProcessor"/>
+ <projectService serviceInterface="com.intellij.platform.ProjectBaseDirectory"
+ serviceImplementation="com.intellij.platform.ProjectBaseDirectory"/>
</extensions>
<actions>
diff --git a/resources/src/META-INF/PostfixTemplates.xml b/resources/src/META-INF/PostfixTemplates.xml
new file mode 100644
index 0000000..367c9f8
--- /dev/null
+++ b/resources/src/META-INF/PostfixTemplates.xml
@@ -0,0 +1,37 @@
+<idea-plugin version="2">
+ <extensionPoints>
+ <extensionPoint name="postfixTemplate" interface="com.intellij.codeInsight.template.postfix.templates.PostfixTemplate"/>
+ </extensionPoints>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ElseStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.IntroduceVariablePostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.NotNullCheckPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.IsNullCheckPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.NotExpressionPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ForeachPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.WhileStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.CastExpressionPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.IfStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ForAscendingPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ForDescendingPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.IntroduceFieldPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ParenthesizedExpressionPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ReturnStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.SwitchStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.ThrowExceptionPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.AssertStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.SynchronizedStatementPostfixTemplate"/>
+ <postfixTemplate implementation="com.intellij.codeInsight.template.postfix.templates.InstanceofExpressionPostfixTemplate"/>
+ </extensions>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <applicationService id="postfixCompletionSettings" serviceImplementation="com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings"/>
+ <customLiveTemplate implementation="com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate"/>
+
+ <completion.contributor language="JAVA" implementationClass="com.intellij.codeInsight.template.postfix.completion.PostfixTemplateCompletionContributor"/>
+ <lookup.actionProvider implementation="com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupActionProvider"/>
+
+ <editorOptionsProvider id="editing.postfixCompletion" instance="com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesConfigurable"/>
+ </extensions>
+</idea-plugin>
\ No newline at end of file
diff --git a/resources/src/idea/RichPlatformActions.xml b/resources/src/idea/RichPlatformActions.xml
index 803383d..52bc9e8 100644
--- a/resources/src/idea/RichPlatformActions.xml
+++ b/resources/src/idea/RichPlatformActions.xml
@@ -426,9 +426,5 @@
<add-to-group group-id="ToolsBasicGroup" anchor="after" relative-to-action="SaveFileAsTemplate"/>
</group>
- <action internal="true" class="com.intellij.ide.projectWizard.NewProjectWizardAction" text="Launch New Project Wizard">
- <add-to-group group-id="ToolsBasicGroup"/>
- </action>
-
</actions>
</component>
diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml
index 11b2997..e6ab127 100644
--- a/resources/src/idea/RichPlatformPlugin.xml
+++ b/resources/src/idea/RichPlatformPlugin.xml
@@ -10,13 +10,6 @@
<xi:include href="/componentSets/IdeaComponents.xml" xpointer="xpointer(/components/*)"/>
<xi:include href="/idea/RichPlatformActions.xml" xpointer="xpointer(/component/*)"/>
- <application-components>
- <component>
- <interface-class>com.intellij.ide.RecentProjectsManagerBase</interface-class>
- <implementation-class>com.intellij.ide.RecentProjectsManager</implementation-class>
- </component>
- </application-components>
-
<project-components>
<component>
<implementation-class>com.intellij.framework.detection.impl.FrameworkDetectionManager</implementation-class>
@@ -61,7 +54,9 @@
interface="com.intellij.execution.runners.JavaProgramPatcher"/>
<extensionPoint name="OrderRootTypeUI"
- beanClass="com.intellij.openapi.extensions.KeyedFactoryEPBean"/>
+ beanClass="com.intellij.openapi.extensions.KeyedFactoryEPBean">
+ <with attribute="implementationClass" implements="com.intellij.openapi.roots.ui.OrderRootTypeUIFactory"/>
+ </extensionPoint>
<extensionPoint name="packaging.elementType" interface="com.intellij.packaging.elements.PackagingElementType"/>
<extensionPoint name="packaging.artifactPropertiesProvider" interface="com.intellij.packaging.artifacts.ArtifactPropertiesProvider"/>
@@ -79,13 +74,16 @@
<extensionPoint name="projectImportBuilder" interface="com.intellij.projectImport.ProjectImportBuilder"/>
<extensionPoint name="projectStructureDetector" interface="com.intellij.ide.util.projectWizard.importSources.ProjectStructureDetector"/>
- <extensionPoint name="codeInsight.wordCompletionFilter" beanClass="com.intellij.lang.LanguageExtensionPoint"/>
+ <extensionPoint name="codeInsight.wordCompletionFilter" beanClass="com.intellij.lang.LanguageExtensionPoint">
+ <with attribute="implementationClass" implements="com.intellij.lang.WordCompletionElementFilter"/>
+ </extensionPoint>
<extensionPoint name="projectStructureConfigurableFilter" interface="com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableFilter"/>
<extensionPoint name="projectStructureConfigurableAdder" interface="com.intellij.openapi.roots.ui.configuration.ProjectStructureConfigurableContributor"/>
<extensionPoint name="compiler" area="IDEA_PROJECT" interface="com.intellij.openapi.compiler.Compiler"/>
<extensionPoint name="compilerFactory" area="IDEA_PROJECT" interface="com.intellij.openapi.compiler.CompilerFactory"/>
+ <extensionPoint name="compiler.task" area="IDEA_PROJECT" beanClass="com.intellij.compiler.CompileTaskBean"/>
<extensionPoint name="compilerSettingsFactory" area="IDEA_PROJECT" interface="com.intellij.compiler.CompilerSettingsFactory"/>
<extensionPoint name="compileServer.plugin" beanClass="com.intellij.compiler.server.CompileServerPlugin"/>
<extensionPoint name="buildProcess.parametersProvider" area="IDEA_PROJECT" interface="com.intellij.compiler.server.BuildProcessParametersProvider"/>
@@ -129,6 +127,9 @@
<compiler implementation="com.intellij.packaging.impl.compiler.ArtifactsCompiler" id="artifactsCompiler"/>
<gotoRelatedProvider implementation="com.intellij.testIntegration.GotoTestRelatedProvider"/>
+ <applicationService serviceInterface="com.intellij.ide.RecentProjectsManagerBase"
+ serviceImplementation="com.intellij.ide.RecentProjectsManager"/>
+
<applicationService serviceInterface="com.intellij.util.descriptors.ConfigFileFactory"
serviceImplementation="com.intellij.util.descriptors.impl.ConfigFileFactoryImpl"/>
@@ -312,11 +313,8 @@
<!--
<projectTemplatesFactory implementation="com.intellij.platform.templates.RemoteTemplatesFactory"/>
-->
- <projectTemplatesFactory implementation="com.intellij.platform.templates.PlainModuleTemplatesFactory"/>
<projectTemplateFileProcessor implementation="com.intellij.platform.templates.SystemFileProcessor"/>
- <projectWizard.projectCategory implementation="com.intellij.ide.projectWizard.BuilderBasedProjectType$Empty"/>
-
<applicationService serviceImplementation="com.intellij.ide.util.newProjectWizard.SelectTemplateSettings"/>
<gotoFileContributor implementation="com.intellij.ide.util.gotoByName.ProjectBaseDirNavigationContributor"/>
@@ -388,6 +386,8 @@
<moduleRendererFactory implementation="com.intellij.ide.util.DefaultModuleRendererFactory" order="last"/>
<projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaResourceRootEditHandler"/>
<projectStructure.sourceRootEditHandler implementation="com.intellij.openapi.roots.ui.configuration.JavaTestResourceRootEditHandler"/>
+
+ <buildProcess.parametersProvider implementation="com.intellij.compiler.classFilesIndex.api.index.ClassFilesIndexerBuilderParametersProvider"/>
</extensions>
<xi:include href="/META-INF/xdebugger.xml" xpointer="xpointer(/idea-plugin/*)"/>
diff --git a/samples/textEditor/src/myDocumentFiles/MyVisualPanel.java b/samples/textEditor/src/myDocumentFiles/MyVisualPanel.java
index 2a627a0..9df683f 100644
--- a/samples/textEditor/src/myDocumentFiles/MyVisualPanel.java
+++ b/samples/textEditor/src/myDocumentFiles/MyVisualPanel.java
@@ -116,7 +116,7 @@
}
if (!initialFileContent.equals(myFileEditor.getText())) {
if (Messages.showYesNoDialog("The file " + selectedVFile.getName() +
- " has been changed. Are you sure you want to overwrite it?", "File Changed", Messages.getQuestionIcon()) == 0) {
+ " has been changed. Are you sure you want to overwrite it?", "File Changed", Messages.getQuestionIcon()) == Messages.YES) {
if (docFile.isWritable()) {
docFile.setText(myFileEditor.getText());
} else {
diff --git a/spellchecker/src/com/intellij/spellchecker/SpellCheckerSeveritiesProvider.java b/spellchecker/src/com/intellij/spellchecker/SpellCheckerSeveritiesProvider.java
index 6ac8570..bfa7b55 100644
--- a/spellchecker/src/com/intellij/spellchecker/SpellCheckerSeveritiesProvider.java
+++ b/spellchecker/src/com/intellij/spellchecker/SpellCheckerSeveritiesProvider.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.
@@ -29,7 +29,7 @@
import org.jetbrains.annotations.NotNull;
import java.awt.*;
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class SpellCheckerSeveritiesProvider extends SeveritiesProvider {
@@ -38,16 +38,13 @@
@Override
@NotNull
public List<HighlightInfoType> getSeveritiesHighlightInfoTypes() {
- final List<HighlightInfoType> result = new ArrayList<HighlightInfoType>();
-
final TextAttributes attributes = new TextAttributes();
attributes.setEffectType(EffectType.WAVE_UNDERSCORE);
attributes.setEffectColor(new Color(0, 128, 0));
- result.add(new HighlightInfoType.HighlightInfoTypeImpl(TYPO,
- TextAttributesKey.createTextAttributesKey("TYPO", attributes)));
- return result;
+ HighlightInfoType typo = new HighlightInfoType.HighlightInfoTypeImpl(TYPO, TextAttributesKey.createTextAttributesKey("TYPO", attributes));
+ return Collections.singletonList(typo);
}
@Override
diff --git a/spellchecker/src/com/intellij/spellchecker/english.dic b/spellchecker/src/com/intellij/spellchecker/english.dic
index 55ef34c..169e4c2 100644
--- a/spellchecker/src/com/intellij/spellchecker/english.dic
+++ b/spellchecker/src/com/intellij/spellchecker/english.dic
@@ -45419,6 +45419,7 @@
cesspool
cesspool's
cesspools
+cesure
cetacean
cetaceans
cg
@@ -96079,6 +96080,7 @@
pared
paregoric
paregoric's
+paren
parent
parent's
parentage
@@ -114872,6 +114874,7 @@
simplicities
simplicity
simplicity's
+simplifiable
simplification
simplifications
simplified
@@ -120550,6 +120553,7 @@
submitter
submitters
submitting
+subnet
subnormal
suboptimal
suborbital
diff --git a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
index 0dbb113..ccf39a5 100644
--- a/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
+++ b/spellchecker/src/com/intellij/spellchecker/jetbrains.dic
@@ -43,6 +43,7 @@
btree
buffered
buffering
+buildable
builtin
bzip
calc
@@ -73,6 +74,7 @@
codesign
commandline
committer
+commonjs
conf
config
configs
@@ -89,6 +91,7 @@
datafile
datafiles
datetime
+dbcp
dealloc
deallocate
decompile
@@ -116,6 +119,7 @@
dtrace
dumpfile
dylib
+easymock
ehcache
elseif
elsif
@@ -127,6 +131,7 @@
exif
expr
facebook
+facelet
favicon
filename
fileset
@@ -136,6 +141,7 @@
finalizer
finalizers
firefox
+fixme
foreach
formatter
freelist
@@ -167,6 +173,7 @@
hostname
hprof
href
+hsql
hsqldb
html
http
@@ -199,7 +206,10 @@
javafx
javascript
javax
+jaxb
+jaxen
jetbrains
+jibx
jndi
jnilib
jpeg
@@ -240,6 +250,7 @@
lvalue
lvalues
macrodef
+makefile
maxdatafiles
maxextents
maximizable
@@ -299,6 +310,7 @@
nomonitoring
nonatomic
noninfingement
+nonnull
nonschema
noorder
noparallel
@@ -327,7 +339,9 @@
outfile
overrider
overriders
+pageable
param
+parameterizable
params
patcher
patchers
@@ -348,6 +362,7 @@
plugins
pointcut
pointcuts
+portlet
polyadic
popup
popups
@@ -369,15 +384,18 @@
profiler
progressbar
proven
+proxool
pycharm
readme
readonly
readwrite
+rearranger
rebase
rebased
rebasing
rect
redis
+redispatch
redistributions
refactor
refactored
@@ -394,6 +412,7 @@
reifying
reindex
renderer
+replacer
repo
resetlogs
resizable
@@ -423,10 +442,45 @@
servererror
servlet
servlets
+severities
sftp
shader
+sigabrt
+sigaio
+sigalrm
+sigbus
+sigchld
+sigcont
+sigemt
+sigfpe
+sighup
+sigill
+sigint
+sigkill
+siglwp
significand
significands
+sigpipe
+sigpoll
+sigprof
+sigpwr
+sigquit
+sigsegv
+sigstop
+sigsys
+sigterm
+sigtrap
+sigtstp
+sigttin
+sigttou
+sigurg
+sigusr1
+sigusr2
+sigvtalrm
+sigwaiting
+sigwinch
+sigxcpu
+sigxfsz
smallfile
smallint
soname
@@ -463,6 +517,7 @@
superclasses
superview
superviews
+sybase
symlink
symlinks
sysdate
@@ -480,6 +535,7 @@
toggleable
tokenize
tokenizer
+toolchain
tooltip
tooltips
toplink
@@ -503,6 +559,7 @@
unprotect
unwatch
uploader
+urlencoded
urowid
username
utf
@@ -523,6 +580,7 @@
viewlet
vtlvariable
watchlist
+webpack
webservice
whitespace
whitespaces
@@ -532,10 +590,12 @@
wildcards
wordwrap
workflow
+writeln
wsdl
xcode
xcodeproj
xhtml
+xmlbeans
xmlschema
xmlschemas
xmltype
diff --git a/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java b/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java
index 31c0462..b71b599 100644
--- a/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.java
+++ b/spellchecker/src/com/intellij/spellchecker/ui/SpellCheckingEditorCustomization.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.
@@ -25,6 +25,7 @@
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.spellchecker.inspections.SpellCheckingInspection;
import com.intellij.ui.SimpleEditorCustomization;
@@ -152,8 +153,8 @@
}
@Override
- public boolean isToolEnabled(HighlightDisplayKey key) {
- return myDelegate.isToolEnabled(key) && SPELL_CHECK_TOOLS.containsKey(key.toString()) && myUseSpellCheck;
+ public boolean isToolEnabled(HighlightDisplayKey key, PsiElement element) {
+ return myDelegate.isToolEnabled(key, element) && SPELL_CHECK_TOOLS.containsKey(key.toString()) && myUseSpellCheck;
}
public void setUseSpellCheck(boolean useSpellCheck) {
diff --git a/spellchecker/src/com/intellij/spellchecker/util/SpellCheckerBundle.java b/spellchecker/src/com/intellij/spellchecker/util/SpellCheckerBundle.java
index cc9f63c..cf4c87b 100644
--- a/spellchecker/src/com/intellij/spellchecker/util/SpellCheckerBundle.java
+++ b/spellchecker/src/com/intellij/spellchecker/util/SpellCheckerBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -17,21 +17,22 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.util.ResourceBundle;
public final class SpellCheckerBundle {
- @NonNls
- private static final String BUNDLE_NAME = "com.intellij.spellchecker.util.SpellCheckerBundle";
- private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
- private SpellCheckerBundle() {
- }
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE_NAME) String key, @NotNull Object... params) {
+ return CommonBundle.message(BUNDLE, key, params);
+ }
- public static String message(@PropertyKey(resourceBundle = BUNDLE_NAME) String key, Object... params) {
- return CommonBundle.message(BUNDLE, key, params);
-
- }
+ @NonNls
+ private static final String BUNDLE_NAME = "com.intellij.spellchecker.util.SpellCheckerBundle";
+ private static final ResourceBundle BUNDLE = ResourceBundle.getBundle(BUNDLE_NAME);
+
+ private SpellCheckerBundle() {
+ }
}
diff --git a/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java b/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java
new file mode 100644
index 0000000..3fd653f
--- /dev/null
+++ b/spellchecker/testSrc/com/intellij/spellchecker/ui/SpellCheckingEditorCustomizationTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.spellchecker.ui;
+
+import com.intellij.codeInspection.ex.InspectionProfileImpl;
+import com.intellij.openapi.editor.ex.EditorEx;
+import com.intellij.openapi.fileTypes.PlainTextFileType;
+import com.intellij.spellchecker.inspections.SpellCheckingInspection;
+import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
+
+public class SpellCheckingEditorCustomizationTest extends LightPlatformCodeInsightFixtureTestCase {
+ public void testEnabled() throws Exception {
+ doTest(true, "<TYPO descr=\"Typo: In word 'missspelling'\">missspelling</TYPO>");
+ }
+
+ public void testDisabled() throws Exception {
+ doTest(false, "missspelling");
+ }
+
+ @Override
+ protected boolean isWriteActionRequired() {
+ return false;
+ }
+
+ private void doTest(boolean enabled, String document) {
+ InspectionProfileImpl.INIT_INSPECTIONS = true;
+ try {
+ myFixture.configureByText(PlainTextFileType.INSTANCE, document);
+ myFixture.enableInspections(new SpellCheckingInspection());
+
+ SpellCheckingEditorCustomization.getInstance(enabled).customize((EditorEx)myFixture.getEditor());
+
+ myFixture.checkHighlighting();
+ }
+ finally {
+ InspectionProfileImpl.INIT_INSPECTIONS = false;
+ }
+ }
+}
diff --git a/tools/launcher-generator/src/com/pme/launcher/LauncherGeneratorMain.java b/tools/launcher-generator/src/com/pme/launcher/LauncherGeneratorMain.java
index 41f6eb4..ece9dbd 100644
--- a/tools/launcher-generator/src/com/pme/launcher/LauncherGeneratorMain.java
+++ b/tools/launcher-generator/src/com/pme/launcher/LauncherGeneratorMain.java
@@ -164,6 +164,7 @@
generator.setVersionInfoString("LegalCopyright", "Copyright (C) 2000-" + year + " " + companyName);
generator.setVersionInfoString("ProductName", productFullName);
generator.setVersionInfoString("FileVersion", versionString);
+ generator.setVersionInfoString("FileDescription", productFullName);
generator.setVersionInfoString("ProductVersion", versionString);
generator.setVersionInfoString("InternalName", productShortName.toLowerCase() + ".exe");
generator.setVersionInfoString("OriginalFilename", productShortName.toLowerCase() + ".exe");
diff --git a/updater/src/com/intellij/updater/BaseUpdateAction.java b/updater/src/com/intellij/updater/BaseUpdateAction.java
index 2ddfb68..1d5e5a1 100644
--- a/updater/src/com/intellij/updater/BaseUpdateAction.java
+++ b/updater/src/com/intellij/updater/BaseUpdateAction.java
@@ -60,6 +60,7 @@
protected void writeDiff(InputStream olderFileIn, InputStream newerFileIn, ZipOutputStream patchOutput)
throws IOException {
+ Runner.logger.info("writing diff");
ByteArrayOutputStream diffOutput = new ByteArrayOutputStream();
byte[] newerFileBuffer = JBDiff.bsdiff(olderFileIn, newerFileIn, diffOutput);
diffOutput.close();
diff --git a/updater/src/com/intellij/updater/ConsoleUpdaterUI.java b/updater/src/com/intellij/updater/ConsoleUpdaterUI.java
index 677502e..c1114dd 100644
--- a/updater/src/com/intellij/updater/ConsoleUpdaterUI.java
+++ b/updater/src/com/intellij/updater/ConsoleUpdaterUI.java
@@ -10,6 +10,7 @@
public void startProcess(String title) {
System.out.println(title);
+ Runner.logger.info("title: " + title);
}
public void setProgress(int percentage) {
@@ -20,6 +21,7 @@
public void setStatus(String status) {
System.out.println(myStatus = status);
+ Runner.logger.info("status: " + status);
}
public void showError(Throwable e) {
diff --git a/updater/src/com/intellij/updater/CreateAction.java b/updater/src/com/intellij/updater/CreateAction.java
index aeeb5ed..1d6ca0c 100644
--- a/updater/src/com/intellij/updater/CreateAction.java
+++ b/updater/src/com/intellij/updater/CreateAction.java
@@ -18,6 +18,7 @@
}
protected void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
+ Runner.logger.info("building PatchFile");
patchOutput.putNextEntry(new ZipEntry(myPath));
writeExecutableFlag(patchOutput, newerFile);
@@ -28,6 +29,7 @@
@Override
protected ValidationResult doValidate(File toFile) {
+ Runner.logger.info("validation the result");
ValidationResult result = doValidateAccess(toFile, ValidationResult.Action.CREATE);
if (result != null) return result;
diff --git a/updater/src/com/intellij/updater/Digester.java b/updater/src/com/intellij/updater/Digester.java
index 326f829..00792ce 100644
--- a/updater/src/com/intellij/updater/Digester.java
+++ b/updater/src/com/intellij/updater/Digester.java
@@ -28,6 +28,7 @@
zipFile = new ZipFile(file);
}
catch (IOException e) {
+ Runner.printStackTrace(e);
return doDigestRegularFile(file);
}
diff --git a/updater/src/com/intellij/updater/Patch.java b/updater/src/com/intellij/updater/Patch.java
index 71a9a52..9b66535 100644
--- a/updater/src/com/intellij/updater/Patch.java
+++ b/updater/src/com/intellij/updater/Patch.java
@@ -34,6 +34,7 @@
throws IOException, OperationCancelledException {
DiffCalculator.Result diff;
+ Runner.logger.info("Calculating difference...");
ui.startProcess("Calculating difference...");
ui.checkCancelled();
@@ -60,6 +61,7 @@
}
}
+ Runner.logger.info("Preparing actions...");
ui.startProcess("Preparing actions...");
ui.checkCancelled();
@@ -146,6 +148,7 @@
final LinkedHashSet<String> files = Utils.collectRelativePaths(toDir);
final List<ValidationResult> result = new ArrayList<ValidationResult>();
+ Runner.logger.info("Validating installation...");
forEach(myActions, "Validating installation...", ui, true,
new ActionsProcessor() {
public void forEach(PatchAction each) throws IOException {
@@ -197,10 +200,12 @@
});
}
catch (OperationCancelledException e) {
+ Runner.printStackTrace(e);
shouldRevert = true;
cancelled = true;
}
catch (Throwable e) {
+ Runner.printStackTrace(e);
shouldRevert = true;
ui.showError(e);
}
diff --git a/updater/src/com/intellij/updater/PatchAction.java b/updater/src/com/intellij/updater/PatchAction.java
index 76259f0..42afb50 100644
--- a/updater/src/com/intellij/updater/PatchAction.java
+++ b/updater/src/com/intellij/updater/PatchAction.java
@@ -102,9 +102,11 @@
return true;
}
catch (OverlappingFileLockException e) {
+ Runner.printStackTrace(e);
return false;
}
catch (IOException e) {
+ Runner.printStackTrace(e);
return false;
}
}
diff --git a/updater/src/com/intellij/updater/PatchFileCreator.java b/updater/src/com/intellij/updater/PatchFileCreator.java
index 4eab80c..e889237 100644
--- a/updater/src/com/intellij/updater/PatchFileCreator.java
+++ b/updater/src/com/intellij/updater/PatchFileCreator.java
@@ -20,7 +20,9 @@
List<String> criticalFiles,
List<String> optionalFiles,
UpdaterUI ui) throws IOException, OperationCancelledException {
+
Patch patchInfo = new Patch(olderDir, newerDir, ignoredFiles, criticalFiles, optionalFiles, ui);
+ Runner.logger.info("Creating the patch file '" + patchFile + "'...");
ui.startProcess("Creating the patch file '" + patchFile + "'...");
ui.checkCancelled();
@@ -34,6 +36,8 @@
List<PatchAction> actions = patchInfo.getActions();
for (PatchAction each : actions) {
+
+ Runner.logger.info("Packing " + each.getPath());
ui.setStatus("Packing " + each.getPath());
ui.checkCancelled();
each.buildPatchFile(olderDir, newerDir, out);
diff --git a/updater/src/com/intellij/updater/Runner.java b/updater/src/com/intellij/updater/Runner.java
index 2935f7c..462a6b3 100644
--- a/updater/src/com/intellij/updater/Runner.java
+++ b/updater/src/com/intellij/updater/Runner.java
@@ -1,5 +1,10 @@
package com.intellij.updater;
+import org.apache.log4j.FileAppender;
+import org.apache.log4j.Level;
+import org.apache.log4j.Logger;
+import org.apache.log4j.PatternLayout;
+
import javax.swing.*;
import java.io.*;
import java.net.URI;
@@ -11,21 +16,21 @@
import java.util.zip.ZipInputStream;
public class Runner {
+ public static Logger logger = null;
private static final String PATCH_FILE_NAME = "patch-file.zip";
private static final String PATCH_PROPERTIES_ENTRY = "patch.properties";
private static final String OLD_BUILD_DESCRIPTION = "old.build.description";
private static final String NEW_BUILD_DESCRIPTION = "new.build.description";
public static void main(String[] args) throws Exception {
- if (args.length != 2 && args.length < 6) {
+ if (args.length != 3 && args.length < 7) {
printUsage();
return;
}
String command = args[0];
-
if ("create".equals(command)) {
- if (args.length < 6) {
+ if (args.length < 7) {
printUsage();
return;
}
@@ -34,18 +39,24 @@
String oldFolder = args[3];
String newFolder = args[4];
String patchFile = args[5];
+ String logFolder = args[6];
+ initLogger(logFolder);
+
List<String> ignoredFiles = extractFiles(args, "ignored");
List<String> criticalFiles = extractFiles(args, "critical");
List<String> optionalFiles = extractFiles(args, "optional");
create(oldVersionDesc, newVersionDesc, oldFolder, newFolder, patchFile, ignoredFiles, criticalFiles, optionalFiles);
}
else if ("install".equals(command)) {
- if (args.length != 2) {
+ if (args.length != 3) {
printUsage();
return;
}
String destFolder = args[1];
+ String logFolder = args[2];
+ initLogger(logFolder);
+ logger.info("destFolder: " + destFolder);
install(destFolder);
}
else {
@@ -54,6 +65,59 @@
}
}
+ private static boolean validateLogDir(String logFolder){
+ File fileLogDir = new File(logFolder);
+ /* check if the dir for log file
+ 1)exists 2)has write perm. and 5)has 1MB+ free space */
+ if (!fileLogDir.exists() || !fileLogDir.canWrite() || fileLogDir.getUsableSpace() < 1000000){
+ return false;
+ }
+ return true;
+ }
+
+ private static String getLogDir(String logFolder){
+ if (!validateLogDir(logFolder)){
+ logFolder = System.getProperty("java.io.tmpdir");
+ if (!validateLogDir(logFolder)){
+ logFolder = System.getProperty("user.home");
+ }
+ }
+ System.out.println("Log dir: " + logFolder);
+ return logFolder;
+ }
+
+ public static void initLogger(String logFolder) {
+ if (logger == null) {
+ logFolder = getLogDir(logFolder);
+ FileAppender update = new FileAppender();
+
+ update.setFile(new File(logFolder, "idea_updater.log").getAbsolutePath());
+ update.setLayout(new PatternLayout("%d{dd MMM yyyy HH:mm:ss} %-5p %C{1}.%M - %m%n"));
+ update.setThreshold(Level.ALL);
+ update.setAppend(true);
+ update.activateOptions();
+
+ FileAppender updateError = new FileAppender();
+ 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();
+
+ logger = Logger.getLogger("com.intellij.updater");
+ logger.addAppender(updateError);
+ logger.addAppender(update);
+ logger.setLevel(Level.ALL);
+
+ logger.info("--- Updater started ---");
+ }
+ }
+
+ public static void printStackTrace(Throwable e){
+ logger.error(e.getMessage(), e);
+ }
+
public static List<String> extractFiles(String[] args, String paramName) {
List<String> result = new ArrayList<String>();
for (String param : args) {
@@ -94,6 +158,7 @@
optionalFiles,
ui);
+ logger.info("Packing jar file: " + patchFile );
ui.startProcess("Packing jar file '" + patchFile + "'...");
FileOutputStream fileOut = new FileOutputStream(patchFile);
@@ -135,6 +200,7 @@
}
private static void cleanup(UpdaterUI ui) throws IOException {
+ logger.info("Cleaning up...");
ui.startProcess("Cleaning up...");
ui.setProgressIndeterminate();
Utils.cleanup();
@@ -157,6 +223,7 @@
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
}
catch (Exception ignore) {
+ printStackTrace(ignore);
}
}
});
@@ -165,6 +232,7 @@
props.getProperty(NEW_BUILD_DESCRIPTION),
new SwingUpdaterUI.InstallOperation() {
public boolean execute(UpdaterUI ui) throws OperationCancelledException {
+ logger.info("installing patch to the " + destFolder);
return doInstall(ui, destFolder);
}
});
@@ -176,6 +244,7 @@
File patchFile = Utils.createTempFile();
ZipFile jarFile = new ZipFile(resolveJarFile());
+ logger.info("Extracting patch file...");
ui.startProcess("Extracting patch file...");
ui.setProgressIndeterminate();
try {
@@ -202,6 +271,7 @@
}
catch (IOException e) {
ui.showError(e);
+ printStackTrace(e);
}
}
finally {
@@ -210,6 +280,7 @@
}
catch (IOException e) {
ui.showError(e);
+ printStackTrace(e);
}
}
@@ -233,6 +304,7 @@
return new File(new URI(jarFileUrl));
}
catch (URISyntaxException e) {
+ printStackTrace(e);
throw new IOException(e.getMessage());
}
}
diff --git a/updater/src/com/intellij/updater/SwingUpdaterUI.java b/updater/src/com/intellij/updater/SwingUpdaterUI.java
index 1fa8514..d44fc2e 100644
--- a/updater/src/com/intellij/updater/SwingUpdaterUI.java
+++ b/updater/src/com/intellij/updater/SwingUpdaterUI.java
@@ -135,6 +135,7 @@
Thread.sleep(100);
}
catch (InterruptedException e) {
+ Runner.printStackTrace(e);
return;
}
@@ -180,8 +181,10 @@
myApplied = myOperation.execute(SwingUpdaterUI.this);
}
catch (OperationCancelledException ignore) {
+ Runner.printStackTrace(ignore);
}
catch(Throwable e) {
+ Runner.printStackTrace(e);
showError(e);
}
finally {
diff --git a/updater/src/com/intellij/updater/UpdateZipAction.java b/updater/src/com/intellij/updater/UpdateZipAction.java
index 672d357..7741b81 100644
--- a/updater/src/com/intellij/updater/UpdateZipAction.java
+++ b/updater/src/com/intellij/updater/UpdateZipAction.java
@@ -103,6 +103,8 @@
new ZipFile(newerFile).close();
}
catch (IOException e) {
+ Runner.logger.error("Corrupted target file: " + newerFile);
+ Runner.printStackTrace(e);
throw new IOException("Corrupted target file: " + newerFile, e);
}
@@ -115,6 +117,8 @@
olderZip = new ZipFile(olderFile);
}
catch (IOException e) {
+ Runner.logger.error("Corrupted source file: " + olderFile);
+ Runner.printStackTrace(e);
throw new IOException("Corrupted source file: " + olderFile, e);
}
@@ -137,6 +141,8 @@
patchOutput.closeEntry();
}
catch (IOException e) {
+ Runner.logger.error("Error building patch for .zip entry " + name);
+ Runner.printStackTrace(e);
throw new IOException("Error building patch for .zip entry " + name, e);
}
}
diff --git a/updater/src/com/intellij/updater/Utils.java b/updater/src/com/intellij/updater/Utils.java
index 666ac1a..03ca264 100644
--- a/updater/src/com/intellij/updater/Utils.java
+++ b/updater/src/com/intellij/updater/Utils.java
@@ -20,6 +20,7 @@
myTempDir = File.createTempFile("idea.updater.", ".tmp");
delete(myTempDir);
myTempDir.mkdirs();
+ Runner.logger.info("created temp file: " + myTempDir.getPath());
}
return File.createTempFile("temp.", ".tmp", myTempDir);
@@ -28,13 +29,16 @@
public static File createTempDir() throws IOException {
File result = createTempFile();
delete(result);
+ Runner.logger.info("deleted tmp dir: " + result.getPath());
result.mkdirs();
+ Runner.logger.info("created tmp dir: " + result.getPath());
return result;
}
public static void cleanup() throws IOException {
if (myTempDir == null) return;
delete(myTempDir);
+ Runner.logger.info("deleted file " + myTempDir.getPath());
myTempDir = null;
}
@@ -44,6 +48,7 @@
if (files != null) {
for (File each : files) {
delete(each);
+ Runner.logger.info("deleted file " + each.getPath());
}
}
}
@@ -53,6 +58,7 @@
Thread.sleep(10);
}
catch (InterruptedException ignore) {
+ Runner.printStackTrace(ignore);
}
}
if (file.exists()) throw new IOException("Cannot delete file " + file);
@@ -60,11 +66,13 @@
public static void setExecutable(File file, boolean executable) throws IOException {
if (executable && !file.setExecutable(true)) {
+ Runner.logger.error("Can't set executable permissions for file");
throw new IOException("Cannot set executable permissions for: " + file);
}
}
public static void copy(File from, File to) throws IOException {
+ Runner.logger.info("from " + from.getPath() + " to " + to.getPath());
if (from.isDirectory()) {
File[] files = from.listFiles();
if (files == null) throw new IOException("Cannot get directory's content: " + from);
@@ -141,6 +149,7 @@
public static InputStream getEntryInputStream(ZipFile zipFile, String entryPath) throws IOException {
InputStream result = findEntryInputStream(zipFile, entryPath);
if (result == null) throw new IOException("Entry " + entryPath + " not found");
+ Runner.logger.info("entryPath: " + entryPath);
return result;
}
diff --git a/updater/testData/Readme.txt b/updater/testData/Readme.txt
new file mode 100644
index 0000000..c509af0
--- /dev/null
+++ b/updater/testData/Readme.txt
@@ -0,0 +1,166 @@
+IntelliJ IDEA 8.0M1 - README
+
+Thank you for downloading IntelliJ IDEA!
+
+IntelliJ IDEA is a multi-platform Java IDE, which includes intelligent editor, rich-featured GUI designer,
+visual debugger, javac/jikes/rmic compiler integration, refactoring, enhanced project navigation,
+intelligent code inspection and analysis features, J2EE and JDK 1.5 support.
+
+
+Contents:
+=========
+ BUILD.TXT File containing the current build number
+ KnownIssues.TXT Known issues and workarounds
+ README.TXT This file
+ bin/ Startup scripts for launching IntelliJ IDEA
+ help/ Online help files
+ jre/ Bundled JRE
+ lib/ Library files
+ license/ License files for IntelliJ IDEA and bundled software
+ plugins/ Standard plugins
+ redist/ Contains libraries that need to be redistributed with your application if certain IDEA features are used:
+ - forms_rt.jar should be distributed with your applications that use GUI forms with
+ the "GridLayoutManager (IntelliJ)" layout manager
+ - javac2.jar is an Ant task for building applications that use IntelliJ IDEA's UI Designer
+ bytecode generation or @NotNull assertions generation
+ - annotations.jar contains JDK 1.5 annotation classes for 'Constant Conditions & Exceptions' inspection tool.
+
+ Install-Linux-tar.txt Installation instructions for Linux (included in Linux installation package only)
+ Install-Windows-zip.txt Installation instructions for Windows zip-file (included in Windows zip installation package only)
+
+ USER_HOME/.IntelliJIdea80/
+
+ config/ Configuration files (See INSTALLATION_HOME/bin/idea.properties to tweak location of the configs)
+ codestyles/ User's code style settings
+ colors/ User's colors and fonts settings
+ fileTemplates/ Custom file templates
+ filetypes/ Custom file types
+ ideTalk/ ideTalk settings
+ inspection/ Executable file and auxiliary data for running offline code inspections
+ keymaps/ Contains files with custom keymaps
+ migration/ API migration map
+ options/ IDE options configuration files
+ plugins/ Directory for custom plugins (it appears after the 1st plugin is installed)
+ shelf/ Shelved changes (in standard .patch file format)
+ templates/ Live templates, both built-in and custom
+ tools/ External tools
+ idea70.key File containing your license key (editing not recommended)
+
+ system/ Various IDEA internal caches including Local History data storage.
+ (See INSTALLATION_HOME/bin/idea.properties to tweak location of the caches).
+ Also log directory with IDEA log files is located there.
+
+
+Installing IntelliJ IDEA
+========================
+ For Linux and other Generic Unix users:
+ Please read the contents of the Install-Linux-tar.txt file.
+
+ Installing on Mac OS:
+ IntelliJ IDEA is distributed as a .dmg file. You only need to drag it to
+ the destination folder, from which you can start the application.
+
+Uninstalling IntelliJ IDEA
+==========================
+ If you installed IntelliJ IDEA with the help of Installation Wizard, then
+ just run the INSTALLATION_HOME/bin/Uninstall.exe file
+
+ To uninstall IntelliJ IDEA after manual installation, simply delete the
+ contents of the IntelliJ IDEA home installation directory.
+
+
+Licensing & pricing
+==========================
+ Licensing and pricing information can be found at http://www.jetbrains.com/idea/buy/index.html.
+
+
+IntelliJ IDEA Overview
+==========================
+ For general info and facts on IntelliJ IDEA, you can refer to IntelliJ IDEA Info Kit at
+ http://www.jetbrains.com/idea/documentation/product_info_kit.html.
+
+
+IDEA Development Package
+==========================
+ Contains:
+ - Source code for the OpenAPI classes;
+ - Documentation (JavaDocs for the OpenAPI and a number of additional components);
+ - Simple example plugins demonstrating usage of the OpenAPI;
+ - Source code for plugins shipped with IDEA:
+ * Plugin Development Kit
+ * IDEtalk plugin
+ * Images support plugin
+ * Inspection Gadgets
+ * Intention PowerPack
+ * J2ME development support plugin
+ * JavaScript support plugin
+ * JavaScript inspections plugin
+ * JavaScript Intention PowerPack
+ * GWTStudio plugin
+ * KlassMaster stacktrace unscramble plugin
+ * StrutsAssistant plugin
+ * StarTeam, Perforce, Subversion, Visual SourceSafe integration
+ * Tomcat, Weblogic, WebSphere, Geronimo, JBoss, GlassFish, JSR45 integration
+
+ Download page: http://www.jetbrains.com/idea/download/index.html
+
+ Source code of additional open source plugins shipped with IntelliJ IDEA is available in the Subversion
+ repository at:
+ http://svn.jetbrains.org/idea/Trunk/bundled/
+
+
+Using Plugins
+=============
+ IDEA now smartly integrates with the Community web-site which holds a repository of the third-party plugins to it.
+ This integration, supplied with a convenient UI, helps you incorporate any available plugins without switching from
+ IDEA settings dialog (Settings | Plugins).
+
+ You can browse the plugins Web site, rate and comment on plugins at:
+ http://plugins.intellij.net/
+
+
+Home Page:
+==========
+ http://www.jetbrains.com
+
+
+IntelliJ Technology Network
+===========================
+ http://www.intellij.net
+ Early Access to new products, internal builds and patches, Bug/Features database, Forums/newsgroups
+
+
+IntelliJ Community Site
+=======================
+ http://www.intellij.org
+ The community-driven Wiki site dedicated to IntelliJ products and technologies.
+
+
+Support
+=======
+ For technical support and assistance, you may find necessary information at the Support page
+ (http://www.jetbrains.com/support/index.html) or contact us at support@jetbrains.com.
+
+
+Bug Reporting:
+==============
+ Send emails to bugs@jetbrains.com
+
+
+Contacting us:
+==============
+ sales@jetbrains.com - Sales inquiries, billing, order processing questions
+ support@jetbrains.com - Technical support (all products)
+ sales.us@jetbrains.com - Sales inquiries in the United States
+ support.us@jetbrains.com - Technical support for US customers
+ suggestions@jetbrains.com - Feature suggestions
+ info@jetbrains.com - Product inquiries
+
+
+=============
+You are encouraged to visit our IntelliJ IDEA web site at http://www.jetbrains.com/idea/
+or to contact us via e-mail at feedback@jetbrains.com if you have any comments about
+this release. In particular, we are very interested in any ease-of-use, user
+interface suggestions that you may have. We will be posting regular updates
+of our progress to our online forums and newsgroups.
+=============
diff --git a/updater/testData/bin/focuskiller.dll b/updater/testData/bin/focuskiller.dll
new file mode 100644
index 0000000..c1f8e04
--- /dev/null
+++ b/updater/testData/bin/focuskiller.dll
Binary files differ
diff --git a/updater/testData/bin/idea.bat b/updater/testData/bin/idea.bat
new file mode 100644
index 0000000..79a087f
--- /dev/null
+++ b/updater/testData/bin/idea.bat
@@ -0,0 +1,66 @@
+@echo off
+
+::----------------------------------------------------------------------
+:: IntelliJ IDEA Startup Script
+::----------------------------------------------------------------------
+
+set JDK_HOME=c:/tools/jdk
+
+:: ---------------------------------------------------------------------
+:: Before you run IntelliJ IDEA specify the location of the
+:: JDK 1.5 installation directory which will be used for running IDEA
+:: ---------------------------------------------------------------------
+IF "%IDEA_JDK%" == "" SET IDEA_JDK=%JDK_HOME%
+IF "%IDEA_JDK%" == "" goto error
+
+:: ---------------------------------------------------------------------
+:: Before you run IntelliJ IDEA specify the location of the
+:: directory where IntelliJ IDEA is installed
+:: In most cases you do not need to change the settings below.
+:: ---------------------------------------------------------------------
+SET IDEA_HOME=..
+
+SET JAVA_EXE=%IDEA_JDK%\jre\bin\java.exe
+IF NOT EXIST "%JAVA_EXE%" goto error
+
+IF "%IDEA_MAIN_CLASS_NAME%" == "" SET IDEA_MAIN_CLASS_NAME=com.intellij.idea.Main
+
+IF NOT "%IDEA_PROPERTIES%" == "" set IDEA_PROPERTIES_PROPERTY=-Didea.properties.file=%IDEA_PROPERTIES%
+
+:: ---------------------------------------------------------------------
+:: You may specify your own JVM arguments in idea.exe.vmoptions file. Put one option per line there.
+:: ---------------------------------------------------------------------
+SET ACC=
+FOR /F "delims=" %%i in (%IDEA_HOME%\bin\idea.exe.vmoptions) DO call %IDEA_HOME%\bin\append.bat "%%i"
+
+set REQUIRED_IDEA_JVM_ARGS=-Xbootclasspath/p:%IDEA_HOME%/lib/boot.jar %IDEA_PROPERTIES_PROPERTY% %REQUIRED_IDEA_JVM_ARGS%
+SET JVM_ARGS=%ACC% %REQUIRED_IDEA_JVM_ARGS%
+
+SET OLD_PATH=%PATH%
+SET PATH=%IDEA_HOME%\bin;%PATH%
+
+SET CLASS_PATH=%IDEA_HOME%\lib\bootstrap.jar
+SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\util.jar
+SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\jdom.jar
+SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\log4j.jar
+SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\extensions.jar
+SET CLASS_PATH=%CLASS_PATH%;%IDEA_HOME%\lib\trove4j.jar
+SET CLASS_PATH=%CLASS_PATH%;%IDEA_JDK%\lib\tools.jar
+
+:: ---------------------------------------------------------------------
+:: You may specify additional class paths in IDEA_CLASS_PATH variable.
+:: It is a good idea to specify paths to your plugins in this variable.
+:: ---------------------------------------------------------------------
+IF NOT "%IDEA_CLASS_PATH%" == "" SET CLASS_PATH=%CLASS_PATH%;%IDEA_CLASS_PATH%
+
+"%JAVA_EXE%" %JVM_ARGS% -cp "%CLASS_PATH%" %IDEA_MAIN_CLASS_NAME% %*
+
+SET PATH=%OLD_PATH%
+goto end
+:error
+echo ---------------------------------------------------------------------
+echo ERROR: cannot start IntelliJ IDEA.
+echo No JDK found to run IDEA. Please validate either IDEA_JDK or JDK_HOME points to valid JDK installation
+echo ---------------------------------------------------------------------
+pause
+:end
diff --git a/updater/testData/bin/idea.properties b/updater/testData/bin/idea.properties
new file mode 100644
index 0000000..37bc736
--- /dev/null
+++ b/updater/testData/bin/idea.properties
@@ -0,0 +1,105 @@
+# Set up IDEA_PROPERTIES environment variable to specify custom location of this properties file like
+# SET IDEA_PROPERTIES=c:\ideaconfig\idea.properties
+# before launching idea.
+# If not specified it is searched according following sequence (first successful is used).
+# 1. ${user.home}
+# 2. ${idea.home}/bin
+
+# Use ${idea.home} macro to specify location relative to IDEA installation home
+# Also use ${xxx} where xxx is any java property (including defined in previous lines of this file) to refer to its value
+# Note for Windows users: please make sure you're using forward slashes. I.e. c:/idea/system
+
+#---------------------------------------------------------------------
+# Uncomment this option if you want to customize path to IDEA config folder. Make sure you're using forward slashes
+#---------------------------------------------------------------------
+idea.config.path=${idea.home}/config
+
+#---------------------------------------------------------------------
+# Uncomment this option if you want to customize path to IDEA system folder. Make sure you're using forward slashes
+#---------------------------------------------------------------------
+idea.system.path=${idea.home}/system
+
+#---------------------------------------------------------------------
+# Uncomment this option if you want to customize path to user installed plugins folder. Make sure you're using forward slashes
+#---------------------------------------------------------------------
+idea.plugins.path=${idea.home}/config/plugins
+
+#---------------------------------------------------------------------
+# Maximum file size (kilobytes) IDEA should provide intellisense for.
+# The larger file is the slower its editor works and higher overall system memory requirements are
+# if intellisense is enabled. Remove this property or set to very large number if you need
+# intellisense for any files available regardless their size.
+# Please note this option doesn't operate with Java files. Regardless of the option value intellisense will anyway stay there.
+#---------------------------------------------------------------------
+idea.max.intellisense.filesize=2048
+
+#---------------------------------------------------------------------
+# There are two possible values of idea.popup.weight property: "heavy" and "medium".
+# If you have WM configured as "Focus follows mouse with Auto Raise" then you have to
+# set this property to "medium". It prevents problems with popup menus on some
+# configurations.
+# ---------------------------------------------------------------------
+idea.popup.weight=heavy
+
+#----------------------------------------------------------------------
+# Disabling this property may lead to visual glitches like blinking and fail to repaint
+# on certain display adapter cards.
+#----------------------------------------------------------------------
+sun.java2d.noddraw=true
+
+#----------------------------------------------------------------------
+# Removing this property may lead to editor performance degradation under Windows.
+#----------------------------------------------------------------------
+sun.java2d.d3d=false
+
+#-----------------------------------------------------------------------
+# IDEA copies library jars to prevent their locking. If copying is not desirable, specify "true"
+#-----------------------------------------------------------------------
+idea.jars.nocopy=false
+
+#----------------------------------------------------------------------
+# Configure if a special launcher should be used when running processes from within IDEA.
+# Using Launcher enables "soft exit" and "thread dump" features
+#----------------------------------------------------------------------
+idea.no.launcher=false
+
+#-----------------------------------------------------------------------
+# The VM option value to be used start the JVM in debug mode.
+# Some environments define it in a different way (-XXdebug in Oracle VM)
+#-----------------------------------------------------------------------
+idea.xdebug.key=-Xdebug
+
+#-----------------------------------------------------------------------
+# Switch into JMX 1.0 compatible mode
+# Uncomment this option to be able to run IDEA using J2SDK 1.5 while working
+# with application servers (like WebLogic) running 1.4
+#-----------------------------------------------------------------------
+#jmx.serial.form=1.0
+
+#-----------------------------------------------------------------------
+# Uncomment this option if you don't like to receive notifications about
+# fatal errors that happen to IDEA or plugins installed.
+#-----------------------------------------------------------------------
+idea.fatal.error.notification=disabled
+
+# Workaround for slow scrolling in JDK6
+swing.bufferPerWindow=false
+
+#-----------------------------------------------------------------------
+# Uncomment this property to prevent IDEA from throwing ProcessCanceledException when user activity
+# detected. This option is only useful for plugin developers, while debugging PSI related activities
+# performed in background error analysis thread.
+# DO NOT UNCOMMENT THIS UNLESS YOU'RE DEBUGGING IDEA ITSELF. Significant slowdowns and lockups will happen otherwise.
+#-----------------------------------------------------------------------
+#idea.ProcessCanceledException=disabled
+
+#----------------------------------------------------------------------
+# Removing this property may lead to editor performance degradation under X-Windows.
+#----------------------------------------------------------------------
+sun.java2d.pmoffscreen=false
+
+#---------------------------------------------------------------------
+# Maximum size (kilobytes) IDEA will load for showing past file contents -
+# in Show Diff or when calculating Digest Diff
+#---------------------------------------------------------------------
+#idea.max.vcs.loaded.size.kb=20480
\ No newline at end of file
diff --git a/updater/testData/lib/annotations.jar b/updater/testData/lib/annotations.jar
new file mode 100644
index 0000000..53f730f
--- /dev/null
+++ b/updater/testData/lib/annotations.jar
Binary files differ
diff --git a/updater/testData/lib/annotations_changed.jar b/updater/testData/lib/annotations_changed.jar
new file mode 100644
index 0000000..43af95c
--- /dev/null
+++ b/updater/testData/lib/annotations_changed.jar
Binary files differ
diff --git a/updater/testData/lib/boot.jar b/updater/testData/lib/boot.jar
new file mode 100644
index 0000000..98b408f
--- /dev/null
+++ b/updater/testData/lib/boot.jar
Binary files differ
diff --git a/updater/testData/lib/boot2.jar b/updater/testData/lib/boot2.jar
new file mode 100644
index 0000000..5c9c316
--- /dev/null
+++ b/updater/testData/lib/boot2.jar
Binary files differ
diff --git a/updater/testData/lib/boot2_changed_with_unchanged_content.jar b/updater/testData/lib/boot2_changed_with_unchanged_content.jar
new file mode 100644
index 0000000..c8eb3d9
--- /dev/null
+++ b/updater/testData/lib/boot2_changed_with_unchanged_content.jar
Binary files differ
diff --git a/updater/testData/lib/boot_with_directory_becomes_file.jar b/updater/testData/lib/boot_with_directory_becomes_file.jar
new file mode 100644
index 0000000..4c16379
--- /dev/null
+++ b/updater/testData/lib/boot_with_directory_becomes_file.jar
Binary files differ
diff --git a/updater/testData/lib/bootstrap.jar b/updater/testData/lib/bootstrap.jar
new file mode 100644
index 0000000..3a32734
--- /dev/null
+++ b/updater/testData/lib/bootstrap.jar
Binary files differ
diff --git a/updater/testData/lib/bootstrap_deleted.jar b/updater/testData/lib/bootstrap_deleted.jar
new file mode 100644
index 0000000..b0aed41
--- /dev/null
+++ b/updater/testData/lib/bootstrap_deleted.jar
Binary files differ
diff --git a/updater/testSrc/com/intellij/updater/DigesterTest.java b/updater/testSrc/com/intellij/updater/DigesterTest.java
new file mode 100644
index 0000000..a7ec965
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/DigesterTest.java
@@ -0,0 +1,21 @@
+package com.intellij.updater;
+
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class DigesterTest extends UpdaterTestCase {
+ @Test
+ public void testBasics() throws Exception {
+ 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/PatchFileCreatorTest.java b/updater/testSrc/com/intellij/updater/PatchFileCreatorTest.java
new file mode 100644
index 0000000..4e87db2
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/PatchFileCreatorTest.java
@@ -0,0 +1,333 @@
+package com.intellij.updater;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import static org.junit.Assert.*;
+
+@SuppressWarnings("ResultOfMethodCallIgnored")
+public class PatchFileCreatorTest extends PatchTestCase {
+ private File myFile;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ myFile = getTempFile("patch.zip");
+ }
+
+ @Test
+ public void testCreatingAndApplying() throws Exception {
+ createPatch();
+
+ assertAppliedAndRevertedCorrectly(PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI));
+ }
+
+ @Test
+ public void failOnEmptySourceJar() throws Exception {
+ final File sourceJar = new File(myOlderDir, "lib/empty.jar");
+ if (sourceJar.exists()) sourceJar.delete();
+ assertTrue(sourceJar.createNewFile());
+
+ try {
+ final File targetJar = new File(myNewerDir, "lib/empty.jar");
+ FileUtil.copy(new File(myNewerDir, "lib/annotations.jar"), targetJar);
+
+ try {
+ createPatch();
+ fail("Should have failed to create a patch from empty .jar");
+ }
+ catch (IOException e) {
+ final String reason = e.getMessage();
+ assertEquals("Corrupted source file: " + sourceJar, reason);
+ }
+ finally {
+ targetJar.delete();
+ }
+ }
+ finally {
+ sourceJar.delete();
+ }
+ }
+
+ @Test
+ public void failOnEmptyTargetJar() throws Exception {
+ final File sourceJar = new File(myOlderDir, "lib/empty.jar");
+ FileUtil.copy(new File(myOlderDir, "lib/annotations.jar"), sourceJar);
+
+ try {
+ final File targetJar = new File(myNewerDir, "lib/empty.jar");
+ if (targetJar.exists()) targetJar.delete();
+ assertTrue(targetJar.createNewFile());
+
+ try {
+ createPatch();
+ fail("Should have failed to create a patch against empty .jar");
+ }
+ catch (IOException e) {
+ final String reason = e.getMessage();
+ assertEquals("Corrupted target file: " + targetJar, reason);
+ }
+ finally {
+ targetJar.delete();
+ }
+ }
+ finally {
+ sourceJar.delete();
+ }
+ }
+
+ @Test
+ public void testReverting() throws Exception {
+ createPatch();
+
+ PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
+ preparationResult.patch.getActions().add(new MyFailOnApplyPatchAction());
+ assertNothingHasChanged(preparationResult, new HashMap<String, ValidationResult.Option>());
+ }
+
+ @Test
+ public void testApplyingWithAbsentFileToDelete() throws Exception {
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+
+ new File(myOlderDir, "bin/idea.bat").delete();
+
+ assertAppliedAndRevertedCorrectly(PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI));
+ }
+
+ @Test
+ public void testApplyingWithAbsentOptionalFile() throws Exception {
+ FileUtil.writeToFile(new File(myNewerDir, "bin/idea.bat"), "new content".getBytes());
+
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.singletonList("bin/idea.bat"), TEST_UI);
+
+ new File(myOlderDir, "bin/idea.bat").delete();
+
+ PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
+ assertTrue(preparationResult.validationResults.isEmpty());
+ assertAppliedAndRevertedCorrectly(preparationResult);
+ }
+
+ @Test
+ public void testRevertingWithAbsentFileToDelete() throws Exception {
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+
+ new File(myOlderDir, "bin/idea.bat").delete();
+
+ PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
+ preparationResult.patch.getActions().add(new MyFailOnApplyPatchAction());
+ assertNothingHasChanged(preparationResult, new HashMap<String, ValidationResult.Option>());
+ }
+
+ @Test
+ public void testApplyingWithoutCriticalFiles() throws Exception {
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+ PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
+
+ assertTrue(PatchFileCreator.apply(preparationResult, new HashMap<String, ValidationResult.Option>(), TEST_UI));
+ }
+
+ @Test
+ public void testApplyingWithCriticalFiles() throws Exception {
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Arrays.asList("lib/annotations.jar"),
+ Collections.<String>emptyList(), TEST_UI);
+
+ PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
+
+ assertTrue(PatchFileCreator.apply(preparationResult, new HashMap<String, ValidationResult.Option>(), TEST_UI));
+ assertAppliedCorrectly();
+ }
+
+ @Test
+ public void testApplyingWithCaseChangedNames() throws Exception {
+ FileUtil.rename(new File(myOlderDir, "Readme.txt"),
+ new File(myOlderDir, "README.txt"));
+
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+
+ assertAppliedAndRevertedCorrectly(PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI));
+ }
+
+ @Test
+ public void testCreatingAndApplyingWhenDirectoryBecomesFile() throws Exception {
+ File file = new File(myOlderDir, "Readme.txt");
+ file.delete();
+ file.mkdirs();
+
+ new File(file, "subFile.txt").createNewFile();
+ new File(file, "subDir").mkdir();
+ new File(file, "subDir/subFile.txt").createNewFile();
+
+ FileUtil.copy(new File(myOlderDir, "lib/boot.jar"),
+ new File(myOlderDir, "lib/boot_with_directory_becomes_file.jar"));
+
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+
+ assertAppliedAndRevertedCorrectly(PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI));
+ }
+
+ @Test
+ public void testCreatingAndApplyingWhenFileBecomesDirectory() throws Exception {
+ File file = new File(myOlderDir, "bin");
+ assertTrue(FileUtil.delete(file));
+ file.createNewFile();
+
+ FileUtil.copy(new File(myOlderDir, "lib/boot_with_directory_becomes_file.jar"),
+ new File(myOlderDir, "lib/boot.jar"));
+
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+
+ assertAppliedAndRevertedCorrectly(PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI));
+ }
+
+ @Test
+ public void testConsideringOptions() throws Exception {
+ createPatch();
+
+ PatchFileCreator.PreparationResult preparationResult = PatchFileCreator.prepareAndValidate(myFile, myOlderDir, TEST_UI);
+ Map<String, ValidationResult.Option> options = new HashMap<String, ValidationResult.Option>();
+ for (PatchAction each : preparationResult.patch.getActions()) {
+ options.put(each.getPath(), ValidationResult.Option.IGNORE);
+ }
+
+ assertNothingHasChanged(preparationResult, options);
+ }
+
+ private void createPatch() throws IOException, OperationCancelledException {
+ PatchFileCreator.create(myOlderDir, myNewerDir, myFile,
+ Collections.<String>emptyList(), Collections.<String>emptyList(), Collections.<String>emptyList(), TEST_UI);
+ assertTrue(myFile.exists());
+ }
+
+ private void assertNothingHasChanged(PatchFileCreator.PreparationResult preparationResult, Map<String, ValidationResult.Option> options)
+ throws Exception {
+ Map<String, Long> before = Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI);
+ PatchFileCreator.apply(preparationResult, options, TEST_UI);
+ Map<String, Long> after = Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI);
+
+ DiffCalculator.Result diff = DiffCalculator.calculate(before, after);
+ assertTrue(diff.filesToCreate.isEmpty());
+ assertTrue(diff.filesToDelete.isEmpty());
+ assertTrue(diff.filesToUpdate.isEmpty());
+ }
+
+ private void assertAppliedAndRevertedCorrectly(PatchFileCreator.PreparationResult preparationResult)
+ throws IOException, OperationCancelledException {
+
+ Map<String, Long> original = Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI);
+
+ File backup = getTempFile("backup");
+
+ for (ValidationResult each : preparationResult.validationResults) {
+ assertTrue(each.toString(), each.kind != ValidationResult.Kind.ERROR);
+ }
+
+ List<PatchAction> appliedActions =
+ PatchFileCreator.apply(preparationResult, new HashMap<String, ValidationResult.Option>(), backup, TEST_UI).appliedActions;
+ assertAppliedCorrectly();
+
+ assertFalse(original.equals(Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI)));
+
+ PatchFileCreator.revert(preparationResult, appliedActions, backup, TEST_UI);
+
+ assertEquals(original, Digester.digestFiles(myOlderDir, Collections.<String>emptyList(), TEST_UI));
+ }
+
+ protected void assertAppliedCorrectly() throws IOException {
+ File newFile = new File(myOlderDir, "newDir/newFile.txt");
+ assertTrue(newFile.exists());
+ assertEquals("hello", FileUtil.loadFile(newFile));
+
+ File changedFile = new File(myOlderDir, "Readme.txt");
+ assertTrue(changedFile.exists());
+ assertEquals("hello", FileUtil.loadFile(changedFile));
+
+ assertFalse(new File(myOlderDir, "bin/idea.bat").exists());
+
+ // do not remove unchanged
+ checkZipEntry("lib/annotations.jar", "org/jetbrains/annotations/Nls.class", 502);
+ // add new
+ checkZipEntry("lib/annotations.jar", "org/jetbrains/annotations/NewClass.class", 453);
+ // update changed
+ checkZipEntry("lib/annotations.jar", "org/jetbrains/annotations/Nullable.class", 546);
+ // remove obsolete
+ checkNoZipEntry("lib/annotations.jar", "org/jetbrains/annotations/TestOnly.class");
+
+ // test for archives with only deleted files
+ checkNoZipEntry("lib/bootstrap.jar", "com/intellij/ide/ClassloaderUtil.class");
+
+ // packing directories too
+ checkZipEntry("lib/annotations.jar", "org/", 0);
+ checkZipEntry("lib/annotations.jar", "org/jetbrains/", 0);
+ checkZipEntry("lib/annotations.jar", "org/jetbrains/annotations/", 0);
+ checkZipEntry("lib/bootstrap.jar", "com/", 0);
+ checkZipEntry("lib/bootstrap.jar", "com/intellij/", 0);
+ checkZipEntry("lib/bootstrap.jar", "com/intellij/ide/", 0);
+ }
+
+ private void checkZipEntry(String jar, String entryName, int expectedSize) throws IOException {
+ ZipFile zipFile = new ZipFile(new File(myOlderDir, jar));
+ try {
+ ZipEntry entry = zipFile.getEntry(entryName);
+ assertNotNull(entry);
+ assertEquals(expectedSize, entry.getSize());
+ }
+ finally {
+ zipFile.close();
+ }
+ }
+
+ private void checkNoZipEntry(String jar, String entryName) throws IOException {
+ ZipFile zipFile = new ZipFile(new File(myOlderDir, jar));
+ try {
+ assertNull(zipFile.getEntry(entryName));
+ }
+ finally {
+ zipFile.close();
+ }
+ }
+
+ private static class MyFailOnApplyPatchAction extends PatchAction {
+ public MyFailOnApplyPatchAction() {
+ super("_dummy_file_", -1);
+ }
+
+ @Override
+ protected void doBuildPatchFile(File olderFile, File newerFile, ZipOutputStream patchOutput) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected ValidationResult doValidate(File toFile) throws IOException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected void doApply(ZipFile patchFile, File toFile) throws IOException {
+ throw new IOException("dummy exception");
+ }
+
+ @Override
+ protected void doBackup(File toFile, File backupFile) throws IOException {
+ }
+
+ @Override
+ protected void doRevert(File toFile, File backupFile) throws IOException {
+ }
+ }
+}
diff --git a/updater/testSrc/com/intellij/updater/PatchTest.java b/updater/testSrc/com/intellij/updater/PatchTest.java
new file mode 100644
index 0000000..14ff6c0
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/PatchTest.java
@@ -0,0 +1,192 @@
+package com.intellij.updater;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.nio.channels.FileLock;
+import java.util.*;
+
+import static org.junit.Assert.assertEquals;
+
+@SuppressWarnings("ResultOfMethodCallIgnored")
+public class PatchTest extends PatchTestCase {
+ private Patch myPatch;
+
+ @Override
+ @Before
+ public void setUp() throws Exception {
+ super.setUp();
+ myPatch = new Patch(myOlderDir, myNewerDir, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Collections.<String>emptyList(), TEST_UI);
+ }
+
+ @Test
+ public void testBasics() throws Exception {
+ List<PatchAction> expectedActions = Arrays.asList(
+ new CreateAction("newDir/newFile.txt"),
+ new UpdateAction("Readme.txt", CHECKSUMS.README_TXT),
+ new UpdateZipAction("lib/annotations.jar",
+ Arrays.asList("org/jetbrains/annotations/NewClass.class"),
+ Arrays.asList("org/jetbrains/annotations/Nullable.class"),
+ Arrays.asList("org/jetbrains/annotations/TestOnly.class"),
+ CHECKSUMS.ANNOTATIONS_JAR),
+ new UpdateZipAction("lib/bootstrap.jar",
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList(),
+ Arrays.asList("com/intellij/ide/ClassloaderUtil.class"),
+ CHECKSUMS.BOOTSTRAP_JAR),
+ new DeleteAction("bin/idea.bat", CHECKSUMS.IDEA_BAT));
+ List<PatchAction> actualActions = new ArrayList<PatchAction>(myPatch.getActions());
+ Collections.sort(expectedActions, COMPARATOR);
+ Collections.sort(actualActions, COMPARATOR);
+ assertEquals(expectedActions, actualActions);
+ }
+
+ @Test
+ public void testCreatingWithIgnoredFiles() throws Exception {
+ myPatch = new Patch(myOlderDir,
+ myNewerDir,
+ Arrays.asList("Readme.txt", "bin/idea.bat"),
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList(),
+ TEST_UI);
+
+ List<PatchAction> expectedActions = Arrays.asList(
+ new CreateAction("newDir/newFile.txt"),
+ new UpdateZipAction("lib/annotations.jar",
+ Arrays.asList("org/jetbrains/annotations/NewClass.class"),
+ Arrays.asList("org/jetbrains/annotations/Nullable.class"),
+ Arrays.asList("org/jetbrains/annotations/TestOnly.class"),
+ CHECKSUMS.ANNOTATIONS_JAR),
+ new UpdateZipAction("lib/bootstrap.jar",
+ Collections.<String>emptyList(),
+ Collections.<String>emptyList(),
+ Arrays.asList("com/intellij/ide/ClassloaderUtil.class"),
+ CHECKSUMS.BOOTSTRAP_JAR));
+ List<PatchAction> actualActions = new ArrayList<PatchAction>(myPatch.getActions());
+ Collections.sort(expectedActions, COMPARATOR);
+ Collections.sort(actualActions, COMPARATOR);
+ assertEquals(expectedActions, actualActions);
+ }
+
+ @Test
+ public void testValidation() throws Exception {
+ FileUtil.writeToFile(new File(myOlderDir, "bin/idea.bat"), "changed".getBytes());
+ new File(myOlderDir, "extraDir").mkdirs();
+ new File(myOlderDir, "extraDir/extraFile.txt").createNewFile();
+ new File(myOlderDir, "newDir").mkdirs();
+ new File(myOlderDir, "newDir/newFile.txt").createNewFile();
+ FileUtil.writeToFile(new File(myOlderDir, "Readme.txt"), "changed".getBytes());
+ FileUtil.writeToFile(new File(myOlderDir, "lib/annotations.jar"), "changed".getBytes());
+ FileUtil.delete(new File(myOlderDir, "lib/bootstrap.jar"));
+
+ assertEquals(
+ new HashSet<ValidationResult>(Arrays.asList(
+ new ValidationResult(ValidationResult.Kind.CONFLICT,
+ "newDir/newFile.txt",
+ ValidationResult.Action.CREATE,
+ ValidationResult.ALREADY_EXISTS_MESSAGE,
+ ValidationResult.Option.REPLACE, ValidationResult.Option.KEEP),
+ new ValidationResult(ValidationResult.Kind.ERROR,
+ "Readme.txt",
+ ValidationResult.Action.UPDATE,
+ ValidationResult.MODIFIED_MESSAGE,
+ ValidationResult.Option.IGNORE),
+ new ValidationResult(ValidationResult.Kind.ERROR,
+ "lib/annotations.jar",
+ ValidationResult.Action.UPDATE,
+ ValidationResult.MODIFIED_MESSAGE,
+ ValidationResult.Option.IGNORE),
+ new ValidationResult(ValidationResult.Kind.ERROR,
+ "lib/bootstrap.jar",
+ ValidationResult.Action.UPDATE,
+ ValidationResult.ABSENT_MESSAGE,
+ ValidationResult.Option.IGNORE),
+ new ValidationResult(ValidationResult.Kind.CONFLICT,
+ "bin/idea.bat",
+ ValidationResult.Action.DELETE,
+ ValidationResult.MODIFIED_MESSAGE,
+ ValidationResult.Option.DELETE, ValidationResult.Option.KEEP))),
+ new HashSet<ValidationResult>(myPatch.validate(myOlderDir, TEST_UI)));
+ }
+
+ @Test
+ public void testValidationWithOptionalFiles() throws Exception {
+ FileUtil.writeToFile(new File(myOlderDir, "lib/annotations.jar"), "changed".getBytes());
+ assertEquals(new HashSet<ValidationResult>(Arrays.asList(
+ new ValidationResult(ValidationResult.Kind.ERROR,
+ "lib/annotations.jar",
+ ValidationResult.Action.UPDATE,
+ ValidationResult.MODIFIED_MESSAGE,
+ ValidationResult.Option.IGNORE))),
+ new HashSet<ValidationResult>(myPatch.validate(myOlderDir, TEST_UI)));
+
+ myPatch = new Patch(myOlderDir, myNewerDir, Collections.<String>emptyList(), Collections.<String>emptyList(),
+ Arrays.asList("lib/annotations.jar"), TEST_UI);
+ FileUtil.delete(new File(myOlderDir, "lib/annotations.jar"));
+ assertEquals(Collections.<ValidationResult>emptyList(),
+ myPatch.validate(myOlderDir, TEST_UI));
+ }
+
+ @Test
+ public void testValidatingNonAccessibleFiles() throws Exception {
+ File f = new File(myOlderDir, "Readme.txt");
+ FileOutputStream s = new FileOutputStream(f, true);
+ try {
+ FileLock lock = s.getChannel().lock();
+ try {
+ List<ValidationResult> result = myPatch.validate(myOlderDir, TEST_UI);
+ assertEquals(
+ new HashSet<ValidationResult>(Arrays.asList(
+ new ValidationResult(ValidationResult.Kind.ERROR,
+ "Readme.txt",
+ ValidationResult.Action.UPDATE,
+ ValidationResult.ACCESS_DENIED_MESSAGE,
+ ValidationResult.Option.IGNORE))),
+ new HashSet<ValidationResult>(result));
+ }
+ finally {
+ lock.release();
+ }
+ }
+ finally {
+ s.close();
+ }
+ }
+
+ @Test
+ public void testSaveLoad() throws Exception {
+ File f = getTempFile("file");
+ try {
+ FileOutputStream out = new FileOutputStream(f);
+ try {
+ myPatch.write(out);
+ }
+ finally {
+ out.close();
+ }
+
+ FileInputStream in = new FileInputStream(f);
+ try {
+ assertEquals(myPatch.getActions(), new Patch(in).getActions());
+ }
+ finally {
+ in.close();
+ }
+ }
+ finally {
+ f.delete();
+ }
+ }
+
+ private static final Comparator<PatchAction> COMPARATOR = new Comparator<PatchAction>() {
+ @Override
+ public int compare(PatchAction o1, PatchAction o2) {
+ return o1.toString().compareTo(o2.toString());
+ }
+ };
+}
diff --git a/updater/testSrc/com/intellij/updater/PatchTestCase.java b/updater/testSrc/com/intellij/updater/PatchTestCase.java
new file mode 100644
index 0000000..417c32e
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/PatchTestCase.java
@@ -0,0 +1,41 @@
+package com.intellij.updater;
+
+import com.intellij.openapi.util.io.FileUtil;
+
+import java.io.File;
+
+@SuppressWarnings("ResultOfMethodCallIgnored")
+public abstract class PatchTestCase extends UpdaterTestCase {
+ protected File myNewerDir;
+ protected File myOlderDir;
+
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ myOlderDir = getDataDir();
+ myNewerDir = getTempFile("newDir");
+ FileUtil.copyDir(myOlderDir, myNewerDir);
+
+ FileUtil.delete(new File(myNewerDir, "bin/idea.bat"));
+ FileUtil.writeToFile(new File(myNewerDir, "Readme.txt"), "hello".getBytes());
+ File newFile = new File(myNewerDir, "newDir/newFile.txt");
+ newFile.getParentFile().mkdirs();
+ newFile.createNewFile();
+ FileUtil.writeToFile(newFile, "hello".getBytes());
+
+ FileUtil.delete(new File(myOlderDir, "lib/annotations_changed.jar"));
+ FileUtil.delete(new File(myNewerDir, "lib/annotations.jar"));
+ FileUtil.rename(new File(myNewerDir, "lib/annotations_changed.jar"),
+ new File(myNewerDir, "lib/annotations.jar"));
+
+ FileUtil.delete(new File(myOlderDir, "lib/bootstrap_deleted.jar"));
+ FileUtil.delete(new File(myNewerDir, "lib/bootstrap.jar"));
+ FileUtil.rename(new File(myNewerDir, "lib/bootstrap_deleted.jar"),
+ new File(myNewerDir, "lib/bootstrap.jar"));
+
+ FileUtil.delete(new File(myOlderDir, "lib/boot2_changed_with_unchanged_content.jar"));
+ FileUtil.delete(new File(myNewerDir, "lib/boot2.jar"));
+ FileUtil.rename(new File(myNewerDir, "lib/boot2_changed_with_unchanged_content.jar"),
+ new File(myNewerDir, "lib/boot2.jar"));
+ }
+}
\ No newline at end of file
diff --git a/updater/testSrc/com/intellij/updater/RunnerTest.java b/updater/testSrc/com/intellij/updater/RunnerTest.java
new file mode 100644
index 0000000..4813db1
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/RunnerTest.java
@@ -0,0 +1,25 @@
+package com.intellij.updater;
+
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+
+public class RunnerTest extends UpdaterTestCase {
+ @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"));
+
+ assertEquals(Arrays.asList("xxx", "yyy", "zzz/zzz", "aaa"),
+ Runner.extractFiles(args, "ignored"));
+
+ assertEquals(Arrays.asList("ccc"),
+ Runner.extractFiles(args, "critical"));
+
+ assertEquals(Collections.<String>emptyList(),
+ Runner.extractFiles(args, "unknown"));
+ }
+}
diff --git a/updater/testSrc/com/intellij/updater/UpdaterTestCase.java b/updater/testSrc/com/intellij/updater/UpdaterTestCase.java
new file mode 100644
index 0000000..82d7bbe
--- /dev/null
+++ b/updater/testSrc/com/intellij/updater/UpdaterTestCase.java
@@ -0,0 +1,73 @@
+package com.intellij.updater;
+
+import com.intellij.openapi.application.ex.PathManagerEx;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
+import com.intellij.testFramework.fixtures.TempDirTestFixture;
+import org.junit.After;
+import org.junit.Before;
+
+import java.io.File;
+
+public abstract class UpdaterTestCase {
+ protected static final UpdaterUI TEST_UI = new ConsoleUpdaterUI(){
+ @Override
+ public void startProcess(String title) {
+ }
+
+ @Override
+ public void setStatus(String status) {
+ }
+ };
+
+ protected CheckSums CHECKSUMS;
+ private TempDirTestFixture myTempDirFixture;
+
+ @Before
+ public void setUp() throws Exception {
+ Runner.initLogger(System.getProperty("java.io.tmpdir"));
+ myTempDirFixture = IdeaTestFixtureFactory.getFixtureFactory().createTempDirTestFixture();
+ myTempDirFixture.setUp();
+
+ FileUtil.copyDir(PathManagerEx.findFileUnderCommunityHome("updater/testData"), getDataDir());
+
+ boolean windowsLineEnds = new File(getDataDir(), "Readme.txt").length() == 7132;
+ CHECKSUMS = new CheckSums(windowsLineEnds);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ myTempDirFixture.tearDown();
+ Utils.cleanup();
+ }
+
+ public File getDataDir() {
+ return getTempFile("data");
+ }
+
+ public File getTempFile(String fileName) {
+ return new File(myTempDirFixture.getTempDirPath(), fileName);
+ }
+
+ protected static class CheckSums {
+ public final long README_TXT;
+ public final long IDEA_BAT;
+ public final long ANNOTATIONS_JAR;
+ public final long BOOTSTRAP_JAR;
+ public final long FOCUSKILLER_DLL;
+
+ public CheckSums(boolean windowsLineEnds) {
+ if (windowsLineEnds) {
+ README_TXT = 1272723667L;
+ IDEA_BAT = 3088608749L;
+ }
+ else {
+ README_TXT = 7256327L;
+ IDEA_BAT = 1493936069L;
+ }
+ ANNOTATIONS_JAR = 2119442657L;
+ BOOTSTRAP_JAR = 2082851308L;
+ FOCUSKILLER_DLL = 1991212227L;
+ }
+ }
+}
\ No newline at end of file
diff --git a/updater/updater.iml b/updater/updater.iml
index c053808..e55b58d 100644
--- a/updater/updater.iml
+++ b/updater/updater.iml
@@ -4,9 +4,13 @@
<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="library" name="Log4J" level="project" />
+ <orderEntry type="module" module-name="testFramework" scope="TEST" />
+ <orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
</component>
</module>
diff --git a/xml/dom-impl/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java b/xml/dom-impl/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java
index 52c2153..350fe41 100644
--- a/xml/dom-impl/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.java
+++ b/xml/dom-impl/src/com/intellij/codeInsight/navigation/NavigationGutterIconBuilder.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.
@@ -26,7 +26,9 @@
import com.intellij.openapi.editor.markup.GutterIconRenderer;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
+import com.intellij.openapi.util.Factory;
import com.intellij.openapi.util.NotNullLazyValue;
+import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiElement;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
@@ -64,7 +66,7 @@
private final Icon myIcon;
private final NotNullFunction<T,Collection<? extends PsiElement>> myConverter;
- private NotNullLazyValue<Collection<? extends T>> myTargets;
+ private NotNullLazyValue<Collection<T>> myTargets;
private boolean myLazy;
private String myTooltipText;
private String myPopupTitle;
@@ -134,18 +136,15 @@
}
public NavigationGutterIconBuilder<T> setTargets(@NotNull final NotNullLazyValue<Collection<? extends T>> targets) {
- myTargets = targets;
+ //noinspection unchecked
+ myTargets = (NotNullLazyValue)targets;
myLazy = true;
return this;
}
public NavigationGutterIconBuilder<T> setTargets(@NotNull final Collection<? extends T> targets) {
- myTargets = new NotNullLazyValue<Collection<? extends T>>() {
- @NotNull
- public Collection<? extends T> compute() {
- return targets;
- }
- };
+ //noinspection unchecked
+ myTargets = NotNullLazyValue.createConstantValue((Collection<T>)targets);
return this;
}
@@ -206,46 +205,55 @@
public RelatedItemLineMarkerInfo<PsiElement> createLineMarkerInfo(@NotNull PsiElement element) {
final MyNavigationGutterIconRenderer renderer = createGutterIconRenderer(element.getProject());
final String tooltip = renderer.getTooltipText();
- NotNullLazyValue<Collection<? extends GotoRelatedItem>> gotoTargets = new NotNullLazyValue<Collection<? extends GotoRelatedItem>>() {
- @NotNull
- @Override
- protected Collection<? extends GotoRelatedItem> compute() {
- if (myGotoRelatedItemProvider != null) {
- return ContainerUtil.concat(myTargets.getValue(), myGotoRelatedItemProvider);
- }
- return Collections.emptyList();
- }
- };
+ NotNullLazyValue<Collection<? extends GotoRelatedItem>> gotoTargets = createGotoTargetsThunk(myLazy, myGotoRelatedItemProvider,
+ evaluateAndForget(myTargets));
return new RelatedItemLineMarkerInfo<PsiElement>(element, element.getTextRange(), renderer.getIcon(), Pass.UPDATE_OVERRIDEN_MARKERS,
tooltip == null ? null : new ConstantFunction<PsiElement, String>(tooltip),
renderer.isNavigateAction() ? renderer : null, renderer.getAlignment(),
gotoTargets);
}
+ private static <T> NotNullLazyValue<Collection<? extends GotoRelatedItem>> createGotoTargetsThunk(boolean lazy,
+ final NotNullFunction<T, Collection<? extends GotoRelatedItem>> gotoRelatedItemProvider,
+ final Factory<Collection<T>> factory) {
+ if (gotoRelatedItemProvider == null) {
+ return NotNullLazyValue.<Collection<? extends GotoRelatedItem>>createConstantValue(Collections.<GotoRelatedItem>emptyList());
+ }
+
+ if (lazy) {
+ return new NotNullLazyValue<Collection<? extends GotoRelatedItem>>() {
+ @NotNull
+ @Override
+ protected Collection<? extends GotoRelatedItem> compute() {
+ return ContainerUtil.concat(factory.create(), gotoRelatedItemProvider);
+ }
+ };
+ }
+ Collection<GotoRelatedItem> concat = ContainerUtil.concat(factory.create(), gotoRelatedItemProvider);
+ return NotNullLazyValue.<Collection<? extends GotoRelatedItem>>createConstantValue(concat);
+ }
+
private void checkBuilt() {
assert myTargets != null : "Must have called .setTargets() before calling create()";
}
-
- private MyNavigationGutterIconRenderer createGutterIconRenderer(@NotNull Project project) {
- checkBuilt();
- final SmartPointerManager manager = SmartPointerManager.getInstance(project);
-
- NotNullLazyValue<List<SmartPsiElementPointer>> pointers = new NotNullLazyValue<List<SmartPsiElementPointer>>() {
- @NotNull
- public List<SmartPsiElementPointer> compute() {
- Set<PsiElement> elements = new THashSet<PsiElement>();
- Collection<? extends T> targets = myTargets.getValue();
- final List<SmartPsiElementPointer> list = new ArrayList<SmartPsiElementPointer>(targets.size());
- for (final T target : targets) {
- for (final PsiElement psiElement : myConverter.fun(target)) {
- if (elements.add(psiElement) && psiElement.isValid()) {
- list.add(manager.createSmartPsiElementPointer(psiElement));
- }
- }
- }
- return list;
+
+ private static <T> Factory<T> evaluateAndForget(NotNullLazyValue<T> lazyValue) {
+ final Ref<NotNullLazyValue<T>> ref = Ref.create(lazyValue);
+ return new Factory<T>() {
+ @Override
+ public T create() {
+ T result = ref.get().getValue();
+ ref.set(null);
+ return result;
}
};
+ }
+
+ private MyNavigationGutterIconRenderer createGutterIconRenderer(@NotNull final Project project) {
+ checkBuilt();
+
+ NotNullLazyValue<List<SmartPsiElementPointer>> pointers = createPointersThunk(myLazy, project, evaluateAndForget(myTargets),
+ myConverter);
final boolean empty = isEmpty();
@@ -278,6 +286,37 @@
return new MyNavigationGutterIconRenderer(this, myAlignment, myIcon, myTooltipText, pointers, renderer, empty);
}
+ private static <T> NotNullLazyValue<List<SmartPsiElementPointer>> createPointersThunk(boolean lazy,
+ final Project project,
+ final Factory<Collection<T>> targets,
+ final NotNullFunction<T, Collection<? extends PsiElement>> converter) {
+ if (!lazy) {
+ return NotNullLazyValue.createConstantValue(calcPsiTargets(project, targets.create(), converter));
+ }
+
+ return new NotNullLazyValue<List<SmartPsiElementPointer>>() {
+ @NotNull
+ public List<SmartPsiElementPointer> compute() {
+ return calcPsiTargets(project, targets.create(), converter);
+ }
+ };
+ }
+
+ private static <T> List<SmartPsiElementPointer> calcPsiTargets(Project project, Collection<? extends T> targets,
+ NotNullFunction<T, Collection<? extends PsiElement>> converter) {
+ SmartPointerManager manager = SmartPointerManager.getInstance(project);
+ Set<PsiElement> elements = new THashSet<PsiElement>();
+ final List<SmartPsiElementPointer> list = new ArrayList<SmartPsiElementPointer>(targets.size());
+ for (final T target : targets) {
+ for (final PsiElement psiElement : converter.fun(target)) {
+ if (elements.add(psiElement) && psiElement.isValid()) {
+ list.add(manager.createSmartPsiElementPointer(psiElement));
+ }
+ }
+ }
+ return list;
+ }
+
private boolean isEmpty() {
if (myLazy) {
return false;
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 dafea5a..493f6a5 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/DomFileIndex.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/DomFileIndex.java
@@ -101,13 +101,6 @@
@Override
public int getVersion() {
- final DomApplicationComponent component = DomApplicationComponent.getInstance();
- int result = 0;
- for (DomFileDescription description : component.getAllFileDescriptions()) {
- result += description.getVersion();
- result += description.getRootTagName().hashCode(); // so that a plugin enabling/disabling could trigger the reindexing
- }
- return result;
+ return DomApplicationComponent.getInstance().getCumulativeVersion();
}
-
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java b/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
index 0d86645..edb8521 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/EnumConverter.java
@@ -1,9 +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.util.xml;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NotNull;
@@ -63,6 +78,6 @@
}
public boolean isExhaustive() {
- return !ReflectionCache.isAssignable(NonExhaustiveEnum.class, myType);
+ return !ReflectionUtil.isAssignable(NonExhaustiveEnum.class, myType);
}
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/ModelMergerImpl.java b/xml/dom-impl/src/com/intellij/util/xml/ModelMergerImpl.java
index fb2fe38..b06563e 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/ModelMergerImpl.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/ModelMergerImpl.java
@@ -1,7 +1,21 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.xml;
import com.intellij.openapi.util.Pair;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ConcurrentFactoryMap;
@@ -258,10 +272,10 @@
}
private JavaMethod getJavaMethod(final Method method) {
- if (ReflectionCache.isAssignable(MERGED_OBJECT_CLASS, method.getDeclaringClass())) {
+ if (ReflectionUtil.isAssignable(MERGED_OBJECT_CLASS, method.getDeclaringClass())) {
return JavaMethod.getMethod(MERGED_OBJECT_CLASS, method);
}
- if (ReflectionCache.isAssignable(method.getDeclaringClass(), myClass)) {
+ if (ReflectionUtil.isAssignable(method.getDeclaringClass(), myClass)) {
return JavaMethod.getMethod(myClass, method);
}
return JavaMethod.getMethod(method.getDeclaringClass(), method);
@@ -273,7 +287,7 @@
final Method method = getPrimaryKeyMethod(implementation.getClass());
if (method != null) {
final Object o = DomReflectionUtil.invokeMethod(method, implementation);
- return ReflectionCache.isAssignable(GenericValue.class, method.getReturnType()) ? ((GenericValue)o).getValue() : o;
+ return ReflectionUtil.isAssignable(GenericValue.class, method.getReturnType()) ? ((GenericValue)o).getValue() : o;
}
else {
if (implementation instanceof GenericValue) {
@@ -315,7 +329,7 @@
final List<Object> results = new ArrayList<Object>();
- if (ReflectionCache.isInterface(returnType)) {
+ if (returnType.isInterface()) {
final List<Object> orderedPrimaryKeys = new SmartList<Object>();
final FactoryMap<Object, List<Set<Object>>> map = new FactoryMap<Object, List<Set<Object>>>() {
@NotNull
@@ -369,7 +383,7 @@
protected final Object mergeImplementations(final Class returnType, final List<Object> implementations) {
for (int i = myMergingStrategies.size() - 1; i >= 0; i--) {
- if (ReflectionCache.isAssignable(myMergingStrategyClasses.get(i), returnType)) {
+ if (ReflectionUtil.isAssignable(myMergingStrategyClasses.get(i), returnType)) {
final Object o = myMergingStrategies.get(i).mergeChildren(returnType, implementations);
if (o != null) {
return o;
diff --git a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementsHighlightingUtil.java b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementsHighlightingUtil.java
index 8c2e60b..06cfcd3 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementsHighlightingUtil.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/highlighting/DomElementsHighlightingUtil.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.
@@ -93,7 +93,7 @@
private static Annotation createAnnotation(final HighlightSeverity severity,
final TextRange range,
final String text) {
- String tooltip = text == null ? null : "<html><body>" + XmlStringUtil.escapeString(text) + "</body></html>";
+ String tooltip = text == null ? null : XmlStringUtil.wrapInHtml(XmlStringUtil.escapeString(text));
return new Annotation(range.getStartOffset(), range.getEndOffset(), severity, text, tooltip);
}
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 058ce38..f995670 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
@@ -30,7 +30,6 @@
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
import java.lang.reflect.Type;
import java.util.List;
@@ -94,6 +93,15 @@
return ServiceManager.getService(DomApplicationComponent.class);
}
+ 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
+ }
+ return result;
+ }
+
public final synchronized Set<DomFileDescription> getFileDescriptions(String rootTagName) {
return myRootTagName2FileDescription.get(rootTagName);
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomImplUtil.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomImplUtil.java
index eaeac39..c95c92c 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomImplUtil.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomImplUtil.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.
@@ -23,7 +23,7 @@
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.xml.*;
import com.intellij.util.xml.reflect.DomCollectionChildDescription;
@@ -77,9 +77,9 @@
if (method.getAnnotation(SubTag.class) != null) return false;
if (method.getAnnotation(SubTagList.class) != null) return false;
if (method.getAnnotation(Convert.class) != null || method.getAnnotation(Resolve.class) != null) {
- return !ReflectionCache.isAssignable(GenericDomValue.class, method.getReturnType());
+ return !ReflectionUtil.isAssignable(GenericDomValue.class, method.getReturnType());
}
- if (ReflectionCache.isAssignable(DomElement.class, method.getReturnType())) return false;
+ if (ReflectionUtil.isAssignable(DomElement.class, method.getReturnType())) return false;
return true;
}
return false;
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java
index d1d85cc..7bf5e11 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomInvocationHandler.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.
@@ -441,7 +441,7 @@
private Converter createConverter(final JavaMethod method) {
final Type returnType = method.getGenericReturnType();
final Type type = returnType == void.class ? method.getGenericParameterTypes()[0] : returnType;
- final Class parameter = ReflectionUtil.substituteGenericType(type, myType);
+ final Class parameter = DomUtil.substituteGenericType(type, myType);
if (parameter == null) {
LOG.error(type + " " + myType);
}
@@ -514,7 +514,7 @@
if (proxy == null) {
Class<?> rawType = getRawType();
Class<? extends DomElement> implementation = myManager.getApplicationComponent().getImplementation(rawType);
- final boolean isInterface = ReflectionCache.isInterface(rawType);
+ final boolean isInterface = rawType.isInterface();
if (implementation == null && !isInterface) {
//noinspection unchecked
implementation = (Class<? extends DomElement>)rawType;
@@ -690,7 +690,7 @@
}
public final String toString() {
- if (ReflectionCache.isAssignable(GenericValue.class, getRawType())) {
+ if (ReflectionUtil.isAssignable(GenericValue.class, getRawType())) {
return ((GenericValue)getProxy()).getStringValue();
}
return myType.toString() + " @" + hashCode();
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java
index ed67161..b9a93e1 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomManagerImpl.java
@@ -42,6 +42,7 @@
import com.intellij.psi.xml.XmlElement;
import com.intellij.psi.xml.XmlFile;
import com.intellij.psi.xml.XmlTag;
+import com.intellij.reference.SoftReference;
import com.intellij.semantic.SemKey;
import com.intellij.semantic.SemService;
import com.intellij.util.EventDispatcher;
@@ -86,31 +87,26 @@
private final SemService mySemService;
private final ConverterManager myConverterManager;
private final DomApplicationComponent myApplicationComponent;
- private final PsiFileFactory myFileFactory;
- private final ProjectFileIndex myFileIndex;
private long myModificationCount;
private boolean myChanging;
public DomManagerImpl(Project project,
- final XmlAspect xmlAspect,
SemService semService,
ConverterManager converterManager,
- DomApplicationComponent appComponent,
- PsiFileFactory fileFactory,
- ProjectFileIndex fileIndex) {
+ DomApplicationComponent appComponent) {
myProject = project;
mySemService = semService;
myConverterManager = converterManager;
myApplicationComponent = appComponent;
- myFileFactory = fileFactory;
- myFileIndex = fileIndex;
- PomModel pomModel = PomManager.getModel(project);
+ final PomModel pomModel = PomManager.getModel(project);
pomModel.addModelListener(new PomModelListener() {
public void modelChanged(PomModelEvent event) {
- final XmlChangeSet changeSet = (XmlChangeSet)event.getChangeSet(xmlAspect);
- if (changeSet != null && !myChanging) {
+ if (myChanging) return;
+
+ final XmlChangeSet changeSet = (XmlChangeSet)event.getChangeSet(pomModel.getModelAspect(XmlAspect.class));
+ if (changeSet != null) {
for (XmlFile file : changeSet.getChangedFiles()) {
DomFileElementImpl<DomElement> element = getCachedFileElement(file);
if (element != null) {
@@ -121,7 +117,7 @@
}
public boolean isAspectChangeInteresting(PomModelAspect aspect) {
- return xmlAspect.equals(aspect);
+ return aspect instanceof XmlAspect;
}
}, project);
@@ -234,7 +230,7 @@
}
private void processFileOrDirectoryChange(final VirtualFile file) {
- if (!myFileIndex.isInContent(file)) return;
+ if (!ProjectFileIndex.SERVICE.getInstance(myProject).isInContent(file)) return;
if (!file.isDirectory()) {
processFileChange(file);
} else {
@@ -377,7 +373,7 @@
@Nullable
static <T extends DomElement> DomFileElementImpl<T> getCachedFileElement(@NotNull XmlFile file) {
WeakReference<DomFileElementImpl> ref = file.getUserData(CACHED_FILE_ELEMENT);
- return ref == null ? null : ref.get();
+ return SoftReference.dereference(ref);
}
@Nullable
@@ -444,7 +440,7 @@
}
public final <T extends DomElement> T createMockElement(final Class<T> aClass, final Module module, final boolean physical) {
- final XmlFile file = (XmlFile)myFileFactory.createFileFromText("a.xml", StdFileTypes.XML, "", (long)0, physical);
+ final XmlFile file = (XmlFile)PsiFileFactory.getInstance(myProject).createFileFromText("a.xml", StdFileTypes.XML, "", (long)0, physical);
file.putUserData(MOCK_ELEMENT_MODULE, module);
file.putUserData(MOCK, new Object());
return getFileElement(file, aClass, "I_sincerely_hope_that_nobody_will_have_such_a_root_tag_name").getRootElement();
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DomServiceImpl.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DomServiceImpl.java
index ce5bb54..b63a29d 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DomServiceImpl.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DomServiceImpl.java
@@ -39,12 +39,9 @@
import com.intellij.psi.xml.*;
import com.intellij.util.Function;
import com.intellij.util.indexing.FileBasedIndex;
-import com.intellij.util.indexing.FileContent;
-import com.intellij.util.text.CharSequenceReader;
import com.intellij.util.xml.*;
import com.intellij.util.xml.structure.DomStructureViewBuilder;
import com.intellij.util.xml.stubs.FileStub;
-import com.intellij.util.xml.stubs.builder.DomStubBuilder;
import com.intellij.xml.util.XmlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -90,13 +87,6 @@
if (!file.isValid()) return XmlFileHeader.EMPTY;
- if (XmlUtil.isStubBuilding() && file.getFileType() == XmlFileType.INSTANCE) {
- FileContent fileContent = file.getUserData(DomStubBuilder.CONTENT_FOR_DOM_STUBS);
- if (fileContent != null) {
- //noinspection IOResourceOpenedButNotSafelyClosed
- return NanoXmlUtil.parseHeader(new CharSequenceReader(fileContent.getContentAsText()));
- }
- }
return NanoXmlUtil.parseHeader(file);
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java b/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java
index fa95b8a..96fbf46 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/DynamicGenericInfo.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -138,7 +138,7 @@
private static <T extends DomChildDescriptionImpl> ChildrenDescriptionsHolder<T> internChildrenHolder(XmlFile file, ChildrenDescriptionsHolder<T> holder) {
SoftReference<ConcurrentHashMap<ChildrenDescriptionsHolder, ChildrenDescriptionsHolder>> ref = file.getUserData(HOLDERS_CACHE);
- ConcurrentHashMap<ChildrenDescriptionsHolder, ChildrenDescriptionsHolder> cache = ref == null ? null : ref.get();
+ ConcurrentHashMap<ChildrenDescriptionsHolder, ChildrenDescriptionsHolder> cache = SoftReference.dereference(ref);
if (cache == null) {
cache = new ConcurrentHashMap<ChildrenDescriptionsHolder, ChildrenDescriptionsHolder>();
file.putUserData(HOLDERS_CACHE, new SoftReference<ConcurrentHashMap<ChildrenDescriptionsHolder, ChildrenDescriptionsHolder>>(cache));
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/FileDescriptionCachedValueProvider.java b/xml/dom-impl/src/com/intellij/util/xml/impl/FileDescriptionCachedValueProvider.java
index a9adbfe..4b6ac95 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/FileDescriptionCachedValueProvider.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/FileDescriptionCachedValueProvider.java
@@ -15,6 +15,7 @@
*/
package com.intellij.util.xml.impl;
+import com.intellij.ide.highlighter.DomSupportEnabled;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.util.Condition;
@@ -91,6 +92,14 @@
sb.append("File is valid\n");
}
+ if (!(myXmlFile.getFileType() instanceof DomSupportEnabled)) {
+ return null;
+ }
+
+ if (sb != null) {
+ sb.append("File is of dom file type\n");
+ }
+
final DomFileDescription<T> description = findFileDescription(rootTagName, sb);
final DomFileElementImpl oldValue = getLastValue();
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java b/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
index d817a7e..2df2c4c 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/GenericValueReferenceProvider.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.
@@ -22,7 +22,7 @@
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.ProcessingContext;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.xml.*;
import com.intellij.xml.util.XmlEnumeratedValueReferenceProvider;
import org.jetbrains.annotations.NotNull;
@@ -145,7 +145,7 @@
final Class clazz = DomUtil.getGenericValueParameter(invocationHandler.getDomElementType());
if (clazz == null) return PsiReference.EMPTY_ARRAY;
- if (ReflectionCache.isAssignable(Integer.class, clazz)) {
+ if (ReflectionUtil.isAssignable(Integer.class, clazz)) {
return new PsiReference[]{new GenericDomValueReference<Integer>((GenericDomValue<Integer>)domValue) {
@NotNull
public Object[] getVariants() {
@@ -153,7 +153,7 @@
}
}};
}
- if (ReflectionCache.isAssignable(String.class, clazz)) {
+ if (ReflectionUtil.isAssignable(String.class, clazz)) {
return PsiReference.EMPTY_ARRAY;
}
PsiReferenceFactory provider = myProviders.get(clazz);
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/ImplementationClassCache.java b/xml/dom-impl/src/com/intellij/util/xml/impl/ImplementationClassCache.java
index 463c06d..3cb49c9 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/ImplementationClassCache.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/ImplementationClassCache.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,10 +19,6 @@
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.Disposer;
import com.intellij.util.NotNullFunction;
-import com.intellij.util.ReflectionCache;
-import com.intellij.util.SofterReference;
-import com.intellij.util.containers.ConcurrentFactoryMap;
-import com.intellij.util.containers.ConcurrentHashMap;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.xml.DomReflectionUtil;
import com.intellij.util.xml.Implementation;
@@ -33,7 +29,6 @@
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
-import java.util.concurrent.ConcurrentMap;
/**
* @author peter
@@ -82,7 +77,7 @@
return;
}
}
- for (final Class aClass1 : ReflectionCache.getInterfaces(concreteInterface)) {
+ for (final Class aClass1 : concreteInterface.getInterfaces()) {
findImplementationClassDFS(aClass1, results);
}
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfoBuilder.java b/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfoBuilder.java
index e029fe1..86009af 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfoBuilder.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/StaticGenericInfoBuilder.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,7 +19,6 @@
import com.intellij.openapi.util.MultiValuesMap;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.FactoryMap;
@@ -68,7 +67,7 @@
final Set<JavaMethod> methods = new LinkedHashSet<JavaMethod>();
InvocationCache invocationCache = DomApplicationComponent.getInstance().getInvocationCache(myClass);
- for (final Method method : ReflectionCache.getMethods(myClass)) {
+ for (final Method method : myClass.getMethods()) {
methods.add(invocationCache.getInternedMethod(method));
}
for (final JavaMethod method : methods) {
@@ -81,7 +80,7 @@
{
final Class implClass = DomApplicationComponent.getInstance().getImplementation(myClass);
if (implClass != null) {
- for (Method method : ReflectionCache.getMethods(implClass)) {
+ for (Method method : implClass.getMethods()) {
final int modifiers = method.getModifiers();
if (!Modifier.isAbstract(modifiers) &&
!Modifier.isVolatile(modifiers) &&
diff --git a/xml/dom-impl/src/com/intellij/util/xml/impl/VisitorDescription.java b/xml/dom-impl/src/com/intellij/util/xml/impl/VisitorDescription.java
index 80ea5cd..58fa38e 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/impl/VisitorDescription.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/impl/VisitorDescription.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,7 +15,7 @@
*/
package com.intellij.util.xml.impl;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ConcurrentClassMap;
import com.intellij.util.xml.DomElement;
import com.intellij.util.xml.DomElementVisitor;
@@ -34,13 +34,13 @@
public VisitorDescription(final Class<? extends DomElementVisitor> visitorClass) {
myVisitorClass = visitorClass;
- for (final Method method : ReflectionCache.getMethods(visitorClass)) {
+ for (final Method method : visitorClass.getMethods()) {
final Class<?>[] parameterTypes = method.getParameterTypes();
if (parameterTypes.length != 1) {
continue;
}
final Class<?> domClass = parameterTypes[0];
- if (!ReflectionCache.isAssignable(DomElement.class, domClass)) {
+ if (!ReflectionUtil.isAssignable(DomElement.class, domClass)) {
continue;
}
final String methodName = method.getName();
diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilder.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilder.java
index caf72cf..7528f98 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilder.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilder.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,13 +17,13 @@
import com.intellij.ide.highlighter.XmlFileType;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.extensions.Extensions;
+import com.intellij.openapi.editor.Document;
+import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiManager;
import com.intellij.psi.stubs.BinaryFileStubBuilder;
import com.intellij.psi.stubs.Stub;
import com.intellij.psi.xml.XmlFile;
@@ -31,6 +31,7 @@
import com.intellij.util.indexing.FileBasedIndexImpl;
import com.intellij.util.indexing.FileContent;
import com.intellij.util.xml.*;
+import com.intellij.util.xml.impl.DomApplicationComponent;
import com.intellij.util.xml.impl.DomManagerImpl;
import com.intellij.util.xml.stubs.FileStub;
import com.intellij.xml.util.XmlUtil;
@@ -40,8 +41,6 @@
* Date: 8/2/12
*/
public class DomStubBuilder implements BinaryFileStubBuilder {
-
- public final static Key<FileContent> CONTENT_FOR_DOM_STUBS = Key.create("dom stubs content");
private final static Logger LOG = Logger.getInstance(DomStubBuilder.class);
@Override
@@ -52,21 +51,27 @@
@Override
public Stub buildStubTree(FileContent fileContent) {
- VirtualFile file = fileContent.getFile();
- Project project = fileContent.getProject();
- PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
+ PsiFile psiFile = fileContent.getPsiFile();
if (!(psiFile instanceof XmlFile)) return null;
+ Document document = FileDocumentManager.getInstance().getCachedDocument(fileContent.getFile());
+ Project project = fileContent.getProject();
+ if (document != null) {
+ PsiFile existingPsi = PsiDocumentManager.getInstance(project).getPsiFile(document);
+ if (existingPsi != null) {
+ psiFile = existingPsi;
+ }
+ }
+
XmlFile xmlFile = (XmlFile)psiFile;
try {
XmlUtil.BUILDING_DOM_STUBS.set(Boolean.TRUE);
- psiFile.putUserData(CONTENT_FOR_DOM_STUBS, fileContent);
DomFileElement<? extends DomElement> fileElement = DomManager.getDomManager(project).getFileElement(xmlFile);
if (fileElement == null || !fileElement.getFileDescription().hasStubs()) return null;
XmlFileHeader header = DomService.getInstance().getXmlFileHeader(xmlFile);
if (header.getRootTagLocalName() == null) {
- LOG.error("null root tag for " + fileElement + " for " + file);
+ LOG.error("null root tag for " + fileElement + " for " + fileContent.getFile());
}
FileStub fileStub = new FileStub(header);
XmlTag rootTag = xmlFile.getRootTag();
@@ -77,17 +82,11 @@
}
finally {
XmlUtil.BUILDING_DOM_STUBS.set(Boolean.FALSE);
- psiFile.putUserData(CONTENT_FOR_DOM_STUBS, null);
}
}
@Override
public int getStubVersion() {
- int version = 17;
- DomFileDescription[] descriptions = Extensions.getExtensions(DomFileDescription.EP_NAME);
- for (DomFileDescription description : descriptions) {
- version += description.getStubVersion();
- }
- return version;
+ return 18 + DomApplicationComponent.getInstance().getCumulativeVersion();
}
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilderVisitor.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilderVisitor.java
index 3602f9c..894836b 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilderVisitor.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/builder/DomStubBuilderVisitor.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.
@@ -64,7 +64,7 @@
StringRef.fromNullableString(nsKey),
index,
description instanceof CustomDomChildrenDescription,
- StringRef.fromNullableString(elementClass));
+ elementClass == null ? null : StringRef.fromNullableString(elementClass));
for (XmlAttribute attribute : tag.getAttributes()) {
visitXmlElement(attribute, stub, 0);
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java b/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java
index 512d2cc..d1ba594 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/stubs/index/DomNamespaceKeyIndex.java
@@ -51,13 +51,13 @@
namespaceKey,
domFileElement.getFile().getProject(),
GlobalSearchScope.fileScope(domFileElement.getFile()),
- new IdFilter() {
- @Override
- public boolean containsFileId(int id) {
- return id == virtualFileId;
- }
- },
- processor
+ new IdFilter() {
+ @Override
+ public boolean containsFileId(int id) {
+ return id == virtualFileId;
+ }
+ },
+ processor
);
return processor.isFound();
}
diff --git a/xml/dom-impl/src/com/intellij/util/xml/tree/actions/DeleteDomElement.java b/xml/dom-impl/src/com/intellij/util/xml/tree/actions/DeleteDomElement.java
index bbd2bf6..d525acf 100644
--- a/xml/dom-impl/src/com/intellij/util/xml/tree/actions/DeleteDomElement.java
+++ b/xml/dom-impl/src/com/intellij/util/xml/tree/actions/DeleteDomElement.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -57,7 +57,7 @@
final int ret = Messages.showOkCancelDialog(getPresentationText(selectedNode) + "?", ApplicationBundle.message("action.remove"),
Messages.getQuestionIcon());
- if (ret == 0) {
+ if (ret == Messages.OK) {
new WriteCommandAction(domElement.getManager().getProject(), DomUtil.getFile(domElement)) {
protected void run(final Result result) throws Throwable {
domElement.undefine();
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/DomBundle.java b/xml/dom-openapi/src/com/intellij/util/xml/DomBundle.java
index b1379dc..a36a99a 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/DomBundle.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/DomBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -18,6 +18,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -28,20 +29,19 @@
* @author Dmitry Avdeev
*/
public class DomBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = "messages.DomBundle") String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls protected static final String PATH_TO_BUNDLE = "messages.DomBundle";
private DomBundle() {
}
- public static String message(@PropertyKey(resourceBundle = "messages.DomBundle")String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java b/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java
index 9a6de09..3b84cdf 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/DomUtil.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,6 @@
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.xml.*;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.SmartList;
import com.intellij.util.containers.ConcurrentFactoryMap;
@@ -48,20 +47,23 @@
*/
public class DomUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.util.xml.DomUtil");
- public static final TypeVariable<Class<GenericValue>> GENERIC_VALUE_TYPE_VARIABLE = ReflectionCache.getTypeParameters(GenericValue.class)[0];
+ public static final TypeVariable<Class<GenericValue>> GENERIC_VALUE_TYPE_VARIABLE = GenericValue.class.getTypeParameters()[0];
private static final Class<Void> DUMMY = void.class;
private static final Key<DomFileElement> FILE_ELEMENT_KEY = Key.create("dom file element");
private static final ConcurrentFactoryMap<Type, Class> ourTypeParameters = new ConcurrentFactoryMap<Type, Class>() {
@NotNull
protected Class create(final Type key) {
- final Class<?> result = ReflectionUtil.substituteGenericType(GENERIC_VALUE_TYPE_VARIABLE, key);
+ final Class<?> result = substituteGenericType(GENERIC_VALUE_TYPE_VARIABLE, key);
return result == null ? DUMMY : result;
}
};
-
- private DomUtil() {
- }
+ private static final ConcurrentFactoryMap<Pair<Type, Type>, Class> ourVariableSubstitutions = new ConcurrentFactoryMap<Pair<Type, Type>, Class>() {
+ @Nullable
+ protected Class create(final Pair<Type, Type> key) {
+ return ReflectionUtil.substituteGenericType(key.first, key.second);
+ }
+ };
public static Class extractParameterClassFromGenericType(Type type) {
return getGenericValueParameter(type);
@@ -156,6 +158,10 @@
return description != null ? description.getGetterMethod(description.getValues(parent).indexOf(element)) : null;
}
+ public static Class<?> substituteGenericType(Type genericType, Type classType) {
+ return ourVariableSubstitutions.get(Pair.create(genericType, classType));
+ }
+
@Nullable
public static Class getGenericValueParameter(Type type) {
final Class aClass = ourTypeParameters.get(type);
@@ -306,7 +312,7 @@
}
public static Collection<Class> getAllInterfaces(final Class aClass, final Collection<Class> result) {
- final Class[] interfaces = ReflectionCache.getInterfaces(aClass);
+ final Class[] interfaces = aClass.getInterfaces();
ContainerUtil.addAll(result, interfaces);
if (aClass.getSuperclass() != null) {
getAllInterfaces(aClass.getSuperclass(), result);
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ElementPresentationManager.java b/xml/dom-openapi/src/com/intellij/util/xml/ElementPresentationManager.java
index e802a98..43bc6c6 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/ElementPresentationManager.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/ElementPresentationManager.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.
@@ -26,7 +26,6 @@
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import com.intellij.util.NullableFunction;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.containers.ConcurrentFactoryMap;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -34,7 +33,9 @@
import javax.swing.*;
import java.lang.reflect.Method;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
/**
* @author peter
@@ -43,7 +44,7 @@
private static final ConcurrentFactoryMap<Class,Method> ourNameValueMethods = new ConcurrentFactoryMap<Class, Method>() {
@Nullable
protected Method create(final Class key) {
- for (final Method method : ReflectionCache.getMethods(key)) {
+ for (final Method method : key.getMethods()) {
if (JavaMethod.getMethod(key, method).getAnnotation(NameValue.class) != null) {
return method;
}
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/JavaMethodSignature.java b/xml/dom-openapi/src/com/intellij/util/xml/JavaMethodSignature.java
index 359ec5a..54a2fe9 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/JavaMethodSignature.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/JavaMethodSignature.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,13 +16,14 @@
package com.intellij.util.xml;
import com.intellij.util.ArrayUtil;
-import com.intellij.util.ReflectionCache;
import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.Nullable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
/**
* @author peter
@@ -47,7 +48,7 @@
@Nullable
public final Method findMethod(final Class aClass) {
Method method = getDeclaredMethod(aClass);
- if (method == null && ReflectionCache.isInterface(aClass)) {
+ if (method == null && aClass.isInterface()) {
method = getDeclaredMethod(Object.class);
}
return method;
@@ -90,7 +91,7 @@
public final <T extends Annotation> Method findAnnotatedMethod(final Class<T> annotationClass, final Class startFrom) {
for (Method method : getAllMethods(startFrom)) {
final T annotation = method.getAnnotation(annotationClass);
- if (annotation != null && ReflectionCache.isAssignable(method.getDeclaringClass(), startFrom)) {
+ if (annotation != null && ReflectionUtil.isAssignable(method.getDeclaringClass(), startFrom)) {
return method;
}
}
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ModelMerger.java b/xml/dom-openapi/src/com/intellij/util/xml/ModelMerger.java
index b8f9c97..572aa10 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/ModelMerger.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/ModelMerger.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.
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/ModelMergerUtil.java b/xml/dom-openapi/src/com/intellij/util/xml/ModelMergerUtil.java
index 07fdd48..2481f42 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/ModelMergerUtil.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/ModelMergerUtil.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,11 +15,12 @@
*/
package com.intellij.util.xml;
+import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
-import com.intellij.util.CommonProcessors;import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -59,7 +60,7 @@
if (element == null) return null;
CommonProcessors.FindFirstProcessor<T> processor = new CommonProcessors.FindFirstProcessor<T>() {
public boolean process(final T t) {
- return !ReflectionCache.isAssignable(clazz, t.getClass()) || super.process(t);
+ return !ReflectionUtil.isAssignable(clazz, t.getClass()) || super.process(t);
}
};
new ImplementationProcessor<T>(processor, true).process(element);
@@ -71,7 +72,7 @@
if (element == null) return Collections.emptyList();
CommonProcessors.CollectProcessor<T> processor = new CommonProcessors.CollectProcessor<T>() {
public boolean process(final T t) {
- return !ReflectionCache.isAssignable(clazz, t.getClass()) || super.process(t);
+ return !ReflectionUtil.isAssignable(clazz, t.getClass()) || super.process(t);
}
};
new ImplementationProcessor<T>(processor, true).process(element);
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/NamedEnumUtil.java b/xml/dom-openapi/src/com/intellij/util/xml/NamedEnumUtil.java
index 060a7a5..85a59b8 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/NamedEnumUtil.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/NamedEnumUtil.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,9 +15,9 @@
*/
package com.intellij.util.xml;
-import com.intellij.util.Function;
-import com.intellij.util.ReflectionCache;
import com.intellij.openapi.util.Comparing;
+import com.intellij.util.Function;
+import com.intellij.util.ReflectionUtil;
/**
* @author peter
@@ -47,7 +47,7 @@
}
private static <T extends Enum> Function<Enum, String> getShow(final Class<T> enumClass) {
- return ReflectionCache.isAssignable(NamedEnum.class, enumClass) ? NAMED_SHOW : SIMPLE_SHOW;
+ return ReflectionUtil.isAssignable(NamedEnum.class, enumClass) ? NAMED_SHOW : SIMPLE_SHOW;
}
public static <T extends Enum> String getEnumValueByElement(final T element) {
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/Stubbed.java b/xml/dom-openapi/src/com/intellij/util/xml/Stubbed.java
index 95d73a4..75abd4c 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/Stubbed.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/Stubbed.java
@@ -27,6 +27,4 @@
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.METHOD, ElementType.TYPE})
public @interface Stubbed {
-
- boolean stubAllAttributes() default false;
}
\ No newline at end of file
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/highlighting/BasicDomElementsInspection.java b/xml/dom-openapi/src/com/intellij/util/xml/highlighting/BasicDomElementsInspection.java
index 6bc1224..f1c7c08 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/highlighting/BasicDomElementsInspection.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/highlighting/BasicDomElementsInspection.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.
diff --git a/xml/dom-openapi/src/com/intellij/util/xml/highlighting/DomElementsInspection.java b/xml/dom-openapi/src/com/intellij/util/xml/highlighting/DomElementsInspection.java
index fe7670e..3c7844b 100644
--- a/xml/dom-openapi/src/com/intellij/util/xml/highlighting/DomElementsInspection.java
+++ b/xml/dom-openapi/src/com/intellij/util/xml/highlighting/DomElementsInspection.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.
diff --git a/xml/dom-tests/tests/com/intellij/util/xml/DomChildrenTest.java b/xml/dom-tests/tests/com/intellij/util/xml/DomChildrenTest.java
index 89229bf..efd9325 100644
--- a/xml/dom-tests/tests/com/intellij/util/xml/DomChildrenTest.java
+++ b/xml/dom-tests/tests/com/intellij/util/xml/DomChildrenTest.java
@@ -206,7 +206,7 @@
assertTrue(child2.isValid());
assertEquals(element, child2.getParent());
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
child2.undefine();
assertFalse(child2.isValid());
diff --git a/xml/dom-tests/tests/com/intellij/util/xml/DomIncludesTest.java b/xml/dom-tests/tests/com/intellij/util/xml/DomIncludesTest.java
index 3de62d6..095c9d4 100644
--- a/xml/dom-tests/tests/com/intellij/util/xml/DomIncludesTest.java
+++ b/xml/dom-tests/tests/com/intellij/util/xml/DomIncludesTest.java
@@ -1,12 +1,23 @@
/*
- * Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
- * Use is subject to license terms.
+ * Copyright 2000-2014 JetBrains s.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.xml;
import com.intellij.codeInsight.navigation.actions.GotoDeclarationAction;
-import com.intellij.concurrency.JobLauncher;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.PomTargetPsiElement;
@@ -110,23 +121,23 @@
final AtomicReference<Exception> ex = new AtomicReference<Exception>();
for (int j = 0; j < threadCount; j++) {
- JobLauncher.getInstance().submitToJobThread(0, new Runnable() {
+ ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
@Override
public void run() {
try {
- for (int k = 0; k < iterationCount; k++) {
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- public void run() {
+ for (int k = 0; k < iterationCount; k++) {
+ ApplicationManager.getApplication().runReadAction(new Runnable() {
+ public void run() {
final List<Boy> boys = rootElement.getBoys();
Thread.yield();
final List<Child> children = rootElement.getChildren();
Thread.yield();
assertEquals(boys, rootElement.getBoys());
assertEquals(children, rootElement.getChildren());
- }
- });
- Thread.yield();
- }
+ }
+ });
+ Thread.yield();
+ }
}
catch (Exception e) {
ex.set(e);
@@ -139,7 +150,7 @@
}
for (int i = 0; i < iterationCount; i++) {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
fileB.getViewProvider().getDocument().insertString(0, " ");
fileD.getViewProvider().getDocument().insertString(0, " ");
@@ -147,16 +158,15 @@
}
});
Thread.sleep(10);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
fileC.getViewProvider().getDocument().insertString(0, " ");
fileE.getViewProvider().getDocument().insertString(0, " ");
PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); //clear xinclude caches
}
});
Thread.sleep(10);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
+
fileB.getViewProvider().getDocument().setText(textB);
fileC.getViewProvider().getDocument().setText(textC);
fileD.getViewProvider().getDocument().setText(textD);
diff --git a/xml/dom-tests/tests/com/intellij/util/xml/impl/IncrementalUpdateEventsTest.java b/xml/dom-tests/tests/com/intellij/util/xml/impl/IncrementalUpdateEventsTest.java
index 2f7f2fe..41c6b49 100644
--- a/xml/dom-tests/tests/com/intellij/util/xml/impl/IncrementalUpdateEventsTest.java
+++ b/xml/dom-tests/tests/com/intellij/util/xml/impl/IncrementalUpdateEventsTest.java
@@ -15,7 +15,7 @@
*/
package com.intellij.util.xml.impl;
-import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.xml.DomElement;
@@ -123,7 +123,7 @@
private void deleteTag(final int index) throws IncorrectOperationException {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
myElement.getXmlTag().getSubTags()[index].delete();
}
diff --git a/xml/dom-tests/tests/com/intellij/util/xml/impl/TreeIncrementalUpdateTest.java b/xml/dom-tests/tests/com/intellij/util/xml/impl/TreeIncrementalUpdateTest.java
index 7d69ccf..3ad475a 100644
--- a/xml/dom-tests/tests/com/intellij/util/xml/impl/TreeIncrementalUpdateTest.java
+++ b/xml/dom-tests/tests/com/intellij/util/xml/impl/TreeIncrementalUpdateTest.java
@@ -1,3 +1,18 @@
+/*
+ * 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.util.xml.impl;
import com.intellij.openapi.application.ApplicationManager;
@@ -357,7 +372,7 @@
final XmlTag tag = element.getXmlTag();
final XmlTag childTag = tag.getSubTags()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
childTag.delete();
}
@@ -376,8 +391,7 @@
final Sepulka element = createElement("<a><foo/><bar/></a>", Sepulka.class);
final List<MyElement> list = element.getCustomChildren();
final XmlTag tag = element.getXmlTag();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
tag.getSubTags()[0].delete();
tag.getSubTags()[0].delete();
}
diff --git a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java
index 54983ba..d0c2174 100644
--- a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.java
+++ b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubTest.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.psi.stubs.ObjectStubTree;
import com.intellij.psi.stubs.StubTreeLoader;
import com.intellij.psi.xml.XmlFile;
+import com.intellij.testFramework.TestDataFile;
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import com.intellij.util.xml.DomElement;
@@ -62,11 +63,11 @@
return "/xml/dom-tests/testData/stubs";
}
- protected ElementStub getRootStub(String filePath) {
+ protected ElementStub getRootStub(@TestDataFile String filePath) {
return getRootStub(filePath, myFixture);
}
- public static ElementStub getRootStub(String filePath, JavaCodeInsightTestFixture fixture) {
+ public static ElementStub getRootStub(@TestDataFile String filePath, JavaCodeInsightTestFixture fixture) {
PsiFile psiFile = fixture.configureByFile(filePath);
StubTreeLoader loader = StubTreeLoader.getInstance();
@@ -79,12 +80,12 @@
return root;
}
- protected void doBuilderTest(String file, String stubText) {
+ protected void doBuilderTest(@TestDataFile String file, String stubText) {
ElementStub stub = getRootStub(file);
assertEquals(stubText, DebugUtil.stubTreeToString(stub));
}
- protected <T extends DomElement> DomFileElement<T> prepare(String path, Class<T> domClass) {
+ protected <T extends DomElement> DomFileElement<T> prepare(@TestDataFile String path, Class<T> domClass) {
XmlFile file = prepareFile(path);
DomFileElement<T> fileElement = DomManager.getDomManager(getProject()).getFileElement(file, domClass);
diff --git a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java
index 92afd1c..085960f 100644
--- a/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java
+++ b/xml/dom-tests/tests/com/intellij/util/xml/stubs/DomStubUsingTest.java
@@ -114,12 +114,7 @@
public void testFileLoading() throws Exception {
XmlFile file = prepareFile("foo.xml");
- ((PsiManagerImpl)getPsiManager()).setAssertOnFileLoadingFilter(VirtualFileFilter.ALL);
- try {
- DomManager.getDomManager(getProject()).getFileElement(file, Foo.class);
- }
- finally {
- ((PsiManagerImpl)getPsiManager()).setAssertOnFileLoadingFilter(VirtualFileFilter.NONE);
- }
+ ((PsiManagerImpl)getPsiManager()).setAssertOnFileLoadingFilter(VirtualFileFilter.ALL, myTestRootDisposable);
+ DomManager.getDomManager(getProject()).getFileElement(file, Foo.class);
}
}
diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form
index dca1e25..bccba83 100644
--- a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form
+++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsForm.form
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.application.options.editor.WebEditorOptionsProvider">
- <grid id="27dc6" binding="myWholePanel" layout-manager="GridLayoutManager" row-count="2" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="27dc6" binding="myWholePanel" 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="451" height="400"/>
+ <xy x="20" y="20" width="451" height="419"/>
</constraints>
<properties/>
<border type="none"/>
<children>
- <grid id="247ce" layout-manager="GridLayoutManager" row-count="6" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <grid id="247ce" layout-manager="GridLayoutManager" row-count="5" 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="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="8" fill="2" indent="0" use-parent-layout="false"/>
@@ -52,14 +52,6 @@
<text value="Automatically insert required subtags"/>
</properties>
</component>
- <component id="49db6" class="com.intellij.ui.components.JBCheckBox" binding="mySelectWholeSelectorOnDoubleClick">
- <constraints>
- <grid row="5" 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="Select whole CSS selector suffix on double click"/>
- </properties>
- </component>
<component id="8169b" class="com.intellij.ui.components.JBCheckBox" binding="myAddQuotasForAttributeValue">
<constraints>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
@@ -72,9 +64,30 @@
</grid>
<vspacer id="e0bcf">
<constraints>
- <grid row="1" 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="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>
+ <grid id="6320d" 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="8" fill="2" 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="CSS" noi18n="true"/>
+ <children>
+ <component id="c4d28" class="com.intellij.ui.components.JBCheckBox" binding="mySelectWholeCssIdentifierOnDoubleClick">
+ <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>
+ <text value="Select whole CSS identifiers on double click"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
</children>
</grid>
</form>
diff --git a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java
index 292e3e1..077d450 100644
--- a/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.java
+++ b/xml/impl/src/com/intellij/application/options/editor/WebEditorOptionsProvider.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.
@@ -31,7 +31,7 @@
private JCheckBox myAutomaticallyInsertRequiredAttributesCheckBox;
private JCheckBox myAutomaticallyInsertRequiredSubTagsCheckBox;
private JCheckBox myAutomaticallyStartAttributeAfterCheckBox;
- private JBCheckBox mySelectWholeSelectorOnDoubleClick;
+ private JBCheckBox mySelectWholeCssIdentifierOnDoubleClick;
private JBCheckBox myAddQuotasForAttributeValue;
@@ -52,7 +52,7 @@
return xmlEditorOptions.isAutomaticallyInsertClosingTag() != myAutomaticallyInsertClosingTagCheckBox.isSelected() ||
xmlEditorOptions.isAutomaticallyInsertRequiredAttributes() != myAutomaticallyInsertRequiredAttributesCheckBox.isSelected() ||
xmlEditorOptions.isAutomaticallyStartAttribute() != myAutomaticallyStartAttributeAfterCheckBox.isSelected() ||
- xmlEditorOptions.isSelectWholeCssSelectorSuffixOnDoubleClick() != mySelectWholeSelectorOnDoubleClick.isSelected() ||
+ xmlEditorOptions.isSelectWholeCssIdentifierOnDoubleClick() != mySelectWholeCssIdentifierOnDoubleClick.isSelected() ||
xmlEditorOptions.isAutomaticallyInsertRequiredSubTags() != myAutomaticallyInsertRequiredSubTagsCheckBox.isSelected() ||
xmlEditorOptions.isInsertQuotesForAttributeValue() != myAddQuotasForAttributeValue.isSelected();
}
@@ -63,7 +63,7 @@
xmlEditorOptions.setAutomaticallyInsertRequiredAttributes(myAutomaticallyInsertRequiredAttributesCheckBox.isSelected());
xmlEditorOptions.setAutomaticallyInsertRequiredSubTags(myAutomaticallyInsertRequiredSubTagsCheckBox.isSelected());
xmlEditorOptions.setAutomaticallyStartAttribute(myAutomaticallyStartAttributeAfterCheckBox.isSelected());
- xmlEditorOptions.setSelectWholeCssSelectorSuffixOnDoubleClick(mySelectWholeSelectorOnDoubleClick.isSelected());
+ xmlEditorOptions.setSelectWholeCssIdentifierOnDoubleClick(mySelectWholeCssIdentifierOnDoubleClick.isSelected());
xmlEditorOptions.setInsertQuotesForAttributeValue(myAddQuotasForAttributeValue.isSelected());
}
@@ -73,7 +73,7 @@
myAutomaticallyInsertRequiredAttributesCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertRequiredAttributes());
myAutomaticallyInsertRequiredSubTagsCheckBox.setSelected(xmlEditorOptions.isAutomaticallyInsertRequiredSubTags());
myAutomaticallyStartAttributeAfterCheckBox.setSelected(xmlEditorOptions.isAutomaticallyStartAttribute());
- mySelectWholeSelectorOnDoubleClick.setSelected(xmlEditorOptions.isSelectWholeCssSelectorSuffixOnDoubleClick());
+ mySelectWholeCssIdentifierOnDoubleClick.setSelected(xmlEditorOptions.isSelectWholeCssIdentifierOnDoubleClick());
myAddQuotasForAttributeValue.setSelected(xmlEditorOptions.isInsertQuotesForAttributeValue());
}
diff --git a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java
index dbf7393..6823d69 100644
--- a/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java
+++ b/xml/impl/src/com/intellij/codeInsight/completion/HtmlCompletionData.java
@@ -25,7 +25,11 @@
import com.intellij.psi.filters.getters.XmlAttributeValueGetter;
import com.intellij.psi.filters.position.XmlTokenTypeFilter;
import com.intellij.psi.util.PsiTreeUtil;
-import com.intellij.psi.xml.*;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.psi.xml.XmlToken;
+import com.intellij.psi.xml.XmlTokenType;
+import com.intellij.xml.util.HtmlUtil;
import org.jetbrains.annotations.NonNls;
/**
@@ -36,7 +40,6 @@
private boolean myCaseInsensitive;
private static final @NonNls String JAVASCRIPT_LANGUAGE_ID = "JavaScript";
private static final @NonNls String STYLE_TAG = "style";
- private static final @NonNls String SCRIPT_TAG = "script";
public HtmlCompletionData() {
this(true);
@@ -46,6 +49,7 @@
myCaseInsensitive = _caseInsensitive;
}
+ @Override
protected ElementFilter createXmlEntityCompletionFilter() {
if (isCaseInsensitive()) {
return new AndFilter(
@@ -77,12 +81,15 @@
myCaseInsensitive = caseInsensitive;
}
+ @Override
protected XmlAttributeValueGetter getAttributeValueGetter() {
return new HtmlAttributeValueGetter(!isCaseInsensitive());
}
+ @Override
protected ElementFilter createTagCompletionFilter() {
return new ElementFilter() {
+ @Override
public boolean isAcceptable(Object element, PsiElement context) {
String name = ((XmlTag)context).getName();
@@ -92,7 +99,7 @@
}
if (equalNames(name, STYLE_TAG) ||
- equalNames(name,SCRIPT_TAG)) {
+ equalNames(name, HtmlUtil.SCRIPT_TAG_NAME)) {
return false;
}
@@ -100,33 +107,40 @@
return true;
}
+ @Override
public boolean isClassAcceptable(Class hintClass) {
return true;
}
};
}
+ @Override
protected ElementFilter createAttributeCompletionFilter() {
return new ElementFilter() {
+ @Override
public boolean isAcceptable(Object element, PsiElement context) {
if (isStyleAttributeContext(context)) return false;
return true;
}
+ @Override
public boolean isClassAcceptable(Class hintClass) {
return true;
}
};
}
+ @Override
protected ElementFilter createAttributeValueCompletionFilter() {
return new ElementFilter() {
+ @Override
public boolean isAcceptable(Object element, PsiElement context) {
if (isStyleAttributeContext(context)) return false;
if ( isScriptContext((PsiElement)element) ) return false;
return true;
}
+ @Override
public boolean isClassAcceptable(Class hintClass) {
return true;
}
@@ -151,11 +165,13 @@
return false;
}
+ @Override
public void registerVariant(CompletionVariant variant) {
super.registerVariant(variant);
if (isCaseInsensitive()) variant.setCaseInsensitive(true);
}
+ @Override
public String findPrefix(PsiElement insertedElement, int offset) {
String prefix = super.findPrefix(insertedElement, offset);
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java
index 2f61dd4..88d639a 100644
--- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/analysis/CreateNSDeclarationIntentionFix.java
@@ -206,9 +206,11 @@
@Override
public boolean showHint(@NotNull final Editor editor) {
- if (myToken == null) return false;
- XmlToken token = (XmlToken)myToken.retrieve();
- if (token == null) return false;
+ XmlToken token = null;
+ if (myToken != null) {
+ token = (XmlToken)myToken.retrieve();
+ if (token == null) return false;
+ }
if (!XmlSettings.getInstance().SHOW_XML_ADD_IMPORT_HINTS || myNamespacePrefix.isEmpty()) {
return false;
}
@@ -219,7 +221,7 @@
final String message = ShowAutoImportPass.getMessage(namespaces.size() > 1, namespaces.iterator().next());
final String title = getTitle();
final ImportNSAction action = new ImportNSAction(namespaces, getFile(), element, editor, title);
- if (element instanceof XmlTag) {
+ if (element instanceof XmlTag && token != null) {
if (VisibleHighlightingPassFactory.calculateVisibleRange(editor).contains(token.getTextRange())) {
HintManager.getInstance().showQuestionHint(editor, message,
token.getTextOffset(),
diff --git a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.java b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.java
index 5ab2f8d..707846c 100644
--- a/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.java
+++ b/xml/impl/src/com/intellij/codeInsight/daemon/impl/quickfix/BaseExtResourceAction.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,9 +18,7 @@
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.PsiReference;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.DependentNSReference;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.URLReference;
import com.intellij.psi.xml.XmlFile;
@@ -75,6 +73,12 @@
@Nullable
public static String findUri(PsiFile file, int offset) {
+ PsiElement element = file.findElementAt(offset);
+ if (element == null ||
+ element instanceof PsiWhiteSpace ) {
+ return null;
+ }
+
PsiReference currentRef = file.getViewProvider().findReferenceAt(offset, file.getLanguage());
if (currentRef == null) currentRef = file.getViewProvider().findReferenceAt(offset);
if (currentRef instanceof URLReference ||
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
index 2259d26..e724f7b 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/HtmlSelectioner.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.
@@ -26,15 +26,12 @@
import com.intellij.application.options.editor.WebEditorOptions;
import com.intellij.codeInsight.editorActions.wordSelection.AbstractWordSelectioner;
-import com.intellij.codeInsight.highlighting.BraceMatchingUtil;
import com.intellij.ide.highlighter.HighlighterFactory;
+import com.intellij.lang.ASTNode;
import com.intellij.lang.Language;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.highlighter.EditorHighlighter;
-import com.intellij.openapi.editor.highlighter.HighlighterIterator;
-import com.intellij.openapi.fileTypes.FileType;
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;
@@ -87,7 +84,6 @@
}
PsiFile psiFile = e.getContainingFile();
- FileType fileType = psiFile.getVirtualFile().getFileType();
addAttributeSelection(result, editor, editorText, e);
final FileViewProvider fileViewProvider = psiFile.getViewProvider();
@@ -99,53 +95,34 @@
EditorHighlighter highlighter = HighlighterFactory.createHighlighter(e.getProject(), psiFile.getVirtualFile());
highlighter.setText(editorText);
- addTagSelection(editorText, cursorOffset, fileType, highlighter, result);
+ addTagSelection2(e, result);
return result;
}
- private static void addTagSelection(CharSequence editorText, int cursorOffset, FileType fileType,
- @NotNull EditorHighlighter highlighter, @NotNull List<TextRange> result) {
- int start = cursorOffset;
-
- while (true) {
- if (start < 0) return;
- HighlighterIterator i = highlighter.createIterator(start);
- if (i.atEnd()) return;
-
- while (true) {
- if (i.getTokenType() == XmlTokenType.XML_START_TAG_START) break;
- i.retreat();
- if (i.atEnd()) return;
+ private static void addTagSelection2(PsiElement e, List<TextRange> result) {
+ XmlTag tag = PsiTreeUtil.getParentOfType(e, XmlTag.class, true);
+ while (tag != null) {
+ result.add(tag.getTextRange());
+ 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()));
}
-
- start = i.getStart();
- final boolean matched = BraceMatchingUtil.matchBrace(editorText, fileType, i, true);
-
- if (matched) {
- final int tagEnd = i.getEnd();
- result.add(new TextRange(start, tagEnd));
-
- HighlighterIterator j = highlighter.createIterator(start);
- while (!j.atEnd() && j.getTokenType() != XmlTokenType.XML_TAG_END) j.advance();
- while (!i.atEnd() && i.getTokenType() != XmlTokenType.XML_END_TAG_START) i.retreat();
-
- if (!i.atEnd() && !j.atEnd()) {
- result.add(new UnfairTextRange(j.getEnd(), i.getStart()));
- }
- if (!j.atEnd()) {
- result.add(new TextRange(start, j.getEnd()));
- }
- if (!i.atEnd()) {
- result.add(new TextRange(i.getStart(), tagEnd));
- }
+ if (tagStartEnd != null) {
+ result.add(new TextRange(tag.getTextRange().getStartOffset(),
+ tagStartEnd.getTextRange().getEndOffset()));
}
-
- start--;
+ if (tagEndStart != null) {
+ result.add(new TextRange(tagEndStart.getTextRange().getStartOffset(),
+ tag.getTextRange().getEndOffset()));
+ }
+ tag = PsiTreeUtil.getParentOfType(tag, XmlTag.class, true);
}
}
- private static void addAttributeSelection(@NotNull List<TextRange> result, @NotNull Editor editor,
+ private static void addAttributeSelection(@NotNull List<TextRange> result, @NotNull Editor editor,
@NotNull CharSequence editorText, @Nullable PsiElement e) {
final XmlAttribute attribute = PsiTreeUtil.getParentOfType(e, XmlAttribute.class);
@@ -169,7 +146,7 @@
@Override
public int getMinimalTextRangeLength(@NotNull PsiElement element, @NotNull CharSequence text, int cursorOffset) {
- if (WebEditorOptions.getInstance().isSelectWholeCssSelectorSuffixOnDoubleClick()) {
+ if (WebEditorOptions.getInstance().isSelectWholeCssIdentifierOnDoubleClick()) {
final XmlAttribute attribute = PsiTreeUtil.getParentOfType(element, XmlAttribute.class);
final XmlAttributeValue attributeValue = PsiTreeUtil.getParentOfType(element, XmlAttributeValue.class);
if (attribute != null && attributeValue != null) {
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
index 821694d..35e7727 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/XmlSlashTypedHandler.java
@@ -23,10 +23,7 @@
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.FileViewProvider;
-import com.intellij.psi.PsiDocumentManager;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
+import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.templateLanguages.OuterLanguageElement;
import com.intellij.psi.tree.IElementType;
@@ -86,6 +83,14 @@
if ("</".equals(prevLeafText) && prevLeaf.getElementType() == XML_END_TAG_START) {
XmlTag tag = PsiTreeUtil.getParentOfType(element, XmlTag.class);
if (tag != null && StringUtil.isNotEmpty(tag.getName()) && TreeUtil.findSibling(prevLeaf, XmlTokenType.XML_NAME) == null) {
+ // check for template language like JSP
+ if (provider instanceof MultiplePsiFilesPerDocumentFileViewProvider) {
+ PsiElement element1 = SingleRootFileViewProvider.findElementAt(file, offset - 1);
+ XmlTag tag1 = PsiTreeUtil.getParentOfType(element1, XmlTag.class);
+ if (tag1 != null && tag1 != tag && tag1.getTextOffset() > tag.getTextOffset() && element1.getText().startsWith("</")) {
+ tag = tag1;
+ }
+ }
EditorModificationUtil.insertStringAtCaret(editor, tag.getName() + ">");
return Result.STOP;
}
diff --git a/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java b/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java
index 770ac7a..da385b0 100644
--- a/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java
+++ b/xml/impl/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMover.java
@@ -24,7 +24,6 @@
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.PsiWhiteSpace;
-import com.intellij.psi.html.HtmlTag;
import com.intellij.psi.impl.source.xml.TagNameVariantCollector;
import com.intellij.psi.impl.source.xml.XmlDocumentImpl;
import com.intellij.psi.util.PsiTreeUtil;
@@ -34,6 +33,7 @@
import com.intellij.psi.xml.XmlText;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlNSDescriptor;
+import com.intellij.xml.util.HtmlUtil;
import org.jetbrains.annotations.NotNull;
class XmlMover extends LineMover {
@@ -62,11 +62,7 @@
if (checkInjections(movedEndElement, movedStartElement)) return false;
XmlTag nearestTag = PsiTreeUtil.getParentOfType(movedStartElement, XmlTag.class);
- if (nearestTag != null &&
- ( "script".equals(nearestTag.getLocalName()) ||
- (nearestTag instanceof HtmlTag && "script".equalsIgnoreCase(nearestTag.getLocalName()))
- )
- ) {
+ if (nearestTag != null && HtmlUtil.isScriptTag(nearestTag)) {
return false;
}
diff --git a/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java b/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java
index 798a3d9..087943d 100644
--- a/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java
+++ b/xml/impl/src/com/intellij/codeInsight/hint/api/impls/XmlParameterInfoHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -67,7 +67,7 @@
return true;
}
- public XmlTag findElementForParameterInfo(final CreateParameterInfoContext context) {
+ public XmlTag findElementForParameterInfo(@NotNull final CreateParameterInfoContext context) {
final XmlTag tag = findXmlTag(context.getFile(), context.getOffset());
final XmlElementDescriptor descriptor = tag != null ? tag.getDescriptor() : null;
@@ -80,11 +80,11 @@
return tag;
}
- public void showParameterInfo(final @NotNull XmlTag element, final CreateParameterInfoContext context) {
+ public void showParameterInfo(final @NotNull XmlTag element, @NotNull final CreateParameterInfoContext context) {
context.showHint(element, element.getTextRange().getStartOffset() + 1, this);
}
- public XmlTag findElementForUpdatingParameterInfo(final UpdateParameterInfoContext context) {
+ public XmlTag findElementForUpdatingParameterInfo(@NotNull final UpdateParameterInfoContext context) {
final XmlTag tag = findXmlTag(context.getFile(), context.getOffset());
if (tag != null) {
final PsiElement currentXmlTag = context.getParameterOwner();
@@ -94,9 +94,9 @@
return null;
}
- public void updateParameterInfo(@NotNull final XmlTag o, final UpdateParameterInfoContext context) {
- if (context.getParameterOwner() == null || o.equals(context.getParameterOwner())) {
- context.setParameterOwner( o );
+ public void updateParameterInfo(@NotNull final XmlTag parameterOwner, @NotNull final UpdateParameterInfoContext context) {
+ if (context.getParameterOwner() == null || parameterOwner.equals(context.getParameterOwner())) {
+ context.setParameterOwner(parameterOwner);
} else {
context.removeHint();
}
@@ -145,7 +145,7 @@
return null;
}
- public void updateUI(XmlElementDescriptor o, final ParameterInfoUIContext context) {
+ public void updateUI(XmlElementDescriptor o, @NotNull final ParameterInfoUIContext context) {
updateElementDescriptor(
o,
context,
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java
index f6f5bda..f4284e4 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/ZenCodingTemplate.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,10 +28,12 @@
import com.intellij.codeInsight.template.emmet.tokens.ZenCodingToken;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
+import com.intellij.diagnostic.AttachmentFactory;
import com.intellij.ide.IdeEventQueue;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorModificationUtil;
import com.intellij.openapi.editor.ScrollType;
@@ -72,6 +74,7 @@
public static final char MARKER = '\0';
private static final String EMMET_RECENT_WRAP_ABBREVIATIONS_KEY = "emmet.recent.wrap.abbreviations";
private static final String EMMET_LAST_WRAP_ABBREVIATIONS_KEY = "emmet.last.wrap.abbreviations";
+ private static final Logger LOG = Logger.getInstance(ZenCodingTemplate.class);
@Nullable
public static ZenCodingGenerator findApplicableDefaultGenerator(@NotNull PsiElement context, boolean wrapping) {
@@ -116,7 +119,7 @@
return parse(key, callback, generator, null) != null;
}
- public void expand(String key, @NotNull CustomTemplateCallback callback) {
+ public void expand(@NotNull String key, @NotNull CustomTemplateCallback callback) {
ZenCodingGenerator defaultGenerator = findApplicableDefaultGenerator(callback.getContext(), false);
assert defaultGenerator != null;
expand(key, callback, null, defaultGenerator, Collections.<ZenCodingFilter>emptyList(), true);
@@ -291,7 +294,7 @@
public void wrap(@NotNull final String selection, @NotNull final CustomTemplateCallback callback) {
final TextFieldWithStoredHistory field = new TextFieldWithStoredHistory(EMMET_RECENT_WRAP_ABBREVIATIONS_KEY);
final Dimension fieldPreferredSize = field.getPreferredSize();
- field.setPreferredSize(new Dimension(Math.max(160, fieldPreferredSize.width), fieldPreferredSize.height));
+ field.setPreferredSize(new Dimension(Math.max(220, fieldPreferredSize.width), fieldPreferredSize.height));
field.setHistorySize(10);
final JBPopupFactory popupFactory = JBPopupFactory.getInstance();
final BalloonImpl balloon = (BalloonImpl)popupFactory.createDialogBalloonBuilder(field, XmlBundle.message("emmet.title"))
@@ -375,7 +378,11 @@
static boolean checkTemplateKey(String inputString, CustomTemplateCallback callback) {
ZenCodingGenerator generator = findApplicableDefaultGenerator(callback.getContext(), true);
- assert generator != null;
+ if (generator == null) {
+ LOG.error("Emmet is disabled for context for file " + callback.getFileType().getName(),
+ AttachmentFactory.createAttachment(callback.getEditor().getDocument()));
+ return false;
+ }
return checkTemplateKey(inputString, callback, generator);
}
@@ -383,7 +390,6 @@
if (file == null) {
return false;
}
- PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
PsiElement element = CustomTemplateCallback.getContext(file, offset);
final ZenCodingGenerator applicableGenerator = findApplicableDefaultGenerator(element, wrapping);
return applicableGenerator != null && applicableGenerator.isEnabled();
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetAbbreviationCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetAbbreviationCompletionProvider.java
index 9968f63..0dd4769 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetAbbreviationCompletionProvider.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetAbbreviationCompletionProvider.java
@@ -18,12 +18,11 @@
import com.intellij.codeInsight.completion.CompletionParameters;
import com.intellij.codeInsight.completion.CompletionProvider;
import com.intellij.codeInsight.completion.CompletionResultSet;
-import com.intellij.codeInsight.template.CustomTemplateCallback;
-import com.intellij.codeInsight.template.Template;
-import com.intellij.codeInsight.template.TemplateEditingListener;
+import com.intellij.codeInsight.template.*;
import com.intellij.codeInsight.template.emmet.ZenCodingTemplate;
import com.intellij.codeInsight.template.emmet.filters.SingleLineEmmetFilter;
import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator;
+import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
import com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor;
import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
import com.intellij.codeInsight.template.impl.TemplateImpl;
@@ -56,6 +55,11 @@
return;
}
+ ZenCodingTemplate zenCodingTemplate = CustomLiveTemplate.EP_NAME.findExtension(ZenCodingTemplate.class);
+ if (zenCodingTemplate == null) {
+ return;
+ }
+
final PsiFile file = parameters.getPosition().getContainingFile();
final Editor editor = parameters.getEditor();
@@ -89,13 +93,13 @@
final TemplateImpl template = generatedTemplate.get();
template.setKey(templatePrefix);
template.setDescription(template.getTemplateText());
- result.addElement(createLookupElement(template));
+ result.addElement(createLookupElement(zenCodingTemplate, template));
result.restartCompletionOnPrefixChange(StandardPatterns.string().startsWith(templatePrefix));
}
}
- protected LiveTemplateLookupElement createLookupElement(TemplateImpl template) {
- return new LiveTemplateLookupElement(template, null, true, true);
+ protected LiveTemplateLookupElement createLookupElement(@NotNull CustomLiveTemplateBase customLiveTemplate, @NotNull TemplateImpl template) {
+ return new CustomLiveTemplateLookupElement(customLiveTemplate, template.getKey(), template.getKey(), template.getDescription(), true, true);
}
protected abstract ZenCodingGenerator getGenerator();
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java
new file mode 100644
index 0000000..a127ab2
--- /dev/null
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/EmmetLookupActionProvider.java
@@ -0,0 +1,70 @@
+/*
+ * 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.codeInsight.template.emmet.completion;
+
+import com.intellij.application.options.emmet.EmmetCompositeConfigurable;
+import com.intellij.application.options.emmet.EmmetOptions;
+import com.intellij.codeInsight.lookup.Lookup;
+import com.intellij.codeInsight.lookup.LookupActionProvider;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementAction;
+import com.intellij.codeInsight.template.emmet.ZenCodingTemplate;
+import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.project.Project;
+import com.intellij.util.Consumer;
+import com.intellij.util.PlatformIcons;
+
+public class EmmetLookupActionProvider implements LookupActionProvider {
+ @Override
+ public void fillActions(LookupElement element, final Lookup lookup, Consumer<LookupElementAction> consumer) {
+ if (element instanceof CustomLiveTemplateLookupElement &&
+ ((CustomLiveTemplateLookupElement)element).getCustomLiveTemplate() instanceof ZenCodingTemplate) {
+ consumer.consume(new LookupElementAction(PlatformIcons.EDIT, "Edit Emmet settings") {
+ @Override
+ public Result performLookupAction() {
+ final Project project = lookup.getEditor().getProject();
+ assert project != null;
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ if (project.isDisposed()) return;
+
+ final EmmetCompositeConfigurable configurable = new EmmetCompositeConfigurable();
+ ShowSettingsUtil.getInstance().editConfigurable(project, configurable);
+ }
+ });
+ return Result.HIDE_LOOKUP;
+ }
+ });
+
+ consumer.consume(new LookupElementAction(AllIcons.Actions.Delete, String.format("Disable Emmet")) {
+ @Override
+ public Result performLookupAction() {
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ EmmetOptions.getInstance().setEmmetEnabled(false);
+ }
+ });
+ return Result.HIDE_LOOKUP;
+ }
+ });
+ }
+ }
+}
diff --git a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/XmlEmmetAbbreviationCompletionProvider.java b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/XmlEmmetAbbreviationCompletionProvider.java
index c2a55be..b251ffd 100644
--- a/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/XmlEmmetAbbreviationCompletionProvider.java
+++ b/xml/impl/src/com/intellij/codeInsight/template/emmet/completion/XmlEmmetAbbreviationCompletionProvider.java
@@ -17,15 +17,14 @@
import com.intellij.application.options.emmet.EmmetOptions;
import com.intellij.codeInsight.completion.CompletionParameters;
+import com.intellij.codeInsight.template.CustomLiveTemplateBase;
import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGeneratorImpl;
import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator;
+import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
import com.intellij.codeInsight.template.impl.TemplateImpl;
+import org.jetbrains.annotations.NotNull;
-/**
- * User: zolotov
- * Date: 8/9/13
- */
public class XmlEmmetAbbreviationCompletionProvider extends EmmetAbbreviationCompletionProvider {
@Override
protected boolean isAvailable(CompletionParameters parameters) {
@@ -34,10 +33,8 @@
}
@Override
- protected LiveTemplateLookupElement createLookupElement(final TemplateImpl template) {
- final String description = template.getDescription();
- template.setDescription(null);
- return new LiveTemplateLookupElement(template, description, false, true);
+ protected LiveTemplateLookupElement createLookupElement(@NotNull CustomLiveTemplateBase customLiveTemplate, @NotNull final TemplateImpl template) {
+ return new CustomLiveTemplateLookupElement(customLiveTemplate, template.getKey(), template.getDescription(), "", false, true);
}
@Override
diff --git a/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java b/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java
index a75e395..92a34a9 100644
--- a/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java
+++ b/xml/impl/src/com/intellij/html/impl/Html5CustomAttributeDescriptorsProvider.java
@@ -16,6 +16,8 @@
package com.intellij.html.impl;
import com.intellij.html.index.Html5CustomAttributesIndex;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Processor;
@@ -42,9 +44,19 @@
currentAttrs.add(attribute.getName());
}
final List<XmlAttributeDescriptor> result = new ArrayList<XmlAttributeDescriptor>();
+ final GlobalSearchScope scope = GlobalSearchScope.allScope(tag.getProject());
FileBasedIndex.getInstance().processAllKeys(Html5CustomAttributesIndex.INDEX_ID, new Processor<String>() {
@Override
public boolean process(String s) {
+ final boolean canProcessKey = !FileBasedIndex.getInstance().processValues(Html5CustomAttributesIndex.INDEX_ID, s,
+ null, new FileBasedIndex.ValueProcessor<Void>() {
+ @Override
+ public boolean process(VirtualFile file, Void value) {
+ return false;
+ }
+ }, scope);
+ if (!canProcessKey) return true;
+
boolean add = true;
for (String attr : currentAttrs) {
if (attr.startsWith(s)) {
@@ -56,7 +68,7 @@
}
return true;
}
- }, tag.getProject());
+ }, scope, null);
return result.toArray(new XmlAttributeDescriptor[result.size()]);
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
new file mode 100644
index 0000000..3e21ac0
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserLauncherImpl.java
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers;
+
+import com.intellij.CommonBundle;
+import com.intellij.Patches;
+import com.intellij.concurrency.JobScheduler;
+import com.intellij.execution.ExecutionException;
+import com.intellij.execution.configurations.GeneralCommandLine;
+import com.intellij.execution.util.ExecUtil;
+import com.intellij.ide.BrowserUtil;
+import com.intellij.ide.GeneralSettings;
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.progress.ProgressIndicator;
+import com.intellij.openapi.progress.Task;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.DialogWrapper;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.SystemInfo;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.*;
+import com.intellij.ui.AppUIUtil;
+import com.intellij.ui.GuiUtils;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.PathUtil;
+import com.intellij.util.io.ZipUtil;
+import com.intellij.util.ui.OptionsDialog;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.*;
+import java.io.File;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.*;
+import java.util.List;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+final class BrowserLauncherImpl extends BrowserLauncher {
+ private static final Logger LOG = Logger.getInstance(BrowserLauncherImpl.class);
+
+ private static boolean isDesktopActionSupported(Desktop.Action action) {
+ return !Patches.SUN_BUG_ID_6457572 && !Patches.SUN_BUG_ID_6486393 &&
+ Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(action);
+ }
+
+ public static boolean canStartDefaultBrowser() {
+ return isDesktopActionSupported(Desktop.Action.BROWSE) ||
+ SystemInfo.isMac || SystemInfo.isWindows ||
+ SystemInfo.isUnix && SystemInfo.hasXdgOpen();
+ }
+
+ private static GeneralSettings getGeneralSettingsInstance() {
+ if (ApplicationManager.getApplication() != null) {
+ GeneralSettings settings = GeneralSettings.getInstance();
+ if (settings != null) {
+ return settings;
+ }
+ }
+
+ return new GeneralSettings();
+ }
+
+ @Nullable
+ private static List<String> getDefaultBrowserCommand() {
+ if (SystemInfo.isWindows) {
+ return Arrays.asList(ExecUtil.getWindowsShellName(), "/c", "start", GeneralCommandLine.inescapableQuote(""));
+ }
+ else if (SystemInfo.isMac) {
+ return Collections.singletonList(ExecUtil.getOpenCommandPath());
+ }
+ else if (SystemInfo.isUnix && SystemInfo.hasXdgOpen()) {
+ return Collections.singletonList("xdg-open");
+ }
+ else {
+ return null;
+ }
+ }
+
+ @Override
+ public void open(@NotNull String url) {
+ openOrBrowse(url, false);
+ }
+
+ @Override
+ public void browse(@NotNull File file) {
+ browse(VfsUtil.toUri(file));
+ }
+
+ @Override
+ public void browse(@NotNull URI uri) {
+ LOG.debug("Launch browser: [" + uri + "]");
+
+ GeneralSettings settings = getGeneralSettingsInstance();
+ if (settings.isUseDefaultBrowser()) {
+ if (isDesktopActionSupported(Desktop.Action.BROWSE)) {
+ try {
+ Desktop.getDesktop().browse(uri);
+ LOG.debug("Browser launched using JDK 1.6 API");
+ return;
+ }
+ catch (Exception e) {
+ LOG.warn("Error while using Desktop API, fallback to CLI", e);
+ }
+ }
+
+ List<String> command = getDefaultBrowserCommand();
+ if (command != null) {
+ doLaunch(uri.toString(), command, null, null, ArrayUtil.EMPTY_STRING_ARRAY);
+ return;
+ }
+ }
+
+ browseUsingPath(uri.toString(), settings.getBrowserPath(), null, null);
+ }
+
+ private void openOrBrowse(@NotNull String url, boolean browse) {
+ url = url.trim();
+
+ if (url.startsWith("jar:")) {
+ String files = extractFiles(url);
+ if (files == null) {
+ return;
+ }
+ url = files;
+ }
+
+ URI uri;
+ if (BrowserUtil.isAbsoluteURL(url)) {
+ uri = VfsUtil.toUri(url);
+ }
+ else {
+ File file = new File(url);
+ if (!browse && isDesktopActionSupported(Desktop.Action.OPEN)) {
+ try {
+ Desktop.getDesktop().open(file);
+ return;
+ }
+ catch (IOException e) {
+ LOG.debug(e);
+ }
+ }
+
+ browse(file);
+ return;
+ }
+
+ if (uri == null) {
+ showError(IdeBundle.message("error.malformed.url", url), null, null, null);
+ }
+ else {
+ browse(uri);
+ }
+ }
+
+ @Nullable
+ private static String extractFiles(String url) {
+ try {
+ int sharpPos = url.indexOf('#');
+ String anchor = "";
+ if (sharpPos != -1) {
+ anchor = url.substring(sharpPos);
+ url = url.substring(0, sharpPos);
+ }
+
+ VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(url);
+ if (file == null || !(file.getFileSystem() instanceof JarFileSystem)) return null;
+
+ JarFileSystem jarFileSystem = (JarFileSystem)file.getFileSystem();
+ VirtualFile jarVirtualFile = jarFileSystem.getVirtualFileForJar(file);
+ if (jarVirtualFile == null) return null;
+
+ String targetFilePath = file.getPath();
+ String targetFileRelativePath = StringUtil.substringAfter(targetFilePath, JarFileSystem.JAR_SEPARATOR);
+ LOG.assertTrue(targetFileRelativePath != null);
+
+ String jarVirtualFileLocationHash = jarVirtualFile.getName() + Integer.toHexString(jarVirtualFile.getUrl().hashCode());
+ final File outputDir = new File(getExtractedFilesDir(), jarVirtualFileLocationHash);
+
+ final String currentTimestamp = String.valueOf(new File(jarVirtualFile.getPath()).lastModified());
+ final File timestampFile = new File(outputDir, ".idea.timestamp");
+
+ String previousTimestamp = null;
+ if (timestampFile.exists()) {
+ previousTimestamp = FileUtilRt.loadFile(timestampFile);
+ }
+
+ if (!currentTimestamp.equals(previousTimestamp)) {
+ final Ref<Boolean> extract = new Ref<Boolean>();
+ Runnable r = new Runnable() {
+ @Override
+ public void run() {
+ final ConfirmExtractDialog dialog = new ConfirmExtractDialog();
+ if (dialog.isToBeShown()) {
+ dialog.show();
+ extract.set(dialog.isOK());
+ }
+ else {
+ dialog.close(DialogWrapper.OK_EXIT_CODE);
+ extract.set(true);
+ }
+ }
+ };
+
+ try {
+ GuiUtils.runOrInvokeAndWait(r);
+ }
+ catch (InvocationTargetException ignored) {
+ extract.set(false);
+ }
+ catch (InterruptedException ignored) {
+ extract.set(false);
+ }
+
+ if (!extract.get()) {
+ return null;
+ }
+
+ @SuppressWarnings("ConstantConditions")
+ final ZipFile zipFile = jarFileSystem.getJarFile(file).getZipFile();
+ if (zipFile == null) {
+ return null;
+ }
+ ZipEntry entry = zipFile.getEntry(targetFileRelativePath);
+ if (entry == null) {
+ return null;
+ }
+ InputStream is = zipFile.getInputStream(entry);
+ try {
+ ZipUtil.extractEntry(entry, is, outputDir);
+ }
+ finally {
+ is.close();
+ }
+
+ ApplicationManager.getApplication().invokeLater(new Runnable() {
+ @Override
+ public void run() {
+ new Task.Backgroundable(null, "Extracting files...", true) {
+ @Override
+ public void run(@NotNull final ProgressIndicator indicator) {
+ final int size = zipFile.size();
+ final int[] counter = new int[]{0};
+
+ class MyFilter implements FilenameFilter {
+ private final Set<File> myImportantDirs = new HashSet<File>(
+ Arrays.asList(outputDir, new File(outputDir, "resources")));
+ private final boolean myImportantOnly;
+
+ private MyFilter(boolean importantOnly) {
+ myImportantOnly = importantOnly;
+ }
+
+ @Override
+ public boolean accept(@NotNull File dir, @NotNull String name) {
+ indicator.checkCanceled();
+ boolean result = myImportantOnly == myImportantDirs.contains(dir);
+ if (result) {
+ indicator.setFraction(((double)counter[0]) / size);
+ counter[0]++;
+ }
+ return result;
+ }
+ }
+
+ try {
+ ZipUtil.extract(zipFile, outputDir, new MyFilter(true));
+ ZipUtil.extract(zipFile, outputDir, new MyFilter(false));
+ FileUtil.writeToFile(timestampFile, currentTimestamp.getBytes());
+ }
+ catch (IOException ignore) {
+ }
+ }
+ }.queue();
+ }
+ });
+ }
+
+ return VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(new File(outputDir, targetFileRelativePath).getPath())) + anchor;
+ }
+ catch (IOException e) {
+ LOG.warn(e);
+ Messages.showErrorDialog("Cannot extract files: " + e.getMessage(), "Error");
+ return null;
+ }
+ }
+
+ private static File getExtractedFilesDir() {
+ return new File(PathManager.getSystemPath(), "ExtractedFiles");
+ }
+
+ public static void clearExtractedFiles() {
+ FileUtil.delete(getExtractedFilesDir());
+ }
+
+ private static class ConfirmExtractDialog extends OptionsDialog {
+ private ConfirmExtractDialog() {
+ super(null);
+ setTitle("Confirmation");
+ init();
+ }
+
+ @Override
+ protected boolean isToBeShown() {
+ return getGeneralSettingsInstance().isConfirmExtractFiles();
+ }
+
+ @Override
+ protected void setToBeShown(boolean value, boolean onOk) {
+ getGeneralSettingsInstance().setConfirmExtractFiles(value);
+ }
+
+ @Override
+ protected boolean shouldSaveOptionsOnCancel() {
+ return true;
+ }
+
+ @Override
+ @NotNull
+ protected Action[] createActions() {
+ setOKButtonText(CommonBundle.getYesButtonText());
+ return new Action[]{getOKAction(), getCancelAction()};
+ }
+
+ @Override
+ protected JComponent createCenterPanel() {
+ JPanel panel = new JPanel(new BorderLayout());
+ String message = "The files are inside an archive, do you want them to be extracted?";
+ JLabel label = new JLabel(message);
+
+ label.setIconTextGap(10);
+ label.setIcon(Messages.getQuestionIcon());
+
+ panel.add(label, BorderLayout.CENTER);
+ panel.add(Box.createVerticalStrut(10), BorderLayout.SOUTH);
+
+ return panel;
+ }
+ }
+
+ @Override
+ public void browse(@NotNull String url, @Nullable WebBrowser browser) {
+ browse(url, browser, null);
+ }
+
+ @Override
+ public void browse(@NotNull String url, @Nullable WebBrowser browser, @Nullable Project project) {
+ if (browser == null) {
+ openOrBrowse(url, true);
+ }
+ else {
+ for (UrlOpener urlOpener : UrlOpener.EP_NAME.getExtensions()) {
+ if (urlOpener.openUrl(browser, url, project)) {
+ return;
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean browseUsingPath(@Nullable String url,
+ @Nullable String browserPath,
+ @Nullable WebBrowser browser,
+ @Nullable Project project,
+ @NotNull String... additionalParameters) {
+ return doLaunch(url, browserPath == null && browser != null ? PathUtil.toSystemDependentName(browser.getPath()) : browserPath, browser, project, additionalParameters);
+ }
+
+ private static boolean doLaunch(@Nullable String url,
+ @Nullable String browserPath,
+ @Nullable WebBrowser browser,
+ @Nullable Project project,
+ @NotNull String[] additionalParameters) {
+ if (StringUtil.isEmptyOrSpaces(browserPath)) {
+ showError(browser == null ? IdeBundle.message("error.please.specify.path.to.web.browser", CommonBundle.settingsActionPath()) : browser
+ .getBrowserNotFoundMessage(), browser, project, IdeBundle.message("title.browser.not.found"));
+ return false;
+ }
+
+ return doLaunch(url, BrowserUtil.getOpenBrowserCommand(browserPath, false), browser, project, additionalParameters);
+ }
+
+ private static boolean doLaunch(@Nullable String url,
+ @NotNull List<String> command,
+ @Nullable final WebBrowser browser,
+ @Nullable final Project project,
+ String[] additionalParameters) {
+ GeneralCommandLine commandLine = new GeneralCommandLine(command);
+ if (url != null) {
+ commandLine.addParameter(url);
+ }
+
+ addArgs(commandLine, browser == null ? null : browser.getSpecificSettings(), additionalParameters);
+
+ try {
+ final Process process = commandLine.createProcess();
+ if (isOpenCommandUsed(commandLine)) {
+ final Future<?> future = ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (process.waitFor() == 1) {
+ showError(ExecUtil.readFirstLine(process.getErrorStream(), null), browser, project, null);
+ }
+ }
+ catch (InterruptedException ignored) {
+ }
+ }
+ });
+ // 30 seconds is enough to start
+ JobScheduler.getScheduler().schedule(new Runnable() {
+ @Override
+ public void run() {
+ future.cancel(true);
+ }
+ }, 30, TimeUnit.MILLISECONDS);
+ }
+ return true;
+ }
+ catch (ExecutionException e) {
+ showError(e.getMessage(), browser, project, null);
+ return false;
+ }
+ }
+
+ public static void showError(@Nullable final String error, @Nullable final WebBrowser browser, @Nullable final Project project, @Nullable final String title) {
+ if (ApplicationManager.getApplication() == null) {
+ LOG.warn(error);
+ // Not started yet. Not able to show message up. (Could happen in License panel under Linux).
+ return;
+ }
+
+ AppUIUtil.invokeOnEdt(new Runnable() {
+ @Override
+ public void run() {
+ if (Messages.showYesNoDialog(project, StringUtil.notNullize(error, "Unknown error"),
+ title == null ? IdeBundle.message("browser.error") : title, Messages.OK_BUTTON,
+ IdeBundle.message("button.fix"), null) == Messages.NO) {
+ final BrowserSettings browserSettings = new BrowserSettings();
+ ShowSettingsUtil.getInstance().editConfigurable(project, browserSettings, browser == null ? null : new Runnable() {
+ @Override
+ public void run() {
+ browserSettings.selectBrowser(browser);
+ }
+ });
+ }
+ }
+ });
+ }
+
+ private static void addArgs(@NotNull GeneralCommandLine command, @Nullable BrowserSpecificSettings settings, @NotNull String[] additional) {
+ List<String> specific = settings == null ? Collections.<String>emptyList() : settings.getAdditionalParameters();
+ if (specific.size() + additional.length > 0) {
+ if (isOpenCommandUsed(command)) {
+ if (BrowserUtil.isOpenCommandSupportArgs()) {
+ command.addParameter("--args");
+ }
+ else {
+ LOG.warn("'open' command doesn't allow to pass command line arguments so they will be ignored: " +
+ StringUtil.join(specific, ", ") + " " + Arrays.toString(additional));
+ return;
+ }
+ }
+
+ command.addParameters(specific);
+ command.addParameters(additional);
+ }
+ }
+
+ private static boolean isOpenCommandUsed(@NotNull GeneralCommandLine command) {
+ return SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.getExePath());
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
index 4ef9c20..3ae67de 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSelector.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,14 +15,15 @@
*/
package com.intellij.ide.browsers;
-import com.intellij.ide.BrowserSettings;
-import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.openapi.options.ShowSettingsUtil;
import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.IconLoader;
import com.intellij.ui.ComboboxWithBrowseButton;
-import com.intellij.util.ArrayUtil;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.ui.MutableCollectionComboBoxModel;
import com.intellij.util.PlatformIcons;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -31,72 +32,105 @@
import java.util.ArrayList;
import java.util.List;
-/**
- * @author nik
- */
public class BrowserSelector {
- private ComboboxWithBrowseButton myBrowserComboWithBrowse;
+ private final ComboboxWithBrowseButton myBrowserComboWithBrowse;
+ private MutableCollectionComboBoxModel<WebBrowser> myModel;
+
+ public BrowserSelector() {
+ this(true);
+ }
public BrowserSelector(final boolean allowDefaultBrowser) {
- myBrowserComboWithBrowse = new ComboboxWithBrowseButton(new ComboBox());
+ this(new Condition<WebBrowser>() {
+ @Override
+ public boolean value(WebBrowser browser) {
+ return allowDefaultBrowser || browser != null;
+ }
+ });
+ }
+
+ public BrowserSelector(@NotNull final Condition<WebBrowser> browserCondition) {
+ myModel = createBrowsersComboModel(browserCondition);
+ myBrowserComboWithBrowse = new ComboboxWithBrowseButton(new ComboBox(myModel));
myBrowserComboWithBrowse.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
- final ShowSettingsUtil util = ShowSettingsUtil.getInstance();
- util.editConfigurable(myBrowserComboWithBrowse, new BrowserSettings());
+ WebBrowserManager browserManager = WebBrowserManager.getInstance();
+ long modificationCount = browserManager.getModificationCount();
+ ShowSettingsUtil.getInstance().editConfigurable(myBrowserComboWithBrowse, new BrowserSettings());
- final BrowsersConfiguration.BrowserFamily selectedItem = getSelectedBrowser();
- initBrowsersComboModel(allowDefaultBrowser);
+ WebBrowser selectedItem = getSelected();
+ if (modificationCount != browserManager.getModificationCount()) {
+ myModel = createBrowsersComboModel(browserCondition);
+ //noinspection unchecked
+ myBrowserComboWithBrowse.getComboBox().setModel(myModel);
+ }
if (selectedItem != null) {
- setSelectedBrowser(selectedItem);
+ setSelected(selectedItem);
}
}
});
- final JComboBox comboBox = myBrowserComboWithBrowse.getComboBox();
- comboBox.setRenderer(new ListCellRendererWrapper<BrowsersConfiguration.BrowserFamily>() {
+ //noinspection unchecked
+ myBrowserComboWithBrowse.getComboBox().setRenderer(new ListCellRendererWrapper<WebBrowser>() {
@Override
public void customize(JList list,
- BrowsersConfiguration.BrowserFamily value,
+ WebBrowser value,
int index,
boolean selected,
boolean hasFocus) {
- final Icon baseIcon = value != null ? value.getIcon() : PlatformIcons.WEB_ICON;
- final Icon icon = myBrowserComboWithBrowse.isEnabled() ? baseIcon : IconLoader.getDisabledIcon(baseIcon);
- setIcon(icon);
+ Icon baseIcon;
+ if (value == null) {
+ WebBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowser();
+ baseIcon = defaultBrowser == null ? PlatformIcons.WEB_ICON : defaultBrowser.getIcon();
+ }
+ else {
+ baseIcon = value.getIcon();
+ }
+ setIcon(myBrowserComboWithBrowse.isEnabled() ? baseIcon : IconLoader.getDisabledIcon(baseIcon));
setText(value != null ? value.getName() : "Default");
}
});
-
- initBrowsersComboModel(allowDefaultBrowser);
}
public JComponent getMainComponent() {
return myBrowserComboWithBrowse;
}
- private void initBrowsersComboModel(boolean allowDefaultBrowser) {
- final List<BrowsersConfiguration.BrowserFamily> activeBrowsers = new ArrayList<BrowsersConfiguration.BrowserFamily>();
- if (allowDefaultBrowser) {
- activeBrowsers.add(null);
+ private static MutableCollectionComboBoxModel<WebBrowser> createBrowsersComboModel(@NotNull Condition<WebBrowser> browserCondition) {
+ List<WebBrowser> list = new ArrayList<WebBrowser>();
+ if (browserCondition.value(null)) {
+ list.add(null);
}
- activeBrowsers.addAll(BrowsersConfiguration.getInstance().getActiveBrowsers());
-
- myBrowserComboWithBrowse.getComboBox().setModel(new DefaultComboBoxModel(ArrayUtil.toObjectArray(activeBrowsers)));
+ list.addAll(WebBrowserManager.getInstance().getBrowsers(browserCondition));
+ return new MutableCollectionComboBoxModel<WebBrowser>(list);
}
@Nullable
- public BrowsersConfiguration.BrowserFamily getSelectedBrowser() {
- return (BrowsersConfiguration.BrowserFamily)myBrowserComboWithBrowse.getComboBox().getSelectedItem();
+ public WebBrowser getSelected() {
+ return myModel.getSelected();
}
@Nullable
- public String getSelectedBrowserFamilyName() {
- final BrowsersConfiguration.BrowserFamily browser = getSelectedBrowser();
- return browser != null ? browser.getName() : null;
+ public String getSelectedBrowserId() {
+ WebBrowser browser = getSelected();
+ return browser != null ? browser.getId().toString() : null;
}
- public void setSelectedBrowser(@Nullable BrowsersConfiguration.BrowserFamily selectedItem) {
+ public void setSelected(@Nullable WebBrowser selectedItem) {
myBrowserComboWithBrowse.getComboBox().setSelectedItem(selectedItem);
}
+
+ public boolean addAndSelect(@NotNull WebBrowser browser) {
+ if (myModel.contains(browser)) {
+ return false;
+ }
+
+ myModel.addItem(browser);
+ return true;
+ }
+
+ public int getSize() {
+ return myModel.getSize();
+ }
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettings.java
new file mode 100644
index 0000000..2fb7738
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettings.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.options.Configurable;
+import com.intellij.openapi.options.ConfigurationException;
+import com.intellij.openapi.options.SearchableConfigurable;
+import org.jetbrains.annotations.Nls;
+import org.jetbrains.annotations.NotNull;
+
+import javax.swing.*;
+
+public class BrowserSettings implements SearchableConfigurable, Configurable.NoScroll {
+ private BrowserSettingsPanel myPanel;
+
+ @Override
+ @NotNull
+ public String getId() {
+ return getHelpTopic();
+ }
+
+ @Override
+ public Runnable enableSearch(final String option) {
+ return null;
+ }
+
+ @Override
+ @Nls
+ public String getDisplayName() {
+ return IdeBundle.message("browsers.settings");
+ }
+
+ @Override
+ @NotNull
+ public String getHelpTopic() {
+ return "reference.settings.ide.settings.web.browsers";
+ }
+
+ @Override
+ public JComponent createComponent() {
+ if (myPanel == null) {
+ myPanel = new BrowserSettingsPanel();
+ }
+ return myPanel.getComponent();
+ }
+
+ @Override
+ public boolean isModified() {
+ return myPanel != null && myPanel.isModified();
+ }
+
+ @Override
+ public void apply() throws ConfigurationException {
+ if (myPanel != null) {
+ myPanel.apply();
+ }
+ }
+
+ @Override
+ public void reset() {
+ if (myPanel != null) {
+ myPanel.reset();
+ }
+ }
+
+ @Override
+ public void disposeUIResources() {
+ myPanel = null;
+ }
+
+ public void selectBrowser(@NotNull WebBrowser browser) {
+ createComponent();
+ myPanel.selectBrowser(browser);
+ }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
new file mode 100644
index 0000000..52d0743
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.form
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.browsers.BrowserSettingsPanel">
+ <grid id="27dc6" binding="root" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
+ <margin top="0" left="0" bottom="0" right="0"/>
+ <constraints>
+ <xy x="20" y="20" width="595" height="400"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <grid id="df7ca" binding="defaultBrowserPanel" layout-manager="GridLayoutManager" row-count="1" 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="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ <border type="none"/>
+ <children>
+ <component id="8484a" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="alternativeBrowserPathField">
+ <constraints>
+ <grid row="0" column="2" 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="95daa" class="com.intellij.openapi.ui.ComboBox" binding="defaultBrowserComboBox">
+ <constraints>
+ <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
+ </constraints>
+ <properties/>
+ </component>
+ <component id="abf80" class="javax.swing.JLabel">
+ <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>
+ <text value="Default Browser:"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <component id="c38a1" class="javax.swing.JComponent" binding="browsersTable" custom-create="true">
+ <constraints>
+ <grid row="0" column="0" row-span="1" col-span="1" vsize-policy="7" hsize-policy="7" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
+ </constraints>
+ </component>
+ <component id="b18a3" class="javax.swing.JCheckBox" binding="confirmExtractFiles" default-binding="true">
+ <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="Show confirmation before extracting files"/>
+ </properties>
+ </component>
+ <component id="d1faa" class="javax.swing.JButton" binding="clearExtractedFiles" 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"/>
+ </constraints>
+ <properties>
+ <text value="Clear extracted files"/>
+ </properties>
+ </component>
+ </children>
+ </grid>
+ <buttonGroups>
+ <group name="defaultBrowserGroup">
+ <member id="b68f"/>
+ <member id="34067"/>
+ </group>
+ </buttonGroups>
+</form>
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
new file mode 100644
index 0000000..e930550
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserSettingsPanel.java
@@ -0,0 +1,364 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers;
+
+import com.intellij.ide.GeneralSettings;
+import com.intellij.ide.IdeBundle;
+import com.intellij.openapi.fileChooser.FileChooserDescriptor;
+import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
+import com.intellij.openapi.options.ShowSettingsUtil;
+import com.intellij.openapi.ui.ComboBox;
+import com.intellij.openapi.ui.TextFieldWithBrowseButton;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.ui.EnumComboBoxModel;
+import com.intellij.ui.ListCellRendererWrapper;
+import com.intellij.ui.TitledSeparator;
+import com.intellij.util.Function;
+import com.intellij.util.PathUtil;
+import com.intellij.util.ui.ColumnInfo;
+import com.intellij.util.ui.ListTableModel;
+import com.intellij.util.ui.LocalPathCellEditor;
+import com.intellij.util.ui.UIUtil;
+import com.intellij.util.ui.table.IconTableCellRenderer;
+import com.intellij.util.ui.table.TableModelEditor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.TableModelEvent;
+import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableCellRenderer;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.Collections;
+import java.util.UUID;
+
+import static com.intellij.ide.browsers.WebBrowserManager.DefaultBrowser;
+import static com.intellij.util.ui.table.TableModelEditor.EditableColumnInfo;
+
+final class BrowserSettingsPanel {
+ private static final FileChooserDescriptor APP_FILE_CHOOSER_DESCRIPTOR = FileChooserDescriptorFactory.createSingleFileOrExecutableAppDescriptor();
+
+ private static final EditableColumnInfo<ConfigurableWebBrowser, String> PATH_COLUMN_INFO =
+ new EditableColumnInfo<ConfigurableWebBrowser, String>("Path") {
+ @Override
+ public String valueOf(ConfigurableWebBrowser item) {
+ return PathUtil.toSystemDependentName(item.getPath());
+ }
+
+ @Override
+ public void setValue(ConfigurableWebBrowser item, String value) {
+ item.setPath(value);
+ }
+
+ @Nullable
+ @Override
+ public TableCellEditor getEditor(ConfigurableWebBrowser item) {
+ return new LocalPathCellEditor().fileChooserDescriptor(APP_FILE_CHOOSER_DESCRIPTOR).normalizePath(true);
+ }
+ };
+
+ private static final ColumnInfo[] COLUMNS = {new EditableColumnInfo<ConfigurableWebBrowser, Boolean>() {
+ @Override
+ public Class getColumnClass() {
+ return Boolean.class;
+ }
+
+ @Override
+ public Boolean valueOf(ConfigurableWebBrowser item) {
+ return item.isActive();
+ }
+
+ @Override
+ public void setValue(ConfigurableWebBrowser item, Boolean value) {
+ item.setActive(value);
+ }
+ }, new EditableColumnInfo<ConfigurableWebBrowser, String>("Name") {
+ @Override
+ public String valueOf(ConfigurableWebBrowser item) {
+ return item.getName();
+ }
+
+ @Override
+ public void setValue(ConfigurableWebBrowser item, String value) {
+ item.setName(value);
+ }
+ }, new ColumnInfo<ConfigurableWebBrowser, BrowserFamily>("Family") {
+ @Override
+ public Class getColumnClass() {
+ return BrowserFamily.class;
+ }
+
+ @Override
+ public BrowserFamily valueOf(ConfigurableWebBrowser item) {
+ return item.getFamily();
+ }
+
+ @Override
+ public void setValue(ConfigurableWebBrowser item, BrowserFamily value) {
+ item.setFamily(value);
+ item.setSpecificSettings(value.createBrowserSpecificSettings());
+ }
+
+ @Nullable
+ @Override
+ public TableCellRenderer getRenderer(ConfigurableWebBrowser item) {
+ return IconTableCellRenderer.ICONABLE;
+ }
+
+ @Override
+ public boolean isCellEditable(ConfigurableWebBrowser item) {
+ return !WebBrowserManager.getInstance().isPredefinedBrowser(item);
+ }
+ }, PATH_COLUMN_INFO};
+
+ private JPanel root;
+
+ private TextFieldWithBrowseButton alternativeBrowserPathField;
+
+ private JCheckBox confirmExtractFiles;
+ private JButton clearExtractedFiles;
+ private JPanel defaultBrowserPanel;
+
+ @SuppressWarnings("UnusedDeclaration")
+ private JComponent browsersTable;
+
+ private ComboBox defaultBrowserComboBox;
+
+ private TableModelEditor<ConfigurableWebBrowser> browsersEditor;
+
+ private String customPathValue;
+
+ public BrowserSettingsPanel() {
+ alternativeBrowserPathField.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null,
+ APP_FILE_CHOOSER_DESCRIPTOR);
+
+ defaultBrowserPanel.setBorder(TitledSeparator.EMPTY_BORDER);
+
+ //noinspection unchecked
+ defaultBrowserComboBox.setModel(new EnumComboBoxModel<DefaultBrowser>(DefaultBrowser.class));
+ if (BrowserLauncherImpl.canStartDefaultBrowser()) {
+ defaultBrowserComboBox.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ boolean customPathEnabled = e.getItem() == DefaultBrowser.ALTERNATIVE;
+ if (e.getStateChange() == ItemEvent.DESELECTED) {
+ if (customPathEnabled) {
+ customPathValue = alternativeBrowserPathField.getText();
+ }
+ }
+ else if (e.getStateChange() == ItemEvent.SELECTED) {
+ alternativeBrowserPathField.setEnabled(customPathEnabled);
+ updateCustomPathTextFieldValue((DefaultBrowser)e.getItem());
+ }
+ }
+ });
+
+ defaultBrowserComboBox.setRenderer(new ListCellRendererWrapper<DefaultBrowser>() {
+ @Override
+ public void customize(JList list, DefaultBrowser value, int index, boolean selected, boolean hasFocus) {
+ String name;
+ switch (value) {
+ case SYSTEM:
+ name = "System default";
+ break;
+ case FIRST:
+ name = "First listed";
+ break;
+ case ALTERNATIVE:
+ name = "Custom path";
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+
+ setText(name);
+ }
+ });
+
+ if (UIUtil.isUnderAquaLookAndFeel()) {
+ defaultBrowserComboBox.setBorder(new EmptyBorder(3, 0, 0, 0));
+ }
+ }
+ else {
+ defaultBrowserComboBox.setVisible(false);
+ }
+
+ clearExtractedFiles.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ BrowserLauncherImpl.clearExtractedFiles();
+ }
+ });
+ }
+
+ private void updateCustomPathTextFieldValue(DefaultBrowser browser) {
+ if (browser == DefaultBrowser.ALTERNATIVE) {
+ alternativeBrowserPathField.setText(customPathValue);
+ }
+ else if (browser == DefaultBrowser.FIRST) {
+ setCustomPathToFirstListed();
+ }
+ else {
+ alternativeBrowserPathField.setText("");
+ }
+ }
+
+ private void createUIComponents() {
+ TableModelEditor.DialogItemEditor<ConfigurableWebBrowser> itemEditor = new TableModelEditor.DialogItemEditor<ConfigurableWebBrowser>() {
+ @NotNull
+ @Override
+ public Class<ConfigurableWebBrowser> getItemClass() {
+ return ConfigurableWebBrowser.class;
+ }
+
+ @Override
+ public ConfigurableWebBrowser clone(@NotNull ConfigurableWebBrowser item, boolean forInPlaceEditing) {
+ return new ConfigurableWebBrowser(forInPlaceEditing ? item.getId() : UUID.randomUUID(),
+ item.getFamily(), item.getName(), item.getPath(), item.isActive(),
+ forInPlaceEditing ? item.getSpecificSettings() : cloneSettings(item));
+ }
+
+ @Override
+ public void edit(@NotNull ConfigurableWebBrowser browser, @NotNull Function<ConfigurableWebBrowser, ConfigurableWebBrowser> mutator) {
+ BrowserSpecificSettings settings = cloneSettings(browser);
+ if (settings != null && ShowSettingsUtil.getInstance().editConfigurable(browsersTable, settings.createConfigurable())) {
+ mutator.fun(browser).setSpecificSettings(settings);
+ }
+ }
+
+ @Nullable
+ private BrowserSpecificSettings cloneSettings(@NotNull ConfigurableWebBrowser browser) {
+ BrowserSpecificSettings settings = browser.getSpecificSettings();
+ if (settings == null) {
+ return null;
+ }
+
+ BrowserSpecificSettings newSettings = browser.getFamily().createBrowserSpecificSettings();
+ assert newSettings != null;
+ TableModelEditor.cloneUsingXmlSerialization(settings, newSettings);
+ return newSettings;
+ }
+
+ @Override
+ public void applyEdited(@NotNull ConfigurableWebBrowser oldItem, @NotNull ConfigurableWebBrowser newItem) {
+ oldItem.setSpecificSettings(newItem.getSpecificSettings());
+ }
+
+ @Override
+ public boolean isEditable(@NotNull ConfigurableWebBrowser browser) {
+ return browser.getSpecificSettings() != null;
+ }
+
+ @Override
+ public boolean isRemovable(@NotNull ConfigurableWebBrowser item) {
+ return !WebBrowserManager.getInstance().isPredefinedBrowser(item);
+ }
+ };
+ browsersEditor = new TableModelEditor<ConfigurableWebBrowser>(Collections.<ConfigurableWebBrowser>emptyList(), COLUMNS,
+ itemEditor, "No web browsers configured"
+ ).modelListener(new TableModelEditor.DataChangedListener<ConfigurableWebBrowser>() {
+ @Override
+ public void tableChanged(TableModelEvent event) {
+ update(event.getFirstRow());
+ }
+
+ @Override
+ public void dataChanged(@NotNull ColumnInfo<ConfigurableWebBrowser, ?> columnInfo, int rowIndex) {
+ if (columnInfo == PATH_COLUMN_INFO) {
+ update(rowIndex);
+ }
+ }
+
+ private void update(int rowIndex) {
+ if (rowIndex == 0 && getDefaultBrowser() == DefaultBrowser.FIRST) {
+ setCustomPathToFirstListed();
+ }
+ }
+ });
+ browsersTable = browsersEditor.createComponent();
+ }
+
+ private void setCustomPathToFirstListed() {
+ ListTableModel<ConfigurableWebBrowser> model = browsersEditor.getModel();
+ alternativeBrowserPathField.setText(model.getRowCount() == 0 ? "" : model.getRowValue(0).getPath());
+ }
+
+ @NotNull
+ public JPanel getComponent() {
+ return root;
+ }
+
+ public boolean isModified() {
+ WebBrowserManager browserManager = WebBrowserManager.getInstance();
+ GeneralSettings generalSettings = GeneralSettings.getInstance();
+
+ DefaultBrowser defaultBrowser = getDefaultBrowser();
+ if (browserManager.getDefaultBrowserMode() != defaultBrowser || generalSettings.isConfirmExtractFiles() != confirmExtractFiles.isSelected()) {
+ return true;
+ }
+
+ if (defaultBrowser == DefaultBrowser.ALTERNATIVE &&
+ !Comparing.strEqual(generalSettings.getBrowserPath(), alternativeBrowserPathField.getText())) {
+ return true;
+ }
+
+ return browsersEditor.isModified(browserManager.getList());
+ }
+
+ public void apply() {
+ GeneralSettings settings = GeneralSettings.getInstance();
+
+ settings.setUseDefaultBrowser(getDefaultBrowser() == DefaultBrowser.SYSTEM);
+
+ if (alternativeBrowserPathField.isEnabled()) {
+ settings.setBrowserPath(alternativeBrowserPathField.getText());
+ }
+
+ settings.setConfirmExtractFiles(confirmExtractFiles.isSelected());
+
+ WebBrowserManager browserManager = WebBrowserManager.getInstance();
+ browserManager.defaultBrowser = getDefaultBrowser();
+ browserManager.setList(browsersEditor.apply());
+ }
+
+ private DefaultBrowser getDefaultBrowser() {
+ return (DefaultBrowser)defaultBrowserComboBox.getSelectedItem();
+ }
+
+ public void reset() {
+ GeneralSettings settings = GeneralSettings.getInstance();
+
+ DefaultBrowser defaultBrowser = WebBrowserManager.getInstance().getDefaultBrowserMode();
+ defaultBrowserComboBox.setSelectedItem(defaultBrowser);
+
+ confirmExtractFiles.setSelected(settings.isConfirmExtractFiles());
+ browsersEditor.reset(WebBrowserManager.getInstance().getList());
+
+ customPathValue = settings.getBrowserPath();
+ alternativeBrowserPathField.setEnabled(defaultBrowser == DefaultBrowser.ALTERNATIVE);
+ updateCustomPathTextFieldValue(defaultBrowser);
+ }
+
+ public void selectBrowser(@NotNull WebBrowser browser) {
+ if (browser instanceof ConfigurableWebBrowser) {
+ browsersEditor.selectItem((ConfigurableWebBrowser)browser);
+ }
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java b/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
deleted file mode 100644
index 2af780a..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserSpecificSettings.java
+++ /dev/null
@@ -1,34 +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.ide.browsers;
-
-import com.intellij.openapi.options.Configurable;
-import com.intellij.util.ArrayUtil;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.NonNls;
-
-/**
- * @author nik
- */
-public abstract class BrowserSpecificSettings {
-
- public abstract Configurable createConfigurable();
-
- @NotNull @NonNls
- public String[] getAdditionalParameters() {
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java b/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java
index b2d5c6f..8e3f014 100644
--- a/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java
+++ b/xml/impl/src/com/intellij/ide/browsers/BrowserStarter.java
@@ -31,7 +31,7 @@
}
public void start() {
- if (!mySettings.isSelected() || StringUtil.isEmptyOrSpaces(mySettings.getUrl())) {
+ if (!mySettings.isSelected() || mySettings.getUrl() == null) {
return;
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java b/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java
deleted file mode 100644
index 0210580..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/BrowsersConfiguration.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.ide.browsers.chrome.ChromeSettings;
-import com.intellij.ide.browsers.firefox.FirefoxSettings;
-import com.intellij.openapi.components.*;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.containers.hash.LinkedHashMap;
-import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
-import com.intellij.util.xmlb.XmlSerializer;
-import com.intellij.xml.XmlBundle;
-import org.jdom.Element;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
-@State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/browsers.xml")})
-public class BrowsersConfiguration implements PersistentStateComponent<Element> {
- public enum BrowserFamily {
- CHROME(XmlBundle.message("browsers.chrome"), "chrome", "google-chrome", "Google Chrome", AllIcons.Xml.Browsers.Chrome16) {
- @Override
- public BrowserSpecificSettings createBrowserSpecificSettings() {
- return new ChromeSettings();
- }
- },
- EXPLORER(XmlBundle.message("browsers.explorer"), "iexplore", null, null, AllIcons.Xml.Browsers.Explorer16),
- FIREFOX(XmlBundle.message("browsers.firefox"), "firefox", "firefox", "Firefox", AllIcons.Xml.Browsers.Firefox16) {
- @Override
- public BrowserSpecificSettings createBrowserSpecificSettings() {
- return new FirefoxSettings();
- }
- },
- OPERA(XmlBundle.message("browsers.opera"), "opera", "opera", "Opera", AllIcons.Xml.Browsers.Opera16),
- SAFARI(XmlBundle.message("browsers.safari"), "safari", null, "Safari", AllIcons.Xml.Browsers.Safari16);
-
- private final String myName;
- private final String myWindowsPath;
- private final String myUnixPath;
- private final String myMacPath;
- private final Icon myIcon;
-
- BrowserFamily(final String name,
- @NonNls final String windowsPath,
- @NonNls final String unixPath,
- @NonNls final String macPath,
- final Icon icon) {
- myName = name;
- myWindowsPath = windowsPath;
- myUnixPath = unixPath;
- myMacPath = macPath;
- myIcon = icon;
- }
-
- @Nullable
- public BrowserSpecificSettings createBrowserSpecificSettings() {
- return null;
- }
-
- @Nullable
- public String getExecutionPath() {
- if (SystemInfo.isWindows) {
- return myWindowsPath;
- }
- else if (SystemInfo.isMac) {
- return myMacPath;
- }
- else if (SystemInfo.isUnix) {
- return myUnixPath;
- }
-
- return null;
- }
-
- public String getName() {
- return myName;
- }
-
- public Icon getIcon() {
- return myIcon;
- }
- }
-
- private final Map<BrowserFamily, WebBrowserSettings> myBrowserToSettingsMap = new LinkedHashMap<BrowserFamily, WebBrowserSettings>();
-
- @Override
- @SuppressWarnings({"HardCodedStringLiteral"})
- public Element getState() {
- @NonNls Element element = new Element("WebBrowsersConfiguration");
- for (Map.Entry<BrowserFamily, WebBrowserSettings> entry : myBrowserToSettingsMap.entrySet()) {
- Element browser = new Element("browser");
- browser.setAttribute("family", entry.getKey().toString());
- WebBrowserSettings settings = entry.getValue();
- browser.setAttribute("path", settings.getPath());
- browser.setAttribute("active", Boolean.toString(settings.isActive()));
- BrowserSpecificSettings specificSettings = settings.getBrowserSpecificSettings();
- if (specificSettings != null) {
- Element settingsElement = new Element("settings");
- XmlSerializer.serializeInto(specificSettings, settingsElement, new SkipDefaultValuesSerializationFilters());
- if (!settingsElement.getContent().isEmpty()) {
- browser.addContent(settingsElement);
- }
- }
- element.addContent(browser);
- }
-
- return element;
- }
-
- @Override
- public void loadState(Element element) {
- for (Element child : element.getChildren("browser")) {
- Element settingsElement = child.getChild("settings");
- try {
- BrowserFamily browserFamily = BrowserFamily.valueOf(child.getAttributeValue("family"));
- BrowserSpecificSettings specificSettings = settingsElement == null ? null : browserFamily.createBrowserSpecificSettings();
- if (specificSettings != null) {
- XmlSerializer.deserializeInto(specificSettings, settingsElement);
- }
- myBrowserToSettingsMap.put(browserFamily, new WebBrowserSettings(child.getAttributeValue("path"), Boolean.parseBoolean(child.getAttributeValue("active")), specificSettings));
- }
- catch (IllegalArgumentException ignored) {
- }
- }
- }
-
- public List<BrowserFamily> getActiveBrowsers() {
- final List<BrowserFamily> browsers = new ArrayList<BrowserFamily>();
- for (BrowserFamily family : BrowserFamily.values()) {
- if (getBrowserSettings(family).isActive()) {
- browsers.add(family);
- }
- }
- return browsers;
- }
-
- public void updateBrowserValue(final BrowserFamily family, final String path, boolean isActive) {
- final WebBrowserSettings settings = getBrowserSettings(family);
- myBrowserToSettingsMap.put(family, new WebBrowserSettings(path, isActive, settings.getBrowserSpecificSettings()));
- }
-
- public void updateBrowserSpecificSettings(BrowserFamily family, BrowserSpecificSettings specificSettings) {
- final WebBrowserSettings settings = getBrowserSettings(family);
- myBrowserToSettingsMap.put(family, new WebBrowserSettings(settings.getPath(), settings.isActive(), specificSettings));
- }
-
- @NotNull
- public WebBrowserSettings getBrowserSettings(@NotNull final BrowserFamily browserFamily) {
- WebBrowserSettings result = myBrowserToSettingsMap.get(browserFamily);
- if (result == null) {
- final String path = browserFamily.getExecutionPath();
- result = new WebBrowserSettings(StringUtil.notNullize(path), path != null, null);
- myBrowserToSettingsMap.put(browserFamily, result);
- }
-
- return result;
- }
-
- public static BrowsersConfiguration getInstance() {
- return ServiceManager.getService(BrowsersConfiguration.class);
- }
-
- @Nullable
- public BrowserFamily findFamilyByName(@Nullable String name) {
- for (BrowserFamily family : BrowserFamily.values()) {
- if (family.getName().equals(name)) {
- return family;
- }
- }
- return null;
- }
-
- @Nullable
- public BrowserFamily findFamilyByPath(@Nullable String path) {
- if (!StringUtil.isEmptyOrSpaces(path)) {
- String name = FileUtil.getNameWithoutExtension(new File(path).getName());
- for (BrowserFamily family : BrowserFamily.values()) {
- if (name.equalsIgnoreCase(family.getExecutionPath())) {
- return family;
- }
- }
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
new file mode 100644
index 0000000..d15c59d
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/ConfigurableWebBrowser.java
@@ -0,0 +1,123 @@
+package com.intellij.ide.browsers;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.Comparing;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.PathUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.util.UUID;
+
+final class ConfigurableWebBrowser extends WebBrowserBase {
+ private boolean active;
+ private String path;
+
+ private BrowserSpecificSettings specificSettings;
+
+ @SuppressWarnings("UnusedDeclaration")
+ public ConfigurableWebBrowser() {
+ this(UUID.randomUUID(), BrowserFamily.CHROME);
+ }
+
+ public ConfigurableWebBrowser(@NotNull UUID id, @NotNull BrowserFamily family) {
+ this(id, family, family.getName(), family.getExecutionPath(), true, family.createBrowserSpecificSettings());
+ }
+
+ public ConfigurableWebBrowser(@NotNull UUID id,
+ @NotNull BrowserFamily family,
+ @NotNull String name,
+ @Nullable String path,
+ boolean active,
+ @Nullable BrowserSpecificSettings specificSettings) {
+ super(id, family, name);
+
+ this.path = StringUtil.nullize(path);
+ this.active = active;
+ this.specificSettings = specificSettings;
+ }
+
+ public void setName(@NotNull String value) {
+ name = value;
+ }
+
+ public void setFamily(@NotNull BrowserFamily value) {
+ family = value;
+ }
+
+ @NotNull
+ @Override
+ public Icon getIcon() {
+ if (family == BrowserFamily.CHROME) {
+ if (checkNameAndPath("Yandex")) {
+ return AllIcons.Xml.Browsers.Yandex16;
+ }
+ else if (checkNameAndPath("Dartium") || checkNameAndPath("Chromium")) {
+ return AllIcons.Xml.Browsers.Chromium16;
+ }
+ else if (checkNameAndPath("Canary")) {
+ return AllIcons.Xml.Browsers.Canary16;
+ }
+ else if (checkNameAndPath("Opera")) {
+ return AllIcons.Xml.Browsers.Opera16;
+ }
+ }
+ return family.getIcon();
+ }
+
+ private boolean checkNameAndPath(@NotNull String what) {
+ return StringUtil.containsIgnoreCase(name, what) || path != null && StringUtil.containsIgnoreCase(path, what);
+ }
+
+ @Nullable
+ @Override
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(@Nullable String value) {
+ path = PathUtil.toSystemIndependentName(StringUtil.nullize(value));
+ }
+
+ @Override
+ @Nullable
+ public BrowserSpecificSettings getSpecificSettings() {
+ return specificSettings;
+ }
+
+ public void setSpecificSettings(@Nullable BrowserSpecificSettings value) {
+ specificSettings = value;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setActive(boolean value) {
+ active = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof ConfigurableWebBrowser)) {
+ return false;
+ }
+
+ ConfigurableWebBrowser browser = (ConfigurableWebBrowser)o;
+ return getId().equals(browser.getId()) &&
+ family.equals(browser.family) &&
+ active == browser.active &&
+ Comparing.strEqual(name, browser.name) &&
+ Comparing.equal(path, browser.path) &&
+ Comparing.equal(specificSettings, browser.specificSettings);
+ }
+
+ @Override
+ public int hashCode() {
+ return getId().hashCode();
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java b/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java
index 9cb6e72..cbc8cb1 100644
--- a/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java
+++ b/xml/impl/src/com/intellij/ide/browsers/JavaScriptDebuggerStarter.java
@@ -40,15 +40,17 @@
}
public static <RC extends RunConfiguration> void startDebugOrLaunchBrowser(@NotNull RC runConfiguration, @NotNull StartBrowserSettings settings) {
- startDebugOrLaunchBrowser(runConfiguration, settings.getUrl(), settings.getBrowser(), settings.isStartJavaScriptDebugger());
+ String url = settings.getUrl();
+ assert url != null;
+ startDebugOrLaunchBrowser(runConfiguration, url, settings.getBrowser(), settings.isStartJavaScriptDebugger());
}
public static <RC extends RunConfiguration> void startDebugOrLaunchBrowser(@NotNull RC runConfiguration,
- @NotNull String url,
- @Nullable BrowsersConfiguration.BrowserFamily browser,
- boolean startDebugger) {
+ @NotNull String url,
+ @Nullable WebBrowser browser,
+ boolean startDebugger) {
if (!startDebugger || !start(runConfiguration, url)) {
- UrlOpener.launchBrowser(browser, url);
+ BrowserLauncher.getInstance().browse(url, browser, runConfiguration.getProject());
}
}
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/OpenFileInDefaultBrowserAction.java
deleted file mode 100644
index 1ffc4d2..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/OpenFileInDefaultBrowserAction.java
+++ /dev/null
@@ -1,175 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.ide.GeneralSettings;
-import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
-import com.intellij.openapi.actionSystem.*;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.project.DumbAwareAction;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.ui.popup.JBPopupFactory;
-import com.intellij.openapi.util.AsyncResult;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.testFramework.LightVirtualFile;
-import com.intellij.ui.ColoredListCellRenderer;
-import com.intellij.ui.components.JBList;
-import com.intellij.util.Consumer;
-import com.intellij.util.Url;
-import com.intellij.util.containers.ContainerUtil;
-import com.intellij.xml.XmlBundle;
-import com.intellij.xml.util.HtmlUtil;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.event.InputEvent;
-import java.util.Collection;
-
-public class OpenFileInDefaultBrowserAction extends DumbAwareAction {
- private static final Logger LOG = Logger.getInstance(OpenFileInDefaultBrowserAction.class);
-
- @Override
- public void update(AnActionEvent e) {
- final DataContext dataContext = e.getDataContext();
- final PsiFile file = CommonDataKeys.PSI_FILE.getData(dataContext);
- final Presentation presentation = e.getPresentation();
-
- if (file == null || file.getVirtualFile() == null) {
- presentation.setVisible(false);
- presentation.setEnabled(false);
- return;
- }
-
- Pair<WebBrowserUrlProvider, Collection<Url>> browserUrlProvider = WebBrowserServiceImpl.getProvider(file);
- final boolean isHtmlFile = HtmlUtil.isHtmlFile(file);
- if (browserUrlProvider == null) {
- if (file.getVirtualFile() instanceof LightVirtualFile) {
- presentation.setVisible(false);
- presentation.setEnabled(false);
- return;
- }
- else {
- presentation.setEnabled(isHtmlFile);
- }
- }
- else {
- presentation.setEnabled(true);
- }
- presentation.setVisible(true);
-
- String text = getTemplatePresentation().getText();
- String description = getTemplatePresentation().getDescription();
-
- if (browserUrlProvider != null) {
- final String customText = browserUrlProvider.first.getOpenInBrowserActionText(file);
- if (customText != null) {
- text = customText;
- }
- final String customDescription = browserUrlProvider.first.getOpenInBrowserActionDescription(file);
- if (customDescription != null) {
- description = customDescription;
- }
- if (isHtmlFile) {
- description += " (hold Shift to open URL of local file)";
- }
- }
-
- presentation.setText(text);
- presentation.setDescription(description);
-
- GeneralSettings settings = GeneralSettings.getInstance();
- if (!settings.isUseDefaultBrowser()) {
- BrowsersConfiguration.BrowserFamily family = BrowsersConfiguration.getInstance().findFamilyByPath(settings.getBrowserPath());
- if (family != null) {
- presentation.setIcon(family.getIcon());
- }
- }
-
- if (ActionPlaces.isPopupPlace(e.getPlace())) {
- presentation.setVisible(presentation.isEnabled());
- }
- }
-
- @Override
- public void actionPerformed(AnActionEvent e) {
- DataContext dataContext = e.getDataContext();
- PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(dataContext);
- LOG.assertTrue(psiFile != null);
- InputEvent event = e.getInputEvent();
- doOpen(psiFile, event != null && event.isShiftDown(), null);
- }
-
- public static void doOpen(PsiElement psiFile, boolean preferLocalUrl, final WebBrowser browser) {
- try {
- Collection<Url> urls = WebBrowserService.getInstance().getUrlToOpen(psiFile, preferLocalUrl);
- if (!urls.isEmpty()) {
- chooseUrl(urls).doWhenDone(new Consumer<Url>() {
- @Override
- public void consume(Url url) {
- ApplicationManager.getApplication().saveAll();
- UrlOpener.launchBrowser(url.toExternalForm(), browser);
- }
- });
- }
- }
- catch (WebBrowserUrlProvider.BrowserException e1) {
- Messages.showErrorDialog(e1.getMessage(), XmlBundle.message("browser.error"));
- }
- catch (Exception e1) {
- LOG.error(e1);
- }
- }
-
- @NotNull
- private static AsyncResult<Url> chooseUrl(Collection<Url> urls) {
- if (urls.size() == 1) {
- return new AsyncResult.Done<Url>(ContainerUtil.getFirstItem(urls));
- }
-
- final JBList list = new JBList(urls);
- list.setCellRenderer(new ColoredListCellRenderer() {
- @Override
- protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
- // todo icons looks good, but is it really suitable for all URLs providers?
- setIcon(AllIcons.Nodes.Servlet);
- append(((Url)value).toDecodedForm());
- }
- });
-
- final AsyncResult<Url> result = new AsyncResult<Url>();
- JBPopupFactory.getInstance().
- createListPopupBuilder(list).
- setTitle("Choose Url").
- setItemChoosenCallback(new Runnable() {
- @Override
- public void run() {
- Url value = (Url)list.getSelectedValue();
- if (value != null) {
- result.setDone(value);
- }
- else {
- result.setRejected();
- }
- }
- }).
- createPopup().showInFocusCenter();
- return result;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java
index 3ea6376..7ba4026 100644
--- a/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java
+++ b/xml/impl/src/com/intellij/ide/browsers/OpenUrlHyperlinkInfo.java
@@ -57,13 +57,12 @@
@Override
public ActionGroup getPopupMenuGroup(@NotNull MouseEvent event) {
DefaultActionGroup group = new DefaultActionGroup();
- for (BrowsersConfiguration.BrowserFamily browserFamily : BrowsersConfiguration.getInstance().getActiveBrowsers()) {
- final WebBrowser browser = WebBrowser.getStandardBrowser(browserFamily);
+ for (final WebBrowser browser : WebBrowserManager.getInstance().getActiveBrowsers()) {
if (browserCondition == null ? browser.equals(this.browser) : browserCondition.value(browser)) {
group.add(new AnAction("Open in " + browser.getName(), "Open URL in " + browser.getName(), browser.getIcon()) {
@Override
public void actionPerformed(AnActionEvent e) {
- UrlOpener.launchBrowser(url, browser);
+ BrowserLauncher.getInstance().browse(url, browser, e.getProject());
}
});
}
@@ -80,6 +79,6 @@
@Override
public void navigate(Project project) {
- UrlOpener.launchBrowser(url, browser);
+ BrowserLauncher.getInstance().browse(url, browser, project);
}
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java b/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java
deleted file mode 100644
index f4a5c7e..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/SelectInDefaultBrowserTarget.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers;
-
-import com.intellij.ide.SelectInContext;
-import com.intellij.ide.SelectInTargetBase;
-import com.intellij.ide.StandardTargetWeights;
-import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Pair;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.testFramework.LightVirtualFile;
-import com.intellij.util.Url;
-import com.intellij.xml.XmlBundle;
-import com.intellij.xml.util.HtmlUtil;
-
-import java.util.Collection;
-
-class SelectInDefaultBrowserTarget extends SelectInTargetBase {
- private static final Logger LOG = Logger.getInstance(SelectInDefaultBrowserTarget.class);
-
- private String currentName = "";
-
- @Override
- public boolean canSelect(SelectInContext context) {
- Object selectorInFile = context.getSelectorInFile();
- if (!(selectorInFile instanceof PsiElement)) {
- return false;
- }
-
- PsiFile file = ((PsiElement)selectorInFile).getContainingFile();
- if (file == null || file.getVirtualFile() == null) {
- return false;
- }
-
- Pair<WebBrowserUrlProvider, Collection<Url>> browserUrlProvider = WebBrowserServiceImpl.getProvider(file);
- currentName = XmlBundle.message("browser.select.in.default.name");
- if (browserUrlProvider == null) {
- return HtmlUtil.isHtmlFile(file) && !(file.getVirtualFile() instanceof LightVirtualFile);
- }
- else {
- String customText = browserUrlProvider.first.getOpenInBrowserActionText(file);
- if (customText != null) {
- currentName = customText;
- }
- }
- return true;
- }
-
- @Override
- public String toString() {
- return currentName;
- }
-
- @Override
- public void selectIn(SelectInContext context, boolean requestFocus) {
- PsiElement psiElement = (PsiElement)context.getSelectorInFile();
- LOG.assertTrue(psiElement != null);
- PsiFile psiFile = psiElement.getContainingFile();
- LOG.assertTrue(psiFile != null);
- OpenFileInDefaultBrowserAction.doOpen(psiFile, false, null);
- }
-
- @Override
- public float getWeight() {
- return StandardTargetWeights.OS_FILE_MANAGER;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java
index 75cb440..fe2163e 100644
--- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java
+++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserPanel.java
@@ -12,7 +12,6 @@
import com.intellij.openapi.ui.TextBrowseFolderListener;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.openapi.vfs.StandardFileSystems;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiBinaryFile;
@@ -71,17 +70,20 @@
return myRoot;
}
- @NotNull
+ @Nullable
public String getUrl() {
- String url = myUrlField.getText();
- if (!url.isEmpty() && !URLUtil.containsScheme(url)) {
- return VirtualFileManager.constructUrl(StandardFileSystems.HTTP_PROTOCOL, url);
+ String url = StringUtil.nullize(myUrlField.getText(), true);
+ if (url != null) {
+ url = url.trim();
+ if (!URLUtil.containsScheme(url)) {
+ return VirtualFileManager.constructUrl(URLUtil.HTTP_PROTOCOL, url);
+ }
}
return url;
}
public void setUrl(@Nullable String url) {
- myUrlField.setText(StringUtil.notNullize(url));
+ myUrlField.setText(url);
}
public void clearBorder() {
@@ -105,13 +107,14 @@
}
private void createUIComponents() {
- myBrowserSelector = new BrowserSelector(true);
+ myBrowserSelector = new BrowserSelector();
myBrowserComboBox = myBrowserSelector.getMainComponent();
if (UIUtil.isUnderAquaLookAndFeel()) {
myBrowserComboBox.setBorder(new EmptyBorder(3, 0, 0, 0));
}
}
+ @Nullable
private static Url virtualFileToUrl(VirtualFile file, Project project) {
PsiFile psiFile;
AccessToken token = ReadAction.start();
@@ -124,6 +127,16 @@
return psiFile != null && !(psiFile instanceof PsiBinaryFile) ? WebBrowserServiceImpl.getUrlForContext(psiFile) : null;
}
+ @NotNull
+ public StartBrowserSettings createSettings() {
+ StartBrowserSettings browserSettings = new StartBrowserSettings();
+ browserSettings.setSelected(isSelected());
+ browserSettings.setBrowser(myBrowserSelector.getSelected());
+ browserSettings.setStartJavaScriptDebugger(myStartJavaScriptDebuggerCheckBox.isSelected());
+ browserSettings.setUrl(getUrl());
+ return browserSettings;
+ }
+
public static void setupUrlField(@NotNull TextFieldWithBrowseButton field, @NotNull final Project project) {
FileChooserDescriptor descriptor = new FileChooserDescriptor(true, false, false, false, false, false) {
@Override
@@ -140,7 +153,8 @@
@NotNull
@Override
protected String chosenFileToResultingText(@NotNull VirtualFile chosenFile) {
- return virtualFileToUrl(chosenFile, project).toDecodedForm();
+ Url url = virtualFileToUrl(chosenFile, project);
+ return url == null ? chosenFile.getUrl() : url.toDecodedForm();
}
});
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java
index 99f847a..f93e16b 100644
--- a/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java
+++ b/xml/impl/src/com/intellij/ide/browsers/StartBrowserSettings.java
@@ -1,128 +1,80 @@
package com.intellij.ide.browsers;
+import com.google.common.base.CharMatcher;
+import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.text.StringUtil;
-import org.jdom.Attribute;
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-/**
- * @author Sergey Simonchik
- */
+@Tag("browser")
public class StartBrowserSettings {
- private static final String BROWSER_ELEMENT = "browser";
- private static final String START_BROWSER_ATTR = "start";
- private static final String BROWSER_NAME_ATTR = "name";
- private static final String URL_ATTR = "url";
- private static final String WITH_JS_DEBUGGER_ATTR = "with-js-debugger";
+ private boolean mySelected;
+ private WebBrowser myBrowser;
- private final boolean mySelected;
- private final BrowsersConfiguration.BrowserFamily myBrowser;
- private final String myUrl;
- private final boolean myStartJavaScriptDebugger;
+ private String myUrl;
+ private boolean myStartJavaScriptDebugger;
- private StartBrowserSettings(boolean selected,
- @Nullable BrowsersConfiguration.BrowserFamily browser,
- @NotNull String url,
- boolean startJavaScriptDebugger) {
- mySelected = selected;
- myBrowser = browser;
- myUrl = url;
- myStartJavaScriptDebugger = startJavaScriptDebugger;
- }
-
+ @Attribute("start")
public boolean isSelected() {
return mySelected;
}
+ public void setSelected(boolean selected) {
+ mySelected = selected;
+ }
+
@Nullable
- public BrowsersConfiguration.BrowserFamily getBrowser() {
+ @Attribute(value = "name", converter = WebBrowserReferenceConverter.class)
+ public WebBrowser getBrowser() {
return myBrowser;
}
+ public void setBrowser(@Nullable WebBrowser value) {
+ myBrowser = value;
+ }
+
+ @Nullable
+ @Attribute
public String getUrl() {
return myUrl;
}
+ public void setUrl(@Nullable String value) {
+ String normalized = StringUtil.nullize(value, true);
+ if (normalized != null) {
+ normalized = CharMatcher.WHITESPACE.trimFrom(normalized);
+ }
+ myUrl = normalized;
+ }
+
+ @Attribute("with-js-debugger")
public boolean isStartJavaScriptDebugger() {
return myStartJavaScriptDebugger;
}
+ public void setStartJavaScriptDebugger(boolean value) {
+ myStartJavaScriptDebugger = value;
+ }
+
@NotNull
public static StartBrowserSettings readExternal(@NotNull Element parent) {
- Builder builder = new Builder();
- Element child = parent.getChild(BROWSER_ELEMENT);
- if (child != null) {
- builder.setSelected(Boolean.parseBoolean(getAttrValue(child, START_BROWSER_ATTR)));
- builder.setBrowser(BrowsersConfiguration.getInstance().findFamilyByName(getAttrValue(child, BROWSER_NAME_ATTR)));
- builder.setUrl(StringUtil.notNullize(getAttrValue(child, URL_ATTR)));
- builder.setStartJavaScriptDebugger(Boolean.parseBoolean(getAttrValue(child, WITH_JS_DEBUGGER_ATTR)));
+ Element state = parent.getChild("browser");
+ StartBrowserSettings settings = new StartBrowserSettings();
+ if (state != null) {
+ XmlSerializer.deserializeInto(settings, state);
}
- return builder.build();
+ return settings;
}
public void writeExternal(@NotNull Element parent) {
- Element child = new Element(BROWSER_ELEMENT);
- child.setAttribute(START_BROWSER_ATTR, String.valueOf(isSelected()));
- if (myBrowser != null) {
- child.setAttribute(BROWSER_NAME_ATTR, myBrowser.getName());
- }
- child.setAttribute(URL_ATTR, getUrl());
- child.setAttribute(WITH_JS_DEBUGGER_ATTR, String.valueOf(isStartJavaScriptDebugger()));
- parent.addContent(child);
- }
-
- @Nullable
- private static String getAttrValue(Element element, String attrKey) {
- Attribute attribute = element.getAttribute(attrKey);
- return attribute != null ? attribute.getValue() : null;
- }
-
- public static class Builder {
- private boolean mySelected;
- private BrowsersConfiguration.BrowserFamily myBrowser;
- private String myUrl = "";
- private boolean myStartJavaScriptDebugger;
-
- public Builder() {
- }
-
- public Builder(@Nullable StartBrowserSettings settings) {
- if (settings != null) {
- mySelected = settings.isSelected();
- myBrowser = settings.getBrowser();
- myUrl = settings.getUrl();
- myStartJavaScriptDebugger = settings.isStartJavaScriptDebugger();
- }
- }
-
- public Builder setSelected(boolean selected) {
- mySelected = selected;
- return this;
- }
-
- /**
- * @param browser {@link com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily} instance,
- * null if Default browser needed
- */
- public Builder setBrowser(@Nullable BrowsersConfiguration.BrowserFamily browser) {
- myBrowser = browser;
- return this;
- }
-
- public Builder setUrl(@NotNull String url) {
- myUrl = url;
- return this;
- }
-
- public Builder setStartJavaScriptDebugger(boolean startJavaScriptDebugger) {
- myStartJavaScriptDebugger = startJavaScriptDebugger;
- return this;
- }
-
- @NotNull
- public StartBrowserSettings build() {
- return new StartBrowserSettings(mySelected, myBrowser, myUrl, myStartJavaScriptDebugger);
+ Element state = XmlSerializer.serialize(this, new SkipDefaultValuesSerializationFilters());
+ if (!JDOMUtil.isEmpty(state)) {
+ parent.addContent(state);
}
}
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java
deleted file mode 100644
index fde236c..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/UrlOpener.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers;
-
-import com.intellij.ide.BrowserUtil;
-import com.intellij.openapi.extensions.ExtensionPointName;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public abstract class UrlOpener {
- public static final ExtensionPointName<UrlOpener> EP_NAME = ExtensionPointName.create("org.jetbrains.urlOpener");
-
- public static void launchBrowser(final @Nullable BrowsersConfiguration.BrowserFamily family, final @NotNull String url) {
- launchBrowser(url, family == null ? null : WebBrowser.getStandardBrowser(family));
- }
-
- // different params order in order not to break compilation for launchBrowser(null, url)
- public static void launchBrowser(final @NotNull String url, final @Nullable WebBrowser browser) {
- if (browser == null) {
- BrowserUtil.launchBrowser(url);
- }
- else {
- for (UrlOpener urlOpener : EP_NAME.getExtensions()) {
- if (urlOpener.openUrl(browser, url)) {
- return;
- }
- }
- }
- }
-
- public abstract boolean openUrl(final @NotNull WebBrowser browser, final @NotNull String url);
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java
deleted file mode 100644
index dbc4842..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/WebBrowser.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers;
-
-import com.intellij.CommonBundle;
-import com.intellij.ide.IdeBundle;
-import com.intellij.openapi.util.Computable;
-import com.intellij.openapi.util.NullableComputable;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-
-import static com.intellij.ide.browsers.BrowsersConfiguration.BrowserFamily;
-
-/*
- This class is a temporary solution that allows to use browser not listed in the BrowserFamily enum.
- TODO Vladimir Krivosheev: get rid of BrowserFamily enum usage, allow to create custom browsers at Web Browsers page in Settings (WEB-2093).
- */
-public class WebBrowser {
-
- public static final WebBrowser CHROME = createStandardBrowser(BrowserFamily.CHROME);
- public static final WebBrowser FIREFOX = createStandardBrowser(BrowserFamily.FIREFOX);
- public static final WebBrowser EXPLORER = createStandardBrowser(BrowserFamily.EXPLORER);
- public static final WebBrowser OPERA = createStandardBrowser(BrowserFamily.OPERA);
- public static final WebBrowser SAFARI = createStandardBrowser(BrowserFamily.SAFARI);
-
- private final @NotNull BrowserFamily myFamily;
- private final @NotNull String myName;
- private final @NotNull Icon myIcon;
- private final @NotNull Computable<String> myPathComputable;
- private final @NotNull String myBrowserNotFoundMessage;
-
- @NotNull
- public static WebBrowser getStandardBrowser(final @NotNull BrowserFamily browserFamily) {
- switch (browserFamily) {
- case CHROME:
- return CHROME;
- case FIREFOX:
- return FIREFOX;
- case EXPLORER:
- return EXPLORER;
- case OPERA:
- return OPERA;
- case SAFARI:
- return SAFARI;
- default:
- assert false : browserFamily;
- return null;
- }
- }
-
- private WebBrowser(final @NotNull BrowserFamily family,
- final @NotNull String name,
- final @NotNull Icon icon,
- final @NotNull NullableComputable<String> pathComputable,
- final @NotNull String browserNotFoundMessage) {
- myFamily = family;
- myName = name;
- myIcon = icon;
- myPathComputable = pathComputable;
- myBrowserNotFoundMessage = browserNotFoundMessage;
- }
-
- @NotNull
- public String getName() {
- return myName;
- }
-
- @NotNull
- public BrowserFamily getFamily() {
- return myFamily;
- }
-
- @NotNull
- public Icon getIcon() {
- return myIcon;
- }
-
- @Nullable
- public String getPath() {
- return myPathComputable.compute();
- }
-
- @NotNull
- public String getBrowserNotFoundMessage() {
- return myBrowserNotFoundMessage;
- }
-
- @Nullable
- public BrowserSpecificSettings getBrowserSpecificSettings() {
- return null;
- }
-
- private static WebBrowser createStandardBrowser(final BrowserFamily family) {
- final String browserNotFoundMessage = IdeBundle.message("error.0.browser.path.not.specified", family.getName(),
- CommonBundle.settingsActionPath());
- return new WebBrowser(family, family.getName(), family.getIcon(), new NullableComputable<String>() {
- @Override
- @NotNull
- public String compute() {
- return BrowsersConfiguration.getInstance().getBrowserSettings(family).getPath();
- }
- }, browserNotFoundMessage) {
- @Override
- @Nullable
- public BrowserSpecificSettings getBrowserSpecificSettings() {
- return BrowsersConfiguration.getInstance().getBrowserSettings(getFamily()).getBrowserSpecificSettings();
- }
- };
- }
-
- public static WebBrowser createCustomBrowser(final @NotNull BrowserFamily family,
- final @NotNull String name,
- final @NotNull Icon icon,
- final @NotNull NullableComputable<String> pathComputable,
- final @NotNull String browserNotFoundMessage) {
- return new WebBrowser(family, name, icon, pathComputable, browserNotFoundMessage);
- }
-
- @Override
- public String toString() {
- return getName() + " (" + getPath() + ")";
- }
-}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java
new file mode 100644
index 0000000..af7ff95
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserBase.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers;
+
+import com.intellij.ide.IdeBundle;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.UUID;
+
+public abstract class WebBrowserBase extends WebBrowser {
+ protected @NotNull BrowserFamily family;
+ protected @NotNull String name;
+ private final UUID id;
+
+ protected WebBrowserBase(@NotNull UUID id, @NotNull BrowserFamily family, @NotNull String name) {
+ this.id = id;
+ this.family = family;
+ this.name = name;
+ }
+
+ @Override
+ @NotNull
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ @NotNull
+ public final UUID getId() {
+ return id;
+ }
+
+ @Override
+ @NotNull
+ public BrowserFamily getFamily() {
+ return family;
+ }
+
+ @Override
+ @NotNull
+ public String getBrowserNotFoundMessage() {
+ return IdeBundle.message("error.0.browser.path.not.specified", getName());
+ }
+
+ @Override
+ @Nullable
+ public BrowserSpecificSettings getSpecificSettings() {
+ return null;
+ }
+
+ @Override
+ public String toString() {
+ return getName() + " (" + getPath() + ")";
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
new file mode 100644
index 0000000..8b8b60a
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserManager.java
@@ -0,0 +1,374 @@
+/*
+ * 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.ide.browsers;
+
+import com.intellij.openapi.components.*;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.Condition;
+import com.intellij.openapi.util.Conditions;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.ModificationTracker;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.SmartList;
+import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
+import com.intellij.util.xmlb.XmlSerializer;
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
+
+@State(name = "WebBrowsersConfiguration", storages = {@Storage(file = StoragePathMacros.APP_CONFIG + "/web-browsers.xml")})
+public class WebBrowserManager implements PersistentStateComponent<Element>, ModificationTracker {
+ private static final Logger LOG = Logger.getInstance(WebBrowserManager.class);
+
+ // default standard browser ID must be constant across all IDE versions on all machines for all users
+ private static final UUID DEFAULT_CHROME_ID = UUID.fromString("98CA6316-2F89-46D9-A9E5-FA9E2B0625B3");
+ private static final UUID DEFAULT_FIREFOX_ID = UUID.fromString("A7BB68E0-33C0-4D6F-A81A-AAC1FDB870C8");
+ private static final UUID DEFAULT_SAFARI_ID = UUID.fromString("E5120D43-2C3F-47EF-9F26-65E539E05186");
+ private static final UUID DEFAULT_OPERA_ID = UUID.fromString("53E2F627-B1A7-4DFA-BFA7-5B83CC034776");
+ private static final UUID DEFAULT_EXPLORER_ID = UUID.fromString("16BF23D4-93E0-4FFC-BFD6-CB13575177B0");
+
+ private List<ConfigurableWebBrowser> browsers;
+
+ private long modificationCount;
+
+ DefaultBrowser defaultBrowser = DefaultBrowser.SYSTEM;
+
+ public WebBrowserManager() {
+ browsers = new ArrayList<ConfigurableWebBrowser>();
+ browsers.add(new ConfigurableWebBrowser(DEFAULT_CHROME_ID, BrowserFamily.CHROME));
+ browsers.add(new ConfigurableWebBrowser(DEFAULT_FIREFOX_ID, BrowserFamily.FIREFOX));
+ browsers.add(new ConfigurableWebBrowser(DEFAULT_SAFARI_ID, BrowserFamily.SAFARI));
+ browsers.add(new ConfigurableWebBrowser(DEFAULT_OPERA_ID, BrowserFamily.OPERA));
+ browsers.add(new ConfigurableWebBrowser(DEFAULT_EXPLORER_ID, BrowserFamily.EXPLORER));
+ }
+
+ public static WebBrowserManager getInstance() {
+ return ServiceManager.getService(WebBrowserManager.class);
+ }
+
+ boolean isPredefinedBrowser(@NotNull ConfigurableWebBrowser browser) {
+ UUID id = browser.getId();
+ return id.equals(DEFAULT_CHROME_ID) ||
+ id.equals(DEFAULT_FIREFOX_ID) ||
+ id.equals(DEFAULT_SAFARI_ID) ||
+ id.equals(DEFAULT_OPERA_ID) ||
+ id.equals(DEFAULT_EXPLORER_ID);
+ }
+
+ public enum DefaultBrowser {
+ SYSTEM, FIRST, ALTERNATIVE
+ }
+
+ @NotNull
+ public DefaultBrowser getDefaultBrowserMode() {
+ return defaultBrowser;
+ }
+
+ @Override
+ public Element getState() {
+ Element state = new Element("state");
+ if (defaultBrowser != DefaultBrowser.SYSTEM) {
+ state.setAttribute("default", defaultBrowser.name().toLowerCase());
+ }
+
+ for (ConfigurableWebBrowser browser : browsers) {
+ Element entry = new Element("browser");
+ entry.setAttribute("id", browser.getId().toString());
+ entry.setAttribute("name", browser.getName());
+ entry.setAttribute("family", browser.getFamily().name());
+
+ String path = browser.getPath();
+ if (path != null && !path.equals(browser.getFamily().getExecutionPath())) {
+ entry.setAttribute("path", path);
+ }
+
+ if (!browser.isActive()) {
+ entry.setAttribute("active", "false");
+ }
+
+ BrowserSpecificSettings specificSettings = browser.getSpecificSettings();
+ if (specificSettings != null) {
+ Element settingsElement = new Element("settings");
+ XmlSerializer.serializeInto(specificSettings, settingsElement, new SkipDefaultValuesSerializationFilters());
+ if (!JDOMUtil.isEmpty(settingsElement)) {
+ entry.addContent(settingsElement);
+ }
+ }
+ state.addContent(entry);
+ }
+ return state;
+ }
+
+ @Nullable
+ private static BrowserFamily readFamily(String value) {
+ try {
+ return BrowserFamily.valueOf(value);
+ }
+ catch (RuntimeException e) {
+ LOG.warn(e);
+
+ for (BrowserFamily family : BrowserFamily.values()) {
+ if (family.getName().equalsIgnoreCase(value)) {
+ return family;
+ }
+ }
+
+ return null;
+ }
+ }
+
+ @Nullable
+ private static UUID readId(String value, @NotNull BrowserFamily family, @NotNull List<ConfigurableWebBrowser> existingBrowsers) {
+ if (StringUtil.isEmpty(value)) {
+ UUID id;
+ switch (family) {
+ case CHROME:
+ id = DEFAULT_CHROME_ID;
+ break;
+ case EXPLORER:
+ id = DEFAULT_EXPLORER_ID;
+ break;
+ case FIREFOX:
+ id = DEFAULT_FIREFOX_ID;
+ break;
+ case OPERA:
+ id = DEFAULT_OPERA_ID;
+ break;
+ case SAFARI:
+ id = DEFAULT_SAFARI_ID;
+ break;
+
+ default:
+ return null;
+ }
+
+ for (ConfigurableWebBrowser browser : existingBrowsers) {
+ if (browser.getId() == id) {
+ // duplicated entry, skip
+ return null;
+ }
+ }
+ return id;
+ }
+ else {
+ try {
+ return UUID.fromString(value);
+ }
+ catch (Exception e) {
+ LOG.warn(e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void loadState(Element element) {
+ String defaultValue = element.getAttributeValue("default");
+ if (!StringUtil.isEmpty(defaultValue)) {
+ try {
+ defaultBrowser = DefaultBrowser.valueOf(defaultValue.toUpperCase());
+ }
+ catch (IllegalArgumentException e) {
+ LOG.warn(e);
+ }
+ }
+
+ List<ConfigurableWebBrowser> list = new ArrayList<ConfigurableWebBrowser>();
+ for (Element child : element.getChildren("browser")) {
+ BrowserFamily family = readFamily(child.getAttributeValue("family"));
+ if (family == null) {
+ continue;
+ }
+
+ UUID id = readId(child.getAttributeValue("id"), family, list);
+ if (id == null) {
+ continue;
+ }
+
+ Element settingsElement = child.getChild("settings");
+ BrowserSpecificSettings specificSettings = family.createBrowserSpecificSettings();
+ if (specificSettings != null && settingsElement != null) {
+ try {
+ XmlSerializer.deserializeInto(specificSettings, settingsElement);
+ }
+ catch (Exception e) {
+ LOG.warn(e);
+ }
+ }
+
+ String activeValue = child.getAttributeValue("active");
+
+ String path = StringUtil.nullize(child.getAttributeValue("path"), true);
+ if (path == null) {
+ path = family.getExecutionPath();
+ }
+
+ list.add(new ConfigurableWebBrowser(id,
+ family,
+ StringUtil.notNullize(child.getAttributeValue("name"), family.getName()),
+ path,
+ activeValue == null || Boolean.parseBoolean(activeValue),
+ specificSettings));
+ }
+
+ setList(list);
+ }
+
+ @NotNull
+ public List<WebBrowser> getBrowsers() {
+ return Collections.<WebBrowser>unmodifiableList(browsers);
+ }
+
+ @NotNull
+ List<ConfigurableWebBrowser> getList() {
+ return browsers;
+ }
+
+ void setList(@NotNull List<ConfigurableWebBrowser> value) {
+ browsers = value;
+ modificationCount++;
+ }
+
+ @NotNull
+ public List<WebBrowser> getActiveBrowsers() {
+ return getBrowsers(Conditions.<WebBrowser>alwaysTrue(), true);
+ }
+
+ @NotNull
+ public List<WebBrowser> getBrowsers(@NotNull Condition<WebBrowser> condition) {
+ return getBrowsers(condition, true);
+ }
+
+ @NotNull
+ public List<WebBrowser> getBrowsers(@NotNull Condition<WebBrowser> condition, boolean onlyActive) {
+ List<WebBrowser> result = new SmartList<WebBrowser>();
+ for (ConfigurableWebBrowser browser : browsers) {
+ if ((!onlyActive || browser.isActive()) && condition.value(browser)) {
+ result.add(browser);
+ }
+ }
+ return result;
+ }
+
+ public void setBrowserSpecificSettings(@NotNull WebBrowser browser, @NotNull BrowserSpecificSettings specificSettings) {
+ ((ConfigurableWebBrowser)browser).setSpecificSettings(specificSettings);
+ }
+
+ public void setBrowserPath(@NotNull WebBrowser browser, @Nullable String path, boolean isActive) {
+ ((ConfigurableWebBrowser)browser).setPath(path);
+ ((ConfigurableWebBrowser)browser).setActive(isActive);
+ }
+
+ public WebBrowser addBrowser(final @NotNull UUID id,
+ final @NotNull BrowserFamily family,
+ final @NotNull String name,
+ final @Nullable String path,
+ final boolean active,
+ final BrowserSpecificSettings specificSettings) {
+ final ConfigurableWebBrowser browser = new ConfigurableWebBrowser(id, family, name, path, active, specificSettings);
+ browsers.add(browser);
+ modificationCount++;
+ return browser;
+ }
+
+ @Nullable
+ private static UUID parseUuid(@NotNull String id) {
+ if (id.indexOf('-') == -1) {
+ return null;
+ }
+
+ try {
+ return UUID.fromString(id);
+ }
+ catch (IllegalArgumentException ignored) {
+ return null;
+ }
+ }
+
+ @Nullable
+ public WebBrowser findBrowserById(@Nullable String idOrName) {
+ if (StringUtil.isEmpty(idOrName)) {
+ return null;
+ }
+
+ UUID id = parseUuid(idOrName);
+ if (id == null) {
+ for (ConfigurableWebBrowser browser : browsers) {
+ if (browser.getName().equals(idOrName) ||
+ browser.getFamily().name().equalsIgnoreCase(idOrName) ||
+ browser.getFamily().getName().equalsIgnoreCase(idOrName)) {
+ return browser;
+ }
+ }
+ return null;
+ }
+
+ for (ConfigurableWebBrowser browser : browsers) {
+ if (browser.getId().equals(id)) {
+ return browser;
+ }
+ }
+ return null;
+ }
+
+ @NotNull
+ public WebBrowser getBrowser(@NotNull BrowserFamily family) {
+ WebBrowser browser = findBrowser(family);
+ LOG.assertTrue(browser != null, "Must be at least one browser per family");
+ return browser;
+ }
+
+ @Nullable
+ public WebBrowser findBrowser(@NotNull BrowserFamily family) {
+ for (ConfigurableWebBrowser browser : browsers) {
+ if (browser.isActive() && family.equals(browser.getFamily())) {
+ return browser;
+ }
+ }
+
+ for (ConfigurableWebBrowser browser : browsers) {
+ if (family.equals(browser.getFamily())) {
+ return browser;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean isActive(@NotNull WebBrowser browser) {
+ return !(browser instanceof ConfigurableWebBrowser) || ((ConfigurableWebBrowser)browser).isActive();
+ }
+
+ @Nullable
+ public WebBrowser getDefaultBrowser() {
+ for (ConfigurableWebBrowser browser : browsers) {
+ if (browser.isActive()) {
+ return browser;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public long getModificationCount() {
+ return modificationCount;
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java
new file mode 100644
index 0000000..d65f179
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/WebBrowserReferenceConverter.java
@@ -0,0 +1,19 @@
+package com.intellij.ide.browsers;
+
+import com.intellij.util.xmlb.Converter;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public final class WebBrowserReferenceConverter extends Converter<WebBrowser> {
+ @Nullable
+ @Override
+ public WebBrowser fromString(@NotNull String value) {
+ return WebBrowserManager.getInstance().findBrowserById(value);
+ }
+
+ @NotNull
+ @Override
+ public String toString(@NotNull WebBrowser browser) {
+ return browser.getId().toString();
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowserSettings.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowserSettings.java
deleted file mode 100644
index e7b391d..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/WebBrowserSettings.java
+++ /dev/null
@@ -1,46 +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.ide.browsers;
-
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author nik
- */
-public class WebBrowserSettings {
- private final String myPath;
- private final boolean myActive;
- private final BrowserSpecificSettings myBrowserSpecificSettings;
-
- public WebBrowserSettings(String path, boolean active, BrowserSpecificSettings browserSpecificSettings) {
- myPath = path;
- myActive = active;
- myBrowserSpecificSettings = browserSpecificSettings;
- }
-
- public String getPath() {
- return myPath;
- }
-
- public boolean isActive() {
- return myActive;
- }
-
- @Nullable
- public BrowserSpecificSettings getBrowserSpecificSettings() {
- return myBrowserSpecificSettings;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/WebBrowsersPanel.java b/xml/impl/src/com/intellij/ide/browsers/WebBrowsersPanel.java
deleted file mode 100644
index b969776..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/WebBrowsersPanel.java
+++ /dev/null
@@ -1,221 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers;
-
-import com.intellij.ide.IdeBundle;
-import com.intellij.ide.browsers.impl.BrowserConfigurationHelper;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
-import com.intellij.openapi.options.ShowSettingsUtil;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.ui.IdeBorderFactory;
-import com.intellij.util.containers.HashMap;
-import com.intellij.xml.XmlBundle;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-
-/**
- * @author spleaner
- */
-public class WebBrowsersPanel extends JPanel {
- private final JPanel mySettingsPanel;
- private Map<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>> myBrowserSettingsMap =
- new HashMap<BrowsersConfiguration.BrowserFamily, Pair<JCheckBox, TextFieldWithBrowseButton>>();
- private final BrowsersConfiguration myConfiguration;
-
- public WebBrowsersPanel(final BrowsersConfiguration configuration) {
- setLayout(new BorderLayout());
-
- myConfiguration = configuration;
-
- mySettingsPanel = new JPanel();
- mySettingsPanel.setLayout(new BoxLayout(mySettingsPanel, BoxLayout.Y_AXIS));
-
- add(mySettingsPanel, BorderLayout.NORTH);
-
- createIndividualSettings(BrowsersConfiguration.BrowserFamily.FIREFOX, mySettingsPanel);
- createIndividualSettings(BrowsersConfiguration.BrowserFamily.EXPLORER, mySettingsPanel);
- createIndividualSettings(BrowsersConfiguration.BrowserFamily.SAFARI, mySettingsPanel);
- createIndividualSettings(BrowsersConfiguration.BrowserFamily.CHROME, mySettingsPanel);
- createIndividualSettings(BrowsersConfiguration.BrowserFamily.OPERA, mySettingsPanel);
-
- createPlatformSpecificAction(mySettingsPanel);
- }
-
- private void createIndividualSettings(@NotNull final BrowsersConfiguration.BrowserFamily family, final JPanel container) {
- final JPanel result = new JPanel();
-
- result.setBorder(IdeBorderFactory.createTitledBorder(family.getName(), true));
-
- result.setLayout(new BoxLayout(result, BoxLayout.Y_AXIS));
-
- final TextFieldWithBrowseButton field = new TextFieldWithBrowseButton();
- FileChooserDescriptor descriptor = SystemInfo.isMac
- ? FileChooserDescriptorFactory.createSingleFolderDescriptor()
- : FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
- field.addBrowseFolderListener(IdeBundle.message("title.select.path.to.browser"), null, null, descriptor);
-
- result.add(field);
-
- final JPanel bottomPanel = new JPanel(new BorderLayout());
-
- final JPanel activePanel = new JPanel();
- activePanel.setLayout(new BoxLayout(activePanel, BoxLayout.X_AXIS));
-
- final JCheckBox checkBox = new JCheckBox();
- activePanel.add(checkBox);
- final JLabel label = new JLabel(XmlBundle.message("browser.active"));
- label.setLabelFor(checkBox);
- activePanel.add(label);
- bottomPanel.add(activePanel, BorderLayout.WEST);
-
- final JButton resetButton = new JButton(XmlBundle.message("browser.default.settings"));
- resetButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(final ActionEvent e) {
- field.getTextField().setText(family.getExecutionPath());
- }
- });
-
- JPanel buttonsPanel = new JPanel(new BorderLayout());
- if (family.createBrowserSpecificSettings() != null) {
- final JButton editSettingsButton = new JButton(XmlBundle.message("button.text.settings"));
- editSettingsButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- editSettings(family);
- }
- });
- buttonsPanel.add(editSettingsButton, BorderLayout.CENTER);
- }
- buttonsPanel.add(resetButton, BorderLayout.EAST);
-
- bottomPanel.add(buttonsPanel, BorderLayout.EAST);
-
- result.add(bottomPanel);
- container.add(result);
-
- final WebBrowserSettings settings = myConfiguration.getBrowserSettings(family);
- field.getTextField().setText(settings.getPath());
- checkBox.setSelected(settings.isActive());
-
- myBrowserSettingsMap.put(family, Pair.create(checkBox, field));
- }
-
- private void editSettings(BrowsersConfiguration.BrowserFamily family) {
- BrowserSpecificSettings settings = myConfiguration.getBrowserSettings(family).getBrowserSpecificSettings();
- if (settings == null) {
- settings = family.createBrowserSpecificSettings();
- }
- if (settings != null && ShowSettingsUtil.getInstance().editConfigurable(mySettingsPanel, settings.createConfigurable())) {
- myConfiguration.updateBrowserSpecificSettings(family, settings);
- }
- }
-
- private void createPlatformSpecificAction(JPanel container) {
- if (SystemInfo.isWindows) {
- JButton registryButton = new JButton(XmlBundle.message("read.win.registry"));
- registryButton.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- applySettingsFromWindowsRegistry();
- }
- });
-
- JPanel panel = new JPanel(new BorderLayout());
- panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
- panel.add(registryButton, BorderLayout.EAST);
- container.add(panel);
- }
- }
-
- private void applySettingsFromWindowsRegistry() {
- ApplicationManager.getApplication().executeOnPooledThread(new SwingWorker<Map<BrowsersConfiguration.BrowserFamily, String>, Void>() {
- @Override
- protected Map<BrowsersConfiguration.BrowserFamily, String> doInBackground() throws Exception {
- return BrowserConfigurationHelper.getBrowserPathsFromRegistry();
- }
-
- @Override
- protected void done() {
- Map<BrowsersConfiguration.BrowserFamily, String> map = null;
- try {
- map = get();
- }
- catch (InterruptedException ignore) { }
- catch (ExecutionException ignore) { }
-
- if (myBrowserSettingsMap == null || map == null || map.isEmpty()) {
- return;
- }
-
- for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) {
- Pair<JCheckBox, TextFieldWithBrowseButton> pair = myBrowserSettingsMap.get(family);
- String pathToExe = map.get(family);
- if (pathToExe != null) {
- pair.first.setSelected(true);
- pair.second.setText(pathToExe);
- }
- else {
- pair.first.setSelected(false);
- }
- }
- }
- });
- }
-
- public void dispose() {
- myBrowserSettingsMap = null;
- }
-
- public boolean isModified() {
- for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) {
- final WebBrowserSettings old = myConfiguration.getBrowserSettings(family);
- final Pair<JCheckBox, TextFieldWithBrowseButton> settings = myBrowserSettingsMap.get(family);
-
- if (old.isActive() != settings.first.isSelected() || !old.getPath().equals(settings.second.getText())) {
- return true;
- }
- }
-
- return false;
- }
-
- public void apply() {
- for (BrowsersConfiguration.BrowserFamily family : myBrowserSettingsMap.keySet()) {
- final Pair<JCheckBox, TextFieldWithBrowseButton> buttonPair = myBrowserSettingsMap.get(family);
- myConfiguration.updateBrowserValue(family, buttonPair.second.getText(), buttonPair.first.isSelected());
- }
- }
-
- public void reset() {
- for (BrowsersConfiguration.BrowserFamily family : myBrowserSettingsMap.keySet()) {
- final Pair<JCheckBox, TextFieldWithBrowseButton> buttonPair = myBrowserSettingsMap.get(family);
- final WebBrowserSettings settings = myConfiguration.getBrowserSettings(family);
- buttonPair.first.setSelected(settings.isActive());
- buttonPair.second.getTextField().setText(settings.getPath());
- }
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
new file mode 100644
index 0000000..ac6b476
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/BaseOpenInBrowserAction.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers.actions;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.browsers.*;
+import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
+import com.intellij.openapi.actionSystem.*;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.keymap.KeymapManager;
+import com.intellij.openapi.keymap.KeymapUtil;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.popup.JBPopupFactory;
+import com.intellij.openapi.util.AsyncResult;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiDocumentManager;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.psi.PsiManager;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.ui.ColoredListCellRenderer;
+import com.intellij.ui.components.JBList;
+import com.intellij.util.Consumer;
+import com.intellij.util.ObjectUtils;
+import com.intellij.util.Url;
+import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import javax.swing.*;
+import java.awt.event.InputEvent;
+import java.util.Collection;
+
+public abstract class BaseOpenInBrowserAction extends DumbAwareAction {
+ private static final Logger LOG = Logger.getInstance(BaseOpenInBrowserAction.class);
+
+ protected BaseOpenInBrowserAction(@NotNull WebBrowser browser) {
+ super(browser.getName(), null, browser.getIcon());
+ }
+
+ @SuppressWarnings("UnusedDeclaration")
+ protected BaseOpenInBrowserAction(@Nullable String text, @Nullable String description, @Nullable Icon icon) {
+ super(text, description, icon);
+ }
+
+ @Nullable
+ protected abstract WebBrowser getBrowser(@NotNull AnActionEvent event);
+
+ @Override
+ public final void update(AnActionEvent e) {
+ WebBrowser browser = getBrowser(e);
+ if (browser == null) {
+ e.getPresentation().setEnabledAndVisible(false);
+ return;
+ }
+
+ Pair<OpenInBrowserRequest, WebBrowserUrlProvider> result = doUpdate(e);
+ if (result == null) {
+ return;
+ }
+
+ String description = getTemplatePresentation().getText();
+ if (ActionPlaces.CONTEXT_TOOLBAR.equals(e.getPlace())) {
+ StringBuilder builder = new StringBuilder(description);
+ builder.append(" (");
+ Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts("WebOpenInAction");
+ if (shortcuts.length > 0) {
+ builder.append(KeymapUtil.getShortcutText(shortcuts[0]));
+ }
+
+ if (HtmlUtil.isHtmlFile(result.first.getFile())) {
+ builder.append(", hold Shift to open URL of local file");
+ }
+ builder.append(')');
+ description = builder.toString();
+ }
+ e.getPresentation().setText(description);
+ }
+
+ @Override
+ public final void actionPerformed(AnActionEvent e) {
+ WebBrowser browser = getBrowser(e);
+ if (browser != null) {
+ open(e, browser);
+ }
+ }
+
+ @Nullable
+ public static OpenInBrowserRequest createRequest(@NotNull DataContext context) {
+ final Editor editor = CommonDataKeys.EDITOR.getData(context);
+ if (editor != null) {
+ Project project = editor.getProject();
+ if (project != null && project.isInitialized()) {
+ PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(context);
+ if (psiFile == null) {
+ psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
+ }
+ if (psiFile != null) {
+ return new OpenInBrowserRequest(psiFile) {
+ private PsiElement element;
+
+ @NotNull
+ @Override
+ public PsiElement getElement() {
+ if (element == null) {
+ element = getFile().findElementAt(editor.getCaretModel().getOffset());
+ }
+ return ObjectUtils.chooseNotNull(element, getFile());
+ }
+ };
+ }
+ }
+ }
+ else {
+ final PsiFile psiFile = CommonDataKeys.PSI_FILE.getData(context);
+ if (psiFile != null) {
+ return OpenInBrowserRequest.create(psiFile);
+ }
+
+ final VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(context);
+ final Project project = CommonDataKeys.PROJECT.getData(context);
+ if (virtualFile != null && !virtualFile.isDirectory() && virtualFile.isValid() && project != null && project.isInitialized()) {
+ return new OpenInBrowserRequest() {
+ @NotNull
+ @Override
+ public VirtualFile getVirtualFile() {
+ return virtualFile;
+ }
+
+ @NotNull
+ @Override
+ public Project getProject() {
+ return project;
+ }
+
+ @NotNull
+ @Override
+ public PsiElement getElement() {
+ return getFile();
+ }
+
+ @NotNull
+ @Override
+ public PsiFile getFile() {
+ if (file == null) {
+ file = PsiManager.getInstance(getProject()).findFile(virtualFile);
+ LOG.assertTrue(file != null, virtualFile.getPath());
+ }
+ return file;
+ }
+ };
+ }
+ }
+ return null;
+ }
+
+ @Nullable
+ public static Pair<OpenInBrowserRequest, WebBrowserUrlProvider> doUpdate(@NotNull AnActionEvent event) {
+ OpenInBrowserRequest request = createRequest(event.getDataContext());
+ boolean applicable = false;
+ WebBrowserUrlProvider provider = null;
+ if (request != null) {
+ applicable = HtmlUtil.isHtmlFile(request.getFile()) && !(request.getVirtualFile() instanceof LightVirtualFile);
+ if (!applicable) {
+ provider = WebBrowserServiceImpl.getProvider(request);
+ applicable = provider != null;
+ }
+ }
+
+ event.getPresentation().setEnabledAndVisible(applicable);
+ return applicable ? Pair.create(request, provider) : null;
+ }
+
+ public static void open(@NotNull AnActionEvent event, @Nullable WebBrowser browser) {
+ open(createRequest(event.getDataContext()), (event.getModifiers() & InputEvent.SHIFT_MASK) != 0, browser);
+ }
+
+ public static void open(@Nullable final OpenInBrowserRequest request, boolean preferLocalUrl, @Nullable final WebBrowser browser) {
+ if (request == null) {
+ return;
+ }
+
+ try {
+ Collection<Url> urls = WebBrowserService.getInstance().getUrlsToOpen(request, preferLocalUrl);
+ if (!urls.isEmpty()) {
+ chooseUrl(urls).doWhenDone(new Consumer<Url>() {
+ @Override
+ public void consume(Url url) {
+ ApplicationManager.getApplication().saveAll();
+ BrowserLauncher.getInstance().browse(url.toExternalForm(), browser, request.getProject());
+ }
+ });
+ }
+ }
+ catch (WebBrowserUrlProvider.BrowserException e1) {
+ Messages.showErrorDialog(e1.getMessage(), IdeBundle.message("browser.error"));
+ }
+ catch (Exception e1) {
+ LOG.error(e1);
+ }
+ }
+
+ @NotNull
+ private static AsyncResult<Url> chooseUrl(@NotNull Collection<Url> urls) {
+ if (urls.size() == 1) {
+ return new AsyncResult.Done<Url>(ContainerUtil.getFirstItem(urls));
+ }
+
+ final JBList list = new JBList(urls);
+ list.setCellRenderer(new ColoredListCellRenderer() {
+ @Override
+ protected void customizeCellRenderer(JList list, Object value, int index, boolean selected, boolean hasFocus) {
+ // todo icons looks good, but is it really suitable for all URLs providers?
+ setIcon(AllIcons.Nodes.Servlet);
+ append(((Url)value).toDecodedForm());
+ }
+ });
+
+ final AsyncResult<Url> result = new AsyncResult<Url>();
+ JBPopupFactory.getInstance().
+ createListPopupBuilder(list).
+ setTitle("Choose Url").
+ setItemChoosenCallback(new Runnable() {
+ @Override
+ public void run() {
+ Url value = (Url)list.getSelectedValue();
+ if (value != null) {
+ result.setDone(value);
+ }
+ else {
+ result.setRejected();
+ }
+ }
+ }).
+ createPopup().showInFocusCenter();
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/BaseWebBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/BaseWebBrowserAction.java
new file mode 100644
index 0000000..48de5c0
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/BaseWebBrowserAction.java
@@ -0,0 +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.ide.browsers.actions;
+
+import com.intellij.ide.browsers.WebBrowser;
+import com.intellij.ide.browsers.WebBrowserManager;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+final class BaseWebBrowserAction extends BaseOpenInBrowserAction {
+ private final WebBrowser browser;
+
+ public BaseWebBrowserAction(@NotNull WebBrowser browser) {
+ super(browser);
+
+ this.browser = browser;
+ }
+
+ @Nullable
+ @Override
+ protected WebBrowser getBrowser(@NotNull AnActionEvent event) {
+ return WebBrowserManager.getInstance().isActive(browser) && browser.getPath() != null ? browser : null;
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.java
new file mode 100644
index 0000000..45cf021
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenFileInDefaultBrowserAction.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 com.intellij.ide.browsers.actions;
+
+import com.intellij.ide.GeneralSettings;
+import com.intellij.ide.browsers.OpenInBrowserRequest;
+import com.intellij.ide.browsers.WebBrowser;
+import com.intellij.ide.browsers.WebBrowserManager;
+import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.openapi.actionSystem.ActionPlaces;
+import com.intellij.openapi.actionSystem.AnActionEvent;
+import com.intellij.openapi.actionSystem.Presentation;
+import com.intellij.openapi.project.DumbAwareAction;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.xml.util.HtmlUtil;
+import org.jetbrains.annotations.Nullable;
+
+public class OpenFileInDefaultBrowserAction extends DumbAwareAction {
+ @Override
+ public void update(AnActionEvent e) {
+ Presentation presentation = e.getPresentation();
+
+ Pair<OpenInBrowserRequest, WebBrowserUrlProvider> result = BaseOpenInBrowserAction.doUpdate(e);
+ if (result == null) {
+ return;
+ }
+
+ WebBrowserUrlProvider browserUrlProvider = result.second;
+ String text = getTemplatePresentation().getText();
+ String description = getTemplatePresentation().getDescription();
+ if (browserUrlProvider != null) {
+ String customDescription = browserUrlProvider.getOpenInBrowserActionDescription(result.first.getFile());
+ if (customDescription != null) {
+ description = customDescription;
+ }
+ if (HtmlUtil.isHtmlFile(result.first.getFile())) {
+ description += " (hold Shift to open URL of local file)";
+ }
+ }
+
+ presentation.setText(text);
+ presentation.setDescription(description);
+
+ WebBrowser browser = findUsingBrowser();
+ if (browser != null) {
+ presentation.setIcon(browser.getIcon());
+ }
+
+ if (ActionPlaces.isPopupPlace(e.getPlace())) {
+ presentation.setVisible(presentation.isEnabled());
+ }
+ }
+
+ @Nullable
+ private static WebBrowser findUsingBrowser() {
+ WebBrowserManager browserManager = WebBrowserManager.getInstance();
+ if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.FIRST) {
+ return browserManager.getDefaultBrowser();
+ }
+ else if (browserManager.getDefaultBrowserMode() == WebBrowserManager.DefaultBrowser.ALTERNATIVE) {
+ String path = GeneralSettings.getInstance().getBrowserPath();
+ if (!StringUtil.isEmpty(path)) {
+ WebBrowser browser = browserManager.findBrowserById(path);
+ if (browser == null) {
+ for (WebBrowser item : browserManager.getActiveBrowsers()) {
+ if (path.equals(item.getPath())) {
+ return item;
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void actionPerformed(AnActionEvent e) {
+ BaseOpenInBrowserAction.open(e, findUsingBrowser());
+ }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.java b/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.java
new file mode 100644
index 0000000..2d5409f
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/OpenInBrowserBaseGroupAction.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 com.intellij.ide.browsers.actions;
+
+import com.intellij.icons.AllIcons;
+import com.intellij.ide.browsers.WebBrowser;
+import com.intellij.ide.browsers.WebBrowserManager;
+import com.intellij.openapi.actionSystem.ActionManager;
+import com.intellij.openapi.actionSystem.AnAction;
+import com.intellij.openapi.actionSystem.ComputableActionGroup;
+import com.intellij.psi.util.CachedValueProvider;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.List;
+
+public abstract class OpenInBrowserBaseGroupAction extends ComputableActionGroup {
+ private OpenFileInDefaultBrowserAction myDefaultBrowserAction;
+
+ protected OpenInBrowserBaseGroupAction(boolean popup) {
+ super(popup);
+ }
+
+ @NotNull
+ @Override
+ protected final CachedValueProvider<AnAction[]> createChildrenProvider(@NotNull final ActionManager actionManager) {
+ return new CachedValueProvider<AnAction[]>() {
+ @Nullable
+ @Override
+ public Result<AnAction[]> compute() {
+ List<WebBrowser> browsers = WebBrowserManager.getInstance().getBrowsers();
+ boolean addDefaultBrowser = isPopup();
+ int offset = addDefaultBrowser ? 1 : 0;
+ AnAction[] actions = new AnAction[browsers.size() + offset];
+
+ if (addDefaultBrowser) {
+ if (myDefaultBrowserAction == null) {
+ myDefaultBrowserAction = new OpenFileInDefaultBrowserAction();
+ myDefaultBrowserAction.getTemplatePresentation().setText("Default");
+ myDefaultBrowserAction.getTemplatePresentation().setIcon(AllIcons.Nodes.PpWeb);
+ }
+ actions[0] = myDefaultBrowserAction;
+ }
+
+ for (int i = 0, size = browsers.size(); i < size; i++) {
+ actions[i + offset] = new BaseWebBrowserAction(browsers.get(i));
+ }
+
+ return Result.create(actions, WebBrowserManager.getInstance());
+ }
+ };
+ }
+
+ public static final class OpenInBrowserGroupAction extends OpenInBrowserBaseGroupAction {
+ public OpenInBrowserGroupAction() {
+ super(true);
+ }
+ }
+
+ public static final class OpenInBrowserEditorContextBarGroupAction extends OpenInBrowserBaseGroupAction {
+ public OpenInBrowserEditorContextBarGroupAction() {
+ super(false);
+ }
+ }
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/actions/SelectInDefaultBrowserTarget.java b/xml/impl/src/com/intellij/ide/browsers/actions/SelectInDefaultBrowserTarget.java
new file mode 100644
index 0000000..bb88451
--- /dev/null
+++ b/xml/impl/src/com/intellij/ide/browsers/actions/SelectInDefaultBrowserTarget.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2000-2014 JetBrains s.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.browsers.actions;
+
+import com.intellij.ide.SelectInContext;
+import com.intellij.ide.SelectInTargetBase;
+import com.intellij.ide.StandardTargetWeights;
+import com.intellij.ide.browsers.OpenInBrowserRequest;
+import com.intellij.ide.browsers.WebBrowserUrlProvider;
+import com.intellij.ide.browsers.impl.WebBrowserServiceImpl;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.testFramework.LightVirtualFile;
+import com.intellij.xml.XmlBundle;
+import com.intellij.xml.util.HtmlUtil;
+
+final class SelectInDefaultBrowserTarget extends SelectInTargetBase {
+ private static final Logger LOG = Logger.getInstance(SelectInDefaultBrowserTarget.class);
+
+ @Override
+ public boolean canSelect(SelectInContext context) {
+ Object selectorInFile = context.getSelectorInFile();
+ OpenInBrowserRequest request = selectorInFile instanceof PsiElement ? OpenInBrowserRequest.create((PsiElement)selectorInFile) : null;
+ if (request == null) {
+ return false;
+ }
+
+ WebBrowserUrlProvider urlProvider = WebBrowserServiceImpl.getProvider(request);
+ if (urlProvider == null) {
+ VirtualFile virtualFile = request.getVirtualFile();
+ return virtualFile instanceof HttpVirtualFile || (HtmlUtil.isHtmlFile(request.getFile()) && !(virtualFile instanceof LightVirtualFile));
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return XmlBundle.message("browser.select.in.default.name");
+ }
+
+ @Override
+ public void selectIn(SelectInContext context, boolean requestFocus) {
+ PsiElement element = (PsiElement)context.getSelectorInFile();
+ LOG.assertTrue(element != null);
+ BaseOpenInBrowserAction.open(OpenInBrowserRequest.create(element), false, null);
+ }
+
+ @Override
+ public float getWeight() {
+ return StandardTargetWeights.OS_FILE_MANAGER;
+ }
+}
diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
deleted file mode 100644
index 81f9044..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettings.java
+++ /dev/null
@@ -1,83 +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 com.intellij.ide.browsers.chrome;
-
-import com.intellij.execution.configurations.ParametersList;
-import com.intellij.ide.browsers.BrowserSpecificSettings;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.xmlb.annotations.Tag;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-/**
- * @author nik
- */
-public class ChromeSettings extends BrowserSpecificSettings {
- @NonNls public static final String USER_DATA_DIR_ARG = "--user-data-dir=";
- private String myCommandLineOptions = "";
- private String myUserDataDirectoryPath;
- private boolean myUseCustomProfile;
-
- public ChromeSettings() {
- }
-
- @Nullable
- @Tag("user-data-dir")
- public String getUserDataDirectoryPath() {
- return myUserDataDirectoryPath;
- }
-
- @Tag("use-custom-profile")
- public boolean isUseCustomProfile() {
- return myUseCustomProfile;
- }
-
- @Tag("command-line-options")
- public String getCommandLineOptions() {
- return myCommandLineOptions;
- }
-
- public void setCommandLineOptions(String commandLineOptions) {
- myCommandLineOptions = commandLineOptions;
- }
-
- public void setUserDataDirectoryPath(String userDataDirectoryPath) {
- myUserDataDirectoryPath = userDataDirectoryPath;
- }
-
- public void setUseCustomProfile(boolean useCustomProfile) {
- myUseCustomProfile = useCustomProfile;
- }
-
- @NotNull
- @Override
- public String[] getAdditionalParameters() {
- String[] cliOptions = ParametersList.parse(myCommandLineOptions);
- if (myUseCustomProfile && myUserDataDirectoryPath != null) {
- return ArrayUtil.mergeArrays(cliOptions, USER_DATA_DIR_ARG + FileUtil.toSystemDependentName(myUserDataDirectoryPath));
- }
- else {
- return cliOptions;
- }
- }
-
- @Override
- public ChromeSettingsConfigurable createConfigurable() {
- return new ChromeSettingsConfigurable(this);
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java b/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java
deleted file mode 100644
index 9e8b681..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/chrome/ChromeSettingsConfigurable.java
+++ /dev/null
@@ -1,135 +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 com.intellij.ide.browsers.chrome;
-
-import com.intellij.openapi.application.PathManager;
-import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.ui.RawCommandLineEditor;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.io.File;
-import java.io.IOException;
-
-/**
- * @author nik
- */
-public class ChromeSettingsConfigurable implements Configurable {
- private final ChromeSettings mySettings;
- private JPanel myMainPanel;
- private JCheckBox myUseCustomProfileCheckBox;
- private TextFieldWithBrowseButton myUserDataDirField;
- private JLabel myCommandLineOptionsLabel;
- private RawCommandLineEditor myCommandLineOptionsEditor;
- private final String myDefaultUserDirPath;
-
- public ChromeSettingsConfigurable(@NotNull ChromeSettings settings) {
- mySettings = settings;
- myUserDataDirField.addBrowseFolderListener("Select User Data Directory", "Specifies the directory that user data (your \"profile\") is kept in", null,
- FileChooserDescriptorFactory.createSingleFolderDescriptor());
- myUseCustomProfileCheckBox.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- myUserDataDirField.setEnabled(myUseCustomProfileCheckBox.isSelected());
- }
- });
- myDefaultUserDirPath = getDefaultUserDataPath();
- myCommandLineOptionsEditor.setDialogCaption("Chrome Command Line Options");
- myCommandLineOptionsLabel.setLabelFor(myCommandLineOptionsEditor.getTextField());
- }
-
- @Override
- public JComponent createComponent() {
- return myMainPanel;
- }
-
- @Override
- public boolean isModified() {
- if (myUseCustomProfileCheckBox.isSelected() != mySettings.isUseCustomProfile()
- || !myCommandLineOptionsEditor.getText().equals(mySettings.getCommandLineOptions())) {
- return true;
- }
-
- String configuredPath = getConfiguredUserDataDirPath();
- String storedPath = mySettings.getUserDataDirectoryPath();
- if (myDefaultUserDirPath.equals(configuredPath) && storedPath == null) return false;
- return !configuredPath.equals(storedPath);
- }
-
-
- private String getConfiguredUserDataDirPath() {
- return FileUtil.toSystemIndependentName(myUserDataDirField.getText());
- }
-
- @Override
- public void apply() throws ConfigurationException {
- mySettings.setCommandLineOptions(myCommandLineOptionsEditor.getText());
- mySettings.setUseCustomProfile(myUseCustomProfileCheckBox.isSelected());
- mySettings.setUserDataDirectoryPath(getConfiguredUserDataDirPath());
- }
-
- @Override
- public void reset() {
- myCommandLineOptionsEditor.setText(mySettings.getCommandLineOptions());
- myUseCustomProfileCheckBox.setSelected(mySettings.isUseCustomProfile());
- myUserDataDirField.setEnabled(mySettings.isUseCustomProfile());
- String path = mySettings.getUserDataDirectoryPath();
- if (path != null) {
- myUserDataDirField.setText(FileUtil.toSystemDependentName(path));
- }
- else {
- myUserDataDirField.setText(myDefaultUserDirPath);
- }
- }
-
- public void enableRecommendedOptions() {
- if (!myUseCustomProfileCheckBox.isSelected()) {
- myUseCustomProfileCheckBox.doClick(0);
- }
- }
-
- private static String getDefaultUserDataPath() {
- File dir = new File(PathManager.getConfigPath(), "chrome-user-data");
- try {
- return dir.getCanonicalPath();
- }
- catch (IOException e) {
- return dir.getAbsolutePath();
- }
- }
-
- @Override
- public void disposeUIResources() {
- }
-
- @Nls
- @Override
- public String getDisplayName() {
- return "Chrome Settings";
- }
-
- @Override
- public String getHelpTopic() {
- return null;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java
deleted file mode 100644
index 618a015..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettings.java
+++ /dev/null
@@ -1,89 +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.ide.browsers.firefox;
-
-import com.intellij.ide.browsers.BrowserSpecificSettings;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.util.xmlb.annotations.Tag;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.NotNull;
-
-import java.io.File;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class FirefoxSettings extends BrowserSpecificSettings {
- private String myProfilesIniPath;
- private String myProfile;
-
- public FirefoxSettings() {
- }
-
- public FirefoxSettings(String profilesIniPath, String profile) {
- myProfilesIniPath = profilesIniPath;
- myProfile = profile;
- }
-
- @Nullable
- @Tag("profiles-ini-path")
- public String getProfilesIniPath() {
- return myProfilesIniPath;
- }
-
- public void setProfilesIniPath(String profilesIniPath) {
- myProfilesIniPath = profilesIniPath;
- }
-
- @Nullable
- @Tag("profile")
- public String getProfile() {
- return myProfile;
- }
-
- public void setProfile(String profile) {
- myProfile = profile;
- }
-
- @Override
- public Configurable createConfigurable() {
- return new FirefoxSettingsConfigurable(this);
- }
-
- @Nullable
- public File getProfilesIniFile() {
- if (myProfilesIniPath != null) {
- return new File(FileUtil.toSystemDependentName(myProfilesIniPath));
- }
- return FirefoxUtil.getDefaultProfileIniPath();
- }
-
- @NotNull
- @Override
- public String[] getAdditionalParameters() {
- final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(getProfilesIniFile());
- if (profiles.size() >= 2) {
- final FirefoxProfile profile = FirefoxUtil.findProfileByNameOrDefault(myProfile, profiles);
- if (profile != null && !profile.isDefault()) {
- return new String[] {"-P", profile.getName()};
- }
- }
- return ArrayUtil.EMPTY_STRING_ARRAY;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form
deleted file mode 100644
index bd1e753..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.form
+++ /dev/null
@@ -1,89 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.ide.browsers.firefox.FirefoxSettingsConfigurable">
- <grid id="27dc6" binding="myMainPanel" 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>
- <xy x="20" y="20" width="500" height="400"/>
- </constraints>
- <properties/>
- <border type="none"/>
- <children>
- <vspacer id="90b50">
- <constraints>
- <grid row="1" 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="735f0" 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>
- <grid row="0" 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 id="f9834" layout-manager="GridLayoutManager" row-count="1" 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="0" 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>
- <component id="852e3" class="javax.swing.JLabel">
- <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>
- <text resource-bundle="messages/XmlBundle" key="label.text.path.to.profiles.ini"/>
- </properties>
- </component>
- <hspacer id="d637d">
- <constraints>
- <grid row="0" 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>
- </children>
- </grid>
- <component id="a31a5" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myProfilesIniPathField">
- <constraints>
- <grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="2" use-parent-layout="false">
- <preferred-size width="350" height="-1"/>
- </grid>
- </constraints>
- <properties/>
- </component>
- <grid id="baf65" layout-manager="GridLayoutManager" row-count="1" 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="2" 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>
- <component id="11a5c" class="javax.swing.JLabel">
- <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="c6e14"/>
- <text resource-bundle="messages/XmlBundle" key="label.text.profile"/>
- </properties>
- </component>
- <hspacer id="d3289">
- <constraints>
- <grid row="0" column="2" 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="c6e14" class="javax.swing.JComboBox" binding="myProfileCombobox">
- <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"/>
- </constraints>
- <properties/>
- </component>
- </children>
- </grid>
- </children>
- </grid>
- </children>
- </grid>
-</form>
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
deleted file mode 100644
index fb92f51..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxSettingsConfigurable.java
+++ /dev/null
@@ -1,143 +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.ide.browsers.firefox;
-
-import com.intellij.openapi.fileChooser.FileChooserDescriptor;
-import com.intellij.openapi.options.Configurable;
-import com.intellij.openapi.options.ConfigurationException;
-import com.intellij.openapi.ui.TextFieldWithBrowseButton;
-import com.intellij.openapi.util.Comparing;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.VirtualFile;
-import com.intellij.ui.DocumentAdapter;
-import com.intellij.xml.XmlBundle;
-import org.jetbrains.annotations.Nls;
-import org.jetbrains.annotations.Nullable;
-
-import javax.swing.*;
-import javax.swing.event.DocumentEvent;
-import java.io.File;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class FirefoxSettingsConfigurable implements Configurable {
- private static final FileChooserDescriptor PROFILES_INI_CHOOSER_DESCRIPTOR = createProfilesIniChooserDescriptor();
-
- private JPanel myMainPanel;
- private JComboBox myProfileCombobox;
- private TextFieldWithBrowseButton myProfilesIniPathField;
- private final FirefoxSettings mySettings;
- private String myLastProfilesIniPath;
- private String myDefaultProfilesIniPath;
- private String myDefaultProfile;
-
- public FirefoxSettingsConfigurable(FirefoxSettings settings) {
- mySettings = settings;
- myProfilesIniPathField.addBrowseFolderListener(XmlBundle.message("chooser.title.select.profiles.ini.file"), null, null, PROFILES_INI_CHOOSER_DESCRIPTOR);
- myProfilesIniPathField.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
- @Override
- protected void textChanged(DocumentEvent e) {
- updateProfilesList();
- }
- });
- }
-
- public static FileChooserDescriptor createProfilesIniChooserDescriptor() {
- return new FileChooserDescriptor(true, false, false, false, false, false) {
- @Override
- public boolean isFileVisible(VirtualFile file, boolean showHiddenFiles) {
- if (!file.isDirectory() && !file.getName().equals(FirefoxUtil.PROFILES_INI_FILE)) {
- return false;
- }
- return super.isFileVisible(file, showHiddenFiles);
- }
- };
- }
-
- public JComponent createComponent() {
- return myMainPanel;
- }
-
- public boolean isModified() {
- return !Comparing.equal(mySettings.getProfile(), getConfiguredProfileName()) ||
- !Comparing.equal(mySettings.getProfilesIniPath(), getConfiguredProfileIniPath());
- }
-
- @Nullable
- private String getConfiguredProfileIniPath() {
- final String path = myProfilesIniPathField.getText();
- if (myDefaultProfilesIniPath.equals(path)) {
- return null;
- }
- return FileUtil.toSystemIndependentName(path);
- }
-
- @Nullable
- private String getConfiguredProfileName() {
- final String selected = (String)myProfileCombobox.getSelectedItem();
- if (Comparing.equal(myDefaultProfile, selected)) {
- return null;
- }
- return selected;
- }
-
- public void apply() throws ConfigurationException {
- mySettings.setProfile(getConfiguredProfileName());
- mySettings.setProfilesIniPath(getConfiguredProfileIniPath());
- }
-
- public void reset() {
- final File defaultFile = FirefoxUtil.getDefaultProfileIniPath();
- myDefaultProfilesIniPath = defaultFile != null ? defaultFile.getAbsolutePath() : "";
-
- final String path = mySettings.getProfilesIniPath();
- myProfilesIniPathField.setText(path != null ? FileUtil.toSystemDependentName(path) : myDefaultProfilesIniPath);
- updateProfilesList();
- final String profileName = mySettings.getProfile();
- myProfileCombobox.setSelectedItem(profileName != null ? profileName : myDefaultProfile);
- }
-
- private void updateProfilesList() {
- final String profilesIniPath = myProfilesIniPathField.getText();
- if (myLastProfilesIniPath != null && myLastProfilesIniPath.equals(profilesIniPath)) return;
-
- myProfileCombobox.removeAllItems();
- final List<FirefoxProfile> profiles = FirefoxUtil.computeProfiles(new File(profilesIniPath));
- final FirefoxProfile defaultProfile = FirefoxUtil.getDefaultProfile(profiles);
- myDefaultProfile = defaultProfile != null ? defaultProfile.getName() : null;
- for (FirefoxProfile profile : profiles) {
- myProfileCombobox.addItem(profile.getName());
- }
- if (!profiles.isEmpty()) {
- myProfileCombobox.setSelectedIndex(0);
- }
- myLastProfilesIniPath = profilesIniPath;
- }
-
- public void disposeUIResources() {
- }
-
- @Nls
- public String getDisplayName() {
- return XmlBundle.message("display.name.firefox.settings");
- }
-
- public String getHelpTopic() {
- return null;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java b/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java
deleted file mode 100644
index 5541052..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/firefox/FirefoxUtil.java
+++ /dev/null
@@ -1,181 +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.ide.browsers.firefox;
-
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.SystemProperties;
-import org.jetbrains.annotations.NonNls;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * @author nik
- */
-public class FirefoxUtil {
- private static final Logger LOG = Logger.getInstance("#com.intellij.ide.browsers.firefox.FirefoxUtil");
- @NonNls public static final String PROFILES_INI_FILE = "profiles.ini";
-
- private FirefoxUtil() {
- }
-
- @Nullable
- public static File getDefaultProfileIniPath() {
- File[] roots = getProfilesDirs();
- for (File profilesDir : roots) {
- File profilesFile = new File(profilesDir, PROFILES_INI_FILE);
- if (profilesFile.isFile()) {
- return profilesFile;
- }
- }
- return null;
- }
-
- @Nullable
- public static File getFirefoxExtensionsDir(FirefoxSettings settings) {
- File profilesFile = settings.getProfilesIniFile();
- if (profilesFile != null && profilesFile.exists()) {
- List<FirefoxProfile> profiles = computeProfiles(profilesFile);
- FirefoxProfile profile = findProfileByNameOrDefault(settings.getProfile(), profiles);
- if (profile != null) {
- File profileDir = profile.getProfileDirectory(profilesFile);
- if (profileDir.isDirectory()) {
- return new File(profileDir, "extensions");
- }
- }
- }
- return null;
- }
-
- @Nullable
- public static FirefoxProfile findProfileByNameOrDefault(@Nullable String name, List<FirefoxProfile> profiles) {
- for (FirefoxProfile profile : profiles) {
- if (profile.getName().equals(name)) {
- return profile;
- }
- }
- return getDefaultProfile(profiles);
- }
-
- @Nullable
- public static FirefoxProfile getDefaultProfile(List<FirefoxProfile> profiles) {
- if (profiles.isEmpty()) return null;
-
- for (FirefoxProfile profile : profiles) {
- if (profile.isDefault()) {
- return profile;
- }
- }
- return profiles.get(0);
- }
-
- @NotNull
- public static List<FirefoxProfile> computeProfiles(File profilesFile) {
- if (!profilesFile.isFile()) {
- return Collections.emptyList();
- }
-
- try {
- BufferedReader reader = new BufferedReader(new FileReader(profilesFile));
- try {
- final List<FirefoxProfile> profiles = new ArrayList<FirefoxProfile>();
- boolean insideProfile = false;
- String currentName = null;
- String currentPath = null;
- boolean isDefault = false;
- boolean isRelative = false;
- boolean eof = false;
- while (!eof) {
- @NonNls String line = reader.readLine();
- if (line == null) {
- eof = true;
- line = "[]";
- }
- else {
- line = line.trim();
- }
-
- if (line.startsWith("[") && line.endsWith("]")) {
- if (!StringUtil.isEmpty(currentPath) && !StringUtil.isEmpty(currentName)) {
- profiles.add(new FirefoxProfile(currentName, currentPath, isDefault, isRelative));
- }
- currentName = null;
- currentPath = null;
- isDefault = false;
- isRelative = false;
- insideProfile = StringUtil.startsWithIgnoreCase(line, "[Profile");
- continue;
- }
-
- final int i = line.indexOf('=');
- if (i != -1 && insideProfile) {
- @NonNls String name = line.substring(0, i).trim();
- @NonNls String value = line.substring(i + 1).trim();
- if (name.equalsIgnoreCase("path")) {
- currentPath = value;
- }
- else if (name.equalsIgnoreCase("name")) {
- currentName = value;
- }
- else if (name.equalsIgnoreCase("default") && value.equals("1")) {
- isDefault = true;
- }
- else if (name.equalsIgnoreCase("isrelative") && value.equals("1")) {
- isRelative = true;
- }
- }
- }
- return profiles;
- }
- finally {
- reader.close();
- }
- }
- catch (IOException e) {
- LOG.info(e);
- }
- return Collections.emptyList();
- }
-
- private static File[] getProfilesDirs() {
- final String userHome = SystemProperties.getUserHome();
- if (SystemInfo.isMac) {
- return new File[] {
- new File(userHome, "Library" + File.separator + "Mozilla" + File.separator + "Firefox"),
- new File(userHome, "Library" + File.separator + "Application Support" + File.separator + "Firefox"),
- };
- }
- if (SystemInfo.isUnix) {
- return new File[] {new File(userHome, ".mozilla" + File.separator + "firefox")};
- }
-
- String localPath = "Mozilla" + File.separator + "Firefox";
- return new File[] {
- new File(System.getenv("APPDATA"), localPath),
- new File(userHome, "AppData" + File.separator + "Roaming" + File.separator + localPath),
- new File(userHome, "Application Data" + File.separator + localPath)
- };
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java
index c534910..dc08f2c 100644
--- a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserConfigurationHelper.java
@@ -15,7 +15,7 @@
*/
package com.intellij.ide.browsers.impl;
-import com.intellij.ide.browsers.BrowsersConfiguration;
+import com.intellij.ide.browsers.BrowserFamily;
import com.intellij.openapi.util.io.WindowsRegistryUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -32,13 +32,13 @@
* Read data from Windows registry (may take some time to run).
*/
@NotNull
- public static Map<BrowsersConfiguration.BrowserFamily, String> getBrowserPathsFromRegistry() {
- Map<BrowsersConfiguration.BrowserFamily, String> map =
- new EnumMap<BrowsersConfiguration.BrowserFamily, String>(BrowsersConfiguration.BrowserFamily.class);
+ public static Map<BrowserFamily, String> getBrowserPathsFromRegistry() {
+ Map<BrowserFamily, String> map =
+ new EnumMap<BrowserFamily, String>(BrowserFamily.class);
List<String> sections = WindowsRegistryUtil.readRegistryBranch(START_MENU_KEY);
for (String section : sections) {
- BrowsersConfiguration.BrowserFamily family = getFamily(section);
+ BrowserFamily family = getFamily(section);
if (family != null) {
String pathToExe = WindowsRegistryUtil.readRegistryDefault(START_MENU_KEY + "\\" + section + "\\shell\\open\\command");
if (pathToExe != null) {
@@ -51,9 +51,9 @@
}
@Nullable
- private static BrowsersConfiguration.BrowserFamily getFamily(String registryName) {
+ private static BrowserFamily getFamily(String registryName) {
registryName = registryName.toLowerCase();
- for (BrowsersConfiguration.BrowserFamily family : BrowsersConfiguration.BrowserFamily.values()) {
+ for (BrowserFamily family : BrowserFamily.values()) {
if (registryName.contains(family.getName().toLowerCase(Locale.US))) {
return family;
}
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java
deleted file mode 100644
index 11ee96f..0000000
--- a/xml/impl/src/com/intellij/ide/browsers/impl/BrowserSettingsProviderImpl.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2000-2013 JetBrains s.r.o.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.intellij.ide.browsers.impl;
-
-import com.intellij.ide.BrowserSettingsProvider;
-import com.intellij.ide.browsers.BrowsersConfiguration;
-import com.intellij.ide.browsers.WebBrowsersPanel;
-import com.intellij.openapi.options.ConfigurationException;
-import org.jetbrains.annotations.NotNull;
-
-import javax.swing.*;
-
-/**
- * @author spleaner
- */
-public class BrowserSettingsProviderImpl extends BrowserSettingsProvider {
- private WebBrowsersPanel mySettingsPanel;
- private final BrowsersConfiguration myConfiguration;
-
- public BrowserSettingsProviderImpl(@NotNull final BrowsersConfiguration configuration) {
- myConfiguration = configuration;
- }
-
- public JComponent createComponent() {
- if (mySettingsPanel == null) {
- mySettingsPanel = new WebBrowsersPanel(myConfiguration);
- }
-
- return mySettingsPanel;
- }
-
- public boolean isModified() {
- return mySettingsPanel != null && mySettingsPanel.isModified();
- }
-
- public void apply() throws ConfigurationException {
- mySettingsPanel.apply();
- }
-
- public void reset() {
- mySettingsPanel.reset();
- }
-
- public void disposeUIResources() {
- mySettingsPanel.dispose();
- mySettingsPanel = null;
- }
-}
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java
index 07f221f..20c9264 100644
--- a/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.java
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/DefaultUrlOpener.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,98 +15,16 @@
*/
package com.intellij.ide.browsers.impl;
-import com.intellij.CommonBundle;
-import com.intellij.execution.ExecutionException;
-import com.intellij.execution.configurations.GeneralCommandLine;
-import com.intellij.execution.util.ExecUtil;
-import com.intellij.ide.BrowserUtil;
-import com.intellij.ide.IdeBundle;
-import com.intellij.ide.browsers.*;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.ui.Messages;
-import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
-import com.intellij.xml.XmlBundle;
+import com.intellij.ide.browsers.BrowserLauncher;
+import com.intellij.ide.browsers.UrlOpener;
+import com.intellij.ide.browsers.WebBrowser;
+import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-public class DefaultUrlOpener extends UrlOpener {
- private static final Logger LOG = Logger.getInstance(DefaultUrlOpener.class);
-
- public boolean openUrl(final @NotNull WebBrowser browser, final @NotNull String url) {
- return launchBrowser(browser, url, false);
+final class DefaultUrlOpener extends UrlOpener {
+ @Override
+ public boolean openUrl(@NotNull WebBrowser browser, @NotNull String url, @Nullable Project project) {
+ return BrowserLauncher.getInstance().browseUsingPath(url, null, browser, project);
}
-
- public static boolean launchBrowser(@NotNull WebBrowser browser,
- @Nullable String url,
- boolean newWindowIfPossible,
- @NotNull String... additionalParameters) {
- final String browserPath = browser.getPath();
- if (StringUtil.isEmptyOrSpaces(browserPath)) {
- Messages.showErrorDialog(browser.getBrowserNotFoundMessage(), IdeBundle.message("title.browser.not.found"));
- return false;
- }
-
- return doLaunchBrowser(browserPath, browser.getBrowserSpecificSettings(), url, newWindowIfPossible, additionalParameters);
- }
-
- public static boolean launchBrowser(@NotNull BrowsersConfiguration.BrowserFamily family,
- @Nullable String url,
- boolean newWindowIfPossible,
- @NotNull String... additionalParameters) {
- WebBrowserSettings settings = BrowsersConfiguration.getInstance().getBrowserSettings(family);
- String browserPath = settings.getPath();
- if (StringUtil.isEmpty(browserPath)) {
- String message = IdeBundle.message("error.0.browser.path.not.specified", family.getName(), CommonBundle.settingsActionPath());
- Messages.showErrorDialog(message, IdeBundle.message("title.browser.not.found"));
- return false;
- }
-
- return doLaunchBrowser(browserPath, settings.getBrowserSpecificSettings(), url, newWindowIfPossible, additionalParameters);
- }
-
- private static boolean doLaunchBrowser(final String browserPath,
- final BrowserSpecificSettings browserSpecificSettings,
- final String url,
- final boolean newWindowIfPossible,
- final String[] additionalParameters) {
- List<String> command = BrowserUtil.getOpenBrowserCommand(browserPath, newWindowIfPossible);
- if (url != null) {
- command.add(url);
- }
- addArgs(command, browserSpecificSettings, additionalParameters);
-
- try {
- new GeneralCommandLine(command).createProcess();
- return true;
- }
- catch (ExecutionException e) {
- Messages.showErrorDialog(e.getMessage(), XmlBundle.message("browser.error"));
- return false;
- }
- }
-
- private static void addArgs(List<String> command, @Nullable BrowserSpecificSettings settings, String[] additional) {
- String[] specific = settings != null ? settings.getAdditionalParameters() : ArrayUtil.EMPTY_STRING_ARRAY;
-
- if (specific.length + additional.length > 0) {
- if (SystemInfo.isMac && ExecUtil.getOpenCommandPath().equals(command.get(0))) {
- if (!BrowserUtil.isOpenCommandSupportArgs()) {
- LOG.warn("'open' command doesn't allow to pass command line arguments so they will be ignored: " +
- Arrays.toString(specific) + " " + Arrays.toString(additional));
- }
- else {
- command.add("--args");
- }
- }
-
- Collections.addAll(command, specific);
- Collections.addAll(command, additional);
- }
- }
-}
+}
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
index 6cba9ab..5647e69 100644
--- a/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
+++ b/xml/impl/src/com/intellij/ide/browsers/impl/WebBrowserServiceImpl.java
@@ -15,15 +15,13 @@
*/
package com.intellij.ide.browsers.impl;
+import com.intellij.ide.browsers.OpenInBrowserRequest;
import com.intellij.ide.browsers.WebBrowserService;
import com.intellij.ide.browsers.WebBrowserUrlProvider;
import com.intellij.openapi.project.DumbService;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.impl.http.HttpVirtualFile;
import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.Url;
import com.intellij.util.Urls;
@@ -34,47 +32,31 @@
import java.util.Collection;
import java.util.Collections;
-import java.util.Set;
public class WebBrowserServiceImpl extends WebBrowserService {
- @Override
- public boolean canOpenInBrowser(@NotNull PsiElement psiElement) {
- PsiFile psiFile = psiElement instanceof PsiFile ? (PsiFile)psiElement : psiElement.getContainingFile();
- VirtualFile virtualFile = psiFile == null ? null : psiFile.getVirtualFile();
- return virtualFile != null &&
- ((HtmlUtil.isHtmlFile(psiFile) && !(virtualFile instanceof LightVirtualFile)) || getProvider(psiElement, psiFile) != null);
- }
-
@NotNull
@Override
- public Collection<Url> getUrlToOpen(@NotNull PsiElement psiElement, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException {
- final PsiFile psiFile = psiElement instanceof PsiFile ? (PsiFile)psiElement : psiElement.getContainingFile();
- if (psiFile == null) {
- return Collections.emptySet();
- }
- VirtualFile virtualFile = psiFile.getVirtualFile();
- if (virtualFile == null) {
- return Collections.emptySet();
- }
+ public Collection<Url> getUrlsToOpen(@NotNull OpenInBrowserRequest request, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException {
+ VirtualFile virtualFile = request.getVirtualFile();
if (virtualFile instanceof HttpVirtualFile) {
return Collections.singleton(Urls.newFromVirtualFile(virtualFile));
}
- if (!(preferLocalUrl && HtmlUtil.isHtmlFile(psiFile))) {
- Pair<WebBrowserUrlProvider, Collection<Url>> provider = getProvider(psiElement);
+ if (!preferLocalUrl || !HtmlUtil.isHtmlFile(request.getFile())) {
+ WebBrowserUrlProvider provider = getProvider(request);
if (provider != null) {
- if (provider.second != null) {
- return provider.second;
+ if (request.getResult() != null) {
+ return request.getResult();
}
try {
- Collection<Url> urls = provider.first.getUrls(psiElement, psiFile, virtualFile);
+ Collection<Url> urls = provider.getUrls(request);
if (!urls.isEmpty()) {
return urls;
}
}
catch (WebBrowserUrlProvider.BrowserException e) {
- if (!HtmlUtil.isHtmlFile(psiFile)) {
+ if (!HtmlUtil.isHtmlFile(request.getFile())) {
throw e;
}
}
@@ -84,18 +66,11 @@
}
@Nullable
- public static Pair<WebBrowserUrlProvider, Collection<Url>> getProvider(@Nullable PsiElement element) {
- PsiFile psiFile = element == null ? null : element.getContainingFile();
- return psiFile == null ? null : getProvider(element, psiFile);
- }
-
- private static Pair<WebBrowserUrlProvider, Collection<Url>> getProvider(PsiElement element, PsiFile psiFile) {
- Ref<Set<Url>> result = Ref.create();
- DumbService dumbService = DumbService.getInstance(psiFile.getProject());
+ public static WebBrowserUrlProvider getProvider(@NotNull OpenInBrowserRequest request) {
+ DumbService dumbService = DumbService.getInstance(request.getProject());
for (WebBrowserUrlProvider urlProvider : WebBrowserUrlProvider.EP_NAME.getExtensions()) {
- //noinspection deprecation
- if ((!dumbService.isDumb() || DumbService.isDumbAware(urlProvider)) && urlProvider.canHandleElement(element, psiFile, result)) {
- return new Pair<WebBrowserUrlProvider, Collection<Url>>(urlProvider, result.get());
+ if ((!dumbService.isDumb() || DumbService.isDumbAware(urlProvider)) && urlProvider.canHandleElement(request)) {
+ return urlProvider;
}
}
return null;
@@ -103,14 +78,9 @@
@Nullable
public static Url getUrlForContext(@NotNull PsiElement sourceElement) {
- PsiFile psiFile = sourceElement.getContainingFile();
- if (psiFile == null) {
- return null;
- }
-
Url url;
try {
- Collection<Url> urls = WebBrowserService.getInstance().getUrlToOpen(sourceElement, false);
+ Collection<Url> urls = WebBrowserService.getInstance().getUrlsToOpen(sourceElement, false);
url = ContainerUtil.getFirstItem(urls);
if (url == null) {
return null;
@@ -120,7 +90,7 @@
return null;
}
- VirtualFile virtualFile = psiFile.getVirtualFile();
+ VirtualFile virtualFile = sourceElement.getContainingFile().getVirtualFile();
if (virtualFile == null) {
return null;
}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java b/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java
index d3bc34b..f896146 100644
--- a/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java
+++ b/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java
@@ -24,6 +24,7 @@
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.xml.util.HtmlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -69,7 +70,7 @@
return null;
}
- if (tag.getName().equalsIgnoreCase("img") || tag.getName().equalsIgnoreCase("script")) {
+ if (tag.getName().equalsIgnoreCase("img") || HtmlUtil.isScriptTag(tag)) {
return getPathDescription(tag.getAttributeValue("src"));
}
else if (tag.getName().equalsIgnoreCase("link")) {
diff --git a/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java b/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java
index 19089b6..41b456d 100644
--- a/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java
+++ b/xml/impl/src/com/intellij/lang/xml/XmlFindUsagesProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -15,7 +15,6 @@
*/
package com.intellij.lang.xml;
-import com.intellij.find.impl.HelpID;
import com.intellij.lang.LangBundle;
import com.intellij.lang.cacheBuilder.WordsScanner;
import com.intellij.lang.findUsages.DescriptiveNameUtil;
@@ -73,7 +72,7 @@
}
public String getHelpId(@NotNull PsiElement element) {
- return HelpID.FIND_OTHER_USAGES;
+ return com.intellij.lang.HelpID.FIND_OTHER_USAGES;
}
@NotNull
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java
deleted file mode 100644
index bcd6f5a..0000000
--- a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java
+++ /dev/null
@@ -1,100 +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.psi.impl.source.html;
-
-import com.intellij.lang.ASTNode;
-import com.intellij.lang.Language;
-import com.intellij.lang.injection.MultiHostInjector;
-import com.intellij.lang.injection.MultiHostRegistrar;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.TextRange;
-import com.intellij.psi.PsiComment;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiLanguageInjectionHost;
-import com.intellij.psi.tree.TokenSet;
-import com.intellij.psi.xml.XmlComment;
-import com.intellij.psi.xml.XmlTokenType;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Arrays;
-import java.util.List;
-
-/**
- * @author spleaner
- */
-public class HtmlConditionalCommentInjector implements MultiHostInjector {
-
- /**
- * Allows to check if given element is a
- * <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>.
- *
- * @param host target element to check
- * @return <code>true</code> if given element is conditional comment; <code>false</code> otherwise
- */
- public static boolean isConditionalComment(@NotNull PsiElement host) {
- return parseConditionalCommentBoundaries(host) != null;
- }
-
- /**
- * Tries to parse given element as <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>.
- *
- * @param host target element to parse
- * @return <code>null</code> if given element is not a conditional comment;
- * pair like <code>(conditional comment start element; conditional comment end element)</code> otherwise
- */
- @Nullable
- private static Pair<ASTNode, ASTNode> parseConditionalCommentBoundaries(@NotNull PsiElement host) {
- if (!(host instanceof XmlComment)) {
- return null;
- }
- final ASTNode comment = host.getNode();
- if (comment == null) {
- return null;
- }
- final ASTNode conditionalStart = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END));
- if (conditionalStart == null) {
- return null;
- }
- final ASTNode conditionalEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START));
- if (conditionalEnd == null) {
- return null;
- }
- final ASTNode endOfEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END));
- return endOfEnd == null ? null : new Pair<ASTNode, ASTNode>(conditionalStart, conditionalEnd);
- }
-
- public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) {
- Pair<ASTNode, ASTNode> pair = parseConditionalCommentBoundaries(host);
- if (pair == null) {
- return;
- }
- final TextRange textRange = host.getTextRange();
- final int startOffset = textRange.getStartOffset();
- Language language = host.getParent().getLanguage();
- ASTNode conditionalStart = pair.first;
- ASTNode conditionalEnd = pair.second;
- TextRange range = new TextRange(conditionalStart.getTextRange().getEndOffset() - startOffset, conditionalEnd.getStartOffset() - startOffset);
- if (range.getStartOffset() < range.getEndOffset()) {
- registrar.startInjecting(language).addPlace(null, null, (PsiLanguageInjectionHost)host, range).doneInjecting();
- }
- }
-
- @NotNull
- public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
- return Arrays.asList(PsiComment.class);
- }
-}
diff --git a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlScriptLanguageInjector.java b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlScriptLanguageInjector.java
index 23c9cfd..ccde7d3 100644
--- a/xml/impl/src/com/intellij/psi/impl/source/html/HtmlScriptLanguageInjector.java
+++ b/xml/impl/src/com/intellij/psi/impl/source/html/HtmlScriptLanguageInjector.java
@@ -39,7 +39,7 @@
return;
}
XmlTag scriptTag = ((XmlText)host).getParentTag();
- if (scriptTag == null || !"script".equalsIgnoreCase(scriptTag.getLocalName())) {
+ if (scriptTag == null || !HtmlUtil.isScriptTag(scriptTag)) {
return;
}
String mimeType = scriptTag.getAttributeValue("type");
diff --git a/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java b/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java
index 25d0248..bf58ebf 100644
--- a/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java
+++ b/xml/impl/src/com/intellij/xml/actions/GenerateXmlTagAction.java
@@ -80,6 +80,7 @@
throw new CommonRefactoringUtil.RefactoringErrorHintException("Caret should be positioned inside a tag");
}
XmlElementDescriptor currentTagDescriptor = contextTag.getDescriptor();
+ assert currentTagDescriptor != null;
final XmlElementDescriptor[] descriptors = currentTagDescriptor.getElementsDescriptors(contextTag);
Arrays.sort(descriptors, new Comparator<XmlElementDescriptor>() {
@Override
@@ -110,7 +111,9 @@
else {
newTag = (XmlTag)contextTag.addAfter(newTag, anchor);
}
- generateTag(newTag);
+ if (newTag != null) {
+ generateTag(newTag, editor);
+ }
}
}.execute();
}
@@ -169,7 +172,7 @@
return previousPositionIsPossible ? null : anchor;
}
- public static void generateTag(XmlTag newTag) {
+ public static void generateTag(@NotNull XmlTag newTag, Editor editor) {
generateRaw(newTag);
final XmlTag restored = CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(newTag);
if (restored == null) {
@@ -177,10 +180,10 @@
}
TemplateBuilder builder = TemplateBuilderFactory.getInstance().createTemplateBuilder(restored);
replaceElements(restored, builder);
- builder.run();
+ builder.run(editor, false);
}
- private static void generateRaw(final XmlTag newTag) {
+ private static void generateRaw(final @NotNull XmlTag newTag) {
XmlElementDescriptor selected = newTag.getDescriptor();
if (selected == null) return;
switch (selected.getContentType()) {
diff --git a/xml/impl/src/com/intellij/xml/actions/validate/StdErrorReporter.java b/xml/impl/src/com/intellij/xml/actions/validate/StdErrorReporter.java
index 248d63f..eabb303 100644
--- a/xml/impl/src/com/intellij/xml/actions/validate/StdErrorReporter.java
+++ b/xml/impl/src/com/intellij/xml/actions/validate/StdErrorReporter.java
@@ -211,7 +211,7 @@
XmlBundle.message("xml.validate.validation.is.running.terminate.confirmation.title"),
Messages.getQuestionIcon()
);
- if (result != 0) {
+ if (result != Messages.YES) {
event.consume();
}
}
diff --git a/xml/impl/src/com/intellij/xml/arrangement/XmlRearranger.java b/xml/impl/src/com/intellij/xml/arrangement/XmlRearranger.java
index 9e20743..12212ea 100644
--- a/xml/impl/src/com/intellij/xml/arrangement/XmlRearranger.java
+++ b/xml/impl/src/com/intellij/xml/arrangement/XmlRearranger.java
@@ -5,9 +5,7 @@
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.codeStyle.CodeStyleSettings;
-import com.intellij.psi.codeStyle.arrangement.ArrangementSettings;
-import com.intellij.psi.codeStyle.arrangement.ArrangementUtil;
-import com.intellij.psi.codeStyle.arrangement.Rearranger;
+import com.intellij.psi.codeStyle.arrangement.*;
import com.intellij.psi.codeStyle.arrangement.group.ArrangementGroupingRule;
import com.intellij.psi.codeStyle.arrangement.match.ArrangementEntryMatcher;
import com.intellij.psi.codeStyle.arrangement.match.StdArrangementEntryMatcher;
@@ -46,6 +44,8 @@
Collections.<ArrangementGroupingRule>emptyList(), DEFAULT_MATCH_RULES);
}
+ private static final DefaultArrangementSettingsSerializer SETTINGS_SERIALIZER = new DefaultArrangementSettingsSerializer(DEFAULT_SETTINGS);
+
@NotNull
public static StdArrangementMatchRule attrArrangementRule(@NotNull String nameFilter,
@NotNull String namespaceFilter,
@@ -56,6 +56,12 @@
)), orderType);
}
+ @NotNull
+ @Override
+ public ArrangementSettingsSerializer getSerializer() {
+ return SETTINGS_SERIALIZER;
+ }
+
@Nullable
@Override
public StdArrangementSettings getDefaultSettings() {
diff --git a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java
index 12ead10..07f316d 100644
--- a/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java
+++ b/xml/impl/src/com/intellij/xml/util/ColorSampleLookupValue.java
@@ -21,9 +21,7 @@
import com.intellij.codeInsight.lookup.LookupValueWithUIHint;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Iconable;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
-import com.intellij.ui.ColorUtil;
import com.intellij.xml.XmlBundle;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -31,252 +29,22 @@
import javax.swing.*;
import java.awt.*;
-import java.util.*;
+import java.util.HashMap;
+import java.util.LinkedList;
import java.util.List;
+import java.util.StringTokenizer;
/**
* @author maxim
*/
public class ColorSampleLookupValue implements LookupValueWithUIHint, DeferredUserLookupValue, Iconable, LookupValueWithPriority {
private static volatile ColorSampleLookupValue[] ourColors;
- private static Map<String, String> ourColorNameToHexCodeMap;
- private static Map<String, String> ourHexCodeToColorNameMap;
-
- @NonNls private static final String BR = "<br>";
-
- @NonNls private static final String systemColorsString = "ActiveBorder\n" +
- " Active window border.\n" +
- "ActiveCaption\n" +
- " Active window caption.\n" +
- "AppWorkspace\n" +
- " Background color of multiple document interface.\n" +
- "Background\n" +
- " Desktop background.\n" +
- "ButtonFace\n" +
- " Face color for three-dimensional display elements.\n" +
- "ButtonHighlight\n" +
- " Highlight color for three-dimensional display elements (for edges facing away from the light source).\n" +
- "ButtonShadow\n" +
- " Shadow color for three-dimensional display elements.\n" +
- "ButtonText\n" +
- " Text on push buttons.\n" +
- "CaptionText\n" +
- " Text in caption, size box, and scrollbar arrow box.\n" +
- "GrayText\n" +
- " Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.\n" +
- "Highlight\n" +
- " Item(s) selected in a control.\n" +
- "HighlightText\n" +
- " Text of item(s) selected in a control.\n" +
- "InactiveBorder\n" +
- " Inactive window border.\n" +
- "InactiveCaption\n" +
- " Inactive window caption.\n" +
- "InactiveCaptionText\n" +
- " Color of text in an inactive caption.\n" +
- "InfoBackground\n" +
- " Background color for tooltip controls.\n" +
- "InfoText\n" +
- " Text color for tooltip controls.\n" +
- "Menu\n" +
- " Menu background.\n" +
- "MenuText\n" +
- " Text in menus.\n" +
- "Scrollbar\n" +
- " Scroll bar gray area.\n" +
- "ThreeDDarkShadow\n" +
- " Dark shadow for three-dimensional display elements.\n" +
- "ThreeDFace\n" +
- " Face color for three-dimensional display elements.\n" +
- "ThreeDHighlight\n" +
- " Highlight color for three-dimensional display elements.\n" +
- "ThreeDLightShadow\n" +
- " Light color for three-dimensional display elements (for edges facing the light source).\n" +
- "ThreeDShadow\n" +
- " Dark shadow for three-dimensional display elements.\n" +
- "Window\n" +
- " Window background.\n" +
- "WindowFrame\n" +
- " Window frame.\n" +
- "WindowText\n" +
- " Text in windows. ";
- @NonNls private static final String standardColorsString = "maroon #800000 red #ff0000 orange #ffA500 yellow #ffff00 olive #808000\n" +
- "purple #800080 fuchsia #ff00ff white #ffffff lime #00ff00 green #008000\n" +
- "navy #000080 blue #0000ff aqua #00ffff teal #008080\n" +
- "black #000000 silver #c0c0c0 gray #808080";
- @NonNls private static final String colorsString = "aliceblue \t#f0f8ff \t240,248,255\n" +
- " \t \tantiquewhite \t#faebd7 \t250,235,215\n" +
- " \t \taqua \t#00ffff \t0,255,255\n" +
- " \t \taquamarine \t#7fffd4 \t127,255,212\n" +
- " \t \tazure \t#f0ffff \t240,255,255\n" +
- " \t \tbeige \t#f5f5dc \t245,245,220\n" +
- " \t \tbisque \t#ffe4c4 \t255,228,196\n" +
- " \t \tblack \t#000000 \t0,0,0\n" +
- " \t \tblanchedalmond \t#ffebcd \t255,235,205\n" +
- " \t \tblue \t#0000ff \t0,0,255\n" +
- " \t \tblueviolet \t#8a2be2 \t138,43,226\n" +
- " \t \tbrown \t#a52a2a \t165,42,42\n" +
- " \t \tburlywood \t#deb887 \t222,184,135\n" +
- " \t \tcadetblue \t#5f9ea0 \t95,158,160\n" +
- " \t \tchartreuse \t#7fff00 \t127,255,0\n" +
- " \t \tchocolate \t#d2691e \t210,105,30\n" +
- " \t \tcoral \t#ff7f50 \t255,127,80\n" +
- " \t \tcornflowerblue \t#6495ed \t100,149,237\n" +
- " \t \tcornsilk \t#fff8dc \t255,248,220\n" +
- " \t \tcrimson \t#dc143c \t220,20,60\n" +
- " \t \tcyan \t#00ffff \t0,255,255\n" +
- " \t \tdarkblue \t#00008b \t0,0,139\n" +
- " \t \tdarkcyan \t#008b8b \t0,139,139\n" +
- " \t \tdarkgoldenrod \t#b8860b \t184,134,11\n" +
- " \t \tdarkgray \t#a9a9a9 \t169,169,169\n" +
- " \t \tdarkgrey \t#a9a9a9 \t169,169,169\n" +
- " \t \tdarkgreen \t#006400 \t0,100,0\n" +
- " \t \tdarkkhaki \t#bdb76b \t189,183,107\n" +
- " \t \tdarkmagenta \t#8b008b \t139,0,139\n" +
- " \t \tdarkolivegreen \t#556b2f \t85,107,47\n" +
- " \t \tdarkorange \t#ff8c00 \t255,140,0\n" +
- " \t \tdarkorchid \t#9932cc \t153,50,204\n" +
- " \t \tdarkred \t#8b0000 \t139,0,0\n" +
- " \t \tdarksalmon \t#e9967a \t233,150,122\n" +
- " \t \tdarkseagreen \t#8fbc8f \t143,188,143\n" +
- " \t \tdarkslateblue \t#483d8b \t72,61,139\n" +
- " \t \tdarkslategray \t#2f4f4f \t47,79,79\n" +
- " \t \tdarkslategrey \t#2f4f4f \t47,79,79\n" +
- " \t \tdarkturquoise \t#00ced1 \t0,206,209\n" +
- " \t \tdarkviolet \t#9400d3 \t148,0,211\n" +
- " \t \tdeeppink \t#ff1493 \t255,20,147\n" +
- " \t \tdeepskyblue \t#00bfff \t0,191,255\n" +
- " \t \tdimgray \t#696969 \t105,105,105\n" +
- " \t \tdimgrey \t#696969 \t105,105,105\n" +
- " \t \tdodgerblue \t#1e90ff \t30,144,255\n" +
- " \t \tfirebrick \t#b22222 \t178,34,34\n" +
- " \t \tfloralwhite \t#fffaf0 \t255,250,240\n" +
- " \t \tforestgreen \t#228b22 \t34,139,34\n" +
- " \t \tfuchsia \t#ff00ff \t255,0,255\n" +
- " \t \tgainsboro \t#dcdcdc \t220,220,220\n" +
- " \t \tghostwhite \t#f8f8ff \t248,248,255\n" +
- " \t \tgold \t#ffd700 \t255,215,0\n" +
- " \t \tgoldenrod \t#daa520 \t218,165,32\n" +
- " \t \tgray \t#808080 \t128,128,128\n" +
- " \t \tgrey \t#808080 \t128,128,128\n" +
- " \t \tgreen \t#008000 \t0,128,0\n" +
- " \t \tgreenyellow \t#adff2f \t173,255,47\n" +
- " \t \thoneydew \t#f0fff0 \t240,255,240\n" +
- " \t \thotpink \t#ff69b4 \t255,105,180\n" +
- " \t \tindianred \t#cd5c5c \t205,92,92\n" +
- " \t \tindigo \t#4b0082 \t75,0,130\n" +
- " \t \tivory \t#fffff0 \t255,255,240\n" +
- " \t \tkhaki \t#f0e68c \t240,230,140\n" +
- " \t \tlavender \t#e6e6fa \t230,230,250\n" +
- " \t \tlavenderblush \t#fff0f5 \t255,240,245\n" +
- " \t \tlawngreen \t#7cfc00 \t124,252,0\n" +
- " \t \tlemonchiffon \t#fffacd \t255,250,205\n" +
- " \t \tlightblue \t#add8e6 \t173,216,230\n" +
- " \t \tlightcoral \t#f08080 \t240,128,128\n" +
- " \t \tlightcyan \t#e0ffff \t224,255,255\n" +
- " \t \tlightgoldenrodyellow \t#fafad2 \t250,250,210\n" +
- " \t \tlightgray \t#d3d3d3 \t211,211,211\n" +
- " \t \tlightgrey \t#d3d3d3 \t211,211,211\n" +
- " \t \tlightgreen \t#90ee90 \t144,238,144\n" +
- " \t \tlightpink \t#ffb6c1 \t255,182,193\n" +
- " \t \tlightsalmon \t#ffa07a \t255,160,122\n" +
- " \t \tlightseagreen \t#20b2aa \t32,178,170\n" +
- " \t \tlightskyblue \t#87cefa \t135,206,250\n" +
- " \t \tlightslategray \t#778899 \t119,136,153\n" +
- " \t \tlightslategrey \t#778899 \t119,136,153\n" +
- " \t \tlightsteelblue \t#b0c4de \t176,196,222\n" +
- " \t \tlightyellow \t#ffffe0 \t255,255,224\n" +
- " \t \tlime \t#00ff00 \t0,255,0\n" +
- " \t \tlimegreen \t#32cd32 \t50,205,50\n" +
- " \t \tlinen \t#faf0e6 \t250,240,230\n" +
- " \t \tmagenta \t#ff00ff \t255,0,255\n" +
- " \t \tmaroon \t#800000 \t128,0,0\n" +
- " \t \tmediumaquamarine \t#66cdaa \t102,205,170\n" +
- " \t \tmediumblue \t#0000cd \t0,0,205\n" +
- " \t \tmediumorchid \t#ba55d3 \t186,85,211\n" +
- " \t \tmediumpurple \t#9370db \t147,112,219\n" +
- " \t \tmediumseagreen \t#3cb371 \t60,179,113\n" +
- " \t \tmediumslateblue \t#7b68ee \t123,104,238\n" +
- " \t \tmediumspringgreen \t#00fa9a \t0,250,154\n" +
- " \t \tmediumturquoise \t#48d1cc \t72,209,204\n" +
- " \t \tmediumvioletred \t#c71585 \t199,21,133\n" +
- " \t \tmidnightblue \t#191970 \t25,25,112\n" +
- " \t \tmintcream \t#f5fffa \t245,255,250\n" +
- " \t \tmistyrose \t#ffe4e1 \t255,228,225\n" +
- " \t \tmoccasin \t#ffe4b5 \t255,228,181\n" +
- " \t \tnavajowhite \t#ffdead \t255,222,173\n" +
- " \t \tnavy \t#000080 \t0,0,128\n" +
- " \t \toldlace \t#fdf5e6 \t253,245,230\n" +
- " \t \tolive \t#808000 \t128,128,0\n" +
- " \t \tolivedrab \t#6b8e23 \t107,142,35\n" +
- " \t \torange \t#ffa500 \t255,165,0\n" +
- " \t \torangered \t#ff4500 \t255,69,0\n" +
- " \t \torchid \t#da70d6 \t218,112,214\n" +
- " \t \tpalegoldenrod \t#eee8aa \t238,232,170\n" +
- " \t \tpalegreen \t#98fb98 \t152,251,152\n" +
- " \t \tpaleturquoise \t#afeeee \t175,238,238\n" +
- " \t \tpalevioletred \t#db7093 \t219,112,147\n" +
- " \t \tpapayawhip \t#ffefd5 \t255,239,213\n" +
- " \t \tpeachpuff \t#ffdab9 \t255,218,185\n" +
- " \t \tperu \t#cd853f \t205,133,63\n" +
- " \t \tpink \t#ffc0cb \t255,192,203\n" +
- " \t \tplum \t#dda0dd \t221,160,221\n" +
- " \t \tpowderblue \t#b0e0e6 \t176,224,230\n" +
- " \t \tpurple \t#800080 \t128,0,128\n" +
- " \t \tred \t#ff0000 \t255,0,0\n" +
- " \t \trosybrown \t#bc8f8f \t188,143,143\n" +
- " \t \troyalblue \t#4169e1 \t65,105,225\n" +
- " \t \tsaddlebrown \t#8b4513 \t139,69,19\n" +
- " \t \tsalmon \t#fa8072 \t250,128,114\n" +
- " \t \tsandybrown \t#f4a460 \t244,164,96\n" +
- " \t \tseagreen \t#2e8b57 \t46,139,87\n" +
- " \t \tseashell \t#fff5ee \t255,245,238\n" +
- " \t \tsienna \t#a0522d \t160,82,45\n" +
- " \t \tsilver \t#c0c0c0 \t192,192,192\n" +
- " \t \tskyblue \t#87ceeb \t135,206,235\n" +
- " \t \tslateblue \t#6a5acd \t106,90,205\n" +
- " \t \tslategray \t#708090 \t112,128,144\n" +
- " \t \tslategrey \t#708090 \t112,128,144\n" +
- " \t \tsnow \t#fffafa \t255,250,250\n" +
- " \t \tspringgreen \t#00ff7f \t0,255,127\n" +
- " \t \tsteelblue \t#4682b4 \t70,130,180\n" +
- " \t \ttan \t#d2b48c \t210,180,140\n" +
- " \t \tteal \t#008080 \t0,128,128\n" +
- " \t \tthistle \t#d8bfd8 \t216,191,216\n" +
- " \t \ttomato \t#ff6347 \t255,99,71\n" +
- " \t \tturquoise \t#40e0d0 \t64,224,208\n" +
- " \t \tviolet \t#ee82ee \t238,130,238\n" +
- " \t \twheat \t#f5deb3 \t245,222,179\n" +
- " \t \twhite \t#ffffff \t255,255,255\n" +
- " \t \twhitesmoke \t#f5f5f5 \t245,245,245\n" +
- " \t \tyellow \t#ffff00 \t255,255,0\n" +
- " \t \tyellowgreen \t#9acd32 \t154,205,50";
private final boolean myIsStandard;
private final String myName;
private final String myValue;
private Color myColor;
- private static final ArrayList<String> ourSystemColors;
- private static final List<String> ourStandardColors;
+ @NonNls private static final String BR = "<br>";
- static {
- ourSystemColors = new ArrayList<String>();
- StringTokenizer tokenizer = new StringTokenizer(systemColorsString, "\n");
-
- while (tokenizer.hasMoreTokens()) {
- String name = tokenizer.nextToken();
- ourSystemColors.add(name.toLowerCase());
- tokenizer.nextToken();
- }
-
- ourStandardColors = new ArrayList<String>();
- tokenizer = new StringTokenizer(standardColorsString, ", \n");
-
- while (tokenizer.hasMoreTokens()) {
- String name = tokenizer.nextToken();
- ourStandardColors.add(name);
- tokenizer.nextToken();
- }
- }
public ColorSampleLookupValue(String name, String value, boolean isStandard) {
myName = name;
@@ -322,22 +90,13 @@
return true;
}
- public static boolean isSystemColorName(@NotNull @NonNls final String s) {
- return ourSystemColors.contains(s);
- }
-
- public static boolean isStandardColor(@NotNull @NonNls final String s) {
- return ourStandardColors.contains(s);
- }
-
+ @NotNull
public static ColorSampleLookupValue[] getColors() {
if (ourColors == null) {
synchronized (ColorSampleLookupValue.class) {
if (ourColors == null) {
- ourColorNameToHexCodeMap = new HashMap<String, String>(25);
- ourHexCodeToColorNameMap = new HashMap<String, String>(25);
List<ColorSampleLookupValue> colorsList = new LinkedList<ColorSampleLookupValue>();
- StringTokenizer tokenizer = new StringTokenizer(systemColorsString, "\n");
+ StringTokenizer tokenizer = new StringTokenizer(ColorMap.systemColorsString, "\n");
while (tokenizer.hasMoreTokens()) {
String name = tokenizer.nextToken();
@@ -345,20 +104,18 @@
tokenizer.nextToken();
}
- tokenizer = new StringTokenizer(standardColorsString, ", \n");
+ tokenizer = new StringTokenizer(ColorMap.standardColorsString, ", \n");
HashMap<String, String> standardColors = new HashMap<String, String>();
while (tokenizer.hasMoreTokens()) {
String name = tokenizer.nextToken();
String value = tokenizer.nextToken();
standardColors.put(name, name);
- ourColorNameToHexCodeMap.put(name, value);
- ourHexCodeToColorNameMap.put(value, name);
colorsList.add(new ColorSampleLookupValue(name, value, true));
}
- tokenizer = new StringTokenizer(colorsString, " \t\n");
+ tokenizer = new StringTokenizer(ColorMap.colorsString, " \t\n");
while (tokenizer.hasMoreTokens()) {
String name = tokenizer.nextToken();
@@ -368,12 +125,10 @@
if (!standardColors.containsKey(name)) {
colorsList.add(new ColorSampleLookupValue(name, hexValue, false));
- ourColorNameToHexCodeMap.put(name, hexValue);
- ourHexCodeToColorNameMap.put(hexValue, name);
}
}
- colorsList.toArray(ourColors = new ColorSampleLookupValue[colorsList.size()]);
+ ourColors = colorsList.toArray(new ColorSampleLookupValue[colorsList.size()]);
}
}
}
@@ -402,16 +157,6 @@
return myName == null || Character.isLowerCase(myName.charAt(0)) ? HIGHER : NORMAL;
}
- public static synchronized String getHexCodeForColorName(String colorName) {
- getColors(); // to guarantee initialization
- return ourColorNameToHexCodeMap.get(colorName);
- }
-
- public static synchronized String getColorNameForHexCode(String hexString) {
- getColors(); // to guarantee initialization
- return ourHexCodeToColorNameMap.get(hexString);
- }
-
public static void addColorPreviewAndCodeToLookup(final PsiElement currentElement, final StringBuilder buf) {
final Color colorFromElement = UserColorLookup.getColorFromElement(currentElement);
@@ -437,7 +182,7 @@
public static void addColorPreviewAndCodeToLookup(final Color color, final StringBuilder buf) {
if (color == null) return;
final String code = '#' + toHex(color);
- final String colorName = getColorNameForHexCode(code);
+ final String colorName = ColorMap.getColorNameForHexCode(code);
if (colorName != null) {
buf.append(XmlBundle.message("color.name", colorName)).append(BR);
}
@@ -446,17 +191,6 @@
buf.append(XmlBundle.message("color.preview", colorBox)).append(BR);
}
- public static Color getColor(String text) {
- if (StringUtil.isEmptyOrSpaces(text)) {
- return null;
- }
- String hexValue = text.charAt(0) == '#' ? text : getHexCodeForColorName(text.toLowerCase());
- if (hexValue != null) {
- return ColorUtil.fromHex(hexValue, null);
- }
- return null;
- }
-
@Override
public String toString() {
return myName == null ? myValue : myValue + " " + myName;
diff --git a/xml/impl/src/com/intellij/xml/util/UserColorLookup.java b/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
index 1f39b91..46c82f2 100644
--- a/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
+++ b/xml/impl/src/com/intellij/xml/util/UserColorLookup.java
@@ -94,6 +94,6 @@
public static Color getColorFromElement(final PsiElement element) {
if (!(element instanceof XmlToken)) return null;
- return ColorSampleLookupValue.getColor(element.getText());
+ return ColorMap.getColor(element.getText());
}
}
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/attributes.html b/xml/impl/src/com/intellij/xml/util/documentation/attributes.html
index 5a56faa..0de2c54 100644
--- a/xml/impl/src/com/intellij/xml/util/documentation/attributes.html
+++ b/xml/impl/src/com/intellij/xml/util/documentation/attributes.html
@@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
-<!-- $Id: attributes.html,v 1.1 2004/12/24 21:53:29 Maxim.Mossienko Exp $ -->
+<!-- $Id: attributes.html,v 1.2 1999/12/24 23:37:48 ijacobs Exp $ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Index of the HTML 4 Attributes</title>
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/elements.html b/xml/impl/src/com/intellij/xml/util/documentation/elements.html
index 527bf9b..ea7e87b 100644
--- a/xml/impl/src/com/intellij/xml/util/documentation/elements.html
+++ b/xml/impl/src/com/intellij/xml/util/documentation/elements.html
@@ -1,6 +1,6 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html lang="en">
-<!-- $Id: elements.html,v 1.1 2004/12/24 21:53:29 Maxim.Mossienko Exp $ -->
+<!-- $Id: elements.html,v 1.2 1999/12/24 23:37:48 ijacobs Exp $ -->
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Index of the HTML 4 Elements</title>
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/html5.html b/xml/impl/src/com/intellij/xml/util/documentation/html5.html
new file mode 100644
index 0000000..97adbfb
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/html5.html
@@ -0,0 +1,3690 @@
+<!DOCTYPE html><html data-bug-component="HTML5 spec" data-bug-product="HTML WG" lang="en-US-x-Hixie"><meta charset="utf-8"><title>Index — HTML 5.1
+ Nightly
+ </title><script src="js/bug-assist.js"></script><script src="link-fixup.js"></script><style type="text/css">
+
+ .applies thead th > * { display: block; }
+ .applies thead code { display: block; }
+ .applies tbody th { white-space: nowrap; }
+ .applies td { text-align: center; }
+ .applies .yes { background: yellow; }
+
+ .matrix, .matrix td { border: hidden; text-align: right; }
+ .matrix { margin-left: 2em; }
+
+ .dice-example { border-collapse: collapse; border-style: hidden solid solid hidden; border-width: thin; margin-left: 3em; }
+ .dice-example caption { width: 30em; font-size: smaller; font-style: italic; padding: 0.75em 0; text-align: left; }
+ .dice-example td, .dice-example th { border: solid thin; width: 1.35em; height: 1.05em; text-align: center; padding: 0; }
+
+ td.eg { border-width: thin; text-align: center; }
+
+ #table-example-1 { border: solid thin; border-collapse: collapse; margin-left: 3em; }
+ #table-example-1 * { font-family: "Essays1743", serif; line-height: 1.01em; }
+ #table-example-1 caption { padding-bottom: 0.5em; }
+ #table-example-1 thead, #table-example-1 tbody { border: none; }
+ #table-example-1 th, #table-example-1 td { border: solid thin; }
+ #table-example-1 th { font-weight: normal; }
+ #table-example-1 td { border-style: none solid; vertical-align: top; }
+ #table-example-1 th { padding: 0.5em; vertical-align: middle; text-align: center; }
+ #table-example-1 tbody tr:first-child td { padding-top: 0.5em; }
+ #table-example-1 tbody tr:last-child td { padding-bottom: 1.5em; }
+ #table-example-1 tbody td:first-child { padding-left: 2.5em; padding-right: 0; width: 9em; }
+ #table-example-1 tbody td:first-child::after { content: leader(". "); }
+ #table-example-1 tbody td { padding-left: 2em; padding-right: 2em; }
+ #table-example-1 tbody td:first-child + td { width: 10em; }
+ #table-example-1 tbody td:first-child + td ~ td { width: 2.5em; }
+ #table-example-1 tbody td:first-child + td + td + td ~ td { width: 1.25em; }
+
+ .apple-table-examples { border: none; border-collapse: separate; border-spacing: 1.5em 0em; width: 40em; margin-left: 3em; }
+ .apple-table-examples * { font-family: "Times", serif; }
+ .apple-table-examples td, .apple-table-examples th { border: none; white-space: nowrap; padding-top: 0; padding-bottom: 0; }
+ .apple-table-examples tbody th:first-child { border-left: none; width: 100%; }
+ .apple-table-examples thead th:first-child ~ th { font-size: smaller; font-weight: bolder; border-bottom: solid 2px; text-align: center; }
+ .apple-table-examples tbody th::after, .apple-table-examples tfoot th::after { content: leader(". ") }
+ .apple-table-examples tbody th, .apple-table-examples tfoot th { font: inherit; text-align: left; }
+ .apple-table-examples td { text-align: right; vertical-align: top; }
+ .apple-table-examples.e1 tbody tr:last-child td { border-bottom: solid 1px; }
+ .apple-table-examples.e1 tbody + tbody tr:last-child td { border-bottom: double 3px; }
+ .apple-table-examples.e2 th[scope=row] { padding-left: 1em; }
+ .apple-table-examples sup { line-height: 0; }
+
+ .details-example img { vertical-align: top; }
+
+ #base64-table {
+ white-space: nowrap;
+ font-size: 0.6em;
+ column-width: 6em;
+ column-count: 5;
+ column-gap: 1em;
+ -moz-column-width: 6em;
+ -moz-column-count: 5;
+ -moz-column-gap: 1em;
+ -webkit-column-width: 6em;
+ -webkit-column-count: 5;
+ -webkit-column-gap: 1em;
+ }
+ #base64-table thead { display: none; }
+ #base64-table * { border: none; }
+ #base64-table tbody td:first-child:after { content: ':'; }
+ #base64-table tbody td:last-child { text-align: right; }
+
+ #named-character-references-table {
+ white-space: nowrap;
+ font-size: 0.6em;
+ column-width: 30em;
+ column-gap: 1em;
+ -moz-column-width: 30em;
+ -moz-column-gap: 1em;
+ -webkit-column-width: 30em;
+ -webkit-column-gap: 1em;
+ }
+ #named-character-references-table > table > tbody > tr > td:first-child + td,
+ #named-character-references-table > table > tbody > tr > td:last-child { text-align: center; }
+ #named-character-references-table > table > tbody > tr > td:last-child:hover > span { position: absolute; top: auto; left: auto; margin-left: 0.5em; line-height: 1.2; font-size: 5em; border: outset; padding: 0.25em 0.5em; background: white; width: 1.25em; height: auto; text-align: center; }
+ #named-character-references-table > table > tbody > tr#entity-CounterClockwiseContourIntegral > td:first-child { font-size: 0.5em; }
+
+ .glyph.control { color: red; }
+
+ @font-face {
+ font-family: 'Essays1743';
+ src: url('fonts/Essays1743.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-weight: bold;
+ src: url('fonts/Essays1743-Bold.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-style: italic;
+ src: url('fonts/Essays1743-Italic.ttf');
+ }
+ @font-face {
+ font-family: 'Essays1743';
+ font-style: italic;
+ font-weight: bold;
+ src: url('fonts/Essays1743-BoldItalic.ttf');
+ }
+
+ </style><style type="text/css">
+ pre { margin-left: 2em; white-space: pre-wrap; }
+ h2 { margin: 3em 0 1em 0; }
+ h3 { margin: 2.5em 0 1em 0; }
+ h4 { margin: 2.5em 0 0.75em 0; }
+ h5, h6 { margin: 2.5em 0 1em; }
+ h1 + h2, h1 + h2 + h2, h1 + p, h1 + p + h2 { margin: 0.75em 0 0.75em; }
+ h2 + h3, h3 + h4, h4 + h5, h5 + h6 { margin-top: 0.5em; }
+ p { margin: 1em 0; }
+ hr:not(.top) { display: block; background: none; border: none; padding: 0; margin: 2em 0; height: auto; }
+ .element dd, .element dl { margin-top: 0em; margin-bottom: 0.25em;}
+ dt { margin-top: 0.75em; margin-bottom: 0.5em; clear: left; }
+ .element dt { margin-top: 0.5em; margin-bottom: 0.5em; }
+ adding tag omission & allowed ARIA role, state and property info to element definitions in HTML5.1 http://www.w3.org/html/wg/drafts/html/master/semantics.html#the-html-element … feedabck welcome!
+ dt + dt { margin-top: 0; }
+ dd dt { margin-top: 0.25em; margin-bottom: 0; }
+ dd p { margin-top: 0; }
+ dd dl + p { margin-top: 1em; }
+ dd table + p { margin-top: 1em; }
+ p + * > li, dd li { margin: 1em 0; }
+ dt, dfn { font-weight: bold; font-style: normal; }
+ i, em { font-style: italic; }
+ dt dfn { font-style: italic; }
+ pre, code { font-size: inherit; font-family: monospace; font-variant: normal; }
+ pre strong { color: black; font: inherit; font-weight: bold; background: yellow; }
+ pre em { font-weight: bolder; font-style: normal; }
+ @media screen { code { color: #D93B00; } code :link, code :visited { color: inherit; } }
+ var { background-color: #f9f9f9; border: 1px solid #eee; padding: 0 2px; }
+ var sub { vertical-align: bottom; font-size: smaller; position: relative; top: 0.1em; }
+ table { border-collapse: collapse; border-style: hidden hidden none hidden; }
+ table thead, table tbody { border-bottom: solid; }
+ table tbody th:first-child { border-left: solid; }
+ table tbody th { text-align: left; }
+ table td, table th { border-left: solid; border-right: solid; border-bottom: solid thin; vertical-align: top; padding: 0.2em; }
+ blockquote { margin: 0 0 0 2em; border: 0; padding: 0; font-style: italic; }
+
+ .bad, .bad *:not(.XXX) { color: #5F6D7A; border-color: gray; background: transparent; }
+ .matrix, .matrix td { border: none; text-align: right; }
+ .matrix { margin-left: 2em; }
+ .dice-example { border-collapse: collapse; border-style: hidden solid solid hidden; border-width: thin; margin-left: 3em; }
+ .dice-example caption { width: 30em; font-size: smaller; font-style: italic; padding: 0.75em 0; text-align: left; }
+ .dice-example td, .dice-example th { border: solid thin; width: 1.35em; height: 1.05em; text-align: center; padding: 0; }
+
+ .toc dfn, h1 dfn, h2 dfn, h3 dfn, h4 dfn, h5 dfn, h6 dfn { font: inherit; }
+ img.extra, p.overview { float: right; }
+ pre.idl { border: solid thin #d3d3d3; background: #FCFCFC; color: black; padding: 0.5em 1em; position: relative; }
+ pre.idl :link, pre.idl :visited { color: inherit; background: transparent; }
+ pre.idl::before { content: "IDL"; font: bold small sans-serif; padding: 0.5em; background: white; position: absolute; top: 0; margin: -1px 0 0 -4em; width: 1.5em; border: thin solid; border-radius: 0 0 0 0.5em }
+ pre.css { border: solid thin; background: #FFFFEE; color: black; padding: 0.5em 1em; }
+ pre.css:first-line { color: #AAAA50; }
+ dl.domintro {padding: 0.5em 1em; border: none; background:#E9FBE9; border: 1px solid lightgray; }
+ hr + dl.domintro, div.impl + dl.domintro { margin-top: 2.5em; margin-bottom: 1.5em; }
+ dl.domintro dt, dl.domintro dt * { color: black; text-decoration: none; }
+ dl.domintro dd { margin: 0.5em 0 1em 2em; padding: 0; }
+ dl.domintro dd p { margin: 0.5em 0; }
+ dl.domintro:before { display: table; margin: -1em -0.5em -0.5em auto; width: auto; content: 'This definition is non-normative. Implementation requirements are given below this definition.'; color: #606060; border:1px solid lightgray; background: white; padding: 0 0.25em;font-size:.9em;}
+ dl.switch { padding-left: 2em; }
+ dl.switch > dt { text-indent: -1.5em; }
+ dl.switch > dt:before { content: '\21AA'; padding: 0 0.5em 0 0; display: inline-block; width: 1em; text-align: right; line-height: 0.5em; }
+ dl.triple { padding: 0 0 0 1em; }
+ dl.triple dt, dl.triple dd { margin: 0; display: inline }
+ dl.triple dt:after { content: ':'; }
+ dl.triple dd:after { content: '\A'; white-space: pre; }
+ .diff-old { text-decoration: line-through; color: silver; background: transparent; }
+ .diff-chg, .diff-new { text-decoration: underline; color: green; background: transparent; }
+ a .diff-new { border-bottom: 1px blue solid; }
+
+ figure.diagrams { border: double black; background: white; padding: 1em; }
+ figure.diagrams img { display: block; margin: 1em auto; }
+
+ h2 { page-break-before: always; }
+ h1, h2, h3, h4, h5, h6 { page-break-after: avoid; }
+ h1 + h2, hr + h2.no-toc { page-break-before: auto; }
+
+ p > span:not([title=""]):not([class="XXX"]):not([class="impl"]):not([class="note"]),
+ li > span:not([title=""]):not([class="XXX"]):not([class="impl"]):not([class="note"]) { border-bottom: solid #9999CC; }
+
+ div.head { margin: 0 0 1em; padding: 1em 0 0 0; }
+ div.head p { margin: 0; }
+ div.head h1 { margin: 0; }
+ div.head .logo { float: right; margin: 0 1em; }
+ div.head .logo img { border: none } /* remove border from top image */
+ div.head dl { margin: 1em 0; }
+ div.head p.copyright, div.head p.alt { font-size: x-small; font-style: oblique; margin: 0; }
+
+ body > .toc > li { margin-top: 1em; margin-bottom: 1em; }
+ body > .toc.brief > li { margin-top: 0.35em; margin-bottom: 0.35em; }
+ body > .toc > li > * { margin-bottom: 0.5em; }
+ body > .toc > li > * > li > * { margin-bottom: 0.25em; }
+ .toc, .toc li { list-style: none; }
+
+ .brief { margin-top: 1em; margin-bottom: 1em; line-height: 1.1; }
+ .brief li { margin: 0; padding: 0; }
+ .brief li p { margin: 0; padding: 0; }
+
+ .category-list { margin-top: -0.75em; margin-bottom: 1em; line-height: 1.5; }
+ .category-list::before { content: '\21D2\A0'; font-size: 1.2em; font-weight: 900; }
+ .category-list li { display: inline; }
+ .category-list li:not(:last-child)::after { content: ', '; }
+ .category-list li > span, .category-list li > a { text-transform: lowercase; }
+ .category-list li * { text-transform: none; } /* don't affect <code> nested in <a> */
+
+ .XXX { color: #E50000; background: white; border: solid red; padding: 0.5em; margin: 1em 0; }
+ .XXX > :first-child { margin-top: 0; }
+ p .XXX { line-height: 3em; }
+ .annotation { border: solid thin black; background: #0C479D; color: white; position: relative; margin: 8px 0 20px 0; }
+ .annotation:before { position: absolute; left: 0; top: 0; width: 100%; height: 100%; margin: 6px -6px -6px 6px; background: #333333; z-index: -1; content: ''; }
+ .annotation :link, .annotation :visited { color: inherit; }
+ .annotation :link:hover, .annotation :visited:hover { background: transparent; }
+ .annotation span { border: none ! important; }
+ .note { border-left-style: solid; border-left-width: 0.25em; background: none repeat scroll 0 0 #E9FBE9; border-color: #52E052; }
+ .warning { background-color: #F9F0D4; border: medium double #FF0000; margin: 1em; padding: 1em; }
+ .note em, .warning em, .note i, .warning i { font-style: normal; }
+ p.note, div.note { padding: 0.5em 2em; }
+ span.note { padding: 0 2em; }
+ .note p:first-child, .warning p:first-child { margin-top: 0; }
+ .note p:last-child, .warning p:last-child { margin-bottom: 0; }
+ .warning:before { font-style: normal; }
+ p.note:before { content: 'Note: '; font-weight: bolder;}
+ p.warning:before { content: '\26A0 Warning! '; font-weight:bolder;}
+ .critical {margin:1em; border:double red; padding:1em; background-color:#F9F0D4;}
+
+ .bookkeeping:before { display: block; content: 'Bookkeeping details'; font-weight: bolder; font-style: italic; }
+ .bookkeeping { font-size: 0.8em; margin: 2em 0; }
+ .bookkeeping p { margin: 0.5em 2em; display: list-item; list-style: square; }
+ .bookkeeping dt { margin: 0.5em 2em 0; }
+ .bookkeeping dd { margin: 0 3em 0.5em; }
+
+ h4 { position: relative; z-index: 3; }
+ h4 + .element, h4 + div + .element { margin-top: -2.5em; padding-top: 2em; }
+ .element {
+ background: #F4F4FA;
+ color: black;
+ margin: 0 0 1em 0.15em;
+ padding: 0 1em 0.25em 0.75em;
+ border-left: solid #9999FF 0.25em;
+ position: relative;
+ z-index: 1;
+ }
+ .element:before {
+ position: absolute;
+ z-index: 2;
+ top: 0;
+ left: -1.15em;
+ height: 2em;
+ width: 0.9em;
+ background: #F4F4FA;
+ content: ' ';
+ border-style: none none solid solid;
+ border-color: #9999FF;
+ border-width: 0.25em;
+ }
+
+ .example { display: block; color: #222222; background: #FCFCFC; border-left-style: solid;border-color:#c0c0c0; border-left-width: 0.25em; margin-left: 1em; padding-left: 1em;padding-bottom: 0.5em;}
+ div.example:before { content: 'Code Example: '; font-weight: bolder;}
+ td > .example:only-child { margin: 0 0 0 0.1em; }
+
+ ul.domTree, ul.domTree ul { padding: 0 0 0 1em; margin: 0; }
+ ul.domTree li { padding: 0; margin: 0; list-style: none; position: relative; }
+ ul.domTree li li { list-style: none; }
+ ul.domTree li:first-child::before { position: absolute; top: 0; height: 0.6em; left: -0.75em; width: 0.5em; border-style: none none solid solid; content: ''; border-width: 0.1em; }
+ ul.domTree li:not(:last-child)::after { position: absolute; top: 0; bottom: -0.6em; left: -0.75em; width: 0.5em; border-style: none none solid solid; content: ''; border-width: 0.1em; }
+ ul.domTree span { font-style: italic; font-family: serif; }
+ ul.domTree .t1 code { color: purple; font-weight: bold; }
+ ul.domTree .t2 { font-style: normal; font-family: monospace; }
+ ul.domTree .t2 .name { color: black; font-weight: bold; }
+ ul.domTree .t2 .value { color: blue; font-weight: normal; }
+ ul.domTree .t3 code, .domTree .t4 code, .domTree .t5 code { color: gray; }
+ ul.domTree .t7 code, .domTree .t8 code { color: green; }
+ ul.domTree .t10 code { color: teal; }
+
+ body.dfnEnabled dfn { cursor: pointer; }
+ .dfnPanel {
+ display: inline;
+ position: absolute;
+ z-index: 10;
+ height: auto;
+ width: auto;
+ padding: 0.5em 0.75em;
+ font: small sans-serif, Droid Sans Fallback;
+ background: #DDDDDD;
+ color: black;
+ border: outset 0.2em;
+ }
+ .dfnPanel * { margin: 0; padding: 0; font: inherit; text-indent: 0; }
+ .dfnPanel :link, .dfnPanel :visited { color: black; }
+ .dfnPanel p { font-weight: bolder; }
+ .dfnPanel * + p { margin-top: 0.25em; }
+ .dfnPanel li { list-style-position: inside; }
+
+ #configUI { position: absolute; z-index: 20; top: 10em; right: 1em; width: 11em; font-size: small; }
+ #configUI p { margin: 0.5em 0; padding: 0.3em; background: #EEEEEE; color: black; border: inset thin; }
+ #configUI p label { display: block; }
+ #configUI #updateUI, #configUI .loginUI { text-align: center; }
+ #configUI input[type=button] { display: block; margin: auto; }
+
+ fieldset { margin: 1em; padding: 0.5em 1em; }
+ fieldset > legend + * { margin-top: 0; }
+ fieldset > :last-child { margin-bottom: 0; }
+ fieldset p { margin: 0.5em 0; }
+ header p.subline {color:#005A9C; font: 140% sans-serif;margin: 0.75em 0;}
+ #authorButton {overflow: visible; padding: 0.1em 0.3em; position: fixed; right: 2em; top: 6em; width: auto;}
+
+ @media print {#authorButton { display:none;}}
+
+ </style><link href="http://www.w3.org/StyleSheets/TR/W3C-ED" rel="stylesheet" type="text/css"><!--<link href="switcher/W3C-ED-au.css" rel="stylesheet" type="text/css">--><script>
+ function getCookie(name) {
+ var params = location.search.substr(1).split("&");
+ for (var index = 0; index < params.length; index++) {
+ if (params[index] == name)
+ return "1";
+ var data = params[index].split("=");
+ if (data[0] == name)
+ return unescape(data[1]);
+ }
+ var cookies = document.cookie.split("; ");
+ for (var index = 0; index < cookies.length; index++) {
+ var data = cookies[index].split("=");
+ if (data[0] == name)
+ return unescape(data[1]);
+ }
+ return null;
+ }
+ </script><!-- style switcher script by Stommepoes --><link href="switcher/author-view.css" id="author-view" rel="alternate stylesheet" title="Author documentation only"><script src="switcher/authorstylesheet.js"></script><link href="iana.html" rel="prev" title="12 IANA considerations">
+ <link href="Overview.html#contents" rel="contents" title="Table of contents">
+ <link href="references.html" rel="next" title="References">
+ <body class="split chapter" onload="fixBrokenLink();"><div class="head" id="head">
+<header><span id="styleSwitch"></span>
+ <p><a href="http://www.w3.org/"><img alt="W3C" height="48" src="http://www.w3.org/Icons/w3c_home" width="72"></a></p>
+
+ <h1 id="big-title">HTML 5.1
+ Nightly
+ </h1>
+ <p class="no-num no-toc subline">A vocabulary and associated APIs for HTML and XHTML</p>
+ <p class="no-num no-toc subline">Editor's Draft 16 January 2014</p>
+ </header></div>
+
+
+ <nav class="prev_next">
+ <a href="iana.html">← 12 IANA considerations</a> –
+ <a href="Overview.html#contents">Table of contents</a> –
+ <a href="references.html">References →</a>
+ <ol class="toc"><li><a class="no-num" href="index.html#index">Index</a>
+ <ol><li><a class="no-num" href="index.html#elements-1">Elements</a><li><a class="no-num" href="index.html#element-content-categories">Element content categories</a><li><a class="no-num" href="index.html#attributes-1">Attributes</a><li><a class="no-num" href="index.html#element-interfaces">Element Interfaces</a><li><a class="no-num" href="index.html#all-interfaces">All Interfaces</a><li><a class="no-num" href="index.html#events-0">Events</a></ol></ol></nav>
+
+ <h2 class="no-num" id="index">Index</h2>
+
+ <div class="impl">
+
+ <p>The following sections only cover conforming elements and features.</p>
+
+ </div>
+
+ <h3 class="no-num" id="elements-1">Elements</h3>
+
+ <p><i>This section is non-normative.</i></p>
+ <!-- XXX this index doesn't list the palpable elements -->
+
+ <table><caption>List of elements</caption>
+ <thead><tr><th> Element
+ <th> Description
+ <th> Categories
+ <th> Parents†
+ <th> Children
+ <th> Attributes
+ <th> Interface
+ <tbody><tr><th><code><a href="text-level-semantics.html#the-a-element">a</a></code></th>
+ <td>Hyperlink</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a href="dom.html#transparent">transparent</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-hyperlink-href"><a href="links.html#href-3">href</a></code>;
+ <code data-anolis-xref="attr-hyperlink-target"><a href="links.html#target-4">target</a></code>;
+ <code data-anolis-xref="attr-hyperlink-download"><a href="links.html#download-1">download</a></code>;
+<!--PING-->
+ <code data-anolis-xref="attr-hyperlink-rel"><a href="links.html#rel-3">rel</a></code>;
+ <code data-anolis-xref="attr-hyperlink-hreflang"><a href="links.html#hreflang-3">hreflang</a></code>;
+ <code data-anolis-xref="attr-hyperlink-type"><a href="links.html#type-14">type</a></code></td>
+ <td><code><a href="text-level-semantics.html#htmlanchorelement">HTMLAnchorElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-abbr-element">abbr</a></code></th>
+ <td>Abbreviation</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-address-element">address</a></code></th>
+ <td>Contact information for a page or <code><a href="sections.html#the-article-element">article</a></code> element</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-area-element">area</a></code></th>
+ <td>Hyperlink or dead area on an image map</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-area-alt"><a href="embedded-content-0.html#alt-2">alt</a></code>;
+ <code data-anolis-xref="attr-area-coords"><a href="embedded-content-0.html#coords">coords</a></code>;
+ <code data-anolis-xref="attr-area-shape"><a href="embedded-content-0.html#shape">shape</a></code>;
+ <code data-anolis-xref="attr-hyperlink-href"><a href="links.html#href-3">href</a></code>;
+ <code data-anolis-xref="attr-hyperlink-target"><a href="links.html#target-4">target</a></code>;
+ <code data-anolis-xref="attr-hyperlink-download"><a href="links.html#download-1">download</a></code>;
+<!--PING-->
+ <code data-anolis-xref="attr-hyperlink-rel"><a href="links.html#rel-3">rel</a></code>;
+ <code data-anolis-xref="attr-hyperlink-hreflang"><a href="links.html#hreflang-3">hreflang</a></code>;
+ <code data-anolis-xref="attr-hyperlink-type"><a href="links.html#type-14">type</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlareaelement">HTMLAreaElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-article-element">article</a></code></th>
+ <td>Self-contained syndicatable or reusable composition</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning content" href="dom.html#sectioning-content-0">sectioning</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-aside-element">aside</a></code></th>
+ <td>Sidebar for tangentially related content</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning content" href="dom.html#sectioning-content-0">sectioning</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-audio-element">audio</a></code></th>
+ <td>Audio player</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><code><a href="embedded-content-0.html#the-source-element">source</a></code>*;
+ <a href="dom.html#transparent">transparent</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-media-src"><a href="embedded-content-0.html#src-9">src</a></code>;
+ <code data-anolis-xref="attr-media-crossorigin"><a href="embedded-content-0.html#crossorigin-3">crossorigin</a></code>;
+ <code data-anolis-xref="attr-media-preload"><a href="embedded-content-0.html#preload">preload</a></code>;
+ <code data-anolis-xref="attr-media-autoplay"><a href="embedded-content-0.html#autoplay">autoplay</a></code>;
+ <code data-anolis-xref="attr-media-mediagroup"><a href="embedded-content-0.html#mediagroup">mediagroup</a></code>;
+ <code data-anolis-xref="attr-media-loop"><a href="embedded-content-0.html#loop">loop</a></code>;
+ <code data-anolis-xref="attr-media-muted"><a href="embedded-content-0.html#muted-1">muted</a></code>;
+ <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">controls</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlaudioelement">HTMLAudioElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-b-element">b</a></code></th>
+ <td>Keywords</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="document-metadata.html#the-base-element">base</a></code></th>
+ <td>Base URL and default target <a href="browsers.html#browsing-context">browsing context</a> for <a data-anolis-xref="attr-hyperlink-target" href="links.html#target-4">hyperlinks</a> and <a data-anolis-xref="attr-fs-target" href="forms.html#target-5">forms</a></td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a></td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-base-href"><a href="document-metadata.html#href">href</a></code>;
+ <code data-anolis-xref="attr-base-target"><a href="document-metadata.html#target-0">target</a></code></td>
+ <td><code><a href="document-metadata.html#htmlbaseelement">HTMLBaseElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-bdi-element">bdi</a></code></th>
+ <td>Text directionality isolation</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-bdo-element">bdo</a></code></th>
+ <td>Text directionality formatting</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-blockquote-element">blockquote</a></code></th>
+ <td>A section quoted from another source</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-blockquote-cite"><a href="grouping-content.html#cite">cite</a></code></td>
+ <td><code><a href="grouping-content.html#htmlquoteelement">HTMLQuoteElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-body-element">body</a></code></th>
+ <td>Document body</td>
+ <td><a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a></td>
+ <td><code><a href="semantics.html#the-html-element">html</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="handler-window-onafterprint"><a href="webappapis.html#onafterprint">onafterprint</a></code>;
+ <code data-anolis-xref="handler-window-onbeforeprint"><a href="webappapis.html#onbeforeprint">onbeforeprint</a></code>;
+ <code data-anolis-xref="handler-window-onbeforeunload"><a href="webappapis.html#onbeforeunload">onbeforeunload</a></code>;
+ <code data-anolis-xref="handler-window-onhashchange"><a href="webappapis.html#onhashchange">onhashchange</a></code>;
+ <code data-anolis-xref="handler-window-onmessage"><a href="webappapis.html#onmessage">onmessage</a></code>;
+ <code data-anolis-xref="handler-window-onoffline"><a href="webappapis.html#onoffline">onoffline</a></code>;
+ <code data-anolis-xref="handler-window-ononline"><a href="webappapis.html#ononline">ononline</a></code>;
+ <code data-anolis-xref="handler-window-onpagehide"><a href="webappapis.html#onpagehide">onpagehide</a></code>;
+ <code data-anolis-xref="handler-window-onpageshow"><a href="webappapis.html#onpageshow">onpageshow</a></code>;
+ <code data-anolis-xref="handler-window-onpopstate"><a href="webappapis.html#onpopstate">onpopstate</a></code>;
+ <code data-anolis-xref="handler-window-onstorage"><a href="webappapis.html#onstorage">onstorage</a></code>;
+ <code data-anolis-xref="handler-window-onunload"><a href="webappapis.html#onunload">onunload</a></code></td>
+ <td><code><a href="sections.html#htmlbodyelement">HTMLBodyElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-br-element">br</a></code></th>
+ <td>Line break, e.g. in poem or postal address</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="text-level-semantics.html#htmlbrelement">HTMLBRElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-button-element">button</a></code></th>
+ <td>Button control</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a>;
+ <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">submittable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">autofocus</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">disabled</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-fs-formaction"><a href="forms.html#formaction">formaction</a></code>;
+ <code data-anolis-xref="attr-fs-formenctype"><a href="forms.html#formenctype">formenctype</a></code>;
+ <code data-anolis-xref="attr-fs-formmethod"><a href="forms.html#formmethod">formmethod</a></code>;
+ <code data-anolis-xref="attr-fs-formnovalidate"><a href="forms.html#formnovalidate">formnovalidate</a></code>;
+ <code data-anolis-xref="attr-fs-formtarget"><a href="forms.html#formtarget">formtarget</a></code>;
+ <code data-anolis-xref="attr-button-menu"><a href="forms.html#menu-1">menu</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code>;
+ <code data-anolis-xref="attr-button-type"><a href="forms.html#type-17">type</a></code>;
+ <code data-anolis-xref="attr-button-value"><a href="forms.html#value-9">value</a></code></td>
+ <td><code><a href="forms.html#htmlbuttonelement">HTMLButtonElement</a></code></td>
+ <tr><th><code><a href="scripting-1.html#the-canvas-element">canvas</a></code></th>
+ <td>Scriptable bitmap canvas</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a href="dom.html#transparent">transparent</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-canvas-width"><a href="scripting-1.html#width-3">width</a></code>;
+ <code data-anolis-xref="attr-canvas-height"><a href="scripting-1.html#height-3">height</a></code></td>
+ <td><code><a href="scripting-1.html#htmlcanvaselement">HTMLCanvasElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-caption-element">caption</a></code></th>
+ <td>Table caption</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="tabular-data.html#htmltablecaptionelement">HTMLTableCaptionElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-cite-element">cite</a></code></th>
+ <td>Title of a work</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-code-element">code</a></code></th>
+ <td>Computer code</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-col-element">col</a></code></th>
+ <td>Table column</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-colgroup-element">colgroup</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-col-span"><a href="tabular-data.html#span-1">span</a></code></td>
+ <td><code><a href="tabular-data.html#htmltablecolelement">HTMLTableColElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-colgroup-element">colgroup</a></code></th>
+ <td>Group of columns in a table</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><code><a href="tabular-data.html#the-col-element">col</a></code>*;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-colgroup-span"><a href="tabular-data.html#span">span</a></code></td>
+ <td><code><a href="tabular-data.html#htmltablecolelement">HTMLTableColElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-data-element">data</a></code></th>
+ <td>Machine-readable equivalent</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-data-value"><a href="text-level-semantics.html#value-2">value</a></code></td>
+ <td><code><a href="text-level-semantics.html#htmldataelement">HTMLDataElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-datalist-element">datalist</a></code></th>
+ <td>Container for options for <a data-anolis-xref="attr-input-list" href="forms.html#list">combo box control</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <code><a href="forms.html#the-option-element">option</a></code></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="forms.html#htmldatalistelement">HTMLDataListElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-dd-element">dd</a></code></th>
+ <td>Content for corresponding <code><a href="grouping-content.html#the-dt-element">dt</a></code> element(s)</td>
+ <td>none</td>
+ <td><code><a href="grouping-content.html#the-dl-element">dl</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="edits.html#the-del-element">del</a></code></th>
+ <td>A removal from the document</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a href="dom.html#transparent">transparent</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-mod-cite"><a href="edits.html#cite-2">cite</a></code>;
+ <code data-anolis-xref="attr-mod-datetime"><a href="edits.html#datetime-1">datetime</a></code></td>
+ <td><code><a href="edits.html#htmlmodelement">HTMLModElement</a></code></td>
+ <tr><th><code><a href="interactive-elements.html#the-details-element">details</a></code></th>
+ <td>Disclosure control for hiding details</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="interactive-elements.html#the-summary-element">summary</a></code>*;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-details-open"><a href="interactive-elements.html#open">open</a></code></td>
+ <td><code><a href="interactive-elements.html#htmldetailselement">HTMLDetailsElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-dfn-element">dfn</a></code></th>
+ <td>Defining instance</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="interactive-elements.html#the-dialog-element">dialog</a></code></th>
+ <td>Dialog box or window</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-dialog-open"><a href="interactive-elements.html#open-1">open</a></code></td>
+ <td><code><a href="interactive-elements.html#htmldialogelement">HTMLDialogElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-div-element">div</a></code></th>
+ <td>Generic flow container</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="grouping-content.html#htmldivelement">HTMLDivElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-dl-element">dl</a></code></th>
+ <td>Association list consisting of zero or more name-value groups</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="grouping-content.html#the-dt-element">dt</a></code>*;
+ <code><a href="grouping-content.html#the-dd-element">dd</a></code>*;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="grouping-content.html#htmldlistelement">HTMLDListElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-dt-element">dt</a></code></th>
+ <td>Legend for corresponding <code><a href="grouping-content.html#the-dd-element">dd</a></code> element(s)</td>
+ <td>none</td>
+ <td><code><a href="grouping-content.html#the-dl-element">dl</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-em-element">em</a></code></th>
+ <td>Stress emphasis</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-embed-element">embed</a></code></th>
+ <td><a href="infrastructure.html#plugin">Plugin</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-embed-src"><a href="embedded-content-0.html#src-3">src</a></code>;
+ <code data-anolis-xref="attr-embed-type"><a href="embedded-content-0.html#type-7">type</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">width</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">height</a></code>;
+ any*</td>
+ <td><code><a href="embedded-content-0.html#htmlembedelement">HTMLEmbedElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-fieldset-element">fieldset</a></code></th>
+ <td>Group of form controls</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a>;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="forms.html#the-legend-element">legend</a></code>*;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-fieldset-disabled"><a href="forms.html#disabled-10">disabled</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code></td>
+ <td><code><a href="forms.html#htmlfieldsetelement">HTMLFieldSetElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-figcaption-element">figcaption</a></code></th>
+ <td>Caption for <code><a href="grouping-content.html#the-figure-element">figure</a></code></td>
+ <td>none</td>
+ <td><code><a href="grouping-content.html#the-figure-element">figure</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-figure-element">figure</a></code></th>
+ <td>Figure with optional caption</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="grouping-content.html#the-figcaption-element">figcaption</a></code>*;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-footer-element">footer</a></code></th>
+ <td>Footer for a page or section</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-form-element">form</a></code></th>
+ <td>User-submittable form</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-form-accept-charset"><a href="forms.html#accept-charset">accept-charset</a></code>;
+ <code data-anolis-xref="attr-fs-action"><a href="forms.html#action">action</a></code>;
+ <code data-anolis-xref="attr-form-autocomplete"><a href="forms.html#autocomplete">autocomplete</a></code>;
+ <code data-anolis-xref="attr-fs-enctype"><a href="forms.html#enctype">enctype</a></code>;
+ <code data-anolis-xref="attr-fs-method"><a href="forms.html#method">method</a></code>;
+ <code data-anolis-xref="attr-form-name"><a href="forms.html#name-9">name</a></code>;
+ <code data-anolis-xref="attr-fs-novalidate"><a href="forms.html#novalidate">novalidate</a></code>;
+ <code data-anolis-xref="attr-fs-target"><a href="forms.html#target-5">target</a></code></td>
+ <td><code><a href="forms.html#htmlformelement">HTMLFormElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h1</a></code>, <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h2</a></code>, <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h3</a></code>, <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h4</a></code>, <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h5</a></code>, <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h6</a></code></th>
+ <td>Section heading</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Heading content" href="dom.html#heading-content-0">heading</a></td>
+ <!-- hgroup removed SF-->
+ <td>
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code></td>
+ <tr><th><code><a href="document-metadata.html#the-head-element">head</a></code></th>
+ <td>Container for document metadata</td>
+ <td>none</td>
+ <td><code><a href="semantics.html#the-html-element">html</a></code></td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata content</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="document-metadata.html#htmlheadelement">HTMLHeadElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-header-element">header</a></code></th>
+ <td>Introductory or navigational aids for a page or section</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ </tr><!--FORK: removed hgroup--><tr><th><code><a href="grouping-content.html#the-hr-element">hr</a></code></th>
+ <td>Thematic break</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="grouping-content.html#htmlhrelement">HTMLHRElement</a></code></td>
+ <tr><th><code><a href="semantics.html#the-html-element">html</a></code></th>
+ <td>Root element</td>
+ <td>none</td>
+ <td>none*</td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>*;
+ <code><a href="sections.html#the-body-element">body</a></code>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-html-manifest"><a href="semantics.html#manifest">manifest</a></code></td>
+ <td><code><a href="semantics.html#htmlhtmlelement">HTMLHtmlElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-i-element">i</a></code></th>
+ <td>Alternate voice</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code></th>
+ <td><a href="browsers.html#nested-browsing-contexts-0">Nested browsing context</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>text*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-iframe-src"><a href="embedded-content-0.html#src-1">src</a></code>;
+ <code data-anolis-xref="attr-iframe-srcdoc"><a href="embedded-content-0.html#srcdoc">srcdoc</a></code>;
+ <code data-anolis-xref="attr-iframe-name"><a href="embedded-content-0.html#name-1">name</a></code>;
+ <code data-anolis-xref="attr-iframe-sandbox"><a href="embedded-content-0.html#sandbox">a/a></code>;
+ <code data-anolis-xref="attr-iframe-seamless"><a href="embedded-content-0.html#seamless">seamless</a></code>;
+ <code data-anolis-xref="attr-iframe-allowfullscreen"><a href="embedded-content-0.html#allowfullscreen">allowfullscreen</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">width</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">height</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmliframeelement">HTMLIFrameElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-img-element">img</a></code></th>
+ <td>Image</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>*;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-img-alt"><a href="embedded-content-0.html#alt-0">alt</a></code>;
+ <code data-anolis-xref="attr-img-src"><a href="embedded-content-0.html#src">src</a></code>;
+ <code data-anolis-xref="attr-img-crossorigin"><a href="embedded-content-0.html#crossorigin-1">crossorigin</a></code>;
+ <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">usemap</a></code>;
+ <code data-anolis-xref="attr-img-ismap"><a href="embedded-content-0.html#ismap">ismap</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">width</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">height</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlimageelement">HTMLImageElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-input-element">input</a></code></th>
+ <td>Form control</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>*;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a>;
+ <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">submittable</a>;
+ <a data-anolis-xref="category-reset" href="forms.html#resettable-elements">resettable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-input-accept"><a href="forms.html#accept-0">accept</a></code>;
+ <code data-anolis-xref="attr-input-alt"><a href="forms.html#alt-5">alt</a></code>;
+ <code data-anolis-xref="attr-fe-autocomplete"><a href="forms.html#autocomplete-1">autocomplete</a></code>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">autofocus</a></code>;
+ <code data-anolis-xref="attr-input-checked"><a href="forms.html#checked">checked</a></code>;
+ <code data-anolis-xref="attr-fe-dirname"><a href="forms.html#dirname-1">dirname</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">disabled</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-fs-formaction"><a href="forms.html#formaction">formaction</a></code>;
+ <code data-anolis-xref="attr-fs-formenctype"><a href="forms.html#formenctype">formenctype</a></code>;
+ <code data-anolis-xref="attr-fs-formmethod"><a href="forms.html#formmethod">formmethod</a></code>;
+ <code data-anolis-xref="attr-fs-formnovalidate"><a href="forms.html#formnovalidate">formnovalidate</a></code>;
+ <code data-anolis-xref="attr-fs-formtarget"><a href="forms.html#formtarget">formtarget</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">height</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode"><a href="forms.html#inputmode-1">inputmode</a></code>;
+ <code data-anolis-xref="attr-input-list"><a href="forms.html#list">list</a></code>;
+ <code data-anolis-xref="attr-input-max"><a href="forms.html#max-0">max</a></code>;
+ <code data-anolis-xref="attr-input-maxlength"><a href="forms.html#maxlength-0">maxlength</a></code>;
+ <code data-anolis-xref="attr-input-min"><a href="forms.html#min-0">min</a></code>;
+ <code data-anolis-xref="attr-input-minlength"><a href="forms.html#minlength-0">minlength</a></code>;
+ <code data-anolis-xref="attr-input-multiple"><a href="forms.html#multiple-0">multiple</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code>;
+ <code data-anolis-xref="attr-input-pattern"><a href="forms.html#pattern-0">pattern</a></code>;
+ <code data-anolis-xref="attr-input-placeholder"><a href="forms.html#placeholder-0">placeholder</a></code>;
+ <code data-anolis-xref="attr-input-readonly"><a href="forms.html#readonly-0">readonly</a></code>;
+ <code data-anolis-xref="attr-input-required"><a href="forms.html#required-0">required</a></code>;
+ <code data-anolis-xref="attr-input-size"><a href="forms.html#size-1">size</a></code>;
+ <code data-anolis-xref="attr-input-src"><a href="forms.html#src-12">src</a></code>;
+ <code data-anolis-xref="attr-input-step"><a href="forms.html#step-0">step</a></code>;
+ <code data-anolis-xref="attr-input-type"><a href="forms.html#type-15">type</a></code>;
+ <code data-anolis-xref="attr-input-value"><a href="forms.html#value-6">value</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">width</a></code></td>
+ <td><code><a href="forms.html#htmlinputelement">HTMLInputElement</a></code></td>
+ <tr><th><code><a href="edits.html#the-ins-element">ins</a></code></th>
+ <td>An addition to the document</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a href="dom.html#transparent">transparent</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-mod-cite"><a href="edits.html#cite-2">cite</a></code>;
+ <code data-anolis-xref="attr-mod-datetime"><a href="edits.html#datetime-1">datetime</a></code></td>
+ <td><code><a href="edits.html#htmlmodelement">HTMLModElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-kbd-element">kbd</a></code></th>
+ <td>User input</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-keygen-element">keygen</a></code></th>
+ <td>Cryptographic key-pair generator form control</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a>;
+ <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">submittable</a>;
+ <a data-anolis-xref="category-reset" href="forms.html#resettable-elements">resettable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">autofocus</a></code>;
+ <code data-anolis-xref="attr-keygen-challenge"><a href="forms.html#challenge">challenge</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">disabled</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-keygen-keytype"><a href="forms.html#keytype">keytype</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code></td>
+ <td><code><a href="forms.html#htmlkeygenelement">HTMLKeygenElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-label-element">label</a></code></th>
+ <td>Caption for a form control</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-label-for"><a href="forms.html#for">for</a></code></td>
+ <td><code><a href="forms.html#htmllabelelement">HTMLLabelElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-legend-element">legend</a></code></th>
+ <td>Caption for <code><a href="forms.html#the-fieldset-element">fieldset</a></code></td>
+ <td>none</td>
+ <td><code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="forms.html#htmllegendelement">HTMLLegendElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-li-element">li</a></code></th>
+ <td>List item</td>
+ <td>none</td>
+ <td><code><a href="grouping-content.html#the-ol-element">ol</a></code>;
+ <code><a href="grouping-content.html#the-ul-element">ul</a></code>;
+ <code><a href="interactive-elements.html#the-menu-element">menu</a></code>*;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-li-value"><a href="grouping-content.html#value-0">value</a></code>*</td>
+ <td><code><a href="grouping-content.html#htmllielement">HTMLLIElement</a></code></td>
+ <tr><th><code><a href="document-metadata.html#the-link-element">link</a></code></th>
+ <td>Link metadata</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>;
+ <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>*;
+ <a data-anolis-xref="phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-link-href"><a href="document-metadata.html#href-1">href</a></code>;
+ <code data-anolis-xref="attr-link-crossorigin"><a href="document-metadata.html#crossorigin">crossorigin</a></code>;
+ <code data-anolis-xref="attr-link-rel"><a href="document-metadata.html#rel">rel</a></code>;
+ <code data-anolis-xref="attr-link-media"><a href="document-metadata.html#media">media</a></code>;
+ <code data-anolis-xref="attr-link-hreflang"><a href="document-metadata.html#hreflang">hreflang</a></code>;
+ <code data-anolis-xref="attr-link-type"><a href="document-metadata.html#type-0">type</a></code>;
+ <code data-anolis-xref="attr-link-sizes"><a href="links.html#sizes-0">sizes</a></code></td>
+ <td><code><a href="document-metadata.html#htmllinkelement">HTMLLinkElement</a></code></td>
+ </tr><!-- main is main content of doc not body SF--><tr><th><code><a href="grouping-content.html#the-main-element">main</a></code></th>
+ <td>Main content of a document
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code>
+ <tr><th><code><a href="embedded-content-0.html#the-map-element">map</a></code></th>
+ <td><a href="embedded-content-0.html#image-map">Image map</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a href="dom.html#transparent">transparent</a>;
+ <code><a href="embedded-content-0.html#the-area-element">area</a></code>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-map-name"><a href="embedded-content-0.html#name-7">name</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlmapelement">HTMLMapElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-mark-element">mark</a></code></th>
+ <td>Highlight</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="interactive-elements.html#the-menu-element">menu</a></code></th>
+ <td>Menu of commands</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <code><a href="interactive-elements.html#the-menu-element">menu</a></code>*</td>
+ <td><code><a href="grouping-content.html#the-li-element">li</a></code>*;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*;
+ <code><a href="interactive-elements.html#the-menuitem-element">menuitem</a></code>*;
+ <code><a href="grouping-content.html#the-hr-element">hr</a></code>*;
+ <code><a href="interactive-elements.html#the-menu-element">menu</a></code>*;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-menu-type"><a href="interactive-elements.html#type-24">type</a></code>;
+ <code data-anolis-xref="attr-menu-label"><a href="interactive-elements.html#label-7">label</a></code></td>
+ <td><code><a href="interactive-elements.html#htmlmenuelement">HTMLMenuElement</a></code></td>
+ <tr><th><code><a href="interactive-elements.html#the-menuitem-element">menuitem</a></code></th>
+ <td>Menu command</td>
+ <td>none</td>
+ <td><code><a href="interactive-elements.html#the-menu-element">menu</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-menuitem-type"><a href="interactive-elements.html#type-26">type</a></code>;
+ <code data-anolis-xref="attr-menuitem-label"><a href="interactive-elements.html#label-9">label</a></code>;
+ <code data-anolis-xref="attr-menuitem-icon"><a href="interactive-elements.html#icon">icon</a></code>;
+ <code data-anolis-xref="attr-menuitem-disabled"><a href="interactive-elements.html#disabled-15">disabled</a></code>;
+ <code data-anolis-xref="attr-menuitem-checked"><a href="interactive-elements.html#checked-1">checked</a></code>;
+ <code data-anolis-xref="attr-menuitem-radiogroup"><a href="interactive-elements.html#radiogroup">radiogroup</a></code>;
+ <code data-anolis-xref="attr-menuitem-default"><a href="interactive-elements.html#default-4">default</a></code>;
+ <code data-anolis-xref="attr-menuitem-command"><a href="interactive-elements.html#command-1">command</a></code></td>
+ <td><code><a href="interactive-elements.html#htmlmenuitemelement">HTMLMenuItemElement</a></code></td>
+ <tr><th><code><a href="document-metadata.html#the-meta-element">meta</a></code></th>
+ <td>Text metadata</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>;
+ <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>*;
+ <a data-anolis-xref="phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-meta-name"><a href="document-metadata.html#name">name</a></code>;
+ <code data-anolis-xref="attr-meta-http-equiv"><a href="document-metadata.html#http-equiv">http-equiv</a></code>;
+ <code data-anolis-xref="attr-meta-content"><a href="document-metadata.html#content">content</a></code>;
+ <code data-anolis-xref="attr-meta-charset"><a href="document-metadata.html#charset-0">charset</a></code></td>
+ <td><code><a href="document-metadata.html#htmlmetaelement">HTMLMetaElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-meter-element">meter</a></code></th>
+ <td>Gauge</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-meter-value"><a href="forms.html#value-19">value</a></code>;
+ <code data-anolis-xref="attr-meter-min"><a href="forms.html#min-1">min</a></code>;
+ <code data-anolis-xref="attr-meter-max"><a href="forms.html#max-3">max</a></code>;
+ <code data-anolis-xref="attr-meter-low"><a href="forms.html#low">low</a></code>;
+ <code data-anolis-xref="attr-meter-high"><a href="forms.html#high">high</a></code>;
+ <code data-anolis-xref="attr-meter-optimum"><a href="forms.html#optimum">optimum</a></code></td>
+ <td><code><a href="forms.html#htmlmeterelement">HTMLMeterElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-nav-element">nav</a></code></th>
+ <td>Section with navigational links</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning content" href="dom.html#sectioning-content-0">sectioning</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="scripting-1.html#the-noscript-element">noscript</a></code></th>
+ <td>Fallback content for script</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>*;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>*;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td>varies*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-object-element">object</a></code></th>
+ <td>Image, <a href="browsers.html#nested-browsing-contexts-0">nested browsing context</a>, or <a href="infrastructure.html#plugin">plugin</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>*;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">submittable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><code><a href="embedded-content-0.html#the-param-element">param</a></code>*;
+ <a href="dom.html#transparent">transparent</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-object-data"><a href="embedded-content-0.html#data-1">data</a></code>;
+ <code data-anolis-xref="attr-object-type"><a href="embedded-content-0.html#type-9">type</a></code>;
+ <code data-anolis-xref="attr-object-typemustmatch"><a href="embedded-content-0.html#typemustmatch">typemustmatch</a></code>;
+ <code data-anolis-xref="attr-object-name"><a href="embedded-content-0.html#name-3">name</a></code>;
+ <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">usemap</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">width</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">height</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlobjectelement">HTMLObjectElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-ol-element">ol</a></code></th>
+ <td>Ordered list</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="grouping-content.html#the-li-element">li</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-ol-reversed"><a href="grouping-content.html#reversed">reversed</a></code>;
+ <code data-anolis-xref="attr-ol-start"><a href="grouping-content.html#start-0">start</a></code>;
+ <code data-anolis-xref="attr-ol-type"><a href="grouping-content.html#type-4">type</a></code></td>
+ <td><code><a href="grouping-content.html#htmlolistelement">HTMLOListElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-optgroup-element">optgroup</a></code></th>
+ <td>Group of options in a list box</td>
+ <td>none</td>
+ <td><code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><code><a href="forms.html#the-option-element">option</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-optgroup-disabled"><a href="forms.html#disabled-5">disabled</a></code>;
+ <code data-anolis-xref="attr-optgroup-label"><a href="forms.html#label-2">label</a></code></td>
+ <td><code><a href="forms.html#htmloptgroupelement">HTMLOptGroupElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-option-element">option</a></code></th>
+ <td>Option in a list box or combo box control</td>
+ <td>none</td>
+ <td><code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-datalist-element">datalist</a></code>;
+ <code><a href="forms.html#the-optgroup-element">optgroup</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="text content" href="dom.html#text-1">text</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-option-disabled"><a href="forms.html#disabled-7">disabled</a></code>;
+ <code data-anolis-xref="attr-option-label"><a href="forms.html#label-4">label</a></code>;
+ <code data-anolis-xref="attr-option-selected"><a href="forms.html#selected">selected</a></code>;
+ <code data-anolis-xref="attr-option-value"><a href="forms.html#value-12">value</a></code></td>
+ <td><code><a href="forms.html#htmloptionelement">HTMLOptionElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-output-element">output</a></code></th>
+ <td>Calculated output value</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a>;
+ <a data-anolis-xref="category-reset" href="forms.html#resettable-elements">resettable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-output-for"><a href="forms.html#for-0">for</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code></td>
+ <td><code><a href="forms.html#htmloutputelement">HTMLOutputElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-p-element">p</a></code></th>
+ <td>Paragraph</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="grouping-content.html#htmlparagraphelement">HTMLParagraphElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-param-element">param</a></code></th>
+ <td>Parameter for <code><a href="embedded-content-0.html#the-object-element">object</a></code></td>
+ <td>none</td>
+ <td><code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-param-name"><a href="embedded-content-0.html#name-5">name</a></code>;
+ <code data-anolis-xref="attr-param-value"><a href="embedded-content-0.html#value-4">value</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlparamelement">HTMLParamElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-pre-element">pre</a></code></th>
+ <td>Block of preformatted text</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="grouping-content.html#htmlpreelement">HTMLPreElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-progress-element">progress</a></code></th>
+ <td>Progress bar</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-progress-value"><a href="forms.html#value-17">value</a></code>;
+ <code data-anolis-xref="attr-progress-max"><a href="forms.html#max-1">max</a></code></td>
+ <td><code><a href="forms.html#htmlprogresselement">HTMLProgressElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-q-element">q</a></code></th>
+ <td>Quotation</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-q-cite"><a href="text-level-semantics.html#cite-1">cite</a></code></td>
+ <td><code><a href="grouping-content.html#htmlquoteelement">HTMLQuoteElement</a></code></td>
+ </tr><!-- FORK --><tr><th><code><a href="text-level-semantics.html#the-rb-element">rb</a></code></th>
+ <td>Ruby base</td>
+ <td>none</td>
+ <td><code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ </tr><!-- /FORK --><tr><th><code><a href="text-level-semantics.html#the-rp-element">rp</a></code></th>
+ <td>Parenthesis for ruby annotation text</td>
+ <td>none</td>
+ <td><code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-rt-element">rt</a></code></th>
+ <td>Ruby annotation text</td>
+ <td>none</td>
+ <td><code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <!-- FORK -->
+ <code><a href="text-level-semantics.html#the-rtc-element">rtc</a></code>;
+ <!-- /FORK -->
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ </tr><!-- FORK --><tr><th><code><a href="text-level-semantics.html#the-rtc-element">rtc</a></code></th>
+ <td>Ruby annotation text container</td>
+ <td>none</td>
+ <td><code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ </tr><!-- /FORK --><tr><th><code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code></th>
+ <td>Ruby annotation(s)</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <code><a href="text-level-semantics.html#the-rp-element">rp</a></code>;
+ <code><a href="text-level-semantics.html#the-rt-element">rt</a></code>;
+ <!-- FORK -->
+ <code><a href="text-level-semantics.html#the-rb-element">rb</a></code>;
+ <code><a href="text-level-semantics.html#the-rtc-element">rtc</a></code>*
+ <!-- /FORK -->
+ </td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-s-element">s</a></code></th>
+ <td>Inaccurate text</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-samp-element">samp</a></code></th>
+ <td>Computer output</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="scripting-1.html#the-script-element">script</a></code></th>
+ <td>Embedded script</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Script-supporting elements" href="dom.html#script-supporting-elements-0">script-supporting</a></td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Script-supporting elements" href="dom.html#script-supporting-elements-0">script-supporting</a></td>
+ <td>script, data, or script documentation*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-script-src"><a href="scripting-1.html#src-13">src</a></code>;
+ <code data-anolis-xref="attr-script-type"><a href="scripting-1.html#type-29">type</a></code>;
+ <code data-anolis-xref="attr-script-charset"><a href="scripting-1.html#charset-1">charset</a></code>;
+ <code data-anolis-xref="attr-script-async"><a href="scripting-1.html#async">async</a></code>;
+ <code data-anolis-xref="attr-script-defer"><a href="scripting-1.html#defer">defer</a></code>;
+ <code data-anolis-xref="attr-script-crossorigin"><a href="scripting-1.html#crossorigin-5">crossorigin</a></code></td>
+ <td><code><a href="scripting-1.html#htmlscriptelement">HTMLScriptElement</a></code></td>
+ <tr><th><code><a href="sections.html#the-section-element">section</a></code></th>
+ <td>Generic document or application section</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Sectioning content" href="dom.html#sectioning-content-0">sectioning</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-select-element">select</a></code></th>
+ <td>List box control</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a>;
+ <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">submittable</a>;
+ <a data-anolis-xref="category-reset" href="forms.html#resettable-elements">resettable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><code><a href="forms.html#the-option-element">option</a></code>, <code><a href="forms.html#the-optgroup-element">optgroup</a></code></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">autofocus</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">disabled</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-select-multiple"><a href="forms.html#multiple-1">multiple</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code>;
+ <code data-anolis-xref="attr-select-required"><a href="forms.html#required-2">required</a></code>;
+ <code data-anolis-xref="attr-select-size"><a href="forms.html#size-2">size</a></code></td>
+ <td><code><a href="forms.html#htmlselectelement">HTMLSelectElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-small-element">small</a></code></th>
+ <td>Side comment</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-source-element">source</a></code></th>
+ <td>Media source for <code><a href="embedded-content-0.html#the-video-element">video</a></code> or <code><a href="embedded-content-0.html#the-audio-element">audio</a></code></td>
+ <td>none</td>
+ <td><code><a href="embedded-content-0.html#the-video-element">video</a></code>;
+ <code><a href="embedded-content-0.html#the-audio-element">audio</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-source-src"><a href="embedded-content-0.html#src-5">src</a></code>;
+ <code data-anolis-xref="attr-source-type"><a href="embedded-content-0.html#type-11">type</a></code>;
+ <code data-anolis-xref="attr-source-media"><a href="embedded-content-0.html#media-3">media</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlsourceelement">HTMLSourceElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-span-element">span</a></code></th>
+ <td>Generic phrasing container</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="text-level-semantics.html#htmlspanelement">HTMLSpanElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-strong-element">strong</a></code></th>
+ <td>Importance</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="document-metadata.html#the-style-element">style</a></code></th>
+ <td>Embedded styling information</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>;
+ <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>*;
+ <a data-anolis-xref="flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td>varies*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-style-media"><a href="document-metadata.html#media-1">media</a></code>;
+ <code data-anolis-xref="attr-style-type"><a href="document-metadata.html#type-2">type</a></code>;
+ <code data-anolis-xref="attr-style-scoped"><a href="document-metadata.html#scoped">scoped</a></code></td>
+ <td><code><a href="document-metadata.html#htmlstyleelement">HTMLStyleElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-sub-and-sup-elements">sub</a></code></th>
+ <td>Subscript</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="interactive-elements.html#the-summary-element">summary</a></code></th>
+ <td>Caption for <code><a href="interactive-elements.html#the-details-element">details</a></code></td>
+ <td>none</td>
+ <td><code><a href="interactive-elements.html#the-details-element">details</a></code></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-sub-and-sup-elements">sup</a></code></th>
+ <td>Superscript</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-table-element">table</a></code></th>
+ <td>Table</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="tabular-data.html#the-caption-element">caption</a></code>*;
+ <code><a href="tabular-data.html#the-colgroup-element">colgroup</a></code>*;
+ <code><a href="tabular-data.html#the-thead-element">thead</a></code>*;
+ <code><a href="tabular-data.html#the-tbody-element">tbody</a></code>*;
+ <code><a href="tabular-data.html#the-tfoot-element">tfoot</a></code>*;
+ <code><a href="tabular-data.html#the-tr-element">tr</a></code>*;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+<!--FORK:table border not in WHATWG spec-->
+ <code data-anolis-xref="attr-table-border"><a href="tabular-data.html#border">border</a></code>
+ <code data-anolis-xref="attr-table-sortable"><a href="tabular-data.html#sortable-0">sortable</a></code></td>
+ <td><code><a href="tabular-data.html#htmltableelement">HTMLTableElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-tbody-element">tbody</a></code></th>
+ <td>Group of rows in a table</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><code><a href="tabular-data.html#the-tr-element">tr</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="tabular-data.html#htmltablesectionelement">HTMLTableSectionElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-td-element">td</a></code></th>
+ <td>Table cell</td>
+ <td><a data-anolis-xref="Sectioning root" href="sections.html#sectioning-roots">sectioning root</a></td>
+ <td><code><a href="tabular-data.html#the-tr-element">tr</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-tdth-colspan"><a href="tabular-data.html#colspan">colspan</a></code>;
+ <code data-anolis-xref="attr-tdth-rowspan"><a href="tabular-data.html#rowspan">rowspan</a></code>;
+ <code data-anolis-xref="attr-tdth-headers"><a href="tabular-data.html#headers">headers</a></code></td>
+ <td><code><a href="tabular-data.html#htmltabledatacellelement">HTMLTableDataCellElement</a></code></td>
+ <tr><th><code><a href="scripting-1.html#the-template-element">template</a></code></th>
+ <td>Template</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Script-supporting elements" href="dom.html#script-supporting-elements-0">script-supporting</a></td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Script-supporting elements" href="dom.html#script-supporting-elements-0">script-supporting</a>;
+ <code><a href="tabular-data.html#the-colgroup-element">colgroup</a></code>*</td>
+ <td>it's complicated*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="scripting-1.html#htmltemplateelement">HTMLTemplateElement</a></code></td>
+ <tr><th><code><a href="forms.html#the-textarea-element">textarea</a></code></th>
+ <td>Multiline text field</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a>;
+ <a data-anolis-xref="category-listed" href="forms.html#listed-elements">listed</a>;
+ <a data-anolis-xref="category-label" href="forms.html#labelable-elements">labelable</a>;
+ <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">submittable</a>;
+ <a data-anolis-xref="category-reset" href="forms.html#resettable-elements">resettable</a>;
+ <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">reassociateable</a>;
+ <a data-anolis-xref="Form-associated element" href="forms.html#form-associated-elements">form-associated</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="text content" href="dom.html#text-1">text</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">autofocus</a></code>;
+ <code data-anolis-xref="attr-textarea-cols"><a href="forms.html#cols">cols</a></code>;
+ <code data-anolis-xref="attr-fe-dirname"><a href="forms.html#dirname-1">dirname</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">disabled</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">form</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode"><a href="forms.html#inputmode-1">inputmode</a></code>;
+ <code data-anolis-xref="attr-textarea-maxlength"><a href="forms.html#maxlength-1">maxlength</a></code>;
+ <code data-anolis-xref="attr-textarea-minlength"><a href="forms.html#minlength-1">minlength</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">name</a></code>;
+ <code data-anolis-xref="attr-textarea-placeholder"><a href="forms.html#placeholder-1">placeholder</a></code>;
+ <code data-anolis-xref="attr-textarea-readonly"><a href="forms.html#readonly-1">readonly</a></code>;
+ <code data-anolis-xref="attr-textarea-required"><a href="forms.html#required-4">required</a></code>;
+ <code data-anolis-xref="attr-textarea-rows"><a href="forms.html#rows-1">rows</a></code>;
+ <code data-anolis-xref="attr-textarea-wrap"><a href="forms.html#wrap">wrap</a></code></td>
+ <td><code><a href="forms.html#htmltextareaelement">HTMLTextAreaElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-tfoot-element">tfoot</a></code></th>
+ <td>Group of footer rows in a table</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><code><a href="tabular-data.html#the-tr-element">tr</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="tabular-data.html#htmltablesectionelement">HTMLTableSectionElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-th-element">th</a></code></th>
+ <td>Table header cell</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-tr-element">tr</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-tdth-colspan"><a href="tabular-data.html#colspan">colspan</a></code>;
+ <code data-anolis-xref="attr-tdth-rowspan"><a href="tabular-data.html#rowspan">rowspan</a></code>;
+ <code data-anolis-xref="attr-tdth-headers"><a href="tabular-data.html#headers">headers</a></code>;
+ <code data-anolis-xref="attr-th-scope"><a href="tabular-data.html#scope-0">scope</a></code>;
+ <code data-anolis-xref="attr-th-sorted"><a href="tabular-data.html#sorted-0">sorted</a></code>;
+ <code data-anolis-xref="attr-th-abbr"><a href="tabular-data.html#abbr">abbr</a></code></td>
+ <td><code><a href="tabular-data.html#htmltableheadercellelement">HTMLTableHeaderCellElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-thead-element">thead</a></code></th>
+ <td>Group of heading rows in a table</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><code><a href="tabular-data.html#the-tr-element">tr</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="tabular-data.html#htmltablesectionelement">HTMLTableSectionElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-time-element">time</a></code></th>
+ <td>Machine-readable equivalent of date- or time-related data</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-time-datetime"><a href="text-level-semantics.html#datetime">datetime</a></code></td>
+ <td><code><a href="text-level-semantics.html#htmltimeelement">HTMLTimeElement</a></code></td>
+ <tr><th><code><a href="document-metadata.html#the-title-element">title</a></code></th>
+ <td>Document title</td>
+ <td><a data-anolis-xref="Metadata content" href="dom.html#metadata-content-0">metadata</a></td>
+ <td><code><a href="document-metadata.html#the-head-element">head</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><a data-anolis-xref="text content" href="dom.html#text-1">text</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="document-metadata.html#htmltitleelement">HTMLTitleElement</a></code></td>
+ <tr><th><code><a href="tabular-data.html#the-tr-element">tr</a></code></th>
+ <td>Table row</td>
+ <td>none</td>
+ <td><code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="tabular-data.html#the-thead-element">thead</a></code>;
+ <code><a href="tabular-data.html#the-tbody-element">tbody</a></code>;
+ <code><a href="tabular-data.html#the-tfoot-element">tfoot</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td><code><a href="tabular-data.html#the-th-element">th</a></code>*;
+ <code><a href="tabular-data.html#the-td-element">td</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="tabular-data.html#htmltablerowelement">HTMLTableRowElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-track-element">track</a></code></th>
+ <td>Timed text track</td>
+ <td>none</td>
+ <td><code><a href="embedded-content-0.html#the-audio-element">audio</a></code>;
+ <code><a href="embedded-content-0.html#the-video-element">video</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-track-default"><a href="embedded-content-0.html#default">default</a></code>;
+ <code data-anolis-xref="attr-track-kind"><a href="embedded-content-0.html#kind">kind</a></code>;
+ <code data-anolis-xref="attr-track-label"><a href="embedded-content-0.html#label">label</a></code>;
+ <code data-anolis-xref="attr-track-src"><a href="embedded-content-0.html#src-7">src</a></code>;
+ <code data-anolis-xref="attr-track-srclang"><a href="embedded-content-0.html#srclang">srclang</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmltrackelement">HTMLTrackElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-u-element">u</a></code></th>
+ <td>Keywords</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="grouping-content.html#the-ul-element">ul</a></code></th>
+ <td>List</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a></td>
+ <td><code><a href="grouping-content.html#the-li-element">li</a></code>;
+ <a href="dom.html#script-supporting-elements-0">script-supporting elements</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="grouping-content.html#htmlulistelement">HTMLUListElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-var-element">var</a></code></th>
+ <td>Variable</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ <tr><th><code><a href="embedded-content-0.html#the-video-element">video</a></code></th>
+ <td>Video player</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a>;
+ <a data-anolis-xref="Embedded content" href="dom.html#embedded-content-2">embedded</a>;
+ <a data-anolis-xref="Interactive content" href="dom.html#interactive-content-0">interactive</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><code><a href="embedded-content-0.html#the-source-element">source</a></code>*;
+ <a href="dom.html#transparent">transparent</a>*</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a>;
+ <code data-anolis-xref="attr-media-src"><a href="embedded-content-0.html#src-9">src</a></code>;
+ <code data-anolis-xref="attr-media-crossorigin"><a href="embedded-content-0.html#crossorigin-3">crossorigin</a></code>;
+ <code data-anolis-xref="attr-video-poster"><a href="embedded-content-0.html#poster">poster</a></code>;
+ <code data-anolis-xref="attr-media-preload"><a href="embedded-content-0.html#preload">preload</a></code>;
+ <code data-anolis-xref="attr-media-autoplay"><a href="embedded-content-0.html#autoplay">autoplay</a></code>;
+ <code data-anolis-xref="attr-media-mediagroup"><a href="embedded-content-0.html#mediagroup">mediagroup</a></code>;
+ <code data-anolis-xref="attr-media-loop"><a href="embedded-content-0.html#loop">loop</a></code>;
+ <code data-anolis-xref="attr-media-muted"><a href="embedded-content-0.html#muted-1">muted</a></code>;
+ <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">controls</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">width</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">height</a></code></td>
+ <td><code><a href="embedded-content-0.html#htmlvideoelement">HTMLVideoElement</a></code></td>
+ <tr><th><code><a href="text-level-semantics.html#the-wbr-element">wbr</a></code></th>
+ <td>Line breaking opportunity</td>
+ <td><a data-anolis-xref="Flow content" href="dom.html#flow-content-1">flow</a>;
+ <a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td><a data-anolis-xref="Phrasing content" href="dom.html#phrasing-content-1">phrasing</a></td>
+ <td>empty</td>
+ <td><a data-anolis-xref="global attributes" href="dom.html#global-attributes">globals</a></td>
+ <td><code><a href="dom.html#htmlelement">HTMLElement</a></code></td>
+ </table><p class="tablenote"><small>An asterisk (*) in a cell indicates that the actual rules are more
+ complicated than indicated in the table above.</small></p>
+
+ <p>† Categories in the "Parents" column refer to parents that list the given categories in
+ their content model, not to elements that themselves are in those categories. For example, the
+ <code><a href="text-level-semantics.html#the-a-element">a</a></code> element's "Parents" column says "phrasing", so any element whose content model
+ contains the "phrasing" category could be a parent of an <code><a href="text-level-semantics.html#the-a-element">a</a></code> element. Since the "flow"
+ category includes all the "phrasing" elements, that means the <code><a href="tabular-data.html#the-th-element">th</a></code> element could be a
+ parent to an <code><a href="text-level-semantics.html#the-a-element">a</a></code> element.</p>
+
+
+
+ <h3 class="no-num" id="element-content-categories">Element content categories</h3>
+
+ <p><i>This section is non-normative.</i></p>
+ <!-- when updating this also check the category-list <ul>s -->
+
+ <table><caption>List of element content categories</caption>
+ <thead><tr><th> Category
+ <th> Elements
+ <th> Elements with exceptions
+ <tbody><tr><td> <a href="dom.html#metadata-content-0">Metadata content</a>
+ <td>
+ <code><a href="document-metadata.html#the-base-element">base</a></code>;
+ <code><a href="document-metadata.html#the-link-element">link</a></code>;
+ <code><a href="document-metadata.html#the-meta-element">meta</a></code>;
+ <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>;
+ <code><a href="scripting-1.html#the-script-element">script</a></code>;
+ <code><a href="document-metadata.html#the-style-element">style</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>;
+ <code><a href="document-metadata.html#the-title-element">title</a></code>
+ <td>
+ —
+
+ <tr><td> <a href="dom.html#flow-content-1">Flow content</a>
+ <td>
+ <code><a href="text-level-semantics.html#the-a-element">a</a></code>;
+ <code><a href="text-level-semantics.html#the-abbr-element">abbr</a></code>;
+ <code><a href="sections.html#the-address-element">address</a></code>;
+ <code><a href="sections.html#the-article-element">article</a></code>;
+ <code><a href="sections.html#the-aside-element">aside</a></code>;
+ <code><a href="embedded-content-0.html#the-audio-element">audio</a></code>;
+ <code><a href="text-level-semantics.html#the-b-element">b</a></code>;
+ <code><a href="text-level-semantics.html#the-bdi-element">bdi</a></code>;
+ <code><a href="text-level-semantics.html#the-bdo-element">bdo</a></code>;
+ <code><a href="grouping-content.html#the-blockquote-element">blockquote</a></code>;
+ <code><a href="text-level-semantics.html#the-br-element">br</a></code>;
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="scripting-1.html#the-canvas-element">canvas</a></code>;
+ <code><a href="text-level-semantics.html#the-cite-element">cite</a></code>;
+ <code><a href="text-level-semantics.html#the-code-element">code</a></code>;
+ <code><a href="text-level-semantics.html#the-data-element">data</a></code>;
+ <code><a href="forms.html#the-datalist-element">datalist</a></code>;
+ <code><a href="edits.html#the-del-element">del</a></code>;
+ <code><a href="interactive-elements.html#the-details-element">details</a></code>;
+ <code><a href="text-level-semantics.html#the-dfn-element">dfn</a></code>;
+ <code><a href="interactive-elements.html#the-dialog-element">dialog</a></code>;
+ <code><a href="grouping-content.html#the-div-element">div</a></code>;
+ <code><a href="grouping-content.html#the-dl-element">dl</a></code>;
+ <code><a href="text-level-semantics.html#the-em-element">em</a></code>;
+ <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>;
+ <code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="grouping-content.html#the-figure-element">figure</a></code>;
+ <code><a href="sections.html#the-footer-element">footer</a></code>;
+ <code><a href="forms.html#the-form-element">form</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h1</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h2</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h3</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h4</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h5</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h6</a></code>;
+ <code><a href="sections.html#the-header-element">header</a></code>;
+ <!--FORK START/END HGROUP removed-->
+ <code><a href="grouping-content.html#the-hr-element">hr</a></code>;
+ <code><a href="text-level-semantics.html#the-i-element">i</a></code>;
+ <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>;
+ <code><a href="embedded-content-0.html#the-img-element">img</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="edits.html#the-ins-element">ins</a></code>;
+ <code><a href="text-level-semantics.html#the-kbd-element">kbd</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-label-element">label</a></code>;
+ <code><a href="grouping-content.html#the-main-element">main</a></code>;
+ <code><a href="embedded-content-0.html#the-map-element">map</a></code>;
+ <code><a href="text-level-semantics.html#the-mark-element">mark</a></code>;
+ <code><a href="embedded-content-0.html#math">math</a></code>;
+ <code><a href="interactive-elements.html#the-menu-element">menu</a></code>;
+ <code><a href="forms.html#the-meter-element">meter</a></code>;
+ <code><a href="sections.html#the-nav-element">nav</a></code>;
+ <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="grouping-content.html#the-ol-element">ol</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="grouping-content.html#the-p-element">p</a></code>;
+ <code><a href="grouping-content.html#the-pre-element">pre</a></code>;
+ <code><a href="forms.html#the-progress-element">progress</a></code>;
+ <code><a href="text-level-semantics.html#the-q-element">q</a></code>;
+ <code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <code><a href="text-level-semantics.html#the-s-element">s</a></code>;
+ <code><a href="text-level-semantics.html#the-samp-element">samp</a></code>;
+ <code><a href="scripting-1.html#the-script-element">script</a></code>;
+ <code><a href="sections.html#the-section-element">section</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="text-level-semantics.html#the-small-element">small</a></code>;
+ <code><a href="text-level-semantics.html#the-span-element">span</a></code>;
+ <code><a href="text-level-semantics.html#the-strong-element">strong</a></code>;
+ <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sub</a></code>;
+ <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sup</a></code>;
+ <code><a href="embedded-content-0.html#svg-0">svg</a></code>;
+ <code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>;
+ <code><a href="text-level-semantics.html#the-time-element">time</a></code>;
+ <code><a href="text-level-semantics.html#the-u-element">u</a></code>;
+ <code><a href="grouping-content.html#the-ul-element">ul</a></code>;
+ <code><a href="text-level-semantics.html#the-var-element">var</a></code>;
+ <code><a href="embedded-content-0.html#the-video-element">video</a></code>;
+ <code><a href="text-level-semantics.html#the-wbr-element">wbr</a></code>;
+ <a data-anolis-xref="text content" href="dom.html#text-1">Text</a>
+ <td>
+ <code><a href="embedded-content-0.html#the-area-element">area</a></code> (if it is a descendant of a <code><a href="embedded-content-0.html#the-map-element">map</a></code> element);
+ <code><a href="document-metadata.html#the-link-element">link</a></code> (if the <code data-anolis-xref="attr-itemprop">itemprop</code> attribute is present);
+ <code><a href="document-metadata.html#the-meta-element">meta</a></code> (if the <code data-anolis-xref="attr-itemprop">itemprop</code> attribute is present);
+ <code><a href="document-metadata.html#the-style-element">style</a></code> (if the <code data-anolis-xref="attr-style-scoped"><a href="document-metadata.html#scoped">scoped</a></code> attribute is present)
+
+ <tr><td> <a href="dom.html#sectioning-content-0">Sectioning content</a>
+ <td>
+ <code><a href="sections.html#the-article-element">article</a></code>;
+ <code><a href="sections.html#the-aside-element">aside</a></code>;
+ <code><a href="sections.html#the-nav-element">nav</a></code>;
+ <code><a href="sections.html#the-section-element">section</a></code>
+ <td>
+ —
+
+ <tr><td> <a href="dom.html#heading-content-0">Heading content</a>
+ <td>
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h1</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h2</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h3</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h4</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h5</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h6</a></code>;
+ <!--FORK START/END hgroup removed-->
+ <td>
+ —
+
+ <tr><td> <a href="dom.html#phrasing-content-1">Phrasing content</a>
+ <td>
+ <code><a href="text-level-semantics.html#the-a-element">a</a></code>;
+ <code><a href="text-level-semantics.html#the-abbr-element">abbr</a></code>;
+ <code><a href="embedded-content-0.html#the-audio-element">audio</a></code>;
+ <code><a href="text-level-semantics.html#the-b-element">b</a></code>;
+ <code><a href="text-level-semantics.html#the-bdi-element">bdi</a></code>;
+ <code><a href="text-level-semantics.html#the-bdo-element">bdo</a></code>;
+ <code><a href="text-level-semantics.html#the-br-element">br</a></code>;
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="scripting-1.html#the-canvas-element">canvas</a></code>;
+ <code><a href="text-level-semantics.html#the-cite-element">cite</a></code>;
+ <code><a href="text-level-semantics.html#the-code-element">code</a></code>;
+ <code><a href="text-level-semantics.html#the-data-element">data</a></code>;
+ <code><a href="forms.html#the-datalist-element">datalist</a></code>;
+ <code><a href="edits.html#the-del-element">del</a></code>;
+ <code><a href="text-level-semantics.html#the-dfn-element">dfn</a></code>;
+ <code><a href="text-level-semantics.html#the-em-element">em</a></code>;
+ <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>;
+ <code><a href="text-level-semantics.html#the-i-element">i</a></code>;
+ <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>;
+ <code><a href="embedded-content-0.html#the-img-element">img</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="edits.html#the-ins-element">ins</a></code>;
+ <code><a href="text-level-semantics.html#the-kbd-element">kbd</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-label-element">label</a></code>;
+ <code><a href="embedded-content-0.html#the-map-element">map</a></code>;
+ <code><a href="text-level-semantics.html#the-mark-element">mark</a></code>;
+ <code><a href="embedded-content-0.html#math">math</a></code>;
+ <code><a href="forms.html#the-meter-element">meter</a></code>;
+ <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="forms.html#the-progress-element">progress</a></code>;
+ <code><a href="text-level-semantics.html#the-q-element">q</a></code>;
+ <code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <code><a href="text-level-semantics.html#the-s-element">s</a></code>;
+ <code><a href="text-level-semantics.html#the-samp-element">samp</a></code>;
+ <code><a href="scripting-1.html#the-script-element">script</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="text-level-semantics.html#the-small-element">small</a></code>;
+ <code><a href="text-level-semantics.html#the-span-element">span</a></code>;
+ <code><a href="text-level-semantics.html#the-strong-element">strong</a></code>;
+ <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sub</a></code>;
+ <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sup</a></code>;
+ <code><a href="embedded-content-0.html#svg-0">svg</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>;
+ <code><a href="text-level-semantics.html#the-time-element">time</a></code>;
+ <code><a href="text-level-semantics.html#the-u-element">u</a></code>;
+ <code><a href="text-level-semantics.html#the-var-element">var</a></code>;
+ <code><a href="embedded-content-0.html#the-video-element">video</a></code>;
+ <code><a href="text-level-semantics.html#the-wbr-element">wbr</a></code>;
+ <a data-anolis-xref="text content" href="dom.html#text-1">Text</a>
+ <td>
+ <code><a href="embedded-content-0.html#the-area-element">area</a></code> (if it is a descendant of a <code><a href="embedded-content-0.html#the-map-element">map</a></code> element);
+ <code><a href="document-metadata.html#the-link-element">link</a></code> (if the <code data-anolis-xref="attr-itemprop">itemprop</code> attribute is present);
+ <code><a href="document-metadata.html#the-meta-element">meta</a></code> (if the <code data-anolis-xref="attr-itemprop">itemprop</code> attribute is present)
+
+ <tr><td> <a href="dom.html#embedded-content-2">Embedded content</a>
+ <td>
+ <code><a href="embedded-content-0.html#the-audio-element">audio</a></code>
+ <code><a href="scripting-1.html#the-canvas-element">canvas</a></code>
+ <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>
+ <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>
+ <code><a href="embedded-content-0.html#the-img-element">img</a></code>
+ <code><a href="embedded-content-0.html#math">math</a></code>
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>
+ <code><a href="embedded-content-0.html#svg-0">svg</a></code>
+ <code><a href="embedded-content-0.html#the-video-element">video</a></code>
+ <td>
+ —
+
+ <tr><td> <a href="dom.html#interactive-content-0">Interactive content</a>
+ <td>
+ <code><a href="text-level-semantics.html#the-a-element">a</a></code>;
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="interactive-elements.html#the-details-element">details</a></code>;
+ <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>;
+ <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-label-element">label</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>;
+ <td>
+ <code><a href="embedded-content-0.html#the-audio-element">audio</a></code> (if the <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">controls</a></code> attribute is present);
+ <code><a href="embedded-content-0.html#the-img-element">img</a></code> (if the <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">usemap</a></code> attribute is present);
+ <code><a href="forms.html#the-input-element">input</a></code> (if the <code data-anolis-xref="attr-input-type"><a href="forms.html#type-15">type</a></code> attribute is <em>not</em> in the <a data-anolis-xref="attr-input-type-hidden" href="forms.html#hidden-state-(type=hidden)">Hidden</a> state);
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code> (if the <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">usemap</a></code> attribute is present)<!-- see also comment in <object> section -->;
+ <code><a href="embedded-content-0.html#the-video-element">video</a></code> (if the <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">controls</a></code> attribute is present)
+
+ <tr><td> <a data-anolis-xref="sectioning root" href="sections.html#sectioning-roots">Sectioning roots</a>
+ <td>
+ <code><a href="grouping-content.html#the-blockquote-element">blockquote</a></code>;
+ <code><a href="sections.html#the-body-element">body</a></code>;
+ <code><a href="interactive-elements.html#the-details-element">details</a></code>;
+ <code><a href="interactive-elements.html#the-dialog-element">dialog</a></code>;
+ <code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="grouping-content.html#the-figure-element">figure</a></code>;
+ <code><a href="tabular-data.html#the-td-element">td</a></code>
+ <td>
+ —
+
+ <tr><td> <a data-anolis-xref="form-associated element" href="forms.html#form-associated-elements">Form-associated elements</a>
+ <td>
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-label-element">label</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>;
+ <code><a href="embedded-content-0.html#the-img-element">img</a></code>
+ <td>
+ —
+
+ <tr><td> <a data-anolis-xref="category-listed" href="forms.html#listed-elements">Listed elements</a>
+ <td>
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>
+ <td>
+ —
+
+ <tr><td> <a data-anolis-xref="category-submit" href="forms.html#submittable-elements">Submittable elements</a>
+ <td>
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>
+ <td>
+ —
+
+ <tr><td> <a data-anolis-xref="category-reset" href="forms.html#resettable-elements">Resettable elements</a>
+ <td>
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>
+ <td>
+ —
+
+ <tr><td> <a data-anolis-xref="category-label" href="forms.html#labelable-elements">Labelable elements</a>
+ <td>
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-meter-element">meter</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="forms.html#the-progress-element">progress</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>
+ <td>
+ —
+
+ <tr><td> <a data-anolis-xref="category-form-attr" href="forms.html#reassociateable-elements">Reassociateable elements</a>
+ <td>
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="forms.html#the-input-element">input</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-label-element">label</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>
+ <td>
+ —
+
+ <tr><td> <a href="dom.html#palpable-content-0">Palpable content</a>
+ <td>
+ <code><a href="text-level-semantics.html#the-a-element">a</a></code>;
+ <code><a href="text-level-semantics.html#the-abbr-element">abbr</a></code>;
+ <code><a href="sections.html#the-address-element">address</a></code>;
+ <code><a href="sections.html#the-article-element">article</a></code>;
+ <code><a href="sections.html#the-aside-element">aside</a></code>;
+ <code><a href="text-level-semantics.html#the-b-element">b</a></code>;
+ <code><a href="text-level-semantics.html#the-bdi-element">bdi</a></code>;
+ <code><a href="text-level-semantics.html#the-bdo-element">bdo</a></code>;
+ <code><a href="grouping-content.html#the-blockquote-element">blockquote</a></code>;
+ <code><a href="forms.html#the-button-element">button</a></code>;
+ <code><a href="scripting-1.html#the-canvas-element">canvas</a></code>;
+ <code><a href="text-level-semantics.html#the-cite-element">cite</a></code>;
+ <code><a href="text-level-semantics.html#the-code-element">code</a></code>;
+ <code><a href="text-level-semantics.html#the-data-element">data</a></code>;
+ <code><a href="interactive-elements.html#the-details-element">details</a></code>;
+ <code><a href="text-level-semantics.html#the-dfn-element">dfn</a></code>;
+ <code><a href="grouping-content.html#the-div-element">div</a></code>;
+ <code><a href="text-level-semantics.html#the-em-element">em</a></code>;
+ <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>;
+ <code><a href="forms.html#the-fieldset-element">fieldset</a></code>;
+ <code><a href="grouping-content.html#the-figure-element">figure</a></code>;
+ <code><a href="sections.html#the-footer-element">footer</a></code>;
+ <code><a href="forms.html#the-form-element">form</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h1</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h2</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h3</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h4</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h5</a></code>;
+ <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h6</a></code>;
+ <code><a href="sections.html#the-header-element">header</a></code>;
+ <!--FORK START/END hgroup removed-->
+ <code><a href="text-level-semantics.html#the-i-element">i</a></code>;
+ <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>;
+ <code><a href="embedded-content-0.html#the-img-element">img</a></code>;
+ <code><a href="edits.html#the-ins-element">ins</a></code>;
+ <code><a href="text-level-semantics.html#the-kbd-element">kbd</a></code>;
+ <code><a href="forms.html#the-keygen-element">keygen</a></code>;
+ <code><a href="forms.html#the-label-element">label</a></code>;
+ <code><a href="grouping-content.html#the-main-element">main</a></code>;
+ <code><a href="embedded-content-0.html#the-map-element">map</a></code>;
+ <code><a href="text-level-semantics.html#the-mark-element">mark</a></code>;
+ <code><a href="embedded-content-0.html#math">math</a></code>;
+ <code><a href="forms.html#the-meter-element">meter</a></code>;
+ <code><a href="sections.html#the-nav-element">nav</a></code>;
+ <code><a href="embedded-content-0.html#the-object-element">object</a></code>;
+ <code><a href="forms.html#the-output-element">output</a></code>;
+ <code><a href="grouping-content.html#the-p-element">p</a></code>;
+ <code><a href="grouping-content.html#the-pre-element">pre</a></code>;
+ <code><a href="forms.html#the-progress-element">progress</a></code>;
+ <code><a href="text-level-semantics.html#the-q-element">q</a></code>;
+ <code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>;
+ <code><a href="text-level-semantics.html#the-s-element">s</a></code>;
+ <code><a href="text-level-semantics.html#the-samp-element">samp</a></code>;
+ <code><a href="sections.html#the-section-element">section</a></code>;
+ <code><a href="forms.html#the-select-element">select</a></code>;
+ <code><a href="text-level-semantics.html#the-small-element">small</a></code>;
+ <code><a href="text-level-semantics.html#the-span-element">span</a></code>;
+ <code><a href="text-level-semantics.html#the-strong-element">strong</a></code>;
+ <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sub</a></code>;
+ <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sup</a></code>;
+ <code><a href="embedded-content-0.html#svg-0">svg</a></code>;
+ <code><a href="tabular-data.html#the-table-element">table</a></code>;
+ <code><a href="forms.html#the-textarea-element">textarea</a></code>;
+ <code><a href="text-level-semantics.html#the-time-element">time</a></code>;
+ <code><a href="text-level-semantics.html#the-u-element">u</a></code>;
+ <code><a href="text-level-semantics.html#the-var-element">var</a></code>;
+ <code><a href="embedded-content-0.html#the-video-element">video</a></code>
+ <td>
+ <code><a href="embedded-content-0.html#the-audio-element">audio</a></code> (if the <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">controls</a></code> attribute is present);
+ <code><a href="grouping-content.html#the-dl-element">dl</a></code> (if the element's children include at least one name-value group);
+ <code><a href="forms.html#the-input-element">input</a></code> (if the <code data-anolis-xref="attr-input-type"><a href="forms.html#type-15">type</a></code> attribute is <em>not</em> in the <a data-anolis-xref="attr-input-type-hidden" href="forms.html#hidden-state-(type=hidden)">Hidden</a> state);
+ <code><a href="interactive-elements.html#the-menu-element">menu</a></code> (if the <code data-anolis-xref="attr-menu-type"><a href="interactive-elements.html#type-24">type</a></code> attribute is in the <a data-anolis-xref="toolbar state" href="interactive-elements.html#toolbar">toolbar</a> state);
+ <code><a href="grouping-content.html#the-ol-element">ol</a></code> (if the element's children include at least one <code><a href="grouping-content.html#the-li-element">li</a></code> element);
+ <code><a href="grouping-content.html#the-ul-element">ul</a></code> (if the element's children include at least one <code><a href="grouping-content.html#the-li-element">li</a></code> element);
+ <a data-anolis-xref="text content" href="dom.html#text-1">Text</a> that is not <a href="dom.html#inter-element-whitespace">inter-element whitespace</a>
+
+ <tr><td> <a href="dom.html#script-supporting-elements-0">Script-supporting elements</a>
+ <td>
+ <code><a href="scripting-1.html#the-script-element">script</a></code>;
+ <code><a href="scripting-1.html#the-template-element">template</a></code>
+ <td>
+ —
+
+ </table><h3 class="no-num" id="attributes-1">Attributes</h3>
+
+ <p><i>This section is non-normative.</i></p>
+ <table><caption>List of attributes (excluding event handler content attributes)</caption>
+ <thead><tr><th> Attribute
+ <th> Element(s)
+ <th> Description
+ <th> Value
+ <tbody><tr><th> <code data-anolis-xref="">abbr</code>
+ <td> <code data-anolis-xref="attr-th-abbr"><a href="tabular-data.html#abbr">th</a></code>
+ <td> Alternative label to use for the header cell when referencing the cell in other contexts
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">accept</code>
+ <td> <code data-anolis-xref="attr-input-accept"><a href="forms.html#accept-0">input</a></code>
+ <td> Hint for expected file type in <a data-anolis-xref="attr-input-type-file" href="forms.html#file-upload-state-(type=file)">file upload controls</a>
+ <td> <a href="infrastructure.html#set-of-comma-separated-tokens">Set of comma-separated tokens</a>* consisting of <a data-anolis-xref="valid MIME type" href="infrastructure.html#valid-mime-type">valid MIME types with no parameters</a> or <code data-anolis-xref="">audio/*</code>, <code data-anolis-xref="">video/*</code>, or <code data-anolis-xref="">image/*</code>
+ <tr><th> <code data-anolis-xref="">accept-charset</code>
+ <td> <code data-anolis-xref="attr-form-accept-charset"><a href="forms.html#accept-charset">form</a></code>
+ <td> Character encodings to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="infrastructure.html#ordered-set-of-unique-space-separated-tokens">Ordered set of unique space-separated tokens</a>, <a href="infrastructure.html#ascii-case-insensitive">ASCII case-insensitive</a>, consisting of <a data-anolis-xref="encoding label" href="infrastructure.html#encoding-labels">labels</a> of <a data-anolis-xref="ASCII-compatible character encoding" href="infrastructure.html#ascii-compatible-character-encoding">ASCII-compatible character encodings</a>*
+ <tr><th> <code data-anolis-xref="">accesskey</code>
+ <td> <a data-anolis-xref="attr-accesskey" href="editing.html#the-accesskey-attribute">HTML elements</a>
+ <td> Keyboard shortcut to activate or focus element
+ <td> <a href="infrastructure.html#ordered-set-of-unique-space-separated-tokens">Ordered set of unique space-separated tokens</a>, <a href="infrastructure.html#case-sensitive">case-sensitive</a>, consisting of one Unicode code point in length
+ <tr><th> <code data-anolis-xref="">action</code>
+ <td> <code data-anolis-xref="attr-fs-action"><a href="forms.html#action">form</a></code>
+ <td> <a href="infrastructure.html#url">URL</a> to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">allowfullscreen</code>
+ <td> <code data-anolis-xref="attr-iframe-allowfullscreen"><a href="embedded-content-0.html#allowfullscreen">iframe</a></code>
+ <td> Whether to allow the <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>'s contents to use <code data-anolis-xref="dom-element-requestFullscreen"><a href="infrastructure.html#requestfullscreen()">requestFullscreen()</a></code>
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">alt</code>
+ <td> <code data-anolis-xref="attr-area-alt"><a href="embedded-content-0.html#alt-2">area</a></code>;
+ <code data-anolis-xref="attr-img-alt"><a href="embedded-content-0.html#alt-0">img</a></code>;
+ <code data-anolis-xref="attr-input-alt"><a href="forms.html#alt-5">input</a></code>
+ <td> Replacement text for use when images are not available
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">async</code>
+ <td> <code data-anolis-xref="attr-script-async"><a href="scripting-1.html#async">script</a></code>
+ <td> Execute script asynchronously
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">autocomplete</code>
+ <td> <code data-anolis-xref="attr-form-autocomplete"><a href="forms.html#autocomplete">form</a></code>
+ <td> Default setting for autofill feature for controls in the form
+ <td> "<code data-anolis-xref="">on</code>"; "<code data-anolis-xref="">off</code>"
+ <tr><th> <code data-anolis-xref="">autocomplete</code>
+ <td> <code data-anolis-xref="attr-fe-autocomplete"><a href="forms.html#autocomplete-1">input</a></code>;
+ <code data-anolis-xref="attr-fe-autocomplete"><a href="forms.html#autocomplete-1">select</a></code>;
+ <code data-anolis-xref="attr-fe-autocomplete"><a href="forms.html#autocomplete-1">textarea</a></code>
+ <td> Hint for form autofill feature
+ <td> <a data-anolis-xref="autofill field" href="forms.html#autofill-fields">Autofill field</a> name and related tokens*
+ <tr><th> <code data-anolis-xref="">autofocus</code>
+ <td> <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">button</a></code>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">input</a></code>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">keygen</a></code>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">select</a></code>;
+ <code data-anolis-xref="attr-fe-autofocus"><a href="forms.html#autofocus">textarea</a></code>
+ <td> Automatically focus the form control when the page is loaded
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">autoplay</code>
+ <td> <code data-anolis-xref="attr-media-autoplay"><a href="embedded-content-0.html#autoplay">audio</a></code>;
+ <code data-anolis-xref="attr-media-autoplay"><a href="embedded-content-0.html#autoplay">video</a></code>
+ <td> Hint that the <a href="embedded-content-0.html#media-resource">media resource</a> can be started automatically when the page is loaded
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">border</code>
+ <td> <code data-anolis-xref="attr-table-border"><a href="tabular-data.html#border">table</a></code>
+ <td> Explicit indication that the <code><a href="tabular-data.html#the-table-element">table</a></code> element is not being used for layout purposes
+ <td> The empty string, or "<code data-anolis-xref="">1</code>"
+ <tr><th> <code data-anolis-xref="">challenge</code>
+ <td> <code data-anolis-xref="attr-keygen-challenge"><a href="forms.html#challenge">keygen</a></code>
+ <td> String to package with the generated and signed public key
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">charset</code>
+ <td> <code data-anolis-xref="attr-meta-charset"><a href="document-metadata.html#charset-0">meta</a></code>
+ <td> <a href="document-metadata.html#character-encoding-declaration">Character encoding declaration</a>
+ <td> <a href="infrastructure.html#encoding-labels">Encoding label</a>*
+ <tr><th> <code data-anolis-xref="">charset</code>
+ <td> <code data-anolis-xref="attr-script-charset"><a href="scripting-1.html#charset-1">script</a></code>
+ <td> Character encoding of the external script resource
+ <td> <a href="infrastructure.html#encoding-labels">Encoding label</a>*
+ <tr><th> <code data-anolis-xref="">checked</code>
+ <td> <code data-anolis-xref="attr-menuitem-checked"><a href="interactive-elements.html#checked-1">menuitem</a></code>;
+ <code data-anolis-xref="attr-input-checked"><a href="forms.html#checked">input</a></code>
+ <td> Whether the command or control is checked
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">cite</code>
+ <td> <code data-anolis-xref="attr-blockquote-cite"><a href="grouping-content.html#cite">blockquote</a></code>;
+ <code data-anolis-xref="attr-mod-cite"><a href="edits.html#cite-2">del</a></code>;
+ <code data-anolis-xref="attr-mod-cite"><a href="edits.html#cite-2">ins</a></code>;
+ <code data-anolis-xref="attr-q-cite"><a href="text-level-semantics.html#cite-1">q</a></code>
+ <td> Link to the source of the quotation or more information about the edit
+ <td> <a href="infrastructure.html#valid-url-potentially-surrounded-by-spaces">Valid URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">class</code>
+ <td> <a data-anolis-xref="attr-class" href="dom.html#classes">HTML elements</a>
+ <td> Classes to which the element belongs
+ <td> <a href="infrastructure.html#set-of-space-separated-tokens">Set of space-separated tokens</a>
+ <tr><th> <code data-anolis-xref="">cols</code>
+ <td> <code data-anolis-xref="attr-textarea-cols"><a href="forms.html#cols">textarea</a></code>
+ <td> Maximum number of characters per line
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a> greater than zero
+ <tr><th> <code data-anolis-xref="">colspan</code>
+ <td> <code data-anolis-xref="attr-tdth-colspan"><a href="tabular-data.html#colspan">td</a></code>;
+ <code data-anolis-xref="attr-tdth-colspan"><a href="tabular-data.html#colspan">th</a></code>
+ <td> Number of columns that the cell is to span
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a> greater than zero
+ <tr><th> <code data-anolis-xref="">command</code>
+ <td> <code data-anolis-xref="attr-menuitem-command"><a href="interactive-elements.html#command-1">menuitem</a></code>
+ <td> Command definition
+ <td> <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>*
+ <tr><th> <code data-anolis-xref="">content</code>
+ <td> <code data-anolis-xref="attr-meta-content"><a href="document-metadata.html#content">meta</a></code>
+ <td> Value of the element
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">contenteditable</code>
+ <td> <a data-anolis-xref="attr-contenteditable" href="editing.html#contenteditable-0">HTML elements</a>
+ <td> Whether the element is editable
+ <td> "<code data-anolis-xref="">true</code>"; "<code data-anolis-xref="">false</code>"
+ <tr><th> <code data-anolis-xref="">contextmenu</code>
+ <td> <a data-anolis-xref="attr-contextmenu" href="interactive-elements.html#contextmenu">HTML elements</a>
+ <td> The element's context menu
+ <td> <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>*
+ <tr><th> <code data-anolis-xref="">controls</code>
+ <td> <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">audio</a></code>;
+ <code data-anolis-xref="attr-media-controls"><a href="embedded-content-0.html#controls">video</a></code>
+ <td> Show user agent controls
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">coords</code>
+ <td> <code data-anolis-xref="attr-area-coords"><a href="embedded-content-0.html#coords">area</a></code>
+ <td> Coordinates for the shape to be created in an <a href="embedded-content-0.html#image-map">image map</a>
+ <td> <a href="infrastructure.html#valid-list-of-integers">Valid list of integers</a>*
+ <tr><th> <code data-anolis-xref="">crossorigin</code>
+ <td> <code data-anolis-xref="attr-media-crossorigin"><a href="embedded-content-0.html#crossorigin-3">audio</a></code>;
+ <code data-anolis-xref="attr-img-crossorigin"><a href="embedded-content-0.html#crossorigin-1">img</a></code>;
+ <code data-anolis-xref="attr-link-crossorigin"><a href="document-metadata.html#crossorigin">link</a></code>;
+ <code data-anolis-xref="attr-script-crossorigin"><a href="scripting-1.html#crossorigin-5">script</a></code>;
+ <code data-anolis-xref="attr-media-crossorigin"><a href="embedded-content-0.html#crossorigin-3">video</a></code>
+ <td> How the element handles crossorigin requests
+ <td> "<code data-anolis-xref="attr-crossorigin-anonymous-keyword"><a href="infrastructure.html#anonymous">anonymous</a></code>"; "<code data-anolis-xref="attr-crossorigin-use-credentials-keyword"><a href="infrastructure.html#use-credentials">use-credentials</a></code>"
+ <tr><th> <code data-anolis-xref="">data</code>
+ <td> <code data-anolis-xref="attr-object-data"><a href="embedded-content-0.html#data-1">object</a></code>
+ <td> Address of the resource
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">datetime</code>
+ <td> <code data-anolis-xref="attr-mod-datetime"><a href="edits.html#datetime-1">del</a></code>;
+ <code data-anolis-xref="attr-mod-datetime"><a href="edits.html#datetime-1">ins</a></code>
+ <td> Date and (optionally) time of the change
+ <td> <a href="infrastructure.html#valid-date-string-with-optional-time">Valid date string with optional time</a>
+ <tr><th> <code data-anolis-xref="">datetime</code>
+ <td> <code data-anolis-xref="attr-time-datetime"><a href="text-level-semantics.html#datetime">time</a></code>
+ <td> Machine-readable value
+ <td> <a href="infrastructure.html#valid-month-string">Valid month string</a>,
+ <a href="infrastructure.html#valid-date-string">valid date string</a>,
+ <a href="infrastructure.html#valid-yearless-date-string">valid yearless date string</a>,
+ <a href="infrastructure.html#valid-time-string">valid time string</a>,
+ <a href="infrastructure.html#valid-local-date-and-time-string">valid local date and time string</a>,
+ <a href="infrastructure.html#valid-time-zone-offset-string">valid time-zone offset string</a>,
+ <a href="infrastructure.html#valid-global-date-and-time-string">valid global date and time string</a>,
+ <a href="infrastructure.html#valid-week-string">valid week string</a>,
+ <a href="infrastructure.html#valid-non-negative-integer">valid non-negative integer</a>, or
+ <a href="infrastructure.html#valid-duration-string">valid duration string</a>
+ <tr><th> <code data-anolis-xref="">default</code>
+ <td> <code data-anolis-xref="attr-menuitem-default"><a href="interactive-elements.html#default-4">menuitem</a></code>
+ <td> Mark the command as being a default command
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">default</code>
+ <td> <code data-anolis-xref="attr-track-default"><a href="embedded-content-0.html#default">track</a></code>
+ <td> Enable the track if no other <a href="embedded-content-0.html#text-tracks">text track</a> is more suitable
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">defer</code>
+ <td> <code data-anolis-xref="attr-script-defer"><a href="scripting-1.html#defer">script</a></code>
+ <td> Defer script execution
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">dir</code>
+ <td> <a data-anolis-xref="attr-dir" href="dom.html#the-dir-attribute">HTML elements</a>
+ <td> <a data-anolis-xref="the directionality" href="dom.html#the-directionality">The text directionality</a> of the element
+ <td> "<code data-anolis-xref="attr-dir-ltr"><a href="dom.html#ltr">ltr</a></code>"; "<code data-anolis-xref="attr-dir-rtl"><a href="dom.html#rtl">rtl</a></code>"; "<code data-anolis-xref="attr-dir-auto"><a href="dom.html#auto">auto</a></code>"
+ <tr><th> <code data-anolis-xref="">dir</code>
+ <td> <code><a href="text-level-semantics.html#the-bdo-element">bdo</a></code>
+ <td> <a data-anolis-xref="the directionality" href="dom.html#the-directionality">The text directionality</a> of the element
+ <td> "<code data-anolis-xref="attr-dir-ltr"><a href="dom.html#ltr">ltr</a></code>"; "<code data-anolis-xref="attr-dir-rtl"><a href="dom.html#rtl">rtl</a></code>"
+ <tr><th> <code data-anolis-xref="">dirname</code>
+ <td> <code data-anolis-xref="attr-fe-dirname"><a href="forms.html#dirname-1">input</a></code>;
+ <code data-anolis-xref="attr-fe-dirname"><a href="forms.html#dirname-1">textarea</a></code>
+ <td> Name of form field to use for sending the element's <a data-anolis-xref="the directionality" href="dom.html#the-directionality">directionality</a> in <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">disabled</code>
+ <td> <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">button</a></code>;
+ <code data-anolis-xref="attr-menuitem-disabled"><a href="interactive-elements.html#disabled-15">menuitem</a></code>;
+ <code data-anolis-xref="attr-fieldset-disabled"><a href="forms.html#disabled-10">fieldset</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">input</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">keygen</a></code>;
+ <code data-anolis-xref="attr-optgroup-disabled"><a href="forms.html#disabled-5">optgroup</a></code>;
+ <code data-anolis-xref="attr-option-disabled"><a href="forms.html#disabled-7">option</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">select</a></code>;
+ <code data-anolis-xref="attr-fe-disabled"><a href="forms.html#disabled-12">textarea</a></code>
+ <td> Whether the form control is disabled
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">download</code>
+ <td> <code data-anolis-xref="attr-hyperlink-download"><a href="links.html#download-1">a</a></code>;
+ <code data-anolis-xref="attr-hyperlink-download"><a href="links.html#download-1">area</a></code>
+ <td> Whether to download the resource instead of navigating to it, and its file name if so
+ <td> Text
+ <tr><th> <code data-anolis-xref="">draggable</code>
+ <td> <a data-anolis-xref="attr-draggable" href="editing.html#the-draggable-attribute">HTML elements</a>
+ <td> Whether the element is draggable
+ <td> "<code data-anolis-xref="">true</code>"; "<code data-anolis-xref="">false</code>"
+ <tr><th> <code data-anolis-xref="">dropzone</code>
+ <td> <a data-anolis-xref="attr-dropzone" href="editing.html#the-dropzone-attribute">HTML elements</a>
+ <td> Accepted item types for drag-and-drop
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#ascii-case-insensitive">ASCII case-insensitive</a>, consisting of accepted types and drag feedback*
+ <tr><th> <code data-anolis-xref="">enctype</code>
+ <td> <code data-anolis-xref="attr-fs-enctype"><a href="forms.html#enctype">form</a></code>
+ <td> Form data set encoding type to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> "<code data-anolis-xref="attr-fs-enctype-urlencoded"><a href="forms.html#application/x-www-form-urlencoded-0">application/x-www-form-urlencoded</a></code>"; "<code data-anolis-xref="attr-fs-enctype-formdata"><a href="forms.html#multipart/form-data">multipart/form-data</a></code>"; "<code data-anolis-xref="attr-fs-enctype-text"><a href="forms.html#text/plain">text/plain</a></code>"
+ <tr><th> <code data-anolis-xref="">for</code>
+ <td> <code data-anolis-xref="attr-label-for"><a href="forms.html#for">label</a></code>
+ <td> Associate the label with form control
+ <td> <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>*
+ <tr><th> <code data-anolis-xref="">for</code>
+ <td> <code data-anolis-xref="attr-output-for"><a href="forms.html#for-0">output</a></code>
+ <td> Specifies controls from which the output was calculated
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#case-sensitive">case-sensitive</a>, consisting of IDs*
+ <tr><th> <code data-anolis-xref="">form</code>
+ <td> <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">button</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">fieldset</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">input</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">keygen</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">label</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">object</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">output</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">select</a></code>;
+ <code data-anolis-xref="attr-fae-form"><a href="forms.html#form-1">textarea</a></code>
+ <td> Associates the control with a <code><a href="forms.html#the-form-element">form</a></code> element
+ <td> <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>*
+ <tr><th> <code data-anolis-xref="">formaction</code>
+ <td> <code data-anolis-xref="attr-fs-formaction"><a href="forms.html#formaction">button</a></code>;
+ <code data-anolis-xref="attr-fs-formaction"><a href="forms.html#formaction">input</a></code>
+ <td> <a href="infrastructure.html#url">URL</a> to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">formenctype</code>
+ <td> <code data-anolis-xref="attr-fs-formenctype"><a href="forms.html#formenctype">button</a></code>;
+ <code data-anolis-xref="attr-fs-formenctype"><a href="forms.html#formenctype">input</a></code>
+ <td> Form data set encoding type to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> "<code data-anolis-xref="attr-fs-enctype-urlencoded"><a href="forms.html#application/x-www-form-urlencoded-0">application/x-www-form-urlencoded</a></code>"; "<code data-anolis-xref="attr-fs-enctype-formdata"><a href="forms.html#multipart/form-data">multipart/form-data</a></code>"; "<code data-anolis-xref="attr-fs-enctype-text"><a href="forms.html#text/plain">text/plain</a></code>"
+ <tr><th> <code data-anolis-xref="">formmethod</code>
+ <td> <code data-anolis-xref="attr-fs-formmethod"><a href="forms.html#formmethod">button</a></code>;
+ <code data-anolis-xref="attr-fs-formmethod"><a href="forms.html#formmethod">input</a></code>
+ <td> HTTP method to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> "<code data-anolis-xref="">GET</code>"; "<code data-anolis-xref="">POST</code>"
+ <tr><th> <code data-anolis-xref="">formnovalidate</code>
+ <td> <code data-anolis-xref="attr-fs-formnovalidate"><a href="forms.html#formnovalidate">button</a></code>;
+ <code data-anolis-xref="attr-fs-formnovalidate"><a href="forms.html#formnovalidate">input</a></code>
+ <td> Bypass form control validation for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">formtarget</code>
+ <td> <code data-anolis-xref="attr-fs-formtarget"><a href="forms.html#formtarget">button</a></code>;
+ <code data-anolis-xref="attr-fs-formtarget"><a href="forms.html#formtarget">input</a></code>
+ <td> <a href="browsers.html#browsing-context">Browsing context</a> for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="browsers.html#valid-browsing-context-name-or-keyword">Valid browsing context name or keyword</a>
+ <tr><th> <code data-anolis-xref="">headers</code>
+ <td> <code data-anolis-xref="attr-tdth-headers"><a href="tabular-data.html#headers">td</a></code>;
+ <code data-anolis-xref="attr-tdth-headers"><a href="tabular-data.html#headers">th</a></code>
+ <td> The header cells for this cell
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#case-sensitive">case-sensitive</a>, consisting of IDs*
+ <tr><th> <code data-anolis-xref="">height</code>
+ <td> <code data-anolis-xref="attr-canvas-height"><a href="scripting-1.html#height-3">canvas</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">embed</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">iframe</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">img</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">input</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">object</a></code>;
+ <code data-anolis-xref="attr-dim-height"><a href="embedded-content-0.html#height-0">video</a></code>
+ <td> Vertical dimension
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a>
+ <tr><th> <code data-anolis-xref="">hidden</code>
+ <td> <a data-anolis-xref="attr-hidden" href="editing.html#the-hidden-attribute">HTML elements</a>
+ <td> Whether the element is relevant
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">high</code>
+ <td> <code data-anolis-xref="attr-meter-high"><a href="forms.html#high">meter</a></code>
+ <td> Low limit of high range
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a>*
+ <tr><th> <code data-anolis-xref="">href</code>
+ <td> <code data-anolis-xref="attr-hyperlink-href"><a href="links.html#href-3">a</a></code>;
+ <code data-anolis-xref="attr-hyperlink-href"><a href="links.html#href-3">area</a></code>
+ <td> Address of the <a href="links.html#hyperlinks">hyperlink</a>
+ <td> <a href="infrastructure.html#valid-url-potentially-surrounded-by-spaces">Valid URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">href</code>
+ <td> <code data-anolis-xref="attr-link-href"><a href="document-metadata.html#href-1">link</a></code>
+ <td> Address of the <a href="links.html#hyperlinks">hyperlink</a>
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">href</code>
+ <td> <code data-anolis-xref="attr-base-href"><a href="document-metadata.html#href">base</a></code>
+ <td> <a href="infrastructure.html#document-base-url">Document base URL</a>
+ <td> <a href="infrastructure.html#valid-url-potentially-surrounded-by-spaces">Valid URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">hreflang</code>
+ <td> <code data-anolis-xref="attr-hyperlink-hreflang"><a href="links.html#hreflang-3">a</a></code>;
+ <code data-anolis-xref="attr-hyperlink-hreflang"><a href="links.html#hreflang-3">area</a></code>;
+ <code data-anolis-xref="attr-link-hreflang"><a href="document-metadata.html#hreflang">link</a></code>
+ <td> Language of the linked resource
+ <td> Valid BCP 47 language tag
+ <tr><th> <code data-anolis-xref="">http-equiv</code>
+ <td> <code data-anolis-xref="attr-meta-http-equiv"><a href="document-metadata.html#http-equiv">meta</a></code>
+ <td> Pragma directive
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">icon</code>
+ <td> <code data-anolis-xref="attr-menuitem-icon"><a href="interactive-elements.html#icon">menuitem</a></code>
+ <td> Icon for the command
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">id</code>
+ <td> <a data-anolis-xref="attr-id" href="dom.html#the-id-attribute">HTML elements</a>
+ <td> The element's <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">inert</code>
+ <td> <a data-anolis-xref="attr-inert" href="editing.html#the-inert-attribute">HTML elements</a>
+ <td> Whether the element and its descendants are inert
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">inputmode</code>
+ <td> <code data-anolis-xref="attr-fe-inputmode"><a href="forms.html#inputmode-1">input</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode"><a href="forms.html#inputmode-1">textarea</a></code>
+ <td> Hint for selecting an input modality
+ <td> <code data-anolis-xref="attr-fe-inputmode-keyword-verbatim"><a href="forms.html#verbatim">verbatim</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-latin"><a href="forms.html#latin">latin</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-latin-name"><a href="forms.html#latin-name">latin-name</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-latin-prose"><a href="forms.html#latin-prose">latin-prose</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-full-width-latin"><a href="forms.html#full-width-latin">full-width-latin</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-kana"><a href="forms.html#kana">kana</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-katakana"><a href="forms.html#katakana">katakana</a></code>;
+ <!-- <code data-x="attr-fe-inputmode-keyword-half-width-katakana">half-width-katakana</code>; -->
+ <code data-anolis-xref="attr-fe-inputmode-keyword-numeric"><a href="forms.html#numeric">numeric</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-tel"><a href="forms.html#tel-0">tel</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-email"><a href="forms.html#email-0">email</a></code>;
+ <code data-anolis-xref="attr-fe-inputmode-keyword-url"><a href="forms.html#url-2">url</a></code>
+ <tr><th> <code data-anolis-xref="">ismap</code>
+ <td> <code data-anolis-xref="attr-img-ismap"><a href="embedded-content-0.html#ismap">img</a></code>
+ <td> Whether the image is a server-side image map
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">itemid</code>
+ <td> <span data-anolis-xref="attr-itemid">HTML elements</span>
+ <td> <span>Global identifier</span> for a microdata item
+ <td> <a href="infrastructure.html#valid-url-potentially-surrounded-by-spaces">Valid URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">itemprop</code>
+ <td> <span data-anolis-xref="attr-itemprop">HTML elements</span>
+ <td> <span>Property names</span> of a microdata item
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#case-sensitive">case-sensitive</a>, consisting of <a data-anolis-xref="absolute URL" href="infrastructure.html#absolute-url">valid absolute URLs</a>, <span data-anolis-xref="defined property name">defined property names</span>, or text*
+ <tr><th> <code data-anolis-xref="">itemref</code>
+ <td> <span data-anolis-xref="attr-itemref">HTML elements</span>
+ <td> Referenced elements
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#case-sensitive">case-sensitive</a>, consisting of IDs*
+ <tr><th> <code data-anolis-xref="">itemscope</code>
+ <td> <span data-anolis-xref="attr-itemscope">HTML elements</span>
+ <td> Introduces a microdata item
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">itemtype</code>
+ <td> <span data-anolis-xref="attr-itemtype">HTML elements</span>
+ <td> <span>Item types</span> of a microdata item
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#case-sensitive">case-sensitive</a>, consisting of <a data-anolis-xref="absolute URL" href="infrastructure.html#absolute-url">valid absolute URL</a>*
+ <tr><th> <code data-anolis-xref="">keytype</code>
+ <td> <code data-anolis-xref="attr-keygen-keytype"><a href="forms.html#keytype">keygen</a></code>
+ <td> The type of cryptographic key to generate
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">kind</code>
+ <td> <code data-anolis-xref="attr-track-kind"><a href="embedded-content-0.html#kind">track</a></code>
+ <td> The type of text track
+ <td> "<code data-anolis-xref="attr-track-kind-subtitles"><a href="embedded-content-0.html#subtitles-0">subtitles</a></code>";
+ "<code data-anolis-xref="attr-track-kind-captions"><a href="embedded-content-0.html#captions-0">captions</a></code>";
+ "<code data-anolis-xref="attr-track-kind-descriptions"><a href="embedded-content-0.html#descriptions-0">descriptions</a></code>";
+ "<code data-anolis-xref="attr-track-kind-chapters"><a href="embedded-content-0.html#chapters-0">chapters</a></code>";
+ "<code data-anolis-xref="attr-track-kind-metadata"><a href="embedded-content-0.html#metadata-0">metadata</a></code>"
+ <tr><th> <code data-anolis-xref="">label</code>
+ <td> <code data-anolis-xref="attr-menuitem-label"><a href="interactive-elements.html#label-9">menuitem</a></code>;
+ <code data-anolis-xref="attr-menu-label"><a href="interactive-elements.html#label-7">menu</a></code>;
+ <code data-anolis-xref="attr-optgroup-label"><a href="forms.html#label-2">optgroup</a></code>;
+ <code data-anolis-xref="attr-option-label"><a href="forms.html#label-4">option</a></code>;
+ <code data-anolis-xref="attr-track-label"><a href="embedded-content-0.html#label">track</a></code>
+ <td> User-visible label
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">lang</code>
+ <td> <a data-anolis-xref="attr-lang" href="dom.html#lang">HTML elements</a>
+ <td> <a href="dom.html#language">Language</a> of the element
+ <td> Valid BCP 47 language tag or the empty string
+ <tr><th> <code data-anolis-xref="">list</code>
+ <td> <code data-anolis-xref="attr-input-list"><a href="forms.html#list">input</a></code>
+ <td> List of autocomplete options
+ <td> <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>*
+ <tr><th> <code data-anolis-xref="">loop</code>
+ <td> <code data-anolis-xref="attr-media-loop"><a href="embedded-content-0.html#loop">audio</a></code>;
+ <code data-anolis-xref="attr-media-loop"><a href="embedded-content-0.html#loop">video</a></code>
+ <td> Whether to loop the <a href="embedded-content-0.html#media-resource">media resource</a>
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">low</code>
+ <td> <code data-anolis-xref="attr-meter-low"><a href="forms.html#low">meter</a></code>
+ <td> High limit of low range
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a>*
+ <tr><th> <code data-anolis-xref="">manifest</code>
+ <td> <code data-anolis-xref="attr-html-manifest"><a href="semantics.html#manifest">html</a></code>
+ <td> <a data-anolis-xref="concept-appcache-manifest" href="browsers.html#the-manifest">Application cache manifest</a>
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">max</code>
+ <td> <code data-anolis-xref="attr-input-max"><a href="forms.html#max-0">input</a></code>
+ <td> Maximum value
+ <td> Varies*
+ <tr><th> <code data-anolis-xref="">max</code>
+ <td> <code data-anolis-xref="attr-meter-max"><a href="forms.html#max-3">meter</a></code>;
+ <code data-anolis-xref="attr-progress-max"><a href="forms.html#max-1">progress</a></code>
+ <td> Upper bound of range
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a>*
+ <tr><th> <code data-anolis-xref="">maxlength</code>
+ <td> <code data-anolis-xref="attr-input-maxlength"><a href="forms.html#maxlength-0">input</a></code>;
+ <code data-anolis-xref="attr-textarea-maxlength"><a href="forms.html#maxlength-1">textarea</a></code>
+ <td> Maximum length of value
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a>
+ <tr><th> <code data-anolis-xref="">media</code>
+ <td> <code data-anolis-xref="attr-link-media"><a href="document-metadata.html#media">link</a></code>;
+ <code data-anolis-xref="attr-source-media"><a href="embedded-content-0.html#media-3">source</a></code>;
+ <code data-anolis-xref="attr-style-media"><a href="document-metadata.html#media-1">style</a></code>
+ <td> Applicable media
+ <td> <a href="infrastructure.html#valid-media-query">Valid media query</a>
+ <tr><th> <code data-anolis-xref="">mediagroup</code>
+ <td> <code data-anolis-xref="attr-media-mediagroup"><a href="embedded-content-0.html#mediagroup">audio</a></code>;
+ <code data-anolis-xref="attr-media-mediagroup"><a href="embedded-content-0.html#mediagroup">video</a></code>
+ <td> Groups <a data-anolis-xref="media element" href="embedded-content-0.html#media-elements-0">media elements</a> together with an implicit <code><a href="embedded-content-0.html#mediacontroller">MediaController</a></code>
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">menu</code>
+ <td> <code data-anolis-xref="attr-button-menu"><a href="forms.html#menu-1">button</a></code>
+ <td> Specifies the element's <a href="forms.html#designated-pop-up-menu">designated pop-up menu</a>
+ <td> <a data-anolis-xref="concept-id" href="infrastructure.html#unique-identifier-(id)">ID</a>*
+ <tr><th> <code data-anolis-xref="">method</code>
+ <td> <code data-anolis-xref="attr-fs-method"><a href="forms.html#method">form</a></code>
+ <td> HTTP method to use for <a href="forms.html#form-submission-0">form submission</a>
+ <td> "<code data-anolis-xref="attr-fs-method-GET-keyword"><a href="forms.html#get">GET</a></code>";
+ "<code data-anolis-xref="attr-fs-method-POST-keyword"><a href="forms.html#post">POST</a></code>";
+<!--FORM-DIALOG-->
+ <tr><th> <code data-anolis-xref="">min</code>
+ <td> <code data-anolis-xref="attr-input-min"><a href="forms.html#min-0">input</a></code>
+ <td> Minimum value
+ <td> Varies*
+ <tr><th> <code data-anolis-xref="">min</code>
+ <td> <code data-anolis-xref="attr-meter-min"><a href="forms.html#min-1">meter</a></code>
+ <td> Lower bound of range
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a>*
+ <tr><th> <code data-anolis-xref="">minlength</code>
+ <td> <code data-anolis-xref="attr-input-minlength"><a href="forms.html#minlength-0">input</a></code>;
+ <code data-anolis-xref="attr-textarea-minlength"><a href="forms.html#minlength-1">textarea</a></code>
+ <td> Minimum length of value
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a>
+ <tr><th> <code data-anolis-xref="">multiple</code>
+ <td> <code data-anolis-xref="attr-input-multiple"><a href="forms.html#multiple-0">input</a></code>;
+ <code data-anolis-xref="attr-select-multiple"><a href="forms.html#multiple-1">select</a></code>
+ <td> Whether to allow multiple values
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">muted</code>
+ <td> <code data-anolis-xref="attr-media-muted"><a href="embedded-content-0.html#muted-1">audio</a></code>;
+ <code data-anolis-xref="attr-media-muted"><a href="embedded-content-0.html#muted-1">video</a></code>
+ <td> Whether to mute the <a href="embedded-content-0.html#media-resource">media resource</a> by default
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">name</code>
+ <td> <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">button</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">fieldset</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">input</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">keygen</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">output</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">select</a></code>;
+ <code data-anolis-xref="attr-fe-name"><a href="forms.html#name-11">textarea</a></code>
+ <td> Name of form control to use for <a href="forms.html#form-submission-0">form submission</a> and in the <code data-anolis-xref="dom-form-elements"><a href="forms.html#elements-2">form.elements</a></code> API
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">name</code>
+ <td> <code data-anolis-xref="attr-form-name"><a href="forms.html#name-9">form</a></code>
+ <td> Name of form to use in the <code data-anolis-xref="dom-document-forms"><a href="dom.html#forms-0">document.forms</a></code> API
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">name</code>
+ <td> <code data-anolis-xref="attr-iframe-name"><a href="embedded-content-0.html#name-1">iframe</a></code>;
+ <code data-anolis-xref="attr-object-name"><a href="embedded-content-0.html#name-3">object</a></code>
+ <td> Name of <a href="browsers.html#nested-browsing-contexts-0">nested browsing context</a>
+ <td> <a href="browsers.html#valid-browsing-context-name-or-keyword">Valid browsing context name or keyword</a>
+ <tr><th> <code data-anolis-xref="">name</code>
+ <td> <code data-anolis-xref="attr-map-name"><a href="embedded-content-0.html#name-7">map</a></code>
+ <td> Name of <a href="embedded-content-0.html#image-map">image map</a> to reference from the <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">usemap</a></code> attribute
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">name</code>
+ <td> <code data-anolis-xref="attr-meta-name"><a href="document-metadata.html#name">meta</a></code>
+ <td> Metadata name
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">name</code>
+ <td> <code data-anolis-xref="attr-param-name"><a href="embedded-content-0.html#name-5">param</a></code>
+ <td> Name of parameter
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">novalidate</code>
+ <td> <code data-anolis-xref="attr-fs-novalidate"><a href="forms.html#novalidate">form</a></code>
+ <td> Bypass form control validation for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">open</code>
+ <td> <code data-anolis-xref="attr-details-open"><a href="interactive-elements.html#open">details</a></code>
+ <td> Whether the details are visible
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">open</code>
+ <td> <code data-anolis-xref="attr-dialog-open"><a href="interactive-elements.html#open-1">dialog</a></code>
+ <td> Whether the dialog box is showing
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">optimum</code>
+ <td> <code data-anolis-xref="attr-meter-optimum"><a href="forms.html#optimum">meter</a></code>
+ <td> Optimum value in gauge
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a>*
+ <tr><th> <code data-anolis-xref="">pattern</code>
+ <td> <code data-anolis-xref="attr-input-pattern"><a href="forms.html#pattern-0">input</a></code>
+ <td> Pattern to be matched by the form control's value
+ <td> Regular expression matching the JavaScript <i data-anolis-xref="">Pattern</i> production
+<!--PING-->
+ <tr><th> <code data-anolis-xref="">placeholder</code>
+ <td> <code data-anolis-xref="attr-input-placeholder"><a href="forms.html#placeholder-0">input</a></code>;
+ <code data-anolis-xref="attr-textarea-placeholder"><a href="forms.html#placeholder-1">textarea</a></code>
+ <td> User-visible label to be placed within the form control
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">poster</code>
+ <td> <code data-anolis-xref="attr-video-poster"><a href="embedded-content-0.html#poster">video</a></code>
+ <td> Poster frame to show prior to video playback
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">preload</code>
+ <td> <code data-anolis-xref="attr-media-preload"><a href="embedded-content-0.html#preload">audio</a></code>;
+ <code data-anolis-xref="attr-media-preload"><a href="embedded-content-0.html#preload">video</a></code>
+ <td> Hints how much buffering the <a href="embedded-content-0.html#media-resource">media resource</a> will likely need
+ <td> "<code data-anolis-xref="attr-media-preload-none"><a href="embedded-content-0.html#none-0">none</a></code>";
+ "<code data-anolis-xref="attr-media-preload-metadata"><a href="embedded-content-0.html#metadata-1">metadata</a></code>";
+ "<code data-anolis-xref="attr-media-preload-auto"><a href="embedded-content-0.html#auto-1">auto</a></code>"
+ <tr><th> <code data-anolis-xref="">radiogroup</code>
+ <td> <code data-anolis-xref="attr-menuitem-radiogroup"><a href="interactive-elements.html#radiogroup">menuitem</a></code>
+ <td> Name of group of commands to treat as a radio button group
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">readonly</code>
+ <td> <code data-anolis-xref="attr-input-readonly"><a href="forms.html#readonly-0">input</a></code>;
+ <code data-anolis-xref="attr-textarea-readonly"><a href="forms.html#readonly-1">textarea</a></code>
+ <td> Whether to allow the value to be edited by the user
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">rel</code>
+ <td> <code data-anolis-xref="attr-hyperlink-rel"><a href="links.html#rel-3">a</a></code>;
+ <code data-anolis-xref="attr-hyperlink-rel"><a href="links.html#rel-3">area</a></code>;
+ <code data-anolis-xref="attr-link-rel"><a href="document-metadata.html#rel">link</a></code>
+ <td> Relationship between the document containing the hyperlink and the destination resource
+ <td> <a href="infrastructure.html#set-of-space-separated-tokens">Set of space-separated tokens</a>*
+ <tr><th> <code data-anolis-xref="">required</code>
+ <td> <code data-anolis-xref="attr-input-required"><a href="forms.html#required-0">input</a></code>;
+ <code data-anolis-xref="attr-select-required"><a href="forms.html#required-2">select</a></code>;
+ <code data-anolis-xref="attr-textarea-required"><a href="forms.html#required-4">textarea</a></code>
+ <td> Whether the control is required for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">reversed</code>
+ <td> <code data-anolis-xref="attr-ol-reversed"><a href="grouping-content.html#reversed">ol</a></code>
+ <td> Number the list backwards
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">rows</code>
+ <td> <code data-anolis-xref="attr-textarea-rows"><a href="forms.html#rows-1">textarea</a></code>
+ <td> Number of lines to show
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a> greater than zero
+ <tr><th> <code data-anolis-xref="">rowspan</code>
+ <td> <code data-anolis-xref="attr-tdth-rowspan"><a href="tabular-data.html#rowspan">td</a></code>;
+ <code data-anolis-xref="attr-tdth-rowspan"><a href="tabular-data.html#rowspan">th</a></code>
+ <td> Number of rows that the cell is to span
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a>
+ <tr><th> <code data-anolis-xref="">sandbox</code>
+ <td> <code data-anolis-xref="attr-iframe-sandbox"><a href="embedded-content-0.html#sandbox">iframe</a></code>
+ <td> Security rules for nested content
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#ascii-case-insensitive">ASCII case-insensitive</a>, consisting of
+ "<code data-anolis-xref="attr-iframe-sandbox-allow-forms"><a href="browsers.html#allow-forms">allow-forms</a></code>",
+ "<code data-anolis-xref="attr-iframe-sandbox-allow-pointer-lock"><a href="browsers.html#allow-pointer-lock">allow-pointer-lock</a></code>",
+ "<code data-anolis-xref="attr-iframe-sandbox-allow-popups"><a href="browsers.html#allow-popups">allow-popups</a></code>",
+ "<code data-anolis-xref="attr-iframe-sandbox-allow-same-origin"><a href="browsers.html#allow-same-origin">allow-same-origin</a></code>",
+ "<code data-anolis-xref="attr-iframe-sandbox-allow-scripts"><a href="browsers.html#allow-scripts">allow-scripts</a></code> and
+ "<code data-anolis-xref="attr-iframe-sandbox-allow-top-navigation"><a href="browsers.html#allow-top-navigation">allow-top-navigation</a></code>"
+ <tr><th> <code data-anolis-xref="">spellcheck</code>
+ <td> <a data-anolis-xref="attr-spellcheck" href="editing.html#spellcheck">HTML elements</a>
+ <td> Whether the element is to have its spelling and grammar checked
+ <td> "<code data-anolis-xref="">true</code>"; "<code data-anolis-xref="">false</code>"
+ <tr><th> <code data-anolis-xref="">scope</code>
+ <td> <code data-anolis-xref="attr-th-scope"><a href="tabular-data.html#scope-0">th</a></code>
+ <td> Specifies which cells the header cell applies to
+ <td> "<code data-anolis-xref="attr-th-scope-row"><a href="tabular-data.html#row">row</a></code>";
+ "<code data-anolis-xref="attr-th-scope-col"><a href="tabular-data.html#col">col</a></code>";
+ "<code data-anolis-xref="attr-th-scope-rowgroup"><a href="tabular-data.html#rowgroup">rowgroup</a></code>";
+ "<code data-anolis-xref="attr-th-scope-colgroup"><a href="tabular-data.html#colgroup">colgroup</a></code>"
+ <tr><th> <code data-anolis-xref="">scoped</code>
+ <td> <code data-anolis-xref="attr-style-scoped"><a href="document-metadata.html#scoped">style</a></code>
+ <td> Whether the styles apply to the entire document or just the parent subtree
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">seamless</code>
+ <td> <code data-anolis-xref="attr-iframe-seamless"><a href="embedded-content-0.html#seamless">iframe</a></code>
+ <td> Whether to apply the document's styles to the nested content
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">selected</code>
+ <td> <code data-anolis-xref="attr-option-selected"><a href="forms.html#selected">option</a></code>
+ <td> Whether the option is selected by default
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">shape</code>
+ <td> <code data-anolis-xref="attr-area-shape"><a href="embedded-content-0.html#shape">area</a></code>
+ <td> The kind of shape to be created in an <a href="embedded-content-0.html#image-map">image map</a>
+ <td> "<code data-anolis-xref="attr-area-shape-keyword-circle"><a href="embedded-content-0.html#circle">circle</a></code>";
+ "<code data-anolis-xref="attr-area-shape-keyword-default"><a href="embedded-content-0.html#default-1">default</a></code>";
+ "<code data-anolis-xref="attr-area-shape-keyword-poly"><a href="embedded-content-0.html#poly">poly</a></code>";
+ "<code data-anolis-xref="attr-area-shape-keyword-rect"><a href="embedded-content-0.html#rect">rect</a></code>"
+ <tr><th> <code data-anolis-xref="">size</code>
+ <td> <code data-anolis-xref="attr-input-size"><a href="forms.html#size-1">input</a></code>;
+ <code data-anolis-xref="attr-select-size"><a href="forms.html#size-2">select</a></code>
+ <td> Size of the control
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a> greater than zero
+ <tr><th> <code data-anolis-xref="">sizes</code>
+ <td> <code data-anolis-xref="attr-link-sizes"><a href="links.html#sizes-0">link</a></code>
+ <td> Sizes of the icons (for <code data-anolis-xref="attr-link-rel"><a href="document-metadata.html#rel">rel</a></code>="<code data-anolis-xref="rel-icon"><a href="links.html#rel-icon">icon</a></code>")
+ <td> <a href="infrastructure.html#unordered-set-of-unique-space-separated-tokens">Unordered set of unique space-separated tokens</a>, <a href="infrastructure.html#ascii-case-insensitive">ASCII case-insensitive</a>, consisting of sizes*
+ <tr><th> <code data-anolis-xref="">sortable</code>
+ <td> <code data-anolis-xref="attr-table-sortable"><a href="tabular-data.html#sortable-0">table</a></code>
+ <td> Enables a sorting interface for the table
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">sorted</code>
+ <td> <code data-anolis-xref="attr-th-sorted"><a href="tabular-data.html#sorted-0">th</a></code>
+ <td> <a href="tabular-data.html#column-sort-direction">Column sort direction</a> and <a data-anolis-xref="column key ordinality" href="tabular-data.html#column-key-ordinality">ordinality</a>
+ <td> <a href="infrastructure.html#set-of-space-separated-tokens">Set of space-separated tokens</a>, <a href="infrastructure.html#ascii-case-insensitive">ASCII case-insensitive</a>, consisting of neither, one, or both of "<code data-anolis-xref="attr-th-sorted-reversed"><a href="tabular-data.html#reversed-1">reversed</a></code>" and a <a href="infrastructure.html#valid-non-negative-integer">valid non-negative integer</a> greater than zero
+ <tr><th> <code data-anolis-xref="">span</code>
+ <td> <code data-anolis-xref="attr-col-span"><a href="tabular-data.html#span-1">col</a></code>;
+ <code data-anolis-xref="attr-colgroup-span"><a href="tabular-data.html#span">colgroup</a></code>
+ <td> Number of columns spanned by the element
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a> greater than zero
+ <tr><th> <code data-anolis-xref="">src</code>
+ <td> <code data-anolis-xref="attr-media-src"><a href="embedded-content-0.html#src-9">audio</a></code>;
+ <code data-anolis-xref="attr-embed-src"><a href="embedded-content-0.html#src-3">embed</a></code>;
+ <code data-anolis-xref="attr-iframe-src"><a href="embedded-content-0.html#src-1">iframe</a></code>;
+ <code data-anolis-xref="attr-img-src"><a href="embedded-content-0.html#src">img</a></code>;
+ <code data-anolis-xref="attr-input-src"><a href="forms.html#src-12">input</a></code>;
+ <code data-anolis-xref="attr-script-src"><a href="scripting-1.html#src-13">script</a></code>;
+ <code data-anolis-xref="attr-source-src"><a href="embedded-content-0.html#src-5">source</a></code>;
+ <code data-anolis-xref="attr-track-src"><a href="embedded-content-0.html#src-7">track</a></code>;
+ <code data-anolis-xref="attr-media-src"><a href="embedded-content-0.html#src-9">video</a></code>
+ <td> Address of the resource
+ <td> <a href="infrastructure.html#valid-non-empty-url-potentially-surrounded-by-spaces">Valid non-empty URL potentially surrounded by spaces</a>
+ <tr><th> <code data-anolis-xref="">srcdoc</code>
+ <td> <code data-anolis-xref="attr-iframe-srcdoc"><a href="embedded-content-0.html#srcdoc">iframe</a></code>
+ <td> A document to render in the <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>
+ <td> The source of <a href="embedded-content-0.html#an-iframe-srcdoc-document">an <code>iframe</code> <code data-anolis-xref="attr-iframe-srcdoc">srcdoc</code> document</a>*
+ <tr><th> <code data-anolis-xref="">srclang</code>
+ <td> <code data-anolis-xref="attr-track-srclang"><a href="embedded-content-0.html#srclang">track</a></code>
+ <td> Language of the text track
+ <td> Valid BCP 47 language tag
+ <tr><th> <code data-anolis-xref="">start</code>
+ <td> <code data-anolis-xref="attr-ol-start"><a href="grouping-content.html#start-0">ol</a></code>
+ <td> <a href="grouping-content.html#ordinal-value">Ordinal value</a> of the first item
+ <td> <a href="infrastructure.html#valid-integer">Valid integer</a>
+ <tr><th> <code data-anolis-xref="">step</code>
+ <td> <code data-anolis-xref="attr-input-step"><a href="forms.html#step-0">input</a></code>
+ <td> Granularity to be matched by the form control's value
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a> greater than zero, or "<code data-anolis-xref="">any</code>"
+ <tr><th> <code data-anolis-xref="">style</code>
+ <td> <a data-anolis-xref="attr-style" href="dom.html#the-style-attribute">HTML elements</a>
+ <td> Presentational and formatting instructions
+ <td> CSS declarations*
+ <tr><th> <code data-anolis-xref="">tabindex</code>
+ <td> <a data-anolis-xref="attr-tabindex" href="editing.html#tabindex">HTML elements</a>
+ <td> Whether the element is focusable, and the relative order of the element for the purposes of sequential focus navigation
+ <td> <a href="infrastructure.html#valid-integer">Valid integer</a>
+ <tr><th> <code data-anolis-xref="">target</code>
+ <td> <code data-anolis-xref="attr-hyperlink-target"><a href="links.html#target-4">a</a></code>;
+ <code data-anolis-xref="attr-hyperlink-target"><a href="links.html#target-4">area</a></code>
+ <td> <a href="browsers.html#browsing-context">Browsing context</a> for <a href="links.html#hyperlinks">hyperlink</a> <a data-anolis-xref="navigate" href="browsers.html#navigated">navigation</a>
+ <td> <a href="browsers.html#valid-browsing-context-name-or-keyword">Valid browsing context name or keyword</a>
+ <tr><th> <code data-anolis-xref="">target</code>
+ <td> <code data-anolis-xref="attr-base-target"><a href="document-metadata.html#target-0">base</a></code>
+ <td> Default <a href="browsers.html#browsing-context">browsing context</a> for <a href="links.html#hyperlinks">hyperlink</a> <a data-anolis-xref="navigate" href="browsers.html#navigated">navigation</a> and <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="browsers.html#valid-browsing-context-name-or-keyword">Valid browsing context name or keyword</a>
+ <tr><th> <code data-anolis-xref="">target</code>
+ <td> <code data-anolis-xref="attr-fs-target"><a href="forms.html#target-5">form</a></code>
+ <td> <a href="browsers.html#browsing-context">Browsing context</a> for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="browsers.html#valid-browsing-context-name-or-keyword">Valid browsing context name or keyword</a>
+ <tr><th> <code data-anolis-xref="">title</code>
+ <td> <a data-anolis-xref="attr-title" href="dom.html#title">HTML elements</a>
+ <td> Advisory information for the element
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">title</code>
+ <td> <code data-anolis-xref="attr-abbr-title"><a href="text-level-semantics.html#title-4">abbr</a></code>;
+ <code data-anolis-xref="attr-dfn-title"><a href="text-level-semantics.html#title-3">dfn</a></code>
+ <td> Full term or expansion of abbreviation
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">title</code>
+ <td> <code data-anolis-xref="attr-input-title">input</code>
+ <td> Description of pattern (when used with <code data-anolis-xref="attr-input-pattern"><a href="forms.html#pattern-0">pattern</a></code> attribute)
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">title</code>
+ <td> <code data-anolis-xref="attr-menuitem-title"><a href="interactive-elements.html#title-5">menuitem</a></code>
+ <td> Hint describing the command
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">title</code>
+ <td> <code data-anolis-xref="attr-link-title"><a href="document-metadata.html#title-1">link</a></code>
+ <td> Title of the link
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">title</code>
+ <td> <code data-anolis-xref="attr-link-title"><a href="document-metadata.html#title-1">link</a></code>;
+ <code data-anolis-xref="attr-style-title"><a href="document-metadata.html#title-2">style</a></code>
+ <td> Alternative style sheet set name
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">translate</code>
+ <td> <a data-anolis-xref="attr-translate" href="dom.html#translate">HTML elements</a>
+ <td> Whether the element is to be translated when the page is localized
+ <td> "<code data-anolis-xref="">yes</code>"; "<code data-anolis-xref="">no</code>"
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-hyperlink-type"><a href="links.html#type-14">a</a></code>;
+ <code data-anolis-xref="attr-hyperlink-type"><a href="links.html#type-14">area</a></code>;
+ <code data-anolis-xref="attr-link-type"><a href="document-metadata.html#type-0">link</a></code>
+ <td> Hint for the type of the referenced resource
+ <td> <a href="infrastructure.html#valid-mime-type">Valid MIME type</a>
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-button-type"><a href="forms.html#type-17">button</a></code>
+ <td> Type of button
+ <td> "<code data-anolis-xref="attr-button-type-submit"><a href="forms.html#submit-0">submit</a></code>";
+ "<code data-anolis-xref="attr-button-type-reset"><a href="forms.html#reset-0">reset</a></code>";
+ "<code data-anolis-xref="attr-button-type-button"><a href="forms.html#button-0">button</a></code>";
+ "<code data-anolis-xref="attr-button-type-menu"><a href="forms.html#menu">menu</a></code>"
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-embed-type"><a href="embedded-content-0.html#type-7">embed</a></code>;
+ <code data-anolis-xref="attr-object-type"><a href="embedded-content-0.html#type-9">object</a></code>;
+ <code data-anolis-xref="attr-script-type"><a href="scripting-1.html#type-29">script</a></code>;
+ <code data-anolis-xref="attr-source-type"><a href="embedded-content-0.html#type-11">source</a></code>;
+ <code data-anolis-xref="attr-style-type"><a href="document-metadata.html#type-2">style</a></code>
+ <td> Type of embedded resource
+ <td> <a href="infrastructure.html#valid-mime-type">Valid MIME type</a>
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-input-type"><a href="forms.html#type-15">input</a></code>
+ <td> Type of form control
+ <td> <a data-anolis-xref="attr-input-type" href="forms.html#type-15"><code>input</code> type keyword</a>
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-menu-type"><a href="interactive-elements.html#type-24">menu</a></code>
+ <td> Type of menu
+ <td> "<code data-anolis-xref="popup menu state"><a href="interactive-elements.html#popup-menu">popup</a></code>"; "<code data-anolis-xref="toolbar state"><a href="interactive-elements.html#toolbar">toolbar</a></code>"
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-menuitem-type"><a href="interactive-elements.html#type-26">menuitem</a></code>
+ <td> Type of command
+ <td> "<code data-anolis-xref="attr-menuitem-type-keyword-command"><a href="interactive-elements.html#command">command</a></code>";
+ "<code data-anolis-xref="attr-menuitem-type-keyword-checkbox"><a href="interactive-elements.html#checkbox-0">checkbox</a></code>";
+ "<code data-anolis-xref="attr-menuitem-type-keyword-radio"><a href="interactive-elements.html#radio-0">radio</a></code>"
+ <tr><th> <code data-anolis-xref="">type</code>
+ <td> <code data-anolis-xref="attr-ol-type"><a href="grouping-content.html#type-4">ol</a></code>
+ <td> Kind of list marker
+ <td> "<code data-anolis-xref="attr-ol-type-keyword-decimal"><a href="grouping-content.html#1">1</a></code>";
+ "<code data-anolis-xref="attr-ol-type-keyword-lower-alpha"><a href="grouping-content.html#a">a</a></code>";
+ "<code data-anolis-xref="attr-ol-type-keyword-upper-alpha"><a href="grouping-content.html#a-0">A</a></code>";
+ "<code data-anolis-xref="attr-ol-type-keyword-lower-roman"><a href="grouping-content.html#i">i</a></code>";
+ "<code data-anolis-xref="attr-ol-type-keyword-upper-roman"><a href="grouping-content.html#i-0">I</a></code>"
+ <tr><th> <code data-anolis-xref="">typemustmatch</code>
+ <td> <code data-anolis-xref="attr-object-typemustmatch"><a href="embedded-content-0.html#typemustmatch">object</a></code>
+ <td> Whether the <code data-anolis-xref="attr-object-type"><a href="embedded-content-0.html#type-9">type</a></code> attribute and the <a href="infrastructure.html#content-type-metadata">Content-Type</a> value need to match for the resource to be used
+ <td> <a href="infrastructure.html#boolean-attributes-0">Boolean attribute</a>
+ <tr><th> <code data-anolis-xref="">usemap</code>
+ <td> <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">img</a></code>;
+ <code data-anolis-xref="attr-hyperlink-usemap"><a href="embedded-content-0.html#usemap-1">object</a></code>
+ <td> Name of <a href="embedded-content-0.html#image-map">image map</a> to use
+ <td> <a href="infrastructure.html#valid-hash-name-reference">Valid hash-name reference</a>*
+ <tr><th> <code data-anolis-xref="">value</code>
+ <td> <code data-anolis-xref="attr-button-value"><a href="forms.html#value-9">button</a></code>;
+ <code data-anolis-xref="attr-option-value"><a href="forms.html#value-12">option</a></code>
+ <td> Value to be used for <a href="forms.html#form-submission-0">form submission</a>
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">value</code>
+ <td> <code data-anolis-xref="attr-data-value"><a href="text-level-semantics.html#value-2">data</a></code>
+ <td> Machine-readable value
+ <td> <a href="dom.html#attribute-text">Text</a>*
+ <tr><th> <code data-anolis-xref="">value</code>
+ <td> <code data-anolis-xref="attr-input-value"><a href="forms.html#value-6">input</a></code>
+ <td> Value of the form control
+ <td> Varies*
+ <tr><th> <code data-anolis-xref="">value</code>
+ <td> <code data-anolis-xref="attr-li-value"><a href="grouping-content.html#value-0">li</a></code>
+ <td> <a href="grouping-content.html#ordinal-value">Ordinal value</a> of the list item
+ <td> <a href="infrastructure.html#valid-integer">Valid integer</a>
+ <tr><th> <code data-anolis-xref="">value</code>
+ <td> <code data-anolis-xref="attr-meter-value"><a href="forms.html#value-19">meter</a></code>;
+ <code data-anolis-xref="attr-progress-value"><a href="forms.html#value-17">progress</a></code>
+ <td> Current value of the element
+ <td> <a href="infrastructure.html#valid-floating-point-number">Valid floating-point number</a>
+ <tr><th> <code data-anolis-xref="">value</code>
+ <td> <code data-anolis-xref="attr-param-value"><a href="embedded-content-0.html#value-4">param</a></code>
+ <td> Value of parameter
+ <td> <a href="dom.html#attribute-text">Text</a>
+ <tr><th> <code data-anolis-xref="">width</code>
+ <td> <code data-anolis-xref="attr-canvas-width"><a href="scripting-1.html#width-3">canvas</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">embed</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">iframe</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">img</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">input</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">object</a></code>;
+ <code data-anolis-xref="attr-dim-width"><a href="embedded-content-0.html#width-0">video</a></code>
+ <td> Horizontal dimension
+ <td> <a href="infrastructure.html#valid-non-negative-integer">Valid non-negative integer</a>
+ <tr><th> <code data-anolis-xref="">wrap</code>
+ <td> <code data-anolis-xref="attr-textarea-wrap"><a href="forms.html#wrap">textarea</a></code>
+ <td> How the value of the form control is to be wrapped for <a href="forms.html#form-submission-0">form submission</a>
+ <td> "<code data-anolis-xref="attr-textarea-wrap-soft"><a href="forms.html#soft">soft</a></code>";
+ "<code data-anolis-xref="attr-textarea-wrap-hard"><a href="forms.html#hard">hard</a></code>"
+ </table><p class="tablenote"><small>An asterisk (*) in a cell indicates that the actual rules are more
+ complicated than indicated in the table above.</small></p>
+
+ <hr><table id="ix-event-handlers"><caption>List of event handler content attributes</caption>
+ <thead><tr><th> Attribute
+ <th> Element(s)
+ <th> Description
+ <th> Value
+ <tbody><tr><th id="ix-handler-onabort"> <code data-anolis-xref="">onabort</code>
+ <td> <a data-anolis-xref="handler-onabort" href="webappapis.html#onabort">HTML elements</a>
+ <td> <code data-anolis-xref="event-abort">abort</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onafterprint"> <code data-anolis-xref="">onafterprint</code>
+ <td> <code data-anolis-xref="handler-window-onafterprint"><a href="webappapis.html#onafterprint">body</a></code>
+ <td> <code data-anolis-xref="event-afterprint">afterprint</code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onbeforeprint"> <code data-anolis-xref="">onbeforeprint</code>
+ <td> <code data-anolis-xref="handler-window-onbeforeprint"><a href="webappapis.html#onbeforeprint">body</a></code>
+ <td> <code data-anolis-xref="event-beforeprint">beforeprint</code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onbeforeunload"> <code data-anolis-xref="">onbeforeunload</code>
+ <td> <code data-anolis-xref="handler-window-onbeforeunload"><a href="webappapis.html#onbeforeunload">body</a></code>
+ <td> <code data-anolis-xref="event-beforeunload">beforeunload</code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onblur"> <code data-anolis-xref="">onblur</code>
+ <td> <a data-anolis-xref="handler-onblur" href="webappapis.html#onblur">HTML elements</a>
+ <td> <code data-anolis-xref="event-blur">blur</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oncancel"> <code data-anolis-xref="">oncancel</code>
+ <td> <a data-anolis-xref="handler-oncancel" href="webappapis.html#oncancel">HTML elements</a>
+ <td> <code data-anolis-xref="event-cancel"><a href="interactive-elements.html#cancel">cancel</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oncanplay"> <code data-anolis-xref="">oncanplay</code>
+ <td> <a data-anolis-xref="handler-oncanplay" href="webappapis.html#oncanplay-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-canplay"><a href="embedded-content-0.html#canplay">canplay</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oncanplaythrough"> <code data-anolis-xref="">oncanplaythrough</code>
+ <td> <a data-anolis-xref="handler-oncanplaythrough" href="webappapis.html#oncanplaythrough-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-canplaythrough"><a href="embedded-content-0.html#canplaythrough">canplaythrough</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onchange"> <code data-anolis-xref="">onchange</code>
+ <td> <a data-anolis-xref="handler-onchange" href="webappapis.html#onchange-1">HTML elements</a>
+ <td> <code data-anolis-xref="event-change">change</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onclick"> <code data-anolis-xref="">onclick</code>
+ <td> <a data-anolis-xref="handler-onclick" href="webappapis.html#onclick">HTML elements</a>
+ <td> <code data-anolis-xref="event-click"><a href="infrastructure.html#click">click</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onclose"> <code data-anolis-xref="">onclose</code>
+ <td> <a data-anolis-xref="handler-onclose" href="webappapis.html#onclose">HTML elements</a>
+ <td> <code data-anolis-xref="event-close"><a href="interactive-elements.html#close">close</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oncontextmenu"> <code data-anolis-xref="">oncontextmenu</code>
+ <td> <a data-anolis-xref="handler-oncontextmenu" href="webappapis.html#oncontextmenu">HTML elements</a>
+ <td> <code data-anolis-xref="event-contextmenu">contextmenu</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oncuechange"> <code data-anolis-xref="">oncuechange</code>
+ <td> <a data-anolis-xref="handler-oncuechange" href="webappapis.html#oncuechange-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-cuechange">cuechange</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondblclick"> <code data-anolis-xref="">ondblclick</code>
+ <td> <a data-anolis-xref="handler-ondblclick" href="webappapis.html#ondblclick">HTML elements</a>
+ <td> <code data-anolis-xref="event-dblclick">dblclick</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondrag"> <code data-anolis-xref="">ondrag</code>
+ <td> <a data-anolis-xref="handler-ondrag" href="webappapis.html#ondrag">HTML elements</a>
+ <td> <code data-anolis-xref="event-drag"><a href="editing.html#drag">drag</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondragend"> <code data-anolis-xref="">ondragend</code>
+ <td> <a data-anolis-xref="handler-ondragend" href="webappapis.html#ondragend">HTML elements</a>
+ <td> <code data-anolis-xref="event-dragend"><a href="editing.html#dragend">dragend</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondragenter"> <code data-anolis-xref="">ondragenter</code>
+ <td> <a data-anolis-xref="handler-ondragenter" href="webappapis.html#ondragenter">HTML elements</a>
+ <td> <code data-anolis-xref="event-dragenter"><a href="editing.html#dragenter">dragenter</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondragexit"> <code data-anolis-xref="">ondragexit</code>
+ <td> <a data-anolis-xref="handler-ondragexit" href="webappapis.html#ondragexit">HTML elements</a>
+ <td> <code data-anolis-xref="event-dragexit"><a href="editing.html#dragexit">dragexit</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondragleave"> <code data-anolis-xref="">ondragleave</code>
+ <td> <a data-anolis-xref="handler-ondragleave" href="webappapis.html#ondragleave">HTML elements</a>
+ <td> <code data-anolis-xref="event-dragleave"><a href="editing.html#dragleave">dragleave</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondragover"> <code data-anolis-xref="">ondragover</code>
+ <td> <a data-anolis-xref="handler-ondragover" href="webappapis.html#ondragover">HTML elements</a>
+ <td> <code data-anolis-xref="event-dragover"><a href="editing.html#dragover">dragover</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondragstart"> <code data-anolis-xref="">ondragstart</code>
+ <td> <a data-anolis-xref="handler-ondragstart" href="webappapis.html#ondragstart">HTML elements</a>
+ <td> <code data-anolis-xref="event-dragstart"><a href="editing.html#dragstart">dragstart</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondrop"> <code data-anolis-xref="">ondrop</code>
+ <td> <a data-anolis-xref="handler-ondrop" href="webappapis.html#ondrop">HTML elements</a>
+ <td> <code data-anolis-xref="event-drop"><a href="editing.html#drop">drop</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ondurationchange"> <code data-anolis-xref="">ondurationchange</code>
+ <td> <a data-anolis-xref="handler-ondurationchange" href="webappapis.html#ondurationchange-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-durationchange"><a href="embedded-content-0.html#durationchange">durationchange</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onemptied"> <code data-anolis-xref="">onemptied</code>
+ <td> <a data-anolis-xref="handler-onemptied" href="webappapis.html#onemptied-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-emptied"><a href="embedded-content-0.html#emptied">emptied</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onended"> <code data-anolis-xref="">onended</code>
+ <td> <a data-anolis-xref="handler-onended" href="webappapis.html#onended-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-ended"><a href="embedded-content-0.html#ended-1">ended</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onerror"> <code data-anolis-xref="">onerror</code>
+ <td> <a data-anolis-xref="handler-onerror" href="webappapis.html#onerror-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-error">error</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onfocus"> <code data-anolis-xref="">onfocus</code>
+ <td> <a data-anolis-xref="handler-onfocus" href="webappapis.html#onfocus">HTML elements</a>
+ <td> <code data-anolis-xref="event-focus">focus</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onhashchange"> <code data-anolis-xref="">onhashchange</code>
+ <td> <code data-anolis-xref="handler-window-onhashchange"><a href="webappapis.html#onhashchange">body</a></code>
+ <td> <code data-anolis-xref="event-hashchange"><a href="browsers.html#hashchange">hashchange</a></code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oninput"> <code data-anolis-xref="">oninput</code>
+ <td> <a data-anolis-xref="handler-oninput" href="webappapis.html#oninput">HTML elements</a>
+ <td> <code data-anolis-xref="event-input">input</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-oninvalid"> <code data-anolis-xref="">oninvalid</code>
+ <td> <a data-anolis-xref="handler-oninvalid" href="webappapis.html#oninvalid">HTML elements</a>
+ <td> <code data-anolis-xref="event-invalid">invalid</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onkeydown"> <code data-anolis-xref="">onkeydown</code>
+ <td> <a data-anolis-xref="handler-onkeydown" href="webappapis.html#onkeydown">HTML elements</a>
+ <td> <code data-anolis-xref="event-keydown">keydown</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onkeypress"> <code data-anolis-xref="">onkeypress</code>
+ <td> <a data-anolis-xref="handler-onkeypress" href="webappapis.html#onkeypress">HTML elements</a>
+ <td> <code data-anolis-xref="event-keypress">keypress</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onkeyup"> <code data-anolis-xref="">onkeyup</code>
+ <td> <a data-anolis-xref="handler-onkeyup" href="webappapis.html#onkeyup">HTML elements</a>
+ <td> <code data-anolis-xref="event-keyup">keyup</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onload"> <code data-anolis-xref="">onload</code>
+ <td> <a data-anolis-xref="handler-onload" href="webappapis.html#onload">HTML elements</a>
+ <td> <code data-anolis-xref="event-load">load</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onloadeddata"> <code data-anolis-xref="">onloadeddata</code>
+ <td> <a data-anolis-xref="handler-onloadeddata" href="webappapis.html#onloadeddata-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-loadeddata"><a href="embedded-content-0.html#loadeddata">loadeddata</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onloadedmetadata"> <code data-anolis-xref="">onloadedmetadata</code>
+ <td> <a data-anolis-xref="handler-onloadedmetadata" href="webappapis.html#onloadedmetadata-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-loadedmetadata"><a href="embedded-content-0.html#loadedmetadata">loadedmetadata</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onloadstart"> <code data-anolis-xref="">onloadstart</code>
+ <td> <a data-anolis-xref="handler-onloadstart" href="webappapis.html#onloadstart">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-loadstart"><a href="embedded-content-0.html#loadstart">loadstart</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onmessage"> <code data-anolis-xref="">onmessage</code>
+ <td> <code data-anolis-xref="handler-window-onmessage"><a href="webappapis.html#onmessage">body</a></code>
+ <td> <code data-anolis-xref="event-message">message</code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmousedown"> <code data-anolis-xref="">onmousedown</code>
+ <td> <a data-anolis-xref="handler-onmousedown" href="webappapis.html#onmousedown">HTML elements</a>
+ <td> <code data-anolis-xref="event-mousedown">mousedown</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmouseenter"> <code data-anolis-xref="">onmouseenter</code>
+ <td> <a data-anolis-xref="handler-onmouseenter" href="webappapis.html#onmouseenter">HTML elements</a>
+ <td> <code data-anolis-xref="event-mouseenter">mouseenter</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmouseleave"> <code data-anolis-xref="">onmouseleave</code>
+ <td> <a data-anolis-xref="handler-onmouseleave" href="webappapis.html#onmouseleave">HTML elements</a>
+ <td> <code data-anolis-xref="event-mouseleave">mouseleave</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmousemove"> <code data-anolis-xref="">onmousemove</code>
+ <td> <a data-anolis-xref="handler-onmousemove" href="webappapis.html#onmousemove">HTML elements</a>
+ <td> <code data-anolis-xref="event-mousemove">mousemove</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmouseout"> <code data-anolis-xref="">onmouseout</code>
+ <td> <a data-anolis-xref="handler-onmouseout" href="webappapis.html#onmouseout">HTML elements</a>
+ <td> <code data-anolis-xref="event-mouseout">mouseout</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmouseover"> <code data-anolis-xref="">onmouseover</code>
+ <td> <a data-anolis-xref="handler-onmouseover" href="webappapis.html#onmouseover">HTML elements</a>
+ <td> <code data-anolis-xref="event-mouseover">mouseover</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmouseup"> <code data-anolis-xref="">onmouseup</code>
+ <td> <a data-anolis-xref="handler-onmouseup" href="webappapis.html#onmouseup">HTML elements</a>
+ <td> <code data-anolis-xref="event-mouseup">mouseup</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onmousewheel"> <code data-anolis-xref="">onmousewheel</code>
+ <td> <a data-anolis-xref="handler-onmousewheel" href="webappapis.html#onmousewheel">HTML elements</a>
+ <td> <code data-anolis-xref="event-mousewheel">mousewheel</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onoffline"> <code data-anolis-xref="">onoffline</code>
+ <td> <code data-anolis-xref="handler-window-onoffline"><a href="webappapis.html#onoffline">body</a></code>
+ <td> <code data-anolis-xref="event-offline"><a href="browsers.html#offline-0">offline</a></code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-ononline"> <code data-anolis-xref="">ononline</code>
+ <td> <code data-anolis-xref="handler-window-ononline"><a href="webappapis.html#ononline">body</a></code>
+ <td> <code data-anolis-xref="event-online"><a href="browsers.html#online">online</a></code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onpagehide"> <code data-anolis-xref="">onpagehide</code>
+ <td> <code data-anolis-xref="handler-window-onpagehide"><a href="webappapis.html#onpagehide">body</a></code>
+ <td> <code data-anolis-xref="event-pagehide"><a href="browsers.html#pagehide">pagehide</a></code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onpageshow"> <code data-anolis-xref="">onpageshow</code>
+ <td> <code data-anolis-xref="handler-window-onpageshow"><a href="webappapis.html#onpageshow">body</a></code>
+ <td> <code data-anolis-xref="event-pageshow"><a href="browsers.html#pageshow">pageshow</a></code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onpause"> <code data-anolis-xref="">onpause</code>
+ <td> <a data-anolis-xref="handler-onpause" href="webappapis.html#onpause-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-pause"><a href="embedded-content-0.html#pause">pause</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onplay"> <code data-anolis-xref="">onplay</code>
+ <td> <a data-anolis-xref="handler-onplay" href="webappapis.html#onplay-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-play"><a href="embedded-content-0.html#play">play</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onplaying"> <code data-anolis-xref="">onplaying</code>
+ <td> <a data-anolis-xref="handler-onplaying" href="webappapis.html#onplaying-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-playing"><a href="embedded-content-0.html#playing-0">playing</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onpopstate"> <code data-anolis-xref="">onpopstate</code>
+ <td> <code data-anolis-xref="handler-window-onpopstate"><a href="webappapis.html#onpopstate">body</a></code>
+ <td> <code data-anolis-xref="event-popstate"><a href="browsers.html#popstate">popstate</a></code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onprogress"> <code data-anolis-xref="">onprogress</code>
+ <td> <a data-anolis-xref="handler-onprogress" href="webappapis.html#onprogress-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-progress"><a href="embedded-content-0.html#progress">progress</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onratechange"> <code data-anolis-xref="">onratechange</code>
+ <td> <a data-anolis-xref="handler-onratechange" href="webappapis.html#onratechange-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-ratechange"><a href="embedded-content-0.html#ratechange">ratechange</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onreset"> <code data-anolis-xref="">onreset</code>
+ <td> <a data-anolis-xref="handler-onreset" href="webappapis.html#onreset">HTML elements</a>
+ <td> <code data-anolis-xref="event-reset">reset</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onresize"> <code data-anolis-xref="">onresize</code>
+ <td> <a data-anolis-xref="handler-onresize" href="webappapis.html#onresize">HTML elements</a>
+ <td> <code data-anolis-xref="event-resize">resize</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onscroll"> <code data-anolis-xref="">onscroll</code>
+ <td> <a data-anolis-xref="handler-onscroll" href="webappapis.html#onscroll">HTML elements</a>
+ <td> <code data-anolis-xref="event-scroll">scroll</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onseeked"> <code data-anolis-xref="">onseeked</code>
+ <td> <a data-anolis-xref="handler-onseeked" href="webappapis.html#onseeked">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-seeked"><a href="embedded-content-0.html#seeked">seeked</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onseeking"> <code data-anolis-xref="">onseeking</code>
+ <td> <a data-anolis-xref="handler-onseeking" href="webappapis.html#onseeking">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-seeking"><a href="embedded-content-0.html#seeking-1">seeking</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onselect"> <code data-anolis-xref="">onselect</code>
+ <td> <a data-anolis-xref="handler-onselect" href="webappapis.html#onselect">HTML elements</a>
+ <td> <code data-anolis-xref="event-select">select</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onshow"> <code data-anolis-xref="">onshow</code>
+ <td> <a data-anolis-xref="handler-onshow" href="webappapis.html#onshow">HTML elements</a>
+ <td> <code data-anolis-xref="event-show">show</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onsort"> <code data-anolis-xref="">onsort</code>
+ <td> <a data-anolis-xref="handler-onsort" href="webappapis.html#onsort">HTML elements</a>
+ <td> <code data-anolis-xref="event-sort">sort</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onstalled"> <code data-anolis-xref="">onstalled</code>
+ <td> <a data-anolis-xref="handler-onstalled" href="webappapis.html#onstalled">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-stalled"><a href="embedded-content-0.html#stalled">stalled</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onstorage"> <code data-anolis-xref="">onstorage</code>
+ <td> <code data-anolis-xref="handler-window-onstorage"><a href="webappapis.html#onstorage">body</a></code>
+ <td> <code data-anolis-xref="event-storage">storage</code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onsubmit"> <code data-anolis-xref="">onsubmit</code>
+ <td> <a data-anolis-xref="handler-onsubmit" href="webappapis.html#onsubmit">HTML elements</a>
+ <td> <code data-anolis-xref="event-submit">submit</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onsuspend"> <code data-anolis-xref="">onsuspend</code>
+ <td> <a data-anolis-xref="handler-onsuspend" href="webappapis.html#onsuspend">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-suspend"><a href="embedded-content-0.html#suspend">suspend</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ontimeupdate"> <code data-anolis-xref="">ontimeupdate</code>
+ <td> <a data-anolis-xref="handler-ontimeupdate" href="webappapis.html#ontimeupdate-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-timeupdate"><a href="embedded-content-0.html#timeupdate">timeupdate</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-ontoggle"> <code data-anolis-xref="">ontoggle</code>
+ <td> <a data-anolis-xref="handler-ontoggle" href="webappapis.html#ontoggle">HTML elements</a>
+ <td> <code data-anolis-xref="event-toggle">toggle</code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-window-onunload"> <code data-anolis-xref="">onunload</code>
+ <td> <code data-anolis-xref="handler-window-onunload"><a href="webappapis.html#onunload">body</a></code>
+ <td> <code data-anolis-xref="event-unload">unload</code> event handler for <code><a href="browsers.html#window">Window</a></code> object
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onvolumechange"> <code data-anolis-xref="">onvolumechange</code>
+ <td> <a data-anolis-xref="handler-onvolumechange" href="webappapis.html#onvolumechange-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-volumechange"><a href="embedded-content-0.html#volumechange">volumechange</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ <tr><th id="ix-handler-onwaiting"> <code data-anolis-xref="">onwaiting</code>
+ <td> <a data-anolis-xref="handler-onwaiting" href="webappapis.html#onwaiting-0">HTML elements</a>
+ <td> <code data-anolis-xref="event-media-waiting"><a href="embedded-content-0.html#waiting-0">waiting</a></code> event handler
+ <td> <a data-anolis-xref="event handler content attributes" href="webappapis.html#event-handler-content-attribute">Event handler content attribute</a>
+
+ </table><!-- v2 for completeness: (also search for REFLECTIDL)
+ <h3 class="no-num">Reflecting IDL attributes</h3>
+
+ <!- -END dev-html- -><p><i>This section is non-normative.</i></p><!- -START dev-html- ->
+
+ <table>
+ <caption>List of <dfn>reflecting IDL attributes</dfn></caption>
+ <thead>
+ <tr>
+ <th> Interface
+ <th> Element(s)
+ <th> IDL attribute
+ <th> Reflects...
+ <tbody>
+ ...
+ <tr>
+ <td> <code>HTMLElement</code>
+ <td> <span>HTML elements</span>
+ <td> <code data-x="dom-contextMenu">contextMenu</code>
+ <td> <code data-x="attr-contextmenu">contextmenu</code>
+ <tr>
+ <td> <code>HTMLOptionElement</code>
+ <td> <code>option</code>
+ <td> <code data-x="dom-option-text">text</code>
+ <td> <code>textContent</code>
+ </table>
+ ( include option.text; textarea.defaultValue, and other attributes that "reflect" the element's textContent )
+--><h3 class="no-num" id="element-interfaces">Element Interfaces</h3>
+
+ <p><i>This section is non-normative.</i></p>
+ <table><caption>List of interfaces for elements</caption>
+ <thead><tr><th> Element(s)
+ <th> Interface(s)
+ <tbody><tr><td> <code><a href="text-level-semantics.html#the-a-element">a</a></code>
+ <td> <code><a href="text-level-semantics.html#htmlanchorelement">HTMLAnchorElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-abbr-element">abbr</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-address-element">address</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-area-element">area</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlareaelement">HTMLAreaElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-article-element">article</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-aside-element">aside</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-audio-element">audio</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlaudioelement">HTMLAudioElement</a></code> : <code><a href="embedded-content-0.html#htmlmediaelement">HTMLMediaElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-b-element">b</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="document-metadata.html#the-base-element">base</a></code>
+ <td> <code><a href="document-metadata.html#htmlbaseelement">HTMLBaseElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-bdi-element">bdi</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-bdo-element">bdo</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-blockquote-element">blockquote</a></code>
+ <td> <code><a href="grouping-content.html#htmlquoteelement">HTMLQuoteElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-body-element">body</a></code>
+ <td> <code><a href="sections.html#htmlbodyelement">HTMLBodyElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-br-element">br</a></code>
+ <td> <code><a href="text-level-semantics.html#htmlbrelement">HTMLBRElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-button-element">button</a></code>
+ <td> <code><a href="forms.html#htmlbuttonelement">HTMLButtonElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="scripting-1.html#the-canvas-element">canvas</a></code>
+ <td> <code><a href="scripting-1.html#htmlcanvaselement">HTMLCanvasElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-caption-element">caption</a></code>
+ <td> <code><a href="tabular-data.html#htmltablecaptionelement">HTMLTableCaptionElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-cite-element">cite</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-code-element">code</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-col-element">col</a></code>
+ <td> <code><a href="tabular-data.html#htmltablecolelement">HTMLTableColElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-colgroup-element">colgroup</a></code>
+ <td> <code><a href="tabular-data.html#htmltablecolelement">HTMLTableColElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="interactive-elements.html#the-menuitem-element">menuitem</a></code>
+ <td> <code><a href="interactive-elements.html#htmlmenuitemelement">HTMLMenuItemElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-data-element">data</a></code>
+ <td> <code><a href="text-level-semantics.html#htmldataelement">HTMLDataElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-datalist-element">datalist</a></code>
+ <td> <code><a href="forms.html#htmldatalistelement">HTMLDataListElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-dd-element">dd</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="edits.html#the-del-element">del</a></code>
+ <td> <code><a href="edits.html#htmlmodelement">HTMLModElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="interactive-elements.html#the-details-element">details</a></code>
+ <td> <code><a href="interactive-elements.html#htmldetailselement">HTMLDetailsElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-dfn-element">dfn</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="interactive-elements.html#the-dialog-element">dialog</a></code>
+ <td> <code><a href="interactive-elements.html#htmldialogelement">HTMLDialogElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-div-element">div</a></code>
+ <td> <code><a href="grouping-content.html#htmldivelement">HTMLDivElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-dl-element">dl</a></code>
+ <td> <code><a href="grouping-content.html#htmldlistelement">HTMLDListElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-dt-element">dt</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-em-element">em</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlembedelement">HTMLEmbedElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-fieldset-element">fieldset</a></code>
+ <td> <code><a href="forms.html#htmlfieldsetelement">HTMLFieldSetElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-figcaption-element">figcaption</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-figure-element">figure</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-footer-element">footer</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-form-element">form</a></code>
+ <td> <code><a href="forms.html#htmlformelement">HTMLFormElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h1</a></code>
+ <td> <code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h2</a></code>
+ <td> <code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h3</a></code>
+ <td> <code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h4</a></code>
+ <td> <code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h5</a></code>
+ <td> <code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-h1,-h2,-h3,-h4,-h5,-and-h6-elements">h6</a></code>
+ <td> <code><a href="sections.html#htmlheadingelement">HTMLHeadingElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="document-metadata.html#the-head-element">head</a></code>
+ <td> <code><a href="document-metadata.html#htmlheadelement">HTMLHeadElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-header-element">header</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <!--FORK START/END hgroup removed-->
+
+ <tr><td> <code><a href="grouping-content.html#the-hr-element">hr</a></code>
+ <td> <code><a href="grouping-content.html#htmlhrelement">HTMLHRElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="semantics.html#the-html-element">html</a></code>
+ <td> <code><a href="semantics.html#htmlhtmlelement">HTMLHtmlElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-i-element">i</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-iframe-element">iframe</a></code>
+ <td> <code><a href="embedded-content-0.html#htmliframeelement">HTMLIFrameElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-img-element">img</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlimageelement">HTMLImageElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-input-element">input</a></code>
+ <td> <code><a href="forms.html#htmlinputelement">HTMLInputElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="edits.html#the-ins-element">ins</a></code>
+ <td> <code><a href="edits.html#htmlmodelement">HTMLModElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-kbd-element">kbd</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-keygen-element">keygen</a></code>
+ <td> <code><a href="forms.html#htmlkeygenelement">HTMLKeygenElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-label-element">label</a></code>
+ <td> <code><a href="forms.html#htmllabelelement">HTMLLabelElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-legend-element">legend</a></code>
+ <td> <code><a href="forms.html#htmllegendelement">HTMLLegendElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-li-element">li</a></code>
+ <td> <code><a href="grouping-content.html#htmllielement">HTMLLIElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="document-metadata.html#the-link-element">link</a></code>
+ <td> <code><a href="document-metadata.html#htmllinkelement">HTMLLinkElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-main-element">main</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-map-element">map</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlmapelement">HTMLMapElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-mark-element">mark</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="interactive-elements.html#the-menu-element">menu</a></code>
+ <td> <code><a href="interactive-elements.html#htmlmenuelement">HTMLMenuElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="document-metadata.html#the-meta-element">meta</a></code>
+ <td> <code><a href="document-metadata.html#htmlmetaelement">HTMLMetaElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-meter-element">meter</a></code>
+ <td> <code><a href="forms.html#htmlmeterelement">HTMLMeterElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-nav-element">nav</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="scripting-1.html#the-noscript-element">noscript</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-object-element">object</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlobjectelement">HTMLObjectElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-ol-element">ol</a></code>
+ <td> <code><a href="grouping-content.html#htmlolistelement">HTMLOListElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-optgroup-element">optgroup</a></code>
+ <td> <code><a href="forms.html#htmloptgroupelement">HTMLOptGroupElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-option-element">option</a></code>
+ <td> <code><a href="forms.html#htmloptionelement">HTMLOptionElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-output-element">output</a></code>
+ <td> <code><a href="forms.html#htmloutputelement">HTMLOutputElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-p-element">p</a></code>
+ <td> <code><a href="grouping-content.html#htmlparagraphelement">HTMLParagraphElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-param-element">param</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlparamelement">HTMLParamElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-pre-element">pre</a></code>
+ <td> <code><a href="grouping-content.html#htmlpreelement">HTMLPreElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-progress-element">progress</a></code>
+ <td> <code><a href="forms.html#htmlprogresselement">HTMLProgressElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-q-element">q</a></code>
+ <td> <code><a href="grouping-content.html#htmlquoteelement">HTMLQuoteElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <!-- FORK -->
+ <tr><td> <code><a href="text-level-semantics.html#the-rb-element">rb</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+ <!-- /FORK -->
+
+ <tr><td> <code><a href="text-level-semantics.html#the-rp-element">rp</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-rt-element">rt</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <!-- FORK -->
+ <tr><td> <code><a href="text-level-semantics.html#the-rtc-element">rtc</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+ <!-- /FORK -->
+
+ <tr><td> <code><a href="text-level-semantics.html#the-ruby-element">ruby</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-s-element">s</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-samp-element">samp</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="scripting-1.html#the-script-element">script</a></code>
+ <td> <code><a href="scripting-1.html#htmlscriptelement">HTMLScriptElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="sections.html#the-section-element">section</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-select-element">select</a></code>
+ <td> <code><a href="forms.html#htmlselectelement">HTMLSelectElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-small-element">small</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-source-element">source</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlsourceelement">HTMLSourceElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-span-element">span</a></code>
+ <td> <code><a href="text-level-semantics.html#htmlspanelement">HTMLSpanElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-strong-element">strong</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="document-metadata.html#the-style-element">style</a></code>
+ <td> <code><a href="document-metadata.html#htmlstyleelement">HTMLStyleElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sub</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="interactive-elements.html#the-summary-element">summary</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-sub-and-sup-elements">sup</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-table-element">table</a></code>
+ <td> <code><a href="tabular-data.html#htmltableelement">HTMLTableElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-tbody-element">tbody</a></code>
+ <td> <code><a href="tabular-data.html#htmltablesectionelement">HTMLTableSectionElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-td-element">td</a></code>
+ <td> <code><a href="tabular-data.html#htmltabledatacellelement">HTMLTableDataCellElement</a></code> : <code><a href="tabular-data.html#htmltablecellelement">HTMLTableCellElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="scripting-1.html#the-template-element">template</a></code>
+ <td> <code><a href="scripting-1.html#htmltemplateelement">HTMLTemplateElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="forms.html#the-textarea-element">textarea</a></code>
+ <td> <code><a href="forms.html#htmltextareaelement">HTMLTextAreaElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-tfoot-element">tfoot</a></code>
+ <td> <code><a href="tabular-data.html#htmltablesectionelement">HTMLTableSectionElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-th-element">th</a></code>
+ <td> <code><a href="tabular-data.html#htmltableheadercellelement">HTMLTableHeaderCellElement</a></code> : <code><a href="tabular-data.html#htmltablecellelement">HTMLTableCellElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-thead-element">thead</a></code>
+ <td> <code><a href="tabular-data.html#htmltablesectionelement">HTMLTableSectionElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-time-element">time</a></code>
+ <td> <code><a href="text-level-semantics.html#htmltimeelement">HTMLTimeElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="document-metadata.html#the-title-element">title</a></code>
+ <td> <code><a href="document-metadata.html#htmltitleelement">HTMLTitleElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="tabular-data.html#the-tr-element">tr</a></code>
+ <td> <code><a href="tabular-data.html#htmltablerowelement">HTMLTableRowElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-track-element">track</a></code>
+ <td> <code><a href="embedded-content-0.html#htmltrackelement">HTMLTrackElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-u-element">u</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="grouping-content.html#the-ul-element">ul</a></code>
+ <td> <code><a href="grouping-content.html#htmlulistelement">HTMLUListElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-var-element">var</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="embedded-content-0.html#the-video-element">video</a></code>
+ <td> <code><a href="embedded-content-0.html#htmlvideoelement">HTMLVideoElement</a></code> : <code><a href="embedded-content-0.html#htmlmediaelement">HTMLMediaElement</a></code> : <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ <tr><td> <code><a href="text-level-semantics.html#the-wbr-element">wbr</a></code>
+ <td> <code><a href="dom.html#htmlelement">HTMLElement</a></code>
+
+ </table><h3 class="no-num" id="all-interfaces">All Interfaces</h3>
+
+ <p><i>This section is non-normative.</i></p>
+ <ul></ul><!-- (only has events from HTML5) --><h3 class="no-num" id="events-0">Events</h3>
+
+ <p><i>This section is non-normative.</i></p>
+ <table><caption>List of events</caption>
+ <thead><tr><th> Event
+ <th> Interface
+ <th> Description
+ <tbody><tr><td> <code data-anolis-xref="event-abort">abort</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the download was aborted by the user
+
+ <tr><td> <code data-anolis-xref="event-afterprint">afterprint</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> after printing
+
+ <tr><td> <code data-anolis-xref="event-beforeprint">beforeprint</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> before printing
+
+ <tr><td> <code data-anolis-xref="event-beforeunload">beforeunload</code>
+ <td> <code><a href="browsers.html#beforeunloadevent">BeforeUnloadEvent</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the page is about to be unloaded, in case the page would like to show a warning prompt
+
+ <tr><td> <code data-anolis-xref="event-blur">blur</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at nodes losing focus
+
+ <tr><td> <code data-anolis-xref="event-change">change</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at controls when the user commits a value change
+
+ <tr><td> <code data-anolis-xref="event-click"><a href="infrastructure.html#click">click</a></code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at an element before its <a href="dom.html#activation-behavior">activation behavior</a> is run
+
+ <tr><td> <code data-anolis-xref="event-contextmenu">contextmenu</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at elements when the user requests their context menu
+
+ <tr><td> <code data-anolis-xref="event-DOMContentLoaded">DOMContentLoaded</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="dom.html#document-0">Document</a></code> once the parser has finished
+
+ <tr><td> <code data-anolis-xref="event-error">error</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at elements when network and script errors occur
+
+ <tr><td> <code data-anolis-xref="event-focus">focus</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at nodes gaining focus
+
+ <tr><td> <code data-anolis-xref="event-hashchange"><a href="browsers.html#hashchange">hashchange</a></code>
+ <td> <code><a href="browsers.html#hashchangeevent">HashChangeEvent</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the fragment identifier part of <a href="dom.html#the-document's-address">the document's address</a> changes
+
+ <tr><td> <code data-anolis-xref="event-input">input</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at controls when the user changes the value
+
+ <tr><td> <code data-anolis-xref="event-invalid">invalid</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at controls during form validation if they do not satisfy their constraints
+
+ <tr><td> <code data-anolis-xref="event-load">load</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the document has finished loading; fired at an element containing a resource (e.g. <code><a href="embedded-content-0.html#the-img-element">img</a></code>, <code><a href="embedded-content-0.html#the-embed-element">embed</a></code>) when its resource has finished loading
+
+ <tr><td> <code data-anolis-xref="event-message">message</code>
+ <td> <code>MessageEvent</code>
+ <td> Fired at an object when the object receives a message
+
+ <tr><td> <code data-anolis-xref="event-offline"><a href="browsers.html#offline-0">offline</a></code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the network connections fails
+
+ <tr><td> <code data-anolis-xref="event-online"><a href="browsers.html#online">online</a></code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the network connections returns
+
+ <tr><td> <code data-anolis-xref="event-pagehide"><a href="browsers.html#pagehide">pagehide</a></code>
+ <td> <code><a href="browsers.html#pagetransitionevent">PageTransitionEvent</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the page's entry in the <a href="browsers.html#session-history">session history</a> stops being the <a href="browsers.html#current-entry">current entry</a>
+
+ <tr><td> <code data-anolis-xref="event-pageshow"><a href="browsers.html#pageshow">pageshow</a></code>
+ <td> <code><a href="browsers.html#pagetransitionevent">PageTransitionEvent</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the page's entry in the <a href="browsers.html#session-history">session history</a> becomes the <a href="browsers.html#current-entry">current entry</a>
+
+ <tr><td> <code data-anolis-xref="event-popstate"><a href="browsers.html#popstate">popstate</a></code>
+ <td> <code><a href="browsers.html#popstateevent">PopStateEvent</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> when the user navigates the <a href="browsers.html#session-history">session history</a>
+
+ <tr><td> <code data-anolis-xref="event-readystatechange"><a href="dom.html#readystatechange">readystatechange</a></code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="dom.html#document-0">Document</a></code> when it finishes parsing and again when all its subresources have finished loading
+
+ <tr><td> <code data-anolis-xref="event-reset">reset</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at a <code><a href="forms.html#the-form-element">form</a></code> element when it is <a data-anolis-xref="concept-form-reset" href="forms.html#reset-1">reset</a>
+
+ <tr><td> <code data-anolis-xref="event-show">show</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at a <code><a href="interactive-elements.html#the-menu-element">menu</a></code> element when it is shown as a context menu
+
+ <tr><td> <code data-anolis-xref="event-submit">submit</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at a <code><a href="forms.html#the-form-element">form</a></code> element when it is <a data-anolis-xref="concept-form-submit" href="forms.html#submitted">submitted</a>
+
+ <tr><td> <code data-anolis-xref="event-unload">unload</code>
+ <td> <code><a href="infrastructure.html#event">Event</a></code>
+ <td> Fired at the <code><a href="browsers.html#window">Window</a></code> object when the page is going away
+
+ </table><p class="note">See also <a href="embedded-content-0.html#mediaevents">media element
+ events</a>, <a href="browsers.html#appcacheevents">application cache events</a>,
+ and <a href="editing.html#dndevents">drag-and-drop events</a>.</p>
+
+
+
+
+<!--FIXUP 2dcontext -4-->
+
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/html5TagTableGen.rb b/xml/impl/src/com/intellij/xml/util/documentation/html5TagTableGen.rb
new file mode 100644
index 0000000..6d0ddd1
--- /dev/null
+++ b/xml/impl/src/com/intellij/xml/util/documentation/html5TagTableGen.rb
@@ -0,0 +1,85 @@
+require 'rexml/document'
+
+# read html4 tags and attributes to be able to skip them
+file = File.new("htmltable.xml")
+doc = REXML::Document.new file
+known4Tags = Set.new
+known4Attributes = Set.new
+doc.elements.each("html-property-table/tag") { |e| known4Tags << e.attributes["name"] }
+doc.elements.each("html-property-table/attribute") { |e| known4Attributes << e.attributes["name"] }
+file.close
+
+# read html5 tags and attributes for verifying generated data
+file = File.new("html5table.xml")
+doc = REXML::Document.new file
+known5Tags = Set.new
+known5Attributes = Set.new
+doc.elements.each("html-property-table/tag") { |e| known5Tags << e.attributes["name"] }
+doc.elements.each("html-property-table/attribute") { |e| known5Attributes << e.attributes["name"] }
+file.close
+
+# read html5 spec
+generatedTags = Set.new
+result = '<html-property-table baseHelpRef="http://dev.w3.org/html5/spec/">'
+file = File.new("html5.html")
+content = file.read
+offset = 0
+# parse tags
+content.scan(/<tr><th><code><a href="([^"]+)">([^<]+).*<\/th>\s*<td>(?:<a href="[^"]+">)?([^<]+).*(<\/td>)?/) do |match|
+ next if known4Tags.include?($2)
+ startTag = true
+ endTag = true
+ nextTag = content.index("<tr>", ($~.offset(0)[1]))
+ empty = content[$~.offset(0)[0]..nextTag].include?("empty")
+ dtd = ""
+ result +=
+ "<tag name = \"#{$2}\"\n" +
+ " helpref = \"#{$1}\"\n" +
+ " description = \"#{$3}\"\n" +
+ " startTag = \"#{startTag}\"\n" +
+ " endTag = \"#{endTag}\"\n" +
+ " empty = \"#{empty}\"\n" +
+ " dtd = \"#{dtd}\"\n" +
+ "/>\n"
+ generatedTags << $2
+ offset = $~.offset(0)[1]
+end
+
+generatedAttributes = Set.new
+content[offset..-1].scan(/<tr><th>\s?<code(?:[^>]*)>([^<]+)\s*<\/code>\s*<td>([^;\n]*(?:;\s*[^;\n]*)*)\s*<td>\s*(.*)\s*<td>(.*)/) do
+ next if known4Attributes.include?($1)
+ name = $1
+ field_and_link = $2
+ description = $3
+ type = $4
+ type = type.gsub(/<[^>]*>/, "").gsub(/\s+/, " ").gsub(/"/, "").gsub(/^\s+/, "").gsub(/;$/, "")
+ description = description.gsub(/<[^>]*>/, "").gsub(/\s+/, " ").gsub(/"/, "").gsub(/^\s+/, "").gsub(/;$/, "")
+ helpref_match = field_and_link.match(/<a href="([^"]*)"/)
+ helpref = helpref_match ? helpref_match[1] : ""
+ relatedTags = field_and_link.gsub(/<[^>]*>/, "").gsub(/\s+/, " ").gsub(/"/, "").gsub(/^\s+/, "").gsub(/;$/, "")
+ dtd = ""
+ default = true
+ result +=
+ "<attribute name = \"#{name}\"\n" +
+ " helpref = \"#{helpref}\"\n" +
+ " description = \"#{description}\"\n" +
+ " relatedTags = \"#{relatedTags}\"\n" +
+ " dtd = \"#{dtd}\"\n" +
+ " type = \"#{type}\"\n" +
+ " default = \"#{default}\"\n" +
+ "/>\n"
+ generatedAttributes << name
+end
+result += '</html-property-table>'
+puts result
+
+
+
+# verify that we haven't missed tags or attributes
+if (!(generatedTags + known4Tags).superset?(known5Tags))
+ printf $stderr, "warning! missing tags: #{(known5Tags - known4Tags - generatedTags).to_a.sort}\n"
+end
+
+if !(generatedAttributes + known4Attributes).superset?(known5Attributes)
+ printf $stderr, "warning! missing attributes: #{(known5Attributes - known4Attributes - generatedAttributes).to_a.sort}\n"
+end
\ No newline at end of file
diff --git a/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml b/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
index de3dbab..bd4aa46 100644
--- a/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
+++ b/xml/impl/src/com/intellij/xml/util/documentation/html5table.xml
@@ -1,23 +1,6 @@
-<html-property-table baseHelpRef="http://dev.w3.org/html5/spec/">
-<tag name = "main"
- helpref = "grouping-content.html#the-main-element"
- description = "represents the main content of the body of a document or application"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "section"
- helpref = "sections.html#the-section-element"
- description = "generic document or application section"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "article"
+<html-property-table baseHelpRef="http://dev.w3.org/html5/spec/"><tag name = "article"
helpref = "sections.html#the-article-element"
- description = "self-contained composition in a document, page, application, or site and that is intended to be independently distributable or reusable, e.g. in syndication"
+ description = "Self-contained syndicatable or reusable composition"
startTag = "true"
endTag = "true"
empty = "false"
@@ -25,463 +8,47 @@
/>
<tag name = "aside"
helpref = "sections.html#the-aside-element"
- description = "a section of a page that consists of content that is tangentially related to the content around the aside element, and which could be considered separate from that content"
+ description = "Sidebar for tangentially related content"
startTag = "true"
endTag = "true"
empty = "false"
dtd = ""
/>
-<tag name = "hgroup"
- helpref = "sections.html#the-hgroup-element"
- description = "heading of a section"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "header"
- helpref = "sections.html#the-header-element"
- description = "group of introductory or navigational aids"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "footer"
- helpref = "sections.html#the-footer-element"
- description = "a footer for its nearest ancestor sectioning content or sectioning root element"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "nav"
- helpref = "sections.html#the-nav-element"
- description = "section of a page that links to other pages or to parts within the page"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "figure"
- helpref = "grouping-content.html#the-figure-element"
- description = "some flow content, optionally with a caption, that is self-contained and is typically referenced as a single unit from the main flow of the document"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "figcaption"
- helpref = "grouping-content.html#the-figcaption-element"
- description = "a caption or legend for the rest of the contents of the figcaption element's parent figure element, if any"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "video"
- helpref = "video.html#video"
- description = "used for playing videos or movies"
- startTag = "true"
- endTag = "false"
- empty = "false"
- dtd = ""
-/>
<tag name = "audio"
- helpref = "video.html#audio"
- description = "a sound or audio stream"
- startTag = "true"
- endTag = "false"
- empty = "false"
- dtd = ""
-/>
-<tag name = "embed"
- helpref = "the-iframe-element.html#the-embed-element"
- description = "integration point for an external application or interactive content"
- startTag = "true"
- endTag = "true"
- empty = "true"
- dtd = ""
-/>
-<tag name = "mark"
- helpref = "text-level-semantics.html#the-mark-element"
- description = "a run of text in one document marked or highlighted for reference purposes, due to its relevance in another context"
+ helpref = "embedded-content-0.html#the-audio-element"
+ description = "Audio player"
startTag = "true"
endTag = "true"
empty = "false"
dtd = ""
/>
-<tag name = "progress"
- helpref = "the-button-element.html#the-progress-element"
- description = "the completion progress of a task"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "meter"
- helpref = "the-button-element.html#the-meter-element"
- description = "a scalar measurement within a known range, or a fractional value"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "time"
- helpref = "rendering.html#the-time-element-0"
- description = "either a time on a 24 hour clock, or a precise date in the proleptic Gregorian calendar, optionally with a time and a time-zone offset"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "ruby"
- helpref = "text-level-semantics.html#the-ruby-element"
- description = "allows one or more spans of phrasing content to be marked with ruby annotation"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "rt"
- helpref = "text-level-semantics.html#the-rt-element"
- description = "marks the ruby text component of a ruby annotation"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "rp"
- helpref = "text-level-semantics.html#the-rp-element"
- description = "can be used to provide parentheses around a ruby text component of a ruby annotation, to be shown by user agents that don't support ruby annotations"
+<tag name = "bdi"
+ helpref = "text-level-semantics.html#the-bdi-element"
+ description = "Text directionality isolation"
startTag = "true"
endTag = "true"
empty = "false"
dtd = ""
/>
<tag name = "canvas"
- helpref = "the-canvas-element.html#the-canvas-element"
- description = "provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, or other visual images on the fly"
+ helpref = "scripting-1.html#the-canvas-element"
+ description = "Scriptable bitmap canvas"
startTag = "true"
endTag = "true"
empty = "false"
dtd = ""
/>
-<tag name = "command"
- helpref = "interactive-elements.html#the-command"
- description = "provides scripts with a resolution-dependent bitmap canvas, which can be used for rendering graphs, game graphics, or other visual images on the fly"
+<tag name = "data"
+ helpref = "text-level-semantics.html#the-data-element"
+ description = "Machine-readable equivalent"
startTag = "true"
endTag = "true"
- empty = "true"
+ empty = "false"
dtd = ""
/>
<tag name = "datalist"
- helpref = "the-button-element.html#the-datalist-element"
- description = "a set of option elements that represent predefined options for other controls"
- startTag = "true"
- endTag = "true"
- empty = "false"
- dtd = ""
-/>
-<tag name = "keygen"
- helpref = "the-button-element.html#the-keygen-element"
- description = "a key pair generator control"
- startTag = "true"
- endTag = "true"
- empty = "true"
- dtd = ""
-/>
-<tag name = "output"
- helpref = "the-button-element.html#the-output-element"
- description = "the result of a calculation"
- startTag = "true"
- endTag = "true"
- empty = "true"
- dtd = ""
-/>
-<attribute name = "media"
- helpref = "links.html#attr-hyperlink-media"
- description = "suppress word wrap"
- relatedTags = "a,area"
- dtd = ""
- type = "common.data.mediaquery"
- default = "false"
-/>
-<attribute name = "ping"
- helpref = ""
- description = "a space-separated list of URLs which have to be pinged when the hyperlink is followed"
- relatedTags = "a,area"
- dtd = ""
- type = "common.data.uris"
- default = "true"
-/>
-<attribute name = "hreflang"
- helpref = "links.html#attr-hyperlink-hreflang"
- description = "gives the language of the linked resource"
- relatedTags = "area"
- dtd = ""
- type = "common.data.langcode"
- default = "false"
-/>
-<attribute name = "rel"
- helpref = "links.html#attr-hyperlink-rel"
- description = ""
- relatedTags = "area"
- dtd = ""
- type = "common.data.tokens"
- default = "false"
-/>
-<attribute name = "charset"
- helpref = "semantics.html#attr-meta-charset"
- description = "the character encoding used by the document"
- relatedTags = "meta"
- dtd = ""
- type = "common.data.charset"
- default = "false"
-/>
-<attribute name = "autofocus"
- helpref = "association-of-controls-and-forms.html#attr-fe-autofocus"
- description = "allows the user to indicate that a control is to be focused as soon as the page is loaded, allowing the user to just start typing without having to manually focus the main control"
- relatedTags = "input,select,textarea,button"
- dtd = ""
- type = "(autofocus)"
- default = "true"
-/>
-<attribute name = "placeholder"
- helpref = "common-input-element-attributes.html#attr-input-placeholder"
- description = "short hint (a word or short phrase) intended to aid the user with data entry"
- relatedTags = "input"
- dtd = ""
- type = "string"
- default = "true"
-/>
-<attribute name = "placeholder"
- helpref = "the-button-element.html#attr-textarea-placeholder"
- description = "a hint (a word or short phrase) intended to aid the user with data entry"
- relatedTags = "textarea"
- dtd = ""
- type = "string"
- default = "false"
-/>
-<attribute name = "form"
- helpref = "association-of-controls-and-forms.html#attr-fae-form"
- description = ""
- relatedTags = "input,output,select,textarea,button,fieldset"
- dtd = ""
- type = "common.data.idref"
- default = "true"
-/>
-<attribute name = "required"
- helpref = "common-input-element-attributes.html#attr-input-required"
- description = "when specified, the element is required"
- relatedTags = "input"
- dtd = ""
- type = "(required)"
- default = "true"
-/>
-<attribute name = "required"
- helpref = "the-button-element.html#attr-textarea-required"
- description = "when specified, the user will be required to enter a value before submitting the form"
- relatedTags = "textarea"
- dtd = ""
- type = "(required)"
- default = "false"
-/>
-<attribute name = "disabled"
- helpref = ""
- description = "disabling all its contents when specified"
- relatedTags = "fieldset"
- dtd = ""
- type = "(disabled)"
- default = "false"
-/>
-<attribute name = "autocomplete"
- helpref = "common-input-element-attributes.html#attr-input-autocomplete"
- description = "autocompletion state"
- relatedTags = "input"
- dtd = ""
- type = "(on | off)"
- default = "true"
-/>
-<attribute name = "min"
- helpref = "common-input-element-attributes.html#attr-input-min"
- description = "indicate the allowed range of values for the element"
- relatedTags = "input"
- dtd = ""
- type = "common.data.datetime"
- default = "true"
-/>
-<attribute name = "max"
- helpref = "common-input-element-attributes.html#attr-input-max"
- description = "indicate the allowed range of values for the element"
- relatedTags = "input"
- dtd = ""
- type = "common.data.datetime"
- default = "true"
-/>
-<attribute name = "multiple"
- helpref = "common-input-element-attributes.html#attr-input-multiple"
- description = "whether the user is to be allowed to specify more than one value"
- relatedTags = "input"
- dtd = ""
- type = "(multiple)"
- default = "false"
-/>
-<attribute name = "pattern"
- helpref = "common-input-element-attributes.html#attr-input-pattern"
- description = "regular expression against which the control's value is to be checked"
- relatedTags = "input"
- dtd = ""
- type = "form.data.pattern"
- default = "true"
-/>
-<attribute name = "step"
- helpref = "common-input-element-attributes.html#attr-input-step"
- description = "the granularity that is expected (and required) of the value, by limiting the allowed values"
- relatedTags = "input"
- dtd = ""
- type = "string"
- default = "true"
-/>
-<attribute name = "list"
- helpref = "common-input-element-attributes.html#attr-input-list"
- description = "element that lists predefined options suggested to the user"
- relatedTags = "input"
- dtd = ""
- type = "common.data.idref"
- default = "true"
-/>
-<attribute name = "novalidate"
- helpref = "association-of-controls-and-forms.html#attr-fs-novalidate"
- description = "if the form is not to be validated during submission"
- relatedTags = "form"
- dtd = ""
- type = "(novalidate)"
- default = "true"
-/>
-<attribute name = "formnovalidate"
- helpref = "association-of-controls-and-forms.html#attr-fs-formnovalidate"
- description = "if the form is not to be validated during submission"
- relatedTags = "input,button"
- dtd = ""
- type = "(formnovalidate)"
- default = "true"
-/>
-<attribute name = "formaction"
- helpref = "association-of-controls-and-forms.html#attr-fs-formaction"
- description = "server-side form handler"
- relatedTags = "input,button"
- dtd = ""
- type = "common.data.uri"
- default = "true"
-/>
-<attribute name = "formenctype"
- helpref = "association-of-controls-and-forms.html#attr-fs-formenctype"
- description = ""
- relatedTags = "input,button"
- dtd = ""
- type = "shared-form.attrs.formenctype.data"
- default = "true"
-/>
-<attribute name = "formmethod"
- helpref = "association-of-controls-and-forms.html#attr-fs-formmethod"
- description = "HTTP method used to submit the form"
- relatedTags = "input,button"
- dtd = ""
- type = "(GET | POST)"
- default = "true"
-/>
-<attribute name = "formtarget"
- helpref = "association-of-controls-and-forms.html#attr-fs-formtarget"
- description = "render in this frame"
- relatedTags = "input,button"
- dtd = ""
- type = "common.data.browsing-context-or-keyword"
- default = "true"
-/>
-<attribute name = "type"
- helpref = "interactive-elements.html#attr-menu-type"
- description = "kind of menu being declared"
- relatedTags = "menu"
- dtd = ""
- type = "(toolbar | context)"
- default = "false"
-/>
-<attribute name = "label"
- helpref = "interactive-elements.html#attr-menu-label"
- description = "label of the menu"
- relatedTags = "menu"
- dtd = ""
- type = "string"
- default = "false"
-/>
-<attribute name = "scoped"
- helpref = "interactive-elements.html#attr-menu-label"
- description = "enables scoped style sheets"
- relatedTags = "style"
- dtd = ""
- type = "(scoped)"
- default = "true"
-/>
-<attribute name = "async"
- helpref = "scripting-1.html#attr-script-async"
- description = "influences script loading and execution"
- relatedTags = "script"
- dtd = ""
- type = "(async)"
- default = "true"
-/>
-<attribute name = "manifest"
- helpref = "semantics.html#attr-html-manifest"
- description = "address of the document's application cache manifest"
- relatedTags = "html"
- dtd = ""
- type = "common.data.uri"
- default = "true"
-/>
-<attribute name = "sizes"
- helpref = "links.html#attr-link-sizes"
- description = "the size of the referenced icon"
- relatedTags = "link"
- dtd = ""
- type = "string"
- default = "true"
-/>
-<attribute name = "reversed"
- helpref = "grouping-content.html#attr-ol-reversed"
- description = "if the list order is descending when present"
- relatedTags = "ol"
- dtd = ""
- type = "(reversed)"
- default = "true"
-/>
-<attribute name = "sandbox"
- helpref = "the-iframe-element.html#attr-iframe-sandbox"
- description = "enables a set of extra restrictions on any content hosted by the iframe"
- relatedTags = "iframe"
- dtd = ""
- type = "SandboxType"
- default = "true"
-/>
-<attribute name = "seamless"
- helpref = "the-iframe-element.html#attr-iframe-seamless"
- description = ""
- relatedTags = "iframe"
- dtd = ""
- type = "(seamless)"
- default = "true"
-/>
-<attribute name = "srcdoc"
- helpref = "the-iframe-element.html#attr-iframe-srcdoc"
- description = "content of the page that the nested browsing context is to contain"
- relatedTags = "iframe"
- dtd = ""
- type = "string"
- default = "true"
-/>
-<tag name = "bdi"
- helpref = "text-level-semantics.html#the-bdi-element"
- description = "represents a span of text that is to be isolated from its surroundings for the purposes of bidirectional text formatting"
+ helpref = "forms.html#the-datalist-element"
+ description = "Container for options for "
startTag = "true"
endTag = "true"
empty = "false"
@@ -489,15 +56,176 @@
/>
<tag name = "details"
helpref = "interactive-elements.html#the-details-element"
- description = "represents a disclosure widget from which the user can obtain additional information or controls"
+ description = "Disclosure control for hiding details"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "dialog"
+ helpref = "interactive-elements.html#the-dialog-element"
+ description = "Dialog box or window"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "embed"
+ helpref = "embedded-content-0.html#the-embed-element"
+ description = "Plugin"
+ startTag = "true"
+ endTag = "true"
+ empty = "true"
+ dtd = ""
+/>
+<tag name = "figcaption"
+ helpref = "grouping-content.html#the-figcaption-element"
+ description = "Caption for "
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "figure"
+ helpref = "grouping-content.html#the-figure-element"
+ description = "Figure with optional caption"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "footer"
+ helpref = "sections.html#the-footer-element"
+ description = "Footer for a page or section"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "header"
+ helpref = "sections.html#the-header-element"
+ description = "Introductory or navigational aids for a page or section"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "keygen"
+ helpref = "forms.html#the-keygen-element"
+ description = "Cryptographic key-pair generator form control"
+ startTag = "true"
+ endTag = "true"
+ empty = "true"
+ dtd = ""
+/>
+<tag name = "main"
+ helpref = "grouping-content.html#the-main-element"
+ description = "Main content of a document
+ "
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "mark"
+ helpref = "text-level-semantics.html#the-mark-element"
+ description = "Highlight"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "menuitem"
+ helpref = "interactive-elements.html#the-menuitem-element"
+ description = "Menu command"
+ startTag = "true"
+ endTag = "true"
+ empty = "true"
+ dtd = ""
+/>
+<tag name = "meter"
+ helpref = "forms.html#the-meter-element"
+ description = "Gauge"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "nav"
+ helpref = "sections.html#the-nav-element"
+ description = "Section with navigational links"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "output"
+ helpref = "forms.html#the-output-element"
+ description = "Calculated output value"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "progress"
+ helpref = "forms.html#the-progress-element"
+ description = "Progress bar"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "rb"
+ helpref = "text-level-semantics.html#the-rb-element"
+ description = "Ruby base"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "rp"
+ helpref = "text-level-semantics.html#the-rp-element"
+ description = "Parenthesis for ruby annotation text"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "rt"
+ helpref = "text-level-semantics.html#the-rt-element"
+ description = "Ruby annotation text"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "rtc"
+ helpref = "text-level-semantics.html#the-rtc-element"
+ description = "Ruby annotation text container"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "ruby"
+ helpref = "text-level-semantics.html#the-ruby-element"
+ description = "Ruby annotation(s)"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "section"
+ helpref = "sections.html#the-section-element"
+ description = "Generic document or application section"
startTag = "true"
endTag = "true"
empty = "false"
dtd = ""
/>
<tag name = "source"
- helpref = "video.html#the-source-element"
- description = "allows authors to specify multiple alternative media resources for media elements. It does not represent anything on its own"
+ helpref = "embedded-content-0.html#the-source-element"
+ description = "Media source for "
startTag = "true"
endTag = "true"
empty = "true"
@@ -505,26 +233,626 @@
/>
<tag name = "summary"
helpref = "interactive-elements.html#the-summary-element"
- description = "represents a summary, caption, or legend for the rest of the contents of the summary element's parent details element, if any"
+ description = "Caption for "
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "template"
+ helpref = "scripting-1.html#the-template-element"
+ description = "Template"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
+<tag name = "time"
+ helpref = "text-level-semantics.html#the-time-element"
+ description = "Machine-readable equivalent of date- or time-related data"
startTag = "true"
endTag = "true"
empty = "false"
dtd = ""
/>
<tag name = "track"
- helpref = "video.html#the-track-element"
- description = "allows authors to specify explicit external timed text tracks for media elements. It does not represent anything on its own"
+ helpref = "embedded-content-0.html#the-track-element"
+ description = "Timed text track"
startTag = "true"
endTag = "true"
empty = "true"
dtd = ""
/>
+<tag name = "video"
+ helpref = "embedded-content-0.html#the-video-element"
+ description = "Video player"
+ startTag = "true"
+ endTag = "true"
+ empty = "false"
+ dtd = ""
+/>
<tag name = "wbr"
helpref = "text-level-semantics.html#the-wbr-element"
- description = "represents a line break opportunity"
+ description = "Line breaking opportunity"
startTag = "true"
endTag = "true"
empty = "true"
dtd = ""
/>
-</html-property-table>
\ No newline at end of file
+<attribute name = "allowfullscreen"
+ helpref = "embedded-content-0.html#allowfullscreen"
+ description = "Whether to allow the iframe's contents to use requestFullscreen()"
+ relatedTags = "iframe"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "async"
+ helpref = "scripting-1.html#async"
+ description = "Execute script asynchronously"
+ relatedTags = "script"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "autocomplete"
+ helpref = "forms.html#autocomplete"
+ description = "Default setting for autofill feature for controls in the form"
+ relatedTags = "form"
+ dtd = ""
+ type = "on; off"
+ default = "true"
+/>
+<attribute name = "autocomplete"
+ helpref = "forms.html#autocomplete-1"
+ description = "Hint for form autofill feature"
+ relatedTags = "input; select; textarea"
+ dtd = ""
+ type = "Autofill field name and related tokens*"
+ default = "true"
+/>
+<attribute name = "autofocus"
+ helpref = "forms.html#autofocus"
+ description = "Automatically focus the form control when the page is loaded"
+ relatedTags = "button; input; keygen; select; textarea"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "autoplay"
+ helpref = "embedded-content-0.html#autoplay"
+ description = "Hint that the media resource can be started automatically when the page is loaded"
+ relatedTags = "audio; video"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "challenge"
+ helpref = "forms.html#challenge"
+ description = "String to package with the generated and signed public key"
+ relatedTags = "keygen"
+ dtd = ""
+ type = "Text"
+ default = "true"
+/>
+<attribute name = "command"
+ helpref = "interactive-elements.html#command-1"
+ description = "Command definition"
+ relatedTags = "menuitem"
+ dtd = ""
+ type = "ID*"
+ default = "true"
+/>
+<attribute name = "contenteditable"
+ helpref = ""
+ description = "Whether the element is editable"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "true; false"
+ default = "true"
+/>
+<attribute name = "contextmenu"
+ helpref = ""
+ description = "The element's context menu"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "ID*"
+ default = "true"
+/>
+<attribute name = "controls"
+ helpref = "embedded-content-0.html#controls"
+ description = "Show user agent controls"
+ relatedTags = "audio; video"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "crossorigin"
+ helpref = "embedded-content-0.html#crossorigin-3"
+ description = "How the element handles crossorigin requests"
+ relatedTags = "audio; img; link; script; video"
+ dtd = ""
+ type = "anonymous; use-credentials"
+ default = "true"
+/>
+<attribute name = "default"
+ helpref = "interactive-elements.html#default-4"
+ description = "Mark the command as being a default command"
+ relatedTags = "menuitem"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "default"
+ helpref = "embedded-content-0.html#default"
+ description = "Enable the track if no other text track is more suitable"
+ relatedTags = "track"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "dirname"
+ helpref = "forms.html#dirname-1"
+ description = "Name of form field to use for sending the element's directionality in form submission"
+ relatedTags = "input; textarea"
+ dtd = ""
+ type = "Text*"
+ default = "true"
+/>
+<attribute name = "download"
+ helpref = "links.html#download-1"
+ description = "Whether to download the resource instead of navigating to it, and its file name if so"
+ relatedTags = "a; area"
+ dtd = ""
+ type = "Text"
+ default = "true"
+/>
+<attribute name = "draggable"
+ helpref = ""
+ description = "Whether the element is draggable"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "true; false"
+ default = "true"
+/>
+<attribute name = "dropzone"
+ helpref = ""
+ description = "Accepted item types for drag-and-drop"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Unordered set of unique space-separated tokens, ASCII case-insensitive, consisting of accepted types and drag feedback*"
+ default = "true"
+/>
+<attribute name = "form"
+ helpref = "forms.html#form-1"
+ description = "Associates the control with a form element"
+ relatedTags = "button; fieldset; input; keygen; label; object; output; select; textarea"
+ dtd = ""
+ type = "ID*"
+ default = "true"
+/>
+<attribute name = "formaction"
+ helpref = "forms.html#formaction"
+ description = "URL to use for form submission"
+ relatedTags = "button; input"
+ dtd = ""
+ type = "Valid non-empty URL potentially surrounded by spaces"
+ default = "true"
+/>
+<attribute name = "formenctype"
+ helpref = "forms.html#formenctype"
+ description = "Form data set encoding type to use for form submission"
+ relatedTags = "button; input"
+ dtd = ""
+ type = "application/x-www-form-urlencoded; multipart/form-data; text/plain"
+ default = "true"
+/>
+<attribute name = "formmethod"
+ helpref = "forms.html#formmethod"
+ description = "HTTP method to use for form submission"
+ relatedTags = "button; input"
+ dtd = ""
+ type = "GET; POST"
+ default = "true"
+/>
+<attribute name = "formnovalidate"
+ helpref = "forms.html#formnovalidate"
+ description = "Bypass form control validation for form submission"
+ relatedTags = "button; input"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "formtarget"
+ helpref = "forms.html#formtarget"
+ description = "Browsing context for form submission"
+ relatedTags = "button; input"
+ dtd = ""
+ type = "Valid browsing context name or keyword"
+ default = "true"
+/>
+<attribute name = "hidden"
+ helpref = ""
+ description = "Whether the element is relevant"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "high"
+ helpref = "forms.html#high"
+ description = "Low limit of high range"
+ relatedTags = "meter"
+ dtd = ""
+ type = "Valid floating-point number*"
+ default = "true"
+/>
+<attribute name = "icon"
+ helpref = "interactive-elements.html#icon"
+ description = "Icon for the command"
+ relatedTags = "menuitem"
+ dtd = ""
+ type = "Valid non-empty URL potentially surrounded by spaces"
+ default = "true"
+/>
+<attribute name = "inert"
+ helpref = ""
+ description = "Whether the element and its descendants are inert"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "inputmode"
+ helpref = "forms.html#inputmode-1"
+ description = "Hint for selecting an input modality"
+ relatedTags = "input; textarea"
+ dtd = ""
+ type = "verbatim; "
+ default = "true"
+/>
+<attribute name = "itemid"
+ helpref = ""
+ description = "Global identifier for a microdata item"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Valid URL potentially surrounded by spaces"
+ default = "true"
+/>
+<attribute name = "itemprop"
+ helpref = ""
+ description = "Property names of a microdata item"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Unordered set of unique space-separated tokens, case-sensitive, consisting of valid absolute URLs, defined property names, or text*"
+ default = "true"
+/>
+<attribute name = "itemref"
+ helpref = ""
+ description = "Referenced elements"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Unordered set of unique space-separated tokens, case-sensitive, consisting of IDs*"
+ default = "true"
+/>
+<attribute name = "itemscope"
+ helpref = ""
+ description = "Introduces a microdata item"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "itemtype"
+ helpref = ""
+ description = "Item types of a microdata item"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "Unordered set of unique space-separated tokens, case-sensitive, consisting of valid absolute URL*"
+ default = "true"
+/>
+<attribute name = "keytype"
+ helpref = "forms.html#keytype"
+ description = "The type of cryptographic key to generate"
+ relatedTags = "keygen"
+ dtd = ""
+ type = "Text*"
+ default = "true"
+/>
+<attribute name = "kind"
+ helpref = "embedded-content-0.html#kind"
+ description = "The type of text track"
+ relatedTags = "track"
+ dtd = ""
+ type = "subtitles"
+ default = "true"
+/>
+<attribute name = "list"
+ helpref = "forms.html#list"
+ description = "List of autocomplete options"
+ relatedTags = "input"
+ dtd = ""
+ type = "ID*"
+ default = "true"
+/>
+<attribute name = "loop"
+ helpref = "embedded-content-0.html#loop"
+ description = "Whether to loop the media resource"
+ relatedTags = "audio; video"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "low"
+ helpref = "forms.html#low"
+ description = "High limit of low range"
+ relatedTags = "meter"
+ dtd = ""
+ type = "Valid floating-point number*"
+ default = "true"
+/>
+<attribute name = "manifest"
+ helpref = "semantics.html#manifest"
+ description = "Application cache manifest"
+ relatedTags = "html"
+ dtd = ""
+ type = "Valid non-empty URL potentially surrounded by spaces"
+ default = "true"
+/>
+<attribute name = "max"
+ helpref = "forms.html#max-0"
+ description = "Maximum value"
+ relatedTags = "input"
+ dtd = ""
+ type = "Varies*"
+ default = "true"
+/>
+<attribute name = "max"
+ helpref = "forms.html#max-3"
+ description = "Upper bound of range"
+ relatedTags = "meter; progress"
+ dtd = ""
+ type = "Valid floating-point number*"
+ default = "true"
+/>
+<attribute name = "mediagroup"
+ helpref = "embedded-content-0.html#mediagroup"
+ description = "Groups media elements together with an implicit MediaController"
+ relatedTags = "audio; video"
+ dtd = ""
+ type = "Text"
+ default = "true"
+/>
+<attribute name = "menu"
+ helpref = "forms.html#menu-1"
+ description = "Specifies the element's designated pop-up menu"
+ relatedTags = "button"
+ dtd = ""
+ type = "ID*"
+ default = "true"
+/>
+<attribute name = "min"
+ helpref = "forms.html#min-0"
+ description = "Minimum value"
+ relatedTags = "input"
+ dtd = ""
+ type = "Varies*"
+ default = "true"
+/>
+<attribute name = "min"
+ helpref = "forms.html#min-1"
+ description = "Lower bound of range"
+ relatedTags = "meter"
+ dtd = ""
+ type = "Valid floating-point number*"
+ default = "true"
+/>
+<attribute name = "minlength"
+ helpref = "forms.html#minlength-0"
+ description = "Minimum length of value"
+ relatedTags = "input; textarea"
+ dtd = ""
+ type = "Valid non-negative integer"
+ default = "true"
+/>
+<attribute name = "muted"
+ helpref = "embedded-content-0.html#muted-1"
+ description = "Whether to mute the media resource by default"
+ relatedTags = "audio; video"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "novalidate"
+ helpref = "forms.html#novalidate"
+ description = "Bypass form control validation for form submission"
+ relatedTags = "form"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "open"
+ helpref = "interactive-elements.html#open"
+ description = "Whether the details are visible"
+ relatedTags = "details"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "open"
+ helpref = "interactive-elements.html#open-1"
+ description = "Whether the dialog box is showing"
+ relatedTags = "dialog"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "optimum"
+ helpref = "forms.html#optimum"
+ description = "Optimum value in gauge"
+ relatedTags = "meter"
+ dtd = ""
+ type = "Valid floating-point number*"
+ default = "true"
+/>
+<attribute name = "pattern"
+ helpref = "forms.html#pattern-0"
+ description = "Pattern to be matched by the form control's value"
+ relatedTags = "input"
+ dtd = ""
+ type = "Regular expression matching the JavaScript Pattern production"
+ default = "true"
+/>
+<attribute name = "placeholder"
+ helpref = "forms.html#placeholder-0"
+ description = "User-visible label to be placed within the form control"
+ relatedTags = "input; textarea"
+ dtd = ""
+ type = "Text*"
+ default = "true"
+/>
+<attribute name = "poster"
+ helpref = "embedded-content-0.html#poster"
+ description = "Poster frame to show prior to video playback"
+ relatedTags = "video"
+ dtd = ""
+ type = "Valid non-empty URL potentially surrounded by spaces"
+ default = "true"
+/>
+<attribute name = "preload"
+ helpref = "embedded-content-0.html#preload"
+ description = "Hints how much buffering the media resource will likely need"
+ relatedTags = "audio; video"
+ dtd = ""
+ type = "none"
+ default = "true"
+/>
+<attribute name = "radiogroup"
+ helpref = "interactive-elements.html#radiogroup"
+ description = "Name of group of commands to treat as a radio button group"
+ relatedTags = "menuitem"
+ dtd = ""
+ type = "Text"
+ default = "true"
+/>
+<attribute name = "required"
+ helpref = "forms.html#required-0"
+ description = "Whether the control is required for form submission"
+ relatedTags = "input; select; textarea"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "reversed"
+ helpref = "grouping-content.html#reversed"
+ description = "Number the list backwards"
+ relatedTags = "ol"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "sandbox"
+ helpref = "embedded-content-0.html#sandbox"
+ description = "Security rules for nested content"
+ relatedTags = "iframe"
+ dtd = ""
+ type = "Unordered set of unique space-separated tokens, ASCII case-insensitive, consisting of"
+ default = "true"
+/>
+<attribute name = "spellcheck"
+ helpref = ""
+ description = "Whether the element is to have its spelling and grammar checked"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "true; false"
+ default = "true"
+/>
+<attribute name = "scoped"
+ helpref = "document-metadata.html#scoped"
+ description = "Whether the styles apply to the entire document or just the parent subtree"
+ relatedTags = "style"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "seamless"
+ helpref = "embedded-content-0.html#seamless"
+ description = "Whether to apply the document's styles to the nested content"
+ relatedTags = "iframe"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "sizes"
+ helpref = "links.html#sizes-0"
+ description = "Sizes of the icons (for rel=icon)"
+ relatedTags = "link"
+ dtd = ""
+ type = "Unordered set of unique space-separated tokens, ASCII case-insensitive, consisting of sizes*"
+ default = "true"
+/>
+<attribute name = "sortable"
+ helpref = "tabular-data.html#sortable-0"
+ description = "Enables a sorting interface for the table"
+ relatedTags = "table"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "sorted"
+ helpref = "tabular-data.html#sorted-0"
+ description = "Column sort direction and ordinality"
+ relatedTags = "th"
+ dtd = ""
+ type = "Set of space-separated tokens, ASCII case-insensitive, consisting of neither, one, or both of reversed and a valid non-negative integer greater than zero"
+ default = "true"
+/>
+<attribute name = "srcdoc"
+ helpref = "embedded-content-0.html#srcdoc"
+ description = "A document to render in the iframe"
+ relatedTags = "iframe"
+ dtd = ""
+ type = "The source of an iframe srcdoc document*"
+ default = "true"
+/>
+<attribute name = "srclang"
+ helpref = "embedded-content-0.html#srclang"
+ description = "Language of the text track"
+ relatedTags = "track"
+ dtd = ""
+ type = "Valid BCP 47 language tag"
+ default = "true"
+/>
+<attribute name = "step"
+ helpref = "forms.html#step-0"
+ description = "Granularity to be matched by the form control's value"
+ relatedTags = "input"
+ dtd = ""
+ type = "Valid floating-point number greater than zero, or any"
+ default = "true"
+/>
+<attribute name = "translate"
+ helpref = ""
+ description = "Whether the element is to be translated when the page is localized"
+ relatedTags = "HTML elements"
+ dtd = ""
+ type = "yes; no"
+ default = "true"
+/>
+<attribute name = "typemustmatch"
+ helpref = "embedded-content-0.html#typemustmatch"
+ description = "Whether the type attribute and the Content-Type value need to match for the resource to be used"
+ relatedTags = "object"
+ dtd = ""
+ type = "Boolean attribute"
+ default = "true"
+/>
+<attribute name = "wrap"
+ helpref = "forms.html#wrap"
+ description = "How the value of the form control is to be wrapped for form submission"
+ relatedTags = "textarea"
+ dtd = ""
+ type = "soft"
+ default = "true"
+/>
+</html-property-table>
diff --git a/xml/impl/xml.iml b/xml/impl/xml.iml
index 093ca25..20135bd 100644
--- a/xml/impl/xml.iml
+++ b/xml/impl/xml.iml
@@ -19,6 +19,7 @@
<orderEntry type="library" name="Guava" level="project" />
<orderEntry type="module" module-name="xml-psi-impl" exported="" />
<orderEntry type="module" module-name="xml-analysis-impl" exported="" />
+ <orderEntry type="library" name="swingx" level="project" />
</component>
<component name="copyright">
<Base>
diff --git a/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java b/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java
new file mode 100644
index 0000000..10d84cc
--- /dev/null
+++ b/xml/openapi/src/com/intellij/ide/browsers/OpenInBrowserRequest.java
@@ -0,0 +1,66 @@
+package com.intellij.ide.browsers;
+
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiFile;
+import com.intellij.util.Url;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+public abstract class OpenInBrowserRequest {
+ private Collection<Url> result;
+ protected PsiFile file;
+
+ public OpenInBrowserRequest(@NotNull PsiFile file) {
+ this.file = file;
+ }
+
+ public OpenInBrowserRequest() {
+ }
+
+ @Nullable
+ public static OpenInBrowserRequest create(@NotNull final PsiElement element) {
+ PsiFile psiFile = element.isValid() ? element.getContainingFile() : null;
+ if (psiFile == null || psiFile.getVirtualFile() == null) {
+ return null;
+ }
+
+ return new OpenInBrowserRequest(psiFile) {
+ @NotNull
+ @Override
+ public PsiElement getElement() {
+ return element;
+ }
+ };
+ }
+
+ @NotNull
+ public PsiFile getFile() {
+ return file;
+ }
+
+ @NotNull
+ public VirtualFile getVirtualFile() {
+ return file.getVirtualFile();
+ }
+
+ @NotNull
+ public Project getProject() {
+ return file.getProject();
+ }
+
+ @NotNull
+ public abstract PsiElement getElement();
+
+ public void setResult(@NotNull Collection<Url> result) {
+ this.result = result;
+ }
+
+ @Nullable
+ public Collection<Url> getResult() {
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java
index 139d7ba..179e571 100644
--- a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java
+++ b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserService.java
@@ -21,14 +21,19 @@
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
+import java.util.Collections;
public abstract class WebBrowserService {
public static WebBrowserService getInstance() {
return ServiceManager.getService(WebBrowserService.class);
}
- public abstract boolean canOpenInBrowser(@NotNull PsiElement psiElement);
+ @NotNull
+ public abstract Collection<Url> getUrlsToOpen(@NotNull OpenInBrowserRequest request, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException;
@NotNull
- public abstract Collection<Url> getUrlToOpen(@NotNull PsiElement psiElement, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException;
+ public Collection<Url> getUrlsToOpen(@NotNull final PsiElement element, boolean preferLocalUrl) throws WebBrowserUrlProvider.BrowserException {
+ OpenInBrowserRequest request = OpenInBrowserRequest.create(element);
+ return request == null ? Collections.<Url>emptyList() : getUrlsToOpen(request, preferLocalUrl);
+ }
}
\ No newline at end of file
diff --git a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java
index 6846dc8..372c28a 100644
--- a/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java
+++ b/xml/openapi/src/com/intellij/ide/browsers/WebBrowserUrlProvider.java
@@ -31,6 +31,21 @@
public abstract class WebBrowserUrlProvider {
public static final ExtensionPointName<WebBrowserUrlProvider> EP_NAME = ExtensionPointName.create("com.intellij.webBrowserUrlProvider");
+ private final boolean myDeprecatedMethodOverridden;
+
+ protected WebBrowserUrlProvider() {
+ boolean deprecatedMethodOverridden;
+ try {
+ deprecatedMethodOverridden =
+ getClass().getMethod("canHandleElement", PsiElement.class, PsiFile.class, Ref.class).getDeclaringClass() != WebBrowserUrlProvider.class ||
+ getClass().getMethod("canHandle", PsiElement.class, PsiFile.class, Ref.class).getDeclaringClass() != WebBrowserUrlProvider.class;
+ }
+ catch (Throwable ignored) {
+ deprecatedMethodOverridden = false;
+ }
+ myDeprecatedMethodOverridden = deprecatedMethodOverridden;
+ }
+
/**
* Browser exceptions are printed in Error Dialog when user presses any browser button
*/
@@ -46,6 +61,7 @@
*/
public boolean canHandleElement(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull Ref<Set<Url>> result) {
Ref<Collection<Url>> ref = Ref.create();
+ @SuppressWarnings("deprecation")
boolean canHandle = canHandle(element, psiFile, ref);
if (!ref.isNull()) {
result.set(ContainerUtil.newHashSet(ref.get()));
@@ -53,16 +69,29 @@
return canHandle;
}
+ @SuppressWarnings("UnusedParameters")
+ @Deprecated
+ /**
+ * @deprecated to remove in IDEA 15
+ */
public boolean canHandle(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull Ref<Collection<Url>> result) {
- VirtualFile file = psiFile.getVirtualFile();
- if (file == null) {
- return false;
+ return false;
+ }
+
+ public boolean canHandleElement(@NotNull OpenInBrowserRequest request) {
+ if (myDeprecatedMethodOverridden) {
+ Ref<Set<Url>> resultRef = Ref.create();
+ //noinspection deprecation
+ if (canHandleElement(request.getElement(), request.getFile(), resultRef)) {
+ request.setResult(resultRef.get());
+ return true;
+ }
}
try {
- Collection<Url> urls = getUrls(element, psiFile, file);
+ Collection<Url> urls = getUrls(request);
if (!urls.isEmpty()) {
- result.set(urls);
+ request.setResult(urls);
return true;
}
}
@@ -73,15 +102,29 @@
}
@Nullable
- protected Url getUrl(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull VirtualFile virtualFile) throws BrowserException {
+ protected Url getUrl(@NotNull OpenInBrowserRequest request, @NotNull VirtualFile virtualFile) throws BrowserException {
+ //noinspection deprecation
+ return myDeprecatedMethodOverridden ? getUrl(request.getElement(), request.getFile(), virtualFile) : null;
+ }
+
+ @SuppressWarnings("UnusedParameters")
+ @Deprecated
+ @Nullable
+ /**
+ * @deprecated to remove in IDEA 14
+ */
+ public Url getUrl(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull VirtualFile virtualFile) throws BrowserException {
return null;
}
- public Collection<Url> getUrls(@NotNull PsiElement element, @NotNull PsiFile psiFile, @NotNull VirtualFile virtualFile) throws BrowserException {
- return ContainerUtil.createMaybeSingletonSet(getUrl(element, psiFile, virtualFile));
+ @NotNull
+ public Collection<Url> getUrls(@NotNull OpenInBrowserRequest request) throws BrowserException {
+ return ContainerUtil.createMaybeSingletonList(getUrl(request, request.getVirtualFile()));
}
+ @SuppressWarnings({"UnusedParameters", "UnusedDeclaration"})
@Nullable
+ @Deprecated
public String getOpenInBrowserActionText(@NotNull PsiFile file) {
return null;
}
diff --git a/xml/relaxng/src/org/intellij/html/RngHtml5MetaDataContributor.java b/xml/relaxng/src/org/intellij/html/RngHtml5MetaDataContributor.java
index 9d7c0a3..5bdfd43 100644
--- a/xml/relaxng/src/org/intellij/html/RngHtml5MetaDataContributor.java
+++ b/xml/relaxng/src/org/intellij/html/RngHtml5MetaDataContributor.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.html;
import com.intellij.psi.PsiElement;
@@ -7,7 +22,7 @@
import com.intellij.psi.filters.XmlTextFilter;
import com.intellij.psi.meta.MetaDataContributor;
import com.intellij.psi.meta.MetaDataRegistrar;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import com.intellij.xml.util.XmlUtil;
import org.intellij.plugins.relaxNG.compact.psi.RncDecl;
import org.intellij.plugins.relaxNG.compact.psi.RncFile;
@@ -34,7 +49,7 @@
}
public boolean isClassAcceptable(Class hintClass) {
- return ReflectionCache.isAssignable(RncDocument.class, hintClass);
+ return ReflectionUtil.isAssignable(RncDocument.class, hintClass);
}
public boolean isAcceptable(Object element, PsiElement context) {
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/convert/IdeaDriver.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/convert/IdeaDriver.java
index 5d760e6..46e5f97 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/convert/IdeaDriver.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/convert/IdeaDriver.java
@@ -139,7 +139,7 @@
if (file.exists()) {
final String msg = "The file '" + file.getAbsolutePath() + "' already exists. Overwrite it?";
final int choice = Messages.showYesNoDialog(myProject, msg, "Output File Exists", Messages.getWarningIcon());
- if (choice == 0) {
+ if (choice == Messages.YES) {
return super.open(sourceUri, encoding);
} else if (choice == 1) {
throw new CanceledException();
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngElementDescriptor.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngElementDescriptor.java
index 0bf6be4..43cc0bf 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngElementDescriptor.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngElementDescriptor.java
@@ -16,12 +16,14 @@
package org.intellij.plugins.relaxNG.model.descriptors;
+import com.intellij.lang.ASTNode;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
+import com.intellij.psi.impl.source.tree.TreeUtil;
import com.intellij.psi.util.*;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
@@ -31,6 +33,7 @@
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlElementsGroup;
import com.intellij.xml.XmlNSDescriptor;
+import org.intellij.plugins.relaxNG.compact.RncElementTypes;
import org.intellij.plugins.relaxNG.compact.RncFileType;
import org.intellij.plugins.relaxNG.validation.RngSchemaValidator;
import org.jetbrains.annotations.NonNls;
@@ -270,7 +273,10 @@
final PsiElement at;
if (column > 0) {
if (decl.getContainingFile().getFileType() == RncFileType.getInstance()) {
- return file.findElementAt(startOffset + column);
+ final PsiElement rncElement = file.findElementAt(startOffset + column);
+ final ASTNode pattern = rncElement != null ? TreeUtil.findParent(rncElement.getNode(), RncElementTypes.PATTERN) : null;
+ final ASTNode nameClass = pattern != null ? pattern.findChildByType(RncElementTypes.NAME_CLASS) : null;
+ return nameClass != null ? nameClass.getPsi() : rncElement;
}
at = file.findElementAt(startOffset + column - 2);
} else {
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngNsDescriptor.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngNsDescriptor.java
index e6689ce..2bed77f 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngNsDescriptor.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/model/descriptors/RngNsDescriptor.java
@@ -189,7 +189,7 @@
dPatterns = new ArrayList<DElementPattern>();
name2patterns.put(qName, dPatterns);
}
- dPatterns.add(pattern);
+ if (!dPatterns.contains(pattern)) dPatterns.add(pattern);
}
}
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/MessageViewHelper.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/MessageViewHelper.java
index a2baae2..6344c1d 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/MessageViewHelper.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/validation/MessageViewHelper.java
@@ -196,7 +196,7 @@
myContentName + " is still running. Close anyway?",
Messages.getQuestionIcon()
);
- if (result != 0) {
+ if (result != Messages.YES) {
event.consume();
}
}
diff --git a/xml/relaxng/src/org/intellij/plugins/relaxNG/xml/dom/impl/RngReferenceConverter.java b/xml/relaxng/src/org/intellij/plugins/relaxNG/xml/dom/impl/RngReferenceConverter.java
index 163e212..02a4af1 100644
--- a/xml/relaxng/src/org/intellij/plugins/relaxNG/xml/dom/impl/RngReferenceConverter.java
+++ b/xml/relaxng/src/org/intellij/plugins/relaxNG/xml/dom/impl/RngReferenceConverter.java
@@ -17,7 +17,6 @@
package org.intellij.plugins.relaxNG.xml.dom.impl;
import com.intellij.openapi.util.Ref;
-import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceBase;
@@ -53,7 +52,7 @@
}
return new PsiReference[]{
- new PsiReferenceBase<XmlAttributeValue>(value, TextRange.from(1, value.getTextLength() - 2), true) {
+ new PsiReferenceBase<XmlAttributeValue>(value, true) {
public PsiElement resolve() {
// final XmlTag tag = PsiTreeUtil.getParentOfType(value, XmlTag.class);
// final XmlTag include = getAncestorTag(tag, "include", ProjectLoader.RNG_NAMESPACE);
diff --git a/xml/relaxng/src/resources/html5-schema/LICENSE b/xml/relaxng/src/resources/html5-schema/LICENSE
old mode 100644
new mode 100755
diff --git a/xml/relaxng/src/resources/html5-schema/applications.rnc b/xml/relaxng/src/resources/html5-schema/applications.rnc
deleted file mode 100644
index a98c20d..0000000
--- a/xml/relaxng/src/resources/html5-schema/applications.rnc
+++ /dev/null
@@ -1,364 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Web Application Features #
-# #####################################################################
-
-## Additions to Common Attributes
-
- common.attrs.interact &=
- ( common.attrs.contextmenu?
- & common.attrs.contenteditable?
- & common.attrs.draggable?
- & common.attrs.dropzone?
- & common.attrs.hidden?
- & common.attrs.spellcheck?
- )
-
- common.attrs.other &= common.attrs.interact
-
-## Context Menu: contextmenu
-
- common.attrs.contextmenu =
- attribute contextmenu {
- common.data.idref
- }
-
-## Editable Content: contenteditable
-
- common.attrs.contenteditable =
- attribute contenteditable {
- w:string "true" | w:string "false" | w:string ""
- }
-
-## Draggable Element: draggable
-
- common.attrs.draggable =
- attribute draggable {
- w:string "true" | w:string "false"
- }
-
-## Dropzone: dropzone
-
- common.attrs.dropzone =
- attribute dropzone {
- list {
- ( xsd:string { pattern = "[sS][tT][rR][iI][nN][gG]:.+" }
- | xsd:string { pattern = "[fF][iI][lL][eE]:.+" }
- )*
- ,
- ( w:string "copy"
- | w:string "move"
- | w:string "link"
- )?
- ,
- ( xsd:string { pattern = "[sS][tT][rR][iI][nN][gG]:.+" }
- | xsd:string { pattern = "[fF][iI][lL][eE]:.+" }
- )*
- }
- }
-
-## Hidden Element: hidden
-
- common.attrs.hidden =
- attribute hidden {
- w:string "hidden" | w:string ""
- }
-
-## Spellchecking and grammar checking: spellcheck
-
- common.attrs.spellcheck =
- attribute spellcheck{
- w:string "true" | w:string "false" | w:string ""
- }
-
-## Application Cache: manifest
-
- html.attrs.manifest =
- attribute manifest {
- common.data.uri.non-empty
- }
-
- html.attrs &= html.attrs.manifest?
-
-## Progess Indicator: <progress>
-
- progress.elem =
- element progress { progress.inner & progress.attrs }
- progress.attrs =
- ( common.attrs
- & progress.attrs.value?
- & progress.attrs.max?
- & ( common.attrs.aria.role.progressbar
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- progress.attrs.value =
- attribute value {
- common.data.float.non-negative
- }
- progress.attrs.max =
- attribute max {
- common.data.float.positive
- }
- progress.inner =
- ( common.inner.phrasing ) #Cannot enforce textContent format here
-
- common.elem.phrasing |= progress.elem
-
-## Dialog box, inspector, or window: <dialog>
- dialog.elem =
- element dialog { dialog.inner & dialog.attrs }
- dialog.attrs =
- ( common.attrs
- & dialog.attrs.open?
- & ( common.attrs.aria.role.alert
- | common.attrs.aria.role.alertdialog
- | common.attrs.aria.role.contentinfo
- | common.attrs.aria.role.dialog
- | common.attrs.aria.role.log
- | common.attrs.aria.role.main
- | common.attrs.aria.role.marquee
- | common.attrs.aria.role.region
- | common.attrs.aria.role.status
- | common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.document
- | common.attrs.aria.landmark.search
- )?
- )
- dialog.attrs.open =
- attribute open {
- w:string "open" | w:string ""
- }
- dialog.inner =
- ( common.inner.flow )
- common.elem.flow |= dialog.elem
-
-## Command with an associated action: <command type='command'>
-
- command.command.elem =
- element command { command.inner & command.command.attrs }
- command.command.attrs =
- ( common.attrs
- & command.command.attrs.type?
- & common-command.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- command.command.attrs.type =
- attribute type {
- w:string "command"
- }
- command.elem = command.command.elem
-
-## Selection of one item from a list of items: <command type='radio'>
-
- command.radio.elem =
- element command { command.inner & command.radio.attrs }
- command.radio.attrs =
- ( common.attrs
- & ( command.radio.attrs.type
- & command.radio.attrs.radiogroup #REVISIT taking liberties here
- & command.radio.attrs.checked?
- )
- & common-command.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- command.radio.attrs.type =
- attribute type {
- w:string "radio"
- }
- command.radio.attrs.radiogroup =
- attribute radiogroup {
- string #REVISIT need special format here?
- }
- command.radio.attrs.checked =
- attribute checked {
- w:string "checked" | w:string ""
- }
- command.elem |= command.radio.elem
-
-## State or option that can be toggled: <command type='checkbox'>
-
- command.checkbox.elem =
- element command { command.inner & command.checkbox.attrs }
- command.checkbox.attrs =
- ( common.attrs
- & ( command.checkbox.attrs.type
- & command.checkbox.attrs.checked?
- )
- & common-command.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- command.checkbox.attrs.type =
- attribute type {
- w:string "checkbox"
- }
- command.checkbox.attrs.checked =
- attribute checked {
- w:string "checked" | w:string ""
- }
- command.elem |= command.checkbox.elem
-
- common-command.attrs =
- ( command.attrs.label?
- & command.attrs.icon?
- & command.attrs.disabled?
- )
- command.attrs.label =
- attribute label {
- string
- }
- command.attrs.icon =
- attribute icon {
- common.data.uri.non-empty
- }
- command.attrs.disabled =
- attribute disabled {
- w:string "disabled" | w:string ""
- }
- command.inner =
- ( empty )
-
- common.elem.metadata |=
- ( command.elem & nonHTMLizable )
- common.elem.phrasing |= command.elem
-
-## Menu: <menu>
-
- menu.elem =
- element menu { menu.inner & menu.attrs }
- menu.attrs =
- ( common.attrs
- & menu.attrs.type?
- & menu.attrs.label?
- & common.attrs.aria? # some roles only allowed if type is "toolbar" state; check in assertions
- )
- menu.attrs.type =
- attribute type {
- w:string "toolbar" | w:string "context"
- }
- menu.attrs.label =
- attribute label {
- string
- }
- menu.inner =
- ( mli.elem*
- | common.inner.flow
- )
-
- common.elem.flow |= menu.elem
- # REVISIT allow nested menus
-
-## Menu Item: <li>
-
- mli.elem =
- element li { mli.inner & mli.attrs }
- mli.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- mli.inner =
- ( common.inner.flow )
-
-## Canvas for Dynamic Graphics: <canvas>
-
- canvas.elem.flow =
- element canvas { canvas.inner.flow & canvas.attrs }
- canvas.elem.phrasing =
- element canvas { canvas.inner.phrasing & canvas.attrs }
- canvas.attrs =
- ( common.attrs
- & canvas.attrs.height?
- & canvas.attrs.width?
- & common.attrs.aria?
- )
- canvas.attrs.height =
- attribute height {
- common.data.integer.non-negative
- }
- canvas.attrs.width =
- attribute width {
- common.data.integer.non-negative
- }
- canvas.inner.flow =
- ( common.inner.transparent.flow )
- canvas.inner.phrasing =
- ( common.inner.phrasing )
-
- common.elem.flow |= canvas.elem.flow
- common.elem.phrasing |= canvas.elem.phrasing
-
-## Additional On-Demand Information: <details>
-
- details.elem =
- element details { details.inner & details.attrs }
- details.attrs =
- ( common.attrs
- & details.attrs.open?
- & ( common.attrs.aria.implicit.region # aria-expanded must be true if open attr present; check by assertions
- | common.attrs.aria.role.alertdialog
- | common.attrs.aria.role.banner
- | common.attrs.aria.role.button
- | common.attrs.aria.role.combobox
- | common.attrs.aria.role.dialog
- | common.attrs.aria.role.directory
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.img
- | common.attrs.aria.role.link
- | common.attrs.aria.role.list
- | common.attrs.aria.role.listbox
- | common.attrs.aria.role.listitem
- | common.attrs.aria.role.log
- | common.attrs.aria.role.marquee
- | common.attrs.aria.role.menu
- | common.attrs.aria.role.menubar
- | common.attrs.aria.role.note
- | common.attrs.aria.role.separator
- | common.attrs.aria.role.status
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.tablist
- | common.attrs.aria.role.tabpanel
- | common.attrs.aria.role.toolbar
- | common.attrs.aria.role.tree
- | common.attrs.aria.role.treeitem
- | common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.article
- | common.attrs.aria.landmark.complementary
- | common.attrs.aria.landmark.contentinfo
- | common.attrs.aria.landmark.document
- | common.attrs.aria.landmark.form
- | common.attrs.aria.landmark.main
- | common.attrs.aria.landmark.navigation
- | common.attrs.aria.landmark.search
- )?
- )
- details.attrs.open =
- attribute open {
- w:string "open" | w:string ""
- }
- details.inner =
- ( summary.elem
- , common.inner.flow
- )
-
- common.elem.flow |= details.elem
-
-## Caption/summary for details element: <summary>
-
- summary.elem =
- element summary { summary.inner & summary.attrs }
- summary.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- summary.inner =
- ( common.inner.phrasing )
diff --git a/xml/relaxng/src/resources/html5-schema/aria.rnc b/xml/relaxng/src/resources/html5-schema/aria.rnc
deleted file mode 100644
index a7a3067..0000000
--- a/xml/relaxng/src/resources/html5-schema/aria.rnc
+++ /dev/null
@@ -1,1095 +0,0 @@
-# #####################################################################
-## RELAX NG Schema for HTML 5: Accessible Rich Internet Applications #
-# #####################################################################
-
-# #####################################################################
-## ARIA
-
-## Global states and properties
-
-aria.global =
- ( aria.prop.atomic?
- & aria.state.busy?
- & aria.prop.controls?
- & aria.prop.describedby?
- & aria.state.disabled?
- & aria.state.dropeffect?
- & aria.prop.flowto?
- & aria.state.grabbed?
- & aria.prop.haspopup?
- & aria.state.hidden?
- & aria.state.invalid?
- & aria.prop.label?
- & aria.prop.labelledby?
- & aria.prop.live?
- & aria.prop.owns?
- & aria.prop.relevant?
- & aria.prop.required?
- )
-
-common.attrs.other &= aria.global?
-
-## States and Properties for Native Roles
-
-# common.attrs.aria.implicit.button |=
-# ( aria.prop.controls?
-# )
-
-# common.attrs.aria.implicit.input |=
-# ( aria.prop.controls?
-# & aria.state.invalid?
-# & aria.prop.required?
-# )
-
-common.attrs.aria.implicit.region |=
- ( aria.state.expanded?
-# & aria.prop.level?
- )
-
-common.attrs.aria.implicit.group |=
- ( aria.state.expanded?
- & aria.prop.activedescendant?
- )
-
-common.attrs.aria.implicit.th |=
- ( aria.prop.sort?
- & aria.prop.level?
- & aria.state.expanded?
- & aria.prop.readonly?
- & aria.state.selected?
- )
-
-# common.attrs.aria.implicit.structure |=
-# ( aria.prop.atomic?
-# & aria.state.busy?
-# & aria.prop.channel?
-# & aria.prop.live?
-# & aria.prop.relevant?
-# )
-
-# common.attrs.aria.implicit.link |=
-# ( aria.prop.controls?
-# & aria.state.disabled?
-# )
-
-common.attrs.aria.implicit.listitem |=
- ( aria.prop.posinset?
- & aria.prop.setsize?
-# & aria.prop.atomic?
- )
-
-# common.attrs.aria.implicit.img |=
-# ( aria.prop.atomic?
-# & aria.state.busy?
-# & aria.prop.channel?
-# & aria.prop.controls?
-# & aria.prop.live?
-# & aria.prop.relevant?
-# )
-
-#common.attrs.aria.implicit.select |=
-# ( aria.state.invalid?
-# & aria.prop.required?
-# & aria.prop.atomic?
-# & aria.state.busy?
-# & aria.prop.channel?
-# & aria.prop.controls?
-# & aria.prop.live?
-# & aria.prop.relevant?
-# )
-
-# #####################################################################
-## States
-
-## busy
- aria.state.busy =
- attribute aria-busy
- { string "true"
- | string "false" #default
- }
-
-## checked
- aria.state.checked =
- attribute aria-checked
- { string "true"
- | string "false"
- | string "mixed"
- | string "undefined" #default
- }
-
-## disabled
- aria.state.disabled =
- attribute aria-disabled
- { string "true"
- | string "false" #default
- }
-
-## dropeffect
- aria.state.dropeffect =
- attribute aria-dropeffect
- { token "none" #default
- | token "popup"
- | token "execute"
- | list
- { ( string "copy" )
- , ( string "execute" )?
- }
- | list
- { ( string "move" )
- , ( string "execute" )?
- }
- | list
- { ( string "reference" )
- , ( string "execute" )?
- }
- | list
- { ( string "execute" )
- , ( string "copy" )
- }
- | list
- { ( string "execute" )
- , ( string "move" )
- }
- | list
- { ( string "execute" )
- , ( string "reference" )
- }
- }
-
-## expanded
- aria.state.expanded =
- attribute aria-expanded
- { string "true"
- | string "false"
- | string "undefined" #default
- }
-
-## grabbed
- aria.state.grabbed =
- attribute aria-grabbed
- { string "true"
- | string "false"
- | string "undefined" #default
- }
-
-## hidden
- aria.state.hidden =
- attribute aria-hidden
- { string "true"
- | string "false" #default
- }
-
-## invalid
- aria.state.invalid =
- attribute aria-invalid
- { string "true"
- | string "false" #default
- | string "grammar"
- | string "spelling"
- }
-
-## pressed
- aria.state.pressed =
- attribute aria-pressed
- { string "true"
- | string "false"
- | string "mixed"
- | string "undefined" #default
- }
-
-## selected
- aria.state.selected =
- attribute aria-selected
- { string "true"
- | string "false"
- | string "undefined" #default
- }
-
-
-
-# #####################################################################
-## Properties
-
-## activedescendant
- aria.prop.activedescendant =
- attribute aria-activedescendant {
- common.data.idref #REVISIT add Schematron check
- }
-
-## atomic
- aria.prop.atomic =
- attribute aria-atomic
- { string "true"
- | string "false" #default
- }
-
-## autocomplete
- aria.prop.autocomplete =
- attribute aria-autocomplete
- { string "inline"
- | string "list"
- | string "both"
- | string "none" #default
- }
-
-## controls
- aria.prop.controls =
- attribute aria-controls {
- common.data.idrefs #REVISIT add Schematron check
- }
-
-## describedby
- aria.prop.describedby =
- attribute aria-describedby {
- common.data.idrefs #REVISIT add Schematron check
- }
-
-## flowto
- aria.prop.flowto =
- attribute aria-flowto {
- common.data.idrefs #REVISIT add Schematron check
- }
-
-## haspopup
- aria.prop.haspopup =
- attribute aria-haspopup
- { string "true" #REVISIT check owns or descendant
- | string "false" #default
- }
-
-## label
- aria.prop.label =
- attribute aria-label {
- string
- }
-
-## labelledby
- aria.prop.labelledby =
- attribute aria-labelledby {
- common.data.idrefs #REVISIT add Schematron check
- }
-
-## level
- aria.prop.level =
- attribute aria-level {
- common.data.integer.positive
- }
-
-## live
- aria.prop.live =
- attribute aria-live
- { string "off" #default
- | string "polite"
- | string "assertive"
- }
-
-## multiline
- aria.prop.multiline =
- attribute aria-multiline
- { string "true"
- | string "false" #default
- }
-
-## multiselectable
- aria.prop.multiselectable =
- attribute aria-multiselectable
- { string "true"
- | string "false" #default
- }
-
-## owns
- aria.prop.owns =
- attribute aria-owns {
- common.data.idrefs #REVISIT add Schematron check
- }
-
-## posinset
- aria.prop.posinset =
- attribute aria-posinset {
- common.data.integer.positive
- }
-
-## readonly
- aria.prop.readonly =
- attribute aria-readonly
- { string "true"
- | string "false" #default
- }
- common.attrs.aria.prop.readonly |= aria.prop.readonly
-
-## relevant
- aria.prop.relevant =
- attribute aria-relevant
- { token "all"
- | list
- { ( string "additions" )
- , ( string "removals" )?
- , ( string "text" )?
- }
- | list
- { ( string "additions" )
- , ( string "text" )?
- , ( string "removals" )?
- }
- | list
- { ( string "removals" )
- , ( string "additions" )?
- , ( string "text" )?
- }
- | list
- { ( string "removals" )
- , ( string "text" )?
- , ( string "additions" )?
- }
- | list
- { ( string "text" )
- , ( string "additions" )?
- , ( string "removals" )?
- }
- | list
- { ( string "text" )
- , ( string "removals" )?
- , ( string "additions" )?
- }
- }
-
-## required
- aria.prop.required =
- attribute aria-required
- { string "true"
- | string "false" #default
- }
-
-## setsize
- aria.prop.setsize =
- attribute aria-setsize {
- common.data.integer.non-negative
- }
-
-## sort
- aria.prop.sort =
- attribute aria-sort
- { string "ascending"
- | string "descending"
- | string "none" #default
- | string "other"
- }
-
-## valuemax
- aria.prop.valuemax =
- attribute aria-valuemax {
- common.data.float #REVISIT
- }
-
-## valuemin
- aria.prop.valuemin =
- attribute aria-valuemin {
- common.data.float #REVISIT
- }
-
-## valuenow
- aria.prop.valuenow =
- attribute aria-valuenow {
- common.data.float #REVISIT
- }
-
-## valuetext
- aria.prop.valuetext =
- attribute aria-valuetext {
- string
- }
-
-# #####################################################################
-## Roles
-
-## alert
- aria.alert =
- ( aria.role.alert
- & aria.state.expanded?
- )
- aria.role.alert =
- attribute role { string "alert" }
-
- common.attrs.aria |= aria.alert
- common.attrs.aria.role.alert |= aria.alert
-
-## alertdialog
- aria.alertdialog =
- ( aria.role.alertdialog
- & aria.state.expanded?
- )
- aria.role.alertdialog =
- attribute role { string "alertdialog" }
-
- common.attrs.aria |= aria.alertdialog
- common.attrs.aria.role.alertdialog |= aria.alertdialog
-
-## application
- aria.application =
- ( aria.role.application
- & aria.state.expanded?
- )
- aria.role.application =
- attribute role { string "application" }
-
- common.attrs.aria |= aria.application
- common.attrs.aria.landmark.application |= aria.application
-
-## article
- aria.article =
- ( aria.role.article
- & aria.state.expanded?
- )
- aria.role.article =
- attribute role { string "article" }
-
- common.attrs.aria |= aria.article
- common.attrs.aria.landmark.article |= aria.article
-
-## banner
- aria.banner =
- ( aria.role.banner
- & aria.state.expanded?
- )
- aria.role.banner =
- attribute role { string "banner" }
-
- common.attrs.aria |= aria.banner
- common.attrs.aria.landmark.banner |= aria.banner
-
-## button
- aria.button =
- ( aria.role.button
- & aria.state.pressed? # not inherited
- )
- aria.role.button =
- attribute role { string "button" }
-
- common.attrs.aria |= aria.button
- common.attrs.aria.role.button |= aria.button
-
-## checkbox
- aria.checkbox =
- ( aria.role.checkbox
- & aria.state.checked #required!
- )
- aria.role.checkbox =
- attribute role { string "checkbox" }
-
- common.attrs.aria |= aria.checkbox
-
-# columnheader
- aria.columnheader =
- ( aria.role.columnheader
- & aria.prop.sort? # not inherited
- & aria.prop.readonly? # not inherited
- & aria.state.selected? # not inherited
- & aria.state.expanded?
- )
- aria.role.columnheader =
- attribute role { string "columnheader" }
-
- common.attrs.aria |= aria.columnheader
-
-## combobox
- aria.combobox =
- ( aria.role.combobox
- & aria.prop.activedescendant?
- & aria.state.expanded #required!
- )
- aria.role.combobox =
- attribute role { string "combobox" }
-
- common.attrs.aria |= aria.combobox
- common.attrs.aria.role.combobox |= aria.combobox
-
-## complementary
- aria.complementary =
- ( aria.role.complementary
- & aria.state.expanded?
- )
- aria.role.complementary =
- attribute role { string "complementary" }
-
- common.attrs.aria |= aria.complementary
- common.attrs.aria.landmark.complementary |= aria.complementary
-
-## contentinfo
- aria.contentinfo =
- ( aria.role.contentinfo
- & aria.state.expanded?
- )
- aria.role.contentinfo =
- attribute role { string "contentinfo" }
-
- common.attrs.aria |= aria.contentinfo
- common.attrs.aria.landmark.contentinfo |= aria.contentinfo
-
-## definition
- aria.definition =
- ( aria.role.definition
- & aria.state.expanded?
- )
- aria.role.definition =
- attribute role { string "definition" }
-
- common.attrs.aria |= aria.definition
-
-## dialog
- aria.dialog =
- ( aria.role.dialog
- & aria.state.expanded?
- )
- aria.role.dialog =
- attribute role { string "dialog" }
-
- common.attrs.aria |= aria.dialog
- common.attrs.aria.role.dialog |= aria.dialog
-
-## directory
- aria.directory =
- ( aria.role.directory
- & aria.state.expanded?
- )
- aria.role.directory =
- attribute role { string "directory" }
-
- common.attrs.aria |= aria.directory
- common.attrs.aria.role.directory |= aria.directory
-
-## document
- aria.document =
- ( aria.role.document
- & aria.state.expanded?
- )
- aria.role.document =
- attribute role { string "document" }
-
- common.attrs.aria |= aria.document
- common.attrs.aria.landmark.document |= aria.document
-
-## form
- aria.form =
- ( aria.role.form
- & aria.state.expanded?
- )
- aria.role.form =
- attribute role { string "form" }
-
- common.attrs.aria |= aria.form
- common.attrs.aria.landmark.form |= aria.form
-
-## grid
- aria.grid =
- ( aria.role.grid
- & aria.prop.level? # not inherited
- & aria.prop.multiselectable? # not inherited
- & aria.prop.readonly? # not inherited
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.grid =
- attribute role { string "grid" }
-
- common.attrs.aria |= aria.grid
-
-## gridcell
- aria.gridcell =
- ( aria.role.gridcell
- & aria.prop.level? # net inherited
- & aria.prop.readonly? # not inherited
- & aria.state.selected? # not inherited
- & aria.state.expanded?
- )
- aria.role.gridcell =
- attribute role { string "gridcell" }
-
- common.attrs.aria |= aria.gridcell
-
-## group
- aria.group =
- ( aria.role.group
- & aria.prop.activedescendant? # not inherited
- & aria.state.expanded? # not inherited
- )
- aria.role.group =
- attribute role { string "group" }
-
- common.attrs.aria |= aria.group
-
-## heading
- aria.heading =
- ( aria.role.heading
- & aria.prop.level ? # not inherited
- & aria.state.expanded?
- )
- aria.role.heading =
- attribute role { string "heading" }
-
- common.attrs.aria |= aria.heading
- common.attrs.aria.role.heading |= aria.heading
-
-## img
- aria.img =
- ( aria.role.img
- & aria.state.expanded?
- )
- aria.role.img =
- attribute role { string "img" }
-
- common.attrs.aria |= aria.img
- common.attrs.aria.role.img |= aria.img
-
-## link
- aria.link =
- ( aria.role.link
- )
- aria.role.link =
- attribute role { string "link" }
-
- common.attrs.aria |= aria.link
- common.attrs.aria.role.link |= aria.link
-
-## list
- aria.list =
- ( aria.role.list
- & aria.state.expanded?
- )
- aria.role.list =
- attribute role { string "list" }
-
- common.attrs.aria |= aria.list
- common.attrs.aria.role.list |= aria.list
-
-## listbox
- aria.listbox =
- ( aria.role.listbox
- & aria.prop.multiselectable? # not inherited
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.listbox =
- attribute role { string "listbox" }
-
- common.attrs.aria |= aria.listbox
- common.attrs.aria.role.listbox |= aria.listbox
-
-## listitem
- aria.listitem =
- ( aria.role.listitem
- & aria.prop.posinset? # not inherited
- & aria.prop.setsize? # not inherited
- & aria.prop.level? # not inherited
- & aria.state.expanded?
- )
- aria.role.listitem =
- attribute role { string "listitem" }
-
- common.attrs.aria |= aria.listitem
- common.attrs.aria.role.listitem |= aria.listitem
-
-## log
- aria.log =
- ( aria.role.log
- & aria.state.expanded?
- )
- aria.role.log =
- attribute role { string "log" }
-
- common.attrs.aria |= aria.log
- common.attrs.aria.role.log |= aria.log
-
-## main
- aria.main =
- ( aria.role.main
- & aria.state.expanded?
- )
- aria.role.main =
- attribute role { string "main" }
-
- common.attrs.aria |= aria.main
- common.attrs.aria.landmark.main |= aria.main
-
-## marquee
- aria.marquee =
- ( aria.role.marquee
- & aria.state.expanded?
- )
- aria.role.marquee =
- attribute role { string "marquee" }
-
- common.attrs.aria |= aria.marquee
- common.attrs.aria.role.marquee |= aria.marquee
-
-## math
- aria.math =
- ( aria.role.math
- & aria.state.expanded?
- )
- aria.role.math =
- attribute role { string "math" }
-
- common.attrs.aria |= aria.math
-
-## menu
- aria.menu =
- ( aria.role.menu
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.menu =
- attribute role { string "menu" }
-
- common.attrs.aria |= aria.menu
- common.attrs.aria.role.menu |= aria.menu
-
-## menubar
- aria.menubar =
- ( aria.role.menubar
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.menubar =
- attribute role { string "menubar" }
-
- common.attrs.aria |= aria.menubar
- common.attrs.aria.role.menubar |= aria.menubar
-
-
-## menuitem
- aria.menuitem =
- ( aria.role.menuitem )
- aria.role.menuitem =
- attribute role { string "menuitem" }
-
- common.attrs.aria |= aria.menuitem
- common.attrs.aria.role.menuitem |= aria.menuitem
-
-## menuitemcheckbox
- aria.menuitemcheckbox =
- ( aria.role.menuitemcheckbox
- & aria.state.checked #required
- )
- aria.role.menuitemcheckbox =
- attribute role { string "menuitemcheckbox" }
-
- common.attrs.aria |= aria.menuitemcheckbox
- common.attrs.aria.role.menuitemcheckbox |= aria.menuitemcheckbox
-
-## menuitemradio
- aria.menuitemradio =
- ( aria.role.menuitemradio
- & aria.state.checked #required
- & aria.state.selected?
- )
- aria.role.menuitemradio =
- attribute role { string "menuitemradio" }
-
- common.attrs.aria |= aria.menuitemradio
- common.attrs.aria.role.menuitemradio |= aria.menuitemradio
-
-## navigation
- aria.navigation =
- ( aria.role.navigation
- & aria.state.expanded?
- )
- aria.role.navigation =
- attribute role { string "navigation" }
-
- common.attrs.aria |= aria.navigation
- common.attrs.aria.landmark.navigation |= aria.navigation
-
-## note
- aria.note =
- ( aria.role.note
- & aria.state.expanded?
- )
- aria.role.note =
- attribute role { string "note" }
-
- common.attrs.aria |= aria.note
- common.attrs.aria.landmark.note |= aria.note
-
-## option
- aria.option =
- ( aria.role.option
- & aria.state.checked? # not inherited
- & aria.state.selected? # not inherited
- )
- aria.role.option =
- attribute role { string "option" }
-
- common.attrs.aria |= aria.option
- common.attrs.aria.role.option |= aria.option
-
-
-## presentation
- aria.presentation =
- ( aria.role.presentation
- & aria.state.expanded?
- )
- aria.role.presentation =
- attribute role { string "presentation" }
-
- common.attrs.aria |= aria.presentation
- common.attrs.aria.role.presentation |= aria.presentation
-
-## progressbar
- aria.progressbar =
- ( aria.role.progressbar
- & aria.prop.valuemax? # not inherited
- & aria.prop.valuemin? # not inherited
- & aria.prop.valuenow? # not inherited
- & aria.prop.valuetext? # not inherited
- )
- aria.role.progressbar =
- attribute role { string "progressbar" }
-
- common.attrs.aria |= aria.progressbar
- common.attrs.aria.role.progressbar |= aria.progressbar
-
-## radio
- aria.radio =
- ( aria.role.radio
- & aria.state.checked #required!
- & aria.state.selected?
- )
- aria.role.radio =
- attribute role { string "radio" }
-
- common.attrs.aria |= aria.radio
- common.attrs.aria.role.radio |= aria.radio
-
-## radiogroup
- aria.radiogroup =
- ( aria.role.radiogroup
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.radiogroup =
- attribute role { string "radiogroup" }
-
- common.attrs.aria |= aria.radiogroup
-
-## region
- aria.region =
- ( aria.role.region
- & aria.state.expanded?
- )
- aria.role.region =
- attribute role { string "region" }
-
- common.attrs.aria |= aria.region
- common.attrs.aria.role.region |= aria.region
-
-## row
- aria.row =
- ( aria.role.row
- & aria.prop.level? # not inherited
- & aria.state.selected? # not inherited
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.row =
- attribute role { string "row" }
-
- common.attrs.aria |= aria.row
-
-# rowheader
- aria.rowheader =
- ( aria.role.rowheader
- & aria.prop.sort? # not inherited
- & aria.prop.readonly? # not inherited
- & aria.state.selected? # not inherited
- & aria.state.expanded?
- )
- aria.role.rowheader =
- attribute role { string "rowheader" }
-
- common.attrs.aria |= aria.rowheader
-
-## search
- aria.search =
- ( aria.role.search
- & aria.state.expanded?
- )
- aria.role.search =
- attribute role { string "search" }
-
- common.attrs.aria |= aria.search
- common.attrs.aria.landmark.search |= aria.search
-
-## separator
- aria.separator =
- ( aria.role.separator
- & aria.state.expanded?
- )
- aria.role.separator =
- attribute role { string "separator" }
-
- common.attrs.aria |= aria.separator
- common.attrs.aria.role.separator |= aria.separator
-
-## slider
- aria.slider =
- ( aria.role.slider
- & aria.prop.valuemax
- & aria.prop.valuemin
- & aria.prop.valuenow
- & aria.prop.valuetext
- )
- aria.role.slider =
- attribute role { string "slider" }
-
- common.attrs.aria |= aria.slider
- common.attrs.aria.role.slider |= aria.slider
-
-## spinbutton
- aria.spinbutton =
- ( aria.role.spinbutton
- & aria.prop.activedescendant?
- & aria.prop.valuemax
- & aria.prop.valuemin
- & aria.prop.valuenow
- & aria.prop.valuetext
- )
- aria.role.spinbutton =
- attribute role { string "spinbutton" }
-
- common.attrs.aria |= aria.spinbutton
- common.attrs.aria.role.spinbutton |= aria.spinbutton
-
-## status
- aria.status =
- ( aria.role.status
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.status =
- attribute role { string "status" }
-
- common.attrs.aria |= aria.status
- common.attrs.aria.role.status |= aria.status
-
-## tab
- aria.tab =
- ( aria.role.tab
- & aria.state.selected?
- & aria.state.expanded?
- )
- aria.role.tab =
- attribute role { string "tab" }
-
- common.attrs.aria |= aria.tab
- common.attrs.aria.role.tab |= aria.tab
-
-## tablist
- aria.tablist =
- ( aria.role.tablist
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.tablist =
- attribute role { string "tablist" }
- common.attrs.aria |= aria.tablist
- common.attrs.aria.role.tablist |= aria.tablist
-
-## tabpanel
- aria.tabpanel =
- ( aria.role.tabpanel
- & aria.state.expanded?
- )
- aria.role.tabpanel =
- attribute role { string "tabpanel" }
-
- common.attrs.aria |= aria.tabpanel
- common.attrs.aria.role.tabpanel |= aria.tabpanel
-
-## textbox
- aria.textbox =
- ( aria.role.textbox
- & aria.prop.autocomplete? # not inherited
- & aria.prop.multiline? # not inherited
- & aria.prop.readonly? # not inherited
- )
- aria.role.textbox =
- attribute role { string "textbox" }
-
- common.attrs.aria |= aria.textbox
- common.attrs.aria.role.textbox |= aria.textbox
-
-## timer
- aria.timer =
- ( aria.role.timer
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.timer =
- attribute role { string "timer" }
-
- common.attrs.aria |= aria.timer
-
-## toolbar
- aria.toolbar =
- ( aria.role.toolbar
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.toolbar =
- attribute role { string "toolbar" }
-
- common.attrs.aria |= aria.toolbar
- common.attrs.aria.role.toolbar |= aria.toolbar
-
-## tooltip
- aria.tooltip =
- ( aria.role.tooltip
- & aria.state.expanded?
- )
- aria.role.tooltip =
- attribute role { string "tooltip" }
-
- common.attrs.aria |= aria.tooltip
-
-## tree
- aria.tree =
- ( aria.role.tree
- & aria.prop.multiselectable? # not inherited
- & aria.prop.activedescendant?
- & aria.state.expanded?
- )
- aria.role.tree =
- attribute role { string "tree" }
-
- common.attrs.aria |= aria.tree
- common.attrs.aria.role.tree |= aria.tree
-
-## treegrid
- aria.treegrid =
- ( aria.role.treegrid
- & aria.prop.activedescendant?
- & aria.state.expanded?
- & aria.prop.level?
- & aria.prop.multiselectable?
- & aria.prop.readonly?
- )
- aria.role.treegrid =
- attribute role { string "treegrid" }
-
- common.attrs.aria |= aria.treegrid
-
-## treeitem
- aria.treeitem =
- ( aria.role.treeitem
- & aria.state.checked?
- & aria.state.expanded?
- & aria.prop.level?
- & aria.prop.posinset?
- & aria.state.selected?
- & aria.prop.setsize?
- )
- aria.role.treeitem =
- attribute role { string "treeitem" }
-
- common.attrs.aria |= aria.treeitem
- common.attrs.aria.role.treeitem |= aria.treeitem
diff --git a/xml/relaxng/src/resources/html5-schema/block.rnc b/xml/relaxng/src/resources/html5-schema/block.rnc
deleted file mode 100644
index eeef411..0000000
--- a/xml/relaxng/src/resources/html5-schema/block.rnc
+++ /dev/null
@@ -1,221 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Basic Prose Markup #
-# #####################################################################
-
-# #####################################################################
-## Paragraph-Level
-
-## Paragraph: <p>
-
- p.elem =
- element p { p.inner & p.attrs }
- p.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- p.inner =
- ( common.inner.phrasing ) # REVISIT lists in span?
-
- common.elem.flow |= p.elem
-
-## Hint Transition: <hr>
-
- hr.elem =
- element hr { hr.inner & hr.attrs }
- hr.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.separator
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- hr.inner =
- ( empty )
-
- common.elem.flow |= hr.elem
-
-# #####################################################################
-## Preformatting Blocks
-
-## Preformatted Text: <pre>
-
- pre.elem =
- element pre { pre.inner & pre.attrs }
- pre.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- pre.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= pre.elem
-
-# #####################################################################
-## Simple Lists
-
-## Unordered List: <ul>
-
- ul.elem =
- element ul { ul.inner & ul.attrs }
- ul.attrs =
- ( common.attrs
- & ( ( common.attrs.aria.role.directory
- | common.attrs.aria.role.list
- | common.attrs.aria.role.listbox
- | common.attrs.aria.role.menu
- | common.attrs.aria.role.menubar
- | common.attrs.aria.role.tablist
- | common.attrs.aria.role.toolbar
- | common.attrs.aria.role.tree
- | common.attrs.aria.role.presentation
- )
- | common.attrs.aria.implicit.region
- )?
- )
- ul.inner =
- ( li.elem* )
-
- common.elem.flow |= ul.elem
-
-## Unordered List Item: <li>
-
- li.elem =
- element li { li.inner & li.attrs }
- li.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- li.inner =
- ( common.inner.flow )
-
-## Ordered List: <ol>
-
- ol.elem =
- element ol { ol.inner & ol.attrs }
- ol.attrs =
- ( common.attrs
- & ol.attrs.start?
- & ol.attrs.reversed?
- & ol.attrs.type?
- & ( ( common.attrs.aria.role.directory
- | common.attrs.aria.role.list
- | common.attrs.aria.role.listbox
- | common.attrs.aria.role.menu
- | common.attrs.aria.role.menubar
- | common.attrs.aria.role.tablist
- | common.attrs.aria.role.toolbar
- | common.attrs.aria.role.tree
- | common.attrs.aria.role.presentation
- )
- | common.attrs.aria.implicit.region
- )?
- )
- ol.attrs.start =
- attribute start {
- common.data.integer
- }
- ol.attrs.reversed =
- attribute reversed {
- w:string "reversed" | w:string ""
- }
- ol.attrs.type =
- attribute type {
- w:string "1" | w:string "a" | w:string "A" | w:string "i" | w:string "I"
- }
- ol.inner =
- ( oli.elem* )
-
- common.elem.flow |= ol.elem
-
-## Ordered List Item: <li>
-
- oli.elem =
- element li { oli.inner & oli.attrs }
- oli.attrs =
- ( common.attrs
- & oli.attrs.value?
- & common.attrs.aria?
- )
- oli.attrs.value =
- attribute value {
- common.data.integer
- }
- oli.inner =
- ( common.inner.flow )
-
-# #####################################################################
-## Definition Lists
-
-## Definition List: <dl>
-
- dl.elem =
- element dl { dl.inner & dl.attrs }
- dl.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- dl.inner =
- ( ( dt.elem+
- , dd.elem+
- )*
- )
-
- common.elem.flow |= dl.elem
-
-## Definition Term: <dt>
-
- dt.elem =
- element dt { dt.inner & dt.attrs }
- dt.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- dt.inner =
- ( common.inner.flow )
-
-## Definition Description: <dd>
-
- dd.elem =
- element dd { dd.inner & dd.attrs }
- dd.elem.phrasing =
- element dd { dd.inner.phrasing & dd.attrs }
- dd.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- dd.inner =
- ( common.inner.flow )
- dd.inner.phrasing =
- ( common.inner.phrasing )
-
-# #####################################################################
-## Miscellaneous Elements
-
-## Generic Container: <div>
-
- div.elem =
- element div { div.inner & div.attrs }
- div.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- div.inner =
- ( common.inner.flow )
-
- common.elem.flow |= div.elem
-
-## Title or Explanatory Caption: <legend>
-
- legend.elem =
- element legend { legend.inner & legend.attrs }
- legend.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- legend.inner =
- ( common.inner.phrasing )
diff --git a/xml/relaxng/src/resources/html5-schema/common.rnc b/xml/relaxng/src/resources/html5-schema/common.rnc
deleted file mode 100644
index 34d15fb..0000000
--- a/xml/relaxng/src/resources/html5-schema/common.rnc
+++ /dev/null
@@ -1,478 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Common Definitions #
-# #####################################################################
-
-
-# #####################################################################
-## Language Parameters - redefine in inclusion block as necessary #
-# #####################################################################
-
-## HTML vs. XHTML restrictions
-
- XMLonly = empty
- HTMLonly = notAllowed
-
-## HTML 4 Compatibility - set to notAllowed to disallow markup introduced in HTML 5
-# (This only affects mixed-version modules; wholly HTML5
-# modules should simply be left out of the inclusion list.)
-
- v5only = empty
-
-## HTML Compatibility Switches - set to notAllowed to disallow
-
- ## XML features that can't be roundtripped HTML <-> XHTML
- # (xml:base on elements other than <html>)
- nonRoundtrippable = empty
-
- ## XML features that can't be serialized as HTML
- nonHTMLizable = empty
-
-## features that are not part of the W3C HTML spec
- nonW3C = empty
-
-# #####################################################################
-## Wildcards #
-# #####################################################################
-
-## Any attribute from any namespace
-
- common.attr.anything =
- attribute * { text }*
-
-## Any element from any namespace
-
- common.elem.anything =
- element * { common.inner.anything & common.attr.anything }
-
-## Any content from any namespace
-
- common.inner.anything =
- ( text
- & common.elem.anything*
- )
-
-# #####################################################################
-## Common Element Classes #
-# #####################################################################
-
-## Metadata Elements
-
- common.elem.metadata =
- ( notAllowed )
-
-## Phrase Elements
-
- common.elem.phrasing =
- ( notAllowed )
-
-## Prose Elements
-
- common.elem.flow =
- ( common.elem.phrasing )
-
-
-# #####################################################################
-## Common Content Models #
-# #####################################################################
-
-## Metadata Content
-
- common.inner.metadata =
- ( common.elem.metadata* )
-
-## Phrase Content
-
- common.inner.phrasing =
- ( text & common.elem.phrasing* )
-
-## Prose Content
-
- common.inner.transparent.flow =
- ( text & common.elem.flow* )
-
- common.inner.flow =
- ( style.elem.scoped?,
- ( text
- & common.elem.flow*
- )
- )
-
-# #####################################################################
-## Common Attributes #
-# #####################################################################
-
-# When updating, check <bdo> definition too
-
-common.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- )
-
-common.attrs.basic =
- ( ( common.attrs.id
- | common.attrs.xml-id
- )? # REVISIT assuming only either one is allowed
- & common.attrs.class?
- & common.attrs.title?
- & common.attrs.base?
- & common.attrs.space?
- )
- common.attrs.id =
- attribute id {
- common.data.id
- }
- common.attrs.xml-id =
- attribute xml:id {
- xsd:NCName
- } & XMLonly
- common.attrs.class =
- attribute class {
- common.data.tokens
- }
- common.attrs.title =
- attribute title {
- text
- }
- common.attrs.base =
- common.attrs.xmlbase
- & nonRoundtrippable
- common.attrs.xmlbase =
- attribute xml:base {
- common.data.uri
- } & XMLonly
- common.attrs.space =
- common.attrs.xmlspace
- common.attrs.xmlspace =
- attribute xml:space {
- string "preserve" | string "default"
- } & XMLonly
-
-common.attrs.i18n =
- ( common.attrs.dir?
- & common.attrs.language?
- & common.attrs.translate?
- )
- common.attrs.dir =
- attribute dir {
- w:string "ltr" | w:string "rtl" | w:string "auto"
- }
- # This lang definition is a hack for enviroments where
- # the HTML5 parser maps lang to xml:lang.
- # Sameness check left to Schematron
- common.attrs.language =
- ( common.attrs.xmllang?
- & common.attrs.lang?
- )
- common.attrs.lang =
- attribute lang {
- common.data.langcode
- } & XMLonly
- common.attrs.xmllang =
- attribute xml:lang {
- common.data.langcode
- }
-# common.attrs.language =
-# ( common.attrs.lang
-# | common.attrs.xmllang
-# )
-# common.attrs.lang =
-# attribute lang {
-# common.data.langcode
-# } & HTMLonly
-# common.attrs.xmllang =
-# attribute xml:lang {
-# common.data.langcode
-# } & XMLonly
- common.attrs.translate =
- attribute translate {
- w:string "yes" | w:string "no"
- }
-
-common.attrs.present =
- ( common.attrs.style?
- & common.attrs.tabindex?
- & common.attrs.accesskey?
- )
- common.attrs.style =
- attribute style {
- string
- }
- common.attrs.tabindex =
- attribute tabindex {
- common.data.integer
- }
- # REVISIT move style to a module and bundle tabindex with ARIA
- common.attrs.accesskey =
- attribute accesskey {
- common.data.keylabellist
- }
-
-common.attrs.other =
- empty
-
-# #####################################################################
-## Common Datatypes #
-# #####################################################################
-
-## Names and Tokens
-
- common.data.tokens =
- list { token* }
-
- common.data.browsing-context =
- w:browsing-context
-
- common.data.browsing-context-or-keyword =
- w:browsing-context-or-keyword
-# xsd:string {
-# pattern = "()|([^_].*)|(_[bB][lL][aA][nN][kK])|(_[sS][eE][lL][fF])|(_[pP][aA][rR][eE][nN][tT])|(_[tT][oO][pP])"
-# }
-
-
-## IDs and IDREFs
-
- common.data.id =
- w:ID
-# xsd:string {
-# pattern = "\S+"
-# }
-
- common.data.idref =
- w:IDREF
-
- common.data.idrefs =
- w:IDREFS
-
- common.data.name =
- w:ID #FIXME
-
- common.data.hash-name =
- w:hash-name
-# xsd:string {
-# pattern = "#.+"
-# }
-
-## Numerical
-
- common.data.integer =
- w:integer
-# xsd:string {
-# pattern = "-?[0-9]+"
-# }
-
- common.data.integer.positive =
- w:integer-positive
-# xsd:string {
-# pattern = "0*[1-9][0-9]*"
-# }
-
- common.data.integer.non-negative =
- w:integer-non-negative
-# xsd:string {
-# pattern = "[0-9]+"
-# }
-
-# common.data.percent =
-# xsd:string {
-# pattern = "(100)|([1-9]?[0-9](\.[0-9]+)?)%"
-# }
-
- common.data.float =
- w:float
-# xsd:string {
-# pattern = "-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"
-# }
-
- common.data.float.positive =
- w:float-positive
-# xsd:string {
-# pattern = "(0*[1-9][0-9]*(\.[0-9]+)?)|([0-9]+(\.0*[1-9][0-9]*)?)([eE]-?[0-9]+)?"
-# }
-
- common.data.float.non-negative =
- w:float-non-negative
-# xsd:string {
-# pattern = "[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"
-# }
-
-## Temporal
-
- common.data.datetime =
- w:datetime-tz
-
- common.data.date-or-time =
- w:date-or-time
-
- common.data.date =
- w:date
-
- common.data.time-datetime =
- w:time-datetime
-
-## IRIs
-
- common.data.uri =
- # allow either a non-empty IRI ref or zero or more HTML
- # space characters (which are: space, tab, LF, FF, CR)
- ( w:iri-ref
- | xsd:string {
- pattern = "[ \x{0A}-\x{0D}]*"
- # NOTE The range above incorrectly allows U+000B
- # in addition to the HTML space characters; but
- # that's not a problem in practice because HTML
- # and XML parsers will both catch any U+000B
- # and report an error for it before that pattern
- # ever gets evaluated.
- }
- )
-
- common.data.uri.non-empty =
- w:iri-ref
-
- common.data.uris =
- list { w:iri-ref* }
-
- common.data.uri.absolute =
- w:iri
-
-## <link type='icon'> sizes
-
- common.data.sizes =
-# list { w:sizes }
- list {
- xsd:string {
- pattern = "[1-9][0-9]*x[1-9][0-9]*"
- }+
- }
-
-## MIME types
-
- common.data.mimetype =
- w:mime-type
-
-## Encodings
-
- common.data.charset =
- w:charset
-
- common.data.meta-charset =
- w:meta-charset
-
-## Refresh
-
- common.data.refresh =
- w:refresh
-
-## Default style
-
- common.data.default-style =
- string
-# w:default-style
-
-## Media Queries
-
- common.data.mediaquery =
- w:media-query
-
-## Language Codes
-
- common.data.langcode =
- w:string "" | w:language
-
-## List of Key Labels
- common.data.keylabellist =
- w:keylabellist
-
-## Microdata Properties
- common.data.microdata-properties =
- list { w:microdata-property+ }
-
-## Zero
- common.data.zero =
- w:zero
-
-## ECMAScript FunctionBody
- common.data.functionbody =
- w:functionbody
-
-# #####################################################################
-## WF2 Module Hook #
-# #####################################################################
-
-common-form.attrs.form = ( notAllowed )
-
-# #####################################################################
-## ARIA Module Hooks #
-# #####################################################################
-
-common.attrs.aria = ( notAllowed )
-common.attrs.aria.role.alert = ( notAllowed )
-common.attrs.aria.role.alertdialog = ( notAllowed )
-common.attrs.aria.role.application = ( notAllowed )
-common.attrs.aria.role.article = ( notAllowed )
-common.attrs.aria.role.banner = ( notAllowed )
-common.attrs.aria.role.button = ( notAllowed )
-common.attrs.aria.role.checkbox = ( notAllowed )
-common.attrs.aria.role.combobox = ( notAllowed )
-common.attrs.aria.role.complementary = ( notAllowed )
-common.attrs.aria.role.contentinfo = ( notAllowed )
-common.attrs.aria.role.dialog = ( notAllowed )
-common.attrs.aria.role.directory = ( notAllowed )
-common.attrs.aria.role.document = ( notAllowed )
-common.attrs.aria.role.heading = ( notAllowed )
-common.attrs.aria.role.img = ( notAllowed )
-common.attrs.aria.role.link = ( notAllowed )
-common.attrs.aria.role.list = ( notAllowed )
-common.attrs.aria.role.listitem = ( notAllowed )
-common.attrs.aria.role.log = ( notAllowed )
-common.attrs.aria.role.listbox = ( notAllowed )
-common.attrs.aria.role.main = ( notAllowed )
-common.attrs.aria.role.marquee = ( notAllowed )
-common.attrs.aria.role.menu = ( notAllowed )
-common.attrs.aria.role.menubar = ( notAllowed )
-common.attrs.aria.role.menuitem = ( notAllowed )
-common.attrs.aria.role.menuitemcheckbox = ( notAllowed )
-common.attrs.aria.role.menuitemradio = ( notAllowed )
-common.attrs.aria.role.note = ( notAllowed )
-common.attrs.aria.role.option = ( notAllowed )
-common.attrs.aria.role.presentation = ( notAllowed )
-common.attrs.aria.role.progressbar = ( notAllowed )
-common.attrs.aria.role.radio = ( notAllowed )
-common.attrs.aria.role.region = ( notAllowed )
-common.attrs.aria.role.search = ( notAllowed )
-common.attrs.aria.role.separator = ( notAllowed )
-common.attrs.aria.role.slider = ( notAllowed )
-common.attrs.aria.role.spinbutton = ( notAllowed )
-common.attrs.aria.role.status = ( notAllowed )
-common.attrs.aria.role.tab = ( notAllowed )
-common.attrs.aria.role.tablist = ( notAllowed )
-common.attrs.aria.role.textbox = ( notAllowed )
-common.attrs.aria.role.toolbar = ( notAllowed )
-common.attrs.aria.role.tree = ( notAllowed )
-common.attrs.aria.role.treeitem = ( notAllowed )
-common.attrs.aria.implicit.button = ( notAllowed )
-common.attrs.aria.implicit.input = ( notAllowed )
-common.attrs.aria.implicit.region = ( notAllowed )
-common.attrs.aria.implicit.group = ( notAllowed )
-common.attrs.aria.implicit.th = ( notAllowed )
-common.attrs.aria.implicit.structure = ( notAllowed )
-common.attrs.aria.implicit.link = ( notAllowed )
-common.attrs.aria.implicit.listitem = ( notAllowed )
-common.attrs.aria.implicit.img = ( notAllowed )
-common.attrs.aria.implicit.select = ( notAllowed )
-common.attrs.aria.prop.readonly = ( notAllowed )
-common.attrs.aria.landmark.application = ( notAllowed )
-common.attrs.aria.landmark.banner = ( notAllowed )
-common.attrs.aria.landmark.complementary = ( notAllowed )
-common.attrs.aria.landmark.contentinfo = ( notAllowed )
-common.attrs.aria.landmark.main = ( notAllowed )
-common.attrs.aria.landmark.navigation = ( notAllowed )
-common.attrs.aria.landmark.search = ( notAllowed )
-# per ARIA spec: article, document, and note are not actually landmarks
-common.attrs.aria.landmark.article = ( notAllowed )
-common.attrs.aria.landmark.document = ( notAllowed )
-common.attrs.aria.landmark.note = ( notAllowed )
diff --git a/xml/relaxng/src/resources/html5-schema/data.rnc b/xml/relaxng/src/resources/html5-schema/data.rnc
deleted file mode 100644
index e4c72de..0000000
--- a/xml/relaxng/src/resources/html5-schema/data.rnc
+++ /dev/null
@@ -1,78 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Static Data Markup #
-# #####################################################################
-
-## Time: <time>
-
- time.elem =
- element time { time.inner & time.attrs }
- time.attrs =
- ( common.attrs
- & time.attrs.datetime?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- time.attrs.datetime =
- attribute datetime {
- common.data.time-datetime
- }
- time.attrs.datetime.dateonly =
- attribute datetime {
- common.data.date
- }
- time.attrs.datetime.tz =
- attribute datetime {
- common.data.datetime
- }
- time.inner =
- ( common.inner.phrasing ) #Cannot enforce textContent format here
-
- common.elem.phrasing |= time.elem
-
-## Scalar Gauge: <meter>
-
- meter.elem =
- element meter { meter.inner & meter.attrs }
- meter.attrs =
- ( common.attrs
- & meter.attrs.value
- & meter.attrs.min?
- & meter.attrs.low?
- & meter.attrs.high?
- & meter.attrs.max?
- & meter.attrs.optimum?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meter.attrs.value =
- attribute value {
- common.data.float
- }
- meter.attrs.min =
- attribute min {
- common.data.float
- }
- meter.attrs.low =
- attribute low {
- common.data.float
- }
- meter.attrs.high =
- attribute high {
- common.data.float
- }
- meter.attrs.max =
- attribute max {
- common.data.float
- }
- meter.attrs.optimum =
- attribute optimum {
- common.data.float
- }
- meter.inner =
- ( common.inner.phrasing ) #Cannot enforce textContent format here
-
- common.elem.phrasing |= meter.elem
diff --git a/xml/relaxng/src/resources/html5-schema/embed.rnc b/xml/relaxng/src/resources/html5-schema/embed.rnc
deleted file mode 100644
index 014ac5b..0000000
--- a/xml/relaxng/src/resources/html5-schema/embed.rnc
+++ /dev/null
@@ -1,657 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-namespace local = ""
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Embedded Content #
-# #####################################################################
-
-#######################################################################
-## Replaced Content
-
-## Images: <img>
-
- img.elem =
- element img { img.inner & img.attrs }
- img.attrs =
- ( common.attrs
- & img.attrs.src
- & img.attrs.alt? # ARIA: if alt empty, only allowed role value is "presentation"; check in assertions
- & img.attrs.height?
- & img.attrs.width?
- & img.attrs.usemap?
- & img.attrs.ismap?
- & img.attrs.border? # obsolete
- & common.attrs.aria?
- )
- img.attrs.src =
- attribute src {
- common.data.uri.non-empty
- }
- img.attrs.alt =
- attribute alt {
- text
- }
- img.attrs.height =
- attribute height {
- common.data.integer.non-negative
- }
- img.attrs.width =
- attribute width {
- common.data.integer.non-negative
- }
- img.attrs.usemap =
- attribute usemap {
- common.data.hash-name
- }
- img.attrs.ismap =
- attribute ismap {
- w:string "ismap" | w:string ""
- }
- img.attrs.border =
- attribute border {
- common.data.zero
- }
- img.inner =
- empty
-
- common.elem.phrasing |= img.elem
-
-## Plug-ins: <embed>
-
- embed.elem =
- element embed { embed.inner & embed.attrs }
- embed.attrs =
- ( common.attrs
- & embed.attrs.src?
- & embed.attrs.type?
- & embed.attrs.height?
- & embed.attrs.width?
- & embed.attrs.other*
- & ( common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.document
- | common.attrs.aria.role.img
- )?
- )
- embed.attrs.src =
- attribute src {
- common.data.uri.non-empty
- }
- embed.attrs.type =
- attribute type {
- common.data.mimetype
- }
- embed.attrs.height =
- attribute height {
- common.data.integer.non-negative
- }
- embed.attrs.width =
- attribute width {
- common.data.integer.non-negative
- }
- embed.attrs.other = # REVISIT common.attrs
- attribute local:* - ( src
- | type
- | height
- | width
- | id
- | class
- | title
- | dir
- | lang
- | translate
- | style
- | tabindex
- | contextmenu
- | contenteditable
- | draggable
- | dropzone
- | hidden
- | onabort
- | onblur
- | oncanplay
- | oncanplaythrough
- | onchange
- | onclick
- | oncontextmenu
- | ondblclick
- | ondrag
- | ondragend
- | ondragenter
- | ondragleave
- | ondragover
- | ondragstart
- | ondrop
- | ondurationchange
- | onemptied
- | onended
- | onerror
- | onfocus
- | oninput
- | oninvalid
- | onkeydown
- | onkeypress
- | onkeyup
- | onload
- | onloadeddata
- | onloadedmetadata
- | onloadstart
- | onmousedown
- | onmousemove
- | onmouseout
- | onmouseover
- | onmouseup
- | onmousewheel
- | onpause
- | onplay
- | onplaying
- | onprogress
- | onratechange
- | onreset
- | onscroll
- | onseeked
- | onseeking
- | onselect
- | onshow
- | onstalled
- | onsubmit
- | onsuspend
- | ontimeupdate
- | onvolumechange
- | onwaiting
- | onafterprint
- | onbeforeprint
- | onbeforeunload
- | onhashchange
- | onmessage
- | onoffline
- | ononline
- | onpopstate
- | onredo
- | onresize
- | onstorage
- | onundo
- | onunload
- | role
- | aria-atomic
- | aria-busy
- | aria-controls
- | aria-describedby
- | aria-disabled
- | aria-dropeffect
- | aria-expanded
- | aria-flowto
- | aria-grabbed
- | aria-haspopup
- | aria-hidden
- | aria-invalid
- | aria-label
- | aria-labelledby
- | aria-live
- | aria-owns
- | aria-relevant
- | aria-required
- | spellcheck
- | accesskey
- | itemref
- | itemprop
- | itemscope
- | itemtype
- | itemid
- | name
- | align
- | about
- | prefix
- | property
- | typeof
- | vocab
- | content
- | datatype
- | href
- | rel
- | resource
- | rev
- | inlist
- | its-loc-note
- | its-loc-note-type
- | its-loc-note-ref
- | its-term-info-ref
- | its-term
- | its-term-confidence
- | its-within-text
- | its-domain-mapping
- | its-disambig-granularity
- | its-disambig-confidence
- | its-disambig-class-ref
- | its-disambig-ident
- | its-disambig-ident-ref
- | its-disambig-source
- | its-locale-filter-list
- | its-person
- | its-person-ref
- | its-org
- | its-org-ref
- | its-tool
- | its-tool-ref
- | its-rev-person
- | its-rev-person-ref
- | its-rev-org
- | its-rev-org-ref
- | its-rev-tool
- | its-rev-tool-ref
- | its-prov-ref
- | its-provenance-records-ref
- | its-loc-quality-issues-ref
- | its-loc-quality-issue-type
- | its-loc-quality-issue-comment
- | its-loc-quality-issue-severity
- | its-loc-quality-issue-profile-ref
- | its-loc-quality-issue-enabled
- | its-loc-quality-rating-score
- | its-loc-quality-rating-vote
- | its-loc-quality-rating-score-threshold
- | its-loc-quality-rating-vote-threshold
- | its-loc-quality-rating-profile-ref
- | its-mt-confidence
- | its-allowed-characters
- | its-storage-size
- | its-storage-encoding
- | its-line-break-type
- | its-annotators-ref
- )
- {
- string
- }
- embed.inner =
- empty
-
- common.elem.phrasing |= embed.elem
-
-## Generic Objects: <object>
-
- object.elem.flow =
- element object { object.inner.flow & object.attrs }
- object.elem.phrasing =
- element object { object.inner.phrasing & object.attrs }
- object.attrs =
- ( common.attrs
- & ( ( object.attrs.data
- & object.attrs.type?
- )
- | object.attrs.type
- )
-# & object.attrs.classid?
-# & object.attrs.codebase?
-# & object.attrs.codetype?
- & object.attrs.height?
- & object.attrs.width?
- & object.attrs.usemap?
- & object.attrs.name?
- & common-form.attrs.form?
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.document
- | common.attrs.aria.role.img
- )?
- )
- object.attrs.data =
- attribute data {
- common.data.uri.non-empty
- }
- object.attrs.type =
- attribute type {
- common.data.mimetype
- }
- object.attrs.height =
- attribute height {
- common.data.integer.non-negative
- }
- object.attrs.width =
- attribute width {
- common.data.integer.non-negative
- }
- object.attrs.usemap =
- attribute usemap {
- common.data.hash-name
- }
- object.attrs.name =
- attribute name {
- common.data.browsing-context
- }
- object.inner.flow =
- ( param.elem*
- , common.inner.transparent.flow
- )
- object.inner.phrasing =
- ( param.elem*
- , common.inner.phrasing
- )
-
- common.elem.flow |= object.elem.flow
- common.elem.phrasing |= object.elem.phrasing
-
-## Initialization Parameters: <param>
-
- param.elem =
- element param { param.inner & param.attrs }
- param.attrs =
- ( common.attrs
- & param.attrs.name
- & param.attrs.value
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- param.attrs.name =
- attribute name {
- string
- }
- param.attrs.value =
- attribute value {
- string
- }
- param.inner =
- ( empty )
-
-## Inline Frame: <iframe>
-
- iframe.elem =
- element iframe { iframe.inner & iframe.attrs }
- iframe.attrs =
- ( common.attrs
- & iframe.attrs.src?
- & iframe.attrs.srcdoc?
- & iframe.attrs.name?
- & iframe.attrs.width?
- & iframe.attrs.height?
- & iframe.attrs.sandbox?
- & iframe.attrs.seamless?
- & iframe.attrs.allowfullscreen?
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.document
- | common.attrs.aria.role.img
- )?
- )
- iframe.attrs.src =
- attribute src {
- common.data.uri.non-empty
- }
- iframe.attrs.srcdoc =
- attribute srcdoc {
- string #FIXME
- }
- iframe.attrs.name =
- attribute name {
- common.data.browsing-context
- }
- iframe.attrs.height =
- attribute height {
- common.data.integer.non-negative
- }
- iframe.attrs.width =
- attribute width {
- common.data.integer.non-negative
- }
- iframe.attrs.seamless =
- attribute seamless {
- w:string "seamless" | w:string ""
- } & v5only
- iframe.attrs.sandbox =
- attribute sandbox
- { list
- { ( w:string "allow-top-navigation" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-scripts" )?
- }
- | list
- { ( w:string "allow-top-navigation" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-forms" )?
- }
- | list
- { ( w:string "allow-top-navigation" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-scripts" )?
- }
- | list
- { ( w:string "allow-top-navigation" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-same-origin" )?
- }
- | list
- { ( w:string "allow-top-navigation" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-forms" )?
- }
- | list
- { ( w:string "allow-top-navigation" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-same-origin" )?
- }
- | list
- { ( w:string "allow-same-origin" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-scripts" )?
- }
- | list
- { ( w:string "allow-same-origin" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-forms" )?
- }
- | list
- { ( w:string "allow-forms" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-scripts" )?
- }
- | list
- { ( w:string "allow-forms" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-same-origin" )?
- }
- | list
- { ( w:string "allow-scripts" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-forms" )?
- }
- | list
- { ( w:string "allow-scripts" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-same-origin" )?
- }
- | list
- { ( w:string "allow-same-origin" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-scripts" )?
- }
- | list
- { ( w:string "allow-same-origin" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-forms" )?
- }
- | list
- { ( w:string "allow-forms" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-scripts" )?
- }
- | list
- { ( w:string "allow-forms" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-same-origin" )?
- }
- | list
- { ( w:string "allow-scripts" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-forms" )?
- }
- | list
- { ( w:string "allow-scripts" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-top-navigation" )?
- , ( w:string "allow-same-origin" )?
- }
- | list
- { ( w:string "allow-same-origin" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-top-navigation" )?
- }
- | list
- { ( w:string "allow-same-origin" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-top-navigation" )?
- }
- | list
- { ( w:string "allow-forms" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-top-navigation" )?
- }
- | list
- { ( w:string "allow-forms" )?
- , ( w:string "allow-scripts" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-top-navigation" )?
- }
- | list
- { ( w:string "allow-scripts" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-top-navigation" )?
- }
- | list
- { ( w:string "allow-scripts" )?
- , ( w:string "allow-forms" )?
- , ( w:string "allow-same-origin" )?
- , ( w:string "allow-top-navigation" )?
- }
- } & v5only
- iframe.attrs.allowfullscreen =
- attribute allowfullscreen {
- w:string "allowfullscreen" | w:string ""
- } & v5only
- iframe.inner =
- ( text )
-
- common.elem.phrasing |= iframe.elem
-
-#######################################################################
-## Image Maps
-
-## Map Definition: <map>
-
- map.elem.flow =
- element map { map.inner.flow & map.attrs }
- map.elem.phrasing =
- element map { map.inner.phrasing & map.attrs }
- map.attrs =
- ( common.attrs
- & map.attrs.name
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- ) # REVISIT make id required in Schematron
- map.attrs.name =
- attribute name {
- common.data.name
- }
- map.inner.flow =
- ( common.inner.transparent.flow )
- map.inner.phrasing =
- ( common.inner.phrasing )
-
- common.elem.flow |= map.elem.flow
- common.elem.phrasing |= map.elem.phrasing
-
-## Map Area Definition: <area>
-
- area.elem =
- element area { area.inner & area.attrs }
- area.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & ( area.attrs.alt
- & shared-hyperlink.attrs.href
- )?
- & shared-hyperlink.attrs.target?
- & shared-hyperlink.attrs.ping?
- & shared-hyperlink.attrs.rel?
- & shared-hyperlink.attrs.media?
- & shared-hyperlink.attrs.hreflang?
- & shared-hyperlink.attrs.type?
- & area.attrs.shape?
- & ( common.attrs.aria.role.link
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- area.attrs.alt =
- attribute alt {
- text
- }
- area.attrs.shape =
- ( ( area.attrs.shape.rect? & area.attrs.coords.rect )
- | ( area.attrs.shape.circle & area.attrs.coords.circle )
- | ( area.attrs.shape.poly & area.attrs.coords.poly )
- | ( area.attrs.shape.default )
- )
- area.attrs.shape.rect =
- attribute shape {
- w:string "rect"
- }
- area.attrs.coords.rect =
- attribute coords {
- w:rectangle
-# xsd:token {
-# pattern = "-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+"
-# }
- }
- area.attrs.shape.circle =
- attribute shape {
- w:string "circle"
- }
- area.attrs.coords.circle =
- attribute coords {
- w:circle
-# xsd:token {
-# pattern = "-?[0-9]+,-?[0-9]+,[0-9]+"
-# }
- }
- area.attrs.shape.poly =
- attribute shape {
- w:string "poly"
- }
- area.attrs.coords.poly =
- attribute coords {
- w:polyline
-# xsd:token {
-# pattern = "-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+(,-?[0-9]+,-?[0-9]+)*"
-# }
- }
- area.attrs.shape.default =
- attribute shape {
- w:string "default"
- }
- area.inner =
- ( empty )
-
- common.elem.phrasing |= area.elem
diff --git a/xml/relaxng/src/resources/html5-schema/html5-all.rnc b/xml/relaxng/src/resources/html5-schema/html5-all.rnc
new file mode 100644
index 0000000..64e1831
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5-all.rnc
@@ -0,0 +1,3 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "html5-svg-mathml.rnc"
+include "html5/html5full-rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5-its.rnc b/xml/relaxng/src/resources/html5-schema/html5-its.rnc
new file mode 100644
index 0000000..8a8a86d
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5-its.rnc
@@ -0,0 +1,28 @@
+# Copyright (c) 2012 Jirka Kosek <jirka@kosek.cz>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+namespace local = ""
+
+include "html5-svg-mathml.rnc"
+include "html5/html5full.rnc"
+include "its20-html5.rnc"
+
+common.attrs &= its-html-attributes
diff --git a/xml/relaxng/src/resources/html5-schema/html5-no-microdata.rnc b/xml/relaxng/src/resources/html5-schema/html5-no-microdata.rnc
new file mode 100644
index 0000000..d59eab9
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5-no-microdata.rnc
@@ -0,0 +1,2 @@
+include "html5-svg-mathml.rnc"
+include "html5/html5full-no-microdata.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5-rdfalite-w3c.rnc b/xml/relaxng/src/resources/html5-schema/html5-rdfalite-w3c.rnc
new file mode 100644
index 0000000..6cbfa55
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5-rdfalite-w3c.rnc
@@ -0,0 +1,2 @@
+include "html5-svg-mathml.rnc"
+include "html5/html5full-rdfalite.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5-rdfalite.rnc b/xml/relaxng/src/resources/html5-schema/html5-rdfalite.rnc
new file mode 100644
index 0000000..6cbfa55
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5-rdfalite.rnc
@@ -0,0 +1,2 @@
+include "html5-svg-mathml.rnc"
+include "html5/html5full-rdfalite.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc b/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc
new file mode 100644
index 0000000..fadc971
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5-svg-mathml.rnc
@@ -0,0 +1,29 @@
+namespace svg = "http://www.w3.org/2000/svg"
+namespace math = "http://www.w3.org/1998/Math/MathML"
+
+include "svg11/svg11-tiny-inc.rnc"
+include "mml3/mathml3-inc.rnc"
+
+common.elem.phrasing |= svg
+
+common.elem.phrasing |= math
+
+SVG.foreignObject.content |=
+ ( math
+ | html.elem
+ | body.elem
+ | common.inner.flow
+ )
+
+annotation-xml.model.svg |= svg
+
+annotation-xml.model.xhtml |=
+ ( html.elem
+ | common.elem.flow
+ )
+
+# in our integration, <mtext> is the only MathML "token element" that can
+# contain HTML element content; the <mi>, <mn>, <mo> and <ms> elements
+# cannot; see http://www.w3.org/Bugs/Public/show_bug.cgi?id=9859#c8 for a
+# rationale
+mtext.content |= common.elem.phrasing
diff --git a/xml/relaxng/src/resources/html5-schema/html5.rnc b/xml/relaxng/src/resources/html5-schema/html5.rnc
index 4d0a71a..64e1831 100644
--- a/xml/relaxng/src/resources/html5-schema/html5.rnc
+++ b/xml/relaxng/src/resources/html5-schema/html5.rnc
@@ -1,60 +1,3 @@
default namespace = "http://www.w3.org/1999/xhtml"
-# #####################################################################
-## RELAX NG Schema for HTML 5 #
-# #####################################################################
-
- # To validate an HTML 5 document, you must first validate against #
- # this schema and then ALSO validate against assertions.sch #
-
- ## HTML flavor RELAX NG schemas can only be used after the #
- ## document has been transformed to well-formed XML. #
- ## - Insert closing slashes in all empty element tags #
- ## - Insert all optional start and end tags #
- ## - Add xmlns "http://www.w3.org/1999/xhtml" #
- ## - Properly escape <script> and <style> CDATA #
- ## - Parse and transform all HTML-only entities to numeric #
- ## character references #
- ## Obviously, syntax-checking involving these features cannot be #
- ## done by the RELAX NG schema and must be checked, along with the #
- ## <!DOCTYPE> requirement, by some other application. #
-
-# #####################################################################
-## Schema Framework & Parameters
-
-include "common.rnc" {
- # XHTML flavor #
- XMLonly = notAllowed
- HTMLonly = empty
- # HTML 4 compat #
- v5only = empty
- # HTML-serializability #
- nonHTMLizable = notAllowed
- # HTML-roundtrippability #
- nonRoundtrippable = notAllowed
-}
-
-include "common-ext.rnc"
-
-# #####################################################################
-## Language Definitions
-
-start = html.elem
-
-include "meta.rnc"
-include "meta-ext.rnc"
-include "phrase.rnc"
-include "block.rnc"
-include "sectional.rnc"
-include "structural.rnc"
-include "revision.rnc"
-include "embed.rnc"
-include "ruby.rnc"
-include "media.rnc"
-include "core-scripting.rnc"
-include "core-scripting-ext.rnc"
-include "tables.rnc"
-include "form-datatypes.rnc"
-include "web-forms.rnc"
-include "web-forms2.rnc"
-include "applications.rnc"
-include "data.rnc"
+include "html5-svg-mathml.rnc"
+include "html5/html5full-rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/applications.rnc b/xml/relaxng/src/resources/html5-schema/html5/applications.rnc
new file mode 100755
index 0000000..ac07294
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/applications.rnc
@@ -0,0 +1,431 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Web Application Features #
+# #####################################################################
+
+## Additions to Common Attributes
+
+ common.attrs.interact &=
+ ( common.attrs.contextmenu?
+ & common.attrs.contenteditable?
+ & common.attrs.draggable?
+ & common.attrs.dropzone?
+ & common.attrs.hidden?
+ & common.attrs.spellcheck?
+ )
+
+ common.attrs.other &= common.attrs.interact
+
+## Context Menu: contextmenu
+
+ common.attrs.contextmenu =
+ attribute contextmenu {
+ common.data.idref
+ }
+
+## Editable Content: contenteditable
+
+ common.attrs.contenteditable =
+ attribute contenteditable {
+ w:string "true" | w:string "false" | w:string ""
+ }
+
+## Draggable Element: draggable
+
+ common.attrs.draggable =
+ attribute draggable {
+ w:string "true" | w:string "false"
+ }
+
+## Dropzone: dropzone
+
+ common.attrs.dropzone =
+ attribute dropzone {
+ list {
+ ( xsd:string { pattern = "[sS][tT][rR][iI][nN][gG]:.+" }
+ | xsd:string { pattern = "[fF][iI][lL][eE]:.+" }
+ )*
+ ,
+ ( w:string "copy"
+ | w:string "move"
+ | w:string "link"
+ )?
+ ,
+ ( xsd:string { pattern = "[sS][tT][rR][iI][nN][gG]:.+" }
+ | xsd:string { pattern = "[fF][iI][lL][eE]:.+" }
+ )*
+ }
+ }
+
+## Hidden Element: hidden
+
+ common.attrs.hidden =
+ attribute hidden {
+ w:string "hidden" | w:string ""
+ }
+
+## Spellchecking and grammar checking: spellcheck
+
+ common.attrs.spellcheck =
+ attribute spellcheck{
+ w:string "true" | w:string "false" | w:string ""
+ }
+
+## Application Cache: manifest
+
+ html.attrs.manifest =
+ attribute manifest {
+ common.data.uri.non-empty
+ }
+
+ html.attrs &= html.attrs.manifest?
+
+## Progess Indicator: <progress>
+
+ progress.elem =
+ element progress { progress.inner & progress.attrs }
+ progress.attrs =
+ ( common.attrs
+ & progress.attrs.value?
+ & progress.attrs.max?
+ & ( common.attrs.aria.implicit.progressbar
+ | common.attrs.aria.role.progressbar
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ progress.attrs.value =
+ attribute value {
+ common.data.float.non-negative
+ }
+ progress.attrs.max =
+ attribute max {
+ common.data.float.positive
+ }
+ progress.inner =
+ ( common.inner.phrasing ) #Cannot enforce textContent format here
+
+ common.elem.phrasing |= progress.elem
+
+## Dialog box, inspector, or window: <dialog>
+ dialog.elem =
+ element dialog { dialog.inner & dialog.attrs }
+ dialog.attrs =
+ ( common.attrs
+ & dialog.attrs.open?
+ & ( common.attrs.aria.implicit.dialog
+ | common.attrs.aria.role.alert
+ | common.attrs.aria.role.alertdialog
+ | common.attrs.aria.role.contentinfo
+ | common.attrs.aria.role.dialog
+ | common.attrs.aria.role.log
+ | common.attrs.aria.role.marquee
+ | common.attrs.aria.role.region
+ | common.attrs.aria.role.status
+ | common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.landmark.main
+ | common.attrs.aria.landmark.search
+ )?
+ )
+ dialog.attrs.open =
+ attribute open {
+ w:string "open" | w:string ""
+ }
+ dialog.inner =
+ ( common.inner.flow )
+ common.elem.flow |= dialog.elem
+
+## Toolbar: <menu type=toolbar>
+
+ menu.toolbar.elem =
+ element menu { menu.toolbar.inner & menu.toolbar.attrs }
+ menu.toolbar.attrs =
+ ( common.attrs
+ & menu.toolbar.attrs.type?
+ & ( common.attrs.aria.implicit.toolbar
+ | common.attrs.aria.role.directory
+ | common.attrs.aria.role.list
+ | common.attrs.aria.role.listbox
+ | common.attrs.aria.role.menu
+ | common.attrs.aria.role.menubar
+ | common.attrs.aria.role.tablist
+ | common.attrs.aria.role.toolbar
+ | common.attrs.aria.role.tree
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ menu.toolbar.attrs.type =
+ attribute type {
+ w:string "toolbar"
+ }
+ menu.toolbar.inner =
+ ( mli.elem*
+ | common.inner.flow
+ )
+ menu.elem |= menu.toolbar.elem
+
+## Toolbar item: <li>
+
+ mli.elem =
+ element li { mli.inner & mli.attrs }
+ mli.attrs =
+ ( common.attrs
+ & ( ( common.attrs.aria.role.listitem
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.option
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.treeitem
+ | common.attrs.aria.role.presentation
+ )
+ )?
+ )
+ mli.inner =
+ ( common.inner.flow )
+
+## Popup menu: <menu type=popup>
+
+ menu.popup.elem =
+ element menu { menu.popup.inner & menu.popup.attrs }
+ menu.popup.attrs =
+ ( common.attrs
+ & menu.popup.attrs.type?
+ & menu.attrs.label?
+ & common.attrs.aria?
+ )
+ menu.popup.attrs.type =
+ attribute type {
+ w:string "popup"
+ }
+ menu.attrs.label =
+ attribute label {
+ string
+ }
+ menu.popup.inner =
+ ( menuitem.elem*
+ & hr.elem*
+ & menu.popup.elem*
+ & common.elem.script-supporting*
+ )
+ menu.elem |= menu.popup.elem
+
+## Ambiguous menu: <menu> (with no "type" attribute)
+ menu.ambiguous.elem =
+ element menu { menu.ambiguous.inner & menu.ambiguous.attrs }
+ menu.ambiguous.attrs =
+ ( common.attrs
+ & menu.attrs.label?
+ & common.attrs.aria?
+ )
+ menu.ambiguous.inner =
+ ( ( menuitem.elem*
+ & hr.elem*
+ & menu.ambiguous.elem*
+ & common.elem.script-supporting*
+ )
+ | ( mli.elem*
+ | common.inner.flow
+ )
+ )
+ menu.elem |= menu.ambiguous.elem
+
+ common.elem.flow |= menu.elem
+ # REVISIT allow nested menus
+
+## Explicit command in popup menu: <menuitem type=command>
+ menuitem.explicit.command.elem =
+ element menuitem { menuitem.inner & menuitem.explicit.command.attrs }
+ menuitem.explicit.command.attrs =
+ ( common.attrs
+ & menuitem.explicit.command.attrs.type?
+ & menuitem.attrs.label?
+ & menuitem.attrs.icon?
+ & menuitem.attrs.disabled?
+ & menuitem.attrs.default?
+ & common.attrs.aria?
+ )
+ menuitem.explicit.command.attrs.type =
+ attribute type {
+ w:string "command"
+ }
+ menuitem.attrs.label =
+ attribute label {
+ w:non-empty-string
+ }
+ menuitem.attrs.icon =
+ attribute icon {
+ common.data.uri.non-empty
+ }
+ menuitem.attrs.disabled =
+ attribute disabled {
+ w:string "" | w:string "disabled"
+ }
+ menuitem.attrs.default =
+ attribute default {
+ w:string "" | w:string "default"
+ }
+ menuitem.elem |= menuitem.explicit.command.elem
+
+## Checkbox in popup menu: <menuitem type=checkbox>
+ menuitem.checkbox.elem =
+ element menuitem { menuitem.inner & menuitem.checkbox.attrs }
+ menuitem.checkbox.attrs =
+ ( common.attrs
+ & menuitem.checkbox.attrs.type
+ & menuitem.attrs.label?
+ & menuitem.attrs.icon?
+ & menuitem.attrs.disabled?
+ & menuitem.attrs.checked?
+ & menuitem.attrs.radiogroup?
+ & menuitem.attrs.default?
+ & common.attrs.aria?
+ )
+ menuitem.checkbox.attrs.type =
+ attribute type {
+ w:string "checkbox"
+ }
+ menuitem.attrs.checked =
+ attribute checked {
+ w:string "checked" | w:string ""
+ }
+ menuitem.attrs.radiogroup =
+ attribute radiogroup {
+ string
+ }
+ menuitem.elem |= menuitem.checkbox.elem
+
+## Radio button in popup menu: <menuitem type=radio>
+ menuitem.radio.elem =
+ element menuitem { menuitem.inner & menuitem.radio.attrs }
+ menuitem.radio.attrs =
+ ( common.attrs
+ & menuitem.radio.attrs.type
+ & menuitem.attrs.label?
+ & menuitem.attrs.icon?
+ & menuitem.attrs.disabled?
+ & menuitem.attrs.checked?
+ & menuitem.attrs.radiogroup?
+ & menuitem.attrs.default?
+ & common.attrs.aria?
+ )
+ menuitem.radio.attrs.type =
+ attribute type {
+ w:string "radio"
+ }
+ menuitem.elem |= menuitem.radio.elem
+
+## Indirect command in popup menu: <menuitem command>
+ menuitem.indirect.command.elem =
+ element menuitem { menuitem.inner & menuitem.indirect.command.attrs }
+ menuitem.indirect.command.attrs =
+ ( common.attrs
+ & menuitem.attrs.default?
+ & menuitem.attrs.command
+ & common.attrs.aria?
+ )
+ menuitem.attrs.command =
+ attribute command {
+ common.data.idref
+ }
+ menuitem.elem |= menuitem.indirect.command.elem
+
+ menuitem.inner =
+ ( empty )
+
+## Canvas for Dynamic Graphics: <canvas>
+
+ canvas.elem.flow =
+ element canvas { canvas.inner.flow & canvas.attrs }
+ canvas.elem.phrasing =
+ element canvas { canvas.inner.phrasing & canvas.attrs }
+ canvas.attrs =
+ ( common.attrs
+ & canvas.attrs.height?
+ & canvas.attrs.width?
+ & common.attrs.aria?
+ )
+ canvas.attrs.height =
+ attribute height {
+ common.data.integer.non-negative
+ }
+ canvas.attrs.width =
+ attribute width {
+ common.data.integer.non-negative
+ }
+ canvas.inner.flow =
+ ( common.inner.transparent.flow )
+ canvas.inner.phrasing =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= canvas.elem.flow
+ common.elem.phrasing |= canvas.elem.phrasing
+
+## Additional On-Demand Information: <details>
+
+ details.elem =
+ element details { details.inner & details.attrs }
+ details.attrs =
+ ( common.attrs
+ & details.attrs.open?
+ & ( common.attrs.aria.implicit.group # aria-expanded must be true if open attr present; check by assertions
+ | common.attrs.aria.role.alertdialog
+ | common.attrs.aria.role.banner
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.combobox
+ | common.attrs.aria.role.dialog
+ | common.attrs.aria.role.directory
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.img
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.list
+ | common.attrs.aria.role.listbox
+ | common.attrs.aria.role.listitem
+ | common.attrs.aria.role.log
+ | common.attrs.aria.role.marquee
+ | common.attrs.aria.role.menu
+ | common.attrs.aria.role.menubar
+ | common.attrs.aria.role.note
+ | common.attrs.aria.role.status
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.tablist
+ | common.attrs.aria.role.tabpanel
+ | common.attrs.aria.role.toolbar
+ | common.attrs.aria.role.tree
+ | common.attrs.aria.role.treeitem
+ | common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.article
+ | common.attrs.aria.landmark.complementary
+ | common.attrs.aria.landmark.contentinfo
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.landmark.form
+ | common.attrs.aria.landmark.main
+ | common.attrs.aria.landmark.navigation
+ | common.attrs.aria.landmark.search
+ )?
+ )
+ details.attrs.open =
+ attribute open {
+ w:string "open" | w:string ""
+ }
+ details.inner =
+ ( summary.elem
+ , common.inner.flow
+ )
+
+ common.elem.flow |= details.elem
+
+## Caption/summary for details element: <summary>
+
+ summary.elem =
+ element summary { summary.inner & summary.attrs }
+ summary.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ summary.inner =
+ ( common.inner.phrasing )
diff --git a/xml/relaxng/src/resources/html5-schema/html5/aria.rnc b/xml/relaxng/src/resources/html5-schema/html5/aria.rnc
new file mode 100755
index 0000000..b1035a0
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/aria.rnc
@@ -0,0 +1,1246 @@
+# #####################################################################
+## RELAX NG Schema for HTML 5: Accessible Rich Internet Applications #
+# #####################################################################
+#
+# history: http://hsivonen.iki.fi/aria-html5-bis/
+
+# #####################################################################
+## ARIA
+
+## Global states and properties
+
+aria.global =
+ ( aria.prop.atomic?
+ & aria.state.busy?
+ & aria.prop.controls?
+ & aria.prop.describedby?
+ & aria.state.disabled?
+ & aria.state.dropeffect?
+ & aria.prop.flowto?
+ & aria.state.grabbed?
+ & aria.prop.haspopup?
+ & aria.state.hidden?
+ & aria.state.invalid?
+ & aria.prop.label?
+ & aria.prop.labelledby?
+ & aria.prop.live?
+ & aria.prop.owns?
+ & aria.prop.relevant?
+ )
+
+common.attrs.other &= aria.global?
+
+## States and Properties for Native Roles
+
+common.attrs.aria.implicit.button |=
+ ( aria.state.expanded?
+ & aria.state.pressed?
+ )
+
+common.attrs.aria.implicit.checkbox |=
+ ( aria.state.checked? )
+
+common.attrs.aria.implicit.combobox |=
+ ( aria.state.expanded?
+ & aria.prop.autocomplete?
+ & aria.prop.required?
+ & aria.prop.activedescendant?
+ )
+
+common.attrs.aria.implicit.dialog |=
+ ( aria.state.expanded? )
+
+common.attrs.aria.implicit.document |=
+ ( aria.state.expanded? )
+
+common.attrs.aria.implicit.group |=
+ ( aria.state.expanded?
+ & aria.prop.activedescendant?
+ )
+
+common.attrs.aria.implicit.heading |=
+ ( aria.state.expanded?
+ & aria.prop.level?
+ )
+
+common.attrs.aria.implicit.img |=
+ ( aria.state.expanded? )
+
+common.attrs.aria.implicit.link |=
+ ( aria.state.expanded? )
+
+common.attrs.aria.implicit.listbox |=
+ ( aria.prop.multiselectable?
+ & aria.prop.required?
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+
+common.attrs.aria.implicit.listitem |=
+ ( aria.prop.level?
+ & aria.prop.posinset?
+ & aria.prop.setsize?
+ & aria.state.expanded?
+ )
+
+common.attrs.aria.implicit.option |=
+ ( aria.prop.posinset?
+ & aria.prop.setsize?
+ & aria.state.checked?
+ & aria.state.selected?
+ )
+
+common.attrs.aria.implicit.progressbar |=
+ ( aria.prop.valuemax?
+ & aria.prop.valuemin?
+ & aria.prop.valuenow?
+ & aria.prop.valuetext?
+ )
+
+common.attrs.aria.implicit.radio |=
+ ( aria.prop.posinset?
+ & aria.prop.setsize?
+ & aria.state.checked?
+ & aria.state.selected?
+ )
+
+common.attrs.aria.implicit.slider |=
+ ( aria.prop.valuemax?
+ & aria.prop.valuemin?
+ & aria.prop.valuenow?
+ & aria.prop.valuetext?
+ & aria.prop.orientation?
+ )
+
+common.attrs.aria.implicit.spinbutton |=
+ ( aria.prop.valuemax?
+ & aria.prop.valuemin?
+ & aria.prop.valuenow?
+ & aria.prop.valuetext?
+ & aria.prop.required?
+ )
+
+common.attrs.aria.implicit.textbox |=
+ ( aria.prop.activedescendant?
+ & aria.prop.autocomplete?
+ & aria.prop.multiline?
+ & aria.prop.readonly?
+ & aria.prop.required?
+ )
+
+common.attrs.aria.implicit.toolbar |=
+ ( aria.state.expanded?
+ & aria.prop.activedescendant?
+ )
+
+common.attrs.aria.implicit.columnheader |=
+ ( aria.prop.sort?
+ & aria.prop.readonly?
+ & aria.prop.required?
+ & aria.state.selected?
+ & aria.state.expanded?
+ )
+
+common.attrs.aria.implicit.rowheader |=
+ ( aria.prop.sort?
+ & aria.prop.readonly?
+ & aria.prop.required?
+ & aria.state.selected?
+ & aria.state.expanded?
+ )
+
+#common.attrs.aria.implicit.select |=
+# ( aria.state.invalid?
+# & aria.prop.required?
+# & aria.prop.atomic?
+# & aria.state.busy?
+# & aria.prop.channel?
+# & aria.prop.controls?
+# & aria.prop.live?
+# & aria.prop.relevant?
+# )
+
+# section
+# |
+# |_ region
+# |
+# |_ article
+# |
+# |_ landmark
+# | |_ banner
+# | |_ complementary
+# | |_ contentinfo
+# | |_ main
+# | |_ navigation
+# |
+# |_ list
+# |
+# |_ status
+
+common.attrs.aria.implicit.section |=
+ ( aria.state.expanded? )
+
+common.attrs.aria.implicit.region |= common.attrs.aria.implicit.section
+
+common.attrs.aria.implicit.article |= common.attrs.aria.implicit.region
+common.attrs.aria.implicit.landmark |= common.attrs.aria.implicit.region
+common.attrs.aria.implicit.list |= common.attrs.aria.implicit.region
+common.attrs.aria.implicit.status |= common.attrs.aria.implicit.region
+
+common.attrs.aria.implicit.banner |= common.attrs.aria.implicit.landmark
+common.attrs.aria.implicit.complementary |= common.attrs.aria.implicit.landmark
+common.attrs.aria.implicit.contentinfo |= common.attrs.aria.implicit.landmark
+common.attrs.aria.implicit.main |= common.attrs.aria.implicit.landmark
+common.attrs.aria.implicit.navigation |= common.attrs.aria.implicit.landmark
+
+# #####################################################################
+## States
+
+## busy
+ aria.state.busy =
+ attribute aria-busy
+ { string "true"
+ | string "false" #default
+ }
+
+## checked
+ aria.state.checked =
+ attribute aria-checked
+ { string "true"
+ | string "false"
+ | string "mixed"
+ | string "undefined" #default
+ }
+
+## disabled
+ aria.state.disabled =
+ attribute aria-disabled
+ { string "true"
+ | string "false" #default
+ }
+
+## dropeffect
+ aria.state.dropeffect =
+ attribute aria-dropeffect
+ { token "none" #default
+ | token "popup"
+ | token "execute"
+ | list
+ { ( string "copy" )
+ , ( string "execute" )?
+ }
+ | list
+ { ( string "move" )
+ , ( string "execute" )?
+ }
+ | list
+ { ( string "link" )
+ , ( string "execute" )?
+ }
+ | list
+ { ( string "execute" )
+ , ( string "copy" )
+ }
+ | list
+ { ( string "execute" )
+ , ( string "move" )
+ }
+ | list
+ { ( string "execute" )
+ , ( string "link" )
+ }
+ }
+
+## expanded
+ aria.state.expanded =
+ attribute aria-expanded
+ { string "true"
+ | string "false"
+ | string "undefined" #default
+ }
+
+## grabbed
+ aria.state.grabbed =
+ attribute aria-grabbed
+ { string "true"
+ | string "false"
+ | string "undefined" #default
+ }
+
+## hidden
+ aria.state.hidden =
+ attribute aria-hidden
+ { string "true"
+ | string "false" #default
+ }
+
+## invalid
+ aria.state.invalid =
+ attribute aria-invalid
+ { string "true"
+ | string "false" #default
+ | string "grammar"
+ | string "spelling"
+ }
+
+## pressed
+ aria.state.pressed =
+ attribute aria-pressed
+ { string "true"
+ | string "false"
+ | string "mixed"
+ | string "undefined" #default
+ }
+
+## selected
+ aria.state.selected =
+ attribute aria-selected
+ { string "true"
+ | string "false"
+ | string "undefined" #default
+ }
+
+
+
+# #####################################################################
+## Properties
+
+## activedescendant
+ aria.prop.activedescendant =
+ attribute aria-activedescendant {
+ common.data.idref #REVISIT add Schematron check
+ }
+
+## atomic
+ aria.prop.atomic =
+ attribute aria-atomic
+ { string "true"
+ | string "false" #default
+ }
+
+## autocomplete
+ aria.prop.autocomplete =
+ attribute aria-autocomplete
+ { string "inline"
+ | string "list"
+ | string "both"
+ | string "none" #default
+ }
+
+## controls
+ aria.prop.controls =
+ attribute aria-controls {
+ common.data.idrefs #REVISIT add Schematron check
+ }
+
+## describedby
+ aria.prop.describedby =
+ attribute aria-describedby {
+ common.data.idrefs #REVISIT add Schematron check
+ }
+
+## flowto
+ aria.prop.flowto =
+ attribute aria-flowto {
+ common.data.idrefs #REVISIT add Schematron check
+ }
+
+## haspopup
+ aria.prop.haspopup =
+ attribute aria-haspopup
+ { string "true" #REVISIT check owns or descendant
+ | string "false" #default
+ }
+
+## label
+ aria.prop.label =
+ attribute aria-label {
+ string
+ }
+
+## labelledby
+ aria.prop.labelledby =
+ attribute aria-labelledby {
+ common.data.idrefs #REVISIT add Schematron check
+ }
+
+## level
+ aria.prop.level =
+ attribute aria-level {
+ common.data.integer.positive
+ }
+
+## live
+ aria.prop.live =
+ attribute aria-live
+ { string "off" #default
+ | string "polite"
+ | string "assertive"
+ }
+
+## multiline
+ aria.prop.multiline =
+ attribute aria-multiline
+ { string "true"
+ | string "false" #default
+ }
+
+## multiselectable
+ aria.prop.multiselectable =
+ attribute aria-multiselectable
+ { string "true"
+ | string "false" #default
+ }
+
+## orientation
+ aria.prop.orientation =
+ attribute aria-orientation
+ { string "vertical"
+ | string "horizontal" #default
+ }
+
+## owns
+ aria.prop.owns =
+ attribute aria-owns {
+ common.data.idrefs #REVISIT add Schematron check
+ }
+
+## posinset
+ aria.prop.posinset =
+ attribute aria-posinset {
+ common.data.integer.positive
+ }
+
+## readonly
+ aria.prop.readonly =
+ attribute aria-readonly
+ { string "true"
+ | string "false" #default
+ }
+ common.attrs.aria.prop.readonly |= aria.prop.readonly
+
+## relevant
+ aria.prop.relevant =
+ attribute aria-relevant
+ { token "all"
+ | list
+ { ( string "additions" )
+ , ( string "removals" )?
+ , ( string "text" )?
+ }
+ | list
+ { ( string "additions" )
+ , ( string "text" )?
+ , ( string "removals" )?
+ }
+ | list
+ { ( string "removals" )
+ , ( string "additions" )?
+ , ( string "text" )?
+ }
+ | list
+ { ( string "removals" )
+ , ( string "text" )?
+ , ( string "additions" )?
+ }
+ | list
+ { ( string "text" )
+ , ( string "additions" )?
+ , ( string "removals" )?
+ }
+ | list
+ { ( string "text" )
+ , ( string "removals" )?
+ , ( string "additions" )?
+ }
+ }
+
+## required
+ aria.prop.required =
+ attribute aria-required
+ { string "true"
+ | string "false" #default
+ }
+
+## setsize
+ aria.prop.setsize =
+ attribute aria-setsize {
+ common.data.integer.non-negative
+ }
+
+## sort
+ aria.prop.sort =
+ attribute aria-sort
+ { string "ascending"
+ | string "descending"
+ | string "none" #default
+ | string "other"
+ }
+
+## valuemax
+ aria.prop.valuemax =
+ attribute aria-valuemax {
+ common.data.float #REVISIT
+ }
+
+## valuemin
+ aria.prop.valuemin =
+ attribute aria-valuemin {
+ common.data.float #REVISIT
+ }
+
+## valuenow
+ aria.prop.valuenow =
+ attribute aria-valuenow {
+ common.data.float #REVISIT
+ }
+
+## valuetext
+ aria.prop.valuetext =
+ attribute aria-valuetext {
+ string
+ }
+
+# #####################################################################
+## Roles
+
+## alert
+ aria.alert =
+ ( aria.role.alert
+ & aria.state.expanded?
+ )
+ aria.role.alert =
+ attribute role { string "alert" }
+
+ common.attrs.aria |= aria.alert
+ common.attrs.aria.role.alert |= aria.alert
+
+## alertdialog
+ aria.alertdialog =
+ ( aria.role.alertdialog
+ & aria.state.expanded?
+ )
+ aria.role.alertdialog =
+ attribute role { string "alertdialog" }
+
+ common.attrs.aria |= aria.alertdialog
+ common.attrs.aria.role.alertdialog |= aria.alertdialog
+
+## application
+ aria.application =
+ ( aria.role.application
+ & aria.state.expanded?
+ )
+ aria.role.application =
+ attribute role { string "application" }
+
+ common.attrs.aria |= aria.application
+ common.attrs.aria.landmark.application |= aria.application
+
+## article
+ aria.article =
+ ( aria.role.article
+ & aria.state.expanded?
+ )
+ aria.role.article =
+ attribute role { string "article" }
+
+ common.attrs.aria |= aria.article
+ common.attrs.aria.landmark.article |= aria.article
+
+## banner
+ aria.banner =
+ ( aria.role.banner
+ & aria.state.expanded?
+ )
+ aria.role.banner =
+ attribute role { string "banner" }
+
+ common.attrs.aria |= aria.banner
+ common.attrs.aria.landmark.banner |= aria.banner
+
+## button
+ aria.button =
+ ( aria.role.button
+ & aria.state.expanded?
+ & aria.state.pressed? # not inherited
+ )
+ aria.role.button =
+ attribute role { string "button" }
+
+ common.attrs.aria |= aria.button
+ common.attrs.aria.role.button |= aria.button
+
+## checkbox
+ aria.checkbox =
+ ( aria.role.checkbox
+ & aria.state.checked #required!
+ )
+ aria.role.checkbox =
+ attribute role { string "checkbox" }
+
+ common.attrs.aria |= aria.checkbox
+ common.attrs.aria.role.checkbox |= aria.checkbox
+
+# columnheader
+ aria.columnheader =
+ ( aria.role.columnheader
+ & aria.prop.sort? # not inherited
+ & aria.prop.readonly? # not inherited
+ & aria.state.selected? # not inherited
+ & aria.state.expanded?
+ & aria.prop.required?
+ )
+ aria.role.columnheader =
+ attribute role { string "columnheader" }
+
+ common.attrs.aria |= aria.columnheader
+
+## combobox
+ aria.combobox =
+ ( aria.role.combobox
+ & aria.prop.activedescendant?
+ & aria.state.expanded #required!
+ & aria.prop.autocomplete?
+ & aria.prop.required?
+ )
+ aria.role.combobox =
+ attribute role { string "combobox" }
+
+ common.attrs.aria |= aria.combobox
+ common.attrs.aria.role.combobox |= aria.combobox
+
+## complementary
+ aria.complementary =
+ ( aria.role.complementary
+ & aria.state.expanded?
+ )
+ aria.role.complementary =
+ attribute role { string "complementary" }
+
+ common.attrs.aria |= aria.complementary
+ common.attrs.aria.landmark.complementary |= aria.complementary
+
+## contentinfo
+ aria.contentinfo =
+ ( aria.role.contentinfo
+ & aria.state.expanded?
+ )
+ aria.role.contentinfo =
+ attribute role { string "contentinfo" }
+
+ common.attrs.aria |= aria.contentinfo
+ common.attrs.aria.landmark.contentinfo |= aria.contentinfo
+
+## definition
+ aria.definition =
+ ( aria.role.definition
+ & aria.state.expanded?
+ )
+ aria.role.definition =
+ attribute role { string "definition" }
+
+ common.attrs.aria |= aria.definition
+
+## dialog
+ aria.dialog =
+ ( aria.role.dialog
+ & aria.state.expanded?
+ )
+ aria.role.dialog =
+ attribute role { string "dialog" }
+
+ common.attrs.aria |= aria.dialog
+ common.attrs.aria.role.dialog |= aria.dialog
+
+## directory
+ aria.directory =
+ ( aria.role.directory
+ & aria.state.expanded?
+ )
+ aria.role.directory =
+ attribute role { string "directory" }
+
+ common.attrs.aria |= aria.directory
+ common.attrs.aria.role.directory |= aria.directory
+
+## document
+ aria.document =
+ ( aria.role.document
+ & aria.state.expanded?
+ )
+ aria.role.document =
+ attribute role { string "document" }
+
+ common.attrs.aria |= aria.document
+ common.attrs.aria.landmark.document |= aria.document
+
+## form
+ aria.form =
+ ( aria.role.form
+ & aria.state.expanded?
+ )
+ aria.role.form =
+ attribute role { string "form" }
+
+ common.attrs.aria |= aria.form
+ common.attrs.aria.landmark.form |= aria.form
+
+## grid
+ aria.grid =
+ ( aria.role.grid
+ & aria.prop.level? # not inherited
+ & aria.prop.multiselectable? # not inherited
+ & aria.prop.readonly? # not inherited
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.grid =
+ attribute role { string "grid" }
+
+ common.attrs.aria |= aria.grid
+
+## gridcell
+ aria.gridcell =
+ ( aria.role.gridcell
+ & aria.prop.level? # net inherited
+ & aria.prop.readonly? # not inherited
+ & aria.state.selected? # not inherited
+ & aria.state.expanded?
+ & aria.prop.required?
+ )
+ aria.role.gridcell =
+ attribute role { string "gridcell" }
+
+ common.attrs.aria |= aria.gridcell
+
+## group
+ aria.group =
+ ( aria.role.group
+ & aria.prop.activedescendant? # not inherited
+ & aria.state.expanded? # not inherited
+ )
+ aria.role.group =
+ attribute role { string "group" }
+
+ common.attrs.aria |= aria.group
+ common.attrs.aria.role.group |= aria.group
+
+## heading
+ aria.heading =
+ ( aria.role.heading
+ & aria.prop.level ? # not inherited
+ & aria.state.expanded?
+ )
+ aria.role.heading =
+ attribute role { string "heading" }
+
+ common.attrs.aria |= aria.heading
+ common.attrs.aria.role.heading |= aria.heading
+
+## img
+ aria.img =
+ ( aria.role.img
+ & aria.state.expanded?
+ )
+ aria.role.img =
+ attribute role { string "img" }
+
+ common.attrs.aria |= aria.img
+ common.attrs.aria.role.img |= aria.img
+
+## link
+ aria.link =
+ ( aria.role.link
+ & aria.state.expanded?
+ )
+ aria.role.link =
+ attribute role { string "link" }
+
+ common.attrs.aria |= aria.link
+ common.attrs.aria.role.link |= aria.link
+
+## list
+ aria.list =
+ ( aria.role.list
+ & aria.state.expanded?
+ )
+ aria.role.list =
+ attribute role { string "list" }
+
+ common.attrs.aria |= aria.list
+ common.attrs.aria.role.list |= aria.list
+
+## listbox
+ aria.listbox =
+ ( aria.role.listbox
+ & aria.prop.multiselectable? # not inherited
+ & aria.prop.required?
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.listbox =
+ attribute role { string "listbox" }
+
+ common.attrs.aria |= aria.listbox
+ common.attrs.aria.role.listbox |= aria.listbox
+
+## listitem
+ aria.listitem =
+ ( aria.role.listitem
+ & aria.prop.posinset? # not inherited
+ & aria.prop.setsize? # not inherited
+ & aria.prop.level? # not inherited
+ & aria.state.expanded?
+ )
+ aria.role.listitem =
+ attribute role { string "listitem" }
+
+ common.attrs.aria |= aria.listitem
+ common.attrs.aria.role.listitem |= aria.listitem
+
+## log
+ aria.log =
+ ( aria.role.log
+ & aria.state.expanded?
+ )
+ aria.role.log =
+ attribute role { string "log" }
+
+ common.attrs.aria |= aria.log
+ common.attrs.aria.role.log |= aria.log
+
+## main
+ aria.main =
+ ( aria.role.main
+ & aria.state.expanded?
+ )
+ aria.role.main =
+ attribute role { string "main" }
+
+ common.attrs.aria |= aria.main
+ common.attrs.aria.landmark.main |= aria.main
+
+## marquee
+ aria.marquee =
+ ( aria.role.marquee
+ & aria.state.expanded?
+ )
+ aria.role.marquee =
+ attribute role { string "marquee" }
+
+ common.attrs.aria |= aria.marquee
+ common.attrs.aria.role.marquee |= aria.marquee
+
+## math
+ aria.math =
+ ( aria.role.math
+ & aria.state.expanded?
+ )
+ aria.role.math =
+ attribute role { string "math" }
+
+ common.attrs.aria |= aria.math
+
+## menu
+ aria.menu =
+ ( aria.role.menu
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.menu =
+ attribute role { string "menu" }
+
+ common.attrs.aria |= aria.menu
+ common.attrs.aria.role.menu |= aria.menu
+
+## menubar
+ aria.menubar =
+ ( aria.role.menubar
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.menubar =
+ attribute role { string "menubar" }
+
+ common.attrs.aria |= aria.menubar
+ common.attrs.aria.role.menubar |= aria.menubar
+
+
+## menuitem
+ aria.menuitem =
+ ( aria.role.menuitem )
+ aria.role.menuitem =
+ attribute role { string "menuitem" }
+
+ common.attrs.aria |= aria.menuitem
+ common.attrs.aria.role.menuitem |= aria.menuitem
+
+## menuitemcheckbox
+ aria.menuitemcheckbox =
+ ( aria.role.menuitemcheckbox
+ & aria.state.checked #required
+ )
+ aria.role.menuitemcheckbox =
+ attribute role { string "menuitemcheckbox" }
+
+ common.attrs.aria |= aria.menuitemcheckbox
+ common.attrs.aria.role.menuitemcheckbox |= aria.menuitemcheckbox
+
+## menuitemradio
+ aria.menuitemradio =
+ ( aria.role.menuitemradio
+ & aria.state.checked #required
+ & aria.state.selected?
+ & aria.prop.posinset?
+ & aria.prop.setsize?
+ )
+ aria.role.menuitemradio =
+ attribute role { string "menuitemradio" }
+
+ common.attrs.aria |= aria.menuitemradio
+ common.attrs.aria.role.menuitemradio |= aria.menuitemradio
+
+## navigation
+ aria.navigation =
+ ( aria.role.navigation
+ & aria.state.expanded?
+ )
+ aria.role.navigation =
+ attribute role { string "navigation" }
+
+ common.attrs.aria |= aria.navigation
+ common.attrs.aria.landmark.navigation |= aria.navigation
+
+## note
+ aria.note =
+ ( aria.role.note
+ & aria.state.expanded?
+ )
+ aria.role.note =
+ attribute role { string "note" }
+
+ common.attrs.aria |= aria.note
+ common.attrs.aria.landmark.note |= aria.note
+
+## option
+ aria.option =
+ ( aria.role.option
+ & aria.state.checked? # not inherited
+ & aria.state.selected? # not inherited
+ & aria.prop.posinset?
+ & aria.prop.setsize?
+ )
+ aria.role.option =
+ attribute role { string "option" }
+
+ common.attrs.aria |= aria.option
+ common.attrs.aria.role.option |= aria.option
+
+
+## presentation
+ aria.presentation =
+ ( aria.role.presentation
+ & aria.state.expanded?
+ )
+ aria.role.presentation =
+ attribute role { string "presentation" }
+
+ common.attrs.aria |= aria.presentation
+ common.attrs.aria.role.presentation |= aria.presentation
+
+## progressbar
+ aria.progressbar =
+ ( aria.role.progressbar
+ & aria.prop.valuemax? # not inherited
+ & aria.prop.valuemin? # not inherited
+ & aria.prop.valuenow? # not inherited
+ & aria.prop.valuetext? # not inherited
+ )
+ aria.role.progressbar =
+ attribute role { string "progressbar" }
+
+ common.attrs.aria |= aria.progressbar
+ common.attrs.aria.role.progressbar |= aria.progressbar
+
+## radio
+ aria.radio =
+ ( aria.role.radio
+ & aria.state.checked #required!
+ & aria.state.selected?
+ & aria.prop.posinset?
+ & aria.prop.setsize?
+ )
+ aria.role.radio =
+ attribute role { string "radio" }
+
+ common.attrs.aria |= aria.radio
+ common.attrs.aria.role.radio |= aria.radio
+
+## radiogroup
+ aria.radiogroup =
+ ( aria.role.radiogroup
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ & aria.prop.required?
+ )
+ aria.role.radiogroup =
+ attribute role { string "radiogroup" }
+
+ common.attrs.aria |= aria.radiogroup
+
+## region
+ aria.region =
+ ( aria.role.region
+ & aria.state.expanded?
+ )
+ aria.role.region =
+ attribute role { string "region" }
+
+ common.attrs.aria |= aria.region
+ common.attrs.aria.role.region |= aria.region
+
+## row
+ aria.row =
+ ( aria.role.row
+ & aria.prop.level? # not inherited
+ & aria.state.selected? # not inherited
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.row =
+ attribute role { string "row" }
+
+ common.attrs.aria |= aria.row
+
+## rowgroup
+ aria.rowgroup =
+ ( aria.role.rowgroup
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.rowgroup =
+ attribute role { string "rowgroup" }
+
+ common.attrs.aria |= aria.rowgroup
+
+# rowheader
+ aria.rowheader =
+ ( aria.role.rowheader
+ & aria.prop.sort? # not inherited
+ & aria.prop.readonly? # not inherited
+ & aria.state.selected? # not inherited
+ & aria.state.expanded?
+ & aria.prop.required?
+ )
+ aria.role.rowheader =
+ attribute role { string "rowheader" }
+
+ common.attrs.aria |= aria.rowheader
+
+## scrollbar
+ aria.scrollbar =
+ ( aria.role.scrollbar
+ & aria.prop.orientation
+ & aria.prop.valuemax
+ & aria.prop.valuemin
+ & aria.prop.valuenow
+ & aria.prop.valuetext?
+ )
+ aria.role.scrollbar =
+ attribute role { string "scrollbar" }
+
+ common.attrs.aria |= aria.scrollbar
+
+## search
+ aria.search =
+ ( aria.role.search
+ & aria.state.expanded?
+ )
+ aria.role.search =
+ attribute role { string "search" }
+
+ common.attrs.aria |= aria.search
+ common.attrs.aria.landmark.search |= aria.search
+
+## separator
+ aria.separator =
+ ( aria.role.separator
+ & aria.state.expanded?
+ & aria.prop.orientation?
+ )
+ aria.role.separator =
+ attribute role { string "separator" }
+
+ common.attrs.aria |= aria.separator
+ common.attrs.aria.role.separator |= aria.separator
+
+## slider
+ aria.slider =
+ ( aria.role.slider
+ & aria.prop.valuemax
+ & aria.prop.valuemin
+ & aria.prop.valuenow
+ & aria.prop.valuetext?
+ & aria.prop.orientation?
+ )
+ aria.role.slider =
+ attribute role { string "slider" }
+
+ common.attrs.aria |= aria.slider
+ common.attrs.aria.role.slider |= aria.slider
+
+## spinbutton
+ aria.spinbutton =
+ ( aria.role.spinbutton
+ & aria.prop.valuemax
+ & aria.prop.valuemin
+ & aria.prop.valuenow
+ & aria.prop.valuetext?
+ & aria.prop.required?
+ )
+ aria.role.spinbutton =
+ attribute role { string "spinbutton" }
+
+ common.attrs.aria |= aria.spinbutton
+ common.attrs.aria.role.spinbutton |= aria.spinbutton
+
+## status
+ aria.status =
+ ( aria.role.status
+ & aria.state.expanded?
+ )
+ aria.role.status =
+ attribute role { string "status" }
+
+ common.attrs.aria |= aria.status
+ common.attrs.aria.role.status |= aria.status
+
+## tab
+ aria.tab =
+ ( aria.role.tab
+ & aria.state.selected?
+ & aria.state.expanded?
+ )
+ aria.role.tab =
+ attribute role { string "tab" }
+
+ common.attrs.aria |= aria.tab
+ common.attrs.aria.role.tab |= aria.tab
+
+## tablist
+ aria.tablist =
+ ( aria.role.tablist
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ & aria.prop.level?
+ & aria.prop.multiselectable?
+ )
+ aria.role.tablist =
+ attribute role { string "tablist" }
+ common.attrs.aria |= aria.tablist
+ common.attrs.aria.role.tablist |= aria.tablist
+
+## tabpanel
+ aria.tabpanel =
+ ( aria.role.tabpanel
+ & aria.state.expanded?
+ )
+ aria.role.tabpanel =
+ attribute role { string "tabpanel" }
+
+ common.attrs.aria |= aria.tabpanel
+ common.attrs.aria.role.tabpanel |= aria.tabpanel
+
+## textbox
+ aria.textbox =
+ ( aria.role.textbox
+ & aria.prop.activedescendant?
+ & aria.prop.autocomplete? # not inherited
+ & aria.prop.multiline? # not inherited
+ & aria.prop.readonly? # not inherited
+ & aria.prop.required?
+ )
+ aria.role.textbox =
+ attribute role { string "textbox" }
+
+ common.attrs.aria |= aria.textbox
+ common.attrs.aria.role.textbox |= aria.textbox
+
+## timer
+ aria.timer =
+ ( aria.role.timer
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.timer =
+ attribute role { string "timer" }
+
+ common.attrs.aria |= aria.timer
+
+## toolbar
+ aria.toolbar =
+ ( aria.role.toolbar
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ )
+ aria.role.toolbar =
+ attribute role { string "toolbar" }
+
+ common.attrs.aria |= aria.toolbar
+ common.attrs.aria.role.toolbar |= aria.toolbar
+
+## tooltip
+ aria.tooltip =
+ ( aria.role.tooltip
+ & aria.state.expanded?
+ )
+ aria.role.tooltip =
+ attribute role { string "tooltip" }
+
+ common.attrs.aria |= aria.tooltip
+
+## tree
+ aria.tree =
+ ( aria.role.tree
+ & aria.prop.multiselectable? # not inherited
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ & aria.prop.required?
+ )
+ aria.role.tree =
+ attribute role { string "tree" }
+
+ common.attrs.aria |= aria.tree
+ common.attrs.aria.role.tree |= aria.tree
+
+## treegrid
+ aria.treegrid =
+ ( aria.role.treegrid
+ & aria.prop.activedescendant?
+ & aria.state.expanded?
+ & aria.prop.level?
+ & aria.prop.multiselectable?
+ & aria.prop.readonly?
+ & aria.prop.required?
+ )
+ aria.role.treegrid =
+ attribute role { string "treegrid" }
+
+ common.attrs.aria |= aria.treegrid
+
+## treeitem
+ aria.treeitem =
+ ( aria.role.treeitem
+ & aria.state.checked?
+ & aria.state.expanded?
+ & aria.prop.level?
+ & aria.prop.posinset?
+ & aria.state.selected?
+ & aria.prop.setsize?
+ )
+ aria.role.treeitem =
+ attribute role { string "treeitem" }
+
+ common.attrs.aria |= aria.treeitem
+ common.attrs.aria.role.treeitem |= aria.treeitem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/block.rnc b/xml/relaxng/src/resources/html5-schema/html5/block.rnc
new file mode 100755
index 0000000..2fd2d23
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/block.rnc
@@ -0,0 +1,246 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Basic Prose Markup #
+# #####################################################################
+
+# #####################################################################
+## Paragraph-Level
+
+## Paragraph: <p>
+
+ p.elem =
+ element p { p.inner & p.attrs }
+ p.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ p.inner =
+ ( common.inner.phrasing ) # REVISIT lists in span?
+
+ common.elem.flow |= p.elem
+
+## Hint Transition: <hr>
+
+ hr.elem =
+ element hr { hr.inner & hr.attrs }
+ hr.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.separator
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ hr.inner =
+ ( empty )
+
+ common.elem.flow |= hr.elem
+
+# #####################################################################
+## Preformatting Blocks
+
+## Preformatted Text: <pre>
+
+ pre.elem =
+ element pre { pre.inner & pre.attrs }
+ pre.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ pre.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= pre.elem
+
+# #####################################################################
+## Simple Lists
+
+## Unordered List: <ul>
+
+ ul.elem =
+ element ul { ul.inner & ul.attrs }
+ ul.attrs =
+ ( common.attrs
+ & ( ( common.attrs.aria.role.directory
+ | common.attrs.aria.role.group
+ | common.attrs.aria.role.list
+ | common.attrs.aria.role.listbox
+ | common.attrs.aria.role.menu
+ | common.attrs.aria.role.menubar
+ | common.attrs.aria.role.tablist
+ | common.attrs.aria.role.toolbar
+ | common.attrs.aria.role.tree
+ | common.attrs.aria.role.presentation
+ )
+ | common.attrs.aria.implicit.list
+ )?
+ )
+ ul.inner =
+ ( li.elem*
+ & common.elem.script-supporting*
+ )
+
+ common.elem.flow |= ul.elem
+
+## Unordered List Item: <li>
+
+ li.elem =
+ element li { li.inner & li.attrs }
+ li.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.listitem
+ | common.attrs.aria.role.listitem
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.option
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.treeitem
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ li.inner =
+ ( common.inner.flow )
+
+## Ordered List: <ol>
+
+ ol.elem =
+ element ol { ol.inner & ol.attrs }
+ ol.attrs =
+ ( common.attrs
+ & ol.attrs.start?
+ & ol.attrs.reversed?
+ & ol.attrs.type?
+ & ( ( common.attrs.aria.role.directory
+ | common.attrs.aria.role.list
+ | common.attrs.aria.role.listbox
+ | common.attrs.aria.role.menu
+ | common.attrs.aria.role.menubar
+ | common.attrs.aria.role.tablist
+ | common.attrs.aria.role.toolbar
+ | common.attrs.aria.role.tree
+ | common.attrs.aria.role.presentation
+ )
+ | common.attrs.aria.implicit.list
+ )?
+ )
+ ol.attrs.start =
+ attribute start {
+ common.data.integer
+ }
+ ol.attrs.reversed =
+ attribute reversed {
+ w:string "reversed" | w:string ""
+ }
+ ol.attrs.type =
+ attribute type {
+ w:string "1" | w:string "a" | w:string "A" | w:string "i" | w:string "I"
+ }
+ ol.inner =
+ ( oli.elem*
+ & common.elem.script-supporting*
+ )
+
+ common.elem.flow |= ol.elem
+
+## Ordered List Item: <li>
+
+ oli.elem =
+ element li { oli.inner & oli.attrs }
+ oli.attrs =
+ ( common.attrs
+ & oli.attrs.value?
+ & ( common.attrs.aria.implicit.listitem
+ | common.attrs.aria.role.listitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.option
+ | common.attrs.aria.role.treeitem
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ oli.attrs.value =
+ attribute value {
+ common.data.integer
+ }
+ oli.inner =
+ ( common.inner.flow )
+
+# #####################################################################
+## Definition Lists
+
+## Definition List: <dl>
+
+ dl.elem =
+ element dl { dl.inner & dl.attrs }
+ dl.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ dl.inner =
+ ( ( ( dt.elem
+ & common.elem.script-supporting*
+ )+
+ ,
+ ( dd.elem
+ & common.elem.script-supporting*
+ )+
+ )*
+ )
+
+ common.elem.flow |= dl.elem
+
+## Definition Term: <dt>
+
+ dt.elem =
+ element dt { dt.inner & dt.attrs }
+ dt.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ dt.inner =
+ ( common.inner.flow )
+
+## Definition Description: <dd>
+
+ dd.elem =
+ element dd { dd.inner & dd.attrs }
+ dd.elem.phrasing =
+ element dd { dd.inner.phrasing & dd.attrs }
+ dd.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ dd.inner =
+ ( common.inner.flow )
+ dd.inner.phrasing =
+ ( common.inner.phrasing )
+
+# #####################################################################
+## Miscellaneous Elements
+
+## Generic Container: <div>
+
+ div.elem =
+ element div { div.inner & div.attrs }
+ div.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ div.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= div.elem
+
+## Title or Explanatory Caption: <legend>
+
+ legend.elem =
+ element legend { legend.inner & legend.attrs }
+ legend.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ legend.inner =
+ ( common.inner.phrasing )
diff --git a/xml/relaxng/src/resources/html5-schema/common-ext.rnc b/xml/relaxng/src/resources/html5-schema/html5/common-ext.rnc
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/common-ext.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/common-ext.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/common.rnc b/xml/relaxng/src/resources/html5-schema/html5/common.rnc
new file mode 100755
index 0000000..9f1e656
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/common.rnc
@@ -0,0 +1,510 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Common Definitions #
+# #####################################################################
+
+
+# #####################################################################
+## Language Parameters - redefine in inclusion block as necessary #
+# #####################################################################
+
+## HTML vs. XHTML restrictions
+
+ XMLonly = empty
+ HTMLonly = notAllowed
+
+## HTML 4 Compatibility - set to notAllowed to disallow markup introduced in HTML 5
+# (This only affects mixed-version modules; wholly HTML5
+# modules should simply be left out of the inclusion list.)
+
+ v5only = empty
+
+## HTML Compatibility Switches - set to notAllowed to disallow
+
+ ## XML features that can't be roundtripped HTML <-> XHTML
+ # (xml:base on elements other than <html>)
+ nonRoundtrippable = empty
+
+ ## XML features that can't be serialized as HTML
+ nonHTMLizable = empty
+
+## features that are not part of the W3C HTML spec
+ nonW3C = empty
+
+# #####################################################################
+## Wildcards #
+# #####################################################################
+
+## Any attribute from any namespace
+
+ common.attr.anything =
+ attribute * { text }*
+
+## Any element from any namespace
+
+ common.elem.anything =
+ element * { common.inner.anything & common.attr.anything }
+
+## Any content from any namespace
+
+ common.inner.anything =
+ ( text
+ & common.elem.anything*
+ )
+
+# #####################################################################
+## Common Element Classes #
+# #####################################################################
+
+## Metadata Elements
+
+ common.elem.metadata =
+ ( notAllowed )
+
+## Phrase Elements
+
+ common.elem.phrasing =
+ ( notAllowed )
+
+## Prose Elements
+
+ common.elem.flow =
+ ( common.elem.phrasing )
+
+
+# #####################################################################
+## Common Content Models #
+# #####################################################################
+
+## Metadata Content
+
+ common.inner.metadata =
+ ( common.elem.metadata* )
+
+## Phrase Content
+
+ common.inner.phrasing =
+ ( text & common.elem.phrasing* )
+
+## Prose Content
+
+ common.inner.transparent.flow =
+ ( text & common.elem.flow* )
+
+ common.inner.flow =
+ ( style.elem.scoped*,
+ ( text
+ & common.elem.flow*
+ )
+ )
+
+# #####################################################################
+## Common Attributes #
+# #####################################################################
+
+# When updating, check <bdo> definition too
+
+common.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ )
+
+common.attrs.basic =
+ ( ( common.attrs.id
+ | common.attrs.xml-id
+ )? # REVISIT assuming only either one is allowed
+ & common.attrs.class?
+ & common.attrs.title?
+ & common.attrs.base?
+ & common.attrs.space?
+ )
+ common.attrs.id =
+ attribute id {
+ common.data.id
+ }
+ common.attrs.xml-id =
+ attribute xml:id {
+ xsd:NCName
+ } & XMLonly
+ common.attrs.class =
+ attribute class {
+ common.data.tokens
+ }
+ common.attrs.title =
+ attribute title {
+ text
+ }
+ common.attrs.base =
+ common.attrs.xmlbase
+ & nonRoundtrippable
+ common.attrs.xmlbase =
+ attribute xml:base {
+ common.data.uri
+ } & XMLonly
+ common.attrs.space =
+ common.attrs.xmlspace
+ common.attrs.xmlspace =
+ attribute xml:space {
+ string "preserve" | string "default"
+ } & XMLonly
+
+common.attrs.i18n =
+ ( common.attrs.dir?
+ & common.attrs.language?
+ & common.attrs.translate?
+ )
+ common.attrs.dir =
+ attribute dir {
+ w:string "ltr" | w:string "rtl" | w:string "auto"
+ }
+ # This lang definition is a hack for enviroments where
+ # the HTML5 parser maps lang to xml:lang.
+ # Sameness check left to Schematron
+ common.attrs.language =
+ ( common.attrs.xmllang?
+ & common.attrs.lang?
+ )
+ common.attrs.lang =
+ attribute lang {
+ common.data.langcode
+ } & XMLonly
+ common.attrs.xmllang =
+ attribute xml:lang {
+ common.data.langcode
+ }
+# common.attrs.language =
+# ( common.attrs.lang
+# | common.attrs.xmllang
+# )
+# common.attrs.lang =
+# attribute lang {
+# common.data.langcode
+# } & HTMLonly
+# common.attrs.xmllang =
+# attribute xml:lang {
+# common.data.langcode
+# } & XMLonly
+ common.attrs.translate =
+ attribute translate {
+ w:string "" | w:string "yes" | w:string "no"
+ }
+
+common.attrs.present =
+ ( common.attrs.style?
+ & common.attrs.tabindex?
+ & common.attrs.accesskey?
+ )
+ common.attrs.style =
+ attribute style {
+ string
+ }
+ common.attrs.tabindex =
+ attribute tabindex {
+ common.data.integer
+ }
+ # REVISIT move style to a module and bundle tabindex with ARIA
+ common.attrs.accesskey =
+ attribute accesskey {
+ common.data.keylabellist
+ }
+
+common.attrs.other =
+ empty
+
+# #####################################################################
+## Common Datatypes #
+# #####################################################################
+
+## Names and Tokens
+
+ common.data.tokens =
+ list { token* }
+
+ common.data.browsing-context =
+ w:browsing-context
+
+ common.data.browsing-context-or-keyword =
+ w:browsing-context-or-keyword
+# xsd:string {
+# pattern = "()|([^_].*)|(_[bB][lL][aA][nN][kK])|(_[sS][eE][lL][fF])|(_[pP][aA][rR][eE][nN][tT])|(_[tT][oO][pP])"
+# }
+
+
+## IDs and IDREFs
+
+ common.data.id =
+ w:ID
+# xsd:string {
+# pattern = "\S+"
+# }
+
+ common.data.idref =
+ w:IDREF
+
+ common.data.idrefs =
+ w:IDREFS
+
+ common.data.name =
+ w:ID #FIXME
+
+ common.data.hash-name =
+ w:hash-name
+# xsd:string {
+# pattern = "#.+"
+# }
+
+## Numerical
+
+ common.data.integer =
+ w:integer
+# xsd:string {
+# pattern = "-?[0-9]+"
+# }
+
+ common.data.integer.positive =
+ w:integer-positive
+# xsd:string {
+# pattern = "0*[1-9][0-9]*"
+# }
+
+ common.data.integer.non-negative =
+ w:integer-non-negative
+# xsd:string {
+# pattern = "[0-9]+"
+# }
+
+# common.data.percent =
+# xsd:string {
+# pattern = "(100)|([1-9]?[0-9](\.[0-9]+)?)%"
+# }
+
+ common.data.float =
+ w:float
+# xsd:string {
+# pattern = "-?[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"
+# }
+
+ common.data.float.positive =
+ w:float-positive
+# xsd:string {
+# pattern = "(0*[1-9][0-9]*(\.[0-9]+)?)|([0-9]+(\.0*[1-9][0-9]*)?)([eE]-?[0-9]+)?"
+# }
+
+ common.data.float.non-negative =
+ w:float-non-negative
+# xsd:string {
+# pattern = "[0-9]+(\.[0-9]+)?([eE]-?[0-9]+)?"
+# }
+
+## Temporal
+
+ common.data.datetime =
+ w:datetime-tz
+
+ common.data.date-or-time =
+ w:date-or-time
+
+ common.data.date =
+ w:date
+
+ common.data.time-datetime =
+ w:time-datetime
+
+## IRIs
+
+ common.data.uri =
+ # allow either a non-empty IRI ref or zero or more HTML
+ # space characters (which are: space, tab, LF, FF, CR)
+ ( w:iri-ref
+ | xsd:string {
+ pattern = "[ \x{0A}-\x{0D}]*"
+ # NOTE The range above incorrectly allows U+000B
+ # in addition to the HTML space characters; but
+ # that's not a problem in practice because HTML
+ # and XML parsers will both catch any U+000B
+ # and report an error for it before that pattern
+ # ever gets evaluated.
+ }
+ )
+
+ common.data.uri.non-empty =
+ w:iri-ref
+
+ common.data.uris =
+ list { w:iri-ref* }
+
+ common.data.uri.absolute =
+ w:iri
+
+## <link type='icon'> sizes
+
+ common.data.sizes =
+# list { w:sizes }
+ list {
+ xsd:string {
+ pattern = "[1-9][0-9]*x[1-9][0-9]*"
+ }+
+ }
+
+## MIME types
+
+ common.data.mimetype =
+ w:mime-type
+
+## Encodings
+
+ common.data.charset =
+ w:charset
+
+ common.data.meta-charset =
+ w:meta-charset
+
+## Refresh
+
+ common.data.refresh =
+ w:refresh
+
+## Default style
+
+ common.data.default-style =
+ string
+# w:default-style
+
+## Media Queries
+
+ common.data.mediaquery =
+ w:media-query
+
+## Language Codes
+
+ common.data.langcode =
+ w:string "" | w:language
+
+## List of Key Labels
+ common.data.keylabellist =
+ w:keylabellist
+
+## Microdata Properties
+ common.data.microdata-properties =
+ list { w:microdata-property+ }
+
+## Zero
+ common.data.zero =
+ w:zero
+
+## ECMAScript FunctionBody
+ common.data.functionbody =
+ w:functionbody
+
+# #####################################################################
+## WF2 Module Hook #
+# #####################################################################
+
+common-form.attrs.form = ( notAllowed )
+
+# #####################################################################
+## Script-supporting elements
+# #####################################################################
+
+common.elem.script-supporting = ( notAllowed )
+
+# #####################################################################
+## ARIA Module Hooks #
+# #####################################################################
+
+common.attrs.aria = ( notAllowed )
+common.attrs.aria.role.alert = ( notAllowed )
+common.attrs.aria.role.alertdialog = ( notAllowed )
+common.attrs.aria.role.application = ( notAllowed )
+common.attrs.aria.role.article = ( notAllowed )
+common.attrs.aria.role.banner = ( notAllowed )
+common.attrs.aria.role.button = ( notAllowed )
+common.attrs.aria.role.checkbox = ( notAllowed )
+common.attrs.aria.role.combobox = ( notAllowed )
+common.attrs.aria.role.complementary = ( notAllowed )
+common.attrs.aria.role.contentinfo = ( notAllowed )
+common.attrs.aria.role.dialog = ( notAllowed )
+common.attrs.aria.role.directory = ( notAllowed )
+common.attrs.aria.role.document = ( notAllowed )
+common.attrs.aria.role.group = ( notAllowed )
+common.attrs.aria.role.heading = ( notAllowed )
+common.attrs.aria.role.img = ( notAllowed )
+common.attrs.aria.role.link = ( notAllowed )
+common.attrs.aria.role.list = ( notAllowed )
+common.attrs.aria.role.listitem = ( notAllowed )
+common.attrs.aria.role.log = ( notAllowed )
+common.attrs.aria.role.listbox = ( notAllowed )
+common.attrs.aria.role.main = ( notAllowed )
+common.attrs.aria.role.marquee = ( notAllowed )
+common.attrs.aria.role.menu = ( notAllowed )
+common.attrs.aria.role.menubar = ( notAllowed )
+common.attrs.aria.role.menuitem = ( notAllowed )
+common.attrs.aria.role.menuitemcheckbox = ( notAllowed )
+common.attrs.aria.role.menuitemradio = ( notAllowed )
+common.attrs.aria.role.note = ( notAllowed )
+common.attrs.aria.role.option = ( notAllowed )
+common.attrs.aria.role.presentation = ( notAllowed )
+common.attrs.aria.role.progressbar = ( notAllowed )
+common.attrs.aria.role.radio = ( notAllowed )
+common.attrs.aria.role.region = ( notAllowed )
+common.attrs.aria.role.search = ( notAllowed )
+common.attrs.aria.role.separator = ( notAllowed )
+common.attrs.aria.role.slider = ( notAllowed )
+common.attrs.aria.role.spinbutton = ( notAllowed )
+common.attrs.aria.role.status = ( notAllowed )
+common.attrs.aria.role.tab = ( notAllowed )
+common.attrs.aria.role.tablist = ( notAllowed )
+common.attrs.aria.role.tabpanel = ( notAllowed )
+common.attrs.aria.role.textbox = ( notAllowed )
+common.attrs.aria.role.toolbar = ( notAllowed )
+common.attrs.aria.role.tree = ( notAllowed )
+common.attrs.aria.role.treeitem = ( notAllowed )
+common.attrs.aria.implicit.article = ( notAllowed )
+common.attrs.aria.implicit.banner = ( notAllowed )
+common.attrs.aria.implicit.button = ( notAllowed )
+common.attrs.aria.implicit.checkbox = ( notAllowed )
+common.attrs.aria.implicit.columnheader = ( notAllowed )
+common.attrs.aria.implicit.combobox = ( notAllowed )
+common.attrs.aria.implicit.complementary = ( notAllowed )
+common.attrs.aria.implicit.contentinfo = ( notAllowed )
+common.attrs.aria.implicit.dialog = ( notAllowed )
+common.attrs.aria.implicit.document = ( notAllowed )
+common.attrs.aria.implicit.group = ( notAllowed )
+common.attrs.aria.implicit.heading = ( notAllowed )
+common.attrs.aria.implicit.img = ( notAllowed )
+common.attrs.aria.implicit.landmark = ( notAllowed )
+common.attrs.aria.implicit.link = ( notAllowed )
+common.attrs.aria.implicit.list = ( notAllowed )
+common.attrs.aria.implicit.listbox = ( notAllowed )
+common.attrs.aria.implicit.listitem = ( notAllowed )
+common.attrs.aria.implicit.main = ( notAllowed )
+common.attrs.aria.implicit.navigation = ( notAllowed )
+common.attrs.aria.implicit.option = ( notAllowed )
+common.attrs.aria.implicit.progressbar = ( notAllowed )
+common.attrs.aria.implicit.radio = ( notAllowed )
+common.attrs.aria.implicit.region = ( notAllowed )
+common.attrs.aria.implicit.rowheader = ( notAllowed )
+common.attrs.aria.implicit.section = ( notAllowed )
+common.attrs.aria.implicit.select = ( notAllowed )
+common.attrs.aria.implicit.slider = ( notAllowed )
+common.attrs.aria.implicit.spinbutton = ( notAllowed )
+common.attrs.aria.implicit.status = ( notAllowed )
+common.attrs.aria.implicit.structure = ( notAllowed )
+common.attrs.aria.implicit.textbox = ( notAllowed )
+common.attrs.aria.implicit.toolbar = ( notAllowed )
+common.attrs.aria.prop.readonly = ( notAllowed )
+common.attrs.aria.landmark.application = ( notAllowed )
+common.attrs.aria.landmark.banner = ( notAllowed )
+common.attrs.aria.landmark.complementary = ( notAllowed )
+common.attrs.aria.landmark.contentinfo = ( notAllowed )
+common.attrs.aria.landmark.form = ( notAllowed )
+common.attrs.aria.landmark.main = ( notAllowed )
+common.attrs.aria.landmark.navigation = ( notAllowed )
+common.attrs.aria.landmark.search = ( notAllowed )
+# per ARIA spec: article, document, and note are not actually landmarks
+common.attrs.aria.landmark.article = ( notAllowed )
+common.attrs.aria.landmark.document = ( notAllowed )
+common.attrs.aria.landmark.note = ( notAllowed )
diff --git a/xml/relaxng/src/resources/html5-schema/core-scripting-ext.rnc b/xml/relaxng/src/resources/html5-schema/html5/core-scripting-ext.rnc
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/core-scripting-ext.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/core-scripting-ext.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/core-scripting.rnc b/xml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/core-scripting.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/core-scripting.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/data.rnc b/xml/relaxng/src/resources/html5-schema/html5/data.rnc
new file mode 100755
index 0000000..7a95b54
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/data.rnc
@@ -0,0 +1,98 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Static Data Markup #
+# #####################################################################
+
+## Time: <time>
+
+ time.elem =
+ element time { time.inner & time.attrs }
+ time.attrs =
+ ( common.attrs
+ & time.attrs.datetime?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ time.attrs.datetime =
+ attribute datetime {
+ common.data.time-datetime
+ }
+ time.attrs.datetime.dateonly =
+ attribute datetime {
+ common.data.date
+ }
+ time.attrs.datetime.tz =
+ attribute datetime {
+ common.data.datetime
+ }
+ time.inner =
+ ( common.inner.phrasing ) #Cannot enforce textContent format here
+
+ common.elem.phrasing |= time.elem
+
+## Data: <data>
+
+ data.elem =
+ element data { data.inner & data.attrs }
+ data.attrs =
+ ( common.attrs
+ & data.attrs.value
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ data.attrs.value =
+ attribute value {
+ string
+ }
+ data.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= data.elem
+
+## Scalar Gauge: <meter>
+
+ meter.elem =
+ element meter { meter.inner & meter.attrs }
+ meter.attrs =
+ ( common.attrs
+ & meter.attrs.value
+ & meter.attrs.min?
+ & meter.attrs.low?
+ & meter.attrs.high?
+ & meter.attrs.max?
+ & meter.attrs.optimum?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meter.attrs.value =
+ attribute value {
+ common.data.float
+ }
+ meter.attrs.min =
+ attribute min {
+ common.data.float
+ }
+ meter.attrs.low =
+ attribute low {
+ common.data.float
+ }
+ meter.attrs.high =
+ attribute high {
+ common.data.float
+ }
+ meter.attrs.max =
+ attribute max {
+ common.data.float
+ }
+ meter.attrs.optimum =
+ attribute optimum {
+ common.data.float
+ }
+ meter.inner =
+ ( common.inner.phrasing ) #Cannot enforce textContent format here
+
+ common.elem.phrasing |= meter.elem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/embed-ext.rnc b/xml/relaxng/src/resources/html5-schema/html5/embed-ext.rnc
new file mode 100644
index 0000000..9b153c6
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/embed-ext.rnc
@@ -0,0 +1,3 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+embed.attrs |= common.attr.anything
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/html5/embed.rnc b/xml/relaxng/src/resources/html5-schema/html5/embed.rnc
new file mode 100755
index 0000000..51a2f0a
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/embed.rnc
@@ -0,0 +1,657 @@
+datatypes w = "http://whattf.org/datatype-draft"
+namespace local = ""
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Embedded Content #
+# #####################################################################
+
+#######################################################################
+## Replaced Content
+
+## Images: <img>
+
+ img.elem =
+ element img { img.inner & img.attrs }
+ img.attrs =
+ ( common.attrs
+ & img.attrs.src
+ & img.attrs.alt? # ARIA: if alt empty, only allowed role value is "presentation"; check in assertions
+ & img.attrs.height?
+ & img.attrs.width?
+ & img.attrs.usemap?
+ & img.attrs.ismap?
+ & img.attrs.border? # obsolete
+ & ( common.attrs.aria.implicit.img
+ | common.attrs.aria
+ )?
+ )
+ img.attrs.src =
+ attribute src {
+ common.data.uri.non-empty
+ }
+ img.attrs.alt =
+ attribute alt {
+ text
+ }
+ img.attrs.height =
+ attribute height {
+ common.data.integer.non-negative
+ }
+ img.attrs.width =
+ attribute width {
+ common.data.integer.non-negative
+ }
+ img.attrs.usemap =
+ attribute usemap {
+ common.data.hash-name
+ }
+ img.attrs.ismap =
+ attribute ismap {
+ w:string "ismap" | w:string ""
+ }
+ img.attrs.border =
+ attribute border {
+ common.data.zero
+ }
+ img.inner =
+ empty
+
+ common.elem.phrasing |= img.elem
+
+## Plug-ins: <embed>
+
+ embed.elem =
+ element embed { embed.inner & embed.attrs }
+ embed.attrs =
+ ( common.attrs
+ & embed.attrs.src?
+ & embed.attrs.type?
+ & embed.attrs.height?
+ & embed.attrs.width?
+ & embed.attrs.other*
+ & ( common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.role.img
+ )?
+ )
+ embed.attrs.src =
+ attribute src {
+ common.data.uri.non-empty
+ }
+ embed.attrs.type =
+ attribute type {
+ common.data.mimetype
+ }
+ embed.attrs.height =
+ attribute height {
+ common.data.integer.non-negative
+ }
+ embed.attrs.width =
+ attribute width {
+ common.data.integer.non-negative
+ }
+ embed.attrs.other = # REVISIT common.attrs
+ attribute local:* - ( src
+ | type
+ | height
+ | width
+ | id
+ | class
+ | title
+ | dir
+ | lang
+ | translate
+ | style
+ | tabindex
+ | contextmenu
+ | contenteditable
+ | draggable
+ | dropzone
+ | hidden
+ | onabort
+ | onblur
+ | oncanplay
+ | oncanplaythrough
+ | onchange
+ | onclick
+ | oncontextmenu
+ | ondblclick
+ | ondrag
+ | ondragend
+ | ondragenter
+ | ondragleave
+ | ondragover
+ | ondragstart
+ | ondrop
+ | ondurationchange
+ | onemptied
+ | onended
+ | onerror
+ | onfocus
+ | oninput
+ | oninvalid
+ | onkeydown
+ | onkeypress
+ | onkeyup
+ | onload
+ | onloadeddata
+ | onloadedmetadata
+ | onloadstart
+ | onmousedown
+ | onmousemove
+ | onmouseout
+ | onmouseover
+ | onmouseup
+ | onmousewheel
+ | onpause
+ | onplay
+ | onplaying
+ | onprogress
+ | onratechange
+ | onreset
+ | onscroll
+ | onseeked
+ | onseeking
+ | onselect
+ | onshow
+ | onstalled
+ | onsubmit
+ | onsuspend
+ | ontimeupdate
+ | onvolumechange
+ | onwaiting
+ | onafterprint
+ | onbeforeprint
+ | onbeforeunload
+ | onhashchange
+ | onmessage
+ | onoffline
+ | ononline
+ | onpopstate
+ | onredo
+ | onresize
+ | onstorage
+ | onundo
+ | onunload
+ | role
+ | aria-atomic
+ | aria-busy
+ | aria-controls
+ | aria-describedby
+ | aria-disabled
+ | aria-dropeffect
+ | aria-expanded
+ | aria-flowto
+ | aria-grabbed
+ | aria-haspopup
+ | aria-hidden
+ | aria-invalid
+ | aria-label
+ | aria-labelledby
+ | aria-live
+ | aria-owns
+ | aria-relevant
+ | aria-required
+ | spellcheck
+ | accesskey
+ | itemref
+ | itemprop
+ | itemscope
+ | itemtype
+ | itemid
+ | name
+ | align
+ | about
+ | prefix
+ | property
+ | typeof
+ | vocab
+ | content
+ | datatype
+ | href
+ | rel
+ | resource
+ | rev
+ | inlist
+ | its-loc-note
+ | its-loc-note-type
+ | its-loc-note-ref
+ | its-term-info-ref
+ | its-term
+ | its-term-confidence
+ | its-within-text
+ | its-domain-mapping
+ | its-ta-confidence
+ | its-ta-class-ref
+ | its-ta-ident
+ | its-ta-ident-ref
+ | its-ta-source
+ | its-locale-filter-list
+ | its-locale-filter-type
+ | its-person
+ | its-person-ref
+ | its-org
+ | its-org-ref
+ | its-tool
+ | its-tool-ref
+ | its-rev-person
+ | its-rev-person-ref
+ | its-rev-org
+ | its-rev-org-ref
+ | its-rev-tool
+ | its-rev-tool-ref
+ | its-prov-ref
+ | its-provenance-records-ref
+ | its-loc-quality-issues-ref
+ | its-loc-quality-issue-type
+ | its-loc-quality-issue-comment
+ | its-loc-quality-issue-severity
+ | its-loc-quality-issue-profile-ref
+ | its-loc-quality-issue-enabled
+ | its-loc-quality-rating-score
+ | its-loc-quality-rating-vote
+ | its-loc-quality-rating-score-threshold
+ | its-loc-quality-rating-vote-threshold
+ | its-loc-quality-rating-profile-ref
+ | its-mt-confidence
+ | its-allowed-characters
+ | its-storage-size
+ | its-storage-encoding
+ | its-line-break-type
+ | its-annotators-ref
+ )
+ {
+ string
+ }
+ embed.inner =
+ empty
+
+ common.elem.phrasing |= embed.elem
+
+## Generic Objects: <object>
+
+ object.elem.flow =
+ element object { object.inner.flow & object.attrs }
+ object.elem.phrasing =
+ element object { object.inner.phrasing & object.attrs }
+ object.attrs =
+ ( common.attrs
+ & ( ( object.attrs.data
+ & object.attrs.type?
+ )
+ | object.attrs.type
+ )
+# & object.attrs.classid?
+# & object.attrs.codebase?
+# & object.attrs.codetype?
+ & object.attrs.height?
+ & object.attrs.width?
+ & object.attrs.usemap?
+ & object.attrs.name?
+ & common-form.attrs.form?
+ & ( common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.role.img
+ )?
+ )
+ object.attrs.data =
+ attribute data {
+ common.data.uri.non-empty
+ }
+ object.attrs.type =
+ attribute type {
+ common.data.mimetype
+ }
+ object.attrs.height =
+ attribute height {
+ common.data.integer.non-negative
+ }
+ object.attrs.width =
+ attribute width {
+ common.data.integer.non-negative
+ }
+ object.attrs.usemap =
+ attribute usemap {
+ common.data.hash-name
+ }
+ object.attrs.name =
+ attribute name {
+ common.data.browsing-context
+ }
+ object.inner.flow =
+ ( param.elem*
+ , common.inner.transparent.flow
+ )
+ object.inner.phrasing =
+ ( param.elem*
+ , common.inner.phrasing
+ )
+
+ common.elem.flow |= object.elem.flow
+ common.elem.phrasing |= object.elem.phrasing
+
+## Initialization Parameters: <param>
+
+ param.elem =
+ element param { param.inner & param.attrs }
+ param.attrs =
+ ( common.attrs
+ & param.attrs.name
+ & param.attrs.value
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ param.attrs.name =
+ attribute name {
+ string
+ }
+ param.attrs.value =
+ attribute value {
+ string
+ }
+ param.inner =
+ ( empty )
+
+## Inline Frame: <iframe>
+
+ iframe.elem =
+ element iframe { iframe.inner & iframe.attrs }
+ iframe.attrs =
+ ( common.attrs
+ & iframe.attrs.src?
+ & iframe.attrs.srcdoc?
+ & iframe.attrs.name?
+ & iframe.attrs.width?
+ & iframe.attrs.height?
+ & iframe.attrs.sandbox?
+ & iframe.attrs.seamless?
+ & iframe.attrs.allowfullscreen?
+ & ( common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.role.img
+ )?
+ )
+ iframe.attrs.src =
+ attribute src {
+ common.data.uri.non-empty
+ }
+ iframe.attrs.srcdoc =
+ attribute srcdoc {
+ string #FIXME
+ }
+ iframe.attrs.name =
+ attribute name {
+ common.data.browsing-context
+ }
+ iframe.attrs.height =
+ attribute height {
+ common.data.integer.non-negative
+ }
+ iframe.attrs.width =
+ attribute width {
+ common.data.integer.non-negative
+ }
+ iframe.attrs.seamless =
+ attribute seamless {
+ w:string "seamless" | w:string ""
+ } & v5only
+ iframe.attrs.sandbox =
+ attribute sandbox
+ { list
+ { ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-scripts" )?
+ }
+ | list
+ { ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-forms" )?
+ }
+ | list
+ { ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-scripts" )?
+ }
+ | list
+ { ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-same-origin" )?
+ }
+ | list
+ { ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-forms" )?
+ }
+ | list
+ { ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-same-origin" )?
+ }
+ | list
+ { ( w:string "allow-same-origin" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-scripts" )?
+ }
+ | list
+ { ( w:string "allow-same-origin" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-forms" )?
+ }
+ | list
+ { ( w:string "allow-forms" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-scripts" )?
+ }
+ | list
+ { ( w:string "allow-forms" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-same-origin" )?
+ }
+ | list
+ { ( w:string "allow-scripts" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-forms" )?
+ }
+ | list
+ { ( w:string "allow-scripts" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-same-origin" )?
+ }
+ | list
+ { ( w:string "allow-same-origin" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-scripts" )?
+ }
+ | list
+ { ( w:string "allow-same-origin" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-forms" )?
+ }
+ | list
+ { ( w:string "allow-forms" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-scripts" )?
+ }
+ | list
+ { ( w:string "allow-forms" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-same-origin" )?
+ }
+ | list
+ { ( w:string "allow-scripts" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-forms" )?
+ }
+ | list
+ { ( w:string "allow-scripts" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-top-navigation" )?
+ , ( w:string "allow-same-origin" )?
+ }
+ | list
+ { ( w:string "allow-same-origin" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-top-navigation" )?
+ }
+ | list
+ { ( w:string "allow-same-origin" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-top-navigation" )?
+ }
+ | list
+ { ( w:string "allow-forms" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-top-navigation" )?
+ }
+ | list
+ { ( w:string "allow-forms" )?
+ , ( w:string "allow-scripts" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-top-navigation" )?
+ }
+ | list
+ { ( w:string "allow-scripts" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-top-navigation" )?
+ }
+ | list
+ { ( w:string "allow-scripts" )?
+ , ( w:string "allow-forms" )?
+ , ( w:string "allow-same-origin" )?
+ , ( w:string "allow-top-navigation" )?
+ }
+ } & v5only
+ iframe.attrs.allowfullscreen =
+ attribute allowfullscreen {
+ w:string "allowfullscreen" | w:string ""
+ } & v5only
+ iframe.inner =
+ ( text )
+
+ common.elem.phrasing |= iframe.elem
+
+#######################################################################
+## Image Maps
+
+## Map Definition: <map>
+
+ map.elem.flow =
+ element map { map.inner.flow & map.attrs }
+ map.elem.phrasing =
+ element map { map.inner.phrasing & map.attrs }
+ map.attrs =
+ ( common.attrs
+ & map.attrs.name
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ ) # REVISIT make id required in Schematron
+ map.attrs.name =
+ attribute name {
+ common.data.name
+ }
+ map.inner.flow =
+ ( common.inner.transparent.flow )
+ map.inner.phrasing =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= map.elem.flow
+ common.elem.phrasing |= map.elem.phrasing
+
+## Map Area Definition: <area>
+
+ area.elem =
+ element area { area.inner & area.attrs }
+ area.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & shared-hyperlink.attrs.download?
+ & ( area.attrs.alt
+ & shared-hyperlink.attrs.href
+ )?
+ & shared-hyperlink.attrs.target?
+ & shared-hyperlink.attrs.ping?
+ & shared-hyperlink.attrs.rel?
+ & shared-hyperlink.attrs.hreflang?
+ & shared-hyperlink.attrs.type?
+ & area.attrs.shape?
+ & ( common.attrs.aria.role.link
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ area.attrs.alt =
+ attribute alt {
+ text
+ }
+ area.attrs.shape =
+ ( ( area.attrs.shape.rect? & area.attrs.coords.rect )
+ | ( area.attrs.shape.circle & area.attrs.coords.circle )
+ | ( area.attrs.shape.poly & area.attrs.coords.poly )
+ | ( area.attrs.shape.default )
+ )
+ area.attrs.shape.rect =
+ attribute shape {
+ w:string "rect"
+ }
+ area.attrs.coords.rect =
+ attribute coords {
+ w:rectangle
+# xsd:token {
+# pattern = "-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+"
+# }
+ }
+ area.attrs.shape.circle =
+ attribute shape {
+ w:string "circle"
+ }
+ area.attrs.coords.circle =
+ attribute coords {
+ w:circle
+# xsd:token {
+# pattern = "-?[0-9]+,-?[0-9]+,[0-9]+"
+# }
+ }
+ area.attrs.shape.poly =
+ attribute shape {
+ w:string "poly"
+ }
+ area.attrs.coords.poly =
+ attribute coords {
+ w:polyline
+# xsd:token {
+# pattern = "-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+,-?[0-9]+(,-?[0-9]+,-?[0-9]+)*"
+# }
+ }
+ area.attrs.shape.default =
+ attribute shape {
+ w:string "default"
+ }
+ area.inner =
+ ( empty )
+
+ common.elem.phrasing |= area.elem
diff --git a/xml/relaxng/src/resources/html5-schema/form-datatypes.rnc b/xml/relaxng/src/resources/html5-schema/html5/form-datatypes.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/form-datatypes.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/form-datatypes.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/html5.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5.rnc
new file mode 100644
index 0000000..0d8cef8
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/html5.rnc
@@ -0,0 +1,56 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+# #####################################################################
+## RELAX NG Schema for HTML 5 #
+# #####################################################################
+
+ # To validate an HTML 5 document, you must first validate against #
+ # this schema and then ALSO validate against assertions.sch #
+
+ ## HTML flavor RELAX NG schemas can only be used after the #
+ ## document has been transformed to well-formed XML. #
+ ## - Insert closing slashes in all empty element tags #
+ ## - Insert all optional start and end tags #
+ ## - Add xmlns "http://www.w3.org/1999/xhtml" #
+ ## - Properly escape <script> and <style> CDATA #
+ ## - Parse and transform all HTML-only entities to numeric #
+ ## character references #
+ ## Obviously, syntax-checking involving these features cannot be #
+ ## done by the RELAX NG schema and must be checked, along with the #
+ ## <!DOCTYPE> requirement, by some other application. #
+
+# #####################################################################
+## Schema Framework & Parameters
+
+include "common.rnc" {
+ # XHTML flavor #
+ XMLonly = notAllowed
+ HTMLonly = empty
+ # HTML 4 compat #
+ v5only = empty
+ # HTML-serializability #
+ nonHTMLizable = notAllowed
+ # HTML-roundtrippability #
+ nonRoundtrippable = notAllowed
+}
+
+# #####################################################################
+## Language Definitions
+
+start = html.elem
+
+include "meta.rnc"
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "structural.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "core-scripting.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "applications.rnc"
+include "data.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/html5core.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5core.rnc
new file mode 100644
index 0000000..813f356
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/html5core.rnc
@@ -0,0 +1,13 @@
+include "common.rnc" {
+ XMLonly = notAllowed
+ HTMLonly = empty
+ v5only = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "meta.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5exclusions.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5exclusions.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/html5exclusions.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/html5exclusions.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/html5full-no-microdata.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5full-no-microdata.rnc
new file mode 100644
index 0000000..2317e0e
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/html5full-no-microdata.rnc
@@ -0,0 +1,35 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = notAllowed
+ HTMLonly = empty
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
diff --git a/xml/relaxng/src/resources/html5-schema/html5/html5full-rdfa.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5full-rdfa.rnc
new file mode 100644
index 0000000..c894d88
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/html5full-rdfa.rnc
@@ -0,0 +1,41 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = notAllowed
+ HTMLonly = empty
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+include "common-ext.rnc"
+
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "embed-ext.rnc"
+include "core-scripting.rnc"
+include "core-scripting-ext.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "meta-ext.rnc"
+include "rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/html5full-rdfalite.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5full-rdfalite.rnc
new file mode 100644
index 0000000..f201158
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/html5full-rdfalite.rnc
@@ -0,0 +1,39 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = notAllowed
+ HTMLonly = empty
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "microdata.rnc"
+include "rdfa.rnc" {
+ nonRDFaLite = notAllowed
+}
diff --git a/xml/relaxng/src/resources/html5-schema/html5/html5full.rnc b/xml/relaxng/src/resources/html5-schema/html5/html5full.rnc
new file mode 100644
index 0000000..4020c80
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/html5full.rnc
@@ -0,0 +1,36 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = notAllowed
+ HTMLonly = empty
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "microdata.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/its20-html5-types.rnc b/xml/relaxng/src/resources/html5-schema/html5/its20-html5-types.rnc
new file mode 100644
index 0000000..8d16ccc
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/its20-html5-types.rnc
@@ -0,0 +1,151 @@
+# Copyright (c) 2012 Jirka Kosek <jirka@kosek.cz>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+datatypes w = "http://whattf.org/datatype-draft"
+
+its-confidence.type = xsd:double { minInclusive = "0" maxInclusive = "1" }
+
+its-locNote.type = string
+
+## The type of localization note
+its-locNoteType.type =
+ ## Localization note is an alert
+ w:string "alert"
+ |
+ ## Localization note is a description
+ w:string "description"
+
+its-locNoteRef.type = w:iri-ref
+
+its-termInfoRef.type = w:iri-ref
+
+## Indicates a term locally
+its-term.type =
+ ## The value 'yes' means that this is a term
+ w:string "yes"
+ |
+ ## The value 'no' means that this is not a term
+ w:string "no"
+
+its-termConfidence.type = its-confidence.type
+
+## States whether current context is regarded as "within text"
+its-withinText.type =
+ ## The element and its content are part of the flow of its parent element
+ w:string "yes"
+ |
+ ## The element splits the text flow of its parent element and its content is an independent text flow
+ w:string "no"
+ |
+ ## The element is part of the flow of its parent element, its content is an independent flow
+ w:string "nested"
+
+## A comma separated list of mappings between values in the content
+## and workflow specific values. The values may contain spaces; in
+## that case they MUST be delimited by quotation marks.
+its-domainMapping.type = string
+
+its-taConfidence.type = its-confidence.type
+
+its-taClassRef.type = w:iri-ref
+
+its-taIdentRef.type = w:iri-ref
+
+its-taIdent.type = string
+
+its-taSource.type = string
+
+its-localeFilterList.type = string
+
+its-localeFilterType.type = w:string "include" | w:string "exclude"
+
+its-person.type = string
+
+its-personRef.type = w:iri-ref
+
+its-org.type = string
+
+its-orgRef.type = w:iri-ref
+
+its-tool.type = string
+
+its-toolRef.type = w:iri-ref
+
+its-revPerson.type = string
+
+its-revPersonRef.type = w:iri-ref
+
+its-revOrg.type = string
+
+its-revOrgRef.type = w:iri-ref
+
+its-revTool.type = string
+
+its-revToolRef.type = w:iri-ref
+
+its-provRef.type = list { w:iri-ref+ }
+
+its-provenanceRecordsRef.type = w:iri-ref
+
+its-idValue.type = string
+
+its-space.type = "default" | "preserve"
+
+its-locQualityIssuesRef.type = w:iri-ref
+
+its-locQualityIssueType.type = w:string "terminology" | w:string "mistranslation" |
+ w:string "omission" | w:string "untranslated" | w:string "addition" | w:string "duplication" |
+ w:string "inconsistency" | w:string "grammar" | w:string "legal" | w:string "register" |
+ w:string "locale-specific-content" | w:string "locale-violation" | w:string "style" |
+ w:string "characters" | w:string "misspelling" | w:string "typographical" | w:string "formatting" |
+ w:string "inconsistent-entities" | w:string "numbers" | w:string "markup" | w:string "pattern-problem" |
+ w:string "whitespace" | w:string "internationalization" | w:string "length" | w:string "non-conformance" | w:string "uncategorized" |
+ w:string "other"
+
+its-locQualityIssueComment.type = string
+
+its-locQualityIssueSeverity.type = xsd:double { minInclusive = "0" maxInclusive = "100" }
+
+its-locQualityIssueProfileRef.type = w:iri-ref
+
+its-locQualityIssueEnabled.type = w:string "yes" | w:string "no"
+
+its-locQualityRatingScore.type = xsd:double { minInclusive = "0" maxInclusive = "100" }
+
+its-locQualityRatingVote.type = xsd:integer
+
+its-locQualityRatingScoreThreshold.type = xsd:double { minInclusive = "0" maxInclusive = "100" }
+
+its-locQualityRatingVoteThreshold.type = xsd:integer
+
+its-locQualityRatingProfileRef.type = w:iri-ref
+
+its-mtConfidence.type = its-confidence.type
+
+its-allowedCharacters.type = string
+
+its-storageSize.type = xsd:nonNegativeInteger
+
+its-storageEncoding.type = string
+
+its-lineBreakType.type = w:string "cr" | w:string "lf" | w:string "crlf"
+
+its-annotatorsRef.type = string
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/html5/its20-html5.rnc b/xml/relaxng/src/resources/html5-schema/html5/its20-html5.rnc
new file mode 100644
index 0000000..c0c8e48
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/its20-html5.rnc
@@ -0,0 +1,143 @@
+# Copyright (c) 2012 Jirka Kosek <jirka@kosek.cz>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+include "its20-html5-types.rnc"
+
+its-attribute.locNote.html = attribute its-loc-note { its-locNote.type }
+
+its-attribute.locNoteType.html = attribute its-loc-note-type { its-locNoteType.type }
+
+its-attribute.locNoteRef.html = attribute its-loc-note-ref { its-locNoteRef.type }
+
+its-attribute.termInfoRef.html = attribute its-term-info-ref { its-termInfoRef.type }
+
+its-attribute.term.html = attribute its-term { its-term.type }
+
+its-attribute.termConfidence.html = attribute its-term-confidence { its-termConfidence.type }
+
+its-attribute.withinText.html = attribute its-within-text { its-withinText.type }
+
+its-attribute.domainMapping.html = attribute its-domain-mapping { its-domainMapping.type }
+
+its-attribute.taConfidence.html = attribute its-ta-confidence { its-taConfidence.type }
+
+its-attribute.taClassRef.html = attribute its-ta-class-ref { its-taClassRef.type }
+
+its-attribute.taIdent.html = attribute its-ta-ident { its-taIdent.type }
+
+its-attribute.taIdentRef.html = attribute its-ta-ident-ref { its-taIdentRef.type }
+
+its-attribute.taSource.html = attribute its-ta-source { its-taSource.type }
+
+its-attribute.localeFilterList.html = attribute its-locale-filter-list { its-localeFilterList.type }
+
+its-attribute.localeFilterType.html = attribute its-locale-filter-type { its-localeFilterType.type }
+
+its-attribute.person.html = attribute its-person { its-person.type }
+
+its-attribute.personRef.html = attribute its-person-ref { its-personRef.type }
+
+its-attribute.org.html = attribute its-org { its-org.type }
+
+its-attribute.orgRef.html = attribute its-org-ref { its-orgRef.type }
+
+its-attribute.tool.html = attribute its-tool { its-tool.type }
+
+its-attribute.toolRef.html = attribute its-tool-ref { its-toolRef.type }
+
+its-attribute.revPerson.html = attribute its-rev-person { its-revPerson.type }
+
+its-attribute.revPersonRef.html = attribute its-rev-person-ref { its-revPersonRef.type }
+
+its-attribute.revOrg.html = attribute its-rev-org { its-revOrg.type }
+
+its-attribute.revOrgRef.html = attribute its-rev-org-ref { its-revOrgRef.type }
+
+its-attribute.revTool.html = attribute its-rev-tool { its-revTool.type }
+
+its-attribute.revToolRef.html = attribute its-rev-tool-ref { its-revToolRef.type }
+
+its-attribute.provRef.html = attribute its-prov-ref { its-provRef.type }
+
+its-attribute.provenanceRecordsRef.html = attribute its-provenance-records-ref { its-provenanceRecordsRef.type }
+
+its-attribute.locQualityIssuesRef.html = attribute its-loc-quality-issues-ref { its-locQualityIssuesRef.type }
+
+its-attribute.locQualityIssueType.html = attribute its-loc-quality-issue-type { its-locQualityIssueType.type }
+
+its-attribute.locQualityIssueComment.html = attribute its-loc-quality-issue-comment { its-locQualityIssueComment.type }
+
+its-attribute.locQualityIssueSeverity.html = attribute its-loc-quality-issue-severity { its-locQualityIssueSeverity.type }
+
+its-attribute.locQualityIssueProfileRef.html = attribute its-loc-quality-issue-profile-ref { its-locQualityIssueProfileRef.type }
+
+its-attribute.locQualityIssueEnabled.html = attribute its-loc-quality-issue-enabled { its-locQualityIssueEnabled.type }
+
+its-attribute.locQualityRatingScore.html = attribute its-loc-quality-rating-score { its-locQualityRatingScore.type }
+
+its-attribute.locQualityRatingVote.html = attribute its-loc-quality-rating-vote { its-locQualityRatingVote.type }
+
+its-attribute.locQualityRatingScoreThreshold.html = attribute its-loc-quality-rating-score-threshold { its-locQualityRatingScoreThreshold.type }
+
+its-attribute.locQualityRatingVoteThreshold.html = attribute its-loc-quality-rating-vote-threshold { its-locQualityRatingVoteThreshold.type }
+
+its-attribute.locQualityRatingProfileRef.html = attribute its-loc-quality-rating-profile-ref { its-locQualityRatingProfileRef.type }
+
+its-attribute.mtConfidence.html = attribute its-mt-confidence { its-mtConfidence.type }
+
+its-attribute.allowedCharacters.html = attribute its-allowed-characters { its-allowedCharacters.type }
+
+its-attribute.storageSize.html = attribute its-storage-size { its-storageSize.type }
+
+its-attribute.storageEncoding.html = attribute its-storage-encoding { its-storageEncoding.type }
+
+its-attribute.lineBreakType.html = attribute its-line-break-type { its-lineBreakType.type }
+
+its-attribute.annotatorsRef.html = attribute its-annotators-ref { its-annotatorsRef.type }
+
+its-html-attributes =
+ ((its-attribute.locNote.html | its-attribute.locNoteRef.html), its-attribute.locNoteType.html?)? &
+ (its-attribute.term.html, its-attribute.termInfoRef.html?, its-attribute.termConfidence.html?)? &
+ its-attribute.withinText.html? &
+ (its-attribute.taConfidence.html? &
+ (its-attribute.taClassRef.html? &
+ ((its-attribute.taSource.html, its-attribute.taIdent.html) | its-attribute.taIdentRef.html)?)) &
+ (its-attribute.localeFilterList.html, its-attribute.localeFilterType.html?)? &
+ ((
+ (its-attribute.person.html | its-attribute.personRef.html )? &
+ (its-attribute.org.html | its-attribute.orgRef.html )? &
+ (its-attribute.tool.html | its-attribute.toolRef.html )? &
+ (its-attribute.revPerson.html | its-attribute.revPersonRef.html )? &
+ (its-attribute.revOrg.html | its-attribute.revOrgRef.html )? &
+ (its-attribute.revTool.html | its-attribute.revToolRef.html )? &
+ its-attribute.provRef.html?)
+ | its-attribute.provenanceRecordsRef.html)? &
+ (its-attribute.locQualityIssuesRef.html
+ |
+ ((its-attribute.locQualityIssueType.html? & its-attribute.locQualityIssueComment.html?) & its-attribute.locQualityIssueSeverity.html? & its-attribute.locQualityIssueProfileRef.html? & its-attribute.locQualityIssueEnabled.html?)
+ )? &
+ (((its-attribute.locQualityRatingScore.html, its-attribute.locQualityRatingScoreThreshold.html?) | (its-attribute.locQualityRatingVote.html, its-attribute.locQualityRatingVoteThreshold.html?)), its-attribute.locQualityRatingProfileRef.html?)? &
+ its-attribute.mtConfidence.html? &
+ its-attribute.allowedCharacters.html? &
+ (its-attribute.storageSize.html, its-attribute.storageEncoding.html?, its-attribute.lineBreakType.html?)? &
+ its-attribute.annotatorsRef.html?
+
+# FIXME: Find way how to validate stand-off markup inside <script>
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc b/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc
new file mode 100644
index 0000000..e64f770
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/legacy.rnc
@@ -0,0 +1,1415 @@
+datatypes w = "http://whattf.org/datatype-draft"
+# #####################################################################
+## RELAX NG Schema for HTML 5: Obsolete Elements and Attributes #
+# #####################################################################
+
+## In order to work around RELAX NG limitations and to thereby get more
+## useful error messages, the following elements and attributes are
+## allowed here but disallowed in the assertions-checking code.
+
+## Obsolete elements
+
+## Centering: <center>
+
+ center.elem =
+ element center { center.inner & center.attrs }
+ center.attrs =
+ ( common.attrs )
+ center.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= center.elem
+
+## Inline Styling: <font>
+
+ font.elem =
+ element font { font.inner & font.attrs }
+ font.attrs =
+ ( common.attrs
+ & font.attrs.color?
+ & font.attrs.face?
+ & font.attrs.size?
+ & common.attrs.aria?
+ )
+ font.attrs.color =
+ attribute color {
+ string
+ }
+ font.attrs.face =
+ attribute face {
+ string
+ }
+ font.attrs.size =
+ attribute size {
+ string
+ }
+ font.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= font.elem
+
+## Base Font Size: <basefont>
+
+ basefont.elem =
+ element basefont { empty & basefont.attrs }
+ basefont.attrs =
+ ( common.attrs
+ & basefont.attrs.color?
+ & basefont.attrs.face?
+ & basefont.attrs.size?
+ )
+ basefont.attrs.color =
+ attribute color {
+ string
+ }
+ basefont.attrs.face =
+ attribute face {
+ string
+ }
+ basefont.attrs.size =
+ attribute size {
+ string
+ }
+
+ common.elem.flow |= basefont.elem
+
+## Larger Font: <big>
+
+ big.elem =
+ element big { big.inner & big.attrs }
+ big.attrs =
+ ( common.attrs )
+ big.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= big.elem
+
+## Struck Text: <strike>
+
+ strike.elem =
+ element strike { strike.inner & strike.attrs }
+ strike.attrs =
+ ( common.attrs )
+ strike.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= strike.elem
+
+## Teletype: <tt>
+
+ tt.elem =
+ element tt { tt.inner & tt.attrs }
+ tt.attrs =
+ ( common.attrs )
+ tt.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= tt.elem
+
+## Abbreviation: <acronym>
+
+ acronym.elem =
+ element acronym { acronym.inner & acronym.attrs }
+ acronym.attrs =
+ ( common.attrs )
+ acronym.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= acronym.elem
+
+## Directory: <dir>
+
+ dir.elem =
+ element dir { dir.inner & dir.attrs }
+ dir.attrs =
+ ( common.attrs
+ & dir.attrs.compact?
+ )
+ dir.attrs.compact =
+ attribute compact {
+ string
+ }
+ dir.inner =
+ ( li.elem* )
+
+ common.elem.flow |= dir.elem
+
+## Java Applets: <applet>
+
+ applet.elem.flow =
+ element applet { applet.inner.flow & applet.attrs }
+ applet.elem.phrasing =
+ element applet { applet.inner.phrasing & applet.attrs }
+ applet.attrs =
+ ( common.attrs
+ & applet.attrs.archive?
+ & applet.attrs.code
+ & applet.attrs.codebase?
+ & applet.attrs.name?
+ & applet.attrs.height
+ & applet.attrs.width
+ )
+ applet.attrs.archive =
+ attribute archive {
+ common.data.uri #FIXME *comma* separated URI list (*grumble*)
+ }
+ applet.attrs.code =
+ attribute code {
+ token
+ }
+ applet.attrs.codebase =
+ attribute codebase {
+ common.data.uri
+ }
+ applet.attrs.name =
+ attribute name {
+ string #FIXME refine
+ }
+ applet.attrs.height =
+ attribute height {
+ common.data.integer.positive
+ }
+ applet.attrs.width =
+ attribute width {
+ common.data.integer.positive
+ }
+ applet.inner.flow =
+ ( param.elem*
+ , common.inner.flow
+ )
+ applet.inner.phrasing =
+ ( param.elem*
+ , common.inner.phrasing
+ )
+
+ common.elem.flow |= applet.elem.flow
+ common.elem.phrasing |= applet.elem.phrasing
+
+## Frame Set: <frameset>
+
+ frameset.elem =
+ element frameset { frameset.inner & frameset.attrs }
+ frameset.attrs =
+ ( common.attrs
+ & frameset.attrs.rows?
+ & frameset.attrs.columns?
+ & frameset.attrs.onunload?
+ )
+ frameset.attrs.rows =
+ attribute rows {
+ string
+ }
+ frameset.attrs.columns =
+ attribute columns {
+ string
+ }
+ frameset.attrs.onunload =
+ attribute onunload {
+ string
+ }
+ frameset.inner =
+ (
+ ( frameset.elem
+ | frame.elem
+ )+
+ & noframes.elem?
+ )
+
+## Frame: <frame>
+
+ frame.elem =
+ element frame { empty & frame.attrs }
+ frame.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & frame.attrs.longdesc?
+ & frame.attrs.name?
+ & frame.attrs.src?
+ & frame.attrs.frameborder?
+ & frame.attrs.marginwidth?
+ & frame.attrs.marginheight?
+ & frame.attrs.noresize?
+ & frame.attrs.scrolling?
+ )
+ frame.attrs.longdesc =
+ attribute longdesc {
+ string
+ }
+ frame.attrs.name =
+ attribute name {
+ string
+ }
+ frame.attrs.src =
+ attribute src {
+ string
+ }
+ frame.attrs.frameborder =
+ attribute frameborder {
+ string
+ }
+ frame.attrs.marginwidth =
+ attribute marginwidth {
+ string
+ }
+ frame.attrs.marginheight =
+ attribute marginheight {
+ string
+ }
+ frame.attrs.noresize =
+ attribute noresize {
+ string
+ }
+ frame.attrs.scrolling =
+ attribute scrolling {
+ string
+ }
+
+## Alternate no-frames content: <noframes>
+
+ noframes.elem =
+ element noframes { noframes.inner & noframes.attrs }
+ noframes.attrs =
+ ( common.attrs )
+ noframes.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= noframes.elem
+
+## "content-language" pragma directive: <meta http-equiv='content-language'>
+
+ meta.http-equiv.content-language.elem =
+ element meta { meta.inner & meta.http-equiv.content-language.attrs }
+ meta.http-equiv.content-language.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.content-language
+ & meta.http-equiv.attrs.content.content-language?
+ )
+ meta.http-equiv.attrs.http-equiv.content-language =
+ attribute http-equiv {
+ w:string "content-language"
+ }
+ meta.http-equiv.attrs.content.content-language =
+ attribute content {
+ string
+ }
+
+ common.elem.metadata |= meta.http-equiv.content-language.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+## Obsolete attributes
+
+## abbr attribute
+
+ td.attrs.abbr =
+ attribute abbr {
+ string
+ }
+ td.attrs &= td.attrs.abbr?
+
+ th.attrs.abbr =
+ attribute abbr {
+ string
+ }
+ th.attrs &= th.attrs.abbr?
+
+## archive attribute
+
+ object.attrs.archive =
+ attribute archive {
+ string
+ }
+ object.attrs &= object.attrs.archive?
+
+## axis attribute
+
+ td.attrs.axis =
+ attribute axis {
+ string
+ }
+ td.attrs &= td.attrs.axis?
+
+ th.attrs.axis =
+ attribute axis {
+ string
+ }
+ th.attrs &= th.attrs.axis?
+
+## charset attribute
+
+ link.attrs.charset =
+ attribute charset {
+ string
+ }
+ link.attrs &= link.attrs.charset?
+
+ a.attrs.charset =
+ attribute charset {
+ string
+ }
+ a.attrs &= a.attrs.charset?
+
+## classid attribute
+
+ object.attrs.classid =
+ attribute classid {
+ common.data.uri
+ }
+ object.attrs &= object.attrs.classid?
+
+## codebase attribute
+
+ object.attrs.codebase =
+ attribute codebase {
+ common.data.uri
+ }
+ object.attrs &= object.attrs.codebase?
+
+## codetype attribute
+
+ object.attrs.codetype =
+ attribute codetype {
+ common.data.mimetype
+ }
+ object.attrs &= object.attrs.codetype?
+
+## code attribute
+
+ object.attrs.code =
+ attribute code {
+ token
+ }
+ object.attrs &= object.attrs.code?
+
+## coords attribute
+
+ a.attrs.coords =
+ attribute coords {
+ string
+ }
+ a.attrs &= a.attrs.coords?
+
+## declare attribute
+
+ object.attrs.declare =
+ attribute declare {
+ string
+ }
+ object.attrs &= object.attrs.declare?
+
+## longdesc attribute
+
+ img.attrs.longdesc =
+ attribute longdesc {
+ common.data.uri.non-empty
+ }
+ img.attrs &= img.attrs.longdesc?
+
+ iframe.attrs.longdesc =
+ attribute longdesc {
+ string
+ }
+ iframe.attrs &= iframe.attrs.longdesc?
+
+## methods attribute
+
+ a.attrs.methods =
+ attribute methods {
+ string
+ }
+ a.attrs &= a.attrs.methods?
+
+ link.attrs.methods =
+ attribute methods {
+ string
+ }
+ link.attrs &= link.attrs.methods?
+
+## name attribute
+
+ img.attrs.name =
+ attribute name {
+ string
+ }
+ img.attrs &= img.attrs.name?
+
+ embed.attrs.name =
+ attribute name {
+ string
+ }
+ embed.attrs &= embed.attrs.name?
+
+ option.attrs.name =
+ attribute name {
+ string
+ }
+ option.attrs &= option.attrs.name?
+
+## nohref attribute
+
+ area.attrs.nohref =
+ attribute nohref {
+ string
+ }
+ area.attrs &= area.attrs.nohref?
+
+## profile attribute
+
+ head.attrs.profile =
+ attribute profile {
+ string
+ }
+ head.attrs &= head.attrs.profile?
+
+## rev attribute
+
+ link.attrs.rev =
+ attribute rev {
+ string
+ }
+ link.attrs &= link.attrs.rev?
+
+ a.attrs.rev =
+ attribute rev {
+ string
+ }
+ a.attrs &= a.attrs.rev?
+
+## scheme attribute
+
+ meta.attrs.scheme =
+ attribute scheme {
+ string
+ }
+ meta.name.attrs &= meta.attrs.scheme?
+
+## scope attribute
+
+ td.attrs.scope =
+ attribute scope {
+ string
+ }
+ td.attrs &= td.attrs.scope?
+
+## shape attribute
+
+ a.attrs.shape =
+ attribute shape {
+ string
+ }
+ a.attrs &= a.attrs.shape?
+
+## standby attribute
+
+ object.attrs.standby =
+ attribute standby {
+ string
+ }
+ object.attrs &= object.attrs.standby?
+
+## target attribute
+
+ link.attrs.target =
+ attribute target {
+ string
+ }
+ link.attrs &= link.attrs.target?
+
+## type attribute
+
+ param.attrs.type =
+ attribute type {
+ string
+ }
+ param.attrs &= param.attrs.type?
+
+## urn attribute
+
+ a.attrs.urn =
+ attribute urn {
+ string
+ }
+ a.attrs &= a.attrs.urn?
+
+ link.attrs.urn =
+ attribute urn {
+ string
+ }
+ link.attrs &= link.attrs.urn?
+
+## usemap attribute
+
+ input.attrs.usemap =
+ attribute usemap {
+ string
+ }
+ input.image.attrs &= input.attrs.usemap?
+
+## valuetype attribute
+
+ param.attrs.valuetype =
+ attribute valuetype {
+ string
+ }
+ param.attrs &= param.attrs.valuetype?
+
+## version attribute
+
+ html.attrs.version =
+ attribute version {
+ string
+ }
+ html.attrs &= html.attrs.version?
+
+## Obsolete style attributes
+
+## align attribute
+
+ caption.attrs.align =
+ attribute align {
+ string
+ }
+ caption.attrs &= caption.attrs.align?
+
+ col.attrs.align =
+ attribute align {
+ string
+ }
+ col.attrs &= col.attrs.align?
+
+ colgroup.attrs.align =
+ attribute align {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.align?
+
+ div.attrs.align =
+ attribute align {
+ string
+ }
+ div.attrs &= div.attrs.align?
+
+ embed.attrs.align =
+ attribute align {
+ string
+ }
+ embed.attrs &= embed.attrs.align?
+
+ h1.attrs.align =
+ attribute align {
+ string
+ }
+ h1.attrs &= h1.attrs.align?
+
+ h2.attrs.align =
+ attribute align {
+ string
+ }
+ h2.attrs &= h2.attrs.align?
+
+ h3.attrs.align =
+ attribute align {
+ string
+ }
+ h3.attrs &= h3.attrs.align?
+
+ h4.attrs.align =
+ attribute align {
+ string
+ }
+ h4.attrs &= h4.attrs.align?
+
+ h5.attrs.align =
+ attribute align {
+ string
+ }
+ h5.attrs &= h5.attrs.align?
+
+ h6.attrs.align =
+ attribute align {
+ string
+ }
+ h6.attrs &= h6.attrs.align?
+
+ hr.attrs.align =
+ attribute align {
+ string
+ }
+ hr.attrs &= hr.attrs.align?
+
+ iframe.attrs.align =
+ attribute align {
+ string
+ }
+ iframe.attrs &= iframe.attrs.align?
+
+ img.attrs.align =
+ attribute align {
+ string
+ }
+ img.attrs &= img.attrs.align?
+
+ input.attrs.align =
+ attribute align {
+ string
+ }
+ input.text.attrs &= input.attrs.align?
+ input.password.attrs &= input.attrs.align?
+ input.checkbox.attrs &= input.attrs.align?
+ input.radio.attrs &= input.attrs.align?
+ input.button.attrs &= input.attrs.align?
+ input.submit.attrs &= input.attrs.align?
+ input.reset.attrs &= input.attrs.align?
+ input.file.attrs &= input.attrs.align?
+ input.image.attrs &= input.attrs.align?
+ input.datetime.attrs &= input.attrs.align?
+ input.datetime-local.attrs &= input.attrs.align?
+ input.date.attrs &= input.attrs.align?
+ input.month.attrs &= input.attrs.align?
+ input.time.attrs &= input.attrs.align?
+ input.week.attrs &= input.attrs.align?
+ input.number.attrs &= input.attrs.align?
+ input.range.attrs &= input.attrs.align?
+ input.email.attrs &= input.attrs.align?
+ input.url.attrs &= input.attrs.align?
+ input.search.attrs &= input.attrs.align?
+ input.tel.attrs &= input.attrs.align?
+ input.color.attrs &= input.attrs.align?
+
+ legend.attrs.align =
+ attribute align {
+ string
+ }
+ legend.attrs &= legend.attrs.align?
+
+ object.attrs.align =
+ attribute align {
+ string
+ }
+ object.attrs &= object.attrs.align?
+
+ p.attrs.align =
+ attribute align {
+ string
+ }
+ p.attrs &= p.attrs.align?
+
+ table.attrs.align =
+ attribute align {
+ string
+ }
+ table.attrs &= table.attrs.align?
+
+ tbody.attrs.align =
+ attribute align {
+ string
+ }
+ tbody.attrs &= tbody.attrs.align?
+
+ td.attrs.align =
+ attribute align {
+ string
+ }
+ td.attrs &= td.attrs.align?
+
+ tfoot.attrs.align =
+ attribute align {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.align?
+
+ th.attrs.align =
+ attribute align {
+ string
+ }
+ th.attrs &= th.attrs.align?
+
+ thead.attrs.align =
+ attribute align {
+ string
+ }
+ thead.attrs &= thead.attrs.align?
+
+ tr.attrs.align =
+ attribute align {
+ string
+ }
+ tr.attrs &= tr.attrs.align?
+
+## alink attribute
+
+ body.attrs.alink =
+ attribute alink {
+ string
+ }
+ body.attrs &= body.attrs.alink?
+
+ iframe.attrs.allowtransparency =
+ attribute allowtransparency {
+ string
+ }
+ iframe.attrs &= iframe.attrs.allowtransparency?
+
+## background attribute
+
+ body.attrs.background =
+ attribute background {
+ string
+ }
+ body.attrs &= body.attrs.background?
+
+## color attribute
+
+ hr.attrs.color =
+ attribute color {
+ string
+ }
+ hr.attrs &= hr.attrs.color?
+
+
+## bgcolor attribute
+
+ body.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ body.attrs &= body.attrs.bgcolor?
+
+ table.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ table.attrs &= table.attrs.bgcolor?
+
+ tr.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ tr.attrs &= tr.attrs.bgcolor?
+
+ td.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ td.attrs &= td.attrs.bgcolor?
+
+ th.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ th.attrs &= th.attrs.bgcolor?
+
+## border attribute
+
+ object.attrs.border =
+ attribute border {
+ string
+ }
+ object.attrs &= object.attrs.border?
+
+## cellpadding attribute
+
+ table.attrs.cellpadding =
+ attribute cellpadding {
+ string
+ }
+ table.attrs &= table.attrs.cellpadding?
+
+## cellspacing attribute
+
+ table.attrs.cellspacing =
+ attribute cellspacing {
+ string
+ }
+ table.attrs &= table.attrs.cellspacing?
+
+## char attribute
+
+ col.attrs.char =
+ attribute char {
+ string
+ }
+ col.attrs &= col.attrs.char?
+
+ colgroup.attrs.char =
+ attribute char {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.char?
+
+ tbody.attrs.char =
+ attribute char {
+ string
+ }
+ tbody.attrs &= tbody.attrs.char?
+
+ td.attrs.char =
+ attribute char {
+ string
+ }
+ td.attrs &= td.attrs.char?
+
+ tfoot.attrs.char =
+ attribute char {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.char?
+
+ th.attrs.char =
+ attribute char {
+ string
+ }
+ th.attrs &= th.attrs.char?
+
+ thead.attrs.char =
+ attribute char {
+ string
+ }
+ thead.attrs &= thead.attrs.char?
+
+ tr.attrs.char =
+ attribute char {
+ string
+ }
+ tr.attrs &= tr.attrs.char?
+
+## charoff attribute
+
+ col.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ col.attrs &= col.attrs.charoff?
+
+ colgroup.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.charoff?
+
+ tbody.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ tbody.attrs &= tbody.attrs.charoff?
+
+ td.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ td.attrs &= td.attrs.charoff?
+
+ tfoot.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.charoff?
+
+ th.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ th.attrs &= th.attrs.charoff?
+
+ thead.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ thead.attrs &= thead.attrs.charoff?
+
+ tr.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ tr.attrs &= tr.attrs.charoff?
+
+## clear attribute
+
+ br.attrs.clear =
+ attribute clear {
+ string
+ }
+ br.attrs &= br.attrs.clear?
+
+## compact attribute
+
+ dl.attrs.compact =
+ attribute compact {
+ string
+ }
+ dl.attrs &= dl.attrs.compact?
+
+ menu.attrs.compact =
+ attribute compact {
+ string
+ }
+ menu.attrs &= menu.attrs.compact?
+
+ ol.attrs.compact =
+ attribute compact {
+ string
+ }
+ ol.attrs &= ol.attrs.compact?
+
+ ul.attrs.compact =
+ attribute compact {
+ string
+ }
+ ul.attrs &= ul.attrs.compact?
+
+## frame attribute
+
+ table.attrs.frame =
+ attribute frame {
+ string
+ }
+ table.attrs &= table.attrs.frame?
+
+## frameborder attribute
+
+ iframe.attrs.frameborder =
+ attribute frameborder {
+ string
+ }
+ iframe.attrs &= iframe.attrs.frameborder?
+
+## height attribute
+
+ td.attrs.height =
+ attribute height {
+ string
+ }
+ td.attrs &= td.attrs.height?
+
+ th.attrs.height =
+ attribute height {
+ string
+ }
+ th.attrs &= th.attrs.height?
+
+## hspace attribute
+
+ img.attrs.hspace =
+ attribute hspace {
+ string
+ }
+ img.attrs &= img.attrs.hspace?
+
+ object.attrs.hspace =
+ attribute hspace {
+ string
+ }
+ object.attrs &= object.attrs.hspace?
+
+## link attribute
+
+ body.attrs.link =
+ attribute link {
+ string
+ }
+ body.attrs &= body.attrs.link?
+
+## marginbottom attribute
+
+ body.attrs.marginbottom =
+ attribute marginbottom {
+ string
+ }
+ body.attrs &= body.attrs.marginbottom?
+
+## marginheight attribute
+
+ body.attrs.marginheight =
+ attribute marginheight {
+ string
+ }
+ body.attrs &= body.attrs.marginheight?
+
+ iframe.attrs.marginheight =
+ attribute marginheight {
+ string
+ }
+ iframe.attrs &= iframe.attrs.marginheight?
+
+## marginleft attribute
+
+ body.attrs.marginleft =
+ attribute marginleft {
+ string
+ }
+ body.attrs &= body.attrs.marginleft?
+
+## marginright attribute
+
+ body.attrs.marginright =
+ attribute marginright {
+ string
+ }
+ body.attrs &= body.attrs.marginright?
+
+## margintop attribute
+
+ body.attrs.margintop =
+ attribute margintop {
+ string
+ }
+ body.attrs &= body.attrs.margintop?
+
+## marginwidth attribute
+
+ body.attrs.marginwidth =
+ attribute marginwidth {
+ string
+ }
+ body.attrs &= body.attrs.marginwidth?
+
+ iframe.attrs.marginwidth =
+ attribute marginwidth {
+ string
+ }
+ iframe.attrs &= iframe.attrs.marginwidth?
+
+## noshade attribute
+
+ hr.attrs.noshade =
+ attribute noshade {
+ string
+ }
+ hr.attrs &= hr.attrs.noshade?
+
+## nowrap attribute
+
+ td.attrs.nowrap =
+ attribute nowrap {
+ string
+ }
+ td.attrs &= td.attrs.nowrap?
+
+ th.attrs.nowrap =
+ attribute nowrap {
+ string
+ }
+ th.attrs &= th.attrs.nowrap?
+
+## rules attribute
+
+ table.attrs.rules =
+ attribute rules {
+ string
+ }
+ table.attrs &= table.attrs.rules?
+
+## datapagesize attribute
+
+ table.attrs.datapagesize =
+ attribute datapagesize {
+ string
+ }
+ table.attrs &= table.attrs.datapagesize?
+
+## scrolling attribute
+
+ iframe.attrs.scrolling =
+ attribute scrolling {
+ string
+ }
+ iframe.attrs &= iframe.attrs.scrolling?
+
+## size attribute
+
+ hr.attrs.size =
+ attribute size {
+ string
+ }
+ hr.attrs &= hr.attrs.size?
+
+## summary attribute
+
+ table.attrs.summary =
+ attribute summary {
+ string
+ }
+ table.attrs &= table.attrs.summary?
+
+## text attribute
+
+ body.attrs.text =
+ attribute text {
+ string
+ }
+ body.attrs &= body.attrs.text?
+
+## type attribute
+
+ li.attrs.type =
+ attribute type {
+ string
+ }
+ li.attrs &= li.attrs.type?
+ oli.attrs &= li.attrs.type?
+
+ ul.attrs.type =
+ attribute type {
+ string
+ }
+ ul.attrs &= ul.attrs.type?
+
+## valign attribute
+
+ col.attrs.valign =
+ attribute valign {
+ string
+ }
+ col.attrs &= col.attrs.valign?
+
+ colgroup.attrs.valign =
+ attribute valign {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.valign?
+
+ table.attrs.valign =
+ attribute valign {
+ string
+ }
+ table.attrs &= table.attrs.valign?
+
+ tbody.attrs.valign =
+ attribute valign {
+ string
+ }
+ tbody.attrs &= tbody.attrs.valign?
+
+ td.attrs.valign =
+ attribute valign {
+ string
+ }
+ td.attrs &= td.attrs.valign?
+
+ tfoot.attrs.valign =
+ attribute valign {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.valign?
+
+ th.attrs.valign =
+ attribute valign {
+ string
+ }
+ th.attrs &= th.attrs.valign?
+
+ thead.attrs.valign =
+ attribute valign {
+ string
+ }
+ thead.attrs &= thead.attrs.valign?
+
+ tr.attrs.valign =
+ attribute valign {
+ string
+ }
+ tr.attrs &= tr.attrs.valign?
+
+## vlink attribute
+
+ body.attrs.vlink =
+ attribute vlink {
+ string
+ }
+ body.attrs &= body.attrs.vlink?
+
+## vspace attribute
+
+ img.attrs.vspace =
+ attribute vspace {
+ string
+ }
+ img.attrs &= img.attrs.vspace?
+
+ object.attrs.vspace =
+ attribute vspace {
+ string
+ }
+ object.attrs &= object.attrs.vspace?
+
+## width attribute
+
+ col.attrs.width =
+ attribute width {
+ string
+ }
+ col.attrs &= col.attrs.width?
+
+ colgroup.attrs.width =
+ attribute width {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.width?
+
+ hr.attrs.width =
+ attribute width {
+ string
+ }
+ hr.attrs &= hr.attrs.width?
+
+ pre.attrs.width =
+ attribute width {
+ string
+ }
+ pre.attrs &= pre.attrs.width?
+
+ table.attrs.width =
+ attribute width {
+ string
+ }
+ table.attrs &= table.attrs.width?
+
+ td.attrs.width =
+ attribute width {
+ string
+ }
+ td.attrs &= td.attrs.width?
+
+ th.attrs.width =
+ attribute width {
+ string
+ }
+ th.attrs &= th.attrs.width?
+
+## event attribute
+
+ script.attrs.event =
+ attribute event {
+ string
+ }
+ script.attrs.imported &= script.attrs.event?
+ script.attrs.embedded &= script.attrs.event?
+
+## for attribute
+
+ script.attrs.for =
+ attribute for {
+ string
+ }
+ script.attrs.imported &= script.attrs.for?
+ script.attrs.embedded &= script.attrs.for?
+
+## datafld attribute
+
+ legacy.attrs.datafld =
+ attribute datafld {
+ string
+ }
+ span.attrs &= legacy.attrs.datafld?
+ div.attrs &= legacy.attrs.datafld?
+ object.attrs &= legacy.attrs.datafld?
+ input.text.attrs &= legacy.attrs.datafld?
+ input.password.attrs &= legacy.attrs.datafld?
+ input.checkbox.attrs &= legacy.attrs.datafld?
+ input.radio.attrs &= legacy.attrs.datafld?
+ input.button.attrs &= legacy.attrs.datafld?
+ input.submit.attrs &= legacy.attrs.datafld?
+ input.reset.attrs &= legacy.attrs.datafld?
+ input.file.attrs &= legacy.attrs.datafld?
+ input.image.attrs &= legacy.attrs.datafld?
+ input.datetime.attrs &= legacy.attrs.datafld?
+ input.datetime-local.attrs &= legacy.attrs.datafld?
+ input.date.attrs &= legacy.attrs.datafld?
+ input.month.attrs &= legacy.attrs.datafld?
+ input.time.attrs &= legacy.attrs.datafld?
+ input.week.attrs &= legacy.attrs.datafld?
+ input.number.attrs &= legacy.attrs.datafld?
+ input.range.attrs &= legacy.attrs.datafld?
+ input.email.attrs &= legacy.attrs.datafld?
+ input.url.attrs &= legacy.attrs.datafld?
+ input.search.attrs &= legacy.attrs.datafld?
+ input.tel.attrs &= legacy.attrs.datafld?
+ input.color.attrs &= legacy.attrs.datafld?
+ select.attrs &= legacy.attrs.datafld?
+ textarea.attrs &= legacy.attrs.datafld?
+ button.submit.attrs &= legacy.attrs.datafld?
+ button.reset.attrs &= legacy.attrs.datafld?
+ button.button.attrs &= legacy.attrs.datafld?
+ table.attrs &= legacy.attrs.datafld?
+
+## dataformatas attribute
+
+ legacy.attrs.dataformatas =
+ attribute dataformatas {
+ string
+ }
+ span.attrs &= legacy.attrs.dataformatas?
+ div.attrs &= legacy.attrs.dataformatas?
+ object.attrs &= legacy.attrs.dataformatas?
+ input.attrs &= legacy.attrs.dataformatas?
+ input.text.attrs &= legacy.attrs.dataformatas?
+ input.password.attrs &= legacy.attrs.dataformatas?
+ input.checkbox.attrs &= legacy.attrs.dataformatas?
+ input.radio.attrs &= legacy.attrs.dataformatas?
+ input.button.attrs &= legacy.attrs.dataformatas?
+ input.submit.attrs &= legacy.attrs.dataformatas?
+ input.reset.attrs &= legacy.attrs.dataformatas?
+ input.file.attrs &= legacy.attrs.dataformatas?
+ input.image.attrs &= legacy.attrs.dataformatas?
+ input.datetime.attrs &= legacy.attrs.dataformatas?
+ input.datetime-local.attrs &= legacy.attrs.dataformatas?
+ input.date.attrs &= legacy.attrs.dataformatas?
+ input.month.attrs &= legacy.attrs.dataformatas?
+ input.time.attrs &= legacy.attrs.dataformatas?
+ input.week.attrs &= legacy.attrs.dataformatas?
+ input.number.attrs &= legacy.attrs.dataformatas?
+ input.range.attrs &= legacy.attrs.dataformatas?
+ input.email.attrs &= legacy.attrs.dataformatas?
+ input.url.attrs &= legacy.attrs.dataformatas?
+ input.search.attrs &= legacy.attrs.dataformatas?
+ input.tel.attrs &= legacy.attrs.dataformatas?
+ input.color.attrs &= legacy.attrs.dataformatas?
+ select.attrs &= legacy.attrs.dataformatas?
+ textarea.attrs &= legacy.attrs.dataformatas?
+ button.submit.attrs &= legacy.attrs.dataformatas?
+ button.reset.attrs &= legacy.attrs.dataformatas?
+ button.button.attrs &= legacy.attrs.dataformatas?
+ table.attrs &= legacy.attrs.dataformatas?
+
+## datasrc attribute
+
+ legacy.attrs.datasrc =
+ attribute datasrc {
+ string
+ }
+ span.attrs &= legacy.attrs.datasrc?
+ div.attrs &= legacy.attrs.datasrc?
+ object.attrs &= legacy.attrs.datasrc?
+ input.text.attrs &= legacy.attrs.datasrc?
+ input.password.attrs &= legacy.attrs.datasrc?
+ input.checkbox.attrs &= legacy.attrs.datasrc?
+ input.radio.attrs &= legacy.attrs.datasrc?
+ input.button.attrs &= legacy.attrs.datasrc?
+ input.submit.attrs &= legacy.attrs.datasrc?
+ input.reset.attrs &= legacy.attrs.datasrc?
+ input.file.attrs &= legacy.attrs.datasrc?
+ input.image.attrs &= legacy.attrs.datasrc?
+ input.datetime.attrs &= legacy.attrs.datasrc?
+ input.datetime-local.attrs &= legacy.attrs.datasrc?
+ input.date.attrs &= legacy.attrs.datasrc?
+ input.month.attrs &= legacy.attrs.datasrc?
+ input.time.attrs &= legacy.attrs.datasrc?
+ input.week.attrs &= legacy.attrs.datasrc?
+ input.number.attrs &= legacy.attrs.datasrc?
+ input.range.attrs &= legacy.attrs.datasrc?
+ input.email.attrs &= legacy.attrs.datasrc?
+ input.url.attrs &= legacy.attrs.datasrc?
+ input.search.attrs &= legacy.attrs.datasrc?
+ input.tel.attrs &= legacy.attrs.datasrc?
+ input.color.attrs &= legacy.attrs.datasrc?
+ select.attrs &= legacy.attrs.datasrc?
+ textarea.attrs &= legacy.attrs.datasrc?
+ button.submit.attrs &= legacy.attrs.datasrc?
+ button.reset.attrs &= legacy.attrs.datasrc?
+ button.button.attrs &= legacy.attrs.datasrc?
+ table.attrs &= legacy.attrs.datasrc?
diff --git a/xml/relaxng/src/resources/html5-schema/media.rnc b/xml/relaxng/src/resources/html5-schema/html5/media.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/media.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/media.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/meta-ext.rnc b/xml/relaxng/src/resources/html5-schema/html5/meta-ext.rnc
new file mode 100644
index 0000000..cc9a44f
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/meta-ext.rnc
@@ -0,0 +1,62 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+## "Content-Language" pragma directive: <meta http-equiv='Content-Language'>
+
+ meta.http-equiv.content-language.elem =
+ element meta { meta.inner & meta.http-equiv.content-language.attrs }
+ meta.http-equiv.content-language.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.content-language
+ & meta.http-equiv.attrs.content.content-language
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.content-language =
+ attribute http-equiv {
+ w:string "content-language"
+ }
+ meta.http-equiv.attrs.content.content-language =
+ attribute content {
+ common.data.string
+ }
+
+ common.elem.metadata |= meta.http-equiv.content-language.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+## "X-UA-Compatible" pragma directive: <meta http-equiv='X-UA-Compatible'>
+
+ meta.http-equiv.x-ua-compatible.elem =
+ element meta { meta.inner & meta.http-equiv.x-ua-compatible.attrs }
+ meta.http-equiv.x-ua-compatible.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.x-ua-compatible
+ & meta.http-equiv.attrs.content.x-ua-compatible
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.x-ua-compatible =
+ attribute http-equiv {
+ w:string "x-ua-compatible"
+ }
+ meta.http-equiv.attrs.content.x-ua-compatible =
+ attribute content {
+ common.data.string
+ }
+
+ common.elem.metadata |= meta.http-equiv.x-ua-compatible.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+ html.inner |= (
+ head.inner,
+ body.inner
+ )
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/html5/meta.rnc b/xml/relaxng/src/resources/html5-schema/html5/meta.rnc
new file mode 100755
index 0000000..b5e810a
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/meta.rnc
@@ -0,0 +1,364 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Global Structure & Metadata #
+# #####################################################################
+
+## Root Element: <html>
+
+ html.elem =
+ element html { html.inner & html.attrs }
+ html.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ html.inner =
+ ( head.elem
+ , body.elem
+ )
+
+## Metadata Container: <head>
+
+ head.elem =
+ element head { head.inner & head.attrs }
+ head.attrs =
+ ( common.attrs
+# & head.attrs.profile?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+# head.attrs.profile =
+# attribute profile {
+# common.data.uris #REVISIT should these be absolute (zero or more)
+# }
+ head.inner =
+ ( title.elem
+ & base.elem? # REVISIT need a non-schema checker or Schematron
+ & common.inner.metadata # Limit encoding decl position in Schematron
+ )
+# head.inner =
+# ( meta.elem.encoding?
+# , ( title.elem
+# & base.elem? # REVISIT need a non-schema checker or Schematron
+# & common.inner.metadata
+# )
+# )
+
+## Content Container: <body>
+
+ body.elem =
+ element body { body.inner & body.attrs }
+ body.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.implicit.document
+ )?
+ & body.attrs.onafterprint?
+ & body.attrs.onbeforeprint?
+ & body.attrs.onbeforeunload?
+ & body.attrs.onhashchange?
+ & body.attrs.onmessage?
+ & body.attrs.onoffline?
+ & body.attrs.ononline?
+ & body.attrs.onpagehide?
+ & body.attrs.onpageshow?
+ & body.attrs.onpopstate?
+ & body.attrs.onresize?
+ & body.attrs.onstorage?
+ & body.attrs.onunload?
+ )
+ body.inner =
+ ( common.inner.flow )
+
+ body.attrs.onafterprint =
+ attribute onafterprint { common.data.functionbody }
+ body.attrs.onbeforeprint =
+ attribute onbeforeprint { common.data.functionbody }
+ body.attrs.onbeforeunload =
+ attribute onbeforeunload { common.data.functionbody }
+ body.attrs.onhashchange =
+ attribute onhashchange { common.data.functionbody }
+ body.attrs.onmessage =
+ attribute onmessage { common.data.functionbody }
+ body.attrs.onoffline =
+ attribute onoffline { common.data.functionbody }
+ body.attrs.ononline =
+ attribute ononline { common.data.functionbody }
+ body.attrs.onpopstate =
+ attribute onpopstate { common.data.functionbody }
+ body.attrs.onpagehide =
+ attribute onpagehide { common.data.functionbody }
+ body.attrs.onpageshow =
+ attribute onpageshow { common.data.functionbody }
+ body.attrs.onredo =
+ attribute onredo { common.data.functionbody }
+ body.attrs.onresize =
+ attribute onresize { common.data.functionbody }
+ body.attrs.onstorage =
+ attribute onstorage { common.data.functionbody }
+ body.attrs.onundo =
+ attribute onundo { common.data.functionbody }
+ body.attrs.onunload =
+ attribute onunload { common.data.functionbody }
+
+## Document Title: <title>
+
+ title.elem =
+ element title { title.inner & title.attrs }
+ title.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ title.inner =
+ ( text )
+
+## Base URI: <base>
+
+ base.elem =
+ element base { base.inner & base.attrs }
+ base.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & ( ( base.attrs.href
+ & base.attrs.target?
+ )
+ | base.attrs.target
+ )
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ base.attrs.href =
+ attribute href {
+ common.data.uri
+ }
+ base.attrs.target =
+ attribute target {
+ common.data.browsing-context-or-keyword
+ }
+ base.inner =
+ ( empty )
+
+## Global Relationships: <link>
+
+ link.elem =
+ element link { link.inner & link.attrs }
+ link.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & link.attrs.href
+ & link.attrs.rel
+ & shared-hyperlink.attrs.hreflang?
+ & shared-hyperlink.attrs.media?
+ & shared-hyperlink.attrs.type?
+ & link.attrs.sizes?
+ # link.attrs.title included in common.attrs
+ & ( common.attrs.aria.role.link
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ link.attrs.href =
+ attribute href {
+ common.data.uri.non-empty
+ }
+ link.attrs.rel =
+ attribute rel {
+ w:link-rel
+ }
+ link.attrs.sizes =
+ attribute sizes {
+ w:string "any" | common.data.sizes
+ }
+ link.inner =
+ ( empty )
+
+ common.elem.metadata |= link.elem
+
+## Global Style: <style>
+
+ style.elem =
+ element style { style.inner & style.attrs }
+ style.attrs =
+ ( common.attrs
+ & style.attrs.type?
+ & style.attrs.media?
+ # style.attrs.title included in common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ style.attrs.type =
+ attribute type {
+ common.data.mimetype
+ }
+ style.attrs.media =
+ attribute media {
+ common.data.mediaquery
+ }
+ style.inner =
+ ( common.inner.anything )
+
+ common.elem.metadata |= style.elem
+
+## Scoped Style: <style scoped>
+
+ style.elem.scoped =
+ element style { style.inner & style.scoped.attrs }
+ style.scoped.attrs =
+ ( common.attrs
+ & style.attrs.type?
+ & style.attrs.media?
+ & style.attrs.scoped
+ # style.attrs.title included in common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ style.attrs.scoped =
+ attribute scoped {
+ w:string "scoped" | w:string ""
+ }
+
+## Name-Value Metadata: <meta name>
+
+ meta.name.elem =
+ element meta { meta.inner & meta.name.attrs }
+ meta.name.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.name.attrs.name
+ & meta.name.attrs.content
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.name.attrs.name =
+ attribute name {
+ w:meta-name
+ }
+ meta.name.attrs.content =
+ attribute content {
+ string
+ }
+ meta.inner =
+ ( empty )
+
+ common.elem.metadata |= meta.name.elem
+
+## "refresh" pragma directive: <meta http-equiv='refresh'>
+
+ meta.http-equiv.refresh.elem =
+ element meta { meta.inner & meta.http-equiv.refresh.attrs }
+ meta.http-equiv.refresh.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.refresh
+ & meta.http-equiv.attrs.content.refresh
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.refresh =
+ attribute http-equiv {
+ w:string "refresh"
+ }
+ meta.http-equiv.attrs.content.refresh =
+ attribute content {
+ common.data.refresh
+ }
+ common.elem.metadata |= meta.http-equiv.refresh.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+## "default-style" pragma directive: <meta http-equiv='default-style'>
+
+ meta.http-equiv.default-style.elem =
+ element meta { meta.inner & meta.http-equiv.default-style.attrs }
+ meta.http-equiv.default-style.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.default-style
+ & meta.http-equiv.attrs.content.default-style
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.default-style =
+ attribute http-equiv {
+ w:string "default-style"
+ }
+ meta.http-equiv.attrs.content.default-style =
+ attribute content {
+ common.data.default-style
+ }
+
+ common.elem.metadata |= meta.http-equiv.default-style.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+## Inline Character Encoding Statement for HTML: <meta charset>
+
+ meta.charset.elem =
+ element meta { meta.inner & meta.charset.attrs }
+ meta.charset.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.charset.attrs.charset
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.charset.attrs.charset =
+ attribute charset {
+ (common.data.charset & HTMLonly)
+ | (xsd:string {
+ pattern = "[uU][tT][fF]-8"
+ } & XMLonly )
+ }
+
+## Inline Character Encoding Statement for HTML: <meta http-equiv='content-type'>
+
+ meta.http-equiv.content-type.elem =
+ element meta { meta.inner & meta.http-equiv.content-type.attrs }
+ & HTMLonly
+ meta.http-equiv.content-type.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.content-type
+ & meta.http-equiv.attrs.content.content-type
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.content-type =
+ attribute http-equiv {
+ w:string "content-type"
+ }
+ meta.http-equiv.attrs.content.content-type =
+ attribute content {
+ common.data.meta-charset
+ }
+
+ common.elem.metadata |= ( meta.charset.elem | meta.http-equiv.content-type.elem )
diff --git a/xml/relaxng/src/resources/html5-schema/microdata.rnc b/xml/relaxng/src/resources/html5-schema/html5/microdata.rnc
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/microdata.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/microdata.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/phrase.rnc b/xml/relaxng/src/resources/html5-schema/html5/phrase.rnc
new file mode 100755
index 0000000..349cdae
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/phrase.rnc
@@ -0,0 +1,395 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Phrase Markup #
+# #####################################################################
+
+## Contextual Hyperlink: <a>
+
+ a.elem.phrasing =
+ element a { a.inner.phrasing & a.attrs }
+ a.elem.flow =
+ element a { a.inner.flow & a.attrs }
+ a.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & a.attrs.name?
+ & shared-hyperlink.attrs.download?
+ & shared-hyperlink.attrs.href?
+ & shared-hyperlink.attrs.target?
+ & shared-hyperlink.attrs.rel?
+ & shared-hyperlink.attrs.hreflang?
+ & shared-hyperlink.attrs.type?
+ & shared-hyperlink.attrs.ping?
+ & ( common.attrs.aria.implicit.link
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.checkbox
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.treeitem
+ )?
+ )
+ a.attrs.name =
+ attribute name {
+ common.data.id # XXX not what the spec says
+ }
+ a.inner.phrasing =
+ ( common.inner.phrasing )
+ a.inner.flow =
+ ( common.inner.transparent.flow )
+
+ common.elem.phrasing |= a.elem.phrasing
+ common.elem.flow |= a.elem.flow
+
+## Shared hyperlink attributes
+
+ shared-hyperlink.attrs.download =
+ attribute download {
+ string
+ }
+ shared-hyperlink.attrs.href =
+ attribute href {
+ common.data.uri
+ }
+ shared-hyperlink.attrs.target =
+ attribute target {
+ common.data.browsing-context-or-keyword
+ }
+ shared-hyperlink.attrs.rel =
+ attribute rel {
+ w:a-rel
+ }
+ shared-hyperlink.attrs.hreflang =
+ attribute hreflang {
+ common.data.langcode
+ }
+ shared-hyperlink.attrs.media =
+ attribute media {
+ common.data.mediaquery
+ }
+ shared-hyperlink.attrs.type =
+ attribute type {
+ common.data.mimetype
+ }
+
+## Emphatic Stress: <em>
+
+ em.elem =
+ element em { em.inner & em.attrs }
+ em.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ em.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= em.elem
+
+## Strong Importance: <strong>
+
+ strong.elem =
+ element strong { strong.inner & strong.attrs }
+ strong.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ strong.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= strong.elem
+
+## Small Print and Side Comments: <small>
+
+ small.elem =
+ element small { small.inner & small.attrs }
+ small.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ small.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= small.elem
+
+## Marked (Highlighted) Text: <mark>
+
+ mark.elem =
+ element mark { mark.inner & mark.attrs }
+ & v5only
+ mark.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ mark.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= mark.elem
+
+## Abbreviation: <abbr>
+
+ abbr.elem =
+ element abbr { abbr.inner & abbr.attrs }
+ abbr.attrs =
+ ( common.attrs
+ # abbr.attrs.title included in common.attrs
+ & common.attrs.aria?
+ )
+ abbr.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= abbr.elem
+
+## Defining Instance: <dfn>
+
+ dfn.elem =
+ element dfn { dfn.inner & dfn.attrs }
+ dfn.attrs =
+ ( common.attrs
+ # dfn.attrs.title included in common.attrs
+ & common.attrs.aria?
+ )
+ dfn.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= dfn.elem
+
+## Italic: <i>
+
+ i.elem =
+ element i { i.inner & i.attrs }
+ i.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ i.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= i.elem
+
+## Bold: <b>
+
+ b.elem =
+ element b { b.inner & b.attrs }
+ b.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ b.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= b.elem
+
+## Struck Text: <s>
+
+ s.elem =
+ element s { s.inner & s.attrs }
+ s.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ s.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= s.elem
+
+## Underline: <u>
+
+ u.elem =
+ element u { u.inner & u.attrs }
+ u.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ u.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= u.elem
+
+## Code Fragment: <code>
+
+ code.elem =
+ element code { code.inner & code.attrs }
+ code.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ code.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= code.elem
+
+## Variable or Placeholder: <var>
+
+ var.elem =
+ element var { var.inner & var.attrs }
+ var.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ var.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= var.elem
+
+## (Sample) Output: <samp>
+
+ samp.elem =
+ element samp { samp.inner & samp.attrs }
+ samp.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ samp.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= samp.elem
+
+## User Input: <kbd>
+
+ kbd.elem =
+ element kbd { kbd.inner & kbd.attrs }
+ kbd.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ kbd.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= kbd.elem
+
+## Superscript: <sup>
+
+ sup.elem =
+ element sup { sup.inner & sup.attrs }
+ sup.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ sup.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= sup.elem
+
+## Subscript: <sub>
+
+ sub.elem =
+ element sub { sub.inner & sub.attrs }
+ sub.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ sub.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= sub.elem
+
+## Quotation: <q>
+
+ q.elem =
+ element q { q.inner & q.attrs }
+ q.attrs =
+ ( common.attrs
+ & q.attrs.cite?
+ & common.attrs.aria?
+ )
+ q.attrs.cite =
+ attribute cite {
+ common.data.uri
+ }
+ q.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= q.elem
+
+## Title of Work: <cite>
+
+ cite.elem =
+ element cite { cite.inner & cite.attrs }
+ cite.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ cite.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= cite.elem
+
+## Generic Span: <span>
+
+ span.elem =
+ element span { span.inner & span.attrs }
+ span.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ span.inner =
+ ( common.inner.phrasing ) # REVISIT allow ol and ul?
+
+ common.elem.phrasing |= span.elem
+
+## Bidirectional Override: <bdo>
+
+ bdo.elem =
+ element bdo { bdo.inner & bdo.attrs }
+ bdo.attrs =
+ ( common.attrs # dir required in Schematron
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ bdo.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= bdo.elem
+
+## Bidirectional Isolate: <bdi>
+
+ bdi.elem =
+ element bdi { bdi.inner & bdi.attrs }
+ bdi.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ bdi.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= bdi.elem
+
+## Line Break: <br>
+
+ br.elem =
+ element br { br.inner & br.attrs }
+ br.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ br.inner =
+ ( empty )
+
+ common.elem.phrasing |= br.elem
+
+## Line-break opportunity: <wbr>
+
+ wbr.elem =
+ element wbr { wbr.inner & wbr.attrs }
+ wbr.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ wbr.inner =
+ ( empty )
+
+ common.elem.phrasing |= wbr.elem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc b/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc
new file mode 100644
index 0000000..b8513d7
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/rdfa.rnc
@@ -0,0 +1,281 @@
+nonRDFaLite = empty
+# #####################################################################
+## RELAX NG Schema for HTML 5: RDFa 1.1 and RDFa Lite 1.1 #
+# #####################################################################
+
+# #####################################################################
+## RDFa Datatypes #
+# #####################################################################
+
+common.data.rdfa.safecurie =
+ xsd:string {
+ pattern = "\[(([\i-[:]][\c-[:]]*)?:)?[^\s]+\]"
+ minLength = "3"
+ }
+common.data.rdfa.curie =
+ xsd:string {
+ pattern = "(([\i-[:]][\c-[:]]*)?:)?[^\s]+"
+ minLength = "1"
+ }
+common.data.rdfa.term =
+ xsd:string {
+ pattern = "[\i-[:]][/\c-[:]]*"
+ }
+
+# #####################################################################
+## RDFa Attributes #
+# #####################################################################
+
+common.attrs.rdfa &=
+ ( common.attrs.rdfa.about?
+ & common.attrs.rdfa.prefix?
+ & common.attrs.rdfa.property?
+ & common.attrs.rdfa.typeof?
+ & common.attrs.rdfa.vocab?
+ & common.attrs.rdfa.content?
+ & common.attrs.rdfa.datatype?
+ & common.attrs.rdfa.rel?
+ & common.attrs.rdfa.resource?
+ & common.attrs.rdfa.rev?
+ & common.attrs.rdfa.inlist?
+ )
+ common.attrs.rdfa.prefix =
+ attribute prefix {
+ (
+ xsd:string {
+ pattern = "\s*([\i-[:]][\c-[:]]*: [^ ]+)(\s+[\i-[:]][\c-[:]]*: [^ ]+)*\s*"
+ }
+ | string ""
+ )
+ }
+ common.attrs.rdfa.property =
+ attribute property {
+ (
+ list {
+ ( common.data.rdfa.term
+ | common.data.rdfa.curie
+ | common.data.uri.absolute
+ )+
+ }
+ | string ""
+ )
+ }
+ common.attrs.rdfa.resource =
+ attribute resource {
+ ( common.data.rdfa.safecurie
+ | common.data.rdfa.curie
+ | common.data.uri
+ )
+ }
+ common.attrs.rdfa.typeof =
+ attribute typeof {
+ (
+ list {
+ ( common.data.rdfa.term
+ | common.data.rdfa.curie
+ | common.data.uri.absolute
+ )+
+ }
+ | string ""
+ )
+ }
+ common.attrs.rdfa.vocab =
+ attribute vocab {
+ ( common.data.uri.absolute
+ | string ""
+ )
+ }
+ common.attrs.rdfa.about =
+ attribute about {
+ ( common.data.rdfa.safecurie
+ | common.data.rdfa.curie
+ | common.data.uri
+ )
+ } & nonRDFaLite
+ common.attrs.rdfa.content =
+ attribute content {
+ string
+ } & nonRDFaLite
+ common.attrs.rdfa.datatype =
+ attribute datatype {
+ ( common.data.rdfa.term
+ | common.data.rdfa.curie
+ | common.data.uri.absolute
+ | string ""
+ )
+ } & nonRDFaLite
+ common.attrs.rdfa.rel =
+ attribute rel {
+ (
+ list {
+ ( common.data.rdfa.term
+ | common.data.rdfa.curie
+ | common.data.uri.absolute
+ )+
+ }
+ | string ""
+ )
+ } & nonRDFaLite
+ common.attrs.rdfa.rev =
+ attribute rev {
+ (
+ list {
+ ( common.data.rdfa.term
+ | common.data.rdfa.curie
+ | common.data.uri.absolute
+ )+
+ }
+ | string ""
+ )
+ } & nonRDFaLite
+ common.attrs.rdfa.inlist =
+ attribute inlist {
+ string
+ } & nonRDFaLite
+
+common.attrs.rdfa.no-rel &=
+ ( common.attrs.rdfa.about?
+ & common.attrs.rdfa.prefix?
+ & common.attrs.rdfa.property?
+ & common.attrs.rdfa.typeof?
+ & common.attrs.rdfa.vocab?
+ & common.attrs.rdfa.content?
+ & common.attrs.rdfa.datatype?
+ & common.attrs.rdfa.resource?
+ & common.attrs.rdfa.rev?
+ & common.attrs.rdfa.inlist?
+ )
+common.attrs.rdfa.no-rel-rev &=
+ ( common.attrs.rdfa.about?
+ & common.attrs.rdfa.prefix?
+ & common.attrs.rdfa.property?
+ & common.attrs.rdfa.typeof?
+ & common.attrs.rdfa.vocab?
+ & common.attrs.rdfa.content?
+ & common.attrs.rdfa.datatype?
+ & common.attrs.rdfa.resource?
+ & common.attrs.rdfa.inlist?
+ )
+common.attrs.rdfa.no-content-noproperty &=
+ ( common.attrs.rdfa.about?
+ & common.attrs.rdfa.prefix?
+ & common.attrs.rdfa.typeof?
+ & common.attrs.rdfa.vocab?
+ & common.attrs.rdfa.datatype?
+ & common.attrs.rdfa.resource?
+ & common.attrs.rdfa.inlist?
+ )
+
+common.attrs &= common.attrs.rdfa
+
+a.attrs &= common.attrs.rdfa.no-rel-rev
+area.attrs &= common.attrs.rdfa.no-rel
+base.attrs &= common.attrs.rdfa.no-rel
+
+link.rdfa.elem.metadata =
+ element link { link.inner & link.rdfa.attrs.metadata }
+link.rdfa.elem.phrasing =
+ element link { link.inner & link.rdfa.attrs.phrasing }
+link.rdfa.attrs.metadata =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & ( ( common.attrs.rdfa.property
+ & ( link.attrs.rel
+ | common.attrs.rdfa.rel
+ )?
+ )
+ |
+ ( common.attrs.rdfa.property?
+ & ( link.attrs.rel
+ | common.attrs.rdfa.rel
+ )
+ )
+ )
+ & link.attrs.href
+ & common.attrs.rdfa.about?
+ & common.attrs.rdfa.prefix?
+ & common.attrs.rdfa.typeof?
+ & common.attrs.rdfa.vocab?
+ & common.attrs.rdfa.content?
+ & common.attrs.rdfa.datatype?
+ & common.attrs.rdfa.resource?
+ & common.attrs.rdfa.rev?
+ & common.attrs.rdfa.inlist?
+ & shared-hyperlink.attrs.hreflang?
+ & shared-hyperlink.attrs.media?
+ & shared-hyperlink.attrs.type?
+ & link.attrs.sizes?
+ # link.attrs.title included in common.attrs
+ )
+link.rdfa.attrs.phrasing =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & common.attrs.rdfa.property
+ & ( link.attrs.rel
+ | common.attrs.rdfa.rel
+ )?
+ & ( ( common.attrs.rdfa.resource
+ & link.attrs.href?
+ )
+ |
+ ( common.attrs.rdfa.resource?
+ & link.attrs.href
+ )
+ )
+ & common.attrs.rdfa.about?
+ & common.attrs.rdfa.prefix?
+ & common.attrs.rdfa.typeof?
+ & common.attrs.rdfa.vocab?
+ & common.attrs.rdfa.content?
+ & common.attrs.rdfa.datatype?
+ & common.attrs.rdfa.rev?
+ & common.attrs.rdfa.inlist?
+ & shared-hyperlink.attrs.hreflang?
+ & shared-hyperlink.attrs.media?
+ & shared-hyperlink.attrs.type?
+ & link.attrs.sizes?
+ # link.attrs.title included in common.attrs
+ )
+ common.elem.metadata |= link.rdfa.elem.metadata
+ common.elem.phrasing |= link.rdfa.elem.phrasing
+
+## <meta property=foo content=bar> in head ("name" attribute optional)
+ meta.property.elem =
+ element meta { meta.inner & meta.property.attrs }
+ meta.property.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.name.attrs.name?
+ & common.attrs.rdfa.property
+ & meta.name.attrs.content
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ common.elem.metadata |= meta.property.elem
+
+## <meta property=foo content=bar> in body ("name" attribute disallowed)
+ meta.property-no-name.elem =
+ element meta { meta.inner & meta.property-no-name.attrs }
+ meta.property-no-name.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & common.attrs.rdfa.property
+ & meta.name.attrs.content
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ common.elem.phrasing |= meta.property-no-name.elem
+
+meta.property.attrs &= common.attrs.rdfa.no-content-noproperty
+meta.property-no-name.attrs &= common.attrs.rdfa.no-content-noproperty
+meta.name.attrs &= common.attrs.rdfa.no-content-noproperty
diff --git a/xml/relaxng/src/resources/html5-schema/html5/revision.rnc b/xml/relaxng/src/resources/html5-schema/html5/revision.rnc
new file mode 100755
index 0000000..a357bd4
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/revision.rnc
@@ -0,0 +1,54 @@
+# #####################################################################
+## RELAX NG Schema for HTML 5: Revision Annotations #
+# #####################################################################
+
+## Common Attributes
+
+ edit.attrs.cite =
+ attribute cite {
+ common.data.uri
+ }
+ edit.attrs.datetime =
+ attribute datetime {
+ common.data.datetime | common.data.date
+ }
+
+## Inserts: <ins>
+
+ ins.elem.flow =
+ element ins { ins.inner.flow & ins.attrs }
+ ins.elem.phrasing =
+ element ins { ins.inner.phrasing & ins.attrs }
+ ins.attrs =
+ ( common.attrs
+ & edit.attrs.cite?
+ & edit.attrs.datetime?
+ & common.attrs.aria?
+ )
+ ins.inner.flow =
+ ( common.inner.transparent.flow )
+ ins.inner.phrasing =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= ins.elem.flow
+ common.elem.phrasing |= ins.elem.phrasing
+
+## Deletions: <del>
+
+ del.elem.flow =
+ element del { del.inner.flow & del.attrs }
+ del.elem.phrasing =
+ element del { del.inner.phrasing & del.attrs }
+ del.attrs =
+ ( common.attrs
+ & edit.attrs.cite?
+ & edit.attrs.datetime?
+ & common.attrs.aria?
+ )
+ del.inner.flow =
+ ( common.inner.transparent.flow )
+ del.inner.phrasing =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= del.elem.flow
+ common.elem.phrasing |= del.elem.phrasing
diff --git a/xml/relaxng/src/resources/html5-schema/ruby.rnc b/xml/relaxng/src/resources/html5-schema/html5/ruby.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/ruby.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/ruby.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/sectional.rnc b/xml/relaxng/src/resources/html5-schema/html5/sectional.rnc
new file mode 100755
index 0000000..85a49d9
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/sectional.rnc
@@ -0,0 +1,147 @@
+# #####################################################################
+## RELAX NG Schema for HTML 5: Sectioning Markup #
+# #####################################################################
+
+# #####################################################################
+## Headings
+
+## Heading (Rank 1): <h1>
+
+ h1.elem =
+ element h1 { h1.inner & h1.attrs }
+ h1.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.heading
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ h1.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= h1.elem
+
+## Heading (Rank 2): <h2>
+
+ h2.elem =
+ element h2 { h2.inner & h2.attrs }
+ h2.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.heading
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ h2.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= h2.elem
+
+## Heading (Rank 3): <h3>
+
+ h3.elem =
+ element h3 { h3.inner & h3.attrs }
+ h3.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.heading
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ h3.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= h3.elem
+
+## Heading (Rank 4): <h4>
+
+ h4.elem =
+ element h4 { h4.inner & h4.attrs }
+ h4.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.heading
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ h4.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= h4.elem
+
+## Heading (Rank 5): <h5>
+
+ h5.elem =
+ element h5 { h5.inner & h5.attrs }
+ h5.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.heading
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ h5.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= h5.elem
+
+## Heading (Rank 6): <h6>
+
+ h6.elem =
+ element h6 { h6.inner & h6.attrs }
+ h6.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.heading
+ | common.attrs.aria.role.heading
+ | common.attrs.aria.role.tab
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ h6.inner =
+ ( common.inner.phrasing )
+
+ common.elem.flow |= h6.elem
+
+# #####################################################################
+## Section Meta
+
+## Contact Info: <address>
+
+ address.elem =
+ element address { address.inner & address.attrs }
+ address.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.contentinfo
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ address.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= address.elem
+
+# #####################################################################
+## Quotations
+
+## Block Quotes: <blockquote>
+
+ blockquote.elem =
+ element blockquote { blockquote.inner & blockquote.attrs }
+ blockquote.attrs =
+ ( common.attrs
+ & blockquote.attrs.cite?
+ & common.attrs.aria?
+ )
+ blockquote.attrs.cite =
+ attribute cite {
+ common.data.uri
+ }
+ blockquote.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= blockquote.elem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/structural.rnc b/xml/relaxng/src/resources/html5-schema/html5/structural.rnc
new file mode 100755
index 0000000..9e72b5f
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/structural.rnc
@@ -0,0 +1,135 @@
+# #####################################################################
+## RELAX NG Schema for HTML 5: Block Markup Added in HTML5 #
+# #####################################################################
+
+## Section: <section>
+
+ section.elem =
+ element section { section.inner & section.attrs }
+ section.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.region
+ | common.attrs.aria.role.alert
+ | common.attrs.aria.role.alertdialog
+ | common.attrs.aria.role.contentinfo
+ | common.attrs.aria.role.dialog
+ | common.attrs.aria.role.log
+ | common.attrs.aria.role.marquee
+ | common.attrs.aria.role.region
+ | common.attrs.aria.role.status
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.landmark.main
+ | common.attrs.aria.landmark.search
+ )?
+ )
+ section.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= section.elem
+
+## Navigational Links: <nav>
+
+ nav.elem =
+ element nav { nav.inner & nav.attrs }
+ nav.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.navigation
+ | common.attrs.aria.landmark.navigation
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ nav.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= nav.elem
+
+## Article: <article>
+
+ article.elem =
+ element article { article.inner & article.attrs }
+ article.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.article
+ | common.attrs.aria.landmark.article
+ | common.attrs.aria.landmark.document
+ | common.attrs.aria.landmark.application
+ | common.attrs.aria.landmark.main
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ article.inner =
+ ( style.elem*
+ , common.inner.flow
+ )
+
+ common.elem.flow |= article.elem
+
+## Tangential Aside: <aside>
+
+ aside.elem =
+ element aside { aside.inner & aside.attrs }
+ aside.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.complementary
+ | common.attrs.aria.landmark.note
+ | common.attrs.aria.landmark.complementary
+ | common.attrs.aria.landmark.search
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ aside.inner =
+ ( style.elem*
+ , common.inner.flow
+ )
+
+ common.elem.flow |= aside.elem
+
+## Header: <header>
+
+ header.elem =
+ element header { header.inner & header.attrs }
+ header.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.banner
+ | common.attrs.aria.landmark.banner
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ header.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= header.elem
+
+## Footer: <footer>
+
+ footer.elem =
+ element footer { footer.inner & footer.attrs }
+ footer.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.contentinfo
+ | common.attrs.aria.landmark.contentinfo
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ footer.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= footer.elem
+
+## main content: <main>
+
+ main.elem =
+ element main { main.inner & main.attrs }
+ main.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.main
+ | common.attrs.aria.landmark.main
+ )?
+ )
+ main.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= main.elem
diff --git a/xml/relaxng/src/resources/html5-schema/html5/tables.rnc b/xml/relaxng/src/resources/html5-schema/html5/tables.rnc
new file mode 100755
index 0000000..2aecbcf
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/tables.rnc
@@ -0,0 +1,259 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Tables #
+# #####################################################################
+
+# #####################################################################
+## Table Envelope
+
+## Table Datatypes
+
+# tables.data.multilen =
+# ( common.data.integer.positive
+# | common.data.percent
+# | xsd:token { pattern = "[0-9]+\*" } #REVISIT should this one be string?
+# )
+
+## Table Alignment Attributes
+
+ tables.attrs.alignment =
+ ( tables.attrs.align?
+ & tables.attrs.char?
+ & tables.attrs.valign?
+ )
+ tables.attrs.align =
+ attribute align {
+ ( w:string "left"
+ | w:string "center"
+ | w:string "right"
+ | w:string "justify"
+ | w:string "char"
+ )
+ }
+ tables.attrs.char =
+ attribute char {
+ xsd:string { pattern = "." }
+ }
+ tables.attrs.valign =
+ attribute valign {
+ ( w:string "top"
+ | w:string "middle"
+ | w:string "bottom"
+ | w:string "baseline"
+ )
+ }
+
+## Data Table: <table>
+
+ table.elem =
+ element table { table.inner & table.attrs }
+ table.attrs =
+ ( common.attrs
+ & table.attrs.border?
+ & common.attrs.aria?
+ )
+ table.attrs.border =
+ attribute border {
+ string
+ }
+ table.inner =
+ ( caption.elem?
+ , common.elem.script-supporting*
+ , colgroup.elem*
+ , common.elem.script-supporting*
+ , thead.elem?
+ , common.elem.script-supporting*
+ , ( ( tfoot.elem
+ , common.elem.script-supporting*
+ , ( tbody.elem* | tr.elem+ )
+ , common.elem.script-supporting*
+ )
+ | ( ( tbody.elem* | tr.elem+ )
+ , common.elem.script-supporting*
+ , tfoot.elem?
+ )
+ )
+ )
+
+ common.elem.flow |= table.elem
+
+## Table Caption: <caption>
+
+ caption.elem =
+ element caption { caption.inner & caption.attrs }
+ caption.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ caption.inner =
+ ( common.inner.flow )
+
+# #####################################################################
+## Table Super Structure
+
+## Table Column Group: <colgroup>
+
+ colgroup.elem =
+ element colgroup { colgroup.inner & colgroup.attrs }
+ colgroup.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ colgroup.attrs.span =
+ attribute span {
+ common.data.integer.positive
+ }
+ colgroup.inner =
+ ( ( col.elem*
+ & common.elem.script-supporting*
+ )
+ | colgroup.attrs.span?
+ )
+
+## Table Column: <col>
+
+ col.elem =
+ element col { col.inner & col.attrs }
+ col.attrs =
+ ( common.attrs
+ & col.attrs.span?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ col.attrs.span =
+ attribute span {
+ common.data.integer.positive
+ }
+ col.inner =
+ ( empty )
+
+## Table Header Row Group
+
+ thead.elem =
+ element thead { thead.inner & thead.attrs }
+ thead.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ thead.inner =
+ ( tr.elem*
+ & common.elem.script-supporting*
+ )
+
+## Table Footer Row Group
+
+ tfoot.elem =
+ element tfoot { tfoot.inner & tfoot.attrs }
+ tfoot.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ tfoot.inner =
+ ( tr.elem*
+ & common.elem.script-supporting*
+ )
+
+## Table Row Group
+
+ tbody.elem =
+ element tbody { tbody.inner & tbody.attrs }
+ tbody.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ tbody.inner =
+ ( tr.elem*
+ & common.elem.script-supporting*
+ )
+
+# #####################################################################
+## Cell Structure
+
+## Table Row
+
+ tr.elem =
+ element tr { tr.inner & tr.attrs }
+ tr.attrs =
+ ( common.attrs
+ & common.attrs.aria?
+ )
+ tr.inner =
+ ( ( td.elem | th.elem | common.elem.script-supporting )* )
+
+## Common Table Cell Attributes
+
+ tables.attrs.cell-structure =
+ ( tables.attrs.colspan?
+ & tables.attrs.rowspan?
+ )
+ tables.attrs.colspan =
+ attribute colspan {
+ common.data.integer.positive
+ }
+ tables.attrs.rowspan =
+ attribute rowspan {
+ common.data.integer.non-negative
+ }
+
+ tables.attrs.access-headers =
+ ( tables.attrs.headers? )
+ tables.attrs.headers =
+ attribute headers {
+ common.data.idrefs
+ }
+
+ tables.attrs.define-headers =
+ ( tables.attrs.scope? )
+ tables.attrs.scope =
+ attribute scope {
+ ( w:string "row"
+ | w:string "col"
+ | w:string "rowgroup"
+ | w:string "colgroup"
+ )
+ }
+ tables.attrs.abbr =
+ attribute abbr {
+ text
+ }
+
+## Table Data Cell: <td>
+
+ td.elem =
+ element td { td.inner & td.attrs }
+ td.attrs =
+ ( common.attrs
+ & tables.attrs.cell-structure
+ & tables.attrs.headers?
+# & tables.attrs.alignment
+ & common.attrs.aria?
+ )
+ td.inner =
+ ( common.inner.flow )
+
+## Table Header Cells: <th>
+
+ th.elem =
+ element th { th.inner & th.attrs }
+ th.attrs =
+ ( common.attrs
+ & tables.attrs.cell-structure
+ & tables.attrs.scope?
+ & tables.attrs.headers?
+# & tables.attrs.alignment
+ & common.attrs.aria?
+ )
+ th.inner =
+ ( common.inner.flow )
diff --git a/xml/relaxng/src/resources/html5-schema/html5/web-components.rnc b/xml/relaxng/src/resources/html5-schema/html5/web-components.rnc
new file mode 100755
index 0000000..bf45715
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/web-components.rnc
@@ -0,0 +1,43 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Web Components
+# #####################################################################
+
+## Templates: <template>
+
+ template.elem =
+ element template { template.inner & template.attrs }
+ template.attrs =
+ ( common.attrs )
+ template.inner =
+ ( common.inner.metadata
+ | common.inner.flow
+ | ol.inner
+ | ul.inner
+ | dl.inner
+ | figure.inner
+ | ruby.inner
+ | object.inner.flow
+ | object.inner.phrasing
+ | video.inner.flow
+ | video.inner.phrasing
+ | audio.inner.flow
+ | audio.inner.phrasing
+ | table.inner
+ | colgroup.inner
+ | thead.inner
+ | tbody.inner
+ | tfoot.inner
+ | tr.inner
+ | fieldset.inner
+ | select.inner
+ | details.inner
+ | menu.popup.inner
+ )
+ common.elem.metadata |= template.elem
+ common.elem.phrasing |= template.elem
+ common.elem.script-supporting |= template.elem
+
+# also allow <script> wherever <template> is allowed
+ common.elem.script-supporting |= script.elem
diff --git a/xml/relaxng/src/resources/html5-schema/web-forms-scripting.rnc b/xml/relaxng/src/resources/html5-schema/html5/web-forms-scripting.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/web-forms-scripting.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/web-forms-scripting.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/web-forms.rnc b/xml/relaxng/src/resources/html5-schema/html5/web-forms.rnc
new file mode 100755
index 0000000..f786a1b
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/web-forms.rnc
@@ -0,0 +1,604 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Web Forms 1.0 markup #
+# #####################################################################
+
+## Shared attributes for form controls
+
+ common-form.attrs =
+ ( common-form.attrs.name?
+ & common-form.attrs.disabled?
+ )
+
+ common-form.attrs.name =
+ attribute name {
+ string #REVISIT should this be restricted somehow? No & and = perhaps?
+ }
+
+ common-form.attrs.disabled =
+ attribute disabled {
+ w:string "disabled" | w:string ""
+ }
+
+ shared-form.attrs.readonly =
+ attribute readonly {
+ w:string "readonly" | w:string ""
+ }
+
+ shared-form.attrs.maxlength =
+ attribute maxlength {
+ common.data.integer.non-negative
+ }
+
+ shared-form.attrs.size =
+ attribute size {
+ common.data.integer.positive
+ }
+
+ # REVISIT tabindex goes in common.attrs
+
+## Shared attributes for <input>
+
+ input.attrs.checked =
+ attribute checked {
+ w:string "checked" | w:string ""
+ }
+
+## Text Field: <input type='text'>
+
+ input.text.elem =
+ element input { input.text.attrs }
+ input.text.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.text.attrs.type?
+ & shared-form.attrs.maxlength?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.size?
+ & input.text.attrs.value?
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.implicit.combobox
+ | common.attrs.aria.role.textbox
+ | common.attrs.aria.role.combobox
+ )?
+ )
+ input.text.attrs.type =
+ attribute type {
+ w:string "text"
+ }
+ input.text.attrs.value =
+ attribute value {
+ form.data.stringwithoutlinebreaks
+ }
+
+ input.elem = input.text.elem
+
+## Password Field: <input type='password'>
+
+ input.password.elem =
+ element input { input.password.attrs }
+ input.password.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.password.attrs.type
+ & shared-form.attrs.maxlength?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.size?
+ & input.password.attrs.value?
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.role.textbox
+ )?
+ )
+ input.password.attrs.type =
+ attribute type {
+ w:string "password"
+ }
+ input.password.attrs.value =
+ attribute value {
+ form.data.stringwithoutlinebreaks
+ }
+
+ input.elem |= input.password.elem
+
+## Checkbox: <input type='checkbox'>
+
+ input.checkbox.elem =
+ element input { input.checkbox.attrs }
+ input.checkbox.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.checkbox.attrs.type
+ & input.attrs.checked?
+ & input.checkbox.attrs.value?
+ & ( common.attrs.aria.implicit.checkbox
+ | common.attrs.aria.role.checkbox
+ | common.attrs.aria.role.menuitemcheckbox
+ )?
+ )
+ input.checkbox.attrs.type =
+ attribute type {
+ w:string "checkbox"
+ }
+ input.checkbox.attrs.value =
+ attribute value {
+ string #REVISIT require non-empty value?
+ }
+
+ input.elem |= input.checkbox.elem
+
+## Radiobutton: <input type='radio'>
+
+ input.radio.elem =
+ element input { input.radio.attrs }
+ input.radio.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.radio.attrs.type
+ & input.attrs.checked?
+ & input.radio.attrs.value?
+ & ( common.attrs.aria.implicit.radio
+ | common.attrs.aria.role.radio
+ | common.attrs.aria.role.menuitemradio
+ )?
+ )
+ input.radio.attrs.type =
+ attribute type {
+ w:string "radio"
+ }
+ input.radio.attrs.value =
+ attribute value {
+ string #REVISIT require non-empty value?
+ }
+
+ input.elem |= input.radio.elem
+
+## Scripting Hook Button: <input type='button'>
+
+ input.button.elem =
+ element input { input.button.attrs }
+ input.button.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.button.attrs.type
+ & input.button.attrs.value?
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.radio
+ )?
+ )
+ input.button.attrs.type =
+ attribute type {
+ w:string "button"
+ }
+ input.button.attrs.value =
+ attribute value {
+ string #REVISIT require non-empty value?
+ }
+
+ input.elem |= input.button.elem
+ #REVISIT should this be enabled by a scripting module only?
+
+## Submit Button: <input type='submit'>
+
+ input.submit.elem =
+ element input { input.submit.attrs }
+ input.submit.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.submit.attrs.type
+ & input.submit.attrs.value?
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ )?
+ )
+ input.submit.attrs.type =
+ attribute type {
+ w:string "submit"
+ }
+ input.submit.attrs.value =
+ attribute value {
+ string #REVISIT require non-empty value?
+ }
+
+ input.elem |= input.submit.elem
+
+## Reset Button: <input type='reset'>
+
+ input.reset.elem =
+ element input { input.reset.attrs }
+ input.reset.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.reset.attrs.type
+ & input.reset.attrs.value?
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ )?
+ )
+ input.reset.attrs.type =
+ attribute type {
+ w:string "reset"
+ }
+ input.reset.attrs.value =
+ attribute value {
+ string #REVISIT require non-empty value?
+ }
+
+ input.elem |= input.reset.elem
+ # REVISIT does reset make sense outside a form?
+
+## File Upload: <input type='file'>
+
+ input.file.elem =
+ element input { input.file.attrs }
+ input.file.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.file.attrs.type
+ & input.file.attrs.accept?
+ & common.attrs.aria?
+ )
+ input.file.attrs.type =
+ attribute type {
+ w:string "file"
+ }
+ input.file.attrs.accept =
+ attribute accept {
+ form.data.mimetypelist
+ }
+
+ input.elem |= input.file.elem
+
+## Hidden String: <input type='hidden'>
+
+ input.hidden.elem =
+ element input { input.hidden.attrs }
+ input.hidden.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.hidden.attrs.type
+ & input.hidden.attrs.value?
+ & common.attrs.aria?
+ )
+ input.hidden.attrs.type =
+ attribute type {
+ w:string "hidden"
+ }
+ input.hidden.attrs.value =
+ attribute value {
+ string
+ }
+
+ input.elem |= input.hidden.elem
+
+## Image Submit Button: <input type='image'>
+
+ input.image.elem =
+ element input { input.image.attrs }
+ input.image.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.image.attrs.type
+ & input.image.attrs.alt
+ & input.image.attrs.src?
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.radio
+ )?
+ )
+ input.image.attrs.type =
+ attribute type {
+ w:string "image"
+ }
+ input.image.attrs.alt =
+ attribute alt {
+ form.data.nonemptystring
+ }
+ input.image.attrs.src =
+ attribute src {
+ common.data.uri.non-empty
+ }
+
+ input.elem |= input.image.elem
+
+ common.elem.phrasing |= input.elem
+
+## Text Area: <textarea>
+
+ textarea.elem =
+ element textarea { textarea.inner & textarea.attrs }
+ textarea.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & shared-form.attrs.readonly?
+ & textarea.attrs.rows-and-cols-wf1
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.textbox
+ )?
+ #FIXME onfocus, onblur, onselect,onchange
+ )
+ # This is ugly.
+ textarea.attrs.rows-and-cols-wf1 =
+ textarea.attrs.rows-and-cols-wf1.inner
+ textarea.attrs.rows-and-cols-wf1.inner =
+ ( textarea.attrs.cols
+ & textarea.attrs.rows
+ )
+ textarea.attrs.cols =
+ attribute cols {
+ common.data.integer.positive
+ }
+ textarea.attrs.rows =
+ attribute rows {
+ common.data.integer.positive
+ }
+ textarea.inner =
+ ( text )
+
+ common.elem.phrasing |= textarea.elem
+
+# Due to limitations with interleave, handling single/multiple selection
+# enforcement in RELAX NG seems to be possible but really awkward.
+# Tried it. Leaving it to Schematron.
+
+## Select menu option: <option selected>
+
+ option.elem =
+ element option { option.inner & option.attrs }
+ option.attrs =
+ ( common.attrs
+ & common-form.attrs.disabled?
+ & option.attrs.selected?
+ & option.attrs.label?
+ & option.attrs.value?
+ & ( common.attrs.aria.implicit.option
+ | common.attrs.aria.role.option
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.presentation
+ )?
+ )
+ option.attrs.selected =
+ attribute selected {
+ w:string "selected" | w:string ""
+ }
+ option.attrs.label =
+ attribute label {
+ form.data.nonemptystring
+ }
+ option.attrs.value =
+ attribute value {
+ string
+ }
+ option.inner =
+ ( text )
+
+## Option Group: <optgroup>
+
+ optgroup.elem =
+ element optgroup { optgroup.inner & optgroup.attrs }
+ optgroup.attrs =
+ ( common.attrs
+ & optgroup.attrs.label
+ & common-form.attrs.disabled?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ optgroup.attrs.label =
+ attribute label {
+ string
+ }
+ optgroup.inner =
+ ( option.elem*
+ & common.elem.script-supporting*
+ )
+
+## Selection Menu: <select>
+
+ select.elem =
+ element select { select.inner & select.attrs }
+ select.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & select.attrs.size?
+ & select.attrs.multiple?
+ # FIXME onfocus, onblur, onchange
+ & ( common.attrs.aria.implicit.listbox
+ | common.attrs.aria.role.listbox # aria-multiselectable depends on "multiple" value; check in assertions
+ | common.attrs.aria.role.menu
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ select.attrs.size =
+ attribute size {
+ common.data.integer.positive
+ }
+ select.attrs.multiple =
+ attribute multiple {
+ w:string "multiple" | w:string ""
+ }
+ select.inner =
+ ( optgroup.elem*
+ & option.elem*
+ & common.elem.script-supporting*
+ )
+
+ common.elem.phrasing |= select.elem
+
+## Shared Definitions for Complex Button
+
+ button.attrs.value =
+ attribute value {
+ string
+ }
+ button.inner =
+ ( common.inner.phrasing )
+
+## Complex Submit Button: <button type='submit'>
+
+ button.submit.elem =
+ element button { button.inner & button.submit.attrs }
+ button.submit.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & button.submit.attrs.type?
+ & button.attrs.value?
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.radio
+ )?
+ )
+ button.submit.attrs.type =
+ attribute type {
+ w:string "submit"
+ }
+
+ button.elem = button.submit.elem
+
+## Complex Reset Button: <button type='reset'>
+
+ button.reset.elem =
+ element button { button.inner & button.reset.attrs }
+ button.reset.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & button.reset.attrs.type
+ & button.attrs.value? #REVISIT I guess this still affects the DOM
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.radio
+ )?
+ )
+ button.reset.attrs.type =
+ attribute type {
+ w:string "reset"
+ }
+
+ button.elem |= button.reset.elem
+
+## Complex Push Button: <button type='button'>
+
+ button.button.elem =
+ element button { button.inner & button.button.attrs }
+ button.button.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & button.button.attrs.type
+ & button.attrs.value? #REVISIT I guess this still affects the DOM
+ & ( common.attrs.aria.implicit.button
+ | common.attrs.aria.role.button
+ | common.attrs.aria.role.link
+ | common.attrs.aria.role.menuitem
+ | common.attrs.aria.role.menuitemcheckbox
+ | common.attrs.aria.role.menuitemradio
+ | common.attrs.aria.role.radio
+ )?
+ )
+ button.button.attrs.type =
+ attribute type {
+ w:string "button"
+ }
+
+ button.elem |= button.button.elem
+
+ common.elem.phrasing |= button.elem
+
+## Form: <form>
+
+ form.elem =
+ element form { form.inner & form.attrs }
+ form.attrs =
+ ( common.attrs
+ & form.attrs.action? #REVISIT Should this be required anyway?
+ & form.attrs.method?
+ & form.attrs.enctype?
+ & common-form.attrs.name?
+ & form.attrs.accept-charset?
+ & common.attrs.aria?
+ )
+ form.attrs.action =
+ attribute action {
+ common.data.uri.non-empty
+ }
+ form.attrs.method =
+ attribute method {
+ form.attrs.method.data
+ }
+ form.attrs.method.data =
+ ( w:string "get" | w:string "post" )
+ form.attrs.enctype =
+ attribute enctype {
+ form.attrs.enctype.data
+ }
+ form.attrs.enctype.data =
+ ( w:string "application/x-www-form-urlencoded"
+ | w:string "multipart/form-data"
+ )
+ form.attrs.accept-charset =
+ attribute accept-charset {
+ form.data.charsetlist
+ }
+ form.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= form.elem
+
+## Fieldset: <fieldset>
+
+ fieldset.elem =
+ element fieldset { fieldset.inner & fieldset.attrs }
+ fieldset.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.implicit.group
+ | common.attrs.aria
+ )?
+ )
+ fieldset.inner =
+ ( legend.elem? #REVISIT should this be required?
+ , common.inner.flow
+ )
+
+ common.elem.flow |= fieldset.elem
+
+## Label: <label>
+
+ label.elem =
+ element label { label.inner & label.attrs }
+ label.attrs =
+ ( common.attrs
+ & label.attrs.for?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ label.attrs.for =
+ attribute for {
+ common.data.idref
+ }
+ label.inner =
+ ( common.inner.phrasing ) #REVISIT making obvious guess
+
+ common.elem.phrasing |= label.elem
+
diff --git a/xml/relaxng/src/resources/html5-schema/web-forms2-scripting.rnc b/xml/relaxng/src/resources/html5-schema/html5/web-forms2-scripting.rnc
old mode 100644
new mode 100755
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/web-forms2-scripting.rnc
rename to xml/relaxng/src/resources/html5-schema/html5/web-forms2-scripting.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/html5/web-forms2.rnc b/xml/relaxng/src/resources/html5-schema/html5/web-forms2.rnc
new file mode 100755
index 0000000..e83c399
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/web-forms2.rnc
@@ -0,0 +1,830 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+# #####################################################################
+## RELAX NG Schema for HTML 5: Web Forms 2.0 markup #
+# #####################################################################
+
+## Shared attributes for form controls
+
+ common-form.attrs &=
+ ( common-form.attrs.form? )
+
+ common-form.attrs.form |=
+ attribute form {
+ common.data.idref
+ }
+
+ shared-form.attrs.formaction =
+ attribute formaction {
+ common.data.uri.non-empty
+ }
+
+ shared-form.attrs.formenctype =
+ attribute formenctype {
+ shared-form.attrs.formenctype.data
+ }
+ shared-form.attrs.formenctype.data =
+ ( w:string "application/x-www-form-urlencoded"
+ | w:string "multipart/form-data"
+ | w:string "text/plain"
+ )
+
+ shared-form.attrs.formmethod =
+ attribute formmethod {
+ shared-form.attrs.formmethod.data
+ }
+ shared-form.attrs.formmethod.data =
+ ( w:string "get"
+ | w:string "post"
+ )
+
+ shared-form.attrs.formtarget =
+ attribute formtarget {
+ common.data.browsing-context-or-keyword
+ }
+
+ shared-form.attrs.formnovalidate =
+ attribute formnovalidate {
+ w:string "formnovalidate" | w:string ""
+ }
+
+ shared-form.attrs.autofocus =
+ attribute autofocus {
+ w:string "autofocus" | w:string ""
+ }
+
+ shared-form.attrs.pattern =
+ attribute pattern {
+ form.data.pattern
+ }
+
+ shared-form.attrs.template =
+ attribute template {
+ common.data.idref
+ }
+
+ shared-form.attrs.required =
+ attribute required {
+ w:string "required" | w:string ""
+ }
+
+ shared-form.attrs.placeholder =
+ attribute placeholder {
+ form.data.stringwithoutlinebreaks
+ }
+
+ shared-form.attrs.dirname =
+ attribute dirname {
+ form.data.nonemptystring
+ }
+
+## Shared attributes for <input>
+
+ input.attrs.autocomplete =
+ attribute autocomplete {
+ w:string "on" | w:string "off"
+ }
+
+ input.attrs.list =
+ attribute list {
+ common.data.idref
+ }
+
+ input.attrs.step.float =
+ attribute step {
+ w:string "any" | common.data.float.positive
+ }
+
+ input.attrs.step.integer =
+ attribute step {
+ w:string "any" | common.data.integer.positive
+ }
+
+ input.attrs.multiple =
+ attribute multiple {
+ w:string "multiple" | w:string ""
+ }
+
+## Text Field: <input type='text'>, Extensions
+
+ input.text.attrs &=
+ ( input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & shared-form.attrs.pattern?
+ & shared-form.attrs.required?
+ & shared-form.attrs.placeholder?
+ & shared-form.attrs.dirname?
+ )
+
+## Password Field: <input type='password'>, Extensions
+
+ input.password.attrs &=
+ ( input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & shared-form.attrs.pattern?
+ & shared-form.attrs.required?
+ & shared-form.attrs.placeholder?
+ )
+
+## Checkbox <input type='checkbox'>, Extensions
+
+ input.checkbox.attrs &=
+ ( shared-form.attrs.autofocus?
+ & shared-form.attrs.required?
+ )
+
+## Radiobutton: <input type='radio'>, Extensions
+
+ input.radio.attrs &=
+ ( shared-form.attrs.autofocus?
+ & shared-form.attrs.required?
+ )
+
+## Scripting Hook Button: <input type='button'>, Extensions
+
+ input.button.attrs &=
+ ( shared-form.attrs.autofocus? )
+
+## Submit Button: <input type='submit'>, Extensions
+
+ input.submit.attrs &=
+ ( shared-form.attrs.formaction?
+ & shared-form.attrs.autofocus?
+ & shared-form.attrs.formenctype?
+ & shared-form.attrs.formmethod?
+ & shared-form.attrs.formtarget?
+ & shared-form.attrs.formnovalidate?
+ )
+
+## Reset Button: <input type='reset'>, Extensions
+
+ input.reset.attrs &=
+ ( shared-form.attrs.autofocus? )
+
+## File Upload: <input type='file'>, Extensions
+
+ input.file.attrs &=
+ ( shared-form.attrs.autofocus?
+ & shared-form.attrs.required?
+ & input.attrs.multiple?
+ )
+
+## Image Submit Button: <input type='image'>, Extensions
+
+ input.image.attrs &=
+ ( shared-form.attrs.formaction?
+ & shared-form.attrs.autofocus?
+ & shared-form.attrs.formenctype?
+ & shared-form.attrs.formmethod?
+ & shared-form.attrs.formtarget?
+ & shared-form.attrs.formnovalidate?
+ & input.image.attrs.height?
+ & input.image.attrs.width?
+ )
+ input.image.attrs.height =
+ attribute height {
+ common.data.integer.non-negative
+ }
+ input.image.attrs.width =
+ attribute width {
+ common.data.integer.non-negative
+ }
+
+## Global Date and Time: <input type='datetime'>
+
+ input.datetime.elem =
+ element input { input.datetime.attrs }
+ input.datetime.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.datetime.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.datetime.attrs.min?
+ & input.datetime.attrs.max?
+ & input.attrs.step.float?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & input.datetime.attrs.value?
+ & common.attrs.aria?
+ )
+ input.datetime.attrs.type =
+ attribute type {
+ w:string "datetime"
+ }
+ input.datetime.attrs.min =
+ attribute min {
+ common.data.datetime
+ }
+ input.datetime.attrs.max =
+ attribute max {
+ common.data.datetime
+ }
+ input.datetime.attrs.value =
+ attribute value {
+ w:string "" | common.data.datetime
+ }
+
+ input.elem |= input.datetime.elem
+
+## Date and Time with No Time Zone Information: <input type='datetime-local'>
+
+ input.datetime-local.elem =
+ element input { input.datetime-local.attrs }
+ input.datetime-local.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.datetime-local.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.datetime-local.attrs.min?
+ & input.datetime-local.attrs.max?
+ & input.attrs.step.float?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & input.datetime-local.attrs.value?
+ & common.attrs.aria?
+ )
+ input.datetime-local.attrs.type =
+ attribute type {
+ w:string "datetime-local"
+ }
+ input.datetime-local.attrs.min =
+ attribute min {
+ form.data.datetime-local
+ }
+ input.datetime-local.attrs.max =
+ attribute max {
+ form.data.datetime-local
+ }
+ input.datetime-local.attrs.value =
+ attribute value {
+ w:string "" | form.data.datetime-local
+ }
+
+ input.elem |= input.datetime-local.elem
+
+## Date: <input type='date'>
+
+ input.date.elem =
+ element input { input.date.attrs }
+ input.date.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.date.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.date.attrs.min?
+ & input.date.attrs.max?
+ & input.attrs.step.integer?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & input.date.attrs.value?
+ & common.attrs.aria?
+ )
+ input.date.attrs.type =
+ attribute type {
+ w:string "date"
+ }
+ input.date.attrs.min =
+ attribute min {
+ form.data.date
+ }
+ input.date.attrs.max =
+ attribute max {
+ form.data.date
+ }
+ input.date.attrs.value =
+ attribute value {
+ w:string "" | form.data.date
+ }
+
+ input.elem |= input.date.elem
+
+## Year and Month: <input type='month'>
+
+ input.month.elem =
+ element input { input.month.attrs }
+ input.month.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.month.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.month.attrs.min?
+ & input.month.attrs.max?
+ & input.attrs.step.integer?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & input.month.attrs.value?
+ & common.attrs.aria?
+ )
+ input.month.attrs.type =
+ attribute type {
+ w:string "month"
+ }
+ input.month.attrs.min =
+ attribute min {
+ form.data.month
+ }
+ input.month.attrs.max =
+ attribute max {
+ form.data.month
+ }
+ input.month.attrs.value =
+ attribute value {
+ w:string "" | form.data.month
+ }
+
+ input.elem |= input.month.elem
+
+## Time without Time Zone Information: <input type='time'>
+
+ input.time.elem =
+ element input { input.time.attrs }
+ input.time.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.time.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.time.attrs.min?
+ & input.time.attrs.max?
+ & input.attrs.step.float?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & input.time.attrs.value?
+ & common.attrs.aria?
+ )
+ input.time.attrs.type =
+ attribute type {
+ w:string "time"
+ }
+ input.time.attrs.min =
+ attribute min {
+ form.data.time
+ }
+ input.time.attrs.max =
+ attribute max {
+ form.data.time
+ }
+ input.time.attrs.value =
+ attribute value {
+ w:string "" | form.data.time
+ }
+
+ input.elem |= input.time.elem
+
+## Year and Week: <input type='week'>
+
+ input.week.elem =
+ element input { input.week.attrs }
+ input.week.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.week.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.week.attrs.min?
+ & input.week.attrs.max?
+ & input.attrs.step.integer?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & input.week.attrs.value?
+ & common.attrs.aria?
+ )
+ input.week.attrs.type =
+ attribute type {
+ w:string "week"
+ }
+ input.week.attrs.min =
+ attribute min {
+ form.data.week
+ }
+ input.week.attrs.max =
+ attribute max {
+ form.data.week
+ }
+ input.week.attrs.value =
+ attribute value {
+ w:string "" | form.data.week
+ }
+
+ input.elem |= input.week.elem
+
+## Number: <input type='number'>
+
+ input.number.elem =
+ element input { input.number.attrs }
+ input.number.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.number.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.number.attrs.min?
+ & input.number.attrs.max?
+ & input.attrs.step.float?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & shared-form.attrs.placeholder?
+ & input.number.attrs.value?
+ & ( common.attrs.aria.implicit.spinbutton
+ | common.attrs.aria.role.spinbutton
+ )?
+ )
+ input.number.attrs.type =
+ attribute type {
+ w:string "number"
+ }
+ input.number.attrs.min =
+ attribute min {
+ common.data.float
+ }
+ input.number.attrs.max =
+ attribute max {
+ common.data.float
+ }
+ input.number.attrs.value =
+ attribute value {
+ w:string "" | common.data.float
+ }
+
+ input.elem |= input.number.elem
+
+## Imprecise Number: <input type='range'>
+
+ input.range.elem =
+ element input { input.range.attrs }
+ input.range.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.range.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.range.attrs.min?
+ & input.range.attrs.max?
+ & input.attrs.step.float?
+ & input.range.attrs.value?
+ & ( common.attrs.aria.implicit.slider
+ | common.attrs.aria.role.slider
+ )?
+ )
+ input.range.attrs.type =
+ attribute type {
+ w:string "range"
+ }
+ input.range.attrs.min =
+ attribute min {
+ common.data.float
+ }
+ input.range.attrs.max =
+ attribute max {
+ common.data.float
+ }
+ input.range.attrs.value =
+ attribute value {
+ common.data.float
+ }
+
+ input.elem |= input.range.elem
+
+## Email Address: <input type='email'>
+
+ input.email.elem =
+ element input { input.email.attrs }
+ input.email.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.email.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & shared-form.attrs.maxlength?
+ & shared-form.attrs.pattern?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & shared-form.attrs.size?
+ & shared-form.attrs.placeholder?
+ & ( ( input.attrs.multiple
+ & input.email.attrs.value.multiple?
+ )
+ | input.email.attrs.value.single?
+ )?
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.implicit.combobox
+ | common.attrs.aria.role.textbox
+ | common.attrs.aria.role.combobox
+ )?
+ )
+ input.email.attrs.type =
+ attribute type {
+ w:string "email"
+ }
+ input.email.attrs.value.single =
+ attribute value {
+ form.data.emailaddress
+ }
+ input.email.attrs.value.multiple =
+ attribute value {
+ form.data.emailaddresslist
+ }
+
+ input.elem |= input.email.elem
+
+## IRI: <input type='url'>
+
+ input.url.elem =
+ element input { input.url.attrs }
+ input.url.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.url.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & shared-form.attrs.maxlength?
+ & shared-form.attrs.pattern?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & shared-form.attrs.size?
+ & shared-form.attrs.placeholder?
+ & input.url.attrs.value?
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.implicit.combobox
+ | common.attrs.aria.role.textbox
+ | common.attrs.aria.role.combobox
+ )?
+ )
+ input.url.attrs.type =
+ attribute type {
+ w:string "url"
+ }
+ input.url.attrs.value =
+ attribute value {
+ w:string "" | common.data.uri.absolute
+ }
+
+ input.elem |= input.url.elem
+
+## Search: <input type='search'>
+
+ input.search.elem =
+ element input { input.search.attrs }
+ input.search.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.search.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & shared-form.attrs.maxlength?
+ & shared-form.attrs.pattern?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & shared-form.attrs.size?
+ & shared-form.attrs.placeholder?
+ & shared-form.attrs.dirname?
+ & input.search.attrs.value?
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.implicit.combobox
+ | common.attrs.aria.role.textbox
+ | common.attrs.aria.role.combobox
+ )?
+ )
+ input.search.attrs.type =
+ attribute type {
+ w:string "search"
+ }
+ input.search.attrs.value =
+ attribute value {
+ form.data.stringwithoutlinebreaks
+ }
+
+ input.elem |= input.search.elem
+
+## Telephone Number: <input type='tel'>
+
+ input.tel.elem =
+ element input { input.tel.attrs }
+ input.tel.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.tel.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & shared-form.attrs.maxlength?
+ & shared-form.attrs.pattern?
+ & shared-form.attrs.readonly?
+ & shared-form.attrs.required?
+ & shared-form.attrs.size?
+ & shared-form.attrs.placeholder?
+ & input.tel.attrs.value?
+ & ( common.attrs.aria.implicit.textbox
+ | common.attrs.aria.implicit.combobox
+ | common.attrs.aria.role.textbox
+ | common.attrs.aria.role.combobox
+ )?
+ )
+ input.tel.attrs.type =
+ attribute type {
+ w:string "tel"
+ }
+ input.tel.attrs.value =
+ attribute value {
+ form.data.stringwithoutlinebreaks
+ }
+
+ input.elem |= input.tel.elem
+
+## Color: <input type='color'>
+
+ input.color.elem =
+ element input { input.color.attrs }
+ input.color.attrs =
+ ( common.attrs
+ & common-form.attrs
+ & input.color.attrs.type
+ & input.attrs.autocomplete?
+ & shared-form.attrs.autofocus?
+ & input.attrs.list?
+ & input.color.attrs.value?
+ & common.attrs.aria?
+ )
+ input.color.attrs.type =
+ attribute type {
+ w:string "color"
+ }
+ input.color.attrs.value =
+ attribute value {
+ w:string "" | form.data.color
+ }
+
+ input.elem |= input.color.elem
+
+## Form Output: <output>
+
+ output.elem =
+ element output { output.inner & output.attrs }
+ output.attrs =
+ ( common.attrs
+ & common-form.attrs.name?
+ & common-form.attrs.form?
+ & output.attrs.for?
+ & ( common.attrs.aria.implicit.status
+ | common.attrs.aria
+ )?
+ )
+ output.attrs.for =
+ attribute for {
+ common.data.idrefs #REVISIT spec says space--not whitespace
+ }
+ output.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= output.elem
+
+## Text Area: <textarea>, extensions
+
+ textarea.attrs.rows-and-cols-wf1.inner &=
+ notAllowed
+ textarea.attrs.rows-and-cols-wf1 |=
+ empty
+ textarea.attrs &=
+ ( shared-form.attrs.maxlength?
+ & shared-form.attrs.autofocus?
+ & shared-form.attrs.required?
+ & shared-form.attrs.placeholder?
+ & shared-form.attrs.dirname?
+ & textarea.attrs.rows?
+ & ( ( textarea.attrs.wrap.hard
+ & textarea.attrs.cols
+ )
+ | ( textarea.attrs.wrap.soft?
+ & textarea.attrs.cols?
+ )
+ )
+ )
+ textarea.attrs.wrap.hard =
+ attribute wrap {
+ w:string "hard"
+ }
+ textarea.attrs.wrap.soft =
+ attribute wrap {
+ w:string "soft"
+ }
+
+## List of Prefill Data: <datalist>
+
+ #REVISIT should the options in datalist be non-selectable?
+
+ datalist.elem =
+ element datalist { datalist.inner & datalist.attrs }
+ datalist.inner =
+ ( option.elem* & common.inner.phrasing )
+ datalist.attrs =
+ ( common.attrs
+ & ( common.attrs.aria.role.listbox # aria-multiselectable must be false; check by assertions
+ | common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+
+ common.elem.phrasing |= datalist.elem
+
+## Complex Submit Button: <button type='submit'>, extensions
+
+ button.submit.attrs &=
+ ( shared-form.attrs.formaction?
+ & shared-form.attrs.autofocus?
+ & shared-form.attrs.formenctype?
+ & shared-form.attrs.formmethod?
+ & shared-form.attrs.formtarget?
+ & shared-form.attrs.formnovalidate?
+ )
+
+## Complex Reset Button: <button type='reset'>, extensions
+
+ button.reset.attrs &=
+ ( shared-form.attrs.autofocus? )
+
+## Complex Push Button: <button type='button'>, extensions
+
+ button.button.attrs &=
+ ( shared-form.attrs.autofocus? )
+
+## Form: <form>, extensions
+ form.attrs &=
+ ( form.attrs.novalidate?
+ & form.attrs.target?
+ & form.attrs.autocomplete?
+ )
+ form.attrs.novalidate =
+ attribute novalidate {
+ w:string "novalidate" | w:string ""
+ }
+ form.attrs.target =
+ attribute target {
+ common.data.browsing-context-or-keyword
+ }
+ form.attrs.autocomplete =
+ attribute autocomplete {
+ w:string "on" | w:string "off"
+ }
+ # REVISIT should this be case-insensitive in conforming XHTML documents?
+ form.attrs.enctype.data |=
+ ( w:string "text/plain" )
+
+## Fieldset: <fieldset>, extensions
+
+ fieldset.attrs &=
+ ( common-form.attrs )
+
+## Label: <label>, extensions
+
+ label.attrs &=
+ ( common-form.attrs.form? )
+
+## Key-pair generator/input control: <keygen>
+
+ keygen.elem =
+ element keygen { keygen.inner & keygen.attrs }
+ keygen.attrs =
+ ( common.attrs
+ & keygen.attrs.challenge?
+ & keygen.attrs.keytype?
+ & shared-form.attrs.autofocus?
+ & common-form.attrs?
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ keygen.attrs.challenge =
+ attribute challenge {
+ string
+ }
+ keygen.attrs.keytype =
+ attribute keytype {
+ w:string "rsa"
+ }
+ keygen.inner =
+ ( empty )
+
+ common.elem.phrasing |= keygen.elem
+
+## Selection Menu: <select>, Extensions
+
+ select.attrs &=
+ ( shared-form.attrs.autofocus?
+ & shared-form.attrs.required?
+ )
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5.rnc
new file mode 100644
index 0000000..1c6c524
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5.rnc
@@ -0,0 +1,40 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+# #####################################################################
+## RELAX NG Schema for XHTML 5 #
+# #####################################################################
+
+ # To validate an XHTML 5 document, you must first validate against #
+ # this schema and then ALSO validate against assertions.sch #
+
+# #####################################################################
+## Schema Framework & Parameters
+
+include "common.rnc" {
+ # XHTML flavor #
+ XMLonly = empty
+ HTMLonly = notAllowed
+ # HTML 4 compat #
+ v5only = empty
+}
+
+# #####################################################################
+## Language Definitions
+
+start = html.elem
+
+include "meta.rnc"
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "structural.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "core-scripting.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "applications.rnc"
+include "data.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5core-plus-web-forms2.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5core-plus-web-forms2.rnc
new file mode 100644
index 0000000..a1383cf
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5core-plus-web-forms2.rnc
@@ -0,0 +1,18 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "meta.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5core.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5core.rnc
new file mode 100644
index 0000000..9c8d81b
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5core.rnc
@@ -0,0 +1,14 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "meta.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html-no-microdata.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html-no-microdata.rnc
new file mode 100644
index 0000000..b0884a9
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html-no-microdata.rnc
@@ -0,0 +1,35 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html-rdfalite.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html-rdfalite.rnc
new file mode 100644
index 0000000..c2e7d64
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html-rdfalite.rnc
@@ -0,0 +1,39 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "microdata.rnc"
+include "rdfa.rnc" {
+ nonRDFaLite = notAllowed
+}
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html.rnc
new file mode 100644
index 0000000..2e38eea
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-html.rnc
@@ -0,0 +1,36 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "microdata.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-no-microdata.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-no-microdata.rnc
new file mode 100644
index 0000000..3b087c9
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-no-microdata.rnc
@@ -0,0 +1,33 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-rdfa.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-rdfa.rnc
new file mode 100644
index 0000000..c2769ae
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-rdfa.rnc
@@ -0,0 +1,38 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+}
+include "common-ext.rnc"
+
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "embed-ext.rnc"
+include "core-scripting.rnc"
+include "core-scripting-ext.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-rdfalite.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-rdfalite.rnc
new file mode 100644
index 0000000..a193dc2
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml-rdfalite.rnc
@@ -0,0 +1,37 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "microdata.rnc"
+include "rdfa.rnc" {
+ nonRDFaLite = notAllowed
+}
diff --git a/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml.rnc b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml.rnc
new file mode 100644
index 0000000..c189122
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/html5/xhtml5full-xhtml.rnc
@@ -0,0 +1,34 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "common.rnc" {
+ XMLonly = empty
+ HTMLonly = notAllowed
+ v5only = empty
+}
+start = html.elem
+include "phrase.rnc"
+include "block.rnc"
+include "sectional.rnc"
+include "revision.rnc"
+include "embed.rnc"
+include "core-scripting.rnc"
+include "structural.rnc"
+include "ruby.rnc"
+include "media.rnc"
+include "tables.rnc"
+include "form-datatypes.rnc"
+include "web-forms.rnc"
+include "web-forms2.rnc"
+include "web-components.rnc"
+include "applications.rnc"
+include "data.rnc"
+include "legacy.rnc"
+include "aria.rnc"
+include "meta.rnc" {
+ html.inner =
+ ( head.elem
+ , ( body.elem
+ | frameset.elem
+ )
+ )
+}
+include "microdata.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5chars.ent b/xml/relaxng/src/resources/html5-schema/html5chars.ent
index 419a0e6..960fa18 100644
--- a/xml/relaxng/src/resources/html5-schema/html5chars.ent
+++ b/xml/relaxng/src/resources/html5-schema/html5chars.ent
@@ -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,7 @@
-->
<!-- It's an automatically generated code. Do not modify it. -->
-<!-- Please see http://dev.w3.org/html5/html-author/charref and ./html5charref.rb -->
+<!-- Please see http://dev.w3.org/html5/html-author/charref and html5charref.rb -->
<!ENTITY Tab "	" >
<!ENTITY NewLine " " >
diff --git a/xml/relaxng/src/resources/html5-schema/inkscape/inkscape-draft.rnc b/xml/relaxng/src/resources/html5-schema/inkscape/inkscape-draft.rnc
new file mode 100644
index 0000000..58b9004
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/inkscape/inkscape-draft.rnc
@@ -0,0 +1,303 @@
+# Copyright (c) 2007 Mozilla Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+namespace inkscape = "http://www.inkscape.org/namespaces/inkscape"
+namespace sodipodi = "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+
+ sodipodi.namedview.elem =
+ element sodipodi:namedview
+ { sodipodi.namedview.inner
+ & sodipodi.namedview.attrs
+ }
+ sodipodi.namedview.attrs = ( inkscape.attrs )
+ sodipodi.namedview.inner = ( empty )
+
+ inkscape.attrs =
+ ( inkscape.attrs.collect?
+ & inkscape.attrs.connection-end?
+ & inkscape.attrs.connection-start?
+ & inkscape.attrs.connector-avoid?
+ & inkscape.attrs.connector-spacing?
+ & inkscape.attrs.connector-type?
+ & inkscape.attrs.current-layer?
+ & inkscape.attrs.cx?
+ & inkscape.attrs.cy?
+ & inkscape.attrs.dataloss?
+ & inkscape.attrs.document-units?
+ & inkscape.attrs.dstBox?
+ & inkscape.attrs.dstColumn?
+ & inkscape.attrs.dstPath?
+ & inkscape.attrs.dstShape?
+ & inkscape.attrs.excludeShape?
+ & inkscape.attrs.export-filename?
+ & inkscape.attrs.export-xdpi?
+ & inkscape.attrs.export-ydpi?
+ & inkscape.attrs.flatsided?
+ & inkscape.attrs.grid-bbox?
+ & inkscape.attrs.grid-points?
+ & inkscape.attrs.groupmode?
+ & inkscape.attrs.guide-bbox?
+ & inkscape.attrs.guide-points?
+ & inkscape.attrs.has_abs_tolerance?
+ & inkscape.attrs.href?
+ & inkscape.attrs.label?
+ & inkscape.attrs.layoutOptions?
+ & inkscape.attrs.marker?
+ & inkscape.attrs.object-bbox?
+ & inkscape.attrs.object-nodes?
+ & inkscape.attrs.object-paths?
+ & inkscape.attrs.object-points?
+ & inkscape.attrs.offset?
+ & inkscape.attrs.original?
+ & inkscape.attrs.output_extension?
+ & inkscape.attrs.pageopacity?
+ & inkscape.attrs.pageshadow?
+ & inkscape.attrs.radius?
+ & inkscape.attrs.randomized?
+ & inkscape.attrs.rounded?
+ & inkscape.attrs.showpageshadow?
+ & inkscape.attrs.srcNoMarkup?
+ & inkscape.attrs.srcPango?
+ & inkscape.attrs.stockid?
+ & inkscape.attrs.tile-cx?
+ & inkscape.attrs.tile-cy?
+ & inkscape.attrs.tiled-clone-of?
+ & inkscape.attrs.tile-h?
+ & inkscape.attrs.tile-w?
+ & inkscape.attrs.transform-center-x?
+ & inkscape.attrs.transform-center-y?
+ & inkscape.attrs.version?
+ & inkscape.attrs.window-height?
+ & inkscape.attrs.window-width?
+ & inkscape.attrs.window-x?
+ & inkscape.attrs.window-y?
+ & inkscape.attrs.zoom?
+ & sodipodi.attrs.absref?
+ & sodipodi.attrs.arg1?
+ & sodipodi.attrs.arg2?
+ & sodipodi.attrs.argument?
+ & sodipodi.attrs.cx?
+ & sodipodi.attrs.cy?
+ & sodipodi.attrs.docbase?
+ & sodipodi.attrs.docname?
+ & sodipodi.attrs.end?
+ & sodipodi.attrs.expansion?
+ & sodipodi.attrs.insensitive?
+ & sodipodi.attrs.linespacing?
+ & sodipodi.attrs.modified?
+ & sodipodi.attrs.nodetypes?
+ & sodipodi.attrs.nonprintable?
+ & sodipodi.attrs.open?
+ & sodipodi.attrs.original?
+ & sodipodi.attrs.r1?
+ & sodipodi.attrs.r2?
+ & sodipodi.attrs.radius?
+ & sodipodi.attrs.revolution?
+ & sodipodi.attrs.role?
+ & sodipodi.attrs.rx?
+ & sodipodi.attrs.ry?
+ & sodipodi.attrs.sides?
+ & sodipodi.attrs.spiral?
+ & sodipodi.attrs.star?
+ & sodipodi.attrs.start?
+ & sodipodi.attrs.t0?
+ & sodipodi.attrs.type?
+ & sodipodi.attrs.version?
+ )
+ inkscape.attrs.collect =
+ attribute inkscape:collect { string }
+ inkscape.attrs.connection-end =
+ attribute inkscape:connection-end { string }
+ inkscape.attrs.connection-start =
+ attribute inkscape:connection-start { string }
+ inkscape.attrs.connector-avoid =
+ attribute inkscape:connector-avoid { string }
+ inkscape.attrs.connector-spacing =
+ attribute inkscape:connector-spacing { string }
+ inkscape.attrs.connector-type =
+ attribute inkscape:connector-type { string }
+ inkscape.attrs.current-layer =
+ attribute inkscape:current-layer { string }
+ inkscape.attrs.cx =
+ attribute inkscape:cx { string }
+ inkscape.attrs.cy =
+ attribute inkscape:cy { string }
+ inkscape.attrs.dataloss =
+ attribute inkscape:dataloss { string }
+ inkscape.attrs.document-units =
+ attribute inkscape:document-units { string }
+ inkscape.attrs.dstBox =
+ attribute inkscape:dstBox { string }
+ inkscape.attrs.dstColumn =
+ attribute inkscape:dstColumn { string }
+ inkscape.attrs.dstPath =
+ attribute inkscape:dstPath { string }
+ inkscape.attrs.dstShape =
+ attribute inkscape:dstShape { string }
+ inkscape.attrs.excludeShape =
+ attribute inkscape:excludeShape { string }
+ inkscape.attrs.export-filename =
+ attribute inkscape:export-filename { string }
+ inkscape.attrs.export-xdpi =
+ attribute inkscape:export-xdpi { string }
+ inkscape.attrs.export-ydpi =
+ attribute inkscape:export-ydpi { string }
+ inkscape.attrs.flatsided =
+ attribute inkscape:flatsided { string }
+ inkscape.attrs.grid-bbox =
+ attribute inkscape:grid-bbox { string }
+ inkscape.attrs.grid-points =
+ attribute inkscape:grid-points { string }
+ inkscape.attrs.groupmode =
+ attribute inkscape:groupmode { string }
+ inkscape.attrs.guide-bbox =
+ attribute inkscape:guide-bbox { string }
+ inkscape.attrs.guide-points =
+ attribute inkscape:guide-points { string }
+ inkscape.attrs.has_abs_tolerance =
+ attribute inkscape:has_abs_tolerance { string }
+ inkscape.attrs.href =
+ attribute inkscape:href { string }
+ inkscape.attrs.label =
+ attribute inkscape:label { string }
+ inkscape.attrs.layoutOptions =
+ attribute inkscape:layoutOptions { string }
+ inkscape.attrs.marker =
+ attribute inkscape:marker { string }
+ inkscape.attrs.object-bbox =
+ attribute inkscape:object-bbox { string }
+ inkscape.attrs.object-nodes =
+ attribute inkscape:object-nodes { string }
+ inkscape.attrs.object-paths =
+ attribute inkscape:object-paths { string }
+ inkscape.attrs.object-points =
+ attribute inkscape:object-points { string }
+ inkscape.attrs.offset =
+ attribute inkscape:offset { string }
+ inkscape.attrs.original =
+ attribute inkscape:original { string }
+ inkscape.attrs.output_extension =
+ attribute inkscape:output_extension { string }
+ inkscape.attrs.pageopacity =
+ attribute inkscape:pageopacity { string }
+ inkscape.attrs.pageshadow =
+ attribute inkscape:pageshadow { string }
+ inkscape.attrs.radius =
+ attribute inkscape:radius { string }
+ inkscape.attrs.randomized =
+ attribute inkscape:randomized { string }
+ inkscape.attrs.rounded =
+ attribute inkscape:rounded { string }
+ inkscape.attrs.showpageshadow =
+ attribute inkscape:showpageshadow { string }
+ inkscape.attrs.srcNoMarkup =
+ attribute inkscape:srcNoMarkup { string }
+ inkscape.attrs.srcPango =
+ attribute inkscape:srcPango { string }
+ inkscape.attrs.stockid =
+ attribute inkscape:stockid { string }
+ inkscape.attrs.tile-cx =
+ attribute inkscape:tile-cx { string }
+ inkscape.attrs.tile-cy =
+ attribute inkscape:tile-cy { string }
+ inkscape.attrs.tiled-clone-of =
+ attribute inkscape:tiled-clone-of { string }
+ inkscape.attrs.tile-h =
+ attribute inkscape:tile-h { string }
+ inkscape.attrs.tile-w =
+ attribute inkscape:tile-w { string }
+ inkscape.attrs.transform-center-x =
+ attribute inkscape:transform-center-x { string }
+ inkscape.attrs.transform-center-y =
+ attribute inkscape:transform-center-y { string }
+ inkscape.attrs.version =
+ attribute inkscape:version { string }
+ inkscape.attrs.window-height =
+ attribute inkscape:window-height { string }
+ inkscape.attrs.window-width =
+ attribute inkscape:window-width { string }
+ inkscape.attrs.window-x =
+ attribute inkscape:window-x { string }
+ inkscape.attrs.window-y =
+ attribute inkscape:window-y { string }
+ inkscape.attrs.zoom =
+ attribute inkscape:zoom { string }
+ sodipodi.attrs.absref =
+ attribute sodipodi:absref { string }
+ sodipodi.attrs.arg1 =
+ attribute sodipodi:arg1 { string }
+ sodipodi.attrs.arg2 =
+ attribute sodipodi:arg2 { string }
+ sodipodi.attrs.argument =
+ attribute sodipodi:argument { string }
+ sodipodi.attrs.cx =
+ attribute sodipodi:cx { string }
+ sodipodi.attrs.cy =
+ attribute sodipodi:cy { string }
+ sodipodi.attrs.docbase =
+ attribute sodipodi:docbase { string }
+ sodipodi.attrs.docname =
+ attribute sodipodi:docname { string }
+ sodipodi.attrs.end =
+ attribute sodipodi:end { string }
+ sodipodi.attrs.expansion =
+ attribute sodipodi:expansion { string }
+ sodipodi.attrs.insensitive =
+ attribute sodipodi:insensitive { string }
+ sodipodi.attrs.linespacing =
+ attribute sodipodi:linespacing { string }
+ sodipodi.attrs.modified =
+ attribute sodipodi:modified { string }
+ sodipodi.attrs.nodetypes =
+ attribute sodipodi:nodetypes { string }
+ sodipodi.attrs.nonprintable =
+ attribute sodipodi:nonprintable { string }
+ sodipodi.attrs.open =
+ attribute sodipodi:open { string }
+ sodipodi.attrs.original =
+ attribute sodipodi:original { string }
+ sodipodi.attrs.r1 =
+ attribute sodipodi:r1 { string }
+ sodipodi.attrs.r2 =
+ attribute sodipodi:r2 { string }
+ sodipodi.attrs.radius =
+ attribute sodipodi:radius { string }
+ sodipodi.attrs.revolution =
+ attribute sodipodi:revolution { string }
+ sodipodi.attrs.role =
+ attribute sodipodi:role { string }
+ sodipodi.attrs.rx =
+ attribute sodipodi:rx { string }
+ sodipodi.attrs.ry =
+ attribute sodipodi:ry { string }
+ sodipodi.attrs.sides =
+ attribute sodipodi:sides { string }
+ sodipodi.attrs.spiral =
+ attribute sodipodi:spiral { string }
+ sodipodi.attrs.star =
+ attribute sodipodi:star { string }
+ sodipodi.attrs.start =
+ attribute sodipodi:start { string }
+ sodipodi.attrs.t0 =
+ attribute sodipodi:t0 { string }
+ sodipodi.attrs.type =
+ attribute sodipodi:type { string }
+ sodipodi.attrs.version =
+ attribute sodipodi:version { string }
diff --git a/xml/relaxng/src/resources/html5-schema/inkscape/inkscape.rnc b/xml/relaxng/src/resources/html5-schema/inkscape/inkscape.rnc
new file mode 100644
index 0000000..d4aa3ce
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/inkscape/inkscape.rnc
@@ -0,0 +1,69 @@
+# Copyright (c) 2007 Mozilla Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+# This schema is an ugly placeholder until Inkscape get better docs.
+
+namespace inkscape = "http://www.inkscape.org/namespaces/inkscape"
+namespace sodipodi = "http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+namespace none = ""
+
+ sodipodi.anyempty.elem =
+ element sodipodi:*
+ { sodipodi.anyempty.inner
+ & sodipodi.anyempty.attrs
+ }
+ sodipodi.anyempty.attrs =
+ ( inkscape.attrs
+ & inkscape.nonamespace.anyattr*
+ )
+ sodipodi.anyempty.inner = ( empty )
+
+ inkscape.anyempty.elem =
+ element inkscape:*
+ { inkscape.anyempty.inner
+ & inkscape.anyempty.attrs
+ }
+ inkscape.anyempty.attrs =
+ ( inkscape.attrs
+ & inkscape.nonamespace.anyattr*
+ )
+ inkscape.anyempty.inner = ( empty )
+
+ inkscape.elem =
+ ( sodipodi.anyempty.elem
+ | inkscape.anyempty.elem
+ )
+
+ inkscape.attrs =
+ ( inkspace.anyattr*
+ & sodipodi.anyattr*
+ )
+ inkspace.anyattr =
+ attribute inkscape:* { string }
+ sodipodi.anyattr =
+ attribute sodipodi:* { string }
+
+ inkscape.nonamespace.anyattr =
+ attribute none:* { string }
+
+SVG.Core.extra.attrib &= inkscape.attrs
+SVG.defs.content &= inkscape.elem*
+SVG.g.content &= inkscape.elem*
+SVG.svg.content &= inkscape.elem*
diff --git a/xml/relaxng/src/resources/html5-schema/its20-html5-types.rnc b/xml/relaxng/src/resources/html5-schema/its20-html5-types.rnc
new file mode 100644
index 0000000..8d16ccc
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/its20-html5-types.rnc
@@ -0,0 +1,151 @@
+# Copyright (c) 2012 Jirka Kosek <jirka@kosek.cz>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+datatypes w = "http://whattf.org/datatype-draft"
+
+its-confidence.type = xsd:double { minInclusive = "0" maxInclusive = "1" }
+
+its-locNote.type = string
+
+## The type of localization note
+its-locNoteType.type =
+ ## Localization note is an alert
+ w:string "alert"
+ |
+ ## Localization note is a description
+ w:string "description"
+
+its-locNoteRef.type = w:iri-ref
+
+its-termInfoRef.type = w:iri-ref
+
+## Indicates a term locally
+its-term.type =
+ ## The value 'yes' means that this is a term
+ w:string "yes"
+ |
+ ## The value 'no' means that this is not a term
+ w:string "no"
+
+its-termConfidence.type = its-confidence.type
+
+## States whether current context is regarded as "within text"
+its-withinText.type =
+ ## The element and its content are part of the flow of its parent element
+ w:string "yes"
+ |
+ ## The element splits the text flow of its parent element and its content is an independent text flow
+ w:string "no"
+ |
+ ## The element is part of the flow of its parent element, its content is an independent flow
+ w:string "nested"
+
+## A comma separated list of mappings between values in the content
+## and workflow specific values. The values may contain spaces; in
+## that case they MUST be delimited by quotation marks.
+its-domainMapping.type = string
+
+its-taConfidence.type = its-confidence.type
+
+its-taClassRef.type = w:iri-ref
+
+its-taIdentRef.type = w:iri-ref
+
+its-taIdent.type = string
+
+its-taSource.type = string
+
+its-localeFilterList.type = string
+
+its-localeFilterType.type = w:string "include" | w:string "exclude"
+
+its-person.type = string
+
+its-personRef.type = w:iri-ref
+
+its-org.type = string
+
+its-orgRef.type = w:iri-ref
+
+its-tool.type = string
+
+its-toolRef.type = w:iri-ref
+
+its-revPerson.type = string
+
+its-revPersonRef.type = w:iri-ref
+
+its-revOrg.type = string
+
+its-revOrgRef.type = w:iri-ref
+
+its-revTool.type = string
+
+its-revToolRef.type = w:iri-ref
+
+its-provRef.type = list { w:iri-ref+ }
+
+its-provenanceRecordsRef.type = w:iri-ref
+
+its-idValue.type = string
+
+its-space.type = "default" | "preserve"
+
+its-locQualityIssuesRef.type = w:iri-ref
+
+its-locQualityIssueType.type = w:string "terminology" | w:string "mistranslation" |
+ w:string "omission" | w:string "untranslated" | w:string "addition" | w:string "duplication" |
+ w:string "inconsistency" | w:string "grammar" | w:string "legal" | w:string "register" |
+ w:string "locale-specific-content" | w:string "locale-violation" | w:string "style" |
+ w:string "characters" | w:string "misspelling" | w:string "typographical" | w:string "formatting" |
+ w:string "inconsistent-entities" | w:string "numbers" | w:string "markup" | w:string "pattern-problem" |
+ w:string "whitespace" | w:string "internationalization" | w:string "length" | w:string "non-conformance" | w:string "uncategorized" |
+ w:string "other"
+
+its-locQualityIssueComment.type = string
+
+its-locQualityIssueSeverity.type = xsd:double { minInclusive = "0" maxInclusive = "100" }
+
+its-locQualityIssueProfileRef.type = w:iri-ref
+
+its-locQualityIssueEnabled.type = w:string "yes" | w:string "no"
+
+its-locQualityRatingScore.type = xsd:double { minInclusive = "0" maxInclusive = "100" }
+
+its-locQualityRatingVote.type = xsd:integer
+
+its-locQualityRatingScoreThreshold.type = xsd:double { minInclusive = "0" maxInclusive = "100" }
+
+its-locQualityRatingVoteThreshold.type = xsd:integer
+
+its-locQualityRatingProfileRef.type = w:iri-ref
+
+its-mtConfidence.type = its-confidence.type
+
+its-allowedCharacters.type = string
+
+its-storageSize.type = xsd:nonNegativeInteger
+
+its-storageEncoding.type = string
+
+its-lineBreakType.type = w:string "cr" | w:string "lf" | w:string "crlf"
+
+its-annotatorsRef.type = string
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/its20-html5.rnc b/xml/relaxng/src/resources/html5-schema/its20-html5.rnc
new file mode 100644
index 0000000..c0c8e48
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/its20-html5.rnc
@@ -0,0 +1,143 @@
+# Copyright (c) 2012 Jirka Kosek <jirka@kosek.cz>
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+include "its20-html5-types.rnc"
+
+its-attribute.locNote.html = attribute its-loc-note { its-locNote.type }
+
+its-attribute.locNoteType.html = attribute its-loc-note-type { its-locNoteType.type }
+
+its-attribute.locNoteRef.html = attribute its-loc-note-ref { its-locNoteRef.type }
+
+its-attribute.termInfoRef.html = attribute its-term-info-ref { its-termInfoRef.type }
+
+its-attribute.term.html = attribute its-term { its-term.type }
+
+its-attribute.termConfidence.html = attribute its-term-confidence { its-termConfidence.type }
+
+its-attribute.withinText.html = attribute its-within-text { its-withinText.type }
+
+its-attribute.domainMapping.html = attribute its-domain-mapping { its-domainMapping.type }
+
+its-attribute.taConfidence.html = attribute its-ta-confidence { its-taConfidence.type }
+
+its-attribute.taClassRef.html = attribute its-ta-class-ref { its-taClassRef.type }
+
+its-attribute.taIdent.html = attribute its-ta-ident { its-taIdent.type }
+
+its-attribute.taIdentRef.html = attribute its-ta-ident-ref { its-taIdentRef.type }
+
+its-attribute.taSource.html = attribute its-ta-source { its-taSource.type }
+
+its-attribute.localeFilterList.html = attribute its-locale-filter-list { its-localeFilterList.type }
+
+its-attribute.localeFilterType.html = attribute its-locale-filter-type { its-localeFilterType.type }
+
+its-attribute.person.html = attribute its-person { its-person.type }
+
+its-attribute.personRef.html = attribute its-person-ref { its-personRef.type }
+
+its-attribute.org.html = attribute its-org { its-org.type }
+
+its-attribute.orgRef.html = attribute its-org-ref { its-orgRef.type }
+
+its-attribute.tool.html = attribute its-tool { its-tool.type }
+
+its-attribute.toolRef.html = attribute its-tool-ref { its-toolRef.type }
+
+its-attribute.revPerson.html = attribute its-rev-person { its-revPerson.type }
+
+its-attribute.revPersonRef.html = attribute its-rev-person-ref { its-revPersonRef.type }
+
+its-attribute.revOrg.html = attribute its-rev-org { its-revOrg.type }
+
+its-attribute.revOrgRef.html = attribute its-rev-org-ref { its-revOrgRef.type }
+
+its-attribute.revTool.html = attribute its-rev-tool { its-revTool.type }
+
+its-attribute.revToolRef.html = attribute its-rev-tool-ref { its-revToolRef.type }
+
+its-attribute.provRef.html = attribute its-prov-ref { its-provRef.type }
+
+its-attribute.provenanceRecordsRef.html = attribute its-provenance-records-ref { its-provenanceRecordsRef.type }
+
+its-attribute.locQualityIssuesRef.html = attribute its-loc-quality-issues-ref { its-locQualityIssuesRef.type }
+
+its-attribute.locQualityIssueType.html = attribute its-loc-quality-issue-type { its-locQualityIssueType.type }
+
+its-attribute.locQualityIssueComment.html = attribute its-loc-quality-issue-comment { its-locQualityIssueComment.type }
+
+its-attribute.locQualityIssueSeverity.html = attribute its-loc-quality-issue-severity { its-locQualityIssueSeverity.type }
+
+its-attribute.locQualityIssueProfileRef.html = attribute its-loc-quality-issue-profile-ref { its-locQualityIssueProfileRef.type }
+
+its-attribute.locQualityIssueEnabled.html = attribute its-loc-quality-issue-enabled { its-locQualityIssueEnabled.type }
+
+its-attribute.locQualityRatingScore.html = attribute its-loc-quality-rating-score { its-locQualityRatingScore.type }
+
+its-attribute.locQualityRatingVote.html = attribute its-loc-quality-rating-vote { its-locQualityRatingVote.type }
+
+its-attribute.locQualityRatingScoreThreshold.html = attribute its-loc-quality-rating-score-threshold { its-locQualityRatingScoreThreshold.type }
+
+its-attribute.locQualityRatingVoteThreshold.html = attribute its-loc-quality-rating-vote-threshold { its-locQualityRatingVoteThreshold.type }
+
+its-attribute.locQualityRatingProfileRef.html = attribute its-loc-quality-rating-profile-ref { its-locQualityRatingProfileRef.type }
+
+its-attribute.mtConfidence.html = attribute its-mt-confidence { its-mtConfidence.type }
+
+its-attribute.allowedCharacters.html = attribute its-allowed-characters { its-allowedCharacters.type }
+
+its-attribute.storageSize.html = attribute its-storage-size { its-storageSize.type }
+
+its-attribute.storageEncoding.html = attribute its-storage-encoding { its-storageEncoding.type }
+
+its-attribute.lineBreakType.html = attribute its-line-break-type { its-lineBreakType.type }
+
+its-attribute.annotatorsRef.html = attribute its-annotators-ref { its-annotatorsRef.type }
+
+its-html-attributes =
+ ((its-attribute.locNote.html | its-attribute.locNoteRef.html), its-attribute.locNoteType.html?)? &
+ (its-attribute.term.html, its-attribute.termInfoRef.html?, its-attribute.termConfidence.html?)? &
+ its-attribute.withinText.html? &
+ (its-attribute.taConfidence.html? &
+ (its-attribute.taClassRef.html? &
+ ((its-attribute.taSource.html, its-attribute.taIdent.html) | its-attribute.taIdentRef.html)?)) &
+ (its-attribute.localeFilterList.html, its-attribute.localeFilterType.html?)? &
+ ((
+ (its-attribute.person.html | its-attribute.personRef.html )? &
+ (its-attribute.org.html | its-attribute.orgRef.html )? &
+ (its-attribute.tool.html | its-attribute.toolRef.html )? &
+ (its-attribute.revPerson.html | its-attribute.revPersonRef.html )? &
+ (its-attribute.revOrg.html | its-attribute.revOrgRef.html )? &
+ (its-attribute.revTool.html | its-attribute.revToolRef.html )? &
+ its-attribute.provRef.html?)
+ | its-attribute.provenanceRecordsRef.html)? &
+ (its-attribute.locQualityIssuesRef.html
+ |
+ ((its-attribute.locQualityIssueType.html? & its-attribute.locQualityIssueComment.html?) & its-attribute.locQualityIssueSeverity.html? & its-attribute.locQualityIssueProfileRef.html? & its-attribute.locQualityIssueEnabled.html?)
+ )? &
+ (((its-attribute.locQualityRatingScore.html, its-attribute.locQualityRatingScoreThreshold.html?) | (its-attribute.locQualityRatingVote.html, its-attribute.locQualityRatingVoteThreshold.html?)), its-attribute.locQualityRatingProfileRef.html?)? &
+ its-attribute.mtConfidence.html? &
+ its-attribute.allowedCharacters.html? &
+ (its-attribute.storageSize.html, its-attribute.storageEncoding.html?, its-attribute.lineBreakType.html?)? &
+ its-attribute.annotatorsRef.html?
+
+# FIXME: Find way how to validate stand-off markup inside <script>
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc b/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc
new file mode 100644
index 0000000..e64f770
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/legacy/legacy.rnc
@@ -0,0 +1,1415 @@
+datatypes w = "http://whattf.org/datatype-draft"
+# #####################################################################
+## RELAX NG Schema for HTML 5: Obsolete Elements and Attributes #
+# #####################################################################
+
+## In order to work around RELAX NG limitations and to thereby get more
+## useful error messages, the following elements and attributes are
+## allowed here but disallowed in the assertions-checking code.
+
+## Obsolete elements
+
+## Centering: <center>
+
+ center.elem =
+ element center { center.inner & center.attrs }
+ center.attrs =
+ ( common.attrs )
+ center.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= center.elem
+
+## Inline Styling: <font>
+
+ font.elem =
+ element font { font.inner & font.attrs }
+ font.attrs =
+ ( common.attrs
+ & font.attrs.color?
+ & font.attrs.face?
+ & font.attrs.size?
+ & common.attrs.aria?
+ )
+ font.attrs.color =
+ attribute color {
+ string
+ }
+ font.attrs.face =
+ attribute face {
+ string
+ }
+ font.attrs.size =
+ attribute size {
+ string
+ }
+ font.inner =
+ ( common.inner.phrasing )
+
+ common.elem.phrasing |= font.elem
+
+## Base Font Size: <basefont>
+
+ basefont.elem =
+ element basefont { empty & basefont.attrs }
+ basefont.attrs =
+ ( common.attrs
+ & basefont.attrs.color?
+ & basefont.attrs.face?
+ & basefont.attrs.size?
+ )
+ basefont.attrs.color =
+ attribute color {
+ string
+ }
+ basefont.attrs.face =
+ attribute face {
+ string
+ }
+ basefont.attrs.size =
+ attribute size {
+ string
+ }
+
+ common.elem.flow |= basefont.elem
+
+## Larger Font: <big>
+
+ big.elem =
+ element big { big.inner & big.attrs }
+ big.attrs =
+ ( common.attrs )
+ big.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= big.elem
+
+## Struck Text: <strike>
+
+ strike.elem =
+ element strike { strike.inner & strike.attrs }
+ strike.attrs =
+ ( common.attrs )
+ strike.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= strike.elem
+
+## Teletype: <tt>
+
+ tt.elem =
+ element tt { tt.inner & tt.attrs }
+ tt.attrs =
+ ( common.attrs )
+ tt.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= tt.elem
+
+## Abbreviation: <acronym>
+
+ acronym.elem =
+ element acronym { acronym.inner & acronym.attrs }
+ acronym.attrs =
+ ( common.attrs )
+ acronym.inner =
+ ( common.inner.flow )
+
+ common.elem.phrasing |= acronym.elem
+
+## Directory: <dir>
+
+ dir.elem =
+ element dir { dir.inner & dir.attrs }
+ dir.attrs =
+ ( common.attrs
+ & dir.attrs.compact?
+ )
+ dir.attrs.compact =
+ attribute compact {
+ string
+ }
+ dir.inner =
+ ( li.elem* )
+
+ common.elem.flow |= dir.elem
+
+## Java Applets: <applet>
+
+ applet.elem.flow =
+ element applet { applet.inner.flow & applet.attrs }
+ applet.elem.phrasing =
+ element applet { applet.inner.phrasing & applet.attrs }
+ applet.attrs =
+ ( common.attrs
+ & applet.attrs.archive?
+ & applet.attrs.code
+ & applet.attrs.codebase?
+ & applet.attrs.name?
+ & applet.attrs.height
+ & applet.attrs.width
+ )
+ applet.attrs.archive =
+ attribute archive {
+ common.data.uri #FIXME *comma* separated URI list (*grumble*)
+ }
+ applet.attrs.code =
+ attribute code {
+ token
+ }
+ applet.attrs.codebase =
+ attribute codebase {
+ common.data.uri
+ }
+ applet.attrs.name =
+ attribute name {
+ string #FIXME refine
+ }
+ applet.attrs.height =
+ attribute height {
+ common.data.integer.positive
+ }
+ applet.attrs.width =
+ attribute width {
+ common.data.integer.positive
+ }
+ applet.inner.flow =
+ ( param.elem*
+ , common.inner.flow
+ )
+ applet.inner.phrasing =
+ ( param.elem*
+ , common.inner.phrasing
+ )
+
+ common.elem.flow |= applet.elem.flow
+ common.elem.phrasing |= applet.elem.phrasing
+
+## Frame Set: <frameset>
+
+ frameset.elem =
+ element frameset { frameset.inner & frameset.attrs }
+ frameset.attrs =
+ ( common.attrs
+ & frameset.attrs.rows?
+ & frameset.attrs.columns?
+ & frameset.attrs.onunload?
+ )
+ frameset.attrs.rows =
+ attribute rows {
+ string
+ }
+ frameset.attrs.columns =
+ attribute columns {
+ string
+ }
+ frameset.attrs.onunload =
+ attribute onunload {
+ string
+ }
+ frameset.inner =
+ (
+ ( frameset.elem
+ | frame.elem
+ )+
+ & noframes.elem?
+ )
+
+## Frame: <frame>
+
+ frame.elem =
+ element frame { empty & frame.attrs }
+ frame.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & frame.attrs.longdesc?
+ & frame.attrs.name?
+ & frame.attrs.src?
+ & frame.attrs.frameborder?
+ & frame.attrs.marginwidth?
+ & frame.attrs.marginheight?
+ & frame.attrs.noresize?
+ & frame.attrs.scrolling?
+ )
+ frame.attrs.longdesc =
+ attribute longdesc {
+ string
+ }
+ frame.attrs.name =
+ attribute name {
+ string
+ }
+ frame.attrs.src =
+ attribute src {
+ string
+ }
+ frame.attrs.frameborder =
+ attribute frameborder {
+ string
+ }
+ frame.attrs.marginwidth =
+ attribute marginwidth {
+ string
+ }
+ frame.attrs.marginheight =
+ attribute marginheight {
+ string
+ }
+ frame.attrs.noresize =
+ attribute noresize {
+ string
+ }
+ frame.attrs.scrolling =
+ attribute scrolling {
+ string
+ }
+
+## Alternate no-frames content: <noframes>
+
+ noframes.elem =
+ element noframes { noframes.inner & noframes.attrs }
+ noframes.attrs =
+ ( common.attrs )
+ noframes.inner =
+ ( common.inner.flow )
+
+ common.elem.flow |= noframes.elem
+
+## "content-language" pragma directive: <meta http-equiv='content-language'>
+
+ meta.http-equiv.content-language.elem =
+ element meta { meta.inner & meta.http-equiv.content-language.attrs }
+ meta.http-equiv.content-language.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.content-language
+ & meta.http-equiv.attrs.content.content-language?
+ )
+ meta.http-equiv.attrs.http-equiv.content-language =
+ attribute http-equiv {
+ w:string "content-language"
+ }
+ meta.http-equiv.attrs.content.content-language =
+ attribute content {
+ string
+ }
+
+ common.elem.metadata |= meta.http-equiv.content-language.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+## Obsolete attributes
+
+## abbr attribute
+
+ td.attrs.abbr =
+ attribute abbr {
+ string
+ }
+ td.attrs &= td.attrs.abbr?
+
+ th.attrs.abbr =
+ attribute abbr {
+ string
+ }
+ th.attrs &= th.attrs.abbr?
+
+## archive attribute
+
+ object.attrs.archive =
+ attribute archive {
+ string
+ }
+ object.attrs &= object.attrs.archive?
+
+## axis attribute
+
+ td.attrs.axis =
+ attribute axis {
+ string
+ }
+ td.attrs &= td.attrs.axis?
+
+ th.attrs.axis =
+ attribute axis {
+ string
+ }
+ th.attrs &= th.attrs.axis?
+
+## charset attribute
+
+ link.attrs.charset =
+ attribute charset {
+ string
+ }
+ link.attrs &= link.attrs.charset?
+
+ a.attrs.charset =
+ attribute charset {
+ string
+ }
+ a.attrs &= a.attrs.charset?
+
+## classid attribute
+
+ object.attrs.classid =
+ attribute classid {
+ common.data.uri
+ }
+ object.attrs &= object.attrs.classid?
+
+## codebase attribute
+
+ object.attrs.codebase =
+ attribute codebase {
+ common.data.uri
+ }
+ object.attrs &= object.attrs.codebase?
+
+## codetype attribute
+
+ object.attrs.codetype =
+ attribute codetype {
+ common.data.mimetype
+ }
+ object.attrs &= object.attrs.codetype?
+
+## code attribute
+
+ object.attrs.code =
+ attribute code {
+ token
+ }
+ object.attrs &= object.attrs.code?
+
+## coords attribute
+
+ a.attrs.coords =
+ attribute coords {
+ string
+ }
+ a.attrs &= a.attrs.coords?
+
+## declare attribute
+
+ object.attrs.declare =
+ attribute declare {
+ string
+ }
+ object.attrs &= object.attrs.declare?
+
+## longdesc attribute
+
+ img.attrs.longdesc =
+ attribute longdesc {
+ common.data.uri.non-empty
+ }
+ img.attrs &= img.attrs.longdesc?
+
+ iframe.attrs.longdesc =
+ attribute longdesc {
+ string
+ }
+ iframe.attrs &= iframe.attrs.longdesc?
+
+## methods attribute
+
+ a.attrs.methods =
+ attribute methods {
+ string
+ }
+ a.attrs &= a.attrs.methods?
+
+ link.attrs.methods =
+ attribute methods {
+ string
+ }
+ link.attrs &= link.attrs.methods?
+
+## name attribute
+
+ img.attrs.name =
+ attribute name {
+ string
+ }
+ img.attrs &= img.attrs.name?
+
+ embed.attrs.name =
+ attribute name {
+ string
+ }
+ embed.attrs &= embed.attrs.name?
+
+ option.attrs.name =
+ attribute name {
+ string
+ }
+ option.attrs &= option.attrs.name?
+
+## nohref attribute
+
+ area.attrs.nohref =
+ attribute nohref {
+ string
+ }
+ area.attrs &= area.attrs.nohref?
+
+## profile attribute
+
+ head.attrs.profile =
+ attribute profile {
+ string
+ }
+ head.attrs &= head.attrs.profile?
+
+## rev attribute
+
+ link.attrs.rev =
+ attribute rev {
+ string
+ }
+ link.attrs &= link.attrs.rev?
+
+ a.attrs.rev =
+ attribute rev {
+ string
+ }
+ a.attrs &= a.attrs.rev?
+
+## scheme attribute
+
+ meta.attrs.scheme =
+ attribute scheme {
+ string
+ }
+ meta.name.attrs &= meta.attrs.scheme?
+
+## scope attribute
+
+ td.attrs.scope =
+ attribute scope {
+ string
+ }
+ td.attrs &= td.attrs.scope?
+
+## shape attribute
+
+ a.attrs.shape =
+ attribute shape {
+ string
+ }
+ a.attrs &= a.attrs.shape?
+
+## standby attribute
+
+ object.attrs.standby =
+ attribute standby {
+ string
+ }
+ object.attrs &= object.attrs.standby?
+
+## target attribute
+
+ link.attrs.target =
+ attribute target {
+ string
+ }
+ link.attrs &= link.attrs.target?
+
+## type attribute
+
+ param.attrs.type =
+ attribute type {
+ string
+ }
+ param.attrs &= param.attrs.type?
+
+## urn attribute
+
+ a.attrs.urn =
+ attribute urn {
+ string
+ }
+ a.attrs &= a.attrs.urn?
+
+ link.attrs.urn =
+ attribute urn {
+ string
+ }
+ link.attrs &= link.attrs.urn?
+
+## usemap attribute
+
+ input.attrs.usemap =
+ attribute usemap {
+ string
+ }
+ input.image.attrs &= input.attrs.usemap?
+
+## valuetype attribute
+
+ param.attrs.valuetype =
+ attribute valuetype {
+ string
+ }
+ param.attrs &= param.attrs.valuetype?
+
+## version attribute
+
+ html.attrs.version =
+ attribute version {
+ string
+ }
+ html.attrs &= html.attrs.version?
+
+## Obsolete style attributes
+
+## align attribute
+
+ caption.attrs.align =
+ attribute align {
+ string
+ }
+ caption.attrs &= caption.attrs.align?
+
+ col.attrs.align =
+ attribute align {
+ string
+ }
+ col.attrs &= col.attrs.align?
+
+ colgroup.attrs.align =
+ attribute align {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.align?
+
+ div.attrs.align =
+ attribute align {
+ string
+ }
+ div.attrs &= div.attrs.align?
+
+ embed.attrs.align =
+ attribute align {
+ string
+ }
+ embed.attrs &= embed.attrs.align?
+
+ h1.attrs.align =
+ attribute align {
+ string
+ }
+ h1.attrs &= h1.attrs.align?
+
+ h2.attrs.align =
+ attribute align {
+ string
+ }
+ h2.attrs &= h2.attrs.align?
+
+ h3.attrs.align =
+ attribute align {
+ string
+ }
+ h3.attrs &= h3.attrs.align?
+
+ h4.attrs.align =
+ attribute align {
+ string
+ }
+ h4.attrs &= h4.attrs.align?
+
+ h5.attrs.align =
+ attribute align {
+ string
+ }
+ h5.attrs &= h5.attrs.align?
+
+ h6.attrs.align =
+ attribute align {
+ string
+ }
+ h6.attrs &= h6.attrs.align?
+
+ hr.attrs.align =
+ attribute align {
+ string
+ }
+ hr.attrs &= hr.attrs.align?
+
+ iframe.attrs.align =
+ attribute align {
+ string
+ }
+ iframe.attrs &= iframe.attrs.align?
+
+ img.attrs.align =
+ attribute align {
+ string
+ }
+ img.attrs &= img.attrs.align?
+
+ input.attrs.align =
+ attribute align {
+ string
+ }
+ input.text.attrs &= input.attrs.align?
+ input.password.attrs &= input.attrs.align?
+ input.checkbox.attrs &= input.attrs.align?
+ input.radio.attrs &= input.attrs.align?
+ input.button.attrs &= input.attrs.align?
+ input.submit.attrs &= input.attrs.align?
+ input.reset.attrs &= input.attrs.align?
+ input.file.attrs &= input.attrs.align?
+ input.image.attrs &= input.attrs.align?
+ input.datetime.attrs &= input.attrs.align?
+ input.datetime-local.attrs &= input.attrs.align?
+ input.date.attrs &= input.attrs.align?
+ input.month.attrs &= input.attrs.align?
+ input.time.attrs &= input.attrs.align?
+ input.week.attrs &= input.attrs.align?
+ input.number.attrs &= input.attrs.align?
+ input.range.attrs &= input.attrs.align?
+ input.email.attrs &= input.attrs.align?
+ input.url.attrs &= input.attrs.align?
+ input.search.attrs &= input.attrs.align?
+ input.tel.attrs &= input.attrs.align?
+ input.color.attrs &= input.attrs.align?
+
+ legend.attrs.align =
+ attribute align {
+ string
+ }
+ legend.attrs &= legend.attrs.align?
+
+ object.attrs.align =
+ attribute align {
+ string
+ }
+ object.attrs &= object.attrs.align?
+
+ p.attrs.align =
+ attribute align {
+ string
+ }
+ p.attrs &= p.attrs.align?
+
+ table.attrs.align =
+ attribute align {
+ string
+ }
+ table.attrs &= table.attrs.align?
+
+ tbody.attrs.align =
+ attribute align {
+ string
+ }
+ tbody.attrs &= tbody.attrs.align?
+
+ td.attrs.align =
+ attribute align {
+ string
+ }
+ td.attrs &= td.attrs.align?
+
+ tfoot.attrs.align =
+ attribute align {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.align?
+
+ th.attrs.align =
+ attribute align {
+ string
+ }
+ th.attrs &= th.attrs.align?
+
+ thead.attrs.align =
+ attribute align {
+ string
+ }
+ thead.attrs &= thead.attrs.align?
+
+ tr.attrs.align =
+ attribute align {
+ string
+ }
+ tr.attrs &= tr.attrs.align?
+
+## alink attribute
+
+ body.attrs.alink =
+ attribute alink {
+ string
+ }
+ body.attrs &= body.attrs.alink?
+
+ iframe.attrs.allowtransparency =
+ attribute allowtransparency {
+ string
+ }
+ iframe.attrs &= iframe.attrs.allowtransparency?
+
+## background attribute
+
+ body.attrs.background =
+ attribute background {
+ string
+ }
+ body.attrs &= body.attrs.background?
+
+## color attribute
+
+ hr.attrs.color =
+ attribute color {
+ string
+ }
+ hr.attrs &= hr.attrs.color?
+
+
+## bgcolor attribute
+
+ body.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ body.attrs &= body.attrs.bgcolor?
+
+ table.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ table.attrs &= table.attrs.bgcolor?
+
+ tr.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ tr.attrs &= tr.attrs.bgcolor?
+
+ td.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ td.attrs &= td.attrs.bgcolor?
+
+ th.attrs.bgcolor =
+ attribute bgcolor {
+ string
+ }
+ th.attrs &= th.attrs.bgcolor?
+
+## border attribute
+
+ object.attrs.border =
+ attribute border {
+ string
+ }
+ object.attrs &= object.attrs.border?
+
+## cellpadding attribute
+
+ table.attrs.cellpadding =
+ attribute cellpadding {
+ string
+ }
+ table.attrs &= table.attrs.cellpadding?
+
+## cellspacing attribute
+
+ table.attrs.cellspacing =
+ attribute cellspacing {
+ string
+ }
+ table.attrs &= table.attrs.cellspacing?
+
+## char attribute
+
+ col.attrs.char =
+ attribute char {
+ string
+ }
+ col.attrs &= col.attrs.char?
+
+ colgroup.attrs.char =
+ attribute char {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.char?
+
+ tbody.attrs.char =
+ attribute char {
+ string
+ }
+ tbody.attrs &= tbody.attrs.char?
+
+ td.attrs.char =
+ attribute char {
+ string
+ }
+ td.attrs &= td.attrs.char?
+
+ tfoot.attrs.char =
+ attribute char {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.char?
+
+ th.attrs.char =
+ attribute char {
+ string
+ }
+ th.attrs &= th.attrs.char?
+
+ thead.attrs.char =
+ attribute char {
+ string
+ }
+ thead.attrs &= thead.attrs.char?
+
+ tr.attrs.char =
+ attribute char {
+ string
+ }
+ tr.attrs &= tr.attrs.char?
+
+## charoff attribute
+
+ col.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ col.attrs &= col.attrs.charoff?
+
+ colgroup.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.charoff?
+
+ tbody.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ tbody.attrs &= tbody.attrs.charoff?
+
+ td.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ td.attrs &= td.attrs.charoff?
+
+ tfoot.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.charoff?
+
+ th.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ th.attrs &= th.attrs.charoff?
+
+ thead.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ thead.attrs &= thead.attrs.charoff?
+
+ tr.attrs.charoff =
+ attribute charoff {
+ string
+ }
+ tr.attrs &= tr.attrs.charoff?
+
+## clear attribute
+
+ br.attrs.clear =
+ attribute clear {
+ string
+ }
+ br.attrs &= br.attrs.clear?
+
+## compact attribute
+
+ dl.attrs.compact =
+ attribute compact {
+ string
+ }
+ dl.attrs &= dl.attrs.compact?
+
+ menu.attrs.compact =
+ attribute compact {
+ string
+ }
+ menu.attrs &= menu.attrs.compact?
+
+ ol.attrs.compact =
+ attribute compact {
+ string
+ }
+ ol.attrs &= ol.attrs.compact?
+
+ ul.attrs.compact =
+ attribute compact {
+ string
+ }
+ ul.attrs &= ul.attrs.compact?
+
+## frame attribute
+
+ table.attrs.frame =
+ attribute frame {
+ string
+ }
+ table.attrs &= table.attrs.frame?
+
+## frameborder attribute
+
+ iframe.attrs.frameborder =
+ attribute frameborder {
+ string
+ }
+ iframe.attrs &= iframe.attrs.frameborder?
+
+## height attribute
+
+ td.attrs.height =
+ attribute height {
+ string
+ }
+ td.attrs &= td.attrs.height?
+
+ th.attrs.height =
+ attribute height {
+ string
+ }
+ th.attrs &= th.attrs.height?
+
+## hspace attribute
+
+ img.attrs.hspace =
+ attribute hspace {
+ string
+ }
+ img.attrs &= img.attrs.hspace?
+
+ object.attrs.hspace =
+ attribute hspace {
+ string
+ }
+ object.attrs &= object.attrs.hspace?
+
+## link attribute
+
+ body.attrs.link =
+ attribute link {
+ string
+ }
+ body.attrs &= body.attrs.link?
+
+## marginbottom attribute
+
+ body.attrs.marginbottom =
+ attribute marginbottom {
+ string
+ }
+ body.attrs &= body.attrs.marginbottom?
+
+## marginheight attribute
+
+ body.attrs.marginheight =
+ attribute marginheight {
+ string
+ }
+ body.attrs &= body.attrs.marginheight?
+
+ iframe.attrs.marginheight =
+ attribute marginheight {
+ string
+ }
+ iframe.attrs &= iframe.attrs.marginheight?
+
+## marginleft attribute
+
+ body.attrs.marginleft =
+ attribute marginleft {
+ string
+ }
+ body.attrs &= body.attrs.marginleft?
+
+## marginright attribute
+
+ body.attrs.marginright =
+ attribute marginright {
+ string
+ }
+ body.attrs &= body.attrs.marginright?
+
+## margintop attribute
+
+ body.attrs.margintop =
+ attribute margintop {
+ string
+ }
+ body.attrs &= body.attrs.margintop?
+
+## marginwidth attribute
+
+ body.attrs.marginwidth =
+ attribute marginwidth {
+ string
+ }
+ body.attrs &= body.attrs.marginwidth?
+
+ iframe.attrs.marginwidth =
+ attribute marginwidth {
+ string
+ }
+ iframe.attrs &= iframe.attrs.marginwidth?
+
+## noshade attribute
+
+ hr.attrs.noshade =
+ attribute noshade {
+ string
+ }
+ hr.attrs &= hr.attrs.noshade?
+
+## nowrap attribute
+
+ td.attrs.nowrap =
+ attribute nowrap {
+ string
+ }
+ td.attrs &= td.attrs.nowrap?
+
+ th.attrs.nowrap =
+ attribute nowrap {
+ string
+ }
+ th.attrs &= th.attrs.nowrap?
+
+## rules attribute
+
+ table.attrs.rules =
+ attribute rules {
+ string
+ }
+ table.attrs &= table.attrs.rules?
+
+## datapagesize attribute
+
+ table.attrs.datapagesize =
+ attribute datapagesize {
+ string
+ }
+ table.attrs &= table.attrs.datapagesize?
+
+## scrolling attribute
+
+ iframe.attrs.scrolling =
+ attribute scrolling {
+ string
+ }
+ iframe.attrs &= iframe.attrs.scrolling?
+
+## size attribute
+
+ hr.attrs.size =
+ attribute size {
+ string
+ }
+ hr.attrs &= hr.attrs.size?
+
+## summary attribute
+
+ table.attrs.summary =
+ attribute summary {
+ string
+ }
+ table.attrs &= table.attrs.summary?
+
+## text attribute
+
+ body.attrs.text =
+ attribute text {
+ string
+ }
+ body.attrs &= body.attrs.text?
+
+## type attribute
+
+ li.attrs.type =
+ attribute type {
+ string
+ }
+ li.attrs &= li.attrs.type?
+ oli.attrs &= li.attrs.type?
+
+ ul.attrs.type =
+ attribute type {
+ string
+ }
+ ul.attrs &= ul.attrs.type?
+
+## valign attribute
+
+ col.attrs.valign =
+ attribute valign {
+ string
+ }
+ col.attrs &= col.attrs.valign?
+
+ colgroup.attrs.valign =
+ attribute valign {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.valign?
+
+ table.attrs.valign =
+ attribute valign {
+ string
+ }
+ table.attrs &= table.attrs.valign?
+
+ tbody.attrs.valign =
+ attribute valign {
+ string
+ }
+ tbody.attrs &= tbody.attrs.valign?
+
+ td.attrs.valign =
+ attribute valign {
+ string
+ }
+ td.attrs &= td.attrs.valign?
+
+ tfoot.attrs.valign =
+ attribute valign {
+ string
+ }
+ tfoot.attrs &= tfoot.attrs.valign?
+
+ th.attrs.valign =
+ attribute valign {
+ string
+ }
+ th.attrs &= th.attrs.valign?
+
+ thead.attrs.valign =
+ attribute valign {
+ string
+ }
+ thead.attrs &= thead.attrs.valign?
+
+ tr.attrs.valign =
+ attribute valign {
+ string
+ }
+ tr.attrs &= tr.attrs.valign?
+
+## vlink attribute
+
+ body.attrs.vlink =
+ attribute vlink {
+ string
+ }
+ body.attrs &= body.attrs.vlink?
+
+## vspace attribute
+
+ img.attrs.vspace =
+ attribute vspace {
+ string
+ }
+ img.attrs &= img.attrs.vspace?
+
+ object.attrs.vspace =
+ attribute vspace {
+ string
+ }
+ object.attrs &= object.attrs.vspace?
+
+## width attribute
+
+ col.attrs.width =
+ attribute width {
+ string
+ }
+ col.attrs &= col.attrs.width?
+
+ colgroup.attrs.width =
+ attribute width {
+ string
+ }
+ colgroup.attrs &= colgroup.attrs.width?
+
+ hr.attrs.width =
+ attribute width {
+ string
+ }
+ hr.attrs &= hr.attrs.width?
+
+ pre.attrs.width =
+ attribute width {
+ string
+ }
+ pre.attrs &= pre.attrs.width?
+
+ table.attrs.width =
+ attribute width {
+ string
+ }
+ table.attrs &= table.attrs.width?
+
+ td.attrs.width =
+ attribute width {
+ string
+ }
+ td.attrs &= td.attrs.width?
+
+ th.attrs.width =
+ attribute width {
+ string
+ }
+ th.attrs &= th.attrs.width?
+
+## event attribute
+
+ script.attrs.event =
+ attribute event {
+ string
+ }
+ script.attrs.imported &= script.attrs.event?
+ script.attrs.embedded &= script.attrs.event?
+
+## for attribute
+
+ script.attrs.for =
+ attribute for {
+ string
+ }
+ script.attrs.imported &= script.attrs.for?
+ script.attrs.embedded &= script.attrs.for?
+
+## datafld attribute
+
+ legacy.attrs.datafld =
+ attribute datafld {
+ string
+ }
+ span.attrs &= legacy.attrs.datafld?
+ div.attrs &= legacy.attrs.datafld?
+ object.attrs &= legacy.attrs.datafld?
+ input.text.attrs &= legacy.attrs.datafld?
+ input.password.attrs &= legacy.attrs.datafld?
+ input.checkbox.attrs &= legacy.attrs.datafld?
+ input.radio.attrs &= legacy.attrs.datafld?
+ input.button.attrs &= legacy.attrs.datafld?
+ input.submit.attrs &= legacy.attrs.datafld?
+ input.reset.attrs &= legacy.attrs.datafld?
+ input.file.attrs &= legacy.attrs.datafld?
+ input.image.attrs &= legacy.attrs.datafld?
+ input.datetime.attrs &= legacy.attrs.datafld?
+ input.datetime-local.attrs &= legacy.attrs.datafld?
+ input.date.attrs &= legacy.attrs.datafld?
+ input.month.attrs &= legacy.attrs.datafld?
+ input.time.attrs &= legacy.attrs.datafld?
+ input.week.attrs &= legacy.attrs.datafld?
+ input.number.attrs &= legacy.attrs.datafld?
+ input.range.attrs &= legacy.attrs.datafld?
+ input.email.attrs &= legacy.attrs.datafld?
+ input.url.attrs &= legacy.attrs.datafld?
+ input.search.attrs &= legacy.attrs.datafld?
+ input.tel.attrs &= legacy.attrs.datafld?
+ input.color.attrs &= legacy.attrs.datafld?
+ select.attrs &= legacy.attrs.datafld?
+ textarea.attrs &= legacy.attrs.datafld?
+ button.submit.attrs &= legacy.attrs.datafld?
+ button.reset.attrs &= legacy.attrs.datafld?
+ button.button.attrs &= legacy.attrs.datafld?
+ table.attrs &= legacy.attrs.datafld?
+
+## dataformatas attribute
+
+ legacy.attrs.dataformatas =
+ attribute dataformatas {
+ string
+ }
+ span.attrs &= legacy.attrs.dataformatas?
+ div.attrs &= legacy.attrs.dataformatas?
+ object.attrs &= legacy.attrs.dataformatas?
+ input.attrs &= legacy.attrs.dataformatas?
+ input.text.attrs &= legacy.attrs.dataformatas?
+ input.password.attrs &= legacy.attrs.dataformatas?
+ input.checkbox.attrs &= legacy.attrs.dataformatas?
+ input.radio.attrs &= legacy.attrs.dataformatas?
+ input.button.attrs &= legacy.attrs.dataformatas?
+ input.submit.attrs &= legacy.attrs.dataformatas?
+ input.reset.attrs &= legacy.attrs.dataformatas?
+ input.file.attrs &= legacy.attrs.dataformatas?
+ input.image.attrs &= legacy.attrs.dataformatas?
+ input.datetime.attrs &= legacy.attrs.dataformatas?
+ input.datetime-local.attrs &= legacy.attrs.dataformatas?
+ input.date.attrs &= legacy.attrs.dataformatas?
+ input.month.attrs &= legacy.attrs.dataformatas?
+ input.time.attrs &= legacy.attrs.dataformatas?
+ input.week.attrs &= legacy.attrs.dataformatas?
+ input.number.attrs &= legacy.attrs.dataformatas?
+ input.range.attrs &= legacy.attrs.dataformatas?
+ input.email.attrs &= legacy.attrs.dataformatas?
+ input.url.attrs &= legacy.attrs.dataformatas?
+ input.search.attrs &= legacy.attrs.dataformatas?
+ input.tel.attrs &= legacy.attrs.dataformatas?
+ input.color.attrs &= legacy.attrs.dataformatas?
+ select.attrs &= legacy.attrs.dataformatas?
+ textarea.attrs &= legacy.attrs.dataformatas?
+ button.submit.attrs &= legacy.attrs.dataformatas?
+ button.reset.attrs &= legacy.attrs.dataformatas?
+ button.button.attrs &= legacy.attrs.dataformatas?
+ table.attrs &= legacy.attrs.dataformatas?
+
+## datasrc attribute
+
+ legacy.attrs.datasrc =
+ attribute datasrc {
+ string
+ }
+ span.attrs &= legacy.attrs.datasrc?
+ div.attrs &= legacy.attrs.datasrc?
+ object.attrs &= legacy.attrs.datasrc?
+ input.text.attrs &= legacy.attrs.datasrc?
+ input.password.attrs &= legacy.attrs.datasrc?
+ input.checkbox.attrs &= legacy.attrs.datasrc?
+ input.radio.attrs &= legacy.attrs.datasrc?
+ input.button.attrs &= legacy.attrs.datasrc?
+ input.submit.attrs &= legacy.attrs.datasrc?
+ input.reset.attrs &= legacy.attrs.datasrc?
+ input.file.attrs &= legacy.attrs.datasrc?
+ input.image.attrs &= legacy.attrs.datasrc?
+ input.datetime.attrs &= legacy.attrs.datasrc?
+ input.datetime-local.attrs &= legacy.attrs.datasrc?
+ input.date.attrs &= legacy.attrs.datasrc?
+ input.month.attrs &= legacy.attrs.datasrc?
+ input.time.attrs &= legacy.attrs.datasrc?
+ input.week.attrs &= legacy.attrs.datasrc?
+ input.number.attrs &= legacy.attrs.datasrc?
+ input.range.attrs &= legacy.attrs.datasrc?
+ input.email.attrs &= legacy.attrs.datasrc?
+ input.url.attrs &= legacy.attrs.datasrc?
+ input.search.attrs &= legacy.attrs.datasrc?
+ input.tel.attrs &= legacy.attrs.datasrc?
+ input.color.attrs &= legacy.attrs.datasrc?
+ select.attrs &= legacy.attrs.datasrc?
+ textarea.attrs &= legacy.attrs.datasrc?
+ button.submit.attrs &= legacy.attrs.datasrc?
+ button.reset.attrs &= legacy.attrs.datasrc?
+ button.button.attrs &= legacy.attrs.datasrc?
+ table.attrs &= legacy.attrs.datasrc?
diff --git a/xml/relaxng/src/resources/html5-schema/meta-ext.rnc b/xml/relaxng/src/resources/html5-schema/meta-ext.rnc
deleted file mode 100644
index b8c2b67..0000000
--- a/xml/relaxng/src/resources/html5-schema/meta-ext.rnc
+++ /dev/null
@@ -1,57 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-## "Content-Language" pragma directive: <meta http-equiv='Content-Language'>
-
- meta.http-equiv.content-language.elem =
- element meta { meta.inner & meta.http-equiv.content-language.attrs }
- meta.http-equiv.content-language.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.http-equiv.attrs.http-equiv.content-language
- & meta.http-equiv.attrs.content.content-language
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.http-equiv.attrs.http-equiv.content-language =
- attribute http-equiv {
- w:string "content-language"
- }
- meta.http-equiv.attrs.content.content-language =
- attribute content {
- common.data.string
- }
-
- common.elem.metadata |= meta.http-equiv.content-language.elem # not quite right per spec
- # if the definition is
- # reused in another language
-
-## "X-UA-Compatible" pragma directive: <meta http-equiv='X-UA-Compatible'>
-
- meta.http-equiv.x-ua-compatible.elem =
- element meta { meta.inner & meta.http-equiv.x-ua-compatible.attrs }
- meta.http-equiv.x-ua-compatible.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.http-equiv.attrs.http-equiv.x-ua-compatible
- & meta.http-equiv.attrs.content.x-ua-compatible
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.http-equiv.attrs.http-equiv.x-ua-compatible =
- attribute http-equiv {
- w:string "x-ua-compatible"
- }
- meta.http-equiv.attrs.content.x-ua-compatible =
- attribute content {
- common.data.string
- }
-
- common.elem.metadata |= meta.http-equiv.x-ua-compatible.elem # not quite right per spec
- # if the definition is
- # reused in another language
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/html5-schema/meta.rnc b/xml/relaxng/src/resources/html5-schema/meta.rnc
deleted file mode 100644
index 45c7f25..0000000
--- a/xml/relaxng/src/resources/html5-schema/meta.rnc
+++ /dev/null
@@ -1,364 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Global Structure & Metadata #
-# #####################################################################
-
-## Root Element: <html>
-
- html.elem =
- element html { html.inner & html.attrs }
- html.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- html.inner =
- ( head.elem
- , body.elem
- )
-
-## Metadata Container: <head>
-
- head.elem =
- element head { head.inner & head.attrs }
- head.attrs =
- ( common.attrs
-# & head.attrs.profile?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
-# head.attrs.profile =
-# attribute profile {
-# common.data.uris #REVISIT should these be absolute (zero or more)
-# }
- head.inner =
- ( title.elem
- & base.elem? # REVISIT need a non-schema checker or Schematron
- & common.inner.metadata # Limit encoding decl position in Schematron
- )
-# head.inner =
-# ( meta.elem.encoding?
-# , ( title.elem
-# & base.elem? # REVISIT need a non-schema checker or Schematron
-# & common.inner.metadata
-# )
-# )
-
-## Content Container: <body>
-
- body.elem =
- element body { body.inner & body.attrs }
- body.attrs =
- ( common.attrs
- & ( common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.document
- | common.attrs.aria.implicit.structure
- | common.attrs.aria.role.presentation
- )?
- & body.attrs.onafterprint?
- & body.attrs.onbeforeprint?
- & body.attrs.onbeforeunload?
- & body.attrs.onhashchange?
- & body.attrs.onmessage?
- & body.attrs.onoffline?
- & body.attrs.ononline?
- & body.attrs.onpagehide?
- & body.attrs.onpageshow?
- & body.attrs.onpopstate?
- & body.attrs.onresize?
- & body.attrs.onstorage?
- & body.attrs.onunload?
- )
- body.inner =
- ( common.inner.flow )
-
- body.attrs.onafterprint =
- attribute onafterprint { common.data.functionbody }
- body.attrs.onbeforeprint =
- attribute onbeforeprint { common.data.functionbody }
- body.attrs.onbeforeunload =
- attribute onbeforeunload { common.data.functionbody }
- body.attrs.onhashchange =
- attribute onhashchange { common.data.functionbody }
- body.attrs.onmessage =
- attribute onmessage { common.data.functionbody }
- body.attrs.onoffline =
- attribute onoffline { common.data.functionbody }
- body.attrs.ononline =
- attribute ononline { common.data.functionbody }
- body.attrs.onpopstate =
- attribute onpopstate { common.data.functionbody }
- body.attrs.onpagehide =
- attribute onpagehide { common.data.functionbody }
- body.attrs.onpageshow =
- attribute onpageshow { common.data.functionbody }
- body.attrs.onredo =
- attribute onredo { common.data.functionbody }
- body.attrs.onresize =
- attribute onresize { common.data.functionbody }
- body.attrs.onstorage =
- attribute onstorage { common.data.functionbody }
- body.attrs.onundo =
- attribute onundo { common.data.functionbody }
- body.attrs.onunload =
- attribute onunload { common.data.functionbody }
-
-## Document Title: <title>
-
- title.elem =
- element title { title.inner & title.attrs }
- title.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- title.inner =
- ( text )
-
-## Base URI: <base>
-
- base.elem =
- element base { base.inner & base.attrs }
- base.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & ( ( base.attrs.href
- & base.attrs.target?
- )
- | base.attrs.target
- )
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- base.attrs.href =
- attribute href {
- common.data.uri
- }
- base.attrs.target =
- attribute target {
- common.data.browsing-context-or-keyword
- }
- base.inner =
- ( empty )
-
-## Global Relationships: <link>
-
- link.elem =
- element link { link.inner & link.attrs }
- link.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & link.attrs.href
- & link.attrs.rel
- & shared-hyperlink.attrs.hreflang?
- & shared-hyperlink.attrs.media?
- & shared-hyperlink.attrs.type?
- & link.attrs.sizes?
- # link.attrs.title included in common.attrs
- & ( common.attrs.aria.role.link
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- link.attrs.href =
- attribute href {
- common.data.uri.non-empty
- }
- link.attrs.rel =
- attribute rel {
- w:link-rel
- }
- link.attrs.sizes =
- attribute sizes {
- w:string "any" | common.data.sizes
- }
- link.inner =
- ( empty )
-
- common.elem.metadata |= link.elem
-
-## Global Style: <style>
-
- style.elem =
- element style { style.inner & style.attrs }
- style.attrs =
- ( common.attrs
- & style.attrs.type?
- & style.attrs.media?
- # style.attrs.title included in common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- style.attrs.type =
- attribute type {
- common.data.mimetype
- }
- style.attrs.media =
- attribute media {
- common.data.mediaquery
- }
- style.inner =
- ( common.inner.anything )
-
- common.elem.metadata |= style.elem
-
-## Scoped Style: <style scoped>
-
- style.elem.scoped =
- element style { style.inner & style.scoped.attrs }
- style.scoped.attrs =
- ( common.attrs
- & style.attrs.type?
- & style.attrs.media?
- & style.attrs.scoped
- # style.attrs.title included in common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- style.attrs.scoped =
- attribute scoped {
- w:string "scoped" | w:string ""
- }
-
-## Name-Value Metadata: <meta name>
-
- meta.name.elem =
- element meta { meta.inner & meta.name.attrs }
- meta.name.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.name.attrs.name
- & meta.name.attrs.content
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.name.attrs.name =
- attribute name {
- w:meta-name
- }
- meta.name.attrs.content =
- attribute content {
- string
- }
- meta.inner =
- ( empty )
-
- common.elem.metadata |= meta.name.elem
-
-## "refresh" pragma directive: <meta http-equiv='refresh'>
-
- meta.http-equiv.refresh.elem =
- element meta { meta.inner & meta.http-equiv.refresh.attrs }
- meta.http-equiv.refresh.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.http-equiv.attrs.http-equiv.refresh
- & meta.http-equiv.attrs.content.refresh
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.http-equiv.attrs.http-equiv.refresh =
- attribute http-equiv {
- w:string "refresh"
- }
- meta.http-equiv.attrs.content.refresh =
- attribute content {
- common.data.refresh
- }
- common.elem.metadata |= meta.http-equiv.refresh.elem # not quite right per spec
- # if the definition is
- # reused in another language
-
-## "default-style" pragma directive: <meta http-equiv='default-style'>
-
- meta.http-equiv.default-style.elem =
- element meta { meta.inner & meta.http-equiv.default-style.attrs }
- meta.http-equiv.default-style.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.http-equiv.attrs.http-equiv.default-style
- & meta.http-equiv.attrs.content.default-style
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.http-equiv.attrs.http-equiv.default-style =
- attribute http-equiv {
- w:string "default-style"
- }
- meta.http-equiv.attrs.content.default-style =
- attribute content {
- common.data.default-style
- }
-
- common.elem.metadata |= meta.http-equiv.default-style.elem # not quite right per spec
- # if the definition is
- # reused in another language
-
-## Inline Character Encoding Statement for HTML: <meta charset>
-
- meta.charset.elem =
- element meta { meta.inner & meta.charset.attrs }
- meta.charset.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.charset.attrs.charset
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.charset.attrs.charset =
- attribute charset {
- (common.data.charset & HTMLonly)
- | (xsd:string {
- pattern = "[uU][tT][fF]-8"
- } & XMLonly )
- }
-
-## Inline Character Encoding Statement for HTML: <meta http-equiv='content-type'>
-
- meta.http-equiv.content-type.elem =
- element meta { meta.inner & meta.http-equiv.content-type.attrs }
- & HTMLonly
- meta.http-equiv.content-type.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & meta.http-equiv.attrs.http-equiv.content-type
- & meta.http-equiv.attrs.content.content-type
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- meta.http-equiv.attrs.http-equiv.content-type =
- attribute http-equiv {
- w:string "content-type"
- }
- meta.http-equiv.attrs.content.content-type =
- attribute content {
- common.data.meta-charset
- }
-
- common.elem.metadata |= ( meta.charset.elem | meta.http-equiv.content-type.elem )
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/Makefile b/xml/relaxng/src/resources/html5-schema/mml3/Makefile
new file mode 100644
index 0000000..fda4950
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/Makefile
@@ -0,0 +1,18 @@
+BASE=http://www.w3.org/Math/RelaxNG/mathml3
+FILES=\
+mathml3-common.rnc \
+mathml3-content.rnc \
+mathml3-presentation.rnc \
+mathml3-strict-content.rnc \
+mathml3.rnc
+CURL=curl
+CURLFLAGS=-s
+PATCH=patch
+PATCHFLAGS=
+
+all:
+ for file in $(FILES); do $(CURL) $(CURLFLAGS) $(BASE)/$$file > $$file; done
+ $(PATCH) $(PATCHFLAGS) < patch-vnu
+
+clean:
+ $(RM) $(FILES)
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/mathml3-common.rnc b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-common.rnc
new file mode 100644
index 0000000..a67e712
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-common.rnc
@@ -0,0 +1,129 @@
+# This is the Mathematical Markup Language (MathML) 3.0, an XML
+# application for describing mathematical notation and capturing
+# both its structure and content.
+#
+# With additional changes for integration into the validator.nu
+# service.
+#
+# Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+# Copyright 2012 Mozilla Foundation
+#
+# Use and distribution of this code are permitted under the terms
+# W3C Software Notice and License
+# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+
+default namespace m = "http://www.w3.org/1998/Math/MathML"
+namespace local = ""
+# added namespace for HTML5 datatype library -- mike
+datatypes w = "http://whattf.org/datatype-draft"
+
+math = element math {math.attributes,MathExpression*}
+MathExpression = semantics
+
+NonMathMLAtt = attribute (* - (local:*|m:*)) {xsd:string}
+
+CommonDeprecatedAtt = attribute other {text}?
+
+# changed datatype of id attr from ID to w:xml-name -- mike
+CommonAtt = attribute id {w:xml-name}?,
+ attribute xref {text}?,
+ attribute class {xsd:NMTOKENS}?,
+ attribute style {xsd:string}?,
+ attribute href {xsd:anyURI}?,
+ CommonDeprecatedAtt,
+ NonMathMLAtt*
+
+
+math.attributes = CommonAtt,
+ attribute display {"block" | "inline"}?,
+ attribute maxwidth {length}?,
+ attribute overflow {"linebreak" | "scroll" | "elide" | "truncate" | "scale"}?,
+ attribute altimg {xsd:anyURI}?,
+ attribute altimg-width {length}?,
+ attribute altimg-height {length}?,
+ attribute altimg-valign {length | "top" | "middle" | "bottom"}?,
+ attribute alttext {text}?,
+ attribute cdgroup {xsd:anyURI}?,
+ math.deprecatedattributes
+
+# the mathml3-presentation schema adds additional attributes
+# to the math element, all those valid on mstyle
+
+math.deprecatedattributes = attribute mode {xsd:string}?,
+ attribute macros {xsd:string}?
+
+
+name = attribute name {xsd:NCName}
+cd = attribute cd {xsd:NCName}
+
+src = attribute src {xsd:anyURI}?
+
+annotation = element annotation {annotation.attributes,text}
+
+# changed content model of annotation-xml -- mike
+annotation-xml =
+ ( annotation-xml.xhtml
+ | annotation-xml.svg
+ | annotation-xml.mathml
+ )
+ annotation-xml.model = (MathExpression | anyElement)*
+ anyElement =
+ element * - m:* {
+ (attribute * { text }
+ | text
+ | anyElement)*
+ }
+ annotation-xml.xhtml =
+ element annotation-xml {
+ annotation-xml.model, annotation-xml.attributes, att-encoding.xhtml?
+ }
+ annotation-xml.model.xhtml =
+ notAllowed
+ att-encoding.xhtml =
+ attribute encoding {
+ string "application/xhtml+xml" | string "text/html"
+ }
+ annotation-xml.svg =
+ element annotation-xml {
+ annotation-xml.model, annotation-xml.attributes, att-encoding.svg?
+ }
+ annotation-xml.model.svg =
+ notAllowed
+ att-encoding.svg =
+ attribute encoding {
+ string "SVG1.1"
+ }
+ annotation-xml.mathml =
+ element annotation-xml {
+ annotation-xml.model, annotation-xml.attributes, att-encoding.mathml?
+ }
+ annotation-xml.model.mathml =
+ math
+ att-encoding.mathml =
+ attribute encoding {
+ string "MathML" | string "MathML-Content" | string "MathML-Presentation"
+ }
+
+annotation.attributes = CommonAtt,
+ cd?,
+ name?,
+ DefEncAtt,
+ src?
+
+annotation-xml.attributes = CommonAtt, cd?, name?, src?
+
+DefEncAtt = attribute encoding {xsd:string}?,
+ attribute definitionURL {xsd:anyURI}?
+
+semantics = element semantics {semantics.attributes,
+ MathExpression,
+ (annotation|annotation-xml)*}
+semantics.attributes = CommonAtt,DefEncAtt,cd?,name?
+
+
+
+length = xsd:string {
+ pattern = '\s*((-?[0-9]*(\.[0-9]*)?(e[mx]|in|cm|mm|p[xtc]|%)?)|(negative)?((very){0,2}thi(n|ck)|medium)mathspace)\s*'
+}
+
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/mathml3-content.rnc b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-content.rnc
new file mode 100644
index 0000000..9dd1006
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-content.rnc
@@ -0,0 +1,380 @@
+
+# This is the Mathematical Markup Language (MathML) 3.0, an XML
+# application for describing mathematical notation and capturing
+# both its structure and content.
+#
+# With additional changes for integration into the validator.nu
+# service.
+#
+# Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+# Copyright 2012 Mozilla Foundation
+#
+# Use and distribution of this code are permitted under the terms
+# W3C Software Notice and License
+# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+include "mathml3-strict-content.rnc"{
+ cn.content = (text | mglyph | sep | PresentationExpression)*
+ cn.attributes = CommonAtt, DefEncAtt, attribute type {text}?, math-base?
+
+ ci.attributes = CommonAtt, DefEncAtt, ci.type?
+ ci.type = attribute type {text}
+ ci.content = (text | mglyph | PresentationExpression)*
+
+ csymbol.attributes = CommonAtt, DefEncAtt, attribute type {text}?,cd?
+ csymbol.content = (text | mglyph | PresentationExpression)*
+
+ bvar = element bvar { (ci | semantics-ci) & degree?}
+
+ cbytes.attributes = CommonAtt, DefEncAtt
+
+ cs.attributes = CommonAtt, DefEncAtt
+
+ apply.content = ContExp+ | (ContExp, BvarQ, Qualifier*, ContExp*)
+
+ bind.content = apply.content
+}
+
+# changed pattern name to math-base to avoid name conflict - mike
+math-base = attribute base { text }
+
+
+sep = element sep {empty}
+PresentationExpression |= notAllowed
+
+
+DomainQ = (domainofapplication|condition|interval|(lowlimit,uplimit?))*
+domainofapplication = element domainofapplication {ContExp}
+condition = element condition {ContExp}
+uplimit = element uplimit {ContExp}
+lowlimit = element lowlimit {ContExp}
+
+Qualifier = DomainQ|degree|momentabout|logbase
+degree = element degree {ContExp}
+momentabout = element momentabout {ContExp}
+logbase = element logbase {ContExp}
+
+type = attribute type {text}
+order = attribute order {"numeric" | "lexicographic"}
+closure = attribute closure {text}
+
+
+ContExp |= piecewise
+
+
+piecewise = element piecewise {CommonAtt, DefEncAtt,(piece* & otherwise?)}
+
+piece = element piece {CommonAtt, DefEncAtt, ContExp, ContExp}
+
+otherwise = element otherwise {CommonAtt, DefEncAtt, ContExp}
+
+
+DeprecatedContExp = reln | fn | declare
+ContExp |= DeprecatedContExp
+
+reln = element reln {ContExp*}
+fn = element fn {ContExp}
+declare = element declare {attribute type {xsd:string}?,
+ attribute scope {xsd:string}?,
+ attribute nargs {xsd:nonNegativeInteger}?,
+ attribute occurrence {"prefix"|"infix"|"function-model"}?,
+ DefEncAtt,
+ ContExp+}
+
+
+interval.class = interval
+ContExp |= interval.class
+
+
+interval = element interval { CommonAtt, DefEncAtt,closure?, ContExp,ContExp}
+
+unary-functional.class = inverse | ident | domain | codomain | math-image | ln | log | moment
+ContExp |= unary-functional.class
+
+
+inverse = element inverse { CommonAtt, DefEncAtt, empty}
+ident = element ident { CommonAtt, DefEncAtt, empty}
+domain = element domain { CommonAtt, DefEncAtt, empty}
+codomain = element codomain { CommonAtt, DefEncAtt, empty}
+# changed pattern name to math-image to avoid name conflict - mike
+math-image = element image { CommonAtt, DefEncAtt, empty }
+ln = element ln { CommonAtt, DefEncAtt, empty}
+log = element log { CommonAtt, DefEncAtt, empty}
+moment = element moment { CommonAtt, DefEncAtt, empty}
+
+lambda.class = lambda
+ContExp |= lambda.class
+
+
+lambda = element lambda { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp}
+
+nary-functional.class = compose
+ContExp |= nary-functional.class
+
+
+compose = element compose { CommonAtt, DefEncAtt, empty}
+
+binary-arith.class = quotient | divide | minus | power | rem | root
+ContExp |= binary-arith.class
+
+
+quotient = element quotient { CommonAtt, DefEncAtt, empty}
+divide = element divide { CommonAtt, DefEncAtt, empty}
+minus = element minus { CommonAtt, DefEncAtt, empty}
+power = element power { CommonAtt, DefEncAtt, empty}
+rem = element rem { CommonAtt, DefEncAtt, empty}
+root = element root { CommonAtt, DefEncAtt, empty}
+
+unary-arith.class = factorial | minus | root | abs | conjugate | arg | real | imaginary | floor | ceiling | exp
+ContExp |= unary-arith.class
+
+
+factorial = element factorial { CommonAtt, DefEncAtt, empty}
+abs = element abs { CommonAtt, DefEncAtt, empty}
+conjugate = element conjugate { CommonAtt, DefEncAtt, empty}
+arg = element arg { CommonAtt, DefEncAtt, empty}
+real = element real { CommonAtt, DefEncAtt, empty}
+imaginary = element imaginary { CommonAtt, DefEncAtt, empty}
+floor = element floor { CommonAtt, DefEncAtt, empty}
+ceiling = element ceiling { CommonAtt, DefEncAtt, empty}
+exp = element exp { CommonAtt, DefEncAtt, empty}
+
+nary-minmax.class = max | min
+ContExp |= nary-minmax.class
+
+
+max = element max { CommonAtt, DefEncAtt, empty}
+min = element min { CommonAtt, DefEncAtt, empty}
+
+nary-arith.class = plus | times | gcd | lcm
+ContExp |= nary-arith.class
+
+
+plus = element plus { CommonAtt, DefEncAtt, empty}
+times = element times { CommonAtt, DefEncAtt, empty}
+gcd = element gcd { CommonAtt, DefEncAtt, empty}
+lcm = element lcm { CommonAtt, DefEncAtt, empty}
+
+nary-logical.class = and | or | xor
+ContExp |= nary-logical.class
+
+
+and = element and { CommonAtt, DefEncAtt, empty}
+or = element or { CommonAtt, DefEncAtt, empty}
+xor = element xor { CommonAtt, DefEncAtt, empty}
+
+unary-logical.class = not
+ContExp |= unary-logical.class
+
+
+not = element not { CommonAtt, DefEncAtt, empty}
+
+binary-logical.class = implies | equivalent
+ContExp |= binary-logical.class
+
+
+implies = element implies { CommonAtt, DefEncAtt, empty}
+equivalent = element equivalent { CommonAtt, DefEncAtt, empty}
+
+quantifier.class = forall | exists
+ContExp |= quantifier.class
+
+
+forall = element forall { CommonAtt, DefEncAtt, empty}
+exists = element exists { CommonAtt, DefEncAtt, empty}
+
+nary-reln.class = eq | gt | lt | geq | leq
+ContExp |= nary-reln.class
+
+
+eq = element eq { CommonAtt, DefEncAtt, empty}
+gt = element gt { CommonAtt, DefEncAtt, empty}
+lt = element lt { CommonAtt, DefEncAtt, empty}
+geq = element geq { CommonAtt, DefEncAtt, empty}
+leq = element leq { CommonAtt, DefEncAtt, empty}
+
+binary-reln.class = neq | approx | factorof | tendsto
+ContExp |= binary-reln.class
+
+
+neq = element neq { CommonAtt, DefEncAtt, empty}
+approx = element approx { CommonAtt, DefEncAtt, empty}
+factorof = element factorof { CommonAtt, DefEncAtt, empty}
+tendsto = element tendsto { CommonAtt, DefEncAtt, type?, empty}
+
+int.class = int
+ContExp |= int.class
+
+
+int = element int { CommonAtt, DefEncAtt, empty}
+
+Differential-Operator.class = diff
+ContExp |= Differential-Operator.class
+
+
+diff = element diff { CommonAtt, DefEncAtt, empty}
+
+partialdiff.class = partialdiff
+ContExp |= partialdiff.class
+
+
+partialdiff = element partialdiff { CommonAtt, DefEncAtt, empty}
+
+unary-veccalc.class = divergence | grad | curl | laplacian
+ContExp |= unary-veccalc.class
+
+
+divergence = element divergence { CommonAtt, DefEncAtt, empty}
+grad = element grad { CommonAtt, DefEncAtt, empty}
+curl = element curl { CommonAtt, DefEncAtt, empty}
+laplacian = element laplacian { CommonAtt, DefEncAtt, empty}
+
+nary-setlist-constructor.class = math-set | \list
+ContExp |= nary-setlist-constructor.class
+
+
+# changed pattern name to math-set to avoid name conflict - mike
+math-set = element set { CommonAtt, DefEncAtt, type?, BvarQ*, DomainQ*, ContExp*}
+\list = element \list { CommonAtt, DefEncAtt, order?, BvarQ*, DomainQ*, ContExp*}
+
+nary-set.class = union | intersect | cartesianproduct
+ContExp |= nary-set.class
+
+
+union = element union { CommonAtt, DefEncAtt, empty}
+intersect = element intersect { CommonAtt, DefEncAtt, empty}
+cartesianproduct = element cartesianproduct { CommonAtt, DefEncAtt, empty}
+
+binary-set.class = in | notin | notsubset | notprsubset | setdiff
+ContExp |= binary-set.class
+
+
+in = element in { CommonAtt, DefEncAtt, empty}
+notin = element notin { CommonAtt, DefEncAtt, empty}
+notsubset = element notsubset { CommonAtt, DefEncAtt, empty}
+notprsubset = element notprsubset { CommonAtt, DefEncAtt, empty}
+setdiff = element setdiff { CommonAtt, DefEncAtt, empty}
+
+nary-set-reln.class = subset | prsubset
+ContExp |= nary-set-reln.class
+
+
+subset = element subset { CommonAtt, DefEncAtt, empty}
+prsubset = element prsubset { CommonAtt, DefEncAtt, empty}
+
+unary-set.class = card
+ContExp |= unary-set.class
+
+
+card = element card { CommonAtt, DefEncAtt, empty}
+
+sum.class = sum
+ContExp |= sum.class
+
+
+sum = element sum { CommonAtt, DefEncAtt, empty}
+
+product.class = product
+ContExp |= product.class
+
+
+product = element product { CommonAtt, DefEncAtt, empty}
+
+limit.class = limit
+ContExp |= limit.class
+
+
+limit = element limit { CommonAtt, DefEncAtt, empty}
+
+unary-elementary.class = sin | cos | tan | sec | csc | cot | sinh | cosh | tanh | sech | csch | coth | arcsin | arccos | arctan | arccosh | arccot | arccoth | arccsc | arccsch | arcsec | arcsech | arcsinh | arctanh
+ContExp |= unary-elementary.class
+
+
+sin = element sin { CommonAtt, DefEncAtt, empty}
+cos = element cos { CommonAtt, DefEncAtt, empty}
+tan = element tan { CommonAtt, DefEncAtt, empty}
+sec = element sec { CommonAtt, DefEncAtt, empty}
+csc = element csc { CommonAtt, DefEncAtt, empty}
+cot = element cot { CommonAtt, DefEncAtt, empty}
+sinh = element sinh { CommonAtt, DefEncAtt, empty}
+cosh = element cosh { CommonAtt, DefEncAtt, empty}
+tanh = element tanh { CommonAtt, DefEncAtt, empty}
+sech = element sech { CommonAtt, DefEncAtt, empty}
+csch = element csch { CommonAtt, DefEncAtt, empty}
+coth = element coth { CommonAtt, DefEncAtt, empty}
+arcsin = element arcsin { CommonAtt, DefEncAtt, empty}
+arccos = element arccos { CommonAtt, DefEncAtt, empty}
+arctan = element arctan { CommonAtt, DefEncAtt, empty}
+arccosh = element arccosh { CommonAtt, DefEncAtt, empty}
+arccot = element arccot { CommonAtt, DefEncAtt, empty}
+arccoth = element arccoth { CommonAtt, DefEncAtt, empty}
+arccsc = element arccsc { CommonAtt, DefEncAtt, empty}
+arccsch = element arccsch { CommonAtt, DefEncAtt, empty}
+arcsec = element arcsec { CommonAtt, DefEncAtt, empty}
+arcsech = element arcsech { CommonAtt, DefEncAtt, empty}
+arcsinh = element arcsinh { CommonAtt, DefEncAtt, empty}
+arctanh = element arctanh { CommonAtt, DefEncAtt, empty}
+
+nary-stats.class = mean | sdev | variance | median | mode
+ContExp |= nary-stats.class
+
+
+mean = element mean { CommonAtt, DefEncAtt, empty}
+sdev = element sdev { CommonAtt, DefEncAtt, empty}
+variance = element variance { CommonAtt, DefEncAtt, empty}
+median = element median { CommonAtt, DefEncAtt, empty}
+mode = element mode { CommonAtt, DefEncAtt, empty}
+
+nary-constructor.class = vector | matrix | matrixrow
+ContExp |= nary-constructor.class
+
+
+vector = element vector { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*}
+matrix = element matrix { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*}
+matrixrow = element matrixrow { CommonAtt, DefEncAtt, BvarQ, DomainQ, ContExp*}
+
+unary-linalg.class = determinant | transpose
+ContExp |= unary-linalg.class
+
+
+determinant = element determinant { CommonAtt, DefEncAtt, empty}
+transpose = element transpose { CommonAtt, DefEncAtt, empty}
+
+nary-linalg.class = selector
+ContExp |= nary-linalg.class
+
+
+selector = element selector { CommonAtt, DefEncAtt, empty}
+
+binary-linalg.class = vectorproduct | scalarproduct | outerproduct
+ContExp |= binary-linalg.class
+
+
+vectorproduct = element vectorproduct { CommonAtt, DefEncAtt, empty}
+scalarproduct = element scalarproduct { CommonAtt, DefEncAtt, empty}
+outerproduct = element outerproduct { CommonAtt, DefEncAtt, empty}
+
+constant-set.class = integers | reals | rationals | naturalnumbers | complexes | primes | emptyset
+ContExp |= constant-set.class
+
+
+integers = element integers { CommonAtt, DefEncAtt, empty}
+reals = element reals { CommonAtt, DefEncAtt, empty}
+rationals = element rationals { CommonAtt, DefEncAtt, empty}
+naturalnumbers = element naturalnumbers { CommonAtt, DefEncAtt, empty}
+complexes = element complexes { CommonAtt, DefEncAtt, empty}
+primes = element primes { CommonAtt, DefEncAtt, empty}
+emptyset = element emptyset { CommonAtt, DefEncAtt, empty}
+
+constant-arith.class = exponentiale | imaginaryi | notanumber | true | false | pi | eulergamma | infinity
+ContExp |= constant-arith.class
+
+
+exponentiale = element exponentiale { CommonAtt, DefEncAtt, empty}
+imaginaryi = element imaginaryi { CommonAtt, DefEncAtt, empty}
+notanumber = element notanumber { CommonAtt, DefEncAtt, empty}
+true = element true { CommonAtt, DefEncAtt, empty}
+false = element false { CommonAtt, DefEncAtt, empty}
+pi = element pi { CommonAtt, DefEncAtt, empty}
+eulergamma = element eulergamma { CommonAtt, DefEncAtt, empty}
+infinity = element infinity { CommonAtt, DefEncAtt, empty}
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/mathml3-inc.rnc b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-inc.rnc
new file mode 100644
index 0000000..84fe4db
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-inc.rnc
@@ -0,0 +1,22 @@
+# This is the Mathematical Markup Language (MathML) 2.0, an XML
+# application for describing mathematical notation and capturing
+# both its structure and content.
+#
+# Copyright 1998-2009 W3C (MIT, ERCIM, Keio)
+#
+# Use and distribution of this code are permitted under the terms
+# W3C Software Notice and License
+# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace m = "http://www.w3.org/1998/Math/MathML"
+
+
+## Content MathML
+include "mathml3-content.rnc" inherit = m
+
+## Presentation MathML
+include "mathml3-presentation.rnc" inherit = m
+
+## math and semantics common to both Content and Presentation
+include "mathml3-common.rnc" inherit = m
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/mathml3-presentation.rnc b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-presentation.rnc
new file mode 100644
index 0000000..ed6839d
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-presentation.rnc
@@ -0,0 +1,551 @@
+
+# This is the Mathematical Markup Language (MathML) 3.0, an XML
+# application for describing mathematical notation and capturing
+# both its structure and content.
+#
+# With additional changes for integration into the validator.nu
+# service.
+#
+# Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+# Copyright 2012 Mozilla Foundation
+#
+# Use and distribution of this code are permitted under the terms
+# W3C Software Notice and License
+# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+default namespace m = "http://www.w3.org/1998/Math/MathML"
+
+MathExpression |= PresentationExpression
+
+ImpliedMrow = MathExpression*
+
+TableRowExpression = mtr|mlabeledtr
+
+TableCellExpression = mtd
+
+MstackExpression = MathExpression|mscarries|msline|msrow|msgroup
+
+MsrowExpression = MathExpression|none
+
+MultiScriptExpression = (MathExpression|none),(MathExpression|none)
+
+mpadded-length = xsd:string {
+ pattern = '\s*([\+\-]?[0-9]*(\.[0-9]*)?\s*((%?\s*(height|depth|width)?)|e[mx]|in|cm|mm|p[xtc]|((negative)?((very){0,2}thi(n|ck)|medium)mathspace))?)\s*' }
+
+linestyle = "none" | "solid" | "dashed"
+
+verticalalign =
+ "top" |
+ "bottom" |
+ "center" |
+ "baseline" |
+ "axis"
+
+columnalignstyle = "left" | "center" | "right"
+
+notationstyle =
+ "longdiv" |
+ "actuarial" |
+ "radical" |
+ "box" |
+ "roundedbox" |
+ "circle" |
+ "left" |
+ "right" |
+ "top" |
+ "bottom" |
+ "updiagonalstrike" |
+ "downdiagonalstrike" |
+ "verticalstrike" |
+ "horizontalstrike" |
+ "madruwb"
+
+idref = text
+unsigned-integer = xsd:unsignedLong
+integer = xsd:integer
+number = xsd:decimal
+
+character = xsd:string {
+ pattern = '\s*\S\s*'}
+
+color = xsd:string {
+ pattern = '\s*((#[0-9a-fA-F]{3}([0-9a-fA-F]{3})?)|[aA][qQ][uU][aA]|[bB][lL][aA][cC][kK]|[bB][lL][uU][eE]|[fF][uU][cC][hH][sS][iI][aA]|[gG][rR][aA][yY]|[gG][rR][eE][eE][nN]|[lL][iI][mM][eE]|[mM][aA][rR][oO][oO][nN]|[nN][aA][vV][yY]|[oO][lL][iI][vV][eE]|[pP][uU][rR][pP][lL][eE]|[rR][eE][dD]|[sS][iI][lL][vV][eE][rR]|[tT][eE][aA][lL]|[wW][hH][iI][tT][eE]|[yY][eE][lL][lL][oO][wW])\s*'}
+
+
+group-alignment = "left" | "center" | "right" | "decimalpoint"
+group-alignment-list = list {group-alignment+}
+group-alignment-list-list = xsd:string {
+ pattern = '(\s*\{\s*(left|center|right|decimalpoint)(\s+(left|center|right|decimalpoint))*\})*\s*' }
+positive-integer = xsd:positiveInteger
+
+
+TokenExpression = mi|mn|mo|mtext|mspace|ms
+
+token.content = mglyph|malignmark|text
+
+mi = element mi {mi.attributes, token.content*}
+mi.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt
+
+
+mn = element mn {mn.attributes, token.content*}
+mn.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt
+
+
+mo = element mo {mo.attributes, token.content*}
+mo.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt,
+ attribute form {"prefix" | "infix" | "postfix"}?,
+ attribute fence {"true" | "false"}?,
+ attribute separator {"true" | "false"}?,
+ attribute lspace {length}?,
+ attribute rspace {length}?,
+ attribute stretchy {"true" | "false"}?,
+ attribute symmetric {"true" | "false"}?,
+ attribute maxsize {length | "infinity"}?,
+ attribute minsize {length}?,
+ attribute largeop {"true" | "false"}?,
+ attribute movablelimits {"true" | "false"}?,
+ attribute accent {"true" | "false"}?,
+ attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?,
+ attribute lineleading {length}?,
+ attribute linebreakstyle {"before" | "after" | "duplicate" | "infixlinebreakstyle"}?,
+ attribute linebreakmultchar {text}?,
+ attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?,
+ attribute indentshift {length}?,
+ attribute indenttarget {idref}?,
+ attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?,
+ attribute indentshiftfirst {length | "indentshift"}?,
+ attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?,
+ attribute indentshiftlast {length | "indentshift"}?
+
+
+# changed mtext content model to use mtext.content instead of generic
+# token.content, because we want to handle mtext differently than other
+# MathML "token elements" -- mike
+mtext = element mtext { mtext.attributes, mtext.content* }
+mtext.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt
+
+mtext.content = mglyph | malignmark | text
+
+mspace = element mspace {mspace.attributes, empty}
+mspace.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt,
+ attribute width {length}?,
+ attribute height {length}?,
+ attribute depth {length}?,
+ attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak" | "indentingnewline"}?,
+ attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?,
+ attribute indentshift {length}?,
+ attribute indenttarget {idref}?,
+ attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?,
+ attribute indentshiftfirst {length | "indentshift"}?,
+ attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?,
+ attribute indentshiftlast {length | "indentshift"}?
+
+
+ms = element ms {ms.attributes, token.content*}
+ms.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt,
+ attribute lquote {text}?,
+ attribute rquote {text}?
+
+
+mglyph = element mglyph {mglyph.attributes,mglyph.deprecatedattributes,empty}
+mglyph.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute src {xsd:anyURI}?,
+ attribute width {length}?,
+ attribute height {length}?,
+ attribute valign {length}?,
+ attribute alt {text}?
+mglyph.deprecatedattributes =
+ attribute index {integer}?,
+ attribute mathvariant {"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?,
+ attribute mathsize {"small" | "normal" | "big" | length}?,
+ DeprecatedTokenAtt
+
+msline = element msline {msline.attributes,empty}
+msline.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute position {integer}?,
+ attribute length {unsigned-integer}?,
+ attribute leftoverhang {length}?,
+ attribute rightoverhang {length}?,
+ attribute mslinethickness {length | "thin" | "medium" | "thick"}?
+
+none = element none {none.attributes,empty}
+none.attributes =
+ CommonAtt,
+ CommonPresAtt
+
+mprescripts = element mprescripts {mprescripts.attributes,empty}
+mprescripts.attributes =
+ CommonAtt,
+ CommonPresAtt
+
+
+CommonPresAtt =
+ attribute mathcolor {color}?,
+ attribute mathbackground {color | "transparent"}?
+
+TokenAtt =
+ attribute mathvariant {"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?,
+ attribute mathsize {"small" | "normal" | "big" | length}?,
+ attribute dir {"ltr" | "rtl"}?,
+ DeprecatedTokenAtt
+
+DeprecatedTokenAtt =
+ attribute fontfamily {text}?,
+ attribute fontweight {"normal" | "bold"}?,
+ attribute fontstyle {"normal" | "italic"}?,
+ attribute fontsize {length}?,
+ attribute color {color}?,
+ attribute background {color | "transparent"}?
+
+MalignExpression = maligngroup|malignmark
+
+malignmark = element malignmark {malignmark.attributes, empty}
+malignmark.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute edge {"left" | "right"}?
+
+
+maligngroup = element maligngroup {maligngroup.attributes, empty}
+maligngroup.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute groupalign {"left" | "center" | "right" | "decimalpoint"}?
+
+
+PresentationExpression = TokenExpression|MalignExpression|
+ mrow|mfrac|msqrt|mroot|mstyle|merror|mpadded|mphantom|
+ mfenced|menclose|msub|msup|msubsup|munder|mover|munderover|
+ mmultiscripts|mtable|mstack|mlongdiv|maction
+
+
+
+mrow = element mrow {mrow.attributes, MathExpression*}
+mrow.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute dir {"ltr" | "rtl"}?
+
+
+mfrac = element mfrac {mfrac.attributes, MathExpression, MathExpression}
+mfrac.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute linethickness {length | "thin" | "medium" | "thick"}?,
+ attribute numalign {"left" | "center" | "right"}?,
+ attribute denomalign {"left" | "center" | "right"}?,
+ attribute bevelled {"true" | "false"}?
+
+
+msqrt = element msqrt {msqrt.attributes, ImpliedMrow}
+msqrt.attributes =
+ CommonAtt, CommonPresAtt
+
+
+mroot = element mroot {mroot.attributes, MathExpression, MathExpression}
+mroot.attributes =
+ CommonAtt, CommonPresAtt
+
+
+mstyle = element mstyle {mstyle.attributes, ImpliedMrow}
+mstyle.attributes =
+ CommonAtt, CommonPresAtt,
+ mstyle.specificattributes,
+ mstyle.generalattributes,
+ mstyle.deprecatedattributes
+
+mstyle.specificattributes =
+ attribute scriptlevel {integer}?,
+ attribute displaystyle {"true" | "false"}?,
+ attribute scriptsizemultiplier {number}?,
+ attribute scriptminsize {length}?,
+ attribute infixlinebreakstyle {"before" | "after" | "duplicate"}?,
+ attribute decimalpoint {character}?
+
+mstyle.generalattributes =
+ attribute accent {"true" | "false"}?,
+ attribute accentunder {"true" | "false"}?,
+ attribute align {"left" | "right" | "center"}?,
+ attribute alignmentscope {list {("true" | "false") +}}?,
+ attribute bevelled {"true" | "false"}?,
+ attribute charalign {"left" | "center" | "right"}?,
+ attribute charspacing {length | "loose" | "medium" | "tight"}?,
+ attribute close {text}?,
+ attribute columnalign {list {columnalignstyle+} }?,
+ attribute columnlines {list {linestyle +}}?,
+ attribute columnspacing {list {(length) +}}?,
+ attribute columnspan {positive-integer}?,
+ attribute columnwidth {list {("auto" | length | "fit") +}}?,
+ attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?,
+ attribute denomalign {"left" | "center" | "right"}?,
+ attribute depth {length}?,
+ attribute dir {"ltr" | "rtl"}?,
+ attribute edge {"left" | "right"}?,
+ attribute equalcolumns {"true" | "false"}?,
+ attribute equalrows {"true" | "false"}?,
+ attribute fence {"true" | "false"}?,
+ attribute form {"prefix" | "infix" | "postfix"}?,
+ attribute frame {linestyle}?,
+ attribute framespacing {list {length, length}}?,
+ attribute groupalign {group-alignment-list-list}?,
+ attribute height {length}?,
+ attribute indentalign {"left" | "center" | "right" | "auto" | "id"}?,
+ attribute indentalignfirst {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?,
+ attribute indentalignlast {"left" | "center" | "right" | "auto" | "id" | "indentalign"}?,
+ attribute indentshift {length}?,
+ attribute indentshiftfirst {length | "indentshift"}?,
+ attribute indentshiftlast {length | "indentshift"}?,
+ attribute indenttarget {idref}?,
+ attribute largeop {"true" | "false"}?,
+ attribute leftoverhang {length}?,
+ attribute length {unsigned-integer}?,
+ attribute linebreak {"auto" | "newline" | "nobreak" | "goodbreak" | "badbreak"}?,
+ attribute linebreakmultchar {text}?,
+ attribute linebreakstyle {"before" | "after" | "duplicate" | "infixlinebreakstyle"}?,
+ attribute lineleading {length}?,
+ attribute linethickness {length | "thin" | "medium" | "thick"}?,
+ attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?,
+ attribute longdivstyle {"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}?,
+ attribute lquote {text}?,
+ attribute lspace {length}?,
+ attribute mathsize {"small" | "normal" | "big" | length}?,
+ attribute mathvariant {"normal" | "bold" | "italic" | "bold-italic" | "double-struck" | "bold-fraktur" | "script" | "bold-script" | "fraktur" | "sans-serif" | "bold-sans-serif" | "sans-serif-italic" | "sans-serif-bold-italic" | "monospace" | "initial" | "tailed" | "looped" | "stretched"}?,
+ attribute maxsize {length | "infinity"}?,
+ attribute minlabelspacing {length}?,
+ attribute minsize {length}?,
+ attribute movablelimits {"true" | "false"}?,
+ attribute mslinethickness {length | "thin" | "medium" | "thick"}?,
+ attribute notation {text}?,
+ attribute numalign {"left" | "center" | "right"}?,
+ attribute open {text}?,
+ attribute position {integer}?,
+ attribute rightoverhang {length}?,
+ attribute rowalign {list {verticalalign+} }?,
+ attribute rowlines {list {linestyle +}}?,
+ attribute rowspacing {list {(length) +}}?,
+ attribute rowspan {positive-integer}?,
+ attribute rquote {text}?,
+ attribute rspace {length}?,
+ attribute selection {positive-integer}?,
+ attribute separator {"true" | "false"}?,
+ attribute separators {text}?,
+ attribute shift {integer}?,
+ attribute side {"left" | "right" | "leftoverlap" | "rightoverlap"}?,
+ attribute stackalign {"left" | "center" | "right" | "decimalpoint"}?,
+ attribute stretchy {"true" | "false"}?,
+ attribute subscriptshift {length}?,
+ attribute superscriptshift {length}?,
+ attribute symmetric {"true" | "false"}?,
+ attribute valign {length}?,
+ attribute width {length}?
+
+mstyle.deprecatedattributes =
+ DeprecatedTokenAtt,
+ attribute veryverythinmathspace {length}?,
+ attribute verythinmathspace {length}?,
+ attribute thinmathspace {length}?,
+ attribute mediummathspace {length}?,
+ attribute thickmathspace {length}?,
+ attribute verythickmathspace {length}?,
+ attribute veryverythickmathspace {length}?
+
+math.attributes &= CommonPresAtt
+math.attributes &= mstyle.specificattributes
+math.attributes &= mstyle.generalattributes
+
+
+
+
+merror = element merror {merror.attributes, ImpliedMrow}
+merror.attributes =
+ CommonAtt, CommonPresAtt
+
+
+mpadded = element mpadded {mpadded.attributes, ImpliedMrow}
+mpadded.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute height {mpadded-length}?,
+ attribute depth {mpadded-length}?,
+ attribute width {mpadded-length}?,
+ attribute lspace {mpadded-length}?,
+ attribute voffset {mpadded-length}?
+
+
+mphantom = element mphantom {mphantom.attributes, ImpliedMrow}
+mphantom.attributes =
+ CommonAtt, CommonPresAtt
+
+
+mfenced = element mfenced {mfenced.attributes, MathExpression*}
+mfenced.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute open {text}?,
+ attribute close {text}?,
+ attribute separators {text}?
+
+
+menclose = element menclose {menclose.attributes, ImpliedMrow}
+menclose.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute notation {text}?
+
+
+msub = element msub {msub.attributes, MathExpression, MathExpression}
+msub.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute subscriptshift {length}?
+
+
+msup = element msup {msup.attributes, MathExpression, MathExpression}
+msup.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute superscriptshift {length}?
+
+
+msubsup = element msubsup {msubsup.attributes, MathExpression, MathExpression, MathExpression}
+msubsup.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute subscriptshift {length}?,
+ attribute superscriptshift {length}?
+
+
+munder = element munder {munder.attributes, MathExpression, MathExpression}
+munder.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute accentunder {"true" | "false"}?,
+ attribute align {"left" | "right" | "center"}?
+
+
+mover = element mover {mover.attributes, MathExpression, MathExpression}
+mover.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute accent {"true" | "false"}?,
+ attribute align {"left" | "right" | "center"}?
+
+
+munderover = element munderover {munderover.attributes, MathExpression, MathExpression, MathExpression}
+munderover.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute accent {"true" | "false"}?,
+ attribute accentunder {"true" | "false"}?,
+ attribute align {"left" | "right" | "center"}?
+
+
+mmultiscripts = element mmultiscripts {mmultiscripts.attributes, MathExpression,MultiScriptExpression*,(mprescripts,MultiScriptExpression*)?}
+mmultiscripts.attributes =
+ msubsup.attributes
+
+
+mtable = element mtable {mtable.attributes, TableRowExpression*}
+mtable.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute align {xsd:string {
+ pattern ='\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*'}}?,
+ attribute rowalign {list {verticalalign+} }?,
+ attribute columnalign {list {columnalignstyle+} }?,
+ attribute groupalign {group-alignment-list-list}?,
+ attribute alignmentscope {list {("true" | "false") +}}?,
+ attribute columnwidth {list {("auto" | length | "fit") +}}?,
+ attribute width {"auto" | length}?,
+ attribute rowspacing {list {(length) +}}?,
+ attribute columnspacing {list {(length) +}}?,
+ attribute rowlines {list {linestyle +}}?,
+ attribute columnlines {list {linestyle +}}?,
+ attribute frame {linestyle}?,
+ attribute framespacing {list {length, length}}?,
+ attribute equalrows {"true" | "false"}?,
+ attribute equalcolumns {"true" | "false"}?,
+ attribute displaystyle {"true" | "false"}?,
+ attribute side {"left" | "right" | "leftoverlap" | "rightoverlap"}?,
+ attribute minlabelspacing {length}?
+
+
+mlabeledtr = element mlabeledtr {mlabeledtr.attributes, TableCellExpression+}
+mlabeledtr.attributes =
+ mtr.attributes
+
+
+mtr = element mtr {mtr.attributes, TableCellExpression*}
+mtr.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute rowalign {"top" | "bottom" | "center" | "baseline" | "axis"}?,
+ attribute columnalign {list {columnalignstyle+} }?,
+ attribute groupalign {group-alignment-list-list}?
+
+
+mtd = element mtd {mtd.attributes, ImpliedMrow}
+mtd.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute rowspan {positive-integer}?,
+ attribute columnspan {positive-integer}?,
+ attribute rowalign {"top" | "bottom" | "center" | "baseline" | "axis"}?,
+ attribute columnalign {columnalignstyle}?,
+ attribute groupalign {group-alignment-list}?
+
+
+mstack = element mstack {mstack.attributes, MstackExpression*}
+mstack.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute align {xsd:string {
+ pattern ='\s*(top|bottom|center|baseline|axis)(\s+-?[0-9]+)?\s*'}}?,
+ attribute stackalign {"left" | "center" | "right" | "decimalpoint"}?,
+ attribute charalign {"left" | "center" | "right"}?,
+ attribute charspacing {length | "loose" | "medium" | "tight"}?
+
+
+mlongdiv = element mlongdiv {mlongdiv.attributes, MstackExpression,MstackExpression,MstackExpression+}
+mlongdiv.attributes =
+ msgroup.attributes,
+ attribute longdivstyle {"lefttop" | "stackedrightright" | "mediumstackedrightright" | "shortstackedrightright" | "righttop" | "left/\right" | "left)(right" | ":right=right" | "stackedleftleft" | "stackedleftlinetop"}?
+
+
+msgroup = element msgroup {msgroup.attributes, MstackExpression*}
+msgroup.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute position {integer}?,
+ attribute shift {integer}?
+
+
+msrow = element msrow {msrow.attributes, MsrowExpression*}
+msrow.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute position {integer}?
+
+
+mscarries = element mscarries {mscarries.attributes, (MsrowExpression|mscarry)*}
+mscarries.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute position {integer}?,
+ attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?,
+ attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?,
+ attribute scriptsizemultiplier {number}?
+
+
+mscarry = element mscarry {mscarry.attributes, MsrowExpression*}
+mscarry.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute location {"w" | "nw" | "n" | "ne" | "e" | "se" | "s" | "sw"}?,
+ attribute crossout {list {("none" | "updiagonalstrike" | "downdiagonalstrike" | "verticalstrike" | "horizontalstrike")*}}?
+
+
+maction = element maction {maction.attributes, MathExpression+}
+maction.attributes =
+ CommonAtt, CommonPresAtt,
+ attribute actiontype {text},
+ attribute selection {positive-integer}?
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/mathml3-strict-content.rnc b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-strict-content.rnc
new file mode 100644
index 0000000..919a12f
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/mathml3-strict-content.rnc
@@ -0,0 +1,60 @@
+# This is the Mathematical Markup Language (MathML) 3.0, an XML
+# application for describing mathematical notation and capturing
+# both its structure and content.
+#
+# Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+#
+# Use and distribution of this code are permitted under the terms
+# W3C Software Notice and License
+# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+
+default namespace m = "http://www.w3.org/1998/Math/MathML"
+
+ContExp = semantics-contexp | cn | ci | csymbol | apply | bind | share | cerror | cbytes | cs
+
+cn = element cn {cn.attributes,cn.content}
+cn.content = text
+cn.attributes = attribute type {"integer" | "real" | "double" | "hexdouble"}
+
+semantics-ci = element semantics {semantics.attributes,(ci|semantics-ci),
+ (annotation|annotation-xml)*}
+
+semantics-contexp = element semantics {semantics.attributes,ContExp,
+ (annotation|annotation-xml)*}
+
+ci = element ci {ci.attributes, ci.content}
+ci.attributes = CommonAtt, ci.type?
+ci.type = attribute type {"integer" | "rational" | "real" | "complex" | "complex-polar" | "complex-cartesian" | "constant" | "function" | "vector" | "list" | "set" | "matrix"}
+ci.content = text
+
+
+csymbol = element csymbol {csymbol.attributes,csymbol.content}
+
+SymbolName = xsd:NCName
+csymbol.attributes = CommonAtt, cd
+csymbol.content = SymbolName
+
+BvarQ = bvar*
+bvar = element bvar { ci | semantics-ci}
+
+apply = element apply {CommonAtt,apply.content}
+apply.content = ContExp+
+
+
+bind = element bind {CommonAtt,bind.content}
+bind.content = ContExp,bvar*,ContExp
+
+share = element share {CommonAtt, src, empty}
+
+cerror = element cerror {cerror.attributes, csymbol, ContExp*}
+cerror.attributes = CommonAtt
+
+cbytes = element cbytes {cbytes.attributes, base64}
+cbytes.attributes = CommonAtt
+base64 = xsd:base64Binary
+
+cs = element cs {cs.attributes, text}
+cs.attributes = CommonAtt
+
+MathExpression |= ContExp
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/mathml3.rnc b/xml/relaxng/src/resources/html5-schema/mml3/mathml3.rnc
new file mode 100644
index 0000000..eec136f
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/mathml3.rnc
@@ -0,0 +1,18 @@
+# This is the Mathematical Markup Language (MathML) 3.0, an XML
+# application for describing mathematical notation and capturing
+# both its structure and content.
+#
+# With additional changes for integration into the validator.nu
+# service.
+#
+# Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+# Copyright 2012 Mozilla Foundation
+#
+# Use and distribution of this code are permitted under the terms
+# W3C Software Notice and License
+# http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+# moved necessary includes into mathml3-inc.rnc file and we then just
+# include that here; also, set start = math -- mike
+include "mathml3-inc.rnc"
+start = math
diff --git a/xml/relaxng/src/resources/html5-schema/mml3/patch-vnu b/xml/relaxng/src/resources/html5-schema/mml3/patch-vnu
new file mode 100644
index 0000000..8685924
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/mml3/patch-vnu
@@ -0,0 +1,243 @@
+diff -u mathml3-common.rnc mathml3-common.rnc
+--- mathml3-common.rnc.orig 2012-05-23 11:54:19.000000000 +0900
++++ mathml3-common.rnc 2012-05-24 11:24:13.000000000 +0900
+@@ -2,8 +2,12 @@
+ # application for describing mathematical notation and capturing
+ # both its structure and content.
+ #
++# With additional changes for integration into the validator.nu
++# service.
++#
+ # Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+-#
++# Copyright 2012 Mozilla Foundation
++#
+ # Use and distribution of this code are permitted under the terms
+ # W3C Software Notice and License
+ # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+@@ -11,8 +15,8 @@
+
+ default namespace m = "http://www.w3.org/1998/Math/MathML"
+ namespace local = ""
+-
+-start = math
++# added namespace for HTML5 datatype library -- mike
++datatypes w = "http://whattf.org/datatype-draft"
+
+ math = element math {math.attributes,MathExpression*}
+ MathExpression = semantics
+@@ -21,7 +25,8 @@
+
+ CommonDeprecatedAtt = attribute other {text}?
+
+-CommonAtt = attribute id {xsd:ID}?,
++# changed datatype of id attr from ID to w:xml-name -- mike
++CommonAtt = attribute id {w:xml-name}?,
+ attribute xref {text}?,
+ attribute class {xsd:NMTOKENS}?,
+ attribute style {xsd:string}?,
+@@ -56,18 +61,58 @@
+
+ annotation = element annotation {annotation.attributes,text}
+
+-annotation-xml.model = (MathExpression|anyElement)*
++# changed content model of annotation-xml -- mike
++annotation-xml =
++ ( annotation-xml.xhtml
++ | annotation-xml.svg
++ | annotation-xml.mathml
++ )
++ annotation-xml.model = (MathExpression | anyElement)*
++ anyElement =
++ element * - m:* {
++ (attribute * { text }
++ | text
++ | anyElement)*
++ }
++ annotation-xml.xhtml =
++ element annotation-xml {
++ annotation-xml.model, annotation-xml.attributes, att-encoding.xhtml?
++ }
++ annotation-xml.model.xhtml =
++ notAllowed
++ att-encoding.xhtml =
++ attribute encoding {
++ string "application/xhtml+xml" | string "text/html"
++ }
++ annotation-xml.svg =
++ element annotation-xml {
++ annotation-xml.model, annotation-xml.attributes, att-encoding.svg?
++ }
++ annotation-xml.model.svg =
++ notAllowed
++ att-encoding.svg =
++ attribute encoding {
++ string "SVG1.1"
++ }
++ annotation-xml.mathml =
++ element annotation-xml {
++ annotation-xml.model, annotation-xml.attributes, att-encoding.mathml?
++ }
++ annotation-xml.model.mathml =
++ math
++ att-encoding.mathml =
++ attribute encoding {
++ string "MathML" | string "MathML-Content" | string "MathML-Presentation"
++ }
+
+-anyElement = element (* - m:*) {(attribute * {text}|text| anyElement)*}
+-
+-annotation-xml = element annotation-xml {annotation.attributes,
+- annotation-xml.model}
+ annotation.attributes = CommonAtt,
+ cd?,
+ name?,
+ DefEncAtt,
+ src?
+
++annotation-xml.attributes = CommonAtt, cd?, name?, src?
++
+ DefEncAtt = attribute encoding {xsd:string}?,
+ attribute definitionURL {xsd:anyURI}?
+
+diff -u mathml3-content.rnc mathml3-content.rnc
+--- mathml3-content.rnc 2012-05-14 19:38:56.000000000 +0900
++++ mathml3-content.rnc 2012-05-14 19:47:57.000000000 +0900
+@@ -3,15 +3,19 @@
+ # application for describing mathematical notation and capturing
+ # both its structure and content.
+ #
++# With additional changes for integration into the validator.nu
++# service.
++#
+ # Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
+-#
++# Copyright 2012 Mozilla Foundation
++#
+ # Use and distribution of this code are permitted under the terms
+ # W3C Software Notice and License
+ # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+ include "mathml3-strict-content.rnc"{
+ cn.content = (text | mglyph | sep | PresentationExpression)*
+- cn.attributes = CommonAtt, DefEncAtt, attribute type {text}?, base?
++ cn.attributes = CommonAtt, DefEncAtt, attribute type {text}?, math-base?
+
+ ci.attributes = CommonAtt, DefEncAtt, ci.type?
+ ci.type = attribute type {text}
+@@ -31,7 +35,8 @@
+ bind.content = apply.content
+ }
+
+-base = attribute base {text}
++# changed pattern name to math-base to avoid name conflict - mike
++math-base = attribute base { text }
+
+
+ sep = element sep {empty}
+@@ -83,7 +88,7 @@
+
+ interval = element interval { CommonAtt, DefEncAtt,closure?, ContExp,ContExp}
+
+-unary-functional.class = inverse | ident | domain | codomain | image | ln | log | moment
++unary-functional.class = inverse | ident | domain | codomain | math-image | ln | log | moment
+ ContExp |= unary-functional.class
+
+
+@@ -91,7 +96,8 @@
+ ident = element ident { CommonAtt, DefEncAtt, empty}
+ domain = element domain { CommonAtt, DefEncAtt, empty}
+ codomain = element codomain { CommonAtt, DefEncAtt, empty}
+-image = element image { CommonAtt, DefEncAtt, empty}
++# changed pattern name to math-image to avoid name conflict - mike
++math-image = element image { CommonAtt, DefEncAtt, empty }
+ ln = element ln { CommonAtt, DefEncAtt, empty}
+ log = element log { CommonAtt, DefEncAtt, empty}
+ moment = element moment { CommonAtt, DefEncAtt, empty}
+@@ -223,11 +229,12 @@
+ curl = element curl { CommonAtt, DefEncAtt, empty}
+ laplacian = element laplacian { CommonAtt, DefEncAtt, empty}
+
+-nary-setlist-constructor.class = set | \list
++nary-setlist-constructor.class = math-set | \list
+ ContExp |= nary-setlist-constructor.class
+
+
+-set = element set { CommonAtt, DefEncAtt, type?, BvarQ*, DomainQ*, ContExp*}
++# changed pattern name to math-set to avoid name conflict - mike
++math-set = element set { CommonAtt, DefEncAtt, type?, BvarQ*, DomainQ*, ContExp*}
+ \list = element \list { CommonAtt, DefEncAtt, order?, BvarQ*, DomainQ*, ContExp*}
+
+ nary-set.class = union | intersect | cartesianproduct
+@@ -370,4 +377,4 @@
+ false = element false { CommonAtt, DefEncAtt, empty}
+ pi = element pi { CommonAtt, DefEncAtt, empty}
+ eulergamma = element eulergamma { CommonAtt, DefEncAtt, empty}
+-infinity = element infinity { CommonAtt, DefEncAtt, empty}
+\ No newline at end of file
++infinity = element infinity { CommonAtt, DefEncAtt, empty}
+diff -u mathml3-presentation.rnc mathml3-presentation.rnc
+--- mathml3-presentation.rnc 2012-05-14 19:38:57.000000000 +0900
++++ mathml3-presentation.rnc 2012-05-14 19:18:19.000000000 +0900
+@@ -3,7 +3,11 @@
+ # application for describing mathematical notation and capturing
+ # both its structure and content.
+ #
++# With additional changes for integration into the validator.nu
++# service.
++#
+ # Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
++# Copyright 2012 Mozilla Foundation
+ #
+ # Use and distribution of this code are permitted under the terms
+ # W3C Software Notice and License
+@@ -123,12 +127,16 @@
+ attribute indentshiftlast {length | "indentshift"}?
+
+
+-mtext = element mtext {mtext.attributes, token.content*}
++# changed mtext content model to use mtext.content instead of generic
++# token.content, because we want to handle mtext differently than other
++# MathML "token elements" -- mike
++mtext = element mtext { mtext.attributes, mtext.content* }
+ mtext.attributes =
+ CommonAtt,
+ CommonPresAtt,
+ TokenAtt
+
++mtext.content = mglyph | malignmark | text
+
+ mspace = element mspace {mspace.attributes, empty}
+ mspace.attributes =
+diff -u mathml3.rnc mathml3.rnc
+--- mathml3.rnc 2012-05-14 19:38:58.000000000 +0900
++++ mathml3.rnc 2012-05-14 19:34:20.000000000 +0900
+@@ -2,20 +2,17 @@
+ # application for describing mathematical notation and capturing
+ # both its structure and content.
+ #
++# With additional changes for integration into the validator.nu
++# service.
++#
+ # Copyright 1998-2010 W3C (MIT, ERCIM, Keio)
++# Copyright 2012 Mozilla Foundation
+ #
+ # Use and distribution of this code are permitted under the terms
+ # W3C Software Notice and License
+ # http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+-
+-default namespace m = "http://www.w3.org/1998/Math/MathML"
+-
+-## Content MathML
+-include "mathml3-content.rnc"
+-
+-## Presentation MathML
+-include "mathml3-presentation.rnc"
+-
+-## math and semantics common to both Content and Presentation
+-include "mathml3-common.rnc"
++# moved necessary includes into mathml3-inc.rnc file and we then just
++# include that here; also, set start = math -- mike
++include "mathml3-inc.rnc"
++start = math
diff --git a/xml/relaxng/src/resources/html5-schema/phrase.rnc b/xml/relaxng/src/resources/html5-schema/phrase.rnc
deleted file mode 100644
index cf6ed58..0000000
--- a/xml/relaxng/src/resources/html5-schema/phrase.rnc
+++ /dev/null
@@ -1,400 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Phrase Markup #
-# #####################################################################
-
-## Contextual Hyperlink: <a>
-
- a.elem.phrasing =
- element a { a.inner.phrasing & a.attrs }
- a.elem.flow =
- element a { a.inner.flow & a.attrs }
- a.attrs =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & a.attrs.name?
- & shared-hyperlink.attrs.href?
- & shared-hyperlink.attrs.target?
- & shared-hyperlink.attrs.rel?
- & shared-hyperlink.attrs.hreflang?
- & shared-hyperlink.attrs.media?
- & shared-hyperlink.attrs.type?
- & shared-hyperlink.attrs.ping?
- & ( ( common.attrs.aria.role.button
- | common.attrs.aria.role.checkbox
- | common.attrs.aria.role.link
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.menuitemcheckbox
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.treeitem
- )
- | common.attrs.aria.implicit.link
- )?
- )
- a.attrs.name =
- attribute name {
- common.data.id # XXX not what the spec says
- }
- a.inner.phrasing =
- ( common.inner.phrasing )
- a.inner.flow =
- ( common.inner.transparent.flow )
-
- common.elem.phrasing |= a.elem.phrasing
- common.elem.flow |= a.elem.flow
-
-## Shared hyperlink attributes
-
- shared-hyperlink.attrs.href =
- attribute href {
- common.data.uri
- }
- shared-hyperlink.attrs.target =
- attribute target {
- common.data.browsing-context-or-keyword
- }
- shared-hyperlink.attrs.rel =
- attribute rel {
- w:a-rel
- }
- shared-hyperlink.attrs.hreflang =
- attribute hreflang {
- common.data.langcode
- }
- shared-hyperlink.attrs.media =
- attribute media {
- common.data.mediaquery
- }
- shared-hyperlink.attrs.type =
- attribute type {
- common.data.mimetype
- }
- shared-hyperlink.attrs.ping =
- attribute ping {
- common.data.uris
- } & v5only & nonW3C
-
-## Emphatic Stress: <em>
-
- em.elem =
- element em { em.inner & em.attrs }
- em.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- em.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= em.elem
-
-## Strong Importance: <strong>
-
- strong.elem =
- element strong { strong.inner & strong.attrs }
- strong.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- strong.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= strong.elem
-
-## Small Print and Side Comments: <small>
-
- small.elem =
- element small { small.inner & small.attrs }
- small.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- small.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= small.elem
-
-## Marked (Highlighted) Text: <mark>
-
- mark.elem =
- element mark { mark.inner & mark.attrs }
- & v5only
- mark.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- mark.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= mark.elem
-
-## Abbreviation: <abbr>
-
- abbr.elem =
- element abbr { abbr.inner & abbr.attrs }
- abbr.attrs =
- ( common.attrs
- # abbr.attrs.title included in common.attrs
- & common.attrs.aria?
- )
- abbr.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= abbr.elem
-
-## Defining Instance: <dfn>
-
- dfn.elem =
- element dfn { dfn.inner & dfn.attrs }
- dfn.attrs =
- ( common.attrs
- # dfn.attrs.title included in common.attrs
- & common.attrs.aria?
- )
- dfn.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= dfn.elem
-
-## Italic: <i>
-
- i.elem =
- element i { i.inner & i.attrs }
- i.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- i.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= i.elem
-
-## Bold: <b>
-
- b.elem =
- element b { b.inner & b.attrs }
- b.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- b.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= b.elem
-
-## Struck Text: <s>
-
- s.elem =
- element s { s.inner & s.attrs }
- s.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- s.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= s.elem
-
-## Underline: <u>
-
- u.elem =
- element u { u.inner & u.attrs }
- u.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- u.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= u.elem
-
-## Code Fragment: <code>
-
- code.elem =
- element code { code.inner & code.attrs }
- code.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- code.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= code.elem
-
-## Variable or Placeholder: <var>
-
- var.elem =
- element var { var.inner & var.attrs }
- var.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- var.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= var.elem
-
-## (Sample) Output: <samp>
-
- samp.elem =
- element samp { samp.inner & samp.attrs }
- samp.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- samp.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= samp.elem
-
-## User Input: <kbd>
-
- kbd.elem =
- element kbd { kbd.inner & kbd.attrs }
- kbd.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- kbd.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= kbd.elem
-
-## Superscript: <sup>
-
- sup.elem =
- element sup { sup.inner & sup.attrs }
- sup.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- sup.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= sup.elem
-
-## Subscript: <sub>
-
- sub.elem =
- element sub { sub.inner & sub.attrs }
- sub.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- sub.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= sub.elem
-
-## Quotation: <q>
-
- q.elem =
- element q { q.inner & q.attrs }
- q.attrs =
- ( common.attrs
- & q.attrs.cite?
- & common.attrs.aria?
- )
- q.attrs.cite =
- attribute cite {
- common.data.uri
- }
- q.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= q.elem
-
-## Title of Work: <cite>
-
- cite.elem =
- element cite { cite.inner & cite.attrs }
- cite.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- cite.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= cite.elem
-
-## Generic Span: <span>
-
- span.elem =
- element span { span.inner & span.attrs }
- span.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- span.inner =
- ( common.inner.phrasing ) # REVISIT allow ol and ul?
-
- common.elem.phrasing |= span.elem
-
-## Bidirectional Override: <bdo>
-
- bdo.elem =
- element bdo { bdo.inner & bdo.attrs }
- bdo.attrs =
- ( common.attrs # dir required in Schematron
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- bdo.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= bdo.elem
-
-## Bidirectional Isolate: <bdi>
-
- bdi.elem =
- element bdi { bdi.inner & bdi.attrs }
- bdi.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- bdi.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= bdi.elem
-
-## Line Break: <br>
-
- br.elem =
- element br { br.inner & br.attrs }
- br.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- br.inner =
- ( empty )
-
- common.elem.phrasing |= br.elem
-
-## Line-break opportunity: <wbr>
-
- wbr.elem =
- element wbr { wbr.inner & wbr.attrs }
- wbr.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- wbr.inner =
- ( empty )
-
- common.elem.phrasing |= wbr.elem
diff --git a/xml/relaxng/src/resources/html5-schema/rdf/rdf.rnc b/xml/relaxng/src/resources/html5-schema/rdf/rdf.rnc
new file mode 100755
index 0000000..36a1512
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/rdf/rdf.rnc
@@ -0,0 +1,54 @@
+# Copyright (c) 2005-2007 Elika J. Etemad (fantasai) and Henri Sivonen (hsivonen)
+# Copyright (c) 2007 Mozilla Foundation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy of
+# this software and associated documentation files (the "Software"), to deal in
+# the Software without restriction, including without limitation the rights to
+# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+# of the Software, and to permit persons to whom the Software is furnished to do
+# so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+# #####################################################################
+## Anything-goes schema for RDF #
+# #####################################################################
+
+## RDF Root: <rdf:RDF>
+
+ rdf.elem =
+ element rdf:RDF { rdf.inner & rdf.attrs }
+ rdf.attrs =
+ ( rdf.attr.anything )
+ rdf.inner =
+ ( rdf.inner.anything )
+
+## Anything
+
+## Any attribute from any namespace
+
+ rdf.attr.anything =
+ attribute * { text }*
+
+## Any element from any namespace
+
+ rdf.elem.anything =
+ element * { rdf.inner.anything & rdf.attr.anything }
+
+## Any content from any namespace
+
+ rdf.inner.anything =
+ ( text
+ & rdf.elem.anything*
+ )
diff --git a/xml/relaxng/src/resources/html5-schema/rdfa.rnc b/xml/relaxng/src/resources/html5-schema/rdfa.rnc
deleted file mode 100644
index 638c910..0000000
--- a/xml/relaxng/src/resources/html5-schema/rdfa.rnc
+++ /dev/null
@@ -1,240 +0,0 @@
-# #####################################################################
-## RELAX NG Schema for HTML 5: RDFa 1.1 and RDFa Lite 1.1 #
-# #####################################################################
-
-# #####################################################################
-## RDFa Datatypes #
-# #####################################################################
-
-common.data.rdfa.safecurie =
- xsd:string {
- pattern = "\[(([\i-[:]][\c-[:]]*)?:)?[^\s]+\]"
- minLength = "3"
- }
-common.data.rdfa.curie =
- xsd:string {
- pattern = "(([\i-[:]][\c-[:]]*)?:)?[^\s]+"
- minLength = "1"
- }
-common.data.rdfa.term =
- xsd:string {
- pattern = "[\i-[:]][/\c-[:]]*"
- }
-
-# #####################################################################
-## RDFa Attributes #
-# #####################################################################
-
-common.attrs.rdfa &=
- ( common.attrs.rdfa.about?
- & common.attrs.rdfa.prefix?
- & common.attrs.rdfa.property?
- & common.attrs.rdfa.typeof?
- & common.attrs.rdfa.vocab?
- & common.attrs.rdfa.content?
- & common.attrs.rdfa.datatype?
- & common.attrs.rdfa.rel?
- & common.attrs.rdfa.resource?
- & common.attrs.rdfa.rev?
- & common.attrs.rdfa.inlist?
- )
- common.attrs.rdfa.prefix =
- attribute prefix {
- (
- xsd:string {
- pattern = "([\i-[:]][\c-[:]]*: [^ ]+)(\s+[\i-[:]][\c-[:]]*: [^ ]+)*"
- }
- | string ""
- )
- }
- common.attrs.rdfa.property =
- attribute property {
- (
- list {
- ( common.data.rdfa.term
- | common.data.rdfa.curie
- | common.data.uri.absolute
- )+
- }
- | string ""
- )
- }
- common.attrs.rdfa.resource =
- attribute resource {
- ( common.data.rdfa.safecurie
- | common.data.rdfa.curie
- | common.data.uri
- )
- }
- common.attrs.rdfa.typeof =
- attribute typeof {
- (
- list {
- ( common.data.rdfa.term
- | common.data.rdfa.curie
- | common.data.uri.absolute
- )+
- }
- | string ""
- )
- }
- common.attrs.rdfa.vocab =
- attribute vocab {
- ( common.data.uri.absolute
- | string ""
- )
- }
- common.attrs.rdfa.about =
- attribute about {
- ( common.data.rdfa.safecurie
- | common.data.rdfa.curie
- | common.data.uri
- )
- } & nonRDFaLite
- common.attrs.rdfa.content =
- attribute content {
- string
- } & nonRDFaLite
- common.attrs.rdfa.datatype =
- attribute datatype {
- ( common.data.rdfa.term
- | common.data.rdfa.curie
- | common.data.uri.absolute
- | string ""
- )
- } & nonRDFaLite
- common.attrs.rdfa.rel =
- attribute rel {
- (
- list {
- ( common.data.rdfa.term
- | common.data.rdfa.curie
- | common.data.uri.absolute
- )+
- }
- | string ""
- )
- } & nonRDFaLite
- common.attrs.rdfa.rev =
- attribute rev {
- (
- list {
- ( common.data.rdfa.term
- | common.data.rdfa.curie
- | common.data.uri.absolute
- )+
- }
- | string ""
- )
- } & nonRDFaLite
- common.attrs.rdfa.inlist =
- attribute inlist {
- string
- } & nonRDFaLite
-
-common.attrs.rdfa.no-rel &=
- ( common.attrs.rdfa.about?
- & common.attrs.rdfa.prefix?
- & common.attrs.rdfa.property?
- & common.attrs.rdfa.typeof?
- & common.attrs.rdfa.vocab?
- & common.attrs.rdfa.content?
- & common.attrs.rdfa.datatype?
- & common.attrs.rdfa.resource?
- & common.attrs.rdfa.rev?
- & common.attrs.rdfa.inlist?
- )
-common.attrs.rdfa.no-rel-rev &=
- ( common.attrs.rdfa.about?
- & common.attrs.rdfa.prefix?
- & common.attrs.rdfa.property?
- & common.attrs.rdfa.typeof?
- & common.attrs.rdfa.vocab?
- & common.attrs.rdfa.content?
- & common.attrs.rdfa.datatype?
- & common.attrs.rdfa.resource?
- & common.attrs.rdfa.inlist?
- )
-common.attrs.rdfa.no-content-noproperty &=
- ( common.attrs.rdfa.about?
- & common.attrs.rdfa.prefix?
- & common.attrs.rdfa.typeof?
- & common.attrs.rdfa.vocab?
- & common.attrs.rdfa.datatype?
- & common.attrs.rdfa.resource?
- & common.attrs.rdfa.inlist?
- )
-
-common.attrs &= common.attrs.rdfa
-
-a.attrs &= common.attrs.rdfa.no-rel-rev
-area.attrs &= common.attrs.rdfa.no-rel
-base.attrs &= common.attrs.rdfa.no-rel
-
-link.rdfa.elem.metadata =
- element link { link.inner & link.rdfa.attrs.metadata }
-link.rdfa.elem.phrasing =
- element link { link.inner & link.rdfa.attrs.phrasing }
-link.rdfa.attrs.metadata =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & ( ( common.attrs.rdfa.property
- & ( link.attrs.rel
- | common.attrs.rdfa.rel
- )?
- )
- |
- ( common.attrs.rdfa.property?
- & ( link.attrs.rel
- | common.attrs.rdfa.rel
- )
- )
- )
- & link.attrs.href
- & common.attrs.rdfa.about?
- & common.attrs.rdfa.prefix?
- & common.attrs.rdfa.typeof?
- & common.attrs.rdfa.vocab?
- & common.attrs.rdfa.content?
- & common.attrs.rdfa.datatype?
- & common.attrs.rdfa.resource?
- & common.attrs.rdfa.rev?
- & common.attrs.rdfa.inlist?
- & shared-hyperlink.attrs.hreflang?
- & shared-hyperlink.attrs.media?
- & shared-hyperlink.attrs.type?
- & link.attrs.sizes?
- # link.attrs.title included in common.attrs
- )
-link.rdfa.attrs.phrasing =
- ( common.attrs.basic
- & common.attrs.i18n
- & common.attrs.present
- & common.attrs.other
- & common.attrs.rdfa.property
- & ( link.attrs.rel
- | common.attrs.rdfa.rel
- )?
- & link.attrs.href
- & common.attrs.rdfa.about?
- & common.attrs.rdfa.prefix?
- & common.attrs.rdfa.typeof?
- & common.attrs.rdfa.vocab?
- & common.attrs.rdfa.content?
- & common.attrs.rdfa.datatype?
- & common.attrs.rdfa.resource?
- & common.attrs.rdfa.rev?
- & common.attrs.rdfa.inlist?
- & shared-hyperlink.attrs.hreflang?
- & shared-hyperlink.attrs.media?
- & shared-hyperlink.attrs.type?
- & link.attrs.sizes?
- # link.attrs.title included in common.attrs
- )
- common.elem.metadata |= link.rdfa.elem.metadata
- common.elem.phrasing |= link.rdfa.elem.phrasing
-
-meta.name.attrs.name |= common.attrs.rdfa.property
-meta.name.attrs &= common.attrs.rdfa.no-content-noproperty
diff --git a/xml/relaxng/src/resources/html5-schema/revision.rnc b/xml/relaxng/src/resources/html5-schema/revision.rnc
deleted file mode 100644
index 4f518ee..0000000
--- a/xml/relaxng/src/resources/html5-schema/revision.rnc
+++ /dev/null
@@ -1,58 +0,0 @@
-# #####################################################################
-## RELAX NG Schema for HTML 5: Revision Annotations #
-# #####################################################################
-
-## Common Attributes
-
- edit.attrs.cite =
- attribute cite {
- common.data.uri
- }
- edit.attrs.datetime =
- attribute datetime {
- common.data.datetime | common.data.date
- }
-
-## Inserts: <ins>
-
- ins.elem.flow =
- element ins { ins.inner.flow & ins.attrs }
- ins.elem.phrasing =
- element ins { ins.inner.phrasing & ins.attrs }
- ins.attrs =
- ( common.attrs
- & edit.attrs.cite?
- & edit.attrs.datetime?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- ins.inner.flow =
- ( common.inner.transparent.flow )
- ins.inner.phrasing =
- ( common.inner.phrasing )
-
- common.elem.flow |= ins.elem.flow
- common.elem.phrasing |= ins.elem.phrasing
-
-## Deletions: <del>
-
- del.elem.flow =
- element del { del.inner.flow & del.attrs }
- del.elem.phrasing =
- element del { del.inner.phrasing & del.attrs }
- del.attrs =
- ( common.attrs
- & edit.attrs.cite?
- & edit.attrs.datetime?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- del.inner.flow =
- ( common.inner.transparent.flow )
- del.inner.phrasing =
- ( common.inner.phrasing )
-
- common.elem.flow |= del.elem.flow
- common.elem.phrasing |= del.elem.phrasing
diff --git a/xml/relaxng/src/resources/html5-schema/sectional.rnc b/xml/relaxng/src/resources/html5-schema/sectional.rnc
deleted file mode 100644
index 96af56b..0000000
--- a/xml/relaxng/src/resources/html5-schema/sectional.rnc
+++ /dev/null
@@ -1,171 +0,0 @@
-# #####################################################################
-## RELAX NG Schema for HTML 5: Sectioning Markup #
-# #####################################################################
-
-# #####################################################################
-## Headings
-
-## Heading (Rank 1): <h1>
-
- h1.elem =
- element h1 { h1.inner & h1.attrs }
- h1.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- h1.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= h1.elem
-
-## Heading (Rank 2): <h2>
-
- h2.elem =
- element h2 { h2.inner & h2.attrs }
- h2.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- h2.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= h2.elem
-
-## Heading (Rank 3): <h3>
-
- h3.elem =
- element h3 { h3.inner & h3.attrs }
- h3.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- h3.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= h3.elem
-
-## Heading (Rank 4): <h4>
-
- h4.elem =
- element h4 { h4.inner & h4.attrs }
- h4.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- h4.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= h4.elem
-
-## Heading (Rank 5): <h5>
-
- h5.elem =
- element h5 { h5.inner & h5.attrs }
- h5.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- h5.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= h5.elem
-
-## Heading (Rank 6): <h6>
-
- h6.elem =
- element h6 { h6.inner & h6.attrs }
- h6.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- h6.inner =
- ( common.inner.phrasing )
-
- common.elem.flow |= h6.elem
-
-## Heading Group: <hgroup>
-
- hgroup.elem =
- element hgroup { hgroup.inner & hgroup.attrs }
- hgroup.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.structure # not implementing "aria-level property set to the element's outline depth", nor heading role; see http://hsivonen.iki.fi/aria-html5-bis/
- | common.attrs.aria.role.heading
- | common.attrs.aria.role.tab
- | common.attrs.aria.role.presentation
- )?
- )
- hgroup.inner =
- ( h1.elem
- | h2.elem
- | h3.elem
- | h4.elem
- | h5.elem
- | h6.elem
- )+
-
- common.elem.flow |= hgroup.elem
-
-# #####################################################################
-## Section Meta
-
-## Contact Info: <address>
-
- address.elem =
- element address { address.inner & address.attrs }
- address.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.role.contentinfo
- | common.attrs.aria.role.presentation
- )?
- )
- address.inner =
- ( common.inner.flow )
-
- common.elem.flow |= address.elem
-
-# #####################################################################
-## Quotations
-
-## Block Quotes: <blockquote>
-
- blockquote.elem =
- element blockquote { blockquote.inner & blockquote.attrs }
- blockquote.attrs =
- ( common.attrs
- & blockquote.attrs.cite?
- & common.attrs.aria?
- )
- blockquote.attrs.cite =
- attribute cite {
- common.data.uri
- }
- blockquote.inner =
- ( common.inner.flow )
-
- common.elem.flow |= blockquote.elem
diff --git a/xml/relaxng/src/resources/html5-schema/structural.rnc b/xml/relaxng/src/resources/html5-schema/structural.rnc
deleted file mode 100644
index 284f599..0000000
--- a/xml/relaxng/src/resources/html5-schema/structural.rnc
+++ /dev/null
@@ -1,135 +0,0 @@
-# #####################################################################
-## RELAX NG Schema for HTML 5: Block Markup Added in HTML5 #
-# #####################################################################
-
-## Section: <section>
-
- section.elem =
- element section { section.inner & section.attrs }
- section.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.role.alert
- | common.attrs.aria.role.alertdialog
- | common.attrs.aria.role.contentinfo
- | common.attrs.aria.role.dialog
- | common.attrs.aria.role.log
- | common.attrs.aria.role.main
- | common.attrs.aria.role.marquee
- | common.attrs.aria.role.region
- | common.attrs.aria.role.status
- | common.attrs.aria.role.presentation
- | common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.document
- | common.attrs.aria.landmark.search
- )?
- )
- section.inner =
- ( common.inner.flow )
-
- common.elem.flow |= section.elem
-
-## Navigational Links: <nav>
-
- nav.elem =
- element nav { nav.inner & nav.attrs }
- nav.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.navigation
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.presentation
- )?
- )
- nav.inner =
- ( common.inner.flow )
-
- common.elem.flow |= nav.elem
-
-## Article: <article>
-
- article.elem =
- element article { article.inner & article.attrs }
- article.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.article
- | common.attrs.aria.landmark.document
- | common.attrs.aria.landmark.application
- | common.attrs.aria.landmark.main
- | common.attrs.aria.role.presentation
- )?
- )
- article.inner =
- ( style.elem*
- , common.inner.flow
- )
-
- common.elem.flow |= article.elem
-
-## Tangential Aside: <aside>
-
- aside.elem =
- element aside { aside.inner & aside.attrs }
- aside.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.note
- | common.attrs.aria.landmark.complementary
- | common.attrs.aria.landmark.search
- | common.attrs.aria.role.presentation
- )?
- )
- aside.inner =
- ( style.elem*
- , common.inner.flow
- )
-
- common.elem.flow |= aside.elem
-
-## Header: <header>
-
- header.elem =
- element header { header.inner & header.attrs }
- header.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.banner
- | common.attrs.aria.role.presentation
- )?
- )
- header.inner =
- ( common.inner.flow )
-
- common.elem.flow |= header.elem
-
-## Footer: <footer>
-
- footer.elem =
- element footer { footer.inner & footer.attrs }
- footer.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.contentinfo
- | common.attrs.aria.role.presentation
- )?
- )
- footer.inner =
- ( common.inner.flow )
-
- common.elem.flow |= footer.elem
-
-## main content: <main>
-
- main.elem =
- element main { main.inner & main.attrs }
- main.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.landmark.main
- )?
- )
- main.inner =
- ( common.inner.flow )
-
- common.elem.flow |= main.elem
diff --git a/xml/relaxng/src/resources/html5-schema/svg-xhtml5-rdf-mathml.rnc b/xml/relaxng/src/resources/html5-schema/svg-xhtml5-rdf-mathml.rnc
new file mode 100644
index 0000000..d78abee
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg-xhtml5-rdf-mathml.rnc
@@ -0,0 +1,38 @@
+namespace svg = "http://www.w3.org/2000/svg"
+namespace math = "http://www.w3.org/1998/Math/MathML"
+namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+include "html5/xhtml5full-xhtml.rnc" {
+ start = svg
+}
+include "svg11/svg11-inc.rnc"
+include "inkscape/inkscape.rnc"
+include "mml3/mathml3-inc.rnc"
+include "rdf/rdf.rnc"
+
+common.elem.metadata |= rdf.elem
+SVG.metadata.content |= rdf.elem
+
+common.elem.phrasing |= svg
+
+common.elem.phrasing |= math
+
+SVG.foreignObject.content |=
+ ( math
+ | html.elem
+ | body.elem
+ | common.inner.flow
+ )
+
+annotation-xml.model.svg |= svg
+
+annotation-xml.model.xhtml |=
+ ( html.elem
+ | common.elem.flow
+ )
+
+# in our integration, <mtext> is the only MathML "token element" that can
+# contain HTML element content; the <mi>, <mn>, <mo> and <ms> elements
+# cannot; see http://www.w3.org/Bugs/Public/show_bug.cgi?id=9859#c8 for a
+# rationale
+mtext.content |= common.elem.phrasing
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-animation.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-animation.rnc
new file mode 100644
index 0000000..b34476f
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-animation.rnc
@@ -0,0 +1,214 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Animation Module
+## file: svg-animation.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Animation
+##
+## animate, set, animateMotion, animateColor, animateTransform, mpath
+##
+## This module declares markup to provide support for animation.
+##
+
+##
+## SVG.Animation.class
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.Animation.extra.class = notAllowed
+ SVG.Animation.class |=
+ animate
+ | set
+ | animateMotion
+ | animateColor
+ | animateTransform
+ | SVG.Animation.extra.class
+ a:documentation [ "\x{a}" ~ " SVG.Animation.attrib\x{a}" ~ " " ]
+ SVG.Animation.extra.attrib = empty
+ SVG.Animation.attrib = SVG.XLink.attrib, SVG.Animation.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.AnimationAttribute.attrib\x{a}" ~
+ " "
+ ]
+ SVG.AnimationAttribute.extra.attrib = empty
+ SVG.AnimationAttribute.attrib =
+ attribute attributeName { text },
+ attribute attributeType { text }?,
+ SVG.AnimationAttribute.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.AnimationTiming.attrib\x{a}" ~
+ " "
+ ]
+ SVG.AnimationTiming.extra.attrib = empty
+ SVG.AnimationTiming.attrib =
+ attribute begin { text }?,
+ attribute dur { text }?,
+ attribute end { text }?,
+ attribute min { text }?,
+ attribute max { text }?,
+ [ a:defaultValue = "always" ]
+ attribute restart { string "always" | string "never" | string "whenNotActive" }?,
+ attribute repeatCount { text }?,
+ attribute repeatDur { text }?,
+ [ a:defaultValue = "remove" ]
+ attribute fill { string "remove" | string "freeze" }?,
+ SVG.AnimationTiming.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.AnimationValue.attrib\x{a}" ~
+ " "
+ ]
+ SVG.AnimationValue.extra.attrib = empty
+ SVG.AnimationValue.attrib =
+ [ a:defaultValue = "linear" ]
+ attribute calcMode {
+ string "discrete" | string "linear" | string "paced" | string "spline"
+ }?,
+ attribute values { text }?,
+ attribute keyTimes { text }?,
+ attribute keySplines { text }?,
+ attribute from { text }?,
+ attribute to { text }?,
+ attribute by { text }?,
+ SVG.AnimationValue.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.AnimationAddtion.attrib\x{a}" ~
+ " "
+ ]
+ SVG.AnimationAddtion.extra.attrib = empty
+ SVG.AnimationAddtion.attrib =
+ [ a:defaultValue = "replace" ]
+ attribute additive { string "replace" | string "sum" }?,
+ [ a:defaultValue = "none" ]
+ attribute accumulate { string "none" | string "sum" }?,
+ SVG.AnimationAddtion.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " animate: Animate Element\x{a}" ~
+ " "
+ ]
+ SVG.animate.content = SVG.Description.class*
+ animate = element animate { attlist.animate, SVG.animate.content }
+ attlist.animate &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.AnimationEvents.attrib,
+ SVG.External.attrib,
+ SVG.Animation.attrib,
+ SVG.AnimationAttribute.attrib,
+ SVG.AnimationTiming.attrib,
+ SVG.AnimationValue.attrib,
+ SVG.AnimationAddtion.attrib
+ a:documentation [ "\x{a}" ~ " set: Set Element\x{a}" ~ " " ]
+ SVG.set.content = SVG.Description.class*
+ set = element set { attlist.set, SVG.set.content }
+ attlist.set &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.AnimationEvents.attrib,
+ SVG.External.attrib,
+ SVG.Animation.attrib,
+ SVG.AnimationAttribute.attrib,
+ SVG.AnimationTiming.attrib,
+ attribute to { text }?
+ a:documentation [
+ "\x{a}" ~
+ " animateMotion: Animate Motion Element\x{a}" ~
+ " "
+ ]
+ SVG.animateMotion.content = SVG.Description.class*, mpath?
+ animateMotion =
+ element animateMotion {
+ attlist.animateMotion, SVG.animateMotion.content
+ }
+ attlist.animateMotion &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.AnimationEvents.attrib,
+ SVG.External.attrib,
+ SVG.Animation.attrib,
+ SVG.AnimationTiming.attrib,
+ SVG.AnimationAddtion.attrib,
+ [ a:defaultValue = "paced" ]
+ attribute calcMode {
+ string "discrete" | string "linear" | string "paced" | string "spline"
+ }?,
+ attribute values { text }?,
+ attribute keyTimes { text }?,
+ attribute keySplines { text }?,
+ attribute from { text }?,
+ attribute to { text }?,
+ attribute by { text }?,
+ attribute path { text }?,
+ attribute keyPoints { text }?,
+ attribute rotate { text }?,
+ attribute origin { text }?
+ a:documentation [
+ "\x{a}" ~
+ " animateColor: Animate Color Element\x{a}" ~
+ " "
+ ]
+ SVG.animateColor.content = SVG.Description.class*
+ animateColor =
+ element animateColor {
+ attlist.animateColor, SVG.animateColor.content
+ }
+ attlist.animateColor &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.AnimationEvents.attrib,
+ SVG.External.attrib,
+ SVG.Animation.attrib,
+ SVG.AnimationAttribute.attrib,
+ SVG.AnimationTiming.attrib,
+ SVG.AnimationValue.attrib,
+ SVG.AnimationAddtion.attrib
+ a:documentation [
+ "\x{a}" ~
+ " animateTransform: Animate Transform Element\x{a}" ~
+ " "
+ ]
+ SVG.animateTransform.content = SVG.Description.class*
+ animateTransform =
+ element animateTransform {
+ attlist.animateTransform, SVG.animateTransform.content
+ }
+ attlist.animateTransform &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.AnimationEvents.attrib,
+ SVG.External.attrib,
+ SVG.Animation.attrib,
+ SVG.AnimationAttribute.attrib,
+ SVG.AnimationTiming.attrib,
+ SVG.AnimationValue.attrib,
+ SVG.AnimationAddtion.attrib,
+ [ a:defaultValue = "translate" ]
+ attribute type {
+ string "translate" | string "scale" | string "rotate" | string "skewX" | string "skewY"
+ }?
+ a:documentation [
+ "\x{a}" ~
+ " mpath: Motion Path Element\x{a}" ~
+ " "
+ ]
+ SVG.mpath.content = SVG.Description.class*
+ mpath = element mpath { attlist.mpath, SVG.mpath.content }
+ attlist.mpath &=
+ SVG.Core.attrib, SVG.XLinkRequired.attrib, SVG.External.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-animevents-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-animevents-attrib.rnc
new file mode 100644
index 0000000..f3d7a11
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-animevents-attrib.rnc
@@ -0,0 +1,35 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Animation Events Attribute Module
+## file: svg-animevents-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Animation Events Attribute
+##
+## onbegin, onend, onrepeat, onload
+##
+## This module defines the AnimationEvents attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.onbegin.attrib = attribute onbegin { Script.datatype }?
+ SVG.onend.attrib = attribute onend { Script.datatype }?
+ SVG.onrepeat.attrib = attribute onrepeat { Script.datatype }?
+ SVG.AnimationEvents.extra.attrib = empty
+ SVG.AnimationEvents.attrib &=
+ SVG.onbegin.attrib,
+ SVG.onend.attrib,
+ SVG.onrepeat.attrib,
+ SVG.onload.attrib,
+ SVG.AnimationEvents.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-clip.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-clip.rnc
new file mode 100644
index 0000000..a3ee2c1
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-clip.rnc
@@ -0,0 +1,69 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Basic Clip Module
+## file: svg-basic-clip.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Basic Clip
+##
+## clipPath
+##
+## This module declares markup to provide support for clipping.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ ClipPathValue.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Clip.attrib\x{a}" ~ " " ]
+ SVG.Clip.extra.attrib = empty
+ SVG.Clip.attrib &=
+ attribute clip-path { ClipPathValue.datatype }?,
+ attribute clip-rule { ClipFillRule.datatype }?,
+ SVG.Clip.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Clip.class\x{a}" ~ " " ]
+ SVG.Clip.extra.class = notAllowed
+ SVG.Clip.class |= clipPath | SVG.Clip.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " clipPath: Clip Path Element\x{a}" ~
+ " "
+ ]
+ SVG.clipPath.class = rect | SVG.Animation.class | SVG.Use.class
+ SVG.clipPath.content = SVG.Description.class*, SVG.clipPath.class*
+ clipPath =
+ element clipPath { attlist.clipPath, SVG.clipPath.content }
+ attlist.clipPath &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Text.attrib,
+ SVG.TextContent.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute transform { TransformList.datatype }?,
+ attribute clipPathUnits {
+ "userSpaceOnUse" | "objectBoundingBox"
+ }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-filter.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-filter.rnc
new file mode 100644
index 0000000..e3e861f
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-filter.rnc
@@ -0,0 +1,362 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Basic Filter Module
+## file: svg-basic-filter.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Basic Filter
+##
+## filter, feBlend, feColorMatrix, feComponentTransfer, feComposite,
+## feFlood, feGaussianBlur, feImage, feMerge, feMergeNode, feOffset,
+## feTile, feFuncR, feFuncG, feFuncB, feFuncA
+##
+## This module declares markup to provide support for filter effect.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ FilterValue.datatype = xsd:string
+ NumberOptionalNumber.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Filter.attrib\x{a}" ~ " " ]
+ SVG.Filter.extra.attrib = empty
+ SVG.Filter.attrib &=
+ attribute filter { FilterValue.datatype }?,
+ SVG.Filter.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.FilterColor.attrib\x{a}" ~
+ " "
+ ]
+ SVG.FilterColor.extra.attrib = empty
+ SVG.FilterColor.attrib &=
+ attribute color-interpolation-filters {
+ string "auto" | string "sRGB" | string "linearRGB" | string "inherit"
+ }?,
+ SVG.FilterColor.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Filter.class\x{a}" ~ " " ]
+ SVG.Filter.extra.class = notAllowed
+ SVG.Filter.class |= filter | SVG.Filter.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " SVG.FilterPrimitive.class\x{a}" ~
+ " "
+ ]
+ SVG.FilterPrimitive.extra.class = notAllowed
+ SVG.FilterPrimitive.class =
+ feBlend
+ | feColorMatrix
+ | feComponentTransfer
+ | feComposite
+ | feFlood
+ | feGaussianBlur
+ | feImage
+ | feMerge
+ | feOffset
+ | feTile
+ | SVG.FilterPrimitive.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " SVG.FilterPrimitive.attrib\x{a}" ~
+ " "
+ ]
+ SVG.FilterPrimitive.extra.attrib = empty
+ SVG.FilterPrimitive.attrib =
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype }?,
+ attribute height { Length.datatype }?,
+ attribute result { text }?,
+ SVG.FilterPrimitive.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.FilterPrimitiveWithIn.attrib\x{a}" ~
+ " "
+ ]
+ SVG.FilterPrimitiveWithIn.extra.attrib = empty
+ SVG.FilterPrimitiveWithIn.attrib =
+ SVG.FilterPrimitive.attrib,
+ attribute in { text }?,
+ SVG.FilterPrimitiveWithIn.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " filter: Filter Element\x{a}" ~
+ " "
+ ]
+ SVG.filter.content =
+ SVG.Description.class*,
+ (animate | set | SVG.FilterPrimitive.class)*
+ filter = element filter { attlist.filter, SVG.filter.content }
+ attlist.filter &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.XLink.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype }?,
+ attribute height { Length.datatype }?,
+ attribute filterRes { NumberOptionalNumber.datatype }?,
+ attribute filterUnits {
+ string "userSpaceOnUse" | string "objectBoundingBox"
+ }?,
+ attribute primitiveUnits {
+ string "userSpaceOnUse" | string "objectBoundingBox"
+ }?
+ a:documentation [
+ "\x{a}" ~
+ " feBlend: Filter Effect Blend Element\x{a}" ~
+ " "
+ ]
+ SVG.feBlend.content = (animate | set)*
+ feBlend = element feBlend { attlist.feBlend, SVG.feBlend.content }
+ attlist.feBlend &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute in2 { text },
+ [ a:defaultValue = "normal" ]
+ attribute mode {
+ string "normal" | string "multiply" | string "screen" | string "darken" | string "lighten"
+ }?
+ a:documentation [
+ "\x{a}" ~
+ " feColorMatrix: Filter Effect Color Matrix Element\x{a}" ~
+ " "
+ ]
+ SVG.feColorMatrix.content = (animate | set)*
+ feColorMatrix =
+ element feColorMatrix {
+ attlist.feColorMatrix, SVG.feColorMatrix.content
+ }
+ attlist.feColorMatrix &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ [ a:defaultValue = "matrix" ]
+ attribute type {
+ string "matrix" | string "saturate" | string "hueRotate" | string "luminanceToAlpha"
+ }?,
+ attribute values { text }?
+ a:documentation [
+ "\x{a}" ~
+ " feComponentTransfer: Filter Effect Component Transfer Element\x{a}" ~
+ " "
+ ]
+ SVG.feComponentTransfer.content =
+ feFuncR?, feFuncG?, feFuncB?, feFuncA?
+ feComponentTransfer =
+ element feComponentTransfer {
+ attlist.feComponentTransfer, SVG.feComponentTransfer.content
+ }
+ attlist.feComponentTransfer &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib
+ a:documentation [
+ "\x{a}" ~
+ " feComposite: Filter Effect Composite Element\x{a}" ~
+ " "
+ ]
+ SVG.feComposite.content = (animate | set)*
+ feComposite =
+ element feComposite {
+ attlist.feComposite, SVG.feComposite.content
+ }
+ attlist.feComposite &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute in2 { text },
+ [ a:defaultValue = "over" ]
+ attribute operator {
+ string "over" | string "in" | string "out" | string "atop" | string "xor" | string "arithmetic"
+ }?,
+ attribute k1 { Number.datatype }?,
+ attribute k2 { Number.datatype }?,
+ attribute k3 { Number.datatype }?,
+ attribute k4 { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feFlood: Filter Effect Flood Element\x{a}" ~
+ " "
+ ]
+ SVG.feFlood.content = (animate | set | animateColor)*
+ feFlood = element feFlood { attlist.feFlood, SVG.feFlood.content }
+ attlist.feFlood &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Color.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute flood-color { SVGColor.datatype }?,
+ attribute flood-opacity { OpacityValue.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feGaussianBlur: Filter Effect Gaussian Blur Element\x{a}" ~
+ " "
+ ]
+ SVG.feGaussianBlur.content = (animate | set)*
+ feGaussianBlur =
+ element feGaussianBlur {
+ attlist.feGaussianBlur, SVG.feGaussianBlur.content
+ }
+ attlist.feGaussianBlur &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute stdDeviation { NumberOptionalNumber.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feImage: Filter Effect Image Element\x{a}" ~
+ " "
+ ]
+ SVG.feImage.content = (animate | set | animateTransform)*
+ feImage = element feImage { attlist.feImage, SVG.feImage.content }
+ attlist.feImage &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.FilterPrimitive.attrib,
+ SVG.XLinkEmbed.attrib,
+ SVG.External.attrib,
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?
+ a:documentation [
+ "\x{a}" ~
+ " feMerge: Filter Effect Merge Element\x{a}" ~
+ " "
+ ]
+ SVG.feMerge.content = feMergeNode*
+ feMerge = element feMerge { attlist.feMerge, SVG.feMerge.content }
+ attlist.feMerge &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitive.attrib
+ a:documentation [
+ "\x{a}" ~
+ " feMergeNode: Filter Effect Merge Node Element\x{a}" ~
+ " "
+ ]
+ SVG.feMergeNode.content = (animate | set)*
+ feMergeNode =
+ element feMergeNode {
+ attlist.feMergeNode, SVG.feMergeNode.content
+ }
+ attlist.feMergeNode &=
+ SVG.Core.attrib,
+ attribute in { text }?
+ a:documentation [
+ "\x{a}" ~
+ " feOffset: Filter Effect Offset Element\x{a}" ~
+ " "
+ ]
+ SVG.feOffset.content = (animate | set)*
+ feOffset =
+ element feOffset { attlist.feOffset, SVG.feOffset.content }
+ attlist.feOffset &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute dx { Number.datatype }?,
+ attribute dy { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feTile: Filter Effect Tile Element\x{a}" ~
+ " "
+ ]
+ SVG.feTile.content = (animate | set)*
+ feTile = element feTile { attlist.feTile, SVG.feTile.content }
+ attlist.feTile &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib
+ a:documentation [
+ "\x{a}" ~
+ " feFuncR: Filter Effect Function Red Element\x{a}" ~
+ " "
+ ]
+ SVG.feFuncR.content = (animate | set)*
+ feFuncR = element feFuncR { attlist.feFuncR, SVG.feFuncR.content }
+ attlist.feFuncR &=
+ SVG.Core.attrib,
+ attribute type {
+ string "identity" | string "table" | string "discrete" | string "linear" | string "gamma"
+ },
+ attribute tableValues { text }?,
+ attribute slope { Number.datatype }?,
+ attribute intercept { Number.datatype }?,
+ attribute amplitude { Number.datatype }?,
+ attribute exponent { Number.datatype }?,
+ attribute offset { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feFuncG: Filter Effect Function Green Element\x{a}" ~
+ " "
+ ]
+ SVG.feFuncG.content = (animate | set)*
+ feFuncG = element feFuncG { attlist.feFuncG, SVG.feFuncG.content }
+ attlist.feFuncG &=
+ SVG.Core.attrib,
+ attribute type {
+ string "identity" | string "table" | string "discrete" | string "linear" | string "gamma"
+ },
+ attribute tableValues { text }?,
+ attribute slope { Number.datatype }?,
+ attribute intercept { Number.datatype }?,
+ attribute amplitude { Number.datatype }?,
+ attribute exponent { Number.datatype }?,
+ attribute offset { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feFuncB: Filter Effect Function Blue Element\x{a}" ~
+ " "
+ ]
+ SVG.feFuncB.content = (animate | set)*
+ feFuncB = element feFuncB { attlist.feFuncB, SVG.feFuncB.content }
+ attlist.feFuncB &=
+ SVG.Core.attrib,
+ attribute type {
+ string "identity" | string "table" | string "discrete" | string "linear" | string "gamma"
+ },
+ attribute tableValues { text }?,
+ attribute slope { Number.datatype }?,
+ attribute intercept { Number.datatype }?,
+ attribute amplitude { Number.datatype }?,
+ attribute exponent { Number.datatype }?,
+ attribute offset { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feFuncA: Filter Effect Function Alpha Element\x{a}" ~
+ " "
+ ]
+ SVG.feFuncA.content = (animate | set)*
+ feFuncA = element feFuncA { attlist.feFuncA, SVG.feFuncA.content }
+ attlist.feFuncA &=
+ SVG.Core.attrib,
+ attribute type {
+ string "identity" | string "table" | string "discrete" | string "linear" | string "gamma"
+ },
+ attribute tableValues { text }?,
+ attribute slope { Number.datatype }?,
+ attribute intercept { Number.datatype }?,
+ attribute amplitude { Number.datatype }?,
+ attribute exponent { Number.datatype }?,
+ attribute offset { Number.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc
new file mode 100644
index 0000000..32eb146
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-font.rnc
@@ -0,0 +1,200 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Basic Font Module
+## file: svg-basic-font.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Basic Font
+##
+## font, font-face, glyph, missing-glyph, hkern, vkern, font-face-src,
+## font-face-uri, font-face-name
+##
+## This module declares markup to provide support for template.
+##
+
+##
+## SVG.Font.class
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.Font.extra.class = notAllowed
+ SVG.Font.class |= font | font-face | SVG.Font.extra.class
+ a:documentation [ "\x{a}" ~ " font: Font Element\x{a}" ~ " " ]
+ SVG.font.content =
+ SVG.Description.class*,
+ font-face,
+ missing-glyph,
+ (glyph | hkern | vkern)*
+ font = element font { attlist.font, SVG.font.content }
+ attlist.font &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.External.attrib,
+ attribute horiz-origin-x { Number.datatype }?,
+ attribute horiz-origin-y { Number.datatype }?,
+ attribute horiz-adv-x { Number.datatype },
+ attribute vert-origin-x { Number.datatype }?,
+ attribute vert-origin-y { Number.datatype }?,
+ attribute vert-adv-y { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " font-face: Font Face Element\x{a}" ~
+ " "
+ ]
+ SVG.font-face.extra.class = notAllowed
+ SVG.font-face.content =
+ SVG.Description.class*,
+ font-face-src?,
+ SVG.font-face.extra.class
+ font-face =
+ element font-face { attlist.font-face, SVG.font-face.content }
+ attlist.font-face &=
+ SVG.Core.attrib,
+ attribute font-family { text }?,
+ attribute font-style { text }?,
+ attribute font-variant { text }?,
+ attribute font-weight { text }?,
+ attribute font-stretch { text }?,
+ attribute font-size { text }?,
+ attribute unicode-range { text }?,
+ attribute units-per-em { Number.datatype }?,
+ attribute panose-1 { text }?,
+ attribute stemv { Number.datatype }?,
+ attribute stemh { Number.datatype }?,
+ attribute slope { Number.datatype }?,
+ attribute cap-height { Number.datatype }?,
+ attribute x-height { Number.datatype }?,
+ attribute accent-height { Number.datatype }?,
+ attribute ascent { Number.datatype }?,
+ attribute descent { Number.datatype }?,
+ attribute widths { text }?,
+ attribute bbox { text }?,
+ attribute ideographic { Number.datatype }?,
+ attribute alphabetic { Number.datatype }?,
+ attribute mathematical { Number.datatype }?,
+ attribute hanging { Number.datatype }?,
+ attribute v-ideographic { Number.datatype }?,
+ attribute v-alphabetic { Number.datatype }?,
+ attribute v-mathematical { Number.datatype }?,
+ attribute v-hanging { Number.datatype }?,
+ attribute underline-position { Number.datatype }?,
+ attribute underline-thickness { Number.datatype }?,
+ attribute strikethrough-position { Number.datatype }?,
+ attribute strikethrough-thickness { Number.datatype }?,
+ attribute overline-position { Number.datatype }?,
+ attribute overline-thickness { Number.datatype }?
+ a:documentation [ "\x{a}" ~ " glyph: Glyph Element\x{a}" ~ " " ]
+ SVG.glyph.class = notAllowed
+ SVG.glyph.content = SVG.Description.class*, SVG.glyph.class*
+ glyph = element glyph { attlist.glyph, SVG.glyph.content }
+ attlist.glyph &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ attribute unicode { text }?,
+ attribute glyph-name { text }?,
+ attribute d { PathData.datatype }?,
+ attribute orientation { text }?,
+ attribute arabic-form { text }?,
+ attribute lang { LanguageCodes.datatype }?,
+ attribute horiz-adv-x { Number.datatype }?,
+ attribute vert-origin-x { Number.datatype }?,
+ attribute vert-origin-y { Number.datatype }?,
+ attribute vert-adv-y { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " missing-glyph: Missing Glyph Element\x{a}" ~
+ " "
+ ]
+ SVG.missing-glyph.class = notAllowed
+ SVG.missing-glyph.content =
+ SVG.Description.class*, SVG.missing-glyph.class*
+ missing-glyph =
+ element missing-glyph {
+ attlist.missing-glyph, SVG.missing-glyph.content
+ }
+ attlist.missing-glyph &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ attribute d { PathData.datatype }?,
+ attribute horiz-adv-x { Number.datatype }?,
+ attribute vert-origin-x { Number.datatype }?,
+ attribute vert-origin-y { Number.datatype }?,
+ attribute vert-adv-y { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " hkern: Horizontal Kerning Element\x{a}" ~
+ " "
+ ]
+ SVG.hkern.content = empty
+ hkern = element hkern { attlist.hkern, SVG.hkern.content }
+ attlist.hkern &=
+ SVG.Core.attrib,
+ attribute u1 { text }?,
+ attribute g1 { text }?,
+ attribute u2 { text }?,
+ attribute g2 { text }?,
+ attribute k { Number.datatype }
+ a:documentation [
+ "\x{a}" ~
+ " vkern: Vertical Kerning Element\x{a}" ~
+ " "
+ ]
+ SVG.vkern.content = empty
+ vkern = element vkern { attlist.vkern, SVG.vkern.content }
+ attlist.vkern &=
+ SVG.Core.attrib,
+ attribute u1 { text }?,
+ attribute g1 { text }?,
+ attribute u2 { text }?,
+ attribute g2 { text }?,
+ attribute k { Number.datatype }
+ a:documentation [
+ "\x{a}" ~
+ " font-face-src: Font Face Source Element\x{a}" ~
+ " "
+ ]
+ SVG.font-face-src.content = (font-face-uri | font-face-name)+
+ font-face-src =
+ element font-face-src {
+ attlist.font-face-src, SVG.font-face-src.content
+ }
+ attlist.font-face-src &= SVG.Core.attrib
+ a:documentation [
+ "\x{a}" ~
+ " font-face-uri: Font Face URI Element\x{a}" ~
+ " "
+ ]
+ SVG.font-face-uri.content = empty
+ font-face-uri =
+ element font-face-uri {
+ attlist.font-face-uri, SVG.font-face-uri.content
+ }
+ attlist.font-face-uri &= SVG.Core.attrib, SVG.XLinkRequired.attrib
+ a:documentation [
+ "\x{a}" ~
+ " font-face-name: Font Face Name Element\x{a}" ~
+ " "
+ ]
+ SVG.font-face-name.content = empty
+ font-face-name =
+ element font-face-name {
+ attlist.font-face-name, SVG.font-face-name.content
+ }
+ attlist.font-face-name &=
+ SVG.Core.attrib,
+ attribute name { text }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-graphics-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-graphics-attrib.rnc
new file mode 100644
index 0000000..77bbd43
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-graphics-attrib.rnc
@@ -0,0 +1,53 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Basic Graphics Attribute Module
+## file: svg-basic-graphics-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Basic Graphics Attribute
+##
+## display, visibility
+##
+## This module defines the Graphics attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.display.attrib =
+ attribute display {
+ string "inline"
+ | string "block"
+ | string "list-item"
+ | string "run-in"
+ | string "compact"
+ | string "marker"
+ | string "table"
+ | string "inline-table"
+ | string "table-row-group"
+ | string "table-header-group"
+ | string "table-footer-group"
+ | string "table-row"
+ | string "table-column-group"
+ | string "table-column"
+ | string "table-cell"
+ | string "table-caption"
+ | string "none"
+ | string "inherit"
+ }?
+ SVG.visibility.attrib =
+ attribute visibility { string "visible" | string "hidden" | string "collapse" | string "inherit" }?
+ SVG.Graphics.extra.attrib = empty
+ SVG.Graphics.attrib &=
+ SVG.display.attrib,
+ SVG.visibility.attrib,
+ SVG.Graphics.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-structure.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-structure.rnc
new file mode 100644
index 0000000..4471528
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-structure.rnc
@@ -0,0 +1,299 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+##
+## SVG 1.1 Basic Structure Module
+## file: svg-basic-structure.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Basic Structure
+##
+## svg, g, defs, desc, title, metadata, use
+##
+## This module declares the major structural elements and their attributes.
+##
+[ xml:lang = "en" ]
+grammar {
+
+ # removed start = -- hsivonen
+
+ ##
+ ## Include core set of modules
+ ##
+ div {
+
+ ##
+ ## Datatypes Module
+ ##
+ include "svg-datatypes.rnc"
+
+ ##
+ ## Core Attribute Module
+ ##
+ include "svg-core-attrib.rnc"
+ }
+ a:documentation [
+ "\x{a}" ~
+ " Content Models (Default)\x{a}" ~
+ " "
+ ]
+ SVG.Profile.class = notAllowed
+ SVG.Gradient.class = notAllowed
+ SVG.Pattern.class = notAllowed
+ SVG.Clip.class = notAllowed
+ SVG.Mask.class = notAllowed
+ SVG.Filter.class = notAllowed
+ SVG.Cursor.class = notAllowed
+ SVG.Marker.class = notAllowed
+ SVG.View.class = notAllowed
+ SVG.Script.class = notAllowed
+ SVG.Font.class = notAllowed
+ SVG.Extensibility.class = notAllowed
+ SVG.Conditional.class = notAllowed
+ SVG.Image.class = notAllowed
+ SVG.Style.class = notAllowed
+ SVG.Shape.class = notAllowed
+ SVG.Text.class = notAllowed
+ SVG.Hyperlink.class = notAllowed
+ SVG.Animation.class = notAllowed
+ a:documentation [
+ "\x{a}" ~
+ " Attribute Collections (Default)\x{a}" ~
+ " "
+ ]
+ SVG.Container.attrib = empty
+ SVG.Viewport.attrib = empty
+ SVG.Text.attrib = empty
+ SVG.TextContent.attrib = empty
+ SVG.Opacity.attrib = empty
+ SVG.Marker.attrib = empty
+ SVG.Profile.attrib = empty
+ SVG.Gradient.attrib = empty
+ SVG.Clip.attrib = empty
+ SVG.Mask.attrib = empty
+ SVG.Filter.attrib = empty
+ SVG.FilterColor.attrib = empty
+ SVG.Cursor.attrib = empty
+ SVG.External.attrib = empty
+ SVG.Conditional.attrib = empty
+ SVG.Color.attrib = empty
+ SVG.Paint.attrib = empty
+ SVG.Graphics.attrib = empty
+ SVG.DocumentEvents.attrib = empty
+ SVG.GraphicalEvents.attrib = empty
+ SVG.onload.attrib = empty
+ SVG.AnimationEvents.attrib = empty
+ SVG.XLink.attrib = empty
+ SVG.XLinkRequired.attrib = empty
+ SVG.XLinkEmbed.attrib = empty
+ SVG.XLinkReplace.attrib = empty
+ SVG.Style.attrib = empty
+ SVG.Font.attrib = empty
+ a:documentation [
+ "\x{a}" ~
+ " SVG.Description.class\x{a}" ~
+ " "
+ ]
+ SVG.Description.extra.class = notAllowed
+ SVG.Description.class =
+ desc | title | metadata | SVG.Description.extra.class
+ a:documentation [ "\x{a}" ~ " SVG.Use.class\x{a}" ~ " " ]
+ SVG.Use.extra.class = notAllowed
+ SVG.Use.class = use | SVG.Use.extra.class
+ a:documentation [ "\x{a}" ~ " SVG.Structure.class\x{a}" ~ " " ]
+ SVG.Structure.extra.class = notAllowed
+ SVG.Structure.class =
+ svg | g | defs | SVG.Use.class | SVG.Structure.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " SVG.Presentation.attrib\x{a}" ~
+ " "
+ ]
+ SVG.Presentation.extra.attrib = empty
+ SVG.Presentation.attrib =
+ SVG.Container.attrib,
+ SVG.Viewport.attrib,
+ SVG.Text.attrib,
+ SVG.TextContent.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Marker.attrib,
+ SVG.Profile.attrib,
+ SVG.Gradient.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.FilterColor.attrib,
+ SVG.Cursor.attrib,
+ attribute flood-color { SVGColor.datatype }?,
+ attribute flood-opacity { OpacityValue.datatype }?,
+ attribute lighting-color { SVGColor.datatype }?,
+ SVG.Presentation.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " svg: SVG Document Element\x{a}" ~
+ " "
+ ]
+ SVG.svg.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ svg = element svg { attlist.svg, SVG.svg.content }
+ attlist.svg &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.DocumentEvents.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype }?,
+ attribute height { Length.datatype }?,
+ attribute viewBox { ViewBoxSpec.datatype }?,
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?,
+ [ a:defaultValue = "magnify" ]
+ attribute zoomAndPan { string "disable" | string "magnify" }?,
+ [ a:defaultValue = "1.1" ]
+ attribute version { string "1.0" | string "1.1" | string "1.2" }?, # Allow 1.0 and 1.2 -- hsivonen
+ attribute baseProfile { Text.datatype }?,
+ [ a:defaultValue = "text/ecmascript" ]
+ attribute contentScriptType { ContentType.datatype }?,
+ [ a:defaultValue = "text/css" ]
+ attribute contentStyleType { ContentType.datatype }?
+ a:documentation [ "\x{a}" ~ " g: Group Element\x{a}" ~ " " ]
+ SVG.g.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ g = element g { attlist.g, SVG.g.content }
+ attlist.g &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.External.attrib,
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " defs: Definisions Element\x{a}" ~
+ " "
+ ]
+ SVG.defs.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ defs = element defs { attlist.defs, SVG.defs.content }
+ attlist.defs &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.External.attrib,
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " desc: Description Element\x{a}" ~
+ " "
+ ]
+ SVG.desc.content = text
+ desc = element desc { attlist.desc, SVG.desc.content }
+ attlist.desc &= SVG.Core.attrib, SVG.Style.attrib
+ a:documentation [ "\x{a}" ~ " title: Title Element\x{a}" ~ " " ]
+ SVG.title.content = text
+ title = element title { attlist.title, SVG.title.content }
+ attlist.title &= SVG.Core.attrib, SVG.Style.attrib
+ a:documentation [
+ "\x{a}" ~
+ " metadata: Metadata Element\x{a}" ~
+ " "
+ ]
+ SVG.metadata.content = empty # bugfix -- hsivonen
+ metadata =
+ element metadata { attlist.metadata, SVG.metadata.content }
+ attlist.metadata &= SVG.Core.attrib
+ a:documentation [ "\x{a}" ~ " use: Use Element\x{a}" ~ " " ]
+ SVG.use.content = SVG.Description.class*, SVG.Animation.class*
+ use = element use { attlist.use, SVG.use.content }
+ attlist.use &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.XLinkEmbed.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype }?,
+ attribute height { Length.datatype }?,
+ attribute transform { TransformList.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-text.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-text.rnc
new file mode 100644
index 0000000..4cfc157
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-basic-text.rnc
@@ -0,0 +1,147 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Basic Text Module
+## file: svg-basic-text.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Basic Text
+##
+## text, altGlyph, altGlyphDef, glyphRef
+##
+## This module declares markup to provide support for text.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ FontFamilyValue.datatype = xsd:string
+ FontSizeValue.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Font.attrib\x{a}" ~ " " ]
+ SVG.Font.extra.attrib = empty
+ SVG.Font.attrib &=
+ attribute font-family { FontFamilyValue.datatype }?,
+ attribute font-size { FontSizeValue.datatype }?,
+ attribute font-style {
+ string "normal" | string "italic" | string "oblique" | string "inherit"
+ }?,
+ attribute font-weight {
+ string "normal"
+ | string "bold"
+ | string "bolder"
+ | string "lighter"
+ | string "100"
+ | string "200"
+ | string "300"
+ | string "400"
+ | string "500"
+ | string "600"
+ | string "700"
+ | string "800"
+ | string "900"
+ | string "inherit"
+ }?,
+ SVG.Font.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Text.class\x{a}" ~ " " ]
+ SVG.Text.extra.class = notAllowed
+ SVG.Text.class |= \text | SVG.Text.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " SVG.TextContent.class\x{a}" ~
+ " "
+ ]
+ SVG.TextContent.extra.class = notAllowed
+ SVG.TextContent.class = altGlyph | SVG.TextContent.extra.class
+ a:documentation [ "\x{a}" ~ " text: Text Element\x{a}" ~ " " ]
+ SVG.text.class =
+ text
+ | SVG.Description.class
+ | SVG.Animation.class
+ | # <ref name="SVG.TextContent.extra.class"/>
+ SVG.Hyperlink.class
+ SVG.text.content = SVG.text.class*
+ \text = element text { attlist.text, SVG.text.content }
+ attlist.text &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinates.datatype }?,
+ attribute y { Coordinates.datatype }?,
+ attribute rotate { Numbers.datatype }?,
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " altGlyph: Alternate Glyph Element\x{a}" ~
+ " "
+ ]
+ SVG.altGlyph.content = text
+ altGlyph =
+ element altGlyph { attlist.altGlyph, SVG.altGlyph.content }
+ attlist.altGlyph &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.XLink.attrib,
+ SVG.External.attrib,
+ attribute glyphRef { text }?,
+ attribute format { text }?
+ a:documentation [
+ "\x{a}" ~
+ " altGlyphDef: Alternate Glyph Definition Element\x{a}" ~
+ " "
+ ]
+ SVG.altGlyphDef.content = glyphRef+
+ altGlyphDef =
+ element altGlyphDef {
+ attlist.altGlyphDef, SVG.altGlyphDef.content
+ }
+ attlist.altGlyphDef &= SVG.Core.attrib
+ a:documentation [
+ "\x{a}" ~
+ " glyphRef: Glyph Reference Element\x{a}" ~
+ " "
+ ]
+ SVG.glyphRef.content = empty
+ glyphRef =
+ element glyphRef { attlist.glyphRef, SVG.glyphRef.content }
+ attlist.glyphRef &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Font.attrib,
+ SVG.XLink.attrib,
+ attribute glyphRef { text }?,
+ attribute format { text }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-clip.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-clip.rnc
new file mode 100644
index 0000000..a168471
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-clip.rnc
@@ -0,0 +1,32 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+
+
+##
+## SVG 1.1 Clip Module
+## file: svg-clip.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Clip
+##
+## clipPath
+##
+## This module declares markup to provide support for clipping.
+##
+[ xml:lang = "en" ]
+grammar {
+ include "svg-basic-clip.rnc" inherit = svg
+
+ ##
+ ## extend content model of clipPath
+ ##
+ SVG.clipPath.class |= SVG.Shape.class | SVG.Text.class
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc
new file mode 100644
index 0000000..22f3cc2
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-conditional.rnc
@@ -0,0 +1,76 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Conditional Processing Module
+## file: svg-conditional.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Conditional Processing
+##
+## switch
+##
+## This module declares markup to provide support for conditional processing.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ ExtensionList.datatype = xsd:string
+ FeatureList.datatype = xsd:string
+ a:documentation [
+ "\x{a}" ~
+ " SVG.Conditional.attrib\x{a}" ~
+ " "
+ ]
+ SVG.Conditional.extra.attrib = empty
+ SVG.Conditional.attrib &=
+ attribute requiredFeatures { FeatureList.datatype }?,
+ attribute requiredExtensions { ExtensionList.datatype }?,
+ attribute systemLanguage { LanguageCodes.datatype }?,
+ SVG.Conditional.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.Conditional.class\x{a}" ~
+ " "
+ ]
+ SVG.Conditional.extra.class = notAllowed
+ SVG.Conditional.class |= switch | SVG.Conditional.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " switch: Switch Element\x{a}" ~
+ " "
+ ]
+ SVG.switch.content =
+ SVG.Description.class*,
+ (svg
+ | g
+ | use
+ | \text
+ | SVG.Animation.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Shape.class
+ | SVG.Hyperlink.class
+ | SVG.Extensibility.class)*
+ switch = element switch { attlist.switch, SVG.switch.content }
+ attlist.switch &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.External.attrib,
+ attribute transform { TransformList.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-container-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-container-attrib.rnc
new file mode 100644
index 0000000..263fecd
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-container-attrib.rnc
@@ -0,0 +1,35 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Container Attribute Module
+## file: svg-container-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Container Attribute
+##
+## enable-background
+##
+## This module defines the Container attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## 'enable-background' property/attribute value (e.g., 'new', 'accumulate')
+ ##
+ EnableBackgroundValue.datatype = xsd:string
+ SVG.enable-background.attrib =
+ attribute enable-background { EnableBackgroundValue.datatype }?
+ SVG.Container.extra.attrib = empty
+ SVG.Container.attrib &=
+ SVG.enable-background.attrib, SVG.Container.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-core-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-core-attrib.rnc
new file mode 100644
index 0000000..f68b4ac
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-core-attrib.rnc
@@ -0,0 +1,38 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+datatypes w = "http://whattf.org/datatype-draft"
+
+
+##
+## SVG 1.1 Core Attribute Module
+## file: svg-core-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007-2008 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Core Attribute
+##
+## id, xml:base, xml:lang, xml:space
+##
+## This module defines the core set of attributes that can be present on
+## any element.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.id.attrib = attribute id { w:xml-name }?
+ SVG.base.attrib = attribute xml:base { URI.datatype }?
+ SVG.lang.attrib = attribute xml:lang { LanguageCode.datatype }?
+ SVG.space.attrib = attribute xml:space { string "default" | string "preserve" }?
+ SVG.Core.extra.attrib = empty
+ SVG.Core.attrib =
+ SVG.id.attrib,
+ SVG.base.attrib,
+ SVG.lang.attrib,
+ SVG.space.attrib,
+ SVG.Core.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-cursor.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-cursor.rnc
new file mode 100644
index 0000000..c3051d5
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-cursor.rnc
@@ -0,0 +1,53 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Cursor Module
+## file: svg-cursor.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Cursor
+##
+## cursor
+##
+## This module declares markup to provide support for cursor.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ CursorValue.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Cursor.attrib\x{a}" ~ " " ]
+ SVG.Cursor.extra.attrib = empty
+ SVG.Cursor.attrib &=
+ attribute cursor { CursorValue.datatype }?,
+ SVG.Cursor.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Cursor.class\x{a}" ~ " " ]
+ SVG.Cursor.extra.class = notAllowed
+ SVG.Cursor.class |= cursor | SVG.Cursor.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " cursor: Cursor Element\x{a}" ~
+ " "
+ ]
+ SVG.cursor.content = SVG.Description.class*
+ cursor = element cursor { attlist.cursor, SVG.cursor.content }
+ attlist.cursor &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.XLinkRequired.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-datatypes.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-datatypes.rnc
new file mode 100644
index 0000000..70032cb
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-datatypes.rnc
@@ -0,0 +1,138 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+datatypes w = "http://whattf.org/datatype-draft"
+
+
+##
+## SVG 1.1 Datatypes Module
+## file: svg-datatypes.mod
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007-2012 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Datatypes
+##
+## This module declares common data types for properties and attributes.
+##
+
+##
+## feature specification
+##
+[ xml:lang = "en" ]
+grammar {
+ Boolean.datatype = "false" | "true"
+
+ ##
+ ## 'clip-rule' or 'fill-rule' property/attribute value
+ ##
+ ClipFillRule.datatype = "nonzero" | "evenodd" | "inherit"
+
+ ##
+ ## media type, as per [RFC2045]
+ ##
+ ContentType.datatype = xsd:string
+
+ ##
+ ## a <coordinate>
+ ##
+ Coordinate.datatype = xsd:string
+
+ ##
+ ## a list of <coordinate>s
+ ##
+ Coordinates.datatype = xsd:string
+
+ ##
+ ## a <color> value
+ ##
+ Color.datatype = xsd:string
+
+ ##
+ ## a <integer>
+ ##
+ Integer.datatype = xsd:string
+
+ ##
+ ## a language code, as per [RFC3066]
+ ##
+ LanguageCode.datatype = xsd:language
+
+ ##
+ ## comma-separated list of language codes, as per [RFC3066]
+ ##
+ LanguageCodes.datatype = xsd:string
+
+ ##
+ ## a <ength>
+ ##
+ Length.datatype = xsd:string
+
+ ##
+ ## a list of <length>s
+ ##
+ Lengths.datatype = xsd:string
+
+ ##
+ ## a <number>
+ ##
+ Number.datatype = xsd:string
+
+ ##
+ ## a list of <number>s
+ ##
+ Numbers.datatype = xsd:string
+
+ ##
+ ## opacity value (e.g., <number>)
+ ##
+ OpacityValue.datatype = xsd:string
+
+ ##
+ ## a path data specification
+ ##
+ PathData.datatype = w:svg-pathdata
+
+ ##
+ ## 'preserveAspectRatio' attribute specification
+ ##
+ PreserveAspectRatioSpec.datatype =
+ xsd:string {
+ pattern =
+ "([ \t\r\n])*(defer([ \t\r\n])+)?(none|xMinYMin|xMidYMin|xMaxYMin|xMinYMid|xMidYMid|xMaxYMid|xMinYMax|xMidYMax|xMaxYMax)(([ \t\r\n])+(meet|slice))?([ \t\r\n])*"
+ }
+
+ ##
+ ## script expression
+ ##
+ Script.datatype = xsd:string
+
+ ##
+ ## An SVG color value (RGB plus optional ICC)
+ ##
+ SVGColor.datatype = xsd:string
+
+ ##
+ ## arbitrary text string
+ ##
+ Text.datatype = xsd:string
+
+ ##
+ ## list of transforms
+ ##
+ TransformList.datatype = xsd:string
+
+ ##
+ ## a Uniform Resource Identifier, see [URI]
+ ##
+ URI.datatype = xsd:anyURI
+
+ ##
+ ## 'viewBox' attribute specification
+ ##
+ ViewBoxSpec.datatype = xsd:string
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-docevents-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-docevents-attrib.rnc
new file mode 100644
index 0000000..3e106ce
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-docevents-attrib.rnc
@@ -0,0 +1,40 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Document Events Attribute Module
+## file: svg-docevents-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Document Events Attribute
+##
+## onunload, onabort, onerror, onresize, onscroll, onzoom
+##
+## This module defines the DocumentEvents attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.onunload.attrib = attribute onunload { Script.datatype }?
+ SVG.onabort.attrib = attribute onabort { Script.datatype }?
+ SVG.onerror.attrib = attribute onerror { Script.datatype }?
+ SVG.onresize.attrib = attribute onresize { Script.datatype }?
+ SVG.onscroll.attrib = attribute onscroll { Script.datatype }?
+ SVG.onzoom.attrib = attribute onzoom { Script.datatype }?
+ SVG.DocumentEvents.extra.attrib = empty
+ SVG.DocumentEvents.attrib &=
+ SVG.onunload.attrib,
+ SVG.onabort.attrib,
+ SVG.onerror.attrib,
+ SVG.onresize.attrib,
+ SVG.onscroll.attrib,
+ SVG.onzoom.attrib,
+ SVG.DocumentEvents.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc
new file mode 100644
index 0000000..2f075b4
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-extensibility.rnc
@@ -0,0 +1,59 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+default namespace svg = "http://www.w3.org/2000/svg"
+
+a:documentation [
+ "\x{a}" ~
+ " SVG 1.1 Extensibility Module\x{a}" ~
+ " file: svg-extensibility.rng\x{a}" ~
+ "\x{a}" ~
+ " This is SVG, a language for describing two-dimensional graphics in XML.\x{a}" ~
+ " Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.\x{a}" ~
+ "\x{a}" ~
+ " $Id$\x{a}" ~
+ "\x{a}"
+]
+a:documentation [
+ "\x{a}" ~
+ " Extensibility\x{a}" ~
+ "\x{a}" ~
+ " foreignObject\x{a}" ~
+ "\x{a}" ~
+ " This module declares markup to provide support for extensibility.\x{a}" ~
+ " "
+]
+a:documentation [ "\x{a}" ~ " SVG.Extensibility.class\x{a}" ~ " " ]
+SVG.Extensibility.extra.class = notAllowed
+SVG.Extensibility.class |= foreignObject | SVG.Extensibility.extra.class
+a:documentation [
+ "\x{a}" ~
+ " foreignObject: Foreign Object Element\x{a}" ~
+ " "
+]
+SVG.foreignObject.content =
+ notAllowed # bugfix -- hsivonen
+foreignObject =
+ element foreignObject {
+ attlist.foreignObject, SVG.foreignObject.content
+ }
+attlist.foreignObject &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype },
+ attribute height { Length.datatype },
+ attribute transform { TransformList.datatype }?
+
+##
+## any element in foreign namespace
+##
+foreignElement =
+ element * - svg:* {
+ (attribute * - svg:* { text }
+ | text
+ | foreignElement)*
+ }
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-extresources-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-extresources-attrib.rnc
new file mode 100644
index 0000000..e75a53a
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-extresources-attrib.rnc
@@ -0,0 +1,30 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 External Resources Attribute Module
+## file: svg-extresources-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## External Resources Attribute
+##
+## externalResourcesRequired
+##
+## This module defines the External attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.externalResourcesRequired.attrib =
+ attribute externalResourcesRequired { Boolean.datatype }?
+ SVG.External.extra.attrib = empty
+ SVG.External.attrib &=
+ SVG.externalResourcesRequired.attrib, SVG.External.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-filter.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-filter.rnc
new file mode 100644
index 0000000..8f3a4e0
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-filter.rnc
@@ -0,0 +1,218 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Filter Module
+## file: svg-filter.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Filter
+##
+## filter, feBlend, feColorMatrix, feComponentTransfer, feComposite,
+## feConvolveMatrix, feDiffuseLighting, feDisplacementMap, feFlood,
+## feGaussianBlur, feImage, feMerge, feMergeNode, feMorphology, feOffset,
+## feSpecularLighting, feTile, feTurbulence, feDistantLight, fePointLight,
+## feSpotLight, feFuncR, feFuncG, feFuncB, feFuncA
+##
+## This module declares markup to provide support for filter effect.
+##
+[ xml:lang = "en" ]
+grammar {
+ include "svg-basic-filter.rnc"
+
+ ##
+ ## extend SVG.FilterPrimitive.class
+ ##
+ SVG.FilterPrimitive.class |=
+ feConvolveMatrix
+ | feDiffuseLighting
+ | feDisplacementMap
+ | feMorphology
+ | feSpecularLighting
+ | feTurbulence
+ a:documentation [
+ "\x{a}" ~
+ " feConvolveMatrix: Filter Effect Convolve Matrix Element\x{a}" ~
+ " "
+ ]
+ SVG.feConvolveMatrix.content = (animate | set)*
+ feConvolveMatrix =
+ element feConvolveMatrix {
+ attlist.feConvolveMatrix, SVG.feConvolveMatrix.content
+ }
+ attlist.feConvolveMatrix &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute order { NumberOptionalNumber.datatype },
+ attribute kernelMatrix { text },
+ attribute divisor { Number.datatype }?,
+ attribute bias { Number.datatype }?,
+ attribute targetX { Integer.datatype }?,
+ attribute targetY { Integer.datatype }?,
+ [ a:defaultValue = "duplicate" ]
+ attribute edgeMode { string "duplicate" | string "wrap" | string "none" }?,
+ attribute kernelUnitLength { NumberOptionalNumber.datatype }?,
+ attribute preserveAlpha { Boolean.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feDiffuseLighting: Filter Effect Diffuse Lighting Element\x{a}" ~
+ " "
+ ]
+ SVG.feDiffuseLighting.content =
+ (feDistantLight | fePointLight | feSpotLight),
+ (animate | set | animateColor)*
+ feDiffuseLighting =
+ element feDiffuseLighting {
+ attlist.feDiffuseLighting, SVG.feDiffuseLighting.content
+ }
+ attlist.feDiffuseLighting &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Color.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute lighting-color { SVGColor.datatype }?,
+ attribute surfaceScale { Number.datatype }?,
+ attribute diffuseConstant { Number.datatype }?,
+ attribute kernelUnitLength { NumberOptionalNumber.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feDisplacementMap: Filter Effect Displacement Map Element\x{a}" ~
+ " "
+ ]
+ SVG.feDisplacementMap.content = (animate | set)*
+ feDisplacementMap =
+ element feDisplacementMap {
+ attlist.feDisplacementMap, SVG.feDisplacementMap.content
+ }
+ attlist.feDisplacementMap &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute in2 { text },
+ attribute scale { Number.datatype }?,
+ [ a:defaultValue = "A" ]
+ attribute xChannelSelector { string "R" | string "G" | string "B" | string "A" }?,
+ [ a:defaultValue = "A" ]
+ attribute yChannelSelector { string "R" | string "G" | string "B" | string "A" }?
+ a:documentation [
+ "\x{a}" ~
+ " feMorphology: Filter Effect Morphology Element\x{a}" ~
+ " "
+ ]
+ SVG.feMorphology.content = (animate | set)*
+ feMorphology =
+ element feMorphology {
+ attlist.feMorphology, SVG.feMorphology.content
+ }
+ attlist.feMorphology &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ [ a:defaultValue = "erode" ]
+ attribute operator { string "erode" | string "dilate" }?,
+ attribute radius { NumberOptionalNumber.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feSpecularLighting: Filter Effect Specular Lighting Element\x{a}" ~
+ " "
+ ]
+ SVG.feSpecularLighting.content =
+ (feDistantLight | fePointLight | feSpotLight),
+ (animate | set | animateColor)*
+ feSpecularLighting =
+ element feSpecularLighting {
+ attlist.feSpecularLighting, SVG.feSpecularLighting.content
+ }
+ attlist.feSpecularLighting &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Color.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitiveWithIn.attrib,
+ attribute lighting-color { SVGColor.datatype }?,
+ attribute surfaceScale { Number.datatype }?,
+ attribute specularConstant { Number.datatype }?,
+ attribute specularExponent { Number.datatype }?,
+ attribute kernelUnitLength { NumberOptionalNumber.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feTurbulence: Filter Effect Turbulence Element\x{a}" ~
+ " "
+ ]
+ SVG.feTurbulence.content = (animate | set)*
+ feTurbulence =
+ element feTurbulence {
+ attlist.feTurbulence, SVG.feTurbulence.content
+ }
+ attlist.feTurbulence &=
+ SVG.Core.attrib,
+ SVG.FilterColor.attrib,
+ SVG.FilterPrimitive.attrib,
+ attribute baseFrequency { NumberOptionalNumber.datatype }?,
+ attribute numOctaves { Integer.datatype }?,
+ attribute seed { Number.datatype }?,
+ [ a:defaultValue = "noStitch" ]
+ attribute stitchTiles { string "stitch" | string "noStitch" }?,
+ [ a:defaultValue = "turbulence" ]
+ attribute type { string "fractalNoise" | string "turbulence" }?
+ a:documentation [
+ "\x{a}" ~
+ " feDistantLight: Filter Effect Distant Light Element\x{a}" ~
+ " "
+ ]
+ SVG.feDistantLight.content = (animate | set)*
+ feDistantLight =
+ element feDistantLight {
+ attlist.feDistantLight, SVG.feDistantLight.content
+ }
+ attlist.feDistantLight &=
+ SVG.Core.attrib,
+ attribute azimuth { Number.datatype }?,
+ attribute elevation { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " fePointLight: Filter Effect Point Light Element\x{a}" ~
+ " "
+ ]
+ SVG.fePointLight.content = (animate | set)*
+ fePointLight =
+ element fePointLight {
+ attlist.fePointLight, SVG.fePointLight.content
+ }
+ attlist.fePointLight &=
+ SVG.Core.attrib,
+ attribute x { Number.datatype }?,
+ attribute y { Number.datatype }?,
+ attribute z { Number.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " feSpotLight: Filter Effect Spot Light Element\x{a}" ~
+ " "
+ ]
+ SVG.feSpotLight.content = (animate | set)*
+ feSpotLight =
+ element feSpotLight {
+ attlist.feSpotLight, SVG.feSpotLight.content
+ }
+ attlist.feSpotLight &=
+ SVG.Core.attrib,
+ attribute x { Number.datatype }?,
+ attribute y { Number.datatype }?,
+ attribute z { Number.datatype }?,
+ attribute pointsAtX { Number.datatype }?,
+ attribute pointsAtY { Number.datatype }?,
+ attribute pointsAtZ { Number.datatype }?,
+ attribute specularExponent { Number.datatype }?,
+ attribute limitingConeAngle { Number.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-font.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-font.rnc
new file mode 100644
index 0000000..a111a67
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-font.rnc
@@ -0,0 +1,111 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Font Module
+## file: svg-font.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Font
+##
+## font, font-face, glyph, missing-glyph, hkern, vkern, font-face-src,
+## font-face-uri, font-face-format, font-face-name, definition-src
+##
+## This module declares markup to provide support for template.
+##
+[ xml:lang = "en" ]
+grammar {
+ include "svg-basic-font.rnc" {
+ SVG.font-face.extra.class &= definition-src?
+ }
+ a:documentation [
+ "\x{a}" ~
+ " font-face: Font Face Element\x{a}" ~
+ " "
+ ]
+ a:documentation [ "\x{a}" ~ " glyph: Glyph Element\x{a}" ~ " " ]
+ SVG.glyph.class |=
+ SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class
+ a:documentation [
+ "\x{a}" ~
+ " missing-glyph: Missing Glyph Element\x{a}" ~
+ " "
+ ]
+ SVG.missing-glyph.class |=
+ SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class
+ a:documentation [
+ "\x{a}" ~
+ " font-face-uri: Font Face URI Element\x{a}" ~
+ " "
+ ]
+ SVG.font-face-uri.content |= font-face-format*
+ a:documentation [
+ "\x{a}" ~
+ " font-face-format: Font Face Format Element\x{a}" ~
+ " "
+ ]
+ SVG.font-face-format.content = empty
+ font-face-format =
+ element font-face-format {
+ attlist.font-face-format, SVG.font-face-format.content
+ }
+ attlist.font-face-format &=
+ SVG.Core.attrib,
+ attribute string { text }?
+ a:documentation [
+ "\x{a}" ~
+ " definition-src: Definition Source Element\x{a}" ~
+ " "
+ ]
+ SVG.definition-src.content = empty
+ definition-src =
+ element definition-src {
+ attlist.definition-src, SVG.definition-src.content
+ }
+ attlist.definition-src &= SVG.Core.attrib, SVG.XLinkRequired.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-gradient.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-gradient.rnc
new file mode 100644
index 0000000..9ef1ea5
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-gradient.rnc
@@ -0,0 +1,107 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Gradient Module
+## file: svg-gradient.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Gradient
+##
+## linearGradient, radialGradient, stop
+##
+## This module declares markup to provide support for gradient fill.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ NumberOrPercentage.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Gradient.attrib\x{a}" ~ " " ]
+ SVG.Gradient.extra.attrib = empty
+ SVG.Gradient.attrib &=
+ attribute stop-color { SVGColor.datatype }?,
+ attribute stop-opacity { OpacityValue.datatype }?,
+ SVG.Gradient.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Gradient.class\x{a}" ~ " " ]
+ SVG.Gradient.extra.class = notAllowed
+ SVG.Gradient.class |=
+ linearGradient | radialGradient | SVG.Gradient.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " linearGradient: Linear Gradient Element\x{a}" ~
+ " "
+ ]
+ SVG.linearGradient.content =
+ SVG.Description.class*,
+ (stop | animate | set | animateTransform)*
+ linearGradient =
+ element linearGradient {
+ attlist.linearGradient, SVG.linearGradient.content
+ }
+ attlist.linearGradient &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Color.attrib,
+ SVG.Gradient.attrib,
+ SVG.XLink.attrib,
+ SVG.External.attrib,
+ attribute x1 { Coordinate.datatype }?,
+ attribute y1 { Coordinate.datatype }?,
+ attribute x2 { Coordinate.datatype }?,
+ attribute y2 { Coordinate.datatype }?,
+ attribute gradientUnits {
+ string "userSpaceOnUse" | string "objectBoundingBox"
+ }?,
+ attribute gradientTransform { TransformList.datatype }?,
+ attribute spreadMethod { string "pad" | string "reflect" | string "repeat" }?
+ a:documentation [
+ "\x{a}" ~
+ " radialGradient: Radial Gradient Element\x{a}" ~
+ " "
+ ]
+ SVG.radialGradient.content =
+ SVG.Description.class*,
+ (stop | animate | set | animateTransform)*
+ radialGradient =
+ element radialGradient {
+ attlist.radialGradient, SVG.radialGradient.content
+ }
+ attlist.radialGradient &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Color.attrib,
+ SVG.Gradient.attrib,
+ SVG.XLink.attrib,
+ SVG.External.attrib,
+ attribute cx { Coordinate.datatype }?,
+ attribute cy { Coordinate.datatype }?,
+ attribute r { Length.datatype }?,
+ attribute fx { Coordinate.datatype }?,
+ attribute fy { Coordinate.datatype }?,
+ attribute gradientUnits {
+ string "userSpaceOnUse" | string "objectBoundingBox"
+ }?,
+ attribute gradientTransform { TransformList.datatype }?,
+ attribute spreadMethod { string "pad" | string "reflect" | string "repeat" }?
+ a:documentation [ "\x{a}" ~ " stop: Stop Element\x{a}" ~ " " ]
+ SVG.stop.content = (animate | set | animateColor)*
+ stop = element stop { attlist.stop, SVG.stop.content }
+ attlist.stop &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Color.attrib,
+ SVG.Gradient.attrib,
+ attribute offset { NumberOrPercentage.datatype }
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-graphevents-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-graphevents-attrib.rnc
new file mode 100644
index 0000000..1bd0f12
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-graphevents-attrib.rnc
@@ -0,0 +1,49 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Graphical Element Events Attribute Module
+## file: svg-graphevents-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Graphical Element Events Attribute
+##
+## onfocusin, onfocusout, onactivate, onclick, onmousedown, onmouseup,
+## onmouseover, onmousemove, onmouseout, onload
+##
+## This module defines the GraphicalEvents attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.onfocusin.attrib = attribute onfocusin { Script.datatype }?
+ SVG.onfocusout.attrib = attribute onfocusout { Script.datatype }?
+ SVG.onactivate.attrib = attribute onactivate { Script.datatype }?
+ SVG.onclick.attrib = attribute onclick { Script.datatype }?
+ SVG.onmousedown.attrib = attribute onmousedown { Script.datatype }?
+ SVG.onmouseup.attrib = attribute onmouseup { Script.datatype }?
+ SVG.onmouseover.attrib = attribute onmouseover { Script.datatype }?
+ SVG.onmousemove.attrib = attribute onmousemove { Script.datatype }?
+ SVG.onmouseout.attrib = attribute onmouseout { Script.datatype }?
+ SVG.onload.attrib &= attribute onload { Script.datatype }?
+ SVG.GraphicalEvents.extra.attrib = empty
+ SVG.GraphicalEvents.attrib &=
+ SVG.onfocusin.attrib,
+ SVG.onfocusout.attrib,
+ SVG.onactivate.attrib,
+ SVG.onclick.attrib,
+ SVG.onmousedown.attrib,
+ SVG.onmouseup.attrib,
+ SVG.onmouseover.attrib,
+ SVG.onmousemove.attrib,
+ SVG.onmouseout.attrib,
+ SVG.onload.attrib,
+ SVG.GraphicalEvents.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-graphics-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-graphics-attrib.rnc
new file mode 100644
index 0000000..4f8eca4
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-graphics-attrib.rnc
@@ -0,0 +1,66 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+
+
+##
+## SVG 1.1 Graphics Attribute Module
+## file: svg-graphics-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Graphics Attribute
+##
+## display, image-rendering, pointer-events, shape-rendering,
+## text-rendering, visibility
+##
+## This module defines the Graphics attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ include "svg-basic-graphics-attrib.rnc" inherit = svg
+ SVG.image-rendering.attrib =
+ attribute image-rendering {
+ string "auto" | string "optimizeSpeed" | string "optimizeQuality" | string "inherit"
+ }?
+ SVG.pointer-events.attrib =
+ attribute pointer-events {
+ string "visiblePainted"
+ | string "visibleFill"
+ | string "visibleStroke"
+ | string "visible"
+ | string "painted"
+ | string "fill"
+ | string "stroke"
+ | string "all"
+ | string "none"
+ | string "inherit"
+ }?
+ SVG.shape-rendering.attrib =
+ attribute shape-rendering {
+ string "auto"
+ | string "optimizeSpeed"
+ | string "crispEdges"
+ | string "geometricPrecision"
+ | string "inherit"
+ }?
+ SVG.text-rendering.attrib =
+ attribute text-rendering {
+ string "auto"
+ | string "optimizeSpeed"
+ | string "optimizeLegibility"
+ | string "geometricPrecision"
+ | string "inherit"
+ }?
+ SVG.Graphics.attrib &=
+ SVG.image-rendering.attrib,
+ SVG.pointer-events.attrib,
+ SVG.shape-rendering.attrib,
+ SVG.text-rendering.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-hyperlink.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-hyperlink.rnc
new file mode 100644
index 0000000..e277d16
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-hyperlink.rnc
@@ -0,0 +1,68 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Hyperlinking Module
+## file: svg-hyperlink.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Hyperlinking
+##
+## a
+##
+## This module declares markup to provide support for hyper linking.
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## link to this target
+ ##
+ LinkTarget.datatype = xsd:NMTOKEN
+ a:documentation [ "\x{a}" ~ " SVG.Hyperlink.class\x{a}" ~ " " ]
+ SVG.Hyperlink.extra.class = notAllowed
+ SVG.Hyperlink.class |= a | SVG.Hyperlink.extra.class
+ a:documentation [ "\x{a}" ~ " a: Anchor Element\x{a}" ~ " " ]
+ SVG.a.content =
+ (text
+ | SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ a = element a { attlist.a, SVG.a.content }
+ attlist.a &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.XLinkReplace.attrib,
+ SVG.External.attrib,
+ attribute transform { TransformList.datatype }?,
+ attribute target { LinkTarget.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-image.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-image.rnc
new file mode 100644
index 0000000..0d33d73
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-image.rnc
@@ -0,0 +1,60 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Image Module
+## file: svg-image.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Image
+##
+## image
+##
+## This module declares markup to provide support for image.
+##
+
+##
+## SVG.Image.class
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.Image.extra.class = notAllowed
+ SVG.Image.class |= image | SVG.Image.extra.class
+ a:documentation [ "\x{a}" ~ " image: Image Element\x{a}" ~ " " ]
+ SVG.image.content = SVG.Description.class*, SVG.Animation.class*
+ image = element image { attlist.image, SVG.image.content }
+ attlist.image &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Viewport.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Profile.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.XLinkEmbed.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype },
+ attribute height { Length.datatype },
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?,
+ attribute transform { TransformList.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-marker.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-marker.rnc
new file mode 100644
index 0000000..b344876
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-marker.rnc
@@ -0,0 +1,84 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Marker Module
+## file: svg-marker.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Marker
+##
+## marker
+##
+## This module declares markup to provide support for marker.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ MarkerValue.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Marker.attrib\x{a}" ~ " " ]
+ SVG.Marker.extra.attrib = empty
+ SVG.Marker.attrib &=
+ attribute marker-start { MarkerValue.datatype }?,
+ attribute marker-mid { MarkerValue.datatype }?,
+ attribute marker-end { MarkerValue.datatype }?,
+ SVG.Marker.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Marker.class\x{a}" ~ " " ]
+ SVG.Marker.extra.class = notAllowed
+ SVG.Marker.class |= marker | SVG.Marker.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " marker: Marker Element\x{a}" ~
+ " "
+ ]
+ SVG.marker.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ marker = element marker { attlist.marker, SVG.marker.content }
+ attlist.marker &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.External.attrib,
+ attribute refX { Coordinate.datatype }?,
+ attribute refY { Coordinate.datatype }?,
+ attribute markerUnits { string "strokeWidth" | string "userSpaceOnUse" }?,
+ attribute markerWidth { Length.datatype }?,
+ attribute markerHeight { Length.datatype }?,
+ attribute orient { text }?,
+ attribute viewBox { ViewBoxSpec.datatype }?,
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-mask.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-mask.rnc
new file mode 100644
index 0000000..4f17746
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-mask.rnc
@@ -0,0 +1,76 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Mask Module
+## file: svg-mask.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Mask
+##
+## mask
+##
+## This module declares markup to provide support for masking.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ MaskValue.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Mask.attrib\x{a}" ~ " " ]
+ SVG.Mask.extra.attrib = empty
+ SVG.Mask.attrib &=
+ attribute mask { MaskValue.datatype }?,
+ SVG.Mask.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Mask.class\x{a}" ~ " " ]
+ SVG.Mask.extra.class = notAllowed
+ SVG.Mask.class |= mask | SVG.Mask.extra.class
+ a:documentation [ "\x{a}" ~ " mask: Mask Element\x{a}" ~ " " ]
+ SVG.mask.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ mask = element mask { attlist.mask, SVG.mask.content }
+ attlist.mask &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype }?,
+ attribute height { Length.datatype }?,
+ attribute maskUnits { "userSpaceOnUse" | "objectBoundingBox" }?,
+ attribute maskContentUnits {
+ "userSpaceOnUse" | "objectBoundingBox"
+ }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-opacity-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-opacity-attrib.rnc
new file mode 100644
index 0000000..d783c60
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-opacity-attrib.rnc
@@ -0,0 +1,36 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Paint Opacity Attribute Module
+## file: svg-opacity-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Paint Opacity Attribute
+##
+## opacity, fill-opacity, stroke-opacity
+##
+## This module defines the Opacity attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.opacity.attrib = attribute opacity { OpacityValue.datatype }?
+ SVG.fill-opacity.attrib =
+ attribute fill-opacity { OpacityValue.datatype }?
+ SVG.stroke-opacity.attrib =
+ attribute stroke-opacity { OpacityValue.datatype }?
+ SVG.Opacity.extra.attrib = empty
+ SVG.Opacity.attrib &=
+ SVG.opacity.attrib,
+ SVG.fill-opacity.attrib,
+ SVG.stroke-opacity.attrib,
+ SVG.Opacity.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-paint-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-paint-attrib.rnc
new file mode 100644
index 0000000..4e9635d
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-paint-attrib.rnc
@@ -0,0 +1,100 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Paint Attribute Module
+## file: svg-paint-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Paint Attribute
+##
+## fill, fill-rule, stroke, stroke-dasharray, stroke-dashoffset,
+## stroke-linecap, stroke-linejoin, stroke-miterlimit, stroke-width, color,
+## color-interpolation, color-rendering
+##
+## This module defines the Paint and Color attribute sets.
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## a 'fill' or 'stroke' property/attribute value: <paint>
+ ##
+ Paint.datatype = xsd:string
+
+ ##
+ ## 'stroke-dasharray' property/attribute value
+ ## (e.g., 'none', list of <number>s)
+ ##
+ StrokeDashArrayValue.datatype = xsd:string
+
+ ##
+ ## 'stroke-dashoffset' property/attribute value (e.g., 'none', <legnth>)
+ ##
+ StrokeDashOffsetValue.datatype = xsd:string
+
+ ##
+ ## 'stroke-miterlimit' property/attribute value (e.g., <number>)
+ ##
+ StrokeMiterLimitValue.datatype = xsd:string
+
+ ##
+ ## 'stroke-width' property/attribute value (e.g., <length>)
+ ##
+ StrokeWidthValue.datatype = xsd:string
+ SVG.fill.attrib = attribute fill { Paint.datatype }?
+ SVG.fill-rule.attrib =
+ attribute fill-rule { ClipFillRule.datatype }?
+ SVG.stroke.attrib = attribute stroke { Paint.datatype }?
+ SVG.stroke-dasharray.attrib =
+ attribute stroke-dasharray { StrokeDashArrayValue.datatype }?
+ SVG.stroke-dashoffset.attrib =
+ attribute stroke-dashoffset { StrokeDashOffsetValue.datatype }?
+ SVG.stroke-linecap.attrib =
+ attribute stroke-linecap {
+ "butt" | "round" | "square" | "inherit"
+ }?
+ SVG.stroke-linejoin.attrib =
+ attribute stroke-linejoin {
+ "miter" | "round" | "bevel" | "inherit"
+ }?
+ SVG.stroke-miterlimit.attrib =
+ attribute stroke-miterlimit { StrokeMiterLimitValue.datatype }?
+ SVG.stroke-width.attrib =
+ attribute stroke-width { StrokeWidthValue.datatype }?
+ SVG.Paint.extra.attrib = empty
+ SVG.Paint.attrib &=
+ SVG.fill.attrib,
+ SVG.fill-rule.attrib,
+ SVG.stroke.attrib,
+ SVG.stroke-dasharray.attrib,
+ SVG.stroke-dashoffset.attrib,
+ SVG.stroke-linecap.attrib,
+ SVG.stroke-linejoin.attrib,
+ SVG.stroke-miterlimit.attrib,
+ SVG.stroke-width.attrib,
+ SVG.Paint.extra.attrib
+ SVG.color.attrib = attribute color { Color.datatype }?
+ SVG.color-interpolation.attrib =
+ attribute color-interpolation {
+ "auto" | "sRGB" | "linearRGB" | "inherit"
+ }?
+ SVG.color-rendering.attrib =
+ attribute color-rendering {
+ "auto" | "optimizeSpeed" | "optimizeQuality" | "inherit"
+ }?
+ SVG.Color.extra.attrib = empty
+ SVG.Color.attrib &=
+ SVG.color.attrib,
+ SVG.color-interpolation.attrib,
+ SVG.color-rendering.attrib,
+ SVG.Color.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-pattern.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-pattern.rnc
new file mode 100644
index 0000000..2600829
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-pattern.rnc
@@ -0,0 +1,82 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Pattern Module
+## file: svg-pattern.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Pattern
+##
+## pattern
+##
+## This module declares markup to provide support for pattern fill.
+##
+
+##
+## SVG.Pattern.class
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.Pattern.extra.class = notAllowed
+ SVG.Pattern.class |= pattern | SVG.Pattern.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " pattern: Pattern Element\x{a}" ~
+ " "
+ ]
+ SVG.pattern.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ pattern = element pattern { attlist.pattern, SVG.pattern.content }
+ attlist.pattern &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.XLink.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype }?,
+ attribute height { Length.datatype }?,
+ attribute patternUnits {
+ string "userSpaceOnUse" | string "objectBoundingBox"
+ }?,
+ attribute patternContentUnits {
+ string "userSpaceOnUse" | string "objectBoundingBox"
+ }?,
+ attribute patternTransform { TransformList.datatype }?,
+ attribute viewBox { ViewBoxSpec.datatype }?,
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-profile.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-profile.rnc
new file mode 100644
index 0000000..406ce6b
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-profile.rnc
@@ -0,0 +1,60 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Color Profile Module
+## file: svg-profile.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Color Profile
+##
+## color-profile
+##
+## This module declares markup to provide support for color profile.
+##
+
+##
+## SVG.Profile.attrib
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.Profile.extra.attrib = empty
+ SVG.Profile.attrib &=
+ attribute color-profile { text }?,
+ SVG.Profile.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Profile.class\x{a}" ~ " " ]
+ SVG.Profile.extra.class = notAllowed
+ SVG.Profile.class |= color-profile | SVG.Profile.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " color-profile: Color Profile Element\x{a}" ~
+ " "
+ ]
+ SVG.color-profile.content = SVG.Description.class*
+ color-profile =
+ element color-profile {
+ attlist.color-profile, SVG.color-profile.content
+ }
+ attlist.color-profile &=
+ SVG.Core.attrib,
+ SVG.XLink.attrib,
+ attribute local { text }?,
+ attribute name { text },
+ [ a:defaultValue = "auto" ]
+ attribute rendering-intent {
+ string "auto"
+ | string "perceptual"
+ | string "relative-colorimetric"
+ | string "saturation"
+ | string "absolute-colorimetric"
+ }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-qname.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-qname.rnc
new file mode 100644
index 0000000..e8587b5
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-qname.rnc
@@ -0,0 +1,119 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+# .......................................................................
+
+# SVG 1.1 Qualified Name Module .........................................
+
+# file: svg-qname.mod
+#
+# This is SVG, a language for describing two-dimensional graphics in XML.
+# Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+#
+# Modifications Copyright 2007 Mozilla Foundation
+#
+# Revision: $Id$
+#
+# This DTD module is identified by the PUBLIC and SYSTEM identifiers:
+#
+# PUBLIC "-//W3C//ENTITIES SVG 1.1 Qualified Name//EN"
+# SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg-qname.mod"
+#
+# .......................................................................
+
+# Qualified Name
+#
+# This module is contained in two parts, labeled Section 'A' and 'B':
+#
+# Section A declares parameter entities to support namespace-
+# qualified names, namespace declarations, and name prefixing
+# for SVG and extensions.
+#
+# Section B declares parameter entities used to provide
+# namespace-qualified names for all SVG element types:
+
+# Section A: SVG XML Namespace Framework ::::::::::::::::::::::
+
+# 1. Declare a %SVG.prefixed; conditional section keyword, used
+# to activate namespace prefixing. The default value should
+# inherit '%NS.prefixed;' from the DTD driver, so that unless
+# overridden, the default behaviour follows the overall DTD
+# prefixing scheme.
+
+# 2. Declare a parameter entity (eg., %SVG.xmlns;) containing
+# the URI reference used to identify the SVG namespace:
+
+# 3. Declare parameter entities (eg., %SVG.prefix;) containing
+# the default namespace prefix string(s) to use when prefixing
+# is enabled. This may be overridden in the DTD driver or the
+# internal subset of an document instance. If no default prefix
+# is desired, this may be declared as an empty string.
+
+# 4. Declare parameter entities (eg., %SVG.pfx;) containing the
+# colonized prefix(es) (eg., '%SVG.prefix;:') used when
+# prefixing is active, an empty string when it is not.
+
+# 5. The parameter entity %SVG.xmlns.extra.attrib; may be
+# redeclared to contain any non-SVG namespace declaration
+# attributes for namespaces embedded in SVG. The default
+# is an empty string.
+
+# Declare a parameter entity XLINK.xmlns.attrib containing
+# the XML Namespace declarations for XLink.
+XLINK.xmlns.attrib = empty
+# Declare a parameter entity %NS.decl.attrib; containing
+# all XML Namespace declarations used in the DTD, plus the
+# xmlns declaration for SVG, its form dependent on whether
+# prefixing is active.
+
+# Declare a parameter entity %SVG.xmlns.attrib; containing
+# all XML namespace declaration attributes used by SVG,
+# including a default xmlns attribute when prefixing is
+# inactive.
+SVG.xmlns.attrib = empty, XLINK.xmlns.attrib
+# Section B: SVG Qualified Names ::::::::::::::::::::::::::::::
+
+# 6. This section declares parameter entities used to provide
+# namespace-qualified names for all SVG element types.
+
+# module: svg-structure.mod .........................
+
+# module: svg-conditional.mod .......................
+
+# module: svg-image.mod .............................
+
+# module: svg-style.mod .............................
+
+# module: svg-shape.mod .............................
+
+# module: svg-text.mod ..............................
+
+# module: svg-marker.mod ............................
+
+# module: svg-profile.mod ...........................
+
+# module: svg-gradient.mod ..........................
+
+# module: svg-pattern.mod ...........................
+
+# module: svg-clip.mod ..............................
+
+# module: svg-mask.mod ..............................
+
+# module: svg-filter.mod ............................
+
+# module: svg-cursor.mod ............................
+
+# module: svg-hyperlink.mod .........................
+
+# module: svg-view.mod ..............................
+
+# module: svg-script.mod ............................
+
+# module: svg-animation.mod .........................
+
+# module: svg-font.mod ..............................
+
+# module: svg-extensibility.mod .....................
+
+# end of svg-qname.mod
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-script.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-script.rnc
new file mode 100644
index 0000000..ff93aca
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-script.rnc
@@ -0,0 +1,44 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Scripting Module
+## file: svg-script.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Scripting
+##
+## script
+##
+## This module declares markup to provide support for scripting.
+##
+
+##
+## SVG.Script.class
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.Script.extra.class = notAllowed
+ SVG.Script.class |= script | SVG.Script.extra.class
+ a:documentation [
+ "\x{a}" ~
+ " script: Script Element\x{a}" ~
+ " "
+ ]
+ SVG.script.content = text
+ script = element script { attlist.script, SVG.script.content }
+ attlist.script &=
+ SVG.Core.attrib,
+ SVG.XLink.attrib,
+ SVG.External.attrib,
+ attribute type { ContentType.datatype }
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-shape.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-shape.rnc
new file mode 100644
index 0000000..f89cab7
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-shape.rnc
@@ -0,0 +1,214 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Shape Module
+## file: svg-shape.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Shape
+##
+## path, rect, circle, line, ellipse, polyline, polygon
+##
+## This module declares markup to provide support for graphical shapes.
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## a list of points
+ ##
+ Points.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Shape.class\x{a}" ~ " " ]
+ SVG.Shape.extra.class = notAllowed
+ SVG.Shape.class |=
+ path
+ | rect
+ | circle
+ | line
+ | ellipse
+ | polyline
+ | polygon
+ | SVG.Shape.extra.class
+ a:documentation [ "\x{a}" ~ " path: Path Element\x{a}" ~ " " ]
+ SVG.path.content = SVG.Description.class*, SVG.Animation.class*
+ path = element path { attlist.path, SVG.path.content }
+ attlist.path &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Marker.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute d { PathData.datatype },
+ attribute pathLength { Number.datatype }?,
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " rect: Rectangle Element\x{a}" ~
+ " "
+ ]
+ SVG.rect.content = SVG.Description.class*, SVG.Animation.class*
+ rect = element rect { attlist.rect, SVG.rect.content }
+ attlist.rect &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinate.datatype }?,
+ attribute y { Coordinate.datatype }?,
+ attribute width { Length.datatype },
+ attribute height { Length.datatype },
+ attribute rx { Length.datatype }?,
+ attribute ry { Length.datatype }?,
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " circle: Circle Element\x{a}" ~
+ " "
+ ]
+ SVG.circle.content = SVG.Description.class*, SVG.Animation.class*
+ circle = element circle { attlist.circle, SVG.circle.content }
+ attlist.circle &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute cx { Coordinate.datatype }?,
+ attribute cy { Coordinate.datatype }?,
+ attribute r { Length.datatype },
+ attribute transform { TransformList.datatype }?
+ a:documentation [ "\x{a}" ~ " line: Line Element\x{a}" ~ " " ]
+ SVG.line.content = SVG.Description.class*, SVG.Animation.class*
+ line = element line { attlist.line, SVG.line.content }
+ attlist.line &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Marker.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute x1 { Coordinate.datatype }?,
+ attribute y1 { Coordinate.datatype }?,
+ attribute x2 { Coordinate.datatype }?,
+ attribute y2 { Coordinate.datatype }?,
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " ellipse: Ellipse Element\x{a}" ~
+ " "
+ ]
+ SVG.ellipse.content = SVG.Description.class*, SVG.Animation.class*
+ ellipse = element ellipse { attlist.ellipse, SVG.ellipse.content }
+ attlist.ellipse &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute cx { Coordinate.datatype }?,
+ attribute cy { Coordinate.datatype }?,
+ attribute rx { Length.datatype },
+ attribute ry { Length.datatype },
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " polyline: Polyline Element\x{a}" ~
+ " "
+ ]
+ SVG.polyline.content = SVG.Description.class*, SVG.Animation.class*
+ polyline =
+ element polyline { attlist.polyline, SVG.polyline.content }
+ attlist.polyline &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Marker.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute points { Points.datatype },
+ attribute transform { TransformList.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " polygon: Polygon Element\x{a}" ~
+ " "
+ ]
+ SVG.polygon.content = SVG.Description.class*, SVG.Animation.class*
+ polygon = element polygon { attlist.polygon, SVG.polygon.content }
+ attlist.polygon &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Marker.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute points { Points.datatype },
+ attribute transform { TransformList.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-structure.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-structure.rnc
new file mode 100644
index 0000000..bf2db81
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-structure.rnc
@@ -0,0 +1,70 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Structure Module
+## file: svg-structure.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Structure
+##
+## svg, g, defs, desc, title, metadata, symbol, use
+##
+## This module declares the major structural elements and their attributes.
+##
+[ xml:lang = "en" ]
+grammar {
+ include "svg-basic-structure.rnc"
+
+ ##
+ ## extend SVG.Structure.class
+ ##
+ SVG.Structure.class |= symbol
+ a:documentation [
+ "\x{a}" ~
+ " symbol: Symbol Element\x{a}" ~
+ " "
+ ]
+ SVG.symbol.content =
+ (SVG.Description.class
+ | SVG.Animation.class
+ | SVG.Structure.class
+ | SVG.Conditional.class
+ | SVG.Image.class
+ | SVG.Style.class
+ | SVG.Shape.class
+ | SVG.Text.class
+ | SVG.Marker.class
+ | SVG.Profile.class
+ | SVG.Gradient.class
+ | SVG.Pattern.class
+ | SVG.Clip.class
+ | SVG.Mask.class
+ | SVG.Filter.class
+ | SVG.Cursor.class
+ | SVG.Hyperlink.class
+ | SVG.View.class
+ | SVG.Script.class
+ | SVG.Font.class)*
+ symbol = element symbol { attlist.symbol, SVG.symbol.content }
+ attlist.symbol &=
+ SVG.Core.attrib,
+ SVG.Style.attrib,
+ SVG.Presentation.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.External.attrib,
+ attribute viewBox { ViewBoxSpec.datatype }?,
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-style.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-style.rnc
new file mode 100644
index 0000000..a365454
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-style.rnc
@@ -0,0 +1,59 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Style Module
+## file: svg-style.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Style
+##
+## style
+##
+## This module declares markup to provide support for stylesheet.
+##
+
+##
+## Datatypes
+##
+[ xml:lang = "en" ]
+grammar {
+ ClassList.datatype = xsd:NMTOKENS
+ StyleSheet.datatype = xsd:string
+
+ ##
+ ## comma-separated list of media descriptors.
+ ##
+ MediaDesc.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Style.attrib\x{a}" ~ " " ]
+ SVG.Style.extra.attrib = empty
+ SVG.Style.attrib &=
+ attribute style { StyleSheet.datatype }?,
+ attribute class { ClassList.datatype }?,
+ SVG.Style.extra.attrib
+ a:documentation [ "\x{a}" ~ " SVG.Style.class\x{a}" ~ " " ]
+ SVG.Style.extra.class = notAllowed
+ SVG.Style.class |= style | SVG.Style.extra.class
+ a:documentation [ "\x{a}" ~ " style: Style Element\x{a}" ~ " " ]
+ SVG.style.content = text
+ style = element style { attlist.style, SVG.style.content }
+ attlist.style &=
+ [ a:defaultValue = "preserve" ]
+ attribute xml:space { string "preserve" }?,
+ SVG.id.attrib,
+ SVG.base.attrib,
+ SVG.lang.attrib,
+ SVG.Core.extra.attrib,
+ attribute type { ContentType.datatype },
+ attribute media { MediaDesc.datatype }?,
+ attribute title { Text.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-text.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-text.rnc
new file mode 100644
index 0000000..7abfb08
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-text.rnc
@@ -0,0 +1,284 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Text Module
+## file: svg-text.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Text
+##
+## text, tspan, tref, textPath, altGlyph, altGlyphDef, altGlyphItem,
+## glyphRef
+##
+## This module declares markup to provide support for alternate glyph.
+##
+[ xml:lang = "en" ]
+grammar {
+ include "svg-basic-text.rnc"
+ a:documentation [ "\x{a}" ~ " Datatypes\x{a}" ~ " " ]
+ BaselineShiftValue.datatype = xsd:string
+ FontSizeAdjustValue.datatype = xsd:string
+ GlyphOrientationHorizontalValue.datatype = xsd:string
+ GlyphOrientationVerticalValue.datatype = xsd:string
+ KerningValue.datatype = xsd:string
+ SpacingValue.datatype = xsd:string
+ TextDecorationValue.datatype = xsd:string
+ a:documentation [ "\x{a}" ~ " SVG.Text.attrib\x{a}" ~ " " ]
+ SVG.Text.extra.attrib = empty
+ SVG.Text.attrib &=
+ attribute writing-mode {
+ string "lr-tb" | string "rl-tb" | string "tb-rl" | string "lr" | string "rl" | string "tb" | "inherit"
+ }?,
+ SVG.Text.extra.attrib
+ a:documentation [
+ "\x{a}" ~
+ " SVG.TextContent.attrib\x{a}" ~
+ " "
+ ]
+ SVG.TextContent.extra.attrib = empty
+ SVG.TextContent.attrib &=
+ attribute alignment-baseline {
+ string "auto"
+ | string "baseline"
+ | string "before-edge"
+ | string "text-before-edge"
+ | string "middle"
+ | string "central"
+ | string "after-edge"
+ | string "text-after-edge"
+ | string "ideographic"
+ | string "alphabetic"
+ | string "hanging"
+ | string "mathematical"
+ | string "inherit"
+ }?,
+ attribute baseline-shift { BaselineShiftValue.datatype }?,
+ attribute direction { string "ltr" | string "rtl" | string "inherit" }?,
+ attribute dominant-baseline {
+ string "auto"
+ | string "use-script"
+ | string "no-change"
+ | string "reset-size"
+ | string "ideographic"
+ | string "alphabetic"
+ | string "hanging"
+ | string "mathematical"
+ | string "central"
+ | string "middle"
+ | string "text-after-edge"
+ | string "text-before-edge"
+ | string "inherit"
+ }?,
+ attribute glyph-orientation-horizontal {
+ GlyphOrientationHorizontalValue.datatype
+ }?,
+ attribute glyph-orientation-vertical {
+ GlyphOrientationVerticalValue.datatype
+ }?,
+ attribute kerning { KerningValue.datatype }?,
+ attribute letter-spacing { SpacingValue.datatype }?,
+ attribute text-anchor {
+ string "start" | string "middle" | string "end" | string "inherit"
+ }?,
+ attribute text-decoration { TextDecorationValue.datatype }?,
+ attribute unicode-bidi {
+ string "normal" | string "embed" | string "bidi-override" | string "inherit"
+ }?,
+ attribute word-spacing { SpacingValue.datatype }?,
+ SVG.TextContent.extra.attrib
+ SVG.Font.attrib &=
+ attribute font-size-adjust { FontSizeAdjustValue.datatype }?,
+ attribute font-stretch {
+ string "normal"
+ | string "wider"
+ | string "narrower"
+ | string "ultra-condensed"
+ | string "extra-condensed"
+ | string "condensed"
+ | string "semi-condensed"
+ | string "semi-expanded"
+ | string "expanded"
+ | string "extra-expanded"
+ | string "ultra-expanded"
+ | string "inherit"
+ }?,
+ attribute font-variant { string "normal" | string "small-caps" | string "inherit" }?
+
+ ##
+ ## extend SVG.Text.class
+ ##
+ SVG.Text.class |= altGlyphDef
+
+ ##
+ ## extend SVG.TextContent.class
+ ##
+ SVG.TextContent.class |= tspan | tref | textPath
+ a:documentation [ "\x{a}" ~ " text: Text Element\x{a}" ~ " " ]
+ SVG.text.class |= SVG.TextContent.class
+ attlist.text &=
+ SVG.Text.attrib,
+ SVG.TextContent.attrib,
+ attribute dx { Lengths.datatype }?,
+ attribute dy { Lengths.datatype }?,
+ attribute textLength { Length.datatype }?,
+ attribute lengthAdjust { string "spacing" | string "spacingAndGlyphs" }?
+ a:documentation [
+ "\x{a}" ~
+ " tspan: Text Span Element\x{a}" ~
+ " "
+ ]
+ SVG.tspan.content =
+ (text
+ | tspan
+ | tref
+ | altGlyph
+ | animate
+ | set
+ | animateColor
+ | SVG.Description.class
+ | SVG.Hyperlink.class)*
+ tspan = element tspan { attlist.tspan, SVG.tspan.content }
+ attlist.tspan &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.TextContent.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinates.datatype }?,
+ attribute y { Coordinates.datatype }?,
+ attribute dx { Lengths.datatype }?,
+ attribute dy { Lengths.datatype }?,
+ attribute rotate { Numbers.datatype }?,
+ attribute textLength { Length.datatype }?,
+ attribute lengthAdjust { string "spacing" | string "spacingAndGlyphs" }?
+ a:documentation [
+ "\x{a}" ~
+ " tref: Text Reference Element\x{a}" ~
+ " "
+ ]
+ SVG.tref.content =
+ (animate | set | animateColor | SVG.Description.class)*
+ tref = element tref { attlist.tref, SVG.tref.content }
+ attlist.tref &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.TextContent.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.XLinkRequired.attrib,
+ SVG.External.attrib,
+ attribute x { Coordinates.datatype }?,
+ attribute y { Coordinates.datatype }?,
+ attribute dx { Lengths.datatype }?,
+ attribute dy { Lengths.datatype }?,
+ attribute rotate { Numbers.datatype }?,
+ attribute textLength { Length.datatype }?,
+ attribute lengthAdjust { string "spacing" | string "spacingAndGlyphs" }?
+ a:documentation [
+ "\x{a}" ~
+ " textPath: Text Path Element\x{a}" ~
+ " "
+ ]
+ SVG.textPath.content =
+ (text
+ | tspan
+ | tref
+ | altGlyph
+ | animate
+ | set
+ | animateColor
+ | SVG.Description.class
+ | SVG.Hyperlink.class)*
+ textPath =
+ element textPath { attlist.textPath, SVG.textPath.content }
+ attlist.textPath &=
+ SVG.Core.attrib,
+ SVG.Conditional.attrib,
+ SVG.Style.attrib,
+ SVG.TextContent.attrib,
+ SVG.Font.attrib,
+ SVG.Paint.attrib,
+ SVG.Color.attrib,
+ SVG.Opacity.attrib,
+ SVG.Graphics.attrib,
+ SVG.Clip.attrib,
+ SVG.Mask.attrib,
+ SVG.Filter.attrib,
+ SVG.GraphicalEvents.attrib,
+ SVG.Cursor.attrib,
+ SVG.XLinkRequired.attrib,
+ SVG.External.attrib,
+ attribute startOffset { Length.datatype }?,
+ attribute textLength { Length.datatype }?,
+ attribute lengthAdjust { string "spacing" | string "spacingAndGlyphs" }?,
+ attribute method { string "align" | string "stretch" }?,
+ attribute spacing { string "auto" | string "exact" }?
+ a:documentation [
+ "\x{a}" ~
+ " altGlyph: Alternate Glyph Element\x{a}" ~
+ " "
+ ]
+ attlist.altGlyph &=
+ SVG.TextContent.attrib,
+ attribute x { Coordinates.datatype }?,
+ attribute y { Coordinates.datatype }?,
+ attribute dx { Lengths.datatype }?,
+ attribute dy { Lengths.datatype }?,
+ attribute rotate { Numbers.datatype }?
+ a:documentation [
+ "\x{a}" ~
+ " altGlyphDef: Alternate Glyph Definition Element\x{a}" ~
+ " "
+ ]
+ SVG.altGlyphDef.content |= altGlyphItem+
+ a:documentation [
+ "\x{a}" ~
+ " altGlyphItem: Alternate Glyph Item Element\x{a}" ~
+ " "
+ ]
+ SVG.altGlyphItem.content = glyphRef+
+ altGlyphItem =
+ element altGlyphItem {
+ attlist.altGlyphItem, SVG.altGlyphItem.content
+ }
+ attlist.altGlyphItem &= SVG.Core.attrib
+ a:documentation [
+ "\x{a}" ~
+ " glyphRef: Glyph Reference Element\x{a}" ~
+ " "
+ ]
+ attlist.glyphRef &=
+ attribute x { Number.datatype }?,
+ attribute y { Number.datatype }?,
+ attribute dx { Number.datatype }?,
+ attribute dy { Number.datatype }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-view.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-view.rnc
new file mode 100644
index 0000000..86a6fb3
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-view.rnc
@@ -0,0 +1,46 @@
+default namespace = "http://www.w3.org/2000/svg"
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 View Module
+## file: svg-view.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## View
+##
+## view
+##
+## This module declares markup to provide support for view.
+##
+
+##
+## SVG.View.class
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.View.extra.class = notAllowed
+ SVG.View.class |= view | SVG.View.extra.class
+ a:documentation [ "\x{a}" ~ " view: View Element\x{a}" ~ " " ]
+ SVG.view.content = SVG.Description.class*
+ view = element view { attlist.view, SVG.view.content }
+ attlist.view &=
+ SVG.Core.attrib,
+ SVG.External.attrib,
+ attribute viewBox { ViewBoxSpec.datatype }?,
+ [ a:defaultValue = "xMidYMid meet" ]
+ attribute preserveAspectRatio {
+ PreserveAspectRatioSpec.datatype
+ }?,
+ [ a:defaultValue = "magnify" ]
+ attribute zoomAndPan { "disable" | "magnify" }?,
+ attribute viewTarget { text }?
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-viewport-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-viewport-attrib.rnc
new file mode 100644
index 0000000..5972b40
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-viewport-attrib.rnc
@@ -0,0 +1,38 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+
+
+##
+## SVG 1.1 Viewport Attribute Module
+## file: svg-viewport-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## Viewport Attribute
+##
+## clip, overflow
+##
+## This module defines the Viewport attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## 'clip' property/attribute value (e.g., 'auto', rect(...))
+ ##
+ ClipValue.datatype = xsd:string
+ SVG.clip.attrib = attribute clip { ClipValue.datatype }?
+ SVG.overflow.attrib =
+ attribute overflow {
+ string "visible" | string "hidden" | string "scroll" | string "auto" | string "inherit"
+ }?
+ SVG.Viewport.extra.attrib = empty
+ SVG.Viewport.attrib &=
+ SVG.clip.attrib, SVG.overflow.attrib, SVG.Viewport.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg-xlink-attrib.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg-xlink-attrib.rnc
new file mode 100644
index 0000000..d9761f3
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg-xlink-attrib.rnc
@@ -0,0 +1,76 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## SVG 1.1 XLink Attribute Module
+## file: svg-xlink-attrib.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+## Copyright 2001, 2002 W3C (MIT, INRIA, Keio), All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## $Id$
+##
+
+##
+## XLink Attribute
+##
+## type, href, role, arcrole, title, show, actuate
+##
+## This module defines the XLink, XLinkRequired, XLinkEmbed, and
+## XLinkReplace attribute set.
+##
+[ xml:lang = "en" ]
+grammar {
+ SVG.XLink.extra.attrib = empty
+ SVG.XLink.attrib &=
+ [ a:defaultValue = "simple" ]
+ attribute xlink:type { string "simple" }?,
+ attribute xlink:href { URI.datatype }?,
+ attribute xlink:role { URI.datatype }?,
+ attribute xlink:arcrole { URI.datatype }?,
+ attribute xlink:title { text }?,
+ [ a:defaultValue = "other" ] attribute xlink:show { string "other" }?,
+ [ a:defaultValue = "onLoad" ]
+ attribute xlink:actuate { string "onLoad" }?,
+ SVG.XLink.extra.attrib
+ SVG.XLinkRequired.extra.attrib = empty
+ SVG.XLinkRequired.attrib &=
+ [ a:defaultValue = "simple" ]
+ attribute xlink:type { string "simple" }?,
+ attribute xlink:href { URI.datatype },
+ attribute xlink:role { URI.datatype }?,
+ attribute xlink:arcrole { URI.datatype }?,
+ attribute xlink:title { text }?,
+ [ a:defaultValue = "other" ] attribute xlink:show { string "other" }?,
+ [ a:defaultValue = "onLoad" ]
+ attribute xlink:actuate { string "onLoad" }?,
+ SVG.XLinkRequired.extra.attrib
+ SVG.XLinkEmbed.extra.attrib = empty
+ SVG.XLinkEmbed.attrib &=
+ [ a:defaultValue = "simple" ]
+ attribute xlink:type { string "simple" }?,
+ attribute xlink:href { URI.datatype },
+ attribute xlink:role { URI.datatype }?,
+ attribute xlink:arcrole { URI.datatype }?,
+ attribute xlink:title { text }?,
+ [ a:defaultValue = "embed" ] attribute xlink:show { string "embed" }?,
+ [ a:defaultValue = "onLoad" ]
+ attribute xlink:actuate { string "onLoad" }?,
+ SVG.XLinkEmbed.extra.attrib
+ SVG.XLinkReplace.extra.attrib = empty
+ SVG.XLinkReplace.attrib &=
+ [ a:defaultValue = "simple" ]
+ attribute xlink:type { string "simple" }?,
+ attribute xlink:href { URI.datatype },
+ attribute xlink:role { URI.datatype }?,
+ attribute xlink:arcrole { URI.datatype }?,
+ attribute xlink:title { text }?,
+ [ a:defaultValue = "replace" ]
+ attribute xlink:show { string "new" | string "replace" }?,
+ [ a:defaultValue = "onRequest" ]
+ attribute xlink:actuate { string "onRequest" }?,
+ SVG.XLinkReplace.extra.attrib
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg11-basic-inc.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg11-basic-inc.rnc
new file mode 100644
index 0000000..eb4f247
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg11-basic-inc.rnc
@@ -0,0 +1,186 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## RELAX NG schema for SVG 1.1 Basic
+## file: svg11-basic.rng
+##
+## This is SVG Basic, a proper subset of SVG.
+##
+## The Scalable Vector Graphics (SVG)
+## Copyright 2001, 2002 World Wide Web Consortium
+## (Massachusetts Institute of Technology, Institut National de
+## Recherche en Informatique et en Automatique, Keio University).
+## All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## Permission to use, copy, modify and distribute this RELAX NG schema
+## for SVG and its accompanying documentation for any purpose and without
+## fee is hereby granted in perpetuity, provided that the above copyright
+## notice and this paragraph appear in all copies. The copyright holders
+## nor the author make no representation about the suitability of this
+## RELAX NG schema for any purpose.
+##
+## It is provided "as is" without expressed or implied warranty.
+##
+## Author: Masayasu Ishikawa (mimasa@w3.org)
+## Modified by: Henri Sivonen (hsivonen@iki.fi)
+## $Id: svg11-basic.rnc 121 2007-12-15 18:35:39Z hsivonen $
+##
+## This is the driver file for version 1.1 of the SVG Basic RELAX NG schema.
+##
+## The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+##
+## PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN"
+## SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd"
+##
+## Use this URI to identify the default namespace:
+##
+## "http://www.w3.org/2000/svg"
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## Viewport Attribute Module
+ ##
+ include "svg-viewport-attrib.rnc" inherit = svg
+
+ ##
+ ## Paint Attribute Module
+ ##
+ include "svg-paint-attrib.rnc" inherit = svg
+
+ ##
+ ## Opacity Attribute Module
+ ##
+ include "svg-opacity-attrib.rnc" inherit = svg
+
+ ##
+ ## Graphics Attribute Module
+ ##
+ include "svg-graphics-attrib.rnc" inherit = svg
+
+ ##
+ ## Document Events Attribute Module
+ ##
+ include "svg-docevents-attrib.rnc" inherit = svg
+
+ ##
+ ## Graphical Element Events Attribute Module
+ ##
+ include "svg-graphevents-attrib.rnc" inherit = svg
+
+ ##
+ ## Animation Events Attribute Module
+ ##
+ include "svg-animevents-attrib.rnc" inherit = svg
+
+ ##
+ ## XLink Attribute Module
+ ##
+ include "svg-xlink-attrib.rnc" inherit = svg
+
+ ##
+ ## External Resources Attribute Module
+ ##
+ include "svg-extresources-attrib.rnc" inherit = svg
+
+ ##
+ ## Structure Module (required)
+ ##
+ include "svg-structure.rnc" inherit = svg
+
+ ##
+ ## Conditional Processing Module
+ ##
+ include "svg-conditional.rnc" inherit = svg
+
+ ##
+ ## Image Module
+ ##
+ include "svg-image.rnc" inherit = svg
+
+ ##
+ ## Style Module
+ ##
+ include "svg-style.rnc" inherit = svg
+
+ ##
+ ## Shape Module
+ ##
+ include "svg-shape.rnc" inherit = svg
+
+ ##
+ ## Text Module
+ ##
+ include "svg-text.rnc" inherit = svg
+
+ ##
+ ## Color Profile Module
+ ##
+ include "svg-profile.rnc" inherit = svg
+
+ ##
+ ## Gradient Module
+ ##
+ include "svg-gradient.rnc" inherit = svg
+
+ ##
+ ## Pattern Module
+ ##
+ include "svg-pattern.rnc" inherit = svg
+
+ ##
+ ## Basic Clip Module
+ ##
+ include "svg-basic-clip.rnc" inherit = svg
+
+ ##
+ ## Mask Module
+ ##
+ include "svg-mask.rnc" inherit = svg
+
+ ##
+ ## Basic Filter Module
+ ##
+ include "svg-basic-filter.rnc" inherit = svg
+
+ ##
+ ## Cursor Module
+ ##
+ include "svg-cursor.rnc" inherit = svg
+
+ ##
+ ## Hyperlinking Module
+ ##
+ include "svg-hyperlink.rnc" inherit = svg
+
+ ##
+ ## View Module
+ ##
+ include "svg-view.rnc" inherit = svg
+
+ ##
+ ## Scripting Module
+ ##
+ include "svg-script.rnc" inherit = svg
+
+ ##
+ ## Animation Module
+ ##
+ include "svg-animation.rnc" inherit = svg
+
+ ##
+ ## Font Module
+ ##
+ include "svg-font.rnc" inherit = svg
+
+ ##
+ ## Extensibility Module
+ ##
+ include "svg-extensibility.rnc" inherit = svg
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg11-basic.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg11-basic.rnc
new file mode 100644
index 0000000..31dc47b
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg11-basic.rnc
@@ -0,0 +1,57 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## RELAX NG schema for SVG 1.1 Basic
+## file: svg11-basic.rng
+##
+## This is SVG Basic, a proper subset of SVG.
+##
+## The Scalable Vector Graphics (SVG)
+## Copyright 2001, 2002 World Wide Web Consortium
+## (Massachusetts Institute of Technology, Institut National de
+## Recherche en Informatique et en Automatique, Keio University).
+## All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## Permission to use, copy, modify and distribute this RELAX NG schema
+## for SVG and its accompanying documentation for any purpose and without
+## fee is hereby granted in perpetuity, provided that the above copyright
+## notice and this paragraph appear in all copies. The copyright holders
+## nor the author make no representation about the suitability of this
+## RELAX NG schema for any purpose.
+##
+## It is provided "as is" without expressed or implied warranty.
+##
+## Author: Masayasu Ishikawa (mimasa@w3.org)
+## Modified by: Henri Sivonen (hsivonen@iki.fi)
+## $Id$
+##
+## This is the driver file for version 1.1 of the SVG Basic RELAX NG schema.
+##
+## The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+##
+## PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN"
+## SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd"
+##
+## Use this URI to identify the default namespace:
+##
+## "http://www.w3.org/2000/svg"
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## Includes
+ ##
+ include "svg11-basic-inc.rnc" inherit = svg
+
+ # Moved start = here -- hsivonen
+ ##
+ ## The root element is "svg".
+ ##
+ start = svg
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg11-inc.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg11-inc.rnc
new file mode 100644
index 0000000..c2237e2
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg11-inc.rnc
@@ -0,0 +1,196 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## RELAX NG schema for SVG 1.1
+## file: svg11.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+##
+## The Scalable Vector Graphics (SVG)
+## Copyright 2001, 2002 World Wide Web Consortium
+## (Massachusetts Institute of Technology, Institut National de
+## Recherche en Informatique et en Automatique, Keio University).
+## All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## Permission to use, copy, modify and distribute this RELAX NG schema
+## for SVG and its accompanying documentation for any purpose and without
+## fee is hereby granted in perpetuity, provided that the above copyright
+## notice and this paragraph appear in all copies. The copyright holders
+## nor the author make no representation about the suitability of this
+## RELAX NG schema for any purpose.
+##
+## It is provided "as is" without expressed or implied warranty.
+##
+## Author: Masayasu Ishikawa (mimasa@w3.org)
+## Modified by: Henri Sivonen (hsivonen@iki.fi)
+## $Id: svg11.rnc 121 2007-12-15 18:35:39Z hsivonen $
+##
+## This is the driver file for version 1.1 of the SVG RELAX NG schema.
+##
+## The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+##
+## PUBLIC "-//W3C//DTD SVG 1.1//EN"
+## SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
+##
+## Use this URI to identify the default namespace:
+##
+## "http://www.w3.org/2000/svg"
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## Container Attribute Module
+ ##
+ include "svg-container-attrib.rnc" inherit = svg
+
+ ##
+ ## Viewport Attribute Module
+ ##
+ include "svg-viewport-attrib.rnc" inherit = svg
+
+ ##
+ ## Paint Attribute Module
+ ##
+ include "svg-paint-attrib.rnc" inherit = svg
+
+ ##
+ ## Paint Opacity Attribute Module
+ ##
+ include "svg-opacity-attrib.rnc" inherit = svg
+
+ ##
+ ## Graphics Attribute Module
+ ##
+ include "svg-graphics-attrib.rnc" inherit = svg
+
+ ##
+ ## Document Events Attribute Module
+ ##
+ include "svg-docevents-attrib.rnc" inherit = svg
+
+ ##
+ ## Graphical Element Events Attribute Module
+ ##
+ include "svg-graphevents-attrib.rnc" inherit = svg
+
+ ##
+ ## Animation Events Attribute Module
+ ##
+ include "svg-animevents-attrib.rnc" inherit = svg
+
+ ##
+ ## XLink Attribute Module
+ ##
+ include "svg-xlink-attrib.rnc" inherit = svg
+
+ ##
+ ## External Resources Attribute Module
+ ##
+ include "svg-extresources-attrib.rnc" inherit = svg
+
+ ##
+ ## Structure Module (required)
+ ##
+ include "svg-structure.rnc" inherit = svg
+
+ ##
+ ## Conditional Processing Module
+ ##
+ include "svg-conditional.rnc" inherit = svg
+
+ ##
+ ## Image Module
+ ##
+ include "svg-image.rnc" inherit = svg
+
+ ##
+ ## Style Module
+ ##
+ include "svg-style.rnc" inherit = svg
+
+ ##
+ ## Shape Module
+ ##
+ include "svg-shape.rnc" inherit = svg
+
+ ##
+ ## Text Module
+ ##
+ include "svg-text.rnc" inherit = svg
+
+ ##
+ ## Marker Module
+ ##
+ include "svg-marker.rnc" inherit = svg
+
+ ##
+ ## Color Profile Module
+ ##
+ include "svg-profile.rnc" inherit = svg
+
+ ##
+ ## Gradient Module
+ ##
+ include "svg-gradient.rnc" inherit = svg
+
+ ##
+ ## Pattern Module
+ ##
+ include "svg-pattern.rnc" inherit = svg
+
+ ##
+ ## Clip Module
+ ##
+ include "svg-clip.rnc" inherit = svg
+
+ ##
+ ## Mask Module
+ ##
+ include "svg-mask.rnc" inherit = svg
+
+ ##
+ ## Filter Module
+ ##
+ include "svg-filter.rnc" inherit = svg
+
+ ##
+ ## Cursor Module
+ ##
+ include "svg-cursor.rnc" inherit = svg
+
+ ##
+ ## Hyperlinking Module
+ ##
+ include "svg-hyperlink.rnc" inherit = svg
+
+ ##
+ ## View Module
+ ##
+ include "svg-view.rnc" inherit = svg
+
+ ##
+ ## Scripting Module
+ ##
+ include "svg-script.rnc" inherit = svg
+
+ ##
+ ## Animation Module
+ ##
+ include "svg-animation.rnc" inherit = svg
+
+ ##
+ ## Font Module
+ ##
+ include "svg-font.rnc" inherit = svg
+
+ ##
+ ## Extensibility Module
+ ##
+ include "svg-extensibility.rnc" inherit = svg
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg11-tiny-inc.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg11-tiny-inc.rnc
new file mode 100644
index 0000000..86c1bbb
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg11-tiny-inc.rnc
@@ -0,0 +1,141 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## RELAX NG schema for SVG 1.1 Tiny
+## file: svg11-tiny.rng
+##
+## This is SVG Tiny, a proper subset of SVG.
+##
+## The Scalable Vector Graphics (SVG)
+## Copyright 2001, 2002 World Wide Web Consortium
+## (Massachusetts Institute of Technology, Institut National de
+## Recherche en Informatique et en Automatique, Keio University).
+## All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## Permission to use, copy, modify and distribute this RELAX NG schema
+## for SVG and its accompanying documentation for any purpose and without
+## fee is hereby granted in perpetuity, provided that the above copyright
+## notice and this paragraph appear in all copies. The copyright holders
+## nor the author make no representation about the suitability of this
+## RELAX NG schema for any purpose.
+##
+## It is provided "as is" without expressed or implied warranty.
+##
+## Author: Masayasu Ishikawa (mimasa@w3.org)
+## Modified by: Henri Sivonen (hsivonen@iki.fi)
+## $Id: svg11-tiny.rnc 121 2007-12-15 18:35:39Z hsivonen $
+##
+## This is the driver file for version 1.1 of the SVG Tiny RELAX NG schema.
+##
+## The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+##
+## PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN"
+## SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd"
+##
+## Use this URI to identify the default namespace:
+##
+## "http://www.w3.org/2000/svg"
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## Paint Attribute Module
+ ##
+ include "svg-paint-attrib.rnc" inherit = svg
+
+ ##
+ ## Basic Graphics Attribute Module
+ ##
+ include "svg-basic-graphics-attrib.rnc" inherit = svg
+
+ ##
+ ## Document Events Attribute Module
+ ##
+ include "svg-docevents-attrib.rnc" inherit = svg
+
+ ##
+ ## Graphical Element Events Attribute Module
+ ##
+ include "svg-graphevents-attrib.rnc" inherit = svg
+
+ ##
+ ## Animation Events Attribute Module
+ ##
+ include "svg-animevents-attrib.rnc" inherit = svg
+
+ ##
+ ## XLink Attribute Module
+ ##
+ include "svg-xlink-attrib.rnc" inherit = svg
+
+ ##
+ ## External Resources Attribute Module
+ ##
+ include "svg-extresources-attrib.rnc" inherit = svg
+
+ ##
+ ## Basic Structure Module (required)
+ ##
+ include "svg-basic-structure.rnc" inherit = svg
+
+ ##
+ ## Conditional Processing Module
+ ##
+ include "svg-conditional.rnc" inherit = svg
+
+ ##
+ ## Image Module
+ ##
+ include "svg-image.rnc" inherit = svg
+
+ ##
+ ## Style Module
+ ##
+ include "svg-style.rnc" inherit = svg
+
+ ##
+ ## Shape Module
+ ##
+ include "svg-shape.rnc" inherit = svg
+
+ ##
+ ## Basic Text Module
+ ##
+ include "svg-basic-text.rnc" inherit = svg
+
+ ##
+ ## Hyperlinking Module
+ ##
+ include "svg-hyperlink.rnc" inherit = svg
+
+ ##
+ ## View Module
+ ##
+ include "svg-view.rnc" inherit = svg
+
+ ##
+ ## Scripting Module
+ ##
+ include "svg-script.rnc" inherit = svg
+
+ ##
+ ## Animation Module
+ ##
+ include "svg-animation.rnc" inherit = svg
+
+ ##
+ ## Basic Font Module
+ ##
+ include "svg-basic-font.rnc" inherit = svg
+
+ ##
+ ## Extensibility Module
+ ##
+ include "svg-extensibility.rnc" inherit = svg
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg11-tiny.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg11-tiny.rnc
new file mode 100644
index 0000000..969baee
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg11-tiny.rnc
@@ -0,0 +1,57 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## RELAX NG schema for SVG 1.1 Tiny
+## file: svg11-tiny.rng
+##
+## This is SVG Tiny, a proper subset of SVG.
+##
+## The Scalable Vector Graphics (SVG)
+## Copyright 2001, 2002 World Wide Web Consortium
+## (Massachusetts Institute of Technology, Institut National de
+## Recherche en Informatique et en Automatique, Keio University).
+## All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## Permission to use, copy, modify and distribute this RELAX NG schema
+## for SVG and its accompanying documentation for any purpose and without
+## fee is hereby granted in perpetuity, provided that the above copyright
+## notice and this paragraph appear in all copies. The copyright holders
+## nor the author make no representation about the suitability of this
+## RELAX NG schema for any purpose.
+##
+## It is provided "as is" without expressed or implied warranty.
+##
+## Author: Masayasu Ishikawa (mimasa@w3.org)
+## Modified by: Henri Sivonen (hsivonen@iki.fi)
+## $Id$
+##
+## This is the driver file for version 1.1 of the SVG Tiny RELAX NG schema.
+##
+## The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+##
+## PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN"
+## SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd"
+##
+## Use this URI to identify the default namespace:
+##
+## "http://www.w3.org/2000/svg"
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## Extensibility Module
+ ##
+ include "svg11-tiny-inc.rnc" inherit = svg
+
+ # Moved start = here -- hsivonen
+ ##
+ ## The root element is "svg".
+ ##
+ start = svg
+}
diff --git a/xml/relaxng/src/resources/html5-schema/svg11/svg11.rnc b/xml/relaxng/src/resources/html5-schema/svg11/svg11.rnc
new file mode 100644
index 0000000..3100e26
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/svg11/svg11.rnc
@@ -0,0 +1,57 @@
+namespace a = "http://relaxng.org/ns/compatibility/annotations/1.0"
+namespace svg = "http://www.w3.org/2000/svg"
+namespace xlink = "http://www.w3.org/1999/xlink"
+
+
+##
+## RELAX NG schema for SVG 1.1
+## file: svg11.rng
+##
+## This is SVG, a language for describing two-dimensional graphics in XML.
+##
+## The Scalable Vector Graphics (SVG)
+## Copyright 2001, 2002 World Wide Web Consortium
+## (Massachusetts Institute of Technology, Institut National de
+## Recherche en Informatique et en Automatique, Keio University).
+## All Rights Reserved.
+##
+## Modifications Copyright 2007 Mozilla Foundation
+##
+## Permission to use, copy, modify and distribute this RELAX NG schema
+## for SVG and its accompanying documentation for any purpose and without
+## fee is hereby granted in perpetuity, provided that the above copyright
+## notice and this paragraph appear in all copies. The copyright holders
+## nor the author make no representation about the suitability of this
+## RELAX NG schema for any purpose.
+##
+## It is provided "as is" without expressed or implied warranty.
+##
+## Author: Masayasu Ishikawa (mimasa@w3.org)
+## Modified by: Henri Sivonen (hsivonen@iki.fi)
+## $Id$
+##
+## This is the driver file for version 1.1 of the SVG RELAX NG schema.
+##
+## The DTD version is identified by the PUBLIC and SYSTEM identifiers:
+##
+## PUBLIC "-//W3C//DTD SVG 1.1//EN"
+## SYSTEM "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"
+##
+## Use this URI to identify the default namespace:
+##
+## "http://www.w3.org/2000/svg"
+##
+[ xml:lang = "en" ]
+grammar {
+
+ ##
+ ## Includes
+ ##
+ include "svg11-inc.rnc" inherit = svg
+
+ # Moved start = here -- hsivonen
+ ##
+ ## The root element is "svg".
+ ##
+ start = svg
+}
diff --git a/xml/relaxng/src/resources/html5-schema/tables.rnc b/xml/relaxng/src/resources/html5-schema/tables.rnc
deleted file mode 100644
index 3e5d725..0000000
--- a/xml/relaxng/src/resources/html5-schema/tables.rnc
+++ /dev/null
@@ -1,249 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Tables #
-# #####################################################################
-
-# #####################################################################
-## Table Envelope
-
-## Table Datatypes
-
-# tables.data.multilen =
-# ( common.data.integer.positive
-# | common.data.percent
-# | xsd:token { pattern = "[0-9]+\*" } #REVISIT should this one be string?
-# )
-
-## Table Alignment Attributes
-
- tables.attrs.alignment =
- ( tables.attrs.align?
- & tables.attrs.char?
- & tables.attrs.valign?
- )
- tables.attrs.align =
- attribute align {
- ( w:string "left"
- | w:string "center"
- | w:string "right"
- | w:string "justify"
- | w:string "char"
- )
- }
- tables.attrs.char =
- attribute char {
- xsd:string { pattern = "." }
- }
- tables.attrs.valign =
- attribute valign {
- ( w:string "top"
- | w:string "middle"
- | w:string "bottom"
- | w:string "baseline"
- )
- }
-
-## Data Table: <table>
-
- table.elem =
- element table { table.inner & table.attrs }
- table.attrs =
- ( common.attrs
- & table.attrs.border?
- & common.attrs.aria?
- )
- table.attrs.border =
- attribute border {
- string
- }
- table.inner =
- ( caption.elem?
- , colgroup.elem*
- , thead.elem?
- , ( ( tfoot.elem
- , ( tbody.elem* | tr.elem+ )
- )
- | ( ( tbody.elem* | tr.elem+ )
- , tfoot.elem?
- )
- )
- )
-
- common.elem.flow |= table.elem
-
-## Table Caption: <caption>
-
- caption.elem =
- element caption { caption.inner & caption.attrs }
- caption.attrs =
- ( common.attrs
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- caption.inner =
- ( common.inner.flow )
-
-# #####################################################################
-## Table Super Structure
-
-## Table Column Group: <colgroup>
-
- colgroup.elem =
- element colgroup { colgroup.inner & colgroup.attrs }
- colgroup.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- colgroup.attrs.span =
- attribute span {
- common.data.integer.positive
- }
- colgroup.inner =
- ( col.elem*
- | colgroup.attrs.span?
- )
-
-## Table Column: <col>
-
- col.elem =
- element col { col.inner & col.attrs }
- col.attrs =
- ( common.attrs
- & col.attrs.span?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- col.attrs.span =
- attribute span {
- common.data.integer.positive
- }
- col.inner =
- ( empty )
-
-## Table Header Row Group
-
- thead.elem =
- element thead { thead.inner & thead.attrs }
- thead.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- thead.inner =
- ( tr.elem* )
-
-## Table Footer Row Group
-
- tfoot.elem =
- element tfoot { tfoot.inner & tfoot.attrs }
- tfoot.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- tfoot.inner =
- ( tr.elem* )
-
-## Table Row Group
-
- tbody.elem =
- element tbody { tbody.inner & tbody.attrs }
- tbody.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- tbody.inner =
- ( tr.elem* )
-
-# #####################################################################
-## Cell Structure
-
-## Table Row
-
- tr.elem =
- element tr { tr.inner & tr.attrs }
- tr.attrs =
- ( common.attrs
- & common.attrs.aria?
- )
- tr.inner =
- ( ( td.elem | th.elem )* )
-
-## Common Table Cell Attributes
-
- tables.attrs.cell-structure =
- ( tables.attrs.colspan?
- & tables.attrs.rowspan?
- )
- tables.attrs.colspan =
- attribute colspan {
- common.data.integer.positive
- }
- tables.attrs.rowspan =
- attribute rowspan {
- common.data.integer.non-negative
- }
-
- tables.attrs.access-headers =
- ( tables.attrs.headers? )
- tables.attrs.headers =
- attribute headers {
- common.data.idrefs
- }
-
- tables.attrs.define-headers =
- ( tables.attrs.scope? )
- tables.attrs.scope =
- attribute scope {
- ( w:string "row"
- | w:string "col"
- | w:string "rowgroup"
- | w:string "colgroup"
- )
- }
- tables.attrs.abbr =
- attribute abbr {
- text
- }
-
-## Table Data Cell: <td>
-
- td.elem =
- element td { td.inner & td.attrs }
- td.attrs =
- ( common.attrs
- & tables.attrs.cell-structure
- & tables.attrs.headers?
-# & tables.attrs.alignment
- & common.attrs.aria?
- )
- td.inner =
- ( common.inner.flow )
-
-## Table Header Cells: <th>
-
- th.elem =
- element th { th.inner & th.attrs }
- th.attrs =
- ( common.attrs
- & tables.attrs.cell-structure
- & tables.attrs.scope?
- & tables.attrs.headers?
-# & tables.attrs.alignment
- & ( common.attrs.aria.implicit.th
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- th.inner =
- ( common.inner.flow )
diff --git a/xml/relaxng/src/resources/html5-schema/web-forms.rnc b/xml/relaxng/src/resources/html5-schema/web-forms.rnc
deleted file mode 100644
index 73b89d8..0000000
--- a/xml/relaxng/src/resources/html5-schema/web-forms.rnc
+++ /dev/null
@@ -1,590 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Web Forms 1.0 markup #
-# #####################################################################
-
-## Shared attributes for form controls
-
- common-form.attrs =
- ( common-form.attrs.name?
- & common-form.attrs.disabled?
- )
-
- common-form.attrs.name =
- attribute name {
- string #REVISIT should this be restricted somehow? No & and = perhaps?
- }
-
- common-form.attrs.disabled =
- attribute disabled {
- w:string "disabled" | w:string ""
- }
-
- shared-form.attrs.readonly =
- attribute readonly {
- w:string "readonly" | w:string ""
- }
-
- shared-form.attrs.maxlength =
- attribute maxlength {
- common.data.integer.non-negative
- }
-
- shared-form.attrs.size =
- attribute size {
- common.data.integer.positive
- }
-
- # REVISIT tabindex goes in common.attrs
-
-## Shared attributes for <input>
-
- input.attrs.checked =
- attribute checked {
- w:string "checked" | w:string ""
- }
-
-## Text Field: <input type='text'>
-
- input.text.elem =
- element input { input.text.attrs }
- input.text.attrs =
- ( common.attrs
- & common-form.attrs
- & input.text.attrs.type?
- & shared-form.attrs.maxlength?
- & shared-form.attrs.readonly?
- & shared-form.attrs.size?
- & input.text.attrs.value?
- & ( common.attrs.aria?
- | common.attrs.aria.implicit.input
- )?
- )
- input.text.attrs.type =
- attribute type {
- w:string "text"
- }
- input.text.attrs.value =
- attribute value {
- form.data.stringwithoutlinebreaks
- }
-
- input.elem = input.text.elem
-
-## Password Field: <input type='password'>
-
- input.password.elem =
- element input { input.password.attrs }
- input.password.attrs =
- ( common.attrs
- & common-form.attrs
- & input.password.attrs.type
- & shared-form.attrs.maxlength?
- & shared-form.attrs.readonly?
- & shared-form.attrs.size?
- & input.password.attrs.value?
- & common.attrs.aria?
- )
- input.password.attrs.type =
- attribute type {
- w:string "password"
- }
- input.password.attrs.value =
- attribute value {
- form.data.stringwithoutlinebreaks
- }
-
- input.elem |= input.password.elem
-
-## Checkbox: <input type='checkbox'>
-
- input.checkbox.elem =
- element input { input.checkbox.attrs }
- input.checkbox.attrs =
- ( common.attrs
- & common-form.attrs
- & input.checkbox.attrs.type
- & input.attrs.checked?
- & input.checkbox.attrs.value?
- & common.attrs.aria?
- )
- input.checkbox.attrs.type =
- attribute type {
- w:string "checkbox"
- }
- input.checkbox.attrs.value =
- attribute value {
- string #REVISIT require non-empty value?
- }
-
- input.elem |= input.checkbox.elem
-
-## Radiobutton: <input type='radio'>
-
- input.radio.elem =
- element input { input.radio.attrs }
- input.radio.attrs =
- ( common.attrs
- & common-form.attrs
- & input.radio.attrs.type
- & input.attrs.checked?
- & input.radio.attrs.value?
- & ( common.attrs.aria.role.radio
- | common.attrs.aria.role.menuitemradio
- )?
- )
- input.radio.attrs.type =
- attribute type {
- w:string "radio"
- }
- input.radio.attrs.value =
- attribute value {
- string #REVISIT require non-empty value?
- }
-
- input.elem |= input.radio.elem
-
-## Scripting Hook Button: <input type='button'>
-
- input.button.elem =
- element input { input.button.attrs }
- input.button.attrs =
- ( common.attrs
- & common-form.attrs
- & input.button.attrs.type
- & input.button.attrs.value?
- & ( common.attrs.aria.implicit.button
- | common.attrs.aria.role.button
- | common.attrs.aria.role.link
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.menuitemcheckbox
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.radio
- )?
- )
- input.button.attrs.type =
- attribute type {
- w:string "button"
- }
- input.button.attrs.value =
- attribute value {
- string #REVISIT require non-empty value?
- }
-
- input.elem |= input.button.elem
- #REVISIT should this be enabled by a scripting module only?
-
-## Submit Button: <input type='submit'>
-
- input.submit.elem =
- element input { input.submit.attrs }
- input.submit.attrs =
- ( common.attrs
- & common-form.attrs
- & input.submit.attrs.type
- & input.submit.attrs.value?
- & common.attrs.aria?
- )
- input.submit.attrs.type =
- attribute type {
- w:string "submit"
- }
- input.submit.attrs.value =
- attribute value {
- string #REVISIT require non-empty value?
- }
-
- input.elem |= input.submit.elem
-
-## Reset Button: <input type='reset'>
-
- input.reset.elem =
- element input { input.reset.attrs }
- input.reset.attrs =
- ( common.attrs
- & common-form.attrs
- & input.reset.attrs.type
- & input.reset.attrs.value?
- & common.attrs.aria?
- )
- input.reset.attrs.type =
- attribute type {
- w:string "reset"
- }
- input.reset.attrs.value =
- attribute value {
- string #REVISIT require non-empty value?
- }
-
- input.elem |= input.reset.elem
- # REVISIT does reset make sense outside a form?
-
-## File Upload: <input type='file'>
-
- input.file.elem =
- element input { input.file.attrs }
- input.file.attrs =
- ( common.attrs
- & common-form.attrs
- & input.file.attrs.type
- & input.file.attrs.accept?
- & common.attrs.aria?
- )
- input.file.attrs.type =
- attribute type {
- w:string "file"
- }
- input.file.attrs.accept =
- attribute accept {
- form.data.mimetypelist
- }
-
- input.elem |= input.file.elem
-
-## Hidden String: <input type='hidden'>
-
- input.hidden.elem =
- element input { input.hidden.attrs }
- input.hidden.attrs =
- ( common.attrs
- & common-form.attrs
- & input.hidden.attrs.type
- & input.hidden.attrs.value?
- & common.attrs.aria?
- )
- input.hidden.attrs.type =
- attribute type {
- w:string "hidden"
- }
- input.hidden.attrs.value =
- attribute value {
- string
- }
-
- input.elem |= input.hidden.elem
-
-## Image Submit Button: <input type='image'>
-
- input.image.elem =
- element input { input.image.attrs }
- input.image.attrs =
- ( common.attrs
- & common-form.attrs
- & input.image.attrs.type
- & input.image.attrs.alt
- & input.image.attrs.src?
- & ( common.attrs.aria.implicit.button
- | common.attrs.aria.role.button
- | common.attrs.aria.role.link
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.menuitemcheckbox
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.radio
- )?
- )
- input.image.attrs.type =
- attribute type {
- w:string "image"
- }
- input.image.attrs.alt =
- attribute alt {
- form.data.nonemptystring
- }
- input.image.attrs.src =
- attribute src {
- common.data.uri.non-empty
- }
-
- input.elem |= input.image.elem
-
- common.elem.phrasing |= input.elem
-
-## Text Area: <textarea>
-
- textarea.elem =
- element textarea { textarea.inner & textarea.attrs }
- textarea.attrs =
- ( common.attrs
- & common-form.attrs
- & shared-form.attrs.readonly?
- & textarea.attrs.rows-and-cols-wf1
- & ( common.attrs.aria.implicit.input
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.combobox
- | common.attrs.aria.role.textbox
- )?
- #FIXME onfocus, onblur, onselect,onchange
- )
- # This is ugly.
- textarea.attrs.rows-and-cols-wf1 =
- textarea.attrs.rows-and-cols-wf1.inner
- textarea.attrs.rows-and-cols-wf1.inner =
- ( textarea.attrs.cols
- & textarea.attrs.rows
- )
- textarea.attrs.cols =
- attribute cols {
- common.data.integer.positive
- }
- textarea.attrs.rows =
- attribute rows {
- common.data.integer.positive
- }
- textarea.inner =
- ( text )
-
- common.elem.phrasing |= textarea.elem
-
-# Due to limitations with interleave, handling single/multiple selection
-# enforcement in RELAX NG seems to be possible but really awkward.
-# Tried it. Leaving it to Schematron.
-
-## Select menu option: <option selected>
-
- option.elem =
- element option { option.inner & option.attrs }
- option.attrs =
- ( common.attrs
- & common-form.attrs.disabled?
- & option.attrs.selected?
- & option.attrs.label?
- & option.attrs.value?
- & ( common.attrs.aria.implicit.input
- | common.attrs.aria.role.option
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.menuitemcheckbox
- )?
- )
- option.attrs.selected =
- attribute selected {
- w:string "selected" | w:string ""
- }
- option.attrs.label =
- attribute label {
- string
- }
- option.attrs.value =
- attribute value {
- string
- }
- option.inner =
- ( text )
-
-## Option Group: <optgroup>
-
- optgroup.elem =
- element optgroup { optgroup.inner & optgroup.attrs }
- optgroup.attrs =
- ( common.attrs
- & optgroup.attrs.label
- & common-form.attrs.disabled?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- optgroup.attrs.label =
- attribute label {
- string
- }
- optgroup.inner =
- ( option.elem* )
-
-## Selection Menu: <select>
-
- select.elem =
- element select { select.inner & select.attrs }
- select.attrs =
- ( common.attrs
- & common-form.attrs
- & select.attrs.size?
- & select.attrs.multiple?
- # FIXME onfocus, onblur, onchange
- & ( common.attrs.aria.role.listbox # aria-multiselectable depends on "multiple" value; check in assertions
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- select.attrs.size =
- attribute size {
- common.data.integer.positive
- }
- select.attrs.multiple =
- attribute multiple {
- w:string "multiple" | w:string ""
- }
- select.inner =
- ( optgroup.elem*
- & option.elem*
- )
-
- common.elem.phrasing |= select.elem
-
-## Shared Definitions for Complex Button
-
- button.attrs.value =
- attribute value {
- string
- }
- button.inner =
- ( common.inner.phrasing )
-
-## Complex Submit Button: <button type='submit'>
-
- button.submit.elem =
- element button { button.inner & button.submit.attrs }
- button.submit.attrs =
- ( common.attrs
- & common-form.attrs
- & button.submit.attrs.type?
- & button.attrs.value?
- & ( common.attrs.aria.implicit.button
- | common.attrs.aria.role.button
- | common.attrs.aria.role.link
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.menuitemcheckbox
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.radio
- )?
- )
- button.submit.attrs.type =
- attribute type {
- w:string "submit"
- }
-
- button.elem = button.submit.elem
-
-## Complex Reset Button: <button type='reset'>
-
- button.reset.elem =
- element button { button.inner & button.reset.attrs }
- button.reset.attrs =
- ( common.attrs
- & common-form.attrs
- & button.reset.attrs.type
- & button.attrs.value? #REVISIT I guess this still affects the DOM
- & ( common.attrs.aria.implicit.button
- | common.attrs.aria.role.button
- | common.attrs.aria.role.link
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.menuitemcheckbox
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.radio
- )?
- )
- button.reset.attrs.type =
- attribute type {
- w:string "reset"
- }
-
- button.elem |= button.reset.elem
-
-## Complex Push Button: <button type='button'>
-
- button.button.elem =
- element button { button.inner & button.button.attrs }
- button.button.attrs =
- ( common.attrs
- & common-form.attrs
- & button.button.attrs.type
- & button.attrs.value? #REVISIT I guess this still affects the DOM
- & ( common.attrs.aria.implicit.button
- | common.attrs.aria.role.button
- | common.attrs.aria.role.link
- | common.attrs.aria.role.menuitem
- | common.attrs.aria.role.menuitemcheckbox
- | common.attrs.aria.role.menuitemradio
- | common.attrs.aria.role.radio
- )?
- )
- button.button.attrs.type =
- attribute type {
- w:string "button"
- }
-
- button.elem |= button.button.elem
-
- common.elem.phrasing |= button.elem
-
-## Form: <form>
-
- form.elem =
- element form { form.inner & form.attrs }
- form.attrs =
- ( common.attrs
- & form.attrs.action? #REVISIT Should this be required anyway?
- & form.attrs.method?
- & form.attrs.enctype?
- & common-form.attrs.name?
- & form.attrs.accept-charset?
- & ( common.attrs.aria?
- | common.attrs.aria.implicit.region
- )?
- )
- form.attrs.action =
- attribute action {
- common.data.uri.non-empty
- }
- form.attrs.method =
- attribute method {
- form.attrs.method.data
- }
- form.attrs.method.data =
- ( w:string "get" | w:string "post" )
- form.attrs.enctype =
- attribute enctype {
- form.attrs.enctype.data
- }
- form.attrs.enctype.data =
- ( w:string "application/x-www-form-urlencoded"
- | w:string "multipart/form-data"
- )
- form.attrs.accept-charset =
- attribute accept-charset {
- form.data.charsetlist
- }
- form.inner =
- ( common.inner.flow )
-
- common.elem.flow |= form.elem
-
-## Fieldset: <fieldset>
-
- fieldset.elem =
- element fieldset { fieldset.inner & fieldset.attrs }
- fieldset.attrs =
- ( common.attrs
- & ( common.attrs.aria?
- | common.attrs.aria.implicit.region
- )?
- )
- fieldset.inner =
- ( legend.elem? #REVISIT should this be required?
- , common.inner.flow
- )
-
- common.elem.flow |= fieldset.elem
-
-## Label: <label>
-
- label.elem =
- element label { label.inner & label.attrs }
- label.attrs =
- ( common.attrs
- & label.attrs.for?
- & ( common.attrs.aria.implicit.region
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- label.attrs.for =
- attribute for {
- common.data.idref
- }
- label.inner =
- ( common.inner.phrasing ) #REVISIT making obvious guess
-
- common.elem.phrasing |= label.elem
-
diff --git a/xml/relaxng/src/resources/html5-schema/web-forms2.rnc b/xml/relaxng/src/resources/html5-schema/web-forms2.rnc
deleted file mode 100644
index d77067b..0000000
--- a/xml/relaxng/src/resources/html5-schema/web-forms2.rnc
+++ /dev/null
@@ -1,808 +0,0 @@
-datatypes w = "http://whattf.org/datatype-draft"
-
-# #####################################################################
-## RELAX NG Schema for HTML 5: Web Forms 2.0 markup #
-# #####################################################################
-
-## Shared attributes for form controls
-
- common-form.attrs &=
- ( common-form.attrs.form? )
-
- common-form.attrs.form |=
- attribute form {
- common.data.idref
- }
-
- shared-form.attrs.formaction =
- attribute formaction {
- common.data.uri.non-empty
- }
-
- shared-form.attrs.formenctype =
- attribute formenctype {
- shared-form.attrs.formenctype.data
- }
- shared-form.attrs.formenctype.data =
- ( w:string "application/x-www-form-urlencoded"
- | w:string "multipart/form-data"
- | w:string "text/plain"
- )
-
- shared-form.attrs.formmethod =
- attribute formmethod {
- shared-form.attrs.formmethod.data
- }
- shared-form.attrs.formmethod.data =
- ( w:string "get"
- | w:string "post"
- )
-
- shared-form.attrs.formtarget =
- attribute formtarget {
- common.data.browsing-context-or-keyword
- }
-
- shared-form.attrs.formnovalidate =
- attribute formnovalidate {
- w:string "formnovalidate" | w:string ""
- }
-
- shared-form.attrs.autofocus =
- attribute autofocus {
- w:string "autofocus" | w:string ""
- }
-
- shared-form.attrs.pattern =
- attribute pattern {
- form.data.pattern
- }
-
- shared-form.attrs.template =
- attribute template {
- common.data.idref
- }
-
- shared-form.attrs.required =
- attribute required {
- w:string "required" | w:string ""
- }
-
- shared-form.attrs.placeholder =
- attribute placeholder {
- form.data.stringwithoutlinebreaks
- }
-
- shared-form.attrs.dirname =
- attribute dirname {
- form.data.nonemptystring
- }
-
-## Shared attributes for <input>
-
- input.attrs.autocomplete =
- attribute autocomplete {
- w:string "on" | w:string "off"
- }
-
- input.attrs.list =
- attribute list {
- common.data.idref
- }
-
- input.attrs.step.float =
- attribute step {
- w:string "any" | common.data.float.positive
- }
-
- input.attrs.step.integer =
- attribute step {
- w:string "any" | common.data.integer.positive
- }
-
- input.attrs.multiple =
- attribute multiple {
- w:string "multiple" | w:string ""
- }
-
-## Text Field: <input type='text'>, Extensions
-
- input.text.attrs &=
- ( input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & shared-form.attrs.pattern?
- & shared-form.attrs.required?
- & shared-form.attrs.placeholder?
- & shared-form.attrs.dirname?
- )
-
-## Password Field: <input type='password'>, Extensions
-
- input.password.attrs &=
- ( input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & shared-form.attrs.pattern?
- & shared-form.attrs.required?
- & shared-form.attrs.placeholder?
- )
-
-## Checkbox <input type='checkbox'>, Extensions
-
- input.checkbox.attrs &=
- ( shared-form.attrs.autofocus?
- & shared-form.attrs.required?
- )
-
-## Radiobutton: <input type='radio'>, Extensions
-
- input.radio.attrs &=
- ( shared-form.attrs.autofocus?
- & shared-form.attrs.required?
- )
-
-## Scripting Hook Button: <input type='button'>, Extensions
-
- input.button.attrs &=
- ( shared-form.attrs.autofocus? )
-
-## Submit Button: <input type='submit'>, Extensions
-
- input.submit.attrs &=
- ( shared-form.attrs.formaction?
- & shared-form.attrs.autofocus?
- & shared-form.attrs.formenctype?
- & shared-form.attrs.formmethod?
- & shared-form.attrs.formtarget?
- & shared-form.attrs.formnovalidate?
- )
-
-## Reset Button: <input type='reset'>, Extensions
-
- input.reset.attrs &=
- ( shared-form.attrs.autofocus? )
-
-## File Upload: <input type='file'>, Extensions
-
- input.file.attrs &=
- ( shared-form.attrs.autofocus?
- & shared-form.attrs.required?
- & input.attrs.multiple?
- )
-
-## Image Submit Button: <input type='image'>, Extensions
-
- input.image.attrs &=
- ( shared-form.attrs.formaction?
- & shared-form.attrs.autofocus?
- & shared-form.attrs.formenctype?
- & shared-form.attrs.formmethod?
- & shared-form.attrs.formtarget?
- & shared-form.attrs.formnovalidate?
- & input.image.attrs.height?
- & input.image.attrs.width?
- )
- input.image.attrs.height =
- attribute height {
- common.data.integer.non-negative
- }
- input.image.attrs.width =
- attribute width {
- common.data.integer.non-negative
- }
-
-## Global Date and Time: <input type='datetime'>
-
- input.datetime.elem =
- element input { input.datetime.attrs }
- input.datetime.attrs =
- ( common.attrs
- & common-form.attrs
- & input.datetime.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.datetime.attrs.min?
- & input.datetime.attrs.max?
- & input.attrs.step.float?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & input.datetime.attrs.value?
- & common.attrs.aria?
- )
- input.datetime.attrs.type =
- attribute type {
- w:string "datetime"
- }
- input.datetime.attrs.min =
- attribute min {
- common.data.datetime
- }
- input.datetime.attrs.max =
- attribute max {
- common.data.datetime
- }
- input.datetime.attrs.value =
- attribute value {
- w:string "" | common.data.datetime
- }
-
- input.elem |= input.datetime.elem
-
-## Date and Time with No Time Zone Information: <input type='datetime-local'>
-
- input.datetime-local.elem =
- element input { input.datetime-local.attrs }
- input.datetime-local.attrs =
- ( common.attrs
- & common-form.attrs
- & input.datetime-local.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.datetime-local.attrs.min?
- & input.datetime-local.attrs.max?
- & input.attrs.step.float?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & input.datetime-local.attrs.value?
- & common.attrs.aria?
- )
- input.datetime-local.attrs.type =
- attribute type {
- w:string "datetime-local"
- }
- input.datetime-local.attrs.min =
- attribute min {
- form.data.datetime-local
- }
- input.datetime-local.attrs.max =
- attribute max {
- form.data.datetime-local
- }
- input.datetime-local.attrs.value =
- attribute value {
- w:string "" | form.data.datetime-local
- }
-
- input.elem |= input.datetime-local.elem
-
-## Date: <input type='date'>
-
- input.date.elem =
- element input { input.date.attrs }
- input.date.attrs =
- ( common.attrs
- & common-form.attrs
- & input.date.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.date.attrs.min?
- & input.date.attrs.max?
- & input.attrs.step.integer?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & input.date.attrs.value?
- & common.attrs.aria?
- )
- input.date.attrs.type =
- attribute type {
- w:string "date"
- }
- input.date.attrs.min =
- attribute min {
- form.data.date
- }
- input.date.attrs.max =
- attribute max {
- form.data.date
- }
- input.date.attrs.value =
- attribute value {
- w:string "" | form.data.date
- }
-
- input.elem |= input.date.elem
-
-## Year and Month: <input type='month'>
-
- input.month.elem =
- element input { input.month.attrs }
- input.month.attrs =
- ( common.attrs
- & common-form.attrs
- & input.month.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.month.attrs.min?
- & input.month.attrs.max?
- & input.attrs.step.integer?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & input.month.attrs.value?
- & common.attrs.aria?
- )
- input.month.attrs.type =
- attribute type {
- w:string "month"
- }
- input.month.attrs.min =
- attribute min {
- form.data.month
- }
- input.month.attrs.max =
- attribute max {
- form.data.month
- }
- input.month.attrs.value =
- attribute value {
- w:string "" | form.data.month
- }
-
- input.elem |= input.month.elem
-
-## Time without Time Zone Information: <input type='time'>
-
- input.time.elem =
- element input { input.time.attrs }
- input.time.attrs =
- ( common.attrs
- & common-form.attrs
- & input.time.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.time.attrs.min?
- & input.time.attrs.max?
- & input.attrs.step.float?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & input.time.attrs.value?
- & common.attrs.aria?
- )
- input.time.attrs.type =
- attribute type {
- w:string "time"
- }
- input.time.attrs.min =
- attribute min {
- form.data.time
- }
- input.time.attrs.max =
- attribute max {
- form.data.time
- }
- input.time.attrs.value =
- attribute value {
- w:string "" | form.data.time
- }
-
- input.elem |= input.time.elem
-
-## Year and Week: <input type='week'>
-
- input.week.elem =
- element input { input.week.attrs }
- input.week.attrs =
- ( common.attrs
- & common-form.attrs
- & input.week.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.week.attrs.min?
- & input.week.attrs.max?
- & input.attrs.step.integer?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & input.week.attrs.value?
- & common.attrs.aria?
- )
- input.week.attrs.type =
- attribute type {
- w:string "week"
- }
- input.week.attrs.min =
- attribute min {
- form.data.week
- }
- input.week.attrs.max =
- attribute max {
- form.data.week
- }
- input.week.attrs.value =
- attribute value {
- w:string "" | form.data.week
- }
-
- input.elem |= input.week.elem
-
-## Number: <input type='number'>
-
- input.number.elem =
- element input { input.number.attrs }
- input.number.attrs =
- ( common.attrs
- & common-form.attrs
- & input.number.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.number.attrs.min?
- & input.number.attrs.max?
- & input.attrs.step.float?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & shared-form.attrs.placeholder?
- & input.number.attrs.value?
- & common.attrs.aria?
- )
- input.number.attrs.type =
- attribute type {
- w:string "number"
- }
- input.number.attrs.min =
- attribute min {
- common.data.float
- }
- input.number.attrs.max =
- attribute max {
- common.data.float
- }
- input.number.attrs.value =
- attribute value {
- w:string "" | common.data.float
- }
-
- input.elem |= input.number.elem
-
-## Imprecise Number: <input type='range'>
-
- input.range.elem =
- element input { input.range.attrs }
- input.range.attrs =
- ( common.attrs
- & common-form.attrs
- & input.range.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.range.attrs.min?
- & input.range.attrs.max?
- & input.attrs.step.float?
- & input.range.attrs.value?
- & common.attrs.aria?
- )
- input.range.attrs.type =
- attribute type {
- w:string "range"
- }
- input.range.attrs.min =
- attribute min {
- common.data.float
- }
- input.range.attrs.max =
- attribute max {
- common.data.float
- }
- input.range.attrs.value =
- attribute value {
- common.data.float
- }
-
- input.elem |= input.range.elem
-
-## Email Address: <input type='email'>
-
- input.email.elem =
- element input { input.email.attrs }
- input.email.attrs =
- ( common.attrs
- & common-form.attrs
- & input.email.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & shared-form.attrs.maxlength?
- & shared-form.attrs.pattern?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & shared-form.attrs.size?
- & shared-form.attrs.placeholder?
- & ( ( input.attrs.multiple
- & input.email.attrs.value.multiple?
- )
- | input.email.attrs.value.single?
- )?
- & common.attrs.aria?
- )
- input.email.attrs.type =
- attribute type {
- w:string "email"
- }
- input.email.attrs.value.single =
- attribute value {
- form.data.emailaddress
- }
- input.email.attrs.value.multiple =
- attribute value {
- form.data.emailaddresslist
- }
-
- input.elem |= input.email.elem
-
-## IRI: <input type='url'>
-
- input.url.elem =
- element input { input.url.attrs }
- input.url.attrs =
- ( common.attrs
- & common-form.attrs
- & input.url.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & shared-form.attrs.maxlength?
- & shared-form.attrs.pattern?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & shared-form.attrs.size?
- & shared-form.attrs.placeholder?
- & input.url.attrs.value?
- & common.attrs.aria?
- )
- input.url.attrs.type =
- attribute type {
- w:string "url"
- }
- input.url.attrs.value =
- attribute value {
- w:string "" | common.data.uri.absolute
- }
-
- input.elem |= input.url.elem
-
-## Search: <input type='search'>
-
- input.search.elem =
- element input { input.search.attrs }
- input.search.attrs =
- ( common.attrs
- & common-form.attrs
- & input.search.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & shared-form.attrs.maxlength?
- & shared-form.attrs.pattern?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & shared-form.attrs.size?
- & shared-form.attrs.placeholder?
- & shared-form.attrs.dirname?
- & input.search.attrs.value?
- & common.attrs.aria?
- )
- input.search.attrs.type =
- attribute type {
- w:string "search"
- }
- input.search.attrs.value =
- attribute value {
- form.data.stringwithoutlinebreaks
- }
-
- input.elem |= input.search.elem
-
-## Telephone Number: <input type='tel'>
-
- input.tel.elem =
- element input { input.tel.attrs }
- input.tel.attrs =
- ( common.attrs
- & common-form.attrs
- & input.tel.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & shared-form.attrs.maxlength?
- & shared-form.attrs.pattern?
- & shared-form.attrs.readonly?
- & shared-form.attrs.required?
- & shared-form.attrs.size?
- & shared-form.attrs.placeholder?
- & input.tel.attrs.value?
- & common.attrs.aria?
- )
- input.tel.attrs.type =
- attribute type {
- w:string "tel"
- }
- input.tel.attrs.value =
- attribute value {
- form.data.stringwithoutlinebreaks
- }
-
- input.elem |= input.tel.elem
-
-## Color: <input type='color'>
-
- input.color.elem =
- element input { input.color.attrs }
- input.color.attrs =
- ( common.attrs
- & common-form.attrs
- & input.color.attrs.type
- & input.attrs.autocomplete?
- & shared-form.attrs.autofocus?
- & input.attrs.list?
- & input.color.attrs.value?
- & common.attrs.aria?
- )
- input.color.attrs.type =
- attribute type {
- w:string "color"
- }
- input.color.attrs.value =
- attribute value {
- w:string "" | form.data.color
- }
-
- input.elem |= input.color.elem
-
-## Form Output: <output>
-
- output.elem =
- element output { output.inner & output.attrs }
- output.attrs =
- ( common.attrs
- & common-form.attrs.name?
- & common-form.attrs.form?
- & output.attrs.for?
- & common.attrs.aria?
- )
- output.attrs.for =
- attribute for {
- common.data.idrefs #REVISIT spec says space--not whitespace
- }
- output.inner =
- ( common.inner.phrasing )
-
- common.elem.phrasing |= output.elem
-
-## Text Area: <textarea>, extensions
-
- textarea.attrs.rows-and-cols-wf1.inner &=
- notAllowed
- textarea.attrs.rows-and-cols-wf1 |=
- empty
- textarea.attrs &=
- ( shared-form.attrs.maxlength?
- & shared-form.attrs.autofocus?
- & shared-form.attrs.required?
- & shared-form.attrs.placeholder?
- & shared-form.attrs.dirname?
- & textarea.attrs.rows?
- & ( ( textarea.attrs.wrap.hard
- & textarea.attrs.cols
- )
- | ( textarea.attrs.wrap.soft?
- & textarea.attrs.cols?
- )
- )
- )
- textarea.attrs.wrap.hard =
- attribute wrap {
- w:string "hard"
- }
- textarea.attrs.wrap.soft =
- attribute wrap {
- w:string "soft"
- }
-
-## List of Prefill Data: <datalist>
-
- #REVISIT should the options in datalist be non-selectable?
-
- datalist.elem =
- element datalist { datalist.inner & datalist.attrs }
- datalist.inner =
- ( option.elem* & common.inner.phrasing )
- datalist.attrs =
- ( common.attrs
- & ( common.attrs.aria.role.listbox # aria-multiselectable must be false; check by assertions
- | common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
-
- common.elem.phrasing |= datalist.elem
-
-## Complex Submit Button: <button type='submit'>, extensions
-
- button.submit.attrs &=
- ( shared-form.attrs.formaction?
- & shared-form.attrs.autofocus?
- & shared-form.attrs.formenctype?
- & shared-form.attrs.formmethod?
- & shared-form.attrs.formtarget?
- & shared-form.attrs.formnovalidate?
- )
-
-## Complex Reset Button: <button type='reset'>, extensions
-
- button.reset.attrs &=
- ( shared-form.attrs.autofocus? )
-
-## Complex Push Button: <button type='button'>, extensions
-
- button.button.attrs &=
- ( shared-form.attrs.autofocus? )
-
-## Form: <form>, extensions
- form.attrs &=
- ( form.attrs.novalidate?
- & form.attrs.target?
- & form.attrs.autocomplete?
- )
- form.attrs.novalidate =
- attribute novalidate {
- w:string "novalidate" | w:string ""
- }
- form.attrs.target =
- attribute target {
- common.data.browsing-context-or-keyword
- }
- form.attrs.autocomplete =
- attribute autocomplete {
- w:string "on" | w:string "off"
- }
- # REVISIT should this be case-insensitive in conforming XHTML documents?
- form.attrs.enctype.data |=
- ( w:string "text/plain" )
-
-## Fieldset: <fieldset>, extensions
-
- fieldset.attrs &=
- ( common-form.attrs )
-
-## Label: <label>, extensions
-
- label.attrs &=
- ( common-form.attrs.form? )
-
-## Key-pair generator/input control: <keygen>
-
- keygen.elem =
- element keygen { keygen.inner & keygen.attrs }
- keygen.attrs =
- ( common.attrs
- & keygen.attrs.challenge?
- & keygen.attrs.keytype?
- & shared-form.attrs.autofocus?
- & common-form.attrs?
- & ( common.attrs.aria.role.presentation
- | common.attrs.aria.role.menuitem
- )?
- )
- keygen.attrs.challenge =
- attribute challenge {
- string
- }
- keygen.attrs.keytype =
- attribute keytype {
- w:string "rsa"
- }
- keygen.inner =
- ( empty )
-
- common.elem.phrasing |= keygen.elem
-
-## Selection Menu: <select>, Extensions
-
- select.attrs &=
- ( shared-form.attrs.autofocus?
- & shared-form.attrs.required?
- )
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml1-ruby-rdf-svg-mathml.rnc b/xml/relaxng/src/resources/html5-schema/xhtml1-ruby-rdf-svg-mathml.rnc
new file mode 100644
index 0000000..6258850
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/xhtml1-ruby-rdf-svg-mathml.rnc
@@ -0,0 +1,38 @@
+namespace svg = "http://www.w3.org/2000/svg"
+namespace math = "http://www.w3.org/1998/Math/MathML"
+namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+include "xhtml10/xhtml-strict.rnc"
+include "svg11/svg11-inc.rnc"
+include "inkscape/inkscape.rnc"
+include "mml3/mathml3-inc.rnc"
+include "rdf/rdf.rnc"
+include "xhtml10/ruby.rnc"
+
+head.content &= rdf.elem*
+SVG.metadata.content |= rdf.elem
+
+Inline.class |= svg
+
+Inline.class |= math
+
+SVG.foreignObject.content |=
+ ( math
+ | html
+ | body
+ | Block.mix*
+ )
+
+annotation-xml.model.svg |= svg
+
+annotation-xml.model.xhtml |=
+ ( html
+ | Block.class
+ | Inline.class
+ )
+
+# in our integration, <mtext> is the only MathML "token element" that can
+# contain HTML element content; the <mi>, <mn>, <mo> and <ms> elements
+# cannot; see http://www.w3.org/Bugs/Public/show_bug.cgi?id=9859#c8 for a
+# rationale
+mtext.content |= Inline.class
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5-all.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5-all.rnc
new file mode 100644
index 0000000..43bf9ef
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/xhtml5-all.rnc
@@ -0,0 +1,3 @@
+default namespace = "http://www.w3.org/1999/xhtml"
+include "xhtml5-svg-mathml.rnc"
+include "html5/xhtml5full-xhtml-rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5-no-microdata.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5-no-microdata.rnc
new file mode 100644
index 0000000..355fe83
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/xhtml5-no-microdata.rnc
@@ -0,0 +1,2 @@
+include "xhtml5-svg-mathml.rnc"
+include "html5/xhtml5full-xhtml-no-microdata.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5-rdfalite-w3c.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5-rdfalite-w3c.rnc
new file mode 100644
index 0000000..1b16f37
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/xhtml5-rdfalite-w3c.rnc
@@ -0,0 +1,2 @@
+include "xhtml5-svg-mathml.rnc"
+include "html5/xhtml5full-xhtml-rdfalite.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5-rdfalite.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5-rdfalite.rnc
new file mode 100644
index 0000000..1b16f37
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/xhtml5-rdfalite.rnc
@@ -0,0 +1,2 @@
+include "xhtml5-svg-mathml.rnc"
+include "html5/xhtml5full-xhtml-rdfalite.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc
new file mode 100644
index 0000000..74f1886
--- /dev/null
+++ b/xml/relaxng/src/resources/html5-schema/xhtml5-svg-mathml.rnc
@@ -0,0 +1,35 @@
+namespace svg = "http://www.w3.org/2000/svg"
+namespace math = "http://www.w3.org/1998/Math/MathML"
+namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+include "svg11/svg11-tiny-inc.rnc"
+include "inkscape/inkscape.rnc"
+include "mml3/mathml3-inc.rnc"
+include "rdf/rdf.rnc"
+
+common.elem.metadata |= rdf.elem
+SVG.metadata.content |= rdf.elem
+
+common.elem.phrasing |= svg
+
+common.elem.phrasing |= math
+
+SVG.foreignObject.content |=
+ ( math
+ | html.elem
+ | body.elem
+ | common.inner.flow
+ )
+
+annotation-xml.model.svg |= svg
+
+annotation-xml.model.xhtml |=
+ ( html.elem
+ | common.elem.flow
+ )
+
+# in our integration, <mtext> is the only MathML "token element" that can
+# contain HTML element content; the <mi>, <mn>, <mo> and <ms> elements
+# cannot; see http://www.w3.org/Bugs/Public/show_bug.cgi?id=9859#c8 for a
+# rationale
+mtext.content |= common.elem.phrasing
diff --git a/xml/relaxng/src/resources/html5-schema/xhtml5.rnc b/xml/relaxng/src/resources/html5-schema/xhtml5.rnc
index 2d17f9f..43bf9ef 100644
--- a/xml/relaxng/src/resources/html5-schema/xhtml5.rnc
+++ b/xml/relaxng/src/resources/html5-schema/xhtml5.rnc
@@ -1,44 +1,3 @@
default namespace = "http://www.w3.org/1999/xhtml"
-# #####################################################################
-## RELAX NG Schema for XHTML 5 #
-# #####################################################################
-
- # To validate an XHTML 5 document, you must first validate against #
- # this schema and then ALSO validate against assertions.sch #
-
-# #####################################################################
-## Schema Framework & Parameters
-
-include "common.rnc" {
- # XHTML flavor #
- XMLonly = empty
- HTMLonly = notAllowed
- # HTML 4 compat #
- v5only = empty
-}
-
-include "common-ext.rnc"
-
-# #####################################################################
-## Language Definitions
-
-start = html.elem
-
-include "meta.rnc"
-include "meta-ext.rnc"
-include "phrase.rnc"
-include "block.rnc"
-include "sectional.rnc"
-include "structural.rnc"
-include "revision.rnc"
-include "embed.rnc"
-include "ruby.rnc"
-include "media.rnc"
-include "core-scripting.rnc"
-include "core-scripting-ext.rnc"
-include "tables.rnc"
-include "form-datatypes.rnc"
-include "web-forms.rnc"
-include "web-forms2.rnc"
-include "applications.rnc"
-include "data.rnc"
+include "xhtml5-svg-mathml.rnc"
+include "html5/xhtml5full-xhtml-rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/html5charref.rb b/xml/relaxng/src/resources/html5charref.rb
similarity index 100%
rename from xml/relaxng/src/resources/html5-schema/html5charref.rb
rename to xml/relaxng/src/resources/html5charref.rb
diff --git a/xml/relaxng/src/resources/patches/0001_html5.patch b/xml/relaxng/src/resources/patches/0001_html5.patch
new file mode 100644
index 0000000..b462b7c
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0001_html5.patch
@@ -0,0 +1,27 @@
+--- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/html5full-rdfa.rnc 2014-01-24 12:19:52.000000000 +0400
++++ html5/html5full-rdfa.rnc 2014-01-24 13:28:00.000000000 +0400
+@@ -6,13 +6,17 @@
+ nonHTMLizable = notAllowed
+ nonRoundtrippable = notAllowed
+ }
++include "common-ext.rnc"
++
+ start = html.elem
+ include "phrase.rnc"
+ include "block.rnc"
+ include "sectional.rnc"
+ include "revision.rnc"
+ include "embed.rnc"
++include "embed-ext.rnc"
+ include "core-scripting.rnc"
++include "core-scripting-ext.rnc"
+ include "structural.rnc"
+ include "ruby.rnc"
+ include "media.rnc"
+@@ -33,5 +37,6 @@
+ )
+ )
+ }
++include "meta-ext.rnc"
+ include "microdata.rnc"
+ include "rdfa.rnc"
diff --git a/xml/relaxng/src/resources/patches/0002_xhtml5.patch b/xml/relaxng/src/resources/patches/0002_xhtml5.patch
new file mode 100644
index 0000000..13a53ff
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0002_xhtml5.patch
@@ -0,0 +1,20 @@
+--- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/xhtml5full-xhtml-rdfa.rnc 2014-01-24 12:19:52.000000000 +0400
++++ html5/xhtml5full-xhtml-rdfa.rnc 2014-01-25 11:13:41.000000000 +0400
+@@ -4,13 +4,17 @@
+ HTMLonly = notAllowed
+ v5only = empty
+ }
++include "common-ext.rnc"
++
+ start = html.elem
+ include "phrase.rnc"
+ include "block.rnc"
+ include "sectional.rnc"
+ include "revision.rnc"
+ include "embed.rnc"
++include "embed-ext.rnc"
+ include "core-scripting.rnc"
++include "core-scripting-ext.rnc"
+ include "structural.rnc"
+ include "ruby.rnc"
+ include "media.rnc"
diff --git a/xml/relaxng/src/resources/patches/0003_hgroup.patch b/xml/relaxng/src/resources/patches/0003_hgroup.patch
new file mode 100644
index 0000000..714063b
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0003_hgroup.patch
@@ -0,0 +1,34 @@
+--- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/sectional.rnc 2014-01-24 12:18:24.000000000 +0400
++++ html5/sectional.rnc 2014-01-24 14:06:03.000000000 +0400
+@@ -107,31 +107,6 @@
+
+ common.elem.flow |= h6.elem
+
+-## Heading Group: <hgroup>
+-
+- hgroup.elem =
+- element hgroup { hgroup.inner & hgroup.attrs } & nonW3C
+- hgroup.attrs =
+- ( common.attrs
+- & ( common.attrs.aria.implicit.heading
+- | common.attrs.aria.role.heading
+- | common.attrs.aria.role.tab
+- | common.attrs.aria.role.presentation
+- )?
+- )
+- hgroup.inner =
+- ( ( h1.elem
+- | h2.elem
+- | h3.elem
+- | h4.elem
+- | h5.elem
+- | h6.elem
+- )
+- & common.elem.script-supporting*
+- )+
+-
+- common.elem.flow |= hgroup.elem
+-
+ # #####################################################################
+ ## Section Meta
+
diff --git a/xml/relaxng/src/resources/patches/0004_ping.patch b/xml/relaxng/src/resources/patches/0004_ping.patch
new file mode 100644
index 0000000..6f825ac
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0004_ping.patch
@@ -0,0 +1,13 @@
+--- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/phrase.rnc 2014-01-24 12:18:24.000000000 +0400
++++ html5/phrase.rnc 2014-01-24 14:08:26.000000000 +0400
+@@ -76,10 +76,6 @@
+ attribute type {
+ common.data.mimetype
+ }
+- shared-hyperlink.attrs.ping =
+- attribute ping {
+- common.data.uris
+- } & v5only & nonW3C
+
+ ## Emphatic Stress: <em>
+
diff --git a/xml/relaxng/src/resources/patches/0005_html5_namespace.patch b/xml/relaxng/src/resources/patches/0005_html5_namespace.patch
new file mode 100644
index 0000000..31748c4
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0005_html5_namespace.patch
@@ -0,0 +1,6 @@
+--- /Users/denofevil/Code/sandbox/checker/validator/schema/html5-all.rnc 2014-01-24 12:18:54.000000000 +0400
++++ html5-all.rnc 2014-01-24 15:46:08.000000000 +0400
+@@ -1,2 +1,3 @@
++default namespace = "http://www.w3.org/1999/xhtml"
+ include "html5-svg-mathml.rnc"
+ include "html5/html5full-rdfa.rnc"
diff --git a/xml/relaxng/src/resources/patches/0006_xhtml5_namespace.patch b/xml/relaxng/src/resources/patches/0006_xhtml5_namespace.patch
new file mode 100644
index 0000000..1d6d7c9
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0006_xhtml5_namespace.patch
@@ -0,0 +1,6 @@
+--- /Users/denofevil/Code/sandbox/checker/validator/schema/xhtml5-all.rnc 2014-01-24 12:18:54.000000000 +0400
++++ xhtml5-all.rnc 2014-01-24 15:46:01.000000000 +0400
+@@ -1,2 +1,3 @@
++default namespace = "http://www.w3.org/1999/xhtml"
+ include "xhtml5-svg-mathml.rnc"
+ include "html5/xhtml5full-xhtml-rdfa.rnc"
diff --git a/xml/relaxng/src/resources/patches/0007_html5_svg_tiny.patch b/xml/relaxng/src/resources/patches/0007_html5_svg_tiny.patch
new file mode 100644
index 0000000..6a3cc10
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0007_html5_svg_tiny.patch
@@ -0,0 +1,11 @@
+--- /Users/denofevil/Code/sandbox/checker/validator/schema/html5-svg-mathml.rnc 2014-01-24 12:18:54.000000000 +0400
++++ html5-svg-mathml.rnc 2014-01-25 15:32:10.000000000 +0400
+@@ -1,7 +1,7 @@
+ namespace svg = "http://www.w3.org/2000/svg"
+ namespace math = "http://www.w3.org/1998/Math/MathML"
+
+-include "svg11/svg11-inc.rnc"
++include "svg11/svg11-tiny-inc.rnc"
+ include "mml3/mathml3-inc.rnc"
+
+ common.elem.phrasing |= svg
diff --git a/xml/relaxng/src/resources/patches/0008_xhtml5_svg_tiny.patch b/xml/relaxng/src/resources/patches/0008_xhtml5_svg_tiny.patch
new file mode 100644
index 0000000..773c896
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0008_xhtml5_svg_tiny.patch
@@ -0,0 +1,11 @@
+--- /Users/denofevil/Code/sandbox/checker/validator/schema/xhtml5-svg-mathml.rnc 2014-01-24 12:18:54.000000000 +0400
++++ xhtml5-svg-mathml.rnc 2014-01-25 15:50:41.000000000 +0400
+@@ -2,7 +2,7 @@
+ namespace math = "http://www.w3.org/1998/Math/MathML"
+ namespace rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+
+-include "svg11/svg11-inc.rnc"
++include "svg11/svg11-tiny-inc.rnc"
+ include "inkscape/inkscape.rnc"
+ include "mml3/mathml3-inc.rnc"
+ include "rdf/rdf.rnc"
diff --git a/xml/relaxng/src/resources/patches/0009_html_remove_microdata.patch b/xml/relaxng/src/resources/patches/0009_html_remove_microdata.patch
new file mode 100644
index 0000000..8d2ff7d
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0009_html_remove_microdata.patch
@@ -0,0 +1,9 @@
+--- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/html5full-rdfa.rnc 2014-01-24 12:19:52.000000000 +0400
++++ html5/html5full-rdfa.rnc 2014-01-26 16:54:44.000000000 +0400
+@@ -37,6 +37,5 @@
+ )
+ )
+ }
+ include "meta-ext.rnc"
+-include "microdata.rnc"
+ include "rdfa.rnc"
diff --git a/xml/relaxng/src/resources/patches/0010_xhtml_remove_microdata.patch b/xml/relaxng/src/resources/patches/0010_xhtml_remove_microdata.patch
new file mode 100644
index 0000000..dcd0834
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/0010_xhtml_remove_microdata.patch
@@ -0,0 +1,8 @@
+--- /Users/denofevil/Code/sandbox/checker/syntax/relaxng/xhtml5full-xhtml-rdfa.rnc 2014-01-24 12:19:52.000000000 +0400
++++ html5/xhtml5full-xhtml-rdfa.rnc 2014-01-26 16:54:54.000000000 +0400
+@@ -35,5 +35,4 @@
+ )
+ )
+ }
+-include "microdata.rnc"
+ include "rdfa.rnc"
diff --git a/xml/relaxng/src/resources/html5-schema/common-ext.rnc b/xml/relaxng/src/resources/patches/common-ext.rnc
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/common-ext.rnc
copy to xml/relaxng/src/resources/patches/common-ext.rnc
diff --git a/xml/relaxng/src/resources/html5-schema/core-scripting-ext.rnc b/xml/relaxng/src/resources/patches/core-scripting-ext.rnc
similarity index 100%
copy from xml/relaxng/src/resources/html5-schema/core-scripting-ext.rnc
copy to xml/relaxng/src/resources/patches/core-scripting-ext.rnc
diff --git a/xml/relaxng/src/resources/patches/embed-ext.rnc b/xml/relaxng/src/resources/patches/embed-ext.rnc
new file mode 100644
index 0000000..9b153c6
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/embed-ext.rnc
@@ -0,0 +1,3 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+embed.attrs |= common.attr.anything
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/patches/meta-ext.rnc b/xml/relaxng/src/resources/patches/meta-ext.rnc
new file mode 100644
index 0000000..cc9a44f
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/meta-ext.rnc
@@ -0,0 +1,62 @@
+datatypes w = "http://whattf.org/datatype-draft"
+
+## "Content-Language" pragma directive: <meta http-equiv='Content-Language'>
+
+ meta.http-equiv.content-language.elem =
+ element meta { meta.inner & meta.http-equiv.content-language.attrs }
+ meta.http-equiv.content-language.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.content-language
+ & meta.http-equiv.attrs.content.content-language
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.content-language =
+ attribute http-equiv {
+ w:string "content-language"
+ }
+ meta.http-equiv.attrs.content.content-language =
+ attribute content {
+ common.data.string
+ }
+
+ common.elem.metadata |= meta.http-equiv.content-language.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+## "X-UA-Compatible" pragma directive: <meta http-equiv='X-UA-Compatible'>
+
+ meta.http-equiv.x-ua-compatible.elem =
+ element meta { meta.inner & meta.http-equiv.x-ua-compatible.attrs }
+ meta.http-equiv.x-ua-compatible.attrs =
+ ( common.attrs.basic
+ & common.attrs.i18n
+ & common.attrs.present
+ & common.attrs.other
+ & meta.http-equiv.attrs.http-equiv.x-ua-compatible
+ & meta.http-equiv.attrs.content.x-ua-compatible
+ & ( common.attrs.aria.role.presentation
+ | common.attrs.aria.role.menuitem
+ )?
+ )
+ meta.http-equiv.attrs.http-equiv.x-ua-compatible =
+ attribute http-equiv {
+ w:string "x-ua-compatible"
+ }
+ meta.http-equiv.attrs.content.x-ua-compatible =
+ attribute content {
+ common.data.string
+ }
+
+ common.elem.metadata |= meta.http-equiv.x-ua-compatible.elem # not quite right per spec
+ # if the definition is
+ # reused in another language
+
+ html.inner |= (
+ head.inner,
+ body.inner
+ )
\ No newline at end of file
diff --git a/xml/relaxng/src/resources/patches/patch_build.patch b/xml/relaxng/src/resources/patches/patch_build.patch
new file mode 100644
index 0000000..ba4c307
--- /dev/null
+++ b/xml/relaxng/src/resources/patches/patch_build.patch
@@ -0,0 +1,77 @@
+diff -r dd84d714a0da build.py
+--- a/build.py Fri Oct 25 13:00:39 2013 +0900
++++ b/build.py Fri Jan 24 13:53:06 2014 +0400
+@@ -147,8 +147,8 @@
+
+ moduleNames = [
+ "syntax",
+- "util",
+- "xmlparser",
++ # "util",
++ # "xmlparser",
+ "validator",
+ ]
+
+@@ -875,19 +875,19 @@
+ downloadDependency(url, md5sum)
+
+ def buildAll():
+- if 'JAVA_HOME' not in os.environ:
+- print "Error: The JAVA_HOME environment variable is not set."
+- print "Set the JAVA_HOME environment variable to the pathname of the directory where your JDK is installed."
+- sys.exit(1)
+- prepareLocalEntityJar()
+- buildJing()
+- buildDatatypeLibrary()
+- buildNonSchema()
++ # if 'JAVA_HOME' not in os.environ:
++ # print "Error: The JAVA_HOME environment variable is not set."
++ # print "Set the JAVA_HOME environment variable to the pathname of the directory where your JDK is installed."
++ # sys.exit(1)
++ # prepareLocalEntityJar()
++ # buildJing()
++ # buildDatatypeLibrary()
++ # buildNonSchema()
+ buildSchemaDrivers()
+- buildHtmlParser()
+- buildUtil()
+- buildXmlParser()
+- buildValidator()
++ # buildHtmlParser()
++ # buildUtil()
++ # buildXmlParser()
++ # buildValidator()
+
+ def hgCloneOrUpdate(mod, baseUrl):
+ if os.path.exists(mod):
+@@ -925,18 +925,18 @@
+ # XXX root dir
+ for mod in moduleNames:
+ hgCloneOrUpdate(mod, hgRoot)
+- gitCloneOrUpdate("nu-validator-site", gitRoot)
+- runCmd('"%s" co http://jing-trang.googlecode.com/svn/branches/validator-nu jing-trang' % (svnCmd))
+- hgCloneOrUpdate("htmlparser", parserHgRoot)
+- testsRemote = "https://github.com/validator/tests.git"
+- testsBranch = "master"
+- testsDir = "tests"
+- if os.path.exists(testsDir):
+- os.chdir(testsDir)
+- runCmd('"%s" pull %s %s' % (gitCmd, testsRemote, testsBranch))
+- os.chdir("..")
+- else:
+- runCmd('"%s" clone %s %s' % (gitCmd, testsRemote, testsDir))
++ # gitCloneOrUpdate("nu-validator-site", gitRoot)
++ # runCmd('"%s" co http://jing-trang.googlecode.com/svn/branches/validator-nu jing-trang' % (svnCmd))
++ # hgCloneOrUpdate("htmlparser", parserHgRoot)
++ # testsRemote = "https://github.com/validator/tests.git"
++ # testsBranch = "master"
++ # testsDir = "tests"
++ # if os.path.exists(testsDir):
++ # os.chdir(testsDir)
++ # runCmd('"%s" pull %s %s' % (gitCmd, testsRemote, testsBranch))
++ # os.chdir("..")
++ # else:
++ # runCmd('"%s" clone %s %s' % (gitCmd, testsRemote, testsDir))
+
+ def selfUpdate():
+ hgCloneOrUpdate("build", hgRoot)
diff --git a/xml/relaxng/src/resources/update_html5_schema.sh b/xml/relaxng/src/resources/update_html5_schema.sh
new file mode 100755
index 0000000..2991298
--- /dev/null
+++ b/xml/relaxng/src/resources/update_html5_schema.sh
@@ -0,0 +1,57 @@
+#! /bin/bash
+
+set -o errexit
+
+ROOT=$PWD
+PATCHES="$ROOT/patches"
+
+rm -rf temp
+rm -rf result
+mkdir temp
+cd temp
+
+echo ">>>>> Preparing validator build"
+hg clone https://bitbucket.org/validator/build build
+cd build
+hg import "$PATCHES/patch_build.patch" --no-commit
+cd ..
+
+echo
+echo ">>>>> Cloning validator"
+python build/build.py checkout
+
+echo
+echo ">>>>> Building schema drivers"
+python build/build.py build
+
+echo
+echo ">>>>> Collecting schemas"
+cd ..
+mkdir result
+mkdir result/html5
+cp temp/syntax/relaxng/*.rnc result/html5
+rsync -r --include=*.rnc temp/validator/schema/* result
+rm -rf result/xhtml10
+ruby html5charref.rb > result/html5chars.ent
+
+echo
+echo ">>>>> Patching html5 schema"
+cp patches/*.rnc result/html5
+cd result
+for f in `ls $PATCHES`
+do
+ if [[ "$f" == 0*\.* ]]
+ then
+ patch -p0 -u < "$PATCHES/$f"
+ fi
+done
+cd ..
+
+echo
+echo ">>>>> Moving items in place"
+cp result/html5-all.rnc result/html5.rnc
+cp result/xhtml5-all.rnc result/xhtml5.rnc
+cp temp/syntax/relaxng/LICENSE result
+rm -rf html5-schema
+mv result html5-schema
+rm -rf temp
diff --git a/xml/relaxng/test/org/intellij/plugins/relaxNG/RngHtml5CompletionTest.java b/xml/relaxng/test/org/intellij/plugins/relaxNG/RngHtml5CompletionTest.java
index 4deb63f..55db78a 100644
--- a/xml/relaxng/test/org/intellij/plugins/relaxNG/RngHtml5CompletionTest.java
+++ b/xml/relaxng/test/org/intellij/plugins/relaxNG/RngHtml5CompletionTest.java
@@ -15,8 +15,6 @@
*/
package org.intellij.plugins.relaxNG;
-import com.intellij.javaee.ExternalResourceManagerImpl;
-
/**
* @author Eugene.Kudelevsky
*/
@@ -69,7 +67,7 @@
}
public void testHtml5_11() throws Throwable {
- doTestCompletion("html5_11");
+ myTestFixture.testCompletionTyping("/html5_11.xml", "\n", "/html5_11_after.xml");
}
public void testHtml5_12() throws Throwable {
@@ -77,7 +75,7 @@
}
public void testHtml5_13() throws Throwable {
- doTestCompletion("html5_13");
+ myTestFixture.testCompletionTyping("/html5_13.xml", "\n", "/html5_13_after.xml");
}
public void testHtml5_14() throws Throwable {
@@ -85,7 +83,7 @@
}
public void testHtml5_15() throws Throwable {
- doTestCompletion("html5_15");
+ myTestFixture.testCompletionTyping("/html5_15.xml", "\n", "/html5_15_after.xml");
}
public void testHtml5_16() throws Throwable {
diff --git a/xml/relaxng/testData/completion/html5_17.xml b/xml/relaxng/testData/completion/html5_17.xml
index 765c5bb..6cbe695 100644
--- a/xml/relaxng/testData/completion/html5_17.xml
+++ b/xml/relaxng/testData/completion/html5_17.xml
@@ -3,6 +3,7 @@
<title></title>
</head>
<body>
-<command radiogr<caret>
+<menu>
+<menuitem radiogr<caret>
</body>
</html>
\ No newline at end of file
diff --git a/xml/relaxng/testData/completion/html5_17_after.xml b/xml/relaxng/testData/completion/html5_17_after.xml
index c8ffd1b..99f595c 100644
--- a/xml/relaxng/testData/completion/html5_17_after.xml
+++ b/xml/relaxng/testData/completion/html5_17_after.xml
@@ -3,6 +3,7 @@
<title></title>
</head>
<body>
-<command radiogroup=""
+<menu>
+<menuitem radiogroup=""
</body>
</html>
\ No newline at end of file
diff --git a/xml/tests/src/com/intellij/codeInsight/SoftWrapTest.java b/xml/tests/src/com/intellij/codeInsight/SoftWrapTest.java
index 4de8e70..1771a24 100644
--- a/xml/tests/src/com/intellij/codeInsight/SoftWrapTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/SoftWrapTest.java
@@ -15,9 +15,7 @@
*/
package com.intellij.codeInsight;
-import com.intellij.openapi.editor.Editor;
-import com.intellij.openapi.editor.impl.SoftWrapModelImpl;
-import com.intellij.openapi.editor.impl.softwrap.mapping.SoftWrapApplianceManager;
+import com.intellij.testFramework.EditorTestUtil;
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
/**
@@ -29,15 +27,7 @@
public void testSoftWrapInInjection() throws Exception {
myFixture.configureByFile("softWrap.html");
- Editor editor = myFixture.getEditor();
- editor.getSettings().setUseSoftWraps(true);
- ((SoftWrapModelImpl)editor.getSoftWrapModel()).getApplianceManager().setWidthProvider(new SoftWrapApplianceManager.VisibleAreaWidthProvider() {
- @Override
- public int getVisibleAreaWidth() {
- return 600;
- }
- });
-
+ EditorTestUtil.configureSoftWraps(myFixture.getEditor(), 83);
myFixture.type('j');
myFixture.checkResultByFile("softWrap_after.html");
}
diff --git a/xml/tests/src/com/intellij/codeInsight/XmlEventsTest.java b/xml/tests/src/com/intellij/codeInsight/XmlEventsTest.java
index 7b2b211..14d130b 100644
--- a/xml/tests/src/com/intellij/codeInsight/XmlEventsTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/XmlEventsTest.java
@@ -46,7 +46,7 @@
final Listener listener = new Listener(model.getModelAspect(XmlAspect.class));
model.addModelListener(listener);
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
tagFromText.setAttribute("a", "b");
@@ -63,9 +63,7 @@
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>aaa</a>");
final XmlTag otherTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>");
final XmlText xmlText = tagFromText.getValue().getTextElements()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlText.insertAtOffset(otherTag, 2);
}
});
@@ -79,9 +77,7 @@
model.addModelListener(listener);
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>aaa</a>");
final XmlText xmlText = tagFromText.getValue().getTextElements()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlText.insertText("bb", 2);
}
});
@@ -94,9 +90,7 @@
final Listener listener = new Listener(model.getModelAspect(XmlAspect.class));
model.addModelListener(listener);
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>a </a>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
tagFromText.addAfter(tagFromText.getValue().getTextElements()[0], tagFromText.getValue().getTextElements()[0]);
}
});
@@ -109,9 +103,7 @@
final Listener listener = new Listener(model.getModelAspect(XmlAspect.class));
model.addModelListener(listener);
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a>aaa</a>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
tagFromText.delete();
}
});
@@ -171,9 +163,7 @@
final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(text);
final XmlAttribute attribute = tag.getAttribute("name", null);
assert attribute != null;
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
attribute.setValue("new");
}
});
@@ -192,18 +182,11 @@
final PsiFileImpl containingFile = (PsiFileImpl)tagFromText.getContainingFile();
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(getProject());
final Document document = documentManager.getDocument(containingFile);
- CommandProcessor.getInstance().executeCommand(getProject(), new Runnable() {
- @Override
- public void run() {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
document.insertString(positionToInsert, stringToInsert);
documentManager.commitDocument(document);
}
});
- }
- }, "", null);
assertFileTextEquals(getTestName(false) + ".txt", listener.getEventString());
}
diff --git a/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java b/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java
index 52d0465..19385dd 100644
--- a/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/XmlTagTest.java
@@ -87,7 +87,7 @@
final XmlTag childTag = rootTag.createChildTag("b", "bNamespace", null, true);
assertEquals("bNamespace", childTag.getNamespace());
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
XmlTag beanTag = (XmlTag)rootTag.add(childTag);
@@ -99,9 +99,7 @@
public void testDeleteTag() throws Throwable {
XmlTag aTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a><b/> </a>");
final XmlTag bTag = aTag.findFirstSubTag("b");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
bTag.delete();
}
});
@@ -112,9 +110,7 @@
public void testReplaceTag() throws Throwable {
final XmlTag aTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<a><b/></a>");
final XmlTag bTag = aTag.findFirstSubTag("b");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
PsiElement cTag = bTag.replace(XmlElementFactory.getInstance(getProject()).createTagFromText("<c/>"));
assertEquals(1, aTag.getSubTags().length);
assertEquals(cTag, aTag.getSubTags()[0]);
@@ -127,9 +123,7 @@
final XmlTag aTag = elementFactory.createTagFromText("<a>1</a>");
final XmlText displayText = elementFactory.createDisplayText("2");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
final PsiElement psiElement = aTag.addAfter(displayText, aTag.getValue().getChildren()[0]);
assertEquals(psiElement.getContainingFile(), aTag.getContainingFile());
}
@@ -137,9 +131,7 @@
}
public void testWhitespaceInsideTag() throws Exception {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
XmlElementFactory.getInstance(getProject()).createTagFromText("<p/>").getValue().setText("\n");
}
});
@@ -149,9 +141,7 @@
XmlFile xhtmlFile = (XmlFile)PsiFileFactory.getInstance(getProject()).createFileFromText("dummy.xhtml", "<html/>");
final XmlTag rootTag = xhtmlFile.getDocument().getRootTag();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
rootTag.setAttribute("foo", "bar");
}
});
@@ -163,9 +153,7 @@
public void testSetAttribute() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html/>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
rootTag.setAttribute("foo", "bar");
}
});
@@ -179,9 +167,7 @@
public void testSetAttributeWithQuotes() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html/>");
final String value = "a \"b\" c";
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
rootTag.setAttribute("foo", value);
}
});
@@ -195,9 +181,7 @@
public void testSetAttributeWithQuotes2() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html/>");
final String value = "'a \"b\" c'";
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
rootTag.setAttribute("foo", value);
}
});
@@ -227,9 +211,7 @@
public void testSetAttributeWithNamespaces() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<ns:tag xmlns:ns=\"xxx\"/>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
rootTag.setAttribute("foo", "", "bar");
}
});
@@ -243,9 +225,7 @@
public void testTextEdit1() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>aaa</html>");
final XmlText xmlText = rootTag.getValue().getTextElements()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlText.removeText(0, 3);
}
});
@@ -255,9 +235,7 @@
public void testTextEdit2() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>a<a</html>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
rootTag.getValue().getTextElements()[0].removeText(0, 3);
}
});
@@ -268,9 +246,7 @@
public void testTextEdit3() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>a<a</html>");
final XmlText xmlText = rootTag.getValue().getTextElements()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlText.removeText(1, 2);
}
});
@@ -282,9 +258,7 @@
public void testTextEdit4() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>aaa</html>");
final XmlText xmlText = rootTag.getValue().getTextElements()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlText.removeText(1, 2);
}
});
@@ -319,9 +293,7 @@
public void testTextEdit6() throws Exception {
final XmlTag rootTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<html>a<b>1</b>c</html>");
final XmlTag xmlTag = rootTag.findFirstSubTag("b");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlTag.delete();
}
});
@@ -331,9 +303,7 @@
public void testBrace() throws Exception {
final XmlTag tagFromText = XmlElementFactory.getInstance(getProject()).createTagFromText("<a/>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
tagFromText.getValue().setText("<");
}
});
@@ -436,9 +406,7 @@
final XmlTagChild child = tag.getValue().getChildren()[0];
assertTrue(child instanceof XmlText && child.getText().equals("234"));
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
assertNotNull(tag.getParent().addBefore(child, tag));
tag.delete();
}
@@ -456,9 +424,7 @@
final XmlTagChild child = tag.getValue().getChildren()[0];
assertTrue(child instanceof XmlText && child.getText().equals("234"));
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
assertNotNull(tag.getParent().addBefore(child, tag));
tag.delete();
}
@@ -471,9 +437,7 @@
public void testDisplayText() throws Throwable {
final XmlTag tag = XmlElementFactory.getInstance(getProject()).createTagFromText(" <foo/>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
tag.add(XmlElementFactory.getInstance(getProject()).createDisplayText("aaa\nbbb"));
}
});
@@ -489,9 +453,7 @@
final XmlTagChild[] tagElements = tagB.getValue().getChildren();
final PsiElement parent = tagB.getParent();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
PsiElement first = parent.addBefore(tagElements[0], tagB);
assertNotNull(first);
}
@@ -545,9 +507,7 @@
final XmlFile file = (XmlFile)PsiFileFactory.getInstance(getProject())
.createFileFromText("test.xml", "<a>\n <a>\n <b>\n hasgdgasjdgasdg asgdjhasgd</b>\n </a>\n</a>");
final XmlTag tagB = file.getDocument().getRootTag();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
tagB.getSubTags()[0].getSubTags()[0].delete();
}
});
diff --git a/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java b/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java
index 0d1a113..89cc126 100644
--- a/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/XmlTagWriteTest.java
@@ -16,6 +16,7 @@
package com.intellij.codeInsight;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.psi.XmlElementFactory;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlText;
@@ -30,7 +31,7 @@
public void test1() throws IncorrectOperationException {
XmlElementFactory elementFactory = XmlElementFactory.getInstance(getProject());
final XmlTag xmlTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<tag1/>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
xmlTag.add(xmlTag.createChildTag("tag2", XmlUtil.EMPTY_URI, null, false));
@@ -47,9 +48,7 @@
public void test2() throws IncorrectOperationException {
final XmlTag xmlTag = XmlElementFactory.getInstance(getProject()).createTagFromText("<tag1></tag1>");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
xmlTag.add(xmlTag.createChildTag("tag2", XmlUtil.EMPTY_URI, null, false));
}
});
diff --git a/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java b/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java
index f36fa46..86f5936 100644
--- a/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/XmlWrongClosingTagNameInspectionTest.java
@@ -1,6 +1,6 @@
package com.intellij.codeInsight;
-import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase;
+import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NotNull;
@@ -9,7 +9,7 @@
/**
* @author spleaner
*/
-public class XmlWrongClosingTagNameInspectionTest extends LightQuickFixTestCase {
+public class XmlWrongClosingTagNameInspectionTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java b/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java
index 5e2f202..05eb6a3 100644
--- a/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/completion/XmlCompletionTest.java
@@ -677,6 +677,10 @@
myFixture.testCompletionVariants("Substitute/test.xml", "b:instance", "instance");
}
+ public void testAfterPrefix() throws Exception {
+ myFixture.testCompletion("Substitute/testAfterPrefix.xml", "Substitute/testAfterPrefix_after.xml", "Substitute/schema-a.xsd", "Substitute/schema-b.xsd");
+ }
+
public void testEnumeratedTagValue() throws Exception {
myFixture.configureByFile("tagValue/enumerated.xsd");
myFixture.testCompletionVariants("tagValue/completeEnum.xml", "none", "standard");
diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java
index 9f5f3cf..774eb1a 100644
--- a/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/daemon/XmlHighlightingTest.java
@@ -41,6 +41,7 @@
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.editor.EditorModificationUtil;
@@ -387,7 +388,7 @@
try {
doDoTest(true,true);
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
@Override
public void run() {
myEditor.getDocument().insertString(myEditor.getDocument().getCharsSequence().toString().indexOf("?>") + 2, "\n");
@@ -547,9 +548,7 @@
final XmlAttribute attribute = t.getAttribute("name", null);
final XmlAttributeValue valueElement = attribute.getValueElement();
final PsiReference nameReference = valueElement.getReferences()[0];
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
nameReference.handleElementRename("zzz");
}
});
@@ -562,9 +561,7 @@
public void testExternalValidatorOnValidXmlWithNamespacesNotSetup() throws Exception {
final ExternalResourceManagerEx instanceEx = ExternalResourceManagerEx.getInstanceEx();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
instanceEx.addIgnoredResource("http://xml.apache.org/axis/wsdd2/");
instanceEx.addIgnoredResource("http://xml.apache.org/axis/wsdd2/providers/java");
instanceEx.addIgnoredResource("http://soapinterop.org/xsd2");
@@ -578,18 +575,14 @@
public void testExternalValidatorOnValidXmlWithNamespacesNotSetup2() throws Exception {
final ExternalResourceManagerEx instanceEx = ExternalResourceManagerEx.getInstanceEx();
try {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
instanceEx.addIgnoredResource("");
}
});
doTest(getFullRelativeTestName(".xml"), true, false);
} finally {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
instanceEx.removeIgnoredResource("");
}
});
@@ -881,7 +874,7 @@
public void testXsiSchemaLocation2() throws Exception {
doTest(
- new VirtualFile[] {
+ new VirtualFile[]{
getVirtualFile(getFullRelativeTestName()),
getVirtualFile(BASE_PATH + getTestName(false) + "_1.xsd"),
getVirtualFile(BASE_PATH + getTestName(false) + "_2.xsd"),
@@ -1064,9 +1057,7 @@
}
public void testIgnoredNamespaceHighlighting() throws Exception {
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
ExternalResourceManagerEx.getInstanceEx().addIgnoredResource("http://ignored/uri");
}
});
@@ -1242,8 +1233,7 @@
doDoTest(true, false);
final String text = myEditor.getDocument().getText();
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
myEditor.getSelectionModel().setSelection(0, myEditor.getDocument().getTextLength());
}
@@ -1419,9 +1409,7 @@
final Editor schemaEditor = allEditors[0] == myEditor ? allEditors[1]:allEditors[0];
final String text = schemaEditor.getDocument().getText();
final String newText = text.replaceAll("xsd","xs");
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
schemaEditor.getDocument().replaceString(0, text.length(), newText);
}
});
@@ -1433,7 +1421,8 @@
// 10
// 0123456789012
String text = "<html></html>";
- EditorHighlighter xhtmlHighlighter = HighlighterFactory.createHighlighter(StdFileTypes.XHTML,EditorColorsManager.getInstance().getGlobalScheme(),myProject);
+ EditorHighlighter xhtmlHighlighter = HighlighterFactory
+ .createHighlighter(StdFileTypes.XHTML, EditorColorsManager.getInstance().getGlobalScheme(), myProject);
xhtmlHighlighter.setText(text);
HighlighterIterator iterator = xhtmlHighlighter.createIterator(1);
assertSame("Xml tag name", iterator.getTokenType(), XmlTokenType.XML_TAG_NAME);
@@ -1578,9 +1567,7 @@
Collection<HighlightInfo> infos = filterInfos(doHighlighting());
assertEquals(2, infos.size());
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
- public void run() {
+ WriteCommandAction.runWriteCommandAction(null, new Runnable(){public void run() {
EditorModificationUtil.deleteSelectedText(myEditor);
}
});
@@ -1589,8 +1576,7 @@
assertEquals(11, infos.size());
- ApplicationManager.getApplication().runWriteAction(new Runnable() {
- @Override
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
public void run() {
EditorModificationUtil.insertStringAtCaret(myEditor, "<");
}
@@ -2028,6 +2014,14 @@
}, true, false);
}
+ public void testPrefixedSubstitution() throws Exception {
+ doTest(new VirtualFile[]{
+ getVirtualFile(BASE_PATH + "Substitute/prefixed.xml"),
+ getVirtualFile(BASE_PATH + "Substitute/schema-b.xsd"),
+ getVirtualFile(BASE_PATH + "Substitute/schema-a.xsd")
+ }, true, false);
+ }
+
public void testDtdWithXsd() throws Exception {
doTest(
new VirtualFile[] {
diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/FetchExternalResourcesFixTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/FetchExternalResourcesFixTest.java
index 63d2142..34093be 100644
--- a/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/FetchExternalResourcesFixTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/FetchExternalResourcesFixTest.java
@@ -14,7 +14,7 @@
* Time: 19:32:51
* To change this template use Options | File Templates.
*/
-public class FetchExternalResourcesFixTest extends LightQuickFixTestCase {
+public class FetchExternalResourcesFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/IgnoreExternalResourcesFixTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/IgnoreExternalResourcesFixTest.java
index 8fd0277..4561125 100644
--- a/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/IgnoreExternalResourcesFixTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/IgnoreExternalResourcesFixTest.java
@@ -6,7 +6,7 @@
import java.io.File;
-public class IgnoreExternalResourcesFixTest extends LightQuickFixTestCase {
+public class IgnoreExternalResourcesFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/ManuallySetupExternalResourcesFixTest.java b/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/ManuallySetupExternalResourcesFixTest.java
index 9a479ec..283fbc6 100644
--- a/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/ManuallySetupExternalResourcesFixTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/daemon/quickFix/ManuallySetupExternalResourcesFixTest.java
@@ -6,7 +6,7 @@
import java.io.File;
-public class ManuallySetupExternalResourcesFixTest extends LightQuickFixTestCase {
+public class ManuallySetupExternalResourcesFixTest extends LightQuickFixParameterizedTestCase {
public void test() throws Exception { doAllTests(); }
@Override
diff --git a/xml/tests/src/com/intellij/codeInsight/editorActions/HtmlSelectWordTest.java b/xml/tests/src/com/intellij/codeInsight/editorActions/HtmlSelectWordTest.java
index 76a0ffa..abbea07 100644
--- a/xml/tests/src/com/intellij/codeInsight/editorActions/HtmlSelectWordTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/editorActions/HtmlSelectWordTest.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.
@@ -35,22 +35,26 @@
@Override
public void setUp() throws Exception {
super.setUp();
- oldSelectWholeCssSelectorOptionValue = WebEditorOptions.getInstance().isSelectWholeCssSelectorSuffixOnDoubleClick();
+ oldSelectWholeCssSelectorOptionValue = WebEditorOptions.getInstance().isSelectWholeCssIdentifierOnDoubleClick();
}
@Override
public void tearDown() throws Exception {
- WebEditorOptions.getInstance().setSelectWholeCssSelectorSuffixOnDoubleClick(oldSelectWholeCssSelectorOptionValue);
+ WebEditorOptions.getInstance().setSelectWholeCssIdentifierOnDoubleClick(oldSelectWholeCssSelectorOptionValue);
super.tearDown();
}
public void testSelectClassNames() {
- WebEditorOptions.getInstance().setSelectWholeCssSelectorSuffixOnDoubleClick(true);
+ WebEditorOptions.getInstance().setSelectWholeCssIdentifierOnDoubleClick(true);
doTest();
}
public void testSelectClassNamesWithDisabledSelectSelectorOption() {
- WebEditorOptions.getInstance().setSelectWholeCssSelectorSuffixOnDoubleClick(false);
+ WebEditorOptions.getInstance().setSelectWholeCssIdentifierOnDoubleClick(false);
+ doTest();
+ }
+
+ public void testSelectTag() {
doTest();
}
diff --git a/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java b/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java
index e2621fa..3ae70e3 100644
--- a/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java
+++ b/xml/tests/src/com/intellij/codeInsight/editorActions/moveUpDown/XmlMoverTest.java
@@ -1,6 +1,22 @@
+/*
+ * 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.codeInsight.editorActions.moveUpDown;
import com.intellij.codeInsight.CodeInsightTestCase;
+import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.testFramework.PlatformTestUtil;
import org.jetbrains.annotations.NonNls;
@@ -55,7 +71,12 @@
final boolean enabled = handler.isEnabled(myEditor, null);
assertEquals("not enabled for " + afterFileName, new File(getTestDataPath(), afterFileName).exists(), enabled);
if (enabled) {
- handler.execute(myEditor, null);
+ WriteCommandAction.runWriteCommandAction(null, new Runnable() {
+ @Override
+ public void run() {
+ handler.execute(myEditor, null);
+ }
+ });
checkResultByFile(afterFileName);
}
}
diff --git a/xml/tests/src/com/intellij/html/HtmlDocumentationTest.java b/xml/tests/src/com/intellij/html/HtmlDocumentationTest.java
index 025159e..8a231ac 100644
--- a/xml/tests/src/com/intellij/html/HtmlDocumentationTest.java
+++ b/xml/tests/src/com/intellij/html/HtmlDocumentationTest.java
@@ -30,6 +30,15 @@
"</html>");
}
+ public void testQuickDocumentationHtml5TagDialog() throws Exception {
+ doTest("<!DOCTYPE html>\n" +
+ "<html>\n" +
+ "<body onload=\"\">\n" +
+ "<dia<caret>log></dialog\n" +
+ "</body>\n" +
+ "</html>");
+ }
+
public void testQuickDocumentationHtml5Attr() throws Exception {
doTest("<!DOCTYPE html>\n" +
"<html>\n" +
diff --git a/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java b/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java
index 256bb15..205c03f 100644
--- a/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java
+++ b/xml/tests/src/com/intellij/xml/actions/SplitTagActionTest.java
@@ -7,7 +7,6 @@
/**
* @author spleaner
*/
-@SuppressWarnings({"ALL"})
public class SplitTagActionTest extends LightIntentionActionTestCase {
public void test() throws Exception { doAllTests(); }
diff --git a/xml/tests/testData/completion/Substitute/testAfterPrefix.xml b/xml/tests/testData/completion/Substitute/testAfterPrefix.xml
new file mode 100644
index 0000000..fe3effd
--- /dev/null
+++ b/xml/tests/testData/completion/Substitute/testAfterPrefix.xml
@@ -0,0 +1,7 @@
+<root xmlns="http://test/a"
+ xmlns:b="http://test/b"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://test/b schema-b.xsd">
+
+ <b:in<caret>
+</root>
\ No newline at end of file
diff --git a/xml/tests/testData/completion/Substitute/testAfterPrefix_after.xml b/xml/tests/testData/completion/Substitute/testAfterPrefix_after.xml
new file mode 100644
index 0000000..b6231ad
--- /dev/null
+++ b/xml/tests/testData/completion/Substitute/testAfterPrefix_after.xml
@@ -0,0 +1,7 @@
+<root xmlns="http://test/a"
+ xmlns:b="http://test/b"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://test/b schema-b.xsd">
+
+ <b:instance id=""
+</root>
\ No newline at end of file
diff --git a/xml/tests/testData/selectWord/selectTag/after1.html b/xml/tests/testData/selectWord/selectTag/after1.html
new file mode 100644
index 0000000..0a07366
--- /dev/null
+++ b/xml/tests/testData/selectWord/selectTag/after1.html
@@ -0,0 +1,3 @@
+<html>
+<div>blablabla</<selection>div</selection>>
+</html>
\ No newline at end of file
diff --git a/xml/tests/testData/selectWord/selectTag/after2.html b/xml/tests/testData/selectWord/selectTag/after2.html
new file mode 100644
index 0000000..e3efecf
--- /dev/null
+++ b/xml/tests/testData/selectWord/selectTag/after2.html
@@ -0,0 +1,3 @@
+<html>
+<div>blablabla<selection></div></selection>
+</html>
\ No newline at end of file
diff --git a/xml/tests/testData/selectWord/selectTag/after3.html b/xml/tests/testData/selectWord/selectTag/after3.html
new file mode 100644
index 0000000..5d6cf32
--- /dev/null
+++ b/xml/tests/testData/selectWord/selectTag/after3.html
@@ -0,0 +1,3 @@
+<html>
+<selection><div>blablabla</div></selection>
+</html>
\ No newline at end of file
diff --git a/xml/tests/testData/selectWord/selectTag/after4.html b/xml/tests/testData/selectWord/selectTag/after4.html
new file mode 100644
index 0000000..a91a114
--- /dev/null
+++ b/xml/tests/testData/selectWord/selectTag/after4.html
@@ -0,0 +1,3 @@
+<html><selection>
+<div>blablabla</div>
+</selection></html>
\ No newline at end of file
diff --git a/xml/tests/testData/selectWord/selectTag/before.html b/xml/tests/testData/selectWord/selectTag/before.html
new file mode 100644
index 0000000..507f1a1
--- /dev/null
+++ b/xml/tests/testData/selectWord/selectTag/before.html
@@ -0,0 +1,3 @@
+<html>
+<div>blablabla</di<caret>v>
+</html>
\ No newline at end of file
diff --git a/xml/tests/testData/xml/Substitute/prefixed.xml b/xml/tests/testData/xml/Substitute/prefixed.xml
new file mode 100644
index 0000000..1853c67
--- /dev/null
+++ b/xml/tests/testData/xml/Substitute/prefixed.xml
@@ -0,0 +1,7 @@
+<a:root xmlns:a="http://test/a"
+ xmlns:b="http://test/b"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://test/b schema-b.xsd">
+
+ <b:instance id=""/>
+</a:root>
\ No newline at end of file
diff --git a/xml/xml-analysis-impl/src/com/intellij/application/options/editor/WebEditorOptions.java b/xml/xml-analysis-impl/src/com/intellij/application/options/editor/WebEditorOptions.java
index f3504e6..c658068 100644
--- a/xml/xml-analysis-impl/src/com/intellij/application/options/editor/WebEditorOptions.java
+++ b/xml/xml-analysis-impl/src/com/intellij/application/options/editor/WebEditorOptions.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,7 +39,7 @@
private boolean myBreadcrumbsEnabled = true;
private boolean myBreadcrumbsEnabledInXml = false;
private boolean myShowCssColorPreviewInGutter = true;
- private boolean mySelectWholeCssSelectorSuffixOnDoubleClick = true;
+ private boolean mySelectWholeCssIdentifierOnDoubleClick = true;
private boolean myShowCssInlineColorPreview = false;
private boolean myAutomaticallyInsertClosingTag = true;
private boolean myAutomaticallyInsertRequiredAttributes = true;
@@ -178,12 +178,12 @@
XmlSerializerUtil.copyBean(state, this);
}
- public boolean isSelectWholeCssSelectorSuffixOnDoubleClick() {
- return mySelectWholeCssSelectorSuffixOnDoubleClick;
+ public boolean isSelectWholeCssIdentifierOnDoubleClick() {
+ return mySelectWholeCssIdentifierOnDoubleClick;
}
- public void setSelectWholeCssSelectorSuffixOnDoubleClick(boolean selectWholeCssSelectorSuffixOnDoubleClick) {
- mySelectWholeCssSelectorSuffixOnDoubleClick = selectWholeCssSelectorSuffixOnDoubleClick;
+ public void setSelectWholeCssIdentifierOnDoubleClick(boolean selectWholeCssIdentifiersOnDoubleClick) {
+ mySelectWholeCssIdentifierOnDoubleClick = selectWholeCssIdentifiersOnDoubleClick;
}
public boolean isInsertQuotesForAttributeValue() {
diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java b/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java
index 40f85e1..2225b2b 100644
--- a/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.java
+++ b/xml/xml-analysis-impl/src/com/intellij/codeInsight/highlighting/HtmlClosingTagErrorFilter.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,6 +16,7 @@
package com.intellij.codeInsight.highlighting;
import com.intellij.codeInsight.daemon.XmlErrorMessages;
+import com.intellij.codeInsight.daemon.impl.analysis.XmlHighlightVisitor;
import com.intellij.lang.html.HTMLLanguage;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiErrorElement;
@@ -28,6 +29,9 @@
* @author spleaner
*/
public class HtmlClosingTagErrorFilter extends HighlightErrorFilter {
+ public HtmlClosingTagErrorFilter(XmlHighlightVisitor xmlHighlightVisitor) {
+ assert xmlHighlightVisitor != null;
+ }
@Override
public boolean shouldHighlightErrorElement(@NotNull final PsiErrorElement element) {
diff --git a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspectionBase.java b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspectionBase.java
index f26f558..2cc788d 100644
--- a/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspectionBase.java
+++ b/xml/xml-analysis-impl/src/com/intellij/codeInspection/htmlInspections/HtmlUnknownTagInspectionBase.java
@@ -24,6 +24,7 @@
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMExternalizableStringList;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.html.HtmlTag;
import com.intellij.psi.impl.source.html.dtd.HtmlElementDescriptorImpl;
@@ -73,13 +74,6 @@
return descriptor == null || descriptor instanceof AnyXmlElementDescriptor;
}
- // this hack is needed, because we temporarily ignore svg and mathML namespaces
- // todo: provide schemas for svg and mathML and remove this in IDEA XI
- private static boolean isInSpecialHtml5Namespace(XmlTag tag) {
- final String ns = tag.getNamespace();
- return HtmlUtil.SVG_NAMESPACE.equals(ns) || HtmlUtil.MATH_ML_NAMESPACE.endsWith(ns);
- }
-
@Override
@Nls
@NotNull
@@ -100,18 +94,7 @@
}
protected String createPropertiesString() {
- final StringBuffer buffer = new StringBuffer();
- for (final String property : myValues) {
- if (buffer.length() == 0) {
- buffer.append(property);
- }
- else {
- buffer.append(',');
- buffer.append(property);
- }
- }
-
- return buffer.toString();
+ return StringUtil.join(myValues, ",");
}
@Override
@@ -153,7 +136,7 @@
@Override
protected void checkTag(@NotNull final XmlTag tag, @NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
- if (!(tag instanceof HtmlTag) || !XmlHighlightVisitor.shouldBeValidated(tag) || isInSpecialHtml5Namespace(tag)) {
+ if (!(tag instanceof HtmlTag) || !XmlHighlightVisitor.shouldBeValidated(tag)) {
return;
}
diff --git a/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java b/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java
index 7ec5ab4..eb3eac5 100644
--- a/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java
+++ b/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckEmptyTagInspection.java
@@ -44,8 +44,7 @@
*/
public class CheckEmptyTagInspection extends XmlSuppressableInspectionTool {
private static final Logger LOG = Logger.getInstance("#com.intellij.xml.util.CheckEmptyTagInspection");
- @NonNls private static final String SCRIPT_TAG_NAME = "script";
- @NonNls private static final Set<String> ourTagsWithEmptyEndsNotAllowed = new THashSet<String>(Arrays.asList(SCRIPT_TAG_NAME, "div", "iframe"));
+ @NonNls private static final Set<String> ourTagsWithEmptyEndsNotAllowed = new THashSet<String>(Arrays.asList(HtmlUtil.SCRIPT_TAG_NAME, "div", "iframe"));
@Override
public boolean isEnabledByDefault() {
diff --git a/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspectionBase.java b/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspectionBase.java
index 427a022..bf80b8c 100644
--- a/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspectionBase.java
+++ b/xml/xml-analysis-impl/src/com/intellij/xml/util/CheckValidXmlInScriptBodyInspectionBase.java
@@ -41,8 +41,6 @@
protected static final String AMP_ENTITY_REFERENCE = "&";
@NonNls
protected static final String LT_ENTITY_REFERENCE = "<";
- @NonNls
- private static final String SCRIPT_TAG_NAME = "script";
private Lexer myXmlLexer;
@Override
@@ -57,8 +55,8 @@
@Override public void visitXmlTag(final XmlTag tag) {
if (HtmlUtil.isHtmlTag(tag)) return;
- if (SCRIPT_TAG_NAME.equals(tag.getName()) ||
- tag instanceof HtmlTag && SCRIPT_TAG_NAME.equalsIgnoreCase(tag.getName())) {
+ if (HtmlUtil.SCRIPT_TAG_NAME.equals(tag.getName()) ||
+ tag instanceof HtmlTag && HtmlUtil.SCRIPT_TAG_NAME.equalsIgnoreCase(tag.getName())) {
final PsiFile psiFile = tag.getContainingFile();
final FileType fileType = psiFile.getFileType();
@@ -115,7 +113,7 @@
}
protected LocalQuickFix createFix(PsiFile psiFile, PsiElement psiElement, int offsetInElement) {
- throw new UnsupportedOperationException();
+ return null;
}
@Override
diff --git a/xml/xml-psi-api/src/com/intellij/psi/filters/position/NamespaceFilter.java b/xml/xml-psi-api/src/com/intellij/psi/filters/position/NamespaceFilter.java
index 4b49c03..88aba07 100644
--- a/xml/xml-psi-api/src/com/intellij/psi/filters/position/NamespaceFilter.java
+++ b/xml/xml-psi-api/src/com/intellij/psi/filters/position/NamespaceFilter.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,11 +15,11 @@
*/
package com.intellij.psi.filters.position;
-import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
+import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.xml.*;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
import org.jetbrains.annotations.NonNls;
public class NamespaceFilter implements ElementFilter {
@@ -30,7 +30,7 @@
}
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(XmlTag.class, hintClass) || ReflectionCache.isAssignable(XmlDocument.class, hintClass);
+ return ReflectionUtil.isAssignable(XmlTag.class, hintClass) || ReflectionUtil.isAssignable(XmlDocument.class, hintClass);
}
public boolean isAcceptable(Object element, PsiElement context){
diff --git a/xml/xml-psi-api/src/com/intellij/xml/XmlBundle.java b/xml/xml-psi-api/src/com/intellij/xml/XmlBundle.java
index 5f5a732..7940a25 100644
--- a/xml/xml-psi-api/src/com/intellij/xml/XmlBundle.java
+++ b/xml/xml-psi-api/src/com/intellij/xml/XmlBundle.java
@@ -17,6 +17,7 @@
import com.intellij.CommonBundle;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.PropertyKey;
import java.lang.ref.Reference;
@@ -27,20 +28,19 @@
* @author lesya
*/
public class XmlBundle {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls public static final String PATH_TO_BUNDLE = "messages.XmlBundle";
private XmlBundle() {
}
- public static String message(@NonNls @PropertyKey(resourceBundle = PATH_TO_BUNDLE) String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(PATH_TO_BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/xml/xml-psi-impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java b/xml/xml-psi-impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java
index 77d0c1e..cdf58d1 100644
--- a/xml/xml-psi-impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java
+++ b/xml/xml-psi-impl/src/com/intellij/codeInsight/daemon/XmlErrorMessages.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -28,21 +28,19 @@
* @author max
*/
public class XmlErrorMessages {
- private static Reference<ResourceBundle> ourBundle;
+ public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) {
+ return CommonBundle.message(getBundle(), key, params);
+ }
+
+ private static Reference<ResourceBundle> ourBundle;
@NonNls private static final String BUNDLE = "messages.XmlErrorMessages";
private XmlErrorMessages() {
}
- @NotNull
- public static String message(@PropertyKey(resourceBundle = BUNDLE)String key, Object... params) {
- return CommonBundle.message(getBundle(), key, params);
- }
-
private static ResourceBundle getBundle() {
- ResourceBundle bundle = null;
- if (ourBundle != null) bundle = ourBundle.get();
+ ResourceBundle bundle = com.intellij.reference.SoftReference.dereference(ourBundle);
if (bundle == null) {
bundle = ResourceBundle.getBundle(BUNDLE);
ourBundle = new SoftReference<ResourceBundle>(bundle);
diff --git a/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XHtmlFileType.java b/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XHtmlFileType.java
index f8d96be..c6d84ea 100644
--- a/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XHtmlFileType.java
+++ b/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XHtmlFileType.java
@@ -51,4 +51,9 @@
public Icon getIcon() {
return AllIcons.FileTypes.Xhtml;
}
+
+ @Override
+ public boolean isCaseSensitive() {
+ return true;
+ }
}
diff --git a/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java b/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java
index be60b05..6addac1 100644
--- a/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java
+++ b/xml/xml-psi-impl/src/com/intellij/ide/highlighter/XmlLikeFileType.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -42,4 +42,8 @@
Charset charset = CharsetToolkit.forName(name);
return charset == null ? CharsetToolkit.UTF8_CHARSET : charset;
}
+
+ public boolean isCaseSensitive() {
+ return false;
+ }
}
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 b7bbc62..250d27e 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
@@ -248,11 +248,15 @@
if (isOptionalTagEnd) {
boolean foundMatch = childTerminatesParentInStack(childName, true);
if (foundMatch) {
- myTagMarkersStack.pop();
- myTagNamesStack.pop();
+ // allow only one promotion per tag, otherwise last row in table
+ // will make it up to the first one moving all tags in between under first node
+ if (!canTerminate(childName, tagName)) {
+ myTagMarkersStack.pop();
+ myTagNamesStack.pop();
- myTagMarkersStack.push(childMarker);
- myTagNamesStack.push(childName);
+ myTagMarkersStack.push(childMarker);
+ myTagNamesStack.push(childName);
+ }
tag.doneBefore(XmlElementType.HTML_TAG, childMarker);
return true;
@@ -378,24 +382,22 @@
}
private static boolean canTerminate(final String childTagName,final String tagName) {
- // TODO: make hash
- return !(tagName.equalsIgnoreCase(TR_TAG) && childTagName.equalsIgnoreCase(TD_TAG)) ||
- tagName.equalsIgnoreCase(TABLE_TAG) && childTagName.equalsIgnoreCase(TR_TAG);
+ return childTagName.equals(tagName) || HtmlUtil.canTerminate(childTagName, tagName);
}
private boolean childTerminatesParentInStack(final String childName, final boolean terminateOnNonOptionalTag) {
- boolean isTD = TD_TAG.equals(childName);
- boolean isTR = TR_TAG.equals(childName);
+ boolean isCell = TD_TAG.equals(childName) || "th".equals(childName);
+ boolean isRow = TR_TAG.equals(childName);
for (int i = myTagNamesStack.size() - 1; i >= 0; i--) {
String parentName = myTagNamesStack.get(i);
if (terminateOnNonOptionalTag && !HtmlUtil.isOptionalEndForHtmlTagL(parentName)) return false;
- if (isTD && (TR_TAG.equals(parentName) || TABLE_TAG.equals(parentName)) ||
- isTR && TABLE_TAG.equals(parentName)) {
+ if (isCell && (TR_TAG.equals(parentName) || TABLE_TAG.equals(parentName)) ||
+ isRow && TABLE_TAG.equals(parentName)) {
return false;
}
- if (childName.equals(parentName)) {
+ if (canTerminate(childName, parentName)) {
return true;
}
}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.java b/xml/xml-psi-impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.java
index f64fe8b..1c5e2ca 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/filters/position/TargetNamespaceFilter.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,7 +19,7 @@
import com.intellij.psi.filters.XmlTextFilter;
import com.intellij.psi.xml.XmlDocument;
import com.intellij.psi.xml.XmlTag;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -38,7 +38,7 @@
}
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(XmlTag.class, hintClass) || ReflectionCache.isAssignable(XmlDocument.class, hintClass);
+ return ReflectionUtil.isAssignable(XmlTag.class, hintClass) || ReflectionUtil.isAssignable(XmlDocument.class, hintClass);
}
public boolean isAcceptable(Object element, PsiElement context){
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.java b/xml/xml-psi-impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.java
index c323476..fca6f89 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/filters/position/XmlTokenTypeFilter.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,7 @@
import com.intellij.psi.filters.ElementFilter;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.xml.XmlToken;
-import com.intellij.util.ReflectionCache;
+import com.intellij.util.ReflectionUtil;
/**
* Created by IntelliJ IDEA.
@@ -39,7 +39,7 @@
}
public boolean isClassAcceptable(Class hintClass){
- return ReflectionCache.isAssignable(XmlToken.class, hintClass);
+ return ReflectionUtil.isAssignable(XmlToken.class, hintClass);
}
public boolean isAcceptable(Object element, PsiElement context){
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java
new file mode 100644
index 0000000..f0067fe
--- /dev/null
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/HtmlConditionalCommentInjector.java
@@ -0,0 +1,100 @@
+/*
+ * 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.psi.impl.source.html;
+
+import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
+import com.intellij.lang.injection.MultiHostInjector;
+import com.intellij.lang.injection.MultiHostRegistrar;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.TextRange;
+import com.intellij.psi.PsiComment;
+import com.intellij.psi.PsiElement;
+import com.intellij.psi.PsiLanguageInjectionHost;
+import com.intellij.psi.tree.TokenSet;
+import com.intellij.psi.xml.XmlComment;
+import com.intellij.psi.xml.XmlTokenType;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author spleaner
+ */
+public class HtmlConditionalCommentInjector implements MultiHostInjector {
+
+ /**
+ * Allows to check if given element is a
+ * <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>.
+ *
+ * @param host target element to check
+ * @return <code>true</code> if given element is conditional comment; <code>false</code> otherwise
+ */
+ public static boolean isConditionalComment(@NotNull PsiElement host) {
+ return parseConditionalCommentBoundaries(host) != null;
+ }
+
+ /**
+ * Tries to parse given element as <a href="http://msdn.microsoft.com/en-us/library/ms537512(v=vs.85).aspx">conditional comment</a>.
+ *
+ * @param host target element to parse
+ * @return <code>null</code> if given element is not a conditional comment;
+ * pair like <code>(conditional comment start element; conditional comment end element)</code> otherwise
+ */
+ @Nullable
+ private static Pair<ASTNode, ASTNode> parseConditionalCommentBoundaries(@NotNull PsiElement host) {
+ if (!(host instanceof XmlComment)) {
+ return null;
+ }
+ final ASTNode comment = host.getNode();
+ if (comment == null) {
+ return null;
+ }
+ final ASTNode conditionalStart = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_START_END));
+ if (conditionalStart == null) {
+ return null;
+ }
+ final ASTNode conditionalEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END_START));
+ if (conditionalEnd == null) {
+ return null;
+ }
+ final ASTNode endOfEnd = comment.findChildByType(TokenSet.create(XmlTokenType.XML_CONDITIONAL_COMMENT_END));
+ return endOfEnd == null ? null : new Pair<ASTNode, ASTNode>(conditionalStart, conditionalEnd);
+ }
+
+ public void getLanguagesToInject(@NotNull final MultiHostRegistrar registrar, @NotNull final PsiElement host) {
+ Pair<ASTNode, ASTNode> pair = parseConditionalCommentBoundaries(host);
+ if (pair == null) {
+ return;
+ }
+ final TextRange textRange = host.getTextRange();
+ final int startOffset = textRange.getStartOffset();
+ Language language = host.getParent().getLanguage();
+ ASTNode conditionalStart = pair.first;
+ ASTNode conditionalEnd = pair.second;
+ TextRange range = new TextRange(conditionalStart.getTextRange().getEndOffset() - startOffset, conditionalEnd.getStartOffset() - startOffset);
+ if (range.getStartOffset() < range.getEndOffset()) {
+ registrar.startInjecting(language).addPlace(null, null, (PsiLanguageInjectionHost)host, range).doneInjecting();
+ }
+ }
+
+ @NotNull
+ public List<? extends Class<? extends PsiElement>> elementsToInjectIn() {
+ return Arrays.asList(PsiComment.class);
+ }
+}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java
index 2abbb5b..ce5fe4e 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/ScriptSupportUtil.java
@@ -28,8 +28,8 @@
import com.intellij.psi.xml.*;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.util.HtmlPsiUtil;
+import com.intellij.xml.util.HtmlUtil;
import com.intellij.xml.util.XmlPsiUtil;
-import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -41,7 +41,6 @@
public class ScriptSupportUtil {
private static final Key<CachedValue<XmlTag[]>> CachedScriptTagsKey = Key.create("script tags");
private static final ThreadLocal<String> ProcessingDeclarationsFlag = new ThreadLocal<String>();
- @NonNls private static final String SCRIPT_TAG = "script";
private ScriptSupportUtil() {
}
@@ -66,13 +65,14 @@
if (document != null) {
PsiElementProcessor psiElementProcessor = new PsiElementProcessor() {
+ @Override
public boolean execute(@NotNull final PsiElement element) {
if (element instanceof XmlTag) {
final XmlTag tag = (XmlTag)element;
- if (SCRIPT_TAG.equalsIgnoreCase(tag.getName())) {
+ if (HtmlUtil.SCRIPT_TAG_NAME.equalsIgnoreCase(tag.getName())) {
final XmlElementDescriptor descriptor = tag.getDescriptor();
- if (descriptor != null && SCRIPT_TAG.equals(descriptor.getName())) {
+ if (descriptor != null && HtmlUtil.SCRIPT_TAG_NAME.equals(descriptor.getName())) {
scriptTags.add(tag);
}
}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java
index 2dd7767..bd9085a 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/html/dtd/HtmlElementDescriptorImpl.java
@@ -23,6 +23,7 @@
import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.impl.dtd.BaseXmlElementDescriptorImpl;
import com.intellij.xml.impl.schema.XmlNSDescriptorImpl;
+import com.intellij.xml.util.HtmlUtil;
import com.intellij.xml.util.XmlUtil;
import java.util.HashMap;
@@ -110,6 +111,9 @@
}
}
}
+ if (descriptor == null && HtmlUtil.isHtml5Context(context)) {
+ descriptor = myDelegate.getAttributeDescriptor(attributeName, context);
+ }
return descriptor;
}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java
index 02f336a..8c5889d 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/parsing/xml/XmlParser.java
@@ -21,6 +21,7 @@
import com.intellij.lang.*;
import com.intellij.lang.impl.PsiBuilderImpl;
+import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
@@ -51,7 +52,7 @@
if (children[2].getTokenType() != XmlTokenType.XML_TAG_END) return ThreeState.UNSURE;
LighterASTTokenNode name = (LighterASTTokenNode)children[1];
CharSequence newName = name.getText();
- if (!oldName.equals(newName)) return ThreeState.NO;
+ if (!Comparing.equal(oldName, newName)) return ThreeState.NO;
}
return ThreeState.UNSURE;
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
index 23cb9db..450ae10 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/providers/SchemaReferencesProvider.java
@@ -117,7 +117,7 @@
}
public TextRange getRangeInElement() {
- return new TextRange(1,myElement.getTextLength()-1);
+ return ElementManipulators.getValueTextRange(myElement);
}
@Nullable
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/TagNameVariantCollector.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/TagNameVariantCollector.java
index 9ff2f8a..b9840d6 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/TagNameVariantCollector.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/TagNameVariantCollector.java
@@ -44,7 +44,7 @@
@Nullable List<String> nsInfo) {
XmlElementDescriptor elementDescriptor = null;
- String elementNamespace = null;
+ String elementNamespace = element.getNamespacePrefix().isEmpty() ? null : element.getNamespace();
final Map<String, XmlElementDescriptor> descriptorsMap = new HashMap<String, XmlElementDescriptor>();
PsiElement context = element.getParent();
@@ -62,7 +62,9 @@
descriptorsMap.put(namespace, descriptor);
if(elementDescriptor == null) {
elementDescriptor = descriptor;
- elementNamespace = namespace;
+ if (elementNamespace == null) {
+ elementNamespace = namespace;
+ }
}
}
}
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java
index e48926c..8dfb5d8 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeImpl.java
@@ -315,9 +315,7 @@
@NotNull
public PsiReference[] getReferences() {
- final PsiElement parentElement = getParent();
- if (!(parentElement instanceof XmlTag)) return PsiReference.EMPTY_ARRAY;
- final PsiReference[] referencesFromProviders = ReferenceProvidersRegistry.getReferencesFromProviders(this, XmlAttribute.class);
+ final PsiReference[] referencesFromProviders = ReferenceProvidersRegistry.getReferencesFromProviders(this);
if (referencesFromProviders == null) return new PsiReference[]{new XmlAttributeReference(this)};
PsiReference[] refs;
if (isNamespaceDeclaration()) {
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java
index 6ca97dd..b3b29ce 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlAttributeReference.java
@@ -98,7 +98,7 @@
@NotNull
public Object[] getVariants() {
- return ArrayUtil.EMPTY_OBJECT_ARRAY; // moved to XmlCompletionContributor.addAttributeReferenceCompletionVariants()
+ return ArrayUtil.EMPTY_OBJECT_ARRAY; // moved to XmlAttributeReferenceCompletionProvider
}
public boolean isSoft() {
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityCache.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityCache.java
index b361463..8f91c22 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityCache.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlEntityCache.java
@@ -1,6 +1,7 @@
package com.intellij.psi.impl.source.xml;
import com.intellij.openapi.util.Key;
+import com.intellij.openapi.util.ModificationTracker;
import com.intellij.psi.*;
import com.intellij.psi.util.CachedValue;
import com.intellij.psi.util.CachedValueProvider;
@@ -27,7 +28,7 @@
if (declElement instanceof XmlEntityDecl && declElement.isValid() && name.equals(((XmlEntityDecl)declElement).getName()))
return new Result<XmlEntityDecl>((XmlEntityDecl)declElement, declElement);
cachingMap.put(name,null);
- return new Result<XmlEntityDecl>(null,null);
+ return new Result<XmlEntityDecl>(null, ModificationTracker.NEVER_CHANGED);
}
},
false
diff --git a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java
index d177362..c640e27 100644
--- a/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/psi/impl/source/xml/XmlTextImpl.java
@@ -174,20 +174,18 @@
doSetValue(s, getPolicy());
}
- public void doSetValue(final String s, XmlPsiPolicy policy) throws IncorrectOperationException {
- final ASTNode firstEncodedElement = policy.encodeXmlTextContents(s, this);
-
- if (firstEncodedElement == null) {
- delete();
- return;
- }
-
+ public void doSetValue(final String s, final XmlPsiPolicy policy) throws IncorrectOperationException {
final PomModel model = PomManager.getModel(getProject());
final XmlAspect aspect = model.getModelAspect(XmlAspect.class);
model.runTransaction(new PomTransactionBase(this, aspect) {
public PomModelEvent runInner() {
final String oldText = getText();
- replaceAllChildrenToChildrenOf(firstEncodedElement.getTreeParent());
+ final ASTNode firstEncodedElement = policy.encodeXmlTextContents(s, XmlTextImpl.this);
+ if (firstEncodedElement == null) {
+ delete();
+ } else {
+ replaceAllChildrenToChildrenOf(firstEncodedElement.getTreeParent());
+ }
clearCaches();
return XmlTextChangedImpl.createXmlTextChanged(model, XmlTextImpl.this, oldText);
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java
index ba7f346..debb58a 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/ExternalDocumentValidator.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2009 JetBrains s.r.o.
+ * 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.
@@ -104,8 +104,7 @@
file != null &&
myModificationStamp == file.getModificationStamp() &&
!ValidateXmlActionHandler.isValidationDependentFilesOutOfDate((XmlFile)file) &&
- myInfos!=null &&
- myInfos.get()!=null // we have validated before
+ SoftReference.dereference(myInfos)!=null // we have validated before
) {
addAllInfos(host,myInfos.get());
return;
@@ -375,7 +374,7 @@
if (!profile.isToolEnabled(HighlightDisplayKey.find(INSPECTION_SHORT_NAME), containingFile)) return;
SoftReference<ExternalDocumentValidator> validatorReference = project.getUserData(validatorInstanceKey);
- ExternalDocumentValidator validator = validatorReference != null? validatorReference.get() : null;
+ ExternalDocumentValidator validator = SoftReference.dereference(validatorReference);
if(validator == null) {
validator = new ExternalDocumentValidator();
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
index 84fba9a..c8179cc 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlAttributeDescriptorImpl.java
@@ -161,4 +161,9 @@
public void setName(String name) throws IncorrectOperationException {
NamedObjectDescriptor.setName(myTag, name);
}
+
+ @Override
+ public String toString() {
+ return getName();
+ }
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
index 3d3cab7..b5f3461 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/impl/schema/XmlElementDescriptorImpl.java
@@ -256,7 +256,7 @@
XmlNSDescriptor descriptor = ((XmlTag)context).getNSDescriptor(namespace, false);
if (descriptor instanceof XmlNSDescriptorImpl && ((XmlNSDescriptorImpl)descriptor).hasSubstitutions()) {
for (XmlElementDescriptor element : elements) {
- String name = element.getName(context);
+ String name = XmlUtil.getLocalName(element.getName(context)).toString();
String s = ((XmlNSDescriptorImpl)element.getNSDescriptor()).getDefaultNamespace();
XmlElementDescriptor[] substitutes = ((XmlNSDescriptorImpl)descriptor).getSubstitutes(name, s);
result.addAll(Arrays.asList(substitutes));
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/ColorMap.java b/xml/xml-psi-impl/src/com/intellij/xml/util/ColorMap.java
new file mode 100644
index 0000000..cb35298
--- /dev/null
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/ColorMap.java
@@ -0,0 +1,316 @@
+/*
+ * 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.xml.util;
+
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.ui.ColorUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class ColorMap {
+ private static final Map<String, String> ourColorNameToHexCodeMap = new HashMap<String, String>(25);
+ private static final Map<String, String> ourHexCodeToColorNameMap = new HashMap<String, String>(25);
+
+ @NonNls static final String systemColorsString = "ActiveBorder\n" +
+ " Active window border.\n" +
+ "ActiveCaption\n" +
+ " Active window caption.\n" +
+ "AppWorkspace\n" +
+ " Background color of multiple document interface.\n" +
+ "Background\n" +
+ " Desktop background.\n" +
+ "ButtonFace\n" +
+ " Face color for three-dimensional display elements.\n" +
+ "ButtonHighlight\n" +
+ " Highlight color for three-dimensional display elements (for edges facing away from the light source).\n" +
+ "ButtonShadow\n" +
+ " Shadow color for three-dimensional display elements.\n" +
+ "ButtonText\n" +
+ " Text on push buttons.\n" +
+ "CaptionText\n" +
+ " Text in caption, size box, and scrollbar arrow box.\n" +
+ "GrayText\n" +
+ " Grayed (disabled) text. This color is set to #000 if the current display driver does not support a solid gray color.\n" +
+ "Highlight\n" +
+ " Item(s) selected in a control.\n" +
+ "HighlightText\n" +
+ " Text of item(s) selected in a control.\n" +
+ "InactiveBorder\n" +
+ " Inactive window border.\n" +
+ "InactiveCaption\n" +
+ " Inactive window caption.\n" +
+ "InactiveCaptionText\n" +
+ " Color of text in an inactive caption.\n" +
+ "InfoBackground\n" +
+ " Background color for tooltip controls.\n" +
+ "InfoText\n" +
+ " Text color for tooltip controls.\n" +
+ "Menu\n" +
+ " Menu background.\n" +
+ "MenuText\n" +
+ " Text in menus.\n" +
+ "Scrollbar\n" +
+ " Scroll bar gray area.\n" +
+ "ThreeDDarkShadow\n" +
+ " Dark shadow for three-dimensional display elements.\n" +
+ "ThreeDFace\n" +
+ " Face color for three-dimensional display elements.\n" +
+ "ThreeDHighlight\n" +
+ " Highlight color for three-dimensional display elements.\n" +
+ "ThreeDLightShadow\n" +
+ " Light color for three-dimensional display elements (for edges facing the light source).\n" +
+ "ThreeDShadow\n" +
+ " Dark shadow for three-dimensional display elements.\n" +
+ "Window\n" +
+ " Window background.\n" +
+ "WindowFrame\n" +
+ " Window frame.\n" +
+ "WindowText\n" +
+ " Text in windows. ";
+ @NonNls static final String standardColorsString = "maroon #800000 red #ff0000 orange #ffA500 yellow #ffff00 olive #808000\n" +
+ "purple #800080 fuchsia #ff00ff white #ffffff lime #00ff00 green #008000\n" +
+ "navy #000080 blue #0000ff aqua #00ffff teal #008080\n" +
+ "black #000000 silver #c0c0c0 gray #808080";
+ @NonNls static final String colorsString = "aliceblue \t#f0f8ff \t240,248,255\n" +
+ " \t \tantiquewhite \t#faebd7 \t250,235,215\n" +
+ " \t \taqua \t#00ffff \t0,255,255\n" +
+ " \t \taquamarine \t#7fffd4 \t127,255,212\n" +
+ " \t \tazure \t#f0ffff \t240,255,255\n" +
+ " \t \tbeige \t#f5f5dc \t245,245,220\n" +
+ " \t \tbisque \t#ffe4c4 \t255,228,196\n" +
+ " \t \tblack \t#000000 \t0,0,0\n" +
+ " \t \tblanchedalmond \t#ffebcd \t255,235,205\n" +
+ " \t \tblue \t#0000ff \t0,0,255\n" +
+ " \t \tblueviolet \t#8a2be2 \t138,43,226\n" +
+ " \t \tbrown \t#a52a2a \t165,42,42\n" +
+ " \t \tburlywood \t#deb887 \t222,184,135\n" +
+ " \t \tcadetblue \t#5f9ea0 \t95,158,160\n" +
+ " \t \tchartreuse \t#7fff00 \t127,255,0\n" +
+ " \t \tchocolate \t#d2691e \t210,105,30\n" +
+ " \t \tcoral \t#ff7f50 \t255,127,80\n" +
+ " \t \tcornflowerblue \t#6495ed \t100,149,237\n" +
+ " \t \tcornsilk \t#fff8dc \t255,248,220\n" +
+ " \t \tcrimson \t#dc143c \t220,20,60\n" +
+ " \t \tcyan \t#00ffff \t0,255,255\n" +
+ " \t \tdarkblue \t#00008b \t0,0,139\n" +
+ " \t \tdarkcyan \t#008b8b \t0,139,139\n" +
+ " \t \tdarkgoldenrod \t#b8860b \t184,134,11\n" +
+ " \t \tdarkgray \t#a9a9a9 \t169,169,169\n" +
+ " \t \tdarkgrey \t#a9a9a9 \t169,169,169\n" +
+ " \t \tdarkgreen \t#006400 \t0,100,0\n" +
+ " \t \tdarkkhaki \t#bdb76b \t189,183,107\n" +
+ " \t \tdarkmagenta \t#8b008b \t139,0,139\n" +
+ " \t \tdarkolivegreen \t#556b2f \t85,107,47\n" +
+ " \t \tdarkorange \t#ff8c00 \t255,140,0\n" +
+ " \t \tdarkorchid \t#9932cc \t153,50,204\n" +
+ " \t \tdarkred \t#8b0000 \t139,0,0\n" +
+ " \t \tdarksalmon \t#e9967a \t233,150,122\n" +
+ " \t \tdarkseagreen \t#8fbc8f \t143,188,143\n" +
+ " \t \tdarkslateblue \t#483d8b \t72,61,139\n" +
+ " \t \tdarkslategray \t#2f4f4f \t47,79,79\n" +
+ " \t \tdarkslategrey \t#2f4f4f \t47,79,79\n" +
+ " \t \tdarkturquoise \t#00ced1 \t0,206,209\n" +
+ " \t \tdarkviolet \t#9400d3 \t148,0,211\n" +
+ " \t \tdeeppink \t#ff1493 \t255,20,147\n" +
+ " \t \tdeepskyblue \t#00bfff \t0,191,255\n" +
+ " \t \tdimgray \t#696969 \t105,105,105\n" +
+ " \t \tdimgrey \t#696969 \t105,105,105\n" +
+ " \t \tdodgerblue \t#1e90ff \t30,144,255\n" +
+ " \t \tfirebrick \t#b22222 \t178,34,34\n" +
+ " \t \tfloralwhite \t#fffaf0 \t255,250,240\n" +
+ " \t \tforestgreen \t#228b22 \t34,139,34\n" +
+ " \t \tfuchsia \t#ff00ff \t255,0,255\n" +
+ " \t \tgainsboro \t#dcdcdc \t220,220,220\n" +
+ " \t \tghostwhite \t#f8f8ff \t248,248,255\n" +
+ " \t \tgold \t#ffd700 \t255,215,0\n" +
+ " \t \tgoldenrod \t#daa520 \t218,165,32\n" +
+ " \t \tgray \t#808080 \t128,128,128\n" +
+ " \t \tgrey \t#808080 \t128,128,128\n" +
+ " \t \tgreen \t#008000 \t0,128,0\n" +
+ " \t \tgreenyellow \t#adff2f \t173,255,47\n" +
+ " \t \thoneydew \t#f0fff0 \t240,255,240\n" +
+ " \t \thotpink \t#ff69b4 \t255,105,180\n" +
+ " \t \tindianred \t#cd5c5c \t205,92,92\n" +
+ " \t \tindigo \t#4b0082 \t75,0,130\n" +
+ " \t \tivory \t#fffff0 \t255,255,240\n" +
+ " \t \tkhaki \t#f0e68c \t240,230,140\n" +
+ " \t \tlavender \t#e6e6fa \t230,230,250\n" +
+ " \t \tlavenderblush \t#fff0f5 \t255,240,245\n" +
+ " \t \tlawngreen \t#7cfc00 \t124,252,0\n" +
+ " \t \tlemonchiffon \t#fffacd \t255,250,205\n" +
+ " \t \tlightblue \t#add8e6 \t173,216,230\n" +
+ " \t \tlightcoral \t#f08080 \t240,128,128\n" +
+ " \t \tlightcyan \t#e0ffff \t224,255,255\n" +
+ " \t \tlightgoldenrodyellow \t#fafad2 \t250,250,210\n" +
+ " \t \tlightgray \t#d3d3d3 \t211,211,211\n" +
+ " \t \tlightgrey \t#d3d3d3 \t211,211,211\n" +
+ " \t \tlightgreen \t#90ee90 \t144,238,144\n" +
+ " \t \tlightpink \t#ffb6c1 \t255,182,193\n" +
+ " \t \tlightsalmon \t#ffa07a \t255,160,122\n" +
+ " \t \tlightseagreen \t#20b2aa \t32,178,170\n" +
+ " \t \tlightskyblue \t#87cefa \t135,206,250\n" +
+ " \t \tlightslategray \t#778899 \t119,136,153\n" +
+ " \t \tlightslategrey \t#778899 \t119,136,153\n" +
+ " \t \tlightsteelblue \t#b0c4de \t176,196,222\n" +
+ " \t \tlightyellow \t#ffffe0 \t255,255,224\n" +
+ " \t \tlime \t#00ff00 \t0,255,0\n" +
+ " \t \tlimegreen \t#32cd32 \t50,205,50\n" +
+ " \t \tlinen \t#faf0e6 \t250,240,230\n" +
+ " \t \tmagenta \t#ff00ff \t255,0,255\n" +
+ " \t \tmaroon \t#800000 \t128,0,0\n" +
+ " \t \tmediumaquamarine \t#66cdaa \t102,205,170\n" +
+ " \t \tmediumblue \t#0000cd \t0,0,205\n" +
+ " \t \tmediumorchid \t#ba55d3 \t186,85,211\n" +
+ " \t \tmediumpurple \t#9370db \t147,112,219\n" +
+ " \t \tmediumseagreen \t#3cb371 \t60,179,113\n" +
+ " \t \tmediumslateblue \t#7b68ee \t123,104,238\n" +
+ " \t \tmediumspringgreen \t#00fa9a \t0,250,154\n" +
+ " \t \tmediumturquoise \t#48d1cc \t72,209,204\n" +
+ " \t \tmediumvioletred \t#c71585 \t199,21,133\n" +
+ " \t \tmidnightblue \t#191970 \t25,25,112\n" +
+ " \t \tmintcream \t#f5fffa \t245,255,250\n" +
+ " \t \tmistyrose \t#ffe4e1 \t255,228,225\n" +
+ " \t \tmoccasin \t#ffe4b5 \t255,228,181\n" +
+ " \t \tnavajowhite \t#ffdead \t255,222,173\n" +
+ " \t \tnavy \t#000080 \t0,0,128\n" +
+ " \t \toldlace \t#fdf5e6 \t253,245,230\n" +
+ " \t \tolive \t#808000 \t128,128,0\n" +
+ " \t \tolivedrab \t#6b8e23 \t107,142,35\n" +
+ " \t \torange \t#ffa500 \t255,165,0\n" +
+ " \t \torangered \t#ff4500 \t255,69,0\n" +
+ " \t \torchid \t#da70d6 \t218,112,214\n" +
+ " \t \tpalegoldenrod \t#eee8aa \t238,232,170\n" +
+ " \t \tpalegreen \t#98fb98 \t152,251,152\n" +
+ " \t \tpaleturquoise \t#afeeee \t175,238,238\n" +
+ " \t \tpalevioletred \t#db7093 \t219,112,147\n" +
+ " \t \tpapayawhip \t#ffefd5 \t255,239,213\n" +
+ " \t \tpeachpuff \t#ffdab9 \t255,218,185\n" +
+ " \t \tperu \t#cd853f \t205,133,63\n" +
+ " \t \tpink \t#ffc0cb \t255,192,203\n" +
+ " \t \tplum \t#dda0dd \t221,160,221\n" +
+ " \t \tpowderblue \t#b0e0e6 \t176,224,230\n" +
+ " \t \tpurple \t#800080 \t128,0,128\n" +
+ " \t \tred \t#ff0000 \t255,0,0\n" +
+ " \t \trosybrown \t#bc8f8f \t188,143,143\n" +
+ " \t \troyalblue \t#4169e1 \t65,105,225\n" +
+ " \t \tsaddlebrown \t#8b4513 \t139,69,19\n" +
+ " \t \tsalmon \t#fa8072 \t250,128,114\n" +
+ " \t \tsandybrown \t#f4a460 \t244,164,96\n" +
+ " \t \tseagreen \t#2e8b57 \t46,139,87\n" +
+ " \t \tseashell \t#fff5ee \t255,245,238\n" +
+ " \t \tsienna \t#a0522d \t160,82,45\n" +
+ " \t \tsilver \t#c0c0c0 \t192,192,192\n" +
+ " \t \tskyblue \t#87ceeb \t135,206,235\n" +
+ " \t \tslateblue \t#6a5acd \t106,90,205\n" +
+ " \t \tslategray \t#708090 \t112,128,144\n" +
+ " \t \tslategrey \t#708090 \t112,128,144\n" +
+ " \t \tsnow \t#fffafa \t255,250,250\n" +
+ " \t \tspringgreen \t#00ff7f \t0,255,127\n" +
+ " \t \tsteelblue \t#4682b4 \t70,130,180\n" +
+ " \t \ttan \t#d2b48c \t210,180,140\n" +
+ " \t \tteal \t#008080 \t0,128,128\n" +
+ " \t \tthistle \t#d8bfd8 \t216,191,216\n" +
+ " \t \ttomato \t#ff6347 \t255,99,71\n" +
+ " \t \tturquoise \t#40e0d0 \t64,224,208\n" +
+ " \t \tviolet \t#ee82ee \t238,130,238\n" +
+ " \t \twheat \t#f5deb3 \t245,222,179\n" +
+ " \t \twhite \t#ffffff \t255,255,255\n" +
+ " \t \twhitesmoke \t#f5f5f5 \t245,245,245\n" +
+ " \t \tyellow \t#ffff00 \t255,255,0\n" +
+ " \t \tyellowgreen \t#9acd32 \t154,205,50";
+ private static final ArrayList<String> ourSystemColors;
+ private static final List<String> ourStandardColors;
+
+ static {
+ ourSystemColors = new ArrayList<String>();
+ StringTokenizer tokenizer = new StringTokenizer(systemColorsString, "\n");
+
+ while (tokenizer.hasMoreTokens()) {
+ String name = tokenizer.nextToken();
+ ourSystemColors.add(name.toLowerCase());
+ tokenizer.nextToken();
+ }
+
+ ourStandardColors = new ArrayList<String>();
+ tokenizer = new StringTokenizer(standardColorsString, ", \n");
+
+ while (tokenizer.hasMoreTokens()) {
+ String name = tokenizer.nextToken();
+ ourStandardColors.add(name);
+ tokenizer.nextToken();
+ }
+
+ getColors();
+ }
+
+ public static synchronized void getColors() {
+ StringTokenizer tokenizer = new StringTokenizer(standardColorsString, ", \n");
+ HashMap<String, String> standardColors = new HashMap<String, String>();
+
+ while (tokenizer.hasMoreTokens()) {
+ String name = tokenizer.nextToken();
+ String value = tokenizer.nextToken();
+ standardColors.put(name, name);
+ ourColorNameToHexCodeMap.put(name, value);
+ ourHexCodeToColorNameMap.put(value, name);
+ }
+
+ tokenizer = new StringTokenizer(colorsString, " \t\n");
+
+ while (tokenizer.hasMoreTokens()) {
+ String name = tokenizer.nextToken();
+ String hexValue = tokenizer.nextToken();
+
+ tokenizer.nextToken(); // skip rgb
+
+ if (!standardColors.containsKey(name)) {
+ ourColorNameToHexCodeMap.put(name, hexValue);
+ ourHexCodeToColorNameMap.put(hexValue, name);
+ }
+ }
+ }
+
+ public static boolean isSystemColorName(@NotNull @NonNls final String s) {
+ return ourSystemColors.contains(s);
+ }
+
+ public static boolean isStandardColor(@NotNull @NonNls final String s) {
+ return ourStandardColors.contains(s);
+ }
+
+ public static synchronized String getHexCodeForColorName(String colorName) {
+ return ourColorNameToHexCodeMap.get(colorName);
+ }
+
+ public static synchronized String getColorNameForHexCode(String hexString) {
+ return ourHexCodeToColorNameMap.get(hexString);
+ }
+
+ public static Color getColor(String text) {
+ if (StringUtil.isEmptyOrSpaces(text)) {
+ return null;
+ }
+ String hexValue = text.charAt(0) == '#' ? text : getHexCodeForColorName(text.toLowerCase());
+ if (hexValue != null) {
+ return ColorUtil.fromHex(hexValue, null);
+ }
+ return null;
+ }
+}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.java b/xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.java
new file mode 100644
index 0000000..9651de7
--- /dev/null
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HTMLControls.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.intellij.xml.util;
+
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.JDOMUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.CharsetToolkit;
+import com.intellij.util.io.UnsyncByteArrayInputStream;
+import com.intellij.util.xmlb.Converter;
+import com.intellij.util.xmlb.XmlSerializer;
+import com.intellij.util.xmlb.annotations.Attribute;
+import com.intellij.util.xmlb.annotations.Tag;
+import gnu.trove.THashSet;
+import org.jdom.Document;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author Dennis.Ushakov
+ */
+public class HTMLControls {
+ private static Logger LOG = Logger.getInstance(HTMLControls.class);
+ private static Control[] ourControls;
+
+ public static Control[] getControls() {
+ if (ourControls == null) {
+ ourControls = loadControls();
+ }
+ return ourControls;
+ }
+
+ @SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
+ private static Control[] loadControls() {
+ Document document;
+ try {
+ // use temporary bytes stream because otherwise inputStreamSkippingBOM will fail
+ // on ZipFileInputStream used in jar files
+ final InputStream stream = HTMLControls.class.getResourceAsStream("HtmlControls.xml");
+ final byte[] bytes = FileUtilRt.loadBytes(stream);
+ stream.close();
+ final UnsyncByteArrayInputStream bytesStream = new UnsyncByteArrayInputStream(bytes);
+ document = JDOMUtil.loadDocument(CharsetToolkit.inputStreamSkippingBOM(bytesStream));
+ bytesStream.close();
+ } catch (Exception e) {
+ LOG.error(e);
+ return new Control[0];
+ }
+ if (!document.getRootElement().getName().equals("htmlControls")) {
+ LOG.error("HTMLControls storage is broken");
+ return new Control[0];
+ }
+ return XmlSerializer.deserialize(document, Control[].class);
+ }
+
+ public enum TagState { REQUIRED, OPTIONAL, FORBIDDEN }
+
+ @Tag("control")
+ public static class Control {
+ @Attribute("name")
+ public String name;
+ @Attribute(value = "startTag", converter = TagStateConverter.class)
+ public TagState startTag;
+ @Attribute(value = "endTag", converter = TagStateConverter.class)
+ public TagState endTag;
+ @Attribute("emptyAllowed")
+ public boolean emptyAllowed;
+ @Attribute(value = "autoClosedBy", converter = AutoCloseConverter.class)
+ public Set<String> autoClosedBy = Collections.emptySet();
+ }
+
+ private static class TagStateConverter extends Converter<TagState> {
+ @Nullable
+ @Override
+ public TagState fromString(@NotNull String value) {
+ return TagState.valueOf(value.toUpperCase());
+ }
+
+ @NotNull
+ @Override
+ public String toString(@NotNull TagState state) {
+ return state.name().toLowerCase();
+ }
+ }
+
+ private static class AutoCloseConverter extends Converter<Set<String>> {
+ @Nullable
+ @Override
+ public Set<String> fromString(@NotNull String value) {
+ final THashSet<String> result = new THashSet<String>();
+ for (String closingTag : StringUtil.split(value, ",")) {
+ result.add(closingTag.trim());
+ }
+ return result;
+ }
+
+ @NotNull
+ @Override
+ public String toString(@NotNull Set<String> o) {
+ return StringUtil.join(o, ", ");
+ }
+ }
+}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml
new file mode 100644
index 0000000..4dc5149
--- /dev/null
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlControls.xml
@@ -0,0 +1,160 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<htmlControls namespace="System.Web.UI.HtmlControls">
+ <control name="A" type="HtmlAnchor" startTag="required" endTag="Required" emptyAllowed="false">
+ <attribute name="href" type="%URL" />
+ </control>
+ <control name="Acronym" type="HtmlGenericControl" startTag="required" endTag="Required" emptyAllowed="false"/>
+ <control name="address" type="HtmlGenericControl" startTag="required" endTag="Required" emptyAllowed="false"/>
+ <control name="applet" type="HtmlGenericControl" startTag="required" endTag="Required" emptyAllowed="false">
+ <attribute name="codetype" type="%URL" />
+ </control>
+ <control name="area" type="HtmlGenericControl" startTag="required" endTag="Forbidden" emptyAllowed="true">
+ <attribute name="href" type="%URL" />
+ </control>
+
+ <control name="B" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="base" type="HtmlGenericControl" startTag="required" endTag="Forbidden" emptyAllowed="true">
+ <attribute name="codetype" type="%URL" />
+ </control>
+ <control name="baseFont" type="HtmlGenericControl" startTag="required" endTag="Forbidden" emptyAllowed="true"/>
+ <control name="bdo" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="big" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="blockQuote" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="cite" type="%URL" />
+ </control>
+ <control name="body" type="HtmlGenericControl" startTag="optional" endTag="optional" emptyAllowed="false" onlyOnce="true" />
+ <control name="br" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+ <control name="button" type="HtmlButton" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="Caption" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="center" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="cite" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="code" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="col" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+ <control name="colGroup" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="colGroup"/>
+
+ <control name="DD" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="dt, dd"/>
+ <control name="del" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="cite" type="%URL" />
+ </control>
+ <control name="dfn" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="dir" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="div" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="dl" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="dt" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="dt, dd"/>
+
+ <control name="EM" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="embed" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="true" />
+ <control name="FieldSet" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="font" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="form" type="HtmlForm" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="action" type="%URL" />
+ </control>
+ <control name="frame" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true">
+ <attribute name="src" type="%URL" />
+ </control>
+ <control name="frameSet" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="H1" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="H2" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="H3" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="H4" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="H5" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="H6" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="head" type="HtmlHead" startTag="optional" endTag="optional" emptyAllowed="false" onlyOnce="true" autoClosedBy="body">
+ <attribute name="profile" type="%URL" />
+ </control>
+ <control name="hr" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+ <control name="html" type="HtmlGenericControl" startTag="optional" endTag="optional" emptyAllowed="false" onlyOnce="true" />
+
+ <control name="I" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="IFrame" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="src" type="%URL" />
+ </control>
+ <control name="img" type="HtmlImage" startTag="required" endTag="forbidden" emptyAllowed="true">
+ <attribute name="src" type="%URL" />
+ <attribute name="usemap" type="%URL" />
+ </control>
+ <control name="input" startTag="required" endTag="forbidden" emptyAllowed="true">
+ <type name="HtmlInputButton" typeAttribute="BUTTON|SUBMIT|RESET" />
+ <type name="HtmlInputCheckBox" typeAttribute="CheckBox" />
+ <type name="HtmlInputFile" typeAttribute="file" />
+ <type name="HtmlInputHidden" typeAttribute="hidden" />
+ <type name="HtmlInputImage" typeAttribute="image" />
+ <type name="HtmlInputRadioButton" typeAttribute="radio" />
+ <type name="HtmlInputText" typeAttribute="TEXT|PASSWORD" />
+ </control>
+ <control name="ins" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="cite" type="%URL" />
+ </control>
+ <control name="isIndex" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+
+ <control name="KBD" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="Label" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="legend" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="li" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="li"/>
+ <control name="link" type="HtmlLink" startTag="required" endTag="forbidden" emptyAllowed="true">
+ <attribute name="href" type="%URL" />
+ </control>
+
+ <control name="Map" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="menu" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="meta" type="HtmlMeta" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+
+ <control name="noembed" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="true"/>
+ <control name="NoFrames" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="noScript" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="nobr" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="Object" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="classid" type="%URL" />
+ <attribute name="codebase" type="%URL" />
+ <attribute name="data" type="%URL" />
+ <attribute name="name" type="%URL" />
+ <attribute name="usemap" type="%URL" />
+ </control>
+ <control name="ol" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="option" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="option"/>
+
+ <control name="P" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="p"/>
+ <control name="param" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+ <control name="pre" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="Q" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false">
+ <attribute name="cite" type="%URL" />
+ </control>
+
+ <control name="S" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="samp" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="script" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="select" type="HtmlSelect" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="small" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="source" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true">
+ <attribute name="src" type="%URL" />
+ </control>
+ <control name="span" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="strike" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="strong" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="style" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="sub" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="sup" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="Table" type="HtmlTable" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="tbody" type="HtmlGenericControl" startTag="optional" endTag="optional" emptyAllowed="false" autoClosedBy="tfoot, thead, tbody"/>
+ <control name="td" type="HtmlTableCell" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="td, th"/>
+ <control name="textArea" type="HtmlTextArea" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="tfoot" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="tfoot, thead, tbody"/>
+ <control name="th" type="HtmlTableCell" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="td, th"/>
+ <control name="thead" type="HtmlGenericControl" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="tfoot, thead, tbody"/>
+ <control name="title" type="HtmlTitle" startTag="required" endTag="required" emptyAllowed="false" onlyOnce="true" />
+ <control name="tr" type="HtmlTableRow" startTag="required" endTag="optional" emptyAllowed="false" autoClosedBy="tr"/>
+ <control name="track" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true" />
+ <control name="tt" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="U" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="UL" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+
+ <control name="VAR" type="HtmlGenericControl" startTag="required" endTag="required" emptyAllowed="false"/>
+ <control name="wbr" type="HtmlGenericControl" startTag="required" endTag="forbidden" emptyAllowed="true"/>
+</htmlControls>
\ No newline at end of file
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java
index be744f3..ec466c0 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/HtmlUtil.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.
@@ -46,9 +46,11 @@
import com.intellij.xml.Html5SchemaProvider;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
+import com.intellij.xml.XmlNSDescriptor;
import com.intellij.xml.impl.schema.XmlAttributeDescriptorImpl;
import com.intellij.xml.impl.schema.XmlElementDescriptorImpl;
import com.intellij.xml.util.documentation.HtmlDescriptorsTable;
+import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -56,6 +58,7 @@
import java.nio.charset.Charset;
import java.util.List;
+import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
@@ -70,6 +73,8 @@
@NonNls private static final String CHARSET_PREFIX = CHARSET+"=";
@NonNls private static final String HTML5_DATA_ATTR_PREFIX = "data-";
+ public static final String SCRIPT_TAG_NAME = "script";
+
public static final String[] CONTENT_TYPES =
{"application/activemessage", "application/andrew-inset", "application/applefile", "application/atomicmail", "application/dca-rft",
"application/dec-dx", "application/mac-binhex40"
@@ -102,9 +107,6 @@
private HtmlUtil() {
}
- @NonNls private static final String[] EMPTY_TAGS = {
- "base", "hr", "meta", "link", "frame", "br", "basefont", "param", "img", "area", "input", "isindex", "col", /*html 5*/ "source", "wbr"
- };
private static final Set<String> EMPTY_TAGS_MAP = new THashSet<String>();
@NonNls private static final String[] OPTIONAL_END_TAGS = {
//"html",
@@ -146,9 +148,14 @@
"main"
};
private static final Set<String> HTML5_TAGS_SET = new THashSet<String>();
+ private static final Map<String, Set<String>> AUTO_CLOSE_BY_MAP = new THashMap<String, Set<String>>();
static {
- ContainerUtil.addAll(EMPTY_TAGS_MAP, EMPTY_TAGS);
+ for (HTMLControls.Control control : HTMLControls.getControls()) {
+ final String tagName = control.name.toLowerCase();
+ if (control.endTag == HTMLControls.TagState.FORBIDDEN) EMPTY_TAGS_MAP.add(tagName);
+ AUTO_CLOSE_BY_MAP.put(tagName, new THashSet<String>(control.autoClosedBy));
+ }
ContainerUtil.addAll(EMPTY_ATTRS_MAP, EMPTY_ATTRS);
ContainerUtil.addAll(OPTIONAL_END_TAGS_MAP, OPTIONAL_END_TAGS);
ContainerUtil.addAll(BLOCK_TAGS_MAP, BLOCK_TAGS);
@@ -173,6 +180,11 @@
return OPTIONAL_END_TAGS_MAP.contains(tagName);
}
+ public static boolean canTerminate(final String childTagName, final String tagName) {
+ final Set<String> closingTags = AUTO_CLOSE_BY_MAP.get(tagName);
+ return closingTags != null && closingTags.contains(childTagName);
+ }
+
public static boolean isSingleHtmlAttribute(String attrName) {
return EMPTY_ATTRS_MAP.contains(attrName.toLowerCase());
}
@@ -221,6 +233,13 @@
}
}
}
+ } else if (parent instanceof HtmlDocumentImpl) {
+ final XmlNSDescriptor nsDescriptor = descriptor.getNSDescriptor();
+ for (XmlElementDescriptor elementDescriptor : nsDescriptor.getRootElementsDescriptors((XmlDocument)parent)) {
+ if (isHtmlBlockTag(elementDescriptor.getName()) && !variants.contains(elementDescriptor)) {
+ variants.add(elementDescriptor);
+ }
+ }
}
}
}
@@ -262,7 +281,7 @@
return descriptors;
}
- public static XmlElementDescriptor[] getCustomTagDescriptors(XmlElement context) {
+ public static XmlElementDescriptor[] getCustomTagDescriptors(@Nullable PsiElement context) {
String entitiesString = getEntitiesString(context, XmlEntitiesInspection.TAG_SHORT_NAME);
if (entitiesString == null) return XmlElementDescriptor.EMPTY_ARRAY;
@@ -296,7 +315,7 @@
}
@Nullable
- public static String getEntitiesString(XmlElement context, String inspectionName) {
+ public static String getEntitiesString(@Nullable PsiElement context, @NotNull String inspectionName) {
if (context == null) return null;
PsiFile containingFile = context.getContainingFile().getOriginalFile();
@@ -488,7 +507,7 @@
public void endTag(final CharSequence localName, final String namespace, final int startoffset, final int endoffset) {
@NonNls final String name = localName.toString().toLowerCase();
if ("meta".equals(name) && (metHttpEquiv || metHttml5Charset) && contentAttributeValue != null) {
- String charsetName = null;
+ String charsetName;
if (metHttpEquiv) {
int start = contentAttributeValue.indexOf(CHARSET_PREFIX);
if (start == -1) return;
@@ -606,4 +625,8 @@
}
return false;
}
+
+ public static boolean isScriptTag(@Nullable XmlTag tag) {
+ return tag != null && tag.getLocalName().equalsIgnoreCase(SCRIPT_TAG_NAME);
+ }
}
diff --git a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
index 712cf20..bfbc4a7 100644
--- a/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
+++ b/xml/xml-psi-impl/src/com/intellij/xml/util/XmlUtil.java
@@ -376,7 +376,7 @@
return XSLT_URI.equals(ns) || XINCLUDE_URI.equals(ns);
}
- public static char getCharFromEntityRef(@NonNls String text) {
+ public static char getCharFromEntityRef(@NonNls @NotNull String text) {
try {
if (text.charAt(1) != '#') {
text = text.substring(1, text.length() - 1);